skia2/tests/CompressedBackendAllocationTest.cpp
Robert Phillips 8f259a0329 Add BC1_RGB8_UNORM support
This is working in the GL and Vulkan back ends. MacOS only supports the RGBA8 variants.
For mobile devices, probably only nVidia GPUs will support this.

Bug: skia:9680
Change-Id: I9d886b72232a031603e93e46059a97a8aa288b3c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/261093
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
2019-12-20 21:41:09 +00:00

237 lines
9.5 KiB
C++

/*
* Copyright 2019 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/gpu/GrContext.h"
#include "src/core/SkAutoPixmapStorage.h"
#include "src/core/SkMipMap.h"
#include "src/gpu/GrContextPriv.h"
#include "src/image/SkImage_Base.h"
#include "tests/Test.h"
#include "tests/TestUtils.h"
#include "tools/ToolUtils.h"
static void check_solid_pixmap(skiatest::Reporter* reporter,
const SkColor4f& expected, const SkPixmap& actual,
const char* label0, const char* label1, const char* label2) {
const float tols[4] = { 0.01f, 0.01f, 0.01f, 0.01f };
auto error = std::function<ComparePixmapsErrorReporter>(
[reporter, label0, label1, label2](int x, int y, const float diffs[4]) {
SkASSERT(x >= 0 && y >= 0);
ERRORF(reporter, "%s %s %s - mismatch at %d, %d (%f, %f, %f %f)",
label0, label1, label2, x, y,
diffs[0], diffs[1], diffs[2], diffs[3]);
});
CheckSolidPixels(expected, actual, tols, error);
}
// Draw the compressed backend texture (wrapped in an SkImage) into an RGBA surface, attempting
// to access all the mipMap levels.
static void check_compressed_mipmaps(GrContext* context, const GrBackendTexture& backendTex,
const SkColor4f expectedColors[6],
GrMipMapped mipMapped,
skiatest::Reporter* reporter, const char* label) {
const GrCaps* caps = context->priv().caps();
SkImage::CompressionType compression = caps->compressionType(backendTex.getBackendFormat());
SkAlphaType at = kOpaque_SkAlphaType;
sk_sp<SkImage> img = SkImage::MakeFromCompressedTexture(context,
backendTex,
kTopLeft_GrSurfaceOrigin,
at,
nullptr);
if (!img) {
return;
}
SkImageInfo readbackSurfaceII = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType,
kPremul_SkAlphaType);
sk_sp<SkSurface> surf = SkSurface::MakeRenderTarget(context,
SkBudgeted::kNo,
readbackSurfaceII, 1,
kTopLeft_GrSurfaceOrigin,
nullptr);
if (!surf) {
return;
}
SkCanvas* canvas = surf->getCanvas();
SkPaint p;
p.setFilterQuality(kHigh_SkFilterQuality);
int numMipLevels = 1;
if (mipMapped == GrMipMapped::kYes) {
numMipLevels = SkMipMap::ComputeLevelCount(32, 32)+1;
}
for (int i = 0, rectSize = 32; i < numMipLevels; ++i, rectSize /= 2) {
SkASSERT(rectSize >= 1);
canvas->clear(SK_ColorTRANSPARENT);
SkRect r = SkRect::MakeWH(rectSize, rectSize);
canvas->drawImageRect(img, r, &p);
SkImageInfo readbackII = SkImageInfo::Make(rectSize, rectSize,
kRGBA_8888_SkColorType,
kUnpremul_SkAlphaType);
SkAutoPixmapStorage actual2;
SkAssertResult(actual2.tryAlloc(readbackII));
actual2.erase(SkColors::kTransparent);
bool result = surf->readPixels(actual2, 0, 0);
REPORTER_ASSERT(reporter, result);
SkString str;
str.appendf("mip-level %d", i);
check_solid_pixmap(reporter, expectedColors[i], actual2,
GrCompressionTypeToStr(compression), label, str.c_str());
}
}
// Test initialization of GrBackendObjects to a specific color
static void test_compressed_color_init(GrContext* context, skiatest::Reporter* reporter,
std::function<GrBackendTexture (GrContext*,
const SkColor4f&,
GrMipMapped)> create,
const SkColor4f& color, GrMipMapped mipMapped) {
GrBackendTexture backendTex = create(context, color, mipMapped);
if (!backendTex.isValid()) {
// errors here should be reported by the test_wrapping test
return;
}
SkColor4f expectedColors[6] = { color, color, color, color, color, color };
check_compressed_mipmaps(context, backendTex, expectedColors, mipMapped, reporter, "colorinit");
context->deleteBackendTexture(backendTex);
}
static std::unique_ptr<const char[]> make_compressed_data(SkImage::CompressionType compression,
SkColor4f levelColors[6],
GrMipMapped mipMapped) {
SkISize dimensions { 32, 32 };
int numMipLevels = 1;
if (mipMapped == GrMipMapped::kYes) {
numMipLevels = SkMipMap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
}
SkTArray<size_t> mipMapOffsets(numMipLevels);
size_t dataSize = GrCompressedDataSize(compression, dimensions, &mipMapOffsets, mipMapped);
char* data = new char[dataSize];
for (int level = 0; level < numMipLevels; ++level) {
// We have to do this a level at a time bc we might have a different color for
// each level
GrFillInCompressedData(compression, dimensions,
GrMipMapped::kNo, &data[mipMapOffsets[level]], levelColors[level]);
dimensions = {SkTMax(1, dimensions.width() /2), SkTMax(1, dimensions.height()/2)};
}
return std::unique_ptr<const char[]>(data);
}
static void test_compressed_data_init(GrContext* context,
skiatest::Reporter* reporter,
std::function<GrBackendTexture (GrContext*,
const char* data,
size_t dataSize,
GrMipMapped)> create,
SkImage::CompressionType compression,
GrMipMapped mipMapped) {
// TODO: make these transparent for RGBA compressed formats
SkColor4f expectedColors[6] = {
{ 1.0f, 0.0f, 0.0f, 1.0f }, // R
{ 0.0f, 1.0f, 0.0f, 1.0f }, // G
{ 0.0f, 0.0f, 1.0f, 1.0f }, // B
{ 0.0f, 1.0f, 1.0f, 1.0f }, // C
{ 1.0f, 0.0f, 1.0f, 1.0f }, // M
{ 1.0f, 1.0f, 0.0f, 1.0f }, // Y
};
std::unique_ptr<const char[]> data(make_compressed_data(compression, expectedColors,
mipMapped));
size_t dataSize = GrCompressedDataSize(compression, { 32, 32 }, nullptr, mipMapped);
GrBackendTexture backendTex = create(context, data.get(), dataSize, mipMapped);
if (!backendTex.isValid()) {
return;
}
check_compressed_mipmaps(context, backendTex, expectedColors, mipMapped, reporter, "pixmap");
context->deleteBackendTexture(backendTex);
}
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(CompressedBackendAllocationTest, reporter, ctxInfo) {
GrContext* context = ctxInfo.grContext();
const GrCaps* caps = context->priv().caps();
struct {
SkImage::CompressionType fCompression;
SkColor4f fColor;
} combinations[] = {
{ SkImage::CompressionType::kETC1, SkColors::kRed },
{ SkImage::CompressionType::kBC1_RGB8_UNORM, SkColors::kBlue },
};
for (auto combo : combinations) {
GrBackendFormat format = context->compressedBackendFormat(combo.fCompression);
if (!format.isValid()) {
continue;
}
if (!caps->isFormatTexturable(format)) {
continue;
}
for (auto mipMapped : { GrMipMapped::kNo, GrMipMapped::kYes }) {
if (GrMipMapped::kYes == mipMapped && !caps->mipMapSupport()) {
continue;
}
// color initialized
{
auto createWithColorMtd = [format](GrContext* context,
const SkColor4f& color,
GrMipMapped mipMapped) {
return context->createCompressedBackendTexture(32, 32, format, color,
mipMapped, GrProtected::kNo);
};
test_compressed_color_init(context, reporter, createWithColorMtd,
combo.fColor, mipMapped);
}
// data initialized
{
auto createWithDataMtd = [format](GrContext* context,
const char* data, size_t dataSize,
GrMipMapped mipMapped) {
return context->createCompressedBackendTexture(32, 32, format, data, dataSize,
mipMapped, GrProtected::kNo);
};
test_compressed_data_init(context, reporter, createWithDataMtd,
combo.fCompression, mipMapped);
}
}
}
}