libdragon
Modules | Files | Data Structures | Macros | Typedefs | Enumerations | Functions | Variables
Display Subsystem

Video interface system for configuring video output modes and displaying rendered graphics. More...

Modules

 Console Support
 Software console emulation for debugging and simple text output.
 
 2D Graphics
 Software routines for manipulating graphics in a display context.
 
 Hardware Display Interface
 Interface to the hardware sprite/triangle rasterizer (RDP).
 

Files

file  display.c
 Display Subsystem.
 
file  vi.h
 Video Interface Subsystem.
 
file  display.h
 Display Subsystem.
 

Data Structures

struct  vi_config_t
 Video Interface register structure. More...
 
struct  resolution_t
 Video resolution structure. More...
 

Macros

#define VI_REGISTERS_ADDR   0xA4400000
 Register uncached location in memory of VI.
 
#define VI_REGISTERS_COUNT   14
 Number of useful 32-bit registers at the register base.
 
#define VI_REGISTERS   ((volatile uint32_t*)VI_REGISTERS_ADDR)
 Base pointer to hardware Video interface registers that control various aspects of VI configuration. Shouldn't be used by itself, use VI_ registers to get/set their values.
 
#define VI_CTRL   (&VI_REGISTERS[0])
 VI Index register of controlling general display filters/bitdepth configuration.
 
#define VI_ORIGIN   (&VI_REGISTERS[1])
 VI Index register of RDRAM base address of the video output Frame Buffer. This can be changed as needed to implement double or triple buffering.
 
#define VI_WIDTH   (&VI_REGISTERS[2])
 VI Index register of width in pixels of the frame buffer.
 
#define VI_V_INTR   (&VI_REGISTERS[3])
 VI Index register of vertical interrupt.
 
#define VI_V_CURRENT   (&VI_REGISTERS[4])
 VI Index register of the current half line, sampled once per line.
 
#define VI_BURST   (&VI_REGISTERS[5])
 VI Index register of sync/burst values.
 
#define VI_V_SYNC   (&VI_REGISTERS[6])
 VI Index register of total visible and non-visible lines. This should match either NTSC (non-interlaced: 0x20D, interlaced: 0x20C) or PAL (non-interlaced: 0x271, interlaced: 0x270)
 
#define VI_H_SYNC   (&VI_REGISTERS[7])
 VI Index register of total width of a line.
 
#define VI_H_SYNC_LEAP   (&VI_REGISTERS[8])
 VI Index register of an alternate scanline length for one scanline during vsync.
 
#define VI_H_VIDEO   (&VI_REGISTERS[9])
 VI Index register of start/end of the active video image, in screen pixels.
 
#define VI_V_VIDEO   (&VI_REGISTERS[10])
 VI Index register of start/end of the active video image, in screen half-lines.
 
#define VI_V_BURST   (&VI_REGISTERS[11])
 VI Index register of start/end of the color burst enable, in half-lines.
 
#define VI_X_SCALE   (&VI_REGISTERS[12])
 VI Index register of horizontal subpixel offset and 1/horizontal scale up factor.
 
#define VI_Y_SCALE   (&VI_REGISTERS[13])
 VI Index register of vertical subpixel offset and 1/vertical scale up factor.
 
#define VI_TO_REGISTER(index)   (((index) >= 0 && (index) <= VI_REGISTERS_COUNT)? &VI_REGISTERS[index] : NULL)
 VI register by index (0-13)
 
#define VI_TO_INDEX(reg)   ((reg) - VI_REGISTERS)
 VI index from register.
 
#define VI_DEDITHER_FILTER_ENABLE   (1<<16)
 VI_CTRL Register setting: enable dedither filter. More...
 
#define VI_PIXEL_ADVANCE_DEFAULT   (0b0011 << 12)
 VI_CTRL Register setting: default value for pixel advance.
 
#define VI_PIXEL_ADVANCE_BBPLAYER   (0b0001 << 12)
 VI_CTRL Register setting: default value for pixel advance on iQue.
 
#define VI_AA_MODE_NONE   (0b11 << 8)
 VI_CTRL Register setting: disable AA / resamp.
 
#define VI_AA_MODE_RESAMPLE   (0b10 << 8)
 VI_CTRL Register setting: disable AA / enable resamp.
 
#define VI_AA_MODE_RESAMPLE_FETCH_NEEDED   (0b01 << 8)
 VI_CTRL Register setting: enable AA / enable resamp, fetch pixels when needed.
 
#define VI_AA_MODE_RESAMPLE_FETCH_ALWAYS   (0b00 << 8)
 VI_CTRL Register setting: enable AA / enable resamp, fetch pixels always.
 
#define VI_CTRL_SERRATE   (1<<6)
 VI_CTRL Register setting: enable interlaced output.
 
