summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-06 01:12:28 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-06 01:12:28 +0000
commit3a2e7c7b5a3cfabaab0043020f2a35cde53fb0d7 (patch)
tree72416741e7d081122bf1f85954b689bd43eb84b9 /gpu
parentc87bcf000fde1dd7194b5e40e8c9f1058700dd9d (diff)
downloadchromium_src-3a2e7c7b5a3cfabaab0043020f2a35cde53fb0d7.zip
chromium_src-3a2e7c7b5a3cfabaab0043020f2a35cde53fb0d7.tar.gz
chromium_src-3a2e7c7b5a3cfabaab0043020f2a35cde53fb0d7.tar.bz2
Clear render buffers
TEST=unit tests BUG=41300 Review URL: http://codereview.chromium.org/3058043 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@55169 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py17
-rw-r--r--gpu/command_buffer/service/framebuffer_manager.cc22
-rw-r--r--gpu/command_buffer/service/framebuffer_manager.h4
-rw-r--r--gpu/command_buffer/service/framebuffer_manager_unittest.cc104
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc184
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_autogen.h18
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc275
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc18
-rw-r--r--gpu/command_buffer/service/renderbuffer_manager.h1
-rw-r--r--gpu/command_buffer/service/renderbuffer_manager_unittest.cc3
10 files changed, 629 insertions, 17 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index ef65df7..f747f7a 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -1038,7 +1038,13 @@ _FUNCTION_INFO = {
'gl_test_func': 'glCheckFramebufferStatusEXT',
'result': ['GLenum'],
},
- 'ClearDepthf': {'decoder_func': 'glClearDepth'},
+ 'ClearColor': {'decoder_func': 'DoClearColor'},
+ 'ClearDepthf': {
+ 'decoder_func': 'DoClearDepthf',
+ 'gl_test_func': 'glClearDepth',
+ },
+ 'ColorMask': {'decoder_func': 'DoColorMask'},
+ 'ClearStencil': {'decoder_func': 'DoClearStencil'},
'CommandBufferEnable': {
'type': 'Custom',
'immediate': False,
@@ -1091,7 +1097,11 @@ _FUNCTION_INFO = {
},
'DeleteTextures': {'type': 'DELn'},
'DepthRangef': {'decoder_func': 'glDepthRange'},
+ 'DepthMask': {'decoder_func': 'DoDepthMask'},
'DetachShader': {'decoder_func': 'DoDetachShader'},
+ 'Disable': {
+ 'decoder_func': 'DoDisable',
+ },
'DisableVertexAttribArray': {
'decoder_func': 'DoDisableVertexAttribArray',
'impl_decl': False,
@@ -1105,6 +1115,9 @@ _FUNCTION_INFO = {
'type': 'Manual',
'cmd_args': 'GLenum mode, GLsizei count, GLenum type, GLuint index_offset',
},
+ 'Enable': {
+ 'decoder_func': 'DoEnable',
+ },
'EnableVertexAttribArray': {
'decoder_func': 'DoEnableVertexAttribArray',
'impl_decl': False,
@@ -1376,6 +1389,8 @@ _FUNCTION_INFO = {
'cmd_args':
'GLuint shader, const char* data',
},
+ 'StencilMask': {'decoder_func': 'DoStencilMask'},
+ 'StencilMaskSeparate': {'decoder_func': 'DoStencilMaskSeparate'},
'SwapBuffers': {
'type': 'Custom',
'impl_func': False,
diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc
index 8dd036b..9b74f7f 100644
--- a/gpu/command_buffer/service/framebuffer_manager.cc
+++ b/gpu/command_buffer/service/framebuffer_manager.cc
@@ -37,6 +37,25 @@ void FramebufferManager::CreateFramebufferInfo(
DCHECK(result.second);
}
+bool FramebufferManager::FramebufferInfo::HasUnclearedAttachment(
+ GLenum attachment) const {
+ AttachmentToRenderbufferMap::const_iterator it =
+ renderbuffers_.find(attachment);
+ if (it != renderbuffers_.end()) {
+ RenderbufferManager::RenderbufferInfo* info = it->second;
+ return !info->cleared();
+ }
+ return false;
+}
+
+void FramebufferManager::FramebufferInfo::MarkAttachedRenderbuffersAsCleared() {
+ for (AttachmentToRenderbufferMap::iterator it = renderbuffers_.begin();
+ it != renderbuffers_.end(); ++it) {
+ RenderbufferManager::RenderbufferInfo* info = it->second;
+ info->set_cleared();
+ }
+}
+
FramebufferManager::FramebufferInfo* FramebufferManager::GetFramebufferInfo(
GLuint client_id) {
FramebufferInfoMap::iterator it = framebuffer_infos_.find(client_id);
@@ -55,7 +74,8 @@ void FramebufferManager::FramebufferInfo::AttachRenderbuffer(
GLenum attachment, RenderbufferManager::RenderbufferInfo* renderbuffer) {
DCHECK(attachment == GL_COLOR_ATTACHMENT0 ||
attachment == GL_DEPTH_ATTACHMENT ||
- attachment == GL_STENCIL_ATTACHMENT);
+ attachment == GL_STENCIL_ATTACHMENT ||
+ attachment == GL_DEPTH_STENCIL_ATTACHMENT);
if (renderbuffer) {
renderbuffers_[attachment] =
RenderbufferManager::RenderbufferInfo::Ref(renderbuffer);
diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h
index f437e6a..8e0ce40 100644
--- a/gpu/command_buffer/service/framebuffer_manager.h
+++ b/gpu/command_buffer/service/framebuffer_manager.h
@@ -33,11 +33,15 @@ class FramebufferManager {
return service_id_;
}
+ bool HasUnclearedAttachment(GLenum attachment) const;
+
// Attaches a renderbuffer to a particlar attachment.
// Pass null to detach.
void AttachRenderbuffer(
GLenum attachment, RenderbufferManager::RenderbufferInfo* renderbuffer);
+ void MarkAttachedRenderbuffersAsCleared();
+
bool IsDeleted() {
return service_id_ == 0;
}
diff --git a/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
index ed435c1..57fed7b 100644
--- a/gpu/command_buffer/service/framebuffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
@@ -75,7 +75,109 @@ TEST_F(FramebufferManagerTest, Destroy) {
ASSERT_TRUE(info1 == NULL);
}
-// TODO(gman): Write test for AttachRenderbuffer
+class FramebufferInfoTest : public testing::Test {
+ public:
+ static const GLuint kClient1Id = 1;
+ static const GLuint kService1Id = 11;
+
+ FramebufferInfoTest()
+ : manager_() {
+ }
+ ~FramebufferInfoTest() {
+ manager_.Destroy(false);
+ }
+
+ protected:
+ virtual void SetUp() {
+ gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
+ ::gfx::GLInterface::SetGLInterface(gl_.get());
+ manager_.CreateFramebufferInfo(kClient1Id, kService1Id);
+ info_ = manager_.GetFramebufferInfo(kClient1Id);
+ ASSERT_TRUE(info_ != 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_;
+ FramebufferManager::FramebufferInfo* info_;
+};
+
+// 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, info_->service_id());
+ EXPECT_FALSE(info_->IsDeleted());
+}
+
+TEST_F(FramebufferInfoTest, AttachRenderbuffer) {
+ const GLuint kRenderbufferClient1Id = 33;
+ const GLuint kRenderbufferService1Id = 333;
+ const GLuint kRenderbufferClient2Id = 34;
+ const GLuint kRenderbufferService2Id = 334;
+ EXPECT_FALSE(info_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
+ EXPECT_FALSE(info_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
+ EXPECT_FALSE(info_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
+ EXPECT_FALSE(info_->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT));
+
+ RenderbufferManager rb_manager;
+ rb_manager.CreateRenderbufferInfo(
+ kRenderbufferClient1Id, kRenderbufferService1Id);
+ RenderbufferManager::RenderbufferInfo* rb_info1 =
+ rb_manager.GetRenderbufferInfo(kRenderbufferClient1Id);
+ ASSERT_TRUE(rb_info1 != NULL);
+
+ // check adding one attachment
+ info_->AttachRenderbuffer(GL_COLOR_ATTACHMENT0, rb_info1);
+ EXPECT_TRUE(info_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
+ EXPECT_FALSE(info_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
+
+ // check adding another
+ info_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, rb_info1);
+ EXPECT_TRUE(info_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
+ EXPECT_TRUE(info_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
+
+ // check marking them as cleared.
+ info_->MarkAttachedRenderbuffersAsCleared();
+ EXPECT_FALSE(info_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
+ EXPECT_FALSE(info_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
+
+ // Check adding one that is already cleared.
+ info_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, rb_info1);
+ EXPECT_FALSE(info_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
+
+ // Check marking the renderbuffer as unclared.
+ rb_info1->set_internal_format(GL_RGBA);
+ EXPECT_TRUE(info_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
+
+ // Clear it.
+ info_->MarkAttachedRenderbuffersAsCleared();
+ EXPECT_FALSE(info_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
+
+ // Check replacing an attachment
+ rb_manager.CreateRenderbufferInfo(
+ kRenderbufferClient2Id, kRenderbufferService2Id);
+ RenderbufferManager::RenderbufferInfo* rb_info2 =
+ rb_manager.GetRenderbufferInfo(kRenderbufferClient2Id);
+ ASSERT_TRUE(rb_info2 != NULL);
+
+ info_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, rb_info2);
+ EXPECT_TRUE(info_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
+
+ // Check removing it.
+ info_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, NULL);
+ EXPECT_FALSE(info_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
+
+ rb_manager.Destroy(false);
+}
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index bef335d..1a00ed7 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -831,6 +831,12 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
error::Error ShaderSourceHelper(
GLuint client_id, const char* data, uint32 data_size);
+ // Clears any uncleared render buffers attached to the given frame buffer.
+ void ClearUnclearedRenderbuffers(FramebufferManager::FramebufferInfo* info);
+
+ // Remembers the state of some capabilities.
+ void SetCapabilityState(GLenum cap, bool enabled);
+
// Checks if the current program exists and is valid. If not generates the
// appropriate GL error. Returns true if the current program is in a usable
// state.
@@ -886,6 +892,17 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
// Wrapper for glCheckFramebufferStatus
GLenum DoCheckFramebufferStatus(GLenum target);
+ // Wrappers for clear and mask settings functions.
+ void DoClearColor(
+ GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+ void DoClearDepthf(GLclampf depth);
+ void DoClearStencil(GLint s);
+ void DoColorMask(
+ GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+ void DoDepthMask(GLboolean depth);
+ void DoStencilMask(GLuint mask);
+ void DoStencilMaskSeparate(GLenum face, GLuint mask);
+
// Wrapper for glCompileShader.
void DoCompileShader(GLuint shader);
@@ -898,9 +915,15 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
// Wrapper for glDrawArrays.
void DoDrawArrays(GLenum mode, GLint first, GLsizei count);
+ // Wrapper for glDisable
+ void DoDisable(GLenum cap);
+
// Wrapper for glDisableVertexAttribArray.
void DoDisableVertexAttribArray(GLuint index);
+ // Wrapper for glEnable
+ void DoEnable(GLenum cap);
+
// Wrapper for glEnableVertexAttribArray.
void DoEnableVertexAttribArray(GLuint index);
@@ -1160,6 +1183,23 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
GLuint black_2d_texture_id_;
GLuint black_cube_texture_id_;
+ // state saved for clearing so we can clear render buffers and then
+ // restore to these values.
+ GLclampf clear_red_;
+ GLclampf clear_green_;
+ GLclampf clear_blue_;
+ GLclampf clear_alpha_;
+ GLboolean mask_red_;
+ GLboolean mask_green_;
+ GLboolean mask_blue_;
+ GLboolean mask_alpha_;
+ GLint clear_stencil_;
+ GLuint mask_stencil_front_;
+ GLuint mask_stencil_back_;
+ GLclampf clear_depth_;
+ GLboolean mask_depth_;
+ bool enable_scissor_test_;
+
// The program in use by glUseProgram
ProgramManager::ProgramInfo::Ref current_program_;
@@ -1457,6 +1497,20 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
active_texture_unit_(0),
black_2d_texture_id_(0),
black_cube_texture_id_(0),
+ clear_red_(0),
+ clear_green_(0),
+ clear_blue_(0),
+ clear_alpha_(0),
+ mask_red_(true),
+ mask_green_(true),
+ mask_blue_(true),
+ mask_alpha_(true),
+ clear_stencil_(0),
+ mask_stencil_front_(-1),
+ mask_stencil_back_(-1),
+ clear_depth_(1.0f),
+ mask_depth_(true),
+ enable_scissor_test_(false),
anti_aliased_(false),
use_shader_translator_(true),
vertex_compiler_(NULL),
@@ -2741,9 +2795,9 @@ void GLES2DecoderImpl::DoFramebufferRenderbuffer(
return;
}
GLuint service_id = 0;
+ RenderbufferManager::RenderbufferInfo* info = NULL;
if (client_renderbuffer_id) {
- RenderbufferManager::RenderbufferInfo* info =
- GetRenderbufferInfo(client_renderbuffer_id);
+ info = GetRenderbufferInfo(client_renderbuffer_id);
if (!info) {
SetGLError(GL_INVALID_OPERATION,
"glFramebufferRenderbuffer: unknown renderbuffer");
@@ -2753,6 +2807,125 @@ void GLES2DecoderImpl::DoFramebufferRenderbuffer(
}
glFramebufferRenderbufferEXT(
target, attachment, renderbuffertarget, service_id);
+ if (service_id == 0 ||
+ glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
+ bound_framebuffer_->AttachRenderbuffer(attachment, info);
+ if (info) {
+ ClearUnclearedRenderbuffers(bound_framebuffer_);
+ }
+ }
+}
+
+void GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
+ switch (cap) {
+ case GL_SCISSOR_TEST:
+ enable_scissor_test_ = enabled;
+ break;
+ default:
+ break;
+ }
+}
+
+void GLES2DecoderImpl::DoDisable(GLenum cap) {
+ SetCapabilityState(cap, false);
+ glDisable(cap);
+}
+
+void GLES2DecoderImpl::DoEnable(GLenum cap) {
+ SetCapabilityState(cap, true);
+ glEnable(cap);
+}
+
+void GLES2DecoderImpl::DoClearColor(
+ GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
+ clear_red_ = red;
+ clear_green_ = green;
+ clear_blue_ = blue;
+ clear_alpha_ = alpha;
+ glClearColor(red, green, blue, alpha);
+}
+
+void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
+ clear_depth_ = depth;
+ glClearDepth(depth);
+}
+
+void GLES2DecoderImpl::DoClearStencil(GLint s) {
+ clear_stencil_ = s;
+ glClearStencil(s);
+}
+
+void GLES2DecoderImpl::DoColorMask(
+ GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
+ mask_red_ = red;
+ mask_green_ = green;
+ mask_blue_ = blue;
+ mask_alpha_ = alpha;
+ glColorMask(red, green, blue, alpha);
+}
+
+void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
+ mask_depth_ = depth;
+ glDepthMask(depth);
+}
+
+void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
+ mask_stencil_front_ = mask;
+ mask_stencil_back_ = mask;
+ glStencilMask(mask);
+}
+
+void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
+ if (face == GL_FRONT) {
+ mask_stencil_front_ = mask;
+ } else {
+ mask_stencil_back_ = mask;
+ }
+ glStencilMaskSeparate(face, mask);
+}
+
+// NOTE: There's an assumption here that Texture attachments
+// are cleared because they are textures so we only need to clear
+// the renderbuffers.
+void GLES2DecoderImpl::ClearUnclearedRenderbuffers(
+ FramebufferManager::FramebufferInfo* info) {
+ GLbitfield clear_bits = 0;
+ if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
+ glClearColor(0, 0, 0, 0);
+ glColorMask(true, true, true, true);
+ clear_bits |= GL_COLOR_BUFFER_BIT;
+ }
+
+ if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
+ info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
+ glClearStencil(0);
+ glStencilMask(-1);
+ clear_bits |= GL_STENCIL_BUFFER_BIT;
+ }
+
+ if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
+ info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
+ glClearDepth(1.0f);
+ glDepthMask(true);
+ clear_bits |= GL_DEPTH_BUFFER_BIT;
+ }
+
+ glDisable(GL_SCISSOR_TEST);
+ glClear(clear_bits);
+
+ info->MarkAttachedRenderbuffersAsCleared();
+
+ // reset clear color
+ glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
+ glColorMask(mask_red_, mask_green_, mask_blue_, mask_alpha_);
+ glClearStencil(clear_stencil_);
+ glStencilMaskSeparate(GL_FRONT, mask_stencil_front_);
+ glStencilMaskSeparate(GL_BACK, mask_stencil_back_);
+ glClearDepth(clear_depth_);
+ glDepthMask(mask_depth_);
+ if (enable_scissor_test_) {
+ glEnable(GL_SCISSOR_TEST);
+ }
}
GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
@@ -2771,8 +2944,9 @@ void GLES2DecoderImpl::DoFramebufferTexture2D(
return;
}
GLuint service_id = 0;
+ TextureManager::TextureInfo* info = NULL;
if (client_texture_id) {
- TextureManager::TextureInfo* info = GetTextureInfo(client_texture_id);
+ info = GetTextureInfo(client_texture_id);
if (!info) {
SetGLError(GL_INVALID_OPERATION,
"glFramebufferTexture2D: unknown texture");
@@ -2781,6 +2955,10 @@ void GLES2DecoderImpl::DoFramebufferTexture2D(
service_id = info->service_id();
}
glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
+ if (service_id != 0 &&
+ glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
+ ClearUnclearedRenderbuffers(bound_framebuffer_);
+ }
}
void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
index 874bd8a..0ae6355 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -231,21 +231,21 @@ error::Error GLES2DecoderImpl::HandleClearColor(
GLclampf green = static_cast<GLclampf>(c.green);
GLclampf blue = static_cast<GLclampf>(c.blue);
GLclampf alpha = static_cast<GLclampf>(c.alpha);
- glClearColor(red, green, blue, alpha);
+ DoClearColor(red, green, blue, alpha);
return error::kNoError;
}
error::Error GLES2DecoderImpl::HandleClearDepthf(
uint32 immediate_data_size, const gles2::ClearDepthf& c) {
GLclampf depth = static_cast<GLclampf>(c.depth);
- glClearDepth(depth);
+ DoClearDepthf(depth);
return error::kNoError;
}
error::Error GLES2DecoderImpl::HandleClearStencil(
uint32 immediate_data_size, const gles2::ClearStencil& c) {
GLint s = static_cast<GLint>(c.s);
- glClearStencil(s);
+ DoClearStencil(s);
return error::kNoError;
}
@@ -255,7 +255,7 @@ error::Error GLES2DecoderImpl::HandleColorMask(
GLboolean green = static_cast<GLboolean>(c.green);
GLboolean blue = static_cast<GLboolean>(c.blue);
GLboolean alpha = static_cast<GLboolean>(c.alpha);
- glColorMask(red, green, blue, alpha);
+ DoColorMask(red, green, blue, alpha);
return error::kNoError;
}
@@ -613,7 +613,7 @@ error::Error GLES2DecoderImpl::HandleDepthFunc(
error::Error GLES2DecoderImpl::HandleDepthMask(
uint32 immediate_data_size, const gles2::DepthMask& c) {
GLboolean flag = static_cast<GLboolean>(c.flag);
- glDepthMask(flag);
+ DoDepthMask(flag);
return error::kNoError;
}
@@ -640,7 +640,7 @@ error::Error GLES2DecoderImpl::HandleDisable(
SetGLError(GL_INVALID_ENUM, "glDisable: cap GL_INVALID_ENUM");
return error::kNoError;
}
- glDisable(cap);
+ DoDisable(cap);
return error::kNoError;
}
@@ -675,7 +675,7 @@ error::Error GLES2DecoderImpl::HandleEnable(
SetGLError(GL_INVALID_ENUM, "glEnable: cap GL_INVALID_ENUM");
return error::kNoError;
}
- glEnable(cap);
+ DoEnable(cap);
return error::kNoError;
}
@@ -1609,7 +1609,7 @@ error::Error GLES2DecoderImpl::HandleStencilFuncSeparate(
error::Error GLES2DecoderImpl::HandleStencilMask(
uint32 immediate_data_size, const gles2::StencilMask& c) {
GLuint mask = static_cast<GLuint>(c.mask);
- glStencilMask(mask);
+ DoStencilMask(mask);
return error::kNoError;
}
@@ -1621,7 +1621,7 @@ error::Error GLES2DecoderImpl::HandleStencilMaskSeparate(
SetGLError(GL_INVALID_ENUM, "glStencilMaskSeparate: face GL_INVALID_ENUM");
return error::kNoError;
}
- glStencilMaskSeparate(face, mask);
+ DoStencilMaskSeparate(face, mask);
return error::kNoError;
}
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index 2bb4612..4a37678 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -2285,6 +2285,281 @@ TEST_F(GLES2DecoderTest, CopyTexSubImage2DBadArgs) {
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
}
+// Check that if a renderbuffer is attached and GL returns
+// GL_FRAMEBUFFER_COMPLETE that the buffer is cleared and state is restored.
+TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearColor) {
+ DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_,
+ kServiceFramebufferId);
+ ClearColor color_cmd;
+ ColorMask color_mask_cmd;
+ Enable enable_cmd;
+ FramebufferRenderbuffer cmd;
+ color_cmd.Init(0.1f, 0.2f, 0.3f, 0.4f);
+ color_mask_cmd.Init(0, 1, 0, 1);
+ enable_cmd.Init(GL_SCISSOR_TEST);
+ cmd.Init(
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+ client_renderbuffer_id_);
+ InSequence sequence;
+ EXPECT_CALL(*gl_, ClearColor(0.1f, 0.2f, 0.3f, 0.4f))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ColorMask(0, 1, 0, 1))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, Enable(GL_SCISSOR_TEST))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, FramebufferRenderbufferEXT(
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+ kServiceRenderbufferId))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
+ .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ClearColor(0, 0, 0, 0))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ColorMask(1, 1, 1, 1))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, Disable(GL_SCISSOR_TEST))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, Clear(GL_COLOR_BUFFER_BIT))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ClearColor(0.1f, 0.2f, 0.3f, 0.4f))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ColorMask(0, 1, 0, 1))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ClearStencil(0))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, StencilMaskSeparate(GL_FRONT, static_cast<GLuint>(-1)))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, StencilMaskSeparate(GL_BACK, static_cast<GLuint>(-1)))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ClearDepth(1.0f))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, DepthMask(1))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, Enable(GL_SCISSOR_TEST))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_EQ(error::kNoError, ExecuteCmd(color_cmd));
+ EXPECT_EQ(error::kNoError, ExecuteCmd(color_mask_cmd));
+ EXPECT_EQ(error::kNoError, ExecuteCmd(enable_cmd));
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+}
+
+TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearDepth) {
+ DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_,
+ kServiceFramebufferId);
+ ClearDepthf depth_cmd;
+ DepthMask depth_mask_cmd;
+ FramebufferRenderbuffer cmd;
+ depth_cmd.Init(0.5f);
+ depth_mask_cmd.Init(false);
+ cmd.Init(
+ GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
+ client_renderbuffer_id_);
+ InSequence sequence;
+ EXPECT_CALL(*gl_, ClearDepth(0.5f))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, DepthMask(0))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, FramebufferRenderbufferEXT(
+ GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
+ kServiceRenderbufferId))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
+ .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ClearDepth(1.0f))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, DepthMask(1))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, Disable(GL_SCISSOR_TEST))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, Clear(GL_DEPTH_BUFFER_BIT))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ClearColor(0, 0, 0, 0))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ColorMask(1, 1, 1, 1))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ClearStencil(0))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, StencilMaskSeparate(GL_FRONT, static_cast<GLuint>(-1)))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, StencilMaskSeparate(GL_BACK, static_cast<GLuint>(-1)))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ClearDepth(0.5f))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, DepthMask(0))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_EQ(error::kNoError, ExecuteCmd(depth_cmd));
+ EXPECT_EQ(error::kNoError, ExecuteCmd(depth_mask_cmd));
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+}
+
+TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearStencil) {
+ DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_,
+ kServiceFramebufferId);
+ ClearStencil stencil_cmd;
+ StencilMaskSeparate stencil_mask_separate_cmd;
+ FramebufferRenderbuffer cmd;
+ stencil_cmd.Init(123);
+ stencil_mask_separate_cmd.Init(GL_BACK, 0x1234u);
+ cmd.Init(
+ GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+ client_renderbuffer_id_);
+ InSequence sequence;
+ EXPECT_CALL(*gl_, ClearStencil(123))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, StencilMaskSeparate(GL_BACK, 0x1234u))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, FramebufferRenderbufferEXT(
+ GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+ kServiceRenderbufferId))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
+ .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ClearStencil(0))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, StencilMask(static_cast<GLuint>(-1)))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, Disable(GL_SCISSOR_TEST))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, Clear(GL_STENCIL_BUFFER_BIT))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ClearColor(0, 0, 0, 0))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ColorMask(1, 1, 1, 1))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ClearStencil(123))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, StencilMaskSeparate(GL_FRONT, static_cast<GLuint>(-1)))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, StencilMaskSeparate(GL_BACK, 0x1234u))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ClearDepth(1.0f))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, DepthMask(1))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_EQ(error::kNoError, ExecuteCmd(stencil_cmd));
+ EXPECT_EQ(error::kNoError, ExecuteCmd(stencil_mask_separate_cmd));
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+}
+
+#if 0 // Turn this test on once we allow GL_DEPTH_STENCIL_ATTACHMENT
+TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearDepthStencil) {
+ DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_,
+ kServiceFramebufferId);
+ ClearDepthf depth_cmd;
+ ClearStencil stencil_cmd;
+ FramebufferRenderbuffer cmd;
+ depth_cmd.Init(0.5f);
+ stencil_cmd.Init(123);
+ cmd.Init(
+ GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+ client_renderbuffer_id_);
+ InSequence sequence;
+ EXPECT_CALL(*gl_, ClearDepth(0.5f))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ClearStencil(123))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, FramebufferRenderbufferEXT(
+ GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+ kServiceRenderbufferId))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
+ .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ClearStencil(0))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, StencilMask(static_cast<GLuint>(-1)))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ClearDepth(1.0f))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, DepthMask(1))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, Disable(GL_SCISSOR_TEST))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, Clear(GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ClearColor(0, 0, 0, 0))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ColorMask(1, 1, 1, 1))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ClearStencil(123))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, StencilMaskSeparate(GL_FRONT, static_cast<GLuint>(-1)))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, StencilMaskSeparate(GL_BACK, static_cast<GLuint>(-1)))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ClearDepth(0.5f))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, DepthMask(1))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_EQ(error::kNoError, ExecuteCmd(depth_cmd));
+ EXPECT_EQ(error::kNoError, ExecuteCmd(stencil_cmd));
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+}
+#endif
+
// TODO(gman): BufferData
// TODO(gman): BufferDataImmediate
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc
index 45f47bb..9e8e5ae 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc
@@ -72,16 +72,30 @@ void GLES2DecoderTestBase::SpecializedSetup<CopyTexSubImage2D, 0>(
template <>
void GLES2DecoderTestBase::SpecializedSetup<FramebufferRenderbuffer, 0>(
- bool /* valid */) {
+ bool valid) {
DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_,
kServiceFramebufferId);
+ if (valid) {
+ // Return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT so the code
+ // doesn't try to clear the buffer. That is tested else where.
+ EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
+ .WillOnce(Return(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT))
+ .RetiresOnSaturation();
+ }
};
template <>
void GLES2DecoderTestBase::SpecializedSetup<FramebufferTexture2D, 0>(
- bool /* valid */) {
+ bool valid) {
DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_,
kServiceFramebufferId);
+ if (valid) {
+ // Return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT so the code
+ // doesn't try to clear the buffer. That is tested else where.
+ EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
+ .WillOnce(Return(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT))
+ .RetiresOnSaturation();
+ }
};
template <>
diff --git a/gpu/command_buffer/service/renderbuffer_manager.h b/gpu/command_buffer/service/renderbuffer_manager.h
index 50b64a9..1dc16c6 100644
--- a/gpu/command_buffer/service/renderbuffer_manager.h
+++ b/gpu/command_buffer/service/renderbuffer_manager.h
@@ -48,6 +48,7 @@ class RenderbufferManager {
void set_internal_format(GLenum internalformat) {
internal_format_ = internalformat;
+ cleared_ = false;
}
bool IsDeleted() {
diff --git a/gpu/command_buffer/service/renderbuffer_manager_unittest.cc b/gpu/command_buffer/service/renderbuffer_manager_unittest.cc
index 05c51ce..04781324 100644
--- a/gpu/command_buffer/service/renderbuffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/renderbuffer_manager_unittest.cc
@@ -49,6 +49,9 @@ TEST_F(RenderbufferManagerTest, Basic) {
EXPECT_FALSE(info1->cleared());
info1->set_cleared();
EXPECT_TRUE(info1->cleared());
+ // Check if we set the format it gets marked as not cleared.
+ info1->set_internal_format(GL_RGBA);
+ EXPECT_FALSE(info1->cleared());
EXPECT_FALSE(info1->IsDeleted());
EXPECT_EQ(kService1Id, info1->service_id());
// Check we get nothing for a non-existent renderbuffer.