blob: 333b681acd4f4b4fb324b1ae3938ddd4d29a0c1a [file] [log] [blame]
// 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<FramebufferInfoMap::iterator, bool> 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