buffer.c 18.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 * Copyright 2002-2004 Jason Edmeades
 * Copyright 2002-2004 Raphael Junqueira
 * Copyright 2005 Oliver Stieber
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "config.h"
#include "d3d9_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(d3d9);

26 27
static inline IDirect3DVertexBuffer9Impl *impl_from_IDirect3DVertexBuffer9(IDirect3DVertexBuffer9 *iface)
{
28
    return CONTAINING_RECORD(iface, IDirect3DVertexBuffer9Impl, IDirect3DVertexBuffer9_iface);
29 30
}

31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
static HRESULT WINAPI d3d9_vertexbuffer_QueryInterface(IDirect3DVertexBuffer9 *iface, REFIID riid, void **object)
{
    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);

    if (IsEqualGUID(riid, &IID_IDirect3DVertexBuffer9)
            || IsEqualGUID(riid, &IID_IDirect3DResource9)
            || IsEqualGUID(riid, &IID_IUnknown))
    {
        IDirect3DVertexBuffer9_AddRef(iface);
        *object = iface;
        return S_OK;
    }

    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));

    *object = NULL;
    return E_NOINTERFACE;
}

static ULONG WINAPI d3d9_vertexbuffer_AddRef(IDirect3DVertexBuffer9 *iface)
{
52
    IDirect3DVertexBuffer9Impl *buffer = impl_from_IDirect3DVertexBuffer9(iface);
53 54 55 56 57 58 59 60
    ULONG refcount = InterlockedIncrement(&buffer->ref);

    TRACE("%p increasing refcount to %u.\n", iface, refcount);

    if (refcount == 1)
    {
        IDirect3DDevice9Ex_AddRef(buffer->parentDevice);
        wined3d_mutex_lock();
61
        wined3d_buffer_incref(buffer->wineD3DVertexBuffer);
62 63 64 65 66 67 68 69
        wined3d_mutex_unlock();
    }

    return refcount;
}

static ULONG WINAPI d3d9_vertexbuffer_Release(IDirect3DVertexBuffer9 *iface)
{
70
    IDirect3DVertexBuffer9Impl *buffer = impl_from_IDirect3DVertexBuffer9(iface);
71 72 73 74 75 76 77 78 79
    ULONG refcount = InterlockedDecrement(&buffer->ref);

    TRACE("%p decreasing refcount to %u.\n", iface, refcount);

    if (!refcount)
    {
        IDirect3DDevice9Ex *device = buffer->parentDevice;

        wined3d_mutex_lock();
80
        wined3d_buffer_decref(buffer->wineD3DVertexBuffer);
81 82 83 84 85 86 87 88 89
        wined3d_mutex_unlock();

        /* Release the device last, as it may cause the device to be destroyed. */
        IDirect3DDevice9Ex_Release(device);
    }

    return refcount;
}

90 91
static HRESULT WINAPI d3d9_vertexbuffer_GetDevice(IDirect3DVertexBuffer9 *iface,
        IDirect3DDevice9 **device)
92
{
93 94
    IDirect3DVertexBuffer9Impl *buffer = impl_from_IDirect3DVertexBuffer9(iface);

95 96
    TRACE("iface %p, device %p.\n", iface, device);

97
    *device = (IDirect3DDevice9 *)buffer->parentDevice;
98 99 100 101 102 103 104 105 106 107
    IDirect3DDevice9_AddRef(*device);

    TRACE("Returning device %p.\n", *device);

    return D3D_OK;
}

static HRESULT WINAPI d3d9_vertexbuffer_SetPrivateData(IDirect3DVertexBuffer9 *iface,
        REFGUID guid, const void *data, DWORD data_size, DWORD flags)
{
108 109
    IDirect3DVertexBuffer9Impl *buffer = impl_from_IDirect3DVertexBuffer9(iface);
    struct wined3d_resource *resource;
110 111 112 113 114 115
    HRESULT hr;

    TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
            iface, debugstr_guid(guid), data, data_size, flags);

    wined3d_mutex_lock();
116 117
    resource = wined3d_buffer_get_resource(buffer->wineD3DVertexBuffer);
    hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
