skia2/tests/TransferPixelsTest.cpp
Brian Salomon ae64c194fe Convert GrBufferType to enum class, rename, and remove dead values
Renamed to GrGpuBufferType in anticipation of splitting GrBuffer
into GrGpuBuffer and GrCpuBuffer types.

There were two unused values in the enum that are removed, DrawIndirect
and Texel.

Change-Id: Icb6b3da689adbd8e10495c10fd0470a6ee0120b5
Reviewed-on: https://skia-review.googlesource.com/c/189280
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
2019-02-05 15:04:48 +00:00

188 lines
7.2 KiB
C++

/*
* 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"
#include "GrContextFactory.h"
#include "GrContextPriv.h"
#include "GrGpu.h"
#include "GrResourceProvider.h"
#include "GrSurfaceProxy.h"
#include "GrTexture.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) {
GrColor* srcPtr = srcBuffer;
GrColor* dstPtr = dstBuffer;
for (int j = 0; j < height; ++j) {
for (int i = 0; i < width; ++i) {
if (srcPtr[i] != dstPtr[i]) {
return false;
}
}
srcPtr += bufferWidth;
dstPtr += bufferWidth;
}
return true;
}
void basic_transfer_test(skiatest::Reporter* reporter, GrContext* context, GrColorType colorType,
bool renderTarget) {
if (GrCaps::kNone_MapFlags == context->priv().caps()->mapBufferFlags()) {
return;
}
auto resourceProvider = context->priv().resourceProvider();
GrGpu* gpu = context->priv().getGpu();
// set up the data
const int kTextureWidth = 16;
const int kTextureHeight = 16;
#ifdef SK_BUILD_FOR_IOS
// UNPACK_ROW_LENGTH is broken on iOS so rowBytes needs to match data width
const int kBufferWidth = GrBackendApi::kOpenGL == context->backend() ? 16 : 20;
#else
const int kBufferWidth = 20;
#endif
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 = rowBytes*kBufferHeight;
auto bufferFlags = GrResourceProvider::Flags::kNoPendingIO;
sk_sp<GrBuffer> buffer(resourceProvider->createBuffer(size, GrGpuBufferType::kXferCpuToGpu,
kDynamic_GrAccessPattern, bufferFlags));
if (!buffer) {
return;
}
void* data = buffer->map();
memcpy(data, srcBuffer.get(), size);
buffer->unmap();
for (auto srgbEncoding : {GrSRGBEncoded::kNo, GrSRGBEncoded::kYes}) {
// create texture
GrSurfaceDesc desc;
desc.fFlags = renderTarget ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
desc.fWidth = kTextureWidth;
desc.fHeight = kTextureHeight;
desc.fConfig = GrColorTypeToPixelConfig(colorType, srgbEncoding);
desc.fSampleCnt = 1;
if (kUnknown_GrPixelConfig == desc.fConfig) {
SkASSERT(GrSRGBEncoded::kYes == srgbEncoding);
continue;
}
if (!context->priv().caps()->isConfigTexturable(desc.fConfig) ||
(renderTarget && !context->priv().caps()->isConfigRenderable(desc.fConfig))) {
continue;
}
sk_sp<GrTexture> tex = resourceProvider->createTexture(desc, SkBudgeted::kNo);
if (!tex) {
continue;
}
//////////////////////////
// transfer full data
bool result;
result = gpu->transferPixels(tex.get(), 0, 0, kTextureWidth, kTextureHeight, colorType,
buffer.get(), 0, rowBytes);
REPORTER_ASSERT(reporter, result);
memset(dstBuffer.get(), 0xCDCD, size);
result = gpu->readPixels(tex.get(), 0, 0, kTextureWidth, kTextureHeight, colorType,
dstBuffer.get(), rowBytes);
if (result) {
REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_values(srcBuffer,
dstBuffer,
kTextureWidth,
kTextureHeight,
kBufferWidth,
kBufferHeight));
}
//////////////////////////
// transfer partial data
#ifdef SK_BUILD_FOR_IOS
// UNPACK_ROW_LENGTH is broken on iOS so we can't do partial transfers
if (GrBackendApi::kOpenGL == context->backend()) {
continue;
}
#endif
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 = gpu->transferPixels(tex.get(), kLeft, kTop, kWidth, kHeight, colorType,
buffer.get(), offset, rowBytes);
REPORTER_ASSERT(reporter, result);
memset(dstBuffer.get(), 0xCDCD, size);
result = gpu->readPixels(tex.get(), 0, 0, kTextureWidth, kTextureHeight, colorType,
dstBuffer.get(), rowBytes);
if (result) {
REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_values(srcBuffer,
dstBuffer,
kTextureWidth,
kTextureHeight,
kBufferWidth,
kBufferHeight));
}
}
}
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(TransferPixelsTest, reporter, ctxInfo) {
// RGBA
basic_transfer_test(reporter, ctxInfo.grContext(), GrColorType::kRGBA_8888, false);
basic_transfer_test(reporter, ctxInfo.grContext(), GrColorType::kRGBA_8888, true);
// BGRA
basic_transfer_test(reporter, ctxInfo.grContext(), GrColorType::kBGRA_8888, false);
basic_transfer_test(reporter, ctxInfo.grContext(), GrColorType::kBGRA_8888, true);
}