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_APPLICATION ),
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_D24S8 ) ) )
00340                     {
00341                         md3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; 
00342                     } 
00343                     else 
00344                         md3dpp.AutoDepthStencilFormat = D3DFMT_D24X8; 
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             {
00385                 destroy();
00386                 Except( hr, "Failed to create Direct3D9 Device: " + 
00387                     Root::getSingleton().getErrorDescription(hr), 
00388                     "D3D9RenderWindow::create" );
00389             }
00390         }
00391         else
00392             mpD3DDevice = NULL;
00393 
00394         mReady = true;
00395     }
00396 
00397     void D3D9RenderWindow::destroy()
00398     {
00399         SAFE_RELEASE( mpRenderSurface );
00400         SAFE_RELEASE( mpRenderZBuffer );
00401         SAFE_RELEASE( mpD3DDevice );
00402         SAFE_RELEASE(mpRenderSurface);
00403         SAFE_RELEASE(mpRenderZBuffer);
00404         DestroyWindow( mHWnd );
00405     }
00406 
00407     void D3D9RenderWindow::resize( unsigned int width, unsigned int height )
00408     {
00409         mWidth = width;
00410         mHeight = height;
00411 
00412         // Notify viewports of resize
00413         ViewportList::iterator it = mViewportList.begin();
00414         while( it != mViewportList.end() )
00415             (*it).second->_updateDimensions();
00416         // TODO - resize window
00417     }
00418 
00419     void D3D9RenderWindow::swapBuffers( bool waitForVSync )
00420     {
00421         if( mpD3DDevice )
00422         {
00423             HRESULT hr = mpD3DDevice->Present( NULL, NULL, 0, NULL );
00424             if( D3DERR_DEVICELOST == hr )
00425                 // TODO: Restore surfaces
00426                 // restoreD3DSurfaces();
00427                 Except( hr, "Device lost and not restored", "D3D9RenderWindow::swapBuffers" );
00428             else if( FAILED(hr) )
00429                 Except( hr, "Error Presenting surfaces", "D3D9RenderWindow::swapBuffers" );
00430         }
00431     }
00432 
00433     void D3D9RenderWindow::getCustomAttribute( const String& name, void* pData )
00434     {
00435         // Valid attributes and their equvalent native functions:
00436         // D3DDEVICE            : getD3DDevice
00437         // HWND                 : getWindowHandle
00438 
00439         if( name == "D3DDEVICE" )
00440         {
00441             LPDIRECT3DDEVICE9 *pDev = (LPDIRECT3DDEVICE9*)pData;
00442             *pDev = getD3DDevice();
00443             return;
00444         }
00445         else if( name == "HWND" )
00446         {
00447             HWND *pHwnd = (HWND*)pData;
00448             *pHwnd = getWindowHandle();
00449             return;
00450         }
00451         else if( name == "isTexture" )
00452         {
00453             bool *b = reinterpret_cast< bool * >( pData );
00454             *b = false;
00455 
00456             return;
00457         }
00458         else if( name == "D3DZBUFFER" )
00459         {
00460             LPDIRECT3DSURFACE9 *pSurf = (LPDIRECT3DSURFACE9*)pData;
00461             *pSurf = mpRenderZBuffer;
00462             return;
00463         }
00464         else if( name == "DDBACKBUFFER" )
00465         {
00466             LPDIRECT3DSURFACE9 *pSurf = (LPDIRECT3DSURFACE9*)pData;
00467             *pSurf = mpRenderSurface;
00468             return;
00469         }
00470         else if( name == "DDFRONTBUFFER" )
00471         {
00472             LPDIRECT3DSURFACE9 *pSurf = (LPDIRECT3DSURFACE9*)pData;
00473             *pSurf = mpRenderSurface;
00474             return;
00475         }
00476     }
00477 
00478     void D3D9RenderWindow::outputText( int x, int y, const String& text )
00479     {
00480         // Deprecated
00481     }
00482 
00483     void D3D9RenderWindow::WindowMovedOrResized()
00484     {
00485         // TODO
00486     }
00487 
00488     void D3D9RenderWindow::writeContentsToFile(const String& filename)
00489     {
00490         HRESULT hr;
00491         LPDIRECT3DSURFACE9 pSurf=NULL, pTempSurf=NULL;
00492         D3DSURFACE_DESC desc;
00493         D3DDISPLAYMODE dm;
00494 
00495         // get display dimensions
00496         // this will be the dimensions of the front buffer
00497         if (FAILED(hr = mpD3DDevice->GetDisplayMode(0, &dm)))
00498             Except(hr, "Can't get display mode!", "D3D9RenderWindow::writeContentsToFile");
00499 
00500         desc.Width = dm.Width;
00501         desc.Height = dm.Height;
00502         desc.Format = D3DFMT_A8R8G8B8;
00503         if (FAILED(hr = mpD3DDevice->CreateOffscreenPlainSurface(
00504                         desc.Width, 
00505                         desc.Height, 
00506                         desc.Format, 
00507                         D3DPOOL_SYSTEMMEM, 
00508                         &pTempSurf, 
00509                         NULL)))
00510         {
00511             Except(hr, "Cannot create offscreen buffer 1!", "D3D9RenderWindow::writeContentsToFile");
00512         }
00513 
00514         if (FAILED(hr = mpD3DDevice->GetFrontBufferData(0, pTempSurf)))
00515         {
00516             SAFE_RELEASE(pTempSurf);
00517             Except(hr, "Can't get front buffer!", "D3D9RenderWindow::writeContentsToFile");
00518         }
00519 
00520         if (!mIsFullScreen)
00521         {
00522             POINT pt={0, 0};
00523             RECT srcRect;
00524             GetWindowRect(mHWnd, &srcRect);
00525 
00526             desc.Width = srcRect.right - srcRect.left;
00527             desc.Height = srcRect.bottom - srcRect.top;
00528             desc.Format = D3DFMT_A8R8G8B8;         // this is what we get from the screen, so stick with it
00529 
00530             // NB we can't lock the back buffer direct because it's no created that way
00531             // and to do so hits performance, so copy to another surface
00532             // Must be the same format as the source surface
00533             if (FAILED(hr = mpD3DDevice->CreateOffscreenPlainSurface(
00534                             desc.Width, 
00535                             desc.Height, 
00536                             desc.Format, 
00537                             D3DPOOL_DEFAULT, 
00538                             &pSurf,
00539                             NULL)))
00540             {
00541                 SAFE_RELEASE(pSurf);
00542                 Except(hr, "Cannot create offscreen buffer 2!", "D3D9RenderWindow::writeContentsToFile");
00543             }
00544 
00545             // Copy
00546             if (FAILED(hr = mpD3DDevice->UpdateSurface(pTempSurf, &srcRect, pSurf, &pt)))
00547             {
00548                 SAFE_RELEASE(pTempSurf);
00549                 SAFE_RELEASE(pSurf);
00550                 Except(hr, "Cannot update surface!", "D3D9RenderWindow::writeContentsToFile");
00551             }
00552 
00553             SAFE_RELEASE(pTempSurf);
00554             pTempSurf = pSurf;
00555             pSurf = NULL;
00556         }
00557 
00558         D3DLOCKED_RECT lockedRect;
00559         if (FAILED(hr = pTempSurf->LockRect(&lockedRect, NULL, 
00560             D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK)))
00561         {
00562             Except(hr, "can't lock rect!", "D3D9RenderWindow::writeContentsToFile");
00563         } 
00564 
00565         ImageCodec::ImageData imgData;
00566         imgData.width = desc.Width;
00567         imgData.height = desc.Height;
00568         imgData.format = PF_R8G8B8;
00569 
00570         // Allocate contiguous buffer (surfaces aren't necessarily contiguous)
00571         uchar* pBuffer = new uchar[desc.Width * desc.Height * 3];
00572 
00573         uint x, y;
00574         uchar *pData, *pDest;
00575 
00576         pData = (uchar*)lockedRect.pBits;
00577         pDest = pBuffer;
00578         for (y = 0; y < desc.Height; ++y)
00579         {
00580             uchar *pRow = pData;
00581 
00582             for (x = 0; x < desc.Width; ++x)
00583             {
00584                 switch(desc.Format)
00585                 {
00586                 case D3DFMT_R5G6B5:
00587                     WORD val;
00588 
00589                     val = *((WORD*)pRow);
00590                     pRow += 2;
00591 
00592                     *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0xF800, (BYTE)0xFF);
00593                     *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x07E0, (BYTE)0xFF);
00594                     *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x001F, (BYTE)0xFF);
00595                     break;
00596                 case D3DFMT_A8R8G8B8:
00597                 case D3DFMT_X8R8G8B8:
00598                     // Actual format is BRGA for some reason
00599                     *pDest++ = pRow[2]; // R
00600                     *pDest++ = pRow[1]; // G
00601                     *pDest++ = pRow[0]; // B
00602                     pRow += 4; // skip alpha / dummy
00603                     break;
00604                 case D3DFMT_R8G8B8:
00605                     // Actual format is BRGA for some reason
00606                     *pDest++ = pRow[2]; // R
00607                     *pDest++ = pRow[1]; // G
00608                     *pDest++ = pRow[0]; // B
00609                     pRow += 3; 
00610                     break;
00611                 }
00612 
00613 
00614             }
00615             // increase by one line
00616             pData += lockedRect.Pitch;
00617         }
00618 
00619         // Wrap buffer in a chunk
00620         DataChunk chunk(pBuffer, desc.Width * desc.Height * 3);
00621 
00622         // Get codec 
00623         size_t pos = filename.find_last_of(".");
00624         String extension;
00625         if( pos == String::npos )
00626             Except(
00627             Exception::ERR_INVALIDPARAMS, 
00628             "Unable to determine image type for '" + filename + "' - invalid extension.",
00629             "D3D9RenderWindow::writeContentsToFile" );
00630 
00631         while( pos != filename.length() - 1 )
00632             extension += filename[++pos];
00633 
00634         // Get the codec
00635         Codec * pCodec = Codec::getCodec(extension);
00636 
00637         // Write out
00638         pCodec->codeToFile(chunk, filename, &imgData);
00639 
00640         delete [] pBuffer;
00641 
00642         SAFE_RELEASE(pTempSurf);
00643         SAFE_RELEASE(pSurf);
00644     }
00645 }

Copyright © 2002-2003 by The OGRE Team
Last modified Fri May 14 23:22:05 2004