GrSurface -> GrGpuBuffer transfer improvements:
GrCaps now only provides the offset alignment requirement. The row bytes is always bpp * width. GrGpu::transferPixelsFrom now just returns bool since row bytes value is implicit. It now asserts offset is aligned with GrCap's provided value in base class. Implement caps for GL. Bug: skia:8962 Change-Id: I3299b62efe9fe05bfe02f2a6a4c2704f647d0f8a Reviewed-on: https://skia-review.googlesource.com/c/skia/+/206686 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
c0d79e525f
commit
26de56ef09
@ -68,6 +68,7 @@ typedef unsigned char GrGLubyte;
|
||||
typedef unsigned short GrGLushort;
|
||||
typedef unsigned int GrGLuint;
|
||||
typedef uint64_t GrGLuint64;
|
||||
typedef unsigned short int GrGLhalf;
|
||||
typedef float GrGLfloat;
|
||||
typedef float GrGLclampf;
|
||||
typedef double GrGLdouble;
|
||||
|
@ -277,13 +277,30 @@ bool GrCaps::surfaceSupportsWritePixels(const GrSurface* surface) const {
|
||||
return surface->readOnly() ? false : this->onSurfaceSupportsWritePixels(surface);
|
||||
}
|
||||
|
||||
bool GrCaps::transferFromBufferRequirements(GrColorType bufferColorType, int width,
|
||||
size_t* rowBytes, size_t* offsetAlignment) const {
|
||||
size_t GrCaps::transferFromOffsetAlignment(GrColorType bufferColorType) const {
|
||||
if (!this->transferBufferSupport()) {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
return this->onTransferFromBufferRequirements(bufferColorType, width, rowBytes,
|
||||
offsetAlignment);
|
||||
size_t result = this->onTransferFromOffsetAlignment(bufferColorType);
|
||||
if (!result) {
|
||||
return 0;
|
||||
}
|
||||
// It's very convenient to access 1 byte-per-channel 32 bitvRGB/RGBA color types as uint32_t.
|
||||
// Make those aligned reads out of the buffer even if the underlying API doesn't require it.
|
||||
auto componentFlags = GrColorTypeComponentFlags(bufferColorType);
|
||||
if ((componentFlags == kRGBA_SkColorTypeComponentFlags ||
|
||||
componentFlags == kRGB_SkColorTypeComponentFlags) &&
|
||||
GrColorTypeBytesPerPixel(bufferColorType) == 4) {
|
||||
switch (result & 0b11) {
|
||||
// offset alignment already a multiple of 4
|
||||
case 0: return result;
|
||||
// offset alignment is a multiple of 2 but not 4.
|
||||
case 2: return 2 * result;
|
||||
// offset alignment is not a multiple of 2.
|
||||
default: return 4 * result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool GrCaps::canCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
|
||||
@ -329,12 +346,3 @@ bool GrCaps::validateSurfaceDesc(const GrSurfaceDesc& desc, GrMipMapped mipped)
|
||||
GrBackendFormat GrCaps::getBackendFormatFromColorType(SkColorType ct) const {
|
||||
return this->getBackendFormatFromGrColorType(SkColorTypeToGrColorType(ct), GrSRGBEncoded::kNo);
|
||||
}
|
||||
|
||||
bool GrCaps::onTransferFromBufferRequirements(GrColorType bufferColorType, int width,
|
||||
size_t* rowBytes, size_t* offsetAlignment) const {
|
||||
// TODO(bsalomon): Provide backend-specific overrides of this the return the true requirements.
|
||||
// Currently assuming tight row bytes rounded up to a multiple of 4 and 4 byte offset alignment.
|
||||
*rowBytes = GrSizeAlignUp(GrColorTypeBytesPerPixel(bufferColorType) * width, 4);
|
||||
*offsetAlignment = 4;
|
||||
return true;
|
||||
}
|
||||
|
@ -224,21 +224,16 @@ public:
|
||||
bool transferBufferSupport() const { return fTransferBufferSupport; }
|
||||
|
||||
/**
|
||||
* Gets the requirements to use GrGpu::transferPixelsFrom for a given GrColorType. To check
|
||||
* whether a pixels as GrColorType can be read for a given surface see
|
||||
* supportedReadPixelsColorType() and surfaceSupportsReadPixels().
|
||||
* Gets the alignment requirement for the buffer offset used with GrGpu::transferPixelsFrom for
|
||||
* a given GrColorType. To check whether a pixels as GrColorType can be read for a given surface
|
||||
* see supportedReadPixelsColorType() and surfaceSupportsReadPixels().
|
||||
*
|
||||
* @param bufferColorType The color type of the pixel data that will be stored in the transfer
|
||||
* buffer.
|
||||
* @param width The number of color values per row that will be stored in the buffer.
|
||||
* @param rowBytes The number of bytes per row that will be used in the transfer buffer.
|
||||
* @param alignment The required alignment of the offset into the transfer buffer passed
|
||||
* to GrGpu::transferPixelsFrom.
|
||||
* @return true if transferPixelFrom is supported, false otherwise. If false then rowBytes and
|
||||
* alignment are not updated.
|
||||
* @return minimum required alignment for the buffer offset or zero if reading to the color type
|
||||
* is not supported.
|
||||
*/
|
||||
bool transferFromBufferRequirements(GrColorType bufferColorType, int width, size_t* rowBytes,
|
||||
size_t* offsetAlignment) const;
|
||||
size_t transferFromOffsetAlignment(GrColorType bufferColorType) const;
|
||||
|
||||
bool suppressPrints() const { return fSuppressPrints; }
|
||||
|
||||
@ -426,8 +421,7 @@ private:
|
||||
virtual bool onSurfaceSupportsWritePixels(const GrSurface*) const = 0;
|
||||
virtual bool onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
|
||||
const SkIRect& srcRect, const SkIPoint& dstPoint) const = 0;
|
||||
virtual bool onTransferFromBufferRequirements(GrColorType bufferColorType, int width,
|
||||
size_t* rowBytes, size_t* offsetAlignment) const;
|
||||
virtual size_t onTransferFromOffsetAlignment(GrColorType bufferColorType) const = 0;
|
||||
|
||||
// Backends should implement this if they have any extra requirements for use of window
|
||||
// rectangles for a specific GrBackendRenderTarget outside of basic support.
|
||||
|
@ -330,11 +330,13 @@ bool GrGpu::transferPixelsTo(GrTexture* texture, int left, int top, int width, i
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t GrGpu::transferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
|
||||
GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
|
||||
size_t offset) {
|
||||
bool GrGpu::transferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
|
||||
GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
|
||||
size_t offset) {
|
||||
SkASSERT(surface);
|
||||
SkASSERT(transferBuffer);
|
||||
SkASSERT(this->caps()->transferFromOffsetAlignment(bufferColorType));
|
||||
SkASSERT(offset % this->caps()->transferFromOffsetAlignment(bufferColorType) == 0);
|
||||
|
||||
// We require that the write region is contained in the texture
|
||||
SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
|
||||
@ -344,12 +346,12 @@ size_t GrGpu::transferPixelsFrom(GrSurface* surface, int left, int top, int widt
|
||||
}
|
||||
|
||||
this->handleDirtyContext();
|
||||
if (auto result = this->onTransferPixelsFrom(surface, left, top, width, height, bufferColorType,
|
||||
transferBuffer, offset)) {
|
||||
if (this->onTransferPixelsFrom(surface, left, top, width, height, bufferColorType,
|
||||
transferBuffer, offset)) {
|
||||
fStats.incTransfersFromSurface();
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GrGpu::regenerateMipMapLevels(GrTexture* texture) {
|
||||
|
@ -227,10 +227,14 @@ public:
|
||||
|
||||
/**
|
||||
* Reads the pixels from a rectangle of a surface into a buffer. Use
|
||||
* GrCaps::transferFromBufferRequirements to determine the requirements for the buffer size
|
||||
* and offset alignment. If the surface is a MIP mapped texture, the base level is read.
|
||||
* GrCaps::transferFromOffsetAlignment to determine the requirements for the buffer offset
|
||||
* alignment. If the surface is a MIP mapped texture, the base level is read.
|
||||
*
|
||||
* Returns the number of bytes per row in the buffer or zero on failure.
|
||||
* If successful the row bytes in the buffer is always:
|
||||
* GrColorTypeBytesPerPixel(bufferColorType) * 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)
|
||||
@ -241,9 +245,9 @@ public:
|
||||
* @param transferBuffer GrBuffer to write pixels to (type must be "kXferGpuToCpu")
|
||||
* @param offset offset from the start of the buffer
|
||||
*/
|
||||
size_t transferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
|
||||
GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
|
||||
size_t offset);
|
||||
bool transferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
|
||||
GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
|
||||
size_t offset);
|
||||
|
||||
// After the client interacts directly with the 3D context state the GrGpu
|
||||
// must resync its internal state and assumptions about 3D context state.
|
||||
@ -532,9 +536,9 @@ private:
|
||||
GrColorType colorType, GrGpuBuffer* transferBuffer,
|
||||
size_t offset, size_t rowBytes) = 0;
|
||||
// overridden by backend-specific derived class to perform the surface transfer
|
||||
virtual size_t onTransferPixelsFrom(GrSurface*, int left, int top, int width, int height,
|
||||
GrColorType colorType, GrGpuBuffer* transferBuffer,
|
||||
size_t offset) = 0;
|
||||
virtual bool onTransferPixelsFrom(GrSurface*, int left, int top, int width, int height,
|
||||
GrColorType colorType, GrGpuBuffer* transferBuffer,
|
||||
size_t offset) = 0;
|
||||
|
||||
// overridden by backend-specific derived class to perform the resolve
|
||||
virtual void onResolveRenderTarget(GrRenderTarget* target) = 0;
|
||||
|
@ -3259,3 +3259,44 @@ GrBackendFormat GrGLCaps::getBackendFormatFromGrColorType(GrColorType ct,
|
||||
return GrBackendFormat::MakeGL(this->configSizedInternalFormat(config), GR_GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
size_t GrGLCaps::onTransferFromOffsetAlignment(GrColorType bufferColorType) const {
|
||||
// This implementation is highly coupled with decisions made in initConfigTable and GrGLGpu's
|
||||
// read pixels implementation and may not be correct for all types. TODO(bsalomon): This will be
|
||||
// cleaned up/unified as part of removing GrPixelConfig.
|
||||
// There are known problems with 24 vs 32 bit BPP with this color type. Just fail for now.
|
||||
if (GrColorType::kRGB_888x == bufferColorType) {
|
||||
return 0;
|
||||
}
|
||||
auto config = GrColorTypeToPixelConfig(bufferColorType, GrSRGBEncoded::kNo);
|
||||
// This switch is derived from a table titled "Pixel data type parameter values and the
|
||||
// corresponding GL data types" in the OpenGL spec (Table 8.2 in OpenGL 4.5).
|
||||
switch (fConfigTable[config].fFormats.fExternalType) {
|
||||
case GR_GL_UNSIGNED_BYTE: return sizeof(GrGLubyte);
|
||||
case GR_GL_BYTE: return sizeof(GrGLbyte);
|
||||
case GR_GL_UNSIGNED_SHORT: return sizeof(GrGLushort);
|
||||
case GR_GL_SHORT: return sizeof(GrGLshort);
|
||||
case GR_GL_UNSIGNED_INT: return sizeof(GrGLuint);
|
||||
case GR_GL_INT: return sizeof(GrGLint);
|
||||
case GR_GL_HALF_FLOAT: return sizeof(GrGLhalf);
|
||||
case GR_GL_FLOAT: return sizeof(GrGLfloat);
|
||||
case GR_GL_UNSIGNED_SHORT_5_6_5: return sizeof(GrGLushort);
|
||||
case GR_GL_UNSIGNED_SHORT_4_4_4_4: return sizeof(GrGLushort);
|
||||
case GR_GL_UNSIGNED_SHORT_5_5_5_1: return sizeof(GrGLushort);
|
||||
case GR_GL_UNSIGNED_INT_2_10_10_10_REV: return sizeof(GrGLuint);
|
||||
#if 0 // GL types we currently don't use. Here for future reference.
|
||||
case GR_GL_UNSIGNED_BYTE_3_3_2: return sizeof(GrGLubyte);
|
||||
case GR_GL_UNSIGNED_BYTE_2_3_3_REV: return sizeof(GrGLubyte);
|
||||
case GR_GL_UNSIGNED_SHORT_5_6_5_REV: return sizeof(GrGLushort);
|
||||
case GR_GL_UNSIGNED_SHORT_4_4_4_4_REV: return sizeof(GrGLushort);
|
||||
case GR_GL_UNSIGNED_SHORT_1_5_5_5_REV: return sizeof(GrGLushort);
|
||||
case GR_GL_UNSIGNED_INT_8_8_8_8: return sizeof(GrGLuint);
|
||||
case GR_GL_UNSIGNED_INT_8_8_8_8_REV: return sizeof(GrGLuint);
|
||||
case GR_GL_UNSIGNED_INT_10_10_10_2: return sizeof(GrGLuint);
|
||||
case GR_GL_UNSIGNED_INT_24_8: return sizeof(GrGLuint);
|
||||
case GR_GL_UNSIGNED_INT_10F_11F_11F_REV: return sizeof(GrGLuint);
|
||||
case GR_GL_UNSIGNED_INT_5_9_9_9_REV: return sizeof(GrGLuint);
|
||||
case GR_GL_FLOAT_32_UNSIGNED_INT_24_8_REV: return sizeof(GrGLuint);
|
||||
#endif
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
@ -465,6 +465,7 @@ private:
|
||||
bool onSurfaceSupportsWritePixels(const GrSurface*) const override;
|
||||
bool onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
|
||||
const SkIRect& srcRect, const SkIPoint& dstPoint) const override;
|
||||
size_t onTransferFromOffsetAlignment(GrColorType bufferColorType) const override;
|
||||
|
||||
GrGLStandard fStandard;
|
||||
|
||||
|
@ -959,31 +959,14 @@ bool GrGLGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int widt
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t GrGLGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
|
||||
GrColorType dstColorType, GrGpuBuffer* transferBuffer,
|
||||
size_t offset) {
|
||||
size_t offsetAlignment;
|
||||
size_t rowBytes;
|
||||
if (!this->glCaps().transferFromBufferRequirements(dstColorType, width, &rowBytes,
|
||||
&offsetAlignment)) {
|
||||
return false;
|
||||
}
|
||||
if (offset % offsetAlignment) {
|
||||
return false;
|
||||
}
|
||||
if (offset + rowBytes * height > transferBuffer->size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GrGLGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
|
||||
GrColorType dstColorType, GrGpuBuffer* transferBuffer,
|
||||
size_t offset) {
|
||||
auto* glBuffer = static_cast<GrGLBuffer*>(transferBuffer);
|
||||
this->bindBuffer(GrGpuBufferType::kXferGpuToCpu, glBuffer);
|
||||
|
||||
auto offsetAsPtr = reinterpret_cast<void*>(offset);
|
||||
if (this->readOrTransferPixelsFrom(surface, left, top, width, height, dstColorType, offsetAsPtr,
|
||||
rowBytes)) {
|
||||
return rowBytes;
|
||||
}
|
||||
return 0;
|
||||
return this->readOrTransferPixelsFrom(surface, left, top, width, height, dstColorType,
|
||||
offsetAsPtr, width);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2363,7 +2346,7 @@ bool GrGLGpu::readPixelsSupported(GrSurface* surfaceForConfig, GrPixelConfig rea
|
||||
|
||||
bool GrGLGpu::readOrTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
|
||||
GrColorType dstColorType, void* offsetOrPtr,
|
||||
size_t rowBytes) {
|
||||
int rowWidthInPixels) {
|
||||
SkASSERT(surface);
|
||||
|
||||
GrGLRenderTarget* renderTarget = static_cast<GrGLRenderTarget*>(surface->asRenderTarget());
|
||||
@ -2413,13 +2396,10 @@ bool GrGLGpu::readOrTransferPixelsFrom(GrSurface* surface, int left, int top, in
|
||||
GrGLIRect readRect;
|
||||
readRect.setRelativeTo(glvp, left, top, width, height, kTopLeft_GrSurfaceOrigin);
|
||||
|
||||
int bytesPerPixel = GrBytesPerPixel(dstAsConfig);
|
||||
size_t tightRowBytes = bytesPerPixel * width;
|
||||
// determine if GL can read using the passed rowBytes or if we need a scratch buffer.
|
||||
if (rowBytes != tightRowBytes) {
|
||||
if (rowWidthInPixels != width) {
|
||||
SkASSERT(this->glCaps().packRowLengthSupport());
|
||||
SkASSERT(!(rowBytes % bytesPerPixel));
|
||||
GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, static_cast<GrGLint>(rowBytes / bytesPerPixel)));
|
||||
GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, rowWidthInPixels));
|
||||
}
|
||||
GL_CALL(PixelStorei(GR_GL_PACK_ALIGNMENT, config_alignment(dstAsConfig)));
|
||||
|
||||
@ -2444,7 +2424,7 @@ bool GrGLGpu::readOrTransferPixelsFrom(GrSurface* surface, int left, int top, in
|
||||
GR_GL_RENDERBUFFER, stencilAttachment->renderbufferID()));
|
||||
}
|
||||
|
||||
if (rowBytes != tightRowBytes) {
|
||||
if (rowWidthInPixels != width) {
|
||||
SkASSERT(this->glCaps().packRowLengthSupport());
|
||||
GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
|
||||
}
|
||||
@ -2459,36 +2439,37 @@ bool GrGLGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int
|
||||
GrColorType dstColorType, void* buffer, size_t rowBytes) {
|
||||
SkASSERT(surface);
|
||||
|
||||
// TODO: Avoid this conversion by making GrGLCaps work with color types.
|
||||
auto dstAsConfig = GrColorTypeToPixelConfig(dstColorType, GrSRGBEncoded::kNo);
|
||||
int bytesPerPixel = GrColorTypeBytesPerPixel(dstColorType);
|
||||
|
||||
int bytesPerPixel = GrBytesPerPixel(dstAsConfig);
|
||||
size_t tightRowBytes = bytesPerPixel * width;
|
||||
|
||||
size_t readDstRowBytes = tightRowBytes;
|
||||
// GL_PACK_ROW_LENGTH is in terms of pixels not bytes.
|
||||
int rowPixelWidth;
|
||||
void* readDst = buffer;
|
||||
|
||||
// determine if GL can read using the passed rowBytes or if we need a scratch buffer.
|
||||
SkAutoSMalloc<32 * sizeof(GrColor)> scratch;
|
||||
if (rowBytes != tightRowBytes) {
|
||||
if (!rowBytes || rowBytes == (size_t)(width * bytesPerPixel)) {
|
||||
rowPixelWidth = width;
|
||||
} else {
|
||||
if (this->glCaps().packRowLengthSupport() && !(rowBytes % bytesPerPixel)) {
|
||||
readDstRowBytes = rowBytes;
|
||||
rowPixelWidth = rowBytes / bytesPerPixel;
|
||||
} else {
|
||||
scratch.reset(tightRowBytes * height);
|
||||
scratch.reset(width * bytesPerPixel * height);
|
||||
readDst = scratch.get();
|
||||
rowPixelWidth = width;
|
||||
}
|
||||
}
|
||||
if (!this->readOrTransferPixelsFrom(surface, left, top, width, height, dstColorType, readDst,
|
||||
readDstRowBytes)) {
|
||||
rowPixelWidth)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (readDst != buffer) {
|
||||
SkASSERT(readDst != buffer);
|
||||
SkASSERT(rowBytes != tightRowBytes);
|
||||
SkASSERT(rowBytes != (size_t)(rowPixelWidth * bytesPerPixel));
|
||||
const char* src = reinterpret_cast<const char*>(readDst);
|
||||
char* dst = reinterpret_cast<char*>(buffer);
|
||||
SkRectMemcpy(dst, rowBytes, src, readDstRowBytes, tightRowBytes, height);
|
||||
SkRectMemcpy(dst, rowBytes, src, rowPixelWidth * bytesPerPixel, width * bytesPerPixel,
|
||||
height);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -239,10 +239,10 @@ private:
|
||||
|
||||
bool onTransferPixelsTo(GrTexture*, int left, int top, int width, int height, GrColorType,
|
||||
GrGpuBuffer* transferBuffer, size_t offset, size_t rowBytes) override;
|
||||
size_t onTransferPixelsFrom(GrSurface*, int left, int top, int width, int height, GrColorType,
|
||||
GrGpuBuffer* transferBuffer, size_t offset) override;
|
||||
bool onTransferPixelsFrom(GrSurface*, int left, int top, int width, int height, GrColorType,
|
||||
GrGpuBuffer* transferBuffer, size_t offset) override;
|
||||
bool readOrTransferPixelsFrom(GrSurface*, int left, int top, int width, int height, GrColorType,
|
||||
void* offsetOrPtr, size_t rowBytes);
|
||||
void* offsetOrPtr, int rowWidthInPixels);
|
||||
|
||||
// Before calling any variation of TexImage, TexSubImage, etc..., call this to ensure that the
|
||||
// PIXEL_UNPACK_BUFFER is unbound.
|
||||
|
@ -112,6 +112,10 @@ private:
|
||||
const SkIRect& srcRect, const SkIPoint& dstPoint) const override {
|
||||
return true;
|
||||
}
|
||||
size_t onTransferFromOffsetAlignment(GrColorType bufferColorType) const override {
|
||||
// arbitrary
|
||||
return GrSizeAlignUp(GrColorTypeBytesPerPixel(bufferColorType), 4);
|
||||
}
|
||||
|
||||
static const int kMaxSampleCnt = 16;
|
||||
|
||||
|
@ -96,8 +96,8 @@ private:
|
||||
size_t rowBytes) override {
|
||||
return true;
|
||||
}
|
||||
size_t onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
|
||||
GrColorType, GrGpuBuffer* transferBuffer, size_t offset) override {
|
||||
bool onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
|
||||
GrColorType, GrGpuBuffer* transferBuffer, size_t offset) override {
|
||||
return true;
|
||||
}
|
||||
bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin, GrSurface* src,
|
||||
|
@ -85,6 +85,10 @@ private:
|
||||
bool onSurfaceSupportsWritePixels(const GrSurface*) const override;
|
||||
bool onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
|
||||
const SkIRect& srcRect, const SkIPoint& dstPoint) const override;
|
||||
size_t onTransferFromOffsetAlignment(GrColorType bufferColorType) const override {
|
||||
// Transfer buffers not yet supported.
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ConfigInfo {
|
||||
ConfigInfo() : fFlags(0) {}
|
||||
|
@ -169,12 +169,10 @@ private:
|
||||
// TODO: not sure this is worth the work since nobody uses it
|
||||
return false;
|
||||
}
|
||||
size_t onTransferPixelsFrom(GrSurface*,
|
||||
int left, int top, int width, int height,
|
||||
GrColorType, GrGpuBuffer*,
|
||||
size_t offset) override {
|
||||
bool onTransferPixelsFrom(GrSurface*, int left, int top, int width, int height, GrColorType,
|
||||
GrGpuBuffer*, size_t offset) override {
|
||||
// TODO: Will need to implement this to support async read backs.
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool onRegenerateMipMapLevels(GrTexture*) override;
|
||||
|
@ -951,8 +951,7 @@ GrBackendFormat GrVkCaps::getBackendFormatFromGrColorType(GrColorType ct,
|
||||
return GrBackendFormat::MakeVk(format);
|
||||
}
|
||||
|
||||
bool GrVkCaps::onTransferFromBufferRequirements(GrColorType bufferColorType, int width,
|
||||
size_t* rowBytes, size_t* offsetAlignment) const {
|
||||
size_t GrVkCaps::onTransferFromOffsetAlignment(GrColorType bufferColorType) const {
|
||||
// This GrColorType has 32 bpp but the Vulkan pixel format we use for with may have 24bpp
|
||||
// (VK_FORMAT_R8G8B8_...) or may be 32 bpp. We don't support post transforming the pixel data
|
||||
// for transfer-from currently and don't want to have to pass info about the src surface here.
|
||||
@ -962,19 +961,11 @@ bool GrVkCaps::onTransferFromBufferRequirements(GrColorType bufferColorType, int
|
||||
size_t bpp = GrColorTypeBytesPerPixel(bufferColorType);
|
||||
// The VkBufferImageCopy bufferOffset field must be both a multiple of 4 and of a single texel.
|
||||
switch (bpp & 0b11) {
|
||||
case 0: // bpp is a multiple of 4
|
||||
*offsetAlignment = bpp;
|
||||
break;
|
||||
case 2: // bpp is a multiple of 2
|
||||
*offsetAlignment = 2 * bpp;
|
||||
break;
|
||||
case 1:
|
||||
case 3: // bpp neither a multiple of 2 nor 4.
|
||||
*offsetAlignment = 4 * bpp;
|
||||
break;
|
||||
// bpp is already a multiple of 4.
|
||||
case 0: return bpp;
|
||||
// bpp is a multiple of 2 but not 4.
|
||||
case 2: return 2 * bpp;
|
||||
// bpp is not a multiple of 2.
|
||||
default: return 4 * bpp;
|
||||
}
|
||||
// The bufferRowLength member of VkBufferImageCopy is in texel units and must be >= the extent
|
||||
// of the src VkImage region.
|
||||
*rowBytes = width * bpp;
|
||||
return true;
|
||||
}
|
||||
|
@ -199,8 +199,7 @@ private:
|
||||
bool onSurfaceSupportsWritePixels(const GrSurface*) const override;
|
||||
bool onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
|
||||
const SkIRect& srcRect, const SkIPoint& dstPoint) const override;
|
||||
bool onTransferFromBufferRequirements(GrColorType bufferColorType, int width, size_t* rowBytes,
|
||||
size_t* offsetAlignment) const override;
|
||||
size_t onTransferFromOffsetAlignment(GrColorType bufferColorType) const override;
|
||||
|
||||
struct ConfigInfo {
|
||||
ConfigInfo() : fOptimalFlags(0), fLinearFlags(0) {}
|
||||
|
@ -493,23 +493,12 @@ bool GrVkGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int widt
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t GrVkGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
|
||||
GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
|
||||
size_t offset) {
|
||||
bool GrVkGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
|
||||
GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
|
||||
size_t offset) {
|
||||
SkASSERT(surface);
|
||||
SkASSERT(transferBuffer);
|
||||
|
||||
size_t rowBytes;
|
||||
size_t offsetAlignment;
|
||||
if (!this->vkCaps().transferFromBufferRequirements(bufferColorType, width, &rowBytes,
|
||||
&offsetAlignment)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (offset % offsetAlignment || offset + height * rowBytes > transferBuffer->size()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
GrVkTransferBuffer* vkBuffer = static_cast<GrVkTransferBuffer*>(transferBuffer);
|
||||
|
||||
GrVkImage* srcImage;
|
||||
@ -541,12 +530,7 @@ size_t GrVkGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int
|
||||
VkBufferImageCopy region;
|
||||
memset(®ion, 0, sizeof(VkBufferImageCopy));
|
||||
region.bufferOffset = offset;
|
||||
// We're assuming that GrVkCaps made the row bytes tight.
|
||||
region.bufferRowLength = 0;
|
||||
#ifdef SK_DEBUG
|
||||
int bpp = GrColorTypeBytesPerPixel(bufferColorType);
|
||||
SkASSERT(rowBytes == width * (size_t)bpp);
|
||||
#endif
|
||||
region.bufferRowLength = width;
|
||||
region.bufferImageHeight = 0;
|
||||
region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
|
||||
region.imageOffset = { left, top, 0 };
|
||||
@ -572,7 +556,7 @@ size_t GrVkGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int
|
||||
// The caller is responsible for syncing.
|
||||
this->submitCommandBuffer(kSkip_SyncQueue);
|
||||
|
||||
return rowBytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrVkGpu::resolveImage(GrSurface* dst, GrVkRenderTarget* src, const SkIRect& srcRect,
|
||||
|
@ -213,8 +213,8 @@ private:
|
||||
|
||||
bool onTransferPixelsTo(GrTexture*, int left, int top, int width, int height, GrColorType,
|
||||
GrGpuBuffer* transferBuffer, size_t offset, size_t rowBytes) override;
|
||||
size_t onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
|
||||
GrColorType, GrGpuBuffer* transferBuffer, size_t offset) override;
|
||||
bool onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
|
||||
GrColorType, GrGpuBuffer* transferBuffer, size_t offset) override;
|
||||
|
||||
bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin, GrSurface* src,
|
||||
GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
|
||||
|
@ -212,21 +212,16 @@ void basic_transfer_from_test(skiatest::Reporter* reporter, const sk_gpu_test::C
|
||||
const int kPartialWidth = 10;
|
||||
const int kPartialHeight = 2;
|
||||
|
||||
size_t fullBufferRowBytes;
|
||||
size_t partialBufferRowBytes;
|
||||
size_t fullBufferOffsetAlignment;
|
||||
size_t partialBufferOffsetAlignment;
|
||||
|
||||
SkAssertResult(context->priv().caps()->transferFromBufferRequirements(
|
||||
colorType, kTextureWidth, &fullBufferRowBytes, &fullBufferOffsetAlignment));
|
||||
SkAssertResult(context->priv().caps()->transferFromBufferRequirements(
|
||||
colorType, kPartialWidth, &partialBufferRowBytes, &partialBufferOffsetAlignment));
|
||||
size_t bpp = GrColorTypeBytesPerPixel(readColorType);
|
||||
size_t fullBufferRowBytes = kTextureWidth * bpp;
|
||||
size_t partialBufferRowBytes = kPartialWidth * bpp;
|
||||
size_t offsetAlignment = context->priv().caps()->transferFromOffsetAlignment(readColorType);
|
||||
SkASSERT(offsetAlignment);
|
||||
|
||||
size_t bufferSize = fullBufferRowBytes * kTextureHeight;
|
||||
// Arbitrary starting offset for the partial read.
|
||||
size_t partialReadOffset = GrSizeAlignUp(11, partialBufferOffsetAlignment);
|
||||
bufferSize =
|
||||
SkTMax(bufferSize, partialReadOffset + partialBufferRowBytes * partialBufferRowBytes);
|
||||
size_t partialReadOffset = GrSizeAlignUp(11, offsetAlignment);
|
||||
bufferSize = SkTMax(bufferSize, partialReadOffset + partialBufferRowBytes * kPartialHeight);
|
||||
|
||||
sk_sp<GrGpuBuffer> buffer(resourceProvider->createBuffer(
|
||||
bufferSize, GrGpuBufferType::kXferGpuToCpu, kDynamic_GrAccessPattern));
|
||||
@ -269,10 +264,10 @@ void basic_transfer_from_test(skiatest::Reporter* reporter, const sk_gpu_test::C
|
||||
|
||||
//////////////////////////
|
||||
// transfer full data
|
||||
auto bufferRowBytes = gpu->transferPixelsFrom(
|
||||
tex.get(), 0, 0, kTextureWidth, kTextureHeight, readColorType, buffer.get(), 0);
|
||||
REPORTER_ASSERT(reporter, bufferRowBytes = fullBufferRowBytes);
|
||||
if (!bufferRowBytes) {
|
||||
bool result = gpu->transferPixelsFrom(tex.get(), 0, 0, kTextureWidth, kTextureHeight,
|
||||
readColorType, buffer.get(), 0);
|
||||
if (!result) {
|
||||
ERRORF(reporter, "transferPixelsFrom failed.");
|
||||
continue;
|
||||
}
|
||||
++expectedTransferCnt;
|
||||
@ -291,17 +286,17 @@ void basic_transfer_from_test(skiatest::Reporter* reporter, const sk_gpu_test::C
|
||||
kTextureWidth,
|
||||
kTextureHeight,
|
||||
textureDataRowBytes,
|
||||
bufferRowBytes,
|
||||
fullBufferRowBytes,
|
||||
readColorType != colorType));
|
||||
buffer->unmap();
|
||||
|
||||
///////////////////////
|
||||
// Now test a partial read at an offset into the buffer.
|
||||
bufferRowBytes = gpu->transferPixelsFrom(tex.get(), kPartialLeft, kPartialTop,
|
||||
kPartialWidth, kPartialHeight, readColorType,
|
||||
buffer.get(), partialReadOffset);
|
||||
REPORTER_ASSERT(reporter, bufferRowBytes = partialBufferRowBytes);
|
||||
if (!bufferRowBytes) {
|
||||
result = gpu->transferPixelsFrom(tex.get(), kPartialLeft, kPartialTop, kPartialWidth,
|
||||
kPartialHeight, readColorType, buffer.get(),
|
||||
partialReadOffset);
|
||||
if (!result) {
|
||||
ERRORF(reporter, "transferPixelsFrom failed.");
|
||||
continue;
|
||||
}
|
||||
++expectedTransferCnt;
|
||||
@ -325,7 +320,7 @@ void basic_transfer_from_test(skiatest::Reporter* reporter, const sk_gpu_test::C
|
||||
kPartialWidth,
|
||||
kPartialHeight,
|
||||
textureDataRowBytes,
|
||||
bufferRowBytes,
|
||||
partialBufferRowBytes,
|
||||
readColorType != colorType));
|
||||
buffer->unmap();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user