Flutter Engine
The Flutter Engine
Surface_Graphite.cpp
Go to the documentation of this file.
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
9
25
26namespace skgpu::graphite {
27
29 : SkSurface_Base(device->width(), device->height(), &device->surfaceProps())
30 , fDevice(std::move(device))
31 , fImageView(Image::WrapDevice(fDevice)) {}
32
34 // Mark the device immutable when the Surface is destroyed to flush any pending work to the
35 // recorder and to flag the device so that any linked image views can detach from the Device
36 // when they are next drawn.
37 fDevice->setImmutable();
38}
39
41 return fDevice->imageInfo();
42}
43
44Recorder* Surface::onGetRecorder() const { return fDevice->recorder(); }
45
47 return fDevice->readSurfaceView();
48}
49
50SkCanvas* Surface::onNewCanvas() { return new SkCanvas(fDevice); }
51
53 return fDevice->makeSurface(ii, this->props());
54}
55
57 return this->makeImageCopy(subset, fDevice->target()->mipmapped());
58}
59
61 if (this->hasCachedImage()) {
62 SKGPU_LOG_W("Intermingling makeImageSnapshot and asImage calls may produce "
63 "unexpected results. Please use either the old _or_ new API.");
64 }
65 return fImageView;
66}
67
68sk_sp<Image> Surface::makeImageCopy(const SkIRect* subset, Mipmapped mipmapped) const {
69 if (this->hasCachedImage()) {
70 SKGPU_LOG_W("Intermingling makeImageSnapshot and asImage calls may produce "
71 "unexpected results. Please use either the old _or_ new API.");
72 }
73
74 SkIRect srcRect = subset ? *subset : SkIRect::MakeSize(this->imageInfo().dimensions());
75 // NOTE: Must copy through fDevice and not fImageView if the surface's texture is not sampleable
76 return fDevice->makeImageCopy(srcRect, Budgeted::kNo, mipmapped, SkBackingFit::kExact);
77}
78
79void Surface::onWritePixels(const SkPixmap& pixmap, int x, int y) {
80 fDevice->writePixels(pixmap, x, y);
81}
82
84
86 SkIRect srcRect,
87 RescaleGamma rescaleGamma,
88 RescaleMode rescaleMode,
90 ReadPixelsContext context) {
91 // Not supported for Graphite. Use Context::asyncRescaleAndReadPixels instead.
92 callback(context, nullptr);
93}
94
96 bool readAlpha,
97 sk_sp<SkColorSpace> dstColorSpace,
98 SkIRect srcRect,
99 SkISize dstSize,
100 RescaleGamma rescaleGamma,
101 RescaleMode rescaleMode,
103 ReadPixelsContext context) {
104 // Not supported for Graphite. Use Context::asyncRescaleAndReadPixelsYUV420 instead.
105 callback(context, nullptr);
106}
107
109 return fDevice->recorder()->priv().caps()->capabilities();
110}
111
112TextureProxy* Surface::backingTextureProxy() const { return fDevice->target(); }
113
115 const SkImageInfo& info,
116 std::string_view label,
117 Budgeted budgeted,
118 Mipmapped mipmapped,
119 SkBackingFit backingFit,
120 const SkSurfaceProps* props,
121 LoadOp initialLoadOp,
122 bool registerWithRecorder) {
124 info,
125 budgeted,
126 mipmapped,
127 backingFit,
129 initialLoadOp,
130 std::move(label),
131 registerWithRecorder);
132 if (!device) {
133 return nullptr;
134 }
135 // A non-budgeted surface should be fully instantiated before we return it
136 // to the client.
137 SkASSERT(budgeted == Budgeted::kYes || device->target()->isInstantiated());
138 return sk_make_sp<Surface>(std::move(device));
139}
140
142 return Flush(surface.get());
143}
144
146 if (!surface) {
147 return;
148 }
149 auto sb = asSB(surface);
150 if (!sb->isGraphiteBacked()) {
151 return;
152 }
153 auto gs = static_cast<Surface*>(surface);
154 gs->fDevice->flushPendingWorkToRecorder();
155}
156
157} // namespace skgpu::graphite
158
159using namespace skgpu::graphite;
160
161namespace {
162
163bool validate_backend_texture(const Caps* caps,
164 const BackendTexture& texture,
165 const SkColorInfo& info) {
166 if (!texture.isValid() ||
167 texture.dimensions().width() <= 0 ||
168 texture.dimensions().height() <= 0) {
169 return false;
170 }
171
172 if (!SkColorInfoIsValid(info)) {
173 return false;
174 }
175
176 if (!caps->isRenderable(texture.info())) {
177 return false;
178 }
179
180 return caps->areColorTypeAndTextureInfoCompatible(info.colorType(), texture.info());
181}
182
183} // anonymous namespace
184
185namespace SkSurfaces {
187 if (!surface) {
188 return nullptr;
189 }
190 auto sb = asConstSB(surface.get());
191 if (!sb->isGraphiteBacked()) {
192 return nullptr;
193 }
194 auto gs = static_cast<const Surface*>(surface.get());
195 return gs->asImage();
196}
197
199 const SkIRect* subset,
200 skgpu::Mipmapped mipmapped) {
201 if (!surface) {
202 return nullptr;
203 }
204 auto sb = asConstSB(surface.get());
205 if (!sb->isGraphiteBacked()) {
206 return nullptr;
207 }
208 auto gs = static_cast<const Surface*>(surface.get());
209 return gs->makeImageCopy(subset, mipmapped);
210}
211
213 const SkImageInfo& info,
214 skgpu::Mipmapped mipmapped,
215 const SkSurfaceProps* props,
216 std::string_view label) {
217 if (label.empty()) {
218 label = "SkSurfaceRenderTarget";
219 }
220 // The client is getting the ref on this surface so it must be unbudgeted.
221 return skgpu::graphite::Surface::Make(recorder, info, std::move(label), skgpu::Budgeted::kNo,
222 mipmapped, SkBackingFit::kExact, props);
223}
224
226 const BackendTexture& backendTex,
227 SkColorType ct,
229 const SkSurfaceProps* props,
230 TextureReleaseProc releaseP,
231 ReleaseContext releaseC,
232 std::string_view label) {
233 auto releaseHelper = skgpu::RefCntedCallback::Make(releaseP, releaseC);
234
235 if (!recorder) {
236 return nullptr;
237 }
238
239 const Caps* caps = recorder->priv().caps();
240
241 SkColorInfo info(ct, kPremul_SkAlphaType, std::move(cs));
242
243 if (!validate_backend_texture(caps, backendTex, info)) {
244 SKGPU_LOG_E("validate_backend_texture failed: backendTex.info = %s; colorType = %d",
245 backendTex.info().toString().c_str(),
246 info.colorType());
247 return nullptr;
248 }
249
250 if (label.empty()) {
251 label = "SkSurfaceWrappedTexture";
252 }
253
255 recorder->priv().resourceProvider()->createWrappedTexture(backendTex, std::move(label));
256 if (!texture) {
257 return nullptr;
258 }
259 texture->setReleaseCallback(std::move(releaseHelper));
260
262 SkISize deviceSize = proxy->dimensions();
263 // Use kLoad for this device to preserve the existing contents of the wrapped backend texture.
265 std::move(proxy),
266 deviceSize,
267 info,
269 LoadOp::kLoad);
270 return device ? sk_make_sp<Surface>(std::move(device)) : nullptr;
271}
272
273} // namespace SkSurfaces
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
#define SKGPU_LOG_E(fmt,...)
Definition: Log.h:38
#define SKGPU_LOG_W(fmt,...)
Definition: Log.h:40
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkBackingFit
Definition: SkBackingFit.h:16
SkColorType
Definition: SkColorType.h:19
static bool SkColorInfoIsValid(const SkColorInfo &info)
SkYUVColorSpace
Definition: SkImageInfo.h:68
static SkSurfaceProps SkSurfacePropsCopyOrDefault(const SkSurfaceProps *props)
Definition: SkSurfacePriv.h:15
static const SkSurface_Base * asConstSB(const SkSurface *surface)
static SkSurface_Base * asSB(SkSurface *surface)
static bool validate_backend_texture(const GrCaps *caps, const GrBackendTexture &tex, int sampleCnt, GrColorType grCT, bool texturable)
RescaleMode
Definition: SkImage.h:587
RescaleGamma
Definition: SkImage.h:585
const char * c_str() const
Definition: SkString.h:133
friend class SkCanvas
bool hasCachedImage() const
ContentChangeMode
Definition: SkSurface.h:203
void(ReadPixelsContext, std::unique_ptr< const AsyncReadResult >) ReadPixelsCallback
Definition: SkSurface.h:469
const SkSurfaceProps & props() const
Definition: SkSurface.h:604
skgpu::graphite::Recorder * recorder() const
Definition: SkSurface.cpp:232
void * ReadPixelsContext
Definition: SkSurface.h:464
static sk_sp< RefCntedCallback > Make(Callback proc, Context ctx)
const TextureInfo & info() const
virtual bool isRenderable(const TextureInfo &) const =0
bool areColorTypeAndTextureInfoCompatible(SkColorType, const TextureInfo &) const
Definition: Caps.cpp:85
static sk_sp< Device > Make(Recorder *recorder, sk_sp< TextureProxy >, SkISize deviceSize, const SkColorInfo &, const SkSurfaceProps &, LoadOp initialLoadOp, bool registerWithRecorder=true)
Definition: Device.cpp:276
const Caps * caps() const
Definition: RecorderPriv.h:31
ResourceProvider * resourceProvider()
Definition: RecorderPriv.h:33
sk_sp< Texture > createWrappedTexture(const BackendTexture &, std::string_view label)
void onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace, bool readAlpha, sk_sp< SkColorSpace > dstColorSpace, SkIRect srcRect, SkISize dstSize, RescaleGamma rescaleGamma, RescaleMode, ReadPixelsCallback callback, ReadPixelsContext context) override
static sk_sp< Surface > Make(Recorder *recorder, const SkImageInfo &info, std::string_view label, Budgeted budgeted, Mipmapped mipmapped=Mipmapped::kNo, SkBackingFit backingFit=SkBackingFit::kExact, const SkSurfaceProps *props=nullptr)
void onAsyncRescaleAndReadPixels(const SkImageInfo &info, SkIRect srcRect, RescaleGamma rescaleGamma, RescaleMode rescaleMode, ReadPixelsCallback callback, ReadPixelsContext context) override
SkCanvas * onNewCanvas() override
sk_sp< Image > makeImageCopy(const SkIRect *subset, Mipmapped) const
sk_sp< SkSurface > onNewSurface(const SkImageInfo &) override
sk_sp< Image > asImage() const
Recorder * onGetRecorder() const override
sk_sp< SkImage > onNewImageSnapshot(const SkIRect *subset) override
bool onCopyOnWrite(ContentChangeMode) override
void onWritePixels(const SkPixmap &, int x, int y) override
SkImageInfo imageInfo() const override
TextureProxyView readSurfaceView() const
sk_sp< const SkCapabilities > onCapabilities() override
TextureProxy * backingTextureProxy() const
VkDevice device
Definition: main.cc:53
VkSurfaceKHR surface
Definition: main.cc:49
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
FlTexture * texture
double y
double x
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
void * ReleaseContext
SK_API sk_sp< SkImage > AsImage(sk_sp< const SkSurface >)
SK_API sk_sp< SkSurface > WrapBackendTexture(GrRecordingContext *context, const GrBackendTexture &backendTexture, GrSurfaceOrigin origin, int sampleCnt, SkColorType colorType, sk_sp< SkColorSpace > colorSpace, const SkSurfaceProps *surfaceProps, TextureReleaseProc textureReleaseProc=nullptr, ReleaseContext releaseContext=nullptr)
void(*)(ReleaseContext) TextureReleaseProc
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
SK_API sk_sp< SkImage > AsImageCopy(sk_sp< const SkSurface >, const SkIRect *subset=nullptr, skgpu::Mipmapped=skgpu::Mipmapped::kNo)
void Flush(sk_sp< SkSurface > surface)
Budgeted
Definition: GpuTypes.h:35
Mipmapped
Definition: GpuTypes.h:53
Definition: ref_ptr.h:256
int32_t height
int32_t width
Definition: SkRect.h:32
static constexpr SkIRect MakeSize(const SkISize &size)
Definition: SkRect.h:66
Definition: SkSize.h:16
GrSamplerState::WrapMode Wrap
Definition: texelsubset.cpp:40