libdragon
Loading...
Searching...
No Matches
Data Structures | Macros | Enumerations | Functions
surface.h File Reference

Surface buffers used to draw images. More...

Go to the source code of this file.

Data Structures

struct  surface_t
 A surface buffer for graphics. More...
 

Macros

#define TEX_FORMAT_BITDEPTH(fmt)   (4 << ((fmt) & 0x3))
 Extract the depth (number of bits per pixel) from a tex_format_t. (eg: FMT_RGBA16 => 16)
 
#define TEX_FORMAT_PIX2BYTES(fmt, pixels)   ((((pixels) << (((fmt) & 3) + 2)) + 7) >> 3)
 Convert the specified number of pixels to bytes.
 
#define TEX_FORMAT_BYTES2PIX(fmt, bytes)   (((bytes) << 1) >> ((fmt) & 3))
 Convert the specified number of bytes to pixels.
 
#define SURFACE_FLAGS_TEXFORMAT   0x001F
 Pixel format of the surface.
 
#define SURFACE_FLAGS_OWNEDBUFFER   0x0020
 Set if the buffer must be freed.
 
#define SURFACE_FLAGS_TEXINDEX   0x0F00
 Placeholder for rdpq lookup table.
 

Enumerations

enum  tex_format_t {
  FMT_NONE = 0 , FMT_RGBA16 = _RDP_FORMAT_CODE(0, 2) , FMT_RGBA32 = _RDP_FORMAT_CODE(0, 3) , FMT_YUV16 = _RDP_FORMAT_CODE(1, 2) ,
  FMT_CI4 = _RDP_FORMAT_CODE(2, 0) , FMT_CI8 = _RDP_FORMAT_CODE(2, 1) , FMT_IA4 = _RDP_FORMAT_CODE(3, 0) , FMT_IA8 = _RDP_FORMAT_CODE(3, 1) ,
  FMT_IA16 = _RDP_FORMAT_CODE(3, 2) , FMT_I4 = _RDP_FORMAT_CODE(4, 0) , FMT_I8 = _RDP_FORMAT_CODE(4, 1)
}
 Pixel format enum. More...
 

Functions

const char * tex_format_name (tex_format_t fmt)
 Return the name of the texture format as a string (for debugging purposes)
 
surface_t surface_make (void *buffer, tex_format_t format, uint16_t width, uint16_t height, uint16_t stride)
 Initialize a surface_t structure with the provided buffer.
 
surface_t surface_make_linear (void *buffer, tex_format_t format, uint16_t width, uint16_t height)
 Initialize a surface_t structure with the provided linear buffer.
 
surface_t surface_alloc (tex_format_t format, uint16_t width, uint16_t height)
 Allocate a new surface in memory.
 
surface_t surface_make_sub (surface_t *parent, uint16_t x0, uint16_t y0, uint16_t width, uint16_t height)
 Initialize a surface_t structure, pointing to a rectangular portion of another surface.
 
void surface_free (surface_t *surface)
 Free the buffer allocated in a surface.
 
tex_format_t surface_get_format (const surface_t *surface)
 Returns the pixel format of a surface.
 
bool surface_has_owned_buffer (const surface_t *surface)
 Checks whether this surface owns the buffer that it contains.
 
surface_t surface_make_placeholder (int index, tex_format_t format, uint16_t width, uint16_t height, uint16_t stride)
 Create a placeholder surface, that can be used during rdpq block recording.
 
surface_t surface_make_placeholder_linear (int index, tex_format_t format, uint16_t width, uint16_t height)
 Create a linear placeholder surface, that can be used during rdpq block recording.
 
int surface_get_placeholder_index (const surface_t *surface)
 Returns the lookup index of a placeholder surface.
 

Detailed Description

Surface buffers used to draw images.

This module implements a structure surface_t which holds the basic information for a buffer of memory to be used for graphics rendering.

A surface is described by the following properties:

surface_t simply represents an aggregation of these properties.

To allocate a new surface, use surface_alloc. Then later, you can release the memory using surface_free.

// Allocate a 64x64 buffer in RGBA 16-bit format
// Draw some text on it (with the CPU)
graphics_draw_text(&buf, 0, 0, "ABC");
void graphics_draw_text(surface_t *disp, int x, int y, const char *const msg)
Draw a null terminated string to a display context.
Definition graphics.c:593
surface_t surface_alloc(tex_format_t format, uint16_t width, uint16_t height)
Allocate a new surface in memory.
Definition surface.c:32
@ FMT_RGBA16
Format RGBA 5551 (16-bit)
Definition surface.h:106
A surface buffer for graphics.
Definition surface.h:138

Sometimes, you might have an existing raw pointer to a buffer and need to pass it to an API that accepts a surface_t. For those cases, you can use surface_make to create a surface_t instance, that you can throw away after you called the function; surface_free does nothing on these surfaces.

In some cases, you might want to interact with a rectangular portion of an existing surface (for instance, you want to draw with RDP only in the top portion of the screen for some reason). To do so, you can use surface_make_sub to create a surface_t instance that is referring only to a portion of the original surface:

