diff options
author | vangelis@chromium.org <vangelis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-12 19:46:36 +0000 |
---|---|---|
committer | vangelis@chromium.org <vangelis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-12 19:46:36 +0000 |
commit | cb15ef5f66a48d7fae373bacb9dc5e41d8b2739a (patch) | |
tree | 454c2917d3839b3821cc23946da84a5b66cdb757 /gpu | |
parent | 93b17fd02dbf010c420fc6ea456325fcbe2645af (diff) | |
download | chromium_src-cb15ef5f66a48d7fae373bacb9dc5e41d8b2739a.zip chromium_src-cb15ef5f66a48d7fae373bacb9dc5e41d8b2739a.tar.gz chromium_src-cb15ef5f66a48d7fae373bacb9dc5e41d8b2739a.tar.bz2 |
Fixed service side implementation of glTexStorage2DEXT to only initialize the number of
levels requirested. Also ClearLevel now uses glTexSubImage2D to clear the level if the
texture is immutable. Finally, rearranged the code in doTexSubImage2D to correctly
bypass clearing a level if the bitmaps supplied matches the dimensions of the texture level.
BUG=106894
Review URL: http://codereview.chromium.org/8872061
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114059 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 80 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.h | 3 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_mock.h | 5 | ||||
-rw-r--r-- | gpu/command_buffer/service/texture_manager.cc | 12 | ||||
-rw-r--r-- | gpu/command_buffer/service/texture_manager.h | 6 | ||||
-rw-r--r-- | gpu/command_buffer/service/texture_manager_unittest.cc | 18 |
6 files changed, 70 insertions, 54 deletions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 6c6e4e4..8c358f9 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -911,7 +911,8 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, unsigned format, unsigned type, int width, - int height); + int height, + bool is_texture_immutable); // Restore all GL state that affects clearing. void RestoreClearState(); @@ -3238,7 +3239,7 @@ void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) { void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) { TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); if (!info || - !texture_manager()->MarkMipmapsGenerated(feature_info_, info, true)) { + !texture_manager()->MarkMipmapsGenerated(feature_info_, info)) { SetGLError(GL_INVALID_OPERATION, "glGenerateMipmaps: Can not generate mips for npot textures"); return; @@ -6143,7 +6144,8 @@ bool GLES2DecoderImpl::ClearLevel( unsigned format, unsigned type, int width, - int height) { + int height, + bool is_texture_immutable) { // Assumes the size has already been checked. uint32 pixels_size = 0; if (!GLES2Util::ComputeImageDataSize( @@ -6153,8 +6155,13 @@ bool GLES2DecoderImpl::ClearLevel( scoped_array<char> zero(new char[pixels_size]); memset(zero.get(), 0, pixels_size); glBindTexture(bind_target, service_id); - WrappedTexImage2D( - target, level, format, width, height, 0, format, type, zero.get()); + if (is_texture_immutable) { + glTexSubImage2D( + target, level, 0, 0, width, height, format, type, zero.get()); + } else { + WrappedTexImage2D( + target, level, format, width, height, 0, format, type, zero.get()); + } TextureManager::TextureInfo* info = GetTextureInfoForTarget(bind_target); glBindTexture(bind_target, info ? info->service_id() : 0); return true; @@ -6499,19 +6506,19 @@ void GLES2DecoderImpl::DoCompressedTexSubImage2D( if (!info->GetLevelType(target, level, &type, &internal_format)) { SetGLError( GL_INVALID_OPERATION, - "glCompressdTexSubImage2D: level does not exist."); + "glCompressedTexSubImage2D: level does not exist."); return; } if (internal_format != format) { SetGLError( GL_INVALID_OPERATION, - "glCompressdTexSubImage2D: format does not match internal format."); + "glCompressedTexSubImage2D: format does not match internal format."); return; } if (!info->ValidForTexture( target, level, xoffset, yoffset, width, height, format, type)) { SetGLError(GL_INVALID_VALUE, - "glCompressdTexSubImage2D: bad dimensions."); + "glCompressedTexSubImage2D: bad dimensions."); return; } // Note: There is no need to deal with texture cleared tracking here @@ -6602,7 +6609,8 @@ void GLES2DecoderImpl::DoCopyTexImage2D( // some part was clipped so clear the texture. if (!ClearLevel( info->service_id(), info->target(), - target, level, internal_format, GL_UNSIGNED_BYTE, width, height)) { + target, level, internal_format, GL_UNSIGNED_BYTE, width, height, + info->IsImmutable())) { SetGLError(GL_OUT_OF_MEMORY, "glCopyTexImage2D: dimensions too big"); return; } @@ -6752,28 +6760,31 @@ void GLES2DecoderImpl::DoTexSubImage2D( return; } - // See if we can call glTexImage2D instead since it appears to be faster. - if (teximage2d_faster_than_texsubimage2d_ && xoffset == 0 && yoffset == 0 && - !info->IsImmutable()) { - GLsizei tex_width = 0; - GLsizei tex_height = 0; - bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height); - DCHECK(ok); - if (width == tex_width && height == tex_height) { - // NOTE: In OpenGL ES 2.0 border is always zero and format is always the - // same as internal_foramt. If that changes we'll need to look them up. - WrappedTexImage2D( - target, level, format, width, height, 0, format, type, data); - texture_manager()->SetLevelCleared(info, target, level); + GLsizei tex_width = 0; + GLsizei tex_height = 0; + bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height); + DCHECK(ok); + if (xoffset != 0 || yoffset != 0 || + width != tex_width || height != tex_height) { + if (!texture_manager()->ClearTextureLevel(this, info, target, level)) { + SetGLError(GL_OUT_OF_MEMORY, "glTexSubImage2D: dimensions too big"); return; } - } - if (!texture_manager()->ClearTextureLevel(this, info, target, level)) { - SetGLError(GL_OUT_OF_MEMORY, "glTexSubImage2D: dimensions too big"); + glTexSubImage2D( + target, level, xoffset, yoffset, width, height, format, type, data); return; } - glTexSubImage2D( - target, level, xoffset, yoffset, width, height, format, type, data); + + if (teximage2d_faster_than_texsubimage2d_ && !info->IsImmutable()) { + // NOTE: In OpenGL ES 2.0 border is always zero and format is always the + // same as internal_foramt. If that changes we'll need to look them up. + WrappedTexImage2D( + target, level, format, width, height, 0, format, type, data); + } else { + glTexSubImage2D( + target, level, xoffset, yoffset, width, height, format, type, data); + } + texture_manager()->SetLevelCleared(info, target, level); } error::Error GLES2DecoderImpl::HandleTexSubImage2D( @@ -7831,11 +7842,16 @@ void GLES2DecoderImpl::DoTexStorage2DEXT( if (error == GL_NO_ERROR) { GLenum format = ExtractFormatFromStorageFormat(internal_format); GLenum type = ExtractTypeFromStorageFormat(internal_format); - texture_manager()->SetLevelInfo( - feature_info_, info, - target, 0, format, width, height, 1, 0, format, type, - false); - texture_manager()->MarkMipmapsGenerated(feature_info_, info, false); + GLsizei level_width = width; + GLsizei level_height = height; + for (int ii = 0; ii < levels; ++ii) { + texture_manager()->SetLevelInfo( + feature_info_, info, + target, 0, format, level_width, level_height, 1, 0, format, type, + false); + level_width = std::max(1, level_width >> 1); + level_height = std::max(1, level_height >> 1); + } info->SetImmutable(true); } diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h index d5004bb..f823e20 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder.h @@ -131,7 +131,8 @@ class GLES2Decoder : public CommonDecoder { unsigned format, unsigned type, int width, - int height) = 0; + int height, + bool is_texture_immutable) = 0; protected: GLES2Decoder(); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h index 2a94ba0..fb75bc9 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h @@ -57,7 +57,7 @@ class MockGLES2Decoder : public GLES2Decoder { uint32* service_texture_id)); MOCK_METHOD0(GetContextLostReason, error::ContextLostReason()); MOCK_CONST_METHOD1(GetCommandName, const char*(unsigned int command_id)); - MOCK_METHOD8(ClearLevel, bool( + MOCK_METHOD9(ClearLevel, bool( unsigned service_id, unsigned bind_target, unsigned target, @@ -65,7 +65,8 @@ class MockGLES2Decoder : public GLES2Decoder { unsigned format, unsigned type, int width, - int height)); + int height, + bool is_texture_immutable)); DISALLOW_COPY_AND_ASSIGN(MockGLES2Decoder); }; diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index 03873d7..ef0335b 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc @@ -106,8 +106,7 @@ bool TextureManager::TextureInfo::CanRender( } bool TextureManager::TextureInfo::MarkMipmapsGenerated( - const FeatureInfo* feature_info, - bool cleared) { + const FeatureInfo* feature_info) { if (!CanGenerateMipmaps(feature_info)) { return false; } @@ -133,7 +132,7 @@ bool TextureManager::TextureInfo::MarkMipmapsGenerated( info1.border, info1.format, info1.type, - cleared); + true); } } @@ -524,7 +523,7 @@ bool TextureManager::TextureInfo::ClearLevel( // needed to be able to call GL correctly. info.cleared = decoder->ClearLevel( service_id_, target_, info.target, info.level, info.format, info.type, - info.width, info.height); + info.width, info.height, immutable_); if (!info.cleared) { ++num_uncleared_mips_; } @@ -791,8 +790,7 @@ bool TextureManager::SetParameter( bool TextureManager::MarkMipmapsGenerated( const FeatureInfo* feature_info, - TextureManager::TextureInfo* info, - bool cleared) { + TextureManager::TextureInfo* info) { DCHECK(info); if (!info->CanRender(feature_info)) { DCHECK_NE(0, num_unrenderable_textures_); @@ -804,7 +802,7 @@ bool TextureManager::MarkMipmapsGenerated( } num_uncleared_mips_ -= info->num_uncleared_mips(); DCHECK_GE(num_uncleared_mips_, 0); - bool result = info->MarkMipmapsGenerated(feature_info, cleared); + bool result = info->MarkMipmapsGenerated(feature_info); num_uncleared_mips_ += info->num_uncleared_mips(); if (!info->CanRender(feature_info)) { ++num_unrenderable_textures_; diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h index e38706a..0217ed9 100644 --- a/gpu/command_buffer/service/texture_manager.h +++ b/gpu/command_buffer/service/texture_manager.h @@ -254,7 +254,7 @@ class TextureManager { const FeatureInfo* feature_info, GLenum pname, GLint param); // Makes each of the mip levels as though they were generated. - bool MarkMipmapsGenerated(const FeatureInfo* feature_info, bool cleared); + bool MarkMipmapsGenerated(const FeatureInfo* feature_info); void MarkAsDeleted() { service_id_ = 0; @@ -409,8 +409,8 @@ class TextureManager { // Makes each of the mip levels as though they were generated. // Returns false if that's not allowed for the given texture. - bool MarkMipmapsGenerated(const FeatureInfo* feature_info, TextureInfo* info, - bool cleared); + bool MarkMipmapsGenerated(const FeatureInfo* feature_info, + TextureInfo* info); // Clears any uncleared renderable levels. bool ClearRenderableLevels(GLES2Decoder* decoder, TextureInfo* info); diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc index d579ce2..9e911c6 100644 --- a/gpu/command_buffer/service/texture_manager_unittest.cc +++ b/gpu/command_buffer/service/texture_manager_unittest.cc @@ -373,7 +373,7 @@ TEST_F(TextureInfoTest, POT2D) { EXPECT_TRUE(info_->CanGenerateMipmaps(&feature_info_)); // Make mips. - EXPECT_TRUE(manager_.MarkMipmapsGenerated(&feature_info_, info_, true)); + EXPECT_TRUE(manager_.MarkMipmapsGenerated(&feature_info_, info_)); EXPECT_TRUE(info_->texture_complete()); EXPECT_TRUE(info_->CanRender(&feature_info_)); EXPECT_FALSE(manager_.HaveUnrenderableTextures()); @@ -390,7 +390,7 @@ TEST_F(TextureInfoTest, POT2D) { GL_TEXTURE_2D, 3, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true); EXPECT_TRUE(info_->CanGenerateMipmaps(&feature_info_)); // Make mips. - EXPECT_TRUE(manager_.MarkMipmapsGenerated(&feature_info_, info_, true)); + EXPECT_TRUE(manager_.MarkMipmapsGenerated(&feature_info_, info_)); EXPECT_TRUE(info_->CanRender(&feature_info_)); EXPECT_TRUE(info_->texture_complete()); EXPECT_FALSE(manager_.HaveUnrenderableTextures()); @@ -402,7 +402,7 @@ TEST_F(TextureInfoTest, UnusedMips) { // Set level zero to large size. manager_.SetLevelInfo(&feature_info_, info_, GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true); - EXPECT_TRUE(manager_.MarkMipmapsGenerated(&feature_info_, info_, true)); + EXPECT_TRUE(manager_.MarkMipmapsGenerated(&feature_info_, info_)); EXPECT_FALSE(info_->npot()); EXPECT_TRUE(info_->texture_complete()); EXPECT_TRUE(info_->CanRender(&feature_info_)); @@ -410,7 +410,7 @@ TEST_F(TextureInfoTest, UnusedMips) { // Set level zero to large smaller (levels unused mips) manager_.SetLevelInfo(&feature_info_, info_, GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true); - EXPECT_TRUE(manager_.MarkMipmapsGenerated(&feature_info_, info_, true)); + EXPECT_TRUE(manager_.MarkMipmapsGenerated(&feature_info_, info_)); EXPECT_FALSE(info_->npot()); EXPECT_TRUE(info_->texture_complete()); EXPECT_TRUE(info_->CanRender(&feature_info_)); @@ -476,7 +476,7 @@ TEST_F(TextureInfoTest, NPOT2DNPOTOK) { EXPECT_TRUE(info->CanGenerateMipmaps(&feature_info)); EXPECT_FALSE(info->CanRender(&feature_info)); EXPECT_TRUE(manager.HaveUnrenderableTextures()); - EXPECT_TRUE(manager.MarkMipmapsGenerated(&feature_info, info, true)); + EXPECT_TRUE(manager.MarkMipmapsGenerated(&feature_info, info)); EXPECT_TRUE(info->texture_complete()); EXPECT_TRUE(info->CanRender(&feature_info)); EXPECT_FALSE(manager.HaveUnrenderableTextures()); @@ -543,7 +543,7 @@ TEST_F(TextureInfoTest, POTCubeMap) { EXPECT_TRUE(manager_.HaveUnrenderableTextures()); // Make mips. - EXPECT_TRUE(manager_.MarkMipmapsGenerated(&feature_info_, info_, true)); + EXPECT_TRUE(manager_.MarkMipmapsGenerated(&feature_info_, info_)); EXPECT_TRUE(info_->texture_complete()); EXPECT_TRUE(info_->cube_complete()); EXPECT_TRUE(info_->CanRender(&feature_info_)); @@ -563,7 +563,7 @@ TEST_F(TextureInfoTest, POTCubeMap) { 3, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true); EXPECT_TRUE(info_->CanGenerateMipmaps(&feature_info_)); // Make mips. - EXPECT_TRUE(manager_.MarkMipmapsGenerated(&feature_info_, info_, true)); + EXPECT_TRUE(manager_.MarkMipmapsGenerated(&feature_info_, info_)); EXPECT_TRUE(info_->texture_complete()); EXPECT_TRUE(info_->cube_complete()); } @@ -797,7 +797,7 @@ TEST_F(TextureInfoTest, SafeUnsafe) { EXPECT_TRUE(manager_.HaveUnsafeTextures()); EXPECT_TRUE(manager_.HaveUnclearedMips()); EXPECT_EQ(1, info_->num_uncleared_mips()); - manager_.MarkMipmapsGenerated(&feature_info_, info_, true); + manager_.MarkMipmapsGenerated(&feature_info_, info_); EXPECT_TRUE(info_->SafeToRenderFrom()); EXPECT_FALSE(manager_.HaveUnsafeTextures()); EXPECT_FALSE(manager_.HaveUnclearedMips()); @@ -857,7 +857,7 @@ TEST_F(TextureInfoTest, SafeUnsafe) { TEST_F(TextureInfoTest, ClearTexture) { scoped_ptr<MockGLES2Decoder> decoder(new gles2::MockGLES2Decoder()); - EXPECT_CALL(*decoder, ClearLevel(_, _, _, _, _, _, _, _)) + EXPECT_CALL(*decoder, ClearLevel(_, _, _, _, _, _, _, _, _)) .WillRepeatedly(Return(true)); manager_.SetInfoTarget(&feature_info_, info_, GL_TEXTURE_2D); manager_.SetLevelInfo(&feature_info_, info_, |