source: trunk/src/opengl/glide/sst1/texus/texuslib.c

Last change on this file was 2885, checked in by sandervl, 26 years ago

Created new Voodoo 1 Glide dir

File size: 17.6 KB
Line 
1/*
2** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY
3** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT
4** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX
5** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE
6** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com).
7** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
8** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A
9** FULL TEXT OF THE NON-WARRANTY PROVISIONS.
10**
11** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO
12** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN
13** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013,
14** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR
15** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF
16** THE UNITED STATES.
17**
18** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED
19**
20** $Id: texuslib.c,v 1.1 2000-02-25 00:31:39 sandervl Exp $
21*/
22#include <string.h>
23#include <glide.h>
24#include <malloc.h>
25#include "texus.h"
26#include "texusint.h"
27
28void _txDefaultErrorCallback( const char *string, FxBool fatal );
29
30TxErrorCallbackFnc_t _txErrorCallback = _txDefaultErrorCallback;
31
32void _txDefaultErrorCallback( const char *string, FxBool fatal )
33{
34 fprintf(stderr, "Texus: %s", string );
35 if( fatal )
36 exit( -1 );
37}
38
39#ifdef GLIDE3
40 static FxU32 _gr_aspect_index_table[] =
41 {
42 0,
43 1,
44 2,
45 3
46 };
47#else
48 static FxU32 _gr_aspect_index_table[] =
49 {
50 3,
51 2,
52 1,
53 0,
54 1,
55 2,
56 3,
57 };
58#endif
59
60/* size in texels */
61static FxU32 _grMipMapHostSize[4][16] =
62{
63 { /* 1:1 aspect ratio */
64 65536, /* 0 : 256x256 */
65 16384, /* 1 : 128x128 */
66 4096, /* 2 : 64x64 */
67 1024, /* 3 : 32x32 */
68 256, /* 4 : 16x16 */
69 64, /* 5 : 8x8 */
70 16, /* 6 : 4x4 */
71 4, /* 7 : 2x2 */
72 1, /* 8 : 1x1 */
73 },
74 { /* 2:1 aspect ratio */
75 32768, /* 0 : 256x128 */
76 8192, /* 1 : 128x64 */
77 2048, /* 2 : 64x32 */
78 512, /* 3 : 32x16 */
79 128, /* 4 : 16x8 */
80 32, /* 5 : 8x4 */
81 8, /* 6 : 4x2 */
82 2, /* 7 : 2x1 */
83 1, /* 8 : 1x1 */
84 },
85 { /* 4:1 aspect ratio */
86 16384, /* 0 : 256x64 */
87 4096, /* 1 : 128x32 */
88 1024, /* 2 : 64x16 */
89 256, /* 3 : 32x8 */
90 64, /* 4 : 16x4 */
91 16, /* 5 : 8x2 */
92 4, /* 6 : 4x1 */
93 2, /* 7 : 2x1 */
94 1, /* 8 : 1x1 */
95 },
96 { /* 8:1 aspect ratio */
97 8192, /* 0 : 256x32 */
98 2048, /* 1 : 128x16 */
99 512, /* 2 : 64x8 */
100 128, /* 3 : 32x4 */
101 32, /* 4 : 16x2 */
102 8, /* 5 : 8x1 */
103 4, /* 6 : 4x1 */
104 2, /* 7 : 2x1 */
105 1, /* 8 : 1x1 */
106 }
107};
108
109FxU32
110txTexCalcMemRequired( GrLOD_t small_lod, GrLOD_t large_lod,
111 GrAspectRatio_t aspect, GrTextureFormat_t format ) {
112 size_t memRequired;
113 FxI32 lod;
114 memRequired = 0;
115
116#ifdef GLIDE3
117 for( lod = small_lod; lod <= large_lod; lod++ ) {
118#else
119 for( lod = large_lod; lod <= small_lod; lod++ ) {
120#endif
121 memRequired +=
122#ifdef GLIDE3
123 /* Quick port to Glide3. Not the most general way. We would need
124 ** something like GR_ASPECT_MAX, GR_ASPECT_MIN, GR_LOD_MAX and GR_LOD_MIN...
125 ** because this current implementation will break when we have more
126 ** than 8 levels of mipmapping for example.
127 */
128 _grMipMapHostSize[_gr_aspect_index_table[((aspect>=0)?aspect:-aspect)]] [8-lod] << (format>=GR_TEXFMT_16BIT);
129#else
130 _grMipMapHostSize[_gr_aspect_index_table[aspect]] [lod] << (format>=GR_TEXFMT_16BIT);
131#endif
132 }
133 return memRequired ;
134}
135
136static GrLOD_t _txLengthToLOD( int len )
137{
138#ifdef GLIDE3
139 switch( len )
140 {
141 case 256:
142 return GR_LOD_LOG2_256;
143 case 128:
144 return GR_LOD_LOG2_128;
145 case 64:
146 return GR_LOD_LOG2_64;
147 case 32:
148 return GR_LOD_LOG2_32;
149 case 16:
150 return GR_LOD_LOG2_16;
151 case 8:
152 return GR_LOD_LOG2_8;
153 case 4:
154 return GR_LOD_LOG2_4;
155 case 2:
156 return GR_LOD_LOG2_2;
157 case 1:
158 return GR_LOD_LOG2_1;
159 }
160 /*
161 * This is only here to make the compiler shut up.
162 */
163 return GR_LOD_LOG2_1;
164#else
165 switch( len )
166 {
167 case 256:
168 return GR_LOD_256;
169 case 128:
170 return GR_LOD_128;
171 case 64:
172 return GR_LOD_64;
173 case 32:
174 return GR_LOD_32;
175 case 16:
176 return GR_LOD_16;
177 case 8:
178 return GR_LOD_8;
179 case 4:
180 return GR_LOD_4;
181 case 2:
182 return GR_LOD_2;
183 case 1:
184 return GR_LOD_1;
185 }
186 /*
187 * This is only here to make the compiler shut up.
188 */
189 return GR_LOD_1;
190#endif
191
192}
193
194static GrAspectRatio_t _txDimensionsToAspectRatio( int width, int height )
195{
196 int aspect;
197
198 aspect = ( 8 * width ) / height;
199
200#ifdef GLIDE3
201 switch( aspect )
202 {
203 case 64:
204 return GR_ASPECT_LOG2_8x1;
205 case 32:
206 return GR_ASPECT_LOG2_4x1;
207 case 16:
208 return GR_ASPECT_LOG2_2x1;
209 case 8:
210 return GR_ASPECT_LOG2_1x1;
211 case 4:
212 return GR_ASPECT_LOG2_1x2;
213 case 2:
214 return GR_ASPECT_LOG2_1x4;
215 case 1:
216 return GR_ASPECT_LOG2_1x8;
217 }
218
219 /*
220 * Make the compiler shut up.
221 */
222 return GR_ASPECT_LOG2_1x8;
223#else
224 switch( aspect )
225 {
226 case 64:
227 return GR_ASPECT_8x1;
228 case 32:
229 return GR_ASPECT_4x1;
230 case 16:
231 return GR_ASPECT_2x1;
232 case 8:
233 return GR_ASPECT_1x1;
234 case 4:
235 return GR_ASPECT_1x2;
236 case 2:
237 return GR_ASPECT_1x4;
238 case 1:
239 return GR_ASPECT_1x8;
240 }
241
242 /*
243 * Make the compiler shut up.
244 */
245 return GR_ASPECT_1x8;
246#endif
247}
248
249/*
250 * Return the smallest LOD given an aspect ratio
251 * assuming that the LODs "stop" as soon as a side
252 * length becomes 1.
253 */
254static GrLOD_t _txSmallestLOD( GrAspectRatio_t aspect )
255{
256#ifdef GLIDE3
257 switch( aspect )
258 {
259 case GR_ASPECT_LOG2_8x1:
260 case GR_ASPECT_LOG2_1x8:
261 return GR_LOD_LOG2_8;
262 case GR_ASPECT_LOG2_4x1:
263 case GR_ASPECT_LOG2_1x4:
264 return GR_LOD_LOG2_4;
265 case GR_ASPECT_LOG2_2x1:
266 case GR_ASPECT_LOG2_1x2:
267 return GR_LOD_LOG2_2;
268 case GR_ASPECT_LOG2_1x1:
269 return GR_LOD_LOG2_1;
270 }
271 /*
272 * Make the compiler shut up.
273 */
274 return GR_LOD_LOG2_1;
275#else
276 switch( aspect )
277 {
278 case GR_ASPECT_8x1:
279 case GR_ASPECT_1x8:
280 return GR_LOD_8;
281 case GR_ASPECT_4x1:
282 case GR_ASPECT_1x4:
283 return GR_LOD_4;
284 case GR_ASPECT_2x1:
285 case GR_ASPECT_1x2:
286 return GR_LOD_2;
287 case GR_ASPECT_1x1:
288 return GR_LOD_1;
289 }
290 /*
291 * Make the compiler shut up.
292 */
293 return GR_LOD_1;
294
295#endif /* GLIDE3 */
296}
297
298void txNccToPal( FxU32 *pal, const GuNccTable *ncc_table )
299{
300 int i, j;
301
302 for( i = 0; i < 16; i++ )
303 {
304 pal[i] = ncc_table->yRGB[i];
305 }
306
307 for( i = 0; i < 4; i++ )
308 {
309 for( j = 0; j < 3; j++ )
310 {
311 pal[16 + 3 * i + j] = ncc_table->iRGB[i][j];
312 pal[28 + 3 * i + j] = ncc_table->qRGB[i][j];
313 }
314 }
315}
316
317void txPalToNcc( GuNccTable *ncc_table, const FxU32 *pal ) {
318 int i, j;
319
320 for( i = 0; i < 16; i++ )
321 {
322 ncc_table->yRGB[i] = ( FxU8 )pal[i];
323 }
324
325 for( i = 0; i < 4; i++ )
326 {
327 for( j = 0; j < 3; j++ )
328 {
329 ncc_table->iRGB[i][j] = ( FxI16 )( pal[16 + 3 * i + j] );
330 ncc_table->qRGB[i][j] = ( FxI16 )( pal[28 + 3 * i + j] );
331 }
332 }
333
334 /*
335 ** pack the table Y entries
336 */
337 for ( i = 0; i < 4; i++ )
338 {
339 FxU32 packedvalue;
340
341 packedvalue = ( ( FxU32 )( ncc_table->yRGB[i*4+0] & 0xff ) );
342 packedvalue |= ( ( FxU32 )( ncc_table->yRGB[i*4+1] & 0xff ) ) << 8;
343 packedvalue |= ( ( FxU32 )( ncc_table->yRGB[i*4+2] & 0xff ) ) << 16;
344 packedvalue |= ( ( FxU32 )( ncc_table->yRGB[i*4+3] & 0xff ) ) << 24;
345
346 ncc_table->packed_data[i] = packedvalue;
347 }
348
349 /*
350 ** pack the table I entries
351 */
352 for ( i = 0; i < 4; i++ )
353 {
354 FxU32 packedvalue;
355
356 packedvalue = ( ( FxU32 )( ncc_table->iRGB[i][0] & 0x1ff ) ) << 18;
357 packedvalue |= ( ( FxU32 )( ncc_table->iRGB[i][1] & 0x1ff ) ) << 9;
358
359 packedvalue |= ( ( FxU32 )( ncc_table->iRGB[i][2] & 0x1ff ) ) << 0;
360
361 ncc_table->packed_data[i+4] = packedvalue;
362 }
363
364 /*
365 ** pack the table Q entries
366 */
367 for ( i = 0; i < 4; i++ )
368 {
369 FxU32 packedvalue;
370
371 packedvalue = ( ( FxU32 )( ncc_table->qRGB[i][0] & 0x1ff ) ) << 18;
372 packedvalue |= ( ( FxU32 )( ncc_table->qRGB[i][1] & 0x1ff ) ) << 9;;
373 packedvalue |= ( ( FxU32 )( ncc_table->qRGB[i][2] & 0x1ff ) ) << 0;
374
375 ncc_table->packed_data[i+8] = packedvalue;
376 }
377}
378
379size_t txInit3dfInfoFromFile( FILE *file,
380 Gu3dfInfo *info, GrTextureFormat_t destFormat,
381 int *destWidth, int *destHeight,
382 int mipLevels, FxU32 flags )
383{
384 long file_start_position;
385 size_t size_retval;
386 int input_format;
387 TxMip txMip;
388
389#if 0
390 printf( "enter: txInit3dfInfoFromFile\n" );
391 fflush( stdout );
392#endif
393
394 /*
395 * Save the current position of the input file so that we can
396 * later recent it.
397 */
398 file_start_position = ftell( file );
399
400 /*
401 * Read the header of the input file to find out some information
402 * about it.
403 */
404 if( ( input_format = _txReadHeader( file, &txMip ) ) == 0 )
405 {
406 return 0;
407 }
408
409 *destWidth = txMip.width;
410 *destHeight = txMip.height;
411
412 size_retval = txInit3dfInfo( info, destFormat, destWidth, destHeight,
413 mipLevels, flags );
414
415
416 /*
417 * Set the file offset back to where it was when we entered this
418 * function.
419 */
420 fseek( file, file_start_position, SEEK_SET );
421
422 /*
423 * Return the memory required for this texture.
424 */
425#if 0
426 printf( "txInit3dfInfoFromFile returning %ld\n", ( long )size_retval );
427 fflush( stdout );
428#endif
429 return size_retval;
430}
431
432size_t txInit3dfInfo( Gu3dfInfo *info, GrTextureFormat_t destFormat,
433 int *destWidth, int *destHeight,
434 int mipLevels, FxU32 flags )
435{
436 /*
437 * If auto-resize is enabled,
438 */
439 if( ( flags & TX_AUTORESIZE_MASK ) != TX_AUTORESIZE_DISABLE )
440 {
441 /*
442 * Make sure that the texture dimensions are power of two.
443 */
444 if( ( flags & TX_AUTORESIZE_MASK ) == TX_AUTORESIZE_SHRINK )
445 {
446 *destWidth = txFloorPow2( *destWidth );
447 *destHeight = txFloorPow2( *destHeight );
448 }
449 else
450 {
451 *destWidth = txCeilPow2( *destWidth );
452 *destHeight = txCeilPow2( *destHeight );
453 }
454
455 /*
456 * Make sure the dimensions are in range.
457 */
458 while( *destWidth > 256 )
459 *destWidth >>= 1;
460 while( *destHeight > 256 )
461 *destHeight >>= 1;
462
463 /*
464 * Make sure the aspect ratio is valid.
465 */
466 while( ( *destWidth / *destHeight ) > 8 )
467 {
468 *destWidth >>= 1;
469 }
470
471 while( ( *destHeight/ *destWidth ) > 8 )
472 {
473 *destHeight >>= 1;
474 }
475 }
476
477 /*
478 * Calculate the aspect ratio of the texture . . this assumse that
479 * the desired texture size is valid!
480 */
481 info->header.aspect_ratio = _txDimensionsToAspectRatio( *destWidth, *destHeight );
482
483 /*
484 * Calculate the min and max LODs for the texture.
485 */
486 info->header.large_lod = _txLengthToLOD( ( *destHeight > *destWidth ) ? *destHeight : *destWidth );
487 info->header.small_lod = _txSmallestLOD( info->header.aspect_ratio );
488
489 /*
490 * Make sure that we have the correct number of mipmap levels given
491 * the parameter "mipLevels".
492 * If mipLevels is -1, then we want all levels.
493 */
494 if( mipLevels != -1 )
495 {
496 int tmpNumLevels;
497#ifdef GLIDE3
498 tmpNumLevels = info->header.large_lod - info->header.small_lod + 1;
499#else
500 tmpNumLevels = info->header.small_lod - info->header.large_lod + 1;
501#endif
502 if( tmpNumLevels > mipLevels )
503 {
504#ifdef GLIDE3
505 info->header.small_lod += tmpNumLevels - mipLevels;
506#else
507 info->header.small_lod -= tmpNumLevels - mipLevels;
508#endif
509 }
510 }
511
512 /*
513 * Store the geometry of the texture.
514 */
515 info->header.width = *destWidth;
516 info->header.height = *destHeight;
517
518 /*
519 * Store the format of the texture.
520 */
521 info->header.format = destFormat;
522
523 info->mem_required = txTexCalcMemRequired( info->header.small_lod,
524 info->header.large_lod,
525 info->header.aspect_ratio,
526 info->header.format );
527
528 /*
529 * Return the amount of texture memory required for this texture.
530 * The user is responsible for allocating the space for the texture.
531 */
532 return info->mem_required;
533}
534
535
536FxBool txConvertFromFile( FILE *file, Gu3dfInfo *info,
537 FxU32 flags, const void *palNcc )
538{
539 long file_start_position;
540 FxBool retval;
541 TxMip txMip;
542
543 /*
544 * Save the current position of the input file so that we can
545 * later recent it.
546 */
547 file_start_position = ftell( file );
548
549 txMipReadFromFP( &txMip, "(FILE*)", file, GR_TEXFMT_ANY );
550
551 retval = txConvert( info, txMip.format, txMip.width, txMip.height,
552 txMip.data[0], flags, palNcc );
553 txFree( txMip.data[0] );
554
555 return retval;
556}
557
558FxBool txConvert( Gu3dfInfo *info, GrTextureFormat_t srcFormat,
559 int srcWidth, int srcHeight,
560 const void *srcImage, FxU32 flags,
561 const void *palNcc )
562{
563 TxMip srcMip;
564 TxMip trueColorMip;
565 TxMip outputMip;
566 TxMip tmpMip;
567
568 /*
569 * Make a txMip out of the passed data.
570 */
571 memset( &srcMip, 0, sizeof( srcMip ) );
572 srcMip.format = srcFormat;
573 srcMip.width = srcWidth;
574 srcMip.height = srcHeight;
575 srcMip.depth = 1;
576
577 if( palNcc )
578 {
579 switch( srcFormat )
580 {
581 case GR_TEXFMT_YIQ_422:
582 case GR_TEXFMT_AYIQ_8422:
583 txNccToPal( srcMip.pal, palNcc);
584 break;
585 case GR_TEXFMT_P_8:
586 memcpy( srcMip.pal, palNcc, sizeof( FxU32 ) * 256 );
587 break;
588 }
589 }
590 srcMip.data[0] = ( void * )srcImage;
591
592 /*
593 * Set up a txMip to put a true color version of the texture in.
594 */
595 memset( &trueColorMip, 0, sizeof( trueColorMip ) );
596 trueColorMip.format = GR_TEXFMT_ARGB_8888;
597 trueColorMip.width = srcWidth;
598 trueColorMip.height = srcHeight;
599 /*
600 * Set the depth to the mipmapped depth to allocate the image.
601 */
602#ifdef GLIDE3
603 trueColorMip.depth = info->header.large_lod - info->header.small_lod + 1;
604#else
605 trueColorMip.depth = info->header.small_lod - info->header.large_lod + 1;
606#endif
607 if( !txMipAlloc( &trueColorMip ) )
608 return FXFALSE;
609
610 /*
611 * Set to one level only since we only want to dequant the first
612 * level.
613 */
614 trueColorMip.depth = 1;
615
616 /*
617 * Convert from the input format to truecolor.
618 */
619 txMipDequantize( &trueColorMip, &srcMip );
620
621 /*
622 * We realy have more than one level, so. . .
623 */
624#ifdef GLIDE3
625 trueColorMip.depth = info->header.large_lod - info->header.small_lod + 1;
626#else
627 trueColorMip.depth = info->header.small_lod - info->header.large_lod + 1;
628#endif
629
630 /*
631 * WARNING! I do not free srcMip.data[0] since it is passed in by the users.
632 */
633
634 /*
635 * Resample the true color version of the input image to
636 * the passed in size. . . . this should be a valid
637 * size for the hardware to handle.
638 */
639 tmpMip = trueColorMip;
640 tmpMip.width = info->header.width;
641 tmpMip.height = info->header.height;
642 txMipAlloc( &tmpMip );
643
644 if( ( flags & TX_CLAMP_MASK ) == TX_CLAMP_DISABLE )
645 {
646 txMipResample( &tmpMip, &trueColorMip );
647 }
648 else
649 {
650 txMipClamp( &tmpMip, &trueColorMip );
651#if 0
652 txMipView( &tmpMip, "blah", FXTRUE, 0 );
653#endif
654 }
655
656
657#if 0
658 if( _heapchk() != _HEAPOK )
659 txPanic( "_heapchk failed" );
660#endif
661 txFree( trueColorMip.data[0] );
662
663 trueColorMip = tmpMip;
664
665 /*
666 * Generate mipmap levels.
667 */
668#ifdef GLIDE3
669 trueColorMip.depth = info->header.large_lod - info->header.small_lod + 1;
670#else
671 trueColorMip.depth = info->header.small_lod - info->header.large_lod + 1;
672#endif
673 txMipMipmap( &trueColorMip );
674
675#if 0
676 txMipView( &trueColorMip, "blah", FXTRUE, 0 );
677#endif
678
679 /*
680 * Convert from true color to the output color format.
681 */
682 memset( &outputMip, 0, sizeof( outputMip ) );
683 outputMip.format = info->header.format;
684 outputMip.width = info->header.width;
685 outputMip.height = info->header.height;
686 outputMip.depth = trueColorMip.depth;
687 outputMip.data[0] = info->data;
688#if 0
689 txMipAlloc( &outputMip );
690#else
691 txMipSetMipPointers( &outputMip );
692#endif
693
694 if( ( flags & TX_TARGET_PALNCC_MASK ) == TX_TARGET_PALNCC_SOURCE )
695 {
696 txMipTrueToFixedPal( &outputMip, &trueColorMip, palNcc,
697 flags & TX_FIXED_PAL_QUANT_MASK );
698 }
699 else
700 {
701 txMipQuantize( &outputMip, &trueColorMip, outputMip.format,
702 flags & TX_DITHER_MASK, flags & TX_COMPRESSION_MASK );
703 }
704
705 info->data = outputMip.data[0];
706
707 if( ( info->header.format == GR_TEXFMT_YIQ_422 ) ||
708 ( info->header.format == GR_TEXFMT_AYIQ_8422 ) )
709 {
710 txPalToNcc( &info->table.nccTable, outputMip.pal );
711 }
712
713 if( info->header.format == GR_TEXFMT_P_8 || info->header.format == GR_TEXFMT_AP_88 )
714 {
715 memcpy( info->table.palette.data, outputMip.pal, sizeof( FxU32 ) * 256 );
716 }
717
718 txFree( trueColorMip.data[0] );
719
720 return FXTRUE;
721}
722
723
Note: See TracBrowser for help on using the repository browser.