Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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 2001/07/07 20:20:16 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)                                              \
  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)                             \
  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)                                 \
  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)                                 \
  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)                                 \
  115. {                                                                       \
  116.         r = ((pixel&0xFF0000)>>16);                                     \
  117.         g = ((pixel&0xFF00)>>8);                                        \
  118.         b = (pixel&0xFF);                                               \
  119. }
  120. #define RETRIEVE_RGB_PIXEL(buf, bpp, pixel)                                \
  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)                        \
  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)                             \
  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)                                 \
  183. {                                                                       \
  184.         pixel = ((r>>3)<<11)|((g>>2)<<5)|(b>>3);                        \
  185. }
  186. #define RGB555_FROM_RGB(pixel, r, g, b)                                 \
  187. {                                                                       \
  188.         pixel = ((r>>3)<<10)|((g>>3)<<5)|(b>>3);                        \
  189. }
  190. #define RGB888_FROM_RGB(pixel, r, g, b)                                 \
  191. {                                                                       \
  192.         pixel = (r<<16)|(g<<8)|b;                                       \
  193. }
  194. #define ASSEMBLE_RGB(buf, bpp, fmt, r, g, b)                            \
  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)               \
  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)                         \
  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)  \
  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)                           \
  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)                           \
  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)                           \
  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)                    \
  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)                         \
  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)                        \
  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)  \
  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)                        \
  386. { int n = (width+7)/8;                                                  \
  387.         switch (width & 7) {                                            \
  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)                        \
  402. { int n = (width+3)/4;                                                  \
  403.         switch (width & 3) {                                            \
  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)                         \
  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)                         \
  420. { int n;                                                                \
  421.         for ( n=width; n > 0; --n ) {                                   \
  422.                 pixel_copy_increment;                                   \
  423.         }                                                               \
  424. }
  425. #define DUFFS_LOOP8(pixel_copy_increment, width)                        \
  426.         DUFFS_LOOP(pixel_copy_increment, width)
  427. #define DUFFS_LOOP4(pixel_copy_increment, width)                        \
  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 */
  438.