Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenvertexdeclaration.c
Go to the documentation of this file.
00001 /* 00002 * IDirect3DVertexDeclaration9 implementation 00003 * 00004 * Copyright 2002-2003 Raphael Junqueira 00005 * Jason Edmeades 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #include "config.h" 00023 #include "d3d9_private.h" 00024 00025 WINE_DEFAULT_DEBUG_CHANNEL(d3d9); 00026 00027 typedef struct _D3DDECLTYPE_INFO { 00028 D3DDECLTYPE d3dType; 00029 enum wined3d_format_id format; 00030 int size; 00031 int typesize; 00032 } D3DDECLTYPE_INFO; 00033 00034 static D3DDECLTYPE_INFO const d3d_dtype_lookup[D3DDECLTYPE_UNUSED] = { 00035 {D3DDECLTYPE_FLOAT1, WINED3DFMT_R32_FLOAT, 1, sizeof(float)}, 00036 {D3DDECLTYPE_FLOAT2, WINED3DFMT_R32G32_FLOAT, 2, sizeof(float)}, 00037 {D3DDECLTYPE_FLOAT3, WINED3DFMT_R32G32B32_FLOAT, 3, sizeof(float)}, 00038 {D3DDECLTYPE_FLOAT4, WINED3DFMT_R32G32B32A32_FLOAT, 4, sizeof(float)}, 00039 {D3DDECLTYPE_D3DCOLOR, WINED3DFMT_B8G8R8A8_UNORM, 4, sizeof(BYTE)}, 00040 {D3DDECLTYPE_UBYTE4, WINED3DFMT_R8G8B8A8_UINT, 4, sizeof(BYTE)}, 00041 {D3DDECLTYPE_SHORT2, WINED3DFMT_R16G16_SINT, 2, sizeof(short int)}, 00042 {D3DDECLTYPE_SHORT4, WINED3DFMT_R16G16B16A16_SINT, 4, sizeof(short int)}, 00043 {D3DDECLTYPE_UBYTE4N, WINED3DFMT_R8G8B8A8_UNORM, 4, sizeof(BYTE)}, 00044 {D3DDECLTYPE_SHORT2N, WINED3DFMT_R16G16_SNORM, 2, sizeof(short int)}, 00045 {D3DDECLTYPE_SHORT4N, WINED3DFMT_R16G16B16A16_SNORM, 4, sizeof(short int)}, 00046 {D3DDECLTYPE_USHORT2N, WINED3DFMT_R16G16_UNORM, 2, sizeof(short int)}, 00047 {D3DDECLTYPE_USHORT4N, WINED3DFMT_R16G16B16A16_UNORM, 4, sizeof(short int)}, 00048 {D3DDECLTYPE_UDEC3, WINED3DFMT_R10G10B10A2_UINT, 3, sizeof(short int)}, 00049 {D3DDECLTYPE_DEC3N, WINED3DFMT_R10G10B10A2_SNORM, 3, sizeof(short int)}, 00050 {D3DDECLTYPE_FLOAT16_2, WINED3DFMT_R16G16_FLOAT, 2, sizeof(short int)}, 00051 {D3DDECLTYPE_FLOAT16_4, WINED3DFMT_R16G16B16A16_FLOAT, 4, sizeof(short int)}}; 00052 00053 #define D3D_DECL_SIZE(type) d3d_dtype_lookup[type].size 00054 #define D3D_DECL_TYPESIZE(type) d3d_dtype_lookup[type].typesize 00055 00056 HRESULT vdecl_convert_fvf( 00057 DWORD fvf, 00058 D3DVERTEXELEMENT9** ppVertexElements) { 00059 00060 unsigned int idx, idx2; 00061 unsigned int offset; 00062 BOOL has_pos = (fvf & D3DFVF_POSITION_MASK) != 0; 00063 BOOL has_blend = (fvf & D3DFVF_XYZB5) > D3DFVF_XYZRHW; 00064 BOOL has_blend_idx = has_blend && 00065 (((fvf & D3DFVF_XYZB5) == D3DFVF_XYZB5) || 00066 (fvf & D3DFVF_LASTBETA_D3DCOLOR) || 00067 (fvf & D3DFVF_LASTBETA_UBYTE4)); 00068 BOOL has_normal = (fvf & D3DFVF_NORMAL) != 0; 00069 BOOL has_psize = (fvf & D3DFVF_PSIZE) != 0; 00070 00071 BOOL has_diffuse = (fvf & D3DFVF_DIFFUSE) != 0; 00072 BOOL has_specular = (fvf & D3DFVF_SPECULAR) !=0; 00073 00074 DWORD num_textures = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT; 00075 DWORD texcoords = (fvf & 0xFFFF0000) >> 16; 00076 00077 D3DVERTEXELEMENT9 end_element = D3DDECL_END(); 00078 D3DVERTEXELEMENT9 *elements = NULL; 00079 00080 unsigned int size; 00081 DWORD num_blends = 1 + (((fvf & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1); 00082 if (has_blend_idx) num_blends--; 00083 00084 /* Compute declaration size */ 00085 size = has_pos + (has_blend && num_blends > 0) + has_blend_idx + has_normal + 00086 has_psize + has_diffuse + has_specular + num_textures + 1; 00087 00088 /* convert the declaration */ 00089 elements = HeapAlloc(GetProcessHeap(), 0, size * sizeof(D3DVERTEXELEMENT9)); 00090 if (!elements) return D3DERR_OUTOFVIDEOMEMORY; 00091 00092 elements[size-1] = end_element; 00093 idx = 0; 00094 if (has_pos) { 00095 if (!has_blend && (fvf & D3DFVF_XYZRHW)) { 00096 elements[idx].Type = D3DDECLTYPE_FLOAT4; 00097 elements[idx].Usage = D3DDECLUSAGE_POSITIONT; 00098 } 00099 else if (!has_blend && (fvf & D3DFVF_XYZW) == D3DFVF_XYZW) { 00100 elements[idx].Type = D3DDECLTYPE_FLOAT4; 00101 elements[idx].Usage = D3DDECLUSAGE_POSITION; 00102 } 00103 else { 00104 elements[idx].Type = D3DDECLTYPE_FLOAT3; 00105 elements[idx].Usage = D3DDECLUSAGE_POSITION; 00106 } 00107 elements[idx].UsageIndex = 0; 00108 idx++; 00109 } 00110 if (has_blend && (num_blends > 0)) { 00111 if (((fvf & D3DFVF_XYZB5) == D3DFVF_XYZB2) && (fvf & D3DFVF_LASTBETA_D3DCOLOR)) 00112 elements[idx].Type = D3DDECLTYPE_D3DCOLOR; 00113 else { 00114 switch(num_blends) { 00115 case 1: elements[idx].Type = D3DDECLTYPE_FLOAT1; break; 00116 case 2: elements[idx].Type = D3DDECLTYPE_FLOAT2; break; 00117 case 3: elements[idx].Type = D3DDECLTYPE_FLOAT3; break; 00118 case 4: elements[idx].Type = D3DDECLTYPE_FLOAT4; break; 00119 default: 00120 ERR("Unexpected amount of blend values: %u\n", num_blends); 00121 } 00122 } 00123 elements[idx].Usage = D3DDECLUSAGE_BLENDWEIGHT; 00124 elements[idx].UsageIndex = 0; 00125 idx++; 00126 } 00127 if (has_blend_idx) { 00128 if (fvf & D3DFVF_LASTBETA_UBYTE4 || 00129 (((fvf & D3DFVF_XYZB5) == D3DFVF_XYZB2) && (fvf & D3DFVF_LASTBETA_D3DCOLOR))) 00130 elements[idx].Type = D3DDECLTYPE_UBYTE4; 00131 else if (fvf & D3DFVF_LASTBETA_D3DCOLOR) 00132 elements[idx].Type = D3DDECLTYPE_D3DCOLOR; 00133 else 00134 elements[idx].Type = D3DDECLTYPE_FLOAT1; 00135 elements[idx].Usage = D3DDECLUSAGE_BLENDINDICES; 00136 elements[idx].UsageIndex = 0; 00137 idx++; 00138 } 00139 if (has_normal) { 00140 elements[idx].Type = D3DDECLTYPE_FLOAT3; 00141 elements[idx].Usage = D3DDECLUSAGE_NORMAL; 00142 elements[idx].UsageIndex = 0; 00143 idx++; 00144 } 00145 if (has_psize) { 00146 elements[idx].Type = D3DDECLTYPE_FLOAT1; 00147 elements[idx].Usage = D3DDECLUSAGE_PSIZE; 00148 elements[idx].UsageIndex = 0; 00149 idx++; 00150 } 00151 if (has_diffuse) { 00152 elements[idx].Type = D3DDECLTYPE_D3DCOLOR; 00153 elements[idx].Usage = D3DDECLUSAGE_COLOR; 00154 elements[idx].UsageIndex = 0; 00155 idx++; 00156 } 00157 if (has_specular) { 00158 elements[idx].Type = D3DDECLTYPE_D3DCOLOR; 00159 elements[idx].Usage = D3DDECLUSAGE_COLOR; 00160 elements[idx].UsageIndex = 1; 00161 idx++; 00162 } 00163 for (idx2 = 0; idx2 < num_textures; idx2++) { 00164 unsigned int numcoords = (texcoords >> (idx2*2)) & 0x03; 00165 switch (numcoords) { 00166 case D3DFVF_TEXTUREFORMAT1: 00167 elements[idx].Type = D3DDECLTYPE_FLOAT1; 00168 break; 00169 case D3DFVF_TEXTUREFORMAT2: 00170 elements[idx].Type = D3DDECLTYPE_FLOAT2; 00171 break; 00172 case D3DFVF_TEXTUREFORMAT3: 00173 elements[idx].Type = D3DDECLTYPE_FLOAT3; 00174 break; 00175 case D3DFVF_TEXTUREFORMAT4: 00176 elements[idx].Type = D3DDECLTYPE_FLOAT4; 00177 break; 00178 } 00179 elements[idx].Usage = D3DDECLUSAGE_TEXCOORD; 00180 elements[idx].UsageIndex = idx2; 00181 idx++; 00182 } 00183 00184 /* Now compute offsets, and initialize the rest of the fields */ 00185 for (idx = 0, offset = 0; idx < size-1; idx++) { 00186 elements[idx].Stream = 0; 00187 elements[idx].Method = D3DDECLMETHOD_DEFAULT; 00188 elements[idx].Offset = offset; 00189 offset += D3D_DECL_SIZE(elements[idx].Type) * D3D_DECL_TYPESIZE(elements[idx].Type); 00190 } 00191 00192 *ppVertexElements = elements; 00193 return D3D_OK; 00194 } 00195 00196 /* IDirect3DVertexDeclaration9 IUnknown parts follow: */ 00197 static HRESULT WINAPI IDirect3DVertexDeclaration9Impl_QueryInterface(LPDIRECT3DVERTEXDECLARATION9 iface, REFIID riid, LPVOID* ppobj) { 00198 IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface; 00199 00200 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), ppobj); 00201 00202 if (IsEqualGUID(riid, &IID_IUnknown) 00203 || IsEqualGUID(riid, &IID_IDirect3DVertexDeclaration9)) { 00204 IDirect3DVertexDeclaration9_AddRef(iface); 00205 *ppobj = This; 00206 return S_OK; 00207 } 00208 00209 WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppobj); 00210 *ppobj = NULL; 00211 return E_NOINTERFACE; 00212 } 00213 00214 static ULONG WINAPI IDirect3DVertexDeclaration9Impl_AddRef(LPDIRECT3DVERTEXDECLARATION9 iface) { 00215 IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface; 00216 ULONG ref = InterlockedIncrement(&This->ref); 00217 00218 TRACE("%p increasing refcount to %u.\n", iface, ref); 00219 00220 if(ref == 1) { 00221 IDirect3DDevice9Ex_AddRef(This->parentDevice); 00222 if (!This->convFVF) 00223 { 00224 wined3d_mutex_lock(); 00225 wined3d_vertex_declaration_incref(This->wineD3DVertexDeclaration); 00226 wined3d_mutex_unlock(); 00227 } 00228 } 00229 00230 return ref; 00231 } 00232 00233 void IDirect3DVertexDeclaration9Impl_Destroy(LPDIRECT3DVERTEXDECLARATION9 iface) { 00234 IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface; 00235 00236 if(This->ref != 0) { 00237 /* Should not happen unless wine has a bug or the application releases references it does not own */ 00238 ERR("Destroying vdecl with ref != 0\n"); 00239 } 00240 00241 wined3d_mutex_lock(); 00242 wined3d_vertex_declaration_decref(This->wineD3DVertexDeclaration); 00243 wined3d_mutex_unlock(); 00244 } 00245 00246 static ULONG WINAPI IDirect3DVertexDeclaration9Impl_Release(LPDIRECT3DVERTEXDECLARATION9 iface) { 00247 IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface; 00248 ULONG ref = InterlockedDecrement(&This->ref); 00249 00250 TRACE("%p decreasing refcount to %u.\n", iface, ref); 00251 00252 if (ref == 0) { 00253 IDirect3DDevice9Ex *parentDevice = This->parentDevice; 00254 00255 if(!This->convFVF) { 00256 IDirect3DVertexDeclaration9Impl_Destroy(iface); 00257 } 00258 00259 /* Release the device last, as it may cause the device to be destroyed. */ 00260 IDirect3DDevice9Ex_Release(parentDevice); 00261 } 00262 return ref; 00263 } 00264 00265 /* IDirect3DVertexDeclaration9 Interface follow: */ 00266 static HRESULT WINAPI IDirect3DVertexDeclaration9Impl_GetDevice(IDirect3DVertexDeclaration9 *iface, 00267 IDirect3DDevice9 **device) 00268 { 00269 IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface; 00270 00271 TRACE("iface %p, device %p.\n", iface, device); 00272 00273 *device = (IDirect3DDevice9 *)This->parentDevice; 00274 IDirect3DDevice9_AddRef(*device); 00275 00276 TRACE("Returning device %p.\n", *device); 00277 00278 return D3D_OK; 00279 } 00280 00281 static HRESULT WINAPI IDirect3DVertexDeclaration9Impl_GetDeclaration(LPDIRECT3DVERTEXDECLARATION9 iface, D3DVERTEXELEMENT9* pDecl, UINT* pNumElements) { 00282 IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface; 00283 00284 TRACE("iface %p, elements %p, element_count %p.\n", iface, pDecl, pNumElements); 00285 00286 *pNumElements = This->element_count; 00287 00288 /* Passing a NULL pDecl is used to just retrieve the number of elements */ 00289 if (!pDecl) { 00290 TRACE("NULL pDecl passed. Returning D3D_OK.\n"); 00291 return D3D_OK; 00292 } 00293 00294 TRACE("Copying %p to %p\n", This->elements, pDecl); 00295 CopyMemory(pDecl, This->elements, This->element_count * sizeof(D3DVERTEXELEMENT9)); 00296 00297 return D3D_OK; 00298 } 00299 00300 static const IDirect3DVertexDeclaration9Vtbl Direct3DVertexDeclaration9_Vtbl = 00301 { 00302 /* IUnknown */ 00303 IDirect3DVertexDeclaration9Impl_QueryInterface, 00304 IDirect3DVertexDeclaration9Impl_AddRef, 00305 IDirect3DVertexDeclaration9Impl_Release, 00306 /* IDirect3DVertexDeclaration9 */ 00307 IDirect3DVertexDeclaration9Impl_GetDevice, 00308 IDirect3DVertexDeclaration9Impl_GetDeclaration 00309 }; 00310 00311 static void STDMETHODCALLTYPE d3d9_vertexdeclaration_wined3d_object_destroyed(void *parent) 00312 { 00313 IDirect3DVertexDeclaration9Impl *declaration = parent; 00314 HeapFree(GetProcessHeap(), 0, declaration->elements); 00315 HeapFree(GetProcessHeap(), 0, declaration); 00316 } 00317 00318 static const struct wined3d_parent_ops d3d9_vertexdeclaration_wined3d_parent_ops = 00319 { 00320 d3d9_vertexdeclaration_wined3d_object_destroyed, 00321 }; 00322 00323 static HRESULT convert_to_wined3d_declaration(const D3DVERTEXELEMENT9 *d3d9_elements, 00324 struct wined3d_vertex_element **wined3d_elements, UINT *element_count) 00325 { 00326 const D3DVERTEXELEMENT9* element; 00327 UINT count = 1; 00328 UINT i; 00329 00330 TRACE("d3d9_elements %p, wined3d_elements %p\n", d3d9_elements, wined3d_elements); 00331 00332 element = d3d9_elements; 00333 while (element++->Stream != 0xff && count++ < 128); 00334 00335 if (count == 128) return E_FAIL; 00336 00337 /* Skip the END element */ 00338 --count; 00339 00340 *wined3d_elements = HeapAlloc(GetProcessHeap(), 0, count * sizeof(**wined3d_elements)); 00341 if (!*wined3d_elements) { 00342 FIXME("Memory allocation failed\n"); 00343 return D3DERR_OUTOFVIDEOMEMORY; 00344 } 00345 00346 for (i = 0; i < count; ++i) 00347 { 00348 if (d3d9_elements[i].Type >= (sizeof(d3d_dtype_lookup) / sizeof(*d3d_dtype_lookup))) 00349 { 00350 WARN("Invalid element type %#x.\n", d3d9_elements[i].Type); 00351 HeapFree(GetProcessHeap(), 0, *wined3d_elements); 00352 return E_FAIL; 00353 } 00354 (*wined3d_elements)[i].format = d3d_dtype_lookup[d3d9_elements[i].Type].format; 00355 (*wined3d_elements)[i].input_slot = d3d9_elements[i].Stream; 00356 (*wined3d_elements)[i].offset = d3d9_elements[i].Offset; 00357 (*wined3d_elements)[i].output_slot = ~0U; 00358 (*wined3d_elements)[i].method = d3d9_elements[i].Method; 00359 (*wined3d_elements)[i].usage = d3d9_elements[i].Usage; 00360 (*wined3d_elements)[i].usage_idx = d3d9_elements[i].UsageIndex; 00361 } 00362 00363 *element_count = count; 00364 00365 return D3D_OK; 00366 } 00367 00368 HRESULT vertexdeclaration_init(IDirect3DVertexDeclaration9Impl *declaration, 00369 IDirect3DDevice9Impl *device, const D3DVERTEXELEMENT9 *elements) 00370 { 00371 struct wined3d_vertex_element *wined3d_elements; 00372 UINT wined3d_element_count; 00373 UINT element_count; 00374 HRESULT hr; 00375 00376 hr = convert_to_wined3d_declaration(elements, &wined3d_elements, &wined3d_element_count); 00377 if (FAILED(hr)) 00378 { 00379 WARN("Failed to create wined3d vertex declaration elements, hr %#x.\n", hr); 00380 return hr; 00381 } 00382 00383 declaration->lpVtbl = &Direct3DVertexDeclaration9_Vtbl; 00384 declaration->ref = 1; 00385 00386 element_count = wined3d_element_count + 1; 00387 declaration->elements = HeapAlloc(GetProcessHeap(), 0, element_count * sizeof(*declaration->elements)); 00388 if (!declaration->elements) 00389 { 00390 HeapFree(GetProcessHeap(), 0, wined3d_elements); 00391 ERR("Failed to allocate vertex declaration elements memory.\n"); 00392 return D3DERR_OUTOFVIDEOMEMORY; 00393 } 00394 memcpy(declaration->elements, elements, element_count * sizeof(*elements)); 00395 declaration->element_count = element_count; 00396 00397 wined3d_mutex_lock(); 00398 hr = wined3d_vertex_declaration_create(device->wined3d_device, wined3d_elements, wined3d_element_count, 00399 declaration, &d3d9_vertexdeclaration_wined3d_parent_ops, &declaration->wineD3DVertexDeclaration); 00400 wined3d_mutex_unlock(); 00401 HeapFree(GetProcessHeap(), 0, wined3d_elements); 00402 if (FAILED(hr)) 00403 { 00404 HeapFree(GetProcessHeap(), 0, declaration->elements); 00405 WARN("Failed to create wined3d vertex declaration, hr %#x.\n", hr); 00406 return hr; 00407 } 00408 00409 declaration->parentDevice = &device->IDirect3DDevice9Ex_iface; 00410 IDirect3DDevice9Ex_AddRef(declaration->parentDevice); 00411 00412 return D3D_OK; 00413 } Generated on Sat May 26 2012 04:20:41 for ReactOS by
1.7.6.1
|