static void ApplyWindowResize(unsigned int w, unsigned int h) { screen_mode_t *mode; // Find the biggest screen mode that will fall within these // dimensions, falling back to the smallest mode possible if // none is found. mode = I_FindScreenMode(w, h); if (mode == NULL) { mode = I_FindScreenMode(SCREENWIDTH, SCREENHEIGHT); } // Reset mode to resize window. printf("Resize to %ix%i\n", mode->width, mode->height); SetVideoMode(mode, mode->width, mode->height); // Save settings. screen_width = mode->width; screen_height = mode->height; }
static void AutoAdjustWindowed(void) { screen_mode_t *best_mode; // Find a screen_mode_t to fit within the current settings best_mode = I_FindScreenMode(screen_width, screen_height); if (best_mode == NULL) { // Nothing fits within the current settings. // Pick the closest to 320x200 possible. best_mode = I_FindScreenMode(SCREENWIDTH, SCREENHEIGHT_4_3); } // Switch to the best mode if necessary. if (best_mode->width != screen_width || best_mode->height != screen_height) { printf("I_InitGraphics: Cannot run at specified mode: %ix%i\n", screen_width, screen_height); screen_width = best_mode->width; screen_height = best_mode->height; } }
void I_InitGraphics(void) { SDL_Event dummy; byte *doompal; char *env; // Pass through the XSCREENSAVER_WINDOW environment variable to // SDL_WINDOWID, to embed the SDL window into the Xscreensaver // window. env = getenv("XSCREENSAVER_WINDOW"); if (env != NULL) { char winenv[30]; int winid; sscanf(env, "0x%x", &winid); M_snprintf(winenv, sizeof(winenv), "SDL_WINDOWID=%i", winid); putenv(winenv); } SetSDLVideoDriver(); SetWindowPositionVars(); if (SDL_Init(SDL_INIT_VIDEO) < 0) { I_Error("Failed to initialize video: %s", SDL_GetError()); } // Set up title and icon. Windows cares about the ordering; this // has to be done before the call to SDL_SetVideoMode. I_InitWindowTitle(); I_InitWindowIcon(); // Warning to OS X users... though they might never see it :( #ifdef __MACOSX__ if (fullscreen) { printf("Some old versions of OS X might crash in fullscreen mode.\n" "If this happens to you, switch back to windowed mode.\n"); } #endif // // Enter into graphics mode. // // When in screensaver mode, run full screen and auto detect // screen dimensions (don't change video mode) // if (screensaver_mode) { SetVideoMode(NULL, 0, 0); } else { int w, h; if (autoadjust_video_settings) { I_AutoAdjustSettings(); } w = screen_width; h = screen_height; screen_mode = I_FindScreenMode(w, h); if (screen_mode == NULL) { I_Error("I_InitGraphics: Unable to find a screen mode small " "enough for %ix%i", w, h); } if (w != screen_mode->width || h != screen_mode->height) { printf("I_InitGraphics: %s (%ix%i within %ix%i)\n", WindowBoxType(screen_mode, w, h), screen_mode->width, screen_mode->height, w, h); } SetVideoMode(screen_mode, w, h); } // Start with a clear black screen // (screen will be flipped after we set the palette) SDL_FillRect(screenbuffer, NULL, 0); // Set the palette doompal = W_CacheLumpName(DEH_String("PLAYPAL"), PU_CACHE); I_SetPalette(doompal); SDL_SetColors(screenbuffer, palette, 0, 256); CreateCursors(); UpdateFocus(); UpdateGrab(); // On some systems, it takes a second or so for the screen to settle // after changing modes. We include the option to add a delay when // setting the screen mode, so that the game doesn't start immediately // with the player unable to see anything. if (fullscreen && !screensaver_mode) { SDL_Delay(startup_delay); } // Check if we have a native surface we can use // If we have to lock the screen, draw to a buffer and copy // Likewise if the screen pitch is not the same as the width // If we have to multiply, drawing is done to a separate 320x200 buf native_surface = screen == screenbuffer && !SDL_MUSTLOCK(screen) && screen_mode == &mode_scale_1x && screen->pitch == SCREENWIDTH && aspect_ratio_correct; // If not, allocate a buffer and copy from that buffer to the // screen when we do an update if (native_surface) { I_VideoBuffer = (unsigned char *) screen->pixels; I_VideoBuffer += (screen->h - SCREENHEIGHT) / 2; } else { I_VideoBuffer = (unsigned char *) Z_Malloc (SCREENWIDTH * SCREENHEIGHT, PU_STATIC, NULL); } V_RestoreBuffer(); // Clear the screen to black. memset(I_VideoBuffer, 0, SCREENWIDTH * SCREENHEIGHT); // We need SDL to give us translated versions of keys as well SDL_EnableUNICODE(1); // Repeat key presses - this is what Vanilla Doom does // Not sure about repeat rate - probably dependent on which DOS // driver is used. This is good enough though. SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); // clear out any events waiting at the start and center the mouse while (SDL_PollEvent(&dummy)); initialized = true; // Call I_ShutdownGraphics on quit I_AtExit(I_ShutdownGraphics, true); }
static void SetVideoMode(screen_mode_t *mode, int w, int h) { byte *doompal; int flags = 0; doompal = W_CacheLumpName(DEH_String("PLAYPAL"), PU_CACHE); // If we are already running and in a true color mode, we need // to free the screenbuffer surface before setting the new mode. if (screenbuffer != NULL && screen != screenbuffer) { SDL_FreeSurface(screenbuffer); } // Generate lookup tables before setting the video mode. if (mode != NULL && mode->InitMode != NULL) { mode->InitMode(doompal); } // Set the video mode. flags |= SDL_SWSURFACE | SDL_DOUBLEBUF; if (screen_bpp == 8) { flags |= SDL_HWPALETTE; } if (fullscreen) { flags |= SDL_FULLSCREEN; } else { // In windowed mode, the window can be resized while the game is // running. This feature is disabled on OS X, as it adds an ugly // scroll handle to the corner of the screen. #ifndef __MACOSX__ flags |= SDL_RESIZABLE; #endif } screen = SDL_SetVideoMode(w, h, screen_bpp, flags); if (screen == NULL) { I_Error("Error setting video mode %ix%ix%ibpp: %s\n", w, h, screen_bpp, SDL_GetError()); } // Blank out the full screen area in case there is any junk in // the borders that won't otherwise be overwritten. SDL_FillRect(screen, NULL, 0); // If mode was not set, it must be set now that we know the // screen size. if (mode == NULL) { mode = I_FindScreenMode(screen->w, screen->h); if (mode == NULL) { I_Error("I_InitGraphics: Unable to find a screen mode small " "enough for %ix%i", screen->w, screen->h); } // Generate lookup tables before setting the video mode. if (mode->InitMode != NULL) { mode->InitMode(doompal); } } // Create the screenbuffer surface; if we have a real 8-bit palettized // screen, then we can use the screen as the screenbuffer. if (screen->format->BitsPerPixel == 8) { screenbuffer = screen; } else { screenbuffer = SDL_CreateRGBSurface(SDL_SWSURFACE, mode->width, mode->height, 8, 0, 0, 0, 0); SDL_FillRect(screenbuffer, NULL, 0); } // Save screen mode. screen_mode = mode; }
static boolean AutoAdjustFullscreen(void) { SDL_Rect **modes; SDL_Rect *best_mode; screen_mode_t *screen_mode; int diff, best_diff; int i; modes = SDL_ListModes(NULL, SDL_FULLSCREEN); // No fullscreen modes available at all? if (modes == NULL || modes == (SDL_Rect **) -1 || *modes == NULL) { return false; } // Find the best mode that matches the mode specified in the // configuration file best_mode = NULL; best_diff = INT_MAX; for (i=0; modes[i] != NULL; ++i) { //printf("%ix%i?\n", modes[i]->w, modes[i]->h); // What screen_mode_t would be used for this video mode? screen_mode = I_FindScreenMode(modes[i]->w, modes[i]->h); // Never choose a screen mode that we cannot run in, or // is poor quality for fullscreen if (screen_mode == NULL || screen_mode->poor_quality) { // printf("\tUnsupported / poor quality\n"); continue; } // Do we have the exact mode? // If so, no autoadjust needed if (screen_width == modes[i]->w && screen_height == modes[i]->h) { // printf("\tExact mode!\n"); return true; } // Is this mode better than the current mode? diff = (screen_width - modes[i]->w) * (screen_width - modes[i]->w) + (screen_height - modes[i]->h) * (screen_height - modes[i]->h); if (diff < best_diff) { // printf("\tA valid mode\n"); best_mode = modes[i]; best_diff = diff; } } if (best_mode == NULL) { // Unable to find a valid mode! return false; } printf("I_InitGraphics: %ix%i mode not supported on this machine.\n", screen_width, screen_height); screen_width = best_mode->w; screen_height = best_mode->h; return true; }
void I_InitGraphics(void) { SDL_Event dummy; byte *doompal; int flags = 0; char *env; // Pass through the XSCREENSAVER_WINDOW environment variable to // SDL_WINDOWID, to embed the SDL window into the Xscreensaver // window. env = getenv("XSCREENSAVER_WINDOW"); if (env != NULL) { char winenv[30]; int winid; sscanf(env, "0x%x", &winid); sprintf(winenv, "SDL_WINDOWID=%i", winid); putenv(winenv); } SetSDLVideoDriver(); if (SDL_Init(SDL_INIT_VIDEO) < 0) { I_Error("Failed to initialize video: %s", SDL_GetError()); } // Check for command-line video-related parameters. CheckCommandLine(); doompal = W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE); if (screensaver_mode) { windowwidth = 0; windowheight = 0; } else { if (autoadjust_video_settings) { I_AutoAdjustSettings(); } windowwidth = screen_width; windowheight = screen_height; screen_mode = I_FindScreenMode(windowwidth, windowheight); if (screen_mode == NULL) { I_Error("I_InitGraphics: Unable to find a screen mode small " "enough for %ix%i", windowwidth, windowheight); } if (windowwidth != screen_mode->width || windowheight != screen_mode->height) { printf("I_InitGraphics: %s (%ix%i within %ix%i)\n", WindowBoxType(screen_mode, windowwidth, windowheight), screen_mode->width, screen_mode->height, windowwidth, windowheight); } // Generate lookup tables before setting the video mode. if (screen_mode->InitMode != NULL) { screen_mode->InitMode(doompal); } } // Set up title and icon. Windows cares about the ordering; this // has to be done before the call to SDL_SetVideoMode. I_SetWindowCaption(); #if !SDL_VERSION_ATLEAST(1, 3, 0) I_SetWindowIcon(); #endif // Set the video mode. flags |= SDL_SWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF; if (fullscreen) { flags |= SDL_FULLSCREEN; } screen = SDL_SetVideoMode(windowwidth, windowheight, 8, flags); if (screen == NULL) { I_Error("Error setting video mode: %s\n", SDL_GetError()); } // Start with a clear black screen // (screen will be flipped after we set the palette) if (SDL_LockSurface(screen) >= 0) { byte *screenpixels; int y; screenpixels = (byte *) screen->pixels; for (y=0; y<screen->h; ++y) memset(screenpixels + screen->pitch * y, 0, screen->w); SDL_UnlockSurface(screen); } // Set the palette I_SetPalette(doompal); SDL_SetColors(screen, palette, 0, 256); CreateCursors(); UpdateFocus(); UpdateGrab(); // In screensaver mode, now find a screen_mode to use. if (screensaver_mode) { screen_mode = I_FindScreenMode(screen->w, screen->h); if (screen_mode == NULL) { I_Error("I_InitGraphics: Unable to find a screen mode small " "enough for %ix%i", screen->w, screen->h); } // Generate lookup tables before setting the video mode. if (screen_mode->InitMode != NULL) { screen_mode->InitMode(doompal); } } // On some systems, it takes a second or so for the screen to settle // after changing modes. We include the option to add a delay when // setting the screen mode, so that the game doesn't start immediately // with the player unable to see anything. if (fullscreen && !screensaver_mode) { SDL_Delay(startup_delay); } // Check if we have a native surface we can use // If we have to lock the screen, draw to a buffer and copy // Likewise if the screen pitch is not the same as the width // If we have to multiply, drawing is done to a separate 320x200 buf native_surface = !SDL_MUSTLOCK(screen) && screen_mode == &mode_scale_1x && screen->pitch == SCREENWIDTH && aspect_ratio_correct; // If not, allocate a buffer and copy from that buffer to the // screen when we do an update if (native_surface) { screens[0] = (unsigned char *) screen->pixels; screens[0] += (screen->h - SCREENHEIGHT) / 2; } else { screens[0] = (unsigned char *) Z_Malloc (SCREENWIDTH * SCREENHEIGHT, PU_STATIC, NULL); } // "Loading from disk" icon LoadDiskImage(); // Clear the screen to black. memset(screens[0], 0, SCREENWIDTH * SCREENHEIGHT); // We need SDL to give us translated versions of keys as well SDL_EnableUNICODE(1); // Repeat key presses - this is what Vanilla Doom does // Not sure about repeat rate - probably dependent on which DOS // driver is used. This is good enough though. SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); // clear out any events waiting at the start and center the mouse while (SDL_PollEvent(&dummy)); if (usemouse && !nomouse && (fullscreen || grabmouse)) { CenterMouse(); } initialized = true; }
static void SetScaleFactor(int factor) { if (fullscreen) { // In fullscreen, find a mode that will provide this scale factor SDL_Rect **modes; SDL_Rect *best_mode; screen_mode_t *scrmode; int best_num_pixels, num_pixels; int i; modes = SDL_ListModes(NULL, SDL_FULLSCREEN); best_mode = NULL; best_num_pixels = INT_MAX; for (i=0; modes[i] != NULL; ++i) { // What screen_mode_t will this use? scrmode = I_FindScreenMode(modes[i]->w, modes[i]->h); if (scrmode == NULL) { continue; } // Only choose modes that fit the requested scale factor. // // Note that this allows 320x240 as valid for 1x scale, as // 240/200 is rounded down to 1 by integer division. if ((scrmode->width / SCREENWIDTH) != factor || (scrmode->height / SCREENHEIGHT) != factor) { continue; } // Is this a better mode than what we currently have? num_pixels = modes[i]->w * modes[i]->h; if (num_pixels < best_num_pixels) { best_num_pixels = num_pixels; best_mode = modes[i]; } } if (best_mode == NULL) { I_Error("No fullscreen graphics mode available to support " "%ix scale factor!", factor); } screen_width = best_mode->w; screen_height = best_mode->h; } else { int w, h; // Pick 320x200 or 320x240, depending on aspect ratio correct if (aspect_ratio_correct) { w = SCREENWIDTH; h = SCREENHEIGHT_4_3; } else { w = SCREENWIDTH; h = SCREENHEIGHT; } screen_width = w * factor; screen_height = h * factor; } }