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