2007-01-15 12:09:25 -08:00
/*
This file is part of Warzone 2100.
Copyright ( C ) 1999 - 2004 Eidos Interactive
Copyright ( C ) 2005 - 2007 Warzone Resurrection Project
Warzone 2100 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 2 of the License , or
( at your option ) any later version .
Warzone 2100 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 .
You should have received a copy of the GNU General Public License
along with Warzone 2100 ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
2007-04-11 07:21:45 -07:00
# include "lib/framework/frame.h"
2007-11-24 03:49:51 -08:00
# include <SDL_opengl.h>
2006-08-15 09:33:48 -07:00
# ifdef __APPLE__
# include <opengl/glu.h>
# else
2005-11-29 08:20:35 -08:00
# include <GL/glu.h>
2006-08-15 09:33:48 -07:00
# endif
2007-06-28 10:47:08 -07:00
2006-06-02 12:34:58 -07:00
# include "lib/ivis_common/ivisdef.h"
# include "lib/ivis_common/piestate.h"
# include "lib/ivis_common/tex.h"
# include "lib/ivis_common/rendmode.h"
# include "lib/ivis_common/piepalette.h"
# include "lib/ivis_common/ivispatch.h"
2007-04-30 07:09:33 -07:00
# include "lib/ivis_common/png_util.h"
2007-06-28 10:47:08 -07:00
2007-03-28 08:08:57 -07:00
# include "screen.h"
2007-06-28 10:47:08 -07:00
//*************************************************************************
iTexPage _TEX_PAGE [ iV_TEX_MAX ] ;
2007-04-23 15:08:53 -07:00
unsigned int _TEX_INDEX ;
2007-06-28 10:47:08 -07:00
2007-08-01 08:06:23 -07:00
static void pie_PrintLoadedTextures ( void ) ;
2007-06-28 10:47:08 -07:00
//*************************************************************************
/**************************************************************************
Add an image buffer given in s as a new texture page in the texture
table . We check first if the given image has already been loaded ,
as a sanity check ( should never happen ) . The texture numbers are
stored in a special texture table , not in the resource system , for
2007-08-01 08:06:23 -07:00
some unknown reason . Start looking for an available slot in the
texture table at the given slot number .
2007-06-28 10:47:08 -07:00
Returns the texture number of the image .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-01 08:06:23 -07:00
int pie_AddTexPage ( iV_Image * s , const char * filename , int slot )
2007-02-16 15:19:33 -08:00
{
2007-04-19 11:04:41 -07:00
unsigned int i = 0 ;
2007-06-28 10:47:08 -07:00
2007-08-01 08:06:23 -07:00
/* Have we already loaded this one? Should not happen here. */
while ( i < _TEX_INDEX )
{
if ( strncmp ( filename , _TEX_PAGE [ i ] . name , iV_TEXNAME_MAX ) = = 0 )
{
pie_PrintLoadedTextures ( ) ;
2007-06-28 10:47:08 -07:00
}
2007-08-01 08:06:23 -07:00
ASSERT ( strncmp ( filename , _TEX_PAGE [ i ] . name , iV_TEXNAME_MAX ) ! = 0 ,
" pie_AddTexPage: %s loaded again! Already loaded as %s|%u " , filename ,
_TEX_PAGE [ i ] . name , i ) ;
2007-06-28 10:47:08 -07:00
i + + ;
}
2007-08-01 08:06:23 -07:00
/* Use first unused slot */
for ( i = slot ; i < iV_TEX_MAX & & _TEX_PAGE [ i ] . name [ 0 ] ! = ' \0 ' ; i + + ) ;
if ( i = = _TEX_INDEX )
{
_TEX_INDEX + + ; // increase table
2007-06-28 10:47:08 -07:00
}
2007-08-01 08:06:23 -07:00
ASSERT ( i ! = iV_TEX_MAX , " pie_AddTexPage: too many texture pages " ) ;
debug ( LOG_TEXTURE , " pie_AddTexPage: %s page=%d " , filename , _TEX_INDEX ) ;
assert ( s ! = NULL ) ;
2007-06-28 10:47:08 -07:00
/* Stick the name into the tex page structures */
2007-10-27 09:18:52 -07:00
strlcpy ( _TEX_PAGE [ i ] . name , filename , sizeof ( _TEX_PAGE [ i ] . name ) ) ;
2007-06-28 10:47:08 -07:00
2007-04-30 13:42:18 -07:00
glGenTextures ( 1 , ( GLuint * ) & _TEX_PAGE [ i ] . id ) ;
2007-05-01 13:34:54 -07:00
// FIXME: This function is used instead of glBindTexture, but we're juggling with difficult to trace global state here. Look into pie_SetTexturePage's definition for details.
2007-05-01 08:37:20 -07:00
pie_SetTexturePage ( i ) ;
2007-06-28 10:47:08 -07:00
2007-02-16 15:19:33 -08:00
if ( ( s - > width & ( s - > width - 1 ) ) = = 0 & & ( s - > height & ( s - > height - 1 ) ) = = 0 )
{
2007-05-01 13:34:54 -07:00
gluBuild2DMipmaps ( GL_TEXTURE_2D , wz_texture_compression , s - > width , s - > height , iV_getPixelFormat ( s ) , GL_UNSIGNED_BYTE , s - > bmp ) ;
2005-11-29 08:20:35 -08:00
} else {
2007-04-28 17:58:39 -07:00
debug ( LOG_ERROR , " pie_AddTexPage: non POT texture %s " , filename ) ;
2007-06-28 10:47:08 -07:00
}
2007-07-27 09:57:41 -07:00
free ( s - > bmp ) ; // it is uploaded, we do not need it anymore
s - > bmp = NULL ;
2007-06-28 10:47:08 -07:00
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
2006-12-17 10:18:06 -08:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR_MIPMAP_LINEAR ) ;
2007-06-28 10:47:08 -07:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
2007-04-28 13:21:16 -07:00
2007-07-28 06:49:52 -07:00
// Use anisotropic filtering, if available, but only max 4.0 to reduce processor burden
if ( check_extension ( " GL_EXT_texture_filter_anisotropic " ) )
{
GLfloat max ;
glGetFloatv ( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT , & max ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAX_ANISOTROPY_EXT , MIN ( 4.0f , max ) ) ;
}
2008-01-12 07:10:02 -08:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP ) ;
2007-06-28 10:47:08 -07:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP ) ;
/* Send back the texpage number so we can store it in the IMD */
_TEX_INDEX + + ;
return i ;
}
2008-01-12 07:10:02 -08:00
void pie_PrepareSkybox ( const char * pageName )
{
pie_SetTexturePage ( iV_GetTexture ( pageName ) ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_REPEAT ) ;
}
2007-04-28 13:21:16 -07:00
void pie_MakeTexPageName ( char * filename )
2007-04-19 11:04:41 -07:00
{
if ( strncmp ( filename , " page- " , 5 ) = = 0 )
{
int i ;
for ( i = 5 ; i < iV_TEXNAME_MAX - 1 & & isdigit ( filename [ i ] ) ; i + + ) ;
filename [ i ] = ' \0 ' ;
}
}
/*!
* Print the names of all loaded textures to LOG_ERROR
*/
2007-04-29 14:42:22 -07:00
static void pie_PrintLoadedTextures ( void )
2007-04-19 11:04:41 -07:00
{
unsigned int i = 0 ;
debug ( LOG_ERROR , " Available texture pages in memory (%d out of %d max): " , _TEX_INDEX , iV_TEX_MAX ) ;
2007-07-31 05:47:08 -07:00
for ( i = 0 ; i < iV_TEX_MAX & & _TEX_PAGE [ i ] . name [ 0 ] ! = ' \0 ' ; i + + )
{
2007-04-19 11:04:41 -07:00
debug ( LOG_ERROR , " %02d : %s " , i , _TEX_PAGE [ i ] . name ) ;
}
}
2007-06-28 10:47:08 -07:00
/**************************************************************************
Return the texture number for a given texture resource . We keep
textures in a separate data structure _TEX_PAGE apart from the
normal resource system .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-04-16 13:07:56 -07:00
int iV_GetTexture ( const char * filename )
2007-06-28 10:47:08 -07:00
{
2007-04-19 11:04:41 -07:00
unsigned int i = 0 ;
2007-06-28 10:47:08 -07:00
2007-03-16 10:33:20 -07:00
/* Have we already loaded this one then? */
2007-04-19 11:04:41 -07:00
for ( i = 0 ; i < iV_TEX_MAX ; i + + ) {
if ( strncmp ( filename , _TEX_PAGE [ i ] . name , iV_TEXNAME_MAX ) = = 0 ) {
2007-06-28 10:47:08 -07:00
return i ;
}
}
/* This should never happen - by now all textures should have been loaded. */
2005-12-28 03:46:45 -08:00
debug ( LOG_ERROR , " *** texture %s not loaded! *** " , filename ) ;
2007-04-19 11:04:41 -07:00
debug ( LOG_ERROR , " This error probably means you did not specify this texture to be preloaded in the appropriate wrf files before referencing it in some pie file " ) ;
debug ( LOG_ERROR , " Remember that patches override several standard wrf files as well " ) ;
pie_PrintLoadedTextures ( ) ;
2007-03-16 10:33:20 -07:00
2007-06-28 10:47:08 -07:00
return - 1 ;
}
2007-04-19 11:04:41 -07:00
2007-08-01 08:06:23 -07:00
/**************************************************************************
WRF files may specify overrides for the textures on a map . This
is done through an ugly hack involving cutting the texture name
down to just " page-NN " , where NN is the page number , and
replaceing the texture page with the same name if another file
with this prefix is loaded .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int pie_ReplaceTexPage ( iV_Image * s , const char * texPage )
2007-06-28 10:47:08 -07:00
{
2007-08-01 08:06:23 -07:00
int i = iV_GetTexture ( texPage ) ;
2006-07-03 12:43:12 -07:00
2007-08-01 08:06:23 -07:00
ASSERT ( i > = 0 , " pie_ReplaceTexPage: Cannot find any %s to replace! " , texPage ) ;
2007-04-19 11:04:41 -07:00
if ( i < 0 )
2007-03-16 10:33:20 -07:00
{
return - 1 ;
2007-06-28 10:47:08 -07:00
}
2007-04-19 11:04:41 -07:00
2007-08-01 08:06:23 -07:00
glDeleteTextures ( 1 , ( GLuint * ) & _TEX_PAGE [ i ] . id ) ;
2007-08-03 10:39:04 -07:00
debug ( LOG_TEXTURE , " Reloading texture %s from index %d " , texPage , i ) ;
2007-08-01 08:06:23 -07:00
_TEX_PAGE [ i ] . name [ 0 ] = ' \0 ' ;
pie_AddTexPage ( s , texPage , i ) ;
2007-06-28 10:47:08 -07:00
return i ;
}
/*
Alex - fixed this so it doesn ' t try to free up the memory if it got the page from resource
handler - this is because the resource handler will deal with freeing it , and in all probability
will have already done so by the time this is called , thus avoiding an ' already freed ' moan .
*/
2007-03-15 15:49:54 -07:00
void pie_TexShutDown ( void )
2007-02-16 15:19:33 -08:00
{
2007-07-27 09:57:41 -07:00
unsigned int i = 0 ;
2007-06-28 10:47:08 -07:00
2007-07-30 13:20:06 -07:00
while ( i < _TEX_INDEX )
2007-07-27 07:58:17 -07:00
{
glDeleteTextures ( 1 , ( GLuint * ) & _TEX_PAGE [ i ] . id ) ;
2007-06-28 10:47:08 -07:00
i + + ;
}
2007-07-27 09:57:41 -07:00
debug ( LOG_TEXTURE , " pie_TexShutDown successful - did free %u texture pages " , i ) ;
2007-06-28 10:47:08 -07:00
}
2007-03-15 15:49:54 -07:00
void pie_TexInit ( void )
2007-02-16 15:19:33 -08:00
{
2007-03-16 10:33:20 -07:00
int i = 0 ;
2007-06-28 10:47:08 -07:00
2007-03-16 10:33:20 -07:00
while ( i < iV_TEX_MAX ) {
_TEX_PAGE [ i ] . name [ 0 ] = ' \0 ' ;
2007-06-28 10:47:08 -07:00
i + + ;
}
2007-03-16 10:33:20 -07:00
debug ( LOG_TEXTURE , " pie_TexInit successful - initialized %d texture pages \n " , i ) ;
2007-06-28 10:47:08 -07:00
}
2007-05-01 13:34:54 -07:00
void iV_unloadImage ( iV_Image * image )
{
if ( image )
{
2007-07-10 13:32:59 -07:00
if ( image - > bmp )
{
free ( image - > bmp ) ;
image - > bmp = NULL ;
}
2007-05-01 13:34:54 -07:00
}
else
{
debug ( LOG_ERROR , " Tried to free invalid image! " ) ;
}
}
unsigned int iV_getPixelFormat ( const iV_Image * image )
{
switch ( image - > depth )
{
case 3 :
return GL_RGB ;
case 4 :
return GL_RGBA ;
default :
debug ( LOG_ERROR , " iV_getPixelFormat: Unsupported image depth: %u " , image - > depth ) ;
return GL_INVALID_ENUM ;
}
}