summaryrefslogtreecommitdiff
path: root/android_webview/browser
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2013-08-12 14:20:17 +0100
committerBen Murdoch <benm@google.com>2013-08-12 14:20:17 +0100
commitba5b9a6411cb1792fd21f0a078d7a25cd1ceec16 (patch)
treeaa3b1013e823cb7bdee9ece936928292f57b31f4 /android_webview/browser
parentf7fa989080f1e63c6a8aa24d5434922d52d9f51e (diff)
downloadchromium_org-ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16.tar.gz
Merge from Chromium at DEPS revision r216972
This commit was generated by merge_to_master.py. Change-Id: I01cb28d94e3fcf99e3624d75cafa50d929787ddd
Diffstat (limited to 'android_webview/browser')
-rw-r--r--android_webview/browser/browser_view_renderer.h7
-rw-r--r--android_webview/browser/in_process_view_renderer.cc245
-rw-r--r--android_webview/browser/in_process_view_renderer.h22
3 files changed, 158 insertions, 116 deletions
diff --git a/android_webview/browser/browser_view_renderer.h b/android_webview/browser/browser_view_renderer.h
index 9e02959387..78beb17e2f 100644
--- a/android_webview/browser/browser_view_renderer.h
+++ b/android_webview/browser/browser_view_renderer.h
@@ -6,10 +6,12 @@
#define ANDROID_WEBVIEW_BROWSER_BROWSER_VIEW_RENDERER_H_
#include "base/android/scoped_java_ref.h"
+#include "skia/ext/refptr.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/vector2d_f.h"
+class SkPicture;
struct AwDrawGLInfo;
struct AwDrawSWFunctionTable;
@@ -84,7 +86,6 @@ class BrowserViewRenderer {
// Global hookup methods.
static void SetAwDrawSWFunctionTable(AwDrawSWFunctionTable* table);
static AwDrawSWFunctionTable* GetAwDrawSWFunctionTable();
- static bool IsSkiaVersionCompatible();
// Rendering methods.
@@ -108,9 +109,7 @@ class BrowserViewRenderer {
virtual void SetGlobalVisibleRect(const gfx::Rect& visible_rect) = 0;
// CapturePicture API methods.
- virtual base::android::ScopedJavaLocalRef<jobject> CapturePicture(
- int width,
- int height) = 0;
+ virtual skia::RefPtr<SkPicture> CapturePicture(int width, int height) = 0;
virtual void EnableOnNewPicture(bool enabled) = 0;
// View update notifications.
diff --git a/android_webview/browser/in_process_view_renderer.cc b/android_webview/browser/in_process_view_renderer.cc
index 3e256804a4..39614d38ce 100644
--- a/android_webview/browser/in_process_view_renderer.cc
+++ b/android_webview/browser/in_process_view_renderer.cc
@@ -22,7 +22,6 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "gpu/command_buffer/service/in_process_command_buffer.h"
-#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkDevice.h"
@@ -64,13 +63,11 @@ class UserData : public content::WebContents::Data {
InProcessViewRenderer* instance_;
};
-typedef base::Callback<bool(SkCanvas*)> RenderMethod;
-
bool RasterizeIntoBitmap(JNIEnv* env,
const JavaRef<jobject>& jbitmap,
int scroll_x,
int scroll_y,
- const RenderMethod& renderer) {
+ const InProcessViewRenderer::RenderMethod& renderer) {
DCHECK(jbitmap.obj());
AndroidBitmapInfo bitmap_info;
@@ -113,6 +110,26 @@ bool RenderPictureToCanvas(SkPicture* picture, SkCanvas* canvas) {
return true;
}
+class ScopedPixelAccess {
+ public:
+ ScopedPixelAccess(JNIEnv* env, jobject java_canvas) {
+ AwDrawSWFunctionTable* sw_functions =
+ BrowserViewRenderer::GetAwDrawSWFunctionTable();
+ pixels_ = sw_functions ?
+ sw_functions->access_pixels(env, java_canvas) : NULL;
+ }
+ ~ScopedPixelAccess() {
+ if (pixels_)
+ BrowserViewRenderer::GetAwDrawSWFunctionTable()->release_pixels(pixels_);
+ }
+ AwPixelInfo* pixels() { return pixels_; }
+
+ private:
+ AwPixelInfo* pixels_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedPixelAccess);
+};
+
bool HardwareEnabled() {
static bool g_hw_enabled = !CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableWebViewGLMode);
@@ -123,13 +140,6 @@ bool HardwareEnabled() {
// Allows preventing extra copies of data when rendering.
AwDrawSWFunctionTable* g_sw_draw_functions = NULL;
-// Tells if the Skia library versions in Android and Chromium are compatible.
-// If they are then it's possible to pass Skia objects like SkPictures to the
-// Android glue layer via the SW rendering functions.
-// If they are not, then additional copies and rasterizations are required
-// as a fallback mechanism, which will have an important performance impact.
-bool g_is_skia_version_compatible = false;
-
const int64 kFallbackTickTimeoutInMilliseconds = 20;
class ScopedAllowGL {
@@ -180,11 +190,6 @@ static void ScheduleGpuWork() {
void BrowserViewRenderer::SetAwDrawSWFunctionTable(
AwDrawSWFunctionTable* table) {
g_sw_draw_functions = table;
- g_is_skia_version_compatible =
- g_sw_draw_functions->is_skia_version_compatible(&SkGraphics::GetVersion);
- LOG_IF(WARNING, !g_is_skia_version_compatible)
- << "Skia versions are not compatible, rendering performance will suffer.";
-
gpu::InProcessCommandBuffer::SetScheduleCallback(
base::Bind(&ScheduleGpuWork));
}
@@ -194,12 +199,6 @@ AwDrawSWFunctionTable* BrowserViewRenderer::GetAwDrawSWFunctionTable() {
return g_sw_draw_functions;
}
-// static
-bool BrowserViewRenderer::IsSkiaVersionCompatible() {
- DCHECK(g_sw_draw_functions);
- return g_is_skia_version_compatible;
-}
-
InProcessViewRenderer::InProcessViewRenderer(
BrowserViewRenderer::Client* client,
JavaHelper* java_helper,
@@ -213,6 +212,7 @@ InProcessViewRenderer::InProcessViewRenderer(
page_scale_factor_(1.0),
on_new_picture_enable_(false),
compositor_needs_continuous_invalidate_(false),
+ need_fast_invalidate_(false),
block_invalidates_(false),
width_(0),
height_(0),
@@ -305,7 +305,6 @@ bool InProcessViewRenderer::InitializeHwDraw() {
void InProcessViewRenderer::DrawGL(AwDrawGLInfo* draw_info) {
TRACE_EVENT0("android_webview", "InProcessViewRenderer::DrawGL");
- DCHECK(visible_);
manager_key_ = g_view_renderer_manager.Get().DidDrawGL(manager_key_, this);
@@ -330,8 +329,19 @@ void InProcessViewRenderer::DrawGL(AwDrawGLInfo* draw_info) {
}
}
- if (draw_info->mode == AwDrawGLInfo::kModeProcess)
+ if (draw_info->mode == AwDrawGLInfo::kModeProcess) {
+ TRACE_EVENT_INSTANT0(
+ "android_webview", "EarlyOut_ModeProcess", TRACE_EVENT_SCOPE_THREAD);
return;
+ }
+
+ UpdateCachedGlobalVisibleRect();
+ if (cached_global_visible_rect_.IsEmpty()) {
+ TRACE_EVENT_INSTANT0("android_webview",
+ "EarlyOut_EmptyVisibleRect",
+ TRACE_EVENT_SCOPE_THREAD);
+ return;
+ }
// DrawGL may be called without OnDraw, so cancel |fallback_tick_| here as
// well just to be safe.
@@ -361,6 +371,15 @@ void InProcessViewRenderer::DrawGL(AwDrawGLInfo* draw_info) {
draw_info->clip_top,
draw_info->clip_right - draw_info->clip_left,
draw_info->clip_bottom - draw_info->clip_top);
+
+ // Assume we always draw the full visible rect if we are drawing into a layer.
+ bool drew_full_visible_rect = true;
+
+ if (!draw_info->is_layer) {
+ clip_rect.Intersect(cached_global_visible_rect_);
+ drew_full_visible_rect = clip_rect.Contains(cached_global_visible_rect_);
+ }
+
block_invalidates_ = true;
// TODO(joth): Check return value.
compositor_->DemandDrawHw(gfx::Size(draw_info->width, draw_info->height),
@@ -370,8 +389,6 @@ void InProcessViewRenderer::DrawGL(AwDrawGLInfo* draw_info) {
block_invalidates_ = false;
gl_surface_->ResetBackingFrameBufferObject();
- UpdateCachedGlobalVisibleRect();
- bool drew_full_visible_rect = clip_rect.Contains(cached_global_visible_rect_);
EnsureContinuousInvalidation(draw_info, !drew_full_visible_rect);
}
@@ -382,7 +399,6 @@ void InProcessViewRenderer::SetGlobalVisibleRect(
bool InProcessViewRenderer::DrawSWInternal(jobject java_canvas,
const gfx::Rect& clip) {
- TRACE_EVENT0("android_webview", "InProcessViewRenderer::DrawSW");
fallback_tick_.Cancel();
if (clip.IsEmpty()) {
@@ -397,17 +413,57 @@ bool InProcessViewRenderer::DrawSWInternal(jobject java_canvas,
return false;
}
+ return RenderViaAuxilaryBitmapIfNeeded(
+ java_canvas,
+ java_helper_,
+ scroll_at_start_of_frame_,
+ clip,
+ base::Bind(&InProcessViewRenderer::CompositeSW,
+ base::Unretained(this)),
+ web_contents_);
+}
+
+// static
+bool InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded(
+ jobject java_canvas,
+ BrowserViewRenderer::JavaHelper* java_helper,
+ const gfx::Vector2d& scroll_correction,
+ const gfx::Rect& clip,
+ InProcessViewRenderer::RenderMethod render_source,
+ void* owner_key) {
+ TRACE_EVENT0("android_webview",
+ "InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded");
+
JNIEnv* env = AttachCurrentThread();
+ ScopedPixelAccess auto_release_pixels(env, java_canvas);
+ AwPixelInfo* pixels = auto_release_pixels.pixels();
+ SkMatrix matrix;
+ SkBitmap::Config config(SkBitmap::kNo_Config);
+ if (pixels) {
+ switch (pixels->config) {
+ case AwConfig_ARGB_8888:
+ config = SkBitmap::kARGB_8888_Config;
+ break;
+ case AwConfig_RGB_565:
+ config = SkBitmap::kRGB_565_Config;
+ break;
+ }
- AwDrawSWFunctionTable* sw_functions = GetAwDrawSWFunctionTable();
- AwPixelInfo* pixels = sw_functions ?
- sw_functions->access_pixels(env, java_canvas) : NULL;
- // Render into an auxiliary bitmap if pixel info is not available.
- ScopedJavaLocalRef<jobject> jcanvas(env, java_canvas);
- if (pixels == NULL) {
+ for (int i = 0; i < 9; i++) {
+ matrix.set(i, pixels->matrix[i]);
+ }
+ // Workaround for http://crbug.com/271096: SW draw only supports
+ // translate & scale transforms.
+ if (matrix.getType() & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask))
+ config = SkBitmap::kNo_Config;
+ }
+
+ if (config == SkBitmap::kNo_Config) {
+ // Render into an auxiliary bitmap if pixel info is not available.
+ ScopedJavaLocalRef<jobject> jcanvas(env, java_canvas);
TRACE_EVENT0("android_webview", "RenderToAuxBitmap");
- ScopedJavaLocalRef<jobject> jbitmap(java_helper_->CreateBitmap(
- env, clip.width(), clip.height(), jcanvas, web_contents_));
+ ScopedJavaLocalRef<jobject> jbitmap(java_helper->CreateBitmap(
+ env, clip.width(), clip.height(), jcanvas, owner_key));
if (!jbitmap.obj()) {
TRACE_EVENT_INSTANT0("android_webview",
"EarlyOut_BitmapAllocFail",
@@ -416,68 +472,57 @@ bool InProcessViewRenderer::DrawSWInternal(jobject java_canvas,
}
if (!RasterizeIntoBitmap(env, jbitmap,
- clip.x() - scroll_at_start_of_frame_.x(),
- clip.y() - scroll_at_start_of_frame_.y(),
- base::Bind(&InProcessViewRenderer::CompositeSW,
- base::Unretained(this)))) {
+ clip.x() - scroll_correction.x(),
+ clip.y() - scroll_correction.y(),
+ render_source)) {
TRACE_EVENT_INSTANT0("android_webview",
"EarlyOut_RasterizeFail",
TRACE_EVENT_SCOPE_THREAD);
return false;
}
- java_helper_->DrawBitmapIntoCanvas(env, jbitmap, jcanvas,
- clip.x(), clip.y());
+ java_helper->DrawBitmapIntoCanvas(env, jbitmap, jcanvas,
+ clip.x(), clip.y());
return true;
}
// Draw in a SkCanvas built over the pixel information.
- bool succeeded = false;
- {
- SkBitmap bitmap;
- bitmap.setConfig(static_cast<SkBitmap::Config>(pixels->config),
- pixels->width,
- pixels->height,
- pixels->row_bytes);
- bitmap.setPixels(pixels->pixels);
- SkDevice device(bitmap);
- SkCanvas canvas(&device);
- SkMatrix matrix;
- for (int i = 0; i < 9; i++)
- matrix.set(i, pixels->matrix[i]);
- canvas.setMatrix(matrix);
-
- if (pixels->clip_region_size) {
- SkRegion clip_region;
- size_t bytes_read = clip_region.readFromMemory(pixels->clip_region);
- DCHECK_EQ(pixels->clip_region_size, bytes_read);
- canvas.setClipRegion(clip_region);
- } else {
- canvas.clipRect(gfx::RectToSkRect(clip));
+ SkBitmap bitmap;
+ bitmap.setConfig(config,
+ pixels->width,
+ pixels->height,
+ pixels->row_bytes);
+ bitmap.setPixels(pixels->pixels);
+ SkDevice device(bitmap);
+ SkCanvas canvas(&device);
+ canvas.setMatrix(matrix);
+
+ if (pixels->clip_rect_count) {
+ SkRegion clip;
+ for (int i = 0; i < pixels->clip_rect_count; ++i) {
+ clip.op(SkIRect::MakeXYWH(pixels->clip_rects[i + 0],
+ pixels->clip_rects[i + 1],
+ pixels->clip_rects[i + 2],
+ pixels->clip_rects[i + 3]),
+ SkRegion::kUnion_Op);
}
- canvas.translate(scroll_at_start_of_frame_.x(),
- scroll_at_start_of_frame_.y());
-
- succeeded = CompositeSW(&canvas);
+ canvas.setClipRegion(clip);
}
- sw_functions->release_pixels(pixels);
- return succeeded;
+ canvas.translate(scroll_correction.x(),
+ scroll_correction.y());
+
+ return render_source.Run(&canvas);
}
-base::android::ScopedJavaLocalRef<jobject>
-InProcessViewRenderer::CapturePicture(int width, int height) {
- if (!compositor_ || !GetAwDrawSWFunctionTable()) {
- TRACE_EVENT_INSTANT0(
- "android_webview", "EarlyOut_CapturePicture", TRACE_EVENT_SCOPE_THREAD);
- return ScopedJavaLocalRef<jobject>();
- }
+skia::RefPtr<SkPicture> InProcessViewRenderer::CapturePicture(int width,
+ int height) {
+ TRACE_EVENT0("android_webview", "InProcessViewRenderer::CapturePicture");
// Return empty Picture objects for empty SkPictures.
- JNIEnv* env = AttachCurrentThread();
+ skia::RefPtr<SkPicture> picture = skia::AdoptRef(new SkPicture);
if (width <= 0 || height <= 0) {
- return java_helper_->RecordBitmapIntoPicture(env,
- ScopedJavaLocalRef<jobject>());
+ return picture;
}
// Reset scroll back to the origin, will go back to the old
@@ -485,36 +530,11 @@ InProcessViewRenderer::CapturePicture(int width, int height) {
base::AutoReset<gfx::Vector2dF> scroll_reset(&scroll_offset_css_,
gfx::Vector2d());
- skia::RefPtr<SkPicture> picture = skia::AdoptRef(new SkPicture);
SkCanvas* rec_canvas = picture->beginRecording(width, height, 0);
- if (!CompositeSW(rec_canvas))
- return ScopedJavaLocalRef<jobject>();
+ if (compositor_)
+ CompositeSW(rec_canvas);
picture->endRecording();
-
- if (IsSkiaVersionCompatible()) {
- // Add a reference that the create_picture() will take ownership of.
- picture->ref();
- return ScopedJavaLocalRef<jobject>(env,
- GetAwDrawSWFunctionTable()->create_picture(env, picture.get()));
- }
-
- // If Skia versions are not compatible, workaround it by rasterizing the
- // picture into a bitmap and drawing it into a new Java picture. Pass null
- // for |canvas| as we don't have java canvas at this point (and it would be
- // software anyway).
- ScopedJavaLocalRef<jobject> jbitmap(java_helper_->CreateBitmap(
- env, picture->width(), picture->height(), ScopedJavaLocalRef<jobject>(),
- NULL));
- if (!jbitmap.obj())
- return ScopedJavaLocalRef<jobject>();
-
- if (!RasterizeIntoBitmap(env, jbitmap, 0, 0,
- base::Bind(&RenderPictureToCanvas,
- base::Unretained(picture.get())))) {
- return ScopedJavaLocalRef<jobject>();
- }
-
- return java_helper_->RecordBitmapIntoPicture(env, jbitmap);
+ return picture;
}
void InProcessViewRenderer::EnableOnNewPicture(bool enabled) {
@@ -620,6 +640,7 @@ void InProcessViewRenderer::SetContinuousInvalidate(bool invalidate) {
"invalidate",
invalidate);
compositor_needs_continuous_invalidate_ = invalidate;
+ need_fast_invalidate_ = compositor_needs_continuous_invalidate_;
EnsureContinuousInvalidation(NULL, false);
}
@@ -726,11 +747,17 @@ void InProcessViewRenderer::EnsureContinuousInvalidation(
// ticked. This can happen if this is reached because
// invalidate_ignore_compositor is true.
if (compositor_needs_continuous_invalidate_) {
+ int64 delay_in_ms = kFallbackTickTimeoutInMilliseconds;
+ if (need_fast_invalidate_) {
+ TRACE_EVENT_INSTANT0(
+ "android_webview", "FastFallbackTick", TRACE_EVENT_SCOPE_THREAD);
+ delay_in_ms = 0;
+ need_fast_invalidate_ = false;
+ }
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
fallback_tick_.callback(),
- base::TimeDelta::FromMilliseconds(
- kFallbackTickTimeoutInMilliseconds));
+ base::TimeDelta::FromMilliseconds(delay_in_ms));
}
}
}
diff --git a/android_webview/browser/in_process_view_renderer.h b/android_webview/browser/in_process_view_renderer.h
index 8bb2c60e7d..e86796fb30 100644
--- a/android_webview/browser/in_process_view_renderer.h
+++ b/android_webview/browser/in_process_view_renderer.h
@@ -38,6 +38,16 @@ class InProcessViewRenderer : public BrowserViewRenderer,
static InProcessViewRenderer* FromWebContents(
content::WebContents* contents);
+ // TODO(joth): consider extracting this to its own utility class.
+ typedef base::Callback<bool(SkCanvas*)> RenderMethod;
+ static bool RenderViaAuxilaryBitmapIfNeeded(
+ jobject java_canvas,
+ JavaHelper* java_helper,
+ const gfx::Vector2d& scroll_correction,
+ const gfx::Rect& clip,
+ RenderMethod render_source,
+ void* owner_key);
+
// BrowserViewRenderer overrides
virtual bool OnDraw(jobject java_canvas,
bool is_hardware_canvas,
@@ -45,9 +55,8 @@ class InProcessViewRenderer : public BrowserViewRenderer,
const gfx::Rect& clip) OVERRIDE;
virtual void DrawGL(AwDrawGLInfo* draw_info) OVERRIDE;
virtual void SetGlobalVisibleRect(const gfx::Rect& visible_rect) OVERRIDE;
- virtual base::android::ScopedJavaLocalRef<jobject> CapturePicture(
- int width,
- int height) OVERRIDE;
+ virtual skia::RefPtr<SkPicture> CapturePicture(int width,
+ int height) OVERRIDE;
virtual void EnableOnNewPicture(bool enabled) OVERRIDE;
virtual void OnVisibilityChanged(bool visible) OVERRIDE;
virtual void OnSizeChanged(int width, int height) OVERRIDE;
@@ -117,6 +126,13 @@ class InProcessViewRenderer : public BrowserViewRenderer,
// states.
bool compositor_needs_continuous_invalidate_;
+ // If this is true, then the fallback tick is posted with zero delay. This
+ // is to reduce the time in cases when blink main thread is blocked waiting.
+ // This is set when |compositor_needs_continuous_invalidate_| is set.
+ // Eventually, this should correspond to BeginFrame when BeginFrame and
+ // BeginFrameDeadline are separate functions.
+ bool need_fast_invalidate_;
+
// Used to block additional invalidates while one is already pending or before
// compositor draw which may switch continuous_invalidate on and off in the
// process.