aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/DDLPromiseImageHelper.h
diff options
context:
space:
mode:
authorGravatar Robert Phillips <robertphillips@google.com>2018-05-29 16:13:26 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-05-30 10:12:08 +0000
commit96601084b3f7b108c1faf12a2ea12eb7ea8688a0 (patch)
tree222f8ec851bd0156b32a382f458226170f7b33c0 /tools/DDLPromiseImageHelper.h
parent16f558ddeed33c816f3d3dad03997b2ea523c5b9 (diff)
Add DDL to SKPBench
Most of this CL is just repackaging the promise image and tile code from ViaDDL for reuse by SKPBench. Change-Id: Ie5003c36fe85cc5be9639552f9488b8e92dcdbbf Reviewed-on: https://skia-review.googlesource.com/129805 Reviewed-by: Chris Dalton <csmartdalton@google.com> Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com>
Diffstat (limited to 'tools/DDLPromiseImageHelper.h')
-rw-r--r--tools/DDLPromiseImageHelper.h144
1 files changed, 144 insertions, 0 deletions
diff --git a/tools/DDLPromiseImageHelper.h b/tools/DDLPromiseImageHelper.h
new file mode 100644
index 0000000000..b4b51a4f5b
--- /dev/null
+++ b/tools/DDLPromiseImageHelper.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef PromiseImageHelper_DEFINED
+#define PromiseImageHelper_DEFINED
+
+#include "SkBitmap.h"
+#include "SkTArray.h"
+
+#if SK_SUPPORT_GPU
+
+#include "GrBackendSurface.h"
+
+class GrContext;
+class SkDeferredDisplayListRecorder;
+class SkImage;
+class SkPicture;
+
+// This class consolidates tracking & extraction of the original image data from an skp,
+// the upload of said data to the GPU and the fulfillment of promise images.
+//
+// The way this works is:
+// the original skp is converted to SkData and all its image info is extracted into this
+// class and only indices into this class are left in the SkData (via deflateSKP)
+//
+// Prior to replaying in threads, all the images stored in this class are uploaded to the
+// gpu and PromiseImageCallbackContexts are created for them (via uploadAllToGPU)
+//
+// Each thread reinflates the SkData into an SkPicture replacing all the indices w/
+// promise images (all using the same GrBackendTexture and getting a ref to the
+// appropriate PromiseImageCallbackContext) (via reinflateSKP).
+//
+// This class is then reset - dropping all of its refs on the PromiseImageCallbackContexts
+//
+// Each done callback unrefs its PromiseImageCallbackContext so, once all the promise images
+// are done the PromiseImageCallbackContext is freed and its GrBackendTexture removed
+// from VRAM
+//
+// Note: if DDLs are going to be replayed multiple times, the reset call can be delayed until
+// all the replaying is complete. This will pin the GrBackendTextures in VRAM.
+class DDLPromiseImageHelper {
+public:
+ DDLPromiseImageHelper() { }
+
+ // Convert the SkPicture into SkData replacing all the SkImages with an index.
+ sk_sp<SkData> deflateSKP(const SkPicture* inputPicture);
+
+ void uploadAllToGPU(GrContext* context);
+
+ // reinflate a deflated SKP, replacing all the indices with promise images.
+ sk_sp<SkPicture> reinflateSKP(SkDeferredDisplayListRecorder*,
+ SkData* compressedPicture,
+ SkTArray<sk_sp<SkImage>>* promiseImages) const;
+
+ // Remove this class' refs on the PromiseImageCallbackContexts
+ void reset() { fImageInfo.reset(); }
+
+private:
+ // This class acts as a proxy for the single GrBackendTexture representing an image.
+ // Whenever a promise image is created for the image, the promise image receives a ref to
+ // this object. Once all the promise images receive their done callbacks this object
+ // is deleted - removing the GrBackendTexture from VRAM.
+ // Note that while the DDLs are being created in the threads, the PromiseImageHelper holds
+ // a ref on all the PromiseImageCallbackContexts. However, once all the threads are done
+ // it drops all of its refs (via "reset").
+ class PromiseImageCallbackContext : public SkRefCnt {
+ public:
+ PromiseImageCallbackContext(GrContext* context) : fContext(context) {}
+
+ ~PromiseImageCallbackContext();
+
+ void setBackendTexture(const GrBackendTexture& backendTexture) {
+ fBackendTexture = backendTexture;
+ }
+
+ const GrBackendTexture& backendTexture() const { return fBackendTexture; }
+
+ private:
+ GrContext* fContext;
+ GrBackendTexture fBackendTexture;
+
+ typedef SkRefCnt INHERITED;
+ };
+
+ // This is the information extracted into this class from the parsing of the skp file.
+ // Once it has all been uploaded to the GPU and distributed to the promise images, it
+ // is all dropped via "reset".
+ class PromiseImageInfo {
+ public:
+ int fIndex; // index in the 'fImageInfo' array
+ uint32_t fOriginalUniqueID; // original ID for deduping
+ SkBitmap fBitmap; // CPU-side cache of the contents
+ sk_sp<PromiseImageCallbackContext> fCallbackContext;
+ };
+
+ // This stack-based context allows each thread to re-inflate the image indices into
+ // promise images while still using the same GrBackendTexture.
+ struct PerRecorderContext {
+ SkDeferredDisplayListRecorder* fRecorder;
+ const DDLPromiseImageHelper* fHelper;
+ SkTArray<sk_sp<SkImage>>* fPromiseImages;
+ };
+
+ static void PromiseImageFulfillProc(void* textureContext, GrBackendTexture* outTexture) {
+ auto callbackContext = static_cast<PromiseImageCallbackContext*>(textureContext);
+ SkASSERT(callbackContext->backendTexture().isValid());
+ *outTexture = callbackContext->backendTexture();
+ }
+
+ static void PromiseImageReleaseProc(void* textureContext) {
+#ifdef SK_DEBUG
+ auto callbackContext = static_cast<PromiseImageCallbackContext*>(textureContext);
+ SkASSERT(callbackContext->backendTexture().isValid());
+#endif
+ }
+
+ static void PromiseImageDoneProc(void* textureContext) {
+ auto callbackContext = static_cast<PromiseImageCallbackContext*>(textureContext);
+ callbackContext->unref();
+ }
+
+ static sk_sp<SkImage> PromiseImageCreator(const void* rawData, size_t length, void* ctxIn);
+
+ bool isValidID(int id) const { return id >= 0 && id < fImageInfo.count(); }
+ const PromiseImageInfo& getInfo(int id) const { return fImageInfo[id]; }
+
+ // returns -1 if not found
+ int findImage(SkImage* image) const;
+
+ // returns -1 on failure
+ int addImage(SkImage* image);
+
+ // returns -1 on failure
+ int findOrDefineImage(SkImage* image);
+
+ SkTArray<PromiseImageInfo> fImageInfo;
+};
+
+#endif
+#endif