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

Last change on this file was 6653, checked in by bird, 24 years ago

Added $Id:$ keyword.

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