DOSBox-X
|
00001 #include <sys/types.h> 00002 #include <assert.h> 00003 #include <math.h> 00004 00005 #include "dosbox.h" 00006 #include "sdlmain.h" 00007 #include "vga.h" 00008 00009 #include <algorithm> // std::transform 00010 00011 using namespace std; 00012 00013 #if defined(C_SDL2) 00014 Bitu OUTPUT_SURFACE_SetSize() 00015 { 00016 Bitu bpp = 0; 00017 Bitu retFlags = 0; 00018 (void)bpp; 00019 00020 SDL_SetWindowMinimumSize(sdl.window, 1, 1); /* NTS: 0 x 0 is not valid */ 00021 00022 sdl.clip.w = sdl.draw.width; 00023 sdl.clip.h = sdl.draw.height; 00024 if (GFX_IsFullscreen()) { 00025 if (sdl.desktop.full.fixed) { 00026 sdl.clip.x = (Sint16)((sdl.desktop.full.width - sdl.draw.width) / 2); 00027 sdl.clip.y = (Sint16)((sdl.desktop.full.height - sdl.draw.height) / 2); 00028 sdl.window = GFX_SetSDLWindowMode(sdl.desktop.full.width, sdl.desktop.full.height, SCREEN_SURFACE); 00029 if (sdl.window == NULL) 00030 E_Exit("Could not set fullscreen video mode %ix%i-%i: %s", sdl.desktop.full.width, sdl.desktop.full.height, sdl.desktop.bpp, SDL_GetError()); 00031 } 00032 else { 00033 sdl.clip.x = 0; 00034 sdl.clip.y = 0; 00035 sdl.window = GFX_SetSDLWindowMode(sdl.draw.width, sdl.draw.height, SCREEN_SURFACE); 00036 if (sdl.window == NULL) 00037 LOG_MSG("Fullscreen not supported: %s", SDL_GetError()); 00038 GFX_CaptureMouse(); 00039 } 00040 } 00041 else { 00042 int width = sdl.draw.width; 00043 int height = sdl.draw.height; 00044 int menuheight = 0; 00045 00046 sdl.clip.x = 0; sdl.clip.y = 0; 00047 00048 #if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW 00049 /* scale the menu bar if the window is large enough */ 00050 { 00051 Bitu consider_height = menu.maxwindow ? currentWindowHeight : height; 00052 Bitu consider_width = menu.maxwindow ? currentWindowWidth : width; 00053 Bitu final_height = max(max(consider_height, userResizeWindowHeight), (Bitu)(sdl.clip.y + sdl.clip.h)); 00054 Bitu final_width = max(max(consider_width, userResizeWindowWidth), (Bitu)(sdl.clip.x + sdl.clip.w)); 00055 Bitu scale = 1; 00056 00057 while ((final_width / scale) >= (640 * 2) && (final_height / scale) >= (400 * 2)) 00058 scale++; 00059 00060 LOG_MSG("menuScale=%lu", (unsigned long)scale); 00061 mainMenu.setScale(scale); 00062 } 00063 00064 if (mainMenu.isVisible()) menuheight = mainMenu.menuBox.h; 00065 #endif 00066 00067 /* menu size and consideration of width and height */ 00068 Bitu consider_height = height + (unsigned int)menuheight + (sdl.overscan_width * 2); 00069 Bitu consider_width = width + (sdl.overscan_width * 2); 00070 00071 if (menu.maxwindow) { 00072 if (consider_height < currentWindowHeight) 00073 consider_height = currentWindowHeight; 00074 if (consider_width < currentWindowWidth) 00075 consider_width = currentWindowWidth; 00076 } 00077 00078 #if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW 00079 if (mainMenu.isVisible()) 00080 { 00081 extern unsigned int min_sdldraw_menu_width; 00082 extern unsigned int min_sdldraw_menu_height; 00083 /* enforce a minimum 500x300 surface size. 00084 * the menus are useless below 500x300 */ 00085 if (consider_width < (min_sdldraw_menu_width + (sdl.overscan_width * 2))) 00086 consider_width = (min_sdldraw_menu_width + (sdl.overscan_width * 2)); 00087 if (consider_height < (min_sdldraw_menu_height + (sdl.overscan_width * 2) + (unsigned int)menuheight)) 00088 consider_height = (min_sdldraw_menu_height + (sdl.overscan_width * 2) + (unsigned int)menuheight); 00089 } 00090 #endif 00091 00092 /* decide where the rectangle on the screen goes */ 00093 int final_width,final_height; 00094 00095 #if C_XBRZ 00096 /* scale to fit the window. 00097 * fit by aspect ratio if asked to do so. */ 00098 if (sdl_xbrz.enable) 00099 { 00100 final_height = (int)max(consider_height, userResizeWindowHeight) - (int)menuheight - ((int)sdl.overscan_width * 2); 00101 final_width = (int)max(consider_width, userResizeWindowWidth) - ((int)sdl.overscan_width * 2); 00102 00103 sdl.clip.x = sdl.clip.y = 0; 00104 sdl.clip.w = final_width; 00105 sdl.clip.h = final_height; 00106 if (render.aspect) aspectCorrectFitClip(sdl.clip.w, sdl.clip.h, sdl.clip.x, sdl.clip.y, final_width, final_height); 00107 } 00108 else 00109 #endif 00110 /* center the screen in the window */ 00111 { 00112 00113 final_height = (int)max(max(consider_height, userResizeWindowHeight), (Bitu)(sdl.clip.y + sdl.clip.h)) - (int)menuheight - ((int)sdl.overscan_width * 2); 00114 final_width = (int)max(max(consider_width, userResizeWindowWidth), (Bitu)(sdl.clip.x + sdl.clip.w)) - ((int)sdl.overscan_width * 2); 00115 int ax = (final_width - (sdl.clip.x + sdl.clip.w)) / 2; 00116 int ay = (final_height - (sdl.clip.y + sdl.clip.h)) / 2; 00117 if (ax < 0) ax = 0; 00118 if (ay < 0) ay = 0; 00119 sdl.clip.x += ax + (int)sdl.overscan_width; 00120 sdl.clip.y += ay + (int)sdl.overscan_width; 00121 // sdl.clip.w = currentWindowWidth - sdl.clip.x; 00122 // sdl.clip.h = currentWindowHeight - sdl.clip.y; 00123 } 00124 00125 { 00126 final_width += (int)sdl.overscan_width * 2; 00127 final_height += (int)menuheight + (int)sdl.overscan_width * 2; 00128 sdl.clip.y += (int)menuheight; 00129 00130 LOG_MSG("surface consider=%ux%u final=%ux%u", 00131 (unsigned int)consider_width, 00132 (unsigned int)consider_height, 00133 (unsigned int)final_width, 00134 (unsigned int)final_height); 00135 } 00136 00137 sdl.window = GFX_SetSDLWindowMode(final_width, final_height, SCREEN_SURFACE); 00138 if (sdl.window == NULL) 00139 E_Exit("Could not set windowed video mode %ix%i: %s", (int)sdl.draw.width, (int)sdl.draw.height, SDL_GetError()); 00140 00141 sdl.surface = SDL_GetWindowSurface(sdl.window); 00142 if (sdl.surface->w < (sdl.clip.x+sdl.clip.w) || 00143 sdl.surface->h < (sdl.clip.y+sdl.clip.h)) { 00144 /* the window surface must not be smaller than the size we want! 00145 * This is a way to prevent that! */ 00146 SDL_SetWindowMinimumSize(sdl.window, sdl.clip.x+sdl.clip.w, sdl.clip.y+sdl.clip.h); 00147 sdl.window = GFX_SetSDLWindowMode(sdl.clip.x+sdl.clip.w, sdl.clip.y+sdl.clip.h, SCREEN_SURFACE); 00148 } 00149 } 00150 sdl.surface = SDL_GetWindowSurface(sdl.window); 00151 if (sdl.surface == NULL) 00152 E_Exit("Could not retrieve window surface: %s", SDL_GetError()); 00153 switch (sdl.surface->format->BitsPerPixel) { 00154 case 8: 00155 retFlags = GFX_CAN_8; 00156 break; 00157 case 15: 00158 retFlags = GFX_CAN_15; 00159 break; 00160 case 16: 00161 retFlags = GFX_CAN_16; 00162 break; 00163 case 32: 00164 retFlags = GFX_CAN_32; 00165 break; 00166 } 00167 00168 #if C_XBRZ 00169 if (sdl_xbrz.enable) 00170 { 00171 bool old_scale_on = sdl_xbrz.scale_on; 00172 xBRZ_SetScaleParameters(sdl.draw.width, sdl.draw.height, sdl.clip.w, sdl.clip.h); 00173 if (sdl_xbrz.scale_on != old_scale_on) { 00174 // when we are scaling, we ask render code not to do any aspect correction 00175 // when we are not scaling, render code is allowed to do aspect correction at will 00176 // due to this, at each scale mode change we need to schedule resize again because window size could change 00177 PIC_AddEvent(VGA_SetupDrawing, 50); // schedule another resize here, render has already been initialized at this point and we have just changed its option 00178 } 00179 } 00180 #endif 00181 00182 /* WARNING: If the user is resizing our window to smaller than what we want, SDL2 will give us a 00183 * window surface according to the smaller size, and then we crash! */ 00184 assert(sdl.surface->w >= (sdl.clip.x+sdl.clip.w)); 00185 assert(sdl.surface->h >= (sdl.clip.y+sdl.clip.h)); 00186 00187 sdl.deferred_resize = false; 00188 sdl.must_redraw_all = true; 00189 00190 /* Fix a glitch with aspect=true occuring when 00191 changing between modes with different dimensions */ 00192 SDL_FillRect(sdl.surface, NULL, SDL_MapRGB(sdl.surface->format, 0, 0, 0)); 00193 #if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW 00194 mainMenu.screenWidth = sdl.surface->w; 00195 mainMenu.screenHeight = sdl.surface->h; 00196 mainMenu.updateRect(); 00197 mainMenu.setRedraw(); 00198 GFX_DrawSDLMenu(mainMenu, mainMenu.display_list); 00199 #endif 00200 00201 return retFlags; 00202 } 00203 #endif /*defined(C_SDL2)*/