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
);
82 /* *******************************************
83 IWineD3DVertexDeclaration parts follow
84 ******************************************* */
86 static HRESULT WINAPI
IWineD3DVertexDeclarationImpl_GetParent(IWineD3DVertexDeclaration
*iface
, IUnknown
** parent
){
87 IWineD3DVertexDeclarationImpl
*This
= (IWineD3DVertexDeclarationImpl
*)iface
;
89 *parent
= This
->parent
;
90 IUnknown_AddRef(*parent
);
91 TRACE("(%p) : returning %p\n", This
, *parent
);
95 static HRESULT WINAPI
IWineD3DVertexDeclarationImpl_GetDevice(IWineD3DVertexDeclaration
*iface
, IWineD3DDevice
** ppDevice
) {
96 IWineD3DVertexDeclarationImpl
*This
= (IWineD3DVertexDeclarationImpl
*)iface
;
97 TRACE("(%p) : returning %p\n", This
, This
->wineD3DDevice
);
99 *ppDevice
= (IWineD3DDevice
*) This
->wineD3DDevice
;
100 IWineD3DDevice_AddRef(*ppDevice
);
105 static HRESULT WINAPI
IWineD3DVertexDeclarationImpl_GetDeclaration(IWineD3DVertexDeclaration
*iface
,
106 WINED3DVERTEXELEMENT
*elements
, UINT
*element_count
) {
107 IWineD3DVertexDeclarationImpl
*This
= (IWineD3DVertexDeclarationImpl
*)iface
;
108 HRESULT hr
= WINED3D_OK
;
110 TRACE("(%p) : d3d version %d, elements %p, element_count %p\n",
111 This
, ((IWineD3DImpl
*)This
->wineD3DDevice
->wineD3D
)->dxVersion
, elements
, element_count
);
113 *element_count
= This
->declarationWNumElements
;
115 CopyMemory(elements
, This
->pDeclarationWine
, This
->declarationWNumElements
* sizeof(WINED3DVERTEXELEMENT
));
121 static HRESULT WINAPI
IWineD3DVertexDeclarationImpl_SetDeclaration(IWineD3DVertexDeclaration
*iface
,
122 const WINED3DVERTEXELEMENT
*elements
, UINT element_count
) {
123 IWineD3DVertexDeclarationImpl
*This
= (IWineD3DVertexDeclarationImpl
*)iface
;
124 HRESULT hr
= WINED3D_OK
;
126 char isPreLoaded
[MAX_STREAMS
];
128 TRACE("(%p) : d3d version %d\n", This
, ((IWineD3DImpl
*)This
->wineD3DDevice
->wineD3D
)->dxVersion
);
129 memset(isPreLoaded
, 0, sizeof(isPreLoaded
));
131 if (TRACE_ON(d3d_decl
)) {
132 for (i
= 0; i
< element_count
; ++i
) {
133 dump_wined3dvertexelement(elements
+i
);
137 This
->declarationWNumElements
= element_count
;
138 This
->pDeclarationWine
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINED3DVERTEXELEMENT
) * element_count
);
139 if (!This
->pDeclarationWine
) {
140 ERR("Memory allocation failed\n");
141 return WINED3DERR_OUTOFVIDEOMEMORY
;
143 CopyMemory(This
->pDeclarationWine
, elements
, sizeof(WINED3DVERTEXELEMENT
) * element_count
);
146 /* Do some static analysis on the elements to make reading the declaration more comfortable
147 * for the drawing code
149 This
->num_streams
= 0;
150 This
->position_transformed
= FALSE
;
151 for (i
= 0; i
< element_count
; ++i
) {
153 if(This
->pDeclarationWine
[i
].Usage
== WINED3DDECLUSAGE_POSITIONT
) {
154 This
->position_transformed
= TRUE
;
157 /* Find the Streams used in the declaration. The vertex buffers have to be loaded
158 * when drawing, but filter tesselation pseudo streams
160 if(This
->pDeclarationWine
[i
].Stream
>= MAX_STREAMS
) continue;
162 if(This
->pDeclarationWine
[i
].Type
== WINED3DDECLTYPE_UNUSED
) {
163 WARN("The application tries to use WINED3DDECLTYPE_UNUSED, returning E_FAIL\n");
164 /* The caller will release the vdecl, which will free This->pDeclarationWine */
168 if(This
->pDeclarationWine
[i
].Offset
& 0x3) {
169 WARN("Declaration element %d is not 4 byte aligned(%d), returning E_FAIL\n", i
, This
->pDeclarationWine
[i
].Offset
);
170 HeapFree(GetProcessHeap(), 0, This
->pDeclarationWine
);
174 if(!isPreLoaded
[This
->pDeclarationWine
[i
].Stream
]) {
175 This
->streams
[This
->num_streams
] = This
->pDeclarationWine
[i
].Stream
;
177 isPreLoaded
[This
->pDeclarationWine
[i
].Stream
] = 1;
180 /* Create a sorted array containing the attribute declarations that are of type
181 * D3DCOLOR. D3DCOLOR requires swizzling of the r and b component, and if the
182 * declaration of one attribute changes the vertex shader needs recompilation.
183 * Having a sorted array of the attributes allows efficient comparison of the
184 * declaration against a shader
186 if(This
->pDeclarationWine
[i
].Type
== WINED3DDECLTYPE_D3DCOLOR
) {
187 for(j
= 0; j
< This
->num_swizzled_attribs
; j
++) {
188 if(This
->swizzled_attribs
[j
].usage
> This
->pDeclarationWine
[i
].Usage
||
189 (This
->swizzled_attribs
[j
].usage
== This
->pDeclarationWine
[i
].Usage
&&
190 This
->swizzled_attribs
[j
].idx
> This
->pDeclarationWine
[i
].UsageIndex
)) {
191 memmove(&This
->swizzled_attribs
[j
+ 1], &This
->swizzled_attribs
[j
],
192 sizeof(This
->swizzled_attribs
) - (sizeof(This
->swizzled_attribs
[0]) * (j
+ 1)));
197 This
->swizzled_attribs
[j
].usage
= This
->pDeclarationWine
[i
].Usage
;
198 This
->swizzled_attribs
[j
].idx
= This
->pDeclarationWine
[i
].UsageIndex
;
199 This
->num_swizzled_attribs
++;
200 } else if(This
->pDeclarationWine
[i
].Type
== WINED3DDECLTYPE_FLOAT16_2
||
201 This
->pDeclarationWine
[i
].Type
== WINED3DDECLTYPE_FLOAT16_4
) {
202 if(!GL_SUPPORT(NV_HALF_FLOAT
)) {
203 This
->half_float_conv_needed
= TRUE
;
208 TRACE("Swizzled attributes found:\n");
209 for(i
= 0; i
< This
->num_swizzled_attribs
; i
++) {
210 TRACE("%u: %s%d\n", i
,
211 debug_d3ddeclusage(This
->swizzled_attribs
[i
].usage
), This
->swizzled_attribs
[i
].idx
);
213 TRACE("Returning\n");
217 const IWineD3DVertexDeclarationVtbl IWineD3DVertexDeclaration_Vtbl
=
220 IWineD3DVertexDeclarationImpl_QueryInterface
,
221 IWineD3DVertexDeclarationImpl_AddRef
,
222 IWineD3DVertexDeclarationImpl_Release
,
223 /* IWineD3DVertexDeclaration */
224 IWineD3DVertexDeclarationImpl_GetParent
,
225 IWineD3DVertexDeclarationImpl_GetDevice
,
226 IWineD3DVertexDeclarationImpl_GetDeclaration
,
227 IWineD3DVertexDeclarationImpl_SetDeclaration