| /* Direct3D Viewport | |
| * Copyright (c) 2002 Lionel ULMER | |
| * | |
| * This file contains the implementation of Direct3DVertexBuffer COM object | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| */ | |
| #include "config.h" | |
| #include <stdarg.h> | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include "winerror.h" | |
| #include "objbase.h" | |
| #include "wingdi.h" | |
| #include "ddraw.h" | |
| #include "d3d.h" | |
| #include "wine/debug.h" | |
| #include "d3d_private.h" | |
| #include "mesa_private.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(ddraw); | |
| WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom); | |
| HRESULT WINAPI | |
| Main_IDirect3DVertexBufferImpl_7_1T_QueryInterface(LPDIRECT3DVERTEXBUFFER7 iface, | |
| REFIID riid, | |
| LPVOID* obp) | |
| { | |
| ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface); | |
| TRACE("(%p/%p)->(%s,%p)\n", This, iface, debugstr_guid(riid), obp); | |
| /* By default, set the object pointer to NULL */ | |
| *obp = NULL; | |
| if ( IsEqualGUID( &IID_IUnknown, riid ) ) { | |
| IDirect3DVertexBuffer7_AddRef(ICOM_INTERFACE(This,IDirect3DVertexBuffer7)); | |
| *obp = iface; | |
| TRACE(" Creating IUnknown interface at %p.\n", *obp); | |
| return S_OK; | |
| } | |
| if ( IsEqualGUID( &IID_IDirect3DVertexBuffer, riid ) ) { | |
| IDirect3DVertexBuffer7_AddRef(ICOM_INTERFACE(This,IDirect3DVertexBuffer7)); | |
| *obp = ICOM_INTERFACE(This, IDirect3DVertexBuffer); | |
| TRACE(" Creating IDirect3DVertexBuffer interface %p\n", *obp); | |
| return S_OK; | |
| } | |
| if ( IsEqualGUID( &IID_IDirect3DVertexBuffer7, riid ) ) { | |
| IDirect3DVertexBuffer7_AddRef(ICOM_INTERFACE(This,IDirect3DVertexBuffer7)); | |
| *obp = ICOM_INTERFACE(This, IDirect3DVertexBuffer7); | |
| TRACE(" Creating IDirect3DVertexBuffer7 interface %p\n", *obp); | |
| return S_OK; | |
| } | |
| FIXME("(%p): interface for IID %s NOT found!\n", This, debugstr_guid(riid)); | |
| return OLE_E_ENUM_NOMORE; | |
| } | |
| ULONG WINAPI | |
| Main_IDirect3DVertexBufferImpl_7_1T_AddRef(LPDIRECT3DVERTEXBUFFER7 iface) | |
| { | |
| ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface); | |
| TRACE("(%p/%p)->() incrementing from %lu.\n", This, iface, This->ref); | |
| return ++(This->ref); | |
| } | |
| ULONG WINAPI | |
| Main_IDirect3DVertexBufferImpl_7_1T_Release(LPDIRECT3DVERTEXBUFFER7 iface) | |
| { | |
| ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface); | |
| TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref); | |
| if (--(This->ref) == 0) { | |
| HeapFree(GetProcessHeap(), 0, This->vertices); | |
| HeapFree(GetProcessHeap(), 0, This); | |
| return 0; | |
| } | |
| return This->ref; | |
| } | |
| HRESULT WINAPI | |
| Main_IDirect3DVertexBufferImpl_7_1T_Lock(LPDIRECT3DVERTEXBUFFER7 iface, | |
| DWORD dwFlags, | |
| LPVOID* lplpData, | |
| LPDWORD lpdwSize) | |
| { | |
| ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface); | |
| TRACE("(%p/%p)->(%08lx,%p,%p)\n", This, iface, dwFlags, lplpData, lpdwSize); | |
| if (TRACE_ON(ddraw)) { | |
| TRACE(" lock flags : "); | |
| DDRAW_dump_lockflag(dwFlags); | |
| } | |
| if (This->processed == TRUE) { | |
| WARN(" application does a Lock on a vertex buffer resulting from a ProcessVertices call. Expect problems !\n"); | |
| } | |
| if (This->desc.dwCaps & D3DVBCAPS_OPTIMIZED) return D3DERR_VERTEXBUFFEROPTIMIZED; | |
| if (lpdwSize != NULL) *lpdwSize = This->vertex_buffer_size; | |
| *lplpData = This->vertices; | |
| return DD_OK; | |
| } | |
| HRESULT WINAPI | |
| Main_IDirect3DVertexBufferImpl_7_1T_Unlock(LPDIRECT3DVERTEXBUFFER7 iface) | |
| { | |
| ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface); | |
| TRACE("(%p/%p)->()\n", This, iface); | |
| /* Nothing to do here for now. Maybe some optimizations if ever we want to do some :-) */ | |
| return DD_OK; | |
| } | |
| HRESULT WINAPI | |
| Main_IDirect3DVertexBufferImpl_7_1T_ProcessVertices(LPDIRECT3DVERTEXBUFFER7 iface, | |
| DWORD dwVertexOp, | |
| DWORD dwDestIndex, | |
| DWORD dwCount, | |
| LPDIRECT3DVERTEXBUFFER7 lpSrcBuffer, | |
| DWORD dwSrcIndex, | |
| LPDIRECT3DDEVICE7 lpD3DDevice, | |
| DWORD dwFlags) | |
| { | |
| ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface); | |
| FIXME("(%p/%p)->(%08lx,%08lx,%08lx,%p,%08lx,%p,%08lx): stub!\n", This, iface, dwVertexOp, dwDestIndex, dwCount, lpSrcBuffer, dwSrcIndex, lpD3DDevice, dwFlags); | |
| return DD_OK; | |
| } | |
| HRESULT WINAPI | |
| Main_IDirect3DVertexBufferImpl_7_1T_GetVertexBufferDesc(LPDIRECT3DVERTEXBUFFER7 iface, | |
| LPD3DVERTEXBUFFERDESC lpD3DVertexBufferDesc) | |
| { | |
| DWORD size; | |
| ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface); | |
| TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DVertexBufferDesc); | |
| size = lpD3DVertexBufferDesc->dwSize; | |
| memset(lpD3DVertexBufferDesc, 0, size); | |
| memcpy(lpD3DVertexBufferDesc, &This->desc, | |
| (size < This->desc.dwSize) ? size : This->desc.dwSize); | |
| return DD_OK; | |
| } | |
| HRESULT WINAPI | |
| Main_IDirect3DVertexBufferImpl_7_1T_Optimize(LPDIRECT3DVERTEXBUFFER7 iface, | |
| LPDIRECT3DDEVICE7 lpD3DDevice, | |
| DWORD dwFlags) | |
| { | |
| ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface); | |
| FIXME("(%p/%p)->(%p,%08lx): stub!\n", This, iface, lpD3DDevice, dwFlags); | |
| This->desc.dwCaps |= D3DVBCAPS_OPTIMIZED; | |
| return DD_OK; | |
| } | |
| HRESULT WINAPI | |
| Main_IDirect3DVertexBufferImpl_7_ProcessVerticesStrided(LPDIRECT3DVERTEXBUFFER7 iface, | |
| DWORD dwVertexOp, | |
| DWORD dwDestIndex, | |
| DWORD dwCount, | |
| LPD3DDRAWPRIMITIVESTRIDEDDATA lpStrideData, | |
| DWORD dwVertexTypeDesc, | |
| LPDIRECT3DDEVICE7 lpD3DDevice, | |
| DWORD dwFlags) | |
| { | |
| ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface); | |
| FIXME("(%p/%p)->(%08lx,%08lx,%08lx,%p,%08lx,%p,%08lx): stub!\n", This, iface, dwVertexOp, dwDestIndex, dwCount, lpStrideData, dwVertexTypeDesc, lpD3DDevice, dwFlags); | |
| return DD_OK; | |
| } | |
| HRESULT WINAPI | |
| Thunk_IDirect3DVertexBufferImpl_1_ProcessVertices(LPDIRECT3DVERTEXBUFFER iface, | |
| DWORD dwVertexOp, | |
| DWORD dwDestIndex, | |
| DWORD dwCount, | |
| LPDIRECT3DVERTEXBUFFER lpSrcBuffer, | |
| DWORD dwSrcIndex, | |
| LPDIRECT3DDEVICE3 lpD3DDevice, | |
| DWORD dwFlags) | |
| { | |
| TRACE("(%p)->(%08lx,%08lx,%08lx,%p,%08lx,%p,%08lx) thunking to IDirect3DVertexBuffer7 interface.\n", iface, | |
| dwVertexOp, dwDestIndex, dwCount, lpSrcBuffer, dwSrcIndex, lpD3DDevice, dwFlags); | |
| return IDirect3DVertexBuffer7_ProcessVertices(COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, IDirect3DVertexBuffer7, iface), | |
| dwVertexOp, | |
| dwDestIndex, | |
| dwCount, | |
| COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, IDirect3DVertexBuffer7, lpSrcBuffer), | |
| dwSrcIndex, | |
| COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice3, IDirect3DDevice7, lpD3DDevice), | |
| dwFlags); | |
| } | |
| HRESULT WINAPI | |
| Thunk_IDirect3DVertexBufferImpl_1_Optimize(LPDIRECT3DVERTEXBUFFER iface, | |
| LPDIRECT3DDEVICE3 lpD3DDevice, | |
| DWORD dwFlags) | |
| { | |
| TRACE("(%p)->(%p,%08lx) thunking to IDirect3DVertexBuffer7 interface.\n", iface, lpD3DDevice, dwFlags); | |
| return IDirect3DVertexBuffer7_Optimize(COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, IDirect3DVertexBuffer7, iface), | |
| COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice3, IDirect3DDevice7, lpD3DDevice), | |
| dwFlags); | |
| } | |
| HRESULT WINAPI | |
| Thunk_IDirect3DVertexBufferImpl_1_QueryInterface(LPDIRECT3DVERTEXBUFFER iface, | |
| REFIID riid, | |
| LPVOID* obp) | |
| { | |
| TRACE("(%p)->(%s,%p) thunking to IDirect3DVertexBuffer7 interface.\n", iface, debugstr_guid(riid), obp); | |
| return IDirect3DVertexBuffer7_QueryInterface(COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, IDirect3DVertexBuffer7, iface), | |
| riid, | |
| obp); | |
| } | |
| ULONG WINAPI | |
| Thunk_IDirect3DVertexBufferImpl_1_AddRef(LPDIRECT3DVERTEXBUFFER iface) | |
| { | |
| TRACE("(%p)->() thunking to IDirect3DVertexBuffer7 interface.\n", iface); | |
| return IDirect3DVertexBuffer7_AddRef(COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, IDirect3DVertexBuffer7, iface)); | |
| } | |
| ULONG WINAPI | |
| Thunk_IDirect3DVertexBufferImpl_1_Release(LPDIRECT3DVERTEXBUFFER iface) | |
| { | |
| TRACE("(%p)->() thunking to IDirect3DVertexBuffer7 interface.\n", iface); | |
| return IDirect3DVertexBuffer7_Release(COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, IDirect3DVertexBuffer7, iface)); | |
| } | |
| HRESULT WINAPI | |
| Thunk_IDirect3DVertexBufferImpl_1_Lock(LPDIRECT3DVERTEXBUFFER iface, | |
| DWORD dwFlags, | |
| LPVOID* lplpData, | |
| LPDWORD lpdwSize) | |
| { | |
| TRACE("(%p)->(%08lx,%p,%p) thunking to IDirect3DVertexBuffer7 interface.\n", iface, dwFlags, lplpData, lpdwSize); | |
| return IDirect3DVertexBuffer7_Lock(COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, IDirect3DVertexBuffer7, iface), | |
| dwFlags, | |
| lplpData, | |
| lpdwSize); | |
| } | |
| HRESULT WINAPI | |
| Thunk_IDirect3DVertexBufferImpl_1_Unlock(LPDIRECT3DVERTEXBUFFER iface) | |
| { | |
| TRACE("(%p)->() thunking to IDirect3DVertexBuffer7 interface.\n", iface); | |
| return IDirect3DVertexBuffer7_Unlock(COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, IDirect3DVertexBuffer7, iface)); | |
| } | |
| HRESULT WINAPI | |
| Thunk_IDirect3DVertexBufferImpl_1_GetVertexBufferDesc(LPDIRECT3DVERTEXBUFFER iface, | |
| LPD3DVERTEXBUFFERDESC lpD3DVertexBufferDesc) | |
| { | |
| TRACE("(%p)->(%p) thunking to IDirect3DVertexBuffer7 interface.\n", iface, lpD3DVertexBufferDesc); | |
| return IDirect3DVertexBuffer7_GetVertexBufferDesc(COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer, IDirect3DVertexBuffer7, iface), | |
| lpD3DVertexBufferDesc); | |
| } | |
| #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size) | |
| static HRESULT | |
| process_vertices_strided(IDirect3DVertexBufferImpl *This, | |
| DWORD dwVertexOp, | |
| DWORD dwDestIndex, | |
| DWORD dwCount, | |
| LPD3DDRAWPRIMITIVESTRIDEDDATA lpStrideData, | |
| DWORD dwVertexTypeDesc, | |
| IDirect3DDeviceImpl *device_impl, | |
| DWORD dwFlags) | |
| { | |
| IDirect3DVertexBufferGLImpl *glThis = (IDirect3DVertexBufferGLImpl *) This; | |
| DWORD size = get_flexible_vertex_size(dwVertexTypeDesc); | |
| char *dest_ptr; | |
| unsigned int i; | |
| This->processed = TRUE; | |
| /* For the moment, the trick is to save the transform and lighting state at process | |
| time to restore them at drawing time. | |
| The BIG problem with this method is nothing prevents D3D to do dirty tricks like | |
| processing two different sets of vertices with two different rendering parameters | |
| and then to display them using the same DrawPrimitive call. | |
| It would be nice to check for such code here (but well, even this is not trivial | |
| to do). | |
| This is exactly what the TWIST.EXE demo does but using the same kind of ugly stuff | |
| in the D3DExecuteBuffer code. I really wonder why Microsoft went back in time when | |
| implementing this mostly useless (IMHO) API. | |
| */ | |
| glThis->dwVertexTypeDesc = dwVertexTypeDesc; | |
| if (dwVertexTypeDesc & D3DFVF_NORMAL) { | |
| WARN(" lighting state not saved yet... Some strange stuff may happen !\n"); | |
| } | |
| if (glThis->vertices == NULL) { | |
| glThis->vertices = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size * This->desc.dwNumVertices); | |
| } | |
| dest_ptr = ((char *) glThis->vertices) + dwDestIndex * size; | |
| memcpy(&(glThis->world_mat), device_impl->world_mat, sizeof(D3DMATRIX)); | |
| memcpy(&(glThis->view_mat), device_impl->view_mat, sizeof(D3DMATRIX)); | |
| memcpy(&(glThis->proj_mat), device_impl->proj_mat, sizeof(D3DMATRIX)); | |
| for (i = 0; i < dwCount; i++) { | |
| unsigned int tex_index; | |
| if ((dwVertexTypeDesc & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) { | |
| D3DVALUE *position = | |
| (D3DVALUE *) (((char *) lpStrideData->position.lpvData) + i * lpStrideData->position.dwStride); | |
| copy_and_next(dest_ptr, position, 3 * sizeof(D3DVALUE)); | |
| } else if ((dwVertexTypeDesc & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) { | |
| D3DVALUE *position = | |
| (D3DVALUE *) (((char *) lpStrideData->position.lpvData) + i * lpStrideData->position.dwStride); | |
| copy_and_next(dest_ptr, position, 4 * sizeof(D3DVALUE)); | |
| } | |
| if (dwVertexTypeDesc & D3DFVF_RESERVED1) { | |
| dest_ptr += sizeof(DWORD); | |
| } | |
| if (dwVertexTypeDesc & D3DFVF_NORMAL) { | |
| D3DVALUE *normal = | |
| (D3DVALUE *) (((char *) lpStrideData->normal.lpvData) + i * lpStrideData->normal.dwStride); | |
| copy_and_next(dest_ptr, normal, 3 * sizeof(D3DVALUE)); | |
| } | |
| if (dwVertexTypeDesc & D3DFVF_DIFFUSE) { | |
| DWORD *color_d = | |
| (DWORD *) (((char *) lpStrideData->diffuse.lpvData) + i * lpStrideData->diffuse.dwStride); | |
| copy_and_next(dest_ptr, color_d, sizeof(DWORD)); | |
| } | |
| if (dwVertexTypeDesc & D3DFVF_SPECULAR) { | |
| DWORD *color_s = | |
| (DWORD *) (((char *) lpStrideData->specular.lpvData) + i * lpStrideData->specular.dwStride); | |
| copy_and_next(dest_ptr, color_s, sizeof(DWORD)); | |
| } | |
| for (tex_index = 0; tex_index < ((dwVertexTypeDesc & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) { | |
| D3DVALUE *tex_coord = | |
| (D3DVALUE *) (((char *) lpStrideData->textureCoords[tex_index].lpvData) + | |
| i * lpStrideData->textureCoords[tex_index].dwStride); | |
| copy_and_next(dest_ptr, tex_coord, 2 * sizeof(D3DVALUE)); | |
| } | |
| if (TRACE_ON(ddraw_geom)) { | |
| if ((dwVertexTypeDesc & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) { | |
| D3DVALUE *position = | |
| (D3DVALUE *) (((char *) lpStrideData->position.lpvData) + i * lpStrideData->position.dwStride); | |
| TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]); | |
| } else if ((dwVertexTypeDesc & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) { | |
| D3DVALUE *position = | |
| (D3DVALUE *) (((char *) lpStrideData->position.lpvData) + i * lpStrideData->position.dwStride); | |
| TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]); | |
| } | |
| if (dwVertexTypeDesc & D3DFVF_NORMAL) { | |
| D3DVALUE *normal = | |
| (D3DVALUE *) (((char *) lpStrideData->normal.lpvData) + i * lpStrideData->normal.dwStride); | |
| TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]); | |
| } | |
| if (dwVertexTypeDesc & D3DFVF_DIFFUSE) { | |
| DWORD *color_d = | |
| (DWORD *) (((char *) lpStrideData->diffuse.lpvData) + i * lpStrideData->diffuse.dwStride); | |
| TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx", | |
| (*color_d >> 16) & 0xFF, | |
| (*color_d >> 8) & 0xFF, | |
| (*color_d >> 0) & 0xFF, | |
| (*color_d >> 24) & 0xFF); | |
| } | |
| if (dwVertexTypeDesc & D3DFVF_SPECULAR) { | |
| DWORD *color_s = | |
| (DWORD *) (((char *) lpStrideData->specular.lpvData) + i * lpStrideData->specular.dwStride); | |
| TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx", | |
| (*color_s >> 16) & 0xFF, | |
| (*color_s >> 8) & 0xFF, | |
| (*color_s >> 0) & 0xFF, | |
| (*color_s >> 24) & 0xFF); | |
| } | |
| for (tex_index = 0; tex_index < ((dwVertexTypeDesc & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) { | |
| D3DVALUE *tex_coord = | |
| (D3DVALUE *) (((char *) lpStrideData->textureCoords[tex_index].lpvData) + | |
| i * lpStrideData->textureCoords[tex_index].dwStride); | |
| TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]); | |
| } | |
| TRACE_(ddraw_geom)("\n"); | |
| } | |
| } | |
| return DD_OK; | |
| } | |
| #undef copy_and_next | |
| HRESULT WINAPI | |
| GL_IDirect3DVertexBufferImpl_7_1T_ProcessVertices(LPDIRECT3DVERTEXBUFFER7 iface, | |
| DWORD dwVertexOp, | |
| DWORD dwDestIndex, | |
| DWORD dwCount, | |
| LPDIRECT3DVERTEXBUFFER7 lpSrcBuffer, | |
| DWORD dwSrcIndex, | |
| LPDIRECT3DDEVICE7 lpD3DDevice, | |
| DWORD dwFlags) | |
| { | |
| ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface); | |
| IDirect3DVertexBufferImpl *src_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpSrcBuffer); | |
| IDirect3DDeviceImpl *device_impl = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice7, lpD3DDevice); | |
| D3DDRAWPRIMITIVESTRIDEDDATA strided; | |
| DWORD size; | |
| TRACE("(%p/%p)->(%08lx,%08lx,%08lx,%p,%08lx,%p,%08lx)\n", This, iface, dwVertexOp, dwDestIndex, dwCount, lpSrcBuffer, dwSrcIndex, lpD3DDevice, dwFlags); | |
| if (TRACE_ON(ddraw)) { | |
| TRACE(" - vertex operations : "); dump_D3DVOP(dwVertexOp); | |
| TRACE(" - flags : "); dump_D3DPV(dwFlags); | |
| } | |
| if ((dwVertexOp & D3DVOP_TRANSFORM) == 0) return DDERR_INVALIDPARAMS; | |
| size = get_flexible_vertex_size(src_impl->desc.dwFVF); | |
| convert_FVF_to_strided_data(src_impl->desc.dwFVF, ((char *) src_impl->vertices) + dwSrcIndex * size, &strided, 0); | |
| return process_vertices_strided(This, dwVertexOp, dwDestIndex, dwCount, &strided, src_impl->desc.dwFVF, device_impl, dwFlags); | |
| } | |
| HRESULT WINAPI | |
| GL_IDirect3DVertexBufferImpl_7_ProcessVerticesStrided(LPDIRECT3DVERTEXBUFFER7 iface, | |
| DWORD dwVertexOp, | |
| DWORD dwDestIndex, | |
| DWORD dwCount, | |
| LPD3DDRAWPRIMITIVESTRIDEDDATA lpStrideData, | |
| DWORD dwVertexTypeDesc, | |
| LPDIRECT3DDEVICE7 lpD3DDevice, | |
| DWORD dwFlags) | |
| { | |
| ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface); | |
| IDirect3DDeviceImpl *device_impl = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice7, lpD3DDevice); | |
| TRACE("(%p/%p)->(%08lx,%08lx,%08lx,%p,%08lx,%p,%08lx)\n", This, iface, dwVertexOp, dwDestIndex, dwCount, lpStrideData, dwVertexTypeDesc, lpD3DDevice, dwFlags); | |
| if (TRACE_ON(ddraw)) { | |
| TRACE(" - vertex operations : "); dump_D3DVOP(dwVertexOp); | |
| TRACE(" - flags : "); dump_D3DPV(dwFlags); | |
| TRACE(" - vertex format : "); dump_flexible_vertex(dwVertexTypeDesc); | |
| } | |
| if ((dwVertexOp & D3DVOP_TRANSFORM) == 0) return DDERR_INVALIDPARAMS; | |
| return process_vertices_strided(This, dwVertexOp, dwDestIndex, dwCount, lpStrideData, dwVertexTypeDesc, device_impl, dwFlags); | |
| } | |
| #if !defined(__STRICT_ANSI__) && defined(__GNUC__) | |
| # define XCAST(fun) (typeof(VTABLE_IDirect3DVertexBuffer7.fun)) | |
| #else | |
| # define XCAST(fun) (void*) | |
| #endif | |
| IDirect3DVertexBuffer7Vtbl VTABLE_IDirect3DVertexBuffer7 = | |
| { | |
| XCAST(QueryInterface) Main_IDirect3DVertexBufferImpl_7_1T_QueryInterface, | |
| XCAST(AddRef) Main_IDirect3DVertexBufferImpl_7_1T_AddRef, | |
| XCAST(Release) Main_IDirect3DVertexBufferImpl_7_1T_Release, | |
| XCAST(Lock) Main_IDirect3DVertexBufferImpl_7_1T_Lock, | |
| XCAST(Unlock) Main_IDirect3DVertexBufferImpl_7_1T_Unlock, | |
| XCAST(ProcessVertices) GL_IDirect3DVertexBufferImpl_7_1T_ProcessVertices, | |
| XCAST(GetVertexBufferDesc) Main_IDirect3DVertexBufferImpl_7_1T_GetVertexBufferDesc, | |
| XCAST(Optimize) Main_IDirect3DVertexBufferImpl_7_1T_Optimize, | |
| XCAST(ProcessVerticesStrided) GL_IDirect3DVertexBufferImpl_7_ProcessVerticesStrided | |
| }; | |
| #if !defined(__STRICT_ANSI__) && defined(__GNUC__) | |
| #undef XCAST | |
| #endif | |
| #if !defined(__STRICT_ANSI__) && defined(__GNUC__) | |
| # define XCAST(fun) (typeof(VTABLE_IDirect3DVertexBuffer.fun)) | |
| #else | |
| # define XCAST(fun) (void*) | |
| #endif | |
| IDirect3DVertexBufferVtbl VTABLE_IDirect3DVertexBuffer = | |
| { | |
| XCAST(QueryInterface) Thunk_IDirect3DVertexBufferImpl_1_QueryInterface, | |
| XCAST(AddRef) Thunk_IDirect3DVertexBufferImpl_1_AddRef, | |
| XCAST(Release) Thunk_IDirect3DVertexBufferImpl_1_Release, | |
| XCAST(Lock) Thunk_IDirect3DVertexBufferImpl_1_Lock, | |
| XCAST(Unlock) Thunk_IDirect3DVertexBufferImpl_1_Unlock, | |
| XCAST(ProcessVertices) Thunk_IDirect3DVertexBufferImpl_1_ProcessVertices, | |
| XCAST(GetVertexBufferDesc) Thunk_IDirect3DVertexBufferImpl_1_GetVertexBufferDesc, | |
| XCAST(Optimize) Thunk_IDirect3DVertexBufferImpl_1_Optimize | |
| }; | |
| #if !defined(__STRICT_ANSI__) && defined(__GNUC__) | |
| #undef XCAST | |
| #endif | |
| HRESULT d3dvertexbuffer_create(IDirect3DVertexBufferImpl **obj, IDirectDrawImpl *d3d, LPD3DVERTEXBUFFERDESC lpD3DVertBufDesc, DWORD dwFlags) | |
| { | |
| IDirect3DVertexBufferImpl *object; | |
| static const flag_info flags[] = { | |
| FE(D3DVBCAPS_DONOTCLIP), | |
| FE(D3DVBCAPS_OPTIMIZED), | |
| FE(D3DVBCAPS_SYSTEMMEMORY), | |
| FE(D3DVBCAPS_WRITEONLY) | |
| }; | |
| object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBufferGLImpl)); | |
| if (object == NULL) return DDERR_OUTOFMEMORY; | |
| object->ref = 1; | |
| object->d3d = d3d; | |
| object->desc = *lpD3DVertBufDesc; | |
| object->vertex_buffer_size = get_flexible_vertex_size(lpD3DVertBufDesc->dwFVF) * lpD3DVertBufDesc->dwNumVertices; | |
| object->vertices = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->vertex_buffer_size); | |
| ICOM_INIT_INTERFACE(object, IDirect3DVertexBuffer, VTABLE_IDirect3DVertexBuffer); | |
| ICOM_INIT_INTERFACE(object, IDirect3DVertexBuffer7, VTABLE_IDirect3DVertexBuffer7); | |
| *obj = object; | |
| if (TRACE_ON(ddraw)) { | |
| TRACE(" creating implementation at %p with description : \n", *obj); | |
| TRACE(" flags : "); DDRAW_dump_flags_(lpD3DVertBufDesc->dwCaps, flags, sizeof(flags)/sizeof(flags[0]), TRUE); | |
| TRACE(" vertex type : "); dump_flexible_vertex(lpD3DVertBufDesc->dwFVF); | |
| TRACE(" num vertices : %ld\n", lpD3DVertBufDesc->dwNumVertices); | |
| } | |
| return D3D_OK; | |
| } |