1 /*
2  * Copyright 2011 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 "include/gpu/GrContext.h"
9 
10 #include "include/core/SkTraceMemoryDump.h"
11 #include "include/gpu/GrBackendSemaphore.h"
12 #include "include/private/SkDeferredDisplayList.h"
13 #include "include/private/SkImageInfoPriv.h"
14 #include "src/core/SkMakeUnique.h"
15 #include "src/core/SkTaskGroup.h"
16 #include "src/gpu/GrClientMappedBufferManager.h"
17 #include "src/gpu/GrContextPriv.h"
18 #include "src/gpu/GrDrawingManager.h"
19 #include "src/gpu/GrGpu.h"
20 #include "src/gpu/GrMemoryPool.h"
21 #include "src/gpu/GrPathRendererChain.h"
22 #include "src/gpu/GrProxyProvider.h"
23 #include "src/gpu/GrRenderTargetProxy.h"
24 #include "src/gpu/GrResourceCache.h"
25 #include "src/gpu/GrResourceProvider.h"
26 #include "src/gpu/GrSemaphore.h"
27 #include "src/gpu/GrShaderUtils.h"
28 #include "src/gpu/GrSoftwarePathRenderer.h"
29 #include "src/gpu/GrTracing.h"
30 #include "src/gpu/SkGr.h"
31 #include "src/gpu/ccpr/GrCoverageCountingPathRenderer.h"
32 #include "src/gpu/effects/GrSkSLFP.h"
33 #include "src/gpu/text/GrTextBlobCache.h"
34 #include "src/gpu/text/GrTextContext.h"
35 #include "src/image/SkImage_GpuBase.h"
36 #include "src/image/SkSurface_Gpu.h"
37 #include <atomic>
38 
39 #define ASSERT_OWNED_PROXY(P) \
40     SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == this)
41 
42 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
43 #define ASSERT_SINGLE_OWNER \
44     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
45 #define RETURN_IF_ABANDONED if (this->abandoned()) { return; }
46 #define RETURN_FALSE_IF_ABANDONED if (this->abandoned()) { return false; }
47 #define RETURN_NULL_IF_ABANDONED if (this->abandoned()) { return nullptr; }
48 
49 ////////////////////////////////////////////////////////////////////////////////
50 
GrContext(GrBackendApi backend,const GrContextOptions & options,int32_t contextID)51 GrContext::GrContext(GrBackendApi backend, const GrContextOptions& options, int32_t contextID)
52         : INHERITED(backend, options, contextID) {
53     fResourceCache = nullptr;
54     fResourceProvider = nullptr;
55 }
56 
~GrContext()57 GrContext::~GrContext() {
58     ASSERT_SINGLE_OWNER
59 
60     if (this->drawingManager()) {
61         this->drawingManager()->cleanup();
62     }
63     delete fResourceProvider;
64     delete fResourceCache;
65 }
66 
init(sk_sp<const GrCaps> caps,sk_sp<GrSkSLFPFactoryCache> FPFactoryCache)67 bool GrContext::init(sk_sp<const GrCaps> caps, sk_sp<GrSkSLFPFactoryCache> FPFactoryCache) {
68     ASSERT_SINGLE_OWNER
69     SkASSERT(fThreadSafeProxy); // needs to have been initialized by derived classes
70     SkASSERT(this->proxyProvider());
71 
72     if (!INHERITED::init(std::move(caps), std::move(FPFactoryCache))) {
73         return false;
74     }
75 
76     SkASSERT(this->caps());
77     SkASSERT(this->getGrStrikeCache());
78     SkASSERT(this->getTextBlobCache());
79 
80     if (fGpu) {
81         fResourceCache = new GrResourceCache(this->caps(), this->singleOwner(), this->contextID());
82         fResourceProvider = new GrResourceProvider(fGpu.get(), fResourceCache, this->singleOwner());
83         fMappedBufferManager = skstd::make_unique<GrClientMappedBufferManager>(this->contextID());
84     }
85 
86     if (fResourceCache) {
87         fResourceCache->setProxyProvider(this->proxyProvider());
88     }
89 
90     fDidTestPMConversions = false;
91 
92     // DDL TODO: we need to think through how the task group & persistent cache
93     // get passed on to/shared between all the DDLRecorders created with this context.
94     if (this->options().fExecutor) {
95         fTaskGroup = skstd::make_unique<SkTaskGroup>(*this->options().fExecutor);
96     }
97 
98     fPersistentCache = this->options().fPersistentCache;
99     fShaderErrorHandler = this->options().fShaderErrorHandler;
100     if (!fShaderErrorHandler) {
101         fShaderErrorHandler = GrShaderUtils::DefaultShaderErrorHandler();
102     }
103 
104     return true;
105 }
106 
threadSafeProxy()107 sk_sp<GrContextThreadSafeProxy> GrContext::threadSafeProxy() {
108     return fThreadSafeProxy;
109 }
110 
111 //////////////////////////////////////////////////////////////////////////////
112 
abandonContext()113 void GrContext::abandonContext() {
114     if (this->abandoned()) {
115         return;
116     }
117 
118     INHERITED::abandonContext();
119 
120     fMappedBufferManager->abandon();
121 
122     fResourceProvider->abandon();
123 
124     // Need to cleanup the drawing manager first so all the render targets
125     // will be released/forgotten before they too are abandoned.
126     this->drawingManager()->cleanup();
127 
128     // abandon first to so destructors
129     // don't try to free the resources in the API.
130     fResourceCache->abandonAll();
131 
132     fGpu->disconnect(GrGpu::DisconnectType::kAbandon);
133 
134     fMappedBufferManager.reset();
135 }
136 
releaseResourcesAndAbandonContext()137 void GrContext::releaseResourcesAndAbandonContext() {
138     if (this->abandoned()) {
139         return;
140     }
141 
142     INHERITED::abandonContext();
143 
144     fMappedBufferManager.reset();
145 
146     fResourceProvider->abandon();
147 
148     // Need to cleanup the drawing manager first so all the render targets
149     // will be released/forgotten before they too are abandoned.
150     this->drawingManager()->cleanup();
151 
152     // Release all resources in the backend 3D API.
153     fResourceCache->releaseAll();
154 
155     fGpu->disconnect(GrGpu::DisconnectType::kCleanup);
156 }
157 
resetGLTextureBindings()158 void GrContext::resetGLTextureBindings() {
159     if (this->abandoned() || this->backend() != GrBackendApi::kOpenGL) {
160         return;
161     }
162     fGpu->resetTextureBindings();
163 }
164 
resetContext(uint32_t state)165 void GrContext::resetContext(uint32_t state) {
166     ASSERT_SINGLE_OWNER
167     fGpu->markContextDirty(state);
168 }
169 
freeGpuResources()170 void GrContext::freeGpuResources() {
171     ASSERT_SINGLE_OWNER
172 
173     // TODO: the glyph cache doesn't hold any GpuResources so this call should not be needed here.
174     // Some slack in the GrTextBlob's implementation requires it though. That could be fixed.
175     this->getGrStrikeCache()->freeAll();
176 
177     this->drawingManager()->freeGpuResources();
178 
179     fResourceCache->purgeAllUnlocked();
180 }
181 
purgeUnlockedResources(bool scratchResourcesOnly)182 void GrContext::purgeUnlockedResources(bool scratchResourcesOnly) {
183     ASSERT_SINGLE_OWNER
184 
185     if (this->abandoned()) {
186         return;
187     }
188 
189     fResourceCache->purgeUnlockedResources(scratchResourcesOnly);
190     fResourceCache->purgeAsNeeded();
191 
192     // The textBlob Cache doesn't actually hold any GPU resource but this is a convenient
193     // place to purge stale blobs
194     this->getTextBlobCache()->purgeStaleBlobs();
195 }
196 
performDeferredCleanup(std::chrono::milliseconds msNotUsed)197 void GrContext::performDeferredCleanup(std::chrono::milliseconds msNotUsed) {
198     TRACE_EVENT0("skia.gpu", TRACE_FUNC);
199 
200     ASSERT_SINGLE_OWNER
201 
202     if (this->abandoned()) {
203         return;
204     }
205 
206     fMappedBufferManager->process();
207     auto purgeTime = GrStdSteadyClock::now() - msNotUsed;
208 
209     fResourceCache->purgeAsNeeded();
210     fResourceCache->purgeResourcesNotUsedSince(purgeTime);
211 
212     if (auto ccpr = this->drawingManager()->getCoverageCountingPathRenderer()) {
213         ccpr->purgeCacheEntriesOlderThan(this->proxyProvider(), purgeTime);
214     }
215 
216     // The textBlob Cache doesn't actually hold any GPU resource but this is a convenient
217     // place to purge stale blobs
218     this->getTextBlobCache()->purgeStaleBlobs();
219 }
220 
purgeUnlockedResources(size_t bytesToPurge,bool preferScratchResources)221 void GrContext::purgeUnlockedResources(size_t bytesToPurge, bool preferScratchResources) {
222     ASSERT_SINGLE_OWNER
223 
224     if (this->abandoned()) {
225         return;
226     }
227 
228     fResourceCache->purgeUnlockedResources(bytesToPurge, preferScratchResources);
229 }
230 
getResourceCacheUsage(int * resourceCount,size_t * resourceBytes) const231 void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const {
232     ASSERT_SINGLE_OWNER
233 
234     if (resourceCount) {
235         *resourceCount = fResourceCache->getBudgetedResourceCount();
236     }
237     if (resourceBytes) {
238         *resourceBytes = fResourceCache->getBudgetedResourceBytes();
239     }
240 }
241 
getResourceCachePurgeableBytes() const242 size_t GrContext::getResourceCachePurgeableBytes() const {
243     ASSERT_SINGLE_OWNER
244     return fResourceCache->getPurgeableBytes();
245 }
246 
ComputeImageSize(sk_sp<SkImage> image,GrMipMapped mipMapped,bool useNextPow2)247 size_t GrContext::ComputeImageSize(sk_sp<SkImage> image, GrMipMapped mipMapped, bool useNextPow2) {
248     if (!image->isTextureBacked()) {
249         return 0;
250     }
251     SkImage_GpuBase* gpuImage = static_cast<SkImage_GpuBase*>(as_IB(image.get()));
252     GrTextureProxy* proxy = gpuImage->peekProxy();
253     if (!proxy) {
254         return 0;
255     }
256 
257     const GrCaps& caps = *gpuImage->context()->priv().caps();
258     int colorSamplesPerPixel = 1;
259     return GrSurface::ComputeSize(caps, proxy->backendFormat(), image->width(), image->height(),
260                                   colorSamplesPerPixel, mipMapped, useNextPow2);
261 }
262 
263 ////////////////////////////////////////////////////////////////////////////////
264 
maxTextureSize() const265 int GrContext::maxTextureSize() const { return this->caps()->maxTextureSize(); }
266 
maxRenderTargetSize() const267 int GrContext::maxRenderTargetSize() const { return this->caps()->maxRenderTargetSize(); }
268 
colorTypeSupportedAsImage(SkColorType colorType) const269 bool GrContext::colorTypeSupportedAsImage(SkColorType colorType) const {
270     GrBackendFormat format =
271             this->caps()->getDefaultBackendFormat(SkColorTypeToGrColorType(colorType),
272                                                   GrRenderable::kNo);
273     return format.isValid();
274 }
275 
maxSurfaceSampleCountForColorType(SkColorType colorType) const276 int GrContext::maxSurfaceSampleCountForColorType(SkColorType colorType) const {
277     GrBackendFormat format =
278             this->caps()->getDefaultBackendFormat(SkColorTypeToGrColorType(colorType),
279                                                   GrRenderable::kYes);
280     return this->caps()->maxRenderTargetSampleCount(format);
281 }
282 
283 ////////////////////////////////////////////////////////////////////////////////
284 
wait(int numSemaphores,const GrBackendSemaphore waitSemaphores[])285 bool GrContext::wait(int numSemaphores, const GrBackendSemaphore waitSemaphores[]) {
286     if (!fGpu || fGpu->caps()->semaphoreSupport()) {
287         return false;
288     }
289     for (int i = 0; i < numSemaphores; ++i) {
290         sk_sp<GrSemaphore> sema = fResourceProvider->wrapBackendSemaphore(
291                 waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait,
292                 kAdopt_GrWrapOwnership);
293         fGpu->waitSemaphore(std::move(sema));
294     }
295     return true;
296 }
297 
298 ////////////////////////////////////////////////////////////////////////////////
299 
flush(const GrFlushInfo & info,const GrPrepareForExternalIORequests & externalRequests)300 GrSemaphoresSubmitted GrContext::flush(const GrFlushInfo& info,
301                                        const GrPrepareForExternalIORequests& externalRequests) {
302     ASSERT_SINGLE_OWNER
303     if (this->abandoned()) {
304         return GrSemaphoresSubmitted::kNo;
305     }
306 
307     return this->drawingManager()->flush(nullptr, 0, SkSurface::BackendSurfaceAccess::kNoAccess,
308                                          info, externalRequests);
309 }
310 
311 ////////////////////////////////////////////////////////////////////////////////
312 
checkAsyncWorkCompletion()313 void GrContext::checkAsyncWorkCompletion() {
314     if (fGpu) {
315         fGpu->checkFinishProcs();
316     }
317 }
318 
319 ////////////////////////////////////////////////////////////////////////////////
320 
storeVkPipelineCacheData()321 void GrContext::storeVkPipelineCacheData() {
322     if (fGpu) {
323         fGpu->storeVkPipelineCacheData();
324     }
325 }
326 
327 ////////////////////////////////////////////////////////////////////////////////
328 
supportsDistanceFieldText() const329 bool GrContext::supportsDistanceFieldText() const {
330     return this->caps()->shaderCaps()->supportsDistanceFieldText();
331 }
332 
333 //////////////////////////////////////////////////////////////////////////////
334 
getResourceCacheLimits(int * maxResources,size_t * maxResourceBytes) const335 void GrContext::getResourceCacheLimits(int* maxResources, size_t* maxResourceBytes) const {
336     ASSERT_SINGLE_OWNER
337     if (maxResources) {
338         *maxResources = -1;
339     }
340     if (maxResourceBytes) {
341         *maxResourceBytes = this->getResourceCacheLimit();
342     }
343 }
344 
getResourceCacheLimit() const345 size_t GrContext::getResourceCacheLimit() const {
346     ASSERT_SINGLE_OWNER
347     return fResourceCache->getMaxResourceBytes();
348 }
349 
setResourceCacheLimits(int unused,size_t maxResourceBytes)350 void GrContext::setResourceCacheLimits(int unused, size_t maxResourceBytes) {
351     ASSERT_SINGLE_OWNER
352     this->setResourceCacheLimit(maxResourceBytes);
353 }
354 
setResourceCacheLimit(size_t maxResourceBytes)355 void GrContext::setResourceCacheLimit(size_t maxResourceBytes) {
356     ASSERT_SINGLE_OWNER
357     fResourceCache->setLimit(maxResourceBytes);
358 }
359 
360 //////////////////////////////////////////////////////////////////////////////
dumpMemoryStatistics(SkTraceMemoryDump * traceMemoryDump) const361 void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
362     ASSERT_SINGLE_OWNER
363     fResourceCache->dumpMemoryStatistics(traceMemoryDump);
364     traceMemoryDump->dumpNumericValue("skia/gr_text_blob_cache", "size", "bytes",
365                                       this->getTextBlobCache()->usedBytes());
366 }
367 
368 //////////////////////////////////////////////////////////////////////////////
createBackendTexture(int width,int height,const GrBackendFormat & backendFormat,GrMipMapped mipMapped,GrRenderable renderable,GrProtected isProtected)369 GrBackendTexture GrContext::createBackendTexture(int width, int height,
370                                                  const GrBackendFormat& backendFormat,
371                                                  GrMipMapped mipMapped,
372                                                  GrRenderable renderable,
373                                                  GrProtected isProtected) {
374     TRACE_EVENT0("skia.gpu", TRACE_FUNC);
375     if (!this->asDirectContext()) {
376         return GrBackendTexture();
377     }
378 
379     if (this->abandoned()) {
380         return GrBackendTexture();
381     }
382 
383     return fGpu->createBackendTexture(width, height, backendFormat,
384                                       mipMapped, renderable,
385                                       nullptr, 0, nullptr, isProtected);
386 }
387 
createBackendTexture(int width,int height,SkColorType skColorType,GrMipMapped mipMapped,GrRenderable renderable,GrProtected isProtected)388 GrBackendTexture GrContext::createBackendTexture(int width, int height,
389                                                  SkColorType skColorType,
390                                                  GrMipMapped mipMapped,
391                                                  GrRenderable renderable,
392                                                  GrProtected isProtected) {
393     if (!this->asDirectContext()) {
394         return GrBackendTexture();
395     }
396 
397     if (this->abandoned()) {
398         return GrBackendTexture();
399     }
400 
401     const GrBackendFormat format = this->defaultBackendFormat(skColorType, renderable);
402 
403     return this->createBackendTexture(width, height, format, mipMapped, renderable, isProtected);
404 }
405 
createBackendTexture(const SkSurfaceCharacterization & c)406 GrBackendTexture GrContext::createBackendTexture(const SkSurfaceCharacterization& c) {
407     if (!this->asDirectContext() || !c.isValid()) {
408         return GrBackendTexture();
409     }
410 
411     if (this->abandoned()) {
412         return GrBackendTexture();
413     }
414 
415     if (c.usesGLFBO0()) {
416         // If we are making the surface we will never use FBO0.
417         return GrBackendTexture();
418     }
419 
420     if (c.vulkanSecondaryCBCompatible()) {
421         return {};
422     }
423 
424     const GrBackendFormat format = this->defaultBackendFormat(c.colorType(), GrRenderable::kYes);
425     if (!format.isValid()) {
426         return GrBackendTexture();
427     }
428 
429     GrBackendTexture result = this->createBackendTexture(c.width(), c.height(), format,
430                                                          GrMipMapped(c.isMipMapped()),
431                                                          GrRenderable::kYes,
432                                                          c.isProtected());
433     SkASSERT(c.isCompatible(result));
434     return result;
435 }
436 
createBackendTexture(const SkSurfaceCharacterization & c,const SkColor4f & color)437 GrBackendTexture GrContext::createBackendTexture(const SkSurfaceCharacterization& c,
438                                                  const SkColor4f& color) {
439     if (!this->asDirectContext() || !c.isValid()) {
440         return GrBackendTexture();
441     }
442 
443     if (this->abandoned()) {
444         return GrBackendTexture();
445     }
446 
447     if (c.usesGLFBO0()) {
448         // If we are making the surface we will never use FBO0.
449         return GrBackendTexture();
450     }
451 
452     if (c.vulkanSecondaryCBCompatible()) {
453         return {};
454     }
455 
456     const GrBackendFormat format = this->defaultBackendFormat(c.colorType(), GrRenderable::kYes);
457     if (!format.isValid()) {
458         return GrBackendTexture();
459     }
460 
461     GrBackendTexture result = this->createBackendTexture(c.width(), c.height(), format, color,
462                                                          GrMipMapped(c.isMipMapped()),
463                                                          GrRenderable::kYes,
464                                                          c.isProtected());
465     SkASSERT(c.isCompatible(result));
466     return result;
467 }
468 
createBackendTexture(int width,int height,const GrBackendFormat & backendFormat,const SkColor4f & color,GrMipMapped mipMapped,GrRenderable renderable,GrProtected isProtected)469 GrBackendTexture GrContext::createBackendTexture(int width, int height,
470                                                  const GrBackendFormat& backendFormat,
471                                                  const SkColor4f& color,
472                                                  GrMipMapped mipMapped,
473                                                  GrRenderable renderable,
474                                                  GrProtected isProtected) {
475     TRACE_EVENT0("skia.gpu", TRACE_FUNC);
476     if (!this->asDirectContext()) {
477         return GrBackendTexture();
478     }
479 
480     if (this->abandoned()) {
481         return GrBackendTexture();
482     }
483 
484     return fGpu->createBackendTexture(width, height, backendFormat,
485                                       mipMapped, renderable,
486                                       nullptr, 0, &color, isProtected);
487 }
488 
createBackendTexture(int width,int height,SkColorType skColorType,const SkColor4f & color,GrMipMapped mipMapped,GrRenderable renderable,GrProtected isProtected)489 GrBackendTexture GrContext::createBackendTexture(int width, int height,
490                                                  SkColorType skColorType,
491                                                  const SkColor4f& color,
492                                                  GrMipMapped mipMapped,
493                                                  GrRenderable renderable,
494                                                  GrProtected isProtected) {
495     if (!this->asDirectContext()) {
496         return GrBackendTexture();
497     }
498 
499     if (this->abandoned()) {
500         return GrBackendTexture();
501     }
502 
503     GrBackendFormat format = this->defaultBackendFormat(skColorType, renderable);
504     if (!format.isValid()) {
505         return GrBackendTexture();
506     }
507 
508     GrColorType grColorType = SkColorTypeToGrColorType(skColorType);
509     SkColor4f swizzledColor = this->caps()->getOutputSwizzle(format, grColorType).applyTo(color);
510 
511     return this->createBackendTexture(width, height, format, swizzledColor, mipMapped, renderable,
512                                       isProtected);
513 }
514 
createBackendTexture(const SkPixmap srcData[],int numLevels,GrRenderable renderable,GrProtected isProtected)515 GrBackendTexture GrContext::createBackendTexture(const SkPixmap srcData[], int numLevels,
516                                                  GrRenderable renderable, GrProtected isProtected) {
517     TRACE_EVENT0("skia.gpu", TRACE_FUNC);
518 
519     if (!this->asDirectContext()) {
520         return {};
521     }
522 
523     if (this->abandoned()) {
524         return {};
525     }
526 
527     if (!srcData || !numLevels) {
528         return {};
529     }
530 
531     int baseWidth = srcData[0].width();
532     int baseHeight = srcData[0].height();
533     SkColorType colorType = srcData[0].colorType();
534 
535     GrBackendFormat backendFormat = this->defaultBackendFormat(colorType, renderable);
536 
537     return fGpu->createBackendTexture(baseWidth, baseHeight, backendFormat,
538                                       numLevels > 1 ? GrMipMapped::kYes : GrMipMapped::kNo,
539                                       renderable, srcData, numLevels, nullptr, isProtected);
540 }
541 
deleteBackendTexture(GrBackendTexture backendTex)542 void GrContext::deleteBackendTexture(GrBackendTexture backendTex) {
543     TRACE_EVENT0("skia.gpu", TRACE_FUNC);
544     if (this->abandoned() || !backendTex.isValid()) {
545         return;
546     }
547 
548     fGpu->deleteBackendTexture(backendTex);
549 }
550 
precompileShader(const SkData & key,const SkData & data)551 bool GrContext::precompileShader(const SkData& key, const SkData& data) {
552     return fGpu->precompileShader(key, data);
553 }
554 
555 #ifdef SK_ENABLE_DUMP_GPU
556 #include "src/utils/SkJSONWriter.h"
dump() const557 SkString GrContext::dump() const {
558     SkDynamicMemoryWStream stream;
559     SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty);
560     writer.beginObject();
561 
562     writer.appendString("backend", GrBackendApiToStr(this->backend()));
563 
564     writer.appendName("caps");
565     this->caps()->dumpJSON(&writer);
566 
567     writer.appendName("gpu");
568     this->fGpu->dumpJSON(&writer);
569 
570     // Flush JSON to the memory stream
571     writer.endObject();
572     writer.flush();
573 
574     // Null terminate the JSON data in the memory stream
575     stream.write8(0);
576 
577     // Allocate a string big enough to hold all the data, then copy out of the stream
578     SkString result(stream.bytesWritten());
579     stream.copyToAndReset(result.writable_str());
580     return result;
581 }
582 #endif
583