blob: 1f481d0000cf9a97bcd8e03b2ac27892d3045cd0 [file] [log] [blame]
/*
* 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 "SkBitmap.h"
#include "SkBitmapCache.h"
#include "SkImageCacherator.h"
#include "SkPixelRef.h"
#if SK_SUPPORT_GPU
#include "GrContext.h"
#include "GrGpuResourcePriv.h"
#include "GrResourceKey.h"
#include "GrTextureAccess.h"
#include "SkGr.h"
#include "SkGrPriv.h"
#endif
SkImageCacherator* SkImageCacherator::NewFromGenerator(SkImageGenerator* gen) {
if (!gen) {
return nullptr;
}
return SkNEW_ARGS(SkImageCacherator, (gen));
}
SkImageCacherator::SkImageCacherator(SkImageGenerator* gen) : fGenerator(gen) {}
SkImageCacherator::~SkImageCacherator() {
SkDELETE(fGenerator);
}
static bool check_output_bitmap(const SkBitmap& bitmap, uint32_t expectedID) {
SkASSERT(bitmap.getGenerationID() == expectedID);
SkASSERT(bitmap.isImmutable());
SkASSERT(bitmap.getPixels());
return true;
}
static bool generate_bitmap(SkImageGenerator* generator, SkBitmap* bitmap) {
if (!bitmap->tryAllocPixels(generator->getInfo()) ||
!generator->getPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes()))
{
bitmap->reset();
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
bool SkImageCacherator::tryLockAsBitmap(SkBitmap* bitmap) {
const uint32_t uniqueID = fGenerator->uniqueID();
if (SkBitmapCache::Find(uniqueID, bitmap)) {
return check_output_bitmap(*bitmap, uniqueID);
}
if (!generate_bitmap(fGenerator, bitmap)) {
return false;
}
bitmap->pixelRef()->setImmutableWithID(uniqueID);
SkBitmapCache::Add(uniqueID, *bitmap);
return true;
}
bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap) {
const uint32_t uniqueID = fGenerator->uniqueID();
if (this->tryLockAsBitmap(bitmap)) {
return check_output_bitmap(*bitmap, uniqueID);
}
#if SK_SUPPORT_GPU
// Try to get a texture and read it back to raster (and then cache that with our ID)
SkAutoTUnref<GrTexture> tex(fGenerator->generateTexture(nullptr, kUntiled_SkImageUsageType));
if (!tex) {
bitmap->reset();
return false;
}
const SkImageInfo& info = this->info();
if (!bitmap->tryAllocPixels(info)) {
bitmap->reset();
return false;
}
const uint32_t pixelOpsFlags = 0;
if (!tex->readPixels(0, 0, bitmap->width(), bitmap->height(), SkImageInfo2GrPixelConfig(info),
bitmap->getPixels(), bitmap->rowBytes(), pixelOpsFlags)) {
bitmap->reset();
return false;
}
bitmap->pixelRef()->setImmutableWithID(uniqueID);
SkBitmapCache::Add(uniqueID, *bitmap);
return check_output_bitmap(*bitmap, uniqueID);
#else
return false;
#endif
}
//////////////////////////////////////////////////////////////////////////////////////////////////
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
}
GrTexture* SkImageCacherator::lockAsTexture(GrContext* ctx, SkImageUsageType usage) {
#if SK_SUPPORT_GPU
if (!ctx) {
return nullptr;
}
if (GrTexture* tex = this->tryLockAsTexture(ctx, usage)) {
return tex;
}
// Try to get a bitmap and then upload/cache it as a texture
SkBitmap bitmap;
if (!generate_bitmap(fGenerator, &bitmap)) {
return nullptr;
}
return GrRefCachedBitmapTexture(ctx, bitmap, usage);
#else
return nullptr;
#endif
}