118 119 120 121 122 123 124 125
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI d3d9_vertexbuffer_GetPrivateData(IDirect3DVertexBuffer9 *iface,
        REFGUID guid, void *data, DWORD *data_size)
{
126 127
    IDirect3DVertexBuffer9Impl *buffer = impl_from_IDirect3DVertexBuffer9(iface);
    struct wined3d_resource *resource;
128 129 130 131 132 133
    HRESULT hr;

    TRACE("iface %p, guid %s, data %p, data_size %p.\n",
            iface, debugstr_guid(guid), data, data_size);

    wined3d_mutex_lock();
134 135
    resource = wined3d_buffer_get_resource(buffer->wineD3DVertexBuffer);
    hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
136 137 138 139 140 141 142
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI d3d9_vertexbuffer_FreePrivateData(IDirect3DVertexBuffer9 *iface, REFGUID guid)
{
143 144
    IDirect3DVertexBuffer9Impl *buffer = impl_from_IDirect3DVertexBuffer9(iface);
    struct wined3d_resource *resource;
145 146 147 148 149
    HRESULT hr;

    TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));

    wined3d_mutex_lock();
150 151
    resource = wined3d_buffer_get_resource(buffer->wineD3DVertexBuffer);
    hr = wined3d_resource_free_private_data(resource, guid);
152 153 154 155 156 157 158
    wined3d_mutex_unlock();

    return hr;
}

static DWORD WINAPI d3d9_vertexbuffer_SetPriority(IDirect3DVertexBuffer9 *iface, DWORD priority)
{
159
    IDirect3DVertexBuffer9Impl *buffer = impl_from_IDirect3DVertexBuffer9(iface);
160 161 162 163 164
    DWORD previous;

    TRACE("iface %p, priority %u.\n", iface, priority);

    wined3d_mutex_lock();
165
    previous = wined3d_buffer_set_priority(buffer->wineD3DVertexBuffer, priority);
166 167 168 169 170 171 172
    wined3d_mutex_unlock();

    return previous;
}

static DWORD WINAPI d3d9_vertexbuffer_GetPriority(IDirect3DVertexBuffer9 *iface)
{
173
    IDirect3DVertexBuffer9Impl *buffer = impl_from_IDirect3DVertexBuffer9(iface);
174 175 176 177 178
    DWORD priority;

    TRACE("iface %p.\n", iface);

    wined3d_mutex_lock();
179
    priority = wined3d_buffer_get_priority(buffer->wineD3DVertexBuffer);
180 181 182 183 184 185 186
    wined3d_mutex_unlock();

    return priority;
}

static void WINAPI d3d9_vertexbuffer_PreLoad(IDirect3DVertexBuffer9 *iface)
{
187 188
    IDirect3DVertexBuffer9Impl *buffer = impl_from_IDirect3DVertexBuffer9(iface);

189 190 191
    TRACE("iface %p.\n", iface);

    wined3d_mutex_lock();
192
    wined3d_buffer_preload(buffer->wineD3DVertexBuffer);
193 194 195 196 197 198 199 200 201 202
    wined3d_mutex_unlock();
}

static D3DRESOURCETYPE WINAPI d3d9_vertexbuffer_GetType(IDirect3DVertexBuffer9 *iface)
{
    TRACE("iface %p.\n", iface);

    return D3DRTYPE_VERTEXBUFFER;
}

203 204
static HRESULT WINAPI d3d9_vertexbuffer_Lock(IDirect3DVertexBuffer9 *iface, UINT offset, UINT size,
        void **data, DWORD flags)
205
{
206
    IDirect3DVertexBuffer9Impl *buffer = impl_from_IDirect3DVertexBuffer9(iface);
207 208 209 210 211 212
    HRESULT hr;

    TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n",
            iface, offset, size, data, flags);

    wined3d_mutex_lock();
213
    hr = wined3d_buffer_map(buffer->wineD3DVertexBuffer, offset, size, (BYTE **)data, flags);
