vertexbuffer.c 23.5 KB
Newer Older
1
/* Direct3D Vertex Buffer
2
 * Copyright (c) 2002 Lionel ULMER
3
 * Copyright (c) 2006 Stefan DSINGER
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * This file contains the implementation of Direct3DVertexBuffer COM object
 *
 * 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
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 21 22
 */

#include "config.h"
23 24 25 26
#include "wine/port.h"
#include "wine/debug.h"

#include <assert.h>
27
#include <stdarg.h>
28 29 30 31
#include <string.h>
#include <stdlib.h>

#define COBJMACROS
32

33
#include "windef.h"
34
#include "winbase.h"
35
#include "winerror.h"
36
#include "wingdi.h"
37 38
#include "wine/exception.h"

39 40 41
#include "ddraw.h"
#include "d3d.h"

42 43 44 45
#include "ddraw_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(d3d7);
WINE_DECLARE_DEBUG_CHANNEL(ddraw_thunk);
46 47


48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
/*****************************************************************************
 * IUnknown Methods
 *****************************************************************************/

/*****************************************************************************
 * IDirect3DVertexBuffer7::QueryInterface
 *
 * The QueryInterface Method for Vertex Buffers
 * For a link to QueryInterface rules, see IDirectDraw7::QueryInterface
 *
 * Params
 *  riid: Queryied Interface id
 *  obj: Address to return the interface pointer
 *
 * Returns:
 *  S_OK on success
 *  E_NOINTERFACE if the interface wasn't found
 *
 *****************************************************************************/
static HRESULT WINAPI
IDirect3DVertexBufferImpl_QueryInterface(IDirect3DVertexBuffer7 *iface,
                                         REFIID riid,
                                         void  **obj)
71 72
{
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
73
    TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), obj);
74 75

    /* By default, set the object pointer to NULL */
76 77 78 79
    *obj = NULL;

    if ( IsEqualGUID( &IID_IUnknown,  riid ) )
    {
80
        IDirect3DVertexBuffer7_AddRef(ICOM_INTERFACE(This,IDirect3DVertexBuffer7));
81 82 83
        *obj = iface;
        TRACE("  Creating IUnknown interface at %p.\n", *obj);
        return S_OK;
84
    }
85 86
    if ( IsEqualGUID( &IID_IDirect3DVertexBuffer, riid ) )
    {
87
        IDirect3DVertexBuffer7_AddRef(ICOM_INTERFACE(This,IDirect3DVertexBuffer7));
88 89 90
        *obj = ICOM_INTERFACE(This, IDirect3DVertexBuffer);
        TRACE("  Creating IDirect3DVertexBuffer interface %p\n", *obj);
        return S_OK;
91
    }
92 93
    if ( IsEqualGUID( &IID_IDirect3DVertexBuffer7, riid ) )
    {
94
        IDirect3DVertexBuffer7_AddRef(ICOM_INTERFACE(This,IDirect3DVertexBuffer7));
95 96 97
        *obj = ICOM_INTERFACE(This, IDirect3DVertexBuffer7);
        TRACE("  Creating IDirect3DVertexBuffer7 interface %p\n", *obj);
        return S_OK;
98 99
    }
    FIXME("(%p): interface for IID %s NOT found!\n", This, debugstr_guid(riid));
100
    return E_NOINTERFACE;
101 102
}

103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
static HRESULT WINAPI
Thunk_IDirect3DVertexBufferImpl_1_QueryInterface(IDirect3DVertexBuffer *iface,
                                                 REFIID riid,
                                                 void **obj)
{
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, iface);
    TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DVertexBuffer7 interface.\n", This, debugstr_guid(riid), obj);

    return IDirect3DVertexBuffer7_QueryInterface(ICOM_INTERFACE(This, IDirect3DVertexBuffer7),
                                                 riid,
                                                 obj);
}

/*****************************************************************************
 * IDirect3DVertexBuffer7::AddRef
 *
 * AddRef for Vertex Buffers
 *
 * Returns:
 *  The new refcount
 *
 *****************************************************************************/
125
static ULONG WINAPI
126
IDirect3DVertexBufferImpl_AddRef(IDirect3DVertexBuffer7 *iface)
127 128
{
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
129 130
    ULONG ref = InterlockedIncrement(&This->ref);

131
    TRACE("(%p/%p)->() incrementing from %u.\n", This, iface, ref - 1);
132 133

    return ref;
134 135
}

