1 /*
2 * Copyright 2019 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/gpu/GrContextPriv.h"
9
10 #include "include/gpu/GrContextThreadSafeProxy.h"
11 #include "include/gpu/GrTexture.h"
12 #include "src/gpu/GrAuditTrail.h"
13 #include "src/gpu/GrContextThreadSafeProxyPriv.h"
14 #include "src/gpu/GrDrawingManager.h"
15 #include "src/gpu/GrGpu.h"
16 #include "src/gpu/GrMemoryPool.h"
17 #include "src/gpu/GrRenderTargetContext.h"
18 #include "src/gpu/GrSkSLFPFactoryCache.h"
19 #include "src/gpu/GrSurfaceContextPriv.h"
20 #include "src/gpu/GrSurfacePriv.h"
21 #include "src/gpu/GrTextureContext.h"
22 #include "src/gpu/SkGr.h"
23 #include "src/gpu/effects/generated/GrConfigConversionEffect.h"
24 #include "src/gpu/text/GrTextBlobCache.h"
25 #include "src/image/SkImage_Base.h"
26 #include "src/image/SkImage_Gpu.h"
27
28 #define ASSERT_OWNED_PROXY(P) \
29 SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == fContext)
30 #define ASSERT_SINGLE_OWNER \
31 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fContext->singleOwner());)
32 #define RETURN_VALUE_IF_ABANDONED(value) if (fContext->abandoned()) { return (value); }
33 #define RETURN_IF_ABANDONED RETURN_VALUE_IF_ABANDONED(void)
34
refCaps() const35 sk_sp<const GrCaps> GrContextPriv::refCaps() const {
36 return fContext->refCaps();
37 }
38
fpFactoryCache()39 sk_sp<GrSkSLFPFactoryCache> GrContextPriv::fpFactoryCache() {
40 return fContext->fpFactoryCache();
41 }
42
refOpMemoryPool()43 sk_sp<GrOpMemoryPool> GrContextPriv::refOpMemoryPool() {
44 return fContext->refOpMemoryPool();
45 }
46
addOnFlushCallbackObject(GrOnFlushCallbackObject * onFlushCBObject)47 void GrContextPriv::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
48 fContext->addOnFlushCallbackObject(onFlushCBObject);
49 }
50
makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy,GrColorType colorType,SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * props)51 sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy,
52 GrColorType colorType,
53 SkAlphaType alphaType,
54 sk_sp<SkColorSpace> colorSpace,
55 const SkSurfaceProps* props) {
56 return fContext->makeWrappedSurfaceContext(std::move(proxy), colorType, alphaType,
57 std::move(colorSpace), props);
58 }
59
makeDeferredTextureContext(SkBackingFit fit,int width,int height,GrColorType colorType,SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace,GrMipMapped mipMapped,GrSurfaceOrigin origin,SkBudgeted budgeted,GrProtected isProtected)60 sk_sp<GrTextureContext> GrContextPriv::makeDeferredTextureContext(SkBackingFit fit,
61 int width,
62 int height,
63 GrColorType colorType,
64 SkAlphaType alphaType,
65 sk_sp<SkColorSpace> colorSpace,
66 GrMipMapped mipMapped,
67 GrSurfaceOrigin origin,
68 SkBudgeted budgeted,
69 GrProtected isProtected) {
70 return fContext->makeDeferredTextureContext(fit, width, height, colorType, alphaType,
71 std::move(colorSpace), mipMapped, origin, budgeted,
72 isProtected);
73 }
74
makeDeferredRenderTargetContext(SkBackingFit fit,int width,int height,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,int sampleCnt,GrMipMapped mipMapped,GrSurfaceOrigin origin,const SkSurfaceProps * surfaceProps,SkBudgeted budgeted,GrProtected isProtected)75 sk_sp<GrRenderTargetContext> GrContextPriv::makeDeferredRenderTargetContext(
76 SkBackingFit fit,
77 int width,
78 int height,
79 GrColorType colorType,
80 sk_sp<SkColorSpace> colorSpace,
81 int sampleCnt,
82 GrMipMapped mipMapped,
83 GrSurfaceOrigin origin,
84 const SkSurfaceProps* surfaceProps,
85 SkBudgeted budgeted,
86 GrProtected isProtected) {
87 return fContext->makeDeferredRenderTargetContext(fit, width, height, colorType,
88 std::move(colorSpace), sampleCnt, mipMapped,
89 origin, surfaceProps, budgeted, isProtected);
90 }
91
makeDeferredRenderTargetContextWithFallback(SkBackingFit fit,int width,int height,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,int sampleCnt,GrMipMapped mipMapped,GrSurfaceOrigin origin,const SkSurfaceProps * surfaceProps,SkBudgeted budgeted)92 sk_sp<GrRenderTargetContext> GrContextPriv::makeDeferredRenderTargetContextWithFallback(
93 SkBackingFit fit, int width, int height, GrColorType colorType,
94 sk_sp<SkColorSpace> colorSpace, int sampleCnt, GrMipMapped mipMapped,
95 GrSurfaceOrigin origin, const SkSurfaceProps* surfaceProps, SkBudgeted budgeted) {
96 return fContext->makeDeferredRenderTargetContextWithFallback(
97 fit, width, height, colorType, std::move(colorSpace), sampleCnt, mipMapped, origin,
98 surfaceProps, budgeted);
99 }
100
makeBackendTextureContext(const GrBackendTexture & tex,GrSurfaceOrigin origin,GrColorType colorType,SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace)101 sk_sp<GrTextureContext> GrContextPriv::makeBackendTextureContext(const GrBackendTexture& tex,
102 GrSurfaceOrigin origin,
103 GrColorType colorType,
104 SkAlphaType alphaType,
105 sk_sp<SkColorSpace> colorSpace) {
106 ASSERT_SINGLE_OWNER
107
108 sk_sp<GrSurfaceProxy> proxy = this->proxyProvider()->wrapBackendTexture(
109 tex, colorType, origin, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType);
110 if (!proxy) {
111 return nullptr;
112 }
113
114 return this->drawingManager()->makeTextureContext(std::move(proxy), colorType, alphaType,
115 std::move(colorSpace));
116 }
117
makeBackendTextureRenderTargetContext(const GrBackendTexture & tex,GrSurfaceOrigin origin,int sampleCnt,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * props,ReleaseProc releaseProc,ReleaseContext releaseCtx)118 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContext(
119 const GrBackendTexture& tex,
120 GrSurfaceOrigin origin,
121 int sampleCnt,
122 GrColorType colorType,
123 sk_sp<SkColorSpace> colorSpace,
124 const SkSurfaceProps* props,
125 ReleaseProc releaseProc,
126 ReleaseContext releaseCtx) {
127 ASSERT_SINGLE_OWNER
128 SkASSERT(sampleCnt > 0);
129
130 sk_sp<GrTextureProxy> proxy(this->proxyProvider()->wrapRenderableBackendTexture(
131 tex, origin, sampleCnt, colorType, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
132 releaseProc, releaseCtx));
133 if (!proxy) {
134 return nullptr;
135 }
136
137 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), colorType,
138 std::move(colorSpace), props);
139 }
140
makeBackendRenderTargetRenderTargetContext(const GrBackendRenderTarget & backendRT,GrSurfaceOrigin origin,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * surfaceProps,ReleaseProc releaseProc,ReleaseContext releaseCtx)141 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendRenderTargetRenderTargetContext(
142 const GrBackendRenderTarget& backendRT,
143 GrSurfaceOrigin origin,
144 GrColorType colorType,
145 sk_sp<SkColorSpace> colorSpace,
146 const SkSurfaceProps* surfaceProps,
147 ReleaseProc releaseProc,
148 ReleaseContext releaseCtx) {
149 ASSERT_SINGLE_OWNER
150
151 sk_sp<GrSurfaceProxy> proxy = this->proxyProvider()->wrapBackendRenderTarget(
152 backendRT, colorType, origin, releaseProc, releaseCtx);
153 if (!proxy) {
154 return nullptr;
155 }
156
157 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), colorType,
158 std::move(colorSpace), surfaceProps);
159 }
160
makeBackendTextureAsRenderTargetRenderTargetContext(const GrBackendTexture & tex,GrSurfaceOrigin origin,int sampleCnt,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * props)161 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureAsRenderTargetRenderTargetContext(
162 const GrBackendTexture& tex,
163 GrSurfaceOrigin origin,
164 int sampleCnt,
165 GrColorType colorType,
166 sk_sp<SkColorSpace> colorSpace,
167 const SkSurfaceProps* props) {
168 ASSERT_SINGLE_OWNER
169 SkASSERT(sampleCnt > 0);
170 sk_sp<GrSurfaceProxy> proxy(
171 this->proxyProvider()->wrapBackendTextureAsRenderTarget(tex, colorType,
172 origin, sampleCnt));
173 if (!proxy) {
174 return nullptr;
175 }
176
177 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), colorType,
178 std::move(colorSpace), props);
179 }
180
makeVulkanSecondaryCBRenderTargetContext(const SkImageInfo & imageInfo,const GrVkDrawableInfo & vkInfo,const SkSurfaceProps * props)181 sk_sp<GrRenderTargetContext> GrContextPriv::makeVulkanSecondaryCBRenderTargetContext(
182 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo, const SkSurfaceProps* props) {
183 ASSERT_SINGLE_OWNER
184 sk_sp<GrSurfaceProxy> proxy(
185 this->proxyProvider()->wrapVulkanSecondaryCBAsRenderTarget(imageInfo, vkInfo));
186 if (!proxy) {
187 return nullptr;
188 }
189
190 return this->drawingManager()->makeRenderTargetContext(
191 std::move(proxy),
192 SkColorTypeToGrColorType(imageInfo.colorType()),
193 imageInfo.refColorSpace(),
194 props);
195 }
196
flushSurfaces(GrSurfaceProxy * proxies[],int numProxies,const GrFlushInfo & info)197 GrSemaphoresSubmitted GrContextPriv::flushSurfaces(GrSurfaceProxy* proxies[], int numProxies,
198 const GrFlushInfo& info) {
199 ASSERT_SINGLE_OWNER
200 RETURN_VALUE_IF_ABANDONED(GrSemaphoresSubmitted::kNo)
201 GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "flushSurfaces", fContext);
202 SkASSERT(numProxies >= 0);
203 SkASSERT(!numProxies || proxies);
204 for (int i = 0; i < numProxies; ++i) {
205 SkASSERT(proxies[i]);
206 ASSERT_OWNED_PROXY(proxies[i]);
207 }
208 return fContext->drawingManager()->flushSurfaces(
209 proxies, numProxies, SkSurface::BackendSurfaceAccess::kNoAccess, info);
210 }
211
flushSurface(GrSurfaceProxy * proxy)212 void GrContextPriv::flushSurface(GrSurfaceProxy* proxy) {
213 this->flushSurfaces(proxy ? &proxy : nullptr, proxy ? 1 : 0, {});
214 }
215
moveRenderTasksToDDL(SkDeferredDisplayList * ddl)216 void GrContextPriv::moveRenderTasksToDDL(SkDeferredDisplayList* ddl) {
217 fContext->drawingManager()->moveRenderTasksToDDL(ddl);
218 }
219
copyRenderTasksFromDDL(const SkDeferredDisplayList * ddl,GrRenderTargetProxy * newDest)220 void GrContextPriv::copyRenderTasksFromDDL(const SkDeferredDisplayList* ddl,
221 GrRenderTargetProxy* newDest) {
222 fContext->drawingManager()->copyRenderTasksFromDDL(ddl, newDest);
223 }
224
225 //////////////////////////////////////////////////////////////////////////////
226
227 #if GR_TEST_UTILS
resetGpuStats() const228 void GrContextPriv::resetGpuStats() const {
229 #if GR_GPU_STATS
230 fContext->fGpu->stats()->reset();
231 #endif
232 }
233
dumpCacheStats(SkString * out) const234 void GrContextPriv::dumpCacheStats(SkString* out) const {
235 #if GR_CACHE_STATS
236 fContext->fResourceCache->dumpStats(out);
237 #endif
238 }
239
dumpCacheStatsKeyValuePairs(SkTArray<SkString> * keys,SkTArray<double> * values) const240 void GrContextPriv::dumpCacheStatsKeyValuePairs(SkTArray<SkString>* keys,
241 SkTArray<double>* values) const {
242 #if GR_CACHE_STATS
243 fContext->fResourceCache->dumpStatsKeyValuePairs(keys, values);
244 #endif
245 }
246
printCacheStats() const247 void GrContextPriv::printCacheStats() const {
248 SkString out;
249 this->dumpCacheStats(&out);
250 SkDebugf("%s", out.c_str());
251 }
252
dumpGpuStats(SkString * out) const253 void GrContextPriv::dumpGpuStats(SkString* out) const {
254 #if GR_GPU_STATS
255 return fContext->fGpu->stats()->dump(out);
256 #endif
257 }
258
dumpGpuStatsKeyValuePairs(SkTArray<SkString> * keys,SkTArray<double> * values) const259 void GrContextPriv::dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys,
260 SkTArray<double>* values) const {
261 #if GR_GPU_STATS
262 return fContext->fGpu->stats()->dumpKeyValuePairs(keys, values);
263 #endif
264 }
265
printGpuStats() const266 void GrContextPriv::printGpuStats() const {
267 SkString out;
268 this->dumpGpuStats(&out);
269 SkDebugf("%s", out.c_str());
270 }
271
testingOnly_setTextBlobCacheLimit(size_t bytes)272 void GrContextPriv::testingOnly_setTextBlobCacheLimit(size_t bytes) {
273 fContext->priv().getTextBlobCache()->setBudget(bytes);
274 }
275
testingOnly_getFontAtlasImage(GrMaskFormat format,unsigned int index)276 sk_sp<SkImage> GrContextPriv::testingOnly_getFontAtlasImage(GrMaskFormat format, unsigned int index) {
277 auto atlasManager = this->getAtlasManager();
278 if (!atlasManager) {
279 return nullptr;
280 }
281
282 unsigned int numActiveProxies;
283 const sk_sp<GrTextureProxy>* proxies = atlasManager->getProxies(format, &numActiveProxies);
284 if (index >= numActiveProxies || !proxies || !proxies[index]) {
285 return nullptr;
286 }
287
288 SkASSERT(proxies[index]->priv().isExact());
289 sk_sp<SkImage> image(new SkImage_Gpu(sk_ref_sp(fContext), kNeedNewImageUniqueID,
290 kPremul_SkAlphaType, proxies[index], nullptr));
291 return image;
292 }
293
testingOnly_purgeAllUnlockedResources()294 void GrContextPriv::testingOnly_purgeAllUnlockedResources() {
295 fContext->fResourceCache->purgeAllUnlocked();
296 }
297
testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject * cb)298 void GrContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
299 fContext->flush();
300 fContext->drawingManager()->testingOnly_removeOnFlushCallbackObject(cb);
301 }
302 #endif
303
validPMUPMConversionExists()304 bool GrContextPriv::validPMUPMConversionExists() {
305 ASSERT_SINGLE_OWNER
306 if (!fContext->fDidTestPMConversions) {
307 fContext->fPMUPMConversionsRoundTrip =
308 GrConfigConversionEffect::TestForPreservingPMConversions(fContext);
309 fContext->fDidTestPMConversions = true;
310 }
311
312 // The PM<->UPM tests fail or succeed together so we only need to check one.
313 return fContext->fPMUPMConversionsRoundTrip;
314 }
315
createPMToUPMEffect(std::unique_ptr<GrFragmentProcessor> fp)316 std::unique_ptr<GrFragmentProcessor> GrContextPriv::createPMToUPMEffect(
317 std::unique_ptr<GrFragmentProcessor> fp) {
318 ASSERT_SINGLE_OWNER
319 // We should have already called this->priv().validPMUPMConversionExists() in this case
320 SkASSERT(fContext->fDidTestPMConversions);
321 // ...and it should have succeeded
322 SkASSERT(this->validPMUPMConversionExists());
323
324 return GrConfigConversionEffect::Make(std::move(fp), PMConversion::kToUnpremul);
325 }
326
createUPMToPMEffect(std::unique_ptr<GrFragmentProcessor> fp)327 std::unique_ptr<GrFragmentProcessor> GrContextPriv::createUPMToPMEffect(
328 std::unique_ptr<GrFragmentProcessor> fp) {
329 ASSERT_SINGLE_OWNER
330 // We should have already called this->priv().validPMUPMConversionExists() in this case
331 SkASSERT(fContext->fDidTestPMConversions);
332 // ...and it should have succeeded
333 SkASSERT(this->validPMUPMConversionExists());
334
335 return GrConfigConversionEffect::Make(std::move(fp), PMConversion::kToPremul);
336 }
337
338 //////////////////////////////////////////////////////////////////////////////
339
340 #include "src/core/SkMipMap.h"
341
createBackendTexture(const SkPixmap srcData[],int numLevels,GrRenderable renderable,GrProtected isProtected)342 GrBackendTexture GrContextPriv::createBackendTexture(const SkPixmap srcData[], int numLevels,
343 GrRenderable renderable,
344 GrProtected isProtected) {
345 if (!fContext->asDirectContext()) {
346 return {};
347 }
348
349 if (this->abandoned()) {
350 return {};
351 }
352
353 if (!srcData || !numLevels) {
354 return {};
355 }
356
357 int baseWidth = srcData[0].width();
358 int baseHeight = srcData[0].height();
359 SkColorType colorType = srcData[0].colorType();
360
361 if (numLevels > 1) {
362 if (numLevels != SkMipMap::ComputeLevelCount(baseWidth, baseHeight) + 1) {
363 return {};
364 }
365
366 int currentWidth = baseWidth;
367 int currentHeight = baseHeight;
368 for (int i = 1; i < numLevels; ++i) {
369 currentWidth = SkTMax(1, currentWidth / 2);
370 currentHeight = SkTMax(1, currentHeight / 2);
371
372 if (srcData[i].colorType() != colorType) {
373 return {};
374 }
375
376 if (srcData[i].width() != currentWidth || srcData[i].height() != currentHeight) {
377 return {};
378 }
379 }
380 }
381
382 GrBackendFormat backendFormat = fContext->defaultBackendFormat(colorType, renderable);
383 if (!backendFormat.isValid()) {
384 return {};
385 }
386
387 GrGpu* gpu = fContext->fGpu.get();
388
389 // TODO: propagate the array of pixmaps interface to GrGpu
390 return gpu->createBackendTexture(baseWidth, baseHeight, backendFormat,
391 GrMipMapped::kNo, // TODO: use real mipmap setting here
392 renderable, srcData[0].addr(), srcData[0].rowBytes(),
393 nullptr, isProtected);
394 }
395