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 Fri May 14 23:22:06 2004