summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--android_webview/android_webview.gyp4
-rw-r--r--android_webview/browser/browser_view_renderer_impl.cc25
-rw-r--r--android_webview/browser/browser_view_renderer_impl.h9
-rw-r--r--android_webview/browser/in_process_renderer/DEPS8
-rw-r--r--android_webview/browser/in_process_renderer/in_process_renderer_client.cc55
-rw-r--r--android_webview/browser/in_process_renderer/in_process_renderer_client.h27
-rw-r--r--android_webview/browser/in_process_renderer/in_process_view_renderer.cc45
-rw-r--r--android_webview/browser/in_process_renderer/in_process_view_renderer.h44
-rw-r--r--android_webview/lib/main/aw_main_delegate.cc42
-rw-r--r--android_webview/renderer/aw_content_renderer_client.cc15
-rw-r--r--android_webview/renderer/aw_content_renderer_client.h10
-rw-r--r--content/content_common.gypi2
-rw-r--r--content/content_renderer.gypi2
-rw-r--r--content/public/common/content_switches.cc5
-rw-r--r--content/public/common/content_switches.h1
-rw-r--r--content/public/renderer/android/OWNERS6
-rw-r--r--content/public/renderer/android/synchronous_compositor.h35
-rw-r--r--content/public/renderer/android/synchronous_compositor_client.h28
-rw-r--r--content/public/renderer/content_renderer_client.h9
-rw-r--r--content/renderer/android/synchronous_compositor_output_surface.cc69
-rw-r--r--content/renderer/android/synchronous_compositor_output_surface.h56
-rw-r--r--content/renderer/render_widget.cc14
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(