00001 00002 // 00003 // SFML - Simple and Fast Multimedia Library 00004 // Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) 00005 // 00006 // This software is provided 'as-is', without any express or implied warranty. 00007 // In no event will the authors be held liable for any damages arising from the use of this software. 00008 // 00009 // Permission is granted to anyone to use this software for any purpose, 00010 // including commercial applications, and to alter it and redistribute it freely, 00011 // subject to the following restrictions: 00012 // 00013 // 1. The origin of this software must not be misrepresented; 00014 // you must not claim that you wrote the original software. 00015 // If you use this software in a product, an acknowledgment 00016 // in the product documentation would be appreciated but is not required. 00017 // 00018 // 2. Altered source versions must be plainly marked as such, 00019 // and must not be misrepresented as being the original software. 00020 // 00021 // 3. This notice may not be removed or altered from any source distribution. 00022 // 00024 00026 // Headers 00028 #include <SFML/Window/Win32/ContextWGL.hpp> 00029 #include <SFML/Window/WindowImpl.hpp> 00030 #include <SFML/OpenGL.hpp> 00031 #include <SFML/Window/glext/wglext.h> 00032 #include <SFML/System/Lock.hpp> 00033 #include <SFML/System/Mutex.hpp> 00034 #include <SFML/System/Err.hpp> 00035 00036 00037 namespace sf 00038 { 00039 namespace priv 00040 { 00042 ContextWGL::ContextWGL(ContextWGL* shared) : 00043 myWindow (NULL), 00044 myDeviceContext(NULL), 00045 myContext (NULL), 00046 myOwnsWindow (true) 00047 { 00048 // Creating a dummy window is mandatory: we could create a memory DC but then 00049 // its pixel format wouldn't match the regular contexts' format, and thus 00050 // wglShareLists would always fail. Too bad... 00051 00052 // Create a dummy window (disabled and hidden) 00053 myWindow = CreateWindowA("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, 1, 1, NULL, NULL, GetModuleHandle(NULL), NULL); 00054 ShowWindow(myWindow, SW_HIDE); 00055 myDeviceContext = GetDC(myWindow); 00056 00057 // Create the context 00058 if (myDeviceContext) 00059 CreateContext(shared, VideoMode::GetDesktopMode().BitsPerPixel, ContextSettings(0, 0, 0)); 00060 00061 // Activate the context 00062 SetActive(true); 00063 } 00064 00065 00067 ContextWGL::ContextWGL(ContextWGL* shared, const WindowImpl* owner, unsigned int bitsPerPixel, const ContextSettings& settings) : 00068 myWindow (NULL), 00069 myDeviceContext(NULL), 00070 myContext (NULL), 00071 myOwnsWindow (false) 00072 { 00073 // Get the owner window and its device context 00074 myWindow = static_cast<HWND>(owner->GetHandle()); 00075 myDeviceContext = GetDC(myWindow); 00076 00077 // Create the context 00078 if (myDeviceContext) 00079 CreateContext(shared, bitsPerPixel, settings); 00080 00081 // Activate the context 00082 SetActive(true); 00083 } 00084 00085 00087 ContextWGL::~ContextWGL() 00088 { 00089 // Destroy the OpenGL context 00090 if (myContext) 00091 { 00092 if (wglGetCurrentContext() == myContext) 00093 wglMakeCurrent(NULL, NULL); 00094 wglDeleteContext(myContext); 00095 } 00096 00097 // Release the DC 00098 if (myWindow && myDeviceContext) 00099 ReleaseDC(myWindow, myDeviceContext); 00100 00101 // Destroy the window if we own it 00102 if (myWindow && myOwnsWindow) 00103 DestroyWindow(myWindow); 00104 } 00105 00106 00108 bool ContextWGL::MakeCurrent() 00109 { 00110 if (myDeviceContext && myContext) 00111 { 00112 if (wglGetCurrentContext() != myContext) 00113 return wglMakeCurrent(myDeviceContext, myContext) != 0; 00114 else 00115 return true; 00116 } 00117 else 00118 { 00119 return false; 00120 } 00121 } 00122 00123 00125 void ContextWGL::Display() 00126 { 00127 if (myDeviceContext && myContext) 00128 SwapBuffers(myDeviceContext); 00129 } 00130 00131 00133 void ContextWGL::UseVerticalSync(bool enabled) 00134 { 00135 PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = reinterpret_cast<PFNWGLSWAPINTERVALEXTPROC>(wglGetProcAddress("wglSwapIntervalEXT")); 00136 if (wglSwapIntervalEXT) 00137 wglSwapIntervalEXT(enabled ? 1 : 0); 00138 } 00139 00140 00142 void ContextWGL::CreateContext(ContextWGL* shared, unsigned int bitsPerPixel, const ContextSettings& settings) 00143 { 00144 // Save the creation settings 00145 mySettings = settings; 00146 00147 // Let's find a suitable pixel format -- first try with antialiasing 00148 int bestFormat = 0; 00149 if (mySettings.AntialiasingLevel > 0) 00150 { 00151 // Get the wglChoosePixelFormatARB function (it is an extension) 00152 PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>(wglGetProcAddress("wglChoosePixelFormatARB")); 00153 if (wglChoosePixelFormatARB) 00154 { 00155 // Define the basic attributes we want for our window 00156 int intAttributes[] = 00157 { 00158 WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, 00159 WGL_SUPPORT_OPENGL_ARB, GL_TRUE, 00160 WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, 00161 WGL_DOUBLE_BUFFER_ARB, GL_TRUE, 00162 WGL_SAMPLE_BUFFERS_ARB, (mySettings.AntialiasingLevel ? GL_TRUE : GL_FALSE), 00163 WGL_SAMPLES_ARB, mySettings.AntialiasingLevel, 00164 0, 0 00165 }; 00166 00167 // Let's check how many formats are supporting our requirements 00168 int formats[128]; 00169 UINT nbFormats; 00170 float floatAttributes[] = {0, 0}; 00171 bool isValid = wglChoosePixelFormatARB(myDeviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0; 00172 while ((!isValid || (nbFormats == 0)) && mySettings.AntialiasingLevel > 0) 00173 { 00174 // Decrease the antialiasing level until we find a valid one 00175 mySettings.AntialiasingLevel--; 00176 intAttributes[11] = mySettings.AntialiasingLevel; 00177 isValid = wglChoosePixelFormatARB(myDeviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0; 00178 } 00179 00180 // Get the best format among the returned ones 00181 if (isValid && (nbFormats > 0)) 00182 { 00183 int bestScore = 0xFFFF; 00184 for (UINT i = 0; i < nbFormats; ++i) 00185 { 00186 // Get the current format's attributes 00187 PIXELFORMATDESCRIPTOR attributes; 00188 attributes.nSize = sizeof(attributes); 00189 attributes.nVersion = 1; 00190 DescribePixelFormat(myDeviceContext, formats[i], sizeof(attributes), &attributes); 00191 00192 // Evaluate the current configuration 00193 int color = attributes.cRedBits + attributes.cGreenBits + attributes.cBlueBits + attributes.cAlphaBits; 00194 int score = EvaluateFormat(bitsPerPixel, mySettings, color, attributes.cDepthBits, attributes.cStencilBits, mySettings.AntialiasingLevel); 00195 00196 // Keep it if it's better than the current best 00197 if (score < bestScore) 00198 { 00199 bestScore = score; 00200 bestFormat = formats[i]; 00201 } 00202 } 00203 } 00204 } 00205 else 00206 { 00207 // wglChoosePixelFormatARB not supported ; disabling antialiasing 00208 Err() << "Antialiasing is not supported ; it will be disabled" << std::endl; 00209 mySettings.AntialiasingLevel = 0; 00210 } 00211 } 00212 00213 // Find a pixel format with no antialiasing, if not needed or not supported 00214 if (bestFormat == 0) 00215 { 00216 // Setup a pixel format descriptor from the rendering settings 00217 PIXELFORMATDESCRIPTOR descriptor; 00218 ZeroMemory(&descriptor, sizeof(descriptor)); 00219 descriptor.nSize = sizeof(descriptor); 00220 descriptor.nVersion = 1; 00221 descriptor.iLayerType = PFD_MAIN_PLANE; 00222 descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; 00223 descriptor.iPixelType = PFD_TYPE_RGBA; 00224 descriptor.cColorBits = static_cast<BYTE>(bitsPerPixel); 00225 descriptor.cDepthBits = static_cast<BYTE>(mySettings.DepthBits); 00226 descriptor.cStencilBits = static_cast<BYTE>(mySettings.StencilBits); 00227 descriptor.cAlphaBits = bitsPerPixel == 32 ? 8 : 0; 00228 00229 // Get the pixel format that best matches our requirements 00230 bestFormat = ChoosePixelFormat(myDeviceContext, &descriptor); 00231 if (bestFormat == 0) 00232 { 00233 Err() << "Failed to find a suitable pixel format for device context -- cannot create OpenGL context" << std::endl; 00234 return; 00235 } 00236 } 00237 00238 // Extract the depth and stencil bits from the chosen format 00239 PIXELFORMATDESCRIPTOR actualFormat; 00240 actualFormat.nSize = sizeof(actualFormat); 00241 actualFormat.nVersion = 1; 00242 DescribePixelFormat(myDeviceContext, bestFormat, sizeof(actualFormat), &actualFormat); 00243 mySettings.DepthBits = actualFormat.cDepthBits; 00244 mySettings.StencilBits = actualFormat.cStencilBits; 00245 00246 // Set the chosen pixel format 00247 if (!SetPixelFormat(myDeviceContext, bestFormat, &actualFormat)) 00248 { 00249 Err() << "Failed to set pixel format for device context -- cannot create OpenGL context" << std::endl; 00250 return; 00251 } 00252 00253 // Get the context to share display lists with 00254 HGLRC sharedContext = shared ? shared->myContext : NULL; 00255 00256 // Create the OpenGL context -- first try an OpenGL 3.0 context if it is requested 00257 while (!myContext && (mySettings.MajorVersion >= 3)) 00258 { 00259 PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = reinterpret_cast<PFNWGLCREATECONTEXTATTRIBSARBPROC>(wglGetProcAddress("wglCreateContextAttribsARB")); 00260 if (wglCreateContextAttribsARB) 00261 { 00262 int attributes[] = 00263 { 00264 WGL_CONTEXT_MAJOR_VERSION_ARB, mySettings.MajorVersion, 00265 WGL_CONTEXT_MINOR_VERSION_ARB, mySettings.MinorVersion, 00266 0, 0 00267 }; 00268 myContext = wglCreateContextAttribsARB(myDeviceContext, sharedContext, attributes); 00269 } 00270 00271 // If we couldn't create an OpenGL 3 context, adjust the settings 00272 if (!myContext) 00273 { 00274 if (mySettings.MinorVersion > 0) 00275 { 00276 // If the minor version is not 0, we decrease it and try again 00277 mySettings.MinorVersion--; 00278 } 00279 else 00280 { 00281 // If the minor version is 0, we decrease the major version and stop with 3.x contexts 00282 mySettings.MajorVersion = 2; 00283 } 00284 } 00285 } 00286 00287 // If the OpenGL 3.0 context failed or if we don't want one, create a regular OpenGL 1.x/2.x context 00288 if (!myContext) 00289 { 00290 myContext = wglCreateContext(myDeviceContext); 00291 if (!myContext) 00292 { 00293 Err() << "Failed to create an OpenGL context for this window" << std::endl; 00294 return; 00295 } 00296 00297 // Share this context with others 00298 if (sharedContext) 00299 { 00300 // wglShareLists doesn't seem to be thread-safe 00301 static Mutex mutex; 00302 Lock lock(mutex); 00303 00304 if (!wglShareLists(sharedContext, myContext)) 00305 Err() << "Failed to share the OpenGL context" << std::endl; 00306 } 00307 } 00308 } 00309 00310 } // namespace priv 00311 00312 } // namespace sf
:: Copyright © 2007-2008 Laurent Gomila, all rights reserved :: Documentation generated by doxygen 1.5.2 ::