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