mshtml: Merge htmliframe.c into htmlframe.c.
[wine.git] / dlls / d3d8 / device.c
blob5daf6f46c2a68c43295cef29ccd314ff44fbd6ea
1 /*
2 * IDirect3DDevice8 implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2004 Christian Costa
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.
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.
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
22 #include "config.h"
24 #include <math.h>
25 #include <stdarg.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "wingdi.h"
31 #include "wine/debug.h"
33 #include "d3d8_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
37 static void STDMETHODCALLTYPE d3d8_null_wined3d_object_destroyed(void *parent) {}
39 static const struct wined3d_parent_ops d3d8_null_wined3d_parent_ops =
41 d3d8_null_wined3d_object_destroyed,
44 D3DFORMAT d3dformat_from_wined3dformat(enum wined3d_format_id format)
46 BYTE *c = (BYTE *)&format;
48 /* Don't translate FOURCC formats */
49 if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format;
51 switch(format)
53 case WINED3DFMT_UNKNOWN: return D3DFMT_UNKNOWN;
54 case WINED3DFMT_B8G8R8_UNORM: return D3DFMT_R8G8B8;
55 case WINED3DFMT_B8G8R8A8_UNORM: return D3DFMT_A8R8G8B8;
56 case WINED3DFMT_B8G8R8X8_UNORM: return D3DFMT_X8R8G8B8;
57 case WINED3DFMT_B5G6R5_UNORM: return D3DFMT_R5G6B5;
58 case WINED3DFMT_B5G5R5X1_UNORM: return D3DFMT_X1R5G5B5;
59 case WINED3DFMT_B5G5R5A1_UNORM: return D3DFMT_A1R5G5B5;
60 case WINED3DFMT_B4G4R4A4_UNORM: return D3DFMT_A4R4G4B4;
61 case WINED3DFMT_B2G3R3_UNORM: return D3DFMT_R3G3B2;
62 case WINED3DFMT_A8_UNORM: return D3DFMT_A8;
63 case WINED3DFMT_B2G3R3A8_UNORM: return D3DFMT_A8R3G3B2;
64 case WINED3DFMT_B4G4R4X4_UNORM: return D3DFMT_X4R4G4B4;
65 case WINED3DFMT_R10G10B10A2_UNORM: return D3DFMT_A2B10G10R10;
66 case WINED3DFMT_R16G16_UNORM: return D3DFMT_G16R16;
67 case WINED3DFMT_P8_UINT_A8_UNORM: return D3DFMT_A8P8;
68 case WINED3DFMT_P8_UINT: return D3DFMT_P8;
69 case WINED3DFMT_L8_UNORM: return D3DFMT_L8;
70 case WINED3DFMT_L8A8_UNORM: return D3DFMT_A8L8;
71 case WINED3DFMT_L4A4_UNORM: return D3DFMT_A4L4;
72 case WINED3DFMT_R8G8_SNORM: return D3DFMT_V8U8;
73 case WINED3DFMT_R5G5_SNORM_L6_UNORM: return D3DFMT_L6V5U5;
74 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM: return D3DFMT_X8L8V8U8;
75 case WINED3DFMT_R8G8B8A8_SNORM: return D3DFMT_Q8W8V8U8;
76 case WINED3DFMT_R16G16_SNORM: return D3DFMT_V16U16;
77 case WINED3DFMT_R10G11B11_SNORM: return D3DFMT_W11V11U10;
78 case WINED3DFMT_R10G10B10_SNORM_A2_UNORM: return D3DFMT_A2W10V10U10;
79 case WINED3DFMT_D16_LOCKABLE: return D3DFMT_D16_LOCKABLE;
80 case WINED3DFMT_D32_UNORM: return D3DFMT_D32;
81 case WINED3DFMT_S1_UINT_D15_UNORM: return D3DFMT_D15S1;
82 case WINED3DFMT_D24_UNORM_S8_UINT: return D3DFMT_D24S8;
83 case WINED3DFMT_X8D24_UNORM: return D3DFMT_D24X8;
84 case WINED3DFMT_S4X4_UINT_D24_UNORM: return D3DFMT_D24X4S4;
85 case WINED3DFMT_D16_UNORM: return D3DFMT_D16;
86 case WINED3DFMT_R16_UINT: return D3DFMT_INDEX16;
87 case WINED3DFMT_R32_UINT: return D3DFMT_INDEX32;
88 default:
89 FIXME("Unhandled wined3d format %#x.\n", format);
90 return D3DFMT_UNKNOWN;
94 enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format)
96 BYTE *c = (BYTE *)&format;
98 /* Don't translate FOURCC formats */
99 if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format;
101 switch(format)
103 case D3DFMT_UNKNOWN: return WINED3DFMT_UNKNOWN;
104 case D3DFMT_R8G8B8: return WINED3DFMT_B8G8R8_UNORM;
105 case D3DFMT_A8R8G8B8: return WINED3DFMT_B8G8R8A8_UNORM;
106 case D3DFMT_X8R8G8B8: return WINED3DFMT_B8G8R8X8_UNORM;
107 case D3DFMT_R5G6B5: return WINED3DFMT_B5G6R5_UNORM;
108 case D3DFMT_X1R5G5B5: return WINED3DFMT_B5G5R5X1_UNORM;
109 case D3DFMT_A1R5G5B5: return WINED3DFMT_B5G5R5A1_UNORM;
110 case D3DFMT_A4R4G4B4: return WINED3DFMT_B4G4R4A4_UNORM;
111 case D3DFMT_R3G3B2: return WINED3DFMT_B2G3R3_UNORM;
112 case D3DFMT_A8: return WINED3DFMT_A8_UNORM;
113 case D3DFMT_A8R3G3B2: return WINED3DFMT_B2G3R3A8_UNORM;
114 case D3DFMT_X4R4G4B4: return WINED3DFMT_B4G4R4X4_UNORM;
115 case D3DFMT_A2B10G10R10: return WINED3DFMT_R10G10B10A2_UNORM;
116 case D3DFMT_G16R16: return WINED3DFMT_R16G16_UNORM;
117 case D3DFMT_A8P8: return WINED3DFMT_P8_UINT_A8_UNORM;
118 case D3DFMT_P8: return WINED3DFMT_P8_UINT;
119 case D3DFMT_L8: return WINED3DFMT_L8_UNORM;
120 case D3DFMT_A8L8: return WINED3DFMT_L8A8_UNORM;
121 case D3DFMT_A4L4: return WINED3DFMT_L4A4_UNORM;
122 case D3DFMT_V8U8: return WINED3DFMT_R8G8_SNORM;
123 case D3DFMT_L6V5U5: return WINED3DFMT_R5G5_SNORM_L6_UNORM;
124 case D3DFMT_X8L8V8U8: return WINED3DFMT_R8G8_SNORM_L8X8_UNORM;
125 case D3DFMT_Q8W8V8U8: return WINED3DFMT_R8G8B8A8_SNORM;
126 case D3DFMT_V16U16: return WINED3DFMT_R16G16_SNORM;
127 case D3DFMT_W11V11U10: return WINED3DFMT_R10G11B11_SNORM;
128 case D3DFMT_A2W10V10U10: return WINED3DFMT_R10G10B10_SNORM_A2_UNORM;
129 case D3DFMT_D16_LOCKABLE: return WINED3DFMT_D16_LOCKABLE;
130 case D3DFMT_D32: return WINED3DFMT_D32_UNORM;
131 case D3DFMT_D15S1: return WINED3DFMT_S1_UINT_D15_UNORM;
132 case D3DFMT_D24S8: return WINED3DFMT_D24_UNORM_S8_UINT;
133 case D3DFMT_D24X8: return WINED3DFMT_X8D24_UNORM;
134 case D3DFMT_D24X4S4: return WINED3DFMT_S4X4_UINT_D24_UNORM;
135 case D3DFMT_D16: return WINED3DFMT_D16_UNORM;
136 case D3DFMT_INDEX16: return WINED3DFMT_R16_UINT;
137 case D3DFMT_INDEX32: return WINED3DFMT_R32_UINT;
138 default:
139 FIXME("Unhandled D3DFORMAT %#x.\n", format);
140 return WINED3DFMT_UNKNOWN;
144 unsigned int wined3dmapflags_from_d3dmapflags(unsigned int flags)
146 static const unsigned int handled = D3DLOCK_NOSYSLOCK
147 | D3DLOCK_NOOVERWRITE
148 | D3DLOCK_DISCARD
149 | D3DLOCK_NO_DIRTY_UPDATE;
150 unsigned int wined3d_flags;
152 wined3d_flags = flags & handled;
153 if (!(flags & (D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD)))
154 wined3d_flags |= WINED3D_MAP_READ;
155 if (!(flags & D3DLOCK_READONLY))
156 wined3d_flags |= WINED3D_MAP_WRITE;
157 if (!(wined3d_flags & (WINED3D_MAP_READ | WINED3D_MAP_WRITE)))
158 wined3d_flags |= WINED3D_MAP_READ | WINED3D_MAP_WRITE;
159 flags &= ~(handled | D3DLOCK_READONLY);
161 if (flags)
162 FIXME("Unhandled flags %#x.\n", flags);
164 return wined3d_flags;
167 static UINT vertex_count_from_primitive_count(D3DPRIMITIVETYPE primitive_type, UINT primitive_count)
169 switch (primitive_type)
171 case D3DPT_POINTLIST:
172 return primitive_count;
174 case D3DPT_LINELIST:
175 return primitive_count * 2;
177 case D3DPT_LINESTRIP:
178 return primitive_count + 1;
180 case D3DPT_TRIANGLELIST:
181 return primitive_count * 3;
183 case D3DPT_TRIANGLESTRIP:
184 case D3DPT_TRIANGLEFAN:
185 return primitive_count + 2;
187 default:
188 FIXME("Unhandled primitive type %#x.\n", primitive_type);
189 return 0;
193 static D3DSWAPEFFECT d3dswapeffect_from_wined3dswapeffect(enum wined3d_swap_effect effect)
195 switch (effect)
197 case WINED3D_SWAP_EFFECT_DISCARD:
198 return D3DSWAPEFFECT_DISCARD;
199 case WINED3D_SWAP_EFFECT_SEQUENTIAL:
200 return D3DSWAPEFFECT_FLIP;
201 case WINED3D_SWAP_EFFECT_COPY:
202 return D3DSWAPEFFECT_COPY;
203 case WINED3D_SWAP_EFFECT_COPY_VSYNC:
204 return D3DSWAPEFFECT_COPY_VSYNC;
205 default:
206 FIXME("Unhandled swap effect %#x.\n", effect);
207 return D3DSWAPEFFECT_FLIP;
211 static void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS *present_parameters,
212 const struct wined3d_swapchain_desc *swapchain_desc)
214 present_parameters->BackBufferWidth = swapchain_desc->backbuffer_width;
215 present_parameters->BackBufferHeight = swapchain_desc->backbuffer_height;
216 present_parameters->BackBufferFormat = d3dformat_from_wined3dformat(swapchain_desc->backbuffer_format);
217 present_parameters->BackBufferCount = swapchain_desc->backbuffer_count;
218 present_parameters->MultiSampleType = swapchain_desc->multisample_type;
219 present_parameters->SwapEffect = d3dswapeffect_from_wined3dswapeffect(swapchain_desc->swap_effect);
220 present_parameters->hDeviceWindow = swapchain_desc->device_window;
221 present_parameters->Windowed = swapchain_desc->windowed;
222 present_parameters->EnableAutoDepthStencil = swapchain_desc->enable_auto_depth_stencil;
223 present_parameters->AutoDepthStencilFormat
224 = d3dformat_from_wined3dformat(swapchain_desc->auto_depth_stencil_format);
225 present_parameters->Flags = swapchain_desc->flags & D3DPRESENTFLAGS_MASK;
226 present_parameters->FullScreen_RefreshRateInHz = swapchain_desc->refresh_rate;
227 present_parameters->FullScreen_PresentationInterval = swapchain_desc->swap_interval;
230 static enum wined3d_swap_effect wined3dswapeffect_from_d3dswapeffect(D3DSWAPEFFECT effect)
232 switch (effect)
234 case D3DSWAPEFFECT_DISCARD:
235 return WINED3D_SWAP_EFFECT_DISCARD;
236 case D3DSWAPEFFECT_FLIP:
237 return WINED3D_SWAP_EFFECT_SEQUENTIAL;
238 case D3DSWAPEFFECT_COPY:
239 return WINED3D_SWAP_EFFECT_COPY;
240 case D3DSWAPEFFECT_COPY_VSYNC:
241 return WINED3D_SWAP_EFFECT_COPY_VSYNC;
242 default:
243 FIXME("Unhandled swap effect %#x.\n", effect);
244 return WINED3D_SWAP_EFFECT_SEQUENTIAL;
248 static BOOL wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapchain_desc *swapchain_desc,
249 const D3DPRESENT_PARAMETERS *present_parameters)
251 if (!present_parameters->SwapEffect || present_parameters->SwapEffect > D3DSWAPEFFECT_COPY_VSYNC)
253 WARN("Invalid swap effect %u passed.\n", present_parameters->SwapEffect);
254 return FALSE;
256 if (present_parameters->BackBufferCount > 3
257 || ((present_parameters->SwapEffect == D3DSWAPEFFECT_COPY
258 || present_parameters->SwapEffect == D3DSWAPEFFECT_COPY_VSYNC)
259 && present_parameters->BackBufferCount > 1))
261 WARN("Invalid backbuffer count %u.\n", present_parameters->BackBufferCount);
262 return FALSE;
265 swapchain_desc->backbuffer_width = present_parameters->BackBufferWidth;
266 swapchain_desc->backbuffer_height = present_parameters->BackBufferHeight;
267 swapchain_desc->backbuffer_format = wined3dformat_from_d3dformat(present_parameters->BackBufferFormat);
268 swapchain_desc->backbuffer_count = max(1, present_parameters->BackBufferCount);
269 swapchain_desc->backbuffer_usage = WINED3DUSAGE_RENDERTARGET;
270 swapchain_desc->multisample_type = present_parameters->MultiSampleType;
271 swapchain_desc->multisample_quality = 0; /* d3d9 only */
272 swapchain_desc->swap_effect = wined3dswapeffect_from_d3dswapeffect(present_parameters->SwapEffect);
273 swapchain_desc->device_window = present_parameters->hDeviceWindow;
274 swapchain_desc->windowed = present_parameters->Windowed;
275 swapchain_desc->enable_auto_depth_stencil = present_parameters->EnableAutoDepthStencil;
276 swapchain_desc->auto_depth_stencil_format
277 = wined3dformat_from_d3dformat(present_parameters->AutoDepthStencilFormat);
278 swapchain_desc->flags
279 = (present_parameters->Flags & D3DPRESENTFLAGS_MASK) | WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH;
280 swapchain_desc->refresh_rate = present_parameters->FullScreen_RefreshRateInHz;
281 swapchain_desc->swap_interval = present_parameters->FullScreen_PresentationInterval;
282 swapchain_desc->auto_restore_display_mode = TRUE;
284 if (present_parameters->Flags & ~D3DPRESENTFLAGS_MASK)
285 FIXME("Unhandled flags %#x.\n", present_parameters->Flags & ~D3DPRESENTFLAGS_MASK);
287 return TRUE;
290 void d3dcaps_from_wined3dcaps(D3DCAPS8 *caps, const WINED3DCAPS *wined3d_caps)
292 caps->DeviceType = (D3DDEVTYPE)wined3d_caps->DeviceType;
293 caps->AdapterOrdinal = wined3d_caps->AdapterOrdinal;
294 caps->Caps = wined3d_caps->Caps;
295 caps->Caps2 = wined3d_caps->Caps2;
296 caps->Caps3 = wined3d_caps->Caps3;
297 caps->PresentationIntervals = wined3d_caps->PresentationIntervals;
298 caps->CursorCaps = wined3d_caps->CursorCaps;
299 caps->DevCaps = wined3d_caps->DevCaps;
300 caps->PrimitiveMiscCaps = wined3d_caps->PrimitiveMiscCaps;
301 caps->RasterCaps = wined3d_caps->RasterCaps;
302 caps->ZCmpCaps = wined3d_caps->ZCmpCaps;
303 caps->SrcBlendCaps = wined3d_caps->SrcBlendCaps;
304 caps->DestBlendCaps = wined3d_caps->DestBlendCaps;
305 caps->AlphaCmpCaps = wined3d_caps->AlphaCmpCaps;
306 caps->ShadeCaps = wined3d_caps->ShadeCaps;
307 caps->TextureCaps = wined3d_caps->TextureCaps;
308 caps->TextureFilterCaps = wined3d_caps->TextureFilterCaps;
309 caps->CubeTextureFilterCaps = wined3d_caps->CubeTextureFilterCaps;
310 caps->VolumeTextureFilterCaps = wined3d_caps->VolumeTextureFilterCaps;
311 caps->TextureAddressCaps = wined3d_caps->TextureAddressCaps;
312 caps->VolumeTextureAddressCaps = wined3d_caps->VolumeTextureAddressCaps;
313 caps->LineCaps = wined3d_caps->LineCaps;
314 caps->MaxTextureWidth = wined3d_caps->MaxTextureWidth;
315 caps->MaxTextureHeight = wined3d_caps->MaxTextureHeight;
316 caps->MaxVolumeExtent = wined3d_caps->MaxVolumeExtent;
317 caps->MaxTextureRepeat = wined3d_caps->MaxTextureRepeat;
318 caps->MaxTextureAspectRatio = wined3d_caps->MaxTextureAspectRatio;
319 caps->MaxAnisotropy = wined3d_caps->MaxAnisotropy;
320 caps->MaxVertexW = wined3d_caps->MaxVertexW;
321 caps->GuardBandLeft = wined3d_caps->GuardBandLeft;
322 caps->GuardBandTop = wined3d_caps->GuardBandTop;
323 caps->GuardBandRight = wined3d_caps->GuardBandRight;
324 caps->GuardBandBottom = wined3d_caps->GuardBandBottom;
325 caps->ExtentsAdjust = wined3d_caps->ExtentsAdjust;
326 caps->StencilCaps = wined3d_caps->StencilCaps;
327 caps->FVFCaps = wined3d_caps->FVFCaps;
328 caps->TextureOpCaps = wined3d_caps->TextureOpCaps;
329 caps->MaxTextureBlendStages = wined3d_caps->MaxTextureBlendStages;
330 caps->MaxSimultaneousTextures = wined3d_caps->MaxSimultaneousTextures;
331 caps->VertexProcessingCaps = wined3d_caps->VertexProcessingCaps;
332 caps->MaxActiveLights = wined3d_caps->MaxActiveLights;
333 caps->MaxUserClipPlanes = wined3d_caps->MaxUserClipPlanes;
334 caps->MaxVertexBlendMatrices = wined3d_caps->MaxVertexBlendMatrices;
335 caps->MaxVertexBlendMatrixIndex = wined3d_caps->MaxVertexBlendMatrixIndex;
336 caps->MaxPointSize = wined3d_caps->MaxPointSize;
337 caps->MaxPrimitiveCount = wined3d_caps->MaxPrimitiveCount;
338 caps->MaxVertexIndex = wined3d_caps->MaxVertexIndex;
339 caps->MaxStreams = wined3d_caps->MaxStreams;
340 caps->MaxStreamStride = wined3d_caps->MaxStreamStride;
341 caps->VertexShaderVersion = wined3d_caps->VertexShaderVersion;
342 caps->MaxVertexShaderConst = wined3d_caps->MaxVertexShaderConst;
343 caps->PixelShaderVersion = wined3d_caps->PixelShaderVersion;
344 caps->MaxPixelShaderValue = wined3d_caps->PixelShader1xMaxValue;
346 /* D3D8 doesn't support SM 2.0 or higher, so clamp to 1.x */
347 if (caps->PixelShaderVersion)
348 caps->PixelShaderVersion = D3DPS_VERSION(1, 4);
349 else
350 caps->PixelShaderVersion = D3DPS_VERSION(0, 0);
351 if (caps->VertexShaderVersion)
352 caps->VertexShaderVersion = D3DVS_VERSION(1, 1);
353 else
354 caps->VertexShaderVersion = D3DVS_VERSION(0, 0);
355 caps->MaxVertexShaderConst = min(D3D8_MAX_VERTEX_SHADER_CONSTANTF, caps->MaxVertexShaderConst);
357 caps->StencilCaps &= ~WINED3DSTENCILCAPS_TWOSIDED;
360 /* Handle table functions */
361 static DWORD d3d8_allocate_handle(struct d3d8_handle_table *t, void *object, enum d3d8_handle_type type)
363 struct d3d8_handle_entry *entry;
365 if (t->free_entries)
367 DWORD index = t->free_entries - t->entries;
368 /* Use a free handle */
369 entry = t->free_entries;
370 if (entry->type != D3D8_HANDLE_FREE)
372 ERR("Handle %u(%p) is in the free list, but has type %#x.\n", index, entry, entry->type);
373 return D3D8_INVALID_HANDLE;
375 t->free_entries = entry->object;
376 entry->object = object;
377 entry->type = type;
379 return index;
382 if (!(t->entry_count < t->table_size))
384 /* Grow the table */
385 UINT new_size = t->table_size + (t->table_size >> 1);
386 struct d3d8_handle_entry *new_entries;
388 if (!(new_entries = heap_realloc(t->entries, new_size * sizeof(*t->entries))))
390 ERR("Failed to grow the handle table.\n");
391 return D3D8_INVALID_HANDLE;
393 t->entries = new_entries;
394 t->table_size = new_size;
397 entry = &t->entries[t->entry_count];
398 entry->object = object;
399 entry->type = type;
401 return t->entry_count++;
404 static void *d3d8_free_handle(struct d3d8_handle_table *t, DWORD handle, enum d3d8_handle_type type)
406 struct d3d8_handle_entry *entry;
407 void *object;
409 if (handle == D3D8_INVALID_HANDLE || handle >= t->entry_count)
411 WARN("Invalid handle %u passed.\n", handle);
412 return NULL;
415 entry = &t->entries[handle];
416 if (entry->type != type)
418 WARN("Handle %u(%p) is not of type %#x.\n", handle, entry, type);
419 return NULL;
422 object = entry->object;
423 entry->object = t->free_entries;
424 entry->type = D3D8_HANDLE_FREE;
425 t->free_entries = entry;
427 return object;
430 static void *d3d8_get_object(struct d3d8_handle_table *t, DWORD handle, enum d3d8_handle_type type)
432 struct d3d8_handle_entry *entry;
434 if (handle == D3D8_INVALID_HANDLE || handle >= t->entry_count)
436 WARN("Invalid handle %u passed.\n", handle);
437 return NULL;
440 entry = &t->entries[handle];
441 if (entry->type != type)
443 WARN("Handle %u(%p) is not of type %#x.\n", handle, entry, type);
444 return NULL;
447 return entry->object;
450 static HRESULT WINAPI d3d8_device_QueryInterface(IDirect3DDevice8 *iface, REFIID riid, void **out)
452 TRACE("iface %p, riid %s, out %p.\n",
453 iface, debugstr_guid(riid), out);
455 if (IsEqualGUID(riid, &IID_IDirect3DDevice8)
456 || IsEqualGUID(riid, &IID_IUnknown))
458 IDirect3DDevice8_AddRef(iface);
459 *out = iface;
460 return S_OK;
463 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
465 *out = NULL;
466 return E_NOINTERFACE;
469 static ULONG WINAPI d3d8_device_AddRef(IDirect3DDevice8 *iface)
471 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
472 ULONG ref = InterlockedIncrement(&device->ref);
474 TRACE("%p increasing refcount to %u.\n", iface, ref);
476 return ref;
479 static ULONG WINAPI d3d8_device_Release(IDirect3DDevice8 *iface)
481 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
482 ULONG ref;
484 if (device->inDestruction)
485 return 0;
487 ref = InterlockedDecrement(&device->ref);
489 TRACE("%p decreasing refcount to %u.\n", iface, ref);
491 if (!ref)
493 IDirect3D8 *parent = device->d3d_parent;
494 unsigned i;
496 TRACE("Releasing wined3d device %p.\n", device->wined3d_device);
498 wined3d_mutex_lock();
500 device->inDestruction = TRUE;
502 for (i = 0; i < device->numConvertedDecls; ++i)
504 d3d8_vertex_declaration_destroy(device->decls[i].declaration);
506 heap_free(device->decls);
508 if (device->vertex_buffer)
509 wined3d_buffer_decref(device->vertex_buffer);
510 if (device->index_buffer)
511 wined3d_buffer_decref(device->index_buffer);
513 wined3d_device_uninit_3d(device->wined3d_device);
514 wined3d_device_release_focus_window(device->wined3d_device);
515 wined3d_device_decref(device->wined3d_device);
516 heap_free(device->handle_table.entries);
517 heap_free(device);
519 wined3d_mutex_unlock();
521 IDirect3D8_Release(parent);
523 return ref;
526 static HRESULT WINAPI d3d8_device_TestCooperativeLevel(IDirect3DDevice8 *iface)
528 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
530 TRACE("iface %p.\n", iface);
532 TRACE("device state: %#x.\n", device->device_state);
534 switch (device->device_state)
536 default:
537 case D3D8_DEVICE_STATE_OK:
538 return D3D_OK;
539 case D3D8_DEVICE_STATE_LOST:
540 return D3DERR_DEVICELOST;
541 case D3D8_DEVICE_STATE_NOT_RESET:
542 return D3DERR_DEVICENOTRESET;
546 static UINT WINAPI d3d8_device_GetAvailableTextureMem(IDirect3DDevice8 *iface)
548 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
549 UINT ret;
551 TRACE("iface %p.\n", iface);
553 wined3d_mutex_lock();
554 ret = wined3d_device_get_available_texture_mem(device->wined3d_device);
555 wined3d_mutex_unlock();
557 return ret;
560 static HRESULT WINAPI d3d8_device_ResourceManagerDiscardBytes(IDirect3DDevice8 *iface, DWORD byte_count)
562 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
564 TRACE("iface %p, byte_count %u.\n", iface, byte_count);
566 if (byte_count)
567 FIXME("Byte count ignored.\n");
569 wined3d_mutex_lock();
570 wined3d_device_evict_managed_resources(device->wined3d_device);
571 wined3d_mutex_unlock();
573 return D3D_OK;
576 static HRESULT WINAPI d3d8_device_GetDirect3D(IDirect3DDevice8 *iface, IDirect3D8 **d3d8)
578 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
580 TRACE("iface %p, d3d8 %p.\n", iface, d3d8);
582 if (!d3d8)
583 return D3DERR_INVALIDCALL;
585 return IDirect3D8_QueryInterface(device->d3d_parent, &IID_IDirect3D8, (void **)d3d8);
588 static HRESULT WINAPI d3d8_device_GetDeviceCaps(IDirect3DDevice8 *iface, D3DCAPS8 *caps)
590 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
591 WINED3DCAPS wined3d_caps;
592 HRESULT hr;
594 TRACE("iface %p, caps %p.\n", iface, caps);
596 if (!caps)
597 return D3DERR_INVALIDCALL;
599 wined3d_mutex_lock();
600 hr = wined3d_device_get_device_caps(device->wined3d_device, &wined3d_caps);
601 wined3d_mutex_unlock();
603 d3dcaps_from_wined3dcaps(caps, &wined3d_caps);
605 return hr;
608 static HRESULT WINAPI d3d8_device_GetDisplayMode(IDirect3DDevice8 *iface, D3DDISPLAYMODE *mode)
610 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
611 struct wined3d_display_mode wined3d_mode;
612 HRESULT hr;
614 TRACE("iface %p, mode %p.\n", iface, mode);
616 wined3d_mutex_lock();
617 hr = wined3d_device_get_display_mode(device->wined3d_device, 0, &wined3d_mode, NULL);
618 wined3d_mutex_unlock();
620 if (SUCCEEDED(hr))
622 mode->Width = wined3d_mode.width;
623 mode->Height = wined3d_mode.height;
624 mode->RefreshRate = wined3d_mode.refresh_rate;
625 mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
628 return hr;
631 static HRESULT WINAPI d3d8_device_GetCreationParameters(IDirect3DDevice8 *iface,
632 D3DDEVICE_CREATION_PARAMETERS *parameters)
634 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
636 TRACE("iface %p, parameters %p.\n", iface, parameters);
638 wined3d_mutex_lock();
639 wined3d_device_get_creation_parameters(device->wined3d_device,
640 (struct wined3d_device_creation_parameters *)parameters);
641 wined3d_mutex_unlock();
643 return D3D_OK;
646 static HRESULT WINAPI d3d8_device_SetCursorProperties(IDirect3DDevice8 *iface,
647 UINT hotspot_x, UINT hotspot_y, IDirect3DSurface8 *bitmap)
649 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
650 struct d3d8_surface *bitmap_impl = unsafe_impl_from_IDirect3DSurface8(bitmap);
651 HRESULT hr;
653 TRACE("iface %p, hotspot_x %u, hotspot_y %u, bitmap %p.\n",
654 iface, hotspot_x, hotspot_y, bitmap);
656 if (!bitmap)
658 WARN("No cursor bitmap, returning D3DERR_INVALIDCALL.\n");
659 return D3DERR_INVALIDCALL;
662 wined3d_mutex_lock();
663 hr = wined3d_device_set_cursor_properties(device->wined3d_device,
664 hotspot_x, hotspot_y, bitmap_impl->wined3d_texture, bitmap_impl->sub_resource_idx);
665 wined3d_mutex_unlock();
667 return hr;
670 static void WINAPI d3d8_device_SetCursorPosition(IDirect3DDevice8 *iface, UINT x, UINT y, DWORD flags)
672 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
674 TRACE("iface %p, x %u, y %u, flags %#x.\n", iface, x, y, flags);
676 wined3d_mutex_lock();
677 wined3d_device_set_cursor_position(device->wined3d_device, x, y, flags);
678 wined3d_mutex_unlock();
681 static BOOL WINAPI d3d8_device_ShowCursor(IDirect3DDevice8 *iface, BOOL show)
683 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
684 BOOL ret;
686 TRACE("iface %p, show %#x.\n", iface, show);
688 wined3d_mutex_lock();
689 ret = wined3d_device_show_cursor(device->wined3d_device, show);
690 wined3d_mutex_unlock();
692 return ret;
695 static HRESULT WINAPI d3d8_device_CreateAdditionalSwapChain(IDirect3DDevice8 *iface,
696 D3DPRESENT_PARAMETERS *present_parameters, IDirect3DSwapChain8 **swapchain)
698 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
699 struct wined3d_swapchain_desc desc;
700 struct d3d8_swapchain *object;
701 UINT i, count;
702 HRESULT hr;
704 TRACE("iface %p, present_parameters %p, swapchain %p.\n",
705 iface, present_parameters, swapchain);
707 if (!present_parameters->Windowed)
709 WARN("Trying to create an additional fullscreen swapchain, returning D3DERR_INVALIDCALL.\n");
710 return D3DERR_INVALIDCALL;
713 wined3d_mutex_lock();
714 count = wined3d_device_get_swapchain_count(device->wined3d_device);
715 for (i = 0; i < count; ++i)
717 struct wined3d_swapchain *wined3d_swapchain;
719 wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, i);
720 wined3d_swapchain_get_desc(wined3d_swapchain, &desc);
722 if (!desc.windowed)
724 wined3d_mutex_unlock();
725 WARN("Trying to create an additional swapchain in fullscreen mode, returning D3DERR_INVALIDCALL.\n");
726 return D3DERR_INVALIDCALL;
729 wined3d_mutex_unlock();
731 if (!wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters))
732 return D3DERR_INVALIDCALL;
733 if (SUCCEEDED(hr = d3d8_swapchain_create(device, &desc, &object)))
734 *swapchain = &object->IDirect3DSwapChain8_iface;
735 present_parameters_from_wined3d_swapchain_desc(present_parameters, &desc);
737 return hr;
740 static HRESULT CDECL reset_enum_callback(struct wined3d_resource *resource)
742 struct wined3d_resource_desc desc;
743 IDirect3DBaseTexture8 *texture;
744 struct d3d8_surface *surface;
745 IUnknown *parent;
747 wined3d_resource_get_desc(resource, &desc);
748 if (desc.access & WINED3D_RESOURCE_ACCESS_CPU)
749 return D3D_OK;
751 if (desc.resource_type != WINED3D_RTYPE_TEXTURE_2D)
753 WARN("Resource %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", resource);
754 return D3DERR_DEVICELOST;
757 parent = wined3d_resource_get_parent(resource);
758 if (parent && SUCCEEDED(IUnknown_QueryInterface(parent, &IID_IDirect3DBaseTexture8, (void **)&texture)))
760 IDirect3DBaseTexture8_Release(texture);
761 WARN("Texture %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", texture, resource);
762 return D3DERR_DEVICELOST;
765 surface = wined3d_texture_get_sub_resource_parent(wined3d_texture_from_resource(resource), 0);
766 if (!surface->resource.refcount)
767 return D3D_OK;
769 WARN("Surface %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", surface);
770 return D3DERR_DEVICELOST;
773 static HRESULT WINAPI d3d8_device_Reset(IDirect3DDevice8 *iface,
774 D3DPRESENT_PARAMETERS *present_parameters)
776 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
777 struct wined3d_swapchain_desc swapchain_desc;
778 HRESULT hr;
780 TRACE("iface %p, present_parameters %p.\n", iface, present_parameters);
782 if (device->device_state == D3D8_DEVICE_STATE_LOST)
784 WARN("App not active, returning D3DERR_DEVICELOST.\n");
785 return D3DERR_DEVICELOST;
787 if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters))
788 return D3DERR_INVALIDCALL;
790 wined3d_mutex_lock();
792 if (device->vertex_buffer)
794 wined3d_buffer_decref(device->vertex_buffer);
795 device->vertex_buffer = NULL;
796 device->vertex_buffer_size = 0;
798 if (device->index_buffer)
800 wined3d_buffer_decref(device->index_buffer);
801 device->index_buffer = NULL;
802 device->index_buffer_size = 0;
805 if (SUCCEEDED(hr = wined3d_device_reset(device->wined3d_device, &swapchain_desc,
806 NULL, reset_enum_callback, TRUE)))
808 present_parameters->BackBufferCount = swapchain_desc.backbuffer_count;
809 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_POINTSIZE_MIN, 0);
810 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_ZENABLE,
811 !!swapchain_desc.enable_auto_depth_stencil);
812 device->device_state = D3D8_DEVICE_STATE_OK;
814 else
816 device->device_state = D3D8_DEVICE_STATE_NOT_RESET;
818 wined3d_mutex_unlock();
820 return hr;
823 static HRESULT WINAPI d3d8_device_Present(IDirect3DDevice8 *iface, const RECT *src_rect,
824 const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region)
826 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
828 TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p.\n",
829 iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect), dst_window_override, dirty_region);
831 /* Fraps does not hook IDirect3DDevice8::Present regardless of the hotpatch
832 * attribute. It only hooks IDirect3DSwapChain8::Present. Yet it properly
833 * shows a framerate on Windows in applications that only call the device
834 * method, like e.g. the dx8 sdk samples. The conclusion is that native
835 * calls the swapchain's public method from the device. */
836 return IDirect3DSwapChain8_Present(&device->implicit_swapchain->IDirect3DSwapChain8_iface,
837 src_rect, dst_rect, dst_window_override, dirty_region);
840 static HRESULT WINAPI d3d8_device_GetBackBuffer(IDirect3DDevice8 *iface,
841 UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface8 **backbuffer)
843 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
844 struct wined3d_swapchain *wined3d_swapchain;
845 struct wined3d_texture *wined3d_texture;
846 struct d3d8_surface *surface_impl;
848 TRACE("iface %p, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
849 iface, backbuffer_idx, backbuffer_type, backbuffer);
851 /* backbuffer_type is ignored by native. */
853 /* No need to check for backbuffer == NULL, Windows crashes in that case. */
854 wined3d_mutex_lock();
856 wined3d_swapchain = device->implicit_swapchain->wined3d_swapchain;
857 if (!(wined3d_texture = wined3d_swapchain_get_back_buffer(wined3d_swapchain, backbuffer_idx)))
859 wined3d_mutex_unlock();
860 *backbuffer = NULL;
861 return D3DERR_INVALIDCALL;
864 surface_impl = wined3d_texture_get_sub_resource_parent(wined3d_texture, 0);
865 *backbuffer = &surface_impl->IDirect3DSurface8_iface;
866 IDirect3DSurface8_AddRef(*backbuffer);
868 wined3d_mutex_unlock();
869 return D3D_OK;
872 static HRESULT WINAPI d3d8_device_GetRasterStatus(IDirect3DDevice8 *iface, D3DRASTER_STATUS *raster_status)
874 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
875 HRESULT hr;
877 TRACE("iface %p, raster_status %p.\n", iface, raster_status);
879 wined3d_mutex_lock();
880 hr = wined3d_device_get_raster_status(device->wined3d_device, 0, (struct wined3d_raster_status *)raster_status);
881 wined3d_mutex_unlock();
883 return hr;
886 static void WINAPI d3d8_device_SetGammaRamp(IDirect3DDevice8 *iface, DWORD flags, const D3DGAMMARAMP *ramp)
888 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
890 TRACE("iface %p, flags %#x, ramp %p.\n", iface, flags, ramp);
892 /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
893 wined3d_mutex_lock();
894 wined3d_device_set_gamma_ramp(device->wined3d_device, 0, flags, (const struct wined3d_gamma_ramp *)ramp);
895 wined3d_mutex_unlock();
898 static void WINAPI d3d8_device_GetGammaRamp(IDirect3DDevice8 *iface, D3DGAMMARAMP *ramp)
900 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
902 TRACE("iface %p, ramp %p.\n", iface, ramp);
904 /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
905 wined3d_mutex_lock();
906 wined3d_device_get_gamma_ramp(device->wined3d_device, 0, (struct wined3d_gamma_ramp *)ramp);
907 wined3d_mutex_unlock();
910 static HRESULT WINAPI d3d8_device_CreateTexture(IDirect3DDevice8 *iface,
911 UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format,
912 D3DPOOL pool, IDirect3DTexture8 **texture)
914 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
915 struct d3d8_texture *object;
916 HRESULT hr;
918 TRACE("iface %p, width %u, height %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n",
919 iface, width, height, levels, usage, format, pool, texture);
921 if (!format)
922 return D3DERR_INVALIDCALL;
924 *texture = NULL;
925 if (!(object = heap_alloc_zero(sizeof(*object))))
926 return D3DERR_OUTOFVIDEOMEMORY;
928 hr = texture_init(object, device, width, height, levels, usage, format, pool);
929 if (FAILED(hr))
931 WARN("Failed to initialize texture, hr %#x.\n", hr);
932 heap_free(object);
933 return hr;
936 TRACE("Created texture %p.\n", object);
937 *texture = (IDirect3DTexture8 *)&object->IDirect3DBaseTexture8_iface;
939 return D3D_OK;
942 static HRESULT WINAPI d3d8_device_CreateVolumeTexture(IDirect3DDevice8 *iface,
943 UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format,
944 D3DPOOL pool, IDirect3DVolumeTexture8 **texture)
946 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
947 struct d3d8_texture *object;
948 HRESULT hr;
950 TRACE("iface %p, width %u, height %u, depth %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n",
951 iface, width, height, depth, levels, usage, format, pool, texture);
953 if (!format)
954 return D3DERR_INVALIDCALL;
956 *texture = NULL;
957 if (!(object = heap_alloc_zero(sizeof(*object))))
958 return D3DERR_OUTOFVIDEOMEMORY;
960 hr = volumetexture_init(object, device, width, height, depth, levels, usage, format, pool);
961 if (FAILED(hr))
963 WARN("Failed to initialize volume texture, hr %#x.\n", hr);
964 heap_free(object);
965 return hr;
968 TRACE("Created volume texture %p.\n", object);
969 *texture = (IDirect3DVolumeTexture8 *)&object->IDirect3DBaseTexture8_iface;
971 return D3D_OK;
974 static HRESULT WINAPI d3d8_device_CreateCubeTexture(IDirect3DDevice8 *iface, UINT edge_length,
975 UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DCubeTexture8 **texture)
977 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
978 struct d3d8_texture *object;
979 HRESULT hr;
981 TRACE("iface %p, edge_length %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n",
982 iface, edge_length, levels, usage, format, pool, texture);
984 if (!format)
985 return D3DERR_INVALIDCALL;
987 *texture = NULL;
988 if (!(object = heap_alloc_zero(sizeof(*object))))
989 return D3DERR_OUTOFVIDEOMEMORY;
991 hr = cubetexture_init(object, device, edge_length, levels, usage, format, pool);
992 if (FAILED(hr))
994 WARN("Failed to initialize cube texture, hr %#x.\n", hr);
995 heap_free(object);
996 return hr;
999 TRACE("Created cube texture %p.\n", object);
1000 *texture = (IDirect3DCubeTexture8 *)&object->IDirect3DBaseTexture8_iface;
1002 return hr;
1005 static HRESULT WINAPI d3d8_device_CreateVertexBuffer(IDirect3DDevice8 *iface, UINT size,
1006 DWORD usage, DWORD fvf, D3DPOOL pool, IDirect3DVertexBuffer8 **buffer)
1008 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1009 struct d3d8_vertexbuffer *object;
1010 HRESULT hr;
1012 TRACE("iface %p, size %u, usage %#x, fvf %#x, pool %#x, buffer %p.\n",
1013 iface, size, usage, fvf, pool, buffer);
1015 if (!(object = heap_alloc_zero(sizeof(*object))))
1016 return D3DERR_OUTOFVIDEOMEMORY;
1018 hr = vertexbuffer_init(object, device, size, usage, fvf, pool);
1019 if (FAILED(hr))
1021 WARN("Failed to initialize vertex buffer, hr %#x.\n", hr);
1022 heap_free(object);
1023 return hr;
1026 TRACE("Created vertex buffer %p.\n", object);
1027 *buffer = &object->IDirect3DVertexBuffer8_iface;
1029 return D3D_OK;
1032 static HRESULT WINAPI d3d8_device_CreateIndexBuffer(IDirect3DDevice8 *iface, UINT size,
1033 DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer8 **buffer)
1035 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1036 struct d3d8_indexbuffer *object;
1037 HRESULT hr;
1039 TRACE("iface %p, size %u, usage %#x, format %#x, pool %#x, buffer %p.\n",
1040 iface, size, usage, format, pool, buffer);
1042 if (!(object = heap_alloc_zero(sizeof(*object))))
1043 return D3DERR_OUTOFVIDEOMEMORY;
1045 hr = indexbuffer_init(object, device, size, usage, format, pool);
1046 if (FAILED(hr))
1048 WARN("Failed to initialize index buffer, hr %#x.\n", hr);
1049 heap_free(object);
1050 return hr;
1053 TRACE("Created index buffer %p.\n", object);
1054 *buffer = &object->IDirect3DIndexBuffer8_iface;
1056 return D3D_OK;
1059 static HRESULT d3d8_device_create_surface(struct d3d8_device *device, UINT width, UINT height,
1060 D3DFORMAT format, DWORD flags, IDirect3DSurface8 **surface, UINT usage, D3DPOOL pool,
1061 D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality)
1063 struct wined3d_resource_desc desc;
1064 struct d3d8_surface *surface_impl;
1065 struct wined3d_texture *texture;
1066 HRESULT hr;
1068 TRACE("device %p, width %u, height %u, format %#x, flags %#x, surface %p, "
1069 "usage %#x, pool %#x, multisample_type %#x, multisample_quality %u.\n",
1070 device, width, height, format, flags, surface,
1071 usage, pool, multisample_type, multisample_quality);
1073 desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
1074 desc.format = wined3dformat_from_d3dformat(format);
1075 desc.multisample_type = multisample_type;
1076 desc.multisample_quality = multisample_quality;
1077 desc.usage = usage & WINED3DUSAGE_MASK;
1078 if (pool == D3DPOOL_SCRATCH)
1079 desc.usage |= WINED3DUSAGE_SCRATCH;
1080 desc.access = wined3daccess_from_d3dpool(pool, usage)
1081 | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
1082 desc.width = width;
1083 desc.height = height;
1084 desc.depth = 1;
1085 desc.size = 0;
1087 wined3d_mutex_lock();
1089 if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &desc,
1090 1, 1, flags, NULL, NULL, &d3d8_null_wined3d_parent_ops, &texture)))
1092 wined3d_mutex_unlock();
1093 WARN("Failed to create texture, hr %#x.\n", hr);
1094 return hr;
1097 surface_impl = wined3d_texture_get_sub_resource_parent(texture, 0);
1098 surface_impl->parent_device = &device->IDirect3DDevice8_iface;
1099 *surface = &surface_impl->IDirect3DSurface8_iface;
1100 IDirect3DSurface8_AddRef(*surface);
1101 wined3d_texture_decref(texture);
1103 wined3d_mutex_unlock();
1105 return D3D_OK;
1108 static HRESULT WINAPI d3d8_device_CreateRenderTarget(IDirect3DDevice8 *iface, UINT width,
1109 UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, BOOL lockable,
1110 IDirect3DSurface8 **surface)
1112 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1113 DWORD flags = 0;
1115 TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, lockable %#x, surface %p.\n",
1116 iface, width, height, format, multisample_type, lockable, surface);
1118 if (!format)
1119 return D3DERR_INVALIDCALL;
1121 *surface = NULL;
1122 if (lockable)
1123 flags |= WINED3D_TEXTURE_CREATE_MAPPABLE;
1125 return d3d8_device_create_surface(device, width, height, format, flags, surface,
1126 D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, multisample_type, 0);
1129 static HRESULT WINAPI d3d8_device_CreateDepthStencilSurface(IDirect3DDevice8 *iface,
1130 UINT width, UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type,
1131 IDirect3DSurface8 **surface)
1133 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1135 TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, surface %p.\n",
1136 iface, width, height, format, multisample_type, surface);
1138 if (!format)
1139 return D3DERR_INVALIDCALL;
1141 *surface = NULL;
1143 /* TODO: Verify that Discard is false */
1144 return d3d8_device_create_surface(device, width, height, format, WINED3D_TEXTURE_CREATE_MAPPABLE,
1145 surface, D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, multisample_type, 0);
1148 /* IDirect3DDevice8Impl::CreateImageSurface returns surface with pool type SYSTEMMEM */
1149 static HRESULT WINAPI d3d8_device_CreateImageSurface(IDirect3DDevice8 *iface, UINT width,
1150 UINT height, D3DFORMAT format, IDirect3DSurface8 **surface)
1152 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1154 TRACE("iface %p, width %u, height %u, format %#x, surface %p.\n",
1155 iface, width, height, format, surface);
1157 *surface = NULL;
1159 return d3d8_device_create_surface(device, width, height, format, WINED3D_TEXTURE_CREATE_MAPPABLE,
1160 surface, 0, D3DPOOL_SYSTEMMEM, D3DMULTISAMPLE_NONE, 0);
1163 static HRESULT WINAPI d3d8_device_CopyRects(IDirect3DDevice8 *iface,
1164 IDirect3DSurface8 *src_surface, const RECT *src_rects, UINT rect_count,
1165 IDirect3DSurface8 *dst_surface, const POINT *dst_points)
1167 struct d3d8_surface *src = unsafe_impl_from_IDirect3DSurface8(src_surface);
1168 struct d3d8_surface *dst = unsafe_impl_from_IDirect3DSurface8(dst_surface);
1169 enum wined3d_format_id src_format, dst_format;
1170 struct wined3d_sub_resource_desc wined3d_desc;
1171 UINT src_w, src_h;
1173 TRACE("iface %p, src_surface %p, src_rects %p, rect_count %u, dst_surface %p, dst_points %p.\n",
1174 iface, src_surface, src_rects, rect_count, dst_surface, dst_points);
1176 /* Check that the source texture is in WINED3D_POOL_SYSTEM_MEM and the
1177 * destination texture is in WINED3D_POOL_DEFAULT. */
1179 wined3d_mutex_lock();
1180 wined3d_texture_get_sub_resource_desc(src->wined3d_texture, src->sub_resource_idx, &wined3d_desc);
1181 if (wined3d_desc.usage & WINED3DUSAGE_DEPTHSTENCIL)
1183 WARN("Source %p is a depth stencil surface, returning D3DERR_INVALIDCALL.\n", src_surface);
1184 wined3d_mutex_unlock();
1185 return D3DERR_INVALIDCALL;
1187 src_format = wined3d_desc.format;
1188 src_w = wined3d_desc.width;
1189 src_h = wined3d_desc.height;
1191 wined3d_texture_get_sub_resource_desc(dst->wined3d_texture, dst->sub_resource_idx, &wined3d_desc);
1192 if (wined3d_desc.usage & WINED3DUSAGE_DEPTHSTENCIL)
1194 WARN("Destination %p is a depth stencil surface, returning D3DERR_INVALIDCALL.\n", dst_surface);
1195 wined3d_mutex_unlock();
1196 return D3DERR_INVALIDCALL;
1198 dst_format = wined3d_desc.format;
1200 /* Check that the source and destination formats match */
1201 if (src_format != dst_format)
1203 WARN("Source %p format must match the destination %p format, returning D3DERR_INVALIDCALL.\n",
1204 src_surface, dst_surface);
1205 wined3d_mutex_unlock();
1206 return D3DERR_INVALIDCALL;
1209 /* Quick if complete copy ... */
1210 if (!rect_count && !src_rects && !dst_points)
1212 RECT rect = {0, 0, src_w, src_h};
1213 wined3d_texture_blt(dst->wined3d_texture, dst->sub_resource_idx, &rect,
1214 src->wined3d_texture, src->sub_resource_idx, &rect, 0, NULL, WINED3D_TEXF_POINT);
1216 else
1218 unsigned int i;
1219 /* Copy rect by rect */
1220 if (src_rects && dst_points)
1222 for (i = 0; i < rect_count; ++i)
1224 UINT w = src_rects[i].right - src_rects[i].left;
1225 UINT h = src_rects[i].bottom - src_rects[i].top;
1226 RECT dst_rect = {dst_points[i].x, dst_points[i].y,
1227 dst_points[i].x + w, dst_points[i].y + h};
1229 wined3d_texture_blt(dst->wined3d_texture, dst->sub_resource_idx, &dst_rect,
1230 src->wined3d_texture, src->sub_resource_idx, &src_rects[i], 0, NULL, WINED3D_TEXF_POINT);
1233 else
1235 for (i = 0; i < rect_count; ++i)
1237 UINT w = src_rects[i].right - src_rects[i].left;
1238 UINT h = src_rects[i].bottom - src_rects[i].top;
1239 RECT dst_rect = {0, 0, w, h};
1241 wined3d_texture_blt(dst->wined3d_texture, dst->sub_resource_idx, &dst_rect,
1242 src->wined3d_texture, src->sub_resource_idx, &src_rects[i], 0, NULL, WINED3D_TEXF_POINT);
1246 wined3d_mutex_unlock();
1248 return WINED3D_OK;
1251 static HRESULT WINAPI d3d8_device_UpdateTexture(IDirect3DDevice8 *iface,
1252 IDirect3DBaseTexture8 *src_texture, IDirect3DBaseTexture8 *dst_texture)
1254 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1255 struct d3d8_texture *src_impl, *dst_impl;
1256 HRESULT hr;
1258 TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface, src_texture, dst_texture);
1260 src_impl = unsafe_impl_from_IDirect3DBaseTexture8(src_texture);
1261 dst_impl = unsafe_impl_from_IDirect3DBaseTexture8(dst_texture);
1263 wined3d_mutex_lock();
1264 hr = wined3d_device_update_texture(device->wined3d_device,
1265 src_impl->wined3d_texture, dst_impl->wined3d_texture);
1266 wined3d_mutex_unlock();
1268 return hr;
1271 static HRESULT WINAPI d3d8_device_GetFrontBuffer(IDirect3DDevice8 *iface, IDirect3DSurface8 *dst_surface)
1273 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1274 struct d3d8_surface *dst_impl = unsafe_impl_from_IDirect3DSurface8(dst_surface);
1275 HRESULT hr;
1277 TRACE("iface %p, dst_surface %p.\n", iface, dst_surface);
1279 if (!dst_surface)
1281 WARN("Invalid destination surface passed.\n");
1282 return D3DERR_INVALIDCALL;
1285 wined3d_mutex_lock();
1286 hr = wined3d_swapchain_get_front_buffer_data(device->implicit_swapchain->wined3d_swapchain,
1287 dst_impl->wined3d_texture, dst_impl->sub_resource_idx);
1288 wined3d_mutex_unlock();
1290 return hr;
1293 static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface,
1294 IDirect3DSurface8 *render_target, IDirect3DSurface8 *depth_stencil)
1296 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1297 struct d3d8_surface *rt_impl = unsafe_impl_from_IDirect3DSurface8(render_target);
1298 struct d3d8_surface *ds_impl = unsafe_impl_from_IDirect3DSurface8(depth_stencil);
1299 struct wined3d_rendertarget_view *original_dsv, *rtv;
1300 HRESULT hr = D3D_OK;
1302 TRACE("iface %p, render_target %p, depth_stencil %p.\n", iface, render_target, depth_stencil);
1304 if (rt_impl && d3d8_surface_get_device(rt_impl) != device)
1306 WARN("Render target surface does not match device.\n");
1307 return D3DERR_INVALIDCALL;
1310 wined3d_mutex_lock();
1312 if (ds_impl)
1314 struct wined3d_sub_resource_desc ds_desc, rt_desc;
1315 struct wined3d_rendertarget_view *original_rtv;
1316 struct d3d8_surface *original_surface;
1318 /* If no render target is passed in check the size against the current RT */
1319 if (!render_target)
1321 if (!(original_rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0)))
1323 wined3d_mutex_unlock();
1324 return D3DERR_NOTFOUND;
1326 original_surface = wined3d_rendertarget_view_get_sub_resource_parent(original_rtv);
1327 wined3d_texture_get_sub_resource_desc(original_surface->wined3d_texture,
1328 original_surface->sub_resource_idx, &rt_desc);
1330 else
1331 wined3d_texture_get_sub_resource_desc(rt_impl->wined3d_texture,
1332 rt_impl->sub_resource_idx, &rt_desc);
1334 wined3d_texture_get_sub_resource_desc(ds_impl->wined3d_texture, ds_impl->sub_resource_idx, &ds_desc);
1336 if (ds_desc.width < rt_desc.width || ds_desc.height < rt_desc.height)
1338 WARN("Depth stencil is smaller than the render target, returning D3DERR_INVALIDCALL\n");
1339 wined3d_mutex_unlock();
1340 return D3DERR_INVALIDCALL;
1342 if (ds_desc.multisample_type != rt_desc.multisample_type
1343 || ds_desc.multisample_quality != rt_desc.multisample_quality)
1345 WARN("Multisample settings do not match, returning D3DERR_INVALIDCALL\n");
1346 wined3d_mutex_unlock();
1347 return D3DERR_INVALIDCALL;
1351 original_dsv = wined3d_device_get_depth_stencil_view(device->wined3d_device);
1352 rtv = ds_impl ? d3d8_surface_acquire_rendertarget_view(ds_impl) : NULL;
1353 wined3d_device_set_depth_stencil_view(device->wined3d_device, rtv);
1354 d3d8_surface_release_rendertarget_view(ds_impl, rtv);
1355 rtv = render_target ? d3d8_surface_acquire_rendertarget_view(rt_impl) : NULL;
1356 if (render_target && FAILED(hr = wined3d_device_set_rendertarget_view(device->wined3d_device, 0, rtv, TRUE)))
1357 wined3d_device_set_depth_stencil_view(device->wined3d_device, original_dsv);
1358 d3d8_surface_release_rendertarget_view(rt_impl, rtv);
1360 wined3d_mutex_unlock();
1362 return hr;
1365 static HRESULT WINAPI d3d8_device_GetRenderTarget(IDirect3DDevice8 *iface, IDirect3DSurface8 **render_target)
1367 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1368 struct wined3d_rendertarget_view *wined3d_rtv;
1369 struct d3d8_surface *surface_impl;
1370 HRESULT hr;
1372 TRACE("iface %p, render_target %p.\n", iface, render_target);
1374 if (!render_target)
1375 return D3DERR_INVALIDCALL;
1377 wined3d_mutex_lock();
1378 if ((wined3d_rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0)))
1380 /* We want the sub resource parent here, since the view itself may be
1381 * internal to wined3d and may not have a parent. */
1382 surface_impl = wined3d_rendertarget_view_get_sub_resource_parent(wined3d_rtv);
1383 *render_target = &surface_impl->IDirect3DSurface8_iface;
1384 IDirect3DSurface8_AddRef(*render_target);
1385 hr = D3D_OK;
1387 else
1389 ERR("Failed to get wined3d render target.\n");
1390 *render_target = NULL;
1391 hr = D3DERR_NOTFOUND;
1393 wined3d_mutex_unlock();
1395 return hr;
1398 static HRESULT WINAPI d3d8_device_GetDepthStencilSurface(IDirect3DDevice8 *iface, IDirect3DSurface8 **depth_stencil)
1400 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1401 struct wined3d_rendertarget_view *wined3d_dsv;
1402 struct d3d8_surface *surface_impl;
1403 HRESULT hr = D3D_OK;
1405 TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil);
1407 if (!depth_stencil)
1408 return D3DERR_INVALIDCALL;
1410 wined3d_mutex_lock();
1411 if ((wined3d_dsv = wined3d_device_get_depth_stencil_view(device->wined3d_device)))
1413 /* We want the sub resource parent here, since the view itself may be
1414 * internal to wined3d and may not have a parent. */
1415 surface_impl = wined3d_rendertarget_view_get_sub_resource_parent(wined3d_dsv);
1416 *depth_stencil = &surface_impl->IDirect3DSurface8_iface;
1417 IDirect3DSurface8_AddRef(*depth_stencil);
1419 else
1421 hr = D3DERR_NOTFOUND;
1422 *depth_stencil = NULL;
1424 wined3d_mutex_unlock();
1426 return hr;
1429 static HRESULT WINAPI d3d8_device_BeginScene(IDirect3DDevice8 *iface)
1431 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1432 HRESULT hr;
1434 TRACE("iface %p.\n", iface);
1436 wined3d_mutex_lock();
1437 hr = wined3d_device_begin_scene(device->wined3d_device);
1438 wined3d_mutex_unlock();
1440 return hr;
1443 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d8_device_EndScene(IDirect3DDevice8 *iface)
1445 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1446 HRESULT hr;
1448 TRACE("iface %p.\n", iface);
1450 wined3d_mutex_lock();
1451 hr = wined3d_device_end_scene(device->wined3d_device);
1452 wined3d_mutex_unlock();
1454 return hr;
1457 static HRESULT WINAPI d3d8_device_Clear(IDirect3DDevice8 *iface, DWORD rect_count,
1458 const D3DRECT *rects, DWORD flags, D3DCOLOR color, float z, DWORD stencil)
1460 const struct wined3d_color c =
1462 ((color >> 16) & 0xff) / 255.0f,
1463 ((color >> 8) & 0xff) / 255.0f,
1464 (color & 0xff) / 255.0f,
1465 ((color >> 24) & 0xff) / 255.0f,
1467 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1468 HRESULT hr;
1470 TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %u.\n",
1471 iface, rect_count, rects, flags, color, z, stencil);
1473 if (rect_count && !rects)
1475 WARN("count %u with NULL rects.\n", rect_count);
1476 rect_count = 0;
1479 wined3d_mutex_lock();
1480 hr = wined3d_device_clear(device->wined3d_device, rect_count, (const RECT *)rects, flags, &c, z, stencil);
1481 wined3d_mutex_unlock();
1483 return hr;
1486 static HRESULT WINAPI d3d8_device_SetTransform(IDirect3DDevice8 *iface,
1487 D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
1489 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1491 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
1493 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
1494 wined3d_mutex_lock();
1495 wined3d_device_set_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix);
1496 wined3d_mutex_unlock();
1498 return D3D_OK;
1501 static HRESULT WINAPI d3d8_device_GetTransform(IDirect3DDevice8 *iface,
1502 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
1504 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1506 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
1508 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
1509 wined3d_mutex_lock();
1510 wined3d_device_get_transform(device->wined3d_device, state, (struct wined3d_matrix *)matrix);
1511 wined3d_mutex_unlock();
1513 return D3D_OK;
1516 static HRESULT WINAPI d3d8_device_MultiplyTransform(IDirect3DDevice8 *iface,
1517 D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
1519 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1521 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
1523 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
1524 wined3d_mutex_lock();
1525 wined3d_device_multiply_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix);
1526 wined3d_mutex_unlock();
1528 return D3D_OK;
1531 static HRESULT WINAPI d3d8_device_SetViewport(IDirect3DDevice8 *iface, const D3DVIEWPORT8 *viewport)
1533 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1534 struct wined3d_viewport vp;
1536 TRACE("iface %p, viewport %p.\n", iface, viewport);
1538 vp.x = viewport->X;
1539 vp.y = viewport->Y;
1540 vp.width = viewport->Width;
1541 vp.height = viewport->Height;
1542 vp.min_z = viewport->MinZ;
1543 vp.max_z = viewport->MaxZ;
1545 wined3d_mutex_lock();
1546 wined3d_device_set_viewport(device->wined3d_device, &vp);
1547 wined3d_mutex_unlock();
1549 return D3D_OK;
1552 static HRESULT WINAPI d3d8_device_GetViewport(IDirect3DDevice8 *iface, D3DVIEWPORT8 *viewport)
1554 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1555 struct wined3d_viewport wined3d_viewport;
1557 TRACE("iface %p, viewport %p.\n", iface, viewport);
1559 wined3d_mutex_lock();
1560 wined3d_device_get_viewport(device->wined3d_device, &wined3d_viewport);
1561 wined3d_mutex_unlock();
1563 viewport->X = wined3d_viewport.x;
1564 viewport->Y = wined3d_viewport.y;
1565 viewport->Width = wined3d_viewport.width;
1566 viewport->Height = wined3d_viewport.height;
1567 viewport->MinZ = wined3d_viewport.min_z;
1568 viewport->MaxZ = wined3d_viewport.max_z;
1570 return D3D_OK;
1573 static HRESULT WINAPI d3d8_device_SetMaterial(IDirect3DDevice8 *iface, const D3DMATERIAL8 *material)
1575 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1577 TRACE("iface %p, material %p.\n", iface, material);
1579 /* Note: D3DMATERIAL8 is compatible with struct wined3d_material. */
1580 wined3d_mutex_lock();
1581 wined3d_device_set_material(device->wined3d_device, (const struct wined3d_material *)material);
1582 wined3d_mutex_unlock();
1584 return D3D_OK;
1587 static HRESULT WINAPI d3d8_device_GetMaterial(IDirect3DDevice8 *iface, D3DMATERIAL8 *material)
1589 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1591 TRACE("iface %p, material %p.\n", iface, material);
1593 /* Note: D3DMATERIAL8 is compatible with struct wined3d_material. */
1594 wined3d_mutex_lock();
1595 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
1596 wined3d_mutex_unlock();
1598 return D3D_OK;
1601 static HRESULT WINAPI d3d8_device_SetLight(IDirect3DDevice8 *iface, DWORD index, const D3DLIGHT8 *light)
1603 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1604 HRESULT hr;
1606 TRACE("iface %p, index %u, light %p.\n", iface, index, light);
1608 /* Note: D3DLIGHT8 is compatible with struct wined3d_light. */
1609 wined3d_mutex_lock();
1610 hr = wined3d_device_set_light(device->wined3d_device, index, (const struct wined3d_light *)light);
1611 wined3d_mutex_unlock();
1613 return hr;
1616 static HRESULT WINAPI d3d8_device_GetLight(IDirect3DDevice8 *iface, DWORD index, D3DLIGHT8 *light)
1618 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1619 HRESULT hr;
1621 TRACE("iface %p, index %u, light %p.\n", iface, index, light);
1623 /* Note: D3DLIGHT8 is compatible with struct wined3d_light. */
1624 wined3d_mutex_lock();
1625 hr = wined3d_device_get_light(device->wined3d_device, index, (struct wined3d_light *)light);
1626 wined3d_mutex_unlock();
1628 return hr;
1631 static HRESULT WINAPI d3d8_device_LightEnable(IDirect3DDevice8 *iface, DWORD index, BOOL enable)
1633 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1634 HRESULT hr;
1636 TRACE("iface %p, index %u, enable %#x.\n", iface, index, enable);
1638 wined3d_mutex_lock();
1639 hr = wined3d_device_set_light_enable(device->wined3d_device, index, enable);
1640 wined3d_mutex_unlock();
1642 return hr;
1645 static HRESULT WINAPI d3d8_device_GetLightEnable(IDirect3DDevice8 *iface, DWORD index, BOOL *enable)
1647 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1648 HRESULT hr;
1650 TRACE("iface %p, index %u, enable %p.\n", iface, index, enable);
1652 wined3d_mutex_lock();
1653 hr = wined3d_device_get_light_enable(device->wined3d_device, index, enable);
1654 wined3d_mutex_unlock();
1656 return hr;
1659 static HRESULT WINAPI d3d8_device_SetClipPlane(IDirect3DDevice8 *iface, DWORD index, const float *plane)
1661 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1662 HRESULT hr;
1664 TRACE("iface %p, index %u, plane %p.\n", iface, index, plane);
1666 wined3d_mutex_lock();
1667 hr = wined3d_device_set_clip_plane(device->wined3d_device, index, (const struct wined3d_vec4 *)plane);
1668 wined3d_mutex_unlock();
1670 return hr;
1673 static HRESULT WINAPI d3d8_device_GetClipPlane(IDirect3DDevice8 *iface, DWORD index, float *plane)
1675 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1676 HRESULT hr;
1678 TRACE("iface %p, index %u, plane %p.\n", iface, index, plane);
1680 wined3d_mutex_lock();
1681 hr = wined3d_device_get_clip_plane(device->wined3d_device, index, (struct wined3d_vec4 *)plane);
1682 wined3d_mutex_unlock();
1684 return hr;
1687 static HRESULT WINAPI d3d8_device_SetRenderState(IDirect3DDevice8 *iface,
1688 D3DRENDERSTATETYPE state, DWORD value)
1690 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1692 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
1694 wined3d_mutex_lock();
1695 switch (state)
1697 case D3DRS_ZBIAS:
1698 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
1699 break;
1701 default:
1702 wined3d_device_set_render_state(device->wined3d_device, state, value);
1704 wined3d_mutex_unlock();
1706 return D3D_OK;
1709 static HRESULT WINAPI d3d8_device_GetRenderState(IDirect3DDevice8 *iface,
1710 D3DRENDERSTATETYPE state, DWORD *value)
1712 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1714 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
1716 wined3d_mutex_lock();
1717 switch (state)
1719 case D3DRS_ZBIAS:
1720 *value = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS);
1721 break;
1723 default:
1724 *value = wined3d_device_get_render_state(device->wined3d_device, state);
1726 wined3d_mutex_unlock();
1728 return D3D_OK;
1731 static HRESULT WINAPI d3d8_device_BeginStateBlock(IDirect3DDevice8 *iface)
1733 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1734 HRESULT hr;
1736 TRACE("iface %p.\n", iface);
1738 wined3d_mutex_lock();
1739 hr = wined3d_device_begin_stateblock(device->wined3d_device);
1740 wined3d_mutex_unlock();
1742 return hr;
1745 static HRESULT WINAPI d3d8_device_EndStateBlock(IDirect3DDevice8 *iface, DWORD *token)
1747 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1748 struct wined3d_stateblock *stateblock;
1749 HRESULT hr;
1751 TRACE("iface %p, token %p.\n", iface, token);
1753 /* Tell wineD3D to endstateblock before anything else (in case we run out
1754 * of memory later and cause locking problems)
1756 wined3d_mutex_lock();
1757 hr = wined3d_device_end_stateblock(device->wined3d_device, &stateblock);
1758 if (FAILED(hr))
1760 WARN("Failed to end the state block, %#x.\n", hr);
1761 wined3d_mutex_unlock();
1762 return hr;
1765 *token = d3d8_allocate_handle(&device->handle_table, stateblock, D3D8_HANDLE_SB);
1766 wined3d_mutex_unlock();
1768 if (*token == D3D8_INVALID_HANDLE)
1770 ERR("Failed to create a handle\n");
1771 wined3d_mutex_lock();
1772 wined3d_stateblock_decref(stateblock);
1773 wined3d_mutex_unlock();
1774 return E_FAIL;
1776 ++*token;
1778 TRACE("Returning %#x (%p).\n", *token, stateblock);
1780 return hr;
1783 static HRESULT WINAPI d3d8_device_ApplyStateBlock(IDirect3DDevice8 *iface, DWORD token)
1785 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1786 struct wined3d_stateblock *stateblock;
1788 TRACE("iface %p, token %#x.\n", iface, token);
1790 if (!token)
1791 return D3D_OK;
1793 wined3d_mutex_lock();
1794 stateblock = d3d8_get_object(&device->handle_table, token - 1, D3D8_HANDLE_SB);
1795 if (!stateblock)
1797 WARN("Invalid handle (%#x) passed.\n", token);
1798 wined3d_mutex_unlock();
1799 return D3DERR_INVALIDCALL;
1801 wined3d_stateblock_apply(stateblock);
1802 wined3d_mutex_unlock();
1804 return D3D_OK;
1807 static HRESULT WINAPI d3d8_device_CaptureStateBlock(IDirect3DDevice8 *iface, DWORD token)
1809 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1810 struct wined3d_stateblock *stateblock;
1812 TRACE("iface %p, token %#x.\n", iface, token);
1814 wined3d_mutex_lock();
1815 stateblock = d3d8_get_object(&device->handle_table, token - 1, D3D8_HANDLE_SB);
1816 if (!stateblock)
1818 WARN("Invalid handle (%#x) passed.\n", token);
1819 wined3d_mutex_unlock();
1820 return D3DERR_INVALIDCALL;
1822 wined3d_stateblock_capture(stateblock);
1823 wined3d_mutex_unlock();
1825 return D3D_OK;
1828 static HRESULT WINAPI d3d8_device_DeleteStateBlock(IDirect3DDevice8 *iface, DWORD token)
1830 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1831 struct wined3d_stateblock *stateblock;
1833 TRACE("iface %p, token %#x.\n", iface, token);
1835 wined3d_mutex_lock();
1836 stateblock = d3d8_free_handle(&device->handle_table, token - 1, D3D8_HANDLE_SB);
1838 if (!stateblock)
1840 WARN("Invalid handle (%#x) passed.\n", token);
1841 wined3d_mutex_unlock();
1842 return D3DERR_INVALIDCALL;
1845 if (wined3d_stateblock_decref(stateblock))
1847 ERR("Stateblock %p has references left, this shouldn't happen.\n", stateblock);
1849 wined3d_mutex_unlock();
1851 return D3D_OK;
1854 static HRESULT WINAPI d3d8_device_CreateStateBlock(IDirect3DDevice8 *iface,
1855 D3DSTATEBLOCKTYPE type, DWORD *handle)
1857 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1858 struct wined3d_stateblock *stateblock;
1859 HRESULT hr;
1861 TRACE("iface %p, type %#x, handle %p.\n", iface, type, handle);
1863 if (type != D3DSBT_ALL
1864 && type != D3DSBT_PIXELSTATE
1865 && type != D3DSBT_VERTEXSTATE)
1867 WARN("Unexpected stateblock type, returning D3DERR_INVALIDCALL\n");
1868 return D3DERR_INVALIDCALL;
1871 wined3d_mutex_lock();
1872 hr = wined3d_stateblock_create(device->wined3d_device, (enum wined3d_stateblock_type)type, &stateblock);
1873 if (FAILED(hr))
1875 wined3d_mutex_unlock();
1876 ERR("Failed to create the state block, hr %#x\n", hr);
1877 return hr;
1880 *handle = d3d8_allocate_handle(&device->handle_table, stateblock, D3D8_HANDLE_SB);
1881 wined3d_mutex_unlock();
1883 if (*handle == D3D8_INVALID_HANDLE)
1885 ERR("Failed to allocate a handle.\n");
1886 wined3d_mutex_lock();
1887 wined3d_stateblock_decref(stateblock);
1888 wined3d_mutex_unlock();
1889 return E_FAIL;
1891 ++*handle;
1893 TRACE("Returning %#x (%p).\n", *handle, stateblock);
1895 return hr;
1898 static HRESULT WINAPI d3d8_device_SetClipStatus(IDirect3DDevice8 *iface, const D3DCLIPSTATUS8 *clip_status)
1900 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1901 HRESULT hr;
1903 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
1904 /* FIXME: Verify that D3DCLIPSTATUS8 ~= struct wined3d_clip_status. */
1906 wined3d_mutex_lock();
1907 hr = wined3d_device_set_clip_status(device->wined3d_device, (const struct wined3d_clip_status *)clip_status);
1908 wined3d_mutex_unlock();
1910 return hr;
1913 static HRESULT WINAPI d3d8_device_GetClipStatus(IDirect3DDevice8 *iface, D3DCLIPSTATUS8 *clip_status)
1915 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1916 HRESULT hr;
1918 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
1920 wined3d_mutex_lock();
1921 hr = wined3d_device_get_clip_status(device->wined3d_device, (struct wined3d_clip_status *)clip_status);
1922 wined3d_mutex_unlock();
1924 return hr;
1927 static HRESULT WINAPI d3d8_device_GetTexture(IDirect3DDevice8 *iface, DWORD stage, IDirect3DBaseTexture8 **texture)
1929 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1930 struct wined3d_texture *wined3d_texture;
1931 struct d3d8_texture *texture_impl;
1933 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
1935 if (!texture)
1936 return D3DERR_INVALIDCALL;
1938 wined3d_mutex_lock();
1939 if ((wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
1941 texture_impl = wined3d_texture_get_parent(wined3d_texture);
1942 *texture = &texture_impl->IDirect3DBaseTexture8_iface;
1943 IDirect3DBaseTexture8_AddRef(*texture);
1945 else
1947 *texture = NULL;
1949 wined3d_mutex_unlock();
1951 return D3D_OK;
1954 static HRESULT WINAPI d3d8_device_SetTexture(IDirect3DDevice8 *iface, DWORD stage, IDirect3DBaseTexture8 *texture)
1956 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
1957 struct d3d8_texture *texture_impl;
1958 HRESULT hr;
1960 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
1962 texture_impl = unsafe_impl_from_IDirect3DBaseTexture8(texture);
1964 wined3d_mutex_lock();
1965 hr = wined3d_device_set_texture(device->wined3d_device, stage,
1966 texture_impl ? texture_impl->wined3d_texture : NULL);
1967 wined3d_mutex_unlock();
1969 return hr;
1972 static const struct tss_lookup
1974 BOOL sampler_state;
1975 union
1977 enum wined3d_texture_stage_state texture_state;
1978 enum wined3d_sampler_state sampler_state;
1979 } u;
1981 tss_lookup[] =
1983 {FALSE, {WINED3D_TSS_INVALID}}, /* 0, unused */
1984 {FALSE, {WINED3D_TSS_COLOR_OP}}, /* 1, D3DTSS_COLOROP */
1985 {FALSE, {WINED3D_TSS_COLOR_ARG1}}, /* 2, D3DTSS_COLORARG1 */
1986 {FALSE, {WINED3D_TSS_COLOR_ARG2}}, /* 3, D3DTSS_COLORARG2 */
1987 {FALSE, {WINED3D_TSS_ALPHA_OP}}, /* 4, D3DTSS_ALPHAOP */
1988 {FALSE, {WINED3D_TSS_ALPHA_ARG1}}, /* 5, D3DTSS_ALPHAARG1 */
1989 {FALSE, {WINED3D_TSS_ALPHA_ARG2}}, /* 6, D3DTSS_ALPHAARG2 */
1990 {FALSE, {WINED3D_TSS_BUMPENV_MAT00}}, /* 7, D3DTSS_BUMPENVMAT00 */
1991 {FALSE, {WINED3D_TSS_BUMPENV_MAT01}}, /* 8, D3DTSS_BUMPENVMAT01 */
1992 {FALSE, {WINED3D_TSS_BUMPENV_MAT10}}, /* 9, D3DTSS_BUMPENVMAT10 */
1993 {FALSE, {WINED3D_TSS_BUMPENV_MAT11}}, /* 10, D3DTSS_BUMPENVMAT11 */
1994 {FALSE, {WINED3D_TSS_TEXCOORD_INDEX}}, /* 11, D3DTSS_TEXCOORDINDEX */
1995 {FALSE, {WINED3D_TSS_INVALID}}, /* 12, unused */
1996 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 13, D3DTSS_ADDRESSU */
1997 {TRUE, {WINED3D_SAMP_ADDRESS_V}}, /* 14, D3DTSS_ADDRESSV */
1998 {TRUE, {WINED3D_SAMP_BORDER_COLOR}}, /* 15, D3DTSS_BORDERCOLOR */
1999 {TRUE, {WINED3D_SAMP_MAG_FILTER}}, /* 16, D3DTSS_MAGFILTER */
2000 {TRUE, {WINED3D_SAMP_MIN_FILTER}}, /* 17, D3DTSS_MINFILTER */
2001 {TRUE, {WINED3D_SAMP_MIP_FILTER}}, /* 18, D3DTSS_MIPFILTER */
2002 {TRUE, {WINED3D_SAMP_MIPMAP_LOD_BIAS}}, /* 19, D3DTSS_MIPMAPLODBIAS */
2003 {TRUE, {WINED3D_SAMP_MAX_MIP_LEVEL}}, /* 20, D3DTSS_MAXMIPLEVEL */
2004 {TRUE, {WINED3D_SAMP_MAX_ANISOTROPY}}, /* 21, D3DTSS_MAXANISOTROPY */
2005 {FALSE, {WINED3D_TSS_BUMPENV_LSCALE}}, /* 22, D3DTSS_BUMPENVLSCALE */
2006 {FALSE, {WINED3D_TSS_BUMPENV_LOFFSET}}, /* 23, D3DTSS_BUMPENVLOFFSET */
2007 {FALSE, {WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
2008 {TRUE, {WINED3D_SAMP_ADDRESS_W}}, /* 25, D3DTSS_ADDRESSW */
2009 {FALSE, {WINED3D_TSS_COLOR_ARG0}}, /* 26, D3DTSS_COLORARG0 */
2010 {FALSE, {WINED3D_TSS_ALPHA_ARG0}}, /* 27, D3DTSS_ALPHAARG0 */
2011 {FALSE, {WINED3D_TSS_RESULT_ARG}}, /* 28, D3DTSS_RESULTARG */
2014 static HRESULT WINAPI d3d8_device_GetTextureStageState(IDirect3DDevice8 *iface,
2015 DWORD stage, D3DTEXTURESTAGESTATETYPE Type, DWORD *value)
2017 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2018 const struct tss_lookup *l;
2020 TRACE("iface %p, stage %u, state %#x, value %p.\n", iface, stage, Type, value);
2022 if (Type >= sizeof(tss_lookup) / sizeof(*tss_lookup))
2024 WARN("Invalid Type %#x passed.\n", Type);
2025 return D3D_OK;
2028 l = &tss_lookup[Type];
2030 wined3d_mutex_lock();
2031 if (l->sampler_state)
2032 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->u.sampler_state);
2033 else
2034 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->u.texture_state);
2035 wined3d_mutex_unlock();
2037 return D3D_OK;
2040 static HRESULT WINAPI d3d8_device_SetTextureStageState(IDirect3DDevice8 *iface,
2041 DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value)
2043 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2044 const struct tss_lookup *l;
2046 TRACE("iface %p, stage %u, state %#x, value %#x.\n", iface, stage, type, value);
2048 if (type >= sizeof(tss_lookup) / sizeof(*tss_lookup))
2050 WARN("Invalid type %#x passed.\n", type);
2051 return D3D_OK;
2054 l = &tss_lookup[type];
2056 wined3d_mutex_lock();
2057 if (l->sampler_state)
2058 wined3d_device_set_sampler_state(device->wined3d_device, stage, l->u.sampler_state, value);
2059 else
2060 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->u.texture_state, value);
2061 wined3d_mutex_unlock();
2063 return D3D_OK;
2066 static HRESULT WINAPI d3d8_device_ValidateDevice(IDirect3DDevice8 *iface, DWORD *pass_count)
2068 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2069 HRESULT hr;
2071 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
2073 wined3d_mutex_lock();
2074 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
2075 wined3d_mutex_unlock();
2077 return hr;
2080 static HRESULT WINAPI d3d8_device_GetInfo(IDirect3DDevice8 *iface,
2081 DWORD info_id, void *info, DWORD info_size)
2083 FIXME("iface %p, info_id %#x, info %p, info_size %u stub!\n", iface, info_id, info, info_size);
2085 return D3D_OK;
2088 static HRESULT WINAPI d3d8_device_SetPaletteEntries(IDirect3DDevice8 *iface,
2089 UINT palette_idx, const PALETTEENTRY *entries)
2091 WARN("iface %p, palette_idx %u, entries %p unimplemented\n", iface, palette_idx, entries);
2093 /* GPUs stopped supporting palettized textures with the Shader Model 1 generation. Wined3d
2094 * does not have a d3d8/9-style palette API */
2096 return D3D_OK;
2099 static HRESULT WINAPI d3d8_device_GetPaletteEntries(IDirect3DDevice8 *iface,
2100 UINT palette_idx, PALETTEENTRY *entries)
2102 FIXME("iface %p, palette_idx %u, entries %p unimplemented.\n", iface, palette_idx, entries);
2104 return D3DERR_INVALIDCALL;
2107 static HRESULT WINAPI d3d8_device_SetCurrentTexturePalette(IDirect3DDevice8 *iface, UINT palette_idx)
2109 WARN("iface %p, palette_idx %u unimplemented.\n", iface, palette_idx);
2111 return D3D_OK;
2114 static HRESULT WINAPI d3d8_device_GetCurrentTexturePalette(IDirect3DDevice8 *iface, UINT *palette_idx)
2116 FIXME("iface %p, palette_idx %p unimplemented.\n", iface, palette_idx);
2118 return D3DERR_INVALIDCALL;
2121 static HRESULT WINAPI d3d8_device_DrawPrimitive(IDirect3DDevice8 *iface,
2122 D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count)
2124 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2125 HRESULT hr;
2127 TRACE("iface %p, primitive_type %#x, start_vertex %u, primitive_count %u.\n",
2128 iface, primitive_type, start_vertex, primitive_count);
2130 wined3d_mutex_lock();
2131 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
2132 hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex,
2133 vertex_count_from_primitive_count(primitive_type, primitive_count));
2134 wined3d_mutex_unlock();
2136 return hr;
2139 static HRESULT WINAPI d3d8_device_DrawIndexedPrimitive(IDirect3DDevice8 *iface,
2140 D3DPRIMITIVETYPE primitive_type, UINT min_vertex_idx, UINT vertex_count,
2141 UINT start_idx, UINT primitive_count)
2143 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2144 HRESULT hr;
2146 TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, vertex_count %u, start_idx %u, primitive_count %u.\n",
2147 iface, primitive_type, min_vertex_idx, vertex_count, start_idx, primitive_count);
2149 wined3d_mutex_lock();
2150 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
2151 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, start_idx,
2152 vertex_count_from_primitive_count(primitive_type, primitive_count));
2153 wined3d_mutex_unlock();
2155 return hr;
2158 /* The caller is responsible for wined3d locking */
2159 static HRESULT d3d8_device_prepare_vertex_buffer(struct d3d8_device *device, UINT min_size)
2161 HRESULT hr;
2163 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
2165 UINT size = max(device->vertex_buffer_size * 2, min_size);
2166 struct wined3d_buffer_desc desc;
2167 struct wined3d_buffer *buffer;
2169 TRACE("Growing vertex buffer to %u bytes\n", size);
2171 desc.byte_width = size;
2172 desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY;
2173 desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
2174 desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
2175 desc.misc_flags = 0;
2176 desc.structure_byte_stride = 0;
2178 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc,
2179 NULL, NULL, &d3d8_null_wined3d_parent_ops, &buffer)))
2181 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
2182 return hr;
2185 if (device->vertex_buffer)
2186 wined3d_buffer_decref(device->vertex_buffer);
2188 device->vertex_buffer = buffer;
2189 device->vertex_buffer_size = size;
2190 device->vertex_buffer_pos = 0;
2192 return D3D_OK;
2195 static HRESULT WINAPI d3d8_device_DrawPrimitiveUP(IDirect3DDevice8 *iface,
2196 D3DPRIMITIVETYPE primitive_type, UINT primitive_count, const void *data,
2197 UINT stride)
2199 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2200 HRESULT hr;
2201 UINT vtx_count = vertex_count_from_primitive_count(primitive_type, primitive_count);
2202 struct wined3d_map_desc wined3d_map_desc;
2203 struct wined3d_box wined3d_box = {0};
2204 UINT size = vtx_count * stride;
2205 struct wined3d_resource *vb;
2206 UINT vb_pos, align;
2208 TRACE("iface %p, primitive_type %#x, primitive_count %u, data %p, stride %u.\n",
2209 iface, primitive_type, primitive_count, data, stride);
2211 if (!primitive_count)
2213 WARN("primitive_count is 0, returning D3D_OK\n");
2214 return D3D_OK;
2217 wined3d_mutex_lock();
2218 hr = d3d8_device_prepare_vertex_buffer(device, size);
2219 if (FAILED(hr))
2220 goto done;
2222 vb_pos = device->vertex_buffer_pos;
2223 align = vb_pos % stride;
2224 if (align) align = stride - align;
2225 if (vb_pos + size + align > device->vertex_buffer_size)
2226 vb_pos = 0;
2227 else
2228 vb_pos += align;
2230 wined3d_box.left = vb_pos;
2231 wined3d_box.right = vb_pos + size;
2232 vb = wined3d_buffer_get_resource(device->vertex_buffer);
2233 if (FAILED(wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
2234 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
2235 goto done;
2236 memcpy(wined3d_map_desc.data, data, size);
2237 wined3d_resource_unmap(vb, 0);
2238 device->vertex_buffer_pos = vb_pos + size;
2240 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
2241 if (FAILED(hr))
2242 goto done;
2244 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
2245 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vtx_count);
2246 wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0);
2248 done:
2249 wined3d_mutex_unlock();
2250 return hr;
2253 /* The caller is responsible for wined3d locking */
2254 static HRESULT d3d8_device_prepare_index_buffer(struct d3d8_device *device, UINT min_size)
2256 HRESULT hr;
2258 if (device->index_buffer_size < min_size || !device->index_buffer)
2260 UINT size = max(device->index_buffer_size * 2, min_size);
2261 struct wined3d_buffer_desc desc;
2262 struct wined3d_buffer *buffer;
2264 TRACE("Growing index buffer to %u bytes\n", size);
2266 desc.byte_width = size;
2267 desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_STATICDECL;
2268 desc.bind_flags = WINED3D_BIND_INDEX_BUFFER;
2269 desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W;
2270 desc.misc_flags = 0;
2271 desc.structure_byte_stride = 0;
2273 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc,
2274 NULL, NULL, &d3d8_null_wined3d_parent_ops, &buffer)))
2276 ERR("Failed to create index buffer, hr %#x.\n", hr);
2277 return hr;
2280 if (device->index_buffer)
2281 wined3d_buffer_decref(device->index_buffer);
2283 device->index_buffer = buffer;
2284 device->index_buffer_size = size;
2285 device->index_buffer_pos = 0;
2287 return D3D_OK;
2290 static HRESULT WINAPI d3d8_device_DrawIndexedPrimitiveUP(IDirect3DDevice8 *iface,
2291 D3DPRIMITIVETYPE primitive_type, UINT min_vertex_idx, UINT vertex_count,
2292 UINT primitive_count, const void *index_data, D3DFORMAT index_format,
2293 const void *vertex_data, UINT vertex_stride)
2295 UINT idx_count = vertex_count_from_primitive_count(primitive_type, primitive_count);
2296 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2297 UINT idx_fmt_size = index_format == D3DFMT_INDEX16 ? 2 : 4;
2298 UINT vtx_size = vertex_count * vertex_stride;
2299 UINT idx_size = idx_count * idx_fmt_size;
2300 struct wined3d_map_desc wined3d_map_desc;
2301 struct wined3d_box wined3d_box = {0};
2302 struct wined3d_resource *ib, *vb;
2303 UINT vb_pos, ib_pos, align;
2304 HRESULT hr;
2306 TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, vertex_count %u, primitive_count %u, "
2307 "index_data %p, index_format %#x, vertex_data %p, vertex_stride %u.\n",
2308 iface, primitive_type, min_vertex_idx, vertex_count, primitive_count,
2309 index_data, index_format, vertex_data, vertex_stride);
2311 if (!primitive_count)
2313 WARN("primitive_count is 0, returning D3D_OK\n");
2314 return D3D_OK;
2317 wined3d_mutex_lock();
2319 hr = d3d8_device_prepare_vertex_buffer(device, vtx_size);
2320 if (FAILED(hr))
2321 goto done;
2323 vb_pos = device->vertex_buffer_pos;
2324 align = vb_pos % vertex_stride;
2325 if (align) align = vertex_stride - align;
2326 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
2327 vb_pos = 0;
2328 else
2329 vb_pos += align;
2331 wined3d_box.left = vb_pos;
2332 wined3d_box.right = vb_pos + vtx_size;
2333 vb = wined3d_buffer_get_resource(device->vertex_buffer);
2334 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
2335 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
2336 goto done;
2337 memcpy(wined3d_map_desc.data, (char *)vertex_data + min_vertex_idx * vertex_stride, vtx_size);
2338 wined3d_resource_unmap(vb, 0);
2339 device->vertex_buffer_pos = vb_pos + vtx_size;
2341 hr = d3d8_device_prepare_index_buffer(device, idx_size);
2342 if (FAILED(hr))
2343 goto done;
2345 ib_pos = device->index_buffer_pos;
2346 align = ib_pos % idx_fmt_size;
2347 if (align) align = idx_fmt_size - align;
2348 if (ib_pos + idx_size + align > device->index_buffer_size)
2349 ib_pos = 0;
2350 else
2351 ib_pos += align;
2353 wined3d_box.left = ib_pos;
2354 wined3d_box.right = ib_pos + idx_size;
2355 ib = wined3d_buffer_get_resource(device->index_buffer);
2356 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
2357 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
2358 goto done;
2359 memcpy(wined3d_map_desc.data, index_data, idx_size);
2360 wined3d_resource_unmap(ib, 0);
2361 device->index_buffer_pos = ib_pos + idx_size;
2363 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vertex_stride);
2364 if (FAILED(hr))
2365 goto done;
2367 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer,
2368 wined3dformat_from_d3dformat(index_format), 0);
2369 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vertex_stride - min_vertex_idx);
2371 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
2372 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / idx_fmt_size, idx_count);
2374 wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0);
2375 wined3d_device_set_index_buffer(device->wined3d_device, NULL, WINED3DFMT_UNKNOWN, 0);
2376 wined3d_device_set_base_vertex_index(device->wined3d_device, 0);
2378 done:
2379 wined3d_mutex_unlock();
2380 return hr;
2383 static HRESULT WINAPI d3d8_device_ProcessVertices(IDirect3DDevice8 *iface, UINT src_start_idx,
2384 UINT dst_idx, UINT vertex_count, IDirect3DVertexBuffer8 *dst_buffer, DWORD flags)
2386 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2387 struct d3d8_vertexbuffer *dst = unsafe_impl_from_IDirect3DVertexBuffer8(dst_buffer);
2388 HRESULT hr;
2390 TRACE("iface %p, src_start_idx %u, dst_idx %u, vertex_count %u, dst_buffer %p, flags %#x.\n",
2391 iface, src_start_idx, dst_idx, vertex_count, dst_buffer, flags);
2393 wined3d_mutex_lock();
2394 hr = wined3d_device_process_vertices(device->wined3d_device, src_start_idx, dst_idx,
2395 vertex_count, dst->wined3d_buffer, NULL, flags, dst->fvf);
2396 wined3d_mutex_unlock();
2398 return hr;
2401 static HRESULT WINAPI d3d8_device_CreateVertexShader(IDirect3DDevice8 *iface,
2402 const DWORD *declaration, const DWORD *byte_code, DWORD *shader, DWORD usage)
2404 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2405 struct d3d8_vertex_shader *object;
2406 DWORD shader_handle;
2407 DWORD handle;
2408 HRESULT hr;
2410 TRACE("iface %p, declaration %p, byte_code %p, shader %p, usage %#x.\n",
2411 iface, declaration, byte_code, shader, usage);
2413 if (!(object = heap_alloc_zero(sizeof(*object))))
2415 *shader = 0;
2416 return E_OUTOFMEMORY;
2419 wined3d_mutex_lock();
2420 handle = d3d8_allocate_handle(&device->handle_table, object, D3D8_HANDLE_VS);
2421 wined3d_mutex_unlock();
2422 if (handle == D3D8_INVALID_HANDLE)
2424 ERR("Failed to allocate vertex shader handle.\n");
2425 heap_free(object);
2426 *shader = 0;
2427 return E_OUTOFMEMORY;
2430 shader_handle = handle + VS_HIGHESTFIXEDFXF + 1;
2432 hr = d3d8_vertex_shader_init(object, device, declaration, byte_code, shader_handle, usage);
2433 if (FAILED(hr))
2435 WARN("Failed to initialize vertex shader, hr %#x.\n", hr);
2436 wined3d_mutex_lock();
2437 d3d8_free_handle(&device->handle_table, handle, D3D8_HANDLE_VS);
2438 wined3d_mutex_unlock();
2439 heap_free(object);
2440 *shader = 0;
2441 return hr;
2444 TRACE("Created vertex shader %p (handle %#x).\n", object, shader_handle);
2445 *shader = shader_handle;
2447 return D3D_OK;
2450 static struct d3d8_vertex_declaration *d3d8_device_get_fvf_declaration(struct d3d8_device *device, DWORD fvf)
2452 struct d3d8_vertex_declaration *d3d8_declaration;
2453 struct FvfToDecl *convertedDecls = device->decls;
2454 int p, low, high; /* deliberately signed */
2455 HRESULT hr;
2457 TRACE("Searching for declaration for fvf %08x... ", fvf);
2459 low = 0;
2460 high = device->numConvertedDecls - 1;
2461 while (low <= high)
2463 p = (low + high) >> 1;
2464 TRACE("%d ", p);
2466 if (convertedDecls[p].fvf == fvf)
2468 TRACE("found %p\n", convertedDecls[p].declaration);
2469 return convertedDecls[p].declaration;
2472 if (convertedDecls[p].fvf < fvf)
2473 low = p + 1;
2474 else
2475 high = p - 1;
2477 TRACE("not found. Creating and inserting at position %d.\n", low);
2479 if (!(d3d8_declaration = heap_alloc(sizeof(*d3d8_declaration))))
2480 return NULL;
2482 if (FAILED(hr = d3d8_vertex_declaration_init_fvf(d3d8_declaration, device, fvf)))
2484 WARN("Failed to initialize vertex declaration, hr %#x.\n", hr);
2485 heap_free(d3d8_declaration);
2486 return NULL;
2489 if (device->declArraySize == device->numConvertedDecls)
2491 UINT grow = device->declArraySize / 2;
2493 if (!(convertedDecls = heap_realloc(convertedDecls,
2494 sizeof(*convertedDecls) * (device->numConvertedDecls + grow))))
2496 d3d8_vertex_declaration_destroy(d3d8_declaration);
2497 return NULL;
2499 device->decls = convertedDecls;
2500 device->declArraySize += grow;
2503 memmove(convertedDecls + low + 1, convertedDecls + low,
2504 sizeof(*convertedDecls) * (device->numConvertedDecls - low));
2505 convertedDecls[low].declaration = d3d8_declaration;
2506 convertedDecls[low].fvf = fvf;
2507 ++device->numConvertedDecls;
2509 TRACE("Returning %p. %u decls in array.\n", d3d8_declaration, device->numConvertedDecls);
2511 return d3d8_declaration;
2514 static HRESULT WINAPI d3d8_device_SetVertexShader(IDirect3DDevice8 *iface, DWORD shader)
2516 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2517 struct d3d8_vertex_shader *shader_impl;
2519 TRACE("iface %p, shader %#x.\n", iface, shader);
2521 if (VS_HIGHESTFIXEDFXF >= shader)
2523 TRACE("Setting FVF, %#x\n", shader);
2525 wined3d_mutex_lock();
2526 wined3d_device_set_vertex_declaration(device->wined3d_device,
2527 d3d8_device_get_fvf_declaration(device, shader)->wined3d_vertex_declaration);
2528 wined3d_device_set_vertex_shader(device->wined3d_device, NULL);
2529 wined3d_mutex_unlock();
2531 return D3D_OK;
2534 TRACE("Setting shader\n");
2536 wined3d_mutex_lock();
2537 if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS)))
2539 WARN("Invalid handle (%#x) passed.\n", shader);
2540 wined3d_mutex_unlock();
2542 return D3DERR_INVALIDCALL;
2545 wined3d_device_set_vertex_declaration(device->wined3d_device,
2546 shader_impl->vertex_declaration->wined3d_vertex_declaration);
2547 wined3d_device_set_vertex_shader(device->wined3d_device, shader_impl->wined3d_shader);
2548 wined3d_mutex_unlock();
2550 return D3D_OK;
2553 static HRESULT WINAPI d3d8_device_GetVertexShader(IDirect3DDevice8 *iface, DWORD *shader)
2555 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2556 struct wined3d_vertex_declaration *wined3d_declaration;
2557 struct d3d8_vertex_declaration *d3d8_declaration;
2559 TRACE("iface %p, shader %p.\n", iface, shader);
2561 wined3d_mutex_lock();
2562 if ((wined3d_declaration = wined3d_device_get_vertex_declaration(device->wined3d_device)))
2564 d3d8_declaration = wined3d_vertex_declaration_get_parent(wined3d_declaration);
2565 *shader = d3d8_declaration->shader_handle;
2567 else
2569 *shader = 0;
2571 wined3d_mutex_unlock();
2573 TRACE("Returning %#x.\n", *shader);
2575 return D3D_OK;
2578 static HRESULT WINAPI d3d8_device_DeleteVertexShader(IDirect3DDevice8 *iface, DWORD shader)
2580 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2581 struct d3d8_vertex_shader *shader_impl;
2583 TRACE("iface %p, shader %#x.\n", iface, shader);
2585 wined3d_mutex_lock();
2586 if (!(shader_impl = d3d8_free_handle(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS)))
2588 WARN("Invalid handle (%#x) passed.\n", shader);
2589 wined3d_mutex_unlock();
2591 return D3DERR_INVALIDCALL;
2594 if (shader_impl->wined3d_shader
2595 && wined3d_device_get_vertex_shader(device->wined3d_device) == shader_impl->wined3d_shader)
2596 IDirect3DDevice8_SetVertexShader(iface, 0);
2598 wined3d_mutex_unlock();
2600 d3d8_vertex_shader_destroy(shader_impl);
2602 return D3D_OK;
2605 static HRESULT WINAPI d3d8_device_SetVertexShaderConstant(IDirect3DDevice8 *iface,
2606 DWORD start_register, const void *data, DWORD count)
2608 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2609 HRESULT hr;
2611 TRACE("iface %p, start_register %u, data %p, count %u.\n",
2612 iface, start_register, data, count);
2614 if (start_register + count > D3D8_MAX_VERTEX_SHADER_CONSTANTF)
2616 WARN("Trying to access %u constants, but d3d8 only supports %u\n",
2617 start_register + count, D3D8_MAX_VERTEX_SHADER_CONSTANTF);
2618 return D3DERR_INVALIDCALL;
2621 wined3d_mutex_lock();
2622 hr = wined3d_device_set_vs_consts_f(device->wined3d_device, start_register, count, data);
2623 wined3d_mutex_unlock();
2625 return hr;
2628 static HRESULT WINAPI d3d8_device_GetVertexShaderConstant(IDirect3DDevice8 *iface,
2629 DWORD start_register, void *data, DWORD count)
2631 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2632 HRESULT hr;
2634 TRACE("iface %p, start_register %u, data %p, count %u.\n",
2635 iface, start_register, data, count);
2637 if (start_register + count > D3D8_MAX_VERTEX_SHADER_CONSTANTF)
2639 WARN("Trying to access %u constants, but d3d8 only supports %u\n",
2640 start_register + count, D3D8_MAX_VERTEX_SHADER_CONSTANTF);
2641 return D3DERR_INVALIDCALL;
2644 wined3d_mutex_lock();
2645 hr = wined3d_device_get_vs_consts_f(device->wined3d_device, start_register, count, data);
2646 wined3d_mutex_unlock();
2648 return hr;
2651 static HRESULT WINAPI d3d8_device_GetVertexShaderDeclaration(IDirect3DDevice8 *iface,
2652 DWORD shader, void *data, DWORD *data_size)
2654 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2655 struct d3d8_vertex_declaration *declaration;
2656 struct d3d8_vertex_shader *shader_impl;
2658 TRACE("iface %p, shader %#x, data %p, data_size %p.\n",
2659 iface, shader, data, data_size);
2661 wined3d_mutex_lock();
2662 shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS);
2663 wined3d_mutex_unlock();
2665 if (!shader_impl)
2667 WARN("Invalid handle (%#x) passed.\n", shader);
2668 return D3DERR_INVALIDCALL;
2670 declaration = shader_impl->vertex_declaration;
2672 if (!data)
2674 *data_size = declaration->elements_size;
2675 return D3D_OK;
2678 /* MSDN claims that if *data_size is smaller than the required size
2679 * we should write the required size and return D3DERR_MOREDATA.
2680 * That's not actually true. */
2681 if (*data_size < declaration->elements_size)
2682 return D3DERR_INVALIDCALL;
2684 memcpy(data, declaration->elements, declaration->elements_size);
2686 return D3D_OK;
2689 static HRESULT WINAPI d3d8_device_GetVertexShaderFunction(IDirect3DDevice8 *iface,
2690 DWORD shader, void *data, DWORD *data_size)
2692 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2693 struct d3d8_vertex_shader *shader_impl = NULL;
2694 HRESULT hr;
2696 TRACE("iface %p, shader %#x, data %p, data_size %p.\n",
2697 iface, shader, data, data_size);
2699 wined3d_mutex_lock();
2700 if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS)))
2702 WARN("Invalid handle (%#x) passed.\n", shader);
2703 wined3d_mutex_unlock();
2705 return D3DERR_INVALIDCALL;
2708 if (!shader_impl->wined3d_shader)
2710 wined3d_mutex_unlock();
2711 *data_size = 0;
2712 return D3D_OK;
2715 hr = wined3d_shader_get_byte_code(shader_impl->wined3d_shader, data, data_size);
2716 wined3d_mutex_unlock();
2718 return hr;
2721 static HRESULT WINAPI d3d8_device_SetIndices(IDirect3DDevice8 *iface,
2722 IDirect3DIndexBuffer8 *buffer, UINT base_vertex_idx)
2724 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2725 struct d3d8_indexbuffer *ib = unsafe_impl_from_IDirect3DIndexBuffer8(buffer);
2727 TRACE("iface %p, buffer %p, base_vertex_idx %u.\n", iface, buffer, base_vertex_idx);
2729 /* WineD3D takes an INT(due to d3d9), but d3d8 uses UINTs. Do I have to add a check here that
2730 * the UINT doesn't cause an overflow in the INT? It seems rather unlikely because such large
2731 * vertex buffers can't be created to address them with an index that requires the 32nd bit
2732 * (4 Byte minimum vertex size * 2^31-1 -> 8 gb buffer. The index sign would be the least
2733 * problem)
2735 wined3d_mutex_lock();
2736 wined3d_device_set_base_vertex_index(device->wined3d_device, base_vertex_idx);
2737 wined3d_device_set_index_buffer(device->wined3d_device,
2738 ib ? ib->wined3d_buffer : NULL, ib ? ib->format : WINED3DFMT_UNKNOWN, 0);
2739 wined3d_mutex_unlock();
2741 return D3D_OK;
2744 static HRESULT WINAPI d3d8_device_GetIndices(IDirect3DDevice8 *iface,
2745 IDirect3DIndexBuffer8 **buffer, UINT *base_vertex_index)
2747 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2748 enum wined3d_format_id wined3d_format;
2749 struct wined3d_buffer *wined3d_buffer;
2750 struct d3d8_indexbuffer *buffer_impl;
2752 TRACE("iface %p, buffer %p, base_vertex_index %p.\n", iface, buffer, base_vertex_index);
2754 if (!buffer)
2755 return D3DERR_INVALIDCALL;
2757 /* The case from UINT to INT is safe because d3d8 will never set negative values */
2758 wined3d_mutex_lock();
2759 *base_vertex_index = wined3d_device_get_base_vertex_index(device->wined3d_device);
2760 if ((wined3d_buffer = wined3d_device_get_index_buffer(device->wined3d_device, &wined3d_format, NULL)))
2762 buffer_impl = wined3d_buffer_get_parent(wined3d_buffer);
2763 *buffer = &buffer_impl->IDirect3DIndexBuffer8_iface;
2764 IDirect3DIndexBuffer8_AddRef(*buffer);
2766 else
2768 *buffer = NULL;
2770 wined3d_mutex_unlock();
2772 return D3D_OK;
2775 static HRESULT WINAPI d3d8_device_CreatePixelShader(IDirect3DDevice8 *iface,
2776 const DWORD *byte_code, DWORD *shader)
2778 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2779 struct d3d8_pixel_shader *object;
2780 DWORD shader_handle;
2781 DWORD handle;
2782 HRESULT hr;
2784 TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader);
2786 if (!shader)
2787 return D3DERR_INVALIDCALL;
2789 if (!(object = heap_alloc_zero(sizeof(*object))))
2790 return E_OUTOFMEMORY;
2792 wined3d_mutex_lock();
2793 handle = d3d8_allocate_handle(&device->handle_table, object, D3D8_HANDLE_PS);
2794 wined3d_mutex_unlock();
2795 if (handle == D3D8_INVALID_HANDLE)
2797 ERR("Failed to allocate pixel shader handle.\n");
2798 heap_free(object);
2799 return E_OUTOFMEMORY;
2802 shader_handle = handle + VS_HIGHESTFIXEDFXF + 1;
2804 hr = d3d8_pixel_shader_init(object, device, byte_code, shader_handle);
2805 if (FAILED(hr))
2807 WARN("Failed to initialize pixel shader, hr %#x.\n", hr);
2808 wined3d_mutex_lock();
2809 d3d8_free_handle(&device->handle_table, handle, D3D8_HANDLE_PS);
2810 wined3d_mutex_unlock();
2811 heap_free(object);
2812 *shader = 0;
2813 return hr;
2816 TRACE("Created pixel shader %p (handle %#x).\n", object, shader_handle);
2817 *shader = shader_handle;
2819 return D3D_OK;
2822 static HRESULT WINAPI d3d8_device_SetPixelShader(IDirect3DDevice8 *iface, DWORD shader)
2824 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2825 struct d3d8_pixel_shader *shader_impl;
2827 TRACE("iface %p, shader %#x.\n", iface, shader);
2829 wined3d_mutex_lock();
2831 if (!shader)
2833 wined3d_device_set_pixel_shader(device->wined3d_device, NULL);
2834 wined3d_mutex_unlock();
2835 return D3D_OK;
2838 if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS)))
2840 WARN("Invalid handle (%#x) passed.\n", shader);
2841 wined3d_mutex_unlock();
2842 return D3DERR_INVALIDCALL;
2845 TRACE("Setting shader %p.\n", shader_impl);
2846 wined3d_device_set_pixel_shader(device->wined3d_device, shader_impl->wined3d_shader);
2847 wined3d_mutex_unlock();
2849 return D3D_OK;
2852 static HRESULT WINAPI d3d8_device_GetPixelShader(IDirect3DDevice8 *iface, DWORD *shader)
2854 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2855 struct wined3d_shader *object;
2857 TRACE("iface %p, shader %p.\n", iface, shader);
2859 if (!shader)
2860 return D3DERR_INVALIDCALL;
2862 wined3d_mutex_lock();
2863 if ((object = wined3d_device_get_pixel_shader(device->wined3d_device)))
2865 struct d3d8_pixel_shader *d3d8_shader;
2866 d3d8_shader = wined3d_shader_get_parent(object);
2867 *shader = d3d8_shader->handle;
2869 else
2871 *shader = 0;
2873 wined3d_mutex_unlock();
2875 TRACE("Returning %#x.\n", *shader);
2877 return D3D_OK;
2880 static HRESULT WINAPI d3d8_device_DeletePixelShader(IDirect3DDevice8 *iface, DWORD shader)
2882 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2883 struct d3d8_pixel_shader *shader_impl;
2885 TRACE("iface %p, shader %#x.\n", iface, shader);
2887 wined3d_mutex_lock();
2889 if (!(shader_impl = d3d8_free_handle(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS)))
2891 WARN("Invalid handle (%#x) passed.\n", shader);
2892 wined3d_mutex_unlock();
2893 return D3DERR_INVALIDCALL;
2896 if (wined3d_device_get_pixel_shader(device->wined3d_device) == shader_impl->wined3d_shader)
2897 IDirect3DDevice8_SetPixelShader(iface, 0);
2899 wined3d_mutex_unlock();
2901 d3d8_pixel_shader_destroy(shader_impl);
2903 return D3D_OK;
2906 static HRESULT WINAPI d3d8_device_SetPixelShaderConstant(IDirect3DDevice8 *iface,
2907 DWORD start_register, const void *data, DWORD count)
2909 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2910 HRESULT hr;
2912 TRACE("iface %p, start_register %u, data %p, count %u.\n",
2913 iface, start_register, data, count);
2915 wined3d_mutex_lock();
2916 hr = wined3d_device_set_ps_consts_f(device->wined3d_device, start_register, count, data);
2917 wined3d_mutex_unlock();
2919 return hr;
2922 static HRESULT WINAPI d3d8_device_GetPixelShaderConstant(IDirect3DDevice8 *iface,
2923 DWORD start_register, void *data, DWORD count)
2925 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2926 HRESULT hr;
2928 TRACE("iface %p, start_register %u, data %p, count %u.\n",
2929 iface, start_register, data, count);
2931 wined3d_mutex_lock();
2932 hr = wined3d_device_get_ps_consts_f(device->wined3d_device, start_register, count, data);
2933 wined3d_mutex_unlock();
2935 return hr;
2938 static HRESULT WINAPI d3d8_device_GetPixelShaderFunction(IDirect3DDevice8 *iface,
2939 DWORD shader, void *data, DWORD *data_size)
2941 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2942 struct d3d8_pixel_shader *shader_impl = NULL;
2943 HRESULT hr;
2945 TRACE("iface %p, shader %#x, data %p, data_size %p.\n",
2946 iface, shader, data, data_size);
2948 wined3d_mutex_lock();
2949 if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS)))
2951 WARN("Invalid handle (%#x) passed.\n", shader);
2952 wined3d_mutex_unlock();
2954 return D3DERR_INVALIDCALL;
2957 hr = wined3d_shader_get_byte_code(shader_impl->wined3d_shader, data, data_size);
2958 wined3d_mutex_unlock();
2960 return hr;
2963 static HRESULT WINAPI d3d8_device_DrawRectPatch(IDirect3DDevice8 *iface, UINT handle,
2964 const float *segment_count, const D3DRECTPATCH_INFO *patch_info)
2966 FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n",
2967 iface, handle, segment_count, patch_info);
2968 return D3D_OK;
2971 static HRESULT WINAPI d3d8_device_DrawTriPatch(IDirect3DDevice8 *iface, UINT handle,
2972 const float *segment_count, const D3DTRIPATCH_INFO *patch_info)
2974 FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n",
2975 iface, handle, segment_count, patch_info);
2976 return D3D_OK;
2979 static HRESULT WINAPI d3d8_device_DeletePatch(IDirect3DDevice8 *iface, UINT handle)
2981 FIXME("iface %p, handle %#x unimplemented.\n", iface, handle);
2982 return D3DERR_INVALIDCALL;
2985 static HRESULT WINAPI d3d8_device_SetStreamSource(IDirect3DDevice8 *iface,
2986 UINT stream_idx, IDirect3DVertexBuffer8 *buffer, UINT stride)
2988 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
2989 struct d3d8_vertexbuffer *buffer_impl = unsafe_impl_from_IDirect3DVertexBuffer8(buffer);
2990 HRESULT hr;
2992 TRACE("iface %p, stream_idx %u, buffer %p, stride %u.\n",
2993 iface, stream_idx, buffer, stride);
2995 wined3d_mutex_lock();
2996 hr = wined3d_device_set_stream_source(device->wined3d_device, stream_idx,
2997 buffer_impl ? buffer_impl->wined3d_buffer : NULL, 0, stride);
2998 wined3d_mutex_unlock();
3000 return hr;
3003 static HRESULT WINAPI d3d8_device_GetStreamSource(IDirect3DDevice8 *iface,
3004 UINT stream_idx, IDirect3DVertexBuffer8 **buffer, UINT *stride)
3006 struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
3007 struct d3d8_vertexbuffer *buffer_impl;
3008 struct wined3d_buffer *wined3d_buffer = NULL;
3009 HRESULT hr;
3011 TRACE("iface %p, stream_idx %u, buffer %p, stride %p.\n",
3012 iface, stream_idx, buffer, stride);
3014 if (!buffer)
3015 return D3DERR_INVALIDCALL;
3017 wined3d_mutex_lock();
3018 hr = wined3d_device_get_stream_source(device->wined3d_device, stream_idx, &wined3d_buffer, 0, stride);
3019 if (SUCCEEDED(hr) && wined3d_buffer)
3021 buffer_impl = wined3d_buffer_get_parent(wined3d_buffer);
3022 *buffer = &buffer_impl->IDirect3DVertexBuffer8_iface;
3023 IDirect3DVertexBuffer8_AddRef(*buffer);
3025 else
3027 if (FAILED(hr))
3028 ERR("Failed to get wined3d stream source, hr %#x.\n", hr);
3029 *buffer = NULL;
3031 wined3d_mutex_unlock();
3033 return hr;
3036 static const struct IDirect3DDevice8Vtbl d3d8_device_vtbl =
3038 d3d8_device_QueryInterface,
3039 d3d8_device_AddRef,
3040 d3d8_device_Release,
3041 d3d8_device_TestCooperativeLevel,
3042 d3d8_device_GetAvailableTextureMem,
3043 d3d8_device_ResourceManagerDiscardBytes,
3044 d3d8_device_GetDirect3D,
3045 d3d8_device_GetDeviceCaps,
3046 d3d8_device_GetDisplayMode,
3047 d3d8_device_GetCreationParameters,
3048 d3d8_device_SetCursorProperties,
3049 d3d8_device_SetCursorPosition,
3050 d3d8_device_ShowCursor,
3051 d3d8_device_CreateAdditionalSwapChain,
3052 d3d8_device_Reset,
3053 d3d8_device_Present,
3054 d3d8_device_GetBackBuffer,
3055 d3d8_device_GetRasterStatus,
3056 d3d8_device_SetGammaRamp,
3057 d3d8_device_GetGammaRamp,
3058 d3d8_device_CreateTexture,
3059 d3d8_device_CreateVolumeTexture,
3060 d3d8_device_CreateCubeTexture,
3061 d3d8_device_CreateVertexBuffer,
3062 d3d8_device_CreateIndexBuffer,
3063 d3d8_device_CreateRenderTarget,
3064 d3d8_device_CreateDepthStencilSurface,
3065 d3d8_device_CreateImageSurface,
3066 d3d8_device_CopyRects,
3067 d3d8_device_UpdateTexture,
3068 d3d8_device_GetFrontBuffer,
3069 d3d8_device_SetRenderTarget,
3070 d3d8_device_GetRenderTarget,
3071 d3d8_device_GetDepthStencilSurface,
3072 d3d8_device_BeginScene,
3073 d3d8_device_EndScene,
3074 d3d8_device_Clear,
3075 d3d8_device_SetTransform,
3076 d3d8_device_GetTransform,
3077 d3d8_device_MultiplyTransform,
3078 d3d8_device_SetViewport,
3079 d3d8_device_GetViewport,
3080 d3d8_device_SetMaterial,
3081 d3d8_device_GetMaterial,
3082 d3d8_device_SetLight,
3083 d3d8_device_GetLight,
3084 d3d8_device_LightEnable,
3085 d3d8_device_GetLightEnable,
3086 d3d8_device_SetClipPlane,
3087 d3d8_device_GetClipPlane,
3088 d3d8_device_SetRenderState,
3089 d3d8_device_GetRenderState,
3090 d3d8_device_BeginStateBlock,
3091 d3d8_device_EndStateBlock,
3092 d3d8_device_ApplyStateBlock,
3093 d3d8_device_CaptureStateBlock,
3094 d3d8_device_DeleteStateBlock,
3095 d3d8_device_CreateStateBlock,
3096 d3d8_device_SetClipStatus,
3097 d3d8_device_GetClipStatus,
3098 d3d8_device_GetTexture,
3099 d3d8_device_SetTexture,
3100 d3d8_device_GetTextureStageState,
3101 d3d8_device_SetTextureStageState,
3102 d3d8_device_ValidateDevice,
3103 d3d8_device_GetInfo,
3104 d3d8_device_SetPaletteEntries,
3105 d3d8_device_GetPaletteEntries,
3106 d3d8_device_SetCurrentTexturePalette,
3107 d3d8_device_GetCurrentTexturePalette,
3108 d3d8_device_DrawPrimitive,
3109 d3d8_device_DrawIndexedPrimitive,
3110 d3d8_device_DrawPrimitiveUP,
3111 d3d8_device_DrawIndexedPrimitiveUP,
3112 d3d8_device_ProcessVertices,
3113 d3d8_device_CreateVertexShader,
3114 d3d8_device_SetVertexShader,
3115 d3d8_device_GetVertexShader,
3116 d3d8_device_DeleteVertexShader,
3117 d3d8_device_SetVertexShaderConstant,
3118 d3d8_device_GetVertexShaderConstant,
3119 d3d8_device_GetVertexShaderDeclaration,
3120 d3d8_device_GetVertexShaderFunction,
3121 d3d8_device_SetStreamSource,
3122 d3d8_device_GetStreamSource,
3123 d3d8_device_SetIndices,
3124 d3d8_device_GetIndices,
3125 d3d8_device_CreatePixelShader,
3126 d3d8_device_SetPixelShader,
3127 d3d8_device_GetPixelShader,
3128 d3d8_device_DeletePixelShader,
3129 d3d8_device_SetPixelShaderConstant,
3130 d3d8_device_GetPixelShaderConstant,
3131 d3d8_device_GetPixelShaderFunction,
3132 d3d8_device_DrawRectPatch,
3133 d3d8_device_DrawTriPatch,
3134 d3d8_device_DeletePatch,
3137 static inline struct d3d8_device *device_from_device_parent(struct wined3d_device_parent *device_parent)
3139 return CONTAINING_RECORD(device_parent, struct d3d8_device, device_parent);
3142 static void CDECL device_parent_wined3d_device_created(struct wined3d_device_parent *device_parent,
3143 struct wined3d_device *device)
3145 TRACE("device_parent %p, device %p\n", device_parent, device);
3148 static void CDECL device_parent_mode_changed(struct wined3d_device_parent *device_parent)
3150 TRACE("device_parent %p.\n", device_parent);
3153 static void CDECL device_parent_activate(struct wined3d_device_parent *device_parent, BOOL activate)
3155 struct d3d8_device *device = device_from_device_parent(device_parent);
3157 TRACE("device_parent %p, activate %#x.\n", device_parent, activate);
3159 if (!activate)
3160 InterlockedCompareExchange(&device->device_state, D3D8_DEVICE_STATE_LOST, D3D8_DEVICE_STATE_OK);
3161 else
3162 InterlockedCompareExchange(&device->device_state, D3D8_DEVICE_STATE_NOT_RESET, D3D8_DEVICE_STATE_LOST);
3165 static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent *device_parent,
3166 struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
3167 void **parent, const struct wined3d_parent_ops **parent_ops)
3169 struct d3d8_surface *d3d_surface;
3171 TRACE("device_parent %p, wined3d_texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n",
3172 device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops);
3174 if (!(d3d_surface = heap_alloc_zero(sizeof(*d3d_surface))))
3175 return E_OUTOFMEMORY;
3177 surface_init(d3d_surface, wined3d_texture, sub_resource_idx, parent_ops);
3178 *parent = d3d_surface;
3179 TRACE("Created surface %p.\n", d3d_surface);
3181 return D3D_OK;
3184 static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *device_parent,
3185 struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
3186 void **parent, const struct wined3d_parent_ops **parent_ops)
3188 struct d3d8_volume *d3d_volume;
3190 TRACE("device_parent %p, texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n",
3191 device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops);
3193 if (!(d3d_volume = heap_alloc_zero(sizeof(*d3d_volume))))
3194 return E_OUTOFMEMORY;
3196 volume_init(d3d_volume, wined3d_texture, sub_resource_idx, parent_ops);
3197 *parent = d3d_volume;
3198 TRACE("Created volume %p.\n", d3d_volume);
3200 return D3D_OK;
3203 static HRESULT CDECL device_parent_create_swapchain_texture(struct wined3d_device_parent *device_parent,
3204 void *container_parent, const struct wined3d_resource_desc *desc, DWORD texture_flags,
3205 struct wined3d_texture **texture)
3207 struct d3d8_device *device = device_from_device_parent(device_parent);
3208 struct d3d8_surface *d3d_surface;
3209 HRESULT hr;
3211 TRACE("device_parent %p, container_parent %p, desc %p, texture flags %#x, texture %p.\n",
3212 device_parent, container_parent, desc, texture_flags, texture);
3214 if (FAILED(hr = wined3d_texture_create(device->wined3d_device, desc, 1, 1,
3215 texture_flags | WINED3D_TEXTURE_CREATE_MAPPABLE, NULL, &device->IDirect3DDevice8_iface,
3216 &d3d8_null_wined3d_parent_ops, texture)))
3218 WARN("Failed to create texture, hr %#x.\n", hr);
3219 return hr;
3222 d3d_surface = wined3d_texture_get_sub_resource_parent(*texture, 0);
3223 d3d_surface->parent_device = &device->IDirect3DDevice8_iface;
3225 return hr;
3228 static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent,
3229 struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain)
3231 struct d3d8_device *device = device_from_device_parent(device_parent);
3232 struct d3d8_swapchain *d3d_swapchain;
3233 HRESULT hr;
3235 TRACE("device_parent %p, desc %p, swapchain %p.\n", device_parent, desc, swapchain);
3237 if (FAILED(hr = d3d8_swapchain_create(device, desc, &d3d_swapchain)))
3239 WARN("Failed to create swapchain, hr %#x.\n", hr);
3240 *swapchain = NULL;
3241 return hr;
3244 *swapchain = d3d_swapchain->wined3d_swapchain;
3245 wined3d_swapchain_incref(*swapchain);
3246 IDirect3DSwapChain8_Release(&d3d_swapchain->IDirect3DSwapChain8_iface);
3248 return hr;
3251 static const struct wined3d_device_parent_ops d3d8_wined3d_device_parent_ops =
3253 device_parent_wined3d_device_created,
3254 device_parent_mode_changed,
3255 device_parent_activate,
3256 device_parent_surface_created,
3257 device_parent_volume_created,
3258 device_parent_create_swapchain_texture,
3259 device_parent_create_swapchain,
3262 static void setup_fpu(void)
3264 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3265 WORD cw;
3266 __asm__ volatile ("fnstcw %0" : "=m" (cw));
3267 cw = (cw & ~0xf3f) | 0x3f;
3268 __asm__ volatile ("fldcw %0" : : "m" (cw));
3269 #elif defined(__i386__) && defined(_MSC_VER)
3270 WORD cw;
3271 __asm fnstcw cw;
3272 cw = (cw & ~0xf3f) | 0x3f;
3273 __asm fldcw cw;
3274 #else
3275 FIXME("FPU setup not implemented for this platform.\n");
3276 #endif
3279 HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wined3d *wined3d, UINT adapter,
3280 D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters)
3282 struct wined3d_swapchain_desc swapchain_desc;
3283 struct wined3d_swapchain *wined3d_swapchain;
3284 HRESULT hr;
3286 device->IDirect3DDevice8_iface.lpVtbl = &d3d8_device_vtbl;
3287 device->device_parent.ops = &d3d8_wined3d_device_parent_ops;
3288 device->ref = 1;
3289 if (!(device->handle_table.entries = heap_alloc_zero(D3D8_INITIAL_HANDLE_TABLE_SIZE
3290 * sizeof(*device->handle_table.entries))))
3292 ERR("Failed to allocate handle table memory.\n");
3293 return E_OUTOFMEMORY;
3295 device->handle_table.table_size = D3D8_INITIAL_HANDLE_TABLE_SIZE;
3297 if (!(flags & D3DCREATE_FPU_PRESERVE)) setup_fpu();
3299 wined3d_mutex_lock();
3300 hr = wined3d_device_create(wined3d, adapter, device_type, focus_window, flags, 4,
3301 &device->device_parent, &device->wined3d_device);
3302 if (FAILED(hr))
3304 WARN("Failed to create wined3d device, hr %#x.\n", hr);
3305 wined3d_mutex_unlock();
3306 heap_free(device->handle_table.entries);
3307 return hr;
3310 if (!parameters->Windowed)
3312 HWND device_window = parameters->hDeviceWindow;
3314 if (!focus_window)
3315 focus_window = device_window;
3316 if (FAILED(hr = wined3d_device_acquire_focus_window(device->wined3d_device, focus_window)))
3318 ERR("Failed to acquire focus window, hr %#x.\n", hr);
3319 wined3d_device_decref(device->wined3d_device);
3320 wined3d_mutex_unlock();
3321 heap_free(device->handle_table.entries);
3322 return hr;
3325 if (!device_window)
3326 device_window = focus_window;
3327 wined3d_device_setup_fullscreen_window(device->wined3d_device, device_window,
3328 parameters->BackBufferWidth,
3329 parameters->BackBufferHeight);
3332 if (flags & D3DCREATE_MULTITHREADED)
3333 wined3d_device_set_multithreaded(device->wined3d_device);
3335 if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, parameters))
3337 wined3d_device_release_focus_window(device->wined3d_device);
3338 wined3d_device_decref(device->wined3d_device);
3339 wined3d_mutex_unlock();
3340 heap_free(device->handle_table.entries);
3341 return D3DERR_INVALIDCALL;
3344 if (FAILED(hr = wined3d_device_init_3d(device->wined3d_device, &swapchain_desc)))
3346 WARN("Failed to initialize 3D, hr %#x.\n", hr);
3347 wined3d_device_release_focus_window(device->wined3d_device);
3348 wined3d_device_decref(device->wined3d_device);
3349 wined3d_mutex_unlock();
3350 heap_free(device->handle_table.entries);
3351 return hr;
3354 wined3d_device_set_render_state(device->wined3d_device,
3355 WINED3D_RS_ZENABLE, !!swapchain_desc.enable_auto_depth_stencil);
3356 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_POINTSIZE_MIN, 0);
3357 wined3d_mutex_unlock();
3359 present_parameters_from_wined3d_swapchain_desc(parameters, &swapchain_desc);
3361 device->declArraySize = 16;
3362 if (!(device->decls = heap_alloc(device->declArraySize * sizeof(*device->decls))))
3364 ERR("Failed to allocate FVF vertex declaration map memory.\n");
3365 hr = E_OUTOFMEMORY;
3366 goto err;
3369 wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, 0);
3370 device->implicit_swapchain = wined3d_swapchain_get_parent(wined3d_swapchain);
3372 device->d3d_parent = &parent->IDirect3D8_iface;
3373 IDirect3D8_AddRef(device->d3d_parent);
3375 return D3D_OK;
3377 err:
3378 wined3d_mutex_lock();
3379 wined3d_device_uninit_3d(device->wined3d_device);
3380 wined3d_device_release_focus_window(device->wined3d_device);
3381 wined3d_device_decref(device->wined3d_device);
3382 wined3d_mutex_unlock();
3383 heap_free(device->handle_table.entries);
3384 return hr;