OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/browser_plugin/browser_plugin_compositing_helper.h" | 5 #include "content/renderer/browser_plugin/browser_plugin_compositing_helper.h" |
6 | 6 |
7 #include "cc/texture_layer.h" | 7 #include "cc/texture_layer.h" |
8 #include "content/common/browser_plugin_messages.h" | 8 #include "content/common/browser_plugin_messages.h" |
| 9 #include "content/renderer/browser_plugin/browser_plugin_manager.h" |
9 #include "content/renderer/render_thread_impl.h" | 10 #include "content/renderer/render_thread_impl.h" |
| 11 #include "third_party/khronos/GLES2/gl2.h" |
| 12 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3
D.h" |
| 13 #include "third_party/WebKit/Source/Platform/chromium/public/WebSharedGraphicsCo
ntext3D.h" |
10 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" | 14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" |
11 #include "webkit/compositor_bindings/web_layer_impl.h" | 15 #include "webkit/compositor_bindings/web_layer_impl.h" |
12 | 16 |
13 namespace content { | 17 namespace content { |
14 | 18 |
15 static void SendACK(const std::string& mailbox_name, | |
16 int host_route_id, | |
17 int gpu_route_id, | |
18 int gpu_host_id, | |
19 unsigned sync_point) { | |
20 RenderThread::Get()->Send( | |
21 new BrowserPluginHostMsg_BuffersSwappedACK( | |
22 host_route_id, | |
23 gpu_route_id, | |
24 gpu_host_id, | |
25 mailbox_name, | |
26 sync_point)); | |
27 } | |
28 | |
29 BrowserPluginCompositingHelper::BrowserPluginCompositingHelper( | 19 BrowserPluginCompositingHelper::BrowserPluginCompositingHelper( |
30 WebKit::WebPluginContainer* container, | 20 WebKit::WebPluginContainer* container, |
| 21 BrowserPluginManager* manager, |
31 int host_routing_id) | 22 int host_routing_id) |
32 : host_routing_id_(host_routing_id), | 23 : host_routing_id_(host_routing_id), |
33 last_mailbox_valid_(false), | 24 last_mailbox_valid_(false), |
34 container_(container) { | 25 ack_pending_(true), |
| 26 container_(container), |
| 27 browser_plugin_manager_(manager) { |
35 } | 28 } |
36 | 29 |
37 BrowserPluginCompositingHelper::~BrowserPluginCompositingHelper() { | 30 BrowserPluginCompositingHelper::~BrowserPluginCompositingHelper() { |
38 container_->setWebLayer(NULL); | |
39 } | 31 } |
40 | 32 |
41 void BrowserPluginCompositingHelper::EnableCompositing(bool enable) { | 33 void BrowserPluginCompositingHelper::EnableCompositing(bool enable) { |
42 if (enable && !texture_layer_) { | 34 if (enable && !texture_layer_) { |
43 texture_layer_ = cc::TextureLayer::createForMailbox(); | 35 texture_layer_ = cc::TextureLayer::createForMailbox(); |
44 web_layer_.reset(new WebKit::WebLayerImpl(texture_layer_)); | 36 web_layer_.reset(new WebKit::WebLayerImpl(texture_layer_)); |
45 } | 37 } |
46 | 38 |
47 container_->setWebLayer(enable ? web_layer_.get() : NULL); | 39 container_->setWebLayer(enable ? web_layer_.get() : NULL); |
48 } | 40 } |
49 | 41 |
| 42 // If we have a mailbox that was freed up from the compositor, |
| 43 // but we are not expected to return it to the guest renderer |
| 44 // via an ACK, we should free it because we now own it. |
| 45 // To free the mailbox memory, we need a context to consume it |
| 46 // into a texture ID and then delete this texture ID. |
| 47 // We use a shared graphics context accessible from the main |
| 48 // thread to do it. |
| 49 void BrowserPluginCompositingHelper::FreeMailboxMemory( |
| 50 const std::string& mailbox_name, |
| 51 unsigned sync_point) { |
| 52 if (mailbox_name.empty()) |
| 53 return; |
| 54 |
| 55 WebKit::WebGraphicsContext3D *context = |
| 56 WebKit::WebSharedGraphicsContext3D::mainThreadContext(); |
| 57 DCHECK(context); |
| 58 // When a buffer is released from the compositor, we also get a |
| 59 // sync point that specifies when in the command buffer |
| 60 // it's safe to use it again. |
| 61 // If the sync point is non-zero, we need to tell our context |
| 62 // to wait until this sync point is reached before we can safely |
| 63 // delete the buffer. |
| 64 if (sync_point) |
| 65 context->waitSyncPoint(sync_point); |
| 66 |
| 67 unsigned texture_id = context->createTexture(); |
| 68 context->bindTexture(GL_TEXTURE_2D, texture_id); |
| 69 context->consumeTextureCHROMIUM( |
| 70 GL_TEXTURE_2D, |
| 71 reinterpret_cast<const int8*>(mailbox_name.data())); |
| 72 context->deleteTexture(texture_id); |
| 73 } |
| 74 |
| 75 void BrowserPluginCompositingHelper::MailboxReleased( |
| 76 const std::string& mailbox_name, |
| 77 int gpu_route_id, |
| 78 int gpu_host_id, |
| 79 unsigned sync_point) { |
| 80 // We need to send an ACK to TextureImageTransportSurface |
| 81 // for every buffer it sends us. However, if a buffer is freed up from |
| 82 // the compositor in cases like switching back to SW mode without a new |
| 83 // buffer arriving, no ACK is needed and we destroy this buffer. |
| 84 if (!ack_pending_) { |
| 85 FreeMailboxMemory(mailbox_name, sync_point); |
| 86 last_mailbox_valid_ = false; |
| 87 return; |
| 88 } |
| 89 ack_pending_ = false; |
| 90 browser_plugin_manager_->Send( |
| 91 new BrowserPluginHostMsg_BuffersSwappedACK( |
| 92 host_routing_id_, |
| 93 gpu_route_id, |
| 94 gpu_host_id, |
| 95 mailbox_name, |
| 96 sync_point)); |
| 97 } |
| 98 |
| 99 void BrowserPluginCompositingHelper::OnContainerDestroy() { |
| 100 if (container_) |
| 101 container_->setWebLayer(NULL); |
| 102 container_ = NULL; |
| 103 |
| 104 texture_layer_ = NULL; |
| 105 web_layer_.reset(); |
| 106 } |
| 107 |
50 void BrowserPluginCompositingHelper::OnBuffersSwapped( | 108 void BrowserPluginCompositingHelper::OnBuffersSwapped( |
51 const gfx::Size& size, | 109 const gfx::Size& size, |
52 const std::string& mailbox_name, | 110 const std::string& mailbox_name, |
53 int gpu_route_id, | 111 int gpu_route_id, |
54 int gpu_host_id) { | 112 int gpu_host_id) { |
| 113 ack_pending_ = true; |
| 114 // Browser plugin getting destroyed, do a fast ACK. |
| 115 if (!texture_layer_) { |
| 116 MailboxReleased(mailbox_name, gpu_route_id, gpu_host_id, 0); |
| 117 return; |
| 118 } |
| 119 |
| 120 // The size of browser plugin container is not always equal to the size |
| 121 // of the buffer that arrives here. This could be for a number of reasons, |
| 122 // including autosize and a resize in progress. |
| 123 // During resize, the container size changes first and then some time |
| 124 // later, a new buffer with updated size will arrive. During this process, |
| 125 // we need to make sure that things are still displayed pixel perfect. |
| 126 // We accomplish this by modifying texture coordinates in the layer, |
| 127 // and either buffer size or container size change triggers the need |
| 128 // to also update texture coordinates. Visually, this will either |
| 129 // display a smaller part of the buffer or introduce a gutter around it. |
55 if (buffer_size_ != size) { | 130 if (buffer_size_ != size) { |
56 buffer_size_ = size; | 131 buffer_size_ = size; |
57 UpdateUVRect(); | 132 UpdateUVRect(); |
58 } | 133 } |
59 if (!last_mailbox_valid_) | |
60 SendACK(std::string(), host_routing_id_, gpu_route_id, gpu_host_id, 0); | |
61 | 134 |
62 bool current_mailbox_valid = !mailbox_name.empty(); | 135 bool current_mailbox_valid = !mailbox_name.empty(); |
63 if (!current_mailbox_valid && !last_mailbox_valid_) | 136 if (!last_mailbox_valid_) { |
64 return; | 137 MailboxReleased(std::string(), gpu_route_id, gpu_host_id, 0); |
| 138 if (!current_mailbox_valid) |
| 139 return; |
| 140 } |
65 | 141 |
66 cc::TextureLayer::MailboxCallback callback; | 142 cc::TextureLayer::MailboxCallback callback; |
67 if (current_mailbox_valid) { | 143 if (current_mailbox_valid) { |
68 callback = base::Bind(&SendACK, | 144 callback = base::Bind(&BrowserPluginCompositingHelper::MailboxReleased, |
| 145 scoped_refptr<BrowserPluginCompositingHelper>(this), |
69 mailbox_name, | 146 mailbox_name, |
70 host_routing_id_, | |
71 gpu_route_id, | 147 gpu_route_id, |
72 gpu_host_id); | 148 gpu_host_id); |
73 } | 149 } |
| 150 |
74 texture_layer_->setTextureMailbox(mailbox_name, callback); | 151 texture_layer_->setTextureMailbox(mailbox_name, callback); |
75 last_mailbox_valid_ = current_mailbox_valid; | 152 last_mailbox_valid_ = current_mailbox_valid; |
76 } | 153 } |
77 | 154 |
78 void BrowserPluginCompositingHelper::SetContainerSize(const gfx::Size& size) { | 155 void BrowserPluginCompositingHelper::SetContainerSize(const gfx::Size& size) { |
79 if (container_size_ == size) | 156 if (container_size_ == size) |
80 return; | 157 return; |
81 | 158 |
82 container_size_ = size; | 159 container_size_ = size; |
83 UpdateUVRect(); | 160 UpdateUVRect(); |
84 } | 161 } |
85 | 162 |
86 void BrowserPluginCompositingHelper::UpdateUVRect() { | 163 void BrowserPluginCompositingHelper::UpdateUVRect() { |
87 if (!texture_layer_) | 164 if (!texture_layer_) |
88 return; | 165 return; |
89 | 166 |
90 gfx::RectF uv_rect(0, 0, 1, 1); | 167 gfx::RectF uv_rect(0, 0, 1, 1); |
91 if (!buffer_size_.IsEmpty() && !container_size_.IsEmpty()) { | 168 if (!buffer_size_.IsEmpty() && !container_size_.IsEmpty()) { |
92 uv_rect.set_width(static_cast<float>(container_size_.width()) / | 169 uv_rect.set_width(static_cast<float>(container_size_.width()) / |
93 static_cast<float>(buffer_size_.width())); | 170 static_cast<float>(buffer_size_.width())); |
94 uv_rect.set_height(static_cast<float>(container_size_.height()) / | 171 uv_rect.set_height(static_cast<float>(container_size_.height()) / |
95 static_cast<float>(buffer_size_.height())); | 172 static_cast<float>(buffer_size_.height())); |
96 } | 173 } |
97 texture_layer_->setUVRect(uv_rect); | 174 texture_layer_->setUVRect(uv_rect); |
98 } | 175 } |
99 | 176 |
100 } // namespace content | 177 } // namespace content |
OLD | NEW |