buffer.c 18.2 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
/*
 * 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 "d3d8_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(d3d8);

24
static inline struct d3d8_vertexbuffer *impl_from_IDirect3DVertexBuffer8(IDirect3DVertexBuffer8 *iface)
25
{
26
    return CONTAINING_RECORD(iface, struct d3d8_vertexbuffer, IDirect3DVertexBuffer8_iface);
27 28
}

29 30 31 32 33 34 35 36
static HRESULT WINAPI d3d8_vertexbuffer_QueryInterface(IDirect3DVertexBuffer8 *iface, REFIID riid, void **object)
{
    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);

    if (IsEqualGUID(riid, &IID_IDirect3DVertexBuffer8)
            || IsEqualGUID(riid, &IID_IDirect3DResource8)
            || IsEqualGUID(riid, &IID_IUnknown))
    {
37
        IDirect3DVertexBuffer8_AddRef(iface);
38 39 40 41 42 43 44 45 46 47 48 49
        *object = iface;
        return S_OK;
    }

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

    *object = NULL;
    return E_NOINTERFACE;
}

static ULONG WINAPI d3d8_vertexbuffer_AddRef(IDirect3DVertexBuffer8 *iface)
{
50 51
    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
    ULONG refcount = InterlockedIncrement(&buffer->refcount);
52 53 54 55 56

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

    if (refcount == 1)
    {
57
        IDirect3DDevice8_AddRef(buffer->parent_device);
58
        wined3d_mutex_lock();
59
        wined3d_buffer_incref(buffer->wined3d_buffer);
60 61 62 63 64 65 66 67
        wined3d_mutex_unlock();
    }

    return refcount;
}

static ULONG WINAPI d3d8_vertexbuffer_Release(IDirect3DVertexBuffer8 *iface)
{
68 69
    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
    ULONG refcount = InterlockedDecrement(&buffer->refcount);
70 71 72 73 74

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

    if (!refcount)
    {
75
        IDirect3DDevice8 *device = buffer->parent_device;
76 77

        wined3d_mutex_lock();
78
        wined3d_buffer_decref(buffer->wined3d_buffer);
79 80 81 82 83 84 85 86 87
        wined3d_mutex_unlock();

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

    return refcount;
}

88 89
static HRESULT WINAPI d3d8_vertexbuffer_GetDevice(IDirect3DVertexBuffer8 *iface,
        IDirect3DDevice8 **device)
90
{
91
    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
92

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

95
    *device = buffer->parent_device;
96 97 98 99 100 101 102 103 104 105
    IDirect3DDevice8_AddRef(*device);

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

    return D3D_OK;
}

static HRESULT WINAPI d3d8_vertexbuffer_SetPrivateData(IDirect3DVertexBuffer8 *iface,
        REFGUID guid, const void *data, DWORD data_size, DWORD flags)
{
106
    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
107
    struct wined3d_resource *resource;
108 109 110 111 112 113
    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();
114
    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
115
    hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
116 117 118 119 120 121 122 123
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI d3d8_vertexbuffer_GetPrivateData(IDirect3DVertexBuffer8 *iface,
        REFGUID guid, void *data, DWORD *data_size)
{
124
    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
125
    struct wined3d_resource *resource;
126 127 128 129 130 131
    HRESULT hr;

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

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

    return hr;
}

static HRESULT WINAPI d3d8_vertexbuffer_FreePrivateData(IDirect3DVertexBuffer8 *iface, REFGUID guid)
{
141
    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
142
    struct wined3d_resource *resource;
143 144 145 146 147
    HRESULT hr;

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

    wined3d_mutex_lock();
148
    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
149
    hr = wined3d_resource_free_private_data(resource, guid);
150 151 152 153 154 155 156
    wined3d_mutex_unlock();

    return hr;
}

static DWORD WINAPI d3d8_vertexbuffer_SetPriority(IDirect3DVertexBuffer8 *iface, DWORD priority)
{
157
    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
158 159 160 161 162
    DWORD previous;

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

    wined3d_mutex_lock();
163
    previous = wined3d_buffer_set_priority(buffer->wined3d_buffer, priority);
164 165 166 167 168 169 170
    wined3d_mutex_unlock();

    return previous;
}

static DWORD WINAPI d3d8_vertexbuffer_GetPriority(IDirect3DVertexBuffer8 *iface)
{
171
    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
172 173 174 175 176
    DWORD priority;

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

    wined3d_mutex_lock();
177
    priority = wined3d_buffer_get_priority(buffer->wined3d_buffer);
178 179 180 181 182 183 184
    wined3d_mutex_unlock();

    return priority;
}

static void WINAPI d3d8_vertexbuffer_PreLoad(IDirect3DVertexBuffer8 *iface)
{
185
    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
186

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

    wined3d_mutex_lock();
190
    wined3d_buffer_preload(buffer->wined3d_buffer);
191 192 193 194 195 196 197 198 199 200
    wined3d_mutex_unlock();
}

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

    return D3DRTYPE_VERTEXBUFFER;
}

201 202
static HRESULT WINAPI d3d8_vertexbuffer_Lock(IDirect3DVertexBuffer8 *iface, UINT offset, UINT size,
        BYTE **data, DWORD flags)
203
{
204
    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
205 206 207 208 209 210
    HRESULT hr;

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

    wined3d_mutex_lock();
211
    hr = wined3d_buffer_map(buffer->wined3d_buffer, offset, size, data, flags);
212 213 214 215 216 217 218
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI d3d8_vertexbuffer_Unlock(IDirect3DVertexBuffer8 *iface)
{
219
    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
220

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

    wined3d_mutex_lock();
224
    wined3d_buffer_unmap(buffer->wined3d_buffer);
225 226
    wined3d_mutex_unlock();

227
    return D3D_OK;
228 229
}

230 231
static HRESULT WINAPI d3d8_vertexbuffer_GetDesc(IDirect3DVertexBuffer8 *iface,
        D3DVERTEXBUFFER_DESC *desc)
232
{
233
    struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
234
    struct wined3d_resource_desc wined3d_desc;
235
    struct wined3d_resource *wined3d_resource;
236 237 238 239

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

    wined3d_mutex_lock();
240
    wined3d_resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
241
    wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
242 243
    wined3d_mutex_unlock();

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

251
    return D3D_OK;
252 253 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
}

static const IDirect3DVertexBuffer8Vtbl Direct3DVertexBuffer8_Vtbl =
{
    /* IUnknown */
    d3d8_vertexbuffer_QueryInterface,
    d3d8_vertexbuffer_AddRef,
    d3d8_vertexbuffer_Release,
    /* IDirect3DResource8 */
    d3d8_vertexbuffer_GetDevice,
    d3d8_vertexbuffer_SetPrivateData,
    d3d8_vertexbuffer_GetPrivateData,
    d3d8_vertexbuffer_FreePrivateData,
    d3d8_vertexbuffer_SetPriority,
    d3d8_vertexbuffer_GetPriority,
    d3d8_vertexbuffer_PreLoad,
    d3d8_vertexbuffer_GetType,
    /* IDirect3DVertexBuffer8 */
    d3d8_vertexbuffer_Lock,
    d3d8_vertexbuffer_Unlock,
    d3d8_vertexbuffer_GetDesc,
};

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

