diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 368bcd2ae5f..91c12fbdfb0 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1572,41 +1572,36 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, U } } -/***** - * Vertex Declaration - *****/ -static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppVertexDeclaration, - IUnknown *parent, const WINED3DVERTEXELEMENT *elements, UINT element_count) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; +static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice *iface, + IWineD3DVertexDeclaration **declaration, IUnknown *parent, + const WINED3DVERTEXELEMENT *elements, UINT element_count) +{ + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DVertexDeclarationImpl *object = NULL; - HRESULT hr = WINED3D_OK; + HRESULT hr; - TRACE("(%p) : directXVersion %u, elements %p, element_count %d, ppDecl=%p\n", - This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, elements, element_count, ppVertexDeclaration); + TRACE("iface %p, declaration %p, parent %p, elements %p, element_count %u.\n", + iface, declaration, parent, elements, element_count); object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); if(!object) { - ERR("Out of memory\n"); - *ppVertexDeclaration = NULL; - return WINED3DERR_OUTOFVIDEOMEMORY; + ERR("Failed to allocate vertex declaration memory.\n"); + return E_OUTOFMEMORY; } - object->lpVtbl = &IWineD3DVertexDeclaration_Vtbl; - object->wineD3DDevice = This; - object->parent = parent; - object->ref = 1; - - *ppVertexDeclaration = (IWineD3DVertexDeclaration *)object; - - hr = vertexdeclaration_init(object, elements, element_count); - - if(FAILED(hr)) { - IWineD3DVertexDeclaration_Release((IWineD3DVertexDeclaration *)object); - *ppVertexDeclaration = NULL; + hr = vertexdeclaration_init(object, This, elements, element_count, parent); + if (FAILED(hr)) + { + WARN("Failed to initialize vertex declaration, hr %#x.\n", hr); + HeapFree(GetProcessHeap(), 0, object); + return hr; } - return hr; + TRACE("Created verrtex declaration %p.\n", object); + *declaration = (IWineD3DVertexDeclaration *)object; + + return WINED3D_OK; } static unsigned int ConvertFvfToDeclaration(IWineD3DDeviceImpl *This, /* For the GL info, which has the type table */ @@ -1746,20 +1741,22 @@ static unsigned int ConvertFvfToDeclaration(IWineD3DDeviceImpl *This, /* For the return size; } -static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *Parent, DWORD Fvf) { - WINED3DVERTEXELEMENT* elements = NULL; +static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF(IWineD3DDevice *iface, + IWineD3DVertexDeclaration **declaration, IUnknown *parent, DWORD fvf) +{ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; + WINED3DVERTEXELEMENT *elements; unsigned int size; DWORD hr; - size = ConvertFvfToDeclaration(This, Fvf, &elements); - if (size == ~0U) return WINED3DERR_OUTOFVIDEOMEMORY; + TRACE("iface %p, declaration %p, parent %p, fvf %#x.\n", iface, declaration, parent, fvf); - hr = IWineD3DDevice_CreateVertexDeclaration(iface, ppVertexDeclaration, Parent, elements, size); + size = ConvertFvfToDeclaration(This, fvf, &elements); + if (size == ~0U) return E_OUTOFMEMORY; + + hr = IWineD3DDevice_CreateVertexDeclaration(iface, declaration, parent, elements, size); HeapFree(GetProcessHeap(), 0, elements); - if (hr != S_OK) return hr; - - return WINED3D_OK; + return hr; } static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, diff --git a/dlls/wined3d/vertexdeclaration.c b/dlls/wined3d/vertexdeclaration.c index 2c2b7634783..e19aba53247 100644 --- a/dlls/wined3d/vertexdeclaration.c +++ b/dlls/wined3d/vertexdeclaration.c @@ -190,86 +190,7 @@ static BOOL declaration_element_valid_ffp(const WINED3DVERTEXELEMENT *element) } } -HRESULT vertexdeclaration_init(IWineD3DVertexDeclarationImpl *This, - const WINED3DVERTEXELEMENT *elements, UINT element_count) -{ - HRESULT hr = WINED3D_OK; - unsigned int i; - char isPreLoaded[MAX_STREAMS]; - - TRACE("(%p) : d3d version %d\n", This, ((IWineD3DImpl *)This->wineD3DDevice->wineD3D)->dxVersion); - memset(isPreLoaded, 0, sizeof(isPreLoaded)); - - if (TRACE_ON(d3d_decl)) { - for (i = 0; i < element_count; ++i) { - dump_wined3dvertexelement(elements+i); - } - } - - This->element_count = element_count; - This->elements = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->elements) * element_count); - if (!This->elements) - { - ERR("Memory allocation failed\n"); - return WINED3DERR_OUTOFVIDEOMEMORY; - } - - /* Do some static analysis on the elements to make reading the declaration more comfortable - * for the drawing code - */ - This->num_streams = 0; - This->position_transformed = FALSE; - for (i = 0; i < element_count; ++i) { - struct wined3d_vertex_declaration_element *e = &This->elements[i]; - - e->format_desc = getFormatDescEntry(elements[i].format, &This->wineD3DDevice->adapter->gl_info); - e->ffp_valid = declaration_element_valid_ffp(&elements[i]); - e->input_slot = elements[i].input_slot; - e->offset = elements[i].offset; - e->output_slot = elements[i].output_slot; - e->method = elements[i].method; - e->usage = elements[i].usage; - e->usage_idx = elements[i].usage_idx; - - if (e->usage == WINED3DDECLUSAGE_POSITIONT) This->position_transformed = TRUE; - - /* Find the Streams used in the declaration. The vertex buffers have to be loaded - * when drawing, but filter tesselation pseudo streams - */ - if (e->input_slot >= MAX_STREAMS) continue; - - if (!e->format_desc->gl_vtx_format) - { - FIXME("The application tries to use an unsupported format (%s), returning E_FAIL\n", - debug_d3dformat(elements[i].format)); - /* The caller will release the vdecl, which will free This->elements */ - return E_FAIL; - } - - if (e->offset & 0x3) - { - WARN("Declaration element %u is not 4 byte aligned(%u), returning E_FAIL\n", i, e->offset); - return E_FAIL; - } - - if (!isPreLoaded[e->input_slot]) - { - This->streams[This->num_streams] = e->input_slot; - This->num_streams++; - isPreLoaded[e->input_slot] = 1; - } - - if (elements[i].format == WINED3DFMT_R16G16_FLOAT || elements[i].format == WINED3DFMT_R16G16B16A16_FLOAT) - { - if (!GL_SUPPORT(ARB_HALF_FLOAT_VERTEX)) This->half_float_conv_needed = TRUE; - } - } - - TRACE("Returning\n"); - return hr; -} - -const IWineD3DVertexDeclarationVtbl IWineD3DVertexDeclaration_Vtbl = +static const IWineD3DVertexDeclarationVtbl IWineD3DVertexDeclaration_Vtbl = { /* IUnknown */ IWineD3DVertexDeclarationImpl_QueryInterface, @@ -279,3 +200,82 @@ const IWineD3DVertexDeclarationVtbl IWineD3DVertexDeclaration_Vtbl = IWineD3DVertexDeclarationImpl_GetParent, IWineD3DVertexDeclarationImpl_GetDevice, }; + +HRESULT vertexdeclaration_init(IWineD3DVertexDeclarationImpl *declaration, IWineD3DDeviceImpl *device, + const WINED3DVERTEXELEMENT *elements, UINT element_count, IUnknown *parent) +{ + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + WORD preloaded = 0; /* MAX_STREAMS, 16 */ + unsigned int i; + + if (TRACE_ON(d3d_decl)) + { + for (i = 0; i < element_count; ++i) + { + dump_wined3dvertexelement(elements + i); + } + } + + declaration->lpVtbl = &IWineD3DVertexDeclaration_Vtbl; + declaration->ref = 1; + declaration->parent = parent; + declaration->wineD3DDevice = device; + declaration->elements = HeapAlloc(GetProcessHeap(), 0, sizeof(*declaration->elements) * element_count); + if (!declaration->elements) + { + ERR("Failed to allocate elements memory.\n"); + return E_OUTOFMEMORY; + } + declaration->element_count = element_count; + + /* Do some static analysis on the elements to make reading the + * declaration more comfortable for the drawing code. */ + for (i = 0; i < element_count; ++i) + { + struct wined3d_vertex_declaration_element *e = &declaration->elements[i]; + + e->format_desc = getFormatDescEntry(elements[i].format, gl_info); + e->ffp_valid = declaration_element_valid_ffp(&elements[i]); + e->input_slot = elements[i].input_slot; + e->offset = elements[i].offset; + e->output_slot = elements[i].output_slot; + e->method = elements[i].method; + e->usage = elements[i].usage; + e->usage_idx = elements[i].usage_idx; + + if (e->usage == WINED3DDECLUSAGE_POSITIONT) declaration->position_transformed = TRUE; + + /* Find the streams used in the declaration. The vertex buffers have + * to be loaded when drawing, but filter tesselation pseudo streams. */ + if (e->input_slot >= MAX_STREAMS) continue; + + if (!e->format_desc->gl_vtx_format) + { + FIXME("The application tries to use an unsupported format (%s), returning E_FAIL.\n", + debug_d3dformat(elements[i].format)); + HeapFree(GetProcessHeap(), 0, declaration->elements); + return E_FAIL; + } + + if (e->offset & 0x3) + { + WARN("Declaration element %u is not 4 byte aligned(%u), returning E_FAIL.\n", i, e->offset); + HeapFree(GetProcessHeap(), 0, declaration->elements); + return E_FAIL; + } + + if (!(preloaded & (1 << e->input_slot))) + { + declaration->streams[declaration->num_streams] = e->input_slot; + ++declaration->num_streams; + preloaded |= 1 << e->input_slot; + } + + if (elements[i].format == WINED3DFMT_R16G16_FLOAT || elements[i].format == WINED3DFMT_R16G16B16A16_FLOAT) + { + if (!gl_info->supported[ARB_HALF_FLOAT_VERTEX]) declaration->half_float_conv_needed = TRUE; + } + } + + return WINED3D_OK; +} diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 0f0ad4a5a41..f06ab722208 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2198,10 +2198,8 @@ typedef struct IWineD3DVertexDeclarationImpl { BOOL half_float_conv_needed; } IWineD3DVertexDeclarationImpl; -extern const IWineD3DVertexDeclarationVtbl IWineD3DVertexDeclaration_Vtbl DECLSPEC_HIDDEN; - -HRESULT vertexdeclaration_init(IWineD3DVertexDeclarationImpl *This, - const WINED3DVERTEXELEMENT *elements, UINT element_count) DECLSPEC_HIDDEN; +HRESULT vertexdeclaration_init(IWineD3DVertexDeclarationImpl *This, IWineD3DDeviceImpl *device, + const WINED3DVERTEXELEMENT *elements, UINT element_count, IUnknown *parent) DECLSPEC_HIDDEN; /***************************************************************************** * IWineD3DStateBlock implementation structure