Various improvements on OpenGL contexts handling

git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1245 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
LaurentGom 2009-10-27 09:20:20 +00:00
parent 31b72b6385
commit 17190bd158
21 changed files with 217 additions and 225 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -16,9 +16,6 @@ namespace sample_opengl
// Create main window // Create main window
RenderWindow window = new RenderWindow(new VideoMode(800, 600), "SFML.Net OpenGL"); RenderWindow window = new RenderWindow(new VideoMode(800, 600), "SFML.Net OpenGL");
// Activate it as the target for OpenGL calls
window.SetActive();
// Setup event handlers // Setup event handlers
window.Closed += new EventHandler(OnClosed); window.Closed += new EventHandler(OnClosed);
window.KeyPressed += new EventHandler<KeyEventArgs>(OnKeyPressed); window.KeyPressed += new EventHandler<KeyEventArgs>(OnKeyPressed);
@ -79,7 +76,9 @@ namespace sample_opengl
// will be rendered on top of the background sprite // will be rendered on top of the background sprite
window.Flush(); window.Flush();
// Activate the window for OpenGL calls // Activate the window before using OpenGL commands.
// This is useless here because we have only one window which is
// always the active one, but don't forget it if you use multiple windows
window.SetActive(); window.SetActive();
// Clear depth buffer // Clear depth buffer
@ -169,8 +168,6 @@ namespace sample_opengl
/// </summary> /// </summary>
static void OnResized(object sender, SizeEventArgs e) static void OnResized(object sender, SizeEventArgs e)
{ {
RenderWindow window = (RenderWindow)sender;
window.SetActive();
Gl.glViewport(0, 0, (int)e.Width, (int)e.Height); Gl.glViewport(0, 0, (int)e.Width, (int)e.Height);
} }
} }

View File

@ -15,9 +15,6 @@ namespace sample_window
// Create the main window // Create the main window
Window window = new Window(new VideoMode(640, 480, 32), "SFML.Net Window"); Window window = new Window(new VideoMode(640, 480, 32), "SFML.Net Window");
// Activate it as the target for OpenGL calls
window.SetActive();
// Setup event handlers // Setup event handlers
window.Closed += new EventHandler(OnClosed); window.Closed += new EventHandler(OnClosed);
window.KeyPressed += new EventHandler<KeyEventArgs>(OnKeyPressed); window.KeyPressed += new EventHandler<KeyEventArgs>(OnKeyPressed);
@ -44,7 +41,9 @@ namespace sample_window
// Process events // Process events
window.DispatchEvents(); window.DispatchEvents();
// Set the active window before using OpenGL commands // Activate the window before using OpenGL commands.
// This is useless here because we have only one window which is
// always the active one, but don't forget it if you use multiple windows
window.SetActive(); window.SetActive();
// Clear color and depth buffer // Clear color and depth buffer
@ -129,8 +128,6 @@ namespace sample_window
/// </summary> /// </summary>
static void OnResized(object sender, SizeEventArgs e) static void OnResized(object sender, SizeEventArgs e)
{ {
Window window = (Window)sender;
window.SetActive();
Gl.glViewport(0, 0, (int)e.Width, (int)e.Height); Gl.glViewport(0, 0, (int)e.Width, (int)e.Height);
} }
} }

View File

@ -71,6 +71,18 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void SetActive(bool active); void SetActive(bool active);
////////////////////////////////////////////////////////////
/// \brief Make the current thread's reference context active
///
/// This function is meant to be called internally; it is used
/// to deactivate the current context by activating another one
/// (so that we still have an active context on the current thread).
///
/// \return True if operation was successful, false otherwise
///
////////////////////////////////////////////////////////////
static bool SetReferenceActive();
private : private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -17,9 +17,6 @@ int main()
// Create the main window // Create the main window
sf::Window window(sf::VideoMode(640, 480, 32), "SFML Window"); sf::Window window(sf::VideoMode(640, 480, 32), "SFML Window");
// Activate it as the target for OpenGL calls
window.SetActive();
// Create a clock for measuring the time elapsed // Create a clock for measuring the time elapsed
sf::Clock clock; sf::Clock clock;
@ -56,7 +53,9 @@ int main()
glViewport(0, 0, event.Size.Width, event.Size.Height); glViewport(0, 0, event.Size.Width, event.Size.Height);
} }
// Activate the window // Activate the window before using OpenGL commands.
// This is useless here because we have only one window which is
// always the active one, but don't forget it if you use multiple windows
window.SetActive(); window.SetActive();
// Clear color and depth buffer // Clear color and depth buffer

View File

