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 Returns:
27/// [`Surface`] if all parameters are valid; otherwise, `None`
28#[allow(clippy::too_many_arguments)]
29pub 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`
73pub 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`
113pub 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
139pub 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
156pub 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`].
182pub fn resolve_msaa(surface: &mut Surface) {
183 unsafe { sb::C_SkSurfaces_ResolveMSAA(surface:surface.native_mut()) }
184}
185