00001 /*------------------------------------------------------------------------- 00002 This source file is a part of OGRE 00003 (Object-oriented Graphics Rendering Engine) 00004 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 library is free software; you can redistribute it and/or modify it 00011 under the terms of the GNU Lesser General Public License (LGPL) as 00012 published by the Free Software Foundation; either version 2.1 of the 00013 License, or (at your option) any later version. 00014 00015 This library is distributed in the hope that it will be useful, but 00016 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 00017 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 00018 License for more details. 00019 00020 You should have received a copy of the GNU Lesser General Public License 00021 along with this library; if not, write to the Free Software Foundation, 00022 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or go to 00023 http://www.gnu.org/copyleft/lesser.txt 00024 -------------------------------------------------------------------------*/ 00025 #include "OgreD3D7RenderWindow.h" 00026 00027 #include "OgreLogManager.h" 00028 #include "OgreViewport.h" 00029 #include "OgreException.h" 00030 #include "OgreRoot.h" 00031 #include "OgreRenderSystem.h" 00032 #include "OgreD3D7TextureManager.h" 00033 #include "OgreBitwise.h" 00034 #include "OgreImageCodec.h" 00035 00036 namespace Ogre { 00037 00038 00039 // Window procedure callback 00040 // This is a static member, so applies to all windows but we store the 00041 // D3D7RenderWindow instance in the window data GetWindowLong/SetWindowLong. 00042 LRESULT D3D7RenderWindow::WndProc( 00043 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) 00044 { 00045 LPCREATESTRUCT lpcs; 00046 D3D7RenderWindow* win; 00047 00048 // look up window instance 00049 if (uMsg != WM_CREATE) 00050 { 00051 // Get window pointer 00052 win = (D3D7RenderWindow*)GetWindowLong(hWnd, 0); 00053 } 00054 00055 switch( uMsg ) 00056 { 00057 case WM_ACTIVATE: 00058 if( LOWORD( wParam ) == WA_INACTIVE ) 00059 win->mActive = false; 00060 else 00061 win->mActive = true; 00062 break; 00063 00064 case WM_CREATE: 00065 // Log the new window 00066 // Get CREATESTRUCT 00067 lpcs = (LPCREATESTRUCT)lParam; 00068 win = (D3D7RenderWindow*)(lpcs->lpCreateParams); 00069 // Store pointer in window user data area 00070 SetWindowLong(hWnd, 0, (long)win); 00071 win->mActive = true; 00072 00073 return 0; 00074 00075 case WM_KEYDOWN: 00076 // TEMPORARY CODE 00077 // TODO - queue up keydown / keyup events with 00078 // window name and timestamp to be processed 00079 // by main loop 00080 00081 // ESCAPE closes window 00082 //if (wParam == VK_ESCAPE) 00083 //{ 00084 // win->mClosed = true; 00085 // return 0L; 00086 //} 00087 break; 00088 00089 case WM_PAINT: 00090 // If we get WM_PAINT messages, it usually means our window was 00091 // covered up, so we need to refresh it by re-showing the contents 00092 // of the current frame. 00093 if (win->mActive && win->mReady) 00094 win->update(); 00095 break; 00096 00097 case WM_MOVE: 00098 // Move messages need to be tracked to update the screen rects 00099 // used for blitting the backbuffer to the primary. 00100 if(win->mActive && win->mReady) 00101 win->windowMovedOrResized(); 00102 break; 00103 00104 case WM_ENTERSIZEMOVE: 00105 // Prevent 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 00126 break; 00127 00128 case WM_GETMINMAXINFO: 00129 // Prevent the window from going smaller than some minimum size 00130 ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100; 00131 ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100; 00132 break; 00133 00134 case WM_CLOSE: 00135 DestroyWindow( win->mHWnd ); 00136 win->mClosed = true; 00137 return 0; 00138 00139 /* 00140 case WM_DESTROY: 00141 g_DIMSystem->CleanupRenderer(); 00142 PostQuitMessage(0); 00143 return 0L; 00144 */ 00145 } 00146 00147 00148 00149 return DefWindowProc( hWnd, uMsg, wParam, lParam ); 00150 } 00151 00152 // ------------------------------------------- 00153 // D3D7RenderWindow Implementation 00154 // ------------------------------------------- 00155 D3D7RenderWindow::D3D7RenderWindow() 00156 { 00157 mIsUsingDirectDraw = false; 00158 mIsFullScreen = false; 00159 mlpDDDriver = 0; 00160 mHWnd = 0; 00161 mActive = false; 00162 mReady = false; 00163 mClosed = false; 00164 } 00165 00166 D3D7RenderWindow::~D3D7RenderWindow() 00167 { 00168 } 00169 00170 00171 00172 00173 void D3D7RenderWindow::create(const String& name, unsigned int width, unsigned int height, unsigned int colourDepth, 00174 bool fullScreen, int left, int top, bool depthBuffer, void* miscParam, ...) 00175 { 00176 00177 HWND parentHWnd; 00178 HINSTANCE hInst; 00179 DDDriver* drv; 00180 long tempPtr; 00181 00182 00183 // Get variable-length params 00184 // miscParam[0] = HINSTANCE 00185 // miscParam[1] = DDDriver 00186 // miscParam[2] = parent HWND 00187 va_list marker; 00188 va_start(marker, depthBuffer); 00189 00190 tempPtr = va_arg(marker, long); 00191 hInst = *(HINSTANCE*)tempPtr; 00192 00193 tempPtr = va_arg(marker, long); 00194 drv = (DDDriver*)tempPtr; 00195 00196 tempPtr = va_arg(marker, long); 00197 D3D7RenderWindow* parentRW = (D3D7RenderWindow*)tempPtr; 00198 if (parentRW == 0) 00199 { 00200 parentHWnd = 0; 00201 } 00202 else 00203 { 00204 parentHWnd = parentRW->getWindowHandle(); 00205 } 00206 00207 va_end(marker); 00208 00209 // Destroy current window if any 00210 if (mHWnd) 00211 { 00212 destroy(); 00213 } 00214 00215 // TODO: deal with child windows 00216 mParentHWnd = parentHWnd; 00217 00218 00219 // Register the window class 00220 // NB Allow 4 bytes of window data for D3D7RenderWindow pointer 00221 WNDCLASS wndClass = { CS_HREDRAW | CS_VREDRAW, WndProc, 0, 4, hInst, 00222 LoadIcon( NULL, IDI_APPLICATION ), 00223 LoadCursor(NULL, IDC_ARROW), 00224 (HBRUSH)GetStockObject(BLACK_BRUSH), NULL, 00225 TEXT(name.c_str()) }; 00226 RegisterClass( &wndClass ); 00227 00228 // Create our main window 00229 // Pass pointer to self 00230 HWND hWnd = CreateWindow( TEXT(name.c_str()), 00231 TEXT(name.c_str()), 00232 WS_OVERLAPPEDWINDOW, left, top, 00233 width, height, 0L, 0L, hInst, this ); 00234 ShowWindow( hWnd, SW_SHOWNORMAL ); 00235 UpdateWindow( hWnd ); 00236 00237 mHWnd = hWnd; 00238 00239 // Store info 00240 mName = name; 00241 mWidth = width; 00242 mHeight = height; 00243 mIsDepthBuffered = depthBuffer; 00244 mIsFullScreen = fullScreen; 00245 00246 if (fullScreen) 00247 { 00248 mColourDepth = colourDepth; 00249 mLeft = 0; 00250 mTop = 0; 00251 } 00252 else 00253 { 00254 // Get colour depth from display 00255 HDC hdc = GetDC( mHWnd ); 00256 mColourDepth = GetDeviceCaps( hdc, BITSPIXEL ); 00257 ReleaseDC( mHWnd, hdc ); 00258 mTop = top; 00259 mLeft = left; 00260 00261 // Record the dimensions of the blit location 00262 GetClientRect( mHWnd, &rcBlitDest ); 00263 ClientToScreen( mHWnd, (POINT*)&rcBlitDest.left ); 00264 ClientToScreen( mHWnd, (POINT*)&rcBlitDest.right ); 00265 } 00266 00267 LogManager::getSingleton().logMessage( 00268 LML_NORMAL, 00269 "Created Win32 Rendering Window '%s': %i x %i @ %ibpp", 00270 mName.c_str(), mWidth, mHeight, mColourDepth ); 00271 00272 // Set up DirectDraw if appropriate 00273 // NB devices & surfaces set up for root window only 00274 if (drv && mParentHWnd == NULL) 00275 { 00276 // DD Driver object passed 00277 mlpDDDriver = drv; 00278 mIsUsingDirectDraw = true; 00279 00280 createDDSurfaces(); 00281 // Get best device based on render bit depth 00282 D3DDevice* dev = mlpDDDriver->get3DDeviceList()->getBest(mColourDepth); 00283 00284 // create D3D device for this window 00285 mlpD3DDevice = dev->createDevice(mlpDDSBack); 00286 createDepthBuffer(); 00287 } 00288 else 00289 mIsUsingDirectDraw = false; 00290 00291 mReady = true; 00292 } 00293 00294 void D3D7RenderWindow::destroy(void) 00295 { 00296 if (mIsUsingDirectDraw) 00297 releaseDDSurfaces(); 00298 00299 DestroyWindow(mHWnd); 00300 00301 } 00302 00303 bool D3D7RenderWindow::isActive(void) const 00304 { 00305 return mActive; 00306 } 00307 00308 bool D3D7RenderWindow::isClosed(void) const 00309 { 00310 return mClosed; 00311 } 00312 00313 void D3D7RenderWindow::reposition(int left, int top) 00314 { 00315 00316 } 00317 00318 void D3D7RenderWindow::resize(unsigned int width, unsigned int height) 00319 { 00320 mWidth = width; 00321 mHeight = height; 00322 00323 // Notify viewports of resize 00324 ViewportList::iterator it = mViewportList.begin(); 00325 while (it != mViewportList.end()) 00326 (*it++).second->_updateDimensions(); 00327 00328 // TODO - resize window 00329 00330 } 00331 00332 void D3D7RenderWindow::swapBuffers(bool waitForVSync) 00333 { 00334 HRESULT hr; 00335 DWORD flags; 00336 if (mIsUsingDirectDraw) 00337 { 00338 if (mIsFullScreen) 00339 { 00340 // Use flipping chain 00341 if (waitForVSync) 00342 { 00343 flags = DDFLIP_WAIT; 00344 } 00345 else 00346 { 00347 flags = DDFLIP_WAIT | DDFLIP_NOVSYNC; 00348 } 00349 00350 hr = mlpDDSFront->Flip(NULL,flags); 00351 } 00352 else 00353 { 00354 // Ordinary Blit 00355 RECT srcRect; 00356 srcRect.left = 0; 00357 srcRect.top = 0; 00358 srcRect.right = rcBlitDest.right - rcBlitDest.left; 00359 srcRect.bottom = rcBlitDest.bottom - rcBlitDest.top; 00360 hr = mlpDDSFront->Blt(&rcBlitDest,mlpDDSBack,&srcRect,DDBLT_WAIT,NULL); 00361 } 00362 00363 if (hr == DDERR_SURFACELOST) 00364 { 00365 // Restore surfaces 00366 restoreDDSurfaces(); 00367 } 00368 else if (FAILED(hr)) 00369 { 00370 Except( 00371 hr, 00372 "Error flipping surfaces", 00373 "D3D7RenderWindow::swapBuffers" ); 00374 } 00375 } 00376 00377 } 00378 00379 HWND D3D7RenderWindow::getWindowHandle(void) const 00380 { 00381 return mHWnd; 00382 } 00383 00384 HWND D3D7RenderWindow::getParentWindowHandle(void) const 00385 { 00386 return mParentHWnd; 00387 } 00388 00389 bool D3D7RenderWindow::isUsingDirectDraw(void) const 00390 { 00391 return mIsUsingDirectDraw; 00392 } 00393 00394 // ------------------------------------------------------- 00395 // DirectDraw specific methods 00396 // ------------------------------------------------------- 00397 DDDriver* D3D7RenderWindow::getDirectDrawDriver(void) 00398 { 00399 return mlpDDDriver; 00400 } 00401 00402 LPDIRECTDRAWSURFACE7 D3D7RenderWindow::getDDFrontBuffer(void) 00403 { 00404 return mlpDDSFront; 00405 00406 } 00407 00408 LPDIRECTDRAWSURFACE7 D3D7RenderWindow::getDDBackBuffer(void) 00409 { 00410 return mlpDDSBack; 00411 } 00412 LPDIRECT3DDEVICE7 D3D7RenderWindow::getD3DDevice(void) 00413 { 00414 return mlpD3DDevice; 00415 } 00416 00417 void D3D7RenderWindow::createDDSurfaces(void) 00418 { 00419 // Use DirectDraw wrapper object to create surfaces 00420 if( !mlpDDDriver ) 00421 { 00422 Except( 00423 Exception::ERR_INVALIDPARAMS, 00424 "Cannot create surfaces because of no valid DirectDraw object", 00425 "D3D7RenderWindow::createDDSurfaces" ); 00426 } 00427 00428 if( mIsFullScreen ) 00429 { 00430 mlpDDDriver->createWindowSurfaces( 00431 mHWnd, 00432 mWidth, mHeight, mColourDepth, 00433 true, &mlpDDSFront, &mlpDDSBack); 00434 } 00435 else 00436 { 00437 // Windowed mode - need to use client rect for surface dimensions 00438 // I.e. we need to ignore menu bars, borders, title bar etc 00439 RECT rcClient; 00440 unsigned int cWidth, cHeight; 00441 00442 GetClientRect( mHWnd, &rcClient ); 00443 ClientToScreen( mHWnd, (POINT*)&rcClient.left ); 00444 ClientToScreen( mHWnd, (POINT*)&rcClient.right ); 00445 00446 cWidth = rcClient.right - rcClient.left; 00447 cHeight = rcClient.bottom - rcClient.top; 00448 00449 // Create surfaces (AND clipper) 00450 mlpDDDriver->createWindowSurfaces( 00451 mHWnd, 00452 cWidth, cHeight, 0, 00453 false, &mlpDDSFront, &mlpDDSBack); 00454 00455 // Update own dimensions since target width / height is this 00456 mWidth = cWidth; 00457 mHeight = cHeight; 00458 } 00459 } 00460 00461 void D3D7RenderWindow::createDepthBuffer(void) 00462 { 00463 // Get best device based on render bit depth 00464 D3DDevice* dev = mlpDDDriver->get3DDeviceList()->getBest(mColourDepth); 00465 if (mIsDepthBuffered && dev->NeedsZBuffer()) 00466 { 00467 // Create Z buffer 00468 dev->createDepthBuffer(mlpDDSBack); 00469 // Don't set z buffer params here, leave to material 00470 } 00471 } 00472 00473 void D3D7RenderWindow::releaseDDSurfaces(void) 00474 { 00475 // Release Z-buffer 00476 HRESULT hr; 00477 DDSCAPS2 ddscaps; 00478 00479 ZeroMemory(&ddscaps, sizeof(DDSCAPS2)); 00480 ddscaps.dwCaps = DDSCAPS_ZBUFFER; 00481 00482 LPDIRECTDRAWSURFACE7 zBufSurface; 00483 00484 hr = mlpDDSBack->GetAttachedSurface( &ddscaps, &zBufSurface ); 00485 00486 // Release twice as this method has increased 00487 zBufSurface->Release(); 00488 zBufSurface->Release(); 00489 00490 // Release std buffers 00491 mlpDDSBack->Release(); 00492 mlpDDSFront->Release(); 00493 00494 mlpDDSBack = mlpDDSFront = 0; 00495 } 00496 00497 void D3D7RenderWindow::restoreDDSurfaces(void) 00498 { 00499 HRESULT hr; 00500 00501 if( mlpDDSFront->IsLost() ) 00502 { 00503 hr = mlpDDSFront->Restore(); 00504 00505 if( FAILED( hr ) ) 00506 Except( 00507 Exception::ERR_INTERNAL_ERROR, 00508 "Error restoring lost primary surface.", 00509 "D3D7RenderWindow - restoreDDSurfaces" ); 00510 } 00511 00512 if( mlpDDSBack->IsLost() ) 00513 { 00514 hr = mlpDDSBack->Restore(); 00515 00516 if( FAILED( hr ) ) 00517 Except( 00518 Exception::ERR_INTERNAL_ERROR, 00519 "Error restoring lost back buffer surface.", 00520 "D3D7RenderWindow - restoreDDSurfaces" ); 00521 } 00522 } 00523 00524 void D3D7RenderWindow::windowMovedOrResized(void) 00525 { 00526 // If windowed mode, check window size & position 00527 RECT rcCheck; 00528 00529 if( mIsFullScreen ) 00530 return; // Nothing to check 00531 00532 GetClientRect( mHWnd, &rcCheck ); 00533 ClientToScreen( mHWnd, (POINT*)&rcCheck.left ); 00534 ClientToScreen( mHWnd, (POINT*)&rcCheck.right ); 00535 00536 // Has the window resized? If so, we need to recreate surfaces 00537 if( ( rcCheck.right - rcCheck.left != 00538 rcBlitDest.right - rcBlitDest.left ) || 00539 ( rcCheck.bottom - rcCheck.top != 00540 rcBlitDest.bottom - rcBlitDest.top ) ) 00541 { 00542 // The window has changed size - DD surfaces must be recreated 00543 releaseDDSurfaces(); 00544 createDDSurfaces(); 00545 createDepthBuffer(); 00546 00547 // Update Viewport Sizes 00548 00549 for( 00550 ViewportList::iterator it = mViewportList.begin(); 00551 it != mViewportList.end(); 00552 ++it ) 00553 { 00554 it->second->_updateDimensions(); 00555 } 00556 00557 rcBlitDest = rcCheck; 00558 } 00559 else if( 00560 rcCheck.left != rcBlitDest.left || 00561 rcCheck.top != rcBlitDest.top ) 00562 { 00563 // Window has only moved 00564 // Just alter the blit location 00565 rcBlitDest = rcCheck; 00566 } 00567 } 00568 00569 //----------------------------------------------------------------------- 00570 void D3D7RenderWindow::getCustomAttribute( const String& name, void* pData ) 00571 { 00572 // Valid attributes and their equivalent native functions: 00573 // D3DDEVICE : getD3DDeviceDriver 00574 // DDBACKBUFFER : getDDBackBuffer 00575 // DDFRONTBUFFER : getDDFrontBuffer 00576 // HWND : getWindowHandle 00577 00578 if( name == "D3DDEVICE" ) 00579 { 00580 LPDIRECT3DDEVICE7 *pDev = (LPDIRECT3DDEVICE7*)pData; 00581 00582 *pDev = getD3DDevice(); 00583 return; 00584 } 00585 else if( name == "DDBACKBUFFER" ) 00586 { 00587 LPDIRECTDRAWSURFACE7 *pSurf = (LPDIRECTDRAWSURFACE7*)pData; 00588 00589 *pSurf = getDDBackBuffer(); 00590 return; 00591 } 00592 else if( name == "DDFRONTBUFFER" ) 00593 { 00594 LPDIRECTDRAWSURFACE7 *pSurf = (LPDIRECTDRAWSURFACE7*)pData; 00595 00596 *pSurf = getDDFrontBuffer(); 00597 return; 00598 } 00599 else if( name == "HWND" ) 00600 { 00601 HWND *pHwnd = (HWND*)pData; 00602 00603 *pHwnd = getWindowHandle(); 00604 return; 00605 } 00606 else if( name == "isTexture" ) 00607 { 00608 bool *b = reinterpret_cast< bool * >( pData ); 00609 *b = false; 00610 00611 return; 00612 } 00613 } 00614 00615 00616 void D3D7RenderWindow::writeContentsToFile(const String& filename) 00617 { 00618 HRESULT hr; 00619 LPDIRECTDRAWSURFACE7 pTempSurf; 00620 DDSURFACEDESC2 desc; 00621 RECT srcRect; 00622 00623 // Cannot lock surface direct, so create temp surface and blit 00624 memset(&desc, 0, sizeof (DDSURFACEDESC2)); 00625 desc.dwSize = sizeof(DDSURFACEDESC2); 00626 if (FAILED(hr = mlpDDSBack->GetSurfaceDesc(&desc))) 00627 { 00628 Except(hr, "Error getting description of back buffer!", 00629 "D3D7RenderWindow::writeContentsToFile"); 00630 } 00631 00632 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; 00633 desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; 00634 00635 if (FAILED(hr = mlpDDDriver->directDraw()->CreateSurface(&desc, &pTempSurf, NULL))) 00636 { 00637 Except(hr, "Error creating temporary surface!", 00638 "D3D7RenderWindow::writeContentsToFile"); 00639 } 00640 00641 if (mIsFullScreen) 00642 { 00643 pTempSurf->Blt(NULL, mlpDDSFront, NULL, NULL, NULL); 00644 } 00645 else 00646 { 00647 GetWindowRect(mHWnd, &srcRect); 00648 srcRect.left += GetSystemMetrics(SM_CXSIZEFRAME); 00649 srcRect.top += GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION); 00650 srcRect.right = srcRect.left + desc.dwWidth; 00651 srcRect.bottom = srcRect.top + desc.dwHeight; 00652 00653 pTempSurf->Blt(NULL, mlpDDSFront, &srcRect, NULL, NULL); 00654 } 00655 00656 if (FAILED(hr = pTempSurf->Lock(NULL, &desc, 00657 DDLOCK_WAIT | DDLOCK_READONLY, NULL))) 00658 { 00659 Except(hr, "Cannot lock surface!", 00660 "D3D7RenderWindow::writeContentsToFile"); 00661 } 00662 00663 00664 ImageCodec::ImageData imgData; 00665 imgData.width = desc.dwWidth; 00666 imgData.height = desc.dwHeight; 00667 imgData.format = PF_R8G8B8; 00668 00669 // Allocate contiguous buffer (surfaces aren't necessarily contiguous) 00670 uchar* pBuffer = new uchar[desc.dwWidth * desc.dwHeight * 3]; 00671 00672 uint x, y; 00673 uchar *pData, *pDest; 00674 00675 pData = (uchar*)desc.lpSurface; 00676 pDest = pBuffer; 00677 for (y = 0; y < desc.dwHeight; ++y) 00678 { 00679 uchar *pRow = pData; 00680 00681 for (x = 0; x < desc.dwWidth; ++x) 00682 { 00683 if (desc.ddpfPixelFormat.dwRGBBitCount == 16) 00684 { 00685 WORD val; 00686 00687 val = *((WORD*)pRow); 00688 pRow += 2; 00689 00690 *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0xF800, (BYTE)0xFF); 00691 *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x07E0, (BYTE)0xFF); 00692 *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x001F, (BYTE)0xFF); 00693 } 00694 else 00695 { 00696 // Actual format is BRGA for some reason 00697 *pDest++ = pRow[2]; // R 00698 *pDest++ = pRow[1]; // G 00699 *pDest++ = pRow[0]; // B 00700 00701 pRow += 3; // skip alpha / dummy 00702 00703 if (desc.ddpfPixelFormat.dwRGBBitCount == 32) 00704 { 00705 ++pRow; // Skip alpha 00706 } 00707 } 00708 00709 00710 } 00711 // increase by one line 00712 pData += desc.lPitch; 00713 00714 } 00715 00716 00717 // Wrap buffer in a chunk 00718 DataChunk chunk(pBuffer, desc.dwWidth * desc.dwHeight * 3); 00719 00720 // Get codec 00721 size_t pos = filename.find_last_of("."); 00722 String extension; 00723 if( pos == String::npos ) 00724 Except( 00725 Exception::ERR_INVALIDPARAMS, 00726 "Unable to determine image type for '" + filename + "' - invalid extension.", 00727 "D3D8RenderWindow::writeContentsToFile" ); 00728 00729 while( pos != filename.length() - 1 ) 00730 extension += filename[++pos]; 00731 00732 // Get the codec 00733 Codec * pCodec = Codec::getCodec(extension); 00734 00735 // Write out 00736 pCodec->codeToFile(chunk, filename, &imgData); 00737 00738 delete [] pBuffer; 00739 pTempSurf->Release(); 00740 00741 } 00742 00743 } 00744
Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:19 2004