mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 03:24:56 +08:00
platform: PSP volatile(P5) memory allocator
This commit is contained in:
@@ -393,6 +393,10 @@ static ref_api_t gEngfuncs =
|
||||
pfnDrawNormalTriangles,
|
||||
pfnDrawTransparentTriangles,
|
||||
&clgame.drawFuncs
|
||||
#if XASH_PSP
|
||||
,P5Ram_Alloc,
|
||||
P5Ram_Free
|
||||
#endif
|
||||
};
|
||||
|
||||
static void R_UnloadProgs( void )
|
||||
|
||||
@@ -42,6 +42,8 @@ void Platform_MessageBox( const char *title, const char *message, qboolean paren
|
||||
void Platform_ReadCmd( const char *fname, int *argc, char **argv );
|
||||
SceUID Platform_LoadModule( const char *filename, int mpid, SceSize argsize, void *argp );
|
||||
int Platform_UnloadModule( SceUID modid, int *sce_code );
|
||||
|
||||
#include "psp/p5ram_psp.h"
|
||||
#endif
|
||||
#if XASH_ANDROID
|
||||
const char *Android_GetAndroidID( void );
|
||||
|
||||
163
engine/platform/psp/p5ram_psp.c
Normal file
163
engine/platform/psp/p5ram_psp.c
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
p5ram_psp.c - PSP P5 memory allocator
|
||||
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 <pspkernel.h>
|
||||
#include <psppower.h>
|
||||
#include <pspsuspend.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "p5ram_psp.h"
|
||||
|
||||
#define P5RAM_ALIGN( x, a ) ((( x ) + (( typeof( x ))( a ) - 1 )) & ~( typeof( x )( a ) - 1 ))
|
||||
|
||||
#define P5RAM_CHECK( addr ) ((( unsigned int )addr >= ( unsigned int )p5ram_addr) && (( unsigned int )addr < ( unsigned int )p5ram_addr + p5ram_size))
|
||||
|
||||
#define P5RAM_FLAG_INIT 0x01
|
||||
#define P5RAM_FLAG_SUSPENDED 0x02
|
||||
|
||||
typedef struct p5ram_info_s
|
||||
{
|
||||
SceUID uid;
|
||||
size_t size;
|
||||
struct p5ram_info_s *next;
|
||||
}p5ram_info_t;
|
||||
|
||||
static unsigned char p5ram_flags = 0x00;
|
||||
static p5ram_info_t *p5ram_poolchain = NULL;
|
||||
static void *p5ram_addr;
|
||||
static unsigned int p5ram_size;
|
||||
|
||||
int P5Ram_Init( void )
|
||||
{
|
||||
int result;
|
||||
|
||||
if( p5ram_flags & P5RAM_FLAG_INIT )
|
||||
return -1;
|
||||
|
||||
result = sceKernelVolatileMemLock( 0, &p5ram_addr, &p5ram_size );
|
||||
if( result == 0 )
|
||||
p5ram_flags |= P5RAM_FLAG_INIT;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void *P5Ram_Alloc( size_t size )
|
||||
{
|
||||
SceUID uid;
|
||||
void *ptr;
|
||||
|
||||
if(!( p5ram_flags & P5RAM_FLAG_INIT ))
|
||||
return NULL;
|
||||
|
||||
uid = sceKernelAllocPartitionMemory( 5, "USER P5", PSP_SMEM_Low, size + /*sizeof( p5ram_info_t )*/64, NULL );
|
||||
if( uid < 0 ) return NULL;
|
||||
|
||||
ptr = sceKernelGetBlockHeadAddr( uid );
|
||||
(( p5ram_info_t* )ptr )->uid = uid;
|
||||
(( p5ram_info_t* )ptr )->size = size;
|
||||
(( p5ram_info_t* )ptr )->next = p5ram_poolchain;
|
||||
|
||||
p5ram_poolchain = ptr;
|
||||
|
||||
return ptr + /*sizeof( p5ram_info_t )*/64;
|
||||
}
|
||||
|
||||
void P5Ram_Free( void *ptr )
|
||||
{
|
||||
p5ram_info_t *info, *next_ptr;
|
||||
|
||||
if( !( p5ram_flags & P5RAM_FLAG_INIT ) || ptr == NULL ) return;
|
||||
|
||||
info = ( p5ram_info_t* )( ptr - /*sizeof( p5ram_info_t )*/64);
|
||||
|
||||
if( info == p5ram_poolchain )
|
||||
{
|
||||
p5ram_poolchain = p5ram_poolchain->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
next_ptr = p5ram_poolchain;
|
||||
while( next_ptr )
|
||||
{
|
||||
if( next_ptr->next == info )
|
||||
{
|
||||
next_ptr->next = info->next;
|
||||
break;
|
||||
}
|
||||
next_ptr = next_ptr->next;
|
||||
}
|
||||
}
|
||||
|
||||
sceKernelFreePartitionMemory( info->uid );
|
||||
}
|
||||
|
||||
void P5Ram_FreeAll( void )
|
||||
{
|
||||
p5ram_info_t *next_ptr;
|
||||
|
||||
while( p5ram_poolchain )
|
||||
{
|
||||
next_ptr = p5ram_poolchain->next;
|
||||
sceKernelFreePartitionMemory( p5ram_poolchain->uid );
|
||||
p5ram_poolchain = next_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
void P5Ram_Shutdown( void )
|
||||
{
|
||||
if( !( p5ram_flags & P5RAM_FLAG_INIT ))
|
||||
return;
|
||||
|
||||
P5Ram_FreeAll();
|
||||
sceKernelVolatileMemUnlock( 0 );
|
||||
|
||||
p5ram_flags &= ~P5RAM_FLAG_INIT;
|
||||
}
|
||||
|
||||
void P5Ram_PowerCallback( int count, int arg, void *common )
|
||||
{
|
||||
if( !( p5ram_flags & ( P5RAM_FLAG_INIT | P5RAM_FLAG_SUSPENDED )))
|
||||
return;
|
||||
|
||||
if ( arg & PSP_POWER_CB_POWER_SWITCH || arg & PSP_POWER_CB_SUSPENDING )
|
||||
{
|
||||
P5Ram_Shutdown();
|
||||
p5ram_flags |= P5RAM_FLAG_SUSPENDED;
|
||||
}
|
||||
else if ( arg & PSP_POWER_CB_RESUMING )
|
||||
{
|
||||
}
|
||||
else if ( arg & PSP_POWER_CB_RESUME_COMPLETE )
|
||||
{
|
||||
P5Ram_Init();
|
||||
p5ram_flags &= ~P5RAM_FLAG_SUSPENDED;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef P5RAM_DEBUG
|
||||
void P5Ram_Print( void )
|
||||
{
|
||||
p5ram_info_t *next_ptr;
|
||||
|
||||
printf("+++++++++++++++++++++++++++++\n");
|
||||
next_ptr = p5ram_poolchain;
|
||||
while( next_ptr )
|
||||
{
|
||||
printf("P5 ALLOC [ 0x%08X 0x%08X 0x%08X 0x%08X ]\n", next_ptr, next_ptr->uid, next_ptr->size, next_ptr->next );
|
||||
next_ptr = next_ptr->next;
|
||||
}
|
||||
printf("+++++++++++++++++++++++++++++\n");
|
||||
}
|
||||
#endif
|
||||
38
engine/platform/psp/p5ram_psp.h
Normal file
38
engine/platform/psp/p5ram_psp.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
p5ram_psp.h - PSP P5 memory allocator header
|
||||
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.
|
||||
*/
|
||||
#ifndef P5RAM_PSP_H
|
||||
#define P5RAM_PSP_H
|
||||
|
||||
//#define P5RAM_DEBUG
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
int P5Ram_Init( void );
|
||||
void *P5Ram_Alloc( size_t size );
|
||||
void P5Ram_Free( void *ptr );
|
||||
void P5Ram_FreeAll( void );
|
||||
void P5Ram_Shutdown( void );
|
||||
void P5Ram_PowerCallback( int count, int arg, void *common );
|
||||
#ifdef P5RAM_DEBUG
|
||||
void P5Ram_Print( void );
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // P5RAM_PSP_H
|
||||
@@ -30,31 +30,39 @@ PSP_MAIN_THREAD_ATTR( PSP_THREAD_ATTR_USER | PSP_THREAD_ATTR_VFPU );
|
||||
PSP_MAIN_THREAD_STACK_SIZE_KB( 512 );
|
||||
PSP_HEAP_SIZE_KB( -3 * 1024 ); /* 3 MB for prx modules */
|
||||
|
||||
/* Exit callback */
|
||||
static int exit_callback( int arg1, int arg2, void *common )
|
||||
static int Platform_ExitCallback( int count, int arg, void *common )
|
||||
{
|
||||
host.crashed = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Callback thread */
|
||||
static int CallbackThread( SceSize args, void *argp )
|
||||
static int Platform_PowerCallback( int count, int arg, void *common )
|
||||
{
|
||||
P5Ram_PowerCallback( count, arg, common );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Platform_CallbackThread( SceSize args, void *argp )
|
||||
{
|
||||
int cbid;
|
||||
|
||||
cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
|
||||
sceKernelRegisterExitCallback(cbid);
|
||||
cbid = sceKernelCreateCallback( "Exit Callback", Platform_ExitCallback, NULL );
|
||||
sceKernelRegisterExitCallback( cbid );
|
||||
|
||||
cbid = sceKernelCreateCallback( "Power Callback", Platform_PowerCallback, NULL );
|
||||
scePowerRegisterCallback( 0, cbid );
|
||||
|
||||
sceKernelSleepThreadCB();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sets up the callback thread and returns its thread id */
|
||||
static int SetupCallbacks( void )
|
||||
static int Platform_SetupCallbacks( void )
|
||||
{
|
||||
int thid = 0;
|
||||
|
||||
thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
|
||||
thid = sceKernelCreateThread("update_thread", Platform_CallbackThread, 0x11, 0xFA0, 0, 0);
|
||||
if(thid >= 0)
|
||||
{
|
||||
sceKernelStartThread(thid, 0, 0);
|
||||
@@ -259,7 +267,7 @@ int Platform_UnloadModule( SceUID modid, int *sce_code )
|
||||
*sce_code = sceKernelUnloadModule( modid );
|
||||
return ( ( ( *sce_code ) < 0 ) ? -2 : 0 );
|
||||
}
|
||||
|
||||
#include "vfs_psp.h"
|
||||
void Platform_Init( void )
|
||||
{
|
||||
SceUID kamID;
|
||||
@@ -269,7 +277,7 @@ void Platform_Init( void )
|
||||
pspSdkDisableFPUExceptions();
|
||||
|
||||
// exit callback thread
|
||||
SetupCallbacks();
|
||||
Platform_SetupCallbacks();
|
||||
|
||||
// set max cpu/gpu frequency
|
||||
scePowerSetClockFrequency( 333, 333, 166 );
|
||||
@@ -283,10 +291,14 @@ void Platform_Init( void )
|
||||
result = kaGeEdramSetSize( result );
|
||||
Platform_UnloadModule( kamID, &result );
|
||||
}
|
||||
|
||||
// P5 Ram init
|
||||
P5Ram_Init();
|
||||
}
|
||||
|
||||
void Platform_Shutdown( void )
|
||||
{
|
||||
P5Ram_Shutdown();
|
||||
#if XASH_PROFILING
|
||||
gprof_cleanup();
|
||||
#endif
|
||||
|
||||
@@ -431,6 +431,10 @@ typedef struct ref_api_s
|
||||
void (*pfnDrawNormalTriangles)( void );
|
||||
void (*pfnDrawTransparentTriangles)( void );
|
||||
render_interface_t *drawFuncs;
|
||||
#if XASH_PSP
|
||||
void *(*P5Ram_Alloc)( size_t size );
|
||||
void (*P5Ram_Free)( void *ptr );
|
||||
#endif
|
||||
} ref_api_t;
|
||||
|
||||
struct mip_s;
|
||||
|
||||
@@ -291,7 +291,11 @@ static void InitEntityTable( SAVERESTOREDATA *pSaveData, int entityCount )
|
||||
ENTITYTABLE *pTable;
|
||||
int i;
|
||||
|
||||
#if XASH_PSP
|
||||
pSaveData->pTable = P5Ram_Alloc( sizeof( ENTITYTABLE ) * entityCount );
|
||||
#else
|
||||
pSaveData->pTable = Mem_Calloc( host.mempool, sizeof( ENTITYTABLE ) * entityCount );
|
||||
#endif
|
||||
pSaveData->tableCount = entityCount;
|
||||
|
||||
// setup entitytable
|
||||
@@ -607,8 +611,13 @@ static SAVERESTOREDATA *SaveInit( int size, int tokenCount )
|
||||
{
|
||||
SAVERESTOREDATA *pSaveData;
|
||||
|
||||
#if XASH_PSP
|
||||
pSaveData = P5Ram_Alloc( sizeof( SAVERESTOREDATA ) + size );
|
||||
pSaveData->pTokens = (char **)P5Ram_Alloc( tokenCount * sizeof( char* ));
|
||||
#else
|
||||
pSaveData = Mem_Calloc( host.mempool, sizeof( SAVERESTOREDATA ) + size );
|
||||
pSaveData->pTokens = (char **)Mem_Calloc( host.mempool, tokenCount * sizeof( char* ));
|
||||
#endif
|
||||
pSaveData->tokenCount = tokenCount;
|
||||
|
||||
pSaveData->pBaseData = (char *)(pSaveData + 1); // skip the save structure);
|
||||
@@ -657,20 +666,32 @@ static void SaveFinish( SAVERESTOREDATA *pSaveData )
|
||||
|
||||
if( pSaveData->pTokens )
|
||||
{
|
||||
#if XASH_PSP
|
||||
P5Ram_Free( pSaveData->pTokens );
|
||||
#else
|
||||
Mem_Free( pSaveData->pTokens );
|
||||
#endif
|
||||
pSaveData->pTokens = NULL;
|
||||
pSaveData->tokenCount = 0;
|
||||
}
|
||||
|
||||
if( pSaveData->pTable )
|
||||
{
|
||||
#if XASH_PSP
|
||||
P5Ram_Free( pSaveData->pTable );
|
||||
#else
|
||||
Mem_Free( pSaveData->pTable );
|
||||
#endif
|
||||
pSaveData->pTable = NULL;
|
||||
pSaveData->tableCount = 0;
|
||||
}
|
||||
|
||||
svgame.globals->pSaveData = NULL;
|
||||
#if XASH_PSP
|
||||
P5Ram_Free( pSaveData );
|
||||
#else
|
||||
Mem_Free( pSaveData );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2246,7 +2267,11 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
|
||||
// allocate a table for the strings, and parse the table
|
||||
if( tokenSize > 0 )
|
||||
{
|
||||
#if XASH_PSP
|
||||
pTokenList = P5Ram_Alloc( tokenCount * sizeof( char* ));
|
||||
#else
|
||||
pTokenList = Mem_Calloc( host.mempool, tokenCount * sizeof( char* ));
|
||||
#endif
|
||||
|
||||
// make sure the token strings pointed to by the pToken hashtable.
|
||||
for( i = 0; i < tokenCount; i++ )
|
||||
@@ -2274,8 +2299,13 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
|
||||
if( Q_stricmp( pFieldName, "GameHeader" ))
|
||||
{
|
||||
Q_strncpy( comment, "<missing GameHeader>", MAX_STRING );
|
||||
#if XASH_PSP
|
||||
if( pTokenList ) P5Ram_Free( pTokenList );
|
||||
if( pSaveData ) P5Ram_Free( pSaveData );
|
||||
#else
|
||||
if( pTokenList ) Mem_Free( pTokenList );
|
||||
if( pSaveData ) Mem_Free( pSaveData );
|
||||
#endif
|
||||
FS_Close( f );
|
||||
return 0;
|
||||
}
|
||||
@@ -2325,8 +2355,13 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
|
||||
}
|
||||
|
||||
// delete the string table we allocated
|
||||
#if XASH_PSP
|
||||
if( pTokenList ) P5Ram_Free( pTokenList );
|
||||
if( pSaveData ) P5Ram_Free( pSaveData );
|
||||
#else
|
||||
if( pTokenList ) Mem_Free( pTokenList );
|
||||
if( pSaveData ) Mem_Free( pSaveData );
|
||||
#endif
|
||||
FS_Close( f );
|
||||
|
||||
// at least mapname should be filled
|
||||
|
||||
@@ -20,10 +20,10 @@ GNU General Public License for more details.
|
||||
|
||||
#define TEXTURES_HASH_SIZE (MAX_TEXTURES >> 2)
|
||||
|
||||
static gl_texture_t gl_textures[MAX_TEXTURES];
|
||||
static gl_texture_t gl_textures[MAX_TEXTURES];
|
||||
static gl_texture_t* gl_texturesHashTable[TEXTURES_HASH_SIZE];
|
||||
static uint gl_numTextures;
|
||||
static byte *palette_332 = NULL;
|
||||
static uint gl_numTextures;
|
||||
static byte* gl_palette_332 = NULL;
|
||||
|
||||
/*
|
||||
num_colors = PALETTE_BLOCKS x 16 (16-bit CLUT)
|
||||
@@ -65,7 +65,7 @@ GL_Bind
|
||||
void GL_Bind( GLint tmu, GLenum texnum )
|
||||
{
|
||||
gl_texture_t *texture;
|
||||
int i, offset, width, height;
|
||||
int i, offset, width, height;
|
||||
|
||||
// missed or invalid texture?
|
||||
if( texnum <= 0 || texnum >= MAX_TEXTURES )
|
||||
@@ -84,7 +84,7 @@ void GL_Bind( GLint tmu, GLenum texnum )
|
||||
if( texture->format == GU_PSM_T8 )
|
||||
{
|
||||
sceGuClutMode( PALETTE_FORMAT, 0, 0xff, 0 );
|
||||
sceGuClutLoad( PALETTE_BLOCKS, texture->dstPalette ? texture->dstPalette : palette_332 );
|
||||
sceGuClutLoad( PALETTE_BLOCKS, texture->dstPalette );
|
||||
}
|
||||
|
||||
// Set texture parameters
|
||||
@@ -108,7 +108,7 @@ void GL_Bind( GLint tmu, GLenum texnum )
|
||||
sceGuTexFilter( GU_LINEAR, GU_LINEAR );
|
||||
}
|
||||
|
||||
if( FBitSet( texture->flags, TF_CLAMP ) || FBitSet( texture->flags, TF_BORDER ) )
|
||||
if( FBitSet( texture->flags, TF_CLAMP ) || FBitSet( texture->flags, TF_BORDER ))
|
||||
sceGuTexWrap( GU_CLAMP, GU_CLAMP );
|
||||
else
|
||||
sceGuTexWrap( GU_REPEAT, GU_REPEAT );
|
||||
@@ -122,8 +122,8 @@ void GL_Bind( GLint tmu, GLenum texnum )
|
||||
offset = texture->width * texture->height * texture->bpp;
|
||||
for ( i = 1; i < texture->numMips; i++ )
|
||||
{
|
||||
width = Q_max( TEXTURE_SIZE_MIN, ( texture->width >> i ) );
|
||||
height = Q_max( TEXTURE_SIZE_MIN, ( texture->height >> i ) );
|
||||
width = Q_max( TEXTURE_SIZE_MIN, ( texture->width >> i ));
|
||||
height = Q_max( TEXTURE_SIZE_MIN, ( texture->height >> i ));
|
||||
sceGuTexImage( i, width, height, width, &texture->dstTexture[offset] );
|
||||
offset += width * height * texture->bpp;
|
||||
}
|
||||
@@ -138,7 +138,7 @@ GL_CalcImageSize
|
||||
*/
|
||||
static size_t GL_CalcImageSize( pixformat_t format, int width, int height, int depth )
|
||||
{
|
||||
size_t size = 0;
|
||||
size_t size = 0;
|
||||
|
||||
// check the depth error
|
||||
depth = Q_max( 1, depth );
|
||||
@@ -184,14 +184,14 @@ GL_CalcTextureSize
|
||||
*/
|
||||
static size_t GL_CalcTextureSize( int format, int width, int height, byte *outBpp )
|
||||
{
|
||||
size_t size = 0;
|
||||
byte bpp = 0;
|
||||
size_t size = 0;
|
||||
byte bpp = 0;
|
||||
|
||||
switch( format )
|
||||
{
|
||||
case GU_PSM_T4:
|
||||
case GU_PSM_DXT1:
|
||||
size = ( ( width * height ) >> 1 );
|
||||
size = (( width * height ) >> 1 );
|
||||
break;
|
||||
case GU_PSM_T8:
|
||||
case GU_PSM_DXT3:
|
||||
@@ -223,8 +223,8 @@ static size_t GL_CalcTextureSize( int format, int width, int height, byte *outBp
|
||||
|
||||
static int GL_CalcMipmapCount( gl_texture_t *tex, qboolean haveBuffer, size_t *mipSize )
|
||||
{
|
||||
int width, height;
|
||||
int mipCount;
|
||||
int width, height;
|
||||
int mipCount;
|
||||
|
||||
Assert( tex != NULL );
|
||||
|
||||
@@ -233,19 +233,19 @@ static int GL_CalcMipmapCount( gl_texture_t *tex, qboolean haveBuffer, size_t *m
|
||||
|
||||
#if 0
|
||||
// brush model only
|
||||
if( !FBitSet( tex->flags, TF_ALLOW_EMBOSS ) )
|
||||
if( !FBitSet( tex->flags, TF_ALLOW_EMBOSS ))
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
// generate mip-levels by user request
|
||||
if( FBitSet( tex->flags, TF_NOMIPMAP ) )
|
||||
if( FBitSet( tex->flags, TF_NOMIPMAP ))
|
||||
return 1;
|
||||
|
||||
// 8 levels - 7 + 1 base
|
||||
for( mipCount = 1; mipCount < 8; mipCount++ )
|
||||
{
|
||||
width = Q_max( TEXTURE_SIZE_MIN, ( tex->width >> mipCount ) );
|
||||
height = Q_max( TEXTURE_SIZE_MIN, ( tex->height >> mipCount ) );
|
||||
width = Q_max( TEXTURE_SIZE_MIN, ( tex->width >> mipCount ));
|
||||
height = Q_max( TEXTURE_SIZE_MIN, ( tex->height >> mipCount ));
|
||||
|
||||
if( width == TEXTURE_SIZE_MIN && height == TEXTURE_SIZE_MIN )
|
||||
break;
|
||||
@@ -264,9 +264,9 @@ GL_SetTextureDimensions
|
||||
*/
|
||||
static void GL_SetTextureDimensions( gl_texture_t *tex, int width, int height )
|
||||
{
|
||||
int maxTextureSize = glConfig.max_texture_size;
|
||||
int step = (int)gl_round_down->value;
|
||||
int scaled_width, scaled_height;
|
||||
int maxTextureSize = glConfig.max_texture_size;
|
||||
int step = (int)gl_round_down->value;
|
||||
int scaled_width, scaled_height;
|
||||
|
||||
Assert( tex != NULL );
|
||||
|
||||
@@ -276,12 +276,12 @@ static void GL_SetTextureDimensions( gl_texture_t *tex, int width, int height )
|
||||
|
||||
for( scaled_width = 1; scaled_width < width; scaled_width <<= 1 );
|
||||
|
||||
if( step > 0 && width < scaled_width && ( step == 1 || ( scaled_width - width ) > ( scaled_width >> step ) ) )
|
||||
if( step > 0 && width < scaled_width && ( step == 1 || ( scaled_width - width ) > ( scaled_width >> step )))
|
||||
scaled_width >>= 1;
|
||||
|
||||
for( scaled_height = 1; scaled_height < height; scaled_height <<= 1 );
|
||||
|
||||
if( step > 0 && height < scaled_height && ( step == 1 || ( scaled_height - height ) > ( scaled_height >> step ) ) )
|
||||
if( step > 0 && height < scaled_height && ( step == 1 || ( scaled_height - height ) > ( scaled_height >> step )))
|
||||
scaled_height >>= 1;
|
||||
|
||||
width = scaled_width;
|
||||
@@ -342,7 +342,7 @@ static void GL_SetTextureFormat( gl_texture_t *tex, pixformat_t format, int chan
|
||||
case PF_BGRA_32:
|
||||
case PF_RGB_24:
|
||||
case PF_BGR_24:
|
||||
if ( IsLightMap( tex ) )
|
||||
if ( IsLightMap( tex ))
|
||||
tex->format = GU_PSM_8888;
|
||||
else if( haveAlpha )
|
||||
tex->format = GU_PSM_4444;
|
||||
@@ -464,7 +464,7 @@ void GL_ResampleTexture8(const byte *source, int inWidth, int inHeight, byte *de
|
||||
byte *out;
|
||||
const byte *inrow;
|
||||
uint frac;
|
||||
int i, j;
|
||||
int i, j;
|
||||
|
||||
if( !source )
|
||||
return;
|
||||
@@ -659,7 +659,7 @@ PC_SWF - Xash3d Software format mask
|
||||
void GL_PixelConverter( byte *dst, const byte *src, int size, int inFormat, int outFormat )
|
||||
{
|
||||
int i;
|
||||
byte color[4];
|
||||
byte color[4];
|
||||
|
||||
color[0] = color[1] = color[2] = color[3] = 0xff;
|
||||
|
||||
@@ -789,14 +789,14 @@ fast swizzling
|
||||
*/
|
||||
static void GL_TextureSwizzle( byte *dst, const byte *src, uint width, uint height )
|
||||
{
|
||||
uint blockx, blocky;
|
||||
uint j;
|
||||
uint width_blocks = ( width / 16 );
|
||||
uint height_blocks = ( height / 8 );
|
||||
uint src_pitch = ( width - 16 ) / 4;
|
||||
uint src_row = width * 8;
|
||||
uint blockx, blocky;
|
||||
uint j;
|
||||
uint width_blocks = ( width / 16 );
|
||||
uint height_blocks = ( height / 8 );
|
||||
uint src_pitch = ( width - 16 ) / 4;
|
||||
uint src_row = width * 8;
|
||||
const byte* ysrc = src;
|
||||
uint* dst32 = ( uint* )dst;
|
||||
uint* dst32 = ( uint* )dst;
|
||||
|
||||
for ( blocky = 0; blocky < height_blocks; ++blocky )
|
||||
{
|
||||
@@ -827,15 +827,13 @@ upload texture into memory
|
||||
*/
|
||||
static qboolean GL_UploadTexture( gl_texture_t *tex, rgbdata_t *pic )
|
||||
{
|
||||
size_t texSize;
|
||||
uint width, height;
|
||||
uint i;
|
||||
uint offset, mipOffset;
|
||||
qboolean normalMap;
|
||||
qboolean swizzle;
|
||||
void *volBuff;
|
||||
unsigned int volSize;
|
||||
int volUid;
|
||||
size_t texSize;
|
||||
uint width, height;
|
||||
uint i;
|
||||
uint offset, mipOffset;
|
||||
qboolean normalMap;
|
||||
qboolean swizzle;
|
||||
byte *tempBuff;
|
||||
|
||||
// dedicated server
|
||||
if( !glw_state.initialized )
|
||||
@@ -869,11 +867,6 @@ static qboolean GL_UploadTexture( gl_texture_t *tex, rgbdata_t *pic )
|
||||
swizzle = IsLightMap( tex ) ? false : true;
|
||||
mipOffset = 0;
|
||||
|
||||
// Volatile memory for temporary buffer
|
||||
volUid = sceKernelVolatileMemLock( 0, &volBuff, &volSize );
|
||||
if( volUid != 0)
|
||||
gEngfuncs.Host_Error( "GL_UploadTexture: volatile memory lock error ( 0x%08x )\n", volUid );
|
||||
|
||||
// Check allocation size
|
||||
if( tex->dstTexture && ( tex->size != texSize ) )
|
||||
{
|
||||
@@ -894,10 +887,7 @@ static qboolean GL_UploadTexture( gl_texture_t *tex, rgbdata_t *pic )
|
||||
{
|
||||
tex->dstTexture = ( byte* )memalign( 16, texSize );
|
||||
if ( !tex->dstTexture )
|
||||
{
|
||||
sceKernelVolatileMemUnlock( 0 );
|
||||
gEngfuncs.Host_Error( "GL_UploadTexture: %s out of memory for texture ( %lu )\n", tex->name, texSize );
|
||||
}
|
||||
}
|
||||
else SetBits( tex->flags, TF_IMG_INVRAM );
|
||||
}
|
||||
@@ -914,16 +904,21 @@ static qboolean GL_UploadTexture( gl_texture_t *tex, rgbdata_t *pic )
|
||||
{
|
||||
tex->dstPalette = ( byte* )memalign( 16, PALETTE_SIZE );
|
||||
if ( !tex->dstPalette )
|
||||
{
|
||||
sceKernelVolatileMemUnlock( 0 );
|
||||
gEngfuncs.Host_Error( "GL_UploadTexture: %s out of memory for palette ( %lu )\n", tex->name, PALETTE_SIZE );
|
||||
}
|
||||
}
|
||||
|
||||
// Load palette
|
||||
GL_PixelConverter( tex->dstPalette, pic->palette, 256, PC_SWF( pic->type ), PC_HWF( PALETTE_FORMAT ) );
|
||||
GL_PixelConverter( tex->dstPalette, pic->palette, 256, PC_SWF( pic->type ), PC_HWF( PALETTE_FORMAT ));
|
||||
sceKernelDcacheWritebackRange( tex->dstPalette, PALETTE_SIZE );
|
||||
}
|
||||
else tex->dstPalette = gl_palette_332;
|
||||
|
||||
// Volatile memory for temporary buffer
|
||||
if( swizzle )
|
||||
{
|
||||
tempBuff = gEngfuncs.P5Ram_Alloc( texSize );
|
||||
if( !tempBuff ) gEngfuncs.Host_Error( "GL_UploadTexture: temporary memory error\n" );
|
||||
}
|
||||
|
||||
// Load base + mip texture
|
||||
for( i = 0; i < tex->numMips; i++ )
|
||||
@@ -931,66 +926,83 @@ static qboolean GL_UploadTexture( gl_texture_t *tex, rgbdata_t *pic )
|
||||
width = Q_max( TEXTURE_SIZE_MIN, ( tex->width >> i ) );
|
||||
height = Q_max( TEXTURE_SIZE_MIN, ( tex->height >> i ) );
|
||||
|
||||
if( ( pic->width != width ) || ( pic->height != height ) )
|
||||
GL_ResampleTexture8( pic->buffer, pic->width, pic->height, swizzle ? volBuff : ( tex->dstTexture + mipOffset ), width, height );
|
||||
else memcpy( swizzle ? volBuff : ( tex->dstTexture + mipOffset ), pic->buffer, offset );
|
||||
if(( pic->width != width ) || ( pic->height != height ))
|
||||
GL_ResampleTexture8( pic->buffer, pic->width, pic->height, swizzle ? tempBuff : ( tex->dstTexture + mipOffset ), width, height );
|
||||
else memcpy( swizzle ? tempBuff : ( tex->dstTexture + mipOffset ), pic->buffer, offset );
|
||||
|
||||
if(swizzle) GL_TextureSwizzle( tex->dstTexture + mipOffset, volBuff, width, height );
|
||||
if(swizzle) GL_TextureSwizzle( tex->dstTexture + mipOffset, tempBuff, width, height );
|
||||
mipOffset += GL_CalcTextureSize( tex->format, width, height, NULL );
|
||||
}
|
||||
if(swizzle) SetBits( tex->flags, TF_IMG_SWIZZLED );
|
||||
}
|
||||
else if( pic->type == PF_RGB_5650 || pic->type == PF_RGBA_5551 || pic->type == PF_RGBA_4444 )
|
||||
{
|
||||
if( ( pic->width != tex->width ) || ( pic->height != tex->height ) )
|
||||
{
|
||||
for( i = 0; i < tex->height; i++ )
|
||||
{
|
||||
memcpy( swizzle ? ( volBuff + tex->width * tex->bpp * i ) : ( tex->dstTexture + tex->width * tex->bpp * i ),
|
||||
( pic->buffer + pic->width * tex->bpp * i ), pic->width * tex->bpp );
|
||||
}
|
||||
}
|
||||
else memcpy( swizzle ? volBuff : tex->dstTexture, pic->buffer, offset );
|
||||
|
||||
if( swizzle )
|
||||
{
|
||||
GL_TextureSwizzle( tex->dstTexture, volBuff, tex->width * tex->bpp, tex->height );
|
||||
gEngfuncs.P5Ram_Free( tempBuff );
|
||||
SetBits( tex->flags, TF_IMG_SWIZZLED );
|
||||
}
|
||||
}
|
||||
else if( pic->type == PF_RGB_5650 || pic->type == PF_RGBA_5551 || pic->type == PF_RGBA_4444 )
|
||||
{
|
||||
if( swizzle )
|
||||
{
|
||||
tempBuff = gEngfuncs.P5Ram_Alloc( texSize );
|
||||
if( !tempBuff ) gEngfuncs.Host_Error( "GL_UploadTexture: temporary memory error\n" );
|
||||
}
|
||||
|
||||
if(( pic->width != tex->width ) || ( pic->height != tex->height ))
|
||||
{
|
||||
for( i = 0; i < tex->height; i++ )
|
||||
{
|
||||
memcpy( swizzle ? ( tempBuff + tex->width * tex->bpp * i ) : ( tex->dstTexture + tex->width * tex->bpp * i ),
|
||||
( pic->buffer + pic->width * tex->bpp * i ), pic->width * tex->bpp );
|
||||
}
|
||||
}
|
||||
else memcpy( swizzle ? tempBuff : tex->dstTexture, pic->buffer, offset );
|
||||
|
||||
if( swizzle )
|
||||
{
|
||||
GL_TextureSwizzle( tex->dstTexture, tempBuff, tex->width * tex->bpp, tex->height );
|
||||
gEngfuncs.P5Ram_Free( tempBuff );
|
||||
SetBits( tex->flags, TF_IMG_SWIZZLED );
|
||||
}
|
||||
}
|
||||
else // RGBA32
|
||||
{
|
||||
if( ( pic->width != tex->width ) || ( pic->height != tex->height ) )
|
||||
{
|
||||
GL_ResampleTexture32( pic->buffer, pic->width, pic->height, volBuff, tex->width, tex->height, normalMap );
|
||||
offset = tex->width * tex->height * 4; // 4 src bpp
|
||||
}
|
||||
else memcpy( volBuff, pic->buffer, offset );
|
||||
if(( pic->width != tex->width ) || ( pic->height != tex->height ))
|
||||
offset = tex->width * tex->height * 4; // src size
|
||||
|
||||
tempBuff = gEngfuncs.P5Ram_Alloc( swizzle ? ( texSize + offset ) : texSize );
|
||||
if( !tempBuff ) gEngfuncs.Host_Error( "GL_UploadTexture: temporary memory error\n" );
|
||||
|
||||
if(( pic->width != tex->width ) || ( pic->height != tex->height ))
|
||||
GL_ResampleTexture32( pic->buffer, pic->width, pic->height, tempBuff, tex->width, tex->height, normalMap );
|
||||
else memcpy( tempBuff, pic->buffer, offset );
|
||||
/*
|
||||
if( !FBitSet( tex->flags, TF_NOMIPMAP ) && FBitSet( pic->flags, IMAGE_ONEBIT_ALPHA ))
|
||||
volBuff = GL_ApplyFilter( volBuff, tex->width, tex->height );
|
||||
tempBuff = GL_ApplyFilter( tempBuff, tex->width, tex->height );
|
||||
*/
|
||||
if( tex->format == GU_PSM_8888 )
|
||||
{
|
||||
if ( swizzle )
|
||||
{
|
||||
GL_TextureSwizzle( tex->dstTexture, volBuff, tex->width * tex->bpp, tex->height );
|
||||
GL_TextureSwizzle( tex->dstTexture, tempBuff, tex->width * tex->bpp, tex->height );
|
||||
SetBits( tex->flags, TF_IMG_SWIZZLED );
|
||||
}
|
||||
else memcpy( tex->dstTexture, volBuff, texSize );
|
||||
else memcpy( tex->dstTexture, tempBuff, texSize );
|
||||
}
|
||||
else
|
||||
{
|
||||
GL_PixelConverter( swizzle ? (volBuff + offset) : tex->dstTexture, volBuff, tex->width * tex->height, PC_SWF( pic->type ), PC_HWF( tex->format ) );
|
||||
if( tex->format == GU_PSM_T8 ) tex->dstPalette = gl_palette_332;
|
||||
|
||||
GL_PixelConverter( swizzle ? (tempBuff + offset) : tex->dstTexture, tempBuff, tex->width * tex->height, PC_SWF( pic->type ), PC_HWF( tex->format ) );
|
||||
if( swizzle )
|
||||
{
|
||||
GL_TextureSwizzle( tex->dstTexture, volBuff + offset, tex->width * tex->bpp, tex->height );
|
||||
GL_TextureSwizzle( tex->dstTexture, tempBuff + offset, tex->width * tex->bpp, tex->height );
|
||||
SetBits( tex->flags, TF_IMG_SWIZZLED );
|
||||
}
|
||||
}
|
||||
gEngfuncs.P5Ram_Free( tempBuff );
|
||||
}
|
||||
|
||||
sceKernelVolatileMemUnlock( 0 );
|
||||
sceKernelDcacheWritebackRange( tex->dstTexture, texSize );
|
||||
tex->size = texSize;
|
||||
|
||||
@@ -1008,8 +1020,8 @@ GL_UpdateTexture
|
||||
qboolean GL_UpdateTexture( int texnum, int xoff, int yoff, int width, int height, const void *buffer )
|
||||
{
|
||||
gl_texture_t *tex;
|
||||
size_t texsize;
|
||||
byte *dst, *src;
|
||||
size_t texsize;
|
||||
byte *dst, *src;
|
||||
|
||||
// missed or invalid texture?
|
||||
if(( texnum <= 0 ) || ( texnum >= MAX_TEXTURES ))
|
||||
@@ -1030,7 +1042,7 @@ qboolean GL_UpdateTexture( int texnum, int xoff, int yoff, int width, int height
|
||||
|
||||
if( !FBitSet( tex->flags, TF_IMG_UPLOADED ) )
|
||||
{
|
||||
tex->size = GL_CalcTextureSize( tex->format, tex->width, tex->height, &tex->bpp );
|
||||
tex->size = GL_CalcTextureSize( tex->format, tex->width, tex->height, &tex->bpp );
|
||||
tex->numMips = 1;
|
||||
tex->dstPalette = NULL;
|
||||
|
||||
@@ -1055,7 +1067,7 @@ qboolean GL_UpdateTexture( int texnum, int xoff, int yoff, int width, int height
|
||||
dst += tex->width * tex->bpp;
|
||||
src += width * tex->bpp;
|
||||
}
|
||||
|
||||
|
||||
sceKernelDcacheWritebackRange( tex->dstTexture, tex->size );
|
||||
return true;
|
||||
}
|
||||
@@ -1069,8 +1081,8 @@ do specified actions on pixels
|
||||
*/
|
||||
static void GL_ProcessImage( gl_texture_t *tex, rgbdata_t *pic )
|
||||
{
|
||||
float emboss_scale = 0.0f;
|
||||
uint img_flags = 0;
|
||||
float emboss_scale = 0.0f;
|
||||
uint img_flags = 0;
|
||||
|
||||
// force upload texture as RGB or RGBA (detail textures requires this)
|
||||
if( tex->flags & TF_FORCE_COLOR ) pic->flags |= IMAGE_HAS_COLOR;
|
||||
@@ -1250,7 +1262,7 @@ static void GL_DeleteTexture( gl_texture_t *tex )
|
||||
if( tex->original )
|
||||
gEngfuncs.FS_FreeImage( tex->original );
|
||||
|
||||
if( tex->dstPalette )
|
||||
if( tex->dstPalette && tex->dstPalette != gl_palette_332 )
|
||||
free( tex->dstPalette );
|
||||
|
||||
if( tex->dstTexture )
|
||||
@@ -1306,7 +1318,7 @@ GL_LoadTexture
|
||||
int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags )
|
||||
{
|
||||
gl_texture_t *tex;
|
||||
rgbdata_t *pic;
|
||||
rgbdata_t *pic;
|
||||
uint picFlags = 0;
|
||||
|
||||
if( !GL_CheckTexName( name ))
|
||||
@@ -1357,7 +1369,7 @@ int GL_LoadTextureArray( const char **names, int flags )
|
||||
#if 1
|
||||
return 0;
|
||||
#else
|
||||
rgbdata_t *pic, *src;
|
||||
rgbdata_t *pic, *src;
|
||||
char basename[256];
|
||||
uint numLayers = 0;
|
||||
uint picFlags = 0;
|
||||
@@ -1544,7 +1556,7 @@ creates texture from buffer
|
||||
int GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags )
|
||||
{
|
||||
qboolean update = FBitSet( flags, TF_UPDATE ) ? true : false;
|
||||
int datasize = 1;
|
||||
int datasize = 1;
|
||||
rgbdata_t r_empty;
|
||||
|
||||
if( FBitSet( flags, TF_ARB_16BIT ))
|
||||
@@ -1864,35 +1876,35 @@ GL_Create332Palette
|
||||
*/
|
||||
static void GL_Create332Palette( void )
|
||||
{
|
||||
palette_332 = ( byte* )memalign( 16, PALETTE_SIZE );
|
||||
if ( !palette_332 )
|
||||
gl_palette_332 = ( byte* )memalign( 16, PALETTE_SIZE );
|
||||
if ( !gl_palette_332 )
|
||||
gEngfuncs.Host_Error( "GL_Create332Palette: out of memory!\n" );
|
||||
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
#if PALETTE_FORMAT == GU_PSM_5650
|
||||
palette_332[i * 2 + 0] = ( i & 0x07 ) << 2;
|
||||
palette_332[i * 2 + 1] = ( i & 0x38 ) >> 3;
|
||||
palette_332[i * 2 + 1] |= ( i & 0xc0 );
|
||||
gl_palette_332[i * 2 + 0] = ( i & 0x07 ) << 2;
|
||||
gl_palette_332[i * 2 + 1] = ( i & 0x38 ) >> 3;
|
||||
gl_palette_332[i * 2 + 1] |= ( i & 0xc0 );
|
||||
#elif PALETTE_FORMAT == GU_PSM_5551
|
||||
palette_332[i * 2 + 0] = ( i & 0x07 ) << 2;
|
||||
palette_332[i * 2 + 0] |= ( i & 0x08 ) << 4;
|
||||
palette_332[i * 2 + 1] = ( i & 0x30 ) >> 4;
|
||||
palette_332[i * 2 + 1] |= ( i & 0xc0 ) >> 1;
|
||||
palette_332[i * 2 + 1] |= 0x80;
|
||||
gl_palette_332[i * 2 + 0] = ( i & 0x07 ) << 2;
|
||||
gl_palette_332[i * 2 + 0] |= ( i & 0x08 ) << 4;
|
||||
gl_palette_332[i * 2 + 1] = ( i & 0x30 ) >> 4;
|
||||
gl_palette_332[i * 2 + 1] |= ( i & 0xc0 ) >> 1;
|
||||
gl_palette_332[i * 2 + 1] |= 0x80;
|
||||
#elif PALETTE_FORMAT == GU_PSM_4444
|
||||
palette_332[i * 2 + 0] = ( i & 0x07 ) << 1;
|
||||
palette_332[i * 2 + 0] |= ( i & 0x38 ) << 2;
|
||||
palette_332[i * 2 + 1] = ( i & 0xc0 ) >> 4;
|
||||
palette_332[i * 2 + 1] |= 0xf0;
|
||||
gl_palette_332[i * 2 + 0] = ( i & 0x07 ) << 1;
|
||||
gl_palette_332[i * 2 + 0] |= ( i & 0x38 ) << 2;
|
||||
gl_palette_332[i * 2 + 1] = ( i & 0xc0 ) >> 4;
|
||||
gl_palette_332[i * 2 + 1] |= 0xf0;
|
||||
#elif PALETTE_FORMAT == GU_PSM_8888
|
||||
palette_332[i * 4 + 0] = ( i & 0x07 ) << 5;
|
||||
palette_332[i * 4 + 1] = ( i & 0x38 ) << 2;
|
||||
palette_332[i * 4 + 2] = ( i & 0xc0 );
|
||||
palette_332[i * 4 + 3] = 0xff;
|
||||
gl_palette_332[i * 4 + 0] = ( i & 0x07 ) << 5;
|
||||
gl_palette_332[i * 4 + 1] = ( i & 0x38 ) << 2;
|
||||
gl_palette_332[i * 4 + 2] = ( i & 0xc0 );
|
||||
gl_palette_332[i * 4 + 3] = 0xff;
|
||||
#endif
|
||||
}
|
||||
sceKernelDcacheWritebackRange( palette_332, PALETTE_SIZE );
|
||||
sceKernelDcacheWritebackRange( gl_palette_332, PALETTE_SIZE );
|
||||
}
|
||||
|
||||
|
||||
@@ -2025,8 +2037,8 @@ void R_ShutdownImages( void )
|
||||
for( i = 0, tex = gl_textures; i < gl_numTextures; i++, tex++ )
|
||||
GL_DeleteTexture( tex );
|
||||
|
||||
if( palette_332 )
|
||||
free( palette_332 );
|
||||
if( gl_palette_332 )
|
||||
free( gl_palette_332 );
|
||||
|
||||
memset( tr.lightmapTextures, 0, sizeof( tr.lightmapTextures ));
|
||||
memset( gl_texturesHashTable, 0, sizeof( gl_texturesHashTable ));
|
||||
|
||||
Reference in New Issue
Block a user