ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

vertexdeclaration.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.