1 /* -*- c++ -*-
2 FILE: WrapD3D.cpp
3 RCS REVISION: $Revision: 1.8 $
4
5 COPYRIGHT: (c) 1999 -- 2003 Melinda Green, Don Hatch, and Jay Berkenbilt - Superliminal Software
6
7 LICENSE: Free to use and modify for non-commercial purposes as long as the
8 following conditions are adhered to:
9 1) Obvious credit for the source of this code and the designs it embodies
10 are clearly made, and
11 2) Ports and derived versions of 4D Magic Cube programs are not distributed
12 without the express written permission of the authors.
13
14 DESCRIPTION:
15 Abstraction on top of DirectX
16 */
17
18 #include "WrapDx.h"
19
20 #define RELEASE(x) if (x != NULL) {x->Release(); x = NULL;}
21
22
23 static bool s_software_render_only = true; // hack to pass preference to
24 // enum callback
25
WrapD3D()26 WrapD3D::WrapD3D()
27 {
28 m_pDirect3D = 0;
29 m_pDirect3DDevice = 0;
30 m_bTexturesDisabled = FALSE;
31 m_pCurrentDeviceInfo = 0;
32 m_deviceInfoCount = 0;
33 }
34
~WrapD3D()35 WrapD3D::~WrapD3D()
36 {
37 Destroy();
38 }
39
40 BOOL
Create(HWND hWnd,BOOL fullScreen,int width,int height,int bpp,const PALETTEENTRY * pPaletteEntries,int paletteEntryCount,bool software_render_only)41 WrapD3D::Create(HWND hWnd, BOOL fullScreen,
42 int width, int height, int bpp,
43 const PALETTEENTRY * pPaletteEntries,
44 int paletteEntryCount, bool software_render_only)
45 {
46 s_software_render_only = software_render_only; // passing parameter
47 // through global -
48 // dirty, I know
49
50 if (!WrapDD::Create(hWnd,
51 fullScreen, width, height, bpp,
52 pPaletteEntries, paletteEntryCount))
53 {
54 return FALSE;
55 }
56
57 return (D3DCreate() && D3DInit() && D3DSetMode());
58 }
59
60 void
Destroy()61 WrapD3D::Destroy()
62 {
63 RELEASE(m_pDirect3DDevice);
64 RELEASE(m_pDirect3D);
65 WrapDD::Destroy();
66
67 // ??? or in Create()
68 m_pCurrentDeviceInfo = 0;
69 m_deviceInfoCount = 0;
70 }
71
72 void
DestroyButNotDirectDraw()73 WrapD3D::DestroyButNotDirectDraw()
74 {
75 RELEASE(m_pDirect3DDevice);
76 RELEASE(m_pDirect3D);
77 WrapDD::DestroyButNotDirectDraw();
78
79 // ??? or in Create()
80 m_pCurrentDeviceInfo = 0;
81 m_deviceInfoCount = 0;
82 }
83
84 BOOL
D3DCreate()85 WrapD3D::D3DCreate()
86 {
87 HRESULT result;
88
89 result =
90 DirectDraw()->QueryInterface(IID_IDirect3D, (void **)&m_pDirect3D);
91 if (result != DD_OK)
92 {
93 Error("Creation of IDirect3D failed", result);
94 return FALSE;
95 }
96 return TRUE;
97 }
98
99 BOOL
D3DInit()100 WrapD3D::D3DInit()
101 {
102 HRESULT result;
103
104 result = m_pDirect3D->EnumDevices(EnumDevicesCallback, this);
105 if (result != DD_OK)
106 {
107 Error("EnumDevices failed", result);
108 }
109
110 return (result == DD_OK);
111 }
112
113 // Initialize the D3D objects which change when the mode changes.
114 BOOL
D3DSetMode()115 WrapD3D::D3DSetMode()
116 {
117 HRESULT result;
118
119 // Create the viewport and device objects.
120 if (m_pCurrentDeviceInfo->HWDesc.dcmColorModel)
121 {
122 // Hardware driver
123 if (m_bOnlySoftRender)
124 {
125 Error
126 ("Failed to place vital surfaces in video memory for hardware driver",
127 DDERR_GENERIC);
128 return FALSE;
129 }
130 if (m_pCurrentDeviceInfo->HWDesc.dpcTriCaps.
131 dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE)
132 {
133 m_bTexturesDisabled = FALSE;
134 }
135 else
136 {
137 m_bTexturesDisabled = TRUE;
138 }
139
140 if (!CreateZBuffer
141 (DDSCAPS_VIDEOMEMORY, ZBufferDepth(m_pCurrentDeviceInfo)))
142 {
143 return FALSE;
144 }
145 }
146 else
147 {
148 // Software driver
149 if (m_pCurrentDeviceInfo->HELDesc.dpcTriCaps.
150 dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE)
151 {
152 m_bTexturesDisabled = FALSE;
153 }
154 else
155 {
156 m_bTexturesDisabled = TRUE;
157 }
158
159 if (!CreateZBuffer
160 (DDSCAPS_SYSTEMMEMORY, ZBufferDepth(m_pCurrentDeviceInfo)))
161 {
162 return FALSE;
163 }
164 }
165
166 result = BackBuffer()->QueryInterface(m_pCurrentDeviceInfo->Guid,
167 (void **)&m_pDirect3DDevice);
168 if (result != DD_OK)
169 {
170 Error("Create D3D device failed", result);
171 return FALSE;
172 }
173
174 {
175 Mode
176 mode = CurrentMode();
177
178 // enumerate display modes again - m_pCurrentDeviceInfo is now set
179 if (!EnumerateDisplayModes())
180 {
181 return FALSE;
182 }
183
184 // NOTE: the current mode may have been removed
185 if (IsFullScreen())
186 {
187 if (!IsSupportedMode(mode.width, mode.height, mode.bitsPerPixel))
188 {
189 Error("This device cannot support the current display mode",
190 DDERR_GENERIC);
191 return FALSE;
192 }
193 }
194 }
195
196 return TRUE;
197 }
198
199 BOOL
FilterDisplayModes(LPDDSURFACEDESC pddsd)200 WrapD3D::FilterDisplayModes(LPDDSURFACEDESC pddsd)
201 {
202 if (m_pCurrentDeviceInfo)
203 {
204 DWORD
205 deviceDepth;
206
207 if (m_pCurrentDeviceInfo->HWDesc.dwFlags & D3DDD_DEVICERENDERBITDEPTH)
208 {
209 deviceDepth = m_pCurrentDeviceInfo->HWDesc.dwDeviceRenderBitDepth;
210 }
211 else
212 {
213 deviceDepth =
214 m_pCurrentDeviceInfo->HELDesc.dwDeviceRenderBitDepth;
215 }
216
217 return (((pddsd->ddpfPixelFormat.dwRGBBitCount == 8UL) &&
218 (deviceDepth & DDBD_8)) ||
219 ((pddsd->ddpfPixelFormat.dwRGBBitCount == 16UL) &&
220 (deviceDepth & DDBD_16)));
221 }
222
223 return TRUE;
224 }
225
226 int
ZBufferDepth(Direct3DDeviceInfo * pDeviceInfo)227 WrapD3D::ZBufferDepth(Direct3DDeviceInfo * pDeviceInfo)
228 {
229 int
230 depth;
231 DWORD
232 deviceDepth;
233
234 if (pDeviceInfo->HWDesc.dwFlags & D3DDD_DEVICEZBUFFERBITDEPTH)
235 {
236 deviceDepth = pDeviceInfo->HWDesc.dwDeviceZBufferBitDepth;
237 }
238 else
239 {
240 deviceDepth = pDeviceInfo->HELDesc.dwDeviceZBufferBitDepth;
241 }
242
243 if (deviceDepth & DDBD_32)
244 depth = 32;
245 else if (deviceDepth & DDBD_24)
246 depth = 24;
247 else if (deviceDepth & DDBD_16)
248 depth = 16;
249 else if (deviceDepth & DDBD_8)
250 depth = 8;
251 else
252 depth = -1;
253
254 return depth;
255 }
256
257 HRESULT
EnumDevicesCallback(GUID * pGuid,char * pDeviceDescription,char * pDeviceName,LPD3DDEVICEDESC pHWDesc,LPD3DDEVICEDESC pHELDesc)258 WrapD3D::EnumDevicesCallback(GUID * pGuid,
259 char *pDeviceDescription,
260 char *pDeviceName,
261 LPD3DDEVICEDESC pHWDesc,
262 LPD3DDEVICEDESC pHELDesc)
263 {
264 m_deviceInfo[m_deviceInfoCount].Initialize(pGuid,
265 pDeviceDescription,
266 pDeviceName,
267 pHWDesc, pHELDesc);
268
269 // Chooses hardware over software, RGB lights over mono lights
270 // If software only, choose Ramp over RGB.
271
272 if (!m_pCurrentDeviceInfo)
273 {
274 // chooses anything over nothing
275 m_pCurrentDeviceInfo = &m_deviceInfo[m_deviceInfoCount];
276 }
277 else
278 {
279 // this block copied from below to all SW preference
280 if (s_software_render_only)
281 {
282 if (!m_pCurrentDeviceInfo->HWDesc.dcmColorModel)
283 {
284 if (!m_pCurrentDeviceInfo->HELDesc.dcmColorModel)
285 {
286 m_pCurrentDeviceInfo = &m_deviceInfo[m_deviceInfoCount];
287 }
288 else if (pHELDesc->dcmColorModel & D3DCOLOR_MONO &&
289 m_pCurrentDeviceInfo->HELDesc.
290 dcmColorModel & D3DCOLOR_RGB)
291 {
292 m_pCurrentDeviceInfo = &m_deviceInfo[m_deviceInfoCount];
293 }
294 }
295 }
296 else if (pHWDesc->dcmColorModel && !m_bOnlySoftRender)
297 {
298 // hardware device found
299 if (!m_pCurrentDeviceInfo->HWDesc.dcmColorModel)
300 {
301 m_pCurrentDeviceInfo = &m_deviceInfo[m_deviceInfoCount];
302 }
303 else if (pHWDesc->dcmColorModel & D3DCOLOR_RGB &&
304 m_pCurrentDeviceInfo->HWDesc.
305 dcmColorModel & D3DCOLOR_MONO)
306 {
307 m_pCurrentDeviceInfo = &m_deviceInfo[m_deviceInfoCount];
308 }
309 }
310 else if (!m_pCurrentDeviceInfo->HWDesc.dcmColorModel)
311 {
312 if (!m_pCurrentDeviceInfo->HELDesc.dcmColorModel)
313 {
314 m_pCurrentDeviceInfo = &m_deviceInfo[m_deviceInfoCount];
315 }
316 else if (pHELDesc->dcmColorModel & D3DCOLOR_MONO &&
317 m_pCurrentDeviceInfo->HELDesc.
318 dcmColorModel & D3DCOLOR_RGB)
319 {
320 m_pCurrentDeviceInfo = &m_deviceInfo[m_deviceInfoCount];
321 }
322 }
323 }
324 m_deviceInfoCount++;
325
326 if (m_deviceInfoCount == maxDeviceInfoCount)
327 {
328 return (D3DENUMRET_CANCEL);
329 }
330
331 return (D3DENUMRET_OK);
332 }
333
334 HRESULT CALLBACK
EnumDevicesCallback(GUID * pGuid,char * pDeviceDescription,char * pDeviceName,LPD3DDEVICEDESC pHWDesc,LPD3DDEVICEDESC pHELDesc,void * pContext)335 WrapD3D::EnumDevicesCallback(GUID * pGuid,
336 char *pDeviceDescription,
337 char *pDeviceName,
338 LPD3DDEVICEDESC pHWDesc,
339 LPD3DDEVICEDESC pHELDesc, void *pContext)
340 {
341 WrapD3D *
342 pDirect3D = (WrapD3D *) pContext;
343
344 return pDirect3D->EnumDevicesCallback(pGuid,
345 pDeviceDescription,
346 pDeviceName, pHWDesc, pHELDesc);
347 }
348
349 // Returns a string describing the given error code.
350 const char *
ErrorToString(HRESULT error)351 WrapD3D::ErrorToString(HRESULT error)
352 {
353 switch (error)
354 {
355 case DD_OK:
356 return "No error.\0";
357 case D3DERR_BADMAJORVERSION:
358 return "D3DERR_BADMAJORVERSION\0";
359 case D3DERR_BADMINORVERSION:
360 return "D3DERR_BADMINORVERSION\0";
361 case D3DERR_EXECUTE_LOCKED:
362 return "D3DERR_EXECUTE_LOCKED\0";
363 case D3DERR_EXECUTE_NOT_LOCKED:
364 return "D3DERR_EXECUTE_NOT_LOCKED\0";
365 case D3DERR_EXECUTE_CREATE_FAILED:
366 return "D3DERR_EXECUTE_CREATE_FAILED\0";
367 case D3DERR_EXECUTE_DESTROY_FAILED:
368 return "D3DERR_EXECUTE_DESTROY_FAILED\0";
369 case D3DERR_EXECUTE_LOCK_FAILED:
370 return "D3DERR_EXECUTE_LOCK_FAILED\0";
371 case D3DERR_EXECUTE_UNLOCK_FAILED:
372 return "D3DERR_EXECUTE_UNLOCK_FAILED\0";
373 case D3DERR_EXECUTE_FAILED:
374 return "D3DERR_EXECUTE_FAILED\0";
375 case D3DERR_EXECUTE_CLIPPED_FAILED:
376 return "D3DERR_EXECUTE_CLIPPED_FAILED\0";
377 case D3DERR_TEXTURE_NO_SUPPORT:
378 return "D3DERR_TEXTURE_NO_SUPPORT\0";
379 case D3DERR_TEXTURE_NOT_LOCKED:
380 return "D3DERR_TEXTURE_NOT_LOCKED\0";
381 case D3DERR_TEXTURE_LOCKED:
382 return "D3DERR_TEXTURELOCKED\0";
383 case D3DERR_TEXTURE_CREATE_FAILED:
384 return "D3DERR_TEXTURE_CREATE_FAILED\0";
385 case D3DERR_TEXTURE_DESTROY_FAILED:
386 return "D3DERR_TEXTURE_DESTROY_FAILED\0";
387 case D3DERR_TEXTURE_LOCK_FAILED:
388 return "D3DERR_TEXTURE_LOCK_FAILED\0";
389 case D3DERR_TEXTURE_UNLOCK_FAILED:
390 return "D3DERR_TEXTURE_UNLOCK_FAILED\0";
391 case D3DERR_TEXTURE_LOAD_FAILED:
392 return "D3DERR_TEXTURE_LOAD_FAILED\0";
393 case D3DERR_MATRIX_CREATE_FAILED:
394 return "D3DERR_MATRIX_CREATE_FAILED\0";
395 case D3DERR_MATRIX_DESTROY_FAILED:
396 return "D3DERR_MATRIX_DESTROY_FAILED\0";
397 case D3DERR_MATRIX_SETDATA_FAILED:
398 return "D3DERR_MATRIX_SETDATA_FAILED\0";
399 case D3DERR_SETVIEWPORTDATA_FAILED:
400 return "D3DERR_SETVIEWPORTDATA_FAILED\0";
401 case D3DERR_MATERIAL_CREATE_FAILED:
402 return "D3DERR_MATERIAL_CREATE_FAILED\0";
403 case D3DERR_MATERIAL_DESTROY_FAILED:
404 return "D3DERR_MATERIAL_DESTROY_FAILED\0";
405 case D3DERR_MATERIAL_SETDATA_FAILED:
406 return "D3DERR_MATERIAL_SETDATA_FAILED\0";
407 case D3DERR_LIGHT_SET_FAILED:
408 return "D3DERR_LIGHT_SET_FAILED\0";
409 default:
410 return WrapDD::ErrorToString(error);
411 }
412 }
413
414 // Local Variables:
415 // c-basic-offset: 4
416 // c-comment-only-line-offset: 0
417 // c-file-offsets: ((defun-block-intro . +) (block-open . 0) (substatement-open . 0) (statement-cont . +) (statement-case-open . +4) (arglist-intro . +) (arglist-close . +) (inline-open . 0))
418 // indent-tabs-mode: nil
419 // End:
420