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