-/***********************************************************
-* Artsoft Retro-Game Library *
-*----------------------------------------------------------*
-* (c) 1994-2002 Artsoft Entertainment *
-* Holger Schemel *
-* Detmolder Strasse 189 *
-* 33604 Bielefeld *
-* Germany *
-* e-mail: info@artsoft.org *
-*----------------------------------------------------------*
-* sdl.c *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+// Holger Schemel
+// info@artsoft.org
+// http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// sdl.c
+// ============================================================================
#include "system.h"
#include "sound.h"
#include "joystick.h"
#include "misc.h"
+#include "setup.h"
+#define ENABLE_UNUSED_CODE 0 /* currently unused functions */
-#if defined(TARGET_SDL)
/* ========================================================================= */
/* video functions */
/* ========================================================================= */
+/* SDL internal variables */
+#if defined(TARGET_SDL2)
+static SDL_Window *sdl_window = NULL;
+static SDL_Renderer *sdl_renderer = NULL;
+static SDL_Texture *sdl_texture_stream = NULL;
+static SDL_Texture *sdl_texture_target = NULL;
+static boolean fullscreen_enabled = FALSE;
+#endif
+
+static boolean limit_screen_updates = FALSE;
+
+
/* functions from SGE library */
void sge_Line(SDL_Surface *, Sint16, Sint16, Sint16, Sint16, Uint32);
-/* #ifdef PLATFORM_WIN32 */
-#define FULLSCREEN_BUG
-/* #endif */
+void SDLLimitScreenUpdates(boolean enable)
+{
+ limit_screen_updates = enable;
+}
+
+static void FinalizeScreen()
+{
+ // copy global animations to render target buffer, if defined (below border)
+ if (gfx.draw_global_anim_function != NULL)
+ gfx.draw_global_anim_function(DRAW_GLOBAL_ANIM_STAGE_1);
-/* stuff needed to work around SDL/Windows fullscreen drawing bug */
-static int fullscreen_width;
-static int fullscreen_height;
-static int fullscreen_xoffset;
-static int fullscreen_yoffset;
-static int video_xoffset;
-static int video_yoffset;
+ // copy global masked border to render target buffer, if defined
+ if (gfx.draw_global_border_function != NULL)
+ gfx.draw_global_border_function(DRAW_BORDER_TO_SCREEN);
-void SDLInitVideoDisplay(void)
+ // copy global animations to render target buffer, if defined (above border)
+ if (gfx.draw_global_anim_function != NULL)
+ gfx.draw_global_anim_function(DRAW_GLOBAL_ANIM_STAGE_2);
+}
+
+static void UpdateScreen(SDL_Rect *rect)
{
- putenv("SDL_VIDEO_CENTERED=1");
+ static unsigned int update_screen_delay = 0;
+ unsigned int update_screen_delay_value = 50; /* (milliseconds) */
+ SDL_Surface *screen = backbuffer->surface;
- /* initialize SDL video */
- if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
- Error(ERR_EXIT, "SDL_InitSubSystem() failed: %s", SDL_GetError());
+ if (limit_screen_updates &&
+ !DelayReached(&update_screen_delay, update_screen_delay_value))
+ return;
- /* set default SDL depth */
- video.default_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
+ LimitScreenUpdates(FALSE);
+
+#if 0
+ {
+ static int LastFrameCounter = 0;
+ boolean changed = (FrameCounter != LastFrameCounter);
+
+ printf("::: FrameCounter == %d [%s]\n", FrameCounter,
+ (changed ? "-" : "SAME FRAME UPDATED"));
+
+ LastFrameCounter = FrameCounter;
+
+ /*
+ if (FrameCounter % 2)
+ return;
+ */
+ }
+#endif
+
+ if (video.screen_rendering_mode == SPECIAL_RENDERING_BITMAP &&
+ gfx.final_screen_bitmap != NULL) // may not be initialized yet
+ {
+ // draw global animations using bitmaps instead of using textures
+ // to prevent texture scaling artefacts (this is potentially slower)
+
+ BlitBitmap(backbuffer, gfx.final_screen_bitmap, 0, 0,
+ gfx.win_xsize, gfx.win_ysize, 0, 0);
+
+ FinalizeScreen();
+
+ screen = gfx.final_screen_bitmap->surface;
+
+ // force full window redraw
+ rect = NULL;
+ }
+
+#if defined(TARGET_SDL2)
+ SDL_Texture *sdl_texture = sdl_texture_stream;
+
+ if (video.screen_rendering_mode == SPECIAL_RENDERING_TARGET)
+ sdl_texture = sdl_texture_target;
+
+ if (rect)
+ {
+ int bytes_x = screen->pitch / video.width;
+ int bytes_y = screen->pitch;
+
+ SDL_UpdateTexture(sdl_texture, rect,
+ screen->pixels + rect->x * bytes_x + rect->y * bytes_y,
+ screen->pitch);
+ }
+ else
+ {
+ SDL_UpdateTexture(sdl_texture, NULL, screen->pixels, screen->pitch);
+ }
+
+ // clear render target buffer
+ SDL_RenderClear(sdl_renderer);
+
+ // set renderer to use target texture for rendering
+ if (video.screen_rendering_mode == SPECIAL_RENDERING_TARGET ||
+ video.screen_rendering_mode == SPECIAL_RENDERING_DOUBLE)
+ SDL_SetRenderTarget(sdl_renderer, sdl_texture_target);
+
+ // copy backbuffer texture to render target buffer
+ if (video.screen_rendering_mode != SPECIAL_RENDERING_TARGET)
+ SDL_RenderCopy(sdl_renderer, sdl_texture_stream, NULL, NULL);
+
+ if (video.screen_rendering_mode != SPECIAL_RENDERING_BITMAP)
+ FinalizeScreen();
+
+ // when using target texture, copy it to screen buffer
+ if (video.screen_rendering_mode == SPECIAL_RENDERING_TARGET ||
+ video.screen_rendering_mode == SPECIAL_RENDERING_DOUBLE)
+ {
+ SDL_SetRenderTarget(sdl_renderer, NULL);
+ SDL_RenderCopy(sdl_renderer, sdl_texture_target, NULL, NULL);
+ }
+
+ // show render target buffer on screen
+ SDL_RenderPresent(sdl_renderer);
+
+#else // TARGET_SDL
+ if (rect)
+ SDL_UpdateRects(screen, 1, rect);
+ else
+ SDL_UpdateRect(screen, 0, 0, 0, 0);
+#endif
}
-void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
- boolean fullscreen)
+static void SDLSetWindowIcon(char *basename)
{
-#ifdef FULLSCREEN_BUG
- int i;
- static int screen_xy[][2] =
+ /* (setting the window icon on Mac OS X would replace the high-quality
+ dock icon with the currently smaller (and uglier) icon from file) */
+
+#if !defined(PLATFORM_MACOSX)
+ char *filename = getCustomImageFilename(basename);
+ SDL_Surface *surface;
+
+ if (filename == NULL)
{
- { 640, 480 },
- { 800, 600 },
- { 1024, 768 },
- { -1, -1 }
- };
+ Error(ERR_WARN, "SDLSetWindowIcon(): cannot find file '%s'", basename);
+
+ return;
+ }
+
+ if ((surface = IMG_Load(filename)) == NULL)
+ {
+ Error(ERR_WARN, "IMG_Load() failed: %s", SDL_GetError());
+
+ return;
+ }
+
+ /* set transparent color */
+ SDL_SetColorKey(surface, SET_TRANSPARENT_PIXEL,
+ SDL_MapRGB(surface->format, 0x00, 0x00, 0x00));
+
+#if defined(TARGET_SDL2)
+ SDL_SetWindowIcon(sdl_window, surface);
+#else
+ SDL_WM_SetIcon(surface, NULL);
+#endif
#endif
+}
+
+#if defined(TARGET_SDL2)
+
+static boolean equalSDLPixelFormat(SDL_PixelFormat *format1,
+ SDL_PixelFormat *format2)
+{
+ return (format1->format == format2->format &&
+ format1->BitsPerPixel == format2->BitsPerPixel &&
+ format1->BytesPerPixel == format2->BytesPerPixel &&
+ format1->Rmask == format2->Rmask &&
+ format1->Gmask == format2->Gmask &&
+ format1->Bmask == format2->Bmask &&
+ format1->Amask == format2->Amask);
+}
+
+boolean SDLSetNativeSurface(SDL_Surface **surface)
+{
+ SDL_Surface *new_surface;
+
+ if (surface == NULL ||
+ *surface == NULL ||
+ backbuffer == NULL ||
+ backbuffer->surface == NULL)
+ return FALSE;
+
+ // if pixel format already optimized for destination surface, do nothing
+ if (equalSDLPixelFormat((*surface)->format, backbuffer->surface->format))
+ return FALSE;
- /* default: normal game window size */
- fullscreen_width = video.width;
- fullscreen_height = video.height;
- fullscreen_xoffset = 0;
- fullscreen_yoffset = 0;
+ new_surface = SDL_ConvertSurface(*surface, backbuffer->surface->format, 0);
-#ifdef FULLSCREEN_BUG
- for (i = 0; screen_xy[i][0] != -1; i++)
+ if (new_surface == NULL)
+ Error(ERR_EXIT, "SDL_ConvertSurface() failed: %s", SDL_GetError());
+
+ SDL_FreeSurface(*surface);
+
+ *surface = new_surface;
+
+ return TRUE;
+}
+
+SDL_Surface *SDLGetNativeSurface(SDL_Surface *surface)
+{
+ SDL_PixelFormat format;
+ SDL_Surface *new_surface;
+
+ if (surface == NULL)
+ return NULL;
+
+ if (backbuffer && backbuffer->surface)
{
- if (video.width <= screen_xy[i][0] && video.height <= screen_xy[i][1])
- {
- fullscreen_width = screen_xy[i][0];
- fullscreen_height = screen_xy[i][1];
- break;
- }
+ format = *backbuffer->surface->format;
+ format.Amask = surface->format->Amask; // keep alpha channel
}
+ else
+ {
+ format = *surface->format;
+ }
+
+ new_surface = SDL_ConvertSurface(surface, &format, 0);
+
+ if (new_surface == NULL)
+ Error(ERR_EXIT, "SDL_ConvertSurface() failed: %s", SDL_GetError());
+
+ return new_surface;
+}
+
+#else
+
+boolean SDLSetNativeSurface(SDL_Surface **surface)
+{
+ SDL_Surface *new_surface;
+
+ if (surface == NULL ||
+ *surface == NULL ||
+ !video.initialized)
+ return FALSE;
+
+ new_surface = SDL_DisplayFormat(*surface);
+
+ if (new_surface == NULL)
+ Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
+
+ SDL_FreeSurface(*surface);
+
+ *surface = new_surface;
+
+ return TRUE;
+}
+
+SDL_Surface *SDLGetNativeSurface(SDL_Surface *surface)
+{
+ SDL_Surface *new_surface;
+
+ if (video.initialized)
+ new_surface = SDL_DisplayFormat(surface);
+ else
+ new_surface = SDL_ConvertSurface(surface, surface->format, SURFACE_FLAGS);
+
+ if (new_surface == NULL)
+ Error(ERR_EXIT, "%s() failed: %s",
+ (video.initialized ? "SDL_DisplayFormat" : "SDL_ConvertSurface"),
+ SDL_GetError());
+
+ return new_surface;
+}
+
+#endif
+
+#if defined(TARGET_SDL2)
+static SDL_Texture *SDLCreateTextureFromSurface(SDL_Surface *surface)
+{
+ SDL_Texture *texture = SDL_CreateTextureFromSurface(sdl_renderer, surface);
+
+ if (texture == NULL)
+ Error(ERR_EXIT, "SDL_CreateTextureFromSurface() failed: %s",
+ SDL_GetError());
+
+ return texture;
+}
+#endif
+
+void SDLCreateBitmapTextures(Bitmap *bitmap)
+{
+#if defined(TARGET_SDL2)
+ if (bitmap == NULL)
+ return;
+
+ if (bitmap->texture)
+ SDL_DestroyTexture(bitmap->texture);
+ if (bitmap->texture_masked)
+ SDL_DestroyTexture(bitmap->texture_masked);
+
+ bitmap->texture = SDLCreateTextureFromSurface(bitmap->surface);
+ bitmap->texture_masked = SDLCreateTextureFromSurface(bitmap->surface_masked);
+#endif
+}
+
+void SDLFreeBitmapTextures(Bitmap *bitmap)
+{
+#if defined(TARGET_SDL2)
+ if (bitmap == NULL)
+ return;
+
+ if (bitmap->texture)
+ SDL_DestroyTexture(bitmap->texture);
+ if (bitmap->texture_masked)
+ SDL_DestroyTexture(bitmap->texture_masked);
+
+ bitmap->texture = NULL;
+ bitmap->texture_masked = NULL;
+#endif
+}
+
+void SDLInitVideoDisplay(void)
+{
+#if !defined(TARGET_SDL2)
+ if (!strEqual(setup.system.sdl_videodriver, ARG_DEFAULT))
+ SDL_putenv(getStringCat2("SDL_VIDEODRIVER=", setup.system.sdl_videodriver));
+
+ SDL_putenv("SDL_VIDEO_CENTERED=1");
+#endif
+
+ /* initialize SDL video */
+ if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
+ Error(ERR_EXIT, "SDL_InitSubSystem() failed: %s", SDL_GetError());
- fullscreen_xoffset = (fullscreen_width - video.width) / 2;
- fullscreen_yoffset = (fullscreen_height - video.height) / 2;
+ /* set default SDL depth */
+#if !defined(TARGET_SDL2)
+ video.default_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
+#else
+ video.default_depth = 32; // (how to determine video depth in SDL2?)
+#endif
+}
+
+void SDLInitVideoBuffer(boolean fullscreen)
+{
+ video.window_scaling_percent = setup.window_scaling_percent;
+ video.window_scaling_quality = setup.window_scaling_quality;
+ video.screen_rendering_mode =
+ (strEqual(setup.screen_rendering_mode, STR_SPECIAL_RENDERING_BITMAP) ?
+ SPECIAL_RENDERING_BITMAP :
+ strEqual(setup.screen_rendering_mode, STR_SPECIAL_RENDERING_TARGET) ?
+ SPECIAL_RENDERING_TARGET:
+ strEqual(setup.screen_rendering_mode, STR_SPECIAL_RENDERING_DOUBLE) ?
+ SPECIAL_RENDERING_DOUBLE : SPECIAL_RENDERING_OFF);
+
+#if defined(TARGET_SDL2)
+ // SDL 2.0: support for (desktop) fullscreen mode available
+ video.fullscreen_available = TRUE;
+#else
+ // SDL 1.2: no support for fullscreen mode in R'n'D anymore
+ video.fullscreen_available = FALSE;
#endif
/* open SDL video output device (window or fullscreen mode) */
- if (!SDLSetVideoMode(backbuffer, fullscreen))
+ if (!SDLSetVideoMode(fullscreen))
Error(ERR_EXIT, "setting video mode failed");
+ /* !!! SDL2 can only set the window icon if the window already exists !!! */
+ /* set window icon */
+ SDLSetWindowIcon(program.icon_filename);
+
/* set window and icon title */
+#if defined(TARGET_SDL2)
+ SDL_SetWindowTitle(sdl_window, program.window_title);
+#else
SDL_WM_SetCaption(program.window_title, program.window_title);
+#endif
/* SDL cannot directly draw to the visible video framebuffer like X11,
but always uses a backbuffer, which is then blitted to the visible
buffer 'window' at the same size as the SDL backbuffer. Although it
should never be drawn to directly, it would do no harm nevertheless. */
- /* create additional (symbolic) buffer for double-buffering */
- *window = CreateBitmap(video.width, video.height, video.depth);
+ /* create additional (symbolic) buffer for double-buffering */
+ ReCreateBitmap(&window, video.width, video.height, video.depth);
+}
+
+static boolean SDLCreateScreen(boolean fullscreen)
+{
+ SDL_Surface *new_surface = NULL;
+
+#if defined(TARGET_SDL2)
+ int surface_flags_window = SURFACE_FLAGS | SDL_WINDOW_RESIZABLE;
+ int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN_DESKTOP;
+#else
+ int surface_flags_window = SURFACE_FLAGS;
+ int surface_flags_fullscreen = SURFACE_FLAGS; // (no fullscreen in SDL 1.2)
+#endif
+
+ int width = video.width;
+ int height = video.height;
+ int surface_flags = (fullscreen ? surface_flags_fullscreen :
+ surface_flags_window);
+
+ // default window size is unscaled
+ video.window_width = video.width;
+ video.window_height = video.height;
+
+#if defined(TARGET_SDL2)
+
+ // store if initial screen mode is fullscreen mode when changing screen size
+ video.fullscreen_initial = fullscreen;
+
+ float window_scaling_factor = (float)setup.window_scaling_percent / 100;
+
+ video.window_width = window_scaling_factor * width;
+ video.window_height = window_scaling_factor * height;
+
+ if (sdl_texture_stream)
+ {
+ SDL_DestroyTexture(sdl_texture_stream);
+ sdl_texture_stream = NULL;
+ }
+
+ if (sdl_texture_target)
+ {
+ SDL_DestroyTexture(sdl_texture_target);
+ sdl_texture_target = NULL;
+ }
+
+ if (!(fullscreen && fullscreen_enabled))
+ {
+ if (sdl_renderer)
+ {
+ SDL_DestroyRenderer(sdl_renderer);
+ sdl_renderer = NULL;
+ }
+
+ if (sdl_window)
+ {
+ SDL_DestroyWindow(sdl_window);
+ sdl_window = NULL;
+ }
+ }
+
+ if (sdl_window == NULL)
+ sdl_window = SDL_CreateWindow(program.window_title,
+ SDL_WINDOWPOS_CENTERED,
+ SDL_WINDOWPOS_CENTERED,
+ video.window_width,
+ video.window_height,
+ surface_flags);
+
+ if (sdl_window != NULL)
+ {
+#if 0
+ /* if SDL_CreateRenderer() is called from within a VirtualBox Windows VM
+ *without* enabling 2D/3D acceleration and/or guest additions installed,
+ it will crash if flags are *not* set to SDL_RENDERER_SOFTWARE (because
+ it will try to use accelerated graphics and apparently fails miserably) */
+ if (sdl_renderer == NULL)
+ sdl_renderer = SDL_CreateRenderer(sdl_window, -1, SDL_RENDERER_SOFTWARE);
+#else
+ if (sdl_renderer == NULL)
+ sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
+#endif
+
+ if (sdl_renderer != NULL)
+ {
+ SDL_RenderSetLogicalSize(sdl_renderer, width, height);
+ // SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
+ SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, setup.window_scaling_quality);
+
+ sdl_texture_stream = SDL_CreateTexture(sdl_renderer,
+ SDL_PIXELFORMAT_ARGB8888,
+ SDL_TEXTUREACCESS_STREAMING,
+ width, height);
+
+ sdl_texture_target = SDL_CreateTexture(sdl_renderer,
+ SDL_PIXELFORMAT_ARGB8888,
+ SDL_TEXTUREACCESS_TARGET,
+ width, height);
+
+ if (sdl_texture_stream != NULL &&
+ sdl_texture_target != NULL)
+ {
+ // use SDL default values for RGB masks and no alpha channel
+ new_surface = SDL_CreateRGBSurface(0, width, height, 32, 0,0,0, 0);
+
+ if (new_surface == NULL)
+ Error(ERR_WARN, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
+ }
+ else
+ {
+ Error(ERR_WARN, "SDL_CreateTexture() failed: %s", SDL_GetError());
+ }
+ }
+ else
+ {
+ Error(ERR_WARN, "SDL_CreateRenderer() failed: %s", SDL_GetError());
+ }
+ }
+ else
+ {
+ Error(ERR_WARN, "SDL_CreateWindow() failed: %s", SDL_GetError());
+ }
+
+#else // TARGET_SDL
+
+ if (gfx.final_screen_bitmap == NULL)
+ gfx.final_screen_bitmap = CreateBitmapStruct();
+
+ gfx.final_screen_bitmap->width = width;
+ gfx.final_screen_bitmap->height = height;
+
+ gfx.final_screen_bitmap->surface =
+ SDL_SetVideoMode(width, height, video.depth, surface_flags);
+
+ if (gfx.final_screen_bitmap->surface != NULL)
+ {
+ new_surface =
+ SDL_CreateRGBSurface(surface_flags, width, height, video.depth, 0,0,0, 0);
+
+ if (new_surface == NULL)
+ Error(ERR_WARN, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
+
+#if 0
+ new_surface = gfx.final_screen_bitmap->surface;
+ gfx.final_screen_bitmap = NULL;
+#endif
+
+ }
+ else
+ {
+ Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
+ }
+#endif
+
+#if defined(TARGET_SDL2)
+ // store fullscreen state ("video.fullscreen_enabled" may not reflect this!)
+ if (new_surface != NULL)
+ fullscreen_enabled = fullscreen;
+#endif
+
+ if (backbuffer == NULL)
+ backbuffer = CreateBitmapStruct();
+
+ backbuffer->width = video.width;
+ backbuffer->height = video.height;
+
+ if (backbuffer->surface)
+ SDL_FreeSurface(backbuffer->surface);
+
+ backbuffer->surface = new_surface;
+
+ return (new_surface != NULL);
+}
+
+boolean SDLSetVideoMode(boolean fullscreen)
+{
+ boolean success = FALSE;
+
+ SetWindowTitle();
+
+ if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
+ {
+ /* switch display to fullscreen mode, if available */
+ success = SDLCreateScreen(TRUE);
+
+ if (!success)
+ {
+ /* switching display to fullscreen mode failed -- do not try it again */
+ video.fullscreen_available = FALSE;
+ }
+ else
+ {
+ video.fullscreen_enabled = TRUE;
+ }
+ }
+
+ if ((!fullscreen && video.fullscreen_enabled) || !success)
+ {
+ /* switch display to window mode */
+ success = SDLCreateScreen(FALSE);
+
+ if (!success)
+ {
+ /* switching display to window mode failed -- should not happen */
+ }
+ else
+ {
+ video.fullscreen_enabled = FALSE;
+ video.window_scaling_percent = setup.window_scaling_percent;
+ video.window_scaling_quality = setup.window_scaling_quality;
+ video.screen_rendering_mode =
+ (strEqual(setup.screen_rendering_mode, STR_SPECIAL_RENDERING_BITMAP) ?
+ SPECIAL_RENDERING_BITMAP :
+ strEqual(setup.screen_rendering_mode, STR_SPECIAL_RENDERING_TARGET) ?
+ SPECIAL_RENDERING_TARGET:
+ strEqual(setup.screen_rendering_mode, STR_SPECIAL_RENDERING_DOUBLE) ?
+ SPECIAL_RENDERING_DOUBLE : SPECIAL_RENDERING_OFF);
+ }
+ }
+
+#if defined(TARGET_SDL2)
+ SDLRedrawWindow(); // map window
+#endif
+
+#ifdef DEBUG
+#if defined(PLATFORM_WIN32)
+ // experimental drag and drop code
+
+ SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
+
+ {
+ SDL_SysWMinfo wminfo;
+ HWND hwnd;
+ boolean wminfo_success = FALSE;
+
+ SDL_VERSION(&wminfo.version);
+#if defined(TARGET_SDL2)
+ if (sdl_window)
+ wminfo_success = SDL_GetWindowWMInfo(sdl_window, &wminfo);
+#else
+ wminfo_success = (SDL_GetWMInfo(&wminfo) == 1);
+#endif
+
+ if (wminfo_success)
+ {
+#if defined(TARGET_SDL2)
+ hwnd = wminfo.info.win.window;
+#else
+ hwnd = wminfo.window;
+#endif
+
+ DragAcceptFiles(hwnd, TRUE);
+ }
+ }
+#endif
+#endif
+
+ return success;
+}
+
+void SDLSetWindowTitle()
+{
+#if defined(TARGET_SDL2)
+ SDL_SetWindowTitle(sdl_window, program.window_title);
+#else
+ SDL_WM_SetCaption(program.window_title, program.window_title);
+#endif
+}
+
+#if defined(TARGET_SDL2)
+void SDLSetWindowScaling(int window_scaling_percent)
+{
+ if (sdl_window == NULL)
+ return;
+
+ float window_scaling_factor = (float)window_scaling_percent / 100;
+ int new_window_width = (int)(window_scaling_factor * video.width);
+ int new_window_height = (int)(window_scaling_factor * video.height);
+
+ SDL_SetWindowSize(sdl_window, new_window_width, new_window_height);
+
+ video.window_scaling_percent = window_scaling_percent;
+ video.window_width = new_window_width;
+ video.window_height = new_window_height;
+
+ SetWindowTitle();
}
-boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
+void SDLSetWindowScalingQuality(char *window_scaling_quality)
{
- boolean success = TRUE;
- int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
- int surface_flags_window = SURFACE_FLAGS;
- SDL_Surface *new_surface = NULL;
+ SDL_Texture *new_texture;
- if (*backbuffer == NULL)
- *backbuffer = CreateBitmapStruct();
+ if (sdl_texture_stream == NULL ||
+ sdl_texture_target == NULL)
+ return;
- if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
- {
- video_xoffset = fullscreen_xoffset;
- video_yoffset = fullscreen_yoffset;
+ SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, window_scaling_quality);
- /* switch display to fullscreen mode, if available */
- if ((new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height,
- video.depth, surface_flags_fullscreen))
- == NULL)
- {
- /* switching display to fullscreen mode failed */
- Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
+ new_texture = SDL_CreateTexture(sdl_renderer,
+ SDL_PIXELFORMAT_ARGB8888,
+ SDL_TEXTUREACCESS_STREAMING,
+ video.width, video.height);
- /* do not try it again */
- video.fullscreen_available = FALSE;
- success = FALSE;
- }
- else
- {
- (*backbuffer)->surface = new_surface;
+ if (new_texture != NULL)
+ {
+ SDL_DestroyTexture(sdl_texture_stream);
- video.fullscreen_enabled = TRUE;
- success = TRUE;
- }
+ sdl_texture_stream = new_texture;
}
- if ((!fullscreen && video.fullscreen_enabled) || new_surface == NULL)
+ new_texture = SDL_CreateTexture(sdl_renderer,
+ SDL_PIXELFORMAT_ARGB8888,
+ SDL_TEXTUREACCESS_TARGET,
+ video.width, video.height);
+
+ if (new_texture != NULL)
{
- video_xoffset = 0;
- video_yoffset = 0;
+ SDL_DestroyTexture(sdl_texture_target);
- /* switch display to window mode */
- if ((new_surface = SDL_SetVideoMode(video.width, video.height,
- video.depth, surface_flags_window))
- == NULL)
- {
- /* switching display to window mode failed -- should not happen */
- Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
+ sdl_texture_target = new_texture;
+ }
- success = FALSE;
- }
- else
- {
- (*backbuffer)->surface = new_surface;
+ SDLRedrawWindow();
- video.fullscreen_enabled = FALSE;
- success = TRUE;
- }
+ video.window_scaling_quality = window_scaling_quality;
+}
+
+void SDLSetScreenRenderingMode(char *screen_rendering_mode)
+{
+ video.screen_rendering_mode =
+ (strEqual(screen_rendering_mode, STR_SPECIAL_RENDERING_BITMAP) ?
+ SPECIAL_RENDERING_BITMAP :
+ strEqual(screen_rendering_mode, STR_SPECIAL_RENDERING_TARGET) ?
+ SPECIAL_RENDERING_TARGET:
+ strEqual(screen_rendering_mode, STR_SPECIAL_RENDERING_DOUBLE) ?
+ SPECIAL_RENDERING_DOUBLE : SPECIAL_RENDERING_OFF);
+}
+
+void SDLSetWindowFullscreen(boolean fullscreen)
+{
+ if (sdl_window == NULL)
+ return;
+
+ int flags = (fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
+
+ if (SDL_SetWindowFullscreen(sdl_window, flags) == 0)
+ video.fullscreen_enabled = fullscreen_enabled = fullscreen;
+
+ // if screen size was changed in fullscreen mode, correct desktop window size
+ if (!fullscreen && video.fullscreen_initial)
+ {
+ SDLSetWindowScaling(setup.window_scaling_percent);
+ SDL_SetWindowPosition(sdl_window,
+ SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
+
+ video.fullscreen_initial = FALSE;
}
+}
- return success;
+void SDLRedrawWindow()
+{
+ UpdateScreen(NULL);
}
+#endif
-void SDLCreateBitmapContent(Bitmap *new_bitmap, int width, int height,
+void SDLCreateBitmapContent(Bitmap *bitmap, int width, int height,
int depth)
{
- SDL_Surface *surface_tmp, *surface_native;
+ SDL_Surface *surface =
+ SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth, 0,0,0, 0);
- if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth,
- 0, 0, 0, 0))
- == NULL)
+ if (surface == NULL)
Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
- if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
- Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
-
- SDL_FreeSurface(surface_tmp);
+ SDLSetNativeSurface(&surface);
- new_bitmap->surface = surface_native;
+ bitmap->surface = surface;
}
void SDLFreeBitmapPointers(Bitmap *bitmap)
SDL_FreeSurface(bitmap->surface);
if (bitmap->surface_masked)
SDL_FreeSurface(bitmap->surface_masked);
+
bitmap->surface = NULL;
bitmap->surface_masked = NULL;
+
+#if defined(TARGET_SDL2)
+ if (bitmap->texture)
+ SDL_DestroyTexture(bitmap->texture);
+ if (bitmap->texture_masked)
+ SDL_DestroyTexture(bitmap->texture_masked);
+
+ bitmap->texture = NULL;
+ bitmap->texture_masked = NULL;
+#endif
}
void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
SDL_Rect src_rect, dst_rect;
-#ifdef FULLSCREEN_BUG
- if (src_bitmap == backbuffer)
- {
- src_x += video_xoffset;
- src_y += video_yoffset;
- }
-#endif
-
src_rect.x = src_x;
src_rect.y = src_y;
src_rect.w = width;
src_rect.h = height;
-#ifdef FULLSCREEN_BUG
- if (dst_bitmap == backbuffer || dst_bitmap == window)
- {
- dst_x += video_xoffset;
- dst_y += video_yoffset;
- }
-#endif
-
dst_rect.x = dst_x;
dst_rect.y = dst_y;
dst_rect.w = width;
dst_rect.h = height;
- if (src_bitmap != backbuffer || dst_bitmap != window)
+ // if (src_bitmap != backbuffer || dst_bitmap != window)
+ if (!(src_bitmap == backbuffer && dst_bitmap == window))
SDL_BlitSurface((mask_mode == BLIT_MASKED ?
src_bitmap->surface_masked : src_bitmap->surface),
&src_rect, real_dst_bitmap->surface, &dst_rect);
if (dst_bitmap == window)
- SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
+ UpdateScreen(&dst_rect);
}
-void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y,
- int width, int height, Uint32 color)
+void SDLBlitTexture(Bitmap *bitmap,
+ int src_x, int src_y, int width, int height,
+ int dst_x, int dst_y, int mask_mode)
{
- Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
- SDL_Rect rect;
+#if defined(TARGET_SDL2)
+ SDL_Texture *texture;
+ SDL_Rect src_rect;
+ SDL_Rect dst_rect;
-#ifdef FULLSCREEN_BUG
- if (dst_bitmap == backbuffer || dst_bitmap == window)
- {
- x += video_xoffset;
- y += video_yoffset;
- }
+ texture =
+ (mask_mode == BLIT_MASKED ? bitmap->texture_masked : bitmap->texture);
+
+ if (texture == NULL)
+ return;
+
+ src_rect.x = src_x;
+ src_rect.y = src_y;
+ src_rect.w = width;
+ src_rect.h = height;
+
+ dst_rect.x = dst_x;
+ dst_rect.y = dst_y;
+ dst_rect.w = width;
+ dst_rect.h = height;
+
+ SDL_RenderCopy(sdl_renderer, texture, &src_rect, &dst_rect);
#endif
+}
+
+void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height,
+ Uint32 color)
+{
+ Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
+ SDL_Rect rect;
rect.x = x;
rect.y = y;
SDL_FillRect(real_dst_bitmap->surface, &rect, color);
if (dst_bitmap == window)
- SDL_UpdateRect(backbuffer->surface, x, y, width, height);
+ UpdateScreen(&rect);
}
-void SDLFadeScreen(Bitmap *bitmap_cross, int fade_mode, int fade_delay,
- int post_delay)
+void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
+ int fade_mode, int fade_delay, int post_delay,
+ void (*draw_border_function)(void))
{
- static boolean initialization_needed = TRUE;
- static SDL_Surface *surface_screen_copy = NULL;
- static SDL_Surface *surface_black = NULL;
+ SDL_Surface *surface_source = gfx.fade_bitmap_source->surface;
+ SDL_Surface *surface_target = gfx.fade_bitmap_target->surface;
+ SDL_Surface *surface_black = gfx.fade_bitmap_black->surface;
SDL_Surface *surface_screen = backbuffer->surface;
- SDL_Surface *surface_cross; /* initialized later */
+ SDL_Surface *surface_cross = (bitmap_cross ? bitmap_cross->surface : NULL);
SDL_Rect src_rect, dst_rect;
- int src_x = 0, src_y = 0;
- int dst_x = 0, dst_y = 0;
- boolean fade_reverse = (fade_mode == FADE_MODE_FADE_IN ? TRUE : FALSE);
+ SDL_Rect dst_rect2;
+ int src_x = x, src_y = y;
+ int dst_x = x, dst_y = y;
unsigned int time_last, time_current;
- float alpha;
- int alpha_final;
+
+ // store function for drawing global masked border
+ void (*draw_global_border_function)(int) = gfx.draw_global_border_function;
+
+ // deactivate drawing of global border while fading, if needed
+ if (draw_border_function == NULL)
+ gfx.draw_global_border_function = NULL;
src_rect.x = src_x;
src_rect.y = src_y;
- src_rect.w = video.width;
- src_rect.h = video.height;
-
-#ifdef FULLSCREEN_BUG
- dst_x += video_xoffset;
- dst_y += video_yoffset;
-#endif
+ src_rect.w = width;
+ src_rect.h = height;
dst_rect.x = dst_x;
dst_rect.y = dst_y;
- dst_rect.w = video.width;
- dst_rect.h = video.height;
+ dst_rect.w = width; /* (ignored) */
+ dst_rect.h = height; /* (ignored) */
-#if 0
- if (!initialization_needed)
+ dst_rect2 = dst_rect;
+
+ /* copy source and target surfaces to temporary surfaces for fading */
+ if (fade_mode & FADE_TYPE_TRANSFORM)
{
- /* check if screen size has changed (can happen when toggling fullscreen) */
- if (surface_screen_copy->w != surface_screen->w ||
- surface_screen_copy->h != surface_screen->h)
- {
- SDL_FreeSurface(surface_screen_copy);
- SDL_FreeSurface(surface_black);
+ SDL_BlitSurface(surface_cross, &src_rect, surface_source, &src_rect);
+ SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
- initialization_needed = TRUE;
- }
+ draw_global_border_function(DRAW_BORDER_TO_FADE_SOURCE);
+ draw_global_border_function(DRAW_BORDER_TO_FADE_TARGET);
}
-#endif
+ else if (fade_mode & FADE_TYPE_FADE_IN)
+ {
+ SDL_BlitSurface(surface_black, &src_rect, surface_source, &src_rect);
+ SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
- if (initialization_needed)
+ draw_global_border_function(DRAW_BORDER_TO_FADE_TARGET);
+ }
+ else /* FADE_TYPE_FADE_OUT */
{
- unsigned int flags = SDL_SRCALPHA;
+ SDL_BlitSurface(surface_screen, &dst_rect, surface_source, &src_rect);
+ SDL_BlitSurface(surface_black, &src_rect, surface_target, &src_rect);
- /* use same surface type as screen surface */
- if ((surface_screen->flags & SDL_HWSURFACE))
- flags |= SDL_HWSURFACE;
- else
- flags |= SDL_SWSURFACE;
-
- /* create surface for temporary copy of screen buffer */
- if ((surface_screen_copy =
- SDL_CreateRGBSurface(flags,
-#if 1
- video.width,
- video.height,
+ draw_global_border_function(DRAW_BORDER_TO_FADE_SOURCE);
+ }
+
+ time_current = SDL_GetTicks();
+
+ if (fade_mode == FADE_MODE_MELT)
+ {
+ boolean done = FALSE;
+ int melt_pixels = 2;
+ int melt_columns = width / melt_pixels;
+ int ypos[melt_columns];
+ int max_steps = height / 8 + 32;
+ int steps_done = 0;
+ float steps = 0;
+ int i;
+
+ SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
+#if defined(TARGET_SDL2)
+ SDL_SetSurfaceBlendMode(surface_target, SDL_BLENDMODE_NONE);
#else
- surface_screen->w,
- surface_screen->h,
+ SDL_SetAlpha(surface_target, 0, 0); /* disable alpha blending */
#endif
- surface_screen->format->BitsPerPixel,
- surface_screen->format->Rmask,
- surface_screen->format->Gmask,
- surface_screen->format->Bmask,
- surface_screen->format->Amask)) == NULL)
- Error(ERR_EXIT, "SDL_CreateRGBSurface( ) failed: %s", SDL_GetError());
-
- /* create black surface for fading from/to black */
- if ((surface_black =
- SDL_CreateRGBSurface(flags,
-#if 1
- video.width,
- video.height,
+
+ ypos[0] = -GetSimpleRandom(16);
+
+ for (i = 1 ; i < melt_columns; i++)
+ {
+ int r = GetSimpleRandom(3) - 1; /* randomly choose from { -1, 0, -1 } */
+
+ ypos[i] = ypos[i - 1] + r;
+
+ if (ypos[i] > 0)
+ ypos[i] = 0;
+ else
+ if (ypos[i] == -16)
+ ypos[i] = -15;
+ }
+
+ while (!done)
+ {
+ int steps_final;
+
+ time_last = time_current;
+ time_current = SDL_GetTicks();
+ steps += max_steps * ((float)(time_current - time_last) / fade_delay);
+ steps_final = MIN(MAX(0, steps), max_steps);
+
+ steps_done++;
+
+ done = (steps_done >= steps_final);
+
+ for (i = 0 ; i < melt_columns; i++)
+ {
+ if (ypos[i] < 0)
+ {
+ ypos[i]++;
+
+ done = FALSE;
+ }
+ else if (ypos[i] < height)
+ {
+ int y1 = 16;
+ int y2 = 8;
+ int y3 = 8;
+ int dy = (ypos[i] < y1) ? ypos[i] + 1 : y2 + GetSimpleRandom(y3);
+
+ if (ypos[i] + dy >= height)
+ dy = height - ypos[i];
+
+ /* copy part of (appearing) target surface to upper area */
+ src_rect.x = src_x + i * melt_pixels;
+ // src_rect.y = src_y + ypos[i];
+ src_rect.y = src_y;
+ src_rect.w = melt_pixels;
+ // src_rect.h = dy;
+ src_rect.h = ypos[i] + dy;
+
+ dst_rect.x = dst_x + i * melt_pixels;
+ // dst_rect.y = dst_y + ypos[i];
+ dst_rect.y = dst_y;
+
+ if (steps_done >= steps_final)
+ SDL_BlitSurface(surface_target, &src_rect,
+ surface_screen, &dst_rect);
+
+ ypos[i] += dy;
+
+ /* copy part of (disappearing) source surface to lower area */
+ src_rect.x = src_x + i * melt_pixels;
+ src_rect.y = src_y;
+ src_rect.w = melt_pixels;
+ src_rect.h = height - ypos[i];
+
+ dst_rect.x = dst_x + i * melt_pixels;
+ dst_rect.y = dst_y + ypos[i];
+
+ if (steps_done >= steps_final)
+ SDL_BlitSurface(surface_source, &src_rect,
+ surface_screen, &dst_rect);
+
+ done = FALSE;
+ }
+ else
+ {
+ src_rect.x = src_x + i * melt_pixels;
+ src_rect.y = src_y;
+ src_rect.w = melt_pixels;
+ src_rect.h = height;
+
+ dst_rect.x = dst_x + i * melt_pixels;
+ dst_rect.y = dst_y;
+
+ if (steps_done >= steps_final)
+ SDL_BlitSurface(surface_target, &src_rect,
+ surface_screen, &dst_rect);
+ }
+ }
+
+ if (steps_done >= steps_final)
+ {
+ if (draw_border_function != NULL)
+ draw_border_function();
+
+ UpdateScreen(&dst_rect2);
+ }
+ }
+ }
+ else if (fade_mode == FADE_MODE_CURTAIN)
+ {
+ float xx;
+ int xx_final;
+ int xx_size = width / 2;
+
+ SDL_BlitSurface(surface_target, &src_rect, surface_screen, &dst_rect);
+#if defined(TARGET_SDL2)
+ SDL_SetSurfaceBlendMode(surface_source, SDL_BLENDMODE_NONE);
#else
- surface_screen->w,
- surface_screen->h,
+ SDL_SetAlpha(surface_source, 0, 0); /* disable alpha blending */
#endif
- surface_screen->format->BitsPerPixel,
- surface_screen->format->Rmask,
- surface_screen->format->Gmask,
- surface_screen->format->Bmask,
- surface_screen->format->Amask)) == NULL)
- Error(ERR_EXIT, "SDL_CreateRGBSurface( ) failed: %s", SDL_GetError());
- /* completely fill the surface with black color pixels */
- SDL_FillRect(surface_black, NULL,
- SDL_MapRGB(surface_screen->format, 0, 0, 0));
+ for (xx = 0; xx < xx_size;)
+ {
+ time_last = time_current;
+ time_current = SDL_GetTicks();
+ xx += xx_size * ((float)(time_current - time_last) / fade_delay);
+ xx_final = MIN(MAX(0, xx), xx_size);
+
+ src_rect.x = src_x;
+ src_rect.y = src_y;
+ src_rect.w = width;
+ src_rect.h = height;
+
+ dst_rect.x = dst_x;
+ dst_rect.y = dst_y;
+
+ /* draw new (target) image to screen buffer */
+ SDL_BlitSurface(surface_target, &src_rect, surface_screen, &dst_rect);
+
+ if (xx_final < xx_size)
+ {
+ src_rect.w = xx_size - xx_final;
+ src_rect.h = height;
+
+ /* draw old (source) image to screen buffer (left side) */
+
+ src_rect.x = src_x + xx_final;
+ dst_rect.x = dst_x;
+
+ SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
+
+ /* draw old (source) image to screen buffer (right side) */
+
+ src_rect.x = src_x + xx_size;
+ dst_rect.x = dst_x + xx_size + xx_final;
- initialization_needed = FALSE;
+ SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
+ }
+
+ if (draw_border_function != NULL)
+ draw_border_function();
+
+ /* only update the region of the screen that is affected from fading */
+ UpdateScreen(&dst_rect2);
+ }
}
+ else /* fading in, fading out or cross-fading */
+ {
+ float alpha;
+ int alpha_final;
- /* copy the current screen backbuffer to the temporary screen copy buffer */
- SDL_BlitSurface(surface_screen, &dst_rect, surface_screen_copy, &src_rect);
+ for (alpha = 0.0; alpha < 255.0;)
+ {
+ time_last = time_current;
+ time_current = SDL_GetTicks();
+ alpha += 255 * ((float)(time_current - time_last) / fade_delay);
+ alpha_final = MIN(MAX(0, alpha), 255);
+
+ /* draw existing (source) image to screen buffer */
+ SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
+
+ /* draw new (target) image to screen buffer using alpha blending */
+#if defined(TARGET_SDL2)
+ SDL_SetSurfaceAlphaMod(surface_target, alpha_final);
+ SDL_SetSurfaceBlendMode(surface_target, SDL_BLENDMODE_BLEND);
+#else
+ SDL_SetAlpha(surface_target, SDL_SRCALPHA, alpha_final);
+#endif
+ SDL_BlitSurface(surface_target, &src_rect, surface_screen, &dst_rect);
- surface_cross = (fade_mode == FADE_MODE_CROSSFADE ? bitmap_cross->surface :
- surface_black);
+ if (draw_border_function != NULL)
+ draw_border_function();
- time_current = SDL_GetTicks();
+ /* only update the region of the screen that is affected from fading */
+ UpdateScreen(&dst_rect);
+ }
+ }
- for (alpha = 0.0; alpha < 255.0;)
+ if (post_delay > 0)
{
- time_last = time_current;
+ unsigned int time_post_delay;
+
time_current = SDL_GetTicks();
- alpha += 255 * ((float)(time_current - time_last) / fade_delay);
- alpha_final = (int)(fade_reverse ? 255.0 - alpha : alpha);
- alpha_final = MIN(MAX(0, alpha_final), 255);
+ time_post_delay = time_current + post_delay;
- /* draw existing image to screen buffer */
- SDL_BlitSurface(surface_screen_copy, &src_rect, surface_screen, &dst_rect);
+ while (time_current < time_post_delay)
+ {
+ // do not wait longer than 10 ms at a time to be able to ...
+ Delay(MIN(10, time_post_delay - time_current));
- /* draw new image to screen buffer using alpha blending */
- SDL_SetAlpha(surface_cross, SDL_SRCALPHA, alpha_final);
- SDL_BlitSurface(surface_cross, &src_rect, surface_screen, &dst_rect);
+ // ... continue drawing global animations during post delay
+ UpdateScreen(NULL);
- /* draw screen buffer to visible display */
- SDL_Flip(surface_screen);
+ time_current = SDL_GetTicks();
+ }
}
- Delay(post_delay);
+ // restore function for drawing global masked border
+ gfx.draw_global_border_function = draw_global_border_function;
}
void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
rect.w = (to_x - from_x + 1);
rect.h = (to_y - from_y + 1);
-#ifdef FULLSCREEN_BUG
- if (dst_bitmap == backbuffer || dst_bitmap == window)
- {
- rect.x += video_xoffset;
- rect.y += video_yoffset;
- }
-#endif
-
SDL_FillRect(surface, &rect, color);
}
void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
int to_x, int to_y, Uint32 color)
{
-#ifdef FULLSCREEN_BUG
- if (dst_bitmap == backbuffer || dst_bitmap == window)
- {
- from_x += video_xoffset;
- from_y += video_yoffset;
- to_x += video_xoffset;
- to_y += video_yoffset;
- }
-#endif
-
sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
}
-#if 0
+#if ENABLE_UNUSED_CODE
void SDLDrawLines(SDL_Surface *surface, struct XY *points,
int num_points, Uint32 color)
{
{
SDL_Surface *surface = src_bitmap->surface;
-#ifdef FULLSCREEN_BUG
- if (src_bitmap == backbuffer || src_bitmap == window)
- {
- x += video_xoffset;
- y += video_yoffset;
- }
-#endif
-
switch (surface->format->BytesPerPixel)
{
case 1: /* assuming 8-bpp */
/* ========================================================================= */
/* The following functions were taken from the SGE library */
-/* (SDL Graphics Extension Library) by Anders Lindström */
+/* (SDL Graphics Extension Library) by Anders Lindström */
/* http://www.etek.chalmers.se/~e8cal1/sge/index.html */
/* ========================================================================= */
void SDLPutPixel(Bitmap *dst_bitmap, int x, int y, Pixel pixel)
{
-#ifdef FULLSCREEN_BUG
- if (dst_bitmap == backbuffer || dst_bitmap == window)
- {
- x += video_xoffset;
- y += video_yoffset;
- }
-#endif
-
sge_PutPixel(dst_bitmap->surface, x, y, pixel);
}
Uint8 a;
} tColorRGBA;
-int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
+int zoomSurfaceRGBA_scaleDownBy2(SDL_Surface *src, SDL_Surface *dst)
{
- int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
+ int x, y;
tColorRGBA *sp, *csp, *dp;
- int sgap, dgap;
+ int dgap;
+
+ /* pointer setup */
+ sp = csp = (tColorRGBA *) src->pixels;
+ dp = (tColorRGBA *) dst->pixels;
+ dgap = dst->pitch - dst->w * 4;
+
+ for (y = 0; y < dst->h; y++)
+ {
+ sp = csp;
+
+ for (x = 0; x < dst->w; x++)
+ {
+ tColorRGBA *sp0 = sp;
+ tColorRGBA *sp1 = (tColorRGBA *) ((Uint8 *) sp + src->pitch);
+ tColorRGBA *sp00 = &sp0[0];
+ tColorRGBA *sp01 = &sp0[1];
+ tColorRGBA *sp10 = &sp1[0];
+ tColorRGBA *sp11 = &sp1[1];
+ tColorRGBA new;
+
+ /* create new color pixel from all four source color pixels */
+ new.r = (sp00->r + sp01->r + sp10->r + sp11->r) / 4;
+ new.g = (sp00->g + sp01->g + sp10->g + sp11->g) / 4;
+ new.b = (sp00->b + sp01->b + sp10->b + sp11->b) / 4;
+ new.a = (sp00->a + sp01->a + sp10->a + sp11->a) / 4;
+
+ /* draw */
+ *dp = new;
+
+ /* advance source pointers */
+ sp += 2;
+
+ /* advance destination pointer */
+ dp++;
+ }
+
+ /* advance source pointer */
+ csp = (tColorRGBA *) ((Uint8 *) csp + 2 * src->pitch);
+
+ /* advance destination pointers */
+ dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
+ }
+
+ return 0;
+}
+
+int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
+{
+ int x, y, *sax, *say, *csax, *csay;
+ float sx, sy;
+ tColorRGBA *sp, *csp, *csp0, *dp;
+ int dgap;
+
+ /* use specialized zoom function when scaling down to exactly half size */
+ if (src->w == 2 * dst->w &&
+ src->h == 2 * dst->h)
+ return zoomSurfaceRGBA_scaleDownBy2(src, dst);
/* variable setup */
- sx = (int) (65536.0 * (float) src->w / (float) dst->w);
- sy = (int) (65536.0 * (float) src->h / (float) dst->h);
+ sx = (float) src->w / (float) dst->w;
+ sy = (float) src->h / (float) dst->h;
/* allocate memory for row increments */
- sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
- say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
+ csax = sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
+ csay = say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
/* precalculate row increments */
- csx = 0;
- csax = sax;
for (x = 0; x <= dst->w; x++)
- {
- *csax = csx;
- csax++;
- csx &= 0xffff;
- csx += sx;
- }
+ *csax++ = (int)(sx * x);
- csy = 0;
- csay = say;
for (y = 0; y <= dst->h; y++)
- {
- *csay = csy;
- csay++;
- csy &= 0xffff;
- csy += sy;
- }
+ *csay++ = (int)(sy * y);
/* pointer setup */
- sp = csp = (tColorRGBA *) src->pixels;
+ sp = csp = csp0 = (tColorRGBA *) src->pixels;
dp = (tColorRGBA *) dst->pixels;
- sgap = src->pitch - src->w * 4;
dgap = dst->pitch - dst->w * 4;
csay = say;
/* advance source pointers */
csax++;
- sp += (*csax >> 16);
+ sp = csp + *csax;
/* advance destination pointer */
dp++;
/* advance source pointer */
csay++;
- csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
+ csp = (tColorRGBA *) ((Uint8 *) csp0 + *csay * src->pitch);
/* advance destination pointers */
dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
else
{
/* new source surface is 32 bit with a defined RGB ordering */
- zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
+ zoom_src = SDL_CreateRGBSurface(SURFACE_FLAGS, src->w, src->h, 32,
0x000000ff, 0x0000ff00, 0x00ff0000, 0);
SDL_BlitSurface(src, NULL, zoom_src, NULL);
is_32bit = TRUE;
if (is_32bit)
{
/* target surface is 32 bit with source RGBA/ABGR ordering */
- zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
+ zoom_dst = SDL_CreateRGBSurface(SURFACE_FLAGS, dst_width, dst_height, 32,
zoom_src->format->Rmask,
zoom_src->format->Gmask,
zoom_src->format->Bmask, 0);
else
{
/* target surface is 8 bit */
- zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
+ zoom_dst = SDL_CreateRGBSurface(SURFACE_FLAGS, dst_width, dst_height, 8,
0, 0, 0, 0);
}
return zoom_dst;
}
-void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
+Bitmap *SDLZoomBitmap(Bitmap *src_bitmap, int dst_width, int dst_height)
{
- SDL_Surface *sdl_surface_tmp;
- int dst_width = dst_bitmap->width;
- int dst_height = dst_bitmap->height;
+ Bitmap *dst_bitmap = CreateBitmapStruct();
+ SDL_Surface **dst_surface = &dst_bitmap->surface;
+
+ dst_width = MAX(1, dst_width); /* prevent zero bitmap width */
+ dst_height = MAX(1, dst_height); /* prevent zero bitmap height */
- /* throw away old destination surface */
- SDL_FreeSurface(dst_bitmap->surface);
+ dst_bitmap->width = dst_width;
+ dst_bitmap->height = dst_height;
/* create zoomed temporary surface from source surface */
- sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
+ *dst_surface = zoomSurface(src_bitmap->surface, dst_width, dst_height);
/* create native format destination surface from zoomed temporary surface */
- dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
+ SDLSetNativeSurface(dst_surface);
- /* free temporary surface */
- SDL_FreeSurface(sdl_surface_tmp);
+ return dst_bitmap;
}
Bitmap *new_bitmap = CreateBitmapStruct();
SDL_Surface *sdl_image_tmp;
+ print_timestamp_init("SDLLoadImage");
+
+ print_timestamp_time(getBaseNamePtr(filename));
+
/* load image to temporary surface */
if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
{
SetError("IMG_Load(): %s", SDL_GetError());
+
return NULL;
}
+ print_timestamp_time("IMG_Load");
+
+ UPDATE_BUSY_STATE();
+
/* create native non-transparent surface for current image */
- if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
+ if ((new_bitmap->surface = SDLGetNativeSurface(sdl_image_tmp)) == NULL)
{
SetError("SDL_DisplayFormat(): %s", SDL_GetError());
+
return NULL;
}
+ print_timestamp_time("SDL_DisplayFormat (opaque)");
+
+ UPDATE_BUSY_STATE();
+
/* create native transparent surface for current image */
- SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
- SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
- if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
+ if (sdl_image_tmp->format->Amask == 0)
+ SDL_SetColorKey(sdl_image_tmp, SET_TRANSPARENT_PIXEL,
+ SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
+
+ if ((new_bitmap->surface_masked = SDLGetNativeSurface(sdl_image_tmp)) == NULL)
{
SetError("SDL_DisplayFormat(): %s", SDL_GetError());
+
return NULL;
}
+ print_timestamp_time("SDL_DisplayFormat (masked)");
+
+ UPDATE_BUSY_STATE();
+
/* free temporary surface */
SDL_FreeSurface(sdl_image_tmp);
new_bitmap->width = new_bitmap->surface->w;
new_bitmap->height = new_bitmap->surface->h;
+ print_timestamp_done("SDLLoadImage");
+
return new_bitmap;
}
void SDLOpenAudio(void)
{
+#if !defined(TARGET_SDL2)
if (!strEqual(setup.system.sdl_audiodriver, ARG_DEFAULT))
- putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
+ SDL_putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
+#endif
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
{
void SDLNextEvent(Event *event)
{
SDL_WaitEvent(event);
+}
-#ifdef FULLSCREEN_BUG
- if (event->type == EVENT_BUTTONPRESS ||
- event->type == EVENT_BUTTONRELEASE)
- {
- if (((ButtonEvent *)event)->x > video_xoffset)
- ((ButtonEvent *)event)->x -= video_xoffset;
- else
- ((ButtonEvent *)event)->x = 0;
- if (((ButtonEvent *)event)->y > video_yoffset)
- ((ButtonEvent *)event)->y -= video_yoffset;
- else
- ((ButtonEvent *)event)->y = 0;
- }
- else if (event->type == EVENT_MOTIONNOTIFY)
+void SDLHandleWindowManagerEvent(Event *event)
+{
+#ifdef DEBUG
+#if defined(PLATFORM_WIN32)
+ // experimental drag and drop code
+
+ SDL_SysWMEvent *syswmevent = (SDL_SysWMEvent *)event;
+ SDL_SysWMmsg *syswmmsg = (SDL_SysWMmsg *)(syswmevent->msg);
+
+#if defined(TARGET_SDL2)
+ if (syswmmsg->msg.win.msg == WM_DROPFILES)
+#else
+ if (syswmmsg->msg == WM_DROPFILES)
+#endif
{
- if (((MotionEvent *)event)->x > video_xoffset)
- ((MotionEvent *)event)->x -= video_xoffset;
- else
- ((MotionEvent *)event)->x = 0;
- if (((MotionEvent *)event)->y > video_yoffset)
- ((MotionEvent *)event)->y -= video_yoffset;
- else
- ((MotionEvent *)event)->y = 0;
+#if defined(TARGET_SDL2)
+ HDROP hdrop = (HDROP)syswmmsg->msg.win.wParam;
+#else
+ HDROP hdrop = (HDROP)syswmmsg->wParam;
+#endif
+ int i, num_files;
+
+ printf("::: SDL_SYSWMEVENT:\n");
+
+ num_files = DragQueryFile(hdrop, 0xffffffff, NULL, 0);
+
+ for (i = 0; i < num_files; i++)
+ {
+ int buffer_len = DragQueryFile(hdrop, i, NULL, 0);
+ char buffer[buffer_len + 1];
+
+ DragQueryFile(hdrop, i, buffer, buffer_len + 1);
+
+ printf("::: - '%s'\n", buffer);
+ }
+
+#if defined(TARGET_SDL2)
+ DragFinish((HDROP)syswmmsg->msg.win.wParam);
+#else
+ DragFinish((HDROP)syswmmsg->wParam);
+#endif
}
#endif
+#endif
}
return;
SDL_JoystickClose(sdl_joystick[nr]);
+
+ sdl_joystick[nr] = NULL;
}
static boolean SDLCheckJoystickOpened(int nr)
if (nr < 0 || nr > MAX_PLAYERS)
return FALSE;
+#if defined(TARGET_SDL2)
+ return (sdl_joystick[nr] != NULL ? TRUE : FALSE);
+#else
return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
+#endif
}
void HandleJoystickEvent(Event *event)
{
sdl_joystick_subsystem_initialized = TRUE;
- if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
+ if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
{
Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
return;
return TRUE;
}
-
-#endif /* TARGET_SDL */