Add RETRO_DEVICE_POINTER.

Implemented only for X11 so far.

Also clears up viewport_size call.
Changed to viewport_info to also grab X/Y info.
This commit is contained in:
Themaister 2012-10-28 00:38:31 +02:00
parent 690b592301
commit 1908a81e1c
14 changed files with 164 additions and 69 deletions

View File

@ -183,6 +183,8 @@ typedef struct input_driver
const char *ident;
} input_driver_t;
struct rarch_viewport;
typedef struct video_driver
{
void *(*init)(const video_info_t *video, const input_driver_t **input, void **input_data);
@ -206,7 +208,7 @@ typedef struct video_driver
#endif
void (*set_rotation)(void *data, unsigned rotation);
void (*viewport_size)(void *data, unsigned *width, unsigned *height);
void (*viewport_info)(void *data, struct rarch_viewport *vp);
// Reads out in BGR byte order (24bpp).
bool (*read_viewport)(void *data, uint8_t *buffer);
@ -323,7 +325,7 @@ extern const input_driver_t input_null;
#define video_set_shader_func(type, path) driver.video->set_shader(driver.video_data, type, path)
#define video_set_rotation_func(rotate) driver.video->set_rotation(driver.video_data, rotate)
#define video_set_aspect_ratio_func(aspect_idx) driver.video->set_aspect_ratio(driver.video_data, aspect_idx)
#define video_viewport_size_func(width, height) driver.video->viewport_size(driver.video_data, width, height)
#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_free_func() driver.video->free(driver.video_data)

View File

@ -213,26 +213,26 @@ enum rarch_game_type
RARCH_CART_SUFAMI
};
typedef struct
typedef struct rarch_boolean_state
{
bool enable;
unsigned value;
} rarch_boolean_state_t;
typedef struct
typedef struct rarch_frame_count
{
bool is_expired;
unsigned expire_frame;
unsigned current;
} rarch_frame_count_t;
typedef struct
typedef struct rarch_resolution
{
unsigned idx;
unsigned id;
} rarch_resolution_t;
typedef struct
typedef struct rarch_viewport
{
int x;
int y;

View File

@ -156,10 +156,12 @@ void D3DVideo::set_rotation(unsigned rot)
rotation = rot;
}
void D3DVideo::viewport_size(unsigned &width, unsigned &height)
void D3DVideo::viewport_size(rarch_viewport &vp)
{
width = final_viewport.Width;
height = final_viewport.Height;
vp.x = final_viewport.X;
vp.y = final_viewport.Y;
vp.width = final_viewport.Width;
vp.height = final_viewport.Height;
}
bool D3DVideo::read_viewport(uint8_t *buffer)
@ -981,9 +983,9 @@ static void d3d9_free(void *data)
delete reinterpret_cast<D3DVideo*>(data);
}
static void d3d9_viewport_size(void *data, unsigned *width, unsigned *height)
static void d3d9_viewport_info(void *data, struct rarch_viewport *vp)
{
reinterpret_cast<D3DVideo*>(data)->viewport_size(*width, *height);
reinterpret_cast<D3DVideo*>(data)->viewport_info(*vp);
}
static bool d3d9_read_viewport(void *data, uint8_t *buffer)
@ -1008,7 +1010,7 @@ const video_driver_t video_d3d9 = {
"d3d9",
d3d9_set_rotation,
d3d9_viewport_size,
d3d9_viewport_info,
d3d9_read_viewport,
};

View File

@ -44,7 +44,7 @@ class D3DVideo
bool focus() const;
void set_nonblock_state(bool state);
void set_rotation(unsigned rot);
void viewport_size(unsigned &width, unsigned &height);
void viewport_info(rarch_viewport &vp);
bool read_viewport(uint8_t *buffer);
private:

View File

