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:
Drew Barbarello
2017-06-18 08:55:16 -07:00
committed by Colby Klein
parent 7ef14c340d
commit 557be7cf1b
57 changed files with 2616 additions and 370 deletions
+106 -20
View File
@@ -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)