• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
DecoderFramebufferState()16 DecoderFramebufferState::DecoderFramebufferState()
17     : clear_state_dirty(false),
18       bound_read_framebuffer(NULL),
19       bound_draw_framebuffer(NULL) {
20 }
21 
~DecoderFramebufferState()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 
ClearFramebufferCompleteComboMap()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:
RenderbufferAttachment(Renderbuffer * renderbuffer)46   explicit RenderbufferAttachment(
47       Renderbuffer* renderbuffer)
48       : renderbuffer_(renderbuffer) {
49   }
50 
width() const51   virtual GLsizei width() const OVERRIDE {
52     return renderbuffer_->width();
53   }
54 
height() const55   virtual GLsizei height() const OVERRIDE {
56     return renderbuffer_->height();
57   }
58 
internal_format() const59   virtual GLenum internal_format() const OVERRIDE {
60     return renderbuffer_->internal_format();
61   }
62 
texture_type() const63   virtual GLenum texture_type() const OVERRIDE {
64     return 0;
65   }
66 
samples() const67   virtual GLsizei samples() const OVERRIDE {
68     return renderbuffer_->samples();
69   }
70 
object_name() const71   virtual GLuint object_name() const OVERRIDE {
72     return renderbuffer_->client_id();
73   }
74 
cleared() const75   virtual bool cleared() const OVERRIDE {
76     return renderbuffer_->cleared();
77   }
78 
SetCleared(RenderbufferManager * renderbuffer_manager,TextureManager *,bool cleared)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 
IsTexture(TextureRef *) const86   virtual bool IsTexture(
87       TextureRef* /* texture */) const OVERRIDE {
88     return false;
89   }
90 
IsRenderbuffer(Renderbuffer * renderbuffer) const91   virtual bool IsRenderbuffer(
92        Renderbuffer* renderbuffer) const OVERRIDE {
93     return renderbuffer_.get() == renderbuffer;
94   }
95 
CanRenderTo() const96   virtual bool CanRenderTo() const OVERRIDE {
97     return true;
98   }
99 
DetachFromFramebuffer(Framebuffer * framebuffer) const100   virtual void DetachFromFramebuffer(Framebuffer* framebuffer) const OVERRIDE {
101     // Nothing to do for renderbuffers.
102   }
103 
ValidForAttachmentType(GLenum attachment_type,uint32 max_color_attachments)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 
renderbuffer() const112   Renderbuffer* renderbuffer() const {
113     return renderbuffer_.get();
114   }
115 
AddToSignature(TextureManager * texture_manager,std::string * signature) const116   virtual void AddToSignature(
117       TextureManager* texture_manager, std::string* signature) const OVERRIDE {
118     DCHECK(signature);
119     renderbuffer_->AddToSignature(signature);
120   }
121 
OnWillRenderTo() const122   virtual void OnWillRenderTo() const OVERRIDE {}
OnDidRenderTo() const123   virtual void OnDidRenderTo() const OVERRIDE {}
124 
125  protected:
~RenderbufferAttachment()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:
TextureAttachment(TextureRef * texture_ref,GLenum target,GLint level,GLsizei samples)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 
width() const145   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 
height() const153   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 
internal_format() const161   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 
texture_type() const169   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 
samples() const177   virtual GLsizei samples() const OVERRIDE {
178     return samples_;
179   }
180 
object_name() const181   virtual GLuint object_name() const OVERRIDE {
182     return texture_ref_->client_id();
183   }
184 
cleared() const185   virtual bool cleared() const OVERRIDE {
186     return texture_ref_->texture()->IsLevelCleared(target_, level_);
187   }
188 
SetCleared(RenderbufferManager *,TextureManager * texture_manager,bool cleared)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 
IsTexture(TextureRef * texture) const197   virtual bool IsTexture(TextureRef* texture) const OVERRIDE {
198     return texture == texture_ref_.get();
199   }
200 
IsRenderbuffer(Renderbuffer *) const201   virtual bool IsRenderbuffer(
202        Renderbuffer* /* renderbuffer */)
203           const OVERRIDE {
204     return false;
205   }
206 
texture() const207   TextureRef* texture() const {
208     return texture_ref_.get();
209   }
210 
CanRenderTo() const211   virtual bool CanRenderTo() const OVERRIDE {
212     return texture_ref_->texture()->CanRenderTo();
213   }
214 
DetachFromFramebuffer(Framebuffer * framebuffer) const215   virtual void DetachFromFramebuffer(Framebuffer* framebuffer)
216       const OVERRIDE {
217     texture_ref_->texture()->DetachFromFramebuffer();
218     framebuffer->OnTextureRefDetached(texture_ref_.get());
219   }
220 
ValidForAttachmentType(GLenum attachment_type,uint32 max_color_attachments)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 
AddToSignature(TextureManager * texture_manager,std::string * signature) const242   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 
OnWillRenderTo() const249   virtual void OnWillRenderTo() const OVERRIDE {
250     texture_ref_->texture()->OnWillModifyPixels();
251   }
252 
OnDidRenderTo() const253   virtual void OnDidRenderTo() const OVERRIDE {
254     texture_ref_->texture()->OnDidModifyPixels();
255   }
256 
257  protected:
~TextureAttachment()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 
TextureDetachObserver()269 FramebufferManager::TextureDetachObserver::TextureDetachObserver() {}
270 
~TextureDetachObserver()271 FramebufferManager::TextureDetachObserver::~TextureDetachObserver() {}
272 
FramebufferManager(uint32 max_draw_buffers,uint32 max_color_attachments)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 
~FramebufferManager()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 
MarkAsDeleted()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 
Destroy(bool have_context)300 void FramebufferManager::Destroy(bool have_context) {
301   have_context_ = have_context;
302   framebuffers_.clear();
303 }
304 
StartTracking(Framebuffer *)305 void FramebufferManager::StartTracking(
306     Framebuffer* /* framebuffer */) {
307   ++framebuffer_count_;
308 }
309 
StopTracking(Framebuffer *)310 void FramebufferManager::StopTracking(
311     Framebuffer* /* framebuffer */) {
312   --framebuffer_count_;
313 }
314 
CreateFramebuffer(GLuint client_id,GLuint service_id)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 
Framebuffer(FramebufferManager * manager,GLuint service_id)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 
~Framebuffer()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 
HasUnclearedAttachment(GLenum attachment) const352 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 
MarkAttachmentAsCleared(RenderbufferManager * renderbuffer_manager,TextureManager * texture_manager,GLenum attachment,bool cleared)363 void Framebuffer::MarkAttachmentAsCleared(
364       RenderbufferManager* renderbuffer_manager,
365       TextureManager* texture_manager,
366       GLenum attachment,
367       bool cleared) {
368   AttachmentMap::iterator it = attachments_.find(attachment);
369   if (it != attachments_.end()) {
370     Attachment* a = it->second.get();
371     if (a->cleared() != cleared) {
372       a->SetCleared(renderbuffer_manager,
373                     texture_manager,
374                     cleared);
375     }
376   }
377 }
378 
MarkAttachmentsAsCleared(RenderbufferManager * renderbuffer_manager,TextureManager * texture_manager,bool cleared)379 void Framebuffer::MarkAttachmentsAsCleared(
380       RenderbufferManager* renderbuffer_manager,
381       TextureManager* texture_manager,
382       bool cleared) {
383   for (AttachmentMap::iterator it = attachments_.begin();
384        it != attachments_.end(); ++it) {
385     Attachment* attachment = it->second.get();
386     if (attachment->cleared() != cleared) {
387       attachment->SetCleared(renderbuffer_manager, texture_manager, cleared);
388     }
389   }
390 }
391 
HasDepthAttachment() const392 bool Framebuffer::HasDepthAttachment() const {
393   return attachments_.find(GL_DEPTH_STENCIL_ATTACHMENT) != attachments_.end() ||
394          attachments_.find(GL_DEPTH_ATTACHMENT) != attachments_.end();
395 }
396 
HasStencilAttachment() const397 bool Framebuffer::HasStencilAttachment() const {
398   return attachments_.find(GL_DEPTH_STENCIL_ATTACHMENT) != attachments_.end() ||
399          attachments_.find(GL_STENCIL_ATTACHMENT) != attachments_.end();
400 }
401 
GetColorAttachmentFormat() const402 GLenum Framebuffer::GetColorAttachmentFormat() const {
403   AttachmentMap::const_iterator it = attachments_.find(GL_COLOR_ATTACHMENT0);
404   if (it == attachments_.end()) {
405     return 0;
406   }
407   const Attachment* attachment = it->second.get();
408   return attachment->internal_format();
409 }
410 
GetColorAttachmentTextureType() const411 GLenum Framebuffer::GetColorAttachmentTextureType() const {
412   AttachmentMap::const_iterator it = attachments_.find(GL_COLOR_ATTACHMENT0);
413   if (it == attachments_.end()) {
414     return 0;
415   }
416   const Attachment* attachment = it->second.get();
417   return attachment->texture_type();
418 }
419 
IsPossiblyComplete() const420 GLenum Framebuffer::IsPossiblyComplete() const {
421   if (attachments_.empty()) {
422     return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
423   }
424 
425   GLsizei width = -1;
426   GLsizei height = -1;
427   for (AttachmentMap::const_iterator it = attachments_.begin();
428        it != attachments_.end(); ++it) {
429     GLenum attachment_type = it->first;
430     Attachment* attachment = it->second.get();
431     if (!attachment->ValidForAttachmentType(attachment_type,
432                                             manager_->max_color_attachments_)) {
433       return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
434     }
435     if (width < 0) {
436       width = attachment->width();
437       height = attachment->height();
438       if (width == 0 || height == 0) {
439         return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
440       }
441     } else {
442       if (attachment->width() != width || attachment->height() != height) {
443         return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
444       }
445     }
446 
447     if (!attachment->CanRenderTo()) {
448       return GL_FRAMEBUFFER_UNSUPPORTED;
449     }
450   }
451 
452   // This does not mean the framebuffer is actually complete. It just means our
453   // checks passed.
454   return GL_FRAMEBUFFER_COMPLETE;
455 }
456 
GetStatus(TextureManager * texture_manager,GLenum target) const457 GLenum Framebuffer::GetStatus(
458     TextureManager* texture_manager, GLenum target) const {
459   // Check if we have this combo already.
460   std::string signature;
461   if (allow_framebuffer_combo_complete_map_) {
462     signature = base::StringPrintf("|FBO|target=%04x", target);
463     for (AttachmentMap::const_iterator it = attachments_.begin();
464          it != attachments_.end(); ++it) {
465       Attachment* attachment = it->second.get();
466       signature +=
467           base::StringPrintf("|Attachment|attachmentpoint=%04x", it->first);
468       attachment->AddToSignature(texture_manager, &signature);
469     }
470 
471     if (!framebuffer_combo_complete_map_) {
472       framebuffer_combo_complete_map_ = new FramebufferComboCompleteMap();
473     }
474 
475     FramebufferComboCompleteMap::const_iterator it =
476         framebuffer_combo_complete_map_->find(signature);
477     if (it != framebuffer_combo_complete_map_->end()) {
478       return GL_FRAMEBUFFER_COMPLETE;
479     }
480   }
481 
482   GLenum result = glCheckFramebufferStatusEXT(target);
483 
484   // Insert the new result into the combo map.
485   if (allow_framebuffer_combo_complete_map_ &&
486       result == GL_FRAMEBUFFER_COMPLETE) {
487     framebuffer_combo_complete_map_->insert(std::make_pair(signature, true));
488   }
489 
490   return result;
491 }
492 
IsCleared() const493 bool Framebuffer::IsCleared() const {
494   // are all the attachments cleaared?
495   for (AttachmentMap::const_iterator it = attachments_.begin();
496        it != attachments_.end(); ++it) {
497     Attachment* attachment = it->second.get();
498     if (!attachment->cleared()) {
499       return false;
500     }
501   }
502   return true;
503 }
504 
GetDrawBuffer(GLenum draw_buffer) const505 GLenum Framebuffer::GetDrawBuffer(GLenum draw_buffer) const {
506   GLsizei index = static_cast<GLsizei>(
507       draw_buffer - GL_DRAW_BUFFER0_ARB);
508   CHECK(index >= 0 &&
509         index < static_cast<GLsizei>(manager_->max_draw_buffers_));
510   return draw_buffers_[index];
511 }
512 
SetDrawBuffers(GLsizei n,const GLenum * bufs)513 void Framebuffer::SetDrawBuffers(GLsizei n, const GLenum* bufs) {
514   DCHECK(n <= static_cast<GLsizei>(manager_->max_draw_buffers_));
515   for (GLsizei i = 0; i < n; ++i)
516     draw_buffers_[i] = bufs[i];
517 }
518 
HasAlphaMRT() const519 bool Framebuffer::HasAlphaMRT() const {
520   for (uint32 i = 0; i < manager_->max_draw_buffers_; ++i) {
521     if (draw_buffers_[i] != GL_NONE) {
522       const Attachment* attachment = GetAttachment(draw_buffers_[i]);
523       if (!attachment)
524         continue;
525       if ((GLES2Util::GetChannelsForFormat(
526                attachment->internal_format()) & 0x0008) != 0)
527         return true;
528     }
529   }
530   return false;
531 }
532 
UnbindRenderbuffer(GLenum target,Renderbuffer * renderbuffer)533 void Framebuffer::UnbindRenderbuffer(
534     GLenum target, Renderbuffer* renderbuffer) {
535   bool done;
536   do {
537     done = true;
538     for (AttachmentMap::const_iterator it = attachments_.begin();
539          it != attachments_.end(); ++it) {
540       Attachment* attachment = it->second.get();
541       if (attachment->IsRenderbuffer(renderbuffer)) {
542         // TODO(gman): manually detach renderbuffer.
543         // glFramebufferRenderbufferEXT(target, it->first, GL_RENDERBUFFER, 0);
544         AttachRenderbuffer(it->first, NULL);
545         done = false;
546         break;
547       }
548     }
549   } while (!done);
550 }
551 
UnbindTexture(GLenum target,TextureRef * texture_ref)552 void Framebuffer::UnbindTexture(
553     GLenum target, TextureRef* texture_ref) {
554   bool done;
555   do {
556     done = true;
557     for (AttachmentMap::const_iterator it = attachments_.begin();
558          it != attachments_.end(); ++it) {
559       Attachment* attachment = it->second.get();
560       if (attachment->IsTexture(texture_ref)) {
561         // TODO(gman): manually detach texture.
562         // glFramebufferTexture2DEXT(target, it->first, GL_TEXTURE_2D, 0, 0);
563         AttachTexture(it->first, NULL, GL_TEXTURE_2D, 0, 0);
564         done = false;
565         break;
566       }
567     }
568   } while (!done);
569 }
570 
GetFramebuffer(GLuint client_id)571 Framebuffer* FramebufferManager::GetFramebuffer(
572     GLuint client_id) {
573   FramebufferMap::iterator it = framebuffers_.find(client_id);
574   return it != framebuffers_.end() ? it->second.get() : NULL;
575 }
576 
RemoveFramebuffer(GLuint client_id)577 void FramebufferManager::RemoveFramebuffer(GLuint client_id) {
578   FramebufferMap::iterator it = framebuffers_.find(client_id);
579   if (it != framebuffers_.end()) {
580     it->second->MarkAsDeleted();
581     framebuffers_.erase(it);
582   }
583 }
584 
AttachRenderbuffer(GLenum attachment,Renderbuffer * renderbuffer)585 void Framebuffer::AttachRenderbuffer(
586     GLenum attachment, Renderbuffer* renderbuffer) {
587   const Attachment* a = GetAttachment(attachment);
588   if (a)
589     a->DetachFromFramebuffer(this);
590   if (renderbuffer) {
591     attachments_[attachment] = scoped_refptr<Attachment>(
592         new RenderbufferAttachment(renderbuffer));
593   } else {
594     attachments_.erase(attachment);
595   }
596   framebuffer_complete_state_count_id_ = 0;
597 }
598 
AttachTexture(GLenum attachment,TextureRef * texture_ref,GLenum target,GLint level,GLsizei samples)599 void Framebuffer::AttachTexture(
600     GLenum attachment, TextureRef* texture_ref, GLenum target,
601     GLint level, GLsizei samples) {
602   const Attachment* a = GetAttachment(attachment);
603   if (a)
604     a->DetachFromFramebuffer(this);
605   if (texture_ref) {
606     attachments_[attachment] = scoped_refptr<Attachment>(
607         new TextureAttachment(texture_ref, target, level, samples));
608     texture_ref->texture()->AttachToFramebuffer();
609   } else {
610     attachments_.erase(attachment);
611   }
612   framebuffer_complete_state_count_id_ = 0;
613 }
614 
615 const Framebuffer::Attachment*
GetAttachment(GLenum attachment) const616     Framebuffer::GetAttachment(
617         GLenum attachment) const {
618   AttachmentMap::const_iterator it = attachments_.find(attachment);
619   if (it != attachments_.end()) {
620     return it->second.get();
621   }
622   return NULL;
623 }
624 
OnTextureRefDetached(TextureRef * texture)625 void Framebuffer::OnTextureRefDetached(TextureRef* texture) {
626   manager_->OnTextureRefDetached(texture);
627 }
628 
OnWillRenderTo() const629 void Framebuffer::OnWillRenderTo() const {
630   for (AttachmentMap::const_iterator it = attachments_.begin();
631        it != attachments_.end(); ++it) {
632     it->second->OnWillRenderTo();
633   }
634 }
635 
OnDidRenderTo() const636 void Framebuffer::OnDidRenderTo() const {
637   for (AttachmentMap::const_iterator it = attachments_.begin();
638        it != attachments_.end(); ++it) {
639     it->second->OnDidRenderTo();
640   }
641 }
642 
GetClientId(GLuint service_id,GLuint * client_id) const643 bool FramebufferManager::GetClientId(
644     GLuint service_id, GLuint* client_id) const {
645   // This doesn't need to be fast. It's only used during slow queries.
646   for (FramebufferMap::const_iterator it = framebuffers_.begin();
647        it != framebuffers_.end(); ++it) {
648     if (it->second->service_id() == service_id) {
649       *client_id = it->first;
650       return true;
651     }
652   }
653   return false;
654 }
655 
MarkAttachmentsAsCleared(Framebuffer * framebuffer,RenderbufferManager * renderbuffer_manager,TextureManager * texture_manager)656 void FramebufferManager::MarkAttachmentsAsCleared(
657     Framebuffer* framebuffer,
658     RenderbufferManager* renderbuffer_manager,
659     TextureManager* texture_manager) {
660   DCHECK(framebuffer);
661   framebuffer->MarkAttachmentsAsCleared(renderbuffer_manager,
662                                         texture_manager,
663                                         true);
664   MarkAsComplete(framebuffer);
665 }
666 
MarkAsComplete(Framebuffer * framebuffer)667 void FramebufferManager::MarkAsComplete(
668     Framebuffer* framebuffer) {
669   DCHECK(framebuffer);
670   framebuffer->MarkAsComplete(framebuffer_state_change_count_);
671 }
672 
IsComplete(Framebuffer * framebuffer)673 bool FramebufferManager::IsComplete(
674     Framebuffer* framebuffer) {
675   DCHECK(framebuffer);
676   return framebuffer->framebuffer_complete_state_count_id() ==
677       framebuffer_state_change_count_;
678 }
679 
OnTextureRefDetached(TextureRef * texture)680 void FramebufferManager::OnTextureRefDetached(TextureRef* texture) {
681   for (TextureDetachObserverVector::iterator it =
682            texture_detach_observers_.begin();
683        it != texture_detach_observers_.end();
684        ++it) {
685     TextureDetachObserver* observer = *it;
686     observer->OnTextureRefDetachedFromFramebuffer(texture);
687   }
688 }
689 
690 }  // namespace gles2
691 }  // namespace gpu
692 
693 
694