diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-23 02:00:26 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-23 02:00:26 +0000 |
commit | 9edc6b2c8f0e0992c2f17eb5434d7c3044baff19 (patch) | |
tree | ab01dd716b3d0f01675029635ffde9ff9f4d64d9 /gpu | |
parent | d5d9bf9b6414fecc6c9c764b05fb7f0f9a8c8745 (diff) | |
download | chromium_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')
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 |