diff options
22 files changed, 461 insertions, 50 deletions
diff --git a/android_webview/android_webview.gyp b/android_webview/android_webview.gyp index 52c84ad..5ed9151 100644 --- a/android_webview/android_webview.gyp +++ b/android_webview/android_webview.gyp @@ -131,6 +131,10 @@ 'browser/gpu_memory_buffer_factory_impl.h', 'browser/gpu_memory_buffer_impl.cc', 'browser/gpu_memory_buffer_impl.h', + 'browser/in_process_renderer/in_process_renderer_client.cc', + 'browser/in_process_renderer/in_process_renderer_client.h', + 'browser/in_process_renderer/in_process_view_renderer.cc', + 'browser/in_process_renderer/in_process_view_renderer.h', 'browser/icon_helper.cc', 'browser/icon_helper.h', 'browser/input_stream.h', diff --git a/android_webview/browser/browser_view_renderer_impl.cc b/android_webview/browser/browser_view_renderer_impl.cc index 67612ac..94a59e1 100644 --- a/android_webview/browser/browser_view_renderer_impl.cc +++ b/android_webview/browser/browser_view_renderer_impl.cc @@ -6,15 +6,19 @@ #include <android/bitmap.h> +#include "android_webview/browser/in_process_renderer/in_process_view_renderer.h" +#include "android_webview/common/aw_switches.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/command_line.h" #include "base/debug/trace_event.h" #include "base/logging.h" #include "cc/layers/layer.h" #include "content/public/browser/android/content_view_core.h" #include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_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" @@ -117,6 +121,11 @@ class BrowserViewRendererImpl::UserData : public content::WebContents::Data { BrowserViewRendererImpl* BrowserViewRendererImpl::Create( BrowserViewRenderer::Client* client, JavaHelper* java_helper) { + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kMergeUIAndRendererCompositorThreads)) { + return new InProcessViewRenderer(client, java_helper); + } + return new BrowserViewRendererImpl(client, java_helper); } @@ -126,6 +135,15 @@ BrowserViewRendererImpl* BrowserViewRendererImpl::FromWebContents( return UserData::GetInstance(contents); } +// static +BrowserViewRendererImpl* BrowserViewRendererImpl::FromId(int render_process_id, + int render_view_id) { + const content::RenderViewHost* rvh = + content::RenderViewHost::FromID(render_process_id, render_view_id); + if (!rvh) return NULL; + return FromWebContents(content::WebContents::FromRenderViewHost(rvh)); +} + BrowserViewRendererImpl::BrowserViewRendererImpl( BrowserViewRenderer::Client* client, JavaHelper* java_helper) @@ -164,6 +182,11 @@ BrowserViewRendererImpl::~BrowserViewRendererImpl() { SetContents(NULL); } +void BrowserViewRendererImpl::BindSynchronousCompositor( + content::SynchronousCompositor* compositor) { + NOTREACHED(); // Must be handled by the InProcessViewRenderer +} + // static void BrowserViewRendererImpl::SetAwDrawSWFunctionTable( AwDrawSWFunctionTable* table) { @@ -364,6 +387,8 @@ bool BrowserViewRendererImpl::DrawSW(jobject java_canvas, } ScopedJavaLocalRef<jobject> BrowserViewRendererImpl::CapturePicture() { + // TODO(joth): reimplement this in terms of a call to RenderPicture (vitual + // method) passing in a recordingt canvas, rather than using the picture map. skia::RefPtr<SkPicture> picture = GetLastCapturedPicture(); if (!picture || !g_sw_draw_functions) return ScopedJavaLocalRef<jobject>(); diff --git a/android_webview/browser/browser_view_renderer_impl.h b/android_webview/browser/browser_view_renderer_impl.h index d9b0b06..459c7a3 100644 --- a/android_webview/browser/browser_view_renderer_impl.h +++ b/android_webview/browser/browser_view_renderer_impl.h @@ -22,6 +22,7 @@ class SkCanvas; class SkPicture; namespace content { +class SynchronousCompositor; class WebContents; } @@ -40,10 +41,15 @@ class BrowserViewRendererImpl JavaHelper* java_helper); static BrowserViewRendererImpl* FromWebContents( content::WebContents* contents); + static BrowserViewRendererImpl* FromId(int render_process_id, + int render_view_id); static void SetAwDrawSWFunctionTable(AwDrawSWFunctionTable* table); virtual ~BrowserViewRendererImpl(); + virtual void BindSynchronousCompositor( + content::SynchronousCompositor* compositor); + // BrowserViewRenderer implementation. virtual void SetContents( content::ContentViewCore* content_view_core) OVERRIDE; @@ -74,6 +80,8 @@ class BrowserViewRendererImpl BrowserViewRendererImpl(BrowserViewRenderer::Client* client, JavaHelper* java_helper); + virtual bool RenderPicture(SkCanvas* canvas); + private: class UserData; friend class UserData; @@ -88,7 +96,6 @@ class BrowserViewRendererImpl void ResetCompositor(); void Invalidate(); bool RenderSW(SkCanvas* canvas); - bool RenderPicture(SkCanvas* canvas); void OnFrameInfoUpdated(const gfx::SizeF& content_size, const gfx::Vector2dF& scroll_offset, diff --git a/android_webview/browser/in_process_renderer/DEPS b/android_webview/browser/in_process_renderer/DEPS new file mode 100644 index 0000000..51ebf0f --- /dev/null +++ b/android_webview/browser/in_process_renderer/DEPS @@ -0,0 +1,8 @@ +include_rules = [ + # In order to meet synchronous renderer requirements we need to make direct + # calls from android_webview/browser/in_process into some APIs that logically + # live in the renderer side. + "+android_webview/renderer/aw_content_renderer_client.h", + "+content/public/renderer/android", + # Include joth@chromium.org on the review for any additions to this file. +] diff --git a/android_webview/browser/in_process_renderer/in_process_renderer_client.cc b/android_webview/browser/in_process_renderer/in_process_renderer_client.cc new file mode 100644 index 0000000..5f16ae2 --- /dev/null +++ b/android_webview/browser/in_process_renderer/in_process_renderer_client.cc @@ -0,0 +1,55 @@ +// Copyright (c) 2012 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/in_process_renderer/in_process_renderer_client.h" + +#include "android_webview/browser/browser_view_renderer_impl.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_process_host.h" + +namespace android_webview { + +namespace { + +int GetInProcessRendererId() { + content::RenderProcessHost::iterator it = + content::RenderProcessHost::AllHostsIterator(); + if (it.IsAtEnd()) { + // There should always be one RPH in single process more. + NOTREACHED(); + return 0; + } + + int id = it.GetCurrentValue()->GetID(); + it.Advance(); + DCHECK(it.IsAtEnd()); // Not multiprocess compatible. + return id; +} + +} + +MessageLoop* InProcessRendererClient::OverrideCompositorMessageLoop() const { + MessageLoop* rv = content::BrowserThread::UnsafeGetMessageLoopForThread( + content::BrowserThread::UI); + DCHECK(rv); + return rv; +} + +void InProcessRendererClient::DidCreateSynchronousCompositor( + int render_view_id, + content::SynchronousCompositor* compositor) { + BrowserViewRendererImpl* view_renderer = + BrowserViewRendererImpl::FromId(GetInProcessRendererId(), render_view_id); + if (view_renderer) + view_renderer->BindSynchronousCompositor(compositor); +} + +bool InProcessRendererClient::ShouldCreateCompositorInputHandler() const { + // Compositor input handling will be performed by the renderer host + // when UI and compositor threads are merged, so we disable client compositor + // input handling in this case. + return false; +} + +} // namespace android_webview diff --git a/android_webview/browser/in_process_renderer/in_process_renderer_client.h b/android_webview/browser/in_process_renderer/in_process_renderer_client.h new file mode 100644 index 0000000..3c597d5 --- /dev/null +++ b/android_webview/browser/in_process_renderer/in_process_renderer_client.h @@ -0,0 +1,27 @@ +// 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_COMMON_IN_PROCESS_RENDERER_CLIENT_ +#define ANDROID_WEBVIEW_COMMON_IN_PROCESS_RENDERER_CLIENT_ + +#include "android_webview/renderer/aw_content_renderer_client.h" + +namespace android_webview { + +// Specialization of the Renderer client used in single process mode, to +// route various factory-like methods to browser/ side code (in general, +// this is only needed / allowed in order to meet synchronous rendering +// requirements). +class InProcessRendererClient : public AwContentRendererClient { + public: + virtual base::MessageLoop* OverrideCompositorMessageLoop() const OVERRIDE; + virtual void DidCreateSynchronousCompositor( + int render_view_id, + content::SynchronousCompositor* compositor) OVERRIDE; + virtual bool ShouldCreateCompositorInputHandler() const OVERRIDE; +}; + +} // android_webview + +#endif // ANDROID_WEBVIEW_COMMON_IN_PROCESS_RENDERER_CLIENT_ diff --git a/android_webview/browser/in_process_renderer/in_process_view_renderer.cc b/android_webview/browser/in_process_renderer/in_process_view_renderer.cc new file mode 100644 index 0000000..63ac223 --- /dev/null +++ b/android_webview/browser/in_process_renderer/in_process_view_renderer.cc @@ -0,0 +1,45 @@ +// 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/in_process_renderer/in_process_view_renderer.h" + +#include "base/logging.h" +#include "content/public/renderer/android/synchronous_compositor.h" + +namespace android_webview { + +InProcessViewRenderer::InProcessViewRenderer( + BrowserViewRenderer::Client* client, + JavaHelper* java_helper) + : BrowserViewRendererImpl(client, java_helper), + compositor_(NULL) { +} + +InProcessViewRenderer::~InProcessViewRenderer() { + if (compositor_) + compositor_->SetClient(NULL); +} + +void InProcessViewRenderer::BindSynchronousCompositor( + content::SynchronousCompositor* compositor) { + DCHECK(compositor && compositor_ != compositor); + if (compositor_) + compositor_->SetClient(NULL); + compositor_ = compositor; + compositor_->SetClient(this); +} + +bool InProcessViewRenderer::RenderPicture(SkCanvas* canvas) { + return compositor_ && compositor_->DemandDrawSw(canvas); +} + +void InProcessViewRenderer::DidDestroyCompositor( + content::SynchronousCompositor* compositor) { + // Allow for transient hand-over when two compositors may reference + // a single client. + if (compositor_ == compositor) + compositor_ = NULL; +} + +} // namespace android_webview diff --git a/android_webview/browser/in_process_renderer/in_process_view_renderer.h b/android_webview/browser/in_process_renderer/in_process_view_renderer.h new file mode 100644 index 0000000..d2c0c24 --- /dev/null +++ b/android_webview/browser/in_process_renderer/in_process_view_renderer.h @@ -0,0 +1,44 @@ +// 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_IN_PROCESS_IN_PROCESS_VIEW_RENDERER_H_ +#define ANDROID_WEBVIEW_BROWSER_IN_PROCESS_IN_PROCESS_VIEW_RENDERER_H_ + +#include "android_webview/browser/browser_view_renderer_impl.h" + +#include "content/public/renderer/android/synchronous_compositor_client.h" + +namespace content { +class SynchronousCompositor; +} + +namespace android_webview { + +// Provides RenderViewHost wrapper functionality for sending WebView-specific +// IPC messages to the renderer and from there to WebKit. +class InProcessViewRenderer : public BrowserViewRendererImpl, + public content::SynchronousCompositorClient { + public: + InProcessViewRenderer(BrowserViewRenderer::Client* client, + JavaHelper* java_helper); + virtual ~InProcessViewRenderer(); + + // BrowserViewRenderer overrides + virtual void BindSynchronousCompositor( + content::SynchronousCompositor* compositor) OVERRIDE; + virtual bool RenderPicture(SkCanvas* canvas) OVERRIDE; + + // SynchronousCompositorClient overrides + virtual void DidDestroyCompositor( + content::SynchronousCompositor* compositor) OVERRIDE; + + private: + content::SynchronousCompositor* compositor_; + + DISALLOW_COPY_AND_ASSIGN(InProcessViewRenderer); +}; + +} // namespace android_webview + +#endif // ANDROID_WEBVIEW_BROWSER_IN_PROCESS_IN_PROCESS_VIEW_RENDERER_H_ diff --git a/android_webview/lib/main/aw_main_delegate.cc b/android_webview/lib/main/aw_main_delegate.cc index 45207ae..be63a82 100644 --- a/android_webview/lib/main/aw_main_delegate.cc +++ b/android_webview/lib/main/aw_main_delegate.cc @@ -5,6 +5,7 @@ #include "android_webview/lib/main/aw_main_delegate.h" #include "android_webview/browser/aw_content_browser_client.h" +#include "android_webview/browser/in_process_renderer/in_process_renderer_client.h" #include "android_webview/common/aw_switches.h" #include "android_webview/lib/aw_browser_dependency_factory_impl.h" #include "android_webview/native/aw_geolocation_permission_context.h" @@ -29,9 +30,13 @@ AwMainDelegate::~AwMainDelegate() { bool AwMainDelegate::BasicStartupComplete(int* exit_code) { content::SetContentClient(&content_client_); - CommandLine* command_line = CommandLine::ForCurrentProcess(); + CommandLine* cl = CommandLine::ForCurrentProcess(); // Set the command line to enable synchronous API compatibility. - command_line->AppendSwitch(switches::kEnableWebViewSynchronousAPIs); + if (cl->HasSwitch(switches::kMergeUIAndRendererCompositorThreads)) { + cl->AppendSwitch(switches::kEnableSynchronousRendererCompositor); + } else { + cl->AppendSwitch(switches::kEnableWebViewSynchronousAPIs); + } return false; } @@ -75,33 +80,18 @@ content::ContentBrowserClient* return content_browser_client_.get(); } -namespace { -bool UIAndRendererCompositorThreadsMerged() { - return CommandLine::ForCurrentProcess()->HasSwitch( - switches::kMergeUIAndRendererCompositorThreads); -} - -MessageLoop* GetRendererCompositorThreadOverrideLoop() { - if (!UIAndRendererCompositorThreadsMerged()) - return NULL; - - base::MessageLoop* rv = content::BrowserThread::UnsafeGetMessageLoopForThread( - content::BrowserThread::UI); - DCHECK(rv); - return rv; -} -} - content::ContentRendererClient* AwMainDelegate::CreateContentRendererClient() { - // Compositor input handling will be performed by the renderer host - // when UI and compositor threads are merged, so we disable client compositor - // input handling in this case. - const bool enable_client_compositor_input_handling = - !UIAndRendererCompositorThreadsMerged(); + // None of this makes sense for multiprocess. + DCHECK(CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess)); + // During transition period allow running in either threading mode; eventually + // only the compositor/UI thread merge mode will be supported. + const bool merge_threads = + CommandLine::ForCurrentProcess()->HasSwitch( + switches::kMergeUIAndRendererCompositorThreads); content_renderer_client_.reset( - new AwContentRendererClient(&GetRendererCompositorThreadOverrideLoop, - enable_client_compositor_input_handling)); + merge_threads ? new InProcessRendererClient() : + new AwContentRendererClient()); return content_renderer_client_.get(); } diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc index 9429c96..3d4790f 100644 --- a/android_webview/renderer/aw_content_renderer_client.cc +++ b/android_webview/renderer/aw_content_renderer_client.cc @@ -21,12 +21,7 @@ namespace android_webview { -AwContentRendererClient::AwContentRendererClient( - CompositorMessageLoopGetter* compositor_message_loop_getter, - bool should_create_compositor_input_handler) - : compositor_message_loop_getter_(compositor_message_loop_getter), - should_create_compositor_input_handler_( - should_create_compositor_input_handler) { +AwContentRendererClient::AwContentRendererClient() { } AwContentRendererClient::~AwContentRendererClient() { @@ -100,12 +95,4 @@ void AwContentRendererClient::PrefetchHostName(const char* hostname, // Perhaps componentize chrome implementation or move to content/? } -MessageLoop* AwContentRendererClient::OverrideCompositorMessageLoop() const { - return (*compositor_message_loop_getter_)(); -} - -bool AwContentRendererClient::ShouldCreateCompositorInputHandler() const { - return should_create_compositor_input_handler_; -} - } // namespace android_webview diff --git a/android_webview/renderer/aw_content_renderer_client.h b/android_webview/renderer/aw_content_renderer_client.h index bcec659..1249c22 100644 --- a/android_webview/renderer/aw_content_renderer_client.h +++ b/android_webview/renderer/aw_content_renderer_client.h @@ -18,11 +18,7 @@ namespace android_webview { class AwContentRendererClient : public content::ContentRendererClient { public: - typedef base::MessageLoop* CompositorMessageLoopGetter(); - - explicit AwContentRendererClient( - CompositorMessageLoopGetter* compositor_message_loop_getter, - bool should_create_compositor_input_handler); + AwContentRendererClient(); virtual ~AwContentRendererClient(); // ContentRendererClient implementation. @@ -41,14 +37,10 @@ class AwContentRendererClient : public content::ContentRendererClient { size_t length) OVERRIDE; virtual bool IsLinkVisited(unsigned long long link_hash) OVERRIDE; virtual void PrefetchHostName(const char* hostname, size_t length) OVERRIDE; - virtual base::MessageLoop* OverrideCompositorMessageLoop() const OVERRIDE; - virtual bool ShouldCreateCompositorInputHandler() const OVERRIDE; private: scoped_ptr<AwRenderProcessObserver> aw_render_process_observer_; scoped_ptr<components::VisitedLinkSlave> visited_link_slave_; - CompositorMessageLoopGetter* compositor_message_loop_getter_; - bool should_create_compositor_input_handler_; }; } // namespace android_webview diff --git a/content/content_common.gypi b/content/content_common.gypi index e0558e9..57b47ba 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi @@ -22,6 +22,8 @@ '../base/base.gyp:base', ], 'sources': [ + 'public/common/android/synchronous_compositor_client.h', + 'public/common/android/synchronous_compositor.h', 'public/common/bindings_policy.h', 'public/common/child_process_host.h', 'public/common/child_process_host_delegate.cc', diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index ec70560..20acfb7 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi @@ -66,6 +66,8 @@ 'renderer/android/email_detector.h', 'renderer/android/phone_number_detector.cc', 'renderer/android/phone_number_detector.h', + 'renderer/android/synchronous_compositor_output_surface.cc', + 'renderer/android/synchronous_compositor_output_surface.h', 'renderer/device_orientation_dispatcher.cc', 'renderer/device_orientation_dispatcher.h', 'renderer/devtools/devtools_agent.cc', diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index 8929515..208e4e1 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc @@ -437,6 +437,11 @@ const char kForceCompositingMode[] = "force-compositing-mode"; // via field trials. const char kDisableForceCompositingMode[] = "disable-force-compositing-mode"; +// Enable the synchronous renderer compositor API. See +// ContentRendererClient::DidCreateSynchronousCompositor() +const char kEnableSynchronousRendererCompositor[] = + "enable-synchronous-renderer-compositor"; + // Some field trials may be randomized in the browser, and the randomly selected // outcome needs to be propagated to the renderer. For instance, this is used // to modify histograms recorded in the renderer, or to get the renderer to diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index 4692f9e..fd750b7 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h @@ -130,6 +130,7 @@ CONTENT_EXPORT extern const char kEnableSoftwareCompositingGLAdapter[]; CONTENT_EXPORT extern const char kEnableSmoothScrolling[]; CONTENT_EXPORT extern const char kEnableStatsTable[]; extern const char kEnableStrictSiteIsolation[]; +extern const char kEnableSynchronousRendererCompositor[]; CONTENT_EXPORT extern const char kEnableThreadedCompositing[]; CONTENT_EXPORT extern const char kDisableThreadedCompositing[]; extern const char kEnableVirtualGLContexts[]; diff --git a/content/public/renderer/android/OWNERS b/content/public/renderer/android/OWNERS new file mode 100644 index 0000000..cff1ac9 --- /dev/null +++ b/content/public/renderer/android/OWNERS @@ -0,0 +1,6 @@ +# While the SynchronousCompositor API is in active development include +# all the following owners in any changes under this path. + +jamesr@chromium.org +joth@chromium.org +mkosiba@chromium.org diff --git a/content/public/renderer/android/synchronous_compositor.h b/content/public/renderer/android/synchronous_compositor.h new file mode 100644 index 0000000..f0c380d --- /dev/null +++ b/content/public/renderer/android/synchronous_compositor.h @@ -0,0 +1,35 @@ +// 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 CONTENT_PUBLIC_RENDERER_ANDROID_SYNCHRONOUS_COMPOSTIOR_ +#define CONTENT_PUBLIC_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_ + +class SkCanvas; + +namespace content { + +class SynchronousCompositorClient; + +// Interface for embedders that which to direct compositing operations +// synchronously under their own control. Only meaningful when the +// kEnableSyncrhonousRendererCompositor flag is specified. +class SynchronousCompositor { + public: + // Allows changing or resetting the client to NULL (this must be used if + // the client is being deleted prior to the DidDestroyCompositor() call + // being received by the client). Ownership of |client| remains with + // the caller. + virtual void SetClient(SynchronousCompositorClient* client) = 0; + + // "On demand" SW draw, into the supplied canvas (observing the transform + // and clip set there-in). + virtual bool DemandDrawSw(SkCanvas* canvas) = 0; + + protected: + virtual ~SynchronousCompositor() {} +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_RENDERER_ANDROID_SYNCHRONOUS_COMPOSTIOR_ diff --git a/content/public/renderer/android/synchronous_compositor_client.h b/content/public/renderer/android/synchronous_compositor_client.h new file mode 100644 index 0000000..dcbe09a --- /dev/null +++ b/content/public/renderer/android/synchronous_compositor_client.h @@ -0,0 +1,28 @@ +// 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 CONTENT_PUBLIC_RENDERER_ANDROID_SYNCHRONOUS_COMPOSTIOR_CLIENT_H_ +#define CONTENT_PUBLIC_RENDERER_ANDROID_SYNCRHONOUS_COMPOSITOR_CLIENT_H_ + +namespace content { + +class SynchronousCompositor; + +class SynchronousCompositorClient { + public: + // Indication to the client that |compositor| is going out of scope, and + // must not be accessed within or after this call. + // NOTE if the client goes away before the compositor it must call + // SynchronousCompositor::SetClient(NULL) to release the back pointer. + virtual void DidDestroyCompositor(SynchronousCompositor* compositor) = 0; + + // TODO(joth): Add scroll getters and setters, and invalidations. + + protected: + virtual ~SynchronousCompositorClient() {} +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_RENDERER_ANDROID_SYNCHRONOUS_COMPOSTIOR_CLIENT_H_ diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h index 653d38c..84b6d58 100644 --- a/content/public/renderer/content_renderer_client.h +++ b/content/public/renderer/content_renderer_client.h @@ -59,6 +59,7 @@ class WebMediaPlayerParams; namespace content { class RenderView; +class SynchronousCompositor; // Embedder API for participating in renderer logic. class CONTENT_EXPORT ContentRendererClient { @@ -234,6 +235,14 @@ class CONTENT_EXPORT ContentRendererClient { // RenderThreadImpl. If NULL, then a new thread will be created. virtual base::MessageLoop* OverrideCompositorMessageLoop() const; + // Called when a render view's compositor instance is created, when the + // kEnableSynchronousRendererCompositor flag is used. + // NOTE this is called on the Compositor thread: the embedder must + // implement OverrideCompositorMessageLoop() when using this interface. + virtual void DidCreateSynchronousCompositor( + int render_view_id, + SynchronousCompositor* compositor) {} + // Allow the embedder to disable input event filtering by the compositor. virtual bool ShouldCreateCompositorInputHandler() const; }; diff --git a/content/renderer/android/synchronous_compositor_output_surface.cc b/content/renderer/android/synchronous_compositor_output_surface.cc new file mode 100644 index 0000000..87792ea --- /dev/null +++ b/content/renderer/android/synchronous_compositor_output_surface.cc @@ -0,0 +1,69 @@ +// 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 "content/renderer/android/synchronous_compositor_output_surface.h" + +#include "base/logging.h" +#include "cc/output/output_surface_client.h" +#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" +#include "content/public/renderer/android/synchronous_compositor_client.h" +#include "content/public/renderer/content_renderer_client.h" +#include "skia/ext/refptr.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkPicture.h" + +namespace content { + +SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface( + int32 routing_id, + WebGraphicsContext3DCommandBufferImpl* context) + : cc::OutputSurface(scoped_ptr<WebKit::WebGraphicsContext3D>(context)), + compositor_client_(NULL), + routing_id_(routing_id) { + // WARNING: may be called on any thread. +} + +SynchronousCompositorOutputSurface::~SynchronousCompositorOutputSurface() { + DCHECK(CalledOnValidThread()); + if (compositor_client_) + compositor_client_->DidDestroyCompositor(this); +} + +bool SynchronousCompositorOutputSurface::BindToClient( + cc::OutputSurfaceClient* surface_client) { + DCHECK(CalledOnValidThread()); + if (!cc::OutputSurface::BindToClient(surface_client)) + return false; + GetContentClient()->renderer()->DidCreateSynchronousCompositor(routing_id_, + this); + return true; +} + +void SynchronousCompositorOutputSurface::SendFrameToParentCompositor( + cc::CompositorFrame* frame) { + // Intentional no-op: see http://crbug.com/237006 +} + +void SynchronousCompositorOutputSurface::SetClient( + SynchronousCompositorClient* compositor_client) { + DCHECK(CalledOnValidThread()); + compositor_client_ = compositor_client; +} + +bool SynchronousCompositorOutputSurface::DemandDrawSw(SkCanvas* canvas) { + DCHECK(CalledOnValidThread()); + NOTIMPLEMENTED(); // TODO(joth): call through to OutputSurfaceClient + return false; +} + +// Not using base::NonThreadSafe as we want to enforce a more exacting threading +// requirement: SynchronousCompositorOutputSurface() must only be used by +// embedders that supply their own compositor loop via +// OverrideCompositorMessageLoop(). +bool SynchronousCompositorOutputSurface::CalledOnValidThread() const { + return base::MessageLoop::current() && (base::MessageLoop::current() == + GetContentClient()->renderer()->OverrideCompositorMessageLoop()); +} + +} // namespace content diff --git a/content/renderer/android/synchronous_compositor_output_surface.h b/content/renderer/android/synchronous_compositor_output_surface.h new file mode 100644 index 0000000..04af44f --- /dev/null +++ b/content/renderer/android/synchronous_compositor_output_surface.h @@ -0,0 +1,56 @@ +// 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 CONTENT_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_OUTPUT_SURFACE_H_ +#define CONTENT_RENDERER_ANDOIRD_SYNCHRONOUS_COMPOSITOR_OUTPUT_SURFACE_H_ + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "cc/output/output_surface.h" +#include "content/public/renderer/android/synchronous_compositor.h" + +namespace content { + +class SynchronousCompositorClient; +class WebGraphicsContext3DCommandBufferImpl; + +// Specialization of the output surface that adapts it to implement the +// content::SynchronousCompositor public API. This class effects an "inversion +// of control" - enabling drawing to be orchestrated by the embedding +// layer, instead of driven by the compositor internals - hence it holds two +// 'client' pointers (including |client_| in the OutputSurface baseclass) which +// represent the consumers of the two roles in plays. +// This class can be created only on the main thread, but then becomes pinned +// to a fixed thread when BindToClient is called. +class SynchronousCompositorOutputSurface + : NON_EXPORTED_BASE(public cc::OutputSurface), + NON_EXPORTED_BASE(public SynchronousCompositor) { + public: + SynchronousCompositorOutputSurface( + int32 routing_id, + WebGraphicsContext3DCommandBufferImpl* context); + virtual ~SynchronousCompositorOutputSurface(); + + // OutputSurface. + virtual bool BindToClient(cc::OutputSurfaceClient* surface_client) OVERRIDE; + virtual void SendFrameToParentCompositor(cc::CompositorFrame* frame) OVERRIDE; + + // SynchronousCompositor. + virtual void SetClient(SynchronousCompositorClient* compositor_client) + OVERRIDE; + virtual bool DemandDrawSw(SkCanvas* canvas) OVERRIDE; + + private: + bool CalledOnValidThread() const; + + SynchronousCompositorClient* compositor_client_; + int routing_id_; + + DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorOutputSurface); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_OUTPUT_SURFACE_H_ diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index f8d3137..b681e5d 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc @@ -58,6 +58,10 @@ #include "webkit/plugins/npapi/webplugin.h" #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" +#if defined(OS_ANDROID) +#include "content/renderer/android/synchronous_compositor_output_surface.h" +#endif + #if defined(OS_POSIX) #include "ipc/ipc_channel_posix.h" #include "third_party/skia/include/core/SkMallocPixelRef.h" @@ -581,6 +585,16 @@ scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface() { if (!context) return scoped_ptr<cc::OutputSurface>(); +#if defined(OS_ANDROID) + if (command_line.HasSwitch(switches::kEnableSynchronousRendererCompositor)) { + // TODO(joth): Move above the |context| creation step above when the + // SynchronousCompositor no longer depends on externally created context. + return scoped_ptr<cc::OutputSurface>( + new SynchronousCompositorOutputSurface(routing_id(), + context)); + } +#endif + bool composite_to_mailbox = command_line.HasSwitch(cc::switches::kCompositeToMailbox); DCHECK(!composite_to_mailbox || command_line.HasSwitch( |