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
RenderWindow window = new RenderWindow(new VideoMode(800, 600), "SFML.Net OpenGL");
// Activate it as the target for OpenGL calls
window.SetActive();
// Setup event handlers
window.Closed += new EventHandler(OnClosed);
window.KeyPressed += new EventHandler<KeyEventArgs>(OnKeyPressed);
@ -79,7 +76,9 @@ namespace sample_opengl
// will be rendered on top of the background sprite
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();
// Clear depth buffer
@ -169,8 +168,6 @@ namespace sample_opengl
/// </summary>
static void OnResized(object sender, SizeEventArgs e)
{
RenderWindow window = (RenderWindow)sender;
window.SetActive();
Gl.glViewport(0, 0, (int)e.Width, (int)e.Height);
}
}

View File

@ -15,9 +15,6 @@ namespace sample_window
// Create the main 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
window.Closed += new EventHandler(OnClosed);
window.KeyPressed += new EventHandler<KeyEventArgs>(OnKeyPressed);
@ -44,7 +41,9 @@ namespace sample_window
// Process events
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();
// Clear color and depth buffer
@ -129,8 +128,6 @@ namespace sample_window
/// </summary>
static void OnResized(object sender, SizeEventArgs e)
{
Window window = (Window)sender;
window.SetActive();
Gl.glViewport(0, 0, (int)e.Width, (int)e.Height);
}
}

View File

@ -71,6 +71,18 @@ public :
////////////////////////////////////////////////////////////
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 :
////////////////////////////////////////////////////////////

View File

@ -17,9 +17,6 @@ int main()
// Create the main 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
sf::Clock clock;
@ -56,7 +53,9 @@ int main()
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();
// Clear color and depth buffer

View File

@ -45,8 +45,6 @@ namespace sf
namespace priv
{
////////////////////////////////////////////////////////////
/// Default constructor
////////////////////////////////////////////////////////////
AudioDevice::AudioDevice()
{
// Create the device
@ -78,8 +76,6 @@ AudioDevice::AudioDevice()
}
////////////////////////////////////////////////////////////
/// Destructor
////////////////////////////////////////////////////////////
AudioDevice::~AudioDevice()
{
@ -94,8 +90,6 @@ AudioDevice::~AudioDevice()
}
////////////////////////////////////////////////////////////
/// Get the unique instance of the class
////////////////////////////////////////////////////////////
AudioDevice& AudioDevice::GetInstance()
{
@ -103,8 +97,6 @@ AudioDevice& AudioDevice::GetInstance()
}
////////////////////////////////////////////////////////////
/// Get the OpenAL audio device
////////////////////////////////////////////////////////////
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
{

View File

@ -37,30 +37,30 @@ namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// AudioDevice is the high-level wrapper around the audio API,
/// it manages creation and destruction of the audio device and context
/// and stores the device capabilities
/// \brief High-level wrapper around the audio API, it manages
/// the creation and destruction of the audio device and
/// context and stores the device capabilities
///
////////////////////////////////////////////////////////////
class AudioDevice
{
public :
////////////////////////////////////////////////////////////
/// Default constructor
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
AudioDevice();
////////////////////////////////////////////////////////////
/// Destructor
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~AudioDevice();
////////////////////////////////////////////////////////////
/// Get the unique instance of the class
/// \brief Get the unique instance of the class
///
/// \return Unique instance of the class
///
@ -68,7 +68,7 @@ public :
static AudioDevice& GetInstance();
////////////////////////////////////////////////////////////
/// Get the OpenAL audio device
/// \brief Get the OpenAL audio device
///
/// \return OpenAL device (cannot be NULL)
///
@ -76,9 +76,9 @@ public :
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
///

View File

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

View File

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

View File

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

View File

@ -67,7 +67,7 @@ RenderImageImplPBuffer::~RenderImageImplPBuffer()
// This is to make sure that another valid context is made
// 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 (myDeviceContext && myContext && (wglGetCurrentContext() != myContext))
if (myDeviceContext && myContext)
{
// Bind the OpenGL context of the P-Buffer
if (!wglMakeCurrent(myDeviceContext, myContext))
{
std::cout << "Failed to activate render image" << std::endl;
return false;
}
if (wglGetCurrentContext() != myContext)
return wglMakeCurrent(myDeviceContext, myContext) != 0;
else
return true;
}
else
{
return false;
}
}
else
{
// We don't actually unbind the P-Buffer,
// for performances and consistency 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;
}
@ -192,10 +194,6 @@ bool RenderImageImplPBuffer::Activate(bool active)
////////////////////////////////////////////////////////////
bool RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
{
// Store the current active context
HDC currentDC = wglGetCurrentDC();
HGLRC currentContext = wglGetCurrentContext();
if (Activate(true))
{
// Bind the texture
@ -205,8 +203,8 @@ bool RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
// Copy the rendered pixels to the image
GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight));
// Restore the previous context
wglMakeCurrent(currentDC, currentContext);
// Deactivate the P-Buffer
Activate(false);
return true;
}

View File

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

View File

@ -99,8 +99,9 @@ ContextGL::~ContextGL()
{
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);
}
}
@ -116,27 +117,41 @@ const ContextSettings& ContextGL::GetSettings() const
////////////////////////////////////////////////////////////
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
// it the reference context for the whole thread
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);
}
if (!threadContext)
threadContext = this;
return true;
return true;
}
}
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;
////////////////////////////////////////////////////////////
/// \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 :
////////////////////////////////////////////////////////////
@ -140,15 +152,13 @@ protected :
ContextGL();
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the context as the current target
/// \brief Activate the context as the current target
/// for rendering
///
/// \param active True to activate, false to deactivate
///
/// \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

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;
else
return true;
}
if (glXGetCurrentContext() != myContext)
return glXMakeCurrent(myDisplay, myWindow, myContext) != 0;
else
{
return false;
}
return true;
}
else
{
if (glXGetCurrentContext() == myContext)
return glXMakeCurrent(myDisplay, None, NULL) != 0;
else
return true;
return false;
}
}

