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                 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