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