[690] | 1 | /*
|
---|
| 2 | -----------------------------------------------------------------------------
|
---|
| 3 | This source file is part of OGRE
|
---|
| 4 | (Object-oriented Graphics Rendering Engine)
|
---|
| 5 | For the latest info, see http://www.ogre3d.org/
|
---|
| 6 |
|
---|
| 7 | Copyright (c) 2000-2005 The OGRE Team
|
---|
| 8 | Also see acknowledgements in Readme.html
|
---|
| 9 |
|
---|
| 10 | This program is free software; you can redistribute it and/or modify it under
|
---|
| 11 | the terms of the GNU Lesser General Public License as published by the Free Software
|
---|
| 12 | Foundation; either version 2 of the License, or (at your option) any later
|
---|
| 13 | version.
|
---|
| 14 |
|
---|
| 15 | This program is distributed in the hope that it will be useful, but WITHOUT
|
---|
| 16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
---|
| 17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
---|
| 18 |
|
---|
| 19 | You should have received a copy of the GNU Lesser General Public License along with
|
---|
| 20 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
---|
| 21 | Place - Suite 330, Boston, MA 02111-1307, USA, or go to
|
---|
| 22 | http://www.gnu.org/copyleft/lesser.txt.
|
---|
| 23 | -----------------------------------------------------------------------------
|
---|
| 24 | */
|
---|
| 25 | #include "OgreD3D7RenderSystem.h"
|
---|
| 26 | #include "OgreD3D7Device.h"
|
---|
| 27 | #include "OgreDDDriver.h"
|
---|
| 28 | #include "OgreDDVideoMode.h"
|
---|
| 29 | #include "OgreLight.h"
|
---|
| 30 | #include "OgreCamera.h"
|
---|
| 31 | #include "OgreLogManager.h"
|
---|
| 32 | #include "OgreException.h"
|
---|
| 33 |
|
---|
| 34 | namespace Ogre {
|
---|
| 35 |
|
---|
| 36 | static HRESULT CALLBACK EnumZBuffersCallback(DDPIXELFORMAT* pddpf,
|
---|
| 37 | VOID* pFormats)
|
---|
| 38 | {
|
---|
| 39 | // Add to list of formats
|
---|
| 40 | std::vector<DDPIXELFORMAT> *vec;
|
---|
| 41 | vec = (std::vector<DDPIXELFORMAT>*)pFormats;
|
---|
| 42 |
|
---|
| 43 | if (pddpf->dwFlags & DDPF_ZBUFFER)
|
---|
| 44 | vec->push_back(*pddpf);
|
---|
| 45 | return D3DENUMRET_OK;
|
---|
| 46 |
|
---|
| 47 | }
|
---|
| 48 |
|
---|
| 49 |
|
---|
| 50 |
|
---|
| 51 |
|
---|
| 52 | D3DDevice D3DDevice::operator=(const D3DDevice &orig)
|
---|
| 53 | {
|
---|
| 54 |
|
---|
| 55 |
|
---|
| 56 | mDeviceName = orig.mDeviceName;
|
---|
| 57 | mDeviceDescription = orig.mDeviceDescription;
|
---|
| 58 | mD3DDeviceDesc = orig.mD3DDeviceDesc;
|
---|
| 59 | mIsHardwareAccelerated = orig.mIsHardwareAccelerated;
|
---|
| 60 | mNeedsZBuffer = orig.mNeedsZBuffer;
|
---|
| 61 |
|
---|
| 62 |
|
---|
| 63 | return *this;
|
---|
| 64 |
|
---|
| 65 | }
|
---|
| 66 |
|
---|
| 67 | // Default constructor
|
---|
| 68 | D3DDevice::D3DDevice()
|
---|
| 69 | {
|
---|
| 70 | // Init pointers
|
---|
| 71 | lpD3D = NULL;
|
---|
| 72 |
|
---|
| 73 | }
|
---|
| 74 |
|
---|
| 75 | // Copy Constructor
|
---|
| 76 | D3DDevice::D3DDevice(const D3DDevice &ob)
|
---|
| 77 | {
|
---|
| 78 | lpD3D = ob.lpD3D;
|
---|
| 79 | mViewport = ob.mViewport;
|
---|
| 80 | mDeviceDescription = ob.mDeviceDescription;
|
---|
| 81 | mDeviceName = ob.mDeviceName;
|
---|
| 82 | mD3DDeviceDesc = ob.mD3DDeviceDesc;
|
---|
| 83 | mIsHardwareAccelerated = ob.mIsHardwareAccelerated;
|
---|
| 84 | mNeedsZBuffer = ob.mNeedsZBuffer;
|
---|
| 85 |
|
---|
| 86 | }
|
---|
| 87 |
|
---|
| 88 | // Enum constructor
|
---|
| 89 | D3DDevice::D3DDevice(LPDIRECT3D7 lpDirect3D, LPSTR lpDeviceDesc, LPSTR lpDeviceName,
|
---|
| 90 | LPD3DDEVICEDESC7 lpD3DDeviceDesc)
|
---|
| 91 | {
|
---|
| 92 | // Init pointers
|
---|
| 93 | lpD3D = NULL;
|
---|
| 94 |
|
---|
| 95 | // Copy pointer to Direct3D7 interface
|
---|
| 96 | lpD3D = lpDirect3D;
|
---|
| 97 |
|
---|
| 98 | // Copy Name and Description
|
---|
| 99 | mDeviceDescription = lpDeviceDesc;
|
---|
| 100 | mDeviceName = lpDeviceName;
|
---|
| 101 |
|
---|
| 102 | // Is this a hardware or emulation device?
|
---|
| 103 | mIsHardwareAccelerated = ( 0 != (lpD3DDeviceDesc->dwDevCaps & D3DDEVCAPS_HWRASTERIZATION) );
|
---|
| 104 |
|
---|
| 105 |
|
---|
| 106 | // Copy device description
|
---|
| 107 | // No need to differentiate between SW and HW anymore
|
---|
| 108 | memcpy(&mD3DDeviceDesc, lpD3DDeviceDesc, sizeof(D3DDEVICEDESC7));
|
---|
| 109 |
|
---|
| 110 | StringUtil::StrStreamType str;
|
---|
| 111 | str << "Detected Direct3D Device " << lpDeviceDesc;
|
---|
| 112 | LogManager::getSingleton().logMessage(str.str());
|
---|
| 113 | logCaps();
|
---|
| 114 |
|
---|
| 115 | // Do we need a Z Buffer?
|
---|
| 116 | mNeedsZBuffer = !(mD3DDeviceDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR);
|
---|
| 117 | if (mNeedsZBuffer)
|
---|
| 118 | LogManager::getSingleton().logMessage("This device needs a Z-Buffer");
|
---|
| 119 | else
|
---|
| 120 | LogManager::getSingleton().logMessage("This device does not need a Z-Buffer");
|
---|
| 121 |
|
---|
| 122 |
|
---|
| 123 | }
|
---|
| 124 |
|
---|
| 125 | D3DDevice::~D3DDevice()
|
---|
| 126 | {
|
---|
| 127 | }
|
---|
| 128 |
|
---|
| 129 | LPDIRECT3DDEVICE7 D3DDevice::createDevice(LPDIRECTDRAWSURFACE7 renderTarget)
|
---|
| 130 | {
|
---|
| 131 | LPDIRECT3DDEVICE7 dev;
|
---|
| 132 | HRESULT hr;
|
---|
| 133 |
|
---|
| 134 | hr = lpD3D->CreateDevice(mD3DDeviceDesc.deviceGUID, renderTarget, &dev);
|
---|
| 135 | if(FAILED(hr))
|
---|
| 136 | throw Exception(hr, "Error creating new D3D device.",
|
---|
| 137 | "D3DDevice::createDevice");
|
---|
| 138 |
|
---|
| 139 | return dev;
|
---|
| 140 |
|
---|
| 141 | }
|
---|
| 142 |
|
---|
| 143 | LPDIRECT3D7 D3DDevice::getID3D(void)
|
---|
| 144 | {
|
---|
| 145 | return lpD3D;
|
---|
| 146 | }
|
---|
| 147 |
|
---|
| 148 |
|
---|
| 149 | bool D3DDevice::HardwareAccelerated(void) const
|
---|
| 150 | {
|
---|
| 151 | return mIsHardwareAccelerated;
|
---|
| 152 | }
|
---|
| 153 |
|
---|
| 154 | void D3DDevice::logCaps(void) const
|
---|
| 155 | {
|
---|
| 156 | // Sends capabilities of this driver to the log
|
---|
| 157 | char msg[255];
|
---|
| 158 |
|
---|
| 159 | LogManager::getSingleton().logMessage("Direct3D Device Capabilities:");
|
---|
| 160 |
|
---|
| 161 | sprintf(msg, " Hardware Accelerated: %i", HardwareAccelerated());
|
---|
| 162 | LogManager::getSingleton().logMessage(msg);
|
---|
| 163 |
|
---|
| 164 | sprintf(msg, " Mipmapping: %i", CanMipmap());
|
---|
| 165 | LogManager::getSingleton().logMessage(msg);
|
---|
| 166 |
|
---|
| 167 | sprintf(msg, " Bilinear Filtering: %i", CanBilinearFilter());
|
---|
| 168 | LogManager::getSingleton().logMessage(msg);
|
---|
| 169 |
|
---|
| 170 | sprintf(msg, " Trilinear Filtering: %i", CanTrilinearFilter());
|
---|
| 171 | LogManager::getSingleton().logMessage(msg);
|
---|
| 172 |
|
---|
| 173 | sprintf(msg, " Hardware Transform & Light: %i", CanHWTransformAndLight());
|
---|
| 174 | LogManager::getSingleton().logMessage(msg);
|
---|
| 175 |
|
---|
| 176 | sprintf(msg, " Max rendering colour depth: %i", RenderBitDepth());
|
---|
| 177 | LogManager::getSingleton().logMessage(msg);
|
---|
| 178 |
|
---|
| 179 | sprintf(msg, " Max single-pass texture layers: %i", MaxSinglePassTextureLayers());
|
---|
| 180 | LogManager::getSingleton().logMessage(msg);
|
---|
| 181 |
|
---|
| 182 | sprintf(msg, " Pixel fog supported: %i", ( mD3DDeviceDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE ) );
|
---|
| 183 | LogManager::getSingleton().logMessage(msg);
|
---|
| 184 |
|
---|
| 185 | sprintf(msg, " Vertex fog supported: %i", ( mD3DDeviceDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGVERTEX) );
|
---|
| 186 | LogManager::getSingleton().logMessage(msg);
|
---|
| 187 |
|
---|
| 188 |
|
---|
| 189 |
|
---|
| 190 | }
|
---|
| 191 |
|
---|
| 192 |
|
---|
| 193 | void D3DDevice::Cleanup(void)
|
---|
| 194 | {
|
---|
| 195 | // Release DirectX Objects
|
---|
| 196 |
|
---|
| 197 | lpD3D = NULL;
|
---|
| 198 | }
|
---|
| 199 |
|
---|
| 200 |
|
---|
| 201 |
|
---|
| 202 |
|
---|
| 203 | String D3DDevice::DeviceName(void) const
|
---|
| 204 | {
|
---|
| 205 | return mDeviceName;
|
---|
| 206 | }
|
---|
| 207 |
|
---|
| 208 | String D3DDevice::DeviceDescription(void) const
|
---|
| 209 | {
|
---|
| 210 | return mDeviceDescription;
|
---|
| 211 | }
|
---|
| 212 |
|
---|
| 213 |
|
---|
| 214 | void D3DDevice::createDepthBuffer(LPDIRECTDRAWSURFACE7 renderTarget)
|
---|
| 215 | {
|
---|
| 216 | DWORD bestDepth, bestStencil;
|
---|
| 217 | DDSURFACEDESC2 ddsd, src_ddsd;
|
---|
| 218 | LPDIRECTDRAW7 lpDD7;
|
---|
| 219 | LPDIRECTDRAWSURFACE7 lpZBuffer;
|
---|
| 220 | HRESULT hr;
|
---|
| 221 |
|
---|
| 222 | LogManager::getSingleton().logMessage("Direct3D - Creating Z-Buffer");
|
---|
| 223 |
|
---|
| 224 | // First check we NEED a depth buffer - e.g. PowerVR doesn't need one
|
---|
| 225 | if (mNeedsZBuffer)
|
---|
| 226 | {
|
---|
| 227 | // Get description from source surface
|
---|
| 228 | ZeroMemory(&src_ddsd, sizeof(DDSURFACEDESC2));
|
---|
| 229 | src_ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
---|
| 230 | renderTarget->GetSurfaceDesc(&src_ddsd);
|
---|
| 231 |
|
---|
| 232 | // Enumerate Depth Buffers
|
---|
| 233 | mDepthBufferFormats.clear();
|
---|
| 234 | lpD3D->EnumZBufferFormats(
|
---|
| 235 | mD3DDeviceDesc.deviceGUID,
|
---|
| 236 | EnumZBuffersCallback,
|
---|
| 237 | (LPVOID)&mDepthBufferFormats );
|
---|
| 238 |
|
---|
| 239 | // Choose the best one
|
---|
| 240 | // NB make sure Z buffer is the same depth as colour buffer (GeForce TnL problem)
|
---|
| 241 | // Also use best stencil if z depth is the same
|
---|
| 242 | bestDepth = 0;
|
---|
| 243 | bestStencil = 0;
|
---|
| 244 |
|
---|
| 245 | std::vector<DDPIXELFORMAT>::iterator it, best_it;
|
---|
| 246 | for(
|
---|
| 247 | it = mDepthBufferFormats.begin();
|
---|
| 248 | it != mDepthBufferFormats.end();
|
---|
| 249 | ++it )
|
---|
| 250 | {
|
---|
| 251 | if( ( (*it).dwZBufferBitDepth > bestDepth || (*it).dwStencilBitDepth > bestStencil)
|
---|
| 252 | &&
|
---|
| 253 | (*it).dwZBufferBitDepth <= src_ddsd.ddpfPixelFormat.dwZBufferBitDepth )
|
---|
| 254 | {
|
---|
| 255 | best_it = it;
|
---|
| 256 | bestDepth = (*it).dwZBufferBitDepth;
|
---|
| 257 | bestStencil = (*it).dwStencilBitDepth;
|
---|
| 258 | }
|
---|
| 259 | }
|
---|
| 260 |
|
---|
| 261 | // Setup the surface desc for the z-buffer.
|
---|
| 262 | ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
|
---|
| 263 |
|
---|
| 264 | ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
---|
| 265 | ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
|
---|
| 266 |
|
---|
| 267 | ddsd.dwWidth = src_ddsd.dwWidth;
|
---|
| 268 | ddsd.dwHeight = src_ddsd.dwHeight;
|
---|
| 269 |
|
---|
| 270 | ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
|
---|
| 271 |
|
---|
| 272 | memcpy( &ddsd.ddpfPixelFormat, &(*best_it), sizeof(DDPIXELFORMAT) );
|
---|
| 273 |
|
---|
| 274 | // Software devices require system-memory depth buffers.
|
---|
| 275 | if( mIsHardwareAccelerated )
|
---|
| 276 | ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
|
---|
| 277 | else
|
---|
| 278 | ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
---|
| 279 |
|
---|
| 280 | // Create the depth-buffer.
|
---|
| 281 | renderTarget->GetDDInterface( (VOID**)&lpDD7 );
|
---|
| 282 | lpDD7->Release();
|
---|
| 283 |
|
---|
| 284 | if( FAILED( hr = lpDD7->CreateSurface( &ddsd, &lpZBuffer, NULL ) ) )
|
---|
| 285 | OGRE_EXCEPT(
|
---|
| 286 | hr,
|
---|
| 287 | "Error creating depth buffer",
|
---|
| 288 | "D3DDevice::createDepthBuffer" );
|
---|
| 289 |
|
---|
| 290 | if( FAILED( hr = renderTarget->AddAttachedSurface(lpZBuffer) ) )
|
---|
| 291 | OGRE_EXCEPT(
|
---|
| 292 | hr,
|
---|
| 293 | "Error attaching depth buffer to render target",
|
---|
| 294 | "D3DDevice::createDepthBuffer" );
|
---|
| 295 |
|
---|
| 296 | // Log stencil buffer depth
|
---|
| 297 | mStencilBufferDepth = ddsd.ddpfPixelFormat.dwStencilBitDepth;
|
---|
| 298 |
|
---|
| 299 | StringUtil::StrStreamType str;
|
---|
| 300 | str << "Depth-Buffer created (" << ddsd.ddpfPixelFormat.dwZBufferBitDepth
|
---|
| 301 | << "-bit, " << mStencilBufferDepth << "-bit stencil)";
|
---|
| 302 | LogManager::getSingleton().logMessage(
|
---|
| 303 | LML_NORMAL, str.str());
|
---|
| 304 | if (mStencilBufferDepth == 0)
|
---|
| 305 | {
|
---|
| 306 | LogManager::getSingleton().logMessage("Warning: software stencilling "
|
---|
| 307 | "in use, stencil operations will not be hardware accelerated.");
|
---|
| 308 | }
|
---|
| 309 | }
|
---|
| 310 | }
|
---|
| 311 |
|
---|
| 312 | bool D3DDevice::CanMipmap(void) const
|
---|
| 313 | {
|
---|
| 314 | return (mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MIPNEAREST) > 0;
|
---|
| 315 | }
|
---|
| 316 |
|
---|
| 317 | bool D3DDevice::CanBilinearFilter(void) const
|
---|
| 318 | {
|
---|
| 319 | return (mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR) > 0;
|
---|
| 320 | }
|
---|
| 321 |
|
---|
| 322 | bool D3DDevice::CanTrilinearFilter(void) const
|
---|
| 323 | {
|
---|
| 324 | return (mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEARMIPLINEAR) > 0;
|
---|
| 325 | }
|
---|
| 326 |
|
---|
| 327 | unsigned int D3DDevice::RenderBitDepth(void) const
|
---|
| 328 | {
|
---|
| 329 |
|
---|
| 330 | if (mD3DDeviceDesc.dwDeviceRenderBitDepth & DDBD_32)
|
---|
| 331 | return 32;
|
---|
| 332 | else if (mD3DDeviceDesc.dwDeviceRenderBitDepth & DDBD_24)
|
---|
| 333 | return 24;
|
---|
| 334 | else if (mD3DDeviceDesc.dwDeviceRenderBitDepth & DDBD_16)
|
---|
| 335 | return 16;
|
---|
| 336 | else if (mD3DDeviceDesc.dwDeviceRenderBitDepth & DDBD_8)
|
---|
| 337 | return 8;
|
---|
| 338 | else
|
---|
| 339 | return 0;
|
---|
| 340 | }
|
---|
| 341 |
|
---|
| 342 | unsigned int D3DDevice::ZBufferBitDepth(void) const
|
---|
| 343 | {
|
---|
| 344 | switch(mD3DDeviceDesc.dwDeviceZBufferBitDepth)
|
---|
| 345 | {
|
---|
| 346 | case DDBD_8:
|
---|
| 347 | return 8;
|
---|
| 348 | case DDBD_16:
|
---|
| 349 | return 16;
|
---|
| 350 | case DDBD_24:
|
---|
| 351 | return 24;
|
---|
| 352 | case DDBD_32:
|
---|
| 353 | return 32;
|
---|
| 354 | }
|
---|
| 355 |
|
---|
| 356 | return 0;
|
---|
| 357 |
|
---|
| 358 | }
|
---|
| 359 | bool D3DDevice::NeedsZBuffer(void) const
|
---|
| 360 | {
|
---|
| 361 | return mNeedsZBuffer;
|
---|
| 362 | }
|
---|
| 363 |
|
---|
| 364 | bool D3DDevice::CanHWTransformAndLight(void) const
|
---|
| 365 | {
|
---|
| 366 | return (mD3DDeviceDesc.dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) > 0;
|
---|
| 367 | }
|
---|
| 368 |
|
---|
| 369 | unsigned int D3DDevice::MaxSinglePassTextureLayers(void) const
|
---|
| 370 | {
|
---|
| 371 | // The maximum number of texture layers the device can support in a singe pass
|
---|
| 372 |
|
---|
| 373 | return mD3DDeviceDesc.wMaxSimultaneousTextures;
|
---|
| 374 | }
|
---|
| 375 |
|
---|
| 376 | ushort D3DDevice::StencilBufferBitDepth(void) const
|
---|
| 377 | {
|
---|
| 378 | return mStencilBufferDepth;
|
---|
| 379 | }
|
---|
| 380 |
|
---|
| 381 |
|
---|
| 382 | } // Namespace
|
---|