diff --git a/ref/gl/gl2_shim/fragment.glsl.inc b/ref/gl/gl2_shim/fragment.glsl.inc new file mode 100644 index 00000000..0e66d98a --- /dev/null +++ b/ref/gl/gl2_shim/fragment.glsl.inc @@ -0,0 +1,53 @@ +R"( +precision mediump float; +#if ATTR_TEXCOORD0 +uniform sampler2D uTex0; +#endif +#if ATTR_TEXCOORD1 +uniform sampler2D uTex1; +#endif +#if FEAT_ALPHA_TEST +uniform float uAlphaTest; +#endif +#if FEAT_FOG +uniform vec4 uFog; +#endif +uniform vec4 uColor; +#if ATTR_COLOR +in vec4 vColor; +#endif +#if ATTR_TEXCOORD0 +in vec2 vTexCoord0; +#endif +#if ATTR_TEXCOORD1 +in vec2 vTexCoord1; +#endif +#if ATTR_NORMAL +in vec2 vNormal; +#endif +out vec4 oFragColor; +void main() +{ +#if ATTR_COLOR + vec4 c = vColor; +#else + vec4 c = uColor; +#endif +#if ATTR_TEXCOORD0 + c = c * texture(uTex0, vTexCoord0); +#endif +#if ATTR_TEXCOORD1 + c = c * texture(uTex1, vTexCoord1); +#endif +#if FEAT_ALPHA_TEST + if(c.a <= uAlphaTest) + discard; +#endif +#if FEAT_FOG + float fogDist = gl_FragCoord.z / gl_FragCoord.w; + float fogRate = clamp(exp(-uFog.w * fogDist), 0.f, 1.f); + c.rgb = mix(uFog.rgb, c.rgb, fogRate); +#endif + oFragColor = c; +} +)" diff --git a/ref/gl/gl2_shim/gl2_shim.c b/ref/gl/gl2_shim/gl2_shim.c new file mode 100644 index 00000000..8dad3874 --- /dev/null +++ b/ref/gl/gl2_shim/gl2_shim.c @@ -0,0 +1,623 @@ +/* +gl2wrap_shim.c - vitaGL custom immediate mode shim +Copyright (C) 2023 fgsfds + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +*/ + +/* + this is a "replacement" for vitaGL's immediate mode tailored specifically for xash + this will only provide performance gains if vitaGL is built with DRAW_SPEEDHACK=1 + since that makes it assume that all vertex data pointers are GPU-mapped +*/ + +#include +#include +#include +#include + +#include "port.h" +#include "xash3d_types.h" +#include "cvardef.h" +#include "const.h" +#include "com_model.h" +#include "cl_entity.h" +#include "render_api.h" +#include "protocol.h" +#include "dlight.h" +#include "ref_api.h" +#include "com_strings.h" +#include "crtlib.h" +#include "gl2_shim.h" +#include "../gl_export.h" +#define MAX_SHADERLEN 4096 +// increase this when adding more attributes +#define MAX_PROGS 32 + +extern ref_api_t gEngfuncs; + +static void APIENTRY (*rpglEnable)(GLenum e); +static void APIENTRY (*rpglDisable)(GLenum e); + +enum gl2wrap_attrib_e +{ + GL2_ATTR_POS = 0, // 1 + GL2_ATTR_COLOR = 1, // 2 + GL2_ATTR_TEXCOORD0 = 2, // 4 + GL2_ATTR_TEXCOORD1 = 3, // 8 + GL2_ATTR_MAX +}; + +// continuation of previous enum +enum gl2wrap_flag_e +{ + GL2_FLAG_ALPHA_TEST = GL2_ATTR_MAX, // 16 + GL2_FLAG_FOG, // 32 + GL2_FLAG_NORMAL, + GL2_FLAG_MAX +}; + +typedef struct +{ + GLuint flags; + GLint attridx[GL2_ATTR_MAX]; + GLuint glprog; + GLint ucolor; + GLint ualpha; + GLint utex0; + GLint utex1; + GLint ufog; +} gl2wrap_prog_t; + +static const char *gl2wrap_vert_src = +#include "vertex.glsl.inc" +; + +static const char *gl2wrap_frag_src = +#include "fragment.glsl.inc" +; + +static int gl2wrap_init = 0; + +static struct +{ + GLfloat *attrbuf[GL2_ATTR_MAX]; + GLuint cur_flags; + GLint begin; + GLint end; + GLenum prim; + GLfloat color[4]; + GLfloat fog[4]; // color + density + GLfloat alpharef; + gl2wrap_prog_t progs[MAX_PROGS]; + gl2wrap_prog_t *cur_prog; + GLboolean uchanged; +} gl2wrap; + +static const int gl2wrap_attr_size[GL2_ATTR_MAX] = { 3, 4, 2, 2 }; + +static const char *gl2wrap_flag_name[GL2_FLAG_MAX] = +{ + "ATTR_POSITION", + "ATTR_COLOR", + "ATTR_TEXCOORD0", + "ATTR_TEXCOORD1", + "FEAT_ALPHA_TEST", + "FEAT_FOG", + "ATTR_NORMAL", +}; + +static const char *gl2wrap_attr_name[GL2_ATTR_MAX] = +{ + "inPosition", + "inColor", + "inTexCoord0", + "inTexCoord1", +}; + +// HACK: borrow alpha test and fog flags from internal vitaGL state +GLboolean alpha_test_state; +GLboolean fogging; + +static char *GL_PrintInfoLog( GLhandleARB object ) +{ + static char msg[8192]; + int maxLength = 0; + + pglGetObjectParameterivARB( object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &maxLength ); + + if( maxLength >= sizeof( msg )) + { + //ALERT( at_warning, "GL_PrintInfoLog: message exceeds %i symbols\n", sizeof( msg )); + maxLength = sizeof( msg ) - 1; + } + + pglGetInfoLogARB( object, maxLength, &maxLength, msg ); + + return msg; +} + + +static GLuint GL2_GenerateShader( const gl2wrap_prog_t *prog, GLenum type ) +{ + char *shader, shader_buf[MAX_SHADERLEN + 1]; + char tmp[256]; + int i; + GLint status, len; + GLuint id; + + shader = shader_buf; + //shader[0] = '\n'; + shader[0] = 0; + Q_strncat(shader, "#version 130\n", MAX_SHADERLEN); + + for ( i = 0; i < GL2_FLAG_MAX; ++i ) + { + Q_snprintf( tmp, sizeof( tmp ), "#define %s %d\n", gl2wrap_flag_name[i], prog->flags & ( 1 << i ) ); + Q_strncat( shader, tmp, MAX_SHADERLEN ); + } + + if ( type == GL_FRAGMENT_SHADER_ARB ) + Q_strncat( shader, gl2wrap_frag_src, MAX_SHADERLEN ); + else + Q_strncat( shader, gl2wrap_vert_src, MAX_SHADERLEN ); + + id = pglCreateShaderObjectARB( type ); + len = Q_strlen( shader ); + pglShaderSourceARB( id, 1, (const void *)&shader, &len ); + pglCompileShaderARB( id ); + pglGetObjectParameterivARB( id, GL_OBJECT_COMPILE_STATUS_ARB, &status ); + //pglGetOShaderiv( id, GL_OBJECT_COMPILE_STATUS_ARB, &status ); + //gEngfuncs.Con_Reportf( S_ERROR "GL2_GenerateShader( 0x%04x, 0x%x ): compile failed: %s\n", prog->flags, type, GL_PrintInfoLog(id)); + if ( status == GL_FALSE ) + { + gEngfuncs.Con_Reportf( S_ERROR "GL2_GenerateShader( 0x%04x, 0x%x ): compile failed: %s\n", prog->flags, type, GL_PrintInfoLog(id)); + + gEngfuncs.Con_DPrintf( "Shader text:\n%s\n\n", shader ); + pglDeleteObjectARB( id ); + return 0; + } + + return id; +} + +static gl2wrap_prog_t *GL2_GetProg( const GLuint flags ) +{ + int i, loc, status; + GLuint vp, fp, glprog; + gl2wrap_prog_t *prog; + + // try to find existing prog matching this feature set + + if ( gl2wrap.cur_prog && gl2wrap.cur_prog->flags == flags ) + return gl2wrap.cur_prog; + + for ( i = 0; i < MAX_PROGS; ++i ) + { + if ( gl2wrap.progs[i].flags == flags ) + return &gl2wrap.progs[i]; + else if ( gl2wrap.progs[i].flags == 0 ) + break; + } + + if ( i == MAX_PROGS ) + { + gEngfuncs.Host_Error( "GL2_GetProg(): Ran out of program slots for 0x%04x\n", flags ); + return NULL; + } + + // new prog; generate shaders + + gEngfuncs.Con_DPrintf( S_NOTE "GL2_GetProg(): Generating progs for 0x%04x\n", flags ); + prog = &gl2wrap.progs[i]; + prog->flags = flags; + + vp = GL2_GenerateShader( prog, GL_VERTEX_SHADER_ARB ); + fp = GL2_GenerateShader( prog, GL_FRAGMENT_SHADER_ARB ); + if ( !vp || !fp ) + { + prog->flags = 0; + return NULL; + } + + glprog = pglCreateProgramObjectARB(); + pglAttachObjectARB( glprog, vp ); + pglAttachObjectARB( glprog, fp ); + + loc = 0; + for ( i = 0; i < GL2_ATTR_MAX; ++i ) + { + if ( flags & ( 1 << i ) ) + { + prog->attridx[i] = loc; + pglBindAttribLocationARB( glprog, loc++, gl2wrap_attr_name[i] ); + } + else + { + prog->attridx[i] = -1; + } + } + + pglLinkProgramARB( glprog ); + pglDeleteObjectARB( vp ); + pglDeleteObjectARB( fp ); + + pglGetObjectParameterivARB( glprog, GL_OBJECT_LINK_STATUS_ARB, &status ); + if ( status == GL_FALSE ) + { + gEngfuncs.Con_Reportf( S_ERROR "GL2_GetProg(): Failed linking progs for 0x%04x!\n%s\n", prog->flags, GL_PrintInfoLog(glprog) ); + prog->flags = 0; + pglDeleteObjectARB( glprog ); + return NULL; + } + + prog->ucolor = pglGetUniformLocationARB( glprog, "uColor" ); + prog->ualpha = pglGetUniformLocationARB( glprog, "uAlphaTest" ); + prog->utex0 = pglGetUniformLocationARB( glprog, "uTex0" ); + prog->utex1 = pglGetUniformLocationARB( glprog, "uTex1" ); + prog->ufog = pglGetUniformLocationARB( glprog, "uFog" ); + + // these never change + if ( prog->utex0 >= 0 ) + pglUniform1iARB( prog->utex0, 0 ); + if ( prog->utex1 >= 0 ) + pglUniform1iARB( prog->utex1, 1 ); + + prog->glprog = glprog; + + gEngfuncs.Con_DPrintf( S_NOTE "GL2_GetProg(): Generated progs for 0x%04x\n", flags ); + + return prog; +} + +static gl2wrap_prog_t *GL2_SetProg( const GLuint flags ) +{ + gl2wrap_prog_t *prog = NULL; + + if ( flags && ( prog = GL2_GetProg( flags ) ) ) + { + if ( prog != gl2wrap.cur_prog ) + { + pglUseProgramObjectARB( prog->glprog ); + gl2wrap.uchanged = GL_TRUE; + } + if ( gl2wrap.uchanged ) + { + if ( prog->ualpha >= 0 ) + pglUniform1fARB( prog->ualpha, gl2wrap.alpharef ); + if ( prog->ucolor >= 0 ) + pglUniform4fvARB( prog->ucolor, 1, gl2wrap.color ); + if ( prog->ufog >= 0 ) + pglUniform4fvARB( prog->ufog, 1, gl2wrap.fog ); + gl2wrap.uchanged = GL_FALSE; + } + } + else + { + pglUseProgramObjectARB( 0 ); + } + + gl2wrap.cur_prog = prog; + return prog; +} + + +int GL2_ShimInit( void ) +{ + int i; + GLuint total, size; + static const GLuint precache_progs[] = { + 0x0001, // out = ucolor + 0x0005, // out = tex0 * ucolor + 0x0007, // out = tex0 * vcolor + 0x0015, // out = tex0 * ucolor + FEAT_ALPHA_TEST + 0x0021, // out = ucolor + FEAT_FOG + 0x0025, // out = tex0 * ucolor + FEAT_FOG + 0x0027, // out = tex0 * vcolor + FEAT_FOG + 0x0035, // out = tex0 * ucolor + FEAT_ALPHA_TEST + FEAT_FOG + }; + + if ( gl2wrap_init ) + return 0; + + memset( &gl2wrap, 0, sizeof( gl2wrap ) ); + + gl2wrap.color[0] = 1.f; + gl2wrap.color[1] = 1.f; + gl2wrap.color[2] = 1.f; + gl2wrap.color[3] = 1.f; + gl2wrap.uchanged = GL_TRUE; + + total = 0; + for ( i = 0; i < GL2_ATTR_MAX; ++i ) + { + size = GL2_MAX_VERTS * gl2wrap_attr_size[i] * sizeof( GLfloat ); + gl2wrap.attrbuf[i] = memalign( 0x100, size ); + total += size; + } + + GL2_ShimInstall(); + + gEngfuncs.Con_DPrintf( S_NOTE "GL2_ShimInit(): %u bytes allocated for vertex buffer\n", total ); + gEngfuncs.Con_DPrintf( S_NOTE "GL2_ShimInit(): Pre-generating %u progs...\n", sizeof( precache_progs ) / sizeof( *precache_progs ) ); + for ( i = 0; i < (int)( sizeof( precache_progs ) / sizeof( *precache_progs ) ); ++i ) + GL2_GetProg( precache_progs[i] ); + + gl2wrap_init = 1; + return 0; +} + +void GL2_ShimShutdown( void ) +{ + int i; + + if ( !gl2wrap_init ) + return; + + pglFinish(); + pglUseProgramObjectARB( 0 ); + + /* + // FIXME: this sometimes causes the game to block on glDeleteProgram for up to a minute + // but since this is only called on shutdown or game change, it should be fine to skip + for ( i = 0; i < MAX_PROGS; ++i ) + { + if ( gl2wrap.progs[i].flags ) + glDeleteProgram( gl2wrap.progs[i].glprog ); + } + */ + + for ( i = 0; i < GL2_ATTR_MAX; ++i ) + free( gl2wrap.attrbuf[i] ); + + memset( &gl2wrap, 0, sizeof( gl2wrap ) ); + + gl2wrap_init = 0; +} + +void GL2_ShimEndFrame( void ) +{ + gl2wrap.end = gl2wrap.begin = 0; +} + +void GL2_Begin( GLenum prim ) +{ + int i; + gl2wrap.prim = prim; + gl2wrap.begin = gl2wrap.end; + // pos always enabled + gl2wrap.cur_flags = 1 << GL2_ATTR_POS; + // disable all vertex attrib pointers + for ( i = 0; i < GL2_ATTR_MAX; ++i ) + pglDisableVertexAttribArrayARB( i ); +} + +void GL2_End( void ) +{ + int i; + gl2wrap_prog_t *prog; + GLuint flags = gl2wrap.cur_flags; + GLint count = gl2wrap.end - gl2wrap.begin; + + if ( !gl2wrap.prim || !count ) + goto _leave; // end without begin + + // enable alpha test and fog if needed + if ( alpha_test_state ) + flags |= 1 << GL2_FLAG_ALPHA_TEST; + if ( fogging ) + flags |= 1 << GL2_FLAG_FOG; + + prog = GL2_SetProg( flags ); + if ( !prog ) + { + gEngfuncs.Host_Error( "GL2_End(): Could not find program for flags 0x%04x!\n", flags ); + goto _leave; + } + + for ( i = 0; i < GL2_ATTR_MAX; ++i ) + { + if ( prog->attridx[i] >= 0 ) + { + pglEnableVertexAttribArrayARB( prog->attridx[i] ); + pglVertexAttribPointerARB( prog->attridx[i], gl2wrap_attr_size[i], GL_FLOAT, GL_FALSE, 0, gl2wrap.attrbuf[i] + gl2wrap_attr_size[i] * gl2wrap.begin ); + } + } + + pglDrawArrays( gl2wrap.prim, 0, count ); + +_leave: + gl2wrap.prim = GL_NONE; + gl2wrap.begin = gl2wrap.end; + gl2wrap.cur_flags = 0; +} + +void GL2_Vertex3f( GLfloat x, GLfloat y, GLfloat z ) +{ + GLfloat *p = gl2wrap.attrbuf[GL2_ATTR_POS] + gl2wrap.end * 3; + *p++ = x; + *p++ = y; + *p++ = z; + ++gl2wrap.end; + if ( gl2wrap.end >= GL2_MAX_VERTS ) + { + gEngfuncs.Con_DPrintf( S_ERROR "GL2_Vertex3f(): Vertex buffer overflow!\n" ); + gl2wrap.end = gl2wrap.begin = 0; + } +} + +void GL2_Vertex2f( GLfloat x, GLfloat y ) +{ + GL2_Vertex3f( x, y, 0.f ); +} + +void GL2_Vertex3fv( const GLfloat *v ) +{ + GL2_Vertex3f( v[0], v[1], v[2] ); +} + +void GL2_Color4f( GLfloat r, GLfloat g, GLfloat b, GLfloat a ) +{ + gl2wrap.color[0] = r; + gl2wrap.color[1] = g; + gl2wrap.color[2] = b; + gl2wrap.color[3] = a; + gl2wrap.uchanged = GL_TRUE; + if ( gl2wrap.prim ) + { + // HACK: enable color attribute if we're using color inside a Begin-End pair + GLfloat *p = gl2wrap.attrbuf[GL2_ATTR_COLOR] + gl2wrap.end * 4; + gl2wrap.cur_flags |= 1 << GL2_ATTR_COLOR; + *p++ = r; + *p++ = g; + *p++ = b; + *p++ = a; + } +} + +void GL2_Color3f( GLfloat r, GLfloat g, GLfloat b ) +{ + GL2_Color4f( r, g, b, 1.f ); +} + +void GL2_Color4ub( GLubyte r, GLubyte g, GLubyte b, GLubyte a ) +{ + GL2_Color4f( (GLfloat)r / 255.f, (GLfloat)g / 255.f, (GLfloat)b / 255.f, (GLfloat)a / 255.f ); +} + +void GL2_Color4ubv( const GLubyte *v ) +{ + GL2_Color4ub( v[0], v[1], v[2], v[3] ); +} + +void GL2_TexCoord2f( GLfloat u, GLfloat v ) +{ + // by spec glTexCoord always updates texunit 0 + GLfloat *p = gl2wrap.attrbuf[GL2_ATTR_TEXCOORD0] + gl2wrap.end * 2; + gl2wrap.cur_flags |= 1 << GL2_ATTR_TEXCOORD0; + *p++ = u; + *p++ = v; +} + +void GL2_MultiTexCoord2f( GLenum tex, GLfloat u, GLfloat v ) +{ + GLfloat *p; + // assume there can only be two + if ( tex == GL_TEXTURE0_ARB ) + { + p = gl2wrap.attrbuf[GL2_ATTR_TEXCOORD0] + gl2wrap.end * 2; + gl2wrap.cur_flags |= 1 << GL2_ATTR_TEXCOORD0; + } + else + { + p = gl2wrap.attrbuf[GL2_ATTR_TEXCOORD1] + gl2wrap.end * 2; + gl2wrap.cur_flags |= 1 << GL2_ATTR_TEXCOORD1; + } + *p++ = u; + *p++ = v; +} + +void GL2_Normal3fv( const GLfloat *v ) +{ + /* this does not seem to be necessary */ +} + +void GL2_ShadeModel( GLenum unused ) +{ + /* this doesn't do anything in vitaGL except spit errors in debug mode, so stub it out */ +} + +void GL2_AlphaFunc( GLenum mode, GLfloat ref ) +{ + gl2wrap.alpharef = ref; + gl2wrap.uchanged = GL_TRUE; + // mode is always GL_GREATER +} + +void GL2_Fogf( GLenum param, GLfloat val ) +{ + if ( param == GL_FOG_DENSITY ) + { + gl2wrap.fog[3] = val; + gl2wrap.uchanged = GL_TRUE; + } +} + +void GL2_Fogfv( GLenum param, const GLfloat *val ) +{ + if ( param == GL_FOG_COLOR ) + { + gl2wrap.fog[0] = val[0]; + gl2wrap.fog[1] = val[1]; + gl2wrap.fog[2] = val[2]; + gl2wrap.uchanged = GL_TRUE; + } +} + +void GL2_DrawBuffer( GLenum mode ) +{ + /* unsupported */ +} + +void GL2_Hint( GLenum hint, GLenum val ) +{ + /* none of the used hints are supported; stub to prevent errors */ +} + +void GL2_Enable( GLenum e ) +{ + if( e == GL_FOG ) + fogging = 1; + else if( e == GL_ALPHA_TEST ) + alpha_test_state = 1; + else rpglEnable(e); +} + +void GL2_Disable( GLenum e ) +{ + if( e == GL_FOG ) + fogging = 0; + else if( e == GL_ALPHA_TEST ) + alpha_test_state = 0; + else rpglDisable(e); +} + + +#define GL2_OVERRIDE_PTR( name ) \ +{ \ + pgl ## name = GL2_ ## name; \ +} + +void GL2_ShimInstall( void ) +{ + rpglEnable = pglEnable; + rpglDisable = pglDisable; + GL2_OVERRIDE_PTR( Vertex2f ) + GL2_OVERRIDE_PTR( Vertex3f ) + GL2_OVERRIDE_PTR( Vertex3fv ) + GL2_OVERRIDE_PTR( Color3f ) + GL2_OVERRIDE_PTR( Color4f ) + GL2_OVERRIDE_PTR( Color4ub ) + GL2_OVERRIDE_PTR( Color4ubv ) + GL2_OVERRIDE_PTR( Normal3fv ) + GL2_OVERRIDE_PTR( TexCoord2f ) + GL2_OVERRIDE_PTR( MultiTexCoord2f ) + GL2_OVERRIDE_PTR( ShadeModel ) + GL2_OVERRIDE_PTR( DrawBuffer ) + GL2_OVERRIDE_PTR( AlphaFunc ) + GL2_OVERRIDE_PTR( Fogf ) + GL2_OVERRIDE_PTR( Fogfv ) + GL2_OVERRIDE_PTR( Hint ) + GL2_OVERRIDE_PTR( Begin ) + GL2_OVERRIDE_PTR( End ) + GL2_OVERRIDE_PTR( Enable ) + GL2_OVERRIDE_PTR( Disable ) +} diff --git a/ref/gl/gl2_shim/gl2_shim.h b/ref/gl/gl2_shim/gl2_shim.h new file mode 100644 index 00000000..cfdc9e54 --- /dev/null +++ b/ref/gl/gl2_shim/gl2_shim.h @@ -0,0 +1,24 @@ +/* +vgl_shim.h - vitaGL custom immediate mode shim +Copyright (C) 2023 fgsfds + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +*/ + +#pragma once + +// max verts in a single frame +#define GL2_MAX_VERTS 32768 + +int GL2_ShimInit( void ); +void GL2_ShimInstall( void ); +void GL2_ShimShutdown( void ); +void GL2_ShimEndFrame( void ); diff --git a/ref/gl/gl2_shim/vertex.glsl.inc b/ref/gl/gl2_shim/vertex.glsl.inc new file mode 100644 index 00000000..093a5758 --- /dev/null +++ b/ref/gl/gl2_shim/vertex.glsl.inc @@ -0,0 +1,50 @@ +R"( + +#define layout(x) +#define in attribute +#define out varying + +layout(location = 0) in vec3 inPosition; +#if ATTR_COLOR +layout(location = 1) in vec4 inColor; +#endif +#if ATTR_NORMAL +layout(location = 2) in vec3 inNormal; +#endif +#if ATTR_TEXCOORD0 +layout(location = 3) in vec2 inTexCoord0; +#endif +#if ATTR_TEXCOORD1 +layout(location = 4) in vec2 inTexCoord1; +#endif + +#if ATTR_COLOR +out vec4 vColor; +#endif +#if ATTR_TEXCOORD0 +out vec2 vTexCoord0; +#endif +#if ATTR_TEXCOORD1 +out vec2 vTexCoord0; +#endif +#if ATTR_NORMAL +out vec3 vNormal; +#endif + +void main() +{ + gl_Position = gl_ModelViewProjectionMatrix * vec4(inPosition,1.0f); +#if ATTR_COLOR + vColor = inColor; +#endif +#if ATTR_NORMAL + vNormal = inNormal; +#endif +#if ATTR_TEXCOORD0 + vTexCoord0 = inTexCoord0; +#endif +#if ATTR_TEXCOORD1 + vTexCoord1 = inTexCoord1; +#endif +} +)" diff --git a/ref/gl/gl2_shim/wscript b/ref/gl/gl2_shim/wscript new file mode 100644 index 00000000..b34d7da2 --- /dev/null +++ b/ref/gl/gl2_shim/wscript @@ -0,0 +1,25 @@ +#! /usr/bin/env python +# encoding: utf-8 + +import os + +def options(opt): + pass + +def configure(conf): + conf.define('REF_DLL', 1) + +def build(bld): + source = bld.path.ant_glob( [ '*.c' ] ) + includes = [ '.' ] + libs = [ 'engine_includes', 'sdk_includes' ] + bld.env.LDFLAGS += ['-fPIC'] + bld.env.CFLAGS += ['-fPIC'] + bld.stlib( + source = source, + target = 'gl2_shim', + features = 'c', + includes = includes, + use = libs, + subsystem = bld.env.MSVC_SUBSYSTEM + ) diff --git a/ref/gl/gl_local.h b/ref/gl/gl_local.h index a66c1f41..c05b78a4 100644 --- a/ref/gl/gl_local.h +++ b/ref/gl/gl_local.h @@ -40,6 +40,9 @@ int VGL_ShimInit( void ); void VGL_ShimShutdown( void ); void VGL_ShimEndFrame( void ); #endif +#if !defined(XASH_GLES) && !defined(XASH_GL_STATIC) +#include "gl2_shim/gl2_shim.h" +#endif #ifndef offsetof #ifdef __GNUC__ @@ -617,6 +620,7 @@ enum GL_DRAW_RANGEELEMENTS_EXT, GL_TEXTURE_MULTISAMPLE, GL_ARB_TEXTURE_COMPRESSION_BPTC, + R_SHADER_OBJECTS_EXT, GL_EXTCOUNT, // must be last }; diff --git a/ref/gl/gl_opengl.c b/ref/gl/gl_opengl.c index dcae951d..2034a120 100644 --- a/ref/gl/gl_opengl.c +++ b/ref/gl/gl_opengl.c @@ -247,6 +247,64 @@ static dllfunc_t drawrangeelementsextfuncs[] = { NULL, NULL } }; + +static dllfunc_t shaderobjectsfuncs[] = +{ + { GL_CALL( glDeleteObjectARB ) }, + { GL_CALL( glGetHandleARB ) }, + { GL_CALL( glDetachObjectARB ) }, + { GL_CALL( glCreateShaderObjectARB ) }, + { GL_CALL( glShaderSourceARB ) }, + { GL_CALL( glCompileShaderARB ) }, + { GL_CALL( glCreateProgramObjectARB ) }, + { GL_CALL( glAttachObjectARB ) }, + { GL_CALL( glLinkProgramARB ) }, + { GL_CALL( glUseProgramObjectARB ) }, + { GL_CALL( glValidateProgramARB ) }, + { GL_CALL( glUniform1fARB ) }, + { GL_CALL( glUniform2fARB ) }, + { GL_CALL( glUniform3fARB ) }, + { GL_CALL( glUniform4fARB ) }, + { GL_CALL( glUniform1iARB ) }, + { GL_CALL( glUniform2iARB ) }, + { GL_CALL( glUniform3iARB ) }, + { GL_CALL( glUniform4iARB ) }, + { GL_CALL( glUniform1fvARB ) }, + { GL_CALL( glUniform2fvARB ) }, + { GL_CALL( glUniform3fvARB ) }, + { GL_CALL( glUniform4fvARB ) }, + { GL_CALL( glUniform1ivARB ) }, + { GL_CALL( glUniform2ivARB ) }, + { GL_CALL( glUniform3ivARB ) }, + { GL_CALL( glUniform4ivARB ) }, + { GL_CALL( glUniformMatrix2fvARB ) }, + { GL_CALL( glUniformMatrix3fvARB ) }, + { GL_CALL( glUniformMatrix4fvARB ) }, + { GL_CALL( glGetObjectParameterfvARB ) }, + { GL_CALL( glGetObjectParameterivARB ) }, + { GL_CALL( glGetInfoLogARB ) }, + { GL_CALL( glGetAttachedObjectsARB ) }, + { GL_CALL( glGetUniformLocationARB ) }, + { GL_CALL( glGetActiveUniformARB ) }, + { GL_CALL( glGetUniformfvARB ) }, + { GL_CALL( glGetUniformivARB ) }, + { GL_CALL( glGetShaderSourceARB ) }, + { GL_CALL( glVertexAttribPointerARB ) }, + { GL_CALL( glEnableVertexAttribArrayARB ) }, + { GL_CALL( glDisableVertexAttribArrayARB ) }, + { GL_CALL( glBindAttribLocationARB ) }, + { GL_CALL( glGetActiveAttribARB ) }, + { GL_CALL( glGetAttribLocationARB ) }, + { GL_CALL( glVertexAttrib2fARB ) }, + { GL_CALL( glVertexAttrib2fvARB ) }, +// { GL_CALL( glVertexAttrib3fv ) }, +// { GL_CALL( glVertexAttrib4f ) }, +// { GL_CALL( glVertexAttrib4fv ) }, +// { GL_CALL( glVertexAttrib4ubv ) }, +{ NULL, NULL } +}; + + /* ======================== DebugCallback @@ -703,6 +761,7 @@ void GL_InitExtensionsBigGL( void ) GL_CheckExtension( "GL_ARB_vertex_buffer_object", vbofuncs, "gl_vertex_buffer_object", GL_ARB_VERTEX_BUFFER_OBJECT_EXT ); GL_CheckExtension( "GL_ARB_texture_multisample", multisampletexfuncs, "gl_texture_multisample", GL_TEXTURE_MULTISAMPLE ); GL_CheckExtension( "GL_ARB_texture_compression_bptc", NULL, "gl_texture_bptc_compression", GL_ARB_TEXTURE_COMPRESSION_BPTC ); + GL_CheckExtension( "GL_ARB_shader_objects", shaderobjectsfuncs, "gl_shaderobjects", R_SHADER_OBJECTS_EXT ); if( GL_CheckExtension( "GL_ARB_shading_language_100", NULL, NULL, GL_SHADER_GLSL100_EXT )) { pglGetIntegerv( GL_MAX_TEXTURE_COORDS_ARB, &glConfig.max_texture_coords ); @@ -747,6 +806,10 @@ void GL_InitExtensionsBigGL( void ) // init our immediate mode override VGL_ShimInit(); #endif +#if !defined(XASH_GLES) && !defined(XASH_GL_STATIC) + if( gEngfuncs.Sys_CheckParm("-gl2shim") ) + GL2_ShimInit(); +#endif } #endif @@ -822,6 +885,9 @@ void GL_ClearExtensions( void ) // deinit our immediate mode override VGL_ShimShutdown(); #endif +#if !defined(XASH_GLES) && !defined(XASH_GL_STATIC) + GL2_ShimShutdown(); +#endif } //======================================================================= diff --git a/ref/gl/gl_rmain.c b/ref/gl/gl_rmain.c index b57d9ea5..4ba32a13 100644 --- a/ref/gl/gl_rmain.c +++ b/ref/gl/gl_rmain.c @@ -20,6 +20,7 @@ GNU General Public License for more details. #include "particledef.h" #include "entity_types.h" + #define IsLiquidContents( cnt ) ( cnt == CONTENTS_WATER || cnt == CONTENTS_SLIME || cnt == CONTENTS_LAVA ) float gldepthmin, gldepthmax; @@ -1126,6 +1127,9 @@ void R_EndFrame( void ) { #if XASH_PSVITA VGL_ShimEndFrame(); +#endif +#if !defined(XASH_GLES) && !defined(XASH_GL_STATIC) + GL2_ShimEndFrame(); #endif // flush any remaining 2D bits R_Set2DMode( false ); diff --git a/ref/gl/wscript b/ref/gl/wscript index 16266c9e..de5f5281 100644 --- a/ref/gl/wscript +++ b/ref/gl/wscript @@ -37,6 +37,7 @@ def build(bld): if bld.env.DEST_OS == 'psvita': libs += [ 'sdk_includes', 'vgl_shim' ] else: + libs += [ 'gl2_shim' ] libs += [ 'public', 'M' ] source = bld.path.ant_glob(['*.c']) diff --git a/wscript b/wscript index edb43173..057dce42 100644 --- a/wscript +++ b/wscript @@ -90,6 +90,8 @@ SUBDIRS = [ # enabled on PSVita only Subproject('ref/gl/vgl_shim', lambda x: x.env.DEST_OS == 'psvita'), + Subproject('ref/gl/gl2_shim', lambda x: not x.env.DEDICATED and x.env.GL), + ] REFDLLS = [