Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenvertexdeclaration.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
1.7.6.1
|