@ -384,10 +384,15 @@ static void video_set_rotation(void *data, unsigned rot)
ext->driver->set_rotation(ext->handle, rot);
}
static void video_viewport_size(void *data, unsigned *width, unsigned *height)
static void video_viewport_info(void *data, struct rarch_viewport *vp)
{
ext_t *ext = (ext_t*)data;
ext->driver->viewport_size(ext->handle, width, height);
unsigned width = 0, height = 0;
ext->driver->viewport_size(ext->handle, &width, &height);
vp->x = vp->y = 0;
vp->width = width;
vp->height = height;
}
static bool video_read_viewport(void *data, uint8_t *buffer)
@ -420,7 +425,7 @@ const video_driver_t video_ext = {
#endif
video_set_rotation,
video_viewport_size,
video_viewport_info,
video_read_viewport,
};

View File

@ -206,9 +206,9 @@ static void calculate_font_coords(gl_t *gl,
GLfloat scale_factor = scale;
GLfloat lx = pos_x;
GLfloat hx = (GLfloat)gl->font_last_width * scale_factor / gl->vp_width + lx;
GLfloat hx = (GLfloat)gl->font_last_width * scale_factor / gl->vp.width + lx;
GLfloat ly = pos_y;
GLfloat hy = (GLfloat)gl->font_last_height * scale_factor / gl->vp_height + ly;
GLfloat hy = (GLfloat)gl->font_last_height * scale_factor / gl->vp.height + ly;
font_vertex[0] = lx;
font_vertex[2] = hx;
@ -219,8 +219,8 @@ static void calculate_font_coords(gl_t *gl,
font_vertex[5] = ly;
font_vertex[7] = ly;
GLfloat shift_x = 2.0f / gl->vp_width;
GLfloat shift_y = 2.0f / gl->vp_height;
GLfloat shift_x = 2.0f / gl->vp.width;
GLfloat shift_y = 2.0f / gl->vp.height;
for (unsigned i = 0; i < 4; i++)
{
font_vertex_dark[2 * i + 0] = font_vertex[2 * i + 0] - shift_x;
@ -318,7 +318,7 @@ void gl_render_msg(void *data, const char *msg)
#ifdef HAVE_FREETYPE
gl_t *gl = (gl_t*)data;
setup_font(data, msg,
g_settings.video.font_scale ? (GLfloat)gl->vp_width / (GLfloat)gl->full_x : 1.0f,
g_settings.video.font_scale ? (GLfloat)gl->vp.width / (GLfloat)gl->full_x : 1.0f,
g_settings.video.msg_pos_x, g_settings.video.msg_pos_y);
#endif
}

View File

@ -689,12 +689,13 @@ void gl_set_viewport(gl_t *gl, unsigned width, unsigned height, bool force_full,
}
glViewport(x, y, width, height);
gl->vp.x = x;
gl->vp.y = y;
gl->vp.width = width;
gl->vp.height = height;
gl_set_projection(gl, &ortho, allow_rotate);
gl->vp_width = width;
gl->vp_height = height;
// Set last backbuffer viewport.
if (!force_full)
{
@ -808,7 +809,7 @@ static void gl_frame_fbo(gl_t *gl, const struct gl_tex_info *tex_info)
gl_set_viewport(gl, rect->img_width, rect->img_height, true, false);
gl_shader_set_params(prev_rect->img_width, prev_rect->img_height,
prev_rect->width, prev_rect->height,
gl->vp_width, gl->vp_height, gl->frame_count,
gl->vp.width, gl->vp.height, gl->frame_count,
tex_info, gl->prev_info, fbo_tex_info, fbo_tex_info_cnt);
gl_shader_set_coords(&gl->coords, &gl->mvp);
@ -835,7 +836,7 @@ static void gl_frame_fbo(gl_t *gl, const struct gl_tex_info *tex_info)
gl_set_viewport(gl, gl->win_width, gl->win_height, false, true);
gl_shader_set_params(prev_rect->img_width, prev_rect->img_height,
prev_rect->width, prev_rect->height,
gl->vp_width, gl->vp_height, gl->frame_count,
gl->vp.width, gl->vp.height, gl->frame_count,
tex_info, gl->prev_info, fbo_tex_info, fbo_tex_info_cnt);
gl->coords.vertex = vertex_ptr;
@ -1121,7 +1122,7 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei
glClear(GL_COLOR_BUFFER_BIT);
gl_shader_set_params(width, height,
gl->tex_w, gl->tex_h,
gl->vp_width, gl->vp_height,
gl->vp.width, gl->vp.height,
gl->frame_count,
&tex_info, gl->prev_info, NULL, 0);
@ -1498,24 +1499,17 @@ static bool gl_set_shader(void *data, enum rarch_shader_type type, const char *p
#endif
#ifndef NO_GL_READ_VIEWPORT
static void gl_viewport_size(void *data, unsigned *width, unsigned *height)
static void gl_viewport_info(void *data, struct rarch_viewport *vp)
{
(void)data;
GLint vp[4];
glGetIntegerv(GL_VIEWPORT, vp);
*width = vp[2];
*height = vp[3];
gl_t *gl = (gl_t*)data;
*vp = gl->vp;
}
static bool gl_read_viewport(void *data, uint8_t *buffer)
{
(void)data;
gl_t *gl = (gl_t*)data;
GLint vp[4];
glGetIntegerv(GL_VIEWPORT, vp);
glPixelStorei(GL_PACK_ALIGNMENT, get_alignment(vp[2] * 3));
glPixelStorei(GL_PACK_ALIGNMENT, 1);
#ifdef HAVE_OPENGLES
glReadPixels(vp[0], vp[1],
@ -1523,7 +1517,7 @@ static bool gl_read_viewport(void *data, uint8_t *buffer)
GL_RGB, GL_UNSIGNED_BYTE, buffer);
uint8_t *pixels = (uint8_t*)buffer;
unsigned num_pixels = vp[2] * vp[3];
unsigned num_pixels = gl->vp.width * gl->vp.height;
// Convert RGB to BGR. Formats are byte ordered, so just swap 1st and 3rd byte.
for (unsigned i = 0; i <= num_pixels; pixels += 3, i++)
{
@ -1532,10 +1526,10 @@ static bool gl_read_viewport(void *data, uint8_t *buffer)
pixels[0] = tmp;
}
#else
glPixelStorei(GL_PACK_ROW_LENGTH, vp[2]);
glPixelStorei(GL_PACK_ROW_LENGTH, gl->vp.width);
glReadPixels(vp[0], vp[1],
vp[2], vp[3],
glReadPixels(gl->vp.x, gl->vp.y,
gl->vp.width, gl->vp.height,
GL_BGR, GL_UNSIGNED_BYTE, buffer);
#endif
@ -1681,7 +1675,7 @@ const video_driver_t video_gl = {
gl_set_rotation,
#ifndef NO_GL_READ_VIEWPORT
gl_viewport_size,
gl_viewport_info,
gl_read_viewport,
#else
NULL,

View File

@ -202,8 +202,9 @@ typedef struct gl
unsigned win_width;
unsigned win_height;
unsigned vp_width, vp_out_width;
unsigned vp_height, vp_out_height;
struct rarch_viewport vp;
unsigned vp_out_width;
unsigned vp_out_height;
unsigned last_width[TEXTURES];
unsigned last_height[TEXTURES];
unsigned tex_w, tex_h;

View File

@ -148,3 +148,27 @@ bool input_joypad_hat_raw(const rarch_joypad_driver_t *driver,
return driver->button(joypad, HAT_MAP(hat, hat_dir));
}
bool input_translate_coord_viewport(int mouse_x, int mouse_y,
int16_t *res_x, int16_t *res_y)
{
struct rarch_viewport vp = {0};
if (driver.video->viewport_info)
video_viewport_info_func(&vp);
else
return false;
mouse_x -= vp.x;
mouse_y -= vp.y;
int scaled_x = (2 * mouse_x * 0x7fff) / (int)vp.width - 0x7fff;
int scaled_y = (2 * mouse_y * 0x7fff) / (int)vp.height - 0x7fff;
if (scaled_x < -0x7fff || scaled_x > 0x7fff)
scaled_x = -0x8000; // OOB
if (scaled_y < -0x7fff || scaled_y > 0x7fff)
scaled_y = -0x8000; // OOB
*res_x = scaled_x;
*res_y = scaled_y;
return true;
}

View File

@ -46,6 +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);
typedef struct rarch_joypad_driver
{
bool (*init)(void);

View File

@ -208,6 +208,34 @@ static int16_t x_mouse_state(x11_input_t *x11, unsigned id)
}
}
static int16_t x_pointer_state(x11_input_t *x11, unsigned id)
{
int16_t res_x = 0, res_y = 0;
bool valid = input_translate_coord_viewport(x11->mouse_x, x11->mouse_y, &res_x, &res_y);
if (!valid)
return 0;
bool inside = (res_x >= -0x7fff) && (res_x <= 0x7fff) &&
(res_y >= -0x7fff) && (res_y <= 0x7fff);
if (!inside)
return 0;
switch (id)
{
case RETRO_DEVICE_ID_POINTER_X:
return res_x;
case RETRO_DEVICE_ID_POINTER_Y:
return res_y;
case RETRO_DEVICE_ID_POINTER_PRESSED:
return x11->mouse_l;
default:
return 0;
}
}
static int16_t x_lightgun_state(x11_input_t *x11, unsigned id)
{
switch (id)
@ -250,6 +278,9 @@ static int16_t x_input_state(void *data, const struct retro_keybind **binds, uns
case RETRO_DEVICE_MOUSE:
return x_mouse_state(x11, id);
case RETRO_DEVICE_POINTER:
return x_pointer_state(x11, id);
case RETRO_DEVICE_LIGHTGUN:
return x_lightgun_state(x11, id);
@ -284,8 +315,8 @@ static void x_input_poll_mouse(x11_input_t *x11)
&win_x, &win_y,
&mask);
x11->mouse_x = root_x;
x11->mouse_y = root_y;
x11->mouse_x = win_x;
x11->mouse_y = win_y;
x11->mouse_l = mask & Button1Mask;
x11->mouse_m = mask & Button2Mask;
x11->mouse_r = mask & Button3Mask;

View File

@ -135,6 +135,12 @@ static void update_input(void)
if (mouse_r)
fprintf(stderr, "Mouse R pressed.\n");
bool pointer_pressed = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED);
int16_t pointer_x = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X);
int16_t pointer_y = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y);
if (pointer_pressed)
fprintf(stderr, "Pointer: (%6d, %6d).\n", pointer_x, pointer_y);
dir_x += input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X) / 2000;
dir_y += input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y) / 2000;
//dir_x += input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X) / 2000;

View File

@ -19,7 +19,7 @@ extern "C" {
#endif
// Used for checking API/ABI mismatches that can break libretro implementations.
// It is not incremented for compatible changes.
// It is not incremented for compatible changes to the API.
#define RETRO_API_VERSION 1
// Libretro's fundamental device abstractions.
@ -50,6 +50,23 @@ extern "C" {
// Only use ANALOG type when polling for analog values of the axes.
#define RETRO_DEVICE_ANALOG 5
// Abstracts the concept of a pointing mechanism, e.g. touch.
// This allows libretro to query in absolute coordinates where on the screen a mouse (or something similar) is being placed.
// For a touch centric device, coordinates reported are the coordinates of the press.
//
// Coordinates in X and Y are reported as:
// [-0x7fff, 0x7fff]: -0x7fff corresponds to the far left/top of the screen,
// and 0x7fff corresponds to the far right/bottom of the screen.
// The "screen" is here defined as area that is passed to the frontend and later displayed on the monitor.
// The frontend is free to scale/resize this screen as it sees fit, however,
// (X, Y) = (-0x7fff, -0x7fff) will correspond to the top-left pixel of the game image, etc.
//
// To check if the pointer coordinates are valid (e.g. a touch display actually being touched),
// PRESSED returns 1 or 0.
// If using a mouse, PRESSED will usually correspond to the left mouse button.
// PRESSED will only return 1 if the pointer is inside the game screen.
#define RETRO_DEVICE_POINTER 6
// These device types are specializations of the base types above.
// They should only be used in retro_set_controller_type() to inform libretro implementations
// about use of a very specific device type.
@ -101,6 +118,11 @@ extern "C" {
#define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5
#define RETRO_DEVICE_ID_LIGHTGUN_START 6
// Id values for POINTER.
#define RETRO_DEVICE_ID_POINTER_X 0
#define RETRO_DEVICE_ID_POINTER_Y 1
#define RETRO_DEVICE_ID_POINTER_PRESSED 2
// Returned from retro_get_region().
#define RETRO_REGION_NTSC 0
#define RETRO_REGION_PAL 1

View File

@ -91,10 +91,11 @@ static void set_fast_forward_button(bool new_button_state, bool new_hold_button_
#if defined(HAVE_SCREENSHOTS) && !defined(_XBOX)
static bool take_screenshot_viewport(void)
{
struct rarch_viewport vp = {0};
unsigned width = 0, height = 0;
video_viewport_size_func(&width, &height);
video_viewport_info_func(&vp);
if (!width || !height)
if (!vp.width || !vp.height)
return false;
uint8_t *buffer = (uint8_t*)malloc(width * height * 3);
@ -110,7 +111,7 @@ static bool take_screenshot_viewport(void)
// Data read from viewport is in bottom-up order, suitable for BMP.
if (!screenshot_dump(g_settings.screenshot_directory,
buffer,
width, height, width * 3, true))
vp.width, vp.height, vp.width * 3, true))
{
free(buffer);
return false;
@ -141,7 +142,7 @@ static void take_screenshot(void)
bool ret = false;
if (g_settings.video.gpu_screenshot && driver.video->read_viewport && driver.video->viewport_size)
if (g_settings.video.gpu_screenshot && driver.video->read_viewport && driver.video->viewport_info)
ret = take_screenshot_viewport();
else if (g_extern.frame_cache.data)
ret = take_screenshot_raw();
@ -197,9 +198,9 @@ static void recording_dump_frame(const void *data, unsigned width, unsigned heig
if (g_extern.record_gpu_buffer)
{
unsigned gpu_w = 0, gpu_h = 0;
video_viewport_size_func(&gpu_w, &gpu_h);
if (!gpu_w || !gpu_h)
struct rarch_viewport vp = {0};
video_viewport_info_func(&vp);
if (!vp.width || !vp.height)
{
RARCH_WARN("Viewport size calculation failed! Will continue using raw data. This will probably not work right ...\n");
free(g_extern.record_gpu_buffer);
@ -210,7 +211,7 @@ static void recording_dump_frame(const void *data, unsigned width, unsigned heig
}
// User has resized. We're kinda fucked now.
if (gpu_w != g_extern.record_gpu_width || gpu_h != g_extern.record_gpu_height)
if (vp.width != g_extern.record_gpu_width || vp.height != g_extern.record_gpu_height)
{
static const char msg[] = "Recording terminated due to resize.";
RARCH_WARN("%s\n", msg);
@ -1262,10 +1263,10 @@ static void init_recording(void)
if (g_settings.video.gpu_record && driver.video->read_viewport)
{
unsigned width = 0, height = 0;
video_viewport_size_func(&width, &height);
struct rarch_viewport vp = {0};
video_viewport_info_func(&vp);
if (!width || !height)
if (!vp.width || !vp.height)
{
RARCH_ERR("Failed to get viewport information from video driver. "
"Cannot start recording ...\n");
@ -1273,19 +1274,24 @@ static void init_recording(void)
return;
}
params.out_width = width;
params.out_height = height;
params.fb_width = next_pow2(width);
params.fb_height = next_pow2(height);
params.aspect_ratio = (float)width / height;
params.out_width = vp.width;
params.out_height = vp.height;
params.fb_width = next_pow2(vp.width);
params.fb_height = next_pow2(vp.height);
if (g_settings.video.force_aspect && (g_settings.video.aspect_ratio > 0.0f))
params.aspect_ratio = g_settings.video.aspect_ratio;
else
params.aspect_ratio = (float)vp.width / vp.height;
params.pix_fmt = FFEMU_PIX_BGR24;
g_extern.record_gpu_width = width;
g_extern.record_gpu_height = height;
g_extern.record_gpu_width = vp.width;
g_extern.record_gpu_height = vp.height;
RARCH_LOG("Detected viewport of %u x %u\n",
width, height);
vp.width, vp.height);
g_extern.record_gpu_buffer = (uint8_t*)malloc(width * height * 3);
g_extern.record_gpu_buffer = (uint8_t*)malloc(vp.width * vp.height * 3);
if (!g_extern.record_gpu_buffer)
{
RARCH_ERR("Failed to allocate GPU record buffer.\n");