@ -45,8 +45,6 @@ namespace sf
namespace priv namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Default constructor
////////////////////////////////////////////////////////////
AudioDevice::AudioDevice() AudioDevice::AudioDevice()
{ {
// Create the device // Create the device
@ -78,8 +76,6 @@ AudioDevice::AudioDevice()
} }
////////////////////////////////////////////////////////////
/// Destructor
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
AudioDevice::~AudioDevice() AudioDevice::~AudioDevice()
{ {
@ -94,8 +90,6 @@ AudioDevice::~AudioDevice()
} }
////////////////////////////////////////////////////////////
/// Get the unique instance of the class
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
AudioDevice& AudioDevice::GetInstance() AudioDevice& AudioDevice::GetInstance()
{ {
@ -103,8 +97,6 @@ AudioDevice& AudioDevice::GetInstance()
} }
////////////////////////////////////////////////////////////
/// Get the OpenAL audio device
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
ALCdevice* AudioDevice::GetDevice() const ALCdevice* AudioDevice::GetDevice() const
{ {
@ -112,8 +104,6 @@ ALCdevice* AudioDevice::GetDevice() const
} }
////////////////////////////////////////////////////////////
/// Get the OpenAL format that matches the given number of channels
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
ALenum AudioDevice::GetFormatFromChannelsCount(unsigned int channelsCount) const ALenum AudioDevice::GetFormatFromChannelsCount(unsigned int channelsCount) const
{ {

View File

@ -37,30 +37,30 @@ namespace sf
{ {
namespace priv namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// AudioDevice is the high-level wrapper around the audio API, /// \brief High-level wrapper around the audio API, it manages
/// it manages creation and destruction of the audio device and context /// the creation and destruction of the audio device and
/// and stores the device capabilities /// context and stores the device capabilities
///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class AudioDevice class AudioDevice
{ {
public : public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Default constructor /// \brief Default constructor
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
AudioDevice(); AudioDevice();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Destructor /// \brief Destructor
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
~AudioDevice(); ~AudioDevice();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Get the unique instance of the class /// \brief Get the unique instance of the class
/// ///
/// \return Unique instance of the class /// \return Unique instance of the class
/// ///
@ -68,7 +68,7 @@ public :
static AudioDevice& GetInstance(); static AudioDevice& GetInstance();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Get the OpenAL audio device /// \brief Get the OpenAL audio device
/// ///
/// \return OpenAL device (cannot be NULL) /// \return OpenAL device (cannot be NULL)
/// ///
@ -76,9 +76,9 @@ public :
ALCdevice* GetDevice() const; ALCdevice* GetDevice() const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Get the OpenAL format that matches the given number of channels /// \brief Get the OpenAL format that matches the given number of channels
/// ///
/// \param channelsCount : Number of channels /// \param channelsCount Number of channels
/// ///
/// \return Corresponding format /// \return Corresponding format
/// ///

View File

@ -407,8 +407,6 @@ bool Image::CopyScreen(RenderWindow& window, const IntRect& sourceRect)
myNeedArrayUpdate = true; myNeedArrayUpdate = true;
myPixelsFlipped = true; myPixelsFlipped = true;
window.SetActive(false);
return true; return true;
} }
else else

View File

@ -27,7 +27,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/Linux/RenderImageImplPBuffer.hpp> #include <SFML/Graphics/Linux/RenderImageImplPBuffer.hpp>
#include <SFML/Graphics/GLCheck.hpp> #include <SFML/Graphics/GLCheck.hpp>
#include <SFML/Window/Context.hpp> #include <SFML/Window/Context.hpp>
#include <iostream> #include <iostream>
@ -58,12 +58,12 @@ RenderImageImplPBuffer::~RenderImageImplPBuffer()
if (myPBuffer) if (myPBuffer)
glXDestroyGLXPbufferSGIX(myDisplay, myPBuffer); glXDestroyGLXPbufferSGIX(myDisplay, myPBuffer);
XCloseDisplay(myDisplay); XCloseDisplay(myDisplay);
// This is to make sure that another valid context is made // This is to make sure that another valid context is made
// active after we destroy the P-Buffer's one // active after we destroy the P-Buffer's one
Context context; Context::SetReferenceActive();
} }
@ -72,18 +72,18 @@ RenderImageImplPBuffer::~RenderImageImplPBuffer()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImageImplPBuffer::IsSupported() bool RenderImageImplPBuffer::IsSupported()
{ {
// Make sure that GLEW is initialized // Make sure that GLEW is initialized
EnsureGlewInit(); EnsureGlewInit();
return glxewIsSupported("GLX_SGIX_pbuffer"); return glxewIsSupported("GLX_SGIX_pbuffer");
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// /see RenderImageImpl::Create /// /see RenderImageImpl::Create
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImageImplPBuffer::Create(unsigned int width, unsigned int height, unsigned int, bool depthBuffer) bool RenderImageImplPBuffer::Create(unsigned int width, unsigned int height, unsigned int, bool depthBuffer)
{ {
// Store the dimensions // Store the dimensions
myWidth = width; myWidth = width;
myHeight = height; myHeight = height;
@ -91,11 +91,11 @@ bool RenderImageImplPBuffer::Create(unsigned int width, unsigned int height, uns
// Define the PBuffer attributes // Define the PBuffer attributes
int visualAttributes[] = int visualAttributes[] =
{ {
GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
GLX_RED_SIZE, 8, GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8, GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8, GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8, GLX_ALPHA_SIZE, 8,
GLX_DEPTH_SIZE, (depthBuffer ? 24 : 0), GLX_DEPTH_SIZE, (depthBuffer ? 24 : 0),
0 0
@ -106,24 +106,24 @@ bool RenderImageImplPBuffer::Create(unsigned int width, unsigned int height, uns
GLX_PBUFFER_HEIGHT, height, GLX_PBUFFER_HEIGHT, height,
0 0
}; };
// Get the available FB configurations // Get the available FB configurations
int nbConfigs = 0; int nbConfigs = 0;
GLXFBConfig* configs = glXChooseFBConfigSGIX(myDisplay, DefaultScreen(myDisplay), visualAttributes, &nbConfigs); GLXFBConfig* configs = glXChooseFBConfigSGIX(myDisplay, DefaultScreen(myDisplay), visualAttributes, &nbConfigs);
if (!configs || !nbConfigs) if (!configs || !nbConfigs)
{ {
std::cerr << "Impossible to create render image (failed to find a suitable pixel format for PBuffer)" << std::endl; std::cerr << "Impossible to create render image (failed to find a suitable pixel format for PBuffer)" << std::endl;
return false; return false;
} }
// Create the P-Buffer // Create the P-Buffer
myPBuffer = glXCreateGLXPbufferSGIX(myDisplay, configs[0], width, height, PBufferAttributes); myPBuffer = glXCreateGLXPbufferSGIX(myDisplay, configs[0], width, height, PBufferAttributes);
if (!myPBuffer) if (!myPBuffer)
{ {
std::cerr << "Impossible to create render image (failed to create the OpenGL PBuffer)" << std::endl; std::cerr << "Impossible to create render image (failed to create the OpenGL PBuffer)" << std::endl;
XFree(configs); XFree(configs);
return false; return false;
} }
// Check the actual size of the P-Buffer // Check the actual size of the P-Buffer
unsigned int actualWidth, actualHeight; unsigned int actualWidth, actualHeight;
@ -134,35 +134,35 @@ bool RenderImageImplPBuffer::Create(unsigned int width, unsigned int height, uns
std::cerr << "Impossible to create render image (failed to match the requested size). " std::cerr << "Impossible to create render image (failed to match the requested size). "
<< "Size: " << actualWidth << "x" << actualHeight << " - " << "Size: " << actualWidth << "x" << actualHeight << " - "
<< "Requested: " << width << "x" << height << "Requested: " << width << "x" << height
<< std::endl; << std::endl;
XFree(configs); XFree(configs);
return false; return false;
} }
// We'll have to share the P-Buffer context with the current context // We'll have to share the P-Buffer context with the current context
GLXDrawable currentDrawable = glXGetCurrentDrawable(); GLXDrawable currentDrawable = glXGetCurrentDrawable();
GLXContext currentContext = glXGetCurrentContext(); GLXContext currentContext = glXGetCurrentContext();
if (currentContext) if (currentContext)
glXMakeCurrent(myDisplay, NULL, NULL); glXMakeCurrent(myDisplay, NULL, NULL);
// Create the context // Create the context
XVisualInfo* visual = glXGetVisualFromFBConfig(myDisplay, configs[0]); XVisualInfo* visual = glXGetVisualFromFBConfig(myDisplay, configs[0]);
myContext = glXCreateContext(myDisplay, visual, currentContext, true); myContext = glXCreateContext(myDisplay, visual, currentContext, true);
if (!myContext) if (!myContext)
{ {
std::cerr << "Impossible to create render image (failed to create the OpenGL context)" << std::endl; std::cerr << "Impossible to create render image (failed to create the OpenGL context)" << std::endl;
XFree(configs); XFree(configs);
XFree(visual); XFree(visual);
return false; return false;
} }
// Restore the previous active context // Restore the previous active context
if (currentContext) if (currentContext)
glXMakeCurrent(myDisplay, currentDrawable, currentContext); glXMakeCurrent(myDisplay, currentDrawable, currentContext);
// Cleanup resources // Cleanup resources
XFree(configs); XFree(configs);
XFree(visual); XFree(visual);
return true; return true;
} }
@ -175,22 +175,25 @@ bool RenderImageImplPBuffer::Activate(bool active)
{ {
if (active) if (active)
{ {
if (myPBuffer && myContext && (glXGetCurrentContext() != myContext)) if (myPBuffer && myContext)
{ {
// Bind the OpenGL context of the P-Buffer if (glXGetCurrentContext() != myContext)
if (!glXMakeCurrent(myDisplay, myPBuffer, myContext)) return glXMakeCurrent(myDisplay, myPBuffer, myContext) != 0;
{ else
std::cout << "Failed to activate render image" << std::endl; return true;
return false; }
} else
{
return false;
} }
} }
else else
{ {
// We don't actually unbind the P-Buffer, for performances reasons // To deactivate the P-Buffer's context, we actually activate
// another one so that we make sure that there is always an
// active context for subsequent graphics operations
return Context::SetReferenceActive();
} }
return true;
} }
@ -199,10 +202,6 @@ bool RenderImageImplPBuffer::Activate(bool active)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImageImplPBuffer::UpdateTexture(unsigned int textureId) bool RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
{ {
// Store the current active context
GLXDrawable currentDrawable = glXGetCurrentDrawable();
GLXContext currentContext = glXGetCurrentContext();
if (Activate(true)) if (Activate(true))
{ {
// Bind the texture // Bind the texture
@ -212,8 +211,8 @@ bool RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
// Copy the rendered pixels to the image // Copy the rendered pixels to the image
GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight)); GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight));
// Restore the previous context // Deactivate the P-Buffer
glXMakeCurrent(myDisplay, currentDrawable, currentContext); Activate(false);
return true; return true;
} }

View File

@ -48,6 +48,7 @@ RenderWindow::RenderWindow()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderWindow::RenderWindow(VideoMode mode, const std::string& title, unsigned long style, const ContextSettings& settings) RenderWindow::RenderWindow(VideoMode mode, const std::string& title, unsigned long style, const ContextSettings& settings)
{ {
// Don't call the base class constructor because it contains virtual function calls
Create(mode, title, style, settings); Create(mode, title, style, settings);
} }
@ -57,6 +58,7 @@ RenderWindow::RenderWindow(VideoMode mode, const std::string& title, unsigned lo
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderWindow::RenderWindow(WindowHandle handle, const ContextSettings& settings) RenderWindow::RenderWindow(WindowHandle handle, const ContextSettings& settings)
{ {
// Don't call the base class constructor because it contains virtual function calls
Create(handle, settings); Create(handle, settings);
} }

View File

@ -67,7 +67,7 @@ RenderImageImplPBuffer::~RenderImageImplPBuffer()
// This is to make sure that another valid context is made // This is to make sure that another valid context is made
// active after we destroy the P-Buffer's one // active after we destroy the P-Buffer's one
Context context; Context::SetReferenceActive();
} }
@ -167,23 +167,25 @@ bool RenderImageImplPBuffer::Activate(bool active)
{ {
if (active) if (active)
{ {
if (myDeviceContext && myContext && (wglGetCurrentContext() != myContext)) if (myDeviceContext && myContext)
{ {
// Bind the OpenGL context of the P-Buffer if (wglGetCurrentContext() != myContext)
if (!wglMakeCurrent(myDeviceContext, myContext)) return wglMakeCurrent(myDeviceContext, myContext) != 0;
{ else
std::cout << "Failed to activate render image" << std::endl; return true;
return false; }
} else
{
return false;
} }
} }
else else
{ {
// We don't actually unbind the P-Buffer, // To deactivate the P-Buffer's context, we actually activate
// for performances and consistency reasons // another one so that we make sure that there is always an
// active context for subsequent graphics operations
return Context::SetReferenceActive();
} }
return true;
} }
@ -192,10 +194,6 @@ bool RenderImageImplPBuffer::Activate(bool active)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImageImplPBuffer::UpdateTexture(unsigned int textureId) bool RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
{ {
// Store the current active context
HDC currentDC = wglGetCurrentDC();
HGLRC currentContext = wglGetCurrentContext();
if (Activate(true)) if (Activate(true))
{ {
// Bind the texture // Bind the texture
@ -205,8 +203,8 @@ bool RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
// Copy the rendered pixels to the image // Copy the rendered pixels to the image
GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight)); GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight));
// Restore the previous context // Deactivate the P-Buffer
wglMakeCurrent(currentDC, currentContext); Activate(false);
return true; return true;
} }