214 215 216 217 218 219 220
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI d3d9_vertexbuffer_Unlock(IDirect3DVertexBuffer9 *iface)
{
221 222
    IDirect3DVertexBuffer9Impl *buffer = impl_from_IDirect3DVertexBuffer9(iface);

223 224 225
    TRACE("iface %p.\n", iface);

    wined3d_mutex_lock();
226
    wined3d_buffer_unmap(buffer->wineD3DVertexBuffer);
227 228
    wined3d_mutex_unlock();

229
    return D3D_OK;
230 231
}

232 233
static HRESULT WINAPI d3d9_vertexbuffer_GetDesc(IDirect3DVertexBuffer9 *iface,
        D3DVERTEXBUFFER_DESC *desc)
234
{
235
    IDirect3DVertexBuffer9Impl *buffer = impl_from_IDirect3DVertexBuffer9(iface);
236
    struct wined3d_resource_desc wined3d_desc;
237
    struct wined3d_resource *wined3d_resource;
238 239 240 241

    TRACE("iface %p, desc %p.\n", iface, desc);

    wined3d_mutex_lock();
242 243
    wined3d_resource = wined3d_buffer_get_resource(buffer->wineD3DVertexBuffer);
    wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
244 245
    wined3d_mutex_unlock();

246
    desc->Format = D3DFMT_VERTEXDATA;
247
    desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
248 249
    desc->Pool = wined3d_desc.pool;
    desc->Size = wined3d_desc.size;
250 251
    desc->Type = D3DRTYPE_VERTEXBUFFER;
    desc->FVF = buffer->fvf;
252

253
    return D3D_OK;
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
}

static const IDirect3DVertexBuffer9Vtbl d3d9_vertexbuffer_vtbl =
{
    /* IUnknown */
    d3d9_vertexbuffer_QueryInterface,
    d3d9_vertexbuffer_AddRef,
    d3d9_vertexbuffer_Release,
    /* IDirect3DResource9 */
    d3d9_vertexbuffer_GetDevice,
    d3d9_vertexbuffer_SetPrivateData,
    d3d9_vertexbuffer_GetPrivateData,
    d3d9_vertexbuffer_FreePrivateData,
    d3d9_vertexbuffer_SetPriority,
    d3d9_vertexbuffer_GetPriority,
    d3d9_vertexbuffer_PreLoad,
    d3d9_vertexbuffer_GetType,
    /* IDirect3DVertexBuffer9 */
    d3d9_vertexbuffer_Lock,
    d3d9_vertexbuffer_Unlock,
    d3d9_vertexbuffer_GetDesc,
};

static void STDMETHODCALLTYPE d3d9_vertexbuffer_wined3d_object_destroyed(void *parent)
{
    HeapFree(GetProcessHeap(), 0, parent);
}

static const struct wined3d_parent_ops d3d9_vertexbuffer_wined3d_parent_ops =
{
    d3d9_vertexbuffer_wined3d_object_destroyed,
};

HRESULT vertexbuffer_init(IDirect3DVertexBuffer9Impl *buffer, IDirect3DDevice9Impl *device,
        UINT size, UINT usage, DWORD fvf, D3DPOOL pool)
{
    HRESULT hr;

292
    buffer->IDirect3DVertexBuffer9_iface.lpVtbl = &d3d9_vertexbuffer_vtbl;
293 294 295 296
    buffer->ref = 1;
    buffer->fvf = fvf;

    wined3d_mutex_lock();
297
    hr = wined3d_buffer_create_vb(device->wined3d_device, size, usage & WINED3DUSAGE_MASK,
298
            (enum wined3d_pool)pool, buffer, &d3d9_vertexbuffer_wined3d_parent_ops, &buffer->wineD3DVertexBuffer);
299 300 301 302 303 304 305
    wined3d_mutex_unlock();
    if (FAILED(hr))
    {
        WARN("Failed to create wined3d buffer, hr %#x.\n", hr);
        return hr;
    }

306
    buffer->parentDevice = &device->IDirect3DDevice9Ex_iface;
307 308 309 310 311
    IDirect3DDevice9Ex_AddRef(buffer->parentDevice);

    return D3D_OK;
}

312 313 314 315 316 317 318 319 320
IDirect3DVertexBuffer9Impl *unsafe_impl_from_IDirect3DVertexBuffer9(IDirect3DVertexBuffer9 *iface)
{
    if (!iface)
        return NULL;
    assert(iface->lpVtbl == &d3d9_vertexbuffer_vtbl);

    return impl_from_IDirect3DVertexBuffer9(iface);
}