static const struct wined3d_parent_ops d3d8_vertexbuffer_wined3d_parent_ops =
{
    d3d8_vertexbuffer_wined3d_object_destroyed,
};

285
HRESULT vertexbuffer_init(struct d3d8_vertexbuffer *buffer, struct d3d8_device *device,
286 287 288 289
        UINT size, DWORD usage, DWORD fvf, D3DPOOL pool)
{
    HRESULT hr;

290
    buffer->IDirect3DVertexBuffer8_iface.lpVtbl = &Direct3DVertexBuffer8_Vtbl;
291
    buffer->refcount = 1;
292 293 294
    buffer->fvf = fvf;

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

304
    buffer->parent_device = &device->IDirect3DDevice8_iface;
305
    IDirect3DDevice8_AddRef(buffer->parent_device);
306 307 308 309

    return D3D_OK;
}

310
struct d3d8_vertexbuffer *unsafe_impl_from_IDirect3DVertexBuffer8(IDirect3DVertexBuffer8 *iface)
311 312 313 314 315 316 317 318
{
    if (!iface)
        return NULL;
    assert(iface->lpVtbl == &Direct3DVertexBuffer8_Vtbl);

    return impl_from_IDirect3DVertexBuffer8(iface);
}

319
static inline struct d3d8_indexbuffer *impl_from_IDirect3DIndexBuffer8(IDirect3DIndexBuffer8 *iface)
320
{
321
    return CONTAINING_RECORD(iface, struct d3d8_indexbuffer, IDirect3DIndexBuffer8_iface);
322 323
}

