skia_safe/gpu/ganesh/
surface_ganesh.rs

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