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             Root::getSingleton().getRenderSystem()->detachRenderTarget( win->getName() );
00136             win->mClosed = true;
00137             return 0;
00138         }
00139 
00140         return DefWindowProc( hWnd, uMsg, wParam, lParam );
00141     }
00142 
00143     D3D9RenderWindow::D3D9RenderWindow()
00144     {
00145         mIsFullScreen = false;
00146         mpD3DDriver= NULL;
00147         mpD3DDevice = NULL;
00148         mHWnd = 0;
00149         mActive = false;
00150         mReady = false;
00151         mClosed = false;
00152         mExternalHandle = NULL;
00153     }
00154 
00155     D3D9RenderWindow::~D3D9RenderWindow()
00156     {
00157         SAFE_RELEASE( mpRenderSurface );
00158         SAFE_RELEASE( mpRenderZBuffer );
00159         SAFE_RELEASE( mpD3DDevice );
00160     }
00161 
00162     bool D3D9RenderWindow::_checkMultiSampleQuality(D3DMULTISAMPLE_TYPE type, DWORD *outQuality, D3DFORMAT format, UINT adapterNum, D3DDEVTYPE deviceType, BOOL fullScreen)
00163     {
00164         LPDIRECT3D9 pD3D = mpD3DDriver->getD3D();
00165 
00166         if (SUCCEEDED(pD3D->CheckDeviceMultiSampleType(
00167                 adapterNum, 
00168                 deviceType, format, 
00169                 fullScreen, type, outQuality)))
00170             return true;
00171         else
00172             return false;
00173     }
00174 
00175     void D3D9RenderWindow::create( const String& name, unsigned int width, unsigned int height, unsigned int colourDepth, 
00176         bool fullScreen, int left, int top, bool depthBuffer, void* miscParam, ... )
00177     {
00178         HWND parentHWnd;
00179         HINSTANCE hInst;
00180         D3D9Driver* driver;
00181         long tempPtr;
00182         
00183         D3DMULTISAMPLE_TYPE mFSAAType = D3DMULTISAMPLE_NONE;
00184         DWORD mFSAAQuality = 0;
00185         // Get variable-length params
00186         // miscParam[0] = HINSTANCE
00187         // miscParam[1] = D3D9Driver
00188         // miscParam[2] = parent HWND
00189         // miscParam[3] = multisample type
00190         // miscParam[4] = multisample quality
00191         // miscParam[5] = vsync
00192 
00193         va_list marker;
00194         va_start( marker, depthBuffer );
00195 
00196         tempPtr = va_arg( marker, long );
00197         hInst = *(HINSTANCE*)tempPtr;
00198 
00199         tempPtr = va_arg( marker, long );
00200         driver = (D3D9Driver*)tempPtr;
00201 
00202         tempPtr = va_arg( marker, long );
00203         D3D9RenderWindow* parentRW = (D3D9RenderWindow*)tempPtr;
00204         if( parentRW == NULL )
00205             parentHWnd = 0;
00206         else
00207             parentHWnd = parentRW->getWindowHandle();
00208 
00209         tempPtr = va_arg( marker, long );
00210         mFSAAType = (D3DMULTISAMPLE_TYPE)tempPtr;
00211 
00212         tempPtr = va_arg( marker, long );
00213         mFSAAQuality = (DWORD)tempPtr;
00214 
00215         tempPtr = va_arg( marker, long );
00216         bool vsync = tempPtr ? true : false;
00217 
00218         va_end( marker );
00219 
00220         // Destroy current window if any
00221         if( mHWnd )
00222             destroy();
00223 
00224         // track the parent window handle
00225         mParentHWnd = parentHWnd;
00226 
00227         if (!mExternalHandle)
00228         {
00229             mWidth = width;
00230             mHeight = height;
00231             if (!fullScreen)
00232             {
00233                 if (!left && (unsigned)GetSystemMetrics(SM_CXSCREEN) > mWidth)
00234                     mLeft = (GetSystemMetrics(SM_CXSCREEN) / 2) - (mWidth / 2);
00235                 else
00236                     mLeft = left;
00237                 if (!top && (unsigned)GetSystemMetrics(SM_CYSCREEN) > mHeight)
00238                     mTop = (GetSystemMetrics(SM_CYSCREEN) / 2) - (mHeight / 2);
00239                 else
00240                     mTop = top;
00241             }
00242             else
00243                 mTop = mLeft = 0;
00244 
00245             // Register the window class
00246             // NB allow 4 bytes of window data for D3D9RenderWindow pointer
00247             WNDCLASS wndClass = { CS_HREDRAW | CS_VREDRAW, WndProc, 0, 4, hInst,
00248                 LoadIcon( NULL, "IDI_ICON1" ),
00249                 LoadCursor( NULL, IDC_ARROW ),
00250                 (HBRUSH)GetStockObject( BLACK_BRUSH ), NULL,
00251                 TEXT(name.c_str()) };
00252             RegisterClass( &wndClass );
00253 
00254             // Create our main window
00255             // Pass pointer to self
00256             HWND hWnd = CreateWindow(TEXT(name.c_str()),
00257                                      TEXT(name.c_str()),
00258                                      WS_OVERLAPPEDWINDOW, mLeft, mTop,
00259                                      mWidth, mHeight, 0L, 0L, hInst, this);
00260             ShowWindow(hWnd, SW_SHOWNORMAL);
00261             UpdateWindow(hWnd);
00262 
00263             mHWnd = hWnd;
00264             // Store info
00265             mName = name;
00266             mIsDepthBuffered = depthBuffer;
00267             mIsFullScreen = fullScreen;
00268         }
00269         else
00270         {
00271             mHWnd = mExternalHandle;
00272             ShowWindow(mHWnd, SW_SHOWNORMAL);
00273             UpdateWindow(mHWnd);
00274             RECT rc;
00275             GetClientRect(mHWnd,&rc);
00276             mWidth = rc.right;
00277             mHeight = rc.bottom;
00278             mLeft = rc.left;
00279             mTop = rc.top;
00280             mName = name;
00281             mIsDepthBuffered = depthBuffer;
00282             mIsFullScreen = fullScreen;
00283         }
00284 
00285         // track colour depth
00286         mColourDepth = colourDepth;
00287 
00288         LogManager::getSingleton().logMessage(
00289             LML_NORMAL, "D3D9 : Created D3D9 Rendering Window '%s' : %ix%i, %ibpp",
00290             mName.c_str(), mWidth, mHeight, mColourDepth );
00291 
00292         if( driver && mParentHWnd == NULL )
00293         {
00294             mpD3DDriver = driver;
00295             HRESULT hr;
00296             LPDIRECT3D9 pD3D = mpD3DDriver->getD3D();
00297             D3DDEVTYPE devType = D3DDEVTYPE_HAL;
00298 
00299             ZeroMemory( &md3dpp, sizeof(D3DPRESENT_PARAMETERS) );
00300             md3dpp.Windowed                 = !fullScreen;
00301             md3dpp.SwapEffect               = D3DSWAPEFFECT_DISCARD;
00302             md3dpp.BackBufferCount          = 1;
00303             md3dpp.EnableAutoDepthStencil   = depthBuffer;
00304             md3dpp.hDeviceWindow            = mHWnd;
00305             md3dpp.BackBufferWidth          = mWidth;
00306             md3dpp.BackBufferHeight         = mHeight;
00307 
00308             if (vsync)
00309                 md3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
00310             else
00311                 md3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
00312 
00313             md3dpp.BackBufferFormat     = D3DFMT_R5G6B5;
00314             if( mColourDepth > 16 )
00315                 md3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
00316 
00317             if (mColourDepth > 16 )
00318             {
00319                 // Try to create a 32-bit depth, 8-bit stencil
00320                 if( FAILED( pD3D->CheckDeviceFormat(mpD3DDriver->getAdapterNumber(),
00321                     devType,  md3dpp.BackBufferFormat,  D3DUSAGE_DEPTHSTENCIL, 
00322                     D3DRTYPE_SURFACE, D3DFMT_D24S8 )))
00323                 {
00324                     // Bugger, no 8-bit hardware stencil, just try 32-bit zbuffer 
00325                     if( FAILED( pD3D->CheckDeviceFormat(mpD3DDriver->getAdapterNumber(),
00326                         devType,  md3dpp.BackBufferFormat,  D3DUSAGE_DEPTHSTENCIL, 
00327                         D3DRTYPE_SURFACE, D3DFMT_D32 )))
00328                     {
00329                         // Jeez, what a naff card. Fall back on 16-bit depth buffering
00330                         md3dpp.AutoDepthStencilFormat = D3DFMT_D16;
00331                     }
00332                     else
00333                         md3dpp.AutoDepthStencilFormat = D3DFMT_D32;
00334                 }
00335                 else
00336                 {
00337                     // Woohoo!
00338                     if( SUCCEEDED( pD3D->CheckDepthStencilMatch( mpD3DDriver->getAdapterNumber(), devType,
00339                         md3dpp.BackBufferFormat, md3dpp.BackBufferFormat, D3DFMT_D24X8 ) ) )
00340                     {
00341                         md3dpp.AutoDepthStencilFormat = D3DFMT_D24X8; 
00342                     } 
00343                     else 
00344                         md3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; 
00345                 }
00346             }
00347             else
00348                 // 16-bit depth, software stencil
00349                 md3dpp.AutoDepthStencilFormat   = D3DFMT_D16;
00350 
00351             md3dpp.MultiSampleType = mFSAAType;
00352             md3dpp.MultiSampleQuality = (mFSAAQuality == 0) ? NULL : mFSAAQuality;
00353 
00354             hr = pD3D->CreateDevice( mpD3DDriver->getAdapterNumber(), devType, mHWnd,
00355                 D3DCREATE_HARDWARE_VERTEXPROCESSING, &md3dpp, &mpD3DDevice );
00356             if( SUCCEEDED( hr ) )
00357             {
00358                 mpD3DDevice->GetRenderTarget( 0, &mpRenderSurface );
00359                 mpD3DDevice->GetDepthStencilSurface( &mpRenderZBuffer );
00360             }
00361             else
00362             {
00363                 hr = pD3D->CreateDevice( mpD3DDriver->getAdapterNumber(), devType, mHWnd,
00364                     D3DCREATE_MIXED_VERTEXPROCESSING, &md3dpp, &mpD3DDevice );
00365                 if( SUCCEEDED( hr ) )
00366                 {
00367                     mpD3DDevice->GetRenderTarget( 0, &mpRenderSurface );
00368                     mpD3DDevice->GetDepthStencilSurface( &mpRenderZBuffer );
00369                 }
00370                 else
00371                 {
00372                     hr = pD3D->CreateDevice( mpD3DDriver->getAdapterNumber(), devType, mHWnd,
00373                         D3DCREATE_SOFTWARE_VERTEXPROCESSING, &md3dpp, &mpD3DDevice );
00374                     if( SUCCEEDED( hr ) )
00375                     {
00376                         mpD3DDevice->GetRenderTarget( 0, &mpRenderSurface );
00377                         mpD3DDevice->GetDepthStencilSurface( &mpRenderZBuffer );
00378                     }
00379                 }
00380             }
00381 
00382             // TODO: make this a bit better e.g. go from pure vertex processing to software
00383             if( FAILED( hr ) )
00384                 Except( hr, "Failed to create Direct3D9 Device", "D3D9RenderWindow::create" );
00385         }
00386         else
00387             mpD3DDevice = NULL;
00388 
00389         mReady = true;
00390     }
00391 
00392     void D3D9RenderWindow::destroy()
00393     {
00394         SAFE_RELEASE( mpRenderSurface );
00395         SAFE_RELEASE( mpRenderZBuffer );
00396         SAFE_RELEASE( mpD3DDevice );
00397         SAFE_RELEASE(mpRenderSurface);
00398         SAFE_RELEASE(mpRenderZBuffer);
00399         DestroyWindow( mHWnd );
00400     }
00401 
00402     void D3D9RenderWindow::resize( unsigned int width, unsigned int height )
00403     {
00404         mWidth = width;
00405         mHeight = height;
00406 
00407         // Notify viewports of resize
00408         ViewportList::iterator it = mViewportList.begin();
00409         while( it != mViewportList.end() )
00410             (*it).second->_updateDimensions();
00411         // TODO - resize window
00412     }
00413 
00414     void D3D9RenderWindow::swapBuffers( bool waitForVSync )
00415     {
00416         if( mpD3DDevice )
00417         {
00418             HRESULT hr = mpD3DDevice->Present( NULL, NULL, 0, NULL );
00419             if( D3DERR_DEVICELOST == hr )
00420                 // TODO: Restore surfaces
00421                 // restoreD3DSurfaces();
00422                 Except( hr, "Device lost and not restored", "D3D9RenderWindow::swapBuffers" );
00423             else if( FAILED(hr) )
00424                 Except( hr, "Error Presenting surfaces", "D3D9RenderWindow::swapBuffers" );
00425         }
00426     }
00427 
00428     void D3D9RenderWindow::getCustomAttribute( const String& name, void* pData )
00429     {
00430         // Valid attributes and their equvalent native functions:
00431         // D3DDEVICE            : getD3DDevice
00432         // HWND                 : getWindowHandle
00433 
00434         if( name == "D3DDEVICE" )
00435         {
00436             LPDIRECT3DDEVICE9 *pDev = (LPDIRECT3DDEVICE9*)pData;
00437             *pDev = getD3DDevice();
00438             return;
00439         }
00440         else if( name == "HWND" )
00441         {
00442             HWND *pHwnd = (HWND*)pData;
00443             *pHwnd = getWindowHandle();
00444             return;
00445         }
00446         else if( name == "isTexture" )
00447         {
00448             bool *b = reinterpret_cast< bool * >( pData );
00449             *b = false;
00450 
00451             return;
00452         }
00453         else if( name == "D3DZBUFFER" )
00454         {
00455             LPDIRECT3DSURFACE9 *pSurf = (LPDIRECT3DSURFACE9*)pData;
00456             *pSurf = mpRenderZBuffer;
00457             return;
00458         }
00459         else if( name == "DDBACKBUFFER" )
00460         {
00461             LPDIRECT3DSURFACE9 *pSurf = (LPDIRECT3DSURFACE9*)pData;
00462             *pSurf = mpRenderSurface;
00463             return;
00464         }
00465         else if( name == "DDFRONTBUFFER" )
00466         {
00467             LPDIRECT3DSURFACE9 *pSurf = (LPDIRECT3DSURFACE9*)pData;
00468             *pSurf = mpRenderSurface;
00469             return;
00470         }
00471     }
00472 
00473     void D3D9RenderWindow::outputText( int x, int y, const String& text )
00474     {
00475         // Deprecated
00476     }
00477 
00478     void D3D9RenderWindow::WindowMovedOrResized()
00479     {
00480         // TODO
00481     }
00482 
00483     void D3D9RenderWindow::writeContentsToFile(const String& filename)
00484     {
00485         HRESULT hr;
00486         LPDIRECT3DSURFACE9 pSurf=NULL, pTempSurf=NULL;
00487         D3DSURFACE_DESC desc;
00488         D3DDISPLAYMODE dm;
00489 
00490         // get display dimensions
00491         // this will be the dimensions of the front buffer
00492         if (FAILED(hr = mpD3DDevice->GetDisplayMode(0, &dm)))
00493             Except(hr, "Can't get display mode!", "D3D9RenderWindow::writeContentsToFile");
00494 
00495         desc.Width = dm.Width;
00496         desc.Height = dm.Height;
00497         desc.Format = D3DFMT_A8R8G8B8;
00498         if (FAILED(hr = mpD3DDevice->CreateOffscreenPlainSurface(
00499                         desc.Width, 
00500                         desc.Height, 
00501                         desc.Format, 
00502                         D3DPOOL_SYSTEMMEM, 
00503                         &pTempSurf, 
00504                         NULL)))
00505         {
00506             Except(hr, "Cannot create offscreen buffer 1!", "D3D9RenderWindow::writeContentsToFile");
00507         }
00508 
00509         if (FAILED(hr = mpD3DDevice->GetFrontBufferData(0, pTempSurf)))
00510         {
00511             SAFE_RELEASE(pTempSurf);
00512             Except(hr, "Can't get front buffer!", "D3D9RenderWindow::writeContentsToFile");
00513         }
00514 
00515         if (!mIsFullScreen)
00516         {
00517             POINT pt={0, 0};
00518             RECT srcRect;
00519             GetWindowRect(mHWnd, &srcRect);
00520 
00521             desc.Width = srcRect.right - srcRect.left;
00522             desc.Height = srcRect.bottom - srcRect.top;
00523             desc.Format = D3DFMT_A8R8G8B8;         // this is what we get from the screen, so stick with it
00524 
00525             // NB we can't lock the back buffer direct because it's no created that way
00526             // and to do so hits performance, so copy to another surface
00527             // Must be the same format as the source surface
00528             if (FAILED(hr = mpD3DDevice->CreateOffscreenPlainSurface(
00529                             desc.Width, 
00530                             desc.Height, 
00531                             desc.Format, 
00532                             D3DPOOL_DEFAULT, 
00533                             &pSurf,
00534                             NULL)))
00535             {
00536                 SAFE_RELEASE(pSurf);
00537                 Except(hr, "Cannot create offscreen buffer 2!", "D3D9RenderWindow::writeContentsToFile");
00538             }
00539 
00540             // Copy
00541             if (FAILED(hr = mpD3DDevice->UpdateSurface(pTempSurf, &srcRect, pSurf, &pt)))
00542             {
00543                 SAFE_RELEASE(pTempSurf);
00544                 SAFE_RELEASE(pSurf);
00545                 Except(hr, "Cannot update surface!", "D3D9RenderWindow::writeContentsToFile");
00546             }
00547 
00548             SAFE_RELEASE(pTempSurf);
00549             pTempSurf = pSurf;
00550             pSurf = NULL;
00551         }
00552 
00553         D3DLOCKED_RECT lockedRect;
00554         if (FAILED(hr = pTempSurf->LockRect(&lockedRect, NULL, 
00555             D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK)))
00556         {
00557             Except(hr, "can't lock rect!", "D3D9RenderWindow::writeContentsToFile");
00558         } 
00559 
00560         ImageCodec::ImageData imgData;
00561         imgData.width = desc.Width;
00562         imgData.height = desc.Height;
00563         imgData.format = PF_R8G8B8;
00564 
00565         // Allocate contiguous buffer (surfaces aren't necessarily contiguous)
00566         uchar* pBuffer = new uchar[desc.Width * desc.Height * 3];
00567 
00568         uint x, y;
00569         uchar *pData, *pDest;
00570 
00571         pData = (uchar*)lockedRect.pBits;
00572         pDest = pBuffer;
00573         for (y = 0; y < desc.Height; ++y)
00574         {
00575             uchar *pRow = pData;
00576 
00577             for (x = 0; x < desc.Width; ++x)
00578             {
00579                 switch(desc.Format)
00580                 {
00581                 case D3DFMT_R5G6B5:
00582                     WORD val;
00583 
00584                     val = *((WORD*)pRow);
00585                     pRow += 2;
00586 
00587                     *pDest++ = Bitwise::convertBitPattern<WORD, BYTE>(val, 0xF800, 0xFF);
00588                     *pDest++ = Bitwise::convertBitPattern<WORD, BYTE>(val, 0x07E0, 0xFF);
00589                     *pDest++ = Bitwise::convertBitPattern<WORD, BYTE>(val, 0x001F, 0xFF);
00590                     break;
00591                 case D3DFMT_A8R8G8B8:
00592                 case D3DFMT_X8R8G8B8:
00593                     // Actual format is BRGA for some reason
00594                     *pDest++ = pRow[2]; // R
00595                     *pDest++ = pRow[1]; // G
00596                     *pDest++ = pRow[0]; // B
00597                     pRow += 4; // skip alpha / dummy
00598                     break;
00599                 case D3DFMT_R8G8B8:
00600                     // Actual format is BRGA for some reason
00601                     *pDest++ = pRow[2]; // R
00602                     *pDest++ = pRow[1]; // G
00603                     *pDest++ = pRow[0]; // B
00604                     pRow += 3; 
00605                     break;
00606                 }
00607 
00608 
00609             }
00610             // increase by one line
00611             pData += lockedRect.Pitch;
00612         }
00613 
00614         // Wrap buffer in a chunk
00615         DataChunk chunk(pBuffer, desc.Width * desc.Height * 3);
00616 
00617         // Get codec 
00618         size_t pos = filename.find_last_of(".");
00619         String extension;
00620         if( pos == String::npos )
00621             Except(
00622             Exception::ERR_INVALIDPARAMS, 
00623             "Unable to determine image type for '" + filename + "' - invalid extension.",
00624             "D3D9RenderWindow::writeContentsToFile" );
00625 
00626         while( pos != filename.length() - 1 )
00627             extension += filename[++pos];
00628 
00629         // Get the codec
00630         Codec * pCodec = Codec::getCodec(extension);
00631 
00632         // Write out
00633         pCodec->codeToFile(chunk, filename, &imgData);
00634 
00635         delete [] pBuffer;
00636 
00637         SAFE_RELEASE(pTempSurf);
00638         SAFE_RELEASE(pSurf);
00639     }
00640 }

Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:08 2004