diff --git a/driver.h b/driver.h index 43074591b1..f27b6e2b52 100644 --- a/driver.h +++ b/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 diff --git a/general.h b/general.h index 036466222f..de47caafc4 100644 --- a/general.h +++ b/general.h @@ -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. diff --git a/gfx/d3d9/d3d9.cpp b/gfx/d3d9/d3d9.cpp index e29d8230c8..70efc7a69e 100644 --- a/gfx/d3d9/d3d9.cpp +++ b/gfx/d3d9/d3d9.cpp @@ -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) diff --git a/gfx/gl.c b/gfx/gl.c index e2fe9a72e1..d36a141f9e 100644 --- a/gfx/gl.c +++ b/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) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 340982a4f7..53878978d8 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -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]; diff --git a/gfx/sdl_gfx.c b/gfx/sdl_gfx.c index 0f9e8a074c..0f30ad2778 100644 --- a/gfx/sdl_gfx.c +++ b/gfx/sdl_gfx.c @@ -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 = { diff --git a/gfx/xvideo.c b/gfx/xvideo.c index 853facde4e..c825bf1b86 100644 --- a/gfx/xvideo.c +++ b/gfx/xvideo.c @@ -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; diff --git a/input/dinput.c b/input/dinput.c index 04e5972106..a222924b70 100644 --- a/input/dinput.c +++ b/input/dinput.c @@ -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); diff --git a/input/input_common.c b/input/input_common.c index 46172a5cc2..9886591462 100644 --- a/input/input_common.c +++ b/input/input_common.c @@ -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; } diff --git a/input/input_common.h b/input/input_common.h index e542bf65fd..bb61907b8f 100644 --- a/input/input_common.h +++ b/input/input_common.h @@ -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 { diff --git a/input/overlay.c b/input/overlay.c index 9861cd1465..98775c2530 100644 --- a/input/overlay.c +++ b/input/overlay.c @@ -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) diff --git a/input/overlay.h b/input/overlay.h index 76e4d2f26c..6b5d6ea452 100644 --- a/input/overlay.h +++ b/input/overlay.h @@ -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); diff --git a/input/sdl_input.c b/input/sdl_input.c index 4e406e0a67..2d8a60ae4f 100644 --- a/input/sdl_input.c +++ b/input/sdl_input.c @@ -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: diff --git a/input/x11_input.c b/input/x11_input.c index ff26cb009b..1f5851724a 100644 --- a/input/x11_input.c +++ b/input/x11_input.c @@ -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); diff --git a/media/overlays/basic_overlay.cfg b/media/overlays/basic_overlay.cfg index 7cce1d0148..d154edf1fc 100644 --- a/media/overlays/basic_overlay.cfg +++ b/media/overlays/basic_overlay.cfg @@ -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" diff --git a/retroarch.c b/retroarch.c index 4a1514b71b..55c293a81f 100644 --- a/retroarch.c +++ b/retroarch.c @@ -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); }