From d2676c2985359dd7e9240b14e3e1f13079f781d2 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 7 Oct 2016 17:04:58 -0700 Subject: [PATCH] Fixed bug 2924 - SDL_CreateRGBSurface[From] versions that take SDL_PIXELFORMAT enum Daniel Gibson Currently, SDL_CreateRGBSurface() and SDL_CreateRGBSurfaceFrom() take Uint32 masks for RGBA to "describe" the Pixelformat of the surface. Internally those value are only used to map to one of the SDL_PIXELFORMAT_* enum values that are used for further processing. I think it would be both handy and more efficient to be able to specify SDL_PIXELFORMAT_* yourself without using SDL_PixelFormatEnumToMasks() to create masks first, so I implemented functions that do that: SDL_CreateRGBSurfaceWithFormat() and SDL_CreateRGBSurfaceWithFormatFrom() which are like the versions without "WithFormat" but instead of taking 4 Uint32s for R/G/B/A masks, they take one for a SDL_PIXELFORMAT_* enum value. Together with https://bugzilla.libsdl.org/show_bug.cgi?id=2923 creating a SDL_Surface* from RGBA data (e.g. from stb_image) is as easy as surf = SDL_SDL_CreateRGBSurfaceWithFormat(0, w, h, bppToUse*8, SDL_PIXELFORMAT_RGBA32); --- include/SDL_surface.h | 4 ++ src/dynapi/SDL_dynapi_overrides.h | 4 ++ src/dynapi/SDL_dynapi_procs.h | 2 + src/video/SDL_surface.c | 65 ++++++++++++++++++++++++------- 4 files changed, 60 insertions(+), 15 deletions(-) diff --git a/include/SDL_surface.h b/include/SDL_surface.h index 0fc65da98..e4a06a204 100644 --- a/include/SDL_surface.h +++ b/include/SDL_surface.h @@ -118,6 +118,8 @@ typedef int (*SDL_blit) (struct SDL_Surface * src, SDL_Rect * srcrect, extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurface (Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); +extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceWithFormat + (Uint32 flags, int width, int height, int depth, Uint32 format); extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, @@ -127,6 +129,8 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceFrom(void *pixels, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); +extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceWithFormatFrom + (void *pixels, int width, int height, int depth, int pitch, Uint32 format); extern DECLSPEC void SDLCALL SDL_FreeSurface(SDL_Surface * surface); /** diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 8ae86b09b..fbb03f943 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -445,6 +445,8 @@ #define SDL_iconv_close SDL_iconv_close_REAL #define SDL_iconv SDL_iconv_REAL #define SDL_iconv_string SDL_iconv_string_REAL +#define SDL_CreateRGBSurfaceWithFormat SDL_CreateRGBSurfaceWithFormat_REAL +#define SDL_CreateRGBSurfaceWithFormatFrom SDL_CreateRGBSurfaceWithFormatFrom_REAL #define SDL_CreateRGBSurface SDL_CreateRGBSurface_REAL #define SDL_CreateRGBSurfaceFrom SDL_CreateRGBSurfaceFrom_REAL #define SDL_FreeSurface SDL_FreeSurface_REAL @@ -607,3 +609,5 @@ #define SDL_RenderGetIntegerScale SDL_RenderGetIntegerScale_REAL #define SDL_DequeueAudio SDL_DequeueAudio_REAL #define SDL_SetWindowResizable SDL_SetWindowResizable_REAL +#define SDL_CreateRGBSurfaceWithFormat SDL_CreateRGBSurfaceWithFormat_REAL +#define SDL_CreateRGBSurfaceWithFormatFrom SDL_CreateRGBSurfaceWithFormatFrom_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index b2df0620b..b7cf285e8 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -641,3 +641,5 @@ SDL_DYNAPI_PROC(int,SDL_RenderSetIntegerScale,(SDL_Renderer *a, SDL_bool b),(a,b SDL_DYNAPI_PROC(SDL_bool,SDL_RenderGetIntegerScale,(SDL_Renderer *a),(a),return) SDL_DYNAPI_PROC(Uint32,SDL_DequeueAudio,(SDL_AudioDeviceID a, void *b, Uint32 c),(a,b,c),return) SDL_DYNAPI_PROC(void,SDL_SetWindowResizable,(SDL_Window *a, SDL_bool b),(a,b),) +SDL_DYNAPI_PROC(SDL_Surface*,SDL_CreateRGBSurfaceWithFormat,(Uint32 a, int b, int c, int d, Uint32 e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(SDL_Surface*,SDL_CreateRGBSurfaceWithFormatFrom,(void *a, int b, int c, int d, int e, Uint32 f),(a,b,c,d,e,f),return) diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index dae07f285..9d52e5ca4 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -27,27 +27,20 @@ #include "SDL_pixels_c.h" /* Public routines */ + /* - * Create an empty RGB surface of the appropriate depth + * Create an empty RGB surface of the appropriate depth using the given + * enum SDL_PIXELFORMAT_* format */ SDL_Surface * -SDL_CreateRGBSurface(Uint32 flags, - int width, int height, int depth, - Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +SDL_CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth, + Uint32 format) { SDL_Surface *surface; - Uint32 format; /* The flags are no longer used, make the compiler happy */ (void)flags; - /* Get the pixel format */ - format = SDL_MasksToPixelFormatEnum(depth, Rmask, Gmask, Bmask, Amask); - if (format == SDL_PIXELFORMAT_UNKNOWN) { - SDL_SetError("Unknown pixel format"); - return NULL; - } - /* Allocate the surface */ surface = (SDL_Surface *) SDL_calloc(1, sizeof(*surface)); if (surface == NULL) { @@ -105,7 +98,7 @@ SDL_CreateRGBSurface(Uint32 flags, } /* By default surface with an alpha mask are set up for blending */ - if (Amask) { + if (surface->format->Amask) { SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND); } @@ -114,6 +107,26 @@ SDL_CreateRGBSurface(Uint32 flags, return surface; } +/* + * Create an empty RGB surface of the appropriate depth + */ +SDL_Surface * +SDL_CreateRGBSurface(Uint32 flags, + int width, int height, int depth, + Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +{ + Uint32 format; + + /* Get the pixel format */ + format = SDL_MasksToPixelFormatEnum(depth, Rmask, Gmask, Bmask, Amask); + if (format == SDL_PIXELFORMAT_UNKNOWN) { + SDL_SetError("Unknown pixel format"); + return NULL; + } + + return SDL_CreateRGBSurfaceWithFormat(flags, width, height, depth, format); +} + /* * Create an RGB surface from an existing memory buffer */ @@ -125,8 +138,30 @@ SDL_CreateRGBSurfaceFrom(void *pixels, { SDL_Surface *surface; - surface = - SDL_CreateRGBSurface(0, 0, 0, depth, Rmask, Gmask, Bmask, Amask); + surface = SDL_CreateRGBSurface(0, 0, 0, depth, Rmask, Gmask, Bmask, Amask); + if (surface != NULL) { + surface->flags |= SDL_PREALLOC; + surface->pixels = pixels; + surface->w = width; + surface->h = height; + surface->pitch = pitch; + SDL_SetClipRect(surface, NULL); + } + return surface; +} + +/* + * Create an RGB surface from an existing memory buffer using the given given + * enum SDL_PIXELFORMAT_* format + */ +SDL_Surface * +SDL_CreateRGBSurfaceWithFormatFrom(void *pixels, + int width, int height, int depth, int pitch, + Uint32 format) +{ + SDL_Surface *surface; + + surface = SDL_CreateRGBSurfaceWithFormat(0, 0, 0, depth, format); if (surface != NULL) { surface->flags |= SDL_PREALLOC; surface->pixels = pixels;