surface_t *fb = display_get(); // wait for a framebuffer to be ready
// Attach the RDP to the top 40 rows of the framebuffer
surface_t fbtop = surface_make_sub(fb, 0, 0, 320, 40);
rdpq_attach(&fbtop);
surface_t * display_get(void)
Get a display buffer for rendering.
Definition display.c:326
void rdpq_attach(const surface_t *surf_color, const surface_t *surf_z)
Attach the RDP to a color surface (and optionally a Z buffer)
Definition rdpq_attach.c:76
surface_t surface_make_sub(surface_t *parent, uint16_t x0, uint16_t y0, uint16_t width, uint16_t height)
Initialize a surface_t structure, pointing to a rectangular portion of another surface.
Definition surface.c:57

Surfaces created by surface_make_sub don't need to be freed as they are just references to the parent surface; surface_free does nothing on them.


Data Structure Documentation

◆ surface_t

struct surface_t

A surface buffer for graphics.

This structure holds the basic information about a buffer used to hold graphics. It is commonly used by graphics routines in libdragon as either a source (eg: texture) or a target (eg: framebuffer). It can be used for both CPU-based drawing (such as graphics.h) or RDP-basic drawing (such as rdp.h and rdpq.h).

Use surface_alloc / surface_free to allocate / free a surface. If you already have a memory pointer to a graphics buffer and you just need to wrap it in a surface_t, use surface_make.

Data Fields
uint16_t flags Flags (including pixel format)
uint16_t width Width in pixels.
uint16_t height Height in pixels.
uint16_t stride Stride in bytes (length of a row)
void * buffer Buffer pointer.

Macro Definition Documentation

◆ TEX_FORMAT_BITDEPTH

#define TEX_FORMAT_BITDEPTH (   fmt)    (4 << ((fmt) & 0x3))

Extract the depth (number of bits per pixel) from a tex_format_t. (eg: FMT_RGBA16 => 16)

Note that there are texture format that are 4bpp, so don't divide this by 8 to get the number of bytes per pixels, but rather use TEX_FORMAT_BYTES2PIX and TEX_FORMAT_PIX2BYTES.

◆ TEX_FORMAT_PIX2BYTES

#define TEX_FORMAT_PIX2BYTES (   fmt,
  pixels 
)    ((((pixels) << (((fmt) & 3) + 2)) + 7) >> 3)

Convert the specified number of pixels to bytes.

Note
This macro rounds up the value. For 4bpp surfaces, this means that it returns the safe number of bytes that can hold the specified number of pixels. For instance, TEX_FORMAT_PIX2BYTES(FMT_CI4, 3) returns 2, as you need 2 bytes to store 3 pixels in 4bpp format (even though the last byte is only half used).

◆ TEX_FORMAT_BYTES2PIX

#define TEX_FORMAT_BYTES2PIX (   fmt,
  bytes 
)    (((bytes) << 1) >> ((fmt) & 3))

Convert the specified number of bytes to pixels.

Note
This macro rounds down the value. For instance, for a 32-bpp surface, calling TEX_FORMAT_BYTES2PIX(FMT_RGBA32, 5) returns 1, because you can safely store at maximum 1 32bpp pixel in 5 bytes.

Enumeration Type Documentation

◆ tex_format_t

Pixel format enum.

This enum defines the pixel formats that can be used for surface_t buffers. The list corresponds to the pixel formats that the RDP can use as textures.

Note
Some of these formats can be used by RDP as framebuffer (specifically, FMT_RGBA16, FMT_RGBA32 and FMT_CI8).
Warning
the CPU-based graphics library graphics.h only accepts surfaces in either FMT_RGBA16 or FMT_RGBA32 as target buffers, and does not assert.
Enumerator
FMT_NONE 

Placeholder for no format defined.

FMT_RGBA16 

Format RGBA 5551 (16-bit)

FMT_RGBA32 

Format RGBA 8888 (32-bit)

FMT_YUV16 

Format YUV2 4:2:2 (data interleaved as YUYV)

FMT_CI4 

Format CI4: color index 4-bit (paletted, 2 indices per byte)

FMT_CI8 

Format CI8: color index 8-bit (paletted, 1 index per byte)

FMT_IA4 

Format IA4: 3-bit intensity + 1-bit alpha (4-bit per pixel)

FMT_IA8 

Format IA8: 4-bit intensity + 4-bit alpha (8-bit per pixel)

FMT_IA16 

Format IA16: 8-bit intensity + 8-bit alpha (16-bit per pixel)

FMT_I4 

Format I4: 4-bit intensity (4-bit per pixel)

FMT_I8 

Format I8: 8-bit intensity (8-bit per pixel)

Function Documentation

◆ surface_make()

surface_t surface_make ( void *  buffer,
tex_format_t  format,
uint16_t  width,
uint16_t  height,
uint16_t  stride 
)
inline

Initialize a surface_t structure with the provided buffer.

This functions initializes a surface_t structure with the provided buffer and information. It is just a helper to fill the structure fields.

It is not necessary to call surface_free on surfaces created by surface_make as there is nothing to free: the provided buffer will not be owned by the structure, so it is up to the caller to handle its lifetime.

