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 %u.\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 %u.\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 %#x, 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 wined3d_adapter
= wined3d_output_get_adapter(d3d8
->wined3d_outputs
[output_idx
]);
125 if (SUCCEEDED(hr
= wined3d_adapter_get_identifier(wined3d_adapter
, flags
, &adapter_id
)))
127 identifier
->DriverVersion
= adapter_id
.driver_version
;
128 identifier
->VendorId
= adapter_id
.vendor_id
;
129 identifier
->DeviceId
= adapter_id
.device_id
;
130 identifier
->SubSysId
= adapter_id
.subsystem_id
;
131 identifier
->Revision
= adapter_id
.revision
;
132 memcpy(&identifier
->DeviceIdentifier
, &adapter_id
.device_identifier
, sizeof(identifier
->DeviceIdentifier
));
133 identifier
->WHQLLevel
= adapter_id
.whql_level
;
139 static UINT WINAPI
d3d8_GetAdapterModeCount(IDirect3D8
*iface
, UINT adapter
)
141 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
142 unsigned int output_idx
, count
;
144 TRACE("iface %p, adapter %u.\n", iface
, adapter
);
146 output_idx
= adapter
;
147 if (output_idx
>= d3d8
->wined3d_output_count
)
150 wined3d_mutex_lock();
151 count
= wined3d_output_get_mode_count(d3d8
->wined3d_outputs
[output_idx
],
152 WINED3DFMT_UNKNOWN
, WINED3D_SCANLINE_ORDERING_UNKNOWN
);
153 wined3d_mutex_unlock();
158 static HRESULT WINAPI
d3d8_EnumAdapterModes(IDirect3D8
*iface
, UINT adapter
, UINT mode_idx
, D3DDISPLAYMODE
*mode
)
160 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
161 struct wined3d_display_mode wined3d_mode
;
162 unsigned int output_idx
;
165 TRACE("iface %p, adapter %u, mode_idx %u, mode %p.\n",
166 iface
, adapter
, mode_idx
, mode
);
168 output_idx
= adapter
;
169 if (output_idx
>= d3d8
->wined3d_output_count
)
170 return D3DERR_INVALIDCALL
;
172 wined3d_mutex_lock();
173 hr
= wined3d_output_get_mode(d3d8
->wined3d_outputs
[output_idx
], WINED3DFMT_UNKNOWN
,
174 WINED3D_SCANLINE_ORDERING_UNKNOWN
, mode_idx
, &wined3d_mode
);
175 wined3d_mutex_unlock();
179 mode
->Width
= wined3d_mode
.width
;
180 mode
->Height
= wined3d_mode
.height
;
181 mode
->RefreshRate
= wined3d_mode
.refresh_rate
;
182 mode
->Format
= d3dformat_from_wined3dformat(wined3d_mode
.format_id
);
188 static HRESULT WINAPI
d3d8_GetAdapterDisplayMode(IDirect3D8
*iface
, UINT adapter
, D3DDISPLAYMODE
*mode
)
190 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
191 struct wined3d_display_mode wined3d_mode
;
192 unsigned int output_idx
;
195 TRACE("iface %p, adapter %u, mode %p.\n",
196 iface
, adapter
, mode
);
198 output_idx
= adapter
;
199 if (output_idx
>= d3d8
->wined3d_output_count
)
200 return D3DERR_INVALIDCALL
;
202 wined3d_mutex_lock();
203 hr
= wined3d_output_get_display_mode(d3d8
->wined3d_outputs
[output_idx
], &wined3d_mode
, NULL
);
204 wined3d_mutex_unlock();
208 mode
->Width
= wined3d_mode
.width
;
209 mode
->Height
= wined3d_mode
.height
;
210 mode
->RefreshRate
= wined3d_mode
.refresh_rate
;
211 mode
->Format
= d3dformat_from_wined3dformat(wined3d_mode
.format_id
);
217 static HRESULT WINAPI
d3d8_CheckDeviceType(IDirect3D8
*iface
, UINT adapter
, D3DDEVTYPE device_type
,
218 D3DFORMAT display_format
, D3DFORMAT backbuffer_format
, BOOL windowed
)
220 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
221 unsigned int output_idx
;
224 TRACE("iface %p, adapter %u, device_type %#x, display_format %#x, backbuffer_format %#x, windowed %#x.\n",
225 iface
, adapter
, device_type
, display_format
, backbuffer_format
, windowed
);
227 output_idx
= adapter
;
228 if (output_idx
>= d3d8
->wined3d_output_count
)
229 return D3DERR_INVALIDCALL
;
231 if (!windowed
&& display_format
!= D3DFMT_X8R8G8B8
&& display_format
!= D3DFMT_R5G6B5
)
232 return WINED3DERR_NOTAVAILABLE
;
234 wined3d_mutex_lock();
235 hr
= wined3d_check_device_type(d3d8
->wined3d
, d3d8
->wined3d_outputs
[output_idx
],
236 wined3d_device_type_from_d3d(device_type
), wined3dformat_from_d3dformat(display_format
),
237 wined3dformat_from_d3dformat(backbuffer_format
), windowed
);
238 wined3d_mutex_unlock();
243 static HRESULT WINAPI
d3d8_CheckDeviceFormat(IDirect3D8
*iface
, UINT adapter
, D3DDEVTYPE device_type
,
244 D3DFORMAT adapter_format
, DWORD usage
, D3DRESOURCETYPE resource_type
, D3DFORMAT format
)
246 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
247 enum wined3d_resource_type wined3d_rtype
;
248 struct wined3d_adapter
*wined3d_adapter
;
249 unsigned int bind_flags
;
250 unsigned int output_idx
;
253 TRACE("iface %p, adapter %u, device_type %#x, adapter_format %#x, usage %#x, resource_type %#x, format %#x.\n",
254 iface
, adapter
, device_type
, adapter_format
, usage
, resource_type
, format
);
256 output_idx
= adapter
;
257 if (output_idx
>= d3d8
->wined3d_output_count
)
258 return D3DERR_INVALIDCALL
;
260 if (adapter_format
!= D3DFMT_X8R8G8B8
&& adapter_format
!= D3DFMT_R5G6B5
261 && adapter_format
!= D3DFMT_X1R5G5B5
)
263 WARN("Invalid adapter format.\n");
264 return adapter_format
? D3DERR_NOTAVAILABLE
: D3DERR_INVALIDCALL
;
267 bind_flags
= wined3d_bind_flags_from_d3d8_usage(usage
);
268 usage
= usage
& (WINED3DUSAGE_MASK
| WINED3DUSAGE_QUERY_MASK
);
269 switch (resource_type
)
271 case D3DRTYPE_CUBETEXTURE
:
272 usage
|= WINED3DUSAGE_LEGACY_CUBEMAP
;
273 case D3DRTYPE_TEXTURE
:
274 bind_flags
|= WINED3D_BIND_SHADER_RESOURCE
;
275 case D3DRTYPE_SURFACE
:
276 wined3d_rtype
= WINED3D_RTYPE_TEXTURE_2D
;
279 case D3DRTYPE_VOLUMETEXTURE
:
280 case D3DRTYPE_VOLUME
:
281 bind_flags
|= WINED3D_BIND_SHADER_RESOURCE
;
282 wined3d_rtype
= WINED3D_RTYPE_TEXTURE_3D
;
285 case D3DRTYPE_VERTEXBUFFER
:
286 case D3DRTYPE_INDEXBUFFER
:
287 wined3d_rtype
= WINED3D_RTYPE_BUFFER
;
291 FIXME("Unhandled resource type %#x.\n", resource_type
);
292 return WINED3DERR_INVALIDCALL
;
295 wined3d_mutex_lock();
296 wined3d_adapter
= wined3d_output_get_adapter(d3d8
->wined3d_outputs
[output_idx
]);
297 if (format
== D3DFMT_RESZ
&& resource_type
== D3DRTYPE_SURFACE
&& usage
== D3DUSAGE_RENDERTARGET
)
301 hr
= wined3d_check_device_multisample_type(wined3d_adapter
, wined3d_device_type_from_d3d(device_type
),
302 WINED3DFMT_D24_UNORM_S8_UINT
, FALSE
, WINED3D_MULTISAMPLE_NON_MASKABLE
, &levels
);
303 if (SUCCEEDED(hr
) && !levels
)
304 hr
= D3DERR_NOTAVAILABLE
;
307 hr
= wined3d_check_device_format(d3d8
->wined3d
, wined3d_adapter
, wined3d_device_type_from_d3d(device_type
),
308 wined3dformat_from_d3dformat(adapter_format
), usage
, bind_flags
, wined3d_rtype
,
309 wined3dformat_from_d3dformat(format
));
310 wined3d_mutex_unlock();
315 static HRESULT WINAPI
d3d8_CheckDeviceMultiSampleType(IDirect3D8
*iface
, UINT adapter
, D3DDEVTYPE device_type
,
316 D3DFORMAT format
, BOOL windowed
, D3DMULTISAMPLE_TYPE multisample_type
)
318 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
319 struct wined3d_adapter
*wined3d_adapter
;
320 unsigned int output_idx
;
323 TRACE("iface %p, adapter %u, device_type %#x, format %#x, windowed %#x, multisample_type %#x.\n",
324 iface
, adapter
, device_type
, format
, windowed
, multisample_type
);
326 output_idx
= adapter
;
327 if (output_idx
>= d3d8
->wined3d_output_count
)
328 return D3DERR_INVALIDCALL
;
330 if (multisample_type
> D3DMULTISAMPLE_16_SAMPLES
)
331 return D3DERR_INVALIDCALL
;
333 wined3d_mutex_lock();
334 wined3d_adapter
= wined3d_output_get_adapter(d3d8
->wined3d_outputs
[output_idx
]);
335 hr
= wined3d_check_device_multisample_type(wined3d_adapter
, wined3d_device_type_from_d3d(device_type
),
336 wined3dformat_from_d3dformat(format
), windowed
,
337 (enum wined3d_multisample_type
)multisample_type
, NULL
);
338 wined3d_mutex_unlock();
343 static HRESULT WINAPI
d3d8_CheckDepthStencilMatch(IDirect3D8
*iface
, UINT adapter
, D3DDEVTYPE device_type
,
344 D3DFORMAT adapter_format
, D3DFORMAT rt_format
, D3DFORMAT ds_format
)
346 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
347 struct wined3d_adapter
*wined3d_adapter
;
348 unsigned int output_idx
;
351 TRACE("iface %p, adapter %u, device_type %#x, adapter_format %#x, rt_format %#x, ds_format %#x.\n",
352 iface
, adapter
, device_type
, adapter_format
, rt_format
, ds_format
);
354 output_idx
= adapter
;
355 if (output_idx
>= d3d8
->wined3d_output_count
)
356 return D3DERR_INVALIDCALL
;
358 wined3d_mutex_lock();
359 wined3d_adapter
= wined3d_output_get_adapter(d3d8
->wined3d_outputs
[output_idx
]);
360 hr
= wined3d_check_depth_stencil_match(wined3d_adapter
, wined3d_device_type_from_d3d(device_type
),
361 wined3dformat_from_d3dformat(adapter_format
), wined3dformat_from_d3dformat(rt_format
),
362 wined3dformat_from_d3dformat(ds_format
));
363 wined3d_mutex_unlock();
368 static HRESULT WINAPI
d3d8_GetDeviceCaps(IDirect3D8
*iface
, UINT adapter
, D3DDEVTYPE device_type
, D3DCAPS8
*caps
)
370 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
371 struct wined3d_adapter
*wined3d_adapter
;
372 struct wined3d_caps wined3d_caps
;
373 unsigned int output_idx
;
376 TRACE("iface %p, adapter %u, device_type %#x, caps %p.\n", iface
, adapter
, device_type
, caps
);
378 output_idx
= adapter
;
379 if (output_idx
>= d3d8
->wined3d_output_count
)
380 return D3DERR_INVALIDCALL
;
383 return D3DERR_INVALIDCALL
;
385 wined3d_mutex_lock();
386 wined3d_adapter
= wined3d_output_get_adapter(d3d8
->wined3d_outputs
[output_idx
]);
387 hr
= wined3d_get_device_caps(wined3d_adapter
, wined3d_device_type_from_d3d(device_type
), &wined3d_caps
);
388 wined3d_mutex_unlock();
390 d3dcaps_from_wined3dcaps(caps
, &wined3d_caps
, adapter
);
395 static HMONITOR WINAPI
d3d8_GetAdapterMonitor(IDirect3D8
*iface
, UINT adapter
)
397 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
398 struct wined3d_output_desc desc
;
399 unsigned int output_idx
;
402 TRACE("iface %p, adapter %u.\n", iface
, adapter
);
404 output_idx
= adapter
;
405 if (output_idx
>= d3d8
->wined3d_output_count
)
408 wined3d_mutex_lock();
409 hr
= wined3d_output_get_desc(d3d8
->wined3d_outputs
[output_idx
], &desc
);
410 wined3d_mutex_unlock();
414 WARN("Failed to get output desc, hr %#x.\n", hr
);
421 static HRESULT WINAPI
d3d8_CreateDevice(IDirect3D8
*iface
, UINT adapter
,
422 D3DDEVTYPE device_type
, HWND focus_window
, DWORD flags
, D3DPRESENT_PARAMETERS
*parameters
,
423 IDirect3DDevice8
**device
)
425 struct d3d8
*d3d8
= impl_from_IDirect3D8(iface
);
426 struct d3d8_device
*object
;
429 TRACE("iface %p, adapter %u, device_type %#x, focus_window %p, flags %#x, parameters %p, device %p.\n",
430 iface
, adapter
, device_type
, focus_window
, flags
, parameters
, device
);
432 if (!(object
= heap_alloc_zero(sizeof(*object
))))
433 return E_OUTOFMEMORY
;
435 hr
= device_init(object
, d3d8
, d3d8
->wined3d
, adapter
, device_type
, focus_window
, flags
, parameters
);
438 WARN("Failed to initialize device, hr %#x.\n", hr
);
443 TRACE("Created device %p.\n", object
);
444 *device
= &object
->IDirect3DDevice8_iface
;
449 static const struct IDirect3D8Vtbl d3d8_vtbl
=
456 d3d8_RegisterSoftwareDevice
,
457 d3d8_GetAdapterCount
,
458 d3d8_GetAdapterIdentifier
,
459 d3d8_GetAdapterModeCount
,
460 d3d8_EnumAdapterModes
,
461 d3d8_GetAdapterDisplayMode
,
462 d3d8_CheckDeviceType
,
463 d3d8_CheckDeviceFormat
,
464 d3d8_CheckDeviceMultiSampleType
,
465 d3d8_CheckDepthStencilMatch
,
467 d3d8_GetAdapterMonitor
,
471 BOOL
d3d8_init(struct d3d8
*d3d8
)
473 DWORD flags
= WINED3D_LEGACY_DEPTH_BIAS
| WINED3D_VIDMEM_ACCOUNTING
474 | WINED3D_HANDLE_RESTORE
| WINED3D_PIXEL_CENTER_INTEGER
475 | WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR
| WINED3D_NO_PRIMITIVE_RESTART
476 | WINED3D_LEGACY_CUBEMAP_FILTERING
;
477 unsigned int adapter_idx
, output_idx
, adapter_count
, output_count
= 0;
478 struct wined3d_adapter
*wined3d_adapter
;
480 d3d8
->IDirect3D8_iface
.lpVtbl
= &d3d8_vtbl
;
483 wined3d_mutex_lock();
484 d3d8
->wined3d
= wined3d_create(flags
);
487 wined3d_mutex_unlock();
491 adapter_count
= wined3d_get_adapter_count(d3d8
->wined3d
);
492 for (adapter_idx
= 0; adapter_idx
< adapter_count
; ++adapter_idx
)
494 wined3d_adapter
= wined3d_get_adapter(d3d8
->wined3d
, adapter_idx
);
495 output_count
+= wined3d_adapter_get_output_count(wined3d_adapter
);
498 d3d8
->wined3d_outputs
= heap_calloc(output_count
, sizeof(*d3d8
->wined3d_outputs
));
499 if (!d3d8
->wined3d_outputs
)
501 wined3d_decref(d3d8
->wined3d
);
502 wined3d_mutex_unlock();
506 d3d8
->wined3d_output_count
= 0;
507 for (adapter_idx
= 0; adapter_idx
< adapter_count
; ++adapter_idx
)
509 wined3d_adapter
= wined3d_get_adapter(d3d8
->wined3d
, adapter_idx
);
510 output_count
= wined3d_adapter_get_output_count(wined3d_adapter
);
511 for (output_idx
= 0; output_idx
< output_count
; ++output_idx
)
513 d3d8
->wined3d_outputs
[d3d8
->wined3d_output_count
] =
514 wined3d_adapter_get_output(wined3d_adapter
, output_idx
);
515 ++d3d8
->wined3d_output_count
;
519 wined3d_mutex_unlock();