// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "gpu/command_buffer/service/framebuffer_manager.h" #include "base/logging.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" namespace gpu { namespace gles2 { class RenderbufferAttachment : public FramebufferManager::FramebufferInfo::Attachment { public: explicit RenderbufferAttachment( RenderbufferManager::RenderbufferInfo* render_buffer) : render_buffer_(render_buffer) { } virtual ~RenderbufferAttachment() { } virtual GLsizei width() const { return render_buffer_->width(); } virtual GLsizei height() const { return render_buffer_->height(); } virtual GLenum internal_format() const { return render_buffer_->internal_format(); } virtual GLsizei samples() const { return render_buffer_->samples(); } virtual bool cleared() const { return render_buffer_->cleared(); } virtual void set_cleared() { render_buffer_->set_cleared(); } RenderbufferManager::RenderbufferInfo* render_buffer() const { return render_buffer_.get(); } private: RenderbufferManager::RenderbufferInfo::Ref render_buffer_; DISALLOW_COPY_AND_ASSIGN(RenderbufferAttachment); }; class TextureAttachment : public FramebufferManager::FramebufferInfo::Attachment { public: TextureAttachment( TextureManager::TextureInfo* texture, GLenum target, GLint level) : texture_(texture), target_(target), level_(level) { } virtual ~TextureAttachment() { } virtual GLsizei width() const { GLsizei temp_width = 0; GLsizei temp_height = 0; texture_->GetLevelSize(target_, level_, &temp_width, &temp_height); return temp_width; } virtual GLsizei height() const { GLsizei temp_width = 0; GLsizei temp_height = 0; texture_->GetLevelSize(target_, level_, &temp_width, &temp_height); return temp_height; } virtual GLenum internal_format() const { GLenum temp_type = 0; GLenum temp_internal_format = 0; texture_->GetLevelType(target_, level_, &temp_type, &temp_internal_format); return temp_internal_format; } virtual GLsizei samples() const { return 0; } virtual bool cleared() const { // Textures are cleared on creation. return true; } virtual void set_cleared() { NOTREACHED(); } TextureManager::TextureInfo* texture() const { return texture_.get(); } private: TextureManager::TextureInfo::Ref texture_; GLenum target_; GLint level_; DISALLOW_COPY_AND_ASSIGN(TextureAttachment); }; FramebufferManager::FramebufferManager() {} FramebufferManager::~FramebufferManager() { DCHECK(framebuffer_infos_.empty()); } void FramebufferManager::Destroy(bool have_context) { while (!framebuffer_infos_.empty()) { if (have_context) { FramebufferInfo* info = framebuffer_infos_.begin()->second; if (!info->IsDeleted()) { GLuint service_id = info->service_id(); glDeleteFramebuffersEXT(1, &service_id); info->MarkAsDeleted(); } } framebuffer_infos_.erase(framebuffer_infos_.begin()); } } void FramebufferManager::CreateFramebufferInfo( GLuint client_id, GLuint service_id) { std::pair result = framebuffer_infos_.insert( std::make_pair( client_id, FramebufferInfo::Ref(new FramebufferInfo(service_id)))); DCHECK(result.second); } FramebufferManager::FramebufferInfo::FramebufferInfo(GLuint service_id) : service_id_(service_id) , has_been_bound_(false) { } FramebufferManager::FramebufferInfo::~FramebufferInfo() {} bool FramebufferManager::FramebufferInfo::HasUnclearedAttachment( GLenum attachment) const { AttachmentMap::const_iterator it = attachments_.find(attachment); if (it != attachments_.end()) { const Attachment* attachment = it->second; return !attachment->cleared(); } return false; } void FramebufferManager::FramebufferInfo::MarkAttachedRenderbuffersAsCleared() { for (AttachmentMap::iterator it = attachments_.begin(); it != attachments_.end(); ++it) { Attachment* attachment = it->second; if (!attachment->cleared()) { attachment->set_cleared(); } } } FramebufferManager::FramebufferInfo* FramebufferManager::GetFramebufferInfo( GLuint client_id) { FramebufferInfoMap::iterator it = framebuffer_infos_.find(client_id); return it != framebuffer_infos_.end() ? it->second : NULL; } void FramebufferManager::RemoveFramebufferInfo(GLuint client_id) { FramebufferInfoMap::iterator it = framebuffer_infos_.find(client_id); if (it != framebuffer_infos_.end()) { it->second->MarkAsDeleted(); framebuffer_infos_.erase(it); } } void FramebufferManager::FramebufferInfo::AttachRenderbuffer( GLenum attachment, RenderbufferManager::RenderbufferInfo* renderbuffer) { DCHECK(attachment == GL_COLOR_ATTACHMENT0 || attachment == GL_DEPTH_ATTACHMENT || attachment == GL_STENCIL_ATTACHMENT || attachment == GL_DEPTH_STENCIL_ATTACHMENT); if (renderbuffer) { attachments_[attachment] = Attachment::Ref( new RenderbufferAttachment(renderbuffer)); } else { attachments_.erase(attachment); } } void FramebufferManager::FramebufferInfo::AttachTexture( GLenum attachment, TextureManager::TextureInfo* texture, GLenum target, GLint level) { DCHECK(attachment == GL_COLOR_ATTACHMENT0 || attachment == GL_DEPTH_ATTACHMENT || attachment == GL_STENCIL_ATTACHMENT || attachment == GL_DEPTH_STENCIL_ATTACHMENT); if (texture) { attachments_[attachment] = Attachment::Ref( new TextureAttachment(texture, target, level)); } else { attachments_.erase(attachment); } } const FramebufferManager::FramebufferInfo::Attachment* FramebufferManager::FramebufferInfo::GetAttachment( GLenum attachment) const { AttachmentMap::const_iterator it = attachments_.find(attachment); if (it != attachments_.end()) { return it->second; } return NULL; } bool FramebufferManager::GetClientId( GLuint service_id, GLuint* client_id) const { // This doesn't need to be fast. It's only used during slow queries. for (FramebufferInfoMap::const_iterator it = framebuffer_infos_.begin(); it != framebuffer_infos_.end(); ++it) { if (it->second->service_id() == service_id) { *client_id = it->first; return true; } } return false; } } // namespace gles2 } // namespace gpu