#define VI_DIVOT_ENABLE   (1<<4)
 VI_CTRL Register setting: enable divot filter (fixes 1 pixel holes after AA).
 
#define VI_GAMMA_ENABLE   (1<<3)
 VI_CTRL Register setting: enable gamma correction filter.
 
#define VI_GAMMA_DITHER_ENABLE   (1<<2)
 VI_CTRL Register setting: enable gamma correction filter and hardware dither the least significant color bit on output.
 
#define VI_CTRL_TYPE   (0b11)
 VI_CTRL Register setting: framebuffer source format.
 
#define VI_CTRL_TYPE_32_BPP   (0b11)
 VI_CTRL Register setting: set the framebuffer source as 32-bit.
 
#define VI_CTRL_TYPE_16_BPP   (0b10)
 VI_CTRL Register setting: set the framebuffer source as 16-bit (5-5-5-3).
 
#define VI_CTRL_TYPE_BLANK   (0b00)
 VI_CTRL Register setting: set the framebuffer source as blank (no data and no sync, TV screens will either show static or nothing).
 
#define VI_ORIGIN_SET(value)   ((value & 0xFFFFFF) << 0)
 VI_ORIGIN Register: set the address of a framebuffer. More...
 
#define VI_WIDTH_SET(value)   ((value & 0xFFF) << 0)
 VI_ORIGIN Register: set the width of a framebuffer. More...
 
#define VI_V_CURRENT_VBLANK   2
 VI_V_CURRENT Register: default value for vblank begin line. More...
 
#define VI_V_INTR_SET(value)   ((value & 0x3FF) << 0)
 VI_V_INTR Register: set value for vertical interrupt. More...
 
#define VI_V_INTR_DEFAULT   0x3FF
 VI_V_INTR Register: default value for vertical interrupt.
 
#define VI_BURST_START(value)   ((value & 0x3F) << 20)
 VI_BURST Register: set start of color burst in pixels from hsync. More...
 
#define VI_VSYNC_WIDTH(value)   ((value & 0x7) << 16)
 VI_BURST Register: set vertical sync width in half lines.
 
#define VI_BURST_WIDTH(value)   ((value & 0xFF) << 8)
 VI_BURST Register: set color burst width in pixels.
 
#define VI_HSYNC_WIDTH(value)   ((value & 0xFF) << 0)
 VI_BURST Register: set horizontal sync width in pixels.
 
#define VI_BURST_START_NTSC   62
 VI_BURST Register: NTSC default start of color burst in pixels from hsync.
 
#define VI_VSYNC_WIDTH_NTSC   5
 VI_BURST Register: NTSC default vertical sync width in half lines.
 
#define VI_BURST_WIDTH_NTSC   34
 VI_BURST Register: NTSC default color burst width in pixels.
 
#define VI_HSYNC_WIDTH_NTSC   57
 VI_BURST Register: NTSC default horizontal sync width in pixels.
 
#define VI_BURST_START_PAL   64
 VI_BURST Register: PAL default start of color burst in pixels from hsync.
 
#define VI_VSYNC_WIDTH_PAL   4
 VI_BURST Register: PAL default vertical sync width in half lines.
 
#define VI_BURST_WIDTH_PAL   35
 VI_BURST Register: PAL default color burst width in pixels.

 
#define VI_HSYNC_WIDTH_PAL   58
 VI_BURST Register: PAL default horizontal sync width in pixels.
 
#define VI_X_SCALE_SET(value)   (( 1024*(value) + 320 ) / 640)
 VI_X_SCALE Register: set 1/horizontal scale up factor (value is converted to 2.10 format) More...
 
#define VI_Y_SCALE_SET(value)   (( 1024*(value) + 120 ) / 240)
 VI_Y_SCALE Register: set 1/vertical scale up factor (value is converted to 2.10 format) More...
 

Typedefs

typedef surface_tdisplay_context_t
 Display context (DEPRECATED: Use surface_t instead) More...
 

Enumerations

enum  bitdepth_t { DEPTH_16_BPP , DEPTH_32_BPP }
 Valid bit depths. More...
 
enum  gamma_t { GAMMA_NONE , GAMMA_CORRECT , GAMMA_CORRECT_DITHER }
 Valid gamma correction settings. More...
 
enum  filter_options_t {
  FILTERS_DISABLED , FILTERS_RESAMPLE , FILTERS_DEDITHER , FILTERS_RESAMPLE_ANTIALIAS ,
  FILTERS_RESAMPLE_ANTIALIAS_DEDITHER
}
 Valid display filter options. More...
 

Functions

void vi_write_safe (volatile uint32_t *reg, uint32_t value)
 Write a set of video registers to the VI. More...
 
void vi_write_config (const vi_config_t *config)
 Write a set of video registers to the VI. More...
 