321 322
static inline IDirect3DIndexBuffer9Impl *impl_from_IDirect3DIndexBuffer9(IDirect3DIndexBuffer9 *iface)
{
323
    return CONTAINING_RECORD(iface, IDirect3DIndexBuffer9Impl, IDirect3DIndexBuffer9_iface);
324 325
}

326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
static HRESULT WINAPI d3d9_indexbuffer_QueryInterface(IDirect3DIndexBuffer9 *iface, REFIID riid, void **object)
{
    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);

    if (IsEqualGUID(riid, &IID_IDirect3DIndexBuffer9)
            || IsEqualGUID(riid, &IID_IDirect3DResource9)
            || IsEqualGUID(riid, &IID_IUnknown))
    {
        IDirect3DIndexBuffer9_AddRef(iface);
        *object = iface;
        return S_OK;
    }

    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));

    *object = NULL;
    return E_NOINTERFACE;
}

static ULONG WINAPI d3d9_indexbuffer_AddRef(IDirect3DIndexBuffer9 *iface)
{
347
    IDirect3DIndexBuffer9Impl *buffer = impl_from_IDirect3DIndexBuffer9(iface);
348 349 350 351 352 353 354 355
    ULONG refcount = InterlockedIncrement(&buffer->ref);

    TRACE("%p increasing refcount to %u.\n", iface, refcount);

    if (refcount == 1)
    {
        IDirect3DDevice9Ex_AddRef(buffer->parentDevice);
        wined3d_mutex_lock();
356
        wined3d_buffer_incref(buffer->wineD3DIndexBuffer);
357 358 359 360 361 362 363 364
        wined3d_mutex_unlock();
    }

    return refcount;
}

static ULONG WINAPI d3d9_indexbuffer_Release(IDirect3DIndexBuffer9 *iface)
{
365
    IDirect3DIndexBuffer9Impl *buffer = impl_from_IDirect3DIndexBuffer9(iface);
366 367 368 369 370 371 372 373 374
    ULONG refcount = InterlockedDecrement(&buffer->ref);

    TRACE("%p decreasing refcount to %u.\n", iface, refcount);

    if (!refcount)
    {
        IDirect3DDevice9Ex *device = buffer->parentDevice;

        wined3d_mutex_lock();
375
        wined3d_buffer_decref(buffer->wineD3DIndexBuffer);
376 377 378 379 380 381 382 383 384
        wined3d_mutex_unlock();

        /* Release the device last, as it may cause the device to be destroyed. */
        IDirect3DDevice9Ex_Release(device);
    }

    return refcount;
}

385 386
static HRESULT WINAPI d3d9_indexbuffer_GetDevice(IDirect3DIndexBuffer9 *iface,
        IDirect3DDevice9 **device)
387
{
388 389
    IDirect3DIndexBuffer9Impl *buffer = impl_from_IDirect3DIndexBuffer9(iface);

390 391
    TRACE("iface %p, device %p.\n", iface, device);

392
    *device = (IDirect3DDevice9 *)buffer->parentDevice;
393 394 395 396 397 398 399 400 401 402
    IDirect3DDevice9_AddRef(*device);

    TRACE("Returning device %p.\n", *device);

    return D3D_OK;
}

static HRESULT WINAPI d3d9_indexbuffer_SetPrivateData(IDirect3DIndexBuffer9 *iface,
        REFGUID guid, const void *data, DWORD data_size, DWORD flags)
{
403 404
    IDirect3DIndexBuffer9Impl *buffer = impl_from_IDirect3DIndexBuffer9(iface);
    struct wined3d_resource *resource;
405 406 407 408 409 410
    HRESULT hr;

    TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
            iface, debugstr_guid(guid), data, data_size, flags);

    wined3d_mutex_lock();
411 412
    resource = wined3d_buffer_get_resource(buffer->wineD3DIndexBuffer);
    hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
