15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/framebuffer_manager.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/common/gles2_cmd_utils.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "gpu/command_buffer/service/renderbuffer_manager.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "gpu/command_buffer/service/texture_manager.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gpu {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gles2 {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DecoderFramebufferState::DecoderFramebufferState()
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    : clear_state_dirty(false),
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      bound_read_framebuffer(NULL),
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      bound_draw_framebuffer(NULL) {
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DecoderFramebufferState::~DecoderFramebufferState() {
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Framebuffer::FramebufferComboCompleteMap*
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Framebuffer::framebuffer_combo_complete_map_;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Framebuffer completeness is not cacheable on OS X because of dynamic
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// graphics switching.
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// http://crbug.com/180876
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_MACOSX)
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool Framebuffer::allow_framebuffer_combo_complete_map_ = false;
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#else
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool Framebuffer::allow_framebuffer_combo_complete_map_ = true;
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Framebuffer::ClearFramebufferCompleteComboMap() {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (framebuffer_combo_complete_map_) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    framebuffer_combo_complete_map_->clear();
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RenderbufferAttachment
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public Framebuffer::Attachment {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit RenderbufferAttachment(
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Renderbuffer* renderbuffer)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : renderbuffer_(renderbuffer) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual GLsizei width() const OVERRIDE {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return renderbuffer_->width();
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual GLsizei height() const OVERRIDE {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return renderbuffer_->height();
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual GLenum internal_format() const OVERRIDE {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return renderbuffer_->internal_format();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual GLenum texture_type() const OVERRIDE {
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return 0;
65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual GLsizei samples() const OVERRIDE {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return renderbuffer_->samples();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual GLuint object_name() const OVERRIDE {
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return renderbuffer_->client_id();
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool cleared() const OVERRIDE {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return renderbuffer_->cleared();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetCleared(
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RenderbufferManager* renderbuffer_manager,
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      TextureManager* /* texture_manager */,
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool cleared) OVERRIDE {
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    renderbuffer_manager->SetCleared(renderbuffer_.get(), cleared);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool IsTexture(
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      TextureRef* /* texture */) const OVERRIDE {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool IsRenderbuffer(
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       Renderbuffer* renderbuffer) const OVERRIDE {
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return renderbuffer_.get() == renderbuffer;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool CanRenderTo() const OVERRIDE {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  virtual void DetachFromFramebuffer(Framebuffer* framebuffer) const OVERRIDE {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Nothing to do for renderbuffers.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool ValidForAttachmentType(
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GLenum attachment_type, uint32 max_color_attachments) OVERRIDE {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 need = GLES2Util::GetChannelsNeededForAttachmentType(
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        attachment_type, max_color_attachments);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 have = GLES2Util::GetChannelsForFormat(internal_format());
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (need & have) != 0;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Renderbuffer* renderbuffer() const {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return renderbuffer_.get();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddToSignature(
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TextureManager* texture_manager, std::string* signature) const OVERRIDE {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(signature);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    renderbuffer_->AddToSignature(signature);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnWillRenderTo() const OVERRIDE {}
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnDidRenderTo() const OVERRIDE {}
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~RenderbufferAttachment() { }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<Renderbuffer> renderbuffer_;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(RenderbufferAttachment);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TextureAttachment
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public Framebuffer::Attachment {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TextureAttachment(
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      TextureRef* texture_ref, GLenum target, GLint level, GLsizei samples)
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      : texture_ref_(texture_ref),
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        target_(target),
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        level_(level),
1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        samples_(samples) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual GLsizei width() const OVERRIDE {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLsizei temp_width = 0;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLsizei temp_height = 0;
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    texture_ref_->texture()->GetLevelSize(
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        target_, level_, &temp_width, &temp_height);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return temp_width;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual GLsizei height() const OVERRIDE {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLsizei temp_width = 0;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLsizei temp_height = 0;
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    texture_ref_->texture()->GetLevelSize(
15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        target_, level_, &temp_width, &temp_height);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return temp_height;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual GLenum internal_format() const OVERRIDE {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLenum temp_type = 0;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLenum temp_internal_format = 0;
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    texture_ref_->texture()->GetLevelType(
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        target_, level_, &temp_type, &temp_internal_format);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return temp_internal_format;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual GLenum texture_type() const OVERRIDE {
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    GLenum temp_type = 0;
171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    GLenum temp_internal_format = 0;
172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    texture_ref_->texture()->GetLevelType(
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        target_, level_, &temp_type, &temp_internal_format);
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return temp_type;
175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual GLsizei samples() const OVERRIDE {
1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return samples_;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual GLuint object_name() const OVERRIDE {
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return texture_ref_->client_id();
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool cleared() const OVERRIDE {
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return texture_ref_->texture()->IsLevelCleared(target_, level_);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetCleared(
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RenderbufferManager* /* renderbuffer_manager */,
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      TextureManager* texture_manager,
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool cleared) OVERRIDE {
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    texture_manager->SetLevelCleared(
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        texture_ref_.get(), target_, level_, cleared);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual bool IsTexture(TextureRef* texture) const OVERRIDE {
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return texture == texture_ref_.get();
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool IsRenderbuffer(
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       Renderbuffer* /* renderbuffer */)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          const OVERRIDE {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  TextureRef* texture() const {
20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return texture_ref_.get();
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool CanRenderTo() const OVERRIDE {
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return texture_ref_->texture()->CanRenderTo();
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  virtual void DetachFromFramebuffer(Framebuffer* framebuffer)
2168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      const OVERRIDE {
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    texture_ref_->texture()->DetachFromFramebuffer();
2188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    framebuffer->OnTextureRefDetached(texture_ref_.get());
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool ValidForAttachmentType(
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GLenum attachment_type, uint32 max_color_attachments) OVERRIDE {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLenum type = 0;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLenum internal_format = 0;
22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!texture_ref_->texture()->GetLevelType(
22690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        target_, level_, &type, &internal_format)) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 need = GLES2Util::GetChannelsNeededForAttachmentType(
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        attachment_type, max_color_attachments);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 have = GLES2Util::GetChannelsForFormat(internal_format);
2323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Workaround for NVIDIA drivers that incorrectly expose these formats as
2343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // renderable:
2353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (internal_format == GL_LUMINANCE || internal_format == GL_ALPHA ||
2363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        internal_format == GL_LUMINANCE_ALPHA) {
2373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return false;
2383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (need & have) != 0;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddToSignature(
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TextureManager* texture_manager, std::string* signature) const OVERRIDE {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(signature);
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    texture_manager->AddToSignature(
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        texture_ref_.get(), target_, level_, signature);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnWillRenderTo() const OVERRIDE {
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    texture_ref_->texture()->OnWillModifyPixels();
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnDidRenderTo() const OVERRIDE {
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    texture_ref_->texture()->OnDidModifyPixels();
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~TextureAttachment() {}
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_refptr<TextureRef> texture_ref_;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLenum target_;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLint level_;
2647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  GLsizei samples_;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TextureAttachment);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)FramebufferManager::TextureDetachObserver::TextureDetachObserver() {}
2708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)FramebufferManager::TextureDetachObserver::~TextureDetachObserver() {}
2728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FramebufferManager::FramebufferManager(
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint32 max_draw_buffers, uint32 max_color_attachments)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : framebuffer_state_change_count_(1),
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      framebuffer_count_(0),
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      have_context_(true),
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      max_draw_buffers_(max_draw_buffers),
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      max_color_attachments_(max_color_attachments) {
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_GT(max_draw_buffers_, 0u);
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_GT(max_color_attachments_, 0u);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FramebufferManager::~FramebufferManager() {
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(framebuffers_.empty());
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If this triggers, that means something is keeping a reference to a
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Framebuffer belonging to this.
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK_EQ(framebuffer_count_, 0u);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Framebuffer::MarkAsDeleted() {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  deleted_ = true;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!attachments_.empty()) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Attachment* attachment = attachments_.begin()->second.get();
2958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    attachment->DetachFromFramebuffer(this);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    attachments_.erase(attachments_.begin());
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FramebufferManager::Destroy(bool have_context) {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  have_context_ = have_context;
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  framebuffers_.clear();
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FramebufferManager::StartTracking(
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Framebuffer* /* framebuffer */) {
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ++framebuffer_count_;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FramebufferManager::StopTracking(
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Framebuffer* /* framebuffer */) {
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  --framebuffer_count_;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FramebufferManager::CreateFramebuffer(
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLuint client_id, GLuint service_id) {
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::pair<FramebufferMap::iterator, bool> result =
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      framebuffers_.insert(
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          std::make_pair(
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              client_id,
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              scoped_refptr<Framebuffer>(
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  new Framebuffer(this, service_id))));
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(result.second);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Framebuffer::Framebuffer(
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FramebufferManager* manager, GLuint service_id)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : manager_(manager),
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      deleted_(false),
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service_id_(service_id),
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_been_bound_(false),
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framebuffer_complete_state_count_id_(0) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manager->StartTracking(this);
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_GT(manager->max_draw_buffers_, 0u);
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  draw_buffers_.reset(new GLenum[manager->max_draw_buffers_]);
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  draw_buffers_[0] = GL_COLOR_ATTACHMENT0;
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (uint32 i = 1; i < manager->max_draw_buffers_; ++i)
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    draw_buffers_[i] = GL_NONE;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Framebuffer::~Framebuffer() {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (manager_) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (manager_->have_context_) {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLuint id = service_id();
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      glDeleteFramebuffersEXT(1, &id);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    manager_->StopTracking(this);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    manager_ = NULL;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Framebuffer::HasUnclearedAttachment(
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLenum attachment) const {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AttachmentMap::const_iterator it =
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      attachments_.find(attachment);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != attachments_.end()) {
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const Attachment* attachment = it->second.get();
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !attachment->cleared();
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool Framebuffer::HasUnclearedColorAttachments() const {
36446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (AttachmentMap::const_iterator it = attachments_.begin();
36546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       it != attachments_.end(); ++it) {
36646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (it->first >= GL_COLOR_ATTACHMENT0 &&
36746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        it->first < GL_COLOR_ATTACHMENT0 + manager_->max_draw_buffers_) {
36846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      const Attachment* attachment = it->second.get();
36946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (!attachment->cleared())
37046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return true;
37146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
37246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
37346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return false;
37446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
37546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
37646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void Framebuffer::ChangeDrawBuffersHelper(bool recover) const {
37746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<GLenum[]> buffers(new GLenum[manager_->max_draw_buffers_]);
37846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (uint32 i = 0; i < manager_->max_draw_buffers_; ++i)
37946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    buffers[i] = GL_NONE;
38046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (AttachmentMap::const_iterator it = attachments_.begin();
38146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       it != attachments_.end(); ++it) {
38246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (it->first >= GL_COLOR_ATTACHMENT0 &&
38346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        it->first < GL_COLOR_ATTACHMENT0 + manager_->max_draw_buffers_) {
38446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      buffers[it->first - GL_COLOR_ATTACHMENT0] = it->first;
38546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
38646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
38746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bool different = false;
38846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (uint32 i = 0; i < manager_->max_draw_buffers_; ++i) {
38946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (buffers[i] != draw_buffers_[i]) {
39046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      different = true;
39146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
39246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
39346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
39446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (different) {
39546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (recover)
39646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      glDrawBuffersARB(manager_->max_draw_buffers_, draw_buffers_.get());
39746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    else
39846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      glDrawBuffersARB(manager_->max_draw_buffers_, buffers.get());
39946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
40046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
40146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
40246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void Framebuffer::PrepareDrawBuffersForClear() const {
40346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bool recover = false;
40446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ChangeDrawBuffersHelper(recover);
40546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
40646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
40746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void Framebuffer::RestoreDrawBuffersAfterClear() const {
40846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bool recover = true;
40946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ChangeDrawBuffersHelper(recover);
41046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
41146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Framebuffer::MarkAttachmentAsCleared(
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RenderbufferManager* renderbuffer_manager,
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      TextureManager* texture_manager,
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GLenum attachment,
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool cleared) {
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AttachmentMap::iterator it = attachments_.find(attachment);
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (it != attachments_.end()) {
419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    Attachment* a = it->second.get();
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (a->cleared() != cleared) {
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      a->SetCleared(renderbuffer_manager,
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    texture_manager,
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    cleared);
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Framebuffer::MarkAttachmentsAsCleared(
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RenderbufferManager* renderbuffer_manager,
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      TextureManager* texture_manager,
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool cleared) {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (AttachmentMap::iterator it = attachments_.begin();
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != attachments_.end(); ++it) {
434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    Attachment* attachment = it->second.get();
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (attachment->cleared() != cleared) {
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      attachment->SetCleared(renderbuffer_manager, texture_manager, cleared);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Framebuffer::HasDepthAttachment() const {
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return attachments_.find(GL_DEPTH_STENCIL_ATTACHMENT) != attachments_.end() ||
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         attachments_.find(GL_DEPTH_ATTACHMENT) != attachments_.end();
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Framebuffer::HasStencilAttachment() const {
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return attachments_.find(GL_DEPTH_STENCIL_ATTACHMENT) != attachments_.end() ||
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         attachments_.find(GL_STENCIL_ATTACHMENT) != attachments_.end();
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GLenum Framebuffer::GetColorAttachmentFormat() const {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AttachmentMap::const_iterator it = attachments_.find(GL_COLOR_ATTACHMENT0);
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == attachments_.end()) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const Attachment* attachment = it->second.get();
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return attachment->internal_format();
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
460a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)GLenum Framebuffer::GetColorAttachmentTextureType() const {
461a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  AttachmentMap::const_iterator it = attachments_.find(GL_COLOR_ATTACHMENT0);
462a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (it == attachments_.end()) {
463a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return 0;
464a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
465a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const Attachment* attachment = it->second.get();
466a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return attachment->texture_type();
467a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
468a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GLenum Framebuffer::IsPossiblyComplete() const {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (attachments_.empty()) {
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLsizei width = -1;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLsizei height = -1;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (AttachmentMap::const_iterator it = attachments_.begin();
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != attachments_.end(); ++it) {
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLenum attachment_type = it->first;
479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    Attachment* attachment = it->second.get();
480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!attachment->ValidForAttachmentType(attachment_type,
481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                            manager_->max_color_attachments_)) {
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (width < 0) {
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      width = attachment->width();
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      height = attachment->height();
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (width == 0 || height == 0) {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (attachment->width() != width || attachment->height() != height) {
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!attachment->CanRenderTo()) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GL_FRAMEBUFFER_UNSUPPORTED;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This does not mean the framebuffer is actually complete. It just means our
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // checks passed.
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GL_FRAMEBUFFER_COMPLETE;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GLenum Framebuffer::GetStatus(
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TextureManager* texture_manager, GLenum target) const {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if we have this combo already.
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string signature;
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (allow_framebuffer_combo_complete_map_) {
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    signature = base::StringPrintf("|FBO|target=%04x", target);
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (AttachmentMap::const_iterator it = attachments_.begin();
513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         it != attachments_.end(); ++it) {
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      Attachment* attachment = it->second.get();
515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      signature +=
516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          base::StringPrintf("|Attachment|attachmentpoint=%04x", it->first);
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      attachment->AddToSignature(texture_manager, &signature);
518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!framebuffer_combo_complete_map_) {
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      framebuffer_combo_complete_map_ = new FramebufferComboCompleteMap();
522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FramebufferComboCompleteMap::const_iterator it =
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        framebuffer_combo_complete_map_->find(signature);
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (it != framebuffer_combo_complete_map_->end()) {
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return GL_FRAMEBUFFER_COMPLETE;
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLenum result = glCheckFramebufferStatusEXT(target);
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Insert the new result into the combo map.
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (allow_framebuffer_combo_complete_map_ &&
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      result == GL_FRAMEBUFFER_COMPLETE) {
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    framebuffer_combo_complete_map_->insert(std::make_pair(signature, true));
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Framebuffer::IsCleared() const {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // are all the attachments cleaared?
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (AttachmentMap::const_iterator it = attachments_.begin();
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != attachments_.end(); ++it) {
546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    Attachment* attachment = it->second.get();
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!attachment->cleared()) {
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GLenum Framebuffer::GetDrawBuffer(GLenum draw_buffer) const {
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GLsizei index = static_cast<GLsizei>(
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      draw_buffer - GL_DRAW_BUFFER0_ARB);
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(index >= 0 &&
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        index < static_cast<GLsizei>(manager_->max_draw_buffers_));
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return draw_buffers_[index];
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Framebuffer::SetDrawBuffers(GLsizei n, const GLenum* bufs) {
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(n <= static_cast<GLsizei>(manager_->max_draw_buffers_));
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (GLsizei i = 0; i < n; ++i)
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    draw_buffers_[i] = bufs[i];
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
56846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
56946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool Framebuffer::HasAlphaMRT() const {
5717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for (uint32 i = 0; i < manager_->max_draw_buffers_; ++i) {
5727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (draw_buffers_[i] != GL_NONE) {
5737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const Attachment* attachment = GetAttachment(draw_buffers_[i]);
5747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (!attachment)
5757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        continue;
5767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if ((GLES2Util::GetChannelsForFormat(
5777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)               attachment->internal_format()) & 0x0008) != 0)
5787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return true;
5797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
5807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
5817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return false;
5827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
5837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Framebuffer::UnbindRenderbuffer(
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLenum target, Renderbuffer* renderbuffer) {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool done;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    done = true;
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (AttachmentMap::const_iterator it = attachments_.begin();
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         it != attachments_.end(); ++it) {
591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      Attachment* attachment = it->second.get();
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (attachment->IsRenderbuffer(renderbuffer)) {
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO(gman): manually detach renderbuffer.
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // glFramebufferRenderbufferEXT(target, it->first, GL_RENDERBUFFER, 0);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AttachRenderbuffer(it->first, NULL);
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        done = false;
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (!done);
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Framebuffer::UnbindTexture(
60490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    GLenum target, TextureRef* texture_ref) {
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool done;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    done = true;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (AttachmentMap::const_iterator it = attachments_.begin();
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         it != attachments_.end(); ++it) {
610868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      Attachment* attachment = it->second.get();
61190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (attachment->IsTexture(texture_ref)) {
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO(gman): manually detach texture.
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // glFramebufferTexture2DEXT(target, it->first, GL_TEXTURE_2D, 0, 0);
6147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        AttachTexture(it->first, NULL, GL_TEXTURE_2D, 0, 0);
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        done = false;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (!done);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Framebuffer* FramebufferManager::GetFramebuffer(
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLuint client_id) {
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FramebufferMap::iterator it = framebuffers_.find(client_id);
625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return it != framebuffers_.end() ? it->second.get() : NULL;
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FramebufferManager::RemoveFramebuffer(GLuint client_id) {
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FramebufferMap::iterator it = framebuffers_.find(client_id);
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (it != framebuffers_.end()) {
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it->second->MarkAsDeleted();
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    framebuffers_.erase(it);
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Framebuffer::AttachRenderbuffer(
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLenum attachment, Renderbuffer* renderbuffer) {
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const Attachment* a = GetAttachment(attachment);
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (a)
6408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    a->DetachFromFramebuffer(this);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (renderbuffer) {
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    attachments_[attachment] = scoped_refptr<Attachment>(
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new RenderbufferAttachment(renderbuffer));
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    attachments_.erase(attachment);
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  framebuffer_complete_state_count_id_ = 0;
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Framebuffer::AttachTexture(
65190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    GLenum attachment, TextureRef* texture_ref, GLenum target,
6527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    GLint level, GLsizei samples) {
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Attachment* a = GetAttachment(attachment);
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (a)
6558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    a->DetachFromFramebuffer(this);
65690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (texture_ref) {
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    attachments_[attachment] = scoped_refptr<Attachment>(
6587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        new TextureAttachment(texture_ref, target, level, samples));
65990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    texture_ref->texture()->AttachToFramebuffer();
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    attachments_.erase(attachment);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  framebuffer_complete_state_count_id_ = 0;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const Framebuffer::Attachment*
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Framebuffer::GetAttachment(
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GLenum attachment) const {
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AttachmentMap::const_iterator it = attachments_.find(attachment);
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != attachments_.end()) {
671868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return it->second.get();
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void Framebuffer::OnTextureRefDetached(TextureRef* texture) {
6778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  manager_->OnTextureRefDetached(texture);
6788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
680a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void Framebuffer::OnWillRenderTo() const {
681a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (AttachmentMap::const_iterator it = attachments_.begin();
682a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       it != attachments_.end(); ++it) {
683a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    it->second->OnWillRenderTo();
684a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
685a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
686a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
687a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void Framebuffer::OnDidRenderTo() const {
688a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (AttachmentMap::const_iterator it = attachments_.begin();
689a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       it != attachments_.end(); ++it) {
690a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    it->second->OnDidRenderTo();
691a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
692a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
693a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FramebufferManager::GetClientId(
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLuint service_id, GLuint* client_id) const {
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This doesn't need to be fast. It's only used during slow queries.
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (FramebufferMap::const_iterator it = framebuffers_.begin();
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != framebuffers_.end(); ++it) {
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->second->service_id() == service_id) {
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *client_id = it->first;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FramebufferManager::MarkAttachmentsAsCleared(
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Framebuffer* framebuffer,
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RenderbufferManager* renderbuffer_manager,
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TextureManager* texture_manager) {
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(framebuffer);
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  framebuffer->MarkAttachmentsAsCleared(renderbuffer_manager,
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        texture_manager,
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        true);
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MarkAsComplete(framebuffer);
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FramebufferManager::MarkAsComplete(
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Framebuffer* framebuffer) {
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(framebuffer);
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  framebuffer->MarkAsComplete(framebuffer_state_change_count_);
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FramebufferManager::IsComplete(
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Framebuffer* framebuffer) {
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(framebuffer);
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return framebuffer->framebuffer_complete_state_count_id() ==
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framebuffer_state_change_count_;
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void FramebufferManager::OnTextureRefDetached(TextureRef* texture) {
7320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  for (TextureDetachObserverVector::iterator it =
7330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)           texture_detach_observers_.begin();
7340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)       it != texture_detach_observers_.end();
7350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)       ++it) {
7360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    TextureDetachObserver* observer = *it;
7370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    observer->OnTextureRefDetachedFromFramebuffer(texture);
7380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
7398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
7408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gles2
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gpu
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745