Chromium Code Reviews| Index: android_webview/browser/browser_view_renderer_impl.cc |
| diff --git a/android_webview/browser/browser_view_renderer_impl.cc b/android_webview/browser/browser_view_renderer_impl.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..833e07cf7cee4c732ab0bab385a3b677b9b06373 |
| --- /dev/null |
| +++ b/android_webview/browser/browser_view_renderer_impl.cc |
| @@ -0,0 +1,573 @@ |
| +// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "android_webview/browser/browser_view_renderer_impl.h" |
| + |
| +#include <android/bitmap.h> |
| +#include <sys/system_properties.h> |
| + |
| +#include "android_webview/common/renderer_picture_map.h" |
| +#include "android_webview/public/browser/draw_gl.h" |
| +#include "android_webview/public/browser/draw_sw.h" |
| +#include "base/android/jni_android.h" |
| +#include "base/debug/trace_event.h" |
| +#include "base/logging.h" |
| +#include "cc/layer.h" |
| +#include "content/public/browser/android/content_view_core.h" |
| +#include "content/public/browser/render_process_host.h" |
| +#include "content/public/browser/web_contents.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" |
| +#include "ui/gfx/size.h" |
| +#include "ui/gfx/transform.h" |
| +#include "ui/gl/gl_bindings.h" |
| + |
| +// TODO(leandrogracia): remove when crbug.com/164140 is closed. |
| +// Borrowed from gl2ext.h. Cannot be included due to conflicts with |
| +// gl_bindings.h and the EGL library methods (eglGetCurrentContext). |
| +#ifndef GL_TEXTURE_EXTERNAL_OES |
| +#define GL_TEXTURE_EXTERNAL_OES 0x8D65 |
| +#endif |
| + |
| +#ifndef GL_TEXTURE_BINDING_EXTERNAL_OES |
| +#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67 |
| +#endif |
| + |
| +using base::android::AttachCurrentThread; |
| +using base::android::JavaRef; |
| +using base::android::ScopedJavaLocalRef; |
| +using content::Compositor; |
| +using content::ContentViewCore; |
| + |
| +namespace { |
| + |
| +typedef base::Callback<bool(SkCanvas*)> RenderMethod; |
| + |
| +static bool RasterizeIntoBitmap(JNIEnv* env, |
| + const JavaRef<jobject>& jbitmap, |
| + int scroll_x, |
| + int scroll_y, |
| + const RenderMethod& renderer) { |
| + DCHECK(jbitmap.obj()); |
| + |
| + AndroidBitmapInfo bitmap_info; |
| + if (AndroidBitmap_getInfo(env, jbitmap.obj(), &bitmap_info) < 0) { |
| + LOG(ERROR) << "Error getting java bitmap info."; |
| + return false; |
| + } |
| + |
| + void* pixels = NULL; |
| + if (AndroidBitmap_lockPixels(env, jbitmap.obj(), &pixels) < 0) { |
| + LOG(ERROR) << "Error locking java bitmap pixels."; |
| + return false; |
| + } |
| + |
| + bool succeeded = false; |
|
joth
2013/02/06 20:26:31
nit: you can remove = false here, as it's uncondit
Leandro Graciá Gil
2013/02/07 12:43:56
Done.
|
| + { |
| + SkBitmap bitmap; |
| + bitmap.setConfig(SkBitmap::kARGB_8888_Config, |
| + bitmap_info.width, |
| + bitmap_info.height, |
| + bitmap_info.stride); |
| + bitmap.setPixels(pixels); |
| + |
| + SkDevice device(bitmap); |
| + SkCanvas canvas(&device); |
| + canvas.translate(-scroll_x, -scroll_y); |
| + succeeded = renderer.Run(&canvas); |
| + } |
| + |
| + if (AndroidBitmap_unlockPixels(env, jbitmap.obj()) < 0) { |
| + LOG(ERROR) << "Error unlocking java bitmap pixels."; |
| + return false; |
| + } |
| + |
| + return succeeded; |
| +} |
| + |
| +} // namespace |
| + |
| +namespace android_webview { |
| + |
| +// static |
| +BrowserViewRendererImpl* BrowserViewRendererImpl::Create( |
| + BrowserViewRenderer::Client* client, |
| + JavaHelper* java_helper) { |
| + return new BrowserViewRendererImpl(client, java_helper); |
| +} |
| + |
| +BrowserViewRendererImpl::BrowserViewRendererImpl( |
| + BrowserViewRenderer::Client* client, |
| + JavaHelper* java_helper) |
| + : BrowserViewRenderer(client, java_helper), |
| + ALLOW_THIS_IN_INITIALIZER_LIST(compositor_(Compositor::Create(this))), |
| + view_clip_layer_(cc::Layer::create()), |
| + transform_layer_(cc::Layer::create()), |
| + scissor_clip_layer_(cc::Layer::create()), |
| + view_visible_(false), |
| + compositor_visible_(false), |
| + is_composite_pending_(false), |
| + dpi_scale_(1.0f), |
| + on_new_picture_mode_(kOnNewPictureDisabled), |
| + last_frame_context_(NULL), |
| + web_contents_(NULL) { |
| + DCHECK(java_helper); |
| + |
| + // Define the view hierarchy. |
| + transform_layer_->addChild(view_clip_layer_); |
| + scissor_clip_layer_->addChild(transform_layer_); |
| + compositor_->SetRootLayer(scissor_clip_layer_); |
| + |
| + RendererPictureMap::CreateInstance(); |
| +} |
| + |
| +BrowserViewRendererImpl::~BrowserViewRendererImpl() { |
| +} |
| + |
| +void BrowserViewRendererImpl::SetContents(ContentViewCore* content_view_core) { |
| + dpi_scale_ = content_view_core->GetDpiScale(); |
| + web_contents_ = content_view_core->GetWebContents(); |
| + if (!view_renderer_host_) |
| + view_renderer_host_.reset(new ViewRendererHost(web_contents_, this)); |
| + else |
| + view_renderer_host_->Observe(web_contents_); |
| + |
| + view_clip_layer_->removeAllChildren(); |
| + view_clip_layer_->addChild(content_view_core->GetLayer()); |
| + Invalidate(); |
| +} |
| + |
| +void BrowserViewRendererImpl::DrawGL(AwDrawGLInfo* draw_info) { |
| + TRACE_EVENT0("android_webview", "BrowserViewRendererImpl::DrawGL"); |
| + |
| + if (view_size_.IsEmpty() || !scissor_clip_layer_ || |
| + draw_info->mode == AwDrawGLInfo::kModeProcess) |
| + return; |
| + |
| + DCHECK_EQ(draw_info->mode, AwDrawGLInfo::kModeDraw); |
| + |
| + SetCompositorVisibility(view_visible_); |
| + if (!compositor_visible_) |
| + return; |
| + |
| + // TODO(leandrogracia): remove when crbug.com/164140 is closed. |
| + // --------------------------------------------------------------------------- |
| + GLint texture_external_oes_binding; |
| + glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texture_external_oes_binding); |
| + |
| + GLint vertex_array_buffer_binding; |
| + glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &vertex_array_buffer_binding); |
| + |
| + GLint index_array_buffer_binding; |
| + glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &index_array_buffer_binding); |
| + |
| + GLint pack_alignment; |
| + glGetIntegerv(GL_PACK_ALIGNMENT, &pack_alignment); |
| + |
| + GLint unpack_alignment; |
| + glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack_alignment); |
| + |
| + struct { |
| + GLint enabled; |
| + GLint size; |
| + GLint type; |
| + GLint normalized; |
| + GLint stride; |
| + GLvoid* pointer; |
| + } vertex_attrib[3]; |
| + |
| + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(vertex_attrib); ++i) { |
| + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, |
| + &vertex_attrib[i].enabled); |
| + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, |
| + &vertex_attrib[i].size); |
| + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, |
| + &vertex_attrib[i].type); |
| + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, |
| + &vertex_attrib[i].normalized); |
| + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, |
| + &vertex_attrib[i].stride); |
| + glGetVertexAttribPointerv(i, GL_VERTEX_ATTRIB_ARRAY_POINTER, |
| + &vertex_attrib[i].pointer); |
| + } |
| + |
| + GLboolean depth_test; |
| + glGetBooleanv(GL_DEPTH_TEST, &depth_test); |
| + |
| + GLboolean cull_face; |
| + glGetBooleanv(GL_CULL_FACE, &cull_face); |
| + |
| + GLboolean color_mask[4]; |
| + glGetBooleanv(GL_COLOR_WRITEMASK, color_mask); |
| + |
| + GLboolean blend_enabled; |
| + glGetBooleanv(GL_BLEND, &blend_enabled); |
| + |
| + GLint blend_src_rgb; |
| + glGetIntegerv(GL_BLEND_SRC_RGB, &blend_src_rgb); |
| + |
| + GLint blend_src_alpha; |
| + glGetIntegerv(GL_BLEND_SRC_ALPHA, &blend_src_alpha); |
| + |
| + GLint blend_dest_rgb; |
| + glGetIntegerv(GL_BLEND_DST_RGB, &blend_dest_rgb); |
| + |
| + GLint blend_dest_alpha; |
| + glGetIntegerv(GL_BLEND_DST_ALPHA, &blend_dest_alpha); |
| + |
| + GLint active_texture; |
| + glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture); |
| + |
| + GLint viewport[4]; |
| + glGetIntegerv(GL_VIEWPORT, viewport); |
| + |
| + GLboolean scissor_test; |
| + glGetBooleanv(GL_SCISSOR_TEST, &scissor_test); |
| + |
| + GLint scissor_box[4]; |
| + glGetIntegerv(GL_SCISSOR_BOX, scissor_box); |
| + |
| + GLint current_program; |
| + glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program); |
| + // --------------------------------------------------------------------------- |
| + |
| + // We need to watch if the current Android context has changed and enforce |
| + // a clean-up in the compositor. |
| + EGLContext current_context = eglGetCurrentContext(); |
| + if (!current_context) { |
| + LOG(WARNING) << "No current context attached. Skipping composite."; |
| + return; |
| + } |
| + |
| + if (last_frame_context_ != current_context) { |
| + if (last_frame_context_) |
| + ResetCompositor(); |
| + last_frame_context_ = current_context; |
| + } |
| + |
| + compositor_->SetWindowBounds(gfx::Size(draw_info->width, draw_info->height)); |
| + |
| + if (draw_info->is_layer) { |
| + // When rendering into a separate layer no view clipping, transform, |
| + // scissoring or background transparency need to be handled. |
| + // The Android framework will composite us afterwards. |
| + compositor_->SetHasTransparentBackground(false); |
| + view_clip_layer_->setMasksToBounds(false); |
| + transform_layer_->setTransform(gfx::Transform()); |
| + scissor_clip_layer_->setMasksToBounds(false); |
| + scissor_clip_layer_->setPosition(gfx::PointF()); |
| + scissor_clip_layer_->setBounds(gfx::Size()); |
| + scissor_clip_layer_->setSublayerTransform(gfx::Transform()); |
| + |
| + } else { |
| + compositor_->SetHasTransparentBackground(true); |
| + |
| + gfx::Rect clip_rect(draw_info->clip_left, draw_info->clip_top, |
| + draw_info->clip_right - draw_info->clip_left, |
| + draw_info->clip_bottom - draw_info->clip_top); |
| + |
| + scissor_clip_layer_->setPosition(clip_rect.origin()); |
| + scissor_clip_layer_->setBounds(clip_rect.size()); |
| + scissor_clip_layer_->setMasksToBounds(true); |
| + |
| + // The compositor clipping architecture enforces us to have the clip layer |
| + // as an ancestor of the area we want to clip, but this makes the transform |
| + // become relative to the clip area rather than the full surface. The clip |
| + // position offset needs to be undone before applying the transform. |
| + gfx::Transform undo_clip_position; |
| + undo_clip_position.Translate(-clip_rect.x(), -clip_rect.y()); |
| + scissor_clip_layer_->setSublayerTransform(undo_clip_position); |
| + |
| + gfx::Transform transform; |
| + transform.matrix().setColMajorf(draw_info->transform); |
| + |
| + // The scrolling values of the Android Framework affect the transformation |
| + // matrix. This needs to be undone to let the compositor handle scrolling. |
| + transform.Translate(hw_rendering_scroll_.x(), hw_rendering_scroll_.y()); |
|
mkosiba (inactive)
2013/02/07 10:10:29
like we discussed earlier - when we have syncrhono
Leandro Graciá Gil
2013/02/07 12:43:56
Good point. Done.
|
| + transform_layer_->setTransform(transform); |
| + |
| + view_clip_layer_->setMasksToBounds(true); |
| + } |
| + |
| + compositor_->Composite(); |
| + is_composite_pending_ = false; |
| + |
| + // TODO(leandrogracia): remove when crbug.com/164140 is closed. |
| + // --------------------------------------------------------------------------- |
| + char no_gl_restore_prop[PROP_VALUE_MAX]; |
| + __system_property_get("webview.chromium_no_gl_restore", no_gl_restore_prop); |
| + if (!strcmp(no_gl_restore_prop, "true")) { |
| + LOG(WARNING) << "Android GL functor not restoring the previous GL state."; |
| + } else { |
| + glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_external_oes_binding); |
| + glBindBuffer(GL_ARRAY_BUFFER, vertex_array_buffer_binding); |
| + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_array_buffer_binding); |
| + |
| + glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment); |
| + glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment); |
| + |
| + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(vertex_attrib); ++i) { |
| + glVertexAttribPointer(i, vertex_attrib[i].size, |
| + vertex_attrib[i].type, vertex_attrib[i].normalized, |
| + vertex_attrib[i].stride, vertex_attrib[i].pointer); |
| + |
| + if (vertex_attrib[i].enabled) |
| + glEnableVertexAttribArray(i); |
| + else |
| + glDisableVertexAttribArray(i); |
| + } |
| + |
| + if (depth_test) |
| + glEnable(GL_DEPTH_TEST); |
| + else |
| + glDisable(GL_DEPTH_TEST); |
| + |
| + if (cull_face) |
| + glEnable(GL_CULL_FACE); |
| + else |
| + glDisable(GL_CULL_FACE); |
| + |
| + glColorMask(color_mask[0], color_mask[1], color_mask[2], |
| + color_mask[3]); |
|
mkosiba (inactive)
2013/02/07 10:10:29
nit: indent
Leandro Graciá Gil
2013/02/07 12:43:56
Done.
|
| + |
| + if (blend_enabled) |
| + glEnable(GL_BLEND); |
| + else |
| + glDisable(GL_BLEND); |
| + |
| + glBlendFuncSeparate(blend_src_rgb, blend_dest_rgb, |
| + blend_src_alpha, blend_dest_alpha); |
|
mkosiba (inactive)
2013/02/07 10:10:29
nit:indent
Leandro Graciá Gil
2013/02/07 12:43:56
Done.
|
| + |
| + glActiveTexture(active_texture); |
| + |
| + glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); |
| + |
| + if (scissor_test) |
| + glEnable(GL_SCISSOR_TEST); |
| + else |
| + glDisable(GL_SCISSOR_TEST); |
| + |
| + glScissor(scissor_box[0], scissor_box[1], scissor_box[2], |
| + scissor_box[3]); |
|
mkosiba (inactive)
2013/02/07 10:10:29
nit: indent
Leandro Graciá Gil
2013/02/07 12:43:56
Done.
|
| + |
| + glUseProgram(current_program); |
| + } |
| + // --------------------------------------------------------------------------- |
| +} |
| + |
| +void BrowserViewRendererImpl::SetScrollForHWFrame(int x, int y) { |
| + hw_rendering_scroll_ = gfx::Point(x, y); |
| +} |
| + |
| +bool BrowserViewRendererImpl::DrawSW(jobject java_canvas, |
| + const gfx::Rect& clip) { |
| + TRACE_EVENT0("android_webview", "BrowserViewRendererImpl::DrawSW"); |
| + |
| + if (clip.IsEmpty()) |
| + return true; |
| + |
| + AwPixelInfo* pixels; |
| + JNIEnv* env = AttachCurrentThread(); |
| + |
| + // Render into an auxiliary bitmap if pixel info is not available. |
| + if (!SWDrawFunctions() || |
| + (pixels = SWDrawFunctions()->access_pixels(env, java_canvas)) == NULL) { |
| + ScopedJavaLocalRef<jobject> jbitmap(java_helper()->CreateBitmap( |
| + env, clip.width(), clip.height())); |
| + if (!jbitmap.obj()) |
| + return false; |
| + |
| + if (!RasterizeIntoBitmap(env, jbitmap, clip.x(), clip.y(), |
| + base::Bind(&BrowserViewRendererImpl::RenderSW, base::Unretained(this)))) |
|
joth
2013/02/06 20:26:31
if (!RasterizeIntoBitmap(env, jbitmap, clip.x(), c
Leandro Graciá Gil
2013/02/07 12:43:56
Done.
|
| + return false; |
| + |
| + ScopedJavaLocalRef<jobject> jcanvas(env, java_canvas); |
| + java_helper()->DrawBitmapIntoCanvas(env, jbitmap, jcanvas); |
| + 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); |
|
joth
2013/02/06 20:26:31
feels like there's some repetition here with Raste
Leandro Graciá Gil
2013/02/07 12:43:56
It's similar but not quite the same. RasterizeInto
|
| + SkMatrix matrix; |
| + for (int i = 0; i < 9; i++) |
| + matrix.set(i, pixels->matrix[i]); |
| + canvas.setMatrix(matrix); |
| + |
| + SkRegion clip; |
| + if (pixels->clip_region_size) { |
| + size_t bytes_read = clip.readFromMemory(pixels->clip_region); |
| + DCHECK_EQ(pixels->clip_region_size, bytes_read); |
| + canvas.setClipRegion(clip); |
| + } else { |
| + clip.setRect(SkIRect::MakeWH(pixels->width, pixels->height)); |
| + } |
| + |
| + succeeded = RenderSW(&canvas); |
| + } |
| + |
| + SWDrawFunctions()->release_pixels(pixels); |
| + return succeeded; |
| +} |
| + |
| +ScopedJavaLocalRef<jobject> BrowserViewRendererImpl::CapturePicture() { |
| + skia::RefPtr<SkPicture> picture = GetLastCapturedPicture(); |
| + if (!picture || !SWDrawFunctions()) |
| + return ScopedJavaLocalRef<jobject>(); |
| + |
| + JNIEnv* env = AttachCurrentThread(); |
| + if (IsSkiaVersionCompatible()) { |
| + return ScopedJavaLocalRef<jobject>(env, |
| + SWDrawFunctions()->create_picture(env, picture->clone())); |
| + } |
| + |
| + // If Skia versions are not compatible, workaround it by rasterizing the |
| + // picture into a bitmap and drawing it into a new Java picture. |
| + ScopedJavaLocalRef<jobject> jbitmap(java_helper()->CreateBitmap( |
| + env, picture->width(), picture->height())); |
| + if (!jbitmap.obj()) |
| + return ScopedJavaLocalRef<jobject>(); |
| + |
| + if (!RasterizeIntoBitmap(env, jbitmap, 0, 0, |
| + base::Bind(&BrowserViewRendererImpl::RenderPicture, |
| + base::Unretained(this)))) { |
| + return ScopedJavaLocalRef<jobject>(); |
| + } |
| + |
| + return java_helper()->RecordBitmapIntoPicture(env, jbitmap); |
| +} |
| + |
| +void BrowserViewRendererImpl::EnableOnNewPicture(OnNewPictureMode mode) { |
| + on_new_picture_mode_ = mode; |
| + |
| + // TODO(leandrogracia): when SW rendering uses the compositor rather than |
| + // picture rasterization, send update the renderer side with the correct |
| + // listener state. (For now, we always leave render picture listener enabled). |
| + // render_view_host_ext_->EnableCapturePictureCallback(enabled); |
| + //DCHECK(view_renderer_host_); |
| + //view_renderer_host_->EnableCapturePictureCallback( |
| + // on_new_picture_mode_ == kOnNewPictureEnabled); |
| +} |
| + |
| +void BrowserViewRendererImpl::OnVisibilityChanged(bool view_visible, |
| + bool window_visible) { |
|
joth
2013/02/06 20:26:31
indent
Leandro Graciá Gil
2013/02/07 12:43:56
Done.
|
| + view_visible_ = window_visible && view_visible; |
| + Invalidate(); |
| +} |
| + |
| +void BrowserViewRendererImpl::OnSizeChanged(int width, int height) { |
| + view_size_ = gfx::Size(width, height); |
| + view_clip_layer_->setBounds(view_size_); |
| +} |
| + |
| +void BrowserViewRendererImpl::OnAttachedToWindow(int width, int height) { |
| + view_size_ = gfx::Size(width, height); |
| + view_clip_layer_->setBounds(view_size_); |
| +} |
| + |
| +void BrowserViewRendererImpl::OnDetachedFromWindow() { |
| + view_visible_ = false; |
| + SetCompositorVisibility(false); |
| +} |
| + |
| +void BrowserViewRendererImpl::ScheduleComposite() { |
| + TRACE_EVENT0("android_webview", "BrowserViewRendererImpl::ScheduleComposite"); |
| + |
| + if (is_composite_pending_) |
| + return; |
| + |
| + is_composite_pending_ = true; |
| + Invalidate(); |
| +} |
| + |
| +skia::RefPtr<SkPicture> BrowserViewRendererImpl::GetLastCapturedPicture() { |
| + // Use the latest available picture if the listener callback is enabled. |
| + skia::RefPtr<SkPicture> picture; |
| + if (on_new_picture_mode_ == kOnNewPictureEnabled) |
| + picture = RendererPictureMap::GetInstance()->GetRendererPicture( |
| + web_contents_->GetRoutingID()); |
| + |
| + // If not available or not in listener mode get it synchronously. |
| + if (!picture) { |
| + DCHECK(view_renderer_host_); |
| + view_renderer_host_->CapturePictureSync(); |
| + picture = RendererPictureMap::GetInstance()->GetRendererPicture( |
| + web_contents_->GetRoutingID()); |
| + } |
| + |
| + return picture; |
| +} |
| + |
| +void BrowserViewRendererImpl::OnPictureUpdated(int process_id, |
| + int render_view_id) { |
| + CHECK_EQ(web_contents_->GetRenderProcessHost()->GetID(), process_id); |
| + if (render_view_id != web_contents_->GetRoutingID()) |
| + return; |
| + |
| + // TODO(leandrogracia): this can be made unconditional once software rendering |
| + // uses Ubercompositor. Until then this path is required for SW invalidations. |
| + if (on_new_picture_mode_ == kOnNewPictureEnabled) |
| + client()->OnNewPicture(CapturePicture()); |
| + |
| + // TODO(leandrogracia): delete when sw rendering uses Ubercompositor. |
| + // Invalidation should be provided by the compositor only. |
| + Invalidate(); |
| +} |
| + |
| +void BrowserViewRendererImpl::SetCompositorVisibility(bool visible) { |
| + if (compositor_visible_ != visible) { |
| + compositor_visible_ = visible; |
| + compositor_->SetVisible(compositor_visible_); |
| + } |
| +} |
| + |
| +void BrowserViewRendererImpl::ResetCompositor() { |
| + compositor_.reset(content::Compositor::Create(this)); |
| + compositor_->SetRootLayer(scissor_clip_layer_); |
| +} |
| + |
| +void BrowserViewRendererImpl::Invalidate() { |
| + if (view_visible_) |
| + client()->Invalidate(); |
| + |
| + // When not in invalidation-only mode onNewPicture will be triggered |
| + // from the OnPictureUpdated callback. |
| + if (on_new_picture_mode_ == kOnNewPictureInvalidationOnly) |
| + client()->OnNewPicture(ScopedJavaLocalRef<jobject>()); |
| +} |
| + |
| +bool BrowserViewRendererImpl::RenderSW(SkCanvas* canvas) { |
| + // TODO(leandrogracia): once Ubercompositor is ready and we support software |
| + // rendering mode, we should avoid this as much as we can, ideally always. |
| + // This includes finding a proper replacement for onDraw calls in hardware |
| + // mode with software canvases. http://crbug.com/170086. |
| + return RenderPicture(canvas); |
| + |
| + //compositor_->Composite(); |
| + //is_composite_pending_ = false; |
| + //return true; |
| +} |
| + |
| +bool BrowserViewRendererImpl::RenderPicture(SkCanvas* canvas) { |
| + skia::RefPtr<SkPicture> picture = GetLastCapturedPicture(); |
| + if (!picture) |
| + return false; |
| + |
| + // Correct device scale. |
| + canvas->scale(dpi_scale_, dpi_scale_); |
| + |
| + picture->draw(canvas); |
| + return true; |
| +} |
| + |
| +} // namespace android_webview |