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