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