summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzmo <zmo@chromium.org>2016-02-16 18:07:25 -0800
committerCommit bot <commit-bot@chromium.org>2016-02-17 02:08:24 +0000
commitec8cab4d9895568bb2c682556efdcc3aa08ab818 (patch)
treed84d3abb81b26ab3efd97b9009760bbe76e17fd1
parent13db724fd2cd536b1331dc6c36b135f15b3f112c (diff)
downloadchromium_src-ec8cab4d9895568bb2c682556efdcc3aa08ab818.zip
chromium_src-ec8cab4d9895568bb2c682556efdcc3aa08ab818.tar.gz
chromium_src-ec8cab4d9895568bb2c682556efdcc3aa08ab818.tar.bz2
Upgrade TexSubImage3D and TexStorage3D.
BUG=429053 TEST=gpu_unittests,webgl2_conformance R=piman@chromium.org CQ_INCLUDE_TRYBOTS=tryserver.chromium.win:win_optional_gpu_tests_rel Review URL: https://codereview.chromium.org/1684343002 Cr-Commit-Position: refs/heads/master@{#375752}
-rw-r--r--content/test/gpu/gpu_tests/webgl2_conformance_expectations.py4
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py2
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc200
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_autogen.h2
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h12
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc27
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h11
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc30
-rw-r--r--gpu/command_buffer/service/texture_manager.cc88
-rw-r--r--gpu/command_buffer/service/texture_manager.h9
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(