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