OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | 1 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 2 // found in the LICENSE file. |
4 | 3 |
5 #include "content/common/gpu/texture_image_transport_surface.h" | 4 #include "content/common/gpu/texture_image_transport_surface.h" |
6 | 5 |
7 #include <string> | 6 #include <string> |
8 #include <vector> | 7 #include <vector> |
9 | 8 |
10 #include "base/command_line.h" | 9 #include "base/command_line.h" |
11 #include "content/common/gpu/gl_scoped_binders.h" | 10 #include "content/common/gpu/gl_scoped_binders.h" |
12 #include "content/common/gpu/gpu_channel.h" | 11 #include "content/common/gpu/gpu_channel.h" |
13 #include "content/common/gpu/gpu_channel_manager.h" | 12 #include "content/common/gpu/gpu_channel_manager.h" |
14 #include "content/common/gpu/gpu_messages.h" | 13 #include "content/common/gpu/gpu_messages.h" |
15 #include "content/common/gpu/sync_point_manager.h" | 14 #include "content/common/gpu/sync_point_manager.h" |
16 #include "content/public/common/content_switches.h" | 15 #include "content/public/common/content_switches.h" |
17 #include "gpu/command_buffer/service/context_group.h" | 16 #include "gpu/command_buffer/service/context_group.h" |
18 #include "gpu/command_buffer/service/gpu_scheduler.h" | 17 #include "gpu/command_buffer/service/gpu_scheduler.h" |
19 #include "gpu/command_buffer/service/texture_manager.h" | 18 #include "gpu/command_buffer/service/texture_definition.h" |
20 | 19 |
21 using gpu::gles2::ContextGroup; | 20 using gpu::gles2::ContextGroup; |
| 21 using gpu::gles2::MailboxManager; |
| 22 using gpu::gles2::MailboxName; |
| 23 using gpu::gles2::TextureDefinition; |
22 using gpu::gles2::TextureManager; | 24 using gpu::gles2::TextureManager; |
23 typedef TextureManager::TextureInfo TextureInfo; | |
24 | 25 |
25 namespace content { | 26 namespace content { |
26 | 27 |
27 TextureImageTransportSurface::Texture::Texture() | 28 TextureImageTransportSurface::Texture::Texture() |
28 : client_id(0), | 29 : service_id(0) { |
29 sent_to_client(false) { | |
30 } | 30 } |
31 | 31 |
32 TextureImageTransportSurface::Texture::~Texture() { | 32 TextureImageTransportSurface::Texture::~Texture() { |
33 } | 33 } |
34 | 34 |
35 TextureImageTransportSurface::TextureImageTransportSurface( | 35 TextureImageTransportSurface::TextureImageTransportSurface( |
36 GpuChannelManager* manager, | 36 GpuChannelManager* manager, |
37 GpuCommandBufferStub* stub, | 37 GpuCommandBufferStub* stub, |
38 const gfx::GLSurfaceHandle& handle) | 38 const gfx::GLSurfaceHandle& handle) |
39 : fbo_id_(0), | 39 : fbo_id_(0), |
40 front_(0), | |
41 stub_destroyed_(false), | 40 stub_destroyed_(false), |
42 backbuffer_suggested_allocation_(true), | 41 backbuffer_suggested_allocation_(true), |
43 frontbuffer_suggested_allocation_(true), | 42 frontbuffer_suggested_allocation_(true), |
44 frontbuffer_is_protected_(true), | |
45 protection_state_id_(0), | |
46 handle_(handle), | 43 handle_(handle), |
47 parent_stub_(NULL), | |
48 is_swap_buffers_pending_(false), | 44 is_swap_buffers_pending_(false), |
49 did_unschedule_(false) { | 45 did_unschedule_(false) { |
50 helper_.reset(new ImageTransportHelper(this, | 46 helper_.reset(new ImageTransportHelper(this, |
51 manager, | 47 manager, |
52 stub, | 48 stub, |
53 gfx::kNullPluginWindow)); | 49 gfx::kNullPluginWindow)); |
54 } | 50 } |
55 | 51 |
56 TextureImageTransportSurface::~TextureImageTransportSurface() { | 52 TextureImageTransportSurface::~TextureImageTransportSurface() { |
57 DCHECK(stub_destroyed_); | 53 DCHECK(stub_destroyed_); |
| 54 |
| 55 if (is_swap_buffers_pending_) { |
| 56 scoped_ptr<TextureDefinition> definition(mailbox_manager_->ConsumeTexture( |
| 57 GL_TEXTURE_2D, mailbox_name_)); |
| 58 if (definition.get()) { |
| 59 uint32 service_id = definition->ReleaseServiceId(); |
| 60 GpuChannelManager* manager = helper_->manager(); |
| 61 DCHECK(manager); |
| 62 if (manager->MakeCurrent(surface_.get())) |
| 63 glDeleteTextures(1, &service_id); |
| 64 } |
| 65 } |
| 66 |
58 Destroy(); | 67 Destroy(); |
59 } | 68 } |
60 | 69 |
61 bool TextureImageTransportSurface::Initialize() { | 70 bool TextureImageTransportSurface::Initialize() { |
| 71 mailbox_manager_ = |
| 72 helper_->stub()->decoder()->GetContextGroup()->mailbox_manager(); |
| 73 mailbox_manager_->GenerateMailboxName(&mailbox_name_); |
| 74 |
| 75 GpuHostMsg_AcceleratedSurfaceNew_Params params; |
| 76 params.width = 0; |
| 77 params.height = 0; |
| 78 params.mailbox_name.resize(sizeof(mailbox_name_)); |
| 79 memcpy(params.mailbox_name.data(), &mailbox_name_, sizeof(mailbox_name_)); |
| 80 helper_->SendAcceleratedSurfaceNew(params); |
| 81 |
62 GpuChannelManager* manager = helper_->manager(); | 82 GpuChannelManager* manager = helper_->manager(); |
63 GpuChannel* parent_channel = manager->LookupChannel(handle_.parent_client_id); | |
64 if (!parent_channel) | |
65 return false; | |
66 | |
67 parent_stub_ = parent_channel->LookupCommandBuffer(handle_.parent_context_id); | |
68 if (!parent_stub_) | |
69 return false; | |
70 | |
71 parent_stub_->AddDestructionObserver(this); | |
72 TextureManager* texture_manager = | |
73 parent_stub_->decoder()->GetContextGroup()->texture_manager(); | |
74 DCHECK(texture_manager); | |
75 | |
76 for (int i = 0; i < 2; ++i) { | |
77 Texture& texture = textures_[i]; | |
78 texture.client_id = handle_.parent_texture_id[i]; | |
79 texture.info = texture_manager->GetTextureInfo(texture.client_id); | |
80 if (!texture.info) | |
81 return false; | |
82 | |
83 if (!texture.info->target()) | |
84 texture_manager->SetInfoTarget(texture.info, GL_TEXTURE_2D); | |
85 texture_manager->SetParameter( | |
86 texture.info, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
87 texture_manager->SetParameter( | |
88 texture.info, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
89 texture_manager->SetParameter( | |
90 texture.info, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
91 texture_manager->SetParameter( | |
92 texture.info, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
93 } | |
94 | |
95 surface_ = manager->GetDefaultOffscreenSurface(); | 83 surface_ = manager->GetDefaultOffscreenSurface(); |
96 if (!surface_.get()) | 84 if (!surface_.get()) |
97 return false; | 85 return false; |
98 | 86 |
99 if (!helper_->Initialize()) | 87 if (!helper_->Initialize()) |
100 return false; | 88 return false; |
101 | 89 |
102 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | 90 // TODO: Move this somewhere else. |
103 if (command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess)) | 91 GpuChannel* parent_channel = manager->LookupChannel(handle_.parent_client_id); |
104 helper_->SetPreemptByCounter(parent_channel->MessagesPendingCount()); | 92 if (parent_channel) { |
| 93 const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 94 if (command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess)) |
| 95 helper_->SetPreemptByCounter(parent_channel->MessagesPendingCount()); |
| 96 } |
105 | 97 |
106 return true; | 98 return true; |
107 } | 99 } |
108 | 100 |
109 void TextureImageTransportSurface::Destroy() { | 101 void TextureImageTransportSurface::Destroy() { |
110 if (parent_stub_) { | |
111 parent_stub_->decoder()->MakeCurrent(); | |
112 ReleaseParentStub(); | |
113 } | |
114 | |
115 if (surface_.get()) | 102 if (surface_.get()) |
116 surface_ = NULL; | 103 surface_ = NULL; |
117 | 104 |
118 helper_->Destroy(); | 105 helper_->Destroy(); |
119 } | 106 } |
120 | 107 |
121 bool TextureImageTransportSurface::DeferDraws() { | 108 bool TextureImageTransportSurface::DeferDraws() { |
122 // The command buffer hit a draw/clear command that could clobber the | 109 // The command buffer hit a draw/clear command that could clobber the |
123 // texture in use by the UI compositor. If a Swap is pending, abort | 110 // texture in use by the UI compositor. If a Swap is pending, abort |
124 // processing of the command by returning true and unschedule until the Swap | 111 // processing of the command by returning true and unschedule until the Swap |
(...skipping 19 matching lines...) Expand all Loading... |
144 if (stub_destroyed_) { | 131 if (stub_destroyed_) { |
145 // Early-exit so that we don't recreate the fbo. We still want to return | 132 // Early-exit so that we don't recreate the fbo. We still want to return |
146 // true, so that the context is made current and the GLES2DecoderImpl can | 133 // true, so that the context is made current and the GLES2DecoderImpl can |
147 // release its own resources. | 134 // release its own resources. |
148 return true; | 135 return true; |
149 } | 136 } |
150 | 137 |
151 if (!fbo_id_) { | 138 if (!fbo_id_) { |
152 glGenFramebuffersEXT(1, &fbo_id_); | 139 glGenFramebuffersEXT(1, &fbo_id_); |
153 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_); | 140 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_); |
154 CreateBackTexture(gfx::Size(1, 1)); | 141 current_size_ = gfx::Size(1, 1); |
| 142 CreateBackTexture(); |
155 | 143 |
156 #ifndef NDEBUG | 144 #ifndef NDEBUG |
157 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); | 145 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); |
158 if (status != GL_FRAMEBUFFER_COMPLETE) { | 146 if (status != GL_FRAMEBUFFER_COMPLETE) { |
159 DLOG(ERROR) << "Framebuffer incomplete."; | 147 DLOG(ERROR) << "Framebuffer incomplete."; |
160 glDeleteFramebuffersEXT(1, &fbo_id_); | 148 glDeleteFramebuffersEXT(1, &fbo_id_); |
161 fbo_id_ = 0; | 149 fbo_id_ = 0; |
162 return false; | 150 return false; |
163 } | 151 } |
164 #endif | 152 #endif |
(...skipping 10 matching lines...) Expand all Loading... |
175 | 163 |
176 void TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) { | 164 void TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) { |
177 if (backbuffer_suggested_allocation_ == allocation) | 165 if (backbuffer_suggested_allocation_ == allocation) |
178 return; | 166 return; |
179 backbuffer_suggested_allocation_ = allocation; | 167 backbuffer_suggested_allocation_ = allocation; |
180 | 168 |
181 if (!helper_->MakeCurrent()) | 169 if (!helper_->MakeCurrent()) |
182 return; | 170 return; |
183 | 171 |
184 if (backbuffer_suggested_allocation_) { | 172 if (backbuffer_suggested_allocation_) { |
185 DCHECK(!textures_[back()].info->service_id() || | 173 DCHECK(!backbuffer_.service_id); |
186 !textures_[back()].sent_to_client); | 174 CreateBackTexture(); |
187 CreateBackTexture(textures_[back()].size); | |
188 } else { | 175 } else { |
189 ReleaseTexture(back()); | 176 ReleaseBackBuffer(); |
190 } | 177 } |
191 } | 178 } |
192 | 179 |
193 void TextureImageTransportSurface::SetFrontbufferAllocation(bool allocation) { | 180 void TextureImageTransportSurface::SetFrontbufferAllocation(bool allocation) { |
194 if (frontbuffer_suggested_allocation_ == allocation) | 181 if (frontbuffer_suggested_allocation_ == allocation) |
195 return; | 182 return; |
196 frontbuffer_suggested_allocation_ = allocation; | 183 frontbuffer_suggested_allocation_ = allocation; |
197 AdjustFrontBufferAllocation(); | 184 AdjustFrontBufferAllocation(); |
198 } | 185 } |
199 | 186 |
200 void TextureImageTransportSurface::AdjustFrontBufferAllocation() { | 187 void TextureImageTransportSurface::AdjustFrontBufferAllocation() { |
201 if (!helper_->MakeCurrent()) | 188 if (!helper_->MakeCurrent()) |
202 return; | 189 return; |
203 | 190 |
204 if (!frontbuffer_suggested_allocation_ && !frontbuffer_is_protected_ && | 191 if (!frontbuffer_suggested_allocation_) { |
205 textures_[front()].info->service_id()) { | 192 GpuHostMsg_AcceleratedSurfaceRelease_Params params; |
206 ReleaseTexture(front()); | 193 helper_->SendAcceleratedSurfaceRelease(params); |
207 if (textures_[front()].sent_to_client) { | |
208 GpuHostMsg_AcceleratedSurfaceRelease_Params params; | |
209 params.identifier = textures_[front()].client_id; | |
210 helper_->SendAcceleratedSurfaceRelease(params); | |
211 textures_[front()].sent_to_client = false; | |
212 } | |
213 } | 194 } |
214 } | 195 } |
215 | 196 |
216 void* TextureImageTransportSurface::GetShareHandle() { | 197 void* TextureImageTransportSurface::GetShareHandle() { |
217 return GetHandle(); | 198 return GetHandle(); |
218 } | 199 } |
219 | 200 |
220 void* TextureImageTransportSurface::GetDisplay() { | 201 void* TextureImageTransportSurface::GetDisplay() { |
221 return surface_.get() ? surface_->GetDisplay() : NULL; | 202 return surface_.get() ? surface_->GetDisplay() : NULL; |
222 } | 203 } |
223 | 204 |
224 void* TextureImageTransportSurface::GetConfig() { | 205 void* TextureImageTransportSurface::GetConfig() { |
225 return surface_.get() ? surface_->GetConfig() : NULL; | 206 return surface_.get() ? surface_->GetConfig() : NULL; |
226 } | 207 } |
227 | 208 |
228 void TextureImageTransportSurface::OnResize(gfx::Size size) { | 209 void TextureImageTransportSurface::OnResize(gfx::Size size) { |
229 CreateBackTexture(size); | 210 current_size_ = size; |
| 211 CreateBackTexture(); |
230 } | 212 } |
231 | 213 |
232 void TextureImageTransportSurface::OnWillDestroyStub( | 214 void TextureImageTransportSurface::OnWillDestroyStub( |
233 GpuCommandBufferStub* stub) { | 215 GpuCommandBufferStub* stub) { |
234 if (stub == parent_stub_) { | 216 DCHECK(stub == helper_->stub()); |
235 ReleaseParentStub(); | 217 stub->RemoveDestructionObserver(this); |
236 helper_->SetPreemptByCounter(NULL); | |
237 } else { | |
238 DCHECK(stub == helper_->stub()); | |
239 stub->RemoveDestructionObserver(this); | |
240 | 218 |
241 // We are losing the stub owning us, this is our last chance to clean up the | 219 // We are losing the stub owning us, this is our last chance to clean up the |
242 // resources we allocated in the stub's context. | 220 // resources we allocated in the stub's context. |
243 if (fbo_id_) { | 221 if (fbo_id_) { |
244 glDeleteFramebuffersEXT(1, &fbo_id_); | 222 glDeleteFramebuffersEXT(1, &fbo_id_); |
245 CHECK_GL_ERROR(); | 223 CHECK_GL_ERROR(); |
246 fbo_id_ = 0; | 224 fbo_id_ = 0; |
247 } | 225 } |
248 | 226 |
249 stub_destroyed_ = true; | 227 stub_destroyed_ = true; |
250 } | |
251 } | 228 } |
252 | 229 |
253 bool TextureImageTransportSurface::SwapBuffers() { | 230 bool TextureImageTransportSurface::SwapBuffers() { |
254 DCHECK(backbuffer_suggested_allocation_); | 231 DCHECK(backbuffer_suggested_allocation_); |
255 if (!frontbuffer_suggested_allocation_ || !frontbuffer_is_protected_) | 232 if (!frontbuffer_suggested_allocation_) |
256 return true; | 233 return true; |
257 if (!parent_stub_) { | |
258 LOG(ERROR) << "SwapBuffers failed because no parent stub."; | |
259 return false; | |
260 } | |
261 | 234 |
262 glFlush(); | 235 glFlush(); |
263 front_ = back(); | 236 previous_damage_rect_ = gfx::Rect(backbuffer_.size); |
264 previous_damage_rect_ = gfx::Rect(textures_[front()].size); | 237 ProduceTexture(backbuffer_); |
265 | 238 |
266 DCHECK(textures_[front()].client_id != 0); | 239 // Do not allow destruction while we are still waiting for a swap ACK. |
| 240 AddRef(); |
267 | 241 |
268 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; | 242 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; |
269 params.surface_handle = textures_[front()].client_id; | |
270 params.protection_state_id = protection_state_id_; | |
271 params.skip_ack = false; | |
272 helper_->SendAcceleratedSurfaceBuffersSwapped(params); | 243 helper_->SendAcceleratedSurfaceBuffersSwapped(params); |
273 | 244 |
274 DCHECK(!is_swap_buffers_pending_); | 245 DCHECK(!is_swap_buffers_pending_); |
275 is_swap_buffers_pending_ = true; | 246 is_swap_buffers_pending_ = true; |
276 return true; | 247 return true; |
277 } | 248 } |
278 | 249 |
279 bool TextureImageTransportSurface::PostSubBuffer( | 250 bool TextureImageTransportSurface::PostSubBuffer( |
280 int x, int y, int width, int height) { | 251 int x, int y, int width, int height) { |
281 DCHECK(backbuffer_suggested_allocation_); | 252 DCHECK(backbuffer_suggested_allocation_); |
282 DCHECK(textures_[back()].info->service_id()); | 253 DCHECK(backbuffer_.service_id); |
283 if (!frontbuffer_suggested_allocation_ || !frontbuffer_is_protected_) | 254 if (!frontbuffer_suggested_allocation_) |
284 return true; | 255 return true; |
285 // If we are recreating the frontbuffer with this swap, make sure we are | |
286 // drawing a full frame. | |
287 DCHECK(textures_[front()].info->service_id() || | |
288 (!x && !y && gfx::Size(width, height) == textures_[back()].size)); | |
289 if (!parent_stub_) { | |
290 LOG(ERROR) << "PostSubBuffer failed because no parent stub."; | |
291 return false; | |
292 } | |
293 | |
294 const gfx::Rect new_damage_rect(x, y, width, height); | 256 const gfx::Rect new_damage_rect(x, y, width, height); |
295 | 257 |
296 // An empty damage rect is a successful no-op. | 258 // An empty damage rect is a successful no-op. |
297 if (new_damage_rect.IsEmpty()) | 259 if (new_damage_rect.IsEmpty()) |
298 return true; | 260 return true; |
299 | 261 |
300 int back_texture_service_id = textures_[back()].info->service_id(); | 262 glFlush(); |
301 int front_texture_service_id = textures_[front()].info->service_id(); | 263 previous_damage_rect_ = new_damage_rect; |
| 264 ProduceTexture(backbuffer_); |
302 | 265 |
303 gfx::Size expected_size = textures_[back()].size; | 266 // Do not allow destruction while we are still waiting for a swap ACK. |
304 bool surfaces_same_size = textures_[front()].size == expected_size; | 267 AddRef(); |
305 | |
306 if (surfaces_same_size) { | |
307 std::vector<gfx::Rect> regions_to_copy; | |
308 GetRegionsToCopy(previous_damage_rect_, new_damage_rect, ®ions_to_copy); | |
309 | |
310 ScopedFrameBufferBinder fbo_binder(fbo_id_); | |
311 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, | |
312 GL_COLOR_ATTACHMENT0, | |
313 GL_TEXTURE_2D, | |
314 front_texture_service_id, | |
315 0); | |
316 ScopedTextureBinder texture_binder(back_texture_service_id); | |
317 | |
318 for (size_t i = 0; i < regions_to_copy.size(); ++i) { | |
319 const gfx::Rect& region_to_copy = regions_to_copy[i]; | |
320 if (!region_to_copy.IsEmpty()) { | |
321 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, region_to_copy.x(), | |
322 region_to_copy.y(), region_to_copy.x(), region_to_copy.y(), | |
323 region_to_copy.width(), region_to_copy.height()); | |
324 } | |
325 } | |
326 } else { | |
327 DCHECK(new_damage_rect == gfx::Rect(expected_size)); | |
328 } | |
329 | |
330 glFlush(); | |
331 front_ = back(); | |
332 previous_damage_rect_ = new_damage_rect; | |
333 | |
334 DCHECK(textures_[front()].client_id); | |
335 | 268 |
336 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; | 269 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; |
337 params.surface_handle = textures_[front()].client_id; | |
338 params.x = x; | 270 params.x = x; |
339 params.y = y; | 271 params.y = y; |
340 params.width = width; | 272 params.width = width; |
341 params.height = height; | 273 params.height = height; |
342 params.protection_state_id = protection_state_id_; | |
343 helper_->SendAcceleratedSurfacePostSubBuffer(params); | 274 helper_->SendAcceleratedSurfacePostSubBuffer(params); |
344 | 275 |
345 DCHECK(!is_swap_buffers_pending_); | 276 DCHECK(!is_swap_buffers_pending_); |
346 is_swap_buffers_pending_ = true; | 277 is_swap_buffers_pending_ = true; |
347 return true; | 278 return true; |
348 } | 279 } |
349 | 280 |
350 std::string TextureImageTransportSurface::GetExtensions() { | 281 std::string TextureImageTransportSurface::GetExtensions() { |
351 std::string extensions = gfx::GLSurface::GetExtensions(); | 282 std::string extensions = gfx::GLSurface::GetExtensions(); |
352 extensions += extensions.empty() ? "" : " "; | 283 extensions += extensions.empty() ? "" : " "; |
353 extensions += "GL_CHROMIUM_front_buffer_cached "; | 284 extensions += "GL_CHROMIUM_front_buffer_cached "; |
354 extensions += "GL_CHROMIUM_post_sub_buffer"; | 285 extensions += "GL_CHROMIUM_post_sub_buffer"; |
355 return extensions; | 286 return extensions; |
356 } | 287 } |
357 | 288 |
358 gfx::Size TextureImageTransportSurface::GetSize() { | 289 gfx::Size TextureImageTransportSurface::GetSize() { |
359 gfx::Size size = textures_[back()].size; | 290 gfx::Size size = current_size_; |
360 | 291 |
361 // OSMesa expects a non-zero size. | 292 // OSMesa expects a non-zero size. |
362 return gfx::Size(size.width() == 0 ? 1 : size.width(), | 293 return gfx::Size(size.width() == 0 ? 1 : size.width(), |
363 size.height() == 0 ? 1 : size.height()); | 294 size.height() == 0 ? 1 : size.height()); |
364 } | 295 } |
365 | 296 |
366 void* TextureImageTransportSurface::GetHandle() { | 297 void* TextureImageTransportSurface::GetHandle() { |
367 return surface_.get() ? surface_->GetHandle() : NULL; | 298 return surface_.get() ? surface_->GetHandle() : NULL; |
368 } | 299 } |
369 | 300 |
370 unsigned TextureImageTransportSurface::GetFormat() { | 301 unsigned TextureImageTransportSurface::GetFormat() { |
371 return surface_.get() ? surface_->GetFormat() : 0; | 302 return surface_.get() ? surface_->GetFormat() : 0; |
372 } | 303 } |
373 | 304 |
374 void TextureImageTransportSurface::OnSetFrontSurfaceIsProtected( | |
375 bool is_protected, uint32 protection_state_id) { | |
376 protection_state_id_ = protection_state_id; | |
377 if (frontbuffer_is_protected_ == is_protected) | |
378 return; | |
379 frontbuffer_is_protected_ = is_protected; | |
380 AdjustFrontBufferAllocation(); | |
381 | |
382 // If surface is set to protected, and we haven't actually released it yet, | |
383 // we can set the ui surface handle now just by sending a swap message. | |
384 if (is_protected && textures_[front()].info->service_id() && | |
385 textures_[front()].sent_to_client) { | |
386 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; | |
387 params.surface_handle = textures_[front()].client_id; | |
388 params.protection_state_id = protection_state_id_; | |
389 params.skip_ack = true; | |
390 helper_->SendAcceleratedSurfaceBuffersSwapped(params); | |
391 } | |
392 } | |
393 | |
394 void TextureImageTransportSurface::OnBufferPresented(uint32 sync_point) { | 305 void TextureImageTransportSurface::OnBufferPresented(uint32 sync_point) { |
395 if (sync_point == 0) { | 306 if (sync_point == 0) { |
396 BufferPresentedImpl(); | 307 BufferPresentedImpl(); |
397 } else { | 308 } else { |
398 helper_->manager()->sync_point_manager()->AddSyncPointCallback( | 309 helper_->manager()->sync_point_manager()->AddSyncPointCallback( |
399 sync_point, | 310 sync_point, |
400 base::Bind(&TextureImageTransportSurface::BufferPresentedImpl, | 311 base::Bind(&TextureImageTransportSurface::BufferPresentedImpl, this)); |
401 this->AsWeakPtr())); | |
402 } | 312 } |
| 313 |
| 314 // Careful, we might get deleted now if we were only waiting for |
| 315 // a final swap ACK. |
| 316 Release(); |
403 } | 317 } |
404 | 318 |
405 void TextureImageTransportSurface::BufferPresentedImpl() { | 319 void TextureImageTransportSurface::BufferPresentedImpl() { |
| 320 if (stub_destroyed_) |
| 321 return; |
| 322 |
406 DCHECK(is_swap_buffers_pending_); | 323 DCHECK(is_swap_buffers_pending_); |
407 is_swap_buffers_pending_ = false; | 324 is_swap_buffers_pending_ = false; |
408 | 325 |
409 // We're relying on the fact that the parent context is | 326 // We're relying on the fact that the parent context is |
410 // finished with it's context when it inserts the sync point that | 327 // finished with it's context when it inserts the sync point that |
411 // triggers this callback. | 328 // triggers this callback. |
412 if (helper_->MakeCurrent()) { | 329 if (helper_->MakeCurrent()) { |
413 if (textures_[front()].size != textures_[back()].size || | 330 DCHECK(!backbuffer_.service_id); |
414 !textures_[back()].info->service_id() || | 331 ConsumeTexture(backbuffer_); |
415 !textures_[back()].sent_to_client) { | 332 if (backbuffer_.size != current_size_ || |
| 333 !backbuffer_.service_id) { |
416 // We may get an ACK from a stale swap just to reschedule. In that case, | 334 // We may get an ACK from a stale swap just to reschedule. In that case, |
417 // we may not have a backbuffer suggestion and should not recreate one. | 335 // we may not have a backbuffer suggestion and should not recreate one. |
418 if (backbuffer_suggested_allocation_) | 336 if (backbuffer_suggested_allocation_) |
419 CreateBackTexture(textures_[front()].size); | 337 CreateBackTexture(); |
420 } else { | 338 } else { |
421 AttachBackTextureToFBO(); | 339 AttachBackTextureToFBO(); |
422 } | 340 } |
423 } | 341 } |
424 | 342 |
425 // Even if MakeCurrent fails, schedule anyway, to trigger the lost context | 343 // Even if MakeCurrent fails, schedule anyway, to trigger the lost context |
426 // logic. | 344 // logic. |
427 if (did_unschedule_) { | 345 if (did_unschedule_) { |
428 did_unschedule_ = false; | 346 did_unschedule_ = false; |
429 helper_->SetScheduled(true); | 347 helper_->SetScheduled(true); |
430 } | 348 } |
431 } | 349 } |
432 | 350 |
433 void TextureImageTransportSurface::OnResizeViewACK() { | 351 void TextureImageTransportSurface::OnResizeViewACK() { |
434 NOTREACHED(); | 352 NOTREACHED(); |
435 } | 353 } |
436 | 354 |
437 void TextureImageTransportSurface::ReleaseTexture(int id) { | 355 void TextureImageTransportSurface::ReleaseBackBuffer() { |
438 if (!parent_stub_) | 356 if (!backbuffer_.service_id) |
439 return; | 357 return; |
440 Texture& texture = textures_[id]; | |
441 TextureInfo* info = texture.info; | |
442 DCHECK(info); | |
443 | |
444 GLuint service_id = info->service_id(); | |
445 if (!service_id) | |
446 return; | |
447 info->SetServiceId(0); | |
448 | 358 |
449 { | 359 { |
450 ScopedFrameBufferBinder fbo_binder(fbo_id_); | 360 ScopedFrameBufferBinder fbo_binder(fbo_id_); |
451 glDeleteTextures(1, &service_id); | 361 glDeleteTextures(1, &backbuffer_.service_id); |
| 362 backbuffer_.service_id = 0; |
452 } | 363 } |
453 glFlush(); | 364 glFlush(); |
454 CHECK_GL_ERROR(); | 365 CHECK_GL_ERROR(); |
455 } | 366 } |
456 | 367 |
457 void TextureImageTransportSurface::CreateBackTexture(const gfx::Size& size) { | 368 void TextureImageTransportSurface::CreateBackTexture() { |
458 if (!parent_stub_) | 369 // We are waiting for our backbuffer in the mailbox, so we shouldn't be |
459 return; | 370 // reallocating the backbuffer now. |
460 Texture& texture = textures_[back()]; | 371 DCHECK(!is_swap_buffers_pending_); |
461 TextureInfo* info = texture.info; | |
462 DCHECK(info); | |
463 | 372 |
464 GLuint service_id = info->service_id(); | 373 gfx::Size& size = current_size_; |
| 374 Texture& texture = backbuffer_; |
465 | 375 |
466 if (service_id && texture.size == size && texture.sent_to_client) | 376 if (texture.service_id && texture.size == size) |
467 return; | 377 return; |
468 | 378 |
469 if (!service_id) { | 379 if (!texture.service_id) { |
470 glGenTextures(1, &service_id); | 380 glGenTextures(1, &texture.service_id); |
471 info->SetServiceId(service_id); | |
472 } | 381 } |
473 | 382 |
474 if (size != texture.size) { | 383 if (size != texture.size) { |
475 texture.size = size; | 384 texture.size = size; |
476 TextureManager* texture_manager = | |
477 parent_stub_->decoder()->GetContextGroup()->texture_manager(); | |
478 texture_manager->SetLevelInfo( | |
479 info, | |
480 GL_TEXTURE_2D, | |
481 0, | |
482 GL_RGBA, | |
483 size.width(), | |
484 size.height(), | |
485 1, | |
486 0, | |
487 GL_RGBA, | |
488 GL_UNSIGNED_BYTE, | |
489 true); | |
490 } | 385 } |
491 | 386 |
492 { | 387 { |
493 ScopedTextureBinder texture_binder(service_id); | 388 ScopedTextureBinder texture_binder(texture.service_id); |
494 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 389 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
495 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 390 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
496 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 391 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
497 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 392 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
498 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, | 393 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, |
499 size.width(), size.height(), 0, | 394 size.width(), size.height(), 0, |
500 GL_RGBA, GL_UNSIGNED_BYTE, NULL); | 395 GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
501 CHECK_GL_ERROR(); | 396 CHECK_GL_ERROR(); |
502 } | 397 } |
503 | 398 |
504 AttachBackTextureToFBO(); | 399 AttachBackTextureToFBO(); |
505 | |
506 GpuHostMsg_AcceleratedSurfaceNew_Params params; | |
507 params.width = size.width(); | |
508 params.height = size.height(); | |
509 params.surface_handle = texture.client_id; | |
510 helper_->SendAcceleratedSurfaceNew(params); | |
511 texture.sent_to_client = true; | |
512 } | 400 } |
513 | 401 |
514 void TextureImageTransportSurface::AttachBackTextureToFBO() { | 402 void TextureImageTransportSurface::AttachBackTextureToFBO() { |
515 if (!parent_stub_) | 403 DCHECK(backbuffer_.service_id); |
516 return; | |
517 TextureInfo* info = textures_[back()].info; | |
518 DCHECK(info); | |
519 | |
520 ScopedFrameBufferBinder fbo_binder(fbo_id_); | 404 ScopedFrameBufferBinder fbo_binder(fbo_id_); |
521 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, | 405 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, |
522 GL_COLOR_ATTACHMENT0, | 406 GL_COLOR_ATTACHMENT0, |
523 GL_TEXTURE_2D, | 407 GL_TEXTURE_2D, |
524 info->service_id(), | 408 backbuffer_.service_id, |
525 0); | 409 0); |
526 glFlush(); | 410 glFlush(); |
527 CHECK_GL_ERROR(); | 411 CHECK_GL_ERROR(); |
528 | 412 |
529 #ifndef NDEBUG | 413 #ifndef NDEBUG |
530 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); | 414 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); |
531 if (status != GL_FRAMEBUFFER_COMPLETE) { | 415 if (status != GL_FRAMEBUFFER_COMPLETE) { |
532 DLOG(ERROR) << "Framebuffer incomplete."; | 416 DLOG(ERROR) << "Framebuffer incomplete: " << status; |
| 417 DCHECK(false); |
533 } | 418 } |
534 #endif | 419 #endif |
535 } | 420 } |
536 | 421 |
537 void TextureImageTransportSurface::ReleaseParentStub() { | 422 void TextureImageTransportSurface::ConsumeTexture(Texture& texture) { |
538 DCHECK(parent_stub_); | 423 DCHECK(!texture.service_id); |
539 parent_stub_->RemoveDestructionObserver(this); | 424 scoped_ptr<TextureDefinition> definition(mailbox_manager_->ConsumeTexture( |
540 for (int i = 0; i < 2; ++i) { | 425 GL_TEXTURE_2D, mailbox_name_)); |
541 Texture& texture = textures_[i]; | 426 if (definition.get()) { |
542 texture.info = NULL; | 427 texture.service_id = definition->ReleaseServiceId(); |
543 if (!texture.sent_to_client) | 428 texture.size = gfx::Size(definition->level_infos()[0][0].width, |
544 continue; | 429 definition->level_infos()[0][0].height); |
545 GpuHostMsg_AcceleratedSurfaceRelease_Params params; | |
546 params.identifier = texture.client_id; | |
547 helper_->SendAcceleratedSurfaceRelease(params); | |
548 } | 430 } |
549 parent_stub_ = NULL; | 431 } |
| 432 |
| 433 void TextureImageTransportSurface::ProduceTexture(Texture& texture) { |
| 434 DCHECK(texture.service_id); |
| 435 TextureManager* texture_manager = |
| 436 helper_->stub()->decoder()->GetContextGroup()->texture_manager(); |
| 437 DCHECK(texture.size.width() > 0 && texture.size.height() > 0); |
| 438 TextureDefinition::LevelInfo info( |
| 439 GL_TEXTURE_2D, GL_RGBA, texture.size.width(), texture.size.height(), 1, |
| 440 0, GL_RGBA, GL_UNSIGNED_BYTE, true); |
| 441 |
| 442 TextureDefinition::LevelInfos level_infos; |
| 443 level_infos.resize(1); |
| 444 level_infos[0].resize(texture_manager->MaxLevelsForTarget(GL_TEXTURE_2D)); |
| 445 level_infos[0][0] = info; |
| 446 scoped_ptr<TextureDefinition> definition(new TextureDefinition( |
| 447 GL_TEXTURE_2D, |
| 448 texture.service_id, |
| 449 true, |
| 450 level_infos)); |
| 451 mailbox_manager_->ProduceTexture( |
| 452 GL_TEXTURE_2D, |
| 453 mailbox_name_, |
| 454 definition.release(), |
| 455 helper_->stub()->decoder()->GetContextGroup()->texture_manager()); |
| 456 texture.service_id = 0; |
550 } | 457 } |
551 | 458 |
552 } // namespace content | 459 } // namespace content |
OLD | NEW |