Fixed alpha blending textures with the GDI renderer
authorSam Lantinga <slouken@libsdl.org>
Sat, 07 Feb 2009 17:56:08 +0000
changeset 30548d93bfecb9dc
parent 3053 aa34d1180d30
child 3055 cd863dd2082b
Fixed alpha blending textures with the GDI renderer
include/SDL_pixels.h
src/video/SDL_alphamult.c
src/video/SDL_alphamult.h
src/video/SDL_blit.h
src/video/win32/SDL_gdirender.c
     1.1 --- a/include/SDL_pixels.h	Fri Jan 30 06:40:16 2009 +0000
     1.2 +++ b/include/SDL_pixels.h	Sat Feb 07 17:56:08 2009 +0000
     1.3 @@ -117,6 +117,12 @@
     1.4       (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX4) || \
     1.5       (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX8))
     1.6  
     1.7 +#define SDL_ISPIXELFORMAT_ALPHA(format)   \
     1.8 +    ((SDL_PIXELORDER(format) == SDL_PACKEDORDER_ARGB) || \
     1.9 +     (SDL_PIXELORDER(format) == SDL_PACKEDORDER_RGBA) || \
    1.10 +     (SDL_PIXELORDER(format) == SDL_PACKEDORDER_ABGR) || \
    1.11 +     (SDL_PIXELORDER(format) == SDL_PACKEDORDER_BGRA))
    1.12 +
    1.13  #define SDL_ISPIXELFORMAT_FOURCC(format)    \
    1.14      ((format) && !((format) & 0x80000000))
    1.15  
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/video/SDL_alphamult.c	Sat Feb 07 17:56:08 2009 +0000
     2.3 @@ -0,0 +1,58 @@
     2.4 +/*
     2.5 +    SDL - Simple DirectMedia Layer
     2.6 +    Copyright (C) 1997-2009 Sam Lantinga
     2.7 +
     2.8 +    This library is free software; you can redistribute it and/or
     2.9 +    modify it under the terms of the GNU Lesser General Public
    2.10 +    License as published by the Free Software Foundation; either
    2.11 +    version 2.1 of the License, or (at your option) any later version.
    2.12 +
    2.13 +    This library is distributed in the hope that it will be useful,
    2.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    2.16 +    Lesser General Public License for more details.
    2.17 +
    2.18 +    You should have received a copy of the GNU Lesser General Public
    2.19 +    License along with this library; if not, write to the Free Software
    2.20 +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    2.21 +
    2.22 +    Sam Lantinga
    2.23 +    slouken@libsdl.org
    2.24 +*/
    2.25 +#include "SDL_config.h"
    2.26 +
    2.27 +#include "SDL_blit.h"
    2.28 +#include "SDL_alphamult.h"
    2.29 +
    2.30 +/* Functions to pre-multiply the alpha channel into the color channels */
    2.31 +
    2.32 +#define DEFINE_PREMULTIPLY_FUNC(fmt) \
    2.33 +void \
    2.34 +SDL_PreMultiplyAlpha##fmt(int w, int h, Uint32 *pixels, int pitch) \
    2.35 +{ \
    2.36 +    pitch /= 4; \
    2.37 +    while (h--) { \
    2.38 +        int n; \
    2.39 +        Uint32 *row = pixels; \
    2.40 +        Uint32 pixel; \
    2.41 +        unsigned r, g, b, a; \
    2.42 + \
    2.43 +        for (n = w; n--; ) { \
    2.44 +            pixel = *row; \
    2.45 +            RGBA_FROM_##fmt(pixel, r, g, b, a); \
    2.46 +            r = (r * a) / 255; \
    2.47 +            g = (g * a) / 255; \
    2.48 +            b = (b * a) / 255; \
    2.49 +            fmt##_FROM_RGBA(*row, r, g, b, a); \
    2.50 +            ++row; \
    2.51 +        } \
    2.52 +        pixels += pitch; \
    2.53 +    } \
    2.54 +}
    2.55 +
    2.56 +DEFINE_PREMULTIPLY_FUNC(ARGB8888)
    2.57 +DEFINE_PREMULTIPLY_FUNC(RGBA8888)
    2.58 +DEFINE_PREMULTIPLY_FUNC(ABGR8888)
    2.59 +DEFINE_PREMULTIPLY_FUNC(BGRA8888)
    2.60 +
    2.61 +/* vi: set ts=4 sw=4 expandtab: */
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/video/SDL_alphamult.h	Sat Feb 07 17:56:08 2009 +0000
     3.3 @@ -0,0 +1,36 @@
     3.4 +/*
     3.5 +    SDL - Simple DirectMedia Layer
     3.6 +    Copyright (C) 1997-2009 Sam Lantinga
     3.7 +
     3.8 +    This library is free software; you can redistribute it and/or
     3.9 +    modify it under the terms of the GNU Lesser General Public
    3.10 +    License as published by the Free Software Foundation; either
    3.11 +    version 2.1 of the License, or (at your option) any later version.
    3.12 +
    3.13 +    This library is distributed in the hope that it will be useful,
    3.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    3.16 +    Lesser General Public License for more details.
    3.17 +
    3.18 +    You should have received a copy of the GNU Lesser General Public
    3.19 +    License along with this library; if not, write to the Free Software
    3.20 +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    3.21 +
    3.22 +    Sam Lantinga
    3.23 +    slouken@libsdl.org
    3.24 +*/
    3.25 +
    3.26 +/* Functions to pre-multiply the alpha channel into the color channels */
    3.27 +
    3.28 +#define DEFINE_PREMULTIPLY_FUNC(fmt) \
    3.29 +void \
    3.30 +SDL_PreMultiplyAlpha##fmt(int w, int h, Uint32 *pixels, int pitch);
    3.31 +
    3.32 +DEFINE_PREMULTIPLY_FUNC(ARGB8888)
    3.33 +DEFINE_PREMULTIPLY_FUNC(RGBA8888)
    3.34 +DEFINE_PREMULTIPLY_FUNC(ABGR8888)
    3.35 +DEFINE_PREMULTIPLY_FUNC(BGRA8888)
    3.36 +
    3.37 +#undef DEFINE_PREMULTIPLY_FUNC
    3.38 +
    3.39 +/* vi: set ts=4 sw=4 expandtab: */
     4.1 --- a/src/video/SDL_blit.h	Fri Jan 30 06:40:16 2009 +0000
     4.2 +++ b/src/video/SDL_blit.h	Sat Feb 07 17:56:08 2009 +0000
     4.3 @@ -240,6 +240,18 @@
     4.4  {									\
     4.5  	Pixel = (a<<24)|(r<<16)|(g<<8)|b;				\
     4.6  }
     4.7 +#define RGBA8888_FROM_RGBA(Pixel, r, g, b, a)				\
     4.8 +{									\
     4.9 +	Pixel = (r<<24)|(g<<16)|(b<<8)|a;				\
    4.10 +}
    4.11 +#define ABGR8888_FROM_RGBA(Pixel, r, g, b, a)				\
    4.12 +{									\
    4.13 +	Pixel = (a<<24)|(b<<16)|(g<<8)|r;				\
    4.14 +}
    4.15 +#define BGRA8888_FROM_RGBA(Pixel, r, g, b, a)				\
    4.16 +{									\
    4.17 +	Pixel = (b<<24)|(g<<16)|(r<<8)|a;				\
    4.18 +}
    4.19  #define ASSEMBLE_RGB(buf, bpp, fmt, r, g, b) 				\
    4.20  {									\
    4.21  	switch (bpp) {							\
    4.22 @@ -347,6 +359,13 @@
    4.23  	b = ((Pixel>>16)&0xFF);						\
    4.24  	a = (Pixel>>24);						\
    4.25  }
    4.26 +#define RGBA_FROM_BGRA8888(Pixel, r, g, b, a)				\
    4.27 +{									\
    4.28 +	r = ((Pixel>>8)&0xFF);						\
    4.29 +	g = ((Pixel>>16)&0xFF);						\
    4.30 +	b = (Pixel>>24);						\
    4.31 +	a = (Pixel&0xFF);						\
    4.32 +}
    4.33  #define DISEMBLE_RGBA(buf, bpp, fmt, Pixel, r, g, b, a)			   \
    4.34  do {									   \
    4.35  	switch (bpp) {							   \
     5.1 --- a/src/video/win32/SDL_gdirender.c	Fri Jan 30 06:40:16 2009 +0000
     5.2 +++ b/src/video/win32/SDL_gdirender.c	Sat Feb 07 17:56:08 2009 +0000
     5.3 @@ -26,6 +26,7 @@
     5.4  #include "SDL_win32video.h"
     5.5  #include "../SDL_rect_c.h"
     5.6  #include "../SDL_yuv_sw_c.h"
     5.7 +#include "../SDL_alphamult.h"
     5.8  
     5.9  /* GDI renderer implementation */
    5.10  
    5.11 @@ -120,6 +121,7 @@
    5.12      HBITMAP hbm;
    5.13      void *pixels;
    5.14      int pitch;
    5.15 +    SDL_bool premultiplied;
    5.16  } GDI_TextureData;
    5.17  
    5.18  static void
    5.19 @@ -463,10 +465,36 @@
    5.20  static int
    5.21  GDI_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
    5.22  {
    5.23 +    GDI_TextureData *data = (GDI_TextureData *) texture->driverdata;
    5.24 +
    5.25      switch (texture->blendMode) {
    5.26      case SDL_BLENDMODE_NONE:
    5.27 +        if (data->premultiplied) {
    5.28 +            /* Crap, we've lost the original pixel data... *sigh* */
    5.29 +        }
    5.30 +        return 0;
    5.31      case SDL_BLENDMODE_MASK:
    5.32      case SDL_BLENDMODE_BLEND:
    5.33 +        if (!data->premultiplied && data->pixels) {
    5.34 +            switch (texture->format) {
    5.35 +            case SDL_PIXELFORMAT_ARGB8888:
    5.36 +                SDL_PreMultiplyAlphaARGB8888(texture->w, texture->h, (Uint32 *)data->pixels, data->pitch);
    5.37 +                data->premultiplied = SDL_TRUE;
    5.38 +                break;
    5.39 +            case SDL_PIXELFORMAT_RGBA8888:
    5.40 +                SDL_PreMultiplyAlphaRGBA8888(texture->w, texture->h, (Uint32 *)data->pixels, data->pitch);
    5.41 +                data->premultiplied = SDL_TRUE;
    5.42 +                break;
    5.43 +            case SDL_PIXELFORMAT_ABGR8888:
    5.44 +                SDL_PreMultiplyAlphaABGR8888(texture->w, texture->h, (Uint32 *)data->pixels, data->pitch);
    5.45 +                data->premultiplied = SDL_TRUE;
    5.46 +                break;
    5.47 +            case SDL_PIXELFORMAT_BGRA8888:
    5.48 +                SDL_PreMultiplyAlphaBGRA8888(texture->w, texture->h, (Uint32 *)data->pixels, data->pitch);
    5.49 +                data->premultiplied = SDL_TRUE;
    5.50 +                break;
    5.51 +            }
    5.52 +        }
    5.53          return 0;
    5.54      default:
    5.55          SDL_Unsupported();
    5.56 @@ -525,6 +553,23 @@
    5.57                  src += pitch;
    5.58                  dst += data->pitch;
    5.59              }
    5.60 +            if (data->premultiplied) {
    5.61 +                Uint32 *pixels = (Uint32 *) data->pixels + rect->y * (data->pitch / 4) + rect->x;
    5.62 +                switch (texture->format) {
    5.63 +                case SDL_PIXELFORMAT_ARGB8888:
    5.64 +                    SDL_PreMultiplyAlphaARGB8888(rect->w, rect->h, pixels, data->pitch);
    5.65 +                    break;
    5.66 +                case SDL_PIXELFORMAT_RGBA8888:
    5.67 +                    SDL_PreMultiplyAlphaRGBA8888(rect->w, rect->h, pixels, data->pitch);
    5.68 +                    break;
    5.69 +                case SDL_PIXELFORMAT_ABGR8888:
    5.70 +                    SDL_PreMultiplyAlphaABGR8888(rect->w, rect->h, pixels, data->pitch);
    5.71 +                    break;
    5.72 +                case SDL_PIXELFORMAT_BGRA8888:
    5.73 +                    SDL_PreMultiplyAlphaBGRA8888(rect->w, rect->h, pixels, data->pitch);
    5.74 +                    break;
    5.75 +                }
    5.76 +            }
    5.77          } else if (rect->w == texture->w && pitch == data->pitch) {
    5.78              if (!SetDIBits
    5.79                  (renderdata->window_hdc, data->hbm, rect->y, rect->h, pixels,
    5.80 @@ -700,16 +745,13 @@
    5.81          SelectPalette(data->memory_hdc, texturedata->hpal, TRUE);
    5.82          RealizePalette(data->memory_hdc);
    5.83      }
    5.84 -    if (texture->blendMode & SDL_BLENDMODE_MASK) {
    5.85 +    if (texture->blendMode & (SDL_BLENDMODE_MASK|SDL_BLENDMODE_BLEND)) {
    5.86          BLENDFUNCTION blendFunc = {
    5.87              AC_SRC_OVER,
    5.88              0,
    5.89              texture->a,
    5.90              AC_SRC_ALPHA
    5.91          };
    5.92 -        /* FIXME: GDI uses premultiplied alpha!
    5.93 -         *        Once we solve this and somehow support blended drawing we can enable SDL_BLENDMODE_BLEND
    5.94 -         */
    5.95          if (!AlphaBlend
    5.96              (data->current_hdc, dstrect->x, dstrect->y, dstrect->w,
    5.97               dstrect->h, data->memory_hdc, srcrect->x, srcrect->y, srcrect->w,