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