View File

@ -54,4 +54,11 @@ void Context::SetActive(bool active)
} }
////////////////////////////////////////////////////////////
bool Context::SetReferenceActive()
{
return priv::ContextGL::SetReferenceActive();
}
} // namespace sf } // namespace sf

View File

@ -99,8 +99,9 @@ ContextGL::~ContextGL()
{ {
threadContext = NULL; threadContext = NULL;
} }
else if (threadContext != NULL) else if (threadContext)
{ {
// Don't call this->SetActive(false), it would lead to a pure virtual function call
threadContext->SetActive(true); threadContext->SetActive(true);
} }
} }
@ -116,27 +117,41 @@ const ContextSettings& ContextGL::GetSettings() const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool ContextGL::SetActive(bool active) bool ContextGL::SetActive(bool active)
{ {
if (MakeCurrent(active)) if (active)
{ {
if (active && (threadContext == 0)) // Activate the context
if (MakeCurrent())
{ {
// If this is the first context to be activated on this thread, make // If this is the first context to be activated on this thread, make
// it the reference context for the whole thread // it the reference context for the whole thread
threadContext = this; if (!threadContext)
} threadContext = this;
else if (!active && (threadContext != NULL) && (threadContext != this))
{
// Activate the reference context for this thread to ensure
// that there is always an active context for subsequent graphics operations
threadContext->SetActive(true);
}
return true; return true;
}
} }
else else
{ {
return false; // Deactivate the context
if (threadContext && (threadContext != this))
{
// To deactivate the context, we actually activate another one
// so that we make sure that there is always an active context
// for subsequent graphics operations
return threadContext->SetActive(true);
}
} }
// If we got there then something failed
return false;
}
////////////////////////////////////////////////////////////
bool ContextGL::SetReferenceActive()
{
if (threadContext)
return threadContext->SetActive(true);
} }

