mirror of
https://github.com/libretro/RetroArch
synced 2025-02-06 00:39:53 +00:00
Add get_proc_address.
Render something "real" in GL.
This commit is contained in:
parent
f7cab36188
commit
1cececac18
12
driver.c
12
driver.c
@ -280,6 +280,14 @@ uintptr_t driver_get_current_framebuffer(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
retro_proc_address_t driver_get_proc_address(const char *sym)
|
||||||
|
{
|
||||||
|
if (driver.video_poke && driver.video_poke->get_proc_address)
|
||||||
|
return driver.video_poke->get_proc_address(driver.video_data, sym);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Only called once on init and deinit.
|
// Only called once on init and deinit.
|
||||||
// Video and input drivers need to be active (owned)
|
// Video and input drivers need to be active (owned)
|
||||||
// before retroarch core starts.
|
// before retroarch core starts.
|
||||||
@ -332,6 +340,10 @@ void init_drivers(void)
|
|||||||
adjust_system_rates();
|
adjust_system_rates();
|
||||||
|
|
||||||
init_video_input();
|
init_video_input();
|
||||||
|
|
||||||
|
if (g_extern.system.hw_render_callback.context_reset)
|
||||||
|
g_extern.system.hw_render_callback.context_reset();
|
||||||
|
|
||||||
init_audio();
|
init_audio();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
driver.h
2
driver.h
@ -324,6 +324,7 @@ typedef struct video_poke_interface
|
|||||||
void (*set_fbo_state)(void *data, unsigned state);
|
void (*set_fbo_state)(void *data, unsigned state);
|
||||||
unsigned (*get_fbo_state)(void *data);
|
unsigned (*get_fbo_state)(void *data);
|
||||||
uintptr_t (*get_current_framebuffer)(void *data);
|
uintptr_t (*get_current_framebuffer)(void *data);
|
||||||
|
retro_proc_address_t (*get_proc_address)(void *data, const char *sym);
|
||||||
#endif
|
#endif
|
||||||
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);
|
||||||
@ -449,6 +450,7 @@ void driver_set_monitor_refresh_rate(float hz);
|
|||||||
|
|
||||||
// Used by RETRO_ENVIRONMENT_SET_HW_RENDER.
|
// Used by RETRO_ENVIRONMENT_SET_HW_RENDER.
|
||||||
uintptr_t driver_get_current_framebuffer(void);
|
uintptr_t driver_get_current_framebuffer(void);
|
||||||
|
retro_proc_address_t driver_get_proc_address(const char *sym);
|
||||||
|
|
||||||
extern driver_t driver;
|
extern driver_t driver;
|
||||||
|
|
||||||
|
@ -561,6 +561,7 @@ static bool environment_cb(unsigned cmd, void *data)
|
|||||||
RARCH_LOG("Environ SET_HW_RENDER.\n");
|
RARCH_LOG("Environ SET_HW_RENDER.\n");
|
||||||
struct retro_hw_render_callback *cb = (struct retro_hw_render_callback*)data;
|
struct retro_hw_render_callback *cb = (struct retro_hw_render_callback*)data;
|
||||||
cb->get_current_framebuffer = driver_get_current_framebuffer;
|
cb->get_current_framebuffer = driver_get_current_framebuffer;
|
||||||
|
cb->get_proc_address = driver_get_proc_address;
|
||||||
memcpy(&g_extern.system.hw_render_callback, cb, sizeof(*cb));
|
memcpy(&g_extern.system.hw_render_callback, cb, sizeof(*cb));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
12
gfx/gl.c
12
gfx/gl.c
@ -1932,11 +1932,6 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_FBO
|
|
||||||
if (gl->hw_render_fbo_init)
|
|
||||||
g_extern.system.hw_render_callback.context_reset();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return gl;
|
return gl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2375,6 +2370,12 @@ static uintptr_t gl_get_current_framebuffer(void *data)
|
|||||||
gl_t *gl = (gl_t*)data;
|
gl_t *gl = (gl_t*)data;
|
||||||
return gl->hw_render_fbo[(gl->tex_index + 1) & TEXTURES_MASK];
|
return gl->hw_render_fbo[(gl->tex_index + 1) & TEXTURES_MASK];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static retro_proc_address_t gl_get_proc_address(void *data, const char *sym)
|
||||||
|
{
|
||||||
|
gl_t *gl = (gl_t*)data;
|
||||||
|
return gl->ctx_driver->get_proc_address(sym);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void gl_set_aspect_ratio(void *data, unsigned aspectratio_index)
|
static void gl_set_aspect_ratio(void *data, unsigned aspectratio_index)
|
||||||
@ -2434,6 +2435,7 @@ static const video_poke_interface_t gl_poke_interface = {
|
|||||||
gl_set_fbo_state,
|
gl_set_fbo_state,
|
||||||
gl_get_fbo_state,
|
gl_get_fbo_state,
|
||||||
gl_get_current_framebuffer,
|
gl_get_current_framebuffer,
|
||||||
|
gl_get_proc_address,
|
||||||
#endif
|
#endif
|
||||||
gl_set_aspect_ratio,
|
gl_set_aspect_ratio,
|
||||||
gl_apply_state_changes,
|
gl_apply_state_changes,
|
||||||
|
@ -679,6 +679,7 @@ static const video_poke_interface_t thread_poke = {
|
|||||||
thread_set_fbo_state,
|
thread_set_fbo_state,
|
||||||
thread_get_fbo_state,
|
thread_get_fbo_state,
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
#endif
|
#endif
|
||||||
thread_set_aspect_ratio,
|
thread_set_aspect_ratio,
|
||||||
thread_apply_state_changes,
|
thread_apply_state_changes,
|
||||||
|
@ -5,20 +5,118 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
|
#define GL_GLEXT_PROTOTYPES
|
||||||
#include <GL/glext.h>
|
#include <GL/glext.h>
|
||||||
|
|
||||||
static uint16_t *frame_buf;
|
static PFNGLCREATEPROGRAMPROC pglCreateProgram;
|
||||||
|
static PFNGLCREATESHADERPROC pglCreateShader;
|
||||||
|
static PFNGLCREATESHADERPROC pglCompileShader;
|
||||||
|
static PFNGLCREATESHADERPROC pglUseProgram;
|
||||||
|
static PFNGLSHADERSOURCEPROC pglShaderSource;
|
||||||
|
static PFNGLATTACHSHADERPROC pglAttachShader;
|
||||||
|
static PFNGLLINKPROGRAMPROC pglLinkProgram;
|
||||||
|
static PFNGLBINDFRAMEBUFFERPROC pglBindFramebuffer;
|
||||||
|
static PFNGLGETUNIFORMLOCATIONPROC pglGetUniformLocation;
|
||||||
|
static PFNGLUNIFORMMATRIX4FVPROC pglUniformMatrix4fv;
|
||||||
|
static PFNGLGETATTRIBLOCATIONPROC pglGetAttribLocation;
|
||||||
|
static PFNGLVERTEXATTRIBPOINTERPROC pglVertexAttribPointer;
|
||||||
|
static PFNGLENABLEVERTEXATTRIBARRAYPROC pglEnableVertexAttribArray;
|
||||||
|
static PFNGLDISABLEVERTEXATTRIBARRAYPROC pglDisableVertexAttribArray;
|
||||||
|
|
||||||
|
static struct retro_hw_render_callback hw_render;
|
||||||
|
|
||||||
|
struct gl_proc_map
|
||||||
|
{
|
||||||
|
void *proc;
|
||||||
|
const char *sym;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PROC_BIND(name) { &(pgl##name), "gl" #name }
|
||||||
|
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||||
|
static const struct gl_proc_map proc_map[] = {
|
||||||
|
PROC_BIND(CreateProgram),
|
||||||
|
PROC_BIND(CreateShader),
|
||||||
|
PROC_BIND(CompileShader),
|
||||||
|
PROC_BIND(UseProgram),
|
||||||
|
PROC_BIND(ShaderSource),
|
||||||
|
PROC_BIND(AttachShader),
|
||||||
|
PROC_BIND(LinkProgram),
|
||||||
|
PROC_BIND(BindFramebuffer),
|
||||||
|
PROC_BIND(GetUniformLocation),
|
||||||
|
PROC_BIND(GetAttribLocation),
|
||||||
|
PROC_BIND(UniformMatrix4fv),
|
||||||
|
PROC_BIND(VertexAttribPointer),
|
||||||
|
PROC_BIND(EnableVertexAttribArray),
|
||||||
|
PROC_BIND(DisableVertexAttribArray),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void init_gl_proc(void)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < ARRAY_SIZE(proc_map); i++)
|
||||||
|
{
|
||||||
|
retro_proc_address_t proc = hw_render.get_proc_address(proc_map[i].sym);
|
||||||
|
if (!proc)
|
||||||
|
fprintf(stderr, "Symbol %s not found!\n", proc_map[i].sym);
|
||||||
|
memcpy(proc_map[i].proc, &proc, sizeof(proc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLuint prog;
|
||||||
|
|
||||||
|
static const GLfloat vertex[] = {
|
||||||
|
0.0, 0.0,
|
||||||
|
1.0, 0.0,
|
||||||
|
0.0, 1.0,
|
||||||
|
1.0, 1.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const GLfloat color[] = {
|
||||||
|
1.0, 1.0, 1.0, 1.0,
|
||||||
|
1.0, 1.0, 0.0, 1.0,
|
||||||
|
0.0, 1.0, 1.0, 1.0,
|
||||||
|
1.0, 0.0, 1.0, 1.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const char *vertex_shader[] = {
|
||||||
|
"uniform mat4 uMVP;",
|
||||||
|
"attribute vec2 aVertex;",
|
||||||
|
"attribute vec4 aColor;",
|
||||||
|
"varying vec4 color;",
|
||||||
|
"void main() {",
|
||||||
|
" gl_Position = uMVP * vec4(aVertex, 0.0, 1.0);",
|
||||||
|
" color = aColor;",
|
||||||
|
"}",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *fragment_shader[] = {
|
||||||
|
"varying vec4 color;",
|
||||||
|
"void main() {",
|
||||||
|
" gl_FragColor = color;",
|
||||||
|
"}",
|
||||||
|
};
|
||||||
|
|
||||||
|
static void compile_program(void)
|
||||||
|
{
|
||||||
|
prog = pglCreateProgram();
|
||||||
|
GLuint vert = pglCreateShader(GL_VERTEX_SHADER);
|
||||||
|
GLuint frag = pglCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
|
||||||
|
pglShaderSource(vert, ARRAY_SIZE(vertex_shader), vertex_shader, 0);
|
||||||
|
pglShaderSource(frag, ARRAY_SIZE(fragment_shader), fragment_shader, 0);
|
||||||
|
pglCompileShader(vert);
|
||||||
|
pglCompileShader(frag);
|
||||||
|
|
||||||
|
pglAttachShader(prog, vert);
|
||||||
|
pglAttachShader(prog, frag);
|
||||||
|
pglLinkProgram(prog);
|
||||||
|
}
|
||||||
|
|
||||||
void retro_init(void)
|
void retro_init(void)
|
||||||
{
|
{}
|
||||||
frame_buf = calloc(320 * 240, sizeof(uint16_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
void retro_deinit(void)
|
void retro_deinit(void)
|
||||||
{
|
{}
|
||||||
free(frame_buf);
|
|
||||||
frame_buf = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned retro_api_version(void)
|
unsigned retro_api_version(void)
|
||||||
{
|
{
|
||||||
@ -93,24 +191,47 @@ void retro_set_video_refresh(retro_video_refresh_t cb)
|
|||||||
video_cb = cb;
|
video_cb = cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct retro_hw_render_callback hw_render;
|
|
||||||
|
|
||||||
void retro_run(void)
|
void retro_run(void)
|
||||||
{
|
{
|
||||||
input_poll_cb();
|
input_poll_cb();
|
||||||
static unsigned frame_count = 0;
|
|
||||||
frame_count = (frame_count + 1) % 60;
|
pglBindFramebuffer(GL_FRAMEBUFFER, hw_render.get_current_framebuffer());
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, hw_render.get_current_framebuffer());
|
glClearColor(0.3, 0.4, 0.5, 1.0);
|
||||||
glViewport(0, 0, 320, 240);
|
glViewport(0, 0, 320, 240);
|
||||||
glClearColor(frame_count / 120.0, frame_count / 60.0, frame_count / 60.0, 1.0);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
pglUseProgram(prog);
|
||||||
|
|
||||||
|
int loc = pglGetUniformLocation(prog, "uMVP");
|
||||||
|
static const GLfloat identity[] = {
|
||||||
|
1, 0, 0, 0,
|
||||||
|
0, 1, 0, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 0, 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
pglUniformMatrix4fv(loc, 1, GL_FALSE, identity);
|
||||||
|
|
||||||
|
int vloc = pglGetAttribLocation(prog, "aVertex");
|
||||||
|
pglVertexAttribPointer(vloc, 2, GL_FLOAT, GL_FALSE, 0, vertex);
|
||||||
|
pglEnableVertexAttribArray(vloc);
|
||||||
|
int cloc = pglGetAttribLocation(prog, "aColor");
|
||||||
|
pglVertexAttribPointer(cloc, 4, GL_FLOAT, GL_FALSE, 0, color);
|
||||||
|
pglEnableVertexAttribArray(cloc);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
pglUseProgram(0);
|
||||||
|
pglDisableVertexAttribArray(vloc);
|
||||||
|
pglDisableVertexAttribArray(cloc);
|
||||||
|
|
||||||
video_cb(RETRO_HW_FRAME_BUFFER_VALID, 320, 240, 0);
|
video_cb(RETRO_HW_FRAME_BUFFER_VALID, 320, 240, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void context_reset(void)
|
static void context_reset(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Context reset!\n");
|
fprintf(stderr, "Context reset!\n");
|
||||||
|
init_gl_proc();
|
||||||
|
compile_program();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool retro_load_game(const struct retro_game_info *info)
|
bool retro_load_game(const struct retro_game_info *info)
|
||||||
|
@ -444,6 +444,10 @@ typedef void (*retro_hw_context_reset_t)(void);
|
|||||||
// Gets current framebuffer which is to be rendered to. Could change every frame potentially.
|
// Gets current framebuffer which is to be rendered to. Could change every frame potentially.
|
||||||
typedef uintptr_t (*retro_hw_get_current_framebuffer_t)(void);
|
typedef uintptr_t (*retro_hw_get_current_framebuffer_t)(void);
|
||||||
|
|
||||||
|
// Get a symbol from HW context.
|
||||||
|
typedef void (*retro_proc_address_t)(void);
|
||||||
|
typedef retro_proc_address_t (*retro_hw_get_proc_address_t)(const char *sym);
|
||||||
|
|
||||||
enum retro_hw_context_type
|
enum retro_hw_context_type
|
||||||
{
|
{
|
||||||
RETRO_HW_CONTEXT_NONE = 0,
|
RETRO_HW_CONTEXT_NONE = 0,
|
||||||
@ -457,6 +461,7 @@ struct retro_hw_render_callback
|
|||||||
enum retro_hw_context_type context_type; // Which API to use. Set by libretro core.
|
enum retro_hw_context_type context_type; // Which API to use. Set by libretro core.
|
||||||
retro_hw_context_reset_t context_reset; // Set by libretro core.
|
retro_hw_context_reset_t context_reset; // Set by libretro core.
|
||||||
retro_hw_get_current_framebuffer_t get_current_framebuffer; // Set by frontend.
|
retro_hw_get_current_framebuffer_t get_current_framebuffer; // Set by frontend.
|
||||||
|
retro_hw_get_proc_address_t get_proc_address; // Set by frontend.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. Called by the frontend in response to keyboard events.
|
// Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. Called by the frontend in response to keyboard events.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user