/* gu_render.c - render initialization Copyright (C) 2010 Uncle Mike Copyright (C) 2022 Sergey Galushko 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 "gu_local.h" cvar_t *gl_texture_lodfunc; cvar_t *gl_texture_lodbias; cvar_t *gl_texture_lodslope; cvar_t *gl_texture_nearest; cvar_t *gl_lightmap_nearest; cvar_t *gl_keeptjunctions; cvar_t *gl_emboss_scale; cvar_t *gl_detailscale; cvar_t *gl_depthoffset; cvar_t *gl_wireframe; cvar_t *gl_nosort; cvar_t *gl_vsync; cvar_t *gl_clear; cvar_t *gl_test; cvar_t *gl_subdivide_size; cvar_t *r_speeds; cvar_t *r_fullbright; cvar_t *r_norefresh; cvar_t *r_lighting_extended; cvar_t *r_lighting_modulate; cvar_t *r_lighting_ambient; cvar_t *r_detailtextures; cvar_t *r_drawentities; cvar_t *r_adjust_fov; cvar_t *r_decals; cvar_t *r_novis; cvar_t *r_nocull; cvar_t *r_lockpvs; cvar_t *r_lockfrustum; cvar_t *r_traceglow; cvar_t *r_dynamic; cvar_t *r_lightmap; cvar_t *r_showhull; cvar_t *r_fast_particles; cvar_t *gl_round_down; cvar_t *gl_showtextures; cvar_t *cl_lightstyle_lerping; cvar_t *vid_brightness; cvar_t *vid_gamma; cvar_t *tracerred; cvar_t *tracergreen; cvar_t *tracerblue; cvar_t *traceralpha; byte *r_temppool; gl_globals_t tr; glconfig_t glConfig; glstate_t glState; glwstate_t glw_state; gurender_t guRender; // Set frame buffer #define PSP_FB_WIDTH 480 #define PSP_FB_HEIGHT 272 #define PSP_FB_BWIDTH 512 #define PSP_FB_FORMAT GU_PSM_5650 //4444,5551,5650,8888 #if PSP_FB_FORMAT == GU_PSM_4444 #define PSP_FB_BPP 2 #elif PSP_FB_FORMAT == GU_PSM_5551 #define PSP_FB_BPP 2 #elif PSP_FB_FORMAT == GU_PSM_5650 #define PSP_FB_BPP 2 #elif PSP_FB_FORMAT == GU_PSM_8888 #define PSP_FB_BPP 4 #endif #define PSP_GU_LIST_SIZE 0x100000 // 1Mb static byte context_list[PSP_GU_LIST_SIZE] __attribute__( ( aligned( 64 ) ) ); /* =============== GU_Init =============== */ static void GU_Init( void ) { memset( &guRender, 0, sizeof( guRender )); guRender.screen_width = PSP_FB_WIDTH; guRender.screen_height = PSP_FB_HEIGHT; guRender.buffer_width = PSP_FB_BWIDTH; guRender.buffer_format = PSP_FB_FORMAT; guRender.buffer_bpp = PSP_FB_BPP; guRender.draw_buffer = ( void* )valloc( guRender.buffer_width * guRender.screen_height * guRender.buffer_bpp ); if( !guRender.draw_buffer ) gEngfuncs.Host_Error( "Memory allocation failled! (guRender.draw_buffer)\n" ); guRender.disp_buffer = ( void* )valloc( guRender.buffer_width * guRender.screen_height * guRender.buffer_bpp ); if( !guRender.disp_buffer ) gEngfuncs.Host_Error( "Memory allocation failled! (guRender.disp_buffer)\n" ); guRender.depth_buffer = ( void* )valloc( guRender.buffer_width * guRender.screen_height * guRender.buffer_bpp ); if( !guRender.depth_buffer ) gEngfuncs.Host_Error( "Memory allocation failled! (guRender.depth_buffer)\n" ); guRender.context_list = context_list; guRender.context_list_size = sizeof( context_list ); // Initialise the GU. sceGuInit(); // Set up the GU. sceGuStart( GU_DIRECT, guRender.context_list ); sceGuDrawBuffer( guRender.buffer_format, vrelptr( guRender.draw_buffer ), guRender.buffer_width ); sceGuDispBuffer( guRender.screen_width, guRender.screen_height, vrelptr( guRender.disp_buffer ), guRender.buffer_width ); sceGuDepthBuffer( vrelptr( guRender.depth_buffer ), guRender.buffer_width ); // Set the rendering offset and viewport. sceGuOffset( 2048 - ( guRender.screen_width / 2 ), 2048 - ( guRender.screen_height / 2 ) ); sceGuViewport( 2048, 2048, guRender.screen_width, guRender.screen_height ); // Set up scissoring. sceGuEnable( GU_SCISSOR_TEST ); sceGuScissor( 0, 0, guRender.screen_width, guRender.screen_height ); // Xash default sceGuClearColor( GU_COLOR( 0.5f, 0.5f, 0.5f, 1.0f ) ); sceGuDisable( GU_DEPTH_TEST ); sceGuDisable( GU_CULL_FACE ); sceGuEnable( GU_CLIP_PLANES ); sceGuDepthFunc( GU_LEQUAL ); sceGuColor( 0xffffffff ); // Set up stencil if( glState.stencilEnabled ) { sceGuDisable( GU_STENCIL_TEST ); /*pglStencilMask( ( GLuint ) ~0 );*/ // alpha color sceGuPixelMask sceGuStencilFunc( GU_EQUAL, 0, ~0 ); sceGuStencilOp( GU_KEEP, GU_INCR, GU_INCR ); } sceGuDepthRange( 0, 65535 ); sceGuDepthOffset( 0 ); sceGuDisable( GU_BLEND ); sceGuDisable( GU_ALPHA_TEST ); sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 ); sceGuAlphaFunc( GU_GREATER, DEFAULT_ALPHATEST, 0xff ); sceGuEnable( GU_TEXTURE_2D ); sceGuShadeModel( GU_SMOOTH ); sceGuFrontFace( GU_CW ); // reversed // Set the default matrices. sceGumMatrixMode( GU_PROJECTION ); sceGumLoadIdentity(); sceGumMatrixMode( GU_VIEW ); sceGumLoadIdentity(); sceGumMatrixMode( GU_MODEL ); sceGumLoadIdentity(); sceGumMatrixMode( GU_TEXTURE ); sceGumLoadIdentity(); sceGumUpdateMatrix(); sceGuFinish(); sceGuSync( GU_SYNC_FINISH, GU_SYNC_WAIT ); // Turn on the display. sceDisplayWaitVblankStart(); sceGuDisplay(GU_TRUE); // Start a new render. sceGuStart( GU_DIRECT, guRender.context_list ); } /* =============== GU_Shutdown =============== */ static void GU_Shutdown( void ) { // Finish rendering. sceGuFinish(); sceGuSync( GU_SYNC_FINISH, GU_SYNC_WAIT ); // Shut down the display. sceGuTerm(); // Free the buffers. if( guRender.draw_buffer ) vfree( guRender.draw_buffer ); if( guRender.disp_buffer ) vfree( guRender.disp_buffer ); if( guRender.depth_buffer ) vfree( guRender.depth_buffer ); guRender.draw_buffer = NULL; guRender.disp_buffer = NULL; guRender.depth_buffer = NULL; } /* ============== GL_GetProcAddress defined just for nanogl/glwes, so it don't link to SDL2 directly, nor use dlsym ============== */ void GAME_EXPORT *GL_GetProcAddress( const char *name ) { return gEngfuncs.GL_GetProcAddress( name ); } /* =============== GL_SetDefaultState =============== */ static void GL_SetDefaultState( void ) { memset( &glState, 0, sizeof( glState )); // init draw stack tr.draw_list = &tr.draw_stack[0]; tr.draw_stack_pos = 0; // init glState struct glState.currentTexture = -1; glState.texIdentityMatrix = true; glState.fogColor = 0; glState.fogDensity = 0; glState.fogStart = 100.0f; glState.fogEnd = 1000.0f; } #if 0 /* =============== GL_SetDefaults =============== */ static void GU_SetDefaults( void ) { pglFinish(); pglClearColor( 0.5f, 0.5f, 0.5f, 1.0f ); pglDisable( GL_DEPTH_TEST ); pglDisable( GL_CULL_FACE ); pglDisable( GL_SCISSOR_TEST ); pglDepthFunc( GL_LEQUAL ); pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); if( glState.stencilEnabled ) { pglDisable( GL_STENCIL_TEST ); pglStencilMask( ( GLuint ) ~0 ); pglStencilFunc( GL_EQUAL, 0, ~0 ); pglStencilOp( GL_KEEP, GL_INCR, GL_INCR ); } pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); pglPolygonOffset( -1.0f, -2.0f ); GL_CleanupAllTextureUnits(); pglDisable( GL_BLEND ); pglDisable( GL_ALPHA_TEST ); pglDisable( GL_POLYGON_OFFSET_FILL ); pglAlphaFunc( GL_GREATER, DEFAULT_ALPHATEST ); pglEnable( GL_TEXTURE_2D ); pglShadeModel( GL_SMOOTH ); pglFrontFace( GL_CCW ); pglPointSize( 1.2f ); pglLineWidth( 1.2f ); GL_Cull( GL_NONE ); } #endif /* ================= R_RenderInfo_f ================= */ void R_RenderInfo_f( void ) { gEngfuncs.Con_Printf( "\n" ); gEngfuncs.Con_Printf( "HARDWARE RENDER\n"); gEngfuncs.Con_Printf( "MAX_TEXTURE_SIZE: %i\n", glConfig.max_texture_size ); gEngfuncs.Con_Printf( "MODE: %ix%i\n", gpGlobals->width, gpGlobals->height ); gEngfuncs.Con_Printf( "VERTICAL SYNC: %s\n", gl_vsync->value ? "enabled" : "disabled" ); gEngfuncs.Con_Printf( "VRAM AVAILABLE: %i\n", vmemavail() ); } void GL_InitExtensions( void ) { glState.stencilEnabled = true; glConfig.max_texture_size = 256; // get our various GL strings gEngfuncs.Con_Reportf( "^3Video^7: PSP HW\n" ); gEngfuncs.Cvar_Get( "gl_max_size", va( "%i", glConfig.max_texture_size ), 0, "opengl texture max dims" ); /* gEngfuncs.Image_AddCmdFlags( IL_DDS_HARDWARE ); */ R_RenderInfo_f(); tr.framecount = tr.visframecount = 1; glw_state.initialized = true; } void GL_ClearExtensions( void ) { // now all extensions are disabled glw_state.initialized = false; } //======================================================================= /* ================= GL_InitCommands ================= */ void GL_InitCommands( void ) { r_speeds = gEngfuncs.Cvar_Get( "r_speeds", "0", FCVAR_ARCHIVE, "shows renderer speeds" ); r_fullbright = gEngfuncs.Cvar_Get( "r_fullbright", "0", FCVAR_CHEAT, "disable lightmaps, get fullbright for entities" ); r_norefresh = gEngfuncs.Cvar_Get( "r_norefresh", "0", 0, "disable 3D rendering (use with caution)" ); r_lighting_extended = gEngfuncs.Cvar_Get( "r_lighting_extended", "0", FCVAR_ARCHIVE, "allow to get lighting from world and bmodels" ); // disabled r_lighting_modulate = gEngfuncs.Cvar_Get( "r_lighting_modulate", "0.6", FCVAR_ARCHIVE, "lightstyles modulate scale" ); r_lighting_ambient = gEngfuncs.Cvar_Get( "r_lighting_ambient", "0.3", FCVAR_ARCHIVE, "map ambient lighting scale" ); r_novis = gEngfuncs.Cvar_Get( "r_novis", "0", 0, "ignore vis information (perfomance test)" ); r_nocull = gEngfuncs.Cvar_Get( "r_nocull", "0", 0, "ignore frustrum culling (perfomance test)" ); r_detailtextures = gEngfuncs.Cvar_Get( "r_detailtextures", "0", FCVAR_ARCHIVE, "enable detail textures support, use '2' for autogenerate detail.txt" ); // disabled r_lockpvs = gEngfuncs.Cvar_Get( "r_lockpvs", "0", FCVAR_CHEAT, "lockpvs area at current point (pvs test)" ); r_lockfrustum = gEngfuncs.Cvar_Get( "r_lockfrustum", "0", FCVAR_CHEAT, "lock frustrum area at current point (cull test)" ); r_dynamic = gEngfuncs.Cvar_Get( "r_dynamic", "1", FCVAR_ARCHIVE, "allow dynamic lighting (dlights, lightstyles)" ); r_traceglow = gEngfuncs.Cvar_Get( "r_traceglow", "0", FCVAR_ARCHIVE, "cull flares behind models" ); // disabled r_lightmap = gEngfuncs.Cvar_Get( "r_lightmap", "0", FCVAR_CHEAT, "lightmap debugging tool" ); r_drawentities = gEngfuncs.Cvar_Get( "r_drawentities", "1", FCVAR_CHEAT, "render entities" ); r_decals = gEngfuncs.pfnGetCvarPointer( "r_decals", 0 ); r_showhull = gEngfuncs.pfnGetCvarPointer( "r_showhull", 0 ); r_fast_particles = gEngfuncs.Cvar_Get( "r_fast_particles", "1", FCVAR_ARCHIVE, "use GU_POINTS for particles" ); gl_texture_nearest = gEngfuncs.Cvar_Get( "gl_texture_nearest", "0", FCVAR_GLCONFIG, "disable texture filter" ); gl_lightmap_nearest = gEngfuncs.Cvar_Get( "gl_lightmap_nearest", "0", FCVAR_GLCONFIG, "disable lightmap filter" ); gl_vsync = gEngfuncs.pfnGetCvarPointer( "gl_vsync", 0 ); gl_detailscale = gEngfuncs.Cvar_Get( "gl_detailscale", "4.0", FCVAR_GLCONFIG, "default scale applies while auto-generate list of detail textures" ); gl_texture_lodfunc = gEngfuncs.Cvar_Get( "gl_texture_lodfunc", "2", FCVAR_GLCONFIG, "LOD func for mipmapped textures" ); gl_texture_lodbias = gEngfuncs.Cvar_Get( "gl_texture_lodbias", "-6.0", FCVAR_GLCONFIG, "LOD bias for mipmapped textures (perfomance|quality)" ); gl_texture_lodslope = gEngfuncs.Cvar_Get( "gl_texture_lodslope", "0.3", FCVAR_GLCONFIG, "LOD slope for mipmapped textures" ); gl_keeptjunctions = gEngfuncs.Cvar_Get( "gl_keeptjunctions", "1", FCVAR_GLCONFIG, "removing tjuncs causes blinking pixels" ); gl_emboss_scale = gEngfuncs.Cvar_Get( "gl_emboss_scale", "0", FCVAR_GLCONFIG|FCVAR_LATCH, "fake bumpmapping scale" ); gl_showtextures = gEngfuncs.pfnGetCvarPointer( "r_showtextures", 0 ); gl_nosort = gEngfuncs.Cvar_Get( "gl_nosort", "1", FCVAR_GLCONFIG, "disable sorting of translucent surfaces" ); gl_clear = gEngfuncs.pfnGetCvarPointer( "gl_clear", 0 ); gl_test = gEngfuncs.Cvar_Get( "gl_test", "0", 0, "engine developer cvar for quick testing new features" ); gl_wireframe = gEngfuncs.Cvar_Get( "gl_wireframe", "0", FCVAR_GLCONFIG|FCVAR_SPONLY, "show wireframe overlay" ); gl_subdivide_size = gEngfuncs.Cvar_Get( "gl_subdivide_size", "256.0", FCVAR_GLCONFIG, "the division value for the sky brushes" ); gl_round_down = gEngfuncs.Cvar_Get( "gl_round_down", "1", FCVAR_GLCONFIG, "round texture sizes to nearest POT value" ); // these cvar not used by engine but some mods requires this gl_depthoffset = gEngfuncs.Cvar_Get( "gl_depthoffset", "256.0", FCVAR_GLCONFIG, "depth offset for decals" ); // make sure gl_vsync is checked after vid_restart SetBits( gl_vsync->flags, FCVAR_CHANGED ); vid_gamma = gEngfuncs.pfnGetCvarPointer( "gamma", 0 ); vid_brightness = gEngfuncs.pfnGetCvarPointer( "brightness", 0 ); tracerred = gEngfuncs.Cvar_Get( "tracerred", "0.8", 0, "tracer red component weight ( 0 - 1.0 )" ); tracergreen = gEngfuncs.Cvar_Get( "tracergreen", "0.8", 0, "tracer green component weight ( 0 - 1.0 )" ); tracerblue = gEngfuncs.Cvar_Get( "tracerblue", "0.4", 0, "tracer blue component weight ( 0 - 1.0 )" ); traceralpha = gEngfuncs.Cvar_Get( "traceralpha", "0.5", 0, "tracer alpha amount ( 0 - 1.0 )" ); cl_lightstyle_lerping = gEngfuncs.pfnGetCvarPointer( "cl_lightstyle_lerping", 0 ); gEngfuncs.Cmd_AddCommand( "r_info", R_RenderInfo_f, "display renderer info" ); gEngfuncs.Cmd_AddCommand( "timerefresh", SCR_TimeRefresh_f, "turn quickly and print rendering statistcs" ); } /* ================= GL_RemoveCommands ================= */ void GL_RemoveCommands( void ) { gEngfuncs.Cmd_RemoveCommand( "r_info" ); } /* =============== R_Init =============== */ qboolean R_Init( void ) { if( glw_state.initialized ) return true; if( vinit() < 0 ) { gEngfuncs.Host_Error( "Can't initialize video subsystem\nVRam unavailable" ); return false; } GL_InitCommands(); GL_InitRandomTable(); GL_SetDefaultState(); // create the window and set up the context if( !gEngfuncs.R_Init_Video( REF_GL )) // request GL context { GL_RemoveCommands(); gEngfuncs.R_Free_Video(); // Why? Host_Error again??? // gEngfuncs.Host_Error( "Can't initialize video subsystem\nProbably driver was not installed" ); return false; } r_temppool = Mem_AllocPool( "Render Zone" ); GU_Init(); R_InitImages(); R_SpriteInit(); R_StudioInit(); R_AliasInit(); R_ClearDecals(); R_ClearScene(); return true; } /* =============== R_Shutdown =============== */ void R_Shutdown( void ) { if( !glw_state.initialized ) return; GL_RemoveCommands(); R_ShutdownImages(); GU_Shutdown(); Mem_FreePool( &r_temppool ); // shut down OS specific OpenGL stuff like contexts, etc. gEngfuncs.R_Free_Video(); } void GL_SetupAttributes( int safegl ) { }