324 325 326 327 328 329 330 331
static HRESULT WINAPI d3d8_indexbuffer_QueryInterface(IDirect3DIndexBuffer8 *iface, REFIID riid, void **object)
{
    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);

    if (IsEqualGUID(riid, &IID_IDirect3DIndexBuffer8)
            || IsEqualGUID(riid, &IID_IDirect3DResource8)
            || IsEqualGUID(riid, &IID_IUnknown))
    {
332
        IDirect3DIndexBuffer8_AddRef(iface);
333 334 335 336 337 338 339 340 341 342 343 344
        *object = iface;
        return S_OK;
    }

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

    *object = NULL;
    return E_NOINTERFACE;
}

static ULONG WINAPI d3d8_indexbuffer_AddRef(IDirect3DIndexBuffer8 *iface)
{
345 346
    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
    ULONG refcount = InterlockedIncrement(&buffer->refcount);
347 348 349 350 351

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

    if (refcount == 1)
    {
352
        IDirect3DDevice8_AddRef(buffer->parent_device);
353
        wined3d_mutex_lock();
354
        wined3d_buffer_incref(buffer->wined3d_buffer);
355 356 357 358 359 360 361 362
        wined3d_mutex_unlock();
    }

    return refcount;
}

static ULONG WINAPI d3d8_indexbuffer_Release(IDirect3DIndexBuffer8 *iface)
{
363 364
    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
    ULONG refcount = InterlockedDecrement(&buffer->refcount);
365 366 367 368 369

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

    if (!refcount)
    {
370
        IDirect3DDevice8 *device = buffer->parent_device;
371 372

        wined3d_mutex_lock();
373
        wined3d_buffer_decref(buffer->wined3d_buffer);
374 375 376 377 378 379 380 381 382
        wined3d_mutex_unlock();

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

    return refcount;
}

383 384
static HRESULT WINAPI d3d8_indexbuffer_GetDevice(IDirect3DIndexBuffer8 *iface,
        IDirect3DDevice8 **device)
385
{
386
    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
387

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

390
    *device = buffer->parent_device;
391 392 393 394 395 396 397 398 399 400
    IDirect3DDevice8_AddRef(*device);

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

    return D3D_OK;
}

static HRESULT WINAPI d3d8_indexbuffer_SetPrivateData(IDirect3DIndexBuffer8 *iface,
        REFGUID guid, const void *data, DWORD data_size, DWORD flags)
{
401
    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
402
    struct wined3d_resource *resource;
403 404 405 406 407 408
    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();
409
    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
410
    hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
411 412 413 414 415 416 417 418
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI d3d8_indexbuffer_GetPrivateData(IDirect3DIndexBuffer8 *iface,
        REFGUID guid, void *data, DWORD *data_size)
{
419
    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
420
    struct wined3d_resource *resource;
421 422 423 424 425 426
    HRESULT hr;

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

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

    return hr;
}

static HRESULT WINAPI d3d8_indexbuffer_FreePrivateData(IDirect3DIndexBuffer8 *iface, REFGUID guid)
{
436
    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
437
    struct wined3d_resource *resource;
438 439 440 441 442
    HRESULT hr;

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

    wined3d_mutex_lock();
443
    resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
444
    hr = wined3d_resource_free_private_data(resource, guid);
445 446 447 448 449 450 451
    wined3d_mutex_unlock();

    return hr;
}

static DWORD WINAPI d3d8_indexbuffer_SetPriority(IDirect3DIndexBuffer8 *iface, DWORD priority)
{
452
    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
453 454 455 456 457
    DWORD previous;

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

    wined3d_mutex_lock();
458
    previous = wined3d_buffer_set_priority(buffer->wined3d_buffer, priority);
459 460 461 462 463 464 465
    wined3d_mutex_unlock();

    return previous;
}

static DWORD WINAPI d3d8_indexbuffer_GetPriority(IDirect3DIndexBuffer8 *iface)
{
466
    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
467 468 469 470 471
    DWORD priority;

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

    wined3d_mutex_lock();
472
    priority = wined3d_buffer_get_priority(buffer->wined3d_buffer);
473 474 475 476 477 478 479
    wined3d_mutex_unlock();

    return priority;
}

static void WINAPI d3d8_indexbuffer_PreLoad(IDirect3DIndexBuffer8 *iface)
{
480
    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
481

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

    wined3d_mutex_lock();
485
    wined3d_buffer_preload(buffer->wined3d_buffer);
486 487 488 489 490 491 492 493 494 495
    wined3d_mutex_unlock();
}

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

    return D3DRTYPE_INDEXBUFFER;
}

496 497
static HRESULT WINAPI d3d8_indexbuffer_Lock(IDirect3DIndexBuffer8 *iface, UINT offset, UINT size,
        BYTE **data, DWORD flags)
498
{
499
    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
500 501 502 503 504 505
    HRESULT hr;

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

    wined3d_mutex_lock();
506
    hr = wined3d_buffer_map(buffer->wined3d_buffer, offset, size, data, flags);
507 508 509 510 511 512 513
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI d3d8_indexbuffer_Unlock(IDirect3DIndexBuffer8 *iface)
{
514
    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
515

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

    wined3d_mutex_lock();
519
    wined3d_buffer_unmap(buffer->wined3d_buffer);
520 521
    wined3d_mutex_unlock();

522
    return D3D_OK;
523 524
}

525 526
static HRESULT WINAPI d3d8_indexbuffer_GetDesc(IDirect3DIndexBuffer8 *iface,
        D3DINDEXBUFFER_DESC *desc)
527
{
528
    struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
529
    struct wined3d_resource_desc wined3d_desc;
530
    struct wined3d_resource *wined3d_resource;
531 532 533 534

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

    wined3d_mutex_lock();
535
    wined3d_resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
536
    wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
537 538
    wined3d_mutex_unlock();

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

545
    return D3D_OK;
546 547 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
}

static const IDirect3DIndexBuffer8Vtbl d3d8_indexbuffer_vtbl =
{
    /* IUnknown */
    d3d8_indexbuffer_QueryInterface,
    d3d8_indexbuffer_AddRef,
    d3d8_indexbuffer_Release,
    /* IDirect3DResource8 */
    d3d8_indexbuffer_GetDevice,
    d3d8_indexbuffer_SetPrivateData,
    d3d8_indexbuffer_GetPrivateData,
    d3d8_indexbuffer_FreePrivateData,
    d3d8_indexbuffer_SetPriority,
    d3d8_indexbuffer_GetPriority,
    d3d8_indexbuffer_PreLoad,
    d3d8_indexbuffer_GetType,
    /* IDirect3DIndexBuffer8 */
    d3d8_indexbuffer_Lock,
    d3d8_indexbuffer_Unlock,
    d3d8_indexbuffer_GetDesc,
};

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

static const struct wined3d_parent_ops d3d8_indexbuffer_wined3d_parent_ops =
{
    d3d8_indexbuffer_wined3d_object_destroyed,
};

579
HRESULT indexbuffer_init(struct d3d8_indexbuffer *buffer, struct d3d8_device *device,
580 581 582 583
        UINT size, DWORD usage, D3DFORMAT format, D3DPOOL pool)
{
    HRESULT hr;

584
    buffer->IDirect3DIndexBuffer8_iface.lpVtbl = &d3d8_indexbuffer_vtbl;
585
    buffer->refcount = 1;
586 587 588
    buffer->format = wined3dformat_from_d3dformat(format);

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

598
    buffer->parent_device = &device->IDirect3DDevice8_iface;
599
    IDirect3DDevice8_AddRef(buffer->parent_device);
600 601 602

    return D3D_OK;
}
603

604
struct d3d8_indexbuffer *unsafe_impl_from_IDirect3DIndexBuffer8(IDirect3DIndexBuffer8 *iface)
605 606 607 608 609 610 611
{
    if (!iface)
        return NULL;
    assert(iface->lpVtbl == &d3d8_indexbuffer_vtbl);

    return impl_from_IDirect3DIndexBuffer8(iface);
}