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.
22 static char rcsid[] = "$Id: rle.c,v 1.2 2001-01-31 15:17:48 bradleyb Exp $";
39 //#define RLE_CODE 0xC0
40 //#define NOT_RLE_CODE 63
43 #define NOT_RLE_CODE 31
45 void rle_expand_texture_sub( grs_bitmap * bmp, grs_bitmap * rle_temp_bitmap_1 );
49 int gr_rle_decode_asm( ubyte * src, ubyte * dest );
50 #pragma aux gr_rle_decode_asm parm [esi] [edi] value [edi] modify exact [eax ebx ecx edx esi edi] = \
86 void rle_stosb(char *dest, int len, int color);
87 #pragma aux rle_stosb = "cld rep stosb" parm [edi] [ecx] [eax] modify exact [edi ecx];
88 #elif defined __GNUC__
89 static inline int gr_rle_decode_asm( ubyte * src, ubyte * dest ) {
92 __asm__ __volatile__ (
100 " movb (%%esi), %%al;"
109 " movb (%%esi), %%al;"
115 " movb %%al, (%%edi);"
119 : "=D" (__ret), "=S" (dummy) : "1" (src), "D" (dest) : "%eax", "%ecx");
123 static inline void rle_stosb(char *dest, int len, int color) {
125 __asm__ __volatile__ (
127 : "=D" (dummy[0]), "=c" (dummy[1])
128 : "0" (dest), "1" (len), "a" (color) );
130 #elif defined _MSC_VER
131 __inline int gr_rle_decode_asm( ubyte * src, ubyte * dest )
170 __inline void rle_stosb(char *dest, int len, int color)
184 /* Well, if inline assembler is not supported for this compiler, we don't
185 **really** want ASM... */
190 void rle_stosb(ubyte *dest, int len, int color)
193 for (i=0; i<len; i++ )
198 void gr_rle_decode( ubyte * src, ubyte * dest )
202 ubyte data, count = 0;
206 if ( (data & RLE_CODE) != RLE_CODE ) {
209 count = data & NOT_RLE_CODE;
210 if (count==0) return;
212 for (i=0; i<count; i++ )
217 gr_rle_decode_asm( src, dest );
221 // Given pointer to start of one scanline of rle data, uncompress it to
222 // dest, from source pixels x1 to x2.
223 void gr_rle_expand_scanline_masked( ubyte *dest, ubyte *src, int x1, int x2 )
229 if ( x2 < x1 ) return;
233 if ( color == RLE_CODE ) return;
234 if ( (color & RLE_CODE)==RLE_CODE ) {
235 count = color & (~RLE_CODE);
245 // we know have '*count' pixels of 'color'.
247 if ( x1+count > x2 ) {
249 if ( color != 255 ) rle_stosb( dest, count, color );
253 if ( color != 255 ) rle_stosb( dest, count, color );
259 if ( color == RLE_CODE ) return;
260 if ( (color & RLE_CODE) == (RLE_CODE) ) {
261 count = color & (~RLE_CODE);
267 // we know have '*count' pixels of 'color'.
268 if ( i+count <= x2 ) {
269 if ( color != 255 )rle_stosb( dest, count, color );
274 if ( color != 255 )rle_stosb( dest, count, color );
282 void gr_rle_expand_scanline( ubyte *dest, ubyte *src, int x1, int x2 )
288 if ( x2 < x1 ) return;
292 if ( color == RLE_CODE ) return;
293 if ( (color & RLE_CODE)==RLE_CODE ) {
294 count = color & (~RLE_CODE);
304 // we know have '*count' pixels of 'color'.
306 if ( x1+count > x2 ) {
308 rle_stosb( dest, count, color );
312 rle_stosb( dest, count, color );
318 if ( color == RLE_CODE ) return;
319 if ( (color & RLE_CODE)==RLE_CODE ) {
320 count = color & (~RLE_CODE);
326 // we know have '*count' pixels of 'color'.
327 if ( i+count <= x2 ) {
328 rle_stosb( dest, count, color );
333 rle_stosb( dest, count, color );
341 int gr_rle_encode( int org_size, ubyte *src, ubyte *dest )
352 for (i=1; i<org_size; i++ ) {
356 if ( (count==1) && ((oc & RLE_CODE)!=RLE_CODE) ) {
358 Assert( oc != RLE_CODE );
369 if ( count == NOT_RLE_CODE ) {
377 if ( (count==1) && ((oc & RLE_CODE)!=RLE_CODE) ) {
379 Assert( oc != RLE_CODE );
388 return dest-dest_start;
392 int gr_rle_getsize( int org_size, ubyte *src )
402 for (i=1; i<org_size; i++ ) {
406 if ( (count==1) && ((oc & RLE_CODE)!=RLE_CODE) ) {
417 if ( count == NOT_RLE_CODE ) {
424 if ( (count==1) && ((oc & RLE_CODE)!=RLE_CODE) ) {
436 int gr_bitmap_rle_compress( grs_bitmap * bmp )
442 rle_data=d_malloc( (bmp->bm_w+1)* bmp->bm_h );
443 if (rle_data==NULL) return 0;
444 doffset = 4 + bmp->bm_h;
445 for (y=0; y<bmp->bm_h; y++ ) {
446 d1= gr_rle_getsize( bmp->bm_w, &bmp->bm_data[bmp->bm_w*y] );
447 if ( ((doffset+d1) > bmp->bm_w*bmp->bm_h) || (d1 > 255 ) ) {
451 d = gr_rle_encode( bmp->bm_w, &bmp->bm_data[bmp->bm_w*y], &rle_data[doffset] );
456 //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 );
457 memcpy( rle_data, &doffset, 4 );
458 memcpy( bmp->bm_data, rle_data, doffset );
460 bmp->bm_flags |= BM_FLAG_RLE;
464 #define MAX_CACHE_BITMAPS 32
466 typedef struct rle_cache_element {
467 grs_bitmap * rle_bitmap;
469 grs_bitmap * expanded_bitmap;
473 int rle_cache_initialized = 0;
476 rle_cache_element rle_cache[MAX_CACHE_BITMAPS];
481 void rle_cache_close(void)
483 if (rle_cache_initialized) {
485 rle_cache_initialized = 0;
486 for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
487 gr_free_bitmap(rle_cache[i].expanded_bitmap);
492 void rle_cache_init()
495 for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
496 rle_cache[i].rle_bitmap = NULL;
497 rle_cache[i].expanded_bitmap = gr_create_bitmap( 64, 64 );
498 rle_cache[i].last_used = 0;
499 Assert( rle_cache[i].expanded_bitmap != NULL );
501 rle_cache_initialized = 1;
502 atexit( rle_cache_close );
505 void rle_cache_flush()
508 for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
509 rle_cache[i].rle_bitmap = NULL;
510 rle_cache[i].last_used = 0;
516 grs_bitmap * rle_expand_texture( grs_bitmap * bmp )
519 int lowest_count, lc;
520 int least_recently_used;
522 if (!rle_cache_initialized) rle_cache_init();
524 Assert( !(bmp->bm_flags & BM_FLAG_PAGED_OUT) );
528 if ( rle_counter < lc ) {
529 for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
530 rle_cache[i].rle_bitmap = NULL;
531 rle_cache[i].last_used = 0;
535 // if (((rle_counter % 100)==1) && (rle_hits+rle_misses > 0))
536 // mprintf(( 0, "RLE-CACHE %d%%, H:%d, M:%d\n", (rle_misses*100)/(rle_hits+rle_misses), rle_hits, rle_misses ));
538 lowest_count = rle_cache[rle_next].last_used;
539 least_recently_used = rle_next;
541 if ( rle_next >= MAX_CACHE_BITMAPS )
544 for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
545 if (rle_cache[i].rle_bitmap == bmp) {
547 rle_cache[i].last_used = rle_counter;
548 return rle_cache[i].expanded_bitmap;
550 if ( rle_cache[i].last_used < lowest_count ) {
551 lowest_count = rle_cache[i].last_used;
552 least_recently_used = i;
556 rle_expand_texture_sub( bmp, rle_cache[least_recently_used].expanded_bitmap );
557 rle_cache[least_recently_used].rle_bitmap = bmp;
558 rle_cache[least_recently_used].last_used = rle_counter;
559 return rle_cache[least_recently_used].expanded_bitmap;
562 void rle_expand_texture_sub( grs_bitmap * bmp, grs_bitmap * rle_temp_bitmap_1 )
564 unsigned char * dbits;
565 unsigned char * sbits;
568 unsigned char * dbits1;
572 Assert (bmp->iMagic == BM_MAGIC_NUMBER);
575 sbits = &bmp->bm_data[4 + 64];
576 dbits = rle_temp_bitmap_1->bm_data;
578 rle_temp_bitmap_1->bm_flags = bmp->bm_flags & (~BM_FLAG_RLE);
580 for (i=0; i < 64; i++ ) {
582 gr_rle_decode(sbits,dbits);
584 dbits1=(unsigned char *)gr_rle_decode_asm( sbits, dbits );
586 sbits += (int)bmp->bm_data[4+i];
589 Assert( dbits == dbits1 ); // Get John, bogus rle data!
593 gr_set_bitmap_data (rle_temp_bitmap_1, rle_temp_bitmap_1->bm_data);
598 void gr_rle_expand_scanline_generic( grs_bitmap * dest, int dx, int dy, ubyte *src,
599 int x1, int x2, int masked )
605 if ( x2 < x1 ) return;
609 if ( color == RLE_CODE ) return;
610 if ( (color & RLE_CODE) == RLE_CODE ) {
611 count = color & NOT_RLE_CODE;
621 // we know have '*count' pixels of 'color'.
623 if ( x1+count > x2 ) {
625 if (!masked || color != 255)
626 for ( j=0; j<count; j++ )
627 gr_bm_pixel( dest, dx++, dy, color );
631 if (masked && color == 255)
634 for ( j=0; j<count; j++ )
635 gr_bm_pixel( dest, dx++, dy, color );
640 if ( color == RLE_CODE ) return;
641 if ( (color & RLE_CODE) == RLE_CODE ) {
642 count = color & NOT_RLE_CODE;
648 // we know have '*count' pixels of 'color'.
649 if ( i+count <= x2 ) {
650 if (masked && color == 255)
653 for ( j=0; j<count; j++ )
654 gr_bm_pixel( dest, dx++, dy, color );
658 if (masked && color == 255)
661 for ( j=0; j<count; j++ )
662 gr_bm_pixel( dest, dx++, dy, color );