diff options
author | Ben Murdoch <benm@google.com> | 2013-08-12 14:20:17 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2013-08-12 14:20:17 +0100 |
commit | ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16 (patch) | |
tree | aa3b1013e823cb7bdee9ece936928292f57b31f4 /android_webview/browser | |
parent | f7fa989080f1e63c6a8aa24d5434922d52d9f51e (diff) | |
download | chromium_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.h | 7 | ||||
-rw-r--r-- | android_webview/browser/in_process_view_renderer.cc | 245 | ||||
-rw-r--r-- | android_webview/browser/in_process_view_renderer.h | 22 |
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. |