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