Android: SurfaceTexture-based image transport
This is an interim solution for where the embedder cannot use a command buffer context running on the gpu thread for frontend rendering (i.e. for the browser compositor), for example draw functor/callback based UI drawing.
On Android, sharing GL resources across threads is not a given and SurfaceTexture is therefore the only compatible option.
TBR=jam@chromium.org for .gyp change
BUG=161409
Review URL: https://codereview.chromium.org/11343058
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@168332 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index bed4799..442e752 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -23,8 +23,11 @@
#include "third_party/khronos/GLES2/gl2ext.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebCompositorOutputSurface.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebSolidColorLayer.h"
#include "ui/gfx/android/java_bitmap.h"
#include "webkit/compositor_bindings/web_compositor_support_impl.h"
+#include "webkit/glue/webthread_impl.h"
+#include "webkit/gpu/webgraphicscontext3d_in_process_impl.h"
using webkit::WebCompositorSupportImpl;
@@ -37,6 +40,8 @@
static bool g_initialized = false;
static base::LazyInstance<WebCompositorSupportImpl> g_compositor_support =
LAZY_INSTANCE_INITIALIZER;
+static WebKit::WebThread* g_impl_thread = NULL;
+static bool g_use_direct_gl = false;
// Adapts a pure WebGraphicsContext3D into a WebCompositorOutputSurface.
class WebGraphicsContextToOutputSurfaceAdapter :
@@ -91,11 +96,20 @@
// static
void Compositor::Initialize() {
- g_compositor_support.Get().initialize(NULL);
+ DCHECK(!CompositorImpl::IsInitialized());
+ g_compositor_support.Get().initialize(g_impl_thread);
g_initialized = true;
}
// static
+void Compositor::InitializeWithFlags(uint32 flags) {
+ g_use_direct_gl = flags & DIRECT_CONTEXT_ON_DRAW_THREAD;
+ if (flags & ENABLE_COMPOSITOR_THREAD)
+ g_impl_thread = new webkit_glue::WebThreadImpl("Browser Compositor");
+ Compositor::Initialize();
+}
+
+// static
WebCompositorSupportImpl* CompositorImpl::CompositorSupport() {
DCHECK(g_initialized);
return g_compositor_support.Pointer();
@@ -106,6 +120,11 @@
return g_initialized;
}
+// static
+bool CompositorImpl::UsesDirectGL() {
+ return g_use_direct_gl;
+}
+
CompositorImpl::CompositorImpl(Compositor::Client* client)
: window_(NULL),
surface_id_(0),
@@ -135,7 +154,7 @@
ANativeWindow_release(window_);
window_ = NULL;
surface_id_ = 0;
- host_.reset();
+ SetVisible(false);
}
if (window) {
@@ -145,8 +164,14 @@
tracker->SetSurfaceHandle(
surface_id_,
gfx::GLSurfaceHandle(gfx::kDummyPluginWindow, false));
+ SetVisible(true);
+ }
+}
- DCHECK(!host_.get());
+void CompositorImpl::SetVisible(bool visible) {
+ if (!visible) {
+ host_.reset();
+ } else if (!host_.get()) {
WebKit::WebLayerTreeView::Settings settings;
settings.refreshRate = 60.0;
host_.reset(g_compositor_support.Get().createLayerTreeView(
@@ -243,28 +268,38 @@
}
WebKit::WebCompositorOutputSurface* CompositorImpl::createOutputSurface() {
- DCHECK(window_ && surface_id_);
- WebKit::WebGraphicsContext3D::Attributes attrs;
- attrs.shareResources = true;
- attrs.noAutomaticFlushes = true;
- GpuChannelHostFactory* factory = BrowserGpuChannelHostFactory::instance();
- GURL url("chrome://gpu/Compositor::createContext3D");
- base::WeakPtr<WebGraphicsContext3DSwapBuffersClient> swap_client;
- scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
- new WebGraphicsContext3DCommandBufferImpl(
- surface_id_,
- url,
- factory,
- swap_client));
- if (!context->Initialize(
- attrs,
- false,
- CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)) {
- LOG(ERROR) << "Failed to create 3D context for compositor.";
- return NULL;
+ if (g_use_direct_gl) {
+ WebKit::WebGraphicsContext3D::Attributes attrs;
+ attrs.shareResources = false;
+ attrs.noAutomaticFlushes = true;
+ scoped_ptr<webkit::gpu::WebGraphicsContext3DInProcessImpl> context(
+ webkit::gpu::WebGraphicsContext3DInProcessImpl::CreateForWindow(
+ attrs,
+ window_,
+ NULL));
+ return new WebGraphicsContextToOutputSurfaceAdapter(context.release());
+ } else {
+ DCHECK(window_ && surface_id_);
+ WebKit::WebGraphicsContext3D::Attributes attrs;
+ attrs.shareResources = true;
+ attrs.noAutomaticFlushes = true;
+ GpuChannelHostFactory* factory = BrowserGpuChannelHostFactory::instance();
+ GURL url("chrome://gpu/Compositor::createContext3D");
+ base::WeakPtr<WebGraphicsContext3DSwapBuffersClient> swap_client;
+ scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
+ new WebGraphicsContext3DCommandBufferImpl(surface_id_,
+ url,
+ factory,
+ swap_client));
+ if (!context->Initialize(
+ attrs,
+ false,
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)) {
+ LOG(ERROR) << "Failed to create 3D context for compositor.";
+ return NULL;
+ }
+ return new WebGraphicsContextToOutputSurfaceAdapter(context.release());
}
-
- return new WebGraphicsContextToOutputSurfaceAdapter(context.release());
}
void CompositorImpl::didRecreateOutputSurface(bool success) {
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h
index 379145a0..eebc6d1 100644
--- a/content/browser/renderer_host/compositor_impl_android.h
+++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -35,9 +35,13 @@
static webkit::WebCompositorSupportImpl* CompositorSupport();
static bool IsInitialized();
+ // Returns true if initialized with DIRECT_CONTEXT_ON_DRAW_THREAD.
+ static bool UsesDirectGL();
+
// Compositor implementation.
virtual void SetRootLayer(WebKit::WebLayer* root) OVERRIDE;
virtual void SetWindowSurface(ANativeWindow* window) OVERRIDE;
+ virtual void SetVisible(bool visible) OVERRIDE;
virtual void SetWindowBounds(const gfx::Size& size) OVERRIDE;
virtual bool CompositeAndReadback(
void *pixels, const gfx::Rect& rect) OVERRIDE;
diff --git a/content/browser/renderer_host/image_transport_factory_android.cc b/content/browser/renderer_host/image_transport_factory_android.cc
index deef500..a2b8f10e 100644
--- a/content/browser/renderer_host/image_transport_factory_android.cc
+++ b/content/browser/renderer_host/image_transport_factory_android.cc
@@ -6,40 +6,97 @@
#include "base/memory/singleton.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
+#include "content/browser/renderer_host/compositor_impl_android.h"
#include "content/common/gpu/gpu_process_launch_causes.h"
#include "content/common/gpu/client/gl_helper.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
+#include "webkit/gpu/webgraphicscontext3d_in_process_impl.h"
namespace content {
-// static
-ImageTransportFactoryAndroid* ImageTransportFactoryAndroid::GetInstance() {
- return Singleton<ImageTransportFactoryAndroid>::get();
+namespace {
+
+static ImageTransportFactoryAndroid* g_factory = NULL;
+
+class DirectGLImageTransportFactory : public ImageTransportFactoryAndroid {
+ public:
+ DirectGLImageTransportFactory();
+ virtual ~DirectGLImageTransportFactory();
+
+ virtual gfx::GLSurfaceHandle CreateSharedSurfaceHandle() OVERRIDE {
+ return gfx::GLSurfaceHandle();
+ }
+ virtual void DestroySharedSurfaceHandle(
+ const gfx::GLSurfaceHandle& handle) OVERRIDE {}
+ virtual uint32_t InsertSyncPoint() OVERRIDE { return 0; }
+ virtual WebKit::WebGraphicsContext3D* GetContext3D() OVERRIDE {
+ return context_.get();
+ }
+ virtual GLHelper* GetGLHelper() OVERRIDE { return NULL; }
+
+ private:
+ scoped_ptr<webkit::gpu::WebGraphicsContext3DInProcessImpl> context_;
+
+ DISALLOW_COPY_AND_ASSIGN(DirectGLImageTransportFactory);
+};
+
+DirectGLImageTransportFactory::DirectGLImageTransportFactory() {
+ WebKit::WebGraphicsContext3D::Attributes attrs;
+ attrs.shareResources = false;
+ attrs.noAutomaticFlushes = true;
+ context_.reset(
+ webkit::gpu::WebGraphicsContext3DInProcessImpl::CreateForWindow(
+ attrs,
+ NULL,
+ NULL));
}
-ImageTransportFactoryAndroid::ImageTransportFactoryAndroid() {
+DirectGLImageTransportFactory::~DirectGLImageTransportFactory() {
+}
+
+class CmdBufferImageTransportFactory : public ImageTransportFactoryAndroid {
+ public:
+ CmdBufferImageTransportFactory();
+ virtual ~CmdBufferImageTransportFactory();
+
+ virtual gfx::GLSurfaceHandle CreateSharedSurfaceHandle() OVERRIDE;
+ virtual void DestroySharedSurfaceHandle(
+ const gfx::GLSurfaceHandle& handle) OVERRIDE;
+ virtual uint32_t InsertSyncPoint() OVERRIDE;
+ virtual WebKit::WebGraphicsContext3D* GetContext3D() OVERRIDE {
+ return context_.get();
+ }
+ virtual GLHelper* GetGLHelper() OVERRIDE;
+
+ private:
+ scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context_;
+ scoped_ptr<GLHelper> gl_helper_;
+
+ DISALLOW_COPY_AND_ASSIGN(CmdBufferImageTransportFactory);
+};
+
+CmdBufferImageTransportFactory::CmdBufferImageTransportFactory() {
WebKit::WebGraphicsContext3D::Attributes attrs;
attrs.shareResources = true;
GpuChannelHostFactory* factory = BrowserGpuChannelHostFactory::instance();
GURL url("chrome://gpu/ImageTransportFactoryAndroid");
base::WeakPtr<WebGraphicsContext3DSwapBuffersClient> swap_client;
- context_.reset(
- new WebGraphicsContext3DCommandBufferImpl(
- 0, // offscreen
- url,
- factory,
- swap_client));
+ context_.reset(new WebGraphicsContext3DCommandBufferImpl(0, // offscreen
+ url,
+ factory,
+ swap_client));
context_->Initialize(
attrs,
false,
CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE);
}
-ImageTransportFactoryAndroid::~ImageTransportFactoryAndroid() {
+CmdBufferImageTransportFactory::~CmdBufferImageTransportFactory() {
}
-gfx::GLSurfaceHandle ImageTransportFactoryAndroid::CreateSharedSurfaceHandle() {
+gfx::GLSurfaceHandle
+CmdBufferImageTransportFactory::CreateSharedSurfaceHandle() {
if (!context_->makeContextCurrent()) {
NOTREACHED() << "Failed to make shared graphics context current";
return gfx::GLSurfaceHandle();
@@ -57,7 +114,7 @@
return handle;
}
-void ImageTransportFactoryAndroid::DestroySharedSurfaceHandle(
+void CmdBufferImageTransportFactory::DestroySharedSurfaceHandle(
const gfx::GLSurfaceHandle& handle) {
if (!context_->makeContextCurrent()) {
NOTREACHED() << "Failed to make shared graphics context current";
@@ -69,19 +126,35 @@
context_->finish();
}
-uint32_t ImageTransportFactoryAndroid::InsertSyncPoint() {
+uint32_t CmdBufferImageTransportFactory::InsertSyncPoint() {
return context_->insertSyncPoint();
}
-WebKit::WebGraphicsContext3D* ImageTransportFactoryAndroid::GetContext3D() {
- return context_.get();
-}
-
-GLHelper* ImageTransportFactoryAndroid::GetGLHelper() {
+GLHelper* CmdBufferImageTransportFactory::GetGLHelper() {
if (!gl_helper_.get())
gl_helper_.reset(new GLHelper(GetContext3D(), NULL));
return gl_helper_.get();
}
-} // namespace content
+} // anonymous namespace
+
+// static
+ImageTransportFactoryAndroid* ImageTransportFactoryAndroid::GetInstance() {
+ if (!g_factory) {
+ if (CompositorImpl::UsesDirectGL())
+ g_factory = new DirectGLImageTransportFactory();
+ else
+ g_factory = new CmdBufferImageTransportFactory();
+ }
+
+ return g_factory;
+}
+
+ImageTransportFactoryAndroid::ImageTransportFactoryAndroid() {
+}
+
+ImageTransportFactoryAndroid::~ImageTransportFactoryAndroid() {
+}
+
+} // namespace content
diff --git a/content/browser/renderer_host/image_transport_factory_android.h b/content/browser/renderer_host/image_transport_factory_android.h
index 34d9a584..669d516 100644
--- a/content/browser/renderer_host/image_transport_factory_android.h
+++ b/content/browser/renderer_host/image_transport_factory_android.h
@@ -8,32 +8,34 @@
#include "base/memory/scoped_ptr.h"
#include "ui/gfx/native_widget_types.h"
+namespace gfx {
+class GLShareGroup;
+}
+
namespace WebKit {
- class WebGraphicsContext3D;
+class WebGraphicsContext3D;
}
namespace content {
class GLHelper;
-class WebGraphicsContext3DCommandBufferImpl;
class ImageTransportFactoryAndroid {
public:
- ImageTransportFactoryAndroid();
- ~ImageTransportFactoryAndroid();
+ virtual ~ImageTransportFactoryAndroid();
static ImageTransportFactoryAndroid* GetInstance();
- gfx::GLSurfaceHandle CreateSharedSurfaceHandle();
- void DestroySharedSurfaceHandle(const gfx::GLSurfaceHandle& handle);
+ virtual gfx::GLSurfaceHandle CreateSharedSurfaceHandle() = 0;
+ virtual void DestroySharedSurfaceHandle(
+ const gfx::GLSurfaceHandle& handle) = 0;
- uint32_t InsertSyncPoint();
+ virtual uint32_t InsertSyncPoint() = 0;
- WebKit::WebGraphicsContext3D* GetContext3D();
- GLHelper* GetGLHelper();
+ virtual WebKit::WebGraphicsContext3D* GetContext3D() = 0;
+ virtual GLHelper* GetGLHelper() = 0;
- private:
- scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context_;
- scoped_ptr<GLHelper> gl_helper_;
+protected:
+ ImageTransportFactoryAndroid();
};
} // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index ae2fb837..8b4b59f 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -15,6 +15,7 @@
#include "content/browser/renderer_host/compositor_impl_android.h"
#include "content/browser/renderer_host/image_transport_factory_android.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/surface_texture_transport_client_android.h"
#include "content/common/android/device_info.h"
#include "content/common/gpu/client/gl_helper.h"
#include "content/common/gpu/gpu_messages.h"
@@ -22,6 +23,7 @@
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
#include "third_party/WebKit/Source/Platform/chromium/public/Platform.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebExternalTextureLayer.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebSize.h"
#include "ui/gfx/android/java_bitmap.h"
#include "webkit/compositor_bindings/web_compositor_support_impl.h"
@@ -55,16 +57,25 @@
content_view_core_(NULL),
ime_adapter_android_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
cached_background_color_(SK_ColorWHITE),
- texture_layer_(WebKit::WebExternalTextureLayer::create()),
texture_id_in_layer_(0) {
+ if (CompositorImpl::UsesDirectGL()) {
+ surface_texture_transport_.reset(new SurfaceTextureTransportClient());
+ layer_ = surface_texture_transport_->Initialize();
+ } else {
+ // TODO: Cannot use CompositorImpl::CompositorSupport() in unit tests.
+ texture_layer_.reset(WebKit::WebExternalTextureLayer::create());
+ layer_ = texture_layer_->layer();
+ }
+
host_->SetView(this);
SetContentViewCore(content_view_core);
// RenderWidgetHost is initialized as visible. If is_hidden_ is true, tell
// RenderWidgetHost to hide.
if (is_hidden_)
host_->WasHidden();
- texture_layer_->layer()->setOpaque(true);
- texture_layer_->layer()->setDrawsContent(!is_hidden_);
+
+ layer_->setOpaque(true);
+ layer_->setDrawsContent(!is_hidden_);
}
RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
@@ -116,6 +127,9 @@
}
void RenderWidgetHostViewAndroid::SetSize(const gfx::Size& size) {
+ if (surface_texture_transport_.get())
+ surface_texture_transport_->SetSize(size);
+
host_->WasResized();
}
@@ -229,13 +243,13 @@
if (content_view_core_)
is_hidden_ = false;
- texture_layer_->layer()->setDrawsContent(true);
+ layer_->setDrawsContent(true);
}
void RenderWidgetHostViewAndroid::Hide() {
is_hidden_ = true;
- texture_layer_->layer()->setDrawsContent(false);
+ layer_->setDrawsContent(false);
}
bool RenderWidgetHostViewAndroid::IsShowing() {
@@ -293,7 +307,7 @@
void RenderWidgetHostViewAndroid::Destroy() {
if (content_view_core_) {
- content_view_core_->RemoveWebLayer(texture_layer_->layer());
+ content_view_core_->RemoveWebLayer(layer_);
content_view_core_ = NULL;
}
@@ -378,7 +392,8 @@
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
int gpu_host_id) {
texture_layer_->setTextureId(params.surface_handle);
- texture_layer_->layer()->setBounds(params.size);
+ DCHECK(texture_layer_->layer() == layer_);
+ layer_->setBounds(params.size);
texture_id_in_layer_ = params.surface_handle;
texture_size_in_layer_ = params.size;
@@ -416,11 +431,17 @@
gfx::GLSurfaceHandle RenderWidgetHostViewAndroid::GetCompositingSurface() {
if (CompositorImpl::IsInitialized()) {
// The app uses the browser-side compositor.
- if (shared_surface_.is_null())
- shared_surface_ =
- ImageTransportFactoryAndroid::GetInstance()->
- CreateSharedSurfaceHandle();
- return shared_surface_;
+ if (surface_texture_transport_.get()) {
+ return surface_texture_transport_->GetCompositingSurface(
+ host_->surface_id());
+ } else {
+ if (shared_surface_.is_null()) {
+ shared_surface_ =
+ ImageTransportFactoryAndroid::GetInstance()->
+ CreateSharedSurfaceHandle();
+ }
+ return shared_surface_;
+ }
}
// On Android, we cannot generate a window handle that can be passed to the
@@ -542,11 +563,11 @@
void RenderWidgetHostViewAndroid::SetContentViewCore(
ContentViewCoreImpl* content_view_core) {
if (content_view_core_)
- content_view_core_->RemoveWebLayer(texture_layer_->layer());
+ content_view_core_->RemoveWebLayer(layer_);
content_view_core_ = content_view_core;
if (content_view_core_)
- content_view_core_->AttachWebLayer(texture_layer_->layer());
+ content_view_core_->AttachWebLayer(layer_);
}
void RenderWidgetHostViewAndroid::HasTouchEventHandlers(
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index 0f075cdc..44ed4078 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -12,7 +12,6 @@
#include "content/browser/renderer_host/ime_adapter_android.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "third_party/skia/include/core/SkColor.h"
-#include "third_party/WebKit/Source/Platform/chromium/public/WebExternalTextureLayer.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
#include "ui/gfx/size.h"
@@ -22,6 +21,8 @@
struct GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params;
namespace WebKit {
+class WebExternalTextureLayer;
+class WebLayer;
class WebTouchEvent;
class WebMouseEvent;
}
@@ -30,6 +31,7 @@
class ContentViewCoreImpl;
class RenderWidgetHost;
class RenderWidgetHostImpl;
+class SurfaceTextureTransportClient;
struct NativeWebKeyboardEvent;
// -----------------------------------------------------------------------------
@@ -162,6 +164,11 @@
// The texture layer for this view when using browser-side compositing.
scoped_ptr<WebKit::WebExternalTextureLayer> texture_layer_;
+ // The layer used for rendering the contents of this view.
+ // It is either owned by texture_layer_ or surface_texture_transport_
+ // depending on the mode.
+ WebKit::WebLayer* layer_;
+
// The most recent texture id that was pushed to the texture layer.
unsigned int texture_id_in_layer_;
@@ -172,6 +179,9 @@
// compositor) for this view.
gfx::GLSurfaceHandle shared_surface_;
+ // Used for image transport when needing to share resources across threads.
+ scoped_ptr<SurfaceTextureTransportClient> surface_texture_transport_;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAndroid);
};
diff --git a/content/browser/renderer_host/surface_texture_transport_client_android.cc b/content/browser/renderer_host/surface_texture_transport_client_android.cc
new file mode 100644
index 0000000..685ee4e
--- /dev/null
+++ b/content/browser/renderer_host/surface_texture_transport_client_android.cc
@@ -0,0 +1,100 @@
+// 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 "content/browser/renderer_host/surface_texture_transport_client_android.h"
+
+#include <android/native_window_jni.h>
+
+#include "base/bind.h"
+#include "content/browser/gpu/gpu_surface_tracker.h"
+#include "content/browser/renderer_host/compositor_impl_android.h"
+#include "content/browser/renderer_host/image_transport_factory_android.h"
+#include "content/common/android/surface_texture_bridge.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebVideoLayer.h"
+#include "webkit/compositor_bindings/web_compositor_support_impl.h"
+#include "webkit/media/webvideoframe_impl.h"
+
+namespace {
+
+static const uint32 kGLTextureExternalOES = 0x8D65;
+
+} // anonymous namespace
+
+namespace content {
+
+SurfaceTextureTransportClient::SurfaceTextureTransportClient()
+ : window_(NULL),
+ texture_id_(0) {
+}
+
+SurfaceTextureTransportClient::~SurfaceTextureTransportClient() {
+ if (window_)
+ ANativeWindow_release(window_);
+}
+
+WebKit::WebLayer* SurfaceTextureTransportClient::Initialize() {
+ // Use a SurfaceTexture to stream frames to the UI thread.
+ video_layer_.reset(
+ CompositorImpl::CompositorSupport()->createVideoLayer(this));
+ surface_texture_ = new SurfaceTextureBridge(0);
+ surface_texture_->SetFrameAvailableCallback(
+ base::Bind(
+ &SurfaceTextureTransportClient::OnSurfaceTextureFrameAvailable,
+ base::Unretained(this)));
+ surface_texture_->DetachFromGLContext();
+ return video_layer_->layer();
+}
+
+gfx::GLSurfaceHandle
+SurfaceTextureTransportClient::GetCompositingSurface(int surface_id) {
+ DCHECK(surface_id);
+ if (!window_)
+ window_ = surface_texture_->CreateSurface();
+
+ GpuSurfaceTracker::Get()->SetNativeWidget(surface_id, window_);
+ return gfx::GLSurfaceHandle(gfx::kDummyPluginWindow, false);
+}
+
+void SurfaceTextureTransportClient::SetSize(const gfx::Size& size) {
+ surface_texture_->SetDefaultBufferSize(size.width(), size.height());
+ video_layer_->layer()->setBounds(size);
+ video_frame_.reset();
+}
+
+WebKit::WebVideoFrame* SurfaceTextureTransportClient::getCurrentFrame() {
+ if (!texture_id_) {
+ WebKit::WebGraphicsContext3D* context =
+ ImageTransportFactoryAndroid::GetInstance()->GetContext3D();
+ context->makeContextCurrent();
+ texture_id_ = context->createTexture();
+ }
+ if (!video_frame_.get()) {
+ surface_texture_->AttachToGLContext(texture_id_);
+ const gfx::Size size = video_layer_->layer()->bounds();
+ video_frame_.reset(
+ new webkit_media::WebVideoFrameImpl(
+ media::VideoFrame::WrapNativeTexture(
+ texture_id_, kGLTextureExternalOES,
+ size,
+ gfx::Rect(gfx::Point(), size),
+ size,
+ base::TimeDelta(),
+ media::VideoFrame::ReadPixelsCB(),
+ base::Closure())));
+ }
+ surface_texture_->UpdateTexImage();
+
+ return video_frame_.get();
+}
+
+void SurfaceTextureTransportClient::putCurrentFrame(
+ WebKit::WebVideoFrame* frame) {
+}
+
+void SurfaceTextureTransportClient::OnSurfaceTextureFrameAvailable() {
+ video_layer_->layer()->invalidate();
+}
+
+} // namespace content
diff --git a/content/browser/renderer_host/surface_texture_transport_client_android.h b/content/browser/renderer_host/surface_texture_transport_client_android.h
new file mode 100644
index 0000000..26e87c5
--- /dev/null
+++ b/content/browser/renderer_host/surface_texture_transport_client_android.h
@@ -0,0 +1,51 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_SURFACE_TEXTURE_TRANSPORT_CLIENT_ANDROID_H_
+#define CONTENT_BROWSER_RENDERER_HOST_SURFACE_TEXTURE_TRANSPORT_CLIENT_ANDROID_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebVideoFrameProvider.h"
+#include "ui/gfx/native_widget_types.h"
+
+struct ANativeWindow;
+
+namespace WebKit {
+class WebLayer;
+class WebVideoLayer;
+}
+
+namespace content {
+class SurfaceTextureBridge;
+
+class SurfaceTextureTransportClient : public WebKit::WebVideoFrameProvider {
+ public:
+ SurfaceTextureTransportClient();
+ virtual ~SurfaceTextureTransportClient();
+
+ WebKit::WebLayer* Initialize();
+ gfx::GLSurfaceHandle GetCompositingSurface(int surface_id);
+ void SetSize(const gfx::Size& size);
+
+ // WebKit::WebVideoFrameProvider implementation.
+ virtual void setVideoFrameProviderClient(Client*) OVERRIDE {}
+ virtual WebKit::WebVideoFrame* getCurrentFrame() OVERRIDE;
+ virtual void putCurrentFrame(WebKit::WebVideoFrame* frame) OVERRIDE;
+
+ private:
+ void OnSurfaceTextureFrameAvailable();
+
+ scoped_ptr<WebKit::WebVideoLayer> video_layer_;
+ scoped_refptr<SurfaceTextureBridge> surface_texture_;
+ ANativeWindow* window_;
+ scoped_ptr<WebKit::WebVideoFrame> video_frame_;
+ uint32 texture_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(SurfaceTextureTransportClient);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_SURFACE_TEXTURE_TRANSPORT_CLIENT_ANDROID_H_
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index f4d91512..02cad6f 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -723,6 +723,8 @@
'browser/renderer_host/socket_stream_dispatcher_host.h',
'browser/renderer_host/socket_stream_host.cc',
'browser/renderer_host/socket_stream_host.h',
+ 'browser/renderer_host/surface_texture_transport_client_android.cc',
+ 'browser/renderer_host/surface_texture_transport_client_android.h',
'browser/renderer_host/sync_resource_handler.cc',
'browser/renderer_host/sync_resource_handler.h',
'browser/renderer_host/tap_suppression_controller_aura.cc',
diff --git a/content/public/browser/android/compositor.h b/content/public/browser/android/compositor.h
index 11c1dbd..998c22d 100644
--- a/content/public/browser/android/compositor.h
+++ b/content/public/browser/android/compositor.h
@@ -38,9 +38,22 @@
virtual ~Compositor() {}
// Performs the global initialization needed before any compositor
- // instance can be used.
+ // instance can be used. This should be called only once.
static void Initialize();
+ enum CompositorFlags {
+ // Creates a direct GL context on the thread that draws
+ // (i.e. main or impl thread).
+ DIRECT_CONTEXT_ON_DRAW_THREAD = 1,
+
+ // Runs the compositor in threaded mode.
+ ENABLE_COMPOSITOR_THREAD = 1 << 1,
+ };
+
+ // Initialize with flags. This should only be called once instead
+ // of Initialize().
+ static void InitializeWithFlags(uint32 flags);
+
// Creates and returns a compositor instance.
static Compositor* Create(Client* client);
@@ -50,6 +63,11 @@
// Set the output surface bounds.
virtual void SetWindowBounds(const gfx::Size& size) = 0;
+ // Sets the window visibility. When becoming invisible, resources will get
+ // freed and other calls into the compositor are not allowed until after
+ // having been made visible again.
+ virtual void SetVisible(bool visible) = 0;
+
// Set the output surface handle which the compositor renders into.
virtual void SetWindowSurface(ANativeWindow* window) = 0;
diff --git a/ui/gl/gl_context_android.cc b/ui/gl/gl_context_android.cc
index 66ab2c6..270c312 100644
--- a/ui/gl/gl_context_android.cc
+++ b/ui/gl/gl_context_android.cc
@@ -10,6 +10,7 @@
#include "ui/gl/gl_context_egl.h"
#include "ui/gl/gl_context_stub.h"
#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface.h"
namespace gfx {
@@ -21,7 +22,11 @@
if (GetGLImplementation() == kGLImplementationMockGL)
return scoped_refptr<GLContext>(new GLContextStub());
- scoped_refptr<GLContextEGL> context(new GLContextEGL(share_group));
+ scoped_refptr<GLContext> context;
+ if (compatible_surface->GetHandle())
+ context = new GLContextEGL(share_group);
+ else
+ context = new GLContextStub();
if (!context->Initialize(compatible_surface, gpu_preference))
return NULL;
return context;
diff --git a/ui/gl/gl_surface_android.cc b/ui/gl/gl_surface_android.cc
index 76002b7..e201ffd 100644
--- a/ui/gl/gl_surface_android.cc
+++ b/ui/gl/gl_surface_android.cc
@@ -13,6 +13,7 @@
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface_stub.h"
using ui::GetLastEGLErrorString;
@@ -46,8 +47,11 @@
switch (GetGLImplementation()) {
case kGLImplementationEGLGLES2: {
- scoped_refptr<GLSurface> surface = window ?
- new NativeViewGLSurfaceEGL(false, window) : new AndroidViewSurface();
+ scoped_refptr<GLSurface> surface;
+ if (window)
+ surface = new NativeViewGLSurfaceEGL(false, window);
+ else
+ surface = new GLSurfaceStub();
if (!surface->Initialize())
return NULL;
return surface;