From ecddae3859018ea01887528f3248f03a138be6c3 Mon Sep 17 00:00:00 2001 From: havoc Date: Thu, 14 Feb 2008 17:38:09 +0000 Subject: [PATCH] implemented vid_samples cvar (antialiasing samples per pixel) oh and for the record, Windows multisample buffer setup is awful. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@8090 d7cf8633-e32d-0410-b094-e92efae38249 --- menu.c | 148 +++++++++++++------------ vid.h | 4 +- vid_agl.c | 18 ++- vid_glx.c | 13 ++- vid_null.c | 2 +- vid_sdl.c | 13 ++- vid_shared.c | 47 +++++--- vid_wgl.c | 305 ++++++++++++++++++++++++++++++++++++++------------- 8 files changed, 373 insertions(+), 177 deletions(-) diff --git a/menu.c b/menu.c index 61fc2532..afae9ad2 100644 --- a/menu.c +++ b/menu.c @@ -2795,7 +2795,7 @@ video_resolution_t video_resolutions[] = #define VIDEO_ITEMS 11 static int video_cursor = 0; -static int video_cursor_table[VIDEO_ITEMS] = {56, 68, 88, 100, 108, 116, 136, 166, 174, 182, 190}; +static int video_cursor_table[VIDEO_ITEMS] = {68, 88, 96, 104, 112, 120, 128, 136, 144, 152, 168}; static int video_resolution; void M_Menu_Video_f (void) @@ -2842,6 +2842,7 @@ void M_Menu_Video_f (void) static void M_Video_Draw (void) { + int t; cachepic_t *p; M_Background(320, 200); @@ -2850,49 +2851,64 @@ static void M_Video_Draw (void) p = Draw_CachePic ("gfx/vidmodes"); M_DrawPic((320-p->width)/2, 4, "gfx/vidmodes"); - // Current Resolution - M_Print(16, video_cursor_table[0], " Current Resolution"); + t = 0; + + // Current and Proposed Resolution + M_Print(16, video_cursor_table[t] - 12, " Current Resolution"); if (vid_supportrefreshrate && vid.userefreshrate && vid.fullscreen) - M_Print(220, video_cursor_table[0], va("%dx%d %dhz", vid.width, vid.height, vid.refreshrate)); + M_Print(220, video_cursor_table[t] - 12, va("%dx%d %dhz", vid.width, vid.height, vid.refreshrate)); else - M_Print(220, video_cursor_table[0], va("%dx%d", vid.width, vid.height)); + M_Print(220, video_cursor_table[t] - 12, va("%dx%d", vid.width, vid.height)); + M_Print(16, video_cursor_table[t], " New Resolution"); + M_Print(220, video_cursor_table[t], va("%dx%d", video_resolutions[video_resolution].width, video_resolutions[video_resolution].height)); + M_Print(96, video_cursor_table[t] + 8, va("Type: %s", video_resolutions[video_resolution].type)); + t++; - // Proposed Resolution - M_Print(16, video_cursor_table[1], " New Resolution"); - M_Print(220, video_cursor_table[1], va("%dx%d", video_resolutions[video_resolution].width, video_resolutions[video_resolution].height)); - M_Print(96, video_cursor_table[1] + 8, va("Type: %s", video_resolutions[video_resolution].type)); + // Bits per pixel + M_Print(16, video_cursor_table[t], " Bits per pixel"); + M_Print(220, video_cursor_table[t], (vid_bitsperpixel.integer == 32) ? "32" : "16"); + t++; // Bits per pixel - M_Print(16, video_cursor_table[2], " Bits per pixel"); - M_Print(220, video_cursor_table[2], (vid_bitsperpixel.integer == 32) ? "32" : "16"); + M_Print(16, video_cursor_table[t], " Antialiasing"); + M_DrawSlider(220, video_cursor_table[t], vid_samples.value, 1, 32); + t++; // Refresh Rate - M_ItemPrint(16, video_cursor_table[3], " Use Refresh Rate", vid_supportrefreshrate); - M_DrawCheckbox(220, video_cursor_table[3], vid_userefreshrate.integer); + M_ItemPrint(16, video_cursor_table[t], " Use Refresh Rate", vid_supportrefreshrate); + M_DrawCheckbox(220, video_cursor_table[t], vid_userefreshrate.integer); + t++; // Refresh Rate - M_ItemPrint(16, video_cursor_table[4], " Refresh Rate", vid_supportrefreshrate && vid_userefreshrate.integer); - M_DrawSlider(220, video_cursor_table[4], vid_refreshrate.integer, 60, 150); + M_ItemPrint(16, video_cursor_table[t], " Refresh Rate", vid_supportrefreshrate && vid_userefreshrate.integer); + M_DrawSlider(220, video_cursor_table[t], vid_refreshrate.integer, 60, 150); + t++; // Fullscreen - M_Print(16, video_cursor_table[5], " Fullscreen"); - M_DrawCheckbox(220, video_cursor_table[5], vid_fullscreen.integer); - - // "Apply" button - M_Print(220, video_cursor_table[6], "Apply"); + M_Print(16, video_cursor_table[t], " Fullscreen"); + M_DrawCheckbox(220, video_cursor_table[t], vid_fullscreen.integer); + t++; // Vertical Sync - M_ItemPrint(16, video_cursor_table[7], " Vertical Sync", gl_videosyncavailable); - M_DrawCheckbox(220, video_cursor_table[7], vid_vsync.integer); + M_ItemPrint(16, video_cursor_table[t], " Vertical Sync", gl_videosyncavailable); + M_DrawCheckbox(220, video_cursor_table[t], vid_vsync.integer); + t++; - M_ItemPrint(16, video_cursor_table[8], " Anisotropic Filter", gl_support_anisotropy); - M_DrawSlider(220, video_cursor_table[8], gl_texture_anisotropy.integer, 1, gl_max_anisotropy); + M_ItemPrint(16, video_cursor_table[t], " Anisotropic Filter", gl_support_anisotropy); + M_DrawSlider(220, video_cursor_table[t], gl_texture_anisotropy.integer, 1, gl_max_anisotropy); + t++; - M_ItemPrint(16, video_cursor_table[9], " Texture Quality", true); - M_DrawSlider(220, video_cursor_table[9], gl_picmip.value, 3, 0); + M_ItemPrint(16, video_cursor_table[t], " Texture Quality", true); + M_DrawSlider(220, video_cursor_table[t], gl_picmip.value, 3, 0); + t++; - M_ItemPrint(16, video_cursor_table[10], " Texture Compression", gl_support_texture_compression); - M_DrawCheckbox(220, video_cursor_table[10], gl_texturecompression.integer); + M_ItemPrint(16, video_cursor_table[t], " Texture Compression", gl_support_texture_compression); + M_DrawCheckbox(220, video_cursor_table[t], gl_texturecompression.integer); + t++; + + // "Apply" button + M_Print(220, video_cursor_table[t], "Apply"); + t++; // Cursor M_DrawCharacter(200, video_cursor_table[video_cursor], 12+((int)(realtime*4)&1)); @@ -2901,55 +2917,44 @@ static void M_Video_Draw (void) static void M_Menu_Video_AdjustSliders (int dir) { + int t; + S_LocalSound ("sound/misc/menu3.wav"); - switch (video_cursor) + t = 0; + if (video_cursor == t++) { // Resolution - case 1: + int r; + for(r = 0;r < VID_RES_COUNT;r++) { - int r; - for(r = 0;r < VID_RES_COUNT;r++) - { - video_resolution += dir; - if (video_resolution >= VID_RES_COUNT) - video_resolution = 0; - if (video_resolution < 0) - video_resolution = VID_RES_COUNT - 1; - if (video_resolutions[video_resolution].width >= vid_minwidth.integer && video_resolutions[video_resolution].height >= vid_minheight.integer) - break; - } - break; + video_resolution += dir; + if (video_resolution >= VID_RES_COUNT) + video_resolution = 0; + if (video_resolution < 0) + video_resolution = VID_RES_COUNT - 1; + if (video_resolutions[video_resolution].width >= vid_minwidth.integer && video_resolutions[video_resolution].height >= vid_minheight.integer) + break; } - - // Bits per pixel - case 2: - Cvar_SetValueQuick (&vid_bitsperpixel, (vid_bitsperpixel.integer == 32) ? 16 : 32); - break; - // Refresh Rate - case 3: - Cvar_SetValueQuick (&vid_userefreshrate, !vid_userefreshrate.integer); - break; - case 4: - Cvar_SetValueQuick (&vid_refreshrate, bound(60, vid_refreshrate.integer + dir, 150)); - break; - case 5: - Cvar_SetValueQuick (&vid_fullscreen, !vid_fullscreen.integer); - break; - - case 7: - Cvar_SetValueQuick (&vid_vsync, !vid_vsync.integer); - break; - case 8: - Cvar_SetValueQuick (&gl_texture_anisotropy, bound(1, gl_texture_anisotropy.value * (dir < 0 ? 0.5 : 2.0), gl_max_anisotropy)); - break; - case 9: - Cvar_SetValueQuick (&gl_picmip, bound(0, gl_picmip.value - dir, 3)); - break; - case 10: - Cvar_SetValueQuick (&gl_texturecompression, !gl_texturecompression.integer); - break; } + else if (video_cursor == t++) + Cvar_SetValueQuick (&vid_bitsperpixel, (vid_bitsperpixel.integer == 32) ? 16 : 32); + else if (video_cursor == t++) + Cvar_SetValueQuick (&vid_samples, bound(1, vid_samples.value * (dir > 0 ? 2 : 0.5), 32)); + else if (video_cursor == t++) + Cvar_SetValueQuick (&vid_userefreshrate, !vid_userefreshrate.integer); + else if (video_cursor == t++) + Cvar_SetValueQuick (&vid_refreshrate, bound(60, vid_refreshrate.integer + dir, 150)); + else if (video_cursor == t++) + Cvar_SetValueQuick (&vid_fullscreen, !vid_fullscreen.integer); + else if (video_cursor == t++) + Cvar_SetValueQuick (&vid_vsync, !vid_vsync.integer); + else if (video_cursor == t++) + Cvar_SetValueQuick (&gl_texture_anisotropy, bound(1, gl_texture_anisotropy.value * (dir < 0 ? 0.5 : 2.0), gl_max_anisotropy)); + else if (video_cursor == t++) + Cvar_SetValueQuick (&gl_picmip, bound(0, gl_picmip.value - dir, 3)); + else if (video_cursor == t++) + Cvar_SetValueQuick (&gl_texturecompression, !gl_texturecompression.integer); } @@ -2961,6 +2966,7 @@ static void M_Video_Key (int key, char ascii) // vid_shared.c has a copy of the current video config. We restore it Cvar_SetValueQuick(&vid_fullscreen, vid.fullscreen); Cvar_SetValueQuick(&vid_bitsperpixel, vid.bitsperpixel); + Cvar_SetValueQuick(&vid_samples, vid.samples); if (vid_supportrefreshrate) Cvar_SetValueQuick(&vid_refreshrate, vid.refreshrate); Cvar_SetValueQuick(&vid_userefreshrate, vid.userefreshrate); @@ -2973,7 +2979,7 @@ static void M_Video_Key (int key, char ascii) m_entersound = true; switch (video_cursor) { - case 6: + case (VIDEO_ITEMS - 1): Cvar_SetValueQuick (&vid_width, video_resolutions[video_resolution].width); Cvar_SetValueQuick (&vid_height, video_resolutions[video_resolution].height); Cvar_SetValueQuick (&vid_conwidth, video_resolutions[video_resolution].conwidth); diff --git a/vid.h b/vid.h index aac4edc3..f80ac780 100644 --- a/vid.h +++ b/vid.h @@ -36,6 +36,7 @@ typedef struct viddef_s int refreshrate; qboolean userefreshrate; int stereobuffer; + int samples; } viddef_t; // global video state @@ -53,6 +54,7 @@ extern cvar_t vid_fullscreen; extern cvar_t vid_width; extern cvar_t vid_height; extern cvar_t vid_bitsperpixel; +extern cvar_t vid_samples; extern cvar_t vid_refreshrate; extern cvar_t vid_userefreshrate; extern cvar_t vid_vsync; @@ -125,7 +127,7 @@ int VID_SetMode (int modenum); // sets the mode; only used by the Quake engine for resetting to mode 0 (the // base mode) on memory allocation failures -int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer); +int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer, int samples); // allocates and opens an appropriate OpenGL context (and its window) diff --git a/vid_agl.c b/vid_agl.c index 1bf5995b..2cf7194b 100644 --- a/vid_agl.c +++ b/vid_agl.c @@ -499,7 +499,7 @@ static void VID_ProcessPendingAsyncEvents (void) Sys_Quit(0); } -static void VID_BuildAGLAttrib(GLint *attrib, qboolean stencil, qboolean fullscreen, qboolean stereobuffer) +static void VID_BuildAGLAttrib(GLint *attrib, qboolean stencil, qboolean fullscreen, qboolean stereobuffer, int samples) { *attrib++ = AGL_RGBA; *attrib++ = AGL_RED_SIZE;*attrib++ = 1; @@ -518,10 +518,22 @@ static void VID_BuildAGLAttrib(GLint *attrib, qboolean stencil, qboolean fullscr *attrib++ = AGL_FULLSCREEN; if (stereobuffer) *attrib++ = AGL_STEREO; +#ifdef AGL_SAMPLE_BUFFERS_ARB +#ifdef AGL_SAMPLES_ARB + if (samples > 1) + { + *attrib++ = AGL_SAMPLE_BUFFERS_ARB; + *attrib++ = 1; + *attrib++ = AGL_SAMPLES_ARB; + *attrib++ = samples; + } +#endif +#endif + *attrib++ = AGL_NONE; } -int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer) +int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer, int samples) { const EventTypeSpec winEvents[] = { @@ -592,7 +604,7 @@ int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate GetEventTypeCount(winEvents), winEvents, window, NULL); // Create the desired attribute list - VID_BuildAGLAttrib(attributes, bpp == 32, fullscreen, stereobuffer); + VID_BuildAGLAttrib(attributes, bpp == 32, fullscreen, stereobuffer, samples); if (!fullscreen) { diff --git a/vid_glx.c b/vid_glx.c index ad52b4a0..ff985108 100644 --- a/vid_glx.c +++ b/vid_glx.c @@ -613,7 +613,7 @@ void VID_Init(void) mouse_avail = false; } -void VID_BuildGLXAttrib(int *attrib, qboolean stencil, qboolean stereobuffer) +void VID_BuildGLXAttrib(int *attrib, qboolean stencil, qboolean stereobuffer, int samples) { *attrib++ = GLX_RGBA; *attrib++ = GLX_RED_SIZE;*attrib++ = 1; @@ -629,10 +629,17 @@ void VID_BuildGLXAttrib(int *attrib, qboolean stencil, qboolean stereobuffer) } if (stereobuffer) *attrib++ = GLX_STEREO; + if (samples) + { + *attrib++ = GLX_SAMPLE_BUFFERS_ARB; + *attrib++ = 1; + *attrib++ = GLX_SAMPLES_ARB; + *attrib++ = samples; + } *attrib++ = None; } -int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer) +int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer, int samples) { int i; int attrib[32]; @@ -693,7 +700,7 @@ int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate return false; } - VID_BuildGLXAttrib(attrib, bpp == 32, stereobuffer); + VID_BuildGLXAttrib(attrib, bpp == 32, stereobuffer, samples); visinfo = qglXChooseVisual(vidx11_display, vidx11_screen, attrib); if (!visinfo) { diff --git a/vid_null.c b/vid_null.c index 48755028..a7c18f97 100644 --- a/vid_null.c +++ b/vid_null.c @@ -70,7 +70,7 @@ void VID_Init(void) InitSig(); // trap evil signals } -int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer) +int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer, int samples) { return false; } diff --git a/vid_sdl.c b/vid_sdl.c index 3902899c..bb3b2239 100644 --- a/vid_sdl.c +++ b/vid_sdl.c @@ -491,9 +491,15 @@ static void VID_SetCaption() icon = LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDI_ICON1 ) ); #ifndef _W64 //If Windows 64bit data types don't exist +#ifndef SetClassLongPtr #define SetClassLongPtr SetClassLong +#endif +#ifndef GCLP_HICON #define GCLP_HICON GCL_HICON +#endif +#ifndef LONG_PTR #define LONG_PTR LONG +#endif #endif SetClassLongPtr( info.window, GCLP_HICON, (LONG_PTR)icon ); } @@ -623,7 +629,7 @@ static void VID_OutputVersion() version->major, version->minor, version->patch ); } -int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer) +int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer, int samples) { int i; static int notfirstvideomode = false; @@ -699,6 +705,11 @@ int VID_InitMode(int fullscreen, int width, int height, int bpp, int refreshrate SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1); else SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 0); + if (samples > 1) + { + SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, 1); + SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, samples); + } video_bpp = bpp; video_flags = flags; diff --git a/vid_shared.c b/vid_shared.c index c864fb99..280b1116 100644 --- a/vid_shared.c +++ b/vid_shared.c @@ -82,6 +82,7 @@ cvar_t vid_fullscreen = {CVAR_SAVE, "vid_fullscreen", "1", "use fullscreen (1) o cvar_t vid_width = {CVAR_SAVE, "vid_width", "640", "resolution"}; cvar_t vid_height = {CVAR_SAVE, "vid_height", "480", "resolution"}; cvar_t vid_bitsperpixel = {CVAR_SAVE, "vid_bitsperpixel", "32", "how many bits per pixel to render at (32 or 16, 32 is recommended)"}; +cvar_t vid_samples = {CVAR_SAVE, "vid_samples", "1", "how many anti-aliasing samples per pixel to request from the graphics driver (4 is recommended, 1 is faster)"}; cvar_t vid_refreshrate = {CVAR_SAVE, "vid_refreshrate", "60", "refresh rate to use, in hz (higher values flicker less, if supported by your monitor)"}; cvar_t vid_userefreshrate = {CVAR_SAVE, "vid_userefreshrate", "0", "set this to 1 to make vid_refreshrate used, or to 0 to let the engine choose a sane default"}; cvar_t vid_stereobuffer = {CVAR_SAVE, "vid_stereobuffer", "0", "enables 'quad-buffered' stereo rendering for stereo shutterglasses, HMD (head mounted display) devices, or polarized stereo LCDs, if supported by your drivers"}; @@ -1045,6 +1046,7 @@ void VID_Shared_Init(void) Cvar_RegisterVariable(&vid_width); Cvar_RegisterVariable(&vid_height); Cvar_RegisterVariable(&vid_bitsperpixel); + Cvar_RegisterVariable(&vid_samples); Cvar_RegisterVariable(&vid_refreshrate); Cvar_RegisterVariable(&vid_userefreshrate); Cvar_RegisterVariable(&vid_stereobuffer); @@ -1063,16 +1065,17 @@ void VID_Shared_Init(void) Cvar_Set("gl_combine", "0"); } -int VID_Mode(int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer) +int VID_Mode(int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer, int samples) { cl_ignoremousemoves = 2; - Con_Printf("Initialized Video Mode: %s %dx%dx%dx%dhz%s\n", fullscreen ? "fullscreen" : "window", width, height, bpp, refreshrate, stereobuffer ? " stereo" : ""); - if (VID_InitMode(fullscreen, width, height, bpp, vid_userefreshrate.integer ? max(1, refreshrate) : 0, stereobuffer)) + Con_Printf("Initialized Video Mode: %s %dx%dx%dx%dhz%s%s\n", fullscreen ? "fullscreen" : "window", width, height, bpp, refreshrate, stereobuffer ? " stereo" : "", samples > 1 ? va("(%ix AA)", samples) : ""); + if (VID_InitMode(fullscreen, width, height, bpp, vid_userefreshrate.integer ? max(1, refreshrate) : 0, stereobuffer, samples)) { vid.fullscreen = fullscreen; vid.width = width; vid.height = height; vid.bitsperpixel = bpp; + vid.samples = samples; vid.refreshrate = refreshrate; vid.stereobuffer = stereobuffer; vid.userefreshrate = vid_userefreshrate.integer; @@ -1080,6 +1083,7 @@ int VID_Mode(int fullscreen, int width, int height, int bpp, int refreshrate, in Cvar_SetValueQuick(&vid_width, width); Cvar_SetValueQuick(&vid_height, height); Cvar_SetValueQuick(&vid_bitsperpixel, bpp); + Cvar_SetValueQuick(&vid_samples, samples); if(vid_userefreshrate.integer) Cvar_SetValueQuick(&vid_refreshrate, refreshrate); Cvar_SetValueQuick(&vid_stereobuffer, stereobuffer); @@ -1109,20 +1113,31 @@ void VID_Restart_f(void) if (vid_commandlinecheck) return; - Con_Printf("VID_Restart: changing from %s %dx%dx%dbpp, to %s %dx%dx%dbpp.\n", - vid.fullscreen ? "fullscreen" : "window", vid.width, vid.height, vid.bitsperpixel, - vid_fullscreen.integer ? "fullscreen" : "window", vid_width.integer, vid_height.integer, vid_bitsperpixel.integer); + Con_Printf("VID_Restart: changing from %s %dx%dx%dbpp%s%s, to %s %dx%dx%dbpp%s%s.\n", + vid.fullscreen ? "fullscreen" : "window", vid.width, vid.height, vid.bitsperpixel, vid.fullscreen && vid_userefreshrate.integer ? va("x%ihz", vid.refreshrate) : "", vid.samples > 1 ? va(" (%ix AA)", vid.samples) : "", + vid_fullscreen.integer ? "fullscreen" : "window", vid_width.integer, vid_height.integer, vid_bitsperpixel.integer, vid_fullscreen.integer && vid_userefreshrate.integer ? va("x%ihz", vid_refreshrate.integer) : "", vid_samples.integer > 1 ? va(" (%ix AA)", vid_samples.integer) : ""); VID_CloseSystems(); VID_Shutdown(); - if (!VID_Mode(vid_fullscreen.integer, vid_width.integer, vid_height.integer, vid_bitsperpixel.integer, vid_refreshrate.integer, vid_stereobuffer.integer)) + if (!VID_Mode(vid_fullscreen.integer, vid_width.integer, vid_height.integer, vid_bitsperpixel.integer, vid_refreshrate.integer, vid_stereobuffer.integer, vid_samples.integer)) { Con_Print("Video mode change failed\n"); - if (!VID_Mode(vid.fullscreen, vid.width, vid.height, vid.bitsperpixel, vid.refreshrate, vid.stereobuffer)) + if (!VID_Mode(vid.fullscreen, vid.width, vid.height, vid.bitsperpixel, vid.refreshrate, vid.stereobuffer, vid.samples)) Sys_Error("Unable to restore to last working video mode"); } VID_OpenSystems(); } +const char *vidfallbacks[][2] = +{ + {"vid_stereobuffer", "0"}, + {"vid_samples", "1"}, + {"vid_userefreshrate", "0"}, + {"vid_width", "640"}, + {"vid_height", "480"}, + {"vid_bitsperpixel", "16"}, + {NULL, NULL} +}; + // this is only called once by Host_StartVideo void VID_Start(void) { @@ -1158,19 +1173,15 @@ void VID_Start(void) Cvar_SetQuick(&vid_bitsperpixel, com_argv[i+1]); } - success = VID_Mode(vid_fullscreen.integer, vid_width.integer, vid_height.integer, vid_bitsperpixel.integer, vid_refreshrate.integer, vid_stereobuffer.integer); + success = VID_Mode(vid_fullscreen.integer, vid_width.integer, vid_height.integer, vid_bitsperpixel.integer, vid_refreshrate.integer, vid_stereobuffer.integer, vid_samples.integer); if (!success) { Con_Print("Desired video mode fail, trying fallbacks...\n"); - success = VID_Mode(vid_fullscreen.integer, vid_width.integer, vid_height.integer, vid_bitsperpixel.integer, 60, vid_stereobuffer.integer); - if (!success && vid_stereobuffer.integer) - success = VID_Mode(vid_fullscreen.integer, vid_width.integer, vid_height.integer, vid_bitsperpixel.integer, vid_refreshrate.integer, false); - if (!success && vid_bitsperpixel.integer > 16) - success = VID_Mode(vid_fullscreen.integer, vid_width.integer, vid_height.integer, 16, 60, false); - if (!success && (vid_width.integer > 640 || vid_height.integer > 480)) - success = VID_Mode(vid_fullscreen.integer, 640, 480, 16, 60, false); - if (!success && vid_fullscreen.integer) - success = VID_Mode(false, 640, 480, 16, 60, false); + for (i = 0;!success && vidfallbacks[i][0] != NULL;i++) + { + Cvar_Set(vidfallbacks[i][0], vidfallbacks[i][1]); + success = VID_Mode(vid_fullscreen.integer, vid_width.integer, vid_height.integer, vid_bitsperpixel.integer, vid_refreshrate.integer, vid_stereobuffer.integer, vid_samples.integer); + } if (!success) Sys_Error("Video modes failed"); } diff --git a/vid_wgl.c b/vid_wgl.c index d8097591..88cc6814 100644 --- a/vid_wgl.c +++ b/vid_wgl.c @@ -55,6 +55,8 @@ static PROC (WINAPI *qwglGetProcAddress)(LPCSTR); static BOOL (WINAPI *qwglMakeCurrent)(HDC, HGLRC); static BOOL (WINAPI *qwglSwapIntervalEXT)(int interval); static const char *(WINAPI *qwglGetExtensionsStringARB)(HDC hdc); +static BOOL (WINAPI *qwglChoosePixelFormatARB)(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +static BOOL (WINAPI *qwglGetPixelFormatAttribivARB)(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); static dllfunction_t wglfuncs[] = { @@ -78,6 +80,13 @@ static dllfunction_t wglswapintervalfuncs[] = {NULL, NULL} }; +static dllfunction_t wglpixelformatfuncs[] = +{ + {"wglChoosePixelFormatARB", (void **) &qwglChoosePixelFormatARB}, + {"wglGetPixelFormatAttribivARB", (void **) &qwglGetPixelFormatAttribivARB}, + {NULL, NULL} +}; + static DEVMODE gdevmode, initialdevmode; static qboolean vid_initialized = false; static qboolean vid_wassuspended = false; @@ -521,7 +530,7 @@ LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_SYSCOMMAND: // prevent screensaver from occuring while the active window - if (fActive && ((wParam & 0xFFF0) == SC_SCREENSAVE || (wParam & 0xFFF0) == SC_MONITORPOWER)) + if (vid_activewindow && ((wParam & 0xFFF0) == SC_SCREENSAVE || (wParam & 0xFFF0) == SC_MONITORPOWER)) lRet = 0;; // note: password-locked screensavers on Vista still work break; @@ -681,6 +690,64 @@ void *GL_GetProcAddress(const char *name) return p; } +#ifndef WGL_ARB_pixel_format +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_DRAW_TO_BITMAP_ARB 0x2002 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NEED_PALETTE_ARB 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_NUMBER_OVERLAYS_ARB 0x2008 +#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 +#define WGL_TRANSPARENT_ARB 0x200A +#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 +#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 +#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 +#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A +#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B +#define WGL_SHARE_DEPTH_ARB 0x200C +#define WGL_SHARE_STENCIL_ARB 0x200D +#define WGL_SHARE_ACCUM_ARB 0x200E +#define WGL_SUPPORT_GDI_ARB 0x200F +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201A +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_ALPHA_SHIFT_ARB 0x201C +#define WGL_ACCUM_BITS_ARB 0x201D +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_SWAP_EXCHANGE_ARB 0x2028 +#define WGL_SWAP_COPY_ARB 0x2029 +#define WGL_SWAP_UNDEFINED_ARB 0x202A +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_TYPE_COLORINDEX_ARB 0x202C +#endif + +#ifndef WGL_ARB_multisample +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 +#endif + + static void IN_Init(void); void VID_Init(void) { @@ -710,7 +777,7 @@ void VID_Init(void) IN_Init(); } -int VID_InitMode (int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer) +int VID_InitMode (int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer, int samples) { int i; HDC hdc; @@ -737,13 +804,19 @@ int VID_InitMode (int fullscreen, int width, int height, int bpp, int refreshrat 0, // reserved 0, 0, 0 // layer masks ignored }; - int pixelformat; + int windowpass; + int pixelformat, newpixelformat; + int numpixelformats; DWORD WindowStyle, ExWindowStyle; int CenterX, CenterY; const char *gldrivername; int depth; DEVMODE thismode; qboolean foundmode, foundgoodmode; + int *a; + float *af; + int attribs[128]; + float attribsf[16]; if (vid_initialized) Sys_Error("VID_InitMode called when video is already initialised"); @@ -763,6 +836,59 @@ int VID_InitMode (int fullscreen, int width, int height, int bpp, int refreshrat if (stereobuffer) pfd.dwFlags |= PFD_STEREO; + a = attribs; + af = attribsf; + *a++ = WGL_DRAW_TO_WINDOW_ARB; + *a++ = GL_TRUE; + *a++ = WGL_ACCELERATION_ARB; + *a++ = WGL_FULL_ACCELERATION_ARB; + *a++ = WGL_DOUBLE_BUFFER_ARB; + *a++ = true; + + if (bpp >= 32) + { + *a++ = WGL_RED_BITS_ARB; + *a++ = 8; + *a++ = WGL_GREEN_BITS_ARB; + *a++ = 8; + *a++ = WGL_BLUE_BITS_ARB; + *a++ = 8; + *a++ = WGL_ALPHA_BITS_ARB; + *a++ = 1; + *a++ = WGL_DEPTH_BITS_ARB; + *a++ = 24; + *a++ = WGL_STENCIL_BITS_ARB; + *a++ = 8; + } + else + { + *a++ = WGL_RED_BITS_ARB; + *a++ = 1; + *a++ = WGL_GREEN_BITS_ARB; + *a++ = 1; + *a++ = WGL_BLUE_BITS_ARB; + *a++ = 1; + *a++ = WGL_DEPTH_BITS_ARB; + *a++ = 16; + } + + if (stereobuffer) + { + *a++ = WGL_STEREO_ARB; + *a++ = GL_TRUE; + } + + if (samples > 1) + { + *a++ = WGL_SAMPLE_BUFFERS_ARB; + *a++ = 1; + *a++ = WGL_SAMPLES_ARB; + *a++ = samples; + } + + *a = 0; + *af = 0; + gldrivername = "opengl32.dll"; // COMMANDLINEOPTION: Windows WGL: -gl_driver selects a GL driver library, default is opengl32.dll, useful only for 3dfxogl.dll or 3dfxvgl.dll, if you don't know what this is for, you don't need it i = COM_CheckParm("-gl_driver"); @@ -940,14 +1066,106 @@ int VID_InitMode (int fullscreen, int width, int height, int bpp, int refreshrat rect.top += CenterY; rect.bottom += CenterY; - mainwindow = CreateWindowEx (ExWindowStyle, "DarkPlacesWindowClass", gamename, WindowStyle, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, global_hInstance, NULL); - if (!mainwindow) + pixelformat = 0; + newpixelformat = 0; + for (windowpass = 0;windowpass < 2;windowpass++) { - Con_Printf("CreateWindowEx(%d, %s, %s, %d, %d, %d, %d, %d, %p, %p, %d, %p) failed\n", (int)ExWindowStyle, "DarkPlacesWindowClass", gamename, (int)WindowStyle, (int)(rect.left), (int)(rect.top), (int)(rect.right - rect.left), (int)(rect.bottom - rect.top), NULL, NULL, (int)global_hInstance, NULL); - VID_Shutdown(); - return false; + mainwindow = CreateWindowEx (ExWindowStyle, "DarkPlacesWindowClass", gamename, WindowStyle, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, global_hInstance, NULL); + if (!mainwindow) + { + Con_Printf("CreateWindowEx(%d, %s, %s, %d, %d, %d, %d, %d, %p, %p, %d, %p) failed\n", (int)ExWindowStyle, "DarkPlacesWindowClass", gamename, (int)WindowStyle, (int)(rect.left), (int)(rect.top), (int)(rect.right - rect.left), (int)(rect.bottom - rect.top), NULL, NULL, (int)global_hInstance, NULL); + VID_Shutdown(); + return false; + } + + baseDC = GetDC(mainwindow); + + if (!newpixelformat) + newpixelformat = ChoosePixelFormat(baseDC, &pfd); + pixelformat = newpixelformat; + if (!pixelformat) + { + VID_Shutdown(); + Con_Printf("ChoosePixelFormat(%d, %p) failed\n", (int)baseDC, &pfd); + return false; + } + + if (SetPixelFormat(baseDC, pixelformat, &pfd) == false) + { + VID_Shutdown(); + Con_Printf("SetPixelFormat(%d, %d, %p) failed\n", (int)baseDC, pixelformat, &pfd); + return false; + } + + if (!GL_CheckExtension("wgl", wglfuncs, NULL, false)) + { + VID_Shutdown(); + Con_Print("wgl functions not found\n"); + return false; + } + + baseRC = qwglCreateContext(baseDC); + if (!baseRC) + { + VID_Shutdown(); + Con_Print("Could not initialize GL (wglCreateContext failed).\n\nMake sure you are in 65536 color mode, and try running -window.\n"); + return false; + } + if (!qwglMakeCurrent(baseDC, baseRC)) + { + VID_Shutdown(); + Con_Printf("wglMakeCurrent(%d, %d) failed\n", (int)baseDC, (int)baseRC); + return false; + } + + if ((qglGetString = (const GLubyte* (GLAPIENTRY *)(GLenum name))GL_GetProcAddress("glGetString")) == NULL) + { + VID_Shutdown(); + Con_Print("glGetString not found\n"); + return false; + } + if ((qwglGetExtensionsStringARB = (const char *(WINAPI *)(HDC hdc))GL_GetProcAddress("wglGetExtensionsStringARB")) == NULL) + Con_Print("wglGetExtensionsStringARB not found\n"); + + gl_renderer = qglGetString(GL_RENDERER); + gl_vendor = qglGetString(GL_VENDOR); + gl_version = qglGetString(GL_VERSION); + gl_extensions = qglGetString(GL_EXTENSIONS); + gl_platform = "WGL"; + gl_platformextensions = ""; + + if (qwglGetExtensionsStringARB) + gl_platformextensions = qwglGetExtensionsStringARB(baseDC); + + // now some nice Windows pain: + // we have created a window, we needed one to find out if there are + // any multisample pixel formats available, the problem is that to + // actually use one of those multisample formats we now have to + // recreate the window (yes Microsoft OpenGL really is that bad) + + if (windowpass == 0) + { + if (!GL_CheckExtension("WGL_ARB_pixel_format", wglpixelformatfuncs, "-noarbpixelformat", false) || !qwglChoosePixelFormatARB(baseDC, attribs, attribsf, 1, &newpixelformat, &numpixelformats) || !newpixelformat) + break; + // ok we got one - do it all over again with newpixelformat + qwglMakeCurrent(NULL, NULL); + qwglDeleteContext(baseRC);baseRC = 0; + ReleaseDC(mainwindow, baseDC);baseDC = 0; + // eat up any messages waiting for us + while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + } } + Con_DPrintf("GL_VENDOR: %s\n", gl_vendor); + Con_DPrintf("GL_RENDERER: %s\n", gl_renderer); + Con_DPrintf("GL_VERSION: %s\n", gl_version); + Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions); + Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions); + /* if (!fullscreen) SetWindowPos (mainwindow, NULL, CenterX, CenterY, 0, 0,SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); @@ -979,84 +1197,13 @@ int VID_InitMode (int fullscreen, int width, int height, int bpp, int refreshrat // fix the leftover Alt from any Alt-Tab or the like that switched us away ClearAllStates (); - baseDC = GetDC(mainwindow); - - if ((pixelformat = ChoosePixelFormat(baseDC, &pfd)) == 0) - { - VID_Shutdown(); - Con_Printf("ChoosePixelFormat(%d, %p) failed\n", (int)baseDC, &pfd); - return false; - } - - if (SetPixelFormat(baseDC, pixelformat, &pfd) == false) - { - VID_Shutdown(); - Con_Printf("SetPixelFormat(%d, %d, %p) failed\n", (int)baseDC, pixelformat, &pfd); - return false; - } - - if (!GL_CheckExtension("wgl", wglfuncs, NULL, false)) - { - VID_Shutdown(); - Con_Print("wgl functions not found\n"); - return false; - } - - baseRC = qwglCreateContext(baseDC); - if (!baseRC) - { - VID_Shutdown(); - Con_Print("Could not initialize GL (wglCreateContext failed).\n\nMake sure you are in 65536 color mode, and try running -window.\n"); - return false; - } - if (!qwglMakeCurrent(baseDC, baseRC)) - { - VID_Shutdown(); - Con_Printf("wglMakeCurrent(%d, %d) failed\n", (int)baseDC, (int)baseRC); - return false; - } - - if ((qglGetString = (const GLubyte* (GLAPIENTRY *)(GLenum name))GL_GetProcAddress("glGetString")) == NULL) - { - VID_Shutdown(); - Con_Print("glGetString not found\n"); - return false; - } - if ((qwglGetExtensionsStringARB = (const char *(WINAPI *)(HDC hdc))GL_GetProcAddress("wglGetExtensionsStringARB")) == NULL) - Con_Print("wglGetExtensionsStringARB not found\n"); - gl_renderer = qglGetString(GL_RENDERER); - gl_vendor = qglGetString(GL_VENDOR); - gl_version = qglGetString(GL_VERSION); - gl_extensions = qglGetString(GL_EXTENSIONS); - gl_platform = "WGL"; - gl_platformextensions = ""; - - Con_DPrintf("GL_VENDOR: %s\n", gl_vendor); - Con_DPrintf("GL_RENDERER: %s\n", gl_renderer); - Con_DPrintf("GL_VERSION: %s\n", gl_version); - Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions); - Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions); - gl_videosyncavailable = false; - if (qwglGetExtensionsStringARB) - gl_platformextensions = qwglGetExtensionsStringARB(baseDC); - // COMMANDLINEOPTION: Windows WGL: -novideosync disables WGL_EXT_swap_control gl_videosyncavailable = GL_CheckExtension("WGL_EXT_swap_control", wglswapintervalfuncs, "-novideosync", false); - //ReleaseDC(mainwindow, hdc); GL_Init (); - // LordHavoc: special differences for ATI (broken 8bit color when also using 32bit? weird!) - if (strncasecmp(gl_vendor,"ATI",3)==0) - { - if (strncasecmp(gl_renderer,"Rage Pro",8)==0) - isRagePro = true; - } - if (strncasecmp(gl_renderer,"Matrox G200 Direct3D",20)==0) // a D3D driver for GL? sigh... - isG200 = true; - //vid_menudrawfn = VID_MenuDraw; //vid_menukeyfn = VID_MenuKey; vid_usingmouse = false; -- 2.39.2