Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / src / image / SkSurface_Gpu.cpp
1 /*
2  * Copyright 2012 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 "src/image/SkSurface_Gpu.h"
9
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"
31
32 #if SK_SUPPORT_GPU
33
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());
38 }
39
40 SkSurface_Gpu::~SkSurface_Gpu() {
41 }
42
43 GrRecordingContext* SkSurface_Gpu::onGetRecordingContext() {
44     return fDevice->recordingContext();
45 }
46
47 skgpu::BaseDevice* SkSurface_Gpu::getDevice() {
48     return fDevice.get();
49 }
50
51 static GrRenderTarget* prepare_rt_for_external_access(SkSurface_Gpu* surface,
52                                                       SkSurface::BackendHandleAccess access) {
53     auto dContext = surface->recordingContext()->asDirectContext();
54     if (!dContext) {
55         return nullptr;
56     }
57     if (dContext->abandoned()) {
58         return nullptr;
59     }
60
61     switch (access) {
62         case SkSurface::kFlushRead_BackendHandleAccess:
63             break;
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);
68             break;
69     }
70
71     dContext->priv().flushSurface(surface->getDevice()->targetProxy());
72
73     // Grab the render target *after* firing notifications, as it may get switched if CoW kicks in.
74     return surface->getDevice()->targetProxy()->peekRenderTarget();
75 }
76
77 GrBackendTexture SkSurface_Gpu::onGetBackendTexture(BackendHandleAccess access) {
78     GrRenderTarget* rt = prepare_rt_for_external_access(this, access);
79     if (!rt) {
80         return GrBackendTexture(); // invalid
81     }
82     GrTexture* texture = rt->asTexture();
83     if (texture) {
84         return texture->getBackendTexture();
85     }
86     return GrBackendTexture(); // invalid
87 }
88
89 GrBackendRenderTarget SkSurface_Gpu::onGetBackendRenderTarget(BackendHandleAccess access) {
90     GrRenderTarget* rt = prepare_rt_for_external_access(this, access);
91     if (!rt) {
92         return GrBackendRenderTarget(); // invalid
93     }
94
95     return rt->getBackendRenderTarget();
96 }
97
98 SkCanvas* SkSurface_Gpu::onNewCanvas() { return new SkCanvas(fDevice); }
99
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());
108 }
109
110 sk_sp<SkImage> SkSurface_Gpu::onNewImageSnapshot(const SkIRect* subset) {
111     GrRenderTargetProxy* rtp = fDevice->targetProxy();
112     if (!rtp) {
113         return nullptr;
114     }
115
116     auto rContext = fDevice->recordingContext();
117
118     GrSurfaceProxyView srcView = fDevice->readSurfaceView();
119
120     SkBudgeted budgeted = rtp->isBudgeted();
121
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),
130                                                     srcView,
131                                                     fDevice->imageInfo().colorInfo());
132         }
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);
137     }
138
139     const SkImageInfo info = fDevice->imageInfo();
140     if (!srcView.asTextureProxy()) {
141         return nullptr;
142     }
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,
148                                    std::move(srcView),
149                                    info.colorInfo());
150 }
151
152 void SkSurface_Gpu::onWritePixels(const SkPixmap& src, int x, int y) {
153     fDevice->writePixels(src, x, y);
154 }
155
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,
163                                        srcRect,
164                                        rescaleGamma,
165                                        rescaleMode,
166                                        callback,
167                                        context);
168 }
169
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),
180                                              srcRect,
181                                              dstSize,
182                                              rescaleGamma,
183                                              rescaleMode,
184                                              callback,
185                                              context);
186 }
187
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();
193
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();
197     SkASSERT(image);
198
199     if (static_cast<SkImage_Gpu*>(image.get())->surfaceMustCopyOnWrite(readSurfaceView.proxy())) {
200         if (!fDevice->replaceBackingProxy(mode)) {
201             return false;
202         }
203     } else if (kDiscard_ContentChangeMode == mode) {
204         this->SkSurface_Gpu::onDiscard();
205     }
206     return true;
207 }
208
209 void SkSurface_Gpu::onDiscard() { fDevice->discard(); }
210
211 void SkSurface_Gpu::onResolveMSAA() { fDevice->resolveMSAA(); }
212
213 GrSemaphoresSubmitted SkSurface_Gpu::onFlush(BackendSurfaceAccess access, const GrFlushInfo& info,
214                                              const GrBackendSurfaceMutableState* newState) {
215
216     auto dContext = fDevice->recordingContext()->asDirectContext();
217     if (!dContext) {
218         return GrSemaphoresSubmitted::kNo;
219     }
220
221     GrRenderTargetProxy* rtp = fDevice->targetProxy();
222
223     return dContext->priv().flushSurface(rtp, access, info, newState);
224 }
225
226 bool SkSurface_Gpu::onWait(int numSemaphores, const GrBackendSemaphore* waitSemaphores,
227                            bool deleteSemaphoresAfterWait) {
228     return fDevice->wait(numSemaphores, waitSemaphores, deleteSemaphoresAfterWait);
229 }
230
231 bool SkSurface_Gpu::onCharacterize(SkSurfaceCharacterization* characterization) const {
232     auto direct = fDevice->recordingContext()->asDirectContext();
233     if (!direct) {
234         return false;
235     }
236
237     SkImageInfo ii = fDevice->imageInfo();
238     if (ii.colorType() == kUnknown_SkColorType) {
239         return false;
240     }
241
242     GrSurfaceProxyView readSurfaceView = fDevice->readSurfaceView();
243     size_t maxResourceBytes = direct->getResourceCacheLimit();
244
245     bool mipmapped = readSurfaceView.asTextureProxy()
246                             ? GrMipmapped::kYes == readSurfaceView.asTextureProxy()->mipmapped()
247                             : false;
248
249     bool usesGLFBO0 = readSurfaceView.asRenderTargetProxy()->glRTFBOIDIs0();
250     // We should never get in the situation where we have a texture render target that is also
251     // backend by FBO 0.
252     SkASSERT(!usesGLFBO0 || !SkToBool(readSurfaceView.asTextureProxy()));
253
254     bool vkRTSupportsInputAttachment =
255                             readSurfaceView.asRenderTargetProxy()->supportsVkInputAttachment();
256
257     GrBackendFormat format = readSurfaceView.proxy()->backendFormat();
258     int numSamples = readSurfaceView.asRenderTargetProxy()->numSamples();
259     GrProtected isProtected = readSurfaceView.asRenderTargetProxy()->isProtected();
260
261     characterization->set(
262             direct->threadSafeProxy(),
263             maxResourceBytes,
264             ii,
265             format,
266             readSurfaceView.origin(),
267             numSamples,
268             SkSurfaceCharacterization::Textureable(SkToBool(readSurfaceView.asTextureProxy())),
269             SkSurfaceCharacterization::MipMapped(mipmapped),
270             SkSurfaceCharacterization::UsesGLFBO0(usesGLFBO0),
271             SkSurfaceCharacterization::VkRTSupportsInputAttachment(vkRTSupportsInputAttachment),
272             SkSurfaceCharacterization::VulkanSecondaryCBCompatible(false),
273             isProtected,
274             this->props());
275     return true;
276 }
277
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.
282     auto tryDraw = [&] {
283         auto surfaceContext = fDevice->recordingContext();
284         auto canvasContext = GrAsDirectContext(canvas->recordingContext());
285         if (!canvasContext) {
286             return false;
287         }
288         if (canvasContext->priv().contextID() != surfaceContext->priv().contextID()) {
289             return false;
290         }
291         GrSurfaceProxyView srcView = fDevice->readSurfaceView();
292         if (!srcView.asTextureProxyRef()) {
293             return false;
294         }
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,
300                                                        std::move(srcView),
301                                                        info.colorInfo());
302         canvas->drawImage(image.get(), x, y, sampling, paint);
303         return true;
304     };
305     if (!tryDraw()) {
306         INHERITED::onDraw(canvas, x, y, sampling, paint);
307     }
308 }
309
310 bool SkSurface_Gpu::onIsCompatible(const SkSurfaceCharacterization& characterization) const {
311     auto direct = fDevice->recordingContext()->asDirectContext();
312     if (!direct) {
313         return false;
314     }
315
316     if (!characterization.isValid()) {
317         return false;
318     }
319
320     if (characterization.vulkanSecondaryCBCompatible()) {
321         return false;
322     }
323
324     SkImageInfo ii = fDevice->imageInfo();
325     if (ii.colorType() == kUnknown_SkColorType) {
326         return false;
327     }
328
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();
334
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.
340             return false;
341         }
342
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.
347             return false;
348         }
349     }
350
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) {
357             return false;
358         }
359     }
360
361     GrBackendFormat format = targetView.asRenderTargetProxy()->backendFormat();
362     int numSamples = targetView.asRenderTargetProxy()->numSamples();
363     GrProtected isProtected = targetView.proxy()->isProtected();
364
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();
377 }
378
379 bool SkSurface_Gpu::onDraw(sk_sp<const SkDeferredDisplayList> ddl, SkIPoint offset) {
380     if (!ddl || !this->isCompatible(ddl->characterization())) {
381         return false;
382     }
383
384     auto direct = fDevice->recordingContext()->asDirectContext();
385     if (!direct) {
386         return false;
387     }
388
389     GrSurfaceProxyView view = fDevice->readSurfaceView();
390
391     direct->priv().createDDLTask(std::move(ddl), view.asRenderTargetProxyRef(), offset);
392     return true;
393 }
394
395 sk_sp<const SkCapabilities> SkSurface_Gpu::onCapabilities() {
396     return fDevice->recordingContext()->skCapabilities();
397 }
398
399 ///////////////////////////////////////////////////////////////////////////////
400
401 sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrRecordingContext* rContext,
402                                              const SkSurfaceCharacterization& c,
403                                              SkBudgeted budgeted) {
404     if (!rContext || !c.isValid()) {
405         return nullptr;
406     }
407
408     if (c.usesGLFBO0()) {
409         // If we are making the surface we will never use FBO0.
410         return nullptr;
411     }
412
413     if (c.vulkanSecondaryCBCompatible()) {
414         return nullptr;
415     }
416
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);
421     if (!device) {
422         return nullptr;
423     }
424
425     sk_sp<SkSurface> result = sk_make_sp<SkSurface_Gpu>(std::move(device));
426 #ifdef SK_DEBUG
427     if (result) {
428         SkASSERT(result->isCompatible(c));
429     }
430 #endif
431
432     return result;
433 }
434
435 static bool validate_backend_texture(const GrCaps* caps, const GrBackendTexture& tex,
436                                      int sampleCnt, GrColorType grCT,
437                                      bool texturable) {
438     if (!tex.isValid()) {
439         return false;
440     }
441
442     GrBackendFormat backendFormat = tex.getBackendFormat();
443     if (!backendFormat.isValid()) {
444         return false;
445     }
446
447     if (!caps->areColorTypeAndFormatCompatible(grCT, backendFormat)) {
448         return false;
449     }
450
451     if (!caps->isFormatAsColorTypeRenderable(grCT, backendFormat, sampleCnt)) {
452         return false;
453     }
454
455     if (texturable && !caps->isFormatTexturable(backendFormat, tex.textureType())) {
456         return false;
457     }
458
459     return true;
460 }
461
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) {
466     if (!rContext) {
467         return nullptr;
468     }
469     sampleCount = std::max(1, sampleCount);
470     GrMipmapped mipmapped = shouldCreateWithMips ? GrMipmapped::kYes : GrMipmapped::kNo;
471
472     if (!rContext->priv().caps()->mipmapSupport()) {
473         mipmapped = GrMipmapped::kNo;
474     }
475
476     auto device = rContext->priv().createDevice(budgeted, info, SkBackingFit::kExact,
477                                                 sampleCount, mipmapped, GrProtected::kNo, origin,
478                                                 SkSurfacePropsCopyOrDefault(props),
479                                                 skgpu::BaseDevice::InitContents::kClear);
480     if (!device) {
481         return nullptr;
482     }
483     return sk_make_sp<SkSurface_Gpu>(std::move(device));
484 }
485
486 sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrRecordingContext* rContext,
487                                                    const GrBackendTexture& tex,
488                                                    GrSurfaceOrigin origin,
489                                                    int sampleCnt,
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);
496
497     if (!rContext) {
498         return nullptr;
499     }
500     sampleCnt = std::max(1, sampleCnt);
501
502     GrColorType grColorType = SkColorTypeToGrColorType(colorType);
503     if (grColorType == GrColorType::kUnknown) {
504         return nullptr;
505     }
506
507     if (!validate_backend_texture(rContext->priv().caps(), tex, sampleCnt, grColorType, true)) {
508         return nullptr;
509     }
510
511     sk_sp<GrTextureProxy> proxy(rContext->priv().proxyProvider()->wrapRenderableBackendTexture(
512             tex, sampleCnt, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
513             std::move(releaseHelper)));
514     if (!proxy) {
515         return nullptr;
516     }
517
518     auto device = rContext->priv().createDevice(grColorType, std::move(proxy),
519                                                 std::move(colorSpace), origin,
520                                                 SkSurfacePropsCopyOrDefault(props),
521                                                 skgpu::BaseDevice::InitContents::kUninit);
522     if (!device) {
523         return nullptr;
524     }
525
526     return sk_make_sp<SkSurface_Gpu>(std::move(device));
527 }
528
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);
535
536     auto rContext = fDevice->recordingContext();
537     if (rContext->abandoned()) {
538         return false;
539     }
540     if (!backendTexture.isValid()) {
541         return false;
542     }
543     if (backendTexture.width() != this->width() || backendTexture.height() != this->height()) {
544         return false;
545     }
546     auto* oldRTP = fDevice->targetProxy();
547     auto oldProxy = sk_ref_sp(oldRTP->asTextureProxy());
548     if (!oldProxy) {
549         return false;
550     }
551     auto* oldTexture = oldProxy->peekTexture();
552     if (!oldTexture) {
553         return false;
554     }
555     if (!oldTexture->resourcePriv().refsWrappedObjects()) {
556         return false;
557     }
558     if (oldTexture->backendFormat() != backendTexture.getBackendFormat()) {
559         return false;
560     }
561     if (oldTexture->getBackendTexture().isSameTexture(backendTexture)) {
562         return false;
563     }
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)) {
569         return false;
570     }
571
572     sk_sp<SkColorSpace> colorSpace = fDevice->imageInfo().refColorSpace();
573
574     SkASSERT(sampleCnt > 0);
575     sk_sp<GrTextureProxy> proxy(rContext->priv().proxyProvider()->wrapRenderableBackendTexture(
576             backendTexture, sampleCnt, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
577             std::move(releaseHelper)));
578     if (!proxy) {
579         return false;
580     }
581
582     return fDevice->replaceBackingProxy(mode, sk_ref_sp(proxy->asRenderTargetProxy()), grColorType,
583                                         std::move(colorSpace), origin, this->props());
584 }
585
586 bool validate_backend_render_target(const GrCaps* caps, const GrBackendRenderTarget& rt,
587                                     GrColorType grCT) {
588     if (!caps->areColorTypeAndFormatCompatible(grCT, rt.getBackendFormat())) {
589         return false;
590     }
591
592     if (!caps->isFormatAsColorTypeRenderable(grCT, rt.getBackendFormat(), rt.sampleCnt())) {
593         return false;
594     }
595
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) {
599         return false;
600     }
601
602     return true;
603 }
604
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);
614
615     if (!rContext) {
616         return nullptr;
617     }
618
619     GrColorType grColorType = SkColorTypeToGrColorType(colorType);
620     if (grColorType == GrColorType::kUnknown) {
621         return nullptr;
622     }
623
624     if (!validate_backend_render_target(rContext->priv().caps(), rt, grColorType)) {
625         return nullptr;
626     }
627
628     auto proxyProvider = rContext->priv().proxyProvider();
629     auto proxy = proxyProvider->wrapBackendRenderTarget(rt, std::move(releaseHelper));
630     if (!proxy) {
631         return nullptr;
632     }
633
634     auto device = rContext->priv().createDevice(grColorType, std::move(proxy),
635                                                 std::move(colorSpace), origin,
636                                                 SkSurfacePropsCopyOrDefault(props),
637                                                 skgpu::BaseDevice::InitContents::kUninit);
638     if (!device) {
639         return nullptr;
640     }
641
642     return sk_make_sp<SkSurface_Gpu>(std::move(device));
643 }
644
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
652                                                     , bool fromWindow
653 #endif
654                                                     ) {
655     AHardwareBuffer_Desc bufferDesc;
656     AHardwareBuffer_describe(hardwareBuffer, &bufferDesc);
657
658     if (!SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT)) {
659         return nullptr;
660     }
661
662     bool isTextureable = SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE);
663
664     GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(dContext,
665                                                                              hardwareBuffer,
666                                                                              bufferDesc.format,
667                                                                              true);
668     if (!backendFormat.isValid()) {
669         return nullptr;
670     }
671
672     if (isTextureable) {
673         GrAHardwareBufferUtils::DeleteImageProc deleteImageProc = nullptr;
674         GrAHardwareBufferUtils::UpdateImageProc updateImageProc = nullptr;
675         GrAHardwareBufferUtils::TexImageCtx deleteImageCtx = nullptr;
676
677         bool isProtectedContent =
678                 SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
679
680         bool fromWindowLocal = false;
681 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
682         fromWindowLocal = fromWindow;
683 #endif
684
685         GrBackendTexture backendTexture =
686                 GrAHardwareBufferUtils::MakeBackendTexture(dContext,
687                                                            hardwareBuffer,
688                                                            bufferDesc.width,
689                                                            bufferDesc.height,
690                                                            &deleteImageProc,
691                                                            &updateImageProc,
692                                                            &deleteImageCtx,
693                                                            isProtectedContent,
694                                                            backendFormat,
695                                                            true,
696                                                            fromWindowLocal);
697         if (!backendTexture.isValid()) {
698             return nullptr;
699         }
700
701         SkColorType colorType =
702                 GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(bufferDesc.format);
703
704         sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(dContext, backendTexture,
705                 origin, 0, colorType, std::move(colorSpace), surfaceProps, deleteImageProc,
706                 deleteImageCtx);
707
708         if (!surface) {
709             SkASSERT(deleteImageProc);
710             deleteImageProc(deleteImageCtx);
711         }
712
713         return surface;
714     } else {
715         return nullptr;
716     }
717 }
718 #endif
719
720 void SkSurface::flushAndSubmit(bool syncCpu) {
721     this->flush(BackendSurfaceAccess::kNoAccess, GrFlushInfo());
722
723     auto direct = GrAsDirectContext(this->recordingContext());
724     if (direct) {
725         direct->submit(syncCpu);
726     }
727 }
728
729 #endif