Compare commits

..

14 Commits

Author SHA1 Message Date
Alibek Omarov
8f819a2fde engine: platform: sdl: fix forgotten icon setup call 2023-10-23 00:31:30 +03:00
Alibek Omarov
3251b68df5 ref: gl: more simple search of GL func with alternative name (EXT, OES suffixes or no suffix) 2023-10-22 20:02:14 +03:00
Alibek Omarov
3ac8ad9484 engine: fixup endianness found by -Werror=strict-aliasing in old armv7hf compiler (d259421111) 2023-10-22 20:02:14 +03:00
Alibek Omarov
b9ca0d4563 engine: common: network: more simple IP address copying from sockaddr to netadr_t and back 2023-10-22 20:02:14 +03:00
mittorn
dcb3da53b0 engine/client: fallback to defaults in touch_reloadconfig if config not exist 2023-10-22 20:02:14 +03:00
mittorn
e68b19ed1a engine/client: handle touch config aspect ratio, try correctly handle touch aspect on resizeable windows 2023-10-22 20:02:14 +03:00
mittorn
14c7a84482 engine/client: always save touch config if it was resetted manually (helps after writing broken/empty config) 2023-10-22 20:02:14 +03:00
mittorn
c1d1aa6787 ref_gl: rewrite ARB workaround to check EXT/OES names, notify user that function found with different name 2023-10-22 20:02:14 +03:00
mittorn
bee81e9723 engine: Make SDL_GetBasePath error not fatal 2023-10-22 20:02:14 +03:00
mittorn
1bfb6c560a platform/sdl: add check for missing hint defines 2023-10-22 20:02:14 +03:00
mittorn
24d6f1788a platform/sdl: workaround ubuntu SDL2 bug preventing resolving any extensions on EGL 2023-10-22 20:02:14 +03:00
mittorn
fb95cc9a97 engine/client: respect m_ignore in mouse client code as grabbing window breaks touch input 2023-10-22 20:02:14 +03:00
mittorn
b949da291e engine: fix strict aliasing issues found by an old armv7hf compiler 2023-10-22 20:02:14 +03:00
Alibek Omarov
2ecbe5b67e engine: add testing master server at mentality.rip:27011 2023-10-22 19:39:58 +03:00
14 changed files with 204 additions and 44 deletions

View File