View File

@ -129,6 +129,18 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual void UseVerticalSync(bool enabled) = 0; virtual void UseVerticalSync(bool enabled) = 0;
////////////////////////////////////////////////////////////
/// \brief Make the current thread's reference context active
///
/// This function is meant to be called internally; it is used
/// to deactivate the current context by activating another one
/// (so that we still have an active context on the current thread).
///
/// \return True if operation was successful, false otherwise
///
////////////////////////////////////////////////////////////
static bool SetReferenceActive();
protected : protected :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -140,15 +152,13 @@ protected :
ContextGL(); ContextGL();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the context as the current target /// \brief Activate the context as the current target
/// for rendering /// for rendering
/// ///
/// \param active True to activate, false to deactivate
///
/// \return True on success, false if any error happened /// \return True on success, false if any error happened
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual bool MakeCurrent(bool active) = 0; virtual bool MakeCurrent() = 0;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Evaluate a pixel format configuration /// \brief Evaluate a pixel format configuration

View File

@ -113,28 +113,18 @@ ContextGLX::~ContextGLX()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool ContextGLX::MakeCurrent(bool active) bool ContextGLX::MakeCurrent()
{ {
if (active) if (myContext)
{ {
if (myContext) if (glXGetCurrentContext() != myContext)
{ return glXMakeCurrent(myDisplay, myWindow, myContext) != 0;
if (glXGetCurrentContext() != myContext)
return glXMakeCurrent(myDisplay, myWindow, myContext) != 0;
else
return true;
}
else else
{ return true;
return false;
}
} }
else else
{ {
if (glXGetCurrentContext() == myContext) return false;
return glXMakeCurrent(myDisplay, None, NULL) != 0;
else
return true;
} }
} }

