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  * vertex declaration implementation
00003  *
00004  * Copyright 2002-2005 Raphael Junqueira
00005  * Copyright 2004 Jason Edmeades
00006  * Copyright 2004 Christian Costa
00007  * Copyright 2005 Oliver Stieber
00008  * Copyright 2009 Henri Verbeet for CodeWeavers
00009  *
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00023  */
00024 
00025 #include "config.h"
00026 #include "wined3d_private.h"
00027 
00028 WINE_DEFAULT_DEBUG_CHANNEL(d3d_decl);
00029 
00030 static void dump_wined3d_vertex_element(const struct wined3d_vertex_element *element)
00031 {
00032     TRACE("     format: %s (%#x)\n", debug_d3dformat(element->format), element->format);
00033     TRACE(" input_slot: %u\n", element->input_slot);
00034     TRACE("     offset: %u\n", element->offset);
00035     TRACE("output_slot: %u\n", element->output_slot);
00036     TRACE("     method: %s (%#x)\n", debug_d3ddeclmethod(element->method), element->method);
00037     TRACE("      usage: %s (%#x)\n", debug_d3ddeclusage(element->usage), element->usage);
00038     TRACE("  usage_idx: %u\n", element->usage_idx);
00039 }
00040 
00041 ULONG CDECL wined3d_vertex_declaration_incref(struct wined3d_vertex_declaration *declaration)
00042 {
00043     ULONG refcount = InterlockedIncrement(&declaration->ref);
00044 
00045     TRACE("%p increasing refcount to %u.\n", declaration, refcount);
00046 
00047     return refcount;
00048 }
00049 
00050 ULONG CDECL wined3d_vertex_declaration_decref(struct wined3d_vertex_declaration *declaration)
00051 {
00052     ULONG refcount = InterlockedDecrement(&declaration->ref);
00053 
00054     TRACE("%p decreasing refcount to %u.\n", declaration, refcount);
00055 
00056     if (!refcount)
00057     {
00058         HeapFree(GetProcessHeap(), 0, declaration->elements);
00059         declaration->parent_ops->wined3d_object_destroyed(declaration->parent);
00060         HeapFree(GetProcessHeap(), 0, declaration);
00061     }
00062 
00063     return refcount;
00064 }
00065 
00066 void * CDECL wined3d_vertex_declaration_get_parent(const struct wined3d_vertex_declaration *declaration)
00067 {
00068     TRACE("declaration %p.\n", declaration);
00069 
00070     return declaration->parent;
00071 }
00072 
00073 static BOOL declaration_element_valid_ffp(const struct wined3d_vertex_element *element)
00074 {
00075     switch(element->usage)
00076     {
00077         case WINED3DDECLUSAGE_POSITION:
00078         case WINED3DDECLUSAGE_POSITIONT:
00079             switch(element->format)
00080             {
00081                 case WINED3DFMT_R32G32_FLOAT:
00082                 case WINED3DFMT_R32G32B32_FLOAT:
00083                 case WINED3DFMT_R32G32B32A32_FLOAT:
00084                 case WINED3DFMT_R16G16_SINT:
00085                 case WINED3DFMT_R16G16B16A16_SINT:
00086                 case WINED3DFMT_R16G16_FLOAT:
00087                 case WINED3DFMT_R16G16B16A16_FLOAT:
00088                     return TRUE;
00089                 default:
00090                     return FALSE;
00091             }
00092 
00093         case WINED3DDECLUSAGE_BLENDWEIGHT:
00094             switch(element->format)
00095             {
00096                 case WINED3DFMT_R32_FLOAT:
00097                 case WINED3DFMT_R32G32_FLOAT:
00098                 case WINED3DFMT_R32G32B32_FLOAT:
00099                 case WINED3DFMT_R32G32B32A32_FLOAT:
00100                 case WINED3DFMT_B8G8R8A8_UNORM:
00101                 case WINED3DFMT_R8G8B8A8_UINT:
00102                 case WINED3DFMT_R16G16_SINT:
00103                 case WINED3DFMT_R16G16B16A16_SINT:
00104                 case WINED3DFMT_R16G16_FLOAT:
00105                 case WINED3DFMT_R16G16B16A16_FLOAT:
00106                     return TRUE;
00107                 default:
00108                     return FALSE;
00109             }
00110 
00111         case WINED3DDECLUSAGE_NORMAL:
00112             switch(element->format)
00113             {
00114                 case WINED3DFMT_R32G32B32_FLOAT:
00115                 case WINED3DFMT_R32G32B32A32_FLOAT:
00116                 case WINED3DFMT_R16G16B16A16_SINT:
00117                 case WINED3DFMT_R16G16B16A16_FLOAT:
00118                     return TRUE;
00119                 default:
00120                     return FALSE;
00121             }
00122 
00123         case WINED3DDECLUSAGE_TEXCOORD:
00124             switch(element->format)
00125             {
00126                 case WINED3DFMT_R32_FLOAT:
00127                 case WINED3DFMT_R32G32_FLOAT:
00128                 case WINED3DFMT_R32G32B32_FLOAT:
00129                 case WINED3DFMT_R32G32B32A32_FLOAT:
00130                 case WINED3DFMT_R16G16_SINT:
00131                 case WINED3DFMT_R16G16B16A16_SINT:
00132                 case WINED3DFMT_R16G16_FLOAT:
00133                 case WINED3DFMT_R16G16B16A16_FLOAT:
00134                     return TRUE;
00135                 default:
00136                     return FALSE;
00137             }
00138 
00139         case WINED3DDECLUSAGE_COLOR:
00140             switch(element->format)
00141             {
00142                 case WINED3DFMT_R32G32B32_FLOAT:
00143                 case WINED3DFMT_R32G32B32A32_FLOAT:
00144                 case WINED3DFMT_B8G8R8A8_UNORM:
00145                 case WINED3DFMT_R8G8B8A8_UINT:
00146                 case WINED3DFMT_R16G16B16A16_SINT:
00147                 case WINED3DFMT_R8G8B8A8_UNORM:
00148                 case WINED3DFMT_R16G16B16A16_SNORM:
00149                 case WINED3DFMT_R16G16B16A16_UNORM:
00150                 case WINED3DFMT_R16G16B16A16_FLOAT:
00151                     return TRUE;
00152                 default:
00153                     return FALSE;
00154             }
00155 
00156         default:
00157             return FALSE;
00158     }
00159 }
00160 
00161 static HRESULT vertexdeclaration_init(struct wined3d_vertex_declaration *declaration,
00162         struct wined3d_device *device, const struct wined3d_vertex_element *elements, UINT element_count,
00163         void *parent, const struct wined3d_parent_ops *parent_ops)
00164 {
00165     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
00166     WORD preloaded = 0; /* MAX_STREAMS, 16 */
00167     unsigned int i;
00168 
00169     if (TRACE_ON(d3d_decl))
00170     {
00171         for (i = 0; i < element_count; ++i)
00172         {
00173             dump_wined3d_vertex_element(elements + i);
00174         }
00175     }
00176 
00177     declaration->ref = 1;
00178     declaration->parent = parent;
00179     declaration->parent_ops = parent_ops;
00180     declaration->device = device;
00181     declaration->elements = HeapAlloc(GetProcessHeap(), 0, sizeof(*declaration->elements) * element_count);
00182     if (!declaration->elements)
00183     {
00184         ERR("Failed to allocate elements memory.\n");
00185         return E_OUTOFMEMORY;
00186     }
00187     declaration->element_count = element_count;
00188 
00189     /* Do some static analysis on the elements to make reading the
00190      * declaration more comfortable for the drawing code. */
00191     for (i = 0; i < element_count; ++i)
00192     {
00193         struct wined3d_vertex_declaration_element *e = &declaration->elements[i];
00194 
00195         e->format = wined3d_get_format(gl_info, elements[i].format);
00196         e->ffp_valid = declaration_element_valid_ffp(&elements[i]);
00197         e->input_slot = elements[i].input_slot;
00198         e->offset = elements[i].offset;
00199         e->output_slot = elements[i].output_slot;
00200         e->method = elements[i].method;
00201         e->usage = elements[i].usage;
00202         e->usage_idx = elements[i].usage_idx;
00203 
00204         if (e->usage == WINED3DDECLUSAGE_POSITIONT) declaration->position_transformed = TRUE;
00205 
00206         /* Find the streams used in the declaration. The vertex buffers have
00207          * to be loaded when drawing, but filter tesselation pseudo streams. */
00208         if (e->input_slot >= MAX_STREAMS) continue;
00209 
00210         if (!e->format->gl_vtx_format)
00211         {
00212             FIXME("The application tries to use an unsupported format (%s), returning E_FAIL.\n",
00213                     debug_d3dformat(elements[i].format));
00214             HeapFree(GetProcessHeap(), 0, declaration->elements);
00215             return E_FAIL;
00216         }
00217 
00218         if (e->offset & 0x3)
00219         {
00220             WARN("Declaration element %u is not 4 byte aligned(%u), returning E_FAIL.\n", i, e->offset);
00221             HeapFree(GetProcessHeap(), 0, declaration->elements);
00222             return E_FAIL;
00223         }
00224 
00225         if (!(preloaded & (1 << e->input_slot)))
00226         {
00227             declaration->streams[declaration->num_streams] = e->input_slot;
00228             ++declaration->num_streams;
00229             preloaded |= 1 << e->input_slot;
00230         }
00231 
00232         if (elements[i].format == WINED3DFMT_R16G16_FLOAT || elements[i].format == WINED3DFMT_R16G16B16A16_FLOAT)
00233         {
00234             if (!gl_info->supported[ARB_HALF_FLOAT_VERTEX]) declaration->half_float_conv_needed = TRUE;
00235         }
00236     }
00237 
00238     return WINED3D_OK;
00239 }
00240 
00241 HRESULT CDECL wined3d_vertex_declaration_create(struct wined3d_device *device,
00242         const struct wined3d_vertex_element *elements, UINT element_count, void *parent,
00243         const struct wined3d_parent_ops *parent_ops, struct wined3d_vertex_declaration **declaration)
00244 {
00245     struct wined3d_vertex_declaration *object;
00246     HRESULT hr;
00247 
00248     TRACE("device %p, elements %p, element_count %u, parent %p, parent_ops %p, declaration %p.\n",
00249             device, elements, element_count, parent, parent_ops, declaration);
00250 
00251     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
00252     if(!object)
00253     {
00254         ERR("Failed to allocate vertex declaration memory.\n");
00255         return E_OUTOFMEMORY;
00256     }
00257 
00258     hr = vertexdeclaration_init(object, device, elements, element_count, parent, parent_ops);
00259     if (FAILED(hr))
00260     {
00261         WARN("Failed to initialize vertex declaration, hr %#x.\n", hr);
00262         HeapFree(GetProcessHeap(), 0, object);
00263         return hr;
00264     }
00265 
00266     TRACE("Created vertex declaration %p.\n", object);
00267     *declaration = object;
00268 
00269     return WINED3D_OK;
00270 }
00271 
00272 struct wined3d_fvf_convert_state
00273 {
00274     const struct wined3d_gl_info *gl_info;
00275     struct wined3d_vertex_element *elements;
00276     UINT offset;
00277     UINT idx;
00278 };
00279 
00280 static void append_decl_element(struct wined3d_fvf_convert_state *state,
00281         enum wined3d_format_id format_id, WINED3DDECLUSAGE usage, UINT usage_idx)
00282 {
00283     struct wined3d_vertex_element *elements = state->elements;
00284     const struct wined3d_format *format;
00285     UINT offset = state->offset;
00286     UINT idx = state->idx;
00287 
00288     elements[idx].format = format_id;
00289     elements[idx].input_slot = 0;
00290     elements[idx].offset = offset;
00291     elements[idx].output_slot = 0;
00292     elements[idx].method = WINED3DDECLMETHOD_DEFAULT;
00293     elements[idx].usage = usage;
00294     elements[idx].usage_idx = usage_idx;
00295 
00296     format = wined3d_get_format(state->gl_info, format_id);
00297     state->offset += format->component_count * format->component_size;
00298     ++state->idx;
00299 }
00300 
00301 static unsigned int convert_fvf_to_declaration(const struct wined3d_gl_info *gl_info,
00302         DWORD fvf, struct wined3d_vertex_element **elements)
00303 {
00304     BOOL has_pos = !!(fvf & WINED3DFVF_POSITION_MASK);
00305     BOOL has_blend = (fvf & WINED3DFVF_XYZB5) > WINED3DFVF_XYZRHW;
00306     BOOL has_blend_idx = has_blend &&
00307        (((fvf & WINED3DFVF_XYZB5) == WINED3DFVF_XYZB5) ||
00308         (fvf & WINED3DFVF_LASTBETA_D3DCOLOR) ||
00309         (fvf & WINED3DFVF_LASTBETA_UBYTE4));
00310     BOOL has_normal = !!(fvf & WINED3DFVF_NORMAL);
00311     BOOL has_psize = !!(fvf & WINED3DFVF_PSIZE);
00312     BOOL has_diffuse = !!(fvf & WINED3DFVF_DIFFUSE);
00313     BOOL has_specular = !!(fvf & WINED3DFVF_SPECULAR);
00314 
00315     DWORD num_textures = (fvf & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
00316     DWORD texcoords = (fvf & 0xFFFF0000) >> 16;
00317     struct wined3d_fvf_convert_state state;
00318     unsigned int size;
00319     unsigned int idx;
00320     DWORD num_blends = 1 + (((fvf & WINED3DFVF_XYZB5) - WINED3DFVF_XYZB1) >> 1);
00321     if (has_blend_idx) num_blends--;
00322 
00323     /* Compute declaration size */
00324     size = has_pos + (has_blend && num_blends > 0) + has_blend_idx + has_normal +
00325            has_psize + has_diffuse + has_specular + num_textures;
00326 
00327     state.gl_info = gl_info;
00328     state.elements = HeapAlloc(GetProcessHeap(), 0, size * sizeof(*state.elements));
00329     if (!state.elements) return ~0U;
00330     state.offset = 0;
00331     state.idx = 0;
00332 
00333     if (has_pos)
00334     {
00335         if (!has_blend && (fvf & WINED3DFVF_XYZRHW))
00336             append_decl_element(&state, WINED3DFMT_R32G32B32A32_FLOAT, WINED3DDECLUSAGE_POSITIONT, 0);
00337         else if ((fvf & WINED3DFVF_XYZW) == WINED3DFVF_XYZW)
00338             append_decl_element(&state, WINED3DFMT_R32G32B32A32_FLOAT, WINED3DDECLUSAGE_POSITION, 0);
00339         else
00340             append_decl_element(&state, WINED3DFMT_R32G32B32_FLOAT, WINED3DDECLUSAGE_POSITION, 0);
00341     }
00342 
00343     if (has_blend && (num_blends > 0))
00344     {
00345         if ((fvf & WINED3DFVF_XYZB5) == WINED3DFVF_XYZB2 && (fvf & WINED3DFVF_LASTBETA_D3DCOLOR))
00346             append_decl_element(&state, WINED3DFMT_B8G8R8A8_UNORM, WINED3DDECLUSAGE_BLENDWEIGHT, 0);
00347         else
00348         {
00349             switch (num_blends)
00350             {
00351                 case 1:
00352                     append_decl_element(&state, WINED3DFMT_R32_FLOAT, WINED3DDECLUSAGE_BLENDWEIGHT, 0);
00353                     break;
00354                 case 2:
00355                     append_decl_element(&state, WINED3DFMT_R32G32_FLOAT, WINED3DDECLUSAGE_BLENDWEIGHT, 0);
00356                     break;
00357                 case 3:
00358                     append_decl_element(&state, WINED3DFMT_R32G32B32_FLOAT, WINED3DDECLUSAGE_BLENDWEIGHT, 0);
00359                     break;
00360                 case 4:
00361                     append_decl_element(&state, WINED3DFMT_R32G32B32A32_FLOAT, WINED3DDECLUSAGE_BLENDWEIGHT, 0);
00362                     break;
00363                 default:
00364                     ERR("Unexpected amount of blend values: %u\n", num_blends);
00365             }
00366         }
00367     }
00368 
00369     if (has_blend_idx)
00370     {
00371         if ((fvf & WINED3DFVF_LASTBETA_UBYTE4)
00372                 || ((fvf & WINED3DFVF_XYZB5) == WINED3DFVF_XYZB2 && (fvf & WINED3DFVF_LASTBETA_D3DCOLOR)))
00373             append_decl_element(&state, WINED3DFMT_R8G8B8A8_UINT, WINED3DDECLUSAGE_BLENDINDICES, 0);
00374         else if (fvf & WINED3DFVF_LASTBETA_D3DCOLOR)
00375             append_decl_element(&state, WINED3DFMT_B8G8R8A8_UNORM, WINED3DDECLUSAGE_BLENDINDICES, 0);
00376         else
00377             append_decl_element(&state, WINED3DFMT_R32_FLOAT, WINED3DDECLUSAGE_BLENDINDICES, 0);
00378     }
00379 
00380     if (has_normal) append_decl_element(&state, WINED3DFMT_R32G32B32_FLOAT, WINED3DDECLUSAGE_NORMAL, 0);
00381     if (has_psize) append_decl_element(&state, WINED3DFMT_R32_FLOAT, WINED3DDECLUSAGE_PSIZE, 0);
00382     if (has_diffuse) append_decl_element(&state, WINED3DFMT_B8G8R8A8_UNORM, WINED3DDECLUSAGE_COLOR, 0);
00383     if (has_specular) append_decl_element(&state, WINED3DFMT_B8G8R8A8_UNORM, WINED3DDECLUSAGE_COLOR, 1);
00384 
00385     for (idx = 0; idx < num_textures; ++idx)
00386     {
00387         switch ((texcoords >> (idx * 2)) & 0x03)
00388         {
00389             case WINED3DFVF_TEXTUREFORMAT1:
00390                 append_decl_element(&state, WINED3DFMT_R32_FLOAT, WINED3DDECLUSAGE_TEXCOORD, idx);
00391                 break;
00392             case WINED3DFVF_TEXTUREFORMAT2:
00393                 append_decl_element(&state, WINED3DFMT_R32G32_FLOAT, WINED3DDECLUSAGE_TEXCOORD, idx);
00394                 break;
00395             case WINED3DFVF_TEXTUREFORMAT3:
00396                 append_decl_element(&state, WINED3DFMT_R32G32B32_FLOAT, WINED3DDECLUSAGE_TEXCOORD, idx);
00397                 break;
00398             case WINED3DFVF_TEXTUREFORMAT4:
00399                 append_decl_element(&state, WINED3DFMT_R32G32B32A32_FLOAT, WINED3DDECLUSAGE_TEXCOORD, idx);
00400                 break;
00401         }
00402     }
00403 
00404     *elements = state.elements;
00405     return size;
00406 }
00407 
00408 HRESULT CDECL wined3d_vertex_declaration_create_from_fvf(struct wined3d_device *device,
00409         DWORD fvf, void *parent, const struct wined3d_parent_ops *parent_ops,
00410         struct wined3d_vertex_declaration **declaration)
00411 {
00412     struct wined3d_vertex_element *elements;
00413     unsigned int size;
00414     DWORD hr;
00415 
00416     TRACE("device %p, fvf %#x, parent %p, parent_ops %p, declaration %p.\n",
00417             device, fvf, parent, parent_ops, declaration);
00418 
00419     size = convert_fvf_to_declaration(&device->adapter->gl_info, fvf, &elements);
00420     if (size == ~0U) return E_OUTOFMEMORY;
00421 
00422     hr = wined3d_vertex_declaration_create(device, elements, size, parent, parent_ops, declaration);
00423     HeapFree(GetProcessHeap(), 0, elements);
00424     return hr;
00425 }

Generated on Thu May 24 2012 04:22:25 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.