diff options
10 files changed, 290 insertions, 95 deletions
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index aa3f293..75b1c8d 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py @@ -69,10 +69,6 @@ class WebGL2ConformanceExpectations(WebGLConformanceExpectations): # Note that this test fails on ['win', 'intel'] with bug=483282 self.Fail('conformance2/buffers/uniform-buffers.html', bug=577368) - # Command buffer side handling of TexSubImage3D is incorrect. - self.Fail('conformance2/textures/misc/tex-storage-and-subimage-3d.html', - bug=570453) - # Windows only. self.Fail('conformance2/textures/canvas/tex-image-and-sub-image-2d' + '-with-canvas-r8-red-unsigned_byte.html', diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index b38c6de..5fcec4e 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -3712,6 +3712,8 @@ _FUNCTION_INFO = { }, 'TexStorage3D': { 'unsafe': True, + 'unit_test': False, + 'decoder_func': 'DoTexStorage3D', 'trace_level': 2, }, 'TexSubImage2D': { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index c68e159..6165f0b 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -917,20 +917,6 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { GLsizei width, GLsizei height); - // Wrapper for TexSubImage3D. - error::Error DoTexSubImage3D( - GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLenum format, - GLenum type, - const void * data); - // Wrapper for TexImageIOSurface2DCHROMIUM. void DoTexImageIOSurface2DCHROMIUM( GLenum target, @@ -969,6 +955,15 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { GLsizei width, GLsizei height); + // Wrapper for TexStorage3D. + void DoTexStorage3D( + GLenum target, + GLint levels, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth); + void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key); void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target, const GLbyte* key); @@ -10088,6 +10083,8 @@ bool GLES2DecoderImpl::ClearLevel(Texture* texture, int yoffset, int width, int height) { + // TODO(zmo): Implement clearing of 3D textures. crbug.com/597201. + DCHECK(target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY); uint32_t channels = GLES2Util::GetChannelsForFormat(format); if ((feature_info_->feature_flags().angle_depth_texture || feature_info_->IsES3Enabled()) @@ -11497,8 +11494,9 @@ error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32_t immediate_data_size, return error::kOutOfBounds; TextureManager::DoTexSubImageArguments args = { - target, level, xoffset, yoffset, width, - height, format, type, pixels, data_size}; + target, level, xoffset, yoffset, 0, width, height, 1, + format, type, pixels, data_size, + TextureManager::DoTexSubImageArguments::kTexSubImage2D}; texture_manager()->ValidateAndDoTexSubImage(this, &texture_state_, &state_, &framebuffer_state_, "glTexSubImage2D", args); @@ -11509,42 +11507,6 @@ error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32_t immediate_data_size, return error::kNoError; } -error::Error GLES2DecoderImpl::DoTexSubImage3D( - GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLint zoffset, - GLsizei width, - GLsizei height, - GLsizei depth, - GLenum format, - GLenum type, - const void * data) { - TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( - &state_, target); - if (!texture_ref) { - LOCAL_SET_GL_ERROR( - GL_INVALID_ENUM, "glTexSubImage3D", "invalid target"); - } - - LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D"); - ScopedTextureUploadTimer timer(&texture_state_); - glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, - depth, format, type, data); - GLenum error = LOCAL_PEEK_GL_ERROR("glTexSubImage3D"); - if (error == GL_NO_ERROR) { - // TODO(zmo): This is not 100% correct because only part of the level - // image is cleared. - texture_manager()->SetLevelCleared(texture_ref, target, level, true); - } - - // This may be a slow command. Exit command processing to allow for - // context preemption and GPU watchdog checks. - ExitCommandProcessingEarly(); - return error::kNoError; -} - error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32_t immediate_data_size, const void* cmd_data) { if (!unsafe_es3_apis_enabled()) @@ -11574,10 +11536,24 @@ error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32_t immediate_data_size, NULL, NULL)) { return error::kOutOfBounds; } + const void* pixels = GetSharedMemoryAs<const void*>( c.pixels_shm_id, c.pixels_shm_offset, data_size); - return DoTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, - height, depth, format, type, pixels); + if (!pixels) + return error::kOutOfBounds; + + TextureManager::DoTexSubImageArguments args = { + target, level, xoffset, yoffset, zoffset, width, height, depth, + format, type, pixels, data_size, + TextureManager::DoTexSubImageArguments::kTexSubImage3D}; + texture_manager()->ValidateAndDoTexSubImage(this, &texture_state_, &state_, + &framebuffer_state_, + "glTexSubImage3D", args); + + // This may be a slow command. Exit command processing to allow for + // context preemption and GPU watchdog checks. + ExitCommandProcessingEarly(); + return error::kNoError; } error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv( @@ -13850,6 +13826,122 @@ void GLES2DecoderImpl::DoTexStorage2DEXT( } } +void GLES2DecoderImpl::DoTexStorage3D( + GLenum target, + GLint levels, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth) { + TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage3D", + "widthXheight", width * height, "depth", depth); + if (!validators_->texture_3_d_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glTexStorage3D", target, "target"); + return; + } + if (levels <= 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "levels <= 0"); + return; + } + if (!validators_->texture_internal_format_storage.IsValid(internal_format)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glTexStorage3D", internal_format, + "internal_format"); + return; + } + if (width <= 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "width <= 0"); + return; + } + if (height <= 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "height <= 0"); + return; + } + if (depth <= 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "depth <= 0"); + return; + } + if (!texture_manager()->ValidForTarget(target, 0, width, height, depth) || + TextureManager::ComputeMipMapCount( + target, width, height, depth) < levels) { + LOCAL_SET_GL_ERROR( + GL_INVALID_VALUE, "glTexStorage3D", "dimensions out of range"); + return; + } + TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( + &state_, target); + if (!texture_ref) { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, + "glTexStorage3D", "unknown texture for target"); + return; + } + Texture* texture = texture_ref->texture(); + if (texture->IsAttachedToFramebuffer()) { + framebuffer_state_.clear_state_dirty = true; + } + if (texture->IsImmutable()) { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, "glTexStorage3D", "texture is immutable"); + return; + } + + GLenum format = TextureManager::ExtractFormatFromStorageFormat( + internal_format); + GLenum type = TextureManager::ExtractTypeFromStorageFormat(internal_format); + + { + GLsizei level_width = width; + GLsizei level_height = height; + GLsizei level_depth = depth; + uint32_t estimated_size = 0; + for (int ii = 0; ii < levels; ++ii) { + uint32_t level_size = 0; + if (!GLES2Util::ComputeImageDataSizes( + level_width, level_height, level_depth, format, type, + state_.unpack_alignment, + &estimated_size, NULL, NULL) || + !SafeAddUint32(estimated_size, level_size, &estimated_size)) { + LOCAL_SET_GL_ERROR( + GL_OUT_OF_MEMORY, "glTexStorage3D", "dimensions too large"); + return; + } + level_width = std::max(1, level_width >> 1); + level_height = std::max(1, level_height >> 1); + if (target == GL_TEXTURE_3D) + level_depth = std::max(1, level_depth >> 1); + } + if (!EnsureGPUMemoryAvailable(estimated_size)) { + LOCAL_SET_GL_ERROR( + GL_OUT_OF_MEMORY, "glTexStorage3D", "out of memory"); + return; + } + } + + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage3D"); + glTexStorage3D(target, levels, internal_format, width, height, depth); + GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage3D"); + if (error == GL_NO_ERROR) { + GLsizei level_width = width; + GLsizei level_height = height; + GLsizei level_depth = depth; + + GLenum cur_format = feature_info_->IsES3Enabled() ? + internal_format : format; + for (int ii = 0; ii < levels; ++ii) { + // TODO(zmo): Implement clearing of 3D textures. crbug.com/597201. + texture_manager()->SetLevelInfo(texture_ref, target, ii, cur_format, + level_width, level_height, level_depth, 0, + format, type, + gfx::Rect(level_width, level_height)); + level_width = std::max(1, level_width >> 1); + level_height = std::max(1, level_height >> 1); + if (target == GL_TEXTURE_3D) + level_depth = std::max(1, level_depth >> 1); + } + texture->SetImmutable(true); + } +} + error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM( uint32_t immediate_data_size, const void* cmd_data) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index 510ced0..a8f03ab 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -2902,7 +2902,7 @@ error::Error GLES2DecoderImpl::HandleTexStorage3D(uint32_t immediate_data_size, GLsizei width = static_cast<GLsizei>(c.width); GLsizei height = static_cast<GLsizei>(c.height); GLsizei depth = static_cast<GLsizei>(c.depth); - glTexStorage3D(target, levels, internalFormat, width, height, depth); + DoTexStorage3D(target, levels, internalFormat, width, height, depth); return error::kNoError; } diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h index f1241ea..417b4ea 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h @@ -1211,18 +1211,6 @@ TEST_P(GLES2DecoderTest2, TexParameterivImmediateInvalidArgs1_0) { EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_P(GLES2DecoderTest2, TexStorage3DValidArgs) { - EXPECT_CALL(*gl_, TexStorage3D(GL_TEXTURE_3D, 2, GL_RGB565, 4, 5, 6)); - SpecializedSetup<cmds::TexStorage3D, 0>(true); - cmds::TexStorage3D cmd; - cmd.Init(GL_TEXTURE_3D, 2, GL_RGB565, 4, 5, 6); - decoder_->set_unsafe_es3_apis_enabled(true); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - decoder_->set_unsafe_es3_apis_enabled(false); - EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); -} - TEST_P(GLES2DecoderTest2, TransformFeedbackVaryingsBucketValidArgs) { const uint32_t kBucketId = 123; const char kSource0[] = "hello"; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index b6285b7..bf6d9d1 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -1250,6 +1250,33 @@ void GLES2DecoderTestBase::DoCompressedTexImage2D(GLenum target, EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); } +void GLES2DecoderTestBase::DoTexImage3D(GLenum target, + GLint level, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + uint32_t shared_memory_id, + uint32_t shared_memory_offset) { + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, TexImage3D(target, level, internal_format, + width, height, depth, border, format, type, _)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + cmds::TexImage3D cmd; + cmd.Init(target, level, internal_format, width, height, depth, format, type, + shared_memory_id, shared_memory_offset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + void GLES2DecoderTestBase::DoRenderbufferStorage( GLenum target, GLenum internal_format, GLenum actual_format, GLsizei width, GLsizei height, GLenum error) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h index 1e08254..fddfdf1 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h @@ -327,6 +327,17 @@ class GLES2DecoderTestBase : public ::testing::TestWithParam<bool> { uint32_t shared_memory_id, uint32_t shared_memory_offset, GLenum expected_internal_format); + void DoTexImage3D(GLenum target, + GLint level, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + uint32_t shared_memory_id, + uint32_t shared_memory_offset); void DoRenderbufferStorage( GLenum target, GLenum internal_format, GLenum actual_format, GLsizei width, GLsizei height, GLenum error); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc index 24f6584..b91ceeb 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc @@ -3356,6 +3356,36 @@ TEST_P(GLES2DecoderManualInitTest, GetNoCompressedTextureFormats) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } +TEST_P(GLES3DecoderTest, TexStorage3DValidArgs) { + DoBindTexture(GL_TEXTURE_3D, client_texture_id_, kServiceTextureId); + EXPECT_CALL(*gl_, TexStorage3D(GL_TEXTURE_3D, 2, GL_RGB565, 4, 5, 6)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + cmds::TexStorage3D cmd; + cmd.Init(GL_TEXTURE_3D, 2, GL_RGB565, 4, 5, 6); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES3DecoderTest, TexImage3DValidArgs) { + const GLenum kTarget = GL_TEXTURE_3D; + const GLint kLevel = 2; + const GLint kInternalFormat = GL_RGBA8; + const GLsizei kWidth = 2; + const GLsizei kHeight = 2; + const GLsizei kDepth = 2; + const GLenum kFormat = GL_RGBA; + const GLenum kType = GL_UNSIGNED_BYTE; + + DoBindTexture(GL_TEXTURE_3D, client_texture_id_, kServiceTextureId); + DoTexImage3D(kTarget, kLevel, kInternalFormat, kWidth, kHeight, kDepth, 0, + kFormat, kType, kSharedMemoryId, kSharedMemoryOffset); +} + // TODO(gman): Complete this test. // TEST_P(GLES2DecoderTest, CompressedTexImage2DGLError) { // } diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index 9ad7937..9bdcb96 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc @@ -1850,9 +1850,12 @@ GLsizei TextureManager::ComputeMipMapCount(GLenum target, switch (target) { case GL_TEXTURE_EXTERNAL_OES: return 1; - default: + case GL_TEXTURE_3D: return 1 + base::bits::Log2Floor(std::max(std::max(width, height), depth)); + default: + return 1 + + base::bits::Log2Floor(std::max(width, height)); } } @@ -2127,7 +2130,10 @@ bool TextureManager::ValidateTexSubImage(ContextState* state, ErrorState* error_state = state->GetErrorState(); const Validators* validators = feature_info_->validators(); - if (!validators->texture_target.IsValid(args.target)) { + if ((args.command_type == DoTexSubImageArguments::kTexSubImage2D && + !validators->texture_target.IsValid(args.target)) || + (args.command_type == DoTexSubImageArguments::kTexSubImage3D && + !validators->texture_3_d_target.IsValid(args.target))) { ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(error_state, function_name, args.target, "target"); return false; @@ -2142,6 +2148,11 @@ bool TextureManager::ValidateTexSubImage(ContextState* state, "height < 0"); return false; } + if (args.depth < 0) { + ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, + "depth < 0"); + return false; + } TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target); if (!local_texture_ref) { ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name, @@ -2162,12 +2173,15 @@ bool TextureManager::ValidateTexSubImage(ContextState* state, return false; } if (args.type != current_type && !feature_info_->IsES3Enabled()) { + // It isn't explicitly required in the ES2 spec, but some drivers generate + // an error. It is better to be consistent across drivers. ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name, "type does not match type of texture."); return false; } - if (!texture->ValidForTexture(args.target, args.level, args.xoffset, - args.yoffset, 0, args.width, args.height, 1)) { + if (!texture->ValidForTexture(args.target, args.level, + args.xoffset, args.yoffset, args.zoffset, + args.width, args.height, args.depth)) { ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, "bad dimensions."); return false; @@ -2201,11 +2215,14 @@ void TextureManager::ValidateAndDoTexSubImage( Texture* texture = texture_ref->texture(); GLsizei tex_width = 0; GLsizei tex_height = 0; + GLsizei tex_depth = 0; bool ok = texture->GetLevelSize(args.target, args.level, &tex_width, - &tex_height, nullptr); + &tex_height, &tex_depth); DCHECK(ok); - if (args.xoffset != 0 || args.yoffset != 0 || args.width != tex_width || - args.height != tex_height) { + if (args.xoffset != 0 || args.yoffset != 0 || args.zoffset != 0 || + args.width != tex_width || args.height != tex_height || + args.depth != tex_depth) { + // TODO(zmo): Implement clearing of 3D textures. crbug.com/597201. gfx::Rect cleared_rect; if (CombineAdjacentRects( texture->GetLevelClearedRect(args.target, args.level), @@ -2220,15 +2237,21 @@ void TextureManager::ValidateAndDoTexSubImage( // Otherwise clear part of texture level that is not already cleared. if (!ClearTextureLevel(decoder, texture_ref, args.target, args.level)) { ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, - "glTexSubImage2D", "dimensions too big"); + function_name, "dimensions too big"); return; } } ScopedTextureUploadTimer timer(texture_state); - glTexSubImage2D(args.target, args.level, args.xoffset, args.yoffset, - args.width, args.height, AdjustTexFormat(args.format), - args.type, args.pixels); - return; + if (args.command_type == DoTexSubImageArguments::kTexSubImage3D) { + glTexSubImage3D(args.target, args.level, args.xoffset, args.yoffset, + args.zoffset, args.width, args.height, args.depth, + AdjustTexFormat(args.format), args.type, args.pixels); + } else { + glTexSubImage2D(args.target, args.level, args.xoffset, args.yoffset, + args.width, args.height, AdjustTexFormat(args.format), + args.type, args.pixels); + return; + } } if (!texture_state->texsubimage_faster_than_teximage && @@ -2237,16 +2260,28 @@ void TextureManager::ValidateAndDoTexSubImage( GLenum internal_format; GLenum tex_type; texture->GetLevelType(args.target, args.level, &tex_type, &internal_format); - // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need + // NOTE: In OpenGL ES 2/3 border is always zero. If that changes we'll need // to look it up. - glTexImage2D(args.target, args.level, internal_format, args.width, - args.height, 0, AdjustTexFormat(args.format), args.type, - args.pixels); + if (args.command_type == DoTexSubImageArguments::kTexSubImage3D) { + glTexImage3D(args.target, args.level, internal_format, args.width, + args.height, args.depth, 0, AdjustTexFormat(args.format), + args.type, args.pixels); + } else { + glTexImage2D(args.target, args.level, internal_format, args.width, + args.height, 0, AdjustTexFormat(args.format), args.type, + args.pixels); + } } else { ScopedTextureUploadTimer timer(texture_state); - glTexSubImage2D(args.target, args.level, args.xoffset, args.yoffset, - args.width, args.height, AdjustTexFormat(args.format), - args.type, args.pixels); + if (args.command_type == DoTexSubImageArguments::kTexSubImage3D) { + glTexSubImage3D(args.target, args.level, args.xoffset, args.yoffset, + args.zoffset, args.width, args.height, args.depth, + AdjustTexFormat(args.format), args.type, args.pixels); + } else { + glTexSubImage2D(args.target, args.level, args.xoffset, args.yoffset, + args.width, args.height, AdjustTexFormat(args.format), + args.type, args.pixels); + } } SetLevelCleared(texture_ref, args.target, args.level, true); return; @@ -2287,9 +2322,13 @@ void TextureManager::DoTexImage( if (level_is_same && !args.pixels) { // Just set the level texture but mark the texture as uncleared. - SetLevelInfo(texture_ref, args.target, args.level, args.internal_format, - args.width, args.height, args.depth, args.border, args.format, - args.type, gfx::Rect()); + // TODO(zmo): Implement clearing of 3D textures. crbug.com/597201. + bool set_as_cleared = + (args.command_type == DoTexImageArguments::kTexImage3D); + SetLevelInfo( + texture_ref, args.target, args.level, args.internal_format, args.width, + args.height, args.depth, args.border, args.format, args.type, + set_as_cleared ? gfx::Rect(args.width, args.height) : gfx::Rect()); texture_state->tex_image_failed = false; return; } @@ -2340,10 +2379,13 @@ void TextureManager::DoTexImage( GetAllGLErrors()); } if (error == GL_NO_ERROR) { + // TODO(zmo): Implement clearing of 3D textures. crbug.com/597201. + bool set_as_cleared = (args.pixels != nullptr || + args.command_type == DoTexImageArguments::kTexImage3D); SetLevelInfo( texture_ref, args.target, args.level, args.internal_format, args.width, args.height, args.depth, args.border, args.format, args.type, - args.pixels != NULL ? gfx::Rect(args.width, args.height) : gfx::Rect()); + set_as_cleared ? gfx::Rect(args.width, args.height) : gfx::Rect()); texture_state->tex_image_failed = false; } } diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h index 1f1e58d..03b4598 100644 --- a/gpu/command_buffer/service/texture_manager.h +++ b/gpu/command_buffer/service/texture_manager.h @@ -910,17 +910,24 @@ class GPU_EXPORT TextureManager : public base::trace_event::MemoryDumpProvider { const DoTexImageArguments& args); struct DoTexSubImageArguments { + enum TexSubImageCommandType { + kTexSubImage2D, + kTexSubImage3D, + }; + GLenum target; GLint level; GLint xoffset; GLint yoffset; + GLint zoffset; GLsizei width; GLsizei height; + GLsizei depth; GLenum format; GLenum type; const void* pixels; uint32_t pixels_size; - // TODO(kkinnunen): currently this is used only for TexSubImage2D. + TexSubImageCommandType command_type; }; bool ValidateTexSubImage( |