/** * Search video mode size that best suits the given width/height/bpp * constraints and set them into given arguments. With zeroed arguments, * set largest video mode. * * Return true if mode is forced (shouldn't be further limited). */ bool Resolution_Search(int *width, int *height, int *bpp, bool keep) { #ifndef __LIBRETRO__ #if !WITH_SDL2 SDL_Rect **modes; SDL_PixelFormat pixelformat; Uint32 modeflags = 0 /*SDL_HWSURFACE | SDL_HWPALETTE*/; #endif /* Search in available modes the best suited */ DEBUGPRINT(("resolution: video mode asked: %dx%dx%d (%s)\n", *width, *height, *bpp, bInFullScreen ? "fullscreen" : "windowed")); if (bInFullScreen) { /* resolution change not allowed? */ if (keep) { Resolution_GetDesktopSize(width, height); return true; } } if (ConfigureParams.Screen.bForceMax) { /* force given max size */ Resolution_GetMaxSize(width, height); return true; } #if !WITH_SDL2 if (bInFullScreen) modeflags |= SDL_FULLSCREEN; /*--- Search a video mode with asked bpp ---*/ if (*bpp != 0) { pixelformat.BitsPerPixel = *bpp; modes = SDL_ListModes(&pixelformat, modeflags); if ((modes != (SDL_Rect **) 0) && (modes != (SDL_Rect **) -1)) { DEBUGPRINT(("resolution: searching a good video mode (given bpp)\n")); if (Resolution_Select(modes, width, height)) { DEBUGPRINT(("resolution: video mode selected: %dx%dx%d\n", *width, *height, *bpp)); return false; } } } /*--- Search a video mode with any bpp ---*/ modes = SDL_ListModes(NULL, modeflags); if ((modes != (SDL_Rect **) 0) && (modes != (SDL_Rect **) -1)) { DEBUGPRINT(("resolution: searching a good video mode (any bpp)\n")); if (Resolution_Select(modes, width, height)) { DEBUGPRINT(("resolution: video mode selected: %dx%dx%d\n", *width, *height, *bpp)); return false; } } if (modes == (SDL_Rect **) 0) { fprintf(stderr, "WARNING: No suitable video modes available!\n"); } if (modes == (SDL_Rect **) -1) { /* Any mode available */ DEBUGPRINT(("resolution: All resolutions available.\n")); } #endif #else *width = retrow; *height = retroh; *bpp = 2; #endif DEBUGPRINT(("resolution: video mode selected: %dx%dx%d\n", *width, *height, *bpp)); return false; }
void HostScreen_setWindowSize(int width, int height, int bpp) { int screenwidth, screenheight, maxw, maxh; int scalex, scaley, sbarheight; if (bpp == 24) bpp = 32; /* constrain size request to user's desktop size */ Resolution_GetDesktopSize(&maxw, &maxh); scalex = scaley = 1; while (width > maxw*scalex) { scalex *= 2; } while (height > maxh*scalex) { scalex *= 2; } if (scalex * scaley > 1) { fprintf(stderr, "WARNING: too large screen size %dx%d -> divided by %dx%d!\n", width, height, scalex, scaley); width /= scalex; height /= scaley; } Resolution_GetLimits(&maxw, &maxh, &bpp); nScreenZoomX = nScreenZoomY = 1; if (ConfigureParams.Screen.bAspectCorrect) { /* Falcon (and TT) pixel scaling factors seem to 2^x * (quarter/half pixel, interlace/double line), so * do aspect correction as 2's exponent. */ while (nScreenZoomX*width < height && 2*nScreenZoomX*width < maxw) { nScreenZoomX *= 2; } while (2*nScreenZoomY*height < width && 2*nScreenZoomY*height < maxh) { nScreenZoomY *= 2; } if (nScreenZoomX*nScreenZoomY > 2) { fprintf(stderr, "WARNING: strange screen size %dx%d -> aspect corrected by %dx%d!\n", width, height, nScreenZoomX, nScreenZoomY); } } /* then select scale as close to target size as possible * without having larger size than it */ scalex = maxw/(nScreenZoomX*width); scaley = maxh/(nScreenZoomY*height); if (scalex > 1 && scaley > 1) { /* keep aspect ratio */ if (scalex < scaley) { nScreenZoomX *= scalex; nScreenZoomY *= scalex; } else { nScreenZoomX *= scaley; nScreenZoomY *= scaley; } } hs_width_req = width; hs_height_req = height; width *= nScreenZoomX; height *= nScreenZoomY; /* get statusbar size for this screen size */ sbarheight = Statusbar_GetHeightForSize(width, height); screenheight = height + sbarheight; screenwidth = width; /* get resolution corresponding to these */ Resolution_Search(&screenwidth, &screenheight, &bpp); /* re-calculate statusbar height for this resolution */ sbarheight = Statusbar_SetHeight(screenwidth, screenheight-sbarheight); hs_bpp = bpp; /* videl.c might scale things differently in fullscreen than * in windowed mode because this uses screensize instead of using * the aspect scaled sizes directly, but it works better this way. */ hs_width = screenwidth; hs_height = screenheight - sbarheight; if (sdlscrn && (!bpp || sdlscrn->format->BitsPerPixel == bpp) && sdlscrn->w == (signed)screenwidth && sdlscrn->h == (signed)screenheight && (sdlscrn->flags&SDL_FULLSCREEN) == (sdl_videoparams&SDL_FULLSCREEN)) { /* same host screen size despite Atari resolution change, * -> no time consuming host video mode change needed */ if (screenwidth > width || screenheight > height+sbarheight) { /* Atari screen smaller than host -> clear screen */ SDL_Rect rect; rect.x = 0; rect.y = 0; rect.w = sdlscrn->w; rect.h = sdlscrn->h - sbarheight; SDL_FillRect(sdlscrn, &rect, SDL_MapRGB(sdlscrn->format, 0, 0, 0)); /* re-calculate variables in case height + statusbar height * don't anymore match SDL surface size (there's an assert * for that) */ Statusbar_Init(sdlscrn); } // check in case switched from VDI to Hostscreen doUpdate = ( sdlscrn->flags & SDL_HWSURFACE ) == 0; return; } if (bInFullScreen) { /* un-embed the Hatari WM window for fullscreen */ Control_ReparentWindow(screenwidth, screenheight, bInFullScreen); sdl_videoparams = SDL_SWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN; } else { sdl_videoparams = SDL_SWSURFACE|SDL_HWPALETTE; } #ifdef _MUDFLAP if (sdlscrn) { __mf_unregister(sdlscrn->pixels, sdlscrn->pitch*sdlscrn->h, __MF_TYPE_GUESS); } #endif sdlscrn = SDL_SetVideoMode(screenwidth, screenheight, bpp, sdl_videoparams); #ifdef _MUDFLAP __mf_register(sdlscrn->pixels, sdlscrn->pitch*sdlscrn->h, __MF_TYPE_GUESS, "SDL pixels"); #endif if (!bInFullScreen) { /* re-embed the new Hatari SDL window */ Control_ReparentWindow(screenwidth, screenheight, bInFullScreen); } // In case surface format changed, update SDL palette & remap the native palette HostScreen_updatePalette(256); HostScreen_remapPalette(); // redraw statusbar Statusbar_Init(sdlscrn); Dprintf(("Surface Pitch = %d, width = %d, height = %d\n", sdlscrn->pitch, sdlscrn->w, sdlscrn->h)); Dprintf(("Must Lock? %s\n", SDL_MUSTLOCK(sdlscrn) ? "YES" : "NO")); // is the SDL_update needed? doUpdate = ( sdlscrn->flags & SDL_HWSURFACE ) == 0; Dprintf(("Pixel format:bitspp=%d, tmasks r=%04x g=%04x b=%04x" ", tshifts r=%d g=%d b=%d" ", tlosses r=%d g=%d b=%d\n", sdlscrn->format->BitsPerPixel, sdlscrn->format->Rmask, sdlscrn->format->Gmask, sdlscrn->format->Bmask, sdlscrn->format->Rshift, sdlscrn->format->Gshift, sdlscrn->format->Bshift, sdlscrn->format->Rloss, sdlscrn->format->Gloss, sdlscrn->format->Bloss)); Main_WarpMouse(sdlscrn->w/2,sdlscrn->h/2); }
/** * Show and process the window dialog. */ void Dialog_WindowDlg(void) { int deskw, deskh, but, skip = 0; unsigned int i; SDLGui_CenterDlg(windowdlg); /* Set up general window options in the dialog from actual values: */ if (ConfigureParams.Screen.bFullScreen) windowdlg[DLGSCRN_FULLSCRN].state |= SG_SELECTED; else windowdlg[DLGSCRN_FULLSCRN].state &= ~SG_SELECTED; if (ConfigureParams.Screen.bKeepResolution) windowdlg[DLGSCRN_KEEP_RES].state |= SG_SELECTED; else windowdlg[DLGSCRN_KEEP_RES].state &= ~SG_SELECTED; if (ConfigureParams.Screen.bKeepResolutionST) windowdlg[DLGSCRN_KEEP_RES_ST].state |= SG_SELECTED; else windowdlg[DLGSCRN_KEEP_RES_ST].state &= ~SG_SELECTED; windowdlg[DLGSCRN_STATUSBAR].state &= ~SG_SELECTED; windowdlg[DLGSCRN_DRIVELED].state &= ~SG_SELECTED; windowdlg[DLGSCRN_NONE].state &= ~SG_SELECTED; if (ConfigureParams.Screen.bShowStatusbar) windowdlg[DLGSCRN_STATUSBAR].state |= SG_SELECTED; else if (ConfigureParams.Screen.bShowDriveLed) windowdlg[DLGSCRN_DRIVELED].state |= SG_SELECTED; else windowdlg[DLGSCRN_NONE].state |= SG_SELECTED; for (i = 0; i < ITEMS_IN_ARRAY(skip_frames); i++) { if (ConfigureParams.Screen.nFrameSkips >= skip_frames[i]) skip = i; windowdlg[i+DLGSCRN_SKIP0].state &= ~SG_SELECTED; } windowdlg[DLGSCRN_SKIP0+skip].state |= SG_SELECTED; Resolution_GetDesktopSize(&deskw, &deskh); sprintf(sMaxWidth, "%4i", ConfigureParams.Screen.nMaxWidth); sprintf(sMaxHeight, "%4i", ConfigureParams.Screen.nMaxHeight); /* Initialize window capture options: */ if (ConfigureParams.Screen.bCrop) windowdlg[DLGSCRN_CROP].state |= SG_SELECTED; else windowdlg[DLGSCRN_CROP].state &= ~SG_SELECTED; if (Avi_AreWeRecording()) windowdlg[DLGSCRN_RECANIM].txt = RECORD_STOP; else windowdlg[DLGSCRN_RECANIM].txt = RECORD_START; /* The window dialog main loop */ do { but = SDLGui_DoDialog(windowdlg, NULL); switch (but) { case DLGSCRN_MAX_WLESS: ConfigureParams.Screen.nMaxWidth = VDI_Limit(ConfigureParams.Screen.nMaxWidth - MAX_SIZE_STEP, MAX_SIZE_STEP, MIN_VDI_WIDTH, deskw); sprintf(sMaxWidth, "%4i", ConfigureParams.Screen.nMaxWidth); break; case DLGSCRN_MAX_WMORE: ConfigureParams.Screen.nMaxWidth = VDI_Limit(ConfigureParams.Screen.nMaxWidth + MAX_SIZE_STEP, MAX_SIZE_STEP, MIN_VDI_WIDTH, deskw); sprintf(sMaxWidth, "%4i", ConfigureParams.Screen.nMaxWidth); break; case DLGSCRN_MAX_HLESS: ConfigureParams.Screen.nMaxHeight = VDI_Limit(ConfigureParams.Screen.nMaxHeight - MAX_SIZE_STEP, MAX_SIZE_STEP, MIN_VDI_HEIGHT, deskh); sprintf(sMaxHeight, "%4i", ConfigureParams.Screen.nMaxHeight); break; case DLGSCRN_MAX_HMORE: ConfigureParams.Screen.nMaxHeight = VDI_Limit(ConfigureParams.Screen.nMaxHeight + MAX_SIZE_STEP, MAX_SIZE_STEP, MIN_VDI_HEIGHT, deskh); sprintf(sMaxHeight, "%4i", ConfigureParams.Screen.nMaxHeight); break; case DLGSCRN_CAPTURE: SDL_UpdateRect(sdlscrn, 0,0,0,0); ConfigureParams.Screen.bCrop = (windowdlg[DLGSCRN_CROP].state & SG_SELECTED); ScreenSnapShot_SaveScreen(); break; case DLGSCRN_RECANIM: if (Avi_AreWeRecording()) { /* AVI indexing can take a while for larger files */ Statusbar_AddMessage("Finishing AVI file...", 100); Statusbar_Update(sdlscrn, true); Avi_StopRecording(); windowdlg[DLGSCRN_RECANIM].txt = RECORD_START; Statusbar_AddMessage("Emulation paused", 100); Statusbar_Update(sdlscrn, true); } else { ConfigureParams.Screen.bCrop = (windowdlg[DLGSCRN_CROP].state & SG_SELECTED); Avi_StartRecording ( ConfigureParams.Video.AviRecordFile , ConfigureParams.Screen.bCrop , ConfigureParams.Video.AviRecordFps == 0 ? ClocksTimings_GetVBLPerSec ( ConfigureParams.System.nMachineType , nScreenRefreshRate ) : (Uint32)ConfigureParams.Video.AviRecordFps << CLOCKS_TIMINGS_SHIFT_VBL , 1 << CLOCKS_TIMINGS_SHIFT_VBL , ConfigureParams.Video.AviRecordVcodec ); windowdlg[DLGSCRN_RECANIM].txt = RECORD_STOP; } break; } } while (but != DLGSCRN_EXIT_WINDOW && but != SDLGUI_QUIT && but != SDLGUI_ERROR && !bQuitProgram); /* Read new values from dialog: */ ConfigureParams.Screen.bFullScreen = (windowdlg[DLGSCRN_FULLSCRN].state & SG_SELECTED); ConfigureParams.Screen.bKeepResolution = (windowdlg[DLGSCRN_KEEP_RES].state & SG_SELECTED); ConfigureParams.Screen.bKeepResolutionST = (windowdlg[DLGSCRN_KEEP_RES_ST].state & SG_SELECTED); ConfigureParams.Screen.bShowStatusbar = false; ConfigureParams.Screen.bShowDriveLed = false; if (windowdlg[DLGSCRN_STATUSBAR].state & SG_SELECTED) ConfigureParams.Screen.bShowStatusbar = true; else if (windowdlg[DLGSCRN_DRIVELED].state & SG_SELECTED) ConfigureParams.Screen.bShowDriveLed = true; for (i = DLGSCRN_SKIP0; i <= DLGSCRN_SKIP4; i++) { if (windowdlg[i].state & SG_SELECTED) { ConfigureParams.Screen.nFrameSkips = skip_frames[i-DLGSCRN_SKIP0]; break; } } ConfigureParams.Screen.bCrop = (windowdlg[DLGSCRN_CROP].state & SG_SELECTED); }