2 * Copyright 2012 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "src/image/SkSurface_Gpu.h"
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkCapabilities.h"
12 #include "include/core/SkDeferredDisplayList.h"
13 #include "include/core/SkSurfaceCharacterization.h"
14 #include "include/gpu/GrBackendSurface.h"
15 #include "include/gpu/GrDirectContext.h"
16 #include "include/gpu/GrRecordingContext.h"
17 #include "src/core/SkImagePriv.h"
18 #include "src/core/SkSurfacePriv.h"
19 #include "src/gpu/ganesh/BaseDevice.h"
20 #include "src/gpu/ganesh/GrAHardwareBufferUtils_impl.h"
21 #include "src/gpu/ganesh/GrCaps.h"
22 #include "src/gpu/ganesh/GrContextThreadSafeProxyPriv.h"
23 #include "src/gpu/ganesh/GrDirectContextPriv.h"
24 #include "src/gpu/ganesh/GrProxyProvider.h"
25 #include "src/gpu/ganesh/GrRecordingContextPriv.h"
26 #include "src/gpu/ganesh/GrRenderTarget.h"
27 #include "src/gpu/ganesh/GrTexture.h"
28 #include "src/image/SkImage_Base.h"
29 #include "src/image/SkImage_Gpu.h"
30 #include "src/image/SkSurface_Base.h"
34 SkSurface_Gpu::SkSurface_Gpu(sk_sp<skgpu::BaseDevice> device)
35 : INHERITED(device->width(), device->height(), &device->surfaceProps())
36 , fDevice(std::move(device)) {
37 SkASSERT(fDevice->targetProxy()->priv().isExact());
40 SkSurface_Gpu::~SkSurface_Gpu() {
43 GrRecordingContext* SkSurface_Gpu::onGetRecordingContext() {
44 return fDevice->recordingContext();
47 skgpu::BaseDevice* SkSurface_Gpu::getDevice() {
51 static GrRenderTarget* prepare_rt_for_external_access(SkSurface_Gpu* surface,
52 SkSurface::BackendHandleAccess access) {
53 auto dContext = surface->recordingContext()->asDirectContext();
57 if (dContext->abandoned()) {
62 case SkSurface::kFlushRead_BackendHandleAccess:
64 case SkSurface::kFlushWrite_BackendHandleAccess:
65 case SkSurface::kDiscardWrite_BackendHandleAccess:
66 // for now we don't special-case on Discard, but we may in the future.
67 surface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode);
71 dContext->priv().flushSurface(surface->getDevice()->targetProxy());
73 // Grab the render target *after* firing notifications, as it may get switched if CoW kicks in.
74 return surface->getDevice()->targetProxy()->peekRenderTarget();
77 GrBackendTexture SkSurface_Gpu::onGetBackendTexture(BackendHandleAccess access) {
78 GrRenderTarget* rt = prepare_rt_for_external_access(this, access);
80 return GrBackendTexture(); // invalid
82 GrTexture* texture = rt->asTexture();
84 return texture->getBackendTexture();
86 return GrBackendTexture(); // invalid
89 GrBackendRenderTarget SkSurface_Gpu::onGetBackendRenderTarget(BackendHandleAccess access) {
90 GrRenderTarget* rt = prepare_rt_for_external_access(this, access);
92 return GrBackendRenderTarget(); // invalid
95 return rt->getBackendRenderTarget();
98 SkCanvas* SkSurface_Gpu::onNewCanvas() { return new SkCanvas(fDevice); }
100 sk_sp<SkSurface> SkSurface_Gpu::onNewSurface(const SkImageInfo& info) {
101 GrSurfaceProxyView targetView = fDevice->readSurfaceView();
102 int sampleCount = targetView.asRenderTargetProxy()->numSamples();
103 GrSurfaceOrigin origin = targetView.origin();
104 // TODO: Make caller specify this (change virtual signature of onNewSurface).
105 static const SkBudgeted kBudgeted = SkBudgeted::kNo;
106 return SkSurface::MakeRenderTarget(fDevice->recordingContext(), kBudgeted, info, sampleCount,
107 origin, &this->props());
110 sk_sp<SkImage> SkSurface_Gpu::onNewImageSnapshot(const SkIRect* subset) {
111 GrRenderTargetProxy* rtp = fDevice->targetProxy();
116 auto rContext = fDevice->recordingContext();
118 GrSurfaceProxyView srcView = fDevice->readSurfaceView();
120 SkBudgeted budgeted = rtp->isBudgeted();
122 if (subset || !srcView.asTextureProxy() || rtp->refsWrappedObjects()) {
123 // If the original render target is a buffer originally created by the client, then we don't
124 // want to ever retarget the SkSurface at another buffer we create. If the source is a
125 // texture (and the image is not subsetted) we make a dual-proxied SkImage that will
126 // attempt to share the backing store until the surface writes to the shared backing store
127 // at which point it uses a copy.
128 if (!subset && srcView.asTextureProxy()) {
129 return SkImage_Gpu::MakeWithVolatileSrc(sk_ref_sp(rContext),
131 fDevice->imageInfo().colorInfo());
133 auto rect = subset ? *subset : SkIRect::MakeSize(srcView.dimensions());
134 GrMipmapped mipmapped = srcView.mipmapped();
135 srcView = GrSurfaceProxyView::Copy(rContext, std::move(srcView), mipmapped, rect,
136 SkBackingFit::kExact, budgeted);
139 const SkImageInfo info = fDevice->imageInfo();
140 if (!srcView.asTextureProxy()) {
143 // The surfaceDrawContext coming out of SkGpuDevice should always be exact and the
144 // above copy creates a kExact surfaceContext.
145 SkASSERT(srcView.proxy()->priv().isExact());
146 return sk_make_sp<SkImage_Gpu>(sk_ref_sp(rContext),
147 kNeedNewImageUniqueID,
152 void SkSurface_Gpu::onWritePixels(const SkPixmap& src, int x, int y) {
153 fDevice->writePixels(src, x, y);
156 void SkSurface_Gpu::onAsyncRescaleAndReadPixels(const SkImageInfo& info,
157 const SkIRect& srcRect,
158 RescaleGamma rescaleGamma,
159 RescaleMode rescaleMode,
160 ReadPixelsCallback callback,
161 ReadPixelsContext context) {
162 fDevice->asyncRescaleAndReadPixels(info,
170 void SkSurface_Gpu::onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
171 sk_sp<SkColorSpace> dstColorSpace,
172 const SkIRect& srcRect,
173 const SkISize& dstSize,
174 RescaleGamma rescaleGamma,
175 RescaleMode rescaleMode,
176 ReadPixelsCallback callback,
177 ReadPixelsContext context) {
178 fDevice->asyncRescaleAndReadPixelsYUV420(yuvColorSpace,
179 std::move(dstColorSpace),
188 // Create a new render target and, if necessary, copy the contents of the old
189 // render target into it. Note that this flushes the SkGpuDevice but
190 // doesn't force an OpenGL flush.
191 bool SkSurface_Gpu::onCopyOnWrite(ContentChangeMode mode) {
192 GrSurfaceProxyView readSurfaceView = fDevice->readSurfaceView();
194 // are we sharing our backing proxy with the image? Note this call should never create a new
195 // image because onCopyOnWrite is only called when there is a cached image.
196 sk_sp<SkImage> image = this->refCachedImage();
199 if (static_cast<SkImage_Gpu*>(image.get())->surfaceMustCopyOnWrite(readSurfaceView.proxy())) {
200 if (!fDevice->replaceBackingProxy(mode)) {
203 } else if (kDiscard_ContentChangeMode == mode) {
204 this->SkSurface_Gpu::onDiscard();
209 void SkSurface_Gpu::onDiscard() { fDevice->discard(); }
211 void SkSurface_Gpu::onResolveMSAA() { fDevice->resolveMSAA(); }
213 GrSemaphoresSubmitted SkSurface_Gpu::onFlush(BackendSurfaceAccess access, const GrFlushInfo& info,
214 const GrBackendSurfaceMutableState* newState) {
216 auto dContext = fDevice->recordingContext()->asDirectContext();
218 return GrSemaphoresSubmitted::kNo;
221 GrRenderTargetProxy* rtp = fDevice->targetProxy();
223 return dContext->priv().flushSurface(rtp, access, info, newState);
226 bool SkSurface_Gpu::onWait(int numSemaphores, const GrBackendSemaphore* waitSemaphores,
227 bool deleteSemaphoresAfterWait) {
228 return fDevice->wait(numSemaphores, waitSemaphores, deleteSemaphoresAfterWait);
231 bool SkSurface_Gpu::onCharacterize(SkSurfaceCharacterization* characterization) const {
232 auto direct = fDevice->recordingContext()->asDirectContext();
237 SkImageInfo ii = fDevice->imageInfo();
238 if (ii.colorType() == kUnknown_SkColorType) {
242 GrSurfaceProxyView readSurfaceView = fDevice->readSurfaceView();
243 size_t maxResourceBytes = direct->getResourceCacheLimit();
245 bool mipmapped = readSurfaceView.asTextureProxy()
246 ? GrMipmapped::kYes == readSurfaceView.asTextureProxy()->mipmapped()
249 bool usesGLFBO0 = readSurfaceView.asRenderTargetProxy()->glRTFBOIDIs0();
250 // We should never get in the situation where we have a texture render target that is also
252 SkASSERT(!usesGLFBO0 || !SkToBool(readSurfaceView.asTextureProxy()));
254 bool vkRTSupportsInputAttachment =
255 readSurfaceView.asRenderTargetProxy()->supportsVkInputAttachment();
257 GrBackendFormat format = readSurfaceView.proxy()->backendFormat();
258 int numSamples = readSurfaceView.asRenderTargetProxy()->numSamples();
259 GrProtected isProtected = readSurfaceView.asRenderTargetProxy()->isProtected();
261 characterization->set(
262 direct->threadSafeProxy(),
266 readSurfaceView.origin(),
268 SkSurfaceCharacterization::Textureable(SkToBool(readSurfaceView.asTextureProxy())),
269 SkSurfaceCharacterization::MipMapped(mipmapped),
270 SkSurfaceCharacterization::UsesGLFBO0(usesGLFBO0),
271 SkSurfaceCharacterization::VkRTSupportsInputAttachment(vkRTSupportsInputAttachment),
272 SkSurfaceCharacterization::VulkanSecondaryCBCompatible(false),
278 void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
279 const SkSamplingOptions& sampling, const SkPaint* paint) {
280 // If the dst is also GPU we try to not force a new image snapshot (by calling the base class
281 // onDraw) since that may not always perform the copy-on-write optimization.
283 auto surfaceContext = fDevice->recordingContext();
284 auto canvasContext = GrAsDirectContext(canvas->recordingContext());
285 if (!canvasContext) {
288 if (canvasContext->priv().contextID() != surfaceContext->priv().contextID()) {
291 GrSurfaceProxyView srcView = fDevice->readSurfaceView();
292 if (!srcView.asTextureProxyRef()) {
295 // Possibly we could skip making an image here if SkGpuDevice exposed a lower level way
296 // of drawing a texture proxy.
297 const SkImageInfo info = fDevice->imageInfo();
298 sk_sp<SkImage> image = sk_make_sp<SkImage_Gpu>(sk_ref_sp(canvasContext),
299 kNeedNewImageUniqueID,
302 canvas->drawImage(image.get(), x, y, sampling, paint);
306 INHERITED::onDraw(canvas, x, y, sampling, paint);
310 bool SkSurface_Gpu::onIsCompatible(const SkSurfaceCharacterization& characterization) const {
311 auto direct = fDevice->recordingContext()->asDirectContext();
316 if (!characterization.isValid()) {
320 if (characterization.vulkanSecondaryCBCompatible()) {
324 SkImageInfo ii = fDevice->imageInfo();
325 if (ii.colorType() == kUnknown_SkColorType) {
329 GrSurfaceProxyView targetView = fDevice->readSurfaceView();
330 // As long as the current state if the context allows for greater or equal resources,
331 // we allow the DDL to be replayed.
332 // DDL TODO: should we just remove the resource check and ignore the cache limits on playback?
333 size_t maxResourceBytes = direct->getResourceCacheLimit();
335 if (characterization.isTextureable()) {
336 if (!targetView.asTextureProxy()) {
337 // If the characterization was textureable we require the replay dest to also be
338 // textureable. If the characterized surface wasn't textureable we allow the replay
339 // dest to be textureable.
343 if (characterization.isMipMapped() &&
344 GrMipmapped::kNo == targetView.asTextureProxy()->mipmapped()) {
345 // Fail if the DDL's surface was mipmapped but the replay surface is not.
346 // Allow drawing to proceed if the DDL was not mipmapped but the replay surface is.
351 if (characterization.usesGLFBO0() != targetView.asRenderTargetProxy()->glRTFBOIDIs0()) {
352 // FBO0-ness effects how MSAA and window rectangles work. If the characterization was
353 // tagged as FBO0 it would never have been allowed to use window rectangles. If MSAA
354 // was also never used then a DDL recorded with this characterization should be replayable
355 // on a non-FBO0 surface.
356 if (!characterization.usesGLFBO0() || characterization.sampleCount() > 1) {
361 GrBackendFormat format = targetView.asRenderTargetProxy()->backendFormat();
362 int numSamples = targetView.asRenderTargetProxy()->numSamples();
363 GrProtected isProtected = targetView.proxy()->isProtected();
365 return characterization.contextInfo() &&
366 characterization.contextInfo()->priv().matches(direct) &&
367 characterization.cacheMaxResourceBytes() <= maxResourceBytes &&
368 characterization.origin() == targetView.origin() &&
369 characterization.backendFormat() == format &&
370 characterization.width() == ii.width() &&
371 characterization.height() == ii.height() &&
372 characterization.colorType() == ii.colorType() &&
373 characterization.sampleCount() == numSamples &&
374 SkColorSpace::Equals(characterization.colorSpace(), ii.colorInfo().colorSpace()) &&
375 characterization.isProtected() == isProtected &&
376 characterization.surfaceProps() == fDevice->surfaceProps();
379 bool SkSurface_Gpu::onDraw(sk_sp<const SkDeferredDisplayList> ddl, SkIPoint offset) {
380 if (!ddl || !this->isCompatible(ddl->characterization())) {
384 auto direct = fDevice->recordingContext()->asDirectContext();
389 GrSurfaceProxyView view = fDevice->readSurfaceView();
391 direct->priv().createDDLTask(std::move(ddl), view.asRenderTargetProxyRef(), offset);
395 sk_sp<const SkCapabilities> SkSurface_Gpu::onCapabilities() {
396 return fDevice->recordingContext()->skCapabilities();
399 ///////////////////////////////////////////////////////////////////////////////
401 sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrRecordingContext* rContext,
402 const SkSurfaceCharacterization& c,
403 SkBudgeted budgeted) {
404 if (!rContext || !c.isValid()) {
408 if (c.usesGLFBO0()) {
409 // If we are making the surface we will never use FBO0.
413 if (c.vulkanSecondaryCBCompatible()) {
417 auto device = rContext->priv().createDevice(budgeted, c.imageInfo(), SkBackingFit::kExact,
418 c.sampleCount(), GrMipmapped(c.isMipMapped()),
419 c.isProtected(), c.origin(), c.surfaceProps(),
420 skgpu::BaseDevice::InitContents::kClear);
425 sk_sp<SkSurface> result = sk_make_sp<SkSurface_Gpu>(std::move(device));
428 SkASSERT(result->isCompatible(c));
435 static bool validate_backend_texture(const GrCaps* caps, const GrBackendTexture& tex,
436 int sampleCnt, GrColorType grCT,
438 if (!tex.isValid()) {
442 GrBackendFormat backendFormat = tex.getBackendFormat();
443 if (!backendFormat.isValid()) {
447 if (!caps->areColorTypeAndFormatCompatible(grCT, backendFormat)) {
451 if (!caps->isFormatAsColorTypeRenderable(grCT, backendFormat, sampleCnt)) {
455 if (texturable && !caps->isFormatTexturable(backendFormat, tex.textureType())) {
462 sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrRecordingContext* rContext, SkBudgeted budgeted,
463 const SkImageInfo& info, int sampleCount,
464 GrSurfaceOrigin origin, const SkSurfaceProps* props,
465 bool shouldCreateWithMips) {
469 sampleCount = std::max(1, sampleCount);
470 GrMipmapped mipmapped = shouldCreateWithMips ? GrMipmapped::kYes : GrMipmapped::kNo;
472 if (!rContext->priv().caps()->mipmapSupport()) {
473 mipmapped = GrMipmapped::kNo;
476 auto device = rContext->priv().createDevice(budgeted, info, SkBackingFit::kExact,
477 sampleCount, mipmapped, GrProtected::kNo, origin,
478 SkSurfacePropsCopyOrDefault(props),
479 skgpu::BaseDevice::InitContents::kClear);
483 return sk_make_sp<SkSurface_Gpu>(std::move(device));
486 sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrRecordingContext* rContext,
487 const GrBackendTexture& tex,
488 GrSurfaceOrigin origin,
490 SkColorType colorType,
491 sk_sp<SkColorSpace> colorSpace,
492 const SkSurfaceProps* props,
493 SkSurface::TextureReleaseProc textureReleaseProc,
494 SkSurface::ReleaseContext releaseContext) {
495 auto releaseHelper = skgpu::RefCntedCallback::Make(textureReleaseProc, releaseContext);
500 sampleCnt = std::max(1, sampleCnt);
502 GrColorType grColorType = SkColorTypeToGrColorType(colorType);
503 if (grColorType == GrColorType::kUnknown) {
507 if (!validate_backend_texture(rContext->priv().caps(), tex, sampleCnt, grColorType, true)) {
511 sk_sp<GrTextureProxy> proxy(rContext->priv().proxyProvider()->wrapRenderableBackendTexture(
512 tex, sampleCnt, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
513 std::move(releaseHelper)));
518 auto device = rContext->priv().createDevice(grColorType, std::move(proxy),
519 std::move(colorSpace), origin,
520 SkSurfacePropsCopyOrDefault(props),
521 skgpu::BaseDevice::InitContents::kUninit);
526 return sk_make_sp<SkSurface_Gpu>(std::move(device));
529 bool SkSurface_Gpu::onReplaceBackendTexture(const GrBackendTexture& backendTexture,
530 GrSurfaceOrigin origin,
531 ContentChangeMode mode,
532 TextureReleaseProc releaseProc,
533 ReleaseContext releaseContext) {
534 auto releaseHelper = skgpu::RefCntedCallback::Make(releaseProc, releaseContext);
536 auto rContext = fDevice->recordingContext();
537 if (rContext->abandoned()) {
540 if (!backendTexture.isValid()) {
543 if (backendTexture.width() != this->width() || backendTexture.height() != this->height()) {
546 auto* oldRTP = fDevice->targetProxy();
547 auto oldProxy = sk_ref_sp(oldRTP->asTextureProxy());
551 auto* oldTexture = oldProxy->peekTexture();
555 if (!oldTexture->resourcePriv().refsWrappedObjects()) {
558 if (oldTexture->backendFormat() != backendTexture.getBackendFormat()) {
561 if (oldTexture->getBackendTexture().isSameTexture(backendTexture)) {
564 SkASSERT(oldTexture->asRenderTarget());
565 int sampleCnt = oldTexture->asRenderTarget()->numSamples();
566 GrColorType grColorType = SkColorTypeToGrColorType(this->getCanvas()->imageInfo().colorType());
567 if (!validate_backend_texture(rContext->priv().caps(), backendTexture,
568 sampleCnt, grColorType, true)) {
572 sk_sp<SkColorSpace> colorSpace = fDevice->imageInfo().refColorSpace();
574 SkASSERT(sampleCnt > 0);
575 sk_sp<GrTextureProxy> proxy(rContext->priv().proxyProvider()->wrapRenderableBackendTexture(
576 backendTexture, sampleCnt, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
577 std::move(releaseHelper)));
582 return fDevice->replaceBackingProxy(mode, sk_ref_sp(proxy->asRenderTargetProxy()), grColorType,
583 std::move(colorSpace), origin, this->props());
586 bool validate_backend_render_target(const GrCaps* caps, const GrBackendRenderTarget& rt,
588 if (!caps->areColorTypeAndFormatCompatible(grCT, rt.getBackendFormat())) {
592 if (!caps->isFormatAsColorTypeRenderable(grCT, rt.getBackendFormat(), rt.sampleCnt())) {
596 // We require the stencil bits to be either 0, 8, or 16.
597 int stencilBits = rt.stencilBits();
598 if (stencilBits != 0 && stencilBits != 8 && stencilBits != 16) {
605 sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrRecordingContext* rContext,
606 const GrBackendRenderTarget& rt,
607 GrSurfaceOrigin origin,
608 SkColorType colorType,
609 sk_sp<SkColorSpace> colorSpace,
610 const SkSurfaceProps* props,
611 SkSurface::RenderTargetReleaseProc relProc,
612 SkSurface::ReleaseContext releaseContext) {
613 auto releaseHelper = skgpu::RefCntedCallback::Make(relProc, releaseContext);
619 GrColorType grColorType = SkColorTypeToGrColorType(colorType);
620 if (grColorType == GrColorType::kUnknown) {
624 if (!validate_backend_render_target(rContext->priv().caps(), rt, grColorType)) {
628 auto proxyProvider = rContext->priv().proxyProvider();
629 auto proxy = proxyProvider->wrapBackendRenderTarget(rt, std::move(releaseHelper));
634 auto device = rContext->priv().createDevice(grColorType, std::move(proxy),
635 std::move(colorSpace), origin,
636 SkSurfacePropsCopyOrDefault(props),
637 skgpu::BaseDevice::InitContents::kUninit);
642 return sk_make_sp<SkSurface_Gpu>(std::move(device));
645 #if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
646 sk_sp<SkSurface> SkSurface::MakeFromAHardwareBuffer(GrDirectContext* dContext,
647 AHardwareBuffer* hardwareBuffer,
648 GrSurfaceOrigin origin,
649 sk_sp<SkColorSpace> colorSpace,
650 const SkSurfaceProps* surfaceProps
651 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
655 AHardwareBuffer_Desc bufferDesc;
656 AHardwareBuffer_describe(hardwareBuffer, &bufferDesc);
658 if (!SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT)) {
662 bool isTextureable = SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE);
664 GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(dContext,
668 if (!backendFormat.isValid()) {
673 GrAHardwareBufferUtils::DeleteImageProc deleteImageProc = nullptr;
674 GrAHardwareBufferUtils::UpdateImageProc updateImageProc = nullptr;
675 GrAHardwareBufferUtils::TexImageCtx deleteImageCtx = nullptr;
677 bool isProtectedContent =
678 SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
680 bool fromWindowLocal = false;
681 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
682 fromWindowLocal = fromWindow;
685 GrBackendTexture backendTexture =
686 GrAHardwareBufferUtils::MakeBackendTexture(dContext,
697 if (!backendTexture.isValid()) {
701 SkColorType colorType =
702 GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(bufferDesc.format);
704 sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(dContext, backendTexture,
705 origin, 0, colorType, std::move(colorSpace), surfaceProps, deleteImageProc,
709 SkASSERT(deleteImageProc);
710 deleteImageProc(deleteImageCtx);
720 void SkSurface::flushAndSubmit(bool syncCpu) {
721 this->flush(BackendSurfaceAccess::kNoAccess, GrFlushInfo());
723 auto direct = GrAsDirectContext(this->recordingContext());
725 direct->submit(syncCpu);