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

Revision 657, 15.8 KB checked in by mattausch, 18 years ago (diff)

added ogre dependencies and patched ogre sources

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