mirror of
https://github.com/libretro/RetroArch
synced 2025-03-30 16:20:27 +00:00
Add overlay rendering to GL.
This allows e.g. Android to render a keypad overlay for touch.
This commit is contained in:
parent
c42bbaf191
commit
5eb7432fff
@ -548,6 +548,7 @@ const gfx_ctx_driver_t gfx_ctx_android = {
|
|||||||
NULL,
|
NULL,
|
||||||
gfx_ctx_init_egl_image_buffer,
|
gfx_ctx_init_egl_image_buffer,
|
||||||
gfx_ctx_write_egl_image,
|
gfx_ctx_write_egl_image,
|
||||||
|
NULL,
|
||||||
"android",
|
"android",
|
||||||
#ifdef HAVE_RMENU
|
#ifdef HAVE_RMENU
|
||||||
gfx_ctx_set_blend,
|
gfx_ctx_set_blend,
|
||||||
|
@ -651,6 +651,7 @@ const gfx_ctx_driver_t gfx_ctx_drm_egl = {
|
|||||||
gfx_ctx_get_proc_address,
|
gfx_ctx_get_proc_address,
|
||||||
gfx_ctx_init_egl_image_buffer,
|
gfx_ctx_init_egl_image_buffer,
|
||||||
gfx_ctx_write_egl_image,
|
gfx_ctx_write_egl_image,
|
||||||
|
NULL,
|
||||||
"drm-egl",
|
"drm-egl",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -598,6 +598,7 @@ const gfx_ctx_driver_t gfx_ctx_glx = {
|
|||||||
gfx_ctx_get_proc_address,
|
gfx_ctx_get_proc_address,
|
||||||
gfx_ctx_init_egl_image_buffer,
|
gfx_ctx_init_egl_image_buffer,
|
||||||
gfx_ctx_write_egl_image,
|
gfx_ctx_write_egl_image,
|
||||||
|
NULL,
|
||||||
"glx",
|
"glx",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -535,6 +535,7 @@ const gfx_ctx_driver_t gfx_ctx_ps3 = {
|
|||||||
NULL,
|
NULL,
|
||||||
gfx_ctx_init_egl_image_buffer,
|
gfx_ctx_init_egl_image_buffer,
|
||||||
gfx_ctx_write_egl_image,
|
gfx_ctx_write_egl_image,
|
||||||
|
NULL,
|
||||||
"ps3",
|
"ps3",
|
||||||
#ifdef HAVE_RMENU
|
#ifdef HAVE_RMENU
|
||||||
gfx_ctx_set_blend,
|
gfx_ctx_set_blend,
|
||||||
|
@ -371,6 +371,7 @@ const gfx_ctx_driver_t gfx_ctx_sdl_gl = {
|
|||||||
gfx_ctx_get_proc_address,
|
gfx_ctx_get_proc_address,
|
||||||
gfx_ctx_init_egl_image_buffer,
|
gfx_ctx_init_egl_image_buffer,
|
||||||
gfx_ctx_write_egl_image,
|
gfx_ctx_write_egl_image,
|
||||||
|
NULL,
|
||||||
"sdl-gl",
|
"sdl-gl",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -480,5 +480,6 @@ const gfx_ctx_driver_t gfx_ctx_videocore = {
|
|||||||
gfx_ctx_get_proc_address,
|
gfx_ctx_get_proc_address,
|
||||||
gfx_ctx_init_egl_image_buffer,
|
gfx_ctx_init_egl_image_buffer,
|
||||||
gfx_ctx_write_egl_image,
|
gfx_ctx_write_egl_image,
|
||||||
|
NULL,
|
||||||
"videocore",
|
"videocore",
|
||||||
};
|
};
|
||||||
|
@ -456,6 +456,7 @@ const gfx_ctx_driver_t gfx_ctx_wgl = {
|
|||||||
gfx_ctx_get_proc_address,
|
gfx_ctx_get_proc_address,
|
||||||
gfx_ctx_init_egl_image_buffer,
|
gfx_ctx_init_egl_image_buffer,
|
||||||
gfx_ctx_write_egl_image,
|
gfx_ctx_write_egl_image,
|
||||||
|
NULL,
|
||||||
"wgl",
|
"wgl",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -490,6 +490,7 @@ const gfx_ctx_driver_t gfx_ctx_xdk = {
|
|||||||
NULL,
|
NULL,
|
||||||
gfx_ctx_init_egl_image_buffer,
|
gfx_ctx_init_egl_image_buffer,
|
||||||
gfx_ctx_write_egl_image,
|
gfx_ctx_write_egl_image,
|
||||||
|
NULL,
|
||||||
"xdk",
|
"xdk",
|
||||||
|
|
||||||
// RARCH_CONSOLE stuff.
|
// RARCH_CONSOLE stuff.
|
||||||
|
@ -549,6 +549,7 @@ const gfx_ctx_driver_t gfx_ctx_x_egl = {
|
|||||||
gfx_ctx_get_proc_address,
|
gfx_ctx_get_proc_address,
|
||||||
gfx_ctx_init_egl_image_buffer,
|
gfx_ctx_init_egl_image_buffer,
|
||||||
gfx_ctx_write_egl_image,
|
gfx_ctx_write_egl_image,
|
||||||
|
NULL,
|
||||||
"x-egl",
|
"x-egl",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -101,6 +101,10 @@ typedef struct gfx_ctx_driver
|
|||||||
// Always returns true the first time it's called for a new index. The graphics core must handle a change in the handle correctly.
|
// Always returns true the first time it's called for a new index. The graphics core must handle a change in the handle correctly.
|
||||||
bool (*write_egl_image)(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle);
|
bool (*write_egl_image)(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle);
|
||||||
|
|
||||||
|
// Called after frame is rendered, but before swap.
|
||||||
|
// Can be used to render context-specific overlays and stuff.
|
||||||
|
bool (*post_render)(void *gl);
|
||||||
|
|
||||||
// Human readable string.
|
// Human readable string.
|
||||||
const char *ident;
|
const char *ident;
|
||||||
|
|
||||||
|
77
gfx/gl.c
77
gfx/gl.c
@ -21,6 +21,7 @@
|
|||||||
#include "../driver.h"
|
#include "../driver.h"
|
||||||
#include "../performance.h"
|
#include "../performance.h"
|
||||||
#include "scaler/scaler.h"
|
#include "scaler/scaler.h"
|
||||||
|
#include "image.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "../libretro.h"
|
#include "../libretro.h"
|
||||||
@ -1182,6 +1183,9 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei
|
|||||||
if (msg && gl->font_ctx)
|
if (msg && gl->font_ctx)
|
||||||
gl->font_ctx->render_msg(gl, msg);
|
gl->font_ctx->render_msg(gl, msg);
|
||||||
|
|
||||||
|
if (gl->ctx_driver->post_render)
|
||||||
|
context_post_render_func(gl);
|
||||||
|
|
||||||
#if !defined(RARCH_CONSOLE)
|
#if !defined(RARCH_CONSOLE)
|
||||||
context_update_window_title_func(false);
|
context_update_window_title_func(false);
|
||||||
#endif
|
#endif
|
||||||
@ -1230,6 +1234,8 @@ static void gl_free(void *data)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
glDeleteTextures(TEXTURES, gl->texture);
|
glDeleteTextures(TEXTURES, gl->texture);
|
||||||
|
if (gl->tex_overlay)
|
||||||
|
glDeleteTextures(1, &gl->tex_overlay);
|
||||||
|
|
||||||
#if defined(HAVE_PSGL)
|
#if defined(HAVE_PSGL)
|
||||||
glBindBuffer(GL_TEXTURE_REFERENCE_BUFFER_SCE, 0);
|
glBindBuffer(GL_TEXTURE_REFERENCE_BUFFER_SCE, 0);
|
||||||
@ -1776,9 +1782,78 @@ static void gl_set_aspect_ratio(void *data, unsigned aspectratio_index)
|
|||||||
gl->keep_aspect = true;
|
gl->keep_aspect = true;
|
||||||
gl->should_resize = true;
|
gl->should_resize = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool gl_load_overlay(gl_t *gl, const char *path)
|
||||||
|
{
|
||||||
|
if (!gl->tex_overlay)
|
||||||
|
glGenTextures(1, &gl->tex_overlay);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, gl->tex_overlay);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
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)));
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, RARCH_GL_INTERNAL_FORMAT32,
|
||||||
|
img.width, img.height, 0, RARCH_GL_TEXTURE_TYPE32,
|
||||||
|
RARCH_GL_FORMAT32, img.pixels);
|
||||||
|
|
||||||
|
free(img.pixels);
|
||||||
|
gl_set_overlay_tex_coord(gl, 0, 0, 1, 1); // Default. Stretch to whole screen.
|
||||||
|
gl_set_overlay_vertex_coord(gl, 0, 0, 1, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_set_overlay_tex_coord(gl_t *gl,
|
||||||
|
GLfloat x, GLfloat y,
|
||||||
|
GLfloat w, GLfloat h)
|
||||||
|
{
|
||||||
|
gl->overlay_tex_coord[0] = x; gl->overlay_tex_coord[1] = y;
|
||||||
|
gl->overlay_tex_coord[2] = x + w; gl->overlay_tex_coord[3] = y;
|
||||||
|
gl->overlay_tex_coord[4] = x; gl->overlay_tex_coord[5] = y + h;
|
||||||
|
gl->overlay_tex_coord[6] = x + w; gl->overlay_tex_coord[7] = y + h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_set_overlay_vertex_coord(gl_t *gl,
|
||||||
|
GLfloat x, GLfloat y,
|
||||||
|
GLfloat w, GLfloat h)
|
||||||
|
{
|
||||||
|
// Flipped, so we preserve top-down semantics.
|
||||||
|
y = 1.0f - y;
|
||||||
|
h = -h;
|
||||||
|
|
||||||
|
gl->overlay_vertex_coord[0] = x; gl->overlay_vertex_coord[1] = y;
|
||||||
|
gl->overlay_vertex_coord[2] = x + w; gl->overlay_vertex_coord[3] = y;
|
||||||
|
gl->overlay_vertex_coord[4] = x; gl->overlay_vertex_coord[5] = y + h;
|
||||||
|
gl->overlay_vertex_coord[6] = x + w; gl->overlay_vertex_coord[7] = y + h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_render_overlay(gl_t *gl)
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_2D, gl->tex_overlay);
|
||||||
|
|
||||||
|
gl_shader_use_func(gl, 0);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
gl->coords.vertex = gl->overlay_vertex_coord;
|
||||||
|
gl->coords.tex_coord = gl->overlay_tex_coord;
|
||||||
|
gl_shader_set_coords_func(gl, &gl->coords, &gl->mvp);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
|
gl->coords.vertex = vertex_ptr;
|
||||||
|
gl->coords.tex_coord = gl->tex_coords;
|
||||||
|
}
|
||||||
|
|
||||||
const video_driver_t video_gl = {
|
const video_driver_t video_gl = {
|
||||||
gl_init,
|
gl_init,
|
||||||
gl_frame,
|
gl_frame,
|
||||||
|
@ -76,6 +76,7 @@
|
|||||||
#define context_translate_aspect_func(width, height) gl->ctx_driver->translate_aspect(width, height)
|
#define context_translate_aspect_func(width, height) gl->ctx_driver->translate_aspect(width, height)
|
||||||
#define context_set_resize_func(width, height) gl->ctx_driver->set_resize(width, height)
|
#define context_set_resize_func(width, height) gl->ctx_driver->set_resize(width, height)
|
||||||
#define context_swap_buffers_func() gl->ctx_driver->swap_buffers()
|
#define context_swap_buffers_func() gl->ctx_driver->swap_buffers()
|
||||||
|
#define context_post_render_func(gl) gl->ctx_driver->post_render(gl)
|
||||||
#define context_swap_interval_func(var) gl->ctx_driver->swap_interval(var)
|
#define context_swap_interval_func(var) gl->ctx_driver->swap_interval(var)
|
||||||
#define context_has_focus_func() gl->ctx_driver->has_focus()
|
#define context_has_focus_func() gl->ctx_driver->has_focus()
|
||||||
#define context_check_window_func(quit, resize, width, height, frame_count) \
|
#define context_check_window_func(quit, resize, width, height, frame_count) \
|
||||||
@ -279,6 +280,12 @@ typedef struct gl
|
|||||||
|
|
||||||
bool egl_images;
|
bool egl_images;
|
||||||
|
|
||||||
|
// Overlay rendering
|
||||||
|
GLuint tex_overlay;
|
||||||
|
GLfloat overlay_tex_coord[8];
|
||||||
|
GLfloat overlay_vertex_coord[8];
|
||||||
|
GLfloat overlay_alpha_mod; // TODO. Needs a specific shader.
|
||||||
|
|
||||||
#if !defined(HAVE_OPENGLES) && defined(HAVE_FFMPEG)
|
#if !defined(HAVE_OPENGLES) && defined(HAVE_FFMPEG)
|
||||||
// PBOs used for asynchronous viewport readbacks.
|
// PBOs used for asynchronous viewport readbacks.
|
||||||
GLuint pbo_readback[4];
|
GLuint pbo_readback[4];
|
||||||
@ -359,4 +366,14 @@ void gl_shader_set_coords(gl_t *gl, const struct gl_coords *coords, const math_m
|
|||||||
void gl_init_fbo(gl_t *gl, unsigned width, unsigned height);
|
void gl_init_fbo(gl_t *gl, unsigned width, unsigned height);
|
||||||
void gl_deinit_fbo(gl_t *gl);
|
void gl_deinit_fbo(gl_t *gl);
|
||||||
|
|
||||||
|
bool gl_load_overlay(gl_t *gl, const char *path);
|
||||||
|
void gl_set_overlay_tex_coord(gl_t *gl,
|
||||||
|
GLfloat x, GLfloat y, // Relative coordinates [0, 1] range for screen.
|
||||||
|
GLfloat w, GLfloat h);
|
||||||
|
void gl_set_overlay_vertex_coord(gl_t *gl,
|
||||||
|
GLfloat x, GLfloat y, // Relative coordinates [0, 1] range for screen.
|
||||||
|
GLfloat w, GLfloat h);
|
||||||
|
void gl_render_overlay(gl_t *gl);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user