Fix signed/unsigned comparison warnings.
[wine] / dlls / ddraw / d3dvertexbuffer.c
1 /* Direct3D Viewport
2  * Copyright (c) 2002 Lionel ULMER
3  *
4  * This file contains the implementation of Direct3DVertexBuffer COM object
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "objbase.h"
28 #include "wingdi.h"
29 #include "ddraw.h"
30 #include "d3d.h"
31 #include "wine/debug.h"
32
33 #include "d3d_private.h"
34 #include "mesa_private.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom);
38
39 HRESULT WINAPI
40 Main_IDirect3DVertexBufferImpl_7_1T_QueryInterface(LPDIRECT3DVERTEXBUFFER7 iface,
41                                                    REFIID riid,
42                                                    LPVOID* obp)
43 {
44     ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
45     TRACE("(%p/%p)->(%s,%p)\n", This, iface, debugstr_guid(riid), obp);
46
47     /* By default, set the object pointer to NULL */
48     *obp = NULL;
49       
50     if ( IsEqualGUID( &IID_IUnknown,  riid ) ) {
51         IDirect3DVertexBuffer7_AddRef(ICOM_INTERFACE(This,IDirect3DVertexBuffer7));
52         *obp = iface;
53         TRACE("  Creating IUnknown interface at %p.\n", *obp);
54         return S_OK;
55     }
56     if ( IsEqualGUID( &IID_IDirect3DVertexBuffer, riid ) ) {
57         IDirect3DVertexBuffer7_AddRef(ICOM_INTERFACE(This,IDirect3DVertexBuffer7));
58         *obp = ICOM_INTERFACE(This, IDirect3DVertexBuffer);
59         TRACE("  Creating IDirect3DVertexBuffer interface %p\n", *obp);
60         return S_OK;
61     }
62     if ( IsEqualGUID( &IID_IDirect3DVertexBuffer7, riid ) ) {
63         IDirect3DVertexBuffer7_AddRef(ICOM_INTERFACE(This,IDirect3DVertexBuffer7));
64         *obp = ICOM_INTERFACE(This, IDirect3DVertexBuffer7);
65         TRACE("  Creating IDirect3DVertexBuffer7 interface %p\n", *obp);
66         return S_OK;
67     }
68     FIXME("(%p): interface for IID %s NOT found!\n", This, debugstr_guid(riid));
69     return OLE_E_ENUM_NOMORE;
70 }
71
72 ULONG WINAPI
73 Main_IDirect3DVertexBufferImpl_7_1T_AddRef(LPDIRECT3DVERTEXBUFFER7 iface)
74 {
75     ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
76     TRACE("(%p/%p)->() incrementing from %lu.\n", This, iface, This->ref);
77     return ++(This->ref);
78 }
79
80 ULONG WINAPI
81 Main_IDirect3DVertexBufferImpl_7_1T_Release(LPDIRECT3DVERTEXBUFFER7 iface)
82 {
83     ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
84     TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
85     if (--(This->ref) == 0) {
86         HeapFree(GetProcessHeap(), 0, This->vertices);
87         HeapFree(GetProcessHeap(), 0, This);
88         return 0;
89     }
90     return This->ref;
91 }
92
93 HRESULT WINAPI
94 Main_IDirect3DVertexBufferImpl_7_1T_Lock(LPDIRECT3DVERTEXBUFFER7 iface,
95                                          DWORD dwFlags,
96                                          LPVOID* lplpData,
97                                          LPDWORD lpdwSize)
98 {
99     ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
100     TRACE("(%p/%p)->(%08lx,%p,%p)\n", This, iface, dwFlags, lplpData, lpdwSize);
101
102     if (TRACE_ON(ddraw)) {
103         TRACE(" lock flags : ");
104         DDRAW_dump_lockflag(dwFlags);
105     }
106     
107     if (This->processed == TRUE) {
108         WARN(" application does a Lock on a vertex buffer resulting from a ProcessVertices call. Expect problems !\n");
109     }
110
111     if (This->desc.dwCaps & D3DVBCAPS_OPTIMIZED) return D3DERR_VERTEXBUFFEROPTIMIZED;
112
113     if (lpdwSize != NULL) *lpdwSize = This->vertex_buffer_size;
114     *lplpData = This->vertices;
115     
116     return DD_OK;
117 }
118
119 HRESULT WINAPI
120 Main_IDirect3DVertexBufferImpl_7_1T_Unlock(LPDIRECT3DVERTEXBUFFER7 iface)
121 {
122     ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
123     TRACE("(%p/%p)->()\n", This, iface);
124     /* Nothing to do here for now. Maybe some optimizations if ever we want to do some :-) */
125     return DD_OK;
126 }
127
128 HRESULT WINAPI
129 Main_IDirect3DVertexBufferImpl_7_1T_ProcessVertices(LPDIRECT3DVERTEXBUFFER7 iface,
130                                                     DWORD dwVertexOp,
131                                                     DWORD dwDestIndex,
132                                                     DWORD dwCount,
133                                                     LPDIRECT3DVERTEXBUFFER7 lpSrcBuffer,
134                                                     DWORD dwSrcIndex,
135                                                     LPDIRECT3DDEVICE7 lpD3DDevice,
136                                                     DWORD dwFlags)
137 {
138     ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
139     FIXME("(%p/%p)->(%08lx,%08lx,%08lx,%p,%08lx,%p,%08lx): stub!\n", This, iface, dwVertexOp, dwDestIndex, dwCount, lpSrcBuffer, dwSrcIndex, lpD3DDevice, dwFlags);    
140     return DD_OK;
141 }
142
143 HRESULT WINAPI
144 Main_IDirect3DVertexBufferImpl_7_1T_GetVertexBufferDesc(LPDIRECT3DVERTEXBUFFER7 iface,
145                                                         LPD3DVERTEXBUFFERDESC lpD3DVertexBufferDesc)
146 {
147     DWORD size;
148     ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
149     
150     TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DVertexBufferDesc);
151     
152     size = lpD3DVertexBufferDesc->dwSize;
153     memset(lpD3DVertexBufferDesc, 0, size);
154     memcpy(lpD3DVertexBufferDesc, &This->desc, 
155            (size < This->desc.dwSize) ? size : This->desc.dwSize);
156     
157     return DD_OK;
158 }
159
160 HRESULT WINAPI
161 Main_IDirect3DVertexBufferImpl_7_1T_Optimize(LPDIRECT3DVERTEXBUFFER7 iface,
162                                              LPDIRECT3DDEVICE7 lpD3DDevice,
163                                              DWORD dwFlags)
164 {
165     ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
166     FIXME("(%p/%p)->(%p,%08lx): stub!\n", This, iface, lpD3DDevice, dwFlags);
167
168     This->desc.dwCaps |= D3DVBCAPS_OPTIMIZED;
169
170     return DD_OK;
171 }
172
173 HRESULT WINAPI
174 Main_IDirect3DVertexBufferImpl_7_ProcessVerticesStrided(LPDIRECT3DVERTEXBUFFER7 iface,
175                                                         DWORD dwVertexOp,
176                                                         DWORD dwDestIndex,
177                                                         DWORD dwCount,
178                                                         LPD3DDRAWPRIMITIVESTRIDEDDATA lpStrideData,
179                                                         DWORD dwVertexTypeDesc,
180                                                         LPDIRECT3DDEVICE7 lpD3DDevice,
181                                                         DWORD dwFlags)
182 {
183     ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
184     FIXME("(%p/%p)->(%08lx,%08lx,%08lx,%p,%08lx,%p,%08lx): stub!\n", This, iface, dwVertexOp, dwDestIndex, dwCount, lpStrideData, dwVertexTypeDesc, lpD3DDevice, dwFlags);
185     return DD_OK;
186 }
187
188 HRESULT WINAPI
189 Thunk_IDirect3DVertexBufferImpl_1_ProcessVertices(LPDIRECT3DVERTEXBUFFER iface,
190                                                   DWORD dwVertexOp,
191                                                   DWORD dwDestIndex,
192                                                   DWORD dwCount,
193                                                   LPDIRECT3DVERTEXBUFFER lpSrcBuffer,
194                                                   DWORD dwSrcIndex,
195                                                   LPDIRECT3DDEVICE3 lpD3DDevice,
196                                                   DWORD dwFlags)
197 {
198     TRACE("(%p)->(%08lx,%08lx,%08lx,%p,%08lx,%p,%08lx) thunking to IDirect3DVertexBuffer7 interface.\n", iface,
199           dwVertexOp, dwDestIndex, dwCount, lpSrcBuffer, dwSrcIndex, lpD3DDevice, dwFlags);
200     return IDirect3DVertexBuffer7_ProcessVertices(COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, IDirect3DVertexBuffer7, iface),
201                                                   dwVertexOp,
202                                                   dwDestIndex,
203                                                   dwCount,
204                                                   COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, IDirect3DVertexBuffer7, lpSrcBuffer),
205                                                   dwSrcIndex,
206                                                   COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice3, IDirect3DDevice7, lpD3DDevice),
207                                                   dwFlags);
208 }
209
210 HRESULT WINAPI
211 Thunk_IDirect3DVertexBufferImpl_1_Optimize(LPDIRECT3DVERTEXBUFFER iface,
212                                            LPDIRECT3DDEVICE3 lpD3DDevice,
213                                            DWORD dwFlags)
214 {
215     TRACE("(%p)->(%p,%08lx) thunking to IDirect3DVertexBuffer7 interface.\n", iface, lpD3DDevice, dwFlags);
216     return IDirect3DVertexBuffer7_Optimize(COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, IDirect3DVertexBuffer7, iface),
217                                            COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice3, IDirect3DDevice7, lpD3DDevice),
218                                            dwFlags);
219 }
220
221 HRESULT WINAPI
222 Thunk_IDirect3DVertexBufferImpl_1_QueryInterface(LPDIRECT3DVERTEXBUFFER iface,
223                                                  REFIID riid,
224                                                  LPVOID* obp)
225 {
226     TRACE("(%p)->(%s,%p) thunking to IDirect3DVertexBuffer7 interface.\n", iface, debugstr_guid(riid), obp);
227     return IDirect3DVertexBuffer7_QueryInterface(COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, IDirect3DVertexBuffer7, iface),
228                                                  riid,
229                                                  obp);
230 }
231
232 ULONG WINAPI
233 Thunk_IDirect3DVertexBufferImpl_1_AddRef(LPDIRECT3DVERTEXBUFFER iface)
234 {
235     TRACE("(%p)->() thunking to IDirect3DVertexBuffer7 interface.\n", iface);
236     return IDirect3DVertexBuffer7_AddRef(COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, IDirect3DVertexBuffer7, iface));
237 }
238
239 ULONG WINAPI
240 Thunk_IDirect3DVertexBufferImpl_1_Release(LPDIRECT3DVERTEXBUFFER iface)
241 {
242     TRACE("(%p)->() thunking to IDirect3DVertexBuffer7 interface.\n", iface);
243     return IDirect3DVertexBuffer7_Release(COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, IDirect3DVertexBuffer7, iface));
244 }
245
246 HRESULT WINAPI
247 Thunk_IDirect3DVertexBufferImpl_1_Lock(LPDIRECT3DVERTEXBUFFER iface,
248                                        DWORD dwFlags,
249                                        LPVOID* lplpData,
250                                        LPDWORD lpdwSize)
251 {
252     TRACE("(%p)->(%08lx,%p,%p) thunking to IDirect3DVertexBuffer7 interface.\n", iface, dwFlags, lplpData, lpdwSize);
253     return IDirect3DVertexBuffer7_Lock(COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, IDirect3DVertexBuffer7, iface),
254                                        dwFlags,
255                                        lplpData,
256                                        lpdwSize);
257 }
258
259 HRESULT WINAPI
260 Thunk_IDirect3DVertexBufferImpl_1_Unlock(LPDIRECT3DVERTEXBUFFER iface)
261 {
262     TRACE("(%p)->() thunking to IDirect3DVertexBuffer7 interface.\n", iface);
263     return IDirect3DVertexBuffer7_Unlock(COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, IDirect3DVertexBuffer7, iface));
264 }
265
266 HRESULT WINAPI
267 Thunk_IDirect3DVertexBufferImpl_1_GetVertexBufferDesc(LPDIRECT3DVERTEXBUFFER iface,
268                                                       LPD3DVERTEXBUFFERDESC lpD3DVertexBufferDesc)
269 {
270     TRACE("(%p)->(%p) thunking to IDirect3DVertexBuffer7 interface.\n", iface, lpD3DVertexBufferDesc);
271     return IDirect3DVertexBuffer7_GetVertexBufferDesc(COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, IDirect3DVertexBuffer7, iface),
272                                                       lpD3DVertexBufferDesc);
273 }
274
275 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
276
277 static HRESULT
278 process_vertices_strided(IDirect3DVertexBufferImpl *This,
279                          DWORD dwVertexOp,
280                          DWORD dwDestIndex,
281                          DWORD dwCount,
282                          LPD3DDRAWPRIMITIVESTRIDEDDATA lpStrideData,
283                          DWORD dwVertexTypeDesc,
284                          IDirect3DDeviceImpl *device_impl,
285                          DWORD dwFlags)
286 {
287     IDirect3DVertexBufferGLImpl *glThis = (IDirect3DVertexBufferGLImpl *) This;
288     DWORD size = get_flexible_vertex_size(dwVertexTypeDesc);
289     char *dest_ptr;
290     unsigned int i;
291
292     This->processed = TRUE;
293
294     /* For the moment, the trick is to save the transform and lighting state at process
295        time to restore them at drawing time.
296        
297        The BIG problem with this method is nothing prevents D3D to do dirty tricks like
298        processing two different sets of vertices with two different rendering parameters
299        and then to display them using the same DrawPrimitive call.
300
301        It would be nice to check for such code here (but well, even this is not trivial
302        to do).
303
304        This is exactly what the TWIST.EXE demo does but using the same kind of ugly stuff
305        in the D3DExecuteBuffer code. I really wonder why Microsoft went back in time when
306        implementing this mostly useless (IMHO) API.
307     */
308     glThis->dwVertexTypeDesc = dwVertexTypeDesc;
309
310     if (dwVertexTypeDesc & D3DFVF_NORMAL) {
311         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
312     }
313
314     if (glThis->vertices == NULL) {
315         glThis->vertices = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size * This->desc.dwNumVertices);
316     }
317     dest_ptr = ((char *) glThis->vertices) + dwDestIndex * size;
318     
319     memcpy(&(glThis->world_mat), device_impl->world_mat, sizeof(D3DMATRIX));
320     memcpy(&(glThis->view_mat), device_impl->view_mat, sizeof(D3DMATRIX));
321     memcpy(&(glThis->proj_mat), device_impl->proj_mat, sizeof(D3DMATRIX));
322
323     for (i = 0; i < dwCount; i++) {
324         unsigned int tex_index;
325
326         if ((dwVertexTypeDesc & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
327             D3DVALUE *position =
328               (D3DVALUE *) (((char *) lpStrideData->position.lpvData) + i * lpStrideData->position.dwStride);
329             copy_and_next(dest_ptr, position, 3 * sizeof(D3DVALUE));
330         } else if ((dwVertexTypeDesc & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
331             D3DVALUE *position =
332               (D3DVALUE *) (((char *) lpStrideData->position.lpvData) + i * lpStrideData->position.dwStride);
333             copy_and_next(dest_ptr, position, 4 * sizeof(D3DVALUE));
334         }
335         if (dwVertexTypeDesc & D3DFVF_RESERVED1) {
336             dest_ptr += sizeof(DWORD);
337         }
338         if (dwVertexTypeDesc & D3DFVF_NORMAL) { 
339             D3DVALUE *normal = 
340               (D3DVALUE *) (((char *) lpStrideData->normal.lpvData) + i * lpStrideData->normal.dwStride);           
341             copy_and_next(dest_ptr, normal, 3 * sizeof(D3DVALUE));
342         }
343         if (dwVertexTypeDesc & D3DFVF_DIFFUSE) {
344             DWORD *color_d = 
345               (DWORD *) (((char *) lpStrideData->diffuse.lpvData) + i * lpStrideData->diffuse.dwStride);
346             copy_and_next(dest_ptr, color_d, sizeof(DWORD));
347         }
348         if (dwVertexTypeDesc & D3DFVF_SPECULAR) { 
349             DWORD *color_s = 
350               (DWORD *) (((char *) lpStrideData->specular.lpvData) + i * lpStrideData->specular.dwStride);
351             copy_and_next(dest_ptr, color_s, sizeof(DWORD));
352         }
353         for (tex_index = 0; tex_index < ((dwVertexTypeDesc & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
354             D3DVALUE *tex_coord =
355               (D3DVALUE *) (((char *) lpStrideData->textureCoords[tex_index].lpvData) + 
356                             i * lpStrideData->textureCoords[tex_index].dwStride);
357             copy_and_next(dest_ptr, tex_coord, 2 * sizeof(D3DVALUE));
358         }
359
360         if (TRACE_ON(ddraw_geom)) {
361             if ((dwVertexTypeDesc & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
362                 D3DVALUE *position =
363                   (D3DVALUE *) (((char *) lpStrideData->position.lpvData) + i * lpStrideData->position.dwStride);
364                 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
365             } else if ((dwVertexTypeDesc & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
366                 D3DVALUE *position =
367                   (D3DVALUE *) (((char *) lpStrideData->position.lpvData) + i * lpStrideData->position.dwStride);
368                 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
369             }
370             if (dwVertexTypeDesc & D3DFVF_NORMAL) { 
371                 D3DVALUE *normal = 
372                   (D3DVALUE *) (((char *) lpStrideData->normal.lpvData) + i * lpStrideData->normal.dwStride);       
373                 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
374             }
375             if (dwVertexTypeDesc & D3DFVF_DIFFUSE) {
376                 DWORD *color_d = 
377                   (DWORD *) (((char *) lpStrideData->diffuse.lpvData) + i * lpStrideData->diffuse.dwStride);
378                 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
379                                    (*color_d >> 16) & 0xFF,
380                                    (*color_d >>  8) & 0xFF,
381                                    (*color_d >>  0) & 0xFF,
382                                    (*color_d >> 24) & 0xFF);
383             }
384             if (dwVertexTypeDesc & D3DFVF_SPECULAR) { 
385                 DWORD *color_s = 
386                   (DWORD *) (((char *) lpStrideData->specular.lpvData) + i * lpStrideData->specular.dwStride);
387                 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
388                                    (*color_s >> 16) & 0xFF,
389                                    (*color_s >>  8) & 0xFF,
390                                    (*color_s >>  0) & 0xFF,
391                                    (*color_s >> 24) & 0xFF);
392             }
393             for (tex_index = 0; tex_index < ((dwVertexTypeDesc & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
394                 D3DVALUE *tex_coord =
395                   (D3DVALUE *) (((char *) lpStrideData->textureCoords[tex_index].lpvData) + 
396                                 i * lpStrideData->textureCoords[tex_index].dwStride);
397                 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
398             }
399             TRACE_(ddraw_geom)("\n");
400         }
401     }
402
403     return DD_OK;
404 }
405
406 #undef copy_and_next
407
408 HRESULT WINAPI
409 GL_IDirect3DVertexBufferImpl_7_1T_ProcessVertices(LPDIRECT3DVERTEXBUFFER7 iface,
410                                                   DWORD dwVertexOp,
411                                                   DWORD dwDestIndex,
412                                                   DWORD dwCount,
413                                                   LPDIRECT3DVERTEXBUFFER7 lpSrcBuffer,
414                                                   DWORD dwSrcIndex,
415                                                   LPDIRECT3DDEVICE7 lpD3DDevice,
416                                                   DWORD dwFlags)
417 {
418     ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
419     IDirect3DVertexBufferImpl *src_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpSrcBuffer);
420     IDirect3DDeviceImpl *device_impl = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice7, lpD3DDevice);
421     D3DDRAWPRIMITIVESTRIDEDDATA strided;
422     DWORD size;
423
424     TRACE("(%p/%p)->(%08lx,%08lx,%08lx,%p,%08lx,%p,%08lx)\n", This, iface, dwVertexOp, dwDestIndex, dwCount, lpSrcBuffer, dwSrcIndex, lpD3DDevice, dwFlags);    
425
426     if (TRACE_ON(ddraw)) {
427         TRACE(" - vertex operations : "); dump_D3DVOP(dwVertexOp);
428         TRACE(" - flags             : "); dump_D3DPV(dwFlags);
429     }
430
431     if ((dwVertexOp & D3DVOP_TRANSFORM) == 0) return DDERR_INVALIDPARAMS;
432
433     size = get_flexible_vertex_size(src_impl->desc.dwFVF);
434     convert_FVF_to_strided_data(src_impl->desc.dwFVF, ((char *) src_impl->vertices) + dwSrcIndex * size, &strided, 0);
435
436     return process_vertices_strided(This, dwVertexOp, dwDestIndex, dwCount, &strided, src_impl->desc.dwFVF, device_impl, dwFlags);
437 }
438
439 HRESULT WINAPI
440 GL_IDirect3DVertexBufferImpl_7_ProcessVerticesStrided(LPDIRECT3DVERTEXBUFFER7 iface,
441                                                       DWORD dwVertexOp,
442                                                       DWORD dwDestIndex,
443                                                       DWORD dwCount,
444                                                       LPD3DDRAWPRIMITIVESTRIDEDDATA lpStrideData,
445                                                       DWORD dwVertexTypeDesc,
446                                                       LPDIRECT3DDEVICE7 lpD3DDevice,
447                                                       DWORD dwFlags)
448 {
449     ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
450     IDirect3DDeviceImpl *device_impl = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice7, lpD3DDevice);
451
452     TRACE("(%p/%p)->(%08lx,%08lx,%08lx,%p,%08lx,%p,%08lx)\n", This, iface, dwVertexOp, dwDestIndex, dwCount, lpStrideData, dwVertexTypeDesc, lpD3DDevice, dwFlags);
453     if (TRACE_ON(ddraw)) {
454         TRACE(" - vertex operations : "); dump_D3DVOP(dwVertexOp);
455         TRACE(" - flags             : "); dump_D3DPV(dwFlags);
456         TRACE(" - vertex format     : "); dump_flexible_vertex(dwVertexTypeDesc);
457     }
458
459     if ((dwVertexOp & D3DVOP_TRANSFORM) == 0) return DDERR_INVALIDPARAMS;
460
461     return process_vertices_strided(This, dwVertexOp, dwDestIndex, dwCount, lpStrideData, dwVertexTypeDesc, device_impl, dwFlags);
462 }
463
464
465
466 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
467 # define XCAST(fun)     (typeof(VTABLE_IDirect3DVertexBuffer7.fun))
468 #else
469 # define XCAST(fun)     (void*)
470 #endif
471
472 IDirect3DVertexBuffer7Vtbl VTABLE_IDirect3DVertexBuffer7 =
473 {
474     XCAST(QueryInterface) Main_IDirect3DVertexBufferImpl_7_1T_QueryInterface,
475     XCAST(AddRef) Main_IDirect3DVertexBufferImpl_7_1T_AddRef,
476     XCAST(Release) Main_IDirect3DVertexBufferImpl_7_1T_Release,
477     XCAST(Lock) Main_IDirect3DVertexBufferImpl_7_1T_Lock,
478     XCAST(Unlock) Main_IDirect3DVertexBufferImpl_7_1T_Unlock,
479     XCAST(ProcessVertices) GL_IDirect3DVertexBufferImpl_7_1T_ProcessVertices,
480     XCAST(GetVertexBufferDesc) Main_IDirect3DVertexBufferImpl_7_1T_GetVertexBufferDesc,
481     XCAST(Optimize) Main_IDirect3DVertexBufferImpl_7_1T_Optimize,
482     XCAST(ProcessVerticesStrided) GL_IDirect3DVertexBufferImpl_7_ProcessVerticesStrided
483 };
484
485 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
486 #undef XCAST
487 #endif
488
489
490 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
491 # define XCAST(fun)     (typeof(VTABLE_IDirect3DVertexBuffer.fun))
492 #else
493 # define XCAST(fun)     (void*)
494 #endif
495
496 IDirect3DVertexBufferVtbl VTABLE_IDirect3DVertexBuffer =
497 {
498     XCAST(QueryInterface) Thunk_IDirect3DVertexBufferImpl_1_QueryInterface,
499     XCAST(AddRef) Thunk_IDirect3DVertexBufferImpl_1_AddRef,
500     XCAST(Release) Thunk_IDirect3DVertexBufferImpl_1_Release,
501     XCAST(Lock) Thunk_IDirect3DVertexBufferImpl_1_Lock,
502     XCAST(Unlock) Thunk_IDirect3DVertexBufferImpl_1_Unlock,
503     XCAST(ProcessVertices) Thunk_IDirect3DVertexBufferImpl_1_ProcessVertices,
504     XCAST(GetVertexBufferDesc) Thunk_IDirect3DVertexBufferImpl_1_GetVertexBufferDesc,
505     XCAST(Optimize) Thunk_IDirect3DVertexBufferImpl_1_Optimize
506 };
507
508 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
509 #undef XCAST
510 #endif
511
512 HRESULT d3dvertexbuffer_create(IDirect3DVertexBufferImpl **obj, IDirectDrawImpl *d3d, LPD3DVERTEXBUFFERDESC lpD3DVertBufDesc, DWORD dwFlags)
513 {
514     IDirect3DVertexBufferImpl *object;
515     static const flag_info flags[] = {
516         FE(D3DVBCAPS_DONOTCLIP),
517         FE(D3DVBCAPS_OPTIMIZED),
518         FE(D3DVBCAPS_SYSTEMMEMORY),
519         FE(D3DVBCAPS_WRITEONLY)
520     };
521
522     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBufferGLImpl));
523     if (object == NULL) return DDERR_OUTOFMEMORY;
524
525     object->ref = 1;
526     object->d3d = d3d;
527     object->desc = *lpD3DVertBufDesc;
528     object->vertex_buffer_size = get_flexible_vertex_size(lpD3DVertBufDesc->dwFVF) * lpD3DVertBufDesc->dwNumVertices;
529     object->vertices = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->vertex_buffer_size);
530     
531     ICOM_INIT_INTERFACE(object, IDirect3DVertexBuffer,  VTABLE_IDirect3DVertexBuffer);
532     ICOM_INIT_INTERFACE(object, IDirect3DVertexBuffer7, VTABLE_IDirect3DVertexBuffer7);
533
534     *obj = object;
535
536     if (TRACE_ON(ddraw)) {
537         TRACE(" creating implementation at %p with description : \n", *obj);
538         TRACE("  flags        : "); DDRAW_dump_flags_(lpD3DVertBufDesc->dwCaps, flags, sizeof(flags)/sizeof(flags[0]), TRUE);
539         TRACE("  vertex type  : "); dump_flexible_vertex(lpD3DVertBufDesc->dwFVF);
540         TRACE("  num vertices : %ld\n", lpD3DVertBufDesc->dwNumVertices);
541     }
542     
543     
544     return D3D_OK;
545 }