xref: /aosp_15_r20/external/skia/src/gpu/graphite/Surface_Graphite.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2021 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Surface_Graphite.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCapabilities.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/BackendTexture.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Recorder.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Surface.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkSurfacePriv.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/RefCntedCallback.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/SkBackingFit.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Caps.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Device.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Image_Graphite.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Log.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RecorderPriv.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ResourceProvider.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Texture.h"
25*c8dee2aaSAndroid Build Coastguard Worker 
26*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite {
27*c8dee2aaSAndroid Build Coastguard Worker 
Surface(sk_sp<Device> device)28*c8dee2aaSAndroid Build Coastguard Worker Surface::Surface(sk_sp<Device> device)
29*c8dee2aaSAndroid Build Coastguard Worker         : SkSurface_Base(device->width(), device->height(), &device->surfaceProps())
30*c8dee2aaSAndroid Build Coastguard Worker         , fDevice(std::move(device))
31*c8dee2aaSAndroid Build Coastguard Worker         , fImageView(Image::WrapDevice(fDevice)) {}
32*c8dee2aaSAndroid Build Coastguard Worker 
~Surface()33*c8dee2aaSAndroid Build Coastguard Worker Surface::~Surface() {
34*c8dee2aaSAndroid Build Coastguard Worker     // Mark the device immutable when the Surface is destroyed to flush any pending work to the
35*c8dee2aaSAndroid Build Coastguard Worker     // recorder and to flag the device so that any linked image views can detach from the Device
36*c8dee2aaSAndroid Build Coastguard Worker     // when they are next drawn.
37*c8dee2aaSAndroid Build Coastguard Worker     fDevice->setImmutable();
38*c8dee2aaSAndroid Build Coastguard Worker }
39*c8dee2aaSAndroid Build Coastguard Worker 
imageInfo() const40*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo Surface::imageInfo() const {
41*c8dee2aaSAndroid Build Coastguard Worker     return fDevice->imageInfo();
42*c8dee2aaSAndroid Build Coastguard Worker }
43*c8dee2aaSAndroid Build Coastguard Worker 
onGetRecorder() const44*c8dee2aaSAndroid Build Coastguard Worker Recorder* Surface::onGetRecorder() const { return fDevice->recorder(); }
45*c8dee2aaSAndroid Build Coastguard Worker 
readSurfaceView() const46*c8dee2aaSAndroid Build Coastguard Worker TextureProxyView Surface::readSurfaceView() const {
47*c8dee2aaSAndroid Build Coastguard Worker     return fDevice->readSurfaceView();
48*c8dee2aaSAndroid Build Coastguard Worker }
49*c8dee2aaSAndroid Build Coastguard Worker 
onNewCanvas()50*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* Surface::onNewCanvas() { return new SkCanvas(fDevice); }
51*c8dee2aaSAndroid Build Coastguard Worker 
onNewSurface(const SkImageInfo & ii)52*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> Surface::onNewSurface(const SkImageInfo& ii) {
53*c8dee2aaSAndroid Build Coastguard Worker     return fDevice->makeSurface(ii, this->props());
54*c8dee2aaSAndroid Build Coastguard Worker }
55*c8dee2aaSAndroid Build Coastguard Worker 
onNewImageSnapshot(const SkIRect * subset)56*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> Surface::onNewImageSnapshot(const SkIRect* subset) {
57*c8dee2aaSAndroid Build Coastguard Worker     return this->makeImageCopy(subset, fDevice->target()->mipmapped());
58*c8dee2aaSAndroid Build Coastguard Worker }
59*c8dee2aaSAndroid Build Coastguard Worker 
asImage() const60*c8dee2aaSAndroid Build Coastguard Worker sk_sp<Image> Surface::asImage() const {
61*c8dee2aaSAndroid Build Coastguard Worker     if (this->hasCachedImage()) {
62*c8dee2aaSAndroid Build Coastguard Worker         SKGPU_LOG_W("Intermingling makeImageSnapshot and asImage calls may produce "
63*c8dee2aaSAndroid Build Coastguard Worker                     "unexpected results. Please use either the old _or_ new API.");
64*c8dee2aaSAndroid Build Coastguard Worker     }
65*c8dee2aaSAndroid Build Coastguard Worker     return fImageView;
66*c8dee2aaSAndroid Build Coastguard Worker }
67*c8dee2aaSAndroid Build Coastguard Worker 
makeImageCopy(const SkIRect * subset,Mipmapped mipmapped) const68*c8dee2aaSAndroid Build Coastguard Worker sk_sp<Image> Surface::makeImageCopy(const SkIRect* subset, Mipmapped mipmapped) const {
69*c8dee2aaSAndroid Build Coastguard Worker     if (this->hasCachedImage()) {
70*c8dee2aaSAndroid Build Coastguard Worker         SKGPU_LOG_W("Intermingling makeImageSnapshot and asImage calls may produce "
71*c8dee2aaSAndroid Build Coastguard Worker                     "unexpected results. Please use either the old _or_ new API.");
72*c8dee2aaSAndroid Build Coastguard Worker     }
73*c8dee2aaSAndroid Build Coastguard Worker 
74*c8dee2aaSAndroid Build Coastguard Worker     SkIRect srcRect = subset ? *subset : SkIRect::MakeSize(this->imageInfo().dimensions());
75*c8dee2aaSAndroid Build Coastguard Worker     // NOTE: Must copy through fDevice and not fImageView if the surface's texture is not sampleable
76*c8dee2aaSAndroid Build Coastguard Worker     return fDevice->makeImageCopy(srcRect, Budgeted::kNo, mipmapped, SkBackingFit::kExact);
77*c8dee2aaSAndroid Build Coastguard Worker }
78*c8dee2aaSAndroid Build Coastguard Worker 
onWritePixels(const SkPixmap & pixmap,int x,int y)79*c8dee2aaSAndroid Build Coastguard Worker void Surface::onWritePixels(const SkPixmap& pixmap, int x, int y) {
80*c8dee2aaSAndroid Build Coastguard Worker     fDevice->writePixels(pixmap, x, y);
81*c8dee2aaSAndroid Build Coastguard Worker }
82*c8dee2aaSAndroid Build Coastguard Worker 
onCopyOnWrite(ContentChangeMode)83*c8dee2aaSAndroid Build Coastguard Worker bool Surface::onCopyOnWrite(ContentChangeMode) { return true; }
84*c8dee2aaSAndroid Build Coastguard Worker 
onAsyncRescaleAndReadPixels(const SkImageInfo & info,SkIRect srcRect,RescaleGamma rescaleGamma,RescaleMode rescaleMode,ReadPixelsCallback callback,ReadPixelsContext context)85*c8dee2aaSAndroid Build Coastguard Worker void Surface::onAsyncRescaleAndReadPixels(const SkImageInfo& info,
86*c8dee2aaSAndroid Build Coastguard Worker                                           SkIRect srcRect,
87*c8dee2aaSAndroid Build Coastguard Worker                                           RescaleGamma rescaleGamma,
88*c8dee2aaSAndroid Build Coastguard Worker                                           RescaleMode rescaleMode,
89*c8dee2aaSAndroid Build Coastguard Worker                                           ReadPixelsCallback callback,
90*c8dee2aaSAndroid Build Coastguard Worker                                           ReadPixelsContext context) {
91*c8dee2aaSAndroid Build Coastguard Worker     // Not supported for Graphite. Use Context::asyncRescaleAndReadPixels instead.
92*c8dee2aaSAndroid Build Coastguard Worker     callback(context, nullptr);
93*c8dee2aaSAndroid Build Coastguard Worker }
94*c8dee2aaSAndroid Build Coastguard Worker 
onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,bool readAlpha,sk_sp<SkColorSpace> dstColorSpace,SkIRect srcRect,SkISize dstSize,RescaleGamma rescaleGamma,RescaleMode rescaleMode,ReadPixelsCallback callback,ReadPixelsContext context)95*c8dee2aaSAndroid Build Coastguard Worker void Surface::onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
96*c8dee2aaSAndroid Build Coastguard Worker                                                 bool readAlpha,
97*c8dee2aaSAndroid Build Coastguard Worker                                                 sk_sp<SkColorSpace> dstColorSpace,
98*c8dee2aaSAndroid Build Coastguard Worker                                                 SkIRect srcRect,
99*c8dee2aaSAndroid Build Coastguard Worker                                                 SkISize dstSize,
100*c8dee2aaSAndroid Build Coastguard Worker                                                 RescaleGamma rescaleGamma,
101*c8dee2aaSAndroid Build Coastguard Worker                                                 RescaleMode rescaleMode,
102*c8dee2aaSAndroid Build Coastguard Worker                                                 ReadPixelsCallback callback,
103*c8dee2aaSAndroid Build Coastguard Worker                                                 ReadPixelsContext context) {
104*c8dee2aaSAndroid Build Coastguard Worker     // Not supported for Graphite. Use Context::asyncRescaleAndReadPixelsYUV420 instead.
105*c8dee2aaSAndroid Build Coastguard Worker     callback(context, nullptr);
106*c8dee2aaSAndroid Build Coastguard Worker }
107*c8dee2aaSAndroid Build Coastguard Worker 
onCapabilities()108*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const SkCapabilities> Surface::onCapabilities() {
109*c8dee2aaSAndroid Build Coastguard Worker     return fDevice->recorder()->priv().caps()->capabilities();
110*c8dee2aaSAndroid Build Coastguard Worker }
111*c8dee2aaSAndroid Build Coastguard Worker 
backingTextureProxy() const112*c8dee2aaSAndroid Build Coastguard Worker TextureProxy* Surface::backingTextureProxy() const { return fDevice->target(); }
113*c8dee2aaSAndroid Build Coastguard Worker 
Make(Recorder * recorder,const SkImageInfo & info,std::string_view label,Budgeted budgeted,Mipmapped mipmapped,SkBackingFit backingFit,const SkSurfaceProps * props,LoadOp initialLoadOp,bool registerWithRecorder)114*c8dee2aaSAndroid Build Coastguard Worker sk_sp<Surface> Surface::Make(Recorder* recorder,
115*c8dee2aaSAndroid Build Coastguard Worker                              const SkImageInfo& info,
116*c8dee2aaSAndroid Build Coastguard Worker                              std::string_view label,
117*c8dee2aaSAndroid Build Coastguard Worker                              Budgeted budgeted,
118*c8dee2aaSAndroid Build Coastguard Worker                              Mipmapped mipmapped,
119*c8dee2aaSAndroid Build Coastguard Worker                              SkBackingFit backingFit,
120*c8dee2aaSAndroid Build Coastguard Worker                              const SkSurfaceProps* props,
121*c8dee2aaSAndroid Build Coastguard Worker                              LoadOp initialLoadOp,
122*c8dee2aaSAndroid Build Coastguard Worker                              bool registerWithRecorder) {
123*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<Device> device = Device::Make(recorder,
124*c8dee2aaSAndroid Build Coastguard Worker                                         info,
125*c8dee2aaSAndroid Build Coastguard Worker                                         budgeted,
126*c8dee2aaSAndroid Build Coastguard Worker                                         mipmapped,
127*c8dee2aaSAndroid Build Coastguard Worker                                         backingFit,
128*c8dee2aaSAndroid Build Coastguard Worker                                         SkSurfacePropsCopyOrDefault(props),
129*c8dee2aaSAndroid Build Coastguard Worker                                         initialLoadOp,
130*c8dee2aaSAndroid Build Coastguard Worker                                         std::move(label),
131*c8dee2aaSAndroid Build Coastguard Worker                                         registerWithRecorder);
132*c8dee2aaSAndroid Build Coastguard Worker     if (!device) {
133*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
134*c8dee2aaSAndroid Build Coastguard Worker     }
135*c8dee2aaSAndroid Build Coastguard Worker     // A non-budgeted surface should be fully instantiated before we return it
136*c8dee2aaSAndroid Build Coastguard Worker     // to the client.
137*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(budgeted == Budgeted::kYes || device->target()->isInstantiated());
138*c8dee2aaSAndroid Build Coastguard Worker     return sk_make_sp<Surface>(std::move(device));
139*c8dee2aaSAndroid Build Coastguard Worker }
140*c8dee2aaSAndroid Build Coastguard Worker 
Flush(sk_sp<SkSurface> surface)141*c8dee2aaSAndroid Build Coastguard Worker void Flush(sk_sp<SkSurface> surface) {
142*c8dee2aaSAndroid Build Coastguard Worker     return Flush(surface.get());
143*c8dee2aaSAndroid Build Coastguard Worker }
144*c8dee2aaSAndroid Build Coastguard Worker 
Flush(SkSurface * surface)145*c8dee2aaSAndroid Build Coastguard Worker void Flush(SkSurface* surface) {
146*c8dee2aaSAndroid Build Coastguard Worker     if (!surface) {
147*c8dee2aaSAndroid Build Coastguard Worker         return;
148*c8dee2aaSAndroid Build Coastguard Worker     }
149*c8dee2aaSAndroid Build Coastguard Worker     auto sb = asSB(surface);
150*c8dee2aaSAndroid Build Coastguard Worker     if (!sb->isGraphiteBacked()) {
151*c8dee2aaSAndroid Build Coastguard Worker         return;
152*c8dee2aaSAndroid Build Coastguard Worker     }
153*c8dee2aaSAndroid Build Coastguard Worker     auto gs = static_cast<Surface*>(surface);
154*c8dee2aaSAndroid Build Coastguard Worker     gs->fDevice->flushPendingWorkToRecorder();
155*c8dee2aaSAndroid Build Coastguard Worker }
156*c8dee2aaSAndroid Build Coastguard Worker 
157*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite
158*c8dee2aaSAndroid Build Coastguard Worker 
159*c8dee2aaSAndroid Build Coastguard Worker using namespace skgpu::graphite;
160*c8dee2aaSAndroid Build Coastguard Worker 
161*c8dee2aaSAndroid Build Coastguard Worker namespace {
162*c8dee2aaSAndroid Build Coastguard Worker 
validate_backend_texture(const Caps * caps,const BackendTexture & texture,const SkColorInfo & info)163*c8dee2aaSAndroid Build Coastguard Worker bool validate_backend_texture(const Caps* caps,
164*c8dee2aaSAndroid Build Coastguard Worker                               const BackendTexture& texture,
165*c8dee2aaSAndroid Build Coastguard Worker                               const SkColorInfo& info) {
166*c8dee2aaSAndroid Build Coastguard Worker     if (!texture.isValid() ||
167*c8dee2aaSAndroid Build Coastguard Worker         texture.dimensions().width() <= 0 ||
168*c8dee2aaSAndroid Build Coastguard Worker         texture.dimensions().height() <= 0) {
169*c8dee2aaSAndroid Build Coastguard Worker         return false;
170*c8dee2aaSAndroid Build Coastguard Worker     }
171*c8dee2aaSAndroid Build Coastguard Worker 
172*c8dee2aaSAndroid Build Coastguard Worker     if (!SkColorInfoIsValid(info)) {
173*c8dee2aaSAndroid Build Coastguard Worker         return false;
174*c8dee2aaSAndroid Build Coastguard Worker     }
175*c8dee2aaSAndroid Build Coastguard Worker 
176*c8dee2aaSAndroid Build Coastguard Worker     if (!caps->isRenderable(texture.info())) {
177*c8dee2aaSAndroid Build Coastguard Worker         return false;
178*c8dee2aaSAndroid Build Coastguard Worker     }
179*c8dee2aaSAndroid Build Coastguard Worker 
180*c8dee2aaSAndroid Build Coastguard Worker     return caps->areColorTypeAndTextureInfoCompatible(info.colorType(), texture.info());
181*c8dee2aaSAndroid Build Coastguard Worker }
182*c8dee2aaSAndroid Build Coastguard Worker 
183*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
184*c8dee2aaSAndroid Build Coastguard Worker 
185*c8dee2aaSAndroid Build Coastguard Worker namespace SkSurfaces {
AsImage(sk_sp<const SkSurface> surface)186*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> AsImage(sk_sp<const SkSurface> surface) {
187*c8dee2aaSAndroid Build Coastguard Worker     if (!surface) {
188*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
189*c8dee2aaSAndroid Build Coastguard Worker     }
190*c8dee2aaSAndroid Build Coastguard Worker     auto sb = asConstSB(surface.get());
191*c8dee2aaSAndroid Build Coastguard Worker     if (!sb->isGraphiteBacked()) {
192*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
193*c8dee2aaSAndroid Build Coastguard Worker     }
194*c8dee2aaSAndroid Build Coastguard Worker     auto gs = static_cast<const Surface*>(surface.get());
195*c8dee2aaSAndroid Build Coastguard Worker     return gs->asImage();
196*c8dee2aaSAndroid Build Coastguard Worker }
197*c8dee2aaSAndroid Build Coastguard Worker 
AsImageCopy(sk_sp<const SkSurface> surface,const SkIRect * subset,skgpu::Mipmapped mipmapped)198*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> AsImageCopy(sk_sp<const SkSurface> surface,
199*c8dee2aaSAndroid Build Coastguard Worker                            const SkIRect* subset,
200*c8dee2aaSAndroid Build Coastguard Worker                            skgpu::Mipmapped mipmapped) {
201*c8dee2aaSAndroid Build Coastguard Worker     if (!surface) {
202*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
203*c8dee2aaSAndroid Build Coastguard Worker     }
204*c8dee2aaSAndroid Build Coastguard Worker     auto sb = asConstSB(surface.get());
205*c8dee2aaSAndroid Build Coastguard Worker     if (!sb->isGraphiteBacked()) {
206*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
207*c8dee2aaSAndroid Build Coastguard Worker     }
208*c8dee2aaSAndroid Build Coastguard Worker     auto gs = static_cast<const Surface*>(surface.get());
209*c8dee2aaSAndroid Build Coastguard Worker     return gs->makeImageCopy(subset, mipmapped);
210*c8dee2aaSAndroid Build Coastguard Worker }
211*c8dee2aaSAndroid Build Coastguard Worker 
RenderTarget(Recorder * recorder,const SkImageInfo & info,skgpu::Mipmapped mipmapped,const SkSurfaceProps * props,std::string_view label)212*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> RenderTarget(Recorder* recorder,
213*c8dee2aaSAndroid Build Coastguard Worker                               const SkImageInfo& info,
214*c8dee2aaSAndroid Build Coastguard Worker                               skgpu::Mipmapped mipmapped,
215*c8dee2aaSAndroid Build Coastguard Worker                               const SkSurfaceProps* props,
216*c8dee2aaSAndroid Build Coastguard Worker                               std::string_view label) {
217*c8dee2aaSAndroid Build Coastguard Worker     if (label.empty()) {
218*c8dee2aaSAndroid Build Coastguard Worker         label = "SkSurfaceRenderTarget";
219*c8dee2aaSAndroid Build Coastguard Worker     }
220*c8dee2aaSAndroid Build Coastguard Worker     // The client is getting the ref on this surface so it must be unbudgeted.
221*c8dee2aaSAndroid Build Coastguard Worker     return skgpu::graphite::Surface::Make(recorder, info, std::move(label), skgpu::Budgeted::kNo,
222*c8dee2aaSAndroid Build Coastguard Worker                                           mipmapped, SkBackingFit::kExact, props);
223*c8dee2aaSAndroid Build Coastguard Worker }
224*c8dee2aaSAndroid Build Coastguard Worker 
WrapBackendTexture(Recorder * recorder,const BackendTexture & backendTex,SkColorType ct,sk_sp<SkColorSpace> cs,const SkSurfaceProps * props,TextureReleaseProc releaseP,ReleaseContext releaseC,std::string_view label)225*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> WrapBackendTexture(Recorder* recorder,
226*c8dee2aaSAndroid Build Coastguard Worker                                     const BackendTexture& backendTex,
227*c8dee2aaSAndroid Build Coastguard Worker                                     SkColorType ct,
228*c8dee2aaSAndroid Build Coastguard Worker                                     sk_sp<SkColorSpace> cs,
229*c8dee2aaSAndroid Build Coastguard Worker                                     const SkSurfaceProps* props,
230*c8dee2aaSAndroid Build Coastguard Worker                                     TextureReleaseProc releaseP,
231*c8dee2aaSAndroid Build Coastguard Worker                                     ReleaseContext releaseC,
232*c8dee2aaSAndroid Build Coastguard Worker                                     std::string_view label) {
233*c8dee2aaSAndroid Build Coastguard Worker     auto releaseHelper = skgpu::RefCntedCallback::Make(releaseP, releaseC);
234*c8dee2aaSAndroid Build Coastguard Worker 
235*c8dee2aaSAndroid Build Coastguard Worker     if (!recorder) {
236*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
237*c8dee2aaSAndroid Build Coastguard Worker     }
238*c8dee2aaSAndroid Build Coastguard Worker 
239*c8dee2aaSAndroid Build Coastguard Worker     const Caps* caps = recorder->priv().caps();
240*c8dee2aaSAndroid Build Coastguard Worker 
241*c8dee2aaSAndroid Build Coastguard Worker     SkColorInfo info(ct, kPremul_SkAlphaType, std::move(cs));
242*c8dee2aaSAndroid Build Coastguard Worker 
243*c8dee2aaSAndroid Build Coastguard Worker     if (!validate_backend_texture(caps, backendTex, info)) {
244*c8dee2aaSAndroid Build Coastguard Worker         SKGPU_LOG_E("validate_backend_texture failed: backendTex.info = %s; colorType = %d",
245*c8dee2aaSAndroid Build Coastguard Worker                     backendTex.info().toString().c_str(),
246*c8dee2aaSAndroid Build Coastguard Worker                     info.colorType());
247*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
248*c8dee2aaSAndroid Build Coastguard Worker     }
249*c8dee2aaSAndroid Build Coastguard Worker 
250*c8dee2aaSAndroid Build Coastguard Worker     if (label.empty()) {
251*c8dee2aaSAndroid Build Coastguard Worker         label = "SkSurfaceWrappedTexture";
252*c8dee2aaSAndroid Build Coastguard Worker     }
253*c8dee2aaSAndroid Build Coastguard Worker 
254*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<Texture> texture =
255*c8dee2aaSAndroid Build Coastguard Worker             recorder->priv().resourceProvider()->createWrappedTexture(backendTex, std::move(label));
256*c8dee2aaSAndroid Build Coastguard Worker     if (!texture) {
257*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
258*c8dee2aaSAndroid Build Coastguard Worker     }
259*c8dee2aaSAndroid Build Coastguard Worker     texture->setReleaseCallback(std::move(releaseHelper));
260*c8dee2aaSAndroid Build Coastguard Worker 
261*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<TextureProxy> proxy = TextureProxy::Wrap(std::move(texture));
262*c8dee2aaSAndroid Build Coastguard Worker     SkISize deviceSize = proxy->dimensions();
263*c8dee2aaSAndroid Build Coastguard Worker     // Use kLoad for this device to preserve the existing contents of the wrapped backend texture.
264*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<Device> device = Device::Make(recorder,
265*c8dee2aaSAndroid Build Coastguard Worker                                         std::move(proxy),
266*c8dee2aaSAndroid Build Coastguard Worker                                         deviceSize,
267*c8dee2aaSAndroid Build Coastguard Worker                                         info,
268*c8dee2aaSAndroid Build Coastguard Worker                                         SkSurfacePropsCopyOrDefault(props),
269*c8dee2aaSAndroid Build Coastguard Worker                                         LoadOp::kLoad);
270*c8dee2aaSAndroid Build Coastguard Worker     return device ? sk_make_sp<Surface>(std::move(device)) : nullptr;
271*c8dee2aaSAndroid Build Coastguard Worker }
272*c8dee2aaSAndroid Build Coastguard Worker 
273*c8dee2aaSAndroid Build Coastguard Worker }  // namespace SkSurfaces
274