/* 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. */ #ifndef XASH_DEDICATED #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 = max( 0, shotsize ); } /* ============= CL_GenericHandle ============= */ const char *CL_GenericHandle( int fileindex ) { if( fileindex < 0 || fileindex >= MAX_CUSTOM ) return 0; return cl.files_precache[fileindex]; } int CL_RenderGetParm( int parm, 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 ); default: if( checkRef ) return ref.dllFuncs.RenderGetParm( parm, arg ); } return 0; } static int 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, NULL, // 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, NULL, NULL, R_Mem_Alloc, R_Mem_Free, pfnGetFilesList, pfnFileBufferCRC32, COM_CompareFileTime, Host_Error, (void*)CL_ModelHandle, pfnTime, Cvar_Set, S_FadeMusicVolume, COM_SetRandomSeed, }; /* =============== 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 gRenderAPI.GetDetailScaleForTexture = ref.dllFuncs.GetDetailScaleForTexture; gRenderAPI.GetExtraParmsForTexture = ref.dllFuncs.GetDetailScaleForTexture; gRenderAPI.GetFrameTime = ref.dllFuncs.GetFrameTime; gRenderAPI.R_SetCurrentEntity = ref.dllFuncs.R_SetCurrentEntity; gRenderAPI.R_SetCurrentModel = ref.dllFuncs.R_SetCurrentModel; gRenderAPI.R_StoreEfrags = R_StoreEfrags; gRenderAPI.GL_FindTexture = ref.dllFuncs.GL_FindTexture; gRenderAPI.GL_TextureName = ref.dllFuncs.GL_TextureName; gRenderAPI.GL_TextureData = ref.dllFuncs.GL_TextureData; gRenderAPI.GL_LoadTexture = ref.dllFuncs.GL_LoadTexture; gRenderAPI.GL_CreateTexture = ref.dllFuncs.GL_CreateTexture; gRenderAPI.GL_LoadTextureArray = ref.dllFuncs.GL_LoadTextureArray; gRenderAPI.GL_CreateTextureArray = ref.dllFuncs.GL_CreateTextureArray; gRenderAPI.GL_FreeTexture = ref.dllFuncs.GL_FreeTexture; gRenderAPI.DrawSingleDecal = ref.dllFuncs.DrawSingleDecal; gRenderAPI.R_DecalSetupVerts = ref.dllFuncs.R_DecalSetupVerts; gRenderAPI.R_EntityRemoveDecals = ref.dllFuncs.R_EntityRemoveDecals; gRenderAPI.AVI_UploadRawFrame = ref.dllFuncs.AVI_UploadRawFrame; gRenderAPI.GL_Bind = ref.dllFuncs.GL_Bind; gRenderAPI.GL_SelectTexture = ref.dllFuncs.GL_SelectTexture; gRenderAPI.GL_LoadTextureMatrix = ref.dllFuncs.GL_LoadTextureMatrix; gRenderAPI.GL_TexMatrixIdentity = ref.dllFuncs.GL_TexMatrixIdentity; gRenderAPI.GL_CleanUpTextureUnits = ref.dllFuncs.GL_CleanUpTextureUnits; gRenderAPI.GL_TexGen = ref.dllFuncs.GL_TexGen; gRenderAPI.GL_TextureTarget = ref.dllFuncs.GL_TextureTarget; gRenderAPI.GL_TexCoordArrayMode = ref.dllFuncs.GL_TexCoordArrayMode; gRenderAPI.GL_GetProcAddress = GL_GetProcAddress; gRenderAPI.GL_UpdateTexSize = ref.dllFuncs.GL_UpdateTexSize; gRenderAPI.GL_DrawParticles = ref.dllFuncs.GL_DrawParticles; gRenderAPI.LightVec = ref.dllFuncs.LightVec; gRenderAPI.StudioGetTexture = ref.dllFuncs.StudioGetTexture; 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; } #endif // XASH_DEDICATED