source: trunk/VUT/work/ogre_changes/RenderSystems/Direct3D7/src/OgreD3D7RenderWindow.cpp @ 153

Revision 153, 27.7 KB checked in by mattausch, 19 years ago (diff)

added item buffer queries

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