136
static ULONG WINAPI
137
Thunk_IDirect3DVertexBufferImpl_1_AddRef(IDirect3DVertexBuffer *iface)
138
{
139 140
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, iface);
    TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DVertexBuffer7 interface.\n", This);
141

142
    return IDirect3DVertexBuffer7_AddRef(ICOM_INTERFACE(This, IDirect3DVertexBuffer7));
143 144
}

145 146 147 148 149 150 151 152 153 154

/*****************************************************************************
 * IDirect3DVertexBuffer7::Release
 *
 * Release for Vertex Buffers
 *
 * Returns:
 *  The new refcount
 *
 *****************************************************************************/
155
static ULONG WINAPI
156
IDirect3DVertexBufferImpl_Release(IDirect3DVertexBuffer7 *iface)
157 158
{
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
159
    ULONG ref = InterlockedDecrement(&This->ref);
160

161
    TRACE("(%p)->() decrementing from %u.\n", This, ref + 1);
162

163 164
    if (ref == 0)
    {
165 166 167
        IWineD3DVertexBuffer *curVB = NULL;
        UINT offset, stride;

168
        EnterCriticalSection(&ddraw_cs);
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
        /* D3D7 Vertex buffers don't stay bound in the device, they are passed as a parameter
         * to drawPrimitiveVB. DrawPrimitiveVB sets them as the stream source in wined3d,
         * and they should get unset there before they are destroyed
         */
        IWineD3DDevice_GetStreamSource(This->ddraw->wineD3DDevice,
                                       0 /* Stream number */,
                                       &curVB,
                                       &offset,
                                       &stride);
        if(curVB == This->wineD3DVertexBuffer)
        {
            IWineD3DDevice_SetStreamSource(This->ddraw->wineD3DDevice,
                                        0 /* Steam number */,
                                        NULL /* stream data */,
                                        0 /* Offset */,
                                        0 /* stride */);
        }
        if(curVB)
        {
            IWineD3DVertexBuffer_Release(curVB); /* For the GetStreamSource */
        }

191
        IWineD3DVertexDeclaration_Release(This->wineD3DVertexDeclaration);
192
        IWineD3DVertexBuffer_Release(This->wineD3DVertexBuffer);
193
        LeaveCriticalSection(&ddraw_cs);
194
        HeapFree(GetProcessHeap(), 0, This);
195

196 197 198
        return 0;
    }
    return ref;
199 200
}

201
static ULONG WINAPI
202
Thunk_IDirect3DVertexBufferImpl_1_Release(IDirect3DVertexBuffer *iface)
203
{
204 205
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, iface);
    TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DVertexBuffer7 interface.\n", This);
206

207
    return IDirect3DVertexBuffer7_Release(ICOM_INTERFACE(This, IDirect3DVertexBuffer7));
208 209
}

210 211 212
/*****************************************************************************
 * IDirect3DVertexBuffer Methods
 *****************************************************************************/
213

214 215 216 217
/*****************************************************************************
 * IDirect3DVertexBuffer7::Lock
 *
 * Locks the vertex buffer and returns a pointer to the vertex data
218 219
 * Locking vertex buffers is similar to locking surfaces, because Windows
 * uses surfaces to store vertex data internally (According to the DX sdk)
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
 *
 * Params:
 *  Flags: Locking flags. Relevant here are DDLOCK_READONLY, DDLOCK_WRITEONLY,
 *         DDLOCK_DISCARDCONTENTS and DDLOCK_NOOVERWRITE.
 *  Data:  Returns a pointer to the vertex data
 *  Size:  Returns the size of the buffer if not NULL
 *
 * Returns:
 *  D3D_OK on success
 *  DDERR_INVALIDPARAMS if Data is NULL
 *  D3DERR_VERTEXBUFFEROPTIMIZED if called on an optimized buffer(WineD3D)
 *
 *****************************************************************************/
static HRESULT WINAPI
IDirect3DVertexBufferImpl_Lock(IDirect3DVertexBuffer7 *iface,
                               DWORD Flags,
                               void **Data,
                               DWORD *Size)
