diff options
-rw-r--r-- | gyp/core.gypi | 2 | ||||
-rw-r--r-- | src/core/SkImageCacherator.cpp | 79 | ||||
-rw-r--r-- | src/core/SkImageCacherator.h | 5 | ||||
-rw-r--r-- | src/gpu/GrTextureMaker.h | 1 | ||||
-rw-r--r-- | src/gpu/SkGr.cpp | 68 | ||||
-rw-r--r-- | src/gpu/SkGrPriv.h | 10 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 12 | ||||
-rw-r--r-- | src/image/SkImage.cpp | 3 | ||||
-rw-r--r-- | src/image/SkImageShader.cpp | 144 | ||||
-rw-r--r-- | src/image/SkImageShader.h | 44 | ||||
-rw-r--r-- | src/image/SkImage_Base.h | 5 | ||||
-rw-r--r-- | src/image/SkImage_Generator.cpp | 16 | ||||
-rw-r--r-- | src/image/SkImage_Gpu.cpp | 61 | ||||
-rw-r--r-- | src/image/SkImage_Gpu.h | 3 | ||||
-rw-r--r-- | src/image/SkImage_Raster.cpp | 9 |
15 files changed, 383 insertions, 79 deletions
diff --git a/gyp/core.gypi b/gyp/core.gypi index 94711b9a3d..9459225bd8 100644 --- a/gyp/core.gypi +++ b/gyp/core.gypi @@ -255,6 +255,8 @@ '<(skia_src_path)/image/SkImage_Generator.cpp', # '<(skia_src_path)/image/SkImage_Gpu.cpp', '<(skia_src_path)/image/SkImage_Raster.cpp', + '<(skia_src_path)/image/SkImageShader.cpp', + '<(skia_src_path)/image/SkImageShader.h', '<(skia_src_path)/image/SkSurface.cpp', '<(skia_src_path)/image/SkSurface_Base.h', # '<(skia_src_path)/image/SkSurface_Gpu.cpp', diff --git a/src/core/SkImageCacherator.cpp b/src/core/SkImageCacherator.cpp index b35e053b0d..03e358a568 100644 --- a/src/core/SkImageCacherator.cpp +++ b/src/core/SkImageCacherator.cpp @@ -207,7 +207,6 @@ static GrTexture* set_key_and_return(GrTexture* tex, const GrUniqueKey& key) { tex->resourcePriv().setUniqueKey(key); return tex; } -#endif /* * We have a 5 ways to try to return a texture (in sorted order) @@ -218,13 +217,8 @@ static GrTexture* set_key_and_return(GrTexture* tex, const GrUniqueKey& key) { * 4. Ask the generator to return YUV planes, which the GPU can convert * 5. Ask the generator to return RGB(A) data, which the GPU can convert */ -GrTexture* SkImageCacherator::lockAsTexture(GrContext* ctx, SkImageUsageType usage, - const SkImage* client) { -#if SK_SUPPORT_GPU - if (!ctx) { - return nullptr; - } - +GrTexture* SkImageCacherator::lockUnstretchedTexture(GrContext* ctx, SkImageUsageType usage, + const SkImage* client) { // textures (at least the texture-key) only support 16bit dimensions, so abort early // if we're too big. if (fInfo.width() > 0xFFFF || fInfo.height() > 0xFFFF) { @@ -275,8 +269,75 @@ GrTexture* SkImageCacherator::lockAsTexture(GrContext* ctx, SkImageUsageType usa if (this->tryLockAsBitmap(&bitmap, client)) { return GrRefCachedBitmapTexture(ctx, bitmap, usage); } -#endif + return nullptr; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#include "GrTextureMaker.h" + +class Cacherator_GrTextureMaker : public GrTextureMaker { +public: + Cacherator_GrTextureMaker(SkImageCacherator* cacher, SkImageUsageType usage, + const SkImage* client, const GrUniqueKey& unstretchedKey) + : INHERITED(cacher->info().width(), cacher->info().height()) + , fCacher(cacher) + , fUsage(usage) + , fClient(client) + , fUnstretchedKey(unstretchedKey) + {} + +protected: + // TODO: consider overriding this, for the case where the underlying generator might be + // able to efficiently produce a "stretched" texture natively (e.g. picture-backed) +// GrTexture* onGenerateStretchedTexture(GrContext*, const SkGrStretch&) override; + + GrTexture* onRefUnstretchedTexture(GrContext* ctx) override { + return fCacher->lockUnstretchedTexture(ctx, fUsage, fClient); + } + + bool onMakeStretchedKey(const SkGrStretch& stretch, GrUniqueKey* stretchedKey) override { + return GrMakeStretchedKey(fUnstretchedKey, stretch, stretchedKey); + } + + void onNotifyStretchCached(const GrUniqueKey& stretchedKey) override { + if (fClient) { + as_IB(fClient)->notifyAddedToCache(); + } + } + bool onGetROBitmap(SkBitmap* bitmap) override { + return fCacher->lockAsBitmap(bitmap, fClient); + } + +private: + SkImageCacherator* fCacher; + const SkImageUsageType fUsage; + const SkImage* fClient; + const GrUniqueKey fUnstretchedKey; + + typedef GrTextureMaker INHERITED; +}; + +GrTexture* SkImageCacherator::lockAsTexture(GrContext* ctx, SkImageUsageType usage, + const SkImage* client) { + if (!ctx) { + return nullptr; + } + + GrUniqueKey key; + GrMakeKeyFromImageID(&key, this->uniqueID(), + SkIRect::MakeWH(this->info().width(), this->info().height()), + *ctx->caps(), usage); + + return Cacherator_GrTextureMaker(this, usage, client, key).refCachedTexture(ctx, usage); +} + +#else + +GrTexture* SkImageCacherator::lockAsTexture(GrContext* ctx, SkImageUsageType usage, + const SkImage* client) { return nullptr; } +#endif diff --git a/src/core/SkImageCacherator.h b/src/core/SkImageCacherator.h index 6812c72fcc..c5c65498cc 100644 --- a/src/core/SkImageCacherator.h +++ b/src/core/SkImageCacherator.h @@ -58,6 +58,9 @@ private: bool generateBitmap(SkBitmap*); bool tryLockAsBitmap(SkBitmap*, const SkImage*); +#if SK_SUPPORT_GPU + GrTexture* lockUnstretchedTexture(GrContext*, SkImageUsageType, const SkImage* client); +#endif class ScopedGenerator { SkImageCacherator* fCacher; @@ -78,6 +81,8 @@ private: const SkImageInfo fInfo; const SkIPoint fOrigin; const uint32_t fUniqueID; + + friend class Cacherator_GrTextureMaker; }; #endif diff --git a/src/gpu/GrTextureMaker.h b/src/gpu/GrTextureMaker.h index 669a7eeb08..1cbf63a029 100644 --- a/src/gpu/GrTextureMaker.h +++ b/src/gpu/GrTextureMaker.h @@ -24,6 +24,7 @@ public: int width() const { return fWidth; } int height() const { return fHeight; } + GrTexture* refCachedTexture(GrContext*, SkImageUsageType); GrTexture* refCachedTexture(GrContext*, const GrTextureParams*); protected: diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp index 7fe8fe188b..a726939788 100644 --- a/src/gpu/SkGr.cpp +++ b/src/gpu/SkGr.cpp @@ -37,6 +37,33 @@ # include "etc1.h" #endif +bool GrTextureUsageSupported(const GrCaps& caps, int width, int height, SkImageUsageType usage) { + if (caps.npotTextureTileSupport()) { + return true; + } + const bool is_pow2 = SkIsPow2(width) && SkIsPow2(height); + return is_pow2 || kUntiled_SkImageUsageType == usage; +} + +GrTextureParams GrImageUsageToTextureParams(SkImageUsageType usage) { + // Just need a params that will trigger the correct cache key / etc, since the usage doesn't + // tell us the specifics about filter level or specific tiling. + + const SkShader::TileMode tiles[] = { + SkShader::kClamp_TileMode, // kUntiled_SkImageUsageType + SkShader::kRepeat_TileMode, // kTiled_Unfiltered_SkImageUsageType + SkShader::kRepeat_TileMode, // kTiled_Filtered_SkImageUsageType + }; + + const GrTextureParams::FilterMode filters[] = { + GrTextureParams::kNone_FilterMode, // kUntiled_SkImageUsageType + GrTextureParams::kNone_FilterMode, // kTiled_Unfiltered_SkImageUsageType + GrTextureParams::kBilerp_FilterMode, // kTiled_Filtered_SkImageUsageType + }; + + return GrTextureParams(tiles[usage], filters[usage]); +} + /* Fill out buffer with the compressed format Ganesh expects from a colortable based bitmap. [palette (colortable) + indices]. @@ -133,8 +160,8 @@ static void get_stretch(const GrContext* ctx, int width, int height, } } -static bool make_stretched_key(const GrUniqueKey& origKey, const SkGrStretch& stretch, - GrUniqueKey* stretchedKey) { +bool GrMakeStretchedKey(const GrUniqueKey& origKey, const SkGrStretch& stretch, + GrUniqueKey* stretchedKey) { if (origKey.isValid() && SkGrStretch::kNone_Type != stretch.fType) { uint32_t width = SkToU16(stretch.fWidth); uint32_t height = SkToU16(stretch.fHeight); @@ -169,12 +196,7 @@ void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& sub SkGrStretch::kBilerp_Type, // kTiled_Filtered_SkImageUsageType }; - const bool isPow2 = SkIsPow2(subset.width()) && SkIsPow2(subset.height()); - const bool needToStretch = !isPow2 && - usage != kUntiled_SkImageUsageType && - !caps.npotTextureTileSupport(); - - if (needToStretch) { + if (!GrTextureUsageSupported(caps, subset.width(), subset.height(), usage)) { GrUniqueKey tmpKey; make_unstretched_key(&tmpKey, imageID, subset); @@ -182,7 +204,7 @@ void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& sub stretch.fType = stretches[usage]; stretch.fWidth = SkNextPow2(subset.width()); stretch.fHeight = SkNextPow2(subset.height()); - if (!make_stretched_key(tmpKey, stretch, key)) { + if (!GrMakeStretchedKey(tmpKey, stretch, key)) { goto UNSTRETCHED; } } else { @@ -195,7 +217,7 @@ static void make_image_keys(uint32_t imageID, const SkIRect& subset, const SkGrS GrUniqueKey* key, GrUniqueKey* stretchedKey) { make_unstretched_key(key, imageID, subset); if (SkGrStretch::kNone_Type != stretch.fType) { - make_stretched_key(*key, stretch, stretchedKey); + GrMakeStretchedKey(*key, stretch, stretchedKey); } } @@ -510,7 +532,7 @@ bool GrIsImageInCache(const GrContext* ctx, uint32_t imageID, const SkIRect& sub return false; } GrUniqueKey stretchedKey; - make_stretched_key(key, stretch, &stretchedKey); + GrMakeStretchedKey(key, stretch, &stretchedKey); return ctx->textureProvider()->existsTextureWithUniqueKey(stretchedKey); } @@ -551,7 +573,7 @@ protected: GrUniqueKey unstretchedKey; make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap.getSubset()); - return make_stretched_key(unstretchedKey, stretch, stretchedKey); + return GrMakeStretchedKey(unstretchedKey, stretch, stretchedKey); } void onNotifyStretchCached(const GrUniqueKey& stretchedKey) override { @@ -579,22 +601,7 @@ GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap, GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap, SkImageUsageType usage) { - // Just need a params that will trigger the correct cache key / etc, since the usage doesn't - // tell us the specifics about filter level or specific tiling. - - const SkShader::TileMode tiles[] = { - SkShader::kClamp_TileMode, // kUntiled_SkImageUsageType - SkShader::kRepeat_TileMode, // kTiled_Unfiltered_SkImageUsageType - SkShader::kRepeat_TileMode, // kTiled_Filtered_SkImageUsageType - }; - - const GrTextureParams::FilterMode filters[] = { - GrTextureParams::kNone_FilterMode, // kUntiled_SkImageUsageType - GrTextureParams::kNone_FilterMode, // kTiled_Unfiltered_SkImageUsageType - GrTextureParams::kBilerp_FilterMode, // kTiled_Filtered_SkImageUsageType - }; - - GrTextureParams params(tiles[usage], filters[usage]); + GrTextureParams params = GrImageUsageToTextureParams(usage); return GrRefCachedBitmapTexture(ctx, bitmap, ¶ms); } @@ -908,6 +915,11 @@ GrTextureParams::FilterMode GrSkFilterQualityToGrFilterMode(SkFilterQuality pain //////////////////////////////////////////////////////////////////////////////////////////////// +GrTexture* GrTextureMaker::refCachedTexture(GrContext* ctx, SkImageUsageType usage) { + GrTextureParams params = GrImageUsageToTextureParams(usage); + return this->refCachedTexture(ctx, ¶ms); +} + GrTexture* GrTextureMaker::refCachedTexture(GrContext* ctx, const GrTextureParams* params) { SkGrStretch stretch; get_stretch(ctx, this->width(), this->height(), params, &stretch); diff --git a/src/gpu/SkGrPriv.h b/src/gpu/SkGrPriv.h index 1564d31bc9..25fda57d9e 100644 --- a/src/gpu/SkGrPriv.h +++ b/src/gpu/SkGrPriv.h @@ -9,6 +9,7 @@ #define SkGrPriv_DEFINED #include "GrTypes.h" +#include "GrTextureAccess.h" #include "SkImageInfo.h" #include "SkXfermode.h" @@ -31,6 +32,8 @@ struct SkGrStretch { int fHeight; }; +GrTextureParams GrImageUsageToTextureParams(SkImageUsageType); + /** * Our key includes the offset, width, and height so that bitmaps created by extractSubset() * are unique. @@ -45,6 +48,11 @@ struct SkGrStretch { void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& imageBounds, const GrCaps&, SkImageUsageType); +/** + * Given an "unstretched" key, and a stretch rec, produce a stretched key. + */ +bool GrMakeStretchedKey(const GrUniqueKey& origKey, const SkGrStretch&, GrUniqueKey* stretchedKey); + /** Converts an SkPaint to a GrPaint for a given GrContext. The matrix is required in order to convert the SkShader (if any) on the SkPaint. */ bool SkPaintToGrPaint(GrContext*, @@ -76,4 +84,6 @@ bool SkPaintToGrPaintWithXfermode(GrContext* context, bool primitiveIsSrc, GrPaint* grPaint); +bool GrTextureUsageSupported(const GrCaps&, int width, int height, SkImageUsageType); + #endif diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index cb12fefc32..5388387c3b 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -2246,6 +2246,18 @@ static inline GrGLenum tile_to_gl_wrap(SkShader::TileMode tm) { void GrGLGpu::bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture) { SkASSERT(texture); +#ifdef SK_DEBUG + if (!this->caps()->npotTextureTileSupport()) { + const bool tileX = SkShader::kClamp_TileMode != params.getTileModeX(); + const bool tileY = SkShader::kClamp_TileMode != params.getTileModeY(); + if (tileX || tileY) { + const int w = texture->width(); + const int h = texture->height(); + SkASSERT(SkIsPow2(w) && SkIsPow2(h)); + } + } +#endif + // If we created a rt/tex and rendered to it without using a texture and now we're texturing // from the rt it will still be the last bound texture, but it needs resolving. So keep this // out of the "last != next" check. diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp index b639821a95..ee76a7ea39 100644 --- a/src/image/SkImage.cpp +++ b/src/image/SkImage.cpp @@ -11,6 +11,7 @@ #include "SkData.h" #include "SkImageGenerator.h" #include "SkImagePriv.h" +#include "SkImageShader.h" #include "SkImage_Base.h" #include "SkNextID.h" #include "SkPixelRef.h" @@ -69,7 +70,7 @@ void SkImage::preroll(GrContext* ctx) const { SkShader* SkImage::newShader(SkShader::TileMode tileX, SkShader::TileMode tileY, const SkMatrix* localMatrix) const { - return as_IB(this)->onNewShader(tileX, tileY, localMatrix); + return SkImageShader::Create(this, tileX, tileY, localMatrix); } SkData* SkImage::encode(SkImageEncoder::Type type, int quality) const { diff --git a/src/image/SkImageShader.cpp b/src/image/SkImageShader.cpp new file mode 100644 index 0000000000..fde0f0c9d5 --- /dev/null +++ b/src/image/SkImageShader.cpp @@ -0,0 +1,144 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkBitmapProcShader.h" +#include "SkBitmapProvider.h" +#include "SkImage_Base.h" +#include "SkImageShader.h" +#include "SkReadBuffer.h" +#include "SkWriteBuffer.h" + +SkImageShader::SkImageShader(const SkImage* img, TileMode tmx, TileMode tmy, const SkMatrix* matrix) + : INHERITED(matrix) + , fImage(SkRef(img)) + , fTileModeX(tmx) + , fTileModeY(tmy) +{} + +SkFlattenable* SkImageShader::CreateProc(SkReadBuffer& buffer) { + const TileMode tx = (TileMode)buffer.readUInt(); + const TileMode ty = (TileMode)buffer.readUInt(); + SkMatrix matrix; + buffer.readMatrix(&matrix); + SkAutoTUnref<SkImage> img(buffer.readImage()); + if (!img) { + return nullptr; + } + return new SkImageShader(img, tx, ty, &matrix); +} + +void SkImageShader::flatten(SkWriteBuffer& buffer) const { + buffer.writeUInt(fTileModeX); + buffer.writeUInt(fTileModeY); + buffer.writeMatrix(this->getLocalMatrix()); + buffer.writeImage(fImage); +} + +bool SkImageShader::isOpaque() const { + return fImage->isOpaque(); +} + +size_t SkImageShader::contextSize() const { + return SkBitmapProcShader::ContextSize(); +} + +SkShader::Context* SkImageShader::onCreateContext(const ContextRec& rec, void* storage) const { + return SkBitmapProcShader::MakeContext(*this, fTileModeX, fTileModeY, + SkBitmapProvider(fImage), rec, storage); +} + +SkShader* SkImageShader::Create(const SkImage* image, TileMode tx, TileMode ty, + const SkMatrix* localMatrix) { + if (!image) { + return nullptr; + } + return new SkImageShader(image, tx, ty, localMatrix); +} + +#ifndef SK_IGNORE_TO_STRING +void SkImageShader::toString(SkString* str) const { + const char* gTileModeName[SkShader::kTileModeCount] = { + "clamp", "repeat", "mirror" + }; + + str->appendf("ImageShader: ((%s %s) ", gTileModeName[fTileModeX], gTileModeName[fTileModeY]); + fImage->toString(str); + this->INHERITED::toString(str); + str->append(")"); +} +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#if SK_SUPPORT_GPU + +#include "GrTextureAccess.h" +#include "SkGr.h" +#include "effects/GrSimpleTextureEffect.h" +#include "effects/GrBicubicEffect.h" +#include "effects/GrSimpleTextureEffect.h" + +const GrFragmentProcessor* SkImageShader::asFragmentProcessor(GrContext* context, + const SkMatrix& viewM, + const SkMatrix* localMatrix, + SkFilterQuality filterQuality, + GrProcessorDataManager* mgr) const { + SkMatrix matrix; + matrix.setIDiv(fImage->width(), fImage->height()); + + SkMatrix lmInverse; + if (!this->getLocalMatrix().invert(&lmInverse)) { + return nullptr; + } + if (localMatrix) { + SkMatrix inv; + if (!localMatrix->invert(&inv)) { + return nullptr; + } + lmInverse.postConcat(inv); + } + matrix.preConcat(lmInverse); + + SkShader::TileMode tm[] = { fTileModeX, fTileModeY }; + + // Must set wrap and filter on the sampler before requesting a texture. In two places below + // we check the matrix scale factors to determine how to interpret the filter quality setting. + // This completely ignores the complexity of the drawVertices case where explicit local coords + // are provided by the caller. + bool doBicubic; + GrTextureParams::FilterMode textureFilterMode = + GrSkFilterQualityToGrFilterMode(filterQuality, viewM, this->getLocalMatrix(), &doBicubic); + GrTextureParams params(tm, textureFilterMode); + + SkImageUsageType usageType; + if (kClamp_TileMode == fTileModeX && kClamp_TileMode == fTileModeY) { + usageType = kUntiled_SkImageUsageType; + } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) { + usageType = kTiled_Unfiltered_SkImageUsageType; + } else { + usageType = kTiled_Filtered_SkImageUsageType; + } + + SkAutoTUnref<GrTexture> texture(as_IB(fImage)->asTextureRef(context, usageType)); + if (!texture) { + return nullptr; + } + + SkAutoTUnref<GrFragmentProcessor> inner; + if (doBicubic) { + inner.reset(GrBicubicEffect::Create(mgr, texture, matrix, tm)); + } else { + inner.reset(GrSimpleTextureEffect::Create(mgr, texture, matrix, params)); + } + + if (GrPixelConfigIsAlphaOnly(texture->config())) { + return SkRef(inner.get()); + } + return GrFragmentProcessor::MulOutputByInputAlpha(inner); +} + +#endif diff --git a/src/image/SkImageShader.h b/src/image/SkImageShader.h new file mode 100644 index 0000000000..fdd7976aad --- /dev/null +++ b/src/image/SkImageShader.h @@ -0,0 +1,44 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkImageShader_DEFINED +#define SkImageShader_DEFINED + +#include "SkImage.h" +#include "SkShader.h" + +class SkImageShader : public SkShader { +public: + static SkShader* Create(const SkImage*, TileMode tx, TileMode ty, const SkMatrix* localMatrix); + + bool isOpaque() const override; + size_t contextSize() const override; + + SK_TO_STRING_OVERRIDE() + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkImageShader) + +#if SK_SUPPORT_GPU + const GrFragmentProcessor* asFragmentProcessor(GrContext*, const SkMatrix& viewM, + const SkMatrix*, SkFilterQuality, + GrProcessorDataManager*) const override; +#endif + +protected: + void flatten(SkWriteBuffer&) const override; + Context* onCreateContext(const ContextRec&, void* storage) const override; + + SkAutoTUnref<const SkImage> fImage; + const TileMode fTileModeX; + const TileMode fTileModeY; + +private: + SkImageShader(const SkImage*, TileMode tx, TileMode ty, const SkMatrix* localMatrix); + + typedef SkShader INHERITED; +}; + +#endif diff --git a/src/image/SkImage_Base.h b/src/image/SkImage_Base.h index bbcf182ab8..757262ad3d 100644 --- a/src/image/SkImage_Base.h +++ b/src/image/SkImage_Base.h @@ -54,11 +54,8 @@ public: // Caller must call unref when they are done. virtual GrTexture* asTextureRef(GrContext*, SkImageUsageType) const = 0; - virtual SkShader* onNewShader(SkShader::TileMode, - SkShader::TileMode, - const SkMatrix* localMatrix) const { return nullptr; } - virtual SkImage* onNewSubset(const SkIRect&) const = 0; + virtual SkData* onRefEncoded() const { return nullptr; } virtual bool onAsLegacyBitmap(SkBitmap*, LegacyBitmapMode) const; diff --git a/src/image/SkImage_Generator.cpp b/src/image/SkImage_Generator.cpp index 765234fa0c..1c1b263371 100644 --- a/src/image/SkImage_Generator.cpp +++ b/src/image/SkImage_Generator.cpp @@ -28,11 +28,6 @@ public: SkImage* onNewSubset(const SkIRect&) const override; bool getROPixels(SkBitmap*) const override; GrTexture* asTextureRef(GrContext*, SkImageUsageType) const override; - - SkShader* onNewShader(SkShader::TileMode, - SkShader::TileMode, - const SkMatrix* localMatrix) const override; - bool onIsLazyGenerated() const override { return true; } private: @@ -43,17 +38,6 @@ private: /////////////////////////////////////////////////////////////////////////////// -SkShader* SkImage_Generator::onNewShader(SkShader::TileMode tileX, SkShader::TileMode tileY, - const SkMatrix* localMatrix) const { - // TODO: need a native Shader that takes Cacherator (or this image) so we can natively return - // textures as output from the shader. - SkBitmap bm; - if (this->getROPixels(&bm)) { - return SkShader::CreateBitmapShader(bm, tileX, tileY, localMatrix); - } - return nullptr; -} - bool SkImage_Generator::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB, int srcX, int srcY) const { SkBitmap bm; diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp index 1a63a0d6ba..2cc0241a48 100644 --- a/src/image/SkImage_Gpu.cpp +++ b/src/image/SkImage_Gpu.cpp @@ -7,11 +7,14 @@ #include "SkBitmapCache.h" #include "SkImage_Gpu.h" +#include "GrCaps.h" #include "GrContext.h" #include "GrDrawContext.h" +#include "GrTextureMaker.h" #include "effects/GrYUVtoRGBEffect.h" #include "SkCanvas.h" #include "SkGpuDevice.h" +#include "SkGrPriv.h" #include "SkPixelRef.h" SkImage_Gpu::SkImage_Gpu(int w, int h, uint32_t uniqueID, SkAlphaType at, GrTexture* tex, @@ -35,13 +38,6 @@ extern void SkTextureImageApplyBudgetedDecision(SkImage* image) { } } -SkShader* SkImage_Gpu::onNewShader(SkShader::TileMode tileX, SkShader::TileMode tileY, - const SkMatrix* localMatrix) const { - SkBitmap bm; - GrWrapTextureInBitmap(fTexture, this->width(), this->height(), this->isOpaque(), &bm); - return SkShader::CreateBitmapShader(bm, tileX, tileY, localMatrix); -} - bool SkImage_Gpu::getROPixels(SkBitmap* dst) const { if (SkBitmapCache::Find(this->uniqueID(), dst)) { SkASSERT(dst->getGenerationID() == this->uniqueID()); @@ -65,9 +61,56 @@ bool SkImage_Gpu::getROPixels(SkBitmap* dst) const { return true; } +static void make_raw_texture_stretched_key(uint32_t imageID, const SkGrStretch& stretch, + GrUniqueKey* stretchedKey) { + SkASSERT(SkGrStretch::kNone_Type != stretch.fType); + + uint32_t width = SkToU16(stretch.fWidth); + uint32_t height = SkToU16(stretch.fHeight); + + static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); + GrUniqueKey::Builder builder(stretchedKey, kDomain, 3); + builder[0] = imageID; + builder[1] = stretch.fType; + builder[2] = width | (height << 16); + builder.finish(); +} + +class Texture_GrTextureMaker : public GrTextureMaker { +public: + Texture_GrTextureMaker(const SkImage* image, GrTexture* unstretched) + : INHERITED(image->width(), image->height()) + , fImage(image) + , fUnstretched(unstretched) + {} + +protected: + GrTexture* onRefUnstretchedTexture(GrContext* ctx) override { + return SkRef(fUnstretched); + } + + bool onMakeStretchedKey(const SkGrStretch& stretch, GrUniqueKey* stretchedKey) override { + make_raw_texture_stretched_key(fImage->uniqueID(), stretch, stretchedKey); + return stretchedKey->isValid(); + } + + void onNotifyStretchCached(const GrUniqueKey& stretchedKey) override { + as_IB(fImage)->notifyAddedToCache(); + } + + bool onGetROBitmap(SkBitmap* bitmap) override { + return as_IB(fImage)->getROPixels(bitmap); + } + +private: + const SkImage* fImage; + GrTexture* fUnstretched; + + typedef GrTextureMaker INHERITED; +}; + GrTexture* SkImage_Gpu::asTextureRef(GrContext* ctx, SkImageUsageType usage) const { - fTexture->ref(); - return fTexture; + return Texture_GrTextureMaker(this, fTexture).refCachedTexture(ctx, usage); } bool SkImage_Gpu::isOpaque() const { diff --git a/src/image/SkImage_Gpu.h b/src/image/SkImage_Gpu.h index 5e847dd381..8bfdfa7cd8 100644 --- a/src/image/SkImage_Gpu.h +++ b/src/image/SkImage_Gpu.h @@ -40,9 +40,6 @@ public: SkImage* onNewSubset(const SkIRect&) const override; GrTexture* peekTexture() const override { return fTexture; } - SkShader* onNewShader(SkShader::TileMode, - SkShader::TileMode, - const SkMatrix* localMatrix) const override; bool isOpaque() const override; bool onReadPixels(const SkImageInfo&, void* dstPixels, size_t dstRowBytes, int srcX, int srcY) const override; diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp index 512e788a39..c88e17689c 100644 --- a/src/image/SkImage_Raster.cpp +++ b/src/image/SkImage_Raster.cpp @@ -79,10 +79,6 @@ public: SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); } - SkShader* onNewShader(SkShader::TileMode, - SkShader::TileMode, - const SkMatrix* localMatrix) const override; - bool isOpaque() const override; bool onAsLegacyBitmap(SkBitmap*, LegacyBitmapMode) const override; @@ -143,11 +139,6 @@ SkImage_Raster::SkImage_Raster(const Info& info, SkPixelRef* pr, const SkIPoint& SkImage_Raster::~SkImage_Raster() {} -SkShader* SkImage_Raster::onNewShader(SkShader::TileMode tileX, SkShader::TileMode tileY, - const SkMatrix* localMatrix) const { - return SkShader::CreateBitmapShader(fBitmap, tileX, tileY, localMatrix); -} - bool SkImage_Raster::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, int srcX, int srcY) const { SkBitmap shallowCopy(fBitmap); |