Reland DeferredTextureImageData low-bit-depth/dithering support
Cause DeferredTextureImageData functionality to support low bit depth (4444, 565) image formats (with dithering). Updated to handle colorspace + 4444 colortype correctly. Bug: 720105 Change-Id: Ib7e14d937849f4f6b08fda6992a240bb203d0089 Reviewed-on: https://skia-review.googlesource.com/19094 Commit-Queue: Eric Karl <ericrk@chromium.org> Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
a8d45e5220
commit
7a8c84c6c9
@ -17,7 +17,9 @@
|
|||||||
// Helper function that uploads the given SkImage using MakeFromDeferredTextureImageData and then
|
// Helper function that uploads the given SkImage using MakeFromDeferredTextureImageData and then
|
||||||
// draws the uploaded version at the specified coordinates.
|
// draws the uploaded version at the specified coordinates.
|
||||||
static void DrawDeferredTextureImageData(SkCanvas* canvas,
|
static void DrawDeferredTextureImageData(SkCanvas* canvas,
|
||||||
SkImage::DeferredTextureImageUsageParams* params) {
|
const char* resourceName,
|
||||||
|
SkImage::DeferredTextureImageUsageParams* params,
|
||||||
|
SkColorType dstColorType) {
|
||||||
GrContext* context = canvas->getGrContext();
|
GrContext* context = canvas->getGrContext();
|
||||||
if (!context) {
|
if (!context) {
|
||||||
skiagm::GM::DrawGpuOnlyMessage(canvas);
|
skiagm::GM::DrawGpuOnlyMessage(canvas);
|
||||||
@ -27,14 +29,14 @@ static void DrawDeferredTextureImageData(SkCanvas* canvas,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
sk_sp<SkImage> encodedImage = GetResourceAsImage("mandrill_512.png");
|
sk_sp<SkImage> encodedImage = GetResourceAsImage(resourceName);
|
||||||
if (!encodedImage) {
|
if (!encodedImage) {
|
||||||
SkDebugf("\nCould not load resource.\n");
|
SkDebugf("\nCould not load resource.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t requiredMemoryInBytes = encodedImage->getDeferredTextureImageData(
|
size_t requiredMemoryInBytes = encodedImage->getDeferredTextureImageData(
|
||||||
*proxy, params, 1, nullptr, canvas->imageInfo().colorSpace());
|
*proxy, params, 1, nullptr, canvas->imageInfo().colorSpace(), dstColorType);
|
||||||
if (requiredMemoryInBytes == 0) {
|
if (requiredMemoryInBytes == 0) {
|
||||||
SkDebugf("\nCould not create DeferredTextureImageData.\n");
|
SkDebugf("\nCould not create DeferredTextureImageData.\n");
|
||||||
return;
|
return;
|
||||||
@ -43,7 +45,7 @@ static void DrawDeferredTextureImageData(SkCanvas* canvas,
|
|||||||
std::vector<uint8_t> memory;
|
std::vector<uint8_t> memory;
|
||||||
memory.resize(requiredMemoryInBytes);
|
memory.resize(requiredMemoryInBytes);
|
||||||
encodedImage->getDeferredTextureImageData(
|
encodedImage->getDeferredTextureImageData(
|
||||||
*proxy, params, 1, memory.data(), canvas->imageInfo().colorSpace());
|
*proxy, params, 1, memory.data(), canvas->imageInfo().colorSpace(), dstColorType);
|
||||||
sk_sp<SkImage> uploadedEncodedImage = SkImage::MakeFromDeferredTextureImageData(
|
sk_sp<SkImage> uploadedEncodedImage = SkImage::MakeFromDeferredTextureImageData(
|
||||||
context, memory.data(), SkBudgeted::kNo);
|
context, memory.data(), SkBudgeted::kNo);
|
||||||
|
|
||||||
@ -52,14 +54,14 @@ static void DrawDeferredTextureImageData(SkCanvas* canvas,
|
|||||||
|
|
||||||
|
|
||||||
SkBitmap bitmap;
|
SkBitmap bitmap;
|
||||||
if (!GetResourceAsBitmap("mandrill_512.png", &bitmap)) {
|
if (!GetResourceAsBitmap(resourceName, &bitmap)) {
|
||||||
SkDebugf("\nCould not decode resource.\n");
|
SkDebugf("\nCould not decode resource.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sk_sp<SkImage> decodedImage = SkImage::MakeFromBitmap(bitmap);
|
sk_sp<SkImage> decodedImage = SkImage::MakeFromBitmap(bitmap);
|
||||||
|
|
||||||
requiredMemoryInBytes = decodedImage->getDeferredTextureImageData(
|
requiredMemoryInBytes = decodedImage->getDeferredTextureImageData(
|
||||||
*proxy, params, 1, nullptr, canvas->imageInfo().colorSpace());
|
*proxy, params, 1, nullptr, canvas->imageInfo().colorSpace(), dstColorType);
|
||||||
if (requiredMemoryInBytes == 0) {
|
if (requiredMemoryInBytes == 0) {
|
||||||
SkDebugf("\nCould not create DeferredTextureImageData.\n");
|
SkDebugf("\nCould not create DeferredTextureImageData.\n");
|
||||||
return;
|
return;
|
||||||
@ -67,15 +69,16 @@ static void DrawDeferredTextureImageData(SkCanvas* canvas,
|
|||||||
|
|
||||||
memory.resize(requiredMemoryInBytes);
|
memory.resize(requiredMemoryInBytes);
|
||||||
decodedImage->getDeferredTextureImageData(
|
decodedImage->getDeferredTextureImageData(
|
||||||
*proxy, params, 1, memory.data(), canvas->imageInfo().colorSpace());
|
*proxy, params, 1, memory.data(), canvas->imageInfo().colorSpace(), dstColorType);
|
||||||
sk_sp<SkImage> uploadedDecodedImage = SkImage::MakeFromDeferredTextureImageData(
|
sk_sp<SkImage> uploadedDecodedImage = SkImage::MakeFromDeferredTextureImageData(
|
||||||
context, memory.data(), SkBudgeted::kNo);
|
context, memory.data(), SkBudgeted::kNo);
|
||||||
|
|
||||||
canvas->drawImage(uploadedDecodedImage, 512 + 20, 10);
|
canvas->drawImage(uploadedDecodedImage, encodedImage->width() + 20, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawDeferredTextureImageMipMapTree(SkCanvas* canvas, SkImage* image,
|
static void DrawDeferredTextureImageMipMapTree(SkCanvas* canvas, SkImage* image,
|
||||||
SkImage::DeferredTextureImageUsageParams* params) {
|
SkImage::DeferredTextureImageUsageParams* params,
|
||||||
|
SkColorType dstColorType) {
|
||||||
GrContext* context = canvas->getGrContext();
|
GrContext* context = canvas->getGrContext();
|
||||||
if (!context) {
|
if (!context) {
|
||||||
skiagm::GM::DrawGpuOnlyMessage(canvas);
|
skiagm::GM::DrawGpuOnlyMessage(canvas);
|
||||||
@ -88,7 +91,7 @@ static void DrawDeferredTextureImageMipMapTree(SkCanvas* canvas, SkImage* image,
|
|||||||
|
|
||||||
int mipLevelCount = SkMipMap::ComputeLevelCount(image->width(), image->height());
|
int mipLevelCount = SkMipMap::ComputeLevelCount(image->width(), image->height());
|
||||||
size_t requiredMemoryInBytes = image->getDeferredTextureImageData(
|
size_t requiredMemoryInBytes = image->getDeferredTextureImageData(
|
||||||
*proxy, params, 1, nullptr, canvas->imageInfo().colorSpace());
|
*proxy, params, 1, nullptr, canvas->imageInfo().colorSpace(), dstColorType);
|
||||||
if (requiredMemoryInBytes == 0) {
|
if (requiredMemoryInBytes == 0) {
|
||||||
SkDebugf("\nCould not create DeferredTextureImageData.\n");
|
SkDebugf("\nCould not create DeferredTextureImageData.\n");
|
||||||
return;
|
return;
|
||||||
@ -97,7 +100,7 @@ static void DrawDeferredTextureImageMipMapTree(SkCanvas* canvas, SkImage* image,
|
|||||||
std::vector<uint8_t> memory;
|
std::vector<uint8_t> memory;
|
||||||
memory.resize(requiredMemoryInBytes);
|
memory.resize(requiredMemoryInBytes);
|
||||||
image->getDeferredTextureImageData(
|
image->getDeferredTextureImageData(
|
||||||
*proxy, params, 1, memory.data(), canvas->imageInfo().colorSpace());
|
*proxy, params, 1, memory.data(), canvas->imageInfo().colorSpace(), dstColorType);
|
||||||
sk_sp<SkImage> uploadedImage = SkImage::MakeFromDeferredTextureImageData(
|
sk_sp<SkImage> uploadedImage = SkImage::MakeFromDeferredTextureImageData(
|
||||||
context, memory.data(), SkBudgeted::kNo);
|
context, memory.data(), SkBudgeted::kNo);
|
||||||
|
|
||||||
@ -145,13 +148,19 @@ static void DrawDeferredTextureImageMipMapTree(SkCanvas* canvas, SkImage* image,
|
|||||||
DEF_SIMPLE_GM(deferred_texture_image_none, canvas, 512 + 512 + 30, 512 + 20) {
|
DEF_SIMPLE_GM(deferred_texture_image_none, canvas, 512 + 512 + 30, 512 + 20) {
|
||||||
auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(1.f, 1.f),
|
auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(1.f, 1.f),
|
||||||
kNone_SkFilterQuality, 0);
|
kNone_SkFilterQuality, 0);
|
||||||
DrawDeferredTextureImageData(canvas, ¶ms);
|
DrawDeferredTextureImageData(canvas, "mandrill_512.png", ¶ms, kN32_SkColorType);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_SIMPLE_GM(deferred_texture_image_low, canvas, 512 + 512 + 30, 512 + 20) {
|
DEF_SIMPLE_GM(deferred_texture_image_low, canvas, 512 + 512 + 30, 512 + 20) {
|
||||||
auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(1.f, 1.f),
|
auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(1.f, 1.f),
|
||||||
kLow_SkFilterQuality, 0);
|
kLow_SkFilterQuality, 0);
|
||||||
DrawDeferredTextureImageData(canvas, ¶ms);
|
DrawDeferredTextureImageData(canvas, "mandrill_512.png", ¶ms, kN32_SkColorType);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEF_SIMPLE_GM(deferred_texture_image_low_dithered, canvas, 180 + 180 + 30, 180 + 20) {
|
||||||
|
auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(0.25f, 0.25f),
|
||||||
|
kLow_SkFilterQuality, 0);
|
||||||
|
DrawDeferredTextureImageData(canvas, "dog.jpg", ¶ms, kARGB_4444_SkColorType);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_SIMPLE_GM(deferred_texture_image_medium_encoded, canvas, 512 + 512 + 30, 1110) {
|
DEF_SIMPLE_GM(deferred_texture_image_medium_encoded, canvas, 512 + 512 + 30, 1110) {
|
||||||
@ -163,7 +172,7 @@ DEF_SIMPLE_GM(deferred_texture_image_medium_encoded, canvas, 512 + 512 + 30, 111
|
|||||||
|
|
||||||
auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(0.25f, 0.25f),
|
auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(0.25f, 0.25f),
|
||||||
kMedium_SkFilterQuality, 0);
|
kMedium_SkFilterQuality, 0);
|
||||||
DrawDeferredTextureImageMipMapTree(canvas, encodedImage.get(), ¶ms);
|
DrawDeferredTextureImageMipMapTree(canvas, encodedImage.get(), ¶ms, kN32_SkColorType);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_SIMPLE_GM(deferred_texture_image_medium_decoded, canvas, 512 + 512 + 30, 1110) {
|
DEF_SIMPLE_GM(deferred_texture_image_medium_decoded, canvas, 512 + 512 + 30, 1110) {
|
||||||
@ -176,13 +185,13 @@ DEF_SIMPLE_GM(deferred_texture_image_medium_decoded, canvas, 512 + 512 + 30, 111
|
|||||||
|
|
||||||
auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(0.25f, 0.25f),
|
auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(0.25f, 0.25f),
|
||||||
kMedium_SkFilterQuality, 0);
|
kMedium_SkFilterQuality, 0);
|
||||||
DrawDeferredTextureImageMipMapTree(canvas, decodedImage.get(), ¶ms);
|
DrawDeferredTextureImageMipMapTree(canvas, decodedImage.get(), ¶ms, kN32_SkColorType);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_SIMPLE_GM(deferred_texture_image_high, canvas, 512 + 512 + 30, 512 + 20) {
|
DEF_SIMPLE_GM(deferred_texture_image_high, canvas, 512 + 512 + 30, 512 + 20) {
|
||||||
auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(1.f, 1.f),
|
auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(1.f, 1.f),
|
||||||
kHigh_SkFilterQuality, 0);
|
kHigh_SkFilterQuality, 0);
|
||||||
DrawDeferredTextureImageData(canvas, ¶ms);
|
DrawDeferredTextureImageData(canvas, "mandrill_512.png", ¶ms, kN32_SkColorType);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_SIMPLE_GM(deferred_texture_image_medium_encoded_indexed, canvas, 128 + 128 + 30, 340) {
|
DEF_SIMPLE_GM(deferred_texture_image_medium_encoded_indexed, canvas, 128 + 128 + 30, 340) {
|
||||||
@ -194,7 +203,7 @@ DEF_SIMPLE_GM(deferred_texture_image_medium_encoded_indexed, canvas, 128 + 128 +
|
|||||||
|
|
||||||
auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(0.25f, 0.25f),
|
auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(0.25f, 0.25f),
|
||||||
kMedium_SkFilterQuality, 0);
|
kMedium_SkFilterQuality, 0);
|
||||||
DrawDeferredTextureImageMipMapTree(canvas, encodedImage.get(), ¶ms);
|
DrawDeferredTextureImageMipMapTree(canvas, encodedImage.get(), ¶ms, kN32_SkColorType);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_SIMPLE_GM(deferred_texture_image_medium_decoded_indexed, canvas, 128 + 128 + 30, 340) {
|
DEF_SIMPLE_GM(deferred_texture_image_medium_decoded_indexed, canvas, 128 + 128 + 30, 340) {
|
||||||
@ -207,7 +216,7 @@ DEF_SIMPLE_GM(deferred_texture_image_medium_decoded_indexed, canvas, 128 + 128 +
|
|||||||
|
|
||||||
auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(0.25f, 0.25f),
|
auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(0.25f, 0.25f),
|
||||||
kMedium_SkFilterQuality, 0);
|
kMedium_SkFilterQuality, 0);
|
||||||
DrawDeferredTextureImageMipMapTree(canvas, decodedImage.get(), ¶ms);
|
DrawDeferredTextureImageMipMapTree(canvas, decodedImage.get(), ¶ms, kN32_SkColorType);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -477,12 +477,18 @@ public:
|
|||||||
* dstColorSpace is the color space of the surface where this texture will ultimately be used.
|
* dstColorSpace is the color space of the surface where this texture will ultimately be used.
|
||||||
* If the method determines that mip-maps are needed, this helps determine the correct strategy
|
* If the method determines that mip-maps are needed, this helps determine the correct strategy
|
||||||
* for building them (gamma-correct or not).
|
* for building them (gamma-correct or not).
|
||||||
|
*
|
||||||
|
* dstColorType is the color type of the surface where this texture will ultimately be used.
|
||||||
|
* This determines the format with which the image will be uploaded to the GPU. If dstColorType
|
||||||
|
* does not support color spaces (low bit depth types such as ARGB_4444), then dstColorSpace
|
||||||
|
* must be null.
|
||||||
*/
|
*/
|
||||||
size_t getDeferredTextureImageData(const GrContextThreadSafeProxy&,
|
size_t getDeferredTextureImageData(const GrContextThreadSafeProxy&,
|
||||||
const DeferredTextureImageUsageParams[],
|
const DeferredTextureImageUsageParams[],
|
||||||
int paramCnt,
|
int paramCnt,
|
||||||
void* buffer,
|
void* buffer,
|
||||||
SkColorSpace* dstColorSpace = nullptr) const;
|
SkColorSpace* dstColorSpace = nullptr,
|
||||||
|
SkColorType dstColorType = kN32_SkColorType) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a texture-backed image from data produced in SkImage::getDeferredTextureImageData.
|
* Returns a texture-backed image from data produced in SkImage::getDeferredTextureImageData.
|
||||||
|
@ -14,6 +14,16 @@ SkAutoPixmapStorage::~SkAutoPixmapStorage() {
|
|||||||
this->freeStorage();
|
this->freeStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SkAutoPixmapStorage& SkAutoPixmapStorage::operator=(SkAutoPixmapStorage&& other) {
|
||||||
|
this->fStorage = other.fStorage;
|
||||||
|
this->INHERITED::reset(other.info(), this->fStorage, other.rowBytes(), other.ctable());
|
||||||
|
|
||||||
|
other.fStorage = nullptr;
|
||||||
|
other.INHERITED::reset();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
size_t SkAutoPixmapStorage::AllocSize(const SkImageInfo& info, size_t* rowBytes) {
|
size_t SkAutoPixmapStorage::AllocSize(const SkImageInfo& info, size_t* rowBytes) {
|
||||||
size_t rb = info.minRowBytes();
|
size_t rb = info.minRowBytes();
|
||||||
if (rowBytes) {
|
if (rowBytes) {
|
||||||
|
@ -16,6 +16,11 @@ public:
|
|||||||
SkAutoPixmapStorage();
|
SkAutoPixmapStorage();
|
||||||
~SkAutoPixmapStorage();
|
~SkAutoPixmapStorage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Leave the moved-from object in a free-but-valid state.
|
||||||
|
*/
|
||||||
|
SkAutoPixmapStorage& operator=(SkAutoPixmapStorage&& other);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to allocate memory for the pixels needed to match the specified Info. On success
|
* Try to allocate memory for the pixels needed to match the specified Info. On success
|
||||||
* return true and fill out the pixmap to point to that memory. The storage will be freed
|
* return true and fill out the pixmap to point to that memory. The storage will be freed
|
||||||
|
@ -347,7 +347,8 @@ sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx,
|
|||||||
size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy&,
|
size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy&,
|
||||||
const DeferredTextureImageUsageParams[],
|
const DeferredTextureImageUsageParams[],
|
||||||
int paramCnt, void* buffer,
|
int paramCnt, void* buffer,
|
||||||
SkColorSpace* dstColorSpace) const {
|
SkColorSpace* dstColorSpace,
|
||||||
|
SkColorType dstColorType) const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,10 +597,22 @@ private:
|
|||||||
offsetof(DeferredTextureImage, member), \
|
offsetof(DeferredTextureImage, member), \
|
||||||
sizeof(DeferredTextureImage::member));
|
sizeof(DeferredTextureImage::member));
|
||||||
|
|
||||||
|
static bool SupportsColorSpace(SkColorType colorType) {
|
||||||
|
switch (colorType) {
|
||||||
|
case kRGBA_8888_SkColorType:
|
||||||
|
case kBGRA_8888_SkColorType:
|
||||||
|
case kRGBA_F16_SkColorType:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& proxy,
|
size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& proxy,
|
||||||
const DeferredTextureImageUsageParams params[],
|
const DeferredTextureImageUsageParams params[],
|
||||||
int paramCnt, void* buffer,
|
int paramCnt, void* buffer,
|
||||||
SkColorSpace* dstColorSpace) const {
|
SkColorSpace* dstColorSpace,
|
||||||
|
SkColorType dstColorType) const {
|
||||||
// Some quick-rejects where is makes no sense to return CPU data
|
// Some quick-rejects where is makes no sense to return CPU data
|
||||||
// e.g.
|
// e.g.
|
||||||
// - texture backed
|
// - texture backed
|
||||||
@ -613,6 +625,12 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool supportsColorSpace = SupportsColorSpace(dstColorType);
|
||||||
|
// Quick reject if the caller requests a color space with an unsupported color type.
|
||||||
|
if (SkToBool(dstColorSpace) && !supportsColorSpace) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Extract relevant min/max values from the params array.
|
// Extract relevant min/max values from the params array.
|
||||||
int lowestPreScaleMipLevel = params[0].fPreScaleMipLevel;
|
int lowestPreScaleMipLevel = params[0].fPreScaleMipLevel;
|
||||||
SkFilterQuality highestFilterQuality = params[0].fQuality;
|
SkFilterQuality highestFilterQuality = params[0].fQuality;
|
||||||
@ -657,7 +675,8 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox
|
|||||||
SkAutoPixmapStorage pixmap;
|
SkAutoPixmapStorage pixmap;
|
||||||
SkImageInfo info;
|
SkImageInfo info;
|
||||||
size_t pixelSize = 0;
|
size_t pixelSize = 0;
|
||||||
if (!isScaled && this->peekPixels(&pixmap) && !pixmap.ctable()) {
|
if (!isScaled && this->peekPixels(&pixmap) && !pixmap.ctable() &&
|
||||||
|
pixmap.info().colorType() == dstColorType) {
|
||||||
info = pixmap.info();
|
info = pixmap.info();
|
||||||
pixelSize = SkAlign8(pixmap.getSafeSize());
|
pixelSize = SkAlign8(pixmap.getSafeSize());
|
||||||
if (!dstColorSpace) {
|
if (!dstColorSpace) {
|
||||||
@ -680,24 +699,35 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox
|
|||||||
info = info.makeColorSpace(nullptr);
|
info = info.makeColorSpace(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (kIndex_8_SkColorType == info.colorType()) {
|
// Force color type to be the requested type.
|
||||||
// Force Index8 to be N32 instead. Index8 is unsupported in Ganesh.
|
info = info.makeColorType(dstColorType);
|
||||||
info = info.makeColorType(kN32_SkColorType);
|
|
||||||
}
|
|
||||||
pixelSize = SkAlign8(SkAutoPixmapStorage::AllocSize(info, nullptr));
|
pixelSize = SkAlign8(SkAutoPixmapStorage::AllocSize(info, nullptr));
|
||||||
if (fillMode) {
|
if (fillMode) {
|
||||||
pixmap.alloc(info);
|
// Always decode to N32 and convert to the requested type if necessary.
|
||||||
|
SkImageInfo decodeInfo = info.makeColorType(kN32_SkColorType);
|
||||||
|
SkAutoPixmapStorage decodePixmap;
|
||||||
|
decodePixmap.alloc(decodeInfo);
|
||||||
|
|
||||||
if (isScaled) {
|
if (isScaled) {
|
||||||
if (!this->scalePixels(pixmap, scaleFilterQuality,
|
if (!this->scalePixels(decodePixmap, scaleFilterQuality,
|
||||||
SkImage::kDisallow_CachingHint)) {
|
SkImage::kDisallow_CachingHint)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!this->readPixels(pixmap, 0, 0, SkImage::kDisallow_CachingHint)) {
|
if (!this->readPixels(decodePixmap, 0, 0, SkImage::kDisallow_CachingHint)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SkASSERT(!pixmap.ctable());
|
SkASSERT(!decodePixmap.ctable());
|
||||||
|
|
||||||
|
if (decodeInfo.colorType() != info.colorType()) {
|
||||||
|
pixmap.alloc(info);
|
||||||
|
// Convert and copy the decoded pixmap to the target pixmap.
|
||||||
|
decodePixmap.readPixels(pixmap.info(), pixmap.writable_addr(), pixmap.rowBytes(), 0,
|
||||||
|
0);
|
||||||
|
} else {
|
||||||
|
pixmap = std::move(decodePixmap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int mipMapLevelCount = 1;
|
int mipMapLevelCount = 1;
|
||||||
@ -735,10 +765,11 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox
|
|||||||
SkColorSpaceTransferFn fn;
|
SkColorSpaceTransferFn fn;
|
||||||
if (info.colorSpace()) {
|
if (info.colorSpace()) {
|
||||||
SkASSERT(dstColorSpace);
|
SkASSERT(dstColorSpace);
|
||||||
|
SkASSERT(supportsColorSpace);
|
||||||
colorSpaceOffset = size;
|
colorSpaceOffset = size;
|
||||||
colorSpaceSize = info.colorSpace()->writeToMemory(nullptr);
|
colorSpaceSize = info.colorSpace()->writeToMemory(nullptr);
|
||||||
size += colorSpaceSize;
|
size += colorSpaceSize;
|
||||||
} else if (this->colorSpace() && this->colorSpace()->isNumericalTransferFn(&fn)) {
|
} else if (supportsColorSpace && this->colorSpace() && this->colorSpace()->isNumericalTransferFn(&fn)) {
|
||||||
// In legacy mode, preserve the color space tag on the SkImage. This is only
|
// In legacy mode, preserve the color space tag on the SkImage. This is only
|
||||||
// supported if the color space has a parametric transfer function.
|
// supported if the color space has a parametric transfer function.
|
||||||
SkASSERT(!dstColorSpace);
|
SkASSERT(!dstColorSpace);
|
||||||
@ -762,6 +793,7 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox
|
|||||||
SkDestinationSurfaceColorMode colorMode = SkDestinationSurfaceColorMode::kLegacy;
|
SkDestinationSurfaceColorMode colorMode = SkDestinationSurfaceColorMode::kLegacy;
|
||||||
if (proxy.fCaps->srgbSupport() && SkToBool(dstColorSpace) &&
|
if (proxy.fCaps->srgbSupport() && SkToBool(dstColorSpace) &&
|
||||||
info.colorSpace() && info.colorSpace()->gammaCloseToSRGB()) {
|
info.colorSpace() && info.colorSpace()->gammaCloseToSRGB()) {
|
||||||
|
SkASSERT(supportsColorSpace);
|
||||||
colorMode = SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware;
|
colorMode = SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1024,21 +1024,23 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredTextureImage, reporter, ctxInfo) {
|
|||||||
struct {
|
struct {
|
||||||
std::function<sk_sp<SkImage> ()> fImageFactory;
|
std::function<sk_sp<SkImage> ()> fImageFactory;
|
||||||
std::vector<SkImage::DeferredTextureImageUsageParams> fParams;
|
std::vector<SkImage::DeferredTextureImageUsageParams> fParams;
|
||||||
|
sk_sp<SkColorSpace> fColorSpace;
|
||||||
|
SkColorType fColorType;
|
||||||
SkFilterQuality fExpectedQuality;
|
SkFilterQuality fExpectedQuality;
|
||||||
int fExpectedScaleFactor;
|
int fExpectedScaleFactor;
|
||||||
bool fExpectation;
|
bool fExpectation;
|
||||||
} testCases[] = {
|
} testCases[] = {
|
||||||
{ create_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
{ create_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
||||||
kNone_SkFilterQuality, 1, true },
|
nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, true },
|
||||||
{ create_codec_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
{ create_codec_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
||||||
kNone_SkFilterQuality, 1, true },
|
nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, true },
|
||||||
{ create_data_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
{ create_data_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
||||||
kNone_SkFilterQuality, 1, true },
|
nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, true },
|
||||||
{ create_picture_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
{ create_picture_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
||||||
kNone_SkFilterQuality, 1, false },
|
nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, false },
|
||||||
{ [context] { return create_gpu_image(context); },
|
{ [context] { return create_gpu_image(context); },
|
||||||
{{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
{{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
||||||
kNone_SkFilterQuality, 1, false },
|
nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, false },
|
||||||
// Create a texture image in a another GrContext.
|
// Create a texture image in a another GrContext.
|
||||||
{ [testContext, otherContextInfo] {
|
{ [testContext, otherContextInfo] {
|
||||||
otherContextInfo.testContext()->makeCurrent();
|
otherContextInfo.testContext()->makeCurrent();
|
||||||
@ -1046,21 +1048,34 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredTextureImage, reporter, ctxInfo) {
|
|||||||
testContext->makeCurrent();
|
testContext->makeCurrent();
|
||||||
return otherContextImage;
|
return otherContextImage;
|
||||||
}, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
}, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
||||||
kNone_SkFilterQuality, 1, false },
|
nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, false },
|
||||||
// Create an image that is too large to upload.
|
// Create an image that is too large to upload.
|
||||||
{ createLarge, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
{ createLarge, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
||||||
kNone_SkFilterQuality, 1, false },
|
nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, false },
|
||||||
// Create an image that is too large, but is scaled to an acceptable size.
|
// Create an image that is too large, but is scaled to an acceptable size.
|
||||||
{ createLarge, {{SkMatrix::I(), kMedium_SkFilterQuality, 4}},
|
{ createLarge, {{SkMatrix::I(), kMedium_SkFilterQuality, 4}},
|
||||||
kMedium_SkFilterQuality, 16, true},
|
nullptr, kN32_SkColorType, kMedium_SkFilterQuality, 16, true},
|
||||||
// Create an image with multiple low filter qualities, make sure we round up.
|
// Create an image with multiple low filter qualities, make sure we round up.
|
||||||
{ createLarge, {{SkMatrix::I(), kNone_SkFilterQuality, 4},
|
{ createLarge, {{SkMatrix::I(), kNone_SkFilterQuality, 4},
|
||||||
{SkMatrix::I(), kMedium_SkFilterQuality, 4}},
|
{SkMatrix::I(), kMedium_SkFilterQuality, 4}},
|
||||||
kMedium_SkFilterQuality, 16, true},
|
nullptr, kN32_SkColorType, kMedium_SkFilterQuality, 16, true},
|
||||||
// Create an image with multiple prescale levels, make sure we chose the minimum scale.
|
// Create an image with multiple prescale levels, make sure we chose the minimum scale.
|
||||||
{ createLarge, {{SkMatrix::I(), kMedium_SkFilterQuality, 5},
|
{ createLarge, {{SkMatrix::I(), kMedium_SkFilterQuality, 5},
|
||||||
{SkMatrix::I(), kMedium_SkFilterQuality, 4}},
|
{SkMatrix::I(), kMedium_SkFilterQuality, 4}},
|
||||||
kMedium_SkFilterQuality, 16, true},
|
nullptr, kN32_SkColorType, kMedium_SkFilterQuality, 16, true},
|
||||||
|
// Create a images which are decoded to a 4444 backing.
|
||||||
|
{ create_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
||||||
|
nullptr, kARGB_4444_SkColorType, kNone_SkFilterQuality, 1, true },
|
||||||
|
{ create_codec_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
||||||
|
nullptr, kARGB_4444_SkColorType, kNone_SkFilterQuality, 1, true },
|
||||||
|
{ create_data_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
||||||
|
nullptr, kARGB_4444_SkColorType, kNone_SkFilterQuality, 1, true },
|
||||||
|
// Valid SkColorSpace and SkColorType.
|
||||||
|
{ create_data_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
||||||
|
SkColorSpace::MakeSRGB(), kN32_SkColorType, kNone_SkFilterQuality, 1, true },
|
||||||
|
// Invalid SkColorSpace and SkColorType.
|
||||||
|
{ create_data_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
|
||||||
|
SkColorSpace::MakeSRGB(), kARGB_4444_SkColorType, kNone_SkFilterQuality, 1, false },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1073,7 +1088,8 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredTextureImage, reporter, ctxInfo) {
|
|||||||
|
|
||||||
size_t size = image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
|
size_t size = image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
|
||||||
static_cast<int>(testCase.fParams.size()),
|
static_cast<int>(testCase.fParams.size()),
|
||||||
nullptr, nullptr);
|
nullptr, testCase.fColorSpace.get(),
|
||||||
|
testCase.fColorType);
|
||||||
static const char *const kFS[] = { "fail", "succeed" };
|
static const char *const kFS[] = { "fail", "succeed" };
|
||||||
if (SkToBool(size) != testCase.fExpectation) {
|
if (SkToBool(size) != testCase.fExpectation) {
|
||||||
ERRORF(reporter, "This image was expected to %s but did not.",
|
ERRORF(reporter, "This image was expected to %s but did not.",
|
||||||
@ -1084,12 +1100,14 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredTextureImage, reporter, ctxInfo) {
|
|||||||
void* misaligned = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(buffer) + 3);
|
void* misaligned = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(buffer) + 3);
|
||||||
if (image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
|
if (image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
|
||||||
static_cast<int>(testCase.fParams.size()),
|
static_cast<int>(testCase.fParams.size()),
|
||||||
misaligned, nullptr)) {
|
misaligned, testCase.fColorSpace.get(),
|
||||||
|
testCase.fColorType)) {
|
||||||
ERRORF(reporter, "Should fail when buffer is misaligned.");
|
ERRORF(reporter, "Should fail when buffer is misaligned.");
|
||||||
}
|
}
|
||||||
if (!image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
|
if (!image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
|
||||||
static_cast<int>(testCase.fParams.size()),
|
static_cast<int>(testCase.fParams.size()),
|
||||||
buffer, nullptr)) {
|
buffer, testCase.fColorSpace.get(),
|
||||||
|
testCase.fColorType)) {
|
||||||
ERRORF(reporter, "deferred image size succeeded but creation failed.");
|
ERRORF(reporter, "deferred image size succeeded but creation failed.");
|
||||||
} else {
|
} else {
|
||||||
for (auto budgeted : { SkBudgeted::kNo, SkBudgeted::kYes }) {
|
for (auto budgeted : { SkBudgeted::kNo, SkBudgeted::kYes }) {
|
||||||
|
Loading…
Reference in New Issue
Block a user