зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1280499 - Allow SKIP_ROWS+height>IMAGE_HEIGHT and fix paranoid uploading. - r=jrmuizel
Top-of-tree test is green now. MozReview-Commit-ID: IbCTHK62qGT
This commit is contained in:
Родитель
3740e5150b
Коммит
ff9844ee32
|
@ -132,6 +132,12 @@ FormatForPackingInfo(const PackingInfo& pi)
|
||||||
|
|
||||||
////////////////////
|
////////////////////
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
ZeroOn2D(TexImageTarget target, uint32_t val)
|
||||||
|
{
|
||||||
|
return (IsTarget3D(target) ? val : 0);
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
FallbackOnZero(uint32_t val, uint32_t fallback)
|
FallbackOnZero(uint32_t val, uint32_t fallback)
|
||||||
{
|
{
|
||||||
|
@ -143,11 +149,13 @@ TexUnpackBlob::TexUnpackBlob(const WebGLContext* webgl, TexImageTarget target,
|
||||||
uint32_t depth, bool isSrcPremult)
|
uint32_t depth, bool isSrcPremult)
|
||||||
: mAlignment(webgl->mPixelStore_UnpackAlignment)
|
: mAlignment(webgl->mPixelStore_UnpackAlignment)
|
||||||
, mRowLength(rowLength)
|
, mRowLength(rowLength)
|
||||||
, mImageHeight(FallbackOnZero(webgl->mPixelStore_UnpackImageHeight, height))
|
, mImageHeight(FallbackOnZero(ZeroOn2D(target,
|
||||||
|
webgl->mPixelStore_UnpackImageHeight),
|
||||||
|
height))
|
||||||
|
|
||||||
, mSkipPixels(webgl->mPixelStore_UnpackSkipPixels)
|
, mSkipPixels(webgl->mPixelStore_UnpackSkipPixels)
|
||||||
, mSkipRows(webgl->mPixelStore_UnpackSkipRows)
|
, mSkipRows(webgl->mPixelStore_UnpackSkipRows)
|
||||||
, mSkipImages(IsTarget3D(target) ? webgl->mPixelStore_UnpackSkipImages : 0)
|
, mSkipImages(ZeroOn2D(target, webgl->mPixelStore_UnpackSkipImages))
|
||||||
|
|
||||||
, mWidth(width)
|
, mWidth(width)
|
||||||
, mHeight(height)
|
, mHeight(height)
|
||||||
|
@ -393,41 +401,54 @@ TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec, const char* fun
|
||||||
zOffset, mWidth, mHeight, mDepth, nullptr);
|
zOffset, mWidth, mHeight, mDepth, nullptr);
|
||||||
gl->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER,
|
gl->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER,
|
||||||
webgl->mBoundPixelUnpackBuffer->mGLName);
|
webgl->mBoundPixelUnpackBuffer->mGLName);
|
||||||
|
if (*out_error)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////
|
//////
|
||||||
|
|
||||||
|
// Make our sometimes-implicit values explicit. Also this keeps them constant when we
|
||||||
|
// ask for height=mHeight-1 and such.
|
||||||
|
gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, mRowLength);
|
||||||
|
gl->fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT, mImageHeight);
|
||||||
|
|
||||||
if (mDepth > 1) {
|
if (mDepth > 1) {
|
||||||
*out_error = DoTexOrSubImage(true, gl, target, level, dui, xOffset, yOffset,
|
*out_error = DoTexOrSubImage(true, gl, target, level, dui, xOffset, yOffset,
|
||||||
zOffset, mWidth, mHeight, mDepth-1, uploadPtr);
|
zOffset, mWidth, mHeight, mDepth-1, uploadPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip the images we uploaded.
|
||||||
|
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES, mSkipImages + mDepth - 1);
|
||||||
|
|
||||||
if (mHeight > 1) {
|
if (mHeight > 1) {
|
||||||
*out_error = DoTexOrSubImage(true, gl, target, level, dui, xOffset, yOffset,
|
*out_error = DoTexOrSubImage(true, gl, target, level, dui, xOffset, yOffset,
|
||||||
zOffset+mDepth-1, mWidth, mHeight-1, 1, uploadPtr);
|
zOffset+mDepth-1, mWidth, mHeight-1, 1, uploadPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t imageStride = rowStride.value() * mImageHeight;
|
const auto totalSkipRows = CheckedUint32(mSkipImages) * mImageHeight + mSkipRows;
|
||||||
|
const auto totalFullRows = CheckedUint32(mDepth - 1) * mImageHeight + mHeight - 1;
|
||||||
|
const auto tailOffsetRows = totalSkipRows + totalFullRows;
|
||||||
|
|
||||||
const uint32_t usedImages = mSkipImages + mDepth;
|
const auto tailOffsetBytes = tailOffsetRows * rowStride;
|
||||||
const uint32_t usedRows = mSkipRows + mHeight;
|
|
||||||
|
|
||||||
uploadPtr += (usedImages - 1) * imageStride;
|
uploadPtr += tailOffsetBytes.value();
|
||||||
uploadPtr += (usedRows - 1) * rowStride.value();
|
|
||||||
|
|
||||||
//////
|
//////
|
||||||
|
|
||||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1);
|
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1); // No stride padding.
|
||||||
gl->fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT, 0);
|
gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0); // No padding in general.
|
||||||
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES, 0);
|
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES, 0); // Don't skip images,
|
||||||
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS, 0);
|
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS, 0); // or rows.
|
||||||
|
// Keep skipping pixels though!
|
||||||
|
|
||||||
*out_error = DoTexOrSubImage(true, gl, target, level, dui, xOffset,
|
*out_error = DoTexOrSubImage(true, gl, target, level, dui, xOffset,
|
||||||
yOffset+mHeight-1, zOffset+mDepth-1, mWidth, 1, 1,
|
yOffset+mHeight-1, zOffset+mDepth-1, mWidth, 1, 1,
|
||||||
uploadPtr);
|
uploadPtr);
|
||||||
|
|
||||||
|
// Reset all our modified state.
|
||||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, webgl->mPixelStore_UnpackAlignment);
|
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, webgl->mPixelStore_UnpackAlignment);
|
||||||
gl->fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT, webgl->mPixelStore_UnpackImageHeight);
|
gl->fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT, webgl->mPixelStore_UnpackImageHeight);
|
||||||
|
gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, webgl->mPixelStore_UnpackRowLength);
|
||||||
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES, webgl->mPixelStore_UnpackSkipImages);
|
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES, webgl->mPixelStore_UnpackSkipImages);
|
||||||
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS, webgl->mPixelStore_UnpackSkipRows);
|
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS, webgl->mPixelStore_UnpackSkipRows);
|
||||||
|
|
||||||
|
|
|
@ -129,34 +129,33 @@ bool
|
||||||
WebGLContext::ValidateUnpackPixels(const char* funcName, uint32_t fullRows,
|
WebGLContext::ValidateUnpackPixels(const char* funcName, uint32_t fullRows,
|
||||||
uint32_t tailPixels, webgl::TexUnpackBlob* blob)
|
uint32_t tailPixels, webgl::TexUnpackBlob* blob)
|
||||||
{
|
{
|
||||||
|
auto skipPixels = CheckedUint32(blob->mSkipPixels);
|
||||||
|
skipPixels += CheckedUint32(blob->mSkipRows);
|
||||||
|
|
||||||
const auto usedPixelsPerRow = CheckedUint32(blob->mSkipPixels) + blob->mWidth;
|
const auto usedPixelsPerRow = CheckedUint32(blob->mSkipPixels) + blob->mWidth;
|
||||||
const auto usedRowsPerImage = CheckedUint32(blob->mSkipRows) + blob->mHeight;
|
if (!usedPixelsPerRow.isValid() || usedPixelsPerRow.value() > blob->mRowLength) {
|
||||||
const auto usedImages = CheckedUint32(blob->mSkipImages) + blob->mDepth;
|
ErrorInvalidOperation("%s: UNPACK_SKIP_PIXELS + height > UNPACK_ROW_LENGTH.",
|
||||||
|
|
||||||
if (!usedPixelsPerRow.isValid() ||
|
|
||||||
!usedRowsPerImage.isValid() ||
|
|
||||||
!usedImages.isValid())
|
|
||||||
{
|
|
||||||
ErrorOutOfMemory("%s: Invalid calculation for e.g. UNPACK_SKIP_PIXELS + width.",
|
|
||||||
funcName);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////
|
|
||||||
|
|
||||||
if (usedPixelsPerRow.value() > blob->mRowLength ||
|
|
||||||
usedRowsPerImage.value() > blob->mImageHeight)
|
|
||||||
{
|
|
||||||
ErrorInvalidOperation("%s: UNPACK_ROW_LENGTH or UNPACK_IMAGE_HEIGHT too small.",
|
|
||||||
funcName);
|
funcName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (blob->mHeight > blob->mImageHeight) {
|
||||||
|
ErrorInvalidOperation("%s: height > UNPACK_IMAGE_HEIGHT.", funcName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//////
|
//////
|
||||||
|
|
||||||
auto fullRowsNeeded = (usedImages - 1) * blob->mImageHeight;
|
// The spec doesn't bound SKIP_ROWS + height <= IMAGE_HEIGHT, unfortunately.
|
||||||
fullRowsNeeded += usedRowsPerImage - 1;
|
auto skipFullRows = CheckedUint32(blob->mSkipImages) * blob->mImageHeight;
|
||||||
|
skipFullRows += blob->mSkipRows;
|
||||||
|
|
||||||
|
MOZ_ASSERT(blob->mDepth >= 1);
|
||||||
|
MOZ_ASSERT(blob->mHeight >= 1);
|
||||||
|
auto usedFullRows = CheckedUint32(blob->mDepth - 1) * blob->mImageHeight;
|
||||||
|
usedFullRows += blob->mHeight - 1; // Full rows in the final image, excluding the tail.
|
||||||
|
|
||||||
|
const auto fullRowsNeeded = skipFullRows + usedFullRows;
|
||||||
if (!fullRowsNeeded.isValid()) {
|
if (!fullRowsNeeded.isValid()) {
|
||||||
ErrorOutOfMemory("%s: Invalid calculation for required row count.",
|
ErrorOutOfMemory("%s: Invalid calculation for required row count.",
|
||||||
funcName);
|
funcName);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче