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

# OgreDDDriver.cpp

Go to the documentation of this file.

    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 "OgreD3D7RenderSystem.h"
    00026 #include "OgreDDDriver.h"
    00027 #include "OgreDDVideoModeList.h"
    00028 #include "OgreDDVideoMode.h"
    00029 #include "OgreD3D7DeviceList.h"
    00030 #include "OgreD3D7Device.h"
    00031 #include "OgreLogManager.h"
    00032 #include "OgreException.h"
    00033
    00034 namespace Ogre {
    00035     DDDriver DDDriver::operator=(const DDDriver &orig)
    00036     {
    00037
    00038
    00039         mGuid = orig.mGuid;
    00040         //mDriverDesc = new char(strlen(orig.mDriverDesc) + 1);
    00041         //strcpy(mDriverDesc, orig.mDriverDesc);
    00042         mDriverDesc = orig.mDriverDesc;
    00043         //mDriverName = new char(strlen(orig.mDriverName)+1);
    00044         //strcpy(mDriverName, orig.mDriverName);
    00045         mDriverName = orig.mDriverName;
    00046         mPrimaryDisplay = orig.mPrimaryDisplay;
    00047         active3DDevice = orig.active3DDevice;
    00048         activeVideoMode = orig.activeVideoMode;
    00049         lpD3D = orig.lpD3D;
    00050         lpDD7 = orig.lpDD7;
    00051         lpDDClipper = orig.lpDDClipper;
    00052         lpDDSBack = orig.lpDDSBack;
    00053         lpDDSPrimary = orig.lpDDSPrimary;
    00054         mSWCaps = orig.mSWCaps;
    00055         mHWCaps = orig.mHWCaps;
    00056         mDeviceList = orig.mDeviceList;
    00057         mVideoModeList = orig.mVideoModeList;
    00058
    00059
    00060         return *this;
    00061
    00062     }
    00063
    00064     // Default constructor
    00065     DDDriver::DDDriver()
    00066     {
    00067         // Init pointers
    00068         active3DDevice = NULL;
    00069         activeHWnd = 0;
    00070         activeVideoMode = NULL;
    00071         lpD3D = NULL;
    00072         lpDD7 = NULL;
    00073         lpDDClipper = NULL;
    00074         lpDDSBack = NULL;
    00075         lpDDSPrimary = NULL;
    00076         mDeviceList = NULL;
    00077         mVideoModeList = NULL;
    00078
    00079
    00080     }
    00081
    00082     DDDriver::~DDDriver()
    00083     {
    00084         // Delete related system objects
    00085         if (mDeviceList)
    00086             delete mDeviceList;
    00087         if (mVideoModeList)
    00088             delete mVideoModeList;
    00089
    00090     }
    00091
    00092
    00093     // Copy Constructor
    00094     DDDriver::DDDriver(const DDDriver &ob)
    00095     {
    00096
    00097
    00098         mGuid = ob.mGuid;
    00099         //mDriverDesc = new char(strlen(ob.mDriverDesc) + 1);
    00100         //strcpy(mDriverDesc, ob.mDriverDesc);
    00101         mDriverDesc = ob.mDriverDesc;
    00102         //mDriverName = new char(strlen(ob.mDriverName)+1);
    00103         //strcpy(mDriverName, ob.mDriverName);
    00104         mDriverName = ob.mDriverName;
    00105         mPrimaryDisplay = ob.mPrimaryDisplay;
    00106         active3DDevice = ob.active3DDevice;
    00107         activeVideoMode = ob.activeVideoMode;
    00108         lpD3D = ob.lpD3D;
    00109         lpDD7 = ob.lpDD7;
    00110         lpDDClipper = ob.lpDDClipper;
    00111         lpDDSBack = ob.lpDDSBack;
    00112         lpDDSPrimary = ob.lpDDSPrimary;
    00113         mSWCaps = ob.mSWCaps;
    00114         mHWCaps = ob.mHWCaps;
    00115         mDeviceList = ob.mDeviceList;
    00116         mVideoModeList = ob.mVideoModeList;
    00117
    00118     }
    00119
    00120     // Constructor with enumeration details
    00121     DDDriver::DDDriver(GUID FAR *lpGuid,
    00122                                 LPSTR lpDriverDescription,
    00123                                 LPSTR lpDriverName)
    00124     {
    00125         HRESULT hr;
    00126
    00127         // Init pointers
    00128         active3DDevice = NULL;
    00129         activeHWnd = 0;
    00130         activeVideoMode = NULL;
    00131         lpD3D = NULL;
    00132         lpDD7 = NULL;
    00133         lpDDClipper = NULL;
    00134         lpDDSBack = NULL;
    00135         lpDDSPrimary = NULL;
    00136         mDeviceList = NULL;
    00137         mVideoModeList = NULL;
    00138
    00139         // Copy GUID, Description and Name
    00140         // Deal with NULL (default display driver)
    00141         if (lpGuid)
    00142         {
    00143             memcpy(&mGuid, lpGuid, sizeof(GUID));
    00144             mPrimaryDisplay = false;
    00145         }
    00146         else
    00147             mPrimaryDisplay = true;
    00148
    00149
    00150         mDriverDesc = String(lpDriverDescription);
    00151         //mDriverDesc = new char(strlen(lpDriverDescription)+1);
    00152         //strcpy(mDriverDesc, lpDriverDescription);
    00153
    00154         mDriverName = String(lpDriverName);
    00155         //mDriverName = new char(strlen(lpDriverName)+1);
    00156         //strcpy(mDriverName, lpDriverName);
    00157
    00158
    00159         // Get capabilities
    00160         mHWCaps.dwSize = sizeof(DDCAPS);
    00161         mSWCaps.dwSize = sizeof(DDCAPS);
    00162
    00163         hr = directDraw()->GetCaps(&mHWCaps, &mSWCaps);
    00164         if (FAILED(hr))
    00165             throw Exception(hr, "Cannot get direct draw driver capabilities.",
    00166                 "DIM_DDDriver - directDraw()");
    00167
    00168
    00169     }
    00170
    00171     void DDDriver::createWindowSurfaces(HWND hWnd, unsigned int width, unsigned int height, unsigned int colourDepth, bool fullScreen,
    00172             LPDIRECTDRAWSURFACE7 *front, LPDIRECTDRAWSURFACE7 *back)
    00173     {
    00174
    00175         char msg[150];
    00176         DWORD dwFlags;
    00177         DDSURFACEDESC2 ddsd;
    00178         HRESULT hr;
    00179         DDSCAPS2 ddscaps;
    00180         LPDIRECTDRAWCLIPPER clip;
    00181
    00182         LogManager::getSingleton().logMessage("Creating DirectDraw surfaces for window with dimensions:");
    00183
    00184         if (fullScreen)
    00185             sprintf(msg, "  FULLSCREEN w:%i h:%i bpp:%i", width, height, colourDepth);
    00186         else
    00187             sprintf(msg, "  WINDOWED w:%i h:%i", width, height);
    00188
    00189         LogManager::getSingleton().logMessage(msg);
    00190
    00191         // Set co-op level
    00192         if (fullScreen)
    00193         {
    00194             dwFlags = DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE;
    00195         }
    00196         else
    00197         {
    00198             dwFlags = DDSCL_NORMAL;
    00199         }
    00200
    00201         // Also set FPU cooperative mode (optimisation)
    00202         dwFlags = dwFlags | DDSCL_FPUSETUP;
    00203
    00204         hr = directDraw()->SetCooperativeLevel(hWnd, dwFlags);
    00205         if (FAILED(hr))
    00206             throw Exception(hr, "Error setting cooperative mode",
    00207                 "DDDriver - createWindowSurfaces");
    00208
    00209
    00210         // Create surfaces
    00211         // If we're running fullscreen, create a complex flipping
    00212         // chain surface (implicit back buffer)
    00213         // Otherwise we need separate back buffers
    00214
    00215         if (fullScreen)
    00216         {
    00217             // Set Video Mode
    00218             hr = lpDD7->SetDisplayMode(width, height, colourDepth, 0, 0);
    00219             if (FAILED(hr))
    00220                 throw Exception(hr, "Unable to set fullScreen display mode.", "DDDriver - createWindowSurfaces");
    00221
    00222             // Set up surfaces
    00223             ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) );
    00224             ddsd.dwSize = sizeof(DDSURFACEDESC2);
    00225             ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
    00226             ddsd.ddsCaps.dwCaps = DDSCAPS_COMPLEX |
    00227                 DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
    00228
    00229             // Create a single back buffer
    00230             ddsd.dwBackBufferCount = 1;
    00231             hr = directDraw()->CreateSurface(&ddsd,front,NULL);
    00232             if (FAILED(hr))
    00233                 throw Exception(hr, "Error creating linked surface buffers",
    00234                     "DDDriver - createWindowSurfaces");
    00235
    00236             // Get back buffer
    00237             ZeroMemory(&ddscaps, sizeof(DDSCAPS2));
    00238             ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
    00239             hr = (*front)->GetAttachedSurface(&ddscaps, back);
    00240
    00241             if (FAILED(hr))
    00242                 throw Exception(hr, "Error retrieving linked back buffer",
    00243                     "DDDriver - createWindowSurfaces");
    00244
    00245             LogManager::getSingleton().logMessage("Successfully created full screen rendering surface / flipping chain.");
    00246         }
    00247         else
    00248         {
    00249             // Explicitly create front and back buffers, and create
    00250             // a clipper object
    00251
    00252             // Standard non-auto-flip primary
    00253             ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) );
    00254             ddsd.dwSize  = sizeof(DDSURFACEDESC2);
    00255             ddsd.dwFlags = DDSD_CAPS;
    00256             ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
    00257             hr = directDraw()->CreateSurface(&ddsd,front,NULL);
    00258             if (FAILED(hr))
    00259                 throw Exception(hr, "Error creating primary surface buffer",
    00260                     "DDDriver - createWindowSurfaces");
    00261
    00262
    00263             // Create offscreen buffer
    00264             ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
    00265             ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |
    00266                 DDSCAPS_3DDEVICE;
    00267             // Set the dimensions of the back buffer. Note that if our window changes
    00268             // size, we need to destroy this surface and create a new one.
    00269             ddsd.dwWidth  = width;
    00270             ddsd.dwHeight = height;
    00271             // Create the back buffer. The most likely reason for failure is running
    00272             // out of video memory. (A more sophisticated app should handle this.)
    00273             hr = directDraw()->CreateSurface( &ddsd, back, NULL );
    00274             if( FAILED( hr ) )
    00275                 throw Exception(hr, "Error creating back surface buffer",
    00276                     "DDDriver - createWindowSurfaces");
    00277
    00278             LogManager::getSingleton().logMessage("Windowed mode rendering & display surfaces created.");
    00279
    00280             // Create clipper
    00281             hr = directDraw()->CreateClipper(0, &clip, NULL);
    00282             if (FAILED(hr))
    00283                 throw Exception(hr, "Error creating clipper",
    00284                     "DDDriver - createWindowSurfaces");
    00285
    00286             // Assign it to the window
    00287             clip->SetHWnd(0,hWnd);
    00288             // Assign it to primary surface
    00289             (*front)->SetClipper(clip);
    00290             clip->Release();
    00291
    00292             LogManager::getSingleton().logMessage("Window clipper created.");
    00293
    00294         }
    00295
    00296
    00297
    00298     }
    00299
    00300
    00301     String DDDriver::DriverName(void) const
    00302     {
    00303         return mDriverName;
    00304     }
    00305
    00306     String DDDriver::DriverDescription(void) const
    00307     {
    00308         return mDriverDesc;
    00309     }
    00310
    00311     D3DDeviceList* DDDriver::get3DDeviceList(void)
    00312     {
    00313         if (!mDeviceList)
    00314             mDeviceList = new D3DDeviceList(lpD3D);
    00315
    00316         return mDeviceList;
    00317     }
    00318
    00319     DDVideoModeList* DDDriver::getVideoModeList(void)
    00320     {
    00321         if (!mVideoModeList)
    00322             mVideoModeList = new DDVideoModeList(lpDD7);
    00323
    00324         return mVideoModeList;
    00325     }
    00326
    00327     DDVideoMode* DDDriver::getActiveVideoMode(void)
    00328     {
    00329         return activeVideoMode;
    00330     }
    00331
    00332
    00333     D3DDevice* DDDriver::get3DDevice(void)
    00334     {
    00335         return active3DDevice;
    00336     }
    00337
    00338
    00339     LPDIRECTDRAW7 DDDriver::directDraw()
    00340     {
    00341         HRESULT rVal;
    00342
    00343         if (!lpDD7)
    00344         {
    00345             // We need to create a direct draw object
    00346             // Create with GUID for this driver
    00347             if (mPrimaryDisplay)
    00348                 rVal = DirectDrawCreateEx( NULL, (VOID**)&lpDD7, IID_IDirectDraw7, NULL );
    00349             else
    00350                 rVal = DirectDrawCreateEx( &mGuid, (VOID**)&lpDD7, IID_IDirectDraw7, NULL );
    00351             if (rVal != DD_OK)
    00352                 throw Exception(rVal, "Cannot create direct draw interface.",
    00353                     "DIM_DDDriver - directDraw()");
    00354
    00355             // Get Direct3D interface too
    00356             lpDD7->QueryInterface(IID_IDirect3D7, (VOID**)&lpD3D);
    00357
    00358
    00359         }
    00360
    00361         return lpDD7;
    00362     }
    00363
    00364     void DDDriver::Cleanup(void)
    00365     {
    00366         // Tell 3D Device to clean itself up
    00367         if (active3DDevice)
    00368         {
    00369             active3DDevice->Cleanup();
    00370         }
    00371
    00372         if (activeHWnd && lpDD7)
    00373             lpDD7->SetCooperativeLevel(activeHWnd, DDSCL_NORMAL);
    00374
    00375         // Release DirectX system objects
    00376
    00377         if (lpDDSBack)
    00378         {
    00379             lpDDSBack->Release();
    00380             lpDDSBack = NULL;
    00381         }
    00382
    00383         if (lpDDSPrimary)
    00384         {
    00385             lpDDSPrimary->Release();
    00386             lpDDSPrimary = NULL;
    00387         }
    00388
    00389         if (lpD3D)
    00390         {
    00391             lpD3D->Release();
    00392             lpD3D = NULL;
    00393         }
    00394
    00395         if (lpDD7)
    00396         {
    00397             lpDD7->Release();
    00398             lpDD7 = NULL;
    00399         }
    00400
    00401
    00402
    00403
    00404     }
    00405
    00406
    00407     void DDDriver::CheckWindow(void)
    00408     {
    00409         // If windowed mode, check window size & position
    00410         RECT rcCheck;
    00411
    00412         if (RunningFullScreen())
    00413             return;
    00414
    00415         GetClientRect( activeHWnd, &rcCheck );
    00416         ClientToScreen( activeHWnd, (POINT*)&rcCheck.left );
    00417         ClientToScreen( activeHWnd, (POINT*)&rcCheck.right );
    00418
    00419         // Has the window resized? If so, we need to recreate surfaces
    00420         if ((rcCheck.right - rcCheck.left !=
    00421                 rcViewport.right - rcViewport.left) ||
    00422             (rcCheck.bottom - rcCheck.top !=
    00423                 rcViewport.bottom - rcViewport.top))
    00424         {
    00425             // The window has changed size
    00426             //g_DIMSystem->CleanupRenderer();
    00427             //g_DIMSystem->Reinitialise();
    00428         }
    00429         else if (rcCheck.left != rcViewport.left ||
    00430             rcCheck.top != rcViewport.top)
    00431         {
    00432             // Window has only moved
    00433             // Just alter the blit location
    00434             rcViewport = rcCheck;
    00435         }
    00436
    00437
    00438     }
    00439
    00440
    00441     void DDDriver::FlipBuffers(void)
    00442     {
    00443         HRESULT hr;
    00444         if (runningFullScreen)
    00445         {
    00446             // Use flipping chain
    00447             hr = lpDDSPrimary->Flip(NULL,DDFLIP_WAIT);
    00448
    00449
    00450         }
    00451         else
    00452         {
    00453             // Ordinary Blit
    00454             RECT srcRect;
    00455             srcRect.left = 0;
    00456             srcRect.top = 0;
    00457             srcRect.right = rcViewport.right - rcViewport.left;
    00458             srcRect.bottom = rcViewport.bottom - rcViewport.top;
    00459             hr = lpDDSPrimary->Blt(&rcViewport,lpDDSBack,&srcRect,DDBLT_WAIT,NULL);
    00460         }
    00461
    00462         if (hr == DDERR_SURFACELOST)
    00463         {
    00464             // Restore surfaces
    00465             RestoreSurfaces();
    00466         }
    00467         else
    00468         {
    00469             if (FAILED(hr))
    00470              throw Exception(hr,"Error flipping surfaces", "DDDriver::FlipBuffers");
    00471         }
    00472
    00473     }
    00474
    00475     void DDDriver::RestoreSurfaces(void)
    00476     {
    00477         HRESULT hr;
    00478
    00479         if (lpDDSPrimary->IsLost())
    00480         {
    00481             hr = lpDDSPrimary->Restore();
    00482             if (FAILED(hr))
    00483                 throw Exception(hr, "Error restoring lost primary surface.", "DDDriver - RestoreSurfaces");
    00484         }
    00485
    00486         if (lpDDSBack->IsLost())
    00487         {
    00488             hr = lpDDSBack->Restore();
    00489             if (FAILED(hr))
    00490                 throw Exception(hr, "Error restoring lost back buffer surface.", "DDDriver - RestoreSurfaces");
    00491         }
    00492
    00493     }
    00494
    00495     void DDDriver::OutputText(int x, int y, char* text)
    00496     {
    00497         HDC hDC;
    00498
    00499         // Get a DC for the surface. Then, write out the buffer
    00500         if( lpDDSBack )
    00501         {
    00502             if( SUCCEEDED( lpDDSBack->GetDC(&hDC) ) )
    00503             {
    00504                 SetTextColor( hDC, RGB(255,255,0) );
    00505                 SetBkMode( hDC, TRANSPARENT );
    00506                 ExtTextOut( hDC, x, y, 0, NULL, text, lstrlen(text), NULL );
    00507                 lpDDSBack->ReleaseDC(hDC);
    00508             }
    00509         }
    00510     }
    00511
    00512     bool DDDriver::RunningFullScreen(void) const
    00513     {
    00514         return runningFullScreen;
    00515     }
    00516
    00517     RECT DDDriver::ViewportRect(void) const
    00518     {
    00519         return rcViewport;
    00520     }
    00521
    00522     bool DDDriver::CanRenderWindowed(void) const
    00523     {
    00524         return (mHWCaps.dwCaps2 & DDCAPS2_CANRENDERWINDOWED) > 0;
    00525     }
    00526
    00527
    00528     bool DDDriver::Has3DAcceleration(void) const
    00529     {
    00530         return (mHWCaps.dwCaps & DDCAPS_3D);
    00531     }
    00532
    00533
    00534
    00535     void DDDriver::GetDisplayDetails(unsigned int& width, unsigned int& height, unsigned int& colourDepth)
    00536     {
    00537         // Get details from primary surface
    00538         // This works for both windowed and fullscreen modes
    00539
    00540         DDSURFACEDESC2 ddsd;
    00541
    00542
    00543         if (lpDDSPrimary)
    00544         {
    00545             ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
    00546             ddsd.dwSize = sizeof(DDSURFACEDESC2);
    00547             lpDDSPrimary->GetSurfaceDesc(&ddsd);
    00548
    00549             width = ddsd.dwWidth;
    00550             height = ddsd.dwHeight;
    00551             colourDepth = ddsd.ddpfPixelFormat.dwRGBBitCount;
    00552         }
    00553     }
    00554
    00555     void DDDriver::logCaps(void) const
    00556     {
    00557         // Sends capabilities of this driver to the log
    00558         char msg[255];
    00559
    00560         LogManager::getSingleton().logMessage("DirectDraw Driver Capabilities:");
    00561
    00562         sprintf(msg, "  3D Acceleration: %i", Has3DAcceleration());
    00563         LogManager::getSingleton().logMessage(msg);
    00564
    00565         sprintf(msg, "  Render in a window: %i", CanRenderWindowed());
    00566         LogManager::getSingleton().logMessage(msg);
    00567
    00568
    00569
    00570     }
    00571
    00572 }
    00573
    00574

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:22 2004