diff --git a/src/SDL12_compat.c b/src/SDL12_compat.c index 9b5ba459b..0c1c4fb86 100644 --- a/src/SDL12_compat.c +++ b/src/SDL12_compat.c @@ -980,6 +980,7 @@ static SDL_Window *VideoWindow20 = NULL; static SDL_Renderer *VideoRenderer20 = NULL; static SDL_mutex *VideoRendererLock = NULL; static SDL_Texture *VideoTexture20 = NULL; +static SDL12_Surface VideoSurface12Location; static SDL12_Surface *VideoSurface12 = NULL; static SDL_Palette *VideoPhysicalPalette20 = NULL; static Uint32 VideoSurfacePresentTicks = 0; @@ -2616,6 +2617,19 @@ SDL_WasInit(Uint32 sdl12flags) return InitFlags20to12(SDL20_WasInit(sdl20flags)) | extraflags; } +static void +FreeSurfaceContents(SDL12_Surface *surface12) +{ + if (surface12->surface20) { + SDL20_FreeSurface(surface12->surface20); + surface12->surface20 = NULL; + } + if (surface12->format) { + SDL20_free(surface12->format->palette); + SDL20_free(surface12->format); + surface12->format = NULL; + } +} static SDL12_Surface *EndVidModeCreate(void); static void @@ -4701,7 +4715,7 @@ EventFilter20to12(void *data, SDL_Event *event20) } case SDL_MOUSEMOTION: - if (!VideoSurface12) { + if (!VideoSurface12 || !VideoSurface12->surface20) { return 1; /* we don't have a screen surface yet? Don't send this on to the app. */ } @@ -4937,26 +4951,21 @@ Rect12to20(const SDL12_Rect *rect12, SDL_Rect *rect20) return rect20; } -static SDL12_Surface * -Surface20to12(SDL_Surface *surface20) +static SDL_bool +Surface20to12InPlace(SDL_Surface *surface20, + SDL12_Surface *surface12) { SDL_BlendMode blendmode = SDL_BLENDMODE_NONE; - SDL12_Surface *surface12 = NULL; SDL12_Palette *palette12 = NULL; SDL12_PixelFormat *format12 = NULL; Uint32 flags = 0; if (!surface20) { - return NULL; + return SDL_FALSE; } if (surface20->pitch > 65535) { SDL20_SetError("Pitch is too large"); /* can't fit to 16-bits */ - return NULL; - } - - surface12 = (SDL12_Surface *) SDL20_malloc(sizeof (SDL12_Surface)); - if (!surface12) { - goto failed; + return SDL_FALSE; } if (surface20->format->palette) { @@ -5029,12 +5038,33 @@ Surface20to12(SDL_Surface *surface20) Rect20to12(&surface20->clip_rect, &surface12->clip_rect); surface12->refcount = surface20->refcount; - return surface12; + return SDL_TRUE; failed: - SDL20_free(surface12); SDL20_free(palette12); SDL20_free(format12); + return SDL_FALSE; +} + +static SDL12_Surface * +Surface20to12(SDL_Surface *surface20) +{ + SDL12_Surface *surface12 = NULL; + + surface12 = (SDL12_Surface *) SDL20_malloc(sizeof (SDL12_Surface)); + if (!surface12) { + goto failed; + } + + SDL20_zerop(surface12); + if (!Surface20to12InPlace(surface20, surface12)) { + goto failed; + } + + return surface12; + +failed: + SDL20_free(surface12); return NULL; } @@ -5102,11 +5132,10 @@ SetPalette12ForMasks(SDL12_Surface *surface12, const Uint32 Rmask, const Uint32 } } -DECLSPEC12 SDL12_Surface * SDLCALL -SDL_CreateRGBSurface(Uint32 flags12, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +static SDL_Surface * +CreateRGBSurface(Uint32 flags12, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) { SDL_Surface *surface20; - SDL12_Surface *surface12; /* SDL 1.2 checks this. */ if ((width >= 16384) || (height >= 65536)) { @@ -5152,21 +5181,38 @@ SDL_CreateRGBSurface(Uint32 flags12, int width, int height, int depth, Uint32 Rm surface20 = SDL20_CreateRGBSurface(0, width, height, depth, Rmask, Gmask, Bmask, Amask); } - surface12 = Surface20to12(surface20); - if (!surface12) { - SDL20_FreeSurface(surface20); - return NULL; - } - - SDL_assert((surface12->flags & ~(SDL12_SRCCOLORKEY|SDL12_SRCALPHA)) == 0); /* shouldn't have prealloc, rleaccel, or dontfree. */ + return surface20; +} +static void +Surface12SetMasks(SDL12_Surface *surface12, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +{ SetPalette12ForMasks(surface12, Rmask, Gmask, Bmask); if (Amask != 0) { surface12->flags |= SDL12_SRCALPHA; - SDL20_SetSurfaceBlendMode(surface20, SDL_BLENDMODE_BLEND); + SDL20_SetSurfaceBlendMode(surface12->surface20, SDL_BLENDMODE_BLEND); + } +} + +DECLSPEC12 SDL12_Surface * SDLCALL +SDL_CreateRGBSurface(Uint32 flags12, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +{ + SDL12_Surface *surface12; + SDL_Surface *surface20; + + surface20 = CreateRGBSurface(flags12, width, height, depth, Rmask, Gmask, Bmask, Amask); + if (!surface20) { + return NULL; + } + surface12 = Surface20to12(surface20); + if (!surface12) { + SDL20_FreeSurface(surface20); + return NULL; } + SDL_assert((surface12->flags & ~(SDL12_SRCCOLORKEY|SDL12_SRCALPHA)) == 0); /* shouldn't have prealloc, rleaccel, or dontfree. */ + Surface12SetMasks(surface12, Rmask, Gmask, Bmask, Amask); return surface12; } @@ -5195,6 +5241,8 @@ SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pit SDL_assert((surface12->flags & ~(SDL12_SRCCOLORKEY|SDL12_SRCALPHA)) == SDL12_PREALLOC); /* should _only_ have prealloc. */ + /* TODO: Is it correct that this always ignored Amask, or should it be + * using Surface12SetMasks which takes Amask into account? */ SetPalette12ForMasks(surface12, Rmask, Gmask, Bmask); return surface12; @@ -5207,11 +5255,7 @@ SDL_FreeSurface(SDL12_Surface *surface12) surface12->refcount--; if (surface12->refcount) return; - SDL20_FreeSurface(surface12->surface20); - if (surface12->format) { - SDL20_free(surface12->format->palette); - SDL20_free(surface12->format); - } + FreeSurfaceContents(surface12); SDL20_free(surface12); } } @@ -5526,11 +5570,9 @@ EndVidModeCreate(void) VideoPhysicalPalette20 = NULL; } if (VideoSurface12) { - SDL12_Surface *screen12 = VideoSurface12; SDL20_free(VideoSurface12->pixels); VideoSurface12->pixels = NULL; - VideoSurface12 = NULL; /* SDL_FreeSurface will ignore the screen surface, so NULL the global variable out. */ - SDL_FreeSurface(screen12); + FreeSurfaceContents(VideoSurface12); } if (VideoConvertSurface20) { SDL20_FreeSurface(VideoConvertSurface20); @@ -5564,16 +5606,27 @@ EndVidModeCreate(void) return NULL; } - -static SDL12_Surface * -CreateSurface12WithFormat(const int w, const int h, const Uint32 fmt) +/* Essentially the same as SDL_CreateRGBSurface, but in-place */ +static void +CreateVideoSurface(const Uint32 fmt) { Uint32 rmask, gmask, bmask, amask; int bpp; + SDL_Surface *surface20; + if (!SDL20_PixelFormatEnumToMasks(fmt, &bpp, &rmask, &gmask, &bmask, &amask)) { - return NULL; + return; } - return SDL_CreateRGBSurface(0, w, h, bpp, rmask, gmask, bmask, amask); + + SDL20_zerop(VideoSurface12); + surface20 = CreateRGBSurface(0, 0, 0, bpp, rmask, gmask, bmask, amask); + + if (!Surface20to12InPlace(surface20, VideoSurface12)) { + FreeSurfaceContents(VideoSurface12); + return; + } + + Surface12SetMasks(VideoSurface12, rmask, gmask, bmask, amask); } static SDL_Surface * @@ -5910,6 +5963,8 @@ SetVideoModeImpl(int width, int height, int bpp, Uint32 flags12) int scaled_height = height; const char *fromwin_env = NULL; + VideoSurface12 = &VideoSurface12Location; + if (flags12 & SDL12_OPENGL) { /* For now we default GL scaling to ENABLED. If an app breaks or is linked directly to glBindFramebuffer, they'll need to turn it off with this environment variable. @@ -5999,11 +6054,11 @@ SetVideoModeImpl(int width, int height, int bpp, Uint32 flags12) default: SDL20_SetError("Unsupported bits-per-pixel"); return NULL; } - SDL_assert((VideoSurface12 != NULL) == (VideoWindow20 != NULL)); + SDL_assert((VideoSurface12->surface20 != NULL) == (VideoWindow20 != NULL)); - if (VideoSurface12 && ((VideoSurface12->flags & SDL12_OPENGL) != (flags12 & SDL12_OPENGL))) { + if (VideoSurface12->surface20 && ((VideoSurface12->flags & SDL12_OPENGL) != (flags12 & SDL12_OPENGL))) { EndVidModeCreate(); /* rebuild the window if moving to/from a GL context */ - } else if (VideoSurface12 && (VideoSurface12->surface20->format->format != appfmt)) { + } else if (VideoSurface12->surface20 && (VideoSurface12->surface20->format->format != appfmt)) { EndVidModeCreate(); /* rebuild the window if changing pixel format */ } else if (VideoGLContext20) { /* SDL 1.2 (infuriatingly!) destroys the GL context on each resize in some cases, on various platforms. Try to match that. */ @@ -6145,11 +6200,11 @@ SetVideoModeImpl(int width, int height, int bpp, Uint32 flags12) SDL20_SetWindowResizable(VideoWindow20, (flags12 & SDL12_RESIZABLE) ? SDL_TRUE : SDL_FALSE); } - if (VideoSurface12) { + if (VideoSurface12->surface20) { SDL20_free(VideoSurface12->pixels); } else { - VideoSurface12 = CreateSurface12WithFormat(0, 0, appfmt); - if (!VideoSurface12) { + CreateVideoSurface(appfmt); + if (!VideoSurface12->surface20) { return EndVidModeCreate(); } } @@ -6665,7 +6720,7 @@ DECLSPEC12 SDL12_Surface * SDLCALL SDL_DisplayFormat(SDL12_Surface *surface12) { const Uint32 flags = surface12->flags & (SDL12_SRCCOLORKEY|SDL12_SRCALPHA|SDL12_RLEACCELOK); - if (!VideoSurface12) { + if (!VideoSurface12 || !VideoSurface12->surface20) { SDL20_SetError("No video mode has been set"); return NULL; } @@ -6681,7 +6736,7 @@ SDL_DisplayFormatAlpha(SDL12_Surface *surface12) SDL_PixelFormat *fmt20 = NULL; SDL12_PixelFormat fmt12; - if (!VideoSurface12) { + if (!VideoSurface12 || !VideoSurface12->surface20) { SDL20_SetError("No video mode has been set"); return NULL; } @@ -7266,7 +7321,7 @@ static void HandleInputGrab(SDL12_GrabMode mode) { /* SDL 1.2 always grabbed input if the video mode was fullscreen. */ - const SDL_bool isfullscreen = (VideoSurface12 && (VideoSurface12->flags & SDL12_FULLSCREEN)) ? SDL_TRUE : SDL_FALSE; + const SDL_bool isfullscreen = (VideoSurface12 && VideoSurface12->surface20 && (VideoSurface12->flags & SDL12_FULLSCREEN)) ? SDL_TRUE : SDL_FALSE; const SDL_bool wantgrab = (isfullscreen || (mode == SDL12_GRAB_ON)) ? SDL_TRUE : SDL_FALSE; if (VideoWindowGrabbed != wantgrab) { if (VideoWindow20) {