Elim cr-checkbox
[chromium-blink-merge.git] / gpu / command_buffer / service / framebuffer_manager.cc
blob4a4ffde26f240c07849d2eb09ba59f093002b234
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.
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/framebuffer_completeness_cache.h"
10 #include "gpu/command_buffer/service/renderbuffer_manager.h"
11 #include "gpu/command_buffer/service/texture_manager.h"
12 #include "ui/gl/gl_bindings.h"
14 namespace gpu {
15 namespace gles2 {
17 DecoderFramebufferState::DecoderFramebufferState()
18 : clear_state_dirty(false),
19 bound_read_framebuffer(NULL),
20 bound_draw_framebuffer(NULL) {
23 DecoderFramebufferState::~DecoderFramebufferState() {
26 class RenderbufferAttachment
27 : public Framebuffer::Attachment {
28 public:
29 explicit RenderbufferAttachment(
30 Renderbuffer* renderbuffer)
31 : renderbuffer_(renderbuffer) {
34 GLsizei width() const override { return renderbuffer_->width(); }
36 GLsizei height() const override { return renderbuffer_->height(); }
38 GLenum internal_format() const override {
39 return renderbuffer_->internal_format();
42 GLenum texture_type() const override { return 0; }
44 GLsizei samples() const override { return renderbuffer_->samples(); }
46 GLuint object_name() const override { return renderbuffer_->client_id(); }
48 bool cleared() const override { return renderbuffer_->cleared(); }
50 void SetCleared(RenderbufferManager* renderbuffer_manager,
51 TextureManager* /* texture_manager */,
52 bool cleared) override {
53 renderbuffer_manager->SetCleared(renderbuffer_.get(), cleared);
56 bool IsTexture(TextureRef* /* texture */) const override { return false; }
58 bool IsRenderbuffer(Renderbuffer* renderbuffer) const override {
59 return renderbuffer_.get() == renderbuffer;
62 bool CanRenderTo() const override { return true; }
64 void DetachFromFramebuffer(Framebuffer* framebuffer) const override {
65 // Nothing to do for renderbuffers.
68 bool ValidForAttachmentType(GLenum attachment_type,
69 uint32 max_color_attachments) override {
70 uint32 need = GLES2Util::GetChannelsNeededForAttachmentType(
71 attachment_type, max_color_attachments);
72 uint32 have = GLES2Util::GetChannelsForFormat(internal_format());
73 return (need & have) != 0;
76 Renderbuffer* renderbuffer() const {
77 return renderbuffer_.get();
80 size_t GetSignatureSize(TextureManager* texture_manager) const override {
81 return renderbuffer_->GetSignatureSize();
84 void AddToSignature(TextureManager* texture_manager,
85 std::string* signature) const override {
86 DCHECK(signature);
87 renderbuffer_->AddToSignature(signature);
90 void OnWillRenderTo() const override {}
91 void OnDidRenderTo() const override {}
92 bool FormsFeedbackLoop(TextureRef* /* texture */,
93 GLint /*level */) const override {
94 return false;
97 protected:
98 ~RenderbufferAttachment() override {}
100 private:
101 scoped_refptr<Renderbuffer> renderbuffer_;
103 DISALLOW_COPY_AND_ASSIGN(RenderbufferAttachment);
106 class TextureAttachment
107 : public Framebuffer::Attachment {
108 public:
109 TextureAttachment(
110 TextureRef* texture_ref, GLenum target, GLint level, GLsizei samples)
111 : texture_ref_(texture_ref),
112 target_(target),
113 level_(level),
114 samples_(samples) {
117 GLsizei width() const override {
118 GLsizei temp_width = 0;
119 GLsizei temp_height = 0;
120 texture_ref_->texture()->GetLevelSize(
121 target_, level_, &temp_width, &temp_height, nullptr);
122 return temp_width;
125 GLsizei height() const override {
126 GLsizei temp_width = 0;
127 GLsizei temp_height = 0;
128 texture_ref_->texture()->GetLevelSize(
129 target_, level_, &temp_width, &temp_height, nullptr);
130 return temp_height;
133 GLenum internal_format() const override {
134 GLenum temp_type = 0;
135 GLenum temp_internal_format = 0;
136 texture_ref_->texture()->GetLevelType(
137 target_, level_, &temp_type, &temp_internal_format);
138 return temp_internal_format;
141 GLenum texture_type() const override {
142 GLenum temp_type = 0;
143 GLenum temp_internal_format = 0;
144 texture_ref_->texture()->GetLevelType(
145 target_, level_, &temp_type, &temp_internal_format);
146 return temp_type;
149 GLsizei samples() const override { return samples_; }
151 GLuint object_name() const override { return texture_ref_->client_id(); }
153 bool cleared() const override {
154 return texture_ref_->texture()->IsLevelCleared(target_, level_);
157 void SetCleared(RenderbufferManager* /* renderbuffer_manager */,
158 TextureManager* texture_manager,
159 bool cleared) override {
160 texture_manager->SetLevelCleared(
161 texture_ref_.get(), target_, level_, cleared);
164 bool IsTexture(TextureRef* texture) const override {
165 return texture == texture_ref_.get();
168 bool IsRenderbuffer(Renderbuffer* /* renderbuffer */) const override {
169 return false;
172 TextureRef* texture() const {
173 return texture_ref_.get();
176 bool CanRenderTo() const override {
177 return texture_ref_->texture()->CanRenderTo();
180 void DetachFromFramebuffer(Framebuffer* framebuffer) const override {
181 texture_ref_->texture()->DetachFromFramebuffer();
182 framebuffer->OnTextureRefDetached(texture_ref_.get());
185 bool ValidForAttachmentType(GLenum attachment_type,
186 uint32 max_color_attachments) override {
187 GLenum type = 0;
188 GLenum internal_format = 0;
189 if (!texture_ref_->texture()->GetLevelType(
190 target_, level_, &type, &internal_format)) {
191 return false;
193 uint32 need = GLES2Util::GetChannelsNeededForAttachmentType(
194 attachment_type, max_color_attachments);
195 uint32 have = GLES2Util::GetChannelsForFormat(internal_format);
197 // Workaround for NVIDIA drivers that incorrectly expose these formats as
198 // renderable:
199 if (internal_format == GL_LUMINANCE || internal_format == GL_ALPHA ||
200 internal_format == GL_LUMINANCE_ALPHA) {
201 return false;
203 return (need & have) != 0;
206 size_t GetSignatureSize(TextureManager* texture_manager) const override {
207 return texture_manager->GetSignatureSize();
210 void AddToSignature(TextureManager* texture_manager,
211 std::string* signature) const override {
212 DCHECK(signature);
213 texture_manager->AddToSignature(
214 texture_ref_.get(), target_, level_, signature);
217 void OnWillRenderTo() const override {
218 texture_ref_->texture()->OnWillModifyPixels();
221 void OnDidRenderTo() const override {
222 texture_ref_->texture()->OnDidModifyPixels();
225 bool FormsFeedbackLoop(TextureRef* texture, GLint level) const override {
226 return texture == texture_ref_.get() && level == level_;
229 protected:
230 ~TextureAttachment() override {}
232 private:
233 scoped_refptr<TextureRef> texture_ref_;
234 GLenum target_;
235 GLint level_;
236 GLsizei samples_;
238 DISALLOW_COPY_AND_ASSIGN(TextureAttachment);
241 FramebufferManager::TextureDetachObserver::TextureDetachObserver() {}
243 FramebufferManager::TextureDetachObserver::~TextureDetachObserver() {}
245 FramebufferManager::FramebufferManager(
246 uint32 max_draw_buffers,
247 uint32 max_color_attachments,
248 ContextGroup::ContextType context_type,
249 const scoped_refptr<FramebufferCompletenessCache>&
250 framebuffer_combo_complete_cache)
251 : framebuffer_state_change_count_(1),
252 framebuffer_count_(0),
253 have_context_(true),
254 max_draw_buffers_(max_draw_buffers),
255 max_color_attachments_(max_color_attachments),
256 context_type_(context_type),
257 framebuffer_combo_complete_cache_(framebuffer_combo_complete_cache) {
258 DCHECK_GT(max_draw_buffers_, 0u);
259 DCHECK_GT(max_color_attachments_, 0u);
262 FramebufferManager::~FramebufferManager() {
263 DCHECK(framebuffers_.empty());
264 // If this triggers, that means something is keeping a reference to a
265 // Framebuffer belonging to this.
266 CHECK_EQ(framebuffer_count_, 0u);
269 void Framebuffer::MarkAsDeleted() {
270 deleted_ = true;
271 while (!attachments_.empty()) {
272 Attachment* attachment = attachments_.begin()->second.get();
273 attachment->DetachFromFramebuffer(this);
274 attachments_.erase(attachments_.begin());
278 void FramebufferManager::Destroy(bool have_context) {
279 have_context_ = have_context;
280 framebuffers_.clear();
283 void FramebufferManager::StartTracking(
284 Framebuffer* /* framebuffer */) {
285 ++framebuffer_count_;
288 void FramebufferManager::StopTracking(
289 Framebuffer* /* framebuffer */) {
290 --framebuffer_count_;
293 void FramebufferManager::CreateFramebuffer(
294 GLuint client_id, GLuint service_id) {
295 std::pair<FramebufferMap::iterator, bool> result =
296 framebuffers_.insert(
297 std::make_pair(
298 client_id,
299 scoped_refptr<Framebuffer>(
300 new Framebuffer(this, service_id))));
301 DCHECK(result.second);
304 Framebuffer::Framebuffer(
305 FramebufferManager* manager, GLuint service_id)
306 : manager_(manager),
307 deleted_(false),
308 service_id_(service_id),
309 has_been_bound_(false),
310 framebuffer_complete_state_count_id_(0),
311 read_buffer_(GL_COLOR_ATTACHMENT0) {
312 manager->StartTracking(this);
313 DCHECK_GT(manager->max_draw_buffers_, 0u);
314 draw_buffers_.reset(new GLenum[manager->max_draw_buffers_]);
315 draw_buffers_[0] = GL_COLOR_ATTACHMENT0;
316 for (uint32 i = 1; i < manager->max_draw_buffers_; ++i)
317 draw_buffers_[i] = GL_NONE;
320 Framebuffer::~Framebuffer() {
321 if (manager_) {
322 if (manager_->have_context_) {
323 GLuint id = service_id();
324 glDeleteFramebuffersEXT(1, &id);
326 manager_->StopTracking(this);
327 manager_ = NULL;
331 bool Framebuffer::HasUnclearedAttachment(
332 GLenum attachment) const {
333 AttachmentMap::const_iterator it =
334 attachments_.find(attachment);
335 if (it != attachments_.end()) {
336 const Attachment* attachment = it->second.get();
337 return !attachment->cleared();
339 return false;
342 bool Framebuffer::HasUnclearedColorAttachments() const {
343 for (AttachmentMap::const_iterator it = attachments_.begin();
344 it != attachments_.end(); ++it) {
345 if (it->first >= GL_COLOR_ATTACHMENT0 &&
346 it->first < GL_COLOR_ATTACHMENT0 + manager_->max_draw_buffers_) {
347 const Attachment* attachment = it->second.get();
348 if (!attachment->cleared())
349 return true;
352 return false;
355 void Framebuffer::ChangeDrawBuffersHelper(bool recover) const {
356 scoped_ptr<GLenum[]> buffers(new GLenum[manager_->max_draw_buffers_]);
357 for (uint32 i = 0; i < manager_->max_draw_buffers_; ++i)
358 buffers[i] = GL_NONE;
359 for (AttachmentMap::const_iterator it = attachments_.begin();
360 it != attachments_.end(); ++it) {
361 if (it->first >= GL_COLOR_ATTACHMENT0 &&
362 it->first < GL_COLOR_ATTACHMENT0 + manager_->max_draw_buffers_ &&
363 !GLES2Util::IsIntegerFormat(it->second->internal_format())) {
364 buffers[it->first - GL_COLOR_ATTACHMENT0] = it->first;
367 bool different = false;
368 for (uint32 i = 0; i < manager_->max_draw_buffers_; ++i) {
369 if (buffers[i] != draw_buffers_[i]) {
370 different = true;
371 break;
374 if (different) {
375 if (recover)
376 glDrawBuffersARB(manager_->max_draw_buffers_, draw_buffers_.get());
377 else
378 glDrawBuffersARB(manager_->max_draw_buffers_, buffers.get());
382 void Framebuffer::PrepareDrawBuffersForClear() const {
383 bool recover = false;
384 ChangeDrawBuffersHelper(recover);
387 void Framebuffer::RestoreDrawBuffersAfterClear() const {
388 bool recover = true;
389 ChangeDrawBuffersHelper(recover);
392 void Framebuffer::ClearIntegerBuffers() {
393 for (AttachmentMap::const_iterator it = attachments_.begin();
394 it != attachments_.end(); ++it) {
395 GLenum internal_format = it->second->internal_format();
396 if (it->first >= GL_COLOR_ATTACHMENT0 &&
397 it->first < GL_COLOR_ATTACHMENT0 + manager_->max_draw_buffers_ &&
398 !it->second->cleared() &&
399 GLES2Util::IsIntegerFormat(internal_format)) {
400 GLint drawbuffer = it->first - GL_COLOR_ATTACHMENT0;
401 if (GLES2Util::IsUnsignedIntegerFormat(internal_format)) {
402 const static GLuint kZero[] = { 0u, 0u, 0u, 0u };
403 glClearBufferuiv(GL_COLOR, drawbuffer, kZero);
404 } else { // IsUnsignedIntegerFormat(internal_format)
405 const static GLint kZero[] = { 0, 0, 0, 0 };
406 glClearBufferiv(GL_COLOR, drawbuffer, kZero);
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);
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);
441 bool Framebuffer::HasDepthAttachment() const {
442 return attachments_.find(GL_DEPTH_STENCIL_ATTACHMENT) != attachments_.end() ||
443 attachments_.find(GL_DEPTH_ATTACHMENT) != attachments_.end();
446 bool Framebuffer::HasStencilAttachment() const {
447 return attachments_.find(GL_DEPTH_STENCIL_ATTACHMENT) != attachments_.end() ||
448 attachments_.find(GL_STENCIL_ATTACHMENT) != attachments_.end();
451 GLenum Framebuffer::GetReadBufferInternalFormat() const {
452 if (read_buffer_ == GL_NONE)
453 return 0;
454 AttachmentMap::const_iterator it = attachments_.find(read_buffer_);
455 if (it == attachments_.end()) {
456 return 0;
458 const Attachment* attachment = it->second.get();
459 return attachment->internal_format();
462 GLenum Framebuffer::GetReadBufferTextureType() const {
463 if (read_buffer_ == GL_NONE)
464 return 0;
465 AttachmentMap::const_iterator it = attachments_.find(read_buffer_);
466 if (it == attachments_.end()) {
467 return 0;
469 const Attachment* attachment = it->second.get();
470 return attachment->texture_type();
473 GLenum Framebuffer::IsPossiblyComplete() const {
474 if (attachments_.empty()) {
475 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
478 GLsizei width = -1;
479 GLsizei height = -1;
480 for (AttachmentMap::const_iterator it = attachments_.begin();
481 it != attachments_.end(); ++it) {
482 GLenum attachment_type = it->first;
483 Attachment* attachment = it->second.get();
484 if (!attachment->ValidForAttachmentType(attachment_type,
485 manager_->max_color_attachments_)) {
486 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
488 if (width < 0) {
489 width = attachment->width();
490 height = attachment->height();
491 if (width == 0 || height == 0) {
492 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
494 } else if (manager_->context_type() != ContextGroup::CONTEXT_TYPE_WEBGL2) {
495 // TODO(zmo): revisit this if we create ES3 contexts for clients other
496 // than WebGL 2.
497 if (attachment->width() != width || attachment->height() != height) {
498 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
502 if (!attachment->CanRenderTo()) {
503 return GL_FRAMEBUFFER_UNSUPPORTED;
507 // This does not mean the framebuffer is actually complete. It just means our
508 // checks passed.
509 return GL_FRAMEBUFFER_COMPLETE;
512 GLenum Framebuffer::GetStatus(
513 TextureManager* texture_manager, GLenum target) const {
514 if (!manager_->GetFramebufferComboCompleteCache()) {
515 return glCheckFramebufferStatusEXT(target);
517 // Check if we have this combo already.
518 std::string signature;
520 size_t signature_size = sizeof(target);
521 for (AttachmentMap::const_iterator it = attachments_.begin();
522 it != attachments_.end(); ++it) {
523 Attachment* attachment = it->second.get();
524 signature_size +=
525 sizeof(it->first) + attachment->GetSignatureSize(texture_manager);
528 signature.reserve(signature_size);
529 signature.append(reinterpret_cast<const char*>(&target), sizeof(target));
531 for (AttachmentMap::const_iterator it = attachments_.begin();
532 it != attachments_.end(); ++it) {
533 Attachment* attachment = it->second.get();
534 signature.append(reinterpret_cast<const char*>(&it->first),
535 sizeof(it->first));
536 attachment->AddToSignature(texture_manager, &signature);
538 DCHECK(signature.size() == signature_size);
540 if (manager_->GetFramebufferComboCompleteCache()->IsComplete(signature)) {
541 return GL_FRAMEBUFFER_COMPLETE;
544 GLenum result = glCheckFramebufferStatusEXT(target);
546 if (result == GL_FRAMEBUFFER_COMPLETE) {
547 manager_->GetFramebufferComboCompleteCache()->SetComplete(signature);
550 return result;
553 bool Framebuffer::IsCleared() const {
554 // are all the attachments cleaared?
555 for (AttachmentMap::const_iterator it = attachments_.begin();
556 it != attachments_.end(); ++it) {
557 Attachment* attachment = it->second.get();
558 if (!attachment->cleared()) {
559 return false;
562 return true;
565 GLenum Framebuffer::GetDrawBuffer(GLenum draw_buffer) const {
566 GLsizei index = static_cast<GLsizei>(
567 draw_buffer - GL_DRAW_BUFFER0_ARB);
568 CHECK(index >= 0 &&
569 index < static_cast<GLsizei>(manager_->max_draw_buffers_));
570 return draw_buffers_[index];
573 void Framebuffer::SetDrawBuffers(GLsizei n, const GLenum* bufs) {
574 DCHECK(n <= static_cast<GLsizei>(manager_->max_draw_buffers_));
575 for (GLsizei i = 0; i < n; ++i)
576 draw_buffers_[i] = bufs[i];
579 bool Framebuffer::HasAlphaMRT() const {
580 for (uint32 i = 0; i < manager_->max_draw_buffers_; ++i) {
581 if (draw_buffers_[i] != GL_NONE) {
582 const Attachment* attachment = GetAttachment(draw_buffers_[i]);
583 if (!attachment)
584 continue;
585 if ((GLES2Util::GetChannelsForFormat(
586 attachment->internal_format()) & 0x0008) != 0)
587 return true;
590 return false;
593 bool Framebuffer::HasSameInternalFormatsMRT() const {
594 GLenum internal_format = 0;
595 for (uint32 i = 0; i < manager_->max_draw_buffers_; ++i) {
596 if (draw_buffers_[i] != GL_NONE) {
597 const Attachment* attachment = GetAttachment(draw_buffers_[i]);
598 if (!attachment)
599 continue;
600 if (!internal_format) {
601 internal_format = attachment->internal_format();
602 } else if (internal_format != attachment->internal_format()) {
603 return false;
607 return true;
610 void Framebuffer::UnbindRenderbuffer(
611 GLenum target, Renderbuffer* renderbuffer) {
612 bool done;
613 do {
614 done = true;
615 for (AttachmentMap::const_iterator it = attachments_.begin();
616 it != attachments_.end(); ++it) {
617 Attachment* attachment = it->second.get();
618 if (attachment->IsRenderbuffer(renderbuffer)) {
619 // TODO(gman): manually detach renderbuffer.
620 // glFramebufferRenderbufferEXT(target, it->first, GL_RENDERBUFFER, 0);
621 AttachRenderbuffer(it->first, NULL);
622 done = false;
623 break;
626 } while (!done);
629 void Framebuffer::UnbindTexture(
630 GLenum target, TextureRef* texture_ref) {
631 bool done;
632 do {
633 done = true;
634 for (AttachmentMap::const_iterator it = attachments_.begin();
635 it != attachments_.end(); ++it) {
636 Attachment* attachment = it->second.get();
637 if (attachment->IsTexture(texture_ref)) {
638 // TODO(gman): manually detach texture.
639 // glFramebufferTexture2DEXT(target, it->first, GL_TEXTURE_2D, 0, 0);
640 AttachTexture(it->first, NULL, GL_TEXTURE_2D, 0, 0);
641 done = false;
642 break;
645 } while (!done);
648 Framebuffer* FramebufferManager::GetFramebuffer(
649 GLuint client_id) {
650 FramebufferMap::iterator it = framebuffers_.find(client_id);
651 return it != framebuffers_.end() ? it->second.get() : NULL;
654 void FramebufferManager::RemoveFramebuffer(GLuint client_id) {
655 FramebufferMap::iterator it = framebuffers_.find(client_id);
656 if (it != framebuffers_.end()) {
657 it->second->MarkAsDeleted();
658 framebuffers_.erase(it);
662 void Framebuffer::DoUnbindGLAttachmentsForWorkaround(GLenum target) {
663 // Replace all attachments with the default Renderbuffer.
664 for (AttachmentMap::const_iterator it = attachments_.begin();
665 it != attachments_.end(); ++it) {
666 glFramebufferRenderbufferEXT(target, it->first, GL_RENDERBUFFER, 0);
670 void Framebuffer::AttachRenderbuffer(
671 GLenum attachment, Renderbuffer* renderbuffer) {
672 const Attachment* a = GetAttachment(attachment);
673 if (a)
674 a->DetachFromFramebuffer(this);
675 if (renderbuffer) {
676 attachments_[attachment] = scoped_refptr<Attachment>(
677 new RenderbufferAttachment(renderbuffer));
678 } else {
679 attachments_.erase(attachment);
681 framebuffer_complete_state_count_id_ = 0;
684 void Framebuffer::AttachTexture(
685 GLenum attachment, TextureRef* texture_ref, GLenum target,
686 GLint level, GLsizei samples) {
687 const Attachment* a = GetAttachment(attachment);
688 if (a)
689 a->DetachFromFramebuffer(this);
690 if (texture_ref) {
691 attachments_[attachment] = scoped_refptr<Attachment>(
692 new TextureAttachment(texture_ref, target, level, samples));
693 texture_ref->texture()->AttachToFramebuffer();
694 } else {
695 attachments_.erase(attachment);
697 framebuffer_complete_state_count_id_ = 0;
700 const Framebuffer::Attachment*
701 Framebuffer::GetAttachment(
702 GLenum attachment) const {
703 AttachmentMap::const_iterator it = attachments_.find(attachment);
704 if (it != attachments_.end()) {
705 return it->second.get();
707 return NULL;
710 const Framebuffer::Attachment* Framebuffer::GetReadBufferAttachment() const {
711 if (read_buffer_ == GL_NONE)
712 return nullptr;
713 return GetAttachment(read_buffer_);
716 void Framebuffer::OnTextureRefDetached(TextureRef* texture) {
717 manager_->OnTextureRefDetached(texture);
720 void Framebuffer::OnWillRenderTo(GLenum attachment) const {
721 for (AttachmentMap::const_iterator it = attachments_.begin();
722 it != attachments_.end(); ++it) {
723 if (attachment == 0 || attachment == it->first) {
724 it->second->OnWillRenderTo();
729 void Framebuffer::OnDidRenderTo(GLenum attachment) const {
730 for (AttachmentMap::const_iterator it = attachments_.begin();
731 it != attachments_.end(); ++it) {
732 if (attachment == 0 || attachment == it->first) {
733 it->second->OnDidRenderTo();
738 bool FramebufferManager::GetClientId(
739 GLuint service_id, GLuint* client_id) const {
740 // This doesn't need to be fast. It's only used during slow queries.
741 for (FramebufferMap::const_iterator it = framebuffers_.begin();
742 it != framebuffers_.end(); ++it) {
743 if (it->second->service_id() == service_id) {
744 *client_id = it->first;
745 return true;
748 return false;
751 void FramebufferManager::MarkAttachmentsAsCleared(
752 Framebuffer* framebuffer,
753 RenderbufferManager* renderbuffer_manager,
754 TextureManager* texture_manager) {
755 DCHECK(framebuffer);
756 framebuffer->MarkAttachmentsAsCleared(renderbuffer_manager,
757 texture_manager,
758 true);
759 MarkAsComplete(framebuffer);
762 void FramebufferManager::MarkAsComplete(
763 Framebuffer* framebuffer) {
764 DCHECK(framebuffer);
765 framebuffer->MarkAsComplete(framebuffer_state_change_count_);
768 bool FramebufferManager::IsComplete(
769 Framebuffer* framebuffer) {
770 DCHECK(framebuffer);
771 return framebuffer->framebuffer_complete_state_count_id() ==
772 framebuffer_state_change_count_;
775 void FramebufferManager::OnTextureRefDetached(TextureRef* texture) {
776 for (TextureDetachObserverVector::iterator it =
777 texture_detach_observers_.begin();
778 it != texture_detach_observers_.end();
779 ++it) {
780 TextureDetachObserver* observer = *it;
781 observer->OnTextureRefDetachedFromFramebuffer(texture);
785 } // namespace gles2
786 } // namespace gpu