| 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();
|
| }
|
|
|