Revert "Clean up onTransferPixels"
This reverts commit f7037d003c
.
Reason for revert: Issues on test bots.
Original change's description:
> Clean up onTransferPixels
>
> Bug: skia:5126
> Change-Id: I323c50e7854744302007b4ae7bd25e5742c14cbc
> Reviewed-on: https://skia-review.googlesource.com/19055
> Commit-Queue: Jim Van Verth <jvanverth@google.com>
> Reviewed-by: Greg Daniel <egdaniel@google.com>
TBR=egdaniel@google.com,jvanverth@google.com,bsalomon@google.com,brianosman@google.com
Change-Id: I923fda4d5cd8c2896fb347f9b2695b7f83d9137b
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:5126
Reviewed-on: https://skia-review.googlesource.com/20444
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
parent
f7037d003c
commit
ce57552e11
@ -252,7 +252,6 @@ tests_sources = [
|
||||
"$_tests/TopoSortTest.cpp",
|
||||
"$_tests/TraceMemoryDumpTest.cpp",
|
||||
"$_tests/TracingTest.cpp",
|
||||
"$_tests/TransferPixelsTest.cpp",
|
||||
"$_tests/TypefaceTest.cpp",
|
||||
"$_tests/UnicodeTest.cpp",
|
||||
"$_tests/UtilsTest.cpp",
|
||||
|
@ -389,24 +389,30 @@ bool GrGpu::writePixels(GrSurface* surface,
|
||||
return this->writePixels(surface, left, top, width, height, config, texels);
|
||||
}
|
||||
|
||||
bool GrGpu::transferPixels(GrTexture* texture,
|
||||
bool GrGpu::transferPixels(GrSurface* surface,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, GrBuffer* transferBuffer,
|
||||
size_t offset, size_t rowBytes) {
|
||||
size_t offset, size_t rowBytes, GrFence* fence) {
|
||||
SkASSERT(transferBuffer);
|
||||
SkASSERT(fence);
|
||||
|
||||
// We don't allow conversion between integer configs and float/fixed configs.
|
||||
if (GrPixelConfigIsSint(texture->config()) != GrPixelConfigIsSint(config)) {
|
||||
if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(config)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->handleDirtyContext();
|
||||
if (this->onTransferPixels(texture, left, top, width, height, config,
|
||||
if (this->onTransferPixels(surface, left, top, width, height, config,
|
||||
transferBuffer, offset, rowBytes)) {
|
||||
SkIRect rect = SkIRect::MakeXYWH(left, top, width, height);
|
||||
this->didWriteToSurface(texture, &rect);
|
||||
this->didWriteToSurface(surface, &rect);
|
||||
fStats.incTransfersToTexture();
|
||||
|
||||
if (*fence) {
|
||||
this->deleteFence(*fence);
|
||||
}
|
||||
*fence = this->insertFence();
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -291,26 +291,23 @@ public:
|
||||
size_t rowBytes);
|
||||
|
||||
/**
|
||||
* Updates the pixels in a rectangle of a texture using a buffer
|
||||
* Updates the pixels in a rectangle of a surface using a buffer
|
||||
*
|
||||
* There are a couple of assumptions here. First, we only update the top miplevel.
|
||||
* And second, that any y flip needed has already been done in the buffer.
|
||||
*
|
||||
* @param texture The texture to write to.
|
||||
* @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 config the pixel config of the source buffer
|
||||
* @param transferBuffer GrBuffer to read pixels from (type must be "kXferCpuToGpu")
|
||||
* @param transferBuffer GrBuffer to read pixels from (type must be "kCpuToGpu")
|
||||
* @param offset offset from the start of the buffer
|
||||
* @param rowBytes number of bytes between consecutive rows in the buffer. Zero
|
||||
* @param rowBytes number of bytes between consecutive rows. Zero
|
||||
* means rows are tightly packed.
|
||||
*/
|
||||
bool transferPixels(GrTexture* texture,
|
||||
bool transferPixels(GrSurface* surface,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, GrBuffer* transferBuffer,
|
||||
size_t offset, size_t rowBytes);
|
||||
size_t offset, size_t rowBytes, GrFence* fence);
|
||||
|
||||
// After the client interacts directly with the 3D context state the GrGpu
|
||||
// must resync its internal state and assumptions about 3D context state.
|
||||
@ -591,8 +588,8 @@ private:
|
||||
GrPixelConfig config,
|
||||
const SkTArray<GrMipLevel>& texels) = 0;
|
||||
|
||||
// overridden by backend-specific derived class to perform the texture transfer
|
||||
virtual bool onTransferPixels(GrTexture*,
|
||||
// overridden by backend-specific derived class to perform the surface write
|
||||
virtual bool onTransferPixels(GrSurface*,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, GrBuffer* transferBuffer,
|
||||
size_t offset, size_t rowBytes) = 0;
|
||||
|
@ -31,12 +31,6 @@
|
||||
|
||||
GrGLBuffer* GrGLBuffer::Create(GrGLGpu* gpu, size_t size, GrBufferType intendedType,
|
||||
GrAccessPattern accessPattern, const void* data) {
|
||||
if (gpu->glCaps().transferBufferType() == GrGLCaps::kNone_TransferBufferType &&
|
||||
(kXferCpuToGpu_GrBufferType == intendedType ||
|
||||
kXferGpuToCpu_GrBufferType == intendedType)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<GrGLBuffer> buffer(new GrGLBuffer(gpu, size, intendedType, accessPattern, data));
|
||||
if (0 == buffer->bufferID()) {
|
||||
return nullptr;
|
||||
|
@ -457,14 +457,10 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
|
||||
fTransferBufferType = kPBO_TransferBufferType;
|
||||
}
|
||||
} else {
|
||||
if (version >= GR_GL_VER(3, 0) ||
|
||||
(ctxInfo.hasExtension("GL_NV_pixel_buffer_object") &&
|
||||
// GL_EXT_unpack_subimage needed to support subtexture rectangles
|
||||
ctxInfo.hasExtension("GL_EXT_unpack_subimage"))) {
|
||||
if (version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_NV_pixel_buffer_object")) {
|
||||
fTransferBufferType = kPBO_TransferBufferType;
|
||||
// TODO: get transfer buffers working in Chrome
|
||||
// } else if (ctxInfo.hasExtension("GL_CHROMIUM_pixel_transfer_buffer_object")) {
|
||||
// fTransferBufferType = kChromium_TransferBufferType;
|
||||
} else if (ctxInfo.hasExtension("GL_CHROMIUM_pixel_transfer_buffer_object")) {
|
||||
fTransferBufferType = kChromium_TransferBufferType;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -783,6 +783,36 @@ bool GrGLGpu::onWritePixels(GrSurface* surface,
|
||||
left, top, width, height, config, texels);
|
||||
}
|
||||
|
||||
bool GrGLGpu::onTransferPixels(GrSurface* surface,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, GrBuffer* transferBuffer,
|
||||
size_t offset, size_t rowBytes) {
|
||||
GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture());
|
||||
|
||||
if (!check_write_and_transfer_input(glTex, surface, config)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->setScratchTextureUnit();
|
||||
GL_CALL(BindTexture(glTex->target(), glTex->textureID()));
|
||||
|
||||
SkASSERT(!transferBuffer->isMapped());
|
||||
SkASSERT(!transferBuffer->isCPUBacked());
|
||||
const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(transferBuffer);
|
||||
this->bindBuffer(kXferCpuToGpu_GrBufferType, glBuffer);
|
||||
|
||||
bool success = false;
|
||||
GrMipLevel mipLevel;
|
||||
mipLevel.fPixels = transferBuffer;
|
||||
mipLevel.fRowBytes = rowBytes;
|
||||
SkSTArray<1, GrMipLevel> texels;
|
||||
texels.push_back(mipLevel);
|
||||
success = this->uploadTexData(glTex->config(), glTex->width(), glTex->height(), glTex->origin(),
|
||||
glTex->target(), kTransfer_UploadType, left, top, width, height,
|
||||
config, texels);
|
||||
return success;
|
||||
}
|
||||
|
||||
// For GL_[UN]PACK_ALIGNMENT.
|
||||
static inline GrGLint config_alignment(GrPixelConfig config) {
|
||||
switch (config) {
|
||||
@ -809,78 +839,6 @@ static inline GrGLint config_alignment(GrPixelConfig config) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool GrGLGpu::onTransferPixels(GrTexture* texture,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, GrBuffer* transferBuffer,
|
||||
size_t offset, size_t rowBytes) {
|
||||
GrGLTexture* glTex = static_cast<GrGLTexture*>(texture);
|
||||
GrPixelConfig texConfig = glTex->config();
|
||||
SkASSERT(this->caps()->isConfigTexturable(texConfig));
|
||||
|
||||
if (!check_write_and_transfer_input(glTex, texture, config)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (width <= 0 || width > SK_MaxS32 || height <= 0 || height > SK_MaxS32) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->setScratchTextureUnit();
|
||||
GL_CALL(BindTexture(glTex->target(), glTex->textureID()));
|
||||
|
||||
SkASSERT(!transferBuffer->isMapped());
|
||||
SkASSERT(!transferBuffer->isCPUBacked());
|
||||
const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(transferBuffer);
|
||||
this->bindBuffer(kXferCpuToGpu_GrBufferType, glBuffer);
|
||||
|
||||
size_t bpp = GrBytesPerPixel(config);
|
||||
const size_t trimRowBytes = width * bpp;
|
||||
const void* pixels = (void*)offset;
|
||||
if (!GrSurfacePriv::AdjustWritePixelParams(glTex->width(), glTex->height(), bpp,
|
||||
&left, &top,
|
||||
&width, &height,
|
||||
&pixels,
|
||||
&rowBytes)) {
|
||||
return false;
|
||||
}
|
||||
if (width < 0 || width < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool restoreGLRowLength = false;
|
||||
if (trimRowBytes != rowBytes) {
|
||||
// we should have checked for this support already
|
||||
SkASSERT(this->glCaps().unpackRowLengthSupport());
|
||||
GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowBytes / bpp));
|
||||
restoreGLRowLength = true;
|
||||
}
|
||||
|
||||
// Internal format comes from the texture desc.
|
||||
GrGLenum internalFormat;
|
||||
// External format and type come from the upload data.
|
||||
GrGLenum externalFormat;
|
||||
GrGLenum externalType;
|
||||
if (!this->glCaps().getTexImageFormats(texConfig, config, &internalFormat,
|
||||
&externalFormat, &externalType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, config_alignment(texConfig)));
|
||||
GL_CALL(TexSubImage2D(glTex->target(),
|
||||
0,
|
||||
left, top,
|
||||
width,
|
||||
height,
|
||||
externalFormat, externalType,
|
||||
pixels));
|
||||
|
||||
if (restoreGLRowLength) {
|
||||
GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates storage space for the texture and fills it with texels.
|
||||
*
|
||||
@ -1013,13 +971,6 @@ bool GrGLGpu::uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight
|
||||
const SkTArray<GrMipLevel>& texels) {
|
||||
SkASSERT(this->caps()->isConfigTexturable(texConfig));
|
||||
|
||||
// unbind any previous transfer buffer
|
||||
auto& xferBufferState = fHWBufferState[kXferCpuToGpu_GrBufferType];
|
||||
if (!xferBufferState.fBoundBufferUniqueID.isInvalid()) {
|
||||
GL_CALL(BindBuffer(xferBufferState.fGLTarget, 0));
|
||||
xferBufferState.invalidate();
|
||||
}
|
||||
|
||||
// texels is const.
|
||||
// But we may need to flip the texture vertically to prepare it.
|
||||
// Rather than flip in place and alter the incoming data,
|
||||
@ -1029,7 +980,7 @@ bool GrGLGpu::uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight
|
||||
|
||||
for (int currentMipLevel = texelsShallowCopy.count() - 1; currentMipLevel >= 0;
|
||||
currentMipLevel--) {
|
||||
SkASSERT(texelsShallowCopy[currentMipLevel].fPixels);
|
||||
SkASSERT(texelsShallowCopy[currentMipLevel].fPixels || kTransfer_UploadType == uploadType);
|
||||
}
|
||||
|
||||
const GrGLInterface* interface = this->glInterface();
|
||||
@ -1135,26 +1086,30 @@ bool GrGLGpu::uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight
|
||||
GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
|
||||
restoreGLRowLength = true;
|
||||
}
|
||||
} else if (trimRowBytes != rowBytes || swFlipY) {
|
||||
// copy data into our new storage, skipping the trailing bytes
|
||||
const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels;
|
||||
if (swFlipY && currentHeight >= 1) {
|
||||
src += (currentHeight - 1) * rowBytes;
|
||||
}
|
||||
char* dst = buffer + individual_mip_offsets[currentMipLevel];
|
||||
for (int y = 0; y < currentHeight; y++) {
|
||||
memcpy(dst, src, trimRowBytes);
|
||||
if (swFlipY) {
|
||||
src -= rowBytes;
|
||||
} else {
|
||||
src += rowBytes;
|
||||
} else if (kTransfer_UploadType != uploadType) {
|
||||
if (trimRowBytes != rowBytes || swFlipY) {
|
||||
// copy data into our new storage, skipping the trailing bytes
|
||||
const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels;
|
||||
if (swFlipY && currentHeight >= 1) {
|
||||
src += (currentHeight - 1) * rowBytes;
|
||||
}
|
||||
dst += trimRowBytes;
|
||||
char* dst = buffer + individual_mip_offsets[currentMipLevel];
|
||||
for (int y = 0; y < currentHeight; y++) {
|
||||
memcpy(dst, src, trimRowBytes);
|
||||
if (swFlipY) {
|
||||
src -= rowBytes;
|
||||
} else {
|
||||
src += rowBytes;
|
||||
}
|
||||
dst += trimRowBytes;
|
||||
}
|
||||
// now point data to our copied version
|
||||
texelsShallowCopy[currentMipLevel].fPixels = buffer +
|
||||
individual_mip_offsets[currentMipLevel];
|
||||
texelsShallowCopy[currentMipLevel].fRowBytes = trimRowBytes;
|
||||
}
|
||||
// now point data to our copied version
|
||||
texelsShallowCopy[currentMipLevel].fPixels = buffer +
|
||||
individual_mip_offsets[currentMipLevel];
|
||||
texelsShallowCopy[currentMipLevel].fRowBytes = trimRowBytes;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,7 +247,7 @@ private:
|
||||
GrPixelConfig config,
|
||||
const SkTArray<GrMipLevel>& texels) override;
|
||||
|
||||
bool onTransferPixels(GrTexture*,
|
||||
bool onTransferPixels(GrSurface*,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, GrBuffer* transferBuffer,
|
||||
size_t offset, size_t rowBytes) override;
|
||||
@ -373,8 +373,9 @@ private:
|
||||
|
||||
// helper for onCreateTexture and writeTexturePixels
|
||||
enum UploadType {
|
||||
kNewTexture_UploadType, // we are creating a new texture
|
||||
kWrite_UploadType, // we are using TexSubImage2D to copy data to an existing texture
|
||||
kNewTexture_UploadType, // we are creating a new texture
|
||||
kWrite_UploadType, // we are using TexSubImage2D to copy data to an existing texture
|
||||
kTransfer_UploadType, // we are using a transfer buffer to copy data
|
||||
};
|
||||
bool uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight,
|
||||
GrSurfaceOrigin texOrigin, GrGLenum target, UploadType uploadType, int left,
|
||||
|
@ -301,13 +301,11 @@ GrBuffer* GrVkGpu::onCreateBuffer(size_t size, GrBufferType type, GrAccessPatter
|
||||
buff = GrVkIndexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern);
|
||||
break;
|
||||
case kXferCpuToGpu_GrBufferType:
|
||||
SkASSERT(kDynamic_GrAccessPattern == accessPattern ||
|
||||
kStream_GrAccessPattern == accessPattern);
|
||||
SkASSERT(kStream_GrAccessPattern == accessPattern);
|
||||
buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyRead_Type);
|
||||
break;
|
||||
case kXferGpuToCpu_GrBufferType:
|
||||
SkASSERT(kDynamic_GrAccessPattern == accessPattern ||
|
||||
kStream_GrAccessPattern == accessPattern);
|
||||
SkASSERT(kStream_GrAccessPattern == accessPattern);
|
||||
buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyWrite_Type);
|
||||
break;
|
||||
case kTexel_GrBufferType:
|
||||
@ -422,62 +420,6 @@ bool GrVkGpu::onWritePixels(GrSurface* surface,
|
||||
return success;
|
||||
}
|
||||
|
||||
bool GrVkGpu::onTransferPixels(GrTexture* texture,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, GrBuffer* transferBuffer,
|
||||
size_t bufferOffset, size_t rowBytes) {
|
||||
// Vulkan only supports 4-byte aligned offsets
|
||||
if (SkToBool(bufferOffset & 0x2)) {
|
||||
return false;
|
||||
}
|
||||
GrVkTexture* vkTex = static_cast<GrVkTexture*>(texture);
|
||||
if (!vkTex) {
|
||||
return false;
|
||||
}
|
||||
GrVkTransferBuffer* vkBuffer = static_cast<GrVkTransferBuffer*>(transferBuffer);
|
||||
if (!vkBuffer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We assume Vulkan doesn't do sRGB <-> linear conversions when reading and writing pixels.
|
||||
if (GrPixelConfigIsSRGB(texture->config()) != GrPixelConfigIsSRGB(config)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t bpp = GrBytesPerPixel(config);
|
||||
if (rowBytes == 0) {
|
||||
rowBytes = bpp*width;
|
||||
}
|
||||
|
||||
// Set up copy region
|
||||
VkBufferImageCopy region;
|
||||
memset(®ion, 0, sizeof(VkBufferImageCopy));
|
||||
region.bufferOffset = bufferOffset;
|
||||
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 };
|
||||
|
||||
// Change layout of our target so it can be copied to
|
||||
vkTex->setImageLayout(this,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
false);
|
||||
|
||||
// Copy the buffer to the image
|
||||
fCurrentCmdBuffer->copyBufferToImage(this,
|
||||
vkBuffer,
|
||||
vkTex,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1,
|
||||
®ion);
|
||||
|
||||
vkTex->texturePriv().dirtyMipMaps(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrVkGpu::resolveImage(GrSurface* dst, GrVkRenderTarget* src, const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
SkASSERT(dst);
|
||||
|
@ -203,10 +203,10 @@ private:
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, const SkTArray<GrMipLevel>&) override;
|
||||
|
||||
bool onTransferPixels(GrTexture*,
|
||||
bool onTransferPixels(GrSurface*,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, GrBuffer* transferBuffer,
|
||||
size_t offset, size_t rowBytes) override;
|
||||
size_t offset, size_t rowBytes) override { return false; }
|
||||
|
||||
// Ends and submits the current command buffer to the queue and then creates a new command
|
||||
// buffer and begins it. If sync is set to kForce_SyncQueue, the function will wait for all
|
||||
|
@ -1,173 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
// This is a GPU-backend specific test. It relies on static intializers to work
|
||||
|
||||
#include "SkTypes.h"
|
||||
|
||||
#if SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
|
||||
|
||||
#include "GrContextFactory.h"
|
||||
#include "GrContextPriv.h"
|
||||
#include "GrGpu.h"
|
||||
#include "GrResourceProvider.h"
|
||||
#include "GrSurfaceProxy.h"
|
||||
#include "GrTexture.h"
|
||||
#include "GrTest.h"
|
||||
#include "SkGr.h"
|
||||
#include "SkSurface.h"
|
||||
#include "Test.h"
|
||||
|
||||
using sk_gpu_test::GrContextFactory;
|
||||
|
||||
void fill_transfer_data(int left, int top, int width, int height, int bufferWidth,
|
||||
GrColor* data) {
|
||||
|
||||
// build red-green gradient
|
||||
for (int j = top; j < top + height; ++j) {
|
||||
for (int i = left; i < left + width; ++i) {
|
||||
unsigned int red = (unsigned int)(256.f*((i - left) / (float)width));
|
||||
unsigned int green = (unsigned int)(256.f*((j - top) / (float)height));
|
||||
data[i + j*bufferWidth] = GrColorPackRGBA(red - (red>>8),
|
||||
green - (green>>8), 0xff, 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool does_full_buffer_contain_correct_values(GrColor* srcBuffer,
|
||||
GrColor* dstBuffer,
|
||||
int width,
|
||||
int height,
|
||||
int bufferWidth,
|
||||
int bufferHeight,
|
||||
GrSurfaceOrigin origin) {
|
||||
GrColor* srcPtr = srcBuffer;
|
||||
bool bottomUp = SkToBool(kBottomLeft_GrSurfaceOrigin == origin);
|
||||
GrColor* dstPtr = bottomUp ? dstBuffer + bufferWidth*(bufferHeight-1) : dstBuffer;
|
||||
int dstIncrement = bottomUp ? -bufferWidth : +bufferWidth;
|
||||
|
||||
for (int j = 0; j < height; ++j) {
|
||||
for (int i = 0; i < width; ++i) {
|
||||
if (srcPtr[i] != dstPtr[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
srcPtr += bufferWidth;
|
||||
dstPtr += dstIncrement;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void basic_transfer_test(skiatest::Reporter* reporter, GrContext* context, GrPixelConfig config,
|
||||
GrSurfaceOrigin origin, bool renderTarget) {
|
||||
// set up the data
|
||||
const int kTextureWidth = 16;
|
||||
const int kTextureHeight = 16;
|
||||
const int kBufferWidth = 20;
|
||||
const int kBufferHeight = 16;
|
||||
size_t rowBytes = kBufferWidth * sizeof(GrColor);
|
||||
SkAutoTMalloc<GrColor> srcBuffer(kBufferWidth*kBufferHeight);
|
||||
SkAutoTMalloc<GrColor> dstBuffer(kBufferWidth*kBufferHeight);
|
||||
|
||||
fill_transfer_data(0, 0, kTextureWidth, kTextureHeight, kBufferWidth, srcBuffer.get());
|
||||
|
||||
// create and fill transfer buffer
|
||||
size_t size = GrBytesPerPixel(config)*kBufferWidth*kBufferWidth;
|
||||
uint32_t bufferFlags = GrResourceProvider::kNoPendingIO_Flag;
|
||||
GrBuffer* buffer = context->resourceProvider()->createBuffer(size,
|
||||
kXferCpuToGpu_GrBufferType,
|
||||
kDynamic_GrAccessPattern,
|
||||
bufferFlags);
|
||||
void* data = buffer->map();
|
||||
memcpy(data, srcBuffer.get(), size);
|
||||
buffer->unmap();
|
||||
|
||||
// create texture
|
||||
GrSurfaceDesc desc;
|
||||
desc.fConfig = config;
|
||||
desc.fFlags = renderTarget ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
|
||||
desc.fOrigin = origin;
|
||||
desc.fWidth = kTextureWidth;
|
||||
desc.fHeight = kTextureHeight;
|
||||
desc.fSampleCnt = 0;
|
||||
sk_sp<GrTexture> tex = context->resourceProvider()->createTexture(desc, SkBudgeted::kNo);
|
||||
|
||||
//////////////////////////
|
||||
// transfer full data
|
||||
|
||||
bool result;
|
||||
result = context->getGpu()->transferPixels(tex.get(), 0, 0, kTextureWidth, kTextureHeight,
|
||||
config, buffer, 0, rowBytes);
|
||||
REPORTER_ASSERT(reporter, result);
|
||||
|
||||
result = context->getGpu()->readPixels(tex.get(), 0, 0, kTextureWidth, kTextureHeight, config,
|
||||
dstBuffer.get(), rowBytes);
|
||||
REPORTER_ASSERT(reporter, result);
|
||||
REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_values(srcBuffer,
|
||||
dstBuffer,
|
||||
kTextureWidth,
|
||||
kTextureHeight,
|
||||
kBufferWidth,
|
||||
kBufferHeight,
|
||||
origin));
|
||||
//////////////////////////
|
||||
// transfer partial data
|
||||
|
||||
const int kLeft = 2;
|
||||
const int kTop = 10;
|
||||
const int kWidth = 10;
|
||||
const int kHeight = 2;
|
||||
|
||||
// change color of subrectangle
|
||||
fill_transfer_data(kLeft, kTop, kWidth, kHeight, kBufferWidth, srcBuffer.get());
|
||||
data = buffer->map();
|
||||
memcpy(data, srcBuffer.get(), size);
|
||||
buffer->unmap();
|
||||
|
||||
size_t offset = sizeof(GrColor)*(kTop*kBufferWidth + kLeft);
|
||||
result = context->getGpu()->transferPixels(tex.get(), kLeft, kTop, kWidth, kHeight, config,
|
||||
buffer, offset, rowBytes);
|
||||
REPORTER_ASSERT(reporter, result);
|
||||
|
||||
memset(dstBuffer, 0, kWidth*kHeight*sizeof(GrColor));
|
||||
|
||||
result = context->getGpu()->readPixels(tex.get(), 0, 0, kTextureWidth, kTextureHeight, config,
|
||||
dstBuffer.get(), rowBytes);
|
||||
REPORTER_ASSERT(reporter, result);
|
||||
|
||||
REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_values(srcBuffer,
|
||||
dstBuffer,
|
||||
kTextureWidth,
|
||||
kTextureHeight,
|
||||
kBufferWidth,
|
||||
kBufferHeight,
|
||||
origin));
|
||||
}
|
||||
|
||||
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(TransferPixelsTest, reporter, ctxInfo) {
|
||||
// RGBA
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), kRGBA_8888_GrPixelConfig,
|
||||
kTopLeft_GrSurfaceOrigin, false);
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), kRGBA_8888_GrPixelConfig,
|
||||
kTopLeft_GrSurfaceOrigin, true);
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), kRGBA_8888_GrPixelConfig,
|
||||
kBottomLeft_GrSurfaceOrigin, false);
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), kRGBA_8888_GrPixelConfig,
|
||||
kBottomLeft_GrSurfaceOrigin, true);
|
||||
|
||||
// BGRA
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), kBGRA_8888_GrPixelConfig,
|
||||
kTopLeft_GrSurfaceOrigin, false);
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), kBGRA_8888_GrPixelConfig,
|
||||
kTopLeft_GrSurfaceOrigin, true);
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), kBGRA_8888_GrPixelConfig,
|
||||
kBottomLeft_GrSurfaceOrigin, false);
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), kBGRA_8888_GrPixelConfig,
|
||||
kBottomLeft_GrSurfaceOrigin, true);
|
||||
}
|
||||
|
||||
#endif
|
@ -402,7 +402,7 @@ private:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool onTransferPixels(GrTexture* texture,
|
||||
bool onTransferPixels(GrSurface* surface,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, GrBuffer* transferBuffer,
|
||||
size_t offset, size_t rowBytes) override {
|
||||
|
Loading…
Reference in New Issue
Block a user