/src/skia/include/gpu/graphite/Image.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2023 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 | | #ifndef skgpu_graphite_Image_DEFINED |
9 | | #define skgpu_graphite_Image_DEFINED |
10 | | |
11 | | #include "include/core/SkColorSpace.h" |
12 | | #include "include/core/SkImage.h" |
13 | | #include "include/core/SkRefCnt.h" |
14 | | #include "include/core/SkSpan.h" |
15 | | #include "include/gpu/GpuTypes.h" |
16 | | |
17 | | class SkYUVAInfo; |
18 | | class SkYUVAPixmaps; |
19 | | struct SkIRect; |
20 | | |
21 | | namespace skgpu::graphite { |
22 | | class BackendTexture; |
23 | | class Recorder; |
24 | | class TextureInfo; |
25 | | class YUVABackendTextureInfo; |
26 | | class YUVABackendTextures; |
27 | | enum class Volatile : bool; |
28 | | } |
29 | | |
30 | | namespace SkImages { |
31 | | enum class GenerateMipmapsFromBase : bool { kNo, kYes }; |
32 | | |
33 | | using TextureReleaseProc = void (*)(ReleaseContext); |
34 | | |
35 | | // Passed to imageRelease |
36 | | using GraphitePromiseImageContext = void*; |
37 | | // Passed to fulfill; for non-YUVA promise images, the image context is used as the fulfill context, |
38 | | // while YUVA promise images have a per-plane fulfill context. |
39 | | using GraphitePromiseTextureFulfillContext = void*; |
40 | | // Returned from fulfill and passed into textureRelease |
41 | | using GraphitePromiseTextureReleaseContext = void*; |
42 | | |
43 | | using GraphitePromiseTextureFulfillProc = |
44 | | std::tuple<skgpu::graphite::BackendTexture, GraphitePromiseTextureReleaseContext> (*)( |
45 | | GraphitePromiseTextureFulfillContext); |
46 | | using GraphitePromiseImageReleaseProc = void (*)(GraphitePromiseImageContext); |
47 | | using GraphitePromiseTextureReleaseProc = void (*)(GraphitePromiseTextureReleaseContext); |
48 | | |
49 | | /** Creates an SkImage from a GPU texture associated with the recorder. The client is still |
50 | | responsible for managing the backend texture's lifetime. |
51 | | |
52 | | SkImage is returned if the format of backendTexture is recognized and supported. |
53 | | Recognized formats vary by GPU back-end. |
54 | | |
55 | | @param recorder The recorder |
56 | | @param backendTexture texture residing on GPU |
57 | | @param colorSpace This describes the color space of this image's contents, as |
58 | | seen after sampling. In general, if the format of the backend |
59 | | texture is SRGB, some linear colorSpace should be supplied |
60 | | (e.g., SkColorSpace::MakeSRGBLinear()). If the format of the |
61 | | backend texture is linear, then the colorSpace should include |
62 | | a description of the transfer function as |
63 | | well (e.g., SkColorSpace::MakeSRGB()). |
64 | | @param origin Whether the Texture logically treats the origin as TopLeft or |
65 | | BottomLeft |
66 | | @param generateMipmapsFromBase If kYes then the pixel contents of the textures upper mipmap |
67 | | levels are generated by successive downsampling of the base |
68 | | level. If the texture is not mipmapped or isn't renderable then |
69 | | image creation will fail. If kNo and the texture is mipmapped |
70 | | then the contents of upper levels are assumed to already be |
71 | | valid. |
72 | | @return created SkImage, or nullptr |
73 | | */ |
74 | | SK_API sk_sp<SkImage> WrapTexture(skgpu::graphite::Recorder*, |
75 | | const skgpu::graphite::BackendTexture&, |
76 | | SkColorType colorType, |
77 | | SkAlphaType alphaType, |
78 | | sk_sp<SkColorSpace> colorSpace, |
79 | | skgpu::Origin origin, |
80 | | GenerateMipmapsFromBase generateMipmapsFromBase, |
81 | | TextureReleaseProc = nullptr, |
82 | | ReleaseContext = nullptr); |
83 | | |
84 | | SK_API sk_sp<SkImage> WrapTexture(skgpu::graphite::Recorder*, |
85 | | const skgpu::graphite::BackendTexture&, |
86 | | SkColorType colorType, |
87 | | SkAlphaType alphaType, |
88 | | sk_sp<SkColorSpace> colorSpace, |
89 | | skgpu::Origin origin, |
90 | | TextureReleaseProc = nullptr, |
91 | | ReleaseContext = nullptr); |
92 | | |
93 | | SK_API sk_sp<SkImage> WrapTexture(skgpu::graphite::Recorder*, |
94 | | const skgpu::graphite::BackendTexture&, |
95 | | SkColorType colorType, |
96 | | SkAlphaType alphaType, |
97 | | sk_sp<SkColorSpace> colorSpace, |
98 | | TextureReleaseProc = nullptr, |
99 | | ReleaseContext = nullptr); |
100 | | |
101 | | #if !defined(SK_DISABLE_LEGACY_GRAPHITE_IMAGES) |
102 | | inline sk_sp<SkImage> AdoptTextureFrom(skgpu::graphite::Recorder* recorder, |
103 | | const skgpu::graphite::BackendTexture& tex, |
104 | | SkColorType colorType, |
105 | | SkAlphaType alphaType, |
106 | | sk_sp<SkColorSpace> colorSpace, |
107 | | skgpu::Origin origin, |
108 | | TextureReleaseProc trProc = nullptr, |
109 | 0 | ReleaseContext ctx = nullptr) { |
110 | 0 | return WrapTexture(recorder, tex, colorType, alphaType, colorSpace, origin, trProc, ctx); |
111 | 0 | } |
112 | | |
113 | | inline sk_sp<SkImage> AdoptTextureFrom(skgpu::graphite::Recorder* recorder, |
114 | | const skgpu::graphite::BackendTexture& tex, |
115 | | SkColorType colorType, |
116 | | SkAlphaType alphaType, |
117 | | sk_sp<SkColorSpace> colorSpace, |
118 | | TextureReleaseProc trProc = nullptr, |
119 | 0 | ReleaseContext ctx = nullptr) { |
120 | 0 | return WrapTexture(recorder, tex, colorType, alphaType, colorSpace, trProc, ctx); |
121 | 0 | } |
122 | | #endif |
123 | | |
124 | | /** Create a new SkImage that is very similar to an SkImage created by WrapTexture. The difference |
125 | | is that the caller need not have created the backend texture nor populated it with data when |
126 | | creating the image. Instead of passing a BackendTexture to the factory the client supplies a |
127 | | description of the texture consisting of dimensions, TextureInfo, SkColorInfo and Volatility. |
128 | | |
129 | | In general, 'fulfill' must return a BackendTexture that matches the properties provided at |
130 | | SkImage creation time. The BackendTexture must refer to a valid existing texture in the backend |
131 | | API context/device, and already be populated with data. The texture cannot be deleted until |
132 | | 'textureRelease' is called. 'textureRelease' will be called with the textureReleaseContext |
133 | | returned by 'fulfill'. |
134 | | |
135 | | Wrt when and how often the fulfill, imageRelease, and textureRelease callbacks will be called: |
136 | | |
137 | | For non-volatile promise images, 'fulfill' will be called at Context::insertRecording time. |
138 | | Regardless of whether 'fulfill' succeeded or failed, 'imageRelease' will always be called only |
139 | | once - when Skia will no longer try calling 'fulfill' to get a backend texture. If 'fulfill' |
140 | | failed (i.e., it didn't return a valid backend texture) then 'textureRelease' will never be |
141 | | called. If 'fulfill' was successful then 'textureRelease' will be called only once when the GPU |
142 | | is done with the contents of the promise image. This will usually occur during a Context::submit |
143 | | call but it could occur earlier due to error conditions. 'fulfill' can be called multiple times |
144 | | if the promise image is used in multiple recordings. If 'fulfill' fails, the insertRecording |
145 | | itself will fail. Subsequent insertRecording calls (with Recordings that use the promise image) |
146 | | will keep calling 'fulfill' until it succeeds. |
147 | | |
148 | | For volatile promise images, 'fulfill' will be called each time the Recording is inserted into a |
149 | | Context. Regardless of whether 'fulfill' succeeded or failed, 'imageRelease' will always be |
150 | | called only once just like the non-volatile case. If 'fulfill' fails at insertRecording-time, |
151 | | 'textureRelease' will never be called. If 'fulfill' was successful then a 'textureRelease' |
152 | | matching that 'fulfill' will be called when the GPU is done with the contents of the promise |
153 | | image. This will usually occur during a Context::submit call but it could occur earlier due to |
154 | | error conditions. |
155 | | |
156 | | @param recorder the recorder that will capture the commands creating the image |
157 | | @param dimensions width & height of promised gpu texture |
158 | | @param textureInfo structural information for the promised gpu texture |
159 | | @param colorInfo color type, alpha type and colorSpace information for the image |
160 | | @param origin Whether the Texture logically treats the origin as TopLeft or BottomLeft |
161 | | @param isVolatile volatility of the promise image |
162 | | @param fulfill function called to get the actual backend texture, |
163 | | and the instance for the GraphitePromiseTextureReleaseProc |
164 | | @param imageRelease function called when any image-centric data can be deleted |
165 | | @param textureRelease function called when the backend texture can be deleted |
166 | | @param imageContext state passed to fulfill and imageRelease |
167 | | @return created SkImage, or nullptr |
168 | | */ |
169 | | SK_API sk_sp<SkImage> PromiseTextureFrom(skgpu::graphite::Recorder*, |
170 | | SkISize dimensions, |
171 | | const skgpu::graphite::TextureInfo&, |
172 | | const SkColorInfo&, |
173 | | skgpu::Origin origin, |
174 | | skgpu::graphite::Volatile, |
175 | | GraphitePromiseTextureFulfillProc, |
176 | | GraphitePromiseImageReleaseProc, |
177 | | GraphitePromiseTextureReleaseProc, |
178 | | GraphitePromiseImageContext); |
179 | | |
180 | | SK_API sk_sp<SkImage> PromiseTextureFrom(skgpu::graphite::Recorder*, |
181 | | SkISize dimensions, |
182 | | const skgpu::graphite::TextureInfo&, |
183 | | const SkColorInfo&, |
184 | | skgpu::graphite::Volatile, |
185 | | GraphitePromiseTextureFulfillProc, |
186 | | GraphitePromiseImageReleaseProc, |
187 | | GraphitePromiseTextureReleaseProc, |
188 | | GraphitePromiseImageContext); |
189 | | |
190 | | /** This is similar to 'PromiseTextureFrom' but it creates a GPU-backed SkImage from YUV[A] data. |
191 | | The source data may be planar (i.e. spread across multiple textures). In the extreme Y, U, V, |
192 | | and A are all in different planes and thus the image is specified by four textures. |
193 | | 'backendTextureInfo' describes the planar arrangement, texture formats, and conversion to RGB. |
194 | | Separate 'fulfill' and 'textureRelease' calls are made for each texture. Each texture has its |
195 | | own GraphitePromiseFulfillContext. The GraphitePromiseImageReleaseProc will be made even on |
196 | | failure. 'planeContexts' has one entry for each of the up to four textures, as indicated by |
197 | | 'backendTextureInfo'. Currently the mipmapped property of 'backendTextureInfo' is ignored. |
198 | | However, in the near future it will be required that if it is kYes then the fulfillProc must |
199 | | return a mip mapped texture for each plane in order to successfully draw the image. |
200 | | |
201 | | @param recorder the recorder that will capture the commands creating the image |
202 | | @param backendTextureInfo info about the promised yuva gpu texture(s) |
203 | | @param imageColorSpace range of colors; may be nullptr |
204 | | @param isVolatile volatility of the promise image |
205 | | @param fulfill function called to get the actual backend texture for |
206 | | a given GraphitePromiseTextureContext, and the instance |
207 | | for the GraphitePromiseTextureReleaseProc |
208 | | @param imageRelease function called when any image-centric data can be deleted |
209 | | @param textureRelease function called when the backend texture can be deleted |
210 | | @param imageContext state passed to imageRelease |
211 | | @param planeContexts states passed to fulfill for each plane |
212 | | @return created SkImage, or nullptr |
213 | | */ |
214 | | SK_API sk_sp<SkImage> PromiseTextureFromYUVA(skgpu::graphite::Recorder*, |
215 | | const skgpu::graphite::YUVABackendTextureInfo&, |
216 | | sk_sp<SkColorSpace> imageColorSpace, |
217 | | skgpu::graphite::Volatile, |
218 | | GraphitePromiseTextureFulfillProc, |
219 | | GraphitePromiseImageReleaseProc, |
220 | | GraphitePromiseTextureReleaseProc, |
221 | | GraphitePromiseImageContext imageContext, |
222 | | GraphitePromiseTextureFulfillContext planeContexts[]); |
223 | | |
224 | | |
225 | | /** Returns an SkImage backed by a Graphite texture, using the provided Recorder for creation and |
226 | | uploads if necessary. The returned SkImage respects the required image properties' mipmap |
227 | | setting for non-Graphite SkImages; i.e., if mipmapping is required, the backing Graphite texture |
228 | | will have allocated mip map levels. |
229 | | |
230 | | It is assumed that MIP maps are always supported by the GPU. |
231 | | |
232 | | Returns original SkImage if the image is already Graphite-backed and the required mipmapping is |
233 | | compatible with the backing Graphite texture. If the required mipmapping is not compatible, |
234 | | nullptr will be returned. |
235 | | |
236 | | Returns nullptr if no Recorder is provided, or if SkImage was created with another Recorder and |
237 | | work on that Recorder has not been submitted. |
238 | | |
239 | | @param Recorder the Recorder to use for storing commands |
240 | | @param RequiredProperties properties the returned SkImage must possess (e.g. mipmaps) |
241 | | @return created SkImage, or nullptr |
242 | | */ |
243 | | SK_API sk_sp<SkImage> TextureFromImage(skgpu::graphite::Recorder*, |
244 | | const SkImage*, |
245 | | SkImage::RequiredProperties = {}); |
246 | | |
247 | | inline sk_sp<SkImage> TextureFromImage(skgpu::graphite::Recorder* r, |
248 | | const sk_sp<const SkImage>& img, |
249 | 0 | SkImage::RequiredProperties props = {}) { |
250 | 0 | return TextureFromImage(r, img.get(), props); |
251 | 0 | } |
252 | | |
253 | | /** Creates SkImage from SkYUVAPixmaps. |
254 | | |
255 | | The image will remain planar with each plane converted to a texture using the passed Recorder. |
256 | | |
257 | | SkYUVAPixmaps has a SkYUVAInfo which specifies the transformation from YUV to RGB. The |
258 | | SkColorSpace of the resulting RGB values is specified by imgColorSpace. This will be the |
259 | | SkColorSpace reported by the image and when drawn the RGB values will be converted from this |
260 | | space into the destination space (if the destination is tagged). |
261 | | |
262 | | This is only supported using the GPU backend and will fail if recorder is nullptr. |
263 | | |
264 | | SkYUVAPixmaps does not need to remain valid after this returns. |
265 | | |
266 | | @param Recorder The Recorder to use for storing commands |
267 | | @param pixmaps The planes as pixmaps with supported SkYUVAInfo that |
268 | | specifies conversion to RGB. |
269 | | @param RequiredProperties Properties the returned SkImage must possess (e.g. mipmaps) |
270 | | @param limitToMaxTextureSize Downscale image to GPU maximum texture size, if necessary |
271 | | @param imgColorSpace Range of colors of the resulting image; may be nullptr |
272 | | @return Created SkImage, or nullptr |
273 | | */ |
274 | | SK_API sk_sp<SkImage> TextureFromYUVAPixmaps(skgpu::graphite::Recorder*, |
275 | | const SkYUVAPixmaps& pixmaps, |
276 | | SkImage::RequiredProperties = {}, |
277 | | bool limitToMaxTextureSize = false, |
278 | | sk_sp<SkColorSpace> imgColorSpace = nullptr); |
279 | | |
280 | | /** Creates an SkImage from YUV[A] planar textures associated with the recorder. |
281 | | @param recorder The recorder. |
282 | | @param yuvaBackendTextures A set of textures containing YUVA data and a description of the |
283 | | data and transformation to RGBA. |
284 | | @param imageColorSpace range of colors of the resulting image after conversion to RGB; |
285 | | may be nullptr |
286 | | @param TextureReleaseProc called when the backend textures can be released |
287 | | @param ReleaseContext state passed to TextureReleaseProc |
288 | | @return created SkImage, or nullptr |
289 | | */ |
290 | | SK_API sk_sp<SkImage> TextureFromYUVATextures( |
291 | | skgpu::graphite::Recorder* recorder, |
292 | | const skgpu::graphite::YUVABackendTextures& yuvaBackendTextures, |
293 | | sk_sp<SkColorSpace> imageColorSpace, |
294 | | TextureReleaseProc = nullptr, |
295 | | ReleaseContext = nullptr); |
296 | | |
297 | | /** Creates an SkImage from YUV[A] planar SkImages associated with the recorder. |
298 | | |
299 | | The images should have kGraphite type, and the result will be nullptr if any are not. The |
300 | | resulting SkImage will not take a ref on the given SkImages but will take a ref on the |
301 | | underlying TextureProxies. The releaseProcs, if any, for those Textures will be the ones set |
302 | | when the given SkImages were created. |
303 | | |
304 | | @param recorder The recorder. |
305 | | @param yuvaInfo Structure describing the YUVA format |
306 | | @param images A set of SkImages containing YUVA data |
307 | | @param imageColorSpace Range of colors of the resulting image after conversion to RGB; |
308 | | may be nullptr |
309 | | @return created SkImage, or nullptr |
310 | | */ |
311 | | SK_API sk_sp<SkImage> TextureFromYUVAImages( |
312 | | skgpu::graphite::Recorder* recorder, |
313 | | const SkYUVAInfo& yuvaInfo, |
314 | | SkSpan<const sk_sp<SkImage>> images, |
315 | | sk_sp<SkColorSpace> imageColorSpace); |
316 | | |
317 | | /** Returns subset of this image as a texture-backed image. |
318 | | |
319 | | Returns nullptr if any of the following are true: |
320 | | - Subset is empty |
321 | | - Subset is not contained inside the image's bounds |
322 | | - Pixels in the source image could not be read or copied |
323 | | - The source image is texture-backed and context does not match the source image's context. |
324 | | |
325 | | @param recorder the non-null recorder in which to create the new image. |
326 | | @param img Source image |
327 | | @param subset bounds of returned SkImage |
328 | | @param props properties the returned SkImage must possess (e.g. mipmaps) |
329 | | @return the subsetted image, uploaded as a texture, or nullptr |
330 | | */ |
331 | | SK_API sk_sp<SkImage> SubsetTextureFrom(skgpu::graphite::Recorder* recorder, |
332 | | const SkImage* img, |
333 | | const SkIRect& subset, |
334 | | SkImage::RequiredProperties props = {}); |
335 | | |
336 | | /** Creates a filtered SkImage on the GPU. filter processes the src image, potentially changing |
337 | | color, position, and size. subset is the bounds of src that are processed by filter. clipBounds |
338 | | is the expected bounds of the filtered SkImage. outSubset is required storage for the actual |
339 | | bounds of the filtered SkImage. offset is required storage for translation of returned SkImage. |
340 | | |
341 | | Returns nullptr if SkImage could not be created. If nullptr is returned, outSubset and offset |
342 | | are undefined. |
343 | | |
344 | | Useful for animation of SkImageFilter that varies size from frame to frame. Returned SkImage is |
345 | | created larger than required by filter so that GPU texture can be reused with different sized |
346 | | effects. outSubset describes the valid bounds of GPU texture returned. offset translates the |
347 | | returned SkImage to keep subsequent animation frames aligned with respect to each other. |
348 | | |
349 | | @param recorder the recorder in which the filtering operation is to be performed |
350 | | @param filter how SkImage is sampled when transformed |
351 | | @param subset bounds of SkImage processed by filter |
352 | | @param clipBounds expected bounds of filtered SkImage |
353 | | @param outSubset storage for returned SkImage bounds |
354 | | @param offset storage for returned SkImage translation |
355 | | @return filtered SkImage, or nullptr |
356 | | */ |
357 | | SK_API sk_sp<SkImage> MakeWithFilter(skgpu::graphite::Recorder* recorder, |
358 | | sk_sp<SkImage> src, |
359 | | const SkImageFilter* filter, |
360 | | const SkIRect& subset, |
361 | | const SkIRect& clipBounds, |
362 | | SkIRect* outSubset, |
363 | | SkIPoint* offset); |
364 | | |
365 | | } // namespace SkImages |
366 | | |
367 | | |
368 | | #endif // skgpu_graphite_Image_DEFINED |