1 | use skia_bindings as sb; |
2 | |
3 | use crate::{gpu, prelude::*, surface::BackendHandleAccess, ImageInfo, Surface, SurfaceProps}; |
4 | |
5 | /// Returns [`Surface`] on GPU indicated by context. Allocates memory for pixels, based on the |
6 | /// width, height, and [`crate::ColorType`] in [`ImageInfo`]. budgeted selects whether allocation |
7 | /// for pixels is tracked by context. `image_info` describes the pixel format in |
8 | /// [`crate::ColorType`], and transparency in [`crate::AlphaType`], and color matching in |
9 | /// [`crate::ColorSpace`]. |
10 | /// |
11 | /// `sample_count` requests the number of samples per pixel. Pass zero to disable multi-sample |
12 | /// anti-aliasing. The request is rounded up to the next supported count, or rounded down if it is |
13 | /// larger than the maximum supported count. |
14 | /// |
15 | /// `surface_origin` pins either the top-left or the bottom-left corner to the origin. |
16 | /// |
17 | /// `should_create_with_mips` hints that [`crate::Image`] returned by [`Surface::image_snapshot`] is |
18 | /// mip map. |
19 | /// |
20 | /// * `context` - GPU context |
21 | /// * `image_info` - width, height, [`crate::ColorType`], [`crate::AlphaType`], |
22 | /// [`crate::ColorSpace`]; width, or height, or both, may be zero |
23 | /// * `sample_count` - samples per pixel, or 0 to disable full scene anti-aliasing |
24 | /// * `surface_props` - LCD striping orientation and setting for device independent fonts; may be |
25 | /// `None` |
26 | /// * `should_create_with_mips` - hint that [`Surface`] will host mip map images Returns: |
27 | /// [`Surface`] if all parameters are valid; otherwise, `None` |
28 | #[allow (clippy::too_many_arguments)] |
29 | pub fn render_target( |
30 | context: &mut gpu::RecordingContext, |
31 | budgeted: gpu::Budgeted, |
32 | image_info: &ImageInfo, |
33 | sample_count: impl Into<Option<usize>>, |
34 | surface_origin: impl Into<Option<gpu::SurfaceOrigin>>, |
35 | surface_props: Option<&SurfaceProps>, |
36 | should_create_with_mips: impl Into<Option<bool>>, |
37 | is_protected: impl Into<Option<bool>>, |
38 | ) -> Option<Surface> { |
39 | Surface::from_ptr(unsafe { |
40 | sb::C_SkSurfaces_RenderTarget( |
41 | context:context.native_mut(), |
42 | budgeted:budgeted.into_native(), |
43 | imageInfo:image_info.native(), |
44 | sampleCount:sample_count.into().unwrap_or(0).try_into().unwrap(), |
45 | surfaceOrigin:surface_origin |
46 | .into() |
47 | .unwrap_or(gpu::SurfaceOrigin::BottomLeft), |
48 | surfaceProps:surface_props.native_ptr_or_null(), |
49 | shouldCreateWithMips:should_create_with_mips.into().unwrap_or(false), |
50 | isProtected:is_protected.into().unwrap_or(false), |
51 | ) |
52 | }) |
53 | } |
54 | |
55 | /// Wraps a GPU-backed texture into [`Surface`]. Caller must ensure the texture is |
56 | /// valid for the lifetime of returned [`Surface`]. If `sample_cnt` greater than zero, |
57 | /// creates an intermediate MSAA [`Surface`] which is used for drawing `backend_texture`. |
58 | /// |
59 | /// [`Surface`] is returned if all parameters are valid. `backend_texture` is valid if |
60 | /// its pixel configuration agrees with `color_space` and context; for instance, if |
61 | /// `backend_texture` has an sRGB configuration, then context must support sRGB, |
62 | /// and `color_space` must be present. Further, `backend_texture` width and height must |
63 | /// not exceed context capabilities, and the context must be able to support |
64 | /// back-end textures. |
65 | /// |
66 | /// * `context` - GPU context |
67 | /// * `backend_texture` - texture residing on GPU |
68 | /// * `sample_cnt` - samples per pixel, or 0 to disable full scene anti-aliasing |
69 | /// * `color_space` - range of colors; may be `None` |
70 | /// * `surface_props` - LCD striping orientation and setting for device independent |
71 | /// fonts; may be `None` |
72 | /// Returns: [`Surface`] if all parameters are valid; otherwise, `None` |
73 | pub fn wrap_backend_texture( |
74 | context: &mut gpu::RecordingContext, |
75 | backend_texture: &gpu::BackendTexture, |
76 | origin: gpu::SurfaceOrigin, |
77 | sample_cnt: impl Into<Option<usize>>, |
78 | color_type: crate::ColorType, |
79 | color_space: impl Into<Option<crate::ColorSpace>>, |
80 | surface_props: Option<&SurfaceProps>, |
81 | ) -> Option<Surface> { |
82 | Surface::from_ptr(unsafe { |
83 | sb::C_SkSurfaces_WrapBackendTexture( |
84 | context:context.native_mut(), |
85 | backendTexture:backend_texture.native(), |
86 | origin, |
87 | sampleCnt:sample_cnt.into().unwrap_or(0).try_into().unwrap(), |
88 | colorType:color_type.into_native(), |
89 | colorSpace:color_space.into().into_ptr_or_null(), |
90 | surfaceProps:surface_props.native_ptr_or_null(), |
91 | ) |
92 | }) |
93 | } |
94 | |
95 | /// Wraps a GPU-backed buffer into [`Surface`]. Caller must ensure `backend_render_target` |
96 | /// is valid for the lifetime of returned [`Surface`]. |
97 | /// |
98 | /// [`Surface`] is returned if all parameters are valid. `backend_render_target` is valid if |
99 | /// its pixel configuration agrees with `color_space` and context; for instance, if |
100 | /// `backend_render_target` has an sRGB configuration, then context must support sRGB, |
101 | /// and `color_space` must be present. Further, `backend_render_target` width and height must |
102 | /// not exceed context capabilities, and the context must be able to support |
103 | /// back-end render targets. |
104 | /// |
105 | /// * `context` - GPU context |
106 | /// * `backend_render_target` - GPU intermediate memory buffer |
107 | /// * `origin` - origin of canvas |
108 | /// * `color_type` - type of colors in the buffer |
109 | /// * `color_space` - range of colors |
110 | /// * `surface_props` - LCD striping orientation and setting for device independent |
111 | /// fonts; may be `None` |
112 | /// Returns: [`Surface`] if all parameters are valid; otherwise, `None` |
113 | pub fn wrap_backend_render_target( |
114 | context: &mut gpu::RecordingContext, |
115 | backend_render_target: &gpu::BackendRenderTarget, |
116 | origin: gpu::SurfaceOrigin, |
117 | color_type: crate::ColorType, |
118 | color_space: impl Into<Option<crate::ColorSpace>>, |
119 | surface_props: Option<&SurfaceProps>, |
120 | ) -> Option<Surface> { |
121 | Surface::from_ptr(unsafe { |
122 | sb::C_SkSurfaces_WrapBackendRenderTarget( |
123 | context:context.native_mut(), |
124 | backendRenderTarget:backend_render_target.native(), |
125 | origin, |
126 | colorType:color_type.into_native(), |
127 | colorSpace:color_space.into().into_ptr_or_null(), |
128 | surfaceProps:surface_props.native_ptr_or_null(), |
129 | ) |
130 | }) |
131 | } |
132 | |
133 | /// Retrieves the back-end texture. If [`Surface`] has no back-end texture, `None` |
134 | /// is returned. |
135 | /// |
136 | /// The returned [`gpu::BackendTexture`] should be discarded if the [`Surface`] is drawn to or deleted. |
137 | /// |
138 | /// Returns: GPU texture reference; `None` on failure |
139 | pub fn get_backend_texture( |
140 | surface: &mut Surface, |
141 | handle_access: BackendHandleAccess, |
142 | ) -> Option<gpu::BackendTexture> { |
143 | unsafe { |
144 | let ptr: *mut GrBackendTexture = sb::C_SkSurfaces_GetBackendTexture(surface:surface.native_mut(), handleAccess:handle_access); |
145 | gpu::BackendTexture::from_native_if_valid(backend_texture:ptr) |
146 | } |
147 | } |
148 | |
149 | /// Retrieves the back-end render target. If [`Surface`] has no back-end render target, `None` |
150 | /// is returned. |
151 | /// |
152 | /// The returned [`gpu::BackendRenderTarget`] should be discarded if the [`Surface`] is drawn to |
153 | /// or deleted. |
154 | /// |
155 | /// Returns: GPU render target reference; `None` on failure |
156 | pub fn get_backend_render_target( |
157 | surface: &mut Surface, |
158 | handle_access: BackendHandleAccess, |
159 | ) -> Option<gpu::BackendRenderTarget> { |
160 | unsafe { |
161 | let mut backend_render_target: GrBackendRenderTarget = construct(|rt: *mut GrBackendRenderTarget| sb::C_GrBackendRenderTarget_Construct(uninitialized:rt)); |
162 | sb::C_SkSurfaces_GetBackendRenderTarget( |
163 | surface:surface.native_mut(), |
164 | handleAccess:handle_access, |
165 | &mut backend_render_target, |
166 | ); |
167 | |
168 | gpu::BackendRenderTarget::from_native_c_if_valid(native:backend_render_target) |
169 | } |
170 | } |
171 | |
172 | /// If a surface is a Ganesh-backed surface, is being drawn with MSAA, and there is a resolve |
173 | /// texture, this call will insert a resolve command into the stream of gpu commands. In order |
174 | /// for the resolve to actually have an effect, the work still needs to be flushed and submitted |
175 | /// to the GPU after recording the resolve command. If a resolve is not supported or the |
176 | /// [`Surface`] has no dirty work to resolve, then this call is a no-op. |
177 | /// |
178 | /// This call is most useful when the [`Surface`] is created by wrapping a single sampled gpu |
179 | /// texture, but asking Skia to render with MSAA. If the client wants to use the wrapped texture |
180 | /// outside of Skia, the only way to trigger a resolve is either to call this command or use |
181 | /// [`gpu::DirectContext::flush`]. |
182 | pub fn resolve_msaa(surface: &mut Surface) { |
183 | unsafe { sb::C_SkSurfaces_ResolveMSAA(surface:surface.native_mut()) } |
184 | } |
185 | |