VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/device.c@ 48345

Last change on this file since 48345 was 48345, checked in by vboxsync, 12 years ago

header fixes

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette