diff --git a/gfx/gl.c b/gfx/gl.c index 3807c9ef6e..897f21e37b 100644 --- a/gfx/gl.c +++ b/gfx/gl.c @@ -135,6 +135,11 @@ static PFNGLBINDFRAMEBUFFERPROC pglBindFramebuffer; static PFNGLFRAMEBUFFERTEXTURE2DPROC pglFramebufferTexture2D; static PFNGLCHECKFRAMEBUFFERSTATUSPROC pglCheckFramebufferStatus; static PFNGLDELETEFRAMEBUFFERSPROC pglDeleteFramebuffers; +static PFNGLGENRENDERBUFFERSPROC pglGenRenderbuffers; +static PFNGLBINDRENDERBUFFERPROC pglBindRenderbuffer; +static PFNGLFRAMEBUFFERRENDERBUFFERPROC pglFramebufferRenderbuffer; +static PFNGLRENDERBUFFERSTORAGEPROC pglRenderbufferStorage; +static PFNGLDELETERENDERBUFFERSPROC pglDeleteRenderbuffers; static bool load_fbo_proc(gl_t *gl) { @@ -143,9 +148,17 @@ static bool load_fbo_proc(gl_t *gl) LOAD_GL_SYM(FramebufferTexture2D); LOAD_GL_SYM(CheckFramebufferStatus); LOAD_GL_SYM(DeleteFramebuffers); + LOAD_GL_SYM(GenRenderbuffers); + LOAD_GL_SYM(BindRenderbuffer); + LOAD_GL_SYM(FramebufferRenderbuffer); + LOAD_GL_SYM(RenderbufferStorage); + LOAD_GL_SYM(DeleteRenderbuffers); return pglGenFramebuffers && pglBindFramebuffer && pglFramebufferTexture2D && - pglCheckFramebufferStatus && pglDeleteFramebuffers; + pglCheckFramebufferStatus && pglDeleteFramebuffers && + pglGenRenderbuffers && pglBindRenderbuffer && + pglFramebufferRenderbuffer && pglRenderbufferStorage && + pglDeleteRenderbuffers; } #elif defined(HAVE_OPENGLES2) #define pglGenFramebuffers glGenFramebuffers @@ -153,6 +166,11 @@ static bool load_fbo_proc(gl_t *gl) #define pglFramebufferTexture2D glFramebufferTexture2D #define pglCheckFramebufferStatus glCheckFramebufferStatus #define pglDeleteFramebuffers glDeleteFramebuffers +#define pglGenRenderbuffers glGenRenderbuffers +#define pglBindRenderbuffer glBindRenderbuffer +#define pglFramebufferRenderbuffer glFramebufferRenderbuffer +#define pglRenderbufferStorage glRenderbufferStorage +#define pglDeleteRenderbuffers glDeleteRenderbuffers #define load_fbo_proc(gl) (true) #elif defined(HAVE_OPENGLES) #define pglGenFramebuffers glGenFramebuffersOES @@ -160,6 +178,11 @@ static bool load_fbo_proc(gl_t *gl) #define pglFramebufferTexture2D glFramebufferTexture2DOES #define pglCheckFramebufferStatus glCheckFramebufferStatusOES #define pglDeleteFramebuffers glDeleteFramebuffersOES +#define pglGenRenderbuffers glGenRenderbuffersOES +#define pglBindRenderbuffer glBindRenderbufferOES +#define pglFramebufferRenderbuffer glFramebufferRenderbufferOES +#define pglRenderbufferStorage glRenderbufferStorageOES +#define pglDeleteRenderbuffers glDeleteRenderbuffersOES #define GL_FRAMEBUFFER GL_FRAMEBUFFER_OES #define GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT #define GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_OES @@ -170,6 +193,11 @@ static bool load_fbo_proc(gl_t *gl) #define pglFramebufferTexture2D glFramebufferTexture2D #define pglCheckFramebufferStatus glCheckFramebufferStatus #define pglDeleteFramebuffers glDeleteFramebuffers +#define pglGenRenderbuffers glGenRenderbuffers +#define pglBindRenderbuffer glBindRenderbuffer +#define pglFramebufferRenderbuffer glFramebufferRenderbuffer +#define pglRenderbufferStorage glRenderbufferStorage +#define pglDeleteRenderbuffers glDeleteRenderbuffers #define load_fbo_proc(gl) (true) #endif #endif @@ -710,10 +738,44 @@ bool gl_init_hw_render(gl_t *gl, unsigned width, unsigned height) glBindTexture(GL_TEXTURE_2D, 0); pglGenFramebuffers(TEXTURES, gl->hw_render_fbo); + bool depth = g_extern.system.hw_render_callback.depth; + bool stencil = g_extern.system.hw_render_callback.stencil; + + if (depth) + { + pglGenRenderbuffers(TEXTURES, gl->hw_render_depth); + gl->hw_render_depth_init = true; + } + + if (stencil) + { + pglGenRenderbuffers(TEXTURES, gl->hw_render_stencil); + gl->hw_render_stencil_init = true; + } + for (unsigned i = 0; i < TEXTURES; i++) { pglBindFramebuffer(GL_FRAMEBUFFER, gl->hw_render_fbo[i]); pglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl->texture[i], 0); + + if (depth) + { + pglBindRenderbuffer(GL_RENDERBUFFER, gl->hw_render_depth[i]); + pglRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, + width, height); + pglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, gl->hw_render_depth[i]); + } + + if (stencil) + { + pglBindRenderbuffer(GL_RENDERBUFFER, gl->hw_render_stencil[i]); + pglRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, + width, height); + pglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, gl->hw_render_stencil[i]); + } + GLenum status = pglCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { @@ -723,6 +785,7 @@ bool gl_init_hw_render(gl_t *gl, unsigned width, unsigned height) } pglBindFramebuffer(GL_FRAMEBUFFER, 0); + pglBindRenderbuffer(GL_RENDERBUFFER, 0); gl->hw_render_fbo_init = true; return true; } @@ -1593,6 +1656,10 @@ static void gl_free(void *data) if (gl->hw_render_fbo_init) pglDeleteFramebuffers(TEXTURES, gl->hw_render_fbo); + if (gl->hw_render_depth) + pglDeleteRenderbuffers(TEXTURES, gl->hw_render_depth); + if (gl->hw_render_stencil) + pglDeleteRenderbuffers(TEXTURES, gl->hw_render_stencil); gl->hw_render_fbo_init = false; #endif diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 814ba5611e..5160a17611 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -244,7 +244,11 @@ typedef struct gl bool fbo_inited; GLuint hw_render_fbo[TEXTURES]; + GLuint hw_render_depth[TEXTURES]; + GLuint hw_render_stencil[TEXTURES]; bool hw_render_fbo_init; + bool hw_render_depth_init; + bool hw_render_stencil_init; #endif bool should_resize; diff --git a/libretro-test-gl/libretro-test.c b/libretro-test-gl/libretro-test.c index 54f6ddd838..5c835f4ba3 100644 --- a/libretro-test-gl/libretro-test.c +++ b/libretro-test-gl/libretro-test.c @@ -218,10 +218,12 @@ void retro_run(void) pglBindFramebuffer(GL_FRAMEBUFFER, hw_render.get_current_framebuffer()); glClearColor(0.3, 0.4, 0.5, 1.0); glViewport(0, 0, 512, 512); - glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); pglUseProgram(prog); + glEnable(GL_DEPTH_TEST); + int loc = pglGetUniformLocation(prog, "uMVP"); static unsigned frame_count; @@ -230,15 +232,6 @@ void retro_run(void) float cos_angle = cos(angle); float sin_angle = sin(angle); - const GLfloat mvp[] = { - cos_angle, -sin_angle, 0, 0, - sin_angle, cos_angle, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1, - }; - - pglUniformMatrix4fv(loc, 1, GL_FALSE, mvp); - int vloc = pglGetAttribLocation(prog, "aVertex"); pglVertexAttribPointer(vloc, 2, GL_FLOAT, GL_FALSE, 0, vertex); pglEnableVertexAttribArray(vloc); @@ -246,7 +239,28 @@ void retro_run(void) pglVertexAttribPointer(cloc, 4, GL_FLOAT, GL_FALSE, 0, color); pglEnableVertexAttribArray(cloc); + const GLfloat mvp[] = { + cos_angle, -sin_angle, 0, 0, + sin_angle, cos_angle, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + }; + pglUniformMatrix4fv(loc, 1, GL_FALSE, mvp); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + cos_angle *= 0.5; + sin_angle *= 0.5; + const GLfloat mvp2[] = { + cos_angle, -sin_angle, 0, 0.0, + sin_angle, cos_angle, 0, 0.0, + 0, 0, 1, 0, + 0.4, 0.4, 0.2, 1, + }; + + pglUniformMatrix4fv(loc, 1, GL_FALSE, mvp2); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + pglUseProgram(0); pglDisableVertexAttribArray(vloc); pglDisableVertexAttribArray(cloc); @@ -274,6 +288,8 @@ bool retro_load_game(const struct retro_game_info *info) hw_render.context_type = RETRO_HW_CONTEXT_OPENGL; hw_render.context_reset = context_reset; + hw_render.depth = true; + hw_render.stencil = true; if (!environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render)) return false; diff --git a/libretro.h b/libretro.h index 048bed8fbe..e710337ce6 100755 --- a/libretro.h +++ b/libretro.h @@ -462,6 +462,8 @@ struct retro_hw_render_callback 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_proc_address_t get_proc_address; // Set by frontend. + bool depth; // Set if render buffers should have depth component attached. + bool stencil; // Set if render buffers should have stencil component attached. }; // Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. Called by the frontend in response to keyboard events.