Main Page Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

# OgreD3D9RenderWindow.cpp

Go to the documentation of this file.

    00001 /*
    00002 -----------------------------------------------------------------------------
    00003 This source file is part of OGRE
    00004     (Object-oriented Graphics Rendering Engine)
    00005 For the latest info, see http://www.ogre3d.org/
    00006
    00007 Copyright © 2000-2002 The OGRE Team
    00008 Also see acknowledgements in Readme.html
    00009
    00010 This program is free software; you can redistribute it and/or modify it under
    00011 the terms of the GNU Lesser General Public License as published by the Free Software
    00012 Foundation; either version 2 of the License, or (at your option) any later
    00013 version.
    00014
    00015 This program is distributed in the hope that it will be useful, but WITHOUT
    00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
    00018
    00019 You should have received a copy of the GNU Lesser General Public License along with
    00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
    00022 http://www.gnu.org/copyleft/lesser.txt.
    00023 -----------------------------------------------------------------------------
    00024 */
    00025 #include "OgreD3D9RenderWindow.h"
    00026 #include "OgreLogManager.h"
    00027 #include "OgreViewport.h"
    00028 #include "OgreException.h"
    00029 #include "OgreRenderSystem.h"
    00030 #include "OgreBitwise.h"
    00031 #include "OgreImageCodec.h"
    00032
    00033 #include "OgreNoMemoryMacros.h"
    00034 #include <d3d9.h>
    00035 #include "OgreMemoryMacros.h"
    00036 #include "OgreRoot.h"
    00037
    00038 namespace Ogre
    00039 {
    00040     // Window procedure callback
    00041     // This is a static member, so applies to all windows but we store the
    00042     // D3D9RenderWindow instance in the window data GetWindowLog/SetWindowLog
    00043     LRESULT D3D9RenderWindow::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
    00044     {
    00045         LPCREATESTRUCT lpcs;
    00046         D3D9RenderWindow* win;
    00047
    00048         // look up window instance
    00049         if( WM_CREATE != uMsg )
    00050             // Get window pointer
    00051             win = (D3D9RenderWindow*)GetWindowLong( hWnd, 0 );
    00052
    00053         switch( uMsg )
    00054         {
    00055         case WM_ACTIVATE:
    00056             if( WA_INACTIVE == LOWORD( wParam ) )
    00057                 win->mActive = false;
    00058             else
    00059                 win->mActive = true;
    00060             break;
    00061
    00062         case WM_CREATE:
    00063             // Log the new window
    00064             // Get CREATESTRUCT
    00065             lpcs = (LPCREATESTRUCT)lParam;
    00066             win = (D3D9RenderWindow*)(lpcs->lpCreateParams);
    00067             // Store pointer in window user data area
    00068             SetWindowLong( hWnd, 0, (long)win );
    00069             win->mActive = true;
    00070
    00071             return 0;
    00072             break;
    00073
    00074         case WM_KEYDOWN:
    00075             // TEMPORARY CODE
    00076             // TODO - queue up keydown / keyup events with
    00077             //  window name and timestamp to be processed
    00078             //  by main loop
    00079
    00080             // ESCAPE closes window
    00081             /*
    00082             if (wParam == VK_ESCAPE)
    00083             {
    00084             win->mClosed = true;
    00085             return 0L;
    00086             }
    00087             */
    00088             break;
    00089
    00090         case WM_PAINT:
    00091             // If we get WM_PAINT messges, it usually means our window was
    00092             // comvered up, so we need to refresh it by re-showing the contents
    00093             // of the current frame.
    00094             if( win->mActive && win->mReady )
    00095                 win->update();
    00096             break;
    00097
    00098         case WM_MOVE:
    00099             // Move messages need to be tracked to update the screen rects
    00100             // used for blitting the backbuffer to the primary
    00101             // *** This doesn't need to be used to Direct3D9 ***
    00102             break;
    00103
    00104         case WM_ENTERSIZEMOVE:
    00105             // Previent rendering while moving / sizing
    00106             win->mReady = false;
    00107             break;
    00108
    00109         case WM_EXITSIZEMOVE:
    00110             win->WindowMovedOrResized();
    00111             win->mReady = true;
    00112             break;
    00113
    00114         case WM_SIZE:
    00115             // Check to see if we are losing or gaining our window.  Set the
    00116             // active flag to match
    00117             if( SIZE_MAXHIDE == wParam || SIZE_MINIMIZED == wParam )
    00118                 win->mActive = false;
    00119             else
    00120             {
    00121                 win->mActive = true;
    00122                 if( win->mReady )
    00123                     win->WindowMovedOrResized();
    00124             }
    00125             break;
    00126
    00127         case WM_GETMINMAXINFO:
    00128             // Prevent the window from going smaller than some minimu size
    00129             ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
    00130             ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
    00131             break;
    00132
    00133         case WM_CLOSE:
    00134             DestroyWindow( win->mHWnd );
    00135             win->mClosed = true;
    00136             return 0;
    00137         }
    00138
    00139         return DefWindowProc( hWnd, uMsg, wParam, lParam );
    00140     }
    00141
    00142     D3D9RenderWindow::D3D9RenderWindow()
    00143     {
    00144         mIsFullScreen = false;
    00145         mpD3DDriver= NULL;
    00146         mpD3DDevice = NULL;
    00147         mHWnd = 0;
    00148         mActive = false;
    00149         mReady = false;
    00150         mClosed = false;
    00151         mExternalHandle = NULL;
    00152     }
    00153
    00154     D3D9RenderWindow::~D3D9RenderWindow()
    00155     {
    00156         SAFE_RELEASE( mpRenderSurface );
    00157         SAFE_RELEASE( mpRenderZBuffer );
    00158         SAFE_RELEASE( mpD3DDevice );
    00159     }
    00160
    00161     bool D3D9RenderWindow::_checkMultiSampleQuality(D3DMULTISAMPLE_TYPE type, DWORD *outQuality, D3DFORMAT format, UINT adapterNum, D3DDEVTYPE deviceType, BOOL fullScreen)
    00162     {
    00163         LPDIRECT3D9 pD3D = mpD3DDriver->getD3D();
    00164
    00165         if (SUCCEEDED(pD3D->CheckDeviceMultiSampleType(
    00166                 adapterNum,
    00167                 deviceType, format,
    00168                 fullScreen, type, outQuality)))
    00169             return true;
    00170         else
    00171             return false;
    00172     }
    00173
    00174     void D3D9RenderWindow::create( const String& name, unsigned int width, unsigned int height, unsigned int colourDepth,
    00175         bool fullScreen, int left, int top, bool depthBuffer, void* miscParam, ... )
    00176     {
    00177         HWND parentHWnd;
    00178         HINSTANCE hInst;
    00179         D3D9Driver* driver;
    00180         long tempPtr;
    00181
    00182         D3DMULTISAMPLE_TYPE mFSAAType = D3DMULTISAMPLE_NONE;
    00183         DWORD mFSAAQuality = 0;
    00184         // Get variable-length params
    00185         // miscParam[0] = HINSTANCE
    00186         // miscParam[1] = D3D9Driver
    00187         // miscParam[2] = parent HWND
    00188         // miscParam[3] = multisample type
    00189         // miscParam[4] = multisample quality
    00190         // miscParam[5] = vsync
    00191
    00192         va_list marker;
    00193         va_start( marker, depthBuffer );
    00194
    00195         tempPtr = va_arg( marker, long );
    00196         hInst = *(HINSTANCE*)tempPtr;
    00197
    00198         tempPtr = va_arg( marker, long );
    00199         driver = (D3D9Driver*)tempPtr;
    00200
    00201         tempPtr = va_arg( marker, long );
    00202         D3D9RenderWindow* parentRW = (D3D9RenderWindow*)tempPtr;
    00203         if( parentRW == NULL )
    00204             parentHWnd = 0;
    00205         else
    00206             parentHWnd = parentRW->getWindowHandle();
    00207
    00208         tempPtr = va_arg( marker, long );
    00209         mFSAAType = (D3DMULTISAMPLE_TYPE)tempPtr;
    00210
    00211         tempPtr = va_arg( marker, long );
    00212         mFSAAQuality = (DWORD)tempPtr;
    00213
    00214         tempPtr = va_arg( marker, long );
    00215         bool vsync = tempPtr ? true : false;
    00216
    00217         va_end( marker );
    00218
    00219         // Destroy current window if any
    00220         if( mHWnd )
    00221             destroy();
    00222
    00223         // track the parent window handle
    00224         mParentHWnd = parentHWnd;
    00225
    00226         if (!mExternalHandle)
    00227         {
    00228             mWidth = width;
    00229             mHeight = height;
    00230             if (!fullScreen)
    00231             {
    00232                 if (!left && (unsigned)GetSystemMetrics(SM_CXSCREEN) > mWidth)
    00233                     mLeft = (GetSystemMetrics(SM_CXSCREEN) / 2) - (mWidth / 2);
    00234                 else
    00235                     mLeft = left;
    00236                 if (!top && (unsigned)GetSystemMetrics(SM_CYSCREEN) > mHeight)
    00237                     mTop = (GetSystemMetrics(SM_CYSCREEN) / 2) - (mHeight / 2);
    00238                 else
    00239                     mTop = top;
    00240             }
    00241             else
    00242                 mTop = mLeft = 0;
    00243
    00244             // Register the window class
    00245             // NB allow 4 bytes of window data for D3D9RenderWindow pointer
    00246             WNDCLASS wndClass = { CS_HREDRAW | CS_VREDRAW, WndProc, 0, 4, hInst,
    00247                 LoadIcon( NULL, IDI_APPLICATION ),
    00248                 LoadCursor( NULL, IDC_ARROW ),
    00249                 (HBRUSH)GetStockObject( BLACK_BRUSH ), NULL,
    00250                 TEXT(name.c_str()) };
    00251             RegisterClass( &wndClass );
    00252
    00253             // Create our main window
    00254             // Pass pointer to self
    00255             HWND hWnd = CreateWindow(TEXT(name.c_str()),
    00256                                      TEXT(name.c_str()),
    00257                                      WS_OVERLAPPEDWINDOW, mLeft, mTop,
    00258                                      mWidth, mHeight, 0L, 0L, hInst, this);
    00259             ShowWindow(hWnd, SW_SHOWNORMAL);
    00260             UpdateWindow(hWnd);
    00261
    00262             mHWnd = hWnd;
    00263             // Store info
    00264             mName = name;
    00265             mIsDepthBuffered = depthBuffer;
    00266             mIsFullScreen = fullScreen;
    00267         }
    00268         else
    00269         {
    00270             mHWnd = mExternalHandle;
    00271             ShowWindow(mHWnd, SW_SHOWNORMAL);
    00272             UpdateWindow(mHWnd);
    00273             RECT rc;
    00274             GetClientRect(mHWnd,&rc);
    00275             mWidth = rc.right;
    00276             mHeight = rc.bottom;
    00277             mLeft = rc.left;
    00278             mTop = rc.top;
    00279             mName = name;
    00280             mIsDepthBuffered = depthBuffer;
    00281             mIsFullScreen = fullScreen;
    00282         }
    00283
    00284         // track colour depth
    00285         mColourDepth = colourDepth;
    00286
    00287         LogManager::getSingleton().logMessage(
    00288             LML_NORMAL, "D3D9 : Created D3D9 Rendering Window '%s' : %ix%i, %ibpp",
    00289             mName.c_str(), mWidth, mHeight, mColourDepth );
    00290
    00291         if( driver && mParentHWnd == NULL )
    00292         {
    00293             mpD3DDriver = driver;
    00294             HRESULT hr;
    00295             LPDIRECT3D9 pD3D = mpD3DDriver->getD3D();
    00296             D3DDEVTYPE devType = D3DDEVTYPE_HAL;
    00297
    00298             ZeroMemory( &md3dpp, sizeof(D3DPRESENT_PARAMETERS) );
    00299             md3dpp.Windowed                 = !fullScreen;
    00300             md3dpp.SwapEffect               = D3DSWAPEFFECT_DISCARD;
    00301             md3dpp.BackBufferCount          = 1;
    00302             md3dpp.EnableAutoDepthStencil   = depthBuffer;
    00303             md3dpp.hDeviceWindow            = mHWnd;
    00304             md3dpp.BackBufferWidth          = mWidth;
    00305             md3dpp.BackBufferHeight         = mHeight;
    00306
    00307             if (vsync)
    00308                 md3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
    00309             else
    00310                 md3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
    00311
    00312             md3dpp.BackBufferFormat     = D3DFMT_R5G6B5;
    00313             if( mColourDepth > 16 )
    00314                 md3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
    00315
    00316             if (mColourDepth > 16 )
    00317             {
    00318                 // Try to create a 32-bit depth, 8-bit stencil
    00319                 if( FAILED( pD3D->CheckDeviceFormat(mpD3DDriver->getAdapterNumber(),
    00320                     devType,  md3dpp.BackBufferFormat,  D3DUSAGE_DEPTHSTENCIL,
    00321                     D3DRTYPE_SURFACE, D3DFMT_D24S8 )))
    00322                 {
    00323                     // Bugger, no 8-bit hardware stencil, just try 32-bit zbuffer
    00324                     if( FAILED( pD3D->CheckDeviceFormat(mpD3DDriver->getAdapterNumber(),
    00325                         devType,  md3dpp.BackBufferFormat,  D3DUSAGE_DEPTHSTENCIL,
    00326                         D3DRTYPE_SURFACE, D3DFMT_D32 )))
    00327                     {
    00328                         // Jeez, what a naff card. Fall back on 16-bit depth buffering
    00329                         md3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    00330                     }
    00331                     else
    00332                         md3dpp.AutoDepthStencilFormat = D3DFMT_D32;
    00333                 }
    00334                 else
    00335                 {
    00336                     // Woohoo!
    00337                     if( SUCCEEDED( pD3D->CheckDepthStencilMatch( mpD3DDriver->getAdapterNumber(), devType,
    00338                         md3dpp.BackBufferFormat, md3dpp.BackBufferFormat, D3DFMT_D24S8 ) ) )
    00339                     {
    00340                         md3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
    00341                     }
    00342                     else
    00343                         md3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
    00344                 }
    00345             }
    00346             else
    00347                 // 16-bit depth, software stencil
    00348                 md3dpp.AutoDepthStencilFormat   = D3DFMT_D16;
    00349
    00350             md3dpp.MultiSampleType = mFSAAType;
    00351             md3dpp.MultiSampleQuality = (mFSAAQuality == 0) ? NULL : mFSAAQuality;
    00352
    00353             hr = pD3D->CreateDevice( mpD3DDriver->getAdapterNumber(), devType, mHWnd,
    00354                 D3DCREATE_HARDWARE_VERTEXPROCESSING, &md3dpp, &mpD3DDevice );
    00355             if( SUCCEEDED( hr ) )
    00356             {
    00357                 mpD3DDevice->GetRenderTarget( 0, &mpRenderSurface );
    00358                 mpD3DDevice->GetDepthStencilSurface( &mpRenderZBuffer );
    00359             }
    00360             else
    00361             {
    00362                 hr = pD3D->CreateDevice( mpD3DDriver->getAdapterNumber(), devType, mHWnd,
    00363                     D3DCREATE_MIXED_VERTEXPROCESSING, &md3dpp, &mpD3DDevice );
    00364                 if( SUCCEEDED( hr ) )
    00365                 {
    00366                     mpD3DDevice->GetRenderTarget( 0, &mpRenderSurface );
    00367                     mpD3DDevice->GetDepthStencilSurface( &mpRenderZBuffer );
    00368                 }
    00369                 else
    00370                 {
    00371                     hr = pD3D->CreateDevice( mpD3DDriver->getAdapterNumber(), devType, mHWnd,
    00372                         D3DCREATE_SOFTWARE_VERTEXPROCESSING, &md3dpp, &mpD3DDevice );
    00373                     if( SUCCEEDED( hr ) )
    00374                     {
    00375                         mpD3DDevice->GetRenderTarget( 0, &mpRenderSurface );
    00376                         mpD3DDevice->GetDepthStencilSurface( &mpRenderZBuffer );
    00377                     }
    00378                 }
    00379             }
    00380
    00381             // TODO: make this a bit better e.g. go from pure vertex processing to software
    00382             if( FAILED( hr ) )
    00383             {
    00384                 destroy();
    00385                 Except( hr, "Failed to create Direct3D9 Device: " +
    00386                     Root::getSingleton().getErrorDescription(hr),
    00387                     "D3D9RenderWindow::create" );
    00388             }
    00389         }
    00390         else
    00391             mpD3DDevice = NULL;
    00392
    00393         mReady = true;
    00394     }
    00395
    00396     void D3D9RenderWindow::destroy()
    00397     {
    00398         SAFE_RELEASE( mpRenderSurface );
    00399         SAFE_RELEASE( mpRenderZBuffer );
    00400         SAFE_RELEASE( mpD3DDevice );
    00401         SAFE_RELEASE(mpRenderSurface);
    00402         SAFE_RELEASE(mpRenderZBuffer);
    00403         DestroyWindow( mHWnd );
    00404     }
    00405
    00406     void D3D9RenderWindow::resize( unsigned int width, unsigned int height )
    00407     {
    00408         mWidth = width;
    00409         mHeight = height;
    00410
    00411         // Notify viewports of resize
    00412         ViewportList::iterator it = mViewportList.begin();
    00413         while( it != mViewportList.end() )
    00414             (*it++).second->_updateDimensions();
    00415         // TODO - resize window
    00416     }
    00417
    00418     void D3D9RenderWindow::swapBuffers( bool waitForVSync )
    00419     {
    00420         if( mpD3DDevice )
    00421         {
    00422             HRESULT hr = mpD3DDevice->Present( NULL, NULL, 0, NULL );
    00423             if( D3DERR_DEVICELOST == hr )
    00424                 // TODO: Restore surfaces
    00425                 // restoreD3DSurfaces();
    00426                 Except( hr, "Device lost and not restored", "D3D9RenderWindow::swapBuffers" );
    00427             else if( FAILED(hr) )
    00428                 Except( hr, "Error Presenting surfaces", "D3D9RenderWindow::swapBuffers" );
    00429         }
    00430     }
    00431
    00432     void D3D9RenderWindow::getCustomAttribute( const String& name, void* pData )
    00433     {
    00434         // Valid attributes and their equvalent native functions:
    00435         // D3DDEVICE            : getD3DDevice
    00436         // HWND                 : getWindowHandle
    00437
    00438         if( name == "D3DDEVICE" )
    00439         {
    00440             LPDIRECT3DDEVICE9 *pDev = (LPDIRECT3DDEVICE9*)pData;
    00441             *pDev = getD3DDevice();
    00442             return;
    00443         }
    00444         else if( name == "HWND" )
    00445         {
    00446             HWND *pHwnd = (HWND*)pData;
    00447             *pHwnd = getWindowHandle();
    00448             return;
    00449         }
    00450         else if( name == "isTexture" )
    00451         {
    00452             bool *b = reinterpret_cast< bool * >( pData );
    00453             *b = false;
    00454
    00455             return;
    00456         }
    00457         else if( name == "D3DZBUFFER" )
    00458         {
    00459             LPDIRECT3DSURFACE9 *pSurf = (LPDIRECT3DSURFACE9*)pData;
    00460             *pSurf = mpRenderZBuffer;
    00461             return;
    00462         }
    00463         else if( name == "DDBACKBUFFER" )
    00464         {
    00465             LPDIRECT3DSURFACE9 *pSurf = (LPDIRECT3DSURFACE9*)pData;
    00466             *pSurf = mpRenderSurface;
    00467             return;
    00468         }
    00469         else if( name == "DDFRONTBUFFER" )
    00470         {
    00471             LPDIRECT3DSURFACE9 *pSurf = (LPDIRECT3DSURFACE9*)pData;
    00472             *pSurf = mpRenderSurface;
    00473             return;
    00474         }
    00475     }
    00476
    00477     void D3D9RenderWindow::WindowMovedOrResized()
    00478     {
    00479         // TODO
    00480     }
    00481
    00482     void D3D9RenderWindow::writeContentsToFile(const String& filename)
    00483     {
    00484         HRESULT hr;
    00485         LPDIRECT3DSURFACE9 pSurf=NULL, pTempSurf=NULL;
    00486         D3DSURFACE_DESC desc;
    00487         D3DDISPLAYMODE dm;
    00488
    00489         // get display dimensions
    00490         // this will be the dimensions of the front buffer
    00491         if (FAILED(hr = mpD3DDevice->GetDisplayMode(0, &dm)))
    00492             Except(hr, "Can't get display mode!", "D3D9RenderWindow::writeContentsToFile");
    00493
    00494         desc.Width = dm.Width;
    00495         desc.Height = dm.Height;
    00496         desc.Format = D3DFMT_A8R8G8B8;
    00497         if (FAILED(hr = mpD3DDevice->CreateOffscreenPlainSurface(
    00498                         desc.Width,
    00499                         desc.Height,
    00500                         desc.Format,
    00501                         D3DPOOL_SYSTEMMEM,
    00502                         &pTempSurf,
    00503                         NULL)))
    00504         {
    00505             Except(hr, "Cannot create offscreen buffer 1!", "D3D9RenderWindow::writeContentsToFile");
    00506         }
    00507
    00508         if (FAILED(hr = mpD3DDevice->GetFrontBufferData(0, pTempSurf)))
    00509         {
    00510             SAFE_RELEASE(pTempSurf);
    00511             Except(hr, "Can't get front buffer!", "D3D9RenderWindow::writeContentsToFile");
    00512         }
    00513
    00514         if (!mIsFullScreen)
    00515         {
    00516             POINT pt={0, 0};
    00517             RECT srcRect;
    00518             GetWindowRect(mHWnd, &srcRect);
    00519
    00520             desc.Width = srcRect.right - srcRect.left;
    00521             desc.Height = srcRect.bottom - srcRect.top;
    00522             desc.Format = D3DFMT_A8R8G8B8;         // this is what we get from the screen, so stick with it
    00523
    00524             // NB we can't lock the back buffer direct because it's no created that way
    00525             // and to do so hits performance, so copy to another surface
    00526             // Must be the same format as the source surface
    00527             if (FAILED(hr = mpD3DDevice->CreateOffscreenPlainSurface(
    00528                             desc.Width,
    00529                             desc.Height,
    00530                             desc.Format,
    00531                             D3DPOOL_DEFAULT,
    00532                             &pSurf,
    00533                             NULL)))
    00534             {
    00535                 SAFE_RELEASE(pSurf);
    00536                 Except(hr, "Cannot create offscreen buffer 2!", "D3D9RenderWindow::writeContentsToFile");
    00537             }
    00538
    00539             // Copy
    00540             if (FAILED(hr = mpD3DDevice->UpdateSurface(pTempSurf, &srcRect, pSurf, &pt)))
    00541             {
    00542                 SAFE_RELEASE(pTempSurf);
    00543                 SAFE_RELEASE(pSurf);
    00544                 Except(hr, "Cannot update surface!", "D3D9RenderWindow::writeContentsToFile");
    00545             }
    00546
    00547             SAFE_RELEASE(pTempSurf);
    00548             pTempSurf = pSurf;
    00549             pSurf = NULL;
    00550         }
    00551
    00552         D3DLOCKED_RECT lockedRect;
    00553         if (FAILED(hr = pTempSurf->LockRect(&lockedRect, NULL,
    00554             D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK)))
    00555         {
    00556             Except(hr, "can't lock rect!", "D3D9RenderWindow::writeContentsToFile");
    00557         }
    00558
    00559         ImageCodec::ImageData imgData;
    00560         imgData.width = desc.Width;
    00561         imgData.height = desc.Height;
    00562         imgData.format = PF_R8G8B8;
    00563
    00564         // Allocate contiguous buffer (surfaces aren't necessarily contiguous)
    00565         uchar* pBuffer = new uchar[desc.Width * desc.Height * 3];
    00566
    00567         uint x, y;
    00568         uchar *pData, *pDest;
    00569
    00570         pData = (uchar*)lockedRect.pBits;
    00571         pDest = pBuffer;
    00572         for (y = 0; y < desc.Height; ++y)
    00573         {
    00574             uchar *pRow = pData;
    00575
    00576             for (x = 0; x < desc.Width; ++x)
    00577             {
    00578                 switch(desc.Format)
    00579                 {
    00580                 case D3DFMT_R5G6B5:
    00581                     WORD val;
    00582
    00583                     val = *((WORD*)pRow);
    00584                     pRow += 2;
    00585
    00586                     *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0xF800, (BYTE)0xFF);
    00587                     *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x07E0, (BYTE)0xFF);
    00588                     *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x001F, (BYTE)0xFF);
    00589                     break;
    00590                 case D3DFMT_A8R8G8B8:
    00591                 case D3DFMT_X8R8G8B8:
    00592                     // Actual format is BRGA for some reason
    00593                     *pDest++ = pRow[2]; // R
    00594                     *pDest++ = pRow[1]; // G
    00595                     *pDest++ = pRow[0]; // B
    00596                     pRow += 4; // skip alpha / dummy
    00597                     break;
    00598                 case D3DFMT_R8G8B8:
    00599                     // Actual format is BRGA for some reason
    00600                     *pDest++ = pRow[2]; // R
    00601                     *pDest++ = pRow[1]; // G
    00602                     *pDest++ = pRow[0]; // B
    00603                     pRow += 3;
    00604                     break;
    00605                 }
    00606
    00607
    00608             }
    00609             // increase by one line
    00610             pData += lockedRect.Pitch;
    00611         }
    00612
    00613         // Wrap buffer in a chunk
    00614         DataChunk chunk(pBuffer, desc.Width * desc.Height * 3);
    00615
    00616         // Get codec
    00617         size_t pos = filename.find_last_of(".");
    00618         String extension;
    00619         if( pos == String::npos )
    00620             Except(
    00621             Exception::ERR_INVALIDPARAMS,
    00622             "Unable to determine image type for '" + filename + "' - invalid extension.",
    00623             "D3D9RenderWindow::writeContentsToFile" );
    00624
    00625         while( pos != filename.length() - 1 )
    00626             extension += filename[++pos];
    00627
    00628         // Get the codec
    00629         Codec * pCodec = Codec::getCodec(extension);
    00630
    00631         // Write out
    00632         pCodec->codeToFile(chunk, filename, &imgData);
    00633
    00634         delete [] pBuffer;
    00635
    00636         SAFE_RELEASE(pTempSurf);
    00637         SAFE_RELEASE(pSurf);
    00638     }
    00639 }

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:21 2004