View File

@ -71,15 +71,13 @@ public :
~ContextGLX(); ~ContextGLX();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the context as the current target /// \brief Activate the context as the current target
/// for rendering /// for rendering
/// ///
/// \param active True to activate, false to deactivate
///
/// \return True on success, false if any error happened /// \return True on success, false if any error happened
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual bool MakeCurrent(bool active); virtual bool MakeCurrent();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Display what has been rendered to the context so far /// \brief Display what has been rendered to the context so far

View File

@ -29,6 +29,8 @@
#include <SFML/Window/WindowImpl.hpp> #include <SFML/Window/WindowImpl.hpp>
#include <SFML/OpenGL.hpp> #include <SFML/OpenGL.hpp>
#include <SFML/Window/glext/wglext.h> #include <SFML/Window/glext/wglext.h>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Mutex.hpp>
#include <iostream> #include <iostream>
@ -38,20 +40,20 @@ namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
ContextWGL::ContextWGL(ContextWGL* shared) : ContextWGL::ContextWGL(ContextWGL* shared) :
myWindow (NULL), myWindow (NULL),
myDC (NULL), myDeviceContext(NULL),
myContext (NULL), myContext (NULL),
myOwnsWindow(true) myOwnsWindow (true)
{ {
// TODO : try to create a bitmap in memory instead of a dummy window // TODO : try to create a bitmap in memory instead of a dummy window
// Create a dummy window (disabled and hidden) // Create a dummy window (disabled and hidden)
myWindow = CreateWindowA("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, 1, 1, NULL, NULL, GetModuleHandle(NULL), NULL); myWindow = CreateWindowA("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, 1, 1, NULL, NULL, GetModuleHandle(NULL), NULL);
ShowWindow(myWindow, SW_HIDE); ShowWindow(myWindow, SW_HIDE);
myDC = GetDC(myWindow); myDeviceContext = GetDC(myWindow);
// Create the context // Create the context
if (myDC) if (myDeviceContext)
CreateContext(shared, VideoMode::GetDesktopMode().BitsPerPixel, ContextSettings(0, 0, 0)); CreateContext(shared, VideoMode::GetDesktopMode().BitsPerPixel, ContextSettings(0, 0, 0));
// Activate the context // Activate the context
@ -61,17 +63,17 @@ myOwnsWindow(true)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
ContextWGL::ContextWGL(ContextWGL* shared, const WindowImpl* owner, unsigned int bitsPerPixel, const ContextSettings& settings) : ContextWGL::ContextWGL(ContextWGL* shared, const WindowImpl* owner, unsigned int bitsPerPixel, const ContextSettings& settings) :
myWindow (NULL), myWindow (NULL),
myDC (NULL), myDeviceContext(NULL),
myContext (NULL), myContext (NULL),
myOwnsWindow(false) myOwnsWindow (false)
{ {
// Get the owner window and its device context // Get the owner window and its device context
myWindow = static_cast<HWND>(owner->GetHandle()); myWindow = static_cast<HWND>(owner->GetHandle());
myDC = GetDC(myWindow); myDeviceContext = GetDC(myWindow);
// Create the context // Create the context
if (myDC) if (myDeviceContext)
CreateContext(shared, bitsPerPixel, settings); CreateContext(shared, bitsPerPixel, settings);
// Activate the context // Activate the context
@ -91,8 +93,8 @@ ContextWGL::~ContextWGL()
} }
// Release the DC // Release the DC
if (myWindow && myDC) if (myWindow && myDeviceContext)
ReleaseDC(myWindow, myDC); ReleaseDC(myWindow, myDeviceContext);
// Destroy the window if we own it // Destroy the window if we own it
if (myWindow && myOwnsWindow) if (myWindow && myOwnsWindow)
@ -101,28 +103,18 @@ ContextWGL::~ContextWGL()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool ContextWGL::MakeCurrent(bool active) bool ContextWGL::MakeCurrent()
{ {
if (active) if (myDeviceContext && myContext)
{ {
if (myDC && myContext) if (wglGetCurrentContext() != myContext)
{ return wglMakeCurrent(myDeviceContext, myContext) != 0;
if (wglGetCurrentContext() != myContext)
return wglMakeCurrent(myDC, myContext) != 0;
else
return true;
}
else else
{ return true;
return false;
}
} }
else else
{ {
if (wglGetCurrentContext() == myContext) return false;
return wglMakeCurrent(NULL, NULL) != 0;
else
return true;
} }
} }
@ -130,8 +122,8 @@ bool ContextWGL::MakeCurrent(bool active)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void ContextWGL::Display() void ContextWGL::Display()
{ {
if (myDC && myContext) if (myDeviceContext && myContext)
SwapBuffers(myDC); SwapBuffers(myDeviceContext);
} }
@ -180,7 +172,7 @@ void ContextWGL::CreateContext(ContextWGL* shared, unsigned int bitsPerPixel, co
int formats[128]; int formats[128];
UINT nbFormats; UINT nbFormats;
float floatAttributes[] = {0, 0}; float floatAttributes[] = {0, 0};
bool isValid = wglChoosePixelFormatARB(myDC, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0; bool isValid = wglChoosePixelFormatARB(myDeviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0;
if (!isValid || (nbFormats == 0)) if (!isValid || (nbFormats == 0))
{ {
if (mySettings.AntialiasingLevel > 2) if (mySettings.AntialiasingLevel > 2)
@ -190,7 +182,7 @@ void ContextWGL::CreateContext(ContextWGL* shared, unsigned int bitsPerPixel, co
<< mySettings.AntialiasingLevel << " antialiasing levels ; trying with 2 levels" << std::endl; << mySettings.AntialiasingLevel << " antialiasing levels ; trying with 2 levels" << std::endl;
mySettings.AntialiasingLevel = intAttributes[1] = 2; mySettings.AntialiasingLevel = intAttributes[1] = 2;
isValid = wglChoosePixelFormatARB(myDC, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0; isValid = wglChoosePixelFormatARB(myDeviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0;
} }
if (!isValid || (nbFormats == 0)) if (!isValid || (nbFormats == 0))
@ -211,7 +203,7 @@ void ContextWGL::CreateContext(ContextWGL* shared, unsigned int bitsPerPixel, co
PIXELFORMATDESCRIPTOR attributes; PIXELFORMATDESCRIPTOR attributes;
attributes.nSize = sizeof(attributes); attributes.nSize = sizeof(attributes);
attributes.nVersion = 1; attributes.nVersion = 1;
DescribePixelFormat(myDC, formats[i], sizeof(attributes), &attributes); DescribePixelFormat(myDeviceContext, formats[i], sizeof(attributes), &attributes);
// Evaluate the current configuration // Evaluate the current configuration
int color = attributes.cRedBits + attributes.cGreenBits + attributes.cBlueBits + attributes.cAlphaBits; int color = attributes.cRedBits + attributes.cGreenBits + attributes.cBlueBits + attributes.cAlphaBits;
@ -243,7 +235,7 @@ void ContextWGL::CreateContext(ContextWGL* shared, unsigned int bitsPerPixel, co
descriptor.cStencilBits = static_cast<BYTE>(mySettings.StencilBits); descriptor.cStencilBits = static_cast<BYTE>(mySettings.StencilBits);
// Get the pixel format that best matches our requirements // Get the pixel format that best matches our requirements
bestFormat = ChoosePixelFormat(myDC, &descriptor); bestFormat = ChoosePixelFormat(myDeviceContext, &descriptor);
if (bestFormat == 0) if (bestFormat == 0)
{ {
std::cerr << "Failed to find a suitable pixel format for device context -- cannot create OpenGL context" << std::endl; std::cerr << "Failed to find a suitable pixel format for device context -- cannot create OpenGL context" << std::endl;
@ -255,12 +247,12 @@ void ContextWGL::CreateContext(ContextWGL* shared, unsigned int bitsPerPixel, co
PIXELFORMATDESCRIPTOR actualFormat; PIXELFORMATDESCRIPTOR actualFormat;
actualFormat.nSize = sizeof(actualFormat); actualFormat.nSize = sizeof(actualFormat);
actualFormat.nVersion = 1; actualFormat.nVersion = 1;
DescribePixelFormat(myDC, bestFormat, sizeof(actualFormat), &actualFormat); DescribePixelFormat(myDeviceContext, bestFormat, sizeof(actualFormat), &actualFormat);
mySettings.DepthBits = actualFormat.cDepthBits; mySettings.DepthBits = actualFormat.cDepthBits;
mySettings.StencilBits = actualFormat.cStencilBits; mySettings.StencilBits = actualFormat.cStencilBits;
// Set the chosen pixel format // Set the chosen pixel format
if (!SetPixelFormat(myDC, bestFormat, &actualFormat)) if (!SetPixelFormat(myDeviceContext, bestFormat, &actualFormat))
{ {
std::cerr << "Failed to set pixel format for device context -- cannot create OpenGL context" << std::endl; std::cerr << "Failed to set pixel format for device context -- cannot create OpenGL context" << std::endl;
return; return;
@ -279,13 +271,13 @@ void ContextWGL::CreateContext(ContextWGL* shared, unsigned int bitsPerPixel, co
WGL_CONTEXT_MINOR_VERSION_ARB, 0, WGL_CONTEXT_MINOR_VERSION_ARB, 0,
0, 0 0, 0
}; };
myContext = wglCreateContextAttribsARB(myDC, sharedContext, attributes); myContext = wglCreateContextAttribsARB(myDeviceContext, sharedContext, attributes);
} }
// If the OpenGL 3.0 context failed, create a regular OpenGL 1.x context // If the OpenGL 3.0 context failed, create a regular OpenGL 1.x context
if (!myContext) if (!myContext)
{ {
myContext = wglCreateContext(myDC); myContext = wglCreateContext(myDeviceContext);
if (!myContext) if (!myContext)
{ {
std::cerr << "Failed to create an OpenGL context for this window" << std::endl; std::cerr << "Failed to create an OpenGL context for this window" << std::endl;
@ -295,6 +287,10 @@ void ContextWGL::CreateContext(ContextWGL* shared, unsigned int bitsPerPixel, co
// Share this context with others // Share this context with others
if (sharedContext) if (sharedContext)
{ {
// wglShareLists doesn't seem to be thread-safe
static Mutex mutex;
Lock lock(mutex);
if (!wglShareLists(sharedContext, myContext)) if (!wglShareLists(sharedContext, myContext))
std::cerr << "Failed to share the OpenGL context" << std::endl; std::cerr << "Failed to share the OpenGL context" << std::endl;
} }

View File

@ -70,15 +70,13 @@ public :
~ContextWGL(); ~ContextWGL();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the context as the current target /// \brief Activate the context as the current target
/// for rendering /// for rendering
/// ///
/// \param active True to activate, false to deactivate
///
/// \return True on success, false if any error happened /// \return True on success, false if any error happened
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual bool MakeCurrent(bool active); virtual bool MakeCurrent();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Display what has been rendered to the context so far /// \brief Display what has been rendered to the context so far
@ -122,10 +120,10 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
HWND myWindow; ///< Window to which the context is attached HWND myWindow; ///< Window to which the context is attached
HDC myDC; ///< Device context of the window HDC myDeviceContext; ///< Device context of the window
HGLRC myContext; ///< OpenGL context HGLRC myContext; ///< OpenGL context
bool myOwnsWindow; ///< Did we create the host window? bool myOwnsWindow; ///< Did we create the host window?
}; };
} // namespace priv } // namespace priv

View File

@ -27,7 +27,6 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/Window.hpp> #include <SFML/Window/Window.hpp>
#include <SFML/Window/ContextGL.hpp> #include <SFML/Window/ContextGL.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/Window/WindowImpl.hpp> #include <SFML/Window/WindowImpl.hpp>
#include <SFML/System/Sleep.hpp> #include <SFML/System/Sleep.hpp>
#include <iostream> #include <iostream>
@ -127,16 +126,9 @@ void Window::Create(VideoMode mode, const std::string& title, unsigned long styl
style |= Style::Titlebar; style |= Style::Titlebar;
// Recreate the window implementation // Recreate the window implementation
delete myWindow;
myWindow = priv::WindowImpl::New(mode, title, style); myWindow = priv::WindowImpl::New(mode, title, style);
// Make sure another context is bound, so that:
// - the context creation can request OpenGL extensions if necessary
// - myContext can safely be destroyed (it's no longer bound)
Context context;
// Recreate the context // Recreate the context
delete myContext;
myContext = priv::ContextGL::New(myWindow, mode.BitsPerPixel, settings); myContext = priv::ContextGL::New(myWindow, mode.BitsPerPixel, settings);
// Perform common initializations // Perform common initializations
@ -147,17 +139,13 @@ void Window::Create(VideoMode mode, const std::string& title, unsigned long styl
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Window::Create(WindowHandle handle, const ContextSettings& settings) void Window::Create(WindowHandle handle, const ContextSettings& settings)
{ {
// Recreate the window implementation // Destroy the previous window implementation
Close(); Close();
// Recreate the window implementation
myWindow = priv::WindowImpl::New(handle); myWindow = priv::WindowImpl::New(handle);
// Make sure another context is bound, so that:
// - the context creation can request OpenGL extensions if necessary
// - myContext can safely be destroyed (it's no longer bound)
Context context;
// Recreate the context // Recreate the context
delete myContext;
myContext = priv::ContextGL::New(myWindow, VideoMode::GetDesktopMode().BitsPerPixel, settings); myContext = priv::ContextGL::New(myWindow, VideoMode::GetDesktopMode().BitsPerPixel, settings);
// Perform common initializations // Perform common initializations
@ -325,6 +313,7 @@ bool Window::SetActive(bool active) const
} }
else else
{ {
std::cerr << "Trying to activate the window, but it doesn't have a valid context" << std::endl;
return false; return false;
} }
} }
@ -349,11 +338,8 @@ void Window::Display()
myClock.Reset(); myClock.Reset();
// Display the backbuffer on screen // Display the backbuffer on screen
if (SetActive(true)) if (SetActive())
{
myContext->Display(); myContext->Display();
SetActive(false);
}
} }
@ -435,7 +421,7 @@ void Window::Initialize()
myLastFrameTime = 0.f; myLastFrameTime = 0.f;
// Activate the window // Activate the window
SetActive(true); SetActive();
// Notify the derived class // Notify the derived class
OnCreate(); OnCreate();