source: OGRE/trunk/ogrenew/RenderSystems/GL/src/OgreWin32GLSupport.cpp @ 692

Revision 692, 17.0 KB checked in by mattausch, 18 years ago (diff)

adding ogre 1.2 and dependencies

Line 
1#include "OgreRoot.h"
2#include "OgreException.h"
3#include "OgreLogManager.h"
4#include "OgreStringConverter.h"
5
6#include <algorithm>
7
8#include "OgreWin32GLSupport.h"
9#include "OgreGLTexture.h"
10#include "OgreWin32Window.h"
11#include <GL/wglext.h>
12#include "OgreWin32RenderTexture.h"
13
14using namespace Ogre;
15
16GLenum wglewContextInit (Ogre::GLSupport *glSupport);
17
18namespace Ogre {
19        Win32GLSupport::Win32GLSupport():
20                mInitialWindow(0), mHasPixelFormatARB(0)
21    {
22                // immediately test WGL_ARB_pixel_format and FSAA support
23                // so we can set configuration options appropriately
24                initialiseWGL();
25    }
26
27        template<class C> void remove_duplicates(C& c)
28        {
29                std::sort(c.begin(), c.end());
30                typename C::iterator p = std::unique(c.begin(), c.end());
31                c.erase(p, c.end());
32        }
33
34        void Win32GLSupport::addConfig()
35        {
36                //TODO: EnumDisplayDevices http://msdn.microsoft.com/library/en-us/gdi/devcons_2303.asp
37                /*vector<string> DisplayDevices;
38                DISPLAY_DEVICE DisplayDevice;
39                DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
40                DWORD i=0;
41                while (EnumDisplayDevices(NULL, i++, &DisplayDevice, 0) {
42                        DisplayDevices.push_back(DisplayDevice.DeviceName);
43                }*/
44                 
45                ConfigOption optFullScreen;
46                ConfigOption optVideoMode;
47                ConfigOption optColourDepth;
48                ConfigOption optDisplayFrequency;
49                ConfigOption optVSync;
50                ConfigOption optFSAA;
51                ConfigOption optRTTMode;
52
53                // FS setting possiblities
54                optFullScreen.name = "Full Screen";
55                optFullScreen.possibleValues.push_back("Yes");
56                optFullScreen.possibleValues.push_back("No");
57                optFullScreen.currentValue = "Yes";
58                optFullScreen.immutable = false;
59
60                // Video mode possiblities
61                DEVMODE DevMode;
62                DevMode.dmSize = sizeof(DEVMODE);
63                optVideoMode.name = "Video Mode";
64                optVideoMode.immutable = false;
65                for (DWORD i = 0; EnumDisplaySettings(NULL, i, &DevMode); ++i)
66                {
67                        if (DevMode.dmBitsPerPel < 16 || DevMode.dmPelsHeight < 480)
68                                continue;
69                        mDevModes.push_back(DevMode);
70                        char szBuf[16];
71                        snprintf(szBuf, 16, "%d x %d", DevMode.dmPelsWidth, DevMode.dmPelsHeight);
72                        optVideoMode.possibleValues.push_back(szBuf);
73                }
74                remove_duplicates(optVideoMode.possibleValues);
75                optVideoMode.currentValue = optVideoMode.possibleValues.front();
76
77                optColourDepth.name = "Colour Depth";
78                optColourDepth.immutable = false;
79                optColourDepth.currentValue = "";
80
81                optDisplayFrequency.name = "Display Frequency";
82                optDisplayFrequency.immutable = false;
83                optDisplayFrequency.currentValue = "";
84
85                optVSync.name = "VSync";
86                optVSync.immutable = false;
87                optVSync.possibleValues.push_back("No");
88                optVSync.possibleValues.push_back("Yes");
89                optVSync.currentValue = "No";
90
91                optFSAA.name = "FSAA";
92                optFSAA.immutable = false;
93                optFSAA.possibleValues.push_back("0");
94                for (std::vector<int>::iterator it = mFSAALevels.begin(); it != mFSAALevels.end(); ++it)
95                        optFSAA.possibleValues.push_back(StringConverter::toString(*it));
96                optFSAA.currentValue = "0";
97
98                optRTTMode.name = "RTT Preferred Mode";
99                optRTTMode.possibleValues.push_back("FBO");
100                optRTTMode.possibleValues.push_back("PBuffer");
101                optRTTMode.possibleValues.push_back("Copy");
102                optRTTMode.currentValue = "FBO";
103                optRTTMode.immutable = false;
104
105
106                mOptions[optFullScreen.name] = optFullScreen;
107                mOptions[optVideoMode.name] = optVideoMode;
108                mOptions[optColourDepth.name] = optColourDepth;
109                mOptions[optDisplayFrequency.name] = optDisplayFrequency;
110                mOptions[optVSync.name] = optVSync;
111                mOptions[optFSAA.name] = optFSAA;
112                mOptions[optRTTMode.name] = optRTTMode;
113
114                refreshConfig();
115        }
116
117        void Win32GLSupport::refreshConfig()
118        {
119                ConfigOptionMap::iterator optVideoMode = mOptions.find("Video Mode");
120                ConfigOptionMap::iterator moptColourDepth = mOptions.find("Colour Depth");
121                ConfigOptionMap::iterator moptDisplayFrequency = mOptions.find("Display Frequency");
122                if(optVideoMode == mOptions.end() || moptColourDepth == mOptions.end() || moptDisplayFrequency == mOptions.end())
123                        OGRE_EXCEPT(999, "Can't find mOptions!", "Win32GLSupport::refreshConfig");
124                ConfigOption* optColourDepth = &moptColourDepth->second;
125                ConfigOption* optDisplayFrequency = &moptDisplayFrequency->second;
126
127                const String& val = optVideoMode->second.currentValue;
128                String::size_type pos = val.find('x');
129                if (pos == String::npos)
130                        OGRE_EXCEPT(999, "Invalid Video Mode provided", "Win32GLSupport::refreshConfig");
131                DWORD width = StringConverter::parseUnsignedInt(val.substr(0, pos));
132                DWORD height = StringConverter::parseUnsignedInt(val.substr(pos+1, String::npos));
133
134                for(std::vector<DEVMODE>::const_iterator i = mDevModes.begin(); i != mDevModes.end(); ++i)
135                {
136                        if (i->dmPelsWidth != width || i->dmPelsHeight != height)
137                                continue;
138                        optColourDepth->possibleValues.push_back(StringConverter::toString(i->dmBitsPerPel));
139                        optDisplayFrequency->possibleValues.push_back(StringConverter::toString(i->dmDisplayFrequency));
140                }
141                remove_duplicates(optColourDepth->possibleValues);
142                remove_duplicates(optDisplayFrequency->possibleValues);
143                optColourDepth->currentValue = optColourDepth->possibleValues.back();
144                if (optDisplayFrequency->currentValue != "N/A")
145                        optDisplayFrequency->currentValue = optDisplayFrequency->possibleValues.front();
146        }
147
148        void Win32GLSupport::setConfigOption(const String &name, const String &value)
149        {
150                ConfigOptionMap::iterator it = mOptions.find(name);
151
152                // Update
153                if(it != mOptions.end())
154                        it->second.currentValue = value;
155                else
156                {
157            StringUtil::StrStreamType str;
158            str << "Option named '" << name << "' does not exist.";
159                        OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, str.str(), "Win32GLSupport::setConfigOption" );
160                }
161
162                if( name == "Video Mode" )
163                        refreshConfig();
164
165                if( name == "Full Screen" )
166                {
167                        it = mOptions.find( "Display Frequency" );
168                        if( value == "No" )
169                        {
170                                it->second.currentValue = "N/A";
171                                it->second.immutable = true;
172                        }
173                        else
174                        {
175                                it->second.currentValue = it->second.possibleValues.front();
176                                it->second.immutable = false;
177                        }
178                }
179        }
180
181        String Win32GLSupport::validateConfig()
182        {
183                // TODO, DX9
184                return String("");
185        }
186
187        RenderWindow* Win32GLSupport::createWindow(bool autoCreateWindow, GLRenderSystem* renderSystem, const String& windowTitle)
188        {
189                if (autoCreateWindow)
190        {
191            ConfigOptionMap::iterator opt = mOptions.find("Full Screen");
192            if (opt == mOptions.end())
193                OGRE_EXCEPT(999, "Can't find full screen options!", "Win32GLSupport::createWindow");
194            bool fullscreen = (opt->second.currentValue == "Yes");
195
196            opt = mOptions.find("Video Mode");
197            if (opt == mOptions.end())
198                OGRE_EXCEPT(999, "Can't find video mode options!", "Win32GLSupport::createWindow");
199            String val = opt->second.currentValue;
200            String::size_type pos = val.find('x');
201            if (pos == String::npos)
202                OGRE_EXCEPT(999, "Invalid Video Mode provided", "Win32GLSupport::createWindow");
203
204                        unsigned int w = StringConverter::parseUnsignedInt(val.substr(0, pos));
205            unsigned int h = StringConverter::parseUnsignedInt(val.substr(pos + 1));
206
207                        // Parse optional parameters
208                        NameValuePairList winOptions;
209                        opt = mOptions.find("Colour Depth");
210                        if (opt == mOptions.end())
211                                OGRE_EXCEPT(999, "Can't find Colour Depth options!", "Win32GLSupport::createWindow");
212                        unsigned int colourDepth =
213                                StringConverter::parseUnsignedInt(opt->second.currentValue);
214                        winOptions["colourDepth"] = StringConverter::toString(colourDepth);
215
216                        opt = mOptions.find("VSync");
217                        if (opt == mOptions.end())
218                                OGRE_EXCEPT(999, "Can't find VSync options!", "Win32GLSupport::createWindow");
219                        bool vsync = (opt->second.currentValue == "Yes");
220                        winOptions["vsync"] = StringConverter::toString(vsync);
221                        renderSystem->setWaitForVerticalBlank(vsync);
222
223                        opt = mOptions.find("FSAA");
224                        if (opt == mOptions.end())
225                                OGRE_EXCEPT(999, "Can't find FSAA options!", "Win32GLSupport::createWindow");
226                        unsigned int multisample =
227                                StringConverter::parseUnsignedInt(opt->second.currentValue);
228                        winOptions["FSAA"] = StringConverter::toString(multisample);
229
230            return renderSystem->createRenderWindow(windowTitle, w, h, fullscreen, &winOptions);
231        }
232        else
233        {
234            // XXX What is the else?
235                        return NULL;
236        }
237        }
238
239        RenderWindow* Win32GLSupport::newWindow(const String &name, unsigned int width,
240                unsigned int height, bool fullScreen, const NameValuePairList *miscParams)
241        {
242                ConfigOptionMap::iterator opt = mOptions.find("Display Frequency");
243                if (opt == mOptions.end())
244                        OGRE_EXCEPT(999, "Can't find Display Frequency options!", "Win32GLSupport::newWindow");
245                unsigned int displayFrequency = StringConverter::parseUnsignedInt(opt->second.currentValue);
246
247                Win32Window* window = new Win32Window(*this);
248                window->create(name, width, height, fullScreen, miscParams);
249
250                if(!mInitialWindow)
251                        mInitialWindow = window;
252                return window;
253        }
254
255        void Win32GLSupport::start()
256        {
257                LogManager::getSingleton().logMessage("*** Starting Win32GL Subsystem ***");
258        }
259
260        void Win32GLSupport::stop()
261        {
262                LogManager::getSingleton().logMessage("*** Stopping Win32GL Subsystem ***");
263        }
264
265        void Win32GLSupport::initialiseExtensions() {
266                assert(mInitialWindow);
267                // First, initialise the normal extensions
268                GLSupport::initialiseExtensions();
269                // wglew init
270                wglewContextInit(this);
271
272                // Check for W32 specific extensions probe function
273                PFNWGLGETEXTENSIONSSTRINGARBPROC _wglGetExtensionsStringARB =
274                        (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
275                if(!_wglGetExtensionsStringARB)
276                        return;
277                const char *wgl_extensions = _wglGetExtensionsStringARB(mInitialWindow->getHDC());
278        StringUtil::StrStreamType str;
279        str << "Supported WGL extensions: " << wgl_extensions;
280                LogManager::getSingleton().logMessage(
281                        LML_NORMAL, str.str());
282                // Parse them, and add them to the main list
283                std::stringstream ext;
284        String instr;
285                ext << wgl_extensions;
286        while(ext >> instr)
287        {
288            extensionList.insert(instr);
289        }
290        }
291
292
293        void* Win32GLSupport::getProcAddress(const String& procname)
294        {
295                return (void*)wglGetProcAddress( procname.c_str() );
296        }
297/*
298        RenderTexture * Win32GLSupport::createRenderTexture( const String & name,
299                unsigned int width, unsigned int height,
300                TextureType texType, PixelFormat internalFormat,
301                const NameValuePairList *miscParams )
302        {
303#ifdef HW_RTT
304                bool useBind = checkExtension("WGL_ARB_render_texture");
305
306                if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_HWRENDER_TO_TEXTURE))
307                        return new Win32RenderTexture(*this, name, width, height, texType,
308                                internalFormat, miscParams, useBind);
309                else
310#endif
311                        return new GLRenderTexture(name, width, height, texType, internalFormat, miscParams);
312        }
313
314*/
315        void Win32GLSupport::initialiseWGL()
316        {
317                // wglGetProcAddress does not work without an active OpenGL context,
318                // but we need wglChoosePixelFormatARB's address before we can
319                // create our main window.  Thank you very much, Microsoft!
320                //
321                // The solution is to create a dummy OpenGL window first, and then
322                // test for WGL_ARB_pixel_format support.  If it is not supported,
323                // we make sure to never call the ARB pixel format functions.
324                //
325                // If is is supported, we call the pixel format functions at least once
326                // to initialise them (pointers are stored by glprocs.h).  We can also
327                // take this opportunity to enumerate the valid FSAA modes.
328               
329                LPCSTR dummyText = "OgreWglDummy";
330                HINSTANCE hinst = GetModuleHandle("RenderSystem_GL.dll");
331               
332                WNDCLASS dummyClass;
333                memset(&dummyClass, 0, sizeof(WNDCLASS));
334                dummyClass.style = CS_OWNDC;
335                dummyClass.hInstance = hinst;
336                dummyClass.lpfnWndProc = dummyWndProc;
337                dummyClass.lpszClassName = dummyText;
338                RegisterClass(&dummyClass);
339
340                HWND hwnd = CreateWindow(dummyText, dummyText,
341                        WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
342                        0, 0, 32, 32, 0, 0, hinst, 0);
343
344                // if a simple CreateWindow fails, then boy are we in trouble...
345                if (hwnd == NULL)
346                        OGRE_EXCEPT(0, "CreateWindow() failed", "Win32GLSupport::initializeWGL");
347
348
349                // no chance of failure and no need to release thanks to CS_OWNDC
350                HDC hdc = GetDC(hwnd);
351
352                // assign a simple OpenGL pixel format that everyone supports
353                PIXELFORMATDESCRIPTOR pfd;
354                memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
355                pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
356                pfd.nVersion = 1;
357                pfd.cColorBits = 16;
358                pfd.cDepthBits = 15;
359                pfd.dwFlags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER;
360                pfd.iPixelType = PFD_TYPE_RGBA;
361               
362                // if these fail, wglCreateContext will also quietly fail
363                int format;
364                if ((format = ChoosePixelFormat(hdc, &pfd)) != 0)
365                        SetPixelFormat(hdc, format, &pfd);
366
367                HGLRC hrc = wglCreateContext(hdc);
368                if (hrc)
369                {
370                        // if wglMakeCurrent fails, wglGetProcAddress will return null
371                        wglMakeCurrent(hdc, hrc);
372                       
373                        PFNWGLGETEXTENSIONSSTRINGARBPROC _wglGetExtensionsStringARB =
374                                (PFNWGLGETEXTENSIONSSTRINGARBPROC)
375                                wglGetProcAddress("wglGetExtensionsStringARB");
376                       
377                        // check for pixel format and multisampling support
378                        bool hasMultisample = false;
379                       
380                        if (_wglGetExtensionsStringARB)
381                        {
382                                std::istringstream wglexts(_wglGetExtensionsStringARB(hdc));
383                                std::string ext;
384                                while (wglexts >> ext)
385                                {
386                                        if (ext == "WGL_ARB_pixel_format")
387                                                mHasPixelFormatARB = true;
388                                        else if (ext == "WGL_ARB_multisample")
389                                                hasMultisample = true;
390                                }
391                        }
392
393                        if (mHasPixelFormatARB && hasMultisample)
394                        {
395                                // enumerate all 32-bit formats w/ multisampling
396                                int iattr[] = {
397                                        WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
398                                        WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
399                                        WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
400                                        WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
401                                        WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
402                                        WGL_COLOR_BITS_ARB, 24,
403                                        WGL_ALPHA_BITS_ARB, 8,
404                                        WGL_DEPTH_BITS_ARB, 24,
405                                        WGL_STENCIL_BITS_ARB, 8,
406                                        WGL_SAMPLES_ARB, 2,
407                                        0
408                                };
409                                int formats[256];
410                                unsigned int count;
411                // cheating here.  wglChoosePixelFormatARB procc address needed later on
412                // when a valid GL context does not exist and glew is not initialized yet.
413                __wglewChoosePixelFormatARB =
414                    (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
415                                __wglewChoosePixelFormatARB(hdc, iattr, 0, 256, formats, &count);
416                               
417                                // determine what multisampling levels are offered
418                                int query = WGL_SAMPLES_ARB, samples;
419                                for (unsigned int i = 0; i < count; ++i)
420                                {
421                                        PFNWGLGETPIXELFORMATATTRIBIVARBPROC _wglGetPixelFormatAttribivARB =
422                                                (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
423                                                wglGetProcAddress("wglGetPixelFormatAttribivARB");
424                                        if (_wglGetPixelFormatAttribivARB(hdc, formats[i],
425                                                                                                        0, 1, &query, &samples))
426                                                mFSAALevels.push_back(samples);
427                                }
428                                remove_duplicates(mFSAALevels);
429                        }
430                       
431                        wglMakeCurrent(0, 0);
432                        wglDeleteContext(hrc);
433                }
434
435                // clean up our dummy window and class
436                DestroyWindow(hwnd);
437                UnregisterClass(dummyText, hinst);
438        }
439
440        LRESULT Win32GLSupport::dummyWndProc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp)
441        {
442                return DefWindowProc(hwnd, umsg, wp, lp);
443        }
444
445        bool Win32GLSupport::selectPixelFormat(HDC hdc, int colourDepth, int multisample)
446        {
447                PIXELFORMATDESCRIPTOR pfd;
448                memset(&pfd, 0, sizeof(pfd));
449                pfd.nSize = sizeof(pfd);
450                pfd.nVersion = 1;
451                pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
452                pfd.iPixelType = PFD_TYPE_RGBA;
453                pfd.cColorBits = (colourDepth > 16)? 24 : colourDepth;
454                pfd.cAlphaBits = (colourDepth > 16)? 8 : 0;
455                pfd.cDepthBits = 24;
456                pfd.cStencilBits = 8;
457
458                int format = 0;
459
460                if (multisample)
461                {
462                        // only available at 32bpp with driver support
463                        if (colourDepth < 32 || !mHasPixelFormatARB)
464                                return false;
465                       
466                        int iattr[] = {
467                                WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
468                                WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
469                                WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
470                                WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
471                                WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
472                                WGL_COLOR_BITS_ARB, 24,
473                                WGL_ALPHA_BITS_ARB, 8,
474                                WGL_DEPTH_BITS_ARB, 24,
475                                WGL_STENCIL_BITS_ARB, 8,
476                                WGL_SAMPLES_ARB, multisample,
477                                0
478                        };
479
480                        UINT nformats;
481            assert(__wglewChoosePixelFormatARB && "failed to get proc address for ChoosePixelFormatARB");
482            // ChoosePixelFormatARB proc address was obtained when setting up a dummy GL context in initialiseWGL()
483            // since glew hasn't been initialized yet, we have to cheat and use the previously obtained address
484                        __wglewChoosePixelFormatARB(hdc, iattr, NULL, 1, &format, &nformats);
485                }
486                else
487                {
488                        format = ChoosePixelFormat(hdc, &pfd);
489                }
490
491                return (format != 0 && SetPixelFormat(hdc, format, &pfd));
492        }
493
494        bool Win32GLSupport::supportsPBuffers()
495        {
496                return __WGLEW_ARB_pbuffer;
497        }
498    GLPBuffer *Win32GLSupport::createPBuffer(PixelComponentType format, size_t width, size_t height)
499        {
500                return new Win32PBuffer(format, width, height);
501        }
502}
Note: See TracBrowser for help on using the repository browser.