mirror of
https://github.com/libretro/RetroArch
synced 2025-03-27 05:37:40 +00:00
Add support for full-screen overlays.
This commit is contained in:
parent
d50ad3e543
commit
312980ee30
6
driver.h
6
driver.h
@ -38,6 +38,11 @@
|
||||
#define AUDIO_CHUNK_SIZE_NONBLOCKING 2048 // So we don't get complete line-noise when fast-forwarding audio.
|
||||
#define AUDIO_MAX_RATIO 16
|
||||
|
||||
// Specialized _POINTER that targets the full screen regardless of viewport.
|
||||
// Should not be used by a libretro implementation as coordinates returned make no sense.
|
||||
// It is only used internally for overlays.
|
||||
#define RARCH_DEVICE_POINTER_SCREEN (RETRO_DEVICE_POINTER | 0x10000)
|
||||
|
||||
// libretro has 16 buttons from 0-15 (libretro.h)
|
||||
// Analog binds use RETRO_DEVICE_ANALOG, but we follow the same scheme internally
|
||||
// in RetroArch for simplicity,
|
||||
@ -219,6 +224,7 @@ typedef struct video_overlay_interface
|
||||
bool (*load)(void *data, const uint32_t *image, unsigned width, unsigned height);
|
||||
void (*tex_geom)(void *data, float x, float y, float w, float h);
|
||||
void (*vertex_geom)(void *data, float x, float y, float w, float h);
|
||||
void (*full_screen)(void *data, bool enable);
|
||||
} video_overlay_interface_t;
|
||||
#endif
|
||||
|
||||
|
@ -270,6 +270,8 @@ typedef struct rarch_viewport
|
||||
int y;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
unsigned full_width;
|
||||
unsigned full_height;
|
||||
} rarch_viewport_t;
|
||||
|
||||
// All run-time- / command line flag-related globals go here.
|
||||
|
@ -240,6 +240,9 @@ void D3DVideo::viewport_info(rarch_viewport &vp)
|
||||
vp.y = final_viewport.Y;
|
||||
vp.width = final_viewport.Width;
|
||||
vp.height = final_viewport.Height;
|
||||
|
||||
vp.full_width = screen_width;
|
||||
vp.full_height = screen_height;
|
||||
}
|
||||
|
||||
bool D3DVideo::read_viewport(uint8_t *buffer)
|
||||
|
19
gfx/gl.c
19
gfx/gl.c
@ -1809,6 +1809,8 @@ static void gl_viewport_info(void *data, struct rarch_viewport *vp)
|
||||
{
|
||||
gl_t *gl = (gl_t*)data;
|
||||
*vp = gl->vp;
|
||||
vp->full_width = gl->win_width;
|
||||
vp->full_height = gl->win_height;
|
||||
}
|
||||
|
||||
static bool gl_read_viewport(void *data, uint8_t *buffer)
|
||||
@ -2006,6 +2008,12 @@ static void gl_overlay_enable(void *data, bool state)
|
||||
gl->overlay_enable = state;
|
||||
}
|
||||
|
||||
static void gl_overlay_full_screen(void *data, bool enable)
|
||||
{
|
||||
gl_t *gl = (gl_t*)data;
|
||||
gl->overlay_full_screen = enable;
|
||||
}
|
||||
|
||||
static void gl_render_overlay(void *data)
|
||||
{
|
||||
gl_t *gl = (gl_t*)data;
|
||||
@ -2018,7 +2026,15 @@ static void gl_render_overlay(void *data)
|
||||
gl->coords.tex_coord = gl->overlay_tex_coord;
|
||||
gl_shader_set_coords_func(gl, &gl->coords, &gl->mvp_no_rot);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
if (gl->overlay_full_screen)
|
||||
{
|
||||
glViewport(0, 0, gl->win_width, gl->win_height);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glViewport(gl->vp.x, gl->vp.y, gl->vp.width, gl->vp.height);
|
||||
}
|
||||
else
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
gl->coords.vertex = vertex_ptr;
|
||||
@ -2030,6 +2046,7 @@ static const video_overlay_interface_t gl_overlay_interface = {
|
||||
gl_overlay_load,
|
||||
gl_overlay_tex_geom,
|
||||
gl_overlay_vertex_geom,
|
||||
gl_overlay_full_screen,
|
||||
};
|
||||
|
||||
static void gl_get_overlay_interface(void *data, const video_overlay_interface_t **iface)
|
||||
|
@ -285,6 +285,7 @@ typedef struct gl
|
||||
#ifdef HAVE_OVERLAY
|
||||
// Overlay rendering
|
||||
bool overlay_enable;
|
||||
bool overlay_full_screen;
|
||||
GLuint tex_overlay;
|
||||
GLfloat overlay_tex_coord[8];
|
||||
GLfloat overlay_vertex_coord[8];
|
||||
|
@ -338,8 +338,8 @@ static void sdl_gfx_viewport_info(void *data, struct rarch_viewport *vp)
|
||||
{
|
||||
sdl_video_t *vid = (sdl_video_t*)data;
|
||||
vp->x = vp->y = 0;
|
||||
vp->width = vid->screen->w;
|
||||
vp->height = vid->screen->h;
|
||||
vp->width = vp->full_width = vid->screen->w;
|
||||
vp->height = vp->full_height = vid->screen->h;
|
||||
}
|
||||
|
||||
const video_driver_t video_sdl = {
|
||||
|
@ -530,6 +530,9 @@ static bool check_resize(xv_t *xv, unsigned width, unsigned height)
|
||||
|
||||
static void calc_out_rect(bool keep_aspect, struct rarch_viewport *vp, unsigned vp_width, unsigned vp_height)
|
||||
{
|
||||
vp->full_width = vp_width;
|
||||
vp->full_height = vp_height;
|
||||
|
||||
if (!keep_aspect)
|
||||
{
|
||||
vp->x = 0; vp->y = 0;
|
||||
|
@ -237,17 +237,24 @@ static int16_t dinput_mouse_state(struct dinput_input *di, unsigned id)
|
||||
}
|
||||
}
|
||||
|
||||
static int16_t dinput_pointer_state(struct dinput_input *di, unsigned index, unsigned id)
|
||||
static int16_t dinput_pointer_state(struct dinput_input *di, unsigned index, unsigned id, bool screen)
|
||||
{
|
||||
if (index != 0)
|
||||
return 0;
|
||||
|
||||
int16_t res_x = 0, res_y = 0;
|
||||
bool valid = input_translate_coord_viewport(di->mouse_x, di->mouse_y, &res_x, &res_y);
|
||||
int16_t res_x = 0, res_y = 0, res_screen_x = 0, res_screen_y = 0;
|
||||
bool valid = input_translate_coord_viewport(di->mouse_x, di->mouse_y,
|
||||
&res_x, &res_y, &res_screen_x, &res_screen_y);
|
||||
|
||||
if (!valid)
|
||||
return 0;
|
||||
|
||||
if (screen)
|
||||
{
|
||||
res_x = res_screen_x;
|
||||
res_y = res_screen_y;
|
||||
}
|
||||
|
||||
bool inside = (res_x >= -0x7fff) && (res_x <= 0x7fff) &&
|
||||
(res_y >= -0x7fff) && (res_y <= 0x7fff);
|
||||
|
||||
@ -287,7 +294,8 @@ static int16_t dinput_input_state(void *data,
|
||||
return dinput_mouse_state(di, id);
|
||||
|
||||
case RETRO_DEVICE_POINTER:
|
||||
return dinput_pointer_state(di, index, id);
|
||||
case RARCH_DEVICE_POINTER_SCREEN:
|
||||
return dinput_pointer_state(di, index, id, device == RARCH_DEVICE_POINTER_SCREEN);
|
||||
|
||||
case RETRO_DEVICE_LIGHTGUN:
|
||||
return dinput_lightgun_state(di, id);
|
||||
|
@ -163,7 +163,7 @@ bool input_joypad_hat_raw(const rarch_joypad_driver_t *driver,
|
||||
}
|
||||
|
||||
bool input_translate_coord_viewport(int mouse_x, int mouse_y,
|
||||
int16_t *res_x, int16_t *res_y)
|
||||
int16_t *res_x, int16_t *res_y, int16_t *res_screen_x, int16_t *res_screen_y)
|
||||
{
|
||||
struct rarch_viewport vp = {0};
|
||||
if (driver.video->viewport_info)
|
||||
@ -171,6 +171,13 @@ bool input_translate_coord_viewport(int mouse_x, int mouse_y,
|
||||
else
|
||||
return false;
|
||||
|
||||
int scaled_screen_x = (2 * mouse_x * 0x7fff) / (int)vp.full_width - 0x7fff;
|
||||
int scaled_screen_y = (2 * mouse_y * 0x7fff) / (int)vp.full_height - 0x7fff;
|
||||
if (scaled_screen_x < -0x7fff || scaled_screen_x > 0x7fff)
|
||||
scaled_screen_x = -0x8000; // OOB
|
||||
if (scaled_screen_y < -0x7fff || scaled_screen_y > 0x7fff)
|
||||
scaled_screen_y = -0x8000; // OOB
|
||||
|
||||
mouse_x -= vp.x;
|
||||
mouse_y -= vp.y;
|
||||
|
||||
@ -183,6 +190,8 @@ bool input_translate_coord_viewport(int mouse_x, int mouse_y,
|
||||
|
||||
*res_x = scaled_x;
|
||||
*res_y = scaled_y;
|
||||
*res_screen_x = scaled_screen_x;
|
||||
*res_screen_y = scaled_screen_y;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,8 @@ static inline void input_conv_analog_id_to_bind_id(unsigned index, unsigned id,
|
||||
}
|
||||
}
|
||||
|
||||
bool input_translate_coord_viewport(int mouse_x, int mouse_y, int16_t *res_x, int16_t *res_y);
|
||||
bool input_translate_coord_viewport(int mouse_x, int mouse_y,
|
||||
int16_t *res_x, int16_t *res_y, int16_t *res_screen_x, int16_t *res_screen_y);
|
||||
|
||||
typedef struct rarch_joypad_driver
|
||||
{
|
||||
|
@ -51,6 +51,7 @@ struct overlay
|
||||
unsigned height;
|
||||
|
||||
float x, y, w, h;
|
||||
bool full_screen;
|
||||
};
|
||||
|
||||
struct input_overlay
|
||||
@ -173,6 +174,12 @@ static bool input_overlay_load_overlay(config_file_t *conf, const char *config_p
|
||||
string_list_free(list);
|
||||
}
|
||||
|
||||
char overlay_full_screen_key[64];
|
||||
snprintf(overlay_full_screen_key, sizeof(overlay_full_screen_key),
|
||||
"overlay%u_full_screen", index);
|
||||
overlay->full_screen = false;
|
||||
config_get_bool(conf, overlay_full_screen_key, &overlay->full_screen);
|
||||
|
||||
char overlay_descs_key[64];
|
||||
snprintf(overlay_descs_key, sizeof(overlay_descs_key), "overlay%u_descs", index);
|
||||
|
||||
@ -268,6 +275,7 @@ input_overlay_t *input_overlay_new(const char *overlay)
|
||||
ol->iface->load(ol->iface_data, ol->active->image, ol->active->width, ol->active->height);
|
||||
ol->iface->vertex_geom(ol->iface_data,
|
||||
ol->active->x, ol->active->y, ol->active->w, ol->active->h);
|
||||
ol->iface->full_screen(ol->iface_data, ol->active->full_screen);
|
||||
|
||||
ol->iface->enable(ol->iface_data, true);
|
||||
ol->enable = true;
|
||||
@ -339,6 +347,12 @@ void input_overlay_next(input_overlay_t *ol)
|
||||
ol->iface->load(ol->iface_data, ol->active->image, ol->active->width, ol->active->height);
|
||||
ol->iface->vertex_geom(ol->iface_data,
|
||||
ol->active->x, ol->active->y, ol->active->w, ol->active->h);
|
||||
ol->iface->full_screen(ol->iface_data, ol->active->full_screen);
|
||||
}
|
||||
|
||||
bool input_overlay_full_screen(input_overlay_t *ol)
|
||||
{
|
||||
return ol->active->full_screen;
|
||||
}
|
||||
|
||||
void input_overlay_free(input_overlay_t *ol)
|
||||
|
@ -31,6 +31,8 @@ void input_overlay_free(input_overlay_t *ol);
|
||||
|
||||
void input_overlay_enable(input_overlay_t *ol, bool enable);
|
||||
|
||||
bool input_overlay_full_screen(input_overlay_t *ol);
|
||||
|
||||
// norm_x and norm_y are the result of input_translate_coord_viewport().
|
||||
// Resulting state is a bitmask of (1 << key_bind_id).
|
||||
uint64_t input_overlay_poll(input_overlay_t *ol, int16_t norm_x, int16_t norm_y);
|
||||
|
@ -120,17 +120,24 @@ static int16_t sdl_mouse_device_state(sdl_input_t *sdl, unsigned id)
|
||||
}
|
||||
}
|
||||
|
||||
static int16_t sdl_pointer_device_state(sdl_input_t *sdl, unsigned index, unsigned id)
|
||||
static int16_t sdl_pointer_device_state(sdl_input_t *sdl, unsigned index, unsigned id, bool screen)
|
||||
{
|
||||
if (index != 0)
|
||||
return 0;
|
||||
|
||||
int16_t res_x = 0, res_y = 0;
|
||||
bool valid = input_translate_coord_viewport(sdl->mouse_abs_x, sdl->mouse_abs_y, &res_x, &res_y);
|
||||
int16_t res_x = 0, res_y = 0, res_screen_x = 0, res_screen_y = 0;
|
||||
bool valid = input_translate_coord_viewport(sdl->mouse_abs_x, sdl->mouse_abs_y,
|
||||
&res_x, &res_y, &res_screen_x, &res_screen_y);
|
||||
|
||||
if (!valid)
|
||||
return 0;
|
||||
|
||||
if (screen)
|
||||
{
|
||||
res_x = res_screen_x;
|
||||
res_y = res_screen_y;
|
||||
}
|
||||
|
||||
bool inside = (res_x >= -0x7fff) && (res_x <= 0x7fff) &&
|
||||
(res_y >= -0x7fff) && (res_y <= 0x7fff);
|
||||
|
||||
@ -185,7 +192,8 @@ static int16_t sdl_input_state(void *data_, const struct retro_keybind **binds,
|
||||
case RETRO_DEVICE_MOUSE:
|
||||
return sdl_mouse_device_state(data, id);
|
||||
case RETRO_DEVICE_POINTER:
|
||||
return sdl_pointer_device_state(data, index, id);
|
||||
case RARCH_DEVICE_POINTER_SCREEN:
|
||||
return sdl_pointer_device_state(data, index, id, device == RARCH_DEVICE_POINTER_SCREEN);
|
||||
case RETRO_DEVICE_KEYBOARD:
|
||||
return sdl_keyboard_device_state(data, id);
|
||||
case RETRO_DEVICE_LIGHTGUN:
|
||||
|
@ -107,17 +107,24 @@ static int16_t x_mouse_state(x11_input_t *x11, unsigned id)
|
||||
}
|
||||
}
|
||||
|
||||
static int16_t x_pointer_state(x11_input_t *x11, unsigned index, unsigned id)
|
||||
static int16_t x_pointer_state(x11_input_t *x11, unsigned index, unsigned id, bool screen)
|
||||
{
|
||||
if (index != 0)
|
||||
return 0;
|
||||
|
||||
int16_t res_x = 0, res_y = 0;
|
||||
bool valid = input_translate_coord_viewport(x11->mouse_x, x11->mouse_y, &res_x, &res_y);
|
||||
int16_t res_x = 0, res_y = 0, res_screen_x = 0, res_screen_y = 0;
|
||||
bool valid = input_translate_coord_viewport(x11->mouse_x, x11->mouse_y,
|
||||
&res_x, &res_y, &res_screen_x, &res_screen_y);
|
||||
|
||||
if (!valid)
|
||||
return 0;
|
||||
|
||||
if (screen)
|
||||
{
|
||||
res_x = res_screen_x;
|
||||
res_y = res_screen_y;
|
||||
}
|
||||
|
||||
bool inside = (res_x >= -0x7fff) && (res_x <= 0x7fff) &&
|
||||
(res_y >= -0x7fff) && (res_y <= 0x7fff);
|
||||
|
||||
@ -180,7 +187,8 @@ static int16_t x_input_state(void *data, const struct retro_keybind **binds, uns
|
||||
return x_mouse_state(x11, id);
|
||||
|
||||
case RETRO_DEVICE_POINTER:
|
||||
return x_pointer_state(x11, index, id);
|
||||
case RARCH_DEVICE_POINTER_SCREEN:
|
||||
return x_pointer_state(x11, index, id, device == RARCH_DEVICE_POINTER_SCREEN);
|
||||
|
||||
case RETRO_DEVICE_LIGHTGUN:
|
||||
return x_lightgun_state(x11, id);
|
||||
|
@ -4,6 +4,8 @@ overlay0_overlay = basic_overlay.tga
|
||||
overlay1_overlay = basic_quickmenu_small.tga
|
||||
overlay2_overlay = basic_next.tga
|
||||
|
||||
overlay0_full_screen = true
|
||||
|
||||
overlay0_descs = 15
|
||||
overlay0_desc0 = "left,15,210,rect,10,30"
|
||||
overlay0_desc1 = "right,60,210,rect,10,30"
|
||||
|
@ -474,14 +474,17 @@ static inline void input_poll_overlay(void)
|
||||
{
|
||||
driver.overlay_state = 0;
|
||||
|
||||
unsigned device = input_overlay_full_screen(driver.overlay) ?
|
||||
RARCH_DEVICE_POINTER_SCREEN : RETRO_DEVICE_POINTER;
|
||||
|
||||
for (unsigned i = 0;
|
||||
input_input_state_func(NULL, 0, RETRO_DEVICE_POINTER, i, RETRO_DEVICE_ID_POINTER_PRESSED);
|
||||
input_input_state_func(NULL, 0, device, i, RETRO_DEVICE_ID_POINTER_PRESSED);
|
||||
i++)
|
||||
{
|
||||
int16_t x = input_input_state_func(NULL, 0,
|
||||
RETRO_DEVICE_POINTER, i, RETRO_DEVICE_ID_POINTER_X);
|
||||
device, i, RETRO_DEVICE_ID_POINTER_X);
|
||||
int16_t y = input_input_state_func(NULL, 0,
|
||||
RETRO_DEVICE_POINTER, i, RETRO_DEVICE_ID_POINTER_Y);
|
||||
device, i, RETRO_DEVICE_ID_POINTER_Y);
|
||||
|
||||
driver.overlay_state |= input_overlay_poll(driver.overlay, x, y);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user