Implement additional unary gentype builtins.
[mesa.git] / builtin_function.cpp
1 /*
2 * Copyright © 2010 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include <stdlib.h>
25 #include "glsl_symbol_table.h"
26 #include "glsl_parser_extras.h"
27 #include "glsl_types.h"
28 #include "ir.h"
29
30 static void
31 generate_unop(exec_list *instructions,
32 ir_variable **declarations,
33 const glsl_type *type,
34 enum ir_expression_operation op)
35 {
36 ir_dereference *const retval = new ir_dereference(declarations[16]);
37 ir_dereference *const arg = new ir_dereference(declarations[0]);
38 ir_rvalue *result;
39
40 result = new ir_expression(op, type, arg, NULL);
41
42 ir_instruction *inst = new ir_assignment(retval, result, NULL);
43 instructions->push_tail(inst);
44 }
45
46 static void
47 generate_exp(exec_list *instructions,
48 ir_variable **declarations,
49 const glsl_type *type)
50 {
51 generate_unop(instructions, declarations, type, ir_unop_exp);
52 }
53
54 static void
55 generate_log(exec_list *instructions,
56 ir_variable **declarations,
57 const glsl_type *type)
58 {
59 generate_unop(instructions, declarations, type, ir_unop_log);
60 }
61
62 static void
63 generate_rsq(exec_list *instructions,
64 ir_variable **declarations,
65 const glsl_type *type)
66 {
67 generate_unop(instructions, declarations, type, ir_unop_rsq);
68 }
69
70 static void
71 generate_abs(exec_list *instructions,
72 ir_variable **declarations,
73 const glsl_type *type)
74 {
75 generate_unop(instructions, declarations, type, ir_unop_abs);
76 }
77
78 static void
79 generate_ceil(exec_list *instructions,
80 ir_variable **declarations,
81 const glsl_type *type)
82 {
83 generate_unop(instructions, declarations, type, ir_unop_ceil);
84 }
85
86 static void
87 generate_floor(exec_list *instructions,
88 ir_variable **declarations,
89 const glsl_type *type)
90 {
91 generate_unop(instructions, declarations, type, ir_unop_floor);
92 }
93
94 void
95 generate_function_instance(ir_function *f,
96 const char *name,
97 exec_list *instructions,
98 void (*generate)(exec_list *instructions,
99 ir_variable **declarations,
100 const glsl_type *type),
101 const glsl_type *type)
102 {
103 ir_variable *declarations[17];
104
105 ir_function_signature *const sig = new ir_function_signature(type);
106 f->signatures.push_tail(sig);
107
108 ir_label *const label = new ir_label(name);
109 instructions->push_tail(label);
110 sig->definition = label;
111
112 ir_variable *var = new ir_variable(type, "arg");
113
114 var->mode = ir_var_in;
115 sig->parameters.push_tail(var);
116
117 var = new ir_variable(type, "arg");
118
119 declarations[0] = var;
120
121 ir_variable *retval = new ir_variable(type, "__retval");
122 instructions->push_tail(retval);
123
124 declarations[16] = retval;
125
126 generate(instructions, declarations, type);
127 }
128
129 void
130 make_gentype_function(glsl_symbol_table *symtab, exec_list *instructions,
131 const char *name,
132 void (*generate)(exec_list *instructions,
133 ir_variable **declarations,
134 const glsl_type *type))
135 {
136 ir_function *const f = new ir_function(name);
137 const glsl_type *vec2_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 2, 1);
138 const glsl_type *vec3_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 3, 1);
139 const glsl_type *vec4_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 4, 1);
140
141 bool added = symtab->add_function(name, f);
142 assert(added);
143
144 generate_function_instance(f, name, instructions, generate, glsl_type::float_type);
145 generate_function_instance(f, name, instructions, generate, vec2_type);
146 generate_function_instance(f, name, instructions, generate, vec3_type);
147 generate_function_instance(f, name, instructions, generate, vec4_type);
148 }
149
150 void
151 generate_110_functions(glsl_symbol_table *symtab, exec_list *instructions)
152 {
153 /* FINISHME: radians() */
154 /* FINISHME: degrees() */
155 /* FINISHME: sin() */
156 /* FINISHME: cos() */
157 /* FINISHME: tan() */
158 /* FINISHME: asin() */
159 /* FINISHME: acos() */
160 /* FINISHME: atan(y,x) */
161 /* FINISHME: atan(y/x) */
162 /* FINISHME: pow() */
163 make_gentype_function(symtab, instructions, "exp", generate_exp);
164 make_gentype_function(symtab, instructions, "log", generate_log);
165 /* FINISHME: exp2() */
166 /* FINISHME: log2() */
167 /* FINISHME: sqrt() */
168 make_gentype_function(symtab, instructions, "inversesqrt", generate_rsq);
169 make_gentype_function(symtab, instructions, "abs", generate_abs);
170 /* FINISHME: sign() */
171 make_gentype_function(symtab, instructions, "floor", generate_floor);
172 make_gentype_function(symtab, instructions, "ceil", generate_ceil);
173 /* FINISHME: fract() */
174 /* FINISHME: mod(x, float y) */
175 /* FINISHME: mod(x, y) */
176 /* FINISHME: min() */
177 /* FINISHME: max() */
178 /* FINISHME: clamp() */
179 /* FINISHME: clamp() */
180 /* FINISHME: mix() */
181 /* FINISHME: mix() */
182 /* FINISHME: step() */
183 /* FINISHME: step() */
184 /* FINISHME: smoothstep() */
185 /* FINISHME: smoothstep() */
186 /* FINISHME: floor() */
187 /* FINISHME: step() */
188 /* FINISHME: length() */
189 /* FINISHME: distance() */
190 /* FINISHME: dot() */
191 /* FINISHME: cross() */
192 /* FINISHME: normalize() */
193 /* FINISHME: ftransform() */
194 /* FINISHME: faceforward() */
195 /* FINISHME: reflect() */
196 /* FINISHME: refract() */
197 /* FINISHME: matrixCompMult() */
198 /* FINISHME: lessThan() */
199 /* FINISHME: lessThanEqual() */
200 /* FINISHME: greaterThan() */
201 /* FINISHME: greaterThanEqual() */
202 /* FINISHME: equal() */
203 /* FINISHME: notEqual() */
204 /* FINISHME: any() */
205 /* FINISHME: all() */
206 /* FINISHME: not() */
207 /* FINISHME: texture*() */
208 /* FINISHME: shadow*() */
209 /* FINISHME: dFd[xy]() */
210 /* FINISHME: fwidth() */
211 }
212
213 void
214 _mesa_glsl_initialize_functions(exec_list *instructions,
215 struct _mesa_glsl_parse_state *state)
216 {
217 generate_110_functions(state->symbols, instructions);
218 }