238 239
{
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
240 241
    WINED3DVERTEXBUFFER_DESC Desc;
    HRESULT hr;
242
    TRACE("(%p)->(%08x,%p,%p)\n", This, Flags, Data, Size);
243

244
    EnterCriticalSection(&ddraw_cs);
245
    if(Size)
246
    {
247 248 249 250 251
        /* Get the size, for returning it, and for locking */
        hr = IWineD3DVertexBuffer_GetDesc(This->wineD3DVertexBuffer,
                                          &Desc);
        if(hr != D3D_OK)
        {
252
            ERR("(%p) IWineD3DVertexBuffer::GetDesc failed with hr=%08x\n", This, hr);
253
            LeaveCriticalSection(&ddraw_cs);
254 255 256
            return hr;
        }
        *Size = Desc.Size;
257
    }
258

259 260 261 262 263 264 265
    hr = IWineD3DVertexBuffer_Lock(This->wineD3DVertexBuffer,
                                   0 /* OffsetToLock */,
                                   0 /* SizeToLock, 0 == Full lock */,
                                   (BYTE **) Data,
                                   Flags);
    LeaveCriticalSection(&ddraw_cs);
    return hr;
266 267
}

268 269 270 271 272
static HRESULT WINAPI
Thunk_IDirect3DVertexBufferImpl_1_Lock(IDirect3DVertexBuffer *iface,
                                       DWORD Flags,
                                       void **Data,
                                       DWORD *Size)
273
{
274
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, iface);
275
    TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%p) thunking to IDirect3DVertexBuffer7 interface.\n", This, Flags, Data, Size);
276

277 278 279 280
    return IDirect3DVertexBuffer7_Lock(ICOM_INTERFACE(This, IDirect3DVertexBuffer7),
                                       Flags,
                                       Data,
                                       Size);
281 282
}

283 284 285 286 287 288 289 290 291 292 293
/*****************************************************************************
 * IDirect3DVertexBuffer7::Unlock
 *
 * Unlocks a vertex Buffer
 *
 * Returns:
 *  D3D_OK on success
 *
 *****************************************************************************/
static HRESULT WINAPI
IDirect3DVertexBufferImpl_Unlock(IDirect3DVertexBuffer7 *iface)
294
{
295
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
296
    HRESULT hr;
297
    TRACE("(%p)->()\n", This);
298

299 300 301 302 303
    EnterCriticalSection(&ddraw_cs);
    hr = IWineD3DVertexBuffer_Unlock(This->wineD3DVertexBuffer);
    LeaveCriticalSection(&ddraw_cs);

    return hr;
304 305
}

306 307
static HRESULT WINAPI
Thunk_IDirect3DVertexBufferImpl_1_Unlock(IDirect3DVertexBuffer *iface)
308
{
309 310
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, iface);
    TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DVertexBuffer7 interface.\n", This);
311

312
    return IDirect3DVertexBuffer7_Unlock(ICOM_INTERFACE(This, IDirect3DVertexBuffer7));
313 314 315
}


316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
/*****************************************************************************
 * IDirect3DVertexBuffer7::ProcessVertices
 *
 * Processes untransformed Vertices into a transformed or optimized vertex
 * buffer. It can also perform other operations, such as lighting or clipping
 *
 * Params
 *  VertexOp: Operation(s) to perform: D3DVOP_CLIP, _EXTENTS, _LIGHT, _TRANSFORM
 *  DestIndex: Index in the destination buffer(This), where the vertices are
 *             placed
 *  Count: Number of Vertices in the Source buffer to process
 *  SrcBuffer: Source vertex buffer
 *  SrcIndex: Index of the first vertex in the src buffer to process
 *  D3DDevice: Device to use for transformation
 *  Flags: 0 for default, D3DPV_DONOTCOPYDATA to prevent copying
 *         unchaned vertices
 *
 * Returns:
 *  D3D_OK on success
 *  DDERR_INVALIDPARAMS If D3DVOP_TRANSFORM wasn't passed
 *
 *****************************************************************************/
