Skip to content

Commit

Permalink
Merge/cleanup renderer viewport calculation code. (#496)
Browse files Browse the repository at this point in the history
`fix_viewport_ratio` has been replaced with renderer-specific
viewport initialization functions `set_window_viewport_centered`
and `set_window_viewport_scaled`. The renderer callback
`set_viewport` is now assigned to one of these, and is called
by the function `video_window_update_viewport`, which must be
called by the `create_window` function if it changes the window
size.

The window viewport is used in places that previously called
`fix_viewport_ratio`, which was primarily setting SDL update rects
and `glViewport`. It is also used to convert between window space
and screen space coordinates, which was previously done by two
renderer callbacks `get_screen_coords` and `set_screen_coords`.
These callbacks have been dummied out and the merged replacements
`get_screen_coords_viewport`/`set_screen_coords_viewport` are
called directly instead. If these callbacks are needed again in
the future, they can be uncommented (the only place that used
custom implementations was the GP2X renderer).

Finally, the viewport ratio is provided to `set_viewport` as a
numerator and denominator now instead of as an enum. This allows
`create_window` and `resize_window` to modify the ratio for cases
such as non-square pixels (as the GX renderer was doing with a
hack previously). This must be done in both functions if used.
  • Loading branch information
AliceLR authored Nov 1, 2024
1 parent 72ef2ab commit 442a702
Show file tree
Hide file tree
Showing 24 changed files with 530 additions and 346 deletions.
6 changes: 3 additions & 3 deletions arch/3ds/render.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1135,7 +1135,8 @@ static inline void ctr_draw_playfield(struct ctr_render_data *render_data,
}
}

