mirror of
https://github.com/libretro/RetroArch
synced 2025-04-16 08:43:10 +00:00
(PSL1GHT) Add overlay support (#15149)
This commit is contained in:
parent
f46beade21
commit
6cc05ab5ce
@ -88,6 +88,14 @@ typedef struct
|
|||||||
u32 height;
|
u32 height;
|
||||||
} rsx_texture_t;
|
} rsx_texture_t;
|
||||||
|
|
||||||
|
#ifdef HAVE_OVERLAY
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
rsx_vertex_t *vertices;
|
||||||
|
rsx_texture_t texture;
|
||||||
|
} rsx_overlay_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int height;
|
int height;
|
||||||
@ -149,6 +157,13 @@ typedef struct
|
|||||||
|
|
||||||
float menu_texture_alpha;
|
float menu_texture_alpha;
|
||||||
|
|
||||||
|
#ifdef HAVE_OVERLAY
|
||||||
|
rsx_overlay_t *overlay;
|
||||||
|
unsigned overlays;
|
||||||
|
bool overlay_enable;
|
||||||
|
bool overlay_full_screen;
|
||||||
|
#endif
|
||||||
|
|
||||||
unsigned rotation;
|
unsigned rotation;
|
||||||
|
|
||||||
u16 width;
|
u16 width;
|
||||||
|
@ -1119,6 +1119,199 @@ static void rsx_draw_menu_vertices(rsx_t* rsx)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_OVERLAY
|
||||||
|
static void rsx_draw_overlay_vertices(rsx_t* rsx, unsigned image)
|
||||||
|
{
|
||||||
|
rsx_vertex_t *vertices = &rsx->overlay[image].vertices[0];
|
||||||
|
|
||||||
|
rsxAddressToOffset(&vertices[0].x, &rsx->pos_offset[RSX_SHADER_STOCK_BLEND]);
|
||||||
|
rsxAddressToOffset(&vertices[0].u, &rsx->uv_offset[RSX_SHADER_STOCK_BLEND]);
|
||||||
|
rsxAddressToOffset(&vertices[0].r, &rsx->col_offset[RSX_SHADER_STOCK_BLEND]);
|
||||||
|
|
||||||
|
rsxBindVertexArrayAttrib(rsx->context, rsx->pos_index[RSX_SHADER_STOCK_BLEND]->index, 0,
|
||||||
|
rsx->pos_offset[RSX_SHADER_STOCK_BLEND], sizeof(rsx_vertex_t), 2, GCM_VERTEX_DATA_TYPE_F32, GCM_LOCATION_RSX);
|
||||||
|
rsxBindVertexArrayAttrib(rsx->context, rsx->uv_index[RSX_SHADER_STOCK_BLEND]->index, 0,
|
||||||
|
rsx->uv_offset[RSX_SHADER_STOCK_BLEND], sizeof(rsx_vertex_t), 2, GCM_VERTEX_DATA_TYPE_F32, GCM_LOCATION_RSX);
|
||||||
|
rsxBindVertexArrayAttrib(rsx->context, rsx->col_index[RSX_SHADER_STOCK_BLEND]->index, 0,
|
||||||
|
rsx->col_offset[RSX_SHADER_STOCK_BLEND], sizeof(rsx_vertex_t), 4, GCM_VERTEX_DATA_TYPE_F32, GCM_LOCATION_RSX);
|
||||||
|
|
||||||
|
rsxLoadVertexProgram(rsx->context, rsx->vpo[RSX_SHADER_STOCK_BLEND], rsx->vp_ucode[RSX_SHADER_STOCK_BLEND]);
|
||||||
|
rsxSetVertexProgramParameter(rsx->context, rsx->vpo[RSX_SHADER_STOCK_BLEND], rsx->proj_matrix[RSX_SHADER_STOCK_BLEND], (float *)&rsx->mvp_no_rot);
|
||||||
|
rsxLoadFragmentProgramLocation(rsx->context, rsx->fpo[RSX_SHADER_STOCK_BLEND], rsx->fp_offset[RSX_SHADER_STOCK_BLEND], GCM_LOCATION_RSX);
|
||||||
|
|
||||||
|
rsxSetBlendEnable(rsx->context, GCM_TRUE);
|
||||||
|
rsxSetBlendFunc(rsx->context, GCM_SRC_ALPHA, GCM_ONE_MINUS_SRC_ALPHA, GCM_SRC_ALPHA, GCM_ONE_MINUS_SRC_ALPHA);
|
||||||
|
rsxSetBlendEquation(rsx->context, GCM_FUNC_ADD, GCM_FUNC_ADD);
|
||||||
|
|
||||||
|
rsxClearSurface(rsx->context, GCM_CLEAR_Z);
|
||||||
|
rsxDrawVertexArray(rsx->context, GCM_TYPE_TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
|
rsxSetBlendEnable(rsx->context, GCM_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rsx_overlay_vertex_geom(void *data,
|
||||||
|
unsigned image,
|
||||||
|
float x, float y,
|
||||||
|
float w, float h)
|
||||||
|
{
|
||||||
|
rsx_t *rsx = (rsx_t *)data;
|
||||||
|
rsx_overlay_t *o = NULL;
|
||||||
|
|
||||||
|
if (rsx)
|
||||||
|
o = (rsx_overlay_t *)&rsx->overlay[image];
|
||||||
|
|
||||||
|
if (!o)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Flipped, so we preserve top-down semantics. */
|
||||||
|
y = 1.0f - y;
|
||||||
|
h = -h;
|
||||||
|
|
||||||
|
o->vertices[0].x = x;
|
||||||
|
o->vertices[0].y = y;
|
||||||
|
o->vertices[1].x = x + w;
|
||||||
|
o->vertices[1].y = y;
|
||||||
|
o->vertices[2].x = x;
|
||||||
|
o->vertices[2].y = y + h;
|
||||||
|
o->vertices[3].x = x + w;
|
||||||
|
o->vertices[3].y = y + h;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rsx_overlay_tex_geom(void *data,
|
||||||
|
unsigned image,
|
||||||
|
float x, float y,
|
||||||
|
float w, float h)
|
||||||
|
{
|
||||||
|
rsx_t *rsx = (rsx_t *)data;
|
||||||
|
rsx_overlay_t *o = NULL;
|
||||||
|
|
||||||
|
if (rsx)
|
||||||
|
o = (rsx_overlay_t *)&rsx->overlay[image];
|
||||||
|
|
||||||
|
if (!o)
|
||||||
|
return;
|
||||||
|
|
||||||
|
o->vertices[0].u = x;
|
||||||
|
o->vertices[0].v = y;
|
||||||
|
o->vertices[1].u = x + w;
|
||||||
|
o->vertices[1].v = y;
|
||||||
|
o->vertices[2].u = x;
|
||||||
|
o->vertices[2].v = y + h;
|
||||||
|
o->vertices[3].u = x + w;
|
||||||
|
o->vertices[3].v = y + h;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rsx_free_overlay(rsx_t *rsx)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < rsx->overlays; i++)
|
||||||
|
{
|
||||||
|
if (rsx->overlay[i].texture.data)
|
||||||
|
rsxFree(rsx->overlay[i].texture.data);
|
||||||
|
if (rsx->overlay[i].vertices)
|
||||||
|
rsxFree(rsx->overlay[i].vertices);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(rsx->overlay);
|
||||||
|
rsx->overlay = NULL;
|
||||||
|
rsx->overlays = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool rsx_overlay_load(void *data,
|
||||||
|
const void *image_data, unsigned num_images)
|
||||||
|
{
|
||||||
|
unsigned i, j;
|
||||||
|
rsx_t *rsx = (rsx_t *)data;
|
||||||
|
const struct texture_image *images = (const struct texture_image *)image_data;
|
||||||
|
|
||||||
|
rsx_free_overlay(rsx);
|
||||||
|
rsx->overlay = (rsx_overlay_t *)calloc(num_images, sizeof(rsx_overlay_t));
|
||||||
|
|
||||||
|
if (!rsx->overlay)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rsx->overlays = num_images;
|
||||||
|
|
||||||
|
for (i = 0; i < num_images; i++)
|
||||||
|
{
|
||||||
|
rsx_overlay_t *o = (rsx_overlay_t *)&rsx->overlay[i];
|
||||||
|
o->vertices = (rsx_vertex_t *)rsxMemalign(128, sizeof(rsx_vertex_t) * RSX_MAX_VERTICES);
|
||||||
|
|
||||||
|
/* Default. Stretch to whole screen. */
|
||||||
|
rsx_overlay_tex_geom(rsx, i, 0, 0, 1, 1);
|
||||||
|
rsx_overlay_vertex_geom(rsx, i, 0, 0, 1, 1);
|
||||||
|
for (j = 0; j < RSX_MAX_VERTICES; j++)
|
||||||
|
{
|
||||||
|
o->vertices[j].r = 1.0f;
|
||||||
|
o->vertices[j].g = 1.0f;
|
||||||
|
o->vertices[j].b = 1.0f;
|
||||||
|
o->vertices[j].a = 1.0f;
|
||||||
|
}
|
||||||
|
o->texture.data = NULL;
|
||||||
|
o->texture.height = images[i].height;
|
||||||
|
o->texture.width = images[i].width;
|
||||||
|
rsx_load_texture_data(rsx, &o->texture, images[i].pixels, images[i].width, images[i].height, images[i].width*4,
|
||||||
|
true, false, TEXTURE_FILTER_LINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rsx_overlay_enable(void *data, bool state)
|
||||||
|
{
|
||||||
|
rsx_t *rsx = (rsx_t *)data;
|
||||||
|
rsx->overlay_enable = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rsx_overlay_full_screen(void *data, bool enable)
|
||||||
|
{
|
||||||
|
rsx_t *rsx = (rsx_t *)data;
|
||||||
|
rsx->overlay_full_screen = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rsx_overlay_set_alpha(void *data, unsigned image, float mod)
|
||||||
|
{
|
||||||
|
rsx_t *rsx = (rsx_t *)data;
|
||||||
|
|
||||||
|
if (rsx)
|
||||||
|
{
|
||||||
|
rsx->overlay[image].vertices[0].a = mod;
|
||||||
|
rsx->overlay[image].vertices[1].a = mod;
|
||||||
|
rsx->overlay[image].vertices[2].a = mod;
|
||||||
|
rsx->overlay[image].vertices[3].a = mod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rsx_render_overlay(void *data)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
rsx_t *rsx = (rsx_t *)data;
|
||||||
|
|
||||||
|
rsx_set_viewport(rsx, rsx->width, rsx->height, true, true);
|
||||||
|
|
||||||
|
for (i = 0; i < rsx->overlays; i++)
|
||||||
|
{
|
||||||
|
rsx_set_texture(rsx, &rsx->overlay[i].texture);
|
||||||
|
rsx_draw_overlay_vertices(rsx, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const video_overlay_interface_t rsx_overlay_interface =
|
||||||
|
{
|
||||||
|
rsx_overlay_enable,
|
||||||
|
rsx_overlay_load,
|
||||||
|
rsx_overlay_tex_geom,
|
||||||
|
rsx_overlay_vertex_geom,
|
||||||
|
rsx_overlay_full_screen,
|
||||||
|
rsx_overlay_set_alpha,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void rsx_get_overlay_interface(void *data,
|
||||||
|
const video_overlay_interface_t **iface) {*iface = &rsx_overlay_interface;}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void rsx_update_screen(rsx_t* gcm)
|
static void rsx_update_screen(rsx_t* gcm)
|
||||||
{
|
{
|
||||||
rsxBuffer *buffer = NULL;
|
rsxBuffer *buffer = NULL;
|
||||||
@ -1216,6 +1409,11 @@ static bool rsx_frame(void* data, const void* frame,
|
|||||||
osd_params, NULL);
|
osd_params, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_OVERLAY
|
||||||
|
if (gcm->overlay_enable)
|
||||||
|
rsx_render_overlay(gcm);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_GFX_WIDGETS
|
#ifdef HAVE_GFX_WIDGETS
|
||||||
if (widgets_active)
|
if (widgets_active)
|
||||||
gfx_widgets_frame(video_info);
|
gfx_widgets_frame(video_info);
|
||||||
@ -1427,7 +1625,7 @@ video_driver_t video_gcm =
|
|||||||
NULL, /* read_viewport */
|
NULL, /* read_viewport */
|
||||||
NULL, /* read_frame_raw */
|
NULL, /* read_frame_raw */
|
||||||
#ifdef HAVE_OVERLAY
|
#ifdef HAVE_OVERLAY
|
||||||
NULL,
|
rsx_get_overlay_interface,
|
||||||
#endif
|
#endif
|
||||||
rsx_get_poke_interface,
|
rsx_get_poke_interface,
|
||||||
rsx_wrap_type_to_enum,
|
rsx_wrap_type_to_enum,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user