From 61f6c3277954961743388c9eb68c837da7e760fd Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 18 Aug 2007 01:44:21 +0000 Subject: [PATCH] More work in progress integrating SDL_Surface and the new SDL_Texture API --- include/SDL_compat.h | 4 + include/SDL_video.h | 178 +++++++++++++++--- src/SDL_compat.c | 29 +-- src/video/SDL_RLEaccel.c | 66 ++++--- src/video/SDL_blit.c | 64 +++---- src/video/SDL_blit.h | 33 ++-- src/video/SDL_surface.c | 389 +++++++++++++++++++++++---------------- src/video/SDL_video.c | 108 +++-------- 8 files changed, 506 insertions(+), 365 deletions(-) diff --git a/include/SDL_compat.h b/include/SDL_compat.h index 3d07520aa..184754e6e 100644 --- a/include/SDL_compat.h +++ b/include/SDL_compat.h @@ -37,6 +37,8 @@ extern "C" { #endif #define SDL_SWSURFACE 0x00000000 /* Not used */ +//#define SDL_SRCALPHA 0x00010000 +//#define SDL_SRCCOLORKEY 0x00020000 #define SDL_ANYFORMAT 0x00100000 #define SDL_HWPALETTE 0x00200000 #define SDL_DOUBLEBUF 0x00400000 @@ -146,6 +148,8 @@ extern DECLSPEC void SDLCALL SDL_UpdateRects(SDL_Surface * screen, extern DECLSPEC void SDLCALL SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h); extern DECLSPEC int SDLCALL SDL_Flip(SDL_Surface * screen); +extern DECLSPEC int SDLCALL SDL_SetAlpha(SDL_Surface * surface, Uint32 flag, + Uint8 alpha); extern DECLSPEC SDL_Surface *SDLCALL SDL_DisplayFormat(SDL_Surface * surface); extern DECLSPEC SDL_Surface *SDLCALL SDL_DisplayFormatAlpha(SDL_Surface * surface); diff --git a/include/SDL_video.h b/include/SDL_video.h index f05a5f220..12a85e8ba 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -265,10 +265,7 @@ typedef void *SDL_GLContext; /* These are the currently supported flags for the SDL_surface */ /* Used internally (read-only) */ #define SDL_PREALLOC 0x00000001 /* Surface uses preallocated memory */ -#define SDL_SRCALPHA 0x00000004 /* Blit uses source alpha blending */ -#define SDL_SRCCOLORKEY 0x00000008 /* Blit uses a source color key */ -#define SDL_RLEACCELOK 0x00000010 /* Private flag */ -#define SDL_RLEACCEL 0x00000020 /* Surface is RLE encoded */ +#define SDL_RLEACCEL 0x00000001 /* Surface is RLE encoded */ /* Evaluates to true if the surface needs to be locked before access */ #define SDL_MUSTLOCK(S) (((S)->flags & SDL_RLEACCEL) != 0) @@ -1401,34 +1398,157 @@ extern DECLSPEC int SDLCALL SDL_SaveBMP_RW SDL_SaveBMP_RW(surface, SDL_RWFromFile(file, "wb"), 1) /* - * Sets the color key (transparent pixel) in a blittable surface. - * If 'flag' is SDL_SRCCOLORKEY (optionally OR'd with SDL_RLEACCEL), - * 'key' will be the transparent pixel in the source image of a blit. - * SDL_RLEACCEL requests RLE acceleration for the surface if present, - * and removes RLE acceleration if absent. - * If 'flag' is 0, this function clears any current color key. - * This function returns 0, or -1 if there was an error. + * \fn int SDL_SetSurfaceRLE(SDL_Surface *surface, int flag) + * + * \brief Sets the RLE acceleration hint for a surface. + * + * \return 0 on success, or -1 if the surface is not valid + * + * \note If RLE is enabled, colorkey and alpha blending blits are much faster, + * but the surface must be locked before directly accessing the pixels. */ -extern DECLSPEC int SDLCALL SDL_SetColorKey - (SDL_Surface * surface, Uint32 flag, Uint32 key); +extern DECLSPEC int SDLCALL SDL_SetSurfaceRLE(SDL_Surface *surface, int flag); /* - * This function sets the alpha value for the entire surface, as opposed to - * using the alpha component of each pixel. This value measures the range - * of transparency of the surface, 0 being completely transparent to 255 - * being completely opaque. An 'alpha' value of 255 causes blits to be - * opaque, the source pixels copied to the destination (the default). Note - * that per-surface alpha can be combined with colorkey transparency. - * - * If 'flag' is 0, alpha blending is disabled for the surface. - * If 'flag' is SDL_SRCALPHA, alpha blending is enabled for the surface. - * OR:ing the flag with SDL_RLEACCEL requests RLE acceleration for the - * surface; if SDL_RLEACCEL is not specified, the RLE accel will be removed. - * - * The 'alpha' parameter is ignored for surfaces that have an alpha channel. - */ -extern DECLSPEC int SDLCALL SDL_SetAlpha(SDL_Surface * surface, Uint32 flag, - Uint8 alpha); + * \fn int SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key) + * + * \brief Sets the color key (transparent pixel) in a blittable surface. + * + * \param surface The surface to update + * \param flag Non-zero to enable colorkey and 0 to disable colorkey + * \param key The transparent pixel in the native surface format + * + * \return 0 on success, or -1 if the surface is not valid + */ +extern DECLSPEC int SDLCALL SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key); + +/** + * \fn int SDL_SetSurfaceColorMod(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b) + * + * \brief Set an additional color value used in blit operations + * + * \param surface The surface to update + * \param r The red source color value multiplied into blit operations + * \param g The green source color value multiplied into blit operations + * \param b The blue source color value multiplied into blit operations + * + * \return 0 on success, or -1 if the surface is not valid + * + * \sa SDL_GetSurfaceColorMod() + */ +extern DECLSPEC int SDLCALL SDL_SetSurfaceColorMod(SDL_Surface *surface, + Uint8 r, Uint8 g, Uint8 b); + + +/** + * \fn int SDL_GetSurfaceColorMod(SDL_Surface *surface, Uint8 *r, Uint8 *g, Uint8 *b) + * + * \brief Get the additional color value used in blit operations + * + * \param surface The surface to query + * \param r A pointer filled in with the source red color value + * \param g A pointer filled in with the source green color value + * \param b A pointer filled in with the source blue color value + * + * \return 0 on success, or -1 if the surface is not valid + * + * \sa SDL_SetSurfaceColorMod() + */ +extern DECLSPEC int SDLCALL SDL_GetSurfaceColorMod(SDL_Surface *surface, + Uint8 * r, Uint8 * g, + Uint8 * b); + +/** + * \fn int SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Uint8 alpha) + * + * \brief Set an additional alpha value used in blit operations + * + * \param surface The surface to update + * \param alpha The source alpha value multiplied into blit operations. + * + * \return 0 on success, or -1 if the surface is not valid + * + * \sa SDL_GetSurfaceAlphaMod() + */ +extern DECLSPEC int SDLCALL SDL_SetSurfaceAlphaMod(SDL_Surface *surface, + Uint8 alpha); + +/** + * \fn int SDL_GetSurfaceAlphaMod(SDL_Surface *surface, Uint8 *alpha) + * + * \brief Get the additional alpha value used in blit operations + * + * \param surface The surface to query + * \param alpha A pointer filled in with the source alpha value + * + * \return 0 on success, or -1 if the surface is not valid + * + * \sa SDL_SetSurfaceAlphaMod() + */ +extern DECLSPEC int SDLCALL SDL_GetSurfaceAlphaMod(SDL_Surface *surface, + Uint8 * alpha); + +/** + * \fn int SDL_SetSurfaceBlendMode(SDL_Surface *surface, int blendMode) + * + * \brief Set the blend mode used for blit operations + * + * \param surface The surface to update + * \param blendMode SDL_TextureBlendMode to use for blit blending + * + * \return 0 on success, or -1 if the parameters are not valid + * + * \sa SDL_GetSurfaceBlendMode() + */ +extern DECLSPEC int SDLCALL SDL_SetSurfaceBlendMode(SDL_Surface *surface, + int blendMode); + +/** + * \fn int SDL_GetSurfaceBlendMode(SDL_Surface *surface, int *blendMode) + * + * \brief Get the blend mode used for blit operations + * + * \param surface The surface to query + * \param blendMode A pointer filled in with the current blend mode + * + * \return 0 on success, or -1 if the surface is not valid + * + * \sa SDL_SetSurfaceBlendMode() + */ +extern DECLSPEC int SDLCALL SDL_GetSurfaceBlendMode(SDL_Surface *surface, + int *blendMode); + +/** + * \fn int SDL_SetSurfaceScaleMode(SDL_Surface *surface, int scaleMode) + * + * \brief Set the scale mode used for blit operations + * + * \param surface The surface to update + * \param scaleMode SDL_TextureScaleMode to use for blit scaling + * + * \return 0 on success, or -1 if the surface is not valid or the scale mode is not supported + * + * \note If the scale mode is not supported, the closest supported mode is chosen. Currently only SDL_TEXTURESCALEMODE_FAST is supported on surfaces. + * + * \sa SDL_GetSurfaceScaleMode() + */ +extern DECLSPEC int SDLCALL SDL_SetSurfaceScaleMode(SDL_Surface *surface, + int scaleMode); + +/** + * \fn int SDL_GetSurfaceScaleMode(SDL_Surface *surface, int *scaleMode) + * + * \brief Get the scale mode used for blit operations + * + * \param surface The surface to query + * \param scaleMode A pointer filled in with the current scale mode + * + * \return 0 on success, or -1 if the surface is not valid + * + * \sa SDL_SetSurfaceScaleMode() + */ +extern DECLSPEC int SDLCALL SDL_GetSurfaceScaleMode(SDL_Surface *surface, + int *scaleMode); /* * Sets the clipping rectangle for the destination surface in a blit. diff --git a/src/SDL_compat.c b/src/SDL_compat.c index 303fcbfd7..1c564418f 100644 --- a/src/SDL_compat.c +++ b/src/SDL_compat.c @@ -589,6 +589,22 @@ SDL_GetVideoSurface(void) return SDL_PublicSurface; } +int +SDL_SetAlpha(SDL_Surface * surface, Uint32 flag, Uint8 value) +{ + if (flag & SDL_RLEACCEL) { + SDL_SetSurfaceRLE(surface, 1); + } + if (flag) { + SDL_SetSurfaceAlphaMod(surface, value); + SDL_SetSurfaceBlendMode(surface, SDL_TEXTUREBLENDMODE_BLEND); + } else { + SDL_SetSurfaceAlphaMod(surface, 0xFF); + SDL_SetSurfaceBlendMode(surface, SDL_TEXTUREBLENDMODE_NONE); + } + return 0; +} + SDL_Surface * SDL_DisplayFormat(SDL_Surface * surface) { @@ -600,15 +616,7 @@ SDL_DisplayFormat(SDL_Surface * surface) } /* Set the flags appropriate for copying to display surface */ - flags = SDL_SWSURFACE; -#ifdef AUTORLE_DISPLAYFORMAT - flags |= (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA)); - flags |= SDL_RLEACCELOK; -#else - flags |= - surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA | SDL_RLEACCELOK); -#endif - return SDL_ConvertSurface(surface, SDL_PublicSurface->format, flags); + return SDL_ConvertSurface(surface, SDL_PublicSurface->format, SDL_RLEACCELOK); } SDL_Surface * @@ -658,8 +666,7 @@ SDL_DisplayFormatAlpha(SDL_Surface * surface) break; } format = SDL_AllocFormat(32, rmask, gmask, bmask, amask); - flags = surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK); - converted = SDL_ConvertSurface(surface, format, flags); + converted = SDL_ConvertSurface(surface, format, SDL_RLEACCELOK); SDL_FreeFormat(format); return converted; } diff --git a/src/video/SDL_RLEaccel.c b/src/video/SDL_RLEaccel.c index 68a229b7f..c5c3e2a83 100644 --- a/src/video/SDL_RLEaccel.c +++ b/src/video/SDL_RLEaccel.c @@ -905,8 +905,7 @@ SDL_RLEBlit(SDL_Surface * src, SDL_Rect * srcrect, } } - alpha = (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA - ? src->map->info.a : 255; + alpha = src->map->info.a; /* if left or right edge clipping needed, call clip blit */ if (srcrect->x || srcrect->w != src->w) { RLEClipBlit(w, srcbuf, dst, dstbuf, srcrect, alpha); @@ -1803,7 +1802,7 @@ RLEColorkeySurface(SDL_Surface * surface) int SDL_RLESurface(SDL_Surface * surface) { - int retcode; + int flags; /* Clear any previous RLE conversion */ if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) { @@ -1812,34 +1811,44 @@ SDL_RLESurface(SDL_Surface * surface) /* We don't support RLE encoding of bitmaps */ if (surface->format->BitsPerPixel < 8) { - return (-1); + return -1; } - /* Lock the surface if it's in hardware */ - if (SDL_MUSTLOCK(surface)) { - if (SDL_LockSurface(surface) < 0) { - return (-1); - } + /* Make sure the pixels are available */ + if (!surface->pixels) { + return -1; } - /* Encode */ - if ((surface->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) { - retcode = RLEColorkeySurface(surface); - } else { - if ((surface->flags & SDL_SRCALPHA) == SDL_SRCALPHA - && surface->format->Amask != 0) - retcode = RLEAlphaSurface(surface); - else - retcode = -1; /* no RLE for per-surface alpha sans ckey */ + /* If we don't have colorkey or blending, nothing to do... */ + flags = surface->map->info.flags; + if(!(flags & (SDL_COPY_COLORKEY|SDL_COPY_BLEND))) { + return -1; } - /* Unlock the surface if it's in hardware */ - if (SDL_MUSTLOCK(surface)) { - SDL_UnlockSurface(surface); + /* Pass on combinations not supported */ + if ((flags & SDL_COPY_MODULATE_COLOR) || + (flags & (SDL_COPY_ADD|SDL_COPY_MOD)) || + (flags & SDL_COPY_NEAREST)) { + return -1; } - if (retcode < 0) - return -1; + /* Encode and set up the blit */ + if (!surface->format->Amask || !(flags & SDL_COPY_BLEND)) { + if (!surface->map->identity) { + return -1; + } + if (RLEColorkeySurface(surface) < 0) { + return -1; + } + surface->map->blit = SDL_RLEBlit; + surface->map->info.flags |= SDL_COPY_RLE_COLORKEY; + } else { + if (RLEAlphaSurface(surface) < 0) { + return -1; + } + surface->map->blit = SDL_RLEAlphaBlit; + surface->map->info.flags |= SDL_COPY_RLE_ALPHAKEY; + } /* The surface is now accelerated */ surface->flags |= SDL_RLEACCEL; @@ -1931,13 +1940,12 @@ UnRLEAlpha(SDL_Surface * surface) void SDL_UnRLESurface(SDL_Surface * surface, int recode) { - if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) { + if (surface->flags & SDL_RLEACCEL) { surface->flags &= ~SDL_RLEACCEL; if (recode && !(surface->flags & SDL_PREALLOC)) { - if ((surface->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) { + if (surface->map->info.flags & SDL_COPY_RLE_COLORKEY) { SDL_Rect full; - unsigned alpha_flag; /* re-create the original surface */ surface->pixels = SDL_malloc(surface->h * surface->pitch); @@ -1954,10 +1962,7 @@ SDL_UnRLESurface(SDL_Surface * surface, int recode) full.x = full.y = 0; full.w = surface->w; full.h = surface->h; - alpha_flag = surface->flags & SDL_SRCALPHA; - surface->flags &= ~SDL_SRCALPHA; /* opaque blit */ SDL_RLEBlit(surface, &full, surface, &full); - surface->flags |= alpha_flag; } else { if (!UnRLEAlpha(surface)) { /* Oh crap... */ @@ -1966,8 +1971,9 @@ SDL_UnRLESurface(SDL_Surface * surface, int recode) } } } + surface->map->info.flags &= (SDL_COPY_RLE_COLORKEY|SDL_COPY_RLE_ALPHAKEY); - if (surface->map && surface->map->data) { + if (surface->map->data) { SDL_free(surface->map->data); surface->map->data = NULL; } diff --git a/src/video/SDL_blit.c b/src/video/SDL_blit.c index 3ab73b476..2b48a43c6 100644 --- a/src/video/SDL_blit.c +++ b/src/video/SDL_blit.c @@ -206,7 +206,8 @@ int SDL_CalculateBlit(SDL_Surface * surface) { SDL_BlitFunc blit = NULL; - SDL_Surface *dst = surface->map->dst; + SDL_BlitMap *map = surface->map; + SDL_Surface *dst = map->dst; Uint32 src_format; Uint32 dst_format; @@ -214,67 +215,48 @@ SDL_CalculateBlit(SDL_Surface * surface) if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) { SDL_UnRLESurface(surface, 1); } - surface->map->blit = NULL; - surface->map->info.src_fmt = surface->format; - surface->map->info.src_pitch = surface->pitch; - surface->map->info.dst_fmt = dst->format; - surface->map->info.dst_pitch = dst->pitch; + map->blit = SDL_SoftBlit; + map->info.src_fmt = surface->format; + map->info.src_pitch = surface->pitch; + map->info.dst_fmt = dst->format; + map->info.dst_pitch = dst->pitch; + + /* See if we can do RLE acceleration */ + if (surface->flags & SDL_RLEACCELOK) { + if (SDL_RLESurface(surface) == 0) { + return 0; + } + } + /* Choose a standard blit function */ src_format = SDL_MasksToPixelFormatEnum(surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask); dst_format = SDL_MasksToPixelFormatEnum(dst->format->BitsPerPixel, dst->format->Rmask, dst->format->Gmask, dst->format->Bmask, dst->format->Amask); - /* Check for special "identity" case -- copy blit */ - if (surface->map->identity && !surface->map->info.flags) { + if (map->identity && !map->info.flags) { /* Handle overlapping blits on the same surface */ if (surface == dst) { blit = SDL_BlitCopyOverlap; } else { blit = SDL_BlitCopy; } + } else if (surface->format->BitsPerPixel < 8) { + blit = SDL_ChooseBlitFunc(src_format, dst_format, map->info.flags, SDL_BlitFuncTable0); + } else if (surface->format->BytesPerPixel == 1) { + blit = SDL_ChooseBlitFunc(src_format, dst_format, map->info.flags, SDL_BlitFuncTable1); } else { - if (surface->format->BitsPerPixel < 8) { - blit = SDL_ChooseBlitFunc(src_format, dst_format, surface->map->info.flags, SDL_BlitFuncTable0); - } else { - switch (surface->format->BytesPerPixel) { - case 1: - blit = SDL_ChooseBlitFunc(src_format, dst_format, surface->map->info.flags, SDL_BlitFuncTable1); - break; - case 2: - case 3: - case 4: - blit = SDL_ChooseBlitFunc(src_format, dst_format, surface->map->info.flags, SDL_BlitFuncTableN); - break; - } - } + blit = SDL_ChooseBlitFunc(src_format, dst_format, map->info.flags, SDL_BlitFuncTableN); } if (blit == NULL) { - blit = SDL_ChooseBlitFunc(src_format, dst_format, surface->map->info.flags, SDL_GeneratedBlitFuncTable); + blit = SDL_ChooseBlitFunc(src_format, dst_format, map->info.flags, SDL_GeneratedBlitFuncTable); } /* Make sure we have a blit function */ if (blit == NULL) { - SDL_InvalidateMap(surface->map); + SDL_InvalidateMap(map); SDL_SetError("Blit combination not supported"); return (-1); } - /* Choose software blitting function */ - if ((surface->flags & SDL_RLEACCELOK) && !(surface->map->flags & () { - if (surface->map->identity && (surface->map->flags & SDL_COPY_COLORKEY) - && (blit_index == 1 - || (blit_index == 3 && !surface->format->Amask))) { - if (SDL_RLESurface(surface) == 0) - surface->map->blit = SDL_RLEBlit; - } else if (blit_index == 2 && surface->format->Amask) { - if (SDL_RLESurface(surface) == 0) - surface->map->blit = SDL_RLEAlphaBlit; - } - } - - if (surface->map->blit == NULL) { - surface->map->blit = SDL_SoftBlit; - surface->map->data = blit; - } return (0); } diff --git a/src/video/SDL_blit.h b/src/video/SDL_blit.h index e6cd41464..28e3b1168 100644 --- a/src/video/SDL_blit.h +++ b/src/video/SDL_blit.h @@ -41,23 +41,26 @@ #include "SDL_endian.h" /* SDL blit copy flags */ -#define SDL_COPY_MODULATE_COLOR 0x0001 -#define SDL_COPY_MODULATE_ALPHA 0x0002 -#define SDL_COPY_MASK 0x0010 -#define SDL_COPY_BLEND 0x0020 -#define SDL_COPY_ADD 0x0040 -#define SDL_COPY_MOD 0x0080 -#define SDL_COPY_COLORKEY 0x0100 -#define SDL_COPY_NEAREST 0x0200 +#define SDL_COPY_MODULATE_COLOR 0x00000001 +#define SDL_COPY_MODULATE_ALPHA 0x00000002 +#define SDL_COPY_MASK 0x00000010 +#define SDL_COPY_BLEND 0x00000020 +#define SDL_COPY_ADD 0x00000040 +#define SDL_COPY_MOD 0x00000080 +#define SDL_COPY_COLORKEY 0x00000100 +#define SDL_COPY_NEAREST 0x00000200 +#define SDL_COPY_RLE_DESIRED 0x00001000 +#define SDL_COPY_RLE_COLORKEY 0x00002000 +#define SDL_COPY_RLE_ALPHAKEY 0x00004000 /* SDL blit CPU flags */ -#define SDL_CPU_ANY 0x0000 -#define SDL_CPU_MMX 0x0001 -#define SDL_CPU_3DNOW 0x0002 -#define SDL_CPU_SSE 0x0004 -#define SDL_CPU_SSE2 0x0008 -#define SDL_CPU_ALTIVEC_PREFETCH 0x0010 -#define SDL_CPU_ALTIVEC_NOPREFETCH 0x0020 +#define SDL_CPU_ANY 0x00000000 +#define SDL_CPU_MMX 0x00000001 +#define SDL_CPU_3DNOW 0x00000002 +#define SDL_CPU_SSE 0x00000004 +#define SDL_CPU_SSE2 0x00000008 +#define SDL_CPU_ALTIVEC_PREFETCH 0x00000010 +#define SDL_CPU_ALTIVEC_NOPREFETCH 0x00000020 typedef struct { Uint8 *src; diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index 440ca7d23..afe0b4f6e 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -212,153 +212,251 @@ SDL_SetSurfacePalette(SDL_Surface * surface, SDL_Palette * palette) return 0; } -/* - * Set the color key in a blittable surface - */ -int -SDL_SetColorKey(SDL_Surface * surface, Uint32 flag, Uint32 key) +int SDL_SetSurfaceRLE(SDL_Surface *surface, int flag) { - /* Sanity check the flag as it gets passed in */ - if (flag & SDL_SRCCOLORKEY) { - if (flag & (SDL_RLEACCEL | SDL_RLEACCELOK)) { - flag = (SDL_SRCCOLORKEY | SDL_RLEACCELOK); - } else { - flag = SDL_SRCCOLORKEY; - } + Uint32 flags; + + if (!surface) { + return -1; + } + + if (flag) { + surface->flags |= SDL_RLEACCELOK; } else { - flag = 0; + surface->flags &= ~SDL_RLEACCELOK; + } + if (surface->flags != flags) { + SDL_InvalidateMap(surface->map); } + return 0; +} - /* Optimize away operations that don't change anything */ - if ((flag == (surface->flags & (SDL_SRCCOLORKEY | SDL_RLEACCELOK))) && - (key == surface->map->ckey)) { - return (0); +int SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key) +{ + int flags; + + if (!surface) { + return -1; } - /* UnRLE surfaces before we change the colorkey */ - if (surface->flags & SDL_RLEACCEL) { - SDL_UnRLESurface(surface, 1); + if (flag & SDL_RLEACCEL) { + SDL_SetSurfaceRLE(surface, 1); } + flags = surface->map->info.flags; if (flag) { - surface->flags |= SDL_SRCCOLORKEY; - surface->map->ckey = key; - if (flag & SDL_RLEACCELOK) { - surface->flags |= SDL_RLEACCELOK; - } else { - surface->flags &= ~SDL_RLEACCELOK; - } + surface->map->info.flags |= SDL_COPY_COLORKEY; + surface->map->info.colorkey = key; } else { - surface->flags &= ~(SDL_SRCCOLORKEY | SDL_RLEACCELOK); - surface->map->ckey = 0; + surface->map->info.flags &= ~SDL_COPY_COLORKEY; } - SDL_InvalidateMap(surface->map); - return (0); + if (surface->map->info.flags != flags) { + SDL_InvalidateMap(surface->map); + } + return 0; } -/* This function sets the alpha channel of a surface */ -int -SDL_SetAlpha(SDL_Surface * surface, Uint32 flag, Uint8 value) +int SDL_SetSurfaceColorMod(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b) { - Uint32 oldflags = surface->flags; - Uint32 oldalpha = (surface->map->cmod >> 24); - - /* Sanity check the flag as it gets passed in */ - if (flag & SDL_SRCALPHA) { - if (flag & (SDL_RLEACCEL | SDL_RLEACCELOK)) { - flag = (SDL_SRCALPHA | SDL_RLEACCELOK); - } else { - flag = SDL_SRCALPHA; - } + int flags; + + if (!surface) { + return -1; + } + + surface->map->info.r = r; + surface->map->info.g = g; + surface->map->info.b = b; + + flags = surface->map->info.flags; + if (r != 0xFF || g != 0xFF || b != 0xFF) { + surface->map->info.flags |= SDL_COPY_MODULATE_COLOR; } else { - flag = 0; + surface->map->info.flags &= ~SDL_COPY_MODULATE_COLOR; + } + if (surface->map->info.flags != flags) { + SDL_InvalidateMap(surface->map); } + return 0; +} + - /* Optimize away operations that don't change anything */ - if ((flag == (surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK))) && - (!flag || value == oldalpha)) { - return (0); +int SDL_GetSurfaceColorMod(SDL_Surface *surface, Uint8 * r, Uint8 * g, Uint8 * b) +{ + if (!surface) { + return -1; } - if (!(flag & SDL_RLEACCELOK) && (surface->flags & SDL_RLEACCEL)) - SDL_UnRLESurface(surface, 1); + if (r) { + *r = surface->map->info.r; + } + if (g) { + *g = surface->map->info.g; + } + if (b) { + *b = surface->map->info.b; + } + return 0; +} - if (flag) { - surface->flags |= SDL_SRCALPHA; - surface->map->cmod &= 0x00FFFFFF; - surface->map->cmod |= ((Uint32) value << 24); - if (flag & SDL_RLEACCELOK) { - surface->flags |= SDL_RLEACCELOK; - } else { - surface->flags &= ~SDL_RLEACCELOK; - } +int SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Uint8 alpha) +{ + int flags; + + if (!surface) { + return -1; + } + + surface->map->info.a = alpha; + + flags = surface->map->info.flags; + if (alpha != 0xFF) { + surface->map->info.flags |= SDL_COPY_MODULATE_ALPHA; } else { - surface->flags &= ~SDL_SRCALPHA; - surface->map->cmod |= 0xFF000000; - } - /* - * The representation for software surfaces is independent of - * per-surface alpha, so no need to invalidate the blit mapping - * if just the alpha value was changed. (If either is 255, we still - * need to invalidate.) - */ - if (oldflags != surface->flags - || (((oldalpha + 1) ^ (value + 1)) & 0x100)) { + surface->map->info.flags &= ~SDL_COPY_MODULATE_ALPHA; + } + if (surface->map->info.flags != flags) { SDL_InvalidateMap(surface->map); } - return (0); + return 0; } -int -SDL_SetAlphaChannel(SDL_Surface * surface, Uint8 value) +int SDL_GetSurfaceAlphaMod(SDL_Surface *surface, Uint8 * alpha) { - int row, col; - int offset; - Uint8 *buf; + if (!surface) { + return -1; + } + + if (alpha) { + *alpha = surface->map->info.a; + } + return 0; +} - if ((surface->format->Amask != 0xFF000000) && - (surface->format->Amask != 0x000000FF)) { - SDL_SetError("Unsupported surface alpha mask format"); +int SDL_SetSurfaceBlendMode(SDL_Surface *surface, int blendMode) +{ + int flags, status; + + if (!surface) { return -1; } -#if SDL_BYTEORDER == SDL_LIL_ENDIAN - if (surface->format->Amask == 0xFF000000) { - offset = 3; - } else { - offset = 0; + + status = 0; + flags = surface->map->info.flags; + surface->map->info.flags &= ~(SDL_COPY_MASK|SDL_COPY_BLEND|SDL_COPY_ADD|SDL_COPY_MOD); + switch (blendMode) { + case SDL_TEXTUREBLENDMODE_NONE: + break; + case SDL_TEXTUREBLENDMODE_MASK: + surface->map->info.flags |= SDL_COPY_MASK; + break; + case SDL_TEXTUREBLENDMODE_BLEND: + surface->map->info.flags |= SDL_COPY_BLEND; + break; + case SDL_TEXTUREBLENDMODE_ADD: + surface->map->info.flags |= SDL_COPY_ADD; + break; + case SDL_TEXTUREBLENDMODE_MOD: + surface->map->info.flags |= SDL_COPY_MOD; + break; + default: + SDL_Unsupported(); + status = -1; + break; + } + + if (surface->map->info.flags != flags) { + SDL_InvalidateMap(surface->map); } -#else - if (surface->format->Amask == 0xFF000000) { - offset = 0; - } else { - offset = 3; + return status; +} + +int SDL_GetSurfaceBlendMode(SDL_Surface *surface, int *blendMode) +{ + if (!surface) { + return -1; } -#endif /* Byte ordering */ - /* Quickly set the alpha channel of an RGBA or ARGB surface */ - if (SDL_MUSTLOCK(surface)) { - if (SDL_LockSurface(surface) < 0) { - return -1; - } + if (!blendMode) { + return 0; } - row = surface->h; - while (row--) { - col = surface->w; - buf = (Uint8 *) surface->pixels + row * surface->pitch + offset; - while (col--) { - *buf = value; - buf += 4; - } + + switch(surface->map->info.flags & (SDL_COPY_MASK|SDL_COPY_BLEND|SDL_COPY_ADD|SDL_COPY_MOD)) { + case SDL_COPY_MASK: + *blendMode = SDL_TEXTUREBLENDMODE_MASK: + break; + case SDL_COPY_BLEND: + *blendMode = SDL_TEXTUREBLENDMODE_BLEND: + break; + case SDL_COPY_ADD: + *blendMode = SDL_TEXTUREBLENDMODE_ADD: + break; + case SDL_COPY_MOD: + *blendMode = SDL_TEXTUREBLENDMODE_MOD: + break; + default: + *blendMode = SDL_TEXTUREBLENDMODE_NONE: + break; } - if (SDL_MUSTLOCK(surface)) { - SDL_UnlockSurface(surface); + return 0; +} + +int SDL_SetSurfaceScaleMode(SDL_Surface *surface, int scaleMode) +{ + int flags, status; + + if (!surface) { + return -1; + } + + status = 0; + flags = surface->map->info.flags; + surface->map->info.flags &= ~(SDL_COPY_NEAREST); + switch (scaleMode) { + case SDL_TEXTURESCALEMODE_NONE: + break; + case SDL_TEXTURESCALEMODE_FAST: + surface->map->info.flags |= SDL_COPY_NEAREST; + break; + case SDL_TEXTURESCALEMODE_SLOW: + case SDL_TEXTURESCALEMODE_BEST: + SDL_Unsupported(); + surface->map->info.flags |= SDL_COPY_NEAREST; + status = -1; + break; + default: + SDL_Unsupported(); + status = -1; + break; + } + + if (surface->map->info.flags != flags) { + SDL_InvalidateMap(surface->map); + } + return status; +} + +int SDL_GetSurfaceScaleMode(SDL_Surface *surface, int *scaleMode) +{ + if (!surface) { + return -1; + } + + if (!scaleMode) { + return 0; + } + + switch(surface->map->info.flags & (SDL_COPY_LINEAR)) { + case SDL_COPY_LINEAR: + *scaleMode = SDL_TEXTURESCALEMODE_FAST: + break; + default: + *scaleMode = SDL_TEXTURESCALEMODE_NONE: + break; } return 0; } -/* - * Set the clipping rectangle for a blittable surface - */ SDL_bool SDL_SetClipRect(SDL_Surface * surface, const SDL_Rect * rect) { @@ -557,9 +655,7 @@ SDL_ConvertSurface(SDL_Surface * surface, SDL_PixelFormat * format, Uint32 flags) { SDL_Surface *convert; - Uint32 colorkey = 0; - Uint8 alpha = 0; - Uint32 surface_flags; + Uint32 copy_flags; SDL_Rect bounds; /* Check for empty destination palette! (results in empty image) */ @@ -578,8 +674,7 @@ SDL_ConvertSurface(SDL_Surface * surface, } /* Create a new surface with the desired format */ - convert = SDL_CreateRGBSurface(flags, - surface->w, surface->h, + convert = SDL_CreateRGBSurface(0, surface->w, surface->h, format->BitsPerPixel, format->Rmask, format->Gmask, format->Bmask, format->Amask); @@ -595,26 +690,9 @@ SDL_ConvertSurface(SDL_Surface * surface, convert->format->palette->ncolors = format->palette->ncolors; } - /* Save the original surface color key and alpha */ - surface_flags = surface->flags; - if ((surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) { - /* Convert colourkeyed surfaces to RGBA if requested */ - if ((flags & SDL_SRCCOLORKEY) != SDL_SRCCOLORKEY && format->Amask) { - surface_flags &= ~SDL_SRCCOLORKEY; - } else { - colorkey = surface->map->ckey; - SDL_SetColorKey(surface, 0, 0); - } - } - if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) { - /* Copy over the alpha channel to RGBA if requested */ - if (format->Amask) { - surface->flags &= ~SDL_SRCALPHA; - } else { - alpha = (Uint8) (surface->map->cmod >> 24); - SDL_SetAlpha(surface, 0, 0); - } - } + /* Save the original copy flags */ + copy_flags = surface->map->info.flags; + surface->map->info.flags = 0; /* Copy over the image data */ bounds.x = 0; @@ -624,30 +702,25 @@ SDL_ConvertSurface(SDL_Surface * surface, SDL_LowerBlit(surface, &bounds, convert, &bounds); /* Clean up the original surface, and update converted surface */ - if (convert != NULL) { - SDL_SetClipRect(convert, &surface->clip_rect); - } - if ((surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) { - Uint32 cflags = surface_flags & (SDL_SRCCOLORKEY | SDL_RLEACCELOK); - if (convert != NULL) { - Uint8 keyR, keyG, keyB; - - SDL_GetRGB(colorkey, surface->format, &keyR, &keyG, &keyB); - SDL_SetColorKey(convert, cflags | (flags & SDL_RLEACCELOK), - SDL_MapRGB(convert->format, keyR, keyG, keyB)); - } - SDL_SetColorKey(surface, cflags, colorkey); - } - if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) { - Uint32 aflags = surface_flags & (SDL_SRCALPHA | SDL_RLEACCELOK); - if (convert != NULL) { - SDL_SetAlpha(convert, aflags | (flags & SDL_RLEACCELOK), alpha); - } - if (format->Amask) { - surface->flags |= SDL_SRCALPHA; - } else { - SDL_SetAlpha(surface, aflags, alpha); - } + SDL_SetClipRect(convert, &surface->clip_rect); + if (copy_flags & SDL_COPY_COLORKEY) { + Uint8 keyR, keyG, keyB, keyA; + + SDL_GetRGBA(colorkey, surface->format, &keyR, &keyG, &keyB, &keyA); + SDL_SetColorKey(convert, 1, + SDL_MapRGBA(convert->format, keyR, keyG, keyB, keyA)); + } + convert->map->info.r = surface->map->info.r; + convert->map->info.g = surface->map->info.g; + convert->map->info.b = surface->map->info.b; + convert->map->info.a = surface->map->info.a; + convert->map->info.flags = copy_flags; + surface->map->info.flags = copy_flags; + + /* Enable alpha blending by default if the new surface has an + * alpha channel or alpha modulation */ + if (format->Amask || (copy_flags & SDL_COPY_MODULATE_ALPHA)) { + SDL_SetSurfaceBlendMode(convert, SDL_TEXTUREBLENDMODE_BLEND); } /* We're ready to go! */ diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 966bbecd2..bbb44315b 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -1535,8 +1535,7 @@ SDL_TextureID SDL_CreateTextureFromSurface(Uint32 format, SDL_Surface * surface) { SDL_TextureID textureID; - Uint32 surface_flags = surface->flags; - SDL_PixelFormat *fmt = surface->format; + SDL_PixelFormat *fmt; int bpp; Uint32 Rmask, Gmask, Bmask, Amask; @@ -1544,6 +1543,7 @@ SDL_CreateTextureFromSurface(Uint32 format, SDL_Surface * surface) SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface"); return 0; } + fmt = surface->format; if (format) { if (!SDL_PixelFormatEnumToMasks @@ -1552,7 +1552,7 @@ SDL_CreateTextureFromSurface(Uint32 format, SDL_Surface * surface) return 0; } } else { - if (fmt->Amask || !(surface_flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA))) { + if (surface->format->Amask || !(flags & (SDL_COPY_COLORKEY|SDL_COPY_MASK|SDL_COPY_BLEND))) { bpp = fmt->BitsPerPixel; Rmask = fmt->Rmask; Gmask = fmt->Gmask; @@ -1595,92 +1595,38 @@ SDL_CreateTextureFromSurface(Uint32 format, SDL_Surface * surface) surface->pitch); } } else { - Uint32 cmod; - SDL_Rect bounds; - SDL_Surface dst; + SDL_PixelFormat *dst_fmt; + SDL_Surface *dst = NULL; /* Set up a destination surface for the texture update */ - SDL_zero(dst); - dst.format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); - if (!dst.format) { - SDL_DestroyTexture(textureID); - return 0; - } - dst.w = surface->w; - dst.h = surface->h; - dst.pitch = SDL_CalculatePitch(&dst); - dst.pixels = SDL_malloc(dst.h * dst.pitch); - if (!dst.pixels) { - SDL_DestroyTexture(textureID); - SDL_FreeFormat(dst.format); - SDL_OutOfMemory(); - return 0; - } - - /* Copy the palette if any */ - if (SDL_ISPIXELFORMAT_INDEXED(format)) { - if (fmt->palette) { - SDL_SetTexturePalette(textureID, fmt->palette->colors, 0, - fmt->palette->ncolors); - SDL_SetSurfacePalette(&dst, fmt->palette); - } else { - dst.format->palette = - SDL_AllocPalette((1 << SDL_BITSPERPIXEL(format))); - if (!dst.format->palette) { - SDL_DestroyTexture(textureID); - SDL_FreeFormat(dst.format); - return 0; + dst_fmt = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); + if (dst_fmt) { + if (SDL_ISPIXELFORMAT_INDEXED(format)) { + dst_fmt->palette = SDL_AllocPalette((1 << SDL_BITSPERPIXEL(format))); + if (dst_fmt->palette) { + if (fmt->palette) { +fixme + } else { + SDL_DitherColors(dst_fmt->palette->colors, SDL_BITSPERPIXEL(format)); + } + } + if (fmt->palette) { + dst_fmt->palette = fmt->palette; + } else { } - SDL_DitherColors(dst.format->palette->colors, - SDL_BITSPERPIXEL(format)); - } - } - - /* Make the texture transparent if the surface has colorkey */ - if (surface_flags & SDL_SRCCOLORKEY) { - int row; - int length = dst.w * dst.format->BytesPerPixel; - Uint8 *p = (Uint8 *) dst.pixels; - for (row = 0; row < dst.h; ++row) { - SDL_memset(p, 0, length); - p += dst.pitch; - } - } - - /* Copy over the alpha channel */ - cmod = surface->map->cmod; - if (surface_flags & SDL_SRCALPHA) { - if (fmt->Amask) { - surface->flags &= ~SDL_SRCALPHA; - } else { - /* FIXME: Need to make sure the texture has an alpha channel - * and copy 'alpha' into the texture alpha channel. - */ - SDL_SetAlpha(surface, 0, 0); } - } - /* Copy over the image data */ - bounds.x = 0; - bounds.y = 0; - bounds.w = surface->w; - bounds.h = surface->h; - SDL_LowerBlit(surface, &bounds, &dst, &bounds); - - /* Clean up the original surface */ - if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) { - Uint32 aflags = surface_flags & (SDL_SRCALPHA | SDL_RLEACCELOK); - if (fmt->Amask) { - surface->flags |= SDL_SRCALPHA; - } else { - SDL_SetAlpha(surface, aflags, (cmod >> 24)); + cvt = SDL_ConvertSurface(surface, fmt, 0); + if (cvt) { + SDL_UpdateTexture(textureID, NULL, cvt->pixels, cvt->pitch); + SDL_FreeSurface(cvt); } + SDL_FreeFormat(fmt); } + } - /* Update the texture */ - SDL_UpdateTexture(textureID, NULL, dst.pixels, dst.pitch); - SDL_free(dst.pixels); - SDL_FreeFormat(dst.format); + if (SDL_ISPIXELFORMAT_INDEXED(format) && fmt->palette) { + SDL_SetTexturePalette(textureID, fmt->palette->colors, 0, fmt->palette->ncolors); } return textureID;