mirror of
https://github.com/CTCaer/RetroArch.git
synced 2024-12-13 13:28:49 +00:00
Basic overlay POC works.
Add support for X11.
This commit is contained in:
parent
b4cd58afe7
commit
1250fae7f1
1
Makefile
1
Makefile
@ -13,6 +13,7 @@ OBJ = retroarch.o \
|
||||
rewind.o \
|
||||
gfx/gfx_common.o \
|
||||
input/input_common.o \
|
||||
input/overlay.o \
|
||||
patch.o \
|
||||
fifo_buffer.o \
|
||||
compat/compat.o \
|
||||
|
2
driver.h
2
driver.h
@ -208,7 +208,7 @@ struct rarch_viewport;
|
||||
typedef struct video_overlay_interface
|
||||
{
|
||||
void (*enable)(void *data, bool state);
|
||||
bool (*load)(void *data, const char *path);
|
||||
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);
|
||||
} video_overlay_interface_t;
|
||||
|
@ -42,6 +42,7 @@
|
||||
#define video_set_aspect_ratio_func(aspect_idx) driver.video->set_aspect_ratio(driver.video_data, aspect_idx)
|
||||
#define video_viewport_info_func(info) driver.video->viewport_info(driver.video_data, info)
|
||||
#define video_read_viewport_func(buffer) driver.video->read_viewport(driver.video_data, buffer)
|
||||
#define video_overlay_interface_func(iface) driver.video->overlay_interface(driver.video_data, iface)
|
||||
#define video_free_func() driver.video->free(driver.video_data)
|
||||
#define input_init_func() driver.input->init()
|
||||
#define input_poll_func() driver.input->poll(driver.input_data)
|
||||
|
16
gfx/gl.c
16
gfx/gl.c
@ -1792,7 +1792,7 @@ static void gl_set_aspect_ratio(void *data, unsigned aspectratio_index)
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool gl_overlay_load(void *data, const char *path)
|
||||
static bool gl_overlay_load(void *data, const uint32_t *image, unsigned width, unsigned height)
|
||||
{
|
||||
gl_t *gl = (gl_t*)data;
|
||||
|
||||
@ -1805,19 +1805,11 @@ static bool gl_overlay_load(void *data, const char *path)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
struct texture_image img = {0};
|
||||
if (!texture_image_load(path, &img))
|
||||
{
|
||||
RARCH_ERR("Failed to load overlay image: %s.\n", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(img.width * sizeof(uint32_t)));
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(width * sizeof(uint32_t)));
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, RARCH_GL_INTERNAL_FORMAT32,
|
||||
img.width, img.height, 0, RARCH_GL_TEXTURE_TYPE32,
|
||||
RARCH_GL_FORMAT32, img.pixels);
|
||||
width, height, 0, RARCH_GL_TEXTURE_TYPE32,
|
||||
RARCH_GL_FORMAT32, image);
|
||||
|
||||
free(img.pixels);
|
||||
gl_overlay_tex_geom(gl, 0, 0, 1, 1); // Default. Stretch to whole screen.
|
||||
gl_overlay_vertex_geom(gl, 0, 0, 1, 1);
|
||||
return true;
|
||||
|
115
input/overlay.c
Normal file
115
input/overlay.c
Normal file
@ -0,0 +1,115 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "overlay.h"
|
||||
#include "../general.h"
|
||||
#include "../driver.h"
|
||||
#include "../libretro.h"
|
||||
#include "../gfx/image.h"
|
||||
|
||||
struct input_overlay
|
||||
{
|
||||
void *iface_data;
|
||||
const video_overlay_interface_t *iface;
|
||||
};
|
||||
|
||||
input_overlay_t *input_overlay_new(const char *overlay)
|
||||
{
|
||||
(void)overlay;
|
||||
|
||||
input_overlay_t *ol = (input_overlay_t*)calloc(1, sizeof(*ol));
|
||||
if (!ol)
|
||||
goto error;
|
||||
|
||||
if (!driver.video->overlay_interface)
|
||||
{
|
||||
RARCH_ERR("Overlay interface is not present in video driver.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
video_overlay_interface_func(&ol->iface);
|
||||
ol->iface_data = driver.video_data;
|
||||
|
||||
if (!ol->iface)
|
||||
goto error;
|
||||
|
||||
// Test hardcoded.
|
||||
struct texture_image img = {0};
|
||||
if (!texture_image_load("/tmp/test.png", &img))
|
||||
{
|
||||
RARCH_ERR("Failed to load overlay image.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ol->iface->load(ol->iface_data, img.pixels, img.width, img.height);
|
||||
free(img.pixels);
|
||||
|
||||
ol->iface->enable(ol->iface_data, true);
|
||||
|
||||
return ol;
|
||||
|
||||
error:
|
||||
input_overlay_free(ol);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct overlay_desc
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float rad;
|
||||
unsigned key;
|
||||
};
|
||||
|
||||
// TODO: This will be part of a config of some sort.
|
||||
static const struct overlay_desc descs[] = {
|
||||
{ 0.25, 0.5, 0.1, RETRO_DEVICE_ID_JOYPAD_LEFT },
|
||||
{ 0.75, 0.5, 0.1, RETRO_DEVICE_ID_JOYPAD_RIGHT },
|
||||
};
|
||||
|
||||
uint64_t input_overlay_poll(input_overlay_t *ol, int16_t norm_x, int16_t norm_y)
|
||||
{
|
||||
// norm_x and norm_y is in [-0x7fff, 0x7fff] range, like RETRO_DEVICE_POINTER.
|
||||
float x = (float)(norm_x + 0x7fff) / 0xffff;
|
||||
float y = (float)(norm_y + 0x7fff) / 0xffff;
|
||||
|
||||
uint64_t state = 0;
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(descs); i++)
|
||||
{
|
||||
float sq_dist = (x - descs[i].x) * (x - descs[i].x) + (y - descs[i].y) * (y - descs[i].y);
|
||||
if (sq_dist <= descs[i].rad * descs[i].rad)
|
||||
state |= UINT64_C(1) << descs[i].key;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void input_overlay_next(input_overlay_t *ol)
|
||||
{
|
||||
// Dummy
|
||||
(void)ol;
|
||||
}
|
||||
|
||||
void input_overlay_free(input_overlay_t *ol)
|
||||
{
|
||||
if (!ol)
|
||||
return;
|
||||
|
||||
if (ol->iface)
|
||||
ol->iface->enable(ol->iface_data, false);
|
||||
|
||||
free(ol);
|
||||
}
|
||||
|
39
input/overlay.h
Normal file
39
input/overlay.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef INPUT_OVERLAY_H__
|
||||
#define INPUT_OVERLAY_H__
|
||||
|
||||
#include "../boolean.h"
|
||||
#include <stdint.h>
|
||||
|
||||
// Overlay driver acts as a medium between input drivers and video driver.
|
||||
// Coordinates are fetched from input driver, and an overlay with pressable actions are
|
||||
// displayed on-screen.
|
||||
//
|
||||
// This interface requires that the video driver has support for the overlay interface.
|
||||
typedef struct input_overlay input_overlay_t;
|
||||
|
||||
input_overlay_t *input_overlay_new(const char *overlay);
|
||||
void input_overlay_free(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);
|
||||
|
||||
void input_overlay_next(input_overlay_t *ol);
|
||||
|
||||
#endif
|
||||
|
@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "input_common.h"
|
||||
#include "overlay.h"
|
||||
|
||||
#include "../driver.h"
|
||||
|
||||
@ -30,6 +31,10 @@ typedef struct x11_input
|
||||
{
|
||||
const rarch_joypad_driver_t *joypad;
|
||||
|
||||
bool ol_defer;
|
||||
input_overlay_t *ol;
|
||||
uint64_t ol_state;
|
||||
|
||||
Display *display;
|
||||
Window win;
|
||||
|
||||
@ -58,6 +63,11 @@ static void *x_input_init(void)
|
||||
x11->joypad = input_joypad_init_first();
|
||||
input_init_keyboard_lut(rarch_key_map_x11);
|
||||
|
||||
if (driver.video_data) // Video driver isn't initialized yet, init later.
|
||||
x11->ol = input_overlay_new(NULL);
|
||||
else
|
||||
x11->ol_defer = true;
|
||||
|
||||
return x11;
|
||||
}
|
||||
|
||||
@ -87,7 +97,8 @@ static bool x_bind_button_pressed(void *data, int key)
|
||||
{
|
||||
x11_input_t *x11 = (x11_input_t*)data;
|
||||
return x_is_pressed(x11, g_settings.input.binds[0], key) ||
|
||||
input_joypad_pressed(x11->joypad, 0, &g_settings.input.binds[0][key]);
|
||||
input_joypad_pressed(x11->joypad, 0, &g_settings.input.binds[0][key]) ||
|
||||
(x11->ol_state & (UINT64_C(1) << key));
|
||||
}
|
||||
|
||||
static int16_t x_mouse_state(x11_input_t *x11, unsigned id)
|
||||
@ -165,7 +176,8 @@ static int16_t x_input_state(void *data, const struct retro_keybind **binds, uns
|
||||
{
|
||||
case RETRO_DEVICE_JOYPAD:
|
||||
return x_is_pressed(x11, binds[port], id) ||
|
||||
input_joypad_pressed(x11->joypad, port, &binds[port][id]);
|
||||
input_joypad_pressed(x11->joypad, port, &binds[port][id]) ||
|
||||
((port == 0) && (x11->ol_state & (UINT64_C(1) << id)));
|
||||
|
||||
case RETRO_DEVICE_KEYBOARD:
|
||||
return x_key_pressed(x11, id);
|
||||
@ -194,9 +206,27 @@ static void x_input_free(void *data)
|
||||
if (x11->joypad)
|
||||
x11->joypad->destroy();
|
||||
|
||||
if (x11->ol)
|
||||
input_overlay_free(x11->ol);
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
static void x_input_poll_overlay(x11_input_t *x11)
|
||||
{
|
||||
if (!x11->ol)
|
||||
return;
|
||||
|
||||
if (x11->mouse_l)
|
||||
{
|
||||
int16_t norm_x = 0, norm_y = 0;
|
||||
bool valid = input_translate_coord_viewport(x11->mouse_x, x11->mouse_y, &norm_x, &norm_y);
|
||||
x11->ol_state = valid ? input_overlay_poll(x11->ol, norm_x, norm_y) : 0;
|
||||
}
|
||||
else
|
||||
x11->ol_state = 0;
|
||||
}
|
||||
|
||||
static void x_input_poll_mouse(x11_input_t *x11)
|
||||
{
|
||||
Window root_win, child_win;
|
||||
@ -218,12 +248,20 @@ static void x_input_poll_mouse(x11_input_t *x11)
|
||||
x11->mouse_l = mask & Button1Mask;
|
||||
x11->mouse_m = mask & Button2Mask;
|
||||
x11->mouse_r = mask & Button3Mask;
|
||||
|
||||
x_input_poll_overlay(x11);
|
||||
}
|
||||
|
||||
static void x_input_poll(void *data)
|
||||
{
|
||||
x11_input_t *x11 = (x11_input_t*)data;
|
||||
|
||||
if (x11->ol_defer)
|
||||
{
|
||||
x11->ol = input_overlay_new(NULL);
|
||||
x11->ol_defer = false;
|
||||
}
|
||||
|
||||
if (video_focus_func())
|
||||
XQueryKeymap(x11->display, x11->state);
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user