Index: gpu/command_buffer/client/gles2_implementation.cc |
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc |
index aeaa565559b6478b4962feeec7be954edbd0b763..a8dc4522c20d61aa098ed6fe329f5855ffd56b2c 100644 |
--- a/gpu/command_buffer/client/gles2_implementation.cc |
+++ b/gpu/command_buffer/client/gles2_implementation.cc |
@@ -958,6 +958,12 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) { |
case GL_NUM_PROGRAM_BINARY_FORMATS: |
*params = capabilities_.num_program_binary_formats; |
return true; |
+ case GL_PACK_SKIP_PIXELS: |
+ *params = pack_skip_pixels_; |
+ return true; |
+ case GL_PACK_SKIP_ROWS: |
+ *params = pack_skip_rows_; |
+ return true; |
case GL_PIXEL_PACK_BUFFER_BINDING: |
*params = bound_pixel_pack_buffer_; |
return true; |
@@ -973,6 +979,15 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) { |
case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: |
*params = capabilities_.uniform_buffer_offset_alignment; |
return true; |
+ case GL_UNPACK_SKIP_IMAGES: |
+ *params = unpack_skip_images_; |
+ return true; |
+ case GL_UNPACK_SKIP_PIXELS: |
+ *params = unpack_skip_pixels_; |
+ return true; |
+ case GL_UNPACK_SKIP_ROWS: |
+ *params = unpack_skip_rows_; |
+ return true; |
// Non-cached ES3 parameters. |
case GL_DRAW_BUFFER0: |
@@ -994,8 +1009,6 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) { |
case GL_DRAW_FRAMEBUFFER_BINDING: |
case GL_FRAGMENT_SHADER_DERIVATIVE_HINT: |
case GL_PACK_ROW_LENGTH: |
- case GL_PACK_SKIP_PIXELS: |
- case GL_PACK_SKIP_ROWS: |
case GL_PRIMITIVE_RESTART_FIXED_INDEX: |
case GL_PROGRAM_BINARY_FORMATS: |
case GL_RASTERIZER_DISCARD: |
@@ -1013,9 +1026,6 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) { |
case GL_UNIFORM_BUFFER_START: |
case GL_UNPACK_IMAGE_HEIGHT: |
case GL_UNPACK_ROW_LENGTH: |
- case GL_UNPACK_SKIP_IMAGES: |
- case GL_UNPACK_SKIP_PIXELS: |
- case GL_UNPACK_SKIP_ROWS: |
case GL_VERTEX_ARRAY_BINDING: |
return false; |
default: |
@@ -1764,6 +1774,45 @@ void GLES2Implementation::PixelStorei(GLenum pname, GLint param) { |
GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPixelStorei(" |
<< GLES2Util::GetStringPixelStore(pname) << ", " |
<< param << ")"); |
+ // We have to validate before caching these parameters because we use them |
+ // to compute image sizes on the client side. |
+ switch (pname) { |
+ case GL_PACK_ALIGNMENT: |
+ case GL_UNPACK_ALIGNMENT: |
+ if (param != 1 && param != 2 && param != 4 && param != 8) { |
+ SetGLError(GL_INVALID_VALUE, "glPixelStorei", "invalid param"); |
+ return; |
+ } |
+ break; |
+ case GL_PACK_ROW_LENGTH: |
+ case GL_PACK_SKIP_PIXELS: |
+ case GL_PACK_SKIP_ROWS: |
+ case GL_UNPACK_IMAGE_HEIGHT: |
+ case GL_UNPACK_SKIP_IMAGES: |
+ if (capabilities_.major_version < 3) { |
+ SetGLError(GL_INVALID_ENUM, "glPixelStorei", "invalid pname"); |
+ return; |
+ } |
+ if (param < 0) { |
+ SetGLError(GL_INVALID_VALUE, "glPixelStorei", "invalid param"); |
+ return; |
+ } |
+ break; |
+ case GL_UNPACK_ROW_LENGTH: |
+ case GL_UNPACK_SKIP_ROWS: |
+ case GL_UNPACK_SKIP_PIXELS: |
+ // These parameters are always enabled in ES2 by EXT_unpack_subimage. |
+ if (param < 0) { |
+ SetGLError(GL_INVALID_VALUE, "glPixelStorei", "invalid param"); |
+ return; |
+ } |
+ break; |
+ default: |
+ SetGLError(GL_INVALID_ENUM, "glPixelStorei", "invalid pname"); |
+ return; |
+ } |
+ // Do not send SKIP parameters to the service side. |
+ // Handle them on the client side. |
switch (pname) { |
case GL_PACK_ALIGNMENT: |
pack_alignment_ = param; |
@@ -1773,29 +1822,35 @@ void GLES2Implementation::PixelStorei(GLenum pname, GLint param) { |
break; |
case GL_PACK_SKIP_PIXELS: |
pack_skip_pixels_ = param; |
- break; |
+ return; |
case GL_PACK_SKIP_ROWS: |
pack_skip_rows_ = param; |
- break; |
+ return; |
case GL_UNPACK_ALIGNMENT: |
unpack_alignment_ = param; |
break; |
- case GL_UNPACK_ROW_LENGTH_EXT: |
+ case GL_UNPACK_ROW_LENGTH: |
unpack_row_length_ = param; |
+ if (capabilities_.major_version < 3) { |
+ // In ES2 with EXT_unpack_subimage, it's handled on the client side |
+ // and there is no need to send it to the service side. |
+ return; |
+ } |
break; |
case GL_UNPACK_IMAGE_HEIGHT: |
unpack_image_height_ = param; |
break; |
- case GL_UNPACK_SKIP_ROWS_EXT: |
+ case GL_UNPACK_SKIP_ROWS: |
unpack_skip_rows_ = param; |
- break; |
- case GL_UNPACK_SKIP_PIXELS_EXT: |
+ return; |
+ case GL_UNPACK_SKIP_PIXELS: |
unpack_skip_pixels_ = param; |
- break; |
+ return; |
case GL_UNPACK_SKIP_IMAGES: |
unpack_skip_images_ = param; |
- break; |
+ return; |
default: |
+ NOTREACHED(); |
break; |
} |
helper_->PixelStorei(pname, param); |
@@ -2083,7 +2138,16 @@ GLES2Implementation::GetBoundPixelUnpackTransferBufferIfValid( |
SetGLError(GL_INVALID_OPERATION, function_name, "buffer mapped"); |
return NULL; |
} |
- if ((buffer->size() - offset) < static_cast<GLuint>(size)) { |
+ base::CheckedNumeric<uint32_t> buffer_offset = buffer->shm_offset(); |
+ buffer_offset += offset; |
+ if (!buffer_offset.IsValid()) { |
+ SetGLError(GL_INVALID_VALUE, function_name, "offset to large"); |
+ return NULL; |
+ } |
+ base::CheckedNumeric<uint32_t> required_size = offset; |
+ required_size += size; |
+ if (!required_size.IsValid() || |
+ buffer->size() < required_size.ValueOrDefault(0)) { |
SetGLError(GL_INVALID_VALUE, function_name, "unpack size to large"); |
return NULL; |
} |
@@ -2277,13 +2341,11 @@ void CopyRectToBuffer(const void* pixels, |
const int8_t* source = static_cast<const int8_t*>(pixels); |
int8_t* dest = static_cast<int8_t*>(buffer); |
if (pixels_padded_row_size != buffer_padded_row_size) { |
- // the last row is copied unpadded at the end |
- for (; height > 1; --height) { |
- memcpy(dest, source, buffer_padded_row_size); |
+ for (uint32_t ii = 0; ii < height; ++ii) { |
+ memcpy(dest, source, unpadded_row_size); |
dest += buffer_padded_row_size; |
source += pixels_padded_row_size; |
} |
- memcpy(dest, source, unpadded_row_size); |
} else { |
uint32_t size = (height - 1) * pixels_padded_row_size + unpadded_row_size; |
memcpy(dest, source, size); |
@@ -2292,6 +2354,19 @@ void CopyRectToBuffer(const void* pixels, |
} // anonymous namespace |
+PixelStoreParams GLES2Implementation::GetUnpackParameters(Dimension dimension) { |
+ PixelStoreParams params; |
+ params.alignment = unpack_alignment_; |
+ params.row_length = unpack_row_length_; |
+ params.skip_pixels = unpack_skip_pixels_; |
+ params.skip_rows = unpack_skip_rows_; |
+ if (dimension == k3D) { |
+ params.image_height = unpack_image_height_; |
+ params.skip_images = unpack_skip_images_; |
+ } |
+ return params; |
+} |
+ |
void GLES2Implementation::TexImage2D( |
GLenum target, GLint level, GLint internalformat, GLsizei width, |
GLsizei height, GLint border, GLenum format, GLenum type, |
@@ -2316,19 +2391,47 @@ void GLES2Implementation::TexImage2D( |
uint32_t size; |
uint32_t unpadded_row_size; |
uint32_t padded_row_size; |
- if (!GLES2Util::ComputeImageDataSizes( |
- width, height, 1, format, type, unpack_alignment_, &size, |
- &unpadded_row_size, &padded_row_size)) { |
+ uint32_t skip_size; |
+ PixelStoreParams params = GetUnpackParameters(k2D); |
+ if (!GLES2Util::ComputeImageDataSizesES3(width, height, 1, |
+ format, type, |
+ params, |
+ &size, |
+ &unpadded_row_size, |
+ &padded_row_size, |
+ &skip_size, |
+ nullptr)) { |
SetGLError(GL_INVALID_VALUE, "glTexImage2D", "image size too large"); |
return; |
} |
+ if (bound_pixel_unpack_buffer_) { |
+ base::CheckedNumeric<uint32_t> offset = ToGLuint(pixels); |
+ offset += skip_size; |
+ if (!offset.IsValid()) { |
+ SetGLError(GL_INVALID_VALUE, "glTexImage2D", "skip size too large"); |
+ return; |
+ } |
+ helper_->TexImage2D( |
+ target, level, internalformat, width, height, format, type, |
+ 0, offset.ValueOrDefault(0)); |
+ CheckGLError(); |
+ return; |
+ } |
+ |
// If there's a pixel unpack buffer bound use it when issuing TexImage2D. |
if (bound_pixel_unpack_transfer_buffer_id_) { |
+ if (unpack_row_length_ > 0 || unpack_image_height_ > 0 || |
+ unpack_skip_pixels_ > 0 || unpack_skip_rows_ > 0 || |
+ unpack_skip_images_ > 0) { |
+ SetGLError(GL_INVALID_OPERATION, "glTexImage2D", |
+ "No ES3 pack parameters with pixel unpack transfer buffer."); |
+ return; |
+ } |
+ DCHECK_EQ(0u, skip_size); |
GLuint offset = ToGLuint(pixels); |
BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( |
- bound_pixel_unpack_transfer_buffer_id_, |
- "glTexImage2D", offset, size); |
+ bound_pixel_unpack_transfer_buffer_id_, "glTexImage2D", offset, size); |
if (buffer && buffer->shm_id() != -1) { |
helper_->TexImage2D( |
target, level, internalformat, width, height, format, type, |
@@ -2340,36 +2443,38 @@ void GLES2Implementation::TexImage2D( |
} |
// If there's no data just issue TexImage2D |
- if (!pixels) { |
+ if (!pixels || width == 0 || height == 0) { |
helper_->TexImage2D( |
- target, level, internalformat, width, height, format, type, |
- 0, 0); |
+ target, level, internalformat, width, height, format, type, 0, 0); |
CheckGLError(); |
return; |
} |
- // compute the advance bytes per row for the src pixels |
- uint32_t src_padded_row_size; |
- if (unpack_row_length_ > 0) { |
- if (!GLES2Util::ComputeImagePaddedRowSize( |
- unpack_row_length_, format, type, unpack_alignment_, |
- &src_padded_row_size)) { |
- SetGLError( |
- GL_INVALID_VALUE, "glTexImage2D", "unpack row length too large"); |
+ // Compute the advance bytes per row on the service side. |
+ // Note |size| is recomputed here if needed. |
+ uint32_t service_padded_row_size; |
+ if (unpack_row_length_ > 0 && unpack_row_length_ != width) { |
+ // All parameters have been applied to the data that are sent to the |
+ // service side except UNPACK_ALIGNMENT. |
+ PixelStoreParams service_params; |
+ service_params.alignment = unpack_alignment_; |
+ if (!GLES2Util::ComputeImageDataSizesES3(width, height, 1, |
+ format, type, |
+ service_params, |
+ &size, |
+ nullptr, |
+ &service_padded_row_size, |
+ nullptr, |
+ nullptr)) { |
+ SetGLError(GL_INVALID_VALUE, "glTexImage2D", "image size too large"); |
return; |
} |
} else { |
- src_padded_row_size = padded_row_size; |
+ service_padded_row_size = padded_row_size; |
} |
// advance pixels pointer past the skip rows and skip pixels |
- pixels = reinterpret_cast<const int8_t*>(pixels) + |
- unpack_skip_rows_ * src_padded_row_size; |
- if (unpack_skip_pixels_) { |
- uint32_t group_size = GLES2Util::ComputeImageGroupSize(format, type); |
- pixels = reinterpret_cast<const int8_t*>(pixels) + |
- unpack_skip_pixels_ * group_size; |
- } |
+ pixels = reinterpret_cast<const int8_t*>(pixels) + skip_size; |
// Check if we can send it all at once. |
int32_t shm_id = 0; |
@@ -2397,8 +2502,8 @@ void GLES2Implementation::TexImage2D( |
if (buffer_pointer) { |
CopyRectToBuffer( |
- pixels, height, unpadded_row_size, src_padded_row_size, |
- buffer_pointer, padded_row_size); |
+ pixels, height, unpadded_row_size, padded_row_size, |
+ buffer_pointer, service_padded_row_size); |
helper_->TexImage2D( |
target, level, internalformat, width, height, format, type, |
shm_id, shm_offset); |
@@ -2412,7 +2517,8 @@ void GLES2Implementation::TexImage2D( |
0, 0); |
TexSubImage2DImpl( |
target, level, 0, 0, width, height, format, type, unpadded_row_size, |
- pixels, src_padded_row_size, GL_TRUE, &transfer_alloc, padded_row_size); |
+ pixels, padded_row_size, GL_TRUE, &transfer_alloc, |
+ service_padded_row_size); |
CheckGLError(); |
} |
@@ -2437,22 +2543,51 @@ void GLES2Implementation::TexImage3D( |
SetGLError(GL_INVALID_VALUE, "glTexImage3D", "border != 0"); |
return; |
} |
+ |
uint32_t size; |
uint32_t unpadded_row_size; |
uint32_t padded_row_size; |
- if (!GLES2Util::ComputeImageDataSizes( |
- width, height, depth, format, type, unpack_alignment_, &size, |
- &unpadded_row_size, &padded_row_size)) { |
+ uint32_t skip_size; |
+ PixelStoreParams params = GetUnpackParameters(k3D); |
+ if (!GLES2Util::ComputeImageDataSizesES3(width, height, depth, |
+ format, type, |
+ params, |
+ &size, |
+ &unpadded_row_size, |
+ &padded_row_size, |
+ &skip_size, |
+ nullptr)) { |
SetGLError(GL_INVALID_VALUE, "glTexImage3D", "image size too large"); |
return; |
} |
+ if (bound_pixel_unpack_buffer_) { |
+ base::CheckedNumeric<uint32_t> offset = ToGLuint(pixels); |
+ offset += skip_size; |
+ if (!offset.IsValid()) { |
+ SetGLError(GL_INVALID_VALUE, "glTexImage3D", "skip size too large"); |
+ return; |
+ } |
+ helper_->TexImage3D( |
+ target, level, internalformat, width, height, depth, format, type, |
+ 0, offset.ValueOrDefault(0)); |
+ CheckGLError(); |
+ return; |
+ } |
+ |
// If there's a pixel unpack buffer bound use it when issuing TexImage3D. |
if (bound_pixel_unpack_transfer_buffer_id_) { |
+ if (unpack_row_length_ > 0 || unpack_image_height_ > 0 || |
+ unpack_skip_pixels_ > 0 || unpack_skip_rows_ > 0 || |
+ unpack_skip_images_ > 0) { |
+ SetGLError(GL_INVALID_OPERATION, "glTexImage3D", |
+ "No ES3 pack parameters with pixel unpack transfer buffer."); |
+ return; |
+ } |
+ DCHECK_EQ(0u, skip_size); |
GLuint offset = ToGLuint(pixels); |
BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( |
- bound_pixel_unpack_transfer_buffer_id_, |
- "glTexImage3D", offset, size); |
+ bound_pixel_unpack_transfer_buffer_id_, "glTexImage3D", offset, size); |
if (buffer && buffer->shm_id() != -1) { |
helper_->TexImage3D( |
target, level, internalformat, width, height, depth, format, type, |
@@ -2464,7 +2599,7 @@ void GLES2Implementation::TexImage3D( |
} |
// If there's no data just issue TexImage3D |
- if (!pixels) { |
+ if (!pixels || width == 0 || height == 0 || depth == 0) { |
helper_->TexImage3D( |
target, level, internalformat, width, height, depth, format, type, |
0, 0); |
@@ -2472,31 +2607,34 @@ void GLES2Implementation::TexImage3D( |
return; |
} |
- // compute the advance bytes per row for the src pixels |
- uint32_t src_padded_row_size; |
- if (unpack_row_length_ > 0) { |
- if (!GLES2Util::ComputeImagePaddedRowSize( |
- unpack_row_length_, format, type, unpack_alignment_, |
- &src_padded_row_size)) { |
- SetGLError( |
- GL_INVALID_VALUE, "glTexImage3D", "unpack row length too large"); |
+ // Compute the advance bytes per row on the service side. |
+ // Note |size| is recomputed here if needed. |
+ uint32_t service_padded_row_size; |
+ if ((unpack_row_length_ > 0 && unpack_row_length_ != width) || |
+ (unpack_image_height_ > 0 && unpack_image_height_ != height)) { |
+ // All parameters have been applied to the data that are sent to the |
+ // service side except UNPACK_ALIGNMENT. |
+ PixelStoreParams service_params; |
+ service_params.alignment = unpack_alignment_; |
+ if (!GLES2Util::ComputeImageDataSizesES3(width, height, depth, |
+ format, type, |
+ service_params, |
+ &size, |
+ nullptr, |
+ &service_padded_row_size, |
+ nullptr, |
+ nullptr)) { |
+ SetGLError(GL_INVALID_VALUE, "glTexImage3D", "image size too large"); |
return; |
} |
} else { |
- src_padded_row_size = padded_row_size; |
+ service_padded_row_size = padded_row_size; |
} |
uint32_t src_height = |
unpack_image_height_ > 0 ? unpack_image_height_ : height; |
// advance pixels pointer past the skip images/rows/pixels |
- pixels = reinterpret_cast<const int8_t*>(pixels) + |
- unpack_skip_images_ * src_padded_row_size * src_height + |
- unpack_skip_rows_ * src_padded_row_size; |
- if (unpack_skip_pixels_) { |
- uint32_t group_size = GLES2Util::ComputeImageGroupSize(format, type); |
- pixels = reinterpret_cast<const int8_t*>(pixels) + |
- unpack_skip_pixels_ * group_size; |
- } |
+ pixels = reinterpret_cast<const int8_t*>(pixels) + skip_size; |
// Check if we can send it all at once. |
int32_t shm_id = 0; |
@@ -2524,16 +2662,13 @@ void GLES2Implementation::TexImage3D( |
if (buffer_pointer) { |
for (GLsizei z = 0; z < depth; ++z) { |
- // Only the last row of the last image is unpadded. |
- uint32_t src_unpadded_row_size = |
- (z == depth - 1) ? unpadded_row_size : src_padded_row_size; |
CopyRectToBuffer( |
- pixels, height, src_unpadded_row_size, src_padded_row_size, |
- buffer_pointer, padded_row_size); |
+ pixels, height, unpadded_row_size, padded_row_size, |
+ buffer_pointer, service_padded_row_size); |
pixels = reinterpret_cast<const int8_t*>(pixels) + |
- src_padded_row_size * src_height; |
- buffer_pointer = |
- reinterpret_cast<int8_t*>(buffer_pointer) + padded_row_size * height; |
+ padded_row_size * src_height; |
+ buffer_pointer = reinterpret_cast<int8_t*>(buffer_pointer) + |
+ service_padded_row_size * height; |
} |
helper_->TexImage3D( |
target, level, internalformat, width, height, depth, format, type, |
@@ -2548,8 +2683,8 @@ void GLES2Implementation::TexImage3D( |
0, 0); |
TexSubImage3DImpl( |
target, level, 0, 0, 0, width, height, depth, format, type, |
- unpadded_row_size, pixels, src_padded_row_size, GL_TRUE, &transfer_alloc, |
- padded_row_size); |
+ unpadded_row_size, pixels, padded_row_size, GL_TRUE, &transfer_alloc, |
+ service_padded_row_size); |
CheckGLError(); |
} |
@@ -2566,30 +2701,55 @@ void GLES2Implementation::TexSubImage2D( |
<< GLES2Util::GetStringPixelType(type) << ", " |
<< static_cast<const void*>(pixels) << ")"); |
- if (level < 0 || height < 0 || width < 0) { |
+ if (level < 0 || height < 0 || width < 0 || xoffset < 0 || yoffset < 0) { |
SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "dimension < 0"); |
return; |
} |
- if (height == 0 || width == 0) { |
- return; |
- } |
- uint32_t temp_size; |
+ uint32_t size; |
uint32_t unpadded_row_size; |
uint32_t padded_row_size; |
- if (!GLES2Util::ComputeImageDataSizes( |
- width, height, 1, format, type, unpack_alignment_, &temp_size, |
- &unpadded_row_size, &padded_row_size)) { |
- SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "size to large"); |
+ uint32_t skip_size; |
+ PixelStoreParams params = GetUnpackParameters(k2D); |
+ if (!GLES2Util::ComputeImageDataSizesES3(width, height, 1, |
+ format, type, |
+ params, |
+ &size, |
+ &unpadded_row_size, |
+ &padded_row_size, |
+ &skip_size, |
+ nullptr)) { |
+ SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "image size to large"); |
+ return; |
+ } |
+ |
+ if (bound_pixel_unpack_buffer_) { |
+ base::CheckedNumeric<uint32_t> offset = ToGLuint(pixels); |
+ offset += skip_size; |
+ if (!offset.IsValid()) { |
+ SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "skip size too large"); |
+ return; |
+ } |
+ helper_->TexSubImage2D(target, level, xoffset, yoffset, width, height, |
+ format, type, 0, offset.ValueOrDefault(0), false); |
+ CheckGLError(); |
return; |
} |
// If there's a pixel unpack buffer bound use it when issuing TexSubImage2D. |
if (bound_pixel_unpack_transfer_buffer_id_) { |
+ if (unpack_row_length_ > 0 || unpack_image_height_ > 0 || |
+ unpack_skip_pixels_ > 0 || unpack_skip_rows_ > 0 || |
+ unpack_skip_images_ > 0) { |
+ SetGLError(GL_INVALID_OPERATION, "glTexSubImage2D", |
+ "No ES3 pack parameters with pixel unpack transfer buffer."); |
+ return; |
+ } |
+ DCHECK_EQ(0u, skip_size); |
GLuint offset = ToGLuint(pixels); |
BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( |
bound_pixel_unpack_transfer_buffer_id_, |
- "glTexSubImage2D", offset, temp_size); |
+ "glTexSubImage2D", offset, size); |
if (buffer && buffer->shm_id() != -1) { |
helper_->TexSubImage2D( |
target, level, xoffset, yoffset, width, height, format, type, |
@@ -2600,34 +2760,45 @@ void GLES2Implementation::TexSubImage2D( |
return; |
} |
- // compute the advance bytes per row for the src pixels |
- uint32_t src_padded_row_size; |
- if (unpack_row_length_ > 0) { |
- if (!GLES2Util::ComputeImagePaddedRowSize( |
- unpack_row_length_, format, type, unpack_alignment_, |
- &src_padded_row_size)) { |
- SetGLError( |
- GL_INVALID_VALUE, "glTexImage2D", "unpack row length too large"); |
+ if (width == 0 || height == 0) { |
+ // No need to worry about pixel data. |
+ helper_->TexSubImage2D(target, level, xoffset, yoffset, width, height, |
+ format, type, 0, 0, false); |
+ CheckGLError(); |
+ return; |
+ } |
+ |
+ // Compute the advance bytes per row on the service side. |
+ // Note |size| is recomputed here if needed. |
+ uint32_t service_padded_row_size; |
+ if (unpack_row_length_ > 0 && unpack_row_length_ != width) { |
+ // All parameters have been applied to the data that are sent to the |
+ // service side except UNPACK_ALIGNMENT. |
+ PixelStoreParams service_params; |
+ service_params.alignment = unpack_alignment_; |
+ if (!GLES2Util::ComputeImageDataSizesES3(width, height, 1, |
+ format, type, |
+ service_params, |
+ &size, |
+ nullptr, |
+ &service_padded_row_size, |
+ nullptr, |
+ nullptr)) { |
+ SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "image size too large"); |
return; |
} |
} else { |
- src_padded_row_size = padded_row_size; |
+ service_padded_row_size = padded_row_size; |
} |
// advance pixels pointer past the skip rows and skip pixels |
- pixels = reinterpret_cast<const int8_t*>(pixels) + |
- unpack_skip_rows_ * src_padded_row_size; |
- if (unpack_skip_pixels_) { |
- uint32_t group_size = GLES2Util::ComputeImageGroupSize(format, type); |
- pixels = reinterpret_cast<const int8_t*>(pixels) + |
- unpack_skip_pixels_ * group_size; |
- } |
+ pixels = reinterpret_cast<const int8_t*>(pixels) + skip_size; |
- ScopedTransferBufferPtr buffer(temp_size, helper_, transfer_buffer_); |
+ ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_); |
TexSubImage2DImpl( |
target, level, xoffset, yoffset, width, height, format, type, |
- unpadded_row_size, pixels, src_padded_row_size, GL_FALSE, &buffer, |
- padded_row_size); |
+ unpadded_row_size, pixels, padded_row_size, GL_FALSE, &buffer, |
+ service_padded_row_size); |
CheckGLError(); |
} |
@@ -2645,30 +2816,57 @@ void GLES2Implementation::TexSubImage3D( |
<< GLES2Util::GetStringPixelType(type) << ", " |
<< static_cast<const void*>(pixels) << ")"); |
- if (level < 0 || height < 0 || width < 0 || depth < 0) { |
+ if (level < 0 || height < 0 || width < 0 || depth < 0 || |
+ xoffset < 0 || yoffset < 0 || zoffset < 0) { |
SetGLError(GL_INVALID_VALUE, "glTexSubImage3D", "dimension < 0"); |
return; |
} |
- if (height == 0 || width == 0 || depth == 0) { |
- return; |
- } |
- uint32_t temp_size; |
+ uint32_t size; |
uint32_t unpadded_row_size; |
uint32_t padded_row_size; |
- if (!GLES2Util::ComputeImageDataSizes( |
- width, height, depth, format, type, unpack_alignment_, &temp_size, |
- &unpadded_row_size, &padded_row_size)) { |
- SetGLError(GL_INVALID_VALUE, "glTexSubImage3D", "size to large"); |
+ uint32_t skip_size; |
+ PixelStoreParams params = GetUnpackParameters(k3D); |
+ if (!GLES2Util::ComputeImageDataSizesES3(width, height, depth, |
+ format, type, |
+ params, |
+ &size, |
+ &unpadded_row_size, |
+ &padded_row_size, |
+ &skip_size, |
+ nullptr)) { |
+ SetGLError(GL_INVALID_VALUE, "glTexSubImage3D", "image size to large"); |
+ return; |
+ } |
+ |
+ if (bound_pixel_unpack_buffer_) { |
+ base::CheckedNumeric<uint32_t> offset = ToGLuint(pixels); |
+ offset += skip_size; |
+ if (!offset.IsValid()) { |
+ SetGLError(GL_INVALID_VALUE, "glTexSubImage3D", "skip size too large"); |
+ return; |
+ } |
+ helper_->TexSubImage3D( |
+ target, level, xoffset, yoffset, zoffset, width, height, depth, |
+ format, type, 0, offset.ValueOrDefault(0), false); |
+ CheckGLError(); |
return; |
} |
// If there's a pixel unpack buffer bound use it when issuing TexSubImage2D. |
if (bound_pixel_unpack_transfer_buffer_id_) { |
+ if (unpack_row_length_ > 0 || unpack_image_height_ > 0 || |
+ unpack_skip_pixels_ > 0 || unpack_skip_rows_ > 0 || |
+ unpack_skip_images_ > 0) { |
+ SetGLError(GL_INVALID_OPERATION, "glTexSubImage2D", |
+ "No ES3 pack parameters with pixel unpack transfer buffer."); |
+ return; |
+ } |
+ DCHECK_EQ(0u, skip_size); |
GLuint offset = ToGLuint(pixels); |
BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( |
bound_pixel_unpack_transfer_buffer_id_, |
- "glTexSubImage3D", offset, temp_size); |
+ "glTexSubImage3D", offset, size); |
if (buffer && buffer->shm_id() != -1) { |
helper_->TexSubImage3D( |
target, level, xoffset, yoffset, zoffset, width, height, depth, |
@@ -2679,37 +2877,44 @@ void GLES2Implementation::TexSubImage3D( |
return; |
} |
- // compute the advance bytes per row for the src pixels |
- uint32_t src_padded_row_size; |
- if (unpack_row_length_ > 0) { |
- if (!GLES2Util::ComputeImagePaddedRowSize( |
- unpack_row_length_, format, type, unpack_alignment_, |
- &src_padded_row_size)) { |
- SetGLError( |
- GL_INVALID_VALUE, "glTexImage3D", "unpack row length too large"); |
+ if (width == 0 || height == 0 || height == 0) { |
+ // No need to worry about pixel data. |
+ helper_->TexSubImage2D(target, level, xoffset, yoffset, width, height, |
+ format, type, 0, 0, false); |
+ CheckGLError(); |
+ return; |
+ } |
+ |
+ // Compute the advance bytes per row on the service side |
+ // Note |size| is recomputed here if needed. |
+ uint32_t service_padded_row_size; |
+ if ((unpack_row_length_ > 0 && unpack_row_length_ != width) || |
+ (unpack_image_height_ > 0 && unpack_image_height_ != height)) { |
+ PixelStoreParams service_params; |
+ service_params.alignment = unpack_alignment_; |
+ if (!GLES2Util::ComputeImageDataSizesES3(width, height, depth, |
+ format, type, |
+ service_params, |
+ &size, |
+ nullptr, |
+ &service_padded_row_size, |
+ nullptr, |
+ nullptr)) { |
+ SetGLError(GL_INVALID_VALUE, "glTexSubImage3D", "image size too large"); |
return; |
} |
} else { |
- src_padded_row_size = padded_row_size; |
+ service_padded_row_size = padded_row_size; |
} |
- uint32_t src_height = |
- unpack_image_height_ > 0 ? unpack_image_height_ : height; |
// advance pixels pointer past the skip images/rows/pixels |
- pixels = reinterpret_cast<const int8_t*>(pixels) + |
- unpack_skip_images_ * src_padded_row_size * src_height + |
- unpack_skip_rows_ * src_padded_row_size; |
- if (unpack_skip_pixels_) { |
- uint32_t group_size = GLES2Util::ComputeImageGroupSize(format, type); |
- pixels = reinterpret_cast<const int8_t*>(pixels) + |
- unpack_skip_pixels_ * group_size; |
- } |
+ pixels = reinterpret_cast<const int8_t*>(pixels) + skip_size; |
- ScopedTransferBufferPtr buffer(temp_size, helper_, transfer_buffer_); |
+ ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_); |
TexSubImage3DImpl( |
target, level, xoffset, yoffset, zoffset, width, height, depth, |
- format, type, unpadded_row_size, pixels, src_padded_row_size, GL_FALSE, |
- &buffer, padded_row_size); |
+ format, type, unpadded_row_size, pixels, padded_row_size, GL_FALSE, |
+ &buffer, service_padded_row_size); |
CheckGLError(); |
} |
@@ -2747,6 +2952,8 @@ void GLES2Implementation::TexSubImage2DImpl(GLenum target, |
DCHECK_GE(level, 0); |
DCHECK_GT(height, 0); |
DCHECK_GT(width, 0); |
+ DCHECK_GE(xoffset, 0); |
+ DCHECK_GE(yoffset, 0); |
const int8_t* source = reinterpret_cast<const int8_t*>(pixels); |
// Transfer by rows. |
@@ -2794,9 +3001,12 @@ void GLES2Implementation::TexSubImage3DImpl(GLenum target, |
uint32_t buffer_padded_row_size) { |
DCHECK(buffer); |
DCHECK_GE(level, 0); |
- DCHECK_GT(height, 0); |
DCHECK_GT(width, 0); |
+ DCHECK_GT(height, 0); |
DCHECK_GT(depth, 0); |
+ DCHECK_GE(xoffset, 0); |
+ DCHECK_GE(yoffset, 0); |
+ DCHECK_GE(zoffset, 0); |
const int8_t* source = reinterpret_cast<const int8_t*>(pixels); |
GLsizei total_rows = height * depth; |
GLint row_index = 0, depth_index = 0; |
@@ -2848,24 +3058,14 @@ void GLES2Implementation::TexSubImage3DImpl(GLenum target, |
uint32_t image_size_dst = buffer_padded_row_size * height; |
uint32_t image_size_src = pixels_padded_row_size * src_height; |
for (GLint ii = 0; ii < num_images; ++ii) { |
- uint32_t my_unpadded_row_size; |
- if (total_rows == num_rows && ii + 1 == num_images) |
- my_unpadded_row_size = unpadded_row_size; |
- else |
- my_unpadded_row_size = pixels_padded_row_size; |
CopyRectToBuffer( |
- source + ii * image_size_src, my_height, my_unpadded_row_size, |
+ source + ii * image_size_src, my_height, unpadded_row_size, |
pixels_padded_row_size, buffer_pointer + ii * image_size_dst, |
buffer_padded_row_size); |
} |
} else { |
- uint32_t my_unpadded_row_size; |
- if (total_rows == num_rows) |
- my_unpadded_row_size = unpadded_row_size; |
- else |
- my_unpadded_row_size = pixels_padded_row_size; |
CopyRectToBuffer( |
- source, my_height, my_unpadded_row_size, pixels_padded_row_size, |
+ source, my_height, unpadded_row_size, pixels_padded_row_size, |
buffer->address(), buffer_padded_row_size); |
} |
helper_->TexSubImage3D( |
@@ -3538,23 +3738,6 @@ void GLES2Implementation::ReadPixels( |
return; |
} |
- // glReadPixel pads the size of each row of pixels by an amount specified by |
- // glPixelStorei. So, we have to take that into account both in the fact that |
- // the pixels returned from the ReadPixel command will include that padding |
- // and that when we copy the results to the user's buffer we need to not |
- // write those padding bytes but leave them as they are. |
- |
- TRACE_EVENT0("gpu", "GLES2::ReadPixels"); |
- typedef cmds::ReadPixels::Result Result; |
- |
- if (bound_pixel_pack_buffer_) { |
- GLuint offset = ToGLuint(pixels); |
- helper_->ReadPixels( |
- xoffset, yoffset, width, height, format, type, 0, offset, 0, 0, false); |
- CheckGLError(); |
- return; |
- } |
- |
uint32_t size; |
uint32_t unpadded_row_size; |
uint32_t padded_row_size; |
@@ -3575,6 +3758,30 @@ void GLES2Implementation::ReadPixels( |
SetGLError(GL_INVALID_VALUE, "glReadPixels", "size too large."); |
return; |
} |
+ |
+ // glReadPixel pads the size of each row of pixels by an amount specified by |
+ // glPixelStorei. So, we have to take that into account both in the fact that |
+ // the pixels returned from the ReadPixel command will include that padding |
+ // and that when we copy the results to the user's buffer we need to not |
+ // write those padding bytes but leave them as they are. |
+ |
+ TRACE_EVENT0("gpu", "GLES2::ReadPixels"); |
+ typedef cmds::ReadPixels::Result Result; |
+ |
+ if (bound_pixel_pack_buffer_) { |
+ base::CheckedNumeric<uint32_t> offset = ToGLuint(pixels); |
+ offset += skip_size; |
+ if (!offset.IsValid()) { |
+ SetGLError(GL_INVALID_VALUE, "glReadPixels", "skip size too large."); |
+ return; |
+ } |
+ helper_->ReadPixels( |
+ xoffset, yoffset, width, height, format, type, 0, |
+ offset.ValueOrDefault(0), 0, 0, false); |
+ CheckGLError(); |
+ return; |
+ } |
+ |
uint32_t service_padded_row_size = 0; |
if (pack_row_length_ > 0 && pack_row_length_ != width) { |
if (!GLES2Util::ComputeImagePaddedRowSize(width, |
@@ -3600,7 +3807,7 @@ void GLES2Implementation::ReadPixels( |
bound_pixel_pack_transfer_buffer_id_, "glReadPixels", offset, size); |
if (buffer && buffer->shm_id() != -1) { |
helper_->ReadPixels(xoffset, yoffset, width, height, format, type, |
- buffer->shm_id(), buffer->shm_offset(), |
+ buffer->shm_id(), buffer->shm_offset() + offset, |
0, 0, true); |
CheckGLError(); |
} |