5 1 new backport x11 fs rework (#1485)
* Use XRandR 1.2 to set fullscreen resolution for single output Squash of roothorick's PR #497 (also includes Kyzentun's CMake changes from PR #716) * Cherry-pick json c++1x stuff (b9e3d7174e) * Cherry-pick c++11 support from 5bba5c0038 and 9f8b045309 * rework Linux (X11) fullscreen, improve display-related Graphics Options Implement option to select between monitors for exclusive fullscreen mode on X11 (using XRandR 1.2), or use a fullscreen borderless window. Reimplement resolution/refresh rate/display mode-related option rows using Lua, update choices dynamically so only known-good groupings of resolution/refresh rate/aspect ratio can be selected. Minimally update Windows/MacOS LowLevelWindow implementations to support changes made for Linux side. Fullscreen Borderless Window/multi monitor support from X11 not implemented for those in this commit. * allow forcibly disabling xinerama use on Linux When libXinerama is available, SM tries to use it to find the proper monitor indexes to use to set _NET_WM_FULLSCREEN_MONITORS (on borderless fullscreen). xfwm4 seems to assume that monitors are numbered in increasing order from left to right (rather than using the Xinerama-assigned numbers), so _NET_WM_FULLSCREEN_MONITORS misbehaves on Xfce. This commit bypasses use of libXinerama, and instead forces SM to induce fullscreen on the desired monitor in the backup, hacky way: remove all window hints, move window to desired monitor, then add _NET_WM_STATE_FULLSCREEN hint. This works on mutter and Xfce. * Remove multiple warnings on redundant define. This used to be hard-coded due to pthread related items, but now it's dynamically determined. * fix _fallback menu behavior for unrecognized aspect ratios * Fix error recreating existing FS texture * Bump deployment target to 10.7 to use libc++ on XCode 8 * Add explicit casts to please clang * Update changelog
This commit is contained in:
committed by
Colby Klein
parent
7ef14c340d
commit
557be7cf1b
+106
-20
@@ -15,7 +15,7 @@ using namespace RageDisplay_Legacy_Helpers;
|
||||
#include "RageUtil.h"
|
||||
#include "EnumHelper.h"
|
||||
#include "Foreach.h"
|
||||
#include "DisplayResolutions.h"
|
||||
#include "DisplaySpec.h"
|
||||
#include "LocalizedString.h"
|
||||
|
||||
#include "arch/LowLevelWindow/LowLevelWindow.h"
|
||||
@@ -63,7 +63,7 @@ static const GLenum RageSpriteVertexFormat = GL_T2F_C4F_N3F_V3F;
|
||||
/* If we support texture matrix scaling, a handle to the vertex program: */
|
||||
static GLhandleARB g_bTextureMatrixShader = 0;
|
||||
|
||||
static map<unsigned, RenderTarget *> g_mapRenderTargets;
|
||||
static std::map<unsigned, RenderTarget *> g_mapRenderTargets;
|
||||
static RenderTarget *g_pCurrentRenderTarget = NULL;
|
||||
|
||||
static LowLevelWindow *g_pWind;
|
||||
@@ -264,6 +264,7 @@ RageDisplay_Legacy::RageDisplay_Legacy()
|
||||
|
||||
g_pWind = NULL;
|
||||
g_bTextureMatrixShader = 0;
|
||||
offscreenRenderTarget = nullptr;
|
||||
}
|
||||
|
||||
RString GetInfoLog( GLhandleARB h )
|
||||
@@ -561,10 +562,10 @@ RageDisplay_Legacy::~RageDisplay_Legacy()
|
||||
delete g_pWind;
|
||||
}
|
||||
|
||||
void RageDisplay_Legacy::GetDisplayResolutions( DisplayResolutions &out ) const
|
||||
void RageDisplay_Legacy::GetDisplaySpecs(DisplaySpecs &out) const
|
||||
{
|
||||
out.clear();
|
||||
g_pWind->GetDisplayResolutions( out );
|
||||
g_pWind->GetDisplaySpecs(out);
|
||||
}
|
||||
|
||||
static void CheckPalettedTextures()
|
||||
@@ -685,7 +686,9 @@ void SetupExtensions()
|
||||
const float fGLUVersion = StringToFloat( (const char *) gluGetString(GLU_VERSION) );
|
||||
g_gluVersion = lrintf( fGLUVersion * 10 );
|
||||
|
||||
#ifndef HAVE_X11 // LLW_X11 needs to init GLEW early for GLX exts
|
||||
glewInit();
|
||||
#endif
|
||||
|
||||
g_iMaxTextureUnits = 1;
|
||||
if (GLEW_ARB_multitexture)
|
||||
@@ -712,6 +715,39 @@ void SetupExtensions()
|
||||
}
|
||||
}
|
||||
|
||||
bool RageDisplay_Legacy::UseOffscreenRenderTarget()
|
||||
{
|
||||
if ( !GetActualVideoModeParams().renderOffscreen || !TEXTUREMAN )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !offscreenRenderTarget )
|
||||
{
|
||||
RenderTargetParam param;
|
||||
param.bWithDepthBuffer = true;
|
||||
param.bWithAlpha = true;
|
||||
param.bFloat = false;
|
||||
param.iWidth = GetActualVideoModeParams().width;
|
||||
param.iHeight = GetActualVideoModeParams().height;
|
||||
RageTextureID id( ssprintf( "FullscreenTexture%dx%d", param.iWidth,
|
||||
param.iHeight ) );
|
||||
// See if we have this texture loaded already
|
||||
// (not GC'd yet). If it exists and we try to recreate
|
||||
// it, we'll get an error
|
||||
if ( TEXTUREMAN->IsTextureRegistered( id ) )
|
||||
{
|
||||
offscreenRenderTarget = static_cast<RageTextureRenderTarget*>( TEXTUREMAN->LoadTexture( id ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
offscreenRenderTarget = new RageTextureRenderTarget( id, param );
|
||||
TEXTUREMAN->RegisterTexture( id, offscreenRenderTarget );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void RageDisplay_Legacy::ResolutionChanged()
|
||||
{
|
||||
//LOG->Warn( "RageDisplay_Legacy::ResolutionChanged" );
|
||||
@@ -721,6 +757,13 @@ void RageDisplay_Legacy::ResolutionChanged()
|
||||
EndFrame();
|
||||
|
||||
RageDisplay::ResolutionChanged();
|
||||
|
||||
if (offscreenRenderTarget && TEXTUREMAN)
|
||||
{
|
||||
TEXTUREMAN->UnloadTexture( offscreenRenderTarget );
|
||||
offscreenRenderTarget = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Return true if mode change was successful.
|
||||
@@ -746,6 +789,7 @@ RString RageDisplay_Legacy::TryVideoMode( const VideoModeParams &p, bool &bNewDe
|
||||
if (TEXTUREMAN)
|
||||
TEXTUREMAN->InvalidateTextures();
|
||||
|
||||
|
||||
/* Delete all render targets. They may have associated resources other than
|
||||
* the texture itself. */
|
||||
FOREACHM( unsigned, RenderTarget *, g_mapRenderTargets, rt )
|
||||
@@ -784,8 +828,8 @@ bool RageDisplay_Legacy::BeginFrame()
|
||||
{
|
||||
/* We do this in here, rather than ResolutionChanged, or we won't update the
|
||||
* viewport for the concurrent rendering context. */
|
||||
int fWidth = g_pWind->GetActualVideoModeParams().width;
|
||||
int fHeight = g_pWind->GetActualVideoModeParams().height;
|
||||
int fWidth = g_pWind->GetActualVideoModeParams().windowWidth;
|
||||
int fHeight = g_pWind->GetActualVideoModeParams().windowHeight;
|
||||
|
||||
glViewport( 0, 0, fWidth, fHeight );
|
||||
|
||||
@@ -793,11 +837,34 @@ bool RageDisplay_Legacy::BeginFrame()
|
||||
SetZWrite( true );
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
return RageDisplay::BeginFrame();
|
||||
bool beginFrame = RageDisplay::BeginFrame();
|
||||
if (beginFrame && UseOffscreenRenderTarget()) {
|
||||
offscreenRenderTarget->BeginRenderingTo( false );
|
||||
}
|
||||
|
||||
return beginFrame;
|
||||
}
|
||||
|
||||
void RageDisplay_Legacy::EndFrame()
|
||||
{
|
||||
if (UseOffscreenRenderTarget())
|
||||
{
|
||||
offscreenRenderTarget->FinishRenderingTo();
|
||||
Sprite fullscreenSprite;
|
||||
// We've got a hold of this, don't want sprite deleting it when
|
||||
// it's deleted
|
||||
offscreenRenderTarget->m_iRefCount++;
|
||||
fullscreenSprite.SetTexture(offscreenRenderTarget);
|
||||
fullscreenSprite.SetHorizAlign(align_left);
|
||||
fullscreenSprite.SetVertAlign(align_top);
|
||||
CameraPushMatrix();
|
||||
LoadMenuPerspective( 0, GetActualVideoModeParams().width, GetActualVideoModeParams().height,
|
||||
static_cast<float> (GetActualVideoModeParams().width) / 2.f,
|
||||
static_cast<float> (GetActualVideoModeParams().height) / 2.f );
|
||||
fullscreenSprite.Draw();
|
||||
CameraPopMatrix();
|
||||
}
|
||||
|
||||
FrameLimitBeforeVsync( g_pWind->GetActualVideoModeParams().rate );
|
||||
g_pWind->SwapBuffers();
|
||||
FrameLimitAfterVsync();
|
||||
@@ -823,20 +890,31 @@ RageSurface* RageDisplay_Legacy::CreateScreenshot()
|
||||
int width = g_pWind->GetActualVideoModeParams().width;
|
||||
int height = g_pWind->GetActualVideoModeParams().height;
|
||||
|
||||
const RagePixelFormatDesc &desc = PIXEL_FORMAT_DESC[RagePixelFormat_RGBA8];
|
||||
RageSurface *image = CreateSurface( width, height, desc.bpp,
|
||||
desc.masks[0], desc.masks[1], desc.masks[2], 0 );
|
||||
RageSurface *image = NULL;
|
||||
if (offscreenRenderTarget) {
|
||||
RageSurface *raw = GetTexture(offscreenRenderTarget->GetTexHandle());
|
||||
image = CreateSurface( offscreenRenderTarget->GetImageWidth(), offscreenRenderTarget->GetImageHeight(),
|
||||
raw->fmt.BitsPerPixel, raw->fmt.Rmask, raw->fmt.Gmask, raw->fmt.Bmask,
|
||||
raw->fmt.Amask );
|
||||
RageSurfaceUtils::Blit(raw, image);
|
||||
delete raw;
|
||||
} else {
|
||||
const RagePixelFormatDesc &desc = PIXEL_FORMAT_DESC[RagePixelFormat_RGBA8];
|
||||
image = CreateSurface( width, height, desc.bpp,
|
||||
desc.masks[0], desc.masks[1], desc.masks[2], 0 );
|
||||
|
||||
DebugFlushGLErrors();
|
||||
DebugFlushGLErrors();
|
||||
|
||||
glReadBuffer( GL_FRONT );
|
||||
DebugAssertNoGLError();
|
||||
//TODO: revisit for MacOS, where backbuffer size can be less than window size
|
||||
glReadBuffer( GL_FRONT );
|
||||
DebugAssertNoGLError();
|
||||
|
||||
glReadPixels( 0, 0, g_pWind->GetActualVideoModeParams().width, g_pWind->GetActualVideoModeParams().height, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, image->pixels );
|
||||
DebugAssertNoGLError();
|
||||
glReadPixels( 0, 0, g_pWind->GetActualVideoModeParams().width, g_pWind->GetActualVideoModeParams().height, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, image->pixels );
|
||||
DebugAssertNoGLError();
|
||||
|
||||
RageSurfaceUtils::FlipVertically( image );
|
||||
RageSurfaceUtils::FlipVertically( image );
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
@@ -865,7 +943,7 @@ RageSurface *RageDisplay_Legacy::GetTexture( unsigned iTexture )
|
||||
return pImage;
|
||||
}
|
||||
|
||||
VideoModeParams RageDisplay_Legacy::GetActualVideoModeParams() const
|
||||
ActualVideoModeParams RageDisplay_Legacy::GetActualVideoModeParams() const
|
||||
{
|
||||
return g_pWind->GetActualVideoModeParams();
|
||||
}
|
||||
@@ -2483,6 +2561,14 @@ bool RageDisplay_Legacy::SupportsRenderToTexture() const
|
||||
return GLEW_EXT_framebuffer_object || g_pWind->SupportsRenderToTexture();
|
||||
}
|
||||
|
||||
bool RageDisplay_Legacy::SupportsFullscreenBorderlessWindow() const
|
||||
{
|
||||
// In order to support FSBW, we're going to need the LowLevelWindow implementation
|
||||
// to support creating a fullscreen borderless window, and we're going to need
|
||||
// RenderToTexture support in order to render in alternative resolutions
|
||||
return g_pWind->SupportsFullscreenBorderlessWindow() && SupportsRenderToTexture();
|
||||
}
|
||||
|
||||
/*
|
||||
* Render-to-texture can be implemented in several ways: the generic GL_ARB_pixel_buffer_object,
|
||||
* or platform-specifically. PBO is not available on all hardware that supports RTT,
|
||||
@@ -2525,8 +2611,8 @@ void RageDisplay_Legacy::SetRenderTarget( unsigned iTexture, bool bPreserveTextu
|
||||
DISPLAY->CameraPopMatrix();
|
||||
|
||||
/* Reset the viewport. */
|
||||
int fWidth = g_pWind->GetActualVideoModeParams().width;
|
||||
int fHeight = g_pWind->GetActualVideoModeParams().height;
|
||||
int fWidth = g_pWind->GetActualVideoModeParams().windowWidth;
|
||||
int fHeight = g_pWind->GetActualVideoModeParams().windowHeight;
|
||||
glViewport( 0, 0, fWidth, fHeight );
|
||||
|
||||
if (g_pCurrentRenderTarget)
|
||||
|
||||
Reference in New Issue
Block a user