void display_init (resolution_t res, bitdepth_t bit, uint32_t num_buffers, gamma_t gamma, filter_options_t filters)
 Initialize the display to a particular resolution and bit depth. More...
 
void display_close ()
 Close the display. More...
 
surface_tdisplay_get (void)
 Get a display buffer for rendering. More...
 
surface_tdisplay_try_get (void)
 Try getting a display surface. More...
 
void display_show (surface_t *surf)
 Display a buffer on the screen. More...
 
uint32_t display_get_width (void)
 Get the currently configured width of the display in pixels.
 
uint32_t display_get_height (void)
 Get the currently configured height of the display in pixels.
 
uint32_t display_get_bitdepth (void)
 Get the currently configured bitdepth of the display (in bytes per pixels)
 
uint32_t display_get_num_buffers (void)
 Get the currently configured number of buffers.
 

Variables

const resolution_t RESOLUTION_256x240 = {256, 240, false}
 256x240 mode
 
const resolution_t RESOLUTION_320x240 = {320, 240, false}
 320x240 mode
 
const resolution_t RESOLUTION_512x240 = {512, 240, false}
 512x240 mode, high-res progressive
 
const resolution_t RESOLUTION_640x240 = {640, 240, false}
 640x240 mode, high-res progressive
 
const resolution_t RESOLUTION_512x480 = {512, 480, true}
 512x480 mode, interlaced
 
const resolution_t RESOLUTION_640x480 = {640, 480, true}
 640x480 mode, interlaced
 

Detailed Description

Video interface system for configuring video output modes and displaying rendered graphics.

The display subsystem handles interfacing with the video interface (VI) and the hardware rasterizer (RDP) to allow software and hardware graphics operations. It consists of the Display Subsystem, the 2D Graphics and the Hardware Display Interface modules. A separate module, the Console Support, provides a rudimentary console for developers. Only the display subsystem or the console can be used at the same time. However, commands to draw console text to the display subsystem are available.

The display subsystem module is responsible for initializing the proper video mode for displaying 2D, 3D and software graphics. To set up video on the N64, code should call display_init with the appropriate options. Once the display has been set, a surface can be requested from the display subsystem using display_get. To draw to the acquired surface, code should use functions present in the 2D Graphics and the Hardware Display Interface modules. Once drawing to a surface is complete, the rendered graphic can be displayed to the screen using display_show. Once code has finished rendering all graphics, display_close can be used to shut down the display subsystem.


Data Structure Documentation

◆ vi_config_t

struct vi_config_t

Video Interface register structure.

Whenever trying to configure VI registers, this struct and its index definitions below can be very useful in writing comprehensive and verbose code.

Data Fields
uint32_t regs[VI_REGISTERS_COUNT]

◆ resolution_t

struct resolution_t

Video resolution structure.

You can either use one of the pre-defined constants (such as RESOLUTION_320x240) or define a custom resolution.

Data Fields
int32_t width Screen width (must be between 2 and 800)
int32_t height Screen height (must be between 1 and 720)
bool interlaced True if interlaced mode enabled.

Macro Definition Documentation

◆ VI_DEDITHER_FILTER_ENABLE

#define VI_DEDITHER_FILTER_ENABLE   (1<<16)

VI_CTRL Register setting: enable dedither filter.

Under VI_CTRL

◆ VI_ORIGIN_SET

#define VI_ORIGIN_SET (   value)    ((value & 0xFFFFFF) << 0)

VI_ORIGIN Register: set the address of a framebuffer.

Under VI_ORIGIN

◆ VI_WIDTH_SET

#define VI_WIDTH_SET (   value)    ((value & 0xFFF) << 0)

VI_ORIGIN Register: set the width of a framebuffer.

Under VI_WIDTH

◆ VI_V_CURRENT_VBLANK

#define VI_V_CURRENT_VBLANK   2

VI_V_CURRENT Register: default value for vblank begin line.

Under VI_V_CURRENT

◆ VI_V_INTR_SET

#define VI_V_INTR_SET (   value)    ((value & 0x3FF) << 0)

VI_V_INTR Register: set value for vertical interrupt.

Under VI_V_INTR

◆ VI_BURST_START

#define VI_BURST_START (   value)    ((value & 0x3F) << 20)

VI_BURST Register: set start of color burst in pixels from hsync.

Under VI_BURST

◆ VI_X_SCALE_SET

#define VI_X_SCALE_SET (   value)    (( 1024*(value) + 320 ) / 640)

VI_X_SCALE Register: set 1/horizontal scale up factor (value is converted to 2.10 format)

Under VI_X_SCALE

◆ VI_Y_SCALE_SET

#define VI_Y_SCALE_SET (   value)    (( 1024*(value) + 120 ) / 240)

VI_Y_SCALE Register: set 1/vertical scale up factor (value is converted to 2.10 format)

