mirror of
https://github.com/SFML/SFML.git
synced 2024-11-24 20:31:05 +08:00
Add new thread-safe error logging API
This commit is contained in:
parent
7ba672139c
commit
4aee858fef
@ -40,6 +40,12 @@ namespace sf
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] SFML_SYSTEM_API std::ostream& err();
|
[[nodiscard]] SFML_SYSTEM_API std::ostream& err();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Specify buffer to which warnings and errors are logged
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SFML_SYSTEM_API void setErrorBuffer(std::streambuf* streamBuffer);
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ set(SRC
|
|||||||
${INCROOT}/Err.hpp
|
${INCROOT}/Err.hpp
|
||||||
${INCROOT}/Export.hpp
|
${INCROOT}/Export.hpp
|
||||||
${INCROOT}/InputStream.hpp
|
${INCROOT}/InputStream.hpp
|
||||||
|
${SRCROOT}/Logging.hpp
|
||||||
${INCROOT}/NativeActivity.hpp
|
${INCROOT}/NativeActivity.hpp
|
||||||
${SRCROOT}/Sleep.cpp
|
${SRCROOT}/Sleep.cpp
|
||||||
${INCROOT}/Sleep.hpp
|
${INCROOT}/Sleep.hpp
|
||||||
|
@ -26,8 +26,10 @@
|
|||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
|
#include <SFML/System/Logging.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <mutex>
|
||||||
#include <streambuf>
|
#include <streambuf>
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
@ -96,6 +98,25 @@ private:
|
|||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
|
namespace priv
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::mutex& errorStreamMutex()
|
||||||
|
{
|
||||||
|
static std::mutex mutex;
|
||||||
|
return mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::ostream& errorStream()
|
||||||
|
{
|
||||||
|
static std::ostream errorStream(std::cerr.rdbuf());
|
||||||
|
return errorStream;
|
||||||
|
}
|
||||||
|
} // namespace priv
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
std::ostream& err()
|
std::ostream& err()
|
||||||
{
|
{
|
||||||
@ -106,4 +127,12 @@ std::ostream& err()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void setErrorBuffer(std::streambuf* streamBuffer)
|
||||||
|
{
|
||||||
|
const std::lock_guard lock(priv::errorStreamMutex());
|
||||||
|
priv::errorStream().rdbuf(streamBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
62
src/SFML/System/Logging.hpp
Normal file
62
src/SFML/System/Logging.hpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2024 Laurent Gomila (laurent@sfml-dev.org)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/System/Export.hpp>
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf::priv
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get mutex for locking error stream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SFML_SYSTEM_API std::mutex& errorStreamMutex();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get error stream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SFML_SYSTEM_API std::ostream& errorStream();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Log warning or error to a given stream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
template <typename... Args>
|
||||||
|
void log(Args&&... args)
|
||||||
|
{
|
||||||
|
const std::lock_guard lock(errorStreamMutex());
|
||||||
|
(errorStream() << ... << std::forward<Args>(args));
|
||||||
|
errorStream() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sf::priv
|
@ -28,7 +28,7 @@
|
|||||||
#include <SFML/Window/Context.hpp>
|
#include <SFML/Window/Context.hpp>
|
||||||
#include <SFML/Window/GlContext.hpp>
|
#include <SFML/Window/GlContext.hpp>
|
||||||
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Logging.hpp>
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -50,7 +50,7 @@ namespace sf
|
|||||||
Context::Context() : m_context(priv::GlContext::create())
|
Context::Context() : m_context(priv::GlContext::create())
|
||||||
{
|
{
|
||||||
if (!setActive(true))
|
if (!setActive(true))
|
||||||
err() << "Failed to set context as active during construction" << std::endl;
|
priv::log("Failed to set context as active during construction");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ Context::Context() : m_context(priv::GlContext::create())
|
|||||||
Context::~Context()
|
Context::~Context()
|
||||||
{
|
{
|
||||||
if (m_context && !setActive(false))
|
if (m_context && !setActive(false))
|
||||||
err() << "Failed to set context as inactive during destruction" << std::endl;
|
priv::log("Failed to set context as inactive during destruction");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -144,7 +144,7 @@ Context::Context(const ContextSettings& settings, const Vector2u& size) :
|
|||||||
m_context(priv::GlContext::create(settings, size))
|
m_context(priv::GlContext::create(settings, size))
|
||||||
{
|
{
|
||||||
if (!setActive(true))
|
if (!setActive(true))
|
||||||
err() << "Failed to set context as active during construction" << std::endl;
|
priv::log("Failed to set context as active during construction");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
#include <SFML/Window/Cursor.hpp>
|
#include <SFML/Window/Cursor.hpp>
|
||||||
#include <SFML/Window/CursorImpl.hpp>
|
#include <SFML/Window/CursorImpl.hpp>
|
||||||
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Logging.hpp>
|
||||||
#include <SFML/System/Vector2.hpp>
|
#include <SFML/System/Vector2.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -60,7 +60,7 @@ std::optional<Cursor> Cursor::loadFromPixels(const std::uint8_t* pixels, Vector2
|
|||||||
{
|
{
|
||||||
if ((pixels == nullptr) || (size.x == 0) || (size.y == 0))
|
if ((pixels == nullptr) || (size.x == 0) || (size.y == 0))
|
||||||
{
|
{
|
||||||
err() << "Failed to load cursor from pixels (invalid arguments)" << std::endl;
|
priv::log("Failed to load cursor from pixels (invalid arguments)");
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Window/EGLCheck.hpp>
|
#include <SFML/Window/EGLCheck.hpp>
|
||||||
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Logging.hpp>
|
||||||
|
|
||||||
#include <glad/egl.h>
|
#include <glad/egl.h>
|
||||||
|
|
||||||
@ -163,9 +163,17 @@ void eglCheckError(const std::filesystem::path& file, unsigned int line, std::st
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Log the error
|
// Log the error
|
||||||
err() << "An internal EGL call failed in " << file.filename() << " (" << line << ") : "
|
priv::log("An internal EGL call failed in ",
|
||||||
<< "\nExpression:\n " << expression << "\nError description:\n " << error << "\n " << description << '\n'
|
file.filename(),
|
||||||
<< std::endl;
|
" (",
|
||||||
|
line,
|
||||||
|
") : ",
|
||||||
|
"\nExpression:\n ",
|
||||||
|
expression,
|
||||||
|
"\nError description:\n ",
|
||||||
|
error,
|
||||||
|
"\n ",
|
||||||
|
description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include <SFML/Window/EglContext.hpp>
|
#include <SFML/Window/EglContext.hpp>
|
||||||
#include <SFML/Window/WindowImpl.hpp>
|
#include <SFML/Window/WindowImpl.hpp>
|
||||||
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Logging.hpp>
|
||||||
#include <SFML/System/Sleep.hpp>
|
#include <SFML/System/Sleep.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -93,7 +93,7 @@ void ensureInit()
|
|||||||
{
|
{
|
||||||
// At this point, the failure is unrecoverable
|
// At this point, the failure is unrecoverable
|
||||||
// Dump a message to the console and let the application terminate
|
// Dump a message to the console and let the application terminate
|
||||||
sf::err() << "Failed to load EGL entry points" << std::endl;
|
sf::priv::log("Failed to load EGL entry points");
|
||||||
|
|
||||||
assert(false);
|
assert(false);
|
||||||
|
|
||||||
@ -177,9 +177,9 @@ EglContext::EglContext(EglContext* /*shared*/, const ContextSettings& /*settings
|
|||||||
{
|
{
|
||||||
EglContextImpl::ensureInit();
|
EglContextImpl::ensureInit();
|
||||||
|
|
||||||
sf::err() << "Warning: context has not been initialized. The constructor EglContext(shared, settings, size) is "
|
sf::priv::log(
|
||||||
"currently not implemented."
|
"Warning: context has not been initialized. The constructor EglContext(shared, settings, size) is "
|
||||||
<< std::endl;
|
"currently not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -424,7 +424,7 @@ XVisualInfo EglContext::selectBestVisual(::Display* xDisplay, unsigned int bitsP
|
|||||||
if (nativeVisualId == 0)
|
if (nativeVisualId == 0)
|
||||||
{
|
{
|
||||||
// Should never happen...
|
// Should never happen...
|
||||||
err() << "No EGL visual found. You should check your graphics driver" << std::endl;
|
priv::log("No EGL visual found. You should check your graphics driver");
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -439,7 +439,7 @@ XVisualInfo EglContext::selectBestVisual(::Display* xDisplay, unsigned int bitsP
|
|||||||
if (visualCount == 0)
|
if (visualCount == 0)
|
||||||
{
|
{
|
||||||
// Can't happen...
|
// Can't happen...
|
||||||
err() << "No X11 visual found. Bug in your EGL implementation ?" << std::endl;
|
priv::log("No X11 visual found. Bug in your EGL implementation ?");
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include <SFML/Window/ContextSettings.hpp>
|
#include <SFML/Window/ContextSettings.hpp>
|
||||||
#include <SFML/Window/GlContext.hpp>
|
#include <SFML/Window/GlContext.hpp>
|
||||||
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Logging.hpp>
|
||||||
|
|
||||||
#include <glad/gl.h>
|
#include <glad/gl.h>
|
||||||
|
|
||||||
@ -897,7 +897,7 @@ void GlContext::initialize(const ContextSettings& requestedSettings)
|
|||||||
|
|
||||||
if (!glGetIntegervFunc || !glGetErrorFunc || !glGetStringFunc || !glEnableFunc || !glIsEnabledFunc)
|
if (!glGetIntegervFunc || !glGetErrorFunc || !glGetStringFunc || !glEnableFunc || !glIsEnabledFunc)
|
||||||
{
|
{
|
||||||
err() << "Could not load necessary function to initialize OpenGL context" << std::endl;
|
log("Could not load necessary function to initialize OpenGL context");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -949,13 +949,12 @@ void GlContext::initialize(const ContextSettings& requestedSettings)
|
|||||||
!parseVersionString(version, "OpenGL ES ", m_settings.majorVersion, m_settings.minorVersion) &&
|
!parseVersionString(version, "OpenGL ES ", m_settings.majorVersion, m_settings.minorVersion) &&
|
||||||
!parseVersionString(version, "", m_settings.majorVersion, m_settings.minorVersion))
|
!parseVersionString(version, "", m_settings.majorVersion, m_settings.minorVersion))
|
||||||
{
|
{
|
||||||
err() << "Unable to parse OpenGL version string: " << std::quoted(version) << ", defaulting to 1.1"
|
log("Unable to parse OpenGL version string: ", std::quoted(version), ", defaulting to 1.1");
|
||||||
<< std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
err() << "Unable to retrieve OpenGL version string, defaulting to 1.1" << std::endl;
|
log("Unable to retrieve OpenGL version string, defaulting to 1.1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1038,7 +1037,7 @@ void GlContext::initialize(const ContextSettings& requestedSettings)
|
|||||||
// Check to see if the enable was successful
|
// Check to see if the enable was successful
|
||||||
if (glIsEnabledFunc(GL_FRAMEBUFFER_SRGB) == GL_FALSE)
|
if (glIsEnabledFunc(GL_FRAMEBUFFER_SRGB) == GL_FALSE)
|
||||||
{
|
{
|
||||||
err() << "Warning: Failed to enable GL_FRAMEBUFFER_SRGB" << std::endl;
|
log("Warning: Failed to enable GL_FRAMEBUFFER_SRGB");
|
||||||
m_settings.sRgbCapable = false;
|
m_settings.sRgbCapable = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1061,19 +1060,44 @@ void GlContext::checkSettings(const ContextSettings& requestedSettings) const
|
|||||||
(m_settings.antialiasingLevel < requestedSettings.antialiasingLevel) ||
|
(m_settings.antialiasingLevel < requestedSettings.antialiasingLevel) ||
|
||||||
(m_settings.depthBits < requestedSettings.depthBits) || (!m_settings.sRgbCapable && requestedSettings.sRgbCapable))
|
(m_settings.depthBits < requestedSettings.depthBits) || (!m_settings.sRgbCapable && requestedSettings.sRgbCapable))
|
||||||
{
|
{
|
||||||
err() << "Warning: The created OpenGL context does not fully meet the settings that were requested" << '\n'
|
log("Warning: The created OpenGL context does not fully meet the settings that were requested\n",
|
||||||
<< "Requested: version = " << requestedSettings.majorVersion << "." << requestedSettings.minorVersion
|
"Requested: version = ",
|
||||||
<< " ; depth bits = " << requestedSettings.depthBits << " ; stencil bits = " << requestedSettings.stencilBits
|
requestedSettings.majorVersion,
|
||||||
<< " ; AA level = " << requestedSettings.antialiasingLevel << std::boolalpha
|
".",
|
||||||
<< " ; core = " << ((requestedSettings.attributeFlags & ContextSettings::Core) != 0)
|
requestedSettings.minorVersion,
|
||||||
<< " ; debug = " << ((requestedSettings.attributeFlags & ContextSettings::Debug) != 0)
|
" ; depth bits = ",
|
||||||
<< " ; sRGB = " << requestedSettings.sRgbCapable << std::noboolalpha << '\n'
|
requestedSettings.depthBits,
|
||||||
<< "Created: version = " << m_settings.majorVersion << "." << m_settings.minorVersion
|
" ; stencil bits = ",
|
||||||
<< " ; depth bits = " << m_settings.depthBits << " ; stencil bits = " << m_settings.stencilBits
|
requestedSettings.stencilBits,
|
||||||
<< " ; AA level = " << m_settings.antialiasingLevel << std::boolalpha
|
" ; AA level = ",
|
||||||
<< " ; core = " << ((m_settings.attributeFlags & ContextSettings::Core) != 0)
|
requestedSettings.antialiasingLevel,
|
||||||
<< " ; debug = " << ((m_settings.attributeFlags & ContextSettings::Debug) != 0)
|
std::boolalpha,
|
||||||
<< " ; sRGB = " << m_settings.sRgbCapable << std::noboolalpha << std::endl;
|
" ; core = ",
|
||||||
|
((requestedSettings.attributeFlags & ContextSettings::Core) != 0),
|
||||||
|
" ; debug = ",
|
||||||
|
((requestedSettings.attributeFlags & ContextSettings::Debug) != 0),
|
||||||
|
" ; sRGB = ",
|
||||||
|
requestedSettings.sRgbCapable,
|
||||||
|
std::noboolalpha,
|
||||||
|
'\n',
|
||||||
|
"Created: version = ",
|
||||||
|
m_settings.majorVersion,
|
||||||
|
".",
|
||||||
|
m_settings.minorVersion,
|
||||||
|
" ; depth bits = ",
|
||||||
|
m_settings.depthBits,
|
||||||
|
" ; stencil bits = ",
|
||||||
|
m_settings.stencilBits,
|
||||||
|
" ; AA level = ",
|
||||||
|
m_settings.antialiasingLevel,
|
||||||
|
std::boolalpha,
|
||||||
|
" ; core = ",
|
||||||
|
((m_settings.attributeFlags & ContextSettings::Core) != 0),
|
||||||
|
" ; debug = ",
|
||||||
|
((m_settings.attributeFlags & ContextSettings::Debug) != 0),
|
||||||
|
" ; sRGB = ",
|
||||||
|
m_settings.sRgbCapable,
|
||||||
|
std::noboolalpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Window/SensorManager.hpp>
|
#include <SFML/Window/SensorManager.hpp>
|
||||||
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Logging.hpp>
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
@ -59,8 +59,7 @@ void SensorManager::setEnabled(Sensor::Type sensor, bool enabled)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
err() << "Warning: trying to enable a sensor that is not available (call Sensor::isAvailable to check it)"
|
log("Warning: trying to enable a sensor that is not available (call Sensor::isAvailable to check it)");
|
||||||
<< std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +114,7 @@ SensorManager::SensorManager()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_sensors[sensor].available = false;
|
m_sensors[sensor].available = false;
|
||||||
err() << "Warning: sensor " << i << " failed to open, will not be available" << std::endl;
|
log("Warning: sensor ", i, " failed to open, will not be available");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include <SFML/Window/Window.hpp>
|
#include <SFML/Window/Window.hpp>
|
||||||
#include <SFML/Window/WindowImpl.hpp>
|
#include <SFML/Window/WindowImpl.hpp>
|
||||||
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Logging.hpp>
|
||||||
#include <SFML/System/Sleep.hpp>
|
#include <SFML/System/Sleep.hpp>
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
@ -164,7 +164,7 @@ bool Window::setActive(bool active) const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
err() << "Failed to activate the window's context" << std::endl;
|
priv::log("Failed to activate the window's context");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,7 +201,7 @@ void Window::initialize()
|
|||||||
// Activate the window
|
// Activate the window
|
||||||
if (!setActive())
|
if (!setActive())
|
||||||
{
|
{
|
||||||
err() << "Failed to set window as active during initialization" << std::endl;
|
priv::log("Failed to set window as active during initialization");
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowBase::initialize();
|
WindowBase::initialize();
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
#include <SFML/Window/SensorManager.hpp>
|
#include <SFML/Window/SensorManager.hpp>
|
||||||
#include <SFML/Window/WindowImpl.hpp>
|
#include <SFML/Window/WindowImpl.hpp>
|
||||||
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Logging.hpp>
|
||||||
#include <SFML/System/Sleep.hpp>
|
#include <SFML/System/Sleep.hpp>
|
||||||
#include <SFML/System/Time.hpp>
|
#include <SFML/System/Time.hpp>
|
||||||
|
|
||||||
@ -126,17 +126,22 @@ std::unique_ptr<WindowImpl> WindowImpl::create(
|
|||||||
// Make sure there's not already a fullscreen window (only one is allowed)
|
// Make sure there's not already a fullscreen window (only one is allowed)
|
||||||
if (WindowImplImpl::fullscreenWindow != nullptr)
|
if (WindowImplImpl::fullscreenWindow != nullptr)
|
||||||
{
|
{
|
||||||
err() << "Creating two fullscreen windows is not allowed, switching to windowed mode" << std::endl;
|
log("Creating two fullscreen windows is not allowed, switching to windowed mode");
|
||||||
state = State::Windowed;
|
state = State::Windowed;
|
||||||
}
|
}
|
||||||
// Make sure that the chosen video mode is compatible
|
// Make sure that the chosen video mode is compatible
|
||||||
else if (!mode.isValid())
|
else if (!mode.isValid())
|
||||||
{
|
{
|
||||||
err() << "The requested video mode is not available, switching to a valid mode" << std::endl;
|
log("The requested video mode is not available, switching to a valid mode");
|
||||||
assert(!VideoMode::getFullscreenModes().empty() && "No video modes available");
|
assert(!VideoMode::getFullscreenModes().empty() && "No video modes available");
|
||||||
mode = VideoMode::getFullscreenModes()[0];
|
mode = VideoMode::getFullscreenModes()[0];
|
||||||
err() << " VideoMode: { size: { " << mode.size.x << ", " << mode.size.y
|
log(" VideoMode: { size: { ",
|
||||||
<< " }, bitsPerPixel: " << mode.bitsPerPixel << " }" << std::endl;
|
mode.size.x,
|
||||||
|
", ",
|
||||||
|
mode.size.y,
|
||||||
|
" }, bitsPerPixel: ",
|
||||||
|
mode.bitsPerPixel,
|
||||||
|
" }");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,6 @@ set(SYSTEM_SRC
|
|||||||
System/Angle.test.cpp
|
System/Angle.test.cpp
|
||||||
System/Clock.test.cpp
|
System/Clock.test.cpp
|
||||||
System/Config.test.cpp
|
System/Config.test.cpp
|
||||||
System/Err.test.cpp
|
|
||||||
System/FileInputStream.test.cpp
|
System/FileInputStream.test.cpp
|
||||||
System/MemoryInputStream.test.cpp
|
System/MemoryInputStream.test.cpp
|
||||||
System/Sleep.test.cpp
|
System/Sleep.test.cpp
|
||||||
@ -76,6 +75,7 @@ set(WINDOW_SRC
|
|||||||
Window/Context.test.cpp
|
Window/Context.test.cpp
|
||||||
Window/ContextSettings.test.cpp
|
Window/ContextSettings.test.cpp
|
||||||
Window/Cursor.test.cpp
|
Window/Cursor.test.cpp
|
||||||
|
Window/Err.test.cpp # Tested alongside Window module because the System module performs no logging
|
||||||
Window/Event.test.cpp
|
Window/Event.test.cpp
|
||||||
Window/GlResource.test.cpp
|
Window/GlResource.test.cpp
|
||||||
Window/Joystick.test.cpp
|
Window/Joystick.test.cpp
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
|
|
||||||
|
// Other 1st party headers
|
||||||
|
#include <SFML/Window/Cursor.hpp>
|
||||||
|
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
TEST_CASE("[System] sf::err")
|
TEST_CASE("[System] sf::err")
|
||||||
{
|
{
|
||||||
@ -38,4 +43,26 @@ TEST_CASE("[System] sf::err")
|
|||||||
sf::err().rdbuf(defaultStreamBuffer);
|
sf::err().rdbuf(defaultStreamBuffer);
|
||||||
CHECK(sf::err().rdbuf() == defaultStreamBuffer);
|
CHECK(sf::err().rdbuf() == defaultStreamBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("Log errors")
|
||||||
|
{
|
||||||
|
using namespace std::string_literals;
|
||||||
|
using namespace std::string_view_literals;
|
||||||
|
|
||||||
|
const std::stringstream stream;
|
||||||
|
sf::setErrorBuffer(stream.rdbuf());
|
||||||
|
|
||||||
|
// Produce logs concurrently from multiple threads
|
||||||
|
std::array threads{std::thread([] { (void)sf::Cursor::loadFromPixels(nullptr, {}, {}); }),
|
||||||
|
std::thread([] { (void)sf::Cursor::loadFromPixels(nullptr, {}, {}); }),
|
||||||
|
std::thread([] { (void)sf::Cursor::loadFromPixels(nullptr, {}, {}); })};
|
||||||
|
for (auto& thread : threads)
|
||||||
|
thread.join();
|
||||||
|
|
||||||
|
// Ensure all messages come through in their entirety without being interleaved
|
||||||
|
CHECK(stream.str() ==
|
||||||
|
"Failed to load cursor from pixels (invalid arguments)\n"
|
||||||
|
"Failed to load cursor from pixels (invalid arguments)\n"
|
||||||
|
"Failed to load cursor from pixels (invalid arguments)\n");
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user