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 <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 DCHECK(stub_destroyed_); | 50 DCHECK(stub_destroyed_); |
51 Destroy(); | 51 Destroy(); |
52 } | 52 } |
53 | 53 |
54 bool TextureImageTransportSurface::Initialize() { | 54 bool TextureImageTransportSurface::Initialize() { |
55 mailbox_manager_ = | 55 mailbox_manager_ = |
56 helper_->stub()->decoder()->GetContextGroup()->mailbox_manager(); | 56 helper_->stub()->decoder()->GetContextGroup()->mailbox_manager(); |
57 | 57 |
58 GpuChannelManager* manager = helper_->manager(); | 58 GpuChannelManager* manager = helper_->manager(); |
59 surface_ = manager->GetDefaultOffscreenSurface(); | 59 surface_ = manager->GetDefaultOffscreenSurface(); |
60 if (!surface_) | 60 if (!surface_.get()) |
61 return false; | 61 return false; |
62 | 62 |
63 if (!helper_->Initialize()) | 63 if (!helper_->Initialize()) |
64 return false; | 64 return false; |
65 | 65 |
66 GpuChannel* parent_channel = manager->LookupChannel(handle_.parent_client_id); | 66 GpuChannel* parent_channel = manager->LookupChannel(handle_.parent_client_id); |
67 if (parent_channel) { | 67 if (parent_channel) { |
68 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | 68 const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
69 if (command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess)) | 69 if (command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess)) |
70 helper_->SetPreemptByFlag(parent_channel->GetPreemptionFlag()); | 70 helper_->SetPreemptByFlag(parent_channel->GetPreemptionFlag()); |
71 } | 71 } |
72 | 72 |
73 return true; | 73 return true; |
74 } | 74 } |
75 | 75 |
76 void TextureImageTransportSurface::Destroy() { | 76 void TextureImageTransportSurface::Destroy() { |
77 if (surface_) | 77 if (surface_.get()) |
78 surface_ = NULL; | 78 surface_ = NULL; |
79 | 79 |
80 helper_->Destroy(); | 80 helper_->Destroy(); |
81 } | 81 } |
82 | 82 |
83 bool TextureImageTransportSurface::DeferDraws() { | 83 bool TextureImageTransportSurface::DeferDraws() { |
84 // The command buffer hit a draw/clear command that could clobber the | 84 // The command buffer hit a draw/clear command that could clobber the |
85 // texture in use by the UI compositor. If a Swap is pending, abort | 85 // texture in use by the UI compositor. If a Swap is pending, abort |
86 // processing of the command by returning true and unschedule until the Swap | 86 // processing of the command by returning true and unschedule until the Swap |
87 // Ack arrives. | 87 // Ack arrives. |
(...skipping 22 matching lines...) Expand all Loading... |
110 return fbo_id_; | 110 return fbo_id_; |
111 } | 111 } |
112 | 112 |
113 bool TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) { | 113 bool TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) { |
114 DCHECK(!is_swap_buffers_pending_); | 114 DCHECK(!is_swap_buffers_pending_); |
115 if (backbuffer_suggested_allocation_ == allocation) | 115 if (backbuffer_suggested_allocation_ == allocation) |
116 return true; | 116 return true; |
117 backbuffer_suggested_allocation_ = allocation; | 117 backbuffer_suggested_allocation_ = allocation; |
118 | 118 |
119 if (backbuffer_suggested_allocation_) { | 119 if (backbuffer_suggested_allocation_) { |
120 DCHECK(!backbuffer_); | 120 DCHECK(!backbuffer_.get()); |
121 CreateBackTexture(); | 121 CreateBackTexture(); |
122 } else { | 122 } else { |
123 ReleaseBackTexture(); | 123 ReleaseBackTexture(); |
124 } | 124 } |
125 | 125 |
126 return true; | 126 return true; |
127 } | 127 } |
128 | 128 |
129 void TextureImageTransportSurface::SetFrontbufferAllocation(bool allocation) { | 129 void TextureImageTransportSurface::SetFrontbufferAllocation(bool allocation) { |
130 if (frontbuffer_suggested_allocation_ == allocation) | 130 if (frontbuffer_suggested_allocation_ == allocation) |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 latency_info_ = latency_info; | 187 latency_info_ = latency_info; |
188 } | 188 } |
189 | 189 |
190 bool TextureImageTransportSurface::SwapBuffers() { | 190 bool TextureImageTransportSurface::SwapBuffers() { |
191 DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL)); | 191 DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL)); |
192 DCHECK(backbuffer_suggested_allocation_); | 192 DCHECK(backbuffer_suggested_allocation_); |
193 | 193 |
194 if (!frontbuffer_suggested_allocation_) | 194 if (!frontbuffer_suggested_allocation_) |
195 return true; | 195 return true; |
196 | 196 |
197 if (!backbuffer_) { | 197 if (!backbuffer_.get()) { |
198 LOG(ERROR) << "Swap without valid backing."; | 198 LOG(ERROR) << "Swap without valid backing."; |
199 return true; | 199 return true; |
200 } | 200 } |
201 | 201 |
202 DCHECK(backbuffer_size() == current_size_); | 202 DCHECK(backbuffer_size() == current_size_); |
203 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; | 203 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; |
204 params.size = backbuffer_size(); | 204 params.size = backbuffer_size(); |
205 params.scale_factor = scale_factor_; | 205 params.scale_factor = scale_factor_; |
206 params.mailbox_name.assign( | 206 params.mailbox_name.assign( |
207 reinterpret_cast<const char*>(&back_mailbox_name_), | 207 reinterpret_cast<const char*>(&back_mailbox_name_), |
(...skipping 15 matching lines...) Expand all Loading... |
223 DCHECK(backbuffer_suggested_allocation_); | 223 DCHECK(backbuffer_suggested_allocation_); |
224 if (!frontbuffer_suggested_allocation_) | 224 if (!frontbuffer_suggested_allocation_) |
225 return true; | 225 return true; |
226 const gfx::Rect new_damage_rect(x, y, width, height); | 226 const gfx::Rect new_damage_rect(x, y, width, height); |
227 DCHECK(gfx::Rect(gfx::Point(), current_size_).Contains(new_damage_rect)); | 227 DCHECK(gfx::Rect(gfx::Point(), current_size_).Contains(new_damage_rect)); |
228 | 228 |
229 // An empty damage rect is a successful no-op. | 229 // An empty damage rect is a successful no-op. |
230 if (new_damage_rect.IsEmpty()) | 230 if (new_damage_rect.IsEmpty()) |
231 return true; | 231 return true; |
232 | 232 |
233 if (!backbuffer_) { | 233 if (!backbuffer_.get()) { |
234 LOG(ERROR) << "Swap without valid backing."; | 234 LOG(ERROR) << "Swap without valid backing."; |
235 return true; | 235 return true; |
236 } | 236 } |
237 | 237 |
238 DCHECK(current_size_ == backbuffer_size()); | 238 DCHECK(current_size_ == backbuffer_size()); |
239 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; | 239 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; |
240 params.surface_size = backbuffer_size(); | 240 params.surface_size = backbuffer_size(); |
241 params.surface_scale_factor = scale_factor_; | 241 params.surface_scale_factor = scale_factor_; |
242 params.x = x; | 242 params.x = x; |
243 params.y = y; | 243 params.y = y; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 } | 290 } |
291 } | 291 } |
292 | 292 |
293 void TextureImageTransportSurface::BufferPresentedImpl( | 293 void TextureImageTransportSurface::BufferPresentedImpl( |
294 const std::string& mailbox_name) { | 294 const std::string& mailbox_name) { |
295 DCHECK(is_swap_buffers_pending_); | 295 DCHECK(is_swap_buffers_pending_); |
296 is_swap_buffers_pending_ = false; | 296 is_swap_buffers_pending_ = false; |
297 // We should not have allowed the backbuffer to be discarded while the ack | 297 // We should not have allowed the backbuffer to be discarded while the ack |
298 // was pending. | 298 // was pending. |
299 DCHECK(backbuffer_suggested_allocation_); | 299 DCHECK(backbuffer_suggested_allocation_); |
300 DCHECK(backbuffer_); | 300 DCHECK(backbuffer_.get()); |
301 | 301 |
302 bool swap = true; | 302 bool swap = true; |
303 if (!mailbox_name.empty()) { | 303 if (!mailbox_name.empty()) { |
304 DCHECK(mailbox_name.length() == GL_MAILBOX_SIZE_CHROMIUM); | 304 DCHECK(mailbox_name.length() == GL_MAILBOX_SIZE_CHROMIUM); |
305 if (!memcmp(mailbox_name.data(), | 305 if (!memcmp(mailbox_name.data(), |
306 &back_mailbox_name_, | 306 &back_mailbox_name_, |
307 mailbox_name.length())) { | 307 mailbox_name.length())) { |
308 // The browser has skipped the frame to unblock the GPU process, waiting | 308 // The browser has skipped the frame to unblock the GPU process, waiting |
309 // for one of the right size, and returned the back buffer, so don't swap. | 309 // for one of the right size, and returned the back buffer, so don't swap. |
310 swap = false; | 310 swap = false; |
311 } | 311 } |
312 } | 312 } |
313 if (swap) { | 313 if (swap) { |
314 std::swap(backbuffer_, frontbuffer_); | 314 std::swap(backbuffer_, frontbuffer_); |
315 std::swap(back_mailbox_name_, front_mailbox_name_); | 315 std::swap(back_mailbox_name_, front_mailbox_name_); |
316 } | 316 } |
317 | 317 |
318 // We're relying on the fact that the parent context is | 318 // We're relying on the fact that the parent context is |
319 // finished with its context when it inserts the sync point that | 319 // finished with its context when it inserts the sync point that |
320 // triggers this callback. | 320 // triggers this callback. |
321 if (helper_->MakeCurrent()) { | 321 if (helper_->MakeCurrent()) { |
322 if (frontbuffer_ && !frontbuffer_suggested_allocation_) | 322 if (frontbuffer_.get() && !frontbuffer_suggested_allocation_) |
323 ReleaseFrontTexture(); | 323 ReleaseFrontTexture(); |
324 if (!backbuffer_ || backbuffer_size() != current_size_) | 324 if (!backbuffer_.get() || backbuffer_size() != current_size_) |
325 CreateBackTexture(); | 325 CreateBackTexture(); |
326 else | 326 else |
327 AttachBackTextureToFBO(); | 327 AttachBackTextureToFBO(); |
328 } | 328 } |
329 | 329 |
330 // Even if MakeCurrent fails, schedule anyway, to trigger the lost context | 330 // Even if MakeCurrent fails, schedule anyway, to trigger the lost context |
331 // logic. | 331 // logic. |
332 if (did_unschedule_) { | 332 if (did_unschedule_) { |
333 did_unschedule_ = false; | 333 did_unschedule_ = false; |
334 helper_->SetScheduled(true); | 334 helper_->SetScheduled(true); |
(...skipping 21 matching lines...) Expand all Loading... |
356 GpuHostMsg_AcceleratedSurfaceRelease_Params params; | 356 GpuHostMsg_AcceleratedSurfaceRelease_Params params; |
357 helper_->SendAcceleratedSurfaceRelease(params); | 357 helper_->SendAcceleratedSurfaceRelease(params); |
358 } | 358 } |
359 | 359 |
360 void TextureImageTransportSurface::CreateBackTexture() { | 360 void TextureImageTransportSurface::CreateBackTexture() { |
361 DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL)); | 361 DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL)); |
362 // If |is_swap_buffers_pending| we are waiting for our backbuffer | 362 // If |is_swap_buffers_pending| we are waiting for our backbuffer |
363 // in the mailbox, so we shouldn't be reallocating it now. | 363 // in the mailbox, so we shouldn't be reallocating it now. |
364 DCHECK(!is_swap_buffers_pending_); | 364 DCHECK(!is_swap_buffers_pending_); |
365 | 365 |
366 if (backbuffer_ && backbuffer_size() == current_size_) | 366 if (backbuffer_.get() && backbuffer_size() == current_size_) |
367 return; | 367 return; |
368 | 368 |
369 VLOG(1) << "Allocating new backbuffer texture"; | 369 VLOG(1) << "Allocating new backbuffer texture"; |
370 | 370 |
371 // On Qualcomm we couldn't resize an FBO texture past a certain | 371 // On Qualcomm we couldn't resize an FBO texture past a certain |
372 // size, after we allocated it as 1x1. So here we simply delete | 372 // size, after we allocated it as 1x1. So here we simply delete |
373 // the previous texture on resize, to insure we don't 'run out of | 373 // the previous texture on resize, to insure we don't 'run out of |
374 // memory'. | 374 // memory'. |
375 if (backbuffer_ && | 375 if (backbuffer_.get() && |
376 helper_->stub() | 376 helper_->stub()->decoder()->GetContextGroup()->feature_info() |
377 ->decoder() | 377 ->workarounds().delete_instead_of_resize_fbo) { |
378 ->GetContextGroup() | |
379 ->feature_info() | |
380 ->workarounds() | |
381 .delete_instead_of_resize_fbo) { | |
382 ReleaseBackTexture(); | 378 ReleaseBackTexture(); |
383 } | 379 } |
384 GLES2Decoder* decoder = helper_->stub()->decoder(); | 380 GLES2Decoder* decoder = helper_->stub()->decoder(); |
385 TextureManager* texture_manager = | 381 TextureManager* texture_manager = |
386 decoder->GetContextGroup()->texture_manager(); | 382 decoder->GetContextGroup()->texture_manager(); |
387 if (!backbuffer_) { | 383 if (!backbuffer_.get()) { |
388 mailbox_manager_->GenerateMailboxName(&back_mailbox_name_); | 384 mailbox_manager_->GenerateMailboxName(&back_mailbox_name_); |
389 GLuint service_id; | 385 GLuint service_id; |
390 glGenTextures(1, &service_id); | 386 glGenTextures(1, &service_id); |
391 backbuffer_ = TextureRef::Create(texture_manager, 0, service_id); | 387 backbuffer_ = TextureRef::Create(texture_manager, 0, service_id); |
392 texture_manager->SetTarget(backbuffer_, GL_TEXTURE_2D); | 388 texture_manager->SetTarget(backbuffer_.get(), GL_TEXTURE_2D); |
393 Texture* texture = texture_manager->Produce(backbuffer_); | 389 Texture* texture = texture_manager->Produce(backbuffer_.get()); |
394 bool success = mailbox_manager_->ProduceTexture( | 390 bool success = mailbox_manager_->ProduceTexture( |
395 GL_TEXTURE_2D, back_mailbox_name_, texture); | 391 GL_TEXTURE_2D, back_mailbox_name_, texture); |
396 DCHECK(success); | 392 DCHECK(success); |
397 } | 393 } |
398 | 394 |
399 { | 395 { |
400 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, | 396 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, |
401 backbuffer_->service_id()); | 397 backbuffer_->service_id()); |
402 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, | 398 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, |
403 current_size_.width(), current_size_.height(), 0, | 399 current_size_.width(), current_size_.height(), 0, |
404 GL_RGBA, GL_UNSIGNED_BYTE, NULL); | 400 GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
405 gpu::gles2::ErrorState* error_state = decoder->GetErrorState(); | 401 gpu::gles2::ErrorState* error_state = decoder->GetErrorState(); |
406 texture_manager->SetParameter("Backbuffer", error_state, backbuffer_, | 402 texture_manager->SetParameter("Backbuffer", |
407 GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 403 error_state, |
408 texture_manager->SetParameter("Backbuffer", error_state, backbuffer_, | 404 backbuffer_.get(), |
409 GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 405 GL_TEXTURE_MIN_FILTER, |
410 texture_manager->SetParameter("Backbuffer", error_state, backbuffer_, | 406 GL_LINEAR); |
411 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 407 texture_manager->SetParameter("Backbuffer", |
412 texture_manager->SetParameter("Backbuffer", error_state, backbuffer_, | 408 error_state, |
413 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 409 backbuffer_.get(), |
414 texture_manager->SetLevelInfo( | 410 GL_TEXTURE_MAG_FILTER, |
415 backbuffer_, | 411 GL_LINEAR); |
416 GL_TEXTURE_2D, | 412 texture_manager->SetParameter("Backbuffer", |
417 0, | 413 error_state, |
418 GL_RGBA, | 414 backbuffer_.get(), |
419 current_size_.width(), | 415 GL_TEXTURE_WRAP_S, |
420 current_size_.height(), | 416 GL_CLAMP_TO_EDGE); |
421 1, | 417 texture_manager->SetParameter("Backbuffer", |
422 0, | 418 error_state, |
423 GL_RGBA, | 419 backbuffer_.get(), |
424 GL_UNSIGNED_BYTE, | 420 GL_TEXTURE_WRAP_T, |
425 true); | 421 GL_CLAMP_TO_EDGE); |
426 DCHECK(texture_manager->CanRender(backbuffer_)); | 422 texture_manager->SetLevelInfo(backbuffer_.get(), |
| 423 GL_TEXTURE_2D, |
| 424 0, |
| 425 GL_RGBA, |
| 426 current_size_.width(), |
| 427 current_size_.height(), |
| 428 1, |
| 429 0, |
| 430 GL_RGBA, |
| 431 GL_UNSIGNED_BYTE, |
| 432 true); |
| 433 DCHECK(texture_manager->CanRender(backbuffer_.get())); |
427 CHECK_GL_ERROR(); | 434 CHECK_GL_ERROR(); |
428 } | 435 } |
429 | 436 |
430 AttachBackTextureToFBO(); | 437 AttachBackTextureToFBO(); |
431 } | 438 } |
432 | 439 |
433 void TextureImageTransportSurface::AttachBackTextureToFBO() { | 440 void TextureImageTransportSurface::AttachBackTextureToFBO() { |
434 DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL)); | 441 DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL)); |
435 DCHECK(backbuffer_); | 442 DCHECK(backbuffer_.get()); |
436 gfx::ScopedFrameBufferBinder fbo_binder(fbo_id_); | 443 gfx::ScopedFrameBufferBinder fbo_binder(fbo_id_); |
437 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, | 444 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, |
438 GL_COLOR_ATTACHMENT0, | 445 GL_COLOR_ATTACHMENT0, |
439 GL_TEXTURE_2D, | 446 GL_TEXTURE_2D, |
440 backbuffer_->service_id(), | 447 backbuffer_->service_id(), |
441 0); | 448 0); |
442 CHECK_GL_ERROR(); | 449 CHECK_GL_ERROR(); |
443 | 450 |
444 #ifndef NDEBUG | 451 #ifndef NDEBUG |
445 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); | 452 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); |
446 if (status != GL_FRAMEBUFFER_COMPLETE) { | 453 if (status != GL_FRAMEBUFFER_COMPLETE) { |
447 DLOG(FATAL) << "Framebuffer incomplete: " << status; | 454 DLOG(FATAL) << "Framebuffer incomplete: " << status; |
448 } | 455 } |
449 #endif | 456 #endif |
450 } | 457 } |
451 | 458 |
452 } // namespace content | 459 } // namespace content |
OLD | NEW |