diff --git a/libretro-common/glsm/glsm.c b/libretro-common/glsm/glsm.c new file mode 100644 index 0000000000..59c407c801 --- /dev/null +++ b/libretro-common/glsm/glsm.c @@ -0,0 +1,948 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this libretro SDK code part (glsm). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +struct gl_cached_state +{ + struct + { + GLuint ids[MAX_TEXTURE]; + } bind_textures; + + struct + { + bool enabled[MAX_ATTRIB]; + } vertex_attrib_pointer; + + struct + { + GLuint r; + GLuint g; + GLuint b; + GLuint a; + } clear_color; + + struct + { + bool used; + GLint x; + GLint y; + GLsizei w; + GLsizei h; + } scissor; + + struct + { + GLint x; + GLint y; + GLsizei w; + GLsizei h; + } viewport; + + struct + { + bool used; + GLenum sfactor; + GLenum dfactor; + } blendfunc; + + struct + { + bool used; + GLenum srcRGB; + GLenum dstRGB; + GLenum srcAlpha; + GLenum dstAlpha; + } blendfunc_separate; + + struct + { + bool used; + GLboolean red; + GLboolean green; + GLboolean blue; + GLboolean alpha; + } colormask; + + struct + { + bool used; + GLdouble depth; + } cleardepth; + + struct + { + bool used; + GLenum func; + } depthfunc; + + struct + { + bool used; + GLclampd zNear; + GLclampd zFar; + } depthrange; + + struct + { + bool used; + GLfloat factor; + GLfloat units; + } polygonoffset; + + struct + { + bool used; + GLenum func; + GLint ref; + GLuint mask; + } stencilfunc; + + struct + { + bool used; + GLenum sfail; + GLenum dpfail; + GLenum dppass; + } stencilop; + + struct + { + bool used; + GLenum mode; + } frontface; + + struct + { + bool used; + GLenum mode; + } cullface; + + struct + { + bool used; + GLuint mask; + } stencilmask; + + struct + { + bool used; + GLboolean mask; + } depthmask; + + GLuint vao; + GLuint framebuf; + GLuint program; + GLenum active_texture; + int cap_state[SGL_CAP_MAX]; + int cap_translate[SGL_CAP_MAX]; +}; + +static glsm_framebuffer_lock glsm_fb_lock = NULL; +static glsm_imm_vbo_draw imm_vbo_draw = NULL; +static glsm_imm_vbo_draw imm_vbo_disable = NULL; +struct retro_hw_render_callback hw_render; +static struct gl_cached_state gl_state; + +/* GL wrapper-side */ + +void rglClearDepth(GLdouble depth) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); +#ifdef GLES + glClearDepthf(depth); +#else + glClearDepth(depth); +#endif + gl_state.cleardepth.used = true; + gl_state.cleardepth.depth = depth; +} + +void rglDepthRange(GLclampd zNear, GLclampd zFar) +{ +#ifdef GLES + glDepthRangef(zNear, zFar); +#else + glDepthRange(zNear, zFar); +#endif + gl_state.depthrange.used = true; + gl_state.depthrange.zNear = zNear; + gl_state.depthrange.zFar = zFar; +} + +void rglFrontFace(GLenum mode) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glFrontFace(mode); + gl_state.frontface.used = true; + gl_state.frontface.mode = mode; +} + +void rglDepthFunc(GLenum func) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + gl_state.depthfunc.used = true; + gl_state.depthfunc.func = func; + glDepthFunc(func); +} + +void rglColorMask(GLboolean red, GLboolean green, + GLboolean blue, GLboolean alpha) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glColorMask(red, green, blue, alpha); + gl_state.colormask.red = red; + gl_state.colormask.green = green; + gl_state.colormask.blue = blue; + gl_state.colormask.alpha = alpha; + gl_state.colormask.used = true; +} + +void rglCullFace(GLenum mode) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glCullFace(mode); + gl_state.cullface.used = true; + gl_state.cullface.mode = mode; +} + +void rglStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass) +{ + glStencilOp(sfail, dpfail, dppass); + gl_state.stencilop.used = true; + gl_state.stencilop.sfail = sfail; + gl_state.stencilop.dpfail = dpfail; + gl_state.stencilop.dppass = dppass; +} + +void rglStencilFunc(GLenum func, GLint ref, GLuint mask) +{ + glStencilFunc(func, ref, mask); + gl_state.stencilfunc.used = true; + gl_state.stencilfunc.func = func; + gl_state.stencilfunc.ref = ref; + gl_state.stencilfunc.mask = mask; +} + +GLboolean rglIsEnabled(GLenum cap) +{ + return gl_state.cap_state[cap] ? GL_TRUE : GL_FALSE; +} + +void rglClearColor(GLclampf red, GLclampf green, + GLclampf blue, GLclampf alpha) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glClearColor(red, green, blue, alpha); + gl_state.clear_color.r = red; + gl_state.clear_color.g = green; + gl_state.clear_color.b = blue; + gl_state.clear_color.a = alpha; +} + +void rglScissor(GLint x, GLint y, GLsizei width, GLsizei height) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glScissor(x, y, width, height); + gl_state.scissor.used = true; + gl_state.scissor.x = x; + gl_state.scissor.y = y; + gl_state.scissor.w = width; + gl_state.scissor.h = height; +} + +void rglViewport(GLint x, GLint y, GLsizei width, GLsizei height) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glViewport(x, y, width, height); + gl_state.viewport.x = x; + gl_state.viewport.y = y; + gl_state.viewport.w = width; + gl_state.viewport.h = height; +} + +void rglBlendFunc(GLenum sfactor, GLenum dfactor) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + gl_state.blendfunc.used = true; + gl_state.blendfunc.sfactor = sfactor; + gl_state.blendfunc.dfactor = dfactor; + glBlendFunc(sfactor, dfactor); +} + +void rglBlendFuncSeparate(GLenum sfactor, GLenum dfactor) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + gl_state.blendfunc_separate.used = true; + gl_state.blendfunc_separate.srcRGB = sfactor; + gl_state.blendfunc_separate.dstRGB = dfactor; + gl_state.blendfunc_separate.srcAlpha = sfactor; + gl_state.blendfunc_separate.dstAlpha = dfactor; + glBlendFunc(sfactor, dfactor); +} + +void rglActiveTexture(GLenum texture) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glActiveTexture(texture); + gl_state.active_texture = texture - GL_TEXTURE0; +} + +void rglBindTexture(GLenum target, GLuint texture) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glBindTexture(target, texture); + gl_state.bind_textures.ids[gl_state.active_texture] = texture; +} + +void rglDisable(GLenum cap) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glDisable(gl_state.cap_translate[cap]); + gl_state.cap_state[cap] = 0; +} + +void rglEnable(GLenum cap) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glEnable(gl_state.cap_translate[cap]); + gl_state.cap_state[cap] = 1; +} + +void rglUseProgram(GLuint program) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + gl_state.program = program; + glUseProgram(program); +} + +void rglDepthMask(GLboolean flag) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glDepthMask(flag); + gl_state.depthmask.used = true; + gl_state.depthmask.mask = flag; +} + +void rglStencilMask(GLenum mask) +{ + glStencilMask(mask); + gl_state.stencilmask.used = true; + gl_state.stencilmask.mask = mask; +} + +void rglBufferData(GLenum target, GLsizeiptr size, + const GLvoid *data, GLenum usage) +{ + glBufferData(target, size, data, usage); +} + +void rglBufferSubData(GLenum target, GLintptr offset, + GLsizeiptr size, const GLvoid *data) +{ + glBufferSubData(target, offset, size, data); +} + +void rglBindBuffer(GLenum target, GLuint buffer) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glBindBuffer(target, buffer); +} + +void rglLinkProgram(GLuint program) +{ + glLinkProgram(program); +} + +void rglFramebufferTexture2D(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level) +{ + glFramebufferTexture2D(target, attachment, textarget, texture, level); +} + +void rglDrawArrays(GLenum mode, GLint first, GLsizei count) +{ + glDrawArrays(mode, first, count); +} + +void rglCompressedTexImage2D(GLenum target, GLint level, + GLenum internalformat, GLsizei width, GLsizei height, + GLint border, GLsizei imageSize, const GLvoid *data) +{ + glCompressedTexImage2D(target, level, internalformat, + width, height, border, imageSize, data); +} + +void rglFramebufferRenderbuffer(GLenum target, GLenum attachment, + GLenum renderbuffertarget, GLuint renderbuffer) +{ + glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); +} + +void rglDeleteFramebuffers(GLsizei n, GLuint *framebuffers) +{ + glDeleteFramebuffers(n, framebuffers); +} + +void rglDeleteTextures(GLsizei n, const GLuint *textures) +{ + glDeleteTextures(n, textures); +} + +void rglRenderbufferStorage(GLenum target, GLenum internalFormat, + GLsizei width, GLsizei height) +{ + glRenderbufferStorage(target, internalFormat, width, height); +} + +void rglBindRenderbuffer(GLenum target, GLuint renderbuffer) +{ + glBindRenderbuffer(target, renderbuffer); +} + +void rglDeleteRenderbuffers(GLsizei n, GLuint *renderbuffers) +{ + glDeleteRenderbuffers(n, renderbuffers); +} + +void rglGenRenderbuffers(GLsizei n, GLuint *renderbuffers) +{ + glGenRenderbuffers(n, renderbuffers); +} + +void rglGenFramebuffers(GLsizei n, GLuint *ids) +{ + glGenFramebuffers(n, ids); +} + +void rglBindFramebuffer(GLenum target, GLuint framebuffer) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + if (!glsm_ctl(GLSM_CTL_IS_FRAMEBUFFER_LOCKED, NULL)) + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer + ? framebuffer : hw_render.get_current_framebuffer()); +} + +void rglGenerateMipmap(GLenum target) +{ + glGenerateMipmap(target); +} + +GLenum rglCheckFramebufferStatus(GLenum target) +{ + return glCheckFramebufferStatus(target); +} + +void rglBindFragDataLocation(GLuint program, GLuint colorNumber, + const char * name) +{ + glBindFragDataLocation(program, colorNumber, name); +} + +void rglBindAttribLocation(GLuint program, GLuint index, const GLchar *name) +{ + glBindAttribLocation(program, index, name); +} + +void rglGetProgramiv(GLuint shader, GLenum pname, GLint *params) +{ + glGetProgramiv(shader, pname, params); +} + +void rglGetShaderiv(GLuint shader, GLenum pname, GLint *params) +{ + glGetShaderiv(shader, pname, params); +} + +void rglAttachShader(GLuint program, GLuint shader) +{ + glAttachShader(program, shader); +} + +void rglShaderSource(GLuint shader, GLsizei count, + const GLchar **string, const GLint *length) +{ + return glShaderSource(shader, count, string, length); +} + +void rglCompileShader(GLuint shader) +{ + glCompileShader(shader); +} + +GLuint rglCreateProgram(void) +{ + return glCreateProgram(); +} + +void rglGenTextures(GLsizei n, GLuint *textures) +{ + glGenTextures(n, textures); +} + +void rglGetShaderInfoLog(GLuint shader, GLsizei maxLength, + GLsizei *length, GLchar *infoLog) +{ + glGetShaderInfoLog(shader, maxLength, length, infoLog); +} + +void rglGetProgramInfoLog(GLuint shader, GLsizei maxLength, + GLsizei *length, GLchar *infoLog) +{ + glGetProgramInfoLog(shader, maxLength, length, infoLog); +} + +GLboolean rglIsProgram(GLuint program) +{ + glIsProgram(program); +} + +void rglEnableVertexAttribArray(GLuint index) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + gl_state.vertex_attrib_pointer.enabled[index] = 1; + glEnableVertexAttribArray(index); +} + +void rglDisableVertexAttribArray(GLuint index) +{ + gl_state.vertex_attrib_pointer.enabled[index] = 0; + glDisableVertexAttribArray(index); +} + +void rglDrawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid * indices) +{ + glDrawElements(mode, count, type, indices); +} + +void rglTexCoord2f(GLfloat s, GLfloat t) +{ +#ifdef HAVE_LEGACY_GL + glTexCoord2f(s, t); +#endif +} + +void rglVertexAttribPointer(GLuint name, GLint size, + GLenum type, GLboolean normalized, GLsizei stride, + const GLvoid* pointer) +{ + glVertexAttribPointer(name, size, type, normalized, stride, pointer); +} + +void rglVertexAttrib4f(GLuint name, GLfloat x, GLfloat y, + GLfloat z, GLfloat w) +{ + glVertexAttrib4f(name, x, y, z, w); +} + +void rglVertexAttrib4fv(GLuint name, GLfloat* v) +{ + glVertexAttrib4fv(name, v); +} + +GLuint rglCreateShader(GLenum shaderType) +{ + return glCreateShader(shaderType); +} + +void rglDeleteProgram(GLuint program) +{ + glDeleteProgram(program); +} + +void rglDeleteShader(GLuint shader) +{ + glDeleteShader(shader); +} + +GLint rglGetUniformLocation(GLuint program, const GLchar *name) +{ + return glGetUniformLocation(program, name); +} + +void rglDeleteBuffers(GLsizei n, const GLuint *buffers) +{ + glDeleteBuffers(n, buffers); +} + +void rglGenBuffers(GLsizei n, GLuint *buffers) +{ + glGenBuffers(n, buffers); +} + +void rglUniform1f(GLint location, GLfloat v0) +{ + glUniform1f(location, v0); +} + +void rglUniform1i(GLint location, GLint v0) +{ + glUniform1i(location, v0); +} + +void rglUniform2f(GLint location, GLfloat v0, GLfloat v1) +{ + glUniform2f(location, v0, v1); +} + +void rglUniform2fv(GLint location, GLsizei count, const GLfloat *value) +{ + glUniform2fv(location, count, value); +} + +void rglUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) +{ + glUniform3f(location, v0, v1, v2); +} + +void rglUniform3fv(GLint location, GLsizei count, const GLfloat *value) +{ + glUniform3fv(location, count, value); +} + +void rglUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) +{ + glUniform4f(location, v0, v1, v2, v3); +} + +void rglUniform4fv(GLint location, GLsizei count, const GLfloat *value) +{ + glUniform4fv(location, count, value); +} + +void rglPolygonOffset(GLfloat factor, GLfloat units) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glPolygonOffset(factor, units); + gl_state.polygonoffset.used = true; + gl_state.polygonoffset.factor = factor; + gl_state.polygonoffset.units = units; +} + +/* GLSM-side */ + +static void glsm_state_setup(void) +{ + unsigned i; + + gl_state.cap_translate[SGL_DEPTH_TEST] = GL_DEPTH_TEST; + gl_state.cap_translate[SGL_BLEND] = GL_BLEND; + gl_state.cap_translate[SGL_POLYGON_OFFSET_FILL] = GL_POLYGON_OFFSET_FILL; + gl_state.cap_translate[SGL_FOG] = GL_FOG; + gl_state.cap_translate[SGL_CULL_FACE] = GL_CULL_FACE; + gl_state.cap_translate[SGL_ALPHA_TEST] = GL_ALPHA_TEST; + gl_state.cap_translate[SGL_SCISSOR_TEST] = GL_SCISSOR_TEST; + gl_state.cap_translate[SGL_STENCIL_TEST] = GL_STENCIL_TEST; + + for (i = 0; i < MAX_ATTRIB; i++) + gl_state.vertex_attrib_pointer.enabled[i] = 0; + + gl_state.framebuf = hw_render.get_current_framebuffer(); + gl_state.cullface.mode = GL_BACK; + gl_state.frontface.mode = GL_CCW; + + gl_state.blendfunc_separate.used = false; + gl_state.blendfunc_separate.srcRGB = GL_ONE; + gl_state.blendfunc_separate.dstRGB = GL_ZERO; + gl_state.blendfunc_separate.srcAlpha = GL_ONE; + gl_state.blendfunc_separate.dstAlpha = GL_ZERO; + + gl_state.depthfunc.used = false; + + gl_state.colormask.used = false; + gl_state.colormask.red = GL_TRUE; + gl_state.colormask.green = GL_TRUE; + gl_state.colormask.blue = GL_TRUE; + gl_state.colormask.alpha = GL_TRUE; + + gl_state.polygonoffset.used = false; + + gl_state.depthfunc.func = GL_LESS; + +#ifdef CORE + glGenVertexArrays(1, &gl_state.vao); +#endif +} + +static void glsm_state_bind(void) +{ + unsigned i; + + for (i = 0; i < MAX_ATTRIB; i++) + { + if (gl_state.vertex_attrib_pointer.enabled[i]) + glEnableVertexAttribArray(i); + else + glDisableVertexAttribArray(i); + } + + glBindFramebuffer( + RARCH_GL_FRAMEBUFFER, + hw_render.get_current_framebuffer()); + + if (gl_state.blendfunc.used) + glBlendFunc( + gl_state.blendfunc.sfactor, + gl_state.blendfunc.dfactor); + + if (gl_state.blendfunc_separate.used) + glBlendFuncSeparate( + gl_state.blendfunc_separate.srcRGB, + gl_state.blendfunc_separate.dstRGB, + gl_state.blendfunc_separate.srcAlpha, + gl_state.blendfunc_separate.dstAlpha + ); + + glClearColor( + gl_state.clear_color.r, + gl_state.clear_color.g, + gl_state.clear_color.b, + gl_state.clear_color.a); + + if (gl_state.depthfunc.used) + glDepthFunc(gl_state.depthfunc.func); + + if (gl_state.colormask.used) + glColorMask( + gl_state.colormask.red, + gl_state.colormask.green, + gl_state.colormask.blue, + gl_state.colormask.alpha); + + if (gl_state.cullface.used) + glCullFace(gl_state.cullface.mode); + + if (gl_state.depthmask.used) + glDepthMask(gl_state.depthmask.mask); + + if (gl_state.polygonoffset.used) + glPolygonOffset( + gl_state.polygonoffset.factor, + gl_state.polygonoffset.units); + + if (gl_state.scissor.used) + glScissor( + gl_state.scissor.x, + gl_state.scissor.y, + gl_state.scissor.w, + gl_state.scissor.h); + + glUseProgram(gl_state.program); + + glViewport( + gl_state.viewport.x, + gl_state.viewport.y, + gl_state.viewport.w, + gl_state.viewport.h); +#ifdef CORE + glBindVertexArray(gl_state.vao); +#endif + for(i = 0; i < SGL_CAP_MAX; i ++) + { + if (gl_state.cap_state[i]) + glEnable(gl_state.cap_translate[i]); + else + glDisable(gl_state.cap_translate[i]); + } + + if (gl_state.frontface.used) + glFrontFace(gl_state.frontface.mode); + + if (gl_state.stencilmask.used) + glStencilMask(gl_state.stencilmask.mask); + + if (gl_state.stencilop.used) + glStencilOp(gl_state.stencilop.sfail, + gl_state.stencilop.dpfail, + gl_state.stencilop.dppass); + + if (gl_state.stencilfunc.used) + glStencilFunc( + gl_state.stencilfunc.func, + gl_state.stencilfunc.ref, + gl_state.stencilfunc.mask); + + for (i = 0; i < MAX_TEXTURE; i ++) + { + glActiveTexture(GL_TEXTURE0 + i); + glBindTexture(GL_TEXTURE_2D, gl_state.bind_textures.ids[i]); + } + + glActiveTexture(GL_TEXTURE0 + gl_state.active_texture); + + glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +static void glsm_state_unbind(void) +{ + unsigned i; +#ifdef CORE + glBindVertexArray(0); +#endif + for (i = 0; i < SGL_CAP_MAX; i ++) + glDisable(gl_state.cap_translate[i]); + glDisable(GL_BLEND); + glDisable(GL_CULL_FACE); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_DEPTH_TEST); + glBlendFunc(GL_ONE, GL_ZERO); + if (gl_state.colormask.used) + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + if (gl_state.blendfunc_separate.used) + glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO); + glCullFace(GL_BACK); + glDepthMask(GL_TRUE); + if (gl_state.polygonoffset.used) + glPolygonOffset(0, 0); + glUseProgram(0); + glClearColor(0,0,0,0.0f); + glStencilMask(1); + glFrontFace(GL_CCW); + if (gl_state.depthfunc.used) + glDepthFunc(GL_LESS); + glStencilOp(GL_KEEP,GL_KEEP, GL_KEEP); + glStencilFunc(GL_ALWAYS,0,1); + + /* Clear textures */ + for (i = 0; i < MAX_TEXTURE; i ++) + { + glActiveTexture(GL_TEXTURE0 + i); + glBindTexture(GL_TEXTURE_2D, 0); + } + glActiveTexture(GL_TEXTURE0); + + for (i = 0; i < MAX_ATTRIB; i ++) + glDisableVertexAttribArray(i); + + glBindFramebuffer(RARCH_GL_FRAMEBUFFER, 0); +} + +static bool dummy_framebuffer_lock(void *data) +{ + (void)data; + return false; +} + +static bool glsm_state_ctx_init(void *data) +{ + glsm_ctx_params_t *params = (glsm_ctx_params_t*)data; + + if (!params || !params->environ_cb) + return false; + +#ifdef GLES +#if defined(GLES31) + hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES_VERSION; + hw_render.version_major = 3; + hw_render.version_minor = 1; +#elif defined(GLES3) + hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES3; +#else + hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES2; +#endif +#else +#ifdef CORE + hw_render.context_type = RETRO_HW_CONTEXT_OPENGL_CORE; + hw_render.version_major = 3; + hw_render.version_minor = 1; +#else + hw_render.context_type = RETRO_HW_CONTEXT_OPENGL; +#endif +#endif + hw_render.context_reset = params->context_reset; + hw_render.context_destroy = params->context_destroy; + hw_render.stencil = params->stencil; + hw_render.depth = true; + hw_render.bottom_left_origin = true; + hw_render.cache_context = true; + + imm_vbo_draw = NULL; + imm_vbo_disable = NULL; + + if (params->imm_vbo_draw != NULL) + imm_vbo_draw = params->imm_vbo_draw; + if (params->imm_vbo_disable != NULL) + imm_vbo_disable = params->imm_vbo_disable; + + glsm_fb_lock = dummy_framebuffer_lock; + if (params->framebuffer_lock != NULL) + glsm_fb_lock = params->framebuffer_lock; + + if (imm_vbo_draw != NULL && imm_vbo_disable != NULL) + glsm_ctl(GLSM_CTL_SET_IMM_VBO, NULL); + + if (!params->environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render)) + return false; + + return true; +} + +bool glsm_ctl(enum glsm_state_ctl state, void *data) +{ + static bool imm_vbo_enable = false; + + switch (state) + { + case GLSM_CTL_IS_FRAMEBUFFER_LOCKED: + return glsm_fb_lock(NULL); + case GLSM_CTL_IMM_VBO_DRAW: + if (imm_vbo_draw == NULL || !imm_vbo_enable) + return false; + imm_vbo_draw(NULL); + break; + case GLSM_CTL_IMM_VBO_DISABLE: + if (imm_vbo_disable == NULL || !imm_vbo_enable) + return false; + imm_vbo_disable(NULL); + break; + case GLSM_CTL_IS_IMM_VBO: + return imm_vbo_enable; + case GLSM_CTL_SET_IMM_VBO: + imm_vbo_enable = true; + break; + case GLSM_CTL_UNSET_IMM_VBO: + imm_vbo_enable = false; + break; + case GLSM_CTL_STATE_CONTEXT_RESET: + rglgen_resolve_symbols(hw_render.get_proc_address); + break; + case GLSM_CTL_STATE_CONTEXT_INIT: + return glsm_state_ctx_init(data); + case GLSM_CTL_STATE_SETUP: + glsm_state_setup(); + break; + case GLSM_CTL_STATE_UNBIND: + glsm_state_unbind(); + break; + case GLSM_CTL_STATE_BIND: + glsm_state_bind(); + break; + case GLSM_CTL_NONE: + default: + break; + } + + return true; +} diff --git a/libretro-common/include/glsm/glsm.h b/libretro-common/include/glsm/glsm.h new file mode 100644 index 0000000000..b68d20eab1 --- /dev/null +++ b/libretro-common/include/glsm/glsm.h @@ -0,0 +1,138 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this libretro SDK code part (glsm.h). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef LIBRETRO_SDK_GLSM_H +#define LIBRETRO_SDK_GLSM_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_OPENGLES2 +typedef GLfloat GLdouble; +typedef GLclampf GLclampd; +#endif + +#if defined(HAVE_OPENGLES2) +#define RARCH_GL_RENDERBUFFER GL_RENDERBUFFER +#define RARCH_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES +#define RARCH_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT +#define RARCH_GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT +#elif defined(OSX_PPC) +#define RARCH_GL_RENDERBUFFER GL_RENDERBUFFER_EXT +#define RARCH_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_EXT +#define RARCH_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_EXT +#define RARCH_GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT_EXT +#elif defined(HAVE_PSGL) +#define RARCH_GL_RENDERBUFFER GL_RENDERBUFFER_OES +#define RARCH_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_SCE +#define RARCH_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_OES +#define RARCH_GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT_OES +#else +#define RARCH_GL_RENDERBUFFER GL_RENDERBUFFER +#define RARCH_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8 +#define RARCH_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT +#define RARCH_GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT +#endif + +#if defined(HAVE_PSGL) +#define RARCH_GL_FRAMEBUFFER GL_FRAMEBUFFER_OES +#define RARCH_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_OES +#define RARCH_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT +#elif defined(OSX_PPC) +#define RARCH_GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT +#define RARCH_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_EXT +#define RARCH_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT +#else +#define RARCH_GL_FRAMEBUFFER GL_FRAMEBUFFER +#define RARCH_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE +#define RARCH_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0 +#endif + +#ifndef GL_FOG +#define GL_FOG 0x0B60 +#endif + +#ifndef GL_ALPHA_TEST +#define GL_ALPHA_TEST 0x0BC0 +#endif + +#define MAX_ATTRIB 8 +#define MAX_TEXTURE 32 + +enum +{ + SGL_DEPTH_TEST = 0, + SGL_BLEND = 1, + SGL_POLYGON_OFFSET_FILL = 2, + SGL_FOG = 3, + SGL_CULL_FACE = 4, + SGL_ALPHA_TEST = 5, + SGL_SCISSOR_TEST = 6, + SGL_STENCIL_TEST = 7, + SGL_CAP_MAX +}; + +enum glsm_state_ctl +{ + GLSM_CTL_NONE = 0, + GLSM_CTL_STATE_SETUP, + GLSM_CTL_STATE_BIND, + GLSM_CTL_STATE_UNBIND, + GLSM_CTL_STATE_CONTEXT_RESET, + GLSM_CTL_STATE_CONTEXT_INIT, + GLSM_CTL_IS_IMM_VBO, + GLSM_CTL_SET_IMM_VBO, + GLSM_CTL_UNSET_IMM_VBO, + GLSM_CTL_IMM_VBO_DISABLE, + GLSM_CTL_IMM_VBO_DRAW, + GLSM_CTL_IS_FRAMEBUFFER_LOCKED +}; + +typedef bool (*glsm_imm_vbo_draw)(void *); +typedef bool (*glsm_imm_vbo_disable)(void *); +typedef bool (*glsm_framebuffer_lock)(void *); + +typedef struct glsm_ctx_params +{ + glsm_framebuffer_lock framebuffer_lock; + glsm_imm_vbo_draw imm_vbo_draw; + glsm_imm_vbo_disable imm_vbo_disable; + retro_hw_context_reset_t context_reset; + retro_hw_context_reset_t context_destroy; + retro_environment_t environ_cb; + bool stencil; + unsigned major; + unsigned minor; +} glsm_ctx_params_t; + +bool glsm_ctl(enum glsm_state_ctl state, void *data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libretro-common/include/glsm/glsmsym.h b/libretro-common/include/glsm/glsmsym.h new file mode 100644 index 0000000000..6fa27098cd --- /dev/null +++ b/libretro-common/include/glsm/glsmsym.h @@ -0,0 +1,202 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this libretro SDK code part (glsmsym.h). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef LIBRETRO_SDK_GLSM_SYM_H +#define LIBRETRO_SDK_GLSM_SYM_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* deprecated old FF-style GL symbols */ +#define glTexCoord2f rglTexCoord2f + +/* more forward-compatible GL subset symbols */ +#define glVertexAttrib4f rglVertexAttrib4f +#define glVertexAttrib4fv rglVertexAttrib4fv +#define glDrawArrays rglDrawArrays +#define glDrawElements rglDrawElements +#define glCompressedTexImage2D rglCompressedTexImage2D +#define glBindTexture rglBindTexture +#define glActiveTexture rglActiveTexture +#define glFramebufferTexture2D rglFramebufferTexture2D +#define glFramebufferRenderbuffer rglFramebufferRenderbuffer +#define glDeleteFramebuffers rglDeleteFramebuffers +#define glDeleteTextures rglDeleteTextures +#define glDeleteBuffers rglDeleteBuffers +#define glRenderbufferStorage rglRenderbufferStorage +#define glBindRenderbuffer rglBindRenderbuffer +#define glDeleteRenderbuffers rglDeleteRenderbuffers +#define glGenRenderbuffers rglGenRenderbuffers +#define glGenFramebuffers rglGenFramebuffers +#define glGenTextures rglGenTextures +#define glBindFramebuffer rglBindFramebuffer +#define glGenerateMipmap rglGenerateMipmap +#define glCheckFramebufferStatus rglCheckFramebufferStatus +#define glBindFragDataLocation rglBindFragDataLocation +#define glBindAttribLocation rglBindAttribLocation +#define glLinkProgram rglLinkProgram +#define glGetProgramiv rglGetProgramiv +#define glGetShaderiv rglGetShaderiv +#define glAttachShader rglAttachShader +#define glShaderSource rglShaderSource +#define glCompileShader rglCompileShader +#define glCreateProgram rglCreateProgram +#define glGetShaderInfoLog rglGetShaderInfoLog +#define glGetProgramInfoLog rglGetProgramInfoLog +#define glIsProgram rglIsProgram +#define glEnableVertexAttribArray rglEnableVertexAttribArray +#define glDisableVertexAttribArray rglDisableVertexAttribArray +#define glVertexAttribPointer rglVertexAttribPointer +#define glGetUniformLocation rglGetUniformLocation +#define glGenBuffers rglGenBuffers +#define glDisable(T) rglDisable(S##T) +#define glEnable(T) rglEnable(S##T) +#define glUseProgram rglUseProgram +#define glDepthMask rglDepthMask +#define glStencilMask rglStencilMask +#define glBufferData rglBufferData +#define glBufferSubData rglBufferSubData +#define glBindBuffer rglBindBuffer +#define glCreateShader rglCreateShader +#define glDeleteShader rglDeleteShader +#define glDeleteProgram rglDeleteProgram +#define glUniform1f rglUniform1f +#define glUniform1i rglUniform1i +#define glUniform2f rglUniform2f +#define glUniform2fv rglUniform2fv +#define glUniform3f rglUniform3f +#define glUniform3fv rglUniform3fv +#define glUniform4f rglUniform4f +#define glUniform4fv rglUniform4fv +#define glBlendFunc rglBlendFunc +#define glBlendFuncSeparate rglBlendFuncSeparate +#define glDepthFunc rglDepthFunc +#define glColorMask rglColorMask +#define glClearColor rglClearColor +#define glViewport rglViewport +#define glScissor rglScissor +#define glIsEnabled rglIsEnabled +#define glStencilFunc rglStencilFunc +#define glCullFace rglCullFace +#define glStencilOp rglStencilOp +#define glFrontFace rglFrontFace +#define glDepthRange rglDepthRange +#define glClearDepth rglClearDepth +#define glPolygonOffset rglPolygonOffset + +void rglTexCoord2f(GLfloat s, GLfloat t); +void rglDrawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid * indices); +void rglCompressedTexImage2D(GLenum target, GLint level, + GLenum internalformat, GLsizei width, GLsizei height, + GLint border, GLsizei imageSize, const GLvoid *data); +void glBindTexture(GLenum target, GLuint texture); +void glActiveTexture(GLenum texture); +void rglFramebufferTexture2D(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level); +void rglFramebufferRenderbuffer(GLenum target, GLenum attachment, + GLenum renderbuffertarget, GLuint renderbuffer); +void rglDeleteFramebuffers(GLsizei n, GLuint *framebuffers); +void rglRenderbufferStorage(GLenum target, GLenum internalFormat, + GLsizei width, GLsizei height); +void rglDeleteTextures(GLsizei n, const GLuint *textures); +void rglBindRenderbuffer(GLenum target, GLuint renderbuffer); +void rglDeleteRenderbuffers(GLsizei n, GLuint *renderbuffers); +void rglGenRenderbuffers(GLsizei n, GLuint *renderbuffers); +void rglGenFramebuffers(GLsizei n, GLuint *ids); +void rglGenTextures(GLsizei n, GLuint *textures); +void rglBindFramebuffer(GLenum target, GLuint framebuffer); +void rglGenerateMipmap(GLenum target); +GLenum rglCheckFramebufferStatus(GLenum target); +void rglBindFragDataLocation(GLuint program, GLuint colorNumber, + const char * name); +void rglBindAttribLocation(GLuint program, GLuint index, const GLchar *name); +void rglLinkProgram(GLuint program); +void rglGetProgramiv(GLuint shader, GLenum pname, GLint *params); +void rglGetShaderiv(GLuint shader, GLenum pname, GLint *params); +void rglAttachShader(GLuint program, GLuint shader); +void rglShaderSource(GLuint shader, GLsizei count, + const GLchar **string, const GLint *length); +void rglCompileShader(GLuint shader); +GLuint rglCreateProgram(void); +void rglGetShaderInfoLog(GLuint shader, GLsizei maxLength, + GLsizei *length, GLchar *infoLog); +void rglGetProgramInfoLog(GLuint shader, GLsizei maxLength, + GLsizei *length, GLchar *infoLog); +GLboolean rglIsProgram(GLuint program); +void rglEnableVertexAttribArray(GLuint index); +void rglDisableVertexAttribArray(GLuint index); +void rglVertexAttribPointer(GLuint name, GLint size, + GLenum type, GLboolean normalized, GLsizei stride, + const GLvoid* pointer); +GLint rglGetUniformLocation(GLuint program, const GLchar *name); +void rglGenBuffers(GLsizei n, GLuint *buffers); +void rglDisable(GLenum cap); +void rglEnable(GLenum cap); +void rglUseProgram(GLuint program); +void rglDepthMask(GLboolean flag); +void rglStencilMask(GLenum mask); +void rglBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); +void rglBufferSubData(GLenum target, GLintptr offset, + GLsizeiptr size, const GLvoid *data); +void rglBindBuffer(GLenum target, GLuint buffer); +GLuint rglCreateShader(GLenum shader); +void rglDeleteShader(GLuint shader); +void rglUniform1f(GLint location, GLfloat v0); +void rglUniform1i(GLint location, GLint v0); +void rglUniform2f(GLint location, GLfloat v0, GLfloat v1); +void rglUniform2fv(GLint location, GLsizei count, const GLfloat *value); +void rglUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +void rglUniform3fv(GLint location, GLsizei count, const GLfloat *value); +void rglUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +void rglUniform4fv(GLint location, GLsizei count, const GLfloat *value); +void rglBlendFunc(GLenum sfactor, GLenum dfactor); +void rglBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, + GLenum dstAlpha); +void rglDepthFunc(GLenum func); +void rglColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +void rglClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +void rglViewport(GLint x, GLint y, GLsizei width, GLsizei height); +void rglScissor(GLint x, GLint y, GLsizei width, GLsizei height); +GLboolean rglIsEnabled(GLenum cap); +void rglStencilFunc(GLenum func, GLint ref, GLuint mask); +void rglCullFace(GLenum mode); +void rglStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass); +void rglFrontFace(GLenum mode); +void rglDepthRange(GLclampd zNear, GLclampd zFar); +void rglClearDepth(GLdouble depth); +void rglPolygonOffset(GLfloat factor, GLfloat units); +void rglDrawArrays(GLenum mode, GLint first, GLsizei count); +void rglVertexAttrib4f(GLuint name, GLfloat x, GLfloat y, + GLfloat z, GLfloat w); +void rglVertexAttrib4fv(GLuint name, GLfloat* v); +void rglDeleteProgram(GLuint program); +void rglDeleteBuffers(GLsizei n, const GLuint *buffers); + +#ifdef __cplusplus +} +#endif + +#endif