]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/bitblt.cpp
Initial revision
[taylor/freespace2.git] / src / graphics / bitblt.cpp
1 /*
2  * $Logfile: /Freespace2/code/Graphics/Bitblt.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Code to do software bitblt type stuff
8  *
9  * $Log$
10  * Revision 1.1  2002/05/03 03:28:09  root
11  * Initial revision
12  *
13  * 
14  * 3     11/30/98 1:07p Dave
15  * 16 bit conversion, first run.
16  * 
17  * 2     10/07/98 10:52a Dave
18  * Initial checkin.
19  * 
20  * 1     10/07/98 10:48a Dave
21  * 
22  * 2     4/14/98 12:15p John
23  * Made 16-bpp movies work.
24  * 
25  * 1     3/25/98 8:07p John
26  * Split software renderer into Win32 and DirectX
27  *
28  * $NoKeywords: $
29  */
30
31 #include "osapi.h"
32 #include "2d.h"
33 #include "bmpman.h"
34 #include "key.h"
35 #include "floating.h"
36 #include "palman.h"
37 #include "grsoft.h"
38 #include "grinternal.h"
39
40 // Headers for 2d functions
41 #include "bitblt.h"
42
43 MONITOR( Num2dBitmaps );        
44
45 void gr8_aabitmap_ex(int x,int y,int w,int h,int sx,int sy)
46 {
47 #if 0
48         int hi;
49         bitmap * bmp;
50
51         if ( w < 1 ) return;
52         if ( h < 1 ) return;
53
54         MONITOR_INC( Num2dBitmaps, 1 ); 
55
56         if ( !Current_alphacolor )      return;
57
58         //      mprintf(( "x=%d, y=%d, w=%d, h=%d\n", x, y, w, h ));
59         //      mprintf(( "sx=%d, sy=%d, bw=%d, bh=%d\n", sx, sy, bmp->w, bmp->h ));
60
61         bmp = bm_lock( gr_screen.current_bitmap, 8, BMP_RLE|BMP_NO_PALETTE_MAP );        
62
63         gr_lock();
64
65         if (bmp->flags & BMP_RLE)       {
66                 int * offsets = (int *)(bmp->data);
67                 ubyte *lookup = &Current_alphacolor->table.lookup[0][0];
68                         
69                 for (hi=0; hi < h; hi++ )    {
70                         ubyte * dp = GR_SCREEN_PTR(ubyte,x,y+hi);
71                         ubyte * sp = (ubyte *)bmp->data + offsets[sy+hi];
72
73                         int x1 = sx;
74                         int x2 = sx+w;
75                         int i = 0;                      
76
77                         while(i<x1)     {                       
78                                 int count;
79
80                                 count = int(*sp++);
81                                 int run_span = count & 0x80;
82
83                                 count = (count & (~0x80))+1;            
84                                 if ( i+count > x1 ) {
85                                         // This span crosses X1.. so skip some and draw some
86                                         if ( i+count >= x2 ) {
87                                                 count = x2 - i;
88                                         }
89
90                                         if ( run_span ) {
91                                                 // RLE'd data
92                                                 ubyte c = *sp++;
93
94                                                 if ( c > 0 )    {                                       
95                                                         // We have 'count' pixels of c
96                                                         ubyte *tmp_lookup = &lookup[c<<8];
97                                                         while( count-- ) {
98                                                                 if ( i >= x1 )  {
99                                                                         *dp = tmp_lookup[*dp];
100                                                                         dp++;
101                                                                 }
102                                                                 i++;
103                                                         }       
104                                                 } else {
105                                                         while( count-- ) {
106                                                                 if ( i >= x1 )  {
107                                                                         dp++;
108                                                                 }
109                                                                 i++;
110                                                         }       
111                                                 }
112                                         } else {
113                                                 // non RLE'd data
114
115                                                 // We have 'count' un-rle'd pixels
116                                                 while( count-- ) {
117                                                         if ( i >= x1 )  {
118                                                                 ubyte c = *sp;
119                                                                 *dp = lookup[(c<<8) | *dp];
120                                                                 dp++;
121                                                         }
122                                                         sp++;
123                                                         i++;
124                                                 }       
125                                         }
126
127                                 } else {
128                                         i += count;
129                                         if ( run_span ) {
130                                                 // RLE'd data
131                                                 sp++; 
132                                         } else {
133                                                 sp += count;
134                                         }
135                                 }
136                         }
137
138                         while(i<x2)     {                       
139                                 int count;
140
141                                 count = int(*sp++);
142                                 int run_span = count & 0x80;
143
144                                 count = (count & (~0x80))+1;            
145                                 if ( i+count >= x2 ) {
146                                         count = x2 - i;
147                                 }
148                                 i += count;
149
150                                 ubyte *end_ptr = dp + count;
151                                 
152                                 if ( count > 0 )        {
153                                         if ( run_span ) {
154                                                 // RLE'd data
155                                                 ubyte c = *sp++;
156
157                                                 if ( c > 0 )    {                                       
158                                                         // We have 'count' pixels of c
159                                                         ubyte *tmp_lookup = &lookup[c<<8];
160
161                                                         while( count >= 4 )     {
162                                                                 // We have to plot at least 4 pixels of constant color starting at 'dp'
163                                                                 dp[0] = tmp_lookup[dp[0]];
164                                                                 dp[1] = tmp_lookup[dp[1]];
165                                                                 dp[2] = tmp_lookup[dp[2]];
166                                                                 dp[3] = tmp_lookup[dp[3]];
167
168                                                                 count -= 4;
169                                                                 dp += 4;
170                                                         } 
171
172                                                         while ( count > 0 )     {
173                                                                 *dp = tmp_lookup[*dp];
174                                                                 dp++;
175                                                                 count--;
176                                                         }
177                                                 } 
178                                         } else {
179                                                 // non RLE'd data
180
181                                                 // We have 'count' un-rle'd pixels
182                                                 do {
183                                                         ubyte c = *sp++;
184                                                         *dp = lookup[(c<<8) | *dp];
185                                                         dp++;
186                                                 } while ( dp < end_ptr );
187                                         }
188                                 }
189
190                                 dp = end_ptr;
191                         }
192
193                 }
194         } else {
195                 ubyte * sptr = (ubyte *)( bmp->data + (sy*bmp->w+sx) );
196                 ubyte *lookup = (ubyte *)&Current_alphacolor->table.lookup[0][0];
197
198                 for (hi=0; hi<h; hi++ ) {
199                         int j;
200                         ubyte c, * sp = sptr;   
201                         ubyte * dp = GR_SCREEN_PTR(ubyte,x,hi+y);
202                         for (j=0; j<w; j++ )    {
203                                 c = *sp++;
204                                 if ( c > 0 ) {
205                                         *dp = lookup[(c<<8) | *dp];
206                                 }
207                                 dp++;
208                         }
209                         sptr += bmp->w;
210                 }
211         }
212
213         gr_unlock();
214         bm_unlock(gr_screen.current_bitmap);
215 #endif
216 }
217
218 void grx_aabitmap_ex(int x,int y,int w,int h,int sx,int sy)
219 {
220         int reclip;
221         #ifndef NDEBUG
222         int count = 0;
223         #endif
224
225         int dx1=x, dx2=x+w-1;
226         int dy1=y, dy2=y+h-1;
227
228         int bw, bh;
229         bm_get_info( gr_screen.current_bitmap, &bw, &bh, NULL );
230
231         do {
232                 reclip = 0;
233                 #ifndef NDEBUG
234                         if ( count > 1 ) Int3();
235                         count++;
236                 #endif
237         
238                 if ((dx1 > gr_screen.clip_right ) || (dx2 < gr_screen.clip_left)) return;
239                 if ((dy1 > gr_screen.clip_bottom ) || (dy2 < gr_screen.clip_top)) return;
240                 if ( dx1 < gr_screen.clip_left ) { sx += gr_screen.clip_left-dx1; dx1 = gr_screen.clip_left; }
241                 if ( dy1 < gr_screen.clip_top ) { sy += gr_screen.clip_top-dy1; dy1 = gr_screen.clip_top; }
242                 if ( dx2 > gr_screen.clip_right )       { dx2 = gr_screen.clip_right; }
243                 if ( dy2 > gr_screen.clip_bottom )      { dy2 = gr_screen.clip_bottom; }
244
245                 if ( sx < 0 ) {
246                         dx1 -= sx;
247                         sx = 0;
248                         reclip = 1;
249                 }
250
251                 if ( sy < 0 ) {
252                         dy1 -= sy;
253                         sy = 0;
254                         reclip = 1;
255                 }
256
257                 w = dx2-dx1+1;
258                 h = dy2-dy1+1;
259
260                 if ( sx + w > bw ) {
261                         w = bw - sx;
262                         dx2 = dx1 + w - 1;
263                 }
264
265                 if ( sy + h > bh ) {
266                         h = bh - sy;
267                         dy2 = dy1 + h - 1;
268                 }
269
270                 if ( w < 1 ) return;            // clipped away!
271                 if ( h < 1 ) return;            // clipped away!
272
273         } while (reclip);
274
275         // Make sure clipping algorithm works
276         #ifndef NDEBUG
277                 Assert( w > 0 );
278                 Assert( h > 0 );
279                 Assert( w == (dx2-dx1+1) );
280                 Assert( h == (dy2-dy1+1) );
281                 Assert( sx >= 0 );
282                 Assert( sy >= 0 );
283                 Assert( sx+w <= bw );
284                 Assert( sy+h <= bh );
285                 Assert( dx2 >= dx1 );
286                 Assert( dy2 >= dy1 );
287                 Assert( (dx1 >= gr_screen.clip_left ) && (dx1 <= gr_screen.clip_right) );
288                 Assert( (dx2 >= gr_screen.clip_left ) && (dx2 <= gr_screen.clip_right) );
289                 Assert( (dy1 >= gr_screen.clip_top ) && (dy1 <= gr_screen.clip_bottom) );
290                 Assert( (dy2 >= gr_screen.clip_top ) && (dy2 <= gr_screen.clip_bottom) );
291         #endif
292
293         // We now have dx1,dy1 and dx2,dy2 and sx, sy all set validly within clip regions.
294
295         // Draw bitmap bm[sx,sy] into (dx1,dy1)-(dx2,dy2)
296
297         switch( gr_screen.bits_per_pixel )      {
298         case 8: 
299                 gr8_aabitmap_ex(dx1,dy1,dx2-dx1+1,dy2-dy1+1,sx,sy);
300                 break;
301
302         default:
303                 Error( LOCATION, "Unsupported BPP=%d in grx_aabitmap_ex!\n", gr_screen.bytes_per_pixel );
304         }
305
306
307 }
308
309
310 void gr8_bitmap_ex(int x,int y,int w,int h,int sx,int sy)
311 {
312 #if 0
313         MONITOR_INC( Num2dBitmaps, 1 ); 
314
315         gr_lock();
316
317         // Normal bitblt
318         int i;
319         bitmap * bmp;
320         ubyte * sptr;
321
322         bmp = bm_lock( gr_screen.current_bitmap, 8, 0 );
323         sptr = (ubyte *)( bmp->data + (sy*bmp->w+sx) );
324
325         //mprintf(( "x=%d, y=%d, w=%d, h=%d\n", x, y, w, h ));
326         //mprintf(( "sx=%d, sy=%d, bw=%d, bh=%d\n", sx, sy, bmp->w, bmp->h ));
327
328         if ( bmp->flags & BMP_XPARENT ) {
329                 for (i=0; i<h; i++ )    {
330                         int j;
331                         ubyte c, * sp = sptr;   
332                         ubyte * dp = GR_SCREEN_PTR(ubyte,x,i+y);
333                         for (j=0; j<w; j++ )    {
334                                 c = *sp++;
335                                 if (c != 255) *dp = c;
336                                 dp++;
337                         }
338                         sptr += bmp->w;
339                 }
340         } else {
341                 for (i=0; i<h; i++ )    {
342                         ubyte *dptr = GR_SCREEN_PTR(ubyte,x,i+y);
343                         memcpy( dptr, sptr, w );
344                         sptr += bmp->w;
345                 }
346         }
347         bm_unlock(gr_screen.current_bitmap);
348
349         gr_unlock();
350 #endif
351 }
352
353
354
355 void grx_bitmap_ex(int x,int y,int w,int h,int sx,int sy)
356 {
357         int reclip;
358         #ifndef NDEBUG
359         int count = 0;
360         #endif
361
362         int dx1=x, dx2=x+w-1;
363         int dy1=y, dy2=y+h-1;
364
365         int bw, bh;
366         bm_get_info( gr_screen.current_bitmap, &bw, &bh, NULL );
367
368         do {
369                 reclip = 0;
370                 #ifndef NDEBUG
371                         if ( count > 1 ) Int3();
372                         count++;
373                 #endif
374         
375                 if ((dx1 > gr_screen.clip_right ) || (dx2 < gr_screen.clip_left)) return;
376                 if ((dy1 > gr_screen.clip_bottom ) || (dy2 < gr_screen.clip_top)) return;
377                 if ( dx1 < gr_screen.clip_left ) { sx += gr_screen.clip_left-dx1; dx1 = gr_screen.clip_left; }
378                 if ( dy1 < gr_screen.clip_top ) { sy += gr_screen.clip_top-dy1; dy1 = gr_screen.clip_top; }
379                 if ( dx2 > gr_screen.clip_right )       { dx2 = gr_screen.clip_right; }
380                 if ( dy2 > gr_screen.clip_bottom )      { dy2 = gr_screen.clip_bottom; }
381
382                 if ( sx < 0 ) {
383                         dx1 -= sx;
384                         sx = 0;
385                         reclip = 1;
386                 }
387
388                 if ( sy < 0 ) {
389                         dy1 -= sy;
390                         sy = 0;
391                         reclip = 1;
392                 }
393
394                 w = dx2-dx1+1;
395                 h = dy2-dy1+1;
396
397                 if ( sx + w > bw ) {
398                         w = bw - sx;
399                         dx2 = dx1 + w - 1;
400                 }
401
402                 if ( sy + h > bh ) {
403                         h = bh - sy;
404                         dy2 = dy1 + h - 1;
405                 }
406
407                 if ( w < 1 ) return;            // clipped away!
408                 if ( h < 1 ) return;            // clipped away!
409
410         } while (reclip);
411
412         // Make sure clipping algorithm works
413         #ifndef NDEBUG
414                 Assert( w > 0 );
415                 Assert( h > 0 );
416                 Assert( w == (dx2-dx1+1) );
417                 Assert( h == (dy2-dy1+1) );
418                 Assert( sx >= 0 );
419                 Assert( sy >= 0 );
420                 Assert( sx+w <= bw );
421                 Assert( sy+h <= bh );
422                 Assert( dx2 >= dx1 );
423                 Assert( dy2 >= dy1 );
424                 Assert( (dx1 >= gr_screen.clip_left ) && (dx1 <= gr_screen.clip_right) );
425                 Assert( (dx2 >= gr_screen.clip_left ) && (dx2 <= gr_screen.clip_right) );
426                 Assert( (dy1 >= gr_screen.clip_top ) && (dy1 <= gr_screen.clip_bottom) );
427                 Assert( (dy2 >= gr_screen.clip_top ) && (dy2 <= gr_screen.clip_bottom) );
428         #endif
429
430         // We now have dx1,dy1 and dx2,dy2 and sx, sy all set validly within clip regions.
431
432         // Draw bitmap bm[sx,sy] into (dx1,dy1)-(dx2,dy2)
433
434         gr8_bitmap_ex(dx1,dy1,dx2-dx1+1,dy2-dy1+1,sx,sy);
435 }
436
437
438
439 void grx_bitmap(int x,int y)
440 {
441         int w, h;
442
443         bm_get_info( gr_screen.current_bitmap, &w, &h, NULL );
444         int dx1=x, dx2=x+w-1;
445         int dy1=y, dy2=y+h-1;
446         int sx=0, sy=0;
447
448         if ((dx1 > gr_screen.clip_right ) || (dx2 < gr_screen.clip_left)) return;
449         if ((dy1 > gr_screen.clip_bottom ) || (dy2 < gr_screen.clip_top)) return;
450         if ( dx1 < gr_screen.clip_left ) { sx = gr_screen.clip_left-dx1; dx1 = gr_screen.clip_left; }
451         if ( dy1 < gr_screen.clip_top ) { sy = gr_screen.clip_top-dy1; dy1 = gr_screen.clip_top; }
452         if ( dx2 > gr_screen.clip_right )       { dx2 = gr_screen.clip_right; }
453         if ( dy2 > gr_screen.clip_bottom )      { dy2 = gr_screen.clip_bottom; }
454
455         if ( sx < 0 ) return;
456         if ( sy < 0 ) return;
457         if ( sx >= w ) return;
458         if ( sy >= h ) return;
459
460         // Draw bitmap bm[sx,sy] into (dx1,dy1)-(dx2,dy2)
461
462         gr8_bitmap_ex(dx1,dy1,dx2-dx1+1,dy2-dy1+1,sx,sy);
463 }
464
465 void grx_aabitmap(int x,int y)
466 {
467         int w, h;
468
469         bm_get_info( gr_screen.current_bitmap, &w, &h, NULL );
470         int dx1=x, dx2=x+w-1;
471         int dy1=y, dy2=y+h-1;
472         int sx=0, sy=0;
473
474         if ((dx1 > gr_screen.clip_right ) || (dx2 < gr_screen.clip_left)) return;
475         if ((dy1 > gr_screen.clip_bottom ) || (dy2 < gr_screen.clip_top)) return;
476         if ( dx1 < gr_screen.clip_left ) { sx = gr_screen.clip_left-dx1; dx1 = gr_screen.clip_left; }
477         if ( dy1 < gr_screen.clip_top ) { sy = gr_screen.clip_top-dy1; dy1 = gr_screen.clip_top; }
478         if ( dx2 > gr_screen.clip_right )       { dx2 = gr_screen.clip_right; }
479         if ( dy2 > gr_screen.clip_bottom )      { dy2 = gr_screen.clip_bottom; }
480
481         if ( sx < 0 ) return;
482         if ( sy < 0 ) return;
483         if ( sx >= w ) return;
484         if ( sy >= h ) return;
485
486         // Draw bitmap bm[sx,sy] into (dx1,dy1)-(dx2,dy2)
487
488         gr8_aabitmap_ex(dx1,dy1,dx2-dx1+1,dy2-dy1+1,sx,sy);
489 }
490