Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: content/common/gpu/texture_image_transport_surface.cc

Issue 12717013: Add reference-counting for mailbox textures. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add optional 'pool' reference while textures are in mailbox Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 12 matching lines...) Expand all
23 using gpu::gles2::TextureDefinition; 23 using gpu::gles2::TextureDefinition;
24 using gpu::gles2::TextureManager; 24 using gpu::gles2::TextureManager;
25 25
26 namespace content { 26 namespace content {
27 27
28 TextureImageTransportSurface::TextureImageTransportSurface( 28 TextureImageTransportSurface::TextureImageTransportSurface(
29 GpuChannelManager* manager, 29 GpuChannelManager* manager,
30 GpuCommandBufferStub* stub, 30 GpuCommandBufferStub* stub,
31 const gfx::GLSurfaceHandle& handle) 31 const gfx::GLSurfaceHandle& handle)
32 : fbo_id_(0), 32 : fbo_id_(0),
33 backbuffer_(CreateTextureDefinition(gfx::Size(), 0)), 33 backbuffer_(&TextureDefinition::kEmptyTexture2D),
34 stub_destroyed_(false), 34 stub_destroyed_(false),
35 backbuffer_suggested_allocation_(true), 35 backbuffer_suggested_allocation_(true),
36 frontbuffer_suggested_allocation_(true), 36 frontbuffer_suggested_allocation_(true),
37 handle_(handle), 37 handle_(handle),
38 is_swap_buffers_pending_(false), 38 is_swap_buffers_pending_(false),
39 did_unschedule_(false) { 39 did_unschedule_(false) {
40 helper_.reset(new ImageTransportHelper(this, 40 helper_.reset(
41 manager, 41 new ImageTransportHelper(this, manager, stub, gfx::kNullPluginWindow));
42 stub,
43 gfx::kNullPluginWindow));
44 } 42 }
45 43
46 TextureImageTransportSurface::~TextureImageTransportSurface() { 44 TextureImageTransportSurface::~TextureImageTransportSurface() {
47 DCHECK(stub_destroyed_); 45 DCHECK(stub_destroyed_);
48 Destroy(); 46 Destroy();
49 } 47 }
50 48
51 bool TextureImageTransportSurface::Initialize() { 49 bool TextureImageTransportSurface::Initialize() {
52 mailbox_manager_ = 50 mailbox_manager_ =
53 helper_->stub()->decoder()->GetContextGroup()->mailbox_manager(); 51 helper_->stub()->decoder()->GetContextGroup()->mailbox_manager();
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 } 98 }
101 99
102 bool TextureImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) { 100 bool TextureImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
103 if (stub_destroyed_) { 101 if (stub_destroyed_) {
104 // Early-exit so that we don't recreate the fbo. We still want to return 102 // Early-exit so that we don't recreate the fbo. We still want to return
105 // true, so that the context is made current and the GLES2DecoderImpl can 103 // true, so that the context is made current and the GLES2DecoderImpl can
106 // release its own resources. 104 // release its own resources.
107 return true; 105 return true;
108 } 106 }
109 107
110 context_ = context;
111
112 if (!fbo_id_) { 108 if (!fbo_id_) {
113 glGenFramebuffersEXT(1, &fbo_id_); 109 glGenFramebuffersEXT(1, &fbo_id_);
114 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_); 110 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_);
115 current_size_ = gfx::Size(1, 1); 111 current_size_ = gfx::Size(1, 1);
116 helper_->stub()->AddDestructionObserver(this); 112 helper_->stub()->AddDestructionObserver(this);
117 } 113 }
118 114
119 // We could be receiving non-deferred GL commands, that is anything that does 115 // We could be receiving non-deferred GL commands, that is anything that does
120 // not need a framebuffer. 116 // not need a framebuffer.
121 if (!backbuffer_->service_id() && !is_swap_buffers_pending_ && 117 if (!backbuffer_->service_id() && !is_swap_buffers_pending_ &&
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 202
207 DCHECK(backbuffer_size() == current_size_); 203 DCHECK(backbuffer_size() == current_size_);
208 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; 204 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
209 params.size = backbuffer_size(); 205 params.size = backbuffer_size();
210 params.mailbox_name.assign( 206 params.mailbox_name.assign(
211 reinterpret_cast<const char*>(&mailbox_name_), sizeof(mailbox_name_)); 207 reinterpret_cast<const char*>(&mailbox_name_), sizeof(mailbox_name_));
212 208
213 glFlush(); 209 glFlush();
214 ProduceTexture(); 210 ProduceTexture();
215 211
216 // Do not allow destruction while we are still waiting for a swap ACK,
217 // so we do not leak a texture in the mailbox.
218 AddRef();
219
220 helper_->SendAcceleratedSurfaceBuffersSwapped(params); 212 helper_->SendAcceleratedSurfaceBuffersSwapped(params);
221 213
222 DCHECK(!is_swap_buffers_pending_); 214 DCHECK(!is_swap_buffers_pending_);
223 is_swap_buffers_pending_ = true; 215 is_swap_buffers_pending_ = true;
224 return true; 216 return true;
225 } 217 }
226 218
227 bool TextureImageTransportSurface::PostSubBuffer( 219 bool TextureImageTransportSurface::PostSubBuffer(
228 int x, int y, int width, int height) { 220 int x, int y, int width, int height) {
229 DCHECK(backbuffer_suggested_allocation_); 221 DCHECK(backbuffer_suggested_allocation_);
(...skipping 17 matching lines...) Expand all
247 params.x = x; 239 params.x = x;
248 params.y = y; 240 params.y = y;
249 params.width = width; 241 params.width = width;
250 params.height = height; 242 params.height = height;
251 params.mailbox_name.assign( 243 params.mailbox_name.assign(
252 reinterpret_cast<const char*>(&mailbox_name_), sizeof(mailbox_name_)); 244 reinterpret_cast<const char*>(&mailbox_name_), sizeof(mailbox_name_));
253 245
254 glFlush(); 246 glFlush();
255 ProduceTexture(); 247 ProduceTexture();
256 248
257 // Do not allow destruction while we are still waiting for a swap ACK,
258 // so we do not leak a texture in the mailbox.
259 AddRef();
260
261 helper_->SendAcceleratedSurfacePostSubBuffer(params); 249 helper_->SendAcceleratedSurfacePostSubBuffer(params);
262 250
263 DCHECK(!is_swap_buffers_pending_); 251 DCHECK(!is_swap_buffers_pending_);
264 is_swap_buffers_pending_ = true; 252 is_swap_buffers_pending_ = true;
265 return true; 253 return true;
266 } 254 }
267 255
268 std::string TextureImageTransportSurface::GetExtensions() { 256 std::string TextureImageTransportSurface::GetExtensions() {
269 std::string extensions = gfx::GLSurface::GetExtensions(); 257 std::string extensions = gfx::GLSurface::GetExtensions();
270 extensions += extensions.empty() ? "" : " "; 258 extensions += extensions.empty() ? "" : " ";
(...skipping 22 matching lines...) Expand all
293 const AcceleratedSurfaceMsg_BufferPresented_Params& params) { 281 const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
294 if (params.sync_point == 0) { 282 if (params.sync_point == 0) {
295 BufferPresentedImpl(params.mailbox_name); 283 BufferPresentedImpl(params.mailbox_name);
296 } else { 284 } else {
297 helper_->manager()->sync_point_manager()->AddSyncPointCallback( 285 helper_->manager()->sync_point_manager()->AddSyncPointCallback(
298 params.sync_point, 286 params.sync_point,
299 base::Bind(&TextureImageTransportSurface::BufferPresentedImpl, 287 base::Bind(&TextureImageTransportSurface::BufferPresentedImpl,
300 this, 288 this,
301 params.mailbox_name)); 289 params.mailbox_name));
302 } 290 }
303
304 // Careful, we might get deleted now if we were only waiting for
305 // a final swap ACK.
306 Release();
307 } 291 }
308 292
309 void TextureImageTransportSurface::BufferPresentedImpl( 293 void TextureImageTransportSurface::BufferPresentedImpl(
310 const std::string& mailbox_name) { 294 const std::string& mailbox_name) {
295 if (stub_destroyed_)
296 return;
297
311 DCHECK(!backbuffer_->service_id()); 298 DCHECK(!backbuffer_->service_id());
312 if (!mailbox_name.empty()) { 299 if (!mailbox_name.empty()) {
313 DCHECK(mailbox_name.length() == GL_MAILBOX_SIZE_CHROMIUM); 300 DCHECK(mailbox_name.length() == GL_MAILBOX_SIZE_CHROMIUM);
314 mailbox_name.copy(reinterpret_cast<char *>(&mailbox_name_), 301 mailbox_name.copy(reinterpret_cast<char *>(&mailbox_name_),
315 sizeof(MailboxName)); 302 sizeof(MailboxName));
316 ConsumeTexture(); 303 ConsumeTexture();
317 } 304 }
318 305
319 if (stub_destroyed_ && backbuffer_->service_id()) {
320 // TODO(sievers): Remove this after changes to the mailbox to take ownership
321 // of the service ids.
322 DCHECK(context_.get() && surface_.get());
323 uint32 service_id = backbuffer_->ReleaseServiceId();
324 if (context_->MakeCurrent(surface_.get()))
325 glDeleteTextures(1, &service_id);
326
327 return;
328 }
329
330 DCHECK(is_swap_buffers_pending_); 306 DCHECK(is_swap_buffers_pending_);
331 is_swap_buffers_pending_ = false; 307 is_swap_buffers_pending_ = false;
332 308
333 // We should not have allowed the backbuffer to be discarded while the ack 309 // We should not have allowed the backbuffer to be discarded while the ack
334 // was pending. 310 // was pending.
335 DCHECK(backbuffer_suggested_allocation_); 311 DCHECK(backbuffer_suggested_allocation_);
336 312
337 // We're relying on the fact that the parent context is 313 // We're relying on the fact that the parent context is
338 // finished with it's context when it inserts the sync point that 314 // finished with it's context when it inserts the sync point that
339 // triggers this callback. 315 // triggers this callback.
(...skipping 13 matching lines...) Expand all
353 } 329 }
354 330
355 void TextureImageTransportSurface::OnResizeViewACK() { 331 void TextureImageTransportSurface::OnResizeViewACK() {
356 NOTREACHED(); 332 NOTREACHED();
357 } 333 }
358 334
359 void TextureImageTransportSurface::ReleaseBackTexture() { 335 void TextureImageTransportSurface::ReleaseBackTexture() {
360 if (!backbuffer_->service_id()) 336 if (!backbuffer_->service_id())
361 return; 337 return;
362 338
363 uint32 service_id = backbuffer_->ReleaseServiceId(); 339 StopUsingSharedTexture(backbuffer_, true);
364 glDeleteTextures(1, &service_id); 340 backbuffer_ = &TextureDefinition::kEmptyTexture2D;
365 backbuffer_.reset(CreateTextureDefinition(gfx::Size(), 0));
366 mailbox_name_ = MailboxName(); 341 mailbox_name_ = MailboxName();
367 glFlush(); 342 glFlush();
368 CHECK_GL_ERROR(); 343 CHECK_GL_ERROR();
369 } 344 }
370 345
371 void TextureImageTransportSurface::CreateBackTexture() { 346 void TextureImageTransportSurface::CreateBackTexture() {
372 // If |is_swap_buffers_pending| we are waiting for our backbuffer 347 // If |is_swap_buffers_pending| we are waiting for our backbuffer
373 // in the mailbox, so we shouldn't be reallocating it now. 348 // in the mailbox, so we shouldn't be reallocating it now.
374 DCHECK(!is_swap_buffers_pending_); 349 DCHECK(!is_swap_buffers_pending_);
375 350
376 if (backbuffer_->service_id() && backbuffer_size() == current_size_) 351 if (backbuffer_->service_id() && backbuffer_size() == current_size_)
377 return; 352 return;
378 353
379 uint32 service_id = backbuffer_->ReleaseServiceId(); 354 uint32 service_id = backbuffer_->service_id();
380 355
381 VLOG(1) << "Allocating new backbuffer texture"; 356 VLOG(1) << "Allocating new backbuffer texture";
382 357
383 // On Qualcomm we couldn't resize an FBO texture past a certain 358 // On Qualcomm we couldn't resize an FBO texture past a certain
384 // size, after we allocated it as 1x1. So here we simply delete 359 // size, after we allocated it as 1x1. So here we simply delete
385 // the previous texture on resize, to insure we don't 'run out of 360 // the previous texture on resize, to insure we don't 'run out of
386 // memory'. 361 // memory'.
387 if (service_id && 362 if (service_id &&
388 helper_->stub() 363 helper_->stub()
389 ->decoder() 364 ->decoder()
390 ->GetContextGroup() 365 ->GetContextGroup()
391 ->feature_info() 366 ->feature_info()
392 ->workarounds() 367 ->workarounds()
393 .delete_instead_of_resize_fbo) { 368 .delete_instead_of_resize_fbo) {
394 glDeleteTextures(1, &service_id); 369 StopUsingSharedTexture(backbuffer_, true);
370 backbuffer_ = NULL;
395 service_id = 0; 371 service_id = 0;
396 mailbox_name_ = MailboxName(); 372 mailbox_name_ = MailboxName();
397 } 373 }
398 374
399 if (!service_id) { 375 if (!service_id) {
400 MailboxName new_mailbox_name; 376 MailboxName new_mailbox_name;
401 MailboxName& name = mailbox_name_; 377 MailboxName& name = mailbox_name_;
402 // This slot should be uninitialized. 378 // This slot should be uninitialized.
403 DCHECK(!memcmp(&name, &new_mailbox_name, sizeof(MailboxName))); 379 DCHECK(!memcmp(&name, &new_mailbox_name, sizeof(MailboxName)));
404 mailbox_manager_->GenerateMailboxName(&new_mailbox_name); 380 mailbox_manager_->GenerateMailboxName(&new_mailbox_name);
405 name = new_mailbox_name; 381 name = new_mailbox_name;
406 glGenTextures(1, &service_id); 382 glGenTextures(1, &service_id);
407 } 383 }
408 384
409 backbuffer_.reset( 385 if (!backbuffer_ || !backbuffer_->service_id()) {
410 CreateTextureDefinition(current_size_, service_id)); 386 backbuffer_ = CreateTextureDefinition(current_size_, service_id);
387 StartUsingSharedTexture(backbuffer_);
388 } else {
389 backbuffer_->level_infos()[0][0].width = current_size_.width();
390 backbuffer_->level_infos()[0][0].height = current_size_.height();
391 }
411 392
412 { 393 {
413 ScopedTextureBinder texture_binder(service_id); 394 ScopedTextureBinder texture_binder(service_id);
414 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 395 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
415 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 396 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
416 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 397 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
417 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 398 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
418 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 399 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
419 current_size_.width(), current_size_.height(), 0, 400 current_size_.width(), current_size_.height(), 0,
420 GL_RGBA, GL_UNSIGNED_BYTE, NULL); 401 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
(...skipping 16 matching lines...) Expand all
437 #ifndef NDEBUG 418 #ifndef NDEBUG
438 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); 419 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
439 if (status != GL_FRAMEBUFFER_COMPLETE) { 420 if (status != GL_FRAMEBUFFER_COMPLETE) {
440 DLOG(FATAL) << "Framebuffer incomplete: " << status; 421 DLOG(FATAL) << "Framebuffer incomplete: " << status;
441 } 422 }
442 #endif 423 #endif
443 } 424 }
444 425
445 TextureDefinition* TextureImageTransportSurface::CreateTextureDefinition( 426 TextureDefinition* TextureImageTransportSurface::CreateTextureDefinition(
446 gfx::Size size, int service_id) { 427 gfx::Size size, int service_id) {
428 DCHECK(service_id && !size.IsEmpty());
447 TextureDefinition::LevelInfo info( 429 TextureDefinition::LevelInfo info(
448 GL_TEXTURE_2D, GL_RGBA, size.width(), size.height(), 1, 430 GL_TEXTURE_2D, GL_RGBA, size.width(), size.height(), 1,
449 0, GL_RGBA, GL_UNSIGNED_BYTE, true); 431 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
450 432
451 TextureDefinition::LevelInfos level_infos; 433 TextureDefinition::LevelInfos level_infos;
452 level_infos.resize(1); 434 level_infos.resize(1);
453 level_infos[0].resize(1); 435 level_infos[0].resize(1);
454 level_infos[0][0] = info; 436 level_infos[0][0] = info;
455 return new TextureDefinition( 437 return new TextureDefinition(
456 GL_TEXTURE_2D, 438 GL_TEXTURE_2D,
457 service_id, 439 service_id,
458 GL_LINEAR, 440 GL_LINEAR,
459 GL_LINEAR, 441 GL_LINEAR,
460 GL_CLAMP_TO_EDGE, 442 GL_CLAMP_TO_EDGE,
461 GL_CLAMP_TO_EDGE, 443 GL_CLAMP_TO_EDGE,
462 GL_NONE, 444 GL_NONE,
463 true, 445 true,
464 level_infos); 446 level_infos);
465 } 447 }
466 448
467 void TextureImageTransportSurface::ConsumeTexture() { 449 void TextureImageTransportSurface::ConsumeTexture() {
468 DCHECK(!backbuffer_->service_id()); 450 DCHECK(!backbuffer_->service_id());
469 451
470 backbuffer_.reset(mailbox_manager_->ConsumeTexture( 452 backbuffer_ = mailbox_manager_->ConsumeTexture(GL_TEXTURE_2D, mailbox_name_);
471 GL_TEXTURE_2D, mailbox_name_));
472 if (!backbuffer_) { 453 if (!backbuffer_) {
473 mailbox_name_ = MailboxName(); 454 mailbox_name_ = MailboxName();
474 backbuffer_.reset(CreateTextureDefinition(gfx::Size(), 0)); 455 backbuffer_ = &TextureDefinition::kEmptyTexture2D;
456 } else {
457 StartUsingSharedTexture(backbuffer_);
475 } 458 }
476 } 459 }
477 460
478 void TextureImageTransportSurface::ProduceTexture() { 461 void TextureImageTransportSurface::ProduceTexture() {
479 DCHECK(backbuffer_->service_id()); 462 DCHECK(backbuffer_->service_id());
480 DCHECK(!backbuffer_size().IsEmpty()); 463 DCHECK(!backbuffer_size().IsEmpty());
481 464
482 // Pass NULL as |owner| here to avoid errors from glConsumeTextureCHROMIUM() 465 // Pass NULL as |owner| here to avoid errors from glConsumeTextureCHROMIUM()
483 // when the renderer context group goes away before the RWHV handles a pending 466 // when the renderer context group goes away before the RWHV handles a pending
484 // ACK. We avoid leaking a texture in the mailbox by waiting for the final ACK 467 // ACK. We avoid leaking a texture in the mailbox by waiting for the final ACK
485 // at which point we consume the correct texture back. 468 // at which point we consume the correct texture back.
486 bool success = mailbox_manager_->ProduceTexture( 469 bool success = mailbox_manager_->ProduceTexture(
487 GL_TEXTURE_2D, 470 GL_TEXTURE_2D,
488 mailbox_name_, 471 mailbox_name_,
489 backbuffer_.release(), 472 backbuffer_,
490 NULL); 473 std::make_pair(MailboxManager::TEXTURE_POOL_FOR_SURFACE,
474 helper_->stub()->surface_id()));
475 bool deleted = StopUsingSharedTexture(backbuffer_, true);
476 DCHECK(!deleted);
491 DCHECK(success); 477 DCHECK(success);
492 mailbox_name_ = MailboxName(); 478 mailbox_name_ = MailboxName();
493 backbuffer_.reset(CreateTextureDefinition(gfx::Size(), 0)); 479 backbuffer_ = &TextureDefinition::kEmptyTexture2D;
494 } 480 }
495 481
496 } // namespace content 482 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/texture_image_transport_surface.h ('k') | gpu/command_buffer/service/context_group.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698