diff options
author | bsalomon@google.com <bsalomon@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-10 17:39:34 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-10 17:39:34 +0000 |
commit | 3458a64a85abdd0d95678565bf7c6d20c67a0e4e (patch) | |
tree | f69e05075fd9dc458fc43cc93b64e02066637d35 /gpu | |
parent | 6d32cb06edeb614f99568027e06a32c13c6eb6bb (diff) | |
download | chromium_src-3458a64a85abdd0d95678565bf7c6d20c67a0e4e.zip chromium_src-3458a64a85abdd0d95678565bf7c6d20c67a0e4e.tar.gz chromium_src-3458a64a85abdd0d95678565bf7c6d20c67a0e4e.tar.bz2 |
Add GL_EXT_unpack_subimage support to command buffer client code.
BUG=121780
Review URL: https://chromiumcodereview.appspot.com/10012057
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@131579 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rw-r--r-- | gpu/GLES2/extensions/CHROMIUM/CHROMIUM_flipy.txt | 75 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation.cc | 230 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation.h | 19 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation_unittest.cc | 150 | ||||
-rw-r--r-- | gpu/command_buffer/common/gles2_cmd_utils.cc | 37 | ||||
-rw-r--r-- | gpu/command_buffer/common/gles2_cmd_utils.h | 15 | ||||
-rw-r--r-- | gpu/command_buffer/common/gles2_cmd_utils_unittest.cc | 129 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 78 | ||||
-rw-r--r-- | gpu/command_buffer/service/texture_manager.cc | 4 |
9 files changed, 512 insertions, 225 deletions
diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_flipy.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_flipy.txt index b51f541..7511fc4 100644 --- a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_flipy.txt +++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_flipy.txt @@ -8,7 +8,7 @@ Name Strings Version - Last Modifed Date: July 22, 2011 + Last Modifed Date: April 9, 2012 Dependencies @@ -28,6 +28,77 @@ New Tokens UNPACK_FLIP_Y_CHROMIUM 0x9240 +Additions to the OpenGL ES 2.0 Specification + + Modifications to Table 3.1 (PixelStore Parameters) + + Add the following entry: + + Parameter Name Type Initial Value Valid Range + ============== ==== ============= =========== + UNPACK_FLIP_Y_CHROMIUM boolean FALSE {TRUE, FALSE} + + Modifications to 3.6.2 Transfer of Pixel Rectangles, in the Unpacking + section: + + Change + "If p indicates the location in memory of the first element of the first + row, then the first element of the Nth row is indicated by + p + Nk (3.9)" + to + "If p indicates the location in memory of the first element of the first + row, then the first element of the Nth row is indicated by + p + Nk (3.9) + if UNPACK_FLIP_Y is FALSE. Otherwise, the first element of the Nth row + is indicated by + p - Nk (3.10) + + After the sentence + + "If the number of bits per element is not 1, 2, 4, or 8 times the number + of bits in a GL ubyte, then k = nl for all values of a." + + insert: + + "If UNPACK_FLIP_Y_CHROMIUM is FALSE then p is equal to pixels. Otherwise + p is pixels + (height - 1)k." + +Interactions with GL_EXT_unpack_subimage + + Do not add the sentence "If UNPACK_FLIP_Y_CHROMIUM is FALSE ..." described + in this extension. Instead do the following after applying + GL_EXT_unpack_subimage: + + Change + + "There is a mechanism for selecting a sub-rectangle of groups + from a larger containing rectangle. This mechanism relies on + three integer parameters: UNPACK_ROW_LENGTH, UNPACK_SKIP_ROWS, + and UNPACK_SKIP_PIXELS. Before obtaining the first group from + memory, the pointer supplied to TexImage2D is effectively + advanced by (UNPACK_SKIP_PIXELS)n + (UNPACK_SKIP_ROWS)k + elements. Then <width> groups are obtained from contiguous + elements in memory (without advancing the pointer), after + which the pointer is advanced by k elements. <height> sets of + <width> groups of values are obtained this way. See figure + 3.6." + + to + + "There is a mechanism for selecting a sub-rectangle of groups + from a larger containing rectangle. This mechanism relies on + three integer parameters: UNPACK_ROW_LENGTH, UNPACK_SKIP_ROWS, + and UNPACK_SKIP_PIXELS. IF UNPACK_FLIP_Y_CHROMIUM is FALSE then + p, the location of the first element of the first + group, is pixels + (UNPACK_SKIP_PIXELS)n + (UNPACK_SKIP_ROWS)k. + When UNPACK_FLIP_Y_CHROMIUM is TRUE then p is pixels + + (UNPACK_SKIP_PIXELS)n + (UNPACK_SKIP_ROWS + height - 1)k. After + p is determined <width> groups are obtained from contiguous + elements in memory (without advancing the pointer), after which + the pointer is advanced by +/-k elements depending on the value + of UNPACK_CHROMIUM_FLIP_Y. <height> sets of <width> groups of + values are obtained this way. See figure 3.6." + New Procedures and Functions None. @@ -43,3 +114,5 @@ New State Revision History 7/22/2011 Documented the extension + 4/09/2012 Added more documentation and described interactions with + GL_EXT_unpack_subimage diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 0230f25..4f5d427 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc @@ -389,6 +389,9 @@ GLES2Implementation::GLES2Implementation( pack_alignment_(4), unpack_alignment_(4), unpack_flip_y_(false), + unpack_row_length_(0), + unpack_skip_rows_(0), + unpack_skip_pixels_(0), pack_reverse_row_order_(false), active_texture_unit_(0), bound_framebuffer_(0), @@ -1240,6 +1243,15 @@ void GLES2Implementation::PixelStorei(GLenum pname, GLint param) { case GL_UNPACK_ALIGNMENT: unpack_alignment_ = param; break; + case GL_UNPACK_ROW_LENGTH: + unpack_row_length_ = param; + return; + case GL_UNPACK_SKIP_ROWS: + unpack_skip_rows_ = param; + return; + case GL_UNPACK_SKIP_PIXELS: + unpack_skip_pixels_ = param; + return; case GL_UNPACK_FLIP_Y_CHROMIUM: unpack_flip_y_ = (param != 0); return; @@ -1512,45 +1524,41 @@ void GLES2Implementation::CompressedTexSubImage2D( helper_->SetBucketSize(kResultBucketId, 0); } -bool GLES2Implementation::CopyRectToBufferFlipped( - const void* pixels, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - void* buffer) { - if (width == 0 || height == 0) { - return true; - } - - uint32 temp_size; - if (!GLES2Util::ComputeImageDataSize( - width, 1, format, type, unpack_alignment_, &temp_size)) { - SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: size to large"); - return false; - } - GLsizeiptr unpadded_row_size = temp_size; - if (!GLES2Util::ComputeImageDataSize( - width, 2, format, type, unpack_alignment_, &temp_size)) { - SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: size to large"); - return false; - } - GLsizeiptr padded_row_size = temp_size - unpadded_row_size; - if (padded_row_size < 0 || unpadded_row_size < 0) { - SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: size to large"); - return false; - } +namespace { +void CopyRectToBuffer( + const void* pixels, + uint32 height, + uint32 unpadded_row_size, + uint32 pixels_padded_row_size, + bool flip_y, + void* buffer, + uint32 buffer_padded_row_size) { const int8* source = static_cast<const int8*>(pixels); - int8* dest = static_cast<int8*>(buffer) + padded_row_size * (height - 1); - for (; height; --height) { + int8* dest = static_cast<int8*>(buffer); + if (flip_y || pixels_padded_row_size != buffer_padded_row_size) { + if (flip_y) { + dest += buffer_padded_row_size * (height - 1); + } + // the last row is copied unpadded at the end + for (; height > 1; --height) { + memcpy(dest, source, buffer_padded_row_size); + if (flip_y) { + dest -= buffer_padded_row_size; + } else { + dest += buffer_padded_row_size; + } + source += pixels_padded_row_size; + } memcpy(dest, source, unpadded_row_size); - dest -= padded_row_size; - source += padded_row_size; + } else { + uint32 size = (height - 1) * pixels_padded_row_size + unpadded_row_size; + memcpy(dest, source, size); } - return true; } +} // anonymous namespace + void GLES2Implementation::TexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, @@ -1569,8 +1577,11 @@ void GLES2Implementation::TexImage2D( return; } uint32 size; - if (!GLES2Util::ComputeImageDataSize( - width, height, format, type, unpack_alignment_, &size)) { + uint32 unpadded_row_size; + uint32 padded_row_size; + if (!GLES2Util::ComputeImageDataSizes( + width, height, format, type, unpack_alignment_, &size, + &unpadded_row_size, &padded_row_size)) { SetGLError(GL_INVALID_VALUE, "glTexImage2D: image size too large"); return; } @@ -1583,6 +1594,28 @@ void GLES2Implementation::TexImage2D( return; } + // compute the advance bytes per row for the src pixels + uint32 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"); + return; + } + } else { + src_padded_row_size = padded_row_size; + } + + // advance pixels pointer past the skip rows and skip pixels + pixels = reinterpret_cast<const int8*>(pixels) + + unpack_skip_rows_ * src_padded_row_size; + if (unpack_skip_pixels_) { + uint32 group_size = GLES2Util::ComputeImageGroupSize(format, type); + pixels = reinterpret_cast<const int8*>(pixels) + + unpack_skip_pixels_ * group_size; + } + // Check if we can send it all at once. ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_); if (!buffer.valid()) { @@ -1590,19 +1623,12 @@ void GLES2Implementation::TexImage2D( } if (buffer.size() >= size) { - bool copy_success = true; - if (unpack_flip_y_) { - copy_success = CopyRectToBufferFlipped( - pixels, width, height, format, type, buffer.address()); - } else { - memcpy(buffer.address(), pixels, size); - } - - if (copy_success) { - helper_->TexImage2D( - target, level, internalformat, width, height, border, format, type, - buffer.shm_id(), buffer.offset()); - } + CopyRectToBuffer( + pixels, height, unpadded_row_size, src_padded_row_size, unpack_flip_y_, + buffer.address(), padded_row_size); + helper_->TexImage2D( + target, level, internalformat, width, height, border, format, type, + buffer.shm_id(), buffer.offset()); return; } @@ -1611,8 +1637,8 @@ void GLES2Implementation::TexImage2D( target, level, internalformat, width, height, border, format, type, 0, 0); TexSubImage2DImpl( - target, level, 0, 0, width, height, format, type, pixels, GL_TRUE, - &buffer); + target, level, 0, 0, width, height, format, type, unpadded_row_size, + pixels, src_padded_row_size, GL_TRUE, &buffer, padded_row_size); } void GLES2Implementation::TexSubImage2D( @@ -1637,16 +1663,42 @@ void GLES2Implementation::TexSubImage2D( } uint32 temp_size; - if (!GLES2Util::ComputeImageDataSize( - width, height, format, type, unpack_alignment_, &temp_size)) { + uint32 unpadded_row_size; + uint32 padded_row_size; + if (!GLES2Util::ComputeImageDataSizes( + width, height, format, type, unpack_alignment_, &temp_size, + &unpadded_row_size, &padded_row_size)) { SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: size to large"); return; } + // compute the advance bytes per row for the src pixels + uint32 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"); + return; + } + } else { + src_padded_row_size = padded_row_size; + } + + // advance pixels pointer past the skip rows and skip pixels + pixels = reinterpret_cast<const int8*>(pixels) + + unpack_skip_rows_ * src_padded_row_size; + if (unpack_skip_pixels_) { + uint32 group_size = GLES2Util::ComputeImageGroupSize(format, type); + pixels = reinterpret_cast<const int8*>(pixels) + + unpack_skip_pixels_ * group_size; + } + ScopedTransferBufferPtr buffer(temp_size, helper_, transfer_buffer_); TexSubImage2DImpl( - target, level, xoffset, yoffset, width, height, format, type, pixels, - GL_FALSE, &buffer); + target, level, xoffset, yoffset, width, height, format, type, + unpadded_row_size, pixels, src_padded_row_size, GL_FALSE, &buffer, + padded_row_size); } static GLint ComputeNumRowsThatFitInBuffer( @@ -1662,37 +1714,20 @@ static GLint ComputeNumRowsThatFitInBuffer( void GLES2Implementation::TexSubImage2DImpl( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, - GLsizei height, GLenum format, GLenum type, const void* pixels, - GLboolean internal, ScopedTransferBufferPtr* buffer) { + GLsizei height, GLenum format, GLenum type, uint32 unpadded_row_size, + const void* pixels, uint32 pixels_padded_row_size, GLboolean internal, + ScopedTransferBufferPtr* buffer, uint32 buffer_padded_row_size) { GPU_DCHECK(buffer); GPU_DCHECK_GE(level, 0); GPU_DCHECK_GT(height, 0); GPU_DCHECK_GT(width, 0); - const int8* source = static_cast<const int8*>(pixels); - uint32 temp_size; - if (!GLES2Util::ComputeImageDataSize( - width, 1, format, type, unpack_alignment_, &temp_size)) { - SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: size to large"); - return; - } - GLsizeiptr unpadded_row_size = temp_size; - if (!GLES2Util::ComputeImageDataSize( - width, 2, format, type, unpack_alignment_, &temp_size)) { - SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: size to large"); - return; - } - GLsizeiptr padded_row_size = temp_size - unpadded_row_size; - if (padded_row_size < 0 || unpadded_row_size < 0) { - SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: size to large"); - return; - } - + const int8* source = reinterpret_cast<const int8*>(pixels); GLint original_yoffset = yoffset; // Transfer by rows. while (height) { unsigned int desired_size = - padded_row_size * (height - 1) + unpadded_row_size; + buffer_padded_row_size * (height - 1) + unpadded_row_size; if (!buffer->valid() || buffer->size() == 0) { buffer->Reset(desired_size); if (!buffer->valid()) { @@ -1701,24 +1736,18 @@ void GLES2Implementation::TexSubImage2DImpl( } GLint num_rows = ComputeNumRowsThatFitInBuffer( - padded_row_size, unpadded_row_size, buffer->size()); + buffer_padded_row_size, unpadded_row_size, buffer->size()); num_rows = std::min(num_rows, height); - GLint y; - if (unpack_flip_y_) { - CopyRectToBufferFlipped( - source, width, num_rows, format, type, buffer->address()); - y = original_yoffset + height - num_rows; - } else { - temp_size = padded_row_size * (num_rows - 1) + unpadded_row_size; - memcpy(buffer->address(), source, temp_size); - y = yoffset; - } + CopyRectToBuffer( + source, num_rows, unpadded_row_size, pixels_padded_row_size, + unpack_flip_y_, buffer->address(), buffer_padded_row_size); + GLint y = unpack_flip_y_ ? original_yoffset + height - num_rows : yoffset; helper_->TexSubImage2D( target, level, xoffset, y, width, num_rows, format, type, buffer->shm_id(), buffer->offset(), internal); buffer->Release(); yoffset += num_rows; - source += num_rows * padded_row_size; + source += num_rows * pixels_padded_row_size; height -= num_rows; } } @@ -1945,7 +1974,8 @@ const GLubyte* GLES2Implementation::GetStringHelper(GLenum name) { case GL_EXTENSIONS: str += std::string(str.empty() ? "" : " ") + "GL_CHROMIUM_map_sub " - "GL_CHROMIUM_flipy"; + "GL_CHROMIUM_flipy " + "GL_EXT_unpack_subimage"; break; default: break; @@ -2062,19 +2092,11 @@ void GLES2Implementation::ReadPixels( int8* dest = reinterpret_cast<int8*>(pixels); uint32 temp_size; - if (!GLES2Util::ComputeImageDataSize( - width, 1, format, type, pack_alignment_, &temp_size)) { - SetGLError(GL_INVALID_VALUE, "glReadPixels: size too large."); - return; - } - GLsizeiptr unpadded_row_size = temp_size; - if (!GLES2Util::ComputeImageDataSize( - width, 2, format, type, pack_alignment_, &temp_size)) { - SetGLError(GL_INVALID_VALUE, "glReadPixels: size too large."); - return; - } - GLsizei padded_row_size = temp_size - unpadded_row_size; - if (padded_row_size < 0 || unpadded_row_size < 0) { + uint32 unpadded_row_size; + uint32 padded_row_size; + if (!GLES2Util::ComputeImageDataSizes( + width, 2, format, type, pack_alignment_, &temp_size, &unpadded_row_size, + &padded_row_size)) { SetGLError(GL_INVALID_VALUE, "glReadPixels: size too large."); return; } @@ -2582,8 +2604,8 @@ void* GLES2Implementation::MapTexSubImage2DCHROMIUM( return NULL; } uint32 size; - if (!GLES2Util::ComputeImageDataSize( - width, height, format, type, unpack_alignment_, &size)) { + if (!GLES2Util::ComputeImageDataSizes( + width, height, format, type, unpack_alignment_, &size, NULL, NULL)) { SetGLError( GL_INVALID_VALUE, "MapTexSubImage2DCHROMIUM: image size too large"); return NULL; diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index 69e875c..60fd9c7 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h @@ -413,13 +413,13 @@ class GLES2_IMPL_EXPORT GLES2Implementation { GLuint GetMaxValueInBufferCHROMIUMHelper( GLuint buffer_id, GLsizei count, GLenum type, GLuint offset); - bool CopyRectToBufferFlipped( - const void* pixels, GLsizei width, GLsizei height, GLenum format, - GLenum type, void* buffer); + // The pixels pointer should already account for unpack skip rows and skip + // pixels. void TexSubImage2DImpl( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, - GLsizei height, GLenum format, GLenum type, const void* pixels, - GLboolean internal, ScopedTransferBufferPtr* buffer); + GLsizei height, GLenum format, GLenum type, uint32 unpadded_row_size, + const void* pixels, uint32 pixels_padded_row_size, GLboolean internal, + ScopedTransferBufferPtr* buffer, uint32 buffer_padded_row_size); // Helpers for query functions. bool GetHelper(GLenum pname, GLint* params); @@ -462,6 +462,15 @@ class GLES2_IMPL_EXPORT GLES2Implementation { // unpack yflip as last set by glPixelstorei bool unpack_flip_y_; + // unpack row length as last set by glPixelStorei + GLint unpack_row_length_; + + // unpack skip rows as last set by glPixelStorei + GLint unpack_skip_rows_; + + // unpack skip pixels as last set by glPixelStorei + GLint unpack_skip_pixels_; + // pack reverse row order as last set by glPixelstorei bool pack_reverse_row_order_; diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index e4a1ebe..4bb5830 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc @@ -1836,31 +1836,13 @@ TEST_F(GLES2ImplementationTest, GetIntegerCacheWrite) { EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError()); } -static bool ComputeImageDataSizes( - int width, int height, int format, int type, int unpack_alignment, - uint32* size, uint32* unpadded_row_size, uint32* padded_row_size) { - uint32 temp_size; - if (!GLES2Util::ComputeImageDataSize( - width, 1, format, type, unpack_alignment, &temp_size)) { - return false; - } - *unpadded_row_size = temp_size; - if (!GLES2Util::ComputeImageDataSize( - width, 2, format, type, unpack_alignment, &temp_size)) { - return false; - } - *padded_row_size = temp_size - *unpadded_row_size; - return GLES2Util::ComputeImageDataSize( - width, height, format, type, unpack_alignment, size); -} - static bool CheckRect( int width, int height, GLenum format, GLenum type, int alignment, bool flip_y, const uint8* r1, const uint8* r2) { uint32 size = 0; uint32 unpadded_row_size = 0; uint32 padded_row_size = 0; - if (!ComputeImageDataSizes( + if (!GLES2Util::ComputeImageDataSizes( width, height, format, type, alignment, &size, &unpadded_row_size, &padded_row_size)) { return false; @@ -1965,17 +1947,17 @@ TEST_F(GLES2ImplementationTest, TexImage2D2Writes) { uint32 size = 0; uint32 unpadded_row_size = 0; uint32 padded_row_size = 0; - ASSERT_TRUE(ComputeImageDataSizes( + ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( kWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment, &size, &unpadded_row_size, &padded_row_size)); const GLsizei kHeight = (MaxTransferBufferSize() / padded_row_size) * 2; - ASSERT_TRUE(GLES2Util::ComputeImageDataSize( + ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, - &size)); + &size, NULL, NULL)); uint32 half_size = 0; - ASSERT_TRUE(GLES2Util::ComputeImageDataSize( + ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, - &half_size)); + &half_size, NULL, NULL)); scoped_array<uint8> pixels(new uint8[size]); for (uint32 ii = 0; ii < size; ++ii) { @@ -2073,9 +2055,9 @@ TEST_F(GLES2ImplementationTest, TexSubImage2DFlipY) { }; uint32 sub_2_high_size = 0; - ASSERT_TRUE(GLES2Util::ComputeImageDataSize( + ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( kSubImageWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment, - &sub_2_high_size)); + &sub_2_high_size, NULL, NULL)); ExpectedMemoryInfo mem1 = GetExpectedMemory(sub_2_high_size); ExpectedMemoryInfo mem2 = GetExpectedMemory(sub_2_high_size); @@ -2117,6 +2099,119 @@ TEST_F(GLES2ImplementationTest, TexSubImage2DFlipY) { mem2.ptr)); } +TEST_F(GLES2ImplementationTest, SubImageUnpack) { + static const GLint unpack_alignments[] = { 1, 2, 4, 8 }; + + static const GLenum kFormat = GL_RGB; + static const GLenum kType = GL_UNSIGNED_BYTE; + static const GLint kLevel = 0; + static const GLint kBorder = 0; + // We're testing using the unpack params to pull a subimage out of a larger + // source of pixels. Here we specify the subimage by its border rows / + // columns. + static const GLint kSrcWidth = 33; + static const GLint kSrcSubImageX0 = 11; + static const GLint kSrcSubImageX1 = 20; + static const GLint kSrcSubImageY0 = 18; + static const GLint kSrcSubImageY1 = 23; + static const GLint kSrcSubImageWidth = kSrcSubImageX1 - kSrcSubImageX0; + static const GLint kSrcSubImageHeight = kSrcSubImageY1 - kSrcSubImageY0; + + // these are only used in the texsubimage tests + static const GLint kTexWidth = 1023; + static const GLint kTexHeight = 511; + static const GLint kTexSubXOffset = 419; + static const GLint kTexSubYOffset = 103; + + struct { + PixelStorei pixel_store_i; + TexImage2D tex_image_2d; + } texImageExpected; + + struct { + PixelStorei pixel_store_i; + TexImage2D tex_image_2d; + TexSubImage2D tex_sub_image_2d; + } texSubImageExpected; + + uint32 src_size; + ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( + kSrcWidth, kSrcSubImageY1, kFormat, kType, 8, &src_size, NULL, NULL)); + scoped_array<uint8> src_pixels; + src_pixels.reset(new uint8[src_size]); + for (size_t i = 0; i < src_size; ++i) { + src_pixels[i] = static_cast<int8>(i); + } + + for (int sub = 0; sub < 2; ++sub) { + for (int flip_y = 0; flip_y < 2; ++flip_y) { + for (size_t a = 0; a < arraysize(unpack_alignments); ++a) { + GLint alignment = unpack_alignments[a]; + uint32 size; + uint32 unpadded_row_size; + uint32 padded_row_size; + ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( + kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType, alignment, + &size, &unpadded_row_size, &padded_row_size)); + ASSERT_TRUE(size <= MaxTransferBufferSize()); + ExpectedMemoryInfo mem = GetExpectedMemory(size); + + const void* commands = GetPut(); + gl_->PixelStorei(GL_UNPACK_ALIGNMENT, alignment); + gl_->PixelStorei(GL_UNPACK_ROW_LENGTH, kSrcWidth); + gl_->PixelStorei(GL_UNPACK_SKIP_PIXELS, kSrcSubImageX0); + gl_->PixelStorei(GL_UNPACK_SKIP_ROWS, kSrcSubImageY0); + gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, flip_y); + if (sub) { + gl_->TexImage2D( + GL_TEXTURE_2D, kLevel, kFormat, kTexWidth, kTexHeight, kBorder, + kFormat, kType, NULL); + gl_->TexSubImage2D( + GL_TEXTURE_2D, kLevel, kTexSubXOffset, kTexSubYOffset, + kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType, + src_pixels.get()); + texSubImageExpected.pixel_store_i.Init( + GL_UNPACK_ALIGNMENT, alignment); + texSubImageExpected.tex_image_2d.Init( + GL_TEXTURE_2D, kLevel, kFormat, kTexWidth, kTexHeight, kBorder, + kFormat, kType, 0, 0); + texSubImageExpected.tex_sub_image_2d.Init( + GL_TEXTURE_2D, kLevel, kTexSubXOffset, kTexSubYOffset, + kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType, mem.id, + mem.offset, GL_FALSE); + EXPECT_EQ(0, memcmp( + &texSubImageExpected, commands, sizeof(texSubImageExpected))); + } else { + gl_->TexImage2D( + GL_TEXTURE_2D, kLevel, kFormat, + kSrcSubImageWidth, kSrcSubImageHeight, kBorder, kFormat, kType, + src_pixels.get()); + texImageExpected.pixel_store_i.Init(GL_UNPACK_ALIGNMENT, alignment); + texImageExpected.tex_image_2d.Init( + GL_TEXTURE_2D, kLevel, kFormat, kSrcSubImageWidth, + kSrcSubImageHeight, kBorder, kFormat, kType, mem.id, mem.offset); + EXPECT_EQ(0, memcmp( + &texImageExpected, commands, sizeof(texImageExpected))); + } + uint32 src_padded_row_size; + ASSERT_TRUE(GLES2Util::ComputeImagePaddedRowSize( + kSrcWidth, kFormat, kType, alignment, &src_padded_row_size)); + uint32 bytes_per_group = GLES2Util::ComputeImageGroupSize( + kFormat, kType); + for (int y = 0; y < kSrcSubImageHeight; ++y) { + GLint src_sub_y = flip_y ? kSrcSubImageHeight - y - 1 : y; + const uint8* src_row = src_pixels.get() + + (kSrcSubImageY0 + src_sub_y) * src_padded_row_size + + bytes_per_group * kSrcSubImageX0; + const uint8* dst_row = mem.ptr + y * padded_row_size; + EXPECT_EQ(0, memcmp(src_row, dst_row, unpadded_row_size)); + } + ClearCommands(); + } + } + } +} + // Binds can not be cached with bind_generates_resource = false because // our id might not be valid. More specifically if you bind on contextA then // delete on contextB the resource is still bound on contextA but GetInterger @@ -2181,7 +2276,8 @@ TEST_F(GLES2ImplementationTest, GetString) { const Str7 kString = {"foobar"}; // GL_CHROMIUM_map_sub GL_CHROMIUM_flipy are hard coded into // GLES2Implementation. - const char* expected_str = "foobar GL_CHROMIUM_map_sub GL_CHROMIUM_flipy"; + const char* expected_str = + "foobar GL_CHROMIUM_map_sub GL_CHROMIUM_flipy GL_EXT_unpack_subimage"; const char kBad = 0x12; struct Cmds { cmd::SetBucketSize set_bucket_size1; diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc index aa4abe1..9891268 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils.cc +++ b/gpu/command_buffer/common/gles2_cmd_utils.cc @@ -373,12 +373,31 @@ int BytesPerElement(int type) { } // anonymous namespace +uint32 GLES2Util::ComputeImageGroupSize(int format, int type) { + return BytesPerElement(type) * ElementsPerGroup(format, type); +} + +bool GLES2Util::ComputeImagePaddedRowSize( + int width, int format, int type, int unpack_alignment, + uint32* padded_row_size) { + uint32 bytes_per_group = ComputeImageGroupSize(format, type); + uint32 unpadded_row_size; + if (!SafeMultiplyUint32(width, bytes_per_group, &unpadded_row_size)) { + return false; + } + uint32 temp; + if (!SafeAddUint32(unpadded_row_size, unpack_alignment - 1, &temp)) { + return false; + } + *padded_row_size = (temp / unpack_alignment) * unpack_alignment; + return true; +} + // Returns the amount of data glTexImage2D or glTexSubImage2D will access. -bool GLES2Util::ComputeImageDataSize( +bool GLES2Util::ComputeImageDataSizes( int width, int height, int format, int type, int unpack_alignment, - uint32* size) { - uint32 bytes_per_group = - BytesPerElement(type) * ElementsPerGroup(format, type); + uint32* size, uint32* ret_unpadded_row_size, uint32* ret_padded_row_size) { + uint32 bytes_per_group = ComputeImageGroupSize(format, type); uint32 row_size; if (!SafeMultiplyUint32(width, bytes_per_group, &row_size)) { return false; @@ -397,11 +416,21 @@ bool GLES2Util::ComputeImageDataSize( if (!SafeAddUint32(size_of_all_but_last_row, row_size, size)) { return false; } + if (ret_padded_row_size) { + *ret_padded_row_size = padded_row_size; + } } else { if (!SafeMultiplyUint32(height, row_size, size)) { return false; } + if (ret_padded_row_size) { + *ret_padded_row_size = row_size; + } + } + if (ret_unpadded_row_size) { + *ret_unpadded_row_size = row_size; } + return true; } diff --git a/gpu/command_buffer/common/gles2_cmd_utils.h b/gpu/command_buffer/common/gles2_cmd_utils.h index fd014a1..c4fe663 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils.h +++ b/gpu/command_buffer/common/gles2_cmd_utils.h @@ -103,10 +103,21 @@ class GLES2_UTILS_EXPORT GLES2Util { // function is called. If 0 is returned the id is invalid. int GLGetNumValuesReturned(int id) const; + // Computes the size of a single group of elements from a format and type pair + static uint32 ComputeImageGroupSize(int format, int type); + + // Computes the size of an image row including alignment padding + static bool ComputeImagePaddedRowSize( + int width, int format, int type, int unpack_alignment, + uint32* padded_row_size); + // Computes the size of image data for TexImage2D and TexSubImage2D. - static bool ComputeImageDataSize( + // Optionally the unpadded and padded row sizes can be returned. If height < 2 + // then the padded_row_size will be the same as the unpadded_row_size since + // padding is not necessary. + static bool ComputeImageDataSizes( int width, int height, int format, int type, int unpack_alignment, - uint32* size); + uint32* size, uint32* unpadded_row_size, uint32* padded_row_size); static size_t RenderbufferBytesPerPixel(int format); diff --git a/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc b/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc index cf5a0ee..277461a 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc +++ b/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc @@ -34,77 +34,134 @@ TEST_F(GLES2UtilTest, GLGetNumValuesReturned) { EXPECT_EQ(2, util_.num_shader_binary_formats()); } -TEST_F(GLES2UtilTest, ComputeImageDataSizeFormats) { +TEST_F(GLES2UtilTest, ComputeImageDataSizesFormats) { const uint32 kWidth = 16; const uint32 kHeight = 12; uint32 size; - EXPECT_TRUE(GLES2Util::ComputeImageDataSize( - kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, 1, &size)); + uint32 unpadded_row_size; + uint32 padded_row_size; + EXPECT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, 1, &size, &unpadded_row_size, + &padded_row_size)); EXPECT_EQ(kWidth * kHeight * 3, size); - EXPECT_TRUE(GLES2Util::ComputeImageDataSize( - kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, 1, &size)); + EXPECT_EQ(kWidth * 3, padded_row_size); + EXPECT_EQ(padded_row_size, unpadded_row_size); + EXPECT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, 1, &size, &unpadded_row_size, + &padded_row_size)); EXPECT_EQ(kWidth * kHeight * 4, size); - EXPECT_TRUE(GLES2Util::ComputeImageDataSize( - kWidth, kHeight, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1, &size)); + EXPECT_EQ(kWidth * 4, padded_row_size); + EXPECT_EQ(padded_row_size, unpadded_row_size); + EXPECT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, kHeight, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1, &size, + &unpadded_row_size, &padded_row_size)); EXPECT_EQ(kWidth * kHeight * 1, size); - EXPECT_TRUE(GLES2Util::ComputeImageDataSize( - kWidth, kHeight, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 1, &size)); + EXPECT_EQ(kWidth * 1, padded_row_size); + EXPECT_EQ(padded_row_size, unpadded_row_size); + EXPECT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, kHeight, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 1, &size, + &unpadded_row_size, &padded_row_size)); EXPECT_EQ(kWidth * kHeight * 2, size); - EXPECT_TRUE(GLES2Util::ComputeImageDataSize( - kWidth, kHeight, GL_BGRA_EXT, GL_UNSIGNED_BYTE, 1, &size)); + EXPECT_EQ(kWidth * 2, padded_row_size); + EXPECT_EQ(padded_row_size, unpadded_row_size); + EXPECT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, kHeight, GL_BGRA_EXT, GL_UNSIGNED_BYTE, 1, &size, + &unpadded_row_size, &padded_row_size)); EXPECT_EQ(kWidth * kHeight * 4, size); - EXPECT_TRUE(GLES2Util::ComputeImageDataSize( - kWidth, kHeight, GL_ALPHA, GL_UNSIGNED_BYTE, 1, &size)); + EXPECT_EQ(kWidth * 4, padded_row_size); + EXPECT_EQ(padded_row_size, unpadded_row_size); + EXPECT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, kHeight, GL_ALPHA, GL_UNSIGNED_BYTE, 1, &size, &unpadded_row_size, + &padded_row_size)); EXPECT_EQ(kWidth * kHeight * 1, size); - EXPECT_TRUE(GLES2Util::ComputeImageDataSize( - kWidth, kHeight, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 1, &size)); + EXPECT_EQ(kWidth * 1, padded_row_size); + EXPECT_EQ(padded_row_size, unpadded_row_size); + EXPECT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, kHeight, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 1, &size, + &unpadded_row_size, &padded_row_size)); EXPECT_EQ(kWidth * kHeight * 2, size); - EXPECT_TRUE(GLES2Util::ComputeImageDataSize( + EXPECT_EQ(kWidth * 2, padded_row_size); + EXPECT_EQ(padded_row_size, unpadded_row_size); + EXPECT_TRUE(GLES2Util::ComputeImageDataSizes( kWidth, kHeight, GL_DEPTH_STENCIL_OES, GL_UNSIGNED_INT_24_8_OES, 1, - &size)); + &size, &unpadded_row_size, + &padded_row_size)); EXPECT_EQ(kWidth * kHeight * 4, size); + EXPECT_EQ(kWidth * 4, padded_row_size); + EXPECT_EQ(padded_row_size, unpadded_row_size); } TEST_F(GLES2UtilTest, ComputeImageDataSizeTypes) { const uint32 kWidth = 16; const uint32 kHeight = 12; uint32 size; - EXPECT_TRUE(GLES2Util::ComputeImageDataSize( - kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, 1, &size)); + uint32 unpadded_row_size; + uint32 padded_row_size; + EXPECT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, 1, &size, &unpadded_row_size, + &padded_row_size)); EXPECT_EQ(kWidth * kHeight * 4, size); - EXPECT_TRUE(GLES2Util::ComputeImageDataSize( - kWidth, kHeight, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 1, &size)); + EXPECT_EQ(kWidth * 4, padded_row_size); + EXPECT_EQ(padded_row_size, unpadded_row_size); + EXPECT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, kHeight, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 1, &size, + &unpadded_row_size, &padded_row_size)); EXPECT_EQ(kWidth * kHeight * 2, size); - EXPECT_TRUE(GLES2Util::ComputeImageDataSize( - kWidth, kHeight, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 1, &size)); + EXPECT_EQ(kWidth * 2, padded_row_size); + EXPECT_EQ(padded_row_size, unpadded_row_size); + EXPECT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, kHeight, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 1, &size, + &unpadded_row_size, &padded_row_size)); EXPECT_EQ(kWidth * kHeight * 2, size); - EXPECT_TRUE(GLES2Util::ComputeImageDataSize( - kWidth, kHeight, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 1, &size)); + EXPECT_EQ(kWidth * 2, padded_row_size); + EXPECT_EQ(padded_row_size, unpadded_row_size); + EXPECT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, kHeight, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 1, &size, + &unpadded_row_size, &padded_row_size)); EXPECT_EQ(kWidth * kHeight * 2, size); - EXPECT_TRUE(GLES2Util::ComputeImageDataSize( - kWidth, kHeight, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 1, &size)); + EXPECT_EQ(kWidth * 2, padded_row_size); + EXPECT_EQ(padded_row_size, unpadded_row_size); + EXPECT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, kHeight, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 1, &size, + &unpadded_row_size, &padded_row_size)); EXPECT_EQ(kWidth * kHeight * 4, size); + EXPECT_EQ(kWidth * 4, padded_row_size); + EXPECT_EQ(padded_row_size, unpadded_row_size); } -TEST_F(GLES2UtilTest, ComputeImageDataSizeUnpackAlignment) { +TEST_F(GLES2UtilTest, ComputeImageDataSizesUnpackAlignment) { const uint32 kWidth = 19; const uint32 kHeight = 12; uint32 size; - EXPECT_TRUE(GLES2Util::ComputeImageDataSize( - kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, 1, &size)); + uint32 unpadded_row_size; + uint32 padded_row_size; + EXPECT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, 1, &size, &unpadded_row_size, + &padded_row_size)); EXPECT_EQ(kWidth * kHeight * 3, size); - EXPECT_TRUE(GLES2Util::ComputeImageDataSize( - kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, 2, &size)); + EXPECT_EQ(kWidth * 3, unpadded_row_size); + EXPECT_EQ(kWidth * 3, padded_row_size); + EXPECT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, 2, &size, &unpadded_row_size, + &padded_row_size)); EXPECT_EQ((kWidth * 3 + 1) * (kHeight - 1) + kWidth * 3, size); - EXPECT_TRUE(GLES2Util::ComputeImageDataSize( - kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, 4, &size)); + EXPECT_EQ(kWidth * 3, unpadded_row_size); + EXPECT_EQ(kWidth * 3 + 1, padded_row_size); + EXPECT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, 4, &size, &unpadded_row_size, + &padded_row_size)); EXPECT_EQ((kWidth * 3 + 3) * (kHeight - 1) + kWidth * 3, size); - EXPECT_TRUE(GLES2Util::ComputeImageDataSize( - kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, 8, &size)); + EXPECT_EQ(kWidth * 3, unpadded_row_size); + EXPECT_EQ(kWidth * 3 + 3, padded_row_size); + EXPECT_TRUE(GLES2Util::ComputeImageDataSizes( + kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, 8, &size, &unpadded_row_size, + &padded_row_size)); EXPECT_EQ((kWidth * 3 + 7) * (kHeight - 1) + kWidth * 3, size); + EXPECT_EQ(kWidth * 3, unpadded_row_size); + EXPECT_EQ(kWidth * 3 + 7, padded_row_size); } TEST_F(GLES2UtilTest, RenderbufferBytesPerPixel) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 0a90ec2..45f5aa7 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -1657,8 +1657,9 @@ bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) { bool success = glGetError() == GL_NO_ERROR; if (success) { uint32 image_size = 0; - GLES2Util::ComputeImageDataSize( - size.width(), size.height(), format, GL_UNSIGNED_BYTE, 4, &image_size); + GLES2Util::ComputeImageDataSizes( + size.width(), size.height(), format, GL_UNSIGNED_BYTE, 4, &image_size, + NULL, NULL); estimated_size_ = image_size; decoder_->UpdateBackbufferMemoryAccounting(); } @@ -5971,8 +5972,8 @@ error::Error GLES2DecoderImpl::HandleReadPixels( } typedef gles2::ReadPixels::Result Result; uint32 pixels_size; - if (!GLES2Util::ComputeImageDataSize( - width, height, format, type, pack_alignment_, &pixels_size)) { + if (!GLES2Util::ComputeImageDataSizes( + width, height, format, type, pack_alignment_, &pixels_size, NULL, NULL)) { return error::kOutOfBounds; } void* pixels = GetSharedMemoryAs<void*>( @@ -6017,27 +6018,20 @@ error::Error GLES2DecoderImpl::HandleReadPixels( // The user requested an out of range area. Get the results 1 line // at a time. uint32 temp_size; - if (!GLES2Util::ComputeImageDataSize( - width, 1, format, type, pack_alignment_, &temp_size)) { - SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range"); - return error::kNoError; - } - GLsizei unpadded_row_size = temp_size; - if (!GLES2Util::ComputeImageDataSize( - width, 2, format, type, pack_alignment_, &temp_size)) { - SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range"); - return error::kNoError; - } - GLsizei padded_row_size = temp_size - unpadded_row_size; - if (padded_row_size < 0 || unpadded_row_size < 0) { + uint32 unpadded_row_size; + uint32 padded_row_size; + if (!GLES2Util::ComputeImageDataSizes( + width, 2, format, type, pack_alignment_, &temp_size, + &unpadded_row_size, &padded_row_size)) { SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range"); return error::kNoError; } GLint dest_x_offset = std::max(-x, 0); uint32 dest_row_offset; - if (!GLES2Util::ComputeImageDataSize( - dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) { + if (!GLES2Util::ComputeImageDataSizes( + dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset, NULL, + NULL)) { SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range"); return error::kNoError; } @@ -6072,19 +6066,12 @@ error::Error GLES2DecoderImpl::HandleReadPixels( if ((channels_exist & 0x0008) == 0) { // Set the alpha to 255 because some drivers are buggy in this regard. uint32 temp_size; - if (!GLES2Util::ComputeImageDataSize( - width, 1, format, type, pack_alignment_, &temp_size)) { - SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range"); - return error::kNoError; - } - GLsizei unpadded_row_size = temp_size; - if (!GLES2Util::ComputeImageDataSize( - width, 2, format, type, pack_alignment_, &temp_size)) { - SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range"); - return error::kNoError; - } - GLsizei padded_row_size = temp_size - unpadded_row_size; - if (padded_row_size < 0 || unpadded_row_size < 0) { + + uint32 unpadded_row_size; + uint32 padded_row_size; + if (!GLES2Util::ComputeImageDataSizes( + width, 2, format, type, pack_alignment_, &temp_size, + &unpadded_row_size, &padded_row_size)) { SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range"); return error::kNoError; } @@ -6463,8 +6450,9 @@ bool GLES2DecoderImpl::ClearLevel( bool is_texture_immutable) { // Assumes the size has already been checked. uint32 pixels_size = 0; - if (!GLES2Util::ComputeImageDataSize( - width, height, format, type, unpack_alignment_, &pixels_size)) { + if (!GLES2Util::ComputeImageDataSizes( + width, height, format, type, unpack_alignment_, &pixels_size, NULL, + NULL)) { return false; } scoped_array<char> zero(new char[pixels_size]); @@ -6771,8 +6759,9 @@ error::Error GLES2DecoderImpl::HandleTexImage2D( uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id); uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset); uint32 pixels_size; - if (!GLES2Util::ComputeImageDataSize( - width, height, format, type, unpack_alignment_, &pixels_size)) { + if (!GLES2Util::ComputeImageDataSizes( + width, height, format, type, unpack_alignment_, &pixels_size, NULL, + NULL)) { return error::kOutOfBounds; } const void* pixels = NULL; @@ -6799,8 +6788,8 @@ error::Error GLES2DecoderImpl::HandleTexImage2DImmediate( GLenum format = static_cast<GLenum>(c.format); GLenum type = static_cast<GLenum>(c.type); uint32 size; - if (!GLES2Util::ComputeImageDataSize( - width, height, format, type, unpack_alignment_, &size)) { + if (!GLES2Util::ComputeImageDataSizes( + width, height, format, type, unpack_alignment_, &size, NULL, NULL)) { return error::kOutOfBounds; } const void* pixels = GetImmediateDataAs<const void*>( @@ -7026,8 +7015,9 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D( copyHeight != height) { // some part was clipped so clear the sub rect. uint32 pixels_size = 0; - if (!GLES2Util::ComputeImageDataSize( - width, height, format, type, unpack_alignment_, &pixels_size)) { + if (!GLES2Util::ComputeImageDataSizes( + width, height, format, type, unpack_alignment_, &pixels_size, NULL, + NULL)) { SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large"); return; } @@ -7134,8 +7124,8 @@ error::Error GLES2DecoderImpl::HandleTexSubImage2D( GLenum format = static_cast<GLenum>(c.format); GLenum type = static_cast<GLenum>(c.type); uint32 data_size; - if (!GLES2Util::ComputeImageDataSize( - width, height, format, type, unpack_alignment_, &data_size)) { + if (!GLES2Util::ComputeImageDataSizes( + width, height, format, type, unpack_alignment_, &data_size, NULL, NULL)) { return error::kOutOfBounds; } const void* pixels = GetSharedMemoryAs<const void*>( @@ -7183,8 +7173,8 @@ error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate( GLenum format = static_cast<GLenum>(c.format); GLenum type = static_cast<GLenum>(c.type); uint32 data_size; - if (!GLES2Util::ComputeImageDataSize( - width, height, format, type, unpack_alignment_, &data_size)) { + if (!GLES2Util::ComputeImageDataSizes( + width, height, format, type, unpack_alignment_, &data_size, NULL, NULL)) { return error::kOutOfBounds; } const void* pixels = GetImmediateDataAs<const void*>( diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index 26f4787..055c2ab 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc @@ -265,8 +265,8 @@ void TextureManager::TextureInfo::SetLevelInfo( info.type = type; estimated_size_ -= info.estimated_size; - GLES2Util::ComputeImageDataSize( - width, height, format, type, 4, &info.estimated_size); + GLES2Util::ComputeImageDataSizes( + width, height, format, type, 4, &info.estimated_size, NULL, NULL); estimated_size_ += info.estimated_size; if (!info.cleared) { |