blob: 2f9f454907262c9d42a238323430020742564dcd [file] [log] [blame]
Jim Van Verth8026ccc2018-10-04 13:10:39 -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 SkImage_GpuBase_DEFINED
9#define SkImage_GpuBase_DEFINED
10
Jim Van Verth8bbce0e2018-10-08 14:34:52 -040011#include "GrBackendSurface.h"
12#include "GrTypesPriv.h"
Jim Van Verth8026ccc2018-10-04 13:10:39 -040013#include "SkImage_Base.h"
14
15class GrContext;
16class SkColorSpace;
17
18class SkImage_GpuBase : public SkImage_Base {
19public:
20 SkImage_GpuBase(sk_sp<GrContext>, int width, int height, uint32_t uniqueID,
21 SkAlphaType, SkBudgeted, sk_sp<SkColorSpace>);
22 ~SkImage_GpuBase() override;
23
24 GrContext* context() const final { return fContext.get(); }
25
Brian Osmane50cdf02018-10-19 13:02:14 -040026 bool getROPixels(SkBitmap*, CachingHint) const final;
Jim Van Verth8026ccc2018-10-04 13:10:39 -040027 sk_sp<SkImage> onMakeSubset(const SkIRect& subset) const final;
28
Jim Van Verth8bbce0e2018-10-08 14:34:52 -040029 bool onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
30 int srcX, int srcY, CachingHint) const override;
31
Jim Van Verth8026ccc2018-10-04 13:10:39 -040032 sk_sp<GrTextureProxy> asTextureProxyRef() const override {
33 // we shouldn't end up calling this
34 SkASSERT(false);
35 return this->INHERITED::asTextureProxyRef();
36 }
Brian Osman6064e1c2018-10-19 14:27:54 -040037 sk_sp<GrTextureProxy> asTextureProxyRef(GrContext*, const GrSamplerState&,
Jim Van Verth8026ccc2018-10-04 13:10:39 -040038 SkScalar scaleAdjust[2]) const final;
39
40 sk_sp<GrTextureProxy> refPinnedTextureProxy(uint32_t* uniqueID) const final {
41 *uniqueID = this->uniqueID();
42 return this->asTextureProxyRef();
43 }
44
45 GrBackendTexture onGetBackendTexture(bool flushPendingGrContextIO,
46 GrSurfaceOrigin* origin) const final;
47
48 GrTexture* onGetTexture() const final;
49
50 sk_sp<SkImage> onMakeColorSpace(sk_sp<SkColorSpace>) const final;
51
52 bool onIsValid(GrContext*) const final;
53
Jim Van Verth21bd60d2018-10-12 15:00:20 -040054#if GR_TEST_UTILS
55 void resetContext(sk_sp<GrContext> newContext) {
56 SkASSERT(fContext->uniqueID() == newContext->uniqueID());
57 fContext = newContext;
58 }
59#endif
60
Jim Van Verth8026ccc2018-10-04 13:10:39 -040061 static bool ValidateBackendTexture(GrContext* ctx, const GrBackendTexture& tex,
62 GrPixelConfig* config, SkColorType ct, SkAlphaType at,
63 sk_sp<SkColorSpace> cs);
Jim Van Verth8bbce0e2018-10-08 14:34:52 -040064
65 typedef ReleaseContext TextureContext;
66 typedef void(*TextureFulfillProc)(TextureContext textureContext, GrBackendTexture* outTexture);
67 typedef void(*PromiseDoneProc)(TextureContext textureContext);
68
Jim Van Verth8026ccc2018-10-04 13:10:39 -040069protected:
70 sk_sp<GrContext> fContext;
71 const SkAlphaType fAlphaType; // alpha type for final image
72 const SkBudgeted fBudgeted;
73 sk_sp<SkColorSpace> fColorSpace; // color space for final image
74
75private:
76 typedef SkImage_Base INHERITED;
77};
78
Jim Van Verth8bbce0e2018-10-08 14:34:52 -040079
80/**
81 * This helper holds the normal hard ref for the Release proc as well as a hard ref on the DoneProc.
82 * Thus when a GrTexture is being released, it will unref both the ReleaseProc and DoneProc.
83 */
84class SkPromiseReleaseProcHelper : public GrReleaseProcHelper {
85public:
86 SkPromiseReleaseProcHelper(SkImage_GpuBase::TextureReleaseProc releaseProc,
87 SkImage_GpuBase::TextureContext context,
88 sk_sp<GrReleaseProcHelper> doneHelper)
89 : INHERITED(releaseProc, context)
90 , fDoneProcHelper(std::move(doneHelper)) {
91 }
92
93 void weak_dispose() const override {
94 // Call the inherited weak_dispose first so that we call the ReleaseProc before the DoneProc
95 // if we hold the last ref to the DoneProc.
96 INHERITED::weak_dispose();
97 fDoneProcHelper.reset();
98 }
99
100private:
101 mutable sk_sp<GrReleaseProcHelper> fDoneProcHelper;
102
103 typedef GrReleaseProcHelper INHERITED;
104};
105
106/**
107 * This helper class manages the ref counting for the the ReleaseProc and DoneProc for promise
108 * images. It holds a weak ref on the ReleaseProc (hard refs are owned by GrTextures). The weak ref
109 * allows us to reuse an outstanding ReleaseProc (because we dropped our GrTexture but the GrTexture
110 * isn't done on the GPU) without needing to call FulfillProc again. It also holds a hard ref on the
111 * DoneProc. The idea is that after every flush we may call the ReleaseProc so that the client can
112 * free up their GPU memory if they want to. The life time of the DoneProc matches that of any
113 * outstanding ReleaseProc as well as the PromiseImageHelper. Thus we won't call the DoneProc until
114 * all ReleaseProcs are finished and we are finished with the PromiseImageHelper (i.e. won't call
115 * FulfillProc again).
116 */
117class SkPromiseImageHelper {
118public:
119 SkPromiseImageHelper()
120 : fFulfillProc(nullptr)
121 , fReleaseProc(nullptr)
122 , fContext(nullptr)
123 , fDoneHelper(nullptr) {
124 }
125
126 void set(SkImage_GpuBase::TextureFulfillProc fulfillProc,
127 SkImage_GpuBase::TextureReleaseProc releaseProc,
128 SkImage_GpuBase::PromiseDoneProc doneProc,
129 SkImage_GpuBase::TextureContext context) {
130 fFulfillProc = fulfillProc;
131 fReleaseProc = releaseProc;
132 fContext = context;
133 fDoneHelper.reset(new GrReleaseProcHelper(doneProc, context));
134 }
135
136 SkPromiseImageHelper(SkImage_GpuBase::TextureFulfillProc fulfillProc,
137 SkImage_GpuBase::TextureReleaseProc releaseProc,
138 SkImage_GpuBase::PromiseDoneProc doneProc,
139 SkImage_GpuBase::TextureContext context)
140 : fFulfillProc(fulfillProc)
141 , fReleaseProc(releaseProc)
142 , fContext(context)
143 , fDoneHelper(new GrReleaseProcHelper(doneProc, context)) {
144 }
145
146 bool isValid() { return SkToBool(fDoneHelper); }
147
148 void reset() {
149 this->resetReleaseHelper();
150 fDoneHelper.reset();
151 }
152
153 sk_sp<GrTexture> getTexture(GrResourceProvider* resourceProvider, GrPixelConfig config);
154
155private:
156 // Weak unrefs fReleaseHelper and sets it to null
157 void resetReleaseHelper() {
158 if (fReleaseHelper) {
159 fReleaseHelper->weak_unref();
160 fReleaseHelper = nullptr;
161 }
162 }
163
164 SkImage_GpuBase::TextureFulfillProc fFulfillProc;
165 SkImage_GpuBase::TextureReleaseProc fReleaseProc;
166 SkImage_GpuBase::TextureContext fContext;
167
168 // We cache the GrBackendTexture so that if we deleted the GrTexture but the the release proc
169 // has yet not been called (this can happen on Vulkan), then we can create a new texture without
170 // needing to call the fulfill proc again.
171 GrBackendTexture fBackendTex;
172 // The fReleaseHelper is used to track a weak ref on the release proc. This helps us make sure
173 // we are always pairing fulfill and release proc calls correctly.
174 SkPromiseReleaseProcHelper* fReleaseHelper = nullptr;
175 // We don't want to call the fDoneHelper until we are done with the PromiseImageHelper and all
176 // ReleaseHelpers are finished. Thus we hold a hard ref here and we will pass a hard ref to each
177 // fReleaseHelper we make.
178 sk_sp<GrReleaseProcHelper> fDoneHelper;
179};
180
Jim Van Verth8026ccc2018-10-04 13:10:39 -0400181#endif