| 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 |
| 27 | /// |
| 28 | /// Returns: [`Surface`] if all parameters are valid; otherwise, `None` |
| 29 | #[allow (clippy::too_many_arguments)] |
| 30 | pub 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 | imageInfo:image_info.native(), |
| 45 | sampleCount:sample_count.into().unwrap_or(0).try_into().unwrap(), |
| 46 | surfaceOrigin:surface_origin |
| 47 | .into() |
| 48 | .unwrap_or(gpu::SurfaceOrigin::BottomLeft), |
| 49 | surfaceProps:surface_props.native_ptr_or_null(), |
| 50 | shouldCreateWithMips:should_create_with_mips.into().unwrap_or(false), |
| 51 | isProtected: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` |
| 75 | pub 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 | backendTexture:backend_texture.native(), |
| 88 | origin, |
| 89 | sampleCnt:sample_cnt.into().unwrap_or(0).try_into().unwrap(), |
| 90 | colorType:color_type.into_native(), |
| 91 | colorSpace:color_space.into().into_ptr_or_null(), |
| 92 | surfaceProps: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` |
| 116 | pub 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 | backendRenderTarget:backend_render_target.native(), |
| 128 | origin, |
| 129 | colorType:color_type.into_native(), |
| 130 | colorSpace:color_space.into().into_ptr_or_null(), |
| 131 | surfaceProps: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 |
| 142 | pub fn get_backend_texture( |
| 143 | surface: &mut Surface, |
| 144 | handle_access: BackendHandleAccess, |
| 145 | ) -> Option<gpu::BackendTexture> { |
| 146 | unsafe { |
| 147 | let ptr: *mut GrBackendTexture = sb::C_SkSurfaces_GetBackendTexture(surface.native_mut(), handleAccess:handle_access); |
| 148 | gpu::BackendTexture::from_native_if_valid(backend_texture: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 |
| 159 | pub 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: GrBackendRenderTarget = construct(|rt: *mut GrBackendRenderTarget| sb::C_GrBackendRenderTarget_Construct(uninitialized:rt)); |
| 165 | sb::C_SkSurfaces_GetBackendRenderTarget( |
| 166 | surface.native_mut(), |
| 167 | handleAccess:handle_access, |
| 168 | &mut backend_render_target, |
| 169 | ); |
| 170 | |
| 171 | gpu::BackendRenderTarget::from_native_c_if_valid(native: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`]. |
| 185 | pub fn resolve_msaa(surface: &mut Surface) { |
| 186 | unsafe { sb::C_SkSurfaces_ResolveMSAA(surface.native_mut()) } |
| 187 | } |
| 188 | |