2 * vertex declaration implementation
4 * Copyright 2002-2005 Raphael Junqueira
5 * Copyright 2004 Jason Edmeades
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d_decl
);
29 #define GLINFO_LOCATION This->wineD3DDevice->adapter->gl_info
31 static void dump_wined3dvertexelement(const WINED3DVERTEXELEMENT
*element
) {
32 TRACE(" Stream: %d\n", element
->Stream
);
33 TRACE(" Offset: %d\n", element
->Offset
);
34 TRACE(" Type: %s (%#x)\n", debug_d3ddecltype(element
->Type
), element
->Type
);
35 TRACE(" Method: %s (%#x)\n", debug_d3ddeclmethod(element
->Method
), element
->Method
);
36 TRACE(" Usage: %s (%#x)\n", debug_d3ddeclusage(element
->Usage
), element
->Usage
);
37 TRACE("Usage index: %d\n", element
->UsageIndex
);
38 TRACE(" Register: %d\n", element
->Reg
);
41 /* *******************************************
42 IWineD3DVertexDeclaration IUnknown parts follow
43 ******************************************* */
44 static HRESULT WINAPI
IWineD3DVertexDeclarationImpl_QueryInterface(IWineD3DVertexDeclaration
*iface
, REFIID riid
, LPVOID
*ppobj
)
46 IWineD3DVertexDeclarationImpl
*This
= (IWineD3DVertexDeclarationImpl
*)iface
;
47 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
48 if (IsEqualGUID(riid
, &IID_IUnknown
)
49 || IsEqualGUID(riid
, &IID_IWineD3DBase
)
50 || IsEqualGUID(riid
, &IID_IWineD3DVertexDeclaration
)){
51 IUnknown_AddRef(iface
);
59 static ULONG WINAPI
IWineD3DVertexDeclarationImpl_AddRef(IWineD3DVertexDeclaration
*iface
) {
60 IWineD3DVertexDeclarationImpl
*This
= (IWineD3DVertexDeclarationImpl
*)iface
;
61 TRACE("(%p) : AddRef increasing from %d\n", This
, This
->ref
);
62 return InterlockedIncrement(&This
->ref
);
65 static ULONG WINAPI
IWineD3DVertexDeclarationImpl_Release(IWineD3DVertexDeclaration
*iface
) {
66 IWineD3DVertexDeclarationImpl
*This
= (IWineD3DVertexDeclarationImpl
*)iface
;
68 TRACE("(%p) : Releasing from %d\n", This
, This
->ref
);
69 ref
= InterlockedDecrement(&This
->ref
);
71 if(iface
== This
->wineD3DDevice
->stateBlock
->vertexDecl
) {
72 /* See comment in PixelShader::Release */
73 IWineD3DDeviceImpl_MarkStateDirty(This
->wineD3DDevice
, STATE_VDECL
);
76 HeapFree(GetProcessHeap(), 0, This
->pDeclarationWine
);
77 HeapFree(GetProcessHeap(), 0, This
->ffp_valid
);
78 HeapFree(GetProcessHeap(), 0, This
);
83 /* *******************************************
84 IWineD3DVertexDeclaration parts follow
85 ******************************************* */
87 static HRESULT WINAPI
IWineD3DVertexDeclarationImpl_GetParent(IWineD3DVertexDeclaration
*iface
, IUnknown
** parent
){
88 IWineD3DVertexDeclarationImpl
*This
= (IWineD3DVertexDeclarationImpl
*)iface
;
90 *parent
= This
->parent
;
91 IUnknown_AddRef(*parent
);
92 TRACE("(%p) : returning %p\n", This
, *parent
);
96 static HRESULT WINAPI
IWineD3DVertexDeclarationImpl_GetDevice(IWineD3DVertexDeclaration
*iface
, IWineD3DDevice
** ppDevice
) {
97 IWineD3DVertexDeclarationImpl
*This
= (IWineD3DVertexDeclarationImpl
*)iface
;
98 TRACE("(%p) : returning %p\n", This
, This
->wineD3DDevice
);
100 *ppDevice
= (IWineD3DDevice
*) This
->wineD3DDevice
;
101 IWineD3DDevice_AddRef(*ppDevice
);
106 static HRESULT WINAPI
IWineD3DVertexDeclarationImpl_GetDeclaration(IWineD3DVertexDeclaration
*iface
,
107 WINED3DVERTEXELEMENT
*elements
, UINT
*element_count
) {
108 IWineD3DVertexDeclarationImpl
*This
= (IWineD3DVertexDeclarationImpl
*)iface
;
109 HRESULT hr
= WINED3D_OK
;
111 TRACE("(%p) : d3d version %d, elements %p, element_count %p\n",
112 This
, ((IWineD3DImpl
*)This
->wineD3DDevice
->wineD3D
)->dxVersion
, elements
, element_count
);
114 *element_count
= This
->declarationWNumElements
;
116 CopyMemory(elements
, This
->pDeclarationWine
, This
->declarationWNumElements
* sizeof(WINED3DVERTEXELEMENT
));
122 static BOOL
declaration_element_valid_ffp(const WINED3DVERTEXELEMENT
*element
)
124 switch(element
->Usage
)
126 case WINED3DDECLUSAGE_POSITION
:
127 case WINED3DDECLUSAGE_POSITIONT
:
128 switch(element
->Type
)
130 case WINED3DDECLTYPE_FLOAT2
:
131 case WINED3DDECLTYPE_FLOAT3
:
132 case WINED3DDECLTYPE_FLOAT4
:
133 case WINED3DDECLTYPE_SHORT2
:
134 case WINED3DDECLTYPE_SHORT4
:
135 case WINED3DDECLTYPE_FLOAT16_2
:
136 case WINED3DDECLTYPE_FLOAT16_4
:
142 case WINED3DDECLUSAGE_BLENDWEIGHT
:
143 switch(element
->Type
)
145 case WINED3DDECLTYPE_D3DCOLOR
:
146 case WINED3DDECLTYPE_UBYTE4
:
147 case WINED3DDECLTYPE_SHORT2
:
148 case WINED3DDECLTYPE_SHORT4
:
149 case WINED3DDECLTYPE_FLOAT16_2
:
150 case WINED3DDECLTYPE_FLOAT16_4
:
156 case WINED3DDECLUSAGE_NORMAL
:
157 switch(element
->Type
)
159 case WINED3DDECLTYPE_FLOAT3
:
160 case WINED3DDECLTYPE_FLOAT4
:
161 case WINED3DDECLTYPE_SHORT4
:
162 case WINED3DDECLTYPE_FLOAT16_4
:
168 case WINED3DDECLUSAGE_TEXCOORD
:
169 switch(element
->Type
)
171 case WINED3DDECLTYPE_FLOAT1
:
172 case WINED3DDECLTYPE_FLOAT2
:
173 case WINED3DDECLTYPE_FLOAT3
:
174 case WINED3DDECLTYPE_FLOAT4
:
175 case WINED3DDECLTYPE_SHORT2
:
176 case WINED3DDECLTYPE_SHORT4
:
177 case WINED3DDECLTYPE_FLOAT16_2
:
178 case WINED3DDECLTYPE_FLOAT16_4
:
184 case WINED3DDECLUSAGE_COLOR
:
185 switch(element
->Type
)
187 case WINED3DDECLTYPE_FLOAT3
:
188 case WINED3DDECLTYPE_FLOAT4
:
189 case WINED3DDECLTYPE_D3DCOLOR
:
190 case WINED3DDECLTYPE_UBYTE4
:
191 case WINED3DDECLTYPE_SHORT4
:
192 case WINED3DDECLTYPE_UBYTE4N
:
193 case WINED3DDECLTYPE_SHORT4N
:
194 case WINED3DDECLTYPE_USHORT4N
:
195 case WINED3DDECLTYPE_FLOAT16_4
:
206 static HRESULT WINAPI
IWineD3DVertexDeclarationImpl_SetDeclaration(IWineD3DVertexDeclaration
*iface
,
207 const WINED3DVERTEXELEMENT
*elements
, UINT element_count
) {
208 IWineD3DVertexDeclarationImpl
*This
= (IWineD3DVertexDeclarationImpl
*)iface
;
209 HRESULT hr
= WINED3D_OK
;
211 char isPreLoaded
[MAX_STREAMS
];
213 TRACE("(%p) : d3d version %d\n", This
, ((IWineD3DImpl
*)This
->wineD3DDevice
->wineD3D
)->dxVersion
);
214 memset(isPreLoaded
, 0, sizeof(isPreLoaded
));
216 if (TRACE_ON(d3d_decl
)) {
217 for (i
= 0; i
< element_count
; ++i
) {
218 dump_wined3dvertexelement(elements
+i
);
222 This
->declarationWNumElements
= element_count
;
223 This
->pDeclarationWine
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINED3DVERTEXELEMENT
) * element_count
);
224 This
->ffp_valid
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
->ffp_valid
) * element_count
);
225 if (!This
->pDeclarationWine
|| !This
->ffp_valid
) {
226 ERR("Memory allocation failed\n");
227 return WINED3DERR_OUTOFVIDEOMEMORY
;
229 CopyMemory(This
->pDeclarationWine
, elements
, sizeof(WINED3DVERTEXELEMENT
) * element_count
);
232 /* Do some static analysis on the elements to make reading the declaration more comfortable
233 * for the drawing code
235 This
->num_streams
= 0;
236 This
->position_transformed
= FALSE
;
237 for (i
= 0; i
< element_count
; ++i
) {
238 This
->ffp_valid
[i
] = declaration_element_valid_ffp(&This
->pDeclarationWine
[i
]);
240 if(This
->pDeclarationWine
[i
].Usage
== WINED3DDECLUSAGE_POSITIONT
) {
241 This
->position_transformed
= TRUE
;
244 /* Find the Streams used in the declaration. The vertex buffers have to be loaded
245 * when drawing, but filter tesselation pseudo streams
247 if(This
->pDeclarationWine
[i
].Stream
>= MAX_STREAMS
) continue;
249 if(This
->pDeclarationWine
[i
].Type
== WINED3DDECLTYPE_UNUSED
) {
250 WARN("The application tries to use WINED3DDECLTYPE_UNUSED, returning E_FAIL\n");
251 /* The caller will release the vdecl, which will free This->pDeclarationWine */
255 if(This
->pDeclarationWine
[i
].Offset
& 0x3) {
256 WARN("Declaration element %d is not 4 byte aligned(%d), returning E_FAIL\n", i
, This
->pDeclarationWine
[i
].Offset
);
260 if(!isPreLoaded
[This
->pDeclarationWine
[i
].Stream
]) {
261 This
->streams
[This
->num_streams
] = This
->pDeclarationWine
[i
].Stream
;
263 isPreLoaded
[This
->pDeclarationWine
[i
].Stream
] = 1;
266 /* Create a sorted array containing the attribute declarations that are of type
267 * D3DCOLOR. D3DCOLOR requires swizzling of the r and b component, and if the
268 * declaration of one attribute changes the vertex shader needs recompilation.
269 * Having a sorted array of the attributes allows efficient comparison of the
270 * declaration against a shader
272 if(This
->pDeclarationWine
[i
].Type
== WINED3DDECLTYPE_D3DCOLOR
) {
273 for(j
= 0; j
< This
->num_swizzled_attribs
; j
++) {
274 if(This
->swizzled_attribs
[j
].usage
> This
->pDeclarationWine
[i
].Usage
||
275 (This
->swizzled_attribs
[j
].usage
== This
->pDeclarationWine
[i
].Usage
&&
276 This
->swizzled_attribs
[j
].idx
> This
->pDeclarationWine
[i
].UsageIndex
)) {
277 memmove(&This
->swizzled_attribs
[j
+ 1], &This
->swizzled_attribs
[j
],
278 sizeof(This
->swizzled_attribs
) - (sizeof(This
->swizzled_attribs
[0]) * (j
+ 1)));
283 This
->swizzled_attribs
[j
].usage
= This
->pDeclarationWine
[i
].Usage
;
284 This
->swizzled_attribs
[j
].idx
= This
->pDeclarationWine
[i
].UsageIndex
;
285 This
->num_swizzled_attribs
++;
286 } else if(This
->pDeclarationWine
[i
].Type
== WINED3DDECLTYPE_FLOAT16_2
||
287 This
->pDeclarationWine
[i
].Type
== WINED3DDECLTYPE_FLOAT16_4
) {
288 if(!GL_SUPPORT(NV_HALF_FLOAT
)) {
289 This
->half_float_conv_needed
= TRUE
;
294 TRACE("Swizzled attributes found:\n");
295 for(i
= 0; i
< This
->num_swizzled_attribs
; i
++) {
296 TRACE("%u: %s%d\n", i
,
297 debug_d3ddeclusage(This
->swizzled_attribs
[i
].usage
), This
->swizzled_attribs
[i
].idx
);
299 TRACE("Returning\n");
303 const IWineD3DVertexDeclarationVtbl IWineD3DVertexDeclaration_Vtbl
=
306 IWineD3DVertexDeclarationImpl_QueryInterface
,
307 IWineD3DVertexDeclarationImpl_AddRef
,
308 IWineD3DVertexDeclarationImpl_Release
,
309 /* IWineD3DVertexDeclaration */
310 IWineD3DVertexDeclarationImpl_GetParent
,
311 IWineD3DVertexDeclarationImpl_GetDevice
,
312 IWineD3DVertexDeclarationImpl_GetDeclaration
,
313 IWineD3DVertexDeclarationImpl_SetDeclaration