mirror of
https://github.com/FWGS/xash3d-fwgs
synced 2024-12-22 17:01:14 +01:00
ref: gl: add immediate mode shim for psvita
This commit is contained in:
parent
9cf6e421cb
commit
5a3e3b3977
@ -25,22 +25,12 @@ GNU General Public License for more details.
|
||||
|
||||
#define DATA_PATH "data/xash3d"
|
||||
|
||||
// 200MB libc heap, 512K main thread stack, 32MB for loading game DLLs, 8MB vertex pool
|
||||
// 200MB libc heap, 512K main thread stack, 40MB for loading game DLLs
|
||||
// the rest goes to vitaGL
|
||||
SceUInt32 sceUserMainThreadStackSize = 512 * 1024;
|
||||
unsigned int _pthread_stack_default_user = 512 * 1024;
|
||||
unsigned int _newlib_heap_size_user = 200 * 1024 * 1024;
|
||||
#define VGL_MEM_THRESHOLD ( 40 * 1024 * 1024 )
|
||||
#define VGL_VERTEX_POOL_SIZE ( 4 * 1024 * 1024 )
|
||||
|
||||
/* HACK: stubs for GL functions that are missing from vitaGL */
|
||||
|
||||
static void glDrawBuffer( GLenum which )
|
||||
{
|
||||
/* nada */
|
||||
}
|
||||
|
||||
/* end of GL stubs*/
|
||||
|
||||
/* HACKHACK: force-export stuff required by the dynamic libs */
|
||||
|
||||
@ -73,7 +63,7 @@ static const vrtld_export_t aux_exports[] =
|
||||
VRTLD_EXPORT_SYMBOL( strchrnul ),
|
||||
VRTLD_EXPORT_SYMBOL( rand ),
|
||||
VRTLD_EXPORT_SYMBOL( srand ),
|
||||
VRTLD_EXPORT_SYMBOL( glDrawBuffer ),
|
||||
VRTLD_EXPORT_SYMBOL( sceGxmMapMemory ), // needed by vgl_shim
|
||||
VRTLD_EXPORT( "dlopen", vrtld_dlopen ),
|
||||
VRTLD_EXPORT( "dlclose", vrtld_dlclose ),
|
||||
VRTLD_EXPORT( "dlsym", vrtld_dlsym ),
|
||||
@ -112,11 +102,11 @@ void PSVita_Init( void )
|
||||
Sys_Error( "Could not init vrtld: %s\n", vrtld_dlerror( ) );
|
||||
}
|
||||
|
||||
// init vitaGL with some memory budget for immediate mode vertices
|
||||
// init vitaGL, leaving some memory for DLL mapping
|
||||
// TODO: we don't need to do this for ref_soft
|
||||
vglUseVram( GL_TRUE );
|
||||
vglUseExtraMem( GL_TRUE );
|
||||
vglInitExtended( VGL_VERTEX_POOL_SIZE, 960, 544, VGL_MEM_THRESHOLD, 0 );
|
||||
vglInitExtended( 0, 960, 544, VGL_MEM_THRESHOLD, 0 );
|
||||
}
|
||||
|
||||
void PSVita_Shutdown( void )
|
||||
|
@ -35,6 +35,12 @@ GNU General Public License for more details.
|
||||
#include "gl_export.h"
|
||||
#include "wadfile.h"
|
||||
|
||||
#if XASH_PSVITA
|
||||
int VGL_ShimInit( void );
|
||||
void VGL_ShimShutdown( void );
|
||||
void VGL_ShimEndFrame( void );
|
||||
#endif
|
||||
|
||||
#ifndef offsetof
|
||||
#ifdef __GNUC__
|
||||
#define offsetof(s,m) __builtin_offsetof(s,m)
|
||||
|
@ -755,6 +755,8 @@ void GL_InitExtensionsBigGL( void )
|
||||
#if XASH_PSVITA
|
||||
// NPOT textures are actually supported, but the extension is not listed in GL_EXTENSIONS
|
||||
GL_SetExtension( GL_ARB_TEXTURE_NPOT_EXT, true );
|
||||
// init our immediate mode override
|
||||
VGL_ShimInit();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@ -824,6 +826,10 @@ void GL_ClearExtensions( void )
|
||||
// now all extensions are disabled
|
||||
memset( glConfig.extension, 0, sizeof( glConfig.extension ));
|
||||
glw_state.initialized = false;
|
||||
#if XASH_PSVITA
|
||||
// deinit our immediate mode override
|
||||
VGL_ShimShutdown();
|
||||
#endif
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
@ -1124,6 +1124,9 @@ R_EndFrame
|
||||
*/
|
||||
void R_EndFrame( void )
|
||||
{
|
||||
#if XASH_PSVITA
|
||||
VGL_ShimEndFrame();
|
||||
#endif
|
||||
// flush any remaining 2D bits
|
||||
R_Set2DMode( false );
|
||||
gEngfuncs.GL_SwapBuffers();
|
||||
|
@ -25,6 +25,14 @@ GNU General Public License for more details.
|
||||
#define EVENT_CLIENT 5000 // less than this value it's a server-side studio events
|
||||
#define MAX_LOCALLIGHTS 4
|
||||
|
||||
#if XASH_PSVITA
|
||||
// save some address space by decreasing .bss size
|
||||
// we're not gonna be using the array renderer anyway
|
||||
#define MAXARRAYVERTS 1
|
||||
#else
|
||||
#define MAXARRAYVERTS MAXSTUDIOVERTS
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[MAX_OSPATH];
|
||||
@ -112,10 +120,10 @@ typedef struct
|
||||
player_model_t player_models[MAX_CLIENTS];
|
||||
|
||||
// drawelements renderer
|
||||
vec3_t arrayverts[MAXSTUDIOVERTS];
|
||||
vec2_t arraycoord[MAXSTUDIOVERTS];
|
||||
unsigned short arrayelems[MAXSTUDIOVERTS*6];
|
||||
GLubyte arraycolor[MAXSTUDIOVERTS][4];
|
||||
vec3_t arrayverts[MAXARRAYVERTS];
|
||||
vec2_t arraycoord[MAXARRAYVERTS];
|
||||
unsigned short arrayelems[MAXARRAYVERTS*6];
|
||||
GLubyte arraycolor[MAXARRAYVERTS][4];
|
||||
uint numverts;
|
||||
uint numelems;
|
||||
} studio_draw_state_t;
|
||||
@ -150,6 +158,11 @@ void R_StudioInit( void )
|
||||
r_studio_sort_textures = gEngfuncs.Cvar_Get( "r_studio_sort_textures", "0", FCVAR_GLCONFIG, "change draw order for additive meshes" );
|
||||
r_studio_drawelements = gEngfuncs.Cvar_Get( "r_studio_drawelements", "1", FCVAR_GLCONFIG, "use glDrawElements for studiomodels" );
|
||||
|
||||
#if XASH_PSVITA
|
||||
// don't do the same array-building work twice since that's what our FFP shim does anyway
|
||||
gEngfuncs.Cvar_SetValue( "r_studio_drawelements", 0 );
|
||||
#endif
|
||||
|
||||
Matrix3x4_LoadIdentity( g_studio.rotationmatrix );
|
||||
|
||||
// g-cont. cvar disabled by Valve
|
||||
|
@ -35,7 +35,7 @@ def build(bld):
|
||||
libs = [ 'engine_includes' ]
|
||||
# on PSVita do not link any libraries that are already in the main executable, but add the includes target
|
||||
if bld.env.DEST_OS == 'psvita':
|
||||
libs += [ 'sdk_includes' ]
|
||||
libs += [ 'sdk_includes', 'vgl_shim' ]
|
||||
else:
|
||||
libs += [ 'public', 'M' ]
|
||||
|
||||
|
46
utils/vgl_shim/vgl_shaders/fragment.cg.inc
Normal file
46
utils/vgl_shim/vgl_shaders/fragment.cg.inc
Normal file
@ -0,0 +1,46 @@
|
||||
R""(
|
||||
|
||||
#if ATTR_TEXCOORD0
|
||||
uniform sampler2D uTex0 : TEXUNIT0;
|
||||
#endif
|
||||
#if ATTR_TEXCOORD1
|
||||
uniform sampler2D uTex1 : TEXUNIT1;
|
||||
#endif
|
||||
#if FEAT_ALPHA_TEST
|
||||
uniform float uAlphaTest;
|
||||
#endif
|
||||
|
||||
float4 main(
|
||||
uniform float4 uColor
|
||||
#if ATTR_COLOR
|
||||
, float4 vColor : COLOR
|
||||
#endif
|
||||
#if ATTR_TEXCOORD0
|
||||
, float2 vTexCoord0 : TEXCOORD0
|
||||
#endif
|
||||
#if ATTR_TEXCOORD1
|
||||
, float2 vTexCoord1 : TEXCOORD1
|
||||
#endif
|
||||
#if ATTR_NORMAL
|
||||
, float3 vNormal : TEXCOORD2
|
||||
#endif
|
||||
) {
|
||||
#if ATTR_COLOR
|
||||
float4 c = vColor;
|
||||
#else
|
||||
float4 c = uColor;
|
||||
#endif
|
||||
#if ATTR_TEXCOORD0
|
||||
c *= tex2D(uTex0, vTexCoord0);
|
||||
#endif
|
||||
#if ATTR_TEXCOORD1
|
||||
c *= tex2D(uTex1, vTexCoord1);
|
||||
#endif
|
||||
#if FEAT_ALPHA_TEST
|
||||
if (c.a <= uAlphaTest)
|
||||
discard;
|
||||
#endif
|
||||
return c;
|
||||
}
|
||||
|
||||
)""
|
49
utils/vgl_shim/vgl_shaders/vertex.cg.inc
Normal file
49
utils/vgl_shim/vgl_shaders/vertex.cg.inc
Normal file
@ -0,0 +1,49 @@
|
||||
R""(
|
||||
|
||||
// has to be called this for VGL to fill it in automatically
|
||||
uniform float4x4 gl_ModelViewProjectionMatrix;
|
||||
|
||||
void main(
|
||||
float3 inPosition
|
||||
#if ATTR_COLOR
|
||||
, float4 inColor
|
||||
#endif
|
||||
#if ATTR_NORMAL
|
||||
, float3 inNormal
|
||||
#endif
|
||||
#if ATTR_TEXCOORD0
|
||||
, float2 inTexCoord0
|
||||
#endif
|
||||
#if ATTR_TEXCOORD1
|
||||
, float2 inTexCoord1
|
||||
#endif
|
||||
, float4 out vPosition : POSITION
|
||||
#if ATTR_COLOR
|
||||
, float4 out vColor : COLOR
|
||||
#endif
|
||||
#if ATTR_TEXCOORD0
|
||||
, float2 out vTexCoord0 : TEXCOORD0
|
||||
#endif
|
||||
#if ATTR_TEXCOORD1
|
||||
, float2 out vTexCoord1 : TEXCOORD1
|
||||
#endif
|
||||
#if ATTR_NORMAL
|
||||
, float3 out vNormal : TEXCOORD2
|
||||
#endif
|
||||
) {
|
||||
vPosition = mul(gl_ModelViewProjectionMatrix, float4(inPosition, 1.f));
|
||||
#if ATTR_COLOR
|
||||
vColor = inColor;
|
||||
#endif
|
||||
#if ATTR_NORMAL
|
||||
vNormal = inNormal;
|
||||
#endif
|
||||
#if ATTR_TEXCOORD0
|
||||
vTexCoord0 = inTexCoord0;
|
||||
#endif
|
||||
#if ATTR_TEXCOORD1
|
||||
vTexCoord1 = inTexCoord1;
|
||||
#endif
|
||||
}
|
||||
|
||||
)""
|
532
utils/vgl_shim/vgl_shim.c
Normal file
532
utils/vgl_shim/vgl_shim.c
Normal file
@ -0,0 +1,532 @@
|
||||
/*
|
||||
vgl_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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <vitaGL.h>
|
||||
|
||||
#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 "vgl_shim.h"
|
||||
|
||||
#define MAX_SHADERLEN 4096
|
||||
#define MAX_PROGS 32
|
||||
|
||||
extern ref_api_t gEngfuncs;
|
||||
|
||||
enum vgl_attrib_e
|
||||
{
|
||||
VGL_ATTR_POS = 0, // 1
|
||||
VGL_ATTR_COLOR = 1, // 2
|
||||
VGL_ATTR_TEXCOORD0 = 2, // 4
|
||||
VGL_ATTR_TEXCOORD1 = 3, // 8
|
||||
VGL_ATTR_NORMAL = 4, // 16
|
||||
VGL_ATTR_MAX
|
||||
};
|
||||
|
||||
// continuation of previous enum
|
||||
enum vgl_flag_e
|
||||
{
|
||||
VGL_FLAG_ALPHA_TEST = VGL_ATTR_MAX,
|
||||
VGL_FLAG_MAX
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GLuint flags;
|
||||
GLint attridx[VGL_ATTR_MAX];
|
||||
GLuint glprog;
|
||||
GLint ucolor;
|
||||
GLint ualpha;
|
||||
GLint utex0;
|
||||
GLint utex1;
|
||||
} vgl_prog_t;
|
||||
|
||||
static const char *vgl_vert_src =
|
||||
#include "vgl_shaders/vertex.cg.inc"
|
||||
;
|
||||
|
||||
static const char *vgl_frag_src =
|
||||
#include "vgl_shaders/fragment.cg.inc"
|
||||
;
|
||||
|
||||
static int vgl_init = 0;
|
||||
|
||||
static struct
|
||||
{
|
||||
GLfloat *attrbuf[VGL_ATTR_MAX];
|
||||
GLuint cur_flags;
|
||||
GLint begin;
|
||||
GLint end;
|
||||
GLenum prim;
|
||||
GLfloat color[4];
|
||||
GLfloat alpharef;
|
||||
vgl_prog_t progs[MAX_PROGS];
|
||||
vgl_prog_t *cur_prog;
|
||||
GLboolean uchanged;
|
||||
} vgl;
|
||||
|
||||
static const int vgl_attr_size[VGL_ATTR_MAX] = { 3, 4, 2, 2, 3 };
|
||||
|
||||
static const char *vgl_flag_name[VGL_FLAG_MAX] =
|
||||
{
|
||||
"ATTR_POSITION",
|
||||
"ATTR_COLOR",
|
||||
"ATTR_TEXCOORD0",
|
||||
"ATTR_TEXCOORD1",
|
||||
"ATTR_NORMAL",
|
||||
"FEAT_ALPHA_TEST",
|
||||
};
|
||||
|
||||
static const char *vgl_attr_name[VGL_ATTR_MAX] =
|
||||
{
|
||||
"inPosition",
|
||||
"inColor",
|
||||
"inTexCoord0",
|
||||
"inTexCoord1",
|
||||
"inNormal",
|
||||
};
|
||||
|
||||
// HACK: borrow alpha test flag from internal vitaGL state
|
||||
extern GLboolean alpha_test_state;
|
||||
|
||||
static GLuint VGL_GenerateShader( const vgl_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[1] = 0;
|
||||
|
||||
for ( i = 0; i < VGL_FLAG_MAX; ++i )
|
||||
{
|
||||
snprintf( tmp, sizeof( tmp ), "#define %s %d\n", vgl_flag_name[i], prog->flags & ( 1 << i ) );
|
||||
strncat( shader, tmp, MAX_SHADERLEN );
|
||||
}
|
||||
|
||||
if ( type == GL_FRAGMENT_SHADER )
|
||||
strncat( shader, vgl_frag_src, MAX_SHADERLEN );
|
||||
else
|
||||
strncat( shader, vgl_vert_src, MAX_SHADERLEN );
|
||||
|
||||
id = glCreateShader( type );
|
||||
len = strlen( shader );
|
||||
glShaderSource( id, 1, (const void *)&shader, &len );
|
||||
glCompileShader( id );
|
||||
glGetShaderiv( id, GL_COMPILE_STATUS, &status );
|
||||
if ( status == GL_FALSE )
|
||||
{
|
||||
gEngfuncs.Con_Reportf( S_ERROR "VGL_GenerateShader( 0x%04x, 0x%x ): compile failed:\n", prog->flags, type );
|
||||
gEngfuncs.Con_Printf( "Shader text:\n%s\n\n", shader );
|
||||
glDeleteShader( id );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
static vgl_prog_t *VGL_GetProg( const GLuint flags )
|
||||
{
|
||||
int i, loc, status;
|
||||
GLuint vp, fp, glprog;
|
||||
vgl_prog_t *prog;
|
||||
|
||||
// try to find existing prog matching this feature set
|
||||
|
||||
if ( vgl.cur_prog && vgl.cur_prog->flags == flags )
|
||||
return vgl.cur_prog;
|
||||
|
||||
for ( i = 0; i < MAX_PROGS; ++i )
|
||||
{
|
||||
if ( vgl.progs[i].flags == flags )
|
||||
return &vgl.progs[i];
|
||||
else if ( vgl.progs[i].flags == 0 )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( i == MAX_PROGS )
|
||||
{
|
||||
gEngfuncs.Host_Error( "VGL_GetProg(): Ran out of program slots for 0x%04x\n", flags );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// new prog; generate shaders
|
||||
|
||||
gEngfuncs.Con_DPrintf( S_NOTE "VGL_GetProg(): Generating progs for 0x%04x\n", flags );
|
||||
prog = &vgl.progs[i];
|
||||
prog->flags = flags;
|
||||
|
||||
vp = VGL_GenerateShader( prog, GL_VERTEX_SHADER );
|
||||
fp = VGL_GenerateShader( prog, GL_FRAGMENT_SHADER );
|
||||
if ( !vp || !fp )
|
||||
{
|
||||
prog->flags = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
glprog = glCreateProgram();
|
||||
glAttachShader( glprog, vp );
|
||||
glAttachShader( glprog, fp );
|
||||
|
||||
loc = 0;
|
||||
for ( i = 0; i < VGL_ATTR_MAX; ++i )
|
||||
{
|
||||
if ( flags & ( 1 << i ) )
|
||||
{
|
||||
prog->attridx[i] = loc;
|
||||
glBindAttribLocation( glprog, loc++, vgl_attr_name[i] );
|
||||
}
|
||||
else
|
||||
{
|
||||
prog->attridx[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
glLinkProgram( glprog );
|
||||
glDeleteShader( vp );
|
||||
glDeleteShader( fp );
|
||||
|
||||
glGetProgramiv( glprog, GL_LINK_STATUS, &status );
|
||||
if ( status == GL_FALSE )
|
||||
{
|
||||
gEngfuncs.Con_Reportf( S_ERROR "VGL_GetProg( 0x%04x ): link failed!\n", prog->flags );
|
||||
prog->flags = 0;
|
||||
glDeleteProgram( glprog );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
prog->ucolor = glGetUniformLocation( glprog, "uColor" );
|
||||
prog->ualpha = glGetUniformLocation( glprog, "uAlphaTest" );
|
||||
prog->utex0 = glGetUniformLocation( glprog, "uTex0" );
|
||||
prog->utex1 = glGetUniformLocation( glprog, "uTex1" );
|
||||
|
||||
// these never change
|
||||
if ( prog->utex0 >= 0 )
|
||||
glUniform1i( prog->utex0, 0 );
|
||||
if ( prog->utex1 >= 0 )
|
||||
glUniform1i( prog->utex1, 1 );
|
||||
|
||||
prog->glprog = glprog;
|
||||
|
||||
gEngfuncs.Con_DPrintf( S_NOTE "VGL_GetProg(): Generated progs for 0x%04x: glprog=%u ucolor=%d ualpha=%d\n", flags, glprog, prog->ucolor, prog->ualpha );
|
||||
|
||||
return prog;
|
||||
}
|
||||
|
||||
static vgl_prog_t *VGL_SetProg( const GLuint flags )
|
||||
{
|
||||
vgl_prog_t *prog = NULL;
|
||||
|
||||
if ( flags && ( prog = VGL_GetProg( flags ) ) )
|
||||
{
|
||||
if ( prog != vgl.cur_prog )
|
||||
{
|
||||
glUseProgram( prog->glprog );
|
||||
vgl.uchanged = GL_TRUE;
|
||||
}
|
||||
if ( vgl.uchanged )
|
||||
{
|
||||
if ( prog->ualpha >= 0 )
|
||||
glUniform1f( prog->ualpha, vgl.alpharef );
|
||||
if ( prog->ucolor >= 0 )
|
||||
glUniform4fv( prog->ucolor, 1, vgl.color );
|
||||
vgl.uchanged = GL_FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glUseProgram( 0 );
|
||||
}
|
||||
|
||||
vgl.cur_prog = prog;
|
||||
return prog;
|
||||
}
|
||||
|
||||
int VGL_ShimInit( void )
|
||||
{
|
||||
int i;
|
||||
GLuint total, size;
|
||||
|
||||
if ( vgl_init )
|
||||
return 0;
|
||||
|
||||
memset( &vgl, 0, sizeof( vgl ) );
|
||||
|
||||
vgl.color[0] = 1.f;
|
||||
vgl.color[1] = 1.f;
|
||||
vgl.color[2] = 1.f;
|
||||
vgl.color[3] = 1.f;
|
||||
vgl.uchanged = GL_TRUE;
|
||||
|
||||
total = 0;
|
||||
for ( i = 0; i < VGL_ATTR_MAX; ++i )
|
||||
{
|
||||
size = VGL_MAX_VERTS * vgl_attr_size[i] * sizeof( GLfloat );
|
||||
vgl.attrbuf[i] = memalign( 0x100, size );
|
||||
total += size;
|
||||
}
|
||||
|
||||
VGL_ShimInstall();
|
||||
|
||||
gEngfuncs.Con_DPrintf( S_NOTE "VGL_ShimInit(): %u bytes allocated for vertex buffer\n", total );
|
||||
|
||||
vgl_init = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void VGL_ShimShutdown( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( !vgl_init )
|
||||
return;
|
||||
|
||||
glFinish();
|
||||
glUseProgram( 0 );
|
||||
|
||||
for ( i = 0; i < MAX_PROGS; ++i )
|
||||
{
|
||||
if ( vgl.progs[i].flags )
|
||||
glDeleteProgram( vgl.progs[i].glprog );
|
||||
}
|
||||
|
||||
for ( i = 0; i < VGL_ATTR_MAX; ++i )
|
||||
free( vgl.attrbuf[i] );
|
||||
|
||||
memset( &vgl, 0, sizeof( vgl ) );
|
||||
|
||||
vgl_init = 0;
|
||||
}
|
||||
|
||||
void VGL_ShimEndFrame( void )
|
||||
{
|
||||
vgl.end = vgl.begin = 0;
|
||||
}
|
||||
|
||||
void VGL_Begin( GLenum prim )
|
||||
{
|
||||
int i;
|
||||
vgl.prim = prim;
|
||||
vgl.begin = vgl.end;
|
||||
// pos always enabled
|
||||
vgl.cur_flags = 1 << VGL_ATTR_POS;
|
||||
// disable all vertex attrib pointers
|
||||
for ( i = 0; i < VGL_ATTR_MAX; ++i )
|
||||
glDisableVertexAttribArray( i );
|
||||
}
|
||||
|
||||
void VGL_End( void )
|
||||
{
|
||||
int i;
|
||||
vgl_prog_t *prog;
|
||||
GLuint flags = vgl.cur_flags;
|
||||
GLint count = vgl.end - vgl.begin;
|
||||
|
||||
if ( !vgl.prim || !count )
|
||||
goto _leave; // end without begin
|
||||
|
||||
if ( vgl.end > VGL_MAX_VERTS )
|
||||
{
|
||||
gEngfuncs.Con_Reportf( S_ERROR "VGL_End(): Ran out of vertex space (%d overhead)\n", vgl.end - VGL_MAX_VERTS );
|
||||
vgl.end = 0;
|
||||
goto _leave;
|
||||
}
|
||||
|
||||
// enable alpha test if needed
|
||||
if ( alpha_test_state )
|
||||
flags |= 1 << VGL_FLAG_ALPHA_TEST;
|
||||
|
||||
prog = VGL_SetProg( flags );
|
||||
if ( !prog )
|
||||
{
|
||||
gEngfuncs.Host_Error( "VGL_End(): Could not find program for flags 0x%04x!\n", flags );
|
||||
goto _leave;
|
||||
}
|
||||
|
||||
for ( i = 0; i < VGL_ATTR_MAX; ++i )
|
||||
{
|
||||
if ( prog->attridx[i] >= 0 )
|
||||
{
|
||||
glEnableVertexAttribArray( prog->attridx[i] );
|
||||
glVertexAttribPointer( prog->attridx[i], vgl_attr_size[i], GL_FLOAT, GL_FALSE, 0, vgl.attrbuf[i] + vgl_attr_size[i] * vgl.begin );
|
||||
}
|
||||
}
|
||||
|
||||
glDrawArrays( vgl.prim, 0, count );
|
||||
|
||||
_leave:
|
||||
vgl.prim = GL_NONE;
|
||||
vgl.begin = vgl.end;
|
||||
vgl.cur_flags = 0;
|
||||
}
|
||||
|
||||
void VGL_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
|
||||
{
|
||||
GLfloat *p = vgl.attrbuf[VGL_ATTR_POS] + vgl.end * 3;
|
||||
*p++ = x;
|
||||
*p++ = y;
|
||||
*p++ = z;
|
||||
++vgl.end;
|
||||
if ( vgl.end >= VGL_MAX_VERTS )
|
||||
{
|
||||
gEngfuncs.Con_Reportf( S_ERROR "VGL_Vertex3f(): Vertex buffer overflow!\n" );
|
||||
vgl.end = vgl.begin = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void VGL_Vertex2f( GLfloat x, GLfloat y )
|
||||
{
|
||||
VGL_Vertex3f( x, y, 0.f );
|
||||
}
|
||||
|
||||
void VGL_Vertex3fv( const GLfloat *v )
|
||||
{
|
||||
VGL_Vertex3f( v[0], v[1], v[2] );
|
||||
}
|
||||
|
||||
void VGL_Color4f( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
|
||||
{
|
||||
vgl.color[0] = r;
|
||||
vgl.color[1] = g;
|
||||
vgl.color[2] = b;
|
||||
vgl.color[3] = a;
|
||||
vgl.uchanged = GL_TRUE;
|
||||
if ( vgl.prim )
|
||||
{
|
||||
// HACK: enable color attribute if we're using color inside a Begin-End pair
|
||||
GLfloat *p = vgl.attrbuf[VGL_ATTR_COLOR] + vgl.end * 4;
|
||||
vgl.cur_flags |= 1 << VGL_ATTR_COLOR;
|
||||
*p++ = r;
|
||||
*p++ = g;
|
||||
*p++ = b;
|
||||
*p++ = a;
|
||||
}
|
||||
}
|
||||
|
||||
void VGL_Color3f( GLfloat r, GLfloat g, GLfloat b )
|
||||
{
|
||||
VGL_Color4f( r, g, b, 1.f );
|
||||
}
|
||||
|
||||
void VGL_Color4ub( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
|
||||
{
|
||||
VGL_Color4f( (GLfloat)r / 255.f, (GLfloat)g / 255.f, (GLfloat)b / 255.f, (GLfloat)a / 255.f );
|
||||
}
|
||||
|
||||
void VGL_Color4ubv( const GLubyte *v )
|
||||
{
|
||||
VGL_Color4ub( v[0], v[1], v[2], v[3] );
|
||||
}
|
||||
|
||||
void VGL_TexCoord2f( GLfloat u, GLfloat v )
|
||||
{
|
||||
// by spec glTexCoord always updates texunit 0
|
||||
GLfloat *p = vgl.attrbuf[VGL_ATTR_TEXCOORD0] + vgl.end * 2;
|
||||
vgl.cur_flags |= 1 << VGL_ATTR_TEXCOORD0;
|
||||
*p++ = u;
|
||||
*p++ = v;
|
||||
}
|
||||
|
||||
void VGL_MultiTexCoord2f( GLenum tex, GLfloat u, GLfloat v )
|
||||
{
|
||||
GLfloat *p;
|
||||
// assume there can only be two
|
||||
if ( tex == GL_TEXTURE0 )
|
||||
{
|
||||
p = vgl.attrbuf[VGL_ATTR_TEXCOORD0] + vgl.end * 2;
|
||||
vgl.cur_flags |= 1 << VGL_ATTR_TEXCOORD0;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = vgl.attrbuf[VGL_ATTR_TEXCOORD1] + vgl.end * 2;
|
||||
vgl.cur_flags |= 1 << VGL_ATTR_TEXCOORD1;
|
||||
}
|
||||
*p++ = u;
|
||||
*p++ = v;
|
||||
}
|
||||
|
||||
void VGL_Normal3fv( const GLfloat *v )
|
||||
{
|
||||
/* not sure if we actually need these */
|
||||
}
|
||||
|
||||
void VGL_ShadeModel( GLenum unused )
|
||||
{
|
||||
/* this doesn't do anything in vitaGL except spit errors in debug mode, so stub it out */
|
||||
}
|
||||
|
||||
void VGL_AlphaFunc( GLenum mode, GLfloat ref )
|
||||
{
|
||||
vgl.alpharef = ref;
|
||||
vgl.uchanged = GL_TRUE;
|
||||
// mode is always GL_GREATER
|
||||
}
|
||||
|
||||
void VGL_DrawBuffer( GLenum mode )
|
||||
{
|
||||
/* unsupported */
|
||||
}
|
||||
|
||||
#define VGL_DECLARE_PTR( name ) extern void *pgl ## name
|
||||
#define VGL_OVERRIDE_PTR( name ) pgl ## name = VGL_ ## name
|
||||
|
||||
void VGL_ShimInstall( void )
|
||||
{
|
||||
VGL_DECLARE_PTR( Vertex2f );
|
||||
VGL_DECLARE_PTR( Vertex3f );
|
||||
VGL_DECLARE_PTR( Vertex3fv );
|
||||
VGL_DECLARE_PTR( Color3f );
|
||||
VGL_DECLARE_PTR( Color4f );
|
||||
VGL_DECLARE_PTR( Color4ub );
|
||||
VGL_DECLARE_PTR( Color4ubv );
|
||||
VGL_DECLARE_PTR( Normal3fv );
|
||||
VGL_DECLARE_PTR( TexCoord2f );
|
||||
VGL_DECLARE_PTR( MultiTexCoord2f );
|
||||
VGL_DECLARE_PTR( ShadeModel );
|
||||
VGL_DECLARE_PTR( DrawBuffer );
|
||||
VGL_DECLARE_PTR( AlphaFunc );
|
||||
VGL_DECLARE_PTR( Begin );
|
||||
VGL_DECLARE_PTR( End );
|
||||
VGL_OVERRIDE_PTR( Vertex2f );
|
||||
VGL_OVERRIDE_PTR( Vertex3f );
|
||||
VGL_OVERRIDE_PTR( Vertex3fv );
|
||||
VGL_OVERRIDE_PTR( Color3f );
|
||||
VGL_OVERRIDE_PTR( Color4f );
|
||||
VGL_OVERRIDE_PTR( Color4ub );
|
||||
VGL_OVERRIDE_PTR( Color4ubv );
|
||||
VGL_OVERRIDE_PTR( Normal3fv );
|
||||
VGL_OVERRIDE_PTR( TexCoord2f );
|
||||
VGL_OVERRIDE_PTR( MultiTexCoord2f );
|
||||
VGL_OVERRIDE_PTR( ShadeModel );
|
||||
VGL_OVERRIDE_PTR( DrawBuffer );
|
||||
VGL_OVERRIDE_PTR( AlphaFunc );
|
||||
VGL_OVERRIDE_PTR( Begin );
|
||||
VGL_OVERRIDE_PTR( End );
|
||||
}
|
24
utils/vgl_shim/vgl_shim.h
Normal file
24
utils/vgl_shim/vgl_shim.h
Normal file
@ -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 VGL_MAX_VERTS 16384
|
||||
|
||||
int VGL_ShimInit( void );
|
||||
void VGL_ShimInstall( void );
|
||||
void VGL_ShimShutdown( void );
|
||||
void VGL_ShimEndFrame( void );
|
25
utils/vgl_shim/wscript
Normal file
25
utils/vgl_shim/wscript
Normal file
@ -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 = 'vgl_shim',
|
||||
features = 'c',
|
||||
includes = includes,
|
||||
use = libs,
|
||||
subsystem = bld.env.MSVC_SUBSYSTEM
|
||||
)
|
3
wscript
3
wscript
@ -55,6 +55,9 @@ SUBDIRS = [
|
||||
# enabled optionally
|
||||
Subproject('utils/mdldec', lambda x: x.env.ENABLE_UTILS),
|
||||
Subproject('utils/run-fuzzer', lambda x: x.env.ENABLE_FUZZER),
|
||||
|
||||
# enabled on PSVita only
|
||||
Subproject('utils/vgl_shim', lambda x: x.env.DEST_OS == 'psvita'),
|
||||
]
|
||||
|
||||
def options(opt):
|
||||
|
Loading…
Reference in New Issue
Block a user