diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-20 23:08:46 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-20 23:08:46 +0000 |
commit | 297ca1c292e0ab41225d62bf1dfdaa581874db5c (patch) | |
tree | cf078cc80e62b0371460e28e1100741d0e20f5f9 /gpu | |
parent | 2b20c229af200a3d9ad9b8f5b53d98f2472c296f (diff) | |
download | chromium_src-297ca1c292e0ab41225d62bf1dfdaa581874db5c.zip chromium_src-297ca1c292e0ab41225d62bf1dfdaa581874db5c.tar.gz chromium_src-297ca1c292e0ab41225d62bf1dfdaa581874db5c.tar.bz2 |
Reapply Enforce-RGB patch with bugs fixed
TEST=ran layout tests
BUG=85385
TBR=apatrick@chromium.org
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@89751 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
14 files changed, 1482 insertions, 162 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 43d55a8..1cee782 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -1134,7 +1134,7 @@ _FUNCTION_INFO = { 'decoder_func': 'DoClearDepthf', 'gl_test_func': 'glClearDepth', }, - 'ColorMask': {'decoder_func': 'DoColorMask'}, + 'ColorMask': {'decoder_func': 'DoColorMask', 'expectation': False}, 'ClearStencil': {'decoder_func': 'DoClearStencil'}, 'CommandBufferEnableCHROMIUM': { 'type': 'Custom', @@ -1192,7 +1192,7 @@ _FUNCTION_INFO = { }, 'DeleteTextures': {'type': 'DELn'}, 'DepthRangef': {'decoder_func': 'glDepthRange'}, - 'DepthMask': {'decoder_func': 'DoDepthMask'}, + 'DepthMask': {'decoder_func': 'DoDepthMask', 'expectation': False}, 'DetachShader': {'decoder_func': 'DoDetachShader'}, 'Disable': { 'decoder_func': 'DoDisable', @@ -1507,8 +1507,11 @@ _FUNCTION_INFO = { 'cmd_args': 'GLuint shader, const char* data', }, - 'StencilMask': {'decoder_func': 'DoStencilMask'}, - 'StencilMaskSeparate': {'decoder_func': 'DoStencilMaskSeparate'}, + 'StencilMask': {'decoder_func': 'DoStencilMask', 'expectation': False}, + 'StencilMaskSeparate': { + 'decoder_func': 'DoStencilMaskSeparate', + 'expectation': False, + }, 'SwapBuffers': { 'type': 'Custom', 'impl_func': False, @@ -2742,7 +2745,13 @@ class GENnHandler(TypeHandler): def WriteGLES2ImplementationHeader(self, func, file): """Overrriden from TypeHandler.""" + log_code = (""" GPU_CLIENT_LOG_CODE_BLOCK({ + for (GLsizei i = 0; i < n; ++i) { + GPU_CLIENT_LOG(" " << i << ": " << %s[i]); + } + });""" % func.GetOriginalArgs()[1].name) args = { + 'log_code': log_code, 'return_type': func.return_type, 'name': func.original_name, 'typed_args': func.MakeTypedOriginalArgString(""), @@ -2752,16 +2761,11 @@ class GENnHandler(TypeHandler): } file.Write("%(return_type)s %(name)s(%(typed_args)s) {\n" % args) self.WriteClientGLCallLog(func, file) - file.Write(""" GPU_CLIENT_LOG_CODE_BLOCK({ - for (GLsizei i = 0; i < n; ++i) { - GPU_CLIENT_LOG(" " << i << ": " << %s[i]); - } - }); -""" % func.GetOriginalArgs()[1].name) for arg in func.GetOriginalArgs(): arg.WriteClientSideValidationCode(file, func) code = """ %(resource_type)s_id_handler_->MakeIds(0, %(args)s); helper_->%(name)sImmediate(%(args)s); +%(log_code)s } """ @@ -4348,6 +4352,21 @@ class Argument(object): return self +class BoolArgument(Argument): + """class for GLboolean""" + + def __init__(self, name, type): + Argument.__init__(self, name, 'GLboolean') + + def GetValidArg(self, func, offset, index): + """Gets a valid value for this argument.""" + return 'true' + + def GetValidGLArg(self, func, offset, index): + """Gets a valid GL value for this argument.""" + return 'true' + + class DataSizeArgument(Argument): """class for data_size which Bucket commands do not need.""" @@ -4412,7 +4431,7 @@ class SizeNotNegativeArgument(SizeArgument): class EnumBaseArgument(Argument): - """Base class for EnumArgument, IntArgument and BoolArgument""" + """Base class for EnumArgument, IntArgument and ValidatedBoolArgument""" def __init__(self, name, gl_type, type, gl_error): Argument.__init__(self, name, gl_type) @@ -4487,7 +4506,7 @@ class IntArgument(EnumBaseArgument): EnumBaseArgument.__init__(self, name, "GLint", type, "GL_INVALID_VALUE") -class BoolArgument(EnumBaseArgument): +class ValidatedBoolArgument(EnumBaseArgument): """A class for a GLboolean argument that can only except specific values. For example glUniformMatrix takes a GLboolean for it's transpose but it @@ -5162,6 +5181,8 @@ def CreateArg(arg_string): elif arg_parts[0].startswith('GLenum') and len(arg_parts[0]) > 6: return EnumArgument(arg_parts[-1], " ".join(arg_parts[0:-1])) elif arg_parts[0].startswith('GLboolean') and len(arg_parts[0]) > 9: + return ValidatedBoolArgument(arg_parts[-1], " ".join(arg_parts[0:-1])) + elif arg_parts[0].startswith('GLboolean'): return BoolArgument(arg_parts[-1], " ".join(arg_parts[0:-1])) elif (arg_parts[0].startswith('GLint') and len(arg_parts[0]) > 5 and not arg_parts[0].startswith('GLintptr')): diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 73df70f..0178d16 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -313,17 +313,17 @@ void FrontFace(GLenum mode) { void GenBuffers(GLsizei n, GLuint* buffers) { GPU_CLIENT_LOG("[" << this << "] glGenBuffers(" << n << ", " << static_cast<const void*>(buffers) << ")"); // NOLINT - GPU_CLIENT_LOG_CODE_BLOCK({ - for (GLsizei i = 0; i < n; ++i) { - GPU_CLIENT_LOG(" " << i << ": " << buffers[i]); - } - }); if (n < 0) { SetGLError(GL_INVALID_VALUE, "glGenBuffers: n < 0"); return; } buffer_id_handler_->MakeIds(0, n, buffers); helper_->GenBuffersImmediate(n, buffers); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (GLsizei i = 0; i < n; ++i) { + GPU_CLIENT_LOG(" " << i << ": " << buffers[i]); + } + }); } void GenerateMipmap(GLenum target) { @@ -333,47 +333,47 @@ void GenerateMipmap(GLenum target) { void GenFramebuffers(GLsizei n, GLuint* framebuffers) { GPU_CLIENT_LOG("[" << this << "] glGenFramebuffers(" << n << ", " << static_cast<const void*>(framebuffers) << ")"); // NOLINT - GPU_CLIENT_LOG_CODE_BLOCK({ - for (GLsizei i = 0; i < n; ++i) { - GPU_CLIENT_LOG(" " << i << ": " << framebuffers[i]); - } - }); if (n < 0) { SetGLError(GL_INVALID_VALUE, "glGenFramebuffers: n < 0"); return; } framebuffer_id_handler_->MakeIds(0, n, framebuffers); helper_->GenFramebuffersImmediate(n, framebuffers); -} - -void GenRenderbuffers(GLsizei n, GLuint* renderbuffers) { - GPU_CLIENT_LOG("[" << this << "] glGenRenderbuffers(" << n << ", " << static_cast<const void*>(renderbuffers) << ")"); // NOLINT GPU_CLIENT_LOG_CODE_BLOCK({ for (GLsizei i = 0; i < n; ++i) { - GPU_CLIENT_LOG(" " << i << ": " << renderbuffers[i]); + GPU_CLIENT_LOG(" " << i << ": " << framebuffers[i]); } }); +} + +void GenRenderbuffers(GLsizei n, GLuint* renderbuffers) { + GPU_CLIENT_LOG("[" << this << "] glGenRenderbuffers(" << n << ", " << static_cast<const void*>(renderbuffers) << ")"); // NOLINT if (n < 0) { SetGLError(GL_INVALID_VALUE, "glGenRenderbuffers: n < 0"); return; } renderbuffer_id_handler_->MakeIds(0, n, renderbuffers); helper_->GenRenderbuffersImmediate(n, renderbuffers); -} - -void GenTextures(GLsizei n, GLuint* textures) { - GPU_CLIENT_LOG("[" << this << "] glGenTextures(" << n << ", " << static_cast<const void*>(textures) << ")"); // NOLINT GPU_CLIENT_LOG_CODE_BLOCK({ for (GLsizei i = 0; i < n; ++i) { - GPU_CLIENT_LOG(" " << i << ": " << textures[i]); + GPU_CLIENT_LOG(" " << i << ": " << renderbuffers[i]); } }); +} + +void GenTextures(GLsizei n, GLuint* textures) { + GPU_CLIENT_LOG("[" << this << "] glGenTextures(" << n << ", " << static_cast<const void*>(textures) << ")"); // NOLINT if (n < 0) { SetGLError(GL_INVALID_VALUE, "glGenTextures: n < 0"); return; } texture_id_handler_->MakeIds(0, n, textures); helper_->GenTexturesImmediate(n, textures); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (GLsizei i = 0; i < n; ++i) { + GPU_CLIENT_LOG(" " << i << ": " << textures[i]); + } + }); } void GetActiveAttrib( diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc index a814969..308a948 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils.cc +++ b/gpu/command_buffer/common/gles2_cmd_utils.cc @@ -517,6 +517,7 @@ uint32 GLES2Util::GetChannelsForFormat(int format) { case GL_RGB8_OES: case GL_RGB565: return 0x0007; + case GL_BGRA_EXT: case GL_RGBA: case GL_RGBA8_OES: case GL_RGBA4: diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc index 190a910..316bc32 100644 --- a/gpu/command_buffer/service/framebuffer_manager.cc +++ b/gpu/command_buffer/service/framebuffer_manager.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -43,6 +43,10 @@ class RenderbufferAttachment render_buffer_->set_cleared(); } + virtual bool IsTexture(TextureManager::TextureInfo* /* texture */) const { + return false; + } + RenderbufferManager::RenderbufferInfo* render_buffer() const { return render_buffer_.get(); } @@ -99,6 +103,10 @@ class TextureAttachment NOTREACHED(); } + virtual bool IsTexture(TextureManager::TextureInfo* texture) const { + return texture == texture_.get(); + } + TextureManager::TextureInfo* texture() const { return texture_.get(); } @@ -169,6 +177,25 @@ void FramebufferManager::FramebufferInfo::MarkAttachedRenderbuffersAsCleared() { } } +bool FramebufferManager::FramebufferInfo::HasDepthAttachment() const { + return attachments_.find(GL_DEPTH_STENCIL_ATTACHMENT) != attachments_.end() || + attachments_.find(GL_DEPTH_ATTACHMENT) != attachments_.end(); +} + +bool FramebufferManager::FramebufferInfo::HasStencilAttachment() const { + return attachments_.find(GL_DEPTH_STENCIL_ATTACHMENT) != attachments_.end() || + attachments_.find(GL_STENCIL_ATTACHMENT) != attachments_.end(); +} + +GLenum FramebufferManager::FramebufferInfo::GetColorAttachmentFormat() const { + AttachmentMap::const_iterator it = attachments_.find(GL_COLOR_ATTACHMENT0); + if (it == attachments_.end()) { + return 0; + } + const Attachment* attachment = it->second; + return attachment->internal_format(); +} + bool FramebufferManager::FramebufferInfo::IsNotComplete() const { for (AttachmentMap::const_iterator it = attachments_.begin(); it != attachments_.end(); ++it) { @@ -215,9 +242,14 @@ void FramebufferManager::FramebufferInfo::AttachTexture( attachment == GL_DEPTH_ATTACHMENT || attachment == GL_STENCIL_ATTACHMENT || attachment == GL_DEPTH_STENCIL_ATTACHMENT); + const Attachment* a = GetAttachment(attachment); + if (a && a->IsTexture(texture)) { + texture->DetachFromFramebuffer(); + } if (texture) { attachments_[attachment] = Attachment::Ref( new TextureAttachment(texture, target, level)); + texture->AttachToFramebuffer(); } else { attachments_.erase(attachment); } diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h index 362e0b8..0641c35 100644 --- a/gpu/command_buffer/service/framebuffer_manager.h +++ b/gpu/command_buffer/service/framebuffer_manager.h @@ -36,6 +36,7 @@ class FramebufferManager { virtual GLsizei samples() const = 0; virtual bool cleared() const = 0; virtual void set_cleared() = 0; + virtual bool IsTexture(TextureManager::TextureInfo* texture) const = 0; }; explicit FramebufferInfo(GLuint service_id); @@ -72,8 +73,12 @@ class FramebufferManager { return has_been_bound_ && !IsDeleted(); } + bool HasDepthAttachment() const; + bool HasStencilAttachment() const; + GLenum GetColorAttachmentFormat() const; + // We can't know if the frame buffer is complete since that is - // implementation dependent and we'd have to check after every glTexImage + // implementation dependent and we'd have to check after every glTexImage // call but we can know in certain cases that it's NOT complete which we // need to enforce the OpenGL ES 2.0 spec on top of DesktopGL. bool IsNotComplete() const; diff --git a/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/gpu/command_buffer/service/framebuffer_manager_unittest.cc index d3c3879..77c6622 100644 --- a/gpu/command_buffer/service/framebuffer_manager_unittest.cc +++ b/gpu/command_buffer/service/framebuffer_manager_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -122,6 +122,9 @@ TEST_F(FramebufferInfoTest, Basic) { EXPECT_TRUE(NULL == info_->GetAttachment(GL_DEPTH_ATTACHMENT)); EXPECT_TRUE(NULL == info_->GetAttachment(GL_STENCIL_ATTACHMENT)); EXPECT_TRUE(NULL == info_->GetAttachment(GL_DEPTH_STENCIL_ATTACHMENT)); + EXPECT_FALSE(info_->HasDepthAttachment()); + EXPECT_FALSE(info_->HasStencilAttachment()); + EXPECT_EQ(static_cast<GLenum>(0), info_->GetColorAttachmentFormat()); } TEST_F(FramebufferInfoTest, AttachRenderbuffer) { @@ -161,12 +164,23 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { EXPECT_TRUE(info_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)); EXPECT_FALSE(info_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT)); EXPECT_TRUE(info_->IsNotComplete()); + EXPECT_EQ(static_cast<GLenum>(GL_RGBA4), info_->GetColorAttachmentFormat()); + EXPECT_FALSE(info_->HasDepthAttachment()); + EXPECT_FALSE(info_->HasStencilAttachment()); + + rb_info1->SetInfo(1, GL_RGB, 0, 0); + EXPECT_EQ(static_cast<GLenum>(GL_RGB), info_->GetColorAttachmentFormat()); + EXPECT_FALSE(info_->HasDepthAttachment()); + EXPECT_FALSE(info_->HasStencilAttachment()); // check adding another info_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, rb_info1); EXPECT_TRUE(info_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)); EXPECT_TRUE(info_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT)); EXPECT_TRUE(info_->IsNotComplete()); + EXPECT_EQ(static_cast<GLenum>(GL_RGB), info_->GetColorAttachmentFormat()); + EXPECT_TRUE(info_->HasDepthAttachment()); + EXPECT_FALSE(info_->HasStencilAttachment()); // check marking them as cleared. info_->MarkAttachedRenderbuffersAsCleared(); @@ -177,10 +191,16 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { // Check adding one that is already cleared. info_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, rb_info1); EXPECT_FALSE(info_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT)); + EXPECT_EQ(static_cast<GLenum>(GL_RGB), info_->GetColorAttachmentFormat()); + EXPECT_TRUE(info_->HasDepthAttachment()); + EXPECT_TRUE(info_->HasStencilAttachment()); // Check marking the renderbuffer as unclared. rb_info1->SetInfo(kSamples1, kFormat1, kWidth1, kHeight1); EXPECT_FALSE(info_->IsNotComplete()); + EXPECT_EQ(static_cast<GLenum>(kFormat1), info_->GetColorAttachmentFormat()); + EXPECT_TRUE(info_->HasDepthAttachment()); + EXPECT_TRUE(info_->HasStencilAttachment()); const FramebufferManager::FramebufferInfo::Attachment* attachment = info_->GetAttachment(GL_COLOR_ATTACHMENT0); @@ -230,6 +250,9 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { // Check removing it. info_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, NULL); EXPECT_FALSE(info_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT)); + EXPECT_EQ(static_cast<GLenum>(kFormat1), info_->GetColorAttachmentFormat()); + EXPECT_TRUE(info_->HasDepthAttachment()); + EXPECT_FALSE(info_->HasStencilAttachment()); rb_manager.Destroy(false); } @@ -278,12 +301,14 @@ TEST_F(FramebufferInfoTest, AttachTexture) { info_->AttachTexture(GL_COLOR_ATTACHMENT0, tex_info1, kTarget1, kLevel1); EXPECT_FALSE(info_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)); EXPECT_TRUE(info_->IsNotComplete()); + EXPECT_EQ(static_cast<GLenum>(0), info_->GetColorAttachmentFormat()); tex_manager.SetInfoTarget(tex_info1, GL_TEXTURE_2D); tex_manager.SetLevelInfo( &feature_info, tex_info1, GL_TEXTURE_2D, kLevel1, kFormat1, kWidth1, kHeight1, kDepth, kBorder, kFormat1, kType); EXPECT_FALSE(info_->IsNotComplete()); + EXPECT_EQ(static_cast<GLenum>(kFormat1), info_->GetColorAttachmentFormat()); const FramebufferManager::FramebufferInfo::Attachment* attachment = info_->GetAttachment(GL_COLOR_ATTACHMENT0); @@ -306,6 +331,7 @@ TEST_F(FramebufferInfoTest, AttachTexture) { kFormat2, kWidth2, kHeight2, kDepth, kBorder, kFormat2, kType); info_->AttachTexture(GL_COLOR_ATTACHMENT0, tex_info2, kTarget2, kLevel2); + EXPECT_EQ(static_cast<GLenum>(kFormat2), info_->GetColorAttachmentFormat()); attachment = info_->GetAttachment(GL_COLOR_ATTACHMENT0); ASSERT_TRUE(attachment != NULL); @@ -326,10 +352,12 @@ TEST_F(FramebufferInfoTest, AttachTexture) { EXPECT_EQ(kSamples3, attachment->samples()); EXPECT_EQ(kFormat3, attachment->internal_format()); EXPECT_TRUE(attachment->cleared()); + EXPECT_EQ(static_cast<GLenum>(kFormat3), info_->GetColorAttachmentFormat()); // Check removing it. info_->AttachTexture(GL_COLOR_ATTACHMENT0, NULL, 0, 0); EXPECT_TRUE(info_->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL); + EXPECT_EQ(static_cast<GLenum>(0), info_->GetColorAttachmentFormat()); tex_manager.Destroy(false); } diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 3207c70..97a46a4 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -126,7 +126,7 @@ static bool IsAngle() { #endif } -void WrappedTexImage2D( +static void WrappedTexImage2D( GLenum target, GLint level, GLenum internal_format, @@ -159,6 +159,15 @@ void WrappedTexImage2D( pixels); } +// Wrapper for glEnable/glDisable that doesn't suck. +static void EnableDisable(GLenum pname, bool enable) { + if (enable) { + glEnable(pname); + } else { + glDisable(pname); + } +} + // This class prevents any GL errors that occur when it is in scope from // being reported to the client. class ScopedGLErrorSuppressor { @@ -735,6 +744,15 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, void RestoreCurrentRenderbufferBindings(); void RestoreCurrentTexture2DBindings(); + // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer. + void ApplyDirtyState(); + + // These check the state of the currently bound framebuffer or the + // backbuffer if no framebuffer is bound. + bool BoundFramebufferHasColorAttachmentWithAlpha(); + bool BoundFramebufferHasDepthAttachment(); + bool BoundFramebufferHasStencilAttachment(); + private: friend class ScopedGLErrorSuppressor; friend class ScopedResolvedFrameBufferBinder; @@ -824,6 +842,7 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // Get the format of the currently bound frame buffer (either FBO or regular // back buffer) GLenum GetBoundReadFrameBufferInternalFormat(); + GLenum GetBoundDrawFrameBufferInternalFormat(); // Wrapper for CompressedTexImage2D commands. error::Error DoCompressedTexImage2D( @@ -1032,7 +1051,8 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, void RestoreClearState(); // Remembers the state of some capabilities. - void SetCapabilityState(GLenum cap, bool enabled); + // Returns: true if glEnable/glDisable should actually be called. + bool SetCapabilityState(GLenum cap, bool enabled); // Check that the current frame buffer is complete. Generates error if not. bool CheckFramebufferComplete(const char* func_name); @@ -1259,8 +1279,8 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // Wrapper for glValidateProgram. void DoValidateProgram(GLuint program_client_id); - void DoCopyTextureToParentTextureCHROMIUM(GLuint client_texture_id, - GLuint parent_client_texture_id); + void DoCopyTextureToParentTextureCHROMIUM( + GLuint client_texture_id, GLuint parent_client_texture_id); void DoResizeCHROMIUM(GLuint width, GLuint height); @@ -1462,6 +1482,9 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, GLclampf clear_depth_; GLboolean mask_depth_; bool enable_scissor_test_; + bool enable_depth_test_; + bool enable_stencil_test_; + bool state_dirty_; // The program in use by glUseProgram ProgramManager::ProgramInfo::Ref current_program_; @@ -1501,6 +1524,8 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // The format of the back buffer_ GLenum back_buffer_color_format_; + bool back_buffer_has_depth_; + bool back_buffer_has_stencil_; bool teximage2d_faster_than_texsubimage2d_; bool bufferdata_faster_than_buffersubdata_; @@ -1844,6 +1869,9 @@ GLES2DecoderImpl::GLES2DecoderImpl(SurfaceManager* surface_manager, clear_depth_(1.0f), mask_depth_(true), enable_scissor_test_(false), + enable_depth_test_(false), + enable_stencil_test_(false), + state_dirty_(true), offscreen_target_color_format_(0), offscreen_target_depth_format_(0), offscreen_target_stencil_format_(0), @@ -1851,6 +1879,8 @@ GLES2DecoderImpl::GLES2DecoderImpl(SurfaceManager* surface_manager, copy_texture_to_parent_texture_fb_(0), offscreen_saved_color_format_(0), back_buffer_color_format_(0), + back_buffer_has_depth_(false), + back_buffer_has_stencil_(false), teximage2d_faster_than_texsubimage2d_(true), bufferdata_faster_than_buffersubdata_(true), current_decoder_error_(error::kNoError), @@ -1923,10 +1953,6 @@ bool GLES2DecoderImpl::Initialize( vertex_attrib_manager_.Initialize(group_->max_vertex_attribs()); - GLint v = 0; - glGetIntegerv(GL_ALPHA_BITS, &v); - back_buffer_color_format_ = v ? GL_RGBA : GL_RGB; - if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) { // We have to enable vertex array 0 on OpenGL or it won't render. Note that // OpenGL ES 2.0 does not have this issue. @@ -1954,11 +1980,30 @@ bool GLES2DecoderImpl::Initialize( glActiveTexture(GL_TEXTURE0); CHECK_GL_ERROR(); - if (surface_->IsOffscreen()) { - ContextCreationAttribParser attrib_parser; - if (!attrib_parser.Parse(attribs)) - return false; + ContextCreationAttribParser attrib_parser; + if (!attrib_parser.Parse(attribs)) + return false; + + // These are NOT if the back buffer has these proprorties. They are + // if we want the command buffer to enforce them regardless of what + // the real backbuffer is assuming the real back buffer gives us more than + // we ask for. In other words, if we ask for RGB and we get RGBA then we'll + // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we + // can't do anything about that. + GLint v = 0; + glGetIntegerv(GL_ALPHA_BITS, &v); + // This checks if the user requested RGBA and we have RGBA then RGBA. If the + // user requested RGB then RGB. If the user did not specify a preference than + // use whatever we were given. Same for DEPTH and STENCIL. + back_buffer_color_format_ = + (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB; + glGetIntegerv(GL_DEPTH_BITS, &v); + back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0; + glGetIntegerv(GL_STENCIL_BITS, &v); + back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0; + + if (surface_->IsOffscreen()) { if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 && (context_->HasExtension("GL_EXT_framebuffer_multisample") || context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) { @@ -2217,6 +2262,10 @@ void GLES2DecoderImpl::DeleteFramebuffersHelper( FramebufferManager::FramebufferInfo* info = GetFramebufferInfo(client_ids[ii]); if (info) { + if (info == bound_draw_framebuffer_) { + bound_draw_framebuffer_ = NULL; + state_dirty_ = true; + } GLuint service_id = info->service_id(); glDeleteFramebuffersEXT(1, &service_id); RemoveFramebufferInfo(client_ids[ii]); @@ -2230,6 +2279,7 @@ void GLES2DecoderImpl::DeleteRenderbuffersHelper( RenderbufferManager::RenderbufferInfo* info = GetRenderbufferInfo(client_ids[ii]); if (info) { + state_dirty_ = true; GLuint service_id = info->service_id(); glDeleteRenderbuffersEXT(1, &service_id); RemoveRenderbufferInfo(client_ids[ii]); @@ -2242,6 +2292,9 @@ void GLES2DecoderImpl::DeleteTexturesHelper( for (GLsizei ii = 0; ii < n; ++ii) { TextureManager::TextureInfo* info = GetTextureInfo(client_ids[ii]); if (info) { + if (info->IsAttachedToFramebuffer()) { + state_dirty_ = true; + } GLuint service_id = info->service_id(); glDeleteTextures(1, &service_id); RemoveTextureInfo(client_ids[ii]); @@ -2266,13 +2319,17 @@ static void RebindCurrentFramebuffer( FramebufferManager::FramebufferInfo* info, FrameBuffer* offscreen_frame_buffer) { GLuint framebuffer_id = info ? info->service_id() : 0; + if (framebuffer_id == 0 && offscreen_frame_buffer) { framebuffer_id = offscreen_frame_buffer->id(); } + glBindFramebufferEXT(target, framebuffer_id); } void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() { + state_dirty_ = true; + if (!feature_info_->feature_flags().chromium_framebuffer_multisample) { RebindCurrentFramebuffer( GL_FRAMEBUFFER, @@ -2329,12 +2386,17 @@ gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() { GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() { if (bound_read_framebuffer_ != 0) { - const FramebufferManager::FramebufferInfo::Attachment* attachment = - bound_read_framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0); - if (attachment) { - return attachment->internal_format(); - } - return 0; + return bound_read_framebuffer_->GetColorAttachmentFormat(); + } else if (offscreen_target_frame_buffer_.get()) { + return offscreen_target_color_format_; + } else { + return back_buffer_color_format_; + } +} + +GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() { + if (bound_draw_framebuffer_ != 0) { + return bound_draw_framebuffer_->GetColorAttachmentFormat(); } else if (offscreen_target_frame_buffer_.get()) { return offscreen_target_color_format_; } else { @@ -2426,11 +2488,12 @@ bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() { // Clear the target frame buffer. { ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id()); - glClearColor(0, 0, 0, 0); + glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat( + offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClearStencil(0); - glStencilMaskSeparate(GL_FRONT, GL_TRUE); - glStencilMaskSeparate(GL_BACK, GL_TRUE); + glStencilMaskSeparate(GL_FRONT, -1); + glStencilMaskSeparate(GL_BACK, -1); glClearDepth(0); glDepthMask(GL_TRUE); glDisable(GL_SCISSOR_TEST); @@ -2834,6 +2897,48 @@ void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) { glBindBuffer(target, service_id); } +bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() { + return (GLES2Util::GetChannelsForFormat( + GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0; +} + +bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() { + if (bound_draw_framebuffer_) { + return bound_draw_framebuffer_->HasDepthAttachment(); + } + if (offscreen_target_frame_buffer_.get()) { + return offscreen_target_depth_format_ != 0; + } + return back_buffer_has_depth_; +} + +bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() { + if (bound_draw_framebuffer_) { + return bound_draw_framebuffer_->HasStencilAttachment(); + } + if (offscreen_target_frame_buffer_.get()) { + return offscreen_target_stencil_format_ != 0 || + offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8; + } + return back_buffer_has_stencil_; +} + +void GLES2DecoderImpl::ApplyDirtyState() { + if (state_dirty_) { + glColorMask( + mask_red_, mask_green_, mask_blue_, + mask_alpha_ && BoundFramebufferHasColorAttachmentWithAlpha()); + bool have_depth = BoundFramebufferHasDepthAttachment(); + glDepthMask(mask_depth_ && have_depth); + EnableDisable(GL_DEPTH_TEST, enable_depth_test_ && have_depth); + bool have_stencil = BoundFramebufferHasStencilAttachment(); + glStencilMaskSeparate(GL_FRONT, have_stencil ? mask_stencil_front_ : 0); + glStencilMaskSeparate(GL_BACK, have_stencil ? mask_stencil_back_ : 0); + EnableDisable(GL_STENCIL_TEST, enable_stencil_test_ && have_stencil); + state_dirty_ = false; + } +} + void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) { FramebufferManager::FramebufferInfo* info = NULL; GLuint service_id = 0; @@ -2862,10 +2967,13 @@ void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) { bound_read_framebuffer_ = info; } + state_dirty_ = true; + // When rendering to an offscreen frame buffer, instead of unbinding from // the current frame buffer, bind to the offscreen target frame buffer. - if (info == NULL && offscreen_target_frame_buffer_.get()) + if (info == NULL && offscreen_target_frame_buffer_.get()) { service_id = offscreen_target_frame_buffer_->id(); + } glBindFramebufferEXT(target, service_id); } @@ -3019,6 +3127,69 @@ bool GLES2DecoderImpl::GetHelper( } } switch (pname) { + case GL_COLOR_WRITEMASK: + *num_written = 4; + if (params) { + params[0] = mask_red_; + params[1] = mask_green_; + params[2] = mask_blue_; + params[3] = mask_alpha_; + } + return true; + case GL_DEPTH_WRITEMASK: + *num_written = 1; + if (params) { + params[0] = mask_depth_; + } + return true; + case GL_STENCIL_BACK_WRITEMASK: + *num_written = 1; + if (params) { + params[0] = mask_stencil_back_; + } + return true; + case GL_STENCIL_WRITEMASK: + *num_written = 1; + if (params) { + params[0] = mask_stencil_front_; + } + return true; + case GL_DEPTH_TEST: + *num_written = 1; + if (params) { + params[0] = enable_depth_test_; + } + return true; + case GL_STENCIL_TEST: + *num_written = 1; + if (params) { + params[0] = enable_stencil_test_; + } + return true; + case GL_ALPHA_BITS: + *num_written = 1; + if (params) { + GLint v = 0; + glGetIntegerv(GL_ALPHA_BITS, &v); + params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0; + } + return true; + case GL_DEPTH_BITS: + *num_written = 1; + if (params) { + GLint v = 0; + glGetIntegerv(GL_DEPTH_BITS, &v); + params[0] = BoundFramebufferHasDepthAttachment() ? v : 0; + } + return true; + case GL_STENCIL_BITS: + *num_written = 1; + if (params) { + GLint v = 0; + glGetIntegerv(GL_STENCIL_BITS, &v); + params[0] = BoundFramebufferHasStencilAttachment() ? v : 0; + } + return true; case GL_COMPRESSED_TEXTURE_FORMATS: *num_written = 0; // We don't support compressed textures. @@ -3410,6 +3581,7 @@ error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM( void GLES2DecoderImpl::DoClear(GLbitfield mask) { if (CheckFramebufferComplete("glClear")) { + ApplyDirtyState(); glClear(mask); } } @@ -3436,6 +3608,7 @@ void GLES2DecoderImpl::DoDrawArrays( bool simulated_fixed_attribs = false; if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) { bool textures_set = SetBlackTextureForNonRenderableTextures(); + ApplyDirtyState(); glDrawArrays(mode, first, count); if (textures_set) { RestoreStateForNonRenderableTextures(); @@ -3484,26 +3657,44 @@ void GLES2DecoderImpl::DoFramebufferRenderbuffer( } } } + if (framebuffer_info == bound_draw_framebuffer_) { + state_dirty_ = true; + } } -void GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) { +bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) { switch (cap) { case GL_SCISSOR_TEST: enable_scissor_test_ = enabled; - break; + return true; + case GL_DEPTH_TEST: { + if (enable_depth_test_ != enabled) { + enable_depth_test_ = enabled; + state_dirty_ = true; + } + return false; + } + case GL_STENCIL_TEST: + if (enable_stencil_test_ != enabled) { + enable_stencil_test_ = enabled; + state_dirty_ = true; + } + return false; default: - break; + return true; } } void GLES2DecoderImpl::DoDisable(GLenum cap) { - SetCapabilityState(cap, false); - glDisable(cap); + if (SetCapabilityState(cap, false)) { + glDisable(cap); + } } void GLES2DecoderImpl::DoEnable(GLenum cap) { - SetCapabilityState(cap, true); - glEnable(cap); + if (SetCapabilityState(cap, true)) { + glEnable(cap); + } } void GLES2DecoderImpl::DoClearColor( @@ -3531,27 +3722,28 @@ void GLES2DecoderImpl::DoColorMask( mask_green_ = green; mask_blue_ = blue; mask_alpha_ = alpha; - glColorMask(red, green, blue, alpha); + state_dirty_ = true; } void GLES2DecoderImpl::DoDepthMask(GLboolean depth) { mask_depth_ = depth; - glDepthMask(depth); + state_dirty_ = true; } void GLES2DecoderImpl::DoStencilMask(GLuint mask) { mask_stencil_front_ = mask; mask_stencil_back_ = mask; - glStencilMask(mask); + state_dirty_ = true; } void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) { - if (face == GL_FRONT) { + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { mask_stencil_front_ = mask; - } else { + } + if (face == GL_BACK || face == GL_FRONT_AND_BACK) { mask_stencil_back_ = mask; } - glStencilMaskSeparate(face, mask); + state_dirty_ = true; } // NOTE: There's an assumption here that Texture attachments @@ -3564,7 +3756,10 @@ void GLES2DecoderImpl::ClearUnclearedRenderbuffers( } GLbitfield clear_bits = 0; if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) { - glClearColor(0, 0, 0, 0); + glClearColor( + 0, 0, 0, + (GLES2Util::GetChannelsForFormat( + info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0 : 1); glColorMask(true, true, true, true); clear_bits |= GL_COLOR_BUFFER_BIT; } @@ -3596,13 +3791,10 @@ void GLES2DecoderImpl::ClearUnclearedRenderbuffers( } void GLES2DecoderImpl::RestoreClearState() { + state_dirty_ = true; 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); } @@ -3648,6 +3840,9 @@ void GLES2DecoderImpl::DoFramebufferTexture2D( ClearUnclearedRenderbuffers(target, framebuffer_info); } } + if (framebuffer_info == bound_draw_framebuffer_) { + state_dirty_ = true; + } } void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv( @@ -4444,6 +4639,7 @@ error::Error GLES2DecoderImpl::HandleDrawElements( bool simulated_fixed_attribs = false; if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) { bool textures_set = SetBlackTextureForNonRenderableTextures(); + ApplyDirtyState(); const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset); glDrawElements(mode, count, type, indices); if (textures_set) { @@ -5152,6 +5348,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels( } switch (format) { case GL_RGBA: + case GL_BGRA_EXT: case GL_ALPHA: { int offset = (format == GL_ALPHA) ? 0 : 3; int step = (format == GL_ALPHA) ? 1 : 4; @@ -5660,6 +5857,10 @@ error::Error GLES2DecoderImpl::DoTexImage2D( pixels = zero.get(); } + if (info->IsAttachedToFramebuffer()) { + state_dirty_ = true; + } + if (!teximage2d_faster_than_texsubimage2d_) { GLsizei tex_width = 0; GLsizei tex_height = 0; @@ -5840,6 +6041,10 @@ void GLES2DecoderImpl::DoCopyTexImage2D( ScopedResolvedFrameBufferBinder binder(this, false); gfx::Size size = GetBoundReadFrameBufferSize(); + if (info->IsAttachedToFramebuffer()) { + state_dirty_ = true; + } + // Clip to size to source dimensions GLint copyX = 0; GLint copyY = 0; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc index d50bb6d..82d99e8 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -18,6 +18,10 @@ #include "ui/gfx/gl/gl_implementation.h" #include "ui/gfx/gl/gl_surface_stub.h" +#if !defined(GL_DEPTH24_STENCIL8) +#define GL_DEPTH24_STENCIL8 0x88F0 +#endif + using ::gfx::MockGLInterface; using ::testing::_; using ::testing::DoAll; @@ -45,15 +49,6 @@ class GLES2DecoderTest : public GLES2DecoderTestBase { bool init); }; -class GLES2DecoderRGBBackbufferTest : public GLES2DecoderTest { - public: - GLES2DecoderRGBBackbufferTest() { } - - virtual void SetUp() { - InitDecoder("", false); - } -}; - class GLES2DecoderWithShaderTest : public GLES2DecoderWithShaderTestBase { public: GLES2DecoderWithShaderTest() @@ -89,9 +84,36 @@ class GLES2DecoderWithShaderTest : public GLES2DecoderWithShaderTestBase { } }; +class GLES2DecoderRGBBackbufferTest : public GLES2DecoderWithShaderTest { + public: + GLES2DecoderRGBBackbufferTest() { } + + virtual void SetUp() { + InitDecoder( + "", // extensions + false, // has alpha + false, // has depth + false, // has stencil + false, // request alpha + false, // request depth + false); // request stencil + SetupDefaultProgram(); + } +}; + +class GLES2DecoderManualInitTest : public GLES2DecoderWithShaderTest { + public: + GLES2DecoderManualInitTest() { } + + // Override default setup so nothing gets setup. + virtual void SetUp() { + } +}; + TEST_F(GLES2DecoderWithShaderTest, DrawArraysNoAttributesSucceeds) { SetupTexture(); AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDefaultDirtyState(); EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) .Times(1) @@ -131,6 +153,7 @@ TEST_F(GLES2DecoderWithShaderTest, DrawArraysBadTextureUsesBlack) { .Times(1) .RetiresOnSaturation(); } + SetupExpectationsForApplyingDefaultDirtyState(); DrawArrays cmd; cmd.Init(GL_TRIANGLES, 0, kNumVertices); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); @@ -163,8 +186,10 @@ TEST_F(GLES2DecoderWithShaderTest, TEST_F(GLES2DecoderWithShaderTest, DrawArraysValidAttributesSucceeds) { SetupTexture(); SetupVertexBuffer(); + DoEnableVertexAttribArray(1); DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); AddExpectationsForSimulatedAttrib0(kNumVertices, kServiceBufferId); + SetupExpectationsForApplyingDefaultDirtyState(); EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) .Times(1) @@ -191,6 +216,7 @@ TEST_F(GLES2DecoderWithShaderTest, DrawArraysDeletedBufferFails) { TEST_F(GLES2DecoderWithShaderTest, DrawArraysDeletedProgramSucceeds) { SetupTexture(); AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDefaultDirtyState(); DoDeleteProgram(client_program_id_, kServiceProgramId); EXPECT_CALL(*gl_, DrawArrays(_, _, _)) @@ -259,6 +285,7 @@ TEST_F(GLES2DecoderWithShaderTest, DrawElementsNoAttributesSucceeds) { SetupTexture(); SetupIndexBuffer(); AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, 0); + SetupExpectationsForApplyingDefaultDirtyState(); EXPECT_CALL(*gl_, DrawElements(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, BufferOffset(kValidIndexRangeStart * 2))) @@ -317,6 +344,7 @@ TEST_F(GLES2DecoderWithShaderTest, DrawElementsValidAttributesSucceeds) { SetupIndexBuffer(); DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, kServiceBufferId); + SetupExpectationsForApplyingDefaultDirtyState(); EXPECT_CALL(*gl_, DrawElements(GL_TRIANGLES, kValidIndexRangeCount, GL_UNSIGNED_SHORT, @@ -349,6 +377,7 @@ TEST_F(GLES2DecoderWithShaderTest, DrawElementsDeletedProgramSucceeds) { SetupTexture(); SetupIndexBuffer(); AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, 0); + SetupExpectationsForApplyingDefaultDirtyState(); DoDeleteProgram(client_program_id_, kServiceProgramId); EXPECT_CALL(*gl_, DrawElements(_, _, _, _)) @@ -1245,13 +1274,29 @@ TEST_F(GLES2DecoderTest, CheckFramebufferStatusWithNoBoundTarget) { EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), *result); } +TEST_F(GLES2DecoderWithShaderTest, BindAndDeleteFramebuffer) { + SetupTexture(); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDefaultDirtyState(); + DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, + kServiceFramebufferId); + DoDeleteFramebuffer(client_framebuffer_id_, kServiceFramebufferId); + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + TEST_F(GLES2DecoderTest, FramebufferRenderbufferWithNoBoundTarget) { EXPECT_CALL(*gl_, FramebufferRenderbufferEXT(_, _, _, _)) .Times(0); FramebufferRenderbuffer cmd; cmd.Init( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - client_renderbuffer_id_); + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, + client_renderbuffer_id_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); } @@ -1300,12 +1345,8 @@ TEST_F(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithRenderbuffer) { SetupExpectationsForFramebufferAttachment( GL_COLOR_BUFFER_BIT, // clear bits 0, 0, 0, 0, // color - 0x1111, // color bits 0, // stencil - -1, // stencil mask back, - -1, // stencil mask front, 1.0f, // depth - 1, // depth mask false); // scissor test EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -1360,12 +1401,8 @@ TEST_F(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithTexture) { SetupExpectationsForFramebufferAttachment( 0, // clear bits 0, 0, 0, 0, // color - 0x1111, // color bits 0, // stencil - -1, // stencil mask back, - -1, // stencil mask front, 1.0f, // depth - 1, // depth mask false); // scissor test EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -1542,12 +1579,8 @@ void GLES2DecoderTest::CheckReadPixelsOutOfRange( SetupExpectationsForFramebufferAttachment( 0, // clear bits 0, 0, 0, 0, // color - 0x1111, // color bits 0, // stencil - -1, // stencil mask back, - -1, // stencil mask front, 1.0f, // depth - 1, // depth mask false); // scissor test FramebufferTexture2D fbtex_cmd; fbtex_cmd.Init( @@ -2529,9 +2562,9 @@ TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearColor) { 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_, ColorMask(0, 1, 0, 1)) +// .Times(0) +// .RetiresOnSaturation(); EXPECT_CALL(*gl_, Enable(GL_SCISSOR_TEST)) .Times(1) .RetiresOnSaturation(); @@ -2549,12 +2582,8 @@ TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearColor) { SetupExpectationsForFramebufferAttachment( GL_COLOR_BUFFER_BIT, // clear bits 0.1f, 0.2f, 0.3f, 0.4f, // color - 0x0101, // color bits 0, // stencil - -1, // stencil mask back - -1, // stencil mask front 1.0f, // depth - 1, // depth mask true); // scissor test EXPECT_EQ(error::kNoError, ExecuteCmd(color_cmd)); EXPECT_EQ(error::kNoError, ExecuteCmd(color_mask_cmd)); @@ -2577,9 +2606,9 @@ TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearDepth) { EXPECT_CALL(*gl_, ClearDepth(0.5f)) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, DepthMask(0)) - .Times(1) - .RetiresOnSaturation(); +// EXPECT_CALL(*gl_, DepthMask(0)) +// .Times(1) +// .RetiresOnSaturation(); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) .RetiresOnSaturation(); @@ -2594,12 +2623,8 @@ TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearDepth) { SetupExpectationsForFramebufferAttachment( GL_DEPTH_BUFFER_BIT, // clear bits 0, 0, 0, 0, // color - 0x1111, // color bits 0, // stencil - -1, // stencil mask back, - -1, // stencil mask front, 0.5f, // depth - 0, // depth mask false); // scissor test EXPECT_EQ(error::kNoError, ExecuteCmd(depth_cmd)); EXPECT_EQ(error::kNoError, ExecuteCmd(depth_mask_cmd)); @@ -2621,9 +2646,9 @@ TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearStencil) { EXPECT_CALL(*gl_, ClearStencil(123)) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, StencilMaskSeparate(GL_BACK, 0x1234u)) - .Times(1) - .RetiresOnSaturation(); +// EXPECT_CALL(*gl_, StencilMaskSeparate(GL_BACK, 0x1234u)) +// .Times(1) +// .RetiresOnSaturation(); EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) .RetiresOnSaturation(); @@ -2638,12 +2663,8 @@ TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearStencil) { SetupExpectationsForFramebufferAttachment( GL_STENCIL_BUFFER_BIT, // clear bits 0, 0, 0, 0, // color - 0x1111, // color bits 123, // stencil - -1, // stencil mask back, - 0x1234u, // stencil mask front, 1.0f, // depth - 1, // depth mask false); // scissor test EXPECT_EQ(error::kNoError, ExecuteCmd(stencil_cmd)); EXPECT_EQ(error::kNoError, ExecuteCmd(stencil_mask_separate_cmd)); @@ -2725,12 +2746,8 @@ TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearDepthStencil) { SetupExpectationsForFramebufferAttachment( GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, // clear bits 0, 0, 0, 0, // color - 0x1111, // color bits 123, // stencil - -1, // stencil mask back, - -1, // stencil mask front, 0.5f, // depth - 1, // depth mask false); // scissor test EXPECT_EQ(error::kNoError, ExecuteCmd(depth_cmd)); EXPECT_EQ(error::kNoError, ExecuteCmd(stencil_cmd)); @@ -2974,6 +2991,897 @@ TEST_F(GLES2DecoderTest, EXPECT_EQ(surface.get(), decoder_->GetGLSurface()); } +// Test that with an RGB backbuffer if we set the color mask to 1,1,1,1 it is +// set to 1,1,1,0 at Draw time but is 1,1,1,1 at query time. +TEST_F(GLES2DecoderRGBBackbufferTest, RGBBackbufferColorMask) { + ColorMask cmd; + cmd.Init(true, true, true, true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + SetupTexture(); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDirtyState( + true, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1110, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays draw_cmd; + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_COLOR_WRITEMASK, result->GetData())) + .Times(0); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_COLOR_WRITEMASK, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_COLOR_WRITEMASK), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(1, result->GetData()[0]); + EXPECT_EQ(1, result->GetData()[1]); + EXPECT_EQ(1, result->GetData()[2]); + EXPECT_EQ(1, result->GetData()[3]); +} + +// Test that with no depth if we set DepthMask true that it's set to false at +// draw time but querying it returns true. +TEST_F(GLES2DecoderRGBBackbufferTest, RGBBackbufferDepthMask) { + EXPECT_CALL(*gl_, DepthMask(true)) + .Times(0) + .RetiresOnSaturation(); + DepthMask cmd; + cmd.Init(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + SetupTexture(); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDirtyState( + true, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1110, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays draw_cmd; + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_WRITEMASK, result->GetData())) + .Times(0); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_DEPTH_WRITEMASK, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_WRITEMASK), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(1, result->GetData()[0]); +} + +// Test that with no stencil if we set the stencil mask it's still set to 0 at +// draw time but gets our value if we query. +TEST_F(GLES2DecoderRGBBackbufferTest, RGBBackbufferStencilMask) { + const GLint kMask = 123; + EXPECT_CALL(*gl_, StencilMask(kMask)) + .Times(0) + .RetiresOnSaturation(); + StencilMask cmd; + cmd.Init(kMask); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + SetupTexture(); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDirtyState( + true, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1110, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays draw_cmd; + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_WRITEMASK, result->GetData())) + .Times(0); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_STENCIL_WRITEMASK, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_WRITEMASK), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(kMask, result->GetData()[0]); +} + +// Test that if an FBO is bound we get the correct masks. +TEST_F(GLES2DecoderRGBBackbufferTest, RGBBackbufferColorMaskFBO) { + ColorMask cmd; + cmd.Init(true, true, true, true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + SetupTexture(); + SetupVertexBuffer(); + DoEnableVertexAttribArray(0); + DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0); + DoEnableVertexAttribArray(1); + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); + DoEnableVertexAttribArray(2); + DoVertexAttribPointer(2, 2, GL_FLOAT, 0, 0); + SetupExpectationsForApplyingDirtyState( + true, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1110, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays draw_cmd; + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Check that no extra calls are made on the next draw. + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Setup Frame buffer. + DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, + kServiceFramebufferId); + EXPECT_CALL(*gl_, FramebufferRenderbufferEXT(_, _, _, _)) + .Times(0); + FramebufferRenderbuffer fbrb_cmd; + fbrb_cmd.Init( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, + client_renderbuffer_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + + // This time state needs to be set. + SetupExpectationsForApplyingDirtyState( + false, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1110, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Check that no extra calls are made on the next draw. + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + // Unbind + DoBindFramebuffer(GL_FRAMEBUFFER, 0, 0); + + SetupExpectationsForApplyingDirtyState( + true, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1110, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_F(GLES2DecoderManualInitTest, ActualAlphaMatchesRequestedAlpha) { + InitDecoder( + "", // extensions + true, // has alpha + false, // has depth + false, // has stencil + true, // request alpha + false, // request depth + false); // request stencil + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_ALPHA_BITS, _)) + .WillOnce(SetArgumentPointee<1>(8)) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_ALPHA_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_ALPHA_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(8, result->GetData()[0]); +} + +TEST_F(GLES2DecoderManualInitTest, ActualAlphaDoesNotMatchRequestedAlpha) { + InitDecoder( + "", // extensions + true, // has alpha + false, // has depth + false, // has stencil + false, // request alpha + false, // request depth + false); // request stencil + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_ALPHA_BITS, _)) + .WillOnce(SetArgumentPointee<1>(8)) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_ALPHA_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_ALPHA_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(0, result->GetData()[0]); +} + +TEST_F(GLES2DecoderManualInitTest, ActualDepthMatchesRequestedDepth) { + InitDecoder( + "", // extensions + false, // has alpha + true, // has depth + false, // has stencil + false, // request alpha + true, // request depth + false); // request stencil + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) + .WillOnce(SetArgumentPointee<1>(24)) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(24, result->GetData()[0]); +} + +TEST_F(GLES2DecoderManualInitTest, ActualDepthDoesNotMatchRequestedDepth) { + InitDecoder( + "", // extensions + false, // has alpha + true, // has depth + false, // has stencil + false, // request alpha + false, // request depth + false); // request stencil + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) + .WillOnce(SetArgumentPointee<1>(24)) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(0, result->GetData()[0]); +} + +TEST_F(GLES2DecoderManualInitTest, ActualStencilMatchesRequestedStencil) { + InitDecoder( + "", // extensions + false, // has alpha + false, // has depth + true, // has stencil + false, // request alpha + false, // request depth + true); // request stencil + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) + .WillOnce(SetArgumentPointee<1>(8)) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(8, result->GetData()[0]); +} + +TEST_F(GLES2DecoderManualInitTest, ActualStencilDoesNotMatchRequestedStencil) { + InitDecoder( + "", // extensions + false, // has alpha + false, // has depth + true, // has stencil + false, // request alpha + false, // request depth + false); // request stencil + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) + .WillOnce(SetArgumentPointee<1>(8)) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(0, result->GetData()[0]); +} + +TEST_F(GLES2DecoderManualInitTest, DepthEnableWithDepth) { + InitDecoder( + "", // extensions + false, // has alpha + true, // has depth + false, // has stencil + false, // request alpha + true, // request depth + false); // request stencil + + Enable cmd; + cmd.Init(GL_DEPTH_TEST); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + SetupDefaultProgram(); + SetupTexture(); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDirtyState( + true, // Framebuffer is RGB + true, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1110, // color bits + true, // depth mask + true, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays draw_cmd; + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_TEST, _)) + .Times(0) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_DEPTH_TEST, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_TEST), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(1, result->GetData()[0]); +} + +TEST_F(GLES2DecoderManualInitTest, DepthEnableWithoutRequestedDepth) { + InitDecoder( + "", // extensions + false, // has alpha + true, // has depth + false, // has stencil + false, // request alpha + false, // request depth + false); // request stencil + + Enable cmd; + cmd.Init(GL_DEPTH_TEST); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + SetupDefaultProgram(); + SetupTexture(); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDirtyState( + true, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1110, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays draw_cmd; + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_TEST, _)) + .Times(0) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_DEPTH_TEST, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_TEST), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(1, result->GetData()[0]); +} + +TEST_F(GLES2DecoderManualInitTest, StencilEnableWithStencil) { + InitDecoder( + "", // extensions + false, // has alpha + false, // has depth + true, // has stencil + false, // request alpha + false, // request depth + true); // request stencil + + Enable cmd; + cmd.Init(GL_STENCIL_TEST); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + SetupDefaultProgram(); + SetupTexture(); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDirtyState( + true, // Framebuffer is RGB + false, // Framebuffer has depth + true, // Framebuffer has stencil + 0x1110, // color bits + false, // depth mask + false, // depth enabled + -1, // front stencil mask + -1, // back stencil mask + true); // stencil enabled + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays draw_cmd; + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_TEST, _)) + .Times(0) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_STENCIL_TEST, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_TEST), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(1, result->GetData()[0]); +} + +TEST_F(GLES2DecoderManualInitTest, StencilEnableWithoutRequestedStencil) { + InitDecoder( + "", // extensions + false, // has alpha + false, // has depth + true, // has stencil + false, // request alpha + false, // request depth + false); // request stencil + + Enable cmd; + cmd.Init(GL_STENCIL_TEST); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + SetupDefaultProgram(); + SetupTexture(); + AddExpectationsForSimulatedAttrib0(kNumVertices, 0); + SetupExpectationsForApplyingDirtyState( + true, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1110, // color bits + false, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays draw_cmd; + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices); + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_TEST, _)) + .Times(0) + .RetiresOnSaturation(); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_STENCIL_TEST, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_TEST), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(1, result->GetData()[0]); +} + +TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilReportsCorrectValues) { + InitDecoder( + "GL_OES_packed_depth_stencil", // extensions + false, // has alpha + true, // has depth + true, // has stencil + false, // request alpha + true, // request depth + true); // request stencil + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) + .WillOnce(SetArgumentPointee<1>(8)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(8, result->GetData()[0]); + result->size = 0; + cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) + .WillOnce(SetArgumentPointee<1>(24)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(24, result->GetData()[0]); +} + +TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilNoRequestedStencil) { + InitDecoder( + "GL_OES_packed_depth_stencil", // extensions + false, // has alpha + true, // has depth + true, // has stencil + false, // request alpha + true, // request depth + false); // request stencil + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) + .WillOnce(SetArgumentPointee<1>(8)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(0, result->GetData()[0]); + result->size = 0; + cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) + .WillOnce(SetArgumentPointee<1>(24)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(24, result->GetData()[0]); +} + +TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilRenderbufferDepth) { + InitDecoder( + "GL_OES_packed_depth_stencil", // extensions + false, // has alpha + false, // has depth + false, // has stencil + false, // request alpha + false, // request depth + false); // request stencil + DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, + kServiceRenderbufferId); + DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, + kServiceFramebufferId); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) // for RenderbufferStoage + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) // for FramebufferRenderbuffer + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) // for GetIntegerv + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) // for GetIntegerv + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + + EXPECT_CALL(*gl_, RenderbufferStorageEXT( + GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 100, 50)) + .Times(1) + .RetiresOnSaturation(); + RenderbufferStorage cmd; + cmd.Init(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 100, 50); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_CALL(*gl_, FramebufferRenderbufferEXT( + GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, + kServiceRenderbufferId)) + .Times(1) + .RetiresOnSaturation(); + SetupExpectationsForFramebufferAttachment( + GL_DEPTH_BUFFER_BIT, // clear bits + 0, 0, 0, 0, // color + 0, // stencil + 1.0f, // depth + false); // scissor test + FramebufferRenderbuffer fbrb_cmd; + fbrb_cmd.Init( + GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, + client_renderbuffer_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(fbrb_cmd)); + + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) + .WillOnce(SetArgumentPointee<1>(8)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(0, result->GetData()[0]); + result->size = 0; + cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) + .WillOnce(SetArgumentPointee<1>(24)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(24, result->GetData()[0]); +} + +TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilRenderbufferStencil) { + InitDecoder( + "GL_OES_packed_depth_stencil", // extensions + false, // has alpha + false, // has depth + false, // has stencil + false, // request alpha + false, // request depth + false); // request stencil + DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, + kServiceRenderbufferId); + DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, + kServiceFramebufferId); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) // for RenderbufferStoage + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) // for FramebufferRenderbuffer + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) // for GetIntegerv + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) // for GetIntegerv + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + + EXPECT_CALL(*gl_, RenderbufferStorageEXT( + GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 100, 50)) + .Times(1) + .RetiresOnSaturation(); + RenderbufferStorage cmd; + cmd.Init(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 100, 50); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_CALL(*gl_, FramebufferRenderbufferEXT( + GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, + kServiceRenderbufferId)) + .Times(1) + .RetiresOnSaturation(); + SetupExpectationsForFramebufferAttachment( + GL_STENCIL_BUFFER_BIT, // clear bits + 0, 0, 0, 0, // color + 0, // stencil + 1.0f, // depth + false); // scissor test + FramebufferRenderbuffer fbrb_cmd; + fbrb_cmd.Init( + GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, + client_renderbuffer_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(fbrb_cmd)); + + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->size = 0; + GetIntegerv cmd2; + cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) + .WillOnce(SetArgumentPointee<1>(8)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(8, result->GetData()[0]); + result->size = 0; + cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) + .WillOnce(SetArgumentPointee<1>(24)) + .RetiresOnSaturation(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(0, result->GetData()[0]); +} // TODO(gman): BufferData 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 9497dbc..dc086f3 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc @@ -59,6 +59,22 @@ void GLES2DecoderTestBase::SpecializedSetup<CheckFramebufferStatus, 0>( }; template <> +void GLES2DecoderTestBase::SpecializedSetup<Clear, 0>(bool valid) { + if (valid) { + SetupExpectationsForApplyingDefaultDirtyState(); + } +}; + +template <> +void GLES2DecoderTestBase::SpecializedSetup<ColorMask, 0>( + bool /* valid */) { + // We bind a framebuffer color the colormask test since the framebuffer + // will be considered RGB. + DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, + kServiceFramebufferId); +}; + +template <> void GLES2DecoderTestBase::SpecializedSetup<CopyTexImage2D, 0>( bool valid) { if (valid) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h index 477c3bf..58f5a86 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h @@ -326,10 +326,9 @@ TEST_F(GLES2DecoderTest1, ClearStencilValidArgs) { } TEST_F(GLES2DecoderTest1, ColorMaskValidArgs) { - EXPECT_CALL(*gl_, ColorMask(1, 2, 3, 4)); SpecializedSetup<ColorMask, 0>(true); ColorMask cmd; - cmd.Init(1, 2, 3, 4); + cmd.Init(true, true, true, true); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } @@ -642,10 +641,9 @@ TEST_F(GLES2DecoderTest1, DepthFuncValidArgs) { } TEST_F(GLES2DecoderTest1, DepthMaskValidArgs) { - EXPECT_CALL(*gl_, DepthMask(1)); SpecializedSetup<DepthMask, 0>(true); DepthMask cmd; - cmd.Init(1); + cmd.Init(true); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h index 5d7375b..8f93103 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h @@ -282,10 +282,10 @@ TEST_F(GLES2DecoderTest2, RenderbufferStorageInvalidArgs3_0) { } TEST_F(GLES2DecoderTest2, SampleCoverageValidArgs) { - EXPECT_CALL(*gl_, SampleCoverage(1, 2)); + EXPECT_CALL(*gl_, SampleCoverage(1, true)); SpecializedSetup<SampleCoverage, 0>(true); SampleCoverage cmd; - cmd.Init(1, 2); + cmd.Init(1, true); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } @@ -343,7 +343,6 @@ TEST_F(GLES2DecoderTest2, StencilFuncSeparateValidArgs) { } TEST_F(GLES2DecoderTest2, StencilMaskValidArgs) { - EXPECT_CALL(*gl_, StencilMask(1)); SpecializedSetup<StencilMask, 0>(true); StencilMask cmd; cmd.Init(1); @@ -352,7 +351,6 @@ TEST_F(GLES2DecoderTest2, StencilMaskValidArgs) { } TEST_F(GLES2DecoderTest2, StencilMaskSeparateValidArgs) { - EXPECT_CALL(*gl_, StencilMaskSeparate(GL_FRONT, 2)); SpecializedSetup<StencilMaskSeparate, 0>(true); StencilMaskSeparate cmd; cmd.Init(GL_FRONT, 2); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index 0f20e67..dd6e181 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -48,11 +48,24 @@ GLES2DecoderTestBase::GLES2DecoderTestBase() GLES2DecoderTestBase::~GLES2DecoderTestBase() {} void GLES2DecoderTestBase::SetUp() { - InitDecoder("", true); + InitDecoder( + "", // extensions + true, // has alpha + true, // has depth + false, // has stencil + true, // request alpha + true, // request depth + false); // request stencil } void GLES2DecoderTestBase::InitDecoder( - const char* extensions, bool has_alpha_backbuffer) { + const char* extensions, + bool has_alpha, + bool has_depth, + bool has_stencil, + bool request_alpha, + bool request_depth, + bool request_stencil) { gl_.reset(new StrictMock<MockGLInterface>()); ::gfx::GLInterface::SetGLInterface(gl_.get()); surface_manager_.reset(new StrictMock<MockSurfaceManager>); @@ -65,9 +78,6 @@ void GLES2DecoderTestBase::InitDecoder( EXPECT_TRUE(group_->Initialize(DisallowedExtensions(), extensions)); - EXPECT_CALL(*gl_, GetIntegerv(GL_ALPHA_BITS, _)) - .WillOnce(SetArgumentPointee<1>(has_alpha_backbuffer ? 8 : 0)) - .RetiresOnSaturation(); EXPECT_CALL(*gl_, EnableVertexAttribArray(0)) .Times(1) .RetiresOnSaturation(); @@ -113,6 +123,16 @@ void GLES2DecoderTestBase::InitDecoder( .Times(1) .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetIntegerv(GL_ALPHA_BITS, _)) + .WillOnce(SetArgumentPointee<1>(has_alpha ? 8 : 0)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) + .WillOnce(SetArgumentPointee<1>(has_depth ? 24 : 0)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) + .WillOnce(SetArgumentPointee<1>(has_stencil ? 8 : 0)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, Enable(GL_VERTEX_PROGRAM_POINT_SIZE)) .Times(1) .RetiresOnSaturation(); @@ -134,10 +154,22 @@ void GLES2DecoderTestBase::InitDecoder( context_ = new gfx::GLContextStub; + // From <EGL/egl.h>. + const int32 EGL_ALPHA_SIZE = 0x3021; + const int32 EGL_DEPTH_SIZE = 0x3025; + const int32 EGL_STENCIL_SIZE = 0x3026; + + int32 attributes[] = { + EGL_ALPHA_SIZE, request_alpha ? 8 : 0, + EGL_DEPTH_SIZE, request_depth ? 24 : 0, + EGL_STENCIL_SIZE, request_stencil ? 8 : 0, + }; + std::vector<int32> attribs(attributes, attributes + arraysize(attributes)); + decoder_.reset(GLES2Decoder::Create(surface_manager_.get(), group_.get())); decoder_->Initialize( surface_, context_, surface_->GetSize(), DisallowedExtensions(), - NULL, std::vector<int32>()); + NULL, attribs); decoder_->set_engine(engine_.get()); EXPECT_CALL(*gl_, GenBuffersARB(_, _)) @@ -263,12 +295,8 @@ void GLES2DecoderTestBase::SetupExpectationsForFramebufferAttachment( GLclampf restore_green, GLclampf restore_blue, GLclampf restore_alpha, - GLuint restore_color_mask, GLuint restore_stencil, - GLuint restore_stencil_front_mask, - GLuint restore_stencil_back_mask, GLclampf restore_depth, - GLboolean restore_depth_mask, bool restore_scissor_test) { InSequence sequence; EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) @@ -308,28 +336,12 @@ void GLES2DecoderTestBase::SetupExpectationsForFramebufferAttachment( restore_red, restore_green, restore_blue, restore_alpha)) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, ColorMask( - ((restore_color_mask & 0x1000) != 0) ? 1 : 0, - ((restore_color_mask & 0x0100) != 0) ? 1 : 0, - ((restore_color_mask & 0x0010) != 0) ? 1 : 0, - ((restore_color_mask & 0x0001) != 0) ? 1 : 0)) - .Times(1) - .RetiresOnSaturation(); EXPECT_CALL(*gl_, ClearStencil(restore_stencil)) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, StencilMaskSeparate(GL_FRONT, restore_stencil_front_mask)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, StencilMaskSeparate(GL_BACK, restore_stencil_back_mask)) - .Times(1) - .RetiresOnSaturation(); EXPECT_CALL(*gl_, ClearDepth(restore_depth)) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, DepthMask(restore_depth_mask)) - .Times(1) - .RetiresOnSaturation(); if (restore_scissor_test) { EXPECT_CALL(*gl_, Enable(GL_SCISSOR_TEST)) .Times(1) @@ -386,6 +398,65 @@ void GLES2DecoderTestBase::DoDeleteBuffer( EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); } +void GLES2DecoderTestBase::SetupExpectationsForApplyingDirtyState( + bool framebuffer_is_rgb, + bool framebuffer_has_depth, + bool framebuffer_has_stencil, + GLuint color_bits, + bool depth_mask, + bool depth_enabled, + GLuint front_stencil_mask, + GLuint back_stencil_mask, + bool stencil_enabled) { + EXPECT_CALL(*gl_, ColorMask( + (color_bits & 0x1000) != 0, + (color_bits & 0x0100) != 0, + (color_bits & 0x0010) != 0, + (color_bits & 0x0001) && !framebuffer_is_rgb)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, DepthMask(depth_mask)) + .Times(1) + .RetiresOnSaturation(); + if (framebuffer_has_depth && depth_enabled) { + EXPECT_CALL(*gl_, Enable(GL_DEPTH_TEST)) + .Times(1) + .RetiresOnSaturation(); + } else { + EXPECT_CALL(*gl_, Disable(GL_DEPTH_TEST)) + .Times(1) + .RetiresOnSaturation(); + } + EXPECT_CALL(*gl_, StencilMaskSeparate(GL_FRONT, front_stencil_mask)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, StencilMaskSeparate(GL_BACK, back_stencil_mask)) + .Times(1) + .RetiresOnSaturation(); + if (framebuffer_has_stencil && stencil_enabled) { + EXPECT_CALL(*gl_, Enable(GL_STENCIL_TEST)) + .Times(1) + .RetiresOnSaturation(); + } else { + EXPECT_CALL(*gl_, Disable(GL_STENCIL_TEST)) + .Times(1) + .RetiresOnSaturation(); + } +} + +void GLES2DecoderTestBase::SetupExpectationsForApplyingDefaultDirtyState() { + SetupExpectationsForApplyingDirtyState( + false, // Framebuffer is RGB + false, // Framebuffer has depth + false, // Framebuffer has stencil + 0x1111, // color bits + true, // depth mask + false, // depth enabled + 0, // front stencil mask + 0, // back stencil mask + false); // stencil enabled +} + void GLES2DecoderTestBase::DoBindFramebuffer( GLenum target, GLuint client_id, GLuint service_id) { EXPECT_CALL(*gl_, BindFramebufferEXT(target, service_id)) @@ -535,7 +606,10 @@ const int GLES2DecoderTestBase::kBackBufferHeight; void GLES2DecoderWithShaderTestBase::SetUp() { GLES2DecoderTestBase::SetUp(); + SetupDefaultProgram(); +} +void GLES2DecoderWithShaderTestBase::SetupDefaultProgram() { { static AttribInfo attribs[] = { { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, }, diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h index d939e4f8..10d3037 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h @@ -162,7 +162,14 @@ class GLES2DecoderTestBase : public testing::Test { void SetBucketAsCString(uint32 bucket_id, const char* str); - void InitDecoder(const char* extensions, bool has_alpha_backbuffer); + void InitDecoder( + const char* extensions, + bool has_alpha, + bool has_depth, + bool has_stencil, + bool request_alpha, + bool request_depth, + bool request_stencil); const ContextGroup& group() const { return *group_.get(); @@ -232,14 +239,23 @@ class GLES2DecoderTestBase : public testing::Test { GLclampf restore_green, GLclampf restore_blue, GLclampf restore_alpha, - GLuint restore_color_mask, GLuint restore_stencil, - GLuint restore_stencil_front_mask, - GLuint restore_stencil_back_mask, GLclampf restore_depth, - GLboolean restore_depth_mask, bool restore_scissor_test); + void SetupExpectationsForApplyingDirtyState( + bool framebuffer_is_rgb, + bool framebuffer_has_depth, + bool framebuffer_has_stencil, + GLuint color_bits, // NOTE! bits are 0x1000, 0x0100, 0x0010, and 0x0001 + bool depth_mask, + bool depth_enabled, + GLuint front_stencil_mask, + GLuint back_stencil_mask, + bool stencil_enabled); + + void SetupExpectationsForApplyingDefaultDirtyState(); + GLvoid* BufferOffset(unsigned i) { return static_cast<int8 *>(NULL)+(i); } @@ -382,6 +398,7 @@ class GLES2DecoderWithShaderTestBase : public GLES2DecoderTestBase { virtual void SetUp(); virtual void TearDown(); + void SetupDefaultProgram(); void SetupTexture(); void DoEnableVertexAttribArray(GLint index); diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h index 6b7ff12..2fc1cb9 100644 --- a/gpu/command_buffer/service/texture_manager.h +++ b/gpu/command_buffer/service/texture_manager.h @@ -42,6 +42,7 @@ class TextureManager { cube_complete_(false), npot_(false), has_been_bound_(false), + framebuffer_attachment_count_(0), owned_(true) { } @@ -131,6 +132,19 @@ class TextureManager { owned_ = false; } + bool IsAttachedToFramebuffer() const { + return framebuffer_attachment_count_ != 0; + } + + void AttachToFramebuffer() { + ++framebuffer_attachment_count_; + } + + void DetachFromFramebuffer() { + DCHECK(framebuffer_attachment_count_ > 0); + --framebuffer_attachment_count_; + } + private: friend class TextureManager; friend class base::RefCounted<TextureInfo>; @@ -240,6 +254,9 @@ class TextureManager { // Whether this texture has ever been bound. bool has_been_bound_; + // The number of framebuffers this texture is attached to. + int framebuffer_attachment_count_; + // Whether the associated context group owns this texture and should delete // it. bool owned_; |