2 * IDirect3D8 implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "d3d8_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d8
);
27 static inline struct d3d8
*impl_from_IDirect3D8(IDirect3D8
*iface
)
29 return CONTAINING_RECORD(iface
, struct d3d8
, IDirect3D8_iface
);
32 static HRESULT WINAPI
d3d8_QueryInterface(IDirect3D8
*iface
, REFIID riid
, void **out
)
34 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
36 if (IsEqualGUID(riid
, &IID_IDirect3D8
)
37 || IsEqualGUID(riid
, &IID_IUnknown
))
39 IDirect3D8_AddRef(iface
);
44 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid
));
50 static ULONG WINAPI
d3d8_AddRef(IDirect3D8
*iface
)
52 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
53 ULONG refcount
= InterlockedIncrement(&d3d8
->refcount
);
55 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
60 static ULONG WINAPI
d3d8_Release(IDirect3D8
*iface
)
62 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
63 ULONG refcount
= InterlockedDecrement(&d3d8
->refcount
);
65 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
70 wined3d_decref(d3d8
->wined3d
);
71 wined3d_mutex_unlock();
73 heap_free(d3d8
->wined3d_outputs
);
80 static HRESULT WINAPI
d3d8_RegisterSoftwareDevice(IDirect3D8
*iface
, void *init_function
)
82 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
85 TRACE("iface %p, init_function %p.\n", iface
, init_function
);
88 hr
= wined3d_register_software_device(d3d8
->wined3d
, init_function
);
89 wined3d_mutex_unlock();
94 static UINT WINAPI
d3d8_GetAdapterCount(IDirect3D8
*iface
)
96 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
98 TRACE("iface %p.\n", iface
);
100 return d3d8
->wined3d_output_count
;
103 static HRESULT WINAPI
d3d8_GetAdapterIdentifier(IDirect3D8
*iface
, UINT adapter
,
104 DWORD flags
, D3DADAPTER_IDENTIFIER8
*identifier
)
106 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
107 struct wined3d_adapter_identifier adapter_id
;
108 struct wined3d_adapter
*wined3d_adapter
;
109 unsigned int output_idx
;
112 TRACE("iface %p, adapter %u, flags %#lx, identifier %p.\n",
113 iface
, adapter
, flags
, identifier
);
115 output_idx
= adapter
;
116 if (output_idx
>= d3d8
->wined3d_output_count
)
117 return D3DERR_INVALIDCALL
;
119 adapter_id
.driver
= identifier
->Driver
;
120 adapter_id
.driver_size
= sizeof(identifier
->Driver
);
121 adapter_id
.description
= identifier
->Description
;
122 adapter_id
.description_size
= sizeof(identifier
->Description
);
124 /* D3DENUM_NO_WHQL_LEVEL -> WINED3DENUM_WHQL_LEVEL */
125 flags
^= D3DENUM_NO_WHQL_LEVEL
;
127 wined3d_adapter
= wined3d_output_get_adapter(d3d8
->wined3d_outputs
[output_idx
]);
128 if (SUCCEEDED(hr
= wined3d_adapter_get_identifier(wined3d_adapter
, flags
, &adapter_id
)))
130 identifier
->DriverVersion
= adapter_id
.driver_version
;
131 identifier
->VendorId
= adapter_id
.vendor_id
;
132 identifier
->DeviceId
= adapter_id
.device_id
;
133 identifier
->SubSysId
= adapter_id
.subsystem_id
;
134 identifier
->Revision
= adapter_id
.revision
;
135 memcpy(&identifier
->DeviceIdentifier
, &adapter_id
.device_identifier
, sizeof(identifier
->DeviceIdentifier
));
136 identifier
->WHQLLevel
= adapter_id
.whql_level
;
142 static UINT WINAPI
d3d8_GetAdapterModeCount(IDirect3D8
*iface
, UINT adapter
)
144 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
145 unsigned int output_idx
, count
;
147 TRACE("iface %p, adapter %u.\n", iface
, adapter
);
149 output_idx
= adapter
;
150 if (output_idx
>= d3d8
->wined3d_output_count
)
153 wined3d_mutex_lock();
154 count
= wined3d_output_get_mode_count(d3d8
->wined3d_outputs
[output_idx
],
155 WINED3DFMT_UNKNOWN
, WINED3D_SCANLINE_ORDERING_UNKNOWN
, true);
156 wined3d_mutex_unlock();
161 static HRESULT WINAPI
d3d8_EnumAdapterModes(IDirect3D8
*iface
, UINT adapter
, UINT mode_idx
, D3DDISPLAYMODE
*mode
)
163 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
164 struct wined3d_display_mode wined3d_mode
;
165 unsigned int output_idx
;
168 TRACE("iface %p, adapter %u, mode_idx %u, mode %p.\n",
169 iface
, adapter
, mode_idx
, mode
);
171 output_idx
= adapter
;
172 if (output_idx
>= d3d8
->wined3d_output_count
)
173 return D3DERR_INVALIDCALL
;
175 wined3d_mutex_lock();
176 hr
= wined3d_output_get_mode(d3d8
->wined3d_outputs
[output_idx
], WINED3DFMT_UNKNOWN
,
177 WINED3D_SCANLINE_ORDERING_UNKNOWN
, mode_idx
, &wined3d_mode
, true);
178 wined3d_mutex_unlock();
182 mode
->Width
= wined3d_mode
.width
;
183 mode
->Height
= wined3d_mode
.height
;
184 mode
->RefreshRate
= wined3d_mode
.refresh_rate
;
185 mode
->Format
= d3dformat_from_wined3dformat(wined3d_mode
.format_id
);
191 static HRESULT WINAPI
d3d8_GetAdapterDisplayMode(IDirect3D8
*iface
, UINT adapter
, D3DDISPLAYMODE
*mode
)
193 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
194 struct wined3d_display_mode wined3d_mode
;
195 unsigned int output_idx
;
198 TRACE("iface %p, adapter %u, mode %p.\n",
199 iface
, adapter
, mode
);
201 output_idx
= adapter
;
202 if (output_idx
>= d3d8
->wined3d_output_count
)
203 return D3DERR_INVALIDCALL
;
205 wined3d_mutex_lock();
206 hr
= wined3d_output_get_display_mode(d3d8
->wined3d_outputs
[output_idx
], &wined3d_mode
, NULL
);
207 wined3d_mutex_unlock();
211 mode
->Width
= wined3d_mode
.width
;
212 mode
->Height
= wined3d_mode
.height
;
213 mode
->RefreshRate
= wined3d_mode
.refresh_rate
;
214 mode
->Format
= d3dformat_from_wined3dformat(wined3d_mode
.format_id
);
220 static HRESULT WINAPI
d3d8_CheckDeviceType(IDirect3D8
*iface
, UINT adapter
, D3DDEVTYPE device_type
,
221 D3DFORMAT display_format
, D3DFORMAT backbuffer_format
, BOOL windowed
)
223 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
224 unsigned int output_idx
;
227 TRACE("iface %p, adapter %u, device_type %#x, display_format %#x, backbuffer_format %#x, windowed %#x.\n",
228 iface
, adapter
, device_type
, display_format
, backbuffer_format
, windowed
);
230 output_idx
= adapter
;
231 if (output_idx
>= d3d8
->wined3d_output_count
)
232 return D3DERR_INVALIDCALL
;
234 if (!windowed
&& display_format
!= D3DFMT_X8R8G8B8
&& display_format
!= D3DFMT_R5G6B5
)
235 return WINED3DERR_NOTAVAILABLE
;
237 wined3d_mutex_lock();
238 hr
= wined3d_check_device_type(d3d8
->wined3d
, d3d8
->wined3d_outputs
[output_idx
],
239 wined3d_device_type_from_d3d(device_type
), wined3dformat_from_d3dformat(display_format
),
240 wined3dformat_from_d3dformat(backbuffer_format
), windowed
);
241 wined3d_mutex_unlock();
246 static HRESULT WINAPI
d3d8_CheckDeviceFormat(IDirect3D8
*iface
, UINT adapter
, D3DDEVTYPE device_type
,
247 D3DFORMAT adapter_format
, DWORD usage
, D3DRESOURCETYPE resource_type
, D3DFORMAT format
)
249 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
250 enum wined3d_resource_type wined3d_rtype
;
251 struct wined3d_adapter
*wined3d_adapter
;
252 unsigned int bind_flags
;
253 unsigned int output_idx
;
256 TRACE("iface %p, adapter %u, device_type %#x, adapter_format %#x, usage %#lx, resource_type %#x, format %#x.\n",
257 iface
, adapter
, device_type
, adapter_format
, usage
, resource_type
, format
);
259 output_idx
= adapter
;
260 if (output_idx
>= d3d8
->wined3d_output_count
)
261 return D3DERR_INVALIDCALL
;
263 if (adapter_format
!= D3DFMT_X8R8G8B8
&& adapter_format
!= D3DFMT_R5G6B5
264 && adapter_format
!= D3DFMT_X1R5G5B5
)
266 WARN("Invalid adapter format.\n");
267 return adapter_format
? D3DERR_NOTAVAILABLE
: D3DERR_INVALIDCALL
;
270 bind_flags
= wined3d_bind_flags_from_d3d8_usage(usage
);
271 usage
= usage
& (WINED3DUSAGE_MASK
| WINED3DUSAGE_QUERY_MASK
);
272 switch (resource_type
)
274 case D3DRTYPE_CUBETEXTURE
:
275 usage
|= WINED3DUSAGE_LEGACY_CUBEMAP
;
276 case D3DRTYPE_TEXTURE
:
277 bind_flags
|= WINED3D_BIND_SHADER_RESOURCE
;
278 case D3DRTYPE_SURFACE
:
279 wined3d_rtype
= WINED3D_RTYPE_TEXTURE_2D
;
282 case D3DRTYPE_VOLUMETEXTURE
:
283 case D3DRTYPE_VOLUME
:
284 bind_flags
|= WINED3D_BIND_SHADER_RESOURCE
;
285 wined3d_rtype
= WINED3D_RTYPE_TEXTURE_3D
;
288 case D3DRTYPE_VERTEXBUFFER
:
289 case D3DRTYPE_INDEXBUFFER
:
290 wined3d_rtype
= WINED3D_RTYPE_BUFFER
;
294 FIXME("Unhandled resource type %#x.\n", resource_type
);
295 return WINED3DERR_INVALIDCALL
;
298 wined3d_mutex_lock();
299 wined3d_adapter
= wined3d_output_get_adapter(d3d8
->wined3d_outputs
[output_idx
]);
300 if (format
== D3DFMT_RESZ
&& resource_type
== D3DRTYPE_SURFACE
&& usage
== D3DUSAGE_RENDERTARGET
)
304 hr
= wined3d_check_device_multisample_type(wined3d_adapter
, wined3d_device_type_from_d3d(device_type
),
305 WINED3DFMT_D24_UNORM_S8_UINT
, FALSE
, WINED3D_MULTISAMPLE_NON_MASKABLE
, &levels
);
306 if (SUCCEEDED(hr
) && !levels
)
307 hr
= D3DERR_NOTAVAILABLE
;
310 hr
= wined3d_check_device_format(d3d8
->wined3d
, wined3d_adapter
, wined3d_device_type_from_d3d(device_type
),
311 wined3dformat_from_d3dformat(adapter_format
), usage
, bind_flags
, wined3d_rtype
,
312 wined3dformat_from_d3dformat(format
));
313 wined3d_mutex_unlock();
318 static HRESULT WINAPI
d3d8_CheckDeviceMultiSampleType(IDirect3D8
*iface
, UINT adapter
, D3DDEVTYPE device_type
,
319 D3DFORMAT format
, BOOL windowed
, D3DMULTISAMPLE_TYPE multisample_type
)
321 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
322 struct wined3d_adapter
*wined3d_adapter
;
323 unsigned int output_idx
;
326 TRACE("iface %p, adapter %u, device_type %#x, format %#x, windowed %#x, multisample_type %#x.\n",
327 iface
, adapter
, device_type
, format
, windowed
, multisample_type
);
329 output_idx
= adapter
;
330 if (output_idx
>= d3d8
->wined3d_output_count
)
331 return D3DERR_INVALIDCALL
;
333 if (multisample_type
> D3DMULTISAMPLE_16_SAMPLES
)
334 return D3DERR_INVALIDCALL
;
336 wined3d_mutex_lock();
337 wined3d_adapter
= wined3d_output_get_adapter(d3d8
->wined3d_outputs
[output_idx
]);
338 hr
= wined3d_check_device_multisample_type(wined3d_adapter
, wined3d_device_type_from_d3d(device_type
),
339 wined3dformat_from_d3dformat(format
), windowed
,
340 (enum wined3d_multisample_type
)multisample_type
, NULL
);
341 wined3d_mutex_unlock();
346 static HRESULT WINAPI
d3d8_CheckDepthStencilMatch(IDirect3D8
*iface
, UINT adapter
, D3DDEVTYPE device_type
,
347 D3DFORMAT adapter_format
, D3DFORMAT rt_format
, D3DFORMAT ds_format
)
349 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
350 struct wined3d_adapter
*wined3d_adapter
;
351 unsigned int output_idx
;
354 TRACE("iface %p, adapter %u, device_type %#x, adapter_format %#x, rt_format %#x, ds_format %#x.\n",
355 iface
, adapter
, device_type
, adapter_format
, rt_format
, ds_format
);
357 output_idx
= adapter
;
358 if (output_idx
>= d3d8
->wined3d_output_count
)
359 return D3DERR_INVALIDCALL
;
361 wined3d_mutex_lock();
362 wined3d_adapter
= wined3d_output_get_adapter(d3d8
->wined3d_outputs
[output_idx
]);
363 hr
= wined3d_check_depth_stencil_match(wined3d_adapter
, wined3d_device_type_from_d3d(device_type
),
364 wined3dformat_from_d3dformat(adapter_format
), wined3dformat_from_d3dformat(rt_format
),
365 wined3dformat_from_d3dformat(ds_format
));
366 wined3d_mutex_unlock();
371 static HRESULT WINAPI
d3d8_GetDeviceCaps(IDirect3D8
*iface
, UINT adapter
, D3DDEVTYPE device_type
, D3DCAPS8
*caps
)
373 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
374 struct wined3d_adapter
*wined3d_adapter
;
375 struct wined3d_caps wined3d_caps
;
376 unsigned int output_idx
;
379 TRACE("iface %p, adapter %u, device_type %#x, caps %p.\n", iface
, adapter
, device_type
, caps
);
381 output_idx
= adapter
;
382 if (output_idx
>= d3d8
->wined3d_output_count
)
383 return D3DERR_INVALIDCALL
;
386 return D3DERR_INVALIDCALL
;
388 wined3d_mutex_lock();
389 wined3d_adapter
= wined3d_output_get_adapter(d3d8
->wined3d_outputs
[output_idx
]);
390 hr
= wined3d_get_device_caps(wined3d_adapter
, wined3d_device_type_from_d3d(device_type
), &wined3d_caps
);
391 wined3d_mutex_unlock();
393 d3dcaps_from_wined3dcaps(caps
, &wined3d_caps
, adapter
);
398 static HMONITOR WINAPI
d3d8_GetAdapterMonitor(IDirect3D8
*iface
, UINT adapter
)
400 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
401 struct wined3d_output_desc desc
;
402 unsigned int output_idx
;
405 TRACE("iface %p, adapter %u.\n", iface
, adapter
);
407 output_idx
= adapter
;
408 if (output_idx
>= d3d8
->wined3d_output_count
)
411 wined3d_mutex_lock();
412 hr
= wined3d_output_get_desc(d3d8
->wined3d_outputs
[output_idx
], &desc
);
413 wined3d_mutex_unlock();
417 WARN("Failed to get output desc, hr %#lx.\n", hr
);
424 static HRESULT WINAPI
d3d8_CreateDevice(IDirect3D8
*iface
, UINT adapter
,
425 D3DDEVTYPE device_type
, HWND focus_window
, DWORD flags
, D3DPRESENT_PARAMETERS
*parameters
,
426 IDirect3DDevice8
**device
)
428 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
429 struct d3d8_device
*object
;
432 TRACE("iface %p, adapter %u, device_type %#x, focus_window %p, flags %#lx, parameters %p, device %p.\n",
433 iface
, adapter
, device_type
, focus_window
, flags
, parameters
, device
);
435 if (!(object
= heap_alloc_zero(sizeof(*object
))))
436 return E_OUTOFMEMORY
;
438 hr
= device_init(object
, d3d8
, d3d8
->wined3d
, adapter
, device_type
, focus_window
, flags
, parameters
);
441 WARN("Failed to initialize device, hr %#lx.\n", hr
);
446 TRACE("Created device %p.\n", object
);
447 *device
= &object
->IDirect3DDevice8_iface
;
452 static const struct IDirect3D8Vtbl d3d8_vtbl
=
459 d3d8_RegisterSoftwareDevice
,
460 d3d8_GetAdapterCount
,
461 d3d8_GetAdapterIdentifier
,
462 d3d8_GetAdapterModeCount
,
463 d3d8_EnumAdapterModes
,
464 d3d8_GetAdapterDisplayMode
,
465 d3d8_CheckDeviceType
,
466 d3d8_CheckDeviceFormat
,
467 d3d8_CheckDeviceMultiSampleType
,
468 d3d8_CheckDepthStencilMatch
,
470 d3d8_GetAdapterMonitor
,
474 BOOL
d3d8_init(struct d3d8
*d3d8
)
476 DWORD flags
= WINED3D_LEGACY_DEPTH_BIAS
| WINED3D_HANDLE_RESTORE
477 | WINED3D_PIXEL_CENTER_INTEGER
| WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR
478 | WINED3D_NO_PRIMITIVE_RESTART
| WINED3D_LEGACY_CUBEMAP_FILTERING
479 | WINED3D_NO_DRAW_INDIRECT
;
480 unsigned int adapter_idx
, output_idx
, adapter_count
, output_count
= 0;
481 struct wined3d_adapter
*wined3d_adapter
;
483 d3d8
->IDirect3D8_iface
.lpVtbl
= &d3d8_vtbl
;
486 wined3d_mutex_lock();
487 d3d8
->wined3d
= wined3d_create(flags
);
490 wined3d_mutex_unlock();
494 adapter_count
= wined3d_get_adapter_count(d3d8
->wined3d
);
495 for (adapter_idx
= 0; adapter_idx
< adapter_count
; ++adapter_idx
)
497 wined3d_adapter
= wined3d_get_adapter(d3d8
->wined3d
, adapter_idx
);
498 output_count
+= wined3d_adapter_get_output_count(wined3d_adapter
);
501 d3d8
->wined3d_outputs
= heap_calloc(output_count
, sizeof(*d3d8
->wined3d_outputs
));
502 if (!d3d8
->wined3d_outputs
)
504 wined3d_decref(d3d8
->wined3d
);
505 wined3d_mutex_unlock();
509 d3d8
->wined3d_output_count
= 0;
510 for (adapter_idx
= 0; adapter_idx
< adapter_count
; ++adapter_idx
)
512 wined3d_adapter
= wined3d_get_adapter(d3d8
->wined3d
, adapter_idx
);
513 output_count
= wined3d_adapter_get_output_count(wined3d_adapter
);
514 for (output_idx
= 0; output_idx
< output_count
; ++output_idx
)
516 d3d8
->wined3d_outputs
[d3d8
->wined3d_output_count
] =
517 wined3d_adapter_get_output(wined3d_adapter
, output_idx
);
518 ++d3d8
->wined3d_output_count
;
522 wined3d_mutex_unlock();