OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/common/gpu/texture_image_transport_surface.h" | 5 #include "content/common/gpu/texture_image_transport_surface.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "content/common/gpu/gpu_channel.h" | 8 #include "content/common/gpu/gpu_channel.h" |
9 #include "content/common/gpu/gpu_channel_manager.h" | 9 #include "content/common/gpu/gpu_channel_manager.h" |
10 #include "content/common/gpu/gpu_messages.h" | 10 #include "content/common/gpu/gpu_messages.h" |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
62 | 62 |
63 TextureImageTransportSurface::TextureImageTransportSurface( | 63 TextureImageTransportSurface::TextureImageTransportSurface( |
64 GpuChannelManager* manager, | 64 GpuChannelManager* manager, |
65 GpuCommandBufferStub* stub, | 65 GpuCommandBufferStub* stub, |
66 const gfx::GLSurfaceHandle& handle) | 66 const gfx::GLSurfaceHandle& handle) |
67 : fbo_id_(0), | 67 : fbo_id_(0), |
68 front_(0), | 68 front_(0), |
69 stub_destroyed_(false), | 69 stub_destroyed_(false), |
70 backbuffer_suggested_allocation_(true), | 70 backbuffer_suggested_allocation_(true), |
71 frontbuffer_suggested_allocation_(true), | 71 frontbuffer_suggested_allocation_(true), |
72 frontbuffer_is_protected_(true), | |
73 protection_state_id_(0), | |
72 handle_(handle), | 74 handle_(handle), |
73 parent_stub_(NULL) { | 75 parent_stub_(NULL) { |
74 helper_.reset(new ImageTransportHelper(this, | 76 helper_.reset(new ImageTransportHelper(this, |
75 manager, | 77 manager, |
76 stub, | 78 stub, |
77 gfx::kNullPluginWindow)); | 79 gfx::kNullPluginWindow)); |
78 | 80 |
79 stub->AddDestructionObserver(this); | 81 stub->AddDestructionObserver(this); |
80 } | 82 } |
81 | 83 |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
175 } | 177 } |
176 | 178 |
177 void TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) { | 179 void TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) { |
178 if (backbuffer_suggested_allocation_ == allocation) | 180 if (backbuffer_suggested_allocation_ == allocation) |
179 return; | 181 return; |
180 backbuffer_suggested_allocation_ = allocation; | 182 backbuffer_suggested_allocation_ = allocation; |
181 | 183 |
182 if (!helper_->MakeCurrent()) | 184 if (!helper_->MakeCurrent()) |
183 return; | 185 return; |
184 | 186 |
185 if (backbuffer_suggested_allocation_) | 187 if (backbuffer_suggested_allocation_) { |
188 DCHECK(!textures_[back()].info->service_id() || | |
189 !textures_[back()].sent_to_client); | |
186 CreateBackTexture(textures_[back()].size); | 190 CreateBackTexture(textures_[back()].size); |
187 else | 191 } else { |
188 ReleaseBackTexture(); | 192 ReleaseTexture(back()); |
193 } | |
189 } | 194 } |
190 | 195 |
191 void TextureImageTransportSurface::SetFrontbufferAllocation(bool allocation) { | 196 void TextureImageTransportSurface::SetFrontbufferAllocation(bool allocation) { |
192 if (frontbuffer_suggested_allocation_ == allocation) | 197 if (frontbuffer_suggested_allocation_ == allocation) |
193 return; | 198 return; |
194 frontbuffer_suggested_allocation_ = allocation; | 199 frontbuffer_suggested_allocation_ = allocation; |
200 AdjustFrontBufferAllocation(); | |
201 } | |
202 | |
203 void TextureImageTransportSurface::AdjustFrontBufferAllocation() { | |
204 if (!helper_->MakeCurrent()) | |
205 return; | |
206 | |
207 if (!frontbuffer_suggested_allocation_ && !frontbuffer_is_protected_ && | |
208 textures_[front()].info->service_id()) { | |
209 ReleaseTexture(front()); | |
210 if (textures_[front()].sent_to_client) { | |
211 GpuHostMsg_AcceleratedSurfaceRelease_Params params; | |
212 params.identifier = textures_[front()].client_id; | |
213 helper_->SendAcceleratedSurfaceRelease(params); | |
214 textures_[front()].sent_to_client = false; | |
215 } | |
216 } | |
195 } | 217 } |
196 | 218 |
197 void* TextureImageTransportSurface::GetShareHandle() { | 219 void* TextureImageTransportSurface::GetShareHandle() { |
198 return GetHandle(); | 220 return GetHandle(); |
199 } | 221 } |
200 | 222 |
201 void* TextureImageTransportSurface::GetDisplay() { | 223 void* TextureImageTransportSurface::GetDisplay() { |
202 return parent_stub_ ? parent_stub_->surface()->GetDisplay() : NULL; | 224 return parent_stub_ ? parent_stub_->surface()->GetDisplay() : NULL; |
203 } | 225 } |
204 | 226 |
(...skipping 20 matching lines...) Expand all Loading... | |
225 CHECK_GL_ERROR(); | 247 CHECK_GL_ERROR(); |
226 fbo_id_ = 0; | 248 fbo_id_ = 0; |
227 } | 249 } |
228 | 250 |
229 stub_destroyed_ = true; | 251 stub_destroyed_ = true; |
230 } | 252 } |
231 } | 253 } |
232 | 254 |
233 bool TextureImageTransportSurface::SwapBuffers() { | 255 bool TextureImageTransportSurface::SwapBuffers() { |
234 DCHECK(backbuffer_suggested_allocation_); | 256 DCHECK(backbuffer_suggested_allocation_); |
235 if (!frontbuffer_suggested_allocation_) | 257 if (!frontbuffer_suggested_allocation_ || !frontbuffer_is_protected_) |
236 return true; | 258 return true; |
237 if (!parent_stub_) { | 259 if (!parent_stub_) { |
238 LOG(ERROR) << "SwapBuffers failed because no parent stub."; | 260 LOG(ERROR) << "SwapBuffers failed because no parent stub."; |
239 return false; | 261 return false; |
240 } | 262 } |
241 | 263 |
242 glFlush(); | 264 glFlush(); |
243 front_ = back(); | 265 front_ = back(); |
244 previous_damage_rect_ = gfx::Rect(textures_[front_].size); | 266 previous_damage_rect_ = gfx::Rect(textures_[front()].size); |
245 | 267 |
246 DCHECK(textures_[front_].client_id != 0); | 268 DCHECK(textures_[front()].client_id != 0); |
247 | 269 |
248 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; | 270 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; |
249 params.surface_handle = textures_[front_].client_id; | 271 params.surface_handle = textures_[front()].client_id; |
272 #if defined(USE_AURA) | |
273 params.protection_state_id = protection_state_id_; | |
274 params.require_ack = true; | |
275 #endif | |
250 helper_->SendAcceleratedSurfaceBuffersSwapped(params); | 276 helper_->SendAcceleratedSurfaceBuffersSwapped(params); |
251 helper_->SetScheduled(false); | 277 helper_->SetScheduled(false); |
252 return true; | 278 return true; |
253 } | 279 } |
254 | 280 |
255 bool TextureImageTransportSurface::PostSubBuffer( | 281 bool TextureImageTransportSurface::PostSubBuffer( |
256 int x, int y, int width, int height) { | 282 int x, int y, int width, int height) { |
257 DCHECK(backbuffer_suggested_allocation_); | 283 DCHECK(backbuffer_suggested_allocation_); |
258 if (!frontbuffer_suggested_allocation_) | 284 DCHECK(textures_[back()].info->service_id()); |
285 if (!frontbuffer_suggested_allocation_ || !frontbuffer_is_protected_) | |
259 return true; | 286 return true; |
260 // If we are recreating the frontbuffer with this swap, make sure we are | 287 // If we are recreating the frontbuffer with this swap, make sure we are |
261 // drawing a full frame. | 288 // drawing a full frame. |
262 DCHECK(textures_[front_].info->service_id() || | 289 DCHECK(textures_[front()].info->service_id() || |
263 (!x && !y && gfx::Size(width, height) == textures_[back()].size)); | 290 (!x && !y && gfx::Size(width, height) == textures_[back()].size)); |
264 if (!parent_stub_) { | 291 if (!parent_stub_) { |
265 LOG(ERROR) << "PostSubBuffer failed because no parent stub."; | 292 LOG(ERROR) << "PostSubBuffer failed because no parent stub."; |
266 return false; | 293 return false; |
267 } | 294 } |
268 | 295 |
269 DCHECK(textures_[back()].info); | |
270 int back_texture_service_id = textures_[back()].info->service_id(); | |
271 | |
272 DCHECK(textures_[front_].info); | |
273 int front_texture_service_id = textures_[front_].info->service_id(); | |
274 | |
275 gfx::Size expected_size = textures_[back()].size; | |
276 bool surfaces_same_size = textures_[front_].size == expected_size; | |
277 | |
278 const gfx::Rect new_damage_rect(x, y, width, height); | 296 const gfx::Rect new_damage_rect(x, y, width, height); |
279 | 297 |
280 // An empty damage rect is a successful no-op. | 298 // An empty damage rect is a successful no-op. |
281 if (new_damage_rect.IsEmpty()) | 299 if (new_damage_rect.IsEmpty()) |
282 return true; | 300 return true; |
283 | 301 |
302 int back_texture_service_id = textures_[back()].info->service_id(); | |
303 int front_texture_service_id = textures_[front()].info->service_id(); | |
304 | |
305 gfx::Size expected_size = textures_[back()].size; | |
306 bool surfaces_same_size = textures_[front()].size == expected_size; | |
307 | |
284 if (surfaces_same_size) { | 308 if (surfaces_same_size) { |
285 std::vector<gfx::Rect> regions_to_copy; | 309 std::vector<gfx::Rect> regions_to_copy; |
286 GetRegionsToCopy(previous_damage_rect_, new_damage_rect, ®ions_to_copy); | 310 GetRegionsToCopy(previous_damage_rect_, new_damage_rect, ®ions_to_copy); |
287 | 311 |
288 ScopedFrameBufferBinder fbo_binder(fbo_id_); | 312 ScopedFrameBufferBinder fbo_binder(fbo_id_); |
289 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, | 313 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, |
290 GL_COLOR_ATTACHMENT0, | 314 GL_COLOR_ATTACHMENT0, |
291 GL_TEXTURE_2D, | 315 GL_TEXTURE_2D, |
292 front_texture_service_id, | 316 front_texture_service_id, |
293 0); | 317 0); |
294 ScopedTextureBinder texture_binder(back_texture_service_id); | 318 ScopedTextureBinder texture_binder(back_texture_service_id); |
295 | 319 |
296 for (size_t i = 0; i < regions_to_copy.size(); ++i) { | 320 for (size_t i = 0; i < regions_to_copy.size(); ++i) { |
297 const gfx::Rect& region_to_copy = regions_to_copy[i]; | 321 const gfx::Rect& region_to_copy = regions_to_copy[i]; |
298 if (!region_to_copy.IsEmpty()) { | 322 if (!region_to_copy.IsEmpty()) { |
299 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, region_to_copy.x(), | 323 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, region_to_copy.x(), |
300 region_to_copy.y(), region_to_copy.x(), region_to_copy.y(), | 324 region_to_copy.y(), region_to_copy.x(), region_to_copy.y(), |
301 region_to_copy.width(), region_to_copy.height()); | 325 region_to_copy.width(), region_to_copy.height()); |
302 } | 326 } |
303 } | 327 } |
304 } else { | 328 } else { |
305 DCHECK(new_damage_rect == gfx::Rect(expected_size)); | 329 DCHECK(new_damage_rect == gfx::Rect(expected_size)); |
306 } | 330 } |
307 | 331 |
308 glFlush(); | 332 glFlush(); |
309 front_ = back(); | 333 front_ = back(); |
334 previous_damage_rect_ = new_damage_rect; | |
335 | |
336 DCHECK(textures_[front()].client_id); | |
310 | 337 |
311 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; | 338 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; |
312 params.surface_handle = textures_[front_].client_id; | 339 params.surface_handle = textures_[front()].client_id; |
313 params.x = x; | 340 params.x = x; |
314 params.y = y; | 341 params.y = y; |
315 params.width = width; | 342 params.width = width; |
316 params.height = height; | 343 params.height = height; |
344 #if defined(USE_AURA) | |
piman
2012/06/12 23:05:12
nit: somehow it feels wrong to have a #ifdef USE_A
| |
345 params.protection_state_id = protection_state_id_; | |
346 #endif | |
317 helper_->SendAcceleratedSurfacePostSubBuffer(params); | 347 helper_->SendAcceleratedSurfacePostSubBuffer(params); |
318 helper_->SetScheduled(false); | 348 helper_->SetScheduled(false); |
319 | |
320 previous_damage_rect_ = new_damage_rect; | |
321 return true; | 349 return true; |
322 } | 350 } |
323 | 351 |
324 std::string TextureImageTransportSurface::GetExtensions() { | 352 std::string TextureImageTransportSurface::GetExtensions() { |
325 std::string extensions = gfx::GLSurface::GetExtensions(); | 353 std::string extensions = gfx::GLSurface::GetExtensions(); |
326 extensions += extensions.empty() ? "" : " "; | 354 extensions += extensions.empty() ? "" : " "; |
327 extensions += "GL_CHROMIUM_front_buffer_cached "; | 355 extensions += "GL_CHROMIUM_front_buffer_cached "; |
328 extensions += "GL_CHROMIUM_post_sub_buffer"; | 356 extensions += "GL_CHROMIUM_post_sub_buffer"; |
329 return extensions; | 357 return extensions; |
330 } | 358 } |
331 | 359 |
332 gfx::Size TextureImageTransportSurface::GetSize() { | 360 gfx::Size TextureImageTransportSurface::GetSize() { |
333 return textures_[back()].size; | 361 return textures_[back()].size; |
334 } | 362 } |
335 | 363 |
336 void* TextureImageTransportSurface::GetHandle() { | 364 void* TextureImageTransportSurface::GetHandle() { |
337 return parent_stub_ ? parent_stub_->surface()->GetHandle() : NULL; | 365 return parent_stub_ ? parent_stub_->surface()->GetHandle() : NULL; |
338 } | 366 } |
339 | 367 |
340 | 368 |
341 void TextureImageTransportSurface::OnNewSurfaceACK( | 369 void TextureImageTransportSurface::OnNewSurfaceACK( |
342 uint64 surface_handle, TransportDIB::Handle /*shm_handle*/) { | 370 uint64 surface_handle, TransportDIB::Handle /*shm_handle*/) { |
343 } | 371 } |
344 | 372 |
373 void TextureImageTransportSurface::OnSetFrontSurfaceIsProtected( | |
374 bool is_protected, uint32 protection_state_id) { | |
375 protection_state_id_ = protection_state_id; | |
376 if (frontbuffer_is_protected_ == is_protected) | |
377 return; | |
378 frontbuffer_is_protected_ = is_protected; | |
379 AdjustFrontBufferAllocation(); | |
380 | |
381 // If surface is set to protected, and we haven't actually released it yet, | |
382 // we can set the ui surface handle now just by sending a swap message. | |
383 if (is_protected && textures_[front()].info->service_id() && | |
384 textures_[front()].sent_to_client) { | |
385 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; | |
386 params.surface_handle = textures_[front()].client_id; | |
387 #if defined(USE_AURA) | |
388 params.protection_state_id = protection_state_id_; | |
389 params.require_ack = false; | |
390 #endif | |
391 helper_->SendAcceleratedSurfaceBuffersSwapped(params); | |
392 } | |
393 } | |
394 | |
345 void TextureImageTransportSurface::OnBuffersSwappedACK() { | 395 void TextureImageTransportSurface::OnBuffersSwappedACK() { |
346 if (helper_->MakeCurrent()) { | 396 if (helper_->MakeCurrent()) { |
347 if (textures_[front_].size != textures_[back()].size) { | 397 if (textures_[front()].size != textures_[back()].size || |
348 CreateBackTexture(textures_[front_].size); | 398 !textures_[back()].info->service_id() || |
399 !textures_[back()].sent_to_client) { | |
400 // We may get an ACK from a stale swap just to reschedule. In that case, | |
401 // we may not have a backbuffer suggestion and should not recreate one. | |
402 if (backbuffer_suggested_allocation_) | |
403 CreateBackTexture(textures_[front()].size); | |
349 } else { | 404 } else { |
350 AttachBackTextureToFBO(); | 405 AttachBackTextureToFBO(); |
351 } | 406 } |
352 } | 407 } |
353 | 408 |
354 // Even if MakeCurrent fails, schedule anyway, to trigger the lost context | 409 // Even if MakeCurrent fails, schedule anyway, to trigger the lost context |
355 // logic. | 410 // logic. |
356 helper_->SetScheduled(true); | 411 helper_->SetScheduled(true); |
357 } | 412 } |
358 | 413 |
359 void TextureImageTransportSurface::OnPostSubBufferACK() { | 414 void TextureImageTransportSurface::OnPostSubBufferACK() { |
360 OnBuffersSwappedACK(); | 415 OnBuffersSwappedACK(); |
361 } | 416 } |
362 | 417 |
363 void TextureImageTransportSurface::OnResizeViewACK() { | 418 void TextureImageTransportSurface::OnResizeViewACK() { |
364 NOTREACHED(); | 419 NOTREACHED(); |
365 } | 420 } |
366 | 421 |
367 void TextureImageTransportSurface::ReleaseBackTexture() { | 422 void TextureImageTransportSurface::ReleaseTexture(int id) { |
368 if (!parent_stub_) | 423 if (!parent_stub_) |
369 return; | 424 return; |
370 TextureInfo* info = textures_[back()].info; | 425 Texture& texture = textures_[id]; |
426 TextureInfo* info = texture.info; | |
371 DCHECK(info); | 427 DCHECK(info); |
372 | 428 |
373 GLuint service_id = info->service_id(); | 429 GLuint service_id = info->service_id(); |
374 if (!service_id) | 430 if (!service_id) |
375 return; | 431 return; |
376 info->SetServiceId(0); | 432 info->SetServiceId(0); |
377 | 433 |
378 { | 434 { |
379 ScopedFrameBufferBinder fbo_binder(fbo_id_); | 435 ScopedFrameBufferBinder fbo_binder(fbo_id_); |
380 glDeleteTextures(1, &service_id); | 436 glDeleteTextures(1, &service_id); |
381 } | 437 } |
382 glFlush(); | 438 glFlush(); |
383 CHECK_GL_ERROR(); | 439 CHECK_GL_ERROR(); |
384 } | 440 } |
385 | 441 |
386 void TextureImageTransportSurface::CreateBackTexture(const gfx::Size& size) { | 442 void TextureImageTransportSurface::CreateBackTexture(const gfx::Size& size) { |
387 if (!parent_stub_) | 443 if (!parent_stub_) |
388 return; | 444 return; |
389 Texture& texture = textures_[back()]; | 445 Texture& texture = textures_[back()]; |
390 TextureInfo* info = texture.info; | 446 TextureInfo* info = texture.info; |
391 DCHECK(info); | 447 DCHECK(info); |
392 | 448 |
393 GLuint service_id = info->service_id(); | 449 GLuint service_id = info->service_id(); |
394 | 450 |
395 if (service_id && texture.size == size) | 451 if (service_id && texture.size == size && texture.sent_to_client) |
396 return; | 452 return; |
397 | 453 |
398 if (!service_id) { | 454 if (!service_id) { |
399 glGenTextures(1, &service_id); | 455 glGenTextures(1, &service_id); |
400 info->SetServiceId(service_id); | 456 info->SetServiceId(service_id); |
401 } | 457 } |
402 | 458 |
403 if (size != texture.size) { | 459 if (size != texture.size) { |
404 texture.size = size; | 460 texture.size = size; |
405 TextureManager* texture_manager = | 461 TextureManager* texture_manager = |
(...skipping 30 matching lines...) Expand all Loading... | |
436 params.width = size.width(); | 492 params.width = size.width(); |
437 params.height = size.height(); | 493 params.height = size.height(); |
438 params.surface_handle = texture.client_id; | 494 params.surface_handle = texture.client_id; |
439 helper_->SendAcceleratedSurfaceNew(params); | 495 helper_->SendAcceleratedSurfaceNew(params); |
440 texture.sent_to_client = true; | 496 texture.sent_to_client = true; |
441 } | 497 } |
442 | 498 |
443 void TextureImageTransportSurface::AttachBackTextureToFBO() { | 499 void TextureImageTransportSurface::AttachBackTextureToFBO() { |
444 if (!parent_stub_) | 500 if (!parent_stub_) |
445 return; | 501 return; |
446 DCHECK(textures_[back()].info); | 502 TextureInfo* info = textures_[back()].info; |
503 DCHECK(info); | |
447 | 504 |
448 ScopedFrameBufferBinder fbo_binder(fbo_id_); | 505 ScopedFrameBufferBinder fbo_binder(fbo_id_); |
449 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, | 506 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, |
450 GL_COLOR_ATTACHMENT0, | 507 GL_COLOR_ATTACHMENT0, |
451 GL_TEXTURE_2D, | 508 GL_TEXTURE_2D, |
452 textures_[back()].info->service_id(), | 509 info->service_id(), |
453 0); | 510 0); |
454 glFlush(); | 511 glFlush(); |
455 CHECK_GL_ERROR(); | 512 CHECK_GL_ERROR(); |
456 | 513 |
457 #ifndef NDEBUG | 514 #ifndef NDEBUG |
458 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); | 515 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); |
459 if (status != GL_FRAMEBUFFER_COMPLETE) { | 516 if (status != GL_FRAMEBUFFER_COMPLETE) { |
460 DLOG(ERROR) << "Framebuffer incomplete."; | 517 DLOG(ERROR) << "Framebuffer incomplete."; |
461 } | 518 } |
462 #endif | 519 #endif |
463 } | 520 } |
464 | 521 |
465 void TextureImageTransportSurface::ReleaseParentStub() { | 522 void TextureImageTransportSurface::ReleaseParentStub() { |
466 DCHECK(parent_stub_); | 523 DCHECK(parent_stub_); |
467 parent_stub_->RemoveDestructionObserver(this); | 524 parent_stub_->RemoveDestructionObserver(this); |
468 for (int i = 0; i < 2; ++i) { | 525 for (int i = 0; i < 2; ++i) { |
469 Texture& texture = textures_[i]; | 526 Texture& texture = textures_[i]; |
470 texture.info = NULL; | 527 texture.info = NULL; |
471 if (!texture.sent_to_client) | 528 if (!texture.sent_to_client) |
472 continue; | 529 continue; |
473 GpuHostMsg_AcceleratedSurfaceRelease_Params params; | 530 GpuHostMsg_AcceleratedSurfaceRelease_Params params; |
474 params.identifier = texture.client_id; | 531 params.identifier = texture.client_id; |
475 helper_->SendAcceleratedSurfaceRelease(params); | 532 helper_->SendAcceleratedSurfaceRelease(params); |
476 } | 533 } |
477 parent_stub_ = NULL; | 534 parent_stub_ = NULL; |
478 } | 535 } |
OLD | NEW |