video_layout gl basic implementation

This commit is contained in:
Huw Pascoe 2019-04-03 05:04:17 +01:00
parent 2c56011f84
commit acb28a38c4
2 changed files with 344 additions and 5 deletions

View File

@ -204,6 +204,13 @@ struct gl
GLuint texture[GFX_MAX_TEXTURES];
GLuint hw_render_fbo[GFX_MAX_TEXTURES];
#ifdef HAVE_VIDEO_LAYOUT
bool video_layout_resize;
GLuint video_layout_fbo;
GLuint video_layout_fbo_texture;
GLuint video_layout_white_texture;
#endif
unsigned tex_index; /* For use with PREV. */
unsigned textures;
unsigned fbo_feedback_pass;

View File

@ -979,7 +979,7 @@ static void gl2_create_fbo_textures(gl_t *gl,
glGenTextures(chain->fbo_pass, chain->fbo_texture);
for (i = 0; i < chain->fbo_pass; i++)
gl2_create_fbo_texture(gl,
gl2_create_fbo_texture(gl,
(gl2_renderchain_data_t*)gl->renderchain_data,
i, chain->fbo_texture[i]);
@ -2556,6 +2556,318 @@ static void gl2_pbo_async_readback(gl_t *gl)
gl2_renderchain_unbind_pbo();
}
#ifdef HAVE_VIDEO_LAYOUT
static float video_layout_layer_tex_coord[] = {
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
};
static void gl2_video_layout_fbo_init(gl_t *gl, unsigned width, unsigned height)
{
glGenTextures(1, &gl->video_layout_fbo_texture);
glBindTexture(GL_TEXTURE_2D, gl->video_layout_fbo_texture);
gl2_load_texture_image(GL_TEXTURE_2D, 0, RARCH_GL_INTERNAL_FORMAT32,
width, height, 0, GL_RGBA, GL_FLOAT, NULL);
gl2_gen_fb(1, &gl->video_layout_fbo);
gl2_bind_fb(gl->video_layout_fbo);
gl2_fb_texture_2d(RARCH_GL_FRAMEBUFFER, RARCH_GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, gl->video_layout_fbo_texture, 0);
if (gl2_check_fb_status(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
RARCH_LOG("Unable to create FBO for video_layout\n");
gl2_bind_fb(0);
}
static void gl2_video_layout_fbo_free(gl_t *gl)
{
if (gl->video_layout_fbo)
{
gl2_delete_fb(1, &gl->video_layout_fbo);
gl->video_layout_fbo = 0;
}
if (gl->video_layout_fbo_texture)
{
glDeleteTextures(1, &gl->video_layout_fbo_texture);
gl->video_layout_fbo_texture = 0;
}
}
static void gl2_video_layout_viewport(gl_t *gl, video_frame_info_t *video_info)
{
if (!video_layout_valid())
return;
if (gl->video_layout_resize)
{
if (gl->video_layout_fbo)
gl2_video_layout_fbo_free(gl);
gl2_video_layout_fbo_init(gl, video_info->width, video_info->height);
video_layout_view_change();
gl->video_layout_resize = false;
}
if (video_layout_view_on_change())
{
video_layout_bounds_t b;
b.x = 0.0f;
b.y = 0.0f;
b.w = (float)video_info->width;
b.h = (float)video_info->height;
video_layout_view_fit_bounds(b);
}
if (video_layout_screen_count())
{
const video_layout_bounds_t *bounds;
bounds = video_layout_screen(0);
glViewport(
bounds->x, video_info->height - bounds->y - bounds->h,
bounds->w, bounds->h
);
}
}
static void gl2_video_layout_render(gl_t *gl, video_frame_info_t *video_info)
{
int i;
if (!video_layout_valid())
return;
glViewport(0, 0, video_info->width, video_info->height);
glEnable(GL_BLEND);
for (i = 0; i < video_layout_layer_count(); ++i)
video_layout_layer_render(video_info, i);
glDisable(GL_BLEND);
}
static void gl2_video_layout_init(gl_t *gl)
{
uint32_t px;
gl->video_layout_resize = true;
/* white 1px texture for drawing solid colors */
px = 0xFFFFFFFF;
glGenTextures(1, &gl->video_layout_white_texture);
gl_load_texture_data(gl->video_layout_white_texture,
RARCH_WRAP_EDGE, TEXTURE_FILTER_NEAREST,
sizeof(uint32_t), 1, 1, &px, sizeof(uint32_t));
}
static void gl2_video_layout_free(gl_t *gl)
{
gl2_video_layout_fbo_free(gl);
if (gl->video_layout_white_texture)
{
glDeleteTextures(1, &gl->video_layout_white_texture);
gl->video_layout_white_texture = 0;
}
}
static void *gl2_video_layout_take_image(void *video_driver_data, struct texture_image image)
{
unsigned alignment;
GLuint tex;
tex = 0;
alignment = video_pixel_get_alignment(image.width * sizeof(uint32_t));
glGenTextures(1, &tex);
gl_load_texture_data(tex,
RARCH_WRAP_EDGE, TEXTURE_FILTER_MIPMAP_LINEAR,
alignment, image.width, image.height, image.pixels, sizeof(uint32_t));
free(image.pixels);
return (void*)(uintptr_t)tex;
}
static void gl2_video_layout_free_image(void *video_driver_data, void *image)
{
GLuint tex;
tex = (GLuint)(uintptr_t)image;
glDeleteTextures(1, &tex);
}
static void gl2_video_layout_layer_begin(const video_layout_render_info_t *info)
{
gl_t *gl;
gl = (gl_t*)info->video_driver_data;
gl2_bind_fb(gl->video_layout_fbo);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
gl->shader->use(gl, gl->shader_data,
VIDEO_SHADER_STOCK_BLEND, true);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
static void gl2_video_layout_image(const video_layout_render_info_t *info, void *image_handle, void *alpha_handle)
{
/* TODO alpha_handle */
gl_t *gl;
video_frame_info_t *video_info;
video_layout_bounds_t b;
float coord[8];
float color[16];
int i;
gl = (gl_t*)info->video_driver_data;
video_info = (video_frame_info_t*)info->video_driver_frame_data;
b = info->bounds;
b.x /= video_info->width;
b.y /= video_info->height;
b.w /= video_info->width;
b.h /= video_info->height;
coord[0] = b.x;
coord[1] = 1.f - b.y;
coord[2] = b.x + b.w;
coord[3] = 1.f - b.y;
coord[4] = b.x;
coord[5] = 1.f - (b.y + b.h);
coord[6] = b.x + b.w;
coord[7] = 1.f - (b.y + b.h);
i = 0;
while(i < 16)
{
color[i++] = info->color.r;
color[i++] = info->color.g;
color[i++] = info->color.b;
color[i++] = info->color.a;
}
gl->coords.vertex = coord;
gl->coords.tex_coord = tex_coords;
gl->coords.color = color;
gl->coords.vertices = 4;
gl->shader->set_coords(gl->shader_data, &gl->coords);
gl->shader->set_mvp(gl->shader_data, &gl->mvp_no_rot);
glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr_t)image_handle);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
static void gl2_video_layout_text(const video_layout_render_info_t *info, const char *str)
{
/* TODO */
}
static void gl2_video_layout_counter(const video_layout_render_info_t *info, int value)
{
/* TODO */
}
static void gl2_video_layout_rect(const video_layout_render_info_t *info)
{
gl_t *gl;
gl = (gl_t*)info->video_driver_data;
gl2_video_layout_image(info, (void*)(uintptr_t)gl->video_layout_white_texture, NULL);
}
static void gl2_video_layout_screen(const video_layout_render_info_t *info, int screen_index)
{
gl2_video_layout_rect(info);
}
static void gl2_video_layout_ellipse(const video_layout_render_info_t *info)
{
/* TODO */
}
static void gl2_video_layout_led_dot(const video_layout_render_info_t *info, int dot_count, int dot_mask)
{
/* TODO */
}
static void gl2_video_layout_led_seg(const video_layout_render_info_t *info, video_layout_led_t seg_layout, int seg_mask)
{
/* TODO */
}
static void gl2_video_layout_layer_end(const video_layout_render_info_t *info, video_layout_blend_t blend_type)
{
gl_t *gl;
gl = (gl_t*)info->video_driver_data;
switch (blend_type)
{
case VIDEO_LAYOUT_BLEND_ALPHA:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
break;
case VIDEO_LAYOUT_BLEND_ADD:
glBlendFunc(GL_ONE, GL_ONE);
break;
case VIDEO_LAYOUT_BLEND_MOD:
glBlendFunc(GL_DST_COLOR, GL_ZERO);
break;
}
gl2_bind_fb(0);
gl->coords.vertex = gl->vertex_ptr;
gl->coords.tex_coord = video_layout_layer_tex_coord;
gl->coords.color = gl->white_color_ptr;
gl->coords.vertices = 4;
gl->shader->set_coords(gl->shader_data, &gl->coords);
gl->shader->set_mvp(gl->shader_data, &gl->mvp_no_rot);
glBindTexture(GL_TEXTURE_2D, gl->video_layout_fbo_texture);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
gl->coords.tex_coord = gl->tex_info.coord;
}
static video_layout_render_interface_t gl2_video_layout_render_interface =
{
gl2_video_layout_take_image,
gl2_video_layout_free_image,
gl2_video_layout_layer_begin,
gl2_video_layout_screen,
gl2_video_layout_image,
gl2_video_layout_text,
gl2_video_layout_counter,
gl2_video_layout_rect,
gl2_video_layout_ellipse,
gl2_video_layout_led_dot,
gl2_video_layout_led_seg,
gl2_video_layout_layer_end
};
static const video_layout_render_interface_t *gl2_get_video_layout_render_interface(void *data)
{
return &gl2_video_layout_render_interface;
}
#endif /* HAVE_VIDEO_LAYOUT */
static bool gl2_frame(void *data, const void *frame,
unsigned frame_width, unsigned frame_height,
uint64_t frame_count,
@ -2617,8 +2929,16 @@ static bool gl2_frame(void *data, const void *frame,
}
else
gl2_set_viewport(gl, video_info, width, height, false, true);
#ifdef HAVE_VIDEO_LAYOUT
gl->video_layout_resize = true;
#endif
}
#ifdef HAVE_VIDEO_LAYOUT
gl2_video_layout_viewport(gl, video_info);
#endif
if (frame)
gl->tex_index = ((gl->tex_index + 1) % gl->textures);
@ -2711,7 +3031,7 @@ static bool gl2_frame(void *data, const void *frame,
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if (gl->fbo_inited)
gl2_renderchain_render(gl,
gl2_renderchain_render(gl,
chain,
video_info,
frame_count, &gl->tex_info, &feedback_info);
@ -2720,6 +3040,10 @@ static bool gl2_frame(void *data, const void *frame,
gl2_renderchain_bind_prev_texture(gl,
chain, &gl->tex_info);
#ifdef HAVE_VIDEO_LAYOUT
gl2_video_layout_render(gl, video_info);
#endif
#if defined(HAVE_MENU)
if (gl->menu_texture_enable)
{
@ -2858,10 +3182,14 @@ static void gl2_free(void *data)
if (!gl)
return;
#ifdef HAVE_VIDEO_LAYOUT
gl2_video_layout_free(gl);
#endif
gl2_context_bind_hw_render(gl, false);
if (gl->have_sync)
gl2_renderchain_fence_free(gl,
gl2_renderchain_fence_free(gl,
(gl2_renderchain_data_t*)
gl->renderchain_data);
@ -3598,6 +3926,10 @@ static void *gl2_init(const video_info_t *video,
goto error;
}
#ifdef HAVE_VIDEO_LAYOUT
gl2_video_layout_init(gl);
#endif
gl2_context_bind_hw_render(gl, true);
return gl;
@ -3781,7 +4113,7 @@ static bool gl2_set_shader(void *data,
gl2_init_textures_data(gl);
if (gl->hw_render_use)
gl2_renderchain_init_hw_render(gl,
gl2_renderchain_init_hw_render(gl,
(gl2_renderchain_data_t*)gl->renderchain_data,
gl->tex_w, gl->tex_h);
}
@ -4235,7 +4567,7 @@ video_driver_t video_gl2 = {
gl2_get_overlay_interface,
#endif
#ifdef HAVE_VIDEO_LAYOUT
NULL,
gl2_get_video_layout_render_interface,
#endif
gl2_get_poke_interface,
gl2_wrap_type_to_enum,