From cc3dc29ef42fbd6e3442a9d9ce000c9d52f2ee34 Mon Sep 17 00:00:00 2001 From: David Demelier Date: Tue, 8 Oct 2013 22:40:11 +0200 Subject: [PATCH] Added joystick implementation for FreeBSD (#477) --- cmake/Config.cmake | 5 +- src/SFML/Window/CMakeLists.txt | 42 +- src/SFML/Window/FreeBSD/JoystickImpl.cpp | 380 ++++++++++ src/SFML/Window/FreeBSD/JoystickImpl.hpp | 123 ++++ src/SFML/Window/GlContext.cpp | 2 +- src/SFML/Window/InputImpl.hpp | 2 +- src/SFML/Window/JoystickImpl.hpp | 6 +- src/SFML/Window/{Linux => Unix}/Display.cpp | 2 +- src/SFML/Window/{Linux => Unix}/Display.hpp | 0 .../Window/{Linux => Unix}/GlxContext.cpp | 686 +++++++++--------- .../Window/{Linux => Unix}/GlxContext.hpp | 296 ++++---- src/SFML/Window/{Linux => Unix}/InputImpl.cpp | 4 +- src/SFML/Window/{Linux => Unix}/InputImpl.hpp | 0 .../Window/{Linux => Unix}/JoystickImpl.cpp | 0 .../Window/{Linux => Unix}/JoystickImpl.hpp | 9 +- .../Window/{Linux => Unix}/VideoModeImpl.cpp | 4 +- .../Window/{Linux => Unix}/WindowImplX11.cpp | 7 +- .../Window/{Linux => Unix}/WindowImplX11.hpp | 0 src/SFML/Window/WindowImpl.cpp | 2 +- 19 files changed, 1043 insertions(+), 527 deletions(-) create mode 100644 src/SFML/Window/FreeBSD/JoystickImpl.cpp create mode 100644 src/SFML/Window/FreeBSD/JoystickImpl.hpp rename src/SFML/Window/{Linux => Unix}/Display.cpp (97%) rename src/SFML/Window/{Linux => Unix}/Display.hpp (100%) rename src/SFML/Window/{Linux => Unix}/GlxContext.cpp (95%) rename src/SFML/Window/{Linux => Unix}/GlxContext.hpp (97%) rename src/SFML/Window/{Linux => Unix}/InputImpl.cpp (99%) rename src/SFML/Window/{Linux => Unix}/InputImpl.hpp (100%) rename src/SFML/Window/{Linux => Unix}/JoystickImpl.cpp (100%) rename src/SFML/Window/{Linux => Unix}/JoystickImpl.hpp (95%) rename src/SFML/Window/{Linux => Unix}/VideoModeImpl.cpp (99%) rename src/SFML/Window/{Linux => Unix}/WindowImplX11.cpp (99%) rename src/SFML/Window/{Linux => Unix}/WindowImplX11.hpp (100%) diff --git a/cmake/Config.cmake b/cmake/Config.cmake index ce9bb2c14..05d4a17a1 100644 --- a/cmake/Config.cmake +++ b/cmake/Config.cmake @@ -15,9 +15,10 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") endif() elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(LINUX 1) + set(UNIX 1) elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") - # FreeBSD compile path is the same as Linux - set(LINUX 1) + set(FreeBSD 1) + set(UNIX 1) elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(MACOSX 1) diff --git a/src/SFML/Window/CMakeLists.txt b/src/SFML/Window/CMakeLists.txt index 08cb2eddf..fae4ce9a6 100644 --- a/src/SFML/Window/CMakeLists.txt +++ b/src/SFML/Window/CMakeLists.txt @@ -52,22 +52,33 @@ if(WINDOWS) # make sure that we use the Unicode version of the Win API functions add_definitions(-DUNICODE) -elseif(LINUX) +elseif(UNIX) set(PLATFORM_SRC - ${SRCROOT}/Linux/Display.cpp - ${SRCROOT}/Linux/Display.hpp - ${SRCROOT}/Linux/GlxContext.cpp - ${SRCROOT}/Linux/GlxContext.hpp - ${SRCROOT}/Linux/InputImpl.cpp - ${SRCROOT}/Linux/InputImpl.hpp - ${SRCROOT}/Linux/JoystickImpl.cpp - ${SRCROOT}/Linux/JoystickImpl.hpp - ${SRCROOT}/Linux/VideoModeImpl.cpp - ${SRCROOT}/Linux/WindowImplX11.cpp - ${SRCROOT}/Linux/WindowImplX11.hpp + ${SRCROOT}/Unix/Display.cpp + ${SRCROOT}/Unix/Display.hpp + ${SRCROOT}/Unix/GlxContext.cpp + ${SRCROOT}/Unix/GlxContext.hpp + ${SRCROOT}/Unix/InputImpl.cpp + ${SRCROOT}/Unix/InputImpl.hpp + ${SRCROOT}/Unix/VideoModeImpl.cpp + ${SRCROOT}/Unix/WindowImplX11.cpp + ${SRCROOT}/Unix/WindowImplX11.hpp ) - source_group("linux" FILES ${PLATFORM_SRC}) -else() # MACOSX + if(LINUX) + set(PLATFORM_SRC + ${PLATFORM_SRC} + ${SRCROOT}/Unix/JoystickImpl.cpp + ${SRCROOT}/Unix/JoystickImpl.hpp + ) + elseif(FREEBSD) + set(PLATFORM_SRC + ${PLATFORM_SRC} + ${SRCROOT}/FreeBSD/JoystickImpl.cpp + ${SRCROOT}/FreeBSD/JoystickImpl.hpp + ) + endif() + source_group("unix" FILES ${PLATFORM_SRC}) +elseif(MACOSX) set(PLATFORM_SRC ${SRCROOT}/OSX/cpp_objc_conversion.h ${SRCROOT}/OSX/cpp_objc_conversion.mm @@ -126,6 +137,9 @@ if(WINDOWS) set(WINDOW_EXT_LIBS ${WINDOW_EXT_LIBS} winmm gdi32) elseif(LINUX) set(WINDOW_EXT_LIBS ${WINDOW_EXT_LIBS} ${X11_X11_LIB} ${X11_Xrandr_LIB}) + if(FREEBSD) + set(WINDOW_EXT_LIBS ${WINDOW_EXT_LIBS} usbhid) + endif() elseif(MACOSX) set(WINDOW_EXT_LIBS ${WINDOW_EXT_LIBS} "-framework Foundation -framework AppKit -framework IOKit -framework Carbon") endif() diff --git a/src/SFML/Window/FreeBSD/JoystickImpl.cpp b/src/SFML/Window/FreeBSD/JoystickImpl.cpp new file mode 100644 index 000000000..b4b58300e --- /dev/null +++ b/src/SFML/Window/FreeBSD/JoystickImpl.cpp @@ -0,0 +1,380 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// 2013-2013 David Demelier (demelier.david@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////// +/// \brief This file implements FreeBSD driver joystick +/// +/// It has been tested on a Saitek gamepad with 12 buttons, +/// 2 analog axis and one hat. +/// +/// Note: old joy(4) drivers are not supported and no one use that +/// anymore. +//////////////////////////////////////////////////////////// + + +namespace +{ + std::map plugged; + std::map > hatmap; + + bool isJoystick(const char *name) + { + int fd, id; + bool ret; + report_desc_t desc = NULL; + hid_data_t data = NULL; + hid_item_t item; + + // Assume it isn't + ret = false; + + if ((fd = ::open(name, O_RDONLY | O_NONBLOCK)) < 0) + return false; + + if ((desc = hid_get_report_desc(fd)) == NULL) + goto end; + + id = hid_get_report_id(fd); + if ((data = hid_start_parse(desc, 1 << hid_input, id)) == NULL) + goto end; + + while (hid_get_item(data, &item) > 0) { + switch (item.kind) { + case hid_collection: + switch (HID_PAGE(item.usage)) { + case HUP_GENERIC_DESKTOP: + switch (HID_USAGE(item.usage)) { + case HUG_JOYSTICK: + case HUG_GAME_PAD: + ret = true; + break; + default: + break; + } + default: + break; + } + default: + break; + } + } + +end: + if (desc != NULL) + hid_dispose_report_desc(desc); + if (data != NULL) + hid_end_parse(data); + close(fd); + + return ret; + } + + void updatePluggedList() + { + DIR *dp; + struct dirent *entry; + + /* + * Devices /dev/uhid are shared between joystick and any other + * human interface device. We need to iterate over all found devices + * and check if they are joysticks. The index of JoystickImpl::open + * does not match the /dev/uhid device! + */ + if ((dp = opendir("/dev")) != NULL) { + char name[FILENAME_MAX]; + int jc = 0; + + while ((entry = readdir(dp)) != NULL && jc < sf::Joystick::Count) { + if (strncmp(entry->d_name, "uhid", 4) == 0) { + std::sprintf(name, "/dev/%s", entry->d_name); + + if (isJoystick(name)) + plugged[jc++] = std::string(name); + } + } + + closedir(dp); + } + } + + int usageToAxis(int usage) + { + int axis; + + switch (usage) { + case HUG_X: + axis = sf::Joystick::X; + break; + case HUG_Y: + axis = sf::Joystick::Y; + break; + case HUG_Z: + axis = sf::Joystick::Z; + break; + case HUG_RZ: + axis = sf::Joystick::R; + break; + case HUG_RX: + axis = sf::Joystick::U; + break; + case HUG_RY: + axis = sf::Joystick::V; + break; + default: + axis = -1; + break; + } + + return axis; + } + + void hatvalToSFML(int value, sf::priv::JoystickState &state) + { + state.axes[sf::Joystick::PovX] = hatmap[value].first; + state.axes[sf::Joystick::PovY] = hatmap[value].second; + } +} + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +void JoystickImpl::initialize() +{ + hid_init(NULL); + + // Do an initial scan + updatePluggedList(); + + // Map of hat values + hatmap[0] = std::make_pair(0, 0); // center + + hatmap[1] = std::make_pair(0, -100); // top + hatmap[3] = std::make_pair(100, 0); // right + hatmap[5] = std::make_pair(0, 100); // bottom + hatmap[7] = std::make_pair(-100, 0); // left + + hatmap[2] = std::make_pair(100, -100); // top-right + hatmap[4] = std::make_pair(100, 100); // bottom-right + hatmap[6] = std::make_pair(-100, 100); // bottom-left + hatmap[8] = std::make_pair(-100, -100); // top-left +} + + +//////////////////////////////////////////////////////////// +void JoystickImpl::cleanup() +{ +} + + +//////////////////////////////////////////////////////////// +bool JoystickImpl::isConnected(unsigned int index) +{ + return plugged.find(index) != plugged.end(); +} + + +//////////////////////////////////////////////////////////// +bool JoystickImpl::open(unsigned int index) +{ + if (isConnected(index)) + { + // Open the joystick's file descriptor (read-only and non-blocking) + m_file = ::open(plugged[index].c_str(), O_RDONLY | O_NONBLOCK); + if (m_file >= 0) + { + // Reset the joystick state + m_state = JoystickState(); + + // Get the report descriptor + m_desc = hid_get_report_desc(m_file); + if (m_desc == NULL) { + ::close(m_file); + return false; + } + + // And the id + m_id = hid_get_report_id(m_file); + + // Then allocate a buffer for data retrievement + m_length = hid_report_size(m_desc, hid_input, m_id); + m_buffer = std::calloc(1, m_length); + + if (m_buffer == NULL) { + ::close(m_file); + ::hid_dispose_report_desc(m_desc); + + return false; + } + + return m_state.connected = true; + } + else + { + return false; + } + } + else + { + return false; + } +} + + +//////////////////////////////////////////////////////////// +void JoystickImpl::close() +{ + ::close(m_file); + ::hid_dispose_report_desc(m_desc); + ::free(m_buffer); +} + + +//////////////////////////////////////////////////////////// +JoystickCaps JoystickImpl::getCapabilities() const +{ + JoystickCaps caps; + hid_data_t data; + hid_item_t item; + + data = hid_start_parse(m_desc, 1 << hid_input, m_id); + + while (hid_get_item(data, &item)) { + switch (item.kind) { + case hid_input: + switch (HID_PAGE(item.usage)) { + case HUP_BUTTON: + caps.buttonCount ++; + break; + case HUP_GENERIC_DESKTOP: + { + int usage = HID_USAGE(item.usage); + int axis; + + if (usage == HUG_HAT_SWITCH) { + caps.axes[Joystick::PovX] = true; + caps.axes[Joystick::PovY] = true; + } + else if ((axis = usageToAxis(usage)) != -1) + { + caps.axes[axis] = true; + } + break; + } + default: + break; + } + default: + break; + } + } + + hid_end_parse(data); + + return caps; +} + + +//////////////////////////////////////////////////////////// +JoystickState JoystickImpl::JoystickImpl::update() +{ + while (read(m_file, m_buffer, m_length) == m_length) { + hid_data_t data; + hid_item_t item; + + data = hid_start_parse(m_desc, 1 << hid_input, m_id); + + // No memory? + if (data == NULL) + continue; + + int but = 0; + while (hid_get_item(data, &item)) { + switch (item.kind) { + case hid_input: + switch (HID_PAGE(item.usage)) { + case HUP_BUTTON: + m_state.buttons[but++] = hid_get_data(m_buffer, &item); + break; + case HUP_GENERIC_DESKTOP: + { + int usage = HID_USAGE(item.usage); + int v = hid_get_data(m_buffer, &item); + int axis; + + if (usage == HUG_HAT_SWITCH) + hatvalToSFML(v, m_state); + else if ((axis = usageToAxis(usage)) != -1) + { + int &min = item.logical_minimum; + int &max = item.logical_maximum; + + v = (v - min) * (200) / (max - min) -100; + m_state.axes[axis] = v; + } + + break; + } + default: + break; + } + default: + break; + } + } + + hid_end_parse(data); + } + + return m_state; +} + +} // namespace priv + +} // namespace sf + +// vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4: diff --git a/src/SFML/Window/FreeBSD/JoystickImpl.hpp b/src/SFML/Window/FreeBSD/JoystickImpl.hpp new file mode 100644 index 000000000..c5b9b8f50 --- /dev/null +++ b/src/SFML/Window/FreeBSD/JoystickImpl.hpp @@ -0,0 +1,123 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_JOYSTICKIMPLFREEBSD_HPP +#define SFML_JOYSTICKIMPLFREEBSD_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// + +#include +#include + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief FreeBSD implementation of joysticks +/// +/// This code has been tested on FreeBSD 9.1 only. +//////////////////////////////////////////////////////////// +class JoystickImpl +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Perform the global initialization of the joystick module + /// + //////////////////////////////////////////////////////////// + static void initialize(); + + //////////////////////////////////////////////////////////// + /// \brief Perform the global cleanup of the joystick module + /// + //////////////////////////////////////////////////////////// + static void cleanup(); + + //////////////////////////////////////////////////////////// + /// \brief Check if a joystick is currently connected + /// + /// \param index Index of the joystick to check + /// + /// \return True if the joystick is connected, false otherwise + /// + //////////////////////////////////////////////////////////// + static bool isConnected(unsigned int index); + + //////////////////////////////////////////////////////////// + /// \brief Open the joystick + /// + /// \param index Index assigned to the joystick + /// + /// \return True on success, false on failure + /// + //////////////////////////////////////////////////////////// + bool open(unsigned int index); + + //////////////////////////////////////////////////////////// + /// \brief Close the joystick + /// + //////////////////////////////////////////////////////////// + void close(); + + //////////////////////////////////////////////////////////// + /// \brief Get the joystick capabilities + /// + /// \return Joystick capabilities + /// + //////////////////////////////////////////////////////////// + JoystickCaps getCapabilities() const; + + //////////////////////////////////////////////////////////// + /// \brief Update the joystick and get its new state + /// + /// \return Joystick state + /// + //////////////////////////////////////////////////////////// + JoystickState update(); + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + int m_file; ///< File descriptor of the joystick + + report_desc_t m_desc; ///< USB report descriptor + int m_id; ///< USB id + + void *m_buffer; ///< USB HID buffer + int m_length; ///< Buffer length + + JoystickState m_state; ///< Current state of the joystick +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_JOYSTICKIMPLFREEBSD_HPP diff --git a/src/SFML/Window/GlContext.cpp b/src/SFML/Window/GlContext.cpp index ce4bfec9b..35b2b3b86 100644 --- a/src/SFML/Window/GlContext.cpp +++ b/src/SFML/Window/GlContext.cpp @@ -43,7 +43,7 @@ #elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) - #include + #include typedef sf::priv::GlxContext ContextType; #elif defined(SFML_SYSTEM_MACOS) diff --git a/src/SFML/Window/InputImpl.hpp b/src/SFML/Window/InputImpl.hpp index 0e2069da2..c091ff188 100644 --- a/src/SFML/Window/InputImpl.hpp +++ b/src/SFML/Window/InputImpl.hpp @@ -33,7 +33,7 @@ #if defined(SFML_SYSTEM_WINDOWS) #include #elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) - #include + #include #elif defined(SFML_SYSTEM_MACOS) #include #endif diff --git a/src/SFML/Window/JoystickImpl.hpp b/src/SFML/Window/JoystickImpl.hpp index 1837ab465..8411b5cc4 100644 --- a/src/SFML/Window/JoystickImpl.hpp +++ b/src/SFML/Window/JoystickImpl.hpp @@ -79,8 +79,10 @@ struct JoystickState #if defined(SFML_SYSTEM_WINDOWS) #include -#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) - #include +#elif defined(SFML_SYSTEM_LINUX) + #include +#elif defined(SFML_SYSTEM_FREEBSD) + #include #elif defined(SFML_SYSTEM_MACOS) #include #endif diff --git a/src/SFML/Window/Linux/Display.cpp b/src/SFML/Window/Unix/Display.cpp similarity index 97% rename from src/SFML/Window/Linux/Display.cpp rename to src/SFML/Window/Unix/Display.cpp index 557f8d665..21633ec10 100644 --- a/src/SFML/Window/Linux/Display.cpp +++ b/src/SFML/Window/Unix/Display.cpp @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include +#include #include diff --git a/src/SFML/Window/Linux/Display.hpp b/src/SFML/Window/Unix/Display.hpp similarity index 100% rename from src/SFML/Window/Linux/Display.hpp rename to src/SFML/Window/Unix/Display.hpp diff --git a/src/SFML/Window/Linux/GlxContext.cpp b/src/SFML/Window/Unix/GlxContext.cpp similarity index 95% rename from src/SFML/Window/Linux/GlxContext.cpp rename to src/SFML/Window/Unix/GlxContext.cpp index 6454d781f..ae5c40700 100644 --- a/src/SFML/Window/Linux/GlxContext.cpp +++ b/src/SFML/Window/Unix/GlxContext.cpp @@ -1,343 +1,343 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) -// -// 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. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#define GLX_GLXEXT_LEGACY // so that our local glxext.h is used instead of the system one -#include -#include -#include -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -GlxContext::GlxContext(GlxContext* shared) : -m_window (0), -m_context (NULL), -m_ownsWindow(true) -{ - // Open a connection with the X server - m_display = OpenDisplay(); - - // Create a dummy window (disabled and hidden) - int screen = DefaultScreen(m_display); - m_window = XCreateWindow(m_display, - RootWindow(m_display, screen), - 0, 0, - 1, 1, - 0, - DefaultDepth(m_display, screen), - InputOutput, - DefaultVisual(m_display, screen), - 0, NULL); - - // Create the context - createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, ContextSettings()); -} - - -//////////////////////////////////////////////////////////// -GlxContext::GlxContext(GlxContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) : -m_window (0), -m_context (NULL), -m_ownsWindow(false) -{ - // Open a connection with the X server - // (important: must be the same display as the owner window) - m_display = OpenDisplay(); - - // Get the owner window and its device context - m_window = static_cast< ::Window>(owner->getSystemHandle()); - - // Create the context - if (m_window) - createContext(shared, bitsPerPixel, settings); -} - - -//////////////////////////////////////////////////////////// -GlxContext::GlxContext(GlxContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height) : -m_window (0), -m_context (NULL), -m_ownsWindow(true) -{ - // Open a connection with the X server - m_display = OpenDisplay(); - - // Create the hidden window - int screen = DefaultScreen(m_display); - m_window = XCreateWindow(m_display, - RootWindow(m_display, screen), - 0, 0, - width, height, - 0, - DefaultDepth(m_display, screen), - InputOutput, - DefaultVisual(m_display, screen), - 0, NULL); - - // Create the context - createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, settings); -} - - -//////////////////////////////////////////////////////////// -GlxContext::~GlxContext() -{ - // Destroy the context - if (m_context) - { - if (glXGetCurrentContext() == m_context) - glXMakeCurrent(m_display, None, NULL); - glXDestroyContext(m_display, m_context); - } - - // Destroy the window if we own it - if (m_window && m_ownsWindow) - { - XDestroyWindow(m_display, m_window); - XFlush(m_display); - } - - // Close the connection with the X server - CloseDisplay(m_display); -} - - -//////////////////////////////////////////////////////////// -bool GlxContext::makeCurrent() -{ - return m_context && glXMakeCurrent(m_display, m_window, m_context); -} - - -//////////////////////////////////////////////////////////// -void GlxContext::display() -{ - if (m_window) - glXSwapBuffers(m_display, m_window); -} - - -//////////////////////////////////////////////////////////// -void GlxContext::setVerticalSyncEnabled(bool enabled) -{ - const GLubyte* name = reinterpret_cast("glXSwapIntervalSGI"); - PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = reinterpret_cast(glXGetProcAddress(name)); - if (glXSwapIntervalSGI) - glXSwapIntervalSGI(enabled ? 1 : 0); -} - - -//////////////////////////////////////////////////////////// -XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPerPixel, const ContextSettings& settings) -{ - // Retrieve all the visuals - int count; - XVisualInfo* visuals = XGetVisualInfo(display, 0, NULL, &count); - if (visuals) - { - // Evaluate all the returned visuals, and pick the best one1 - int bestScore = 0xFFFF; - XVisualInfo bestVisual; - for (int i = 0; i < count; ++i) - { - // Check mandatory attributes - int doubleBuffer; - glXGetConfig(display, &visuals[i], GLX_DOUBLEBUFFER, &doubleBuffer); - if (!doubleBuffer) - continue; - - // Extract the components of the current visual - int red, green, blue, alpha, depth, stencil, multiSampling, samples; - glXGetConfig(display, &visuals[i], GLX_RED_SIZE, &red); - glXGetConfig(display, &visuals[i], GLX_GREEN_SIZE, &green); - glXGetConfig(display, &visuals[i], GLX_BLUE_SIZE, &blue); - glXGetConfig(display, &visuals[i], GLX_ALPHA_SIZE, &alpha); - glXGetConfig(display, &visuals[i], GLX_DEPTH_SIZE, &depth); - glXGetConfig(display, &visuals[i], GLX_STENCIL_SIZE, &stencil); - glXGetConfig(display, &visuals[i], GLX_SAMPLE_BUFFERS_ARB, &multiSampling); - glXGetConfig(display, &visuals[i], GLX_SAMPLES_ARB, &samples); - - // Evaluate the visual - int color = red + green + blue + alpha; - int score = evaluateFormat(bitsPerPixel, settings, color, depth, stencil, multiSampling ? samples : 0); - - // If it's better than the current best, make it the new best - if (score < bestScore) - { - bestScore = score; - bestVisual = visuals[i]; - } - } - - // Free the array of visuals - XFree(visuals); - - return bestVisual; - } - else - { - // Should never happen... - err() << "No GLX visual found. You should check your graphics driver" << std::endl; - - return XVisualInfo(); - } -} - - -//////////////////////////////////////////////////////////// -void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings) -{ - XVisualInfo* visualInfo = NULL; - - // Save the creation settings - m_settings = settings; - - // Get the context to share display lists with - GLXContext toShare = shared ? shared->m_context : NULL; - - // Create the OpenGL context -- first try context versions >= 3.0 if it is requested (they require special code) - if (m_settings.majorVersion >= 3) - { - const GLubyte* name = reinterpret_cast("glXCreateContextAttribsARB"); - PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = reinterpret_cast(glXGetProcAddress(name)); - if (glXCreateContextAttribsARB) - { - // Select a GLXFB config that matches the requested context settings - int nbConfigs = 0; - int fbAttributes[] = - { - GLX_DEPTH_SIZE, settings.depthBits, - GLX_STENCIL_SIZE, settings.stencilBits, - GLX_SAMPLE_BUFFERS, settings.antialiasingLevel > 0, - GLX_SAMPLES, settings.antialiasingLevel, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, bitsPerPixel == 32 ? 8 : 0, - GLX_DOUBLEBUFFER, True, - GLX_X_RENDERABLE, True, - GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_CONFIG_CAVEAT, GLX_NONE, - None - }; - GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), fbAttributes, &nbConfigs); - if (configs && nbConfigs) - { - while (!m_context && (m_settings.majorVersion >= 3)) - { - // Create the context - int attributes[] = - { - GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast(m_settings.majorVersion), - GLX_CONTEXT_MINOR_VERSION_ARB, static_cast(m_settings.minorVersion), - GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, - 0, 0 - }; - m_context = glXCreateContextAttribsARB(m_display, configs[0], toShare, true, attributes); - - if (m_context) - { - // Ok: retrieve the config's visual - visualInfo = glXGetVisualFromFBConfig(m_display, configs[0]); - } - else - { - // If we couldn't create the context, lower the version number and try again -- stop at 3.0 - // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care - if (m_settings.minorVersion > 0) - { - // If the minor version is not 0, we decrease it and try again - m_settings.minorVersion--; - } - else - { - // If the minor version is 0, we decrease the major version - m_settings.majorVersion--; - m_settings.minorVersion = 9; - } - } - } - XFree(configs); - } - } - } - - // If the OpenGL >= 3.0 context failed or if we don't want one, create a regular OpenGL 1.x/2.x context - if (!m_context) - { - // set the context version to 2.0 (arbitrary) - m_settings.majorVersion = 2; - m_settings.minorVersion = 0; - - // Retrieve the attributes of the target window - XWindowAttributes windowAttributes; - if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0) - { - err() << "Failed to get the window attributes" << std::endl; - return; - } - - // Get its visual - XVisualInfo tpl; - tpl.screen = DefaultScreen(m_display); - tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); - int nbVisuals = 0; - visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals); - - // Create the context, using the target window's visual - m_context = glXCreateContext(m_display, visualInfo, toShare, true); - if (!m_context) - { - err() << "Failed to create an OpenGL context for this window" << std::endl; - return; - } - } - - // Update the creation settings from the chosen format - int depth, stencil, multiSampling, samples; - glXGetConfig(m_display, visualInfo, GLX_DEPTH_SIZE, &depth); - glXGetConfig(m_display, visualInfo, GLX_STENCIL_SIZE, &stencil); - glXGetConfig(m_display, visualInfo, GLX_SAMPLE_BUFFERS_ARB, &multiSampling); - glXGetConfig(m_display, visualInfo, GLX_SAMPLES_ARB, &samples); - m_settings.depthBits = static_cast(depth); - m_settings.stencilBits = static_cast(stencil); - m_settings.antialiasingLevel = multiSampling ? samples : 0; - - // Free the visual info - XFree(visualInfo); -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#define GLX_GLXEXT_LEGACY // so that our local glxext.h is used instead of the system one +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +GlxContext::GlxContext(GlxContext* shared) : +m_window (0), +m_context (NULL), +m_ownsWindow(true) +{ + // Open a connection with the X server + m_display = OpenDisplay(); + + // Create a dummy window (disabled and hidden) + int screen = DefaultScreen(m_display); + m_window = XCreateWindow(m_display, + RootWindow(m_display, screen), + 0, 0, + 1, 1, + 0, + DefaultDepth(m_display, screen), + InputOutput, + DefaultVisual(m_display, screen), + 0, NULL); + + // Create the context + createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, ContextSettings()); +} + + +//////////////////////////////////////////////////////////// +GlxContext::GlxContext(GlxContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) : +m_window (0), +m_context (NULL), +m_ownsWindow(false) +{ + // Open a connection with the X server + // (important: must be the same display as the owner window) + m_display = OpenDisplay(); + + // Get the owner window and its device context + m_window = static_cast< ::Window>(owner->getSystemHandle()); + + // Create the context + if (m_window) + createContext(shared, bitsPerPixel, settings); +} + + +//////////////////////////////////////////////////////////// +GlxContext::GlxContext(GlxContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height) : +m_window (0), +m_context (NULL), +m_ownsWindow(true) +{ + // Open a connection with the X server + m_display = OpenDisplay(); + + // Create the hidden window + int screen = DefaultScreen(m_display); + m_window = XCreateWindow(m_display, + RootWindow(m_display, screen), + 0, 0, + width, height, + 0, + DefaultDepth(m_display, screen), + InputOutput, + DefaultVisual(m_display, screen), + 0, NULL); + + // Create the context + createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, settings); +} + + +//////////////////////////////////////////////////////////// +GlxContext::~GlxContext() +{ + // Destroy the context + if (m_context) + { + if (glXGetCurrentContext() == m_context) + glXMakeCurrent(m_display, None, NULL); + glXDestroyContext(m_display, m_context); + } + + // Destroy the window if we own it + if (m_window && m_ownsWindow) + { + XDestroyWindow(m_display, m_window); + XFlush(m_display); + } + + // Close the connection with the X server + CloseDisplay(m_display); +} + + +//////////////////////////////////////////////////////////// +bool GlxContext::makeCurrent() +{ + return m_context && glXMakeCurrent(m_display, m_window, m_context); +} + + +//////////////////////////////////////////////////////////// +void GlxContext::display() +{ + if (m_window) + glXSwapBuffers(m_display, m_window); +} + + +//////////////////////////////////////////////////////////// +void GlxContext::setVerticalSyncEnabled(bool enabled) +{ + const GLubyte* name = reinterpret_cast("glXSwapIntervalSGI"); + PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = reinterpret_cast(glXGetProcAddress(name)); + if (glXSwapIntervalSGI) + glXSwapIntervalSGI(enabled ? 1 : 0); +} + + +//////////////////////////////////////////////////////////// +XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPerPixel, const ContextSettings& settings) +{ + // Retrieve all the visuals + int count; + XVisualInfo* visuals = XGetVisualInfo(display, 0, NULL, &count); + if (visuals) + { + // Evaluate all the returned visuals, and pick the best one1 + int bestScore = 0xFFFF; + XVisualInfo bestVisual; + for (int i = 0; i < count; ++i) + { + // Check mandatory attributes + int doubleBuffer; + glXGetConfig(display, &visuals[i], GLX_DOUBLEBUFFER, &doubleBuffer); + if (!doubleBuffer) + continue; + + // Extract the components of the current visual + int red, green, blue, alpha, depth, stencil, multiSampling, samples; + glXGetConfig(display, &visuals[i], GLX_RED_SIZE, &red); + glXGetConfig(display, &visuals[i], GLX_GREEN_SIZE, &green); + glXGetConfig(display, &visuals[i], GLX_BLUE_SIZE, &blue); + glXGetConfig(display, &visuals[i], GLX_ALPHA_SIZE, &alpha); + glXGetConfig(display, &visuals[i], GLX_DEPTH_SIZE, &depth); + glXGetConfig(display, &visuals[i], GLX_STENCIL_SIZE, &stencil); + glXGetConfig(display, &visuals[i], GLX_SAMPLE_BUFFERS_ARB, &multiSampling); + glXGetConfig(display, &visuals[i], GLX_SAMPLES_ARB, &samples); + + // Evaluate the visual + int color = red + green + blue + alpha; + int score = evaluateFormat(bitsPerPixel, settings, color, depth, stencil, multiSampling ? samples : 0); + + // If it's better than the current best, make it the new best + if (score < bestScore) + { + bestScore = score; + bestVisual = visuals[i]; + } + } + + // Free the array of visuals + XFree(visuals); + + return bestVisual; + } + else + { + // Should never happen... + err() << "No GLX visual found. You should check your graphics driver" << std::endl; + + return XVisualInfo(); + } +} + + +//////////////////////////////////////////////////////////// +void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings) +{ + XVisualInfo* visualInfo = NULL; + + // Save the creation settings + m_settings = settings; + + // Get the context to share display lists with + GLXContext toShare = shared ? shared->m_context : NULL; + + // Create the OpenGL context -- first try context versions >= 3.0 if it is requested (they require special code) + if (m_settings.majorVersion >= 3) + { + const GLubyte* name = reinterpret_cast("glXCreateContextAttribsARB"); + PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = reinterpret_cast(glXGetProcAddress(name)); + if (glXCreateContextAttribsARB) + { + // Select a GLXFB config that matches the requested context settings + int nbConfigs = 0; + int fbAttributes[] = + { + GLX_DEPTH_SIZE, settings.depthBits, + GLX_STENCIL_SIZE, settings.stencilBits, + GLX_SAMPLE_BUFFERS, settings.antialiasingLevel > 0, + GLX_SAMPLES, settings.antialiasingLevel, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, bitsPerPixel == 32 ? 8 : 0, + GLX_DOUBLEBUFFER, True, + GLX_X_RENDERABLE, True, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_CONFIG_CAVEAT, GLX_NONE, + None + }; + GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), fbAttributes, &nbConfigs); + if (configs && nbConfigs) + { + while (!m_context && (m_settings.majorVersion >= 3)) + { + // Create the context + int attributes[] = + { + GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast(m_settings.majorVersion), + GLX_CONTEXT_MINOR_VERSION_ARB, static_cast(m_settings.minorVersion), + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, + 0, 0 + }; + m_context = glXCreateContextAttribsARB(m_display, configs[0], toShare, true, attributes); + + if (m_context) + { + // Ok: retrieve the config's visual + visualInfo = glXGetVisualFromFBConfig(m_display, configs[0]); + } + else + { + // If we couldn't create the context, lower the version number and try again -- stop at 3.0 + // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care + if (m_settings.minorVersion > 0) + { + // If the minor version is not 0, we decrease it and try again + m_settings.minorVersion--; + } + else + { + // If the minor version is 0, we decrease the major version + m_settings.majorVersion--; + m_settings.minorVersion = 9; + } + } + } + XFree(configs); + } + } + } + + // If the OpenGL >= 3.0 context failed or if we don't want one, create a regular OpenGL 1.x/2.x context + if (!m_context) + { + // set the context version to 2.0 (arbitrary) + m_settings.majorVersion = 2; + m_settings.minorVersion = 0; + + // Retrieve the attributes of the target window + XWindowAttributes windowAttributes; + if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0) + { + err() << "Failed to get the window attributes" << std::endl; + return; + } + + // Get its visual + XVisualInfo tpl; + tpl.screen = DefaultScreen(m_display); + tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); + int nbVisuals = 0; + visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals); + + // Create the context, using the target window's visual + m_context = glXCreateContext(m_display, visualInfo, toShare, true); + if (!m_context) + { + err() << "Failed to create an OpenGL context for this window" << std::endl; + return; + } + } + + // Update the creation settings from the chosen format + int depth, stencil, multiSampling, samples; + glXGetConfig(m_display, visualInfo, GLX_DEPTH_SIZE, &depth); + glXGetConfig(m_display, visualInfo, GLX_STENCIL_SIZE, &stencil); + glXGetConfig(m_display, visualInfo, GLX_SAMPLE_BUFFERS_ARB, &multiSampling); + glXGetConfig(m_display, visualInfo, GLX_SAMPLES_ARB, &samples); + m_settings.depthBits = static_cast(depth); + m_settings.stencilBits = static_cast(stencil); + m_settings.antialiasingLevel = multiSampling ? samples : 0; + + // Free the visual info + XFree(visualInfo); +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Window/Linux/GlxContext.hpp b/src/SFML/Window/Unix/GlxContext.hpp similarity index 97% rename from src/SFML/Window/Linux/GlxContext.hpp rename to src/SFML/Window/Unix/GlxContext.hpp index 493c8586b..0fee19450 100644 --- a/src/SFML/Window/Linux/GlxContext.hpp +++ b/src/SFML/Window/Unix/GlxContext.hpp @@ -1,148 +1,148 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) -// -// 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. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_GLXCONTEXT_HPP -#define SFML_GLXCONTEXT_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Linux (GLX) implementation of OpenGL contexts -/// -//////////////////////////////////////////////////////////// -class GlxContext : public GlContext -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Create a new default context - /// - /// \param shared Context to share the new one with (can be NULL) - /// - //////////////////////////////////////////////////////////// - GlxContext(GlxContext* shared); - - //////////////////////////////////////////////////////////// - /// \brief Create a new context attached to a window - /// - /// \param shared Context to share the new one with - /// \param settings Creation parameters - /// \param owner Pointer to the owner window - /// \param bitsPerPixel Pixel depth, in bits per pixel - /// - //////////////////////////////////////////////////////////// - GlxContext(GlxContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel); - - //////////////////////////////////////////////////////////// - /// \brief Create a new context that embeds its own rendering target - /// - /// \param shared Context to share the new one with - /// \param settings Creation parameters - /// \param width Back buffer width, in pixels - /// \param height Back buffer height, in pixels - /// - //////////////////////////////////////////////////////////// - GlxContext(GlxContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~GlxContext(); - - //////////////////////////////////////////////////////////// - /// \brief Activate the context as the current target for rendering - /// - /// \return True on success, false if any error happened - /// - //////////////////////////////////////////////////////////// - virtual bool makeCurrent(); - - //////////////////////////////////////////////////////////// - /// \brief Display what has been rendered to the context so far - /// - //////////////////////////////////////////////////////////// - virtual void display(); - - //////////////////////////////////////////////////////////// - /// \brief Enable or disable vertical synchronization - /// - /// Activating vertical synchronization will limit the number - /// of frames displayed to the refresh rate of the monitor. - /// This can avoid some visual artifacts, and limit the framerate - /// to a good value (but not constant across different computers). - /// - /// \param enabled True to enable v-sync, false to deactivate - /// - //////////////////////////////////////////////////////////// - virtual void setVerticalSyncEnabled(bool enabled); - - //////////////////////////////////////////////////////////// - /// \brief Select the best GLX visual for a given set of settings - /// - /// \param display X display - /// \param bitsPerPixel Pixel depth, in bits per pixel - /// \param settings Requested context settings - /// - /// \return The best visual - /// - //////////////////////////////////////////////////////////// - static XVisualInfo selectBestVisual(::Display* display, unsigned int bitsPerPixel, const ContextSettings& settings); - -private : - - //////////////////////////////////////////////////////////// - /// \brief Create the context - /// - /// \param shared Context to share the new one with (can be NULL) - /// \param bitsPerPixel Pixel depth, in bits per pixel - /// \param settings Creation parameters - /// - //////////////////////////////////////////////////////////// - void createContext(GlxContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - ::Display* m_display; ///< Connection to the X server - ::Window m_window; ///< Window to which the context is attached - GLXContext m_context; ///< OpenGL context - bool m_ownsWindow; ///< Do we own the window associated to the context? -}; - -} // namespace priv - -} // namespace sf - -#endif // SFML_GLXCONTEXT_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_GLXCONTEXT_HPP +#define SFML_GLXCONTEXT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Linux (GLX) implementation of OpenGL contexts +/// +//////////////////////////////////////////////////////////// +class GlxContext : public GlContext +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Create a new default context + /// + /// \param shared Context to share the new one with (can be NULL) + /// + //////////////////////////////////////////////////////////// + GlxContext(GlxContext* shared); + + //////////////////////////////////////////////////////////// + /// \brief Create a new context attached to a window + /// + /// \param shared Context to share the new one with + /// \param settings Creation parameters + /// \param owner Pointer to the owner window + /// \param bitsPerPixel Pixel depth, in bits per pixel + /// + //////////////////////////////////////////////////////////// + GlxContext(GlxContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel); + + //////////////////////////////////////////////////////////// + /// \brief Create a new context that embeds its own rendering target + /// + /// \param shared Context to share the new one with + /// \param settings Creation parameters + /// \param width Back buffer width, in pixels + /// \param height Back buffer height, in pixels + /// + //////////////////////////////////////////////////////////// + GlxContext(GlxContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~GlxContext(); + + //////////////////////////////////////////////////////////// + /// \brief Activate the context as the current target for rendering + /// + /// \return True on success, false if any error happened + /// + //////////////////////////////////////////////////////////// + virtual bool makeCurrent(); + + //////////////////////////////////////////////////////////// + /// \brief Display what has been rendered to the context so far + /// + //////////////////////////////////////////////////////////// + virtual void display(); + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable vertical synchronization + /// + /// Activating vertical synchronization will limit the number + /// of frames displayed to the refresh rate of the monitor. + /// This can avoid some visual artifacts, and limit the framerate + /// to a good value (but not constant across different computers). + /// + /// \param enabled True to enable v-sync, false to deactivate + /// + //////////////////////////////////////////////////////////// + virtual void setVerticalSyncEnabled(bool enabled); + + //////////////////////////////////////////////////////////// + /// \brief Select the best GLX visual for a given set of settings + /// + /// \param display X display + /// \param bitsPerPixel Pixel depth, in bits per pixel + /// \param settings Requested context settings + /// + /// \return The best visual + /// + //////////////////////////////////////////////////////////// + static XVisualInfo selectBestVisual(::Display* display, unsigned int bitsPerPixel, const ContextSettings& settings); + +private : + + //////////////////////////////////////////////////////////// + /// \brief Create the context + /// + /// \param shared Context to share the new one with (can be NULL) + /// \param bitsPerPixel Pixel depth, in bits per pixel + /// \param settings Creation parameters + /// + //////////////////////////////////////////////////////////// + void createContext(GlxContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + ::Display* m_display; ///< Connection to the X server + ::Window m_window; ///< Window to which the context is attached + GLXContext m_context; ///< OpenGL context + bool m_ownsWindow; ///< Do we own the window associated to the context? +}; + +} // namespace priv + +} // namespace sf + +#endif // SFML_GLXCONTEXT_HPP diff --git a/src/SFML/Window/Linux/InputImpl.cpp b/src/SFML/Window/Unix/InputImpl.cpp similarity index 99% rename from src/SFML/Window/Linux/InputImpl.cpp rename to src/SFML/Window/Unix/InputImpl.cpp index a9362ff40..5023f0085 100644 --- a/src/SFML/Window/Linux/InputImpl.cpp +++ b/src/SFML/Window/Unix/InputImpl.cpp @@ -25,9 +25,9 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include +#include #include -#include +#include #include #include diff --git a/src/SFML/Window/Linux/InputImpl.hpp b/src/SFML/Window/Unix/InputImpl.hpp similarity index 100% rename from src/SFML/Window/Linux/InputImpl.hpp rename to src/SFML/Window/Unix/InputImpl.hpp diff --git a/src/SFML/Window/Linux/JoystickImpl.cpp b/src/SFML/Window/Unix/JoystickImpl.cpp similarity index 100% rename from src/SFML/Window/Linux/JoystickImpl.cpp rename to src/SFML/Window/Unix/JoystickImpl.cpp diff --git a/src/SFML/Window/Linux/JoystickImpl.hpp b/src/SFML/Window/Unix/JoystickImpl.hpp similarity index 95% rename from src/SFML/Window/Linux/JoystickImpl.hpp rename to src/SFML/Window/Unix/JoystickImpl.hpp index 869f1857d..5c335a779 100644 --- a/src/SFML/Window/Linux/JoystickImpl.hpp +++ b/src/SFML/Window/Unix/JoystickImpl.hpp @@ -28,13 +28,8 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#if defined(SFML_SYSTEM_LINUX) - #include - #include -#elif defined(SFML_SYSTEM_FREEBSD) - // #include ? - #define ABS_MAX 1 -#endif +#include +#include namespace sf diff --git a/src/SFML/Window/Linux/VideoModeImpl.cpp b/src/SFML/Window/Unix/VideoModeImpl.cpp similarity index 99% rename from src/SFML/Window/Linux/VideoModeImpl.cpp rename to src/SFML/Window/Unix/VideoModeImpl.cpp index c669a1391..860948ea7 100644 --- a/src/SFML/Window/Linux/VideoModeImpl.cpp +++ b/src/SFML/Window/Unix/VideoModeImpl.cpp @@ -26,7 +26,7 @@ // Headers //////////////////////////////////////////////////////////// #include -#include +#include #include #include #include @@ -74,7 +74,7 @@ std::vector VideoModeImpl::getFullscreenModes() { // Convert to VideoMode VideoMode mode(sizes[j].width, sizes[j].height, depths[i]); - + // Add it only if it is not already in the array if (std::find(modes.begin(), modes.end(), mode) == modes.end()) modes.push_back(mode); diff --git a/src/SFML/Window/Linux/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp similarity index 99% rename from src/SFML/Window/Linux/WindowImplX11.cpp rename to src/SFML/Window/Unix/WindowImplX11.cpp index 9b541b37f..cdd1afc99 100644 --- a/src/SFML/Window/Linux/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -26,14 +26,15 @@ // Headers //////////////////////////////////////////////////////////// #include // important to be included first (conflict with None) -#include -#include -#include +#include +#include +#include #include #include #include #include #include +#include #include #include #include diff --git a/src/SFML/Window/Linux/WindowImplX11.hpp b/src/SFML/Window/Unix/WindowImplX11.hpp similarity index 100% rename from src/SFML/Window/Linux/WindowImplX11.hpp rename to src/SFML/Window/Unix/WindowImplX11.hpp diff --git a/src/SFML/Window/WindowImpl.cpp b/src/SFML/Window/WindowImpl.cpp index 1b336c75f..50f55dabf 100644 --- a/src/SFML/Window/WindowImpl.cpp +++ b/src/SFML/Window/WindowImpl.cpp @@ -39,7 +39,7 @@ #elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) - #include + #include typedef sf::priv::WindowImplX11 WindowImplType; #elif defined(SFML_SYSTEM_MACOS)