aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkImageCacherator.cpp144
-rw-r--r--src/core/SkImageCacherator.h51
-rw-r--r--src/core/SkImageGenerator.cpp13
-rw-r--r--src/core/SkPictureImageGenerator.cpp30
4 files changed, 237 insertions, 1 deletions
diff --git a/src/core/SkImageCacherator.cpp b/src/core/SkImageCacherator.cpp
new file mode 100644
index 0000000000..b225612a17
--- /dev/null
+++ b/src/core/SkImageCacherator.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 "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(SkImageGenerator* gen) : fGenerator(gen) {}
+
+SkImageCacherator::~SkImageCacherator() {
+ delete 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
+}
+
diff --git a/src/core/SkImageCacherator.h b/src/core/SkImageCacherator.h
new file mode 100644
index 0000000000..86dbd8874f
--- /dev/null
+++ b/src/core/SkImageCacherator.h
@@ -0,0 +1,51 @@
+/*
+ * 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 SkImageCacherator_DEFINED
+#define SkImageCacherator_DEFINED
+
+#include "SkImageGenerator.h"
+
+class GrContext;
+class SkBitmap;
+
+/*
+ * Internal class to manage caching the output of an ImageGenerator.
+ */
+class SkImageCacherator {
+public:
+ // Takes ownership of the generator
+ SkImageCacherator(SkImageGenerator* gen);
+ ~SkImageCacherator();
+
+ const SkImageInfo& info() const { return fGenerator->getInfo(); }
+ SkImageGenerator* generator() const { return fGenerator; }
+
+ /**
+ * On success (true), bitmap will point to the pixels for this generator. If this returns
+ * false, the bitmap will be reset to empty.
+ *
+ * The cached bitmap is valid until it goes out of scope.
+ */
+ bool lockAsBitmap(SkBitmap*);
+
+ /**
+ * Returns a ref() on the texture produced by this generator. The caller must call unref()
+ * when it is done. Will return NULL on failure.
+ *
+ * The cached texture is valid until it is unref'd.
+ */
+ GrTexture* lockAsTexture(GrContext*, SkImageUsageType);
+
+private:
+ bool tryLockAsBitmap(SkBitmap*);
+ GrTexture* tryLockAsTexture(GrContext*, SkImageUsageType);
+
+ SkImageGenerator* fGenerator;
+};
+
+#endif
diff --git a/src/core/SkImageGenerator.cpp b/src/core/SkImageGenerator.cpp
index 82b42d7a97..d42ece828a 100644
--- a/src/core/SkImageGenerator.cpp
+++ b/src/core/SkImageGenerator.cpp
@@ -6,6 +6,12 @@
*/
#include "SkImageGenerator.h"
+#include "SkNextID.h"
+
+SkImageGenerator::SkImageGenerator(const SkImageInfo& info)
+ : fInfo(info)
+ , fUniqueID(SkNextID::ImageID())
+{}
bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
SkPMColor ctable[], int* ctableCount) {
@@ -98,6 +104,13 @@ bool SkImageGenerator::onGetYUV8Planes(SkISize sizes[3], void* planes[3], size_t
return this->onGetYUV8Planes(sizes, planes, rowBytes);
}
+GrTexture* SkImageGenerator::generateTexture(GrContext* ctx, SkImageUsageType usage) {
+ if (!ctx) {
+ return nullptr;
+ }
+ return this->onGenerateTexture(ctx, usage);
+}
+
/////////////////////////////////////////////////////////////////////////////////////////////
SkData* SkImageGenerator::onRefEncodedData() {
diff --git a/src/core/SkPictureImageGenerator.cpp b/src/core/SkPictureImageGenerator.cpp
index 6c3faef250..f92de3b986 100644
--- a/src/core/SkPictureImageGenerator.cpp
+++ b/src/core/SkPictureImageGenerator.cpp
@@ -6,11 +6,11 @@
*/
#include "SkImageGenerator.h"
-
#include "SkCanvas.h"
#include "SkMatrix.h"
#include "SkPaint.h"
#include "SkPicture.h"
+#include "SkSurface.h"
#include "SkTLazy.h"
class SkPictureImageGenerator : SkImageGenerator {
@@ -21,6 +21,9 @@ public:
protected:
bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[],
int* ctableCount) override;
+#if SK_SUPPORT_GPU
+ GrTexture* onGenerateTexture(GrContext*, SkImageUsageType) override;
+#endif
private:
SkPictureImageGenerator(const SkISize&, const SkPicture*, const SkMatrix*, const SkPaint*);
@@ -79,3 +82,28 @@ SkImageGenerator* SkImageGenerator::NewFromPicture(const SkISize& size, const Sk
const SkMatrix* matrix, const SkPaint* paint) {
return SkPictureImageGenerator::Create(size, picture, matrix, paint);
}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+#if SK_SUPPORT_GPU
+#include "GrTexture.h"
+
+GrTexture* SkPictureImageGenerator::onGenerateTexture(GrContext* ctx, SkImageUsageType usage) {
+ //
+ // TODO: respect the usage, by possibly creating a different (pow2) surface
+ //
+ SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(ctx,
+ SkSurface::kYes_Budgeted,
+ this->getInfo()));
+ if (!surface.get()) {
+ return nullptr;
+ }
+ surface->getCanvas()->clear(0); // does NewRenderTarget promise to do this for us?
+ surface->getCanvas()->drawPicture(fPicture, &fMatrix, fPaint.getMaybeNull());
+ SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
+ if (!image.get()) {
+ return nullptr;
+ }
+ return SkSafeRef(image->getTexture());
+}
+#endif