Make GrGpu pixel ops functions take SkIRect instead of LTRB params.

Change-Id: Ic4a8a32a434485b84284decbcc5a8f898197169a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/408359
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Salomon 2021-05-24 12:40:46 -04:00 committed by Skia Commit-Bot
parent f76602e3bf
commit e2078f1106
23 changed files with 720 additions and 427 deletions

View File

@ -58,8 +58,11 @@ public:
// If the worker thread was unable to allocate pixels, this check will fail, and we'll
// end up drawing with an uninitialized mask texture, but at least we won't crash.
if (this->fPixels.addr()) {
writePixelsFn(proxy, 0, 0, this->fPixels.width(), this->fPixels.height(),
pixelColorType, this->fPixels.addr(), this->fPixels.rowBytes());
writePixelsFn(proxy,
SkIRect::MakeSize(fPixels.dimensions()),
pixelColorType,
this->fPixels.addr(),
this->fPixels.rowBytes());
}
// Upload has finished, so tell the proxy to release this GrDeferredProxyUploader
proxy->texPriv().resetDeferredUploader();

View File

@ -115,9 +115,11 @@ private:
* Passed to a deferred upload when it is executed, this method allows the deferred upload to
* actually write its pixel data into a texture.
*/
using GrDeferredTextureUploadWritePixelsFn =
std::function<bool(GrTextureProxy*, int left, int top, int width, int height,
GrColorType srcColorType, const void* buffer, size_t rowBytes)>;
using GrDeferredTextureUploadWritePixelsFn = std::function<bool(GrTextureProxy*,
SkIRect,
GrColorType srcColorType,
const void*,
size_t rowBytes)>;
/**
* A deferred texture upload is simply a std::function that takes a

View File

@ -176,8 +176,11 @@ void GrDrawOpAtlas::Plot::uploadToTexture(GrDeferredTextureUploadWritePixelsFn&
dataPtr += rowBytes * fDirtyRect.fTop;
dataPtr += fBytesPerPixel * fDirtyRect.fLeft;
writePixels(proxy, fOffset.fX + fDirtyRect.fLeft, fOffset.fY + fDirtyRect.fTop,
fDirtyRect.width(), fDirtyRect.height(), fColorType, dataPtr, rowBytes);
writePixels(proxy,
fDirtyRect.makeOffset(fOffset.fX, fOffset.fY),
fColorType,
dataPtr,
rowBytes);
fDirtyRect.setEmpty();
SkDEBUGCODE(fDirty = false;)
}

View File

@ -207,8 +207,12 @@ sk_sp<GrTexture> GrGpu::createTexture(SkISize dimensions,
// Currently if level 0 does not have pixels then no other level may, as enforced by
// validate_texel_levels.
if (texelLevelCount && texels[0].fPixels) {
if (!this->writePixels(tex.get(), 0, 0, dimensions.fWidth, dimensions.fHeight,
textureColorType, srcColorType, texels, texelLevelCount)) {
if (!this->writePixels(tex.get(),
SkIRect::MakeSize(dimensions),
textureColorType,
srcColorType,
texels,
texelLevelCount)) {
return nullptr;
}
// Currently if level[1] of mip map has pixel data then so must all other levels.
@ -379,21 +383,22 @@ bool GrGpu::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
return this->onCopySurface(dst, src, srcRect, dstPoint);
}
bool GrGpu::readPixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType dstColorType, void* buffer,
bool GrGpu::readPixels(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType dstColorType,
void* buffer,
size_t rowBytes) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
SkASSERT(surface);
SkASSERT(!surface->framebufferOnly());
SkASSERT(this->caps()->isFormatTexturable(surface->backendFormat()));
auto subRect = SkIRect::MakeXYWH(left, top, width, height);
auto bounds = SkIRect::MakeWH(surface->width(), surface->height());
if (!bounds.contains(subRect)) {
if (!SkIRect::MakeSize(surface->dimensions()).contains(rect)) {
return false;
}
size_t minRowBytes = SkToSizeT(GrColorTypeBytesPerPixel(dstColorType) * width);
size_t minRowBytes = SkToSizeT(GrColorTypeBytesPerPixel(dstColorType) * rect.width());
if (!this->caps()->readPixelsRowBytesSupport()) {
if (rowBytes != minRowBytes) {
return false;
@ -409,13 +414,16 @@ bool GrGpu::readPixels(GrSurface* surface, int left, int top, int width, int hei
this->handleDirtyContext();
return this->onReadPixels(surface, left, top, width, height, surfaceColorType, dstColorType,
buffer, rowBytes);
return this->onReadPixels(surface, rect, surfaceColorType, dstColorType, buffer, rowBytes);
}
bool GrGpu::writePixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType srcColorType,
const GrMipLevel texels[], int mipLevelCount, bool prepForTexSampling) {
bool GrGpu::writePixels(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType srcColorType,
const GrMipLevel texels[],
int mipLevelCount,
bool prepForTexSampling) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
ATRACE_ANDROID_FRAMEWORK_ALWAYS("Texture upload(%u) %ix%i",
surface->uniqueID().asUInt(), width, height);
@ -430,25 +438,26 @@ bool GrGpu::writePixels(GrSurface* surface, int left, int top, int width, int he
return false;
} else if (mipLevelCount == 1) {
// We require that if we are not mipped, then the write region is contained in the surface
auto subRect = SkIRect::MakeXYWH(left, top, width, height);
auto bounds = SkIRect::MakeWH(surface->width(), surface->height());
if (!bounds.contains(subRect)) {
if (!SkIRect::MakeSize(surface->dimensions()).contains(rect)) {
return false;
}
} else if (0 != left || 0 != top || width != surface->width() || height != surface->height()) {
} else if (rect != SkIRect::MakeSize(surface->dimensions())) {
// We require that if the texels are mipped, than the write region is the entire surface
return false;
}
if (!validate_texel_levels({width, height}, srcColorType, texels, mipLevelCount,
this->caps())) {
if (!validate_texel_levels(rect.size(), srcColorType, texels, mipLevelCount, this->caps())) {
return false;
}
this->handleDirtyContext();
if (this->onWritePixels(surface, left, top, width, height, surfaceColorType, srcColorType,
texels, mipLevelCount, prepForTexSampling)) {
SkIRect rect = SkIRect::MakeXYWH(left, top, width, height);
if (this->onWritePixels(surface,
rect,
surfaceColorType,
srcColorType,
texels,
mipLevelCount,
prepForTexSampling)) {
this->didWriteToSurface(surface, kTopLeft_GrSurfaceOrigin, &rect, mipLevelCount);
fStats.incTextureUploads();
return true;
@ -456,9 +465,13 @@ bool GrGpu::writePixels(GrSurface* surface, int left, int top, int width, int he
return false;
}
bool GrGpu::transferPixelsTo(GrTexture* texture, int left, int top, int width, int height,
GrColorType textureColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset, size_t rowBytes) {
bool GrGpu::transferPixelsTo(GrTexture* texture,
SkIRect rect,
GrColorType textureColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer,
size_t offset,
size_t rowBytes) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
SkASSERT(texture);
SkASSERT(transferBuffer);
@ -468,30 +481,32 @@ bool GrGpu::transferPixelsTo(GrTexture* texture, int left, int top, int width, i
}
// 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)) {
if (!SkIRect::MakeSize(texture->dimensions()).contains(rect)) {
return false;
}
size_t bpp = GrColorTypeBytesPerPixel(bufferColorType);
if (this->caps()->writePixelsRowBytesSupport()) {
if (rowBytes < SkToSizeT(bpp * width)) {
if (rowBytes < SkToSizeT(bpp*rect.width())) {
return false;
}
if (rowBytes % bpp) {
return false;
}
} else {
if (rowBytes != SkToSizeT(bpp * width)) {
if (rowBytes != SkToSizeT(bpp*rect.width())) {
return false;
}
}
this->handleDirtyContext();
if (this->onTransferPixelsTo(texture, left, top, width, height, textureColorType,
bufferColorType, std::move(transferBuffer), offset, rowBytes)) {
SkIRect rect = SkIRect::MakeXYWH(left, top, width, height);
if (this->onTransferPixelsTo(texture,
rect,
textureColorType,
bufferColorType,
std::move(transferBuffer),
offset,
rowBytes)) {
this->didWriteToSurface(texture, kTopLeft_GrSurfaceOrigin, &rect);
fStats.incTransfersToTexture();
@ -500,9 +515,12 @@ bool GrGpu::transferPixelsTo(GrTexture* texture, int left, int top, int width, i
return false;
}
bool GrGpu::transferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset) {
bool GrGpu::transferPixelsFrom(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer,
size_t offset) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
SkASSERT(surface);
SkASSERT(transferBuffer);
@ -516,15 +534,17 @@ bool GrGpu::transferPixelsFrom(GrSurface* surface, int left, int top, int width,
#endif
// We require that the write region is contained in the texture
SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
SkIRect bounds = SkIRect::MakeWH(surface->width(), surface->height());
if (!bounds.contains(subRect)) {
if (!SkIRect::MakeSize(surface->dimensions()).contains(rect)) {
return false;
}
this->handleDirtyContext();
if (this->onTransferPixelsFrom(surface, left, top, width, height, surfaceColorType,
bufferColorType, std::move(transferBuffer), offset)) {
if (this->onTransferPixelsFrom(surface,
rect,
surfaceColorType,
bufferColorType,
std::move(transferBuffer),
offset)) {
fStats.incTransfersFromSurface();
return true;
}

View File

@ -219,11 +219,8 @@ public:
/**
* Reads a rectangle of pixels from a render target. No sRGB/linear conversions are performed.
*
* @param surface The surface to read from
* @param left left edge of the rectangle to read (inclusive)
* @param top top edge of the rectangle to read (inclusive)
* @param width width of rectangle to read in pixels.
* @param height height of rectangle to read in pixels.
* @param surface the surface to read from
* @param rect the rectangle of pixels to read
* @param surfaceColorType the color type for this use of the surface.
* @param dstColorType the color type of the destination buffer.
* @param buffer memory to read the rectangle into.
@ -236,18 +233,18 @@ public:
* is not allowed for the format of the surface or if the rectangle
* read is not contained in the surface.
*/
bool readPixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType dstColorType, void* buffer,
bool readPixels(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType dstColorType,
void* buffer,
size_t rowBytes);
/**
* Updates the pixels in a rectangle of a surface. No sRGB/linear conversions are performed.
*
* @param surface The surface to write to.
* @param left left edge of the rectangle to write (inclusive)
* @param top top edge of the rectangle to write (inclusive)
* @param width width of rectangle to write in pixels.
* @param height height of rectangle to write in pixels.
* @param surface the surface to write to.
* @param rect the rectangle of pixels to overwrite
* @param surfaceColorType the color type for this use of the surface.
* @param srcColorType the color type of the source buffer.
* @param texels array of mipmap levels containing texture data. Row bytes must be a
@ -267,41 +264,55 @@ public:
* the color type is not allowed for the format of the surface or
* if the rectangle written is not contained in the surface.
*/
bool writePixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType srcColorType,
const GrMipLevel texels[], int mipLevelCount, bool prepForTexSampling = false);
bool writePixels(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType srcColorType,
const GrMipLevel texels[],
int mipLevelCount,
bool prepForTexSampling = false);
/**
* Helper for the case of a single level.
*/
bool writePixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType srcColorType, const void* buffer,
size_t rowBytes, bool prepForTexSampling = false) {
bool writePixels(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType srcColorType,
const void* buffer,
size_t rowBytes,
bool prepForTexSampling = false) {
GrMipLevel mipLevel = {buffer, rowBytes, nullptr};
return this->writePixels(surface, left, top, width, height, surfaceColorType, srcColorType,
&mipLevel, 1, prepForTexSampling);
return this->writePixels(surface,
rect,
surfaceColorType,
srcColorType,
&mipLevel,
1,
prepForTexSampling);
}
/**
* Updates the pixels in a rectangle of a texture using a buffer. If the texture is MIP mapped,
* the base level is written to.
*
* @param texture The texture to write to.
* @param left left edge of the rectangle to write (inclusive)
* @param top top edge of the rectangle to write (inclusive)
* @param width width of rectangle to write in pixels.
* @param height height of rectangle to write in pixels.
* @param texture the texture to write to.
* @param rect the rectangle of pixels in the texture to overwrite
* @param textureColorType the color type for this use of the surface.
* @param bufferColorType the color type of the transfer buffer's pixel data
* @param transferBuffer GrBuffer to read pixels from (type must be "kXferCpuToGpu")
* @param offset offset from the start of the buffer
* @param rowBytes number of bytes between consecutive rows in the buffer. Must be a
* multiple of bufferColorType's bytes-per-pixel. Must be tight to width
* if !caps->writePixelsRowBytesSupport().
* multiple of bufferColorType's bytes-per-pixel. Must be tight to
* rect.width() if !caps->writePixelsRowBytesSupport().
*/
bool transferPixelsTo(GrTexture* texture, int left, int top, int width, int height,
GrColorType textureColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset, size_t rowBytes);
bool transferPixelsTo(GrTexture* texture,
SkIRect rect,
GrColorType textureColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer,
size_t offset,
size_t rowBytes);
/**
* Reads the pixels from a rectangle of a surface into a buffer. Use
@ -309,24 +320,24 @@ public:
* the buffer offset alignment. If the surface is a MIP mapped texture, the base level is read.
*
* If successful the row bytes in the buffer is always:
* GrColorTypeBytesPerPixel(bufferColorType) * width
* GrColorTypeBytesPerPixel(bufferColorType) * rect.width()
*
* Asserts that the caller has passed a properly aligned offset and that the buffer is
* large enough to hold the result
*
* @param surface The surface to read from.
* @param left left edge of the rectangle to read (inclusive)
* @param top top edge of the rectangle to read (inclusive)
* @param width width of rectangle to read in pixels.
* @param height height of rectangle to read in pixels.
* @param surface the surface to read from.
* @param rect the rectangle of pixels to read
* @param surfaceColorType the color type for this use of the surface.
* @param bufferColorType the color type of the transfer buffer's pixel data
* @param transferBuffer GrBuffer to write pixels to (type must be "kXferGpuToCpu")
* @param offset offset from the start of the buffer
*/
bool transferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset);
bool transferPixelsFrom(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer,
size_t offset);
// Called to perform a surface to surface copy. Fallbacks to issuing a draw from the src to dst
// take place at higher levels and this function implement faster copy paths. The rect
@ -716,24 +727,36 @@ private:
GrAccessPattern, const void* data) = 0;
// overridden by backend-specific derived class to perform the surface read
virtual bool onReadPixels(GrSurface*, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType dstColorType, void* buffer,
virtual bool onReadPixels(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType dstColorType,
void*,
size_t rowBytes) = 0;
// overridden by backend-specific derived class to perform the surface write
virtual bool onWritePixels(GrSurface*, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType srcColorType,
const GrMipLevel texels[], int mipLevelCount,
virtual bool onWritePixels(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType srcColorType,
const GrMipLevel[],
int mipLevelCount,
bool prepForTexSampling) = 0;
// overridden by backend-specific derived class to perform the texture transfer
virtual bool onTransferPixelsTo(GrTexture*, int left, int top, int width, int height,
GrColorType textiueColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset,
virtual bool onTransferPixelsTo(GrTexture*,
SkIRect,
GrColorType textiueColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer,
size_t offset,
size_t rowBytes) = 0;
// overridden by backend-specific derived class to perform the surface transfer
virtual bool onTransferPixelsFrom(GrSurface*, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
virtual bool onTransferPixelsFrom(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer,
size_t offset) = 0;

View File

@ -100,24 +100,27 @@ void GrOpFlushState::reset() {
void GrOpFlushState::doUpload(GrDeferredTextureUploadFn& upload,
bool shouldPrepareSurfaceForSampling) {
GrDeferredTextureUploadWritePixelsFn wp = [this, shouldPrepareSurfaceForSampling](
GrTextureProxy* dstProxy, int left, int top, int width, int height,
GrColorType colorType, const void* buffer, size_t rowBytes) {
GrTextureProxy* dstProxy,
SkIRect rect,
GrColorType colorType,
const void* buffer,
size_t rowBytes) {
GrSurface* dstSurface = dstProxy->peekSurface();
if (!fGpu->caps()->surfaceSupportsWritePixels(dstSurface)) {
return false;
}
GrCaps::SupportedWrite supportedWrite = fGpu->caps()->supportedWritePixelsColorType(
colorType, dstSurface->backendFormat(), colorType);
size_t tightRB = width * GrColorTypeBytesPerPixel(supportedWrite.fColorType);
size_t tightRB = rect.width()*GrColorTypeBytesPerPixel(supportedWrite.fColorType);
SkASSERT(rowBytes >= tightRB);
std::unique_ptr<char[]> tmpPixels;
if (supportedWrite.fColorType != colorType ||
(!fGpu->caps()->writePixelsRowBytesSupport() && rowBytes != tightRB)) {
tmpPixels.reset(new char[height * tightRB]);
tmpPixels.reset(new char[rect.height()*tightRB]);
// Use kUnknown to ensure no alpha type conversions or clamping occur.
static constexpr auto kAT = kUnknown_SkAlphaType;
GrImageInfo srcInfo(colorType, kAT, nullptr, width, height);
GrImageInfo tmpInfo(supportedWrite.fColorType, kAT, nullptr, width, height);
GrImageInfo srcInfo(colorType, kAT, nullptr, rect.size());
GrImageInfo tmpInfo(supportedWrite.fColorType, kAT, nullptr, rect.size());
if (!GrConvertPixels( GrPixmap(tmpInfo, tmpPixels.get(), tightRB ),
GrCPixmap(srcInfo, buffer, rowBytes))) {
return false;
@ -125,8 +128,12 @@ void GrOpFlushState::doUpload(GrDeferredTextureUploadFn& upload,
rowBytes = tightRB;
buffer = tmpPixels.get();
}
return this->fGpu->writePixels(dstSurface, left, top, width, height, colorType,
supportedWrite.fColorType, buffer, rowBytes,
return this->fGpu->writePixels(dstSurface,
rect,
colorType,
supportedWrite.fColorType,
buffer,
rowBytes,
shouldPrepareSurfaceForSampling);
};
upload(wp);

View File

@ -728,7 +728,11 @@ sk_sp<GrTexture> GrResourceProvider::writePixels(sk_sp<GrTexture> texture,
if (tempColorType == GrColorType::kUnknown) {
return nullptr;
}
SkAssertResult(fGpu->writePixels(texture.get(), 0, 0, baseSize.fWidth, baseSize.fHeight,
colorType, tempColorType, tmpTexels.get(), mipLevelCount));
SkAssertResult(fGpu->writePixels(texture.get(),
SkIRect::MakeSize(baseSize),
colorType,
tempColorType,
tmpTexels.get(),
mipLevelCount));
return texture;
}

View File

@ -343,9 +343,12 @@ bool GrSurfaceContext::readPixels(GrDirectContext* dContext, GrPixmap dst, SkIPo
dContext->priv().flushSurface(srcProxy.get());
dContext->submit();
if (!dContext->priv().getGpu()->readPixels(srcSurface, pt.fX, pt.fY, dst.width(), dst.height(),
if (!dContext->priv().getGpu()->readPixels(srcSurface,
SkIRect::MakePtSize(pt, dst.dimensions()),
this->colorInfo().colorType(),
supportedRead.fColorType, readDst, readRB)) {
supportedRead.fColorType,
readDst,
readRB)) {
return false;
}

View File

@ -24,7 +24,10 @@ bool GrTransferFromRenderTask::onExecute(GrOpFlushState* flushState) {
if (!fSrcProxy->isInstantiated()) {
return false;
}
return flushState->gpu()->transferPixelsFrom(
fSrcProxy->peekSurface(), fSrcRect.fLeft, fSrcRect.fTop, fSrcRect.width(),
fSrcRect.height(), fSurfaceColorType, fDstColorType, fDstBuffer, fDstOffset);
return flushState->gpu()->transferPixelsFrom(fSrcProxy->peekSurface(),
fSrcRect,
fSurfaceColorType,
fDstColorType,
fDstBuffer,
fDstOffset);
}

View File

@ -61,10 +61,7 @@ bool GrWritePixelsTask::onExecute(GrOpFlushState* flushState) {
}
GrSurface* dstSurface = dstProxy->peekSurface();
return flushState->gpu()->writePixels(dstSurface,
fRect.fLeft,
fRect.fTop,
fRect.width(),
fRect.height(),
fRect,
fDstColorType,
fSrcColorType,
fLevels.get(),

View File

@ -556,8 +556,11 @@ void GrD3DGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect& reso
this->resolveTexture(target, resolveRect.fLeft, resolveRect.fTop, rt, resolveRect);
}
bool GrD3DGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType dstColorType, void* buffer,
bool GrD3DGpu::onReadPixels(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType dstColorType,
void* buffer,
size_t rowBytes) {
SkASSERT(surface);
@ -588,8 +591,7 @@ bool GrD3DGpu::onReadPixels(GrSurface* surface, int left, int top, int width, in
GrGpuBufferType::kXferGpuToCpu,
kDynamic_GrAccessPattern);
this->readOrTransferPixels(texResource, left, top, width, height, transferBuffer,
placedFootprint);
this->readOrTransferPixels(texResource, rect, transferBuffer, placedFootprint);
this->submitDirectCommandList(SyncQueue::kForce);
// Copy back to CPU buffer
@ -597,12 +599,16 @@ bool GrD3DGpu::onReadPixels(GrSurface* surface, int left, int top, int width, in
if (GrDxgiFormatBytesPerBlock(texResource->dxgiFormat()) != bpp) {
return false;
}
size_t tightRowBytes = bpp * width;
size_t tightRowBytes = bpp * rect.width();
const void* mappedMemory = transferBuffer->map();
SkRectMemcpy(buffer, rowBytes, mappedMemory, placedFootprint.Footprint.RowPitch,
tightRowBytes, height);
SkRectMemcpy(buffer,
rowBytes,
mappedMemory,
placedFootprint.Footprint.RowPitch,
tightRowBytes,
rect.height());
transferBuffer->unmap();
@ -610,7 +616,7 @@ bool GrD3DGpu::onReadPixels(GrSurface* surface, int left, int top, int width, in
}
void GrD3DGpu::readOrTransferPixels(GrD3DTextureResource* texResource,
int left, int top, int width, int height,
SkIRect rect,
sk_sp<GrGpuBuffer> transferBuffer,
const D3D12_PLACED_SUBRESOURCE_FOOTPRINT& placedFootprint) {
// Set up src location and box
@ -621,10 +627,10 @@ void GrD3DGpu::readOrTransferPixels(GrD3DTextureResource* texResource,
srcLocation.SubresourceIndex = 0;
D3D12_BOX srcBox = {};
srcBox.left = left;
srcBox.top = top;
srcBox.right = left + width;
srcBox.bottom = top + height;
srcBox.left = rect.left();
srcBox.top = rect.top();
srcBox.right = rect.right();
srcBox.bottom = rect.bottom();
srcBox.front = 0;
srcBox.back = 1;
@ -643,9 +649,12 @@ void GrD3DGpu::readOrTransferPixels(GrD3DTextureResource* texResource,
&srcBox);
}
bool GrD3DGpu::onWritePixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType srcColorType,
const GrMipLevel texels[], int mipLevelCount,
bool GrD3DGpu::onWritePixels(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType srcColorType,
const GrMipLevel texels[],
int mipLevelCount,
bool prepForTexSampling) {
GrD3DTexture* d3dTex = static_cast<GrD3DTexture*>(surface->asTexture());
if (!d3dTex) {
@ -664,8 +673,7 @@ bool GrD3DGpu::onWritePixels(GrSurface* surface, int left, int top, int width, i
d3dTex->setResourceState(this, D3D12_RESOURCE_STATE_COPY_DEST);
SkASSERT(mipLevelCount <= d3dTex->maxMipmapLevel() + 1);
success = this->uploadToTexture(d3dTex, left, top, width, height, srcColorType, texels,
mipLevelCount);
success = this->uploadToTexture(d3dTex, rect, srcColorType, texels, mipLevelCount);
if (prepForTexSampling) {
d3dTex->setResourceState(this, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
@ -674,18 +682,20 @@ bool GrD3DGpu::onWritePixels(GrSurface* surface, int left, int top, int width, i
return success;
}
bool GrD3DGpu::uploadToTexture(GrD3DTexture* tex, int left, int top, int width, int height,
GrColorType colorType, const GrMipLevel* texels, int mipLevelCount) {
bool GrD3DGpu::uploadToTexture(GrD3DTexture* tex,
SkIRect rect,
GrColorType colorType,
const GrMipLevel* texels,
int mipLevelCount) {
SkASSERT(this->caps()->isFormatTexturable(tex->backendFormat()));
// The assumption is either that we have no mipmaps, or that our rect is the entire texture
SkASSERT(1 == mipLevelCount ||
(0 == left && 0 == top && width == tex->width() && height == tex->height()));
SkASSERT(mipLevelCount == 1 || rect == SkIRect::MakeSize(tex->dimensions()));
// We assume that if the texture has mip levels, we either upload to all the levels or just the
// first.
SkASSERT(1 == mipLevelCount || mipLevelCount == (tex->maxMipmapLevel() + 1));
SkASSERT(mipLevelCount == 1 || mipLevelCount == (tex->maxMipmapLevel() + 1));
if (width == 0 || height == 0) {
if (rect.isEmpty()) {
return false;
}
@ -713,8 +723,8 @@ bool GrD3DGpu::uploadToTexture(GrD3DTexture* tex, int left, int top, int width,
UINT64 combinedBufferSize;
// We reset the width and height in the description to match our subrectangle size
// so we don't end up allocating more space than we need.
desc.Width = width;
desc.Height = height;
desc.Width = rect.width();
desc.Height = rect.height();
fDevice->GetCopyableFootprints(&desc, 0, mipLevelCount, 0, placedFootprints.get(),
nullptr, nullptr, &combinedBufferSize);
size_t bpp = GrColorTypeBytesPerPixel(colorType);
@ -728,8 +738,8 @@ bool GrD3DGpu::uploadToTexture(GrD3DTexture* tex, int left, int top, int width,
char* bufferData = (char*)slice.fOffsetMapPtr;
int currentWidth = width;
int currentHeight = height;
int currentWidth = rect.width();
int currentHeight = rect.height();
int layerHeight = tex->height();
for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
@ -757,8 +767,12 @@ bool GrD3DGpu::uploadToTexture(GrD3DTexture* tex, int left, int top, int width,
}
ID3D12Resource* d3dBuffer = static_cast<GrD3DBuffer*>(slice.fBuffer)->d3dResource();
fCurrentDirectCommandList->copyBufferToTexture(d3dBuffer, tex, mipLevelCount,
placedFootprints.get(), left, top);
fCurrentDirectCommandList->copyBufferToTexture(d3dBuffer,
tex,
mipLevelCount,
placedFootprints.get(),
rect.left(),
rect.top());
if (mipLevelCount < (int)desc.MipLevels) {
tex->markMipmapsDirty();
@ -767,9 +781,12 @@ bool GrD3DGpu::uploadToTexture(GrD3DTexture* tex, int left, int top, int width,
return true;
}
bool GrD3DGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t bufferOffset,
bool GrD3DGpu::onTransferPixelsTo(GrTexture* texture,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer,
size_t bufferOffset,
size_t rowBytes) {
if (!this->currentCommandList()) {
return false;
@ -801,19 +818,15 @@ bool GrD3DGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int wid
SkASSERT(GrDxgiFormatBytesPerBlock(format) == GrColorTypeBytesPerPixel(bufferColorType));
SkDEBUGCODE(
SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
SkIRect bounds = SkIRect::MakeWH(texture->width(), texture->height());
SkASSERT(bounds.contains(subRect));
)
SkASSERT(SkIRect::MakeSize(texture->dimensions()).contains(rect));
// Set up copy region
D3D12_PLACED_SUBRESOURCE_FOOTPRINT placedFootprint = {};
ID3D12Resource* d3dResource = d3dTex->d3dResource();
SkASSERT(d3dResource);
D3D12_RESOURCE_DESC desc = d3dResource->GetDesc();
desc.Width = width;
desc.Height = height;
desc.Width = rect.width();
desc.Height = rect.height();
UINT64 totalBytes;
fDevice->GetCopyableFootprints(&desc, 0, 1, 0, &placedFootprint,
nullptr, nullptr, &totalBytes);
@ -824,17 +837,24 @@ bool GrD3DGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int wid
// Copy the buffer to the image.
ID3D12Resource* d3dBuffer = static_cast<GrD3DBuffer*>(transferBuffer.get())->d3dResource();
fCurrentDirectCommandList->copyBufferToTexture(d3dBuffer, d3dTex, 1,
&placedFootprint, left, top);
fCurrentDirectCommandList->copyBufferToTexture(d3dBuffer,
d3dTex,
1,
&placedFootprint,
rect.left(),
rect.top());
this->currentCommandList()->addGrBuffer(std::move(transferBuffer));
d3dTex->markMipmapsDirty();
return true;
}
bool GrD3DGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset) {
bool GrD3DGpu::onTransferPixelsFrom(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer,
size_t offset) {
if (!this->currentCommandList()) {
return false;
}
@ -866,16 +886,15 @@ bool GrD3DGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int w
SkASSERT(GrDxgiFormatBytesPerBlock(format) == GrColorTypeBytesPerPixel(bufferColorType));
D3D12_RESOURCE_DESC desc = texResource->d3dResource()->GetDesc();
desc.Width = width;
desc.Height = height;
desc.Width = rect.width();
desc.Height = rect.height();
D3D12_PLACED_SUBRESOURCE_FOOTPRINT placedFootprint;
UINT64 transferTotalBytes;
fDevice->GetCopyableFootprints(&desc, 0, 1, offset, &placedFootprint,
nullptr, nullptr, &transferTotalBytes);
SkASSERT(transferTotalBytes);
this->readOrTransferPixels(texResource, left, top, width, height,
transferBuffer, placedFootprint);
this->readOrTransferPixels(texResource, rect, transferBuffer, placedFootprint);
// TODO: It's not clear how to ensure the transfer is done before we read from the buffer,
// other than maybe doing a resource state transition.

View File

@ -165,22 +165,35 @@ private:
sk_sp<GrGpuBuffer> onCreateBuffer(size_t sizeInBytes, GrGpuBufferType, GrAccessPattern,
const void*) override;
bool onReadPixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType dstColorType, void* buffer,
bool onReadPixels(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType dstColorType,
void*,
size_t rowBytes) override;
bool onWritePixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType srcColorType,
const GrMipLevel texels[], int mipLevelCount,
bool onWritePixels(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType srcColorType,
const GrMipLevel[],
int mipLevelCount,
bool prepForTexSampling) override;
bool onTransferPixelsTo(GrTexture* texture, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset,
bool onTransferPixelsTo(GrTexture*,
SkIRect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer>,
size_t offset,
size_t rowBytes) override;
bool onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset) override;
bool onTransferPixelsFrom(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer>,
size_t offset) override;
bool onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
const SkIPoint& dstPoint) override;
@ -253,11 +266,14 @@ private:
int mipLevelCount,
GrMipmapStatus);
bool uploadToTexture(GrD3DTexture* tex, int left, int top, int width, int height,
GrColorType colorType, const GrMipLevel* texels, int mipLevelCount);
bool uploadToTexture(GrD3DTexture* tex,
SkIRect rect,
GrColorType colorType,
const GrMipLevel texels[],
int mipLevelCount);
void readOrTransferPixels(GrD3DTextureResource* texResource,
int left, int top, int width, int height,
SkIRect rect,
sk_sp<GrGpuBuffer> transferBuffer,
const D3D12_PLACED_SUBRESOURCE_FOOTPRINT& placedFootprint);

View File

@ -178,33 +178,41 @@ sk_sp<GrGpuBuffer> GrDawnGpu::onCreateBuffer(size_t size, GrGpuBufferType type,
}
////////////////////////////////////////////////////////////////////////////////
bool GrDawnGpu::onWritePixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType srcColorType,
const GrMipLevel texels[], int mipLevelCount,
bool GrDawnGpu::onWritePixels(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType srcColorType,
const GrMipLevel texels[],
int mipLevelCount,
bool prepForTexSampling) {
GrDawnTexture* texture = static_cast<GrDawnTexture*>(surface->asTexture());
if (!texture) {
return false;
}
this->uploadTextureData(srcColorType, texels, mipLevelCount,
SkIRect::MakeXYWH(left, top, width, height), texture->texture());
this->uploadTextureData(srcColorType, texels, mipLevelCount, rect, texture->texture());
if (mipLevelCount < texture->maxMipmapLevel() + 1) {
texture->markMipmapsDirty();
}
return true;
}
bool GrDawnGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int width, int height,
GrColorType textureColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t bufferOffset,
bool GrDawnGpu::onTransferPixelsTo(GrTexture* texture,
SkIRect rect,
GrColorType textureColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer,
size_t bufferOffset,
size_t rowBytes) {
SkASSERT(!"unimplemented");
return false;
}
bool GrDawnGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset) {
bool GrDawnGpu::onTransferPixelsFrom(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer,
size_t offset) {
SkASSERT(!"unimplemented");
return false;
}
@ -603,8 +611,11 @@ static void callback(WGPUBufferMapAsyncStatus status, void* userdata) {
*static_cast<bool*>(userdata) = true;
}
bool GrDawnGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType dstColorType, void* buffer,
bool GrDawnGpu::onReadPixels(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType dstColorType,
void* buffer,
size_t rowBytes) {
wgpu::Texture tex = get_dawn_texture_from_surface(surface);
@ -612,9 +623,9 @@ bool GrDawnGpu::onReadPixels(GrSurface* surface, int left, int top, int width, i
return false;
}
size_t origRowBytes = rowBytes;
int origSizeInBytes = origRowBytes * height;
int origSizeInBytes = origRowBytes*rect.height();
rowBytes = GrDawnRoundRowBytes(rowBytes);
int sizeInBytes = rowBytes * height;
int sizeInBytes = rowBytes*rect.height();
wgpu::BufferDescriptor desc;
desc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead;
@ -624,15 +635,15 @@ bool GrDawnGpu::onReadPixels(GrSurface* surface, int left, int top, int width, i
wgpu::ImageCopyTexture srcTexture;
srcTexture.texture = tex;
srcTexture.origin = {(uint32_t) left, (uint32_t) top, 0};
srcTexture.origin = {(uint32_t) rect.left(), (uint32_t) rect.top(), 0};
wgpu::ImageCopyBuffer dstBuffer = {};
dstBuffer.buffer = buf;
dstBuffer.layout.offset = 0;
dstBuffer.layout.bytesPerRow = rowBytes;
dstBuffer.layout.rowsPerImage = height;
dstBuffer.layout.rowsPerImage = rect.height();
wgpu::Extent3D copySize = {(uint32_t) width, (uint32_t) height, 1};
wgpu::Extent3D copySize = {(uint32_t) rect.width(), (uint32_t) rect.height(), 1};
this->getCopyEncoder().CopyTextureToBuffer(&srcTexture, &dstBuffer, &copySize);
this->submitToGpu(true);
@ -648,7 +659,7 @@ bool GrDawnGpu::onReadPixels(GrSurface* surface, int left, int top, int width, i
} else {
const char* src = static_cast<const char*>(readPixelsPtr);
char* dst = static_cast<char*>(buffer);
for (int row = 0; row < height; row++) {
for (int row = 0; row < rect.height(); row++) {
memcpy(dst, src, origRowBytes);
dst += origRowBytes;
src += rowBytes;

View File

@ -160,23 +160,35 @@ private:
sk_sp<GrGpuBuffer> onCreateBuffer(size_t size, GrGpuBufferType type, GrAccessPattern,
const void* data) override;
bool onReadPixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType dstColorType, void* buffer,
bool onReadPixels(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType dstColorType,
void*,
size_t rowBytes) override;
bool onWritePixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType srcColorType,
const GrMipLevel texels[], int mipLevelCount,
bool prepForTexSampling) override;
bool onWritePixels(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType srcColorType,
const GrMipLevel[],
int mipLevelCount,
bool) override;
bool onTransferPixelsTo(GrTexture*, int left, int top, int width, int height,
GrColorType textureColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset,
bool onTransferPixelsTo(GrTexture*,
SkIRect,
GrColorType textureColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer>,
size_t offset,
size_t rowBytes) override;
bool onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset) override;
bool onTransferPixelsFrom(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer>,
size_t offset) override;
void onResolveRenderTarget(GrRenderTarget*, const SkIRect&) override {}

View File

@ -815,9 +815,12 @@ static bool check_write_and_transfer_input(GrGLTexture* glTex) {
return true;
}
bool GrGLGpu::onWritePixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType srcColorType,
const GrMipLevel texels[], int mipLevelCount,
bool GrGLGpu::onWritePixels(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType srcColorType,
const GrMipLevel texels[],
int mipLevelCount,
bool prepForTexSampling) {
auto glTex = static_cast<GrGLTexture*>(surface->asTexture());
@ -845,15 +848,22 @@ bool GrGLGpu::onWritePixels(GrSurface* surface, int left, int top, int width, in
}
SkASSERT(!GrGLFormatIsCompressed(glTex->format()));
SkIRect dstRect = SkIRect::MakeXYWH(left, top, width, height);
return this->uploadColorTypeTexData(glTex->format(), surfaceColorType, glTex->dimensions(),
glTex->target(), dstRect, srcColorType, texels,
return this->uploadColorTypeTexData(glTex->format(),
surfaceColorType,
glTex->dimensions(),
glTex->target(),
rect,
srcColorType,
texels,
mipLevelCount);
}
bool GrGLGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int width, int height,
GrColorType textureColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset,
bool GrGLGpu::onTransferPixelsTo(GrTexture* texture,
SkIRect rect,
GrColorType textureColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer,
size_t offset,
size_t rowBytes) {
GrGLTexture* glTex = static_cast<GrGLTexture*>(texture);
@ -865,9 +875,6 @@ bool GrGLGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int widt
}
static_assert(sizeof(int) == sizeof(int32_t), "");
if (width <= 0 || height <= 0) {
return false;
}
this->bindTextureToScratchUnit(glTex->target(), glTex->textureID());
@ -876,18 +883,11 @@ bool GrGLGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int widt
const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(transferBuffer.get());
this->bindBuffer(GrGpuBufferType::kXferCpuToGpu, glBuffer);
SkDEBUGCODE(
SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
SkIRect bounds = SkIRect::MakeWH(texture->width(), texture->height());
SkASSERT(bounds.contains(subRect));
)
SkASSERT(SkIRect::MakeSize(texture->dimensions()).contains(rect));
size_t bpp = GrColorTypeBytesPerPixel(bufferColorType);
const size_t trimRowBytes = width * bpp;
const size_t trimRowBytes = rect.width() * bpp;
const void* pixels = (void*)offset;
if (width < 0 || height < 0) {
return false;
}
bool restoreGLRowLength = false;
if (trimRowBytes != rowBytes) {
@ -910,10 +910,12 @@ bool GrGLGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int widt
GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1));
GL_CALL(TexSubImage2D(glTex->target(),
0,
left, top,
width,
height,
externalFormat, externalType,
rect.left(),
rect.top(),
rect.width(),
rect.height(),
externalFormat,
externalType,
pixels));
if (restoreGLRowLength) {
@ -923,14 +925,21 @@ bool GrGLGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int widt
return true;
}
bool GrGLGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType dstColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset) {
bool GrGLGpu::onTransferPixelsFrom(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType dstColorType,
sk_sp<GrGpuBuffer> transferBuffer,
size_t offset) {
auto* glBuffer = static_cast<GrGLBuffer*>(transferBuffer.get());
this->bindBuffer(GrGpuBufferType::kXferGpuToCpu, glBuffer);
auto offsetAsPtr = reinterpret_cast<void*>(offset);
return this->readOrTransferPixelsFrom(surface, left, top, width, height, surfaceColorType,
dstColorType, offsetAsPtr, width);
return this->readOrTransferPixelsFrom(surface,
rect,
surfaceColorType,
dstColorType,
offsetAsPtr,
rect.width());
}
void GrGLGpu::unbindXferBuffer(GrGpuBufferType type) {
@ -2098,9 +2107,12 @@ void GrGLGpu::clearStencilClip(const GrScissorState& scissor, bool insideStencil
fHWStencilSettings.invalidate();
}
bool GrGLGpu::readOrTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType dstColorType,
void* offsetOrPtr, int rowWidthInPixels) {
bool GrGLGpu::readOrTransferPixelsFrom(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType dstColorType,
void* offsetOrPtr,
int rowWidthInPixels) {
SkASSERT(surface);
auto format = surface->backendFormat().asGLFormat();
@ -2132,20 +2144,22 @@ bool GrGLGpu::readOrTransferPixelsFrom(GrSurface* surface, int left, int top, in
fHWBoundRenderTargetUniqueID.makeInvalid();
}
// the read rect is viewport-relative
GrNativeRect readRect = {left, top, width, height};
// determine if GL can read using the passed rowBytes or if we need a scratch buffer.
if (rowWidthInPixels != width) {
if (rowWidthInPixels != rect.width()) {
SkASSERT(this->glCaps().readPixelsRowBytesSupport());
GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, rowWidthInPixels));
}
GL_CALL(PixelStorei(GR_GL_PACK_ALIGNMENT, 1));
GL_CALL(ReadPixels(readRect.fX, readRect.fY, readRect.fWidth, readRect.fHeight,
externalFormat, externalType, offsetOrPtr));
GL_CALL(ReadPixels(rect.left(),
rect.top(),
rect.width(),
rect.height(),
externalFormat,
externalType,
offsetOrPtr));
if (rowWidthInPixels != width) {
if (rowWidthInPixels != rect.width()) {
SkASSERT(this->glCaps().readPixelsRowBytesSupport());
GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
}
@ -2156,8 +2170,11 @@ bool GrGLGpu::readOrTransferPixelsFrom(GrSurface* surface, int left, int top, in
return true;
}
bool GrGLGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType dstColorType, void* buffer,
bool GrGLGpu::onReadPixels(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType dstColorType,
void* buffer,
size_t rowBytes) {
SkASSERT(surface);
@ -2166,15 +2183,19 @@ bool GrGLGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int
// GL_PACK_ROW_LENGTH is in terms of pixels not bytes.
int rowPixelWidth;
if (rowBytes == SkToSizeT(width * bytesPerPixel)) {
rowPixelWidth = width;
if (rowBytes == SkToSizeT(rect.width()*bytesPerPixel)) {
rowPixelWidth = rect.width();
} else {
SkASSERT(!(rowBytes % bytesPerPixel));
rowPixelWidth = rowBytes / bytesPerPixel;
}
this->unbindXferBuffer(GrGpuBufferType::kXferGpuToCpu);
return this->readOrTransferPixelsFrom(surface, left, top, width, height, surfaceColorType,
dstColorType, buffer, rowPixelWidth);
return this->readOrTransferPixelsFrom(surface,
rect,
surfaceColorType,
dstColorType,
buffer,
rowPixelWidth);
}
GrOpsRenderPass* GrGLGpu::onGetOpsRenderPass(

View File

@ -295,25 +295,42 @@ private:
GrMipmapped,
GrGLTextureParameters::SamplerOverriddenState*);
bool onReadPixels(GrSurface*, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType dstColorType, void* buffer,
bool onReadPixels(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType dstColorType,
void*,
size_t rowBytes) override;
bool onWritePixels(GrSurface*, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType srcColorType,
const GrMipLevel texels[], int mipLevelCount,
bool onWritePixels(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType srcColorType,
const GrMipLevel[],
int mipLevelCount,
bool prepForTexSampling) override;
bool onTransferPixelsTo(GrTexture*, int left, int top, int width, int height,
GrColorType textureColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset,
bool onTransferPixelsTo(GrTexture*,
SkIRect,
GrColorType textureColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer>,
size_t offset,
size_t rowBytes) override;
bool onTransferPixelsFrom(GrSurface*, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset) override;
bool readOrTransferPixelsFrom(GrSurface*, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType dstColorType,
void* offsetOrPtr, int rowWidthInPixels);
bool onTransferPixelsFrom(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer>,
size_t offset) override;
bool readOrTransferPixelsFrom(GrSurface*,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType dstColorType,
void* offsetOrPtr,
int rowWidthInPixels);
// Unbinds xfer buffers from GL for operations that don't need them.
// Before calling any variation of TexImage, TexSubImage, etc..., call this with

View File

@ -90,30 +90,44 @@ private:
sk_sp<GrGpuBuffer> onCreateBuffer(size_t sizeInBytes, GrGpuBufferType, GrAccessPattern,
const void*) override;
bool onReadPixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType dstColorType, void* buffer,
bool onReadPixels(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType dstColorType,
void*,
size_t rowBytes) override {
return true;
}
bool onWritePixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType srcColorType,
const GrMipLevel texels[], int mipLevelCount,
bool onWritePixels(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType srcColorType,
const GrMipLevel[],
int mipLevelCount,
bool prepForTexSampling) override {
return true;
}
bool onTransferPixelsTo(GrTexture* texture, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset,
bool onTransferPixelsTo(GrTexture*,
SkIRect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer>,
size_t offset,
size_t rowBytes) override {
return true;
}
bool onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset) override {
bool onTransferPixelsFrom(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer>,
size_t offset) override {
return true;
}
bool onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
const SkIPoint& dstPoint) override {
return true;

View File

@ -179,21 +179,35 @@ private:
sk_sp<GrGpuBuffer> onCreateBuffer(size_t, GrGpuBufferType, GrAccessPattern,
const void*) override;
bool onReadPixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType, void* buffer,
bool onReadPixels(GrSurface* surface,
SkIRect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
void*,
size_t rowBytes) override;
bool onWritePixels(GrSurface*, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
const GrMipLevel[], int mipLevelCount,
bool onWritePixels(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
const GrMipLevel[],
int mipLevelCount,
bool prepForTexSampling) override;
bool onTransferPixelsTo(GrTexture*, int left, int top, int width, int height,
GrColorType textureColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer>, size_t offset, size_t rowBytes) override;
bool onTransferPixelsFrom(GrSurface*, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer>, size_t offset) override;
bool onTransferPixelsTo(GrTexture*,
SkIRect,
GrColorType textureColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer>,
size_t offset,
size_t rowBytes) override;
bool onTransferPixelsFrom(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer>,
size_t offset) override;
bool onRegenerateMipMapLevels(GrTexture*) override;
@ -225,13 +239,22 @@ private:
void checkForFinishedCommandBuffers();
// Function that uploads data onto textures with private storage mode (GPU access only).
bool uploadToTexture(GrMtlTexture* tex, int left, int top, int width, int height,
GrColorType dataColorType, const GrMipLevel texels[], int mipLevels);
bool uploadToTexture(GrMtlTexture* tex,
SkIRect rect,
GrColorType dataColorType,
const GrMipLevel texels[],
int mipLevels);
// Function that fills texture levels with transparent black based on levelMask.
bool clearTexture(GrMtlTexture*, size_t bbp, uint32_t levelMask);
bool readOrTransferPixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType dstColorType, id<MTLBuffer> transferBuffer, size_t offset,
size_t imageBytes, size_t rowBytes);
bool readOrTransferPixels(GrSurface* surface,
SkIRect rect,
GrColorType dstColorType,
id<MTLBuffer> transferBuffer,
size_t offset,
size_t imageBytes,
size_t rowBytes);
sk_sp<GrAttachment> makeStencilAttachment(const GrBackendFormat& /*colorFormat*/,
SkISize dimensions, int numStencilSamples) override;

View File

@ -340,22 +340,23 @@ static bool check_max_blit_width(int widthInPixels) {
return true;
}
bool GrMtlGpu::uploadToTexture(GrMtlTexture* tex, int left, int top, int width, int height,
GrColorType dataColorType, const GrMipLevel texels[],
bool GrMtlGpu::uploadToTexture(GrMtlTexture* tex,
SkIRect rect,
GrColorType dataColorType,
const GrMipLevel texels[],
int mipLevelCount) {
SkASSERT(this->caps()->isFormatTexturable(tex->backendFormat()));
// The assumption is either that we have no mipmaps, or that our rect is the entire texture
SkASSERT(1 == mipLevelCount ||
(0 == left && 0 == top && width == tex->width() && height == tex->height()));
SkASSERT(mipLevelCount == 1 || rect == SkIRect::MakeSize(tex->dimensions()));
// We assume that if the texture has mip levels, we either upload to all the levels or just the
// first.
SkASSERT(1 == mipLevelCount || mipLevelCount == (tex->maxMipmapLevel() + 1));
SkASSERT(mipLevelCount == 1 || mipLevelCount == (tex->maxMipmapLevel() + 1));
if (!check_max_blit_width(width)) {
if (!check_max_blit_width(rect.width())) {
return false;
}
if (width == 0 || height == 0) {
if (rect.isEmpty()) {
return false;
}
@ -367,7 +368,7 @@ bool GrMtlGpu::uploadToTexture(GrMtlTexture* tex, int left, int top, int width,
// Either upload only the first miplevel or all miplevels
SkASSERT(1 == mipLevelCount || mipLevelCount == (int)mtlTexture.mipmapLevelCount);
if (1 == mipLevelCount && !texels[0].fPixels) {
if (mipLevelCount == 1 && !texels[0].fPixels) {
return true; // no data to upload
}
@ -381,8 +382,10 @@ bool GrMtlGpu::uploadToTexture(GrMtlTexture* tex, int left, int top, int width,
size_t bpp = GrColorTypeBytesPerPixel(dataColorType);
SkTArray<size_t> individualMipOffsets(mipLevelCount);
size_t combinedBufferSize = GrComputeTightCombinedBufferSize(
bpp, {width, height}, &individualMipOffsets, mipLevelCount);
size_t combinedBufferSize = GrComputeTightCombinedBufferSize(bpp,
rect.size(),
&individualMipOffsets,
mipLevelCount);
SkASSERT(combinedBufferSize);
@ -401,10 +404,10 @@ bool GrMtlGpu::uploadToTexture(GrMtlTexture* tex, int left, int top, int width,
char* bufferData = (char*)slice.fOffsetMapPtr;
GrMtlBuffer* mtlBuffer = static_cast<GrMtlBuffer*>(slice.fBuffer);
int currentWidth = width;
int currentHeight = height;
int currentWidth = rect.width();
int currentHeight = rect.height();
int layerHeight = tex->height();
MTLOrigin origin = MTLOriginMake(left, top, 0);
MTLOrigin origin = MTLOriginMake(rect.left(), rect.top(), 0);
auto cmdBuffer = this->commandBuffer();
id<MTLBlitCommandEncoder> GR_NORETAIN blitCmdEncoder = cmdBuffer->getBlitCommandEncoder();
@ -1258,9 +1261,12 @@ bool GrMtlGpu::onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcR
return success;
}
bool GrMtlGpu::onWritePixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType srcColorType,
const GrMipLevel texels[], int mipLevelCount,
bool GrMtlGpu::onWritePixels(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType srcColorType,
const GrMipLevel texels[],
int mipLevelCount,
bool prepForTexSampling) {
GrMtlTexture* mtlTexture = static_cast<GrMtlTexture*>(surface->asTexture());
// TODO: In principle we should be able to support pure rendertargets as well, but
@ -1276,12 +1282,14 @@ bool GrMtlGpu::onWritePixels(GrSurface* surface, int left, int top, int width, i
SkASSERT(texels[i].fPixels);
}
#endif
return this->uploadToTexture(mtlTexture, left, top, width, height, srcColorType, texels,
mipLevelCount);
return this->uploadToTexture(mtlTexture, rect, srcColorType, texels, mipLevelCount);
}
bool GrMtlGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType dstColorType, void* buffer,
bool GrMtlGpu::onReadPixels(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType dstColorType,
void* buffer,
size_t rowBytes) {
SkASSERT(surface);
@ -1290,8 +1298,8 @@ bool GrMtlGpu::onReadPixels(GrSurface* surface, int left, int top, int width, in
}
int bpp = GrColorTypeBytesPerPixel(dstColorType);
size_t transBufferRowBytes = bpp * width;
size_t transBufferImageBytes = transBufferRowBytes * height;
size_t transBufferRowBytes = bpp*rect.width();
size_t transBufferImageBytes = transBufferRowBytes*rect.height();
// TODO: implement some way of reusing buffers instead of making a new one every time.
NSUInteger options = 0;
@ -1313,23 +1321,35 @@ bool GrMtlGpu::onReadPixels(GrSurface* surface, int left, int top, int width, in
}
GrMtlBuffer* grMtlBuffer = static_cast<GrMtlBuffer*>(transferBuffer.get());
if (!this->readOrTransferPixels(surface, left, top, width, height, dstColorType,
if (!this->readOrTransferPixels(surface,
rect,
dstColorType,
grMtlBuffer->mtlBuffer(),
0, transBufferImageBytes, transBufferRowBytes)) {
0,
transBufferImageBytes,
transBufferRowBytes)) {
return false;
}
this->submitCommandBuffer(kForce_SyncQueue);
const void* mappedMemory = grMtlBuffer->mtlBuffer().contents;
SkRectMemcpy(buffer, rowBytes, mappedMemory, transBufferRowBytes, transBufferRowBytes, height);
SkRectMemcpy(buffer,
rowBytes,
mappedMemory,
transBufferRowBytes,
transBufferRowBytes,
rect.height());
return true;
}
bool GrMtlGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int width, int height,
GrColorType textureColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset,
bool GrMtlGpu::onTransferPixelsTo(GrTexture* texture,
SkIRect rect,
GrColorType textureColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer,
size_t offset,
size_t rowBytes) {
SkASSERT(texture);
SkASSERT(transferBuffer);
@ -1353,15 +1373,15 @@ bool GrMtlGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int wid
return false;
}
MTLOrigin origin = MTLOriginMake(left, top, 0);
MTLOrigin origin = MTLOriginMake(rect.left(), rect.top(), 0);
auto cmdBuffer = this->commandBuffer();
id<MTLBlitCommandEncoder> GR_NORETAIN blitCmdEncoder = cmdBuffer->getBlitCommandEncoder();
[blitCmdEncoder copyFromBuffer: mtlBuffer
sourceOffset: offset + grMtlBuffer->offset()
sourceBytesPerRow: rowBytes
sourceBytesPerImage: rowBytes*height
sourceSize: MTLSizeMake(width, height, 1)
sourceBytesPerImage: rowBytes*rect.height()
sourceSize: MTLSizeMake(rect.width(), rect.height(), 1)
toTexture: mtlTexture
destinationSlice: 0
destinationLevel: 0
@ -1370,9 +1390,12 @@ bool GrMtlGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int wid
return true;
}
bool GrMtlGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset) {
bool GrMtlGpu::onTransferPixelsFrom(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer,
size_t offset) {
SkASSERT(surface);
SkASSERT(transferBuffer);
@ -1391,18 +1414,26 @@ bool GrMtlGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int w
GrMtlBuffer* grMtlBuffer = static_cast<GrMtlBuffer*>(transferBuffer.get());
size_t transBufferRowBytes = bpp * width;
size_t transBufferImageBytes = transBufferRowBytes * height;
size_t transBufferRowBytes = bpp*rect.width();
size_t transBufferImageBytes = transBufferRowBytes*rect.height();
return this->readOrTransferPixels(surface, left, top, width, height, bufferColorType,
grMtlBuffer->mtlBuffer(), offset + grMtlBuffer->offset(),
transBufferImageBytes, transBufferRowBytes);
return this->readOrTransferPixels(surface,
rect,
bufferColorType,
grMtlBuffer->mtlBuffer(),
offset + grMtlBuffer->offset(),
transBufferImageBytes,
transBufferRowBytes);
}
bool GrMtlGpu::readOrTransferPixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType dstColorType, id<MTLBuffer> transferBuffer,
size_t offset, size_t imageBytes, size_t rowBytes) {
if (!check_max_blit_width(width)) {
bool GrMtlGpu::readOrTransferPixels(GrSurface* surface,
SkIRect rect,
GrColorType dstColorType,
id<MTLBuffer> transferBuffer,
size_t offset,
size_t imageBytes,
size_t rowBytes) {
if (!check_max_blit_width(rect.width())) {
return false;
}
@ -1427,8 +1458,8 @@ bool GrMtlGpu::readOrTransferPixels(GrSurface* surface, int left, int top, int w
[blitCmdEncoder copyFromTexture: mtlTexture
sourceSlice: 0
sourceLevel: 0
sourceOrigin: MTLOriginMake(left, top, 0)
sourceSize: MTLSizeMake(width, height, 1)
sourceOrigin: MTLOriginMake(rect.left(), rect.top(), 0)
sourceSize: MTLSizeMake(rect.width(), rect.height(), 1)
toBuffer: transferBuffer
destinationOffset: offset
destinationBytesPerRow: rowBytes

View File

@ -475,9 +475,12 @@ sk_sp<GrGpuBuffer> GrVkGpu::onCreateBuffer(size_t size, GrGpuBufferType type,
return buff;
}
bool GrVkGpu::onWritePixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType srcColorType,
const GrMipLevel texels[], int mipLevelCount,
bool GrVkGpu::onWritePixels(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType srcColorType,
const GrMipLevel texels[],
int mipLevelCount,
bool prepForTexSampling) {
GrVkTexture* texture = static_cast<GrVkTexture*>(surface->asTexture());
if (!texture) {
@ -509,12 +512,18 @@ bool GrVkGpu::onWritePixels(GrSurface* surface, int left, int top, int width, in
return false;
}
}
success = this->uploadTexDataLinear(texAttachment, left, top, width, height, srcColorType,
texels[0].fPixels, texels[0].fRowBytes);
success = this->uploadTexDataLinear(texAttachment,
rect,
srcColorType,
texels[0].fPixels,
texels[0].fRowBytes);
} else {
SkASSERT(mipLevelCount <= (int)texAttachment->mipLevels());
success = this->uploadTexDataOptimal(texAttachment, left, top, width, height, srcColorType,
texels, mipLevelCount);
success = this->uploadTexDataOptimal(texAttachment,
rect,
srcColorType,
texels,
mipLevelCount);
if (1 == mipLevelCount) {
texture->markMipmapsDirty();
}
@ -531,9 +540,12 @@ bool GrVkGpu::onWritePixels(GrSurface* surface, int left, int top, int width, in
return success;
}
bool GrVkGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t bufferOffset,
bool GrVkGpu::onTransferPixelsTo(GrTexture* texture,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer,
size_t bufferOffset,
size_t rowBytes) {
if (!this->currentCommandBuffer()) {
return false;
@ -567,11 +579,7 @@ bool GrVkGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int widt
}
SkASSERT(GrVkFormatBytesPerBlock(format) == GrColorTypeBytesPerPixel(bufferColorType));
SkDEBUGCODE(
SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
SkIRect bounds = SkIRect::MakeWH(texture->width(), texture->height());
SkASSERT(bounds.contains(subRect));
)
SkASSERT(SkIRect::MakeSize(texture->dimensions()).contains(rect));
// Set up copy region
VkBufferImageCopy region;
@ -580,8 +588,8 @@ bool GrVkGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int widt
region.bufferRowLength = (uint32_t)(rowBytes/bpp);
region.bufferImageHeight = 0;
region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
region.imageOffset = { left, top, 0 };
region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 };
region.imageOffset = { rect.left(), rect.top(), 0 };
region.imageExtent = { (uint32_t)rect.width(), (uint32_t)rect.height(), 1 };
// Change layout of our target so it can be copied to
vkTex->setImageLayout(this,
@ -605,9 +613,12 @@ bool GrVkGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int widt
return true;
}
bool GrVkGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset) {
bool GrVkGpu::onTransferPixelsFrom(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer,
size_t offset) {
if (!this->currentCommandBuffer()) {
return false;
}
@ -644,11 +655,11 @@ bool GrVkGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int wi
VkBufferImageCopy region;
memset(&region, 0, sizeof(VkBufferImageCopy));
region.bufferOffset = offset;
region.bufferRowLength = width;
region.bufferRowLength = rect.width();
region.bufferImageHeight = 0;
region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
region.imageOffset = { left, top, 0 };
region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 };
region.imageOffset = {rect.left(), rect.top(), 0};
region.imageExtent = {(uint32_t)rect.width(), (uint32_t)rect.height(), 1};
srcImage->setImageLayout(this,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
@ -729,19 +740,18 @@ void GrVkGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resol
SkIPoint::Make(resolveRect.x(), resolveRect.y()));
}
bool GrVkGpu::uploadTexDataLinear(GrVkAttachment* texAttachment, int left, int top, int width,
int height, GrColorType dataColorType, const void* data,
bool GrVkGpu::uploadTexDataLinear(GrVkAttachment* texAttachment,
SkIRect rect,
GrColorType dataColorType,
const void* data,
size_t rowBytes) {
SkASSERT(data);
SkASSERT(texAttachment->isLinearTiled());
SkDEBUGCODE(
SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
SkIRect bounds = SkIRect::MakeWH(texAttachment->width(), texAttachment->height());
SkASSERT(bounds.contains(subRect));
)
SkASSERT(SkIRect::MakeSize(texAttachment->dimensions()).contains(rect));
size_t bpp = GrColorTypeBytesPerPixel(dataColorType);
size_t trimRowBytes = width * bpp;
size_t trimRowBytes = rect.width() * bpp;
SkASSERT(VK_IMAGE_LAYOUT_PREINITIALIZED == texAttachment->currentLayout() ||
VK_IMAGE_LAYOUT_GENERAL == texAttachment->currentLayout());
@ -763,8 +773,8 @@ bool GrVkGpu::uploadTexDataLinear(GrVkAttachment* texAttachment, int left, int t
if (VK_NULL_HANDLE == alloc.fMemory) {
return false;
}
VkDeviceSize offset = top * layout.rowPitch + left * bpp;
VkDeviceSize size = height*layout.rowPitch;
VkDeviceSize offset = rect.top()*layout.rowPitch + rect.left()*bpp;
VkDeviceSize size = rect.height()*layout.rowPitch;
SkASSERT(size + offset <= alloc.fSize);
void* mapPtr = GrVkMemory::MapAlloc(this, alloc);
if (!mapPtr) {
@ -772,8 +782,12 @@ bool GrVkGpu::uploadTexDataLinear(GrVkAttachment* texAttachment, int left, int t
}
mapPtr = reinterpret_cast<char*>(mapPtr) + offset;
SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), data, rowBytes, trimRowBytes,
height);
SkRectMemcpy(mapPtr,
static_cast<size_t>(layout.rowPitch),
data,
rowBytes,
trimRowBytes,
rect.height());
GrVkMemory::FlushMappedAlloc(this, alloc, offset, size);
GrVkMemory::UnmapAlloc(this, alloc);
@ -840,8 +854,10 @@ static size_t fill_in_compressed_regions(GrStagingBufferManager* stagingBufferMa
return bufferSize;
}
bool GrVkGpu::uploadTexDataOptimal(GrVkAttachment* texAttachment, int left, int top, int width,
int height, GrColorType dataColorType, const GrMipLevel texels[],
bool GrVkGpu::uploadTexDataOptimal(GrVkAttachment* texAttachment,
SkIRect rect,
GrColorType dataColorType,
const GrMipLevel texels[],
int mipLevelCount) {
if (!this->currentCommandBuffer()) {
return false;
@ -849,17 +865,13 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkAttachment* texAttachment, int left, int
SkASSERT(!texAttachment->isLinearTiled());
// The assumption is either that we have no mipmaps, or that our rect is the entire texture
SkASSERT(1 == mipLevelCount ||
(0 == left && 0 == top && width == texAttachment->width() &&
height == texAttachment->height()));
SkASSERT(mipLevelCount == 1 || rect == SkIRect::MakeSize(texAttachment->dimensions()));
// We assume that if the texture has mip levels, we either upload to all the levels or just the
// first.
SkASSERT(1 == mipLevelCount || mipLevelCount == (int)texAttachment->mipLevels());
SkASSERT(mipLevelCount == 1 || mipLevelCount == (int)texAttachment->mipLevels());
if (width == 0 || height == 0) {
return false;
}
SkASSERT(!rect.isEmpty());
SkASSERT(this->vkCaps().surfaceSupportsWritePixels(texAttachment));
@ -876,12 +888,12 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkAttachment* texAttachment, int left, int
size_t combinedBufferSize;
if (mipLevelCount > 1) {
combinedBufferSize = GrComputeTightCombinedBufferSize(bpp,
{width, height},
rect.size(),
&individualMipOffsets,
mipLevelCount);
} else {
SkASSERT(texelsShallowCopy[0].fPixels && texelsShallowCopy[0].fRowBytes);
combinedBufferSize = width*height*bpp;
combinedBufferSize = rect.width()*rect.height()*bpp;
individualMipOffsets.push_back(0);
}
SkASSERT(combinedBufferSize);
@ -900,14 +912,14 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkAttachment* texAttachment, int left, int
return false;
}
int uploadLeft = left;
int uploadTop = top;
int uploadLeft = rect.left();
int uploadTop = rect.top();
char* buffer = (char*) slice.fOffsetMapPtr;
SkTArray<VkBufferImageCopy> regions(mipLevelCount);
int currentWidth = width;
int currentHeight = height;
int currentWidth = rect.width();
int currentHeight = rect.height();
int layerHeight = texAttachment->height();
for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
if (texelsShallowCopy[currentMipLevel].fPixels) {
@ -2330,8 +2342,11 @@ bool GrVkGpu::onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRe
return false;
}
bool GrVkGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType dstColorType, void* buffer,
bool GrVkGpu::onReadPixels(GrSurface* surface,
SkIRect rect,
GrColorType surfaceColorType,
GrColorType dstColorType,
void* buffer,
size_t rowBytes) {
if (surface->isProtected()) {
return false;
@ -2375,13 +2390,13 @@ bool GrVkGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int
if (GrVkFormatBytesPerBlock(image->imageFormat()) != bpp) {
return false;
}
size_t tightRowBytes = bpp * width;
size_t tightRowBytes = bpp*rect.width();
VkBufferImageCopy region;
memset(&region, 0, sizeof(VkBufferImageCopy));
VkOffset3D offset = { left, top, 0 };
VkOffset3D offset = { rect.left(), rect.top(), 0 };
region.imageOffset = offset;
region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 };
region.imageExtent = { (uint32_t)rect.width(), (uint32_t)rect.height(), 1 };
size_t transBufferRowBytes = bpp * region.imageExtent.width;
size_t imageRows = region.imageExtent.height;
@ -2423,7 +2438,7 @@ bool GrVkGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int
}
void* mappedMemory = transferBuffer->map();
SkRectMemcpy(buffer, rowBytes, mappedMemory, transBufferRowBytes, tightRowBytes, height);
SkRectMemcpy(buffer, rowBytes, mappedMemory, transBufferRowBytes, tightRowBytes, rect.height());
transferBuffer->unmap();
return true;

View File

@ -268,22 +268,35 @@ private:
sk_sp<GrGpuBuffer> onCreateBuffer(size_t size, GrGpuBufferType type, GrAccessPattern,
const void* data) override;
bool onReadPixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType dstColorType, void* buffer,
bool onReadPixels(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType dstColorType,
void* buffer,
size_t rowBytes) override;
bool onWritePixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType srcColorType,
const GrMipLevel texels[], int mipLevelCount,
bool onWritePixels(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType srcColorType,
const GrMipLevel[],
int mipLevelCount,
bool prepForTexSampling) override;
bool onTransferPixelsTo(GrTexture*, int left, int top, int width, int height,
GrColorType textureColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset,
bool onTransferPixelsTo(GrTexture*,
SkIRect,
GrColorType textureColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer>,
size_t offset,
size_t rowBytes) override;
bool onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
sk_sp<GrGpuBuffer> transferBuffer, size_t offset) override;
bool onTransferPixelsFrom(GrSurface*,
SkIRect,
GrColorType surfaceColorType,
GrColorType bufferColorType,
sk_sp<GrGpuBuffer>,
size_t offset) override;
bool onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
const SkIPoint& dstPoint) override;
@ -331,10 +344,16 @@ private:
const SkIPoint& dstPoint);
// helpers for onCreateTexture and writeTexturePixels
bool uploadTexDataLinear(GrVkAttachment* tex, int left, int top, int width, int height,
GrColorType colorType, const void* data, size_t rowBytes);
bool uploadTexDataOptimal(GrVkAttachment* tex, int left, int top, int width, int height,
GrColorType colorType, const GrMipLevel texels[], int mipLevelCount);
bool uploadTexDataLinear(GrVkAttachment* tex,
SkIRect rect,
GrColorType colorType,
const void* data,
size_t rowBytes);
bool uploadTexDataOptimal(GrVkAttachment* tex,
SkIRect rect,
GrColorType colorType,
const GrMipLevel texels[],
int mipLevelCount);
bool uploadTexDataCompressed(GrVkAttachment* tex, SkImage::CompressionType compression,
VkFormat vkFormat, SkISize dimensions, GrMipmapped mipMapped,
const void* data, size_t dataSize);

View File

@ -389,9 +389,12 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReadOnlyTexture, reporter, context_info) {
// Try the low level write.
dContext->flushAndSubmit();
auto gpuWriteResult = dContext->priv().getGpu()->writePixels(
proxy->peekTexture(), 0, 0, kSize, kSize, GrColorType::kRGBA_8888,
GrColorType::kRGBA_8888, write.addr32(),
kSize * GrColorTypeBytesPerPixel(GrColorType::kRGBA_8888));
proxy->peekTexture(),
SkIRect::MakeWH(kSize, kSize),
GrColorType::kRGBA_8888,
GrColorType::kRGBA_8888,
write.addr32(),
kSize*GrColorTypeBytesPerPixel(GrColorType::kRGBA_8888));
REPORTER_ASSERT(reporter, gpuWriteResult == (ioType == kRW_GrIOType));
SkBitmap copySrcBitmap;

View File

@ -82,8 +82,12 @@ bool read_pixels_from_texture(GrTexture* texture, GrColorType colorType, char* d
if (supportedRead.fColorType != colorType) {
size_t tmpRowBytes = GrColorTypeBytesPerPixel(supportedRead.fColorType) * w;
std::unique_ptr<char[]> tmpPixels(new char[tmpRowBytes * h]);
if (!gpu->readPixels(texture, 0, 0, w, h, colorType, supportedRead.fColorType,
tmpPixels.get(), tmpRowBytes)) {
if (!gpu->readPixels(texture,
SkIRect::MakeWH(w, h),
colorType,
supportedRead.fColorType,
tmpPixels.get(),
tmpRowBytes)) {
return false;
}
GrImageInfo tmpInfo(supportedRead.fColorType, kUnpremul_SkAlphaType, nullptr, w, h);
@ -92,7 +96,12 @@ bool read_pixels_from_texture(GrTexture* texture, GrColorType colorType, char* d
return GrConvertPixels(GrPixmap(dstInfo, dst, rowBytes),
GrPixmap(tmpInfo, tmpPixels.get(), tmpRowBytes));
}
return gpu->readPixels(texture, 0, 0, w, h, colorType, supportedRead.fColorType, dst, rowBytes);
return gpu->readPixels(texture,
SkIRect::MakeWH(w, h),
colorType,
supportedRead.fColorType,
dst,
rowBytes);
}
void basic_transfer_to_test(skiatest::Reporter* reporter,
@ -170,8 +179,13 @@ void basic_transfer_to_test(skiatest::Reporter* reporter,
// transfer full data
bool result;
result = gpu->transferPixelsTo(tex.get(), 0, 0, kTexDims.fWidth, kTexDims.fHeight, colorType,
allowedSrc.fColorType, buffer, 0, srcRowBytes);
result = gpu->transferPixelsTo(tex.get(),
SkIRect::MakeSize(kTexDims),
colorType,
allowedSrc.fColorType,
buffer,
0,
srcRowBytes);
REPORTER_ASSERT(reporter, result);
size_t dstRowBytes = GrColorTypeBytesPerPixel(colorType) * kTexDims.fWidth;
@ -237,8 +251,13 @@ void basic_transfer_to_test(skiatest::Reporter* reporter,
memcpy(data, srcData.get(), size);
buffer->unmap();
result = gpu->transferPixelsTo(tex.get(), left, top, width, height, colorType,
allowedSrc.fColorType, buffer, offset, srcRowBytes);
result = gpu->transferPixelsTo(tex.get(),
SkIRect::MakeXYWH(left, top, width, height),
colorType,
allowedSrc.fColorType,
buffer,
offset,
srcRowBytes);
if (!result) {
ERRORF(reporter, "Could not transfer pixels to texture, color type: %d",
static_cast<int>(colorType));
@ -340,8 +359,12 @@ void basic_transfer_from_test(skiatest::Reporter* reporter, const sk_gpu_test::C
//////////////////////////
// transfer full data
bool result = gpu->transferPixelsFrom(tex.get(), 0, 0, kTexDims.fWidth, kTexDims.fHeight,
colorType, allowedRead.fColorType, buffer, 0);
bool result = gpu->transferPixelsFrom(tex.get(),
SkIRect::MakeSize(kTexDims),
colorType,
allowedRead.fColorType,
buffer,
0);
if (!result) {
ERRORF(reporter, "transferPixelsFrom failed.");
return;
@ -382,9 +405,13 @@ void basic_transfer_from_test(skiatest::Reporter* reporter, const sk_gpu_test::C
///////////////////////
// Now test a partial read at an offset into the buffer.
result = gpu->transferPixelsFrom(tex.get(), kPartialLeft, kPartialTop, kPartialWidth,
kPartialHeight, colorType, allowedRead.fColorType,
buffer, partialReadOffset);
result = gpu->transferPixelsFrom(
tex.get(),
SkIRect::MakeXYWH(kPartialLeft, kPartialTop, kPartialWidth, kPartialHeight),
colorType,
allowedRead.fColorType,
buffer,
partialReadOffset);
if (!result) {
ERRORF(reporter, "transferPixelsFrom failed.");
return;