X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Flibgame%2Fsdl.c;h=d431aacf29c96c34d73b2a4db489d075608a5640;hp=0b27fafbfec3ad71b4840a2b885d3c96282cc297;hb=0a69f419ffadee5822bc103be9e85d378e0d0274;hpb=2486a7a849210371bb59e733e37b0271a4332d8b diff --git a/src/libgame/sdl.c b/src/libgame/sdl.c index 0b27fafb..d431aacf 100644 --- a/src/libgame/sdl.c +++ b/src/libgame/sdl.c @@ -1,15 +1,13 @@ -/*********************************************************** -* Artsoft Retro-Game Library * -*----------------------------------------------------------* -* (c) 1994-2006 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" @@ -17,8 +15,8 @@ #include "misc.h" #include "setup.h" +#define ENABLE_UNUSED_CODE 0 /* currently unused functions */ -#if defined(TARGET_SDL) /* ========================================================================= */ /* video functions */ @@ -29,6 +27,7 @@ static SDL_Window *sdl_window = NULL; static SDL_Renderer *sdl_renderer = NULL; static SDL_Texture *sdl_texture = NULL; +static boolean fullscreen_enabled = FALSE; #define USE_RENDERER TRUE #endif @@ -55,20 +54,54 @@ static void UpdateScreen(SDL_Rect *rect) { static unsigned int update_screen_delay = 0; unsigned int update_screen_delay_value = 20; /* (milliseconds) */ + SDL_Surface *screen = backbuffer->surface; -#if 1 if (limit_screen_updates && !DelayReached(&update_screen_delay, update_screen_delay_value)) return; 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 USE_FINAL_SCREEN_BITMAP + if (gfx.final_screen_bitmap != NULL) // may not be initialized yet + { + // !!! TEST !!! + // 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); + + // copy global animations to render target buffer, if defined + if (gfx.draw_global_anim_function != NULL) + gfx.draw_global_anim_function(); + + screen = gfx.final_screen_bitmap->surface; + + // force full window redraw + rect = NULL; + } #endif #if defined(TARGET_SDL2) #if USE_RENDERER - SDL_Surface *screen = backbuffer->surface; - -#if 1 if (rect) { int bytes_x = screen->pitch / video.width; @@ -85,13 +118,24 @@ static void UpdateScreen(SDL_Rect *rect) { SDL_UpdateTexture(sdl_texture, NULL, screen->pixels, screen->pitch); } -#else - SDL_UpdateTexture(sdl_texture, NULL, screen->pixels, screen->pitch); -#endif + + // clear render target buffer SDL_RenderClear(sdl_renderer); + + // copy backbuffer to render target buffer SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL); + +#if !USE_FINAL_SCREEN_BITMAP + // copy global animations to render target buffer, if defined + if (gfx.draw_global_anim_function != NULL) + gfx.draw_global_anim_function(); +#endif + + // show render target buffer on screen SDL_RenderPresent(sdl_renderer); + #else + if (rect) SDL_UpdateWindowSurfaceRects(sdl_window, rect, 1); else @@ -100,9 +144,9 @@ static void UpdateScreen(SDL_Rect *rect) #else // TARGET_SDL if (rect) - SDL_UpdateRects(backbuffer->surface, 1, rect); + SDL_UpdateRects(screen, 1, rect); else - SDL_UpdateRect(backbuffer->surface, 0, 0, 0, 0); + SDL_UpdateRect(screen, 0, 0, 0, 0); #endif } @@ -177,16 +221,150 @@ static void SDLSetWindowIcon(char *basename) } #if defined(TARGET_SDL2) -SDL_Surface *SDL_DisplayFormat(SDL_Surface *surface) + +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) { - if (backbuffer == NULL || + 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; + + new_surface = SDL_ConvertSurface(*surface, backbuffer->surface->format, 0); + + 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_Surface *new_surface; + + if (surface == NULL) return NULL; - return SDL_ConvertSurface(surface, backbuffer->surface->format, 0); + if (backbuffer && backbuffer->surface) + new_surface = SDL_ConvertSurface(surface, backbuffer->surface->format, 0); + else + new_surface = SDL_ConvertSurface(surface, 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) @@ -247,12 +425,10 @@ void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window, fullscreen_yoffset = (fullscreen_height - video.height) / 2; #endif -#if 1 checked_free(video.fullscreen_modes); video.fullscreen_modes = NULL; video.fullscreen_mode_current = NULL; -#endif video.window_scaling_percent = setup.window_scaling_percent; video.window_scaling_quality = setup.window_scaling_quality; @@ -369,20 +545,13 @@ void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window, } #endif -#if 0 - /* set window icon */ - SDLSetWindowIcon(program.sdl_icon_filename); -#endif - /* open SDL video output device (window or fullscreen mode) */ if (!SDLSetVideoMode(backbuffer, fullscreen)) Error(ERR_EXIT, "setting video mode failed"); -#if 1 /* !!! SDL2 can only set the window icon if the window already exists !!! */ /* set window icon */ - SDLSetWindowIcon(program.sdl_icon_filename); -#endif + SDLSetWindowIcon(program.icon_filename); /* set window and icon title */ #if defined(TARGET_SDL2) @@ -405,11 +574,7 @@ void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window, should never be drawn to directly, it would do no harm nevertheless. */ /* create additional (symbolic) buffer for double-buffering */ -#if 1 ReCreateBitmap(window, video.width, video.height, video.depth); -#else - *window = CreateBitmap(video.width, video.height, video.depth); -#endif } static SDL_Surface *SDLCreateScreen(DrawBuffer **backbuffer, @@ -418,7 +583,6 @@ static SDL_Surface *SDLCreateScreen(DrawBuffer **backbuffer, SDL_Surface *new_surface = NULL; #if defined(TARGET_SDL2) - static boolean fullscreen_enabled = FALSE; int surface_flags_window = SURFACE_FLAGS | SDL_WINDOW_RESIZABLE; #if USE_DESKTOP_FULLSCREEN int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN_DESKTOP; @@ -442,15 +606,8 @@ static SDL_Surface *SDLCreateScreen(DrawBuffer **backbuffer, #if defined(TARGET_SDL2) - // store if initial screen mode on game start is fullscreen mode - if (sdl_window == NULL) - { -#if 0 - printf("::: GAME STARTS WITH FULLSCREEN %d\n", fullscreen); -#endif - - video.fullscreen_initial = fullscreen; - } + // store if initial screen mode is fullscreen mode when changing screen size + video.fullscreen_initial = fullscreen; #if USE_RENDERER float window_scaling_factor = (float)setup.window_scaling_percent / 100; @@ -461,10 +618,6 @@ static SDL_Surface *SDLCreateScreen(DrawBuffer **backbuffer, video.window_width = window_scaling_factor * width; video.window_height = window_scaling_factor * height; -#if 0 - printf("::: use window scaling factor %f\n", screen_scaling_factor); -#endif - if ((*backbuffer)->surface) { SDL_FreeSurface((*backbuffer)->surface); @@ -492,14 +645,6 @@ static SDL_Surface *SDLCreateScreen(DrawBuffer **backbuffer, } } -#if 0 - Error(ERR_INFO, "::: checking 'sdl_window' ..."); - - if (sdl_window == NULL) - Error(ERR_INFO, "::: calling SDL_CreateWindow() [%d, %d, %d] ...", - setup.fullscreen, fullscreen, fullscreen_enabled); -#endif - if (sdl_window == NULL) sdl_window = SDL_CreateWindow(program.window_title, SDL_WINDOWPOS_CENTERED, @@ -515,8 +660,17 @@ static SDL_Surface *SDLCreateScreen(DrawBuffer **backbuffer, 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) { @@ -531,21 +685,8 @@ static SDL_Surface *SDLCreateScreen(DrawBuffer **backbuffer, if (sdl_texture != NULL) { -#if 1 - // (do not use alpha channel) - new_surface = SDL_CreateRGBSurface(0, width, height, 32, - 0x00FF0000, - 0x0000FF00, - 0x000000FF, - 0x00000000); -#else - // (this uses an alpha channel, which we don't want here) - new_surface = SDL_CreateRGBSurface(0, width, height, 32, - 0x00FF0000, - 0x0000FF00, - 0x000000FF, - 0xFF000000); -#endif + // 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", @@ -597,17 +738,6 @@ static SDL_Surface *SDLCreateScreen(DrawBuffer **backbuffer, boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen) { boolean success = TRUE; -#if 1 -#else -#if defined(TARGET_SDL2) - // int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN; - int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN_DESKTOP; - int surface_flags_window = SURFACE_FLAGS; -#else - int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN; - int surface_flags_window = SURFACE_FLAGS; -#endif -#endif SDL_Surface *new_surface = NULL; SetWindowTitle(); @@ -627,28 +757,7 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen) video_yoffset = fullscreen_yoffset; /* switch display to fullscreen mode, if available */ -#if 1 new_surface = SDLCreateScreen(backbuffer, TRUE); -#else - -#if defined(TARGET_SDL2) - sdl_window = SDL_CreateWindow(program.window_title, - SDL_WINDOWPOS_CENTERED, - SDL_WINDOWPOS_CENTERED, - fullscreen_width, fullscreen_height, - surface_flags_fullscreen); - if (sdl_window != NULL) - { - new_surface = SDL_GetWindowSurface(sdl_window); - - // SDL_UpdateWindowSurface(sdl_window); // immediately map window - // UpdateScreen(NULL); // immediately map window - } -#else - new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height, - video.depth, surface_flags_fullscreen); -#endif -#endif if (new_surface == NULL) { @@ -677,113 +786,7 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen) video_yoffset = 0; /* switch display to window mode */ -#if 1 new_surface = SDLCreateScreen(backbuffer, FALSE); -#else - -#if defined(TARGET_SDL2) - -#if USE_RENDERER - float screen_scaling_factor = 1.2; - int test_fullscreen = 0; - int surface_flags = (test_fullscreen ? surface_flags_fullscreen : - surface_flags_window); - - if ((*backbuffer)->surface) - SDL_FreeSurface((*backbuffer)->surface); - - if (sdl_texture) - SDL_DestroyTexture(sdl_texture); - - if (sdl_renderer) - SDL_DestroyRenderer(sdl_renderer); - - if (sdl_window) - SDL_DestroyWindow(sdl_window); - - sdl_window = SDL_CreateWindow(program.window_title, - SDL_WINDOWPOS_CENTERED, - SDL_WINDOWPOS_CENTERED, - (int)(screen_scaling_factor * video.width), - (int)(screen_scaling_factor * video.height), - surface_flags); - - if (sdl_window != NULL) - { - sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0); - - if (sdl_renderer != NULL) - { - SDL_RenderSetLogicalSize(sdl_renderer, video.width, video.height); - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); - - sdl_texture = SDL_CreateTexture(sdl_renderer, - SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STREAMING, - video.width, video.height); - - if (sdl_texture != NULL) - { -#if 1 - // (do not use alpha channel) - new_surface = SDL_CreateRGBSurface(0, video.width, video.height, 32, - 0x00FF0000, - 0x0000FF00, - 0x000000FF, - 0x00000000); -#else - // (this uses an alpha channel, which we don't want here) - new_surface = SDL_CreateRGBSurface(0, video.width, video.height, 32, - 0x00FF0000, - 0x0000FF00, - 0x000000FF, - 0xFF000000); -#endif - - 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 - - if (sdl_window) - SDL_DestroyWindow(sdl_window); - - sdl_window = SDL_CreateWindow(program.window_title, - SDL_WINDOWPOS_CENTERED, - SDL_WINDOWPOS_CENTERED, - video.width, video.height, - surface_flags_window); - - if (sdl_window != NULL) - { - new_surface = SDL_GetWindowSurface(sdl_window); - - // SDL_UpdateWindowSurface(sdl_window); // immediately map window - // UpdateScreen(NULL); // immediately map window - } -#endif - -#else - new_surface = SDL_SetVideoMode(video.width, video.height, - video.depth, surface_flags_window); -#endif -#endif if (new_surface == NULL) { @@ -806,13 +809,14 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen) #if defined(TARGET_SDL2) SDLRedrawWindow(); // map window - // UpdateScreen(NULL); // map window #endif -#if 1 +#ifdef DEBUG +#if defined(PLATFORM_WIN32) + // experimental drag and drop code + SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); -#if defined(PLATFORM_WIN32) { SDL_SysWMinfo wminfo; HWND hwnd; @@ -862,10 +866,6 @@ void SDLSetWindowScaling(int window_scaling_percent) int new_window_width = (int)(window_scaling_factor * video.width); int new_window_height = (int)(window_scaling_factor * video.height); -#if 0 - Error(ERR_DEBUG, "::: SDLSetWindowScaling(%d) ...", window_scaling_percent); -#endif - SDL_SetWindowSize(sdl_window, new_window_width, new_window_height); video.window_scaling_percent = window_scaling_percent; @@ -910,20 +910,10 @@ void SDLSetWindowFullscreen(boolean fullscreen) int flags = (fullscreen ? SDL_WINDOW_FULLSCREEN : 0); #endif -#if 0 - Error(ERR_DEBUG, "::: SDL_SetWindowFullscreen(%d) ...", fullscreen); -#endif - if (SDL_SetWindowFullscreen(sdl_window, flags) == 0) - video.fullscreen_enabled = fullscreen; - -#if 0 - printf("::: SDLSetWindowFullscreen: %d, %d\n", - fullscreen, video.fullscreen_initial); -#endif + video.fullscreen_enabled = fullscreen_enabled = fullscreen; -#if 1 - // if game started in fullscreen mode, window will also get fullscreen size + // if screen size was changed in fullscreen mode, correct desktop window size if (!fullscreen && video.fullscreen_initial) { SDLSetWindowScaling(setup.window_scaling_percent); @@ -932,7 +922,6 @@ void SDLSetWindowFullscreen(boolean fullscreen) video.fullscreen_initial = FALSE; } -#endif } void SDLRedrawWindow() @@ -941,22 +930,18 @@ void SDLRedrawWindow() } #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) @@ -965,8 +950,19 @@ 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, @@ -1020,6 +1016,37 @@ void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap, #endif } +void SDLBlitTexture(Bitmap *bitmap, + int src_x, int src_y, int width, int height, + int dst_x, int dst_y, int mask_mode) +{ +#if defined(TARGET_SDL2) +#if USE_RENDERER + SDL_Texture *texture; + SDL_Rect src_rect; + SDL_Rect dst_rect; + + 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 +#endif +} + void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height, Uint32 color) { @@ -1291,18 +1318,69 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height, if (draw_border_function != NULL) draw_border_function(); -#if defined(TARGET_SDL2) - // SDL_UpdateWindowSurface(sdl_window); - // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect2, 1); 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 - // SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height); - UpdateScreen(&dst_rect2); + SDL_SetAlpha(surface_source, 0, 0); /* disable alpha blending */ #endif + + 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; + + 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 + else /* fading in, fading out or cross-fading */ { float alpha; int alpha_final; @@ -1329,23 +1407,29 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height, if (draw_border_function != NULL) draw_border_function(); -#if 1 /* only update the region of the screen that is affected from fading */ -#if defined(TARGET_SDL2) - // SDL_UpdateWindowSurface(sdl_window); - // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect, 1); UpdateScreen(&dst_rect); -#else - // SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height); - UpdateScreen(&dst_rect); -#endif -#else - SDL_Flip(surface_screen); -#endif } } - Delay(post_delay); + if (post_delay > 0) + { + unsigned int time_post_delay; + + time_current = SDL_GetTicks(); + time_post_delay = time_current + post_delay; + + 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)); + + // ... continue drawing global animations during post delay + UpdateScreen(NULL); + + time_current = SDL_GetTicks(); + } + } } void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y, @@ -1388,7 +1472,7 @@ void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y, 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) { @@ -1473,7 +1557,7 @@ Pixel SDLGetPixel(Bitmap *src_bitmap, int x, int y) /* ========================================================================= */ /* 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 */ /* ========================================================================= */ @@ -1996,17 +2080,11 @@ int zoomSurfaceRGBA_scaleDownBy2(SDL_Surface *src, SDL_Surface *dst) { int x, y; tColorRGBA *sp, *csp, *dp; -#if 0 - int sgap; -#endif int dgap; /* pointer setup */ sp = csp = (tColorRGBA *) src->pixels; dp = (tColorRGBA *) dst->pixels; -#if 0 - sgap = src->pitch - src->w * 4; -#endif dgap = dst->pitch - dst->w * 4; for (y = 0; y < dst->h; y++) @@ -2051,11 +2129,9 @@ int zoomSurfaceRGBA_scaleDownBy2(SDL_Surface *src, SDL_Surface *dst) int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst) { - int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy; - tColorRGBA *sp, *csp, *dp; -#if 0 - int sgap; -#endif + 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 */ @@ -2064,40 +2140,23 @@ int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst) 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; -#if 0 - sgap = src->pitch - src->w * 4; -#endif dgap = dst->pitch - dst->w * 4; csay = say; @@ -2113,7 +2172,7 @@ int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst) /* advance source pointers */ csax++; - sp += (*csax >> 16); + sp = csp + *csax; /* advance destination pointer */ dp++; @@ -2121,7 +2180,7 @@ int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst) /* 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); @@ -2263,7 +2322,7 @@ SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height) 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; @@ -2274,7 +2333,7 @@ SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height) 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); @@ -2282,7 +2341,7 @@ SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height) 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); } @@ -2318,23 +2377,24 @@ SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height) 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; } @@ -2364,7 +2424,7 @@ Bitmap *SDLLoadImage(char *filename) 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()); @@ -2378,7 +2438,8 @@ Bitmap *SDLLoadImage(char *filename) /* create native transparent surface for current image */ SDL_SetColorKey(sdl_image_tmp, SET_TRANSPARENT_PIXEL, SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00)); - if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL) + + if ((new_bitmap->surface_masked = SDLGetNativeSurface(sdl_image_tmp)) == NULL) { SetError("SDL_DisplayFormat(): %s", SDL_GetError()); @@ -2521,7 +2582,10 @@ void SDLNextEvent(Event *event) 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); @@ -2559,6 +2623,7 @@ void SDLHandleWindowManagerEvent(Event *event) #endif } #endif +#endif } @@ -2697,5 +2762,3 @@ boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2) return TRUE; } - -#endif /* TARGET_SDL */