Use shell icon cache instead of an own IExtractIcon implementation.
[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 < ((dwVertexTypeDesc & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); 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, 2 * 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 < ((dwVertexTypeDesc & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
402                 D3DVALUE *tex_coord =
403                   (D3DVALUE *) (((char *) lpStrideData->textureCoords[tex_index].lpvData) + 
404                                 i * lpStrideData->textureCoords[tex_index].dwStride);
405                 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
406             }
407             TRACE_(ddraw_geom)("\n");
408         }
409     }
410
411     return DD_OK;
412 }
413
414 #undef copy_and_next
415
416 HRESULT WINAPI
417 GL_IDirect3DVertexBufferImpl_7_1T_ProcessVertices(LPDIRECT3DVERTEXBUFFER7 iface,
418                                                   DWORD dwVertexOp,
419                                                   DWORD dwDestIndex,
420                                                   DWORD dwCount,
421                                                   LPDIRECT3DVERTEXBUFFER7 lpSrcBuffer,
422                                                   DWORD dwSrcIndex,
423                                                   LPDIRECT3DDEVICE7 lpD3DDevice,
424                                                   DWORD dwFlags)
425 {
426     ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
427     IDirect3DVertexBufferImpl *src_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpSrcBuffer);
428     IDirect3DDeviceImpl *device_impl = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice7, lpD3DDevice);
429     D3DDRAWPRIMITIVESTRIDEDDATA strided;
430     DWORD size;
431
432     TRACE("(%p/%p)->(%08lx,%08lx,%08lx,%p,%08lx,%p,%08lx)\n", This, iface, dwVertexOp, dwDestIndex, dwCount, lpSrcBuffer, dwSrcIndex, lpD3DDevice, dwFlags);    
433
434     if (TRACE_ON(ddraw)) {
435         TRACE(" - vertex operations : "); dump_D3DVOP(dwVertexOp);
436         TRACE(" - flags             : "); dump_D3DPV(dwFlags);
437     }
438
439     if ((dwVertexOp & D3DVOP_TRANSFORM) == 0) return DDERR_INVALIDPARAMS;
440
441     size = get_flexible_vertex_size(src_impl->desc.dwFVF);
442     convert_FVF_to_strided_data(src_impl->desc.dwFVF, ((char *) src_impl->vertices) + dwSrcIndex * size, &strided, 0);
443
444     return process_vertices_strided(This, dwVertexOp, dwDestIndex, dwCount, &strided, src_impl->desc.dwFVF, device_impl, dwFlags);
445 }
446
447 HRESULT WINAPI
448 GL_IDirect3DVertexBufferImpl_7_ProcessVerticesStrided(LPDIRECT3DVERTEXBUFFER7 iface,
449                                                       DWORD dwVertexOp,
450                                                       DWORD dwDestIndex,
451                                                       DWORD dwCount,
452                                                       LPD3DDRAWPRIMITIVESTRIDEDDATA lpStrideData,
453                                                       DWORD dwVertexTypeDesc,
454                                                       LPDIRECT3DDEVICE7 lpD3DDevice,
455                                                       DWORD dwFlags)
456 {
457     ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
458     IDirect3DDeviceImpl *device_impl = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice7, lpD3DDevice);
459
460     TRACE("(%p/%p)->(%08lx,%08lx,%08lx,%p,%08lx,%p,%08lx)\n", This, iface, dwVertexOp, dwDestIndex, dwCount, lpStrideData, dwVertexTypeDesc, lpD3DDevice, dwFlags);
461     if (TRACE_ON(ddraw)) {
462         TRACE(" - vertex operations : "); dump_D3DVOP(dwVertexOp);
463         TRACE(" - flags             : "); dump_D3DPV(dwFlags);
464         TRACE(" - vertex format     : "); dump_flexible_vertex(dwVertexTypeDesc);
465     }
466
467     if ((dwVertexOp & D3DVOP_TRANSFORM) == 0) return DDERR_INVALIDPARAMS;
468
469     return process_vertices_strided(This, dwVertexOp, dwDestIndex, dwCount, lpStrideData, dwVertexTypeDesc, device_impl, dwFlags);
470 }
471
472
473
474 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
475 # define XCAST(fun)     (typeof(VTABLE_IDirect3DVertexBuffer7.fun))
476 #else
477 # define XCAST(fun)     (void*)
478 #endif
479
480 static const IDirect3DVertexBuffer7Vtbl VTABLE_IDirect3DVertexBuffer7 =
481 {
482     XCAST(QueryInterface) Main_IDirect3DVertexBufferImpl_7_1T_QueryInterface,
483     XCAST(AddRef) Main_IDirect3DVertexBufferImpl_7_1T_AddRef,
484     XCAST(Release) Main_IDirect3DVertexBufferImpl_7_1T_Release,
485     XCAST(Lock) Main_IDirect3DVertexBufferImpl_7_1T_Lock,
486     XCAST(Unlock) Main_IDirect3DVertexBufferImpl_7_1T_Unlock,
487     XCAST(ProcessVertices) GL_IDirect3DVertexBufferImpl_7_1T_ProcessVertices,
488     XCAST(GetVertexBufferDesc) Main_IDirect3DVertexBufferImpl_7_1T_GetVertexBufferDesc,
489     XCAST(Optimize) Main_IDirect3DVertexBufferImpl_7_1T_Optimize,
490     XCAST(ProcessVerticesStrided) GL_IDirect3DVertexBufferImpl_7_ProcessVerticesStrided
491 };
492
493 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
494 #undef XCAST
495 #endif
496
497
498 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
499 # define XCAST(fun)     (typeof(VTABLE_IDirect3DVertexBuffer.fun))
500 #else
501 # define XCAST(fun)     (void*)
502 #endif
503
504 static const IDirect3DVertexBufferVtbl VTABLE_IDirect3DVertexBuffer =
505 {
506     XCAST(QueryInterface) Thunk_IDirect3DVertexBufferImpl_1_QueryInterface,
507     XCAST(AddRef) Thunk_IDirect3DVertexBufferImpl_1_AddRef,
508     XCAST(Release) Thunk_IDirect3DVertexBufferImpl_1_Release,
509     XCAST(Lock) Thunk_IDirect3DVertexBufferImpl_1_Lock,
510     XCAST(Unlock) Thunk_IDirect3DVertexBufferImpl_1_Unlock,
511     XCAST(ProcessVertices) Thunk_IDirect3DVertexBufferImpl_1_ProcessVertices,
512     XCAST(GetVertexBufferDesc) Thunk_IDirect3DVertexBufferImpl_1_GetVertexBufferDesc,
513     XCAST(Optimize) Thunk_IDirect3DVertexBufferImpl_1_Optimize
514 };
515
516 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
517 #undef XCAST
518 #endif
519
520 HRESULT d3dvertexbuffer_create(IDirect3DVertexBufferImpl **obj, IDirectDrawImpl *d3d, LPD3DVERTEXBUFFERDESC lpD3DVertBufDesc, DWORD dwFlags)
521 {
522     IDirect3DVertexBufferImpl *object;
523     static const flag_info flags[] = {
524         FE(D3DVBCAPS_DONOTCLIP),
525         FE(D3DVBCAPS_OPTIMIZED),
526         FE(D3DVBCAPS_SYSTEMMEMORY),
527         FE(D3DVBCAPS_WRITEONLY)
528     };
529
530     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBufferGLImpl));
531     if (object == NULL) return DDERR_OUTOFMEMORY;
532
533     object->ref = 1;
534     object->d3d = d3d;
535     object->desc = *lpD3DVertBufDesc;
536     object->vertex_buffer_size = get_flexible_vertex_size(lpD3DVertBufDesc->dwFVF) * lpD3DVertBufDesc->dwNumVertices;
537     object->vertices = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->vertex_buffer_size);
538     
539     ICOM_INIT_INTERFACE(object, IDirect3DVertexBuffer,  VTABLE_IDirect3DVertexBuffer);
540     ICOM_INIT_INTERFACE(object, IDirect3DVertexBuffer7, VTABLE_IDirect3DVertexBuffer7);
541
542     *obj = object;
543
544     if (TRACE_ON(ddraw)) {
545         TRACE(" creating implementation at %p with description : \n", *obj);
546         TRACE("  flags        : "); DDRAW_dump_flags_(lpD3DVertBufDesc->dwCaps, flags, sizeof(flags)/sizeof(flags[0]), TRUE);
547         TRACE("  vertex type  : "); dump_flexible_vertex(lpD3DVertBufDesc->dwFVF);
548         TRACE("  num vertices : %ld\n", lpD3DVertBufDesc->dwNumVertices);
549     }
550     
551     
552     return D3D_OK;
553 }