Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / src / image / SkImage_GpuBase.cpp
1 /*
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 #include "src/image/SkImage_GpuBase.h"
9
10 #include "include/core/SkBitmap.h"
11 #include "include/core/SkPromiseImageTexture.h"
12 #include "include/gpu/GrBackendSurface.h"
13 #include "include/gpu/GrDirectContext.h"
14 #include "include/gpu/GrRecordingContext.h"
15 #include "include/gpu/GrYUVABackendTextures.h"
16 #include "src/core/SkBitmapCache.h"
17 #include "src/gpu/ganesh/GrDirectContextPriv.h"
18 #include "src/gpu/ganesh/GrImageContextPriv.h"
19 #include "src/gpu/ganesh/GrImageInfo.h"
20 #include "src/gpu/ganesh/GrProxyProvider.h"
21 #include "src/gpu/ganesh/GrRecordingContextPriv.h"
22 #include "src/gpu/ganesh/GrResourceProvider.h"
23 #include "src/gpu/ganesh/GrTexture.h"
24 #include "src/gpu/ganesh/GrYUVATextureProxies.h"
25 #include "src/gpu/ganesh/SurfaceContext.h"
26 #include "src/gpu/ganesh/effects/GrYUVtoRGBEffect.h"
27 #include "src/image/SkImage_Gpu.h"
28 #include "src/image/SkReadPixelsRec.h"
29
30 SkImage_GpuBase::SkImage_GpuBase(sk_sp<GrImageContext> context, SkImageInfo info, uint32_t uniqueID)
31         : INHERITED(std::move(info), uniqueID)
32         , fContext(std::move(context)) {}
33
34 //////////////////////////////////////////////////////////////////////////////////////////////////
35
36 bool SkImage_GpuBase::ValidateBackendTexture(const GrCaps* caps, const GrBackendTexture& tex,
37                                              GrColorType grCT, SkColorType ct, SkAlphaType at,
38                                              sk_sp<SkColorSpace> cs) {
39     if (!tex.isValid()) {
40         return false;
41     }
42     SkColorInfo info(ct, at, cs);
43     if (!SkColorInfoIsValid(info)) {
44         return false;
45     }
46     GrBackendFormat backendFormat = tex.getBackendFormat();
47     if (!backendFormat.isValid()) {
48         return false;
49     }
50
51     return caps->areColorTypeAndFormatCompatible(grCT, backendFormat);
52 }
53
54 bool SkImage_GpuBase::ValidateCompressedBackendTexture(const GrCaps* caps,
55                                                        const GrBackendTexture& tex,
56                                                        SkAlphaType at) {
57     if (!tex.isValid() || tex.width() <= 0 || tex.height() <= 0) {
58         return false;
59     }
60
61     if (tex.width() > caps->maxTextureSize() || tex.height() > caps->maxTextureSize()) {
62         return false;
63     }
64
65     if (at == kUnknown_SkAlphaType) {
66         return false;
67     }
68
69     GrBackendFormat backendFormat = tex.getBackendFormat();
70     if (!backendFormat.isValid()) {
71         return false;
72     }
73
74     if (!caps->isFormatCompressed(backendFormat)) {
75         return false;
76     }
77
78     return true;
79 }
80
81 //////////////////////////////////////////////////////////////////////////////////////////////////
82
83 bool SkImage_GpuBase::getROPixels(GrDirectContext* dContext,
84                                   SkBitmap* dst,
85                                   CachingHint chint) const {
86     if (!fContext->priv().matches(dContext)) {
87         return false;
88     }
89
90     const auto desc = SkBitmapCacheDesc::Make(this);
91     if (SkBitmapCache::Find(desc, dst)) {
92         SkASSERT(dst->isImmutable());
93         SkASSERT(dst->getPixels());
94         return true;
95     }
96
97     SkBitmapCache::RecPtr rec = nullptr;
98     SkPixmap pmap;
99     if (kAllow_CachingHint == chint) {
100         rec = SkBitmapCache::Alloc(desc, this->imageInfo(), &pmap);
101         if (!rec) {
102             return false;
103         }
104     } else {
105         if (!dst->tryAllocPixels(this->imageInfo()) || !dst->peekPixels(&pmap)) {
106             return false;
107         }
108     }
109
110     auto [view, ct] = this->asView(dContext, GrMipmapped::kNo);
111     if (!view) {
112         return false;
113     }
114
115     GrColorInfo colorInfo(ct, this->alphaType(), this->refColorSpace());
116     auto sContext = dContext->priv().makeSC(std::move(view), std::move(colorInfo));
117     if (!sContext) {
118         return false;
119     }
120
121     if (!sContext->readPixels(dContext, pmap, {0, 0})) {
122         return false;
123     }
124
125     if (rec) {
126         SkBitmapCache::Add(std::move(rec), dst);
127         this->notifyAddedToRasterCache();
128     }
129     return true;
130 }
131
132 sk_sp<SkImage> SkImage_GpuBase::onMakeSubset(const SkIRect& subset,
133                                              GrDirectContext* direct) const {
134     if (!fContext->priv().matches(direct)) {
135         return nullptr;
136     }
137
138     auto [view, ct] = this->asView(direct, GrMipmapped::kNo);
139     SkASSERT(view);
140     SkASSERT(ct == SkColorTypeToGrColorType(this->colorType()));
141
142     SkBudgeted isBudgeted = view.proxy()->isBudgeted();
143     auto copyView = GrSurfaceProxyView::Copy(direct,
144                                              std::move(view),
145                                              GrMipmapped::kNo,
146                                              subset,
147                                              SkBackingFit::kExact,
148                                              isBudgeted);
149
150     if (!copyView) {
151         return nullptr;
152     }
153
154     return sk_make_sp<SkImage_Gpu>(sk_ref_sp(direct),
155                                    kNeedNewImageUniqueID,
156                                    std::move(copyView),
157                                    this->imageInfo().colorInfo());
158 }
159
160 bool SkImage_GpuBase::onReadPixels(GrDirectContext* dContext,
161                                    const SkImageInfo& dstInfo,
162                                    void* dstPixels,
163                                    size_t dstRB,
164                                    int srcX,
165                                    int srcY,
166                                    CachingHint) const {
167     if (!fContext->priv().matches(dContext) ||
168         !SkImageInfoValidConversion(dstInfo, this->imageInfo())) {
169         return false;
170     }
171
172     auto [view, ct] = this->asView(dContext, GrMipmapped::kNo);
173     SkASSERT(view);
174
175     GrColorInfo colorInfo(ct, this->alphaType(), this->refColorSpace());
176     auto sContext = dContext->priv().makeSC(std::move(view), colorInfo);
177     if (!sContext) {
178         return false;
179     }
180
181     return sContext->readPixels(dContext, {dstInfo, dstPixels, dstRB}, {srcX, srcY});
182 }
183
184 bool SkImage_GpuBase::onIsValid(GrRecordingContext* context) const {
185     // The base class has already checked that 'context' isn't abandoned (if it's not nullptr)
186     if (fContext->priv().abandoned()) {
187         return false;
188     }
189
190     if (context && !fContext->priv().matches(context)) {
191         return false;
192     }
193
194     return true;
195 }
196
197 sk_sp<GrTextureProxy> SkImage_GpuBase::MakePromiseImageLazyProxy(
198         GrContextThreadSafeProxy* tsp,
199         SkISize dimensions,
200         GrBackendFormat backendFormat,
201         GrMipmapped mipmapped,
202         PromiseImageTextureFulfillProc fulfillProc,
203         sk_sp<skgpu::RefCntedCallback> releaseHelper) {
204     SkASSERT(tsp);
205     SkASSERT(!dimensions.isEmpty());
206     SkASSERT(releaseHelper);
207
208     if (!fulfillProc) {
209         return nullptr;
210     }
211
212     if (mipmapped == GrMipmapped::kYes &&
213         GrTextureTypeHasRestrictedSampling(backendFormat.textureType())) {
214         // It is invalid to have a GL_TEXTURE_EXTERNAL or GL_TEXTURE_RECTANGLE and have mips as
215         // well.
216         return nullptr;
217     }
218
219     /**
220      * This class is the lazy instantiation callback for promise images. It manages calling the
221      * client's Fulfill, Release, and Done procs. It attempts to reuse a GrTexture instance in
222      * cases where the client provides the same SkPromiseImageTexture as Fulfill results for
223      * multiple SkImages. The created GrTexture is given a key based on a unique ID associated with
224      * the SkPromiseImageTexture.
225      *
226      * A key invalidation message is installed on the SkPromiseImageTexture so that the GrTexture
227      * is deleted once it can no longer be used to instantiate a proxy.
228      */
229     class PromiseLazyInstantiateCallback {
230     public:
231         PromiseLazyInstantiateCallback(PromiseImageTextureFulfillProc fulfillProc,
232                                        sk_sp<skgpu::RefCntedCallback> releaseHelper)
233                 : fFulfillProc(fulfillProc), fReleaseHelper(std::move(releaseHelper)) {}
234         PromiseLazyInstantiateCallback(PromiseLazyInstantiateCallback&&) = default;
235         PromiseLazyInstantiateCallback(const PromiseLazyInstantiateCallback&) {
236             // Because we get wrapped in std::function we must be copyable. But we should never
237             // be copied.
238             SkASSERT(false);
239         }
240         PromiseLazyInstantiateCallback& operator=(PromiseLazyInstantiateCallback&&) = default;
241         PromiseLazyInstantiateCallback& operator=(const PromiseLazyInstantiateCallback&) {
242             SkASSERT(false);
243             return *this;
244         }
245
246         ~PromiseLazyInstantiateCallback() {
247             // Our destructor can run on any thread. We trigger the unref of fTexture by message.
248             if (fTexture) {
249                 GrResourceCache::ReturnResourceFromThread(std::move(fTexture), fTextureContextID);
250             }
251         }
252
253         GrSurfaceProxy::LazyCallbackResult operator()(GrResourceProvider* resourceProvider,
254                                                       const GrSurfaceProxy::LazySurfaceDesc&) {
255             // We use the unique key in a way that is unrelated to the SkImage-based key that the
256             // proxy may receive, hence kUnsynced.
257             static constexpr auto kKeySyncMode =
258                     GrSurfaceProxy::LazyInstantiationKeyMode::kUnsynced;
259
260             // In order to make the SkImage "thread safe" we rely on holding an extra ref to the
261             // texture in the callback and signalling the unref via a message to the resource cache.
262             // We need to extend the callback's lifetime to that of the proxy.
263             static constexpr auto kReleaseCallbackOnInstantiation = false;
264
265             // Our proxy is getting instantiated for the second+ time. We are only allowed to call
266             // Fulfill once. So return our cached result.
267             if (fTexture) {
268                 return {fTexture, kReleaseCallbackOnInstantiation, kKeySyncMode};
269             } else if (fFulfillProcFailed) {
270                 // We've already called fulfill and it failed. Our contract says that we should only
271                 // call each callback once.
272                 return {};
273             }
274
275             PromiseImageTextureContext textureContext = fReleaseHelper->context();
276             sk_sp<SkPromiseImageTexture> promiseTexture = fFulfillProc(textureContext);
277
278             if (!promiseTexture) {
279                 fFulfillProcFailed = true;
280                 return {};
281             }
282
283             const GrBackendTexture& backendTexture = promiseTexture->backendTexture();
284             if (!backendTexture.isValid()) {
285                 return {};
286             }
287
288             fTexture = resourceProvider->wrapBackendTexture(backendTexture,
289                                                             kBorrow_GrWrapOwnership,
290                                                             GrWrapCacheable::kNo,
291                                                             kRead_GrIOType);
292             if (!fTexture) {
293                 return {};
294             }
295             fTexture->setRelease(fReleaseHelper);
296             auto dContext = fTexture->getContext();
297             fTextureContextID = dContext->directContextID();
298             return {fTexture, kReleaseCallbackOnInstantiation, kKeySyncMode};
299         }
300
301     private:
302         PromiseImageTextureFulfillProc fFulfillProc;
303         sk_sp<skgpu::RefCntedCallback> fReleaseHelper;
304         sk_sp<GrTexture> fTexture;
305         GrDirectContext::DirectContextID fTextureContextID;
306         bool fFulfillProcFailed = false;
307     } callback(fulfillProc, std::move(releaseHelper));
308
309     return GrProxyProvider::CreatePromiseProxy(tsp, std::move(callback), backendFormat, dimensions,
310                                                mipmapped);
311 }