Subversion Repositories Kolibri OS

Rev

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.  
  24. #include <stdio.h>
  25.  
  26. #include "SDL_types.h"
  27. #include "SDL_video.h"
  28. #include "SDL_blit.h"
  29.  
  30. /* Functions to perform alpha blended blitting */
  31.  
  32. /* N->1 blending with per-surface alpha */
  33. static void BlitNto1SurfaceAlpha(SDL_BlitInfo *info)
  34. {
  35.         int width = info->d_width;
  36.         int height = info->d_height;
  37.         Uint8 *src = info->s_pixels;
  38.         int srcskip = info->s_skip;
  39.         Uint8 *dst = info->d_pixels;
  40.         int dstskip = info->d_skip;
  41.         Uint8 *palmap = info->table;
  42.         SDL_PixelFormat *srcfmt = info->src;
  43.         SDL_PixelFormat *dstfmt = info->dst;
  44.         int srcbpp = srcfmt->BytesPerPixel;
  45.  
  46.         const unsigned A = srcfmt->alpha;
  47.  
  48.         while ( height-- ) {
  49.             DUFFS_LOOP4(
  50.             {
  51.                 Uint32 pixel;
  52.                 unsigned sR;
  53.                 unsigned sG;
  54.                 unsigned sB;
  55.                 unsigned dR;
  56.                 unsigned dG;
  57.                 unsigned dB;
  58.                 DISEMBLE_RGB(src, srcbpp, srcfmt, pixel, sR, sG, sB);
  59.                 dR = dstfmt->palette->colors[*dst].r;
  60.                 dG = dstfmt->palette->colors[*dst].g;
  61.                 dB = dstfmt->palette->colors[*dst].b;
  62.                 ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
  63.                 dR &= 0xff;
  64.                 dG &= 0xff;
  65.                 dB &= 0xff;
  66.                 /* Pack RGB into 8bit pixel */
  67.                 if ( palmap == NULL ) {
  68.                     *dst =((dR>>5)<<(3+2))|
  69.                           ((dG>>5)<<(2))|
  70.                           ((dB>>6)<<(0));
  71.                 } else {
  72.                     *dst = palmap[((dR>>5)<<(3+2))|
  73.                                   ((dG>>5)<<(2))  |
  74.                                   ((dB>>6)<<(0))];
  75.                 }
  76.                 dst++;
  77.                 src += srcbpp;
  78.             },
  79.             width);
  80.             src += srcskip;
  81.             dst += dstskip;
  82.         }
  83. }
  84.  
  85. /* N->1 blending with pixel alpha */
  86. static void BlitNto1PixelAlpha(SDL_BlitInfo *info)
  87. {
  88.         int width = info->d_width;
  89.         int height = info->d_height;
  90.         Uint8 *src = info->s_pixels;
  91.         int srcskip = info->s_skip;
  92.         Uint8 *dst = info->d_pixels;
  93.         int dstskip = info->d_skip;
  94.         Uint8 *palmap = info->table;
  95.         SDL_PixelFormat *srcfmt = info->src;
  96.         SDL_PixelFormat *dstfmt = info->dst;
  97.         int srcbpp = srcfmt->BytesPerPixel;
  98.  
  99.         /* FIXME: fix alpha bit field expansion here too? */
  100.         while ( height-- ) {
  101.             DUFFS_LOOP4(
  102.             {
  103.                 Uint32 pixel;
  104.                 unsigned sR;
  105.                 unsigned sG;
  106.                 unsigned sB;
  107.                 unsigned sA;
  108.                 unsigned dR;
  109.                 unsigned dG;
  110.                 unsigned dB;
  111.                 DISEMBLE_RGBA(src,srcbpp,srcfmt,pixel,sR,sG,sB,sA);
  112.                 dR = dstfmt->palette->colors[*dst].r;
  113.                 dG = dstfmt->palette->colors[*dst].g;
  114.                 dB = dstfmt->palette->colors[*dst].b;
  115.                 ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB);
  116.                 dR &= 0xff;
  117.                 dG &= 0xff;
  118.                 dB &= 0xff;
  119.                 /* Pack RGB into 8bit pixel */
  120.                 if ( palmap == NULL ) {
  121.                     *dst =((dR>>5)<<(3+2))|
  122.                           ((dG>>5)<<(2))|
  123.                           ((dB>>6)<<(0));
  124.                 } else {
  125.                     *dst = palmap[((dR>>5)<<(3+2))|
  126.                                   ((dG>>5)<<(2))  |
  127.                                   ((dB>>6)<<(0))  ];
  128.                 }
  129.                 dst++;
  130.                 src += srcbpp;
  131.             },
  132.             width);
  133.             src += srcskip;
  134.             dst += dstskip;
  135.         }
  136. }
  137.  
  138. /* colorkeyed N->1 blending with per-surface alpha */
  139. static void BlitNto1SurfaceAlphaKey(SDL_BlitInfo *info)
  140. {
  141.         int width = info->d_width;
  142.         int height = info->d_height;
  143.         Uint8 *src = info->s_pixels;
  144.         int srcskip = info->s_skip;
  145.         Uint8 *dst = info->d_pixels;
  146.         int dstskip = info->d_skip;
  147.         Uint8 *palmap = info->table;
  148.         SDL_PixelFormat *srcfmt = info->src;
  149.         SDL_PixelFormat *dstfmt = info->dst;
  150.         int srcbpp = srcfmt->BytesPerPixel;
  151.         Uint32 ckey = srcfmt->colorkey;
  152.  
  153.         const int A = srcfmt->alpha;
  154.  
  155.         while ( height-- ) {
  156.             DUFFS_LOOP(
  157.             {
  158.                 Uint32 pixel;
  159.                 unsigned sR;
  160.                 unsigned sG;
  161.                 unsigned sB;
  162.                 unsigned dR;
  163.                 unsigned dG;
  164.                 unsigned dB;
  165.                 DISEMBLE_RGB(src, srcbpp, srcfmt, pixel, sR, sG, sB);
  166.                 if ( pixel != ckey ) {
  167.                     dR = dstfmt->palette->colors[*dst].r;
  168.                     dG = dstfmt->palette->colors[*dst].g;
  169.                     dB = dstfmt->palette->colors[*dst].b;
  170.                     ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
  171.                     dR &= 0xff;
  172.                     dG &= 0xff;
  173.                     dB &= 0xff;
  174.                     /* Pack RGB into 8bit pixel */
  175.                     if ( palmap == NULL ) {
  176.                         *dst =((dR>>5)<<(3+2))|
  177.                               ((dG>>5)<<(2)) |
  178.                               ((dB>>6)<<(0));
  179.                     } else {
  180.                         *dst = palmap[((dR>>5)<<(3+2))|
  181.                                       ((dG>>5)<<(2))  |
  182.                                       ((dB>>6)<<(0))  ];
  183.                     }
  184.                 }
  185.                 dst++;
  186.                 src += srcbpp;
  187.             },
  188.             width);
  189.             src += srcskip;
  190.             dst += dstskip;
  191.         }
  192. }
  193.  
  194. /* fast RGB888->(A)RGB888 blending with surface alpha=128 special case */
  195. static void BlitRGBtoRGBSurfaceAlpha128(SDL_BlitInfo *info)
  196. {
  197.         int width = info->d_width;
  198.         int height = info->d_height;
  199.         Uint32 *srcp = (Uint32 *)info->s_pixels;
  200.         int srcskip = info->s_skip >> 2;
  201.         Uint32 *dstp = (Uint32 *)info->d_pixels;
  202.         int dstskip = info->d_skip >> 2;
  203.  
  204.         while(height--) {
  205.             DUFFS_LOOP4({
  206.                     Uint32 s = *srcp++;
  207.                     Uint32 d = *dstp;
  208.                     *dstp++ = ((((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1)
  209.                                + (s & d & 0x00010101)) | 0xff000000;
  210.             }, width);
  211.             srcp += srcskip;
  212.             dstp += dstskip;
  213.         }
  214. }
  215.  
  216. /* fast RGB888->(A)RGB888 blending with surface alpha */
  217. static void BlitRGBtoRGBSurfaceAlpha(SDL_BlitInfo *info)
  218. {
  219.         unsigned alpha = info->src->alpha;
  220.         if(alpha == 128) {
  221.                 BlitRGBtoRGBSurfaceAlpha128(info);
  222.         } else {
  223.                 int width = info->d_width;
  224.                 int height = info->d_height;
  225.                 Uint32 *srcp = (Uint32 *)info->s_pixels;
  226.                 int srcskip = info->s_skip >> 2;
  227.                 Uint32 *dstp = (Uint32 *)info->d_pixels;
  228.                 int dstskip = info->d_skip >> 2;
  229.  
  230.                 while(height--) {
  231.                         DUFFS_LOOP4({
  232.                                 Uint32 s;
  233.                                 Uint32 d;
  234.                                 Uint32 s1;
  235.                                 Uint32 d1;
  236.                                 s = *srcp;
  237.                                 d = *dstp;
  238.                                 s1 = s & 0xff00ff;
  239.                                 d1 = d & 0xff00ff;
  240.                                 d1 = (d1 + ((s1 - d1) * alpha >> 8))
  241.                                      & 0xff00ff;
  242.                                 s &= 0xff00;
  243.                                 d &= 0xff00;
  244.                                 d = (d + ((s - d) * alpha >> 8)) & 0xff00;
  245.                                 *dstp = d1 | d | 0xff000000;
  246.                                 ++srcp;
  247.                                 ++dstp;
  248.                         }, width);
  249.                         srcp += srcskip;
  250.                         dstp += dstskip;
  251.                 }
  252.         }
  253. }
  254.  
  255. /* fast ARGB888->(A)RGB888 blending with pixel alpha */
  256. static void BlitRGBtoRGBPixelAlpha(SDL_BlitInfo *info)
  257. {
  258.         int width = info->d_width;
  259.         int height = info->d_height;
  260.         Uint32 *srcp = (Uint32 *)info->s_pixels;
  261.         int srcskip = info->s_skip >> 2;
  262.         Uint32 *dstp = (Uint32 *)info->d_pixels;
  263.         int dstskip = info->d_skip >> 2;
  264.  
  265.         while(height--) {
  266.             DUFFS_LOOP4({
  267.                 Uint32 dalpha;
  268.                 Uint32 d;
  269.                 Uint32 s1;
  270.                 Uint32 d1;
  271.                 Uint32 s = *srcp;
  272.                 Uint32 alpha = s >> 24;
  273.                 /* FIXME: Here we special-case opaque alpha since the
  274.                    compositioning used (>>8 instead of /255) doesn't handle
  275.                    it correctly. Also special-case alpha=0 for speed?
  276.                    Benchmark this! */
  277.                 if(alpha == SDL_ALPHA_OPAQUE) {
  278.                     *dstp = (s & 0x00ffffff) | (*dstp & 0xff000000);
  279.                 } else {
  280.                     /*
  281.                      * take out the middle component (green), and process
  282.                      * the other two in parallel. One multiply less.
  283.                      */
  284.                     d = *dstp;
  285.                     dalpha = d & 0xff000000;
  286.                     s1 = s & 0xff00ff;
  287.                     d1 = d & 0xff00ff;
  288.                     d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff;
  289.                     s &= 0xff00;
  290.                     d &= 0xff00;
  291.                     d = (d + ((s - d) * alpha >> 8)) & 0xff00;
  292.                     *dstp = d1 | d | dalpha;
  293.                 }
  294.                 ++srcp;
  295.                 ++dstp;
  296.             }, width);
  297.             srcp += srcskip;
  298.             dstp += dstskip;
  299.         }
  300. }
  301.  
  302. /* 16bpp special case for per-surface alpha=50%: blend 2 pixels in parallel */
  303.  
  304. /* blend a single 16 bit pixel at 50% */
  305. #define BLEND16_50(d, s, mask)                                          \
  306.         ((((s & mask) + (d & mask)) >> 1) + (s & d & (~mask & 0xffff)))
  307.  
  308. /* blend two 16 bit pixels at 50% */
  309. #define BLEND2x16_50(d, s, mask)                                             \
  310.         (((s & (mask | mask << 16)) >> 1) + ((d & (mask | mask << 16)) >> 1) \
  311.          + (s & d & (~(mask | mask << 16))))
  312.  
  313. static void Blit16to16SurfaceAlpha128(SDL_BlitInfo *info, Uint16 mask)
  314. {
  315.         int width = info->d_width;
  316.         int height = info->d_height;
  317.         Uint16 *srcp = (Uint16 *)info->s_pixels;
  318.         int srcskip = info->s_skip >> 1;
  319.         Uint16 *dstp = (Uint16 *)info->d_pixels;
  320.         int dstskip = info->d_skip >> 1;
  321.  
  322.         while(height--) {
  323.                 if(((unsigned long)srcp ^ (unsigned long)dstp) & 2) {
  324.                         /*
  325.                          * Source and destination not aligned, pipeline it.
  326.                          * This is mostly a win for big blits but no loss for
  327.                          * small ones
  328.                          */
  329.                         Uint32 prev_sw;
  330.                         int w = width;
  331.  
  332.                         /* handle odd destination */
  333.                         if((unsigned long)dstp & 2) {
  334.                                 Uint16 d = *dstp, s = *srcp;
  335.                                 *dstp = BLEND16_50(d, s, mask);
  336.                                 dstp++;
  337.                                 srcp++;
  338.                                 w--;
  339.                         }
  340.                         srcp++; /* srcp is now 32-bit aligned */
  341.  
  342.                         /* bootstrap pipeline with first halfword */
  343.                         prev_sw = ((Uint32 *)srcp)[-1];
  344.  
  345.                         while(w > 1) {
  346.                                 Uint32 sw, dw, s;
  347.                                 sw = *(Uint32 *)srcp;
  348.                                 dw = *(Uint32 *)dstp;
  349.                                 if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
  350.                                         s = (prev_sw << 16) + (sw >> 16);
  351.                                 else
  352.                                         s = (prev_sw >> 16) + (sw << 16);
  353.                                 prev_sw = sw;
  354.                                 *(Uint32 *)dstp = BLEND2x16_50(dw, s, mask);
  355.                                 dstp += 2;
  356.                                 srcp += 2;
  357.                                 w -= 2;
  358.                         }
  359.  
  360.                         /* final pixel if any */
  361.                         if(w) {
  362.                                 Uint16 d = *dstp, s;
  363.                                 if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
  364.                                         s = prev_sw;
  365.                                 else
  366.                                         s = prev_sw >> 16;
  367.                                 *dstp = BLEND16_50(d, s, mask);
  368.                                 srcp++;
  369.                                 dstp++;
  370.                         }
  371.                         srcp += srcskip - 1;
  372.                         dstp += dstskip;
  373.                 } else {
  374.                         /* source and destination are aligned */
  375.                         int w = width;
  376.  
  377.                         /* first odd pixel? */
  378.                         if((unsigned long)srcp & 2) {
  379.                                 Uint16 d = *dstp, s = *srcp;
  380.                                 *dstp = BLEND16_50(d, s, mask);
  381.                                 srcp++;
  382.                                 dstp++;
  383.                                 w--;
  384.                         }
  385.                         /* srcp and dstp are now 32-bit aligned */
  386.  
  387.                         while(w > 1) {
  388.                                 Uint32 sw = *(Uint32 *)srcp;
  389.                                 Uint32 dw = *(Uint32 *)dstp;
  390.                                 *(Uint32 *)dstp = BLEND2x16_50(dw, sw, mask);
  391.                                 srcp += 2;
  392.                                 dstp += 2;
  393.                                 w -= 2;
  394.                         }
  395.  
  396.                         /* last odd pixel? */
  397.                         if(w) {
  398.                                 Uint16 d = *dstp, s = *srcp;
  399.                                 *dstp = BLEND16_50(d, s, mask);
  400.                                 srcp++;
  401.                                 dstp++;
  402.                         }
  403.                         srcp += srcskip;
  404.                         dstp += dstskip;
  405.                 }
  406.         }
  407. }
  408.  
  409. /* fast RGB565->RGB565 blending with surface alpha */
  410. static void Blit565to565SurfaceAlpha(SDL_BlitInfo *info)
  411. {
  412.         unsigned alpha = info->src->alpha;
  413.         if(alpha == 128) {
  414.                 Blit16to16SurfaceAlpha128(info, 0xf7de);
  415.         } else {
  416.                 int width = info->d_width;
  417.                 int height = info->d_height;
  418.                 Uint16 *srcp = (Uint16 *)info->s_pixels;
  419.                 int srcskip = info->s_skip >> 1;
  420.                 Uint16 *dstp = (Uint16 *)info->d_pixels;
  421.                 int dstskip = info->d_skip >> 1;
  422.                 alpha >>= 3;    /* downscale alpha to 5 bits */
  423.  
  424.                 while(height--) {
  425.                         DUFFS_LOOP4({
  426.                                 Uint32 s = *srcp++;
  427.                                 Uint32 d = *dstp;
  428.                                 /*
  429.                                  * shift out the middle component (green) to
  430.                                  * the high 16 bits, and process all three RGB
  431.                                  * components at the same time.
  432.                                  */
  433.                                 s = (s | s << 16) & 0x07e0f81f;
  434.                                 d = (d | d << 16) & 0x07e0f81f;
  435.                                 d += (s - d) * alpha >> 5;
  436.                                 d &= 0x07e0f81f;
  437.                                 *dstp++ = d | d >> 16;
  438.                         }, width);
  439.                         srcp += srcskip;
  440.                         dstp += dstskip;
  441.                 }
  442.         }
  443. }
  444.  
  445. /* fast RGB555->RGB555 blending with surface alpha */
  446. static void Blit555to555SurfaceAlpha(SDL_BlitInfo *info)
  447. {
  448.         unsigned alpha = info->src->alpha; /* downscale alpha to 5 bits */
  449.         if(alpha == 128) {
  450.                 Blit16to16SurfaceAlpha128(info, 0xfbde);
  451.         } else {
  452.                 int width = info->d_width;
  453.                 int height = info->d_height;
  454.                 Uint16 *srcp = (Uint16 *)info->s_pixels;
  455.                 int srcskip = info->s_skip >> 1;
  456.                 Uint16 *dstp = (Uint16 *)info->d_pixels;
  457.                 int dstskip = info->d_skip >> 1;
  458.                 alpha >>= 3;            /* downscale alpha to 5 bits */
  459.  
  460.                 while(height--) {
  461.                         DUFFS_LOOP4({
  462.                                 Uint32 s = *srcp++;
  463.                                 Uint32 d = *dstp;
  464.                                 /*
  465.                                  * shift out the middle component (green) to
  466.                                  * the high 16 bits, and process all three RGB
  467.                                  * components at the same time.
  468.                                  */
  469.                                 s = (s | s << 16) & 0x03e07c1f;
  470.                                 d = (d | d << 16) & 0x03e07c1f;
  471.                                 d += (s - d) * alpha >> 5;
  472.                                 d &= 0x03e07c1f;
  473.                                 *dstp++ = d | d >> 16;
  474.                         }, width);
  475.                         srcp += srcskip;
  476.                         dstp += dstskip;
  477.                 }
  478.         }
  479. }
  480.  
  481. /* fast ARGB8888->RGB565 blending with pixel alpha */
  482. static void BlitARGBto565PixelAlpha(SDL_BlitInfo *info)
  483. {
  484.         int width = info->d_width;
  485.         int height = info->d_height;
  486.         Uint32 *srcp = (Uint32 *)info->s_pixels;
  487.         int srcskip = info->s_skip >> 2;
  488.         Uint16 *dstp = (Uint16 *)info->d_pixels;
  489.         int dstskip = info->d_skip >> 1;
  490.  
  491.         while(height--) {
  492.             DUFFS_LOOP4({
  493.                 Uint32 s = *srcp;
  494.                 unsigned alpha = s >> 27; /* downscale alpha to 5 bits */
  495.                 /* FIXME: Here we special-case opaque alpha since the
  496.                    compositioning used (>>8 instead of /255) doesn't handle
  497.                    it correctly. Also special-case alpha=0 for speed?
  498.                    Benchmark this! */
  499.                 if(alpha == (SDL_ALPHA_OPAQUE >> 3)) {
  500.                     *dstp = (s >> 8 & 0xf800) + (s >> 5 & 0x7e0)
  501.                           + (s >> 3  & 0x1f);
  502.                 } else {
  503.                     Uint32 d = *dstp;
  504.                     /*
  505.                      * convert source and destination to G0RAB65565
  506.                      * and blend all components at the same time
  507.                      */
  508.                     s = ((s & 0xfc00) << 11) + (s >> 8 & 0xf800)
  509.                       + (s >> 3 & 0x1f);
  510.                     d = (d | d << 16) & 0x07e0f81f;
  511.                     d += (s - d) * alpha >> 5;
  512.                     d &= 0x07e0f81f;
  513.                     *dstp = d | d >> 16;
  514.                 }
  515.                 srcp++;
  516.                 dstp++;
  517.             }, width);
  518.             srcp += srcskip;
  519.             dstp += dstskip;
  520.         }
  521. }
  522.  
  523. /* fast ARGB8888->RGB555 blending with pixel alpha */
  524. static void BlitARGBto555PixelAlpha(SDL_BlitInfo *info)
  525. {
  526.         int width = info->d_width;
  527.         int height = info->d_height;
  528.         Uint32 *srcp = (Uint32 *)info->s_pixels;
  529.         int srcskip = info->s_skip >> 2;
  530.         Uint16 *dstp = (Uint16 *)info->d_pixels;
  531.         int dstskip = info->d_skip >> 1;
  532.  
  533.         while(height--) {
  534.             DUFFS_LOOP4({
  535.                 unsigned alpha;
  536.                 Uint32 s = *srcp;
  537.                 alpha = s >> 27; /* downscale alpha to 5 bits */
  538.                 /* FIXME: Here we special-case opaque alpha since the
  539.                    compositioning used (>>8 instead of /255) doesn't handle
  540.                    it correctly. Also special-case alpha=0 for speed?
  541.                    Benchmark this! */
  542.                 if(alpha == (SDL_ALPHA_OPAQUE >> 3)) {
  543.                     *dstp = (s >> 9 & 0x7c00) + (s >> 6 & 0x3e0)
  544.                           + (s >> 3  & 0x1f);
  545.                 } else {
  546.                     Uint32 d = *dstp;
  547.                     /*
  548.                      * convert source and destination to G0RAB65565
  549.                      * and blend all components at the same time
  550.                      */
  551.                     s = ((s & 0xf800) << 10) + (s >> 9 & 0x7c00)
  552.                       + (s >> 3 & 0x1f);
  553.                     d = (d | d << 16) & 0x03e07c1f;
  554.                     d += (s - d) * alpha >> 5;
  555.                     d &= 0x03e07c1f;
  556.                     *dstp = d | d >> 16;
  557.                 }
  558.                 srcp++;
  559.                 dstp++;
  560.             }, width);
  561.             srcp += srcskip;
  562.             dstp += dstskip;
  563.         }
  564. }
  565.  
  566. /* General (slow) N->N blending with per-surface alpha */
  567. static void BlitNtoNSurfaceAlpha(SDL_BlitInfo *info)
  568. {
  569.         int width = info->d_width;
  570.         int height = info->d_height;
  571.         Uint8 *src = info->s_pixels;
  572.         int srcskip = info->s_skip;
  573.         Uint8 *dst = info->d_pixels;
  574.         int dstskip = info->d_skip;
  575.         SDL_PixelFormat *srcfmt = info->src;
  576.         SDL_PixelFormat *dstfmt = info->dst;
  577.         int srcbpp = srcfmt->BytesPerPixel;
  578.         int dstbpp = dstfmt->BytesPerPixel;
  579.         unsigned sA = srcfmt->alpha;
  580.         unsigned dA = dstfmt->Amask ? SDL_ALPHA_OPAQUE : 0;
  581.  
  582.         while ( height-- ) {
  583.             DUFFS_LOOP4(
  584.             {
  585.                 Uint32 pixel;
  586.                 unsigned sR;
  587.                 unsigned sG;
  588.                 unsigned sB;
  589.                 unsigned dR;
  590.                 unsigned dG;
  591.                 unsigned dB;
  592.                 DISEMBLE_RGB(src, srcbpp, srcfmt, pixel, sR, sG, sB);
  593.                 DISEMBLE_RGB(dst, dstbpp, dstfmt, pixel, dR, dG, dB);
  594.                 ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB);
  595.                 ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
  596.                 src += srcbpp;
  597.                 dst += dstbpp;
  598.             },
  599.             width);
  600.             src += srcskip;
  601.             dst += dstskip;
  602.         }
  603. }
  604.  
  605. /* General (slow) colorkeyed N->N blending with per-surface alpha */
  606. static void BlitNtoNSurfaceAlphaKey(SDL_BlitInfo *info)
  607. {
  608.         int width = info->d_width;
  609.         int height = info->d_height;
  610.         Uint8 *src = info->s_pixels;
  611.         int srcskip = info->s_skip;
  612.         Uint8 *dst = info->d_pixels;
  613.         int dstskip = info->d_skip;
  614.         SDL_PixelFormat *srcfmt = info->src;
  615.         SDL_PixelFormat *dstfmt = info->dst;
  616.         Uint32 ckey = srcfmt->colorkey;
  617.         int srcbpp = srcfmt->BytesPerPixel;
  618.         int dstbpp = dstfmt->BytesPerPixel;
  619.         unsigned sA = srcfmt->alpha;
  620.         unsigned dA = dstfmt->Amask ? SDL_ALPHA_OPAQUE : 0;
  621.  
  622.         while ( height-- ) {
  623.             DUFFS_LOOP4(
  624.             {
  625.                 Uint32 pixel;
  626.                 unsigned sR;
  627.                 unsigned sG;
  628.                 unsigned sB;
  629.                 unsigned dR;
  630.                 unsigned dG;
  631.                 unsigned dB;
  632.                 RETRIEVE_RGB_PIXEL(src, srcbpp, pixel);
  633.                 if(pixel != ckey) {
  634.                     RGB_FROM_PIXEL(pixel, srcfmt, sR, sG, sB);
  635.                     DISEMBLE_RGB(dst, dstbpp, dstfmt, pixel, dR, dG, dB);
  636.                     ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB);
  637.                     ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
  638.                 }
  639.                 src += srcbpp;
  640.                 dst += dstbpp;
  641.             },
  642.             width);
  643.             src += srcskip;
  644.             dst += dstskip;
  645.         }
  646. }
  647.  
  648. /* General (slow) N->N blending with pixel alpha */
  649. static void BlitNtoNPixelAlpha(SDL_BlitInfo *info)
  650. {
  651.         int width = info->d_width;
  652.         int height = info->d_height;
  653.         Uint8 *src = info->s_pixels;
  654.         int srcskip = info->s_skip;
  655.         Uint8 *dst = info->d_pixels;
  656.         int dstskip = info->d_skip;
  657.         SDL_PixelFormat *srcfmt = info->src;
  658.         SDL_PixelFormat *dstfmt = info->dst;
  659.  
  660.         int  srcbpp;
  661.         int  dstbpp;
  662.  
  663.         /* Set up some basic variables */
  664.         srcbpp = srcfmt->BytesPerPixel;
  665.         dstbpp = dstfmt->BytesPerPixel;
  666.  
  667.         /* FIXME: for 8bpp source alpha, this doesn't get opaque values
  668.            quite right. for <8bpp source alpha, it gets them very wrong
  669.            (check all macros!)
  670.            It is unclear whether there is a good general solution that doesn't
  671.            need a branch (or a divide). */
  672.         while ( height-- ) {
  673.             DUFFS_LOOP4(
  674.             {
  675.                 Uint32 pixel;
  676.                 unsigned sR;
  677.                 unsigned sG;
  678.                 unsigned sB;
  679.                 unsigned dR;
  680.                 unsigned dG;
  681.                 unsigned dB;
  682.                 unsigned sA;
  683.                 unsigned dA;
  684.                 DISEMBLE_RGBA(src, srcbpp, srcfmt, pixel, sR, sG, sB, sA);
  685.                 DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
  686.                 ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB);
  687.                 ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
  688.                 src += srcbpp;
  689.                 dst += dstbpp;
  690.             },
  691.             width);
  692.             src += srcskip;
  693.             dst += dstskip;
  694.         }
  695. }
  696.  
  697.  
  698. SDL_loblit SDL_CalculateAlphaBlit(SDL_Surface *surface, int blit_index)
  699. {
  700.     SDL_PixelFormat *sf = surface->format;
  701.     SDL_PixelFormat *df = surface->map->dst->format;
  702.  
  703.     if(sf->Amask == 0) {
  704.         if((surface->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
  705.             if(df->BytesPerPixel == 1)
  706.                 return BlitNto1SurfaceAlphaKey;
  707.             else
  708.                 return BlitNtoNSurfaceAlphaKey;
  709.         } else {
  710.             /* Per-surface alpha blits */
  711.             switch(df->BytesPerPixel) {
  712.             case 1:
  713.                 return BlitNto1SurfaceAlpha;
  714.  
  715.             case 2:
  716.                 if(surface->map->identity) {
  717.                     if(df->Gmask == 0x7e0)
  718.                         return Blit565to565SurfaceAlpha;
  719.                     else if(df->Gmask == 0x3e0)
  720.                         return Blit555to555SurfaceAlpha;
  721.                 }
  722.                 return BlitNtoNSurfaceAlpha;
  723.  
  724.             case 4:
  725.                 if(sf->Rmask == df->Rmask
  726.                    && sf->Gmask == df->Gmask
  727.                    && sf->Bmask == df->Bmask
  728.                    && (sf->Rmask | sf->Gmask | sf->Bmask) == 0xffffff
  729.                    && sf->BytesPerPixel == 4)
  730.                     return BlitRGBtoRGBSurfaceAlpha;
  731.                 else
  732.                     return BlitNtoNSurfaceAlpha;
  733.  
  734.             case 3:
  735.             default:
  736.                 return BlitNtoNSurfaceAlpha;
  737.             }
  738.         }
  739.     } else {
  740.         /* Per-pixel alpha blits */
  741.         switch(df->BytesPerPixel) {
  742.         case 1:
  743.             return BlitNto1PixelAlpha;
  744.  
  745.         case 2:
  746.             if(sf->BytesPerPixel == 4 && sf->Amask == 0xff000000
  747.                && sf->Gmask == 0xff00
  748.                && ((sf->Rmask == 0xff && df->Rmask == 0x1f)
  749.                    || (sf->Bmask == 0xff && df->Bmask == 0x1f))) {
  750.                 if(df->Gmask == 0x7e0)
  751.                     return BlitARGBto565PixelAlpha;
  752.                 else if(df->Gmask == 0x3e0)
  753.                     return BlitARGBto555PixelAlpha;
  754.             }
  755.             return BlitNtoNPixelAlpha;
  756.  
  757.         case 4:
  758.             if(sf->Amask == 0xff000000
  759.                && sf->Rmask == df->Rmask
  760.                && sf->Gmask == df->Gmask
  761.                && sf->Bmask == df->Bmask
  762.                && sf->BytesPerPixel == 4)
  763.                 return BlitRGBtoRGBPixelAlpha;
  764.             return BlitNtoNPixelAlpha;
  765.  
  766.         case 3:
  767.         default:
  768.             return BlitNtoNPixelAlpha;
  769.         }
  770.     }
  771. }
  772.  
  773.