[D3D8][D3D9][DDRAW][DXGI][QEDIT][WINED3D]
[reactos.git] / reactos / dll / directx / wine / d3d8 / device.c
1 /*
2 * IDirect3DDevice8 implementation
3 *
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2004 Christian Costa
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "d3d8_private.h"
23
24 static void STDMETHODCALLTYPE d3d8_null_wined3d_object_destroyed(void *parent) {}
25
26 static const struct wined3d_parent_ops d3d8_null_wined3d_parent_ops =
27 {
28 d3d8_null_wined3d_object_destroyed,
29 };
30
31 D3DFORMAT d3dformat_from_wined3dformat(enum wined3d_format_id format)
32 {
33 BYTE *c = (BYTE *)&format;
34
35 /* Don't translate FOURCC formats */
36 if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format;
37
38 switch(format)
39 {
40 case WINED3DFMT_UNKNOWN: return D3DFMT_UNKNOWN;
41 case WINED3DFMT_B8G8R8_UNORM: return D3DFMT_R8G8B8;
42 case WINED3DFMT_B8G8R8A8_UNORM: return D3DFMT_A8R8G8B8;
43 case WINED3DFMT_B8G8R8X8_UNORM: return D3DFMT_X8R8G8B8;
44 case WINED3DFMT_B5G6R5_UNORM: return D3DFMT_R5G6B5;
45 case WINED3DFMT_B5G5R5X1_UNORM: return D3DFMT_X1R5G5B5;
46 case WINED3DFMT_B5G5R5A1_UNORM: return D3DFMT_A1R5G5B5;
47 case WINED3DFMT_B4G4R4A4_UNORM: return D3DFMT_A4R4G4B4;
48 case WINED3DFMT_B2G3R3_UNORM: return D3DFMT_R3G3B2;
49 case WINED3DFMT_A8_UNORM: return D3DFMT_A8;
50 case WINED3DFMT_B2G3R3A8_UNORM: return D3DFMT_A8R3G3B2;
51 case WINED3DFMT_B4G4R4X4_UNORM: return D3DFMT_X4R4G4B4;
52 case WINED3DFMT_R10G10B10A2_UNORM: return D3DFMT_A2B10G10R10;
53 case WINED3DFMT_R16G16_UNORM: return D3DFMT_G16R16;
54 case WINED3DFMT_P8_UINT_A8_UNORM: return D3DFMT_A8P8;
55 case WINED3DFMT_P8_UINT: return D3DFMT_P8;
56 case WINED3DFMT_L8_UNORM: return D3DFMT_L8;
57 case WINED3DFMT_L8A8_UNORM: return D3DFMT_A8L8;
58 case WINED3DFMT_L4A4_UNORM: return D3DFMT_A4L4;
59 case WINED3DFMT_R8G8_SNORM: return D3DFMT_V8U8;
60 case WINED3DFMT_R5G5_SNORM_L6_UNORM: return D3DFMT_L6V5U5;
61 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM: return D3DFMT_X8L8V8U8;
62 case WINED3DFMT_R8G8B8A8_SNORM: return D3DFMT_Q8W8V8U8;
63 case WINED3DFMT_R16G16_SNORM: return D3DFMT_V16U16;
64 case WINED3DFMT_R10G11B11_SNORM: return D3DFMT_W11V11U10;
65 case WINED3DFMT_R10G10B10_SNORM_A2_UNORM: return D3DFMT_A2W10V10U10;
66 case WINED3DFMT_D16_LOCKABLE: return D3DFMT_D16_LOCKABLE;
67 case WINED3DFMT_D32_UNORM: return D3DFMT_D32;
68 case WINED3DFMT_S1_UINT_D15_UNORM: return D3DFMT_D15S1;
69 case WINED3DFMT_D24_UNORM_S8_UINT: return D3DFMT_D24S8;
70 case WINED3DFMT_X8D24_UNORM: return D3DFMT_D24X8;
71 case WINED3DFMT_S4X4_UINT_D24_UNORM: return D3DFMT_D24X4S4;
72 case WINED3DFMT_D16_UNORM: return D3DFMT_D16;
73 case WINED3DFMT_VERTEXDATA: return D3DFMT_VERTEXDATA;
74 case WINED3DFMT_R16_UINT: return D3DFMT_INDEX16;
75 case WINED3DFMT_R32_UINT: return D3DFMT_INDEX32;
76 default:
77 FIXME("Unhandled wined3d format %#x.\n", format);
78 return D3DFMT_UNKNOWN;
79 }
80 }
81
82 enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format)
83 {
84 BYTE *c = (BYTE *)&format;
85
86 /* Don't translate FOURCC formats */
87 if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format;
88
89 switch(format)
90 {
91 case D3DFMT_UNKNOWN: return WINED3DFMT_UNKNOWN;
92 case D3DFMT_R8G8B8: return WINED3DFMT_B8G8R8_UNORM;
93 case D3DFMT_A8R8G8B8: return WINED3DFMT_B8G8R8A8_UNORM;
94 case D3DFMT_X8R8G8B8: return WINED3DFMT_B8G8R8X8_UNORM;
95 case D3DFMT_R5G6B5: return WINED3DFMT_B5G6R5_UNORM;
96 case D3DFMT_X1R5G5B5: return WINED3DFMT_B5G5R5X1_UNORM;
97 case D3DFMT_A1R5G5B5: return WINED3DFMT_B5G5R5A1_UNORM;
98 case D3DFMT_A4R4G4B4: return WINED3DFMT_B4G4R4A4_UNORM;
99 case D3DFMT_R3G3B2: return WINED3DFMT_B2G3R3_UNORM;
100 case D3DFMT_A8: return WINED3DFMT_A8_UNORM;
101 case D3DFMT_A8R3G3B2: return WINED3DFMT_B2G3R3A8_UNORM;
102 case D3DFMT_X4R4G4B4: return WINED3DFMT_B4G4R4X4_UNORM;
103 case D3DFMT_A2B10G10R10: return WINED3DFMT_R10G10B10A2_UNORM;
104 case D3DFMT_G16R16: return WINED3DFMT_R16G16_UNORM;
105 case D3DFMT_A8P8: return WINED3DFMT_P8_UINT_A8_UNORM;
106 case D3DFMT_P8: return WINED3DFMT_P8_UINT;
107 case D3DFMT_L8: return WINED3DFMT_L8_UNORM;
108 case D3DFMT_A8L8: return WINED3DFMT_L8A8_UNORM;
109 case D3DFMT_A4L4: return WINED3DFMT_L4A4_UNORM;
110 case D3DFMT_V8U8: return WINED3DFMT_R8G8_SNORM;
111 case D3DFMT_L6V5U5: return WINED3DFMT_R5G5_SNORM_L6_UNORM;
112 case D3DFMT_X8L8V8U8: return WINED3DFMT_R8G8_SNORM_L8X8_UNORM;
113 case D3DFMT_Q8W8V8U8: return WINED3DFMT_R8G8B8A8_SNORM;
114 case D3DFMT_V16U16: return WINED3DFMT_R16G16_SNORM;
115 case D3DFMT_W11V11U10: return WINED3DFMT_R10G11B11_SNORM;
116 case D3DFMT_A2W10V10U10: return WINED3DFMT_R10G10B10_SNORM_A2_UNORM;
117 case D3DFMT_D16_LOCKABLE: return WINED3DFMT_D16_LOCKABLE;
118 case D3DFMT_D32: return WINED3DFMT_D32_UNORM;
119 case D3DFMT_D15S1: return WINED3DFMT_S1_UINT_D15_UNORM;
120 case D3DFMT_D24S8: return WINED3DFMT_D24_UNORM_S8_UINT;
121 case D3DFMT_D24X8: return WINED3DFMT_X8D24_UNORM;
122 case D3DFMT_D24X4S4: return WINED3DFMT_S4X4_UINT_D24_UNORM;
123 case D3DFMT_D16: return WINED3DFMT_D16_UNORM;
124 case D3DFMT_VERTEXDATA: return WINED3DFMT_VERTEXDATA;
125 case D3DFMT_INDEX16: return WINED3DFMT_R16_UINT;
126 case D3DFMT_INDEX32: return WINED3DFMT_R32_UINT;
127 default:
128 FIXME("Unhandled D3DFORMAT %#x\n", format);
129 return WINED3DFMT_UNKNOWN;
130 }
131 }
132
133 static UINT vertex_count_from_primitive_count(D3DPRIMITIVETYPE primitive_type, UINT primitive_count)
134 {
135 switch(primitive_type)
136 {
137 case D3DPT_POINTLIST:
138 return primitive_count;
139
140 case D3DPT_LINELIST:
141 return primitive_count * 2;
142
143 case D3DPT_LINESTRIP:
144 return primitive_count + 1;
145
146 case D3DPT_TRIANGLELIST:
147 return primitive_count * 3;
148
149 case D3DPT_TRIANGLESTRIP:
150 case D3DPT_TRIANGLEFAN:
151 return primitive_count + 2;
152
153 default:
154 FIXME("Unhandled primitive type %#x\n", primitive_type);
155 return 0;
156 }
157 }
158
159 static void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS *present_parameters,
160 const struct wined3d_swapchain_desc *swapchain_desc)
161 {
162 present_parameters->BackBufferWidth = swapchain_desc->backbuffer_width;
163 present_parameters->BackBufferHeight = swapchain_desc->backbuffer_height;
164 present_parameters->BackBufferFormat = d3dformat_from_wined3dformat(swapchain_desc->backbuffer_format);
165 present_parameters->BackBufferCount = swapchain_desc->backbuffer_count;
166 present_parameters->MultiSampleType = swapchain_desc->multisample_type;
167 present_parameters->SwapEffect = swapchain_desc->swap_effect;
168 present_parameters->hDeviceWindow = swapchain_desc->device_window;
169 present_parameters->Windowed = swapchain_desc->windowed;
170 present_parameters->EnableAutoDepthStencil = swapchain_desc->enable_auto_depth_stencil;
171 present_parameters->AutoDepthStencilFormat
172 = d3dformat_from_wined3dformat(swapchain_desc->auto_depth_stencil_format);
173 present_parameters->Flags = swapchain_desc->flags;
174 present_parameters->FullScreen_RefreshRateInHz = swapchain_desc->refresh_rate;
175 present_parameters->FullScreen_PresentationInterval = swapchain_desc->swap_interval;
176 }
177
178 static void wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapchain_desc *swapchain_desc,
179 const D3DPRESENT_PARAMETERS *present_parameters)
180 {
181 swapchain_desc->backbuffer_width = present_parameters->BackBufferWidth;
182 swapchain_desc->backbuffer_height = present_parameters->BackBufferHeight;
183 swapchain_desc->backbuffer_format = wined3dformat_from_d3dformat(present_parameters->BackBufferFormat);
184 swapchain_desc->backbuffer_count = max(1, present_parameters->BackBufferCount);
185 swapchain_desc->multisample_type = present_parameters->MultiSampleType;
186 swapchain_desc->multisample_quality = 0; /* d3d9 only */
187 swapchain_desc->swap_effect = present_parameters->SwapEffect;
188 swapchain_desc->device_window = present_parameters->hDeviceWindow;
189 swapchain_desc->windowed = present_parameters->Windowed;
190 swapchain_desc->enable_auto_depth_stencil = present_parameters->EnableAutoDepthStencil;
191 swapchain_desc->auto_depth_stencil_format
192 = wined3dformat_from_d3dformat(present_parameters->AutoDepthStencilFormat);
193 swapchain_desc->flags = present_parameters->Flags;
194 swapchain_desc->refresh_rate = present_parameters->FullScreen_RefreshRateInHz;
195 swapchain_desc->swap_interval = present_parameters->FullScreen_PresentationInterval;
196 swapchain_desc->auto_restore_display_mode = TRUE;
197 }
198
199 /* Handle table functions */
200 static DWORD d3d8_allocate_handle(struct d3d8_handle_table *t, void *object, enum d3d8_handle_type type)
201 {
202 struct d3d8_handle_entry *entry;
203
204 if (t->free_entries)
205 {
206 DWORD index = t->free_entries - t->entries;
207 /* Use a free handle */
208 entry = t->free_entries;
209 if (entry->type != D3D8_HANDLE_FREE)
210 {
211 ERR("Handle %u(%p) is in the free list, but has type %#x.\n", index, entry, entry->type);
212 return D3D8_INVALID_HANDLE;
213 }
214 t->free_entries = entry->object;
215 entry->object = object;
216 entry->type = type;
217
218 return index;
219 }
220
221 if (!(t->entry_count < t->table_size))
222 {
223 /* Grow the table */
224 UINT new_size = t->table_size + (t->table_size >> 1);
225 struct d3d8_handle_entry *new_entries = HeapReAlloc(GetProcessHeap(),
226 0, t->entries, new_size * sizeof(*t->entries));
227 if (!new_entries)
228 {
229 ERR("Failed to grow the handle table.\n");
230 return D3D8_INVALID_HANDLE;
231 }
232 t->entries = new_entries;
233 t->table_size = new_size;
234 }
235
236 entry = &t->entries[t->entry_count];
237 entry->object = object;
238 entry->type = type;
239
240 return t->entry_count++;
241 }
242
243 static void *d3d8_free_handle(struct d3d8_handle_table *t, DWORD handle, enum d3d8_handle_type type)
244 {
245 struct d3d8_handle_entry *entry;
246 void *object;
247
248 if (handle == D3D8_INVALID_HANDLE || handle >= t->entry_count)
249 {
250 WARN("Invalid handle %u passed.\n", handle);
251 return NULL;
252 }
253
254 entry = &t->entries[handle];
255 if (entry->type != type)
256 {
257 WARN("Handle %u(%p) is not of type %#x.\n", handle, entry, type);
258 return NULL;
259 }
260
261 object = entry->object;
262 entry->object = t->free_entries;
263 entry->type = D3D8_HANDLE_FREE;
264 t->free_entries = entry;
265
266 return object;
267 }
268
269 static void *d3d8_get_object(struct d3d8_handle_table *t, DWORD handle, enum d3d8_handle_type type)
270 {
271 struct d3d8_handle_entry *entry;
272
273 if (handle == D3D8_INVALID_HANDLE || handle >= t->entry_count)
274 {
275 WARN("Invalid handle %u passed.\n", handle);
276 return NULL;
277 }
278
279 entry = &t->entries[handle];
280 if (entry->type != type)
281 {
282 WARN("Handle %u(%p) is not of type %#x.\n", handle, entry, type);
283 return NULL;
284 }
285
286 return entry->object;
287 }
288
289 static inline struct d3d8_device *impl_from_IDirect3DDevice8(IDirect3DDevice8 *iface)
290 {
291 return CONTAINING_RECORD(iface, struct d3d8_device, IDirect3DDevice8_iface);
292 }
293
294 static HRESULT WINAPI d3d8_device_QueryInterface(IDirect3DDevice8 *iface, REFIID riid, void **out)
295 {
296 TRACE("iface %p, riid %s, out %p.\n",
297 iface, debugstr_guid(riid), out);
298
299 if (IsEqualGUID(riid, &IID_IDirect3DDevice8)
300 || IsEqualGUID(riid, &IID_IUnknown))
301 {
302 IDirect3DDevice8_AddRef(iface);
303 *out = iface;
304 return S_OK;
305 }
306
307 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
308
309 *out = NULL;
310 return E_NOINTERFACE;
311 }
312
313 static ULONG WINAPI d3d8_device_AddRef(IDirect3DDevice8 *iface)
314 {
315 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
316 ULONG ref = InterlockedIncrement(&device->ref);
317
318 TRACE("%p increasing refcount to %u.\n", iface, ref);
319
320 return ref;
321 }
322
323 static ULONG WINAPI d3d8_device_Release(IDirect3DDevice8 *iface)
324 {
325 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
326 ULONG ref;
327
328 if (device->inDestruction)
329 return 0;
330
331 ref = InterlockedDecrement(&device->ref);
332
333 TRACE("%p decreasing refcount to %u.\n", iface, ref);
334
335 if (!ref)
336 {
337 IDirect3D8 *parent = device->d3d_parent;
338 unsigned i;
339
340 TRACE("Releasing wined3d device %p.\n", device->wined3d_device);
341
342 wined3d_mutex_lock();
343
344 device->inDestruction = TRUE;
345
346 for (i = 0; i < device->numConvertedDecls; ++i)
347 {
348 d3d8_vertex_declaration_destroy(device->decls[i].declaration);
349 }
350 HeapFree(GetProcessHeap(), 0, device->decls);
351
352 if (device->vertex_buffer)
353 wined3d_buffer_decref(device->vertex_buffer);
354 if (device->index_buffer)
355 wined3d_buffer_decref(device->index_buffer);
356
357 wined3d_device_uninit_3d(device->wined3d_device);
358 wined3d_device_release_focus_window(device->wined3d_device);
359 wined3d_device_decref(device->wined3d_device);
360 HeapFree(GetProcessHeap(), 0, device->handle_table.entries);
361 HeapFree(GetProcessHeap(), 0, device);
362
363 wined3d_mutex_unlock();
364
365 IDirect3D8_Release(parent);
366 }
367 return ref;
368 }
369
370 static HRESULT WINAPI d3d8_device_TestCooperativeLevel(IDirect3DDevice8 *iface)
371 {
372 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
373
374 TRACE("iface %p.\n", iface);
375
376 if (device->lost)
377 {
378 TRACE("Device is lost.\n");
379 return D3DERR_DEVICENOTRESET;
380 }
381
382 return D3D_OK;
383 }
384
385 static UINT WINAPI d3d8_device_GetAvailableTextureMem(IDirect3DDevice8 *iface)
386 {
387 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
388 HRESULT hr;
389
390 TRACE("iface %p.\n", iface);
391
392 wined3d_mutex_lock();
393 hr = wined3d_device_get_available_texture_mem(device->wined3d_device);
394 wined3d_mutex_unlock();
395
396 return hr;
397 }
398
399 static HRESULT WINAPI d3d8_device_ResourceManagerDiscardBytes(IDirect3DDevice8 *iface, DWORD byte_count)
400 {
401 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
402
403 TRACE("iface %p, byte_count %u.\n", iface, byte_count);
404
405 if (byte_count)
406 FIXME("Byte count ignored.\n");
407
408 wined3d_mutex_lock();
409 wined3d_device_evict_managed_resources(device->wined3d_device);
410 wined3d_mutex_unlock();
411
412 return D3D_OK;
413 }
414
415 static HRESULT WINAPI d3d8_device_GetDirect3D(IDirect3DDevice8 *iface, IDirect3D8 **d3d8)
416 {
417 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
418
419 TRACE("iface %p, d3d8 %p.\n", iface, d3d8);
420
421 if (!d3d8)
422 return D3DERR_INVALIDCALL;
423
424 return IDirect3D8_QueryInterface(device->d3d_parent, &IID_IDirect3D8, (void **)d3d8);
425 }
426
427 static HRESULT WINAPI d3d8_device_GetDeviceCaps(IDirect3DDevice8 *iface, D3DCAPS8 *caps)
428 {
429 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
430 WINED3DCAPS *wined3d_caps;
431 HRESULT hr;
432
433 TRACE("iface %p, caps %p.\n", iface, caps);
434
435 if (!caps)
436 return D3DERR_INVALIDCALL;
437
438 if (!(wined3d_caps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wined3d_caps))))
439 return D3DERR_INVALIDCALL; /* well this is what MSDN says to return */
440
441 wined3d_mutex_lock();
442 hr = wined3d_device_get_device_caps(device->wined3d_device, wined3d_caps);
443 wined3d_mutex_unlock();
444
445 fixup_caps(wined3d_caps);
446 WINECAPSTOD3D8CAPS(caps, wined3d_caps)
447 HeapFree(GetProcessHeap(), 0, wined3d_caps);
448
449 return hr;
450 }
451
452 static HRESULT WINAPI d3d8_device_GetDisplayMode(IDirect3DDevice8 *iface, D3DDISPLAYMODE *mode)
453 {
454 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
455 struct wined3d_display_mode wined3d_mode;
456 HRESULT hr;
457
458 TRACE("iface %p, mode %p.\n", iface, mode);
459
460 wined3d_mutex_lock();
461 hr = wined3d_device_get_display_mode(device->wined3d_device, 0, &wined3d_mode, NULL);
462 wined3d_mutex_unlock();
463
464 if (SUCCEEDED(hr))
465 {
466 mode->Width = wined3d_mode.width;
467 mode->Height = wined3d_mode.height;
468 mode->RefreshRate = wined3d_mode.refresh_rate;
469 mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
470 }
471
472 return hr;
473 }
474
475 static HRESULT WINAPI d3d8_device_GetCreationParameters(IDirect3DDevice8 *iface,
476 D3DDEVICE_CREATION_PARAMETERS *parameters)
477 {
478 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
479
480 TRACE("iface %p, parameters %p.\n", iface, parameters);
481
482 wined3d_mutex_lock();
483 wined3d_device_get_creation_parameters(device->wined3d_device,
484 (struct wined3d_device_creation_parameters *)parameters);
485 wined3d_mutex_unlock();
486
487 return D3D_OK;
488 }
489
490 static HRESULT WINAPI d3d8_device_SetCursorProperties(IDirect3DDevice8 *iface,
491 UINT hotspot_x, UINT hotspot_y, IDirect3DSurface8 *bitmap)
492 {
493 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
494 struct d3d8_surface *bitmap_impl = unsafe_impl_from_IDirect3DSurface8(bitmap);
495 HRESULT hr;
496
497 TRACE("iface %p, hotspot_x %u, hotspot_y %u, bitmap %p.\n",
498 iface, hotspot_x, hotspot_y, bitmap);
499
500 if (!bitmap)
501 {
502 WARN("No cursor bitmap, returning D3DERR_INVALIDCALL.\n");
503 return D3DERR_INVALIDCALL;
504 }
505
506 wined3d_mutex_lock();
507 hr = wined3d_device_set_cursor_properties(device->wined3d_device,
508 hotspot_x, hotspot_y, bitmap_impl->wined3d_surface);
509 wined3d_mutex_unlock();
510
511 return hr;
512 }
513
514 static void WINAPI d3d8_device_SetCursorPosition(IDirect3DDevice8 *iface, UINT x, UINT y, DWORD flags)
515 {
516 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
517
518 TRACE("iface %p, x %u, y %u, flags %#x.\n", iface, x, y, flags);
519
520 wined3d_mutex_lock();
521 wined3d_device_set_cursor_position(device->wined3d_device, x, y, flags);
522 wined3d_mutex_unlock();
523 }
524
525 static BOOL WINAPI d3d8_device_ShowCursor(IDirect3DDevice8 *iface, BOOL show)
526 {
527 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
528 BOOL ret;
529
530 TRACE("iface %p, show %#x.\n", iface, show);
531
532 wined3d_mutex_lock();
533 ret = wined3d_device_show_cursor(device->wined3d_device, show);
534 wined3d_mutex_unlock();
535
536 return ret;
537 }
538
539 static HRESULT WINAPI d3d8_device_CreateAdditionalSwapChain(IDirect3DDevice8 *iface,
540 D3DPRESENT_PARAMETERS *present_parameters, IDirect3DSwapChain8 **swapchain)
541 {
542 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
543 struct wined3d_swapchain_desc desc;
544 struct d3d8_swapchain *object;
545
546 TRACE("iface %p, present_parameters %p, swapchain %p.\n",
547 iface, present_parameters, swapchain);
548
549 wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters);
550 if (SUCCEEDED(d3d8_swapchain_create(device, &desc, &object)))
551 *swapchain = &object->IDirect3DSwapChain8_iface;
552 present_parameters_from_wined3d_swapchain_desc(present_parameters, &desc);
553
554 return D3D_OK;
555 }
556
557 static HRESULT CDECL reset_enum_callback(struct wined3d_resource *resource)
558 {
559 struct wined3d_resource_desc desc;
560
561 wined3d_resource_get_desc(resource, &desc);
562 if (desc.pool == WINED3D_POOL_DEFAULT)
563 {
564 struct d3d8_surface *surface;
565
566 if (desc.resource_type == WINED3D_RTYPE_TEXTURE)
567 {
568 IUnknown *parent = wined3d_resource_get_parent(resource);
569 IDirect3DBaseTexture8 *texture;
570
571 if (SUCCEEDED(IUnknown_QueryInterface(parent, &IID_IDirect3DBaseTexture8, (void **)&texture)))
572 {
573 IDirect3DBaseTexture8_Release(texture);
574 WARN("Texture %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", texture, resource);
575 return D3DERR_DEVICELOST;
576 }
577
578 return D3D_OK;
579 }
580
581 if (desc.resource_type != WINED3D_RTYPE_SURFACE)
582 {
583 WARN("Resource %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", resource);
584 return D3DERR_DEVICELOST;
585 }
586
587 surface = wined3d_resource_get_parent(resource);
588 if (surface->resource.refcount)
589 {
590 WARN("Surface %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", surface, resource);
591 return D3DERR_DEVICELOST;
592 }
593
594 WARN("Surface %p (resource %p) is an implicit resource with ref 0.\n", surface, resource);
595 }
596
597 return D3D_OK;
598 }
599
600 static HRESULT WINAPI d3d8_device_Reset(IDirect3DDevice8 *iface,
601 D3DPRESENT_PARAMETERS *present_parameters)
602 {
603 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
604 struct wined3d_swapchain_desc swapchain_desc;
605 HRESULT hr;
606
607 TRACE("iface %p, present_parameters %p.\n", iface, present_parameters);
608
609 wined3d_mutex_lock();
610
611 if (device->vertex_buffer)
612 {
613 wined3d_buffer_decref(device->vertex_buffer);
614 device->vertex_buffer = NULL;
615 device->vertex_buffer_size = 0;
616 }
617 if (device->index_buffer)
618 {
619 wined3d_buffer_decref(device->index_buffer);
620 device->index_buffer = NULL;
621 device->index_buffer_size = 0;
622 }
623
624 wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters);
625 if (SUCCEEDED(hr = wined3d_device_reset(device->wined3d_device, &swapchain_desc,
626 NULL, reset_enum_callback, TRUE)))
627 {
628 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_POINTSIZE_MIN, 0);
629 device->lost = FALSE;
630 }
631 else
632 {
633 device->lost = TRUE;
634 }
635 wined3d_mutex_unlock();
636
637 return hr;
638 }
639
640 static HRESULT WINAPI d3d8_device_Present(IDirect3DDevice8 *iface, const RECT *src_rect,
641 const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region)
642 {
643 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
644 HRESULT hr;
645
646 TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p.\n",
647 iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect), dst_window_override, dirty_region);
648
649 wined3d_mutex_lock();
650 hr = wined3d_device_present(device->wined3d_device, src_rect, dst_rect,
651 dst_window_override, dirty_region, 0);
652 wined3d_mutex_unlock();
653
654 return hr;
655 }
656
657 static HRESULT WINAPI d3d8_device_GetBackBuffer(IDirect3DDevice8 *iface,
658 UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface8 **backbuffer)
659 {
660 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
661 struct wined3d_surface *wined3d_surface = NULL;
662 struct d3d8_surface *surface_impl;
663 HRESULT hr;
664
665 TRACE("iface %p, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
666 iface, backbuffer_idx, backbuffer_type, backbuffer);
667
668 wined3d_mutex_lock();
669 hr = wined3d_device_get_back_buffer(device->wined3d_device, 0, backbuffer_idx,
670 (enum wined3d_backbuffer_type)backbuffer_type, &wined3d_surface);
671 if (SUCCEEDED(hr) && wined3d_surface && backbuffer)
672 {
673 surface_impl = wined3d_surface_get_parent(wined3d_surface);
674 *backbuffer = &surface_impl->IDirect3DSurface8_iface;
675 IDirect3DSurface8_AddRef(*backbuffer);
676 }
677 wined3d_mutex_unlock();
678
679 return hr;
680 }
681
682 static HRESULT WINAPI d3d8_device_GetRasterStatus(IDirect3DDevice8 *iface, D3DRASTER_STATUS *raster_status)
683 {
684 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
685 HRESULT hr;
686
687 TRACE("iface %p, raster_status %p.\n", iface, raster_status);
688
689 wined3d_mutex_lock();
690 hr = wined3d_device_get_raster_status(device->wined3d_device, 0, (struct wined3d_raster_status *)raster_status);
691 wined3d_mutex_unlock();
692
693 return hr;
694 }
695
696 static void WINAPI d3d8_device_SetGammaRamp(IDirect3DDevice8 *iface, DWORD flags, const D3DGAMMARAMP *ramp)
697 {
698 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
699
700 TRACE("iface %p, flags %#x, ramp %p.\n", iface, flags, ramp);
701
702 /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
703 wined3d_mutex_lock();
704 wined3d_device_set_gamma_ramp(device->wined3d_device, 0, flags, (const struct wined3d_gamma_ramp *)ramp);
705 wined3d_mutex_unlock();
706 }
707
708 static void WINAPI d3d8_device_GetGammaRamp(IDirect3DDevice8 *iface, D3DGAMMARAMP *ramp)
709 {
710 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
711
712 TRACE("iface %p, ramp %p.\n", iface, ramp);
713
714 /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
715 wined3d_mutex_lock();
716 wined3d_device_get_gamma_ramp(device->wined3d_device, 0, (struct wined3d_gamma_ramp *)ramp);
717 wined3d_mutex_unlock();
718 }
719
720 static HRESULT WINAPI d3d8_device_CreateTexture(IDirect3DDevice8 *iface,
721 UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format,
722 D3DPOOL pool, IDirect3DTexture8 **texture)
723 {
724 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
725 struct d3d8_texture *object;
726 HRESULT hr;
727
728 TRACE("iface %p, width %u, height %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n",
729 iface, width, height, levels, usage, format, pool, texture);
730
731 *texture = NULL;
732 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
733 if (!object)
734 return D3DERR_OUTOFVIDEOMEMORY;
735
736 hr = texture_init(object, device, width, height, levels, usage, format, pool);
737 if (FAILED(hr))
738 {
739 WARN("Failed to initialize texture, hr %#x.\n", hr);
740 HeapFree(GetProcessHeap(), 0, object);
741 return hr;
742 }
743
744 TRACE("Created texture %p.\n", object);
745 *texture = (IDirect3DTexture8 *)&object->IDirect3DBaseTexture8_iface;
746
747 return D3D_OK;
748 }
749
750 static HRESULT WINAPI d3d8_device_CreateVolumeTexture(IDirect3DDevice8 *iface,
751 UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format,
752 D3DPOOL pool, IDirect3DVolumeTexture8 **texture)
753 {
754 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
755 struct d3d8_texture *object;
756 HRESULT hr;
757
758 TRACE("iface %p, width %u, height %u, depth %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n",
759 iface, width, height, depth, levels, usage, format, pool, texture);
760
761 *texture = NULL;
762 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
763 if (!object)
764 return D3DERR_OUTOFVIDEOMEMORY;
765
766 hr = volumetexture_init(object, device, width, height, depth, levels, usage, format, pool);
767 if (FAILED(hr))
768 {
769 WARN("Failed to initialize volume texture, hr %#x.\n", hr);
770 HeapFree(GetProcessHeap(), 0, object);
771 return hr;
772 }
773
774 TRACE("Created volume texture %p.\n", object);
775 *texture = (IDirect3DVolumeTexture8 *)&object->IDirect3DBaseTexture8_iface;
776
777 return D3D_OK;
778 }
779
780 static HRESULT WINAPI d3d8_device_CreateCubeTexture(IDirect3DDevice8 *iface, UINT edge_length,
781 UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DCubeTexture8 **texture)
782 {
783 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
784 struct d3d8_texture *object;
785 HRESULT hr;
786
787 TRACE("iface %p, edge_length %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n",
788 iface, edge_length, levels, usage, format, pool, texture);
789
790 *texture = NULL;
791 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
792 if (!object)
793 return D3DERR_OUTOFVIDEOMEMORY;
794
795 hr = cubetexture_init(object, device, edge_length, levels, usage, format, pool);
796 if (FAILED(hr))
797 {
798 WARN("Failed to initialize cube texture, hr %#x.\n", hr);
799 HeapFree(GetProcessHeap(), 0, object);
800 return hr;
801 }
802
803 TRACE("Created cube texture %p.\n", object);
804 *texture = (IDirect3DCubeTexture8 *)&object->IDirect3DBaseTexture8_iface;
805
806 return hr;
807 }
808
809 static HRESULT WINAPI d3d8_device_CreateVertexBuffer(IDirect3DDevice8 *iface, UINT size,
810 DWORD usage, DWORD fvf, D3DPOOL pool, IDirect3DVertexBuffer8 **buffer)
811 {
812 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
813 struct d3d8_vertexbuffer *object;
814 HRESULT hr;
815
816 TRACE("iface %p, size %u, usage %#x, fvf %#x, pool %#x, buffer %p.\n",
817 iface, size, usage, fvf, pool, buffer);
818
819 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
820 if (!object)
821 return D3DERR_OUTOFVIDEOMEMORY;
822
823 hr = vertexbuffer_init(object, device, size, usage, fvf, pool);
824 if (FAILED(hr))
825 {
826 WARN("Failed to initialize vertex buffer, hr %#x.\n", hr);
827 HeapFree(GetProcessHeap(), 0, object);
828 return hr;
829 }
830
831 TRACE("Created vertex buffer %p.\n", object);
832 *buffer = &object->IDirect3DVertexBuffer8_iface;
833
834 return D3D_OK;
835 }
836
837 static HRESULT WINAPI d3d8_device_CreateIndexBuffer(IDirect3DDevice8 *iface, UINT size,
838 DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer8 **buffer)
839 {
840 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
841 struct d3d8_indexbuffer *object;
842 HRESULT hr;
843
844 TRACE("iface %p, size %u, usage %#x, format %#x, pool %#x, buffer %p.\n",
845 iface, size, usage, format, pool, buffer);
846
847 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
848 if (!object)
849 return D3DERR_OUTOFVIDEOMEMORY;
850
851 hr = indexbuffer_init(object, device, size, usage, format, pool);
852 if (FAILED(hr))
853 {
854 WARN("Failed to initialize index buffer, hr %#x.\n", hr);
855 HeapFree(GetProcessHeap(), 0, object);
856 return hr;
857 }
858
859 TRACE("Created index buffer %p.\n", object);
860 *buffer = &object->IDirect3DIndexBuffer8_iface;
861
862 return D3D_OK;
863 }
864
865 static HRESULT d3d8_device_create_surface(struct d3d8_device *device, UINT width, UINT height,
866 D3DFORMAT format, DWORD flags, IDirect3DSurface8 **surface, UINT usage, D3DPOOL pool,
867 D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality)
868 {
869 struct wined3d_resource *sub_resource;
870 struct wined3d_resource_desc desc;
871 struct d3d8_surface *surface_impl;
872 struct wined3d_texture *texture;
873 HRESULT hr;
874
875 TRACE("device %p, width %u, height %u, format %#x, flags %#x, surface %p,\n"
876 "\tusage %#x, pool %#x, multisample_type %#x, multisample_quality %u.\n",
877 device, width, height, format, flags, surface,
878 usage, pool, multisample_type, multisample_quality);
879
880 desc.resource_type = WINED3D_RTYPE_TEXTURE;
881 desc.format = wined3dformat_from_d3dformat(format);
882 desc.multisample_type = multisample_type;
883 desc.multisample_quality = multisample_quality;
884 desc.usage = usage & WINED3DUSAGE_MASK;
885 desc.pool = pool;
886 desc.width = width;
887 desc.height = height;
888 desc.depth = 1;
889 desc.size = 0;
890
891 wined3d_mutex_lock();
892
893 if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &desc,
894 1, flags, NULL, &d3d8_null_wined3d_parent_ops, &texture)))
895 {
896 wined3d_mutex_unlock();
897 WARN("Failed to create texture, hr %#x.\n", hr);
898 return hr;
899 }
900
901 sub_resource = wined3d_texture_get_sub_resource(texture, 0);
902 surface_impl = wined3d_resource_get_parent(sub_resource);
903 surface_impl->forwardReference = NULL;
904 surface_impl->parent_device = &device->IDirect3DDevice8_iface;
905 *surface = &surface_impl->IDirect3DSurface8_iface;
906 IDirect3DSurface8_AddRef(*surface);
907 wined3d_texture_decref(texture);
908
909 wined3d_mutex_unlock();
910
911 return D3D_OK;
912 }
913
914 static HRESULT WINAPI d3d8_device_CreateRenderTarget(IDirect3DDevice8 *iface, UINT width,
915 UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, BOOL lockable,
916 IDirect3DSurface8 **surface)
917 {
918 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
919 DWORD flags = 0;
920
921 TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, lockable %#x, surface %p.\n",
922 iface, width, height, format, multisample_type, lockable, surface);
923
924 *surface = NULL;
925 if (lockable)
926 flags |= WINED3D_SURFACE_MAPPABLE;
927
928 return d3d8_device_create_surface(device, width, height, format, flags, surface,
929 D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, multisample_type, 0);
930 }
931
932 static HRESULT WINAPI d3d8_device_CreateDepthStencilSurface(IDirect3DDevice8 *iface,
933 UINT width, UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type,
934 IDirect3DSurface8 **surface)
935 {
936 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
937
938 TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, surface %p.\n",
939 iface, width, height, format, multisample_type, surface);
940
941 *surface = NULL;
942
943 /* TODO: Verify that Discard is false */
944 return d3d8_device_create_surface(device, width, height, format, WINED3D_SURFACE_MAPPABLE,
945 surface, D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, multisample_type, 0);
946 }
947
948 /* IDirect3DDevice8Impl::CreateImageSurface returns surface with pool type SYSTEMMEM */
949 static HRESULT WINAPI d3d8_device_CreateImageSurface(IDirect3DDevice8 *iface, UINT width,
950 UINT height, D3DFORMAT format, IDirect3DSurface8 **surface)
951 {
952 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
953
954 TRACE("iface %p, width %u, height %u, format %#x, surface %p.\n",
955 iface, width, height, format, surface);
956
957 *surface = NULL;
958
959 return d3d8_device_create_surface(device, width, height, format, WINED3D_SURFACE_MAPPABLE,
960 surface, 0, D3DPOOL_SYSTEMMEM, D3DMULTISAMPLE_NONE, 0);
961 }
962
963 static HRESULT WINAPI d3d8_device_CopyRects(IDirect3DDevice8 *iface,
964 IDirect3DSurface8 *src_surface, const RECT *src_rects, UINT rect_count,
965 IDirect3DSurface8 *dst_surface, const POINT *dst_points)
966 {
967 struct d3d8_surface *src = unsafe_impl_from_IDirect3DSurface8(src_surface);
968 struct d3d8_surface *dst = unsafe_impl_from_IDirect3DSurface8(dst_surface);
969 enum wined3d_format_id src_format, dst_format;
970 struct wined3d_resource_desc wined3d_desc;
971 struct wined3d_resource *wined3d_resource;
972 UINT src_w, src_h;
973 HRESULT hr;
974
975 TRACE("iface %p, src_surface %p, src_rects %p, rect_count %u, dst_surface %p, dst_points %p.\n",
976 iface, src_surface, src_rects, rect_count, dst_surface, dst_points);
977
978 /* Check that the source texture is in WINED3D_POOL_SYSTEM_MEM and the
979 * destination texture is in WINED3D_POOL_DEFAULT. */
980
981 wined3d_mutex_lock();
982 wined3d_resource = wined3d_surface_get_resource(src->wined3d_surface);
983 wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
984 if (wined3d_desc.usage & WINED3DUSAGE_DEPTHSTENCIL)
985 {
986 WARN("Source %p is a depth stencil surface, returning D3DERR_INVALIDCALL.\n", src_surface);
987 wined3d_mutex_unlock();
988 return D3DERR_INVALIDCALL;
989 }
990 src_format = wined3d_desc.format;
991 src_w = wined3d_desc.width;
992 src_h = wined3d_desc.height;
993
994 wined3d_resource = wined3d_surface_get_resource(dst->wined3d_surface);
995 wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
996 if (wined3d_desc.usage & WINED3DUSAGE_DEPTHSTENCIL)
997 {
998 WARN("Destination %p is a depth stencil surface, returning D3DERR_INVALIDCALL.\n", dst_surface);
999 wined3d_mutex_unlock();
1000 return D3DERR_INVALIDCALL;
1001 }
1002 dst_format = wined3d_desc.format;
1003
1004 /* Check that the source and destination formats match */
1005 if (src_format != dst_format && WINED3DFMT_UNKNOWN != dst_format)
1006 {
1007 WARN("Source %p format must match the destination %p format, returning D3DERR_INVALIDCALL.\n",
1008 src_surface, dst_surface);
1009 wined3d_mutex_unlock();
1010 return D3DERR_INVALIDCALL;
1011 }
1012 else if (WINED3DFMT_UNKNOWN == dst_format)
1013 {
1014 TRACE("Converting destination surface from WINED3DFMT_UNKNOWN to the source format.\n");
1015 if (FAILED(hr = wined3d_surface_update_desc(dst->wined3d_surface, wined3d_desc.width, wined3d_desc.height,
1016 src_format, wined3d_desc.multisample_type, wined3d_desc.multisample_quality, NULL, 0)))
1017 {
1018 WARN("Failed to update surface desc, hr %#x.\n", hr);
1019 wined3d_mutex_unlock();
1020 return hr;
1021 }
1022 }
1023
1024 /* Quick if complete copy ... */
1025 if (!rect_count && !src_rects && !dst_points)
1026 {
1027 RECT rect = {0, 0, src_w, src_h};
1028 wined3d_surface_blt(dst->wined3d_surface, &rect,
1029 src->wined3d_surface, &rect, 0, NULL, WINED3D_TEXF_POINT);
1030 }
1031 else
1032 {
1033 unsigned int i;
1034 /* Copy rect by rect */
1035 if (src_rects && dst_points)
1036 {
1037 for (i = 0; i < rect_count; ++i)
1038 {
1039 UINT w = src_rects[i].right - src_rects[i].left;
1040 UINT h = src_rects[i].bottom - src_rects[i].top;
1041 RECT dst_rect = {dst_points[i].x, dst_points[i].y,
1042 dst_points[i].x + w, dst_points[i].y + h};
1043
1044 wined3d_surface_blt(dst->wined3d_surface, &dst_rect,
1045 src->wined3d_surface, &src_rects[i], 0, NULL, WINED3D_TEXF_POINT);
1046 }
1047 }
1048 else
1049 {
1050 for (i = 0; i < rect_count; ++i)
1051 {
1052 UINT w = src_rects[i].right - src_rects[i].left;
1053 UINT h = src_rects[i].bottom - src_rects[i].top;
1054 RECT dst_rect = {0, 0, w, h};
1055
1056 wined3d_surface_blt(dst->wined3d_surface, &dst_rect,
1057 src->wined3d_surface, &src_rects[i], 0, NULL, WINED3D_TEXF_POINT);
1058 }
1059 }
1060 }
1061 wined3d_mutex_unlock();
1062
1063 return WINED3D_OK;
1064 }
1065
1066 static HRESULT WINAPI d3d8_device_UpdateTexture(IDirect3DDevice8 *iface,
1067 IDirect3DBaseTexture8 *src_texture, IDirect3DBaseTexture8 *dst_texture)
1068 {
1069 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1070 struct d3d8_texture *src_impl, *dst_impl;
1071 HRESULT hr;
1072
1073 TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface, src_texture, dst_texture);
1074
1075 src_impl = unsafe_impl_from_IDirect3DBaseTexture8(src_texture);
1076 dst_impl = unsafe_impl_from_IDirect3DBaseTexture8(dst_texture);
1077
1078 wined3d_mutex_lock();
1079 hr = wined3d_device_update_texture(device->wined3d_device,
1080 src_impl->wined3d_texture, dst_impl->wined3d_texture);
1081 wined3d_mutex_unlock();
1082
1083 return hr;
1084 }
1085
1086 static HRESULT WINAPI d3d8_device_GetFrontBuffer(IDirect3DDevice8 *iface, IDirect3DSurface8 *dst_surface)
1087 {
1088 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1089 struct d3d8_surface *dst_impl = unsafe_impl_from_IDirect3DSurface8(dst_surface);
1090 HRESULT hr;
1091
1092 TRACE("iface %p, dst_surface %p.\n", iface, dst_surface);
1093
1094 if (!dst_surface)
1095 {
1096 WARN("Invalid destination surface passed.\n");
1097 return D3DERR_INVALIDCALL;
1098 }
1099
1100 wined3d_mutex_lock();
1101 hr = wined3d_device_get_front_buffer_data(device->wined3d_device, 0, dst_impl->wined3d_surface);
1102 wined3d_mutex_unlock();
1103
1104 return hr;
1105 }
1106
1107 static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface,
1108 IDirect3DSurface8 *render_target, IDirect3DSurface8 *depth_stencil)
1109 {
1110 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1111 struct d3d8_surface *rt_impl = unsafe_impl_from_IDirect3DSurface8(render_target);
1112 struct d3d8_surface *ds_impl = unsafe_impl_from_IDirect3DSurface8(depth_stencil);
1113 struct wined3d_surface *original_ds = NULL;
1114 HRESULT hr = D3D_OK;
1115
1116 TRACE("iface %p, render_target %p, depth_stencil %p.\n", iface, render_target, depth_stencil);
1117
1118 wined3d_mutex_lock();
1119
1120 if (ds_impl)
1121 {
1122 struct wined3d_resource_desc ds_desc, rt_desc;
1123 struct wined3d_resource *wined3d_resource;
1124 struct wined3d_surface *original_rt = NULL;
1125
1126 /* If no render target is passed in check the size against the current RT */
1127 if (!render_target)
1128 {
1129 if (!(original_rt = wined3d_device_get_render_target(device->wined3d_device, 0)))
1130 {
1131 wined3d_mutex_unlock();
1132 return D3DERR_NOTFOUND;
1133 }
1134 wined3d_resource = wined3d_surface_get_resource(original_rt);
1135 }
1136 else
1137 wined3d_resource = wined3d_surface_get_resource(rt_impl->wined3d_surface);
1138 wined3d_resource_get_desc(wined3d_resource, &rt_desc);
1139
1140 wined3d_resource = wined3d_surface_get_resource(ds_impl->wined3d_surface);
1141 wined3d_resource_get_desc(wined3d_resource, &ds_desc);
1142
1143 if (ds_desc.width < rt_desc.width || ds_desc.height < rt_desc.height)
1144 {
1145 WARN("Depth stencil is smaller than the render target, returning D3DERR_INVALIDCALL\n");
1146 wined3d_mutex_unlock();
1147 return D3DERR_INVALIDCALL;
1148 }
1149 }
1150
1151 original_ds = wined3d_device_get_depth_stencil(device->wined3d_device);
1152 wined3d_device_set_depth_stencil(device->wined3d_device, ds_impl ? ds_impl->wined3d_surface : NULL);
1153 if (render_target)
1154 {
1155 hr = wined3d_device_set_render_target(device->wined3d_device, 0, rt_impl->wined3d_surface, TRUE);
1156 if (FAILED(hr))
1157 wined3d_device_set_depth_stencil(device->wined3d_device, original_ds);
1158 }
1159
1160 wined3d_mutex_unlock();
1161
1162 return hr;
1163 }
1164
1165 static HRESULT WINAPI d3d8_device_GetRenderTarget(IDirect3DDevice8 *iface, IDirect3DSurface8 **render_target)
1166 {
1167 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1168 struct wined3d_surface *wined3d_surface;
1169 struct d3d8_surface *surface_impl;
1170 HRESULT hr;
1171
1172 TRACE("iface %p, render_target %p.\n", iface, render_target);
1173
1174 if (!render_target)
1175 return D3DERR_INVALIDCALL;
1176
1177 wined3d_mutex_lock();
1178 if ((wined3d_surface = wined3d_device_get_render_target(device->wined3d_device, 0)))
1179 {
1180 surface_impl = wined3d_surface_get_parent(wined3d_surface);
1181 *render_target = &surface_impl->IDirect3DSurface8_iface;
1182 IDirect3DSurface8_AddRef(*render_target);
1183 hr = D3D_OK;
1184 }
1185 else
1186 {
1187 ERR("Failed to get wined3d render target.\n");
1188 *render_target = NULL;
1189 hr = D3DERR_NOTFOUND;
1190 }
1191 wined3d_mutex_unlock();
1192
1193 return hr;
1194 }
1195
1196 static HRESULT WINAPI d3d8_device_GetDepthStencilSurface(IDirect3DDevice8 *iface, IDirect3DSurface8 **depth_stencil)
1197 {
1198 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1199 struct wined3d_surface *wined3d_surface;
1200 struct d3d8_surface *surface_impl;
1201 HRESULT hr = D3D_OK;
1202
1203 TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil);
1204
1205 if (!depth_stencil)
1206 return D3DERR_INVALIDCALL;
1207
1208 wined3d_mutex_lock();
1209 if ((wined3d_surface = wined3d_device_get_depth_stencil(device->wined3d_device)))
1210 {
1211 surface_impl = wined3d_surface_get_parent(wined3d_surface);
1212 *depth_stencil = &surface_impl->IDirect3DSurface8_iface;
1213 IDirect3DSurface8_AddRef(*depth_stencil);
1214 }
1215 else
1216 {
1217 hr = WINED3DERR_NOTFOUND;
1218 *depth_stencil = NULL;
1219 }
1220 wined3d_mutex_unlock();
1221
1222 return hr;
1223 }
1224
1225 static HRESULT WINAPI d3d8_device_BeginScene(IDirect3DDevice8 *iface)
1226 {
1227 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1228 HRESULT hr;
1229
1230 TRACE("iface %p.\n", iface);
1231
1232 wined3d_mutex_lock();
1233 hr = wined3d_device_begin_scene(device->wined3d_device);
1234 wined3d_mutex_unlock();
1235
1236 return hr;
1237 }
1238
1239 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d8_device_EndScene(IDirect3DDevice8 *iface)
1240 {
1241 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1242 HRESULT hr;
1243
1244 TRACE("iface %p.\n", iface);
1245
1246 wined3d_mutex_lock();
1247 hr = wined3d_device_end_scene(device->wined3d_device);
1248 wined3d_mutex_unlock();
1249
1250 return hr;
1251 }
1252
1253 static HRESULT WINAPI d3d8_device_Clear(IDirect3DDevice8 *iface, DWORD rect_count,
1254 const D3DRECT *rects, DWORD flags, D3DCOLOR color, float z, DWORD stencil)
1255 {
1256 const struct wined3d_color c =
1257 {
1258 ((color >> 16) & 0xff) / 255.0f,
1259 ((color >> 8) & 0xff) / 255.0f,
1260 (color & 0xff) / 255.0f,
1261 ((color >> 24) & 0xff) / 255.0f,
1262 };
1263 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1264 HRESULT hr;
1265
1266 TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %u.\n",
1267 iface, rect_count, rects, flags, color, z, stencil);
1268
1269 wined3d_mutex_lock();
1270 hr = wined3d_device_clear(device->wined3d_device, rect_count, (const RECT *)rects, flags, &c, z, stencil);
1271 wined3d_mutex_unlock();
1272
1273 return hr;
1274 }
1275
1276 static HRESULT WINAPI d3d8_device_SetTransform(IDirect3DDevice8 *iface,
1277 D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
1278 {
1279 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1280
1281 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
1282
1283 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
1284 wined3d_mutex_lock();
1285 wined3d_device_set_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix);
1286 wined3d_mutex_unlock();
1287
1288 return D3D_OK;
1289 }
1290
1291 static HRESULT WINAPI d3d8_device_GetTransform(IDirect3DDevice8 *iface,
1292 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
1293 {
1294 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1295
1296 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
1297
1298 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
1299 wined3d_mutex_lock();
1300 wined3d_device_get_transform(device->wined3d_device, state, (struct wined3d_matrix *)matrix);
1301 wined3d_mutex_unlock();
1302
1303 return D3D_OK;
1304 }
1305
1306 static HRESULT WINAPI d3d8_device_MultiplyTransform(IDirect3DDevice8 *iface,
1307 D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
1308 {
1309 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1310
1311 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
1312
1313 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
1314 wined3d_mutex_lock();
1315 wined3d_device_multiply_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix);
1316 wined3d_mutex_unlock();
1317
1318 return D3D_OK;
1319 }
1320
1321 static HRESULT WINAPI d3d8_device_SetViewport(IDirect3DDevice8 *iface, const D3DVIEWPORT8 *viewport)
1322 {
1323 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1324
1325 TRACE("iface %p, viewport %p.\n", iface, viewport);
1326
1327 /* Note: D3DVIEWPORT8 is compatible with struct wined3d_viewport. */
1328 wined3d_mutex_lock();
1329 wined3d_device_set_viewport(device->wined3d_device, (const struct wined3d_viewport *)viewport);
1330 wined3d_mutex_unlock();
1331
1332 return D3D_OK;
1333 }
1334
1335 static HRESULT WINAPI d3d8_device_GetViewport(IDirect3DDevice8 *iface, D3DVIEWPORT8 *viewport)
1336 {
1337 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1338
1339 TRACE("iface %p, viewport %p.\n", iface, viewport);
1340
1341 /* Note: D3DVIEWPORT8 is compatible with struct wined3d_viewport. */
1342 wined3d_mutex_lock();
1343 wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
1344 wined3d_mutex_unlock();
1345
1346 return D3D_OK;
1347 }
1348
1349 static HRESULT WINAPI d3d8_device_SetMaterial(IDirect3DDevice8 *iface, const D3DMATERIAL8 *material)
1350 {
1351 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1352
1353 TRACE("iface %p, material %p.\n", iface, material);
1354
1355 /* Note: D3DMATERIAL8 is compatible with struct wined3d_material. */
1356 wined3d_mutex_lock();
1357 wined3d_device_set_material(device->wined3d_device, (const struct wined3d_material *)material);
1358 wined3d_mutex_unlock();
1359
1360 return D3D_OK;
1361 }
1362
1363 static HRESULT WINAPI d3d8_device_GetMaterial(IDirect3DDevice8 *iface, D3DMATERIAL8 *material)
1364 {
1365 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1366
1367 TRACE("iface %p, material %p.\n", iface, material);
1368
1369 /* Note: D3DMATERIAL8 is compatible with struct wined3d_material. */
1370 wined3d_mutex_lock();
1371 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
1372 wined3d_mutex_unlock();
1373
1374 return D3D_OK;
1375 }
1376
1377 static HRESULT WINAPI d3d8_device_SetLight(IDirect3DDevice8 *iface, DWORD index, const D3DLIGHT8 *light)
1378 {
1379 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1380 HRESULT hr;
1381
1382 TRACE("iface %p, index %u, light %p.\n", iface, index, light);
1383
1384 /* Note: D3DLIGHT8 is compatible with struct wined3d_light. */
1385 wined3d_mutex_lock();
1386 hr = wined3d_device_set_light(device->wined3d_device, index, (const struct wined3d_light *)light);
1387 wined3d_mutex_unlock();
1388
1389 return hr;
1390 }
1391
1392 static HRESULT WINAPI d3d8_device_GetLight(IDirect3DDevice8 *iface, DWORD index, D3DLIGHT8 *light)
1393 {
1394 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1395 HRESULT hr;
1396
1397 TRACE("iface %p, index %u, light %p.\n", iface, index, light);
1398
1399 /* Note: D3DLIGHT8 is compatible with struct wined3d_light. */
1400 wined3d_mutex_lock();
1401 hr = wined3d_device_get_light(device->wined3d_device, index, (struct wined3d_light *)light);
1402 wined3d_mutex_unlock();
1403
1404 return hr;
1405 }
1406
1407 static HRESULT WINAPI d3d8_device_LightEnable(IDirect3DDevice8 *iface, DWORD index, BOOL enable)
1408 {
1409 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1410 HRESULT hr;
1411
1412 TRACE("iface %p, index %u, enable %#x.\n", iface, index, enable);
1413
1414 wined3d_mutex_lock();
1415 hr = wined3d_device_set_light_enable(device->wined3d_device, index, enable);
1416 wined3d_mutex_unlock();
1417
1418 return hr;
1419 }
1420
1421 static HRESULT WINAPI d3d8_device_GetLightEnable(IDirect3DDevice8 *iface, DWORD index, BOOL *enable)
1422 {
1423 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1424 HRESULT hr;
1425
1426 TRACE("iface %p, index %u, enable %p.\n", iface, index, enable);
1427
1428 wined3d_mutex_lock();
1429 hr = wined3d_device_get_light_enable(device->wined3d_device, index, enable);
1430 wined3d_mutex_unlock();
1431
1432 return hr;
1433 }
1434
1435 static HRESULT WINAPI d3d8_device_SetClipPlane(IDirect3DDevice8 *iface, DWORD index, const float *plane)
1436 {
1437 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1438 HRESULT hr;
1439
1440 TRACE("iface %p, index %u, plane %p.\n", iface, index, plane);
1441
1442 wined3d_mutex_lock();
1443 hr = wined3d_device_set_clip_plane(device->wined3d_device, index, (const struct wined3d_vec4 *)plane);
1444 wined3d_mutex_unlock();
1445
1446 return hr;
1447 }
1448
1449 static HRESULT WINAPI d3d8_device_GetClipPlane(IDirect3DDevice8 *iface, DWORD index, float *plane)
1450 {
1451 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1452 HRESULT hr;
1453
1454 TRACE("iface %p, index %u, plane %p.\n", iface, index, plane);
1455
1456 wined3d_mutex_lock();
1457 hr = wined3d_device_get_clip_plane(device->wined3d_device, index, (struct wined3d_vec4 *)plane);
1458 wined3d_mutex_unlock();
1459
1460 return hr;
1461 }
1462
1463 static HRESULT WINAPI d3d8_device_SetRenderState(IDirect3DDevice8 *iface,
1464 D3DRENDERSTATETYPE state, DWORD value)
1465 {
1466 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1467
1468 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
1469
1470 wined3d_mutex_lock();
1471 switch (state)
1472 {
1473 case D3DRS_ZBIAS:
1474 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
1475 break;
1476
1477 default:
1478 wined3d_device_set_render_state(device->wined3d_device, state, value);
1479 }
1480 wined3d_mutex_unlock();
1481
1482 return D3D_OK;
1483 }
1484
1485 static HRESULT WINAPI d3d8_device_GetRenderState(IDirect3DDevice8 *iface,
1486 D3DRENDERSTATETYPE state, DWORD *value)
1487 {
1488 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1489
1490 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
1491
1492 wined3d_mutex_lock();
1493 switch (state)
1494 {
1495 case D3DRS_ZBIAS:
1496 *value = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS);
1497 break;
1498
1499 default:
1500 *value = wined3d_device_get_render_state(device->wined3d_device, state);
1501 }
1502 wined3d_mutex_unlock();
1503
1504 return D3D_OK;
1505 }
1506
1507 static HRESULT WINAPI d3d8_device_BeginStateBlock(IDirect3DDevice8 *iface)
1508 {
1509 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1510 HRESULT hr;
1511
1512 TRACE("iface %p.\n", iface);
1513
1514 wined3d_mutex_lock();
1515 hr = wined3d_device_begin_stateblock(device->wined3d_device);
1516 wined3d_mutex_unlock();
1517
1518 return hr;
1519 }
1520
1521 static HRESULT WINAPI d3d8_device_EndStateBlock(IDirect3DDevice8 *iface, DWORD *token)
1522 {
1523 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1524 struct wined3d_stateblock *stateblock;
1525 HRESULT hr;
1526
1527 TRACE("iface %p, token %p.\n", iface, token);
1528
1529 /* Tell wineD3D to endstateblock before anything else (in case we run out
1530 * of memory later and cause locking problems)
1531 */
1532 wined3d_mutex_lock();
1533 hr = wined3d_device_end_stateblock(device->wined3d_device, &stateblock);
1534 if (FAILED(hr))
1535 {
1536 WARN("IWineD3DDevice_EndStateBlock returned an error\n");
1537 wined3d_mutex_unlock();
1538 return hr;
1539 }
1540
1541 *token = d3d8_allocate_handle(&device->handle_table, stateblock, D3D8_HANDLE_SB);
1542 wined3d_mutex_unlock();
1543
1544 if (*token == D3D8_INVALID_HANDLE)
1545 {
1546 ERR("Failed to create a handle\n");
1547 wined3d_mutex_lock();
1548 wined3d_stateblock_decref(stateblock);
1549 wined3d_mutex_unlock();
1550 return E_FAIL;
1551 }
1552 ++*token;
1553
1554 TRACE("Returning %#x (%p).\n", *token, stateblock);
1555
1556 return hr;
1557 }
1558
1559 static HRESULT WINAPI d3d8_device_ApplyStateBlock(IDirect3DDevice8 *iface, DWORD token)
1560 {
1561 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1562 struct wined3d_stateblock *stateblock;
1563
1564 TRACE("iface %p, token %#x.\n", iface, token);
1565
1566 if (!token)
1567 return D3D_OK;
1568
1569 wined3d_mutex_lock();
1570 stateblock = d3d8_get_object(&device->handle_table, token - 1, D3D8_HANDLE_SB);
1571 if (!stateblock)
1572 {
1573 WARN("Invalid handle (%#x) passed.\n", token);
1574 wined3d_mutex_unlock();
1575 return D3DERR_INVALIDCALL;
1576 }
1577 wined3d_stateblock_apply(stateblock);
1578 wined3d_mutex_unlock();
1579
1580 return D3D_OK;
1581 }
1582
1583 static HRESULT WINAPI d3d8_device_CaptureStateBlock(IDirect3DDevice8 *iface, DWORD token)
1584 {
1585 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1586 struct wined3d_stateblock *stateblock;
1587
1588 TRACE("iface %p, token %#x.\n", iface, token);
1589
1590 wined3d_mutex_lock();
1591 stateblock = d3d8_get_object(&device->handle_table, token - 1, D3D8_HANDLE_SB);
1592 if (!stateblock)
1593 {
1594 WARN("Invalid handle (%#x) passed.\n", token);
1595 wined3d_mutex_unlock();
1596 return D3DERR_INVALIDCALL;
1597 }
1598 wined3d_stateblock_capture(stateblock);
1599 wined3d_mutex_unlock();
1600
1601 return D3D_OK;
1602 }
1603
1604 static HRESULT WINAPI d3d8_device_DeleteStateBlock(IDirect3DDevice8 *iface, DWORD token)
1605 {
1606 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1607 struct wined3d_stateblock *stateblock;
1608
1609 TRACE("iface %p, token %#x.\n", iface, token);
1610
1611 wined3d_mutex_lock();
1612 stateblock = d3d8_free_handle(&device->handle_table, token - 1, D3D8_HANDLE_SB);
1613
1614 if (!stateblock)
1615 {
1616 WARN("Invalid handle (%#x) passed.\n", token);
1617 wined3d_mutex_unlock();
1618 return D3DERR_INVALIDCALL;
1619 }
1620
1621 if (wined3d_stateblock_decref(stateblock))
1622 {
1623 ERR("Stateblock %p has references left, this shouldn't happen.\n", stateblock);
1624 }
1625 wined3d_mutex_unlock();
1626
1627 return D3D_OK;
1628 }
1629
1630 static HRESULT WINAPI d3d8_device_CreateStateBlock(IDirect3DDevice8 *iface,
1631 D3DSTATEBLOCKTYPE type, DWORD *handle)
1632 {
1633 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1634 struct wined3d_stateblock *stateblock;
1635 HRESULT hr;
1636
1637 TRACE("iface %p, type %#x, handle %p.\n", iface, type, handle);
1638
1639 if (type != D3DSBT_ALL
1640 && type != D3DSBT_PIXELSTATE
1641 && type != D3DSBT_VERTEXSTATE)
1642 {
1643 WARN("Unexpected stateblock type, returning D3DERR_INVALIDCALL\n");
1644 return D3DERR_INVALIDCALL;
1645 }
1646
1647 wined3d_mutex_lock();
1648 hr = wined3d_stateblock_create(device->wined3d_device, (enum wined3d_stateblock_type)type, &stateblock);
1649 if (FAILED(hr))
1650 {
1651 wined3d_mutex_unlock();
1652 ERR("IWineD3DDevice_CreateStateBlock failed, hr %#x\n", hr);
1653 return hr;
1654 }
1655
1656 *handle = d3d8_allocate_handle(&device->handle_table, stateblock, D3D8_HANDLE_SB);
1657 wined3d_mutex_unlock();
1658
1659 if (*handle == D3D8_INVALID_HANDLE)
1660 {
1661 ERR("Failed to allocate a handle.\n");
1662 wined3d_mutex_lock();
1663 wined3d_stateblock_decref(stateblock);
1664 wined3d_mutex_unlock();
1665 return E_FAIL;
1666 }
1667 ++*handle;
1668
1669 TRACE("Returning %#x (%p).\n", *handle, stateblock);
1670
1671 return hr;
1672 }
1673
1674 static HRESULT WINAPI d3d8_device_SetClipStatus(IDirect3DDevice8 *iface, const D3DCLIPSTATUS8 *clip_status)
1675 {
1676 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1677 HRESULT hr;
1678
1679 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
1680 /* FIXME: Verify that D3DCLIPSTATUS8 ~= struct wined3d_clip_status. */
1681
1682 wined3d_mutex_lock();
1683 hr = wined3d_device_set_clip_status(device->wined3d_device, (const struct wined3d_clip_status *)clip_status);
1684 wined3d_mutex_unlock();
1685
1686 return hr;
1687 }
1688
1689 static HRESULT WINAPI d3d8_device_GetClipStatus(IDirect3DDevice8 *iface, D3DCLIPSTATUS8 *clip_status)
1690 {
1691 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1692 HRESULT hr;
1693
1694 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
1695
1696 wined3d_mutex_lock();
1697 hr = wined3d_device_get_clip_status(device->wined3d_device, (struct wined3d_clip_status *)clip_status);
1698 wined3d_mutex_unlock();
1699
1700 return hr;
1701 }
1702
1703 static HRESULT WINAPI d3d8_device_GetTexture(IDirect3DDevice8 *iface, DWORD stage, IDirect3DBaseTexture8 **texture)
1704 {
1705 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1706 struct wined3d_texture *wined3d_texture;
1707 struct d3d8_texture *texture_impl;
1708
1709 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
1710
1711 if (!texture)
1712 return D3DERR_INVALIDCALL;
1713
1714 wined3d_mutex_lock();
1715 if ((wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
1716 {
1717 texture_impl = wined3d_texture_get_parent(wined3d_texture);
1718 *texture = &texture_impl->IDirect3DBaseTexture8_iface;
1719 IDirect3DBaseTexture8_AddRef(*texture);
1720 }
1721 else
1722 {
1723 *texture = NULL;
1724 }
1725 wined3d_mutex_unlock();
1726
1727 return D3D_OK;
1728 }
1729
1730 static HRESULT WINAPI d3d8_device_SetTexture(IDirect3DDevice8 *iface, DWORD stage, IDirect3DBaseTexture8 *texture)
1731 {
1732 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1733 struct d3d8_texture *texture_impl;
1734 HRESULT hr;
1735
1736 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
1737
1738 texture_impl = unsafe_impl_from_IDirect3DBaseTexture8(texture);
1739
1740 wined3d_mutex_lock();
1741 hr = wined3d_device_set_texture(device->wined3d_device, stage,
1742 texture_impl ? texture_impl->wined3d_texture : NULL);
1743 wined3d_mutex_unlock();
1744
1745 return hr;
1746 }
1747
1748 static const struct tss_lookup
1749 {
1750 BOOL sampler_state;
1751 enum wined3d_texture_stage_state state;
1752 }
1753 tss_lookup[] =
1754 {
1755 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
1756 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
1757 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
1758 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
1759 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
1760 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
1761 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
1762 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
1763 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
1764 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
1765 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
1766 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
1767 {FALSE, WINED3D_TSS_INVALID}, /* 12, unused */
1768 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
1769 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
1770 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
1771 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
1772 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
1773 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
1774 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
1775 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
1776 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
1777 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
1778 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
1779 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
1780 {TRUE, WINED3D_SAMP_ADDRESS_W}, /* 25, D3DTSS_ADDRESSW */
1781 {FALSE, WINED3D_TSS_COLOR_ARG0}, /* 26, D3DTSS_COLORARG0 */
1782 {FALSE, WINED3D_TSS_ALPHA_ARG0}, /* 27, D3DTSS_ALPHAARG0 */
1783 {FALSE, WINED3D_TSS_RESULT_ARG}, /* 28, D3DTSS_RESULTARG */
1784 };
1785
1786 static HRESULT WINAPI d3d8_device_GetTextureStageState(IDirect3DDevice8 *iface,
1787 DWORD stage, D3DTEXTURESTAGESTATETYPE Type, DWORD *value)
1788 {
1789 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1790 const struct tss_lookup *l;
1791
1792 TRACE("iface %p, stage %u, state %#x, value %p.\n", iface, stage, Type, value);
1793
1794 if (Type >= sizeof(tss_lookup) / sizeof(*tss_lookup))
1795 {
1796 WARN("Invalid Type %#x passed.\n", Type);
1797 return D3D_OK;
1798 }
1799
1800 l = &tss_lookup[Type];
1801
1802 wined3d_mutex_lock();
1803 if (l->sampler_state)
1804 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->state);
1805 else
1806 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->state);
1807 wined3d_mutex_unlock();
1808
1809 return D3D_OK;
1810 }
1811
1812 static HRESULT WINAPI d3d8_device_SetTextureStageState(IDirect3DDevice8 *iface,
1813 DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value)
1814 {
1815 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1816 const struct tss_lookup *l;
1817
1818 TRACE("iface %p, stage %u, state %#x, value %#x.\n", iface, stage, type, value);
1819
1820 if (type >= sizeof(tss_lookup) / sizeof(*tss_lookup))
1821 {
1822 WARN("Invalid type %#x passed.\n", type);
1823 return D3D_OK;
1824 }
1825
1826 l = &tss_lookup[type];
1827
1828 wined3d_mutex_lock();
1829 if (l->sampler_state)
1830 wined3d_device_set_sampler_state(device->wined3d_device, stage, l->state, value);
1831 else
1832 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->state, value);
1833 wined3d_mutex_unlock();
1834
1835 return D3D_OK;
1836 }
1837
1838 static HRESULT WINAPI d3d8_device_ValidateDevice(IDirect3DDevice8 *iface, DWORD *pass_count)
1839 {
1840 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1841 HRESULT hr;
1842
1843 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
1844
1845 wined3d_mutex_lock();
1846 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
1847 wined3d_mutex_unlock();
1848
1849 return hr;
1850 }
1851
1852 static HRESULT WINAPI d3d8_device_GetInfo(IDirect3DDevice8 *iface,
1853 DWORD info_id, void *info, DWORD info_size)
1854 {
1855 FIXME("iface %p, info_id %#x, info %p, info_size %u stub!\n", iface, info_id, info, info_size);
1856
1857 return D3D_OK;
1858 }
1859
1860 static HRESULT WINAPI d3d8_device_SetPaletteEntries(IDirect3DDevice8 *iface,
1861 UINT palette_idx, const PALETTEENTRY *entries)
1862 {
1863 WARN("iface %p, palette_idx %u, entries %p unimplemented\n", iface, palette_idx, entries);
1864
1865 /* GPUs stopped supporting palettized textures with the Shader Model 1 generation. Wined3d
1866 * does not have a d3d8/9-style palette API */
1867
1868 return D3D_OK;
1869 }
1870
1871 static HRESULT WINAPI d3d8_device_GetPaletteEntries(IDirect3DDevice8 *iface,
1872 UINT palette_idx, PALETTEENTRY *entries)
1873 {
1874 FIXME("iface %p, palette_idx %u, entries %p unimplemented.\n", iface, palette_idx, entries);
1875
1876 return D3DERR_INVALIDCALL;
1877 }
1878
1879 static HRESULT WINAPI d3d8_device_SetCurrentTexturePalette(IDirect3DDevice8 *iface, UINT palette_idx)
1880 {
1881 WARN("iface %p, palette_idx %u unimplemented.\n", iface, palette_idx);
1882
1883 return D3D_OK;
1884 }
1885
1886 static HRESULT WINAPI d3d8_device_GetCurrentTexturePalette(IDirect3DDevice8 *iface, UINT *palette_idx)
1887 {
1888 FIXME("iface %p, palette_idx %p unimplemented.\n", iface, palette_idx);
1889
1890 return D3DERR_INVALIDCALL;
1891 }
1892
1893 static HRESULT WINAPI d3d8_device_DrawPrimitive(IDirect3DDevice8 *iface,
1894 D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count)
1895 {
1896 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1897 HRESULT hr;
1898
1899 TRACE("iface %p, primitive_type %#x, start_vertex %u, primitive_count %u.\n",
1900 iface, primitive_type, start_vertex, primitive_count);
1901
1902 wined3d_mutex_lock();
1903 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
1904 hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex,
1905 vertex_count_from_primitive_count(primitive_type, primitive_count));
1906 wined3d_mutex_unlock();
1907
1908 return hr;
1909 }
1910
1911 static HRESULT WINAPI d3d8_device_DrawIndexedPrimitive(IDirect3DDevice8 *iface,
1912 D3DPRIMITIVETYPE primitive_type, UINT min_vertex_idx, UINT vertex_count,
1913 UINT start_idx, UINT primitive_count)
1914 {
1915 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1916 HRESULT hr;
1917
1918 TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, vertex_count %u, start_idx %u, primitive_count %u.\n",
1919 iface, primitive_type, min_vertex_idx, vertex_count, start_idx, primitive_count);
1920
1921 wined3d_mutex_lock();
1922 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
1923 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, start_idx,
1924 vertex_count_from_primitive_count(primitive_type, primitive_count));
1925 wined3d_mutex_unlock();
1926
1927 return hr;
1928 }
1929
1930 /* The caller is responsible for wined3d locking */
1931 static HRESULT d3d8_device_prepare_vertex_buffer(struct d3d8_device *device, UINT min_size)
1932 {
1933 HRESULT hr;
1934
1935 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
1936 {
1937 UINT size = max(device->vertex_buffer_size * 2, min_size);
1938 struct wined3d_buffer *buffer;
1939
1940 TRACE("Growing vertex buffer to %u bytes\n", size);
1941
1942 hr = wined3d_buffer_create_vb(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
1943 WINED3D_POOL_DEFAULT, NULL, &d3d8_null_wined3d_parent_ops, &buffer);
1944 if (FAILED(hr))
1945 {
1946 ERR("(%p) wined3d_buffer_create_vb failed with hr = %08x\n", device, hr);
1947 return hr;
1948 }
1949
1950 if (device->vertex_buffer)
1951 wined3d_buffer_decref(device->vertex_buffer);
1952
1953 device->vertex_buffer = buffer;
1954 device->vertex_buffer_size = size;
1955 device->vertex_buffer_pos = 0;
1956 }
1957 return D3D_OK;
1958 }
1959
1960 static HRESULT WINAPI d3d8_device_DrawPrimitiveUP(IDirect3DDevice8 *iface,
1961 D3DPRIMITIVETYPE primitive_type, UINT primitive_count, const void *data,
1962 UINT stride)
1963 {
1964 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1965 HRESULT hr;
1966 UINT vtx_count = vertex_count_from_primitive_count(primitive_type, primitive_count);
1967 UINT size = vtx_count * stride;
1968 UINT vb_pos, align;
1969 BYTE *buffer_data;
1970
1971 TRACE("iface %p, primitive_type %#x, primitive_count %u, data %p, stride %u.\n",
1972 iface, primitive_type, primitive_count, data, stride);
1973
1974 if (!primitive_count)
1975 {
1976 WARN("primitive_count is 0, returning D3D_OK\n");
1977 return D3D_OK;
1978 }
1979
1980 wined3d_mutex_lock();
1981 hr = d3d8_device_prepare_vertex_buffer(device, size);
1982 if (FAILED(hr))
1983 goto done;
1984
1985 vb_pos = device->vertex_buffer_pos;
1986 align = vb_pos % stride;
1987 if (align) align = stride - align;
1988 if (vb_pos + size + align > device->vertex_buffer_size)
1989 vb_pos = 0;
1990 else
1991 vb_pos += align;
1992
1993 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, size, &buffer_data,
1994 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
1995 if (FAILED(hr))
1996 goto done;
1997 memcpy(buffer_data, data, size);
1998 wined3d_buffer_unmap(device->vertex_buffer);
1999 device->vertex_buffer_pos = vb_pos + size;
2000
2001 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
2002 if (FAILED(hr))
2003 goto done;
2004
2005 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
2006 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vtx_count);
2007 wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0);
2008
2009 done:
2010 wined3d_mutex_unlock();
2011 return hr;
2012 }
2013
2014 /* The caller is responsible for wined3d locking */
2015 static HRESULT d3d8_device_prepare_index_buffer(struct d3d8_device *device, UINT min_size)
2016 {
2017 HRESULT hr;
2018
2019 if (device->index_buffer_size < min_size || !device->index_buffer)
2020 {
2021 UINT size = max(device->index_buffer_size * 2, min_size);
2022 struct wined3d_buffer *buffer;
2023
2024 TRACE("Growing index buffer to %u bytes\n", size);
2025
2026 hr = wined3d_buffer_create_ib(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
2027 WINED3D_POOL_DEFAULT, NULL, &d3d8_null_wined3d_parent_ops, &buffer);
2028 if (FAILED(hr))
2029 {
2030 ERR("(%p) wined3d_buffer_create_ib failed with hr = %08x\n", device, hr);
2031 return hr;
2032 }
2033
2034 if (device->index_buffer)
2035 wined3d_buffer_decref(device->index_buffer);
2036
2037 device->index_buffer = buffer;
2038 device->index_buffer_size = size;
2039 device->index_buffer_pos = 0;
2040 }
2041 return D3D_OK;
2042 }
2043
2044 static HRESULT WINAPI d3d8_device_DrawIndexedPrimitiveUP(IDirect3DDevice8 *iface,
2045 D3DPRIMITIVETYPE primitive_type, UINT min_vertex_idx, UINT vertex_count,
2046 UINT primitive_count, const void *index_data, D3DFORMAT index_format,
2047 const void *vertex_data, UINT vertex_stride)
2048 {
2049 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2050 HRESULT hr;
2051 BYTE *buffer_data;
2052
2053 UINT idx_count = vertex_count_from_primitive_count(primitive_type, primitive_count);
2054 UINT idx_fmt_size = index_format == D3DFMT_INDEX16 ? 2 : 4;
2055 UINT idx_size = idx_count * idx_fmt_size;
2056 UINT ib_pos;
2057
2058 UINT vtx_size = vertex_count * vertex_stride;
2059 UINT vb_pos, align;
2060
2061 TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, vertex_count %u, primitive_count %u,\n"
2062 "index_data %p, index_format %#x, vertex_data %p, vertex_stride %u.\n",
2063 iface, primitive_type, min_vertex_idx, vertex_count, primitive_count,
2064 index_data, index_format, vertex_data, vertex_stride);
2065
2066 if (!primitive_count)
2067 {
2068 WARN("primitive_count is 0, returning D3D_OK\n");
2069 return D3D_OK;
2070 }
2071
2072 wined3d_mutex_lock();
2073
2074 hr = d3d8_device_prepare_vertex_buffer(device, vtx_size);
2075 if (FAILED(hr))
2076 goto done;
2077
2078 vb_pos = device->vertex_buffer_pos;
2079 align = vb_pos % vertex_stride;
2080 if (align) align = vertex_stride - align;
2081 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
2082 vb_pos = 0;
2083 else
2084 vb_pos += align;
2085
2086 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_size, &buffer_data,
2087 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
2088 if (FAILED(hr))
2089 goto done;
2090 memcpy(buffer_data, vertex_data, vtx_size);
2091 wined3d_buffer_unmap(device->vertex_buffer);
2092 device->vertex_buffer_pos = vb_pos + vtx_size;
2093
2094 hr = d3d8_device_prepare_index_buffer(device, idx_size);
2095 if (FAILED(hr))
2096 goto done;
2097
2098 ib_pos = device->index_buffer_pos;
2099 align = ib_pos % idx_fmt_size;
2100 if (align) align = idx_fmt_size - align;
2101 if (ib_pos + idx_size + align > device->index_buffer_size)
2102 ib_pos = 0;
2103 else
2104 ib_pos += align;
2105
2106 hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &buffer_data,
2107 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
2108 if (FAILED(hr))
2109 goto done;
2110 memcpy(buffer_data, index_data, idx_size);
2111 wined3d_buffer_unmap(device->index_buffer);
2112 device->index_buffer_pos = ib_pos + idx_size;
2113
2114 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vertex_stride);
2115 if (FAILED(hr))
2116 goto done;
2117
2118 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer,
2119 wined3dformat_from_d3dformat(index_format));
2120 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vertex_stride);
2121
2122 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
2123 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / idx_fmt_size, idx_count);
2124
2125 wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0);
2126 wined3d_device_set_index_buffer(device->wined3d_device, NULL, WINED3DFMT_UNKNOWN);
2127 wined3d_device_set_base_vertex_index(device->wined3d_device, 0);
2128
2129 done:
2130 wined3d_mutex_unlock();
2131 return hr;
2132 }
2133
2134 static HRESULT WINAPI d3d8_device_ProcessVertices(IDirect3DDevice8 *iface, UINT src_start_idx,
2135 UINT dst_idx, UINT vertex_count, IDirect3DVertexBuffer8 *dst_buffer, DWORD flags)
2136 {
2137 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2138 struct d3d8_vertexbuffer *dst = unsafe_impl_from_IDirect3DVertexBuffer8(dst_buffer);
2139 HRESULT hr;
2140
2141 TRACE("iface %p, src_start_idx %u, dst_idx %u, vertex_count %u, dst_buffer %p, flags %#x.\n",
2142 iface, src_start_idx, dst_idx, vertex_count, dst_buffer, flags);
2143
2144 wined3d_mutex_lock();
2145 hr = wined3d_device_process_vertices(device->wined3d_device, src_start_idx, dst_idx,
2146 vertex_count, dst->wined3d_buffer, NULL, flags, dst->fvf);
2147 wined3d_mutex_unlock();
2148
2149 return hr;
2150 }
2151
2152 static HRESULT WINAPI d3d8_device_CreateVertexShader(IDirect3DDevice8 *iface,
2153 const DWORD *declaration, const DWORD *byte_code, DWORD *shader, DWORD usage)
2154 {
2155 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2156 struct d3d8_vertex_shader *object;
2157 DWORD shader_handle;
2158 DWORD handle;
2159 HRESULT hr;
2160
2161 TRACE("iface %p, declaration %p, byte_code %p, shader %p, usage %#x.\n",
2162 iface, declaration, byte_code, shader, usage);
2163
2164 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2165 if (!object)
2166 {
2167 *shader = 0;
2168 return E_OUTOFMEMORY;
2169 }
2170
2171 wined3d_mutex_lock();
2172 handle = d3d8_allocate_handle(&device->handle_table, object, D3D8_HANDLE_VS);
2173 wined3d_mutex_unlock();
2174 if (handle == D3D8_INVALID_HANDLE)
2175 {
2176 ERR("Failed to allocate vertex shader handle.\n");
2177 HeapFree(GetProcessHeap(), 0, object);
2178 *shader = 0;
2179 return E_OUTOFMEMORY;
2180 }
2181
2182 shader_handle = handle + VS_HIGHESTFIXEDFXF + 1;
2183
2184 hr = d3d8_vertex_shader_init(object, device, declaration, byte_code, shader_handle, usage);
2185 if (FAILED(hr))
2186 {
2187 WARN("Failed to initialize vertex shader, hr %#x.\n", hr);
2188 wined3d_mutex_lock();
2189 d3d8_free_handle(&device->handle_table, handle, D3D8_HANDLE_VS);
2190 wined3d_mutex_unlock();
2191 HeapFree(GetProcessHeap(), 0, object);
2192 *shader = 0;
2193 return hr;
2194 }
2195
2196 TRACE("Created vertex shader %p (handle %#x).\n", object, shader_handle);
2197 *shader = shader_handle;
2198
2199 return D3D_OK;
2200 }
2201
2202 static struct d3d8_vertex_declaration *d3d8_device_get_fvf_declaration(struct d3d8_device *device, DWORD fvf)
2203 {
2204 struct d3d8_vertex_declaration *d3d8_declaration;
2205 struct FvfToDecl *convertedDecls = device->decls;
2206 int p, low, high; /* deliberately signed */
2207 HRESULT hr;
2208
2209 TRACE("Searching for declaration for fvf %08x... ", fvf);
2210
2211 low = 0;
2212 high = device->numConvertedDecls - 1;
2213 while (low <= high)
2214 {
2215 p = (low + high) >> 1;
2216 TRACE("%d ", p);
2217
2218 if (convertedDecls[p].fvf == fvf)
2219 {
2220 TRACE("found %p\n", convertedDecls[p].declaration);
2221 return convertedDecls[p].declaration;
2222 }
2223
2224 if (convertedDecls[p].fvf < fvf)
2225 low = p + 1;
2226 else
2227 high = p - 1;
2228 }
2229 TRACE("not found. Creating and inserting at position %d.\n", low);
2230
2231 if (!(d3d8_declaration = HeapAlloc(GetProcessHeap(), 0, sizeof(*d3d8_declaration))))
2232 return NULL;
2233
2234 if (FAILED(hr = d3d8_vertex_declaration_init_fvf(d3d8_declaration, device, fvf)))
2235 {
2236 WARN("Failed to initialize vertex declaration, hr %#x.\n", hr);
2237 HeapFree(GetProcessHeap(), 0, d3d8_declaration);
2238 return NULL;
2239 }
2240
2241 if (device->declArraySize == device->numConvertedDecls)
2242 {
2243 UINT grow = device->declArraySize / 2;
2244
2245 convertedDecls = HeapReAlloc(GetProcessHeap(), 0, convertedDecls,
2246 sizeof(*convertedDecls) * (device->numConvertedDecls + grow));
2247 if (!convertedDecls)
2248 {
2249 d3d8_vertex_declaration_destroy(d3d8_declaration);
2250 return NULL;
2251 }
2252 device->decls = convertedDecls;
2253 device->declArraySize += grow;
2254 }
2255
2256 memmove(convertedDecls + low + 1, convertedDecls + low,
2257 sizeof(*convertedDecls) * (device->numConvertedDecls - low));
2258 convertedDecls[low].declaration = d3d8_declaration;
2259 convertedDecls[low].fvf = fvf;
2260 ++device->numConvertedDecls;
2261
2262 TRACE("Returning %p. %u decls in array.\n", d3d8_declaration, device->numConvertedDecls);
2263
2264 return d3d8_declaration;
2265 }
2266
2267 static HRESULT WINAPI d3d8_device_SetVertexShader(IDirect3DDevice8 *iface, DWORD shader)
2268 {
2269 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2270 struct d3d8_vertex_shader *shader_impl;
2271
2272 TRACE("iface %p, shader %#x.\n", iface, shader);
2273
2274 if (VS_HIGHESTFIXEDFXF >= shader)
2275 {
2276 TRACE("Setting FVF, %#x\n", shader);
2277
2278 wined3d_mutex_lock();
2279 wined3d_device_set_vertex_declaration(device->wined3d_device,
2280 d3d8_device_get_fvf_declaration(device, shader)->wined3d_vertex_declaration);
2281 wined3d_device_set_vertex_shader(device->wined3d_device, NULL);
2282 wined3d_mutex_unlock();
2283
2284 return D3D_OK;
2285 }
2286
2287 TRACE("Setting shader\n");
2288
2289 wined3d_mutex_lock();
2290 if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS)))
2291 {
2292 WARN("Invalid handle (%#x) passed.\n", shader);
2293 wined3d_mutex_unlock();
2294
2295 return D3DERR_INVALIDCALL;
2296 }
2297
2298 wined3d_device_set_vertex_declaration(device->wined3d_device,
2299 shader_impl->vertex_declaration->wined3d_vertex_declaration);
2300 wined3d_device_set_vertex_shader(device->wined3d_device, shader_impl->wined3d_shader);
2301 wined3d_mutex_unlock();
2302
2303 return D3D_OK;
2304 }
2305
2306 static HRESULT WINAPI d3d8_device_GetVertexShader(IDirect3DDevice8 *iface, DWORD *shader)
2307 {
2308 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2309 struct wined3d_vertex_declaration *wined3d_declaration;
2310 struct d3d8_vertex_declaration *d3d8_declaration;
2311
2312 TRACE("iface %p, shader %p.\n", iface, shader);
2313
2314 wined3d_mutex_lock();
2315 if ((wined3d_declaration = wined3d_device_get_vertex_declaration(device->wined3d_device)))
2316 {
2317 d3d8_declaration = wined3d_vertex_declaration_get_parent(wined3d_declaration);
2318 *shader = d3d8_declaration->shader_handle;
2319 }
2320 else
2321 {
2322 *shader = 0;
2323 }
2324 wined3d_mutex_unlock();
2325
2326 TRACE("Returning %#x.\n", *shader);
2327
2328 return D3D_OK;
2329 }
2330
2331 static HRESULT WINAPI d3d8_device_DeleteVertexShader(IDirect3DDevice8 *iface, DWORD shader)
2332 {
2333 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2334 struct d3d8_vertex_shader *shader_impl;
2335
2336 TRACE("iface %p, shader %#x.\n", iface, shader);
2337
2338 wined3d_mutex_lock();
2339 if (!(shader_impl = d3d8_free_handle(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS)))
2340 {
2341 WARN("Invalid handle (%#x) passed.\n", shader);
2342 wined3d_mutex_unlock();
2343
2344 return D3DERR_INVALIDCALL;
2345 }
2346
2347 if (shader_impl->wined3d_shader
2348 && wined3d_device_get_vertex_shader(device->wined3d_device) == shader_impl->wined3d_shader)
2349 IDirect3DDevice8_SetVertexShader(iface, 0);
2350
2351 wined3d_mutex_unlock();
2352
2353 d3d8_vertex_shader_destroy(shader_impl);
2354
2355 return D3D_OK;
2356 }
2357
2358 static HRESULT WINAPI d3d8_device_SetVertexShaderConstant(IDirect3DDevice8 *iface,
2359 DWORD start_register, const void *data, DWORD count)
2360 {
2361 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2362 HRESULT hr;
2363
2364 TRACE("iface %p, start_register %u, data %p, count %u.\n",
2365 iface, start_register, data, count);
2366
2367 if (start_register + count > D3D8_MAX_VERTEX_SHADER_CONSTANTF)
2368 {
2369 WARN("Trying to access %u constants, but d3d8 only supports %u\n",
2370 start_register + count, D3D8_MAX_VERTEX_SHADER_CONSTANTF);
2371 return D3DERR_INVALIDCALL;
2372 }
2373
2374 wined3d_mutex_lock();
2375 hr = wined3d_device_set_vs_consts_f(device->wined3d_device, start_register, data, count);
2376 wined3d_mutex_unlock();
2377
2378 return hr;
2379 }
2380
2381 static HRESULT WINAPI d3d8_device_GetVertexShaderConstant(IDirect3DDevice8 *iface,
2382 DWORD start_register, void *data, DWORD count)
2383 {
2384 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2385 HRESULT hr;
2386
2387 TRACE("iface %p, start_register %u, data %p, count %u.\n",
2388 iface, start_register, data, count);
2389
2390 if (start_register + count > D3D8_MAX_VERTEX_SHADER_CONSTANTF)
2391 {
2392 WARN("Trying to access %u constants, but d3d8 only supports %u\n",
2393 start_register + count, D3D8_MAX_VERTEX_SHADER_CONSTANTF);
2394 return D3DERR_INVALIDCALL;
2395 }
2396
2397 wined3d_mutex_lock();
2398 hr = wined3d_device_get_vs_consts_f(device->wined3d_device, start_register, data, count);
2399 wined3d_mutex_unlock();
2400
2401 return hr;
2402 }
2403
2404 static HRESULT WINAPI d3d8_device_GetVertexShaderDeclaration(IDirect3DDevice8 *iface,
2405 DWORD shader, void *data, DWORD *data_size)
2406 {
2407 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2408 struct d3d8_vertex_declaration *declaration;
2409 struct d3d8_vertex_shader *shader_impl;
2410
2411 TRACE("iface %p, shader %#x, data %p, data_size %p.\n",
2412 iface, shader, data, data_size);
2413
2414 wined3d_mutex_lock();
2415 shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS);
2416 wined3d_mutex_unlock();
2417
2418 if (!shader_impl)
2419 {
2420 WARN("Invalid handle (%#x) passed.\n", shader);
2421 return D3DERR_INVALIDCALL;
2422 }
2423 declaration = shader_impl->vertex_declaration;
2424
2425 if (!data)
2426 {
2427 *data_size = declaration->elements_size;
2428 return D3D_OK;
2429 }
2430
2431 /* MSDN claims that if *data_size is smaller than the required size
2432 * we should write the required size and return D3DERR_MOREDATA.
2433 * That's not actually true. */
2434 if (*data_size < declaration->elements_size)
2435 return D3DERR_INVALIDCALL;
2436
2437 memcpy(data, declaration->elements, declaration->elements_size);
2438
2439 return D3D_OK;
2440 }
2441
2442 static HRESULT WINAPI d3d8_device_GetVertexShaderFunction(IDirect3DDevice8 *iface,
2443 DWORD shader, void *data, DWORD *data_size)
2444 {
2445 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2446 struct d3d8_vertex_shader *shader_impl = NULL;
2447 HRESULT hr;
2448
2449 TRACE("iface %p, shader %#x, data %p, data_size %p.\n",
2450 iface, shader, data, data_size);
2451
2452 wined3d_mutex_lock();
2453 if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS)))
2454 {
2455 WARN("Invalid handle (%#x) passed.\n", shader);
2456 wined3d_mutex_unlock();
2457
2458 return D3DERR_INVALIDCALL;
2459 }
2460
2461 if (!shader_impl->wined3d_shader)
2462 {
2463 wined3d_mutex_unlock();
2464 *data_size = 0;
2465 return D3D_OK;
2466 }
2467
2468 hr = wined3d_shader_get_byte_code(shader_impl->wined3d_shader, data, data_size);
2469 wined3d_mutex_unlock();
2470
2471 return hr;
2472 }
2473
2474 static HRESULT WINAPI d3d8_device_SetIndices(IDirect3DDevice8 *iface,
2475 IDirect3DIndexBuffer8 *buffer, UINT base_vertex_idx)
2476 {
2477 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2478 struct d3d8_indexbuffer *ib = unsafe_impl_from_IDirect3DIndexBuffer8(buffer);
2479
2480 TRACE("iface %p, buffer %p, base_vertex_idx %u.\n", iface, buffer, base_vertex_idx);
2481
2482 /* WineD3D takes an INT(due to d3d9), but d3d8 uses UINTs. Do I have to add a check here that
2483 * the UINT doesn't cause an overflow in the INT? It seems rather unlikely because such large
2484 * vertex buffers can't be created to address them with an index that requires the 32nd bit
2485 * (4 Byte minimum vertex size * 2^31-1 -> 8 gb buffer. The index sign would be the least
2486 * problem)
2487 */
2488 wined3d_mutex_lock();
2489 wined3d_device_set_base_vertex_index(device->wined3d_device, base_vertex_idx);
2490 wined3d_device_set_index_buffer(device->wined3d_device,
2491 ib ? ib->wined3d_buffer : NULL,
2492 ib ? ib->format : WINED3DFMT_UNKNOWN);
2493 wined3d_mutex_unlock();
2494
2495 return D3D_OK;
2496 }
2497
2498 static HRESULT WINAPI d3d8_device_GetIndices(IDirect3DDevice8 *iface,
2499 IDirect3DIndexBuffer8 **buffer, UINT *base_vertex_index)
2500 {
2501 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2502 enum wined3d_format_id wined3d_format;
2503 struct wined3d_buffer *wined3d_buffer;
2504 struct d3d8_indexbuffer *buffer_impl;
2505
2506 TRACE("iface %p, buffer %p, base_vertex_index %p.\n", iface, buffer, base_vertex_index);
2507
2508 if (!buffer)
2509 return D3DERR_INVALIDCALL;
2510
2511 /* The case from UINT to INT is safe because d3d8 will never set negative values */
2512 wined3d_mutex_lock();
2513 *base_vertex_index = wined3d_device_get_base_vertex_index(device->wined3d_device);
2514 if ((wined3d_buffer = wined3d_device_get_index_buffer(device->wined3d_device, &wined3d_format)))
2515 {
2516 buffer_impl = wined3d_buffer_get_parent(wined3d_buffer);
2517 *buffer = &buffer_impl->IDirect3DIndexBuffer8_iface;
2518 IDirect3DIndexBuffer8_AddRef(*buffer);
2519 }
2520 else
2521 {
2522 *buffer = NULL;
2523 }
2524 wined3d_mutex_unlock();
2525
2526 return D3D_OK;
2527 }
2528
2529 static HRESULT WINAPI d3d8_device_CreatePixelShader(IDirect3DDevice8 *iface,
2530 const DWORD *byte_code, DWORD *shader)
2531 {
2532 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2533 struct d3d8_pixel_shader *object;
2534 DWORD shader_handle;
2535 DWORD handle;
2536 HRESULT hr;
2537
2538 TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader);
2539
2540 if (!shader)
2541 return D3DERR_INVALIDCALL;
2542
2543 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2544 if (!object)
2545 return E_OUTOFMEMORY;
2546
2547 wined3d_mutex_lock();
2548 handle = d3d8_allocate_handle(&device->handle_table, object, D3D8_HANDLE_PS);
2549 wined3d_mutex_unlock();
2550 if (handle == D3D8_INVALID_HANDLE)
2551 {
2552 ERR("Failed to allocate pixel shader handle.\n");
2553 HeapFree(GetProcessHeap(), 0, object);
2554 return E_OUTOFMEMORY;
2555 }
2556
2557 shader_handle = handle + VS_HIGHESTFIXEDFXF + 1;
2558
2559 hr = d3d8_pixel_shader_init(object, device, byte_code, shader_handle);
2560 if (FAILED(hr))
2561 {
2562 WARN("Failed to initialize pixel shader, hr %#x.\n", hr);
2563 wined3d_mutex_lock();
2564 d3d8_free_handle(&device->handle_table, handle, D3D8_HANDLE_PS);
2565 wined3d_mutex_unlock();
2566 HeapFree(GetProcessHeap(), 0, object);
2567 *shader = 0;
2568 return hr;
2569 }
2570
2571 TRACE("Created pixel shader %p (handle %#x).\n", object, shader_handle);
2572 *shader = shader_handle;
2573
2574 return D3D_OK;
2575 }
2576
2577 static HRESULT WINAPI d3d8_device_SetPixelShader(IDirect3DDevice8 *iface, DWORD shader)
2578 {
2579 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2580 struct d3d8_pixel_shader *shader_impl;
2581
2582 TRACE("iface %p, shader %#x.\n", iface, shader);
2583
2584 wined3d_mutex_lock();
2585
2586 if (!shader)
2587 {
2588 wined3d_device_set_pixel_shader(device->wined3d_device, NULL);
2589 wined3d_mutex_unlock();
2590 return D3D_OK;
2591 }
2592
2593 if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS)))
2594 {
2595 WARN("Invalid handle (%#x) passed.\n", shader);
2596 wined3d_mutex_unlock();
2597 return D3DERR_INVALIDCALL;
2598 }
2599
2600 TRACE("Setting shader %p.\n", shader_impl);
2601 wined3d_device_set_pixel_shader(device->wined3d_device, shader_impl->wined3d_shader);
2602 wined3d_mutex_unlock();
2603
2604 return D3D_OK;
2605 }
2606
2607 static HRESULT WINAPI d3d8_device_GetPixelShader(IDirect3DDevice8 *iface, DWORD *shader)
2608 {
2609 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2610 struct wined3d_shader *object;
2611
2612 TRACE("iface %p, shader %p.\n", iface, shader);
2613
2614 if (!shader)
2615 return D3DERR_INVALIDCALL;
2616
2617 wined3d_mutex_lock();
2618 if ((object = wined3d_device_get_pixel_shader(device->wined3d_device)))
2619 {
2620 struct d3d8_pixel_shader *d3d8_shader;
2621 d3d8_shader = wined3d_shader_get_parent(object);
2622 *shader = d3d8_shader->handle;
2623 }
2624 else
2625 {
2626 *shader = 0;
2627 }
2628 wined3d_mutex_unlock();
2629
2630 TRACE("Returning %#x.\n", *shader);
2631
2632 return D3D_OK;
2633 }
2634
2635 static HRESULT WINAPI d3d8_device_DeletePixelShader(IDirect3DDevice8 *iface, DWORD shader)
2636 {
2637 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2638 struct d3d8_pixel_shader *shader_impl;
2639
2640 TRACE("iface %p, shader %#x.\n", iface, shader);
2641
2642 wined3d_mutex_lock();
2643
2644 if (!(shader_impl = d3d8_free_handle(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS)))
2645 {
2646 WARN("Invalid handle (%#x) passed.\n", shader);
2647 wined3d_mutex_unlock();
2648 return D3DERR_INVALIDCALL;
2649 }
2650
2651 if (wined3d_device_get_pixel_shader(device->wined3d_device) == shader_impl->wined3d_shader)
2652 IDirect3DDevice8_SetPixelShader(iface, 0);
2653
2654 wined3d_mutex_unlock();
2655
2656 d3d8_pixel_shader_destroy(shader_impl);
2657
2658 return D3D_OK;
2659 }
2660
2661 static HRESULT WINAPI d3d8_device_SetPixelShaderConstant(IDirect3DDevice8 *iface,
2662 DWORD start_register, const void *data, DWORD count)
2663 {
2664 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2665 HRESULT hr;
2666
2667 TRACE("iface %p, start_register %u, data %p, count %u.\n",
2668 iface, start_register, data, count);
2669
2670 wined3d_mutex_lock();
2671 hr = wined3d_device_set_ps_consts_f(device->wined3d_device, start_register, data, count);
2672 wined3d_mutex_unlock();
2673
2674 return hr;
2675 }
2676
2677 static HRESULT WINAPI d3d8_device_GetPixelShaderConstant(IDirect3DDevice8 *iface,
2678 DWORD start_register, void *data, DWORD count)
2679 {
2680 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2681 HRESULT hr;
2682
2683 TRACE("iface %p, start_register %u, data %p, count %u.\n",
2684 iface, start_register, data, count);
2685
2686 wined3d_mutex_lock();
2687 hr = wined3d_device_get_ps_consts_f(device->wined3d_device, start_register, data, count);
2688 wined3d_mutex_unlock();
2689
2690 return hr;
2691 }
2692
2693 static HRESULT WINAPI d3d8_device_GetPixelShaderFunction(IDirect3DDevice8 *iface,
2694 DWORD shader, void *data, DWORD *data_size)
2695 {
2696 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2697 struct d3d8_pixel_shader *shader_impl = NULL;
2698 HRESULT hr;
2699
2700 TRACE("iface %p, shader %#x, data %p, data_size %p.\n",
2701 iface, shader, data, data_size);
2702
2703 wined3d_mutex_lock();
2704 if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS)))
2705 {
2706 WARN("Invalid handle (%#x) passed.\n", shader);
2707 wined3d_mutex_unlock();
2708
2709 return D3DERR_INVALIDCALL;
2710 }
2711
2712 hr = wined3d_shader_get_byte_code(shader_impl->wined3d_shader, data, data_size);
2713 wined3d_mutex_unlock();
2714
2715 return hr;
2716 }
2717
2718 static HRESULT WINAPI d3d8_device_DrawRectPatch(IDirect3DDevice8 *iface, UINT handle,
2719 const float *segment_count, const D3DRECTPATCH_INFO *patch_info)
2720 {
2721 FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n",
2722 iface, handle, segment_count, patch_info);
2723 return D3D_OK;
2724 }
2725
2726 static HRESULT WINAPI d3d8_device_DrawTriPatch(IDirect3DDevice8 *iface, UINT handle,
2727 const float *segment_count, const D3DTRIPATCH_INFO *patch_info)
2728 {
2729 FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n",
2730 iface, handle, segment_count, patch_info);
2731 return D3D_OK;
2732 }
2733
2734 static HRESULT WINAPI d3d8_device_DeletePatch(IDirect3DDevice8 *iface, UINT handle)
2735 {
2736 FIXME("iface %p, handle %#x unimplemented.\n", iface, handle);
2737 return D3DERR_INVALIDCALL;
2738 }
2739
2740 static HRESULT WINAPI d3d8_device_SetStreamSource(IDirect3DDevice8 *iface,
2741 UINT stream_idx, IDirect3DVertexBuffer8 *buffer, UINT stride)
2742 {
2743 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2744 struct d3d8_vertexbuffer *buffer_impl = unsafe_impl_from_IDirect3DVertexBuffer8(buffer);
2745 HRESULT hr;
2746
2747 TRACE("iface %p, stream_idx %u, buffer %p, stride %u.\n",
2748 iface, stream_idx, buffer, stride);
2749
2750 wined3d_mutex_lock();
2751 hr = wined3d_device_set_stream_source(device->wined3d_device, stream_idx,
2752 buffer_impl ? buffer_impl->wined3d_buffer : NULL, 0, stride);
2753 wined3d_mutex_unlock();
2754
2755 return hr;
2756 }
2757
2758 static HRESULT WINAPI d3d8_device_GetStreamSource(IDirect3DDevice8 *iface,
2759 UINT stream_idx, IDirect3DVertexBuffer8 **buffer, UINT *stride)
2760 {
2761 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2762 struct d3d8_vertexbuffer *buffer_impl;
2763 struct wined3d_buffer *wined3d_buffer = NULL;
2764 HRESULT hr;
2765
2766 TRACE("iface %p, stream_idx %u, buffer %p, stride %p.\n",
2767 iface, stream_idx, buffer, stride);
2768
2769 if (!buffer)
2770 return D3DERR_INVALIDCALL;
2771
2772 wined3d_mutex_lock();
2773 hr = wined3d_device_get_stream_source(device->wined3d_device, stream_idx, &wined3d_buffer, 0, stride);
2774 if (SUCCEEDED(hr) && wined3d_buffer)
2775 {
2776 buffer_impl = wined3d_buffer_get_parent(wined3d_buffer);
2777 *buffer = &buffer_impl->IDirect3DVertexBuffer8_iface;
2778 IDirect3DVertexBuffer8_AddRef(*buffer);
2779 wined3d_buffer_decref(wined3d_buffer);
2780 }
2781 else
2782 {
2783 if (FAILED(hr))
2784 ERR("Failed to get wined3d stream source, hr %#x.\n", hr);
2785 *buffer = NULL;
2786 }
2787 wined3d_mutex_unlock();
2788
2789 return hr;
2790 }
2791
2792 static const struct IDirect3DDevice8Vtbl d3d8_device_vtbl =
2793 {
2794 d3d8_device_QueryInterface,
2795 d3d8_device_AddRef,
2796 d3d8_device_Release,
2797 d3d8_device_TestCooperativeLevel,
2798 d3d8_device_GetAvailableTextureMem,
2799 d3d8_device_ResourceManagerDiscardBytes,
2800 d3d8_device_GetDirect3D,
2801 d3d8_device_GetDeviceCaps,
2802 d3d8_device_GetDisplayMode,
2803 d3d8_device_GetCreationParameters,
2804 d3d8_device_SetCursorProperties,
2805 d3d8_device_SetCursorPosition,
2806 d3d8_device_ShowCursor,
2807 d3d8_device_CreateAdditionalSwapChain,
2808 d3d8_device_Reset,
2809 d3d8_device_Present,
2810 d3d8_device_GetBackBuffer,
2811 d3d8_device_GetRasterStatus,
2812 d3d8_device_SetGammaRamp,
2813 d3d8_device_GetGammaRamp,
2814 d3d8_device_CreateTexture,
2815 d3d8_device_CreateVolumeTexture,
2816 d3d8_device_CreateCubeTexture,
2817 d3d8_device_CreateVertexBuffer,
2818 d3d8_device_CreateIndexBuffer,
2819 d3d8_device_CreateRenderTarget,
2820 d3d8_device_CreateDepthStencilSurface,
2821 d3d8_device_CreateImageSurface,
2822 d3d8_device_CopyRects,
2823 d3d8_device_UpdateTexture,
2824 d3d8_device_GetFrontBuffer,
2825 d3d8_device_SetRenderTarget,
2826 d3d8_device_GetRenderTarget,
2827 d3d8_device_GetDepthStencilSurface,
2828 d3d8_device_BeginScene,
2829 d3d8_device_EndScene,
2830 d3d8_device_Clear,
2831 d3d8_device_SetTransform,
2832 d3d8_device_GetTransform,
2833 d3d8_device_MultiplyTransform,
2834 d3d8_device_SetViewport,
2835 d3d8_device_GetViewport,
2836 d3d8_device_SetMaterial,
2837 d3d8_device_GetMaterial,
2838 d3d8_device_SetLight,
2839 d3d8_device_GetLight,
2840 d3d8_device_LightEnable,
2841 d3d8_device_GetLightEnable,
2842 d3d8_device_SetClipPlane,
2843 d3d8_device_GetClipPlane,
2844 d3d8_device_SetRenderState,
2845 d3d8_device_GetRenderState,
2846 d3d8_device_BeginStateBlock,
2847 d3d8_device_EndStateBlock,
2848 d3d8_device_ApplyStateBlock,
2849 d3d8_device_CaptureStateBlock,
2850 d3d8_device_DeleteStateBlock,
2851 d3d8_device_CreateStateBlock,
2852 d3d8_device_SetClipStatus,
2853 d3d8_device_GetClipStatus,
2854 d3d8_device_GetTexture,
2855 d3d8_device_SetTexture,
2856 d3d8_device_GetTextureStageState,
2857 d3d8_device_SetTextureStageState,
2858 d3d8_device_ValidateDevice,
2859 d3d8_device_GetInfo,
2860 d3d8_device_SetPaletteEntries,
2861 d3d8_device_GetPaletteEntries,
2862 d3d8_device_SetCurrentTexturePalette,
2863 d3d8_device_GetCurrentTexturePalette,
2864 d3d8_device_DrawPrimitive,
2865 d3d8_device_DrawIndexedPrimitive,
2866 d3d8_device_DrawPrimitiveUP,
2867 d3d8_device_DrawIndexedPrimitiveUP,
2868 d3d8_device_ProcessVertices,
2869 d3d8_device_CreateVertexShader,
2870 d3d8_device_SetVertexShader,
2871 d3d8_device_GetVertexShader,
2872 d3d8_device_DeleteVertexShader,
2873 d3d8_device_SetVertexShaderConstant,
2874 d3d8_device_GetVertexShaderConstant,
2875 d3d8_device_GetVertexShaderDeclaration,
2876 d3d8_device_GetVertexShaderFunction,
2877 d3d8_device_SetStreamSource,
2878 d3d8_device_GetStreamSource,
2879 d3d8_device_SetIndices,
2880 d3d8_device_GetIndices,
2881 d3d8_device_CreatePixelShader,
2882 d3d8_device_SetPixelShader,
2883 d3d8_device_GetPixelShader,
2884 d3d8_device_DeletePixelShader,
2885 d3d8_device_SetPixelShaderConstant,
2886 d3d8_device_GetPixelShaderConstant,
2887 d3d8_device_GetPixelShaderFunction,
2888 d3d8_device_DrawRectPatch,
2889 d3d8_device_DrawTriPatch,
2890 d3d8_device_DeletePatch,
2891 };
2892
2893 static inline struct d3d8_device *device_from_device_parent(struct wined3d_device_parent *device_parent)
2894 {
2895 return CONTAINING_RECORD(device_parent, struct d3d8_device, device_parent);
2896 }
2897
2898 static void CDECL device_parent_wined3d_device_created(struct wined3d_device_parent *device_parent,
2899 struct wined3d_device *device)
2900 {
2901 TRACE("device_parent %p, device %p\n", device_parent, device);
2902 }
2903
2904 static void CDECL device_parent_mode_changed(struct wined3d_device_parent *device_parent)
2905 {
2906 TRACE("device_parent %p.\n", device_parent);
2907 }
2908
2909 static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent *device_parent,
2910 void *container_parent, struct wined3d_surface *surface, void **parent,
2911 const struct wined3d_parent_ops **parent_ops)
2912 {
2913 struct d3d8_device *device = device_from_device_parent(device_parent);
2914 struct d3d8_surface *d3d_surface;
2915
2916 TRACE("device_parent %p, container_parent %p, surface %p, parent %p, parent_ops %p.\n",
2917 device_parent, container_parent, surface, parent, parent_ops);
2918
2919 if (!(d3d_surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d3d_surface))))
2920 {
2921 FIXME("Failed to allocate surface memory.\n");
2922 return D3DERR_OUTOFVIDEOMEMORY;
2923 }
2924
2925 surface_init(d3d_surface, surface, device, parent_ops);
2926 *parent = d3d_surface;
2927 TRACE("Created surface %p.\n", d3d_surface);
2928
2929 d3d_surface->container = container_parent;
2930 IDirect3DDevice8_Release(d3d_surface->parent_device);
2931 d3d_surface->parent_device = NULL;
2932
2933 IDirect3DSurface8_Release(&d3d_surface->IDirect3DSurface8_iface);
2934 d3d_surface->forwardReference = container_parent;
2935
2936 return D3D_OK;
2937 }
2938
2939 static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *device_parent,
2940 void *container_parent, struct wined3d_volume *volume, void **parent,
2941 const struct wined3d_parent_ops **parent_ops)
2942 {
2943 struct d3d8_volume *d3d_volume;
2944
2945 TRACE("device_parent %p, container_parent %p, volume %p, parent %p, parent_ops %p.\n",
2946 device_parent, container_parent, volume, parent, parent_ops);
2947
2948 if (!(d3d_volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d3d_volume))))
2949 return E_OUTOFMEMORY;
2950
2951 volume_init(d3d_volume, volume, parent_ops);
2952 *parent = d3d_volume;
2953 TRACE("Created volume %p.\n", d3d_volume);
2954
2955 d3d_volume->container = container_parent;
2956
2957 IDirect3DVolume8_Release(&d3d_volume->IDirect3DVolume8_iface);
2958 d3d_volume->forwardReference = container_parent;
2959
2960 return D3D_OK;
2961 }
2962
2963 static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_device_parent *device_parent,
2964 void *container_parent, const struct wined3d_resource_desc *desc, struct wined3d_surface **surface)
2965 {
2966 struct d3d8_device *device = device_from_device_parent(device_parent);
2967 struct wined3d_resource_desc texture_desc;
2968 struct d3d8_surface *d3d_surface;
2969 struct wined3d_texture *texture;
2970 HRESULT hr;
2971
2972 TRACE("device_parent %p, container_parent %p, desc %p, surface %p.\n",
2973 device_parent, container_parent, desc, surface);
2974
2975 texture_desc = *desc;
2976 texture_desc.resource_type = WINED3D_RTYPE_TEXTURE;
2977 if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &texture_desc, 1,
2978 WINED3D_SURFACE_MAPPABLE, &device->IDirect3DDevice8_iface, &d3d8_null_wined3d_parent_ops, &texture)))
2979 {
2980 WARN("Failed to create texture, hr %#x.\n", hr);
2981 return hr;
2982 }
2983
2984 *surface = wined3d_surface_from_resource(wined3d_texture_get_sub_resource(texture, 0));
2985 wined3d_surface_incref(*surface);
2986 wined3d_texture_decref(texture);
2987
2988 d3d_surface = wined3d_surface_get_parent(*surface);
2989 d3d_surface->forwardReference = NULL;
2990 d3d_surface->parent_device = &device->IDirect3DDevice8_iface;
2991
2992 return hr;
2993 }
2994
2995 static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent,
2996 struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain)
2997 {
2998 struct d3d8_device *device = device_from_device_parent(device_parent);
2999 struct d3d8_swapchain *d3d_swapchain;
3000 HRESULT hr;
3001
3002 TRACE("device_parent %p, desc %p, swapchain %p.\n", device_parent, desc, swapchain);
3003
3004 if (FAILED(hr = d3d8_swapchain_create(device, desc, &d3d_swapchain)))
3005 {
3006 WARN("Failed to create swapchain, hr %#x.\n", hr);
3007 *swapchain = NULL;
3008 return hr;
3009 }
3010
3011 *swapchain = d3d_swapchain->wined3d_swapchain;
3012 wined3d_swapchain_incref(*swapchain);
3013 IDirect3DSwapChain8_Release(&d3d_swapchain->IDirect3DSwapChain8_iface);
3014
3015 return hr;
3016 }
3017
3018 static const struct wined3d_device_parent_ops d3d8_wined3d_device_parent_ops =
3019 {
3020 device_parent_wined3d_device_created,
3021 device_parent_mode_changed,
3022 device_parent_surface_created,
3023 device_parent_volume_created,
3024 device_parent_create_swapchain_surface,
3025 device_parent_create_swapchain,
3026 };
3027
3028 static void setup_fpu(void)
3029 {
3030 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3031 WORD cw;
3032 __asm__ volatile ("fnstcw %0" : "=m" (cw));
3033 cw = (cw & ~0xf3f) | 0x3f;
3034 __asm__ volatile ("fldcw %0" : : "m" (cw));
3035 #elif defined(__i386__) && defined(_MSC_VER)
3036 WORD cw;
3037 __asm fnstcw cw;
3038 cw = (cw & ~0xf3f) | 0x3f;
3039 __asm fldcw cw;
3040 #else
3041 FIXME("FPU setup not implemented for this platform.\n");
3042 #endif
3043 }
3044
3045 HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wined3d *wined3d, UINT adapter,
3046 D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters)
3047 {
3048 struct wined3d_swapchain_desc swapchain_desc;
3049 HRESULT hr;
3050
3051 device->IDirect3DDevice8_iface.lpVtbl = &d3d8_device_vtbl;
3052 device->device_parent.ops = &d3d8_wined3d_device_parent_ops;
3053 device->ref = 1;
3054 device->handle_table.entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3055 D3D8_INITIAL_HANDLE_TABLE_SIZE * sizeof(*device->handle_table.entries));
3056 if (!device->handle_table.entries)
3057 {
3058 ERR("Failed to allocate handle table memory.\n");
3059 return E_OUTOFMEMORY;
3060 }
3061 device->handle_table.table_size = D3D8_INITIAL_HANDLE_TABLE_SIZE;
3062
3063 if (!(flags & D3DCREATE_FPU_PRESERVE)) setup_fpu();
3064
3065 wined3d_mutex_lock();
3066 hr = wined3d_device_create(wined3d, adapter, device_type, focus_window, flags, 4,
3067 &device->device_parent, &device->wined3d_device);
3068 if (FAILED(hr))
3069 {
3070 WARN("Failed to create wined3d device, hr %#x.\n", hr);
3071 wined3d_mutex_unlock();
3072 HeapFree(GetProcessHeap(), 0, device->handle_table.entries);
3073 return hr;
3074 }
3075
3076 if (!parameters->Windowed)
3077 {
3078 HWND device_window = parameters->hDeviceWindow;
3079
3080 if (!focus_window)
3081 focus_window = device_window;
3082 if (FAILED(hr = wined3d_device_acquire_focus_window(device->wined3d_device, focus_window)))
3083 {
3084 ERR("Failed to acquire focus window, hr %#x.\n", hr);
3085 wined3d_device_decref(device->wined3d_device);
3086 wined3d_mutex_unlock();
3087 HeapFree(GetProcessHeap(), 0, device->handle_table.entries);
3088 return hr;
3089 }
3090
3091 if (!device_window)
3092 device_window = focus_window;
3093 wined3d_device_setup_fullscreen_window(device->wined3d_device, device_window,
3094 parameters->BackBufferWidth,
3095 parameters->BackBufferHeight);
3096 }
3097
3098 if (flags & D3DCREATE_MULTITHREADED)
3099 wined3d_device_set_multithreaded(device->wined3d_device);
3100
3101 wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, parameters);
3102
3103 hr = wined3d_device_init_3d(device->wined3d_device, &swapchain_desc);
3104 if (FAILED(hr))
3105 {
3106 WARN("Failed to initialize 3D, hr %#x.\n", hr);
3107 wined3d_device_release_focus_window(device->wined3d_device);
3108 wined3d_device_decref(device->wined3d_device);
3109 wined3d_mutex_unlock();
3110 HeapFree(GetProcessHeap(), 0, device->handle_table.entries);
3111 return hr;
3112 }
3113
3114 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_POINTSIZE_MIN, 0);
3115 wined3d_mutex_unlock();
3116
3117 present_parameters_from_wined3d_swapchain_desc(parameters, &swapchain_desc);
3118
3119 device->declArraySize = 16;
3120 device->decls = HeapAlloc(GetProcessHeap(), 0, device->declArraySize * sizeof(*device->decls));
3121 if (!device->decls)
3122 {
3123 ERR("Failed to allocate FVF vertex declaration map memory.\n");
3124 hr = E_OUTOFMEMORY;
3125 goto err;
3126 }
3127
3128 device->d3d_parent = &parent->IDirect3D8_iface;
3129 IDirect3D8_AddRef(device->d3d_parent);
3130
3131 return D3D_OK;
3132
3133 err:
3134 wined3d_mutex_lock();
3135 wined3d_device_uninit_3d(device->wined3d_device);
3136 wined3d_device_release_focus_window(device->wined3d_device);
3137 wined3d_device_decref(device->wined3d_device);
3138 wined3d_mutex_unlock();
3139 HeapFree(GetProcessHeap(), 0, device->handle_table.entries);
3140 return hr;
3141 }