Basic overlay POC works.

Add support for X11.
This commit is contained in:
Themaister 2012-12-20 12:24:49 +01:00
parent b4cd58afe7
commit 1250fae7f1
7 changed files with 201 additions and 15 deletions

View File

@ -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 \

View File

@ -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;

View File

@ -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)

View File

@ -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
View 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
View 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

View File

@ -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