Index: gpu/command_buffer/service/gles2_cmd_decoder.cc |
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
index ddde508545de014f8f11dfcdd643fd8400d9f612..bd7bed5278f045b9e79c7fbbed2eba291918d3fc 100644 |
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc |
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
@@ -862,19 +862,8 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { |
void MarkDrawBufferAsCleared(GLenum buffer, GLint drawbuffer_i); |
- // Wrapper for CompressedTexImage2D commands. |
- error::Error DoCompressedTexImage2D( |
- GLenum target, |
- GLint level, |
- GLenum internal_format, |
- GLsizei width, |
- GLsizei height, |
- GLint border, |
- GLsizei image_size, |
- const void* data); |
- |
- // Wrapper for CompressedTexImage3D commands. |
- error::Error DoCompressedTexImage3D( |
+ // Wrapper for CompressedTexImage{2|3}D commands. |
+ error::Error DoCompressedTexImage( |
GLenum target, |
GLint level, |
GLenum internal_format, |
@@ -883,22 +872,11 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { |
GLsizei depth, |
GLint border, |
GLsizei image_size, |
- const void* data); |
- |
- // Wrapper for CompressedTexSubImage2D. |
- void DoCompressedTexSubImage2D( |
- GLenum target, |
- GLint level, |
- GLint xoffset, |
- GLint yoffset, |
- GLsizei width, |
- GLsizei height, |
- GLenum format, |
- GLsizei imageSize, |
- const void* data); |
+ const void* data, |
+ ContextState::Dimension dimension); |
- // Wrapper for CompressedTexSubImage3D. |
- void DoCompressedTexSubImage3D( |
+ // Wrapper for CompressedTexSubImage{2|3}D. |
+ error::Error DoCompressedTexSubImage( |
GLenum target, |
GLint level, |
GLint xoffset, |
@@ -908,8 +886,9 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { |
GLsizei height, |
GLsizei depth, |
GLenum format, |
- GLsizei image_size, |
- const void* data); |
+ GLsizei imageSize, |
+ const void* data, |
+ ContextState::Dimension dimension); |
// Validate if |format| is valid for CopyTex{Sub}Image functions. |
// If not, generate a GL error and return false. |
@@ -13050,14 +13029,18 @@ error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket( |
GLsizei height = static_cast<GLsizei>(c.height); |
GLuint bucket_id = static_cast<GLuint>(c.bucket_id); |
GLint border = static_cast<GLint>(c.border); |
+ |
+ if (state_.bound_pixel_unpack_buffer.get()) { |
+ return error::kInvalidArguments; |
+ } |
Bucket* bucket = GetBucket(bucket_id); |
if (!bucket) |
return error::kInvalidArguments; |
uint32_t image_size = bucket->size(); |
const void* data = bucket->GetData(0, image_size); |
DCHECK(data || !image_size); |
- return DoCompressedTexImage2D(target, level, internal_format, width, height, |
- border, image_size, data); |
+ return DoCompressedTexImage(target, level, internal_format, width, height, 1, |
+ border, image_size, data, ContextState::k2D); |
} |
error::Error GLES2DecoderImpl::HandleCompressedTexImage2D( |
@@ -13071,7 +13054,6 @@ error::Error GLES2DecoderImpl::HandleCompressedTexImage2D( |
GLsizei height = static_cast<GLsizei>(c.height); |
GLint border = static_cast<GLint>(c.border); |
GLsizei image_size = static_cast<GLsizei>(c.imageSize); |
- uint32_t data_size = image_size; |
uint32_t data_shm_id = c.data_shm_id; |
uint32_t data_shm_offset = c.data_shm_offset; |
@@ -13086,26 +13068,172 @@ error::Error GLES2DecoderImpl::HandleCompressedTexImage2D( |
return error::kInvalidArguments; |
} |
data = GetSharedMemoryAs<const void*>( |
- data_shm_id, data_shm_offset, data_size); |
+ data_shm_id, data_shm_offset, image_size); |
} |
- return DoCompressedTexImage2D(target, level, internal_format, width, height, |
- border, image_size, data); |
+ return DoCompressedTexImage(target, level, internal_format, width, height, 1, |
+ border, image_size, data, ContextState::k2D); |
} |
-error::Error GLES2DecoderImpl::DoCompressedTexImage2D( |
- GLenum target, GLint level, GLenum internal_format, GLsizei width, |
- GLsizei height, GLint border, GLsizei image_size, const void* data) { |
- const char* func_name = "glCompressedTexImage2D"; |
- if (!validators_->texture_target.IsValid(target)) { |
- LOCAL_SET_GL_ERROR_INVALID_ENUM(func_name, target, "target"); |
- return error::kNoError; |
+error::Error GLES2DecoderImpl::HandleCompressedTexImage3DBucket( |
+ uint32_t immediate_data_size, const volatile void* cmd_data) { |
+ if (!unsafe_es3_apis_enabled()) |
+ return error::kUnknownCommand; |
+ const volatile gles2::cmds::CompressedTexImage3DBucket& c = |
+ *static_cast<const volatile gles2::cmds::CompressedTexImage3DBucket*>( |
+ cmd_data); |
+ GLenum target = static_cast<GLenum>(c.target); |
+ GLint level = static_cast<GLint>(c.level); |
+ GLenum internal_format = static_cast<GLenum>(c.internalformat); |
+ GLsizei width = static_cast<GLsizei>(c.width); |
+ GLsizei height = static_cast<GLsizei>(c.height); |
+ GLsizei depth = static_cast<GLsizei>(c.depth); |
+ GLuint bucket_id = static_cast<GLuint>(c.bucket_id); |
+ GLint border = static_cast<GLint>(c.border); |
+ |
+ if (state_.bound_pixel_unpack_buffer.get()) { |
+ return error::kInvalidArguments; |
} |
- // TODO(ccameron): Add a separate texture from |texture_target| for |
- // [Compressed]Tex[Sub]Image2D and related functions. |
- // http://crbug.com/536854 |
- if (target == GL_TEXTURE_RECTANGLE_ARB) { |
- LOCAL_SET_GL_ERROR_INVALID_ENUM(func_name, target, "target"); |
- return error::kNoError; |
+ Bucket* bucket = GetBucket(bucket_id); |
+ if (!bucket) |
+ return error::kInvalidArguments; |
+ uint32_t image_size = bucket->size(); |
+ const void* data = bucket->GetData(0, image_size); |
+ DCHECK(data || !image_size); |
+ return DoCompressedTexImage(target, level, internal_format, width, height, |
+ depth, border, image_size, data, |
+ ContextState::k3D); |
+} |
+ |
+error::Error GLES2DecoderImpl::HandleCompressedTexImage3D( |
+ uint32_t immediate_data_size, const volatile void* cmd_data) { |
+ if (!unsafe_es3_apis_enabled()) |
+ return error::kUnknownCommand; |
+ const volatile gles2::cmds::CompressedTexImage3D& c = |
+ *static_cast<const volatile gles2::cmds::CompressedTexImage3D*>(cmd_data); |
+ GLenum target = static_cast<GLenum>(c.target); |
+ GLint level = static_cast<GLint>(c.level); |
+ GLenum internal_format = static_cast<GLenum>(c.internalformat); |
+ GLsizei width = static_cast<GLsizei>(c.width); |
+ GLsizei height = static_cast<GLsizei>(c.height); |
+ GLsizei depth = static_cast<GLsizei>(c.depth); |
+ GLint border = static_cast<GLint>(c.border); |
+ GLsizei image_size = static_cast<GLsizei>(c.imageSize); |
+ uint32_t data_shm_id = c.data_shm_id; |
+ uint32_t data_shm_offset = c.data_shm_offset; |
+ |
+ const void* data; |
+ if (state_.bound_pixel_unpack_buffer.get()) { |
+ if (data_shm_id) { |
+ return error::kInvalidArguments; |
+ } |
+ data = reinterpret_cast<const void*>(data_shm_offset); |
+ } else { |
+ if (!data_shm_id && data_shm_offset) { |
+ return error::kInvalidArguments; |
+ } |
+ data = GetSharedMemoryAs<const void*>( |
+ data_shm_id, data_shm_offset, image_size); |
+ } |
+ return DoCompressedTexImage(target, level, internal_format, width, height, |
+ depth, border, image_size, data, |
+ ContextState::k3D); |
+} |
+ |
+error::Error GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket( |
+ uint32_t immediate_data_size, const volatile void* cmd_data) { |
+ if (!unsafe_es3_apis_enabled()) |
+ return error::kUnknownCommand; |
+ const volatile gles2::cmds::CompressedTexSubImage3DBucket& c = |
+ *static_cast<const volatile gles2::cmds::CompressedTexSubImage3DBucket*>( |
+ cmd_data); |
+ GLenum target = static_cast<GLenum>(c.target); |
+ GLint level = static_cast<GLint>(c.level); |
+ GLint xoffset = static_cast<GLint>(c.xoffset); |
+ GLint yoffset = static_cast<GLint>(c.yoffset); |
+ GLint zoffset = static_cast<GLint>(c.zoffset); |
+ GLsizei width = static_cast<GLsizei>(c.width); |
+ GLsizei height = static_cast<GLsizei>(c.height); |
+ GLsizei depth = static_cast<GLsizei>(c.depth); |
+ GLenum format = static_cast<GLenum>(c.format); |
+ GLuint bucket_id = static_cast<GLuint>(c.bucket_id); |
+ |
+ if (state_.bound_pixel_unpack_buffer.get()) { |
+ return error::kInvalidArguments; |
+ } |
+ Bucket* bucket = GetBucket(bucket_id); |
+ if (!bucket) |
+ return error::kInvalidArguments; |
+ uint32_t image_size = bucket->size(); |
+ const void* data = bucket->GetData(0, image_size); |
+ DCHECK(data || !image_size); |
+ return DoCompressedTexSubImage(target, level, xoffset, yoffset, zoffset, |
+ width, height, depth, format, image_size, |
+ data, ContextState::k3D); |
+} |
+ |
+error::Error GLES2DecoderImpl::HandleCompressedTexSubImage3D( |
+ uint32_t immediate_data_size, const volatile void* cmd_data) { |
+ if (!unsafe_es3_apis_enabled()) |
+ return error::kUnknownCommand; |
+ const volatile gles2::cmds::CompressedTexSubImage3D& c = |
+ *static_cast<const volatile gles2::cmds::CompressedTexSubImage3D*>( |
+ cmd_data); |
+ GLenum target = static_cast<GLenum>(c.target); |
+ GLint level = static_cast<GLint>(c.level); |
+ GLint xoffset = static_cast<GLint>(c.xoffset); |
+ GLint yoffset = static_cast<GLint>(c.yoffset); |
+ GLint zoffset = static_cast<GLint>(c.zoffset); |
+ GLsizei width = static_cast<GLsizei>(c.width); |
+ GLsizei height = static_cast<GLsizei>(c.height); |
+ GLsizei depth = static_cast<GLsizei>(c.depth); |
+ GLenum format = static_cast<GLenum>(c.format); |
+ GLsizei image_size = static_cast<GLsizei>(c.imageSize); |
+ uint32_t data_shm_id = c.data_shm_id; |
+ uint32_t data_shm_offset = c.data_shm_offset; |
+ |
+ const void* data; |
+ if (state_.bound_pixel_unpack_buffer.get()) { |
+ if (data_shm_id) { |
+ return error::kInvalidArguments; |
+ } |
+ data = reinterpret_cast<const void*>(data_shm_offset); |
+ } else { |
+ if (!data_shm_id && data_shm_offset) { |
+ return error::kInvalidArguments; |
+ } |
+ data = GetSharedMemoryAs<const void*>( |
+ data_shm_id, data_shm_offset, image_size); |
+ } |
+ return DoCompressedTexSubImage(target, level, xoffset, yoffset, zoffset, |
+ width, height, depth, format, image_size, |
+ data, ContextState::k3D); |
+} |
+ |
+error::Error GLES2DecoderImpl::DoCompressedTexImage( |
+ GLenum target, GLint level, GLenum internal_format, GLsizei width, |
+ GLsizei height, GLsizei depth, GLint border, GLsizei image_size, |
+ const void* data, ContextState::Dimension dimension) { |
+ const char* func_name; |
+ if (dimension == ContextState::k2D) { |
+ func_name = "glCompressedTexImage2D"; |
+ if (!validators_->texture_target.IsValid(target)) { |
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(func_name, target, "target"); |
+ return error::kNoError; |
+ } |
+ // TODO(ccameron): Add a separate texture from |texture_target| for |
+ // [Compressed]Tex[Sub]Image2D and related functions. |
+ // http://crbug.com/536854 |
+ if (target == GL_TEXTURE_RECTANGLE_ARB) { |
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(func_name, target, "target"); |
+ return error::kNoError; |
+ } |
+ } else { |
+ DCHECK_EQ(ContextState::k3D, dimension); |
+ func_name = "glCompressedTexImage3D"; |
+ if (!validators_->texture_3_d_target.IsValid(target)) { |
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(func_name, target, "target"); |
+ return error::kNoError; |
+ } |
} |
if (!validators_->compressed_texture_format.IsValid(internal_format)) { |
LOCAL_SET_GL_ERROR_INVALID_ENUM( |
@@ -13116,7 +13244,7 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage2D( |
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "imageSize < 0"); |
return error::kNoError; |
} |
- if (!texture_manager()->ValidForTarget(target, level, width, height, 1) || |
+ if (!texture_manager()->ValidForTarget(target, level, width, height, depth) || |
border != 0) { |
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "dimensions out of range"); |
return error::kNoError; |
@@ -13133,9 +13261,10 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage2D( |
LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, "texture is immutable"); |
return error::kNoError; |
} |
+ |
if (!ValidateCompressedTexDimensions(func_name, target, level, |
- width, height, 1, internal_format) || |
- !ValidateCompressedTexFuncData(func_name, width, height, 1, |
+ width, height, depth, internal_format) || |
+ !ValidateCompressedTexFuncData(func_name, width, height, depth, |
internal_format, image_size, data)) { |
return error::kNoError; |
} |
@@ -13156,97 +13285,6 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage2D( |
data = zero.get(); |
} |
LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(func_name); |
- |
- const CompressedFormatInfo* format_info = |
- GetCompressedFormatInfo(internal_format); |
- if (format_info != nullptr && !format_info->support_check(*feature_info_)) { |
- std::unique_ptr<uint8_t[]> decompressed_data = DecompressTextureData( |
- state_, *format_info, width, height, 1, image_size, data); |
- if (!decompressed_data) { |
- MarkContextLost(error::kGuilty); |
- group_->LoseContexts(error::kInnocent); |
- return error::kLostContext; |
- } |
- state_.PushTextureDecompressionUnpackState(); |
- glTexImage2D(target, level, format_info->decompressed_internal_format, |
- width, height, border, format_info->decompressed_format, |
- format_info->decompressed_type, decompressed_data.get()); |
- state_.RestoreUnpackState(); |
- } else { |
- glCompressedTexImage2D(target, level, internal_format, width, height, |
- border, image_size, data); |
- } |
- GLenum error = LOCAL_PEEK_GL_ERROR(func_name); |
- if (error == GL_NO_ERROR) { |
- texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format, |
- width, height, 1, border, 0, 0, |
- gfx::Rect(width, height)); |
- } |
- |
- // 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::DoCompressedTexImage3D( |
- GLenum target, |
- GLint level, |
- GLenum internal_format, |
- GLsizei width, |
- GLsizei height, |
- GLsizei depth, |
- GLint border, |
- GLsizei image_size, |
- const void* data) { |
- if (!texture_manager()->ValidForTarget(target, level, width, height, depth) || |
- border != 0) { |
- LOCAL_SET_GL_ERROR( |
- GL_INVALID_VALUE, |
- "glCompressedTexImage3D", "dimensions out of range"); |
- return error::kNoError; |
- } |
- TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( |
- &state_, target); |
- if (!texture_ref) { |
- LOCAL_SET_GL_ERROR( |
- GL_INVALID_VALUE, |
- "glCompressedTexImage3D", "unknown texture target"); |
- return error::kNoError; |
- } |
- Texture* texture = texture_ref->texture(); |
- if (texture->IsImmutable()) { |
- LOCAL_SET_GL_ERROR( |
- GL_INVALID_OPERATION, |
- "glCompressedTexImage3D", "texture is immutable"); |
- return error::kNoError; |
- } |
- |
- if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target, level, |
- width, height, depth, internal_format) || |
- !ValidateCompressedTexFuncData("glCompressedTexImage3D", width, height, |
- depth, internal_format, image_size, |
- data)) { |
- return error::kNoError; |
- } |
- |
- if (!EnsureGPUMemoryAvailable(image_size)) { |
- LOCAL_SET_GL_ERROR( |
- GL_OUT_OF_MEMORY, "glCompressedTexImage3D", "out of memory"); |
- return error::kNoError; |
- } |
- |
- if (texture->IsAttachedToFramebuffer()) { |
- framebuffer_state_.clear_state_dirty = true; |
- } |
- |
- std::unique_ptr<int8_t[]> zero; |
- if (!state_.bound_pixel_unpack_buffer && !data) { |
- zero.reset(new int8_t[image_size]); |
- memset(zero.get(), 0, image_size); |
- data = zero.get(); |
- } |
- LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D"); |
const CompressedFormatInfo* format_info = |
GetCompressedFormatInfo(internal_format); |
if (format_info != nullptr && !format_info->support_check(*feature_info_)) { |
@@ -13258,15 +13296,27 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage3D( |
return error::kLostContext; |
} |
state_.PushTextureDecompressionUnpackState(); |
- glTexImage3D(target, level, format_info->decompressed_internal_format, |
- width, height, depth, border, format_info->decompressed_format, |
- format_info->decompressed_type, decompressed_data.get()); |
+ if (dimension == ContextState::k2D) { |
+ glTexImage2D(target, level, format_info->decompressed_internal_format, |
+ width, height, border, format_info->decompressed_format, |
+ format_info->decompressed_type, decompressed_data.get()); |
+ } else { |
+ glTexImage3D( |
+ target, level, format_info->decompressed_internal_format, |
+ width, height, depth, border, format_info->decompressed_format, |
+ format_info->decompressed_type, decompressed_data.get()); |
+ } |
state_.RestoreUnpackState(); |
} else { |
- glCompressedTexImage3D(target, level, internal_format, width, height, depth, |
- border, image_size, data); |
+ if (dimension == ContextState::k2D) { |
+ glCompressedTexImage2D(target, level, internal_format, width, height, |
+ border, image_size, data); |
+ } else { |
+ glCompressedTexImage3D(target, level, internal_format, width, height, |
+ depth, border, image_size, data); |
+ } |
} |
- GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D"); |
+ GLenum error = LOCAL_PEEK_GL_ERROR(func_name); |
if (error == GL_NO_ERROR) { |
texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format, |
width, height, depth, border, 0, 0, |
@@ -13279,81 +13329,6 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage3D( |
return error::kNoError; |
} |
-void GLES2DecoderImpl::DoCompressedTexSubImage3D( |
- GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, |
- GLsizei width, GLsizei height, GLsizei depth, GLenum format, |
- GLsizei image_size, const void* data) { |
- if (!texture_manager()->ValidForTarget(target, level, width, height, depth)) { |
- LOCAL_SET_GL_ERROR( |
- GL_INVALID_VALUE, |
- "glCompressedTexSubImage3D", "dimensions out of range"); |
- return; |
- } |
- TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( |
- &state_, target); |
- if (!texture_ref) { |
- LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D", |
- "unknown texture for target"); |
- return; |
- } |
- Texture* texture = texture_ref->texture(); |
- GLenum type = 0, internal_format = 0; |
- if (!texture->GetLevelType(target, level, &type, &internal_format)) { |
- std::string msg = base::StringPrintf( |
- "level %d does not exist", level); |
- LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D", |
- msg.c_str()); |
- return; |
- } |
- if (internal_format != format) { |
- LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D", |
- "format does not match internal format"); |
- return; |
- } |
- if (!texture->ValidForTexture(target, level, xoffset, yoffset, zoffset, |
- width, height, depth)) { |
- LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedTexSubImage3D", |
- "bad dimensions"); |
- return; |
- } |
- if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D", width, height, |
- depth, format, image_size, data) || |
- !ValidateCompressedTexSubDimensions( |
- "glCompressedTexSubImage3D", target, level, xoffset, yoffset, zoffset, |
- width, height, depth, format, texture)) { |
- return; |
- } |
- |
- // Note: There is no need to deal with texture cleared tracking here |
- // because the validation above means you can only get here if the level |
- // is already a matching compressed format and in that case |
- // CompressedTexImage3D already cleared the texture. |
- |
- const CompressedFormatInfo* format_info = |
- GetCompressedFormatInfo(internal_format); |
- if (format_info != nullptr && !format_info->support_check(*feature_info_)) { |
- std::unique_ptr<uint8_t[]> decompressed_data = DecompressTextureData( |
- state_, *format_info, width, height, depth, image_size, data); |
- if (!decompressed_data) { |
- MarkContextLost(error::kGuilty); |
- group_->LoseContexts(error::kInnocent); |
- return; |
- } |
- state_.PushTextureDecompressionUnpackState(); |
- glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, |
- depth, format_info->decompressed_format, |
- format_info->decompressed_type, decompressed_data.get()); |
- state_.RestoreUnpackState(); |
- } else { |
- glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, |
- height, depth, format, image_size, data); |
- } |
- |
- // This may be a slow command. Exit command processing to allow for |
- // context preemption and GPU watchdog checks. |
- ExitCommandProcessingEarly(); |
-} |
- |
error::Error GLES2DecoderImpl::HandleTexImage2D(uint32_t immediate_data_size, |
const volatile void* cmd_data) { |
const char* func_name = "glTexImage2D"; |
@@ -13540,95 +13515,175 @@ error::Error GLES2DecoderImpl::HandleTexImage3D(uint32_t immediate_data_size, |
return error::kNoError; |
} |
-void GLES2DecoderImpl::DoCompressedTexSubImage2D( |
- GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, |
- GLsizei height, GLenum format, GLsizei image_size, const void * data) { |
+error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket( |
+ uint32_t immediate_data_size, const volatile void* cmd_data) { |
+ const volatile gles2::cmds::CompressedTexSubImage2DBucket& c = |
+ *static_cast<const volatile gles2::cmds::CompressedTexSubImage2DBucket*>( |
+ cmd_data); |
+ GLenum target = static_cast<GLenum>(c.target); |
+ GLint level = static_cast<GLint>(c.level); |
+ GLint xoffset = static_cast<GLint>(c.xoffset); |
+ GLint yoffset = static_cast<GLint>(c.yoffset); |
+ GLsizei width = static_cast<GLsizei>(c.width); |
+ GLsizei height = static_cast<GLsizei>(c.height); |
+ GLenum format = static_cast<GLenum>(c.format); |
+ GLuint bucket_id = static_cast<GLuint>(c.bucket_id); |
+ |
+ if (state_.bound_pixel_unpack_buffer.get()) { |
+ return error::kInvalidArguments; |
+ } |
+ Bucket* bucket = GetBucket(bucket_id); |
+ if (!bucket) |
+ return error::kInvalidArguments; |
+ uint32_t image_size = bucket->size(); |
+ const void* data = bucket->GetData(0, image_size); |
+ DCHECK(data || !image_size); |
+ return DoCompressedTexSubImage(target, level, xoffset, yoffset, 0, |
+ width, height, 1, format, image_size, data, |
+ ContextState::k2D); |
+} |
+ |
+error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2D( |
+ uint32_t immediate_data_size, |
+ const volatile void* cmd_data) { |
+ const volatile gles2::cmds::CompressedTexSubImage2D& c = |
+ *static_cast<const volatile gles2::cmds::CompressedTexSubImage2D*>( |
+ cmd_data); |
+ GLenum target = static_cast<GLenum>(c.target); |
+ GLint level = static_cast<GLint>(c.level); |
+ GLint xoffset = static_cast<GLint>(c.xoffset); |
+ GLint yoffset = static_cast<GLint>(c.yoffset); |
+ GLsizei width = static_cast<GLsizei>(c.width); |
+ GLsizei height = static_cast<GLsizei>(c.height); |
+ GLenum format = static_cast<GLenum>(c.format); |
+ GLsizei image_size = static_cast<GLsizei>(c.imageSize); |
+ uint32_t data_shm_id = c.data_shm_id; |
+ uint32_t data_shm_offset = c.data_shm_offset; |
+ |
+ const void* data; |
+ if (state_.bound_pixel_unpack_buffer.get()) { |
+ if (data_shm_id) { |
+ return error::kInvalidArguments; |
+ } |
+ data = reinterpret_cast<const void*>(data_shm_offset); |
+ } else { |
+ if (!data_shm_id && data_shm_offset) { |
+ return error::kInvalidArguments; |
+ } |
+ data = GetSharedMemoryAs<const void*>( |
+ data_shm_id, data_shm_offset, image_size); |
+ } |
+ return DoCompressedTexSubImage(target, level, xoffset, yoffset, 0, |
+ width, height, 1, format, image_size, data, |
+ ContextState::k2D); |
+} |
+ |
+error::Error GLES2DecoderImpl::DoCompressedTexSubImage( |
+ GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, |
+ GLsizei width, GLsizei height, GLsizei depth, GLenum format, |
+ GLsizei image_size, const void * data, ContextState::Dimension dimension) { |
+ const char* func_name; |
+ if (dimension == ContextState::k2D) { |
+ func_name = "glCompressedTexSubImage2D"; |
+ if (!validators_->texture_target.IsValid(target)) { |
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(func_name, target, "target"); |
+ return error::kNoError; |
+ } |
+ } else { |
+ DCHECK_EQ(ContextState::k3D, dimension); |
+ func_name = "glCompressedTexSubImage3D"; |
+ if (!validators_->texture_3_d_target.IsValid(target)) { |
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(func_name, target, "target"); |
+ return error::kNoError; |
+ } |
+ } |
+ if (!validators_->compressed_texture_format.IsValid(format)) { |
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(func_name, format, "format"); |
+ return error::kNoError; |
+ } |
+ if (image_size < 0) { |
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "imageSize < 0"); |
+ return error::kNoError; |
+ } |
+ if (!texture_manager()->ValidForTarget(target, level, width, height, depth)) { |
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "dimensions out of range"); |
+ return error::kNoError; |
+ } |
TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( |
&state_, target); |
if (!texture_ref) { |
LOCAL_SET_GL_ERROR( |
- GL_INVALID_OPERATION, |
- "glCompressedTexSubImage2D", "unknown texture for target"); |
- return; |
- } |
- if (!texture_manager()->ValidForTarget(target, level, width, height, 1)) { |
- LOCAL_SET_GL_ERROR( |
- GL_INVALID_VALUE, |
- "glCompressedTexSubImage2D", "dimensions out of range"); |
- return; |
+ GL_INVALID_OPERATION, func_name, "no texture bound at target"); |
+ return error::kNoError; |
} |
Texture* texture = texture_ref->texture(); |
GLenum type = 0; |
GLenum internal_format = 0; |
if (!texture->GetLevelType(target, level, &type, &internal_format)) { |
- std::string msg = base::StringPrintf( |
- "level %d does not exist", level); |
- LOCAL_SET_GL_ERROR( |
- GL_INVALID_OPERATION, "glCompressedTexSubImage2D", msg.c_str()); |
- return; |
+ std::string msg = base::StringPrintf("level %d does not exist", level); |
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, msg.c_str()); |
+ return error::kNoError; |
} |
if (internal_format != format) { |
- LOCAL_SET_GL_ERROR( |
- GL_INVALID_OPERATION, |
- "glCompressedTexSubImage2D", "format does not match internal format."); |
- return; |
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, |
+ "format does not match internalformat."); |
+ return error::kNoError; |
} |
- if (!texture->ValidForTexture(target, level, xoffset, yoffset, 0, width, |
- height, 1)) { |
- LOCAL_SET_GL_ERROR( |
- GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions."); |
- return; |
+ if (!texture->ValidForTexture(target, level, xoffset, yoffset, zoffset, |
+ width, height, depth)) { |
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "bad dimensions."); |
+ return error::kNoError; |
} |
- if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D", width, height, |
- 1, format, image_size, data) || |
- !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D", target, |
- level, xoffset, yoffset, 0, width, |
- height, 1, format, texture)) { |
- return; |
+ if (!ValidateCompressedTexFuncData( |
+ func_name, width, height, depth, format, image_size, data) || |
+ !ValidateCompressedTexSubDimensions( |
+ func_name, target, level, xoffset, yoffset, zoffset, |
+ width, height, depth, format, texture)) { |
+ return error::kNoError; |
} |
- if (!texture->IsLevelCleared(target, level)) { |
- // This can only happen if the compressed texture was allocated |
- // using TexStorage2D. |
- DCHECK(texture->IsImmutable()); |
- GLsizei level_width = 0, level_height = 0; |
- bool success = texture->GetLevelSize( |
- target, level, &level_width, &level_height, nullptr); |
- DCHECK(success); |
- // We can skip the clear if we're uploading the entire level. |
- if (xoffset == 0 && yoffset == 0 && |
- width == level_width && height == level_height) { |
- texture_manager()->SetLevelCleared(texture_ref, target, level, true); |
- } else { |
- texture_manager()->ClearTextureLevel(this, texture_ref, target, level); |
- } |
- DCHECK(texture->IsLevelCleared(target, level)); |
- } |
+ // Note: There is no need to deal with texture cleared tracking here |
+ // because the validation above means you can only get here if the level |
+ // is already a matching compressed format and in that case |
+ // CompressedTexImage{2|3}D already cleared the texture. |
+ DCHECK(texture->IsLevelCleared(target, level)); |
const CompressedFormatInfo* format_info = |
GetCompressedFormatInfo(internal_format); |
if (format_info != nullptr && !format_info->support_check(*feature_info_)) { |
std::unique_ptr<uint8_t[]> decompressed_data = DecompressTextureData( |
- state_, *format_info, width, height, 1, image_size, data); |
+ state_, *format_info, width, height, depth, image_size, data); |
if (!decompressed_data) { |
MarkContextLost(error::kGuilty); |
group_->LoseContexts(error::kInnocent); |
- return; |
+ return error::kLostContext; |
} |
state_.PushTextureDecompressionUnpackState(); |
- glTexSubImage2D(target, level, xoffset, yoffset, width, height, |
- format_info->decompressed_format, |
- format_info->decompressed_type, decompressed_data.get()); |
+ if (dimension == ContextState::k2D) { |
+ glTexSubImage2D(target, level, xoffset, yoffset, width, height, |
+ format_info->decompressed_format, |
+ format_info->decompressed_type, decompressed_data.get()); |
+ } else { |
+ glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, |
+ depth, format_info->decompressed_format, |
+ format_info->decompressed_type, decompressed_data.get()); |
+ } |
state_.RestoreUnpackState(); |
} else { |
- glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, |
- format, image_size, data); |
+ if (dimension == ContextState::k2D) { |
+ glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, |
+ format, image_size, data); |
+ } else { |
+ glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, |
+ height, depth, format, image_size, data); |
+ } |
} |
// This may be a slow command. Exit command processing to allow for |
// context preemption and GPU watchdog checks. |
ExitCommandProcessingEarly(); |
+ return error::kNoError; |
} |
bool GLES2DecoderImpl::ValidateCopyTexFormat( |