static HRESULT WINAPI
IDirect3DVertexBufferImpl_ProcessVertices(IDirect3DVertexBuffer7 *iface,
                                          DWORD VertexOp,
                                          DWORD DestIndex,
                                          DWORD Count,
                                          IDirect3DVertexBuffer7 *SrcBuffer,
                                          DWORD SrcIndex,
                                          IDirect3DDevice7 *D3DDevice,
                                          DWORD Flags)
347
{
348 349 350 351 352
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
    IDirect3DVertexBufferImpl *Src = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, SrcBuffer);
    IDirect3DDeviceImpl *D3D = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice7, D3DDevice);
    BOOL oldClip, doClip;
    HRESULT hr;
353
    WINED3DVERTEXBUFFER_DESC Desc;
354

355
    TRACE("(%p)->(%08x,%d,%d,%p,%d,%p,%08x)\n", This, VertexOp, DestIndex, Count, Src, SrcIndex, D3D, Flags);
356 357 358 359 360 361 362 363 364 365 366 367 368

    /* Vertex operations:
     * D3DVOP_CLIP: Clips vertices outside the viewing frustrum. Needs clipping information
     * in the vertex buffer (Buffer may not be created with D3DVBCAPS_DONOTCLIP)
     * D3DVOP_EXTENTS: Causes the screen extents to be updated when rendering the vertices
     * D3DVOP_LIGHT: Lights the vertices
     * D3DVOP_TRANSFORM: Transform the vertices. This flag is necessary
     *
     * WineD3D only transforms and clips the vertices by now, so EXTENTS and LIGHT
     * are not implemented. Clipping is disabled ATM, because of unsure conditions.
     */
    if( !(VertexOp & D3DVOP_TRANSFORM) ) return DDERR_INVALIDPARAMS;

369
    EnterCriticalSection(&ddraw_cs);
370 371 372 373 374 375 376 377 378 379 380 381 382 383
    /* WineD3D doesn't know d3d7 vertex operation, it uses
     * render states instead. Set the render states according to
     * the vertex ops
     */
    doClip = VertexOp & D3DVOP_CLIP ? TRUE : FALSE;
    IWineD3DDevice_GetRenderState(D3D->wineD3DDevice,
                                  WINED3DRS_CLIPPING,
                                  (DWORD *) &oldClip);
    if(doClip != oldClip)
    {
        IWineD3DDevice_SetRenderState(D3D->wineD3DDevice,
                                      WINED3DRS_CLIPPING,
                                      doClip);
    }
384

385 386 387 388 389 390 391 392 393
    IWineD3DVertexBuffer_GetDesc(Src->wineD3DVertexBuffer,
                                 &Desc);
    IWineD3DDevice_SetStreamSource(D3D->wineD3DDevice,
                                   0, /* Stream No */
                                   Src->wineD3DVertexBuffer,
                                   0, /* Offset */
                                   get_flexible_vertex_size(Desc.FVF));
    IWineD3DDevice_SetVertexDeclaration(D3D->wineD3DDevice,
                                        Src->wineD3DVertexDeclaration);
394 395 396 397 398
    hr = IWineD3DDevice_ProcessVertices(D3D->wineD3DDevice,
                                        SrcIndex,
                                        DestIndex,
                                        Count,
                                        This->wineD3DVertexBuffer,
399
                                        NULL /* Output vdecl */,
400 401 402 403 404 405 406
                                        Flags);

    /* Restore the states if needed */
    if(doClip != oldClip)
        IWineD3DDevice_SetRenderState(D3D->wineD3DDevice,
                                      WINED3DRS_CLIPPING,
                                      oldClip);
407
    LeaveCriticalSection(&ddraw_cs);
408
    return hr;
409 410
}

411 412 413 414 415 416 417 418 419
static HRESULT WINAPI
Thunk_IDirect3DVertexBufferImpl_1_ProcessVertices(IDirect3DVertexBuffer *iface,
                                                  DWORD VertexOp,
                                                  DWORD DestIndex,
                                                  DWORD Count,
                                                  IDirect3DVertexBuffer *SrcBuffer,
                                                  DWORD SrcIndex,
                                                  IDirect3DDevice3 *D3DDevice,
                                                  DWORD Flags)
420
{
421 422 423 424
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, iface);
    IDirect3DVertexBufferImpl *Src = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, SrcBuffer);
    IDirect3DDeviceImpl *D3D = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice3, D3DDevice);

