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