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