413 414 415 416 417 418 419 420
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI d3d9_indexbuffer_GetPrivateData(IDirect3DIndexBuffer9 *iface,
        REFGUID guid, void *data, DWORD *data_size)
{
421 422
    IDirect3DIndexBuffer9Impl *buffer = impl_from_IDirect3DIndexBuffer9(iface);
    struct wined3d_resource *resource;
423 424 425 426 427 428
    HRESULT hr;

    TRACE("iface %p, guid %s, data %p, data_size %p.\n",
            iface, debugstr_guid(guid), data, data_size);

    wined3d_mutex_lock();
429 430
    resource = wined3d_buffer_get_resource(buffer->wineD3DIndexBuffer);
    hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
431 432 433 434 435 436 437
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI d3d9_indexbuffer_FreePrivateData(IDirect3DIndexBuffer9 *iface, REFGUID guid)
{
438 439
    IDirect3DIndexBuffer9Impl *buffer = impl_from_IDirect3DIndexBuffer9(iface);
    struct wined3d_resource *resource;
440 441 442 443 444
    HRESULT hr;

    TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));

    wined3d_mutex_lock();
445 446
    resource = wined3d_buffer_get_resource(buffer->wineD3DIndexBuffer);
    hr = wined3d_resource_free_private_data(resource, guid);
447 448 449 450 451 452 453
    wined3d_mutex_unlock();

    return hr;
}

static DWORD WINAPI d3d9_indexbuffer_SetPriority(IDirect3DIndexBuffer9 *iface, DWORD priority)
{
454
    IDirect3DIndexBuffer9Impl *buffer = impl_from_IDirect3DIndexBuffer9(iface);
455 456 457 458 459
    DWORD previous;

    TRACE("iface %p, priority %u.\n", iface, priority);

    wined3d_mutex_lock();
460
    previous = wined3d_buffer_set_priority(buffer->wineD3DIndexBuffer, priority);
461 462 463 464 465 466 467
    wined3d_mutex_unlock();

    return previous;
}

static DWORD WINAPI d3d9_indexbuffer_GetPriority(IDirect3DIndexBuffer9 *iface)
{
468
    IDirect3DIndexBuffer9Impl *buffer = impl_from_IDirect3DIndexBuffer9(iface);
469 470 471 472 473
    DWORD priority;

    TRACE("iface %p.\n", iface);

    wined3d_mutex_lock();
474
    priority = wined3d_buffer_get_priority(buffer->wineD3DIndexBuffer);
475 476 477 478 479 480 481
    wined3d_mutex_unlock();

    return priority;
}

static void WINAPI d3d9_indexbuffer_PreLoad(IDirect3DIndexBuffer9 *iface)
{
482 483
    IDirect3DIndexBuffer9Impl *buffer = impl_from_IDirect3DIndexBuffer9(iface);

484 485 486
    TRACE("iface %p.\n", iface);

    wined3d_mutex_lock();
487
    wined3d_buffer_preload(buffer->wineD3DIndexBuffer);
488 489 490 491 492 493 494 495 496 497 498 499 500
    wined3d_mutex_unlock();
}

static D3DRESOURCETYPE WINAPI d3d9_indexbuffer_GetType(IDirect3DIndexBuffer9 *iface)
{
    TRACE("iface %p.\n", iface);

    return D3DRTYPE_INDEXBUFFER;
}

static HRESULT WINAPI d3d9_indexbuffer_Lock(IDirect3DIndexBuffer9 *iface,
        UINT offset, UINT size, void **data, DWORD flags)
{
501
    IDirect3DIndexBuffer9Impl *buffer = impl_from_IDirect3DIndexBuffer9(iface);
502 503 504 505 506 507
    HRESULT hr;

    TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n",
            iface, offset, size, data, flags);

    wined3d_mutex_lock();
508
    hr = wined3d_buffer_map(buffer->wineD3DIndexBuffer, offset, size, (BYTE **)data, flags);
509 510 511 512 513 514 515
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI d3d9_indexbuffer_Unlock(IDirect3DIndexBuffer9 *iface)
{
516 517
    IDirect3DIndexBuffer9Impl *buffer = impl_from_IDirect3DIndexBuffer9(iface);

518 519 520
    TRACE("iface %p.\n", iface);

    wined3d_mutex_lock();
521
    wined3d_buffer_unmap(buffer->wineD3DIndexBuffer);
522 523
    wined3d_mutex_unlock();

524
    return D3D_OK;
525 526
}

