Add overlay rendering to GL.

This allows e.g. Android to render a keypad overlay for touch.
This commit is contained in:
Themaister 2012-12-19 13:26:11 +01:00
parent c42bbaf191
commit 5eb7432fff
12 changed files with 106 additions and 1 deletions

View File

@ -548,6 +548,7 @@ const gfx_ctx_driver_t gfx_ctx_android = {
NULL,
gfx_ctx_init_egl_image_buffer,
gfx_ctx_write_egl_image,
NULL,
"android",
#ifdef HAVE_RMENU
gfx_ctx_set_blend,

View File

@ -651,6 +651,7 @@ const gfx_ctx_driver_t gfx_ctx_drm_egl = {
gfx_ctx_get_proc_address,
gfx_ctx_init_egl_image_buffer,
gfx_ctx_write_egl_image,
NULL,
"drm-egl",
};

View File

@ -598,6 +598,7 @@ const gfx_ctx_driver_t gfx_ctx_glx = {
gfx_ctx_get_proc_address,
gfx_ctx_init_egl_image_buffer,
gfx_ctx_write_egl_image,
NULL,
"glx",
};

View File

@ -535,6 +535,7 @@ const gfx_ctx_driver_t gfx_ctx_ps3 = {
NULL,
gfx_ctx_init_egl_image_buffer,
gfx_ctx_write_egl_image,
NULL,
"ps3",
#ifdef HAVE_RMENU
gfx_ctx_set_blend,

View File

@ -371,6 +371,7 @@ const gfx_ctx_driver_t gfx_ctx_sdl_gl = {
gfx_ctx_get_proc_address,
gfx_ctx_init_egl_image_buffer,
gfx_ctx_write_egl_image,
NULL,
"sdl-gl",
};

View File

@ -480,5 +480,6 @@ const gfx_ctx_driver_t gfx_ctx_videocore = {
gfx_ctx_get_proc_address,
gfx_ctx_init_egl_image_buffer,
gfx_ctx_write_egl_image,
NULL,
"videocore",
};

View File

@ -456,6 +456,7 @@ const gfx_ctx_driver_t gfx_ctx_wgl = {
gfx_ctx_get_proc_address,
gfx_ctx_init_egl_image_buffer,
gfx_ctx_write_egl_image,
NULL,
"wgl",
};

View File

@ -490,6 +490,7 @@ const gfx_ctx_driver_t gfx_ctx_xdk = {
NULL,
gfx_ctx_init_egl_image_buffer,
gfx_ctx_write_egl_image,
NULL,
"xdk",
// RARCH_CONSOLE stuff.

View File

@ -549,6 +549,7 @@ const gfx_ctx_driver_t gfx_ctx_x_egl = {
gfx_ctx_get_proc_address,
gfx_ctx_init_egl_image_buffer,
gfx_ctx_write_egl_image,
NULL,
"x-egl",
};

View File

@ -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.
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.
const char *ident;

View File

@ -21,6 +21,7 @@
#include "../driver.h"
#include "../performance.h"
#include "scaler/scaler.h"
#include "image.h"
#include <stdint.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)
gl->font_ctx->render_msg(gl, msg);
if (gl->ctx_driver->post_render)
context_post_render_func(gl);
#if !defined(RARCH_CONSOLE)
context_update_window_title_func(false);
#endif
@ -1230,6 +1234,8 @@ static void gl_free(void *data)
#endif
glDeleteTextures(TEXTURES, gl->texture);
if (gl->tex_overlay)
glDeleteTextures(1, &gl->tex_overlay);
#if defined(HAVE_PSGL)
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->should_resize = true;
}
#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 = {
gl_init,
gl_frame,

View File

@ -76,6 +76,7 @@
#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_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_has_focus_func() gl->ctx_driver->has_focus()
#define context_check_window_func(quit, resize, width, height, frame_count) \
@ -279,6 +280,12 @@ typedef struct gl
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)
// PBOs used for asynchronous viewport readbacks.
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_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