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
|
---|