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 3 // found in the LICENSE file. 4 5 #include "gpu/command_buffer/service/framebuffer_manager.h" 6 #include "base/logging.h" 7 #include "base/strings/stringprintf.h" 8 #include "gpu/command_buffer/common/gles2_cmd_utils.h" 9 #include "gpu/command_buffer/service/renderbuffer_manager.h" 10 #include "gpu/command_buffer/service/texture_manager.h" 11 #include "ui/gl/gl_bindings.h" 12 13 namespace gpu { 14 namespace gles2 { 15 16 DecoderFramebufferState::DecoderFramebufferState() 17 : clear_state_dirty(false), 18 bound_read_framebuffer(NULL), 19 bound_draw_framebuffer(NULL) { 20 } 21 22 DecoderFramebufferState::~DecoderFramebufferState() { 23 } 24 25 Framebuffer::FramebufferComboCompleteMap* 26 Framebuffer::framebuffer_combo_complete_map_; 27 28 // Framebuffer completeness is not cacheable on OS X because of dynamic 29 // graphics switching. 30 // http://crbug.com/180876 31 #if defined(OS_MACOSX) 32 bool Framebuffer::allow_framebuffer_combo_complete_map_ = false; 33 #else 34 bool Framebuffer::allow_framebuffer_combo_complete_map_ = true; 35 #endif 36 37 void Framebuffer::ClearFramebufferCompleteComboMap() { 38 if (framebuffer_combo_complete_map_) { 39 framebuffer_combo_complete_map_->clear(); 40 } 41 } 42 43 class RenderbufferAttachment 44 : public Framebuffer::Attachment { 45 public: 46 explicit RenderbufferAttachment( 47 Renderbuffer* renderbuffer) 48 : renderbuffer_(renderbuffer) { 49 } 50 51 virtual GLsizei width() const OVERRIDE { 52 return renderbuffer_->width(); 53 } 54 55 virtual GLsizei height() const OVERRIDE { 56 return renderbuffer_->height(); 57 } 58 59 virtual GLenum internal_format() const OVERRIDE { 60 return renderbuffer_->internal_format(); 61 } 62 63 virtual GLenum texture_type() const OVERRIDE { 64 return 0; 65 } 66 67 virtual GLsizei samples() const OVERRIDE { 68 return renderbuffer_->samples(); 69 } 70 71 virtual GLuint object_name() const OVERRIDE { 72 return renderbuffer_->client_id(); 73 } 74 75 virtual bool cleared() const OVERRIDE { 76 return renderbuffer_->cleared(); 77 } 78 79 virtual void SetCleared( 80 RenderbufferManager* renderbuffer_manager, 81 TextureManager* /* texture_manager */, 82 bool cleared) OVERRIDE { 83 renderbuffer_manager->SetCleared(renderbuffer_.get(), cleared); 84 } 85 86 virtual bool IsTexture( 87 TextureRef* /* texture */) const OVERRIDE { 88 return false; 89 } 90 91 virtual bool IsRenderbuffer( 92 Renderbuffer* renderbuffer) const OVERRIDE { 93 return renderbuffer_.get() == renderbuffer; 94 } 95 96 virtual bool CanRenderTo() const OVERRIDE { 97 return true; 98 } 99 100 virtual void DetachFromFramebuffer(Framebuffer* framebuffer) const OVERRIDE { 101 // Nothing to do for renderbuffers. 102 } 103 104 virtual bool ValidForAttachmentType( 105 GLenum attachment_type, uint32 max_color_attachments) OVERRIDE { 106 uint32 need = GLES2Util::GetChannelsNeededForAttachmentType( 107 attachment_type, max_color_attachments); 108 uint32 have = GLES2Util::GetChannelsForFormat(internal_format()); 109 return (need & have) != 0; 110 } 111 112 Renderbuffer* renderbuffer() const { 113 return renderbuffer_.get(); 114 } 115 116 virtual void AddToSignature( 117 TextureManager* texture_manager, std::string* signature) const OVERRIDE { 118 DCHECK(signature); 119 renderbuffer_->AddToSignature(signature); 120 } 121 122 virtual void OnWillRenderTo() const OVERRIDE {} 123 virtual void OnDidRenderTo() const OVERRIDE {} 124 125 protected: 126 virtual ~RenderbufferAttachment() { } 127 128 private: 129 scoped_refptr<Renderbuffer> renderbuffer_; 130 131 DISALLOW_COPY_AND_ASSIGN(RenderbufferAttachment); 132 }; 133 134 class TextureAttachment 135 : public Framebuffer::Attachment { 136 public: 137 TextureAttachment( 138 TextureRef* texture_ref, GLenum target, GLint level, GLsizei samples) 139 : texture_ref_(texture_ref), 140 target_(target), 141 level_(level), 142 samples_(samples) { 143 } 144 145 virtual GLsizei width() const OVERRIDE { 146 GLsizei temp_width = 0; 147 GLsizei temp_height = 0; 148 texture_ref_->texture()->GetLevelSize( 149 target_, level_, &temp_width, &temp_height); 150 return temp_width; 151 } 152 153 virtual GLsizei height() const OVERRIDE { 154 GLsizei temp_width = 0; 155 GLsizei temp_height = 0; 156 texture_ref_->texture()->GetLevelSize( 157 target_, level_, &temp_width, &temp_height); 158 return temp_height; 159 } 160 161 virtual GLenum internal_format() const OVERRIDE { 162 GLenum temp_type = 0; 163 GLenum temp_internal_format = 0; 164 texture_ref_->texture()->GetLevelType( 165 target_, level_, &temp_type, &temp_internal_format); 166 return temp_internal_format; 167 } 168 169 virtual GLenum texture_type() const OVERRIDE { 170 GLenum temp_type = 0; 171 GLenum temp_internal_format = 0; 172 texture_ref_->texture()->GetLevelType( 173 target_, level_, &temp_type, &temp_internal_format); 174 return temp_type; 175 } 176 177 virtual GLsizei samples() const OVERRIDE { 178 return samples_; 179 } 180 181 virtual GLuint object_name() const OVERRIDE { 182 return texture_ref_->client_id(); 183 } 184 185 virtual bool cleared() const OVERRIDE { 186 return texture_ref_->texture()->IsLevelCleared(target_, level_); 187 } 188 189 virtual void SetCleared( 190 RenderbufferManager* /* renderbuffer_manager */, 191 TextureManager* texture_manager, 192 bool cleared) OVERRIDE { 193 texture_manager->SetLevelCleared( 194 texture_ref_.get(), target_, level_, cleared); 195 } 196 197 virtual bool IsTexture(TextureRef* texture) const OVERRIDE { 198 return texture == texture_ref_.get(); 199 } 200 201 virtual bool IsRenderbuffer( 202 Renderbuffer* /* renderbuffer */) 203 const OVERRIDE { 204 return false; 205 } 206 207 TextureRef* texture() const { 208 return texture_ref_.get(); 209 } 210 211 virtual bool CanRenderTo() const OVERRIDE { 212 return texture_ref_->texture()->CanRenderTo(); 213 } 214 215 virtual void DetachFromFramebuffer(Framebuffer* framebuffer) 216 const OVERRIDE { 217 texture_ref_->texture()->DetachFromFramebuffer(); 218 framebuffer->OnTextureRefDetached(texture_ref_.get()); 219 } 220 221 virtual bool ValidForAttachmentType( 222 GLenum attachment_type, uint32 max_color_attachments) OVERRIDE { 223 GLenum type = 0; 224 GLenum internal_format = 0; 225 if (!texture_ref_->texture()->GetLevelType( 226 target_, level_, &type, &internal_format)) { 227 return false; 228 } 229 uint32 need = GLES2Util::GetChannelsNeededForAttachmentType( 230 attachment_type, max_color_attachments); 231 uint32 have = GLES2Util::GetChannelsForFormat(internal_format); 232 233 // Workaround for NVIDIA drivers that incorrectly expose these formats as 234 // renderable: 235 if (internal_format == GL_LUMINANCE || internal_format == GL_ALPHA || 236 internal_format == GL_LUMINANCE_ALPHA) { 237 return false; 238 } 239 return (need & have) != 0; 240 } 241 242 virtual void AddToSignature( 243 TextureManager* texture_manager, std::string* signature) const OVERRIDE { 244 DCHECK(signature); 245 texture_manager->AddToSignature( 246 texture_ref_.get(), target_, level_, signature); 247 } 248 249 virtual void OnWillRenderTo() const OVERRIDE { 250 texture_ref_->texture()->OnWillModifyPixels(); 251 } 252 253 virtual void OnDidRenderTo() const OVERRIDE { 254 texture_ref_->texture()->OnDidModifyPixels(); 255 } 256 257 protected: 258 virtual ~TextureAttachment() {} 259 260 private: 261 scoped_refptr<TextureRef> texture_ref_; 262 GLenum target_; 263 GLint level_; 264 GLsizei samples_; 265 266 DISALLOW_COPY_AND_ASSIGN(TextureAttachment); 267 }; 268 269 FramebufferManager::TextureDetachObserver::TextureDetachObserver() {} 270 271 FramebufferManager::TextureDetachObserver::~TextureDetachObserver() {} 272 273 FramebufferManager::FramebufferManager( 274 uint32 max_draw_buffers, uint32 max_color_attachments) 275 : framebuffer_state_change_count_(1), 276 framebuffer_count_(0), 277 have_context_(true), 278 max_draw_buffers_(max_draw_buffers), 279 max_color_attachments_(max_color_attachments) { 280 DCHECK_GT(max_draw_buffers_, 0u); 281 DCHECK_GT(max_color_attachments_, 0u); 282 } 283 284 FramebufferManager::~FramebufferManager() { 285 DCHECK(framebuffers_.empty()); 286 // If this triggers, that means something is keeping a reference to a 287 // Framebuffer belonging to this. 288 CHECK_EQ(framebuffer_count_, 0u); 289 } 290 291 void Framebuffer::MarkAsDeleted() { 292 deleted_ = true; 293 while (!attachments_.empty()) { 294 Attachment* attachment = attachments_.begin()->second.get(); 295 attachment->DetachFromFramebuffer(this); 296 attachments_.erase(attachments_.begin()); 297 } 298 } 299 300 void FramebufferManager::Destroy(bool have_context) { 301 have_context_ = have_context; 302 framebuffers_.clear(); 303 } 304 305 void FramebufferManager::StartTracking( 306 Framebuffer* /* framebuffer */) { 307 ++framebuffer_count_; 308 } 309 310 void FramebufferManager::StopTracking( 311 Framebuffer* /* framebuffer */) { 312 --framebuffer_count_; 313 } 314 315 void FramebufferManager::CreateFramebuffer( 316 GLuint client_id, GLuint service_id) { 317 std::pair<FramebufferMap::iterator, bool> result = 318 framebuffers_.insert( 319 std::make_pair( 320 client_id, 321 scoped_refptr<Framebuffer>( 322 new Framebuffer(this, service_id)))); 323 DCHECK(result.second); 324 } 325 326 Framebuffer::Framebuffer( 327 FramebufferManager* manager, GLuint service_id) 328 : manager_(manager), 329 deleted_(false), 330 service_id_(service_id), 331 has_been_bound_(false), 332 framebuffer_complete_state_count_id_(0) { 333 manager->StartTracking(this); 334 DCHECK_GT(manager->max_draw_buffers_, 0u); 335 draw_buffers_.reset(new GLenum[manager->max_draw_buffers_]); 336 draw_buffers_[0] = GL_COLOR_ATTACHMENT0; 337 for (uint32 i = 1; i < manager->max_draw_buffers_; ++i) 338 draw_buffers_[i] = GL_NONE; 339 } 340 341 Framebuffer::~Framebuffer() { 342 if (manager_) { 343 if (manager_->have_context_) { 344 GLuint id = service_id(); 345 glDeleteFramebuffersEXT(1, &id); 346 } 347 manager_->StopTracking(this); 348 manager_ = NULL; 349 } 350 } 351 352 bool Framebuffer::HasUnclearedAttachment( 353 GLenum attachment) const { 354 AttachmentMap::const_iterator it = 355 attachments_.find(attachment); 356 if (it != attachments_.end()) { 357 const Attachment* attachment = it->second.get(); 358 return !attachment->cleared(); 359 } 360 return false; 361 } 362 363 bool Framebuffer::HasUnclearedColorAttachments() const { 364 for (AttachmentMap::const_iterator it = attachments_.begin(); 365 it != attachments_.end(); ++it) { 366 if (it->first >= GL_COLOR_ATTACHMENT0 && 367 it->first < GL_COLOR_ATTACHMENT0 + manager_->max_draw_buffers_) { 368 const Attachment* attachment = it->second.get(); 369 if (!attachment->cleared()) 370 return true; 371 } 372 } 373 return false; 374 } 375 376 void Framebuffer::ChangeDrawBuffersHelper(bool recover) const { 377 scoped_ptr<GLenum[]> buffers(new GLenum[manager_->max_draw_buffers_]); 378 for (uint32 i = 0; i < manager_->max_draw_buffers_; ++i) 379 buffers[i] = GL_NONE; 380 for (AttachmentMap::const_iterator it = attachments_.begin(); 381 it != attachments_.end(); ++it) { 382 if (it->first >= GL_COLOR_ATTACHMENT0 && 383 it->first < GL_COLOR_ATTACHMENT0 + manager_->max_draw_buffers_) { 384 buffers[it->first - GL_COLOR_ATTACHMENT0] = it->first; 385 } 386 } 387 bool different = false; 388 for (uint32 i = 0; i < manager_->max_draw_buffers_; ++i) { 389 if (buffers[i] != draw_buffers_[i]) { 390 different = true; 391 break; 392 } 393 } 394 if (different) { 395 if (recover) 396 glDrawBuffersARB(manager_->max_draw_buffers_, draw_buffers_.get()); 397 else 398 glDrawBuffersARB(manager_->max_draw_buffers_, buffers.get()); 399 } 400 } 401 402 void Framebuffer::PrepareDrawBuffersForClear() const { 403 bool recover = false; 404 ChangeDrawBuffersHelper(recover); 405 } 406 407 void Framebuffer::RestoreDrawBuffersAfterClear() const { 408 bool recover = true; 409 ChangeDrawBuffersHelper(recover); 410 } 411 412 void Framebuffer::MarkAttachmentAsCleared( 413 RenderbufferManager* renderbuffer_manager, 414 TextureManager* texture_manager, 415 GLenum attachment, 416 bool cleared) { 417 AttachmentMap::iterator it = attachments_.find(attachment); 418 if (it != attachments_.end()) { 419 Attachment* a = it->second.get(); 420 if (a->cleared() != cleared) { 421 a->SetCleared(renderbuffer_manager, 422 texture_manager, 423 cleared); 424 } 425 } 426 } 427 428 void Framebuffer::MarkAttachmentsAsCleared( 429 RenderbufferManager* renderbuffer_manager, 430 TextureManager* texture_manager, 431 bool cleared) { 432 for (AttachmentMap::iterator it = attachments_.begin(); 433 it != attachments_.end(); ++it) { 434 Attachment* attachment = it->second.get(); 435 if (attachment->cleared() != cleared) { 436 attachment->SetCleared(renderbuffer_manager, texture_manager, cleared); 437 } 438 } 439 } 440 441 bool Framebuffer::HasDepthAttachment() const { 442 return attachments_.find(GL_DEPTH_STENCIL_ATTACHMENT) != attachments_.end() || 443 attachments_.find(GL_DEPTH_ATTACHMENT) != attachments_.end(); 444 } 445 446 bool Framebuffer::HasStencilAttachment() const { 447 return attachments_.find(GL_DEPTH_STENCIL_ATTACHMENT) != attachments_.end() || 448 attachments_.find(GL_STENCIL_ATTACHMENT) != attachments_.end(); 449 } 450 451 GLenum Framebuffer::GetColorAttachmentFormat() const { 452 AttachmentMap::const_iterator it = attachments_.find(GL_COLOR_ATTACHMENT0); 453 if (it == attachments_.end()) { 454 return 0; 455 } 456 const Attachment* attachment = it->second.get(); 457 return attachment->internal_format(); 458 } 459 460 GLenum Framebuffer::GetColorAttachmentTextureType() const { 461 AttachmentMap::const_iterator it = attachments_.find(GL_COLOR_ATTACHMENT0); 462 if (it == attachments_.end()) { 463 return 0; 464 } 465 const Attachment* attachment = it->second.get(); 466 return attachment->texture_type(); 467 } 468 469 GLenum Framebuffer::IsPossiblyComplete() const { 470 if (attachments_.empty()) { 471 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; 472 } 473 474 GLsizei width = -1; 475 GLsizei height = -1; 476 for (AttachmentMap::const_iterator it = attachments_.begin(); 477 it != attachments_.end(); ++it) { 478 GLenum attachment_type = it->first; 479 Attachment* attachment = it->second.get(); 480 if (!attachment->ValidForAttachmentType(attachment_type, 481 manager_->max_color_attachments_)) { 482 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 483 } 484 if (width < 0) { 485 width = attachment->width(); 486 height = attachment->height(); 487 if (width == 0 || height == 0) { 488 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 489 } 490 } else { 491 if (attachment->width() != width || attachment->height() != height) { 492 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT; 493 } 494 } 495 496 if (!attachment->CanRenderTo()) { 497 return GL_FRAMEBUFFER_UNSUPPORTED; 498 } 499 } 500 501 // This does not mean the framebuffer is actually complete. It just means our 502 // checks passed. 503 return GL_FRAMEBUFFER_COMPLETE; 504 } 505 506 GLenum Framebuffer::GetStatus( 507 TextureManager* texture_manager, GLenum target) const { 508 // Check if we have this combo already. 509 std::string signature; 510 if (allow_framebuffer_combo_complete_map_) { 511 signature = base::StringPrintf("|FBO|target=%04x", target); 512 for (AttachmentMap::const_iterator it = attachments_.begin(); 513 it != attachments_.end(); ++it) { 514 Attachment* attachment = it->second.get(); 515 signature += 516 base::StringPrintf("|Attachment|attachmentpoint=%04x", it->first); 517 attachment->AddToSignature(texture_manager, &signature); 518 } 519 520 if (!framebuffer_combo_complete_map_) { 521 framebuffer_combo_complete_map_ = new FramebufferComboCompleteMap(); 522 } 523 524 FramebufferComboCompleteMap::const_iterator it = 525 framebuffer_combo_complete_map_->find(signature); 526 if (it != framebuffer_combo_complete_map_->end()) { 527 return GL_FRAMEBUFFER_COMPLETE; 528 } 529 } 530 531 GLenum result = glCheckFramebufferStatusEXT(target); 532 533 // Insert the new result into the combo map. 534 if (allow_framebuffer_combo_complete_map_ && 535 result == GL_FRAMEBUFFER_COMPLETE) { 536 framebuffer_combo_complete_map_->insert(std::make_pair(signature, true)); 537 } 538 539 return result; 540 } 541 542 bool Framebuffer::IsCleared() const { 543 // are all the attachments cleaared? 544 for (AttachmentMap::const_iterator it = attachments_.begin(); 545 it != attachments_.end(); ++it) { 546 Attachment* attachment = it->second.get(); 547 if (!attachment->cleared()) { 548 return false; 549 } 550 } 551 return true; 552 } 553 554 GLenum Framebuffer::GetDrawBuffer(GLenum draw_buffer) const { 555 GLsizei index = static_cast<GLsizei>( 556 draw_buffer - GL_DRAW_BUFFER0_ARB); 557 CHECK(index >= 0 && 558 index < static_cast<GLsizei>(manager_->max_draw_buffers_)); 559 return draw_buffers_[index]; 560 } 561 562 void Framebuffer::SetDrawBuffers(GLsizei n, const GLenum* bufs) { 563 DCHECK(n <= static_cast<GLsizei>(manager_->max_draw_buffers_)); 564 for (GLsizei i = 0; i < n; ++i) 565 draw_buffers_[i] = bufs[i]; 566 } 567 568 569 570 bool Framebuffer::HasAlphaMRT() const { 571 for (uint32 i = 0; i < manager_->max_draw_buffers_; ++i) { 572 if (draw_buffers_[i] != GL_NONE) { 573 const Attachment* attachment = GetAttachment(draw_buffers_[i]); 574 if (!attachment) 575 continue; 576 if ((GLES2Util::GetChannelsForFormat( 577 attachment->internal_format()) & 0x0008) != 0) 578 return true; 579 } 580 } 581 return false; 582 } 583 584 void Framebuffer::UnbindRenderbuffer( 585 GLenum target, Renderbuffer* renderbuffer) { 586 bool done; 587 do { 588 done = true; 589 for (AttachmentMap::const_iterator it = attachments_.begin(); 590 it != attachments_.end(); ++it) { 591 Attachment* attachment = it->second.get(); 592 if (attachment->IsRenderbuffer(renderbuffer)) { 593 // TODO(gman): manually detach renderbuffer. 594 // glFramebufferRenderbufferEXT(target, it->first, GL_RENDERBUFFER, 0); 595 AttachRenderbuffer(it->first, NULL); 596 done = false; 597 break; 598 } 599 } 600 } while (!done); 601 } 602 603 void Framebuffer::UnbindTexture( 604 GLenum target, TextureRef* texture_ref) { 605 bool done; 606 do { 607 done = true; 608 for (AttachmentMap::const_iterator it = attachments_.begin(); 609 it != attachments_.end(); ++it) { 610 Attachment* attachment = it->second.get(); 611 if (attachment->IsTexture(texture_ref)) { 612 // TODO(gman): manually detach texture. 613 // glFramebufferTexture2DEXT(target, it->first, GL_TEXTURE_2D, 0, 0); 614 AttachTexture(it->first, NULL, GL_TEXTURE_2D, 0, 0); 615 done = false; 616 break; 617 } 618 } 619 } while (!done); 620 } 621 622 Framebuffer* FramebufferManager::GetFramebuffer( 623 GLuint client_id) { 624 FramebufferMap::iterator it = framebuffers_.find(client_id); 625 return it != framebuffers_.end() ? it->second.get() : NULL; 626 } 627 628 void FramebufferManager::RemoveFramebuffer(GLuint client_id) { 629 FramebufferMap::iterator it = framebuffers_.find(client_id); 630 if (it != framebuffers_.end()) { 631 it->second->MarkAsDeleted(); 632 framebuffers_.erase(it); 633 } 634 } 635 636 void Framebuffer::AttachRenderbuffer( 637 GLenum attachment, Renderbuffer* renderbuffer) { 638 const Attachment* a = GetAttachment(attachment); 639 if (a) 640 a->DetachFromFramebuffer(this); 641 if (renderbuffer) { 642 attachments_[attachment] = scoped_refptr<Attachment>( 643 new RenderbufferAttachment(renderbuffer)); 644 } else { 645 attachments_.erase(attachment); 646 } 647 framebuffer_complete_state_count_id_ = 0; 648 } 649 650 void Framebuffer::AttachTexture( 651 GLenum attachment, TextureRef* texture_ref, GLenum target, 652 GLint level, GLsizei samples) { 653 const Attachment* a = GetAttachment(attachment); 654 if (a) 655 a->DetachFromFramebuffer(this); 656 if (texture_ref) { 657 attachments_[attachment] = scoped_refptr<Attachment>( 658 new TextureAttachment(texture_ref, target, level, samples)); 659 texture_ref->texture()->AttachToFramebuffer(); 660 } else { 661 attachments_.erase(attachment); 662 } 663 framebuffer_complete_state_count_id_ = 0; 664 } 665 666 const Framebuffer::Attachment* 667 Framebuffer::GetAttachment( 668 GLenum attachment) const { 669 AttachmentMap::const_iterator it = attachments_.find(attachment); 670 if (it != attachments_.end()) { 671 return it->second.get(); 672 } 673 return NULL; 674 } 675 676 void Framebuffer::OnTextureRefDetached(TextureRef* texture) { 677 manager_->OnTextureRefDetached(texture); 678 } 679 680 void Framebuffer::OnWillRenderTo() const { 681 for (AttachmentMap::const_iterator it = attachments_.begin(); 682 it != attachments_.end(); ++it) { 683 it->second->OnWillRenderTo(); 684 } 685 } 686 687 void Framebuffer::OnDidRenderTo() const { 688 for (AttachmentMap::const_iterator it = attachments_.begin(); 689 it != attachments_.end(); ++it) { 690 it->second->OnDidRenderTo(); 691 } 692 } 693 694 bool FramebufferManager::GetClientId( 695 GLuint service_id, GLuint* client_id) const { 696 // This doesn't need to be fast. It's only used during slow queries. 697 for (FramebufferMap::const_iterator it = framebuffers_.begin(); 698 it != framebuffers_.end(); ++it) { 699 if (it->second->service_id() == service_id) { 700 *client_id = it->first; 701 return true; 702 } 703 } 704 return false; 705 } 706 707 void FramebufferManager::MarkAttachmentsAsCleared( 708 Framebuffer* framebuffer, 709 RenderbufferManager* renderbuffer_manager, 710 TextureManager* texture_manager) { 711 DCHECK(framebuffer); 712 framebuffer->MarkAttachmentsAsCleared(renderbuffer_manager, 713 texture_manager, 714 true); 715 MarkAsComplete(framebuffer); 716 } 717 718 void FramebufferManager::MarkAsComplete( 719 Framebuffer* framebuffer) { 720 DCHECK(framebuffer); 721 framebuffer->MarkAsComplete(framebuffer_state_change_count_); 722 } 723 724 bool FramebufferManager::IsComplete( 725 Framebuffer* framebuffer) { 726 DCHECK(framebuffer); 727 return framebuffer->framebuffer_complete_state_count_id() == 728 framebuffer_state_change_count_; 729 } 730 731 void FramebufferManager::OnTextureRefDetached(TextureRef* texture) { 732 for (TextureDetachObserverVector::iterator it = 733 texture_detach_observers_.begin(); 734 it != texture_detach_observers_.end(); 735 ++it) { 736 TextureDetachObserver* observer = *it; 737 observer->OnTextureRefDetachedFromFramebuffer(texture); 738 } 739 } 740 741 } // namespace gles2 742 } // namespace gpu 743 744 745