Add SkBudgeted parameter to SkImage::makeTextureImage().

Also strengthens/adds some guarantees about this function:
* Always returns the same image if the original is texture-backed and
compatible with GrMipMapped (WRT HW MIP support)
* If a new texture backed image is returned it is always an uncached
texture that is not shared with another image or owned by an image
generator.

Adds a GrImageTexGenPolicy that allows control through image/bitmap
GrTextureProducers of whether a new texture must be made and whether
that texture should be budgeted or not.

Increases unit test coverage of this API.

Bug: skia:8669

Change-Id: Ifc0681856114a08fc8cfc57ca83d22efb1c1f166
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/274938
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Salomon 2020-03-18 10:06:13 -04:00 committed by Skia Commit-Bot
parent 0b1e5fc8f2
commit bc074a68df
47 changed files with 315 additions and 213 deletions

View File

@ -7,6 +7,7 @@ This file includes a list of high level updates for each milestone release.
Milestone 83
<Insert new notes here- top is most recent.>
* SkImage::makeTextureImage() takes an optional SkBudgeted param
*

View File

@ -82,7 +82,7 @@ DEF_SIMPLE_GPU_GM_BG(fpcoordinateoverride, ctx, rtCtx, canvas, 512, 512,
SkBitmap bmp;
GetResourceAsBitmap("images/mandrill_512_q075.jpg", &bmp);
GrBitmapTextureMaker maker(ctx, bmp);
GrBitmapTextureMaker maker(ctx, bmp, GrImageTexGenPolicy::kDraw);
auto view = maker.view(GrMipMapped::kNo);
if (!view) {
return;

View File

@ -184,7 +184,8 @@ public:
}
protected:
GrSurfaceProxyView onGenerateTexture(GrRecordingContext* ctx, const SkImageInfo& info,
const SkIPoint& origin, GrMipMapped mipMapped) override {
const SkIPoint& origin, GrMipMapped mipMapped,
GrImageTexGenPolicy) override {
SkASSERT(ctx);
SkASSERT(ctx == fCtx.get());

View File

@ -80,7 +80,7 @@ protected:
GrMipMapped mipMapped = fFilter == GrSamplerState::Filter::kMipMap &&
context->priv().caps()->mipMapSupport()
? GrMipMapped::kYes : GrMipMapped::kNo;
GrBitmapTextureMaker maker(context, fBitmap);
GrBitmapTextureMaker maker(context, fBitmap, GrImageTexGenPolicy::kDraw);
auto view = maker.view(mipMapped);
if (!view) {
*errorMsg = "Failed to create proxy.";
@ -114,7 +114,7 @@ protected:
SkBitmap subsetBmp;
fBitmap.extractSubset(&subsetBmp, texelSubset);
subsetBmp.setImmutable();
GrBitmapTextureMaker subsetMaker(context, subsetBmp);
GrBitmapTextureMaker subsetMaker(context, subsetBmp, GrImageTexGenPolicy::kDraw);
auto subsetView = subsetMaker.view(mipMapped);
SkRect localRect = SkRect::Make(fBitmap.bounds()).makeOutset(kDrawPad, kDrawPad);

View File

@ -98,7 +98,7 @@ protected:
GrSurfaceProxyView views[3];
for (int i = 0; i < 3; ++i) {
GrBitmapTextureMaker maker(context, fBitmaps[i]);
GrBitmapTextureMaker maker(context, fBitmaps[i], GrImageTexGenPolicy::kDraw);
views[i] = maker.view(GrMipMapped::kNo);
if (!views[i]) {
*errorMsg = "Failed to create proxy";
@ -214,7 +214,7 @@ protected:
GrSurfaceProxyView views[2];
for (int i = 0; i < 2; ++i) {
GrBitmapTextureMaker maker(context, fBitmaps[i]);
GrBitmapTextureMaker maker(context, fBitmaps[i], GrImageTexGenPolicy::kDraw);
views[i] = maker.view(GrMipMapped::kNo);
if (!views[i]) {
*errorMsg = "Failed to create proxy";
@ -315,7 +315,7 @@ protected:
GrSurfaceProxyView views[3];
for (int i = 0; i < 3; ++i) {
GrBitmapTextureMaker maker(context, fBitmaps[i]);
GrBitmapTextureMaker maker(context, fBitmaps[i], GrImageTexGenPolicy::kDraw);
views[i] = maker.view(GrMipMapped::kNo);
if (!views[i]) {
*errorMsg = "Failed to create proxy";

View File

@ -1035,18 +1035,26 @@ public:
/** Returns SkImage backed by GPU texture associated with context. Returned SkImage is
compatible with SkSurface created with dstColorSpace. The returned SkImage respects
mipMapped setting; if mipMapped equals GrMipMapped::kYes, the backing texture
allocates mip map levels. Returns original SkImage if context
and dstColorSpace match and mipMapped is compatible with backing GPU texture.
allocates mip map levels.
The mipMapped parameter is effectively treated as kNo if MIP maps are not supported by the
GPU.
Returns original SkImage if the image is already texture-backed, the context matches, and
mipMapped is compatible with the backing GPU texture. SkBudgeted is ignored in this case.
Returns nullptr if context is nullptr, or if SkImage was created with another
GrContext.
@param context GPU context
@param dstColorSpace range of colors of matching SkSurface on GPU
@param mipMapped whether created SkImage texture must allocate mip map levels
@param GrContext GPU context
@param GrMipMapped whether created SkImage texture must allocate mip map levels
@param SkBudgeted whether to count a newly created texture for the returned image
counts against the GrContext's budget.
@return created SkImage, or nullptr
*/
sk_sp<SkImage> makeTextureImage(GrContext* context, GrMipMapped = GrMipMapped::kNo) const;
sk_sp<SkImage> makeTextureImage(GrContext*,
GrMipMapped = GrMipMapped::kNo,
SkBudgeted = SkBudgeted::kYes) const;
/** Returns raster image or lazy image. Copies SkImage backed by GPU texture into
CPU memory if needed. Returns original SkImage if decoded in raster bitmap,

View File

@ -24,6 +24,8 @@ class SkMatrix;
class SkPaint;
class SkPicture;
enum class GrImageTexGenPolicy : int;
class SK_API SkImageGenerator {
public:
/**
@ -138,9 +140,13 @@ public:
* at least has the mip levels allocated and the base layer filled in. If this is not possible,
* the generator is allowed to return a non mipped proxy, but this will have some additional
* overhead in later allocating mips and copying of the base layer.
*
* GrImageTexGenPolicy determines whether or not a new texture must be created (and its budget
* status) or whether this may (but is not required to) return a pre-existing texture that is
* retained by the generator (kDraw).
*/
GrSurfaceProxyView generateTexture(GrRecordingContext*, const SkImageInfo& info,
const SkIPoint& origin, GrMipMapped);
const SkIPoint& origin, GrMipMapped, GrImageTexGenPolicy);
#endif
@ -175,14 +181,9 @@ protected:
virtual bool onGetYUVA8Planes(const SkYUVASizeInfo&, const SkYUVAIndex[SkYUVAIndex::kIndexCount],
void*[4] /*planes*/) { return false; }
#if SK_SUPPORT_GPU
enum class TexGenType {
kNone, //image generator does not implement onGenerateTexture
kCheap, //onGenerateTexture is implemented and it is fast (does not render offscreen)
kExpensive, //onGenerateTexture is implemented and it is relatively slow
};
// returns nullptr
virtual GrSurfaceProxyView onGenerateTexture(GrRecordingContext*, const SkImageInfo&,
const SkIPoint&, GrMipMapped); // returns nullptr
const SkIPoint&, GrMipMapped, GrImageTexGenPolicy);
#endif
private:

View File

@ -64,18 +64,20 @@ bool SkImageGenerator::getYUVA8Planes(const SkYUVASizeInfo& sizeInfo,
GrSurfaceProxyView SkImageGenerator::generateTexture(GrRecordingContext* ctx,
const SkImageInfo& info,
const SkIPoint& origin,
GrMipMapped mipMapped) {
GrMipMapped mipMapped,
GrImageTexGenPolicy texGenPolicy) {
SkIRect srcRect = SkIRect::MakeXYWH(origin.x(), origin.y(), info.width(), info.height());
if (!SkIRect::MakeWH(fInfo.width(), fInfo.height()).contains(srcRect)) {
return {};
}
return this->onGenerateTexture(ctx, info, origin, mipMapped);
return this->onGenerateTexture(ctx, info, origin, mipMapped, texGenPolicy);
}
GrSurfaceProxyView SkImageGenerator::onGenerateTexture(GrRecordingContext*,
const SkImageInfo&,
const SkIPoint&,
GrMipMapped) {
GrMipMapped,
GrImageTexGenPolicy) {
return {};
}
#endif

View File

@ -12,6 +12,7 @@
#include "include/core/SkPicture.h"
#include "include/core/SkSurface.h"
#include "src/core/SkTLazy.h"
#include "src/gpu/SkGr.h"
#include "src/image/SkImage_Base.h"
class SkPictureImageGenerator : public SkImageGenerator {
@ -25,7 +26,7 @@ protected:
#if SK_SUPPORT_GPU
GrSurfaceProxyView onGenerateTexture(GrRecordingContext*, const SkImageInfo&, const SkIPoint&,
GrMipMapped) override;
GrMipMapped, GrImageTexGenPolicy) override;
#endif
private:
@ -96,13 +97,17 @@ bool SkPictureImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels,
GrSurfaceProxyView SkPictureImageGenerator::onGenerateTexture(GrRecordingContext* ctx,
const SkImageInfo& info,
const SkIPoint& origin,
GrMipMapped mipMapped) {
GrMipMapped mipMapped,
GrImageTexGenPolicy texGenPolicy) {
SkASSERT(ctx);
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
SkBudgeted budgeted = texGenPolicy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted
? SkBudgeted::kNo
: SkBudgeted::kYes;
// CONTEXT TODO: remove this use of 'backdoor' to create an SkSkSurface
auto surface = SkSurface::MakeRenderTarget(ctx->priv().backdoor(), SkBudgeted::kYes, info, 0,
auto surface = SkSurface::MakeRenderTarget(ctx->priv().backdoor(), budgeted, info, 0,
kTopLeft_GrSurfaceOrigin, &props,
mipMapped == GrMipMapped::kYes);
if (!surface) {

View File

@ -31,6 +31,7 @@
#include "src/gpu/GrResourceProviderPriv.h"
#include "src/gpu/GrTexture.h"
#include "src/gpu/GrTextureProxy.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/gl/GrGLDefines.h"
#include <EGL/egl.h>
@ -186,28 +187,33 @@ GrSurfaceProxyView GrAHardwareBufferImageGenerator::makeView(GrRecordingContext*
return GrSurfaceProxyView(std::move(texProxy), fSurfaceOrigin, readSwizzle);
}
GrSurfaceProxyView GrAHardwareBufferImageGenerator::onGenerateTexture(GrRecordingContext* context,
const SkImageInfo& info,
const SkIPoint& origin,
GrMipMapped mipMapped) {
GrSurfaceProxyView GrAHardwareBufferImageGenerator::onGenerateTexture(
GrRecordingContext* context,
const SkImageInfo& info,
const SkIPoint& origin,
GrMipMapped mipMapped,
GrImageTexGenPolicy texGenPolicy) {
GrSurfaceProxyView texProxyView = this->makeView(context);
if (!texProxyView.proxy()) {
return {};
}
SkASSERT(texProxyView.asTextureProxy());
if (origin.isZero() && info.dimensions() == this->getInfo().dimensions() &&
mipMapped == GrMipMapped::kNo) {
if (texGenPolicy == GrImageTexGenPolicy::kDraw && origin.isZero() &&
info.dimensions() == this->getInfo().dimensions() && mipMapped == GrMipMapped::kNo) {
// If the caller wants the full non-MIP mapped texture we're done.
return texProxyView;
}
// Otherwise, make a copy for the requested subset and/or MIP maps.
SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, info.width(), info.height());
SkBudgeted budgeted = texGenPolicy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted
? SkBudgeted::kNo
: SkBudgeted::kYes;
GrColorType grColorType = SkColorTypeToGrColorType(this->getInfo().colorType());
return GrSurfaceProxy::Copy(context, texProxyView.proxy(), texProxyView.origin(), grColorType,
mipMapped, subset, SkBackingFit::kExact,
SkBudgeted::kYes);
mipMapped, subset, SkBackingFit::kExact, budgeted);
}
bool GrAHardwareBufferImageGenerator::onIsValid(GrContext* context) const {

View File

@ -43,7 +43,7 @@ protected:
bool onIsValid(GrContext*) const override;
GrSurfaceProxyView onGenerateTexture(GrRecordingContext*, const SkImageInfo&, const SkIPoint&,
GrMipMapped) override;
GrMipMapped, GrImageTexGenPolicy) override;
private:
GrAHardwareBufferImageGenerator(const SkImageInfo&, AHardwareBuffer*, SkAlphaType,

View File

@ -93,10 +93,12 @@ void GrBackendTextureImageGenerator::ReleaseRefHelper_TextureReleaseProc(void* c
refHelper->unref();
}
GrSurfaceProxyView GrBackendTextureImageGenerator::onGenerateTexture(GrRecordingContext* context,
const SkImageInfo& info,
const SkIPoint& origin,
GrMipMapped mipMapped) {
GrSurfaceProxyView GrBackendTextureImageGenerator::onGenerateTexture(
GrRecordingContext* context,
const SkImageInfo& info,
const SkIPoint& origin,
GrMipMapped mipMapped,
GrImageTexGenPolicy texGenPolicy) {
SkASSERT(context);
if (context->backend() != fBackendTexture.backend()) {
@ -210,18 +212,19 @@ GrSurfaceProxyView GrBackendTextureImageGenerator::onGenerateTexture(GrRecording
return {};
}
if (origin.isZero() && info.dimensions() == fBackendTexture.dimensions() &&
if (texGenPolicy == GrImageTexGenPolicy::kDraw && origin.isZero() &&
info.dimensions() == fBackendTexture.dimensions() &&
(mipMapped == GrMipMapped::kNo || proxy->mipMapped() == GrMipMapped::kYes)) {
// If the caller wants the entire texture and we have the correct mip support, we're done
return GrSurfaceProxyView(std::move(proxy), fSurfaceOrigin, readSwizzle);
} else {
// Otherwise, make a copy of the requested subset. Make sure our temporary is renderable,
// because Vulkan will want to do the copy as a draw. All other copies would require a
// layout change in Vulkan and we do not change the layout of borrowed images.
SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, info.width(), info.height());
return GrSurfaceProxy::Copy(
context, proxy.get(), fSurfaceOrigin, grColorType, mipMapped, subset,
SkBackingFit::kExact, SkBudgeted::kYes);
SkBudgeted budgeted = texGenPolicy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted
? SkBudgeted::kNo
: SkBudgeted::kYes;
return GrSurfaceProxy::Copy(context, proxy.get(), fSurfaceOrigin, grColorType, mipMapped,
subset, SkBackingFit::kExact, budgeted);
}
}

View File

@ -41,7 +41,7 @@ protected:
bool onIsValid(GrContext*) const override { return true; }
GrSurfaceProxyView onGenerateTexture(GrRecordingContext*, const SkImageInfo&, const SkIPoint&,
GrMipMapped mipMapped) override;
GrMipMapped mipMapped, GrImageTexGenPolicy) override;
private:
GrBackendTextureImageGenerator(const SkImageInfo& info, GrTexture*, GrSurfaceOrigin,

View File

@ -26,10 +26,27 @@ static GrImageInfo get_image_info(GrRecordingContext* context, const SkBitmap& b
return {ct, bitmap.alphaType(), bitmap.refColorSpace(), bitmap.dimensions()};
}
GrBitmapTextureMaker::GrBitmapTextureMaker(GrRecordingContext* context, const SkBitmap& bitmap,
Cached cached, SkBackingFit fit)
: INHERITED(context, get_image_info(context, bitmap)), fBitmap(bitmap), fFit(fit) {
if (!bitmap.isVolatile() && cached == Cached::kYes) {
GrBitmapTextureMaker::GrBitmapTextureMaker(GrRecordingContext* context,
const SkBitmap& bitmap,
SkBackingFit fit)
: GrBitmapTextureMaker(context, bitmap, GrImageTexGenPolicy::kNew_Uncached_Budgeted, fit) {}
GrBitmapTextureMaker::GrBitmapTextureMaker(GrRecordingContext* context,
const SkBitmap& bitmap,
GrImageTexGenPolicy cachePolicy)
: GrBitmapTextureMaker(context, bitmap, cachePolicy, SkBackingFit::kExact) {}
GrBitmapTextureMaker::GrBitmapTextureMaker(GrRecordingContext* context,
const SkBitmap& bitmap,
GrImageTexGenPolicy cachePolicy,
SkBackingFit fit)
: INHERITED(context, get_image_info(context, bitmap))
, fBitmap(bitmap)
, fFit(fit)
, fBudgeted(cachePolicy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted
? SkBudgeted::kNo
: SkBudgeted::kYes) {
if (!bitmap.isVolatile() && cachePolicy == GrImageTexGenPolicy::kDraw) {
SkIPoint origin = bitmap.pixelRefOrigin();
SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, bitmap.width(),
bitmap.height());
@ -69,9 +86,9 @@ GrSurfaceProxyView GrBitmapTextureMaker::refOriginalTextureProxyView(GrMipMapped
return {};
}
copy8888.setImmutable();
proxy = proxyProvider->createProxyFromBitmap(copy8888, mipMapped, fFit);
proxy = proxyProvider->createProxyFromBitmap(copy8888, mipMapped, fFit, fBudgeted);
} else {
proxy = proxyProvider->createProxyFromBitmap(fBitmap, mipMapped, fFit);
proxy = proxyProvider->createProxyFromBitmap(fBitmap, mipMapped, fFit, fBudgeted);
}
if (proxy) {
swizzle = this->context()->priv().caps()->getReadSwizzle(proxy->backendFormat(),

View File

@ -10,22 +10,27 @@
#include "include/core/SkBitmap.h"
#include "src/gpu/GrTextureMaker.h"
#include "src/gpu/SkGr.h"
/** This class manages the conversion of SW-backed bitmaps to GrTextures. If the input bitmap is
non-volatile the texture is cached using a key created from the pixels' image id and the
subset of the pixelref specified by the bitmap. */
class GrBitmapTextureMaker final : public GrTextureMaker {
public:
enum class Cached { kNo, kYes };
GrBitmapTextureMaker(GrRecordingContext*, const SkBitmap&, GrImageTexGenPolicy);
GrBitmapTextureMaker(GrRecordingContext* context, const SkBitmap& bitmap,
Cached cached = Cached::kNo, SkBackingFit = SkBackingFit::kExact);
// Always uncached-budgeted. It doesn't make sense to have kApprox cached textures. Moreover,we
// create kApprox textures intermediate buffers and those ought to be budgeted.
GrBitmapTextureMaker(GrRecordingContext*, const SkBitmap&, SkBackingFit);
private:
GrBitmapTextureMaker(GrRecordingContext*, const SkBitmap&, GrImageTexGenPolicy, SkBackingFit);
GrSurfaceProxyView refOriginalTextureProxyView(GrMipMapped) override;
const SkBitmap fBitmap;
const SkBackingFit fFit;
const SkBudgeted fBudgeted;
GrUniqueKey fKey;
typedef GrTextureMaker INHERITED;

View File

@ -151,8 +151,7 @@ static bool sw_draw_with_mask_filter(GrRecordingContext* context,
}
bm.setImmutable();
GrBitmapTextureMaker maker(context, bm, GrBitmapTextureMaker::Cached::kNo,
SkBackingFit::kApprox);
GrBitmapTextureMaker maker(context, bm, SkBackingFit::kApprox);
filteredMaskView = maker.view(GrMipMapped::kNo);
if (!filteredMaskView.proxy()) {
return false;

View File

@ -24,16 +24,17 @@ static GrImageInfo get_image_info(GrRecordingContext* context, const SkImage* cl
return {ct, client->alphaType(), client->refColorSpace(), client->dimensions()};
}
GrImageTextureMaker::GrImageTextureMaker(GrRecordingContext* context, const SkImage* client,
SkImage::CachingHint chint)
GrImageTextureMaker::GrImageTextureMaker(GrRecordingContext* context,
const SkImage* client,
GrImageTexGenPolicy texGenPolicy)
: INHERITED(context, get_image_info(context, client))
, fImage(static_cast<const SkImage_Lazy*>(client))
, fCachingHint(chint) {
, fTexGenPolicy(texGenPolicy) {
SkASSERT(client->isLazyGenerated());
}
GrSurfaceProxyView GrImageTextureMaker::refOriginalTextureProxyView(GrMipMapped mipMapped) {
return fImage->lockTextureProxyView(this->context(), fCachingHint, mipMapped);
return fImage->lockTextureProxyView(this->context(), fTexGenPolicy, mipMapped);
}
/////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -10,6 +10,7 @@
#include "include/core/SkImage.h"
#include "src/gpu/GrTextureMaker.h"
#include "src/gpu/SkGr.h"
class SkImage_Lazy;
class SkImage_GpuYUVA;
@ -18,14 +19,13 @@ class SkImage_GpuYUVA;
is kAllow the image's ID is used for the cache key. */
class GrImageTextureMaker final : public GrTextureMaker {
public:
GrImageTextureMaker(GrRecordingContext* context, const SkImage* client,
SkImage::CachingHint chint);
GrImageTextureMaker(GrRecordingContext*, const SkImage* client, GrImageTexGenPolicy);
private:
GrSurfaceProxyView refOriginalTextureProxyView(GrMipMapped) override;
const SkImage_Lazy* fImage;
SkImage::CachingHint fCachingHint;
GrImageTexGenPolicy fTexGenPolicy;
typedef GrTextureMaker INHERITED;
};

View File

@ -240,7 +240,8 @@ sk_sp<GrTextureProxy> GrProxyProvider::findOrCreateProxyByUniqueKey(const GrUniq
sk_sp<GrTextureProxy> GrProxyProvider::createProxyFromBitmap(const SkBitmap& bitmap,
GrMipMapped mipMapped,
SkBackingFit fit) {
SkBackingFit fit,
SkBudgeted budgeted) {
ASSERT_SINGLE_OWNER
SkASSERT(fit == SkBackingFit::kExact || mipMapped == GrMipMapped::kNo);
@ -277,9 +278,9 @@ sk_sp<GrTextureProxy> GrProxyProvider::createProxyFromBitmap(const SkBitmap& bit
sk_sp<GrTextureProxy> proxy;
if (mipMapped == GrMipMapped::kNo ||
0 == SkMipMap::ComputeLevelCount(copyBitmap.width(), copyBitmap.height())) {
proxy = this->createNonMippedProxyFromBitmap(copyBitmap, fit, format, grCT);
proxy = this->createNonMippedProxyFromBitmap(copyBitmap, fit, format, grCT, budgeted);
} else {
proxy = this->createMippedProxyFromBitmap(copyBitmap, format, grCT);
proxy = this->createMippedProxyFromBitmap(copyBitmap, format, grCT, budgeted);
}
if (!proxy) {
@ -302,20 +303,21 @@ sk_sp<GrTextureProxy> GrProxyProvider::createProxyFromBitmap(const SkBitmap& bit
sk_sp<GrTextureProxy> GrProxyProvider::createNonMippedProxyFromBitmap(const SkBitmap& bitmap,
SkBackingFit fit,
const GrBackendFormat& format,
GrColorType colorType) {
GrColorType colorType,
SkBudgeted budgeted) {
GrSwizzle swizzle = this->caps()->getReadSwizzle(format, colorType);
auto dims = bitmap.dimensions();
sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
[dims, format, bitmap, fit, colorType](GrResourceProvider* resourceProvider) {
[dims, format, bitmap, fit, colorType, budgeted](GrResourceProvider* resourceProvider) {
GrMipLevel mipLevel = { bitmap.getPixels(), bitmap.rowBytes() };
return LazyCallbackResult(resourceProvider->createTexture(
dims, format, colorType, GrRenderable::kNo, 1, SkBudgeted::kYes, fit,
dims, format, colorType, GrRenderable::kNo, 1, budgeted, fit,
GrProtected::kNo, mipLevel));
},
format, dims, swizzle, GrRenderable::kNo, 1, GrMipMapped::kNo,
GrMipMapsStatus::kNotAllocated, GrInternalSurfaceFlags::kNone, fit, SkBudgeted::kYes,
GrMipMapsStatus::kNotAllocated, GrInternalSurfaceFlags::kNone, fit, budgeted,
GrProtected::kNo, UseAllocator::kYes);
if (!proxy) {
@ -327,7 +329,8 @@ sk_sp<GrTextureProxy> GrProxyProvider::createNonMippedProxyFromBitmap(const SkBi
sk_sp<GrTextureProxy> GrProxyProvider::createMippedProxyFromBitmap(const SkBitmap& bitmap,
const GrBackendFormat& format,
GrColorType colorType) {
GrColorType colorType,
SkBudgeted budgeted) {
SkASSERT(this->caps()->mipMapSupport());
@ -340,7 +343,7 @@ sk_sp<GrTextureProxy> GrProxyProvider::createMippedProxyFromBitmap(const SkBitma
auto dims = bitmap.dimensions();
sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
[dims, format, bitmap, mipmaps](GrResourceProvider* resourceProvider) {
[dims, format, bitmap, mipmaps, budgeted](GrResourceProvider* resourceProvider) {
const int mipLevelCount = mipmaps->countLevels() + 1;
std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
@ -357,12 +360,12 @@ sk_sp<GrTextureProxy> GrProxyProvider::createMippedProxyFromBitmap(const SkBitma
SkASSERT(generatedMipLevel.fPixmap.colorType() == bitmap.colorType());
}
return LazyCallbackResult(resourceProvider->createTexture(
dims, format, colorType, GrRenderable::kNo, 1, SkBudgeted::kYes,
GrProtected::kNo, texels.get(), mipLevelCount));
dims, format, colorType, GrRenderable::kNo, 1, budgeted, GrProtected::kNo,
texels.get(), mipLevelCount));
},
format, dims, readSwizzle, GrRenderable::kNo, 1, GrMipMapped::kYes,
GrMipMapsStatus::kValid, GrInternalSurfaceFlags::kNone, SkBackingFit::kExact,
SkBudgeted::kYes, GrProtected::kNo, UseAllocator::kYes);
GrMipMapsStatus::kValid, GrInternalSurfaceFlags::kNone, SkBackingFit::kExact, budgeted,
GrProtected::kNo, UseAllocator::kYes);
if (!proxy) {
return nullptr;

View File

@ -66,8 +66,10 @@ public:
* Creates a new texture proxy for the bitmap, optionally with mip levels generated by the cpu.
* The bitmap is uploaded to the texture proxy assuming a kTopLeft_GrSurfaceOrigin.
*/
sk_sp<GrTextureProxy> createProxyFromBitmap(const SkBitmap& bitmap, GrMipMapped,
SkBackingFit fit);
sk_sp<GrTextureProxy> createProxyFromBitmap(const SkBitmap&,
GrMipMapped,
SkBackingFit,
SkBudgeted);
/*
* Create a GrSurfaceProxy without any data.
@ -273,16 +275,15 @@ private:
/*
* Create an un-mipmapped texture proxy for the bitmap.
*/
sk_sp<GrTextureProxy> createNonMippedProxyFromBitmap(const SkBitmap& bitmap,
SkBackingFit fit,
const GrBackendFormat& format,
GrColorType colorType);
sk_sp<GrTextureProxy> createNonMippedProxyFromBitmap(
const SkBitmap&, SkBackingFit, const GrBackendFormat&, GrColorType, SkBudgeted);
/*
* Create an mipmapped texture proxy for the bitmap.
*/
sk_sp<GrTextureProxy> createMippedProxyFromBitmap(const SkBitmap& bitmap,
const GrBackendFormat& format,
GrColorType colorType);
sk_sp<GrTextureProxy> createMippedProxyFromBitmap(const SkBitmap&,
const GrBackendFormat&,
GrColorType,
SkBudgeted);
// GrColorType is used to determine the proxy's texture swizzle.
sk_sp<GrTextureProxy> createWrapped(sk_sp<GrTexture> tex, GrColorType,

View File

@ -103,6 +103,6 @@ GrSurfaceProxyView GrSWMaskHelper::toTextureView(GrRecordingContext* context, Sk
nullptr));
bitmap.setImmutable();
GrBitmapTextureMaker maker(context, bitmap, GrBitmapTextureMaker::Cached::kNo, fit);
GrBitmapTextureMaker maker(context, bitmap, fit);
return maker.view(GrMipMapped::kNo);
}

View File

@ -108,7 +108,8 @@ GrSurfaceProxyView GrYUVProvider::refAsTextureProxyView(GrRecordingContext* ctx,
SkISize dimensions,
GrColorType colorType,
SkColorSpace* srcColorSpace,
SkColorSpace* dstColorSpace) {
SkColorSpace* dstColorSpace,
SkBudgeted budgeted) {
SkYUVASizeInfo yuvSizeInfo;
SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount];
SkYUVColorSpace yuvColorSpace;
@ -152,7 +153,7 @@ GrSurfaceProxyView GrYUVProvider::refAsTextureProxyView(GrRecordingContext* ctx,
YUVGen_DataReleaseProc, dataStoragePtr));
bitmap.setImmutable();
GrBitmapTextureMaker maker(ctx, bitmap, GrBitmapTextureMaker::Cached::kNo, fit);
GrBitmapTextureMaker maker(ctx, bitmap, fit);
yuvViews[i] = maker.view(GrMipMapped::kNo);
if (!yuvViews[i]) {
@ -165,7 +166,7 @@ GrSurfaceProxyView GrYUVProvider::refAsTextureProxyView(GrRecordingContext* ctx,
// TODO: investigate preallocating mip maps here
auto renderTargetContext = GrRenderTargetContext::Make(
ctx, colorType, nullptr, SkBackingFit::kExact, dimensions, 1, GrMipMapped::kNo,
GrProtected::kNo, kTopLeft_GrSurfaceOrigin);
GrProtected::kNo, kTopLeft_GrSurfaceOrigin, budgeted);
if (!renderTargetContext) {
return {};
}

View File

@ -44,7 +44,8 @@ public:
SkISize,
GrColorType colorType,
SkColorSpace* srcColorSpace,
SkColorSpace* dstColorSpace);
SkColorSpace* dstColorSpace,
SkBudgeted budgeted);
sk_sp<SkCachedData> getPlanes(SkYUVASizeInfo*, SkYUVAIndex[SkYUVAIndex::kIndexCount],
SkYUVColorSpace*, const void* planes[SkYUVASizeInfo::kMaxCount]);

View File

@ -881,10 +881,10 @@ void SkGpuDevice::drawImageNine(const SkImage* image,
} else {
SkBitmap bm;
if (image->isLazyGenerated()) {
GrImageTextureMaker maker(fContext.get(), image, SkImage::kAllow_CachingHint);
GrImageTextureMaker maker(fContext.get(), image, GrImageTexGenPolicy::kDraw);
this->drawProducerLattice(&maker, std::move(iter), dst, paint);
} else if (as_IB(image)->getROPixels(&bm)) {
GrBitmapTextureMaker maker(fContext.get(), bm, GrBitmapTextureMaker::Cached::kYes);
GrBitmapTextureMaker maker(fContext.get(), bm, GrImageTexGenPolicy::kDraw);
this->drawProducerLattice(&maker, std::move(iter), dst, paint);
}
}
@ -932,10 +932,10 @@ void SkGpuDevice::drawImageLattice(const SkImage* image,
} else {
SkBitmap bm;
if (image->isLazyGenerated()) {
GrImageTextureMaker maker(fContext.get(), image, SkImage::kAllow_CachingHint);
GrImageTextureMaker maker(fContext.get(), image, GrImageTexGenPolicy::kDraw);
this->drawProducerLattice(&maker, std::move(iter), dst, paint);
} else if (as_IB(image)->getROPixels(&bm)) {
GrBitmapTextureMaker maker(fContext.get(), bm, GrBitmapTextureMaker::Cached::kYes);
GrBitmapTextureMaker maker(fContext.get(), bm, GrImageTexGenPolicy::kDraw);
this->drawProducerLattice(&maker, std::move(iter), dst, paint);
}
}

View File

@ -569,8 +569,7 @@ void draw_tiled_bitmap(GrContext* context,
SkASSERT(tmpB.width() <= context->priv().caps()->maxTileSize() &&
tmpB.height() <= context->priv().caps()->maxTileSize());
GrBitmapTextureMaker tileProducer(context, tmpB, GrBitmapTextureMaker::Cached::kYes,
SkBackingFit::kExact);
GrBitmapTextureMaker tileProducer(context, tmpB, GrImageTexGenPolicy::kDraw);
GrQuadAAFlags aaFlags = GrQuadAAFlags::kNone;
if (aa == GrAA::kYes) {
@ -719,7 +718,7 @@ void SkGpuDevice::drawImageQuad(const SkImage* image, const SkRect* srcRect, con
// Lazily generated images must get drawn as a texture producer that handles the final
// texture creation.
if (image->isLazyGenerated()) {
GrImageTextureMaker maker(fContext.get(), image, SkImage::kAllow_CachingHint);
GrImageTextureMaker maker(fContext.get(), image, GrImageTexGenPolicy::kDraw);
draw_texture_producer(fContext.get(), fRenderTargetContext.get(), clip, ctm, paint,
&maker, src, dst, dstClip, srcToDst, aa, aaFlags, constraint,
wrapMode, fm, doBicubic);
@ -728,8 +727,7 @@ void SkGpuDevice::drawImageQuad(const SkImage* image, const SkRect* srcRect, con
SkBitmap bm;
if (as_IB(image)->getROPixels(&bm)) {
GrBitmapTextureMaker maker(fContext.get(), bm, GrBitmapTextureMaker::Cached::kYes,
SkBackingFit::kExact);
GrBitmapTextureMaker maker(fContext.get(), bm, GrImageTexGenPolicy::kDraw);
draw_texture_producer(fContext.get(), fRenderTargetContext.get(), clip, ctm, paint,
&maker, src, dst, dstClip, srcToDst, aa, aaFlags, constraint,
wrapMode, fm, doBicubic);

View File

@ -134,32 +134,37 @@ sk_sp<SkIDChangeListener> GrMakeUniqueKeyInvalidationListener(GrUniqueKey* key,
GrSurfaceProxyView GrCopyBaseMipMapToTextureProxy(GrRecordingContext* ctx,
GrSurfaceProxy* baseProxy,
GrSurfaceOrigin origin,
GrColorType srcColorType) {
GrColorType srcColorType,
SkBudgeted budgeted) {
SkASSERT(baseProxy);
if (!ctx->priv().caps()->isFormatCopyable(baseProxy->backendFormat())) {
return {};
}
GrSurfaceProxyView view = GrSurfaceProxy::Copy(ctx, baseProxy, origin, srcColorType,
GrMipMapped::kYes, SkBackingFit::kExact,
SkBudgeted::kYes);
GrSurfaceProxyView view = GrSurfaceProxy::Copy(ctx,
baseProxy,
origin,
srcColorType,
GrMipMapped::kYes,
SkBackingFit::kExact,
budgeted);
SkASSERT(!view.proxy() || view.asTextureProxy());
return view;
}
GrSurfaceProxyView GrRefCachedBitmapView(GrRecordingContext* ctx, const SkBitmap& bitmap,
GrMipMapped mipMapped) {
GrBitmapTextureMaker maker(ctx, bitmap, GrBitmapTextureMaker::Cached::kYes);
GrBitmapTextureMaker maker(ctx, bitmap, GrImageTexGenPolicy::kDraw);
return maker.view(mipMapped);
}
GrSurfaceProxyView GrMakeCachedBitmapProxyView(GrRecordingContext* context, const SkBitmap& bitmap,
SkBackingFit fit) {
GrSurfaceProxyView GrMakeCachedBitmapProxyView(GrRecordingContext* context,
const SkBitmap& bitmap) {
if (!bitmap.peekPixels(nullptr)) {
return {};
}
GrBitmapTextureMaker maker(context, bitmap, GrBitmapTextureMaker::Cached::kYes, fit);
GrBitmapTextureMaker maker(context, bitmap, GrImageTexGenPolicy::kDraw);
return maker.view(GrMipMapped::kNo);
}

View File

@ -163,6 +163,18 @@ static_assert((int)kIDA_GrBlendCoeff == (int)SkBlendModeCoeff::kIDA);
////////////////////////////////////////////////////////////////////////////////
// Texture management
/**
* Policies for how to create textures for SkImages (and SkBitmaps).
*/
enum class GrImageTexGenPolicy : int {
// Choose the cheapest way to generate the texture. Use GrResourceCache if appropriate.
kDraw,
// Always make a new texture that is uncached and unbudgeted.
kNew_Uncached_Unbudgeted,
// Always make a new texture that is uncached and budgeted.
kNew_Uncached_Budgeted
};
/**
* Returns a view that wraps a texture representing the bitmap. The texture is inserted into the
* cache (unless the bitmap is marked volatile and can be retrieved again via this function.
@ -177,14 +189,14 @@ GrSurfaceProxyView GrRefCachedBitmapView(GrRecordingContext*, const SkBitmap&, G
GrSurfaceProxyView GrCopyBaseMipMapToTextureProxy(GrRecordingContext*,
GrSurfaceProxy* baseProxy,
GrSurfaceOrigin origin,
GrColorType srcColorType);
GrColorType srcColorType,
SkBudgeted = SkBudgeted::kYes);
/*
* Create a texture proxy from the provided bitmap and add it to the texture cache
* using the key also extracted from 'bitmp'.
*/
GrSurfaceProxyView GrMakeCachedBitmapProxyView(GrRecordingContext*, const SkBitmap& bitmap,
SkBackingFit fit = SkBackingFit::kExact);
GrSurfaceProxyView GrMakeCachedBitmapProxyView(GrRecordingContext*, const SkBitmap& bitmap);
/**
* Our key includes the offset, width, and height so that bitmaps created by extractSubset()

View File

@ -256,7 +256,7 @@ uniform half4 circleData;
bm.setImmutable();
GrBitmapTextureMaker maker(context, bm);
GrBitmapTextureMaker maker(context, bm, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
auto blurView = maker.view(GrMipMapped::kNo);
if (!blurView) {
return {};

View File

@ -59,7 +59,7 @@
bitmap.installPixels(ii, srcData, 4 * kSize);
bitmap.setImmutable();
GrBitmapTextureMaker maker(context, bitmap);
GrBitmapTextureMaker maker(context, bitmap, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
auto dataView = maker.view(GrMipMapped::kNo);
if (!dataView) {
return false;

View File

@ -84,7 +84,7 @@ static GrSurfaceProxyView CreateIntegralTexture(GrRecordingContext* context, flo
*bitmap.getAddr8(width - 1, 0) = 0;
bitmap.setImmutable();
GrBitmapTextureMaker maker(context, bitmap);
GrBitmapTextureMaker maker(context, bitmap, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
auto view = maker.view(GrMipMapped::kNo);
if (!view) {
return {};

View File

@ -233,7 +233,7 @@ static GrSurfaceProxyView create_profile_texture(GrRecordingContext* context, co
bm.setImmutable();
GrBitmapTextureMaker maker(context, bm);
GrBitmapTextureMaker maker(context, bm, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
auto blurView = maker.view(GrMipMapped::kNo);
if (!blurView) {
return {};

View File

@ -68,7 +68,7 @@ public:
bitmap.installPixels(ii, srcData, 4 * kSize);
bitmap.setImmutable();
GrBitmapTextureMaker maker(context, bitmap);
GrBitmapTextureMaker maker(context, bitmap, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
auto dataView = maker.view(GrMipMapped::kNo);
if (!dataView) {
return false;

View File

@ -67,7 +67,7 @@ public:
*bitmap.getAddr8(width - 1, 0) = 0;
bitmap.setImmutable();
GrBitmapTextureMaker maker(context, bitmap);
GrBitmapTextureMaker maker(context, bitmap, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
auto view = maker.view(GrMipMapped::kNo);
if (!view) {
return {};

View File

@ -690,7 +690,7 @@ static GrSurfaceProxyView create_falloff_texture(GrRecordingContext* context) {
}
bitmap.setImmutable();
GrBitmapTextureMaker maker(context, bitmap);
GrBitmapTextureMaker maker(context, bitmap, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
auto view = maker.view(GrMipMapped::kNo);
SkASSERT(view.origin() == kTopLeft_GrSurfaceOrigin);

View File

@ -500,7 +500,7 @@ sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace
return nullptr;
}
sk_sp<SkImage> SkImage::makeTextureImage(GrContext*, GrMipMapped mipMapped) const {
sk_sp<SkImage> SkImage::makeTextureImage(GrContext*, GrMipMapped, SkBudgeted) const {
return nullptr;
}

View File

@ -418,7 +418,9 @@ static sk_sp<SkImage> create_image_from_producer(GrContext* context, GrTexturePr
producer->alphaType(), sk_ref_sp(producer->colorSpace()));
}
sk_sp<SkImage> SkImage::makeTextureImage(GrContext* context, GrMipMapped mipMapped) const {
sk_sp<SkImage> SkImage::makeTextureImage(GrContext* context,
GrMipMapped mipMapped,
SkBudgeted budgeted) const {
if (!context) {
return nullptr;
}
@ -428,22 +430,35 @@ sk_sp<SkImage> SkImage::makeTextureImage(GrContext* context, GrMipMapped mipMapp
return nullptr;
}
// TODO: Don't flatten YUVA images here.
const GrSurfaceProxyView* view = as_IB(this)->view(context);
SkASSERT(view && view->asTextureProxy());
if (GrMipMapped::kNo == mipMapped || view->asTextureProxy()->mipMapped() == mipMapped) {
if (mipMapped == GrMipMapped::kNo || view->asTextureProxy()->mipMapped() == mipMapped ||
!context->priv().caps()->mipMapSupport()) {
return sk_ref_sp(const_cast<SkImage*>(this));
}
GrTextureAdjuster adjuster(context, *view, this->imageInfo().colorInfo(), this->uniqueID());
return create_image_from_producer(context, &adjuster, this->uniqueID(), mipMapped);
auto copy = GrCopyBaseMipMapToTextureProxy(context->priv().asRecordingContext(),
view->proxy(),
view->origin(),
SkColorTypeToGrColorType(this->colorType()),
budgeted);
if (!copy) {
return nullptr;
}
return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), this->uniqueID(), std::move(copy),
this->colorType(), this->alphaType(), this->refColorSpace());
}
auto policy = budgeted == SkBudgeted::kYes ? GrImageTexGenPolicy::kNew_Uncached_Budgeted
: GrImageTexGenPolicy::kNew_Uncached_Unbudgeted;
if (this->isLazyGenerated()) {
GrImageTextureMaker maker(context, this, kDisallow_CachingHint);
GrImageTextureMaker maker(context, this, policy);
return create_image_from_producer(context, &maker, this->uniqueID(), mipMapped);
}
if (const SkBitmap* bmp = as_IB(this)->onPeekBitmap()) {
GrBitmapTextureMaker maker(context, *bmp, GrBitmapTextureMaker::Cached::kYes);
GrBitmapTextureMaker maker(context, *bmp, policy);
return create_image_from_producer(context, &maker, this->uniqueID(), mipMapped);
}
return nullptr;
@ -545,7 +560,7 @@ sk_sp<SkImage> SkImage::MakeCrossContextFromPixmap(GrContext* context,
// Turn the pixmap into a GrTextureProxy
SkBitmap bmp;
bmp.installPixels(*pixmap);
GrBitmapTextureMaker bitmapMaker(context, bmp);
GrBitmapTextureMaker bitmapMaker(context, bmp, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
GrMipMapped mipMapped = buildMips ? GrMipMapped::kYes : GrMipMapped::kNo;
auto view = bitmapMaker.view(mipMapped);
if (!view) {

View File

@ -291,7 +291,7 @@ sk_sp<SkImage> SkImage::MakeFromYUVAPixmaps(GrContext* context, SkYUVColorSpace
// Turn the pixmap into a GrTextureProxy
SkBitmap bmp;
bmp.installPixels(*pixmap);
GrBitmapTextureMaker bitmapMaker(context, bmp);
GrBitmapTextureMaker bitmapMaker(context, bmp, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
GrMipMapped mipMapped = buildMips ? GrMipMapped::kYes : GrMipMapped::kNo;
GrSurfaceProxyView view;
tempViews[i] = bitmapMaker.view(mipMapped);

View File

@ -235,7 +235,7 @@ GrSurfaceProxyView SkImage_Lazy::refView(GrRecordingContext* context, GrMipMappe
return {};
}
GrImageTextureMaker textureMaker(context, this, kAllow_CachingHint);
GrImageTextureMaker textureMaker(context, this, GrImageTexGenPolicy::kDraw);
return textureMaker.view(mipMapped);
}
#endif
@ -386,7 +386,7 @@ sk_sp<SkCachedData> SkImage_Lazy::getPlanes(SkYUVASizeInfo* yuvaSizeInfo,
* 4. Ask the generator to return RGB(A) data, which the GPU can convert
*/
GrSurfaceProxyView SkImage_Lazy::lockTextureProxyView(GrRecordingContext* ctx,
SkImage::CachingHint chint,
GrImageTexGenPolicy texGenPolicy,
GrMipMapped mipMapped) const {
// Values representing the various texture lock paths we can take. Used for logging the path
// taken to a histogram.
@ -402,7 +402,9 @@ GrSurfaceProxyView SkImage_Lazy::lockTextureProxyView(GrRecordingContext* ctx,
enum { kLockTexturePathCount = kRGBA_LockTexturePath + 1 };
GrUniqueKey key;
GrMakeKeyFromImageID(&key, this->uniqueID(), SkIRect::MakeSize(this->dimensions()));
if (texGenPolicy == GrImageTexGenPolicy::kDraw) {
GrMakeKeyFromImageID(&key, this->uniqueID(), SkIRect::MakeSize(this->dimensions()));
}
const GrCaps* caps = ctx->priv().caps();
GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
@ -418,7 +420,7 @@ GrSurfaceProxyView SkImage_Lazy::lockTextureProxyView(GrRecordingContext* ctx,
auto ct = this->colorTypeOfLockTextureProxy(caps);
// 1. Check the cache for a pre-existing one
// 1. Check the cache for a pre-existing one.
if (key.isValid()) {
auto proxy = proxyProvider->findOrCreateProxyByUniqueKey(key, ct);
if (proxy) {
@ -448,19 +450,20 @@ GrSurfaceProxyView SkImage_Lazy::lockTextureProxyView(GrRecordingContext* ctx,
}
}
// 2. Ask the generator to natively create one
// 2. Ask the generator to natively create one.
{
ScopedGenerator generator(fSharedGenerator);
if (auto view = generator->generateTexture(ctx, this->imageInfo(), fOrigin, mipMapped)) {
SK_HISTOGRAM_ENUMERATION("LockTexturePath", kNative_LockTexturePath,
kLockTexturePathCount);
installKey(view);
return view;
}
ScopedGenerator generator(fSharedGenerator);
if (auto view = generator->generateTexture(ctx, this->imageInfo(), fOrigin, mipMapped,
texGenPolicy)) {
SK_HISTOGRAM_ENUMERATION("LockTexturePath", kNative_LockTexturePath,
kLockTexturePathCount);
installKey(view);
return view;
}
}
// 3. Ask the generator to return YUV planes, which the GPU can convert. If we will be mipping
// the texture we fall through here and have the CPU generate the mip maps for us.
// the texture we skip this step so the CPU generate non-planar MIP maps for us.
if (mipMapped == GrMipMapped::kNo && !ctx->priv().options().fDisableGpuYUVConversion) {
SkColorType colorType = this->colorType();
@ -476,9 +479,12 @@ GrSurfaceProxyView SkImage_Lazy::lockTextureProxyView(GrRecordingContext* ctx,
// TODO: Update to create the mipped surface in the YUV generator and draw the base
// layer directly into the mipped surface.
SkBudgeted budgeted = texGenPolicy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted
? SkBudgeted::kNo
: SkBudgeted::kYes;
auto view = provider.refAsTextureProxyView(ctx, this->imageInfo().dimensions(),
SkColorTypeToGrColorType(colorType),
generatorColorSpace, thisColorSpace);
generatorColorSpace, thisColorSpace, budgeted);
if (view) {
SK_HISTOGRAM_ENUMERATION("LockTexturePath", kYUV_LockTexturePath,
kLockTexturePathCount);
@ -487,9 +493,16 @@ GrSurfaceProxyView SkImage_Lazy::lockTextureProxyView(GrRecordingContext* ctx,
}
}
// 4. Ask the generator to return RGB(A) data, which the GPU can convert
if (SkBitmap bitmap; this->getROPixels(&bitmap, chint)) {
GrBitmapTextureMaker bitmapMaker(ctx, bitmap, GrBitmapTextureMaker::Cached::kNo);
// 4. Ask the generator to return a bitmap, which the GPU can convert.
auto hint = texGenPolicy == GrImageTexGenPolicy::kDraw ? CachingHint::kAllow_CachingHint
: CachingHint::kDisallow_CachingHint;
if (SkBitmap bitmap; this->getROPixels(&bitmap, hint)) {
// We always pass uncached here because we will cache it external to the maker based on
// *our* cache policy. We're just using the maker to generate the texture.
auto makerPolicy = texGenPolicy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted
? GrImageTexGenPolicy::kNew_Uncached_Unbudgeted
: GrImageTexGenPolicy::kNew_Uncached_Budgeted;
GrBitmapTextureMaker bitmapMaker(ctx, bitmap, makerPolicy);
auto view = bitmapMaker.view(mipMapped);
if (view) {
installKey(view);

View File

@ -10,6 +10,7 @@
#include "include/private/SkIDChangeListener.h"
#include "include/private/SkMutex.h"
#include "src/gpu/SkGr.h"
#include "src/image/SkImage_Base.h"
#if SK_SUPPORT_GPU
@ -60,7 +61,7 @@ public:
// Returns the texture proxy. CachingHint refers to whether the generator's output should be
// cached in CPU memory. We will always cache the generated texture on success.
GrSurfaceProxyView lockTextureProxyView(GrRecordingContext*,
SkImage::CachingHint,
GrImageTexGenPolicy,
GrMipMapped) const;
// Returns the GrColorType to use with the GrTextureProxy returned from lockTextureProxy. This

View File

@ -152,8 +152,8 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest, reporter,
SkIPoint origin = SkIPoint::Make(0,0);
SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
kPremul_SkAlphaType);
GrSurfaceProxyView genView =
imageGen->generateTexture(context, imageInfo, origin, requestMipMapped);
GrSurfaceProxyView genView = imageGen->generateTexture(
context, imageInfo, origin, requestMipMapped, GrImageTexGenPolicy::kDraw);
GrSurfaceProxy* genProxy = genView.proxy();
REPORTER_ASSERT(reporter, genProxy);

View File

@ -406,7 +406,8 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReadOnlyTexture, reporter, context_info) {
copySrcBitmap.installPixels(write);
copySrcBitmap.setImmutable();
GrBitmapTextureMaker maker(context, copySrcBitmap);
GrBitmapTextureMaker maker(context, copySrcBitmap,
GrImageTexGenPolicy::kNew_Uncached_Budgeted);
auto copySrc = maker.view(GrMipMapped::kNo);
REPORTER_ASSERT(reporter, copySrc.proxy());

View File

@ -209,7 +209,7 @@ DEF_TEST(ImageFilterCache_ImageBackedRaster, reporter) {
static GrSurfaceProxyView create_proxy_view(GrRecordingContext* context) {
SkBitmap srcBM = create_bm();
GrBitmapTextureMaker maker(context, srcBM);
GrBitmapTextureMaker maker(context, srcBM, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
return maker.view(GrMipMapped::kNo);
}

View File

@ -146,10 +146,12 @@ static sk_sp<SkImage> create_codec_image() {
auto src = SkEncodeBitmap(bitmap, SkEncodedImageFormat::kPNG, 100);
return SkImage::MakeFromEncoded(std::move(src));
}
static sk_sp<SkImage> create_gpu_image(GrContext* context, bool withMips = false) {
static sk_sp<SkImage> create_gpu_image(GrContext* context,
bool withMips = false,
SkBudgeted budgeted = SkBudgeted::kYes) {
const SkImageInfo info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
auto surface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info, 0,
kBottomLeft_GrSurfaceOrigin, nullptr, withMips));
auto surface = SkSurface::MakeRenderTarget(context, budgeted, info, 0,
kBottomLeft_GrSurfaceOrigin, nullptr, withMips);
draw_image_test_pattern(surface->getCanvas());
return surface->makeImageSnapshot();
}
@ -376,24 +378,19 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkImage_makeTextureImage, reporter, contextIn
testContext->makeCurrent();
std::function<sk_sp<SkImage>()> imageFactories[] = {
create_image,
create_codec_image,
create_data_image,
// Create an image from a picture.
create_picture_image,
// Create a texture image.
[context] { return create_gpu_image(context); },
// Create a texture image with mips
//[context] { return create_gpu_image(context, true); },
// Create a texture image in a another GrContext.
[otherContextInfo] {
auto restore = otherContextInfo.testContext()->makeCurrentAndAutoRestore();
sk_sp<SkImage> otherContextImage = create_gpu_image(otherContextInfo.grContext());
otherContextInfo.grContext()->flush();
return otherContextImage;
}
};
create_image, create_codec_image, create_data_image,
// Create an image from a picture.
create_picture_image,
// Create a texture image.
[context] { return create_gpu_image(context, true, SkBudgeted::kYes); },
[context] { return create_gpu_image(context, false, SkBudgeted::kNo); },
// Create a texture image in a another GrContext.
[otherContextInfo] {
auto restore = otherContextInfo.testContext()->makeCurrentAndAutoRestore();
sk_sp<SkImage> otherContextImage = create_gpu_image(otherContextInfo.grContext());
otherContextInfo.grContext()->flush();
return otherContextImage;
}};
for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
for (auto factory : imageFactories) {
sk_sp<SkImage> image(factory());
@ -401,44 +398,49 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkImage_makeTextureImage, reporter, contextIn
ERRORF(reporter, "Error creating image.");
continue;
}
sk_sp<SkImage> texImage(image->makeTextureImage(context, mipMapped));
if (!texImage) {
GrContext* imageContext = as_IB(image)->context();
// We expect to fail if image comes from a different GrContext.
if (!image->isTextureBacked() || imageContext == context) {
ERRORF(reporter, "makeTextureImage failed.");
GrTextureProxy* origProxy = nullptr;
if (auto sp = as_IB(image)->peekProxy()) {
origProxy = sp->asTextureProxy();
SkASSERT(origProxy);
}
for (auto budgeted : {SkBudgeted::kNo, SkBudgeted::kYes}) {
auto texImage = image->makeTextureImage(context, mipMapped, budgeted);
if (!texImage) {
GrContext* imageContext = as_IB(image)->context();
// We expect to fail if image comes from a different GrContext
if (!image->isTextureBacked() || imageContext == context) {
ERRORF(reporter, "makeTextureImage failed.");
}
continue;
}
continue;
}
if (!texImage->isTextureBacked()) {
ERRORF(reporter, "makeTextureImage returned non-texture image.");
continue;
}
if (GrMipMapped::kYes == mipMapped &&
as_IB(texImage)->peekProxy()->mipMapped() != mipMapped &&
context->priv().caps()->mipMapSupport()) {
ERRORF(reporter, "makeTextureImage returned non-mipmapped texture.");
continue;
}
if (image->isTextureBacked()) {
GrSurfaceProxy* origProxy = as_IB(image)->peekProxy();
GrSurfaceProxy* copyProxy = as_IB(texImage)->peekProxy();
if (origProxy->underlyingUniqueID() != copyProxy->underlyingUniqueID()) {
SkASSERT(origProxy->asTextureProxy());
if (GrMipMapped::kNo == mipMapped ||
GrMipMapped::kYes == origProxy->asTextureProxy()->mipMapped()) {
if (!texImage->isTextureBacked()) {
ERRORF(reporter, "makeTextureImage returned non-texture image.");
continue;
}
GrTextureProxy* copyProxy = as_IB(texImage)->peekProxy()->asTextureProxy();
SkASSERT(copyProxy);
bool shouldBeMipped =
mipMapped == GrMipMapped::kYes && context->priv().caps()->mipMapSupport();
if (shouldBeMipped && copyProxy->mipMapped() == GrMipMapped::kNo) {
ERRORF(reporter, "makeTextureImage returned non-mipmapped texture.");
continue;
}
bool origIsMipped = origProxy && origProxy->mipMapped() == GrMipMapped::kYes;
if (image->isTextureBacked() && (!shouldBeMipped || origIsMipped)) {
if (origProxy->underlyingUniqueID() != copyProxy->underlyingUniqueID()) {
ERRORF(reporter, "makeTextureImage made unnecessary texture copy.");
}
} else {
auto* texProxy = as_IB(texImage)->peekProxy()->asTextureProxy();
REPORTER_ASSERT(reporter, !texProxy->getUniqueKey().isValid());
REPORTER_ASSERT(reporter, texProxy->isBudgeted() == budgeted);
}
if (image->width() != texImage->width() || image->height() != texImage->height()) {
ERRORF(reporter, "makeTextureImage changed the image size.");
}
if (image->alphaType() != texImage->alphaType()) {
ERRORF(reporter, "makeTextureImage changed image alpha type.");
}
}
if (image->width() != texImage->width() || image->height() != texImage->height()) {
ERRORF(reporter, "makeTextureImage changed the image size.");
}
if (image->alphaType() != texImage->alphaType()) {
ERRORF(reporter, "makeTextureImage changed image alpha type.");
}
}
}

View File

@ -290,7 +290,7 @@ bool init_test_textures(GrResourceProvider* resourceProvider,
bitmap.installPixels(ii, rgbaData, ii.minRowBytes(),
[](void* addr, void* context) { delete[] (GrColor*)addr; }, nullptr);
bitmap.setImmutable();
GrBitmapTextureMaker maker(context, bitmap);
GrBitmapTextureMaker maker(context, bitmap, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
auto view = maker.view(GrMipMapped::kNo);
if (!view.proxy() || !view.proxy()->instantiate(resourceProvider)) {
return false;
@ -313,7 +313,7 @@ bool init_test_textures(GrResourceProvider* resourceProvider,
bitmap.installPixels(ii, alphaData, ii.minRowBytes(),
[](void* addr, void* context) { delete[] (uint8_t*)addr; }, nullptr);
bitmap.setImmutable();
GrBitmapTextureMaker maker(context, bitmap);
GrBitmapTextureMaker maker(context, bitmap, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
auto view = maker.view(GrMipMapped::kNo);
if (!view.proxy() || !view.proxy()->instantiate(resourceProvider)) {
return false;
@ -340,7 +340,7 @@ GrSurfaceProxyView make_input_texture(GrRecordingContext* context, int width, in
bitmap.installPixels(ii, data, ii.minRowBytes(),
[](void* addr, void* context) { delete[] (GrColor*)addr; }, nullptr);
bitmap.setImmutable();
GrBitmapTextureMaker maker(context, bitmap);
GrBitmapTextureMaker maker(context, bitmap, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
return maker.view(GrMipMapped::kNo);
}

View File

@ -66,7 +66,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReadWriteAlpha, reporter, ctxInfo) {
SkBitmap bitmap;
bitmap.installPixels(ii, alphaDataCopy, ii.minRowBytes());
bitmap.setImmutable();
GrBitmapTextureMaker maker(context, bitmap);
GrBitmapTextureMaker maker(context, bitmap, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
auto view = maker.view(GrMipMapped::kNo);
if (!view.proxy()) {
ERRORF(reporter, "Could not create alpha texture.");

View File

@ -223,7 +223,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_MakeTexture, reporter, ctxInfo)
{
// gpu
GrBitmapTextureMaker maker(context, bm);
GrBitmapTextureMaker maker(context, bm, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
auto view = maker.view(GrMipMapped::kNo);
if (!view) {
return;
@ -254,7 +254,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_MakeTexture, reporter, ctxInfo)
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_Gpu, reporter, ctxInfo) {
GrContext* context = ctxInfo.grContext();
SkBitmap bm = create_bm();
GrBitmapTextureMaker maker(context, bm);
GrBitmapTextureMaker maker(context, bm, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
auto view = maker.view(GrMipMapped::kNo);
if (!view.proxy()) {
return;

View File

@ -229,7 +229,7 @@ static void invalidation_test(GrContext* context, skiatest::Reporter* reporter)
}
sk_sp<SkImage> textureImg = rasterImg->makeTextureImage(context);
REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly());
REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
rasterImg = nullptr; // this invalidates the uniqueKey