Index: code/win32/win_gamma.c =================================================================== --- code/win32/win_gamma.c (revision 1046) +++ code/win32/win_gamma.c (working copy) @@ -140,6 +140,9 @@ return; } + if (!g_wv.activeApp) + return; + //mapGammaMax(); for ( i = 0; i < 256; i++ ) { Index: code/win32/glw_win.h =================================================================== --- code/win32/glw_win.h (revision 1046) +++ code/win32/glw_win.h (working copy) @@ -42,6 +42,7 @@ int desktopWidth, desktopHeight; qboolean cdsFullscreen; + DEVMODE dmFullscreen; FILE *log_fp; } glwstate_t; Index: code/win32/win_glimp.c =================================================================== --- code/win32/win_glimp.c (revision 1046) +++ code/win32/win_glimp.c (working copy) @@ -108,6 +108,21 @@ return qtrue; } +qboolean GLW_ResetFullScreenMode( void ) +{ + if( !glw_state.dmFullscreen.dmSize ) + return qfalse; + + // restore the last working fullscreen DEVMODE + if( ChangeDisplaySettings( &glw_state.dmFullscreen, CDS_FULLSCREEN ) != + DISP_CHANGE_SUCCESSFUL ) + { + return qfalse; + } + ShowWindow( g_wv.hWnd, SW_RESTORE ); + return qtrue; +} + /* ** ChoosePFD ** @@ -580,6 +595,9 @@ int x, y, w, h; int exstyle; + // fullscreen DEVMODE for use with win_allowAltTab + memset( &glw_state.dmFullscreen, 0, sizeof( glw_state.dmFullscreen ) ); + // // register the window class if necessary // @@ -629,7 +647,7 @@ else { exstyle = 0; - stylebits = WINDOW_STYLE|WS_SYSMENU; + stylebits = WINDOW_STYLE|WS_SYSMENU|WS_MINIMIZEBOX; AdjustWindowRect (&r, stylebits, FALSE); } @@ -922,6 +940,12 @@ } } } + if( glw_state.cdsFullscreen ) + memcpy( &glw_state.dmFullscreen, &dm, + sizeof( glw_state.dmFullscreen ) ); + else + memset( &glw_state.dmFullscreen, 0, + sizeof( glw_state.dmFullscreen ) ); } else { Index: code/win32/win_wndproc.c =================================================================== --- code/win32/win_wndproc.c (revision 1046) +++ code/win32/win_wndproc.c (working copy) @@ -35,6 +35,7 @@ cvar_t *vid_xpos; // X coordinate of window position cvar_t *vid_ypos; // Y coordinate of window position cvar_t *r_fullscreen; +cvar_t *win_allowAltTab; #define VID_NUM_MODES ( sizeof( vid_modes ) / sizeof( vid_modes[0] ) ) @@ -47,6 +48,16 @@ if ( s_alttab_disabled ) return; + if ( win_allowAltTab->integer ) + { + Com_Printf("Alt-Tab support enabled (win_allowAltTab = 1)\n" ); + return; + } + else + { + Com_Printf("Alt-Tab support disabled (win_allowAltTab = 0)\n" ); + } + if ( !Q_stricmp( Cvar_VariableString( "arch" ), "winnt" ) ) { RegisterHotKey( 0, 0, MOD_ALT, VK_TAB ); @@ -84,8 +95,15 @@ VID_AppActivate ================== */ +extern void R_ReloadTextures( void ); +extern void R_SetColorMappings( void ); +extern void WG_RestoreGamma( void ); +extern qboolean GLW_ResetFullScreenMode( void ); + static void VID_AppActivate(BOOL fActive, BOOL minimize) { + BOOL wasMinimized = g_wv.isMinimized; + g_wv.isMinimized = minimize; Com_DPrintf("VID_AppActivate: %i\n", fActive ); @@ -106,10 +124,46 @@ if (!g_wv.activeApp ) { IN_Activate (qfalse); + if ( r_fullscreen->integer ) + { + WG_RestoreGamma(); + ShowWindow( g_wv.hWnd, SW_MINIMIZE ); + ChangeDisplaySettings( 0, 0 ); + } } else { IN_Activate (qtrue); + if ( r_fullscreen->integer && wasMinimized ) + { + if( !GLW_ResetFullScreenMode() ) + { + Cbuf_AddText( "vid_restart\n" ); + return; + } + + if( win_allowAltTab->integer == 1 ) + { + // safe alt-tab support + Cbuf_AddText( "vid_restart\n" ); + } + else if( win_allowAltTab->integer == 2 ) + { + // some drivers will keep the opengl context + // during mode change but corrupt texture mem + R_SetColorMappings(); + R_ReloadTextures(); + } + else if( win_allowAltTab->integer == 3 ) + { + // some drivers protect opengl context and + // texture memory during mode change + R_SetColorMappings(); + } + + Com_Printf( "Alt-Tab support can be disabled with " + "\\win_allowAltTab 0\n" ); + } } } @@ -312,6 +366,8 @@ vid_xpos = Cvar_Get ("vid_xpos", "3", CVAR_ARCHIVE); vid_ypos = Cvar_Get ("vid_ypos", "22", CVAR_ARCHIVE); r_fullscreen = Cvar_Get ("r_fullscreen", "1", CVAR_ARCHIVE | CVAR_LATCH ); + win_allowAltTab = Cvar_Get ("win_allowAltTab", "1", + CVAR_ARCHIVE | CVAR_LATCH); MSH_MOUSEWHEEL = RegisterWindowMessage("MSWHEEL_ROLLMSG"); if ( r_fullscreen->integer ) Index: code/renderer/tr_local.h =================================================================== --- code/renderer/tr_local.h (revision 1046) +++ code/renderer/tr_local.h (working copy) @@ -775,6 +775,7 @@ #define MAX_DRAWIMAGES 2048 #define MAX_LIGHTMAPS 256 +#define LIGHTMAP_SIZE 128 #define MAX_SKINS 1024 @@ -912,6 +913,7 @@ int numLightmaps; image_t *lightmaps[MAX_LIGHTMAPS]; + byte lightmapImgs[MAX_LIGHTMAPS][LIGHTMAP_SIZE*LIGHTMAP_SIZE*4]; trRefEntity_t *currentEntity; trRefEntity_t worldEntity; // point currentEntity at this when rendering world @@ -1205,7 +1207,8 @@ image_t *R_FindImageFile( const char *name, qboolean mipmap, qboolean allowPicmip, int glWrapClampMode ); image_t *R_CreateImage( const char *name, const byte *pic, int width, int height, qboolean mipmap - , qboolean allowPicmip, int wrapClampMode ); + , qboolean allowPicmip, int wrapClampMode + , qboolean reload ); qboolean R_GetModeInfo( int *width, int *height, float *windowAspect, int mode ); void R_SetColorMappings( void ); Index: code/renderer/tr_font.c =================================================================== --- code/renderer/tr_font.c (revision 1046) +++ code/renderer/tr_font.c (working copy) @@ -493,7 +493,7 @@ } //Com_sprintf (name, sizeof(name), "fonts/fontImage_%i_%i", imageNumber++, pointSize); - image = R_CreateImage(name, imageBuff, 256, 256, qfalse, qfalse, GL_CLAMP); + image = R_CreateImage(name, imageBuff, 256, 256, qfalse, qfalse, GL_CLAMP, qfalse); h = RE_RegisterShaderFromImage(name, LIGHTMAP_2D, image, qfalse); for (j = lastStart; j < i; j++) { font->glyphs[j].glyph = h; Index: code/renderer/tr_image.c =================================================================== --- code/renderer/tr_image.c (revision 1046) +++ code/renderer/tr_image.c (working copy) @@ -503,9 +503,10 @@ int width, int height, qboolean mipmap, qboolean picmip, - qboolean lightMap, + qboolean lightMap, int *format, - int *pUploadWidth, int *pUploadHeight ) + int *pUploadWidth, + int *pUploadHeight ) { int samples; unsigned *scaledBuffer = NULL; @@ -638,7 +639,10 @@ ( scaled_height == height ) ) { if (!mipmap) { - qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + Com_Printf("RGBA 1\n"); + qglTexImage2D( GL_TEXTURE_2D, 0, internalFormat, + scaled_width, scaled_height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, data); *pUploadWidth = scaled_width; *pUploadHeight = scaled_height; *format = internalFormat; @@ -670,7 +674,9 @@ *pUploadHeight = scaled_height; *format = internalFormat; - qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaledBuffer ); + Com_Printf("RGBA internalFormat\n"); + qglTexImage2D( GL_TEXTURE_2D, 0, internalFormat, scaled_width, + scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaledBuffer ); if (mipmap) { @@ -691,8 +697,10 @@ if ( r_colorMipLevels->integer ) { R_BlendOverTexture( (byte *)scaledBuffer, scaled_width * scaled_height, mipBlendColors[miplevel] ); } - - qglTexImage2D (GL_TEXTURE_2D, miplevel, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaledBuffer ); + Com_Printf("RGBA miplevel\n"); + qglTexImage2D( GL_TEXTURE_2D, miplevel, internalFormat, + scaled_width, scaled_height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, scaledBuffer ); } } done: @@ -731,9 +739,16 @@ This is the only way any image_t are created ================ */ -image_t *R_CreateImage( const char *name, const byte *pic, int width, int height, - qboolean mipmap, qboolean allowPicmip, int glWrapClampMode ) { - image_t *image; +image_t *R_CreateImage( const char *name, + const byte *pic, + int width, + int height, + qboolean mipmap, + qboolean allowPicmip, + int glWrapClampMode, + qboolean reload ) +{ + image_t *image = NULL; qboolean isLightmap = qfalse; long hash; @@ -748,24 +763,49 @@ ri.Error( ERR_DROP, "R_CreateImage: MAX_DRAWIMAGES hit\n"); } - image = tr.images[tr.numImages] = ri.Hunk_Alloc( sizeof( image_t ), h_low ); - image->texnum = 1024 + tr.numImages; - tr.numImages++; + if( reload ) { + long hash; + qboolean found = qfalse; - image->mipmap = mipmap; - image->allowPicmip = allowPicmip; + hash = generateHashValue(name); - strcpy (image->imgName, name); + for( image = hashTable[hash]; image; image = image->next ) { + if ( !strcmp( name, image->imgName ) ) { + found = qtrue; + break; + } + } + if( !found ) { + Com_Printf( "ERROR: could not reload texture %s\n", + image->imgName ); + return NULL; + } + else { + Com_Printf( "FOUND %s %d\n", image->imgName, image->texnum ); + } + qglDeleteTextures( 1, &image->texnum ); + } + else { + image = tr.images[tr.numImages] = + ri.Hunk_Alloc( sizeof( image_t ), h_low ); + image->texnum = 1024 + tr.numImages; + tr.numImages++; - image->width = width; - image->height = height; - image->wrapClampMode = glWrapClampMode; + image->mipmap = mipmap; + image->allowPicmip = allowPicmip; - // lightmaps are always allocated on TMU 1 - if ( qglActiveTextureARB && isLightmap ) { - image->TMU = 1; - } else { - image->TMU = 0; + strcpy (image->imgName, name); + + image->width = width; + image->height = height; + image->wrapClampMode = glWrapClampMode; + + // lightmaps are always allocated on TMU 1 + if ( qglActiveTextureARB && isLightmap ) { + image->TMU = 1; + } else { + image->TMU = 0; + } } if ( qglActiveTextureARB ) { @@ -775,12 +815,12 @@ GL_Bind(image); Upload32( (unsigned *)pic, image->width, image->height, - image->mipmap, - allowPicmip, - isLightmap, - &image->internalFormat, - &image->uploadWidth, - &image->uploadHeight ); + image->mipmap, + allowPicmip, + isLightmap, + &image->internalFormat, + &image->uploadWidth, + &image->uploadHeight ); qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode ); qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode ); @@ -791,9 +831,11 @@ GL_SelectTexture( 0 ); } - hash = generateHashValue(name); - image->next = hashTable[hash]; - hashTable[hash] = image; + if( !reload ) { + hash = generateHashValue(name); + image->next = hashTable[hash]; + hashTable[hash] = image; + } return image; } @@ -2015,22 +2057,24 @@ // load the pic from disk // R_LoadImage( name, &pic, &width, &height ); - if ( pic == NULL ) { // if we dont get a successful load - char altname[MAX_QPATH]; // copy the name - int len; // - strcpy( altname, name ); // - len = strlen( altname ); // - altname[len-3] = toupper(altname[len-3]); // and try upper case extension for unix systems - altname[len-2] = toupper(altname[len-2]); // - altname[len-1] = toupper(altname[len-1]); // - ri.Printf( PRINT_ALL, "trying %s...\n", altname ); // - R_LoadImage( altname, &pic, &width, &height ); // - if (pic == NULL) { // if that fails - return NULL; // bail - } + // if we dont get a successful load + if ( pic == NULL ) { + char altname[MAX_QPATH]; + int len; + + Q_strncpyz( altname, name, sizeof( altname ) ); + len = strlen( altname ); + // try upper case extension for unix systems + altname[len-3] = toupper(altname[len-3]); + altname[len-2] = toupper(altname[len-2]); + altname[len-1] = toupper(altname[len-1]); + ri.Printf( PRINT_ALL, "trying %s...\n", altname ); + R_LoadImage( altname, &pic, &width, &height ); + if (pic == NULL) + return NULL; } - image = R_CreateImage( ( char * ) name, pic, width, height, mipmap, allowPicmip, glWrapClampMode ); + image = R_CreateImage( ( char * ) name, pic, width, height, mipmap, allowPicmip, glWrapClampMode, qfalse ); ri.Free( pic ); return image; } @@ -2042,7 +2086,7 @@ ================ */ #define DLIGHT_SIZE 16 -static void R_CreateDlightImage( void ) { +static void R_CreateDlightImage( qboolean reload ) { int x,y; byte data[DLIGHT_SIZE][DLIGHT_SIZE][4]; int b; @@ -2066,7 +2110,7 @@ data[y][x][3] = 255; } } - tr.dlightImage = R_CreateImage("*dlight", (byte *)data, DLIGHT_SIZE, DLIGHT_SIZE, qfalse, qfalse, GL_CLAMP ); + tr.dlightImage = R_CreateImage("*dlight", (byte *)data, DLIGHT_SIZE, DLIGHT_SIZE, qfalse, qfalse, GL_CLAMP, reload ); } @@ -2131,7 +2175,7 @@ */ #define FOG_S 256 #define FOG_T 32 -static void R_CreateFogImage( void ) { +static void R_CreateFogImage( qboolean reload ) { int x,y; byte *data; float g; @@ -2156,7 +2200,7 @@ // standard openGL clamping doesn't really do what we want -- it includes // the border color at the edges. OpenGL 1.2 has clamp-to-edge, which does // what we want. - tr.fogImage = R_CreateImage("*fog", (byte *)data, FOG_S, FOG_T, qfalse, qfalse, GL_CLAMP ); + tr.fogImage = R_CreateImage("*fog", (byte *)data, FOG_S, FOG_T, qfalse, qfalse, GL_CLAMP, reload ); ri.Hunk_FreeTempMemory( data ); borderColor[0] = 1.0; @@ -2173,7 +2217,7 @@ ================== */ #define DEFAULT_SIZE 16 -static void R_CreateDefaultImage( void ) { +static void R_CreateDefaultImage( qboolean reload ) { int x; byte data[DEFAULT_SIZE][DEFAULT_SIZE][4]; @@ -2200,7 +2244,7 @@ data[x][DEFAULT_SIZE-1][2] = data[x][DEFAULT_SIZE-1][3] = 255; } - tr.defaultImage = R_CreateImage("*default", (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, qtrue, qfalse, GL_REPEAT ); + tr.defaultImage = R_CreateImage("*default", (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, qtrue, qfalse, GL_REPEAT, reload ); } /* @@ -2208,15 +2252,15 @@ R_CreateBuiltinImages ================== */ -void R_CreateBuiltinImages( void ) { +void R_CreateBuiltinImages( qboolean reload ) { int x,y; byte data[DEFAULT_SIZE][DEFAULT_SIZE][4]; - R_CreateDefaultImage(); + R_CreateDefaultImage( reload ); // we use a solid white image instead of disabling texturing Com_Memset( data, 255, sizeof( data ) ); - tr.whiteImage = R_CreateImage("*white", (byte *)data, 8, 8, qfalse, qfalse, GL_REPEAT ); + tr.whiteImage = R_CreateImage("*white", (byte *)data, 8, 8, qfalse, qfalse, GL_REPEAT, reload ); // with overbright bits active, we need an image which is some fraction of full color, // for default lightmaps, etc @@ -2229,16 +2273,17 @@ } } - tr.identityLightImage = R_CreateImage("*identityLight", (byte *)data, 8, 8, qfalse, qfalse, GL_REPEAT ); + tr.identityLightImage = R_CreateImage("*identityLight", (byte *)data, 8, 8, qfalse, qfalse, GL_REPEAT, reload ); - for(x=0;x<32;x++) { // scratchimage is usually used for cinematic drawing - tr.scratchImage[x] = R_CreateImage("*scratch", (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, qfalse, qtrue, GL_CLAMP ); + tr.scratchImage[x] = R_CreateImage( va("*scratch%d",x), + (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, + qfalse, qtrue, GL_CLAMP, reload ); } - - R_CreateDlightImage(); - R_CreateFogImage(); + + R_CreateDlightImage( reload ); + R_CreateFogImage( reload ); } @@ -2338,9 +2383,49 @@ R_SetColorMappings(); // create default texture and white texture - R_CreateBuiltinImages(); + R_CreateBuiltinImages( qfalse ); } +void R_ReloadTextures( void ) { + int i; + image_t *img; + byte *pic; + + R_SyncRenderThread(); + + if ( qglBindTexture ) { + if ( qglActiveTextureARB ) { + GL_SelectTexture( 1 ); + qglBindTexture( GL_TEXTURE_2D, 0 ); + GL_SelectTexture( 0 ); + qglBindTexture( GL_TEXTURE_2D, 0 ); + } else { + qglBindTexture( GL_TEXTURE_2D, 0 ); + } + } + + R_CreateBuiltinImages( qtrue ); + for( i = 0; i < tr.numImages; i++ ) + { + pic = NULL; + img = tr.images[ i ]; + if( img->imgName[ 0 ] == '*' ) + continue; + R_LoadImage( img->imgName, &pic, &img->width, &img->height ); + R_CreateImage( img->imgName, pic, img->width, img->height, + img->mipmap, img->allowPicmip, img->wrapClampMode, + qtrue ); + ri.Free( pic ); + } + + for( i = 0; i < tr.numLightmaps; i++ ) + { + R_CreateImage( va( "*lightmap%d",i ), tr.lightmapImgs[ i ], + LIGHTMAP_SIZE, LIGHTMAP_SIZE, qfalse, qfalse, + GL_CLAMP, qtrue ); + } +} + /* =============== R_DeleteTextures Index: code/renderer/tr_bsp.c =================================================================== --- code/renderer/tr_bsp.c (revision 1046) +++ code/renderer/tr_bsp.c (working copy) @@ -131,7 +131,6 @@ =============== */ -#define LIGHTMAP_SIZE 128 static void R_LoadLightmaps( lump_t *l ) { byte *buf, *buf_p; int len; @@ -140,11 +139,18 @@ float maxIntensity = 0; double sumIntensity = 0; + tr.numLightmaps = 0; + len = l->filelen; if ( !len ) { return; } buf = fileBase + l->fileofs; + + // if we are in r_vertexLight mode, we don't need the lightmaps at all + if ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 ) { + return; + } // we are about to upload textures R_SyncRenderThread(); @@ -160,10 +166,6 @@ tr.numLightmaps = MAX_LIGHTMAPS; } - // if we are in r_vertexLight mode, we don't need the lightmaps at all - if ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 ) { - return; - } for ( i = 0 ; i < tr.numLightmaps ; i++ ) { // expand the 24 bit on-disk to 32 bit @@ -204,8 +206,11 @@ image[j*4+3] = 255; } } + memcpy( &tr.lightmapImgs[i], &image, + sizeof( tr.lightmapImgs[i] ) ); tr.lightmaps[i] = R_CreateImage( va("*lightmap%d",i), image, - LIGHTMAP_SIZE, LIGHTMAP_SIZE, qfalse, qfalse, GL_CLAMP ); + LIGHTMAP_SIZE, LIGHTMAP_SIZE, qfalse, qfalse, GL_CLAMP, + qfalse ); } if ( r_lightmap->integer == 2 ) {