527 528
static HRESULT WINAPI d3d9_indexbuffer_GetDesc(IDirect3DIndexBuffer9 *iface,
        D3DINDEXBUFFER_DESC *desc)
529
{
530
    IDirect3DIndexBuffer9Impl *buffer = impl_from_IDirect3DIndexBuffer9(iface);
531
    struct wined3d_resource_desc wined3d_desc;
532
    struct wined3d_resource *wined3d_resource;
533 534 535 536

    TRACE("iface %p, desc %p.\n", iface, desc);

    wined3d_mutex_lock();
537 538
    wined3d_resource = wined3d_buffer_get_resource(buffer->wineD3DIndexBuffer);
    wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
539 540
    wined3d_mutex_unlock();

541
    desc->Format = d3dformat_from_wined3dformat(buffer->format);
542
    desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
543 544
    desc->Pool = wined3d_desc.pool;
    desc->Size = wined3d_desc.size;
545
    desc->Type = D3DRTYPE_INDEXBUFFER;
546

547
    return D3D_OK;
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
}

static const IDirect3DIndexBuffer9Vtbl d3d9_indexbuffer_vtbl =
{
    /* IUnknown */
    d3d9_indexbuffer_QueryInterface,
    d3d9_indexbuffer_AddRef,
    d3d9_indexbuffer_Release,
    /* IDirect3DResource9 */
    d3d9_indexbuffer_GetDevice,
    d3d9_indexbuffer_SetPrivateData,
    d3d9_indexbuffer_GetPrivateData,
    d3d9_indexbuffer_FreePrivateData,
    d3d9_indexbuffer_SetPriority,
    d3d9_indexbuffer_GetPriority,
    d3d9_indexbuffer_PreLoad,
    d3d9_indexbuffer_GetType,
    /* IDirect3DIndexBuffer9 */
    d3d9_indexbuffer_Lock,
    d3d9_indexbuffer_Unlock,
    d3d9_indexbuffer_GetDesc,
};

static void STDMETHODCALLTYPE d3d9_indexbuffer_wined3d_object_destroyed(void *parent)
{
    HeapFree(GetProcessHeap(), 0, parent);
}

static const struct wined3d_parent_ops d3d9_indexbuffer_wined3d_parent_ops =
{
    d3d9_indexbuffer_wined3d_object_destroyed,
};

HRESULT indexbuffer_init(IDirect3DIndexBuffer9Impl *buffer, IDirect3DDevice9Impl *device,
        UINT size, DWORD usage, D3DFORMAT format, D3DPOOL pool)
{
    HRESULT hr;

586
    buffer->IDirect3DIndexBuffer9_iface.lpVtbl = &d3d9_indexbuffer_vtbl;
587 588 589 590
    buffer->ref = 1;
    buffer->format = wined3dformat_from_d3dformat(format);

    wined3d_mutex_lock();
591
    hr = wined3d_buffer_create_ib(device->wined3d_device, size, usage & WINED3DUSAGE_MASK,
592
            (enum wined3d_pool)pool, buffer, &d3d9_indexbuffer_wined3d_parent_ops, &buffer->wineD3DIndexBuffer);
593 594 595 596 597 598 599
    wined3d_mutex_unlock();
    if (FAILED(hr))
    {
        WARN("Failed to create wined3d buffer, hr %#x.\n", hr);
        return hr;
    }

600
    buffer->parentDevice = &device->IDirect3DDevice9Ex_iface;
601 602 603 604
    IDirect3DDevice9Ex_AddRef(buffer->parentDevice);

    return D3D_OK;
}
605 606 607 608 609 610 611 612 613

IDirect3DIndexBuffer9Impl *unsafe_impl_from_IDirect3DIndexBuffer9(IDirect3DIndexBuffer9 *iface)
{
    if (!iface)
        return NULL;
    assert(iface->lpVtbl == &d3d9_indexbuffer_vtbl);

    return impl_from_IDirect3DIndexBuffer9(iface);
}