1 /*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8
9 #include "include/gpu/GrDirectContext.h"
10
11 #include "include/core/SkTraceMemoryDump.h"
12 #include "include/gpu/GrBackendSemaphore.h"
13 #include "include/gpu/GrContextThreadSafeProxy.h"
14 #include "src/core/SkAutoMalloc.h"
15 #include "src/core/SkTaskGroup.h"
16 #include "src/core/SkTraceEvent.h"
17 #include "src/gpu/GrBackendUtils.h"
18 #include "src/gpu/GrClientMappedBufferManager.h"
19 #include "src/gpu/GrContextThreadSafeProxyPriv.h"
20 #include "src/gpu/GrDirectContextPriv.h"
21 #include "src/gpu/GrDrawingManager.h"
22 #include "src/gpu/GrGpu.h"
23 #include "src/gpu/GrResourceProvider.h"
24 #include "src/gpu/GrSemaphore.h"
25 #include "src/gpu/GrShaderUtils.h"
26 #include "src/gpu/GrThreadSafePipelineBuilder.h"
27 #include "src/gpu/SurfaceContext.h"
28 #include "src/gpu/effects/GrSkSLFP.h"
29 #include "src/gpu/mock/GrMockGpu.h"
30 #include "src/gpu/text/GrAtlasManager.h"
31 #include "src/gpu/text/GrStrikeCache.h"
32 #include "src/image/SkImage_GpuBase.h"
33 #if SK_GPU_V1
34 #include "src/gpu/ops/SmallPathAtlasMgr.h"
35 #else
36 // A vestigial definition for v2 that will never be instantiated
37 namespace skgpu::v1 {
38 class SmallPathAtlasMgr {
39 public:
SmallPathAtlasMgr()40 SmallPathAtlasMgr() { SkASSERT(0); }
reset()41 void reset() { SkASSERT(0); }
42 };
43 }
44 #endif
45 #ifdef SK_GL
46 #include "src/gpu/gl/GrGLGpu.h"
47 #endif
48 #ifdef SK_METAL
49 #include "include/gpu/mtl/GrMtlBackendContext.h"
50 #include "src/gpu/mtl/GrMtlTrampoline.h"
51 #endif
52 #ifdef SK_VULKAN
53 #include "src/gpu/vk/GrVkGpu.h"
54 #endif
55 #ifdef SK_DIRECT3D
56 #include "src/gpu/d3d/GrD3DGpu.h"
57 #endif
58 #ifdef SK_DAWN
59 #include "src/gpu/dawn/GrDawnGpu.h"
60 #endif
61 #include <memory>
62
63 #if GR_TEST_UTILS
64 # include "include/utils/SkRandom.h"
65 # if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS)
66 # include <sanitizer/lsan_interface.h>
67 # endif
68 #endif
69
70 #define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(this->singleOwner())
71
Next()72 GrDirectContext::DirectContextID GrDirectContext::DirectContextID::Next() {
73 static std::atomic<uint32_t> nextID{1};
74 uint32_t id;
75 do {
76 id = nextID.fetch_add(1, std::memory_order_relaxed);
77 } while (id == SK_InvalidUniqueID);
78 return DirectContextID(id);
79 }
80
GrDirectContext(GrBackendApi backend,const GrContextOptions & options)81 GrDirectContext::GrDirectContext(GrBackendApi backend, const GrContextOptions& options)
82 : INHERITED(GrContextThreadSafeProxyPriv::Make(backend, options), false)
83 , fDirectContextID(DirectContextID::Next()) {
84 }
85
~GrDirectContext()86 GrDirectContext::~GrDirectContext() {
87 ASSERT_SINGLE_OWNER
88 // this if-test protects against the case where the context is being destroyed
89 // before having been fully created
90 if (fGpu) {
91 this->flushAndSubmit();
92 }
93
94 // We need to make sure all work is finished on the gpu before we start releasing resources.
95 this->syncAllOutstandingGpuWork(/*shouldExecuteWhileAbandoned=*/false);
96
97 this->destroyDrawingManager();
98
99 // Ideally we could just let the ptr drop, but resource cache queries this ptr in releaseAll.
100 if (fResourceCache) {
101 fResourceCache->releaseAll();
102 }
103 // This has to be after GrResourceCache::releaseAll so that other threads that are holding
104 // async pixel result don't try to destroy buffers off thread.
105 fMappedBufferManager.reset();
106 }
107
threadSafeProxy()108 sk_sp<GrContextThreadSafeProxy> GrDirectContext::threadSafeProxy() {
109 return INHERITED::threadSafeProxy();
110 }
111
resetGLTextureBindings()112 void GrDirectContext::resetGLTextureBindings() {
113 if (this->abandoned() || this->backend() != GrBackendApi::kOpenGL) {
114 return;
115 }
116 fGpu->resetTextureBindings();
117 }
118
resetContext(uint32_t state)119 void GrDirectContext::resetContext(uint32_t state) {
120 ASSERT_SINGLE_OWNER
121 fGpu->markContextDirty(state);
122 }
123
abandonContext()124 void GrDirectContext::abandonContext() {
125 if (INHERITED::abandoned()) {
126 return;
127 }
128
129 INHERITED::abandonContext();
130
131 // We need to make sure all work is finished on the gpu before we start releasing resources.
132 this->syncAllOutstandingGpuWork(this->caps()->mustSyncGpuDuringAbandon());
133
134 fStrikeCache->freeAll();
135
136 fMappedBufferManager->abandon();
137
138 fResourceProvider->abandon();
139
140 // abandon first so destructors don't try to free the resources in the API.
141 fResourceCache->abandonAll();
142
143 fGpu->disconnect(GrGpu::DisconnectType::kAbandon);
144
145 // Must be after GrResourceCache::abandonAll().
146 fMappedBufferManager.reset();
147
148 if (fSmallPathAtlasMgr) {
149 fSmallPathAtlasMgr->reset();
150 }
151 fAtlasManager->freeAll();
152 }
153
abandoned()154 bool GrDirectContext::abandoned() {
155 if (INHERITED::abandoned()) {
156 return true;
157 }
158
159 if (fGpu && fGpu->isDeviceLost()) {
160 this->abandonContext();
161 return true;
162 }
163 return false;
164 }
165
oomed()166 bool GrDirectContext::oomed() { return fGpu ? fGpu->checkAndResetOOMed() : false; }
167
releaseResourcesAndAbandonContext()168 void GrDirectContext::releaseResourcesAndAbandonContext() {
169 if (INHERITED::abandoned()) {
170 return;
171 }
172
173 INHERITED::abandonContext();
174
175 // We need to make sure all work is finished on the gpu before we start releasing resources.
176 this->syncAllOutstandingGpuWork(/*shouldExecuteWhileAbandoned=*/true);
177
178 fResourceProvider->abandon();
179
180 // Release all resources in the backend 3D API.
181 fResourceCache->releaseAll();
182
183 // Must be after GrResourceCache::releaseAll().
184 fMappedBufferManager.reset();
185
186 fGpu->disconnect(GrGpu::DisconnectType::kCleanup);
187 if (fSmallPathAtlasMgr) {
188 fSmallPathAtlasMgr->reset();
189 }
190 fAtlasManager->freeAll();
191 }
192
freeGpuResources()193 void GrDirectContext::freeGpuResources() {
194 ASSERT_SINGLE_OWNER
195
196 if (this->abandoned()) {
197 return;
198 }
199
200 this->flushAndSubmit();
201 if (fSmallPathAtlasMgr) {
202 fSmallPathAtlasMgr->reset();
203 }
204 fAtlasManager->freeAll();
205
206 // TODO: the glyph cache doesn't hold any GpuResources so this call should not be needed here.
207 // Some slack in the GrTextBlob's implementation requires it though. That could be fixed.
208 fStrikeCache->freeAll();
209
210 this->drawingManager()->freeGpuResources();
211
212 fResourceCache->purgeUnlockedResources();
213 }
214
init()215 bool GrDirectContext::init() {
216 ASSERT_SINGLE_OWNER
217 if (!fGpu) {
218 return false;
219 }
220
221 fThreadSafeProxy->priv().init(fGpu->refCaps(), fGpu->refPipelineBuilder());
222 if (!INHERITED::init()) {
223 return false;
224 }
225
226 SkASSERT(this->getTextBlobCache());
227 SkASSERT(this->threadSafeCache());
228
229 fStrikeCache = std::make_unique<GrStrikeCache>();
230 fResourceCache = std::make_unique<GrResourceCache>(this->singleOwner(),
231 this->directContextID(),
232 this->contextID());
233 fResourceCache->setProxyProvider(this->proxyProvider());
234 fResourceCache->setThreadSafeCache(this->threadSafeCache());
235 #if GR_TEST_UTILS
236 if (this->options().fResourceCacheLimitOverride != -1) {
237 this->setResourceCacheLimit(this->options().fResourceCacheLimitOverride);
238 }
239 #endif
240 fResourceProvider = std::make_unique<GrResourceProvider>(fGpu.get(), fResourceCache.get(),
241 this->singleOwner());
242 fMappedBufferManager = std::make_unique<GrClientMappedBufferManager>(this->directContextID());
243
244 fDidTestPMConversions = false;
245
246 // DDL TODO: we need to think through how the task group & persistent cache
247 // get passed on to/shared between all the DDLRecorders created with this context.
248 if (this->options().fExecutor) {
249 fTaskGroup = std::make_unique<SkTaskGroup>(*this->options().fExecutor);
250 }
251
252 fPersistentCache = this->options().fPersistentCache;
253
254 GrDrawOpAtlas::AllowMultitexturing allowMultitexturing;
255 if (GrContextOptions::Enable::kNo == this->options().fAllowMultipleGlyphCacheTextures ||
256 // multitexturing supported only if range can represent the index + texcoords fully
257 !(this->caps()->shaderCaps()->floatIs32Bits() ||
258 this->caps()->shaderCaps()->integerSupport())) {
259 allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kNo;
260 } else {
261 allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes;
262 }
263
264 GrProxyProvider* proxyProvider = this->priv().proxyProvider();
265
266 fAtlasManager = std::make_unique<GrAtlasManager>(proxyProvider,
267 this->options().fGlyphCacheTextureMaximumBytes,
268 allowMultitexturing);
269 this->priv().addOnFlushCallbackObject(fAtlasManager.get());
270
271 return true;
272 }
273
getResourceCacheUsage(int * resourceCount,size_t * resourceBytes) const274 void GrDirectContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const {
275 ASSERT_SINGLE_OWNER
276
277 if (resourceCount) {
278 *resourceCount = fResourceCache->getBudgetedResourceCount();
279 }
280 if (resourceBytes) {
281 *resourceBytes = fResourceCache->getBudgetedResourceBytes();
282 }
283 }
284
getResourceCachePurgeableBytes() const285 size_t GrDirectContext::getResourceCachePurgeableBytes() const {
286 ASSERT_SINGLE_OWNER
287 return fResourceCache->getPurgeableBytes();
288 }
289
getResourceCacheLimits(int * maxResources,size_t * maxResourceBytes) const290 void GrDirectContext::getResourceCacheLimits(int* maxResources, size_t* maxResourceBytes) const {
291 ASSERT_SINGLE_OWNER
292 if (maxResources) {
293 *maxResources = -1;
294 }
295 if (maxResourceBytes) {
296 *maxResourceBytes = this->getResourceCacheLimit();
297 }
298 }
299
getResourceCacheLimit() const300 size_t GrDirectContext::getResourceCacheLimit() const {
301 ASSERT_SINGLE_OWNER
302 return fResourceCache->getMaxResourceBytes();
303 }
304
setResourceCacheLimits(int unused,size_t maxResourceBytes)305 void GrDirectContext::setResourceCacheLimits(int unused, size_t maxResourceBytes) {
306 ASSERT_SINGLE_OWNER
307 this->setResourceCacheLimit(maxResourceBytes);
308 }
309
setResourceCacheLimit(size_t maxResourceBytes)310 void GrDirectContext::setResourceCacheLimit(size_t maxResourceBytes) {
311 ASSERT_SINGLE_OWNER
312 fResourceCache->setLimit(maxResourceBytes);
313 }
314
purgeUnlockedResources(bool scratchResourcesOnly)315 void GrDirectContext::purgeUnlockedResources(bool scratchResourcesOnly) {
316 ASSERT_SINGLE_OWNER
317
318 if (this->abandoned()) {
319 return;
320 }
321
322 fResourceCache->purgeUnlockedResources(scratchResourcesOnly);
323 fResourceCache->purgeAsNeeded();
324
325 // The textBlob Cache doesn't actually hold any GPU resource but this is a convenient
326 // place to purge stale blobs
327 this->getTextBlobCache()->purgeStaleBlobs();
328
329 fGpu->releaseUnlockedBackendObjects();
330 }
331
purgeUnlockAndSafeCacheGpuResources()332 void GrDirectContext::purgeUnlockAndSafeCacheGpuResources() {
333 ASSERT_SINGLE_OWNER
334
335 if (this->abandoned()) {
336 return;
337 }
338
339 fResourceCache->purgeUnlockAndSafeCacheGpuResources();
340 fResourceCache->purgeAsNeeded();
341
342 // The textBlob Cache doesn't actually hold any GPU resource but this is a convenient
343 // place to purge stale blobs
344 this->getTextBlobCache()->purgeStaleBlobs();
345
346 fGpu->releaseUnlockedBackendObjects();
347 }
348
purgeUnlockedResourcesByTag(bool scratchResourceseOnly,const GrGpuResourceTag tag)349 void GrDirectContext::purgeUnlockedResourcesByTag(bool scratchResourceseOnly, const GrGpuResourceTag tag) {
350 ASSERT_SINGLE_OWNER
351 fResourceCache->purgeUnlockedResourcesByTag(scratchResourceseOnly, tag);
352 fResourceCache->purgeAsNeeded();
353
354 // The textBlod Cache doesn't actually hold any GPU resource but this is a convenient
355 // place to purge stale blobs
356 this->getTextBlobCache()->purgeStaleBlobs();
357 }
358
performDeferredCleanup(std::chrono::milliseconds msNotUsed,bool scratchResourcesOnly)359 void GrDirectContext::performDeferredCleanup(std::chrono::milliseconds msNotUsed,
360 bool scratchResourcesOnly) {
361 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
362
363 ASSERT_SINGLE_OWNER
364
365 if (this->abandoned()) {
366 return;
367 }
368
369 this->checkAsyncWorkCompletion();
370 fMappedBufferManager->process();
371 auto purgeTime = GrStdSteadyClock::now() - msNotUsed;
372
373 fResourceCache->purgeAsNeeded();
374 fResourceCache->purgeResourcesNotUsedSince(purgeTime, scratchResourcesOnly);
375
376 // The textBlob Cache doesn't actually hold any GPU resource but this is a convenient
377 // place to purge stale blobs
378 this->getTextBlobCache()->purgeStaleBlobs();
379 }
380
purgeUnlockedResources(size_t bytesToPurge,bool preferScratchResources)381 void GrDirectContext::purgeUnlockedResources(size_t bytesToPurge, bool preferScratchResources) {
382 ASSERT_SINGLE_OWNER
383
384 if (this->abandoned()) {
385 return;
386 }
387
388 fResourceCache->purgeUnlockedResources(bytesToPurge, preferScratchResources);
389 }
390
391 ////////////////////////////////////////////////////////////////////////////////
wait(int numSemaphores,const GrBackendSemaphore waitSemaphores[],bool deleteSemaphoresAfterWait)392 bool GrDirectContext::wait(int numSemaphores, const GrBackendSemaphore waitSemaphores[],
393 bool deleteSemaphoresAfterWait) {
394 if (!fGpu || !fGpu->caps()->semaphoreSupport()) {
395 return false;
396 }
397 GrWrapOwnership ownership =
398 deleteSemaphoresAfterWait ? kAdopt_GrWrapOwnership : kBorrow_GrWrapOwnership;
399 for (int i = 0; i < numSemaphores; ++i) {
400 std::unique_ptr<GrSemaphore> sema = fResourceProvider->wrapBackendSemaphore(
401 waitSemaphores[i], GrSemaphoreWrapType::kWillWait, ownership);
402 // If we failed to wrap the semaphore it means the client didn't give us a valid semaphore
403 // to begin with. Therefore, it is fine to not wait on it.
404 if (sema) {
405 fGpu->waitSemaphore(sema.get());
406 }
407 }
408 return true;
409 }
410
onGetSmallPathAtlasMgr()411 skgpu::v1::SmallPathAtlasMgr* GrDirectContext::onGetSmallPathAtlasMgr() {
412 #if SK_GPU_V1
413 if (!fSmallPathAtlasMgr) {
414 fSmallPathAtlasMgr = std::make_unique<skgpu::v1::SmallPathAtlasMgr>();
415
416 this->priv().addOnFlushCallbackObject(fSmallPathAtlasMgr.get());
417 }
418
419 if (!fSmallPathAtlasMgr->initAtlas(this->proxyProvider(), this->caps())) {
420 return nullptr;
421 }
422 #endif
423
424 return fSmallPathAtlasMgr.get();
425 }
426
427 ////////////////////////////////////////////////////////////////////////////////
428
flush(const GrFlushInfo & info)429 GrSemaphoresSubmitted GrDirectContext::flush(const GrFlushInfo& info) {
430 ASSERT_SINGLE_OWNER
431 if (this->abandoned()) {
432 if (info.fFinishedProc) {
433 info.fFinishedProc(info.fFinishedContext);
434 }
435 if (info.fSubmittedProc) {
436 info.fSubmittedProc(info.fSubmittedContext, false);
437 }
438 return GrSemaphoresSubmitted::kNo;
439 }
440
441 return this->drawingManager()->flushSurfaces({}, SkSurface::BackendSurfaceAccess::kNoAccess,
442 info, nullptr);
443 }
444
submit(bool syncCpu)445 bool GrDirectContext::submit(bool syncCpu) {
446 ASSERT_SINGLE_OWNER
447 if (this->abandoned()) {
448 return false;
449 }
450
451 if (!fGpu) {
452 return false;
453 }
454
455 return fGpu->submitToGpu(syncCpu);
456 }
457
458 ////////////////////////////////////////////////////////////////////////////////
459
checkAsyncWorkCompletion()460 void GrDirectContext::checkAsyncWorkCompletion() {
461 if (fGpu) {
462 fGpu->checkFinishProcs();
463 }
464 }
465
syncAllOutstandingGpuWork(bool shouldExecuteWhileAbandoned)466 void GrDirectContext::syncAllOutstandingGpuWork(bool shouldExecuteWhileAbandoned) {
467 if (fGpu && (!this->abandoned() || shouldExecuteWhileAbandoned)) {
468 fGpu->finishOutstandingGpuWork();
469 this->checkAsyncWorkCompletion();
470 }
471 }
472
473 ////////////////////////////////////////////////////////////////////////////////
474
storeVkPipelineCacheData()475 void GrDirectContext::storeVkPipelineCacheData() {
476 if (fGpu) {
477 fGpu->storeVkPipelineCacheData();
478 }
479 }
480
481 ////////////////////////////////////////////////////////////////////////////////
482
supportsDistanceFieldText() const483 bool GrDirectContext::supportsDistanceFieldText() const {
484 return this->caps()->shaderCaps()->supportsDistanceFieldText();
485 }
486
487 //////////////////////////////////////////////////////////////////////////////
488
dumpMemoryStatistics(SkTraceMemoryDump * traceMemoryDump) const489 void GrDirectContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
490 ASSERT_SINGLE_OWNER
491 fResourceCache->dumpMemoryStatistics(traceMemoryDump);
492 traceMemoryDump->dumpNumericValue("skia/gr_text_blob_cache", "size", "bytes",
493 this->getTextBlobCache()->usedBytes());
494 }
495
dumpMemoryStatisticsByTag(SkTraceMemoryDump * traceMemoryDump,GrGpuResourceTag tag) const496 void GrDirectContext::dumpMemoryStatisticsByTag(SkTraceMemoryDump* traceMemoryDump, GrGpuResourceTag tag) const {
497 ASSERT_SINGLE_OWNER
498 fResourceCache->dumpMemoryStatistics(traceMemoryDump, tag);
499 traceMemoryDump->dumpNumericValue("skia/gr_text_blob_cache", "size", "bytes",
500 this->getTextBlobCache()->usedBytes());
501 }
502
setCurrentGrResourceTag(const GrGpuResourceTag tag)503 void GrDirectContext::setCurrentGrResourceTag(const GrGpuResourceTag tag) {
504 if (fResourceCache) {
505 return fResourceCache->setCurrentGrResourceTag(tag);
506 }
507 }
508
getCurrentGrResourceTag() const509 GrGpuResourceTag GrDirectContext::getCurrentGrResourceTag() const {
510 if (fResourceCache) {
511 return fResourceCache->getCurrentGrResourceTag();
512 }
513 return {};
514 }
releaseByTag(const GrGpuResourceTag tag)515 void GrDirectContext::releaseByTag(const GrGpuResourceTag tag) {
516 if (fResourceCache) {
517 fResourceCache->releaseByTag(tag);
518 }
519 }
getAllGrGpuResourceTags() const520 std::set<GrGpuResourceTag> GrDirectContext::getAllGrGpuResourceTags() const {
521 if (fResourceCache) {
522 return fResourceCache->getAllGrGpuResourceTags();
523 }
524 return {};
525 }
526
createBackendTexture(int width,int height,const GrBackendFormat & backendFormat,GrMipmapped mipMapped,GrRenderable renderable,GrProtected isProtected)527 GrBackendTexture GrDirectContext::createBackendTexture(int width, int height,
528 const GrBackendFormat& backendFormat,
529 GrMipmapped mipMapped,
530 GrRenderable renderable,
531 GrProtected isProtected) {
532 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
533 if (this->abandoned()) {
534 return GrBackendTexture();
535 }
536
537 return fGpu->createBackendTexture({width, height}, backendFormat, renderable,
538 mipMapped, isProtected);
539 }
540
createBackendTexture(int width,int height,SkColorType skColorType,GrMipmapped mipMapped,GrRenderable renderable,GrProtected isProtected)541 GrBackendTexture GrDirectContext::createBackendTexture(int width, int height,
542 SkColorType skColorType,
543 GrMipmapped mipMapped,
544 GrRenderable renderable,
545 GrProtected isProtected) {
546 if (this->abandoned()) {
547 return GrBackendTexture();
548 }
549
550 const GrBackendFormat format = this->defaultBackendFormat(skColorType, renderable);
551
552 return this->createBackendTexture(width, height, format, mipMapped, renderable, isProtected);
553 }
554
create_and_clear_backend_texture(GrDirectContext * dContext,SkISize dimensions,const GrBackendFormat & backendFormat,GrMipmapped mipMapped,GrRenderable renderable,GrProtected isProtected,sk_sp<GrRefCntedCallback> finishedCallback,std::array<float,4> color)555 static GrBackendTexture create_and_clear_backend_texture(GrDirectContext* dContext,
556 SkISize dimensions,
557 const GrBackendFormat& backendFormat,
558 GrMipmapped mipMapped,
559 GrRenderable renderable,
560 GrProtected isProtected,
561 sk_sp<GrRefCntedCallback> finishedCallback,
562 std::array<float, 4> color) {
563 GrGpu* gpu = dContext->priv().getGpu();
564 GrBackendTexture beTex = gpu->createBackendTexture(dimensions, backendFormat, renderable,
565 mipMapped, isProtected);
566 if (!beTex.isValid()) {
567 return {};
568 }
569
570 if (!dContext->priv().getGpu()->clearBackendTexture(beTex,
571 std::move(finishedCallback),
572 color)) {
573 dContext->deleteBackendTexture(beTex);
574 return {};
575 }
576 return beTex;
577 }
578
update_texture_with_pixmaps(GrDirectContext * context,const SkPixmap src[],int numLevels,const GrBackendTexture & backendTexture,GrSurfaceOrigin textureOrigin,sk_sp<GrRefCntedCallback> finishedCallback)579 static bool update_texture_with_pixmaps(GrDirectContext* context,
580 const SkPixmap src[],
581 int numLevels,
582 const GrBackendTexture& backendTexture,
583 GrSurfaceOrigin textureOrigin,
584 sk_sp<GrRefCntedCallback> finishedCallback) {
585 GrColorType ct = SkColorTypeToGrColorType(src[0].colorType());
586 const GrBackendFormat& format = backendTexture.getBackendFormat();
587
588 if (!context->priv().caps()->areColorTypeAndFormatCompatible(ct, format)) {
589 return false;
590 }
591
592 auto proxy = context->priv().proxyProvider()->wrapBackendTexture(backendTexture,
593 kBorrow_GrWrapOwnership,
594 GrWrapCacheable::kNo,
595 kRW_GrIOType,
596 std::move(finishedCallback));
597 if (!proxy) {
598 return false;
599 }
600
601 GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(format, ct);
602 GrSurfaceProxyView view(std::move(proxy), textureOrigin, swizzle);
603 skgpu::SurfaceContext surfaceContext(context, std::move(view), src[0].info().colorInfo());
604 SkAutoSTArray<15, GrCPixmap> tmpSrc(numLevels);
605 for (int i = 0; i < numLevels; ++i) {
606 tmpSrc[i] = src[i];
607 }
608 if (!surfaceContext.writePixels(context, tmpSrc.get(), numLevels)) {
609 return false;
610 }
611
612 GrSurfaceProxy* p = surfaceContext.asSurfaceProxy();
613 GrFlushInfo info;
614 context->priv().drawingManager()->flushSurfaces({&p, 1},
615 SkSurface::BackendSurfaceAccess::kNoAccess,
616 info,
617 nullptr);
618 return true;
619 }
620
createBackendTexture(int width,int height,const GrBackendFormat & backendFormat,const SkColor4f & color,GrMipmapped mipMapped,GrRenderable renderable,GrProtected isProtected,GrGpuFinishedProc finishedProc,GrGpuFinishedContext finishedContext)621 GrBackendTexture GrDirectContext::createBackendTexture(int width, int height,
622 const GrBackendFormat& backendFormat,
623 const SkColor4f& color,
624 GrMipmapped mipMapped,
625 GrRenderable renderable,
626 GrProtected isProtected,
627 GrGpuFinishedProc finishedProc,
628 GrGpuFinishedContext finishedContext) {
629 auto finishedCallback = GrRefCntedCallback::Make(finishedProc, finishedContext);
630
631 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
632 if (this->abandoned()) {
633 return {};
634 }
635
636 return create_and_clear_backend_texture(this,
637 {width, height},
638 backendFormat,
639 mipMapped,
640 renderable,
641 isProtected,
642 std::move(finishedCallback),
643 color.array());
644 }
645
createBackendTexture(int width,int height,SkColorType skColorType,const SkColor4f & color,GrMipmapped mipMapped,GrRenderable renderable,GrProtected isProtected,GrGpuFinishedProc finishedProc,GrGpuFinishedContext finishedContext)646 GrBackendTexture GrDirectContext::createBackendTexture(int width, int height,
647 SkColorType skColorType,
648 const SkColor4f& color,
649 GrMipmapped mipMapped,
650 GrRenderable renderable,
651 GrProtected isProtected,
652 GrGpuFinishedProc finishedProc,
653 GrGpuFinishedContext finishedContext) {
654 auto finishedCallback = GrRefCntedCallback::Make(finishedProc, finishedContext);
655
656 if (this->abandoned()) {
657 return {};
658 }
659
660 GrBackendFormat format = this->defaultBackendFormat(skColorType, renderable);
661 if (!format.isValid()) {
662 return {};
663 }
664
665 GrColorType grColorType = SkColorTypeToGrColorType(skColorType);
666 SkColor4f swizzledColor = this->caps()->getWriteSwizzle(format, grColorType).applyTo(color);
667
668 return create_and_clear_backend_texture(this,
669 {width, height},
670 format,
671 mipMapped,
672 renderable,
673 isProtected,
674 std::move(finishedCallback),
675 swizzledColor.array());
676 }
677
createBackendTexture(const SkPixmap srcData[],int numProvidedLevels,GrSurfaceOrigin textureOrigin,GrRenderable renderable,GrProtected isProtected,GrGpuFinishedProc finishedProc,GrGpuFinishedContext finishedContext)678 GrBackendTexture GrDirectContext::createBackendTexture(const SkPixmap srcData[],
679 int numProvidedLevels,
680 GrSurfaceOrigin textureOrigin,
681 GrRenderable renderable,
682 GrProtected isProtected,
683 GrGpuFinishedProc finishedProc,
684 GrGpuFinishedContext finishedContext) {
685 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
686
687 auto finishedCallback = GrRefCntedCallback::Make(finishedProc, finishedContext);
688
689 if (this->abandoned()) {
690 return {};
691 }
692
693 if (!srcData || numProvidedLevels <= 0) {
694 return {};
695 }
696
697 SkColorType colorType = srcData[0].colorType();
698
699 GrMipmapped mipMapped = GrMipmapped::kNo;
700 if (numProvidedLevels > 1) {
701 mipMapped = GrMipmapped::kYes;
702 }
703
704 GrBackendFormat backendFormat = this->defaultBackendFormat(colorType, renderable);
705 GrBackendTexture beTex = this->createBackendTexture(srcData[0].width(),
706 srcData[0].height(),
707 backendFormat,
708 mipMapped,
709 renderable,
710 isProtected);
711 if (!beTex.isValid()) {
712 return {};
713 }
714 if (!update_texture_with_pixmaps(this,
715 srcData,
716 numProvidedLevels,
717 beTex,
718 textureOrigin,
719 std::move(finishedCallback))) {
720 this->deleteBackendTexture(beTex);
721 return {};
722 }
723 return beTex;
724 }
725
updateBackendTexture(const GrBackendTexture & backendTexture,const SkColor4f & color,GrGpuFinishedProc finishedProc,GrGpuFinishedContext finishedContext)726 bool GrDirectContext::updateBackendTexture(const GrBackendTexture& backendTexture,
727 const SkColor4f& color,
728 GrGpuFinishedProc finishedProc,
729 GrGpuFinishedContext finishedContext) {
730 auto finishedCallback = GrRefCntedCallback::Make(finishedProc, finishedContext);
731
732 if (this->abandoned()) {
733 return false;
734 }
735
736 return fGpu->clearBackendTexture(backendTexture, std::move(finishedCallback), color.array());
737 }
738
updateBackendTexture(const GrBackendTexture & backendTexture,SkColorType skColorType,const SkColor4f & color,GrGpuFinishedProc finishedProc,GrGpuFinishedContext finishedContext)739 bool GrDirectContext::updateBackendTexture(const GrBackendTexture& backendTexture,
740 SkColorType skColorType,
741 const SkColor4f& color,
742 GrGpuFinishedProc finishedProc,
743 GrGpuFinishedContext finishedContext) {
744 auto finishedCallback = GrRefCntedCallback::Make(finishedProc, finishedContext);
745
746 if (this->abandoned()) {
747 return false;
748 }
749
750 GrBackendFormat format = backendTexture.getBackendFormat();
751 GrColorType grColorType = SkColorTypeToGrColorType(skColorType);
752
753 if (!this->caps()->areColorTypeAndFormatCompatible(grColorType, format)) {
754 return false;
755 }
756
757 GrSwizzle swizzle = this->caps()->getWriteSwizzle(format, grColorType);
758 SkColor4f swizzledColor = swizzle.applyTo(color);
759
760 return fGpu->clearBackendTexture(backendTexture,
761 std::move(finishedCallback),
762 swizzledColor.array());
763 }
764
updateBackendTexture(const GrBackendTexture & backendTexture,const SkPixmap srcData[],int numLevels,GrSurfaceOrigin textureOrigin,GrGpuFinishedProc finishedProc,GrGpuFinishedContext finishedContext)765 bool GrDirectContext::updateBackendTexture(const GrBackendTexture& backendTexture,
766 const SkPixmap srcData[],
767 int numLevels,
768 GrSurfaceOrigin textureOrigin,
769 GrGpuFinishedProc finishedProc,
770 GrGpuFinishedContext finishedContext) {
771 auto finishedCallback = GrRefCntedCallback::Make(finishedProc, finishedContext);
772
773 if (this->abandoned()) {
774 return false;
775 }
776
777 if (!srcData || numLevels <= 0) {
778 return false;
779 }
780
781 // If the texture has MIP levels then we require that the full set is overwritten.
782 int numExpectedLevels = 1;
783 if (backendTexture.hasMipmaps()) {
784 numExpectedLevels = SkMipmap::ComputeLevelCount(backendTexture.width(),
785 backendTexture.height()) + 1;
786 }
787 if (numLevels != numExpectedLevels) {
788 return false;
789 }
790 return update_texture_with_pixmaps(this,
791 srcData,
792 numLevels,
793 backendTexture,
794 textureOrigin,
795 std::move(finishedCallback));
796 }
797
798 //////////////////////////////////////////////////////////////////////////////
799
create_and_update_compressed_backend_texture(GrDirectContext * dContext,SkISize dimensions,const GrBackendFormat & backendFormat,GrMipmapped mipMapped,GrProtected isProtected,sk_sp<GrRefCntedCallback> finishedCallback,const void * data,size_t size)800 static GrBackendTexture create_and_update_compressed_backend_texture(
801 GrDirectContext* dContext,
802 SkISize dimensions,
803 const GrBackendFormat& backendFormat,
804 GrMipmapped mipMapped,
805 GrProtected isProtected,
806 sk_sp<GrRefCntedCallback> finishedCallback,
807 const void* data,
808 size_t size) {
809 GrGpu* gpu = dContext->priv().getGpu();
810
811 GrBackendTexture beTex = gpu->createCompressedBackendTexture(dimensions, backendFormat,
812 mipMapped, isProtected);
813 if (!beTex.isValid()) {
814 return {};
815 }
816
817 if (!dContext->priv().getGpu()->updateCompressedBackendTexture(
818 beTex, std::move(finishedCallback), data, size)) {
819 dContext->deleteBackendTexture(beTex);
820 return {};
821 }
822 return beTex;
823 }
824
createCompressedBackendTexture(int width,int height,const GrBackendFormat & backendFormat,const SkColor4f & color,GrMipmapped mipmapped,GrProtected isProtected,GrGpuFinishedProc finishedProc,GrGpuFinishedContext finishedContext)825 GrBackendTexture GrDirectContext::createCompressedBackendTexture(
826 int width, int height,
827 const GrBackendFormat& backendFormat,
828 const SkColor4f& color,
829 GrMipmapped mipmapped,
830 GrProtected isProtected,
831 GrGpuFinishedProc finishedProc,
832 GrGpuFinishedContext finishedContext) {
833 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
834 auto finishedCallback = GrRefCntedCallback::Make(finishedProc, finishedContext);
835
836 if (this->abandoned()) {
837 return {};
838 }
839
840 SkImage::CompressionType compression = GrBackendFormatToCompressionType(backendFormat);
841 if (compression == SkImage::CompressionType::kNone) {
842 return {};
843 }
844
845 size_t size = SkCompressedDataSize(compression,
846 {width, height},
847 nullptr,
848 mipmapped == GrMipmapped::kYes);
849 auto storage = std::make_unique<char[]>(size);
850 GrFillInCompressedData(compression, {width, height}, mipmapped, storage.get(), color);
851 return create_and_update_compressed_backend_texture(this,
852 {width, height},
853 backendFormat,
854 mipmapped,
855 isProtected,
856 std::move(finishedCallback),
857 storage.get(),
858 size);
859 }
860
createCompressedBackendTexture(int width,int height,SkImage::CompressionType compression,const SkColor4f & color,GrMipmapped mipMapped,GrProtected isProtected,GrGpuFinishedProc finishedProc,GrGpuFinishedContext finishedContext)861 GrBackendTexture GrDirectContext::createCompressedBackendTexture(
862 int width, int height,
863 SkImage::CompressionType compression,
864 const SkColor4f& color,
865 GrMipmapped mipMapped,
866 GrProtected isProtected,
867 GrGpuFinishedProc finishedProc,
868 GrGpuFinishedContext finishedContext) {
869 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
870 GrBackendFormat format = this->compressedBackendFormat(compression);
871 return this->createCompressedBackendTexture(width, height, format, color,
872 mipMapped, isProtected, finishedProc,
873 finishedContext);
874 }
875
createCompressedBackendTexture(int width,int height,const GrBackendFormat & backendFormat,const void * compressedData,size_t dataSize,GrMipmapped mipMapped,GrProtected isProtected,GrGpuFinishedProc finishedProc,GrGpuFinishedContext finishedContext)876 GrBackendTexture GrDirectContext::createCompressedBackendTexture(
877 int width, int height,
878 const GrBackendFormat& backendFormat,
879 const void* compressedData,
880 size_t dataSize,
881 GrMipmapped mipMapped,
882 GrProtected isProtected,
883 GrGpuFinishedProc finishedProc,
884 GrGpuFinishedContext finishedContext) {
885 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
886 auto finishedCallback = GrRefCntedCallback::Make(finishedProc, finishedContext);
887
888 if (this->abandoned()) {
889 return {};
890 }
891
892 return create_and_update_compressed_backend_texture(this,
893 {width, height},
894 backendFormat,
895 mipMapped,
896 isProtected,
897 std::move(finishedCallback),
898 compressedData,
899 dataSize);
900 }
901
createCompressedBackendTexture(int width,int height,SkImage::CompressionType compression,const void * data,size_t dataSize,GrMipmapped mipMapped,GrProtected isProtected,GrGpuFinishedProc finishedProc,GrGpuFinishedContext finishedContext)902 GrBackendTexture GrDirectContext::createCompressedBackendTexture(
903 int width, int height,
904 SkImage::CompressionType compression,
905 const void* data, size_t dataSize,
906 GrMipmapped mipMapped,
907 GrProtected isProtected,
908 GrGpuFinishedProc finishedProc,
909 GrGpuFinishedContext finishedContext) {
910 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
911 GrBackendFormat format = this->compressedBackendFormat(compression);
912 return this->createCompressedBackendTexture(width, height, format, data, dataSize, mipMapped,
913 isProtected, finishedProc, finishedContext);
914 }
915
updateCompressedBackendTexture(const GrBackendTexture & backendTexture,const SkColor4f & color,GrGpuFinishedProc finishedProc,GrGpuFinishedContext finishedContext)916 bool GrDirectContext::updateCompressedBackendTexture(const GrBackendTexture& backendTexture,
917 const SkColor4f& color,
918 GrGpuFinishedProc finishedProc,
919 GrGpuFinishedContext finishedContext) {
920 auto finishedCallback = GrRefCntedCallback::Make(finishedProc, finishedContext);
921
922 if (this->abandoned()) {
923 return false;
924 }
925
926 SkImage::CompressionType compression =
927 GrBackendFormatToCompressionType(backendTexture.getBackendFormat());
928 if (compression == SkImage::CompressionType::kNone) {
929 return {};
930 }
931 size_t size = SkCompressedDataSize(compression,
932 backendTexture.dimensions(),
933 nullptr,
934 backendTexture.hasMipmaps());
935 SkAutoMalloc storage(size);
936 GrFillInCompressedData(compression,
937 backendTexture.dimensions(),
938 backendTexture.mipmapped(),
939 static_cast<char*>(storage.get()),
940 color);
941 return fGpu->updateCompressedBackendTexture(backendTexture,
942 std::move(finishedCallback),
943 storage.get(),
944 size);
945 }
946
updateCompressedBackendTexture(const GrBackendTexture & backendTexture,const void * compressedData,size_t dataSize,GrGpuFinishedProc finishedProc,GrGpuFinishedContext finishedContext)947 bool GrDirectContext::updateCompressedBackendTexture(const GrBackendTexture& backendTexture,
948 const void* compressedData,
949 size_t dataSize,
950 GrGpuFinishedProc finishedProc,
951 GrGpuFinishedContext finishedContext) {
952 auto finishedCallback = GrRefCntedCallback::Make(finishedProc, finishedContext);
953
954 if (this->abandoned()) {
955 return false;
956 }
957
958 if (!compressedData) {
959 return false;
960 }
961
962 return fGpu->updateCompressedBackendTexture(backendTexture,
963 std::move(finishedCallback),
964 compressedData,
965 dataSize);
966 }
967
968 //////////////////////////////////////////////////////////////////////////////
969
setBackendTextureState(const GrBackendTexture & backendTexture,const GrBackendSurfaceMutableState & state,GrBackendSurfaceMutableState * previousState,GrGpuFinishedProc finishedProc,GrGpuFinishedContext finishedContext)970 bool GrDirectContext::setBackendTextureState(const GrBackendTexture& backendTexture,
971 const GrBackendSurfaceMutableState& state,
972 GrBackendSurfaceMutableState* previousState,
973 GrGpuFinishedProc finishedProc,
974 GrGpuFinishedContext finishedContext) {
975 auto callback = GrRefCntedCallback::Make(finishedProc, finishedContext);
976
977 if (this->abandoned()) {
978 return false;
979 }
980
981 return fGpu->setBackendTextureState(backendTexture, state, previousState, std::move(callback));
982 }
983
984
setBackendRenderTargetState(const GrBackendRenderTarget & backendRenderTarget,const GrBackendSurfaceMutableState & state,GrBackendSurfaceMutableState * previousState,GrGpuFinishedProc finishedProc,GrGpuFinishedContext finishedContext)985 bool GrDirectContext::setBackendRenderTargetState(const GrBackendRenderTarget& backendRenderTarget,
986 const GrBackendSurfaceMutableState& state,
987 GrBackendSurfaceMutableState* previousState,
988 GrGpuFinishedProc finishedProc,
989 GrGpuFinishedContext finishedContext) {
990 auto callback = GrRefCntedCallback::Make(finishedProc, finishedContext);
991
992 if (this->abandoned()) {
993 return false;
994 }
995
996 return fGpu->setBackendRenderTargetState(backendRenderTarget, state, previousState,
997 std::move(callback));
998 }
999
deleteBackendTexture(GrBackendTexture backendTex)1000 void GrDirectContext::deleteBackendTexture(GrBackendTexture backendTex) {
1001 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
1002 // For the Vulkan backend we still must destroy the backend texture when the context is
1003 // abandoned.
1004 if ((this->abandoned() && this->backend() != GrBackendApi::kVulkan) || !backendTex.isValid()) {
1005 return;
1006 }
1007
1008 fGpu->deleteBackendTexture(backendTex);
1009 }
1010
1011 //////////////////////////////////////////////////////////////////////////////
1012
precompileShader(const SkData & key,const SkData & data)1013 bool GrDirectContext::precompileShader(const SkData& key, const SkData& data) {
1014 return fGpu->precompileShader(key, data);
1015 }
1016
1017 #ifdef SK_ENABLE_DUMP_GPU
1018 #include "include/core/SkString.h"
1019 #include "src/utils/SkJSONWriter.h"
dump() const1020 SkString GrDirectContext::dump() const {
1021 SkDynamicMemoryWStream stream;
1022 SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty);
1023 writer.beginObject();
1024
1025 writer.appendString("backend", GrBackendApiToStr(this->backend()));
1026
1027 writer.appendName("caps");
1028 this->caps()->dumpJSON(&writer);
1029
1030 writer.appendName("gpu");
1031 this->fGpu->dumpJSON(&writer);
1032
1033 writer.appendName("context");
1034 this->dumpJSON(&writer);
1035
1036 // Flush JSON to the memory stream
1037 writer.endObject();
1038 writer.flush();
1039
1040 // Null terminate the JSON data in the memory stream
1041 stream.write8(0);
1042
1043 // Allocate a string big enough to hold all the data, then copy out of the stream
1044 SkString result(stream.bytesWritten());
1045 stream.copyToAndReset(result.writable_str());
1046 return result;
1047 }
1048 #endif
1049
1050 #ifdef SK_GL
1051
1052 /*************************************************************************************************/
MakeGL(sk_sp<const GrGLInterface> glInterface)1053 sk_sp<GrDirectContext> GrDirectContext::MakeGL(sk_sp<const GrGLInterface> glInterface) {
1054 GrContextOptions defaultOptions;
1055 return MakeGL(std::move(glInterface), defaultOptions);
1056 }
1057
MakeGL(const GrContextOptions & options)1058 sk_sp<GrDirectContext> GrDirectContext::MakeGL(const GrContextOptions& options) {
1059 return MakeGL(nullptr, options);
1060 }
1061
MakeGL()1062 sk_sp<GrDirectContext> GrDirectContext::MakeGL() {
1063 GrContextOptions defaultOptions;
1064 return MakeGL(nullptr, defaultOptions);
1065 }
1066
1067 #if GR_TEST_UTILS
make_get_error_with_random_oom(GrGLFunction<GrGLGetErrorFn> original)1068 GrGLFunction<GrGLGetErrorFn> make_get_error_with_random_oom(GrGLFunction<GrGLGetErrorFn> original) {
1069 // A SkRandom and a GrGLFunction<GrGLGetErrorFn> are too big to be captured by a
1070 // GrGLFunction<GrGLGetError> (surprise, surprise). So we make a context object and
1071 // capture that by pointer. However, GrGLFunction doesn't support calling a destructor
1072 // on the thing it captures. So we leak the context.
1073 struct GetErrorContext {
1074 SkRandom fRandom;
1075 GrGLFunction<GrGLGetErrorFn> fGetError;
1076 };
1077
1078 auto errorContext = new GetErrorContext;
1079
1080 #if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS)
1081 __lsan_ignore_object(errorContext);
1082 #endif
1083
1084 errorContext->fGetError = original;
1085
1086 return GrGLFunction<GrGLGetErrorFn>([errorContext]() {
1087 GrGLenum error = errorContext->fGetError();
1088 if (error == GR_GL_NO_ERROR && (errorContext->fRandom.nextU() % 300) == 0) {
1089 error = GR_GL_OUT_OF_MEMORY;
1090 }
1091 return error;
1092 });
1093 }
1094 #endif
1095
MakeGL(sk_sp<const GrGLInterface> glInterface,const GrContextOptions & options)1096 sk_sp<GrDirectContext> GrDirectContext::MakeGL(sk_sp<const GrGLInterface> glInterface,
1097 const GrContextOptions& options) {
1098 sk_sp<GrDirectContext> direct(new GrDirectContext(GrBackendApi::kOpenGL, options));
1099 #if GR_TEST_UTILS
1100 if (options.fRandomGLOOM) {
1101 auto copy = sk_make_sp<GrGLInterface>(*glInterface);
1102 copy->fFunctions.fGetError =
1103 make_get_error_with_random_oom(glInterface->fFunctions.fGetError);
1104 #if GR_GL_CHECK_ERROR
1105 // Suppress logging GL errors since we'll be synthetically generating them.
1106 copy->suppressErrorLogging();
1107 #endif
1108 glInterface = std::move(copy);
1109 }
1110 #endif
1111 direct->fGpu = GrGLGpu::Make(std::move(glInterface), options, direct.get());
1112 if (!direct->init()) {
1113 return nullptr;
1114 }
1115 return direct;
1116 }
1117 #endif
1118
1119 /*************************************************************************************************/
MakeMock(const GrMockOptions * mockOptions)1120 sk_sp<GrDirectContext> GrDirectContext::MakeMock(const GrMockOptions* mockOptions) {
1121 GrContextOptions defaultOptions;
1122 return MakeMock(mockOptions, defaultOptions);
1123 }
1124
MakeMock(const GrMockOptions * mockOptions,const GrContextOptions & options)1125 sk_sp<GrDirectContext> GrDirectContext::MakeMock(const GrMockOptions* mockOptions,
1126 const GrContextOptions& options) {
1127 sk_sp<GrDirectContext> direct(new GrDirectContext(GrBackendApi::kMock, options));
1128
1129 direct->fGpu = GrMockGpu::Make(mockOptions, options, direct.get());
1130 if (!direct->init()) {
1131 return nullptr;
1132 }
1133
1134 return direct;
1135 }
1136
1137 #ifdef SK_VULKAN
1138 /*************************************************************************************************/
MakeVulkan(const GrVkBackendContext & backendContext)1139 sk_sp<GrDirectContext> GrDirectContext::MakeVulkan(const GrVkBackendContext& backendContext) {
1140 GrContextOptions defaultOptions;
1141 return MakeVulkan(backendContext, defaultOptions);
1142 }
1143
MakeVulkan(const GrVkBackendContext & backendContext,const GrContextOptions & options)1144 sk_sp<GrDirectContext> GrDirectContext::MakeVulkan(const GrVkBackendContext& backendContext,
1145 const GrContextOptions& options) {
1146 sk_sp<GrDirectContext> direct(new GrDirectContext(GrBackendApi::kVulkan, options));
1147
1148 direct->fGpu = GrVkGpu::Make(backendContext, options, direct.get());
1149 if (!direct->init()) {
1150 return nullptr;
1151 }
1152
1153 return direct;
1154 }
1155 #endif
1156
1157 #ifdef SK_METAL
1158 /*************************************************************************************************/
MakeMetal(const GrMtlBackendContext & backendContext)1159 sk_sp<GrDirectContext> GrDirectContext::MakeMetal(const GrMtlBackendContext& backendContext) {
1160 GrContextOptions defaultOptions;
1161 return MakeMetal(backendContext, defaultOptions);
1162 }
1163
MakeMetal(const GrMtlBackendContext & backendContext,const GrContextOptions & options)1164 sk_sp<GrDirectContext> GrDirectContext::MakeMetal(const GrMtlBackendContext& backendContext,
1165 const GrContextOptions& options) {
1166 sk_sp<GrDirectContext> direct(new GrDirectContext(GrBackendApi::kMetal, options));
1167
1168 direct->fGpu = GrMtlTrampoline::MakeGpu(backendContext, options, direct.get());
1169 if (!direct->init()) {
1170 return nullptr;
1171 }
1172
1173 return direct;
1174 }
1175
1176 // deprecated
MakeMetal(void * device,void * queue)1177 sk_sp<GrDirectContext> GrDirectContext::MakeMetal(void* device, void* queue) {
1178 GrContextOptions defaultOptions;
1179 return MakeMetal(device, queue, defaultOptions);
1180 }
1181
1182 // deprecated
1183 // remove include/gpu/mtl/GrMtlBackendContext.h, above, when removed
MakeMetal(void * device,void * queue,const GrContextOptions & options)1184 sk_sp<GrDirectContext> GrDirectContext::MakeMetal(void* device, void* queue,
1185 const GrContextOptions& options) {
1186 sk_sp<GrDirectContext> direct(new GrDirectContext(GrBackendApi::kMetal, options));
1187 GrMtlBackendContext backendContext = {};
1188 backendContext.fDevice.reset(device);
1189 backendContext.fQueue.reset(queue);
1190
1191 return GrDirectContext::MakeMetal(backendContext, options);
1192 }
1193 #endif
1194
1195 #ifdef SK_DIRECT3D
1196 /*************************************************************************************************/
MakeDirect3D(const GrD3DBackendContext & backendContext)1197 sk_sp<GrDirectContext> GrDirectContext::MakeDirect3D(const GrD3DBackendContext& backendContext) {
1198 GrContextOptions defaultOptions;
1199 return MakeDirect3D(backendContext, defaultOptions);
1200 }
1201
MakeDirect3D(const GrD3DBackendContext & backendContext,const GrContextOptions & options)1202 sk_sp<GrDirectContext> GrDirectContext::MakeDirect3D(const GrD3DBackendContext& backendContext,
1203 const GrContextOptions& options) {
1204 sk_sp<GrDirectContext> direct(new GrDirectContext(GrBackendApi::kDirect3D, options));
1205
1206 direct->fGpu = GrD3DGpu::Make(backendContext, options, direct.get());
1207 if (!direct->init()) {
1208 return nullptr;
1209 }
1210
1211 return direct;
1212 }
1213 #endif
1214
1215 #ifdef SK_DAWN
1216 /*************************************************************************************************/
MakeDawn(const wgpu::Device & device)1217 sk_sp<GrDirectContext> GrDirectContext::MakeDawn(const wgpu::Device& device) {
1218 GrContextOptions defaultOptions;
1219 return MakeDawn(device, defaultOptions);
1220 }
1221
MakeDawn(const wgpu::Device & device,const GrContextOptions & options)1222 sk_sp<GrDirectContext> GrDirectContext::MakeDawn(const wgpu::Device& device,
1223 const GrContextOptions& options) {
1224 sk_sp<GrDirectContext> direct(new GrDirectContext(GrBackendApi::kDawn, options));
1225
1226 direct->fGpu = GrDawnGpu::Make(device, options, direct.get());
1227 if (!direct->init()) {
1228 return nullptr;
1229 }
1230
1231 return direct;
1232 }
1233
1234 #endif
1235