📄 slang_typeinfo.c
字号:
/* * Mesa 3-D graphics library * Version: 6.5 * * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *//** * \file slang_assemble_typeinfo.c * slang type info * \author Michal Krol */#include "main/imports.h"#include "shader/prog_instruction.h"#include "slang_typeinfo.h"#include "slang_compile.h"#include "slang_log.h"#include "slang_mem.h"/** * Checks if a field selector is a general swizzle (an r-value swizzle * with replicated components or an l-value swizzle mask) for a * vector. Returns GL_TRUE if this is the case, <swz> is filled with * swizzle information. Returns GL_FALSE otherwise. */GLboolean_slang_is_swizzle(const char *field, GLuint rows, slang_swizzle * swz){ GLuint i; GLboolean xyzw = GL_FALSE, rgba = GL_FALSE, stpq = GL_FALSE; /* init to undefined. * We rely on undefined/nil values to distinguish between * regular swizzles and writemasks. * For example, the swizzle ".xNNN" is the writemask ".x". * That's different than the swizzle ".xxxx". */ for (i = 0; i < 4; i++) swz->swizzle[i] = SWIZZLE_NIL; /* the swizzle can be at most 4-component long */ swz->num_components = slang_string_length(field); if (swz->num_components > 4) return GL_FALSE; for (i = 0; i < swz->num_components; i++) { /* mark which swizzle group is used */ switch (field[i]) { case 'x': case 'y': case 'z': case 'w': xyzw = GL_TRUE; break; case 'r': case 'g': case 'b': case 'a': rgba = GL_TRUE; break; case 's': case 't': case 'p': case 'q': stpq = GL_TRUE; break; default: return GL_FALSE; } /* collect swizzle component */ switch (field[i]) { case 'x': case 'r': case 's': swz->swizzle[i] = 0; break; case 'y': case 'g': case 't': swz->swizzle[i] = 1; break; case 'z': case 'b': case 'p': swz->swizzle[i] = 2; break; case 'w': case 'a': case 'q': swz->swizzle[i] = 3; break; } /* check if the component is valid for given vector's row count */ if (rows <= swz->swizzle[i]) return GL_FALSE; } /* only one swizzle group can be used */ if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq)) return GL_FALSE; return GL_TRUE;}/** * Checks if a general swizzle is an l-value swizzle - these swizzles * do not have duplicated fields. Returns GL_TRUE if this is a * swizzle mask. Returns GL_FALSE otherwise */GLboolean_slang_is_swizzle_mask(const slang_swizzle * swz, GLuint rows){ GLuint i, c = 0; /* the swizzle may not be longer than the vector dim */ if (swz->num_components > rows) return GL_FALSE; /* the swizzle components cannot be duplicated */ for (i = 0; i < swz->num_components; i++) { if ((c & (1 << swz->swizzle[i])) != 0) return GL_FALSE; c |= 1 << swz->swizzle[i]; } return GL_TRUE;}/** * Combines (multiplies) two swizzles to form single swizzle. * Example: "vec.wzyx.yx" --> "vec.zw". */GLvoid_slang_multiply_swizzles(slang_swizzle * dst, const slang_swizzle * left, const slang_swizzle * right){ GLuint i; dst->num_components = right->num_components; for (i = 0; i < right->num_components; i++) dst->swizzle[i] = left->swizzle[right->swizzle[i]];}GLvoidslang_type_specifier_ctr(slang_type_specifier * self){ self->type = SLANG_SPEC_VOID; self->_struct = NULL; self->_array = NULL;}GLvoidslang_type_specifier_dtr(slang_type_specifier * self){ if (self->_struct != NULL) { slang_struct_destruct(self->_struct); _slang_free(self->_struct); } if (self->_array != NULL) { slang_type_specifier_dtr(self->_array); _slang_free(self->_array); }}GLbooleanslang_type_specifier_copy(slang_type_specifier * x, const slang_type_specifier * y){ slang_type_specifier z; slang_type_specifier_ctr(&z); z.type = y->type; if (z.type == SLANG_SPEC_STRUCT) { z._struct = (slang_struct *) _slang_alloc(sizeof(slang_struct)); if (z._struct == NULL) { slang_type_specifier_dtr(&z); return GL_FALSE; } if (!slang_struct_construct(z._struct)) { _slang_free(z._struct); slang_type_specifier_dtr(&z); return GL_FALSE; } if (!slang_struct_copy(z._struct, y->_struct)) { slang_type_specifier_dtr(&z); return GL_FALSE; } } else if (z.type == SLANG_SPEC_ARRAY) { z._array = (slang_type_specifier *) _slang_alloc(sizeof(slang_type_specifier)); if (z._array == NULL) { slang_type_specifier_dtr(&z); return GL_FALSE; } slang_type_specifier_ctr(z._array); if (!slang_type_specifier_copy(z._array, y->_array)) { slang_type_specifier_dtr(&z); return GL_FALSE; } } slang_type_specifier_dtr(x); *x = z; return GL_TRUE;}/** * Test if two types are equal. */GLbooleanslang_type_specifier_equal(const slang_type_specifier * x, const slang_type_specifier * y){ if (x->type != y->type) return GL_FALSE; if (x->type == SLANG_SPEC_STRUCT) return slang_struct_equal(x->_struct, y->_struct); if (x->type == SLANG_SPEC_ARRAY) return slang_type_specifier_equal(x->_array, y->_array); return GL_TRUE;}/** * As above, but allow float/int casting. */static GLbooleanslang_type_specifier_compatible(const slang_type_specifier * x, const slang_type_specifier * y){ /* special case: float == int */ if (x->type == SLANG_SPEC_INT && y->type == SLANG_SPEC_FLOAT) { return GL_TRUE; } /* XXX may need to add bool/int compatibility, etc */ if (x->type != y->type) return GL_FALSE; if (x->type == SLANG_SPEC_STRUCT) return slang_struct_equal(x->_struct, y->_struct); if (x->type == SLANG_SPEC_ARRAY) return slang_type_specifier_compatible(x->_array, y->_array); return GL_TRUE;}GLbooleanslang_typeinfo_construct(slang_typeinfo * ti){ _mesa_bzero(ti, sizeof(*ti)); slang_type_specifier_ctr(&ti->spec); ti->array_len = 0; return GL_TRUE;}GLvoidslang_typeinfo_destruct(slang_typeinfo * ti){ slang_type_specifier_dtr(&ti->spec);}/** * Determine the return type of a function. * \param a_name the function name * \param param function parameters (overloading) * \param num_params number of parameters to function * \param space namespace to search * \param spec returns the type * \param funFound returns pointer to the function, or NULL if not found. * \return GL_TRUE for success, GL_FALSE if failure (bad function name) */static GLboolean_slang_typeof_function(slang_atom a_name, slang_operation * params, GLuint num_params, const slang_name_space * space, slang_type_specifier * spec, slang_function **funFound, slang_atom_pool *atoms, slang_info_log *log){ GLboolean error; *funFound = _slang_locate_function(space->funcs, a_name, params, num_params, space, atoms, log, &error); if (error) return GL_FALSE; if (!*funFound) return GL_TRUE; /* yes, not false */ return slang_type_specifier_copy(spec, &(*funFound)->header.type.specifier);}/** * Determine the type of a math function. * \param name name of the operator, one of +,-,*,/ or unary - * \param params array of function parameters * \param num_params number of parameters * \param space namespace to use * \param spec returns the function's type * \param atoms atom pool * \return GL_TRUE for success, GL_FALSE if failure */static GLbooleantypeof_math_call(const char *name, slang_operation *call, const slang_name_space * space, slang_type_specifier * spec, slang_atom_pool * atoms, slang_info_log *log){ if (call->fun) { /* we've previously resolved this function call */ slang_type_specifier_copy(spec, &call->fun->header.type.specifier); return GL_TRUE; } else { slang_atom atom; slang_function *fun; /* number of params: */ assert(call->num_children == 1 || call->num_children == 2); atom = slang_atom_pool_atom(atoms, name); if (!_slang_typeof_function(atom, call->children, call->num_children, space, spec, &fun, atoms, log)) return GL_FALSE; if (fun) { /* Save pointer to save time in future */ call->fun = fun;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -