Index: third_party/WebKit/Source/platform/graphics/gpu/WebGLImageConversion.cpp |
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageConversion.cpp b/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageConversion.cpp |
index 94ed96346338b246a361d940987693eda8a377da..38849d9937831680cd1affa8a12408eaea61b1cb 100644 |
--- a/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageConversion.cpp |
+++ b/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageConversion.cpp |
@@ -1923,8 +1923,26 @@ void FormatConverter::convert() |
return; |
} |
+bool frameIsValid(const SkBitmap& frameBitmap) |
+{ |
+ return !frameBitmap.isNull() |
+ && !frameBitmap.empty() |
+ && frameBitmap.isImmutable() |
+ && frameBitmap.colorType() == kN32_SkColorType; |
+} |
+ |
} // anonymous namespace |
+WebGLImageConversion::PixelStoreParams::PixelStoreParams() |
+ : alignment(4) |
+ , rowLength(0) |
+ , imageHeight(0) |
+ , skipPixels(0) |
+ , skipRows(0) |
+ , skipImages(0) |
+{ |
+} |
+ |
bool WebGLImageConversion::computeFormatAndTypeParameters(GLenum format, GLenum type, unsigned* componentsPerPixel, unsigned* bytesPerComponent) |
{ |
switch (format) { |
@@ -2000,40 +2018,102 @@ bool WebGLImageConversion::computeFormatAndTypeParameters(GLenum format, GLenum |
return true; |
} |
-GLenum WebGLImageConversion::computeImageSizeInBytes(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth, GLint alignment, unsigned* imageSizeInBytes, unsigned* paddingInBytes) |
+GLenum WebGLImageConversion::computeImageSizeInBytes(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth, const PixelStoreParams& params, unsigned* imageSizeInBytes, unsigned* paddingInBytes, unsigned* skipSizeInBytes) |
{ |
ASSERT(imageSizeInBytes); |
- ASSERT(alignment == 1 || alignment == 2 || alignment == 4 || alignment == 8); |
+ ASSERT(params.alignment == 1 || params.alignment == 2 || params.alignment == 4 || params.alignment == 8); |
+ ASSERT(params.rowLength >= 0 && params.imageHeight >= 0); |
+ ASSERT(params.skipPixels >= 0 && params.skipRows >= 0 && params.skipImages >= 0); |
if (width < 0 || height < 0 || depth < 0) |
return GL_INVALID_VALUE; |
- unsigned bytesPerComponent, componentsPerPixel; |
- if (!computeFormatAndTypeParameters(format, type, &bytesPerComponent, &componentsPerPixel)) |
- return GL_INVALID_ENUM; |
if (!width || !height || !depth) { |
*imageSizeInBytes = 0; |
if (paddingInBytes) |
*paddingInBytes = 0; |
+ if (skipSizeInBytes) |
+ *skipSizeInBytes = 0; |
return GL_NO_ERROR; |
} |
- CheckedInt<uint32_t> checkedValue(bytesPerComponent * componentsPerPixel); |
- checkedValue *= width; |
+ |
+ int rowLength = params.rowLength > 0 ? params.rowLength : width; |
+ int imageHeight = params.imageHeight > 0 ? params.imageHeight : height; |
+ |
+ unsigned bytesPerComponent, componentsPerPixel; |
+ if (!computeFormatAndTypeParameters(format, type, &bytesPerComponent, &componentsPerPixel)) |
+ return GL_INVALID_ENUM; |
+ unsigned bytesPerGroup = bytesPerComponent * componentsPerPixel; |
+ CheckedInt<uint32_t> checkedValue = static_cast<uint32_t>(rowLength); |
+ checkedValue *= bytesPerGroup; |
if (!checkedValue.isValid()) |
return GL_INVALID_VALUE; |
- unsigned validRowSize = checkedValue.value(); |
+ |
+ unsigned lastRowSize; |
+ if (params.rowLength > 0 && params.rowLength != width) { |
+ CheckedInt<uint32_t> tmp = width; |
+ tmp *= bytesPerGroup; |
+ if (!tmp.isValid()) |
+ return GL_INVALID_VALUE; |
+ lastRowSize = tmp.value(); |
+ } else { |
+ lastRowSize = checkedValue.value(); |
+ } |
+ |
unsigned padding = 0; |
- unsigned residual = validRowSize % alignment; |
+ unsigned residual = checkedValue.value() % params.alignment; |
if (residual) { |
- padding = alignment - residual; |
+ padding = params.alignment - residual; |
checkedValue += padding; |
} |
- // Last row needs no padding. |
- checkedValue *= (height * depth - 1); |
- checkedValue += validRowSize; |
+ if (!checkedValue.isValid()) |
+ return GL_INVALID_VALUE; |
+ unsigned paddedRowSize = checkedValue.value(); |
+ |
+ CheckedInt<uint32_t> rows = imageHeight; |
+ rows *= (depth - 1); |
+ // Last image is not affected by IMAGE_HEIGHT parameter. |
+ rows += height; |
+ if (!rows.isValid()) |
+ return GL_INVALID_VALUE; |
+ checkedValue *= (rows.value() - 1); |
+ // Last row is not affected by ROW_LENGTH parameter. |
+ checkedValue += lastRowSize; |
if (!checkedValue.isValid()) |
return GL_INVALID_VALUE; |
*imageSizeInBytes = checkedValue.value(); |
if (paddingInBytes) |
*paddingInBytes = padding; |
+ |
+ CheckedInt<uint32_t> skipSize = 0; |
+ if (params.skipImages > 0) { |
+ CheckedInt<uint32_t> tmp = paddedRowSize; |
+ tmp *= imageHeight; |
+ tmp *= params.skipImages; |
+ if (!tmp.isValid()) |
+ return GL_INVALID_VALUE; |
+ skipSize += tmp.value(); |
+ } |
+ if (params.skipRows > 0) { |
+ CheckedInt<uint32_t> tmp = paddedRowSize; |
+ tmp *= params.skipRows; |
+ if (!tmp.isValid()) |
+ return GL_INVALID_VALUE; |
+ skipSize += tmp.value(); |
+ } |
+ if (params.skipPixels > 0) { |
+ CheckedInt<uint32_t> tmp = bytesPerGroup; |
+ tmp *= params.skipPixels; |
+ if (!tmp.isValid()) |
+ return GL_INVALID_VALUE; |
+ skipSize += tmp.value(); |
+ } |
+ if (!skipSize.isValid()) |
+ return GL_INVALID_VALUE; |
+ if (skipSizeInBytes) |
+ *skipSizeInBytes = skipSize.value(); |
+ |
+ checkedValue += skipSize.value(); |
+ if (!checkedValue.isValid()) |
+ return GL_INVALID_VALUE; |
return GL_NO_ERROR; |
} |
@@ -2044,18 +2124,6 @@ WebGLImageConversion::ImageExtractor::ImageExtractor(Image* image, ImageHtmlDomS |
extractImage(premultiplyAlpha, ignoreGammaAndColorProfile); |
} |
-namespace { |
- |
-bool frameIsValid(const SkBitmap& frameBitmap) |
-{ |
- return !frameBitmap.isNull() |
- && !frameBitmap.empty() |
- && frameBitmap.isImmutable() |
- && frameBitmap.colorType() == kN32_SkColorType; |
-} |
- |
-} // anonymous namespace |
- |
void WebGLImageConversion::ImageExtractor::extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile) |
{ |
ASSERT(!m_imagePixelLocker); |
@@ -2230,7 +2298,9 @@ bool WebGLImageConversion::packImageData( |
unsigned packedSize; |
// Output data is tightly packed (alignment == 1). |
- if (computeImageSizeInBytes(format, type, width, height, 1, 1, &packedSize, 0) != GL_NO_ERROR) |
+ PixelStoreParams params; |
+ params.alignment = 1; |
+ if (computeImageSizeInBytes(format, type, width, height, 1, params, &packedSize, 0, 0) != GL_NO_ERROR) |
return false; |
data.resize(packedSize); |
@@ -2257,7 +2327,9 @@ bool WebGLImageConversion::extractImageData( |
unsigned packedSize; |
// Output data is tightly packed (alignment == 1). |
- if (computeImageSizeInBytes(format, type, width, height, 1, 1, &packedSize, 0) != GL_NO_ERROR) |
+ PixelStoreParams params; |
+ params.alignment = 1; |
+ if (computeImageSizeInBytes(format, type, width, height, 1, params, &packedSize, 0, 0) != GL_NO_ERROR) |
return false; |
data.resize(packedSize); |