fermium/
surface.rs

1//! Module for SDL's in-memory bitmap type.
2
3use crate::{
4  blendmode::*, c_char, c_int, c_void, pixels::*, rect::*, rwops::*, stdinc::*,
5};
6
7// makes rustdoc link properly!
8#[allow(unused)]
9use crate::error::*;
10
11/// Surface uses preallocated memory
12pub const SDL_PREALLOC: u32 = 0x00000001;
13/// Surface is RLE encoded
14pub const SDL_RLEACCEL: u32 = 0x00000002;
15/// Surface is referenced internally
16pub const SDL_DONTFREE: u32 = 0x00000004;
17/// Surface uses aligned memory
18pub const SDL_SIMD_ALIGNED: u32 = 0x00000008;
19
20/// Checks if an [`SDL_Surface`] must be locked before the pixels are accessed
21/// directly.
22#[inline]
23#[must_use]
24pub unsafe fn SDL_MUSTLOCK(s: *const SDL_Surface) -> bool {
25  ((*s).flags & SDL_RLEACCEL) != 0
26}
27
28/// A newtype'd `c_void`.
29#[allow(unused)]
30#[repr(transparent)]
31pub struct SDL_BlitMap(c_void);
32
33/// Represents a bitmap image in CPU memory.
34///
35/// Generally, you should not touch these fields yourself.
36#[derive(Debug)]
37#[repr(C)]
38#[allow(missing_docs)]
39pub struct SDL_Surface {
40  /// Read-only
41  pub flags: Uint32,
42  /// Read-only
43  pub format: *mut SDL_PixelFormat,
44  /// Read-only
45  pub w: c_int,
46  /// Read-only
47  pub h: c_int,
48  /// Read-only
49  pub pitch: c_int,
50  /// Read-write
51  pub pixels: *mut c_void,
52  /// Application data associated with the surface, Read-write
53  pub userdata: *mut c_void,
54  /// information needed for surfaces requiring locks, Read-only
55  pub locked: c_int,
56  /// list of BlitMap that hold a reference to this surface, Private
57  pub list_blitmap: *mut c_void,
58  /// clipping information, Read-only
59  pub clip_rect: SDL_Rect,
60  /// info for fast blit mapping to other surfaces, Private
61  pub map: *mut SDL_BlitMap,
62  /// Reference count -- used when freeing surface, Read-mostly
63  pub refcount: c_int,
64}
65
66/// The formula used for converting between YUV and RGB.
67#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
68#[repr(transparent)]
69pub struct SDL_YUV_CONVERSION_MODE(pub u32);
70/// Full range JPEG
71pub const SDL_YUV_CONVERSION_JPEG: SDL_YUV_CONVERSION_MODE =
72  SDL_YUV_CONVERSION_MODE(0);
73/// BT.601 (the default)
74pub const SDL_YUV_CONVERSION_BT601: SDL_YUV_CONVERSION_MODE =
75  SDL_YUV_CONVERSION_MODE(1);
76/// BT.709
77pub const SDL_YUV_CONVERSION_BT709: SDL_YUV_CONVERSION_MODE =
78  SDL_YUV_CONVERSION_MODE(2);
79/// BT.601 for SD content, BT.709 for HD content
80pub const SDL_YUV_CONVERSION_AUTOMATIC: SDL_YUV_CONVERSION_MODE =
81  SDL_YUV_CONVERSION_MODE(3);
82
83/// Given a file path to a BMP file, load and parse it into an [`SDL_Surface`]
84/// as one step.
85///
86/// **Return:** As [`SDL_LoadBMP_RW`]: the new surface, or NULL if there was an
87/// error.
88#[inline]
89pub unsafe fn SDL_LoadBMP(file: *const c_char) -> *mut SDL_Surface {
90  SDL_LoadBMP_RW(SDL_RWFromFile(file, b"rb\0".as_ptr().cast()), 1)
91}
92
93/// Save an [`SDL_Surface`] to the file path specified.
94///
95/// **Return:** As [`SDL_SaveBMP_RW`]: 0 if successful or -1 if there was an
96/// error.
97#[inline]
98pub unsafe fn SDL_SaveBMP(
99  surface: *mut SDL_Surface, file: *const c_char,
100) -> c_int {
101  SDL_SaveBMP_RW(surface, SDL_RWFromFile(file, b"wb\0".as_ptr().cast()), 1)
102}
103
104extern "C" {
105  /// Allocate a new RGB surface.
106  ///
107  /// If the depth is 4 or 8 bits, an empty palette is allocated for the
108  /// surface. If the depth is greater than 8 bits, the pixel format is set
109  /// using the flags `[RGB]mask`.
110  ///
111  /// If the function runs out of memory, it will return NULL.
112  ///
113  /// * `flags`: The `flags` are obsolete and should be set to 0.
114  /// * `width`: The width in pixels of the surface to create.
115  /// * `height`: The height in pixels of the surface to create.
116  /// * `depth`: The depth in bits of the surface to create.
117  /// * `Rmask`: The red mask of the surface to create.
118  /// * `Gmask`: The green mask of the surface to create.
119  /// * `Bmask`: The blue mask of the surface to create.
120  /// * `Amask`: The alpha mask of the surface to create.
121  ///
122  /// **Return:** A new [`SDL_Surface`], or NULL on error (call
123  /// [`SDL_GetErrorMsg`] for more info).
124  ///
125  /// **Note:** This actually uses [`SDL_MasksToPixelFormatEnum`] to determine a
126  /// pixel format enum value, and then calls
127  /// [`SDL_CreateRGBSurfaceWithFormat`]. If you already know the pixel format
128  /// enum value, then you can use that function directly.
129  pub fn SDL_CreateRGBSurface(
130    flags: Uint32, width: c_int, height: c_int, depth: c_int, Rmask: Uint32,
131    Gmask: Uint32, Bmask: Uint32, Amask: Uint32,
132  ) -> *mut SDL_Surface;
133
134  /// Similar to [`SDL_CreateRGBSurface`], but using a pixel format enum value.
135  pub fn SDL_CreateRGBSurfaceWithFormat(
136    flags: Uint32, width: c_int, height: c_int, depth: c_int, format: Uint32,
137  ) -> *mut SDL_Surface;
138
139  /// Makes a surface from a pre-allocated buffer.
140  ///
141  /// The surface depends on the pixels allocation for its lifetime, but has the
142  /// `PRE_ALLOC` flag so it won't free the pixels on its own. In other words,
143  /// this works like a borrow rather than like an ownership transfer.
144  pub fn SDL_CreateRGBSurfaceFrom(
145    pixels: *mut c_void, width: c_int, height: c_int, depth: c_int,
146    pitch: c_int, Rmask: Uint32, Gmask: Uint32, Bmask: Uint32, Amask: Uint32,
147  ) -> *mut SDL_Surface;
148
149  /// Makes a surface from a pre-allocated buffer in a specified format.
150  ///
151  /// This is like a combination of [`SDL_CreateRGBSurfaceWithFormat`] and
152  /// [`SDL_CreateRGBSurfaceFrom`].
153  pub fn SDL_CreateRGBSurfaceWithFormatFrom(
154    pixels: *mut c_void, width: c_int, height: c_int, depth: c_int,
155    pitch: c_int, format: Uint32,
156  ) -> *mut SDL_Surface;
157
158  /// Frees the surface.
159  ///
160  /// This doesn't necessarily free any memory. Surfaces use ref counting for
161  /// some things, and this will only actually free the memory if the ref count
162  /// goes to 0. Also, they can be formed using borrowed memory, and in that
163  /// case freeing the surface will not free the borrowed pixel memory itself.
164  pub fn SDL_FreeSurface(surface: *mut SDL_Surface);
165
166  /// Set the palette used by a surface.
167  ///
168  /// A single palette can be shared with many surfaces.
169  ///
170  /// **Return:** 0, or -1 if the surface format doesn't use a palette.
171  pub fn SDL_SetSurfacePalette(
172    surface: *mut SDL_Surface, palette: *mut SDL_Palette,
173  ) -> c_int;
174
175  /// Sets up a surface for directly accessing the pixels.
176  ///
177  /// Between calls to [`SDL_LockSurface`] / [`SDL_UnlockSurface`], you can
178  /// write to and read from `surface->pixels`, using the pixel format stored
179  /// in `surface->format`.  Once you are done accessing the surface, you
180  /// should use [`SDL_UnlockSurface`] to release it.
181  ///
182  /// Not all surfaces require locking.  If
183  /// [`SDL_MUSTLOCK(surface)`](SDL_MUSTLOCK) evaluates to 0, then you can
184  /// read and write to the surface at any time, and the pixel format of the
185  /// surface will not change.
186  ///
187  /// No operating system or library calls should be made between lock/unlock
188  /// pairs, as critical system locks may be held during this time.
189  ///
190  /// [`SDL_LockSurface`] returns 0, or -1 if the surface couldn't be locked.
191  pub fn SDL_LockSurface(surface: *mut SDL_Surface) -> c_int;
192
193  /// See [`SDL_LockSurface`]
194  pub fn SDL_UnlockSurface(surface: *mut SDL_Surface);
195
196  /// Load a surface from a seekable SDL data stream (memory or file).
197  ///
198  /// If `freesrc` is non-zero, the stream will be closed after being read.
199  ///
200  /// The new surface should be freed with [`SDL_FreeSurface`].
201  ///
202  /// **Return:** the new surface, or NULL if there was an error.
203  pub fn SDL_LoadBMP_RW(
204    src: *mut SDL_RWops, freesrc: c_int,
205  ) -> *mut SDL_Surface;
206
207  /// Save a surface to a seekable SDL data stream (memory or file).
208  ///
209  /// Surfaces with a 24-bit, 32-bit and paletted 8-bit format get saved in the
210  /// BMP directly. Other RGB formats with 8-bit or higher get converted to a
211  /// 24-bit surface or, if they have an alpha mask or a colorkey, to a 32-bit
212  /// surface before they are saved. YUV and paletted 1-bit and 4-bit formats
213  /// are not supported.
214  ///
215  /// If `freedst` is non-zero, the stream will be closed after being written.
216  ///
217  /// **Return:** 0 if successful or -1 if there was an error.
218  pub fn SDL_SaveBMP_RW(
219    surface: *mut SDL_Surface, dst: *mut SDL_RWops, freedst: c_int,
220  ) -> c_int;
221
222  /// Sets the RLE acceleration hint for a surface.
223  ///
224  /// If RLE is enabled, colorkey and alpha blending blits are much faster,
225  /// but the surface must be locked before directly accessing the pixels.
226  ///
227  /// **Return:** 0 on success, or -1 if the surface is not valid
228  pub fn SDL_SetSurfaceRLE(surface: *mut SDL_Surface, flag: c_int) -> c_int;
229
230  /// Returns whether the surface is RLE enabled
231  ///
232  /// **Returns:** `SDL_TRUE` if the surface is RLE enabled, or `SDL_FALSE` if
233  /// the surface is `NULL` or not RLE enabled
234  pub fn SDL_HasSurfaceRLE(surface: *mut SDL_Surface) -> SDL_bool;
235
236  /// Sets the color key (transparent pixel) in a blit-able surface.
237  ///
238  /// You can pass [`SDL_RLEACCEL`] to enable RLE accelerated blits.
239  ///
240  /// * `surface`: The surface to update
241  /// * `flag`: Non-zero to enable colorkey and 0 to disable colorkey
242  /// * `key`: The transparent pixel in the native surface format
243  ///
244  /// **Return:** 0 on success, or -1 if the surface is not valid
245  pub fn SDL_SetColorKey(
246    surface: *mut SDL_Surface, flag: c_int, key: Uint32,
247  ) -> c_int;
248
249  /// Returns whether the surface has a color key
250  ///
251  /// **Return:** `SDL_TRUE` if the surface has a color key, or `SDL_FALSE` if
252  /// the surface is NULL or has no color key
253  pub fn SDL_HasColorKey(surface: *mut SDL_Surface) -> SDL_bool;
254
255  /// Gets the color key (transparent pixel) in a blit-able surface.
256  ///
257  /// * `surface`: The surface to update
258  /// * `key`: A pointer filled in with the transparent pixel in the native
259  ///   surface format
260  ///
261  /// **Return:** 0 on success, or -1 if the surface is not valid or colorkey is
262  /// not enabled.
263  pub fn SDL_GetColorKey(surface: *mut SDL_Surface, key: *mut Uint32) -> c_int;
264
265  /// Set an additional color value used in blit operations.
266  ///
267  /// * `surface`: The surface to update.
268  /// * `r`: The red color value multiplied into blit operations.
269  /// * `g`: The green color value multiplied into blit operations.
270  /// * `b`: The blue color value multiplied into blit operations.
271  ///
272  /// **Return:** 0 on success, or -1 if the surface is not valid.
273  pub fn SDL_SetSurfaceColorMod(
274    surface: *mut SDL_Surface, r: Uint8, g: Uint8, b: Uint8,
275  ) -> c_int;
276
277  /// Get the additional color value used in blit operations.
278  ///
279  /// * `surface`: The surface to query.
280  /// * `r`: A pointer filled in with the current red color value.
281  /// * `g`: A pointer filled in with the current green color value.
282  /// * `b`: A pointer filled in with the current blue color value.
283  ///
284  /// **Return:** 0 on success, or -1 if the surface is not valid.
285  pub fn SDL_GetSurfaceColorMod(
286    surface: *mut SDL_Surface, r: *mut Uint8, g: *mut Uint8, b: *mut Uint8,
287  ) -> c_int;
288
289  /// Get the additional alpha value used in blit operations.
290  ///
291  /// * `surface`: The surface to query.
292  /// * `alpha`: A pointer filled in with the current alpha value.
293  ///
294  /// **Return:** 0 on success, or -1 if the surface is not valid.
295  pub fn SDL_SetSurfaceAlphaMod(
296    surface: *mut SDL_Surface, alpha: Uint8,
297  ) -> c_int;
298
299  /// Set the blend mode used for blit operations.
300  ///
301  /// * `surface`: The surface to update.
302  /// * `blendMode`: [`SDL_BlendMode`] to use for blit blending.
303  ///
304  /// **Return:** 0 on success, or -1 if the parameters are not valid.
305  pub fn SDL_SetSurfaceBlendMode(
306    surface: *mut SDL_Surface, blendMode: SDL_BlendMode,
307  ) -> c_int;
308
309  /// Get the blend mode used for blit operations.
310  ///
311  /// * `surface`:   The surface to query.
312  /// * `blendMode`: A pointer filled in with the current blend mode.
313  ///
314  /// **Return:** 0 on success, or -1 if the surface is not valid.
315  pub fn SDL_GetSurfaceBlendMode(
316    surface: *mut SDL_Surface, blendMode: *mut SDL_BlendMode,
317  ) -> c_int;
318
319  /// Sets the clipping rectangle for the destination surface in a blit.
320  ///
321  /// If the clip rectangle is NULL, clipping will be disabled.
322  ///
323  /// If the clip rectangle doesn't intersect the surface, the function will
324  /// return `SDL_FALSE` and blits will be completely clipped.  Otherwise the
325  /// function returns `SDL_TRUE` and blits to the surface will be clipped to
326  /// the intersection of the surface area and the clipping rectangle.
327  ///
328  /// Note that blits are automatically clipped to the edges of the source
329  /// and destination surfaces.
330  pub fn SDL_SetClipRect(
331    surface: *mut SDL_Surface, rect: *const SDL_Rect,
332  ) -> SDL_bool;
333
334  /// Gets the clipping rectangle for the destination surface in a blit.
335  ///
336  /// `rect` must be a pointer to a valid rectangle which will be filled
337  /// with the correct values.
338  pub fn SDL_GetClipRect(surface: *mut SDL_Surface, rect: *mut SDL_Rect);
339
340  /// Creates a new surface identical to the existing surface
341  pub fn SDL_DuplicateSurface(surface: *mut SDL_Surface) -> *mut SDL_Surface;
342
343  /// Creates a new surface of the specified format, and then copies and maps
344  /// the given surface to it so the blit of the converted surface will be as
345  /// fast as possible.  If this function fails, it returns NULL.
346  ///
347  /// The `flags` parameter is passed to [`SDL_CreateRGBSurface`] and has those
348  /// semantics.  You can also pass [`SDL_RLEACCEL`] in the flags parameter and
349  /// SDL will try to RLE accelerate colorkey and alpha blits in the resulting
350  /// surface.
351  pub fn SDL_ConvertSurface(
352    src: *mut SDL_Surface, fmt: *const SDL_PixelFormat, flags: Uint32,
353  ) -> *mut SDL_Surface;
354
355  /// See [`SDL_ConvertSurface`]
356  pub fn SDL_ConvertSurfaceFormat(
357    src: *mut SDL_Surface, pixel_format: Uint32, flags: Uint32,
358  ) -> *mut SDL_Surface;
359
360  /// Copy a block of pixels of one format to another format
361  ///
362  /// **Return:** 0 on success, or -1 if there was an error
363  pub fn SDL_ConvertPixels(
364    width: c_int, height: c_int, src_format: Uint32, src: *const c_void,
365    src_pitch: c_int, dst_format: Uint32, dst: *mut c_void, dst_pitch: c_int,
366  ) -> c_int;
367
368  /// Performs a fast fill of the given rectangle with `color`.
369  ///
370  /// If `rect` is NULL, the whole surface will be filled with `color`.
371  ///
372  /// The color should be a pixel of the format used by the surface, and
373  /// can be generated by the SDL_MapRGB() function.
374  ///
375  /// **Return:** 0 on success, or -1 on error.
376  pub fn SDL_FillRect(
377    dst: *mut SDL_Surface, rect: *const SDL_Rect, color: Uint32,
378  ) -> c_int;
379
380  /// See [`SDL_FillRect`]
381  pub fn SDL_FillRects(
382    dst: *mut SDL_Surface, rects: *const SDL_Rect, count: c_int, color: Uint32,
383  ) -> c_int;
384
385  /// Performs a fast blit from the source surface to the destination surface.
386  ///
387  /// This assumes that the source and destination rectangles are
388  /// the same size.  If either `srcrect` or `dstrect` are NULL, the entire
389  /// surface (`src` or `dst`) is copied.  The final blit rectangles are saved
390  /// in `srcrect` and `dstrect` after all clipping is performed.
391  ///
392  /// **Return:** If the blit is successful, it returns 0, otherwise it returns
393  /// -1.
394  ///
395  /// The blit function should **not** be called on a locked surface.
396  ///
397  /// The blit semantics for surfaces with and without blending and colorkey
398  /// are defined as follows:
399  /// ```txt
400  /// RGBA->RGB:
401  ///   Source surface blend mode set to SDL_BLENDMODE_BLEND:
402  ///     alpha-blend (using the source alpha-channel and per-surface alpha)
403  ///     SDL_SRCCOLORKEY ignored.
404  ///   Source surface blend mode set to SDL_BLENDMODE_NONE:
405  ///     copy RGB.
406  ///     if SDL_SRCCOLORKEY set, only copy the pixels matching the
407  ///     RGB values of the source color key, ignoring alpha in the
408  ///     comparison.
409  /// RGB->RGBA:
410  ///   Source surface blend mode set to SDL_BLENDMODE_BLEND:
411  ///     alpha-blend (using the source per-surface alpha)
412  ///   Source surface blend mode set to SDL_BLENDMODE_NONE:
413  ///     copy RGB, set destination alpha to source per-surface alpha value.
414  ///   both:
415  ///     if SDL_SRCCOLORKEY set, only copy the pixels matching the
416  ///     source color key.
417  /// RGBA->RGBA:
418  ///   Source surface blend mode set to SDL_BLENDMODE_BLEND:
419  ///     alpha-blend (using the source alpha-channel and per-surface alpha)
420  ///     SDL_SRCCOLORKEY ignored.
421  ///   Source surface blend mode set to SDL_BLENDMODE_NONE:
422  ///     copy all of RGBA to the destination.
423  ///     if SDL_SRCCOLORKEY set, only copy the pixels matching the
424  ///     RGB values of the source color key, ignoring alpha in the
425  ///     comparison.
426  /// RGB->RGB:
427  ///   Source surface blend mode set to SDL_BLENDMODE_BLEND:
428  ///     alpha-blend (using the source per-surface alpha)
429  ///   Source surface blend mode set to SDL_BLENDMODE_NONE:
430  ///     copy RGB.
431  ///   both:
432  ///     if SDL_SRCCOLORKEY set, only copy the pixels matching the
433  ///     source color key.
434  /// ```
435  ///
436  /// You should call [`SDL_BlitSurface`] unless you know exactly how SDL
437  /// blitting works internally and how to use the other blit functions.
438  #[link_name = "SDL_UpperBlit"]
439  pub fn SDL_BlitSurface(
440    src: *mut SDL_Surface, srcrect: *const SDL_Rect, dst: *mut SDL_Surface,
441    dstrect: *mut SDL_Rect,
442  ) -> c_int;
443
444  /// This is the public scaled blit function, SDL_BlitScaled(), and it performs
445  /// rectangle validation and clipping before passing it to
446  /// SDL_LowerBlitScaled()
447  #[link_name = "SDL_UpperBlitScaled"]
448  pub fn SDL_BlitScaled(
449    src: *mut SDL_Surface, srcrect: *const SDL_Rect, dst: *mut SDL_Surface,
450    dstrect: *mut SDL_Rect,
451  ) -> c_int;
452
453  /// Set the YUV conversion mode
454  pub fn SDL_SetYUVConversionMode(mode: SDL_YUV_CONVERSION_MODE);
455
456  /// Get the YUV conversion mode
457  pub fn SDL_GetYUVConversionMode() -> SDL_YUV_CONVERSION_MODE;
458
459  /// Get the YUV conversion mode.
460  ///
461  /// Returns the correct mode for the resolution when the current conversion
462  /// mode is `SDL_YUV_CONVERSION_AUTOMATIC`
463  pub fn SDL_GetYUVConversionModeForResolution(
464    width: c_int, height: c_int,
465  ) -> SDL_YUV_CONVERSION_MODE;
466
467  /// Perform bilinear scaling between two surfaces of the same format, 32BPP.
468  pub fn SDL_SoftStretchLinear(
469    src: *mut SDL_Surface, srcrect: *const SDL_Rect, dst: *mut SDL_Surface,
470    dstrect: *const SDL_Rect,
471  ) -> c_int;
472}