static void create_unique_key_for_image(const SkImage* image, GrUniqueKey* result) { if (!image) { result->reset(); // will be invalid return; } if (const SkBitmap* bm = as_IB(image)->onPeekBitmap()) { SkIPoint origin = bm->pixelRefOrigin(); SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, bm->width(), bm->height()); GrMakeKeyFromImageID(result, bm->getGenerationID(), subset); return; } GrMakeKeyFromImageID(result, image->uniqueID(), image->bounds()); }
void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey, SkColorSpace* dstColorSpace) { // Destination color space is irrelevant - we already have a texture so we're just sub-setting GrUniqueKey baseKey; GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeWH(this->width(), this->height())); MakeCopyKeyFromOrigKey(baseKey, params, copyKey); }
void GrImageTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey) { // By construction this texture adjuster always represents an entire SkImage, so use the // image's width and height for the key's rectangle. GrUniqueKey baseKey; GrMakeKeyFromImageID(&baseKey, fImageBase->uniqueID(), SkIRect::MakeWH(fImageBase->width(), fImageBase->height())); MakeCopyKeyFromOrigKey(baseKey, params, copyKey); }
GrYUVAImageTextureMaker::GrYUVAImageTextureMaker(GrContext* context, const SkImage* client, bool useDecal) : INHERITED(context, client->width(), client->height(), client->isAlphaOnly(), useDecal) , fImage(static_cast<const SkImage_GpuYUVA*>(client)) { SkASSERT(as_IB(client)->isYUVA()); GrMakeKeyFromImageID(&fOriginalKey, client->uniqueID(), SkIRect::MakeWH(this->width(), this->height())); }
GrImageTextureMaker::GrImageTextureMaker(GrRecordingContext* context, const SkImage* client, SkImage::CachingHint chint, bool useDecal) : INHERITED(context, client->width(), client->height(), client->isAlphaOnly(), useDecal) , fImage(static_cast<const SkImage_Lazy*>(client)) , fCachingHint(chint) { SkASSERT(client->isLazyGenerated()); GrMakeKeyFromImageID(&fOriginalKey, client->uniqueID(), SkIRect::MakeWH(this->width(), this->height())); }
GrBitmapTextureMaker::GrBitmapTextureMaker(GrContext* context, const SkBitmap& bitmap) : INHERITED(context, bitmap.width(), bitmap.height(), bmp_is_alpha_only(bitmap)) , 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); } }
/* * We have a 5 ways to try to return a texture (in sorted order) * * 1. Check the cache for a pre-existing one * 2. Ask the genreator to natively create one * 3. Ask the generator to return a compressed form that the GPU might support * 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::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) { return nullptr; } GrUniqueKey key; GrMakeKeyFromImageID(&key, fUniqueID, SkIRect::MakeWH(fInfo.width(), fInfo.height()), *ctx->caps(), usage); // 1. Check the cache for a pre-existing one if (GrTexture* tex = ctx->textureProvider()->findAndRefTextureByUniqueKey(key)) { return tex; } // 2. Ask the genreator to natively create one { ScopedGenerator generator(this); SkIRect subset = SkIRect::MakeXYWH(fOrigin.x(), fOrigin.y(), fInfo.width(), fInfo.height()); if (GrTexture* tex = generator->generateTexture(ctx, usage, &subset)) { return set_key_and_return(tex, key); } } const GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(fInfo); // 3. Ask the generator to return a compressed form that the GPU might support SkAutoTUnref<SkData> data(this->refEncoded()); if (data) { GrTexture* tex = load_compressed_into_texture(ctx, data, desc); if (tex) { return set_key_and_return(tex, key); } } // 4. Ask the generator to return YUV planes, which the GPU can convert { ScopedGenerator generator(this); Generator_GrYUVProvider provider(generator); GrTexture* tex = provider.refAsTexture(ctx, desc, true); if (tex) { return set_key_and_return(tex, key); } } // 5. Ask the generator to return RGB(A) data, which the GPU can convert SkBitmap bitmap; if (this->tryLockAsBitmap(&bitmap, client)) { return GrRefCachedBitmapTexture(ctx, bitmap, usage); } return nullptr; }
Cacherator_GrTextureMaker(GrContext* context, SkImageCacherator* cacher, const SkImage* client, SkImage::CachingHint chint) : INHERITED(context, cacher->info().width(), cacher->info().height()) , fCacher(cacher) , fClient(client) , fCachingHint(chint) { if (client) { GrMakeKeyFromImageID(&fOriginalKey, client->uniqueID(), SkIRect::MakeWH(this->width(), this->height())); } }
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); }
void GrBitmapTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey) { if (fBmp->isVolatile()) { return; } // The content area must represent the whole bitmap. Texture-backed bitmaps don't support // extractSubset(). Therefore, either the bitmap and the texture are the same size or the // content's dimensions are the bitmap's dimensions which is pinned to the upper left // of the texture. GrUniqueKey baseKey; GrMakeKeyFromImageID(&baseKey, fBmp->getGenerationID(), SkIRect::MakeWH(fBmp->width(), fBmp->height())); MakeCopyKeyFromOrigKey(baseKey, params, copyKey); }
GrTexture* SkImageCacherator::tryLockAsTexture(GrContext* ctx, SkImageUsageType usage) { #if SK_SUPPORT_GPU const uint32_t uniqueID = fGenerator->uniqueID(); const SkImageInfo& info = this->info(); GrUniqueKey key; GrMakeKeyFromImageID(&key, uniqueID, info.width(), info.height(), SkIPoint::Make(0, 0), *ctx->caps(), usage); GrTexture* tex = ctx->textureProvider()->findAndRefTextureByUniqueKey(key); if (tex) { return tex; // we got a cache hit! } tex = fGenerator->generateTexture(ctx, usage); if (tex) { tex->resourcePriv().setUniqueKey(key); } return tex; #else return nullptr; #endif }
// This tests the basic capabilities of the uniquely keyed texture proxies. Does assigning // and looking them up work, etc. static void basic_test(GrContext* context, skiatest::Reporter* reporter, sk_sp<GrTextureProxy> proxy) { static int id = 1; GrResourceProvider* resourceProvider = context->priv().resourceProvider(); GrProxyProvider* proxyProvider = context->priv().proxyProvider(); GrResourceCache* cache = context->priv().getResourceCache(); int startCacheCount = cache->getResourceCount(); GrUniqueKey key; if (proxy->getUniqueKey().isValid()) { key = proxy->getUniqueKey(); } else { GrMakeKeyFromImageID(&key, id, SkIRect::MakeWH(64, 64)); ++id; // Assigning the uniqueKey adds the proxy to the hash but doesn't force instantiation REPORTER_ASSERT(reporter, !proxyProvider->numUniqueKeyProxies_TestOnly()); SkAssertResult(proxyProvider->assignUniqueKeyToProxy(key, proxy.get())); } REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly()); REPORTER_ASSERT(reporter, startCacheCount == cache->getResourceCount()); // setUniqueKey had better stick REPORTER_ASSERT(reporter, key == proxy->getUniqueKey()); // We just added it, surely we can find it REPORTER_ASSERT(reporter, proxyProvider->findOrCreateProxyByUniqueKey( key, kBottomLeft_GrSurfaceOrigin)); REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly()); int expectedCacheCount = startCacheCount + (proxy->isInstantiated() ? 0 : 1); // Once instantiated, the backing resource should have the same key SkAssertResult(proxy->instantiate(resourceProvider)); const GrUniqueKey texKey = proxy->peekSurface()->getUniqueKey(); REPORTER_ASSERT(reporter, texKey.isValid()); REPORTER_ASSERT(reporter, key == texKey); // An Unbudgeted-cacheable resource will not get purged when a proxy with the same key is // deleted. bool expectResourceToOutliveProxy = proxy->peekSurface()->resourcePriv().budgetedType() == GrBudgetedType::kUnbudgetedCacheable; // An Unbudgeted-uncacheable resource is never kept alive if it's ref cnt reaches zero even if // it has a key. bool expectDeletingProxyToDeleteResource = proxy->peekSurface()->resourcePriv().budgetedType() == GrBudgetedType::kUnbudgetedUncacheable; // deleting the proxy should delete it from the hash but not the cache proxy = nullptr; if (expectDeletingProxyToDeleteResource) { expectedCacheCount -= 1; } REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly()); REPORTER_ASSERT(reporter, expectedCacheCount == cache->getResourceCount()); // If the proxy was cached refinding it should bring it back to life proxy = proxyProvider->findOrCreateProxyByUniqueKey(key, kBottomLeft_GrSurfaceOrigin); REPORTER_ASSERT(reporter, proxy); REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly()); REPORTER_ASSERT(reporter, expectedCacheCount == cache->getResourceCount()); // Mega-purging it should remove it from both the hash and the cache proxy = nullptr; cache->purgeAllUnlocked(); if (!expectResourceToOutliveProxy) { expectedCacheCount--; } REPORTER_ASSERT(reporter, expectedCacheCount == cache->getResourceCount()); // If the texture was deleted then the proxy should no longer be findable. Otherwise, it should // be. proxy = proxyProvider->findOrCreateProxyByUniqueKey(key, kBottomLeft_GrSurfaceOrigin); REPORTER_ASSERT(reporter, expectResourceToOutliveProxy ? (bool)proxy : !proxy); REPORTER_ASSERT(reporter, expectedCacheCount == cache->getResourceCount()); if (expectResourceToOutliveProxy) { proxy.reset(); GrUniqueKeyInvalidatedMessage msg(texKey, context->priv().contextID()); SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(msg); cache->purgeAsNeeded(); expectedCacheCount--; proxy = proxyProvider->findOrCreateProxyByUniqueKey(key, kBottomLeft_GrSurfaceOrigin); REPORTER_ASSERT(reporter, !proxy); REPORTER_ASSERT(reporter, expectedCacheCount == cache->getResourceCount()); } }
void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey) { GrUniqueKey baseKey; GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeWH(this->width(), this->height())); MakeCopyKeyFromOrigKey(baseKey, params, copyKey); }