Files
glide/swlibs/texus/examples/viewppm.c
1999-11-24 21:43:03 +00:00

425 lines
9.8 KiB
C

/*
** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY
** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT
** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX
** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE
** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com).
** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A
** FULL TEXT OF THE NON-WARRANTY PROVISIONS.
**
** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO
** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN
** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013,
** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR
** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF
** THE UNITED STATES.
**
** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED
**
** $Revision$
** $Date$
*/
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <glide.h>
#include <texus.h>
/*
* VIEWPPM
* This is a simple program to show how to use the Texus library
* to convert textures from an in memory format to a format
* that Glide can handle for texture downloads.
*/
typedef struct
{
unsigned char b, g, r, a;
} Color32;
/*
* This structure contains the factors to multiply normalized [0.0, 1.0]
* texture coordinates by in order to get the texture coordinates that
* Voodoo Graphics expect.
*/
typedef struct
{
float sMult;
float tMult;
} TexCoordFactors;
/*
* An array which is indexed by GrAspectRatio_t to convert from normalized
* texture coordinates to Voodoo texture coordinates.
*/
TexCoordFactors aspectToTexCoordFactors[7] = {
{ 255.0f, 255.0f / 8.0f }, /* GR_ASPECT_8x1 */
{ 255.0f, 255.0f / 4.0f }, /* GR_ASPECT_4x1 */
{ 255.0f, 255.0f / 2.0f }, /* GR_ASPECT_2x1 */
{ 255.0f, 255.0f }, /* GR_ASPECT_1x1 */
{ 255.0f / 2.0f, 255.0f }, /* GR_ASPECT_1x2 */
{ 255.0f / 4.0f, 255.0f }, /* GR_ASPECT_1x4 */
{ 255.0f / 8.0f, 255.0f } /* GR_ASPECT_1x8 */
};
/*
* Do whatever is necessary to get Glide going.
*/
void InitGlide( void )
{
static GrHwConfiguration hwconfig;
grGlideInit();
if ( !grSstQueryHardware( &hwconfig ) )
{
fprintf( stderr, "grQuery failed!" );
exit( -1 );
}
grSstSelect( 0 );
if ( !grSstWinOpen( 0,
GR_RESOLUTION_640x480,
GR_REFRESH_60Hz,
GR_COLORFORMAT_ABGR,
GR_ORIGIN_UPPER_LEFT,
2, 0 ) )
{
fprintf( stderr, "grOpen failed!" );
exit( -1 );
}
grTexCombineFunction( GR_TMU0, GR_TEXTURECOMBINE_DECAL );
guColorCombineFunction( GR_COLORCOMBINE_DECAL_TEXTURE );
grCullMode( GR_CULL_NEGATIVE );
}
int ValidateImageDimensions( int width, int height )
{
switch( width )
{
case 1:
case 2:
case 4:
case 8:
case 16:
case 32:
case 64:
case 128:
case 256:
break;
default:
fprintf( stderr, "Invalid image width: %d\n", width );
return 0;
}
switch( height )
{
case 1:
case 2:
case 4:
case 8:
case 16:
case 32:
case 64:
case 128:
case 256:
break;
default:
fprintf( stderr, "Invalid image height: %d\n", height );
return 0;
}
if( ( ( width / height ) > 8 ) || ( ( height / width ) > 8 ) )
{
fprintf( stderr, "Invalid aspect ratio, must one of:\n" );
fprintf( stderr, "1:8, 1:4, 1:2, 1:1, 2:1, 4:1, 8:1\n" );
return 0;
}
return 1;
}
/*
* Get the dimensions of a PPM file.
* returns 1 if successful, 0 otherwise.
*/
int PPMGetDimensions( const char *filename, int *width, int *height )
{
FILE *fp;
char buf[200];
/*
* Open the PPM file.
*/
if( !( fp = fopen( filename, "rb" ) ) )
return 0;
/*
* Read the PPM header.
*/
/* Skip the P6 */
fgets( buf, 200, fp );
/* REad the dimensions */
fgets( buf, 200, fp );
sscanf( buf, "%d %d", width, height );
fclose( fp );
return 1;
}
/*
* LoadPPM
* Allocate memory for an image, load a ppm file into it.
* Not the most efficient loader because it reads directly
* into a 8888 instead of an 888 without allocating any
* extra memory.
*/
Color32 *PPMLoad( const char *filename )
{
Color32 *out;
char buf[200];
FILE *fp;
int width, height;
long i;
/*
* Open the PPM file.
*/
if( !( fp = fopen( filename, "rb" ) ) )
return NULL;
/*
* Read the PPM header.
*/
/* Skip the P6 */
fgets( buf, 200, fp );
/* REad the dimensions */
fgets( buf, 200, fp );
sscanf( buf, "%d %d", &width, &height );
/* Skip the maxval line. . . assume that it is 255. */
fgets( buf, 200, fp );
/*
* Allocate memory for the output image.
*/
out = ( Color32 * )malloc( sizeof( Color32 ) * ( long )width * ( long )height );
if( !out )
{
fclose( fp );
return NULL;
}
/*
* Read in each texel. . .fill in the alpha with a totally
* opaque value.
*/
for( i = 0; i < ( long )width * ( long )height; i++ )
{
fread( &out[i].r, 1, 1, fp );
fread( &out[i].g, 1, 1, fp );
fread( &out[i].b, 1, 1, fp );
out[i].a = 0xff;
}
fclose( fp );
return out;
}
int main( int argc, char **argv )
{
Color32 *raw_image;
size_t tex_mem_required;
Gu3dfInfo info;
int ppm_width, ppm_height;
int target_width, target_height;
GrMipMapId_t mmid;
GrVertex vtx[4];
float smult, tmult;
if( argc < 2 )
{
fprintf( stderr, "Usage: %s in.ppm [display_width display_height] \n", argv[0] );
exit( -1 );
}
InitGlide();
if( !PPMGetDimensions( argv[1], &ppm_width, &ppm_height ) )
{
fprintf( stderr, "Error getting PPM dimensions\n" );
exit( -1 );
}
/*
* If there are args to resize the image, then remember them.
*/
if( argc == 4 )
{
target_width = atoi( argv[2] );
target_height = atoi( argv[3] );
}
else
{
target_width = ppm_width;
target_height = ppm_height;
}
#if 0
/*
* Validate the geometry of the output image.
*/
if( !ValidateImageDimensions( target_width, target_height ) )
{
fprintf( stderr, "Invalid image dimensions\n" );
exit( -1 );
}
#endif
tex_mem_required = txInit3dfInfo( &info, GR_TEXFMT_P_8,
&target_width, &target_height,
-1, TX_AUTORESIZE_GROW );
/*
* Allocate system memory for the texture.
*/
info.data = malloc( tex_mem_required );
if( !info.data )
{
fprintf( stderr, "Out of memory allocating system memory textures.\n" );
exit( -1 );
}
/*
* Make sure txInit3dfInfo didn't fail.
*/
if( tex_mem_required == 0 )
{
fprintf( stderr, "Problem with txInit3dfInfo\n" );
exit( -1 );
}
/*
* Read the PPM image.
*/
if( !( raw_image = PPMLoad( argv[1] ) ) )
{
fprintf( stderr, "Not able to load PPM file.\n" );
exit( -1 );
}
/*
* Convert to a texture that can be downloaded to the hardware.
*/
txConvert( &info, GR_TEXFMT_ARGB_8888,
ppm_width, ppm_height,
raw_image, TX_DITHER_NONE, NULL );
{
FILE *fp;
fprintf( stderr, "Writing blah.3df\n" );
if( !( fp = fopen( "blah.3df", "wb" ) ) )
{
fprintf( stderr, "Not able to open output file.\n" );
exit( -1 );
}
txWrite( &info, fp, TX_WRITE_3DF );
fclose( fp );
grTexDownloadTable( GR_TMU0,
GR_TEXTABLE_PALETTE,
&info.table.palette.data );
}
/*
* Call Glide to allocate memory for the converted texture.
*/
mmid = guTexAllocateMemory( 0, GR_MIPMAPLEVELMASK_BOTH,
info.header.width, info.header.height,
info.header.format,
GR_MIPMAP_NEAREST,
info.header.small_lod, info.header.large_lod,
info.header.aspect_ratio,
GR_TEXTURECLAMP_WRAP, GR_TEXTURECLAMP_WRAP,
GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR,
0.0F,
FXFALSE );
/*
* Download the texture and set it as the current texture.
*/
guTexDownloadMipMap( mmid, info.data, &info.table.nccTable );
guTexSource( mmid );
/*
* Figure out what the factor is to get from normalized texture
* coords to something that the hardware can deal with.
*/
smult = aspectToTexCoordFactors[info.header.aspect_ratio].sMult;
tmult = aspectToTexCoordFactors[info.header.aspect_ratio].tMult;
/*
* Set up some verts to draw the texture on a couple of triangles
* with.
*/
vtx[0].x = 0.0f;
vtx[0].y = 0.0f;
vtx[0].oow = 1.0f;
vtx[0].tmuvtx[0].sow = 0.0f;
vtx[0].tmuvtx[0].tow = 0.0f;
vtx[1].x = ( float )target_width - 1.0f;
vtx[1].y = 0.0f;
vtx[1].oow = 1.0f;
vtx[1].tmuvtx[0].sow = 1.0f * smult;
vtx[1].tmuvtx[0].tow = 0.0f;
vtx[2].x = ( float )target_width - 1.0f;
vtx[2].y = ( float )target_height - 1.0f;
vtx[2].oow = 1.0f;
vtx[2].tmuvtx[0].sow = 1.0f * smult;
vtx[2].tmuvtx[0].tow = 1.0f * tmult;
vtx[3].x = 0.0f;
vtx[3].y = ( float )target_height - 1.0f;
vtx[3].oow = 1.0f;
vtx[3].tmuvtx[0].sow = 0.0f;
vtx[3].tmuvtx[0].tow = 1.0f * tmult;
printf( "Hit a key to exit\n" );
fflush( stdout );
while( !kbhit() )
{
grDrawTriangle( &vtx[0], &vtx[1], &vtx[2] );
grDrawTriangle( &vtx[0], &vtx[2], &vtx[3] );
grBufferSwap( 1 );
}
/*
* Shutdown Glide (and switch the passthru back to the
* main display.
*/
grGlideShutdown();
/*
* Clean up.
*/
free( raw_image );
free( info.data );
return 0;
}