diff --git a/engine/client/ref_common.c b/engine/client/ref_common.c index 41fb6da6..bb3e72b5 100644 --- a/engine/client/ref_common.c +++ b/engine/client/ref_common.c @@ -558,7 +558,7 @@ static void SetWidthAndHeightFromCommandLine( void ) return; } - R_SaveVideoMode( width, height ); + R_SaveVideoMode( width, height, width, height ); } static void SetFullscreenModeFromCommandLine( void ) diff --git a/engine/client/vid_common.c b/engine/client/vid_common.c index a2a315a7..f31312dd 100644 --- a/engine/client/vid_common.c +++ b/engine/client/vid_common.c @@ -31,6 +31,10 @@ glwstate_t glw_state; convar_t *window_xpos; convar_t *window_ypos; + +convar_t *vid_rotate; +convar_t *vid_scale; + /* ================= VID_StartupGamma @@ -62,19 +66,21 @@ void VID_InitDefaultResolution( void ) R_SaveVideoMode ================= */ -void R_SaveVideoMode( int w, int h ) +void R_SaveVideoMode( int w, int h , int render_w, int render_h ) { - refState.width = w; - refState.height = h; - host.window_center_x = w / 2; host.window_center_y = h / 2; Cvar_SetValue( "width", w ); Cvar_SetValue( "height", h ); + refState.width = render_w; + refState.height = render_h; + + host.renderinfo_changed = false; + // check for 4:3 or 5:4 - if( w * 3 != h * 4 && w * 4 != h * 5 ) + if( render_w * 3 != render_h * 4 && render_w * 4 != render_h * 5 ) refState.wideScreen = true; else refState.wideScreen = false; } @@ -175,6 +181,8 @@ void VID_Init( void ) vid_displayfrequency = Cvar_Get ( "vid_displayfrequency", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "fullscreen refresh rate" ); vid_fullscreen = Cvar_Get( "fullscreen", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "enable fullscreen mode" ); vid_highdpi = Cvar_Get( "vid_highdpi", "1", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "enable High-DPI mode" ); + vid_rotate = Cvar_Get( "vid_rotate", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen rotation (0-3)" ); + vid_scale = Cvar_Get( "vid_scale", "1.0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "pixel scale" ); // a1ba: planned to be named vid_mode for compability // but supported mode list is filled by backends, so numbers are not portable any more diff --git a/engine/client/vid_common.h b/engine/client/vid_common.h index 842ae2fc..f95d2531 100644 --- a/engine/client/vid_common.h +++ b/engine/client/vid_common.h @@ -34,8 +34,11 @@ extern glwstate_t glw_state; extern convar_t *vid_fullscreen; extern convar_t *vid_displayfrequency; extern convar_t *vid_highdpi; +extern convar_t *vid_rotate; +extern convar_t *vid_scale; + extern convar_t *gl_wgl_msaa_samples; -void R_SaveVideoMode( int w, int h ); +void R_SaveVideoMode( int w, int h, int render_w, int render_h ); void VID_CheckChanges( void ); const char *VID_GetModeString( int vid_mode ); void VID_StartupGamma( void ); diff --git a/engine/platform/android/vid_android.c b/engine/platform/android/vid_android.c index a447f5cb..6746f237 100644 --- a/engine/platform/android/vid_android.c +++ b/engine/platform/android/vid_android.c @@ -327,14 +327,34 @@ qboolean VID_SetMode( void ) rserr_t R_ChangeDisplaySettings( int width, int height, qboolean fullscreen ) { + int render_w, render_h; + uint rotate = vid_rotate->value; + Android_GetScreenRes(&width, &height); + render_w = width, render_h = height; + Con_Reportf( "R_ChangeDisplaySettings: forced resolution to %dx%d)\n", width, height); - R_SaveVideoMode( width, height ); + if( ref.dllFuncs.R_SetDisplayTransform( rotate, 0, 0, vid_scale->value, vid_scale->value ) ) + { + if( rotate & 1 ) + { + int swap = render_w; + + render_w = render_h; + render_h = swap; + } + + render_h /= vid_scale->value; + render_w /= vid_scale->value; + } + else + { + Con_Printf( S_WARN "failed to setup screen transform\n" ); + } - host.window_center_x = width / 2; - host.window_center_y = height / 2; + R_SaveVideoMode( width, height, render_w, render_h ); refState.wideScreen = true; // V_AdjustFov will check for widescreen diff --git a/engine/platform/linux/vid_fbdev.c b/engine/platform/linux/vid_fbdev.c index 49e1f0cb..f9915db7 100644 --- a/engine/platform/linux/vid_fbdev.c +++ b/engine/platform/linux/vid_fbdev.c @@ -39,7 +39,7 @@ void GL_SwapBuffers( void ) { } -void FB_GetScreenRes(int *x, int *y) +void FB_GetScreenRes( int *x, int *y ) { *x = fb.vinfo.xres; *y = fb.vinfo.yres; @@ -121,16 +121,32 @@ qboolean VID_SetMode( void ) rserr_t R_ChangeDisplaySettings( int width, int height, qboolean fullscreen ) { + int render_w, render_h; + uint rotate = vid_rotate->value; + FB_GetScreenRes( &width, &height ); + render_w = width, render_h = height; - Con_Reportf( "R_ChangeDisplaySettings: forced resolution to %dx%d)\n", width, height); + Con_Reportf( "R_ChangeDisplaySettings: forced resolution to %dx%d)\n", width, height ); - R_SaveVideoMode( width, height ); + if( ref.dllFuncs.R_SetDisplayTransform( rotate, 0, 0, vid_scale->value, vid_scale->value ) ) + { + if( rotate & 1 ) + { + int swap = render_w; - host.window_center_x = width / 2; - host.window_center_y = height / 2; + render_w = render_h; + render_h = swap; + } - refState.wideScreen = true; // V_AdjustFov will check for widescreen + render_h /= vid_scale->value; + render_w /= vid_scale->value; + } + else + { + Con_Printf( S_WARN "failed to setup screen transform\n" ); + } + R_SaveVideoMode( width, height, render_w, render_h ); return rserr_ok; } @@ -204,6 +220,13 @@ void SW_UnlockBuffer( void ) qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b ) { + if( width > fb.vinfo.xres_virtual || height > fb.vinfo.yres_virtual ) + { + Con_Printf( S_ERROR "requested size %dx%d not fit to framebuffer size %dx%d\n", + width, height, fb.vinfo.xres_virtual, fb.vinfo.yres_virtual ); + return false; + } + *bpp = fb.vinfo.bits_per_pixel >> 3; *stride = fb.vinfo.xres_virtual; *r = FB_BF_TO_MASK(fb.vinfo.red); diff --git a/engine/platform/sdl/events.c b/engine/platform/sdl/events.c index 09e0a9d5..5da4341a 100644 --- a/engine/platform/sdl/events.c +++ b/engine/platform/sdl/events.c @@ -423,14 +423,11 @@ static void SDLash_EventFilter( SDL_Event *event ) VID_RestoreScreenResolution(); break; case SDL_WINDOWEVENT_RESIZED: - case SDL_WINDOWEVENT_MAXIMIZED: { - int w = VID_MIN_WIDTH, h = VID_MIN_HEIGHT; if( vid_fullscreen->value ) break; - SDL_GL_GetDrawableSize( host.hWnd, &w, &h ); - R_SaveVideoMode( w, h ); + VID_SaveWindowSize( event->window.data1, event->window.data2 ); SCR_VidInit(); // tell the client.dll what vid_mode has changed break; } diff --git a/engine/platform/sdl/events.h b/engine/platform/sdl/events.h index d5102331..452f7286 100644 --- a/engine/platform/sdl/events.h +++ b/engine/platform/sdl/events.h @@ -28,7 +28,7 @@ void GL_InitExtensions( void ); qboolean GL_CreateContext( void ); qboolean GL_UpdateContext( void ); qboolean GL_DeleteContext( void ); - +void VID_SaveWindowSize( int width, int height ); #endif // XASH_SDL #endif // KEYWRAPPER_H diff --git a/engine/platform/sdl/vid_sdl.c b/engine/platform/sdl/vid_sdl.c index cc97150c..7816a38e 100644 --- a/engine/platform/sdl/vid_sdl.c +++ b/engine/platform/sdl/vid_sdl.c @@ -449,7 +449,38 @@ qboolean GL_UpdateContext( void ) return true; } -qboolean VID_SetScreenResolution( int width, int height ) +void VID_SaveWindowSize( int width, int height ) +{ + int render_w = width, render_h = height; + uint rotate = vid_rotate->value; + + if( !glw_state.software ) + SDL_GL_GetDrawableSize( host.hWnd, &render_w, &render_h ); + else + SDL_RenderSetLogicalSize( sw.renderer, width, height ); + + if( ref.dllFuncs.R_SetDisplayTransform( rotate, 0, 0, vid_scale->value, vid_scale->value ) ) + { + if( rotate & 1 ) + { + int swap = render_w; + + render_w = render_h; + render_h = swap; + } + + render_h /= vid_scale->value; + render_w /= vid_scale->value; + } + else + { + Con_Printf( S_WARN "failed to setup screen transform\n" ); + } + + R_SaveVideoMode( width, height, render_w, render_h ); +} + +static qboolean VID_SetScreenResolution( int width, int height ) { SDL_DisplayMode want, got; Uint32 wndFlags = 0; @@ -479,9 +510,8 @@ qboolean VID_SetScreenResolution( int width, int height ) SDL_SetWindowGrab( host.hWnd, SDL_TRUE ); SDL_SetWindowSize( host.hWnd, got.w, got.h ); - SDL_GL_GetDrawableSize( host.hWnd, &got.w, &got.h ); + VID_SaveWindowSize( got.w, got.h ); - R_SaveVideoMode( got.w, got.h ); return true; } @@ -672,9 +702,9 @@ qboolean VID_CreateWindow( int width, int height, qboolean fullscreen ) if( !GL_UpdateContext( )) return false; - SDL_GL_GetDrawableSize( host.hWnd, &width, &height ); } - R_SaveVideoMode( width, height ); + + VID_SaveWindowSize( width, height ); return true; } @@ -906,11 +936,7 @@ rserr_t R_ChangeDisplaySettings( int width, int height, qboolean fullscreen ) #endif SDL_SetWindowBordered( host.hWnd, SDL_TRUE ); SDL_SetWindowSize( host.hWnd, width, height ); - if( !glw_state.software ) - SDL_GL_GetDrawableSize( host.hWnd, &width, &height ); - else - SDL_RenderSetLogicalSize(sw.renderer, width, height); - R_SaveVideoMode( width, height ); + VID_SaveWindowSize( width, height ); } return rserr_ok; diff --git a/engine/ref_api.h b/engine/ref_api.h index 9c4b546e..2566c2fb 100644 --- a/engine/ref_api.h +++ b/engine/ref_api.h @@ -88,6 +88,7 @@ typedef struct ref_globals_s // viewport width and height int width; int height; + qboolean fullScreen; qboolean wideScreen; @@ -435,6 +436,7 @@ typedef struct ref_interface_s // const char *(*R_GetInitError)( void ); void (*R_Shutdown)( void ); const char *(*R_GetConfigName)( void ); // returns config name without extension + qboolean (*R_SetDisplayTransform)( uint rotate, int x, int y, float scale_x, float scale_y ); // only called for GL contexts void (*GL_SetupAttributes)( int safegl ); diff --git a/ref_gl/gl_context.c b/ref_gl/gl_context.c index 35505a13..66d1eaec 100644 --- a/ref_gl/gl_context.c +++ b/ref_gl/gl_context.c @@ -308,6 +308,30 @@ void R_ProcessEntData( qboolean allocate ) gEngfuncs.drawFuncs->R_ProcessEntData( allocate ); } +qboolean R_SetDisplayTransform( uint rotate, int offset_x, int offset_y, float scale_x, float scale_y ) +{ + qboolean ret = true; + if( rotate > 0 ) + { + gEngfuncs.Con_Printf("rotation transform not supported\n"); + ret = false; + } + + if( offset_x || offset_y ) + { + gEngfuncs.Con_Printf("offset transform not supported\n"); + ret = false; + } + + if( scale_x != 1.0f || scale_y != 1.0f ) + { + gEngfuncs.Con_Printf("scale transform not supported\n"); + ret = false; + } + + return ret; +} + static const char *R_GetConfigName( void ) { return "opengl"; @@ -318,6 +342,7 @@ ref_interface_t gReffuncs = R_Init, R_Shutdown, R_GetConfigName, + R_SetDisplayTransform, GL_SetupAttributes, GL_InitExtensions,