blob: f4961ae78f3f2772f7127287ea173ad553786051 [file] [log] [blame]
Robert Phillips96601082018-05-29 16:13:26 -04001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef PromiseImageHelper_DEFINED
9#define PromiseImageHelper_DEFINED
10
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkBitmap.h"
Kevin Lubick3b9113f2021-11-02 11:38:39 -040012#include "include/core/SkRefCnt.h"
Brian Salomonbe0e42c2020-08-27 11:00:04 -040013#include "include/core/SkYUVAPixmaps.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "include/gpu/GrBackendSurface.h"
Kevin Lubickdc6cc022023-01-13 11:24:27 -050015#include "include/private/base/SkTArray.h"
Kevin Lubickeb981252023-06-13 07:51:26 -040016#include "include/private/chromium/GrPromiseImageTexture.h"
Kevin Lubick1b3aa8b2023-01-19 14:03:31 -050017#include "src/base/SkTLazy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "src/core/SkCachedData.h"
Robert Phillips96601082018-05-29 16:13:26 -040019
Kevin Lubick0bff57e2023-06-09 14:29:17 -040020class GrContextThreadSafeProxy;
Adlai Hollerb2705682020-10-20 10:11:53 -040021class GrDirectContext;
Robert Phillips96601082018-05-29 16:13:26 -040022class SkImage;
Mike Reed13711eb2020-07-14 17:16:32 -040023class SkMipmap;
Robert Phillips96601082018-05-29 16:13:26 -040024class SkPicture;
Robert Phillips1a578572020-07-13 13:17:09 -040025class SkTaskGroup;
Robert Phillips96601082018-05-29 16:13:26 -040026
Robert Phillips11c67672020-04-23 15:10:03 -040027// This class acts as a proxy for a GrBackendTexture that backs an image.
28// Whenever a promise image is created for the image, the promise image receives a ref to
29// potentially several of these objects. Once all the promise images receive their done
30// callbacks this object is deleted - removing the GrBackendTexture from VRAM.
31// Note that while the DDLs are being created in the threads, the PromiseImageHelper holds
32// a ref on all the PromiseImageCallbackContexts. However, once all the threads are done
33// it drops all of its refs (via "reset").
34class PromiseImageCallbackContext : public SkRefCnt {
35public:
Robert Phillipsd5f3c982020-07-07 13:18:47 -040036 PromiseImageCallbackContext(GrDirectContext* direct, GrBackendFormat backendFormat)
37 : fContext(direct)
Robert Phillips11c67672020-04-23 15:10:03 -040038 , fBackendFormat(backendFormat) {}
39
Brian Salomond0072812020-07-21 17:03:56 -040040 ~PromiseImageCallbackContext() override;
Robert Phillips11c67672020-04-23 15:10:03 -040041
42 const GrBackendFormat& backendFormat() const { return fBackendFormat; }
43
44 void setBackendTexture(const GrBackendTexture& backendTexture);
45
Robert Phillipsd5f3c982020-07-07 13:18:47 -040046 void destroyBackendTexture();
Robert Phillips11c67672020-04-23 15:10:03 -040047
Kevin Lubickeb981252023-06-13 07:51:26 -040048 sk_sp<GrPromiseImageTexture> fulfill() {
Robert Phillips11c67672020-04-23 15:10:03 -040049 ++fTotalFulfills;
50 return fPromiseImageTexture;
51 }
52
53 void release() {
Robert Phillips11c67672020-04-23 15:10:03 -040054 ++fDoneCnt;
Brian Salomon96796122021-01-19 12:11:07 -050055 SkASSERT(fDoneCnt <= fNumImages);
Robert Phillips11c67672020-04-23 15:10:03 -040056 }
57
58 void wasAddedToImage() { fNumImages++; }
59
Kevin Lubickeb981252023-06-13 07:51:26 -040060 const GrPromiseImageTexture* promiseImageTexture() const {
Robert Phillips11c67672020-04-23 15:10:03 -040061 return fPromiseImageTexture.get();
62 }
63
Kevin Lubickeb981252023-06-13 07:51:26 -040064 static sk_sp<GrPromiseImageTexture> PromiseImageFulfillProc(void* textureContext) {
Robert Phillips11c67672020-04-23 15:10:03 -040065 auto callbackContext = static_cast<PromiseImageCallbackContext*>(textureContext);
66 return callbackContext->fulfill();
67 }
68
69 static void PromiseImageReleaseProc(void* textureContext) {
70 auto callbackContext = static_cast<PromiseImageCallbackContext*>(textureContext);
71 callbackContext->release();
Robert Phillips11c67672020-04-23 15:10:03 -040072 callbackContext->unref();
73 }
74
75private:
Robert Phillipsd5f3c982020-07-07 13:18:47 -040076 GrDirectContext* fContext;
Robert Phillips11c67672020-04-23 15:10:03 -040077 GrBackendFormat fBackendFormat;
Kevin Lubickeb981252023-06-13 07:51:26 -040078 sk_sp<GrPromiseImageTexture> fPromiseImageTexture;
Robert Phillips11c67672020-04-23 15:10:03 -040079 int fNumImages = 0;
80 int fTotalFulfills = 0;
Robert Phillips11c67672020-04-23 15:10:03 -040081 int fDoneCnt = 0;
82
John Stiles7571f9e2020-09-02 22:42:33 -040083 using INHERITED = SkRefCnt;
Robert Phillips11c67672020-04-23 15:10:03 -040084};
85
Robert Phillips96601082018-05-29 16:13:26 -040086// This class consolidates tracking & extraction of the original image data from an skp,
87// the upload of said data to the GPU and the fulfillment of promise images.
88//
89// The way this works is:
90// the original skp is converted to SkData and all its image info is extracted into this
Robert Phillips0d8722c2021-03-29 13:29:40 -040091// class and only indices into this class are left in the SkData
92// the PromiseImageCallbackContexts are created for each image
93// the SkData is then reinflated into an SkPicture with promise images replacing all the indices
94// (all in recreateSKP)
Robert Phillips96601082018-05-29 16:13:26 -040095//
Robert Phillips0d8722c2021-03-29 13:29:40 -040096// Prior to replaying in threads, all the images are uploaded to the gpu
97// (in uploadAllToGPU)
Robert Phillips96601082018-05-29 16:13:26 -040098//
99// This class is then reset - dropping all of its refs on the PromiseImageCallbackContexts
100//
101// Each done callback unrefs its PromiseImageCallbackContext so, once all the promise images
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400102// are done, the PromiseImageCallbackContext is freed and its GrBackendTexture removed
Robert Phillips96601082018-05-29 16:13:26 -0400103// from VRAM
104//
105// Note: if DDLs are going to be replayed multiple times, the reset call can be delayed until
106// all the replaying is complete. This will pin the GrBackendTextures in VRAM.
107class DDLPromiseImageHelper {
108public:
Brian Salomon59c60b02020-09-01 15:01:15 -0400109 DDLPromiseImageHelper(const SkYUVAPixmapInfo::SupportedDataTypes& supportedYUVADataTypes)
110 : fSupportedYUVADataTypes(supportedYUVADataTypes) {}
Brian Salomon7d88f312019-02-28 10:03:03 -0500111 ~DDLPromiseImageHelper() = default;
Robert Phillips96601082018-05-29 16:13:26 -0400112
Robert Phillips0d8722c2021-03-29 13:29:40 -0400113 // Convert the input SkPicture into a new one which has promise images rather than live
114 // images.
115 sk_sp<SkPicture> recreateSKP(GrDirectContext*, SkPicture*);
Robert Phillips923181b2020-02-14 12:36:37 -0500116
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400117 void uploadAllToGPU(SkTaskGroup*, GrDirectContext*);
118 void deleteAllFromGPU(SkTaskGroup*, GrDirectContext*);
Robert Phillips96601082018-05-29 16:13:26 -0400119
Robert Phillips0d8722c2021-03-29 13:29:40 -0400120 // Remove this class' refs on the promise images and the PromiseImageCallbackContexts
121 void reset() {
Herb Derbye308b1c2022-12-13 09:27:24 -0500122 fImageInfo.clear();
123 fPromiseImages.clear();
Robert Phillips0d8722c2021-03-29 13:29:40 -0400124 }
Robert Phillips96601082018-05-29 16:13:26 -0400125
126private:
Robert Phillips0d8722c2021-03-29 13:29:40 -0400127 void createCallbackContexts(GrDirectContext*);
128 // reinflate a deflated SKP, replacing all the indices with promise images.
129 sk_sp<SkPicture> reinflateSKP(sk_sp<GrContextThreadSafeProxy>, SkData* deflatedSKP);
130
Robert Phillips96601082018-05-29 16:13:26 -0400131 // This is the information extracted into this class from the parsing of the skp file.
132 // Once it has all been uploaded to the GPU and distributed to the promise images, it
133 // is all dropped via "reset".
134 class PromiseImageInfo {
135 public:
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400136 PromiseImageInfo(int index, uint32_t originalUniqueID, const SkImageInfo& ii);
137 PromiseImageInfo(PromiseImageInfo&& other);
138 ~PromiseImageInfo();
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400139
140 int index() const { return fIndex; }
141 uint32_t originalUniqueID() const { return fOriginalUniqueID; }
Brian Salomon5660e8b2020-08-25 12:40:32 -0400142 bool isYUV() const { return fYUVAPixmaps.isValid(); }
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400143
Adlai Holler55aaefe2021-03-03 16:12:56 -0700144 SkISize overallDimensions() const { return fImageInfo.dimensions(); }
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400145 SkColorType overallColorType() const { return fImageInfo.colorType(); }
146 SkAlphaType overallAlphaType() const { return fImageInfo.alphaType(); }
147 sk_sp<SkColorSpace> refOverallColorSpace() const { return fImageInfo.refColorSpace(); }
148
Brian Salomonbd3792d2020-11-10 14:17:58 -0500149 const SkYUVAInfo& yuvaInfo() const { return fYUVAPixmaps.yuvaInfo(); }
150
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400151 const SkPixmap& yuvPixmap(int index) const {
152 SkASSERT(this->isYUV());
Brian Salomon5660e8b2020-08-25 12:40:32 -0400153 return fYUVAPixmaps.planes()[index];
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400154 }
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400155
156 const SkBitmap& baseLevel() const {
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400157 SkASSERT(!this->isYUV());
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400158 return fBaseLevel;
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400159 }
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400160 // This returns an array of all the available mipLevels - suitable for passing into
161 // createBackendTexture.
John Stilesec9b4aa2020-08-07 13:05:14 -0400162 std::unique_ptr<SkPixmap[]> normalMipLevels() const;
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400163 int numMipLevels() const;
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400164
165 void setCallbackContext(int index, sk_sp<PromiseImageCallbackContext> callbackContext) {
Brian Salomon0c0b5a62021-01-11 14:40:44 -0500166 SkASSERT(index >= 0 && index < (this->isYUV() ? SkYUVAInfo::kMaxPlanes : 1));
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400167 fCallbackContexts[index] = callbackContext;
168 }
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500169 PromiseImageCallbackContext* callbackContext(int index) const {
Brian Salomon0c0b5a62021-01-11 14:40:44 -0500170 SkASSERT(index >= 0 && index < (this->isYUV() ? SkYUVAInfo::kMaxPlanes : 1));
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400171 return fCallbackContexts[index].get();
172 }
173 sk_sp<PromiseImageCallbackContext> refCallbackContext(int index) const {
Brian Salomon0c0b5a62021-01-11 14:40:44 -0500174 SkASSERT(index >= 0 && index < (this->isYUV() ? SkYUVAInfo::kMaxPlanes : 1));
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400175 return fCallbackContexts[index];
176 }
177
Kevin Lubickdf73d162023-09-11 11:56:53 -0400178 skgpu::Mipmapped mipmapped(int index) const {
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400179 if (this->isYUV()) {
Kevin Lubickdf73d162023-09-11 11:56:53 -0400180 return skgpu::Mipmapped::kNo;
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400181 }
Kevin Lubickdf73d162023-09-11 11:56:53 -0400182 return fMipLevels ? skgpu::Mipmapped::kYes : skgpu::Mipmapped::kNo;
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400183 }
Robert Phillips923181b2020-02-14 12:36:37 -0500184 const GrBackendFormat& backendFormat(int index) const {
Brian Salomon0c0b5a62021-01-11 14:40:44 -0500185 SkASSERT(index >= 0 && index < (this->isYUV() ? SkYUVAInfo::kMaxPlanes : 1));
Robert Phillips923181b2020-02-14 12:36:37 -0500186 return fCallbackContexts[index]->backendFormat();
187 }
Kevin Lubickeb981252023-06-13 07:51:26 -0400188 const GrPromiseImageTexture* promiseTexture(int index) const {
Brian Salomon0c0b5a62021-01-11 14:40:44 -0500189 SkASSERT(index >= 0 && index < (this->isYUV() ? SkYUVAInfo::kMaxPlanes : 1));
Brian Salomon3f4cd772019-01-11 16:03:19 -0500190 return fCallbackContexts[index]->promiseImageTexture();
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400191 }
192
Mike Reed13711eb2020-07-14 17:16:32 -0400193 void setMipLevels(const SkBitmap& baseLevel, std::unique_ptr<SkMipmap> mipLevels);
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400194
Brian Salomonefb5f072020-07-28 21:06:43 -0400195 /** Takes ownership of the plane data. */
Brian Salomonbe0e42c2020-08-27 11:00:04 -0400196 void setYUVPlanes(SkYUVAPixmaps yuvaPixmaps) { fYUVAPixmaps = std::move(yuvaPixmaps); }
Brian Salomon5660e8b2020-08-25 12:40:32 -0400197
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400198 private:
199 const int fIndex; // index in the 'fImageInfo' array
200 const uint32_t fOriginalUniqueID; // original ID for deduping
201
202 const SkImageInfo fImageInfo; // info for the overarching image
203
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400204 // CPU-side cache of a normal SkImage's mipmap levels
205 SkBitmap fBaseLevel;
Mike Reed13711eb2020-07-14 17:16:32 -0400206 std::unique_ptr<SkMipmap> fMipLevels;
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400207
208 // CPU-side cache of a YUV SkImage's contents
Brian Salomonbe0e42c2020-08-27 11:00:04 -0400209 SkYUVAPixmaps fYUVAPixmaps;
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400210
Jim Van Verthe24b5872018-10-29 16:26:02 -0400211 // Up to SkYUVASizeInfo::kMaxCount for a YUVA image. Only one for a normal image.
Brian Salomon0c0b5a62021-01-11 14:40:44 -0500212 sk_sp<PromiseImageCallbackContext> fCallbackContexts[SkYUVAInfo::kMaxPlanes];
Robert Phillips96601082018-05-29 16:13:26 -0400213 };
214
Adlai Holler55aaefe2021-03-03 16:12:56 -0700215 struct DeserialImageProcContext {
216 sk_sp<GrContextThreadSafeProxy> fThreadSafeProxy;
Robert Phillips0d8722c2021-03-29 13:29:40 -0400217 DDLPromiseImageHelper* fHelper;
Robert Phillips96601082018-05-29 16:13:26 -0400218 };
219
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400220 static void CreateBETexturesForPromiseImage(GrDirectContext*, PromiseImageInfo*);
Brian Salomonbd3792d2020-11-10 14:17:58 -0500221 static void DeleteBETexturesForPromiseImage(PromiseImageInfo*);
Robert Phillips923181b2020-02-14 12:36:37 -0500222
Robert Phillips923181b2020-02-14 12:36:37 -0500223 static sk_sp<SkImage> CreatePromiseImages(const void* rawData, size_t length, void* ctxIn);
Robert Phillips96601082018-05-29 16:13:26 -0400224
Herb Derbyffacce52022-11-09 10:51:34 -0500225 bool isValidID(int id) const { return id >= 0 && id < fImageInfo.size(); }
Robert Phillips96601082018-05-29 16:13:26 -0400226 const PromiseImageInfo& getInfo(int id) const { return fImageInfo[id]; }
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400227 void uploadImage(GrDirectContext*, PromiseImageInfo*);
Robert Phillips96601082018-05-29 16:13:26 -0400228
229 // returns -1 if not found
230 int findImage(SkImage* image) const;
231
232 // returns -1 on failure
233 int addImage(SkImage* image);
234
235 // returns -1 on failure
236 int findOrDefineImage(SkImage* image);
237
Herb Derbyd7a008392023-03-02 15:36:17 -0500238 SkYUVAPixmapInfo::SupportedDataTypes fSupportedYUVADataTypes;
239 skia_private::TArray<PromiseImageInfo> fImageInfo;
Robert Phillips0d8722c2021-03-29 13:29:40 -0400240
241 // TODO: review the use of 'fPromiseImages' - it doesn't seem useful/necessary
Herb Derbyd7a008392023-03-02 15:36:17 -0500242 skia_private::TArray<sk_sp<SkImage>> fPromiseImages; // All the promise images in the
Robert Phillips0d8722c2021-03-29 13:29:40 -0400243 // reconstituted picture
Robert Phillips96601082018-05-29 16:13:26 -0400244};
245
246#endif