@@ -2247,10 +2247,13 @@ void CL_ReadNetMessage( void )
while( CL_GetMessage( net_message_buffer, &curSize ))
{
if( cls.legacymode && *((int *)&net_message_buffer) == 0xFFFFFFFE )
const int split_header = LittleLong( 0xFFFFFFFE );
if( cls.legacymode && !memcmp( &split_header, net_message_buffer, sizeof( split_header )))
{
// Will rewrite existing packet by merged
if( !NetSplit_GetLong( &cls.netchan.netsplit, &net_from, net_message_buffer, &curSize ) )
continue;
}
MSG_Init( &net_message, "ServerData", net_message_buffer, curSize );

View File

@@ -1534,7 +1534,8 @@ void CL_SendConsistencyInfo( sizebuf_t *msg )
{
case force_exactfile:
MD5_HashFile( md5, filename, NULL );
pc->value = *(int *)md5;
memcpy( &pc->value, md5, sizeof( pc->value ));
LittleLongSW( pc->value );
if( user_changed_diskfile )
MSG_WriteUBitLong( msg, 0, 32 );

View File

@@ -726,6 +726,7 @@ void SCR_VidInit( void )
// restart console size
Con_VidInit ();
Touch_NotifyResize();
}
/*

View File

@@ -132,6 +132,8 @@ static struct touch_s
int whitetexture;
int joytexture; // touch indicator
qboolean configchanged;
float actual_aspect_ratio; // maximum aspect ratio from launch, or aspect ratio when entering editor
float config_aspect_ratio; // aspect ratio set by command from config or after entering editor
} touch;
// private to the engine flags
@@ -168,13 +170,42 @@ CVAR_DEFINE_AUTO( touch_emulate, "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "emulate
#define B(x) (button->x)
#define SCR_W ((float)refState.width)
#define SCR_H ((float)refState.height)
#define TO_SCRN_Y(x) (refState.height * (x))
#define TO_SCRN_Y(x) (refState.width * (x) * Touch_AspectRatio())
#define TO_SCRN_X(x) (refState.width * (x))
static void IN_TouchCheckCoords( float *x1, float *y1, float *x2, float *y2 );
static void IN_TouchEditClear( void );
static void Touch_InitConfig( void );
void Touch_NotifyResize( void )
{
if( refState.width && refState.height && ( !touch.configchanged || !touch.actual_aspect_ratio ))
{
float aspect_ratio = SCR_H/SCR_W;
if( aspect_ratio < 0.99 && aspect_ratio > touch.actual_aspect_ratio )
touch.actual_aspect_ratio = aspect_ratio;
}
}
static inline float Touch_AspectRatio( void )
{
if( touch.config_aspect_ratio )
return touch.config_aspect_ratio;
else if( touch.actual_aspect_ratio )
return touch.actual_aspect_ratio;
else if( refState.width && refState.height )
return SCR_H/SCR_W;
else
return 9.0f / 16.0f;
}
static void Touch_ConfigAspectRatio_f( void )
{
touch.config_aspect_ratio = Q_atof( Cmd_Argv( 1 ));
}
/*
==========================
Touch_ExportButtonToConfig
@@ -206,7 +237,7 @@ static inline int Touch_ExportButtonToConfig( file_t *f, touch_button_t *button,
if( keepAspect )
{
float aspect = ( B(y2) - B(y1) ) / ( ( B(x2) - B(x1) ) /(SCR_H/SCR_W) );
float aspect = ( B(y2) - B(y1) ) / ( ( B(x2) - B(x1) ) /(Touch_AspectRatio()) );
FS_Printf( f, " %f\n", aspect );
}
else FS_Printf( f, "\n" );
@@ -271,6 +302,8 @@ qboolean Touch_DumpConfig( const char *name, const char *profilename )
FS_Printf( f, "touch_setclientonly 0\n" );
FS_Printf( f, "\n// touch buttons\n" );
FS_Printf( f, "touch_removeall\n" );
FS_Printf( f, "touch_aspectratio %f\n", Touch_AspectRatio());
for( button = touch.list_user.first; button; button = button->next )
{
@@ -376,7 +409,7 @@ static void Touch_GenerateCode_f( void )
if( FBitSet( flags, TOUCH_FL_DEF_HIDE ))
SetBits( flags, TOUCH_FL_HIDE );
aspect = ( B(y2) - B(y1) ) / ( ( B(x2) - B(x1) ) /(SCR_H/SCR_W) );
aspect = ( B(y2) - B(y1) ) / ( ( B(x2) - B(x1) ) /(Touch_AspectRatio()) );
if( memcmp( &c, &B(color), sizeof( rgba_t ) ) )
{
Con_Printf( "unsigned char color[] = { %d, %d, %d, %d };\n", B(color[0]), B(color[1]), B(color[2]), B(color[3]) );
@@ -549,6 +582,7 @@ static void Touch_RemoveAll_f( void )
{
IN_TouchEditClear();
Touch_ClearList( &touch.list_user );
touch.config_aspect_ratio = 0.0f;
}
static void Touch_SetColor( touchbuttonlist_t *list, const char *name, byte *color )
@@ -726,6 +760,8 @@ static void Touch_SetCommand_f( void )
Con_Printf( S_USAGE "touch_setcommand <name> <command>\n" );
}
static void Touch_LoadDefaults_f( void );
static void Touch_ReloadConfig_f( void )
{
touch.state = state_none;
@@ -735,8 +771,15 @@ static void Touch_ReloadConfig_f( void )
touch.selection->finger = -1;
touch.edit = touch.selection = NULL;
touch.resize_finger = touch.move_finger = touch.look_finger = touch.wheel_finger = -1;
Cbuf_AddTextf( "exec %s\n", touch_config_file.string );
if( FS_FileExists( touch_config_file.string, true ) )
{
Cbuf_AddTextf( "exec \"%s\"\n", touch_config_file.string );
}
else
{
Touch_LoadDefaults_f();
touch.configchanged = true;
}
}
static touch_button_t *Touch_AddButton( touchbuttonlist_t *list,
@@ -784,7 +827,7 @@ void Touch_AddClientButton( const char *name, const char *texture, const char *c
IN_TouchCheckCoords( &x1, &y1, &x2, &y2 );
if( round == round_aspect )
{
y2 = y1 + ( x2 - x1 ) * (SCR_W/SCR_H) * aspect;
y2 = y1 + ( x2 - x1 ) / (Touch_AspectRatio()) * aspect;
}
button = Touch_AddButton( &touch.list_user, name, texture, command, x1, y1, x2, y2, color, true );
button->flags |= flags | TOUCH_FL_CLIENT | TOUCH_FL_NOEDIT;
@@ -809,7 +852,7 @@ static void Touch_LoadDefaults_f( void )
if( g_DefaultButtons[i].texturefile[0] == '#' )
y2 = y1 + ( (float)clgame.scrInfo.iCharHeight / (float)clgame.scrInfo.iHeight ) * g_DefaultButtons[i].aspect + touch.swidth*2/SCR_H;
else
y2 = y1 + ( x2 - x1 ) * (SCR_W/SCR_H) * g_DefaultButtons[i].aspect;
y2 = y1 + (( x2 - x1 ) / Touch_AspectRatio()) * g_DefaultButtons[i].aspect;
}
IN_TouchCheckCoords( &x1, &y1, &x2, &y2 );
@@ -817,6 +860,7 @@ static void Touch_LoadDefaults_f( void )
button->flags |= g_DefaultButtons[i].flags;
button->aspect = g_DefaultButtons[i].aspect;
}
touch.configchanged = true;
}
// Add default button from client
@@ -909,7 +953,7 @@ static void Touch_AddButton_f( void )
if( aspect )
{
if( B( texturefile )[0] != '#' )
B( y2 ) = B( y1 ) + ( B( x2 ) - B( x1 )) * ( SCR_W / SCR_H ) * aspect;
B( y2 ) = B( y1 ) + (( B( x2 ) - B( x1 )) / Touch_AspectRatio() ) * aspect;
B( aspect ) = aspect;
}
}
@@ -917,11 +961,39 @@ static void Touch_AddButton_f( void )
static void Touch_EnableEdit_f( void )
{
touch_button_t *button;
float current_ratio = SCR_H/SCR_W;
if( touch.state == state_none )
touch.state = state_edit;
touch.resize_finger = touch.move_finger = touch.look_finger = touch.wheel_finger = -1;
touch.move_button = NULL;
touch.configchanged = true;
/* try determine the best ratio
* User enters editor. Window now have correct size. Need to fix aspect ratio in some cases */
// Case A: no config was loaded, touch was generated with lower height, but window was resized higher, reset it to actual size
if( touch.actual_aspect_ratio > current_ratio )
touch.actual_aspect_ratio = current_ratio;
if( !touch.config_aspect_ratio )
touch.config_aspect_ratio = touch.actual_aspect_ratio;
// Case B: config was loaded, but window may be resized later, so keep y coordinate as is
touch.actual_aspect_ratio = current_ratio;
// convert coordinates to actual aspect ratio after it was updated
if( touch.config_aspect_ratio != touch.actual_aspect_ratio )
{
for( button = touch.list_user.first; button; button = button->next )
{
B(y1) /= touch.actual_aspect_ratio / touch.config_aspect_ratio;
B(y2) /= touch.actual_aspect_ratio / touch.config_aspect_ratio;
// clamp positions to make buttons visible by user
if( B(y2) > 1.0f )
{
B(y1) -= B(y2) - 1.0f;
B(y2) -= B(y2) - 1.0f;
}
}
touch.config_aspect_ratio = touch.actual_aspect_ratio;
}
}
static void Touch_DisableEdit_f( void )
@@ -956,7 +1028,7 @@ static void Touch_DeleteProfile_f( void )
static void Touch_InitEditor( void )
{
float x = 0.1f * (SCR_H/SCR_W);
float x = 0.1f * (Touch_AspectRatio());
float y = 0.05f;
touch_button_t *temp;
rgba_t color;
@@ -1051,6 +1123,7 @@ void Touch_Init( void )
Cmd_AddRestrictedCommand( "touch_generate_code", Touch_GenerateCode_f, "create code sample for mobility API" );
Cmd_AddCommand( "touch_fade", Touch_Fade_f, "start fade animation for selected buttons" );
Cmd_AddRestrictedCommand( "touch_toggleselection", Touch_ToggleSelection_f, "toggle vidibility on selected button in editor" );
Cmd_AddRestrictedCommand( "touch_aspectratio", Touch_ConfigAspectRatio_f, "set current aspect ratio" );
// not saved, just runtime state for scripting
Cvar_RegisterVariable( &touch_in_menu );
@@ -1087,7 +1160,7 @@ void Touch_Init( void )
#if SDL_VERSION_ATLEAST( 2, 0, 10 )
SDL_SetHint( SDL_HINT_MOUSE_TOUCH_EVENTS, "0" );
SDL_SetHint( SDL_HINT_TOUCH_MOUSE_EVENTS, "0" );
#else
#elif defined(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH)
SDL_SetHint( SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1" );
#endif
@@ -1170,9 +1243,9 @@ static void Touch_DrawTexture ( float x1, float y1, float x2, float y2, int text
}
#define GRID_COUNT_X ((int)touch_grid_count.value)
#define GRID_COUNT_Y (((int)touch_grid_count.value) * SCR_H / SCR_W)
#define GRID_COUNT_Y (((int)touch_grid_count.value) * Touch_AspectRatio())
#define GRID_X (1.0f/GRID_COUNT_X)
#define GRID_Y (SCR_W/SCR_H/GRID_COUNT_X)
#define GRID_Y (1.0f/Touch_AspectRatio()/GRID_COUNT_X)
#define GRID_ROUND_X(x) ((float)round( x * GRID_COUNT_X ) / GRID_COUNT_X)
#define GRID_ROUND_Y(x) ((float)round( x * GRID_COUNT_Y ) / GRID_COUNT_Y)
@@ -1250,7 +1323,7 @@ static float Touch_DrawText( float x1, float y1, float x2, float y2, const char
{
while( *s && ( *s != '\n' ) && ( *s != ';' ) && ( x1 < maxx ) )
x1 += Touch_DrawCharacter( x1, y1, *s++, size );
y1 += cls.creditsFont.charHeight / 1024.f * size / SCR_H * SCR_W;
y1 += cls.creditsFont.charHeight / 1024.f * size / Touch_AspectRatio();
if( y1 >= maxy )
break;
@@ -1357,11 +1430,12 @@ void Touch_Draw( void )
if( !touch.initialized || ( !touch_enable.value && !touch.clientonly ))
return;
Touch_InitConfig();
if( cls.key_dest != key_game && !touch_in_menu.value )
return;
Touch_InitConfig();
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
if( touch.state >= state_edit && touch_grid_enable.value )
@@ -1948,6 +2022,8 @@ static int Touch_ControlsEvent( touchEventType type, int fingerID, float x, floa
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy )
{
y *= SCR_H/SCR_W/Touch_AspectRatio();
// Con_Printf("%f %f\n", TO_SCRN_X(x), TO_SCRN_Y(y));
// simulate menu mouse click
if( cls.key_dest != key_game && !touch_in_menu.value )
{

View File

@@ -172,6 +172,8 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
{
if( newstate == oldstate )
return;
if( m_ignore.value )
return;
// since SetCursorType controls cursor visibility
// execute it first, and then check mouse grab state
@@ -212,6 +214,9 @@ void IN_CheckMouseState( qboolean active )
qboolean useRawInput = true; // always use SDL code
#endif
if( m_ignore.value )
return;
if( active && useRawInput && !host.mouse_visible && cls.state == ca_active )
{
if( !s_bRawInput )

View File

@@ -75,6 +75,7 @@ void Touch_ResetDefaultButtons( void );
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy );
void Touch_KeyEvent( int key, int down );
qboolean Touch_WantVisibleCursor( void );
void Touch_NotifyResize( void );
//
// in_joy.c

View File

@@ -1025,12 +1025,21 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
host.rootdir[0] = 0;
}
#elif (XASH_SDL == 2) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2
char *szBasePath;
if( !( szBasePath = SDL_GetBasePath() ) )
char *szBasePath = SDL_GetBasePath();
if( szBasePath )
{
Q_strncpy( host.rootdir, szBasePath, sizeof( host.rootdir ));
SDL_free( szBasePath );
}
else
{
#if XASH_POSIX || XASH_WIN32
if( !getcwd( host.rootdir, sizeof( host.rootdir )))
Sys_Error( "couldn't determine current directory: %s, getcwd: %s", SDL_GetError(), strerror( errno ));
#else
Sys_Error( "couldn't determine current directory: %s", SDL_GetError() );
Q_strncpy( host.rootdir, szBasePath, sizeof( host.rootdir ));
SDL_free( szBasePath );
#endif
}
#else
if( !getcwd( host.rootdir, sizeof( host.rootdir )))
{

View File

@@ -284,8 +284,10 @@ int Image_ComparePalette( const byte *pal )
void Image_SetPalette( const byte *pal, uint *d_table )
{
byte rgba[4];
uint uirgba; // TODO: palette looks byte-swapped on big-endian
int i;
// setup palette
switch( image.d_rendermode )
{
@@ -296,7 +298,8 @@ void Image_SetPalette( const byte *pal, uint *d_table )
rgba[1] = pal[i*3+1];
rgba[2] = pal[i*3+2];
rgba[3] = 0xFF;
d_table[i] = *(uint *)rgba;
memcpy( &uirgba, rgba, sizeof( uirgba ));
d_table[i] = uirgba;
}
break;
case LUMP_GRADIENT:
@@ -306,7 +309,8 @@ void Image_SetPalette( const byte *pal, uint *d_table )
rgba[1] = pal[766];
rgba[2] = pal[767];
rgba[3] = i;
d_table[i] = *(uint *)rgba;
memcpy( &uirgba, rgba, sizeof( uirgba ));
d_table[i] = uirgba;
}
break;
case LUMP_MASKED:
@@ -316,7 +320,8 @@ void Image_SetPalette( const byte *pal, uint *d_table )
rgba[1] = pal[i*3+1];
rgba[2] = pal[i*3+2];
rgba[3] = 0xFF;
d_table[i] = *(uint *)rgba;
memcpy( &uirgba, rgba, sizeof( uirgba ));
d_table[i] = uirgba;
}
d_table[255] = 0;
break;
@@ -327,7 +332,8 @@ void Image_SetPalette( const byte *pal, uint *d_table )
rgba[1] = pal[i*4+1];
rgba[2] = pal[i*4+2];
rgba[3] = pal[i*4+3];
d_table[i] = *(uint *)rgba;
memcpy( &uirgba, rgba, sizeof( uirgba ));
d_table[i] = uirgba;
}
break;
}

View File

@@ -419,5 +419,6 @@ void NET_InitMasters( void )
// keep main master always there
NET_AddMaster( MASTERSERVER_ADR, false );
NET_AddMaster( MASTERSERVER_ADR_TEST, false );
NET_LoadMasters( );
}

View File

@@ -274,8 +274,8 @@ static void NET_NetadrToSockadr( netadr_t *a, struct sockaddr_storage *s )
else if( a->type == NA_IP )
{
((struct sockaddr_in *)s)->sin_family = AF_INET;
((struct sockaddr_in *)s)->sin_addr.s_addr = *(uint32_t *)&a->ip;
((struct sockaddr_in *)s)->sin_port = a->port;
((struct sockaddr_in *)s)->sin_addr.s_addr = a->ip4;
}
else if( a->type6 == NA_IP6 )
{
@@ -314,7 +314,7 @@ static void NET_SockadrToNetadr( const struct sockaddr_storage *s, netadr_t *a )
if( s->ss_family == AF_INET )
{
a->type = NA_IP;
*(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
a->ip4 = ((struct sockaddr_in *)s)->sin_addr.s_addr;
a->port = ((struct sockaddr_in *)s)->sin_port;
}
else if( s->ss_family == AF_INET6 )

View File

@@ -70,6 +70,7 @@ GNU General Public License for more details.
#define NET_MAX_MESSAGE PAD_NUMBER(( NET_MAX_PAYLOAD + HEADER_BYTES ), 16 )
#define MASTERSERVER_ADR "mentality.rip:27010"
#define MASTERSERVER_ADR_TEST "mentality.rip:27011"
#define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0"
#define PORT_MASTER 27010

View File

@@ -438,6 +438,25 @@ GL_GetProcAddress
void *GL_GetProcAddress( const char *name )
{
void *func = SDL_GL_GetProcAddress( name );
#if !SDL_VERSION_ATLEAST( 2, 0, 6 ) && XASH_POSIX
if( !func && Sys_CheckParm( "-egl" ))
{
/*
* SDL2 has broken SDL_GL_GetProcAddress until this commit if using egl:
* https://github.com/libsdl-org/SDL/commit/466ba57d42d244e80357e9ad3011c50af30ed225
* so call eglGetProcAddress directly
* */
static void *(*peglGetProcAddress)( const char * );
if( !peglGetProcAddress )
{
void *lib = dlopen( "libEGL.so", RTLD_NOW );
if( lib )
*(void**)&peglGetProcAddress = dlsym( lib, "eglGetProcAddress" );
}
if( peglGetProcAddress )
func = peglGetProcAddress( name );
}
#endif
#if XASH_PSVITA
// try to find in main module
@@ -626,9 +645,9 @@ void VID_RestoreScreenResolution( void )
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
}
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
static void VID_SetWindowIcon( SDL_Window *hWnd )
{
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
rgbdata_t *icon = NULL;
char iconpath[MAX_STRING];
const char *localIcoPath;
@@ -666,8 +685,8 @@ static void VID_SetWindowIcon( SDL_Window *hWnd )
#if XASH_WIN32 // ICO support only for Win32
WIN_SetWindowIcon( LoadIcon( host.hInst, MAKEINTRESOURCE( 101 )));
#endif
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
}
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
static qboolean VID_CreateWindowWithSafeGL( const char *wndname, int xpos, int ypos, int w, int h, uint32_t flags )
{
@@ -785,6 +804,7 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
else VID_RestoreScreenResolution();
#endif
VID_SetWindowIcon( host.hWnd );
SDL_ShowWindow( host.hWnd );
if( glw_state.software )
@@ -996,8 +1016,12 @@ qboolean R_Init_Video( const int type )
refState.desktopBitsPixel = 16;
#endif
#ifdef SDL_HINT_QTWAYLAND_WINDOW_FLAGS
SDL_SetHint( SDL_HINT_QTWAYLAND_WINDOW_FLAGS, "OverridesSystemGestures" );
#endif
#ifdef SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION
SDL_SetHint( SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION, "landscape" );
#endif
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) && !XASH_WIN32
SDL_SetHint( "SDL_VIDEO_X11_XRANDR", "1" );

View File

@@ -121,8 +121,10 @@ void SV_ParseConsistencyResponse( sv_client_t *cl, sizebuf_t *msg )
{
value = MSG_ReadUBitLong( msg, 32 );
LittleLongSW( value );
// will be compare only first 4 bytes
if( value != *(int *)r->rgucMD5_hash )
if( memcmp( &value, r->rgucMD5_hash, 4 ))
badresindex = idx + 1;
}
else

View File

@@ -549,24 +549,54 @@ qboolean GL_CheckExtension( const char *name, const dllfunc_t *funcs, const char
for( func = funcs; func && func->name; func++ )
{
// functions are cleared before all the extensions are evaluated
if((*func->func = (void *)gEngfuncs.GL_GetProcAddress( func->name )) == NULL )
if(( *func->func = (void *)gEngfuncs.GL_GetProcAddress( func->name )) == NULL )
{
string name;
char *end;
size_t i = 0;
#ifdef XASH_GLES
const char *suffixes[] = { "", "EXT", "OES" };
#else
const char *suffixes[] = { "", "EXT" };
#endif
// HACK: fix ARB names
char *str = Q_strstr( func->name, "ARB" );
if(str)
Q_strncpy( name, func->name, sizeof( name ));
if(( end = Q_strstr( name, "ARB" )))
{
string name;
Q_strncpy( name, func->name, MAX_STRING );
name[str - func->name] = '\0';
*func->func = gEngfuncs.GL_GetProcAddress( name );
if( !*func->func )
GL_SetExtension( r_ext, false );
*end = '\0';
}
else
// one or more functions are invalid, extension will be disabled
else // I need Q_strstrnul
{
end = name + Q_strlen( name );
i++; // skip empty suffix
}
for( ; i < sizeof( suffixes ) / sizeof( suffixes[0] ); i++ )
{
void *f;
Q_strncat( name, suffixes[i], sizeof( name ));
if(( f = gEngfuncs.GL_GetProcAddress( name )))
{
// GL_GetProcAddress prints errors about missing functions, so tell user that we found it with different name
gEngfuncs.Con_Printf( S_NOTE "found %s\n", name );
*func->func = f;
break;
}
else
{
*end = '\0'; // cut suffix, try next
}
}
// not found...
if( i == sizeof( suffixes ) / sizeof( suffixes[0] ))
{
GL_SetExtension( r_ext, false );
}
}
}
#endif