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