X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fsdl.c;h=e275149fea202b723e4348394568394fc294f0d7;hb=f1dae0af49fa331f6fedc6cbdf59eed0909ae391;hp=7a108238cbe56c5a4279f61f61bd0198d7c924aa;hpb=97d0f78c43d16fbf73ea0438148a4da781c75600;p=rocksndiamonds.git diff --git a/src/libgame/sdl.c b/src/libgame/sdl.c index 7a108238..e275149f 100644 --- a/src/libgame/sdl.c +++ b/src/libgame/sdl.c @@ -37,6 +37,11 @@ static boolean limit_screen_updates = FALSE; /* functions from SGE library */ void sge_Line(SDL_Surface *, Sint16, Sint16, Sint16, Sint16, Uint32); +#if defined(USE_TOUCH_INPUT_OVERLAY) +/* functions to draw overlay graphics for touch device input */ +static void DrawTouchInputOverlay(); +#endif + void SDLLimitScreenUpdates(boolean enable) { limit_screen_updates = enable; @@ -129,9 +134,18 @@ static void UpdateScreenExt(SDL_Rect *rect, boolean with_frame_delay) SDL_UpdateTexture(sdl_texture, NULL, screen->pixels, screen->pitch); } + int xoff = video.screen_xoffset; + int yoff = video.screen_yoffset; + SDL_Rect dst_rect_screen = { xoff, yoff, video.width, video.height }; SDL_Rect *src_rect1 = NULL, *dst_rect1 = NULL; SDL_Rect *src_rect2 = NULL, *dst_rect2 = NULL; + if (video.screen_rendering_mode == SPECIAL_RENDERING_TARGET || + video.screen_rendering_mode == SPECIAL_RENDERING_DOUBLE) + dst_rect2 = &dst_rect_screen; + else + dst_rect1 = &dst_rect_screen; + #if defined(HAS_SCREEN_KEYBOARD) if (video.shifted_up || video.shifted_up_delay) { @@ -153,8 +167,8 @@ static void UpdateScreenExt(SDL_Rect *rect, boolean with_frame_delay) video.shifted_up_delay = 0; } - SDL_Rect src_rect_up = { 0, pos, video.width, video.height - pos }; - SDL_Rect dst_rect_up = { 0, 0, video.width, video.height - pos }; + SDL_Rect src_rect_up = { 0, pos, video.width, video.height - pos }; + SDL_Rect dst_rect_up = { xoff, yoff, video.width, video.height - pos }; if (video.screen_rendering_mode == SPECIAL_RENDERING_TARGET || video.screen_rendering_mode == SPECIAL_RENDERING_DOUBLE) @@ -192,6 +206,12 @@ static void UpdateScreenExt(SDL_Rect *rect, boolean with_frame_delay) SDL_SetRenderTarget(sdl_renderer, NULL); SDL_RenderCopy(sdl_renderer, sdl_texture_target, src_rect2, dst_rect2); } + +#if defined(USE_TOUCH_INPUT_OVERLAY) + // draw overlay graphics for touch device input, if needed + DrawTouchInputOverlay(); +#endif + #endif // global synchronization point of the game to align video frame delay @@ -419,6 +439,9 @@ boolean SDLSetNativeSurface(SDL_Surface **surface) #if defined(TARGET_SDL2) static SDL_Texture *SDLCreateTextureFromSurface(SDL_Surface *surface) { + if (program.headless) + return NULL; + SDL_Texture *texture = SDL_CreateTextureFromSurface(sdl_renderer, surface); if (texture == NULL) @@ -482,8 +505,11 @@ void SDLInitVideoDisplay(void) #endif } -void SDLInitVideoBuffer(boolean fullscreen) +inline static void SDLInitVideoBuffer_VideoBuffer(boolean fullscreen) { + if (program.headless) + return; + video.window_scaling_percent = setup.window_scaling_percent; video.window_scaling_quality = setup.window_scaling_quality; @@ -511,7 +537,10 @@ void SDLInitVideoBuffer(boolean fullscreen) #else SDL_WM_SetCaption(program.window_title, program.window_title); #endif +} +inline static void SDLInitVideoBuffer_DrawBuffer() +{ /* SDL cannot directly draw to the visible video framebuffer like X11, but always uses a backbuffer, which is then blitted to the visible video framebuffer with 'SDL_UpdateRect' (or replaced with the current @@ -527,6 +556,16 @@ void SDLInitVideoBuffer(boolean fullscreen) /* create additional (symbolic) buffer for double-buffering */ ReCreateBitmap(&window, video.width, video.height); + + /* create dummy drawing buffer for headless mode, if needed */ + if (program.headless) + ReCreateBitmap(&backbuffer, video.width, video.height); +} + +void SDLInitVideoBuffer(boolean fullscreen) +{ + SDLInitVideoBuffer_VideoBuffer(fullscreen); + SDLInitVideoBuffer_DrawBuffer(); } static boolean SDLCreateScreen(boolean fullscreen) @@ -551,16 +590,20 @@ static boolean SDLCreateScreen(boolean fullscreen) it will try to use accelerated graphics and apparently fails miserably) */ int renderer_flags = SDL_RENDERER_SOFTWARE; #endif + + SDLSetScreenSizeAndOffsets(video.width, video.height); #endif int width = video.width; int height = video.height; + int screen_width = video.screen_width; + int screen_height = video.screen_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; + video.window_width = screen_width; + video.window_height = screen_height; #if defined(TARGET_SDL2) @@ -569,8 +612,8 @@ static boolean SDLCreateScreen(boolean 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; + video.window_width = window_scaling_factor * screen_width; + video.window_height = window_scaling_factor * screen_height; if (sdl_texture_stream) { @@ -614,7 +657,7 @@ static boolean SDLCreateScreen(boolean fullscreen) if (sdl_renderer != NULL) { - SDL_RenderSetLogicalSize(sdl_renderer, width, height); + SDL_RenderSetLogicalSize(sdl_renderer, screen_width, screen_height); // SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, setup.window_scaling_quality); @@ -800,8 +843,8 @@ void SDLSetWindowScaling(int window_scaling_percent) 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); + int new_window_width = (int)(window_scaling_factor * video.screen_width); + int new_window_height = (int)(window_scaling_factor * video.screen_height); SDL_SetWindowSize(sdl_window, new_window_width, new_window_height); @@ -873,6 +916,67 @@ void SDLSetWindowFullscreen(boolean fullscreen) video.fullscreen_initial = FALSE; } } + +void SDLSetDisplaySize() +{ + SDL_Rect display_bounds; + + SDL_GetDisplayBounds(0, &display_bounds); + + video.display_width = display_bounds.w; + video.display_height = display_bounds.h; + +#if 0 + Error(ERR_DEBUG, "SDL real screen size: %d x %d", + video.display_width, video.display_height); +#endif +} + +void SDLSetScreenSizeAndOffsets(int width, int height) +{ + // set default video screen size and offsets + video.screen_width = width; + video.screen_height = height; + video.screen_xoffset = 0; + video.screen_yoffset = 0; + +#if defined(USE_COMPLETE_DISPLAY) + float ratio_video = (float) width / height; + float ratio_display = (float) video.display_width / video.display_height; + + if (ratio_video != ratio_display) + { + // adjust drawable screen size to cover the whole device display + + if (ratio_video < ratio_display) + video.screen_width *= ratio_display / ratio_video; + else + video.screen_height *= ratio_video / ratio_display; + + video.screen_xoffset = (video.screen_width - width) / 2; + video.screen_yoffset = (video.screen_height - height) / 2; + +#if 0 + Error(ERR_DEBUG, "Changing screen from %dx%d to %dx%d (%.2f to %.2f)", + width, height, + video.screen_width, video.screen_height, + ratio_video, ratio_display); +#endif + } +#endif +} + +void SDLSetScreenSizeForRenderer(int width, int height) +{ + SDL_RenderSetLogicalSize(sdl_renderer, width, height); +} + +void SDLSetScreenProperties() +{ + SDLSetScreenSizeAndOffsets(video.width, video.height); + SDLSetScreenSizeForRenderer(video.screen_width, video.screen_height); +} + #endif void SDLSetScreenRenderingMode(char *screen_rendering_mode) @@ -898,6 +1002,9 @@ void SDLRedrawWindow() void SDLCreateBitmapContent(Bitmap *bitmap, int width, int height, int depth) { + if (program.headless) + return; + SDL_Surface *surface = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth, 0,0,0, 0); @@ -2282,6 +2389,14 @@ Bitmap *SDLLoadImage(char *filename) Bitmap *new_bitmap = CreateBitmapStruct(); SDL_Surface *sdl_image_tmp; + if (program.headless) + { + /* prevent sanity check warnings at later stage */ + new_bitmap->width = new_bitmap->height = 1; + + return new_bitmap; + } + print_timestamp_init("SDLLoadImage"); print_timestamp_time(getBaseNamePtr(filename)); @@ -2371,6 +2486,9 @@ void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info) void SDLOpenAudio(void) { + if (program.headless) + return; + #if !defined(TARGET_SDL2) if (!strEqual(setup.system.sdl_audiodriver, ARG_DEFAULT)) SDL_putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver)); @@ -2604,3 +2722,98 @@ boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2) return TRUE; } + +#if defined(USE_TOUCH_INPUT_OVERLAY) +static void DrawTouchInputOverlay() +{ + static SDL_Texture *texture = NULL; + static boolean initialized = FALSE; + static boolean deactivated = TRUE; + static int width = 0, height = 0; + static int alpha_max = SDL_ALPHA_OPAQUE / 2; + static int alpha_step = 5; + static int alpha_last = 0; + static int alpha = 0; + + if (!overlay.active && deactivated) + return; + + if (overlay.active) + { + if (alpha < alpha_max) + alpha = MIN(alpha + alpha_step, alpha_max); + + deactivated = FALSE; + } + else + { + alpha = MAX(0, alpha - alpha_step); + + if (alpha == 0) + deactivated = TRUE; + } + + if (!initialized) + { + char *basename = "overlay/VirtualButtons.png"; + char *filename = getCustomImageFilename(basename); + + if (filename == NULL) + Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename); + + SDL_Surface *surface; + + if ((surface = IMG_Load(filename)) == NULL) + Error(ERR_EXIT, "IMG_Load() failed: %s", SDL_GetError()); + + width = surface->w; + height = surface->h; + + /* set black pixel to transparent if no alpha channel / transparent color */ + if (!SDLHasAlpha(surface) && + !SDLHasColorKey(surface)) + SDL_SetColorKey(surface, SET_TRANSPARENT_PIXEL, + SDL_MapRGB(surface->format, 0x00, 0x00, 0x00)); + + if ((texture = SDLCreateTextureFromSurface(surface)) == NULL) + Error(ERR_EXIT, "SDLCreateTextureFromSurface() failed"); + + SDL_FreeSurface(surface); + + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); + SDL_SetTextureAlphaMod(texture, alpha_max); + + initialized = TRUE; + } + + if (alpha != alpha_last) + SDL_SetTextureAlphaMod(texture, alpha); + + alpha_last = alpha; + + float ratio_overlay = (float) width / height; + float ratio_screen = (float) video.screen_width / video.screen_height; + int width_scaled, height_scaled; + int xpos, ypos; + + if (ratio_overlay > ratio_screen) + { + width_scaled = video.screen_width; + height_scaled = video.screen_height * ratio_screen / ratio_overlay; + xpos = 0; + ypos = video.screen_height - height_scaled; + } + else + { + width_scaled = video.screen_width * ratio_overlay / ratio_screen; + height_scaled = video.screen_height; + xpos = (video.screen_width - width_scaled) / 2; + ypos = 0; + } + + SDL_Rect src_rect = { 0, 0, width, height }; + SDL_Rect dst_rect = { xpos, ypos, width_scaled, height_scaled }; + + SDL_RenderCopy(sdl_renderer, texture, &src_rect, &dst_rect); +} +#endif