Chromium Code Reviews| 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 a3ad42338965a9e9f7e5c85fb6e133d83079545d..d161fa083f26d120fbc1f0252035c12edcfecbdb 100644 |
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| @@ -9545,23 +9545,26 @@ error::Error GLES2DecoderImpl::HandlePixelStorei(uint32_t immediate_data_size, |
| } |
| break; |
| case GL_PACK_ROW_LENGTH: |
| - case GL_PACK_SKIP_PIXELS: |
| - case GL_PACK_SKIP_ROWS: |
| case GL_UNPACK_ROW_LENGTH: |
| case GL_UNPACK_IMAGE_HEIGHT: |
| - case GL_UNPACK_SKIP_PIXELS: |
| - case GL_UNPACK_SKIP_ROWS: |
| - case GL_UNPACK_SKIP_IMAGES: |
| if (param < 0) { |
| LOCAL_SET_GL_ERROR( |
| GL_INVALID_VALUE, "glPixelStorei", "invalid param"); |
| return error::kNoError; |
| } |
| + break; |
| + case GL_PACK_SKIP_PIXELS: |
| + case GL_PACK_SKIP_ROWS: |
| + case GL_UNPACK_SKIP_PIXELS: |
| + case GL_UNPACK_SKIP_ROWS: |
| + case GL_UNPACK_SKIP_IMAGES: |
| + // All SKIP parameters are handled on the client side and should never |
| + // be passed to the service side. |
| + NOTREACHED(); |
|
piman
2016/03/08 01:56:50
nit: no NOTREACHED() since this can be reached by
Zhenyao Mo
2016/03/09 18:41:05
Done.
|
| + return error::kInvalidArguments; |
| default: |
| break; |
| } |
| - // For pack skip parameters, we don't apply them and handle them in command |
| - // buffer. |
| // For alignment parameters, we always apply them. |
| // For other parameters, we don't apply them if no buffer is bound at |
| // PIXEL_PACK or PIXEL_UNPACK. We will handle pack and unpack according to |
| @@ -9571,14 +9574,8 @@ error::Error GLES2DecoderImpl::HandlePixelStorei(uint32_t immediate_data_size, |
| if (state_.bound_pixel_pack_buffer.get()) |
| glPixelStorei(pname, param); |
| break; |
| - case GL_PACK_SKIP_PIXELS: |
| - case GL_PACK_SKIP_ROWS: |
| - break; |
| case GL_UNPACK_ROW_LENGTH: |
| case GL_UNPACK_IMAGE_HEIGHT: |
| - case GL_UNPACK_SKIP_PIXELS: |
| - case GL_UNPACK_SKIP_ROWS: |
| - case GL_UNPACK_SKIP_IMAGES: |
| if (state_.bound_pixel_unpack_buffer.get()) |
| glPixelStorei(pname, param); |
| break; |
| @@ -9593,12 +9590,6 @@ error::Error GLES2DecoderImpl::HandlePixelStorei(uint32_t immediate_data_size, |
| case GL_PACK_ROW_LENGTH: |
| state_.pack_row_length = param; |
| break; |
| - case GL_PACK_SKIP_PIXELS: |
| - state_.pack_skip_pixels = param; |
| - break; |
| - case GL_PACK_SKIP_ROWS: |
| - state_.pack_skip_rows = param; |
| - break; |
| case GL_UNPACK_ALIGNMENT: |
| state_.unpack_alignment = param; |
| break; |
| @@ -9608,15 +9599,6 @@ error::Error GLES2DecoderImpl::HandlePixelStorei(uint32_t immediate_data_size, |
| case GL_UNPACK_IMAGE_HEIGHT: |
| state_.unpack_image_height = param; |
| break; |
| - case GL_UNPACK_SKIP_PIXELS: |
| - state_.unpack_skip_pixels = param; |
| - break; |
| - case GL_UNPACK_SKIP_ROWS: |
| - state_.unpack_skip_rows = param; |
| - break; |
| - case GL_UNPACK_SKIP_IMAGES: |
| - state_.unpack_skip_images = param; |
| - break; |
| default: |
| // Validation should have prevented us from getting here. |
| NOTREACHED(); |
| @@ -10266,11 +10248,21 @@ bool GLES2DecoderImpl::ClearLevel3D(Texture* texture, |
| uint32_t size; |
| uint32_t padded_row_size; |
| + uint32_t padding; |
| // Here we use unpack buffer to upload zeros into the texture, one layer |
| - // at a time. We haven't applied unpack parameters to GL except alignment. |
| - if (!GLES2Util::ComputeImageDataSizes( |
| - width, height, depth, format, type, state_.unpack_alignment, &size, |
| - nullptr, &padded_row_size)) { |
| + // at a time. |
| + // We only take into consideration UNPACK_ALIGNMENT, and clear other unpack |
| + // parameters if necessary before TexSubImage3D calls. |
| + PixelStoreParams params; |
| + params.alignment = state_.unpack_alignment; |
| + if (!GLES2Util::ComputeImageDataSizesES3(width, height, depth, |
| + format, type, |
| + params, |
| + &size, |
| + nullptr, |
| + &padded_row_size, |
| + nullptr, |
| + &padding)) { |
| return false; |
| } |
| const uint32_t kMaxZeroSize = 1024 * 1024 * 2; |
| @@ -10332,6 +10324,16 @@ bool GLES2DecoderImpl::ClearLevel3D(Texture* texture, |
| glGenBuffersARB(1, &buffer_id); |
| glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer_id); |
| { |
| + // Include padding as some drivers incorrectly requires padding for the |
| + // last row. |
| + buffer_size += padding; |
| + // Buffer size needs to be a multiple of type bytes. |
| + size_t type_bytes = GLES2Util::GetGLTypeSizeForTextures(type); |
| + size_t residual = buffer_size % type_bytes; |
| + if (residual != 0) { |
| + buffer_size += type_bytes - residual; |
| + } |
| + DCHECK(buffer_size % type_bytes == 0); |
| scoped_ptr<char[]> zero(new char[buffer_size]); |
| memset(zero.get(), 0, buffer_size); |
| // TODO(zmo): Consider glMapBufferRange instead. |
| @@ -10339,6 +10341,20 @@ bool GLES2DecoderImpl::ClearLevel3D(Texture* texture, |
| GL_PIXEL_UNPACK_BUFFER, buffer_size, zero.get(), GL_STATIC_DRAW); |
| } |
| + Buffer* bound_buffer = buffer_manager()->GetBufferInfoForTarget( |
| + &state_, GL_PIXEL_UNPACK_BUFFER); |
| + if (bound_buffer) { |
| + // If an unpack buffer is bound, we need to clear unpack parameters |
| + // because they have been applied to the driver. |
| + if (state_.unpack_row_length > 0) |
| + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); |
| + if (state_.unpack_image_height > 0) |
| + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0); |
| + DCHECK_EQ(0, state_.unpack_skip_pixels); |
| + DCHECK_EQ(0, state_.unpack_skip_rows); |
| + DCHECK_EQ(0, state_.unpack_skip_images); |
| + } |
| + |
| glBindTexture(texture->target(), texture->service_id()); |
| for (size_t ii = 0; ii < subs.size(); ++ii) { |
| @@ -10347,8 +10363,13 @@ bool GLES2DecoderImpl::ClearLevel3D(Texture* texture, |
| subs[ii].depth, format, type, nullptr); |
| } |
| - Buffer* bound_buffer = buffer_manager()->GetBufferInfoForTarget( |
| - &state_, GL_PIXEL_UNPACK_BUFFER); |
| + if (bound_buffer) { |
| + if (state_.unpack_row_length > 0) |
| + glPixelStorei(GL_UNPACK_ROW_LENGTH, state_.unpack_row_length); |
| + if (state_.unpack_image_height > 0) |
| + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, state_.unpack_image_height); |
| + } |
| + |
| glBindBuffer(GL_PIXEL_UNPACK_BUFFER, |
| bound_buffer ? bound_buffer->service_id() : 0); |
| glDeleteBuffersARB(1, &buffer_id); |
| @@ -11229,19 +11250,53 @@ error::Error GLES2DecoderImpl::HandleTexImage2D(uint32_t immediate_data_size, |
| GLenum type = static_cast<GLenum>(c.type); |
| uint32_t pixels_shm_id = static_cast<uint32_t>(c.pixels_shm_id); |
| uint32_t pixels_shm_offset = static_cast<uint32_t>(c.pixels_shm_offset); |
| - uint32_t pixels_size; |
| - if (!GLES2Util::ComputeImageDataSizes( |
| - width, height, 1, format, type, state_.unpack_alignment, &pixels_size, |
| - NULL, NULL)) { |
| + |
| + if (width < 0 || height < 0) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexImage2D", "dimensions < 0"); |
| + return error::kNoError; |
| + } |
| + uint32_t pixels_size = 0; |
| + uint32_t skip_size = 0; |
| + bool no_pixels = false; |
| + PixelStoreParams params; |
| + if (state_.bound_pixel_unpack_buffer.get()) { |
| + DCHECK_EQ(0u, pixels_shm_id); |
|
piman
2016/03/08 01:56:50
Is this DCHECK valid? We can't trust the client. W
Zhenyao Mo
2016/03/09 18:41:05
Done.
|
| + params = state_.GetUnpackParams(ContextState::k2D); |
| + } else { |
| + if (pixels_shm_id) { |
| + // When reading from client buffer, the command buffer client side took |
| + // the responsibility to take the pixels from the client buffer and |
| + // unpack them according to the full ES3 pack parameters as source, all |
| + // parameters for 0 (except for alignment) as destination mem for the |
| + // service side. |
| + params.alignment = state_.unpack_alignment; |
| + } else { |
| + DCHECK_EQ(0u, pixels_shm_offset); |
|
piman
2016/03/08 01:56:50
Same here.
Zhenyao Mo
2016/03/09 18:41:05
Done.
|
| + no_pixels = true; |
| + } |
| + } |
| + if (!no_pixels && |
| + !GLES2Util::ComputeImageDataSizesES3(width, height, 1, |
| + format, type, |
| + params, |
| + &pixels_size, |
| + nullptr, |
| + nullptr, |
| + &skip_size, |
| + nullptr)) { |
| return error::kOutOfBounds; |
| } |
| - const void* pixels = NULL; |
| - if (pixels_shm_id != 0 || pixels_shm_offset != 0) { |
| + DCHECK_EQ(0u, skip_size); |
| + |
| + const void* pixels = nullptr; |
| + if (pixels_shm_id) { |
| pixels = GetSharedMemoryAs<const void*>( |
| pixels_shm_id, pixels_shm_offset, pixels_size); |
| if (!pixels) { |
| return error::kOutOfBounds; |
| } |
| + } else { |
| + pixels = reinterpret_cast<const void*>(pixels_shm_offset); |
| } |
| // For testing only. Allows us to stress the ability to respond to OOM errors. |
| @@ -11287,19 +11342,54 @@ error::Error GLES2DecoderImpl::HandleTexImage3D(uint32_t immediate_data_size, |
| GLenum type = static_cast<GLenum>(c.type); |
| uint32_t pixels_shm_id = static_cast<uint32_t>(c.pixels_shm_id); |
| uint32_t pixels_shm_offset = static_cast<uint32_t>(c.pixels_shm_offset); |
| - uint32_t pixels_size; |
| - if (!GLES2Util::ComputeImageDataSizes( |
| - width, height, depth, format, type, state_.unpack_alignment, &pixels_size, |
| - NULL, NULL)) { |
| + |
| + if (width < 0 || height < 0 || depth < 0) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexImage3D", "dimensions < 0"); |
| + return error::kNoError; |
| + } |
| + |
| + uint32_t pixels_size = 0; |
| + uint32_t skip_size = 0; |
| + bool no_pixels = false; |
| + PixelStoreParams params; |
| + if (state_.bound_pixel_unpack_buffer.get()) { |
| + DCHECK_EQ(0u, pixels_shm_id); |
|
piman
2016/03/08 01:56:50
Same as above.
Zhenyao Mo
2016/03/09 18:41:05
Done.
|
| + params = state_.GetUnpackParams(ContextState::k3D); |
| + } else { |
| + if (pixels_shm_id) { |
| + // When reading from client buffer, the command buffer client side took |
| + // the responsibility to take the pixels from the client buffer and |
| + // unpack them according to the full ES3 pack parameters as source, all |
| + // parameters for 0 (except for alignment) as destination mem for the |
| + // service side. |
| + params.alignment = state_.unpack_alignment; |
| + } else { |
| + DCHECK_EQ(0u, pixels_shm_offset); |
|
piman
2016/03/08 01:56:50
And here.
Zhenyao Mo
2016/03/09 18:41:05
Done.
|
| + no_pixels = true; |
| + } |
| + } |
| + if (!no_pixels && |
| + !GLES2Util::ComputeImageDataSizesES3(width, height, depth, |
| + format, type, |
| + params, |
| + &pixels_size, |
| + nullptr, |
| + nullptr, |
| + &skip_size, |
| + nullptr)) { |
| return error::kOutOfBounds; |
| } |
| - const void* pixels = NULL; |
| - if (pixels_shm_id != 0 || pixels_shm_offset != 0) { |
| + DCHECK_EQ(0u, skip_size); |
| + |
| + const void* pixels = nullptr; |
| + if (pixels_shm_id) { |
| pixels = GetSharedMemoryAs<const void*>( |
| pixels_shm_id, pixels_shm_offset, pixels_size); |
| if (!pixels) { |
| return error::kOutOfBounds; |
| } |
| + } else { |
| + pixels = reinterpret_cast<const void*>(pixels_shm_offset); |
| } |
| // For testing only. Allows us to stress the ability to respond to OOM errors. |
| @@ -11324,15 +11414,8 @@ error::Error GLES2DecoderImpl::HandleTexImage3D(uint32_t immediate_data_size, |
| } |
| void GLES2DecoderImpl::DoCompressedTexSubImage2D( |
| - GLenum target, |
| - GLint level, |
| - GLint xoffset, |
| - GLint yoffset, |
| - GLsizei width, |
| - GLsizei height, |
| - GLenum format, |
| - GLsizei image_size, |
| - const void * data) { |
| + GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, |
| + GLsizei height, GLenum format, GLsizei image_size, const void * data) { |
| TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( |
| &state_, target); |
| if (!texture_ref) { |
| @@ -11679,21 +11762,59 @@ error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32_t immediate_data_size, |
| GLsizei height = static_cast<GLsizei>(c.height); |
| GLenum format = static_cast<GLenum>(c.format); |
| GLenum type = static_cast<GLenum>(c.type); |
| - uint32_t data_size; |
| - if (!GLES2Util::ComputeImageDataSizes( |
| - width, height, 1, format, type, state_.unpack_alignment, &data_size, |
| - NULL, NULL)) { |
| + uint32_t pixels_shm_id = static_cast<uint32_t>(c.pixels_shm_id); |
| + uint32_t pixels_shm_offset = static_cast<uint32_t>(c.pixels_shm_offset); |
| + |
| + if (width < 0 || height < 0) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexSubImage2D", "dimensions < 0"); |
| + return error::kNoError; |
| + } |
| + PixelStoreParams params; |
| + if (state_.bound_pixel_unpack_buffer.get()) { |
| + params = state_.GetUnpackParams(ContextState::k2D); |
| + } else { |
| + // When reading from client buffer, the command buffer client side took |
| + // the responsibility to take the pixels from the client buffer and |
| + // unpack them according to the full ES3 pack parameters as source, all |
| + // parameters for 0 (except for alignment) as destination mem for the |
| + // service side. |
| + params.alignment = state_.unpack_alignment; |
| + } |
| + uint32_t pixels_size; |
| + uint32_t skip_size; |
| + if (!GLES2Util::ComputeImageDataSizesES3(width, height, 1, |
| + format, type, |
| + params, |
| + &pixels_size, |
| + nullptr, |
| + nullptr, |
| + &skip_size, |
| + nullptr)) { |
| return error::kOutOfBounds; |
| } |
| + DCHECK_EQ(0u, skip_size); |
| - const void* pixels = GetSharedMemoryAs<const void*>( |
| - c.pixels_shm_id, c.pixels_shm_offset, data_size); |
| - if (!pixels) |
| - return error::kOutOfBounds; |
| + const void* pixels; |
| + if (state_.bound_pixel_unpack_buffer.get()) { |
| + if (pixels_shm_id != 0) |
| + return error::kInvalidArguments; |
| + pixels = reinterpret_cast<const void*>(pixels_shm_offset); |
| + } else { |
| + if (pixels_size > 0) { |
| + if (pixels_shm_id == 0) |
| + return error::kInvalidArguments; |
| + pixels = GetSharedMemoryAs<const void*>( |
| + pixels_shm_id, pixels_shm_offset, pixels_size); |
| + if (!pixels) |
| + return error::kOutOfBounds; |
| + } else { |
| + pixels = nullptr; |
| + } |
| + } |
| TextureManager::DoTexSubImageArguments args = { |
| target, level, xoffset, yoffset, 0, width, height, 1, |
| - format, type, pixels, data_size, |
| + format, type, pixels, pixels_size, |
| TextureManager::DoTexSubImageArguments::kTexSubImage2D}; |
| texture_manager()->ValidateAndDoTexSubImage(this, &texture_state_, &state_, |
| &framebuffer_state_, |
| @@ -11728,21 +11849,59 @@ error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32_t immediate_data_size, |
| GLsizei depth = static_cast<GLsizei>(c.depth); |
| GLenum format = static_cast<GLenum>(c.format); |
| GLenum type = static_cast<GLenum>(c.type); |
| - uint32_t data_size; |
| - if (!GLES2Util::ComputeImageDataSizes( |
| - width, height, depth, format, type, state_.unpack_alignment, &data_size, |
| - NULL, NULL)) { |
| + uint32_t pixels_shm_id = static_cast<uint32_t>(c.pixels_shm_id); |
| + uint32_t pixels_shm_offset = static_cast<uint32_t>(c.pixels_shm_offset); |
| + |
| + if (width < 0 || height < 0 || depth < 0) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexSubImage3D", "dimensions < 0"); |
| + return error::kNoError; |
| + } |
| + PixelStoreParams params; |
| + if (state_.bound_pixel_unpack_buffer.get()) { |
| + params = state_.GetUnpackParams(ContextState::k3D); |
| + } else { |
| + // When reading from client buffer, the command buffer client side took |
| + // the responsibility to take the pixels from the client buffer and |
| + // unpack them according to the full ES3 pack parameters as source, all |
| + // parameters for 0 (except for alignment) as destination mem for the |
| + // service side. |
| + params.alignment = state_.unpack_alignment; |
| + } |
| + uint32_t pixels_size; |
| + uint32_t skip_size; |
| + if (!GLES2Util::ComputeImageDataSizesES3(width, height, depth, |
| + format, type, |
| + params, |
| + &pixels_size, |
| + nullptr, |
| + nullptr, |
| + &skip_size, |
| + nullptr)) { |
| return error::kOutOfBounds; |
| } |
| + DCHECK_EQ(0u, skip_size); |
| - const void* pixels = GetSharedMemoryAs<const void*>( |
| - c.pixels_shm_id, c.pixels_shm_offset, data_size); |
| - if (!pixels) |
| - return error::kOutOfBounds; |
| + const void* pixels; |
| + if (state_.bound_pixel_unpack_buffer.get()) { |
| + if (pixels_shm_id != 0) |
| + return error::kInvalidArguments; |
| + pixels = reinterpret_cast<const void*>(pixels_shm_offset); |
| + } else { |
| + if (pixels_size > 0) { |
| + if (pixels_shm_id == 0) |
| + return error::kInvalidArguments; |
| + pixels = GetSharedMemoryAs<const void*>( |
| + pixels_shm_id, pixels_shm_offset, pixels_size); |
| + if (!pixels) |
| + return error::kOutOfBounds; |
| + } else { |
| + pixels = nullptr; |
| + } |
| + } |
| TextureManager::DoTexSubImageArguments args = { |
| target, level, xoffset, yoffset, zoffset, width, height, depth, |
| - format, type, pixels, data_size, |
| + format, type, pixels, pixels_size, |
| TextureManager::DoTexSubImageArguments::kTexSubImage3D}; |
| texture_manager()->ValidateAndDoTexSubImage(this, &texture_state_, &state_, |
| &framebuffer_state_, |