blob: 38b60655333e3b5871040e241cf54b0bb6f90075 [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 Verth0e671942018-11-09 12:03:57 -050064 static bool MakeTempTextureProxies(GrContext* ctx, const GrBackendTexture yuvaTextures[],
65 int numTextures, GrSurfaceOrigin imageOrigin,
66 sk_sp<GrTextureProxy> tempTextureProxies[4]);
Jim Van Verth8bbce0e2018-10-08 14:34:52 -040067
68 typedef ReleaseContext TextureContext;
69 typedef void(*TextureFulfillProc)(TextureContext textureContext, GrBackendTexture* outTexture);
70 typedef void(*PromiseDoneProc)(TextureContext textureContext);
71
Jim Van Verth8026ccc2018-10-04 13:10:39 -040072protected:
Jim Van Verth0e671942018-11-09 12:03:57 -050073 static bool RenderYUVAToRGBA(GrContext* ctx, GrRenderTargetContext* renderTargetContext,
74 const SkRect& rect, SkYUVColorSpace yuvColorSpace,
75 const sk_sp<GrTextureProxy> proxies[4],
76 const SkYUVAIndex yuvaIndices[4]);
77
Jim Van Verth8026ccc2018-10-04 13:10:39 -040078 sk_sp<GrContext> fContext;
79 const SkAlphaType fAlphaType; // alpha type for final image
80 const SkBudgeted fBudgeted;
81 sk_sp<SkColorSpace> fColorSpace; // color space for final image
82
83private:
84 typedef SkImage_Base INHERITED;
85};
86
Jim Van Verth8bbce0e2018-10-08 14:34:52 -040087
88/**
89 * This helper holds the normal hard ref for the Release proc as well as a hard ref on the DoneProc.
90 * Thus when a GrTexture is being released, it will unref both the ReleaseProc and DoneProc.
91 */
92class SkPromiseReleaseProcHelper : public GrReleaseProcHelper {
93public:
94 SkPromiseReleaseProcHelper(SkImage_GpuBase::TextureReleaseProc releaseProc,
95 SkImage_GpuBase::TextureContext context,
96 sk_sp<GrReleaseProcHelper> doneHelper)
97 : INHERITED(releaseProc, context)
98 , fDoneProcHelper(std::move(doneHelper)) {
99 }
100
101 void weak_dispose() const override {
102 // Call the inherited weak_dispose first so that we call the ReleaseProc before the DoneProc
103 // if we hold the last ref to the DoneProc.
104 INHERITED::weak_dispose();
105 fDoneProcHelper.reset();
106 }
107
108private:
109 mutable sk_sp<GrReleaseProcHelper> fDoneProcHelper;
110
111 typedef GrReleaseProcHelper INHERITED;
112};
113
114/**
115 * This helper class manages the ref counting for the the ReleaseProc and DoneProc for promise
116 * images. It holds a weak ref on the ReleaseProc (hard refs are owned by GrTextures). The weak ref
117 * allows us to reuse an outstanding ReleaseProc (because we dropped our GrTexture but the GrTexture
118 * isn't done on the GPU) without needing to call FulfillProc again. It also holds a hard ref on the
119 * DoneProc. The idea is that after every flush we may call the ReleaseProc so that the client can
120 * free up their GPU memory if they want to. The life time of the DoneProc matches that of any
121 * outstanding ReleaseProc as well as the PromiseImageHelper. Thus we won't call the DoneProc until
122 * all ReleaseProcs are finished and we are finished with the PromiseImageHelper (i.e. won't call
123 * FulfillProc again).
124 */
125class SkPromiseImageHelper {
126public:
127 SkPromiseImageHelper()
128 : fFulfillProc(nullptr)
129 , fReleaseProc(nullptr)
130 , fContext(nullptr)
131 , fDoneHelper(nullptr) {
132 }
133
134 void set(SkImage_GpuBase::TextureFulfillProc fulfillProc,
135 SkImage_GpuBase::TextureReleaseProc releaseProc,
136 SkImage_GpuBase::PromiseDoneProc doneProc,
137 SkImage_GpuBase::TextureContext context) {
138 fFulfillProc = fulfillProc;
139 fReleaseProc = releaseProc;
140 fContext = context;
141 fDoneHelper.reset(new GrReleaseProcHelper(doneProc, context));
142 }
143
144 SkPromiseImageHelper(SkImage_GpuBase::TextureFulfillProc fulfillProc,
145 SkImage_GpuBase::TextureReleaseProc releaseProc,
146 SkImage_GpuBase::PromiseDoneProc doneProc,
147 SkImage_GpuBase::TextureContext context)
148 : fFulfillProc(fulfillProc)
149 , fReleaseProc(releaseProc)
150 , fContext(context)
151 , fDoneHelper(new GrReleaseProcHelper(doneProc, context)) {
152 }
153
154 bool isValid() { return SkToBool(fDoneHelper); }
155
156 void reset() {
157 this->resetReleaseHelper();
158 fDoneHelper.reset();
159 }
160
161 sk_sp<GrTexture> getTexture(GrResourceProvider* resourceProvider, GrPixelConfig config);
162
163private:
164 // Weak unrefs fReleaseHelper and sets it to null
165 void resetReleaseHelper() {
166 if (fReleaseHelper) {
167 fReleaseHelper->weak_unref();
168 fReleaseHelper = nullptr;
169 }
170 }
171
172 SkImage_GpuBase::TextureFulfillProc fFulfillProc;
173 SkImage_GpuBase::TextureReleaseProc fReleaseProc;
174 SkImage_GpuBase::TextureContext fContext;
175
176 // We cache the GrBackendTexture so that if we deleted the GrTexture but the the release proc
177 // has yet not been called (this can happen on Vulkan), then we can create a new texture without
178 // needing to call the fulfill proc again.
179 GrBackendTexture fBackendTex;
180 // The fReleaseHelper is used to track a weak ref on the release proc. This helps us make sure
181 // we are always pairing fulfill and release proc calls correctly.
182 SkPromiseReleaseProcHelper* fReleaseHelper = nullptr;
183 // We don't want to call the fDoneHelper until we are done with the PromiseImageHelper and all
184 // ReleaseHelpers are finished. Thus we hold a hard ref here and we will pass a hard ref to each
185 // fReleaseHelper we make.
186 sk_sp<GrReleaseProcHelper> fDoneHelper;
187};
188
Jim Van Verth8026ccc2018-10-04 13:10:39 -0400189#endif