Make SkImage_Lazy::onMakeColorSpace return a SkImage_Lazy
Make SkImage_Lazy::onMakeColorSpace return a new SkImage_Lazy with the color space of SkImage_Lazy::fInfo changed. Update the call to SkImageGenerator::getPixels to specify image info with this new color space. Update the call to SkImageGenerator::generateTexture to specify this new color space. Update SkPictureImageGenerator to respect the color space argument. Add a SkTransferFunctionBehavior argument to SkImageGenerator::generateTexture to indicate if color conversion is to be doing using an xform canvas. Update Generator_GrYUVProvider::refAsTextureProxy to include a color conversion step to respect this new color space. TBR=reed@google.com Bug:739559 Change-Id: I156a858884659e9dfae739a653bab2ef89274959 Reviewed-on: https://skia-review.googlesource.com/21605 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Christopher Cameron <ccameron@chromium.org> Reviewed-by: Christopher Cameron <ccameron@google.com> Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
62ae664e74
commit
77e966647f
@ -163,7 +163,8 @@ public:
|
||||
}
|
||||
protected:
|
||||
sk_sp<GrTextureProxy> onGenerateTexture(GrContext* ctx, const SkImageInfo& info,
|
||||
const SkIPoint& origin) override {
|
||||
const SkIPoint& origin,
|
||||
SkTransferFunctionBehavior) override {
|
||||
SkASSERT(ctx);
|
||||
SkASSERT(ctx == fCtx.get());
|
||||
|
||||
|
@ -142,7 +142,8 @@ public:
|
||||
* - it can somehow convert its texture into one that is valid for the provided context.
|
||||
*/
|
||||
sk_sp<GrTextureProxy> generateTexture(GrContext*, const SkImageInfo& info,
|
||||
const SkIPoint& origin);
|
||||
const SkIPoint& origin,
|
||||
SkTransferFunctionBehavior behavior);
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -183,8 +184,8 @@ protected:
|
||||
};
|
||||
|
||||
virtual TexGenType onCanGenerateTexture() const { return TexGenType::kNone; }
|
||||
virtual sk_sp<GrTextureProxy> onGenerateTexture(GrContext*, const SkImageInfo&,
|
||||
const SkIPoint&); // returns nullptr
|
||||
virtual sk_sp<GrTextureProxy> onGenerateTexture(GrContext*, const SkImageInfo&, const SkIPoint&,
|
||||
SkTransferFunctionBehavior); // returns nullptr
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -62,9 +62,9 @@ bool SkColorSpaceXformImageGenerator::onGetPixels(const SkImageInfo& info, void*
|
||||
#include "SkGr.h"
|
||||
#include "effects/GrNonlinearColorSpaceXformEffect.h"
|
||||
|
||||
sk_sp<GrTextureProxy> SkColorSpaceXformImageGenerator::onGenerateTexture(GrContext* ctx,
|
||||
const SkImageInfo& info,
|
||||
const SkIPoint& origin) {
|
||||
sk_sp<GrTextureProxy> SkColorSpaceXformImageGenerator::onGenerateTexture(
|
||||
GrContext* ctx, const SkImageInfo& info, const SkIPoint& origin,
|
||||
SkTransferFunctionBehavior) {
|
||||
// FIXME:
|
||||
// This always operates as if SkTranferFunctionBehavior is kIgnore. Should we add
|
||||
// options so that caller can also request kRespect?
|
||||
|
@ -22,8 +22,8 @@ protected:
|
||||
const Options& opts) override;
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
sk_sp<GrTextureProxy> onGenerateTexture(GrContext*, const SkImageInfo&,
|
||||
const SkIPoint&) override;
|
||||
sk_sp<GrTextureProxy> onGenerateTexture(GrContext*, const SkImageInfo&, const SkIPoint&,
|
||||
SkTransferFunctionBehavior) override;
|
||||
TexGenType onCanGenerateTexture() const override {
|
||||
return TexGenType::kExpensive;
|
||||
}
|
||||
|
@ -65,16 +65,18 @@ bool SkImageGenerator::getYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes
|
||||
#include "GrTextureProxy.h"
|
||||
|
||||
sk_sp<GrTextureProxy> SkImageGenerator::generateTexture(GrContext* ctx, const SkImageInfo& info,
|
||||
const SkIPoint& origin) {
|
||||
const SkIPoint& origin,
|
||||
SkTransferFunctionBehavior behavior) {
|
||||
SkIRect srcRect = SkIRect::MakeXYWH(origin.x(), origin.y(), info.width(), info.height());
|
||||
if (!SkIRect::MakeWH(fInfo.width(), fInfo.height()).contains(srcRect)) {
|
||||
return nullptr;
|
||||
}
|
||||
return this->onGenerateTexture(ctx, info, origin);
|
||||
return this->onGenerateTexture(ctx, info, origin, behavior);
|
||||
}
|
||||
|
||||
sk_sp<GrTextureProxy> SkImageGenerator::onGenerateTexture(GrContext*, const SkImageInfo&,
|
||||
const SkIPoint&) {
|
||||
const SkIPoint&,
|
||||
SkTransferFunctionBehavior) {
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
@ -100,23 +100,32 @@ SkImageGenerator::MakeFromPicture(const SkISize& size, sk_sp<SkPicture> picture,
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
sk_sp<GrTextureProxy> SkPictureImageGenerator::onGenerateTexture(GrContext* ctx,
|
||||
const SkImageInfo& info,
|
||||
const SkIPoint& origin) {
|
||||
sk_sp<GrTextureProxy> SkPictureImageGenerator::onGenerateTexture(
|
||||
GrContext* ctx, const SkImageInfo& info, const SkIPoint& origin,
|
||||
SkTransferFunctionBehavior behavior) {
|
||||
SkASSERT(ctx);
|
||||
bool useXformCanvas = SkTransferFunctionBehavior::kIgnore == behavior && info.colorSpace();
|
||||
|
||||
//
|
||||
// TODO: respect the usage, by possibly creating a different (pow2) surface
|
||||
//
|
||||
sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kYes, info));
|
||||
SkImageInfo surfaceInfo = useXformCanvas ? info.makeColorSpace(nullptr) : info;
|
||||
sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kYes, surfaceInfo));
|
||||
if (!surface) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SkCanvas* canvas = surface->getCanvas();
|
||||
std::unique_ptr<SkCanvas> xformCanvas;
|
||||
if (useXformCanvas) {
|
||||
xformCanvas = SkCreateColorSpaceXformCanvas(canvas, info.refColorSpace());
|
||||
canvas = xformCanvas.get();
|
||||
}
|
||||
|
||||
SkMatrix matrix = fMatrix;
|
||||
matrix.postTranslate(-origin.x(), -origin.y());
|
||||
surface->getCanvas()->clear(0); // does NewRenderTarget promise to do this for us?
|
||||
surface->getCanvas()->drawPicture(fPicture.get(), &matrix, fPaint.getMaybeNull());
|
||||
canvas->clear(0); // does NewRenderTarget promise to do this for us?
|
||||
canvas->drawPicture(fPicture.get(), &matrix, fPaint.getMaybeNull());
|
||||
sk_sp<SkImage> image(surface->makeImageSnapshot());
|
||||
if (!image) {
|
||||
return nullptr;
|
||||
|
@ -22,8 +22,8 @@ protected:
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
TexGenType onCanGenerateTexture() const override { return TexGenType::kExpensive; }
|
||||
sk_sp<GrTextureProxy> onGenerateTexture(GrContext*, const SkImageInfo&,
|
||||
const SkIPoint&) override;
|
||||
sk_sp<GrTextureProxy> onGenerateTexture(GrContext*, const SkImageInfo&, const SkIPoint&,
|
||||
SkTransferFunctionBehavior) override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -96,9 +96,9 @@ void GrAHardwareBufferImageGenerator::deleteImageTexture(void* context) {
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
|
||||
|
||||
sk_sp<GrTextureProxy> GrAHardwareBufferImageGenerator::onGenerateTexture(
|
||||
GrContext* context, const SkImageInfo& info, const SkIPoint& origin) {
|
||||
GrContext* context, const SkImageInfo& info, const SkIPoint& origin,
|
||||
SkTransferFunctionBehavior) {
|
||||
auto proxy = this->makeProxy(context);
|
||||
if (!proxy) {
|
||||
return nullptr;
|
||||
|
@ -35,8 +35,8 @@ protected:
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
TexGenType onCanGenerateTexture() const override { return TexGenType::kCheap; }
|
||||
sk_sp<GrTextureProxy> onGenerateTexture(GrContext*, const SkImageInfo&,
|
||||
const SkIPoint&) override;
|
||||
sk_sp<GrTextureProxy> onGenerateTexture(GrContext*, const SkImageInfo&, const SkIPoint&,
|
||||
SkTransferFunctionBehavior) override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -115,7 +115,8 @@ void GrBackendTextureImageGenerator::ReleaseRefHelper_TextureReleaseProc(void* c
|
||||
}
|
||||
|
||||
sk_sp<GrTextureProxy> GrBackendTextureImageGenerator::onGenerateTexture(
|
||||
GrContext* context, const SkImageInfo& info, const SkIPoint& origin) {
|
||||
GrContext* context, const SkImageInfo& info, const SkIPoint& origin,
|
||||
SkTransferFunctionBehavior) {
|
||||
SkASSERT(context);
|
||||
|
||||
if (context->contextPriv().getBackend() != fBackendTexture.backend()) {
|
||||
|
@ -28,8 +28,8 @@ protected:
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
TexGenType onCanGenerateTexture() const override { return TexGenType::kCheap; }
|
||||
sk_sp<GrTextureProxy> onGenerateTexture(GrContext*, const SkImageInfo&,
|
||||
const SkIPoint&) override;
|
||||
sk_sp<GrTextureProxy> onGenerateTexture(GrContext*, const SkImageInfo&, const SkIPoint&,
|
||||
SkTransferFunctionBehavior) override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "SkRefCnt.h"
|
||||
#include "SkResourceCache.h"
|
||||
#include "SkYUVPlanesCache.h"
|
||||
#include "effects/GrNonlinearColorSpaceXformEffect.h"
|
||||
#include "effects/GrSRGBEffect.h"
|
||||
#include "effects/GrYUVEffect.h"
|
||||
|
||||
@ -84,9 +85,10 @@ bool YUVScoper::init(GrYUVProvider* provider, SkYUVPlanesCache::Info* yuvInfo, v
|
||||
return true;
|
||||
}
|
||||
|
||||
sk_sp<GrTextureProxy> GrYUVProvider::refAsTextureProxy(GrContext* ctx,
|
||||
const GrSurfaceDesc& desc,
|
||||
bool useCache) {
|
||||
sk_sp<GrTextureProxy> GrYUVProvider::refAsTextureProxy(GrContext* ctx, const GrSurfaceDesc& desc,
|
||||
bool useCache,
|
||||
const SkColorSpace* srcColorSpace,
|
||||
const SkColorSpace* dstColorSpace) {
|
||||
SkYUVPlanesCache::Info yuvInfo;
|
||||
void* planes[3];
|
||||
YUVScoper scoper;
|
||||
@ -153,6 +155,14 @@ sk_sp<GrTextureProxy> GrYUVProvider::refAsTextureProxy(GrContext* ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// If the caller expects the pixels in a different color space than the one from the image,
|
||||
// apply a color conversion to do this.
|
||||
sk_sp<GrFragmentProcessor> colorConversionProcessor =
|
||||
GrNonlinearColorSpaceXformEffect::Make(srcColorSpace, dstColorSpace);
|
||||
if (colorConversionProcessor) {
|
||||
paint.addColorFragmentProcessor(colorConversionProcessor);
|
||||
}
|
||||
|
||||
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
|
||||
const SkRect r = SkRect::MakeIWH(yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth,
|
||||
yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight);
|
||||
|
@ -32,11 +32,15 @@ public:
|
||||
* On success, this returns a texture proxy that has converted the YUV data from the provider
|
||||
* into a form that is supported by the GPU (typically transformed into RGB). If useCache
|
||||
* is true, then the texture will automatically have a key added, so it can be retrieved
|
||||
* from the cache (assuming it is requested by a provider w/ the same genID).
|
||||
* from the cache (assuming it is requested by a provider w/ the same genID). If srcColorSpace
|
||||
* and dstColorSpace are specified, then a color conversion from src to dst will be applied to
|
||||
* the pixels.
|
||||
*
|
||||
* On failure (e.g. the provider had no data), this returns NULL.
|
||||
*/
|
||||
sk_sp<GrTextureProxy> refAsTextureProxy(GrContext*, const GrSurfaceDesc&, bool useCache);
|
||||
sk_sp<GrTextureProxy> refAsTextureProxy(GrContext*, const GrSurfaceDesc&, bool useCache,
|
||||
const SkColorSpace* srcColorSpace,
|
||||
const SkColorSpace* dstColorSpace);
|
||||
|
||||
virtual uint32_t onGetID() = 0;
|
||||
|
||||
|
@ -55,13 +55,14 @@ private:
|
||||
class SkImage_Lazy : public SkImage_Base, public SkImageCacherator {
|
||||
public:
|
||||
struct Validator {
|
||||
Validator(sk_sp<SharedGenerator>, const SkIRect* subset);
|
||||
Validator(sk_sp<SharedGenerator>, const SkIRect* subset, sk_sp<SkColorSpace> colorSpace);
|
||||
|
||||
operator bool() const { return fSharedGenerator.get(); }
|
||||
|
||||
sk_sp<SharedGenerator> fSharedGenerator;
|
||||
SkImageInfo fInfo;
|
||||
SkIPoint fOrigin;
|
||||
sk_sp<SkColorSpace> fColorSpace;
|
||||
uint32_t fUniqueID;
|
||||
};
|
||||
|
||||
@ -131,9 +132,22 @@ private:
|
||||
* On success (true), bitmap will point to the pixels for this generator. If this returns
|
||||
* false, the bitmap will be reset to empty.
|
||||
*/
|
||||
bool lockAsBitmap(SkBitmap*, SkImage::CachingHint, CachedFormat, const SkImageInfo&) const;
|
||||
bool lockAsBitmap(SkBitmap*, SkImage::CachingHint, CachedFormat, const SkImageInfo&,
|
||||
SkTransferFunctionBehavior) const;
|
||||
|
||||
/**
|
||||
* Populates parameters to pass to the generator for reading pixels or generating a texture.
|
||||
* For image generators, legacy versus true color blending is indicated using a
|
||||
* SkTransferFunctionBehavior, and the target color space is specified on the SkImageInfo.
|
||||
* If generatorImageInfo has no color space set, set its color space to this SkImage's color
|
||||
* space, and return "ignore" behavior, indicating legacy mode. If generatorImageInfo has a
|
||||
* color space set, return "respect" behavior, indicating linear blending mode.
|
||||
*/
|
||||
SkTransferFunctionBehavior getGeneratorBehaviorAndInfo(SkImageInfo* generatorImageInfo) const;
|
||||
|
||||
sk_sp<SharedGenerator> fSharedGenerator;
|
||||
// Note that fInfo is not necessarily the info from the generator. It may be cropped by
|
||||
// onMakeSubset and its color space may be changed by onMakeColorSpace.
|
||||
const SkImageInfo fInfo;
|
||||
const SkIPoint fOrigin;
|
||||
|
||||
@ -150,9 +164,9 @@ private:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkImage_Lazy::Validator::Validator(sk_sp<SharedGenerator> gen, const SkIRect* subset)
|
||||
SkImage_Lazy::Validator::Validator(sk_sp<SharedGenerator> gen, const SkIRect* subset,
|
||||
sk_sp<SkColorSpace> colorSpace)
|
||||
: fSharedGenerator(std::move(gen)) {
|
||||
|
||||
if (!fSharedGenerator) {
|
||||
return;
|
||||
}
|
||||
@ -182,6 +196,10 @@ SkImage_Lazy::Validator::Validator(sk_sp<SharedGenerator> gen, const SkIRect* su
|
||||
|
||||
fInfo = info.makeWH(subset->width(), subset->height());
|
||||
fOrigin = SkIPoint::Make(subset->x(), subset->y());
|
||||
if (colorSpace) {
|
||||
fInfo = fInfo.makeColorSpace(colorSpace);
|
||||
fUniqueID = SkNextID::ImageID();
|
||||
}
|
||||
|
||||
// colortables are poorly to not-at-all supported in our resourcecache, so we
|
||||
// bully them into N32 (the generator will perform the up-sample)
|
||||
@ -421,7 +439,8 @@ bool SkImage_Lazy::directGeneratePixels(const SkImageInfo& info, void* pixels, s
|
||||
}
|
||||
|
||||
SkImageGenerator::Options opts;
|
||||
opts.fBehavior = behavior;
|
||||
// TODO: This should respect the behavior argument.
|
||||
opts.fBehavior = SkTransferFunctionBehavior::kIgnore;
|
||||
return generator->getPixels(info, pixels, rb, &opts);
|
||||
}
|
||||
|
||||
@ -434,7 +453,8 @@ bool SkImage_Lazy::lockAsBitmapOnlyIfAlreadyCached(SkBitmap* bitmap, CachedForma
|
||||
check_output_bitmap(*bitmap, uniqueID);
|
||||
}
|
||||
|
||||
static bool generate_pixels(SkImageGenerator* gen, const SkPixmap& pmap, int originX, int originY) {
|
||||
static bool generate_pixels(SkImageGenerator* gen, const SkPixmap& pmap, int originX, int originY,
|
||||
SkTransferFunctionBehavior behavior) {
|
||||
const int genW = gen->getInfo().width();
|
||||
const int genH = gen->getInfo().height();
|
||||
const SkIRect srcR = SkIRect::MakeWH(genW, genH);
|
||||
@ -458,7 +478,9 @@ static bool generate_pixels(SkImageGenerator* gen, const SkPixmap& pmap, int ori
|
||||
dstPM = &fullPM;
|
||||
}
|
||||
|
||||
if (!gen->getPixels(dstPM->info(), dstPM->writable_addr(), dstPM->rowBytes())) {
|
||||
SkImageGenerator::Options opts;
|
||||
opts.fBehavior = behavior;
|
||||
if (!gen->getPixels(dstPM->info(), dstPM->writable_addr(), dstPM->rowBytes(), &opts)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -470,8 +492,9 @@ static bool generate_pixels(SkImageGenerator* gen, const SkPixmap& pmap, int ori
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkImage_Lazy::lockAsBitmap(SkBitmap* bitmap, SkImage::CachingHint chint,
|
||||
CachedFormat format, const SkImageInfo& info) const {
|
||||
bool SkImage_Lazy::lockAsBitmap(SkBitmap* bitmap, SkImage::CachingHint chint, CachedFormat format,
|
||||
const SkImageInfo& info,
|
||||
SkTransferFunctionBehavior behavior) const {
|
||||
if (this->lockAsBitmapOnlyIfAlreadyCached(bitmap, format)) {
|
||||
return true;
|
||||
}
|
||||
@ -497,7 +520,7 @@ bool SkImage_Lazy::lockAsBitmap(SkBitmap* bitmap, SkImage::CachingHint chint,
|
||||
}
|
||||
|
||||
ScopedGenerator generator(fSharedGenerator);
|
||||
if (!generate_pixels(generator, pmap, fOrigin.x(), fOrigin.y())) {
|
||||
if (!generate_pixels(generator, pmap, fOrigin.x(), fOrigin.y(), behavior)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -524,14 +547,15 @@ bool SkImage_Lazy::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, siz
|
||||
SkBitmap bm;
|
||||
if (kDisallow_CachingHint == chint) {
|
||||
CachedFormat cacheFormat = this->chooseCacheFormat(dstColorSpace);
|
||||
SkImageInfo genPixelsInfo = dstInfo;
|
||||
SkTransferFunctionBehavior behavior = getGeneratorBehaviorAndInfo(&genPixelsInfo);
|
||||
if (this->lockAsBitmapOnlyIfAlreadyCached(&bm, cacheFormat)) {
|
||||
return bm.readPixels(dstInfo, dstPixels, dstRB, srcX, srcY);
|
||||
} else {
|
||||
// Try passing the caller's buffer directly down to the generator. If this fails we
|
||||
// may still succeed in the general case, as the generator may prefer some other
|
||||
// config, which we could then convert via SkBitmap::readPixels.
|
||||
if (this->directGeneratePixels(dstInfo, dstPixels, dstRB, srcX, srcY,
|
||||
SkTransferFunctionBehavior::kRespect)) {
|
||||
if (this->directGeneratePixels(genPixelsInfo, dstPixels, dstRB, srcX, srcY, behavior)) {
|
||||
return true;
|
||||
}
|
||||
// else fall through
|
||||
@ -552,8 +576,10 @@ SkData* SkImage_Lazy::onRefEncoded() const {
|
||||
bool SkImage_Lazy::getROPixels(SkBitmap* bitmap, SkColorSpace* dstColorSpace,
|
||||
CachingHint chint) const {
|
||||
CachedFormat cacheFormat = this->chooseCacheFormat(dstColorSpace);
|
||||
SkImageInfo cacheInfo = this->buildCacheInfo(cacheFormat);
|
||||
return this->lockAsBitmap(bitmap, chint, cacheFormat, cacheInfo);
|
||||
const SkImageInfo cacheInfo = this->buildCacheInfo(cacheFormat);
|
||||
SkImageInfo genPixelsInfo = cacheInfo;
|
||||
SkTransferFunctionBehavior behavior = getGeneratorBehaviorAndInfo(&genPixelsInfo);
|
||||
return this->lockAsBitmap(bitmap, chint, cacheFormat, genPixelsInfo, behavior);
|
||||
}
|
||||
|
||||
bool SkImage_Lazy::onIsValid(GrContext* context) const {
|
||||
@ -570,6 +596,24 @@ bool SkImage_Lazy::onCanLazyGenerateOnGPU() const {
|
||||
#endif
|
||||
}
|
||||
|
||||
SkTransferFunctionBehavior SkImage_Lazy::getGeneratorBehaviorAndInfo(SkImageInfo* generatorImageInfo) const {
|
||||
if (generatorImageInfo->colorSpace()) {
|
||||
return SkTransferFunctionBehavior::kRespect;
|
||||
}
|
||||
// Only specify an output color space if color conversion can be done on the color type.
|
||||
switch (generatorImageInfo->colorType()) {
|
||||
case kRGBA_8888_SkColorType:
|
||||
case kBGRA_8888_SkColorType:
|
||||
case kRGBA_F16_SkColorType:
|
||||
case kRGB_565_SkColorType:
|
||||
*generatorImageInfo = generatorImageInfo->makeColorSpace(fInfo.refColorSpace());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return SkTransferFunctionBehavior::kIgnore;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
@ -592,37 +636,22 @@ sk_sp<SkImage> SkImage_Lazy::onMakeSubset(const SkIRect& subset) const {
|
||||
SkASSERT(fInfo.bounds() != subset);
|
||||
|
||||
const SkIRect generatorSubset = subset.makeOffset(fOrigin.x(), fOrigin.y());
|
||||
Validator validator(fSharedGenerator, &generatorSubset);
|
||||
Validator validator(fSharedGenerator, &generatorSubset, fInfo.refColorSpace());
|
||||
return validator ? sk_sp<SkImage>(new SkImage_Lazy(&validator)) : nullptr;
|
||||
}
|
||||
|
||||
sk_sp<SkImage> SkImage_Lazy::onMakeColorSpace(sk_sp<SkColorSpace> target,
|
||||
SkColorType targetColorType,
|
||||
SkTransferFunctionBehavior premulBehavior) const {
|
||||
SkBitmap dst;
|
||||
const SkImageInfo& genInfo = fSharedGenerator->getInfo();
|
||||
SkImageInfo dstInfo = genInfo.makeColorType(targetColorType).makeColorSpace(target);
|
||||
dst.allocPixels(dstInfo);
|
||||
if (!this->directGeneratePixels(dstInfo, dst.getPixels(), dst.rowBytes(), 0, 0,
|
||||
premulBehavior)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
dst.setImmutable();
|
||||
sk_sp<SkImage> image = SkImage::MakeFromBitmap(dst);
|
||||
|
||||
if (genInfo.dimensions() != fInfo.dimensions()) {
|
||||
// This image must be a subset.
|
||||
image = image->makeSubset(SkIRect::MakeXYWH(fOrigin.fX, fOrigin.fY,
|
||||
fInfo.width(), fInfo.height()));
|
||||
}
|
||||
|
||||
return image;
|
||||
const SkIRect generatorSubset =
|
||||
SkIRect::MakeXYWH(fOrigin.x(), fOrigin.y(), fInfo.width(), fInfo.height());
|
||||
Validator validator(fSharedGenerator, &generatorSubset, target);
|
||||
return validator ? sk_sp<SkImage>(new SkImage_Lazy(&validator)) : nullptr;
|
||||
}
|
||||
|
||||
sk_sp<SkImage> SkImage::MakeFromGenerator(std::unique_ptr<SkImageGenerator> generator,
|
||||
const SkIRect* subset) {
|
||||
SkImage_Lazy::Validator validator(SharedGenerator::Make(std::move(generator)), subset);
|
||||
SkImage_Lazy::Validator validator(SharedGenerator::Make(std::move(generator)), subset, nullptr);
|
||||
|
||||
return validator ? sk_make_sp<SkImage_Lazy>(&validator) : nullptr;
|
||||
}
|
||||
@ -723,7 +752,9 @@ sk_sp<GrTextureProxy> SkImage_Lazy::lockTextureProxy(GrContext* ctx,
|
||||
// The CachedFormat is both an index for which cache "slot" we'll use to store this particular
|
||||
// decoded variant of the encoded data, and also a recipe for how to transform the original
|
||||
// info to get the one that we're going to decode to.
|
||||
SkImageInfo cacheInfo = this->buildCacheInfo(format);
|
||||
const SkImageInfo cacheInfo = this->buildCacheInfo(format);
|
||||
SkImageInfo genPixelsInfo = cacheInfo;
|
||||
SkTransferFunctionBehavior behavior = getGeneratorBehaviorAndInfo(&genPixelsInfo);
|
||||
|
||||
// 2. Ask the generator to natively create one
|
||||
{
|
||||
@ -732,7 +763,8 @@ sk_sp<GrTextureProxy> SkImage_Lazy::lockTextureProxy(GrContext* ctx,
|
||||
SkImageGenerator::TexGenType::kCheap != generator->onCanGenerateTexture()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (sk_sp<GrTextureProxy> proxy = generator->generateTexture(ctx, cacheInfo, fOrigin)) {
|
||||
if (sk_sp<GrTextureProxy> proxy =
|
||||
generator->generateTexture(ctx, genPixelsInfo, fOrigin, behavior)) {
|
||||
SK_HISTOGRAM_ENUMERATION("LockTexturePath", kNative_LockTexturePath,
|
||||
kLockTexturePathCount);
|
||||
set_key_on_proxy(ctx->resourceProvider(), proxy.get(), key);
|
||||
@ -745,7 +777,17 @@ sk_sp<GrTextureProxy> SkImage_Lazy::lockTextureProxy(GrContext* ctx,
|
||||
const GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(cacheInfo, *ctx->caps());
|
||||
ScopedGenerator generator(fSharedGenerator);
|
||||
Generator_GrYUVProvider provider(generator);
|
||||
if (sk_sp<GrTextureProxy> proxy = provider.refAsTextureProxy(ctx, desc, true)) {
|
||||
|
||||
// The pixels in the texture will be in the generator's color space. If onMakeColorSpace
|
||||
// has been called then this will not match this image's color space. To correct this, apply
|
||||
// a color space conversion from the generator's color space to this image's color space.
|
||||
const SkColorSpace* generatorColorSpace =
|
||||
fSharedGenerator->fGenerator->getInfo().colorSpace();
|
||||
const SkColorSpace* thisColorSpace = fInfo.colorSpace();
|
||||
|
||||
sk_sp<GrTextureProxy> proxy =
|
||||
provider.refAsTextureProxy(ctx, desc, true, generatorColorSpace, thisColorSpace);
|
||||
if (proxy) {
|
||||
SK_HISTOGRAM_ENUMERATION("LockTexturePath", kYUV_LockTexturePath,
|
||||
kLockTexturePathCount);
|
||||
set_key_on_proxy(ctx->resourceProvider(), proxy.get(), key);
|
||||
@ -755,7 +797,7 @@ sk_sp<GrTextureProxy> SkImage_Lazy::lockTextureProxy(GrContext* ctx,
|
||||
|
||||
// 4. Ask the generator to return RGB(A) data, which the GPU can convert
|
||||
SkBitmap bitmap;
|
||||
if (this->lockAsBitmap(&bitmap, chint, format, cacheInfo)) {
|
||||
if (this->lockAsBitmap(&bitmap, chint, format, genPixelsInfo, behavior)) {
|
||||
sk_sp<GrTextureProxy> proxy;
|
||||
if (willBeMipped) {
|
||||
proxy = GrGenerateMipMapsAndUploadToTextureProxy(ctx, bitmap, dstColorSpace);
|
||||
|
Loading…
Reference in New Issue
Block a user