X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Flibgame%2Fsdl.c;h=c7a2b1171561546dd2a9c5f4739283627dd48196;hp=605f2342eed2b6fa162c1a1c86ead1efa5602186;hb=a8816d6e5319f9ec26a45346b08250f61e95c011;hpb=590e9a86daa2b0d3923673bfe02525766224808e diff --git a/src/libgame/sdl.c b/src/libgame/sdl.c index 605f2342..c7a2b117 100644 --- a/src/libgame/sdl.c +++ b/src/libgame/sdl.c @@ -24,8 +24,12 @@ /* video functions */ /* ========================================================================= */ -/* functions from SGE library */ -void sge_Line(SDL_Surface *, Sint16, Sint16, Sint16, Sint16, Uint32); +/* SDL internal variables */ +#if defined(TARGET_SDL2) +static SDL_Window *sdl_window = NULL; +// SDL_Window *sdl_window = NULL; +// static SDL_Renderer *sdl_renderer = NULL; +#endif /* stuff needed to work around SDL/Windows fullscreen drawing bug */ static int fullscreen_width; @@ -35,6 +39,9 @@ static int fullscreen_yoffset; static int video_xoffset; static int video_yoffset; +/* functions from SGE library */ +void sge_Line(SDL_Surface *, Sint16, Sint16, Sint16, Sint16, Uint32); + static void setFullscreenParameters(char *fullscreen_mode_string) { struct ScreenModeInfo *fullscreen_mode; @@ -85,26 +92,47 @@ static void SDLSetWindowIcon(char *basename) } /* set transparent color */ - SDL_SetColorKey(surface, SDL_SRCCOLORKEY, + 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) +SDL_Surface *SDL_DisplayFormat(SDL_Surface *surface) +{ + if (backbuffer == NULL || + backbuffer->surface == NULL) + return NULL; + + return SDL_ConvertSurface(surface, backbuffer->surface->format, 0); } +#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()); /* 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(DrawBuffer **backbuffer, DrawWindow **window, @@ -140,8 +168,20 @@ void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window, fullscreen_xoffset = (fullscreen_width - video.width) / 2; fullscreen_yoffset = (fullscreen_height - video.height) / 2; +#if 1 + checked_free(video.fullscreen_modes); + + video.fullscreen_modes = NULL; + video.fullscreen_mode_current = NULL; +#endif + +#if !defined(TARGET_SDL2) /* get available hardware supported fullscreen modes */ modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE); +#else + // (for now, no display modes in SDL2 -- change this later) + modes = NULL; +#endif if (modes == NULL) { @@ -204,15 +244,26 @@ void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window, } } +#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 + /* set window icon */ + SDLSetWindowIcon(program.sdl_icon_filename); +#endif + /* 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 @@ -228,19 +279,32 @@ 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 } boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen) { boolean success = TRUE; +#if defined(TARGET_SDL2) + int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN; + int surface_flags_window = SURFACE_FLAGS; +#else int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN; int surface_flags_window = SURFACE_FLAGS; +#endif SDL_Surface *new_surface = NULL; if (*backbuffer == NULL) *backbuffer = CreateBitmapStruct(); + /* (real bitmap might be larger in fullscreen mode with video offsets) */ + (*backbuffer)->width = video.width; + (*backbuffer)->height = video.height; + if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available) { setFullscreenParameters(setup.fullscreen_mode); @@ -249,9 +313,24 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen) video_yoffset = fullscreen_yoffset; /* switch display to fullscreen mode, if available */ - if ((new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height, - video.depth, surface_flags_fullscreen)) - == NULL) +#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 + } +#else + new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height, + video.depth, surface_flags_fullscreen); +#endif + + if (new_surface == NULL) { /* switching display to fullscreen mode failed */ Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError()); @@ -278,9 +357,24 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen) video_yoffset = 0; /* switch display to window mode */ - if ((new_surface = SDL_SetVideoMode(video.width, video.height, - video.depth, surface_flags_window)) - == NULL) +#if defined(TARGET_SDL2) + 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 + } +#else + new_surface = SDL_SetVideoMode(video.width, video.height, + video.depth, surface_flags_window); +#endif + + if (new_surface == NULL) { /* switching display to window mode failed -- should not happen */ Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError()); @@ -292,10 +386,30 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen) (*backbuffer)->surface = new_surface; video.fullscreen_enabled = FALSE; + success = TRUE; } } +#if 1 + SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); + +#if defined(PLATFORM_WIN32) + { + SDL_SysWMinfo wminfo; + HWND hwnd; + + SDL_VERSION(&wminfo.version); + SDL_GetWMInfo(&wminfo); + + hwnd = wminfo.window; + + DragAcceptFiles(hwnd, TRUE); + } +#endif +#endif + + return success; } @@ -361,8 +475,16 @@ void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap, src_bitmap->surface_masked : src_bitmap->surface), &src_rect, real_dst_bitmap->surface, &dst_rect); +#if defined(TARGET_SDL2) + if (dst_bitmap == window) + { + // SDL_UpdateWindowSurface(sdl_window); + SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect, 1); + } +#else if (dst_bitmap == window) SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height); +#endif } void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height, @@ -384,8 +506,16 @@ void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height, SDL_FillRect(real_dst_bitmap->surface, &rect, color); +#if defined(TARGET_SDL2) + if (dst_bitmap == window) + { + // SDL_UpdateWindowSurface(sdl_window); + SDL_UpdateWindowSurfaceRects(sdl_window, &rect, 1); + } +#else if (dst_bitmap == window) SDL_UpdateRect(backbuffer->surface, x, y, width, height); +#endif } void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height, @@ -399,11 +529,23 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height, SDL_Surface *surface_screen = backbuffer->surface; SDL_Surface *surface_cross = (bitmap_cross ? bitmap_cross->surface : NULL); SDL_Rect src_rect, dst_rect; +#if defined(TARGET_SDL2) + SDL_Rect dst_rect2; +#endif 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; + + /* check if screen size has changed */ + if (surface_source != NULL && (video.width != surface_source->w || + video.height != surface_source->h)) + { + SDL_FreeSurface(surface_source); + SDL_FreeSurface(surface_target); + SDL_FreeSurface(surface_black); + + initialization_needed = TRUE; + } src_rect.x = src_x; src_rect.y = src_y; @@ -415,11 +557,18 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height, dst_rect.x = dst_x; dst_rect.y = dst_y; - dst_rect.w = width; - dst_rect.h = height; + dst_rect.w = width; /* (ignored) */ + dst_rect.h = height; /* (ignored) */ + +#if defined(TARGET_SDL2) + dst_rect2 = dst_rect; +#endif if (initialization_needed) { +#if defined(TARGET_SDL2) + unsigned int flags = 0; +#else unsigned int flags = SDL_SRCALPHA; /* use same surface type as screen surface */ @@ -427,6 +576,7 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height, flags |= SDL_HWSURFACE; else flags |= SDL_SWSURFACE; +#endif /* create surface for temporary copy of screen buffer (source) */ if ((surface_source = @@ -472,17 +622,17 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height, } /* copy source and target surfaces to temporary surfaces for fading */ - if (fade_mode == FADE_MODE_CROSSFADE) + if (fade_mode & FADE_TYPE_TRANSFORM) { SDL_BlitSurface(surface_cross, &src_rect, surface_source, &src_rect); SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect); } - else if (fade_mode == FADE_MODE_FADE_IN) + 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); } - else /* FADE_MODE_FADE_OUT */ + else /* FADE_TYPE_FADE_OUT */ { SDL_BlitSurface(surface_screen, &dst_rect, surface_source, &src_rect); SDL_BlitSurface(surface_black, &src_rect, surface_target, &src_rect); @@ -490,29 +640,172 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height, time_current = SDL_GetTicks(); - for (alpha = 0.0; alpha < 255.0;) + if (fade_mode == FADE_MODE_MELT) { - time_last = time_current; - time_current = SDL_GetTicks(); - alpha += 255 * ((float)(time_current - time_last) / fade_delay); - alpha_final = MIN(MAX(0, alpha), 255); + 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; - /* draw existing (source) image to screen buffer */ SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect); +#if defined(TARGET_SDL2) + SDL_SetSurfaceBlendMode(surface_target, SDL_BLENDMODE_NONE); +#else + SDL_SetAlpha(surface_target, 0, 0); /* disable alpha blending */ +#endif + + ypos[0] = -GetSimpleRandom(16); - /* draw new (target) image to screen buffer using alpha blending */ - SDL_SetAlpha(surface_target, SDL_SRCALPHA, alpha_final); - SDL_BlitSurface(surface_target, &src_rect, surface_screen, &dst_rect); + 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++; - if (draw_border_function != NULL) - draw_border_function(); + 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(); + +#if defined(TARGET_SDL2) + // SDL_UpdateWindowSurface(sdl_window); + SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect2, 1); +#else + SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height); +#endif + } + } + } + else + { + float alpha; + int alpha_final; + + 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); + + if (draw_border_function != NULL) + draw_border_function(); #if 1 - /* only update the region of the screen that is affected from fading */ - SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height); + /* 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); +#else + SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height); +#endif #else - SDL_Flip(surface_screen); + SDL_Flip(surface_screen); #endif + } } Delay(post_delay); @@ -1166,12 +1459,17 @@ int zoomSurfaceRGBA_scaleDownBy2(SDL_Surface *src, SDL_Surface *dst) { int x, y; tColorRGBA *sp, *csp, *dp; - int sgap, dgap; +#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++) @@ -1218,7 +1516,10 @@ int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst) { int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy; tColorRGBA *sp, *csp, *dp; - int sgap, dgap; +#if 0 + int sgap; +#endif + int dgap; /* use specialized zoom function when scaling down to exactly half size */ if (src->w == 2 * dst->w && @@ -1257,7 +1558,9 @@ int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst) /* 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; csay = say; @@ -1507,6 +1810,10 @@ Bitmap *SDLLoadImage(char *filename) 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) { @@ -1515,6 +1822,10 @@ Bitmap *SDLLoadImage(char *filename) 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) { @@ -1523,8 +1834,12 @@ Bitmap *SDLLoadImage(char *filename) 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_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) { @@ -1533,12 +1848,18 @@ Bitmap *SDLLoadImage(char *filename) 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; } @@ -1586,8 +1907,10 @@ void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info) void SDLOpenAudio(void) { +#if !defined(TARGET_SDL2) if (!strEqual(setup.system.sdl_audiodriver, ARG_DEFAULT)) SDL_putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver)); +#endif if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { @@ -1659,6 +1982,36 @@ void SDLNextEvent(Event *event) } } +void SDLHandleWindowManagerEvent(Event *event) +{ +#if defined(PLATFORM_WIN32) + SDL_SysWMEvent *syswmevent = (SDL_SysWMEvent *)event; + SDL_SysWMmsg *syswmmsg = (SDL_SysWMmsg *)(syswmevent->msg); + + if (syswmmsg->msg == WM_DROPFILES) + { + HDROP hdrop = (HDROP)syswmmsg->wParam; + 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); + } + + DragFinish((HDROP)syswmmsg->wParam); + } +#endif +} + /* ========================================================================= */ /* joystick functions */ @@ -1682,6 +2035,8 @@ static void SDLCloseJoystick(int nr) return; SDL_JoystickClose(sdl_joystick[nr]); + + sdl_joystick[nr] = NULL; } static boolean SDLCheckJoystickOpened(int nr) @@ -1689,7 +2044,11 @@ 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) @@ -1726,7 +2085,7 @@ void SDLInitJoysticks() { 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;