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
GrContext(GrBackendApi backend,int32_t id)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
initCommon(const GrContextOptions & options)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
~GrContext()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
threadSafeProxy()159 sk_sp<GrContextThreadSafeProxy> GrContext::threadSafeProxy() {
160 return fThreadSafeProxy;
161 }
162
163 //////////////////////////////////////////////////////////////////////////////
164
abandonContext()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
abandoned() const185 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
releaseResourcesAndAbandonContext()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
resetContext(uint32_t state)213 void GrContext::resetContext(uint32_t state) {
214 ASSERT_SINGLE_OWNER
215 fGpu->markContextDirty(state);
216 }
217
freeGpuResources()218 void GrContext::freeGpuResources() {
219 ASSERT_SINGLE_OWNER
220
221 fGlyphCache->freeAll();
222
223 fDrawingManager->freeGpuResources();
224
225 fResourceCache->purgeAllUnlocked();
226 }
227
purgeUnlockedResources(bool scratchResourcesOnly)228 void GrContext::purgeUnlockedResources(bool scratchResourcesOnly) {
229 ASSERT_SINGLE_OWNER
230 fResourceCache->purgeUnlockedResources(scratchResourcesOnly);
231 fResourceCache->purgeAsNeeded();
232 fTextBlobCache->purgeStaleBlobs();
233 }
234
performDeferredCleanup(std::chrono::milliseconds msNotUsed)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
purgeUnlockedResources(size_t bytesToPurge,bool preferScratchResources)250 void GrContext::purgeUnlockedResources(size_t bytesToPurge, bool preferScratchResources) {
251 ASSERT_SINGLE_OWNER
252 fResourceCache->purgeUnlockedResources(bytesToPurge, preferScratchResources);
253 }
254
getResourceCacheUsage(int * resourceCount,size_t * resourceBytes) const255 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
getResourceCachePurgeableBytes() const266 size_t GrContext::getResourceCachePurgeableBytes() const {
267 ASSERT_SINGLE_OWNER
268 return fResourceCache->getPurgeableBytes();
269 }
270
271 ////////////////////////////////////////////////////////////////////////////////
272
maxTextureSize() const273 int GrContext::maxTextureSize() const { return fCaps->maxTextureSize(); }
274
maxRenderTargetSize() const275 int GrContext::maxRenderTargetSize() const { return fCaps->maxRenderTargetSize(); }
276
colorTypeSupportedAsImage(SkColorType colorType) const277 bool GrContext::colorTypeSupportedAsImage(SkColorType colorType) const {
278 GrPixelConfig config = SkColorType2GrPixelConfig(colorType);
279 return fCaps->isConfigTexturable(config);
280 }
281
maxSurfaceSampleCountForColorType(SkColorType colorType) const282 int GrContext::maxSurfaceSampleCountForColorType(SkColorType colorType) const {
283 GrPixelConfig config = SkColorType2GrPixelConfig(colorType);
284 return fCaps->maxRenderTargetSampleCount(config);
285 }
286
287 ////////////////////////////////////////////////////////////////////////////////
288
TextBlobCacheOverBudgetCB(void * data)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
flush()301 void GrContext::flush() {
302 ASSERT_SINGLE_OWNER
303 RETURN_IF_ABANDONED
304
305 fDrawingManager->flush(nullptr);
306 }
307
flushAndSignalSemaphores(int numSemaphores,GrBackendSemaphore signalSemaphores[])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
flush(GrSurfaceProxy * proxy)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
storeVkPipelineCacheData()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)
valid_premul_config(GrPixelConfig config)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
valid_premul_color_type(GrColorType ct)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
valid_pixel_conversion(GrColorType cpuColorType,GrPixelConfig gpuConfig,bool premulConversion)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
writeSurfacePixels(GrSurfaceContext * dst,int left,int top,int width,int height,GrColorType srcColorType,SkColorSpace * srcColorSpace,const void * buffer,size_t rowBytes,uint32_t pixelOpsFlags)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
readSurfacePixels(GrSurfaceContext * src,int left,int top,int width,int height,GrColorType dstColorType,SkColorSpace * dstColorSpace,void * buffer,size_t rowBytes,uint32_t pixelOpsFlags)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
prepareSurfaceForExternalIO(GrSurfaceProxy * proxy)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
flushSurfaceWrites(GrSurfaceProxy * proxy)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
flushSurfaceIO(GrSurfaceProxy * proxy)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
refOpMemoryPool()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
opMemoryPool()820 GrOpMemoryPool* GrContextPriv::opMemoryPool() {
821 return this->refOpMemoryPool().get();
822 }
823
makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * props)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
makeDeferredSurfaceContext(const GrBackendFormat & format,const GrSurfaceDesc & dstDesc,GrSurfaceOrigin origin,GrMipMapped mipMapped,SkBackingFit fit,SkBudgeted isDstBudgeted,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * props)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
makeBackendTextureContext(const GrBackendTexture & tex,GrSurfaceOrigin origin,sk_sp<SkColorSpace> colorSpace)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
makeBackendTextureRenderTargetContext(const GrBackendTexture & tex,GrSurfaceOrigin origin,int sampleCnt,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * props)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
makeBackendRenderTargetRenderTargetContext(const GrBackendRenderTarget & backendRT,GrSurfaceOrigin origin,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * surfaceProps)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
makeBackendTextureAsRenderTargetRenderTargetContext(const GrBackendTexture & tex,GrSurfaceOrigin origin,int sampleCnt,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * props)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
makeVulkanSecondaryCBRenderTargetContext(const SkImageInfo & imageInfo,const GrVkDrawableInfo & vkInfo,const SkSurfaceProps * props)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
addOnFlushCallbackObject(GrOnFlushCallbackObject * onFlushCBObject)951 void GrContextPriv::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
952 fContext->fDrawingManager->addOnFlushCallbackObject(onFlushCBObject);
953 }
954
moveOpListsToDDL(SkDeferredDisplayList * ddl)955 void GrContextPriv::moveOpListsToDDL(SkDeferredDisplayList* ddl) {
956 fContext->fDrawingManager->moveOpListsToDDL(ddl);
957 }
958
copyOpListsFromDDL(const SkDeferredDisplayList * ddl,GrRenderTargetProxy * newDest)959 void GrContextPriv::copyOpListsFromDDL(const SkDeferredDisplayList* ddl,
960 GrRenderTargetProxy* newDest) {
961 fContext->fDrawingManager->copyOpListsFromDDL(ddl, newDest);
962 }
963
GrPixelConfigFallback(GrPixelConfig config)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
makeDeferredRenderTargetContextWithFallback(const GrBackendFormat & format,SkBackingFit fit,int width,int height,GrPixelConfig config,sk_sp<SkColorSpace> colorSpace,int sampleCnt,GrMipMapped mipMapped,GrSurfaceOrigin origin,const SkSurfaceProps * surfaceProps,SkBudgeted budgeted)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
makeDeferredRenderTargetContext(const GrBackendFormat & format,SkBackingFit fit,int width,int height,GrPixelConfig config,sk_sp<SkColorSpace> colorSpace,int sampleCnt,GrMipMapped mipMapped,GrSurfaceOrigin origin,const SkSurfaceProps * surfaceProps,SkBudgeted budgeted)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
getFPFactoryCache()1066 sk_sp<GrSkSLFPFactoryCache> GrContextPriv::getFPFactoryCache() { return fContext->fFPFactoryCache; }
1067
createPMToUPMEffect(std::unique_ptr<GrFragmentProcessor> fp)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
createUPMToPMEffect(std::unique_ptr<GrFragmentProcessor> fp)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
validPMUPMConversionExists()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
supportsDistanceFieldText() const1101 bool GrContext::supportsDistanceFieldText() const {
1102 return fCaps->shaderCaps()->supportsDistanceFieldText();
1103 }
1104
1105 //////////////////////////////////////////////////////////////////////////////
1106
1107 // DDL TODO: remove 'maxResources'
getResourceCacheLimits(int * maxResources,size_t * maxResourceBytes) const1108 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
setResourceCacheLimits(int maxResources,size_t maxResourceBytes)1118 void GrContext::setResourceCacheLimits(int maxResources, size_t maxResourceBytes) {
1119 ASSERT_SINGLE_OWNER
1120 fResourceCache->setLimits(maxResources, maxResourceBytes);
1121 }
1122
1123 //////////////////////////////////////////////////////////////////////////////
dumpMemoryStatistics(SkTraceMemoryDump * traceMemoryDump) const1124 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"
dump() const1134 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