Index: content/common/gpu/stream_texture_android.cc |
diff --git a/content/common/gpu/stream_texture_android.cc b/content/common/gpu/stream_texture_android.cc |
index 84a0d1fa64223664b8c9fb6e41e062820ee38e1b..158430f44973fe664f24d101dde9310105e5a8e5 100644 |
--- a/content/common/gpu/stream_texture_android.cc |
+++ b/content/common/gpu/stream_texture_android.cc |
@@ -12,8 +12,11 @@ |
#include "gpu/command_buffer/service/context_state.h" |
#include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
#include "gpu/command_buffer/service/texture_manager.h" |
+#include "ipc/ipc_listener.h" |
#include "ui/gfx/geometry/size.h" |
+#include "ui/gl/android/surface_texture.h" |
#include "ui/gl/gl_context.h" |
+#include "ui/gl/gl_image.h" |
#include "ui/gl/scoped_make_current.h" |
namespace content { |
@@ -23,11 +26,110 @@ using gpu::gles2::GLES2Decoder; |
using gpu::gles2::TextureManager; |
using gpu::gles2::TextureRef; |
+class StreamTexture : public gl::GLImage, |
+ public IPC::Listener, |
+ public GpuCommandBufferStub::DestructionObserver { |
+ public: |
+ static scoped_refptr<StreamTexture> Create(GpuCommandBufferStub* owner_stub, |
+ uint32 client_texture_id, |
+ int32 stream_id); |
+ |
+ void SetReleaseCallback(const base::Closure& release_callback) { |
+ release_callback_ = release_callback; |
+ } |
+ void SetSize(GpuCommandBufferStub* owner_stub, |
+ uint32 client_texture_id, |
+ size_t width, |
+ size_t height) { |
+ size_.SetSize(width, height); |
+ |
+ GLES2Decoder* decoder = owner_stub->decoder(); |
+ TextureManager* texture_manager = |
+ decoder->GetContextGroup()->texture_manager(); |
+ TextureRef* texture = texture_manager->GetTexture(client_texture_id); |
+ if (!texture || (texture->texture()->target() && |
+ texture->texture()->target() != GL_TEXTURE_EXTERNAL_OES)) { |
+ return; |
+ } |
+ |
+ // Prevent deletion on SetLevelInfo() |
+ scoped_refptr<StreamTexture> gl_image = this; |
+ texture_manager->SetLevelInfo( |
+ texture, GL_TEXTURE_EXTERNAL_OES, 0, GetInternalFormat(), width, height, |
+ 1, 0, GetInternalFormat(), GL_UNSIGNED_BYTE, gfx::Rect(size_)); |
+ texture_manager->SetLevelImage(texture, GL_TEXTURE_EXTERNAL_OES, 0, |
+ gl_image.get(), |
+ gpu::gles2::Texture::UNBOUND); |
+ } |
+ |
+ private: |
+ StreamTexture(GpuCommandBufferStub* owner_stub, |
+ int32 route_id, |
+ uint32 texture_id); |
+ ~StreamTexture() override; |
+ |
+ // gl::GLImage implementation: |
+ void Destroy(bool have_context) override; |
+ gfx::Size GetSize() override; |
+ unsigned GetInternalFormat() override; |
+ bool BindTexImage(unsigned target) override; |
+ void ReleaseTexImage(unsigned target) override; |
+ bool CopyTexImage(unsigned target) override; |
+ bool CopyTexSubImage(unsigned target, |
+ const gfx::Point& offset, |
+ const gfx::Rect& rect) override; |
+ bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, |
+ int z_order, |
+ gfx::OverlayTransform transform, |
+ const gfx::Rect& bounds_rect, |
+ const gfx::RectF& crop_rect) override; |
+ void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, |
+ uint64_t process_tracing_id, |
+ const std::string& dump_name) override; |
+ |
+ // GpuCommandBufferStub::DestructionObserver implementation. |
+ void OnWillDestroyStub() override; |
+ |
+ // Called when a new frame is available for the SurfaceTexture. |
+ void OnFrameAvailable(); |
+ |
+ // IPC::Listener implementation: |
+ bool OnMessageReceived(const IPC::Message& message) override; |
+ |
+ // IPC message handlers: |
+ void OnStartListening(); |
+ void OnEstablishPeer(int32 primary_id, int32 secondary_id); |
+ |
+ scoped_refptr<gfx::SurfaceTexture> surface_texture_; |
+ |
+ // Current transform matrix of the surface texture. |
+ float current_matrix_[16]; |
+ |
+ // Current size of the surface texture. |
+ gfx::Size size_; |
+ |
+ // Whether we ever bound a valid frame. |
+ bool has_valid_frame_; |
+ |
+ // Whether a new frame is available that we should update to. |
+ bool has_pending_frame_; |
+ |
+ GpuCommandBufferStub* owner_stub_; |
+ int32 route_id_; |
+ bool has_listener_; |
+ uint32 texture_id_; |
+ |
+ base::Closure release_callback_; |
+ |
+ base::WeakPtrFactory<StreamTexture> weak_factory_; |
+ DISALLOW_COPY_AND_ASSIGN(StreamTexture); |
+}; |
+ |
// static |
-bool StreamTexture::Create( |
+scoped_refptr<StreamTexture> StreamTexture::Create( |
GpuCommandBufferStub* owner_stub, |
uint32 client_texture_id, |
- int stream_id) { |
+ int32 stream_id) { |
GLES2Decoder* decoder = owner_stub->decoder(); |
TextureManager* texture_manager = |
decoder->GetContextGroup()->texture_manager(); |
@@ -38,7 +140,7 @@ bool StreamTexture::Create( |
// TODO: Ideally a valid image id was returned to the client so that |
// it could then call glBindTexImage2D() for doing the following. |
- scoped_refptr<gl::GLImage> gl_image( |
+ scoped_refptr<StreamTexture> gl_image( |
new StreamTexture(owner_stub, stream_id, texture->service_id())); |
gfx::Size size = gl_image->GetSize(); |
texture_manager->SetTarget(texture, GL_TEXTURE_EXTERNAL_OES); |
@@ -48,10 +150,10 @@ bool StreamTexture::Create( |
texture_manager->SetLevelImage(texture, GL_TEXTURE_EXTERNAL_OES, 0, |
gl_image.get(), |
gpu::gles2::Texture::UNBOUND); |
- return true; |
+ return gl_image; |
} |
- return false; |
+ return nullptr; |
} |
StreamTexture::StreamTexture(GpuCommandBufferStub* owner_stub, |
@@ -78,6 +180,7 @@ StreamTexture::~StreamTexture() { |
owner_stub_->RemoveDestructionObserver(this); |
owner_stub_->channel()->RemoveRoute(route_id_); |
} |
+ release_callback_.Run(); |
} |
void StreamTexture::OnWillDestroyStub() { |
@@ -195,7 +298,6 @@ bool StreamTexture::OnMessageReceived(const IPC::Message& message) { |
IPC_BEGIN_MESSAGE_MAP(StreamTexture, message) |
IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_StartListening, OnStartListening) |
IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_EstablishPeer, OnEstablishPeer) |
- IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_SetSize, OnSetSize) |
IPC_MESSAGE_UNHANDLED(handled = false) |
IPC_END_MESSAGE_MAP() |
@@ -248,4 +350,49 @@ void StreamTexture::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, |
// TODO(ericrk): Add OnMemoryDump for GLImages. crbug.com/514914 |
} |
+StreamTextureManager::StreamTextureManager() : weak_factory_(this) {} |
+ |
+StreamTextureManager::~StreamTextureManager() { |
+ if (!stream_textures_.empty()) { |
+ LOG(WARNING) << "Undestroyed stream textures while tearing down " |
+ "StreamTextureManager."; |
+ } |
+} |
+ |
+bool StreamTextureManager::CreateStreamTexture(GpuCommandBufferStub* owner_stub, |
+ uint32 client_texture_id, |
+ int32 stream_id) { |
+ CalledOnValidThread(); |
+ DCHECK_EQ(static_cast<size_t>(0), stream_textures_.count(stream_id)); |
+ scoped_refptr<StreamTexture> stream_texture = |
+ StreamTexture::Create(owner_stub, client_texture_id, stream_id); |
+ if (!stream_texture) |
+ return false; |
+ base::Closure release_callback = |
+ base::Bind(&StreamTextureManager::OnReleaseStreamTexture, |
+ weak_factory_.GetWeakPtr(), stream_id); |
+ stream_texture->SetReleaseCallback(release_callback); |
+ stream_textures_[stream_id] = stream_texture.get(); |
+ return true; |
+} |
+ |
+void StreamTextureManager::SetStreamTextureSize( |
+ GpuCommandBufferStub* owner_stub, |
+ uint32 client_texture_id, |
+ int32 stream_id, |
+ size_t width, |
+ size_t height) { |
+ CalledOnValidThread(); |
+ if (!stream_textures_.count(stream_id)) |
+ return; |
+ stream_textures_[stream_id]->SetSize(owner_stub, client_texture_id, width, |
+ height); |
+} |
+ |
+void StreamTextureManager::OnReleaseStreamTexture(int32 stream_id) { |
+ CalledOnValidThread(); |
+ DCHECK_EQ(static_cast<size_t>(1), stream_textures_.count(stream_id)); |
+ stream_textures_.erase(stream_id); |
+} |
+ |
} // namespace content |