diff options
author | sievers@chromium.org <sievers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-22 18:54:08 +0000 |
---|---|---|
committer | sievers@chromium.org <sievers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-22 18:54:08 +0000 |
commit | 3a59bb92550acf8bf455007bb482f573a05d9448 (patch) | |
tree | adfb58aacf28aa0a4f4bde2e59df1839d89d4e34 | |
parent | b7d060862667150a87fc90939d79aec35a2c0c01 (diff) | |
download | chromium_src-3a59bb92550acf8bf455007bb482f573a05d9448.zip chromium_src-3a59bb92550acf8bf455007bb482f573a05d9448.tar.gz chromium_src-3a59bb92550acf8bf455007bb482f573a05d9448.tar.bz2 |
Support stream textures with the synchronous compositor
This adds a thread-safe StreamTextureManager for GLInProcessContext.
It further adds some plumbing for the webkit thread to be able
to create a StreamTextureFactory from the main thread (see render_view_impl.cc)
with the ability to extract the thread-safe SurfaceTexture(Bridge) for a given stream.
This is nothing but a crazy amount of plumbing to achieve this:
- StreamTexture::Update() i.e. SurfaceTexture::updateTexImage needs to happen on the GL thread
with a current context
- The StreamTextureFactory and Proxy are referenced from the WebmediaPlayer instance which lives on
the main thread
- The callback for invalidating the video is posted to the
compositor thread directly (here: UI thread) bypassing the main thread
BUG=239760
NOTRY=True
Review URL: https://chromiumcodereview.appspot.com/23234003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@219057 0039d316-1c4b-4281-b951-d872f2087c98
17 files changed, 524 insertions, 21 deletions
diff --git a/content/browser/android/in_process/synchronous_compositor_impl.cc b/content/browser/android/in_process/synchronous_compositor_impl.cc index 678f622..8fcebf4 100644 --- a/content/browser/android/in_process/synchronous_compositor_impl.cc +++ b/content/browser/android/in_process/synchronous_compositor_impl.cc @@ -16,13 +16,20 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/renderer/android/synchronous_compositor_factory.h" +#include "content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h" +#include "gpu/command_buffer/client/gl_in_process_context.h" +#include "gpu/command_buffer/service/stream_texture_manager_in_process_android.h" +#include "ui/gl/android/surface_texture_bridge.h" #include "ui/gl/gl_surface.h" #include "webkit/common/gpu/context_provider_in_process.h" +#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h" namespace content { namespace { +using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl; + int GetInProcessRendererId() { content::RenderProcessHost::iterator it = content::RenderProcessHost::AllHostsIterator(); @@ -38,9 +45,38 @@ int GetInProcessRendererId() { return id; } +class VideoContextProvider + : public StreamTextureFactorySynchronousImpl::ContextProvider { + public: + VideoContextProvider( + const scoped_refptr<cc::ContextProvider>& context_provider, + gpu::GLInProcessContext* gl_in_process_context) + : context_provider_(context_provider), + gl_in_process_context_(gl_in_process_context) {} + + virtual scoped_refptr<gfx::SurfaceTextureBridge> GetSurfaceTexture( + uint32 stream_id) OVERRIDE { + return gl_in_process_context_->GetSurfaceTexture(stream_id); + } + + virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE { + return context_provider_->Context3d(); + } + + private: + friend class base::RefCountedThreadSafe<VideoContextProvider>; + virtual ~VideoContextProvider() {} + + scoped_refptr<cc::ContextProvider> context_provider_; + gpu::GLInProcessContext* gl_in_process_context_; + + DISALLOW_COPY_AND_ASSIGN(VideoContextProvider); +}; + class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory { public: - SynchronousCompositorFactoryImpl() { + SynchronousCompositorFactoryImpl() + : wrapped_gl_context_for_main_thread_(NULL) { SynchronousCompositorFactory::SetInstance(this); } @@ -65,15 +101,52 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory { return &synchronous_input_event_filter_; } + scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> + CreateOffscreenContext() { + if (!gfx::GLSurface::InitializeOneOff()) + return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>(); + + const char* allowed_extensions = "*"; + const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu; + + WebKit::WebGraphicsContext3D::Attributes attributes; + attributes.antialias = false; + attributes.shareResources = true; + attributes.noAutomaticFlushes = true; + + gpu::GLInProcessContextAttribs in_process_attribs; + WebGraphicsContext3DInProcessCommandBufferImpl::ConvertAttributes( + attributes, &in_process_attribs); + scoped_ptr<gpu::GLInProcessContext> context( + gpu::GLInProcessContext::CreateContext(true, + NULL, + gfx::Size(1, 1), + attributes.shareResources, + allowed_extensions, + in_process_attribs, + gpu_preference)); + + wrapped_gl_context_for_main_thread_ = context.get(); + if (!context.get()) + return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>(); + + return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>( + WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext( + context.Pass(), attributes)); + } + virtual scoped_refptr<cc::ContextProvider> GetOffscreenContextProviderForMainThread() OVERRIDE { if (!offscreen_context_for_main_thread_.get() || offscreen_context_for_main_thread_->DestroyedOnMainThread()) { offscreen_context_for_main_thread_ = - webkit::gpu::ContextProviderInProcess::CreateOffscreen(); + webkit::gpu::ContextProviderInProcess::Create( + CreateOffscreenContext()); if (offscreen_context_for_main_thread_.get() && - !offscreen_context_for_main_thread_->BindToCurrentThread()) + !offscreen_context_for_main_thread_->BindToCurrentThread()) { offscreen_context_for_main_thread_ = NULL; + wrapped_gl_context_for_main_thread_ = NULL; + } } return offscreen_context_for_main_thread_; } @@ -95,6 +168,16 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory { return offscreen_context_for_compositor_thread_; } + virtual scoped_ptr<StreamTextureFactory> CreateStreamTextureFactory( + int view_id) OVERRIDE { + scoped_refptr<VideoContextProvider> context_provider = + new VideoContextProvider(offscreen_context_for_main_thread_, + wrapped_gl_context_for_main_thread_); + return make_scoped_ptr(new StreamTextureFactorySynchronousImpl( + context_provider.get(), view_id)) + .PassAs<StreamTextureFactory>(); + } + private: SynchronousInputEventFilter synchronous_input_event_filter_; @@ -102,6 +185,9 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory { // not usage. base::Lock offscreen_context_for_compositor_thread_creation_lock_; scoped_refptr<cc::ContextProvider> offscreen_context_for_main_thread_; + // This is a pointer to the context owned by + // |offscreen_context_for_main_thread_|. + gpu::GLInProcessContext* wrapped_gl_context_for_main_thread_; scoped_refptr<cc::ContextProvider> offscreen_context_for_compositor_thread_; }; diff --git a/content/common/gpu/stream_texture_manager_android.h b/content/common/gpu/stream_texture_manager_android.h index 9421d6a..9da84d9 100644 --- a/content/common/gpu/stream_texture_manager_android.h +++ b/content/common/gpu/stream_texture_manager_android.h @@ -30,7 +30,7 @@ class StreamTextureManagerAndroid : public gpu::StreamTextureManager { virtual ~StreamTextureManagerAndroid(); // implement gpu::StreamTextureManager: - virtual GLuint CreateStreamTexture(uint32 service_id, + virtual uint32 CreateStreamTexture(uint32 service_id, uint32 client_id) OVERRIDE; virtual void DestroyStreamTexture(uint32 service_id) OVERRIDE; virtual gpu::StreamTexture* LookupStreamTexture(uint32 service_id) OVERRIDE; diff --git a/content/renderer/android/synchronous_compositor_factory.h b/content/renderer/android/synchronous_compositor_factory.h index 234a033..bd625be 100644 --- a/content/renderer/android/synchronous_compositor_factory.h +++ b/content/renderer/android/synchronous_compositor_factory.h @@ -20,6 +20,7 @@ class OutputSurface; namespace content { class InputHandlerManagerClient; +class StreamTextureFactory; // Decouples creation from usage of the parts needed for the synchonous // compositor rendering path. In practice this is only used in single @@ -44,6 +45,8 @@ class SynchronousCompositorFactory { GetOffscreenContextProviderForMainThread() = 0; virtual scoped_refptr<cc::ContextProvider> GetOffscreenContextProviderForCompositorThread() = 0; + virtual scoped_ptr<StreamTextureFactory> CreateStreamTextureFactory( + int view_id) = 0; protected: SynchronousCompositorFactory() {} diff --git a/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc b/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc index 88878d5..de0ca92 100644 --- a/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc +++ b/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc @@ -4,31 +4,175 @@ #include "content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h" +#include <algorithm> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/location.h" +#include "base/memory/weak_ptr.h" +#include "base/message_loop/message_loop_proxy.h" +#include "base/process/process.h" +#include "base/synchronization/lock.h" +#include "cc/output/context_provider.h" +#include "content/common/android/surface_texture_peer.h" +#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" +#include "ui/gl/android/surface_texture_bridge.h" + namespace content { -StreamTextureFactorySynchronousImpl::StreamTextureFactorySynchronousImpl() {} +namespace { + +class StreamTextureProxyImpl + : public StreamTextureProxy, + public base::SupportsWeakPtr<StreamTextureProxyImpl> { + public: + explicit StreamTextureProxyImpl( + StreamTextureFactorySynchronousImpl::ContextProvider* provider); + virtual ~StreamTextureProxyImpl(); + + // StreamTextureProxy implementation: + virtual void BindToCurrentThread(int32 stream_id) OVERRIDE; + virtual bool IsBoundToThread() OVERRIDE { return loop_.get() != NULL; } + virtual void SetClient(cc::VideoFrameProvider::Client* client) OVERRIDE; + virtual void Release() OVERRIDE; + + private: + void OnFrameAvailable(); + + scoped_refptr<base::MessageLoopProxy> loop_; + base::Lock client_lock_; + cc::VideoFrameProvider::Client* client_; + base::Closure callback_; + + scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider> + context_provider_; + scoped_refptr<gfx::SurfaceTextureBridge> surface_texture_; + + float current_matrix_[16]; + bool has_updated_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureProxyImpl); +}; + +StreamTextureProxyImpl::StreamTextureProxyImpl( + StreamTextureFactorySynchronousImpl::ContextProvider* provider) + : context_provider_(provider), has_updated_(false) { + std::fill(current_matrix_, current_matrix_ + 16, 0); +} + +StreamTextureProxyImpl::~StreamTextureProxyImpl() {} + +void StreamTextureProxyImpl::Release() { + SetClient(NULL); + if (!loop_->BelongsToCurrentThread()) + loop_->DeleteSoon(FROM_HERE, this); + else + delete this; +} + +void StreamTextureProxyImpl::SetClient(cc::VideoFrameProvider::Client* client) { + base::AutoLock lock(client_lock_); + client_ = client; +} + +void StreamTextureProxyImpl::BindToCurrentThread(int stream_id) { + loop_ = base::MessageLoopProxy::current(); + + surface_texture_ = context_provider_->GetSurfaceTexture(stream_id); + if (!surface_texture_) { + LOG(ERROR) << "Failed to get SurfaceTexture for stream."; + return; + } + + callback_ = + base::Bind(&StreamTextureProxyImpl::OnFrameAvailable, AsWeakPtr()); + surface_texture_->SetFrameAvailableCallback(callback_); +} + +void StreamTextureProxyImpl::OnFrameAvailable() { + // GetTransformMatrix only returns something valid after both is true: + // - OnFrameAvailable was called + // - we called UpdateTexImage + if (has_updated_) { + float matrix[16]; + surface_texture_->GetTransformMatrix(matrix); + + if (memcmp(current_matrix_, matrix, sizeof(matrix)) != 0) { + memcpy(current_matrix_, matrix, sizeof(matrix)); + + base::AutoLock lock(client_lock_); + if (client_) + client_->DidUpdateMatrix(current_matrix_); + } + } + // OnFrameAvailable being called a second time implies that we called + // updateTexImage since after we received the first frame. + has_updated_ = true; + + base::AutoLock lock(client_lock_); + if (client_) + client_->DidReceiveFrame(); +} + +} // namespace + +StreamTextureFactorySynchronousImpl::StreamTextureFactorySynchronousImpl( + ContextProvider* context_provider, + int view_id) + : context_provider_(context_provider), view_id_(view_id) {} + StreamTextureFactorySynchronousImpl::~StreamTextureFactorySynchronousImpl() {} StreamTextureProxy* StreamTextureFactorySynchronousImpl::CreateProxy() { - return NULL; + return new StreamTextureProxyImpl(context_provider_); } void StreamTextureFactorySynchronousImpl::EstablishPeer(int32 stream_id, - int player_id) {} + int player_id) { + scoped_refptr<gfx::SurfaceTextureBridge> surface_texture = + context_provider_->GetSurfaceTexture(stream_id); + if (surface_texture) { + SurfaceTexturePeer::GetInstance()->EstablishSurfaceTexturePeer( + base::Process::Current().handle(), + surface_texture, + view_id_, + player_id); + } +} unsigned StreamTextureFactorySynchronousImpl::CreateStreamTexture( unsigned texture_target, unsigned* texture_id, gpu::Mailbox* texture_mailbox, unsigned* texture_mailbox_sync_point) { - return 0; + WebKit::WebGraphicsContext3D* context = context_provider_->Context3d(); + unsigned stream_id = 0; + if (context->makeContextCurrent()) { + *texture_id = context->createTexture(); + stream_id = context->createStreamTextureCHROMIUM(*texture_id); + + context->genMailboxCHROMIUM(texture_mailbox->name); + context->bindTexture(texture_target, *texture_id); + context->produceTextureCHROMIUM(texture_target, texture_mailbox->name); + + context->flush(); + *texture_mailbox_sync_point = context->insertSyncPoint(); + } + return stream_id; } void StreamTextureFactorySynchronousImpl::DestroyStreamTexture( - unsigned texture_id) {} + unsigned texture_id) { + WebKit::WebGraphicsContext3D* context = context_provider_->Context3d(); + if (context->makeContextCurrent()) { + context->destroyStreamTextureCHROMIUM(texture_id); + context->deleteTexture(texture_id); + context->flush(); + } +} void StreamTextureFactorySynchronousImpl::SetStreamTextureSize( - int32 texture_id, + int32 stream_id, const gfx::Size& size) {} } // namespace content diff --git a/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h b/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h index 52fc65a..50f9e80 100644 --- a/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h +++ b/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h @@ -5,14 +5,36 @@ #ifndef CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_SYNCHRONOUS_IMPL_H_ #define CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_SYNCHRONOUS_IMPL_H_ +#include "base/memory/ref_counted.h" #include "content/renderer/media/android/stream_texture_factory_android.h" +namespace gfx { +class SurfaceTextureBridge; +} + +namespace WebKit { +class WebGraphicsContext3D; +} + namespace content { // Factory for when using synchronous compositor in Android WebView. class StreamTextureFactorySynchronousImpl : public StreamTextureFactory { public: - StreamTextureFactorySynchronousImpl(); + class ContextProvider : public base::RefCountedThreadSafe<ContextProvider> { + public: + virtual scoped_refptr<gfx::SurfaceTextureBridge> GetSurfaceTexture( + uint32 stream_id) = 0; + + virtual WebKit::WebGraphicsContext3D* Context3d() = 0; + + protected: + friend class base::RefCountedThreadSafe<ContextProvider>; + virtual ~ContextProvider() {} + }; + + StreamTextureFactorySynchronousImpl(ContextProvider* context_provider, + int view_id); virtual ~StreamTextureFactorySynchronousImpl(); virtual StreamTextureProxy* CreateProxy() OVERRIDE; @@ -23,10 +45,13 @@ class StreamTextureFactorySynchronousImpl : public StreamTextureFactory { gpu::Mailbox* texture_mailbox, unsigned* texture_mailbox_sync_point) OVERRIDE; virtual void DestroyStreamTexture(unsigned texture_id) OVERRIDE; - virtual void SetStreamTextureSize(int32 texture_id, + virtual void SetStreamTextureSize(int32 stream_id, const gfx::Size& size) OVERRIDE; private: + scoped_refptr<ContextProvider> context_provider_; + int view_id_; + DISALLOW_COPY_AND_ASSIGN(StreamTextureFactorySynchronousImpl); }; diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 5bde8ba..32f323f 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc @@ -212,9 +212,9 @@ #include "content/renderer/android/content_detector.h" #include "content/renderer/android/email_detector.h" #include "content/renderer/android/phone_number_detector.h" +#include "content/renderer/android/synchronous_compositor_factory.h" #include "content/renderer/media/android/renderer_media_player_manager.h" #include "content/renderer/media/android/stream_texture_factory_android_impl.h" -#include "content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h" #include "content/renderer/media/android/webmediaplayer_android.h" #include "content/renderer/media/android/webmediaplayer_proxy_android.h" #include "skia/ext/platform_canvas.h" @@ -3037,7 +3037,9 @@ WebMediaPlayer* RenderViewImpl::createMediaPlayer( scoped_ptr<StreamTextureFactory> stream_texture_factory; if (UsingSynchronousRendererCompositor()) { - stream_texture_factory.reset(new StreamTextureFactorySynchronousImpl); + SynchronousCompositorFactory* factory = + SynchronousCompositorFactory::GetInstance(); + stream_texture_factory = factory->CreateStreamTextureFactory(routing_id_); } else { stream_texture_factory.reset(new StreamTextureFactoryImpl( context_provider->Context3d(), gpu_channel_host, routing_id_)); diff --git a/gpu/command_buffer/client/gl_in_process_context.cc b/gpu/command_buffer/client/gl_in_process_context.cc index f97099a..984214d 100644 --- a/gpu/command_buffer/client/gl_in_process_context.cc +++ b/gpu/command_buffer/client/gl_in_process_context.cc @@ -30,6 +30,10 @@ #include "ui/gfx/size.h" #include "ui/gl/gl_image.h" +#if defined(OS_ANDROID) +#include "ui/gl/android/surface_texture_bridge.h" +#endif + namespace gpu { namespace { @@ -65,6 +69,11 @@ class GLInProcessContextImpl OVERRIDE; virtual gles2::GLES2Implementation* GetImplementation() OVERRIDE; +#if defined(OS_ANDROID) + virtual scoped_refptr<gfx::SurfaceTextureBridge> GetSurfaceTexture( + uint32 stream_id) OVERRIDE; +#endif + private: void Destroy(); void PollQueryCallbacks(); @@ -333,6 +342,13 @@ void GLInProcessContextImpl::SignalQuery( } } +#if defined(OS_ANDROID) +scoped_refptr<gfx::SurfaceTextureBridge> +GLInProcessContextImpl::GetSurfaceTexture(uint32 stream_id) { + return command_buffer_->GetSurfaceTexture(stream_id); +} +#endif + } // anonymous namespace GLInProcessContextAttribs::GLInProcessContextAttribs() diff --git a/gpu/command_buffer/client/gl_in_process_context.h b/gpu/command_buffer/client/gl_in_process_context.h index 7e924b5..ec7bdc5 100644 --- a/gpu/command_buffer/client/gl_in_process_context.h +++ b/gpu/command_buffer/client/gl_in_process_context.h @@ -16,6 +16,12 @@ namespace gfx { class Size; } +#if defined(OS_ANDROID) +namespace gfx { +class SurfaceTextureBridge; +} +#endif + namespace gpu { namespace gles2 { @@ -73,6 +79,11 @@ class GLES2_IMPL_EXPORT GLInProcessContext { // Allows direct access to the GLES2 implementation so a GLInProcessContext // can be used without making it current. virtual gles2::GLES2Implementation* GetImplementation() = 0; + +#if defined(OS_ANDROID) + virtual scoped_refptr<gfx::SurfaceTextureBridge> GetSurfaceTexture( + uint32 stream_id) = 0; +#endif }; } // namespace gpu diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc index 2f949c9..6b9fe8a 100644 --- a/gpu/command_buffer/service/in_process_command_buffer.cc +++ b/gpu/command_buffer/service/in_process_command_buffer.cc @@ -34,6 +34,11 @@ #include "ui/gl/gl_image.h" #include "ui/gl/gl_share_group.h" +#if defined(OS_ANDROID) +#include "gpu/command_buffer/service/stream_texture_manager_in_process_android.h" +#include "ui/gl/android/surface_texture_bridge.h" +#endif + namespace gpu { namespace { @@ -379,11 +384,21 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( share_group = new gfx::GLShareGroup; } + StreamTextureManager* stream_texture_manager = NULL; +#if defined(OS_ANDROID) + stream_texture_manager = stream_texture_manager_ = + context_group ? context_group->stream_texture_manager_.get() + : new StreamTextureManagerInProcess; +#endif + bool bind_generates_resource = false; decoder_.reset(gles2::GLES2Decoder::Create( context_group ? context_group->decoder_->GetContextGroup() - : new gles2::ContextGroup( - NULL, NULL, NULL, NULL, bind_generates_resource))); + : new gles2::ContextGroup(NULL, + NULL, + NULL, + stream_texture_manager, + bind_generates_resource))); gpu_scheduler_.reset( new GpuScheduler(command_buffer.get(), decoder_.get(), decoder_.get())); @@ -712,6 +727,14 @@ base::Closure InProcessCommandBuffer::WrapCallback( return wrapped_callback; } +#if defined(OS_ANDROID) +scoped_refptr<gfx::SurfaceTextureBridge> +InProcessCommandBuffer::GetSurfaceTexture(uint32 stream_id) { + DCHECK(stream_texture_manager_); + return stream_texture_manager_->GetSurfaceTexture(stream_id); +} +#endif + // static void InProcessCommandBuffer::EnableVirtualizedContext() { g_use_virtualized_gl_context = true; diff --git a/gpu/command_buffer/service/in_process_command_buffer.h b/gpu/command_buffer/service/in_process_command_buffer.h index 03c0f42..3caf4aa 100644 --- a/gpu/command_buffer/service/in_process_command_buffer.h +++ b/gpu/command_buffer/service/in_process_command_buffer.h @@ -31,6 +31,15 @@ class GLSurface; class Size; } +#if defined(OS_ANDROID) +namespace gfx { +class SurfaceTextureBridge; +} +namespace gpu { +class StreamTextureManagerInProcess; +} +#endif + namespace gpu { namespace gles2 { @@ -116,6 +125,11 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, virtual void QueueTask(const base::Closure& task) = 0; }; +#if defined(OS_ANDROID) + scoped_refptr<gfx::SurfaceTextureBridge> GetSurfaceTexture( + uint32 stream_id); +#endif + private: bool InitializeOnGpuThread(bool is_offscreen, gfx::AcceleratedWidget window, @@ -163,6 +177,10 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, base::Lock state_after_last_flush_lock_; scoped_ptr<GpuControl> gpu_control_; +#if defined(OS_ANDROID) + scoped_refptr<StreamTextureManagerInProcess> stream_texture_manager_; +#endif + // Only used with explicit scheduling and the gpu thread is the same as // the client thread. scoped_ptr<base::SequenceChecker> sequence_checker_; diff --git a/gpu/command_buffer/service/stream_texture_manager.h b/gpu/command_buffer/service/stream_texture_manager.h index b4f0a53..51119fa 100644 --- a/gpu/command_buffer/service/stream_texture_manager.h +++ b/gpu/command_buffer/service/stream_texture_manager.h @@ -6,7 +6,6 @@ #define GPU_COMMAND_BUFFER_SERVICE_STREAM_TEXTURE_MANAGER_H_ #include "base/basictypes.h" -#include "gpu/command_buffer/service/gl_utils.h" namespace gpu { @@ -22,8 +21,7 @@ class StreamTextureManager { } // Returns an identifier for the object, or NULL if not successful. - virtual GLuint CreateStreamTexture(uint32 service_id, - uint32 client_id) = 0; + virtual uint32 CreateStreamTexture(uint32 service_id, uint32 client_id) = 0; virtual void DestroyStreamTexture(uint32 service_id) = 0; diff --git a/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc b/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc new file mode 100644 index 0000000..0a6c4c9 --- /dev/null +++ b/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc @@ -0,0 +1,92 @@ +// Copyright 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 "gpu/command_buffer/service/stream_texture_manager_in_process_android.h" + +#include "base/bind.h" +#include "ui/gfx/size.h" +#include "ui/gl/android/surface_texture_bridge.h" +#include "ui/gl/gl_bindings.h" + +namespace gpu { + +StreamTextureManagerInProcess::StreamTextureImpl::StreamTextureImpl( + uint32 service_id, + uint32 stream_id) + : surface_texture_bridge_(new gfx::SurfaceTextureBridge(service_id)), + stream_id_(stream_id) {} + +StreamTextureManagerInProcess::StreamTextureImpl::~StreamTextureImpl() {} + +void StreamTextureManagerInProcess::StreamTextureImpl::Update() { + GLint texture_id = 0; + glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texture_id); + surface_texture_bridge_->UpdateTexImage(); + glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id); +} + +gfx::Size StreamTextureManagerInProcess::StreamTextureImpl::GetSize() { + return size_; +} + +void StreamTextureManagerInProcess::StreamTextureImpl::SetSize(gfx::Size size) { + size_ = size; +} + +scoped_refptr<gfx::SurfaceTextureBridge> +StreamTextureManagerInProcess::StreamTextureImpl::GetSurfaceTexture() { + return surface_texture_bridge_; +} + +StreamTextureManagerInProcess::StreamTextureManagerInProcess() : next_id_(1) {} + +StreamTextureManagerInProcess::~StreamTextureManagerInProcess() { + if (!textures_.empty()) { + LOG(WARNING) << "Undestroyed surface textures while tearing down " + "StreamTextureManager."; + } +} + +GLuint StreamTextureManagerInProcess::CreateStreamTexture(uint32 service_id, + uint32 client_id) { + base::AutoLock lock(map_lock_); + uint32 stream_id = next_id_++; + linked_ptr<StreamTextureImpl> texture( + new StreamTextureImpl(service_id, stream_id)); + textures_[service_id] = texture; + + if (next_id_ == 0) + next_id_++; + + return stream_id; +} + +void StreamTextureManagerInProcess::DestroyStreamTexture(uint32 service_id) { + base::AutoLock lock(map_lock_); + textures_.erase(service_id); +} + +gpu::StreamTexture* StreamTextureManagerInProcess::LookupStreamTexture( + uint32 service_id) { + base::AutoLock lock(map_lock_); + TextureMap::const_iterator it = textures_.find(service_id); + if (it != textures_.end()) + return it->second.get(); + + return NULL; +} + +scoped_refptr<gfx::SurfaceTextureBridge> +StreamTextureManagerInProcess::GetSurfaceTexture(uint32 stream_id) { + base::AutoLock lock(map_lock_); + for (TextureMap::iterator it = textures_.begin(); it != textures_.end(); + it++) { + if (it->second->stream_id() == stream_id) + return it->second->GetSurfaceTexture(); + } + + return NULL; +} + +} // namespace gpu diff --git a/gpu/command_buffer/service/stream_texture_manager_in_process_android.h b/gpu/command_buffer/service/stream_texture_manager_in_process_android.h new file mode 100644 index 0000000..70ec024 --- /dev/null +++ b/gpu/command_buffer/service/stream_texture_manager_in_process_android.h @@ -0,0 +1,75 @@ +// Copyright 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 GPU_STREAM_TEXTURE_MANAGER_IN_PROCESS_ANDROID_H_ +#define GPU_STREAM_TEXTURE_MANAGER_IN_PROCESS_ANDROID_H_ + +#include <map> + +#include "base/memory/linked_ptr.h" +#include "base/memory/ref_counted.h" +#include "base/synchronization/lock.h" +#include "gpu/command_buffer/service/stream_texture.h" +#include "gpu/command_buffer/service/stream_texture_manager.h" + +namespace gfx { +class Size; +class SurfaceTextureBridge; +} + +namespace gpu { + +class StreamTextureManagerInProcess + : public gpu::StreamTextureManager, + public base::RefCountedThreadSafe<StreamTextureManagerInProcess> { + public: + StreamTextureManagerInProcess(); + + // implement gpu::StreamTextureManager: + virtual uint32 CreateStreamTexture(uint32 service_id, + uint32 client_id) OVERRIDE; + virtual void DestroyStreamTexture(uint32 service_id) OVERRIDE; + virtual gpu::StreamTexture* LookupStreamTexture(uint32 service_id) OVERRIDE; + + scoped_refptr<gfx::SurfaceTextureBridge> GetSurfaceTexture(uint32 stream_id); + + private: + class StreamTextureImpl : public gpu::StreamTexture { + public: + StreamTextureImpl(uint32 service_id, uint32 stream_id); + virtual ~StreamTextureImpl(); + + // implement gpu::StreamTexture + virtual void Update() OVERRIDE; + virtual gfx::Size GetSize() OVERRIDE; + + void SetSize(gfx::Size size); + + scoped_refptr<gfx::SurfaceTextureBridge> GetSurfaceTexture(); + uint32 stream_id() { return stream_id_; } + + private: + scoped_refptr<gfx::SurfaceTextureBridge> surface_texture_bridge_; + uint32 stream_id_; + gfx::Size size_; + + DISALLOW_COPY_AND_ASSIGN(StreamTextureImpl); + }; + + friend class base::RefCountedThreadSafe<StreamTextureManagerInProcess>; + virtual ~StreamTextureManagerInProcess(); + + typedef std::map<uint32, linked_ptr<StreamTextureImpl> > TextureMap; + TextureMap textures_; + + uint32 next_id_; + + base::Lock map_lock_; + + DISALLOW_COPY_AND_ASSIGN(StreamTextureManagerInProcess); +}; + +} // gpu + +#endif // GPU_STREAM_TEXTURE_MANAGER_IN_PROCESS_ANDROID_H_ diff --git a/gpu/command_buffer/service/stream_texture_manager_mock.h b/gpu/command_buffer/service/stream_texture_manager_mock.h index ac145ec..4b744f2 100644 --- a/gpu/command_buffer/service/stream_texture_manager_mock.h +++ b/gpu/command_buffer/service/stream_texture_manager_mock.h @@ -18,8 +18,8 @@ class MockStreamTextureManager : public StreamTextureManager { MockStreamTextureManager(); virtual ~MockStreamTextureManager(); - MOCK_METHOD2(CreateStreamTexture, GLuint(uint32 service_id, - uint32 client_id)); + MOCK_METHOD2(CreateStreamTexture, + uint32(uint32 service_id, uint32 client_id)); MOCK_METHOD1(DestroyStreamTexture, void(uint32 service_id)); MOCK_METHOD1(LookupStreamTexture, StreamTexture*(uint32 service_id)); diff --git a/gpu/command_buffer_service.gypi b/gpu/command_buffer_service.gypi index d9408b6..9c9c3f7 100644 --- a/gpu/command_buffer_service.gypi +++ b/gpu/command_buffer_service.gypi @@ -116,6 +116,8 @@ 'command_buffer/service/shader_translator_cache.cc', 'command_buffer/service/stream_texture.h', 'command_buffer/service/stream_texture_manager.h', + 'command_buffer/service/stream_texture_manager_in_process_android.h', + 'command_buffer/service/stream_texture_manager_in_process_android.cc', 'command_buffer/service/texture_manager.h', 'command_buffer/service/texture_manager.cc', 'command_buffer/service/transfer_buffer_manager.cc', diff --git a/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc b/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc index 66c7a53..9207ef9 100644 --- a/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc +++ b/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc @@ -1117,6 +1117,11 @@ DELEGATE_TO_GL_2(bindTexImage2DCHROMIUM, BindTexImage2DCHROMIUM, DELEGATE_TO_GL_2(releaseTexImage2DCHROMIUM, ReleaseTexImage2DCHROMIUM, WGC3Denum, WGC3Dint) +DELEGATE_TO_GL_1R(createStreamTextureCHROMIUM, CreateStreamTextureCHROMIUM, + WebGLId, WebGLId) +DELEGATE_TO_GL_1(destroyStreamTextureCHROMIUM, DestroyStreamTextureCHROMIUM, + WebGLId) + void* WebGraphicsContext3DInProcessCommandBufferImpl::mapBufferCHROMIUM( WGC3Denum target, WGC3Denum access) { ClearContext(); diff --git a/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h b/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h index f96607d..d763e14 100644 --- a/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h +++ b/webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h @@ -468,6 +468,9 @@ class WEBKIT_GPU_EXPORT WebGraphicsContext3DInProcessCommandBufferImpl virtual void bindTexImage2DCHROMIUM(WGC3Denum target, WGC3Dint imageId); virtual void releaseTexImage2DCHROMIUM(WGC3Denum target, WGC3Dint imageId); + virtual WebGLId createStreamTextureCHROMIUM(WebGLId texture); + virtual void destroyStreamTextureCHROMIUM(WebGLId texture); + virtual void texStorage2DEXT( WGC3Denum target, WGC3Dint levels, WGC3Duint internalformat, WGC3Dint width, WGC3Dint height); |