Add mipmap support to SkPixmap flavor of createBackendTexture
Change-Id: I7a2dea9b0b8e6b985f2d56e587939266022c19e1 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/234664 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
798a31dd8a
commit
7f367983b5
@ -341,9 +341,9 @@ SkColor SkPixmap::getColor(int x, int y) const {
|
||||
b = ((value >> 20) & 0x3ff) * (1/1023.0f),
|
||||
a = ((value >> 30) & 0x3 ) * (1/ 3.0f);
|
||||
if (a != 0 && needsUnpremul) {
|
||||
r *= (1.0f/a);
|
||||
g *= (1.0f/a);
|
||||
b *= (1.0f/a);
|
||||
r = SkTPin(r/a, 0.0f, 1.0f);
|
||||
g = SkTPin(g/a, 0.0f, 1.0f);
|
||||
b = SkTPin(b/a, 0.0f, 1.0f);
|
||||
}
|
||||
return (uint32_t)( r * 255.0f ) << 16
|
||||
| (uint32_t)( g * 255.0f ) << 8
|
||||
|
@ -267,6 +267,9 @@ public:
|
||||
// pixmap(s).
|
||||
// If numLevels is 1 a non-mipMapped texture will result. If a mipMapped texture is desired
|
||||
// the data for all the mipmap levels must be provided.
|
||||
// For the Vulkan backend the layout of the created VkImage will be:
|
||||
// VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
// regardless of the renderability setting
|
||||
GrBackendTexture createBackendTexture(const SkPixmap srcData[], int numLevels,
|
||||
GrRenderable, GrProtected);
|
||||
|
||||
|
@ -3553,11 +3553,6 @@ GrBackendTexture GrGLGpu::onCreateBackendTexture(int w, int h,
|
||||
return GrBackendTexture(); // invalid
|
||||
}
|
||||
|
||||
// Currently we don't support uploading pixel data when mipped.
|
||||
if (srcData && GrMipMapped::kYes == mipMapped) {
|
||||
return GrBackendTexture(); // invalid
|
||||
}
|
||||
|
||||
GrGLTextureInfo info;
|
||||
GrGLTextureParameters::SamplerOverriddenState initialState;
|
||||
|
||||
@ -3596,6 +3591,7 @@ GrBackendTexture GrGLGpu::onCreateBackendTexture(int w, int h,
|
||||
texels[i] = {&(tmpPixels[offset]), currentWidth * bytesPerPixel};
|
||||
}
|
||||
}
|
||||
|
||||
GrSurfaceDesc desc;
|
||||
desc.fWidth = w;
|
||||
desc.fHeight = h;
|
||||
|
@ -16,6 +16,7 @@ GrMTLPixelFormat GrGetMTLPixelFormatFromMtlTextureInfo(const GrMtlTextureInfo&);
|
||||
|
||||
#if GR_TEST_UTILS
|
||||
const char* GrMtlFormatToStr(GrMTLPixelFormat mtlFormat);
|
||||
bool GrMtlFormatIsBGRA(GrMTLPixelFormat mtlFormat);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -712,6 +712,20 @@ static GrPixelConfig mtl_format_to_pixelconfig(MTLPixelFormat format) {
|
||||
SkUNREACHABLE;
|
||||
}
|
||||
|
||||
void copy_src_data(char* dst, size_t bytesPerPixel, const SkTArray<size_t>& individualMipOffsets,
|
||||
const SkPixmap srcData[], int numMipLevels, size_t bufferSize) {
|
||||
SkASSERT(srcData && numMipLevels);
|
||||
SkASSERT(individualMipOffsets.count() == numMipLevels);
|
||||
|
||||
for (int level = 0; level < numMipLevels; ++level) {
|
||||
const size_t trimRB = srcData[level].width() * bytesPerPixel;
|
||||
SkASSERT(individualMipOffsets[level] + trimRB * srcData[level].height() <= bufferSize);
|
||||
SkRectMemcpy(dst + individualMipOffsets[level], trimRB,
|
||||
srcData[level].addr(), srcData[level].rowBytes(),
|
||||
trimRB, srcData[level].height());
|
||||
}
|
||||
}
|
||||
|
||||
bool GrMtlGpu::createMtlTextureForBackendSurface(MTLPixelFormat format,
|
||||
int w, int h, bool texturable,
|
||||
bool renderable, GrMipMapped mipMapped,
|
||||
@ -734,11 +748,8 @@ bool GrMtlGpu::createMtlTextureForBackendSurface(MTLPixelFormat format,
|
||||
if (renderable && !fMtlCaps->isFormatRenderable(format, 1)) {
|
||||
return false;
|
||||
}
|
||||
// Currently we don't support uploading pixel data when mipped.
|
||||
if (srcData && GrMipMapped::kYes == mipMapped) {
|
||||
return false;
|
||||
}
|
||||
if(!check_max_blit_width(w)) {
|
||||
|
||||
if (!check_max_blit_width(w)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -793,14 +804,8 @@ bool GrMtlGpu::createMtlTextureForBackendSurface(MTLPixelFormat format,
|
||||
|
||||
// Fill buffer with data
|
||||
if (srcData) {
|
||||
const size_t trimRowBytes = w * bytesPerPixel;
|
||||
|
||||
// TODO: support mipmapping
|
||||
SkASSERT(1 == mipLevelCount);
|
||||
|
||||
// copy data into the buffer, skipping the trailing bytes
|
||||
const char* src = (const char*) srcData->addr();
|
||||
SkRectMemcpy(buffer, trimRowBytes, src, srcData->rowBytes(), trimRowBytes, h);
|
||||
copy_src_data(buffer, bytesPerPixel, individualMipOffsets,
|
||||
srcData, numMipLevels, combinedBufferSize);
|
||||
} else if (color) {
|
||||
GrPixelConfig config = mtl_format_to_pixelconfig(format);
|
||||
SkASSERT(kUnknown_GrPixelConfig != config);
|
||||
|
@ -353,6 +353,10 @@ bool GrMtlFormatToCompressionType(MTLPixelFormat mtlFormat,
|
||||
}
|
||||
|
||||
#if GR_TEST_UTILS
|
||||
bool GrMtlFormatIsBGRA(GrMTLPixelFormat mtlFormat) {
|
||||
return mtlFormat == MTLPixelFormatBGRA8Unorm;
|
||||
}
|
||||
|
||||
const char* GrMtlFormatToStr(GrMTLPixelFormat mtlFormat) {
|
||||
switch (mtlFormat) {
|
||||
case MTLPixelFormatInvalid: return "Invalid";
|
||||
|
@ -1448,23 +1448,26 @@ GrStencilAttachment* GrVkGpu::createStencilAttachmentForRenderTarget(
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool copy_src_data(GrVkGpu* gpu, const GrVkAlloc& alloc, VkFormat vkFormat,
|
||||
int width, int height,
|
||||
const void* srcData, size_t srcRowBytes) {
|
||||
SkASSERT(srcData);
|
||||
const SkTArray<size_t>& individualMipOffsets,
|
||||
const SkPixmap srcData[], int numMipLevels) {
|
||||
SkASSERT(srcData && numMipLevels);
|
||||
SkASSERT(!GrVkFormatIsCompressed(vkFormat));
|
||||
SkASSERT(individualMipOffsets.count() == numMipLevels);
|
||||
|
||||
void* mapPtr = GrVkMemory::MapAlloc(gpu, alloc);
|
||||
char* mapPtr = (char*) GrVkMemory::MapAlloc(gpu, alloc);
|
||||
if (!mapPtr) {
|
||||
return false;
|
||||
}
|
||||
size_t bytesPerPixel = GrVkBytesPerFormat(vkFormat);
|
||||
const size_t trimRowBytes = width * bytesPerPixel;
|
||||
if (!srcRowBytes) {
|
||||
srcRowBytes = trimRowBytes;
|
||||
}
|
||||
SkASSERT(trimRowBytes * height <= alloc.fSize);
|
||||
|
||||
SkRectMemcpy(mapPtr, trimRowBytes, srcData, srcRowBytes, trimRowBytes, height);
|
||||
for (int level = 0; level < numMipLevels; ++level) {
|
||||
const size_t trimRB = srcData[level].width() * bytesPerPixel;
|
||||
SkASSERT(individualMipOffsets[level] + trimRB * srcData[level].height() <= alloc.fSize);
|
||||
|
||||
SkRectMemcpy(mapPtr + individualMipOffsets[level], trimRB,
|
||||
srcData[level].addr(), srcData[level].rowBytes(),
|
||||
trimRB, srcData[level].height());
|
||||
}
|
||||
|
||||
GrVkMemory::FlushMappedAlloc(gpu, alloc, 0, alloc.fSize);
|
||||
GrVkMemory::UnmapAlloc(gpu, alloc);
|
||||
@ -1527,11 +1530,6 @@ bool GrVkGpu::createVkImageForBackendSurface(VkFormat vkFormat, int w, int h, bo
|
||||
return false;
|
||||
}
|
||||
|
||||
// Currently we don't support uploading pixel data when mipped.
|
||||
if (srcData && GrMipMapped::kYes == mipMapped) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VkImageUsageFlags usageFlags = 0;
|
||||
usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
@ -1644,9 +1642,8 @@ bool GrVkGpu::createVkImageForBackendSurface(VkFormat vkFormat, int w, int h, bo
|
||||
return false;
|
||||
}
|
||||
|
||||
SkASSERT(1 == mipLevelCount);
|
||||
bool result = copy_src_data(this, bufferAlloc, vkFormat, w, h,
|
||||
srcData->addr(), srcData->rowBytes());
|
||||
bool result = copy_src_data(this, bufferAlloc, vkFormat, individualMipOffsets,
|
||||
srcData, numMipLevels);
|
||||
if (!result) {
|
||||
GrVkImage::DestroyImageInfo(this, info);
|
||||
GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
|
||||
|
@ -20,6 +20,11 @@
|
||||
#include "src/gpu/gl/GrGLUtil.h"
|
||||
#endif
|
||||
|
||||
#ifdef SK_METAL
|
||||
#include "include/gpu/mtl/GrMtlTypes.h"
|
||||
#include "src/gpu/mtl/GrMtlCppUtil.h"
|
||||
#endif
|
||||
|
||||
// Test wrapping of GrBackendObjects in SkSurfaces and SkImages (non-static since used in Mtl test)
|
||||
void test_wrapping(GrContext* context, skiatest::Reporter* reporter,
|
||||
std::function<GrBackendTexture (GrContext*,
|
||||
@ -93,60 +98,113 @@ void test_wrapping(GrContext* context, skiatest::Reporter* reporter,
|
||||
context->deleteBackendTexture(backendTex);
|
||||
}
|
||||
|
||||
static bool isBGRA(const GrBackendFormat& format) {
|
||||
switch (format.backend()) {
|
||||
case GrBackendApi::kMetal:
|
||||
#ifdef SK_METAL
|
||||
return GrMtlFormatIsBGRA(format.asMtlFormat());
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
case GrBackendApi::kDawn:
|
||||
return false;
|
||||
case GrBackendApi::kOpenGL:
|
||||
#ifdef SK_GL
|
||||
return format.asGLFormat() == GrGLFormat::kBGRA8;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
case GrBackendApi::kVulkan: {
|
||||
#ifdef SK_VULKAN
|
||||
VkFormat vkFormat;
|
||||
format.asVkFormat(&vkFormat);
|
||||
return vkFormat == VK_FORMAT_B8G8R8A8_UNORM;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
case GrBackendApi::kMock:
|
||||
return format.asMockColorType() == GrColorType::kBGRA_8888;
|
||||
}
|
||||
SkUNREACHABLE;
|
||||
}
|
||||
|
||||
static bool isRGB(const GrBackendFormat& format) {
|
||||
switch (format.backend()) {
|
||||
case GrBackendApi::kMetal:
|
||||
return false; // Metal doesn't even pretend to support this
|
||||
case GrBackendApi::kDawn:
|
||||
return false;
|
||||
case GrBackendApi::kOpenGL:
|
||||
#ifdef SK_GL
|
||||
return format.asGLFormat() == GrGLFormat::kRGB8;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
case GrBackendApi::kVulkan: {
|
||||
#ifdef SK_VULKAN
|
||||
VkFormat vkFormat;
|
||||
format.asVkFormat(&vkFormat);
|
||||
return vkFormat == VK_FORMAT_R8G8B8_UNORM;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
case GrBackendApi::kMock:
|
||||
return false; // No GrColorType::kRGB_888
|
||||
}
|
||||
SkUNREACHABLE;
|
||||
}
|
||||
|
||||
static void check_solid_pixmap(skiatest::Reporter* reporter,
|
||||
const SkColor4f& expected, const SkPixmap& actual,
|
||||
SkColorType ct, const char* label) {
|
||||
SkColorType ct, const char* label1, const char* label2) {
|
||||
// we need 0.001f across the board just for noise
|
||||
// we need 0.01f across the board for 1010102
|
||||
const float tols[4] = {0.01f, 0.01f, 0.01f, 0.01f};
|
||||
const float tols[4] = { 0.01f, 0.01f, 0.01f, 0.01f };
|
||||
|
||||
auto error = std::function<ComparePixmapsErrorReporter>(
|
||||
[reporter, ct, label](int x, int y, const float diffs[4]) {
|
||||
[reporter, ct, label1, label2](int x, int y, const float diffs[4]) {
|
||||
SkASSERT(x >= 0 && y >= 0);
|
||||
ERRORF(reporter, "%s %s - mismatch at %d, %d (%f, %f, %f %f)",
|
||||
ToolUtils::colortype_name(ct), label, x, y,
|
||||
ERRORF(reporter, "%s %s %s - mismatch at %d, %d (%f, %f, %f %f)",
|
||||
ToolUtils::colortype_name(ct), label1, label2, x, y,
|
||||
diffs[0], diffs[1], diffs[2], diffs[3]);
|
||||
});
|
||||
|
||||
check_solid_pixels(expected, actual, tols, error);
|
||||
}
|
||||
|
||||
// What would raster do?
|
||||
static SkColor4f get_expected_color(SkColor4f orig, SkColorType ct) {
|
||||
|
||||
uint32_t components = SkColorTypeComponentFlags(ct);
|
||||
|
||||
if (components & kGray_SkColorTypeComponentFlag) {
|
||||
// For the GPU backends, gray implies a single channel which is opaque.
|
||||
return { orig.fA, orig.fA, orig.fA, 1 };
|
||||
if (ct == kGray_8_SkColorType) {
|
||||
// Prevent the premul raster graciously applies in this case
|
||||
orig.fA = 1.0;
|
||||
}
|
||||
|
||||
float r = orig.fR, g = orig.fG, b = orig.fB, a = orig.fA;
|
||||
SkAlphaType at = SkColorTypeIsAlwaysOpaque(ct) ? kOpaque_SkAlphaType
|
||||
: kPremul_SkAlphaType;
|
||||
|
||||
// Missing channels are set to 0
|
||||
if (!(components & kRed_SkColorTypeComponentFlag)) {
|
||||
r = 0;
|
||||
}
|
||||
if (!(components & kGreen_SkColorTypeComponentFlag)) {
|
||||
g = 0;
|
||||
}
|
||||
if (!(components & kBlue_SkColorTypeComponentFlag)) {
|
||||
b = 0;
|
||||
}
|
||||
// except for missing alpha - which gets set to 1
|
||||
if (!(components & kAlpha_SkColorTypeComponentFlag)) {
|
||||
a = 1;
|
||||
}
|
||||
|
||||
return { r, g, b, a };
|
||||
SkImageInfo ii = SkImageInfo::Make(2, 2, ct, at);
|
||||
SkAutoPixmapStorage pm;
|
||||
pm.alloc(ii);
|
||||
pm.erase(orig);
|
||||
SkColor tmp = pm.getColor(0, 0);
|
||||
return SkColor4f::FromColor(tmp);
|
||||
}
|
||||
|
||||
static void check_mipmaps(GrContext* context, const GrBackendTexture& backendTex,
|
||||
SkColorType skColorType, const SkColor4f expectedColors[6],
|
||||
skiatest::Reporter* reporter);
|
||||
skiatest::Reporter* reporter, const char* label);
|
||||
|
||||
static void check_base_readbacks(GrContext* context, const GrBackendTexture& backendTex,
|
||||
SkColorType skColorType, GrRenderable renderable,
|
||||
const SkColor4f& color, skiatest::Reporter* reporter) {
|
||||
const SkColor4f& color, skiatest::Reporter* reporter,
|
||||
const char* label) {
|
||||
if (isRGB(backendTex.getBackendFormat())) {
|
||||
// readPixels is busted for the RGB backend format (skbug.com/8862)
|
||||
// TODO: add a GrColorType::kRGB_888 to fix the situation
|
||||
return;
|
||||
}
|
||||
|
||||
SkAlphaType at = SkColorTypeIsAlwaysOpaque(skColorType) ? kOpaque_SkAlphaType
|
||||
: kPremul_SkAlphaType;
|
||||
@ -157,28 +215,11 @@ static void check_base_readbacks(GrContext* context, const GrBackendTexture& bac
|
||||
|
||||
{
|
||||
SkImageInfo readBackII = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType,
|
||||
kPremul_SkAlphaType);
|
||||
kUnpremul_SkAlphaType);
|
||||
|
||||
SkAssertResult(actual.tryAlloc(readBackII));
|
||||
}
|
||||
|
||||
if (GrRenderable::kYes == renderable && context->colorTypeSupportedAsSurface(skColorType)) {
|
||||
sk_sp<SkSurface> surf = SkSurface::MakeFromBackendTexture(context,
|
||||
backendTex,
|
||||
kTopLeft_GrSurfaceOrigin,
|
||||
0,
|
||||
skColorType,
|
||||
nullptr, nullptr);
|
||||
if (surf) {
|
||||
actual.erase(SkColors::kTransparent);
|
||||
bool result = surf->readPixels(actual, 0, 0);
|
||||
REPORTER_ASSERT(reporter, result);
|
||||
|
||||
check_solid_pixmap(reporter, expectedColor, actual, skColorType,
|
||||
"SkSurface::readPixels");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
sk_sp<SkImage> img = SkImage::MakeFromTexture(context,
|
||||
backendTex,
|
||||
@ -197,10 +238,29 @@ static void check_base_readbacks(GrContext* context, const GrBackendTexture& bac
|
||||
#endif
|
||||
} else {
|
||||
check_solid_pixmap(reporter, expectedColor, actual, skColorType,
|
||||
"SkImage::readPixels");
|
||||
label, "SkImage::readPixels");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This will mark any mipmaps as dirty (bc that is what we do when we wrap a renderable
|
||||
// backend texture) so it must be done last!
|
||||
if (GrRenderable::kYes == renderable && context->colorTypeSupportedAsSurface(skColorType)) {
|
||||
sk_sp<SkSurface> surf = SkSurface::MakeFromBackendTexture(context,
|
||||
backendTex,
|
||||
kTopLeft_GrSurfaceOrigin,
|
||||
0,
|
||||
skColorType,
|
||||
nullptr, nullptr);
|
||||
if (surf) {
|
||||
actual.erase(SkColors::kTransparent);
|
||||
bool result = surf->readPixels(actual, 0, 0);
|
||||
REPORTER_ASSERT(reporter, result);
|
||||
|
||||
check_solid_pixmap(reporter, expectedColor, actual, skColorType,
|
||||
label, "SkSurface::readPixels");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test initialization of GrBackendObjects to a specific color (non-static since used in Mtl test)
|
||||
@ -226,15 +286,16 @@ void test_color_init(GrContext* context, skiatest::Reporter* reporter,
|
||||
return;
|
||||
}
|
||||
|
||||
check_base_readbacks(context, backendTex, skColorType, renderable, color, reporter);
|
||||
|
||||
if (mipMapped == GrMipMapped::kYes) {
|
||||
SkColor4f expectedColor = get_expected_color(color, skColorType);
|
||||
SkColor4f expectedColors[6] = { expectedColor, expectedColor, expectedColor,
|
||||
expectedColor, expectedColor, expectedColor };
|
||||
check_mipmaps(context, backendTex, skColorType, expectedColors, reporter);
|
||||
check_mipmaps(context, backendTex, skColorType, expectedColors, reporter, "colorinit");
|
||||
}
|
||||
|
||||
// The last step in this test will dirty the mipmaps so do it last
|
||||
check_base_readbacks(context, backendTex, skColorType, renderable, color,
|
||||
reporter, "colorinit");
|
||||
context->deleteBackendTexture(backendTex);
|
||||
}
|
||||
|
||||
@ -242,7 +303,7 @@ void test_color_init(GrContext* context, skiatest::Reporter* reporter,
|
||||
// all the mipMap levels.
|
||||
static void check_mipmaps(GrContext* context, const GrBackendTexture& backendTex,
|
||||
SkColorType skColorType, const SkColor4f expectedColors[6],
|
||||
skiatest::Reporter* reporter) {
|
||||
skiatest::Reporter* reporter, const char* label) {
|
||||
|
||||
#ifdef SK_GL
|
||||
// skbug.com/9141 (RGBA_F32 mipmaps appear to be broken on some Mali devices)
|
||||
@ -256,8 +317,15 @@ static void check_mipmaps(GrContext* context, const GrBackendTexture& backendTex
|
||||
}
|
||||
#endif
|
||||
|
||||
if (isRGB(backendTex.getBackendFormat())) {
|
||||
// readPixels is busted for the RGB backend format (skbug.com/8862)
|
||||
// TODO: add a GrColorType::kRGB_888 to fix the situation
|
||||
return;
|
||||
}
|
||||
|
||||
SkAlphaType at = SkColorTypeIsAlwaysOpaque(skColorType) ? kOpaque_SkAlphaType
|
||||
: kPremul_SkAlphaType;
|
||||
|
||||
sk_sp<SkImage> img = SkImage::MakeFromTexture(context,
|
||||
backendTex,
|
||||
kTopLeft_GrSurfaceOrigin,
|
||||
@ -268,11 +336,12 @@ static void check_mipmaps(GrContext* context, const GrBackendTexture& backendTex
|
||||
return;
|
||||
}
|
||||
|
||||
SkImageInfo newII = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
|
||||
SkImageInfo readbackSurfaceII = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType,
|
||||
kPremul_SkAlphaType);
|
||||
|
||||
sk_sp<SkSurface> surf = SkSurface::MakeRenderTarget(context,
|
||||
SkBudgeted::kNo,
|
||||
newII, 1,
|
||||
readbackSurfaceII, 1,
|
||||
kTopLeft_GrSurfaceOrigin,
|
||||
nullptr);
|
||||
if (!surf) {
|
||||
@ -295,7 +364,7 @@ static void check_mipmaps(GrContext* context, const GrBackendTexture& backendTex
|
||||
|
||||
SkImageInfo readbackII = SkImageInfo::Make(rectSize, rectSize,
|
||||
kRGBA_8888_SkColorType,
|
||||
kPremul_SkAlphaType);
|
||||
kUnpremul_SkAlphaType);
|
||||
SkAutoPixmapStorage actual2;
|
||||
SkAssertResult(actual2.tryAlloc(readbackII));
|
||||
actual2.erase(SkColors::kTransparent);
|
||||
@ -303,10 +372,83 @@ static void check_mipmaps(GrContext* context, const GrBackendTexture& backendTex
|
||||
bool result = surf->readPixels(actual2, 0, 0);
|
||||
REPORTER_ASSERT(reporter, result);
|
||||
|
||||
check_solid_pixmap(reporter, expectedColors[i], actual2, skColorType, "mip-level failure");
|
||||
check_solid_pixmap(reporter, expectedColors[i], actual2, skColorType,
|
||||
label, "mip-level failure");
|
||||
}
|
||||
}
|
||||
|
||||
static int make_pixmaps(SkColorType skColorType, GrMipMapped mipMapped,
|
||||
const SkColor4f colors[6], SkAutoPixmapStorage pixmaps[6]) {
|
||||
int levelSize = 32;
|
||||
int numMipLevels = mipMapped == GrMipMapped::kYes ? 6 : 1;
|
||||
SkAlphaType at = SkColorTypeIsAlwaysOpaque(skColorType) ? kOpaque_SkAlphaType
|
||||
: kPremul_SkAlphaType;
|
||||
for (int level = 0; level < numMipLevels; ++level) {
|
||||
SkImageInfo ii = SkImageInfo::Make(levelSize, levelSize, skColorType, at);
|
||||
pixmaps[level].alloc(ii);
|
||||
pixmaps[level].erase(colors[level]);
|
||||
levelSize /= 2;
|
||||
}
|
||||
return numMipLevels;
|
||||
}
|
||||
|
||||
// Test initialization of GrBackendObjects using SkPixmaps
|
||||
static void test_pixmap_init(GrContext* context, skiatest::Reporter* reporter,
|
||||
std::function<GrBackendTexture (GrContext*,
|
||||
const SkPixmap srcData[],
|
||||
int numLevels,
|
||||
GrRenderable)> create,
|
||||
SkColorType skColorType, GrMipMapped mipMapped,
|
||||
GrRenderable renderable) {
|
||||
SkAutoPixmapStorage pixmapMem[6];
|
||||
SkColor4f colors[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
|
||||
};
|
||||
|
||||
int numMipLevels = make_pixmaps(skColorType, mipMapped, colors, pixmapMem);
|
||||
SkASSERT(numMipLevels);
|
||||
|
||||
// TODO: this is tedious. Should we pass in an array of SkBitmaps instead?
|
||||
SkPixmap pixmaps[6];
|
||||
for (int i = 0; i < numMipLevels; ++i) {
|
||||
pixmaps[i].reset(pixmapMem[i].info(), pixmapMem[i].addr(), pixmapMem[i].rowBytes());
|
||||
}
|
||||
|
||||
GrBackendTexture backendTex = create(context, pixmaps, numMipLevels, renderable);
|
||||
if (!backendTex.isValid()) {
|
||||
// errors here should be reported by the test_wrapping test
|
||||
return;
|
||||
}
|
||||
|
||||
if (skColorType == kBGRA_8888_SkColorType && !isBGRA(backendTex.getBackendFormat())) {
|
||||
// When kBGRA is backed by an RGBA something goes wrong in the swizzling
|
||||
return;
|
||||
}
|
||||
|
||||
if (mipMapped == GrMipMapped::kYes) {
|
||||
SkColor4f expectedColors[6] = {
|
||||
get_expected_color(colors[0], skColorType),
|
||||
get_expected_color(colors[1], skColorType),
|
||||
get_expected_color(colors[2], skColorType),
|
||||
get_expected_color(colors[3], skColorType),
|
||||
get_expected_color(colors[4], skColorType),
|
||||
get_expected_color(colors[5], skColorType),
|
||||
};
|
||||
|
||||
check_mipmaps(context, backendTex, skColorType, expectedColors, reporter, "pixmap");
|
||||
}
|
||||
|
||||
// The last step in this test will dirty the mipmaps so do it last
|
||||
check_base_readbacks(context, backendTex, skColorType, renderable, colors[0],
|
||||
reporter, "pixmap");
|
||||
context->deleteBackendTexture(backendTex);
|
||||
}
|
||||
|
||||
enum class VkLayout {
|
||||
kUndefined,
|
||||
kReadOnlyOptimal,
|
||||
@ -452,11 +594,11 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ColorTypeBackendAllocationTest, reporter, ctx
|
||||
{ kRGBA_F16Norm_SkColorType, SkColors::kLtGray },
|
||||
{ kRGBA_F16_SkColorType, SkColors::kYellow },
|
||||
{ kRGBA_F32_SkColorType, SkColors::kGray },
|
||||
{ kR8G8_unorm_SkColorType, { .25f, .75f, 0, 0 } },
|
||||
{ kR8G8_unorm_SkColorType, { .25f, .75f, 0, 1 } },
|
||||
{ kR16G16_unorm_SkColorType, SkColors::kGreen },
|
||||
{ kA16_unorm_SkColorType, kTransCol },
|
||||
{ kA16_float_SkColorType, kTransCol },
|
||||
{ kR16G16_float_SkColorType, { .25f, .75f, 0, 0 } },
|
||||
{ kR16G16_float_SkColorType, { .25f, .75f, 0, 1 } },
|
||||
{ kR16G16B16A16_unorm_SkColorType,{ .25f, .5f, .75f, 1 } },
|
||||
};
|
||||
|
||||
@ -482,6 +624,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ColorTypeBackendAllocationTest, reporter, ctx
|
||||
renderable).isValid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GrRenderable::kYes == renderable) {
|
||||
if (kRGB_888x_SkColorType == combo.fColorType) {
|
||||
// Ganesh can't perform the blends correctly when rendering this format
|
||||
@ -549,10 +692,41 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ColorTypeBackendAllocationTest, reporter, ctx
|
||||
SkColorTypeToGrColorType(colorType),
|
||||
combo.fColor, mipMapped, renderable);
|
||||
}
|
||||
|
||||
// Gray_8 is problematic. In the colorInit tests there is ambiguity when
|
||||
// mapping from format to colorType (since R8 or A8 could be either Alpha_8
|
||||
// or Gray_8). To compensate for this ambiguity we feed in colors with
|
||||
// R==G==B==A. If we actually do know the colorType (as is the case
|
||||
// in the SkPixmap case, there is no ambiguity but the two test expectations
|
||||
// now collide.
|
||||
// For now, skip the SkPixmap tests. The real answer is to plumb the
|
||||
// SkColorType down further in the color-init case.
|
||||
if (colorType != kGray_8_SkColorType) {
|
||||
auto createWithSrcDataMtd = [](GrContext* context,
|
||||
const SkPixmap srcData[],
|
||||
int numLevels,
|
||||
GrRenderable renderable) {
|
||||
SkASSERT(srcData && numLevels);
|
||||
auto result = context->priv().createBackendTexture(srcData, numLevels,
|
||||
renderable,
|
||||
GrProtected::kNo);
|
||||
check_vk_layout(result, VkLayout::kReadOnlyOptimal);
|
||||
#ifdef SK_DEBUG
|
||||
{
|
||||
auto format = context->defaultBackendFormat(srcData[0].colorType(),
|
||||
renderable);
|
||||
SkASSERT(format == result.getBackendFormat());
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
};
|
||||
|
||||
test_pixmap_init(context, reporter, createWithSrcDataMtd, colorType,
|
||||
mipMapped, renderable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -692,7 +866,7 @@ DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkBackendAllocationTest, reporter, ctxInfo) {
|
||||
const GrVkCaps* vkCaps = static_cast<const GrVkCaps*>(context->priv().caps());
|
||||
|
||||
constexpr SkColor4f kTransCol { 0, 0.25f, 0.75f, 0.5f };
|
||||
constexpr SkColor4f kGrayCol { 0.75f, 0.75f, 0.75f, 0.75f };
|
||||
constexpr SkColor4f kGrayCol { 0.75f, 0.75f, 0.75f, 1 };
|
||||
|
||||
struct {
|
||||
GrColorType fColorType;
|
||||
|
@ -32,10 +32,11 @@ DEF_GPUTEST_FOR_METAL_CONTEXT(MtlBackendAllocationTest, reporter, ctxInfo) {
|
||||
const GrMtlCaps* mtlCaps = static_cast<const GrMtlCaps*>(context->priv().caps());
|
||||
|
||||
constexpr SkColor4f kTransCol { 0, 0.25f, 0.75f, 0.5f };
|
||||
constexpr SkColor4f kGrayCol { 0.75f, 0.75f, 0.75f, 0.75f };
|
||||
|
||||
struct {
|
||||
GrColorType fColorType;
|
||||
MTLPixelFormat fFormat;
|
||||
MTLPixelFormat fFormat;
|
||||
SkColor4f fColor;
|
||||
} combinations[] = {
|
||||
{ GrColorType::kRGBA_8888, MTLPixelFormatRGBA8Unorm, SkColors::kRed },
|
||||
@ -56,7 +57,7 @@ DEF_GPUTEST_FOR_METAL_CONTEXT(MtlBackendAllocationTest, reporter, ctxInfo) {
|
||||
|
||||
{ GrColorType::kAlpha_8, MTLPixelFormatA8Unorm, kTransCol },
|
||||
{ GrColorType::kAlpha_8, MTLPixelFormatR8Unorm, kTransCol },
|
||||
{ GrColorType::kGray_8, MTLPixelFormatR8Unorm, SkColors::kDkGray },
|
||||
{ GrColorType::kGray_8, MTLPixelFormatR8Unorm, kGrayCol },
|
||||
|
||||
{ GrColorType::kRGBA_F32, MTLPixelFormatRGBA32Float, SkColors::kRed },
|
||||
|
||||
@ -114,7 +115,6 @@ DEF_GPUTEST_FOR_METAL_CONTEXT(MtlBackendAllocationTest, reporter, ctxInfo) {
|
||||
combo.fColorType, mipMapped, renderable);
|
||||
}
|
||||
|
||||
// Not implemented for Metal yet
|
||||
{
|
||||
auto createWithColorMtd = [format](GrContext* context,
|
||||
const SkColor4f& color,
|
||||
|
Loading…
Reference in New Issue
Block a user