1 /*
2 * Copyright 2021 Google LLC
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/gpu/graphite/Surface_Graphite.h"
9
10 #include "include/core/SkCapabilities.h"
11 #include "include/gpu/graphite/BackendTexture.h"
12 #include "include/gpu/graphite/Recorder.h"
13 #include "src/gpu/graphite/Caps.h"
14 #include "src/gpu/graphite/Device.h"
15 #include "src/gpu/graphite/Image_Graphite.h"
16 #include "src/gpu/graphite/RecorderPriv.h"
17 #include "src/gpu/graphite/ResourceProvider.h"
18 #include "src/gpu/graphite/Texture.h"
19
20 namespace skgpu::graphite {
21
Surface(sk_sp<Device> device)22 Surface::Surface(sk_sp<Device> device)
23 : SkSurface_Base(device->width(), device->height(), &device->surfaceProps())
24 , fDevice(std::move(device)) {
25 }
26
~Surface()27 Surface::~Surface() {}
28
imageInfo() const29 SkImageInfo Surface::imageInfo() const {
30 return fDevice->imageInfo();
31 }
32
onGetRecorder()33 Recorder* Surface::onGetRecorder() {
34 return fDevice->recorder();
35 }
36
readSurfaceView() const37 TextureProxyView Surface::readSurfaceView() const {
38 return fDevice->readSurfaceView();
39 }
40
onNewCanvas()41 SkCanvas* Surface::onNewCanvas() { return new SkCanvas(fDevice); }
42
onNewSurface(const SkImageInfo & ii)43 sk_sp<SkSurface> Surface::onNewSurface(const SkImageInfo& ii) {
44 return SkSurface::MakeGraphite(fDevice->recorder(), ii, Mipmapped::kNo, &this->props());
45 }
46
onNewImageSnapshot(const SkIRect * subset)47 sk_sp<SkImage> Surface::onNewImageSnapshot(const SkIRect* subset) {
48 TextureProxyView srcView = fDevice->readSurfaceView();
49 if (!srcView) {
50 return nullptr;
51 }
52
53 return this->onMakeImageCopy(subset, srcView.mipmapped());
54 }
55
onAsImage()56 sk_sp<SkImage> Surface::onAsImage() {
57 TextureProxyView srcView = fDevice->readSurfaceView();
58 if (!srcView) {
59 return nullptr;
60 }
61
62 return sk_sp<Image>(new Image(std::move(srcView), this->imageInfo().colorInfo()));
63 }
64
onMakeImageCopy(const SkIRect * subset,Mipmapped mipmapped)65 sk_sp<SkImage> Surface::onMakeImageCopy(const SkIRect* subset, Mipmapped mipmapped) {
66 TextureProxyView srcView = fDevice->createCopy(subset, mipmapped);
67 if (!srcView) {
68 return nullptr;
69 }
70
71 return sk_sp<Image>(new Image(std::move(srcView), this->imageInfo().colorInfo()));
72 }
73
onWritePixels(const SkPixmap & pixmap,int x,int y)74 void Surface::onWritePixels(const SkPixmap& pixmap, int x, int y) {
75 fDevice->writePixels(pixmap, x, y);
76 }
77
onCopyOnWrite(ContentChangeMode)78 bool Surface::onCopyOnWrite(ContentChangeMode) { return true; }
79
onAsyncRescaleAndReadPixels(const SkImageInfo & info,SkIRect srcRect,RescaleGamma rescaleGamma,RescaleMode rescaleMode,ReadPixelsCallback callback,ReadPixelsContext context)80 void Surface::onAsyncRescaleAndReadPixels(const SkImageInfo& info,
81 SkIRect srcRect,
82 RescaleGamma rescaleGamma,
83 RescaleMode rescaleMode,
84 ReadPixelsCallback callback,
85 ReadPixelsContext context) {
86 fDevice->asyncRescaleAndReadPixels(info,
87 srcRect,
88 rescaleGamma,
89 rescaleMode,
90 callback,
91 context);
92 }
93
onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,sk_sp<SkColorSpace> dstColorSpace,SkIRect srcRect,SkISize dstSize,RescaleGamma rescaleGamma,RescaleMode rescaleMode,ReadPixelsCallback callback,ReadPixelsContext context)94 void Surface::onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
95 sk_sp<SkColorSpace> dstColorSpace,
96 SkIRect srcRect,
97 SkISize dstSize,
98 RescaleGamma rescaleGamma,
99 RescaleMode rescaleMode,
100 ReadPixelsCallback callback,
101 ReadPixelsContext context) {
102 fDevice->asyncRescaleAndReadPixelsYUV420(yuvColorSpace,
103 dstColorSpace,
104 srcRect,
105 dstSize,
106 rescaleGamma,
107 rescaleMode,
108 callback,
109 context);
110 }
111
onCapabilities()112 sk_sp<const SkCapabilities> Surface::onCapabilities() {
113 return fDevice->recorder()->priv().caps()->capabilities();
114 }
115
116 #if GRAPHITE_TEST_UTILS && defined(SK_GANESH)
onFlush(BackendSurfaceAccess,const GrFlushInfo &,const skgpu::MutableTextureState *)117 GrSemaphoresSubmitted Surface::onFlush(BackendSurfaceAccess,
118 const GrFlushInfo&,
119 const skgpu::MutableTextureState*) {
120 fDevice->flushPendingWorkToRecorder();
121 return GrSemaphoresSubmitted::kNo;
122 }
123 #endif
124
backingTextureProxy()125 TextureProxy* Surface::backingTextureProxy() { return fDevice->target(); }
126
MakeGraphite(Recorder * recorder,const SkImageInfo & info,skgpu::Budgeted budgeted,Mipmapped mipmapped,const SkSurfaceProps * props)127 sk_sp<SkSurface> Surface::MakeGraphite(Recorder* recorder,
128 const SkImageInfo& info,
129 skgpu::Budgeted budgeted,
130 Mipmapped mipmapped,
131 const SkSurfaceProps* props) {
132 sk_sp<Device> device = Device::Make(recorder, info, budgeted, mipmapped,
133 SkSurfacePropsCopyOrDefault(props),
134 /* addInitialClear= */ true);
135 if (!device) {
136 return nullptr;
137 }
138
139 if (!device->target()->instantiate(recorder->priv().resourceProvider())) {
140 return nullptr;
141 }
142 return sk_make_sp<Surface>(std::move(device));
143 }
144
145 } // namespace skgpu::graphite
146
147 using namespace skgpu::graphite;
148
149 namespace {
150
validate_backend_texture(const Caps * caps,const BackendTexture & texture,const SkColorInfo & info)151 bool validate_backend_texture(const Caps* caps,
152 const BackendTexture& texture,
153 const SkColorInfo& info) {
154 if (!texture.isValid() ||
155 texture.dimensions().width() <= 0 ||
156 texture.dimensions().height() <= 0) {
157 return false;
158 }
159
160 if (!SkColorInfoIsValid(info)) {
161 return false;
162 }
163
164 if (!caps->isRenderable(texture.info())) {
165 return false;
166 }
167
168 return caps->areColorTypeAndTextureInfoCompatible(info.colorType(), texture.info());
169 }
170
171 } // anonymous namespace
172
MakeGraphite(Recorder * recorder,const SkImageInfo & info,skgpu::Mipmapped mipmapped,const SkSurfaceProps * props)173 sk_sp<SkSurface> SkSurface::MakeGraphite(Recorder* recorder,
174 const SkImageInfo& info,
175 skgpu::Mipmapped mipmapped,
176 const SkSurfaceProps* props) {
177 // The client is getting the ref on this surface so it must be unbudgeted.
178 return skgpu::graphite::Surface::MakeGraphite(
179 recorder, info, skgpu::Budgeted::kNo, mipmapped, props);
180 }
181
MakeGraphiteFromBackendTexture(Recorder * recorder,const BackendTexture & backendTex,SkColorType ct,sk_sp<SkColorSpace> cs,const SkSurfaceProps * props)182 sk_sp<SkSurface> SkSurface::MakeGraphiteFromBackendTexture(Recorder* recorder,
183 const BackendTexture& backendTex,
184 SkColorType ct,
185 sk_sp<SkColorSpace> cs,
186 const SkSurfaceProps* props) {
187
188 if (!recorder) {
189 return nullptr;
190 }
191
192 const Caps* caps = recorder->priv().caps();
193
194 SkColorInfo info(ct, kPremul_SkAlphaType, std::move(cs));
195
196 if (!validate_backend_texture(caps, backendTex, info)) {
197 return nullptr;
198 }
199
200 sk_sp<Texture> texture = recorder->priv().resourceProvider()->createWrappedTexture(backendTex);
201 if (!texture) {
202 return nullptr;
203 }
204
205 sk_sp<TextureProxy> proxy(new TextureProxy(std::move(texture)));
206
207 sk_sp<Device> device = Device::Make(recorder,
208 std::move(proxy),
209 info,
210 SkSurfacePropsCopyOrDefault(props),
211 /* addInitialClear= */ false);
212 if (!device) {
213 return nullptr;
214 }
215
216 return sk_make_sp<Surface>(std::move(device));
217 }
218