You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
356 lines
9.3 KiB
356 lines
9.3 KiB
/* |
|
cl_render.c - RenderAPI loader & implementation |
|
Copyright (C) 2019 a1batross |
|
|
|
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 "common.h" |
|
#include "client.h" |
|
#include "library.h" |
|
#include "platform/platform.h" |
|
|
|
int R_FatPVS( const vec3_t org, float radius, byte *visbuffer, qboolean merge, qboolean fullvis ) |
|
{ |
|
return Mod_FatPVS( org, radius, visbuffer, world.visbytes, merge, fullvis ); |
|
} |
|
|
|
lightstyle_t *CL_GetLightStyle( int number ) |
|
{ |
|
Assert( number >= 0 && number < MAX_LIGHTSTYLES ); |
|
return &cl.lightstyles[number]; |
|
} |
|
|
|
const ref_overview_t *GL_GetOverviewParms( void ) |
|
{ |
|
return &clgame.overView; |
|
} |
|
|
|
static void *R_Mem_Alloc( size_t cb, const char *filename, const int fileline ) |
|
{ |
|
return _Mem_Alloc( cls.mempool, cb, true, filename, fileline ); |
|
} |
|
|
|
static void R_Mem_Free( void *mem, const char *filename, const int fileline ) |
|
{ |
|
if( !mem ) return; |
|
_Mem_Free( mem, filename, fileline ); |
|
} |
|
|
|
/* |
|
========= |
|
pfnGetFilesList |
|
|
|
========= |
|
*/ |
|
static char **pfnGetFilesList( const char *pattern, int *numFiles, int gamedironly ) |
|
{ |
|
static search_t *t = NULL; |
|
|
|
if( t ) Mem_Free( t ); // release prev search |
|
|
|
t = FS_Search( pattern, true, gamedironly ); |
|
|
|
if( !t ) |
|
{ |
|
if( numFiles ) *numFiles = 0; |
|
return NULL; |
|
} |
|
|
|
if( numFiles ) *numFiles = t->numfilenames; |
|
return t->filenames; |
|
} |
|
|
|
static uint pfnFileBufferCRC32( const void *buffer, const int length ) |
|
{ |
|
uint modelCRC = 0; |
|
|
|
if( !buffer || length <= 0 ) |
|
return modelCRC; |
|
|
|
CRC32_Init( &modelCRC ); |
|
CRC32_ProcessBuffer( &modelCRC, buffer, length ); |
|
return CRC32_Final( modelCRC ); |
|
} |
|
|
|
/* |
|
================= |
|
R_EnvShot |
|
|
|
================= |
|
*/ |
|
static void R_EnvShot( const float *vieworg, const char *name, qboolean skyshot, int shotsize ) |
|
{ |
|
static vec3_t viewPoint; |
|
|
|
if( !COM_CheckString( name )) |
|
return; |
|
|
|
if( cls.scrshot_action != scrshot_inactive ) |
|
{ |
|
if( cls.scrshot_action != scrshot_skyshot && cls.scrshot_action != scrshot_envshot ) |
|
Con_Printf( S_ERROR "R_%sShot: subsystem is busy, try for next frame.\n", skyshot ? "Sky" : "Env" ); |
|
return; |
|
} |
|
|
|
cls.envshot_vieworg = NULL; // use client view |
|
Q_strncpy( cls.shotname, name, sizeof( cls.shotname )); |
|
|
|
if( vieworg ) |
|
{ |
|
// make sure what viewpoint don't temporare |
|
VectorCopy( vieworg, viewPoint ); |
|
cls.envshot_vieworg = viewPoint; |
|
cls.envshot_disable_vis = true; |
|
} |
|
|
|
// make request for envshot |
|
if( skyshot ) cls.scrshot_action = scrshot_skyshot; |
|
else cls.scrshot_action = scrshot_envshot; |
|
|
|
// catch negative values |
|
cls.envshot_viewsize = Q_max( 0, shotsize ); |
|
} |
|
|
|
/* |
|
============= |
|
CL_GenericHandle |
|
|
|
============= |
|
*/ |
|
const char *CL_GenericHandle( int fileindex ) |
|
{ |
|
if( fileindex < 0 || fileindex >= MAX_CUSTOM ) |
|
return 0; |
|
return cl.files_precache[fileindex]; |
|
} |
|
|
|
intptr_t CL_RenderGetParm( const int parm, const int arg, const qboolean checkRef ) |
|
{ |
|
switch( parm ) |
|
{ |
|
case PARM_BSP2_SUPPORTED: |
|
#ifdef SUPPORT_BSP2_FORMAT |
|
return 1; |
|
#endif |
|
return 0; |
|
case PARM_SKY_SPHERE: |
|
return FBitSet( world.flags, FWORLD_SKYSPHERE ) && !FBitSet( world.flags, FWORLD_CUSTOM_SKYBOX ); |
|
case PARAM_GAMEPAUSED: |
|
return cl.paused; |
|
case PARM_CLIENT_INGAME: |
|
return CL_IsInGame(); |
|
case PARM_MAX_ENTITIES: |
|
return clgame.maxEntities; |
|
case PARM_FEATURES: |
|
return host.features; |
|
case PARM_MAP_HAS_DELUXE: |
|
return FBitSet( world.flags, FWORLD_HAS_DELUXEMAP ); |
|
case PARM_CLIENT_ACTIVE: |
|
return (cls.state == ca_active); |
|
case PARM_DEDICATED_SERVER: |
|
return (host.type == HOST_DEDICATED); |
|
case PARM_WATER_ALPHA: |
|
return FBitSet( world.flags, FWORLD_WATERALPHA ); |
|
case PARM_DELUXEDATA: |
|
return (intptr_t)world.deluxedata; |
|
case PARM_SHADOWDATA: |
|
return (intptr_t)world.shadowdata; |
|
case PARM_FULLSCREEN: |
|
return refState.fullScreen; |
|
case PARM_WIDESCREEN: |
|
return refState.wideScreen; |
|
case PARM_SCREEN_WIDTH: |
|
return refState.width; |
|
case PARM_SCREEN_HEIGHT: |
|
return refState.height; |
|
default: |
|
// indicates call from client.dll |
|
if( checkRef ) |
|
{ |
|
return ref.dllFuncs.RefGetParm( parm, arg ); |
|
} |
|
// call issued from ref_dll, check extensions here |
|
else switch( parm ) |
|
{ |
|
case PARM_DEV_OVERVIEW: |
|
return CL_IsDevOverviewMode(); |
|
case PARM_THIRDPERSON: |
|
return CL_IsThirdPerson(); |
|
case PARM_QUAKE_COMPATIBLE: |
|
return Host_IsQuakeCompatible(); |
|
case PARM_PLAYER_INDEX: |
|
return cl.playernum + 1; |
|
case PARM_VIEWENT_INDEX: |
|
return cl.viewentity; |
|
case PARM_CONNSTATE: |
|
return (int)cls.state; |
|
case PARM_PLAYING_DEMO: |
|
return cls.demoplayback; |
|
case PARM_WATER_LEVEL: |
|
return cl.local.waterlevel; |
|
case PARM_MAX_CLIENTS: |
|
return cl.maxclients; |
|
case PARM_LOCAL_HEALTH: |
|
return cl.local.health; |
|
case PARM_LOCAL_GAME: |
|
return Host_IsLocalGame(); |
|
case PARM_NUMENTITIES: |
|
return pfnNumberOfEntities(); |
|
case PARM_NUMMODELS: |
|
return cl.nummodels; |
|
case PARM_WORLD_VERSION: |
|
return world.version; |
|
} |
|
} |
|
return 0; |
|
} |
|
|
|
static intptr_t pfnRenderGetParm( int parm, int arg ) |
|
{ |
|
return CL_RenderGetParm( parm, arg, true ); |
|
} |
|
|
|
static render_api_t gRenderAPI = |
|
{ |
|
pfnRenderGetParm, // GL_RenderGetParm, |
|
NULL, // R_GetDetailScaleForTexture, |
|
NULL, // R_GetExtraParmsForTexture, |
|
CL_GetLightStyle, |
|
CL_GetDynamicLight, |
|
CL_GetEntityLight, |
|
LightToTexGamma, |
|
NULL, // R_GetFrameTime, |
|
NULL, // R_SetCurrentEntity, |
|
NULL, // R_SetCurrentModel, |
|
R_FatPVS, |
|
R_StoreEfrags, |
|
NULL, // GL_FindTexture, |
|
NULL, // GL_TextureName, |
|
NULL, // GL_TextureData, |
|
NULL, // GL_LoadTexture, |
|
NULL, // GL_CreateTexture, |
|
NULL, // GL_LoadTextureArray, |
|
NULL, // GL_CreateTextureArray, |
|
NULL, // GL_FreeTexture, |
|
NULL, // DrawSingleDecal, |
|
NULL, // R_DecalSetupVerts, |
|
NULL, // R_EntityRemoveDecals, |
|
(void*)AVI_LoadVideo, |
|
(void*)AVI_GetVideoInfo, |
|
(void*)AVI_GetVideoFrameNumber, |
|
(void*)AVI_GetVideoFrame, |
|
NULL, // R_UploadStretchRaw, |
|
(void*)AVI_FreeVideo, |
|
(void*)AVI_IsActive, |
|
S_StreamAviSamples, |
|
NULL, |
|
NULL, |
|
NULL, // GL_Bind, |
|
NULL, // GL_SelectTexture, |
|
NULL, // GL_LoadTexMatrixExt, |
|
NULL, // GL_LoadIdentityTexMatrix, |
|
NULL, // GL_CleanUpTextureUnits, |
|
NULL, // GL_TexGen, |
|
NULL, // GL_TextureTarget, |
|
NULL, // GL_SetTexCoordArrayMode, |
|
NULL, // GL_GetProcAddress, |
|
NULL, // GL_UpdateTexSize, |
|
NULL, |
|
NULL, |
|
NULL, // CL_DrawParticlesExternal, |
|
R_EnvShot, |
|
pfnSPR_LoadExt, |
|
NULL, // R_LightVec, |
|
NULL, // R_StudioGetTexture, |
|
GL_GetOverviewParms, |
|
CL_GenericHandle, |
|
COM_SaveFile, |
|
NULL, |
|
R_Mem_Alloc, |
|
R_Mem_Free, |
|
pfnGetFilesList, |
|
pfnFileBufferCRC32, |
|
COM_CompareFileTime, |
|
Host_Error, |
|
(void*)CL_ModelHandle, |
|
pfnTime, |
|
Cvar_Set, |
|
S_FadeMusicVolume, |
|
COM_SetRandomSeed, |
|
}; |
|
|
|
static void R_FillRenderAPIFromRef( render_api_t *to, const ref_interface_t *from ) |
|
{ |
|
to->GetDetailScaleForTexture = from->GetDetailScaleForTexture; |
|
to->GetExtraParmsForTexture = from->GetExtraParmsForTexture; |
|
to->GetFrameTime = from->GetFrameTime; |
|
to->R_SetCurrentEntity = from->R_SetCurrentEntity; |
|
to->R_SetCurrentModel = from->R_SetCurrentModel; |
|
to->GL_FindTexture = from->GL_FindTexture; |
|
to->GL_TextureName = from->GL_TextureName; |
|
to->GL_TextureData = from->GL_TextureData; |
|
to->GL_LoadTexture = from->GL_LoadTexture; |
|
to->GL_CreateTexture = from->GL_CreateTexture; |
|
to->GL_LoadTextureArray = from->GL_LoadTextureArray; |
|
to->GL_CreateTextureArray = from->GL_CreateTextureArray; |
|
to->GL_FreeTexture = from->GL_FreeTexture; |
|
to->DrawSingleDecal = from->DrawSingleDecal; |
|
to->R_DecalSetupVerts = from->R_DecalSetupVerts; |
|
to->R_EntityRemoveDecals = from->R_EntityRemoveDecals; |
|
to->AVI_UploadRawFrame = from->AVI_UploadRawFrame; |
|
to->GL_Bind = from->GL_Bind; |
|
to->GL_SelectTexture = from->GL_SelectTexture; |
|
to->GL_LoadTextureMatrix = from->GL_LoadTextureMatrix; |
|
to->GL_TexMatrixIdentity = from->GL_TexMatrixIdentity; |
|
to->GL_CleanUpTextureUnits = from->GL_CleanUpTextureUnits; |
|
to->GL_TexGen = from->GL_TexGen; |
|
to->GL_TextureTarget = from->GL_TextureTarget; |
|
to->GL_TexCoordArrayMode = from->GL_TexCoordArrayMode; |
|
to->GL_UpdateTexSize = from->GL_UpdateTexSize; |
|
to->GL_DrawParticles = from->GL_DrawParticles; |
|
to->LightVec = from->LightVec; |
|
to->StudioGetTexture = from->StudioGetTexture; |
|
to->GL_GetProcAddress = from->R_GetProcAddress; |
|
} |
|
|
|
/* |
|
=============== |
|
R_InitRenderAPI |
|
|
|
Initialize client external rendering |
|
=============== |
|
*/ |
|
qboolean R_InitRenderAPI( void ) |
|
{ |
|
// make sure what render functions is cleared |
|
memset( &clgame.drawFuncs, 0, sizeof( clgame.drawFuncs )); |
|
|
|
// fill missing functions from renderer |
|
R_FillRenderAPIFromRef( &gRenderAPI, &ref.dllFuncs ); |
|
|
|
if( clgame.dllFuncs.pfnGetRenderInterface ) |
|
{ |
|
if( clgame.dllFuncs.pfnGetRenderInterface( CL_RENDER_INTERFACE_VERSION, &gRenderAPI, &clgame.drawFuncs )) |
|
{ |
|
Con_Reportf( "CL_LoadProgs: ^2initailized extended RenderAPI ^7ver. %i\n", CL_RENDER_INTERFACE_VERSION ); |
|
return true; |
|
} |
|
|
|
// make sure what render functions is cleared |
|
memset( &clgame.drawFuncs, 0, sizeof( clgame.drawFuncs )); |
|
|
|
return false; // just tell user about problems |
|
} |
|
|
|
// render interface is missed |
|
return true; |
|
}
|
|
|