1 /*THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
2 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
3 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
4 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
5 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
6 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
7 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
8 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
9 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
10 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
13 * Changed shorts to ints in parameters.
18 static char rcsid[] = "$Id: rle.c,v 1.1.1.1 2001-01-19 03:29:57 bradleyb Exp $";
36 //#define RLE_CODE 0xC0
37 //#define NOT_RLE_CODE 63
40 #define NOT_RLE_CODE 31
42 void rle_expand_texture_sub( grs_bitmap * bmp, grs_bitmap * rle_temp_bitmap_1 );
46 int gr_rle_decode_asm( ubyte * src, ubyte * dest );
47 #pragma aux gr_rle_decode_asm parm [esi] [edi] value [edi] modify exact [eax ebx ecx edx esi edi] = \
83 void rle_stosb(char *dest, int len, int color);
84 #pragma aux rle_stosb = "cld rep stosb" parm [edi] [ecx] [eax] modify exact [edi ecx];
85 #elif defined __GNUC__
86 static inline int gr_rle_decode_asm( ubyte * src, ubyte * dest ) {
89 __asm__ __volatile__ (
97 " movb (%%esi), %%al;"
106 " movb (%%esi), %%al;"
112 " movb %%al, (%%edi);"
116 : "=D" (__ret), "=S" (dummy) : "1" (src), "D" (dest) : "%eax", "%ecx");
120 static inline void rle_stosb(char *dest, int len, int color) {
122 __asm__ __volatile__ (
124 : "=D" (dummy[0]), "=c" (dummy[1])
125 : "0" (dest), "1" (len), "a" (color) );
127 #elif defined _MSC_VER
128 __inline int gr_rle_decode_asm( ubyte * src, ubyte * dest )
167 __inline void rle_stosb(char *dest, int len, int color)
181 /* Well, if inline assembler is not supported for this compiler, we don't
182 **really** want ASM... */
187 void rle_stosb(ubyte *dest, int len, int color)
190 for (i=0; i<len; i++ )
195 void gr_rle_decode( ubyte * src, ubyte * dest )
199 ubyte data, count = 0;
203 if ( (data & RLE_CODE) != RLE_CODE ) {
206 count = data & NOT_RLE_CODE;
207 if (count==0) return;
209 for (i=0; i<count; i++ )
214 gr_rle_decode_asm( src, dest );
218 // Given pointer to start of one scanline of rle data, uncompress it to
219 // dest, from source pixels x1 to x2.
220 void gr_rle_expand_scanline_masked( ubyte *dest, ubyte *src, int x1, int x2 )
226 if ( x2 < x1 ) return;
230 if ( color == RLE_CODE ) return;
231 if ( (color & RLE_CODE)==RLE_CODE ) {
232 count = color & (~RLE_CODE);
242 // we know have '*count' pixels of 'color'.
244 if ( x1+count > x2 ) {
246 if ( color != 255 ) rle_stosb( dest, count, color );
250 if ( color != 255 ) rle_stosb( dest, count, color );
256 if ( color == RLE_CODE ) return;
257 if ( (color & RLE_CODE) == (RLE_CODE) ) {
258 count = color & (~RLE_CODE);
264 // we know have '*count' pixels of 'color'.
265 if ( i+count <= x2 ) {
266 if ( color != 255 )rle_stosb( dest, count, color );
271 if ( color != 255 )rle_stosb( dest, count, color );
279 void gr_rle_expand_scanline( ubyte *dest, ubyte *src, int x1, int x2 )
285 if ( x2 < x1 ) return;
289 if ( color == RLE_CODE ) return;
290 if ( (color & RLE_CODE)==RLE_CODE ) {
291 count = color & (~RLE_CODE);
301 // we know have '*count' pixels of 'color'.
303 if ( x1+count > x2 ) {
305 rle_stosb( dest, count, color );
309 rle_stosb( dest, count, color );
315 if ( color == RLE_CODE ) return;
316 if ( (color & RLE_CODE)==RLE_CODE ) {
317 count = color & (~RLE_CODE);
323 // we know have '*count' pixels of 'color'.
324 if ( i+count <= x2 ) {
325 rle_stosb( dest, count, color );
330 rle_stosb( dest, count, color );
338 int gr_rle_encode( int org_size, ubyte *src, ubyte *dest )
349 for (i=1; i<org_size; i++ ) {
353 if ( (count==1) && ((oc & RLE_CODE)!=RLE_CODE) ) {
355 Assert( oc != RLE_CODE );
366 if ( count == NOT_RLE_CODE ) {
374 if ( (count==1) && ((oc & RLE_CODE)!=RLE_CODE) ) {
376 Assert( oc != RLE_CODE );
385 return dest-dest_start;
389 int gr_rle_getsize( int org_size, ubyte *src )
399 for (i=1; i<org_size; i++ ) {
403 if ( (count==1) && ((oc & RLE_CODE)!=RLE_CODE) ) {
414 if ( count == NOT_RLE_CODE ) {
421 if ( (count==1) && ((oc & RLE_CODE)!=RLE_CODE) ) {
433 int gr_bitmap_rle_compress( grs_bitmap * bmp )
439 rle_data=d_malloc( (bmp->bm_w+1)* bmp->bm_h );
440 if (rle_data==NULL) return 0;
441 doffset = 4 + bmp->bm_h;
442 for (y=0; y<bmp->bm_h; y++ ) {
443 d1= gr_rle_getsize( bmp->bm_w, &bmp->bm_data[bmp->bm_w*y] );
444 if ( ((doffset+d1) > bmp->bm_w*bmp->bm_h) || (d1 > 255 ) ) {
448 d = gr_rle_encode( bmp->bm_w, &bmp->bm_data[bmp->bm_w*y], &rle_data[doffset] );
453 //mprintf( 0, "Bitmap of size %dx%d, (%d bytes) went down to %d bytes\n", bmp->bm_w, bmp->bm_h, bmp->bm_h*bmp->bm_w, doffset );
454 memcpy( rle_data, &doffset, 4 );
455 memcpy( bmp->bm_data, rle_data, doffset );
457 bmp->bm_flags |= BM_FLAG_RLE;
461 #define MAX_CACHE_BITMAPS 32
463 typedef struct rle_cache_element {
464 grs_bitmap * rle_bitmap;
466 grs_bitmap * expanded_bitmap;
470 int rle_cache_initialized = 0;
473 rle_cache_element rle_cache[MAX_CACHE_BITMAPS];
478 void rle_cache_close(void)
480 if (rle_cache_initialized) {
482 rle_cache_initialized = 0;
483 for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
484 gr_free_bitmap(rle_cache[i].expanded_bitmap);
489 void rle_cache_init()
492 for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
493 rle_cache[i].rle_bitmap = NULL;
494 rle_cache[i].expanded_bitmap = gr_create_bitmap( 64, 64 );
495 rle_cache[i].last_used = 0;
496 Assert( rle_cache[i].expanded_bitmap != NULL );
498 rle_cache_initialized = 1;
499 atexit( rle_cache_close );
502 void rle_cache_flush()
505 for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
506 rle_cache[i].rle_bitmap = NULL;
507 rle_cache[i].last_used = 0;
513 grs_bitmap * rle_expand_texture( grs_bitmap * bmp )
516 int lowest_count, lc;
517 int least_recently_used;
519 if (!rle_cache_initialized) rle_cache_init();
521 Assert( !(bmp->bm_flags & BM_FLAG_PAGED_OUT) );
525 if ( rle_counter < lc ) {
526 for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
527 rle_cache[i].rle_bitmap = NULL;
528 rle_cache[i].last_used = 0;
532 // if (((rle_counter % 100)==1) && (rle_hits+rle_misses > 0))
533 // mprintf(( 0, "RLE-CACHE %d%%, H:%d, M:%d\n", (rle_misses*100)/(rle_hits+rle_misses), rle_hits, rle_misses ));
535 lowest_count = rle_cache[rle_next].last_used;
536 least_recently_used = rle_next;
538 if ( rle_next >= MAX_CACHE_BITMAPS )
541 for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
542 if (rle_cache[i].rle_bitmap == bmp) {
544 rle_cache[i].last_used = rle_counter;
545 return rle_cache[i].expanded_bitmap;
547 if ( rle_cache[i].last_used < lowest_count ) {
548 lowest_count = rle_cache[i].last_used;
549 least_recently_used = i;
553 rle_expand_texture_sub( bmp, rle_cache[least_recently_used].expanded_bitmap );
554 rle_cache[least_recently_used].rle_bitmap = bmp;
555 rle_cache[least_recently_used].last_used = rle_counter;
556 return rle_cache[least_recently_used].expanded_bitmap;
559 void rle_expand_texture_sub( grs_bitmap * bmp, grs_bitmap * rle_temp_bitmap_1 )
561 unsigned char * dbits;
562 unsigned char * sbits;
565 unsigned char * dbits1;
569 Assert (bmp->iMagic == BM_MAGIC_NUMBER);
572 sbits = &bmp->bm_data[4 + 64];
573 dbits = rle_temp_bitmap_1->bm_data;
575 rle_temp_bitmap_1->bm_flags = bmp->bm_flags & (~BM_FLAG_RLE);
577 for (i=0; i < 64; i++ ) {
579 gr_rle_decode(sbits,dbits);
581 dbits1=(unsigned char *)gr_rle_decode_asm( sbits, dbits );
583 sbits += (int)bmp->bm_data[4+i];
586 Assert( dbits == dbits1 ); // Get John, bogus rle data!
590 gr_set_bitmap_data (rle_temp_bitmap_1, rle_temp_bitmap_1->bm_data);
595 void gr_rle_expand_scanline_generic( grs_bitmap * dest, int dx, int dy, ubyte *src,
596 int x1, int x2, int masked )
602 if ( x2 < x1 ) return;
606 if ( color == RLE_CODE ) return;
607 if ( (color & RLE_CODE) == RLE_CODE ) {
608 count = color & NOT_RLE_CODE;
618 // we know have '*count' pixels of 'color'.
620 if ( x1+count > x2 ) {
622 if (!masked || color != 255)
623 for ( j=0; j<count; j++ )
624 gr_bm_pixel( dest, dx++, dy, color );
628 if (masked && color == 255)
631 for ( j=0; j<count; j++ )
632 gr_bm_pixel( dest, dx++, dy, color );
637 if ( color == RLE_CODE ) return;
638 if ( (color & RLE_CODE) == RLE_CODE ) {
639 count = color & NOT_RLE_CODE;
645 // we know have '*count' pixels of 'color'.
646 if ( i+count <= x2 ) {
647 if (masked && color == 255)
650 for ( j=0; j<count; j++ )
651 gr_bm_pixel( dest, dx++, dy, color );
655 if (masked && color == 255)
658 for ( j=0; j<count; j++ )
659 gr_bm_pixel( dest, dx++, dy, color );