summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-23 02:00:26 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-23 02:00:26 +0000
commit9edc6b2c8f0e0992c2f17eb5434d7c3044baff19 (patch)
treeab01dd716b3d0f01675029635ffde9ff9f4d64d9 /gpu
parentd5d9bf9b6414fecc6c9c764b05fb7f0f9a8c8745 (diff)
downloadchromium_src-9edc6b2c8f0e0992c2f17eb5434d7c3044baff19.zip
chromium_src-9edc6b2c8f0e0992c2f17eb5434d7c3044baff19.tar.gz
chromium_src-9edc6b2c8f0e0992c2f17eb5434d7c3044baff19.tar.bz2
Make CopyTexImage2D and CopyTexSubImage2D fail if
formats are incompatible. TEST=unit tests, more WebGL conformance tests pass. BUG=none Review URL: http://codereview.chromium.org/6028005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@70021 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py19
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils.cc20
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils.h7
-rw-r--r--gpu/command_buffer/service/framebuffer_manager.cc153
-rw-r--r--gpu/command_buffer/service/framebuffer_manager.h32
-rw-r--r--gpu/command_buffer/service/framebuffer_manager_unittest.cc146
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc188
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_autogen.h9
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc92
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc12
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h19
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc6
-rw-r--r--gpu/command_buffer/service/gles2_cmd_validation_autogen.h1
-rw-r--r--gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h8
-rw-r--r--gpu/command_buffer/service/renderbuffer_manager.h30
-rw-r--r--gpu/command_buffer/service/renderbuffer_manager_unittest.cc41
16 files changed, 611 insertions, 172 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 4748581..7c9128c 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -73,9 +73,9 @@ GL_APICALL void GL_APIENTRY glClearDepthf (GLclampf depth);
GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
GL_APICALL void GL_APIENTRY glCompileShader (GLidShader shader);
-GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenumTextureTarget target, GLint level, GLenumCompressedTextureFormat internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenumTextureTarget target, GLint level, GLenumCompressedTextureFormat internalformat, GLsizei width, GLsizei height, GLintTextureBorder border, GLsizei imageSize, const void* data);
GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenumTextureTarget target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenumCompressedTextureFormat format, GLsizei imageSize, const void* data);
-GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenumTextureTarget target, GLint level, GLenumTextureInternalFormat internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenumTextureTarget target, GLint level, GLenumTextureInternalFormat internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLintTextureBorder border);
GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenumTextureTarget target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenumShaderType type);
@@ -99,7 +99,7 @@ GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
GL_APICALL void GL_APIENTRY glFinish (void);
GL_APICALL void GL_APIENTRY glFlush (void);
GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenumFrameBufferTarget target, GLenumAttachment attachment, GLenumRenderBufferTarget renderbuffertarget, GLidRenderbuffer renderbuffer);
-GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenumFrameBufferTarget target, GLenumAttachment attachment, GLenumTextureTarget textarget, GLidTexture texture, GLint level);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenumFrameBufferTarget target, GLenumAttachment attachment, GLenumTextureTarget textarget, GLidTexture texture, GLintZeroOnly level);
GL_APICALL void GL_APIENTRY glFrontFace (GLenumFaceMode mode);
GL_APICALL void GL_APIENTRY glGenBuffers (GLsizeiNotNegative n, GLuint* buffers);
GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenumTextureBindTarget target);
@@ -1003,6 +1003,15 @@ _ENUM_LISTS = {
'5',
],
},
+ 'ZeroOnly': {
+ 'type': 'GLint',
+ 'valid': [
+ '0',
+ ],
+ 'invalid': [
+ '1',
+ ],
+ },
'FalseOnly': {
'type': 'GLboolean',
'valid': [
@@ -5312,8 +5321,8 @@ class GLGenerator(object):
else:
arg = context_arg
file.Write("%s %s(%s) {\n" % (func.return_type, func.name, arg))
-
- file.Write(""" scoped_refptr<PPB_Graphics3D_Impl> graphics_3d =
+
+ file.Write(""" scoped_refptr<PPB_Graphics3D_Impl> graphics_3d =
Resource::GetAs<PPB_Graphics3D_Impl>(context);
""")
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc
index e4f9c8c..8574f4f 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.cc
+++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -499,6 +499,26 @@ uint32 GLES2Util::IndexToGLFaceTarget(int index) {
return faces[index];
}
+uint32 GLES2Util::GetChannelsForFormat(int format) {
+ switch (format) {
+ case GL_ALPHA:
+ return 0x0008;
+ case GL_LUMINANCE:
+ return 0x0007;
+ case GL_LUMINANCE_ALPHA:
+ return 0x000F;
+ case GL_RGB:
+ case GL_RGB565:
+ return 0x0007;
+ case GL_RGBA:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ return 0x000F;
+ default:
+ return 0x0000;
+ }
+}
+
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.h b/gpu/command_buffer/common/gles2_cmd_utils.h
index d85520e..de0db25 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils.h
@@ -80,6 +80,13 @@ class GLES2Util {
static uint32 IndexToGLFaceTarget(int index);
+ // Returns a bitmask for the channels the given format supports where
+ // 0x1 is red
+ // 0x2 is green
+ // 0x4 is blue
+ // 0x8 is alpha
+ static uint32 GetChannelsForFormat(int format);
+
static bool IsNPOT(uint32 value) {
return value > 0 && (value & (value - 1)) != 0;
}
diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc
index 6169a66..43aa8ab 100644
--- a/gpu/command_buffer/service/framebuffer_manager.cc
+++ b/gpu/command_buffer/service/framebuffer_manager.cc
@@ -9,6 +9,108 @@
namespace gpu {
namespace gles2 {
+class RenderbufferAttachment
+ : public FramebufferManager::FramebufferInfo::Attachment {
+ public:
+ explicit RenderbufferAttachment(
+ RenderbufferManager::RenderbufferInfo* render_buffer)
+ : render_buffer_(render_buffer) {
+ }
+
+ virtual ~RenderbufferAttachment() { }
+
+ virtual GLsizei width() const {
+ return render_buffer_->width();
+ }
+
+ virtual GLsizei height() const {
+ return render_buffer_->height();
+ }
+
+ virtual GLenum internal_format() const {
+ return render_buffer_->internal_format();
+ }
+
+ virtual GLsizei samples() const {
+ return render_buffer_->samples();
+ }
+
+ virtual bool cleared() const {
+ return render_buffer_->cleared();
+ }
+
+ virtual void set_cleared() {
+ render_buffer_->set_cleared();
+ }
+
+ RenderbufferManager::RenderbufferInfo* render_buffer() const {
+ return render_buffer_.get();
+ }
+
+ private:
+ RenderbufferManager::RenderbufferInfo::Ref render_buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderbufferAttachment);
+};
+
+class TextureAttachment
+ : public FramebufferManager::FramebufferInfo::Attachment {
+ public:
+ TextureAttachment(
+ TextureManager::TextureInfo* texture, GLenum target, GLint level)
+ : texture_(texture),
+ target_(target),
+ level_(level) {
+ }
+
+ virtual ~TextureAttachment() { }
+
+ virtual GLsizei width() const {
+ GLsizei temp_width = 0;
+ GLsizei temp_height = 0;
+ texture_->GetLevelSize(target_, level_, &temp_width, &temp_height);
+ return temp_width;
+ }
+
+ virtual GLsizei height() const {
+ GLsizei temp_width = 0;
+ GLsizei temp_height = 0;
+ texture_->GetLevelSize(target_, level_, &temp_width, &temp_height);
+ return temp_height;
+ }
+
+ virtual GLenum internal_format() const {
+ GLenum temp_type = 0;
+ GLenum temp_internal_format = 0;
+ texture_->GetLevelType(target_, level_, &temp_type, &temp_internal_format);
+ return temp_internal_format;
+ }
+
+ virtual GLsizei samples() const {
+ return 0;
+ }
+
+ virtual bool cleared() const {
+ // Textures are cleared on creation.
+ return true;
+ }
+
+ virtual void set_cleared() {
+ NOTREACHED();
+ }
+
+ TextureManager::TextureInfo* texture() const {
+ return texture_.get();
+ }
+
+ private:
+ TextureManager::TextureInfo::Ref texture_;
+ GLenum target_;
+ GLint level_;
+
+ DISALLOW_COPY_AND_ASSIGN(TextureAttachment);
+};
+
FramebufferManager::FramebufferManager() {}
FramebufferManager::~FramebufferManager() {
@@ -47,20 +149,22 @@ FramebufferManager::FramebufferInfo::~FramebufferInfo() {}
bool FramebufferManager::FramebufferInfo::HasUnclearedAttachment(
GLenum attachment) const {
- AttachmentToRenderbufferMap::const_iterator it =
- renderbuffers_.find(attachment);
- if (it != renderbuffers_.end()) {
- RenderbufferManager::RenderbufferInfo* info = it->second;
- return !info->cleared();
+ AttachmentMap::const_iterator it =
+ attachments_.find(attachment);
+ if (it != attachments_.end()) {
+ const Attachment* attachment = it->second;
+ return !attachment->cleared();
}
return false;
}
void FramebufferManager::FramebufferInfo::MarkAttachedRenderbuffersAsCleared() {
- for (AttachmentToRenderbufferMap::iterator it = renderbuffers_.begin();
- it != renderbuffers_.end(); ++it) {
- RenderbufferManager::RenderbufferInfo* info = it->second;
- info->set_cleared();
+ for (AttachmentMap::iterator it = attachments_.begin();
+ it != attachments_.end(); ++it) {
+ Attachment* attachment = it->second;
+ if (!attachment->cleared()) {
+ attachment->set_cleared();
+ }
}
}
@@ -85,11 +189,36 @@ void FramebufferManager::FramebufferInfo::AttachRenderbuffer(
attachment == GL_STENCIL_ATTACHMENT ||
attachment == GL_DEPTH_STENCIL_ATTACHMENT);
if (renderbuffer) {
- renderbuffers_[attachment] =
- RenderbufferManager::RenderbufferInfo::Ref(renderbuffer);
+ attachments_[attachment] = Attachment::Ref(
+ new RenderbufferAttachment(renderbuffer));
+ } else {
+ attachments_.erase(attachment);
+ }
+}
+
+void FramebufferManager::FramebufferInfo::AttachTexture(
+ GLenum attachment, TextureManager::TextureInfo* texture, GLenum target,
+ GLint level) {
+ DCHECK(attachment == GL_COLOR_ATTACHMENT0 ||
+ attachment == GL_DEPTH_ATTACHMENT ||
+ attachment == GL_STENCIL_ATTACHMENT ||
+ attachment == GL_DEPTH_STENCIL_ATTACHMENT);
+ if (texture) {
+ attachments_[attachment] = Attachment::Ref(
+ new TextureAttachment(texture, target, level));
} else {
- renderbuffers_.erase(attachment);
+ attachments_.erase(attachment);
+ }
+}
+
+const FramebufferManager::FramebufferInfo::Attachment*
+ FramebufferManager::FramebufferInfo::GetAttachment(
+ GLenum attachment) const {
+ AttachmentMap::const_iterator it = attachments_.find(attachment);
+ if (it != attachments_.end()) {
+ return it->second;
}
+ return NULL;
}
bool FramebufferManager::GetClientId(
diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h
index 79ebb2f..a5c5de8 100644
--- a/gpu/command_buffer/service/framebuffer_manager.h
+++ b/gpu/command_buffer/service/framebuffer_manager.h
@@ -11,6 +11,7 @@
#include "base/scoped_ptr.h"
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/renderbuffer_manager.h"
+#include "gpu/command_buffer/service/texture_manager.h"
namespace gpu {
namespace gles2 {
@@ -24,6 +25,19 @@ class FramebufferManager {
public:
typedef scoped_refptr<FramebufferInfo> Ref;
+ class Attachment : public base::RefCounted<Attachment> {
+ public:
+ typedef scoped_refptr<Attachment> Ref;
+
+ virtual ~Attachment() { }
+ virtual GLsizei width() const = 0;
+ virtual GLsizei height() const = 0;
+ virtual GLenum internal_format() const = 0;
+ virtual GLsizei samples() const = 0;
+ virtual bool cleared() const = 0;
+ virtual void set_cleared() = 0;
+ };
+
explicit FramebufferInfo(GLuint service_id);
GLuint service_id() const {
@@ -37,8 +51,15 @@ class FramebufferManager {
void AttachRenderbuffer(
GLenum attachment, RenderbufferManager::RenderbufferInfo* renderbuffer);
+ // Attaches a texture to a particlar attachment. Pass null to detach.
+ void AttachTexture(
+ GLenum attachment, TextureManager::TextureInfo* texture, GLenum target,
+ GLint level);
+
void MarkAttachedRenderbuffersAsCleared();
+ const Attachment* GetAttachment(GLenum attachment) const;
+
bool IsDeleted() {
return service_id_ == 0;
}
@@ -51,16 +72,17 @@ class FramebufferManager {
void MarkAsDeleted() {
service_id_ = 0;
- renderbuffers_.clear();
+ attachments_.clear();
}
// Service side framebuffer id.
GLuint service_id_;
- // A map of attachments to renderbuffers.
- typedef std::map<GLenum, RenderbufferManager::RenderbufferInfo::Ref>
- AttachmentToRenderbufferMap;
- AttachmentToRenderbufferMap renderbuffers_;
+ // A map of attachments.
+ typedef std::map<GLenum, Attachment::Ref> AttachmentMap;
+ AttachmentMap attachments_;
+
+ DISALLOW_COPY_AND_ASSIGN(FramebufferInfo);
};
FramebufferManager();
diff --git a/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
index 04dba8b..cb30d8e 100644
--- a/gpu/command_buffer/service/framebuffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "gpu/command_buffer/service/framebuffer_manager.h"
+#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/common/gl_mock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -117,6 +118,10 @@ const GLuint FramebufferInfoTest::kService1Id;
TEST_F(FramebufferInfoTest, Basic) {
EXPECT_EQ(kService1Id, info_->service_id());
EXPECT_FALSE(info_->IsDeleted());
+ EXPECT_TRUE(NULL == info_->GetAttachment(GL_COLOR_ATTACHMENT0));
+ 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));
}
TEST_F(FramebufferInfoTest, AttachRenderbuffer) {
@@ -125,6 +130,19 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) {
const GLuint kRenderbufferClient2Id = 34;
const GLuint kRenderbufferService2Id = 334;
const GLint kMaxRenderbufferSize = 128;
+ const GLsizei kWidth1 = 16;
+ const GLsizei kHeight1 = 32;
+ const GLenum kFormat1 = GL_STENCIL_INDEX8;
+ const GLsizei kSamples1 = 0;
+ const GLsizei kWidth2 = 64;
+ const GLsizei kHeight2 = 128;
+ const GLenum kFormat2 = GL_STENCIL_INDEX;
+ const GLsizei kSamples2 = 0;
+ const GLsizei kWidth3 = 75;
+ const GLsizei kHeight3 = 123;
+ const GLenum kFormat3 = GL_STENCIL_INDEX8;
+ const GLsizei kSamples3 = 0;
+
EXPECT_FALSE(info_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
EXPECT_FALSE(info_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
EXPECT_FALSE(info_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
@@ -157,7 +175,17 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) {
EXPECT_FALSE(info_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
// Check marking the renderbuffer as unclared.
- rb_info1->set_internal_format(GL_RGBA);
+ rb_info1->SetInfo(kSamples1, kFormat1, kWidth1, kHeight1);
+
+ const FramebufferManager::FramebufferInfo::Attachment* attachment =
+ info_->GetAttachment(GL_COLOR_ATTACHMENT0);
+ ASSERT_TRUE(attachment != NULL);
+ EXPECT_EQ(kWidth1, attachment->width());
+ EXPECT_EQ(kHeight1, attachment->height());
+ EXPECT_EQ(kSamples1, attachment->samples());
+ EXPECT_EQ(kFormat1, attachment->internal_format());
+ EXPECT_FALSE(attachment->cleared());
+
EXPECT_TRUE(info_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
// Clear it.
@@ -170,10 +198,30 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) {
RenderbufferManager::RenderbufferInfo* rb_info2 =
rb_manager.GetRenderbufferInfo(kRenderbufferClient2Id);
ASSERT_TRUE(rb_info2 != NULL);
+ rb_info2->SetInfo(kSamples2, kFormat2, kWidth2, kHeight2);
info_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, rb_info2);
EXPECT_TRUE(info_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
+ attachment = info_->GetAttachment(GL_STENCIL_ATTACHMENT);
+ ASSERT_TRUE(attachment != NULL);
+ EXPECT_EQ(kWidth2, attachment->width());
+ EXPECT_EQ(kHeight2, attachment->height());
+ EXPECT_EQ(kSamples2, attachment->samples());
+ EXPECT_EQ(kFormat2, attachment->internal_format());
+ EXPECT_FALSE(attachment->cleared());
+
+ // Check changing an attachment.
+ rb_info2->SetInfo(kSamples3, kFormat3, kWidth3, kHeight3);
+
+ attachment = info_->GetAttachment(GL_STENCIL_ATTACHMENT);
+ ASSERT_TRUE(attachment != NULL);
+ EXPECT_EQ(kWidth3, attachment->width());
+ EXPECT_EQ(kHeight3, attachment->height());
+ EXPECT_EQ(kSamples3, attachment->samples());
+ EXPECT_EQ(kFormat3, attachment->internal_format());
+ EXPECT_FALSE(attachment->cleared());
+
// Check removing it.
info_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, NULL);
EXPECT_FALSE(info_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
@@ -181,6 +229,102 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) {
rb_manager.Destroy(false);
}
+TEST_F(FramebufferInfoTest, AttachTexture) {
+ const GLuint kTextureClient1Id = 33;
+ const GLuint kTextureService1Id = 333;
+ const GLuint kTextureClient2Id = 34;
+ const GLuint kTextureService2Id = 334;
+ const GLint kMaxTextureSize = 128;
+ const GLint kDepth = 1;
+ const GLint kBorder = 0;
+ const GLenum kType = GL_UNSIGNED_BYTE;
+ const GLsizei kWidth1 = 16;
+ const GLsizei kHeight1 = 32;
+ const GLint kLevel1 = 0;
+ const GLenum kFormat1 = GL_RGBA;
+ const GLenum kTarget1 = GL_TEXTURE_2D;
+ const GLsizei kSamples1 = 0;
+ const GLsizei kWidth2 = 64;
+ const GLsizei kHeight2 = 128;
+ const GLint kLevel2 = 0;
+ const GLenum kFormat2 = GL_RGB;
+ const GLenum kTarget2 = GL_TEXTURE_2D;
+ const GLsizei kSamples2 = 0;
+ const GLsizei kWidth3 = 75;
+ const GLsizei kHeight3 = 123;
+ const GLint kLevel3 = 0;
+ const GLenum kFormat3 = GL_RGB565;
+ const GLsizei kSamples3 = 0;
+ EXPECT_FALSE(info_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
+ EXPECT_FALSE(info_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
+ EXPECT_FALSE(info_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
+ EXPECT_FALSE(info_->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT));
+
+ FeatureInfo feature_info;
+ TextureManager tex_manager(kMaxTextureSize, kMaxTextureSize);
+ tex_manager.CreateTextureInfo(
+ &feature_info, kTextureClient1Id, kTextureService1Id);
+ TextureManager::TextureInfo* tex_info1 =
+ tex_manager.GetTextureInfo(kTextureClient1Id);
+ ASSERT_TRUE(tex_info1 != NULL);
+ 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);
+
+ // check adding one attachment
+ info_->AttachTexture(GL_COLOR_ATTACHMENT0, tex_info1, kTarget1, kLevel1);
+ EXPECT_FALSE(info_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
+
+ const FramebufferManager::FramebufferInfo::Attachment* attachment =
+ info_->GetAttachment(GL_COLOR_ATTACHMENT0);
+ ASSERT_TRUE(attachment != NULL);
+ EXPECT_EQ(kWidth1, attachment->width());
+ EXPECT_EQ(kHeight1, attachment->height());
+ EXPECT_EQ(kSamples1, attachment->samples());
+ EXPECT_EQ(kFormat1, attachment->internal_format());
+ EXPECT_TRUE(attachment->cleared());
+
+ // Check replacing an attachment
+ tex_manager.CreateTextureInfo(
+ &feature_info, kTextureClient2Id, kTextureService2Id);
+ TextureManager::TextureInfo* tex_info2 =
+ tex_manager.GetTextureInfo(kTextureClient2Id);
+ ASSERT_TRUE(tex_info2 != NULL);
+ tex_manager.SetInfoTarget(tex_info2, GL_TEXTURE_2D);
+ tex_manager.SetLevelInfo(
+ &feature_info, tex_info2, GL_TEXTURE_2D, kLevel2,
+ kFormat2, kWidth2, kHeight2, kDepth, kBorder, kFormat2, kType);
+
+ info_->AttachTexture(GL_COLOR_ATTACHMENT0, tex_info2, kTarget2, kLevel2);
+
+ attachment = info_->GetAttachment(GL_COLOR_ATTACHMENT0);
+ ASSERT_TRUE(attachment != NULL);
+ EXPECT_EQ(kWidth2, attachment->width());
+ EXPECT_EQ(kHeight2, attachment->height());
+ EXPECT_EQ(kSamples2, attachment->samples());
+ EXPECT_EQ(kFormat2, attachment->internal_format());
+ EXPECT_TRUE(attachment->cleared());
+
+ // Check changing attachment
+ tex_manager.SetLevelInfo(
+ &feature_info, tex_info2, GL_TEXTURE_2D, kLevel3,
+ kFormat3, kWidth3, kHeight3, kDepth, kBorder, kFormat3, kType);
+ attachment = info_->GetAttachment(GL_COLOR_ATTACHMENT0);
+ ASSERT_TRUE(attachment != NULL);
+ EXPECT_EQ(kWidth3, attachment->width());
+ EXPECT_EQ(kHeight3, attachment->height());
+ EXPECT_EQ(kSamples3, attachment->samples());
+ EXPECT_EQ(kFormat3, attachment->internal_format());
+ EXPECT_TRUE(attachment->cleared());
+
+ // Check removing it.
+ info_->AttachTexture(GL_COLOR_ATTACHMENT0, NULL, 0, 0);
+ EXPECT_TRUE(info_->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL);
+
+ tex_manager.Destroy(false);
+}
+
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index e544365..249987f 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -778,6 +778,10 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
// or regular back buffer).
gfx::Size GetBoundReadFrameBufferSize();
+ // Get the format of the currently bound frame buffer (either FBO or regular
+ // back buffer)
+ GLenum GetBoundReadFrameBufferInternalFormat();
+
// Wrapper for CompressedTexImage2D commands.
error::Error DoCompressedTexImage2D(
GLenum target,
@@ -2195,81 +2199,12 @@ void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
if (bound_read_framebuffer_ != 0) {
- int width = 0;
- int height = 0;
-
- GLenum target =
- feature_info_->feature_flags().chromium_framebuffer_multisample ?
- GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
-
- // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and
- // stencil.
- GLint fb_type = 0;
- glGetFramebufferAttachmentParameterivEXT(
- target,
- GL_COLOR_ATTACHMENT0,
- GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
- &fb_type);
- switch (fb_type) {
- case GL_RENDERBUFFER:
- {
- GLint renderbuffer_id = 0;
- glGetFramebufferAttachmentParameterivEXT(
- target,
- GL_COLOR_ATTACHMENT0,
- GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
- &renderbuffer_id);
- if (renderbuffer_id != 0) {
- glGetRenderbufferParameterivEXT(
- GL_RENDERBUFFER,
- GL_RENDERBUFFER_WIDTH,
- &width);
- glGetRenderbufferParameterivEXT(
- GL_RENDERBUFFER,
- GL_RENDERBUFFER_HEIGHT,
- &height);
- }
- break;
- }
- case GL_TEXTURE:
- {
- GLint texture_id = 0;
- glGetFramebufferAttachmentParameterivEXT(
- target,
- GL_COLOR_ATTACHMENT0,
- GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
- &texture_id);
- if (texture_id != 0) {
- GLuint client_id = 0;
- if (texture_manager()->GetClientId(texture_id, &client_id)) {
- TextureManager::TextureInfo* texture_info =
- GetTextureInfo(client_id);
- if (texture_info) {
- GLint level = 0;
- GLint face = 0;
- glGetFramebufferAttachmentParameterivEXT(
- target,
- GL_COLOR_ATTACHMENT0,
- GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
- &level);
- glGetFramebufferAttachmentParameterivEXT(
- target,
- GL_COLOR_ATTACHMENT0,
- GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
- &face);
- texture_info->GetLevelSize(
- face ? face : GL_TEXTURE_2D, level, &width, &height);
- }
- }
- }
- break;
- }
- default:
- // unknown so assume width and height are zero.
- break;
+ const FramebufferManager::FramebufferInfo::Attachment* attachment =
+ bound_read_framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
+ if (attachment) {
+ return gfx::Size(attachment->width(), attachment->height());
}
-
- return gfx::Size(width, height);
+ return gfx::Size(0, 0);
} else if (offscreen_target_frame_buffer_.get()) {
return offscreen_size_;
} else {
@@ -2277,6 +2212,22 @@ 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;
+ } else if (offscreen_target_frame_buffer_.get()) {
+ return offscreen_target_color_format_;
+ } else {
+ // TODO(gman): return correct format
+ return GL_RGBA;
+ }
+}
+
bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
if (offscreen_size_ == pending_offscreen_size_)
return true;
@@ -3341,13 +3292,17 @@ void GLES2DecoderImpl::DoFramebufferRenderbuffer(
}
service_id = info->service_id();
}
+ CopyRealGLErrorsToWrapper();
glFramebufferRenderbufferEXT(
target, attachment, renderbuffertarget, service_id);
- if (service_id == 0 ||
- glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
+ GLenum error = glGetError();
+ if (error == GL_NO_ERROR) {
framebuffer_info->AttachRenderbuffer(attachment, info);
- if (info) {
- ClearUnclearedRenderbuffers(target, framebuffer_info);
+ if (service_id == 0 ||
+ glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
+ if (info) {
+ ClearUnclearedRenderbuffers(target, framebuffer_info);
+ }
}
}
}
@@ -3504,10 +3459,15 @@ void GLES2DecoderImpl::DoFramebufferTexture2D(
}
service_id = info->service_id();
}
+ CopyRealGLErrorsToWrapper();
glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
- if (service_id != 0 &&
- glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
- ClearUnclearedRenderbuffers(target, framebuffer_info);
+ GLenum error = glGetError();
+ if (error == GL_NO_ERROR) {
+ framebuffer_info->AttachTexture(attachment, info, textarget, level);
+ if (service_id != 0 &&
+ glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
+ ClearUnclearedRenderbuffers(target, framebuffer_info);
+ }
}
}
@@ -3581,26 +3541,30 @@ void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
"glRenderbufferStorageMultisampleEXT: function not available");
return;
}
- bound_renderbuffer_->set_internal_format(internalformat);
+ GLenum impl_format = internalformat;
if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
- switch (internalformat) {
+ switch (impl_format) {
case GL_DEPTH_COMPONENT16:
- internalformat = GL_DEPTH_COMPONENT;
+ impl_format = GL_DEPTH_COMPONENT;
break;
case GL_RGBA4:
case GL_RGB5_A1:
- internalformat = GL_RGBA;
+ impl_format = GL_RGBA;
break;
case GL_RGB565:
- internalformat = GL_RGB;
+ impl_format = GL_RGB;
break;
}
}
+ CopyRealGLErrorsToWrapper();
glRenderbufferStorageMultisampleEXT(
- target, samples, internalformat, width, height);
- // TODO(gman) should not set internal format unless this succeeds
+ target, samples, impl_format, width, height);
+ GLenum error = glGetError();
+ if (error == GL_NO_ERROR) {
+ bound_renderbuffer_->SetInfo(samples, internalformat, width, height);
+ }
}
void GLES2DecoderImpl::DoRenderbufferStorage(
@@ -3610,25 +3574,29 @@ void GLES2DecoderImpl::DoRenderbufferStorage(
"glGetRenderbufferStorage: no renderbuffer bound");
return;
}
- bound_renderbuffer_->set_internal_format(internalformat);
+ GLenum impl_format = internalformat;
if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
- switch (internalformat) {
+ switch (impl_format) {
case GL_DEPTH_COMPONENT16:
- internalformat = GL_DEPTH_COMPONENT;
+ impl_format = GL_DEPTH_COMPONENT;
break;
case GL_RGBA4:
case GL_RGB5_A1:
- internalformat = GL_RGBA;
+ impl_format = GL_RGBA;
break;
case GL_RGB565:
- internalformat = GL_RGB;
+ impl_format = GL_RGB;
break;
}
}
- glRenderbufferStorageEXT(target, internalformat, width, height);
- // TODO(gman) should not set internal format unless this succeeds
+ CopyRealGLErrorsToWrapper();
+ glRenderbufferStorageEXT(target, impl_format, width, height);
+ GLenum error = glGetError();
+ if (error == GL_NO_ERROR) {
+ bound_renderbuffer_->SetInfo(0, internalformat, width, height);
+ }
}
void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
@@ -5487,13 +5455,21 @@ void GLES2DecoderImpl::DoCopyTexImage2D(
return;
}
- // TODO(gman): Need to check that current FBO is compatible with
- // internal_format.
- // TODO(gman): Type needs to match format for FBO.
+ // Check we have compatible formats.
+ GLenum read_format = GetBoundReadFrameBufferInternalFormat();
+ uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
+ uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
+
+ if ((channels_needed & channels_exist) != channels_needed) {
+ SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
+ return;
+ }
+
CopyRealGLErrorsToWrapper();
ScopedResolvedFrameBufferBinder binder(this);
- // Clip to size to source dimensions
gfx::Size size = GetBoundReadFrameBufferSize();
+
+ // Clip to size to source dimensions
GLint copyX = 0;
GLint copyY = 0;
GLint copyWidth = 0;
@@ -5562,8 +5538,18 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D(
"glCopyTexSubImage2D: bad dimensions.");
return;
}
- // TODO(gman): Should we check that x, y, width, and height are in range
- // for current FBO?
+
+ // Check we have compatible formats.
+ GLenum read_format = GetBoundReadFrameBufferInternalFormat();
+ uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
+ uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
+
+ if ((channels_needed & channels_exist) != channels_needed) {
+ SetGLError(
+ GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
+ return;
+ }
+
ScopedResolvedFrameBufferBinder binder(this);
gfx::Size size = GetBoundReadFrameBufferSize();
GLint copyX = 0;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
index d71a681..60bf9ed 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -380,6 +380,10 @@ error::Error GLES2DecoderImpl::HandleCopyTexImage2D(
SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: height < 0");
return error::kNoError;
}
+ if (!validators_->texture_border.IsValid(border)) {
+ SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: border GL_INVALID_VALUE");
+ return error::kNoError;
+ }
DoCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
return error::kNoError;
}
@@ -721,6 +725,11 @@ error::Error GLES2DecoderImpl::HandleFramebufferTexture2D(
GL_INVALID_ENUM, "glFramebufferTexture2D: textarget GL_INVALID_ENUM");
return error::kNoError;
}
+ if (!validators_->zero_only.IsValid(level)) {
+ SetGLError(
+ GL_INVALID_VALUE, "glFramebufferTexture2D: level GL_INVALID_VALUE");
+ return error::kNoError;
+ }
DoFramebufferTexture2D(target, attachment, textarget, texture, level);
return error::kNoError;
}
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index 46a70ae..c6454bb 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -1235,7 +1235,7 @@ TEST_F(GLES2DecoderTest, FramebufferTexture2DWithNoBoundTarget) {
FramebufferTexture2D cmd;
cmd.Init(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, client_texture_id_,
- 5);
+ 0);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
}
@@ -1259,11 +1259,17 @@ TEST_F(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithNoBoundTarget) {
TEST_F(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithRenderbuffer) {
DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_,
kServiceFramebufferId);
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
EXPECT_CALL(*gl_, FramebufferRenderbufferEXT(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
kServiceRenderbufferId))
.Times(1)
.RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
SetupExpectationsForFramebufferAttachment(
GL_COLOR_BUFFER_BIT, // clear bits
0, 0, 0, 0, // color
@@ -1313,11 +1319,17 @@ TEST_F(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithRenderbuffer) {
TEST_F(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithTexture) {
DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_,
kServiceFramebufferId);
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
EXPECT_CALL(*gl_, FramebufferTexture2DEXT(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- kServiceTextureId, 5))
+ kServiceTextureId, 0))
.Times(1)
.RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
SetupExpectationsForFramebufferAttachment(
0, // clear bits
0, 0, 0, 0, // color
@@ -1353,7 +1365,7 @@ TEST_F(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithTexture) {
GetFramebufferAttachmentParameteriv cmd;
fbtex_cmd.Init(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, client_texture_id_,
- 5);
+ 0);
cmd.Init(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, shared_memory_id_,
@@ -1485,38 +1497,34 @@ void GLES2DecoderTest::CheckReadPixelsOutOfRange(
kFormat, GL_UNSIGNED_BYTE, 0, 0);
DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_,
kServiceFramebufferId);
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, FramebufferTexture2DEXT(
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ kServiceTextureId, 0))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ 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(
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, client_texture_id_,
+ 0);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(fbtex_cmd));
}
- // We need to tell our mock GL to return the info about our FBO.
- EXPECT_CALL(*gl_, GetFramebufferAttachmentParameterivEXT(
- GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
- _))
- .WillOnce(SetArgumentPointee<3>(GL_TEXTURE))
- .RetiresOnSaturation();
- EXPECT_CALL(*gl_, GetFramebufferAttachmentParameterivEXT(
- GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
- _))
- .WillOnce(SetArgumentPointee<3>(kServiceTextureId))
- .RetiresOnSaturation();
- EXPECT_CALL(*gl_, GetFramebufferAttachmentParameterivEXT(
- GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
- _))
- .WillOnce(SetArgumentPointee<3>(0))
- .RetiresOnSaturation();
- EXPECT_CALL(*gl_, GetFramebufferAttachmentParameterivEXT(
- GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
- _))
- .WillOnce(SetArgumentPointee<3>(0))
- .RetiresOnSaturation();
-
ReadPixelsEmulator emu(
kWidth, kHeight, kBytesPerPixel, kSrcPixels, kPackAlignment);
typedef ReadPixels::Result Result;
@@ -2447,11 +2455,17 @@ TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearColor) {
EXPECT_CALL(*gl_, Enable(GL_SCISSOR_TEST))
.Times(1)
.RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
EXPECT_CALL(*gl_, FramebufferRenderbufferEXT(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
kServiceRenderbufferId))
.Times(1)
.RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
SetupExpectationsForFramebufferAttachment(
GL_COLOR_BUFFER_BIT, // clear bits
0.1f, 0.2f, 0.3f, 0.4f, // color
@@ -2486,11 +2500,17 @@ TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearDepth) {
EXPECT_CALL(*gl_, DepthMask(0))
.Times(1)
.RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
EXPECT_CALL(*gl_, FramebufferRenderbufferEXT(
GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
kServiceRenderbufferId))
.Times(1)
.RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
SetupExpectationsForFramebufferAttachment(
GL_DEPTH_BUFFER_BIT, // clear bits
0, 0, 0, 0, // color
@@ -2524,11 +2544,17 @@ TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearStencil) {
EXPECT_CALL(*gl_, StencilMaskSeparate(GL_BACK, 0x1234u))
.Times(1)
.RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
EXPECT_CALL(*gl_, FramebufferRenderbufferEXT(
GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
kServiceRenderbufferId))
.Times(1)
.RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
SetupExpectationsForFramebufferAttachment(
GL_STENCIL_BUFFER_BIT, // clear bits
0, 0, 0, 0, // color
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 e589e6d..931a795 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc
@@ -88,11 +88,17 @@ void GLES2DecoderTestBase::SpecializedSetup<FramebufferRenderbuffer, 0>(
DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_,
kServiceFramebufferId);
if (valid) {
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
// Return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT so the code
// doesn't try to clear the buffer. That is tested else where.
EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
.WillOnce(Return(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT))
.RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
}
};
@@ -102,11 +108,17 @@ void GLES2DecoderTestBase::SpecializedSetup<FramebufferTexture2D, 0>(
DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_,
kServiceFramebufferId);
if (valid) {
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
// Return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT so the code
// doesn't try to clear the buffer. That is tested else where.
EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
.WillOnce(Return(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT))
.RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
}
};
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 786ad92..cd4c33d 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
@@ -801,12 +801,12 @@ TEST_F(GLES2DecoderTest1, FramebufferTexture2DValidArgs) {
EXPECT_CALL(
*gl_, FramebufferTexture2DEXT(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- kServiceTextureId, 5));
+ kServiceTextureId, 0));
SpecializedSetup<FramebufferTexture2D, 0>(true);
FramebufferTexture2D cmd;
cmd.Init(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, client_texture_id_,
- 5);
+ 0);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
@@ -817,7 +817,7 @@ TEST_F(GLES2DecoderTest1, FramebufferTexture2DInvalidArgs0_0) {
FramebufferTexture2D cmd;
cmd.Init(
GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- client_texture_id_, 5);
+ client_texture_id_, 0);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
}
@@ -828,11 +828,22 @@ TEST_F(GLES2DecoderTest1, FramebufferTexture2DInvalidArgs2_0) {
FramebufferTexture2D cmd;
cmd.Init(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_PROXY_TEXTURE_CUBE_MAP,
- client_texture_id_, 5);
+ client_texture_id_, 0);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
}
+TEST_F(GLES2DecoderTest1, FramebufferTexture2DInvalidArgs4_0) {
+ EXPECT_CALL(*gl_, FramebufferTexture2DEXT(_, _, _, _, _)).Times(0);
+ SpecializedSetup<FramebufferTexture2D, 0>(false);
+ FramebufferTexture2D cmd;
+ cmd.Init(
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, client_texture_id_,
+ 1);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+}
+
TEST_F(GLES2DecoderTest1, FrontFaceValidArgs) {
EXPECT_CALL(*gl_, FrontFace(GL_CW));
SpecializedSetup<FrontFace, 0>(true);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc
index a86149f..452857e 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc
@@ -180,10 +180,16 @@ void GLES2DecoderTestBase::SpecializedSetup<RenderbufferStorage, 0>(
DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_,
kServiceRenderbufferId);
if (valid) {
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
EXPECT_CALL(*gl_,
RenderbufferStorageEXT(GL_RENDERBUFFER, _, 3, 4))
.Times(1)
.RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
}
};
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
index 97084ee..c528c1b 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
@@ -52,6 +52,7 @@ ValueValidator<GLint> vertex_attrib_size;
ValueValidator<GLenum> vertex_attrib_type;
ValueValidator<GLenum> vertex_attribute;
ValueValidator<GLenum> vertex_pointer;
+ValueValidator<GLint> zero_only;
#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
index f19e25b..6a81894 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
@@ -415,6 +415,10 @@ static GLenum valid_vertex_pointer_table[] = {
GL_VERTEX_ATTRIB_ARRAY_POINTER,
};
+static GLint valid_zero_only_table[] = {
+ 0,
+};
+
Validators::Validators()
: attachment(
valid_attachment_table, arraysize(valid_attachment_table)),
@@ -524,7 +528,9 @@ Validators::Validators()
valid_vertex_attribute_table, arraysize(
valid_vertex_attribute_table)),
vertex_pointer(
- valid_vertex_pointer_table, arraysize(valid_vertex_pointer_table)) {
+ valid_vertex_pointer_table, arraysize(valid_vertex_pointer_table)),
+ zero_only(
+ valid_zero_only_table, arraysize(valid_zero_only_table)) {
}
#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_IMPLEMENTATION_AUTOGEN_H_ // NOLINT
diff --git a/gpu/command_buffer/service/renderbuffer_manager.h b/gpu/command_buffer/service/renderbuffer_manager.h
index c6992c3a..db9ba816 100644
--- a/gpu/command_buffer/service/renderbuffer_manager.h
+++ b/gpu/command_buffer/service/renderbuffer_manager.h
@@ -26,7 +26,10 @@ class RenderbufferManager {
explicit RenderbufferInfo(GLuint service_id)
: service_id_(service_id),
cleared_(false),
- internal_format_(GL_RGBA4) {
+ samples_(0),
+ internal_format_(GL_RGBA4),
+ width_(0),
+ height_(0) {
}
GLuint service_id() const {
@@ -45,8 +48,24 @@ class RenderbufferManager {
return internal_format_;
}
- void set_internal_format(GLenum internalformat) {
+ GLsizei samples() const {
+ return samples_;
+ }
+
+ GLsizei width() const {
+ return width_;
+ }
+
+ GLsizei height() const {
+ return height_;
+ }
+
+ void SetInfo(
+ GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {
+ samples_ = samples;
internal_format_ = internalformat;
+ width_ = width;
+ height_ = height;
cleared_ = false;
}
@@ -70,8 +89,15 @@ class RenderbufferManager {
// Whether this renderbuffer has been cleared
bool cleared_;
+ // Number of samples (for multi-sampled renderbuffers)
+ GLsizei samples_;
+
// Renderbuffer internalformat set through RenderbufferStorage().
GLenum internal_format_;
+
+ // Dimensions of renderbuffer.
+ GLsizei width_;
+ GLsizei height_;
};
explicit RenderbufferManager(GLint max_renderbuffer_size);
diff --git a/gpu/command_buffer/service/renderbuffer_manager_unittest.cc b/gpu/command_buffer/service/renderbuffer_manager_unittest.cc
index da1849c..c68b599 100644
--- a/gpu/command_buffer/service/renderbuffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/renderbuffer_manager_unittest.cc
@@ -56,14 +56,6 @@ TEST_F(RenderbufferManagerTest, Basic) {
GLuint client_id = 0;
EXPECT_TRUE(manager_.GetClientId(info1->service_id(), &client_id));
EXPECT_EQ(kClient1Id, client_id);
- EXPECT_FALSE(info1->cleared());
- info1->set_cleared();
- EXPECT_TRUE(info1->cleared());
- // Check if we set the format it gets marked as not cleared.
- info1->set_internal_format(GL_RGBA);
- EXPECT_FALSE(info1->cleared());
- EXPECT_FALSE(info1->IsDeleted());
- EXPECT_EQ(kService1Id, info1->service_id());
// Check we get nothing for a non-existent renderbuffer.
EXPECT_TRUE(manager_.GetRenderbufferInfo(kClient2Id) == NULL);
// Check trying to a remove non-existent renderbuffers does not crash.
@@ -90,6 +82,39 @@ TEST_F(RenderbufferManagerTest, Destroy) {
ASSERT_TRUE(info1 == NULL);
}
+TEST_F(RenderbufferManagerTest, RenderbufferInfo) {
+ const GLuint kClient1Id = 1;
+ const GLuint kService1Id = 11;
+ // Check we can create renderbuffer.
+ manager_.CreateRenderbufferInfo(kClient1Id, kService1Id);
+ // Check renderbuffer got created.
+ RenderbufferManager::RenderbufferInfo* info1 =
+ manager_.GetRenderbufferInfo(kClient1Id);
+ ASSERT_TRUE(info1 != NULL);
+ EXPECT_EQ(kService1Id, info1->service_id());
+ EXPECT_EQ(0, info1->samples());
+ EXPECT_EQ(static_cast<GLenum>(GL_RGBA4), info1->internal_format());
+ EXPECT_EQ(0, info1->width());
+ EXPECT_EQ(0, info1->height());
+
+ EXPECT_FALSE(info1->cleared());
+ info1->set_cleared();
+ EXPECT_TRUE(info1->cleared());
+
+ // Check if we set the info it gets marked as not cleared.
+ const GLsizei kSamples = 4;
+ const GLenum kFormat = GL_RGBA;
+ const GLsizei kWidth = 128;
+ const GLsizei kHeight = 64;
+ info1->SetInfo(kSamples, kFormat, kWidth, kHeight);
+ EXPECT_EQ(kSamples, info1->samples());
+ EXPECT_EQ(kFormat, info1->internal_format());
+ EXPECT_EQ(kWidth, info1->width());
+ EXPECT_EQ(kHeight, info1->height());
+ EXPECT_FALSE(info1->cleared());
+ EXPECT_FALSE(info1->IsDeleted());
+}
+
} // namespace gles2
} // namespace gpu