1 /* 2 * Copyright 2005 Oliver Stieber 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #include "d3d8_private.h" 20 21 static inline struct d3d8_vertexbuffer *impl_from_IDirect3DVertexBuffer8(IDirect3DVertexBuffer8 *iface) 22 { 23 return CONTAINING_RECORD(iface, struct d3d8_vertexbuffer, IDirect3DVertexBuffer8_iface); 24 } 25 26 static HRESULT WINAPI d3d8_vertexbuffer_QueryInterface(IDirect3DVertexBuffer8 *iface, REFIID riid, void **object) 27 { 28 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 29 30 if (IsEqualGUID(riid, &IID_IDirect3DVertexBuffer8) 31 || IsEqualGUID(riid, &IID_IDirect3DResource8) 32 || IsEqualGUID(riid, &IID_IUnknown)) 33 { 34 IDirect3DVertexBuffer8_AddRef(iface); 35 *object = iface; 36 return S_OK; 37 } 38 39 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); 40 41 *object = NULL; 42 return E_NOINTERFACE; 43 } 44 45 static ULONG WINAPI d3d8_vertexbuffer_AddRef(IDirect3DVertexBuffer8 *iface) 46 { 47 struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); 48 ULONG refcount = InterlockedIncrement(&buffer->resource.refcount); 49 50 TRACE("%p increasing refcount to %u.\n", iface, refcount); 51 52 if (refcount == 1) 53 { 54 IDirect3DDevice8_AddRef(buffer->parent_device); 55 wined3d_mutex_lock(); 56 wined3d_buffer_incref(buffer->wined3d_buffer); 57 wined3d_mutex_unlock(); 58 } 59 60 return refcount; 61 } 62 63 static ULONG WINAPI d3d8_vertexbuffer_Release(IDirect3DVertexBuffer8 *iface) 64 { 65 struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); 66 ULONG refcount = InterlockedDecrement(&buffer->resource.refcount); 67 68 TRACE("%p decreasing refcount to %u.\n", iface, refcount); 69 70 if (!refcount) 71 { 72 IDirect3DDevice8 *device = buffer->parent_device; 73 74 wined3d_mutex_lock(); 75 wined3d_buffer_decref(buffer->wined3d_buffer); 76 wined3d_mutex_unlock(); 77 78 /* Release the device last, as it may cause the device to be destroyed. */ 79 IDirect3DDevice8_Release(device); 80 } 81 82 return refcount; 83 } 84 85 static HRESULT WINAPI d3d8_vertexbuffer_GetDevice(IDirect3DVertexBuffer8 *iface, 86 IDirect3DDevice8 **device) 87 { 88 struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); 89 90 TRACE("iface %p, device %p.\n", iface, device); 91 92 *device = buffer->parent_device; 93 IDirect3DDevice8_AddRef(*device); 94 95 TRACE("Returning device %p.\n", *device); 96 97 return D3D_OK; 98 } 99 100 static HRESULT WINAPI d3d8_vertexbuffer_SetPrivateData(IDirect3DVertexBuffer8 *iface, 101 REFGUID guid, const void *data, DWORD data_size, DWORD flags) 102 { 103 struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); 104 TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n", 105 iface, debugstr_guid(guid), data, data_size, flags); 106 107 return d3d8_resource_set_private_data(&buffer->resource, guid, data, data_size, flags); 108 } 109 110 static HRESULT WINAPI d3d8_vertexbuffer_GetPrivateData(IDirect3DVertexBuffer8 *iface, 111 REFGUID guid, void *data, DWORD *data_size) 112 { 113 struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); 114 TRACE("iface %p, guid %s, data %p, data_size %p.\n", 115 iface, debugstr_guid(guid), data, data_size); 116 117 return d3d8_resource_get_private_data(&buffer->resource, guid, data, data_size); 118 } 119 120 static HRESULT WINAPI d3d8_vertexbuffer_FreePrivateData(IDirect3DVertexBuffer8 *iface, REFGUID guid) 121 { 122 struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); 123 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); 124 125 return d3d8_resource_free_private_data(&buffer->resource, guid); 126 } 127 128 static DWORD WINAPI d3d8_vertexbuffer_SetPriority(IDirect3DVertexBuffer8 *iface, DWORD priority) 129 { 130 struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); 131 struct wined3d_resource *resource; 132 DWORD previous; 133 134 TRACE("iface %p, priority %u.\n", iface, priority); 135 136 wined3d_mutex_lock(); 137 resource = wined3d_buffer_get_resource(buffer->wined3d_buffer); 138 previous = wined3d_resource_set_priority(resource, priority); 139 wined3d_mutex_unlock(); 140 141 return previous; 142 } 143 144 static DWORD WINAPI d3d8_vertexbuffer_GetPriority(IDirect3DVertexBuffer8 *iface) 145 { 146 struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); 147 const struct wined3d_resource *resource; 148 DWORD priority; 149 150 TRACE("iface %p.\n", iface); 151 152 wined3d_mutex_lock(); 153 resource = wined3d_buffer_get_resource(buffer->wined3d_buffer); 154 priority = wined3d_resource_get_priority(resource); 155 wined3d_mutex_unlock(); 156 157 return priority; 158 } 159 160 static void WINAPI d3d8_vertexbuffer_PreLoad(IDirect3DVertexBuffer8 *iface) 161 { 162 struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); 163 164 TRACE("iface %p.\n", iface); 165 166 wined3d_mutex_lock(); 167 wined3d_resource_preload(wined3d_buffer_get_resource(buffer->wined3d_buffer)); 168 wined3d_mutex_unlock(); 169 } 170 171 static D3DRESOURCETYPE WINAPI d3d8_vertexbuffer_GetType(IDirect3DVertexBuffer8 *iface) 172 { 173 TRACE("iface %p.\n", iface); 174 175 return D3DRTYPE_VERTEXBUFFER; 176 } 177 178 static HRESULT WINAPI d3d8_vertexbuffer_Lock(IDirect3DVertexBuffer8 *iface, UINT offset, UINT size, 179 BYTE **data, DWORD flags) 180 { 181 struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); 182 struct wined3d_map_desc wined3d_map_desc; 183 struct wined3d_box wined3d_box = {0}; 184 HRESULT hr; 185 186 TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n", 187 iface, offset, size, data, flags); 188 189 wined3d_box.left = offset; 190 wined3d_box.right = offset + size; 191 wined3d_mutex_lock(); 192 hr = wined3d_resource_map(wined3d_buffer_get_resource(buffer->wined3d_buffer), 193 0, &wined3d_map_desc, &wined3d_box, flags); 194 wined3d_mutex_unlock(); 195 *data = wined3d_map_desc.data; 196 197 return hr; 198 } 199 200 static HRESULT WINAPI d3d8_vertexbuffer_Unlock(IDirect3DVertexBuffer8 *iface) 201 { 202 struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); 203 204 TRACE("iface %p.\n", iface); 205 206 wined3d_mutex_lock(); 207 wined3d_resource_unmap(wined3d_buffer_get_resource(buffer->wined3d_buffer), 0); 208 wined3d_mutex_unlock(); 209 210 return D3D_OK; 211 } 212 213 static HRESULT WINAPI d3d8_vertexbuffer_GetDesc(IDirect3DVertexBuffer8 *iface, 214 D3DVERTEXBUFFER_DESC *desc) 215 { 216 struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); 217 struct wined3d_resource_desc wined3d_desc; 218 struct wined3d_resource *wined3d_resource; 219 220 TRACE("iface %p, desc %p.\n", iface, desc); 221 222 wined3d_mutex_lock(); 223 wined3d_resource = wined3d_buffer_get_resource(buffer->wined3d_buffer); 224 wined3d_resource_get_desc(wined3d_resource, &wined3d_desc); 225 wined3d_mutex_unlock(); 226 227 desc->Type = D3DRTYPE_VERTEXBUFFER; 228 desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK; 229 desc->Pool = wined3d_desc.pool; 230 desc->Size = wined3d_desc.size; 231 desc->FVF = buffer->fvf; 232 desc->Format = D3DFMT_VERTEXDATA; 233 234 return D3D_OK; 235 } 236 237 static const IDirect3DVertexBuffer8Vtbl Direct3DVertexBuffer8_Vtbl = 238 { 239 /* IUnknown */ 240 d3d8_vertexbuffer_QueryInterface, 241 d3d8_vertexbuffer_AddRef, 242 d3d8_vertexbuffer_Release, 243 /* IDirect3DResource8 */ 244 d3d8_vertexbuffer_GetDevice, 245 d3d8_vertexbuffer_SetPrivateData, 246 d3d8_vertexbuffer_GetPrivateData, 247 d3d8_vertexbuffer_FreePrivateData, 248 d3d8_vertexbuffer_SetPriority, 249 d3d8_vertexbuffer_GetPriority, 250 d3d8_vertexbuffer_PreLoad, 251 d3d8_vertexbuffer_GetType, 252 /* IDirect3DVertexBuffer8 */ 253 d3d8_vertexbuffer_Lock, 254 d3d8_vertexbuffer_Unlock, 255 d3d8_vertexbuffer_GetDesc, 256 }; 257 258 static void STDMETHODCALLTYPE d3d8_vertexbuffer_wined3d_object_destroyed(void *parent) 259 { 260 struct d3d8_vertexbuffer *buffer = parent; 261 d3d8_resource_cleanup(&buffer->resource); 262 HeapFree(GetProcessHeap(), 0, buffer); 263 } 264 265 static const struct wined3d_parent_ops d3d8_vertexbuffer_wined3d_parent_ops = 266 { 267 d3d8_vertexbuffer_wined3d_object_destroyed, 268 }; 269 270 HRESULT vertexbuffer_init(struct d3d8_vertexbuffer *buffer, struct d3d8_device *device, 271 UINT size, DWORD usage, DWORD fvf, D3DPOOL pool) 272 { 273 HRESULT hr; 274 275 buffer->IDirect3DVertexBuffer8_iface.lpVtbl = &Direct3DVertexBuffer8_Vtbl; 276 d3d8_resource_init(&buffer->resource); 277 buffer->fvf = fvf; 278 279 wined3d_mutex_lock(); 280 hr = wined3d_buffer_create_vb(device->wined3d_device, size, usage & WINED3DUSAGE_MASK, 281 (enum wined3d_pool)pool, buffer, &d3d8_vertexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer); 282 wined3d_mutex_unlock(); 283 if (FAILED(hr)) 284 { 285 WARN("Failed to create wined3d buffer, hr %#x.\n", hr); 286 return hr; 287 } 288 289 buffer->parent_device = &device->IDirect3DDevice8_iface; 290 IDirect3DDevice8_AddRef(buffer->parent_device); 291 292 return D3D_OK; 293 } 294 295 struct d3d8_vertexbuffer *unsafe_impl_from_IDirect3DVertexBuffer8(IDirect3DVertexBuffer8 *iface) 296 { 297 if (!iface) 298 return NULL; 299 assert(iface->lpVtbl == &Direct3DVertexBuffer8_Vtbl); 300 301 return impl_from_IDirect3DVertexBuffer8(iface); 302 } 303 304 static inline struct d3d8_indexbuffer *impl_from_IDirect3DIndexBuffer8(IDirect3DIndexBuffer8 *iface) 305 { 306 return CONTAINING_RECORD(iface, struct d3d8_indexbuffer, IDirect3DIndexBuffer8_iface); 307 } 308 309 static HRESULT WINAPI d3d8_indexbuffer_QueryInterface(IDirect3DIndexBuffer8 *iface, REFIID riid, void **object) 310 { 311 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 312 313 if (IsEqualGUID(riid, &IID_IDirect3DIndexBuffer8) 314 || IsEqualGUID(riid, &IID_IDirect3DResource8) 315 || IsEqualGUID(riid, &IID_IUnknown)) 316 { 317 IDirect3DIndexBuffer8_AddRef(iface); 318 *object = iface; 319 return S_OK; 320 } 321 322 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); 323 324 *object = NULL; 325 return E_NOINTERFACE; 326 } 327 328 static ULONG WINAPI d3d8_indexbuffer_AddRef(IDirect3DIndexBuffer8 *iface) 329 { 330 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); 331 ULONG refcount = InterlockedIncrement(&buffer->resource.refcount); 332 333 TRACE("%p increasing refcount to %u.\n", iface, refcount); 334 335 if (refcount == 1) 336 { 337 IDirect3DDevice8_AddRef(buffer->parent_device); 338 wined3d_mutex_lock(); 339 wined3d_buffer_incref(buffer->wined3d_buffer); 340 wined3d_mutex_unlock(); 341 } 342 343 return refcount; 344 } 345 346 static ULONG WINAPI d3d8_indexbuffer_Release(IDirect3DIndexBuffer8 *iface) 347 { 348 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); 349 ULONG refcount = InterlockedDecrement(&buffer->resource.refcount); 350 351 TRACE("%p decreasing refcount to %u.\n", iface, refcount); 352 353 if (!refcount) 354 { 355 IDirect3DDevice8 *device = buffer->parent_device; 356 357 wined3d_mutex_lock(); 358 wined3d_buffer_decref(buffer->wined3d_buffer); 359 wined3d_mutex_unlock(); 360 361 /* Release the device last, as it may cause the device to be destroyed. */ 362 IDirect3DDevice8_Release(device); 363 } 364 365 return refcount; 366 } 367 368 static HRESULT WINAPI d3d8_indexbuffer_GetDevice(IDirect3DIndexBuffer8 *iface, 369 IDirect3DDevice8 **device) 370 { 371 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); 372 373 TRACE("iface %p, device %p.\n", iface, device); 374 375 *device = buffer->parent_device; 376 IDirect3DDevice8_AddRef(*device); 377 378 TRACE("Returning device %p.\n", *device); 379 380 return D3D_OK; 381 } 382 383 static HRESULT WINAPI d3d8_indexbuffer_SetPrivateData(IDirect3DIndexBuffer8 *iface, 384 REFGUID guid, const void *data, DWORD data_size, DWORD flags) 385 { 386 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); 387 TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n", 388 iface, debugstr_guid(guid), data, data_size, flags); 389 390 return d3d8_resource_set_private_data(&buffer->resource, guid, data, data_size, flags); 391 } 392 393 static HRESULT WINAPI d3d8_indexbuffer_GetPrivateData(IDirect3DIndexBuffer8 *iface, 394 REFGUID guid, void *data, DWORD *data_size) 395 { 396 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); 397 TRACE("iface %p, guid %s, data %p, data_size %p.\n", 398 iface, debugstr_guid(guid), data, data_size); 399 400 return d3d8_resource_get_private_data(&buffer->resource, guid, data, data_size); 401 } 402 403 static HRESULT WINAPI d3d8_indexbuffer_FreePrivateData(IDirect3DIndexBuffer8 *iface, REFGUID guid) 404 { 405 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); 406 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); 407 408 return d3d8_resource_free_private_data(&buffer->resource, guid); 409 } 410 411 static DWORD WINAPI d3d8_indexbuffer_SetPriority(IDirect3DIndexBuffer8 *iface, DWORD priority) 412 { 413 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); 414 struct wined3d_resource *resource; 415 DWORD previous; 416 417 TRACE("iface %p, priority %u.\n", iface, priority); 418 419 wined3d_mutex_lock(); 420 resource = wined3d_buffer_get_resource(buffer->wined3d_buffer); 421 previous = wined3d_resource_set_priority(resource, priority); 422 wined3d_mutex_unlock(); 423 424 return previous; 425 } 426 427 static DWORD WINAPI d3d8_indexbuffer_GetPriority(IDirect3DIndexBuffer8 *iface) 428 { 429 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); 430 const struct wined3d_resource *resource; 431 DWORD priority; 432 433 TRACE("iface %p.\n", iface); 434 435 wined3d_mutex_lock(); 436 resource = wined3d_buffer_get_resource(buffer->wined3d_buffer); 437 priority = wined3d_resource_get_priority(resource); 438 wined3d_mutex_unlock(); 439 440 return priority; 441 } 442 443 static void WINAPI d3d8_indexbuffer_PreLoad(IDirect3DIndexBuffer8 *iface) 444 { 445 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); 446 447 TRACE("iface %p.\n", iface); 448 449 wined3d_mutex_lock(); 450 wined3d_resource_preload(wined3d_buffer_get_resource(buffer->wined3d_buffer)); 451 wined3d_mutex_unlock(); 452 } 453 454 static D3DRESOURCETYPE WINAPI d3d8_indexbuffer_GetType(IDirect3DIndexBuffer8 *iface) 455 { 456 TRACE("iface %p.\n", iface); 457 458 return D3DRTYPE_INDEXBUFFER; 459 } 460 461 static HRESULT WINAPI d3d8_indexbuffer_Lock(IDirect3DIndexBuffer8 *iface, UINT offset, UINT size, 462 BYTE **data, DWORD flags) 463 { 464 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); 465 struct wined3d_map_desc wined3d_map_desc; 466 struct wined3d_box wined3d_box = {0}; 467 HRESULT hr; 468 469 TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n", 470 iface, offset, size, data, flags); 471 472 wined3d_box.left = offset; 473 wined3d_box.right = offset + size; 474 wined3d_mutex_lock(); 475 hr = wined3d_resource_map(wined3d_buffer_get_resource(buffer->wined3d_buffer), 476 0, &wined3d_map_desc, &wined3d_box, flags); 477 wined3d_mutex_unlock(); 478 *data = wined3d_map_desc.data; 479 480 return hr; 481 } 482 483 static HRESULT WINAPI d3d8_indexbuffer_Unlock(IDirect3DIndexBuffer8 *iface) 484 { 485 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); 486 487 TRACE("iface %p.\n", iface); 488 489 wined3d_mutex_lock(); 490 wined3d_resource_unmap(wined3d_buffer_get_resource(buffer->wined3d_buffer), 0); 491 wined3d_mutex_unlock(); 492 493 return D3D_OK; 494 } 495 496 static HRESULT WINAPI d3d8_indexbuffer_GetDesc(IDirect3DIndexBuffer8 *iface, 497 D3DINDEXBUFFER_DESC *desc) 498 { 499 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); 500 struct wined3d_resource_desc wined3d_desc; 501 struct wined3d_resource *wined3d_resource; 502 503 TRACE("iface %p, desc %p.\n", iface, desc); 504 505 wined3d_mutex_lock(); 506 wined3d_resource = wined3d_buffer_get_resource(buffer->wined3d_buffer); 507 wined3d_resource_get_desc(wined3d_resource, &wined3d_desc); 508 wined3d_mutex_unlock(); 509 510 desc->Format = d3dformat_from_wined3dformat(buffer->format); 511 desc->Type = D3DRTYPE_INDEXBUFFER; 512 desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK; 513 desc->Pool = wined3d_desc.pool; 514 desc->Size = wined3d_desc.size; 515 516 return D3D_OK; 517 } 518 519 static const IDirect3DIndexBuffer8Vtbl d3d8_indexbuffer_vtbl = 520 { 521 /* IUnknown */ 522 d3d8_indexbuffer_QueryInterface, 523 d3d8_indexbuffer_AddRef, 524 d3d8_indexbuffer_Release, 525 /* IDirect3DResource8 */ 526 d3d8_indexbuffer_GetDevice, 527 d3d8_indexbuffer_SetPrivateData, 528 d3d8_indexbuffer_GetPrivateData, 529 d3d8_indexbuffer_FreePrivateData, 530 d3d8_indexbuffer_SetPriority, 531 d3d8_indexbuffer_GetPriority, 532 d3d8_indexbuffer_PreLoad, 533 d3d8_indexbuffer_GetType, 534 /* IDirect3DIndexBuffer8 */ 535 d3d8_indexbuffer_Lock, 536 d3d8_indexbuffer_Unlock, 537 d3d8_indexbuffer_GetDesc, 538 }; 539 540 static void STDMETHODCALLTYPE d3d8_indexbuffer_wined3d_object_destroyed(void *parent) 541 { 542 struct d3d8_indexbuffer *buffer = parent; 543 d3d8_resource_cleanup(&buffer->resource); 544 HeapFree(GetProcessHeap(), 0, buffer); 545 } 546 547 static const struct wined3d_parent_ops d3d8_indexbuffer_wined3d_parent_ops = 548 { 549 d3d8_indexbuffer_wined3d_object_destroyed, 550 }; 551 552 HRESULT indexbuffer_init(struct d3d8_indexbuffer *buffer, struct d3d8_device *device, 553 UINT size, DWORD usage, D3DFORMAT format, D3DPOOL pool) 554 { 555 HRESULT hr; 556 557 buffer->IDirect3DIndexBuffer8_iface.lpVtbl = &d3d8_indexbuffer_vtbl; 558 d3d8_resource_init(&buffer->resource); 559 buffer->format = wined3dformat_from_d3dformat(format); 560 561 wined3d_mutex_lock(); 562 hr = wined3d_buffer_create_ib(device->wined3d_device, size, usage & WINED3DUSAGE_MASK, 563 (enum wined3d_pool)pool, buffer, &d3d8_indexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer); 564 wined3d_mutex_unlock(); 565 if (FAILED(hr)) 566 { 567 WARN("Failed to create wined3d buffer, hr %#x.\n", hr); 568 return hr; 569 } 570 571 buffer->parent_device = &device->IDirect3DDevice8_iface; 572 IDirect3DDevice8_AddRef(buffer->parent_device); 573 574 return D3D_OK; 575 } 576 577 struct d3d8_indexbuffer *unsafe_impl_from_IDirect3DIndexBuffer8(IDirect3DIndexBuffer8 *iface) 578 { 579 if (!iface) 580 return NULL; 581 assert(iface->lpVtbl == &d3d8_indexbuffer_vtbl); 582 583 return impl_from_IDirect3DIndexBuffer8(iface); 584 } 585