source: trunk/VUT/work/ogre_changes/RenderSystems/GL/src/OgreWin32Window.cpp @ 156

Revision 156, 14.1 KB checked in by mattausch, 19 years ago (diff)
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25
26#include "OgreWin32Window.h"
27#include "OgreRoot.h"
28#include "OgreLogManager.h"
29#include "OgreRenderSystem.h"
30#include "OgreImageCodec.h"
31#include "OgreStringConverter.h"
32#include "OgreException.h"
33#include "OgreWin32GLSupport.h"
34#include "OgreWin32Context.h"
35
36namespace Ogre {
37
38        Win32Window::Win32Window(Win32GLSupport &glsupport):
39                mGLSupport(glsupport),
40        mContext(0)
41    {
42                mIsFullScreen = false;
43                mHWnd = 0;
44                mActive = false;
45                mReady = false;
46                mClosed = false;
47    }
48
49    Win32Window::~Win32Window()
50    {
51                destroy();
52    }
53
54        void Win32Window::create(const String& name, unsigned int width, unsigned int height,
55                    bool fullScreen, const NameValuePairList *miscParams)
56    {
57        HWND parentHWnd = 0;
58                HWND externalHandle = 0;
59                HINSTANCE hInst = GetModuleHandle("RenderSystem_GL.dll");
60                bool vsync = false;
61                unsigned int displayFrequency = 0;
62                String title = name;
63                unsigned int colourDepth = 32;
64                unsigned int left = 0; // Defaults to screen center
65                unsigned int top = 0; // Defaults to screen center
66                bool depthBuffer = true;
67                int multisample = 0;
68
69                if(miscParams)
70                {
71                        // Get variable-length params
72                        NameValuePairList::const_iterator opt;
73                        // left (x)
74                        opt = miscParams->find("left");
75                        if(opt != miscParams->end())
76                                left = StringConverter::parseUnsignedInt(opt->second);
77                        // top (y)
78                        opt = miscParams->find("top");
79                        if(opt != miscParams->end())
80                                top = StringConverter::parseUnsignedInt(opt->second);
81                        // Window title
82                        opt = miscParams->find("title");
83                        if(opt != miscParams->end())
84                                title = opt->second;
85                        // externalWindowHandle         -> externalHandle
86                        opt = miscParams->find("externalWindowHandle");
87                        if(opt != miscParams->end())
88                                externalHandle = (HWND)StringConverter::parseUnsignedInt(opt->second);
89                        // parentWindowHandle -> parentHWnd
90                        opt = miscParams->find("parentWindowHandle");
91                        if(opt != miscParams->end())
92                                parentHWnd = (HWND)StringConverter::parseUnsignedInt(opt->second);
93                        // vsync        [parseBool]
94                        opt = miscParams->find("vsync");
95                        if(opt != miscParams->end())
96                                vsync = StringConverter::parseBool(opt->second);
97                        // displayFrequency
98                        opt = miscParams->find("displayFrequency");
99                        if(opt != miscParams->end())
100                                displayFrequency = StringConverter::parseUnsignedInt(opt->second);
101                        // colourDepth
102                        opt = miscParams->find("colourDepth");
103                        if(opt != miscParams->end())
104                                colourDepth = StringConverter::parseUnsignedInt(opt->second);
105                        // depthBuffer [parseBool]
106                        opt = miscParams->find("depthBuffer");
107                        if(opt != miscParams->end())
108                                depthBuffer = StringConverter::parseBool(opt->second);
109                        // FSAA
110                        opt = miscParams->find("FSAA");
111                        if(opt != miscParams->end())
112                                multisample = StringConverter::parseUnsignedInt(opt->second);
113                }
114               
115                // Destroy current window if any
116                if( mHWnd )
117                        destroy();
118
119        if (fullScreen)
120        {
121                        mColourDepth = colourDepth;
122        }
123                else
124                {
125                        // Get colour depth from display
126                        mColourDepth = GetDeviceCaps(GetDC(0), BITSPIXEL);
127                }
128
129                if (!externalHandle) {
130                        DWORD dwStyle = (fullScreen ? WS_POPUP : WS_OVERLAPPEDWINDOW) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
131                        RECT rc;
132
133                        mWidth = width;
134                        mHeight = height;
135
136                        if (!fullScreen)
137                        {
138                                // Calculate window dimensions required to get the requested client area
139                                SetRect(&rc, 0, 0, mWidth, mHeight);
140                                AdjustWindowRect(&rc, dwStyle, false);
141                                mWidth = rc.right - rc.left;
142                                mHeight = rc.bottom - rc.top;
143
144                                // Clamp width and height to the desktop dimensions
145                                if (mWidth > (unsigned)GetSystemMetrics(SM_CXSCREEN))
146                                        mWidth = (unsigned)GetSystemMetrics(SM_CXSCREEN);
147                                if (mHeight > (unsigned)GetSystemMetrics(SM_CYSCREEN))
148                                        mHeight = (unsigned)GetSystemMetrics(SM_CYSCREEN);
149
150                                if (!left)
151                {
152                                        mLeft = (GetSystemMetrics(SM_CXSCREEN) / 2) - (mWidth / 2);
153                }
154                                else
155                {
156                                        mLeft = left;
157                }
158                                if (!top)
159                {
160                                        mTop = (GetSystemMetrics(SM_CYSCREEN) / 2) - (mHeight / 2);
161                }
162                                else
163                {
164                    mTop = top;
165                }
166                        }
167                        else
168            {
169                                mTop = mLeft = 0;
170            }
171
172                        // Register the window class
173
174                        WNDCLASS wndClass = { CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
175                                WndProc, 0, 4, hInst,
176                                LoadIcon( NULL, IDI_APPLICATION ),
177                                LoadCursor( NULL, IDC_ARROW ),
178                                (HBRUSH)GetStockObject( BLACK_BRUSH ), NULL,
179                                TEXT(title.c_str()) };
180                        RegisterClass( &wndClass );
181
182                        // Create our main window
183                        // Pass pointer to self
184                        HWND hWnd = CreateWindowEx(fullScreen?WS_EX_TOPMOST:0, TEXT(title.c_str()), TEXT(title.c_str()),
185                                dwStyle, mLeft, mTop, mWidth, mHeight, 0L, 0L, hInst, this);
186                        mHWnd = hWnd;
187
188                        GetClientRect(mHWnd,&rc);
189                        mWidth = rc.right;
190                        mHeight = rc.bottom;
191
192            if (fullScreen) {
193                            DEVMODE DevMode;
194                            DevMode.dmSize = sizeof(DevMode);
195                            DevMode.dmBitsPerPel = mColourDepth;
196                            DevMode.dmPelsWidth = mWidth;
197                            DevMode.dmPelsHeight = mHeight;
198                            DevMode.dmDisplayFrequency = displayFrequency;
199                            DevMode.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFREQUENCY;
200                            if (ChangeDisplaySettings(&DevMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
201                                    LogManager::getSingleton().logMessage(LML_CRITICAL, "ChangeDisplaySettingsEx");
202
203                    }
204
205                }
206                else {
207                        mHWnd = externalHandle;
208                        RECT rc;
209                        GetClientRect(mHWnd, &rc);
210                        mWidth = rc.right;
211                        mHeight = rc.bottom;
212                        mLeft = rc.left;
213                        mTop = rc.top;
214                }
215                ShowWindow(mHWnd, SW_SHOWNORMAL);
216                UpdateWindow(mHWnd);
217                mName = name;
218                mIsDepthBuffered = depthBuffer;
219                mIsFullScreen = fullScreen;
220
221               
222                HDC hdc = GetDC(mHWnd);
223
224        StringUtil::StrStreamType str;
225        str << "Created Win32Window '"
226            << mName << "' : " << mWidth << "x" << mHeight
227            << ", " << mColourDepth << "bpp";
228        LogManager::getSingleton().logMessage(LML_NORMAL, str.str());
229
230                if (!mGLSupport.selectPixelFormat(hdc, mColourDepth, multisample))
231                {
232                        if (multisample == 0)
233                                OGRE_EXCEPT(0, "selectPixelFormat failed", "Win32Window::create");
234
235                        LogManager::getSingleton().logMessage(LML_NORMAL, "FSAA level not supported, falling back");
236                        if (!mGLSupport.selectPixelFormat(hdc, mColourDepth, 0))
237                                OGRE_EXCEPT(0, "selectPixelFormat failed", "Win32Window::create");
238                }
239
240                HGLRC glrc = wglCreateContext(hdc);
241                if (!glrc)
242                        OGRE_EXCEPT(0, "wglCreateContext", "Win32Window::create");
243                if (!wglMakeCurrent(hdc, glrc))
244                        OGRE_EXCEPT(0, "wglMakeCurrent", "Win32Window::create");
245               
246                mGlrc = glrc;
247                mHDC = hdc;
248
249                mOldSwapIntervall = wglGetSwapIntervalEXT();
250                if (vsync)
251                        wglSwapIntervalEXT(1);
252                else
253                        wglSwapIntervalEXT(0);
254
255                mReady = true;
256
257        // Create RenderSystem context
258        mContext = new Win32Context(mHDC, mGlrc);
259        // Register the context with the rendersystem and associate it with this window
260        GLRenderSystem *rs = static_cast<GLRenderSystem*>(Root::getSingleton().getRenderSystem());
261        rs->_registerContext(this, mContext);
262    }
263
264    void Win32Window::destroy(void)
265    {
266        // Unregister and destroy OGRE GLContext
267        if (mContext)
268        {
269            GLRenderSystem *rs = static_cast<GLRenderSystem*>(Root::getSingleton().getRenderSystem());
270            rs->_unregisterContext(this);
271            delete mContext;
272            mContext = NULL;
273
274            wglSwapIntervalEXT(mOldSwapIntervall);
275        }
276                if (mGlrc) {
277                        wglMakeCurrent(NULL, NULL);
278                        wglDeleteContext(mGlrc);
279                        mGlrc = NULL;
280                }
281                if (mHDC) {
282                        ReleaseDC(mHWnd, mHDC);
283                        mHDC = NULL;
284                }
285                if (mIsFullScreen)
286                {
287                        ChangeDisplaySettings(NULL, 0);
288                }
289        if (mHWnd)
290        {
291                DestroyWindow(mHWnd);
292            mHWnd = 0;
293        }
294        mActive = false;
295    }
296
297    bool Win32Window::isActive() const
298    {
299        return mActive;
300    }
301
302    bool Win32Window::isClosed() const
303    {
304        return mClosed;
305    }
306
307    void Win32Window::reposition(int left, int top)
308    {
309        // XXX FIXME
310    }
311
312    void Win32Window::resize(unsigned int width, unsigned int height)
313    {
314
315                mWidth = width;
316                mHeight = height;
317
318                // Notify viewports of resize
319                ViewportList::iterator it, itend;
320        itend = mViewportList.end();
321                for( it = mViewportList.begin(); it != itend; ++it )
322                        (*it).second->_updateDimensions();
323                // TODO - resize window
324    }
325
326        void Win32Window::windowMovedOrResized()
327        {
328                RECT temprect;
329                ::GetClientRect(getWindowHandle(),&temprect);
330                resize(temprect.right-temprect.left,temprect.bottom-temprect.top);
331                // TODO
332        }
333
334    void Win32Window::swapBuffers(bool waitForVSync)
335    {
336                SwapBuffers(mHDC);
337    }
338
339        void Win32Window::writeContentsToFile(const String& filename)
340        {
341                ImageCodec::ImageData *imgData = new ImageCodec::ImageData();
342                imgData->width = mWidth;
343                imgData->height = mHeight;
344                imgData->depth = 1;
345                imgData->format = PF_BYTE_RGB;
346
347                // Allocate buffer
348                uchar* pBuffer = new uchar[mWidth * mHeight * 3];
349
350                // Read pixels
351                // I love GL: it does all the locking & colour conversion for us
352                glReadPixels(0,0, mWidth-1, mHeight-1, GL_RGB, GL_UNSIGNED_BYTE, pBuffer);
353
354                // Wrap buffer in a memory stream
355                DataStreamPtr stream(new MemoryDataStream(pBuffer, mWidth * mHeight * 3, false));
356
357                // Need to flip the read data over in Y though
358                Image img;
359                img.loadRawData(stream, mWidth, mHeight, imgData->format );
360                img.flipAroundX();
361
362                MemoryDataStreamPtr streamFlipped(new MemoryDataStream(img.getData(), stream->size(), false));
363
364                // Get codec
365                size_t pos = filename.find_last_of(".");
366                String extension;
367                if( pos == String::npos )
368                        OGRE_EXCEPT(
369                        Exception::ERR_INVALIDPARAMS,
370                        "Unable to determine image type for '" + filename + "' - invalid extension.",
371                        "Win32Window::writeContentsToFile" );
372
373                while( pos != filename.length() - 1 )
374                        extension += filename[++pos];
375
376                // Get the codec
377                Codec * pCodec = Codec::getCodec(extension);
378
379                // Write out
380                Codec::CodecDataPtr ptr(imgData);
381        pCodec->codeToFile(streamFlipped, filename, ptr);
382
383                delete [] pBuffer;
384        }
385
386#ifdef GTP_VISIBILITY_MODIFIED_OGRE
387        uchar *Win32Window::getBufferContents(int &dimx, int &dimy)
388        {
389                dimx = mWidth;
390                dimy = mHeight;
391               
392                // Allocate buffer
393                uchar* pBuffer = new uchar[mWidth * mHeight * 3];
394
395                // Read pixels
396                // I love GL: it does all the locking & colour conversion for us
397                glReadPixels(0, 0, mWidth-1, mHeight-1, GL_RGB, GL_UNSIGNED_BYTE, pBuffer);
398
399                return pBuffer;
400        }
401#endif // GTP_VISIBILITY_MODIFIED_OGRE
402
403        // Window procedure callback
404        // This is a static member, so applies to all windows but we store the
405        // Win32Window instance in the window data GetWindowLog/SetWindowLog
406        LRESULT Win32Window::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
407        {
408                Win32Window* win;
409
410                // look up window instance
411                if( WM_CREATE != uMsg )
412                        win = (Win32Window*)GetWindowLong( hWnd, 0 );
413
414                switch( uMsg )
415                {
416                case WM_ACTIVATE:
417                        if( WA_INACTIVE == LOWORD( wParam ) )
418                                win->mActive = false;
419                        else
420                                win->mActive = true;
421                        break;
422
423                case WM_CREATE: {
424                        // Log the new window
425                        // Get CREATESTRUCT
426                        LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
427                        win = (Win32Window*)(lpcs->lpCreateParams);
428                        // Store pointer in window user data area
429                        SetWindowLong( hWnd, 0, (long)win );
430                        win->mActive = true;
431
432                        return 0; }
433                        break;
434
435                case WM_PAINT:
436                        // If we get WM_PAINT messges, it usually means our window was
437                        // comvered up, so we need to refresh it by re-showing the contents
438                        // of the current frame.
439                        if( win->mActive && win->mReady )
440                                win->update();
441                        break;
442
443                case WM_MOVE:
444                        // Move messages need to be tracked to update the screen rects
445                        // used for blitting the backbuffer to the primary
446                        // *** This doesn't need to be used to Direct3D9 ***
447                        break;
448
449                case WM_ENTERSIZEMOVE:
450                        // Previent rendering while moving / sizing
451                        win->mReady = false;
452                        break;
453
454                case WM_EXITSIZEMOVE:
455                        win->windowMovedOrResized();
456                        win->mReady = true;
457                        break;
458
459                case WM_SIZE:
460                        // Check to see if we are losing or gaining our window.  Set the
461                        // active flag to match
462                        if( SIZE_MAXHIDE == wParam || SIZE_MINIMIZED == wParam )
463                                win->mActive = false;
464                        else
465                        {
466                                win->mActive = true;
467                                if( win->mReady )
468                                        win->windowMovedOrResized();
469                        }
470                        break;
471
472                case WM_GETMINMAXINFO:
473                        // Prevent the window from going smaller than some minimu size
474                        ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
475                        ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
476                        break;
477
478                case WM_CLOSE:
479                        DestroyWindow( win->mHWnd );
480                        win->mClosed = true;
481                        return 0;
482                }
483
484                return DefWindowProc( hWnd, uMsg, wParam, lParam );
485        }
486       
487        void Win32Window::getCustomAttribute( const String& name, void* pData )
488        {
489                if( name == "HWND" )
490                {
491                        HWND *pHwnd = (HWND*)pData;
492                        *pHwnd = getWindowHandle();
493                        return;
494                }
495        }
496
497}
Note: See TracBrowser for help on using the repository browser.