Enable support for unity builds
This commit is contained in:
parent
47a4e88704
commit
f162b3a037
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -17,10 +17,12 @@ jobs:
|
|||||||
- { name: Linux Clang, os: ubuntu-latest, flags: -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ }
|
- { name: Linux Clang, os: ubuntu-latest, flags: -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ }
|
||||||
- { name: MacOS XCode, os: macos-latest }
|
- { name: MacOS XCode, os: macos-latest }
|
||||||
config:
|
config:
|
||||||
- { name: Shared, flags: -DBUILD_SHARED_LIBS=TRUE }
|
- { name: Shared, flags: -DBUILD_SHARED_LIBS=TRUE }
|
||||||
- { name: Static, flags: -DBUILD_SHARED_LIBS=FALSE }
|
- { name: Static, flags: -DBUILD_SHARED_LIBS=FALSE }
|
||||||
|
|
||||||
include:
|
include:
|
||||||
|
- platform: { name: Windows VS2019, os: windows-latest }
|
||||||
|
config: { name: Unity, flags: -DBUILD_SHARED_LIBS=TRUE -DCMAKE_UNITY_BUILD=ON }
|
||||||
- platform: { name: MacOS XCode, os: macos-latest }
|
- platform: { name: MacOS XCode, os: macos-latest }
|
||||||
config: { name: Frameworks, flags: -DSFML_BUILD_FRAMEWORKS=TRUE }
|
config: { name: Frameworks, flags: -DSFML_BUILD_FRAMEWORKS=TRUE }
|
||||||
- platform: { name: MacOS XCode, os: macos-latest }
|
- platform: { name: MacOS XCode, os: macos-latest }
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
const sf::Uint8 audioData = 1;
|
const sf::Uint8 clientAudioData = 1;
|
||||||
const sf::Uint8 endOfStream = 2;
|
const sf::Uint8 clientEndOfStream = 2;
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -71,7 +71,7 @@ private:
|
|||||||
{
|
{
|
||||||
// Pack the audio samples into a network packet
|
// Pack the audio samples into a network packet
|
||||||
sf::Packet packet;
|
sf::Packet packet;
|
||||||
packet << audioData;
|
packet << clientAudioData;
|
||||||
packet.append(samples, sampleCount * sizeof(sf::Int16));
|
packet.append(samples, sampleCount * sizeof(sf::Int16));
|
||||||
|
|
||||||
// Send the audio packet to the server
|
// Send the audio packet to the server
|
||||||
@ -86,7 +86,7 @@ private:
|
|||||||
{
|
{
|
||||||
// Send a "end-of-stream" packet
|
// Send a "end-of-stream" packet
|
||||||
sf::Packet packet;
|
sf::Packet packet;
|
||||||
packet << endOfStream;
|
packet << clientEndOfStream;
|
||||||
m_socket.send(packet);
|
m_socket.send(packet);
|
||||||
|
|
||||||
// Close the socket
|
// Close the socket
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
|
|
||||||
const sf::Uint8 audioData = 1;
|
const sf::Uint8 serverAudioData = 1;
|
||||||
const sf::Uint8 endOfStream = 2;
|
const sf::Uint8 serverEndOfStream = 2;
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -123,7 +123,7 @@ private:
|
|||||||
sf::Uint8 id;
|
sf::Uint8 id;
|
||||||
packet >> id;
|
packet >> id;
|
||||||
|
|
||||||
if (id == audioData)
|
if (id == serverAudioData)
|
||||||
{
|
{
|
||||||
// Extract audio samples from the packet, and append it to our samples buffer
|
// Extract audio samples from the packet, and append it to our samples buffer
|
||||||
const sf::Int16* samples = reinterpret_cast<const sf::Int16*>(static_cast<const char*>(packet.getData()) + 1);
|
const sf::Int16* samples = reinterpret_cast<const sf::Int16*>(static_cast<const char*>(packet.getData()) + 1);
|
||||||
@ -136,7 +136,7 @@ private:
|
|||||||
std::copy(samples, samples + sampleCount, std::back_inserter(m_samples));
|
std::copy(samples, samples + sampleCount, std::back_inserter(m_samples));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (id == endOfStream)
|
else if (id == serverEndOfStream)
|
||||||
{
|
{
|
||||||
// End of stream reached: we stop receiving audio data
|
// End of stream reached: we stop receiving audio data
|
||||||
std::cout << "Audio data has been 100% received!" << std::endl;
|
std::cout << "Audio data has been 100% received!" << std::endl;
|
||||||
|
@ -25,11 +25,18 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#define SF_GLAD_GL_IMPLEMENTATION
|
|
||||||
#include <SFML/Graphics/GLExtensions.hpp>
|
#include <SFML/Graphics/GLExtensions.hpp>
|
||||||
#include <SFML/Window/Context.hpp>
|
#include <SFML/Window/Context.hpp>
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
|
|
||||||
|
// We check for this definition in order to avoid multiple definitions of GLAD
|
||||||
|
// entities during unity builds of SFML.
|
||||||
|
#ifndef SF_GLAD_GL_IMPLEMENTATION_INCLUDED
|
||||||
|
#define SF_GLAD_GL_IMPLEMENTATION_INCLUDED
|
||||||
|
#define SF_GLAD_GL_IMPLEMENTATION
|
||||||
|
#include <glad/gl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(GL_MAJOR_VERSION)
|
#if !defined(GL_MAJOR_VERSION)
|
||||||
#define GL_MAJOR_VERSION 0x821B
|
#define GL_MAJOR_VERSION 0x821B
|
||||||
#endif
|
#endif
|
||||||
|
@ -52,95 +52,99 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
// Mutex to protect ID generation and our context-RenderTarget-map
|
// A nested named namespace is used here to allow unity builds of SFML.
|
||||||
sf::Mutex mutex;
|
namespace RenderTargetImpl
|
||||||
|
|
||||||
// Unique identifier, used for identifying RenderTargets when
|
|
||||||
// tracking the currently active RenderTarget within a given context
|
|
||||||
sf::Uint64 getUniqueId()
|
|
||||||
{
|
{
|
||||||
sf::Lock lock(mutex);
|
// Mutex to protect ID generation and our context-RenderTarget-map
|
||||||
|
sf::Mutex mutex;
|
||||||
|
|
||||||
static sf::Uint64 id = 1; // start at 1, zero is "no RenderTarget"
|
// Unique identifier, used for identifying RenderTargets when
|
||||||
|
// tracking the currently active RenderTarget within a given context
|
||||||
return id++;
|
sf::Uint64 getUniqueId()
|
||||||
}
|
|
||||||
|
|
||||||
// Map to help us detect whether a different RenderTarget
|
|
||||||
// has been activated within a single context
|
|
||||||
typedef std::map<sf::Uint64, sf::Uint64> ContextRenderTargetMap;
|
|
||||||
ContextRenderTargetMap contextRenderTargetMap;
|
|
||||||
|
|
||||||
// Check if a RenderTarget with the given ID is active in the current context
|
|
||||||
bool isActive(sf::Uint64 id)
|
|
||||||
{
|
|
||||||
ContextRenderTargetMap::iterator iter = contextRenderTargetMap.find(sf::Context::getActiveContextId());
|
|
||||||
|
|
||||||
if ((iter == contextRenderTargetMap.end()) || (iter->second != id))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert an sf::BlendMode::Factor constant to the corresponding OpenGL constant.
|
|
||||||
sf::Uint32 factorToGlConstant(sf::BlendMode::Factor blendFactor)
|
|
||||||
{
|
|
||||||
switch (blendFactor)
|
|
||||||
{
|
{
|
||||||
case sf::BlendMode::Zero: return GL_ZERO;
|
sf::Lock lock(mutex);
|
||||||
case sf::BlendMode::One: return GL_ONE;
|
|
||||||
case sf::BlendMode::SrcColor: return GL_SRC_COLOR;
|
static sf::Uint64 id = 1; // start at 1, zero is "no RenderTarget"
|
||||||
case sf::BlendMode::OneMinusSrcColor: return GL_ONE_MINUS_SRC_COLOR;
|
|
||||||
case sf::BlendMode::DstColor: return GL_DST_COLOR;
|
return id++;
|
||||||
case sf::BlendMode::OneMinusDstColor: return GL_ONE_MINUS_DST_COLOR;
|
|
||||||
case sf::BlendMode::SrcAlpha: return GL_SRC_ALPHA;
|
|
||||||
case sf::BlendMode::OneMinusSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA;
|
|
||||||
case sf::BlendMode::DstAlpha: return GL_DST_ALPHA;
|
|
||||||
case sf::BlendMode::OneMinusDstAlpha: return GL_ONE_MINUS_DST_ALPHA;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sf::err() << "Invalid value for sf::BlendMode::Factor! Fallback to sf::BlendMode::Zero." << std::endl;
|
// Map to help us detect whether a different RenderTarget
|
||||||
assert(false);
|
// has been activated within a single context
|
||||||
return GL_ZERO;
|
typedef std::map<sf::Uint64, sf::Uint64> ContextRenderTargetMap;
|
||||||
}
|
ContextRenderTargetMap contextRenderTargetMap;
|
||||||
|
|
||||||
|
// Check if a RenderTarget with the given ID is active in the current context
|
||||||
// Convert an sf::BlendMode::BlendEquation constant to the corresponding OpenGL constant.
|
bool isActive(sf::Uint64 id)
|
||||||
sf::Uint32 equationToGlConstant(sf::BlendMode::Equation blendEquation)
|
|
||||||
{
|
|
||||||
switch (blendEquation)
|
|
||||||
{
|
{
|
||||||
case sf::BlendMode::Add:
|
ContextRenderTargetMap::iterator iter = contextRenderTargetMap.find(sf::Context::getActiveContextId());
|
||||||
return GLEXT_GL_FUNC_ADD;
|
|
||||||
case sf::BlendMode::Subtract:
|
if ((iter == contextRenderTargetMap.end()) || (iter->second != id))
|
||||||
if (GLEXT_blend_subtract)
|
return false;
|
||||||
return GLEXT_GL_FUNC_SUBTRACT;
|
|
||||||
break;
|
return true;
|
||||||
case sf::BlendMode::ReverseSubtract:
|
|
||||||
if (GLEXT_blend_subtract)
|
|
||||||
return GLEXT_GL_FUNC_REVERSE_SUBTRACT;
|
|
||||||
break;
|
|
||||||
case sf::BlendMode::Min:
|
|
||||||
if (GLEXT_blend_minmax)
|
|
||||||
return GLEXT_GL_MIN;
|
|
||||||
break;
|
|
||||||
case sf::BlendMode::Max:
|
|
||||||
if (GLEXT_blend_minmax)
|
|
||||||
return GLEXT_GL_MAX;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool warned = false;
|
// Convert an sf::BlendMode::Factor constant to the corresponding OpenGL constant.
|
||||||
if (!warned)
|
sf::Uint32 factorToGlConstant(sf::BlendMode::Factor blendFactor)
|
||||||
{
|
{
|
||||||
sf::err() << "OpenGL extension EXT_blend_minmax or EXT_blend_subtract unavailable" << std::endl;
|
switch (blendFactor)
|
||||||
sf::err() << "Some blending equations will fallback to sf::BlendMode::Add" << std::endl;
|
{
|
||||||
sf::err() << "Ensure that hardware acceleration is enabled if available" << std::endl;
|
case sf::BlendMode::Zero: return GL_ZERO;
|
||||||
|
case sf::BlendMode::One: return GL_ONE;
|
||||||
|
case sf::BlendMode::SrcColor: return GL_SRC_COLOR;
|
||||||
|
case sf::BlendMode::OneMinusSrcColor: return GL_ONE_MINUS_SRC_COLOR;
|
||||||
|
case sf::BlendMode::DstColor: return GL_DST_COLOR;
|
||||||
|
case sf::BlendMode::OneMinusDstColor: return GL_ONE_MINUS_DST_COLOR;
|
||||||
|
case sf::BlendMode::SrcAlpha: return GL_SRC_ALPHA;
|
||||||
|
case sf::BlendMode::OneMinusSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA;
|
||||||
|
case sf::BlendMode::DstAlpha: return GL_DST_ALPHA;
|
||||||
|
case sf::BlendMode::OneMinusDstAlpha: return GL_ONE_MINUS_DST_ALPHA;
|
||||||
|
}
|
||||||
|
|
||||||
warned = true;
|
sf::err() << "Invalid value for sf::BlendMode::Factor! Fallback to sf::BlendMode::Zero." << std::endl;
|
||||||
|
assert(false);
|
||||||
|
return GL_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLEXT_GL_FUNC_ADD;
|
|
||||||
|
// Convert an sf::BlendMode::BlendEquation constant to the corresponding OpenGL constant.
|
||||||
|
sf::Uint32 equationToGlConstant(sf::BlendMode::Equation blendEquation)
|
||||||
|
{
|
||||||
|
switch (blendEquation)
|
||||||
|
{
|
||||||
|
case sf::BlendMode::Add:
|
||||||
|
return GLEXT_GL_FUNC_ADD;
|
||||||
|
case sf::BlendMode::Subtract:
|
||||||
|
if (GLEXT_blend_subtract)
|
||||||
|
return GLEXT_GL_FUNC_SUBTRACT;
|
||||||
|
break;
|
||||||
|
case sf::BlendMode::ReverseSubtract:
|
||||||
|
if (GLEXT_blend_subtract)
|
||||||
|
return GLEXT_GL_FUNC_REVERSE_SUBTRACT;
|
||||||
|
break;
|
||||||
|
case sf::BlendMode::Min:
|
||||||
|
if (GLEXT_blend_minmax)
|
||||||
|
return GLEXT_GL_MIN;
|
||||||
|
break;
|
||||||
|
case sf::BlendMode::Max:
|
||||||
|
if (GLEXT_blend_minmax)
|
||||||
|
return GLEXT_GL_MAX;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool warned = false;
|
||||||
|
if (!warned)
|
||||||
|
{
|
||||||
|
sf::err() << "OpenGL extension EXT_blend_minmax or EXT_blend_subtract unavailable" << std::endl;
|
||||||
|
sf::err() << "Some blending equations will fallback to sf::BlendMode::Add" << std::endl;
|
||||||
|
sf::err() << "Ensure that hardware acceleration is enabled if available" << std::endl;
|
||||||
|
|
||||||
|
warned = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLEXT_GL_FUNC_ADD;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,7 +171,7 @@ RenderTarget::~RenderTarget()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void RenderTarget::clear(const Color& color)
|
void RenderTarget::clear(const Color& color)
|
||||||
{
|
{
|
||||||
if (isActive(m_id) || setActive(true))
|
if (RenderTargetImpl::isActive(m_id) || setActive(true))
|
||||||
{
|
{
|
||||||
// Unbind texture to fix RenderTexture preventing clear
|
// Unbind texture to fix RenderTexture preventing clear
|
||||||
applyTexture(NULL);
|
applyTexture(NULL);
|
||||||
@ -282,7 +286,7 @@ void RenderTarget::draw(const Vertex* vertices, std::size_t vertexCount,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (isActive(m_id) || setActive(true))
|
if (RenderTargetImpl::isActive(m_id) || setActive(true))
|
||||||
{
|
{
|
||||||
// Check if the vertex count is low enough so that we can pre-transform them
|
// Check if the vertex count is low enough so that we can pre-transform them
|
||||||
bool useVertexCache = (vertexCount <= StatesCache::VertexCacheSize);
|
bool useVertexCache = (vertexCount <= StatesCache::VertexCacheSize);
|
||||||
@ -382,7 +386,7 @@ void RenderTarget::draw(const VertexBuffer& vertexBuffer, std::size_t firstVerte
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (isActive(m_id) || setActive(true))
|
if (RenderTargetImpl::isActive(m_id) || setActive(true))
|
||||||
{
|
{
|
||||||
setupDraw(false, states);
|
setupDraw(false, states);
|
||||||
|
|
||||||
@ -424,11 +428,12 @@ bool RenderTarget::setActive(bool active)
|
|||||||
{
|
{
|
||||||
// Mark this RenderTarget as active or no longer active in the tracking map
|
// Mark this RenderTarget as active or no longer active in the tracking map
|
||||||
{
|
{
|
||||||
sf::Lock lock(mutex);
|
sf::Lock lock(RenderTargetImpl::mutex);
|
||||||
|
|
||||||
Uint64 contextId = Context::getActiveContextId();
|
Uint64 contextId = Context::getActiveContextId();
|
||||||
|
|
||||||
ContextRenderTargetMap::iterator iter = contextRenderTargetMap.find(contextId);
|
using RenderTargetImpl::contextRenderTargetMap;
|
||||||
|
RenderTargetImpl::ContextRenderTargetMap::iterator iter = contextRenderTargetMap.find(contextId);
|
||||||
|
|
||||||
if (active)
|
if (active)
|
||||||
{
|
{
|
||||||
@ -462,7 +467,7 @@ bool RenderTarget::setActive(bool active)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void RenderTarget::pushGLStates()
|
void RenderTarget::pushGLStates()
|
||||||
{
|
{
|
||||||
if (isActive(m_id) || setActive(true))
|
if (RenderTargetImpl::isActive(m_id) || setActive(true))
|
||||||
{
|
{
|
||||||
#ifdef SFML_DEBUG
|
#ifdef SFML_DEBUG
|
||||||
// make sure that the user didn't leave an unchecked OpenGL error
|
// make sure that the user didn't leave an unchecked OpenGL error
|
||||||
@ -494,7 +499,7 @@ void RenderTarget::pushGLStates()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void RenderTarget::popGLStates()
|
void RenderTarget::popGLStates()
|
||||||
{
|
{
|
||||||
if (isActive(m_id) || setActive(true))
|
if (RenderTargetImpl::isActive(m_id) || setActive(true))
|
||||||
{
|
{
|
||||||
glCheck(glMatrixMode(GL_PROJECTION));
|
glCheck(glMatrixMode(GL_PROJECTION));
|
||||||
glCheck(glPopMatrix());
|
glCheck(glPopMatrix());
|
||||||
@ -523,7 +528,7 @@ void RenderTarget::resetGLStates()
|
|||||||
setActive(false);
|
setActive(false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (isActive(m_id) || setActive(true))
|
if (RenderTargetImpl::isActive(m_id) || setActive(true))
|
||||||
{
|
{
|
||||||
// Make sure that extensions are initialized
|
// Make sure that extensions are initialized
|
||||||
priv::ensureExtensionsInit();
|
priv::ensureExtensionsInit();
|
||||||
@ -582,7 +587,7 @@ void RenderTarget::initialize()
|
|||||||
|
|
||||||
// Generate a unique ID for this RenderTarget to track
|
// Generate a unique ID for this RenderTarget to track
|
||||||
// whether it is active within a specific context
|
// whether it is active within a specific context
|
||||||
m_id = getUniqueId();
|
m_id = RenderTargetImpl::getUniqueId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -608,6 +613,9 @@ void RenderTarget::applyCurrentView()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void RenderTarget::applyBlendMode(const BlendMode& mode)
|
void RenderTarget::applyBlendMode(const BlendMode& mode)
|
||||||
{
|
{
|
||||||
|
using RenderTargetImpl::factorToGlConstant;
|
||||||
|
using RenderTargetImpl::equationToGlConstant;
|
||||||
|
|
||||||
// Apply the blend mode, falling back to the non-separate versions if necessary
|
// Apply the blend mode, falling back to the non-separate versions if necessary
|
||||||
if (GLEXT_blend_func_separate)
|
if (GLEXT_blend_func_separate)
|
||||||
{
|
{
|
||||||
|
@ -40,18 +40,22 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
sf::Mutex idMutex;
|
// A nested named namespace is used here to allow unity builds of SFML.
|
||||||
sf::Mutex maximumSizeMutex;
|
namespace TextureImpl
|
||||||
|
|
||||||
// Thread-safe unique identifier generator,
|
|
||||||
// is used for states cache (see RenderTarget)
|
|
||||||
sf::Uint64 getUniqueId()
|
|
||||||
{
|
{
|
||||||
sf::Lock lock(idMutex);
|
sf::Mutex idMutex;
|
||||||
|
sf::Mutex maximumSizeMutex;
|
||||||
|
|
||||||
static sf::Uint64 id = 1; // start at 1, zero is "no texture"
|
// Thread-safe unique identifier generator,
|
||||||
|
// is used for states cache (see RenderTarget)
|
||||||
|
sf::Uint64 getUniqueId()
|
||||||
|
{
|
||||||
|
sf::Lock lock(idMutex);
|
||||||
|
|
||||||
return id++;
|
static sf::Uint64 id = 1; // start at 1, zero is "no texture"
|
||||||
|
|
||||||
|
return id++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +73,7 @@ m_isRepeated (false),
|
|||||||
m_pixelsFlipped(false),
|
m_pixelsFlipped(false),
|
||||||
m_fboAttachment(false),
|
m_fboAttachment(false),
|
||||||
m_hasMipmap (false),
|
m_hasMipmap (false),
|
||||||
m_cacheId (getUniqueId())
|
m_cacheId (TextureImpl::getUniqueId())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +89,7 @@ m_isRepeated (copy.m_isRepeated),
|
|||||||
m_pixelsFlipped(false),
|
m_pixelsFlipped(false),
|
||||||
m_fboAttachment(false),
|
m_fboAttachment(false),
|
||||||
m_hasMipmap (false),
|
m_hasMipmap (false),
|
||||||
m_cacheId (getUniqueId())
|
m_cacheId (TextureImpl::getUniqueId())
|
||||||
{
|
{
|
||||||
if (copy.m_texture)
|
if (copy.m_texture)
|
||||||
{
|
{
|
||||||
@ -206,7 +210,7 @@ bool Texture::create(unsigned int width, unsigned int height)
|
|||||||
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_isRepeated ? GL_REPEAT : (textureEdgeClamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP)));
|
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_isRepeated ? GL_REPEAT : (textureEdgeClamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP)));
|
||||||
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST));
|
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST));
|
||||||
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST));
|
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST));
|
||||||
m_cacheId = getUniqueId();
|
m_cacheId = TextureImpl::getUniqueId();
|
||||||
|
|
||||||
m_hasMipmap = false;
|
m_hasMipmap = false;
|
||||||
|
|
||||||
@ -422,7 +426,7 @@ void Texture::update(const Uint8* pixels, unsigned int width, unsigned int heigh
|
|||||||
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST));
|
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST));
|
||||||
m_hasMipmap = false;
|
m_hasMipmap = false;
|
||||||
m_pixelsFlipped = false;
|
m_pixelsFlipped = false;
|
||||||
m_cacheId = getUniqueId();
|
m_cacheId = TextureImpl::getUniqueId();
|
||||||
|
|
||||||
// Force an OpenGL flush, so that the texture data will appear updated
|
// Force an OpenGL flush, so that the texture data will appear updated
|
||||||
// in all contexts immediately (solves problems in multi-threaded apps)
|
// in all contexts immediately (solves problems in multi-threaded apps)
|
||||||
@ -525,7 +529,7 @@ void Texture::update(const Texture& texture, unsigned int x, unsigned int y)
|
|||||||
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST));
|
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST));
|
||||||
m_hasMipmap = false;
|
m_hasMipmap = false;
|
||||||
m_pixelsFlipped = false;
|
m_pixelsFlipped = false;
|
||||||
m_cacheId = getUniqueId();
|
m_cacheId = TextureImpl::getUniqueId();
|
||||||
|
|
||||||
// Force an OpenGL flush, so that the texture data will appear updated
|
// Force an OpenGL flush, so that the texture data will appear updated
|
||||||
// in all contexts immediately (solves problems in multi-threaded apps)
|
// in all contexts immediately (solves problems in multi-threaded apps)
|
||||||
@ -581,7 +585,7 @@ void Texture::update(const Window& window, unsigned int x, unsigned int y)
|
|||||||
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST));
|
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST));
|
||||||
m_hasMipmap = false;
|
m_hasMipmap = false;
|
||||||
m_pixelsFlipped = true;
|
m_pixelsFlipped = true;
|
||||||
m_cacheId = getUniqueId();
|
m_cacheId = TextureImpl::getUniqueId();
|
||||||
|
|
||||||
// Force an OpenGL flush, so that the texture will appear updated
|
// Force an OpenGL flush, so that the texture will appear updated
|
||||||
// in all contexts immediately (solves problems in multi-threaded apps)
|
// in all contexts immediately (solves problems in multi-threaded apps)
|
||||||
@ -790,7 +794,7 @@ void Texture::bind(const Texture* texture, CoordinateType coordinateType)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int Texture::getMaximumSize()
|
unsigned int Texture::getMaximumSize()
|
||||||
{
|
{
|
||||||
Lock lock(maximumSizeMutex);
|
Lock lock(TextureImpl::maximumSizeMutex);
|
||||||
|
|
||||||
static bool checked = false;
|
static bool checked = false;
|
||||||
static GLint size = 0;
|
static GLint size = 0;
|
||||||
@ -832,8 +836,8 @@ void Texture::swap(Texture& right)
|
|||||||
std::swap(m_fboAttachment, right.m_fboAttachment);
|
std::swap(m_fboAttachment, right.m_fboAttachment);
|
||||||
std::swap(m_hasMipmap, right.m_hasMipmap);
|
std::swap(m_hasMipmap, right.m_hasMipmap);
|
||||||
|
|
||||||
m_cacheId = getUniqueId();
|
m_cacheId = TextureImpl::getUniqueId();
|
||||||
right.m_cacheId = getUniqueId();
|
right.m_cacheId = TextureImpl::getUniqueId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,15 +36,19 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
sf::Mutex isAvailableMutex;
|
// A nested named namespace is used here to allow unity builds of SFML.
|
||||||
|
namespace VertexBufferImpl
|
||||||
GLenum usageToGlEnum(sf::VertexBuffer::Usage usage)
|
|
||||||
{
|
{
|
||||||
switch (usage)
|
sf::Mutex isAvailableMutex;
|
||||||
|
|
||||||
|
GLenum usageToGlEnum(sf::VertexBuffer::Usage usage)
|
||||||
{
|
{
|
||||||
case sf::VertexBuffer::Static: return GLEXT_GL_STATIC_DRAW;
|
switch (usage)
|
||||||
case sf::VertexBuffer::Dynamic: return GLEXT_GL_DYNAMIC_DRAW;
|
{
|
||||||
default: return GLEXT_GL_STREAM_DRAW;
|
case sf::VertexBuffer::Static: return GLEXT_GL_STATIC_DRAW;
|
||||||
|
case sf::VertexBuffer::Dynamic: return GLEXT_GL_DYNAMIC_DRAW;
|
||||||
|
default: return GLEXT_GL_STREAM_DRAW;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,7 +147,7 @@ bool VertexBuffer::create(std::size_t vertexCount)
|
|||||||
}
|
}
|
||||||
|
|
||||||
glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, m_buffer));
|
glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, m_buffer));
|
||||||
glCheck(GLEXT_glBufferData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * vertexCount, 0, usageToGlEnum(m_usage)));
|
glCheck(GLEXT_glBufferData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * vertexCount, 0, VertexBufferImpl::usageToGlEnum(m_usage)));
|
||||||
glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, 0));
|
glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, 0));
|
||||||
|
|
||||||
m_size = vertexCount;
|
m_size = vertexCount;
|
||||||
@ -186,7 +190,7 @@ bool VertexBuffer::update(const Vertex* vertices, std::size_t vertexCount, unsig
|
|||||||
// Check if we need to resize or orphan the buffer
|
// Check if we need to resize or orphan the buffer
|
||||||
if (vertexCount >= m_size)
|
if (vertexCount >= m_size)
|
||||||
{
|
{
|
||||||
glCheck(GLEXT_glBufferData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * vertexCount, 0, usageToGlEnum(m_usage)));
|
glCheck(GLEXT_glBufferData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * vertexCount, 0, VertexBufferImpl::usageToGlEnum(m_usage)));
|
||||||
|
|
||||||
m_size = vertexCount;
|
m_size = vertexCount;
|
||||||
}
|
}
|
||||||
@ -230,7 +234,7 @@ bool VertexBuffer::update(const VertexBuffer& vertexBuffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, m_buffer));
|
glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, m_buffer));
|
||||||
glCheck(GLEXT_glBufferData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * vertexBuffer.m_size, 0, usageToGlEnum(m_usage)));
|
glCheck(GLEXT_glBufferData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * vertexBuffer.m_size, 0, VertexBufferImpl::usageToGlEnum(m_usage)));
|
||||||
|
|
||||||
void* destination = 0;
|
void* destination = 0;
|
||||||
glCheck(destination = GLEXT_glMapBuffer(GLEXT_GL_ARRAY_BUFFER, GLEXT_GL_WRITE_ONLY));
|
glCheck(destination = GLEXT_glMapBuffer(GLEXT_GL_ARRAY_BUFFER, GLEXT_GL_WRITE_ONLY));
|
||||||
@ -332,7 +336,7 @@ VertexBuffer::Usage VertexBuffer::getUsage() const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool VertexBuffer::isAvailable()
|
bool VertexBuffer::isAvailable()
|
||||||
{
|
{
|
||||||
Lock lock(isAvailableMutex);
|
Lock lock(VertexBufferImpl::isAvailableMutex);
|
||||||
|
|
||||||
static bool checked = false;
|
static bool checked = false;
|
||||||
static bool available = false;
|
static bool available = false;
|
||||||
|
@ -32,8 +32,12 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
// This per-thread variable holds the last activated sf::Context for each thread
|
// A nested named namespace is used here to allow unity builds of SFML.
|
||||||
sf::ThreadLocalPtr<sf::Context> currentContext(NULL);
|
namespace ContextImpl
|
||||||
|
{
|
||||||
|
// This per-thread variable holds the current context for each thread
|
||||||
|
sf::ThreadLocalPtr<sf::Context> currentContext(NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
@ -60,7 +64,7 @@ bool Context::setActive(bool active)
|
|||||||
bool result = m_context->setActive(active);
|
bool result = m_context->setActive(active);
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
currentContext = (active ? this : NULL);
|
ContextImpl::currentContext = (active ? this : NULL);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -76,6 +80,8 @@ const ContextSettings& Context::getSettings() const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
const Context* Context::getActiveContext()
|
const Context* Context::getActiveContext()
|
||||||
{
|
{
|
||||||
|
using ContextImpl::currentContext;
|
||||||
|
|
||||||
// We have to check that the last activated sf::Context is still active (a RenderTarget activation may have deactivated it)
|
// We have to check that the last activated sf::Context is still active (a RenderTarget activation may have deactivated it)
|
||||||
if (currentContext && currentContext->m_context == priv::GlContext::getActiveContext())
|
if (currentContext && currentContext->m_context == priv::GlContext::getActiveContext())
|
||||||
return currentContext;
|
return currentContext;
|
||||||
|
@ -39,49 +39,58 @@
|
|||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// We check for this definition in order to avoid multiple definitions of GLAD
|
||||||
|
// entities during unity builds of SFML.
|
||||||
|
#ifndef SF_GLAD_EGL_IMPLEMENTATION_INCLUDED
|
||||||
|
#define SF_GLAD_EGL_IMPLEMENTATION_INCLUDED
|
||||||
#define SF_GLAD_EGL_IMPLEMENTATION
|
#define SF_GLAD_EGL_IMPLEMENTATION
|
||||||
#include <glad/egl.h>
|
#include <glad/egl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
EGLDisplay getInitializedDisplay()
|
// A nested named namespace is used here to allow unity builds of SFML.
|
||||||
|
namespace EglContextImpl
|
||||||
{
|
{
|
||||||
|
EGLDisplay getInitializedDisplay()
|
||||||
|
{
|
||||||
#if defined(SFML_SYSTEM_ANDROID)
|
#if defined(SFML_SYSTEM_ANDROID)
|
||||||
|
|
||||||
// On Android, its native activity handles this for us
|
// On Android, its native activity handles this for us
|
||||||
sf::priv::ActivityStates* states = sf::priv::getActivity(NULL);
|
sf::priv::ActivityStates* states = sf::priv::getActivity(NULL);
|
||||||
sf::Lock lock(states->mutex);
|
sf::Lock lock(states->mutex);
|
||||||
|
|
||||||
return states->display;
|
return states->display;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static EGLDisplay display = EGL_NO_DISPLAY;
|
static EGLDisplay display = EGL_NO_DISPLAY;
|
||||||
|
|
||||||
if (display == EGL_NO_DISPLAY)
|
if (display == EGL_NO_DISPLAY)
|
||||||
{
|
{
|
||||||
eglCheck(display = eglGetDisplay(EGL_DEFAULT_DISPLAY));
|
eglCheck(display = eglGetDisplay(EGL_DEFAULT_DISPLAY));
|
||||||
eglCheck(eglInitialize(display, NULL, NULL));
|
eglCheck(eglInitialize(display, NULL, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
return display;
|
||||||
}
|
}
|
||||||
|
|
||||||
return display;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
////////////////////////////////////////////////////////////
|
void ensureInit()
|
||||||
void ensureInit()
|
|
||||||
{
|
|
||||||
static bool initialized = false;
|
|
||||||
if (!initialized)
|
|
||||||
{
|
{
|
||||||
initialized = true;
|
static bool initialized = false;
|
||||||
|
if (!initialized)
|
||||||
|
{
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
// We don't check the return value since the extension
|
// We don't check the return value since the extension
|
||||||
// flags are cleared even if loading fails
|
// flags are cleared even if loading fails
|
||||||
gladLoaderLoadEGL(EGL_NO_DISPLAY);
|
gladLoaderLoadEGL(EGL_NO_DISPLAY);
|
||||||
|
|
||||||
// Continue loading with a display
|
// Continue loading with a display
|
||||||
gladLoaderLoadEGL(getInitializedDisplay());
|
gladLoaderLoadEGL(getInitializedDisplay());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -98,10 +107,10 @@ m_context (EGL_NO_CONTEXT),
|
|||||||
m_surface (EGL_NO_SURFACE),
|
m_surface (EGL_NO_SURFACE),
|
||||||
m_config (NULL)
|
m_config (NULL)
|
||||||
{
|
{
|
||||||
ensureInit();
|
EglContextImpl::ensureInit();
|
||||||
|
|
||||||
// Get the initialized EGL display
|
// Get the initialized EGL display
|
||||||
m_display = getInitializedDisplay();
|
m_display = EglContextImpl::getInitializedDisplay();
|
||||||
|
|
||||||
// Get the best EGL config matching the default video settings
|
// Get the best EGL config matching the default video settings
|
||||||
m_config = getBestConfig(m_display, VideoMode::getDesktopMode().bitsPerPixel, ContextSettings());
|
m_config = getBestConfig(m_display, VideoMode::getDesktopMode().bitsPerPixel, ContextSettings());
|
||||||
@ -129,7 +138,7 @@ m_context (EGL_NO_CONTEXT),
|
|||||||
m_surface (EGL_NO_SURFACE),
|
m_surface (EGL_NO_SURFACE),
|
||||||
m_config (NULL)
|
m_config (NULL)
|
||||||
{
|
{
|
||||||
ensureInit();
|
EglContextImpl::ensureInit();
|
||||||
|
|
||||||
#ifdef SFML_SYSTEM_ANDROID
|
#ifdef SFML_SYSTEM_ANDROID
|
||||||
|
|
||||||
@ -142,7 +151,7 @@ m_config (NULL)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Get the initialized EGL display
|
// Get the initialized EGL display
|
||||||
m_display = getInitializedDisplay();
|
m_display = EglContextImpl::getInitializedDisplay();
|
||||||
|
|
||||||
// Get the best EGL config matching the requested video settings
|
// Get the best EGL config matching the requested video settings
|
||||||
m_config = getBestConfig(m_display, bitsPerPixel, settings);
|
m_config = getBestConfig(m_display, bitsPerPixel, settings);
|
||||||
@ -166,7 +175,7 @@ m_context (EGL_NO_CONTEXT),
|
|||||||
m_surface (EGL_NO_SURFACE),
|
m_surface (EGL_NO_SURFACE),
|
||||||
m_config (NULL)
|
m_config (NULL)
|
||||||
{
|
{
|
||||||
ensureInit();
|
EglContextImpl::ensureInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -202,7 +211,7 @@ EglContext::~EglContext()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
GlFunctionPointer EglContext::getFunction(const char* name)
|
GlFunctionPointer EglContext::getFunction(const char* name)
|
||||||
{
|
{
|
||||||
ensureInit();
|
EglContextImpl::ensureInit();
|
||||||
|
|
||||||
return reinterpret_cast<GlFunctionPointer>(eglGetProcAddress(name));
|
return reinterpret_cast<GlFunctionPointer>(eglGetProcAddress(name));
|
||||||
}
|
}
|
||||||
@ -288,7 +297,7 @@ void EglContext::destroySurface()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
EGLConfig EglContext::getBestConfig(EGLDisplay display, unsigned int bitsPerPixel, const ContextSettings& settings)
|
EGLConfig EglContext::getBestConfig(EGLDisplay display, unsigned int bitsPerPixel, const ContextSettings& settings)
|
||||||
{
|
{
|
||||||
ensureInit();
|
EglContextImpl::ensureInit();
|
||||||
|
|
||||||
// Set our video settings constraint
|
// Set our video settings constraint
|
||||||
const EGLint attributes[] = {
|
const EGLint attributes[] = {
|
||||||
@ -352,10 +361,10 @@ void EglContext::updateSettings()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
XVisualInfo EglContext::selectBestVisual(::Display* XDisplay, unsigned int bitsPerPixel, const ContextSettings& settings)
|
XVisualInfo EglContext::selectBestVisual(::Display* XDisplay, unsigned int bitsPerPixel, const ContextSettings& settings)
|
||||||
{
|
{
|
||||||
ensureInit();
|
EglContextImpl::ensureInit();
|
||||||
|
|
||||||
// Get the initialized EGL display
|
// Get the initialized EGL display
|
||||||
EGLDisplay display = getInitializedDisplay();
|
EGLDisplay display = EglContextImpl::getInitializedDisplay();
|
||||||
|
|
||||||
// Get the best EGL config matching the default video settings
|
// Get the best EGL config matching the default video settings
|
||||||
EGLConfig config = getBestConfig(display, bitsPerPixel, settings);
|
EGLConfig config = getBestConfig(display, bitsPerPixel, settings);
|
||||||
|
@ -149,158 +149,162 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
// AMD drivers have issues with internal synchronization
|
// A nested named namespace is used here to allow unity builds of SFML.
|
||||||
// We need to make sure that no operating system context
|
namespace GlContextImpl
|
||||||
// or pixel format operations are performed simultaneously
|
|
||||||
// This mutex is also used to protect the shared context
|
|
||||||
// from being locked on multiple threads and for managing
|
|
||||||
// the resource count
|
|
||||||
sf::Mutex mutex;
|
|
||||||
|
|
||||||
// OpenGL resources counter
|
|
||||||
unsigned int resourceCount = 0;
|
|
||||||
|
|
||||||
// This per-thread variable holds the current context for each thread
|
|
||||||
sf::ThreadLocalPtr<sf::priv::GlContext> currentContext(NULL);
|
|
||||||
|
|
||||||
// The hidden, inactive context that will be shared with all other contexts
|
|
||||||
ContextType* sharedContext = NULL;
|
|
||||||
|
|
||||||
// Unique identifier, used for identifying contexts when managing unshareable OpenGL resources
|
|
||||||
sf::Uint64 id = 1; // start at 1, zero is "no context"
|
|
||||||
|
|
||||||
// Set containing callback functions to be called whenever a
|
|
||||||
// context is going to be destroyed
|
|
||||||
// Unshareable OpenGL resources rely on this to clean up properly
|
|
||||||
// whenever a context containing them is destroyed
|
|
||||||
typedef std::set<std::pair<sf::ContextDestroyCallback, void*> > ContextDestroyCallbacks;
|
|
||||||
ContextDestroyCallbacks contextDestroyCallbacks;
|
|
||||||
|
|
||||||
// This structure contains all the state necessary to
|
|
||||||
// track TransientContext usage
|
|
||||||
struct TransientContext : private sf::NonCopyable
|
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
// AMD drivers have issues with internal synchronization
|
||||||
/// \brief Constructor
|
// We need to make sure that no operating system context
|
||||||
///
|
// or pixel format operations are performed simultaneously
|
||||||
////////////////////////////////////////////////////////////
|
// This mutex is also used to protect the shared context
|
||||||
TransientContext() :
|
// from being locked on multiple threads and for managing
|
||||||
referenceCount (0),
|
// the resource count
|
||||||
context (0),
|
sf::Mutex mutex;
|
||||||
sharedContextLock(0),
|
|
||||||
useSharedContext (false)
|
// OpenGL resources counter
|
||||||
|
unsigned int resourceCount = 0;
|
||||||
|
|
||||||
|
// This per-thread variable holds the current context for each thread
|
||||||
|
sf::ThreadLocalPtr<sf::priv::GlContext> currentContext(NULL);
|
||||||
|
|
||||||
|
// The hidden, inactive context that will be shared with all other contexts
|
||||||
|
ContextType* sharedContext = NULL;
|
||||||
|
|
||||||
|
// Unique identifier, used for identifying contexts when managing unshareable OpenGL resources
|
||||||
|
sf::Uint64 id = 1; // start at 1, zero is "no context"
|
||||||
|
|
||||||
|
// Set containing callback functions to be called whenever a
|
||||||
|
// context is going to be destroyed
|
||||||
|
// Unshareable OpenGL resources rely on this to clean up properly
|
||||||
|
// whenever a context containing them is destroyed
|
||||||
|
typedef std::set<std::pair<sf::ContextDestroyCallback, void*> > ContextDestroyCallbacks;
|
||||||
|
ContextDestroyCallbacks contextDestroyCallbacks;
|
||||||
|
|
||||||
|
// This structure contains all the state necessary to
|
||||||
|
// track TransientContext usage
|
||||||
|
struct TransientContext : private sf::NonCopyable
|
||||||
{
|
{
|
||||||
if (resourceCount == 0)
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Constructor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
TransientContext() :
|
||||||
|
referenceCount (0),
|
||||||
|
context (0),
|
||||||
|
sharedContextLock(0),
|
||||||
|
useSharedContext (false)
|
||||||
{
|
{
|
||||||
context = new sf::Context;
|
if (resourceCount == 0)
|
||||||
}
|
|
||||||
else if (!currentContext)
|
|
||||||
{
|
|
||||||
sharedContextLock = new sf::Lock(mutex);
|
|
||||||
useSharedContext = true;
|
|
||||||
sharedContext->setActive(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Destructor
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
~TransientContext()
|
|
||||||
{
|
|
||||||
if (useSharedContext)
|
|
||||||
sharedContext->setActive(false);
|
|
||||||
|
|
||||||
delete sharedContextLock;
|
|
||||||
delete context;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
|
||||||
// Member data
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
unsigned int referenceCount;
|
|
||||||
sf::Context* context;
|
|
||||||
sf::Lock* sharedContextLock;
|
|
||||||
bool useSharedContext;
|
|
||||||
};
|
|
||||||
|
|
||||||
// This per-thread variable tracks if and how a transient
|
|
||||||
// context is currently being used on the current thread
|
|
||||||
sf::ThreadLocalPtr<TransientContext> transientContext(NULL);
|
|
||||||
|
|
||||||
// Supported OpenGL extensions
|
|
||||||
std::vector<std::string> extensions;
|
|
||||||
|
|
||||||
// Load our extensions vector with the supported extensions
|
|
||||||
void loadExtensions()
|
|
||||||
{
|
|
||||||
extensions.clear();
|
|
||||||
|
|
||||||
glGetErrorFuncType glGetErrorFunc = reinterpret_cast<glGetErrorFuncType>(sf::priv::GlContext::getFunction("glGetError"));
|
|
||||||
glGetIntegervFuncType glGetIntegervFunc = reinterpret_cast<glGetIntegervFuncType>(sf::priv::GlContext::getFunction("glGetIntegerv"));
|
|
||||||
glGetStringFuncType glGetStringFunc = reinterpret_cast<glGetStringFuncType>(sf::priv::GlContext::getFunction("glGetString"));
|
|
||||||
|
|
||||||
if (!glGetErrorFunc || !glGetIntegervFunc || !glGetStringFunc)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Check whether a >= 3.0 context is available
|
|
||||||
int majorVersion = 0;
|
|
||||||
glGetIntegervFunc(GL_MAJOR_VERSION, &majorVersion);
|
|
||||||
|
|
||||||
glGetStringiFuncType glGetStringiFunc = reinterpret_cast<glGetStringiFuncType>(sf::priv::GlContext::getFunction("glGetStringi"));
|
|
||||||
|
|
||||||
if (glGetErrorFunc() == GL_INVALID_ENUM || !glGetStringiFunc)
|
|
||||||
{
|
|
||||||
// Try to load the < 3.0 way
|
|
||||||
const char* extensionString = reinterpret_cast<const char*>(glGetStringFunc(GL_EXTENSIONS));
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
const char* extension = extensionString;
|
|
||||||
|
|
||||||
while (*extensionString && (*extensionString != ' '))
|
|
||||||
extensionString++;
|
|
||||||
|
|
||||||
extensions.push_back(std::string(extension, extensionString));
|
|
||||||
}
|
|
||||||
while (*extensionString++);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Try to load the >= 3.0 way
|
|
||||||
int numExtensions = 0;
|
|
||||||
glGetIntegervFunc(GL_NUM_EXTENSIONS, &numExtensions);
|
|
||||||
|
|
||||||
if (numExtensions)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < static_cast<unsigned int>(numExtensions); ++i)
|
|
||||||
{
|
{
|
||||||
const char* extensionString = reinterpret_cast<const char*>(glGetStringiFunc(GL_EXTENSIONS, i));
|
context = new sf::Context;
|
||||||
|
}
|
||||||
|
else if (!currentContext)
|
||||||
|
{
|
||||||
|
sharedContextLock = new sf::Lock(mutex);
|
||||||
|
useSharedContext = true;
|
||||||
|
sharedContext->setActive(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extensions.push_back(extensionString);
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Destructor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
~TransientContext()
|
||||||
|
{
|
||||||
|
if (useSharedContext)
|
||||||
|
sharedContext->setActive(false);
|
||||||
|
|
||||||
|
delete sharedContextLock;
|
||||||
|
delete context;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned int referenceCount;
|
||||||
|
sf::Context* context;
|
||||||
|
sf::Lock* sharedContextLock;
|
||||||
|
bool useSharedContext;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This per-thread variable tracks if and how a transient
|
||||||
|
// context is currently being used on the current thread
|
||||||
|
sf::ThreadLocalPtr<TransientContext> transientContext(NULL);
|
||||||
|
|
||||||
|
// Supported OpenGL extensions
|
||||||
|
std::vector<std::string> extensions;
|
||||||
|
|
||||||
|
// Load our extensions vector with the supported extensions
|
||||||
|
void loadExtensions()
|
||||||
|
{
|
||||||
|
extensions.clear();
|
||||||
|
|
||||||
|
glGetErrorFuncType glGetErrorFunc = reinterpret_cast<glGetErrorFuncType>(sf::priv::GlContext::getFunction("glGetError"));
|
||||||
|
glGetIntegervFuncType glGetIntegervFunc = reinterpret_cast<glGetIntegervFuncType>(sf::priv::GlContext::getFunction("glGetIntegerv"));
|
||||||
|
glGetStringFuncType glGetStringFunc = reinterpret_cast<glGetStringFuncType>(sf::priv::GlContext::getFunction("glGetString"));
|
||||||
|
|
||||||
|
if (!glGetErrorFunc || !glGetIntegervFunc || !glGetStringFunc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check whether a >= 3.0 context is available
|
||||||
|
int majorVersion = 0;
|
||||||
|
glGetIntegervFunc(GL_MAJOR_VERSION, &majorVersion);
|
||||||
|
|
||||||
|
glGetStringiFuncType glGetStringiFunc = reinterpret_cast<glGetStringiFuncType>(sf::priv::GlContext::getFunction("glGetStringi"));
|
||||||
|
|
||||||
|
if (glGetErrorFunc() == GL_INVALID_ENUM || !glGetStringiFunc)
|
||||||
|
{
|
||||||
|
// Try to load the < 3.0 way
|
||||||
|
const char* extensionString = reinterpret_cast<const char*>(glGetStringFunc(GL_EXTENSIONS));
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const char* extension = extensionString;
|
||||||
|
|
||||||
|
while (*extensionString && (*extensionString != ' '))
|
||||||
|
extensionString++;
|
||||||
|
|
||||||
|
extensions.push_back(std::string(extension, extensionString));
|
||||||
|
}
|
||||||
|
while (*extensionString++);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Try to load the >= 3.0 way
|
||||||
|
int numExtensions = 0;
|
||||||
|
glGetIntegervFunc(GL_NUM_EXTENSIONS, &numExtensions);
|
||||||
|
|
||||||
|
if (numExtensions)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < static_cast<unsigned int>(numExtensions); ++i)
|
||||||
|
{
|
||||||
|
const char* extensionString = reinterpret_cast<const char*>(glGetStringiFunc(GL_EXTENSIONS, i));
|
||||||
|
|
||||||
|
extensions.push_back(extensionString);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Helper to parse OpenGL version strings
|
// Helper to parse OpenGL version strings
|
||||||
bool parseVersionString(const char* version, const char* prefix, unsigned int &major, unsigned int &minor)
|
bool parseVersionString(const char* version, const char* prefix, unsigned int &major, unsigned int &minor)
|
||||||
{
|
|
||||||
std::size_t prefixLength = std::strlen(prefix);
|
|
||||||
|
|
||||||
if ((std::strlen(version) >= (prefixLength + 3)) &&
|
|
||||||
(std::strncmp(version, prefix, prefixLength) == 0) &&
|
|
||||||
std::isdigit(version[prefixLength]) &&
|
|
||||||
(version[prefixLength + 1] == '.') &&
|
|
||||||
std::isdigit(version[prefixLength + 2]))
|
|
||||||
{
|
{
|
||||||
major = version[prefixLength] - '0';
|
std::size_t prefixLength = std::strlen(prefix);
|
||||||
minor = version[prefixLength + 2] - '0';
|
|
||||||
|
|
||||||
return true;
|
if ((std::strlen(version) >= (prefixLength + 3)) &&
|
||||||
|
(std::strncmp(version, prefix, prefixLength) == 0) &&
|
||||||
|
std::isdigit(version[prefixLength]) &&
|
||||||
|
(version[prefixLength + 1] == '.') &&
|
||||||
|
std::isdigit(version[prefixLength + 2]))
|
||||||
|
{
|
||||||
|
major = version[prefixLength] - '0';
|
||||||
|
minor = version[prefixLength + 2] - '0';
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,6 +316,12 @@ namespace priv
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void GlContext::initResource()
|
void GlContext::initResource()
|
||||||
{
|
{
|
||||||
|
using GlContextImpl::mutex;
|
||||||
|
using GlContextImpl::resourceCount;
|
||||||
|
using GlContextImpl::currentContext;
|
||||||
|
using GlContextImpl::sharedContext;
|
||||||
|
using GlContextImpl::loadExtensions;
|
||||||
|
|
||||||
// Protect from concurrent access
|
// Protect from concurrent access
|
||||||
Lock lock(mutex);
|
Lock lock(mutex);
|
||||||
|
|
||||||
@ -345,6 +355,10 @@ void GlContext::initResource()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void GlContext::cleanupResource()
|
void GlContext::cleanupResource()
|
||||||
{
|
{
|
||||||
|
using GlContextImpl::mutex;
|
||||||
|
using GlContextImpl::resourceCount;
|
||||||
|
using GlContextImpl::sharedContext;
|
||||||
|
|
||||||
// Protect from concurrent access
|
// Protect from concurrent access
|
||||||
Lock lock(mutex);
|
Lock lock(mutex);
|
||||||
|
|
||||||
@ -367,13 +381,17 @@ void GlContext::cleanupResource()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void GlContext::registerContextDestroyCallback(ContextDestroyCallback callback, void* arg)
|
void GlContext::registerContextDestroyCallback(ContextDestroyCallback callback, void* arg)
|
||||||
{
|
{
|
||||||
contextDestroyCallbacks.insert(std::make_pair(callback, arg));
|
GlContextImpl::contextDestroyCallbacks.insert(std::make_pair(callback, arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void GlContext::acquireTransientContext()
|
void GlContext::acquireTransientContext()
|
||||||
{
|
{
|
||||||
|
using GlContextImpl::mutex;
|
||||||
|
using GlContextImpl::TransientContext;
|
||||||
|
using GlContextImpl::transientContext;
|
||||||
|
|
||||||
// Protect from concurrent access
|
// Protect from concurrent access
|
||||||
Lock lock(mutex);
|
Lock lock(mutex);
|
||||||
|
|
||||||
@ -390,6 +408,9 @@ void GlContext::acquireTransientContext()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void GlContext::releaseTransientContext()
|
void GlContext::releaseTransientContext()
|
||||||
{
|
{
|
||||||
|
using GlContextImpl::mutex;
|
||||||
|
using GlContextImpl::transientContext;
|
||||||
|
|
||||||
// Protect from concurrent access
|
// Protect from concurrent access
|
||||||
Lock lock(mutex);
|
Lock lock(mutex);
|
||||||
|
|
||||||
@ -412,6 +433,9 @@ void GlContext::releaseTransientContext()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
GlContext* GlContext::create()
|
GlContext* GlContext::create()
|
||||||
{
|
{
|
||||||
|
using GlContextImpl::mutex;
|
||||||
|
using GlContextImpl::sharedContext;
|
||||||
|
|
||||||
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
|
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
|
||||||
assert(sharedContext != NULL);
|
assert(sharedContext != NULL);
|
||||||
|
|
||||||
@ -440,6 +464,11 @@ GlContext* GlContext::create()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel)
|
GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel)
|
||||||
{
|
{
|
||||||
|
using GlContextImpl::mutex;
|
||||||
|
using GlContextImpl::resourceCount;
|
||||||
|
using GlContextImpl::sharedContext;
|
||||||
|
using GlContextImpl::loadExtensions;
|
||||||
|
|
||||||
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
|
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
|
||||||
assert(sharedContext != NULL);
|
assert(sharedContext != NULL);
|
||||||
|
|
||||||
@ -488,6 +517,11 @@ GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl*
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
GlContext* GlContext::create(const ContextSettings& settings, unsigned int width, unsigned int height)
|
GlContext* GlContext::create(const ContextSettings& settings, unsigned int width, unsigned int height)
|
||||||
{
|
{
|
||||||
|
using GlContextImpl::mutex;
|
||||||
|
using GlContextImpl::resourceCount;
|
||||||
|
using GlContextImpl::sharedContext;
|
||||||
|
using GlContextImpl::loadExtensions;
|
||||||
|
|
||||||
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
|
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
|
||||||
assert(sharedContext != NULL);
|
assert(sharedContext != NULL);
|
||||||
|
|
||||||
@ -536,6 +570,7 @@ GlContext* GlContext::create(const ContextSettings& settings, unsigned int width
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool GlContext::isExtensionAvailable(const char* name)
|
bool GlContext::isExtensionAvailable(const char* name)
|
||||||
{
|
{
|
||||||
|
using GlContextImpl::extensions;
|
||||||
return std::find(extensions.begin(), extensions.end(), name) != extensions.end();
|
return std::find(extensions.begin(), extensions.end(), name) != extensions.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,7 +578,7 @@ bool GlContext::isExtensionAvailable(const char* name)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
GlFunctionPointer GlContext::getFunction(const char* name)
|
GlFunctionPointer GlContext::getFunction(const char* name)
|
||||||
{
|
{
|
||||||
Lock lock(mutex);
|
Lock lock(GlContextImpl::mutex);
|
||||||
|
|
||||||
return ContextType::getFunction(name);
|
return ContextType::getFunction(name);
|
||||||
}
|
}
|
||||||
@ -552,6 +587,7 @@ GlFunctionPointer GlContext::getFunction(const char* name)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
const GlContext* GlContext::getActiveContext()
|
const GlContext* GlContext::getActiveContext()
|
||||||
{
|
{
|
||||||
|
using GlContextImpl::currentContext;
|
||||||
return currentContext;
|
return currentContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,6 +595,7 @@ const GlContext* GlContext::getActiveContext()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Uint64 GlContext::getActiveContextId()
|
Uint64 GlContext::getActiveContextId()
|
||||||
{
|
{
|
||||||
|
using GlContextImpl::currentContext;
|
||||||
return currentContext ? currentContext->m_id : 0;
|
return currentContext ? currentContext->m_id : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -566,6 +603,9 @@ Uint64 GlContext::getActiveContextId()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
GlContext::~GlContext()
|
GlContext::~GlContext()
|
||||||
{
|
{
|
||||||
|
using GlContextImpl::currentContext;
|
||||||
|
using GlContextImpl::sharedContext;
|
||||||
|
|
||||||
// Deactivate the context before killing it, unless we're inside Cleanup()
|
// Deactivate the context before killing it, unless we're inside Cleanup()
|
||||||
if (sharedContext)
|
if (sharedContext)
|
||||||
{
|
{
|
||||||
@ -585,6 +625,10 @@ const ContextSettings& GlContext::getSettings() const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool GlContext::setActive(bool active)
|
bool GlContext::setActive(bool active)
|
||||||
{
|
{
|
||||||
|
using GlContextImpl::mutex;
|
||||||
|
using GlContextImpl::currentContext;
|
||||||
|
using GlContextImpl::sharedContext;
|
||||||
|
|
||||||
if (active)
|
if (active)
|
||||||
{
|
{
|
||||||
if (this != currentContext)
|
if (this != currentContext)
|
||||||
@ -637,7 +681,7 @@ bool GlContext::setActive(bool active)
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
GlContext::GlContext() :
|
GlContext::GlContext() :
|
||||||
m_id(id++)
|
m_id(GlContextImpl::id++)
|
||||||
{
|
{
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
}
|
}
|
||||||
@ -675,6 +719,10 @@ int GlContext::evaluateFormat(unsigned int bitsPerPixel, const ContextSettings&
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void GlContext::cleanupUnsharedResources()
|
void GlContext::cleanupUnsharedResources()
|
||||||
{
|
{
|
||||||
|
using GlContextImpl::currentContext;
|
||||||
|
using GlContextImpl::ContextDestroyCallbacks;
|
||||||
|
using GlContextImpl::contextDestroyCallbacks;
|
||||||
|
|
||||||
// Save the current context so we can restore it later
|
// Save the current context so we can restore it later
|
||||||
GlContext* contextToRestore = currentContext;
|
GlContext* contextToRestore = currentContext;
|
||||||
|
|
||||||
@ -742,6 +790,8 @@ void GlContext::initialize(const ContextSettings& requestedSettings)
|
|||||||
// OpenGL ES Full profile: The beginning of the returned string is "OpenGL ES major.minor"
|
// OpenGL ES Full profile: The beginning of the returned string is "OpenGL ES major.minor"
|
||||||
// Desktop OpenGL: The beginning of the returned string is "major.minor"
|
// Desktop OpenGL: The beginning of the returned string is "major.minor"
|
||||||
|
|
||||||
|
using GlContextImpl::parseVersionString;
|
||||||
|
|
||||||
if (!parseVersionString(version, "OpenGL ES-CL ", m_settings.majorVersion, m_settings.minorVersion) &&
|
if (!parseVersionString(version, "OpenGL ES-CL ", m_settings.majorVersion, m_settings.minorVersion) &&
|
||||||
!parseVersionString(version, "OpenGL ES-CM ", m_settings.majorVersion, m_settings.minorVersion) &&
|
!parseVersionString(version, "OpenGL ES-CM ", m_settings.majorVersion, m_settings.minorVersion) &&
|
||||||
!parseVersionString(version, "OpenGL ES ", m_settings.majorVersion, m_settings.minorVersion) &&
|
!parseVersionString(version, "OpenGL ES ", m_settings.majorVersion, m_settings.minorVersion) &&
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#define SF_GLAD_GLX_IMPLEMENTATION
|
|
||||||
#include <SFML/Window/Unix/WindowImplX11.hpp> // important to be included first (conflict with None)
|
#include <SFML/Window/Unix/WindowImplX11.hpp> // important to be included first (conflict with None)
|
||||||
#include <SFML/Window/Unix/GlxContext.hpp>
|
#include <SFML/Window/Unix/GlxContext.hpp>
|
||||||
#include <SFML/Window/Unix/Display.hpp>
|
#include <SFML/Window/Unix/Display.hpp>
|
||||||
@ -34,6 +33,14 @@
|
|||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
// We check for this definition in order to avoid multiple definitions of GLAD
|
||||||
|
// entities during unity builds of SFML.
|
||||||
|
#ifndef SF_GLAD_GLX_IMPLEMENTATION_INCLUDED
|
||||||
|
#define SF_GLAD_GLX_IMPLEMENTATION_INCLUDED
|
||||||
|
#define SF_GLAD_GLX_IMPLEMENTATION
|
||||||
|
#include <glad/glx.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(GLX_DEBUGGING) && defined(SFML_DEBUG)
|
#if !defined(GLX_DEBUGGING) && defined(SFML_DEBUG)
|
||||||
// Enable this to print messages to err() everytime GLX produces errors
|
// Enable this to print messages to err() everytime GLX produces errors
|
||||||
//#define GLX_DEBUGGING
|
//#define GLX_DEBUGGING
|
||||||
@ -52,7 +59,7 @@ namespace
|
|||||||
if (!initialized)
|
if (!initialized)
|
||||||
{
|
{
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
// We don't check the return value since the extension
|
// We don't check the return value since the extension
|
||||||
// flags are cleared even if loading fails
|
// flags are cleared even if loading fails
|
||||||
gladLoaderLoadGLX(display, screen);
|
gladLoaderLoadGLX(display, screen);
|
||||||
|
@ -62,105 +62,140 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
sf::priv::WindowImplX11* fullscreenWindow = NULL;
|
// A nested named namespace is used here to allow unity builds of SFML.
|
||||||
std::vector<sf::priv::WindowImplX11*> allWindows;
|
namespace WindowsImplX11Impl
|
||||||
sf::Mutex allWindowsMutex;
|
|
||||||
sf::String windowManagerName;
|
|
||||||
|
|
||||||
sf::String wmAbsPosGood[] = { "Enlightenment", "FVWM", "i3" };
|
|
||||||
|
|
||||||
static const unsigned long eventMask = FocusChangeMask | ButtonPressMask |
|
|
||||||
ButtonReleaseMask | ButtonMotionMask |
|
|
||||||
PointerMotionMask | KeyPressMask |
|
|
||||||
KeyReleaseMask | StructureNotifyMask |
|
|
||||||
EnterWindowMask | LeaveWindowMask |
|
|
||||||
VisibilityChangeMask | PropertyChangeMask;
|
|
||||||
|
|
||||||
static const unsigned int maxTrialsCount = 5;
|
|
||||||
|
|
||||||
// Predicate we use to find key repeat events in processEvent
|
|
||||||
struct KeyRepeatFinder
|
|
||||||
{
|
{
|
||||||
KeyRepeatFinder(unsigned int keycode, Time time) : keycode(keycode), time(time) {}
|
sf::priv::WindowImplX11* fullscreenWindow = NULL;
|
||||||
|
std::vector<sf::priv::WindowImplX11*> allWindows;
|
||||||
|
sf::Mutex allWindowsMutex;
|
||||||
|
sf::String windowManagerName;
|
||||||
|
|
||||||
// Predicate operator that checks event type, keycode and timestamp
|
sf::String wmAbsPosGood[] = { "Enlightenment", "FVWM", "i3" };
|
||||||
bool operator()(const XEvent& event)
|
|
||||||
|
static const unsigned long eventMask = FocusChangeMask | ButtonPressMask |
|
||||||
|
ButtonReleaseMask | ButtonMotionMask |
|
||||||
|
PointerMotionMask | KeyPressMask |
|
||||||
|
KeyReleaseMask | StructureNotifyMask |
|
||||||
|
EnterWindowMask | LeaveWindowMask |
|
||||||
|
VisibilityChangeMask | PropertyChangeMask;
|
||||||
|
|
||||||
|
static const unsigned int maxTrialsCount = 5;
|
||||||
|
|
||||||
|
// Predicate we use to find key repeat events in processEvent
|
||||||
|
struct KeyRepeatFinder
|
||||||
{
|
{
|
||||||
return ((event.type == KeyPress) && (event.xkey.keycode == keycode) && (event.xkey.time - time < 2));
|
KeyRepeatFinder(unsigned int keycode, Time time) : keycode(keycode), time(time) {}
|
||||||
|
|
||||||
|
// Predicate operator that checks event type, keycode and timestamp
|
||||||
|
bool operator()(const XEvent& event)
|
||||||
|
{
|
||||||
|
return ((event.type == KeyPress) && (event.xkey.keycode == keycode) && (event.xkey.time - time < 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int keycode;
|
||||||
|
Time time;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Filter the events received by windows (only allow those matching a specific window)
|
||||||
|
Bool checkEvent(::Display*, XEvent* event, XPointer userData)
|
||||||
|
{
|
||||||
|
// Just check if the event matches the window
|
||||||
|
return event->xany.window == reinterpret_cast< ::Window >(userData);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int keycode;
|
// Find the name of the current executable
|
||||||
Time time;
|
std::string findExecutableName()
|
||||||
};
|
{
|
||||||
|
// We use /proc/self/cmdline to get the command line
|
||||||
|
// the user used to invoke this instance of the application
|
||||||
|
int file = ::open("/proc/self/cmdline", O_RDONLY | O_NONBLOCK);
|
||||||
|
|
||||||
// Filter the events received by windows (only allow those matching a specific window)
|
if (file < 0)
|
||||||
Bool checkEvent(::Display*, XEvent* event, XPointer userData)
|
return "sfml";
|
||||||
{
|
|
||||||
// Just check if the event matches the window
|
|
||||||
return event->xany.window == reinterpret_cast< ::Window >(userData);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the name of the current executable
|
std::vector<char> buffer(256, 0);
|
||||||
std::string findExecutableName()
|
std::size_t offset = 0;
|
||||||
{
|
ssize_t result = 0;
|
||||||
// We use /proc/self/cmdline to get the command line
|
|
||||||
// the user used to invoke this instance of the application
|
|
||||||
int file = ::open("/proc/self/cmdline", O_RDONLY | O_NONBLOCK);
|
|
||||||
|
|
||||||
if (file < 0)
|
while ((result = read(file, &buffer[offset], 256)) > 0)
|
||||||
|
{
|
||||||
|
buffer.resize(buffer.size() + result, 0);
|
||||||
|
offset += result;
|
||||||
|
}
|
||||||
|
|
||||||
|
::close(file);
|
||||||
|
|
||||||
|
if (offset)
|
||||||
|
{
|
||||||
|
buffer[offset] = 0;
|
||||||
|
|
||||||
|
// Remove the path to keep the executable name only
|
||||||
|
return basename(&buffer[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default fallback name
|
||||||
return "sfml";
|
return "sfml";
|
||||||
|
|
||||||
std::vector<char> buffer(256, 0);
|
|
||||||
std::size_t offset = 0;
|
|
||||||
ssize_t result = 0;
|
|
||||||
|
|
||||||
while ((result = read(file, &buffer[offset], 256)) > 0)
|
|
||||||
{
|
|
||||||
buffer.resize(buffer.size() + result, 0);
|
|
||||||
offset += result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
::close(file);
|
// Check if Extended Window Manager Hints are supported
|
||||||
|
bool ewmhSupported()
|
||||||
if (offset)
|
|
||||||
{
|
{
|
||||||
buffer[offset] = 0;
|
static bool checked = false;
|
||||||
|
static bool ewmhSupported = false;
|
||||||
|
|
||||||
// Remove the path to keep the executable name only
|
if (checked)
|
||||||
return basename(&buffer[0]);
|
return ewmhSupported;
|
||||||
}
|
|
||||||
|
|
||||||
// Default fallback name
|
checked = true;
|
||||||
return "sfml";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if Extended Window Manager Hints are supported
|
Atom netSupportingWmCheck = sf::priv::getAtom("_NET_SUPPORTING_WM_CHECK", true);
|
||||||
bool ewmhSupported()
|
Atom netSupported = sf::priv::getAtom("_NET_SUPPORTED", true);
|
||||||
{
|
|
||||||
static bool checked = false;
|
|
||||||
static bool ewmhSupported = false;
|
|
||||||
|
|
||||||
if (checked)
|
if (!netSupportingWmCheck || !netSupported)
|
||||||
return ewmhSupported;
|
return false;
|
||||||
|
|
||||||
checked = true;
|
::Display* display = sf::priv::OpenDisplay();
|
||||||
|
|
||||||
Atom netSupportingWmCheck = sf::priv::getAtom("_NET_SUPPORTING_WM_CHECK", true);
|
Atom actualType;
|
||||||
Atom netSupported = sf::priv::getAtom("_NET_SUPPORTED", true);
|
int actualFormat;
|
||||||
|
unsigned long numItems;
|
||||||
|
unsigned long numBytes;
|
||||||
|
unsigned char* data;
|
||||||
|
|
||||||
if (!netSupportingWmCheck || !netSupported)
|
int result = XGetWindowProperty(display,
|
||||||
return false;
|
DefaultRootWindow(display),
|
||||||
|
netSupportingWmCheck,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
False,
|
||||||
|
XA_WINDOW,
|
||||||
|
&actualType,
|
||||||
|
&actualFormat,
|
||||||
|
&numItems,
|
||||||
|
&numBytes,
|
||||||
|
&data);
|
||||||
|
|
||||||
::Display* display = sf::priv::OpenDisplay();
|
if (result != Success || actualType != XA_WINDOW || numItems != 1)
|
||||||
|
{
|
||||||
|
if (result == Success)
|
||||||
|
XFree(data);
|
||||||
|
|
||||||
Atom actualType;
|
sf::priv::CloseDisplay(display);
|
||||||
int actualFormat;
|
return false;
|
||||||
unsigned long numItems;
|
}
|
||||||
unsigned long numBytes;
|
|
||||||
unsigned char* data;
|
|
||||||
|
|
||||||
int result = XGetWindowProperty(display,
|
::Window rootWindow = *reinterpret_cast< ::Window* >(data);
|
||||||
DefaultRootWindow(display),
|
|
||||||
|
XFree(data);
|
||||||
|
|
||||||
|
if (!rootWindow)
|
||||||
|
{
|
||||||
|
sf::priv::CloseDisplay(display);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = XGetWindowProperty(display,
|
||||||
|
rootWindow,
|
||||||
netSupportingWmCheck,
|
netSupportingWmCheck,
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
@ -172,305 +207,274 @@ namespace
|
|||||||
&numBytes,
|
&numBytes,
|
||||||
&data);
|
&data);
|
||||||
|
|
||||||
if (result != Success || actualType != XA_WINDOW || numItems != 1)
|
if (result != Success || actualType != XA_WINDOW || numItems != 1)
|
||||||
{
|
{
|
||||||
if (result == Success)
|
if (result == Success)
|
||||||
XFree(data);
|
XFree(data);
|
||||||
|
|
||||||
sf::priv::CloseDisplay(display);
|
sf::priv::CloseDisplay(display);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
::Window rootWindow = *reinterpret_cast< ::Window* >(data);
|
::Window childWindow = *reinterpret_cast< ::Window* >(data);
|
||||||
|
|
||||||
XFree(data);
|
|
||||||
|
|
||||||
if (!rootWindow)
|
|
||||||
{
|
|
||||||
sf::priv::CloseDisplay(display);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = XGetWindowProperty(display,
|
|
||||||
rootWindow,
|
|
||||||
netSupportingWmCheck,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
False,
|
|
||||||
XA_WINDOW,
|
|
||||||
&actualType,
|
|
||||||
&actualFormat,
|
|
||||||
&numItems,
|
|
||||||
&numBytes,
|
|
||||||
&data);
|
|
||||||
|
|
||||||
if (result != Success || actualType != XA_WINDOW || numItems != 1)
|
|
||||||
{
|
|
||||||
if (result == Success)
|
|
||||||
XFree(data);
|
|
||||||
|
|
||||||
sf::priv::CloseDisplay(display);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
::Window childWindow = *reinterpret_cast< ::Window* >(data);
|
|
||||||
|
|
||||||
XFree(data);
|
|
||||||
|
|
||||||
if (!childWindow)
|
|
||||||
{
|
|
||||||
sf::priv::CloseDisplay(display);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Conforming window managers should return the same window for both queries
|
|
||||||
if (rootWindow != childWindow)
|
|
||||||
{
|
|
||||||
sf::priv::CloseDisplay(display);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ewmhSupported = true;
|
|
||||||
|
|
||||||
// We try to get the name of the window manager
|
|
||||||
// for window manager specific workarounds
|
|
||||||
Atom netWmName = sf::priv::getAtom("_NET_WM_NAME", true);
|
|
||||||
|
|
||||||
if (!netWmName)
|
|
||||||
{
|
|
||||||
sf::priv::CloseDisplay(display);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Atom utf8StringType = sf::priv::getAtom("UTF8_STRING");
|
|
||||||
|
|
||||||
if (!utf8StringType)
|
|
||||||
utf8StringType = XA_STRING;
|
|
||||||
|
|
||||||
result = XGetWindowProperty(display,
|
|
||||||
rootWindow,
|
|
||||||
netWmName,
|
|
||||||
0,
|
|
||||||
0x7fffffff,
|
|
||||||
False,
|
|
||||||
utf8StringType,
|
|
||||||
&actualType,
|
|
||||||
&actualFormat,
|
|
||||||
&numItems,
|
|
||||||
&numBytes,
|
|
||||||
&data);
|
|
||||||
|
|
||||||
if (actualType && numItems)
|
|
||||||
{
|
|
||||||
// It seems the wm name string reply is not necessarily
|
|
||||||
// null-terminated. The work around is to get its actual
|
|
||||||
// length to build a proper string
|
|
||||||
const char* begin = reinterpret_cast<const char*>(data);
|
|
||||||
const char* end = begin + numItems;
|
|
||||||
windowManagerName = sf::String::fromUtf8(begin, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == Success)
|
|
||||||
XFree(data);
|
XFree(data);
|
||||||
|
|
||||||
sf::priv::CloseDisplay(display);
|
if (!childWindow)
|
||||||
|
{
|
||||||
|
sf::priv::CloseDisplay(display);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
// Conforming window managers should return the same window for both queries
|
||||||
}
|
if (rootWindow != childWindow)
|
||||||
|
{
|
||||||
|
sf::priv::CloseDisplay(display);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the parent window.
|
ewmhSupported = true;
|
||||||
::Window getParentWindow(::Display* disp, ::Window win)
|
|
||||||
{
|
|
||||||
::Window root, parent;
|
|
||||||
::Window* children = NULL;
|
|
||||||
unsigned int numChildren;
|
|
||||||
|
|
||||||
XQueryTree(disp, win, &root, &parent, &children, &numChildren);
|
// We try to get the name of the window manager
|
||||||
|
// for window manager specific workarounds
|
||||||
|
Atom netWmName = sf::priv::getAtom("_NET_WM_NAME", true);
|
||||||
|
|
||||||
// Children information is not used, so must be freed.
|
if (!netWmName)
|
||||||
if (children != NULL)
|
{
|
||||||
XFree(children);
|
sf::priv::CloseDisplay(display);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return parent;
|
Atom utf8StringType = sf::priv::getAtom("UTF8_STRING");
|
||||||
}
|
|
||||||
|
|
||||||
// Get the Frame Extents from EWMH WMs that support it.
|
if (!utf8StringType)
|
||||||
bool getEWMHFrameExtents(::Display* disp, ::Window win,
|
utf8StringType = XA_STRING;
|
||||||
long& xFrameExtent, long& yFrameExtent)
|
|
||||||
{
|
|
||||||
if (!ewmhSupported())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Atom frameExtents = sf::priv::getAtom("_NET_FRAME_EXTENTS", true);
|
result = XGetWindowProperty(display,
|
||||||
|
rootWindow,
|
||||||
if (frameExtents == None)
|
netWmName,
|
||||||
return false;
|
|
||||||
|
|
||||||
bool gotFrameExtents = false;
|
|
||||||
Atom actualType;
|
|
||||||
int actualFormat;
|
|
||||||
unsigned long numItems;
|
|
||||||
unsigned long numBytesLeft;
|
|
||||||
unsigned char* data = NULL;
|
|
||||||
|
|
||||||
int result = XGetWindowProperty(disp,
|
|
||||||
win,
|
|
||||||
frameExtents,
|
|
||||||
0,
|
0,
|
||||||
4,
|
0x7fffffff,
|
||||||
False,
|
False,
|
||||||
XA_CARDINAL,
|
utf8StringType,
|
||||||
&actualType,
|
&actualType,
|
||||||
&actualFormat,
|
&actualFormat,
|
||||||
&numItems,
|
&numItems,
|
||||||
&numBytesLeft,
|
&numBytes,
|
||||||
&data);
|
&data);
|
||||||
|
|
||||||
if ((result == Success) && (actualType == XA_CARDINAL) &&
|
if (actualType && numItems)
|
||||||
(actualFormat == 32) && (numItems == 4) && (numBytesLeft == 0) &&
|
{
|
||||||
(data != NULL))
|
// It seems the wm name string reply is not necessarily
|
||||||
{
|
// null-terminated. The work around is to get its actual
|
||||||
gotFrameExtents = true;
|
// length to build a proper string
|
||||||
|
const char* begin = reinterpret_cast<const char*>(data);
|
||||||
|
const char* end = begin + numItems;
|
||||||
|
windowManagerName = sf::String::fromUtf8(begin, end);
|
||||||
|
}
|
||||||
|
|
||||||
long* extents = (long*) data;
|
if (result == Success)
|
||||||
|
XFree(data);
|
||||||
|
|
||||||
xFrameExtent = extents[0]; // Left.
|
sf::priv::CloseDisplay(display);
|
||||||
yFrameExtent = extents[2]; // Top.
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always free data.
|
// Get the parent window.
|
||||||
if (data != NULL)
|
::Window getParentWindow(::Display* disp, ::Window win)
|
||||||
XFree(data);
|
{
|
||||||
|
::Window root, parent;
|
||||||
|
::Window* children = NULL;
|
||||||
|
unsigned int numChildren;
|
||||||
|
|
||||||
return gotFrameExtents;
|
XQueryTree(disp, win, &root, &parent, &children, &numChildren);
|
||||||
}
|
|
||||||
|
// Children information is not used, so must be freed.
|
||||||
|
if (children != NULL)
|
||||||
|
XFree(children);
|
||||||
|
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the Frame Extents from EWMH WMs that support it.
|
||||||
|
bool getEWMHFrameExtents(::Display* disp, ::Window win,
|
||||||
|
long& xFrameExtent, long& yFrameExtent)
|
||||||
|
{
|
||||||
|
if (!ewmhSupported())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Atom frameExtents = sf::priv::getAtom("_NET_FRAME_EXTENTS", true);
|
||||||
|
|
||||||
|
if (frameExtents == None)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool gotFrameExtents = false;
|
||||||
|
Atom actualType;
|
||||||
|
int actualFormat;
|
||||||
|
unsigned long numItems;
|
||||||
|
unsigned long numBytesLeft;
|
||||||
|
unsigned char* data = NULL;
|
||||||
|
|
||||||
|
int result = XGetWindowProperty(disp,
|
||||||
|
win,
|
||||||
|
frameExtents,
|
||||||
|
0,
|
||||||
|
4,
|
||||||
|
False,
|
||||||
|
XA_CARDINAL,
|
||||||
|
&actualType,
|
||||||
|
&actualFormat,
|
||||||
|
&numItems,
|
||||||
|
&numBytesLeft,
|
||||||
|
&data);
|
||||||
|
|
||||||
|
if ((result == Success) && (actualType == XA_CARDINAL) &&
|
||||||
|
(actualFormat == 32) && (numItems == 4) && (numBytesLeft == 0) &&
|
||||||
|
(data != NULL))
|
||||||
|
{
|
||||||
|
gotFrameExtents = true;
|
||||||
|
|
||||||
|
long* extents = (long*) data;
|
||||||
|
|
||||||
|
xFrameExtent = extents[0]; // Left.
|
||||||
|
yFrameExtent = extents[2]; // Top.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always free data.
|
||||||
|
if (data != NULL)
|
||||||
|
XFree(data);
|
||||||
|
|
||||||
|
return gotFrameExtents;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the current WM is in the list of good WMs that provide
|
||||||
|
// a correct absolute position for the window when queried.
|
||||||
|
bool isWMAbsolutePositionGood()
|
||||||
|
{
|
||||||
|
// This can only work with EWMH, to get the name.
|
||||||
|
if (!ewmhSupported())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < (sizeof(wmAbsPosGood) / sizeof(wmAbsPosGood[0])); i++)
|
||||||
|
{
|
||||||
|
if (wmAbsPosGood[i] == windowManagerName)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the current WM is in the list of good WMs that provide
|
|
||||||
// a correct absolute position for the window when queried.
|
|
||||||
bool isWMAbsolutePositionGood()
|
|
||||||
{
|
|
||||||
// This can only work with EWMH, to get the name.
|
|
||||||
if (!ewmhSupported())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (size_t i = 0; i < (sizeof(wmAbsPosGood) / sizeof(wmAbsPosGood[0])); i++)
|
|
||||||
{
|
|
||||||
if (wmAbsPosGood[i] == windowManagerName)
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
sf::Keyboard::Key keysymToSF(KeySym symbol)
|
||||||
}
|
|
||||||
|
|
||||||
sf::Keyboard::Key keysymToSF(KeySym symbol)
|
|
||||||
{
|
|
||||||
switch (symbol)
|
|
||||||
{
|
{
|
||||||
case XK_Shift_L: return sf::Keyboard::LShift;
|
switch (symbol)
|
||||||
case XK_Shift_R: return sf::Keyboard::RShift;
|
{
|
||||||
case XK_Control_L: return sf::Keyboard::LControl;
|
case XK_Shift_L: return sf::Keyboard::LShift;
|
||||||
case XK_Control_R: return sf::Keyboard::RControl;
|
case XK_Shift_R: return sf::Keyboard::RShift;
|
||||||
case XK_Alt_L: return sf::Keyboard::LAlt;
|
case XK_Control_L: return sf::Keyboard::LControl;
|
||||||
case XK_Alt_R: return sf::Keyboard::RAlt;
|
case XK_Control_R: return sf::Keyboard::RControl;
|
||||||
case XK_Super_L: return sf::Keyboard::LSystem;
|
case XK_Alt_L: return sf::Keyboard::LAlt;
|
||||||
case XK_Super_R: return sf::Keyboard::RSystem;
|
case XK_Alt_R: return sf::Keyboard::RAlt;
|
||||||
case XK_Menu: return sf::Keyboard::Menu;
|
case XK_Super_L: return sf::Keyboard::LSystem;
|
||||||
case XK_Escape: return sf::Keyboard::Escape;
|
case XK_Super_R: return sf::Keyboard::RSystem;
|
||||||
case XK_semicolon: return sf::Keyboard::Semicolon;
|
case XK_Menu: return sf::Keyboard::Menu;
|
||||||
case XK_slash: return sf::Keyboard::Slash;
|
case XK_Escape: return sf::Keyboard::Escape;
|
||||||
case XK_equal: return sf::Keyboard::Equal;
|
case XK_semicolon: return sf::Keyboard::Semicolon;
|
||||||
case XK_minus: return sf::Keyboard::Hyphen;
|
case XK_slash: return sf::Keyboard::Slash;
|
||||||
case XK_bracketleft: return sf::Keyboard::LBracket;
|
case XK_equal: return sf::Keyboard::Equal;
|
||||||
case XK_bracketright: return sf::Keyboard::RBracket;
|
case XK_minus: return sf::Keyboard::Hyphen;
|
||||||
case XK_comma: return sf::Keyboard::Comma;
|
case XK_bracketleft: return sf::Keyboard::LBracket;
|
||||||
case XK_period: return sf::Keyboard::Period;
|
case XK_bracketright: return sf::Keyboard::RBracket;
|
||||||
case XK_apostrophe: return sf::Keyboard::Quote;
|
case XK_comma: return sf::Keyboard::Comma;
|
||||||
case XK_backslash: return sf::Keyboard::Backslash;
|
case XK_period: return sf::Keyboard::Period;
|
||||||
case XK_grave: return sf::Keyboard::Tilde;
|
case XK_apostrophe: return sf::Keyboard::Quote;
|
||||||
case XK_space: return sf::Keyboard::Space;
|
case XK_backslash: return sf::Keyboard::Backslash;
|
||||||
case XK_Return: return sf::Keyboard::Enter;
|
case XK_grave: return sf::Keyboard::Tilde;
|
||||||
case XK_KP_Enter: return sf::Keyboard::Enter;
|
case XK_space: return sf::Keyboard::Space;
|
||||||
case XK_BackSpace: return sf::Keyboard::Backspace;
|
case XK_Return: return sf::Keyboard::Enter;
|
||||||
case XK_Tab: return sf::Keyboard::Tab;
|
case XK_KP_Enter: return sf::Keyboard::Enter;
|
||||||
case XK_Prior: return sf::Keyboard::PageUp;
|
case XK_BackSpace: return sf::Keyboard::Backspace;
|
||||||
case XK_Next: return sf::Keyboard::PageDown;
|
case XK_Tab: return sf::Keyboard::Tab;
|
||||||
case XK_End: return sf::Keyboard::End;
|
case XK_Prior: return sf::Keyboard::PageUp;
|
||||||
case XK_Home: return sf::Keyboard::Home;
|
case XK_Next: return sf::Keyboard::PageDown;
|
||||||
case XK_Insert: return sf::Keyboard::Insert;
|
case XK_End: return sf::Keyboard::End;
|
||||||
case XK_Delete: return sf::Keyboard::Delete;
|
case XK_Home: return sf::Keyboard::Home;
|
||||||
case XK_KP_Add: return sf::Keyboard::Add;
|
case XK_Insert: return sf::Keyboard::Insert;
|
||||||
case XK_KP_Subtract: return sf::Keyboard::Subtract;
|
case XK_Delete: return sf::Keyboard::Delete;
|
||||||
case XK_KP_Multiply: return sf::Keyboard::Multiply;
|
case XK_KP_Add: return sf::Keyboard::Add;
|
||||||
case XK_KP_Divide: return sf::Keyboard::Divide;
|
case XK_KP_Subtract: return sf::Keyboard::Subtract;
|
||||||
case XK_Pause: return sf::Keyboard::Pause;
|
case XK_KP_Multiply: return sf::Keyboard::Multiply;
|
||||||
case XK_F1: return sf::Keyboard::F1;
|
case XK_KP_Divide: return sf::Keyboard::Divide;
|
||||||
case XK_F2: return sf::Keyboard::F2;
|
case XK_Pause: return sf::Keyboard::Pause;
|
||||||
case XK_F3: return sf::Keyboard::F3;
|
case XK_F1: return sf::Keyboard::F1;
|
||||||
case XK_F4: return sf::Keyboard::F4;
|
case XK_F2: return sf::Keyboard::F2;
|
||||||
case XK_F5: return sf::Keyboard::F5;
|
case XK_F3: return sf::Keyboard::F3;
|
||||||
case XK_F6: return sf::Keyboard::F6;
|
case XK_F4: return sf::Keyboard::F4;
|
||||||
case XK_F7: return sf::Keyboard::F7;
|
case XK_F5: return sf::Keyboard::F5;
|
||||||
case XK_F8: return sf::Keyboard::F8;
|
case XK_F6: return sf::Keyboard::F6;
|
||||||
case XK_F9: return sf::Keyboard::F9;
|
case XK_F7: return sf::Keyboard::F7;
|
||||||
case XK_F10: return sf::Keyboard::F10;
|
case XK_F8: return sf::Keyboard::F8;
|
||||||
case XK_F11: return sf::Keyboard::F11;
|
case XK_F9: return sf::Keyboard::F9;
|
||||||
case XK_F12: return sf::Keyboard::F12;
|
case XK_F10: return sf::Keyboard::F10;
|
||||||
case XK_F13: return sf::Keyboard::F13;
|
case XK_F11: return sf::Keyboard::F11;
|
||||||
case XK_F14: return sf::Keyboard::F14;
|
case XK_F12: return sf::Keyboard::F12;
|
||||||
case XK_F15: return sf::Keyboard::F15;
|
case XK_F13: return sf::Keyboard::F13;
|
||||||
case XK_Left: return sf::Keyboard::Left;
|
case XK_F14: return sf::Keyboard::F14;
|
||||||
case XK_Right: return sf::Keyboard::Right;
|
case XK_F15: return sf::Keyboard::F15;
|
||||||
case XK_Up: return sf::Keyboard::Up;
|
case XK_Left: return sf::Keyboard::Left;
|
||||||
case XK_Down: return sf::Keyboard::Down;
|
case XK_Right: return sf::Keyboard::Right;
|
||||||
case XK_KP_Insert: return sf::Keyboard::Numpad0;
|
case XK_Up: return sf::Keyboard::Up;
|
||||||
case XK_KP_End: return sf::Keyboard::Numpad1;
|
case XK_Down: return sf::Keyboard::Down;
|
||||||
case XK_KP_Down: return sf::Keyboard::Numpad2;
|
case XK_KP_Insert: return sf::Keyboard::Numpad0;
|
||||||
case XK_KP_Page_Down: return sf::Keyboard::Numpad3;
|
case XK_KP_End: return sf::Keyboard::Numpad1;
|
||||||
case XK_KP_Left: return sf::Keyboard::Numpad4;
|
case XK_KP_Down: return sf::Keyboard::Numpad2;
|
||||||
case XK_KP_Begin: return sf::Keyboard::Numpad5;
|
case XK_KP_Page_Down: return sf::Keyboard::Numpad3;
|
||||||
case XK_KP_Right: return sf::Keyboard::Numpad6;
|
case XK_KP_Left: return sf::Keyboard::Numpad4;
|
||||||
case XK_KP_Home: return sf::Keyboard::Numpad7;
|
case XK_KP_Begin: return sf::Keyboard::Numpad5;
|
||||||
case XK_KP_Up: return sf::Keyboard::Numpad8;
|
case XK_KP_Right: return sf::Keyboard::Numpad6;
|
||||||
case XK_KP_Page_Up: return sf::Keyboard::Numpad9;
|
case XK_KP_Home: return sf::Keyboard::Numpad7;
|
||||||
case XK_a: return sf::Keyboard::A;
|
case XK_KP_Up: return sf::Keyboard::Numpad8;
|
||||||
case XK_b: return sf::Keyboard::B;
|
case XK_KP_Page_Up: return sf::Keyboard::Numpad9;
|
||||||
case XK_c: return sf::Keyboard::C;
|
case XK_a: return sf::Keyboard::A;
|
||||||
case XK_d: return sf::Keyboard::D;
|
case XK_b: return sf::Keyboard::B;
|
||||||
case XK_e: return sf::Keyboard::E;
|
case XK_c: return sf::Keyboard::C;
|
||||||
case XK_f: return sf::Keyboard::F;
|
case XK_d: return sf::Keyboard::D;
|
||||||
case XK_g: return sf::Keyboard::G;
|
case XK_e: return sf::Keyboard::E;
|
||||||
case XK_h: return sf::Keyboard::H;
|
case XK_f: return sf::Keyboard::F;
|
||||||
case XK_i: return sf::Keyboard::I;
|
case XK_g: return sf::Keyboard::G;
|
||||||
case XK_j: return sf::Keyboard::J;
|
case XK_h: return sf::Keyboard::H;
|
||||||
case XK_k: return sf::Keyboard::K;
|
case XK_i: return sf::Keyboard::I;
|
||||||
case XK_l: return sf::Keyboard::L;
|
case XK_j: return sf::Keyboard::J;
|
||||||
case XK_m: return sf::Keyboard::M;
|
case XK_k: return sf::Keyboard::K;
|
||||||
case XK_n: return sf::Keyboard::N;
|
case XK_l: return sf::Keyboard::L;
|
||||||
case XK_o: return sf::Keyboard::O;
|
case XK_m: return sf::Keyboard::M;
|
||||||
case XK_p: return sf::Keyboard::P;
|
case XK_n: return sf::Keyboard::N;
|
||||||
case XK_q: return sf::Keyboard::Q;
|
case XK_o: return sf::Keyboard::O;
|
||||||
case XK_r: return sf::Keyboard::R;
|
case XK_p: return sf::Keyboard::P;
|
||||||
case XK_s: return sf::Keyboard::S;
|
case XK_q: return sf::Keyboard::Q;
|
||||||
case XK_t: return sf::Keyboard::T;
|
case XK_r: return sf::Keyboard::R;
|
||||||
case XK_u: return sf::Keyboard::U;
|
case XK_s: return sf::Keyboard::S;
|
||||||
case XK_v: return sf::Keyboard::V;
|
case XK_t: return sf::Keyboard::T;
|
||||||
case XK_w: return sf::Keyboard::W;
|
case XK_u: return sf::Keyboard::U;
|
||||||
case XK_x: return sf::Keyboard::X;
|
case XK_v: return sf::Keyboard::V;
|
||||||
case XK_y: return sf::Keyboard::Y;
|
case XK_w: return sf::Keyboard::W;
|
||||||
case XK_z: return sf::Keyboard::Z;
|
case XK_x: return sf::Keyboard::X;
|
||||||
case XK_0: return sf::Keyboard::Num0;
|
case XK_y: return sf::Keyboard::Y;
|
||||||
case XK_1: return sf::Keyboard::Num1;
|
case XK_z: return sf::Keyboard::Z;
|
||||||
case XK_2: return sf::Keyboard::Num2;
|
case XK_0: return sf::Keyboard::Num0;
|
||||||
case XK_3: return sf::Keyboard::Num3;
|
case XK_1: return sf::Keyboard::Num1;
|
||||||
case XK_4: return sf::Keyboard::Num4;
|
case XK_2: return sf::Keyboard::Num2;
|
||||||
case XK_5: return sf::Keyboard::Num5;
|
case XK_3: return sf::Keyboard::Num3;
|
||||||
case XK_6: return sf::Keyboard::Num6;
|
case XK_4: return sf::Keyboard::Num4;
|
||||||
case XK_7: return sf::Keyboard::Num7;
|
case XK_5: return sf::Keyboard::Num5;
|
||||||
case XK_8: return sf::Keyboard::Num8;
|
case XK_6: return sf::Keyboard::Num6;
|
||||||
case XK_9: return sf::Keyboard::Num9;
|
case XK_7: return sf::Keyboard::Num7;
|
||||||
}
|
case XK_8: return sf::Keyboard::Num8;
|
||||||
|
case XK_9: return sf::Keyboard::Num9;
|
||||||
|
}
|
||||||
|
|
||||||
return sf::Keyboard::Unknown;
|
return sf::Keyboard::Unknown;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,6 +504,8 @@ m_iconPixmap (0),
|
|||||||
m_iconMaskPixmap (0),
|
m_iconMaskPixmap (0),
|
||||||
m_lastInputTime (0)
|
m_lastInputTime (0)
|
||||||
{
|
{
|
||||||
|
using namespace WindowsImplX11Impl;
|
||||||
|
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
m_display = OpenDisplay();
|
m_display = OpenDisplay();
|
||||||
|
|
||||||
@ -549,6 +555,8 @@ m_iconPixmap (0),
|
|||||||
m_iconMaskPixmap (0),
|
m_iconMaskPixmap (0),
|
||||||
m_lastInputTime (0)
|
m_lastInputTime (0)
|
||||||
{
|
{
|
||||||
|
using namespace WindowsImplX11Impl;
|
||||||
|
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
m_display = OpenDisplay();
|
m_display = OpenDisplay();
|
||||||
|
|
||||||
@ -745,7 +753,7 @@ m_lastInputTime (0)
|
|||||||
sizeHints->flags &= ~(PMinSize | PMaxSize);
|
sizeHints->flags &= ~(PMinSize | PMaxSize);
|
||||||
XSetWMNormalHints(m_display, m_window, sizeHints);
|
XSetWMNormalHints(m_display, m_window, sizeHints);
|
||||||
XFree(sizeHints);
|
XFree(sizeHints);
|
||||||
|
|
||||||
setVideoMode(mode);
|
setVideoMode(mode);
|
||||||
switchToFullscreen();
|
switchToFullscreen();
|
||||||
}
|
}
|
||||||
@ -755,6 +763,8 @@ m_lastInputTime (0)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
WindowImplX11::~WindowImplX11()
|
WindowImplX11::~WindowImplX11()
|
||||||
{
|
{
|
||||||
|
using namespace WindowsImplX11Impl;
|
||||||
|
|
||||||
// Cleanup graphical resources
|
// Cleanup graphical resources
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
||||||
@ -804,6 +814,8 @@ WindowHandle WindowImplX11::getSystemHandle() const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplX11::processEvents()
|
void WindowImplX11::processEvents()
|
||||||
{
|
{
|
||||||
|
using namespace WindowsImplX11Impl;
|
||||||
|
|
||||||
XEvent event;
|
XEvent event;
|
||||||
|
|
||||||
// Pick out the events that are interesting for this window
|
// Pick out the events that are interesting for this window
|
||||||
@ -826,6 +838,8 @@ void WindowImplX11::processEvents()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Vector2i WindowImplX11::getPosition() const
|
Vector2i WindowImplX11::getPosition() const
|
||||||
{
|
{
|
||||||
|
using namespace WindowsImplX11Impl;
|
||||||
|
|
||||||
// Get absolute position of our window relative to root window. This
|
// Get absolute position of our window relative to root window. This
|
||||||
// takes into account all information that X11 has, including X11
|
// takes into account all information that X11 has, including X11
|
||||||
// border widths and any decorations. It corresponds to where the
|
// border widths and any decorations. It corresponds to where the
|
||||||
@ -1119,6 +1133,8 @@ void WindowImplX11::setMouseCursor(const CursorImpl& cursor)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplX11::setMouseCursorGrabbed(bool grabbed)
|
void WindowImplX11::setMouseCursorGrabbed(bool grabbed)
|
||||||
{
|
{
|
||||||
|
using namespace WindowsImplX11Impl;
|
||||||
|
|
||||||
// This has no effect in fullscreen mode
|
// This has no effect in fullscreen mode
|
||||||
if (m_fullscreen || (m_cursorGrabbed == grabbed))
|
if (m_fullscreen || (m_cursorGrabbed == grabbed))
|
||||||
return;
|
return;
|
||||||
@ -1162,6 +1178,8 @@ void WindowImplX11::setKeyRepeatEnabled(bool enabled)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplX11::requestFocus()
|
void WindowImplX11::requestFocus()
|
||||||
{
|
{
|
||||||
|
using namespace WindowsImplX11Impl;
|
||||||
|
|
||||||
// Focus is only stolen among SFML windows, not between applications
|
// Focus is only stolen among SFML windows, not between applications
|
||||||
// Check the global list of windows to find out whether an SFML window has the focus
|
// Check the global list of windows to find out whether an SFML window has the focus
|
||||||
// Note: can't handle console and other non-SFML windows belonging to the application.
|
// Note: can't handle console and other non-SFML windows belonging to the application.
|
||||||
@ -1226,6 +1244,8 @@ bool WindowImplX11::hasFocus() const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplX11::grabFocus()
|
void WindowImplX11::grabFocus()
|
||||||
{
|
{
|
||||||
|
using namespace WindowsImplX11Impl;
|
||||||
|
|
||||||
Atom netActiveWindow = None;
|
Atom netActiveWindow = None;
|
||||||
|
|
||||||
if (ewmhSupported())
|
if (ewmhSupported())
|
||||||
@ -1275,6 +1295,8 @@ void WindowImplX11::grabFocus()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplX11::setVideoMode(const VideoMode& mode)
|
void WindowImplX11::setVideoMode(const VideoMode& mode)
|
||||||
{
|
{
|
||||||
|
using namespace WindowsImplX11Impl;
|
||||||
|
|
||||||
// Skip mode switching if the new mode is equal to the desktop mode
|
// Skip mode switching if the new mode is equal to the desktop mode
|
||||||
if (mode == VideoMode::getDesktopMode())
|
if (mode == VideoMode::getDesktopMode())
|
||||||
return;
|
return;
|
||||||
@ -1379,6 +1401,8 @@ void WindowImplX11::setVideoMode(const VideoMode& mode)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplX11::resetVideoMode()
|
void WindowImplX11::resetVideoMode()
|
||||||
{
|
{
|
||||||
|
using namespace WindowsImplX11Impl;
|
||||||
|
|
||||||
if (fullscreenWindow == this)
|
if (fullscreenWindow == this)
|
||||||
{
|
{
|
||||||
// Try to set old configuration
|
// Try to set old configuration
|
||||||
@ -1441,6 +1465,8 @@ void WindowImplX11::resetVideoMode()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplX11::switchToFullscreen()
|
void WindowImplX11::switchToFullscreen()
|
||||||
{
|
{
|
||||||
|
using namespace WindowsImplX11Impl;
|
||||||
|
|
||||||
grabFocus();
|
grabFocus();
|
||||||
|
|
||||||
if (ewmhSupported())
|
if (ewmhSupported())
|
||||||
@ -1497,6 +1523,8 @@ void WindowImplX11::switchToFullscreen()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplX11::setProtocols()
|
void WindowImplX11::setProtocols()
|
||||||
{
|
{
|
||||||
|
using namespace WindowsImplX11Impl;
|
||||||
|
|
||||||
Atom wmProtocols = getAtom("WM_PROTOCOLS");
|
Atom wmProtocols = getAtom("WM_PROTOCOLS");
|
||||||
Atom wmDeleteWindow = getAtom("WM_DELETE_WINDOW");
|
Atom wmDeleteWindow = getAtom("WM_DELETE_WINDOW");
|
||||||
|
|
||||||
@ -1563,6 +1591,8 @@ void WindowImplX11::setProtocols()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplX11::initialize()
|
void WindowImplX11::initialize()
|
||||||
{
|
{
|
||||||
|
using namespace WindowsImplX11Impl;
|
||||||
|
|
||||||
// Create the input context
|
// Create the input context
|
||||||
m_inputMethod = XOpenIM(m_display, NULL, NULL, NULL);
|
m_inputMethod = XOpenIM(m_display, NULL, NULL, NULL);
|
||||||
|
|
||||||
@ -1676,6 +1706,8 @@ void WindowImplX11::cleanup()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool WindowImplX11::processEvent(XEvent& windowEvent)
|
bool WindowImplX11::processEvent(XEvent& windowEvent)
|
||||||
{
|
{
|
||||||
|
using namespace WindowsImplX11Impl;
|
||||||
|
|
||||||
// This function implements a workaround to properly discard
|
// This function implements a workaround to properly discard
|
||||||
// repeated key events when necessary. The problem is that the
|
// repeated key events when necessary. The problem is that the
|
||||||
// system's key events policy doesn't match SFML's one: X server will generate
|
// system's key events policy doesn't match SFML's one: X server will generate
|
||||||
|
@ -26,7 +26,9 @@
|
|||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Window/Win32/VulkanImplWin32.hpp>
|
#include <SFML/Window/Win32/VulkanImplWin32.hpp>
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#define VK_USE_PLATFORM_WIN32_KHR
|
#define VK_USE_PLATFORM_WIN32_KHR
|
||||||
#define VK_NO_PROTOTYPES
|
#define VK_NO_PROTOTYPES
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#define SF_GLAD_WGL_IMPLEMENTATION
|
|
||||||
#include <SFML/Window/WindowImpl.hpp> // included first to avoid a warning about macro redefinition
|
#include <SFML/Window/WindowImpl.hpp> // included first to avoid a warning about macro redefinition
|
||||||
#include <SFML/Window/Win32/WglContext.hpp>
|
#include <SFML/Window/Win32/WglContext.hpp>
|
||||||
#include <SFML/System/ThreadLocalPtr.hpp>
|
#include <SFML/System/ThreadLocalPtr.hpp>
|
||||||
@ -35,38 +34,48 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
// We check for this definition in order to avoid multiple definitions of GLAD
|
||||||
|
// entities during unity builds of SFML.
|
||||||
|
#ifndef SF_GLAD_WGL_IMPLEMENTATION_INCLUDED
|
||||||
|
#define SF_GLAD_WGL_IMPLEMENTATION_INCLUDED
|
||||||
|
#define SF_GLAD_WGL_IMPLEMENTATION
|
||||||
|
#include <glad/wgl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
// Some drivers are bugged and don't track the current HDC/HGLRC properly
|
namespace WglContextImpl
|
||||||
// In order to deactivate successfully, we need to track it ourselves as well
|
|
||||||
sf::ThreadLocalPtr<sf::priv::WglContext> currentContext(NULL);
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void ensureInit()
|
|
||||||
{
|
{
|
||||||
static bool initialized = false;
|
// Some drivers are bugged and don't track the current HDC/HGLRC properly
|
||||||
if (!initialized)
|
// In order to deactivate successfully, we need to track it ourselves as well
|
||||||
{
|
sf::ThreadLocalPtr<sf::priv::WglContext> currentContext(NULL);
|
||||||
initialized = true;
|
|
||||||
|
|
||||||
gladLoadWGL(NULL, sf::priv::WglContext::getFunction);
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void ensureInit()
|
||||||
|
{
|
||||||
|
static bool initialized = false;
|
||||||
|
if (!initialized)
|
||||||
|
{
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
|
gladLoadWGL(NULL, sf::priv::WglContext::getFunction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void ensureExtensionsInit(HDC deviceContext)
|
void ensureExtensionsInit(HDC deviceContext)
|
||||||
{
|
|
||||||
static bool initialized = false;
|
|
||||||
if (!initialized)
|
|
||||||
{
|
{
|
||||||
initialized = true;
|
static bool initialized = false;
|
||||||
|
if (!initialized)
|
||||||
|
{
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
// We don't check the return value since the extension
|
// We don't check the return value since the extension
|
||||||
// flags are cleared even if loading fails
|
// flags are cleared even if loading fails
|
||||||
gladLoadWGL(deviceContext, sf::priv::WglContext::getFunction);
|
gladLoadWGL(deviceContext, sf::priv::WglContext::getFunction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,7 +110,7 @@ m_deviceContext(NULL),
|
|||||||
m_context (NULL),
|
m_context (NULL),
|
||||||
m_ownsWindow (false)
|
m_ownsWindow (false)
|
||||||
{
|
{
|
||||||
ensureInit();
|
WglContextImpl::ensureInit();
|
||||||
|
|
||||||
// TODO: Delegate to the other constructor in C++11
|
// TODO: Delegate to the other constructor in C++11
|
||||||
|
|
||||||
@ -124,7 +133,7 @@ m_deviceContext(NULL),
|
|||||||
m_context (NULL),
|
m_context (NULL),
|
||||||
m_ownsWindow (false)
|
m_ownsWindow (false)
|
||||||
{
|
{
|
||||||
ensureInit();
|
WglContextImpl::ensureInit();
|
||||||
|
|
||||||
// Save the creation settings
|
// Save the creation settings
|
||||||
m_settings = settings;
|
m_settings = settings;
|
||||||
@ -145,7 +154,7 @@ m_deviceContext(NULL),
|
|||||||
m_context (NULL),
|
m_context (NULL),
|
||||||
m_ownsWindow (false)
|
m_ownsWindow (false)
|
||||||
{
|
{
|
||||||
ensureInit();
|
WglContextImpl::ensureInit();
|
||||||
|
|
||||||
// Save the creation settings
|
// Save the creation settings
|
||||||
m_settings = settings;
|
m_settings = settings;
|
||||||
@ -167,10 +176,10 @@ WglContext::~WglContext()
|
|||||||
// Destroy the OpenGL context
|
// Destroy the OpenGL context
|
||||||
if (m_context)
|
if (m_context)
|
||||||
{
|
{
|
||||||
if (currentContext == this)
|
if (WglContextImpl::currentContext == this)
|
||||||
{
|
{
|
||||||
if (wglMakeCurrent(m_deviceContext, NULL) == TRUE)
|
if (wglMakeCurrent(m_deviceContext, NULL) == TRUE)
|
||||||
currentContext = NULL;
|
WglContextImpl::currentContext = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
wglDeleteContext(m_context);
|
wglDeleteContext(m_context);
|
||||||
@ -234,7 +243,7 @@ bool WglContext::makeCurrent(bool current)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentContext = (current ? this : NULL);
|
WglContextImpl::currentContext = (current ? this : NULL);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -252,7 +261,7 @@ void WglContext::display()
|
|||||||
void WglContext::setVerticalSyncEnabled(bool enabled)
|
void WglContext::setVerticalSyncEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
// Make sure that extensions are initialized
|
// Make sure that extensions are initialized
|
||||||
ensureExtensionsInit(m_deviceContext);
|
WglContextImpl::ensureExtensionsInit(m_deviceContext);
|
||||||
|
|
||||||
if (SF_GLAD_WGL_EXT_swap_control)
|
if (SF_GLAD_WGL_EXT_swap_control)
|
||||||
{
|
{
|
||||||
@ -277,7 +286,7 @@ void WglContext::setVerticalSyncEnabled(bool enabled)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
int WglContext::selectBestPixelFormat(HDC deviceContext, unsigned int bitsPerPixel, const ContextSettings& settings, bool pbuffer)
|
int WglContext::selectBestPixelFormat(HDC deviceContext, unsigned int bitsPerPixel, const ContextSettings& settings, bool pbuffer)
|
||||||
{
|
{
|
||||||
ensureInit();
|
WglContextImpl::ensureInit();
|
||||||
|
|
||||||
// Let's find a suitable pixel format -- first try with wglChoosePixelFormatARB
|
// Let's find a suitable pixel format -- first try with wglChoosePixelFormatARB
|
||||||
int bestFormat = 0;
|
int bestFormat = 0;
|
||||||
@ -658,7 +667,7 @@ void WglContext::createContext(WglContext* shared)
|
|||||||
static Mutex mutex;
|
static Mutex mutex;
|
||||||
Lock lock(mutex);
|
Lock lock(mutex);
|
||||||
|
|
||||||
if (currentContext == shared)
|
if (WglContextImpl::currentContext == shared)
|
||||||
{
|
{
|
||||||
if (wglMakeCurrent(shared->m_deviceContext, NULL) == FALSE)
|
if (wglMakeCurrent(shared->m_deviceContext, NULL) == FALSE)
|
||||||
{
|
{
|
||||||
@ -666,7 +675,7 @@ void WglContext::createContext(WglContext* shared)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentContext = NULL;
|
WglContextImpl::currentContext = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -728,7 +737,7 @@ void WglContext::createContext(WglContext* shared)
|
|||||||
static Mutex mutex;
|
static Mutex mutex;
|
||||||
Lock lock(mutex);
|
Lock lock(mutex);
|
||||||
|
|
||||||
if (currentContext == shared)
|
if (WglContextImpl::currentContext == shared)
|
||||||
{
|
{
|
||||||
if (wglMakeCurrent(shared->m_deviceContext, NULL) == FALSE)
|
if (wglMakeCurrent(shared->m_deviceContext, NULL) == FALSE)
|
||||||
{
|
{
|
||||||
@ -736,7 +745,7 @@ void WglContext::createContext(WglContext* shared)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentContext = NULL;
|
WglContextImpl::currentContext = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wglShareLists(sharedContext, m_context) == FALSE)
|
if (wglShareLists(sharedContext, m_context) == FALSE)
|
||||||
@ -749,7 +758,7 @@ void WglContext::createContext(WglContext* shared)
|
|||||||
if (!shared && m_context)
|
if (!shared && m_context)
|
||||||
{
|
{
|
||||||
makeCurrent(true);
|
makeCurrent(true);
|
||||||
ensureExtensionsInit(m_deviceContext);
|
WglContextImpl::ensureExtensionsInit(m_deviceContext);
|
||||||
makeCurrent(false);
|
makeCurrent(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,9 @@
|
|||||||
#ifdef _WIN32_WINNT
|
#ifdef _WIN32_WINNT
|
||||||
#undef _WIN32_WINNT
|
#undef _WIN32_WINNT
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef WINVER
|
||||||
|
#undef WINVER
|
||||||
|
#endif
|
||||||
#define _WIN32_WINDOWS 0x0501
|
#define _WIN32_WINDOWS 0x0501
|
||||||
#define _WIN32_WINNT 0x0501
|
#define _WIN32_WINNT 0x0501
|
||||||
#define WINVER 0x0501
|
#define WINVER 0x0501
|
||||||
|
@ -33,7 +33,11 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
const sf::WindowBase* fullscreenWindow = NULL;
|
// A nested named namespace is used here to allow unity builds of SFML.
|
||||||
|
namespace WindowsBaseImpl
|
||||||
|
{
|
||||||
|
const sf::WindowBase* fullscreenWindow = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -366,14 +370,14 @@ void WindowBase::initialize()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
const WindowBase* WindowBase::getFullscreenWindow()
|
const WindowBase* WindowBase::getFullscreenWindow()
|
||||||
{
|
{
|
||||||
return fullscreenWindow;
|
return WindowsBaseImpl::fullscreenWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowBase::setFullscreenWindow(const WindowBase* window)
|
void WindowBase::setFullscreenWindow(const WindowBase* window)
|
||||||
{
|
{
|
||||||
fullscreenWindow = window;
|
WindowsBaseImpl::fullscreenWindow = window;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
Loading…
Reference in New Issue
Block a user