mirror of
https://github.com/libretro/RetroArch
synced 2025-03-29 13:20:30 +00:00
Refactor set_rgui_texture.
More generic and avoids poking directly into RGUI state.
This commit is contained in:
parent
c9725afa5c
commit
4cdfcf30d5
9
driver.h
9
driver.h
@ -298,7 +298,8 @@ typedef struct input_driver
|
|||||||
{
|
{
|
||||||
void *(*init)(void);
|
void *(*init)(void);
|
||||||
void (*poll)(void *data);
|
void (*poll)(void *data);
|
||||||
int16_t (*input_state)(void *data, const struct retro_keybind **retro_keybinds, unsigned port, unsigned device, unsigned index, unsigned id);
|
int16_t (*input_state)(void *data, const struct retro_keybind **retro_keybinds,
|
||||||
|
unsigned port, unsigned device, unsigned index, unsigned id);
|
||||||
bool (*key_pressed)(void *data, int key);
|
bool (*key_pressed)(void *data, int key);
|
||||||
void (*free)(void *data);
|
void (*free)(void *data);
|
||||||
void (*set_keybinds)(void *data, unsigned device, unsigned port, unsigned id, unsigned keybind_action);
|
void (*set_keybinds)(void *data, unsigned device, unsigned port, unsigned id, unsigned keybind_action);
|
||||||
@ -334,9 +335,9 @@ typedef struct video_poke_interface
|
|||||||
void (*set_aspect_ratio)(void *data, unsigned aspectratio_index);
|
void (*set_aspect_ratio)(void *data, unsigned aspectratio_index);
|
||||||
void (*apply_state_changes)(void *data);
|
void (*apply_state_changes)(void *data);
|
||||||
|
|
||||||
// Set to NULL if RGUI texture is not supposed to be rendered.
|
#if defined(HAVE_RGUI)
|
||||||
#ifdef HAVE_RGUI
|
void (*set_texture_frame)(void *data, const void *frame, bool rgb32, unsigned width, unsigned height, float alpha); // Update texture.
|
||||||
void (*set_rgui_texture)(void *data, const void *frame);
|
void (*set_texture_enable)(void *data, bool enable); // Enable/disable rendering.
|
||||||
#endif
|
#endif
|
||||||
void (*set_osd_msg)(void *data, const char *msg, void *userdata);
|
void (*set_osd_msg)(void *data, const char *msg, void *userdata);
|
||||||
|
|
||||||
|
@ -1801,13 +1801,17 @@ bool menu_iterate(void)
|
|||||||
input_entry_ret = rgui_iterate(rgui, action);
|
input_entry_ret = rgui_iterate(rgui, action);
|
||||||
|
|
||||||
// draw last frame for loading messages
|
// draw last frame for loading messages
|
||||||
if (driver.video_poke && driver.video_poke->set_rgui_texture)
|
if (driver.video_poke && driver.video_poke->set_texture_enable)
|
||||||
driver.video_poke->set_rgui_texture(driver.video_data, menu_framebuf);
|
{
|
||||||
|
driver.video_poke->set_texture_frame(driver.video_data, menu_framebuf,
|
||||||
|
false, RGUI_WIDTH, RGUI_HEIGHT, 1.0f);
|
||||||
|
driver.video_poke->set_texture_enable(driver.video_data, true);
|
||||||
|
}
|
||||||
|
|
||||||
rarch_render_cached_frame();
|
rarch_render_cached_frame();
|
||||||
|
|
||||||
if (driver.video_poke && driver.video_poke->set_rgui_texture)
|
if (driver.video_poke && driver.video_poke->set_texture_enable)
|
||||||
driver.video_poke->set_rgui_texture(driver.video_data, NULL);
|
driver.video_poke->set_texture_enable(driver.video_data, false);
|
||||||
|
|
||||||
input_process_ret = menu_input_process(NULL, NULL);
|
input_process_ret = menu_input_process(NULL, NULL);
|
||||||
|
|
||||||
|
96
gfx/gl.c
96
gfx/gl.c
@ -58,10 +58,6 @@
|
|||||||
#include "../frontend/frontend_android.h"
|
#include "../frontend/frontend_android.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_RGUI
|
|
||||||
#include "../frontend/menu/rgui.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Used for the last pass when rendering to the back buffer.
|
// Used for the last pass when rendering to the back buffer.
|
||||||
const GLfloat vertexes_flipped[] = {
|
const GLfloat vertexes_flipped[] = {
|
||||||
0, 1,
|
0, 1,
|
||||||
@ -1131,20 +1127,6 @@ static void gl_init_textures_data(void *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_RGUI
|
|
||||||
static void gl_init_rgui_texture(void *data)
|
|
||||||
{
|
|
||||||
gl_t *gl = (gl_t*)data;
|
|
||||||
|
|
||||||
glGenTextures(1, &gl->rgui_texture);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, gl->rgui_texture);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gl->border_type);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gl->border_type);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void gl_init_textures(void *data, const video_info_t *video)
|
static void gl_init_textures(void *data, const video_info_t *video)
|
||||||
{
|
{
|
||||||
gl_t *gl = (gl_t*)data;
|
gl_t *gl = (gl_t*)data;
|
||||||
@ -1165,10 +1147,6 @@ static void gl_init_textures(void *data, const video_info_t *video)
|
|||||||
|
|
||||||
glGenTextures(TEXTURES, gl->texture);
|
glGenTextures(TEXTURES, gl->texture);
|
||||||
|
|
||||||
#ifdef HAVE_RGUI
|
|
||||||
gl_init_rgui_texture(gl);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < TEXTURES; i++)
|
for (unsigned i = 0; i < TEXTURES; i++)
|
||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_2D, gl->texture[i]);
|
glBindTexture(GL_TEXTURE_2D, gl->texture[i]);
|
||||||
@ -1327,19 +1305,21 @@ static void gl_pbo_async_readback(void *data)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_RGUI
|
#ifdef HAVE_RGUI
|
||||||
static inline void gl_draw_rgui(void *data)
|
static inline void gl_draw_texture(void *data)
|
||||||
{
|
{
|
||||||
gl_t *gl = (gl_t*)data;
|
gl_t *gl = (gl_t*)data;
|
||||||
|
|
||||||
|
const GLfloat color[] = {
|
||||||
|
1.0f, 1.0f, 1.0f, gl->rgui_texture_alpha,
|
||||||
|
1.0f, 1.0f, 1.0f, gl->rgui_texture_alpha,
|
||||||
|
1.0f, 1.0f, 1.0f, gl->rgui_texture_alpha,
|
||||||
|
1.0f, 1.0f, 1.0f, gl->rgui_texture_alpha,
|
||||||
|
};
|
||||||
|
|
||||||
gl->coords.tex_coord = tex_coords;
|
gl->coords.tex_coord = tex_coords;
|
||||||
|
gl->coords.color = color;
|
||||||
glBindTexture(GL_TEXTURE_2D, gl->rgui_texture);
|
glBindTexture(GL_TEXTURE_2D, gl->rgui_texture);
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(RGUI_WIDTH * 2));
|
|
||||||
// RGUI is always packed so pitch = width * bpp
|
|
||||||
glTexImage2D(GL_TEXTURE_2D,
|
|
||||||
0, GL_RGBA, RGUI_WIDTH, RGUI_HEIGHT, 0, GL_RGBA,
|
|
||||||
GL_UNSIGNED_SHORT_4_4_4_4, gl->rgui_data);
|
|
||||||
|
|
||||||
gl_shader_use_func(gl, 0);
|
gl_shader_use_func(gl, 0);
|
||||||
gl_shader_set_coords_func(gl, &gl->coords, &gl->mvp_no_rot);
|
gl_shader_set_coords_func(gl, &gl->coords, &gl->mvp_no_rot);
|
||||||
|
|
||||||
@ -1348,6 +1328,7 @@ static inline void gl_draw_rgui(void *data)
|
|||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
gl->coords.tex_coord = gl->tex_coords;
|
gl->coords.tex_coord = gl->tex_coords;
|
||||||
|
gl->coords.color = white_color;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1458,8 +1439,8 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei
|
|||||||
gl_set_prev_texture(gl, &tex_info);
|
gl_set_prev_texture(gl, &tex_info);
|
||||||
|
|
||||||
#ifdef HAVE_RGUI
|
#ifdef HAVE_RGUI
|
||||||
if (gl->rgui_data)
|
if (gl->rgui_texture_enable)
|
||||||
gl_draw_rgui(gl);
|
gl_draw_texture(gl);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef FPS_COUNTER
|
#ifdef FPS_COUNTER
|
||||||
@ -1540,7 +1521,8 @@ static void gl_free(void *data)
|
|||||||
glDeleteTextures(TEXTURES, gl->texture);
|
glDeleteTextures(TEXTURES, gl->texture);
|
||||||
|
|
||||||
#ifdef HAVE_RGUI
|
#ifdef HAVE_RGUI
|
||||||
glDeleteTextures(1, &gl->rgui_texture);
|
if (gl->rgui_texture)
|
||||||
|
glDeleteTextures(1, &gl->rgui_texture);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_OVERLAY
|
#ifdef HAVE_OVERLAY
|
||||||
@ -2359,10 +2341,51 @@ static void gl_set_blend(void *data, bool enable)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_RGUI
|
#ifdef HAVE_RGUI
|
||||||
static void gl_set_rgui_texture(void *data, const void *frame)
|
static void gl_set_texture_frame(void *data,
|
||||||
|
const void *frame, bool rgb32, unsigned width, unsigned height,
|
||||||
|
float alpha)
|
||||||
{
|
{
|
||||||
gl_t *gl = (gl_t*)data;
|
gl_t *gl = (gl_t*)data;
|
||||||
gl->rgui_data = frame;
|
|
||||||
|
if (!gl->rgui_texture)
|
||||||
|
{
|
||||||
|
glGenTextures(1, &gl->rgui_texture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, gl->rgui_texture);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gl->border_type);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gl->border_type);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
glBindTexture(GL_TEXTURE_2D, gl->rgui_texture);
|
||||||
|
|
||||||
|
gl->rgui_texture_alpha = alpha;
|
||||||
|
|
||||||
|
unsigned base_size = rgb32 ? sizeof(uint32_t) : sizeof(uint16_t);
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(width * base_size));
|
||||||
|
|
||||||
|
if (rgb32)
|
||||||
|
{
|
||||||
|
glTexImage2D(GL_TEXTURE_2D,
|
||||||
|
0, driver.gfx_use_rgba ? GL_RGBA : RARCH_GL_INTERNAL_FORMAT32,
|
||||||
|
width, height,
|
||||||
|
0, driver.gfx_use_rgba ? GL_RGBA : RARCH_GL_TEXTURE_TYPE32,
|
||||||
|
RARCH_GL_FORMAT32, frame);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glTexImage2D(GL_TEXTURE_2D,
|
||||||
|
0, GL_RGBA, width, height, 0, GL_RGBA,
|
||||||
|
GL_UNSIGNED_SHORT_4_4_4_4, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gl_set_texture_enable(void *data, bool state)
|
||||||
|
{
|
||||||
|
gl_t *gl = (gl_t*)data;
|
||||||
|
gl->rgui_texture_enable = state;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -2398,7 +2421,8 @@ static const video_poke_interface_t gl_poke_interface = {
|
|||||||
gl_set_aspect_ratio,
|
gl_set_aspect_ratio,
|
||||||
gl_apply_state_changes,
|
gl_apply_state_changes,
|
||||||
#ifdef HAVE_RGUI
|
#ifdef HAVE_RGUI
|
||||||
gl_set_rgui_texture,
|
gl_set_texture_frame,
|
||||||
|
gl_set_texture_enable,
|
||||||
#endif
|
#endif
|
||||||
gl_set_osd_msg,
|
gl_set_osd_msg,
|
||||||
|
|
||||||
|
@ -287,7 +287,8 @@ typedef struct gl
|
|||||||
|
|
||||||
#ifdef HAVE_RGUI
|
#ifdef HAVE_RGUI
|
||||||
GLuint rgui_texture;
|
GLuint rgui_texture;
|
||||||
const void *rgui_data;
|
bool rgui_texture_enable;
|
||||||
|
GLfloat rgui_texture_alpha;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} gl_t;
|
} gl_t;
|
||||||
|
@ -72,7 +72,17 @@ typedef struct thread_video
|
|||||||
void **input_data;
|
void **input_data;
|
||||||
|
|
||||||
#ifdef HAVE_RGUI
|
#ifdef HAVE_RGUI
|
||||||
const void *rgui_texture;
|
struct
|
||||||
|
{
|
||||||
|
void *frame;
|
||||||
|
size_t frame_cap;
|
||||||
|
bool frame_updated;
|
||||||
|
bool rgb32;
|
||||||
|
unsigned width;
|
||||||
|
unsigned height;
|
||||||
|
float alpha;
|
||||||
|
bool enable;
|
||||||
|
} texture;
|
||||||
#endif
|
#endif
|
||||||
bool apply_state_changes;
|
bool apply_state_changes;
|
||||||
|
|
||||||
@ -294,8 +304,17 @@ static void thread_loop(void *data)
|
|||||||
slock_lock(thr->frame.lock);
|
slock_lock(thr->frame.lock);
|
||||||
|
|
||||||
#ifdef HAVE_RGUI
|
#ifdef HAVE_RGUI
|
||||||
thr->poke->set_rgui_texture(thr->driver_data, thr->rgui_texture);
|
if (thr->texture.frame_updated)
|
||||||
|
{
|
||||||
|
thr->poke->set_texture_frame(thr->driver_data,
|
||||||
|
thr->texture.frame, thr->texture.rgb32,
|
||||||
|
thr->texture.width, thr->texture.height,
|
||||||
|
thr->texture.alpha);
|
||||||
|
thr->texture.frame_updated = false;
|
||||||
|
}
|
||||||
|
thr->poke->set_texture_enable(thr->driver_data, thr->texture.enable);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (thr->apply_state_changes)
|
if (thr->apply_state_changes)
|
||||||
{
|
{
|
||||||
thr->poke->apply_state_changes(thr->driver_data);
|
thr->poke->apply_state_changes(thr->driver_data);
|
||||||
@ -407,7 +426,7 @@ static bool thread_frame(void *data, const void *frame_,
|
|||||||
// we'll want to block to avoid stepping menu
|
// we'll want to block to avoid stepping menu
|
||||||
// at crazy speeds.
|
// at crazy speeds.
|
||||||
#ifdef HAVE_RGUI
|
#ifdef HAVE_RGUI
|
||||||
if (thr->rgui_texture)
|
if (thr->texture.enable)
|
||||||
{
|
{
|
||||||
while (thr->frame.updated)
|
while (thr->frame.updated)
|
||||||
scond_wait(thr->cond_cmd, thr->lock);
|
scond_wait(thr->cond_cmd, thr->lock);
|
||||||
@ -510,6 +529,7 @@ static void thread_free(void *data)
|
|||||||
thread_wait_reply(thr, CMD_FREE);
|
thread_wait_reply(thr, CMD_FREE);
|
||||||
sthread_join(thr->thread);
|
sthread_join(thr->thread);
|
||||||
|
|
||||||
|
free(thr->texture.frame);
|
||||||
free(thr->frame.buffer);
|
free(thr->frame.buffer);
|
||||||
slock_free(thr->frame.lock);
|
slock_free(thr->frame.lock);
|
||||||
slock_free(thr->lock);
|
slock_free(thr->lock);
|
||||||
@ -620,12 +640,37 @@ static void thread_set_aspect_ratio(void *data, unsigned aspectratio_index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_RGUI
|
#ifdef HAVE_RGUI
|
||||||
static void thread_set_rgui_texture(void *data, const void *frame)
|
static void thread_set_texture_frame(void *data, const void *frame,
|
||||||
|
bool rgb32, unsigned width, unsigned height, float alpha)
|
||||||
{
|
{
|
||||||
thread_video_t *thr = (thread_video_t*)data;
|
thread_video_t *thr = (thread_video_t*)data;
|
||||||
|
|
||||||
slock_lock(thr->frame.lock);
|
slock_lock(thr->frame.lock);
|
||||||
thr->rgui_texture = frame;
|
size_t required = width * height * (rgb32 ? sizeof(uint32_t) : sizeof(uint16_t));
|
||||||
|
if (required > thr->texture.frame_cap)
|
||||||
|
{
|
||||||
|
thr->texture.frame = realloc(thr->texture.frame, required);
|
||||||
|
thr->texture.frame_cap = required;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thr->texture.frame)
|
||||||
|
{
|
||||||
|
memcpy(thr->texture.frame, frame, required);
|
||||||
|
thr->texture.frame_updated = true;
|
||||||
|
thr->texture.rgb32 = rgb32;
|
||||||
|
thr->texture.width = width;
|
||||||
|
thr->texture.height = height;
|
||||||
|
thr->texture.alpha = alpha;
|
||||||
|
}
|
||||||
|
slock_unlock(thr->frame.lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void thread_set_texture_enable(void *data, bool state)
|
||||||
|
{
|
||||||
|
thread_video_t *thr = (thread_video_t*)data;
|
||||||
|
|
||||||
|
slock_lock(thr->frame.lock);
|
||||||
|
thr->texture.enable = state;
|
||||||
slock_unlock(thr->frame.lock);
|
slock_unlock(thr->frame.lock);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -648,7 +693,8 @@ static const video_poke_interface_t thread_poke = {
|
|||||||
thread_set_aspect_ratio,
|
thread_set_aspect_ratio,
|
||||||
thread_apply_state_changes,
|
thread_apply_state_changes,
|
||||||
#ifdef HAVE_RGUI
|
#ifdef HAVE_RGUI
|
||||||
thread_set_rgui_texture,
|
thread_set_texture_frame,
|
||||||
|
thread_set_texture_enable,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -918,7 +918,7 @@ static bool gx_frame(void *data, const void *frame,
|
|||||||
DCFlushRange(g_tex.data, height * (width << (gx->rgb32 ? 2 : 1)));
|
DCFlushRange(g_tex.data, height * (width << (gx->rgb32 ? 2 : 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gx->menu_data)
|
if (gx->menu_enable && gx->menu_data)
|
||||||
{
|
{
|
||||||
convert_texture16(gx->menu_data, menu_tex.data, RGUI_WIDTH, RGUI_HEIGHT, RGUI_WIDTH * 2);
|
convert_texture16(gx->menu_data, menu_tex.data, RGUI_WIDTH, RGUI_HEIGHT, RGUI_WIDTH * 2);
|
||||||
DCFlushRange(menu_tex.data, RGUI_WIDTH * RGUI_HEIGHT * 2);
|
DCFlushRange(menu_tex.data, RGUI_WIDTH * RGUI_HEIGHT * 2);
|
||||||
@ -1019,12 +1019,24 @@ static bool gx_set_shader(void *data, enum rarch_shader_type type, const char *p
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gx_set_rgui_texture(void *data, const void *frame)
|
static void gx_set_texture_frame(void *data, const void *frame,
|
||||||
|
bool rgb32, unsigned width, unsigned height, float alpha)
|
||||||
{
|
{
|
||||||
|
(void)rgb32;
|
||||||
|
(void)width;
|
||||||
|
(void)height;
|
||||||
|
(void)alpha;
|
||||||
|
|
||||||
gx_video_t *gx = (gx_video_t*)data;
|
gx_video_t *gx = (gx_video_t*)data;
|
||||||
gx->menu_data = (uint32_t*)frame;
|
gx->menu_data = (uint32_t*)frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gx_set_texture_enable(void *data, bool enable)
|
||||||
|
{
|
||||||
|
gx_video_t *gx = (gx_video_t*)data;
|
||||||
|
gx->menu_enable = enable;
|
||||||
|
}
|
||||||
|
|
||||||
static void gx_apply_state_changes(void *data)
|
static void gx_apply_state_changes(void *data)
|
||||||
{
|
{
|
||||||
gx_video_t *gx = (gx_video_t*)data;
|
gx_video_t *gx = (gx_video_t*)data;
|
||||||
@ -1042,7 +1054,8 @@ static const video_poke_interface_t gx_poke_interface = {
|
|||||||
NULL,
|
NULL,
|
||||||
gx_set_aspect_ratio,
|
gx_set_aspect_ratio,
|
||||||
gx_apply_state_changes,
|
gx_apply_state_changes,
|
||||||
gx_set_rgui_texture,
|
gx_set_texture_frame,
|
||||||
|
gx_set_texture_enable,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void gx_get_poke_interface(void *data, const video_poke_interface_t **iface)
|
static void gx_get_poke_interface(void *data, const video_poke_interface_t **iface)
|
||||||
|
@ -25,6 +25,7 @@ typedef struct gx_video
|
|||||||
bool double_strike;
|
bool double_strike;
|
||||||
bool rgb32;
|
bool rgb32;
|
||||||
uint32_t *menu_data; // FIXME: Should be const uint16_t*.
|
uint32_t *menu_data; // FIXME: Should be const uint16_t*.
|
||||||
|
bool menu_enable;
|
||||||
rarch_viewport_t vp;
|
rarch_viewport_t vp;
|
||||||
unsigned scale;
|
unsigned scale;
|
||||||
} gx_video_t;
|
} gx_video_t;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user