425
    TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%08x,%p,%08x,%p,%08x) thunking to IDirect3DVertexBuffer7 interface.\n", This, VertexOp, DestIndex, Count, Src, SrcIndex, D3D, Flags);
426 427 428 429 430 431 432 433 434

    return IDirect3DVertexBuffer7_ProcessVertices(ICOM_INTERFACE(This, IDirect3DVertexBuffer7),
                                                  VertexOp,
                                                  DestIndex,
                                                  Count,
                                                  ICOM_INTERFACE(Src, IDirect3DVertexBuffer7),
                                                  SrcIndex,
                                                  ICOM_INTERFACE(D3D, IDirect3DDevice7),
                                                  Flags);
435 436
}

437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
/*****************************************************************************
 * IDirect3DVertexBuffer7::GetVertexBufferDesc
 *
 * Returns the description of a vertex buffer
 *
 * Params:
 *  Desc: Address to write the description to
 *
 * Returns
 *  DDERR_INVALIDPARAMS if Desc is NULL
 *  D3D_OK on success
 *
 *****************************************************************************/
static HRESULT WINAPI
IDirect3DVertexBufferImpl_GetVertexBufferDesc(IDirect3DVertexBuffer7 *iface,
                                              D3DVERTEXBUFFERDESC *Desc)
453 454
{
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
455 456 457
    WINED3DVERTEXBUFFER_DESC WDesc;
    HRESULT hr;
    TRACE("(%p)->(%p)\n", This, Desc);
458

459
    if(!Desc) return DDERR_INVALIDPARAMS;
460

461
    EnterCriticalSection(&ddraw_cs);
462 463 464 465
    hr = IWineD3DVertexBuffer_GetDesc(This->wineD3DVertexBuffer,
                                      &WDesc);
    if(hr != D3D_OK)
    {
466
        ERR("(%p) IWineD3DVertexBuffer::GetDesc failed with hr=%08x\n", This, hr);
467
        LeaveCriticalSection(&ddraw_cs);
468
        return hr;
469 470
    }

471 472 473 474
    /* Now fill the Desc structure */
    Desc->dwCaps = This->Caps;
    Desc->dwFVF = WDesc.FVF;
    Desc->dwNumVertices = WDesc.Size / get_flexible_vertex_size(WDesc.FVF);
475
    LeaveCriticalSection(&ddraw_cs);
476

477
    return D3D_OK;
478 479
}

480 481 482
static HRESULT WINAPI
Thunk_IDirect3DVertexBufferImpl_1_GetVertexBufferDesc(IDirect3DVertexBuffer *iface,
                                                      D3DVERTEXBUFFERDESC *Desc)
483
{
484 485
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, iface);
    TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DVertexBuffer7 interface.\n", This, Desc);
486

487 488
    return IDirect3DVertexBuffer7_GetVertexBufferDesc(ICOM_INTERFACE(This, IDirect3DVertexBuffer7),
                                                      Desc);
489 490 491
}


492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
/*****************************************************************************
 * IDirect3DVertexBuffer7::Optimize
 *
 * Converts an unoptimized vertex buffer into an optimized buffer
 *
 * Params:
 *  D3DDevice: Device for which this buffer is optimized
 *  Flags: Not used, should be set to 0
 *
 * Returns
 *  D3D_OK, because it's a stub
 *
 *****************************************************************************/
static HRESULT WINAPI
IDirect3DVertexBufferImpl_Optimize(IDirect3DVertexBuffer7 *iface,
                                   IDirect3DDevice7 *D3DDevice,
                                   DWORD Flags)
{
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
    IDirect3DDeviceImpl *D3D = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice7, D3DDevice);
512
    FIXME("(%p)->(%p,%08x): stub!\n", This, D3D, Flags);
513

514 515 516
    /* We could forward this call to WineD3D and take advantage
     * of it once we use OpenGL vertex buffers
     */
517
    EnterCriticalSection(&ddraw_cs);
518
    This->Caps |= D3DVBCAPS_OPTIMIZED;
519
    LeaveCriticalSection(&ddraw_cs);
520

521 522 523 524 525 526 527
    return DD_OK;
}

