Store mipmap levels in deferred texture image
This is a follow-up to https://codereview.chromium.org/2034933003/ which was reverted due to a memory leak. When creating the deferred texture image, detect if using medium / high quality. If so, generate and store mipmaps in the deferred texture image. When creating a texture from that be sure to read it back out. BUG=578304 GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2115023002 Review-Url: https://codereview.chromium.org/2115023002
This commit is contained in:
parent
8eccc308c8
commit
d6113140f7
195
gm/deferredtextureimage.cpp
Normal file
195
gm/deferredtextureimage.cpp
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright 2016 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#include <vector>
|
||||
|
||||
#include "gm.h"
|
||||
#include "GrContext.h"
|
||||
#include "SkMipMap.h"
|
||||
#include "Resources.h"
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
|
||||
// Helper function that uploads the given SkImage using MakdeFromDeferredTextureImageData and then
|
||||
// draws the uploaded version at the specified coordinates.
|
||||
static void DrawDeferredTextureImageData(SkCanvas* canvas,
|
||||
SkImage::DeferredTextureImageUsageParams* params) {
|
||||
GrContext* context = canvas->getGrContext();
|
||||
if (!context) {
|
||||
skiagm::GM::DrawGpuOnlyMessage(canvas);
|
||||
return;
|
||||
}
|
||||
SkAutoTUnref<GrContextThreadSafeProxy> proxy(context->threadSafeProxy());
|
||||
|
||||
|
||||
|
||||
sk_sp<SkImage> encodedImage = GetResourceAsImage("mandrill_512.png");
|
||||
if (!encodedImage) {
|
||||
SkDebugf("\nCould not load resource.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t requiredMemoryInBytes = encodedImage->getDeferredTextureImageData(
|
||||
*proxy, params, 1, nullptr, SkSourceGammaTreatment::kRespect);
|
||||
if (requiredMemoryInBytes == 0) {
|
||||
SkDebugf("\nCould not create DeferredTextureImageData.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> memory;
|
||||
memory.resize(requiredMemoryInBytes);
|
||||
encodedImage->getDeferredTextureImageData(
|
||||
*proxy, params, 1, memory.data(), SkSourceGammaTreatment::kRespect);
|
||||
sk_sp<SkImage> uploadedEncodedImage = SkImage::MakeFromDeferredTextureImageData(
|
||||
context, memory.data(), SkBudgeted::kNo);
|
||||
|
||||
canvas->drawImage(uploadedEncodedImage, 10, 10);
|
||||
|
||||
|
||||
|
||||
SkBitmap bitmap;
|
||||
if (!GetResourceAsBitmap("mandrill_512.png", &bitmap)) {
|
||||
SkDebugf("\nCould not decode resource.\n");
|
||||
return;
|
||||
}
|
||||
sk_sp<SkImage> decodedImage = SkImage::MakeFromBitmap(bitmap);
|
||||
|
||||
requiredMemoryInBytes = decodedImage->getDeferredTextureImageData(
|
||||
*proxy, params, 1, nullptr, SkSourceGammaTreatment::kRespect);
|
||||
if (requiredMemoryInBytes == 0) {
|
||||
SkDebugf("\nCould not create DeferredTextureImageData.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memory.resize(requiredMemoryInBytes);
|
||||
decodedImage->getDeferredTextureImageData(
|
||||
*proxy, params, 1, memory.data(), SkSourceGammaTreatment::kRespect);
|
||||
sk_sp<SkImage> uploadedDecodedImage = SkImage::MakeFromDeferredTextureImageData(
|
||||
context, memory.data(), SkBudgeted::kNo);
|
||||
|
||||
canvas->drawImage(uploadedDecodedImage, 512 + 20, 10);
|
||||
}
|
||||
|
||||
static void DrawDeferredTextureImageMipMapTree(SkCanvas* canvas, SkImage* image,
|
||||
SkImage::DeferredTextureImageUsageParams* params) {
|
||||
GrContext* context = canvas->getGrContext();
|
||||
if (!context) {
|
||||
skiagm::GM::DrawGpuOnlyMessage(canvas);
|
||||
return;
|
||||
}
|
||||
SkAutoTUnref<GrContextThreadSafeProxy> proxy(context->threadSafeProxy());
|
||||
|
||||
SkPaint paint;
|
||||
paint.setFilterQuality(params->fQuality);
|
||||
|
||||
int mipLevelCount = SkMipMap::ComputeLevelCount(512, 512);
|
||||
size_t requiredMemoryInBytes = image->getDeferredTextureImageData(
|
||||
*proxy, params, 1, nullptr, SkSourceGammaTreatment::kRespect);
|
||||
if (requiredMemoryInBytes == 0) {
|
||||
SkDebugf("\nCould not create DeferredTextureImageData.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> memory;
|
||||
memory.resize(requiredMemoryInBytes);
|
||||
image->getDeferredTextureImageData(
|
||||
*proxy, params, 1, memory.data(), SkSourceGammaTreatment::kRespect);
|
||||
sk_sp<SkImage> uploadedImage = SkImage::MakeFromDeferredTextureImageData(
|
||||
context, memory.data(), SkBudgeted::kNo);
|
||||
|
||||
// draw a column using deferred texture images
|
||||
SkScalar offsetHeight = 10.f;
|
||||
// handle base mipmap level
|
||||
canvas->save();
|
||||
canvas->translate(10.f, offsetHeight);
|
||||
canvas->drawImage(uploadedImage, 0, 0, &paint);
|
||||
canvas->restore();
|
||||
offsetHeight += 512 + 10;
|
||||
// handle generated mipmap levels
|
||||
for (int i = 0; i < mipLevelCount; i++) {
|
||||
SkISize mipSize = SkMipMap::ComputeLevelSize(512, 512, i);
|
||||
canvas->save();
|
||||
canvas->translate(10.f, offsetHeight);
|
||||
canvas->scale(mipSize.width() / 512.f, mipSize.height() / 512.f);
|
||||
canvas->drawImage(uploadedImage, 0, 0, &paint);
|
||||
canvas->restore();
|
||||
offsetHeight += mipSize.height() + 10;
|
||||
}
|
||||
|
||||
// draw a column using SkImage
|
||||
offsetHeight = 10;
|
||||
// handle base mipmap level
|
||||
canvas->save();
|
||||
canvas->translate(512.f + 20.f, offsetHeight);
|
||||
canvas->drawImage(image, 0, 0, &paint);
|
||||
canvas->restore();
|
||||
offsetHeight += 512 + 10;
|
||||
// handle generated mipmap levels
|
||||
for (int i = 0; i < mipLevelCount; i++) {
|
||||
SkISize mipSize = SkMipMap::ComputeLevelSize(512, 512, i);
|
||||
canvas->save();
|
||||
canvas->translate(512.f + 20.f, offsetHeight);
|
||||
canvas->scale(mipSize.width() / 512.f, mipSize.height() / 512.f);
|
||||
canvas->drawImage(image, 0, 0, &paint);
|
||||
canvas->restore();
|
||||
offsetHeight += mipSize.height() + 10;
|
||||
}
|
||||
}
|
||||
|
||||
DEF_SIMPLE_GM(deferred_texture_image_default, canvas, 512 + 512 + 30, 512 + 20) {
|
||||
SkImage::DeferredTextureImageUsageParams params;
|
||||
DrawDeferredTextureImageData(canvas, ¶ms);
|
||||
}
|
||||
|
||||
DEF_SIMPLE_GM(deferred_texture_image_none, canvas, 512 + 512 + 30, 512 + 20) {
|
||||
SkImage::DeferredTextureImageUsageParams params;
|
||||
params.fPreScaleMipLevel = 0;
|
||||
params.fQuality = kNone_SkFilterQuality;
|
||||
DrawDeferredTextureImageData(canvas, ¶ms);
|
||||
}
|
||||
|
||||
DEF_SIMPLE_GM(deferred_texture_image_low, canvas, 512 + 512 + 30, 512 + 20) {
|
||||
SkImage::DeferredTextureImageUsageParams params;
|
||||
params.fPreScaleMipLevel = 0;
|
||||
params.fQuality = kLow_SkFilterQuality;
|
||||
DrawDeferredTextureImageData(canvas, ¶ms);
|
||||
}
|
||||
|
||||
DEF_SIMPLE_GM(deferred_texture_image_medium_encoded, canvas, 512 + 512 + 30, 1110) {
|
||||
sk_sp<SkImage> encodedImage = GetResourceAsImage("mandrill_512.png");
|
||||
if (!encodedImage) {
|
||||
SkDebugf("\nCould not load resource.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SkImage::DeferredTextureImageUsageParams params;
|
||||
params.fMatrix = SkMatrix::MakeScale(0.25f, 0.25f);
|
||||
params.fQuality = kMedium_SkFilterQuality;
|
||||
DrawDeferredTextureImageMipMapTree(canvas, encodedImage.get(), ¶ms);
|
||||
}
|
||||
|
||||
DEF_SIMPLE_GM(deferred_texture_image_medium_decoded, canvas, 512 + 512 + 30, 1110) {
|
||||
SkBitmap bitmap;
|
||||
if (!GetResourceAsBitmap("mandrill_512.png", &bitmap)) {
|
||||
SkDebugf("\nCould not decode resource.\n");
|
||||
return;
|
||||
}
|
||||
sk_sp<SkImage> decodedImage = SkImage::MakeFromBitmap(bitmap);
|
||||
|
||||
SkImage::DeferredTextureImageUsageParams params;
|
||||
params.fMatrix = SkMatrix::MakeScale(0.25f, 0.25f);
|
||||
params.fQuality = kMedium_SkFilterQuality;
|
||||
DrawDeferredTextureImageMipMapTree(canvas, decodedImage.get(), ¶ms);
|
||||
}
|
||||
|
||||
DEF_SIMPLE_GM(deferred_texture_image_high, canvas, 512 + 512 + 30, 512 + 20) {
|
||||
SkImage::DeferredTextureImageUsageParams params;
|
||||
params.fPreScaleMipLevel = 0;
|
||||
params.fQuality = kHigh_SkFilterQuality;
|
||||
DrawDeferredTextureImageData(canvas, ¶ms);
|
||||
}
|
||||
|
||||
#endif
|
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#include <vector>
|
||||
|
||||
#include "gm.h"
|
||||
#include "GrContext.h"
|
||||
#include "Resources.h"
|
||||
#include "SkImage.h"
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
|
||||
// Helper function that uploads the given SkImage using MakdeFromDeferredTextureImageData and then
|
||||
// draws the uploaded version at the specified coordinates.
|
||||
static bool DrawDeferredTextureImageData(GrContext* context, SkCanvas* canvas, SkImage* image,
|
||||
SkImage::DeferredTextureImageUsageParams* params,
|
||||
SkScalar x, SkScalar y) {
|
||||
SkAutoTUnref<GrContextThreadSafeProxy> proxy(context->threadSafeProxy());
|
||||
size_t deferredSize = image->getDeferredTextureImageData(*proxy, params, 1, nullptr);
|
||||
if (deferredSize == 0) {
|
||||
SkDebugf("\nCould not create DeferredTextureImageData.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> memory;
|
||||
memory.resize(deferredSize);
|
||||
image->getDeferredTextureImageData(*proxy, params, 1, memory.data());
|
||||
sk_sp<SkImage> uploadedImage =
|
||||
SkImage::MakeFromDeferredTextureImageData(context, memory.data(), SkBudgeted::kNo);
|
||||
canvas->drawImage(uploadedImage, x, y);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DEF_SIMPLE_GM(deferred_texture_image_data, canvas, 60, 10) {
|
||||
GrContext* context = canvas->getGrContext();
|
||||
if (!context) {
|
||||
skiagm::GM::DrawGpuOnlyMessage(canvas);
|
||||
return;
|
||||
}
|
||||
|
||||
sk_sp<SkImage> encodedImage = GetResourceAsImage("randPixels.png");
|
||||
if (!encodedImage) {
|
||||
SkDebugf("\nCould not load resource.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SkBitmap bitmap;
|
||||
if (!GetResourceAsBitmap("randPixels.png", &bitmap)) {
|
||||
SkDebugf("\nCould not decode resource.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sk_sp<SkImage> decodedImage = SkImage::MakeFromBitmap(bitmap);
|
||||
|
||||
// Draw both encoded and decoded image via deferredTextureImageData.
|
||||
SkImage::DeferredTextureImageUsageParams params;
|
||||
DrawDeferredTextureImageData(context, canvas, encodedImage.get(), ¶ms, 0, 0);
|
||||
DrawDeferredTextureImageData(context, canvas, decodedImage.get(), ¶ms, 10, 0);
|
||||
|
||||
// Draw 50% scaled versions of the encoded and decoded images at medium quality.
|
||||
SkImage::DeferredTextureImageUsageParams mediumScaledParams;
|
||||
mediumScaledParams.fPreScaleMipLevel = 1;
|
||||
mediumScaledParams.fQuality = kMedium_SkFilterQuality;
|
||||
|
||||
DrawDeferredTextureImageData(context, canvas, encodedImage.get(), &mediumScaledParams, 20, 0);
|
||||
DrawDeferredTextureImageData(context, canvas, decodedImage.get(), &mediumScaledParams, 30, 0);
|
||||
|
||||
// Draw 50% scaled versions of the encoded and decoded images at none quality.
|
||||
SkImage::DeferredTextureImageUsageParams noneScaledParams;
|
||||
noneScaledParams.fPreScaleMipLevel = 1;
|
||||
noneScaledParams.fQuality = kNone_SkFilterQuality;
|
||||
|
||||
DrawDeferredTextureImageData(context, canvas, encodedImage.get(), &noneScaledParams, 40, 0);
|
||||
DrawDeferredTextureImageData(context, canvas, decodedImage.get(), &noneScaledParams, 50, 0);
|
||||
}
|
||||
|
||||
#endif
|
@ -396,7 +396,9 @@ public:
|
||||
size_t getDeferredTextureImageData(const GrContextThreadSafeProxy&,
|
||||
const DeferredTextureImageUsageParams[],
|
||||
int paramCnt,
|
||||
void* buffer) const;
|
||||
void* buffer,
|
||||
SkSourceGammaTreatment treatment =
|
||||
SkSourceGammaTreatment::kIgnore) const;
|
||||
|
||||
/**
|
||||
* Returns a texture-backed image from data produced in SkImage::getDeferredTextureImageData.
|
||||
@ -469,7 +471,7 @@ protected:
|
||||
private:
|
||||
static sk_sp<SkImage> MakeTextureFromMipMap(GrContext*, const SkImageInfo&,
|
||||
const GrMipLevel* texels, int mipLevelCount,
|
||||
SkBudgeted);
|
||||
SkBudgeted, SkSourceGammaTreatment);
|
||||
|
||||
const int fWidth;
|
||||
const int fHeight;
|
||||
|
@ -395,6 +395,11 @@ sk_sp<SkImage> SkImage::MakeTextureFromPixmap(GrContext*, const SkPixmap&, SkBud
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<SkImage> MakeTextureFromMipMap(GrContext*, const SkImageInfo&, const GrMipLevel* texels,
|
||||
int mipLevelCount, SkBudgeted, SkSourceGammaTreatment) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<SkImage> SkImage::MakeFromTexture(GrContext*, const GrBackendTextureDesc&, SkAlphaType,
|
||||
sk_sp<SkColorSpace>, TextureReleaseProc, ReleaseContext) {
|
||||
return nullptr;
|
||||
@ -402,7 +407,8 @@ sk_sp<SkImage> SkImage::MakeFromTexture(GrContext*, const GrBackendTextureDesc&,
|
||||
|
||||
size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy&,
|
||||
const DeferredTextureImageUsageParams[],
|
||||
int paramCnt, void* buffer) const {
|
||||
int paramCnt, void* buffer,
|
||||
SkSourceGammaTreatment treatment) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "GrContext.h"
|
||||
#include "GrDrawContext.h"
|
||||
#include "GrImageIDTextureAdjuster.h"
|
||||
#include "GrTexturePriv.h"
|
||||
#include "effects/GrYUVEffect.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkBitmapCache.h"
|
||||
@ -364,35 +365,60 @@ struct MipMapLevelData {
|
||||
};
|
||||
|
||||
struct DeferredTextureImage {
|
||||
uint32_t fContextUniqueID;
|
||||
uint32_t fContextUniqueID;
|
||||
// Right now, the gamma treatment is only considered when generating mipmaps
|
||||
SkSourceGammaTreatment fGammaTreatment;
|
||||
// We don't store a SkImageInfo because it contains a ref-counted SkColorSpace.
|
||||
int fWidth;
|
||||
int fHeight;
|
||||
SkColorType fColorType;
|
||||
SkAlphaType fAlphaType;
|
||||
void* fColorSpace;
|
||||
size_t fColorSpaceSize;
|
||||
int fColorTableCnt;
|
||||
uint32_t* fColorTableData;
|
||||
int fMipMapLevelCount;
|
||||
int fWidth;
|
||||
int fHeight;
|
||||
SkColorType fColorType;
|
||||
SkAlphaType fAlphaType;
|
||||
void* fColorSpace;
|
||||
size_t fColorSpaceSize;
|
||||
int fColorTableCnt;
|
||||
uint32_t* fColorTableData;
|
||||
int fMipMapLevelCount;
|
||||
// The fMipMapLevelData array may contain more than 1 element.
|
||||
// It contains fMipMapLevelCount elements.
|
||||
// That means this struct's size is not known at compile-time.
|
||||
MipMapLevelData fMipMapLevelData[1];
|
||||
MipMapLevelData fMipMapLevelData[1];
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
static bool should_use_mip_maps(const SkImage::DeferredTextureImageUsageParams & param) {
|
||||
bool shouldUseMipMaps = false;
|
||||
|
||||
// Use mipmaps if either
|
||||
// 1.) it is a perspective matrix, or
|
||||
// 2.) the quality is med/high and the scale is < 1
|
||||
if (param.fMatrix.hasPerspective()) {
|
||||
shouldUseMipMaps = true;
|
||||
}
|
||||
if (param.fQuality == kMedium_SkFilterQuality ||
|
||||
param.fQuality == kHigh_SkFilterQuality) {
|
||||
SkScalar minAxisScale = param.fMatrix.getMinScale();
|
||||
if (minAxisScale != -1.f && minAxisScale < 1.f) {
|
||||
shouldUseMipMaps = true;
|
||||
}
|
||||
}
|
||||
|
||||
return shouldUseMipMaps;
|
||||
}
|
||||
|
||||
size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& proxy,
|
||||
const DeferredTextureImageUsageParams params[],
|
||||
int paramCnt, void* buffer) const {
|
||||
int paramCnt, void* buffer,
|
||||
SkSourceGammaTreatment gammaTreatment) const {
|
||||
// Extract relevant min/max values from the params array.
|
||||
int lowestPreScaleMipLevel = params[0].fPreScaleMipLevel;
|
||||
SkFilterQuality highestFilterQuality = params[0].fQuality;
|
||||
bool useMipMaps = should_use_mip_maps(params[0]);
|
||||
for (int i = 1; i < paramCnt; ++i) {
|
||||
if (lowestPreScaleMipLevel > params[i].fPreScaleMipLevel)
|
||||
lowestPreScaleMipLevel = params[i].fPreScaleMipLevel;
|
||||
if (highestFilterQuality < params[i].fQuality)
|
||||
highestFilterQuality = params[i].fQuality;
|
||||
useMipMaps |= should_use_mip_maps(params[i]);
|
||||
}
|
||||
|
||||
const bool fillMode = SkToBool(buffer);
|
||||
@ -462,7 +488,29 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox
|
||||
SkASSERT(!pixmap.ctable());
|
||||
}
|
||||
}
|
||||
SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
|
||||
int mipMapLevelCount = 1;
|
||||
if (useMipMaps) {
|
||||
// SkMipMap only deals with the mipmap levels it generates, which does
|
||||
// not include the base level.
|
||||
// That means it generates and holds levels 1-x instead of 0-x.
|
||||
// So the total mipmap level count is 1 more than what
|
||||
// SkMipMap::ComputeLevelCount returns.
|
||||
mipMapLevelCount = SkMipMap::ComputeLevelCount(scaledSize.width(), scaledSize.height()) + 1;
|
||||
|
||||
// We already initialized pixelSize to the size of the base level.
|
||||
// SkMipMap will generate the extra mipmap levels. Their sizes need to
|
||||
// be added to the total.
|
||||
// Index 0 here does not refer to the base mipmap level -- it is
|
||||
// SkMipMap's first generated mipmap level (level 1).
|
||||
for (int currentMipMapLevelIndex = mipMapLevelCount - 1; currentMipMapLevelIndex >= 0;
|
||||
currentMipMapLevelIndex--) {
|
||||
SkISize mipSize = SkMipMap::ComputeLevelSize(scaledSize.width(), scaledSize.height(),
|
||||
currentMipMapLevelIndex);
|
||||
SkImageInfo mipInfo = SkImageInfo::MakeN32(mipSize.fWidth, mipSize.fHeight, at);
|
||||
pixelSize += SkAlign8(SkAutoPixmapStorage::AllocSize(mipInfo, nullptr));
|
||||
}
|
||||
}
|
||||
size_t size = 0;
|
||||
size_t dtiSize = SkAlign8(sizeof(DeferredTextureImage));
|
||||
size += dtiSize;
|
||||
@ -496,6 +544,7 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox
|
||||
SkASSERT(info == pixmap.info());
|
||||
size_t rowBytes = pixmap.rowBytes();
|
||||
DeferredTextureImage* dti = new (buffer) DeferredTextureImage();
|
||||
dti->fGammaTreatment = gammaTreatment;
|
||||
dti->fContextUniqueID = proxy.fContextUniqueID;
|
||||
dti->fWidth = info.width();
|
||||
dti->fHeight = info.height();
|
||||
@ -514,6 +563,32 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox
|
||||
dti->fColorSpace = nullptr;
|
||||
dti->fColorSpaceSize = 0;
|
||||
}
|
||||
|
||||
// Fill in the mipmap levels if they exist
|
||||
intptr_t mipLevelPtr = bufferAsInt + pixelOffset + SkAlign8(SkAutoPixmapStorage::AllocSize(
|
||||
info, nullptr));
|
||||
if (useMipMaps) {
|
||||
SkAutoTDelete<SkMipMap> mipmaps(SkMipMap::Build(pixmap, gammaTreatment, nullptr));
|
||||
// SkMipMap holds only the mipmap levels it generates.
|
||||
// A programmer can use the data they provided to SkMipMap::Build as level 0.
|
||||
// So the SkMipMap provides levels 1-x but it stores them in its own
|
||||
// range 0-(x-1).
|
||||
for (int generatedMipLevelIndex = 0; generatedMipLevelIndex < mipMapLevelCount - 1;
|
||||
generatedMipLevelIndex++) {
|
||||
SkISize mipSize = SkMipMap::ComputeLevelSize(scaledSize.width(), scaledSize.height(),
|
||||
generatedMipLevelIndex);
|
||||
SkImageInfo mipInfo = SkImageInfo::MakeN32(mipSize.fWidth, mipSize.fHeight, at);
|
||||
SkMipMap::Level mipLevel;
|
||||
mipmaps->getLevel(generatedMipLevelIndex, &mipLevel);
|
||||
memcpy(reinterpret_cast<void*>(mipLevelPtr), mipLevel.fPixmap.addr(),
|
||||
mipLevel.fPixmap.getSafeSize());
|
||||
dti->fMipMapLevelData[generatedMipLevelIndex + 1].fPixelData =
|
||||
reinterpret_cast<void*>(mipLevelPtr);
|
||||
dti->fMipMapLevelData[generatedMipLevelIndex + 1].fRowBytes =
|
||||
mipLevel.fPixmap.rowBytes();
|
||||
mipLevelPtr += SkAlign8(mipLevel.fPixmap.getSafeSize());
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@ -532,17 +607,30 @@ sk_sp<SkImage> SkImage::MakeFromDeferredTextureImageData(GrContext* context, con
|
||||
SkASSERT(dti->fColorTableData);
|
||||
colorTable.reset(new SkColorTable(dti->fColorTableData, dti->fColorTableCnt));
|
||||
}
|
||||
SkASSERT(dti->fMipMapLevelCount == 1);
|
||||
int mipLevelCount = dti->fMipMapLevelCount;
|
||||
SkASSERT(mipLevelCount >= 1);
|
||||
sk_sp<SkColorSpace> colorSpace;
|
||||
if (dti->fColorSpaceSize) {
|
||||
colorSpace = SkColorSpace::Deserialize(dti->fColorSpace, dti->fColorSpaceSize);
|
||||
}
|
||||
SkImageInfo info = SkImageInfo::Make(dti->fWidth, dti->fHeight,
|
||||
dti->fColorType, dti->fAlphaType, colorSpace);
|
||||
SkPixmap pixmap;
|
||||
pixmap.reset(info, dti->fMipMapLevelData[0].fPixelData,
|
||||
dti->fMipMapLevelData[0].fRowBytes, colorTable.get());
|
||||
return SkImage::MakeTextureFromPixmap(context, pixmap, budgeted);
|
||||
if (mipLevelCount == 1) {
|
||||
SkPixmap pixmap;
|
||||
pixmap.reset(info, dti->fMipMapLevelData[0].fPixelData,
|
||||
dti->fMipMapLevelData[0].fRowBytes, colorTable.get());
|
||||
return SkImage::MakeTextureFromPixmap(context, pixmap, budgeted);
|
||||
} else {
|
||||
SkAutoTDeleteArray<GrMipLevel> texels(new GrMipLevel[mipLevelCount]);
|
||||
for (int i = 0; i < mipLevelCount; i++) {
|
||||
texels[i].fPixels = dti->fMipMapLevelData[i].fPixelData;
|
||||
texels[i].fRowBytes = dti->fMipMapLevelData[i].fRowBytes;
|
||||
}
|
||||
|
||||
return SkImage::MakeTextureFromMipMap(context, info, texels.get(),
|
||||
mipLevelCount, SkBudgeted::kYes,
|
||||
dti->fGammaTreatment);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -565,7 +653,8 @@ GrTexture* GrDeepCopyTexture(GrTexture* src, SkBudgeted budgeted) {
|
||||
|
||||
sk_sp<SkImage> SkImage::MakeTextureFromMipMap(GrContext* ctx, const SkImageInfo& info,
|
||||
const GrMipLevel* texels, int mipLevelCount,
|
||||
SkBudgeted budgeted) {
|
||||
SkBudgeted budgeted,
|
||||
SkSourceGammaTreatment gammaTreatment) {
|
||||
if (!ctx) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -573,6 +662,7 @@ sk_sp<SkImage> SkImage::MakeTextureFromMipMap(GrContext* ctx, const SkImageInfo&
|
||||
if (!texture) {
|
||||
return nullptr;
|
||||
}
|
||||
texture->texturePriv().setGammaTreatment(gammaTreatment);
|
||||
return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), kNeedNewImageUniqueID,
|
||||
info.alphaType(), texture, sk_ref_sp(info.colorSpace()),
|
||||
budgeted);
|
||||
|
@ -921,8 +921,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredTextureImage, reporter, ctxInfo) {
|
||||
sk_sp<SkImage> image(testCase.fImageFactory());
|
||||
size_t size = image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
|
||||
static_cast<int>(testCase.fParams.size()),
|
||||
nullptr);
|
||||
|
||||
nullptr, SkSourceGammaTreatment::kIgnore);
|
||||
static const char *const kFS[] = { "fail", "succeed" };
|
||||
if (SkToBool(size) != testCase.fExpectation) {
|
||||
ERRORF(reporter, "This image was expected to %s but did not.",
|
||||
@ -933,12 +932,12 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredTextureImage, reporter, ctxInfo) {
|
||||
void* misaligned = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(buffer) + 3);
|
||||
if (image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
|
||||
static_cast<int>(testCase.fParams.size()),
|
||||
misaligned)) {
|
||||
misaligned, SkSourceGammaTreatment::kIgnore)) {
|
||||
ERRORF(reporter, "Should fail when buffer is misaligned.");
|
||||
}
|
||||
if (!image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
|
||||
static_cast<int>(testCase.fParams.size()),
|
||||
buffer)) {
|
||||
buffer, SkSourceGammaTreatment::kIgnore)) {
|
||||
ERRORF(reporter, "deferred image size succeeded but creation failed.");
|
||||
} else {
|
||||
for (auto budgeted : { SkBudgeted::kNo, SkBudgeted::kYes }) {
|
||||
|
Loading…
Reference in New Issue
Block a user