If you plan to use this format as RDP framebuffer, make sure that the provided buffer respects the required alignment of 64 bytes, otherwise rdpq_attach will fail.

Parameters
[in]bufferPointer to the memory buffer
[in]formatPixel format
[in]widthWidth in pixels
[in]heightHeight in pixels
[in]strideStride in bytes (length of a row)
Returns
The initialized surface
See also
surface_make_linear

◆ surface_make_linear()

surface_t surface_make_linear ( void *  buffer,
tex_format_t  format,
uint16_t  width,
uint16_t  height 
)
inline

Initialize a surface_t structure with the provided linear buffer.

This function is similar to surface_make, but it works for images that are linearly mapped with no per-line padding or extraneous data.

Compared to surface_make, it does not accept a stride parameter, and calculate the stride from the width and the pixel format.

Parameters
[in]bufferPointer to the memory buffer
[in]formatPixel format
[in]widthWidth in pixels
[in]heightHeight in pixels
Returns
The initialized surface
See also
surface_make

◆ surface_alloc()

surface_t surface_alloc ( tex_format_t  format,
uint16_t  width,
uint16_t  height 
)

Allocate a new surface in memory.

This function allocates a new surface with the specified pixel format, width and height. The surface must be freed via surface_free when it is not needed anymore.

A surface allocated via surface_alloc can be used as a RDP frame buffer (passed to rdpq_attach) because it is guaranteed to have the required alignment of 64 bytes, provided it is using one of the formats supported by RDP as a framebuffer target (FMT_RGBA32, FMT_RGBA16 or FMT_I8).

Parameters
[in]formatPixel format of the surface
[in]widthWidth in pixels
[in]heightHeight in pixels
Returns
The initialized surface

◆ surface_make_sub()

surface_t surface_make_sub ( surface_t parent,
uint16_t  x0,
uint16_t  y0,
uint16_t  width,
uint16_t  height 
)

Initialize a surface_t structure, pointing to a rectangular portion of another surface.

The surface returned by this function will point to a portion of the buffer of the parent surface, and will have of course the same pixel format.

Parameters
[in]parentParent surface that will be pointed to
[in]x0X coordinate of the top-left corner within the parent surface
[in]y0Y coordinate of the top-left corner within the parent surface
[in]widthWidth of the surface that will be returned
[in]heightHeight of the surface that will be returned
Returns
The initialized surface

◆ surface_free()

void surface_free ( surface_t surface)

Free the buffer allocated in a surface.

This function should be called after a surface allocated via surface_alloc is not needed anymore.

Calling this function on surfaces allocated via surface_make or surface_make_sub (that is, surfaces initialized with an existing buffer pointer) has no effect but clearing the contents of the surface structure.

Parameters
[in]surfaceThe surface to free

◆ surface_get_format()

tex_format_t surface_get_format ( const surface_t surface)
inline

Returns the pixel format of a surface.

Parameters
[in]surfaceSurface
Returns
The pixel format of the provided surface

◆ surface_has_owned_buffer()

bool surface_has_owned_buffer ( const surface_t surface)
inline

Checks whether this surface owns the buffer that it contains.

Parameters
[in]surfaceSurface
Returns
True if this surface owns the buffer; false otherwise

◆ surface_make_placeholder()

surface_t surface_make_placeholder ( int  index,
tex_format_t  format,
uint16_t  width,
uint16_t  height,
uint16_t  stride 
)
inline

Create a placeholder surface, that can be used during rdpq block recording.

When recording a rspq block (via rspq_block_begin / rspq_block_end) it might be useful sometimes to issue draw commands that refer to a surface, but allowing the actual surface to change later at any time.

See rdpq_set_lookup_address for more information.

Note
A placeholder surface holds a NULL pointer to the actual bytes. Make sure not to use it anywhere else but with rdpq.
Parameters
indexIndex that will be used to lookup the surface at playback time
formatPixel format
widthWidth of the surface in pixels
heightHeight of the surface in pixels
strideStride of the surface in bytes
Returns
surface_t The initialized placeholder surface
See also
surface_make_placeholder_linear
rdpq_set_lookup_address

◆ surface_make_placeholder_linear()

surface_t surface_make_placeholder_linear ( int  index,
tex_format_t  format,
uint16_t  width,
uint16_t  height 
)
inline

Create a linear placeholder surface, that can be used during rdpq block recording.

This function is similar to surface_make_placeholder, but it creates a surface that is linearly mapped with no per-line padding or extraneous data. (so the stride is automatically deduced from the width).

Parameters
indexIndex that will be used to lookup the surface at playback time
formatPixel format
widthWidth of the surface in pixels
heightHeight of the surface in pixels
Returns
surface_t The initialized placeholder surface
See also
surface_make_placeholder

◆ surface_get_placeholder_index()

int surface_get_placeholder_index ( const surface_t surface)
inline

Returns the lookup index of a placeholder surface.

If the surface is a placeholder, this function returns the associated lookup index that will be used to retrieve the actual surface at playback time. Otherwise, if it is a normal surface, this function will return 0.

Parameters
surfacePlaceholder surface
Returns
int The lookup index of the placeholder surface, or 0 if it is a normal surface