summaryrefslogtreecommitdiff
path: root/src/i_video.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/i_video.c')
-rw-r--r--src/i_video.c235
1 files changed, 198 insertions, 37 deletions
diff --git a/src/i_video.c b/src/i_video.c
index 8c2cfeac..6bf2f179 100644
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -31,6 +31,11 @@
#include <math.h>
#include <string.h>
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
#include "icon.c"
#include "config.h"
@@ -139,6 +144,12 @@ static SDL_Surface *screen;
static char *window_title = "";
+// Intermediate 8-bit buffer that we draw to instead of 'screen'.
+// This is used when we are rendering in 32-bit screen mode.
+// When in a real 8-bit screen mode, screenbuffer == screen.
+
+static SDL_Surface *screenbuffer = NULL;
+
// palette
static SDL_Color palette[256];
@@ -172,6 +183,10 @@ static boolean native_surface;
static int screen_width = SCREENWIDTH;
static int screen_height = SCREENHEIGHT;
+// Color depth.
+
+int screen_bpp = 8;
+
// Automatically adjust video settings if the selected mode is
// not a valid video mode.
@@ -911,17 +926,18 @@ static boolean BlitArea(int x1, int y1, int x2, int y2)
return true;
}
- x_offset = (screen->w - screen_mode->width) / 2;
- y_offset = (screen->h - screen_mode->height) / 2;
+ x_offset = (screenbuffer->w - screen_mode->width) / 2;
+ y_offset = (screenbuffer->h - screen_mode->height) / 2;
- if (SDL_LockSurface(screen) >= 0)
+ if (SDL_LockSurface(screenbuffer) >= 0)
{
I_InitScale(I_VideoBuffer,
- (byte *) screen->pixels + (y_offset * screen->pitch)
- + x_offset,
- screen->pitch);
+ (byte *) screenbuffer->pixels
+ + (y_offset * screenbuffer->pitch)
+ + x_offset,
+ screenbuffer->pitch);
result = screen_mode->DrawScreen(x1, y1, x2, y2);
- SDL_UnlockSurface(screen);
+ SDL_UnlockSurface(screenbuffer);
}
else
{
@@ -1055,19 +1071,37 @@ void I_FinishUpdate (void)
// draw to screen
BlitArea(0, 0, SCREENWIDTH, SCREENHEIGHT);
-
- // If we have a palette to set, the act of setting the palette
- // updates the screen
if (palette_to_set)
{
- SDL_SetColors(screen, palette, 0, 256);
+ SDL_SetColors(screenbuffer, palette, 0, 256);
palette_to_set = false;
+
+ // In native 8-bit mode, if we have a palette to set, the act
+ // of setting the palette updates the screen
+
+ if (screenbuffer == screen)
+ {
+ return;
+ }
}
- else
+
+ // In 8in32 mode, we must blit from the fake 8-bit screen buffer
+ // to the real screen before doing a screen flip.
+
+ if (screenbuffer != screen)
{
- SDL_Flip(screen);
+ SDL_Rect dst_rect;
+
+ // Center the buffer within the full screen space.
+
+ dst_rect.x = (screen->w - screenbuffer->w) / 2;
+ dst_rect.y = (screen->h - screenbuffer->h) / 2;
+
+ SDL_BlitSurface(screenbuffer, NULL, screen, &dst_rect);
}
+
+ SDL_Flip(screen);
}
@@ -1348,15 +1382,61 @@ static void AutoAdjustWindowed(void)
}
}
+// Auto-adjust to a valid color depth.
+
+static void AutoAdjustColorDepth(void)
+{
+ SDL_Rect **modes;
+ SDL_PixelFormat format;
+ const SDL_VideoInfo *info;
+ int flags;
+
+ if (fullscreen)
+ {
+ flags = SDL_FULLSCREEN;
+ }
+ else
+ {
+ flags = 0;
+ }
+
+ format.BitsPerPixel = screen_bpp;
+ format.BytesPerPixel = (screen_bpp + 7) / 8;
+
+ // Are any screen modes supported at the configured color depth?
+
+ modes = SDL_ListModes(&format, flags);
+
+ // If not, we must autoadjust to something sensible.
+
+ if (modes == NULL)
+ {
+ printf("I_InitGraphics: %ibpp color depth not supported.\n",
+ screen_bpp);
+
+ info = SDL_GetVideoInfo();
+
+ if (info != NULL && info->vfmt != NULL)
+ {
+ screen_bpp = info->vfmt->BitsPerPixel;
+ }
+ }
+}
+
// If the video mode set in the configuration file is not available,
// try to choose a different mode.
static void I_AutoAdjustSettings(void)
{
- int old_screen_w, old_screen_h;
+ int old_screen_w, old_screen_h, old_screen_bpp;
old_screen_w = screen_width;
old_screen_h = screen_height;
+ old_screen_bpp = screen_bpp;
+
+ // Possibly adjust color depth.
+
+ AutoAdjustColorDepth();
// If we are running fullscreen, try to autoadjust to a valid fullscreen
// mode. If this is impossible, switch to windowed.
@@ -1375,10 +1455,11 @@ static void I_AutoAdjustSettings(void)
// Have the settings changed? Show a message.
- if (screen_width != old_screen_w || screen_height != old_screen_h)
+ if (screen_width != old_screen_w || screen_height != old_screen_h
+ || screen_bpp != old_screen_bpp)
{
- printf("I_InitGraphics: Auto-adjusted to %ix%i.\n",
- screen_width, screen_height);
+ printf("I_InitGraphics: Auto-adjusted to %ix%ix%ibpp.\n",
+ screen_width, screen_height, screen_bpp);
printf("NOTE: Your video settings have been adjusted. "
"To disable this behavior,\n"
@@ -1544,7 +1625,7 @@ static void CheckCommandLine(void)
// Specify the screen width, in pixels.
//
- i = M_CheckParm("-width");
+ i = M_CheckParmWithArgs("-width", 1);
if (i > 0)
{
@@ -1558,7 +1639,7 @@ static void CheckCommandLine(void)
// Specify the screen height, in pixels.
//
- i = M_CheckParm("-height");
+ i = M_CheckParmWithArgs("-height", 1);
if (i > 0)
{
@@ -1567,12 +1648,39 @@ static void CheckCommandLine(void)
//!
// @category video
+ // @arg <bpp>
+ //
+ // Specify the color depth of the screen, in bits per pixel.
+ //
+
+ i = M_CheckParmWithArgs("-bpp", 1);
+
+ if (i > 0)
+ {
+ screen_bpp = atoi(myargv[i + 1]);
+ }
+
+ // Because we love Eternity:
+
+ //!
+ // @category video
+ //
+ // Set the color depth of the screen to 32 bits per pixel.
+ //
+
+ if (M_CheckParm("-8in32"))
+ {
+ screen_bpp = 32;
+ }
+
+ //!
+ // @category video
// @arg <WxY>
//
// Specify the screen mode (when running fullscreen) or the window
// dimensions (when running in windowed mode).
- i = M_CheckParm("-geometry");
+ i = M_CheckParmWithArgs("-geometry", 1);
if (i > 0)
{
@@ -1743,6 +1851,14 @@ static void SetVideoMode(screen_mode_t *mode, int w, int h)
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)
@@ -1752,7 +1868,12 @@ static void SetVideoMode(screen_mode_t *mode, int w, int h)
// Set the video mode.
- flags |= SDL_SWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF;
+ flags |= SDL_SWSURFACE | SDL_DOUBLEBUF;
+
+ if (screen_bpp == 8)
+ {
+ flags |= SDL_HWPALETTE;
+ }
if (fullscreen)
{
@@ -1760,18 +1881,30 @@ static void SetVideoMode(screen_mode_t *mode, int w, int h)
}
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
// villsa - center window
SDL_putenv("SDL_VIDEO_CENTERED=1");
}
- screen = SDL_SetVideoMode(w, h, 8, flags);
+ screen = SDL_SetVideoMode(w, h, screen_bpp, flags);
if (screen == NULL)
{
- I_Error("Error setting video mode: %s\n", SDL_GetError());
+ 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.
@@ -1793,6 +1926,22 @@ static void SetVideoMode(screen_mode_t *mode, int w, int h)
}
}
+ // 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;
@@ -1910,24 +2059,13 @@ void I_InitGraphics(void)
// 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);
- }
+ SDL_FillRect(screenbuffer, NULL, 0);
// Set the palette
doompal = W_CacheLumpName(DEH_String("PLAYPAL"), PU_CACHE);
I_SetPalette(doompal);
- SDL_SetColors(screen, palette, 0, 256);
+ SDL_SetColors(screenbuffer, palette, 0, 256);
CreateCursors();
@@ -1949,7 +2087,8 @@ void I_InitGraphics(void)
// 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)
+ native_surface = screen == screenbuffer
+ && !SDL_MUSTLOCK(screen)
&& screen_mode == &mode_scale_1x
&& screen->pitch == SCREENWIDTH
&& aspect_ratio_correct;
@@ -2013,6 +2152,7 @@ void I_BindVideoVariables(void)
M_BindVariable("startup_delay", &startup_delay);
M_BindVariable("screen_width", &screen_width);
M_BindVariable("screen_height", &screen_height);
+ M_BindVariable("screen_bpp", &screen_bpp);
M_BindVariable("grabmouse", &grabmouse);
M_BindVariable("mouse_acceleration", &mouse_acceleration);
M_BindVariable("mouse_threshold", &mouse_threshold);
@@ -2020,5 +2160,26 @@ void I_BindVideoVariables(void)
M_BindVariable("usegamma", &usegamma);
M_BindVariable("vanilla_keyboard_mapping", &vanilla_keyboard_mapping);
M_BindVariable("novert", &novert);
+
+ // Windows Vista or later? Set screen color depth to
+ // 32 bits per pixel, as 8-bit palettized screen modes
+ // don't work properly in recent versions.
+
+#if defined(_WIN32) && !defined(_WIN32_WCE)
+ {
+ OSVERSIONINFOEX version_info;
+
+ ZeroMemory(&version_info, sizeof(OSVERSIONINFOEX));
+ version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+
+ GetVersionEx((OSVERSIONINFO *) &version_info);
+
+ if (version_info.dwPlatformId == VER_PLATFORM_WIN32_NT
+ && version_info.dwMajorVersion >= 6)
+ {
+ screen_bpp = 32;
+ }
+ }
+#endif
}