static void ctr_sync_screen(struct graphics_data *graphics)
static void ctr_sync_screen(struct graphics_data *graphics,
struct video_window *window)
{
struct ctr_render_data *render_data = (struct ctr_render_data *) graphics->render_data;

Expand Down Expand Up @@ -1200,12 +1201,11 @@ void render_ctr_register(struct renderer *renderer)
renderer->init_video = ctr_init_video;
renderer->free_video = ctr_free_video;
renderer->create_window = ctr_create_window;
renderer->set_viewport = set_window_viewport_centered;
renderer->update_colors = ctr_update_colors;
renderer->remap_char_range = ctr_remap_char_range;
renderer->remap_char = ctr_remap_char;
renderer->remap_charbyte = ctr_remap_charbyte;
renderer->get_screen_coords = get_screen_coords_centered;
renderer->set_screen_coords = set_screen_coords_centered;
renderer->render_layer = ctr_render_layer;
renderer->render_cursor = ctr_render_cursor;
renderer->render_mouse = ctr_render_mouse;
Expand Down
6 changes: 3 additions & 3 deletions arch/djgpp/render_ega.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,8 @@ static void ega_render_mouse(struct graphics_data *graphics,
_farnspokeb(dest, _farnspeekb(dest) ^ 0xFF);
}

static void ega_sync_screen(struct graphics_data *graphics)
static void ega_sync_screen(struct graphics_data *graphics,
struct video_window *window)
{
struct ega_render_data *render_data = graphics->render_data;
uint8_t *src = graphics->charset;
Expand All @@ -509,13 +510,12 @@ void render_ega_register(struct renderer *renderer)
renderer->init_video = ega_init_video;
renderer->free_video = ega_free_video;
renderer->create_window = ega_create_window;
renderer->set_viewport = set_window_viewport_centered;
renderer->set_screen_mode = ega_set_screen_mode;
renderer->update_colors = ega_update_colors;
renderer->remap_char_range = ega_remap_char_range;
renderer->remap_char = ega_remap_char;
renderer->remap_charbyte = ega_remap_charbyte;
renderer->get_screen_coords = get_screen_coords_centered;
renderer->set_screen_coords = set_screen_coords_centered;
renderer->render_graph = ega_render_graph;
renderer->hardware_cursor = ega_hardware_cursor;
renderer->render_mouse = ega_render_mouse;
Expand Down
6 changes: 3 additions & 3 deletions arch/djgpp/render_svga.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,8 @@ static void svga_render_mouse(struct graphics_data *graphics,
graphics->bits_per_pixel, x, y, mask, 0, w, h);
}

static void svga_sync_screen(struct graphics_data *graphics)
static void svga_sync_screen(struct graphics_data *graphics,
struct video_window *window)
{
struct svga_render_data *render_data = graphics->render_data;
__dpmi_regs reg;
Expand Down Expand Up @@ -342,9 +343,8 @@ void render_svga_register(struct renderer *renderer)
renderer->init_video = svga_init_video;
renderer->free_video = svga_free_video;
renderer->create_window = svga_create_window;
renderer->set_viewport = set_window_viewport_centered;
renderer->update_colors = svga_update_colors;
renderer->get_screen_coords = get_screen_coords_centered;
renderer->set_screen_coords = set_screen_coords_centered;
renderer->render_graph = svga_render_graph;
renderer->render_layer = svga_render_layer;
renderer->render_cursor = svga_render_cursor;
Expand Down
6 changes: 3 additions & 3 deletions arch/dreamcast/render.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ static void dc_render_mouse(struct graphics_data *graphics,
0xFFFFFFFF, 0, w, h);
}

static void dc_sync_screen(struct graphics_data *graphics)
static void dc_sync_screen(struct graphics_data *graphics,
struct video_window *window)
{
struct dc_render_data *render_data = graphics->render_data;
pvr_vertex_t vtx;
Expand Down Expand Up @@ -187,9 +188,8 @@ void render_dc_register(struct renderer *renderer)
renderer->init_video = dc_init_video;
renderer->free_video = dc_free_video;
renderer->create_window = dc_create_window;
renderer->set_viewport = set_window_viewport_centered;
renderer->update_colors = dc_update_colors;
renderer->get_screen_coords = get_screen_coords_centered;
renderer->set_screen_coords = set_screen_coords_centered;
renderer->render_graph = dc_render_graph;
renderer->render_layer = dc_render_layer;
renderer->render_cursor = dc_render_cursor;
Expand Down
6 changes: 3 additions & 3 deletions arch/dreamcast/render_fb.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ static void dc_fb_render_mouse(struct graphics_data *graphics,
0xFFFFFFFF, 0, w, h);
}

static void dc_fb_sync_screen(struct graphics_data *graphics)
static void dc_fb_sync_screen(struct graphics_data *graphics,
struct video_window *window)
{
// struct dc_fb_render_data *render_data = graphics->render_data;
vid_flip(-1);
Expand All @@ -126,9 +127,8 @@ void render_dc_fb_register(struct renderer *renderer)
renderer->init_video = dc_fb_init_video;
renderer->free_video = dc_fb_free_video;
renderer->create_window = dc_fb_create_window;
renderer->set_viewport = set_window_viewport_centered;
renderer->update_colors = dc_fb_update_colors;
renderer->get_screen_coords = get_screen_coords_centered;
renderer->set_screen_coords = set_screen_coords_centered;
renderer->render_graph = dc_fb_render_graph;
renderer->render_layer = dc_fb_render_layer;
renderer->render_cursor = dc_fb_render_cursor;
Expand Down
6 changes: 3 additions & 3 deletions arch/nds/render.c
Original file line number Diff line number Diff line change
Expand Up @@ -747,7 +747,8 @@ static void nds_render_mouse(struct graphics_data *graphics,
// stub
}

static void nds_sync_screen(struct graphics_data *graphics)
static void nds_sync_screen(struct graphics_data *graphics,
struct video_window *window)
{
// stub
}
Expand Down Expand Up @@ -849,11 +850,10 @@ void render_nds_register(struct renderer *renderer)
renderer->init_video = nds_init_video;
renderer->create_window = nds_create_window;
renderer->update_colors = nds_update_colors;
renderer->set_viewport = set_window_viewport_centered;
renderer->remap_char_range = nds_remap_char_range;
renderer->remap_char = nds_remap_char;
renderer->remap_charbyte = nds_remap_charbyte;
renderer->get_screen_coords = get_screen_coords_centered;
renderer->set_screen_coords = set_screen_coords_centered;
renderer->render_graph = nds_render_graph;
renderer->render_cursor = nds_render_cursor;
renderer->render_mouse = nds_render_mouse;
Expand Down
31 changes: 14 additions & 17 deletions arch/wii/render_gx.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ static boolean gx_create_window(struct graphics_data *graphics,
{
struct gx_render_data *render_data = graphics->render_data;
float x, y, w, h, scale, xscale, yscale;
int fh, fs, sw, sh, dw, dh;
int fh;

if(window->is_fullscreen)
scale = 8.0 / 9.0;
Expand All @@ -393,31 +393,28 @@ static boolean gx_create_window(struct graphics_data *graphics,
fh = 574;
else
fh = 480;
fs = fh * 720;

if(CONF_GetAspectRatio() == CONF_ASPECT_16_9)
{
sw = fs * 16;
sh = fs * 9;
}
else
{
sw = fs * 4;
sh = fs * 3;
// 4:3 stretched to 16:9; correct ratio for non-square pixels.
window->ratio_numerator *= 3;
window->ratio_denominator *= 4;
}

fix_viewport_ratio(sw, sh, &dw, &dh, graphics->ratio);
window->width_px = 720;
window->height_px = fh;
video_window_update_viewport(window);

if(render_data->rmode->viWidth > render_data->rmode->fbWidth)
xscale = (float)render_data->rmode->fbWidth / render_data->rmode->viWidth;
else
xscale = 1.0;
yscale = (float)render_data->rmode->efbHeight / render_data->rmode->viHeight;

w = (float)dw * 720 / sw * scale;
h = (float)dh * fh / sh * scale;
x = (720 - w) / 2 - render_data->rmode->viXOrigin;
y = (fh - h) / 2 - render_data->rmode->viYOrigin;
w = window->viewport_width * scale;
h = window->viewport_height * scale;
x = (window->width_px - w) / 2 - render_data->rmode->viXOrigin;
y = (window->height_px - h) / 2 - render_data->rmode->viYOrigin;
w *= xscale; h *= yscale; x *= xscale; y *= yscale;

render_data->sx0 = x;
Expand Down Expand Up @@ -910,7 +907,8 @@ static void gx_render_mouse(struct graphics_data *graphics,
GX_End();
}

static void gx_sync_screen(struct graphics_data *graphics)
static void gx_sync_screen(struct graphics_data *graphics,
struct video_window *window)
{
struct gx_render_data *render_data = graphics->render_data;
static u8 tex_ptn[12][2] = {
Expand Down Expand Up @@ -959,12 +957,11 @@ void render_gx_register(struct renderer *renderer)
renderer->free_video = gx_free_video;
renderer->create_window = gx_create_window;
renderer->resize_window = gx_create_window;
renderer->set_viewport = set_window_viewport_scaled;
renderer->update_colors = gx_update_colors;
renderer->remap_char_range = gx_remap_char_range;
renderer->remap_char = gx_remap_char;
renderer->remap_charbyte = gx_remap_charbyte;
renderer->get_screen_coords = get_screen_coords_centered;
renderer->set_screen_coords = set_screen_coords_centered;
renderer->render_layer = gx_render_layer;
renderer->render_cursor = gx_render_cursor;
renderer->render_mouse = gx_render_mouse;
Expand Down
6 changes: 3 additions & 3 deletions arch/wii/render_xfb.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,8 @@ static void xfb_copy_buffer(struct graphics_data *graphics)
}
}

static void xfb_sync_screen(struct graphics_data *graphics)
static void xfb_sync_screen(struct graphics_data *graphics,
struct video_window *window)
{
struct xfb_render_data *render_data = graphics->render_data;

Expand All @@ -365,9 +366,8 @@ void render_xfb_register(struct renderer *renderer)
renderer->init_video = xfb_init_video;
renderer->free_video = xfb_free_video;
renderer->create_window = xfb_create_window;
renderer->set_viewport = set_window_viewport_centered;
renderer->update_colors = xfb_update_colors;
renderer->get_screen_coords = get_screen_coords_centered;
renderer->set_screen_coords = set_screen_coords_centered;
renderer->render_graph = xfb_render_graph;
renderer->render_layer = xfb_render_layer;
renderer->render_cursor = xfb_render_cursor;
Expand Down
85 changes: 79 additions & 6 deletions src/graphics.c
Original file line number Diff line number Diff line change
Expand Up @@ -1276,7 +1276,7 @@ void update_screen(void)
graphics.mouse_width, graphics.mouse_height);
}

graphics.renderer.sync_screen(&graphics);
graphics.renderer.sync_screen(&graphics, &(graphics.window));
}

boolean get_fade_status(void)
Expand Down Expand Up @@ -1843,6 +1843,26 @@ boolean has_video_initialized(void)
return graphics.is_initialized;
}

static void set_window_ratio(struct video_window *window, enum ratio_type ratio)
{
switch(ratio)
{
case RATIO_MODERN_64_35:
window->ratio_numerator = 64;
window->ratio_denominator = 35;
break;
case RATIO_CLASSIC_4_3:
window->ratio_numerator = 4;
window->ratio_denominator = 3;
break;
default:
case RATIO_STRETCH:
window->ratio_numerator = 0;
window->ratio_denominator = 0;
break;
}
}

unsigned video_create_window(void)
{
struct video_window *window = &(graphics.window);
Expand All @@ -1855,6 +1875,7 @@ unsigned video_create_window(void)
window->is_fullscreen_windowed = graphics.fullscreen_windowed;
window->is_headless = false;
window->allow_resize = graphics.allow_resize;
set_window_ratio(window, graphics.ratio);

if(graphics.fullscreen)
{
Expand All @@ -1878,6 +1899,7 @@ unsigned video_create_window(void)
window->width_px = graphics.window_width;
window->height_px = graphics.window_height;
}
video_window_update_viewport(window);

if(graphics.renderer.create_window(&graphics, window))
{
Expand Down Expand Up @@ -1915,6 +1937,36 @@ unsigned video_window_by_platform_id(unsigned platform_id)
return 0;
}

/**
* Update the scaled viewport coordinates within the window according to
* the window's scaling ratio, for use in SDL update rectangles or glViewport.
* The viewport is also used to translate mouse coordinates between screen
* and window space.
*
* This should be called by the renderer any time create_window forces the
* window size (SDL window creation functions already handle this).
* This is called automatically between resize_window and resize_callback.
*
* For best results, call glViewport (or equivalent) in either
* resize_callback or sync_screen.
*/
void video_window_update_viewport(struct video_window *window)
{
if(graphics.renderer.set_viewport)
{
graphics.renderer.set_viewport(&graphics, window);
}
else
{
debug("Implement set_viewport!");
window->viewport_x = 0;
window->viewport_y = 0;
window->viewport_width = window->width_px;
window->viewport_height = window->height_px;
window->is_integer_scaled = false;
}
}

/* Sync the current window size after it has ALREADY been changed by the
* platform or by a call to a graphics.c window resize function.
* SDL2/3 reports a window resize event after it is resized;
Expand All @@ -1937,8 +1989,7 @@ void video_sync_window_size(unsigned window_id,
graphics.window_width = new_width_px;
graphics.window_height = new_height_px;
}
// TODO: call fix_viewport_ratio and update the viewport position here
// instead of in 50 million other places.
video_window_update_viewport(&(graphics.window));

if(graphics.renderer.resize_callback)
graphics.renderer.resize_callback(&graphics, &graphics.window);
Expand All @@ -1964,6 +2015,7 @@ static void resize_window(unsigned window_id, boolean fullscreen)
}
graphics.window.is_fullscreen = fullscreen;
graphics.fullscreen = fullscreen;
set_window_ratio(&graphics.window, graphics.ratio);

graphics.renderer.resize_window(&graphics, &graphics.window);

Expand Down Expand Up @@ -3110,13 +3162,34 @@ boolean get_char_visible_bitmask(uint16_t char_idx, uint8_t palette,
void get_screen_coords(int screen_x, int screen_y, int *x, int *y,
int *min_x, int *min_y, int *max_x, int *max_y)
{
graphics.renderer.get_screen_coords(&graphics, screen_x, screen_y, x, y,
min_x, min_y, max_x, max_y);
#if 0
if(graphics.renderer.get_screen_coords)
{
graphics.renderer.get_screen_coords(&graphics, &(graphics.window),
screen_x, screen_y, x, y, min_x, min_y, max_x, max_y);
}
else
#endif
{
get_screen_coords_viewport(&graphics, &(graphics.window),
screen_x, screen_y, x, y, min_x, min_y, max_x, max_y);
}
}

void set_screen_coords(int x, int y, int *screen_x, int *screen_y)
{
graphics.renderer.set_screen_coords(&graphics, x, y, screen_x, screen_y);
#if 0
if(graphics.renderer.set_screen_coords)
{
graphics.renderer.set_screen_coords(&graphics, &(graphics.window),
x, y, screen_x, screen_y);
}
else
#endif
{
set_screen_coords_viewport(&graphics, &(graphics.window),
x, y, screen_x, screen_y);
}
}

void focus_screen(int x, int y)
Expand Down
Loading

0 comments on commit 442a702

Please sign in to comment.