Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreD3D7RenderWindow.cpp

Go to the documentation of this file.
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                 Root::getSingleton().getRenderSystem()->detachRenderTarget( win->getName() );
00137                 win->mClosed = true;
00138                 return 0;
00139 
00140             /*
00141             case WM_DESTROY:
00142                 g_DIMSystem->CleanupRenderer();
00143                 PostQuitMessage(0);
00144                 return 0L;
00145             */
00146         }
00147 
00148 
00149 
00150         return DefWindowProc( hWnd, uMsg, wParam, lParam );
00151     }
00152 
00153     // -------------------------------------------
00154     // D3D7RenderWindow Implementation
00155     // -------------------------------------------
00156     D3D7RenderWindow::D3D7RenderWindow()
00157     {
00158         mIsUsingDirectDraw = false;
00159         mIsFullScreen = false;
00160         mlpDDDriver = 0;
00161         mHWnd = 0;
00162         mActive = false;
00163         mReady = false;
00164         mClosed = false;
00165     }
00166 
00167     D3D7RenderWindow::~D3D7RenderWindow()
00168     {
00169     }
00170 
00171 
00172 
00173 
00174     void D3D7RenderWindow::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 
00178         HWND parentHWnd;
00179         HINSTANCE hInst;
00180         DDDriver* drv;
00181         long tempPtr;
00182 
00183 
00184         // Get variable-length params
00185         // miscParam[0] = HINSTANCE
00186         // miscParam[1] = DDDriver
00187         // miscParam[2] = parent HWND
00188         va_list marker;
00189         va_start(marker, depthBuffer);
00190 
00191         tempPtr = va_arg(marker, long);
00192         hInst = *(HINSTANCE*)tempPtr;
00193 
00194         tempPtr = va_arg(marker, long);
00195         drv = (DDDriver*)tempPtr;
00196 
00197         tempPtr = va_arg(marker, long);
00198         D3D7RenderWindow* parentRW = (D3D7RenderWindow*)tempPtr;
00199         if (parentRW == 0)
00200         {
00201             parentHWnd = 0;
00202         }
00203         else
00204         {
00205             parentHWnd = parentRW->getWindowHandle();
00206         }
00207 
00208         va_end(marker);
00209 
00210         // Destroy current window if any
00211         if (mHWnd)
00212         {
00213             destroy();
00214         }
00215 
00216         // TODO: deal with child windows
00217         mParentHWnd = parentHWnd;
00218 
00219 
00220         // Register the window class
00221         // NB Allow 4 bytes of window data for D3D7RenderWindow pointer
00222         WNDCLASS wndClass = { CS_HREDRAW | CS_VREDRAW, WndProc, 0, 4, hInst,
00223                               LoadIcon( NULL, IDI_APPLICATION ),
00224                               LoadCursor(NULL, IDC_ARROW),
00225                               (HBRUSH)GetStockObject(BLACK_BRUSH), NULL,
00226                               TEXT(name.c_str()) };
00227         RegisterClass( &wndClass );
00228 
00229         // Create our main window
00230         // Pass pointer to self
00231         HWND hWnd = CreateWindow( TEXT(name.c_str()),
00232                                   TEXT(name.c_str()),
00233                                   WS_OVERLAPPEDWINDOW, left, top,
00234                                   width, height, 0L, 0L, hInst, this );
00235         ShowWindow( hWnd, SW_SHOWNORMAL );
00236         UpdateWindow( hWnd );
00237 
00238         mHWnd = hWnd;
00239 
00240         // Store info
00241         mName = name;
00242         mWidth = width;
00243         mHeight = height;
00244         mIsDepthBuffered = depthBuffer;
00245         mIsFullScreen = fullScreen;
00246 
00247         if (fullScreen)
00248         {
00249             mColourDepth = colourDepth;
00250             mLeft = 0;
00251             mTop = 0;
00252         }
00253         else
00254         {
00255             // Get colour depth from display
00256             HDC hdc = GetDC( mHWnd );
00257             mColourDepth = GetDeviceCaps( hdc, BITSPIXEL );
00258             ReleaseDC( mHWnd, hdc );
00259             mTop = top;
00260             mLeft = left;
00261 
00262             // Record the dimensions of the blit location
00263             GetClientRect( mHWnd, &rcBlitDest );
00264             ClientToScreen( mHWnd, (POINT*)&rcBlitDest.left );
00265             ClientToScreen( mHWnd, (POINT*)&rcBlitDest.right );
00266         }
00267 
00268         LogManager::getSingleton().logMessage( 
00269             LML_NORMAL, 
00270             "Created Win32 Rendering Window '%s': %i x %i @ %ibpp", 
00271             mName.c_str(), mWidth, mHeight, mColourDepth );
00272 
00273         // Set up DirectDraw if appropriate
00274         // NB devices & surfaces set up for root window only
00275         if (drv && mParentHWnd == NULL)
00276         {
00277             // DD Driver object passed
00278             mlpDDDriver = drv;
00279             mIsUsingDirectDraw = true;
00280 
00281             createDDSurfaces();
00282             // Get best device based on render bit depth
00283             D3DDevice* dev = mlpDDDriver->get3DDeviceList()->getBest(mColourDepth);
00284 
00285             // create D3D device for this window
00286             mlpD3DDevice = dev->createDevice(mlpDDSBack);
00287             createDepthBuffer();
00288         }
00289         else
00290             mIsUsingDirectDraw = false;
00291 
00292         mReady = true;
00293     }
00294 
00295     void D3D7RenderWindow::destroy(void)
00296     {
00297         if (mIsUsingDirectDraw)
00298             releaseDDSurfaces();
00299 
00300         DestroyWindow(mHWnd);
00301 
00302     }
00303 
00304     bool D3D7RenderWindow::isActive(void) const
00305     {
00306         return mActive;
00307     }
00308 
00309     bool D3D7RenderWindow::isClosed(void) const
00310     {
00311         return mClosed;
00312     }
00313 
00314     void D3D7RenderWindow::reposition(int left, int top)
00315     {
00316 
00317     }
00318 
00319     void D3D7RenderWindow::resize(unsigned int width, unsigned int height)
00320     {
00321         mWidth = width;
00322         mHeight = height;
00323 
00324         // Notify viewports of resize
00325         ViewportList::iterator it = mViewportList.begin();
00326         while (it != mViewportList.end())
00327             (*it).second->_updateDimensions();
00328 
00329         // TODO - resize window
00330 
00331     }
00332 
00333     void D3D7RenderWindow::swapBuffers(bool waitForVSync)
00334     {
00335         HRESULT hr;
00336         DWORD flags;
00337         if (mIsUsingDirectDraw)
00338         {
00339             if (mIsFullScreen)
00340             {
00341                 // Use flipping chain
00342                 if (waitForVSync)
00343                 {
00344                     flags = DDFLIP_WAIT;
00345                 }
00346                 else
00347                 {
00348                     flags = DDFLIP_WAIT | DDFLIP_NOVSYNC;
00349                 }
00350 
00351                 hr = mlpDDSFront->Flip(NULL,flags);
00352             }
00353             else
00354             {
00355                 // Ordinary Blit
00356                 RECT srcRect;
00357                 srcRect.left = 0;
00358                 srcRect.top = 0;
00359                 srcRect.right = rcBlitDest.right - rcBlitDest.left;
00360                 srcRect.bottom = rcBlitDest.bottom - rcBlitDest.top;
00361                 hr = mlpDDSFront->Blt(&rcBlitDest,mlpDDSBack,&srcRect,DDBLT_WAIT,NULL);
00362             }
00363 
00364             if (hr == DDERR_SURFACELOST)
00365             {
00366                 // Restore surfaces
00367                 restoreDDSurfaces();
00368             }
00369             else if (FAILED(hr))
00370             {
00371                  Except( 
00372                      hr,
00373                      "Error flipping surfaces", 
00374                      "D3D7RenderWindow::swapBuffers" );
00375             }
00376         }
00377 
00378     }
00379 
00380     HWND D3D7RenderWindow::getWindowHandle(void) const
00381     {
00382         return mHWnd;
00383     }
00384 
00385     HWND D3D7RenderWindow::getParentWindowHandle(void) const
00386     {
00387         return mParentHWnd;
00388     }
00389 
00390     bool D3D7RenderWindow::isUsingDirectDraw(void) const
00391     {
00392         return mIsUsingDirectDraw;
00393     }
00394 
00395     // -------------------------------------------------------
00396     //   DirectDraw specific methods
00397     // -------------------------------------------------------
00398     DDDriver* D3D7RenderWindow::getDirectDrawDriver(void)
00399     {
00400         return mlpDDDriver;
00401     }
00402 
00403     LPDIRECTDRAWSURFACE7 D3D7RenderWindow::getDDFrontBuffer(void)
00404     {
00405         return mlpDDSFront;
00406 
00407     }
00408 
00409     LPDIRECTDRAWSURFACE7 D3D7RenderWindow::getDDBackBuffer(void)
00410     {
00411         return mlpDDSBack;
00412     }
00413     LPDIRECT3DDEVICE7 D3D7RenderWindow::getD3DDevice(void)
00414     {
00415         return mlpD3DDevice;
00416     }
00417 
00418     void D3D7RenderWindow::createDDSurfaces(void)
00419     {
00420         // Use DirectDraw wrapper object to create surfaces
00421         if( !mlpDDDriver )
00422         {
00423             Except(
00424             Exception::ERR_INVALIDPARAMS, 
00425             "Cannot create surfaces because of no valid DirectDraw object",
00426             "D3D7RenderWindow::createDDSurfaces" );
00427         }
00428 
00429         if( mIsFullScreen )
00430         {
00431             mlpDDDriver->createWindowSurfaces(
00432                 mHWnd, 
00433                 mWidth, mHeight, mColourDepth,
00434                 true, &mlpDDSFront, &mlpDDSBack);
00435         }
00436         else
00437         {
00438             // Windowed mode - need to use client rect for surface dimensions
00439             // I.e. we need to ignore menu bars, borders, title bar etc
00440             RECT rcClient;
00441             unsigned int cWidth, cHeight;
00442 
00443             GetClientRect( mHWnd, &rcClient );
00444             ClientToScreen( mHWnd, (POINT*)&rcClient.left );
00445             ClientToScreen( mHWnd, (POINT*)&rcClient.right );
00446 
00447             cWidth  = rcClient.right - rcClient.left;
00448             cHeight = rcClient.bottom - rcClient.top;
00449 
00450             // Create surfaces (AND clipper)
00451             mlpDDDriver->createWindowSurfaces(
00452                 mHWnd, 
00453                 cWidth, cHeight, 0,
00454                 false, &mlpDDSFront, &mlpDDSBack);
00455 
00456             // Update own dimensions since target width / height is this
00457             mWidth = cWidth;
00458             mHeight = cHeight;
00459         }
00460     }
00461 
00462     void D3D7RenderWindow::createDepthBuffer(void)
00463     {
00464         // Get best device based on render bit depth
00465         D3DDevice* dev = mlpDDDriver->get3DDeviceList()->getBest(mColourDepth);
00466         if (mIsDepthBuffered && dev->NeedsZBuffer())
00467         {
00468             // Create Z buffer
00469             dev->createDepthBuffer(mlpDDSBack);
00470             // Don't set z buffer params here, leave to material
00471         }
00472     }
00473 
00474     void D3D7RenderWindow::releaseDDSurfaces(void)
00475     {
00476         // Release Z-buffer
00477         HRESULT hr;
00478         DDSCAPS2 ddscaps;
00479 
00480         ZeroMemory(&ddscaps, sizeof(DDSCAPS2));
00481         ddscaps.dwCaps = DDSCAPS_ZBUFFER;
00482 
00483         LPDIRECTDRAWSURFACE7 zBufSurface;
00484 
00485         hr = mlpDDSBack->GetAttachedSurface( &ddscaps, &zBufSurface );
00486 
00487         // Release twice as this method has increased
00488         zBufSurface->Release();
00489         zBufSurface->Release();
00490 
00491         // Release std buffers
00492         mlpDDSBack->Release();
00493         mlpDDSFront->Release();
00494 
00495         mlpDDSBack = mlpDDSFront = 0;
00496     }
00497 
00498     void D3D7RenderWindow::restoreDDSurfaces(void)
00499     {
00500         HRESULT hr;
00501 
00502         if( mlpDDSFront->IsLost() )
00503         {
00504             hr = mlpDDSFront->Restore();
00505 
00506             if( FAILED( hr ) )
00507                 Except( 
00508                     Exception::ERR_INTERNAL_ERROR, 
00509                     "Error restoring lost primary surface.", 
00510                     "D3D7RenderWindow - restoreDDSurfaces" );
00511         }
00512 
00513         if( mlpDDSBack->IsLost() )
00514         {
00515             hr = mlpDDSBack->Restore();
00516 
00517             if( FAILED( hr ) )
00518                 Except( 
00519                     Exception::ERR_INTERNAL_ERROR, 
00520                     "Error restoring lost back buffer surface.", 
00521                     "D3D7RenderWindow - restoreDDSurfaces" );
00522         }
00523     }
00524 
00525     void D3D7RenderWindow::windowMovedOrResized(void)
00526     {
00527         // If windowed mode, check window size & position
00528         RECT rcCheck;
00529 
00530         if( mIsFullScreen )
00531             return; // Nothing to check
00532 
00533         GetClientRect( mHWnd, &rcCheck );
00534         ClientToScreen( mHWnd, (POINT*)&rcCheck.left );
00535         ClientToScreen( mHWnd, (POINT*)&rcCheck.right );
00536 
00537         // Has the window resized? If so, we need to recreate surfaces
00538         if( ( rcCheck.right - rcCheck.left != 
00539                 rcBlitDest.right - rcBlitDest.left ) ||
00540             ( rcCheck.bottom - rcCheck.top !=
00541                 rcBlitDest.bottom - rcBlitDest.top ) )
00542         {
00543             // The window has changed size - DD surfaces must be recreated
00544             releaseDDSurfaces();
00545             createDDSurfaces();
00546             createDepthBuffer();
00547 
00548             // Update Viewport Sizes
00549             
00550             for( 
00551                 ViewportList::iterator it = mViewportList.begin();
00552                 it != mViewportList.end(); 
00553                 ++it )
00554             {
00555                 it->second->_updateDimensions();
00556             }
00557 
00558             rcBlitDest = rcCheck;
00559         }
00560         else if( 
00561             rcCheck.left != rcBlitDest.left ||
00562             rcCheck.top  != rcBlitDest.top )
00563         {
00564             // Window has only moved
00565             // Just alter the blit location
00566             rcBlitDest = rcCheck;
00567         }
00568     }
00569 
00570     //-----------------------------------------------------------------------
00571     void D3D7RenderWindow::outputText( int x, int y, const String& text )
00572     {
00573         HDC hDC;
00574 
00575         if( mIsUsingDirectDraw && mlpDDSBack )
00576         {
00577             // Get a DC for the surface. Then, write out the buffer
00578             if( SUCCEEDED( mlpDDSBack->GetDC(&hDC) ) )
00579             {
00580                 SetTextColor( hDC, RGB(255,255,0) );
00581                 SetBkMode( hDC, TRANSPARENT );
00582                 ExtTextOut( hDC, x, y, 0, NULL, text, lstrlen(text), NULL );
00583                 mlpDDSBack->ReleaseDC(hDC);
00584             }
00585         }
00586     }
00587 
00588     //-----------------------------------------------------------------------
00589     void D3D7RenderWindow::getCustomAttribute( const String& name, void* pData )
00590     {
00591         // Valid attributes and their equivalent native functions:
00592         // D3DDEVICE            : getD3DDeviceDriver
00593         // DDBACKBUFFER         : getDDBackBuffer
00594         // DDFRONTBUFFER        : getDDFrontBuffer
00595         // HWND                 : getWindowHandle
00596 
00597         if( name == "D3DDEVICE" )
00598         {
00599             LPDIRECT3DDEVICE7 *pDev = (LPDIRECT3DDEVICE7*)pData;
00600 
00601             *pDev = getD3DDevice();
00602             return;
00603         }
00604         else if( name == "DDBACKBUFFER" )
00605         {
00606             LPDIRECTDRAWSURFACE7 *pSurf = (LPDIRECTDRAWSURFACE7*)pData;
00607 
00608             *pSurf = getDDBackBuffer();
00609             return;
00610         }
00611         else if( name == "DDFRONTBUFFER" )
00612         {
00613             LPDIRECTDRAWSURFACE7 *pSurf = (LPDIRECTDRAWSURFACE7*)pData;
00614 
00615             *pSurf = getDDFrontBuffer();
00616             return;
00617         }
00618         else if( name == "HWND" )
00619         {
00620             HWND *pHwnd = (HWND*)pData;
00621 
00622             *pHwnd = getWindowHandle();
00623             return;
00624         }
00625         else if( name == "isTexture" )
00626         {
00627             bool *b = reinterpret_cast< bool * >( pData );
00628             *b = false;
00629 
00630             return;
00631         }
00632     }
00633 
00634 
00635     void D3D7RenderWindow::writeContentsToFile(const String& filename)
00636     {
00637          HRESULT hr;
00638          LPDIRECTDRAWSURFACE7 pTempSurf;
00639          DDSURFACEDESC2 desc;
00640          RECT srcRect;
00641  
00642          // Cannot lock surface direct, so create temp surface and blit
00643          memset(&desc, 0, sizeof (DDSURFACEDESC2));
00644          desc.dwSize = sizeof(DDSURFACEDESC2);
00645          if (FAILED(hr = mlpDDSBack->GetSurfaceDesc(&desc)))
00646          {
00647              Except(hr, "Error getting description of back buffer!", 
00648                  "D3D7RenderWindow::writeContentsToFile");
00649          }
00650 
00651          desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
00652          desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
00653 
00654          if (FAILED(hr = mlpDDDriver->directDraw()->CreateSurface(&desc, &pTempSurf, NULL)))
00655          {
00656              Except(hr, "Error creating temporary surface!", 
00657                  "D3D7RenderWindow::writeContentsToFile");
00658          }
00659 
00660          if (mIsFullScreen)
00661          {
00662             pTempSurf->Blt(NULL, mlpDDSFront, NULL, NULL, NULL);
00663          }
00664          else
00665          {
00666             GetWindowRect(mHWnd, &srcRect);
00667             srcRect.left += GetSystemMetrics(SM_CXSIZEFRAME);
00668             srcRect.top += GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION);
00669             srcRect.right = srcRect.left + desc.dwWidth;
00670             srcRect.bottom = srcRect.top + desc.dwHeight;
00671 
00672             pTempSurf->Blt(NULL, mlpDDSFront, &srcRect, NULL, NULL);
00673          }
00674 
00675          if (FAILED(hr = pTempSurf->Lock(NULL, &desc,  
00676              DDLOCK_WAIT | DDLOCK_READONLY, NULL)))
00677          {
00678              Except(hr, "Cannot lock surface!", 
00679                  "D3D7RenderWindow::writeContentsToFile");
00680          }
00681  
00682  
00683          ImageCodec::ImageData imgData;
00684          imgData.width = desc.dwWidth;
00685          imgData.height = desc.dwHeight;
00686          imgData.format = PF_R8G8B8;
00687  
00688          // Allocate contiguous buffer (surfaces aren't necessarily contiguous)
00689          uchar* pBuffer = new uchar[desc.dwWidth * desc.dwHeight * 3];
00690  
00691          uint x, y;
00692          uchar *pData, *pDest;
00693  
00694          pData = (uchar*)desc.lpSurface;
00695          pDest = pBuffer;
00696          for (y = 0; y < desc.dwHeight; ++y)
00697          {
00698              uchar *pRow = pData;
00699  
00700              for (x = 0; x < desc.dwWidth; ++x)
00701              {
00702                  if (desc.ddpfPixelFormat.dwRGBBitCount == 16)
00703                  {
00704                      WORD val;
00705  
00706                      val = *((WORD*)pRow);
00707                      pRow += 2;
00708 
00709                      *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0xF800, (BYTE)0xFF);
00710                      *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x07E0, (BYTE)0xFF);
00711                      *pDest++ = Bitwise::convertBitPattern((WORD)val, (WORD)0x001F, (BYTE)0xFF);
00712                  }
00713                  else
00714                  {
00715                      // Actual format is BRGA for some reason
00716                      *pDest++ = pRow[2]; // R
00717                      *pDest++ = pRow[1]; // G
00718                      *pDest++ = pRow[0]; // B
00719 
00720                      pRow += 3; // skip alpha / dummy
00721 
00722                      if (desc.ddpfPixelFormat.dwRGBBitCount == 32)
00723                      {
00724                          ++pRow; // Skip alpha
00725                      }
00726                  }
00727  
00728                  
00729              }
00730              // increase by one line
00731              pData += desc.lPitch;
00732  
00733          }
00734  
00735  
00736          // Wrap buffer in a chunk
00737          DataChunk chunk(pBuffer, desc.dwWidth * desc.dwHeight * 3);
00738  
00739          // Get codec 
00740          size_t pos = filename.find_last_of(".");
00741          String extension;
00742         if( pos == String::npos )
00743              Except(
00744             Exception::ERR_INVALIDPARAMS, 
00745             "Unable to determine image type for '" + filename + "' - invalid extension.",
00746              "D3D8RenderWindow::writeContentsToFile" );
00747  
00748          while( pos != filename.length() - 1 )
00749              extension += filename[++pos];
00750  
00751          // Get the codec
00752          Codec * pCodec = Codec::getCodec(extension);
00753  
00754          // Write out
00755          pCodec->codeToFile(chunk, filename, &imgData);
00756  
00757          delete [] pBuffer;
00758          pTempSurf->Release();
00759  
00760      }
00761 
00762 }
00763 

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