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