diff options
24 files changed, 715 insertions, 1259 deletions
diff --git a/android_webview/DEPS b/android_webview/DEPS index 02d8ca9..d5e52b5 100644 --- a/android_webview/DEPS +++ b/android_webview/DEPS @@ -8,6 +8,7 @@ include_rules = [ "-android_webview/lib", "!chrome/browser/component", + "+cc", "+content/public/common", "+jni", "+net", diff --git a/android_webview/android_webview.gyp b/android_webview/android_webview.gyp index 8010ba8..195782b 100644 --- a/android_webview/android_webview.gyp +++ b/android_webview/android_webview.gyp @@ -107,7 +107,6 @@ '../components/components.gyp:web_contents_delegate_android', '../content/content.gyp:content', '../skia/skia.gyp:skia', - '../ui/gl/gl.gyp:gl', 'android_webview_pak', ], 'include_dirs': [ @@ -136,9 +135,6 @@ 'browser/aw_request_interceptor.cc', 'browser/aw_request_interceptor.h', 'browser/aw_result_codes.h', - 'browser/browser_view_renderer.h', - 'browser/browser_view_renderer_impl.cc', - 'browser/browser_view_renderer_impl.h', 'browser/find_helper.cc', 'browser/find_helper.h', 'browser/icon_helper.cc', @@ -162,8 +158,6 @@ 'browser/renderer_host/aw_render_view_host_ext.h', 'browser/renderer_host/aw_resource_dispatcher_host_delegate.cc', 'browser/renderer_host/aw_resource_dispatcher_host_delegate.h', - 'browser/renderer_host/view_renderer_host.cc', - 'browser/renderer_host/view_renderer_host.h', 'browser/scoped_allow_wait_for_legacy_web_view_api.h', 'browser/scoped_allow_wait_for_legacy_web_view_api.h', 'common/android_webview_message_generator.cc', @@ -190,8 +184,6 @@ 'renderer/aw_render_process_observer.h', 'renderer/aw_render_view_ext.cc', 'renderer/aw_render_view_ext.h', - 'renderer/view_renderer.cc', - 'renderer/view_renderer.h', ], }, { diff --git a/android_webview/browser/DEPS b/android_webview/browser/DEPS index c48c8f4..2caa535 100644 --- a/android_webview/browser/DEPS +++ b/android_webview/browser/DEPS @@ -2,9 +2,6 @@ include_rules = [ "-android_webview", "+android_webview/browser", "+android_webview/common", - "+android_webview/public/browser", - - "+cc", "+components/auto_login_parser", "+components/navigation_interception", @@ -12,9 +9,6 @@ include_rules = [ "+content/public/browser", - "+ui/gfx", - "+ui/gl", - # Temporary until we bundle our own favicon. See # AwContentBrowserClient::GetDefaultFavicon "!grit/ui_resources.h", diff --git a/android_webview/browser/browser_view_renderer.h b/android_webview/browser/browser_view_renderer.h deleted file mode 100644 index 02f47bc..0000000 --- a/android_webview/browser/browser_view_renderer.h +++ /dev/null @@ -1,95 +0,0 @@ -// 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. - -#ifndef ANDROID_WEBVIEW_BROWSER_BROWSER_VIEW_RENDERER_H_ -#define ANDROID_WEBVIEW_BROWSER_BROWSER_VIEW_RENDERER_H_ - -#include "base/android/scoped_java_ref.h" - -struct AwDrawGLInfo; - -namespace content { -class ContentViewCore; -} - -namespace gfx { -class Rect; -} - -namespace android_webview { - -// Interface for all the WebView-specific content rendering operations. -// Provides software and hardware rendering and the Capture Picture API. -class BrowserViewRenderer { - public: - class Client { - public: - // Called to trigger view invalidations. - virtual void Invalidate() = 0; - - // Called when a new Picture is available. Needs to be enabled - // via the EnableOnNewPicture method. - virtual void OnNewPicture( - const base::android::JavaRef<jobject>& picture) = 0; - - protected: - virtual ~Client() {} - }; - - // Delegate to perform rendering actions involving Java objects. - class JavaHelper { - public: - // Creates a RGBA_8888 Java Bitmap object of the requested size. - virtual base::android::ScopedJavaLocalRef<jobject> CreateBitmap( - JNIEnv* env, - int width, - int height) = 0; - - // Draws the provided Java Bitmap into the provided Java Canvas. - virtual void DrawBitmapIntoCanvas( - JNIEnv* env, - const base::android::JavaRef<jobject>& jbitmap, - const base::android::JavaRef<jobject>& jcanvas) = 0; - - // Creates a Java Picture object that records drawing the provided Bitmap. - virtual base::android::ScopedJavaLocalRef<jobject> RecordBitmapIntoPicture( - JNIEnv* env, - const base::android::JavaRef<jobject>& jbitmap) = 0; - - protected: - virtual ~JavaHelper() {} - }; - - enum OnNewPictureMode { - kOnNewPictureDisabled = 0, - kOnNewPictureEnabled, - kOnNewPictureInvalidationOnly, - }; - - // Content control methods. - virtual void SetContents(content::ContentViewCore* content_view_core) = 0; - - // Hardware rendering methods. - virtual void DrawGL(AwDrawGLInfo* draw_info) = 0; - virtual void SetScrollForHWFrame(int x, int y) = 0; - - // Software rendering methods. - virtual bool DrawSW(jobject java_canvas, const gfx::Rect& clip_bounds) = 0; - - // CapturePicture API methods. - virtual base::android::ScopedJavaLocalRef<jobject> CapturePicture() = 0; - virtual void EnableOnNewPicture(OnNewPictureMode mode) = 0; - - // View update notifications. - virtual void OnVisibilityChanged(bool view_visible, bool window_visible) = 0; - virtual void OnSizeChanged(int width, int height) = 0; - virtual void OnAttachedToWindow(int width, int height) = 0; - virtual void OnDetachedFromWindow() = 0; - - virtual ~BrowserViewRenderer() {} -}; - -} // namespace android_webview - -#endif // ANDROID_WEBVIEW_BROWSER_BROWSER_VIEW_RENDERER_H_ diff --git a/android_webview/browser/browser_view_renderer_impl.cc b/android_webview/browser/browser_view_renderer_impl.cc deleted file mode 100644 index 250cdb0..0000000 --- a/android_webview/browser/browser_view_renderer_impl.cc +++ /dev/null @@ -1,596 +0,0 @@ -// 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 "third_party/skia/include/core/SkGraphics.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 { - -// Provides software rendering functions from the Android glue layer. -// 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; - -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; - { - 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) - : client_(client), - java_helper_(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() { -} - -// static -void BrowserViewRendererImpl::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."; -} - -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. - // TODO(leandrogracia): when scrolling becomes synchronous we should undo - // or override the translation in the compositor, not the one coming from - // the Android View System, as it could be out of bounds for overscrolling. - transform.Translate(hw_rendering_scroll_.x(), hw_rendering_scroll_.y()); - 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]); - - if (blend_enabled) - glEnable(GL_BLEND); - else - glDisable(GL_BLEND); - - glBlendFuncSeparate(blend_src_rgb, blend_dest_rgb, - blend_src_alpha, blend_dest_alpha); - - 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]); - - 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 (!g_sw_draw_functions || - (pixels = g_sw_draw_functions->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)))) { - 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); - 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); - } - - g_sw_draw_functions->release_pixels(pixels); - return succeeded; -} - -ScopedJavaLocalRef<jobject> BrowserViewRendererImpl::CapturePicture() { - skia::RefPtr<SkPicture> picture = GetLastCapturedPicture(); - if (!picture || !g_sw_draw_functions) - return ScopedJavaLocalRef<jobject>(); - - JNIEnv* env = AttachCurrentThread(); - if (g_is_skia_version_compatible) { - return ScopedJavaLocalRef<jobject>(env, - g_sw_draw_functions->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) { - 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); -} - -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 diff --git a/android_webview/browser/browser_view_renderer_impl.h b/android_webview/browser/browser_view_renderer_impl.h deleted file mode 100644 index 323ddcb..0000000 --- a/android_webview/browser/browser_view_renderer_impl.h +++ /dev/null @@ -1,115 +0,0 @@ -// 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. - -#ifndef ANDROID_WEBVIEW_BROWSER_BROWSER_VIEW_RENDERER_IMPL_H_ -#define ANDROID_WEBVIEW_BROWSER_BROWSER_VIEW_RENDERER_IMPL_H_ - -#include "android_webview/browser/browser_view_renderer.h" -#include "android_webview/browser/renderer_host/view_renderer_host.h" -#include "content/public/browser/android/compositor.h" -#include "content/public/browser/web_contents_observer.h" -#include "skia/ext/refptr.h" -#include "ui/gfx/point.h" -#include "ui/gfx/size.h" - -typedef void* EGLContext; -struct AwDrawSWFunctionTable; -struct AwDrawGLInfo; -class SkCanvas; -class SkPicture; - -namespace content { -class WebContents; -} - -namespace android_webview { - -class BrowserViewRendererImpl - : public BrowserViewRenderer, - public ViewRendererHost::Client, - public content::Compositor::Client { - public: - static BrowserViewRendererImpl* Create(BrowserViewRenderer::Client* client, - JavaHelper* java_helper); - virtual ~BrowserViewRendererImpl(); - - // Platform methods. - static void SetAwDrawSWFunctionTable(AwDrawSWFunctionTable* table); - - // BrowserViewRenderer implementation. - virtual void SetContents( - content::ContentViewCore* content_view_core) OVERRIDE; - virtual void DrawGL(AwDrawGLInfo* draw_info) OVERRIDE; - virtual void SetScrollForHWFrame(int x, int y) OVERRIDE; - virtual bool DrawSW(jobject java_canvas, const gfx::Rect& clip) OVERRIDE; - virtual base::android::ScopedJavaLocalRef<jobject> CapturePicture() OVERRIDE; - virtual void EnableOnNewPicture(OnNewPictureMode mode) OVERRIDE; - virtual void OnVisibilityChanged( - bool view_visible, bool window_visible) OVERRIDE; - virtual void OnSizeChanged(int width, int height) OVERRIDE; - virtual void OnAttachedToWindow(int width, int height) OVERRIDE; - virtual void OnDetachedFromWindow() OVERRIDE; - - // content::Compositor::Client implementation. - virtual void ScheduleComposite() OVERRIDE; - - // ViewRendererHost::Client implementation. - virtual void OnPictureUpdated(int process_id, int render_view_id) OVERRIDE; - - protected: - BrowserViewRendererImpl(BrowserViewRenderer::Client* client, - JavaHelper* java_helper); - - private: - // Returns the latest locally available picture if any. - // If none is available will synchronously request the latest one - // and block until the result is received. - skia::RefPtr<SkPicture> GetLastCapturedPicture(); - void OnPictureUpdated(); - - void SetCompositorVisibility(bool visible); - void ResetCompositor(); - void Invalidate(); - bool RenderSW(SkCanvas* canvas); - bool RenderPicture(SkCanvas* canvas); - - BrowserViewRenderer::Client* client_; - BrowserViewRenderer::JavaHelper* java_helper_; - - scoped_ptr<ViewRendererHost> view_renderer_host_; - scoped_ptr<content::Compositor> compositor_; - - // Ensures content keeps clipped within the view during transformations. - scoped_refptr<cc::Layer> view_clip_layer_; - - // Applies the transformation matrix. - scoped_refptr<cc::Layer> transform_layer_; - - // Ensures content is drawn within the scissor clip rect provided by the - // Android framework. - scoped_refptr<cc::Layer> scissor_clip_layer_; - - // Last View scroll before hardware rendering is triggered. - gfx::Point hw_rendering_scroll_; - - bool view_visible_; - bool compositor_visible_; - bool is_composite_pending_; - float dpi_scale_; - gfx::Size view_size_; - OnNewPictureMode on_new_picture_mode_; - - // Used only for detecting Android View System context changes. - // Not to be used between draw calls. - EGLContext last_frame_context_; - - // Set via SetContents. Used to recognize updates to the local WebView. - content::WebContents* web_contents_; - - DISALLOW_COPY_AND_ASSIGN(BrowserViewRendererImpl); -}; - -} // namespace android_webview - -#endif // ANDROID_WEBVIEW_BROWSER_BROWSER_VIEW_RENDERER_IMPL_H_ diff --git a/android_webview/browser/renderer_host/aw_render_view_host_ext.cc b/android_webview/browser/renderer_host/aw_render_view_host_ext.cc index 0c7f082..d76c7e9 100644 --- a/android_webview/browser/renderer_host/aw_render_view_host_ext.cc +++ b/android_webview/browser/renderer_host/aw_render_view_host_ext.cc @@ -18,9 +18,11 @@ namespace android_webview { -AwRenderViewHostExt::AwRenderViewHostExt(content::WebContents* contents) +AwRenderViewHostExt::AwRenderViewHostExt(content::WebContents* contents, + Client* client) : content::WebContentsObserver(contents), - has_new_hit_test_data_(false) { + has_new_hit_test_data_(false), + client_(client) { } AwRenderViewHostExt::~AwRenderViewHostExt() {} @@ -63,6 +65,11 @@ const AwHitTestData& AwRenderViewHostExt::GetLastHitTestData() const { return last_hit_test_data_; } +void AwRenderViewHostExt::EnableCapturePictureCallback(bool enabled) { + Send(new AwViewMsg_EnableCapturePictureCallback( + web_contents()->GetRoutingID(), enabled)); +} + void AwRenderViewHostExt::SetTextZoomLevel(double level) { DCHECK(CalledOnValidThread()); Send(new AwViewMsg_SetTextZoomLevel(web_contents()->GetRoutingID(), level)); @@ -94,6 +101,8 @@ bool AwRenderViewHostExt::OnMessageReceived(const IPC::Message& message) { OnDocumentHasImagesResponse) IPC_MESSAGE_HANDLER(AwViewHostMsg_UpdateHitTestData, OnUpdateHitTestData) + IPC_MESSAGE_HANDLER(AwViewHostMsg_PictureUpdated, + OnPictureUpdated) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -120,4 +129,24 @@ void AwRenderViewHostExt::OnUpdateHitTestData( has_new_hit_test_data_ = true; } +void AwRenderViewHostExt::OnPictureUpdated() { + if (client_) + client_->OnPictureUpdated(web_contents()->GetRenderProcessHost()->GetID(), + routing_id()); +} + +bool AwRenderViewHostExt::IsRenderViewReady() const { + return web_contents()->GetRenderProcessHost()->HasConnection() && + web_contents()->GetRenderViewHost() && + web_contents()->GetRenderViewHost()->IsRenderViewLive(); +} + +void AwRenderViewHostExt::CapturePictureSync() { + if (!IsRenderViewReady()) + return; + + ScopedAllowWaitForLegacyWebViewApi wait; + Send(new AwViewMsg_CapturePictureSync(web_contents()->GetRoutingID())); +} + } // namespace android_webview diff --git a/android_webview/browser/renderer_host/aw_render_view_host_ext.h b/android_webview/browser/renderer_host/aw_render_view_host_ext.h index fae35e9..678ef1a 100644 --- a/android_webview/browser/renderer_host/aw_render_view_host_ext.h +++ b/android_webview/browser/renderer_host/aw_render_view_host_ext.h @@ -25,9 +25,17 @@ namespace android_webview { class AwRenderViewHostExt : public content::WebContentsObserver, public base::NonThreadSafe { public: + class Client { + public: + virtual void OnPictureUpdated(int process_id, int render_view_id) = 0; + + protected: + virtual ~Client() {} + }; + // To send receive messages to a RenderView we take the WebContents instance, // as it internally handles RenderViewHost instances changing underneath us. - AwRenderViewHostExt(content::WebContents* contents); + AwRenderViewHostExt(content::WebContents* contents, Client* client); virtual ~AwRenderViewHostExt(); // |result| will be invoked with the outcome of the request. @@ -50,6 +58,14 @@ class AwRenderViewHostExt : public content::WebContentsObserver, // the corresponding public WebView API is as well. const AwHitTestData& GetLastHitTestData() const; + // Enables updating picture piles on every new frame. + // OnPictureUpdated is called when a new picture is available, + // stored by renderer id in RendererPictureMap. + void EnableCapturePictureCallback(bool enabled); + + // Captures the latest available picture pile synchronously. + void CapturePictureSync(); + // Sets the zoom level for text only. Used in layout modes other than // Text Autosizing. void SetTextZoomLevel(double level); @@ -77,6 +93,8 @@ class AwRenderViewHostExt : public content::WebContentsObserver, bool has_new_hit_test_data_; + Client* client_; + DISALLOW_COPY_AND_ASSIGN(AwRenderViewHostExt); }; diff --git a/android_webview/browser/renderer_host/view_renderer_host.cc b/android_webview/browser/renderer_host/view_renderer_host.cc deleted file mode 100644 index 3b8e654..0000000 --- a/android_webview/browser/renderer_host/view_renderer_host.cc +++ /dev/null @@ -1,68 +0,0 @@ -// 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/renderer_host/view_renderer_host.h" - -#include "android_webview/browser/scoped_allow_wait_for_legacy_web_view_api.h" -#include "android_webview/common/render_view_messages.h" -#include "android_webview/common/renderer_picture_map.h" -#include "content/public/browser/render_process_host.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/web_contents.h" - -namespace android_webview { - -ViewRendererHost::ViewRendererHost(content::WebContents* contents, - Client* client) - : content::WebContentsObserver(contents), - client_(client) { -} - -ViewRendererHost::~ViewRendererHost() { -} - -void ViewRendererHost::CapturePictureSync() { - if (!IsRenderViewReady()) - return; - - ScopedAllowWaitForLegacyWebViewApi wait; - Send(new AwViewMsg_CapturePictureSync(web_contents()->GetRoutingID())); -} - -void ViewRendererHost::EnableCapturePictureCallback(bool enabled) { - Send(new AwViewMsg_EnableCapturePictureCallback( - web_contents()->GetRoutingID(), enabled)); -} - -void ViewRendererHost::OnPictureUpdated() { - if (client_) { - client_->OnPictureUpdated(web_contents()->GetRenderProcessHost()->GetID(), - routing_id()); - } -} - -void ViewRendererHost::RenderViewGone(base::TerminationStatus status) { - DCHECK(CalledOnValidThread()); - RendererPictureMap::GetInstance()->ClearRendererPicture( - web_contents()->GetRoutingID()); -} - -bool ViewRendererHost::OnMessageReceived(const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(ViewRendererHost, message) - IPC_MESSAGE_HANDLER(AwViewHostMsg_PictureUpdated, - OnPictureUpdated) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - - return handled ? true : WebContentsObserver::OnMessageReceived(message); -} - -bool ViewRendererHost::IsRenderViewReady() const { - return web_contents()->GetRenderProcessHost()->HasConnection() && - web_contents()->GetRenderViewHost() && - web_contents()->GetRenderViewHost()->IsRenderViewLive(); -} - -} // namespace android_webview diff --git a/android_webview/browser/renderer_host/view_renderer_host.h b/android_webview/browser/renderer_host/view_renderer_host.h deleted file mode 100644 index aaaad5d..0000000 --- a/android_webview/browser/renderer_host/view_renderer_host.h +++ /dev/null @@ -1,52 +0,0 @@ -// 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. - -#ifndef ANDROID_WEBVIEW_BROWSER_RENDER_HOST_VIEW_RENDERER_HOST_H_ -#define ANDROID_WEBVIEW_BROWSER_RENDER_HOST_VIEW_RENDERER_HOST_H_ - -#include "base/threading/non_thread_safe.h" -#include "content/public/browser/web_contents_observer.h" - -namespace android_webview { - -// Provides RenderViewHost wrapper functionality for sending WebView-specific -// IPC messages to the renderer and from there to WebKit. -class ViewRendererHost : public content::WebContentsObserver, - public base::NonThreadSafe { - public: - class Client { - public: - virtual void OnPictureUpdated(int process_id, int render_view_id) = 0; - - protected: - virtual ~Client() {} - }; - - ViewRendererHost(content::WebContents* contents, Client* client); - virtual ~ViewRendererHost(); - - // Captures the latest available picture pile synchronously. - void CapturePictureSync(); - - // Enables updating picture piles on every new frame. - // OnPictureUpdated is called when a new picture is available, - // stored by renderer id in RendererPictureMap. - void EnableCapturePictureCallback(bool enabled); - - using content::WebContentsObserver::Observe; - - private: - // content::WebContentsObserver implementation. - virtual void RenderViewGone(base::TerminationStatus status) OVERRIDE; - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - - void OnPictureUpdated(); - bool IsRenderViewReady() const; - - Client* client_; -}; - -} // namespace android_webview - -#endif // ANDROID_WEBVIEW_BROWSER_RENDER_HOST_VIEW_RENDERER_HOST_H_ diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index adf23f9..a0027c3 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java @@ -320,8 +320,8 @@ public class AwContents { public int getAwDrawGLViewContext() { // Using the native pointer as the returned viewContext. This is matched by the - // reinterpret_cast back to BrowserViewRenderer pointer in the native DrawGLFunction. - return nativeGetAwDrawGLViewContext(mNativeAwContents); + // reinterpret_cast back to AwContents pointer in the native DrawGLFunction. + return mNativeAwContents; } public boolean onPrepareDrawGL(Canvas canvas) { @@ -998,6 +998,38 @@ public class AwContents { return null; } + /** + * Provides a Bitmap object with a given width and height used for auxiliary rasterization. + */ + @CalledByNative + private static Bitmap createBitmap(int width, int height) { + return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + } + + /** + * Draws a provided bitmap into a canvas. + * Used for convenience from the native side and other static helper methods. + */ + @CalledByNative + private static void drawBitmapIntoCanvas(Bitmap bitmap, Canvas canvas) { + canvas.drawBitmap(bitmap, 0, 0, null); + } + + /** + * Creates a new Picture that records drawing a provided bitmap. + * Will return an empty Picture if the Bitmap is null. + */ + @CalledByNative + private static Picture recordBitmapIntoPicture(Bitmap bitmap) { + Picture picture = new Picture(); + if (bitmap != null) { + Canvas recordingCanvas = picture.beginRecording(bitmap.getWidth(), bitmap.getHeight()); + drawBitmapIntoCanvas(bitmap, recordingCanvas); + picture.endRecording(); + } + return picture; + } + @CalledByNative private void handleJsAlert(String url, String message, JsResultReceiver receiver) { mContentsClient.handleJsAlert(url, message, receiver); @@ -1043,6 +1075,8 @@ public class AwContents { private native void nativeAddVisitedLinks(int nativeAwContents, String[] visitedLinks); + private native boolean nativeDrawSW(int nativeAwContents, Canvas canvas, int clipX, int clipY, + int clipW, int clipH); private native void nativeSetScrollForHWFrame(int nativeAwContents, int scrollX, int scrollY); private native int nativeFindAllSync(int nativeAwContents, String searchString); private native void nativeFindAllAsync(int nativeAwContents, String searchString); @@ -1071,9 +1105,6 @@ public class AwContents { private native void nativeSetWebContents(int nativeAwContents, int nativeNewWebContents); private native void nativeFocusFirstNode(int nativeAwContents); - private native boolean nativeDrawSW(int nativeAwContents, Canvas canvas, int clipX, int clipY, - int clipW, int clipH); - private native int nativeGetAwDrawGLViewContext(int nativeAwContents); private native Picture nativeCapturePicture(int nativeAwContents); private native void nativeEnableOnNewPicture(int nativeAwContents, boolean enabled, boolean invalidationOnly); diff --git a/android_webview/java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java b/android_webview/java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java deleted file mode 100644 index d4e79c8..0000000 --- a/android_webview/java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java +++ /dev/null @@ -1,56 +0,0 @@ -// 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. - -package org.chromium.android_webview; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Picture; - -import org.chromium.base.CalledByNative; -import org.chromium.base.JNINamespace; - -/** - * Provides auxiliary methods related to Picture objects and native SkPictures. - */ -@JNINamespace("android_webview") -public class JavaBrowserViewRendererHelper { - - /** - * Provides a Bitmap object with a given width and height used for auxiliary rasterization. - */ - @CalledByNative - private static Bitmap createBitmap(int width, int height) { - return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - } - - /** - * Draws a provided bitmap into a canvas. - * Used for convenience from the native side and other static helper methods. - */ - @CalledByNative - private static void drawBitmapIntoCanvas(Bitmap bitmap, Canvas canvas) { - canvas.drawBitmap(bitmap, 0, 0, null); - } - - /** - * Creates a new Picture that records drawing a provided bitmap. - * Will return an empty Picture if the Bitmap is null. - */ - @CalledByNative - private static Picture recordBitmapIntoPicture(Bitmap bitmap) { - Picture picture = new Picture(); - if (bitmap != null) { - Canvas recordingCanvas = picture.beginRecording(bitmap.getWidth(), bitmap.getHeight()); - drawBitmapIntoCanvas(bitmap, recordingCanvas); - picture.endRecording(); - } - return picture; - } - - // Should never be instantiated. - private JavaBrowserViewRendererHelper() { - } -} diff --git a/android_webview/native/DEPS b/android_webview/native/DEPS index c3d3955..6693d30 100644 --- a/android_webview/native/DEPS +++ b/android_webview/native/DEPS @@ -1,7 +1,12 @@ include_rules = [ "+content/public/browser", + "+ui/gfx", + "+ui/gl", # Components that Android WebView depends on. "+components/navigation_interception", "+components/web_contents_delegate_android", + + # TODO(joth): Remove if we can move the compositor driver into ../browser/ + "+third_party/skia/include", ] diff --git a/android_webview/native/android_webview_jni_registrar.cc b/android_webview/native/android_webview_jni_registrar.cc index 47c7373..33dfff0 100644 --- a/android_webview/native/android_webview_jni_registrar.cc +++ b/android_webview/native/android_webview_jni_registrar.cc @@ -14,7 +14,6 @@ #include "android_webview/native/cookie_manager.h" #include "android_webview/native/input_stream_impl.h" #include "android_webview/native/intercepted_request_data_impl.h" -#include "android_webview/native/java_browser_view_renderer_helper.h" #include "android_webview/native/js_result_handler.h" #include "base/android/jni_android.h" #include "base/android/jni_registrar.h" @@ -33,7 +32,6 @@ static base::android::RegistrationMethod kWebViewRegisteredMethods[] = { { "CookieManager", RegisterCookieManager }, { "InterceptedRequestDataImpl", RegisterInterceptedRequestData }, { "InputStream", RegisterInputStream }, - { "JavaBrowserViewRendererHelper", RegisterJavaBrowserViewRendererHelper }, { "JsResultHandler", RegisterJsResultHandler }, }; diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc index 6bef690..7b429f2 100644 --- a/android_webview/native/aw_contents.cc +++ b/android_webview/native/aw_contents.cc @@ -4,28 +4,32 @@ #include "android_webview/native/aw_contents.h" +#include <android/bitmap.h> +#include <sys/system_properties.h> + #include "android_webview/browser/aw_browser_context.h" #include "android_webview/browser/aw_browser_main_parts.h" -#include "android_webview/browser/browser_view_renderer_impl.h" #include "android_webview/browser/net_disk_cache_remover.h" #include "android_webview/browser/renderer_host/aw_render_view_host_ext.h" #include "android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h" #include "android_webview/common/aw_hit_test_data.h" +#include "android_webview/common/renderer_picture_map.h" #include "android_webview/native/aw_browser_dependency_factory.h" #include "android_webview/native/aw_contents_io_thread_client_impl.h" #include "android_webview/native/aw_web_contents_delegate.h" -#include "android_webview/native/java_browser_view_renderer_helper.h" #include "android_webview/native/state_serializer.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/android/jni_array.h" #include "base/android/jni_string.h" #include "base/bind.h" #include "base/callback.h" +#include "base/debug/trace_event.h" #include "base/message_loop.h" #include "base/pickle.h" #include "base/string16.h" #include "base/supports_user_data.h" +#include "cc/layer.h" #include "components/navigation_interception/intercept_navigation_delegate.h" #include "content/public/browser/android/content_view_core.h" #include "content/public/browser/browser_thread.h" @@ -37,9 +41,25 @@ #include "content/public/common/ssl_status.h" #include "jni/AwContents_jni.h" #include "net/base/x509_certificate.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 "third_party/skia/include/core/SkGraphics.h" +#include "third_party/skia/include/core/SkPicture.h" #include "ui/gfx/android/java_bitmap.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 -struct AwDrawSWFunctionTable; +#ifndef GL_TEXTURE_BINDING_EXTERNAL_OES +#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67 +#endif using base::android::AttachCurrentThread; using base::android::ConvertJavaStringToUTF16; @@ -61,16 +81,61 @@ static void DrawGLFunction(int view_context, void* spare) { // |view_context| is the value that was returned from the java // AwContents.onPrepareDrawGL; this cast must match the code there. - reinterpret_cast<android_webview::BrowserViewRenderer*>(view_context)->DrawGL( + reinterpret_cast<android_webview::AwContents*>(view_context)->DrawGL( draw_info); } + +typedef base::Callback<bool(SkCanvas*)> RenderMethod; + +static bool RasterizeIntoBitmap(JNIEnv* env, + jobject jbitmap, + int scroll_x, + int scroll_y, + const RenderMethod& renderer) { + DCHECK(jbitmap); + + AndroidBitmapInfo bitmap_info; + if (AndroidBitmap_getInfo(env, jbitmap, &bitmap_info) < 0) { + LOG(WARNING) << "Error getting java bitmap info."; + return false; + } + + void* pixels = NULL; + if (AndroidBitmap_lockPixels(env, jbitmap, &pixels) < 0) { + LOG(WARNING) << "Error locking java bitmap pixels."; + return false; + } + + bool succeeded = false; + { + 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) < 0) { + LOG(WARNING) << "Error unlocking java bitmap pixels."; + return false; + } + + return succeeded; +} } namespace android_webview { namespace { -static JavaBrowserViewRendererHelper java_renderer_helper; +AwDrawSWFunctionTable* g_draw_sw_functions = NULL; +bool g_is_skia_version_compatible = false; const void* kAwContentsUserDataKey = &kAwContentsUserDataKey; @@ -115,8 +180,13 @@ AwContents::AwContents(JNIEnv* env, : java_ref_(env, obj), web_contents_delegate_( new AwWebContentsDelegate(env, web_contents_delegate)), - ALLOW_THIS_IN_INITIALIZER_LIST(browser_view_renderer_( - BrowserViewRendererImpl::Create(this, &java_renderer_helper))) { + view_visible_(false), + compositor_visible_(false), + is_composite_pending_(false), + dpi_scale_(1.0f), + on_new_picture_mode_(kOnNewPictureDisabled), + last_frame_context_(NULL) { + RendererPictureMap::CreateInstance(); android_webview::AwBrowserDependencyFactory* dependency_factory = android_webview::AwBrowserDependencyFactory::GetInstance(); @@ -126,6 +196,12 @@ AwContents::AwContents(JNIEnv* env, SetWebContents(dependency_factory->CreateWebContents()); } +void AwContents::ResetCompositor() { + compositor_.reset(content::Compositor::Create(this)); + if (scissor_clip_layer_.get()) + AttachLayerTree(); +} + void AwContents::SetWebContents(content::WebContents* web_contents) { web_contents_.reset(web_contents); if (find_helper_.get()) { @@ -135,8 +211,11 @@ void AwContents::SetWebContents(content::WebContents* web_contents) { icon_helper_->SetListener(this); web_contents_->SetUserData(kAwContentsUserDataKey, new AwContentsUserData(this)); + web_contents_->SetDelegate(web_contents_delegate_.get()); - render_view_host_ext_.reset(new AwRenderViewHostExt(web_contents_.get())); + render_view_host_ext_.reset(new AwRenderViewHostExt(web_contents_.get(), + this)); + ResetCompositor(); } void AwContents::SetWebContents(JNIEnv* env, jobject obj, jint new_wc) { @@ -152,6 +231,287 @@ AwContents::~AwContents() { icon_helper_->SetListener(NULL); } +void AwContents::DrawGL(AwDrawGLInfo* draw_info) { + + TRACE_EVENT0("AwContents", "AwContents::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()); + 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]); + + if (blend_enabled) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); + + glBlendFuncSeparate(blend_src_rgb, blend_dest_rgb, + blend_src_alpha, blend_dest_alpha); + + 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]); + + glUseProgram(current_program); + } + // --------------------------------------------------------------------------- +} + +bool AwContents::DrawSW(JNIEnv* env, + jobject obj, + jobject java_canvas, + jint clip_x, + jint clip_y, + jint clip_w, + jint clip_h) { + TRACE_EVENT0("AwContents", "AwContents::DrawSW"); + + if (clip_w <= 0 || clip_h <= 0) + return true; + + AwPixelInfo* pixels; + + // Render into an auxiliary bitmap if pixel info is not available. + if (!g_draw_sw_functions || + (pixels = g_draw_sw_functions->access_pixels(env, java_canvas)) == NULL) { + ScopedJavaLocalRef<jobject> jbitmap(Java_AwContents_createBitmap( + env, clip_w, clip_h)); + if (!jbitmap.obj()) + return false; + + if (!RasterizeIntoBitmap(env, jbitmap.obj(), clip_x, clip_y, + base::Bind(&AwContents::RenderSW, base::Unretained(this)))) + return false; + + Java_AwContents_drawBitmapIntoCanvas(env, jbitmap.obj(), java_canvas); + 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); + + 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); + } + + g_draw_sw_functions->release_pixels(pixels); + return succeeded; +} + jint AwContents::GetWebContents(JNIEnv* env, jobject obj) { return reinterpret_cast<jint>(web_contents_.get()); } @@ -160,7 +520,30 @@ void AwContents::DidInitializeContentViewCore(JNIEnv* env, jobject obj, jint content_view_core) { ContentViewCore* core = reinterpret_cast<ContentViewCore*>(content_view_core); DCHECK(core == ContentViewCore::FromWebContents(web_contents_.get())); - browser_view_renderer_->SetContents(core); + + dpi_scale_ = core->GetDpiScale(); + + // Ensures content keeps clipped within the view during transformations. + view_clip_layer_ = cc::Layer::create(); + view_clip_layer_->setBounds(view_size_); + view_clip_layer_->addChild(core->GetLayer()); + + // Applies the transformation matrix. + transform_layer_ = cc::Layer::create(); + transform_layer_->addChild(view_clip_layer_); + + // Ensures content is drawn within the scissor clip rect provided by the + // Android framework. + scissor_clip_layer_ = cc::Layer::create(); + scissor_clip_layer_->addChild(transform_layer_); + + AttachLayerTree(); +} + +void AwContents::AttachLayerTree() { + DCHECK(scissor_clip_layer_.get()); + compositor_->SetRootLayer(scissor_clip_layer_); + Invalidate(); } void AwContents::Destroy(JNIEnv* env, jobject obj) { @@ -169,8 +552,12 @@ void AwContents::Destroy(JNIEnv* env, jobject obj) { // static void SetAwDrawSWFunctionTable(JNIEnv* env, jclass, jint function_table) { - BrowserViewRendererImpl::SetAwDrawSWFunctionTable( - reinterpret_cast<AwDrawSWFunctionTable*>(function_table)); + g_draw_sw_functions = + reinterpret_cast<AwDrawSWFunctionTable*>(function_table); + g_is_skia_version_compatible = + g_draw_sw_functions->is_skia_version_compatible(&SkGraphics::GetVersion); + LOG_IF(WARNING, !g_is_skia_version_compatible) << + "Skia native versions are not compatible."; } // static @@ -178,10 +565,6 @@ jint GetAwDrawGLFunction(JNIEnv* env, jclass) { return reinterpret_cast<jint>(&DrawGLFunction); } -jint AwContents::GetAwDrawGLViewContext(JNIEnv* env, jobject obj) { - return reinterpret_cast<jint>(browser_view_renderer_.get()); -} - namespace { void DocumentHasImagesCallback(const ScopedJavaGlobalRef<jobject>& message, bool has_images) { @@ -507,18 +890,39 @@ void AwContents::OnReceivedTouchIconUrl(const std::string& url, env, obj.obj(), ConvertUTF8ToJavaString(env, url).obj(), precomposed); } +void AwContents::ScheduleComposite() { + TRACE_EVENT0("AwContents", "AwContents::ScheduleComposite"); + + if (is_composite_pending_) + return; + + is_composite_pending_ = true; + Invalidate(); +} + void AwContents::Invalidate() { JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); - if (!obj.is_null()) + if (obj.is_null()) + return; + + if (view_visible_) Java_AwContents_invalidate(env, obj.obj()); + + // When not in invalidation-only mode onNewPicture will be triggered + // from the OnPictureUpdated callback. + if (on_new_picture_mode_ == kOnNewPictureInvalidationOnly) + Java_AwContents_onNewPicture(env, obj.obj(), NULL); } -void AwContents::OnNewPicture(const JavaRef<jobject>& picture) { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); - if (!obj.is_null()) - Java_AwContents_onNewPicture(env, obj.obj(), picture.obj()); +void AwContents::SetCompositorVisibility(bool visible) { + if (compositor_visible_ != visible) { + compositor_visible_ = visible; + compositor_->SetVisible(compositor_visible_); + } +} + +void AwContents::OnSwapBuffersCompleted() { } base::android::ScopedJavaLocalRef<jbyteArray> @@ -582,21 +986,27 @@ void AwContents::UpdateLastHitTestData(JNIEnv* env, jobject obj) { void AwContents::OnSizeChanged(JNIEnv* env, jobject obj, int w, int h, int ow, int oh) { - browser_view_renderer_->OnSizeChanged(w, h); + view_size_ = gfx::Size(w, h); + if (view_clip_layer_.get()) + view_clip_layer_->setBounds(view_size_); } void AwContents::SetWindowViewVisibility(JNIEnv* env, jobject obj, bool window_visible, bool view_visible) { - browser_view_renderer_->OnVisibilityChanged(window_visible, view_visible); + view_visible_ = window_visible && view_visible; + Invalidate(); } void AwContents::OnAttachedToWindow(JNIEnv* env, jobject obj, int w, int h) { - browser_view_renderer_->OnAttachedToWindow(w, h); + view_size_ = gfx::Size(w, h); + if (view_clip_layer_.get()) + view_clip_layer_->setBounds(view_size_); } void AwContents::OnDetachedFromWindow(JNIEnv* env, jobject obj) { - browser_view_renderer_->OnDetachedFromWindow(); + view_visible_ = false; + SetCompositorVisibility(false); } base::android::ScopedJavaLocalRef<jbyteArray> @@ -629,20 +1039,9 @@ jboolean AwContents::RestoreFromOpaqueState( return RestoreFromPickle(&iterator, web_contents_.get()); } -bool AwContents::DrawSW(JNIEnv* env, - jobject obj, - jobject canvas, - jint clip_x, - jint clip_y, - jint clip_w, - jint clip_h) { - return browser_view_renderer_->DrawSW( - canvas, gfx::Rect(clip_x, clip_y, clip_w, clip_h)); -} - void AwContents::SetScrollForHWFrame(JNIEnv* env, jobject obj, int scroll_x, int scroll_y) { - browser_view_renderer_->SetScrollForHWFrame(scroll_x, scroll_y); + hw_rendering_scroll_ = gfx::Point(scroll_x, scroll_y); } void AwContents::SetPendingWebContentsForPopup( @@ -667,22 +1066,106 @@ jint AwContents::ReleasePopupWebContents(JNIEnv* env, jobject obj) { ScopedJavaLocalRef<jobject> AwContents::CapturePicture(JNIEnv* env, jobject obj) { - return browser_view_renderer_->CapturePicture(); + skia::RefPtr<SkPicture> picture = GetLastCapturedPicture(); + if (!picture || !g_draw_sw_functions) + return ScopedJavaLocalRef<jobject>(); + + if (g_is_skia_version_compatible) + return ScopedJavaLocalRef<jobject>(env, + g_draw_sw_functions->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_AwContents_createBitmap( + env, picture->width(), picture->height())); + if (!jbitmap.obj()) + return ScopedJavaLocalRef<jobject>(); + + if (!RasterizeIntoBitmap(env, jbitmap.obj(), 0, 0, + base::Bind(&AwContents::RenderPicture, base::Unretained(this)))) + return ScopedJavaLocalRef<jobject>(); + + return Java_AwContents_recordBitmapIntoPicture(env, jbitmap.obj()); +} + +bool AwContents::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); +} + +bool AwContents::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; } void AwContents::EnableOnNewPicture(JNIEnv* env, jobject obj, jboolean enabled, jboolean invalidation_only) { - BrowserViewRenderer::OnNewPictureMode mode = - BrowserViewRenderer::kOnNewPictureDisabled; if (enabled) { - mode = invalidation_only ? - BrowserViewRenderer::kOnNewPictureInvalidationOnly : - BrowserViewRenderer::kOnNewPictureEnabled; + on_new_picture_mode_ = invalidation_only ? kOnNewPictureInvalidationOnly : + kOnNewPictureEnabled; + } else { + on_new_picture_mode_ = kOnNewPictureDisabled; + } + + // If onNewPicture is triggered only on invalidation do not capture + // pictures on every new frame. + if (on_new_picture_mode_ == kOnNewPictureInvalidationOnly) + enabled = false; + + // 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); +} + +void AwContents::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) { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); + if (!obj.is_null()) { + ScopedJavaLocalRef<jobject> picture = CapturePicture(env, obj.obj()); + Java_AwContents_onNewPicture(env, obj.obj(), picture.obj()); + } + } + + // TODO(leandrogracia): delete when sw rendering uses Ubercompositor. + // Invalidation should be provided by the compositor only. + Invalidate(); +} + +skia::RefPtr<SkPicture> AwContents::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) { + render_view_host_ext_->CapturePictureSync(); + picture = RendererPictureMap::GetInstance()->GetRendererPicture( + web_contents_->GetRoutingID()); } - browser_view_renderer_->EnableOnNewPicture(mode); + return picture; } } // namespace android_webview diff --git a/android_webview/native/aw_contents.h b/android_webview/native/aw_contents.h index 889aaa8..78ababc 100644 --- a/android_webview/native/aw_contents.h +++ b/android_webview/native/aw_contents.h @@ -10,20 +10,29 @@ #include <string> #include <utility> -#include "android_webview/browser/browser_view_renderer.h" #include "android_webview/browser/find_helper.h" #include "android_webview/browser/icon_helper.h" #include "android_webview/browser/renderer_host/aw_render_view_host_ext.h" +#include "android_webview/public/browser/draw_gl.h" #include "base/android/scoped_java_ref.h" #include "base/android/jni_helper.h" #include "base/callback_forward.h" #include "base/memory/scoped_ptr.h" +#include "content/public/browser/android/compositor.h" #include "content/public/browser/javascript_dialog_manager.h" +#include "skia/ext/refptr.h" +#include "third_party/skia/include/core/SkPicture.h" +typedef void* EGLContext; class SkBitmap; class TabContents; +namespace cc { +class Layer; +} + namespace content { +class Compositor; class WebContents; } @@ -38,7 +47,8 @@ class AwWebContentsDelegate; // level of indirection provided by the AwContentsContainer abstraction. class AwContents : public FindHelper::Listener, public IconHelper::Listener, - public BrowserViewRenderer::Client { + public content::Compositor::Client, + public AwRenderViewHostExt::Client { public: enum OnNewPictureMode { kOnNewPictureDisabled = 0, @@ -62,6 +72,15 @@ class AwContents : public FindHelper::Listener, return render_view_host_ext_.get(); } + void DrawGL(AwDrawGLInfo* draw_info); + bool DrawSW(JNIEnv* env, + jobject obj, + jobject canvas, + jint clip_x, + jint clip_y, + jint clip_w, + jint clip_h); + void RunJavaScriptDialog( content::JavaScriptMessageType message_type, const GURL& origin_url, @@ -108,17 +127,9 @@ class AwContents : public FindHelper::Listener, base::android::ScopedJavaLocalRef<jbyteArray> GetOpaqueState( JNIEnv* env, jobject obj); jboolean RestoreFromOpaqueState(JNIEnv* env, jobject obj, jbyteArray state); - void FocusFirstNode(JNIEnv* env, jobject obj); - bool DrawSW(JNIEnv* env, - jobject obj, - jobject canvas, - jint clip_x, - jint clip_y, - jint clip_w, - jint clip_h); void SetScrollForHWFrame(JNIEnv* env, jobject obj, int scroll_x, int scroll_y); - jint GetAwDrawGLViewContext(JNIEnv* env, jobject obj); + void FocusFirstNode(JNIEnv* env, jobject obj); base::android::ScopedJavaLocalRef<jobject> CapturePicture(JNIEnv* env, jobject obj); void EnableOnNewPicture(JNIEnv* env, @@ -139,6 +150,8 @@ class AwContents : public FindHelper::Listener, void FindAllAsync(JNIEnv* env, jobject obj, jstring search_string); void FindNext(JNIEnv* env, jobject obj, jboolean forward); void ClearMatches(JNIEnv* env, jobject obj); + void ClearCache(JNIEnv* env, jobject obj, jboolean include_disk_files); + FindHelper* GetFindHelper(); // FindHelper::Listener implementation. @@ -150,17 +163,29 @@ class AwContents : public FindHelper::Listener, virtual void OnReceivedTouchIconUrl(const std::string& url, const bool precomposed) OVERRIDE; - // BrowserViewRenderer::Client implementation. - virtual void Invalidate() OVERRIDE; - virtual void OnNewPicture( - const base::android::JavaRef<jobject>& picture) OVERRIDE; + // content::Compositor::Client implementation. + virtual void ScheduleComposite() OVERRIDE; + virtual void OnSwapBuffersCompleted() OVERRIDE; - void ClearCache(JNIEnv* env, jobject obj, jboolean include_disk_files); void SetPendingWebContentsForPopup(scoped_ptr<content::WebContents> pending); jint ReleasePopupWebContents(JNIEnv* env, jobject obj); + // AwRenderViewHostExt::Client implementation. + virtual void OnPictureUpdated(int process_id, int render_view_id) OVERRIDE; + + // Returns the latest locally available picture if any. + // If none is available will synchronously request the latest one + // and block until the result is received. + skia::RefPtr<SkPicture> GetLastCapturedPicture(); + private: + void Invalidate(); void SetWebContents(content::WebContents* web_contents); + void SetCompositorVisibility(bool visible); + void ResetCompositor(); + void AttachLayerTree(); + bool RenderSW(SkCanvas* canvas); + bool RenderPicture(SkCanvas* canvas); JavaObjectWeakGlobalRef java_ref_; scoped_ptr<content::WebContents> web_contents_; @@ -169,7 +194,6 @@ class AwContents : public FindHelper::Listener, scoped_ptr<FindHelper> find_helper_; scoped_ptr<IconHelper> icon_helper_; scoped_ptr<content::WebContents> pending_contents_; - scoped_ptr<BrowserViewRenderer> browser_view_renderer_; // GURL is supplied by the content layer as requesting frame. // Callback is supplied by the content layer, and is invoked with the result @@ -178,6 +202,23 @@ class AwContents : public FindHelper::Listener, // The first element in the list is always the currently pending request. std::list<OriginCallback> pending_geolocation_prompts_; + // Compositor-specific state. + scoped_ptr<content::Compositor> compositor_; + scoped_refptr<cc::Layer> scissor_clip_layer_; + scoped_refptr<cc::Layer> transform_layer_; + scoped_refptr<cc::Layer> view_clip_layer_; + gfx::Point hw_rendering_scroll_; + gfx::Size view_size_; + bool view_visible_; + bool compositor_visible_; + bool is_composite_pending_; + float dpi_scale_; + OnNewPictureMode on_new_picture_mode_; + + // Used only for detecting Android View System context changes. + // Not to be used between draw calls. + EGLContext last_frame_context_; + DISALLOW_COPY_AND_ASSIGN(AwContents); }; diff --git a/android_webview/native/java_browser_view_renderer_helper.cc b/android_webview/native/java_browser_view_renderer_helper.cc deleted file mode 100644 index 1dfd9b2..0000000 --- a/android_webview/native/java_browser_view_renderer_helper.cc +++ /dev/null @@ -1,47 +0,0 @@ -// 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/native/java_browser_view_renderer_helper.h" - -#include "jni/JavaBrowserViewRendererHelper_jni.h" - -using base::android::JavaRef; -using base::android::ScopedJavaLocalRef; - -namespace android_webview { - -JavaBrowserViewRendererHelper::JavaBrowserViewRendererHelper() { -} - -JavaBrowserViewRendererHelper::~JavaBrowserViewRendererHelper() { -} - -ScopedJavaLocalRef<jobject> JavaBrowserViewRendererHelper::CreateBitmap( - JNIEnv* env, - int width, - int height) { - return Java_JavaBrowserViewRendererHelper_createBitmap(env, width, height); -} - -void JavaBrowserViewRendererHelper::DrawBitmapIntoCanvas( - JNIEnv* env, - const JavaRef<jobject>& jbitmap, - const JavaRef<jobject>& jcanvas) { - Java_JavaBrowserViewRendererHelper_drawBitmapIntoCanvas( - env, jbitmap.obj(), jcanvas.obj()); -} - -ScopedJavaLocalRef<jobject> -JavaBrowserViewRendererHelper::RecordBitmapIntoPicture( - JNIEnv* env, - const JavaRef<jobject>& jbitmap) { - return Java_JavaBrowserViewRendererHelper_recordBitmapIntoPicture( - env, jbitmap.obj()); -} - -bool RegisterJavaBrowserViewRendererHelper(JNIEnv* env) { - return RegisterNativesImpl(env) >= 0; -} - -} // namespace android_webview diff --git a/android_webview/native/java_browser_view_renderer_helper.h b/android_webview/native/java_browser_view_renderer_helper.h deleted file mode 100644 index d29be80..0000000 --- a/android_webview/native/java_browser_view_renderer_helper.h +++ /dev/null @@ -1,39 +0,0 @@ -// 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. - -#ifndef ANDROID_WEBVIEW_NATIVE_JAVA_BROWSER_VIEW_RENDERER_HELPER_H_ -#define ANDROID_WEBVIEW_NATIVE_JAVA_BROWSER_VIEW_RENDERER_HELPER_H_ - -#include "android_webview/browser/browser_view_renderer.h" -#include "base/android/scoped_java_ref.h" -#include "base/compiler_specific.h" - -namespace android_webview { - -// Native side of java-class of same name. -// Provides utility methods for rendering involving with Java objects. -class JavaBrowserViewRendererHelper : public BrowserViewRenderer::JavaHelper { - public: - JavaBrowserViewRendererHelper(); - virtual ~JavaBrowserViewRendererHelper(); - - // BrowserViewRenderer::JavaHelper implementation. - virtual base::android::ScopedJavaLocalRef<jobject> CreateBitmap( - JNIEnv* env, - int width, - int height) OVERRIDE; - virtual void DrawBitmapIntoCanvas( - JNIEnv* env, - const base::android::JavaRef<jobject>& jbitmap, - const base::android::JavaRef<jobject>& jcanvas) OVERRIDE; - virtual base::android::ScopedJavaLocalRef<jobject> RecordBitmapIntoPicture( - JNIEnv* env, - const base::android::JavaRef<jobject>& jbitmap) OVERRIDE; -}; - -bool RegisterJavaBrowserViewRendererHelper(JNIEnv* env); - -} // namespace android_webview - -#endif // ANDROID_WEBVIEW_NATIVE_JAVA_BROWSER_VIEW_RENDERER_HELPER_H_ diff --git a/android_webview/native/webview_native.gyp b/android_webview/native/webview_native.gyp index cb9562a..1290683 100644 --- a/android_webview/native/webview_native.gyp +++ b/android_webview/native/webview_native.gyp @@ -13,6 +13,7 @@ '../../base/base.gyp:base_static', '../../components/components.gyp:web_contents_delegate_android', '../../skia/skia.gyp:skia', + '../../ui/gl/gl.gyp:gl', 'android_webview_native_jni', ], 'include_dirs': [ @@ -51,8 +52,6 @@ 'input_stream_impl.h', 'intercepted_request_data_impl.cc', 'intercepted_request_data_impl.h', - 'java_browser_view_renderer_helper.cc', - 'java_browser_view_renderer_helper.h', 'js_result_handler.cc', 'js_result_handler.h', 'net_init_native_callback.cc', @@ -83,7 +82,6 @@ '../java/src/org/chromium/android_webview/AwSettings.java', '../java/src/org/chromium/android_webview/AwWebContentsDelegate.java', '../java/src/org/chromium/android_webview/InterceptedRequestData.java', - '../java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java', '../java/src/org/chromium/android_webview/JsResultHandler.java', ], 'variables': { diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc index a1995a3..9a8b21c 100644 --- a/android_webview/renderer/aw_content_renderer_client.cc +++ b/android_webview/renderer/aw_content_renderer_client.cc @@ -7,7 +7,6 @@ #include "android_webview/common/aw_resource.h" #include "android_webview/common/url_constants.h" #include "android_webview/renderer/aw_render_view_ext.h" -#include "android_webview/renderer/view_renderer.h" #include "base/utf_string_conversions.h" #include "components/visitedlink/renderer/visitedlink_slave.h" #include "content/public/renderer/render_thread.h" @@ -43,7 +42,6 @@ void AwContentRendererClient::RenderThreadStarted() { void AwContentRendererClient::RenderViewCreated( content::RenderView* render_view) { AwRenderViewExt::RenderViewCreated(render_view); - ViewRenderer::RenderViewCreated(render_view); } std::string AwContentRendererClient::GetDefaultEncoding() { diff --git a/android_webview/renderer/aw_render_view_ext.cc b/android_webview/renderer/aw_render_view_ext.cc index c895ed47..462553e39 100644 --- a/android_webview/renderer/aw_render_view_ext.cc +++ b/android_webview/renderer/aw_render_view_ext.cc @@ -129,9 +129,14 @@ void PopulateHitTestData(const GURL& absolute_link_url, AwRenderViewExt::AwRenderViewExt(content::RenderView* render_view) : content::RenderViewObserver(render_view) { render_view->GetWebView()->setPermissionClient(this); + // TODO(leandrogracia): remove when SW rendering uses Ubercompositor. + // Until then we need the callback enabled for SW mode invalidation. + // http://crbug.com/170086. + capture_picture_enabled_ = true; } AwRenderViewExt::~AwRenderViewExt() { + RendererPictureMap::GetInstance()->ClearRendererPicture(routing_id()); } // static @@ -144,6 +149,10 @@ bool AwRenderViewExt::OnMessageReceived(const IPC::Message& message) { IPC_BEGIN_MESSAGE_MAP(AwRenderViewExt, message) IPC_MESSAGE_HANDLER(AwViewMsg_DocumentHasImages, OnDocumentHasImagesRequest) IPC_MESSAGE_HANDLER(AwViewMsg_DoHitTest, OnDoHitTest) + IPC_MESSAGE_HANDLER(AwViewMsg_EnableCapturePictureCallback, + OnEnableCapturePictureCallback) + IPC_MESSAGE_HANDLER(AwViewMsg_CapturePictureSync, + OnCapturePictureSync) IPC_MESSAGE_HANDLER(AwViewMsg_SetTextZoomLevel, OnSetTextZoomLevel) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -218,6 +227,15 @@ void AwRenderViewExt::FocusedNodeChanged(const WebKit::WebNode& node) { Send(new AwViewHostMsg_UpdateHitTestData(routing_id(), data)); } +void AwRenderViewExt::DidCommitCompositorFrame() { + if (!capture_picture_enabled_) + return; + + skia::RefPtr<SkPicture> picture = render_view()->CapturePicture(); + RendererPictureMap::GetInstance()->SetRendererPicture(routing_id(), picture); + Send(new AwViewHostMsg_PictureUpdated(routing_id())); +} + void AwRenderViewExt::OnDoHitTest(int view_x, int view_y) { if (!render_view() || !render_view()->GetWebView()) return; @@ -239,6 +257,15 @@ void AwRenderViewExt::OnDoHitTest(int view_x, int view_y) { Send(new AwViewHostMsg_UpdateHitTestData(routing_id(), data)); } +void AwRenderViewExt::OnEnableCapturePictureCallback(bool enable) { + capture_picture_enabled_ = enable; +} + +void AwRenderViewExt::OnCapturePictureSync() { + RendererPictureMap::GetInstance()->SetRendererPicture( + routing_id(), render_view()->CapturePicture()); +} + void AwRenderViewExt::OnSetTextZoomLevel(double zoom_level) { if (!render_view() || !render_view()->GetWebView()) return; diff --git a/android_webview/renderer/aw_render_view_ext.h b/android_webview/renderer/aw_render_view_ext.h index 8cea6e4..49cee36 100644 --- a/android_webview/renderer/aw_render_view_ext.h +++ b/android_webview/renderer/aw_render_view_ext.h @@ -7,6 +7,7 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/memory/weak_ptr.h" #include "content/public/renderer/render_view_observer.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebPermissionClient.h" @@ -27,6 +28,9 @@ class AwRenderViewExt : public content::RenderViewObserver, public: static void RenderViewCreated(content::RenderView* render_view); + // Required to be public by IPC_MESSAGE_HANDLER for sync messages. + using content::RenderViewObserver::Send; + private: AwRenderViewExt(content::RenderView* render_view); virtual ~AwRenderViewExt(); @@ -36,11 +40,16 @@ class AwRenderViewExt : public content::RenderViewObserver, virtual void DidCommitProvisionalLoad(WebKit::WebFrame* frame, bool is_new_navigation) OVERRIDE; virtual void FocusedNodeChanged(const WebKit::WebNode& node) OVERRIDE; + virtual void DidCommitCompositorFrame() OVERRIDE; void OnDocumentHasImagesRequest(int id); void OnDoHitTest(int view_x, int view_y); + void OnEnableCapturePictureCallback(bool enable); + + void OnCapturePictureSync(); + void OnSetTextZoomLevel(double zoom_level); // WebKit::WebPermissionClient implementation. diff --git a/android_webview/renderer/view_renderer.cc b/android_webview/renderer/view_renderer.cc deleted file mode 100644 index dd0d7e7..0000000 --- a/android_webview/renderer/view_renderer.cc +++ /dev/null @@ -1,61 +0,0 @@ -// 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/renderer/view_renderer.h" - -#include "android_webview/common/render_view_messages.h" -#include "android_webview/common/renderer_picture_map.h" -#include "content/public/renderer/render_view.h" -#include "skia/ext/refptr.h" - -namespace android_webview { - -// static -void ViewRenderer::RenderViewCreated(content::RenderView* render_view) { - new ViewRenderer(render_view); // |render_view| takes ownership. -} - -ViewRenderer::ViewRenderer(content::RenderView* render_view) - : content::RenderViewObserver(render_view), - // TODO(leandrogracia): default to false when SW mode uses Ubercompositor. - // Until then we need picture updates enabled for SW mode invalidation. - // http://crbug.com/170086. - capture_picture_enabled_(true) { -} - -ViewRenderer::~ViewRenderer() { - RendererPictureMap::GetInstance()->ClearRendererPicture(routing_id()); -} - -bool ViewRenderer::OnMessageReceived(const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(ViewRenderer, message) - IPC_MESSAGE_HANDLER(AwViewMsg_EnableCapturePictureCallback, - OnEnableCapturePictureCallback) - IPC_MESSAGE_HANDLER(AwViewMsg_CapturePictureSync, - OnCapturePictureSync) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - -void ViewRenderer::DidCommitCompositorFrame() { - if (!capture_picture_enabled_) - return; - - skia::RefPtr<SkPicture> picture = render_view()->CapturePicture(); - RendererPictureMap::GetInstance()->SetRendererPicture(routing_id(), picture); - Send(new AwViewHostMsg_PictureUpdated(routing_id())); -} - -void ViewRenderer::OnEnableCapturePictureCallback(bool enable) { - capture_picture_enabled_ = enable; -} - -void ViewRenderer::OnCapturePictureSync() { - RendererPictureMap::GetInstance()->SetRendererPicture( - routing_id(), render_view()->CapturePicture()); -} - -} // namespace android_webview diff --git a/android_webview/renderer/view_renderer.h b/android_webview/renderer/view_renderer.h deleted file mode 100644 index 8c4ba8f..0000000 --- a/android_webview/renderer/view_renderer.h +++ /dev/null @@ -1,39 +0,0 @@ -// 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. - -#ifndef ANDROID_WEBVIEW_RENDERER_VIEW_RENDERER_H_ -#define ANDROID_WEBVIEW_RENDERER_VIEW_RENDERER_H_ - -#include "content/public/renderer/render_view_observer.h" - -namespace android_webview { - -// Render-process side of ViewRendererHost. -// Implements required interaction with content::RenderView. -class ViewRenderer : public content::RenderViewObserver { - public: - static void RenderViewCreated(content::RenderView* render_view); - - // Required to be public by IPC_MESSAGE_HANDLER. - using content::RenderViewObserver::Send; - - private: - ViewRenderer(content::RenderView* render_view); - virtual ~ViewRenderer(); - - // content::RenderViewObserver implementation. - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - virtual void DidCommitCompositorFrame() OVERRIDE; - - void OnEnableCapturePictureCallback(bool enable); - void OnCapturePictureSync(); - - bool capture_picture_enabled_; - - DISALLOW_COPY_AND_ASSIGN(ViewRenderer); -}; - -} // namespace android_webview - -#endif // ANDROID_WEBVIEW_RENDERER_VIEW_RENDERER_H_ |