X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fsdl.c;h=f02264d9d27ef0fe5a9c997230bf9aecc3bb1379;hb=d6a1a6cb31174ac804f9ad54a919d65478da588f;hp=4c484243934102774e2670d626f967495d87ef53;hpb=59ee473b86e7cbc1d9b09a3c22b0bbd3a410f16f;p=rocksndiamonds.git diff --git a/src/libgame/sdl.c b/src/libgame/sdl.c index 4c484243..f02264d9 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; +static SDL_Renderer *sdl_renderer = NULL; +static SDL_Texture *sdl_texture = NULL; +#endif /* stuff needed to work around SDL/Windows fullscreen drawing bug */ static int fullscreen_width; @@ -35,6 +39,26 @@ 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 UpdateScreen(SDL_Rect *rect) +{ +#if 1 + SDL_Surface *screen = backbuffer->surface; + + SDL_UpdateTexture(sdl_texture, NULL, screen->pixels, screen->pitch); + SDL_RenderClear(sdl_renderer); + SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL); + SDL_RenderPresent(sdl_renderer); +#else + if (rect) + SDL_UpdateWindowSurfaceRects(sdl_window, rect, 1); + else + SDL_UpdateWindowSurface(sdl_window); +#endif +} + static void setFullscreenParameters(char *fullscreen_mode_string) { struct ScreenModeInfo *fullscreen_mode; @@ -85,26 +109,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, @@ -147,8 +192,13 @@ void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window, 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) { @@ -211,15 +261,27 @@ 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 + /* !!! SDL2 can only set the window icon if the window already exists !!! */ + /* 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 @@ -245,8 +307,14 @@ void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window, 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_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 SDL_Surface *new_surface = NULL; if (*backbuffer == NULL) @@ -264,9 +332,25 @@ 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 + UpdateScreen(NULL); // 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()); @@ -293,9 +377,83 @@ 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) + +#if 1 + float scale_factor = 1; + int test_fullscreen = 0; + int surface_flags = (test_fullscreen ? surface_flags_fullscreen : + surface_flags_window); + + sdl_window = SDL_CreateWindow(program.window_title, + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, + (int)(scale_factor * video.width), + (int)(scale_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) + { + new_surface = SDL_CreateRGBSurface(0, video.width, video.height, 32, + 0x00FF0000, + 0x0000FF00, + 0x000000FF, + 0xFF000000); + + 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 + 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 + + if (new_surface == NULL) { /* switching display to window mode failed -- should not happen */ Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError()); @@ -396,8 +554,17 @@ 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); + UpdateScreen(&dst_rect); + } +#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, @@ -419,8 +586,17 @@ 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); + UpdateScreen(&rect); + } +#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, @@ -434,6 +610,9 @@ 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; @@ -462,8 +641,15 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int 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 */ @@ -471,6 +657,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 = @@ -546,7 +733,11 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height, int i; 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); @@ -648,7 +839,13 @@ 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 SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height); +#endif } } } @@ -668,7 +865,12 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height, 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) @@ -676,7 +878,13 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height, #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); +#endif #else SDL_Flip(surface_screen); #endif @@ -1334,12 +1542,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++) @@ -1386,7 +1599,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 && @@ -1425,7 +1641,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; @@ -1675,6 +1893,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) { @@ -1683,6 +1905,8 @@ Bitmap *SDLLoadImage(char *filename) return NULL; } + print_timestamp_time("IMG_Load"); + UPDATE_BUSY_STATE(); /* create native non-transparent surface for current image */ @@ -1693,10 +1917,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) { @@ -1705,6 +1931,8 @@ Bitmap *SDLLoadImage(char *filename) return NULL; } + print_timestamp_time("SDL_DisplayFormat (masked)"); + UPDATE_BUSY_STATE(); /* free temporary surface */ @@ -1713,6 +1941,8 @@ Bitmap *SDLLoadImage(char *filename) new_bitmap->width = new_bitmap->surface->w; new_bitmap->height = new_bitmap->surface->h; + print_timestamp_done("SDLLoadImage"); + return new_bitmap; } @@ -1760,8 +1990,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) { @@ -1886,6 +2118,8 @@ static void SDLCloseJoystick(int nr) return; SDL_JoystickClose(sdl_joystick[nr]); + + sdl_joystick[nr] = NULL; } static boolean SDLCheckJoystickOpened(int nr) @@ -1893,7 +2127,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) @@ -1930,7 +2168,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;