src/video/SDL_blit.h

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. FORMAT_EQUAL
  2. RGB_FROM_PIXEL
  3. RGB_FROM_RGB565
  4. RGB_FROM_RGB555
  5. RGB_FROM_RGB888
  6. RETRIEVE_RGB_PIXEL
  7. DISEMBLE_RGB
  8. PIXEL_FROM_RGB
  9. RGB565_FROM_RGB
  10. RGB555_FROM_RGB
  11. RGB888_FROM_RGB
  12. ASSEMBLE_RGB
  13. ASSEMBLE_RGB_AMASK
  14. RGBA_FROM_PIXEL
  15. RGBA_FROM_8888
  16. RGBA_FROM_RGBA8888
  17. RGBA_FROM_ARGB8888
  18. RGBA_FROM_ABGR8888
  19. DISEMBLE_RGBA
  20. PIXEL_FROM_RGBA
  21. ASSEMBLE_RGBA
  22. ALPHA_BLEND
  23. DUFFS_LOOP8
  24. DUFFS_LOOP4
  25. DUFFS_LOOP
  26. DUFFS_LOOP
  27. DUFFS_LOOP8
  28. DUFFS_LOOP4

   1 /*
   2     SDL - Simple DirectMedia Layer
   3     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
   4 
   5     This library is free software; you can redistribute it and/or
   6     modify it under the terms of the GNU Library General Public
   7     License as published by the Free Software Foundation; either
   8     version 2 of the License, or (at your option) any later version.
   9 
  10     This library is distributed in the hope that it will be useful,
  11     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13     Library General Public License for more details.
  14 
  15     You should have received a copy of the GNU Library General Public
  16     License along with this library; if not, write to the Free
  17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 
  19     Sam Lantinga
  20     slouken@devolution.com
  21 */
  22 
  23 #ifdef SAVE_RCSID
  24 static char rcsid =
  25  "@(#) $Id: SDL_blit.h,v 1.3.2.15 2001/02/13 10:05:50 hercules Exp $";
  26 #endif
  27 
  28 #ifndef _SDL_blit_h
  29 #define _SDL_blit_h
  30 
  31 #include "SDL_endian.h"
  32 
  33 /* The structure passed to the low level blit functions */
  34 typedef struct {
  35         Uint8 *s_pixels;
  36         int s_width;
  37         int s_height;
  38         int s_skip;
  39         Uint8 *d_pixels;
  40         int d_width;
  41         int d_height;
  42         int d_skip;
  43         void *aux_data;
  44         SDL_PixelFormat *src;
  45         Uint8 *table;
  46         SDL_PixelFormat *dst;
  47 } SDL_BlitInfo;
  48 
  49 /* The type definition for the low level blit functions */
  50 typedef void (*SDL_loblit)(SDL_BlitInfo *info);
  51 
  52 /* This is the private info structure for software accelerated blits */
  53 struct private_swaccel {
  54         SDL_loblit blit;
  55         void *aux_data;
  56 };
  57 
  58 /* Blit mapping definition */
  59 typedef struct SDL_BlitMap {
  60         SDL_Surface *dst;
  61         int identity;
  62         Uint8 *table;
  63         SDL_blit hw_blit;
  64         SDL_blit sw_blit;
  65         struct private_hwaccel *hw_data;
  66         struct private_swaccel *sw_data;
  67 
  68         /* the version count matches the destination; mismatch indicates
  69            an invalid mapping */
  70         unsigned int format_version;
  71 } SDL_BlitMap;
  72 
  73 
  74 /* Definitions for special global blit functions */
  75 #include "SDL_blit_A.h"
  76 
  77 /* Functions found in SDL_blit.c */
  78 extern int SDL_CalculateBlit(SDL_Surface *surface);
  79 
  80 /* Functions found in SDL_blit_{0,1,N,A}.c */
  81 extern SDL_loblit SDL_CalculateBlit0(SDL_Surface *surface, int complex);
  82 extern SDL_loblit SDL_CalculateBlit1(SDL_Surface *surface, int complex);
  83 extern SDL_loblit SDL_CalculateBlitN(SDL_Surface *surface, int complex);
  84 extern SDL_loblit SDL_CalculateAlphaBlit(SDL_Surface *surface, int complex);
  85 
  86 /*
  87  * Useful macros for blitting routines
  88  */
  89 
  90 #define FORMAT_EQUAL(A, B)                                              \
     /* [<][>][^][v][top][bottom][index][help] */
  91     ((A)->BitsPerPixel == (B)->BitsPerPixel                             \
  92      && ((A)->Rmask == (B)->Rmask) && ((A)->Amask == (B)->Amask))
  93 
  94 /* Load pixel of the specified format from a buffer and get its R-G-B values */
  95 /* FIXME: rescale values to 0..255 here? */
  96 #define RGB_FROM_PIXEL(pixel, fmt, r, g, b)                             \
     /* [<][>][^][v][top][bottom][index][help] */
  97 {                                                                       \
  98         r = (((pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss);            \
  99         g = (((pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss);            \
 100         b = (((pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss);            \
 101 }
 102 #define RGB_FROM_RGB565(pixel, r, g, b)                                 \
     /* [<][>][^][v][top][bottom][index][help] */
 103 {                                                                       \
 104         r = (((pixel&0xF800)>>11)<<3);                                  \
 105         g = (((pixel&0x07E0)>>5)<<2);                                   \
 106         b = ((pixel&0x001F)<<3);                                        \
 107 }
 108 #define RGB_FROM_RGB555(pixel, r, g, b)                                 \
     /* [<][>][^][v][top][bottom][index][help] */
 109 {                                                                       \
 110         r = (((pixel&0x7C00)>>10)<<3);                                  \
 111         g = (((pixel&0x03E0)>>5)<<3);                                   \
 112         b = ((pixel&0x001F)<<3);                                        \
 113 }
 114 #define RGB_FROM_RGB888(pixel, r, g, b)                                 \
     /* [<][>][^][v][top][bottom][index][help] */
 115 {                                                                       \
 116         r = ((pixel&0xFF0000)>>16);                                     \
 117         g = ((pixel&0xFF00)>>8);                                        \
 118         b = (pixel&0xFF);                                               \
 119 }
 120 #define RETRIEVE_RGB_PIXEL(buf, bpp, pixel)                                \
     /* [<][>][^][v][top][bottom][index][help] */
 121 do {                                                                       \
 122         switch (bpp) {                                                     \
 123                 case 2:                                                    \
 124                         pixel = *((Uint16 *)(buf));                        \
 125                 break;                                                     \
 126                                                                            \
 127                 case 3: {                                                  \
 128                         Uint8 *B = (Uint8 *)(buf);                         \
 129                         if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {              \
 130                                 pixel = B[0] + (B[1] << 8) + (B[2] << 16); \
 131                         } else {                                           \
 132                                 pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \
 133                         }                                                  \
 134                 }                                                          \
 135                 break;                                                     \
 136                                                                            \
 137                 case 4:                                                    \
 138                         pixel = *((Uint32 *)(buf));                        \
 139                 break;                                                     \
 140                                                                            \
 141                 default:                                                   \
 142                         pixel = 0; /* appease gcc */                       \
 143                 break;                                                     \
 144         }                                                                  \
 145 } while(0)
 146 
 147 #define DISEMBLE_RGB(buf, bpp, fmt, pixel, r, g, b)                        \
     /* [<][>][^][v][top][bottom][index][help] */
 148 do {                                                                       \
 149         switch (bpp) {                                                     \
 150                 case 2:                                                    \
 151                         pixel = *((Uint16 *)(buf));                        \
 152                 break;                                                     \
 153                                                                            \
 154                 case 3: {                                                  \
 155                         Uint8 *B = (Uint8 *)buf;                           \
 156                         if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {              \
 157                                 pixel = B[0] + (B[1] << 8) + (B[2] << 16); \
 158                         } else {                                           \
 159                                 pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \
 160                         }                                                  \
 161                 }                                                          \
 162                 break;                                                     \
 163                                                                            \
 164                 case 4:                                                    \
 165                         pixel = *((Uint32 *)(buf));                        \
 166                 break;                                                     \
 167                                                                            \
 168                 default:                                                   \
 169                         pixel = 0;      /* prevent gcc from complaining */ \
 170                 break;                                                     \
 171         }                                                                  \
 172         RGB_FROM_PIXEL(pixel, fmt, r, g, b);                               \
 173 } while(0)
 174 
 175 /* Assemble R-G-B values into a specified pixel format and store them */
 176 #define PIXEL_FROM_RGB(pixel, fmt, r, g, b)                             \
     /* [<][>][^][v][top][bottom][index][help] */
 177 {                                                                       \
 178         pixel = ((r>>fmt->Rloss)<<fmt->Rshift)|                         \
 179                 ((g>>fmt->Gloss)<<fmt->Gshift)|                         \
 180                 ((b>>fmt->Bloss)<<fmt->Bshift);                         \
 181 }
 182 #define RGB565_FROM_RGB(pixel, r, g, b)                                 \
     /* [<][>][^][v][top][bottom][index][help] */
 183 {                                                                       \
 184         pixel = ((r>>3)<<11)|((g>>2)<<5)|(b>>3);                        \
 185 }
 186 #define RGB555_FROM_RGB(pixel, r, g, b)                                 \
     /* [<][>][^][v][top][bottom][index][help] */
 187 {                                                                       \
 188         pixel = ((r>>3)<<10)|((g>>3)<<5)|(b>>3);                        \
 189 }
 190 #define RGB888_FROM_RGB(pixel, r, g, b)                                 \
     /* [<][>][^][v][top][bottom][index][help] */
 191 {                                                                       \
 192         pixel = (r<<16)|(g<<8)|b;                                       \
 193 }
 194 #define ASSEMBLE_RGB(buf, bpp, fmt, r, g, b)                            \
     /* [<][>][^][v][top][bottom][index][help] */
 195 {                                                                       \
 196         switch (bpp) {                                                  \
 197                 case 2: {                                               \
 198                         Uint16 pixel;                                   \
 199                                                                         \
 200                         PIXEL_FROM_RGB(pixel, fmt, r, g, b);            \
 201                         *((Uint16 *)(buf)) = pixel;                     \
 202                 }                                                       \
 203                 break;                                                  \
 204                                                                         \
 205                 case 3: {                                               \
 206                         if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {           \
 207                                 *((buf)+fmt->Rshift/8) = r;             \
 208                                 *((buf)+fmt->Gshift/8) = g;             \
 209                                 *((buf)+fmt->Bshift/8) = b;             \
 210                         } else {                                        \
 211                                 *((buf)+2-fmt->Rshift/8) = r;           \
 212                                 *((buf)+2-fmt->Gshift/8) = g;           \
 213                                 *((buf)+2-fmt->Bshift/8) = b;           \
 214                         }                                               \
 215                 }                                                       \
 216                 break;                                                  \
 217                                                                         \
 218                 case 4: {                                               \
 219                         Uint32 pixel;                                   \
 220                                                                         \
 221                         PIXEL_FROM_RGB(pixel, fmt, r, g, b);            \
 222                         *((Uint32 *)(buf)) = pixel;                     \
 223                 }                                                       \
 224                 break;                                                  \
 225         }                                                               \
 226 }
 227 #define ASSEMBLE_RGB_AMASK(buf, bpp, fmt, r, g, b, Amask)               \
     /* [<][>][^][v][top][bottom][index][help] */
 228 {                                                                       \
 229         switch (bpp) {                                                  \
 230                 case 2: {                                               \
 231                         Uint16 *bufp;                                   \
 232                         Uint16 pixel;                                   \
 233                                                                         \
 234                         bufp = (Uint16 *)buf;                           \
 235                         PIXEL_FROM_RGB(pixel, fmt, r, g, b);            \
 236                         *bufp = pixel | (*bufp & Amask);                \
 237                 }                                                       \
 238                 break;                                                  \
 239                                                                         \
 240                 case 3: {                                               \
 241                         if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {           \
 242                                 *((buf)+fmt->Rshift/8) = r;             \
 243                                 *((buf)+fmt->Gshift/8) = g;             \
 244                                 *((buf)+fmt->Bshift/8) = b;             \
 245                         } else {                                        \
 246                                 *((buf)+2-fmt->Rshift/8) = r;           \
 247                                 *((buf)+2-fmt->Gshift/8) = g;           \
 248                                 *((buf)+2-fmt->Bshift/8) = b;           \
 249                         }                                               \
 250                 }                                                       \
 251                 break;                                                  \
 252                                                                         \
 253                 case 4: {                                               \
 254                         Uint32 *bufp;                                   \
 255                         Uint32 pixel;                                   \
 256                                                                         \
 257                         bufp = (Uint32 *)buf;                           \
 258                         PIXEL_FROM_RGB(pixel, fmt, r, g, b);            \
 259                         *bufp = pixel | (*bufp & Amask);                \
 260                 }                                                       \
 261                 break;                                                  \
 262         }                                                               \
 263 }
 264 
 265 /* FIXME: Should we rescale alpha into 0..255 here? */
 266 #define RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a)                         \
     /* [<][>][^][v][top][bottom][index][help] */
 267 {                                                                       \
 268         r = ((pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss;              \
 269         g = ((pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss;              \
 270         b = ((pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss;              \
 271         a = ((pixel&fmt->Amask)>>fmt->Ashift)<<fmt->Aloss;              \
 272 }
 273 #define RGBA_FROM_8888(pixel, fmt, r, g, b, a)  \
     /* [<][>][^][v][top][bottom][index][help] */
 274 {                                               \
 275         r = (pixel&fmt->Rmask)>>fmt->Rshift;    \
 276         g = (pixel&fmt->Gmask)>>fmt->Gshift;    \
 277         b = (pixel&fmt->Bmask)>>fmt->Bshift;    \
 278         a = (pixel&fmt->Amask)>>fmt->Ashift;    \
 279 }
 280 #define RGBA_FROM_RGBA8888(pixel, r, g, b, a)                           \
     /* [<][>][^][v][top][bottom][index][help] */
 281 {                                                                       \
 282         r = (pixel>>24);                                                \
 283         g = ((pixel>>16)&0xFF);                                         \
 284         b = ((pixel>>8)&0xFF);                                          \
 285         a = (pixel&0xFF);                                               \
 286 }
 287 #define RGBA_FROM_ARGB8888(pixel, r, g, b, a)                           \
     /* [<][>][^][v][top][bottom][index][help] */
 288 {                                                                       \
 289         r = ((pixel>>16)&0xFF);                                         \
 290         g = ((pixel>>8)&0xFF);                                          \
 291         b = (pixel&0xFF);                                               \
 292         a = (pixel>>24);                                                \
 293 }
 294 #define RGBA_FROM_ABGR8888(pixel, r, g, b, a)                           \
     /* [<][>][^][v][top][bottom][index][help] */
 295 {                                                                       \
 296         r = (pixel&0xFF);                                               \
 297         g = ((pixel>>8)&0xFF);                                          \
 298         b = ((pixel>>16)&0xFF);                                         \
 299         a = (pixel>>24);                                                \
 300 }
 301 #define DISEMBLE_RGBA(buf, bpp, fmt, pixel, r, g, b, a)                    \
     /* [<][>][^][v][top][bottom][index][help] */
 302 do {                                                                       \
 303         switch (bpp) {                                                     \
 304                 case 2:                                                    \
 305                         pixel = *((Uint16 *)(buf));                        \
 306                 break;                                                     \
 307                                                                            \
 308                 case 3: {/* FIXME: broken code (no alpha) */               \
 309                         Uint8 *b = (Uint8 *)buf;                           \
 310                         if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {              \
 311                                 pixel = b[0] + (b[1] << 8) + (b[2] << 16); \
 312                         } else {                                           \
 313                                 pixel = (b[0] << 16) + (b[1] << 8) + b[2]; \
 314                         }                                                  \
 315                 }                                                          \
 316                 break;                                                     \
 317                                                                            \
 318                 case 4:                                                    \
 319                         pixel = *((Uint32 *)(buf));                        \
 320                 break;                                                     \
 321                                                                            \
 322                 default:                                                   \
 323                         pixel = 0; /* stop gcc complaints */               \
 324                 break;                                                     \
 325         }                                                                  \
 326         RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a);                           \
 327         pixel &= ~fmt->Amask;                                              \
 328 } while(0)
 329 
 330 /* FIXME: this isn't correct, especially for Alpha (maximum != 255) */
 331 #define PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a)                         \
     /* [<][>][^][v][top][bottom][index][help] */
 332 {                                                                       \
 333         pixel = ((r>>fmt->Rloss)<<fmt->Rshift)|                         \
 334                 ((g>>fmt->Gloss)<<fmt->Gshift)|                         \
 335                 ((b>>fmt->Bloss)<<fmt->Bshift)|                         \
 336                 ((a<<fmt->Aloss)<<fmt->Ashift);                         \
 337 }
 338 #define ASSEMBLE_RGBA(buf, bpp, fmt, r, g, b, a)                        \
     /* [<][>][^][v][top][bottom][index][help] */
 339 {                                                                       \
 340         switch (bpp) {                                                  \
 341                 case 2: {                                               \
 342                         Uint16 pixel;                                   \
 343                                                                         \
 344                         PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a);        \
 345                         *((Uint16 *)(buf)) = pixel;                     \
 346                 }                                                       \
 347                 break;                                                  \
 348                                                                         \
 349                 case 3: { /* FIXME: broken code (no alpha) */           \
 350                         if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {           \
 351                                 *((buf)+fmt->Rshift/8) = r;             \
 352                                 *((buf)+fmt->Gshift/8) = g;             \
 353                                 *((buf)+fmt->Bshift/8) = b;             \
 354                         } else {                                        \
 355                                 *((buf)+2-fmt->Rshift/8) = r;           \
 356                                 *((buf)+2-fmt->Gshift/8) = g;           \
 357                                 *((buf)+2-fmt->Bshift/8) = b;           \
 358                         }                                               \
 359                 }                                                       \
 360                 break;                                                  \
 361                                                                         \
 362                 case 4: {                                               \
 363                         Uint32 pixel;                                   \
 364                                                                         \
 365                         PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a);        \
 366                         *((Uint32 *)(buf)) = pixel;                     \
 367                 }                                                       \
 368                 break;                                                  \
 369         }                                                               \
 370 }
 371 
 372 /* Blend the RGB values of two pixels based on a source alpha value */
 373 #define ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB)  \
     /* [<][>][^][v][top][bottom][index][help] */
 374 do {                                            \
 375         dR = (((sR-dR)*(A))>>8)+dR;             \
 376         dG = (((sG-dG)*(A))>>8)+dG;             \
 377         dB = (((sB-dB)*(A))>>8)+dB;             \
 378 } while(0)
 379 
 380 /* This is a very useful loop for optimizing blitters */
 381 #define USE_DUFFS_LOOP
 382 #ifdef USE_DUFFS_LOOP
 383 
 384 /* 8-times unrolled loop */
 385 #define DUFFS_LOOP8(pixel_copy_increment, width)                        \
     /* [<][>][^][v][top][bottom][index][help] */
 386 { int n = (width+7)/8;                                                  \
 387         switch (width % 8) {                                            \
 388         case 0: do {    pixel_copy_increment;                           \
 389         case 7:         pixel_copy_increment;                           \
 390         case 6:         pixel_copy_increment;                           \
 391         case 5:         pixel_copy_increment;                           \
 392         case 4:         pixel_copy_increment;                           \
 393         case 3:         pixel_copy_increment;                           \
 394         case 2:         pixel_copy_increment;                           \
 395         case 1:         pixel_copy_increment;                           \
 396                 } while ( --n > 0 );                                    \
 397         }                                                               \
 398 }
 399 
 400 /* 4-times unrolled loop */
 401 #define DUFFS_LOOP4(pixel_copy_increment, width)                        \
     /* [<][>][^][v][top][bottom][index][help] */
 402 { int n = (width+3)/4;                                                  \
 403         switch (width % 4) {                                            \
 404         case 0: do {    pixel_copy_increment;                           \
 405         case 3:         pixel_copy_increment;                           \
 406         case 2:         pixel_copy_increment;                           \
 407         case 1:         pixel_copy_increment;                           \
 408                 } while ( --n > 0 );                                    \
 409         }                                                               \
 410 }
 411 
 412 /* Use the 8-times version of the loop by default */
 413 #define DUFFS_LOOP(pixel_copy_increment, width)                         \
     /* [<][>][^][v][top][bottom][index][help] */
 414         DUFFS_LOOP8(pixel_copy_increment, width)
 415 
 416 #else
 417 
 418 /* Don't use Duff's device to unroll loops */
 419 #define DUFFS_LOOP(pixel_copy_increment, width)                         \
     /* [<][>][^][v][top][bottom][index][help] */
 420 { int n;                                                                \
 421         for ( n=width; n > 0; --n ) {                                   \
 422                 pixel_copy_increment;                                   \
 423         }                                                               \
 424 }
 425 #define DUFFS_LOOP8(pixel_copy_increment, width)                        \
     /* [<][>][^][v][top][bottom][index][help] */
 426         DUFFS_LOOP(pixel_copy_increment, width)
 427 #define DUFFS_LOOP4(pixel_copy_increment, width)                        \
     /* [<][>][^][v][top][bottom][index][help] */
 428         DUFFS_LOOP(pixel_copy_increment, width)
 429 
 430 #endif /* USE_DUFFS_LOOP */
 431 
 432 /* Prevent Visual C++ 6.0 from printing out stupid warnings */
 433 #if defined(_MSC_VER) && (_MSC_VER >= 600)
 434 #pragma warning(disable: 4550)
 435 #endif
 436 
 437 #endif /* _SDL_blit_h */

/* [<][>][^][v][top][bottom][index][help] */