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 "OgreD3D7Device.h" 00027 #include "OgreDDDriver.h" 00028 #include "OgreDDVideoMode.h" 00029 #include "OgreLight.h" 00030 #include "OgreCamera.h" 00031 #include "OgreLogManager.h" 00032 #include "OgreException.h" 00033 00034 namespace Ogre { 00035 00036 static HRESULT CALLBACK EnumZBuffersCallback(DDPIXELFORMAT* pddpf, 00037 VOID* pFormats) 00038 { 00039 // Add to list of formats 00040 std::vector<DDPIXELFORMAT> *vec; 00041 vec = (std::vector<DDPIXELFORMAT>*)pFormats; 00042 00043 if (pddpf->dwFlags & DDPF_ZBUFFER) 00044 vec->push_back(*pddpf); 00045 return D3DENUMRET_OK; 00046 00047 } 00048 00049 00050 00051 00052 D3DDevice D3DDevice::operator=(const D3DDevice &orig) 00053 { 00054 00055 00056 mDeviceName = orig.mDeviceName; 00057 mDeviceDescription = orig.mDeviceDescription; 00058 mD3DDeviceDesc = orig.mD3DDeviceDesc; 00059 mIsHardwareAccelerated = orig.mIsHardwareAccelerated; 00060 mNeedsZBuffer = orig.mNeedsZBuffer; 00061 00062 00063 return *this; 00064 00065 } 00066 00067 // Default constructor 00068 D3DDevice::D3DDevice() 00069 { 00070 // Init pointers 00071 lpD3D = NULL; 00072 00073 } 00074 00075 // Copy Constructor 00076 D3DDevice::D3DDevice(const D3DDevice &ob) 00077 { 00078 lpD3D = ob.lpD3D; 00079 mViewport = ob.mViewport; 00080 mDeviceDescription = ob.mDeviceDescription; 00081 mDeviceName = ob.mDeviceName; 00082 mD3DDeviceDesc = ob.mD3DDeviceDesc; 00083 mIsHardwareAccelerated = ob.mIsHardwareAccelerated; 00084 mNeedsZBuffer = ob.mNeedsZBuffer; 00085 00086 } 00087 00088 // Enum constructor 00089 D3DDevice::D3DDevice(LPDIRECT3D7 lpDirect3D, LPSTR lpDeviceDesc, LPSTR lpDeviceName, 00090 LPD3DDEVICEDESC7 lpD3DDeviceDesc) 00091 { 00092 // Init pointers 00093 lpD3D = NULL; 00094 00095 // Copy pointer to Direct3D7 interface 00096 lpD3D = lpDirect3D; 00097 00098 // Copy Name and Description 00099 mDeviceDescription = lpDeviceDesc; 00100 mDeviceName = lpDeviceName; 00101 00102 // Is this a hardware or emulation device? 00103 mIsHardwareAccelerated = ( 0 != (lpD3DDeviceDesc->dwDevCaps & D3DDEVCAPS_HWRASTERIZATION) ); 00104 00105 00106 // Copy device description 00107 // No need to differentiate between SW and HW anymore 00108 memcpy(&mD3DDeviceDesc, lpD3DDeviceDesc, sizeof(D3DDEVICEDESC7)); 00109 00110 char msg[255]; 00111 sprintf(msg, "Detected Direct3D Device %s.", lpDeviceDesc); 00112 LogManager::getSingleton().logMessage(msg); 00113 logCaps(); 00114 00115 // Do we need a Z Buffer? 00116 mNeedsZBuffer = !(mD3DDeviceDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR); 00117 if (mNeedsZBuffer) 00118 sprintf(msg, "This device needs a Z-Buffer"); 00119 else 00120 sprintf(msg, "This device does not need a Z-Buffer"); 00121 00122 LogManager::getSingleton().logMessage(msg); 00123 00124 00125 00126 00127 00128 } 00129 00130 D3DDevice::~D3DDevice() 00131 { 00132 } 00133 00134 LPDIRECT3DDEVICE7 D3DDevice::createDevice(LPDIRECTDRAWSURFACE7 renderTarget) 00135 { 00136 LPDIRECT3DDEVICE7 dev; 00137 HRESULT hr; 00138 00139 hr = lpD3D->CreateDevice(mD3DDeviceDesc.deviceGUID, renderTarget, &dev); 00140 if(FAILED(hr)) 00141 throw Exception(hr, "Error creating new D3D device.", 00142 "D3DDevice::createDevice"); 00143 00144 return dev; 00145 00146 } 00147 00148 LPDIRECT3D7 D3DDevice::getID3D(void) 00149 { 00150 return lpD3D; 00151 } 00152 00153 00154 bool D3DDevice::HardwareAccelerated(void) const 00155 { 00156 return mIsHardwareAccelerated; 00157 } 00158 00159 void D3DDevice::logCaps(void) const 00160 { 00161 // Sends capabilities of this driver to the log 00162 char msg[255]; 00163 00164 LogManager::getSingleton().logMessage("Direct3D Device Capabilities:"); 00165 00166 sprintf(msg, " Hardware Accelerated: %i", HardwareAccelerated()); 00167 LogManager::getSingleton().logMessage(msg); 00168 00169 sprintf(msg, " Mipmapping: %i", CanMipMap()); 00170 LogManager::getSingleton().logMessage(msg); 00171 00172 sprintf(msg, " Bilinear Filtering: %i", CanBilinearFilter()); 00173 LogManager::getSingleton().logMessage(msg); 00174 00175 sprintf(msg, " Trilinear Filtering: %i", CanTrilinearFilter()); 00176 LogManager::getSingleton().logMessage(msg); 00177 00178 sprintf(msg, " Hardware Transform & Light: %i", CanHWTransformAndLight()); 00179 LogManager::getSingleton().logMessage(msg); 00180 00181 sprintf(msg, " Max rendering colour depth: %i", RenderBitDepth()); 00182 LogManager::getSingleton().logMessage(msg); 00183 00184 sprintf(msg, " Max single-pass texture layers: %i", MaxSinglePassTextureLayers()); 00185 LogManager::getSingleton().logMessage(msg); 00186 00187 sprintf(msg, " Pixel fog supported: %i", ( mD3DDeviceDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE ) ); 00188 LogManager::getSingleton().logMessage(msg); 00189 00190 sprintf(msg, " Vertex fog supported: %i", ( mD3DDeviceDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGVERTEX) ); 00191 LogManager::getSingleton().logMessage(msg); 00192 00193 00194 00195 } 00196 00197 00198 void D3DDevice::Cleanup(void) 00199 { 00200 // Release DirectX Objects 00201 00202 lpD3D = NULL; 00203 } 00204 00205 00206 void D3DDevice::createViewport(void) 00207 { 00208 /* 00209 HRESULT hr; 00210 char msg[255]; 00211 sprintf(msg, "Creating Direct3D Viewport For %s.", mDeviceDescription.c_str()); 00212 LogManager::getSingleton().logMessage(msg); 00213 00214 // Create the viewport (D3D interface) 00215 // No need to create from device anymore 00216 00217 // Set size (based on render target surface) 00218 setViewportSize(); 00219 00220 // Set current viewport for device 00221 hr = lpD3DDevice->SetViewport(&mViewport); 00222 if FAILED(hr) 00223 throw Exception(hr, "Error setting current viewport for device", "D3DDevice - setActive"); 00224 00225 LogManager::getSingleton().logMessage("Viewport Created OK"); 00226 00227 // Set up initial camera position 00228 //mCamera = new CCamera(this); 00229 //mCamera->setLocation(0.0f,0.0f,-10.0f); 00230 //mCamera->setTarget(0.0f,0.0f,0.0f); 00231 00232 */ 00233 } 00234 00235 void D3DDevice::setViewportSize(void) 00236 { 00237 00238 /* 00239 DDSURFACEDESC2 renderDesc; 00240 HRESULT hr; 00241 // Get surface desc of render target 00242 renderDesc.dwSize = sizeof(DDSURFACEDESC2); 00243 hr = lpRenderTarget->GetSurfaceDesc(&renderDesc); 00244 00245 00246 if FAILED(hr) 00247 throw Exception(hr, "Error getting render target surface description", "D3DDevice - setActive"); 00248 00249 // Set viewport to match the surface 00250 mViewport.dwX = 0; 00251 mViewport.dwY = 0; 00252 mViewport.dwWidth = renderDesc.dwWidth; 00253 mViewport.dwHeight = renderDesc.dwHeight; 00254 mViewport.dvMinZ = 0.0f; 00255 mViewport.dvMaxZ = 1.0f; 00256 00257 00258 00259 // Set the parameters for the new viewport. 00260 00261 // Store viewport sizes 00262 rcViewportRect.x1 = 0; 00263 rcViewportRect.x2 = renderDesc.dwWidth; 00264 rcViewportRect.y1 = 0; 00265 rcViewportRect.y2 = renderDesc.dwHeight; 00266 */ 00267 } 00268 00269 void D3DDevice::setViewMatrix(D3DMATRIX *mat) 00270 { 00271 /* 00272 HRESULT hr; 00273 00274 hr = lpD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, mat); 00275 00276 if (FAILED(hr)) 00277 throw Exception(hr, "Error setting view matrix.", 00278 "D3DDevice - setViewMatrix"); 00279 */ 00280 } 00281 00282 void D3DDevice::setProjectionMatrix(D3DMATRIX *mat) 00283 { 00284 /* 00285 HRESULT hr; 00286 hr = lpD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, mat); 00287 00288 if (FAILED(hr)) 00289 throw Exception(hr, "Error setting projection matrix.", 00290 "D3DDevice - setProjectionMatrix"); 00291 */ 00292 } 00293 00294 void D3DDevice::setWorldMatrix(D3DMATRIX *mat) 00295 { 00296 /* 00297 HRESULT hr; 00298 hr = lpD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, mat); 00299 00300 if (FAILED(hr)) 00301 throw Exception(hr, "Error setting world matrix.", 00302 "D3DDevice - setWorldMatrix"); 00303 */ 00304 } 00305 00306 void D3DDevice::beginScene(void) 00307 { 00308 /* 00309 HRESULT hr; 00310 00311 // Clear viewport 00312 hr = lpD3DDevice->Clear(0, NULL, 00313 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x0, 1L, 0L); 00314 if (FAILED(hr)) 00315 throw Exception(hr, "Can't clear viewport.", 00316 "D3DDevice - beginScene"); 00317 00318 // BEGIN 00319 00320 hr = lpD3DDevice->BeginScene(); 00321 if (FAILED(hr)) 00322 throw Exception(hr, "Can't begin scene.", 00323 "D3DDevice - beginScene"); 00324 */ 00325 } 00326 00327 void D3DDevice::endScene(void) 00328 { 00329 //lpD3DDevice->EndScene(); 00330 } 00331 00332 00333 void D3DDevice::setAmbientLight(float r, float g, float b) 00334 { 00335 00336 // Just set white for now 00337 //HRESULT hr; 00338 //hr = lpD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff ); 00339 } 00340 00341 00342 00343 00344 String D3DDevice::DeviceName(void) const 00345 { 00346 return mDeviceName; 00347 } 00348 00349 String D3DDevice::DeviceDescription(void) const 00350 { 00351 return mDeviceDescription; 00352 } 00353 00354 00355 void D3DDevice::createDepthBuffer(LPDIRECTDRAWSURFACE7 renderTarget) 00356 { 00357 DWORD bestDepth, bestStencil; 00358 DDSURFACEDESC2 ddsd, src_ddsd; 00359 LPDIRECTDRAW7 lpDD7; 00360 LPDIRECTDRAWSURFACE7 lpZBuffer; 00361 HRESULT hr; 00362 00363 LogManager::getSingleton().logMessage("Direct3D - Creating Z-Buffer"); 00364 00365 // First check we NEED a depth buffer - e.g. PowerVR doesn't need one 00366 if (mNeedsZBuffer) 00367 { 00368 // Get description from source surface 00369 ZeroMemory(&src_ddsd, sizeof(DDSURFACEDESC2)); 00370 src_ddsd.dwSize = sizeof(DDSURFACEDESC2); 00371 renderTarget->GetSurfaceDesc(&src_ddsd); 00372 00373 // Enumerate Depth Buffers 00374 mDepthBufferFormats.clear(); 00375 lpD3D->EnumZBufferFormats( 00376 mD3DDeviceDesc.deviceGUID, 00377 EnumZBuffersCallback, 00378 (LPVOID)&mDepthBufferFormats ); 00379 00380 // Choose the best one 00381 // NB make sure Z buffer is the same depth as colour buffer (GeForce TnL problem) 00382 // Also use best stencil if z depth is the same 00383 bestDepth = 0; 00384 bestStencil = 0; 00385 00386 std::vector<DDPIXELFORMAT>::iterator it, best_it; 00387 for( 00388 it = mDepthBufferFormats.begin(); 00389 it != mDepthBufferFormats.end(); 00390 ++it ) 00391 { 00392 if( ( (*it).dwZBufferBitDepth > bestDepth || (*it).dwStencilBitDepth > bestStencil) 00393 && 00394 (*it).dwZBufferBitDepth <= src_ddsd.ddpfPixelFormat.dwZBufferBitDepth ) 00395 { 00396 best_it = it; 00397 bestDepth = (*it).dwZBufferBitDepth; 00398 bestStencil = (*it).dwStencilBitDepth; 00399 } 00400 } 00401 00402 // Setup the surface desc for the z-buffer. 00403 ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2)); 00404 00405 ddsd.dwSize = sizeof(DDSURFACEDESC2); 00406 ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT; 00407 00408 ddsd.dwWidth = src_ddsd.dwWidth; 00409 ddsd.dwHeight = src_ddsd.dwHeight; 00410 00411 ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER; 00412 00413 memcpy( &ddsd.ddpfPixelFormat, &(*best_it), sizeof(DDPIXELFORMAT) ); 00414 00415 // Software devices require system-memory depth buffers. 00416 if( mIsHardwareAccelerated ) 00417 ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; 00418 else 00419 ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; 00420 00421 // Create the depth-buffer. 00422 renderTarget->GetDDInterface( (VOID**)&lpDD7 ); 00423 lpDD7->Release(); 00424 00425 if( FAILED( hr = lpDD7->CreateSurface( &ddsd, &lpZBuffer, NULL ) ) ) 00426 Except( 00427 hr, 00428 "Error creating depth buffer", 00429 "D3DDevice::createDepthBuffer" ); 00430 00431 if( FAILED( hr = renderTarget->AddAttachedSurface(lpZBuffer) ) ) 00432 Except( 00433 hr, 00434 "Error attaching depth buffer to render target", 00435 "D3DDevice::createDepthBuffer" ); 00436 00437 // Log stencil buffer depth 00438 mStencilBufferDepth = ddsd.ddpfPixelFormat.dwStencilBitDepth; 00439 00440 LogManager::getSingleton().logMessage( 00441 LML_NORMAL, 00442 "Depth-Buffer created (%i-bit, %i-bit stencil)", 00443 ddsd.ddpfPixelFormat.dwZBufferBitDepth, 00444 mStencilBufferDepth); 00445 if (mStencilBufferDepth == 0) 00446 { 00447 LogManager::getSingleton().logMessage("Warning: software stencilling " 00448 "in use, stencil operations will not be hardware accelerated."); 00449 } 00450 } 00451 } 00452 00453 bool D3DDevice::CanMipMap(void) const 00454 { 00455 return (mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MIPNEAREST) > 0; 00456 } 00457 00458 bool D3DDevice::CanBilinearFilter(void) const 00459 { 00460 return (mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR) > 0; 00461 } 00462 00463 bool D3DDevice::CanTrilinearFilter(void) const 00464 { 00465 return (mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEARMIPLINEAR) > 0; 00466 } 00467 00468 unsigned int D3DDevice::RenderBitDepth(void) const 00469 { 00470 00471 if (mD3DDeviceDesc.dwDeviceRenderBitDepth & DDBD_32) 00472 return 32; 00473 else if (mD3DDeviceDesc.dwDeviceRenderBitDepth & DDBD_24) 00474 return 24; 00475 else if (mD3DDeviceDesc.dwDeviceRenderBitDepth & DDBD_16) 00476 return 16; 00477 else if (mD3DDeviceDesc.dwDeviceRenderBitDepth & DDBD_8) 00478 return 8; 00479 else 00480 return 0; 00481 } 00482 00483 unsigned int D3DDevice::ZBufferBitDepth(void) const 00484 { 00485 switch(mD3DDeviceDesc.dwDeviceZBufferBitDepth) 00486 { 00487 case DDBD_8: 00488 return 8; 00489 case DDBD_16: 00490 return 16; 00491 case DDBD_24: 00492 return 24; 00493 case DDBD_32: 00494 return 32; 00495 } 00496 00497 return 0; 00498 00499 } 00500 bool D3DDevice::NeedsZBuffer(void) const 00501 { 00502 return mNeedsZBuffer; 00503 } 00504 00505 bool D3DDevice::CanHWTransformAndLight(void) const 00506 { 00507 return (mD3DDeviceDesc.dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) > 0; 00508 } 00509 00510 unsigned int D3DDevice::MaxSinglePassTextureLayers(void) const 00511 { 00512 // The maximum number of texture layers the device can support in a singe pass 00513 00514 return mD3DDeviceDesc.wMaxSimultaneousTextures; 00515 } 00516 00517 ushort D3DDevice::StencilBufferBitDepth(void) const 00518 { 00519 return mStencilBufferDepth; 00520 } 00521 00522 00523 } // Namespace
Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:18 2004