summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-20 23:08:46 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-20 23:08:46 +0000
commit297ca1c292e0ab41225d62bf1dfdaa581874db5c (patch)
treecf078cc80e62b0371460e28e1100741d0e20f5f9 /gpu
parent2b20c229af200a3d9ad9b8f5b53d98f2472c296f (diff)
downloadchromium_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')
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py45
-rw-r--r--gpu/command_buffer/client/gles2_implementation_autogen.h40
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils.cc1
-rw-r--r--gpu/command_buffer/service/framebuffer_manager.cc34
-rw-r--r--gpu/command_buffer/service/framebuffer_manager.h7
-rw-r--r--gpu/command_buffer/service/framebuffer_manager_unittest.cc30
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc285
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc1004
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc16
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h6
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h6
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc126
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h27
-rw-r--r--gpu/command_buffer/service/texture_manager.h17
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_;