source: OGRE/trunk/ogre_changes/obsolete/RenderSystems/Direct3D7/src/OgreD3D7RenderWindow.cpp @ 657

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

added ogre dependencies and patched ogre sources

Line 
1/*-------------------------------------------------------------------------
2This source file is a part of OGRE
3(Object-oriented Graphics Rendering Engine)
4
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 library is free software; you can redistribute it and/or modify it
11under the terms of the GNU Lesser General Public License (LGPL) as
12published by the Free Software Foundation; either version 2.1 of the
13License, or (at your option) any later version.
14
15This library is distributed in the hope that it will be useful, but
16WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
18License for more details.
19
20You should have received a copy of the GNU Lesser General Public License
21along with this library; if not, write to the Free Software Foundation,
22Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA or go to
23http://www.gnu.org/copyleft/lesser.txt
24-------------------------------------------------------------------------*/
25#include "OgreD3D7RenderWindow.h"
26
27#include "OgreLogManager.h"
28#include "OgreViewport.h"
29#include "OgreException.h"
30#include "OgreRoot.h"
31#include "OgreRenderSystem.h"
32#include "OgreD3D7TextureManager.h"
33#include "OgreBitwise.h"
34#include "OgreImageCodec.h"
35#include "OgreStringConverter.h"
36
37namespace Ogre {
38
39
40    // Window procedure callback
41    // This is a static member, so applies to all windows but we store the
42    // D3D7RenderWindow instance in the window data GetWindowLong/SetWindowLong.
43    LRESULT D3D7RenderWindow::WndProc(
44        HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
45    {
46        LPCREATESTRUCT lpcs;
47        D3D7RenderWindow* win;
48
49        // look up window instance
50        if (uMsg != WM_CREATE)
51        {
52            // Get window pointer
53            win = (D3D7RenderWindow*)GetWindowLong(hWnd, 0);
54        }
55
56        switch( uMsg )
57        {
58            case WM_ACTIVATE:
59                if( LOWORD( wParam ) == WA_INACTIVE )
60                    win->mActive = false;
61                else
62                    win->mActive = true;
63                break;
64
65            case WM_CREATE:
66                // Log the new window
67                // Get CREATESTRUCT
68                lpcs = (LPCREATESTRUCT)lParam;
69                win = (D3D7RenderWindow*)(lpcs->lpCreateParams);
70                // Store pointer in window user data area
71                SetWindowLong(hWnd, 0, (long)win);
72                win->mActive = true;
73
74                return 0;
75
76            case WM_KEYDOWN:
77                // TEMPORARY CODE
78                // TODO - queue up keydown / keyup events with
79                //  window name and timestamp to be processed
80                //  by main loop
81
82                // ESCAPE closes window
83                //if (wParam == VK_ESCAPE)
84                //{
85                //    win->mClosed = true;
86                //    return 0L;
87                //}
88                break;
89
90            case WM_PAINT:
91                // If we get WM_PAINT messages, it usually means our window was
92                // covered up, so we need to refresh it by re-showing the contents
93                // of the current frame.
94                if (win->mActive && win->mReady)
95                    win->update();
96                break;
97
98            case WM_ENTERSIZEMOVE:
99                // Prevent rendering while moving / sizing
100                win->mReady = false;
101                break;
102
103            case WM_EXITSIZEMOVE:
104                win->windowMovedOrResized();
105                win->mReady = true;
106                break;
107
108            case WM_MOVE:
109            case WM_SIZE:
110                // Check to see if we are losing or gaining our window. Set the
111                // active flag to match.
112                if( SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam )
113                    win->mActive = false;
114                else
115                {
116                    win->mActive = true;
117                    if (win->mReady)
118                        win->windowMovedOrResized();
119                }
120
121                break;
122
123            case WM_GETMINMAXINFO:
124                // Prevent the window from going smaller than some minimum size
125                ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
126                ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
127                break;
128
129            case WM_CLOSE:
130                DestroyWindow( win->mHWnd );
131                win->mClosed = true;
132                return 0;
133
134            /*
135            case WM_DESTROY:
136                g_DIMSystem->CleanupRenderer();
137                PostQuitMessage(0);
138                return 0L;
139            */
140        }
141
142
143
144        return DefWindowProc( hWnd, uMsg, wParam, lParam );
145    }
146
147    // -------------------------------------------
148    // D3D7RenderWindow Implementation
149    // -------------------------------------------
150        D3D7RenderWindow::D3D7RenderWindow(HINSTANCE instance, DDDriver *driver):
151                mInstance(instance),
152                mDriver(driver)
153    {
154        mIsUsingDirectDraw = false;
155        mIsFullScreen = false;
156        mlpDDDriver = 0;
157        mHWnd = 0;
158        mActive = false;
159        mReady = false;
160        mClosed = false;
161    }
162
163    D3D7RenderWindow::~D3D7RenderWindow()
164    {
165    }
166
167
168
169        void D3D7RenderWindow::create(const String& name, unsigned int width, unsigned int height,
170                    bool fullScreen, const NameValuePairList *miscParams)
171    {
172
173        HWND parentHWnd = 0;
174        HINSTANCE hInst = mInstance;
175        DDDriver* drv = mDriver;
176        long tempPtr;
177                bool vsync = false;
178                unsigned int displayFrequency = 0;
179                String title = name;
180                unsigned int colourDepth = 32;
181                unsigned int left = 0; // Defaults to screen center
182                unsigned int top = 0; // Defaults to screen center
183                bool depthBuffer = true;
184               
185                if(miscParams)
186                {
187                        // Get variable-length params
188                        NameValuePairList::const_iterator opt;
189                        // left (x)
190                        opt = miscParams->find("left");
191                        if(opt != miscParams->end())
192                                left = StringConverter::parseUnsignedInt(opt->second);
193                        // top (y)
194                        opt = miscParams->find("top");
195                        if(opt != miscParams->end())
196                                top = StringConverter::parseUnsignedInt(opt->second);
197                        // Window title
198                        opt = miscParams->find("title");
199                        if(opt != miscParams->end())
200                                title = opt->second;
201                        // parentWindowHandle -> parentHWnd
202                        opt = miscParams->find("parentWindowHandle");
203                        if(opt != miscParams->end())
204                                parentHWnd = (HWND)StringConverter::parseUnsignedInt(opt->second);
205                        // vsync        [parseBool]
206                        opt = miscParams->find("vsync");
207                        if(opt != miscParams->end())
208                                vsync = StringConverter::parseBool(opt->second);
209                        // displayFrequency
210                        opt = miscParams->find("displayFrequency");
211                        if(opt != miscParams->end())
212                                displayFrequency = StringConverter::parseUnsignedInt(opt->second);
213                        // colourDepth
214                        opt = miscParams->find("colourDepth");
215                        if(opt != miscParams->end())
216                                colourDepth = StringConverter::parseUnsignedInt(opt->second);
217                        // depthBuffer [parseBool]
218                        opt = miscParams->find("depthBuffer");
219                        if(opt != miscParams->end())
220                                depthBuffer = StringConverter::parseBool(opt->second);
221                }
222
223
224        // Destroy current window if any
225        if (mHWnd)
226        {
227            destroy();
228        }
229
230        // TODO: deal with child windows
231        mParentHWnd = parentHWnd;
232
233                DWORD dwStyle = (fullScreen ? WS_POPUP : WS_OVERLAPPEDWINDOW) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
234                RECT rc;
235
236                mWidth = width;
237                mHeight = height;
238
239                if (!fullScreen)
240                {
241                        // Calculate window dimensions required to get the requested client area
242                        SetRect(&rc, 0, 0, mWidth, mHeight);
243                        AdjustWindowRect(&rc, dwStyle, false);
244                        mWidth = rc.right - rc.left;
245                        mHeight = rc.bottom - rc.top;
246
247                        // Clamp width and height to the desktop dimensions
248                        if (mWidth > (unsigned)GetSystemMetrics(SM_CXSCREEN))
249                                mWidth = (unsigned)GetSystemMetrics(SM_CXSCREEN);
250                        if (mHeight > (unsigned)GetSystemMetrics(SM_CYSCREEN))
251                                mHeight = (unsigned)GetSystemMetrics(SM_CYSCREEN);
252
253                        if (!left)
254                                mLeft = (GetSystemMetrics(SM_CXSCREEN) / 2) - (mWidth / 2);
255                        else
256                                mLeft = left;
257                        if (!top)
258                                mTop = (GetSystemMetrics(SM_CYSCREEN) / 2) - (mHeight / 2);
259                        else
260                                mTop = top;
261                }
262                else
263                        mTop = mLeft = 0;
264
265                // Register the window class
266        // NB Allow 4 bytes of window data for D3D7RenderWindow pointer
267        WNDCLASS wndClass = { CS_HREDRAW | CS_VREDRAW, WndProc, 0, 4, hInst,
268                              LoadIcon( NULL, IDI_APPLICATION ),
269                              LoadCursor(NULL, IDC_ARROW),
270                              (HBRUSH)GetStockObject(BLACK_BRUSH), NULL,
271                              TEXT(title.c_str()) };
272        RegisterClass( &wndClass );
273
274        // Create our main window
275        // Pass pointer to self
276        HWND hWnd = CreateWindow( TEXT(title.c_str()),
277                                  TEXT(title.c_str()),
278                                  dwStyle, mLeft, mTop,
279                                  mWidth, mHeight, 0L, 0L, hInst, this );
280
281                GetClientRect(hWnd,&rc);
282                mWidth = rc.right;
283                mHeight = rc.bottom;
284
285                ShowWindow( hWnd, SW_SHOWNORMAL );
286        UpdateWindow( hWnd );
287
288        mHWnd = hWnd;
289
290        // Store info
291        mName = name;
292        mWidth = width;
293        mHeight = height;
294        mIsDepthBuffered = depthBuffer;
295        mIsFullScreen = fullScreen;
296
297        if (fullScreen)
298        {
299            mColourDepth = colourDepth;
300            mLeft = 0;
301            mTop = 0;
302        }
303        else
304        {
305            // Get colour depth from display
306            HDC hdc = GetDC( mHWnd );
307            mColourDepth = GetDeviceCaps( hdc, BITSPIXEL );
308            ReleaseDC( mHWnd, hdc );
309            mTop = top;
310            mLeft = left;
311
312            // Record the dimensions of the blit location
313            GetClientRect( mHWnd, &rcBlitDest );
314            ClientToScreen( mHWnd, (POINT*)&rcBlitDest.left );
315            ClientToScreen( mHWnd, (POINT*)&rcBlitDest.right );
316        }
317
318        StringUtil::StrStreamType str;
319        str << "D3D7 : Created D3D7 Rendering Window '"
320            << mName << "' : " << mWidth << "x" << mHeight
321            << ", " << mColourDepth << "bpp";
322        LogManager::getSingleton().logMessage(
323            LML_NORMAL, str.str());
324
325        // Set up DirectDraw if appropriate
326        // NB devices & surfaces set up for root window only
327        if (drv && mParentHWnd == NULL)
328        {
329            // DD Driver object passed
330            mlpDDDriver = drv;
331            mIsUsingDirectDraw = true;
332
333            createDDSurfaces();
334            // Get best device based on render bit depth
335            D3DDevice* dev = mlpDDDriver->get3DDeviceList()->getBest(mColourDepth);
336
337            // create D3D device for this window
338            mlpD3DDevice = dev->createDevice(mlpDDSBack);
339            createDepthBuffer();
340        }
341        else
342            mIsUsingDirectDraw = false;
343
344        mReady = true;
345    }
346
347    void D3D7RenderWindow::destroy(void)
348    {
349        if (mIsUsingDirectDraw)
350            releaseDDSurfaces();
351
352        DestroyWindow(mHWnd);
353
354    }
355
356    bool D3D7RenderWindow::isActive(void) const
357    {
358        return mActive;
359    }
360
361    bool D3D7RenderWindow::isClosed(void) const
362    {
363        return mClosed;
364    }
365
366    void D3D7RenderWindow::reposition(int left, int top)
367    {
368
369    }
370
371    void D3D7RenderWindow::resize(unsigned int width, unsigned int height)
372    {
373        mWidth = width;
374        mHeight = height;
375
376        // Notify viewports of resize
377        ViewportList::iterator it = mViewportList.begin();
378        while (it != mViewportList.end())
379            (*it++).second->_updateDimensions();
380
381        // TODO - resize window
382
383    }
384
385    void D3D7RenderWindow::swapBuffers(bool waitForVSync)
386    {
387                if (!mlpDDSFront)
388                        return;
389
390        HRESULT hr;
391        DWORD flags;
392        if (mIsUsingDirectDraw)
393        {
394            if (mIsFullScreen)
395            {
396                // Use flipping chain
397                if (waitForVSync)
398                {
399                    flags = DDFLIP_WAIT;
400                }
401                else
402                {
403                    flags = DDFLIP_WAIT | DDFLIP_NOVSYNC;
404                }
405
406                hr = mlpDDSFront->Flip(NULL,flags);
407            }
408            else
409            {
410                // Ordinary Blit
411                RECT srcRect;
412                srcRect.left = 0;
413                srcRect.top = 0;
414                srcRect.right = rcBlitDest.right - rcBlitDest.left;
415                srcRect.bottom = rcBlitDest.bottom - rcBlitDest.top;
416                hr = mlpDDSFront->Blt(&rcBlitDest,mlpDDSBack,&srcRect,DDBLT_WAIT,NULL);
417            }
418
419            if (hr == DDERR_SURFACELOST)
420            {
421                // Restore surfaces
422                //restoreDDSurfaces();
423            }
424            else if (FAILED(hr))
425            {
426                 OGRE_EXCEPT(
427                     hr,
428                     "Error flipping surfaces",
429                     "D3D7RenderWindow::swapBuffers" );
430            }
431        }
432
433    }
434
435    HWND D3D7RenderWindow::getWindowHandle(void) const
436    {
437        return mHWnd;
438    }
439
440    HWND D3D7RenderWindow::getParentWindowHandle(void) const
441    {
442        return mParentHWnd;
443    }
444
445    bool D3D7RenderWindow::isUsingDirectDraw(void) const
446    {
447        return mIsUsingDirectDraw;
448    }
449
450    // -------------------------------------------------------
451    //   DirectDraw specific methods
452    // -------------------------------------------------------
453    DDDriver* D3D7RenderWindow::getDirectDrawDriver(void)
454    {
455        return mlpDDDriver;
456    }
457
458    LPDIRECTDRAWSURFACE7 D3D7RenderWindow::getDDFrontBuffer(void)
459    {
460        return mlpDDSFront;
461
462    }
463
464    LPDIRECTDRAWSURFACE7 D3D7RenderWindow::getDDBackBuffer(void)
465    {
466        return mlpDDSBack;
467    }
468    LPDIRECT3DDEVICE7 D3D7RenderWindow::getD3DDevice(void)
469    {
470        return mlpD3DDevice;
471    }
472
473    void D3D7RenderWindow::createDDSurfaces(void)
474    {
475        // Use DirectDraw wrapper object to create surfaces
476        if( !mlpDDDriver )
477        {
478            OGRE_EXCEPT(
479            Exception::ERR_INVALIDPARAMS,
480            "Cannot create surfaces because of no valid DirectDraw object",
481            "D3D7RenderWindow::createDDSurfaces" );
482        }
483
484        if( mIsFullScreen )
485        {
486            mlpDDDriver->createWindowSurfaces(
487                mHWnd,
488                mWidth, mHeight, mColourDepth,
489                true, &mlpDDSFront, &mlpDDSBack);
490        }
491        else
492        {
493            // Windowed mode - need to use client rect for surface dimensions
494            // I.e. we need to ignore menu bars, borders, title bar etc
495            RECT rcClient;
496            unsigned int cWidth, cHeight;
497
498            GetClientRect( mHWnd, &rcClient );
499            ClientToScreen( mHWnd, (POINT*)&rcClient.left );
500            ClientToScreen( mHWnd, (POINT*)&rcClient.right );
501
502            cWidth  = rcClient.right - rcClient.left;
503            cHeight = rcClient.bottom - rcClient.top;
504
505            // Create surfaces (AND clipper)
506            mlpDDDriver->createWindowSurfaces(
507                mHWnd,
508                cWidth, cHeight, 0,
509                false, &mlpDDSFront, &mlpDDSBack);
510
511            // Update own dimensions since target width / height is this
512            mWidth = cWidth;
513            mHeight = cHeight;
514        }
515    }
516
517    void D3D7RenderWindow::createDepthBuffer(void)
518    {
519        // Get best device based on render bit depth
520        D3DDevice* dev = mlpDDDriver->get3DDeviceList()->getBest(mColourDepth);
521        if (mIsDepthBuffered && dev->NeedsZBuffer())
522        {
523            // Create Z buffer
524            dev->createDepthBuffer(mlpDDSBack);
525            // Don't set z buffer params here, leave to material
526        }
527    }
528
529    void D3D7RenderWindow::releaseDDSurfaces(void)
530    {
531        // Release Z-buffer
532        HRESULT hr;
533        DDSCAPS2 ddscaps;
534
535        ZeroMemory(&ddscaps, sizeof(DDSCAPS2));
536        ddscaps.dwCaps = DDSCAPS_ZBUFFER;
537
538                if (!mlpDDSBack->IsLost())
539                {
540        LPDIRECTDRAWSURFACE7 zBufSurface;
541
542        hr = mlpDDSBack->GetAttachedSurface( &ddscaps, &zBufSurface );
543
544        // Release twice as this method has increased
545        zBufSurface->Release();
546        zBufSurface->Release();
547                }
548
549        // Release std buffers
550        mlpDDSBack->Release();
551        mlpDDSFront->Release();
552
553        mlpDDSBack = mlpDDSFront = 0;
554    }
555
556    void D3D7RenderWindow::restoreDDSurfaces(void)
557    {
558        HRESULT hr;
559
560        if( mlpDDSFront->IsLost() )
561        {
562            hr = mlpDDSFront->Restore();
563
564            if( FAILED( hr ) )
565                        {
566                                if (hr == DDERR_WRONGMODE)
567                                {
568                                        // Fullscreen exclusive mode problem
569                                        // Need to release & recreate
570                                        releaseDDSurfaces();
571                                        createDDSurfaces();
572                                        createDepthBuffer();
573                                        return;
574                                }
575                                else
576                                {
577                                        char szBuffer[512];
578                                        D3DXGetErrorString( hr, 512, szBuffer );
579                OGRE_EXCEPT(
580                    Exception::ERR_INTERNAL_ERROR,
581                                                "Error restoring lost primary surface." + String(szBuffer),
582                    "D3D7RenderWindow - restoreDDSurfaces" );
583        }
584                        }
585        }
586
587        if( mlpDDSBack->IsLost() )
588        {
589            hr = mlpDDSBack->Restore();
590
591            if( FAILED( hr ) )
592                        {
593                                char szBuffer[512];
594                                D3DXGetErrorString( hr, 512, szBuffer );
595                OGRE_EXCEPT(
596                    Exception::ERR_INTERNAL_ERROR,
597                    "Error restoring lost back buffer surface." + String(szBuffer),
598                    "D3D7RenderWindow - restoreDDSurfaces" );
599        }
600    }
601    }
602
603    void D3D7RenderWindow::windowMovedOrResized(void)
604    {
605        // If windowed mode, check window size & position
606        RECT rcCheck;
607
608        if( mIsFullScreen )
609            return; // Nothing to check
610
611        GetClientRect( mHWnd, &rcCheck );
612        ClientToScreen( mHWnd, (POINT*)&rcCheck.left );
613        ClientToScreen( mHWnd, (POINT*)&rcCheck.right );
614
615                if ((rcCheck.right - rcCheck.left) == 0 ||
616                        (rcCheck.bottom - rcCheck.top) == 0)
617                {
618                        return;
619                }
620
621        // Has the window resized? If so, we need to recreate surfaces
622        if( ( rcCheck.right - rcCheck.left !=
623                rcBlitDest.right - rcBlitDest.left ) ||
624            ( rcCheck.bottom - rcCheck.top !=
625                rcBlitDest.bottom - rcBlitDest.top ) )
626        {
627            // The window has changed size - DD surfaces must be recreated
628            releaseDDSurfaces();
629            createDDSurfaces();
630            createDepthBuffer();
631
632            // Update Viewport Sizes
633           
634            for(
635                ViewportList::iterator it = mViewportList.begin();
636                it != mViewportList.end();
637                ++it )
638            {
639                it->second->_updateDimensions();
640            }
641
642            rcBlitDest = rcCheck;
643        }
644        else if(
645            rcCheck.left != rcBlitDest.left ||
646            rcCheck.top  != rcBlitDest.top )
647        {
648            // Window has only moved
649            // Just alter the blit location
650            rcBlitDest = rcCheck;
651        }
652    }
653
654    //-----------------------------------------------------------------------
655    void D3D7RenderWindow::getCustomAttribute( const String& name, void* pData )
656    {
657        // Valid attributes and their equivalent native functions:
658        // D3DDEVICE            : getD3DDeviceDriver
659        // DDBACKBUFFER         : getDDBackBuffer
660        // DDFRONTBUFFER        : getDDFrontBuffer
661        // HWND                 : getWindowHandle
662
663        if( name == "D3DDEVICE" )
664        {
665            LPDIRECT3DDEVICE7 *pDev = (LPDIRECT3DDEVICE7*)pData;
666
667            *pDev = getD3DDevice();
668            return;
669        }
670        else if( name == "DDBACKBUFFER" )
671        {
672            LPDIRECTDRAWSURFACE7 *pSurf = (LPDIRECTDRAWSURFACE7*)pData;
673
674            *pSurf = getDDBackBuffer();
675            return;
676        }
677        else if( name == "DDFRONTBUFFER" )
678        {
679            LPDIRECTDRAWSURFACE7 *pSurf = (LPDIRECTDRAWSURFACE7*)pData;
680
681            *pSurf = getDDFrontBuffer();
682            return;
683        }
684        else if( name == "HWND" )
685        {
686            HWND *pHwnd = (HWND*)pData;
687
688            *pHwnd = getWindowHandle();
689            return;
690        }
691        else if( name == "isTexture" )
692        {
693            bool *b = reinterpret_cast< bool * >( pData );
694            *b = false;
695
696            return;
697        }
698    }
699
700
701    void D3D7RenderWindow::writeContentsToFile(const String& filename)
702    {
703         HRESULT hr;
704         LPDIRECTDRAWSURFACE7 pTempSurf;
705         DDSURFACEDESC2 desc;
706         RECT srcRect;
707 
708         // Cannot lock surface direct, so create temp surface and blit
709         memset(&desc, 0, sizeof (DDSURFACEDESC2));
710                 desc.dwSize = sizeof(DDSURFACEDESC2);
711         if (FAILED(hr = mlpDDSBack->GetSurfaceDesc(&desc)))
712         {
713                 OGRE_EXCEPT(hr, "Error getting description of back buffer!",
714                 "D3D7RenderWindow::writeContentsToFile");
715         }
716
717         desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
718         desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
719
720                 if (FAILED(hr = mlpDDDriver->directDraw()->CreateSurface(&desc, &pTempSurf, NULL)))
721                 {
722             OGRE_EXCEPT(hr, "Error creating temporary surface!",
723                 "D3D7RenderWindow::writeContentsToFile");
724                 }
725
726         if (mIsFullScreen)
727                 {
728                pTempSurf->Blt(NULL, mlpDDSFront, NULL, NULL, NULL);
729                 }
730         else
731         {
732                GetWindowRect(mHWnd, &srcRect);
733            srcRect.left += GetSystemMetrics(SM_CXSIZEFRAME);
734            srcRect.top += GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION);
735            srcRect.right = srcRect.left + desc.dwWidth;
736            srcRect.bottom = srcRect.top + desc.dwHeight;
737
738            pTempSurf->Blt(NULL, mlpDDSFront, &srcRect, NULL, NULL);
739         }
740
741                 if (FAILED(hr = pTempSurf->Lock(NULL, &desc, 
742             DDLOCK_WAIT | DDLOCK_READONLY, NULL)))
743         {
744             OGRE_EXCEPT(hr, "Cannot lock surface!",
745                 "D3D7RenderWindow::writeContentsToFile");
746         }
747 
748 
749         ImageCodec::ImageData *imgData = new ImageCodec::ImageData();
750         imgData->width = desc.dwWidth;
751         imgData->height = desc.dwHeight;
752         imgData->format = PF_BYTE_RGB;
753 
754         // Allocate contiguous buffer (surfaces aren't necessarily contiguous)
755         uchar* pBuffer = new uchar[desc.dwWidth * desc.dwHeight * 3];
756 
757         uint x, y;
758         uchar *pData, *pDest;
759 
760         pData = (uchar*)desc.lpSurface;
761         pDest = pBuffer;
762         for (y = 0; y < desc.dwHeight; ++y)
763         {
764             uchar *pRow = pData;
765 
766             for (x = 0; x < desc.dwWidth; ++x)
767             {
768                                 if (desc.ddpfPixelFormat.dwRGBBitCount == 16)
769                                 {
770                     WORD val;
771 
772                     val = *((WORD*)pRow);
773                                         pRow += 2;
774
775                                         *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0xF800, (BYTE)0xFF);
776                                         *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x07E0, (BYTE)0xFF);
777                                         *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x001F, (BYTE)0xFF);
778                                 }
779                                 else
780                                 {
781                                         // Actual format is BRGA for some reason
782                     *pDest++ = pRow[2]; // R
783                     *pDest++ = pRow[1]; // G
784                     *pDest++ = pRow[0]; // B
785
786                     pRow += 3; // skip alpha / dummy
787
788                                         if (desc.ddpfPixelFormat.dwRGBBitCount == 32)
789                                         {
790                                                 ++pRow; // Skip alpha
791                                         }
792                 }
793 
794                 
795             }
796             // increase by one line
797             pData += desc.lPitch;
798 
799         }
800 
801 
802         // Wrap buffer in a chunk
803         MemoryDataStreamPtr stream(new MemoryDataStream(pBuffer, desc.dwWidth * desc.dwHeight * 3, false));
804 
805         // Get codec
806         size_t pos = filename.find_last_of(".");
807         String extension;
808            if( pos == String::npos )
809             OGRE_EXCEPT(
810                    Exception::ERR_INVALIDPARAMS,
811                    "Unable to determine image type for '" + filename + "' - invalid extension.",
812             "D3D8RenderWindow::writeContentsToFile" );
813 
814         while( pos != filename.length() - 1 )
815             extension += filename[++pos];
816 
817         // Get the codec
818         Codec * pCodec = Codec::getCodec(extension);
819 
820         // Write out
821         pCodec->codeToFile(stream, filename, Codec::CodecDataPtr(imgData));
822 
823         delete [] pBuffer;
824                 pTempSurf->Release();
825 
826     }
827
828#ifdef GTP_VISIBILITY_MODIFIED_OGRE
829        uchar* D3D7RenderWindow::getBufferContents(int &dimx, int &dimy)
830    {
831         HRESULT hr;
832         LPDIRECTDRAWSURFACE7 pTempSurf;
833         DDSURFACEDESC2 desc;
834         RECT srcRect;
835 
836         // Cannot lock surface direct, so create temp surface and blit
837         memset(&desc, 0, sizeof (DDSURFACEDESC2));
838                 desc.dwSize = sizeof(DDSURFACEDESC2);
839         if (FAILED(hr = mlpDDSBack->GetSurfaceDesc(&desc)))
840         {
841                 OGRE_EXCEPT(hr, "Error getting description of back buffer!",
842                 "D3D7RenderWindow::writeContentsToFile");
843         }
844
845         desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
846         desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
847
848                 if (FAILED(hr = mlpDDDriver->directDraw()->CreateSurface(&desc, &pTempSurf, NULL)))
849                 {
850             OGRE_EXCEPT(hr, "Error creating temporary surface!",
851                 "D3D7RenderWindow::writeContentsToFile");
852                 }
853
854         if (mIsFullScreen)
855                 {
856                pTempSurf->Blt(NULL, mlpDDSFront, NULL, NULL, NULL);
857                 }
858         else
859         {
860                GetWindowRect(mHWnd, &srcRect);
861            srcRect.left += GetSystemMetrics(SM_CXSIZEFRAME);
862            srcRect.top += GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION);
863            srcRect.right = srcRect.left + desc.dwWidth;
864            srcRect.bottom = srcRect.top + desc.dwHeight;
865
866            pTempSurf->Blt(NULL, mlpDDSFront, &srcRect, NULL, NULL);
867         }
868
869                 if (FAILED(hr = pTempSurf->Lock(NULL, &desc, 
870             DDLOCK_WAIT | DDLOCK_READONLY, NULL)))
871         {
872             OGRE_EXCEPT(hr, "Cannot lock surface!",
873                 "D3D7RenderWindow::writeContentsToFile");
874         }
875 
876         dimx = desc.dwWidth;
877         dimy = desc.dwHeight;
878         
879 
880         // Allocate contiguous buffer (surfaces aren't necessarily contiguous)
881         uchar* pBuffer = new uchar[desc.dwWidth * desc.dwHeight * 3];
882 
883         uint x, y;
884         uchar *pData, *pDest;
885 
886         pData = (uchar*)desc.lpSurface;
887         pDest = pBuffer;
888         for (y = 0; y < desc.dwHeight; ++y)
889         {
890             uchar *pRow = pData;
891 
892             for (x = 0; x < desc.dwWidth; ++x)
893             {
894                                 if (desc.ddpfPixelFormat.dwRGBBitCount == 16)
895                                 {
896                     WORD val;
897 
898                     val = *((WORD*)pRow);
899                                         pRow += 2;
900
901                                         *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0xF800, (BYTE)0xFF);
902                                         *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x07E0, (BYTE)0xFF);
903                                         *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x001F, (BYTE)0xFF);
904                                 }
905                                 else
906                                 {
907                                         // Actual format is BRGA for some reason
908                     *pDest++ = pRow[2]; // R
909                     *pDest++ = pRow[1]; // G
910                     *pDest++ = pRow[0]; // B
911
912                     pRow += 3; // skip alpha / dummy
913
914                                         if (desc.ddpfPixelFormat.dwRGBBitCount == 32)
915                                         {
916                                                 ++pRow; // Skip alpha
917                                         }
918                 }
919 
920                 
921             }
922             // increase by one line
923             pData += desc.lPitch;
924 
925         }
926 
927                 pTempSurf->Release();
928
929                 return pBuffer;
930
931     }
932#endif // GTP_VISIBILITY_MODIFIED_OGRE
933}
934
Note: See TracBrowser for help on using the repository browser.