static HRESULT WINAPI
Thunk_IDirect3DVertexBufferImpl_1_Optimize(IDirect3DVertexBuffer *iface,
                                           IDirect3DDevice3 *D3DDevice,
                                           DWORD Flags)
528
{
529 530
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, iface);
    IDirect3DDeviceImpl *D3D = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice3, D3DDevice);
531
    TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DVertexBuffer7 interface.\n", This, D3D, Flags);
532

533 534 535 536
    return IDirect3DVertexBuffer7_Optimize(ICOM_INTERFACE(This, IDirect3DVertexBuffer7),
                                           ICOM_INTERFACE(D3D, IDirect3DDevice7),
                                           Flags);
}
537

538 539 540 541 542 543 544 545 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
/*****************************************************************************
 * IDirect3DVertexBuffer7::ProcessVerticesStrided
 *
 * This method processes untransformed strided vertices into a processed
 * or optimized vertex buffer.
 *
 * For more details on the parameters, see
 * IDirect3DVertexBuffer7::ProcessVertices
 *
 * Params:
 *  VertexOp: Operations to perform
 *  DestIndex: Destination index to write the vertices to
 *  Count: Number of input vertices
 *  StrideData: Array containing the input vertices
 *  VertexTypeDesc: Vertex Description or source index?????????
 *  D3DDevice: IDirect3DDevice7 to use for processing
 *  Flags: Can be D3DPV_DONOTCOPYDATA to avoid copying unmodified vertices
 *
 * Returns
 *  D3D_OK on success, or DDERR_*
 *
 *****************************************************************************/
static HRESULT WINAPI
IDirect3DVertexBufferImpl_ProcessVerticesStrided(IDirect3DVertexBuffer7 *iface,
                                                 DWORD VertexOp,
                                                 DWORD DestIndex,
                                                 DWORD Count,
                                                 D3DDRAWPRIMITIVESTRIDEDDATA *StrideData,
                                                 DWORD VertexTypeDesc,
                                                 IDirect3DDevice7 *D3DDevice,
                                                 DWORD Flags)
{
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
    IDirect3DDeviceImpl *D3D = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice7, D3DDevice);
572
    FIXME("(%p)->(%08x,%08x,%08x,%p,%08x,%p,%08x): stub!\n", This, VertexOp, DestIndex, Count, StrideData, VertexTypeDesc, D3D, Flags);
573 574
    return DD_OK;
}
575

576 577 578
/*****************************************************************************
 * The VTables
 *****************************************************************************/
579

580
const IDirect3DVertexBuffer7Vtbl IDirect3DVertexBuffer7_Vtbl =
581
{
582 583 584 585 586 587 588 589 590 591 592 593
    /*** IUnknown Methods ***/
    IDirect3DVertexBufferImpl_QueryInterface,
    IDirect3DVertexBufferImpl_AddRef,
    IDirect3DVertexBufferImpl_Release,
    /*** IDirect3DVertexBuffer Methods ***/
    IDirect3DVertexBufferImpl_Lock,
    IDirect3DVertexBufferImpl_Unlock,
    IDirect3DVertexBufferImpl_ProcessVertices,
    IDirect3DVertexBufferImpl_GetVertexBufferDesc,
    IDirect3DVertexBufferImpl_Optimize,
    /*** IDirect3DVertexBuffer7 Methods ***/
    IDirect3DVertexBufferImpl_ProcessVerticesStrided
594 595
};

596
const IDirect3DVertexBufferVtbl IDirect3DVertexBuffer1_Vtbl =
597
{
598 599 600 601 602 603 604 605 606 607 608
    /*** IUnknown Methods ***/
    Thunk_IDirect3DVertexBufferImpl_1_QueryInterface,
    Thunk_IDirect3DVertexBufferImpl_1_AddRef,
    Thunk_IDirect3DVertexBufferImpl_1_Release,
    /*** IDirect3DVertexBuffer Methods ***/
    Thunk_IDirect3DVertexBufferImpl_1_Lock,
    Thunk_IDirect3DVertexBufferImpl_1_Unlock,
    Thunk_IDirect3DVertexBufferImpl_1_ProcessVertices,
    Thunk_IDirect3DVertexBufferImpl_1_GetVertexBufferDesc,
    Thunk_IDirect3DVertexBufferImpl_1_Optimize
};