• 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 
HasUnclearedColorAttachments() const363 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 
ChangeDrawBuffersHelper(bool recover) const376 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 
PrepareDrawBuffersForClear() const402 void Framebuffer::PrepareDrawBuffersForClear() const {
403   bool recover = false;
404   ChangeDrawBuffersHelper(recover);
405 }
406 
RestoreDrawBuffersAfterClear() const407 void Framebuffer::RestoreDrawBuffersAfterClear() const {
408   bool recover = true;
409   ChangeDrawBuffersHelper(recover);
410 }
411 
MarkAttachmentAsCleared(RenderbufferManager * renderbuffer_manager,TextureManager * texture_manager,GLenum attachment,bool cleared)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 
MarkAttachmentsAsCleared(RenderbufferManager * renderbuffer_manager,TextureManager * texture_manager,bool 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);
437     }
438   }
439 }
440 
HasDepthAttachment() const441 bool Framebuffer::HasDepthAttachment() const {
442   return attachments_.find(GL_DEPTH_STENCIL_ATTACHMENT) != attachments_.end() ||
443          attachments_.find(GL_DEPTH_ATTACHMENT) != attachments_.end();
444 }
445 
HasStencilAttachment() const446 bool Framebuffer::HasStencilAttachment() const {
447   return attachments_.find(GL_DEPTH_STENCIL_ATTACHMENT) != attachments_.end() ||
448          attachments_.find(GL_STENCIL_ATTACHMENT) != attachments_.end();
449 }
450 
GetColorAttachmentFormat() const451 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 
GetColorAttachmentTextureType() const460 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 
IsPossiblyComplete() const469 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 
GetStatus(TextureManager * texture_manager,GLenum target) const506 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 
IsCleared() const542 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 
GetDrawBuffer(GLenum draw_buffer) const554 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 
SetDrawBuffers(GLsizei n,const GLenum * bufs)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 
HasAlphaMRT() const570 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 
UnbindRenderbuffer(GLenum target,Renderbuffer * renderbuffer)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 
UnbindTexture(GLenum target,TextureRef * texture_ref)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 
GetFramebuffer(GLuint client_id)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 
RemoveFramebuffer(GLuint client_id)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 
AttachRenderbuffer(GLenum attachment,Renderbuffer * renderbuffer)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 
AttachTexture(GLenum attachment,TextureRef * texture_ref,GLenum target,GLint level,GLsizei samples)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*
GetAttachment(GLenum attachment) const667     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 
OnTextureRefDetached(TextureRef * texture)676 void Framebuffer::OnTextureRefDetached(TextureRef* texture) {
677   manager_->OnTextureRefDetached(texture);
678 }
679 
OnWillRenderTo() const680 void Framebuffer::OnWillRenderTo() const {
681   for (AttachmentMap::const_iterator it = attachments_.begin();
682        it != attachments_.end(); ++it) {
683     it->second->OnWillRenderTo();
684   }
685 }
686 
OnDidRenderTo() const687 void Framebuffer::OnDidRenderTo() const {
688   for (AttachmentMap::const_iterator it = attachments_.begin();
689        it != attachments_.end(); ++it) {
690     it->second->OnDidRenderTo();
691   }
692 }
693 
GetClientId(GLuint service_id,GLuint * client_id) const694 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 
MarkAttachmentsAsCleared(Framebuffer * framebuffer,RenderbufferManager * renderbuffer_manager,TextureManager * texture_manager)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 
MarkAsComplete(Framebuffer * framebuffer)718 void FramebufferManager::MarkAsComplete(
719     Framebuffer* framebuffer) {
720   DCHECK(framebuffer);
721   framebuffer->MarkAsComplete(framebuffer_state_change_count_);
722 }
723 
IsComplete(Framebuffer * framebuffer)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 
OnTextureRefDetached(TextureRef * texture)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