224 lines
8.5 KiB
C++
224 lines
8.5 KiB
C++
/*
|
|
* Copyright 2022 Google LLC
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "tests/Test.h"
|
|
|
|
#include "include/core/SkColorSpace.h"
|
|
#include "include/gpu/graphite/BackendTexture.h"
|
|
#include "include/gpu/graphite/Context.h"
|
|
#include "include/gpu/graphite/Recorder.h"
|
|
#include "src/core/SkAutoPixmapStorage.h"
|
|
#include "src/gpu/graphite/Caps.h"
|
|
#include "src/gpu/graphite/ContextPriv.h"
|
|
#include "src/gpu/graphite/Surface_Graphite.h"
|
|
#include "tests/TestUtils.h"
|
|
#include "tools/ToolUtils.h"
|
|
|
|
using namespace skgpu;
|
|
using namespace skgpu::graphite;
|
|
|
|
namespace {
|
|
const SkISize kSize = { 32, 32 };
|
|
constexpr int kNumMipLevels = 6;
|
|
|
|
void check_solid_pixmap(skiatest::Reporter* reporter,
|
|
const SkColor4f& expected,
|
|
const SkPixmap& actual,
|
|
SkColorType ct,
|
|
const char* label) {
|
|
const float kTols[4] = { 0.01f, 0.01f, 0.01f, 0.01f };
|
|
|
|
auto error = std::function<ComparePixmapsErrorReporter>(
|
|
[reporter, ct, label, expected](int x, int y, const float diffs[4]) {
|
|
SkASSERT(x >= 0 && y >= 0);
|
|
ERRORF(reporter, "%s %s - mismatch at %d, %d "
|
|
"expected: (%.2f, %.2f, %.2f, %.2f) "
|
|
"- diffs: (%.2f, %.2f, %.2f, %.2f)",
|
|
ToolUtils::colortype_name(ct), label, x, y,
|
|
expected.fR, expected.fG, expected.fB, expected.fA,
|
|
diffs[0], diffs[1], diffs[2], diffs[3]);
|
|
});
|
|
|
|
CheckSolidPixels(expected, actual, kTols, error);
|
|
}
|
|
|
|
void update_backend_texture(Recorder* recorder,
|
|
const BackendTexture& backendTex,
|
|
SkColorType ct,
|
|
bool withMips,
|
|
const SkColor4f colors[6]) {
|
|
SkPixmap pixmaps[6];
|
|
std::unique_ptr<char[]> memForPixmaps;
|
|
|
|
int numMipLevels = ToolUtils::make_pixmaps(ct, kPremul_SkAlphaType, withMips, colors, pixmaps,
|
|
&memForPixmaps);
|
|
SkASSERT(numMipLevels == 1 || numMipLevels == kNumMipLevels);
|
|
SkASSERT(kSize == pixmaps[0].dimensions());
|
|
|
|
recorder->updateBackendTexture(backendTex, pixmaps, numMipLevels);
|
|
|
|
}
|
|
|
|
BackendTexture create_backend_texture(skiatest::Reporter* reporter,
|
|
const Caps* caps,
|
|
Recorder* recorder,
|
|
SkColorType ct,
|
|
bool withMips,
|
|
Renderable renderable,
|
|
const SkColor4f colors[6]) {
|
|
Mipmapped mipmapped = withMips ? Mipmapped::kYes : Mipmapped::kNo;
|
|
TextureInfo info = caps->getDefaultSampledTextureInfo(ct,
|
|
mipmapped,
|
|
Protected::kNo,
|
|
renderable);
|
|
|
|
BackendTexture backendTex = recorder->createBackendTexture(kSize, info);
|
|
REPORTER_ASSERT(reporter, backendTex.isValid());
|
|
|
|
update_backend_texture(recorder, backendTex, ct, withMips, colors);
|
|
|
|
return backendTex;
|
|
}
|
|
|
|
sk_sp<SkImage> wrap_backend_texture(skiatest::Reporter* reporter,
|
|
Recorder* recorder,
|
|
const skgpu::graphite::BackendTexture& backendTex,
|
|
SkColorType ct,
|
|
bool withMips) {
|
|
sk_sp<SkImage> image = SkImage::MakeGraphiteFromBackendTexture(recorder,
|
|
backendTex,
|
|
ct,
|
|
kPremul_SkAlphaType,
|
|
/* colorSpace= */ nullptr);
|
|
REPORTER_ASSERT(reporter, image);
|
|
REPORTER_ASSERT(reporter, image->hasMipmaps() == withMips);
|
|
|
|
return image;
|
|
}
|
|
|
|
void check_levels(skiatest::Reporter* reporter,
|
|
Context* context,
|
|
Recorder* recorder,
|
|
SkImage* image,
|
|
bool withMips,
|
|
const SkColor4f colors[6]) {
|
|
int numLevels = withMips ? kNumMipLevels : 1;
|
|
|
|
SkSamplingOptions sampling = withMips
|
|
? SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNearest)
|
|
: SkSamplingOptions(SkFilterMode::kNearest);
|
|
|
|
SkImageInfo surfaceII = SkImageInfo::Make(kSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
|
|
sk_sp<SkSurface> surf = SkSurface::MakeGraphite(recorder, surfaceII, Mipmapped::kNo);
|
|
SkCanvas* canvas = surf->getCanvas();
|
|
|
|
for (int i = 0, drawSize = kSize.width(); i < numLevels; ++i, drawSize /= 2) {
|
|
if (i == 5) {
|
|
// TODO: Metal currently never draws the top-most mip-level (skbug.com/13792)
|
|
continue;
|
|
}
|
|
|
|
SkImageInfo readbackII = SkImageInfo::Make({drawSize, drawSize}, kRGBA_8888_SkColorType,
|
|
kUnpremul_SkAlphaType);
|
|
SkAutoPixmapStorage actual;
|
|
SkAssertResult(actual.tryAlloc(readbackII));
|
|
actual.erase(SkColors::kTransparent);
|
|
|
|
SkPaint paint;
|
|
paint.setBlendMode(SkBlendMode::kSrc);
|
|
|
|
canvas->clear(SkColors::kTransparent);
|
|
|
|
#if 0
|
|
// This option gives greater control over the tilemodes and texture scaling
|
|
SkMatrix lm;
|
|
lm.setScale(1.0f / (1 << i), 1.0f / (1 << i));
|
|
|
|
paint.setShader(image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, sampling, lm));
|
|
canvas->drawRect(SkRect::MakeWH(drawSize, drawSize), paint);
|
|
#else
|
|
canvas->drawImageRect(image, SkRect::MakeWH(drawSize, drawSize), sampling, &paint);
|
|
#endif
|
|
|
|
if (!surf->readPixels(actual, 0, 0)) {
|
|
ERRORF(reporter, "readPixels failed");
|
|
return;
|
|
}
|
|
|
|
SkString str;
|
|
str.appendf("mip-level %d", i);
|
|
|
|
check_solid_pixmap(reporter, colors[i], actual, image->colorType(), str.c_str());
|
|
}
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(UpdateImageBackendTextureTest, reporter, context) {
|
|
// TODO: Remove this check once Vulkan supports creating default TexutreInfo from caps and we
|
|
// implement createBackendTexture.
|
|
if (context->backend() == BackendApi::kVulkan) {
|
|
return;
|
|
}
|
|
|
|
const Caps* caps = context->priv().caps();
|
|
std::unique_ptr<Recorder> recorder = context->makeRecorder();
|
|
|
|
constexpr SkColor4f kColors[6] = {
|
|
{ 1.0f, 0.0f, 0.0f, 1.0f }, // R
|
|
{ 0.0f, 1.0f, 0.0f, 0.9f }, // G
|
|
{ 0.0f, 0.0f, 1.0f, 0.7f }, // B
|
|
{ 0.0f, 1.0f, 1.0f, 0.5f }, // C
|
|
{ 1.0f, 0.0f, 1.0f, 0.3f }, // M
|
|
{ 1.0f, 1.0f, 0.0f, 0.2f }, // Y
|
|
};
|
|
|
|
constexpr SkColor4f kColorsNew[6] = {
|
|
{ 1.0f, 1.0f, 0.0f, 0.2f }, // Y
|
|
{ 1.0f, 0.0f, 0.0f, 1.0f }, // R
|
|
{ 0.0f, 1.0f, 0.0f, 0.9f }, // G
|
|
{ 0.0f, 0.0f, 1.0f, 0.7f }, // B
|
|
{ 0.0f, 1.0f, 1.0f, 0.5f }, // C
|
|
{ 1.0f, 0.0f, 1.0f, 0.3f }, // M
|
|
};
|
|
|
|
// TODO: test more than just RGBA8
|
|
for (SkColorType ct : { kRGBA_8888_SkColorType }) {
|
|
for (bool withMips : { true, false }) {
|
|
for (Renderable renderable : { Renderable::kYes, Renderable::kNo }) {
|
|
|
|
BackendTexture backendTex = create_backend_texture(reporter, caps, recorder.get(),
|
|
ct, withMips, renderable,
|
|
kColors);
|
|
|
|
sk_sp<SkImage> image = wrap_backend_texture(reporter, recorder.get(), backendTex,
|
|
ct, withMips);
|
|
if (!image) {
|
|
continue;
|
|
}
|
|
|
|
check_levels(reporter, context, recorder.get(), image.get(), withMips, kColors);
|
|
|
|
image.reset();
|
|
|
|
update_backend_texture(recorder.get(), backendTex, ct, withMips, kColorsNew);
|
|
|
|
image = wrap_backend_texture(reporter, recorder.get(), backendTex, ct, withMips);
|
|
if (!image) {
|
|
continue;
|
|
}
|
|
|
|
check_levels(reporter, context, recorder.get(), image.get(), withMips, kColorsNew);
|
|
|
|
image.reset();
|
|
|
|
recorder->deleteBackendTexture(backendTex);
|
|
}
|
|
}
|
|
}
|
|
}
|