Restrict acceptable bounds for uploading data to mip levels on GPU
The help simplify the code (and currect a current bug) inside the uploadPixel functions in GL and Vulkan, we not restrict the bounds upload/write bounds on a higher level. For non mipped uploads, we requiring the bounds to be within the bounds on the texture, and for mipped uploads we require the bounds to be the full texture. Bug: skia:6780 Change-Id: Ia1cff3ee48edd3676afce6265d60e81ccea6ca6a Reviewed-on: https://skia-review.googlesource.com/20825 Reviewed-by: Jim Van Verth <jvanverth@google.com> Commit-Queue: Greg Daniel <egdaniel@google.com>
This commit is contained in:
parent
4e942a301a
commit
660cc9910f
@ -354,6 +354,17 @@ bool GrGpu::writePixels(GrSurface* surface,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, const SkTArray<GrMipLevel>& texels) {
|
||||
SkASSERT(surface);
|
||||
if (1 == texels.count()) {
|
||||
// We require that if we are not mipped, then the write region is contained in the surface
|
||||
SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
|
||||
SkIRect bounds = SkIRect::MakeWH(surface->width(), surface->height());
|
||||
if (!bounds.contains(subRect)) {
|
||||
return false;
|
||||
}
|
||||
} else if (0 != left || 0 != top || width != surface->width() || height != surface->height()) {
|
||||
// We require that if the texels are mipped, than the write region is the entire surface
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
|
||||
if (!texels[currentMipLevel].fPixels ) {
|
||||
@ -400,6 +411,13 @@ bool GrGpu::transferPixels(GrTexture* texture,
|
||||
return false;
|
||||
}
|
||||
|
||||
// We require that the write region is contained in the texture
|
||||
SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
|
||||
SkIRect bounds = SkIRect::MakeWH(texture->width(), texture->height());
|
||||
if (!bounds.contains(subRect)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->handleDirtyContext();
|
||||
if (this->onTransferPixels(texture, left, top, width, height, config,
|
||||
transferBuffer, offset, rowBytes)) {
|
||||
|
@ -833,16 +833,18 @@ bool GrGLGpu::onTransferPixels(GrTexture* texture,
|
||||
const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(transferBuffer);
|
||||
this->bindBuffer(kXferCpuToGpu_GrBufferType, glBuffer);
|
||||
|
||||
SkDEBUGCODE(
|
||||
SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
|
||||
SkIRect bounds = SkIRect::MakeWH(texture->width(), texture->height());
|
||||
SkASSERT(bounds.contains(subRect));
|
||||
)
|
||||
|
||||
size_t bpp = GrBytesPerPixel(config);
|
||||
const size_t trimRowBytes = width * bpp;
|
||||
const void* pixels = (void*)offset;
|
||||
if (!GrSurfacePriv::AdjustWritePixelParams(glTex->width(), glTex->height(), bpp,
|
||||
&left, &top,
|
||||
&width, &height,
|
||||
&pixels,
|
||||
&rowBytes)) {
|
||||
return false;
|
||||
if (!rowBytes) {
|
||||
rowBytes = trimRowBytes;
|
||||
}
|
||||
const void* pixels = (void*)offset;
|
||||
if (width < 0 || width < 0) {
|
||||
return false;
|
||||
}
|
||||
@ -1012,6 +1014,13 @@ bool GrGLGpu::uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight
|
||||
int left, int top, int width, int height, GrPixelConfig dataConfig,
|
||||
const SkTArray<GrMipLevel>& texels) {
|
||||
SkASSERT(this->caps()->isConfigTexturable(texConfig));
|
||||
SkDEBUGCODE(
|
||||
SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
|
||||
SkIRect bounds = SkIRect::MakeWH(texWidth, texHeight);
|
||||
SkASSERT(bounds.contains(subRect));
|
||||
)
|
||||
SkASSERT(1 == texels.count() ||
|
||||
(0 == left && 0 == top && width == texWidth && height == texHeight));
|
||||
|
||||
// unbind any previous transfer buffer
|
||||
auto& xferBufferState = fHWBufferState[kXferCpuToGpu_GrBufferType];
|
||||
@ -1041,26 +1050,6 @@ bool GrGLGpu::uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
|
||||
int twoToTheMipLevel = 1 << currentMipLevel;
|
||||
int currentWidth = SkTMax(1, width / twoToTheMipLevel);
|
||||
int currentHeight = SkTMax(1, height / twoToTheMipLevel);
|
||||
|
||||
if (currentHeight > SK_MaxS32 ||
|
||||
currentWidth > SK_MaxS32) {
|
||||
return false;
|
||||
}
|
||||
if (!GrSurfacePriv::AdjustWritePixelParams(texWidth, texHeight, bpp, &left, &top,
|
||||
¤tWidth, ¤tHeight,
|
||||
&texelsShallowCopy[currentMipLevel].fPixels,
|
||||
&texelsShallowCopy[currentMipLevel].fRowBytes)) {
|
||||
return false;
|
||||
}
|
||||
if (currentWidth < 0 || currentHeight < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Internal format comes from the texture desc.
|
||||
GrGLenum internalFormat;
|
||||
// External format and type come from the upload data.
|
||||
@ -1122,8 +1111,10 @@ bool GrGLGpu::uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight
|
||||
*/
|
||||
restoreGLRowLength = false;
|
||||
|
||||
const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes;
|
||||
|
||||
const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes ?
|
||||
texelsShallowCopy[currentMipLevel].fRowBytes :
|
||||
trimRowBytes;
|
||||
|
||||
// TODO: This optimization should be enabled with or without mips.
|
||||
// For use with mips, we must set GR_GL_UNPACK_ROW_LENGTH once per
|
||||
// mip level, before calling glTexImage2D.
|
||||
|
@ -444,6 +444,11 @@ bool GrVkGpu::onTransferPixels(GrTexture* texture,
|
||||
return false;
|
||||
}
|
||||
|
||||
SkDEBUGCODE(
|
||||
SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
|
||||
SkIRect bounds = SkIRect::MakeWH(texture->width(), texture->height());
|
||||
SkASSERT(bounds.contains(subRect));
|
||||
)
|
||||
size_t bpp = GrBytesPerPixel(config);
|
||||
if (rowBytes == 0) {
|
||||
rowBytes = bpp*width;
|
||||
@ -555,13 +560,16 @@ bool GrVkGpu::uploadTexDataLinear(GrVkTexture* tex,
|
||||
SkASSERT(data);
|
||||
SkASSERT(tex->isLinearTiled());
|
||||
|
||||
SkDEBUGCODE(
|
||||
SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
|
||||
SkIRect bounds = SkIRect::MakeWH(tex->width(), tex->height());
|
||||
SkASSERT(bounds.contains(subRect));
|
||||
)
|
||||
size_t bpp = GrBytesPerPixel(dataConfig);
|
||||
|
||||
if (!GrSurfacePriv::AdjustWritePixelParams(tex->width(), tex->height(), bpp, &left, &top,
|
||||
&width, &height, &data, &rowBytes)) {
|
||||
return false;
|
||||
}
|
||||
size_t trimRowBytes = width * bpp;
|
||||
if (!rowBytes) {
|
||||
rowBytes = trimRowBytes;
|
||||
}
|
||||
|
||||
SkASSERT(VK_IMAGE_LAYOUT_PREINITIALIZED == tex->currentLayout() ||
|
||||
VK_IMAGE_LAYOUT_GENERAL == tex->currentLayout());
|
||||
@ -643,16 +651,6 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex,
|
||||
// Determine whether we need to flip when we copy into the buffer
|
||||
bool flipY = (kBottomLeft_GrSurfaceOrigin == tex->origin() && !texelsShallowCopy.empty());
|
||||
|
||||
// adjust any params (left, top, currentWidth, currentHeight
|
||||
// find the combined size of all the mip levels and the relative offset of
|
||||
// each into the collective buffer
|
||||
// Do the first level separately because we may need to adjust width and height
|
||||
// (for the non-mipped case).
|
||||
if (!GrSurfacePriv::AdjustWritePixelParams(tex->width(), tex->height(), bpp, &left, &top,
|
||||
&width, &height, &texelsShallowCopy[0].fPixels,
|
||||
&texelsShallowCopy[0].fRowBytes)) {
|
||||
return false;
|
||||
}
|
||||
SkTArray<size_t> individualMipOffsets(texelsShallowCopy.count());
|
||||
individualMipOffsets.push_back(0);
|
||||
size_t combinedBufferSize = width * bpp * height;
|
||||
@ -665,12 +663,7 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex,
|
||||
for (int currentMipLevel = 1; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
|
||||
currentWidth = SkTMax(1, currentWidth/2);
|
||||
currentHeight = SkTMax(1, currentHeight/2);
|
||||
if (!GrSurfacePriv::AdjustWritePixelParams(tex->width(), tex->height(), bpp, &left, &top,
|
||||
¤tWidth, ¤tHeight,
|
||||
&texelsShallowCopy[currentMipLevel].fPixels,
|
||||
&texelsShallowCopy[currentMipLevel].fRowBytes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t trimmedSize = currentWidth * bpp * currentHeight;
|
||||
const size_t alignmentDiff = combinedBufferSize & alignmentMask;
|
||||
if (alignmentDiff != 0) {
|
||||
@ -695,7 +688,9 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex,
|
||||
for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
|
||||
SkASSERT(1 == texelsShallowCopy.count() || currentHeight == layerHeight);
|
||||
const size_t trimRowBytes = currentWidth * bpp;
|
||||
const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes;
|
||||
const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes ?
|
||||
texelsShallowCopy[currentMipLevel].fRowBytes :
|
||||
trimRowBytes;
|
||||
|
||||
// copy data into the buffer, skipping the trailing bytes
|
||||
char* dst = buffer + individualMipOffsets[currentMipLevel];
|
||||
|
Loading…
Reference in New Issue
Block a user