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 "GrContext.h"
9 #include "GrBackendSemaphore.h"
10 #include "GrClip.h"
11 #include "GrContextOptions.h"
12 #include "GrContextPriv.h"
13 #include "GrDrawingManager.h"
14 #include "GrGpu.h"
15 #include "GrMemoryPool.h"
16 #include "GrProxyProvider.h"
17 #include "GrRenderTargetContext.h"
18 #include "GrRenderTargetProxy.h"
19 #include "GrResourceCache.h"
20 #include "GrResourceProvider.h"
21 #include "GrSemaphore.h"
22 #include "GrSoftwarePathRenderer.h"
23 #include "GrSurfaceContext.h"
24 #include "GrSurfacePriv.h"
25 #include "GrSurfaceProxyPriv.h"
26 #include "GrTexture.h"
27 #include "GrTextureContext.h"
28 #include "GrTracing.h"
29 #include "SkAutoPixmapStorage.h"
30 #include "SkDeferredDisplayList.h"
31 #include "SkGr.h"
32 #include "SkImageInfoPriv.h"
33 #include "SkMakeUnique.h"
34 #include "SkSurface_Gpu.h"
35 #include "SkTaskGroup.h"
36 #include "SkTraceMemoryDump.h"
37 #include "effects/GrConfigConversionEffect.h"
38 #include "effects/GrSkSLFP.h"
39 #include "ccpr/GrCoverageCountingPathRenderer.h"
40 #include "text/GrTextBlobCache.h"
41 #include <atomic>
42 #include <unordered_map>
43 
44 #define ASSERT_OWNED_PROXY(P) \
45     SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == this)
46 #define ASSERT_OWNED_PROXY_PRIV(P) \
47     SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == fContext)
48 
49 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
50 #define ASSERT_SINGLE_OWNER \
51     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(&fSingleOwner);)
52 #define ASSERT_SINGLE_OWNER_PRIV \
53     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(&fContext->fSingleOwner);)
54 #define RETURN_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return; }
55 #define RETURN_IF_ABANDONED_PRIV if (fContext->fDrawingManager->wasAbandoned()) { return; }
56 #define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return false; }
57 #define RETURN_FALSE_IF_ABANDONED_PRIV if (fContext->fDrawingManager->wasAbandoned()) { return false; }
58 #define RETURN_NULL_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return nullptr; }
59 
60 ////////////////////////////////////////////////////////////////////////////////
61 
62 GrContext::GrContext(GrBackendApi backend, int32_t id)
63         : INHERITED(backend, id) {
64     fResourceCache = nullptr;
65     fResourceProvider = nullptr;
66     fProxyProvider = nullptr;
67     fGlyphCache = nullptr;
68 }
69 
70 bool GrContext::initCommon(const GrContextOptions& options) {
71     ASSERT_SINGLE_OWNER
72     SkASSERT(fCaps);  // needs to have been initialized by derived classes
73     SkASSERT(fThreadSafeProxy); // needs to have been initialized by derived classes
74 
75     if (fGpu) {
76         fCaps = fGpu->refCaps();
77         fResourceCache = new GrResourceCache(fCaps.get(), &fSingleOwner, this->contextID());
78         fResourceProvider = new GrResourceProvider(fGpu.get(), fResourceCache, &fSingleOwner,
79                                                    options.fExplicitlyAllocateGPUResources);
80         fProxyProvider =
81                 new GrProxyProvider(fResourceProvider, fResourceCache, fCaps, &fSingleOwner);
82     } else {
83         fProxyProvider = new GrProxyProvider(this->contextID(), fCaps, &fSingleOwner);
84     }
85 
86     if (fResourceCache) {
87         fResourceCache->setProxyProvider(fProxyProvider);
88     }
89 
90     fDisableGpuYUVConversion = options.fDisableGpuYUVConversion;
91     fSharpenMipmappedTextures = options.fSharpenMipmappedTextures;
92     fDidTestPMConversions = false;
93 
94     GrPathRendererChain::Options prcOptions;
95     prcOptions.fAllowPathMaskCaching = options.fAllowPathMaskCaching;
96 #if GR_TEST_UTILS
97     prcOptions.fGpuPathRenderers = options.fGpuPathRenderers;
98 #endif
99     if (options.fDisableCoverageCountingPaths) {
100         prcOptions.fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting;
101     }
102     if (options.fDisableDistanceFieldPaths) {
103         prcOptions.fGpuPathRenderers &= ~GpuPathRenderers::kSmall;
104     }
105 
106     if (!fResourceCache) {
107         // DDL TODO: remove this crippling of the path renderer chain
108         // Disable the small path renderer bc of the proxies in the atlas. They need to be
109         // unified when the opLists are added back to the destination drawing manager.
110         prcOptions.fGpuPathRenderers &= ~GpuPathRenderers::kSmall;
111         prcOptions.fGpuPathRenderers &= ~GpuPathRenderers::kStencilAndCover;
112     }
113 
114     GrTextContext::Options textContextOptions;
115     textContextOptions.fMaxDistanceFieldFontSize = options.fGlyphsAsPathsFontSize;
116     textContextOptions.fMinDistanceFieldFontSize = options.fMinDistanceFieldFontSize;
117     textContextOptions.fDistanceFieldVerticesAlwaysHaveW = false;
118 #if SK_SUPPORT_ATLAS_TEXT
119     if (GrContextOptions::Enable::kYes == options.fDistanceFieldGlyphVerticesAlwaysHaveW) {
120         textContextOptions.fDistanceFieldVerticesAlwaysHaveW = true;
121     }
122 #endif
123 
124     bool explicitlyAllocatingResources = fResourceProvider
125                                             ? fResourceProvider->explicitlyAllocateGPUResources()
126                                             : false;
127     fDrawingManager.reset(new GrDrawingManager(this, prcOptions, textContextOptions,
128                                                &fSingleOwner, explicitlyAllocatingResources,
129                                                options.fSortRenderTargets,
130                                                options.fReduceOpListSplitting));
131 
132     fGlyphCache = new GrStrikeCache(fCaps.get(), options.fGlyphCacheTextureMaximumBytes);
133 
134     fTextBlobCache.reset(new GrTextBlobCache(TextBlobCacheOverBudgetCB, this, this->contextID()));
135 
136     // DDL TODO: we need to think through how the task group & persistent cache
137     // get passed on to/shared between all the DDLRecorders created with this context.
138     if (options.fExecutor) {
139         fTaskGroup = skstd::make_unique<SkTaskGroup>(*options.fExecutor);
140     }
141 
142     fPersistentCache = options.fPersistentCache;
143 
144     return true;
145 }
146 
147 GrContext::~GrContext() {
148     ASSERT_SINGLE_OWNER
149 
150     if (fDrawingManager) {
151         fDrawingManager->cleanup();
152     }
153     delete fResourceProvider;
154     delete fResourceCache;
155     delete fProxyProvider;
156     delete fGlyphCache;
157 }
158 
159 sk_sp<GrContextThreadSafeProxy> GrContext::threadSafeProxy() {
160     return fThreadSafeProxy;
161 }
162 
163 //////////////////////////////////////////////////////////////////////////////
164 
165 void GrContext::abandonContext() {
166     ASSERT_SINGLE_OWNER
167 
168     fProxyProvider->abandon();
169     fResourceProvider->abandon();
170 
171     // Need to abandon the drawing manager first so all the render targets
172     // will be released/forgotten before they too are abandoned.
173     fDrawingManager->abandon();
174 
175     // abandon first to so destructors
176     // don't try to free the resources in the API.
177     fResourceCache->abandonAll();
178 
179     fGpu->disconnect(GrGpu::DisconnectType::kAbandon);
180 
181     fGlyphCache->freeAll();
182     fTextBlobCache->freeAll();
183 }
184 
185 bool GrContext::abandoned() const {
186     ASSERT_SINGLE_OWNER
187     // If called from ~GrContext(), the drawing manager may already be gone.
188     return !fDrawingManager || fDrawingManager->wasAbandoned();
189 }
190 
191 void GrContext::releaseResourcesAndAbandonContext() {
192     ASSERT_SINGLE_OWNER
193 
194     if (this->abandoned()) {
195         return;
196     }
197     fProxyProvider->abandon();
198     fResourceProvider->abandon();
199 
200     // Need to abandon the drawing manager first so all the render targets
201     // will be released/forgotten before they too are abandoned.
202     fDrawingManager->abandon();
203 
204     // Release all resources in the backend 3D API.
205     fResourceCache->releaseAll();
206 
207     fGpu->disconnect(GrGpu::DisconnectType::kCleanup);
208 
209     fGlyphCache->freeAll();
210     fTextBlobCache->freeAll();
211 }
212 
213 void GrContext::resetContext(uint32_t state) {
214     ASSERT_SINGLE_OWNER
215     fGpu->markContextDirty(state);
216 }
217 
218 void GrContext::freeGpuResources() {
219     ASSERT_SINGLE_OWNER
220 
221     fGlyphCache->freeAll();
222 
223     fDrawingManager->freeGpuResources();
224 
225     fResourceCache->purgeAllUnlocked();
226 }
227 
228 void GrContext::purgeUnlockedResources(bool scratchResourcesOnly) {
229     ASSERT_SINGLE_OWNER
230     fResourceCache->purgeUnlockedResources(scratchResourcesOnly);
231     fResourceCache->purgeAsNeeded();
232     fTextBlobCache->purgeStaleBlobs();
233 }
234 
235 void GrContext::performDeferredCleanup(std::chrono::milliseconds msNotUsed) {
236     ASSERT_SINGLE_OWNER
237 
238     auto purgeTime = GrStdSteadyClock::now() - msNotUsed;
239 
240     fResourceCache->purgeAsNeeded();
241     fResourceCache->purgeResourcesNotUsedSince(purgeTime);
242 
243     if (auto ccpr = fDrawingManager->getCoverageCountingPathRenderer()) {
244         ccpr->purgeCacheEntriesOlderThan(fProxyProvider, purgeTime);
245     }
246 
247     fTextBlobCache->purgeStaleBlobs();
248 }
249 
250 void GrContext::purgeUnlockedResources(size_t bytesToPurge, bool preferScratchResources) {
251     ASSERT_SINGLE_OWNER
252     fResourceCache->purgeUnlockedResources(bytesToPurge, preferScratchResources);
253 }
254 
255 void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const {
256     ASSERT_SINGLE_OWNER
257 
258     if (resourceCount) {
259         *resourceCount = fResourceCache->getBudgetedResourceCount();
260     }
261     if (resourceBytes) {
262         *resourceBytes = fResourceCache->getBudgetedResourceBytes();
263     }
264 }
265 
266 size_t GrContext::getResourceCachePurgeableBytes() const {
267     ASSERT_SINGLE_OWNER
268     return fResourceCache->getPurgeableBytes();
269 }
270 
271 ////////////////////////////////////////////////////////////////////////////////
272 
273 int GrContext::maxTextureSize() const { return fCaps->maxTextureSize(); }
274 
275 int GrContext::maxRenderTargetSize() const { return fCaps->maxRenderTargetSize(); }
276 
277 bool GrContext::colorTypeSupportedAsImage(SkColorType colorType) const {
278     GrPixelConfig config = SkColorType2GrPixelConfig(colorType);
279     return fCaps->isConfigTexturable(config);
280 }
281 
282 int GrContext::maxSurfaceSampleCountForColorType(SkColorType colorType) const {
283     GrPixelConfig config = SkColorType2GrPixelConfig(colorType);
284     return fCaps->maxRenderTargetSampleCount(config);
285 }
286 
287 ////////////////////////////////////////////////////////////////////////////////
288 
289 void GrContext::TextBlobCacheOverBudgetCB(void* data) {
290     SkASSERT(data);
291     // TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on
292     // GrRenderTargetContext to perform a necessary flush.  The solution is to move drawText calls
293     // to below the GrContext level, but this is not trivial because they call drawPath on
294     // SkGpuDevice.
295     GrContext* context = reinterpret_cast<GrContext*>(data);
296     context->flush();
297 }
298 
299 ////////////////////////////////////////////////////////////////////////////////
300 
301 void GrContext::flush() {
302     ASSERT_SINGLE_OWNER
303     RETURN_IF_ABANDONED
304 
305     fDrawingManager->flush(nullptr);
306 }
307 
308 GrSemaphoresSubmitted GrContext::flushAndSignalSemaphores(int numSemaphores,
309                                                           GrBackendSemaphore signalSemaphores[]) {
310     ASSERT_SINGLE_OWNER
311     if (fDrawingManager->wasAbandoned()) { return GrSemaphoresSubmitted::kNo; }
312 
313     return fDrawingManager->flush(nullptr, numSemaphores, signalSemaphores);
314 }
315 
316 void GrContextPriv::flush(GrSurfaceProxy* proxy) {
317     ASSERT_SINGLE_OWNER_PRIV
318     RETURN_IF_ABANDONED_PRIV
319     ASSERT_OWNED_PROXY_PRIV(proxy);
320 
321     fContext->fDrawingManager->flush(proxy);
322 }
323 
324 ////////////////////////////////////////////////////////////////////////////////
325 
326 void GrContext::storeVkPipelineCacheData() {
327     if (fGpu) {
328         fGpu->storeVkPipelineCacheData();
329     }
330 }
331 
332 ////////////////////////////////////////////////////////////////////////////////
333 
334 // TODO: This will be removed when GrSurfaceContexts are aware of their color types.
335 // (skbug.com/6718)
336 static bool valid_premul_config(GrPixelConfig config) {
337     switch (config) {
338         case kUnknown_GrPixelConfig:            return false;
339         case kAlpha_8_GrPixelConfig:            return false;
340         case kGray_8_GrPixelConfig:             return false;
341         case kRGB_565_GrPixelConfig:            return false;
342         case kRGBA_4444_GrPixelConfig:          return true;
343         case kRGBA_8888_GrPixelConfig:          return true;
344         case kRGB_888_GrPixelConfig:            return false;
345         case kRG_88_GrPixelConfig:              return false;
346         case kBGRA_8888_GrPixelConfig:          return true;
347         case kSRGBA_8888_GrPixelConfig:         return true;
348         case kSBGRA_8888_GrPixelConfig:         return true;
349         case kRGBA_1010102_GrPixelConfig:       return true;
350         case kRGBA_float_GrPixelConfig:         return true;
351         case kRG_float_GrPixelConfig:           return false;
352         case kAlpha_half_GrPixelConfig:         return false;
353         case kRGBA_half_GrPixelConfig:          return true;
354         case kRGB_ETC1_GrPixelConfig:           return false;
355         case kAlpha_8_as_Alpha_GrPixelConfig:   return false;
356         case kAlpha_8_as_Red_GrPixelConfig:     return false;
357         case kAlpha_half_as_Red_GrPixelConfig:  return false;
358         case kGray_8_as_Lum_GrPixelConfig:      return false;
359         case kGray_8_as_Red_GrPixelConfig:      return false;
360     }
361     SK_ABORT("Invalid GrPixelConfig");
362     return false;
363 }
364 
365 static bool valid_premul_color_type(GrColorType ct) {
366     switch (ct) {
367         case GrColorType::kUnknown:      return false;
368         case GrColorType::kAlpha_8:      return false;
369         case GrColorType::kRGB_565:      return false;
370         case GrColorType::kABGR_4444:    return true;
371         case GrColorType::kRGBA_8888:    return true;
372         case GrColorType::kRGB_888x:     return false;
373         case GrColorType::kRG_88:        return false;
374         case GrColorType::kBGRA_8888:    return true;
375         case GrColorType::kRGBA_1010102: return true;
376         case GrColorType::kGray_8:       return false;
377         case GrColorType::kAlpha_F16:    return false;
378         case GrColorType::kRGBA_F16:     return true;
379         case GrColorType::kRG_F32:       return false;
380         case GrColorType::kRGBA_F32:     return true;
381         case GrColorType::kRGB_ETC1:     return false;
382     }
383     SK_ABORT("Invalid GrColorType");
384     return false;
385 }
386 
387 static bool valid_pixel_conversion(GrColorType cpuColorType, GrPixelConfig gpuConfig,
388                                    bool premulConversion) {
389     // We only allow premul <-> unpremul conversions for some formats
390     if (premulConversion &&
391         (!valid_premul_color_type(cpuColorType) || !valid_premul_config(gpuConfig))) {
392         return false;
393     }
394     return true;
395 }
396 
397 bool GrContextPriv::writeSurfacePixels(GrSurfaceContext* dst, int left, int top, int width,
398                                        int height, GrColorType srcColorType,
399                                        SkColorSpace* srcColorSpace, const void* buffer,
400                                        size_t rowBytes, uint32_t pixelOpsFlags) {
401     ASSERT_SINGLE_OWNER_PRIV
402     RETURN_FALSE_IF_ABANDONED_PRIV
403     SkASSERT(dst);
404     SkASSERT(buffer);
405     ASSERT_OWNED_PROXY_PRIV(dst->asSurfaceProxy());
406     GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "writeSurfacePixels", fContext);
407 
408     if (GrColorType::kUnknown == srcColorType) {
409         return false;
410     }
411 
412     if (!dst->asSurfaceProxy()->instantiate(this->resourceProvider())) {
413         return false;
414     }
415 
416     GrSurfaceProxy* dstProxy = dst->asSurfaceProxy();
417     GrSurface* dstSurface = dstProxy->peekSurface();
418 
419     if (!GrSurfacePriv::AdjustWritePixelParams(dstSurface->width(), dstSurface->height(),
420                                                GrColorTypeBytesPerPixel(srcColorType), &left, &top,
421                                                &width, &height, &buffer, &rowBytes)) {
422         return false;
423     }
424 
425     // TODO: Make GrSurfaceContext know its alpha type and pass src buffer's alpha type.
426     bool premul = SkToBool(kUnpremul_PixelOpsFlag & pixelOpsFlags);
427 
428     // For canvas2D putImageData performance we have a special code path for unpremul RGBA_8888 srcs
429     // that are premultiplied on the GPU. This is kept as narrow as possible for now.
430     bool canvas2DFastPath =
431             !fContext->contextPriv().caps()->avoidWritePixelsFastPath() &&
432             premul &&
433             !dst->colorSpaceInfo().colorSpace() &&
434             (srcColorType == GrColorType::kRGBA_8888 || srcColorType == GrColorType::kBGRA_8888) &&
435             SkToBool(dst->asRenderTargetContext()) &&
436             (dstProxy->config() == kRGBA_8888_GrPixelConfig ||
437              dstProxy->config() == kBGRA_8888_GrPixelConfig) &&
438             !(pixelOpsFlags & kDontFlush_PixelOpsFlag) &&
439             fContext->contextPriv().caps()->isConfigTexturable(kRGBA_8888_GrPixelConfig) &&
440             fContext->validPMUPMConversionExists();
441 
442     const GrCaps* caps = this->caps();
443     if (!caps->surfaceSupportsWritePixels(dstSurface) ||
444         canvas2DFastPath) {
445         // We don't expect callers that are skipping flushes to require an intermediate draw.
446         SkASSERT(!(pixelOpsFlags & kDontFlush_PixelOpsFlag));
447         if (pixelOpsFlags & kDontFlush_PixelOpsFlag) {
448             return false;
449         }
450 
451         GrSurfaceDesc desc;
452         desc.fWidth = width;
453         desc.fHeight = height;
454         desc.fSampleCnt = 1;
455 
456         GrBackendFormat format;
457         if (canvas2DFastPath) {
458             desc.fConfig = kRGBA_8888_GrPixelConfig;
459             format =
460               fContext->contextPriv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
461         } else {
462             desc.fConfig =  dstProxy->config();
463             format = dstProxy->backendFormat().makeTexture2D();
464             if (!format.isValid()) {
465                 return false;
466             }
467         }
468 
469         auto tempProxy = this->proxyProvider()->createProxy(
470                 format, desc, kTopLeft_GrSurfaceOrigin, SkBackingFit::kApprox, SkBudgeted::kYes);
471         if (!tempProxy) {
472             return false;
473         }
474         auto tempCtx = this->drawingManager()->makeTextureContext(
475                 tempProxy, dst->colorSpaceInfo().refColorSpace());
476         if (!tempCtx) {
477             return false;
478         }
479         uint32_t flags = canvas2DFastPath ? 0 : pixelOpsFlags;
480         // In the fast path we always write the srcData to the temp context as though it were RGBA.
481         // When the data is really BGRA the write will cause the R and B channels to be swapped in
482         // the intermediate surface which gets corrected by a swizzle effect when drawing to the
483         // dst.
484         auto tmpColorType = canvas2DFastPath ? GrColorType::kRGBA_8888 : srcColorType;
485         if (!this->writeSurfacePixels(tempCtx.get(), 0, 0, width, height, tmpColorType,
486                                       srcColorSpace, buffer, rowBytes, flags)) {
487             return false;
488         }
489         if (canvas2DFastPath) {
490             GrPaint paint;
491             paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
492             auto fp = fContext->createUPMToPMEffect(
493                     GrSimpleTextureEffect::Make(std::move(tempProxy), SkMatrix::I()));
494             if (srcColorType == GrColorType::kBGRA_8888) {
495                 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA());
496             }
497             if (!fp) {
498                 return false;
499             }
500             paint.addColorFragmentProcessor(std::move(fp));
501             dst->asRenderTargetContext()->fillRectToRect(
502                     GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
503                     SkRect::MakeXYWH(left, top, width, height), SkRect::MakeWH(width, height));
504             return true;
505         } else {
506             return dst->copy(tempProxy.get(), SkIRect::MakeWH(width, height), {left, top});
507         }
508     }
509 
510     bool convert = premul;
511 
512     if (!valid_pixel_conversion(srcColorType, dstProxy->config(), premul)) {
513         return false;
514     }
515 
516     GrColorType allowedColorType = fContext->contextPriv().caps()->supportedWritePixelsColorType(
517             dstProxy->config(), srcColorType);
518     convert = convert || (srcColorType != allowedColorType);
519 
520     if (!dst->colorSpaceInfo().colorSpace()) {
521         // "Legacy" mode - no color space conversions.
522         srcColorSpace = nullptr;
523     }
524     convert = convert || !SkColorSpace::Equals(srcColorSpace, dst->colorSpaceInfo().colorSpace());
525 
526     std::unique_ptr<char[]> tempBuffer;
527     if (convert) {
528         auto srcSkColorType = GrColorTypeToSkColorType(srcColorType);
529         auto dstSkColorType = GrColorTypeToSkColorType(allowedColorType);
530         if (kUnknown_SkColorType == srcSkColorType || kUnknown_SkColorType == dstSkColorType) {
531             return false;
532         }
533         auto srcAlphaType = SkColorTypeIsAlwaysOpaque(srcSkColorType)
534                 ? kOpaque_SkAlphaType
535                 : (premul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType);
536         SkPixmap src(SkImageInfo::Make(width, height, srcSkColorType, srcAlphaType,
537                                        sk_ref_sp(srcColorSpace)),
538                      buffer, rowBytes);
539         auto tempSrcII = SkImageInfo::Make(width, height, dstSkColorType, kPremul_SkAlphaType,
540                                            dst->colorSpaceInfo().refColorSpace());
541         auto size = tempSrcII.computeMinByteSize();
542         if (!size) {
543             return false;
544         }
545         tempBuffer.reset(new char[size]);
546         SkPixmap tempSrc(tempSrcII, tempBuffer.get(), tempSrcII.minRowBytes());
547         if (!src.readPixels(tempSrc)) {
548             return false;
549         }
550         srcColorType = allowedColorType;
551         buffer = tempSrc.addr();
552         rowBytes = tempSrc.rowBytes();
553         if (dstProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
554             std::unique_ptr<char[]> row(new char[rowBytes]);
555             for (int y = 0; y < height / 2; ++y) {
556                 memcpy(row.get(), tempSrc.addr(0, y), rowBytes);
557                 memcpy(tempSrc.writable_addr(0, y), tempSrc.addr(0, height - 1 - y), rowBytes);
558                 memcpy(tempSrc.writable_addr(0, height - 1 - y), row.get(), rowBytes);
559             }
560             top = dstSurface->height() - top - height;
561         }
562     } else if (dstProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
563         size_t trimRowBytes = GrColorTypeBytesPerPixel(srcColorType) * width;
564         tempBuffer.reset(new char[trimRowBytes * height]);
565         char* dst = reinterpret_cast<char*>(tempBuffer.get()) + trimRowBytes * (height - 1);
566         const char* src = reinterpret_cast<const char*>(buffer);
567         for (int i = 0; i < height; ++i, src += rowBytes, dst -= trimRowBytes) {
568             memcpy(dst, src, trimRowBytes);
569         }
570         buffer = tempBuffer.get();
571         rowBytes = trimRowBytes;
572         top = dstSurface->height() - top - height;
573     }
574 
575     if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && dstSurface->surfacePriv().hasPendingIO()) {
576         this->flush(nullptr);  // MDB TODO: tighten this
577     }
578 
579     return this->getGpu()->writePixels(dstSurface, left, top, width, height, srcColorType, buffer,
580                                        rowBytes);
581 }
582 
583 bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src, int left, int top, int width,
584                                       int height, GrColorType dstColorType,
585                                       SkColorSpace* dstColorSpace, void* buffer, size_t rowBytes,
586                                       uint32_t pixelOpsFlags) {
587     ASSERT_SINGLE_OWNER_PRIV
588     RETURN_FALSE_IF_ABANDONED_PRIV
589     SkASSERT(src);
590     SkASSERT(buffer);
591     ASSERT_OWNED_PROXY_PRIV(src->asSurfaceProxy());
592     GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "readSurfacePixels", fContext);
593 
594     SkASSERT(!(pixelOpsFlags & kDontFlush_PixelOpsFlag));
595     if (pixelOpsFlags & kDontFlush_PixelOpsFlag) {
596         return false;
597     }
598 
599     // MDB TODO: delay this instantiation until later in the method
600     if (!src->asSurfaceProxy()->instantiate(this->resourceProvider())) {
601         return false;
602     }
603 
604     GrSurfaceProxy* srcProxy = src->asSurfaceProxy();
605     GrSurface* srcSurface = srcProxy->peekSurface();
606 
607     if (!GrSurfacePriv::AdjustReadPixelParams(srcSurface->width(), srcSurface->height(),
608                                               GrColorTypeBytesPerPixel(dstColorType), &left, &top,
609                                               &width, &height, &buffer, &rowBytes)) {
610         return false;
611     }
612 
613     // TODO: Make GrSurfaceContext know its alpha type and pass dst buffer's alpha type.
614     bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & pixelOpsFlags);
615 
616     if (!valid_pixel_conversion(dstColorType, srcProxy->config(), unpremul)) {
617         return false;
618     }
619 
620     // This is the getImageData equivalent to the canvas2D putImageData fast path. We probably don't
621     // care so much about getImageData performance. However, in order to ensure putImageData/
622     // getImageData in "legacy" mode are round-trippable we use the GPU to do the complementary
623     // unpremul step to writeSurfacePixels's premul step (which is determined empirically in
624     // fContext->vaildaPMUPMConversionExists()).
625     bool canvas2DFastPath =
626             unpremul &&
627             !src->colorSpaceInfo().colorSpace() &&
628             (GrColorType::kRGBA_8888 == dstColorType || GrColorType::kBGRA_8888 == dstColorType) &&
629             SkToBool(srcProxy->asTextureProxy()) &&
630             (srcProxy->config() == kRGBA_8888_GrPixelConfig ||
631              srcProxy->config() == kBGRA_8888_GrPixelConfig) &&
632             fContext->contextPriv().caps()->isConfigRenderable(kRGBA_8888_GrPixelConfig) &&
633             fContext->validPMUPMConversionExists();
634 
635     if (!fContext->contextPriv().caps()->surfaceSupportsReadPixels(srcSurface) ||
636         canvas2DFastPath) {
637         GrSurfaceDesc desc;
638         desc.fFlags = canvas2DFastPath ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
639         desc.fConfig = canvas2DFastPath ? kRGBA_8888_GrPixelConfig : srcProxy->config();
640         desc.fWidth = width;
641         desc.fHeight = height;
642         desc.fSampleCnt = 1;
643 
644         GrBackendFormat format;
645         if (canvas2DFastPath) {
646             desc.fFlags = kRenderTarget_GrSurfaceFlag;
647             desc.fConfig = kRGBA_8888_GrPixelConfig;
648             format = this->caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
649         } else {
650             desc.fFlags = kNone_GrSurfaceFlags;
651             desc.fConfig = srcProxy->config();
652             format = srcProxy->backendFormat().makeTexture2D();
653             if (!format.isValid()) {
654                 return false;
655             }
656         }
657 
658         auto tempProxy = this->proxyProvider()->createProxy(
659                 format, desc, kTopLeft_GrSurfaceOrigin, SkBackingFit::kApprox, SkBudgeted::kYes);
660         if (!tempProxy) {
661             return false;
662         }
663         sk_sp<GrSurfaceContext> tempCtx;
664         if (canvas2DFastPath) {
665             tempCtx = this->drawingManager()->makeRenderTargetContext(std::move(tempProxy), nullptr,
666                                                                       nullptr);
667             SkASSERT(tempCtx->asRenderTargetContext());
668             tempCtx->asRenderTargetContext()->discard();
669         } else {
670             tempCtx = this->drawingManager()->makeTextureContext(
671                     std::move(tempProxy), src->colorSpaceInfo().refColorSpace());
672         }
673         if (!tempCtx) {
674             return false;
675         }
676         if (canvas2DFastPath) {
677             GrPaint paint;
678             paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
679             auto fp = fContext->createPMToUPMEffect(
680                     GrSimpleTextureEffect::Make(sk_ref_sp(srcProxy->asTextureProxy()),
681                                                 SkMatrix::I()));
682             if (dstColorType == GrColorType::kBGRA_8888) {
683                 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA());
684                 dstColorType = GrColorType::kRGBA_8888;
685             }
686             if (!fp) {
687                 return false;
688             }
689             paint.addColorFragmentProcessor(std::move(fp));
690             tempCtx->asRenderTargetContext()->fillRectToRect(
691                     GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
692                     SkRect::MakeWH(width, height), SkRect::MakeXYWH(left, top, width, height));
693         } else if (!tempCtx->copy(srcProxy, SkIRect::MakeXYWH(left, top, width, height), {0, 0})) {
694             return false;
695         }
696         uint32_t flags = canvas2DFastPath ? 0 : pixelOpsFlags;
697         return this->readSurfacePixels(tempCtx.get(), 0, 0, width, height, dstColorType,
698                                        dstColorSpace, buffer, rowBytes, flags);
699     }
700 
701     bool convert = unpremul;
702 
703     bool flip = srcProxy->origin() == kBottomLeft_GrSurfaceOrigin;
704     if (flip) {
705         top = srcSurface->height() - top - height;
706     }
707 
708     GrColorType allowedColorType = fContext->contextPriv().caps()->supportedReadPixelsColorType(
709             srcProxy->config(), dstColorType);
710     convert = convert || (dstColorType != allowedColorType);
711 
712     if (!src->colorSpaceInfo().colorSpace()) {
713         // "Legacy" mode - no color space conversions.
714         dstColorSpace = nullptr;
715     }
716     convert = convert || !SkColorSpace::Equals(dstColorSpace, src->colorSpaceInfo().colorSpace());
717 
718     SkAutoPixmapStorage tempPixmap;
719     SkPixmap finalPixmap;
720     if (convert) {
721         SkColorType srcSkColorType = GrColorTypeToSkColorType(allowedColorType);
722         SkColorType dstSkColorType = GrColorTypeToSkColorType(dstColorType);
723         bool srcAlwaysOpaque = SkColorTypeIsAlwaysOpaque(srcSkColorType);
724         bool dstAlwaysOpaque = SkColorTypeIsAlwaysOpaque(dstSkColorType);
725         if (kUnknown_SkColorType == srcSkColorType || kUnknown_SkColorType == dstSkColorType) {
726             return false;
727         }
728         auto tempAT = srcAlwaysOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
729         auto tempII = SkImageInfo::Make(width, height, srcSkColorType, tempAT,
730                                         src->colorSpaceInfo().refColorSpace());
731         SkASSERT(!unpremul || !dstAlwaysOpaque);
732         auto finalAT = (srcAlwaysOpaque || dstAlwaysOpaque)
733                                ? kOpaque_SkAlphaType
734                                : unpremul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType;
735         auto finalII =
736                 SkImageInfo::Make(width, height, dstSkColorType, finalAT, sk_ref_sp(dstColorSpace));
737         if (!SkImageInfoValidConversion(finalII, tempII)) {
738             return false;
739         }
740         if (!tempPixmap.tryAlloc(tempII)) {
741             return false;
742         }
743         finalPixmap.reset(finalII, buffer, rowBytes);
744         buffer = tempPixmap.writable_addr();
745         rowBytes = tempPixmap.rowBytes();
746         // Chrome msan bots require this.
747         sk_bzero(buffer, tempPixmap.computeByteSize());
748     }
749 
750     if (srcSurface->surfacePriv().hasPendingWrite()) {
751         this->flush(nullptr);  // MDB TODO: tighten this
752     }
753 
754     if (!fContext->fGpu->readPixels(srcSurface, left, top, width, height, allowedColorType, buffer,
755                                     rowBytes)) {
756         return false;
757     }
758 
759     if (flip) {
760         size_t trimRowBytes = GrColorTypeBytesPerPixel(allowedColorType) * width;
761         std::unique_ptr<char[]> row(new char[trimRowBytes]);
762         char* upper = reinterpret_cast<char*>(buffer);
763         char* lower = reinterpret_cast<char*>(buffer) + (height - 1) * rowBytes;
764         for (int y = 0; y < height / 2; ++y, upper += rowBytes, lower -= rowBytes) {
765             memcpy(row.get(), upper, trimRowBytes);
766             memcpy(upper, lower, trimRowBytes);
767             memcpy(lower, row.get(), trimRowBytes);
768         }
769     }
770     if (convert) {
771         if (!tempPixmap.readPixels(finalPixmap)) {
772             return false;
773         }
774     }
775     return true;
776 }
777 
778 void GrContextPriv::prepareSurfaceForExternalIO(GrSurfaceProxy* proxy) {
779     ASSERT_SINGLE_OWNER_PRIV
780     RETURN_IF_ABANDONED_PRIV
781     SkASSERT(proxy);
782     ASSERT_OWNED_PROXY_PRIV(proxy);
783     fContext->fDrawingManager->prepareSurfaceForExternalIO(proxy, 0, nullptr);
784 }
785 
786 void GrContextPriv::flushSurfaceWrites(GrSurfaceProxy* proxy) {
787     ASSERT_SINGLE_OWNER_PRIV
788     RETURN_IF_ABANDONED_PRIV
789     SkASSERT(proxy);
790     ASSERT_OWNED_PROXY_PRIV(proxy);
791     if (proxy->priv().hasPendingWrite()) {
792         this->flush(proxy);
793     }
794 }
795 
796 void GrContextPriv::flushSurfaceIO(GrSurfaceProxy* proxy) {
797     ASSERT_SINGLE_OWNER_PRIV
798     RETURN_IF_ABANDONED_PRIV
799     SkASSERT(proxy);
800     ASSERT_OWNED_PROXY_PRIV(proxy);
801     if (proxy->priv().hasPendingIO()) {
802         this->flush(proxy);
803     }
804 }
805 
806 ////////////////////////////////////////////////////////////////////////////////
807 
808 sk_sp<GrOpMemoryPool> GrContextPriv::refOpMemoryPool() {
809     if (!fContext->fOpMemoryPool) {
810         // DDL TODO: should the size of the memory pool be decreased in DDL mode? CPU-side memory
811         // consumed in DDL mode vs. normal mode for a single skp might be a good metric of wasted
812         // memory.
813         fContext->fOpMemoryPool = sk_sp<GrOpMemoryPool>(new GrOpMemoryPool(16384, 16384));
814     }
815 
816     SkASSERT(fContext->fOpMemoryPool);
817     return fContext->fOpMemoryPool;
818 }
819 
820 GrOpMemoryPool* GrContextPriv::opMemoryPool() {
821     return this->refOpMemoryPool().get();
822 }
823 
824 sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy,
825                                                                  sk_sp<SkColorSpace> colorSpace,
826                                                                  const SkSurfaceProps* props) {
827     ASSERT_SINGLE_OWNER_PRIV
828 
829     if (proxy->asRenderTargetProxy()) {
830         return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
831                                                                std::move(colorSpace), props);
832     } else {
833         SkASSERT(proxy->asTextureProxy());
834         SkASSERT(!props);
835         return this->drawingManager()->makeTextureContext(std::move(proxy), std::move(colorSpace));
836     }
837 }
838 
839 sk_sp<GrSurfaceContext> GrContextPriv::makeDeferredSurfaceContext(const GrBackendFormat& format,
840                                                                   const GrSurfaceDesc& dstDesc,
841                                                                   GrSurfaceOrigin origin,
842                                                                   GrMipMapped mipMapped,
843                                                                   SkBackingFit fit,
844                                                                   SkBudgeted isDstBudgeted,
845                                                                   sk_sp<SkColorSpace> colorSpace,
846                                                                   const SkSurfaceProps* props) {
847     sk_sp<GrTextureProxy> proxy;
848     if (GrMipMapped::kNo == mipMapped) {
849         proxy = this->proxyProvider()->createProxy(format, dstDesc, origin, fit, isDstBudgeted);
850     } else {
851         SkASSERT(SkBackingFit::kExact == fit);
852         proxy = this->proxyProvider()->createMipMapProxy(format, dstDesc, origin, isDstBudgeted);
853     }
854     if (!proxy) {
855         return nullptr;
856     }
857 
858     sk_sp<GrSurfaceContext> sContext = this->makeWrappedSurfaceContext(std::move(proxy),
859                                                                        std::move(colorSpace),
860                                                                        props);
861     if (sContext && sContext->asRenderTargetContext()) {
862         sContext->asRenderTargetContext()->discard();
863     }
864 
865     return sContext;
866 }
867 
868 sk_sp<GrTextureContext> GrContextPriv::makeBackendTextureContext(const GrBackendTexture& tex,
869                                                                  GrSurfaceOrigin origin,
870                                                                  sk_sp<SkColorSpace> colorSpace) {
871     ASSERT_SINGLE_OWNER_PRIV
872 
873     sk_sp<GrSurfaceProxy> proxy = this->proxyProvider()->wrapBackendTexture(
874             tex, origin, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType);
875     if (!proxy) {
876         return nullptr;
877     }
878 
879     return this->drawingManager()->makeTextureContext(std::move(proxy), std::move(colorSpace));
880 }
881 
882 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContext(
883                                                                    const GrBackendTexture& tex,
884                                                                    GrSurfaceOrigin origin,
885                                                                    int sampleCnt,
886                                                                    sk_sp<SkColorSpace> colorSpace,
887                                                                    const SkSurfaceProps* props) {
888     ASSERT_SINGLE_OWNER_PRIV
889     SkASSERT(sampleCnt > 0);
890 
891     sk_sp<GrTextureProxy> proxy(this->proxyProvider()->wrapRenderableBackendTexture(
892             tex, origin, sampleCnt, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo));
893     if (!proxy) {
894         return nullptr;
895     }
896 
897     return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
898                                                            std::move(colorSpace), props);
899 }
900 
901 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendRenderTargetRenderTargetContext(
902                                                 const GrBackendRenderTarget& backendRT,
903                                                 GrSurfaceOrigin origin,
904                                                 sk_sp<SkColorSpace> colorSpace,
905                                                 const SkSurfaceProps* surfaceProps) {
906     ASSERT_SINGLE_OWNER_PRIV
907 
908     sk_sp<GrSurfaceProxy> proxy = this->proxyProvider()->wrapBackendRenderTarget(backendRT, origin);
909     if (!proxy) {
910         return nullptr;
911     }
912 
913     return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
914                                                            std::move(colorSpace),
915                                                            surfaceProps);
916 }
917 
918 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureAsRenderTargetRenderTargetContext(
919                                                      const GrBackendTexture& tex,
920                                                      GrSurfaceOrigin origin,
921                                                      int sampleCnt,
922                                                      sk_sp<SkColorSpace> colorSpace,
923                                                      const SkSurfaceProps* props) {
924     ASSERT_SINGLE_OWNER_PRIV
925     SkASSERT(sampleCnt > 0);
926     sk_sp<GrSurfaceProxy> proxy(
927             this->proxyProvider()->wrapBackendTextureAsRenderTarget(tex, origin, sampleCnt));
928     if (!proxy) {
929         return nullptr;
930     }
931 
932     return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
933                                                            std::move(colorSpace),
934                                                            props);
935 }
936 
937 sk_sp<GrRenderTargetContext> GrContextPriv::makeVulkanSecondaryCBRenderTargetContext(
938         const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo, const SkSurfaceProps* props) {
939     ASSERT_SINGLE_OWNER_PRIV
940     sk_sp<GrSurfaceProxy> proxy(
941             this->proxyProvider()->wrapVulkanSecondaryCBAsRenderTarget(imageInfo, vkInfo));
942     if (!proxy) {
943         return nullptr;
944     }
945 
946     return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
947                                                            imageInfo.refColorSpace(),
948                                                            props);
949 }
950 
951 void GrContextPriv::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
952     fContext->fDrawingManager->addOnFlushCallbackObject(onFlushCBObject);
953 }
954 
955 void GrContextPriv::moveOpListsToDDL(SkDeferredDisplayList* ddl) {
956     fContext->fDrawingManager->moveOpListsToDDL(ddl);
957 }
958 
959 void GrContextPriv::copyOpListsFromDDL(const SkDeferredDisplayList* ddl,
960                                        GrRenderTargetProxy* newDest) {
961     fContext->fDrawingManager->copyOpListsFromDDL(ddl, newDest);
962 }
963 
964 static inline GrPixelConfig GrPixelConfigFallback(GrPixelConfig config) {
965     switch (config) {
966         case kAlpha_8_GrPixelConfig:
967         case kAlpha_8_as_Alpha_GrPixelConfig:
968         case kAlpha_8_as_Red_GrPixelConfig:
969         case kRGB_565_GrPixelConfig:
970         case kRGBA_4444_GrPixelConfig:
971         case kBGRA_8888_GrPixelConfig:
972         case kRGBA_1010102_GrPixelConfig:
973         case kRGBA_half_GrPixelConfig:
974             return kRGBA_8888_GrPixelConfig;
975         case kSBGRA_8888_GrPixelConfig:
976             return kSRGBA_8888_GrPixelConfig;
977         case kAlpha_half_GrPixelConfig:
978         case kAlpha_half_as_Red_GrPixelConfig:
979             return kRGBA_half_GrPixelConfig;
980         case kGray_8_GrPixelConfig:
981         case kGray_8_as_Lum_GrPixelConfig:
982         case kGray_8_as_Red_GrPixelConfig:
983             return kRGB_888_GrPixelConfig;
984         default:
985             return kUnknown_GrPixelConfig;
986     }
987 }
988 
989 sk_sp<GrRenderTargetContext> GrContextPriv::makeDeferredRenderTargetContextWithFallback(
990                                                                  const GrBackendFormat& format,
991                                                                  SkBackingFit fit,
992                                                                  int width, int height,
993                                                                  GrPixelConfig config,
994                                                                  sk_sp<SkColorSpace> colorSpace,
995                                                                  int sampleCnt,
996                                                                  GrMipMapped mipMapped,
997                                                                  GrSurfaceOrigin origin,
998                                                                  const SkSurfaceProps* surfaceProps,
999                                                                  SkBudgeted budgeted) {
1000     GrBackendFormat localFormat = format;
1001     SkASSERT(sampleCnt > 0);
1002     if (0 == fContext->contextPriv().caps()->getRenderTargetSampleCount(sampleCnt, config)) {
1003         config = GrPixelConfigFallback(config);
1004         // TODO: First we should be checking the getRenderTargetSampleCount from the GrBackendFormat
1005         // and not GrPixelConfig. Besides that, we should implement the fallback in the caps, but
1006         // for now we just convert the fallback pixel config to an SkColorType and then get the
1007         // GrBackendFormat from that.
1008         SkColorType colorType;
1009         if (!GrPixelConfigToColorType(config, &colorType)) {
1010             return nullptr;
1011         }
1012         localFormat = fContext->fCaps->getBackendFormatFromColorType(colorType);
1013     }
1014 
1015     return this->makeDeferredRenderTargetContext(localFormat, fit, width, height, config,
1016                                                  std::move(colorSpace), sampleCnt, mipMapped,
1017                                                  origin, surfaceProps, budgeted);
1018 }
1019 
1020 sk_sp<GrRenderTargetContext> GrContextPriv::makeDeferredRenderTargetContext(
1021                                                         const GrBackendFormat& format,
1022                                                         SkBackingFit fit,
1023                                                         int width, int height,
1024                                                         GrPixelConfig config,
1025                                                         sk_sp<SkColorSpace> colorSpace,
1026                                                         int sampleCnt,
1027                                                         GrMipMapped mipMapped,
1028                                                         GrSurfaceOrigin origin,
1029                                                         const SkSurfaceProps* surfaceProps,
1030                                                         SkBudgeted budgeted) {
1031     SkASSERT(sampleCnt > 0);
1032     if (fContext->abandoned()) {
1033         return nullptr;
1034     }
1035 
1036     GrSurfaceDesc desc;
1037     desc.fFlags = kRenderTarget_GrSurfaceFlag;
1038     desc.fWidth = width;
1039     desc.fHeight = height;
1040     desc.fConfig = config;
1041     desc.fSampleCnt = sampleCnt;
1042 
1043     sk_sp<GrTextureProxy> rtp;
1044     if (GrMipMapped::kNo == mipMapped) {
1045         rtp = fContext->fProxyProvider->createProxy(format, desc, origin, fit, budgeted);
1046     } else {
1047         rtp = fContext->fProxyProvider->createMipMapProxy(format, desc, origin, budgeted);
1048     }
1049     if (!rtp) {
1050         return nullptr;
1051     }
1052 
1053     sk_sp<GrRenderTargetContext> renderTargetContext(
1054         fContext->fDrawingManager->makeRenderTargetContext(std::move(rtp),
1055                                                            std::move(colorSpace),
1056                                                            surfaceProps));
1057     if (!renderTargetContext) {
1058         return nullptr;
1059     }
1060 
1061     renderTargetContext->discard();
1062 
1063     return renderTargetContext;
1064 }
1065 
1066 sk_sp<GrSkSLFPFactoryCache> GrContextPriv::getFPFactoryCache() { return fContext->fFPFactoryCache; }
1067 
1068 std::unique_ptr<GrFragmentProcessor> GrContext::createPMToUPMEffect(
1069         std::unique_ptr<GrFragmentProcessor> fp) {
1070     ASSERT_SINGLE_OWNER
1071     // We should have already called this->validPMUPMConversionExists() in this case
1072     SkASSERT(fDidTestPMConversions);
1073     // ...and it should have succeeded
1074     SkASSERT(this->validPMUPMConversionExists());
1075 
1076     return GrConfigConversionEffect::Make(std::move(fp), PMConversion::kToUnpremul);
1077 }
1078 
1079 std::unique_ptr<GrFragmentProcessor> GrContext::createUPMToPMEffect(
1080         std::unique_ptr<GrFragmentProcessor> fp) {
1081     ASSERT_SINGLE_OWNER
1082     // We should have already called this->validPMUPMConversionExists() in this case
1083     SkASSERT(fDidTestPMConversions);
1084     // ...and it should have succeeded
1085     SkASSERT(this->validPMUPMConversionExists());
1086 
1087     return GrConfigConversionEffect::Make(std::move(fp), PMConversion::kToPremul);
1088 }
1089 
1090 bool GrContext::validPMUPMConversionExists() {
1091     ASSERT_SINGLE_OWNER
1092     if (!fDidTestPMConversions) {
1093         fPMUPMConversionsRoundTrip = GrConfigConversionEffect::TestForPreservingPMConversions(this);
1094         fDidTestPMConversions = true;
1095     }
1096 
1097     // The PM<->UPM tests fail or succeed together so we only need to check one.
1098     return fPMUPMConversionsRoundTrip;
1099 }
1100 
1101 bool GrContext::supportsDistanceFieldText() const {
1102     return fCaps->shaderCaps()->supportsDistanceFieldText();
1103 }
1104 
1105 //////////////////////////////////////////////////////////////////////////////
1106 
1107 // DDL TODO: remove 'maxResources'
1108 void GrContext::getResourceCacheLimits(int* maxResources, size_t* maxResourceBytes) const {
1109     ASSERT_SINGLE_OWNER
1110     if (maxResources) {
1111         *maxResources = fResourceCache->getMaxResourceCount();
1112     }
1113     if (maxResourceBytes) {
1114         *maxResourceBytes = fResourceCache->getMaxResourceBytes();
1115     }
1116 }
1117 
1118 void GrContext::setResourceCacheLimits(int maxResources, size_t maxResourceBytes) {
1119     ASSERT_SINGLE_OWNER
1120     fResourceCache->setLimits(maxResources, maxResourceBytes);
1121 }
1122 
1123 //////////////////////////////////////////////////////////////////////////////
1124 void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
1125     ASSERT_SINGLE_OWNER
1126     fResourceCache->dumpMemoryStatistics(traceMemoryDump);
1127     traceMemoryDump->dumpNumericValue("skia/gr_text_blob_cache", "size", "bytes",
1128                                       fTextBlobCache->usedBytes());
1129 }
1130 
1131 //////////////////////////////////////////////////////////////////////////////
1132 #ifdef SK_ENABLE_DUMP_GPU
1133 #include "SkJSONWriter.h"
1134 SkString GrContextPriv::dump() const {
1135     SkDynamicMemoryWStream stream;
1136     SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty);
1137     writer.beginObject();
1138 
1139     static const char* kBackendStr[] = {
1140         "Metal",
1141         "OpenGL",
1142         "Vulkan",
1143         "Mock",
1144     };
1145     GR_STATIC_ASSERT(0 == (unsigned)GrBackendApi::kMetal);
1146     GR_STATIC_ASSERT(1 == (unsigned)GrBackendApi::kOpenGL);
1147     GR_STATIC_ASSERT(2 == (unsigned)GrBackendApi::kVulkan);
1148     GR_STATIC_ASSERT(3 == (unsigned)GrBackendApi::kMock);
1149     writer.appendString("backend", kBackendStr[(unsigned)fContext->backend()]);
1150 
1151     writer.appendName("caps");
1152     fContext->fCaps->dumpJSON(&writer);
1153 
1154     writer.appendName("gpu");
1155     fContext->fGpu->dumpJSON(&writer);
1156 
1157     // Flush JSON to the memory stream
1158     writer.endObject();
1159     writer.flush();
1160 
1161     // Null terminate the JSON data in the memory stream
1162     stream.write8(0);
1163 
1164     // Allocate a string big enough to hold all the data, then copy out of the stream
1165     SkString result(stream.bytesWritten());
1166     stream.copyToAndReset(result.writable_str());
1167     return result;
1168 }
1169 #endif
1170