blob: 079325807d4338b893c1f1b32e660d1f2c87ada0 [file] [log] [blame]
// Copyright (c) 2012 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/error_state_mock.h"
#include "gpu/command_buffer/service/framebuffer_manager.h"
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/renderbuffer_manager.h"
#include "gpu/command_buffer/service/test_helper.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_mock.h"
using ::testing::Return;
namespace gpu {
namespace gles2 {
namespace {
const GLint kMaxTextureSize = 64;
const GLint kMaxCubemapSize = 64;
const GLint kMaxRenderbufferSize = 64;
const GLint kMaxSamples = 4;
const bool kDepth24Supported = false;
} // namespace
class FramebufferManagerTest : public testing::Test {
public:
FramebufferManagerTest()
: manager_(1, 1),
texture_manager_(
NULL, new FeatureInfo(), kMaxTextureSize, kMaxCubemapSize),
renderbuffer_manager_(NULL, kMaxRenderbufferSize, kMaxSamples,
kDepth24Supported) {
}
virtual ~FramebufferManagerTest() {
manager_.Destroy(false);
texture_manager_.Destroy(false);
renderbuffer_manager_.Destroy(false);
}
protected:
virtual void SetUp() {
gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
::gfx::GLInterface::SetGLInterface(gl_.get());
}
virtual void TearDown() {
::gfx::GLInterface::SetGLInterface(NULL);
gl_.reset();
}
// Use StrictMock to make 100% sure we know how GL will be called.
scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
FramebufferManager manager_;
TextureManager texture_manager_;
RenderbufferManager renderbuffer_manager_;
};
TEST_F(FramebufferManagerTest, Basic) {
const GLuint kClient1Id = 1;
const GLuint kService1Id = 11;
const GLuint kClient2Id = 2;
// Check we can create framebuffer.
manager_.CreateFramebuffer(kClient1Id, kService1Id);
// Check framebuffer got created.
Framebuffer* framebuffer1 = manager_.GetFramebuffer(kClient1Id);
ASSERT_TRUE(framebuffer1 != NULL);
EXPECT_FALSE(framebuffer1->IsDeleted());
EXPECT_EQ(kService1Id, framebuffer1->service_id());
GLuint client_id = 0;
EXPECT_TRUE(manager_.GetClientId(framebuffer1->service_id(), &client_id));
EXPECT_EQ(kClient1Id, client_id);
// Check we get nothing for a non-existent framebuffer.
EXPECT_TRUE(manager_.GetFramebuffer(kClient2Id) == NULL);
// Check trying to a remove non-existent framebuffers does not crash.
manager_.RemoveFramebuffer(kClient2Id);
// Check framebuffer gets deleted when last reference is released.
EXPECT_CALL(*gl_, DeleteFramebuffersEXT(1, ::testing::Pointee(kService1Id)))
.Times(1)
.RetiresOnSaturation();
// Check we can't get the framebuffer after we remove it.
manager_.RemoveFramebuffer(kClient1Id);
EXPECT_TRUE(manager_.GetFramebuffer(kClient1Id) == NULL);
}
TEST_F(FramebufferManagerTest, Destroy) {
const GLuint kClient1Id = 1;
const GLuint kService1Id = 11;
// Check we can create framebuffer.
manager_.CreateFramebuffer(kClient1Id, kService1Id);
// Check framebuffer got created.
Framebuffer* framebuffer1 = manager_.GetFramebuffer(kClient1Id);
ASSERT_TRUE(framebuffer1 != NULL);
EXPECT_CALL(*gl_, DeleteFramebuffersEXT(1, ::testing::Pointee(kService1Id)))
.Times(1)
.RetiresOnSaturation();
manager_.Destroy(true);
// Check the resources were released.
framebuffer1 = manager_.GetFramebuffer(kClient1Id);
ASSERT_TRUE(framebuffer1 == NULL);
}
class FramebufferInfoTest : public testing::Test {
public:
static const GLuint kClient1Id = 1;
static const GLuint kService1Id = 11;
FramebufferInfoTest()
: manager_(1, 1),
texture_manager_(
NULL, new FeatureInfo(), kMaxTextureSize, kMaxCubemapSize),
renderbuffer_manager_(NULL, kMaxRenderbufferSize, kMaxSamples,
kDepth24Supported) {
}
virtual ~FramebufferInfoTest() {
manager_.Destroy(false);
texture_manager_.Destroy(false);
renderbuffer_manager_.Destroy(false);
}
protected:
virtual void SetUp() {
gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
::gfx::GLInterface::SetGLInterface(gl_.get());
manager_.CreateFramebuffer(kClient1Id, kService1Id);
error_state_.reset(new ::testing::StrictMock<gles2::MockErrorState>());
framebuffer_ = manager_.GetFramebuffer(kClient1Id);
ASSERT_TRUE(framebuffer_ != NULL);
}
virtual void TearDown() {
::gfx::GLInterface::SetGLInterface(NULL);
gl_.reset();
}
// Use StrictMock to make 100% sure we know how GL will be called.
scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
FramebufferManager manager_;
Framebuffer* framebuffer_;
TextureManager texture_manager_;
RenderbufferManager renderbuffer_manager_;
scoped_ptr<MockErrorState> error_state_;
};
// GCC requires these declarations, but MSVC requires they not be present
#ifndef COMPILER_MSVC
const GLuint FramebufferInfoTest::kClient1Id;
const GLuint FramebufferInfoTest::kService1Id;
#endif
TEST_F(FramebufferInfoTest, Basic) {
EXPECT_EQ(kService1Id, framebuffer_->service_id());
EXPECT_FALSE(framebuffer_->IsDeleted());
EXPECT_TRUE(NULL == framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0));
EXPECT_TRUE(NULL == framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT));
EXPECT_TRUE(NULL == framebuffer_->GetAttachment(GL_STENCIL_ATTACHMENT));
EXPECT_TRUE(
NULL == framebuffer_->GetAttachment(GL_DEPTH_STENCIL_ATTACHMENT));
EXPECT_FALSE(framebuffer_->HasDepthAttachment());
EXPECT_FALSE(framebuffer_->HasStencilAttachment());
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT),
framebuffer_->IsPossiblyComplete());
EXPECT_TRUE(framebuffer_->IsCleared());
EXPECT_EQ(static_cast<GLenum>(0), framebuffer_->GetColorAttachmentFormat());
EXPECT_FALSE(manager_.IsComplete(framebuffer_));
}
TEST_F(FramebufferInfoTest, AttachRenderbuffer) {
const GLuint kRenderbufferClient1Id = 33;
const GLuint kRenderbufferService1Id = 333;
const GLuint kRenderbufferClient2Id = 34;
const GLuint kRenderbufferService2Id = 334;
const GLuint kRenderbufferClient3Id = 35;
const GLuint kRenderbufferService3Id = 335;
const GLuint kRenderbufferClient4Id = 36;
const GLuint kRenderbufferService4Id = 336;
const GLsizei kWidth1 = 16;
const GLsizei kHeight1 = 32;
const GLenum kFormat1 = GL_RGBA4;
const GLenum kBadFormat1 = GL_DEPTH_COMPONENT16;
const GLsizei kSamples1 = 0;
const GLsizei kWidth2 = 16;
const GLsizei kHeight2 = 32;
const GLenum kFormat2 = GL_DEPTH_COMPONENT16;
const GLsizei kSamples2 = 0;
const GLsizei kWidth3 = 16;
const GLsizei kHeight3 = 32;
const GLenum kFormat3 = GL_STENCIL_INDEX8;
const GLsizei kSamples3 = 0;
const GLsizei kWidth4 = 16;
const GLsizei kHeight4 = 32;
const GLenum kFormat4 = GL_STENCIL_INDEX8;
const GLsizei kSamples4 = 0;
EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
EXPECT_FALSE(
framebuffer_->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT));
renderbuffer_manager_.CreateRenderbuffer(
kRenderbufferClient1Id, kRenderbufferService1Id);
Renderbuffer* renderbuffer1 =
renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient1Id);
ASSERT_TRUE(renderbuffer1 != NULL);
// check adding one attachment
framebuffer_->AttachRenderbuffer(GL_COLOR_ATTACHMENT0, renderbuffer1);
EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
EXPECT_EQ(static_cast<GLenum>(GL_RGBA4),
framebuffer_->GetColorAttachmentFormat());
EXPECT_FALSE(framebuffer_->HasDepthAttachment());
EXPECT_FALSE(framebuffer_->HasStencilAttachment());
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
framebuffer_->IsPossiblyComplete());
EXPECT_TRUE(framebuffer_->IsCleared());
// Try a format that's not good for COLOR_ATTACHMENT0.
renderbuffer_manager_.SetInfo(
renderbuffer1, kSamples1, kBadFormat1, kWidth1, kHeight1);
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
framebuffer_->IsPossiblyComplete());
// Try a good format.
renderbuffer_manager_.SetInfo(
renderbuffer1, kSamples1, kFormat1, kWidth1, kHeight1);
EXPECT_EQ(static_cast<GLenum>(kFormat1),
framebuffer_->GetColorAttachmentFormat());
EXPECT_FALSE(framebuffer_->HasDepthAttachment());
EXPECT_FALSE(framebuffer_->HasStencilAttachment());
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
framebuffer_->IsPossiblyComplete());
EXPECT_FALSE(framebuffer_->IsCleared());
// check adding another
renderbuffer_manager_.CreateRenderbuffer(
kRenderbufferClient2Id, kRenderbufferService2Id);
Renderbuffer* renderbuffer2 =
renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient2Id);
ASSERT_TRUE(renderbuffer2 != NULL);
framebuffer_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, renderbuffer2);
EXPECT_TRUE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
EXPECT_EQ(static_cast<GLenum>(kFormat1),
framebuffer_->GetColorAttachmentFormat());
EXPECT_TRUE(framebuffer_->HasDepthAttachment());
EXPECT_FALSE(framebuffer_->HasStencilAttachment());
// The attachment has a size of 0,0 so depending on the order of the map
// of attachments it could either get INCOMPLETE_ATTACHMENT because it's 0,0
// or INCOMPLETE_DIMENSIONS because it's not the same size as the other
// attachment.
GLenum status = framebuffer_->IsPossiblyComplete();
EXPECT_TRUE(
status == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT ||
status == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT);
EXPECT_FALSE(framebuffer_->IsCleared());
renderbuffer_manager_.SetInfo(
renderbuffer2, kSamples2, kFormat2, kWidth2, kHeight2);
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
framebuffer_->IsPossiblyComplete());
EXPECT_FALSE(framebuffer_->IsCleared());
EXPECT_TRUE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
// check marking them as cleared.
manager_.MarkAttachmentsAsCleared(
framebuffer_, &renderbuffer_manager_, &texture_manager_);
EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
framebuffer_->IsPossiblyComplete());
EXPECT_TRUE(framebuffer_->IsCleared());
// Check adding one that is already cleared.
renderbuffer_manager_.CreateRenderbuffer(
kRenderbufferClient3Id, kRenderbufferService3Id);
Renderbuffer* renderbuffer3 =
renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient3Id);
ASSERT_TRUE(renderbuffer3 != NULL);
renderbuffer_manager_.SetInfo(
renderbuffer3, kSamples3, kFormat3, kWidth3, kHeight3);
renderbuffer_manager_.SetCleared(renderbuffer3, true);
framebuffer_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, renderbuffer3);
EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
EXPECT_EQ(static_cast<GLenum>(kFormat1),
framebuffer_->GetColorAttachmentFormat());
EXPECT_TRUE(framebuffer_->HasDepthAttachment());
EXPECT_TRUE(framebuffer_->HasStencilAttachment());
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
framebuffer_->IsPossiblyComplete());
EXPECT_TRUE(framebuffer_->IsCleared());
// Check marking the renderbuffer as unclared.
renderbuffer_manager_.SetInfo(
renderbuffer1, kSamples1, kFormat1, kWidth1, kHeight1);
EXPECT_EQ(static_cast<GLenum>(kFormat1),
framebuffer_->GetColorAttachmentFormat());
EXPECT_TRUE(framebuffer_->HasDepthAttachment());
EXPECT_TRUE(framebuffer_->HasStencilAttachment());
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
framebuffer_->IsPossiblyComplete());
EXPECT_FALSE(framebuffer_->IsCleared());
const Framebuffer::Attachment* attachment =
framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
ASSERT_TRUE(attachment != NULL);
EXPECT_EQ(kWidth1, attachment->width());
EXPECT_EQ(kHeight1, attachment->height());
EXPECT_EQ(kSamples1, attachment->samples());
EXPECT_EQ(kFormat1, attachment->internal_format());
EXPECT_FALSE(attachment->cleared());
EXPECT_TRUE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
// Clear it.
manager_.MarkAttachmentsAsCleared(
framebuffer_, &renderbuffer_manager_, &texture_manager_);
EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
EXPECT_TRUE(framebuffer_->IsCleared());
// Check replacing an attachment
renderbuffer_manager_.CreateRenderbuffer(
kRenderbufferClient4Id, kRenderbufferService4Id);
Renderbuffer* renderbuffer4 =
renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient4Id);
ASSERT_TRUE(renderbuffer4 != NULL);
renderbuffer_manager_.SetInfo(
renderbuffer4, kSamples4, kFormat4, kWidth4, kHeight4);
framebuffer_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, renderbuffer4);
EXPECT_TRUE(framebuffer_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
EXPECT_FALSE(framebuffer_->IsCleared());
attachment = framebuffer_->GetAttachment(GL_STENCIL_ATTACHMENT);
ASSERT_TRUE(attachment != NULL);
EXPECT_EQ(kWidth4, attachment->width());
EXPECT_EQ(kHeight4, attachment->height());
EXPECT_EQ(kSamples4, attachment->samples());
EXPECT_EQ(kFormat4, attachment->internal_format());
EXPECT_FALSE(attachment->cleared());
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
framebuffer_->IsPossiblyComplete());
// Check changing an attachment.
renderbuffer_manager_.SetInfo(
renderbuffer4, kSamples4, kFormat4, kWidth4 + 1, kHeight4);
attachment = framebuffer_->GetAttachment(GL_STENCIL_ATTACHMENT);
ASSERT_TRUE(attachment != NULL);
EXPECT_EQ(kWidth4 + 1, attachment->width());
EXPECT_EQ(kHeight4, attachment->height());
EXPECT_EQ(kSamples4, attachment->samples());
EXPECT_EQ(kFormat4, attachment->internal_format());
EXPECT_FALSE(attachment->cleared());
EXPECT_FALSE(framebuffer_->IsCleared());
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT),
framebuffer_->IsPossiblyComplete());
// Check removing it.
framebuffer_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, NULL);
EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
EXPECT_EQ(static_cast<GLenum>(kFormat1),
framebuffer_->GetColorAttachmentFormat());
EXPECT_TRUE(framebuffer_->HasDepthAttachment());
EXPECT_FALSE(framebuffer_->HasStencilAttachment());
EXPECT_TRUE(framebuffer_->IsCleared());
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
framebuffer_->IsPossiblyComplete());
// Remove depth, Set color to 0 size.
framebuffer_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, NULL);
renderbuffer_manager_.SetInfo(renderbuffer1, kSamples1, kFormat1, 0, 0);
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
framebuffer_->IsPossiblyComplete());
// Remove color.
framebuffer_->AttachRenderbuffer(GL_COLOR_ATTACHMENT0, NULL);
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT),
framebuffer_->IsPossiblyComplete());
}
TEST_F(FramebufferInfoTest, AttachTexture) {
const GLuint kTextureClient1Id = 33;
const GLuint kTextureService1Id = 333;
const GLuint kTextureClient2Id = 34;
const GLuint kTextureService2Id = 334;
const GLint kDepth = 1;
const GLint kBorder = 0;
const GLenum kType = GL_UNSIGNED_BYTE;
const GLsizei kWidth1 = 16;
const GLsizei kHeight1 = 32;
const GLint kLevel1 = 0;
const GLenum kFormat1 = GL_RGBA;
const GLenum kBadFormat1 = GL_DEPTH_COMPONENT16;
const GLenum kTarget1 = GL_TEXTURE_2D;
const GLsizei kSamples1 = 0;
const GLsizei kWidth2 = 16;
const GLsizei kHeight2 = 32;
const GLint kLevel2 = 0;
const GLenum kFormat2 = GL_RGB;
const GLenum kTarget2 = GL_TEXTURE_2D;
const GLsizei kSamples2 = 0;
const GLsizei kWidth3 = 75;
const GLsizei kHeight3 = 123;
const GLint kLevel3 = 0;
const GLenum kFormat3 = GL_RGB565;
const GLsizei kSamples3 = 0;
EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
EXPECT_FALSE(
framebuffer_->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT));
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT),
framebuffer_->IsPossiblyComplete());
texture_manager_.CreateTexture(kTextureClient1Id, kTextureService1Id);
scoped_refptr<TextureRef> texture1(
texture_manager_.GetTexture(kTextureClient1Id));
ASSERT_TRUE(texture1.get() != NULL);
// check adding one attachment
framebuffer_->AttachTexture(
GL_COLOR_ATTACHMENT0, texture1.get(), kTarget1, kLevel1, kSamples1);
EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
framebuffer_->IsPossiblyComplete());
EXPECT_TRUE(framebuffer_->IsCleared());
EXPECT_EQ(static_cast<GLenum>(0), framebuffer_->GetColorAttachmentFormat());
// Try format that doesn't work with COLOR_ATTACHMENT0
texture_manager_.SetTarget(texture1.get(), GL_TEXTURE_2D);
texture_manager_.SetLevelInfo(texture1.get(),
GL_TEXTURE_2D,
kLevel1,
kBadFormat1,
kWidth1,
kHeight1,
kDepth,
kBorder,
kBadFormat1,
kType,
true);
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
framebuffer_->IsPossiblyComplete());
// Try a good format.
texture_manager_.SetLevelInfo(texture1.get(),
GL_TEXTURE_2D,
kLevel1,
kFormat1,
kWidth1,
kHeight1,
kDepth,
kBorder,
kFormat1,
kType,
false);
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
framebuffer_->IsPossiblyComplete());
EXPECT_FALSE(framebuffer_->IsCleared());
texture_manager_.SetLevelInfo(texture1.get(),
GL_TEXTURE_2D,
kLevel1,
kFormat1,
kWidth1,
kHeight1,
kDepth,
kBorder,
kFormat1,
kType,
true);
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
framebuffer_->IsPossiblyComplete());
EXPECT_TRUE(framebuffer_->IsCleared());
EXPECT_EQ(static_cast<GLenum>(kFormat1),
framebuffer_->GetColorAttachmentFormat());
const Framebuffer::Attachment* attachment =
framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
ASSERT_TRUE(attachment != NULL);
EXPECT_EQ(kWidth1, attachment->width());
EXPECT_EQ(kHeight1, attachment->height());
EXPECT_EQ(kSamples1, attachment->samples());
EXPECT_EQ(kFormat1, attachment->internal_format());
EXPECT_TRUE(attachment->cleared());
// Check replacing an attachment
texture_manager_.CreateTexture(kTextureClient2Id, kTextureService2Id);
scoped_refptr<TextureRef> texture2(
texture_manager_.GetTexture(kTextureClient2Id));
ASSERT_TRUE(texture2.get() != NULL);
texture_manager_.SetTarget(texture2.get(), GL_TEXTURE_2D);
texture_manager_.SetLevelInfo(texture2.get(),
GL_TEXTURE_2D,
kLevel2,
kFormat2,
kWidth2,
kHeight2,
kDepth,
kBorder,
kFormat2,
kType,
true);
framebuffer_->AttachTexture(
GL_COLOR_ATTACHMENT0, texture2.get(), kTarget2, kLevel2, kSamples2);
EXPECT_EQ(static_cast<GLenum>(kFormat2),
framebuffer_->GetColorAttachmentFormat());
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
framebuffer_->IsPossiblyComplete());
EXPECT_TRUE(framebuffer_->IsCleared());
attachment = framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
ASSERT_TRUE(attachment != NULL);
EXPECT_EQ(kWidth2, attachment->width());
EXPECT_EQ(kHeight2, attachment->height());
EXPECT_EQ(kSamples2, attachment->samples());
EXPECT_EQ(kFormat2, attachment->internal_format());
EXPECT_TRUE(attachment->cleared());
// Check changing attachment
texture_manager_.SetLevelInfo(texture2.get(),
GL_TEXTURE_2D,
kLevel3,
kFormat3,
kWidth3,
kHeight3,
kDepth,
kBorder,
kFormat3,
kType,
false);
attachment = framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
ASSERT_TRUE(attachment != NULL);
EXPECT_EQ(kWidth3, attachment->width());
EXPECT_EQ(kHeight3, attachment->height());
EXPECT_EQ(kSamples3, attachment->samples());
EXPECT_EQ(kFormat3, attachment->internal_format());
EXPECT_FALSE(attachment->cleared());
EXPECT_EQ(static_cast<GLenum>(kFormat3),
framebuffer_->GetColorAttachmentFormat());
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
framebuffer_->IsPossiblyComplete());
EXPECT_FALSE(framebuffer_->IsCleared());
// Set to size 0
texture_manager_.SetLevelInfo(texture2.get(),
GL_TEXTURE_2D,
kLevel3,
kFormat3,
0,
0,
kDepth,
kBorder,
kFormat3,
kType,
false);
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
framebuffer_->IsPossiblyComplete());
// Check removing it.
framebuffer_->AttachTexture(GL_COLOR_ATTACHMENT0, NULL, 0, 0, 0);
EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL);
EXPECT_EQ(static_cast<GLenum>(0), framebuffer_->GetColorAttachmentFormat());
EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT),
framebuffer_->IsPossiblyComplete());
EXPECT_TRUE(framebuffer_->IsCleared());
}
TEST_F(FramebufferInfoTest, UnbindRenderbuffer) {
const GLuint kRenderbufferClient1Id = 33;
const GLuint kRenderbufferService1Id = 333;
const GLuint kRenderbufferClient2Id = 34;
const GLuint kRenderbufferService2Id = 334;
renderbuffer_manager_.CreateRenderbuffer(
kRenderbufferClient1Id, kRenderbufferService1Id);
Renderbuffer* renderbuffer1 =
renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient1Id);
ASSERT_TRUE(renderbuffer1 != NULL);
renderbuffer_manager_.CreateRenderbuffer(
kRenderbufferClient2Id, kRenderbufferService2Id);
Renderbuffer* renderbuffer2 =
renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient2Id);
ASSERT_TRUE(renderbuffer2 != NULL);
// Attach to 2 attachment points.
framebuffer_->AttachRenderbuffer(GL_COLOR_ATTACHMENT0, renderbuffer1);
framebuffer_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, renderbuffer1);
// Check they were attached.
EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) != NULL);
EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) != NULL);
// Unbind unattached renderbuffer.
framebuffer_->UnbindRenderbuffer(GL_RENDERBUFFER, renderbuffer2);
// Should be no-op.
EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) != NULL);
EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) != NULL);
// Unbind renderbuffer.
framebuffer_->UnbindRenderbuffer(GL_RENDERBUFFER, renderbuffer1);
// Check they were detached
EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL);
EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) == NULL);
}
TEST_F(FramebufferInfoTest, UnbindTexture) {
const GLuint kTextureClient1Id = 33;
const GLuint kTextureService1Id = 333;
const GLuint kTextureClient2Id = 34;
const GLuint kTextureService2Id = 334;
const GLenum kTarget1 = GL_TEXTURE_2D;
const GLint kLevel1 = 0;
const GLint kSamples1 = 0;
texture_manager_.CreateTexture(kTextureClient1Id, kTextureService1Id);
scoped_refptr<TextureRef> texture1(
texture_manager_.GetTexture(kTextureClient1Id));
ASSERT_TRUE(texture1.get() != NULL);
texture_manager_.CreateTexture(kTextureClient2Id, kTextureService2Id);
scoped_refptr<TextureRef> texture2(
texture_manager_.GetTexture(kTextureClient2Id));
ASSERT_TRUE(texture2.get() != NULL);
// Attach to 2 attachment points.
framebuffer_->AttachTexture(
GL_COLOR_ATTACHMENT0, texture1.get(), kTarget1, kLevel1, kSamples1);
framebuffer_->AttachTexture(
GL_DEPTH_ATTACHMENT, texture1.get(), kTarget1, kLevel1, kSamples1);
// Check they were attached.
EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) != NULL);
EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) != NULL);
// Unbind unattached texture.
framebuffer_->UnbindTexture(kTarget1, texture2.get());
// Should be no-op.
EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) != NULL);
EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) != NULL);
// Unbind texture.
framebuffer_->UnbindTexture(kTarget1, texture1.get());
// Check they were detached
EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL);
EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) == NULL);
}
TEST_F(FramebufferInfoTest, IsCompleteMarkAsComplete) {
const GLuint kRenderbufferClient1Id = 33;
const GLuint kRenderbufferService1Id = 333;
const GLuint kTextureClient2Id = 34;
const GLuint kTextureService2Id = 334;
const GLenum kTarget1 = GL_TEXTURE_2D;
const GLint kLevel1 = 0;
const GLint kSamples1 = 0;
renderbuffer_manager_.CreateRenderbuffer(
kRenderbufferClient1Id, kRenderbufferService1Id);
Renderbuffer* renderbuffer1 =
renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient1Id);
ASSERT_TRUE(renderbuffer1 != NULL);
texture_manager_.CreateTexture(kTextureClient2Id, kTextureService2Id);
scoped_refptr<TextureRef> texture2(
texture_manager_.GetTexture(kTextureClient2Id));
ASSERT_TRUE(texture2.get() != NULL);
// Check MarkAsComlete marks as complete.
manager_.MarkAsComplete(framebuffer_);
EXPECT_TRUE(manager_.IsComplete(framebuffer_));
// Check at attaching marks as not complete.
framebuffer_->AttachTexture(
GL_COLOR_ATTACHMENT0, texture2.get(), kTarget1, kLevel1, kSamples1);
EXPECT_FALSE(manager_.IsComplete(framebuffer_));
manager_.MarkAsComplete(framebuffer_);
EXPECT_TRUE(manager_.IsComplete(framebuffer_));
framebuffer_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, renderbuffer1);
EXPECT_FALSE(manager_.IsComplete(framebuffer_));
// Check MarkAttachmentsAsCleared marks as complete.
manager_.MarkAttachmentsAsCleared(
framebuffer_, &renderbuffer_manager_, &texture_manager_);
EXPECT_TRUE(manager_.IsComplete(framebuffer_));
// Check Unbind marks as not complete.
framebuffer_->UnbindRenderbuffer(GL_RENDERBUFFER, renderbuffer1);
EXPECT_FALSE(manager_.IsComplete(framebuffer_));
manager_.MarkAsComplete(framebuffer_);
EXPECT_TRUE(manager_.IsComplete(framebuffer_));
framebuffer_->UnbindTexture(kTarget1, texture2.get());
EXPECT_FALSE(manager_.IsComplete(framebuffer_));
}
TEST_F(FramebufferInfoTest, GetStatus) {
const GLuint kRenderbufferClient1Id = 33;
const GLuint kRenderbufferService1Id = 333;
const GLuint kTextureClient2Id = 34;
const GLuint kTextureService2Id = 334;
const GLenum kTarget1 = GL_TEXTURE_2D;
const GLint kLevel1 = 0;
const GLint kSamples1 = 0;
renderbuffer_manager_.CreateRenderbuffer(
kRenderbufferClient1Id, kRenderbufferService1Id);
Renderbuffer* renderbuffer1 =
renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient1Id);
ASSERT_TRUE(renderbuffer1 != NULL);
texture_manager_.CreateTexture(kTextureClient2Id, kTextureService2Id);
scoped_refptr<TextureRef> texture2(
texture_manager_.GetTexture(kTextureClient2Id));
ASSERT_TRUE(texture2.get() != NULL);
texture_manager_.SetTarget(texture2.get(), GL_TEXTURE_2D);
EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
framebuffer_->GetStatus(&texture_manager_, GL_FRAMEBUFFER);
// Check a second call for the same type does not call anything
if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) {
EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
}
framebuffer_->GetStatus(&texture_manager_, GL_FRAMEBUFFER);
// Check changing the attachments calls CheckFramebufferStatus.
framebuffer_->AttachTexture(
GL_COLOR_ATTACHMENT0, texture2.get(), kTarget1, kLevel1, kSamples1);
EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)).RetiresOnSaturation();
framebuffer_->GetStatus(&texture_manager_, GL_FRAMEBUFFER);
// Check a second call for the same type does not call anything.
if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) {
EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
}
framebuffer_->GetStatus(&texture_manager_, GL_FRAMEBUFFER);
// Check a second call with a different target calls CheckFramebufferStatus.
EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER))
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER);
// Check a second call for the same type does not call anything.
if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) {
EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER))
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
}
framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER);
// Check adding another attachment calls CheckFramebufferStatus.
framebuffer_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, renderbuffer1);
EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER))
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER);
// Check a second call for the same type does not call anything.
if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) {
EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER))
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
}
framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER);
// Check changing the format calls CheckFramebuffferStatus.
TestHelper::SetTexParameterWithExpectations(gl_.get(),
error_state_.get(),
&texture_manager_,
texture2.get(),
GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE,
GL_NO_ERROR);
EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER))
.WillOnce(Return(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT))
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER);
// Check since it did not return FRAMEBUFFER_COMPLETE that it calls
// CheckFramebufferStatus
framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER);
// Check putting it back does not call CheckFramebufferStatus.
if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) {
EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER))
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
}
TestHelper::SetTexParameterWithExpectations(gl_.get(),
error_state_.get(),
&texture_manager_,
texture2.get(),
GL_TEXTURE_WRAP_S,
GL_REPEAT,
GL_NO_ERROR);
framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER);
// Check Unbinding does not call CheckFramebufferStatus
framebuffer_->UnbindRenderbuffer(GL_RENDERBUFFER, renderbuffer1);
if (!framebuffer_->AllowFramebufferComboCompleteMapForTesting()) {
EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER))
.WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
.RetiresOnSaturation();
}
framebuffer_->GetStatus(&texture_manager_, GL_READ_FRAMEBUFFER);
}
} // namespace gles2
} // namespace gpu