View File

@ -71,15 +71,13 @@ public :
~ContextGLX();
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the context as the current target
/// \brief Activate the context as the current target
/// for rendering
///
/// \param active True to activate, false to deactivate
///
/// \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

View File

@ -29,6 +29,8 @@
#include <SFML/Window/WindowImpl.hpp>
#include <SFML/OpenGL.hpp>
#include <SFML/Window/glext/wglext.h>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Mutex.hpp>
#include <iostream>
@ -38,20 +40,20 @@ namespace priv
{
////////////////////////////////////////////////////////////
ContextWGL::ContextWGL(ContextWGL* shared) :
myWindow (NULL),
myDC (NULL),
myContext (NULL),
myOwnsWindow(true)
myWindow (NULL),
myDeviceContext(NULL),
myContext (NULL),
myOwnsWindow (true)
{
// TODO : try to create a bitmap in memory instead of a dummy window
// Create a dummy window (disabled and hidden)
myWindow = CreateWindowA("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, 1, 1, NULL, NULL, GetModuleHandle(NULL), NULL);
ShowWindow(myWindow, SW_HIDE);
myDC = GetDC(myWindow);
myDeviceContext = GetDC(myWindow);
// Create the context
if (myDC)
if (myDeviceContext)
CreateContext(shared, VideoMode::GetDesktopMode().BitsPerPixel, ContextSettings(0, 0, 0));
// Activate the context
@ -61,17 +63,17 @@ myOwnsWindow(true)
////////////////////////////////////////////////////////////
ContextWGL::ContextWGL(ContextWGL* shared, const WindowImpl* owner, unsigned int bitsPerPixel, const ContextSettings& settings) :
myWindow (NULL),
myDC (NULL),
myContext (NULL),
myOwnsWindow(false)
myWindow (NULL),
myDeviceContext(NULL),
myContext (NULL),
myOwnsWindow (false)
{
// Get the owner window and its device context
myWindow = static_cast<HWND>(owner->GetHandle());
myDC = GetDC(myWindow);
myDeviceContext = GetDC(myWindow);
// Create the context
if (myDC)
if (myDeviceContext)
CreateContext(shared, bitsPerPixel, settings);
// Activate the context
@ -91,8 +93,8 @@ ContextWGL::~ContextWGL()
}
// Release the DC
if (myWindow && myDC)
ReleaseDC(myWindow, myDC);
if (myWindow && myDeviceContext)
ReleaseDC(myWindow, myDeviceContext);
// Destroy the window if we own it
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(myDC, myContext) != 0;
else
return true;
}
if (wglGetCurrentContext() != myContext)
return wglMakeCurrent(myDeviceContext, myContext) != 0;
else
{
return false;
}
return true;
}
else
{
if (wglGetCurrentContext() == myContext)
return wglMakeCurrent(NULL, NULL) != 0;
else
return true;
return false;
}
}
@ -130,8 +122,8 @@ bool ContextWGL::MakeCurrent(bool active)
////////////////////////////////////////////////////////////
void ContextWGL::Display()
{
if (myDC && myContext)
SwapBuffers(myDC);
if (myDeviceContext && myContext)
SwapBuffers(myDeviceContext);
}
@ -180,7 +172,7 @@ void ContextWGL::CreateContext(ContextWGL* shared, unsigned int bitsPerPixel, co
int formats[128];
UINT nbFormats;
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 (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 = 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))
@ -211,7 +203,7 @@ void ContextWGL::CreateContext(ContextWGL* shared, unsigned int bitsPerPixel, co
PIXELFORMATDESCRIPTOR attributes;
attributes.nSize = sizeof(attributes);
attributes.nVersion = 1;
DescribePixelFormat(myDC, formats[i], sizeof(attributes), &attributes);
DescribePixelFormat(myDeviceContext, formats[i], sizeof(attributes), &attributes);
// Evaluate the current configuration
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);
// Get the pixel format that best matches our requirements
bestFormat = ChoosePixelFormat(myDC, &descriptor);
bestFormat = ChoosePixelFormat(myDeviceContext, &descriptor);
if (bestFormat == 0)
{
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;
actualFormat.nSize = sizeof(actualFormat);
actualFormat.nVersion = 1;
DescribePixelFormat(myDC, bestFormat, sizeof(actualFormat), &actualFormat);
DescribePixelFormat(myDeviceContext, bestFormat, sizeof(actualFormat), &actualFormat);
mySettings.DepthBits = actualFormat.cDepthBits;
mySettings.StencilBits = actualFormat.cStencilBits;
// 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;
return;
@ -279,13 +271,13 @@ void ContextWGL::CreateContext(ContextWGL* shared, unsigned int bitsPerPixel, co
WGL_CONTEXT_MINOR_VERSION_ARB, 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 (!myContext)
{
myContext = wglCreateContext(myDC);
myContext = wglCreateContext(myDeviceContext);
if (!myContext)
{
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
if (sharedContext)
{
// wglShareLists doesn't seem to be thread-safe
static Mutex mutex;
Lock lock(mutex);
if (!wglShareLists(sharedContext, myContext))
std::cerr << "Failed to share the OpenGL context" << std::endl;
}

View File

@ -70,15 +70,13 @@ public :
~ContextWGL();
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the context as the current target
/// \brief Activate the context as the current target
/// for rendering
///
/// \param active True to activate, false to deactivate
///
/// \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
@ -122,10 +120,10 @@ private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
HWND myWindow; ///< Window to which the context is attached
HDC myDC; ///< Device context of the window
HGLRC myContext; ///< OpenGL context
bool myOwnsWindow; ///< Did we create the host window?
HWND myWindow; ///< Window to which the context is attached
HDC myDeviceContext; ///< Device context of the window
HGLRC myContext; ///< OpenGL context
bool myOwnsWindow; ///< Did we create the host window?
};
} // namespace priv

View File

@ -27,7 +27,6 @@
////////////////////////////////////////////////////////////
#include <SFML/Window/Window.hpp>
#include <SFML/Window/ContextGL.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/Window/WindowImpl.hpp>
#include <SFML/System/Sleep.hpp>
#include <iostream>
@ -127,16 +126,9 @@ void Window::Create(VideoMode mode, const std::string& title, unsigned long styl
style |= Style::Titlebar;
// Recreate the window implementation
delete myWindow;
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
delete myContext;
myContext = priv::ContextGL::New(myWindow, mode.BitsPerPixel, settings);
// 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)
{
// Recreate the window implementation
// Destroy the previous window implementation
Close();
// Recreate the window implementation
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
delete myContext;
myContext = priv::ContextGL::New(myWindow, VideoMode::GetDesktopMode().BitsPerPixel, settings);
// Perform common initializations
@ -325,6 +313,7 @@ bool Window::SetActive(bool active) const
}
else
{
std::cerr << "Trying to activate the window, but it doesn't have a valid context" << std::endl;
return false;
}
}
@ -349,11 +338,8 @@ void Window::Display()
myClock.Reset();
// Display the backbuffer on screen
if (SetActive(true))
{
if (SetActive())
myContext->Display();
SetActive(false);
}
}
@ -435,7 +421,7 @@ void Window::Initialize()
myLastFrameTime = 0.f;
// Activate the window
SetActive(true);
SetActive();
// Notify the derived class
OnCreate();