Under VI_Y_SCALE

Typedef Documentation

◆ display_context_t

Display context (DEPRECATED: Use surface_t instead)

See also
surface_t

Enumeration Type Documentation

◆ bitdepth_t

enum bitdepth_t

Valid bit depths.

Enumerator
DEPTH_16_BPP 

16 bits per pixel (5-5-5-1)

DEPTH_32_BPP 

32 bits per pixel (8-8-8-8)

◆ gamma_t

enum gamma_t

Valid gamma correction settings.

Enumerator
GAMMA_NONE 

Uncorrected gamma, should be used by default and with assets built by libdragon tools.

GAMMA_CORRECT 

Corrected gamma, should be used on a 32-bit framebuffer only when assets have been produced in linear color space and accurate blending is important.

GAMMA_CORRECT_DITHER 

Corrected gamma with hardware dithered output.

◆ filter_options_t

Valid display filter options.

Libdragon uses preconfigured options for enabling certain combinations of Video Interface filters due to a large number of wrong/invalid configurations with very strict conditions, and to simplify the options for the user.

Like for example antialiasing requiring resampling; dedithering not working with resampling, unless always fetching; always enabling divot filter under AA etc.

The options below provide all possible configurations that are deemed useful in development.

Enumerator
FILTERS_DISABLED 

All display filters are disabled.

FILTERS_RESAMPLE 

Resize the output image with a bilinear filter. In general, VI is in charge of resizing the framebuffer to fit the TV resolution (which is always NTSC 640x480 or PAL 640x512). This option enables a bilinear interpolation that can be used during this resize.

FILTERS_DEDITHER 

Reconstruct a 32-bit output from dithered 16-bit framebuffer.

FILTERS_RESAMPLE_ANTIALIAS 

Resize the output image with a bilinear filter (see FILTERS_RESAMPLE). Add a video interface anti-aliasing pass with a divot filter. To be able to see correct anti-aliased output, this display filter must be enabled, along with anti-aliased rendering of surfaces.

FILTERS_RESAMPLE_ANTIALIAS_DEDITHER 

Resize the output image with a bilinear filter (see FILTERS_RESAMPLE). Add a video interface anti-aliasing pass with a divot filter (see FILTERS_RESAMPLE_ANTIALIAS). Reconstruct a 32-bit output from dithered 16-bit framebuffer.

Function Documentation

◆ vi_write_safe()

void vi_write_safe ( volatile uint32_t *  reg,
uint32_t  value 
)
inline

Write a set of video registers to the VI.

Parameters
[in]regA pointer to a register to be written
[in]valueValue to be written to the register

◆ vi_write_config()

void vi_write_config ( const vi_config_t config)
inline

Write a set of video registers to the VI.

Parameters
[in]configA pointer to a set of register values to be written

◆ display_init()

void display_init ( resolution_t  res,
bitdepth_t  bit,
uint32_t  num_buffers,
gamma_t  gamma,
filter_options_t  filters 
)

Initialize the display to a particular resolution and bit depth.

Initialize video system. This sets up a double, triple, or multiple buffered drawing surface which can be blitted or rendered to using software or hardware.

Parameters
[in]resThe requested resolution. Use either one of the pre-defined resolution (such as RESOLUTION_320x240) or define a custom one.
[in]bitThe requested bit depth (DEPTH_16_BPP or DEPTH_32_BPP)
[in]num_buffersNumber of buffers, usually 2 or 3, but can be more. Triple buffering is recommended in case the application cannot hold a steady full framerate, so that slowdowns don't impact too much.
[in]gammaThe requested gamma setting
[in]filtersThe requested display filtering options, see filter_options_t

◆ display_close()

void display_close ( )

Close the display.

Close a display and free buffer memory associated with it.

◆ display_get()

surface_t * display_get ( void  )

Get a display buffer for rendering.

Grab a surface that is safe for drawing, spin-waiting until one is available.

When you are done drawing on the buffer, use display_show to schedule the buffer to be displayed on the screen during next vblank.

It is possible to get more than a display buffer at the same time, for instance to begin working on a new frame while the previous one is still being rendered in parallel through RDP. It is important to notice that surfaces will always be shown on the screen in the order they were gotten, irrespective of the order display_show is called.

Returns
A valid surface to render to.

◆ display_try_get()

surface_t * display_try_get ( void  )

Try getting a display surface.

This is similar to display_get, but it does not block if no display is available and return NULL instead.

Returns
A valid surface to render to or NULL if none is available.

◆ display_show()

void display_show ( surface_t surf)

Display a buffer on the screen.

Display a surface to the screen on the next vblank.

Notice that this function does not accept any arbitrary surface, but only those returned by display_get, which are owned by the display module.

Parameters
[in]surfA surface to show (previously retrieved using display_get)