Chromium Code Reviews| Index: content/renderer/browser_plugin/browser_plugin_compositing_helper.cc |
| diff --git a/content/renderer/browser_plugin/browser_plugin_compositing_helper.cc b/content/renderer/browser_plugin/browser_plugin_compositing_helper.cc |
| index dd7d84fc51a1b3e65cbcb4d13e53a24e79b05aec..4dd6c5aba18b2d14cdb1084d3ce12cdf3c797f67 100644 |
| --- a/content/renderer/browser_plugin/browser_plugin_compositing_helper.cc |
| +++ b/content/renderer/browser_plugin/browser_plugin_compositing_helper.cc |
| @@ -6,36 +6,28 @@ |
| #include "cc/texture_layer.h" |
| #include "content/common/browser_plugin_messages.h" |
| +#include "content/renderer/browser_plugin/browser_plugin_manager.h" |
| #include "content/renderer/render_thread_impl.h" |
| +#include "third_party/khronos/GLES2/gl2.h" |
| +#include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h" |
| +#include "third_party/WebKit/Source/Platform/chromium/public/WebSharedGraphicsContext3D.h" |
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" |
| #include "webkit/compositor_bindings/web_layer_impl.h" |
| namespace content { |
| -static void SendACK(const std::string& mailbox_name, |
| - int host_route_id, |
| - int gpu_route_id, |
| - int gpu_host_id, |
| - unsigned sync_point) { |
| - RenderThread::Get()->Send( |
| - new BrowserPluginHostMsg_BuffersSwappedACK( |
| - host_route_id, |
| - gpu_route_id, |
| - gpu_host_id, |
| - mailbox_name, |
| - sync_point)); |
| -} |
| - |
| BrowserPluginCompositingHelper::BrowserPluginCompositingHelper( |
| WebKit::WebPluginContainer* container, |
| + BrowserPluginManager* manager, |
| int host_routing_id) |
| : host_routing_id_(host_routing_id), |
| last_mailbox_valid_(false), |
| - container_(container) { |
| + ack_pending_(true), |
| + container_(container), |
| + browser_plugin_manager_(manager) { |
| } |
| BrowserPluginCompositingHelper::~BrowserPluginCompositingHelper() { |
| - container_->setWebLayer(NULL); |
| } |
| void BrowserPluginCompositingHelper::EnableCompositing(bool enable) { |
| @@ -47,30 +39,114 @@ void BrowserPluginCompositingHelper::EnableCompositing(bool enable) { |
| container_->setWebLayer(enable ? web_layer_.get() : NULL); |
| } |
| +// If we have a mailbox that was freed up from the compositor, |
| +// but we are not expected to return it to the guest renderer |
| +// via an ACK, we should free it because we now own it. |
| +// To free the mailbox memory, we need a context to consume it |
| +// into a texture ID and then delete this texture ID. |
| +// We use a shared graphics context accessible from the main |
| +// thread to do it. |
| +void BrowserPluginCompositingHelper::FreeMailboxMemory( |
| + const std::string& mailbox_name, |
| + unsigned sync_point) { |
| + if (mailbox_name.empty()) |
| + return; |
| + |
| + WebKit::WebGraphicsContext3D *context = |
| + WebKit::WebSharedGraphicsContext3D::mainThreadContext(); |
| + DCHECK(context); |
| + // When a buffer is released from the compositor, we also get a |
| + // sync point that specifies when in the command buffer |
| + // it's safe to use it again. |
| + // If the sync point is non-zero, we need to tell our context |
| + // to wait until this sync point is reached before we can safely |
| + // delete the buffer. |
| + if (sync_point) |
| + context->waitSyncPoint(sync_point); |
| + |
| + unsigned texture_id = context->createTexture(); |
| + context->bindTexture(GL_TEXTURE_2D, texture_id); |
| + context->consumeTextureCHROMIUM( |
| + GL_TEXTURE_2D, |
| + reinterpret_cast<const int8*>(mailbox_name.data())); |
| + context->deleteTexture(texture_id); |
| +} |
| + |
| +void BrowserPluginCompositingHelper::MailboxReleased( |
| + const std::string& mailbox_name, |
| + int gpu_route_id, |
| + int gpu_host_id, |
| + unsigned sync_point) { |
| + // We need to send an ACK to TextureImageTransportSurface |
| + // for every buffer it sends us. However, if a buffer is freed up from |
| + // the compositor in cases like switching back to SW mode without a new |
| + // buffer arriving, no ACK is needed and we destroy this buffer. |
| + if (!ack_pending_) { |
| + FreeMailboxMemory(mailbox_name, sync_point); |
| + last_mailbox_valid_ = false; |
| + return; |
| + } |
| + ack_pending_ = false; |
| + browser_plugin_manager_->Send( |
| + new BrowserPluginHostMsg_BuffersSwappedACK( |
| + host_routing_id_, |
| + gpu_route_id, |
| + gpu_host_id, |
| + mailbox_name, |
| + sync_point)); |
| +} |
| + |
| +void BrowserPluginCompositingHelper::OnContainerDestroy() { |
| + if (container_) |
| + container_->setWebLayer(NULL); |
| + container_ = NULL; |
| + |
| + texture_layer_ = NULL; |
| + web_layer_.reset(); |
| +} |
| + |
| void BrowserPluginCompositingHelper::OnBuffersSwapped( |
| const gfx::Size& size, |
| const std::string& mailbox_name, |
| int gpu_route_id, |
| int gpu_host_id) { |
| + ack_pending_ = true; |
| + // Browser plugin getting destroyed, do a fast ACK. |
| + if (!texture_layer_) { |
| + MailboxReleased(mailbox_name, gpu_route_id, gpu_host_id, 0); |
| + return; |
| + } |
| + |
| + // The size of browser plugin container is not always equal to the size |
| + // of the buffer that arrives here. This could be for a number of reasons, |
| + // including autosize and a resize in process. |
|
Fady Samuel
2013/01/18 20:07:47
..in progress.
|
| + // During resize, the container size changes first and then some time |
| + // later, a new buffer with updated size will arrive. During this process |
|
Fady Samuel
2013/01/18 20:07:47
During this process,
|
| + // we need to make sure that things are still displayed pixel perfect. |
| + // We accoplish this by modifying texture coordinates in the layer, |
|
Fady Samuel
2013/01/18 20:07:47
We accomplish
|
| + // and either buffer size or container size change triggers the need |
| + // to also update texture coordinates. |
|
Fady Samuel
2013/01/18 20:07:47
What does this do visually? This is for gutter rig
|
| if (buffer_size_ != size) { |
| buffer_size_ = size; |
| UpdateUVRect(); |
| } |
| - if (!last_mailbox_valid_) |
| - SendACK(std::string(), host_routing_id_, gpu_route_id, gpu_host_id, 0); |
| bool current_mailbox_valid = !mailbox_name.empty(); |
| - if (!current_mailbox_valid && !last_mailbox_valid_) |
| - return; |
| + if (!last_mailbox_valid_) { |
| + MailboxReleased(std::string(), gpu_route_id, gpu_host_id, 0); |
| + if (!current_mailbox_valid) |
| + return; |
| + } |
| cc::TextureLayer::MailboxCallback callback; |
| if (current_mailbox_valid) { |
| - callback = base::Bind(&SendACK, |
| + callback = base::Bind(&BrowserPluginCompositingHelper::MailboxReleased, |
| + scoped_refptr<BrowserPluginCompositingHelper>(this), |
| mailbox_name, |
| - host_routing_id_, |
| gpu_route_id, |
| gpu_host_id); |
| } |
| + |
| texture_layer_->setTextureMailbox(mailbox_name, callback); |
| last_mailbox_valid_ = current_mailbox_valid; |
| } |