| Index: src/gpu/SkGr.cpp
|
| diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
|
| index a23d1c8dad06443e454627201561ed067b379dad..d8444968da6ea2e788b16900fc80af3e314a1243 100644
|
| --- a/src/gpu/SkGr.cpp
|
| +++ b/src/gpu/SkGr.cpp
|
| @@ -5,13 +5,13 @@
|
| * found in the LICENSE file.
|
| */
|
|
|
| +#include "GrTextureMaker.h"
|
|
|
| #include "SkGr.h"
|
|
|
| #include "GrCaps.h"
|
| #include "GrContext.h"
|
| -#include "GrTextureParamsAdjuster.h"
|
| -#include "GrGpuResourcePriv.h"
|
| +#include "GrDrawContext.h"
|
| #include "GrXferProcessor.h"
|
| #include "GrYUVProvider.h"
|
|
|
| @@ -48,17 +48,64 @@ GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info) {
|
| return desc;
|
| }
|
|
|
| -void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& imageBounds) {
|
| - SkASSERT(key);
|
| - SkASSERT(imageID);
|
| - SkASSERT(!imageBounds.isEmpty());
|
| - static const GrUniqueKey::Domain kImageIDDomain = GrUniqueKey::GenerateDomain();
|
| - GrUniqueKey::Builder builder(key, kImageIDDomain, 5);
|
| +static void get_stretch(const GrCaps& caps, int width, int height,
|
| + const GrTextureParams& params, SkGrStretch* stretch) {
|
| + stretch->fType = SkGrStretch::kNone_Type;
|
| + bool doStretch = false;
|
| + if (params.isTiled() && !caps.npotTextureTileSupport() &&
|
| + (!SkIsPow2(width) || !SkIsPow2(height))) {
|
| + doStretch = true;
|
| + stretch->fWidth = GrNextPow2(SkTMax(width, caps.minTextureSize()));
|
| + stretch->fHeight = GrNextPow2(SkTMax(height, caps.minTextureSize()));
|
| + } else if (width < caps.minTextureSize() || height < caps.minTextureSize()) {
|
| + // The small texture issues appear to be with tiling. Hence it seems ok to scale them
|
| + // up using the GPU. If issues persist we may need to CPU-stretch.
|
| + doStretch = true;
|
| + stretch->fWidth = SkTMax(width, caps.minTextureSize());
|
| + stretch->fHeight = SkTMax(height, caps.minTextureSize());
|
| + }
|
| + if (doStretch) {
|
| + switch (params.filterMode()) {
|
| + case GrTextureParams::kNone_FilterMode:
|
| + stretch->fType = SkGrStretch::kNearest_Type;
|
| + break;
|
| + case GrTextureParams::kBilerp_FilterMode:
|
| + case GrTextureParams::kMipMap_FilterMode:
|
| + stretch->fType = SkGrStretch::kBilerp_Type;
|
| + break;
|
| + }
|
| + } else {
|
| + stretch->fWidth = -1;
|
| + stretch->fHeight = -1;
|
| + stretch->fType = SkGrStretch::kNone_Type;
|
| + }
|
| +}
|
| +
|
| +static void make_unstretched_key(GrUniqueKey* key, uint32_t imageID, const SkIRect& subset) {
|
| + SkASSERT(SkIsU16(subset.width()));
|
| + SkASSERT(SkIsU16(subset.height()));
|
| +
|
| + static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
|
| + GrUniqueKey::Builder builder(key, kDomain, 4);
|
| builder[0] = imageID;
|
| - builder[1] = imageBounds.fLeft;
|
| - builder[2] = imageBounds.fTop;
|
| - builder[3] = imageBounds.fRight;
|
| - builder[4] = imageBounds.fBottom;
|
| + builder[1] = subset.x();
|
| + builder[2] = subset.y();
|
| + builder[3] = subset.width() | (subset.height() << 16);
|
| +}
|
| +
|
| +void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& subset,
|
| + const GrCaps& caps, const GrTextureParams& params) {
|
| + SkGrStretch stretch;
|
| + get_stretch(caps, subset.width(), subset.height(), params, &stretch);
|
| + if (SkGrStretch::kNone_Type != stretch.fType) {
|
| + GrUniqueKey tmpKey;
|
| + make_unstretched_key(&tmpKey, imageID, subset);
|
| + if (!GrMakeStretchedKey(tmpKey, stretch, key)) {
|
| + *key = tmpKey;
|
| + }
|
| + } else {
|
| + make_unstretched_key(key, imageID, subset);
|
| + }
|
| }
|
|
|
| GrPixelConfig GrIsCompressedTextureDataSupported(GrContext* ctx, SkData* data,
|
| @@ -103,19 +150,16 @@ GrPixelConfig GrIsCompressedTextureDataSupported(GrContext* ctx, SkData* data,
|
| return kUnknown_GrPixelConfig;
|
| }
|
|
|
| -//////////////////////////////////////////////////////////////////////////////
|
| +/* Fill out buffer with the compressed format Ganesh expects from a colortable
|
| + based bitmap. [palette (colortable) + indices].
|
|
|
| -/**
|
| - * Fill out buffer with the compressed format Ganesh expects from a colortable
|
| - * based bitmap. [palette (colortable) + indices].
|
| - *
|
| - * At the moment Ganesh only supports 8bit version. If Ganesh allowed we others
|
| - * we could detect that the colortable.count is <= 16, and then repack the
|
| - * indices as nibbles to save RAM, but it would take more time (i.e. a lot
|
| - * slower than memcpy), so skipping that for now.
|
| - *
|
| - * Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big
|
| - * as the colortable.count says it is.
|
| + At the moment Ganesh only supports 8bit version. If Ganesh allowed we others
|
| + we could detect that the colortable.count is <= 16, and then repack the
|
| + indices as nibbles to save RAM, but it would take more time (i.e. a lot
|
| + slower than memcpy), so skipping that for now.
|
| +
|
| + Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big
|
| + as the colortable.count says it is.
|
| */
|
| static void build_index8_data(void* buffer, const SkBitmap& bitmap) {
|
| SkASSERT(kIndex_8_SkColorType == bitmap.colorType());
|
| @@ -163,7 +207,130 @@ static void build_index8_data(void* buffer, const SkBitmap& bitmap) {
|
| }
|
| }
|
|
|
| -/**
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +
|
| +
|
| +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);
|
| + static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
|
| + GrUniqueKey::Builder builder(stretchedKey, origKey, kDomain, 2);
|
| + builder[0] = stretch.fType;
|
| + builder[1] = width | (height << 16);
|
| + builder.finish();
|
| + return true;
|
| + }
|
| + SkASSERT(!stretchedKey->isValid());
|
| + return false;
|
| +}
|
| +
|
| +namespace {
|
| +
|
| +// When the SkPixelRef genID changes, invalidate a corresponding GrResource described by key.
|
| +class BitmapInvalidator : public SkPixelRef::GenIDChangeListener {
|
| +public:
|
| + explicit BitmapInvalidator(const GrUniqueKey& key) : fMsg(key) {}
|
| +private:
|
| + GrUniqueKeyInvalidatedMessage fMsg;
|
| +
|
| + void onChange() override {
|
| + SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg);
|
| + }
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +
|
| +GrTexture* GrCreateTextureForPixels(GrContext* ctx,
|
| + const GrUniqueKey& optionalKey,
|
| + GrSurfaceDesc desc,
|
| + SkPixelRef* pixelRefForInvalidationNotification,
|
| + const void* pixels,
|
| + size_t rowBytes) {
|
| + GrTexture* result = ctx->textureProvider()->createTexture(desc, true, pixels, rowBytes);
|
| + if (result && optionalKey.isValid()) {
|
| + if (pixelRefForInvalidationNotification) {
|
| + BitmapInvalidator* listener = new BitmapInvalidator(optionalKey);
|
| + pixelRefForInvalidationNotification->addGenIDChangeListener(listener);
|
| + }
|
| + ctx->textureProvider()->assignUniqueKeyToTexture(optionalKey, result);
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +// creates a new texture that is the input texture scaled up. If optionalKey is valid it will be
|
| +// set on the new texture. stretch controls whether the scaling is done using nearest or bilerp
|
| +// filtering and the size to stretch the texture to.
|
| +GrTexture* stretch_texture(GrTexture* inputTexture, const SkGrStretch& stretch,
|
| + SkPixelRef* pixelRef,
|
| + const GrUniqueKey& optionalKey) {
|
| + SkASSERT(SkGrStretch::kNone_Type != stretch.fType);
|
| +
|
| + GrContext* context = inputTexture->getContext();
|
| + SkASSERT(context);
|
| + const GrCaps* caps = context->caps();
|
| +
|
| + // Either it's a cache miss or the original wasn't cached to begin with.
|
| + GrSurfaceDesc rtDesc = inputTexture->desc();
|
| + rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag;
|
| + rtDesc.fWidth = stretch.fWidth;
|
| + rtDesc.fHeight = stretch.fHeight;
|
| + rtDesc.fConfig = GrMakePixelConfigUncompressed(rtDesc.fConfig);
|
| +
|
| + // If the config isn't renderable try converting to either A8 or an 32 bit config. Otherwise,
|
| + // fail.
|
| + if (!caps->isConfigRenderable(rtDesc.fConfig, false)) {
|
| + if (GrPixelConfigIsAlphaOnly(rtDesc.fConfig)) {
|
| + if (caps->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
|
| + rtDesc.fConfig = kAlpha_8_GrPixelConfig;
|
| + } else if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false)) {
|
| + rtDesc.fConfig = kSkia8888_GrPixelConfig;
|
| + } else {
|
| + return nullptr;
|
| + }
|
| + } else if (kRGB_GrColorComponentFlags ==
|
| + (kRGB_GrColorComponentFlags & GrPixelConfigComponentMask(rtDesc.fConfig))) {
|
| + if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false)) {
|
| + rtDesc.fConfig = kSkia8888_GrPixelConfig;
|
| + } else {
|
| + return nullptr;
|
| + }
|
| + } else {
|
| + return nullptr;
|
| + }
|
| + }
|
| +
|
| + SkAutoTUnref<GrTexture> stretched(GrCreateTextureForPixels(context, optionalKey, rtDesc,
|
| + pixelRef, nullptr,0));
|
| + if (!stretched) {
|
| + return nullptr;
|
| + }
|
| + GrPaint paint;
|
| +
|
| + // If filtering is not desired then we want to ensure all texels in the resampled image are
|
| + // copies of texels from the original.
|
| + GrTextureParams params(SkShader::kClamp_TileMode,
|
| + SkGrStretch::kBilerp_Type == stretch.fType ?
|
| + GrTextureParams::kBilerp_FilterMode :
|
| + GrTextureParams::kNone_FilterMode);
|
| + paint.addColorTextureProcessor(inputTexture, SkMatrix::I(), params);
|
| +
|
| + SkRect rect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtDesc.fHeight));
|
| + SkRect localRect = SkRect::MakeWH(1.f, 1.f);
|
| +
|
| + SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(stretched->asRenderTarget()));
|
| + if (!drawContext) {
|
| + return nullptr;
|
| + }
|
| +
|
| + drawContext->drawNonAARectToRect(GrClip::WideOpen(), paint, SkMatrix::I(), rect, localRect);
|
| +
|
| + return stretched.detach();
|
| +}
|
| +
|
| +/*
|
| * Once we have made SkImages handle all lazy/deferred/generated content, the YUV apis will
|
| * be gone from SkPixelRef, and we can remove this subclass entirely.
|
| */
|
| @@ -183,22 +350,33 @@ public:
|
| }
|
| };
|
|
|
| -static GrTexture* create_texture_from_yuv(GrContext* ctx, const SkBitmap& bm,
|
| - const GrSurfaceDesc& desc) {
|
| +static GrTexture* load_yuv_texture(GrContext* ctx, const GrUniqueKey& optionalKey,
|
| + const SkBitmap& bm, const GrSurfaceDesc& desc) {
|
| // Subsets are not supported, the whole pixelRef is loaded when using YUV decoding
|
| SkPixelRef* pixelRef = bm.pixelRef();
|
| if ((nullptr == pixelRef) ||
|
| - (pixelRef->info().width() != bm.info().width()) ||
|
| + (pixelRef->info().width() != bm.info().width()) ||
|
| (pixelRef->info().height() != bm.info().height())) {
|
| return nullptr;
|
| }
|
|
|
| + const bool useCache = optionalKey.isValid();
|
| PixelRef_GrYUVProvider provider(pixelRef);
|
| + GrTexture* texture = provider.refAsTexture(ctx, desc, useCache);
|
| + if (!texture) {
|
| + return nullptr;
|
| + }
|
|
|
| - return provider.refAsTexture(ctx, desc, !bm.isVolatile());
|
| + if (useCache) {
|
| + BitmapInvalidator* listener = new BitmapInvalidator(optionalKey);
|
| + pixelRef->addGenIDChangeListener(listener);
|
| + ctx->textureProvider()->assignUniqueKeyToTexture(optionalKey, texture);
|
| + }
|
| + return texture;
|
| }
|
|
|
| -static GrTexture* load_etc1_texture(GrContext* ctx, const SkBitmap &bm, GrSurfaceDesc desc) {
|
| +static GrTexture* load_etc1_texture(GrContext* ctx, const GrUniqueKey& optionalKey,
|
| + const SkBitmap &bm, GrSurfaceDesc desc) {
|
| SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData());
|
| if (!data) {
|
| return nullptr;
|
| @@ -211,19 +389,19 @@ static GrTexture* load_etc1_texture(GrContext* ctx, const SkBitmap &bm, GrSurfac
|
| return nullptr;
|
| }
|
|
|
| - return ctx->textureProvider()->createTexture(desc, true, startOfTexData, 0);
|
| + return GrCreateTextureForPixels(ctx, optionalKey, desc, bm.pixelRef(), startOfTexData, 0);
|
| }
|
|
|
| -GrTexture* GrUploadBitmapToTexture(GrContext* ctx, const SkBitmap& bmp) {
|
| - SkASSERT(!bmp.getTexture());
|
| -
|
| - if (bmp.width() < ctx->caps()->minTextureSize() ||
|
| - bmp.height() < ctx->caps()->minTextureSize()) {
|
| +static GrTexture* create_unstretched_bitmap_texture(GrContext* ctx,
|
| + const SkBitmap& origBitmap,
|
| + const GrUniqueKey& optionalKey) {
|
| + if (origBitmap.width() < ctx->caps()->minTextureSize() ||
|
| + origBitmap.height() < ctx->caps()->minTextureSize()) {
|
| return nullptr;
|
| }
|
| -
|
| SkBitmap tmpBitmap;
|
| - const SkBitmap* bitmap = &bmp;
|
| +
|
| + const SkBitmap* bitmap = &origBitmap;
|
|
|
| GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap->info());
|
| const GrCaps* caps = ctx->caps();
|
| @@ -233,14 +411,14 @@ GrTexture* GrUploadBitmapToTexture(GrContext* ctx, const SkBitmap& bmp) {
|
| size_t imageSize = GrCompressedFormatDataSize(kIndex_8_GrPixelConfig,
|
| bitmap->width(), bitmap->height());
|
| SkAutoMalloc storage(imageSize);
|
| - build_index8_data(storage.get(), bmp);
|
| + build_index8_data(storage.get(), origBitmap);
|
|
|
| // our compressed data will be trimmed, so pass width() for its
|
| // "rowBytes", since they are the same now.
|
| - return ctx->textureProvider()->createTexture(desc, true, storage.get(),
|
| - bitmap->width());
|
| + return GrCreateTextureForPixels(ctx, optionalKey, desc, origBitmap.pixelRef(),
|
| + storage.get(), bitmap->width());
|
| } else {
|
| - bmp.copyTo(&tmpBitmap, kN32_SkColorType);
|
| + origBitmap.copyTo(&tmpBitmap, kN32_SkColorType);
|
| // now bitmap points to our temp, which has been promoted to 32bits
|
| bitmap = &tmpBitmap;
|
| desc.fConfig = SkImageInfo2GrPixelConfig(bitmap->info());
|
| @@ -250,16 +428,13 @@ GrTexture* GrUploadBitmapToTexture(GrContext* ctx, const SkBitmap& bmp) {
|
| // compressed data on 'refEncodedData' and upload it. Probably not good, since if
|
| // the bitmap has available pixels, then they might not be what the decompressed
|
| // data is.
|
| -
|
| - // Really?? We aren't doing this with YUV.
|
| -
|
| - GrTexture *texture = load_etc1_texture(ctx, *bitmap, desc);
|
| + GrTexture *texture = load_etc1_texture(ctx, optionalKey, *bitmap, desc);
|
| if (texture) {
|
| return texture;
|
| }
|
| }
|
|
|
| - GrTexture *texture = create_texture_from_yuv(ctx, *bitmap, desc);
|
| + GrTexture *texture = load_yuv_texture(ctx, optionalKey, *bitmap, desc);
|
| if (texture) {
|
| return texture;
|
| }
|
| @@ -269,90 +444,83 @@ GrTexture* GrUploadBitmapToTexture(GrContext* ctx, const SkBitmap& bmp) {
|
| return nullptr;
|
| }
|
|
|
| - return ctx->textureProvider()->createTexture(desc, true, bitmap->getPixels(),
|
| - bitmap->rowBytes());
|
| + return GrCreateTextureForPixels(ctx, optionalKey, desc, origBitmap.pixelRef(),
|
| + bitmap->getPixels(), bitmap->rowBytes());
|
| }
|
|
|
| +static SkBitmap stretch_on_cpu(const SkBitmap& bmp, const SkGrStretch& stretch) {
|
| + SkBitmap stretched;
|
| + stretched.allocN32Pixels(stretch.fWidth, stretch.fHeight);
|
| + SkCanvas canvas(stretched);
|
| + SkPaint paint;
|
| + switch (stretch.fType) {
|
| + case SkGrStretch::kNearest_Type:
|
| + paint.setFilterQuality(kNone_SkFilterQuality);
|
| + break;
|
| + case SkGrStretch::kBilerp_Type:
|
| + paint.setFilterQuality(kLow_SkFilterQuality);
|
| + break;
|
| + case SkGrStretch::kNone_Type:
|
| + SkDEBUGFAIL("Shouldn't get here.");
|
| + break;
|
| + }
|
| + SkRect dstRect = SkRect::MakeWH(SkIntToScalar(stretch.fWidth), SkIntToScalar(stretch.fHeight));
|
| + canvas.drawBitmapRect(bmp, dstRect, &paint);
|
| + return stretched;
|
| +}
|
|
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -
|
| -class Bitmap_GrTextureParamsAdjuster : public GrTextureParamsAdjuster {
|
| +class Bitmap_GrTextureMaker : public GrTextureMaker {
|
| public:
|
| - Bitmap_GrTextureParamsAdjuster(const SkBitmap& bitmap)
|
| + Bitmap_GrTextureMaker(const SkBitmap& bitmap)
|
| : INHERITED(bitmap.width(), bitmap.height())
|
| , fBitmap(bitmap)
|
| - {
|
| - if (!bitmap.isVolatile()) {
|
| - SkIPoint origin = bitmap.pixelRefOrigin();
|
| - SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, bitmap.width(),
|
| - bitmap.height());
|
| - GrMakeKeyFromImageID(&fOriginalKey, bitmap.pixelRef()->getGenerationID(), subset);
|
| - }
|
| - }
|
| + {}
|
|
|
| protected:
|
| - GrTexture* refOriginalTexture(GrContext* ctx) override {
|
| + GrTexture* onRefUnstretchedTexture(GrContext* ctx) override {
|
| GrTexture* tex = fBitmap.getTexture();
|
| if (tex) {
|
| return SkRef(tex);
|
| }
|
|
|
| - if (fOriginalKey.isValid()) {
|
| - tex = ctx->textureProvider()->findAndRefTextureByUniqueKey(fOriginalKey);
|
| - if (tex) {
|
| - return tex;
|
| - }
|
| - }
|
| + GrUniqueKey unstretchedKey;
|
| + make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap.getSubset());
|
|
|
| - tex = GrUploadBitmapToTexture(ctx, fBitmap);
|
| - if (tex && fOriginalKey.isValid()) {
|
| - tex->resourcePriv().setUniqueKey(fOriginalKey);
|
| - InstallInvalidator(fOriginalKey, fBitmap.pixelRef());
|
| + GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey(unstretchedKey);
|
| + if (result) {
|
| + return result;
|
| }
|
| - return tex;
|
| + return create_unstretched_bitmap_texture(ctx, fBitmap, unstretchedKey);
|
| }
|
|
|
| - void makeCopyKey(const CopyParams& copyParams, GrUniqueKey* copyKey) override {
|
| - if (fOriginalKey.isValid()) {
|
| - MakeCopyKeyFromOrigKey(fOriginalKey, copyParams, copyKey);
|
| + bool onMakeStretchedKey(const SkGrStretch& stretch, GrUniqueKey* stretchedKey) override {
|
| + if (fBitmap.isVolatile()) {
|
| + return false;
|
| }
|
| +
|
| + GrUniqueKey unstretchedKey;
|
| + make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap.getSubset());
|
| + return GrMakeStretchedKey(unstretchedKey, stretch, stretchedKey);
|
| }
|
|
|
| - void didCacheCopy(const GrUniqueKey& copyKey) override {
|
| - InstallInvalidator(copyKey, fBitmap.pixelRef());
|
| + void onNotifyStretchCached(const GrUniqueKey& stretchedKey) override {
|
| + fBitmap.pixelRef()->addGenIDChangeListener(new BitmapInvalidator(stretchedKey));
|
| }
|
|
|
| - bool getROBitmap(SkBitmap* bitmap) override {
|
| - SkASSERT(!fBitmap.getTexture());
|
| + bool onGetROBitmap(SkBitmap* bitmap) override {
|
| *bitmap = fBitmap;
|
| return true;
|
| }
|
|
|
| private:
|
| - static void InstallInvalidator(const GrUniqueKey& key, SkPixelRef* pixelRef) {
|
| - class Invalidator : public SkPixelRef::GenIDChangeListener {
|
| - public:
|
| - explicit Invalidator(const GrUniqueKey& key) : fMsg(key) {}
|
| - private:
|
| - GrUniqueKeyInvalidatedMessage fMsg;
|
| -
|
| - void onChange() override {
|
| - SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg);
|
| - }
|
| - };
|
| - Invalidator* listener = new Invalidator(key);
|
| - pixelRef->addGenIDChangeListener(listener);
|
| - }
|
| + const SkBitmap fBitmap;
|
|
|
| - const SkBitmap fBitmap;
|
| - GrUniqueKey fOriginalKey;
|
| -
|
| - typedef GrTextureParamsAdjuster INHERITED;
|
| + typedef GrTextureMaker INHERITED;
|
| };
|
|
|
| GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap,
|
| const GrTextureParams& params) {
|
| - return Bitmap_GrTextureParamsAdjuster(bitmap).refTextureForParams(ctx, params);
|
| + return Bitmap_GrTextureMaker(bitmap).refCachedTexture(ctx, params);
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
| @@ -424,6 +592,7 @@ bool GrPixelConfig2ColorAndProfileType(GrPixelConfig config, SkColorType* ctOut,
|
| return true;
|
| }
|
|
|
| +
|
| ////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
| static inline bool blend_requires_shader(const SkXfermode::Mode mode, bool primitiveIsSrc) {
|
| @@ -673,3 +842,54 @@ GrTextureParams::FilterMode GrSkFilterQualityToGrFilterMode(SkFilterQuality pain
|
| }
|
| return textureFilterMode;
|
| }
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////////////////////
|
| +
|
| +GrTexture* GrTextureMaker::refCachedTexture(GrContext* ctx, const GrTextureParams& params) {
|
| + SkGrStretch stretch;
|
| + get_stretch(*ctx->caps(), this->width(), this->height(), params, &stretch);
|
| +
|
| + if (SkGrStretch::kNone_Type == stretch.fType) {
|
| + return this->onRefUnstretchedTexture(ctx);
|
| + }
|
| +
|
| + GrUniqueKey stretchedKey;
|
| + if (this->onMakeStretchedKey(stretch, &stretchedKey)) {
|
| + GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey(stretchedKey);
|
| + if (result) {
|
| + return result;
|
| + }
|
| + }
|
| +
|
| + GrTexture* result = this->onGenerateStretchedTexture(ctx, stretch);
|
| + if (!result) {
|
| + return nullptr;
|
| + }
|
| +
|
| + if (stretchedKey.isValid()) {
|
| + ctx->textureProvider()->assignUniqueKeyToTexture(stretchedKey, result);
|
| + this->onNotifyStretchCached(stretchedKey);
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +GrTexture* GrTextureMaker::onGenerateStretchedTexture(GrContext* ctx, const SkGrStretch& stretch) {
|
| + if (this->width() < ctx->caps()->minTextureSize() ||
|
| + this->height() < ctx->caps()->minTextureSize())
|
| + {
|
| + // we can't trust our ability to use HW to perform the stretch, so we request
|
| + // a raster instead, and perform the stretch on the CPU.
|
| + SkBitmap bitmap;
|
| + if (!this->onGetROBitmap(&bitmap)) {
|
| + return nullptr;
|
| + }
|
| + SkBitmap stretchedBmp = stretch_on_cpu(bitmap, stretch);
|
| + return create_unstretched_bitmap_texture(ctx, stretchedBmp, GrUniqueKey());
|
| + } else {
|
| + SkAutoTUnref<GrTexture> unstretched(this->onRefUnstretchedTexture(ctx));
|
| + if (!unstretched) {
|
| + return nullptr;
|
| + }
|
| + return stretch_texture(unstretched, stretch, nullptr, GrUniqueKey());
|
| + }
|
| +}
|
|
|