Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5563 | serge | 1 | /* |
2 | * Copyright (C) 2010 Brian Paul All Rights Reserved. |
||
3 | * Copyright (C) 2010 Intel Corporation |
||
4 | * |
||
5 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
6 | * copy of this software and associated documentation files (the "Software"), |
||
7 | * to deal in the Software without restriction, including without limitation |
||
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
9 | * and/or sell copies of the Software, and to permit persons to whom the |
||
10 | * Software is furnished to do so, subject to the following conditions: |
||
11 | * |
||
12 | * The above copyright notice and this permission notice shall be included |
||
13 | * in all copies or substantial portions of the Software. |
||
14 | * |
||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||
16 | * OR 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 |
||
19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
||
20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
||
21 | * OTHER DEALINGS IN THE SOFTWARE. |
||
22 | * |
||
23 | * Author: Kristian Høgsberg |
||
24 | */ |
||
25 | |||
26 | #include "glheader.h" |
||
27 | #include "context.h" |
||
28 | #include "blend.h" |
||
29 | #include "enable.h" |
||
30 | #include "enums.h" |
||
31 | #include "extensions.h" |
||
32 | #include "get.h" |
||
33 | #include "macros.h" |
||
34 | #include "mtypes.h" |
||
35 | #include "state.h" |
||
36 | #include "texcompress.h" |
||
37 | #include "framebuffer.h" |
||
38 | #include "samplerobj.h" |
||
39 | #include "stencil.h" |
||
40 | |||
41 | /* This is a table driven implemetation of the glGet*v() functions. |
||
42 | * The basic idea is that most getters just look up an int somewhere |
||
43 | * in struct gl_context and then convert it to a bool or float according to |
||
44 | * which of glGetIntegerv() glGetBooleanv() etc is being called. |
||
45 | * Instead of generating code to do this, we can just record the enum |
||
46 | * value and the offset into struct gl_context in an array of structs. Then |
||
47 | * in glGet*(), we lookup the struct for the enum in question, and use |
||
48 | * the offset to get the int we need. |
||
49 | * |
||
50 | * Sometimes we need to look up a float, a boolean, a bit in a |
||
51 | * bitfield, a matrix or other types instead, so we need to track the |
||
52 | * type of the value in struct gl_context. And sometimes the value isn't in |
||
53 | * struct gl_context but in the drawbuffer, the array object, current texture |
||
54 | * unit, or maybe it's a computed value. So we need to also track |
||
55 | * where or how to find the value. Finally, we sometimes need to |
||
56 | * check that one of a number of extensions are enabled, the GL |
||
57 | * version or flush or call _mesa_update_state(). This is done by |
||
58 | * attaching optional extra information to the value description |
||
59 | * struct, it's sort of like an array of opcodes that describe extra |
||
60 | * checks or actions. |
||
61 | * |
||
62 | * Putting all this together we end up with struct value_desc below, |
||
63 | * and with a couple of macros to help, the table of struct value_desc |
||
64 | * is about as concise as the specification in the old python script. |
||
65 | */ |
||
66 | |||
67 | #define FLOAT_TO_BOOLEAN(X) ( (X) ? GL_TRUE : GL_FALSE ) |
||
68 | #define FLOAT_TO_FIXED(F) ( ((F) * 65536.0f > INT_MAX) ? INT_MAX : \ |
||
69 | ((F) * 65536.0f < INT_MIN) ? INT_MIN : \ |
||
70 | (GLint) ((F) * 65536.0f) ) |
||
71 | |||
72 | #define INT_TO_BOOLEAN(I) ( (I) ? GL_TRUE : GL_FALSE ) |
||
73 | #define INT_TO_FIXED(I) ( ((I) > SHRT_MAX) ? INT_MAX : \ |
||
74 | ((I) < SHRT_MIN) ? INT_MIN : \ |
||
75 | (GLint) ((I) * 65536) ) |
||
76 | |||
77 | #define INT64_TO_BOOLEAN(I) ( (I) ? GL_TRUE : GL_FALSE ) |
||
78 | #define INT64_TO_INT(I) ( (GLint)((I > INT_MAX) ? INT_MAX : ((I < INT_MIN) ? INT_MIN : (I))) ) |
||
79 | |||
80 | #define BOOLEAN_TO_INT(B) ( (GLint) (B) ) |
||
81 | #define BOOLEAN_TO_INT64(B) ( (GLint64) (B) ) |
||
82 | #define BOOLEAN_TO_FLOAT(B) ( (B) ? 1.0F : 0.0F ) |
||
83 | #define BOOLEAN_TO_FIXED(B) ( (GLint) ((B) ? 1 : 0) << 16 ) |
||
84 | |||
85 | #define ENUM_TO_INT64(E) ( (GLint64) (E) ) |
||
86 | #define ENUM_TO_FIXED(E) (E) |
||
87 | |||
88 | enum value_type { |
||
89 | TYPE_INVALID, |
||
90 | TYPE_INT, |
||
91 | TYPE_INT_2, |
||
92 | TYPE_INT_3, |
||
93 | TYPE_INT_4, |
||
94 | TYPE_INT_N, |
||
95 | TYPE_INT64, |
||
96 | TYPE_ENUM, |
||
97 | TYPE_ENUM_2, |
||
98 | TYPE_BOOLEAN, |
||
99 | TYPE_BIT_0, |
||
100 | TYPE_BIT_1, |
||
101 | TYPE_BIT_2, |
||
102 | TYPE_BIT_3, |
||
103 | TYPE_BIT_4, |
||
104 | TYPE_BIT_5, |
||
105 | TYPE_BIT_6, |
||
106 | TYPE_BIT_7, |
||
107 | TYPE_FLOAT, |
||
108 | TYPE_FLOAT_2, |
||
109 | TYPE_FLOAT_3, |
||
110 | TYPE_FLOAT_4, |
||
111 | TYPE_FLOATN, |
||
112 | TYPE_FLOATN_2, |
||
113 | TYPE_FLOATN_3, |
||
114 | TYPE_FLOATN_4, |
||
115 | TYPE_DOUBLEN, |
||
116 | TYPE_MATRIX, |
||
117 | TYPE_MATRIX_T, |
||
118 | TYPE_CONST |
||
119 | }; |
||
120 | |||
121 | enum value_location { |
||
122 | LOC_BUFFER, |
||
123 | LOC_CONTEXT, |
||
124 | LOC_ARRAY, |
||
125 | LOC_TEXUNIT, |
||
126 | LOC_CUSTOM |
||
127 | }; |
||
128 | |||
129 | enum value_extra { |
||
130 | EXTRA_END = 0x8000, |
||
131 | EXTRA_VERSION_30, |
||
132 | EXTRA_VERSION_31, |
||
133 | EXTRA_VERSION_32, |
||
134 | EXTRA_API_GL, |
||
135 | EXTRA_API_GL_CORE, |
||
136 | EXTRA_API_ES2, |
||
137 | EXTRA_API_ES3, |
||
138 | EXTRA_NEW_BUFFERS, |
||
139 | EXTRA_NEW_FRAG_CLAMP, |
||
140 | EXTRA_VALID_DRAW_BUFFER, |
||
141 | EXTRA_VALID_TEXTURE_UNIT, |
||
142 | EXTRA_VALID_CLIP_DISTANCE, |
||
143 | EXTRA_FLUSH_CURRENT, |
||
144 | EXTRA_GLSL_130, |
||
145 | EXTRA_EXT_UBO_GS4, |
||
146 | }; |
||
147 | |||
148 | #define NO_EXTRA NULL |
||
149 | #define NO_OFFSET 0 |
||
150 | |||
151 | struct value_desc { |
||
152 | GLenum pname; |
||
153 | GLubyte location; /**< enum value_location */ |
||
154 | GLubyte type; /**< enum value_type */ |
||
155 | int offset; |
||
156 | const int *extra; |
||
157 | }; |
||
158 | |||
159 | union value { |
||
160 | GLfloat value_float; |
||
161 | GLfloat value_float_4[4]; |
||
162 | GLmatrix *value_matrix; |
||
163 | GLint value_int; |
||
164 | GLint value_int_4[4]; |
||
165 | GLint64 value_int64; |
||
166 | GLenum value_enum; |
||
167 | |||
168 | /* Sigh, see GL_COMPRESSED_TEXTURE_FORMATS_ARB handling */ |
||
169 | struct { |
||
170 | GLint n, ints[100]; |
||
171 | } value_int_n; |
||
172 | GLboolean value_bool; |
||
173 | }; |
||
174 | |||
175 | #define BUFFER_FIELD(field, type) \ |
||
176 | LOC_BUFFER, type, offsetof(struct gl_framebuffer, field) |
||
177 | #define CONTEXT_FIELD(field, type) \ |
||
178 | LOC_CONTEXT, type, offsetof(struct gl_context, field) |
||
179 | #define ARRAY_FIELD(field, type) \ |
||
180 | LOC_ARRAY, type, offsetof(struct gl_array_object, field) |
||
181 | #undef CONST /* already defined through windows.h */ |
||
182 | #define CONST(value) \ |
||
183 | LOC_CONTEXT, TYPE_CONST, value |
||
184 | |||
185 | #define BUFFER_INT(field) BUFFER_FIELD(field, TYPE_INT) |
||
186 | #define BUFFER_ENUM(field) BUFFER_FIELD(field, TYPE_ENUM) |
||
187 | #define BUFFER_BOOL(field) BUFFER_FIELD(field, TYPE_BOOLEAN) |
||
188 | |||
189 | #define CONTEXT_INT(field) CONTEXT_FIELD(field, TYPE_INT) |
||
190 | #define CONTEXT_INT2(field) CONTEXT_FIELD(field, TYPE_INT_2) |
||
191 | #define CONTEXT_INT64(field) CONTEXT_FIELD(field, TYPE_INT64) |
||
192 | #define CONTEXT_ENUM(field) CONTEXT_FIELD(field, TYPE_ENUM) |
||
193 | #define CONTEXT_ENUM2(field) CONTEXT_FIELD(field, TYPE_ENUM_2) |
||
194 | #define CONTEXT_BOOL(field) CONTEXT_FIELD(field, TYPE_BOOLEAN) |
||
195 | #define CONTEXT_BIT0(field) CONTEXT_FIELD(field, TYPE_BIT_0) |
||
196 | #define CONTEXT_BIT1(field) CONTEXT_FIELD(field, TYPE_BIT_1) |
||
197 | #define CONTEXT_BIT2(field) CONTEXT_FIELD(field, TYPE_BIT_2) |
||
198 | #define CONTEXT_BIT3(field) CONTEXT_FIELD(field, TYPE_BIT_3) |
||
199 | #define CONTEXT_BIT4(field) CONTEXT_FIELD(field, TYPE_BIT_4) |
||
200 | #define CONTEXT_BIT5(field) CONTEXT_FIELD(field, TYPE_BIT_5) |
||
201 | #define CONTEXT_BIT6(field) CONTEXT_FIELD(field, TYPE_BIT_6) |
||
202 | #define CONTEXT_BIT7(field) CONTEXT_FIELD(field, TYPE_BIT_7) |
||
203 | #define CONTEXT_FLOAT(field) CONTEXT_FIELD(field, TYPE_FLOAT) |
||
204 | #define CONTEXT_FLOAT2(field) CONTEXT_FIELD(field, TYPE_FLOAT_2) |
||
205 | #define CONTEXT_FLOAT3(field) CONTEXT_FIELD(field, TYPE_FLOAT_3) |
||
206 | #define CONTEXT_FLOAT4(field) CONTEXT_FIELD(field, TYPE_FLOAT_4) |
||
207 | #define CONTEXT_MATRIX(field) CONTEXT_FIELD(field, TYPE_MATRIX) |
||
208 | #define CONTEXT_MATRIX_T(field) CONTEXT_FIELD(field, TYPE_MATRIX_T) |
||
209 | |||
210 | #define ARRAY_INT(field) ARRAY_FIELD(field, TYPE_INT) |
||
211 | #define ARRAY_ENUM(field) ARRAY_FIELD(field, TYPE_ENUM) |
||
212 | #define ARRAY_BOOL(field) ARRAY_FIELD(field, TYPE_BOOLEAN) |
||
213 | |||
214 | #define EXT(f) \ |
||
215 | offsetof(struct gl_extensions, f) |
||
216 | |||
217 | #define EXTRA_EXT(e) \ |
||
218 | static const int extra_##e[] = { \ |
||
219 | EXT(e), EXTRA_END \ |
||
220 | } |
||
221 | |||
222 | #define EXTRA_EXT2(e1, e2) \ |
||
223 | static const int extra_##e1##_##e2[] = { \ |
||
224 | EXT(e1), EXT(e2), EXTRA_END \ |
||
225 | } |
||
226 | |||
227 | /* The 'extra' mechanism is a way to specify extra checks (such as |
||
228 | * extensions or specific gl versions) or actions (flush current, new |
||
229 | * buffers) that we need to do before looking up an enum. We need to |
||
230 | * declare them all up front so we can refer to them in the value_desc |
||
231 | * structs below. |
||
232 | * |
||
233 | * Each EXTRA_ will be executed. For EXTRA_* enums of extensions and API |
||
234 | * versions, listing multiple ones in an array means an error will be thrown |
||
235 | * only if none of them are available. If you need to check for "AND" |
||
236 | * behavior, you would need to make a custom EXTRA_ enum. |
||
237 | */ |
||
238 | |||
239 | static const int extra_new_buffers[] = { |
||
240 | EXTRA_NEW_BUFFERS, |
||
241 | EXTRA_END |
||
242 | }; |
||
243 | |||
244 | static const int extra_new_frag_clamp[] = { |
||
245 | EXTRA_NEW_FRAG_CLAMP, |
||
246 | EXTRA_END |
||
247 | }; |
||
248 | |||
249 | static const int extra_valid_draw_buffer[] = { |
||
250 | EXTRA_VALID_DRAW_BUFFER, |
||
251 | EXTRA_END |
||
252 | }; |
||
253 | |||
254 | static const int extra_valid_texture_unit[] = { |
||
255 | EXTRA_VALID_TEXTURE_UNIT, |
||
256 | EXTRA_END |
||
257 | }; |
||
258 | |||
259 | static const int extra_valid_clip_distance[] = { |
||
260 | EXTRA_VALID_CLIP_DISTANCE, |
||
261 | EXTRA_END |
||
262 | }; |
||
263 | |||
264 | static const int extra_flush_current_valid_texture_unit[] = { |
||
265 | EXTRA_FLUSH_CURRENT, |
||
266 | EXTRA_VALID_TEXTURE_UNIT, |
||
267 | EXTRA_END |
||
268 | }; |
||
269 | |||
270 | static const int extra_flush_current[] = { |
||
271 | EXTRA_FLUSH_CURRENT, |
||
272 | EXTRA_END |
||
273 | }; |
||
274 | |||
275 | static const int extra_EXT_texture_integer[] = { |
||
276 | EXT(EXT_texture_integer), |
||
277 | EXTRA_END |
||
278 | }; |
||
279 | |||
280 | static const int extra_EXT_texture_integer_and_new_buffers[] = { |
||
281 | EXT(EXT_texture_integer), |
||
282 | EXTRA_NEW_BUFFERS, |
||
283 | EXTRA_END |
||
284 | }; |
||
285 | |||
286 | static const int extra_GLSL_130_es3[] = { |
||
287 | EXTRA_GLSL_130, |
||
288 | EXTRA_API_ES3, |
||
289 | EXTRA_END |
||
290 | }; |
||
291 | |||
292 | static const int extra_texture_buffer_object[] = { |
||
293 | EXTRA_API_GL_CORE, |
||
294 | EXTRA_VERSION_31, |
||
295 | EXT(ARB_texture_buffer_object), |
||
296 | EXTRA_END |
||
297 | }; |
||
298 | |||
299 | static const int extra_ARB_transform_feedback2_api_es3[] = { |
||
300 | EXT(ARB_transform_feedback2), |
||
301 | EXTRA_API_ES3, |
||
302 | EXTRA_END |
||
303 | }; |
||
304 | |||
305 | static const int extra_ARB_uniform_buffer_object_and_geometry_shader[] = { |
||
306 | EXTRA_EXT_UBO_GS4, |
||
307 | EXTRA_END |
||
308 | }; |
||
309 | |||
310 | static const int extra_ARB_ES2_compatibility_api_es2[] = { |
||
311 | EXT(ARB_ES2_compatibility), |
||
312 | EXTRA_API_ES2, |
||
313 | EXTRA_END |
||
314 | }; |
||
315 | |||
316 | static const int extra_ARB_ES3_compatibility_api_es3[] = { |
||
317 | EXT(ARB_ES3_compatibility), |
||
318 | EXTRA_API_ES3, |
||
319 | EXTRA_END |
||
320 | }; |
||
321 | |||
322 | static const int extra_EXT_framebuffer_sRGB_and_new_buffers[] = { |
||
323 | EXT(EXT_framebuffer_sRGB), |
||
324 | EXTRA_NEW_BUFFERS, |
||
325 | EXTRA_END |
||
326 | }; |
||
327 | |||
328 | static const int extra_MESA_texture_array_es3[] = { |
||
329 | EXT(MESA_texture_array), |
||
330 | EXTRA_API_ES3, |
||
331 | EXTRA_END |
||
332 | }; |
||
333 | |||
334 | EXTRA_EXT(ARB_texture_cube_map); |
||
335 | EXTRA_EXT(MESA_texture_array); |
||
336 | EXTRA_EXT(NV_fog_distance); |
||
337 | EXTRA_EXT(EXT_texture_filter_anisotropic); |
||
338 | EXTRA_EXT(NV_point_sprite); |
||
339 | EXTRA_EXT(NV_texture_rectangle); |
||
340 | EXTRA_EXT(EXT_stencil_two_side); |
||
341 | EXTRA_EXT(EXT_depth_bounds_test); |
||
342 | EXTRA_EXT(ARB_depth_clamp); |
||
343 | EXTRA_EXT(ATI_fragment_shader); |
||
344 | EXTRA_EXT(EXT_framebuffer_blit); |
||
345 | EXTRA_EXT(EXT_provoking_vertex); |
||
346 | EXTRA_EXT(ARB_fragment_shader); |
||
347 | EXTRA_EXT(ARB_fragment_program); |
||
348 | EXTRA_EXT2(ARB_framebuffer_object, EXT_framebuffer_multisample); |
||
349 | EXTRA_EXT(ARB_seamless_cube_map); |
||
350 | EXTRA_EXT(ARB_sync); |
||
351 | EXTRA_EXT(ARB_vertex_shader); |
||
352 | EXTRA_EXT(EXT_transform_feedback); |
||
353 | EXTRA_EXT(ARB_transform_feedback3); |
||
354 | EXTRA_EXT(EXT_pixel_buffer_object); |
||
355 | EXTRA_EXT(ARB_vertex_program); |
||
356 | EXTRA_EXT2(NV_point_sprite, ARB_point_sprite); |
||
357 | EXTRA_EXT2(ARB_vertex_program, ARB_fragment_program); |
||
358 | EXTRA_EXT(ARB_geometry_shader4); |
||
359 | EXTRA_EXT(ARB_color_buffer_float); |
||
360 | EXTRA_EXT(EXT_framebuffer_sRGB); |
||
361 | EXTRA_EXT(OES_EGL_image_external); |
||
362 | EXTRA_EXT(ARB_blend_func_extended); |
||
363 | EXTRA_EXT(ARB_uniform_buffer_object); |
||
364 | EXTRA_EXT(ARB_timer_query); |
||
365 | EXTRA_EXT(ARB_map_buffer_alignment); |
||
366 | EXTRA_EXT(ARB_texture_cube_map_array); |
||
367 | EXTRA_EXT(ARB_texture_buffer_range); |
||
368 | EXTRA_EXT(ARB_texture_multisample); |
||
369 | |||
370 | static const int |
||
371 | extra_ARB_color_buffer_float_or_glcore[] = { |
||
372 | EXT(ARB_color_buffer_float), |
||
373 | EXTRA_API_GL_CORE, |
||
374 | EXTRA_END |
||
375 | }; |
||
376 | |||
377 | static const int |
||
378 | extra_NV_primitive_restart[] = { |
||
379 | EXT(NV_primitive_restart), |
||
380 | EXTRA_END |
||
381 | }; |
||
382 | |||
383 | static const int extra_version_30[] = { EXTRA_VERSION_30, EXTRA_END }; |
||
384 | static const int extra_version_31[] = { EXTRA_VERSION_31, EXTRA_END }; |
||
385 | static const int extra_version_32[] = { EXTRA_VERSION_32, EXTRA_END }; |
||
386 | |||
387 | static const int extra_gl30_es3[] = { |
||
388 | EXTRA_VERSION_30, |
||
389 | EXTRA_API_ES3, |
||
390 | EXTRA_END, |
||
391 | }; |
||
392 | |||
393 | static const int extra_gl32_es3[] = { |
||
394 | EXTRA_VERSION_32, |
||
395 | EXTRA_API_ES3, |
||
396 | EXTRA_END, |
||
397 | }; |
||
398 | |||
399 | static const int |
||
400 | extra_ARB_vertex_program_api_es2[] = { |
||
401 | EXT(ARB_vertex_program), |
||
402 | EXTRA_API_ES2, |
||
403 | EXTRA_END |
||
404 | }; |
||
405 | |||
406 | /* The ReadBuffer get token is valid under either full GL or under |
||
407 | * GLES2 if the NV_read_buffer extension is available. */ |
||
408 | static const int |
||
409 | extra_NV_read_buffer_api_gl[] = { |
||
410 | EXTRA_API_ES2, |
||
411 | EXTRA_API_GL, |
||
412 | EXTRA_END |
||
413 | }; |
||
414 | |||
415 | static const int extra_core_ARB_color_buffer_float_and_new_buffers[] = { |
||
416 | EXTRA_API_GL_CORE, |
||
417 | EXT(ARB_color_buffer_float), |
||
418 | EXTRA_NEW_BUFFERS, |
||
419 | EXTRA_END |
||
420 | }; |
||
421 | |||
422 | /* This is the big table describing all the enums we accept in |
||
423 | * glGet*v(). The table is partitioned into six parts: enums |
||
424 | * understood by all GL APIs (OpenGL, GLES and GLES2), enums shared |
||
425 | * between OpenGL and GLES, enums exclusive to GLES, etc for the |
||
426 | * remaining combinations. To look up the enums valid in a given API |
||
427 | * we will use a hash table specific to that API. These tables are in |
||
428 | * turn generated at build time and included through get_hash.h. |
||
429 | */ |
||
430 | |||
431 | #include "get_hash.h" |
||
432 | |||
433 | /* All we need now is a way to look up the value struct from the enum. |
||
434 | * The code generated by gcc for the old generated big switch |
||
435 | * statement is a big, balanced, open coded if/else tree, essentially |
||
436 | * an unrolled binary search. It would be natural to sort the new |
||
437 | * enum table and use bsearch(), but we will use a read-only hash |
||
438 | * table instead. bsearch() has a nice guaranteed worst case |
||
439 | * performance, but we're also guaranteed to hit that worst case |
||
440 | * (log2(n) iterations) for about half the enums. Instead, using an |
||
441 | * open addressing hash table, we can find the enum on the first try |
||
442 | * for 80% of the enums, 1 collision for 10% and never more than 5 |
||
443 | * collisions for any enum (typical numbers). And the code is very |
||
444 | * simple, even though it feels a little magic. */ |
||
445 | |||
446 | #ifdef GET_DEBUG |
||
447 | static void |
||
448 | print_table_stats(int api) |
||
449 | { |
||
450 | int i, j, collisions[11], count, hash, mask; |
||
451 | const struct value_desc *d; |
||
452 | const char *api_names[] = { |
||
453 | [API_OPENGL_COMPAT] = "GL", |
||
454 | [API_OPENGL_CORE] = "GL_CORE", |
||
455 | [API_OPENGLES] = "GLES", |
||
456 | [API_OPENGLES2] = "GLES2", |
||
457 | }; |
||
458 | const char *api_name; |
||
459 | |||
460 | api_name = api < Elements(api_names) ? api_names[api] : "N/A"; |
||
461 | count = 0; |
||
462 | mask = Elements(table(api)) - 1; |
||
463 | memset(collisions, 0, sizeof collisions); |
||
464 | |||
465 | for (i = 0; i < Elements(table(api)); i++) { |
||
466 | if (!table(api)[i]) |
||
467 | continue; |
||
468 | count++; |
||
469 | d = &values[table(api)[i]]; |
||
470 | hash = (d->pname * prime_factor); |
||
471 | j = 0; |
||
472 | while (1) { |
||
473 | if (values[table(api)[hash & mask]].pname == d->pname) |
||
474 | break; |
||
475 | hash += prime_step; |
||
476 | j++; |
||
477 | } |
||
478 | |||
479 | if (j < 10) |
||
480 | collisions[j]++; |
||
481 | else |
||
482 | collisions[10]++; |
||
483 | } |
||
484 | |||
485 | printf("number of enums for %s: %d (total %ld)\n", |
||
486 | api_name, count, Elements(values)); |
||
487 | for (i = 0; i < Elements(collisions) - 1; i++) |
||
488 | if (collisions[i] > 0) |
||
489 | printf(" %d enums with %d %scollisions\n", |
||
490 | collisions[i], i, i == 10 ? "or more " : ""); |
||
491 | } |
||
492 | #endif |
||
493 | |||
494 | /** |
||
495 | * Initialize the enum hash for a given API |
||
496 | * |
||
497 | * This is called from one_time_init() to insert the enum values that |
||
498 | * are valid for the API in question into the enum hash table. |
||
499 | * |
||
500 | * \param the current context, for determining the API in question |
||
501 | */ |
||
502 | void _mesa_init_get_hash(struct gl_context *ctx) |
||
503 | { |
||
504 | #ifdef GET_DEBUG |
||
505 | print_table_stats(); |
||
506 | #endif |
||
507 | } |
||
508 | |||
509 | /** |
||
510 | * Handle irregular enums |
||
511 | * |
||
512 | * Some values don't conform to the "well-known type at context |
||
513 | * pointer + offset" pattern, so we have this function to catch all |
||
514 | * the corner cases. Typically, it's a computed value or a one-off |
||
515 | * pointer to a custom struct or something. |
||
516 | * |
||
517 | * In this case we can't return a pointer to the value, so we'll have |
||
518 | * to use the temporary variable 'v' declared back in the calling |
||
519 | * glGet*v() function to store the result. |
||
520 | * |
||
521 | * \param ctx the current context |
||
522 | * \param d the struct value_desc that describes the enum |
||
523 | * \param v pointer to the tmp declared in the calling glGet*v() function |
||
524 | */ |
||
525 | static void |
||
526 | find_custom_value(struct gl_context *ctx, const struct value_desc *d, union value *v) |
||
527 | { |
||
528 | struct gl_buffer_object **buffer_obj; |
||
529 | struct gl_client_array *array; |
||
530 | GLuint unit, *p; |
||
531 | |||
532 | switch (d->pname) { |
||
533 | case GL_MAJOR_VERSION: |
||
534 | v->value_int = ctx->Version / 10; |
||
535 | break; |
||
536 | case GL_MINOR_VERSION: |
||
537 | v->value_int = ctx->Version % 10; |
||
538 | break; |
||
539 | |||
540 | case GL_TEXTURE_1D: |
||
541 | case GL_TEXTURE_2D: |
||
542 | case GL_TEXTURE_3D: |
||
543 | case GL_TEXTURE_1D_ARRAY_EXT: |
||
544 | case GL_TEXTURE_2D_ARRAY_EXT: |
||
545 | case GL_TEXTURE_CUBE_MAP_ARB: |
||
546 | case GL_TEXTURE_RECTANGLE_NV: |
||
547 | case GL_TEXTURE_EXTERNAL_OES: |
||
548 | v->value_bool = _mesa_IsEnabled(d->pname); |
||
549 | break; |
||
550 | |||
551 | case GL_LINE_STIPPLE_PATTERN: |
||
552 | /* This is the only GLushort, special case it here by promoting |
||
553 | * to an int rather than introducing a new type. */ |
||
554 | v->value_int = ctx->Line.StipplePattern; |
||
555 | break; |
||
556 | |||
557 | case GL_CURRENT_RASTER_TEXTURE_COORDS: |
||
558 | unit = ctx->Texture.CurrentUnit; |
||
559 | v->value_float_4[0] = ctx->Current.RasterTexCoords[unit][0]; |
||
560 | v->value_float_4[1] = ctx->Current.RasterTexCoords[unit][1]; |
||
561 | v->value_float_4[2] = ctx->Current.RasterTexCoords[unit][2]; |
||
562 | v->value_float_4[3] = ctx->Current.RasterTexCoords[unit][3]; |
||
563 | break; |
||
564 | |||
565 | case GL_CURRENT_TEXTURE_COORDS: |
||
566 | unit = ctx->Texture.CurrentUnit; |
||
567 | v->value_float_4[0] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit][0]; |
||
568 | v->value_float_4[1] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit][1]; |
||
569 | v->value_float_4[2] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit][2]; |
||
570 | v->value_float_4[3] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit][3]; |
||
571 | break; |
||
572 | |||
573 | case GL_COLOR_WRITEMASK: |
||
574 | v->value_int_4[0] = ctx->Color.ColorMask[0][RCOMP] ? 1 : 0; |
||
575 | v->value_int_4[1] = ctx->Color.ColorMask[0][GCOMP] ? 1 : 0; |
||
576 | v->value_int_4[2] = ctx->Color.ColorMask[0][BCOMP] ? 1 : 0; |
||
577 | v->value_int_4[3] = ctx->Color.ColorMask[0][ACOMP] ? 1 : 0; |
||
578 | break; |
||
579 | |||
580 | case GL_EDGE_FLAG: |
||
581 | v->value_bool = ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] == 1.0; |
||
582 | break; |
||
583 | |||
584 | case GL_READ_BUFFER: |
||
585 | v->value_enum = ctx->ReadBuffer->ColorReadBuffer; |
||
586 | break; |
||
587 | |||
588 | case GL_MAP2_GRID_DOMAIN: |
||
589 | v->value_float_4[0] = ctx->Eval.MapGrid2u1; |
||
590 | v->value_float_4[1] = ctx->Eval.MapGrid2u2; |
||
591 | v->value_float_4[2] = ctx->Eval.MapGrid2v1; |
||
592 | v->value_float_4[3] = ctx->Eval.MapGrid2v2; |
||
593 | break; |
||
594 | |||
595 | case GL_TEXTURE_STACK_DEPTH: |
||
596 | unit = ctx->Texture.CurrentUnit; |
||
597 | v->value_int = ctx->TextureMatrixStack[unit].Depth + 1; |
||
598 | break; |
||
599 | case GL_TEXTURE_MATRIX: |
||
600 | unit = ctx->Texture.CurrentUnit; |
||
601 | v->value_matrix = ctx->TextureMatrixStack[unit].Top; |
||
602 | break; |
||
603 | |||
604 | case GL_TEXTURE_COORD_ARRAY: |
||
605 | case GL_TEXTURE_COORD_ARRAY_SIZE: |
||
606 | case GL_TEXTURE_COORD_ARRAY_TYPE: |
||
607 | case GL_TEXTURE_COORD_ARRAY_STRIDE: |
||
608 | array = &ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)]; |
||
609 | v->value_int = *(GLuint *) ((char *) array + d->offset); |
||
610 | break; |
||
611 | |||
612 | case GL_ACTIVE_TEXTURE_ARB: |
||
613 | v->value_int = GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit; |
||
614 | break; |
||
615 | case GL_CLIENT_ACTIVE_TEXTURE_ARB: |
||
616 | v->value_int = GL_TEXTURE0_ARB + ctx->Array.ActiveTexture; |
||
617 | break; |
||
618 | |||
619 | case GL_MODELVIEW_STACK_DEPTH: |
||
620 | case GL_PROJECTION_STACK_DEPTH: |
||
621 | v->value_int = *(GLint *) ((char *) ctx + d->offset) + 1; |
||
622 | break; |
||
623 | |||
624 | case GL_MAX_TEXTURE_SIZE: |
||
625 | case GL_MAX_3D_TEXTURE_SIZE: |
||
626 | case GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB: |
||
627 | p = (GLuint *) ((char *) ctx + d->offset); |
||
628 | v->value_int = 1 << (*p - 1); |
||
629 | break; |
||
630 | |||
631 | case GL_SCISSOR_BOX: |
||
632 | v->value_int_4[0] = ctx->Scissor.X; |
||
633 | v->value_int_4[1] = ctx->Scissor.Y; |
||
634 | v->value_int_4[2] = ctx->Scissor.Width; |
||
635 | v->value_int_4[3] = ctx->Scissor.Height; |
||
636 | break; |
||
637 | |||
638 | case GL_LIST_INDEX: |
||
639 | v->value_int = |
||
640 | ctx->ListState.CurrentList ? ctx->ListState.CurrentList->Name : 0; |
||
641 | break; |
||
642 | case GL_LIST_MODE: |
||
643 | if (!ctx->CompileFlag) |
||
644 | v->value_enum = 0; |
||
645 | else if (ctx->ExecuteFlag) |
||
646 | v->value_enum = GL_COMPILE_AND_EXECUTE; |
||
647 | else |
||
648 | v->value_enum = GL_COMPILE; |
||
649 | break; |
||
650 | |||
651 | case GL_VIEWPORT: |
||
652 | v->value_int_4[0] = ctx->Viewport.X; |
||
653 | v->value_int_4[1] = ctx->Viewport.Y; |
||
654 | v->value_int_4[2] = ctx->Viewport.Width; |
||
655 | v->value_int_4[3] = ctx->Viewport.Height; |
||
656 | break; |
||
657 | |||
658 | case GL_ACTIVE_STENCIL_FACE_EXT: |
||
659 | v->value_enum = ctx->Stencil.ActiveFace ? GL_BACK : GL_FRONT; |
||
660 | break; |
||
661 | |||
662 | case GL_STENCIL_FAIL: |
||
663 | v->value_enum = ctx->Stencil.FailFunc[ctx->Stencil.ActiveFace]; |
||
664 | break; |
||
665 | case GL_STENCIL_FUNC: |
||
666 | v->value_enum = ctx->Stencil.Function[ctx->Stencil.ActiveFace]; |
||
667 | break; |
||
668 | case GL_STENCIL_PASS_DEPTH_FAIL: |
||
669 | v->value_enum = ctx->Stencil.ZFailFunc[ctx->Stencil.ActiveFace]; |
||
670 | break; |
||
671 | case GL_STENCIL_PASS_DEPTH_PASS: |
||
672 | v->value_enum = ctx->Stencil.ZPassFunc[ctx->Stencil.ActiveFace]; |
||
673 | break; |
||
674 | case GL_STENCIL_REF: |
||
675 | v->value_int = _mesa_get_stencil_ref(ctx, ctx->Stencil.ActiveFace); |
||
676 | break; |
||
677 | case GL_STENCIL_BACK_REF: |
||
678 | v->value_int = _mesa_get_stencil_ref(ctx, 1); |
||
679 | break; |
||
680 | case GL_STENCIL_VALUE_MASK: |
||
681 | v->value_int = ctx->Stencil.ValueMask[ctx->Stencil.ActiveFace]; |
||
682 | break; |
||
683 | case GL_STENCIL_WRITEMASK: |
||
684 | v->value_int = ctx->Stencil.WriteMask[ctx->Stencil.ActiveFace]; |
||
685 | break; |
||
686 | |||
687 | case GL_NUM_EXTENSIONS: |
||
688 | v->value_int = _mesa_get_extension_count(ctx); |
||
689 | break; |
||
690 | |||
691 | case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES: |
||
692 | v->value_int = _mesa_get_color_read_type(ctx); |
||
693 | break; |
||
694 | case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES: |
||
695 | v->value_int = _mesa_get_color_read_format(ctx); |
||
696 | break; |
||
697 | |||
698 | case GL_CURRENT_MATRIX_STACK_DEPTH_ARB: |
||
699 | v->value_int = ctx->CurrentStack->Depth + 1; |
||
700 | break; |
||
701 | case GL_CURRENT_MATRIX_ARB: |
||
702 | case GL_TRANSPOSE_CURRENT_MATRIX_ARB: |
||
703 | v->value_matrix = ctx->CurrentStack->Top; |
||
704 | break; |
||
705 | |||
706 | case GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB: |
||
707 | v->value_int = _mesa_get_compressed_formats(ctx, NULL); |
||
708 | break; |
||
709 | case GL_COMPRESSED_TEXTURE_FORMATS_ARB: |
||
710 | v->value_int_n.n = |
||
711 | _mesa_get_compressed_formats(ctx, v->value_int_n.ints); |
||
712 | ASSERT(v->value_int_n.n <= 100); |
||
713 | break; |
||
714 | |||
715 | case GL_MAX_VARYING_FLOATS_ARB: |
||
716 | case GL_MAX_FRAGMENT_INPUT_COMPONENTS: |
||
717 | case GL_MAX_VERTEX_OUTPUT_COMPONENTS: |
||
718 | v->value_int = ctx->Const.MaxVarying * 4; |
||
719 | break; |
||
720 | |||
721 | /* Various object names */ |
||
722 | |||
723 | case GL_TEXTURE_BINDING_1D: |
||
724 | case GL_TEXTURE_BINDING_2D: |
||
725 | case GL_TEXTURE_BINDING_3D: |
||
726 | case GL_TEXTURE_BINDING_1D_ARRAY_EXT: |
||
727 | case GL_TEXTURE_BINDING_2D_ARRAY_EXT: |
||
728 | case GL_TEXTURE_BINDING_CUBE_MAP_ARB: |
||
729 | case GL_TEXTURE_BINDING_RECTANGLE_NV: |
||
730 | case GL_TEXTURE_BINDING_EXTERNAL_OES: |
||
731 | case GL_TEXTURE_BINDING_CUBE_MAP_ARRAY: |
||
732 | case GL_TEXTURE_BINDING_2D_MULTISAMPLE: |
||
733 | case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY: |
||
734 | unit = ctx->Texture.CurrentUnit; |
||
735 | v->value_int = |
||
736 | ctx->Texture.Unit[unit].CurrentTex[d->offset]->Name; |
||
737 | break; |
||
738 | |||
739 | /* GL_ARB_vertex_buffer_object */ |
||
740 | case GL_VERTEX_ARRAY_BUFFER_BINDING_ARB: |
||
741 | case GL_NORMAL_ARRAY_BUFFER_BINDING_ARB: |
||
742 | case GL_COLOR_ARRAY_BUFFER_BINDING_ARB: |
||
743 | case GL_INDEX_ARRAY_BUFFER_BINDING_ARB: |
||
744 | case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB: |
||
745 | case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB: |
||
746 | case GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB: |
||
747 | buffer_obj = (struct gl_buffer_object **) |
||
748 | ((char *) ctx->Array.ArrayObj + d->offset); |
||
749 | v->value_int = (*buffer_obj)->Name; |
||
750 | break; |
||
751 | case GL_ARRAY_BUFFER_BINDING_ARB: |
||
752 | v->value_int = ctx->Array.ArrayBufferObj->Name; |
||
753 | break; |
||
754 | case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB: |
||
755 | v->value_int = |
||
756 | ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].BufferObj->Name; |
||
757 | break; |
||
758 | case GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB: |
||
759 | v->value_int = ctx->Array.ArrayObj->ElementArrayBufferObj->Name; |
||
760 | break; |
||
761 | |||
762 | /* ARB_copy_buffer */ |
||
763 | case GL_COPY_READ_BUFFER: |
||
764 | v->value_int = ctx->CopyReadBuffer->Name; |
||
765 | break; |
||
766 | case GL_COPY_WRITE_BUFFER: |
||
767 | v->value_int = ctx->CopyWriteBuffer->Name; |
||
768 | break; |
||
769 | |||
770 | case GL_PIXEL_PACK_BUFFER_BINDING_EXT: |
||
771 | v->value_int = ctx->Pack.BufferObj->Name; |
||
772 | break; |
||
773 | case GL_PIXEL_UNPACK_BUFFER_BINDING_EXT: |
||
774 | v->value_int = ctx->Unpack.BufferObj->Name; |
||
775 | break; |
||
776 | case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: |
||
777 | v->value_int = ctx->TransformFeedback.CurrentBuffer->Name; |
||
778 | break; |
||
779 | case GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED: |
||
780 | v->value_int = ctx->TransformFeedback.CurrentObject->Paused; |
||
781 | break; |
||
782 | case GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE: |
||
783 | v->value_int = ctx->TransformFeedback.CurrentObject->Active; |
||
784 | break; |
||
785 | case GL_TRANSFORM_FEEDBACK_BINDING: |
||
786 | v->value_int = ctx->TransformFeedback.CurrentObject->Name; |
||
787 | break; |
||
788 | case GL_CURRENT_PROGRAM: |
||
789 | v->value_int = |
||
790 | ctx->Shader.ActiveProgram ? ctx->Shader.ActiveProgram->Name : 0; |
||
791 | break; |
||
792 | case GL_READ_FRAMEBUFFER_BINDING_EXT: |
||
793 | v->value_int = ctx->ReadBuffer->Name; |
||
794 | break; |
||
795 | case GL_RENDERBUFFER_BINDING_EXT: |
||
796 | v->value_int = |
||
797 | ctx->CurrentRenderbuffer ? ctx->CurrentRenderbuffer->Name : 0; |
||
798 | break; |
||
799 | case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: |
||
800 | v->value_int = ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POINT_SIZE].BufferObj->Name; |
||
801 | break; |
||
802 | |||
803 | case GL_FOG_COLOR: |
||
804 | if (_mesa_get_clamp_fragment_color(ctx)) |
||
805 | COPY_4FV(v->value_float_4, ctx->Fog.Color); |
||
806 | else |
||
807 | COPY_4FV(v->value_float_4, ctx->Fog.ColorUnclamped); |
||
808 | break; |
||
809 | case GL_COLOR_CLEAR_VALUE: |
||
810 | if (_mesa_get_clamp_fragment_color(ctx)) { |
||
811 | v->value_float_4[0] = CLAMP(ctx->Color.ClearColor.f[0], 0.0F, 1.0F); |
||
812 | v->value_float_4[1] = CLAMP(ctx->Color.ClearColor.f[1], 0.0F, 1.0F); |
||
813 | v->value_float_4[2] = CLAMP(ctx->Color.ClearColor.f[2], 0.0F, 1.0F); |
||
814 | v->value_float_4[3] = CLAMP(ctx->Color.ClearColor.f[3], 0.0F, 1.0F); |
||
815 | } else |
||
816 | COPY_4FV(v->value_float_4, ctx->Color.ClearColor.f); |
||
817 | break; |
||
818 | case GL_BLEND_COLOR_EXT: |
||
819 | if (_mesa_get_clamp_fragment_color(ctx)) |
||
820 | COPY_4FV(v->value_float_4, ctx->Color.BlendColor); |
||
821 | else |
||
822 | COPY_4FV(v->value_float_4, ctx->Color.BlendColorUnclamped); |
||
823 | break; |
||
824 | case GL_ALPHA_TEST_REF: |
||
825 | if (_mesa_get_clamp_fragment_color(ctx)) |
||
826 | v->value_float = ctx->Color.AlphaRef; |
||
827 | else |
||
828 | v->value_float = ctx->Color.AlphaRefUnclamped; |
||
829 | break; |
||
830 | case GL_MAX_VERTEX_UNIFORM_VECTORS: |
||
831 | v->value_int = ctx->Const.VertexProgram.MaxUniformComponents / 4; |
||
832 | break; |
||
833 | |||
834 | case GL_MAX_FRAGMENT_UNIFORM_VECTORS: |
||
835 | v->value_int = ctx->Const.FragmentProgram.MaxUniformComponents / 4; |
||
836 | break; |
||
837 | |||
838 | /* GL_ARB_texture_buffer_object */ |
||
839 | case GL_TEXTURE_BUFFER_ARB: |
||
840 | v->value_int = ctx->Texture.BufferObject->Name; |
||
841 | break; |
||
842 | case GL_TEXTURE_BINDING_BUFFER_ARB: |
||
843 | unit = ctx->Texture.CurrentUnit; |
||
844 | v->value_int = |
||
845 | ctx->Texture.Unit[unit].CurrentTex[TEXTURE_BUFFER_INDEX]->Name; |
||
846 | break; |
||
847 | case GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB: |
||
848 | { |
||
849 | struct gl_buffer_object *buf = |
||
850 | ctx->Texture.Unit[ctx->Texture.CurrentUnit] |
||
851 | .CurrentTex[TEXTURE_BUFFER_INDEX]->BufferObject; |
||
852 | v->value_int = buf ? buf->Name : 0; |
||
853 | } |
||
854 | break; |
||
855 | case GL_TEXTURE_BUFFER_FORMAT_ARB: |
||
856 | v->value_int = ctx->Texture.Unit[ctx->Texture.CurrentUnit] |
||
857 | .CurrentTex[TEXTURE_BUFFER_INDEX]->BufferObjectFormat; |
||
858 | break; |
||
859 | |||
860 | /* GL_ARB_sampler_objects */ |
||
861 | case GL_SAMPLER_BINDING: |
||
862 | { |
||
863 | struct gl_sampler_object *samp = |
||
864 | ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler; |
||
865 | |||
866 | /* |
||
867 | * The sampler object may have been deleted on another context, |
||
868 | * so we try to lookup the sampler object before returning its Name. |
||
869 | */ |
||
870 | if (samp && _mesa_lookup_samplerobj(ctx, samp->Name)) { |
||
871 | v->value_int = samp->Name; |
||
872 | } else { |
||
873 | v->value_int = 0; |
||
874 | } |
||
875 | } |
||
876 | break; |
||
877 | /* GL_ARB_uniform_buffer_object */ |
||
878 | case GL_UNIFORM_BUFFER_BINDING: |
||
879 | v->value_int = ctx->UniformBuffer->Name; |
||
880 | break; |
||
881 | /* GL_ARB_timer_query */ |
||
882 | case GL_TIMESTAMP: |
||
883 | if (ctx->Driver.GetTimestamp) { |
||
884 | v->value_int64 = ctx->Driver.GetTimestamp(ctx); |
||
885 | } |
||
886 | else { |
||
887 | _mesa_problem(ctx, "driver doesn't implement GetTimestamp"); |
||
888 | } |
||
889 | break; |
||
890 | } |
||
891 | } |
||
892 | |||
893 | /** |
||
894 | * Check extra constraints on a struct value_desc descriptor |
||
895 | * |
||
896 | * If a struct value_desc has a non-NULL extra pointer, it means that |
||
897 | * there are a number of extra constraints to check or actions to |
||
898 | * perform. The extras is just an integer array where each integer |
||
899 | * encode different constraints or actions. |
||
900 | * |
||
901 | * \param ctx current context |
||
902 | * \param func name of calling glGet*v() function for error reporting |
||
903 | * \param d the struct value_desc that has the extra constraints |
||
904 | * |
||
905 | * \return GL_FALSE if all of the constraints were not satisfied, |
||
906 | * otherwise GL_TRUE. |
||
907 | */ |
||
908 | static GLboolean |
||
909 | check_extra(struct gl_context *ctx, const char *func, const struct value_desc *d) |
||
910 | { |
||
911 | const GLuint version = ctx->Version; |
||
912 | GLboolean api_check = GL_FALSE; |
||
913 | GLboolean api_found = GL_FALSE; |
||
914 | const int *e; |
||
915 | |||
916 | for (e = d->extra; *e != EXTRA_END; e++) { |
||
917 | switch (*e) { |
||
918 | case EXTRA_VERSION_30: |
||
919 | api_check = GL_TRUE; |
||
920 | if (version >= 30) |
||
921 | api_found = GL_TRUE; |
||
922 | break; |
||
923 | case EXTRA_VERSION_31: |
||
924 | api_check = GL_TRUE; |
||
925 | if (version >= 31) |
||
926 | api_found = GL_TRUE; |
||
927 | break; |
||
928 | case EXTRA_VERSION_32: |
||
929 | api_check = GL_TRUE; |
||
930 | if (version >= 32) |
||
931 | api_found = GL_TRUE; |
||
932 | break; |
||
933 | case EXTRA_NEW_FRAG_CLAMP: |
||
934 | if (ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP)) |
||
935 | _mesa_update_state(ctx); |
||
936 | break; |
||
937 | case EXTRA_API_ES2: |
||
938 | api_check = GL_TRUE; |
||
939 | if (ctx->API == API_OPENGLES2) |
||
940 | api_found = GL_TRUE; |
||
941 | break; |
||
942 | case EXTRA_API_ES3: |
||
943 | api_check = GL_TRUE; |
||
944 | if (_mesa_is_gles3(ctx)) |
||
945 | api_found = GL_TRUE; |
||
946 | break; |
||
947 | case EXTRA_API_GL: |
||
948 | api_check = GL_TRUE; |
||
949 | if (_mesa_is_desktop_gl(ctx)) |
||
950 | api_found = GL_TRUE; |
||
951 | break; |
||
952 | case EXTRA_API_GL_CORE: |
||
953 | api_check = GL_TRUE; |
||
954 | if (ctx->API == API_OPENGL_CORE) |
||
955 | api_found = GL_TRUE; |
||
956 | break; |
||
957 | case EXTRA_NEW_BUFFERS: |
||
958 | if (ctx->NewState & _NEW_BUFFERS) |
||
959 | _mesa_update_state(ctx); |
||
960 | break; |
||
961 | case EXTRA_FLUSH_CURRENT: |
||
962 | FLUSH_CURRENT(ctx, 0); |
||
963 | break; |
||
964 | case EXTRA_VALID_DRAW_BUFFER: |
||
965 | if (d->pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) { |
||
966 | _mesa_error(ctx, GL_INVALID_OPERATION, "%s(draw buffer %u)", |
||
967 | func, d->pname - GL_DRAW_BUFFER0_ARB); |
||
968 | return GL_FALSE; |
||
969 | } |
||
970 | break; |
||
971 | case EXTRA_VALID_TEXTURE_UNIT: |
||
972 | if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) { |
||
973 | _mesa_error(ctx, GL_INVALID_OPERATION, "%s(texture %u)", |
||
974 | func, ctx->Texture.CurrentUnit); |
||
975 | return GL_FALSE; |
||
976 | } |
||
977 | break; |
||
978 | case EXTRA_VALID_CLIP_DISTANCE: |
||
979 | if (d->pname - GL_CLIP_DISTANCE0 >= ctx->Const.MaxClipPlanes) { |
||
980 | _mesa_error(ctx, GL_INVALID_ENUM, "%s(clip distance %u)", |
||
981 | func, d->pname - GL_CLIP_DISTANCE0); |
||
982 | return GL_FALSE; |
||
983 | } |
||
984 | break; |
||
985 | case EXTRA_GLSL_130: |
||
986 | api_check = GL_TRUE; |
||
987 | if (ctx->Const.GLSLVersion >= 130) |
||
988 | api_found = GL_TRUE; |
||
989 | break; |
||
990 | case EXTRA_EXT_UBO_GS4: |
||
991 | api_check = GL_TRUE; |
||
992 | api_found = (ctx->Extensions.ARB_uniform_buffer_object && |
||
993 | ctx->Extensions.ARB_geometry_shader4); |
||
994 | break; |
||
995 | case EXTRA_END: |
||
996 | break; |
||
997 | default: /* *e is a offset into the extension struct */ |
||
998 | api_check = GL_TRUE; |
||
999 | if (*(GLboolean *) ((char *) &ctx->Extensions + *e)) |
||
1000 | api_found = GL_TRUE; |
||
1001 | break; |
||
1002 | } |
||
1003 | } |
||
1004 | |||
1005 | if (api_check && !api_found) { |
||
1006 | _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=%s)", func, |
||
1007 | _mesa_lookup_enum_by_nr(d->pname)); |
||
1008 | return GL_FALSE; |
||
1009 | } |
||
1010 | |||
1011 | return GL_TRUE; |
||
1012 | } |
||
1013 | |||
1014 | static const struct value_desc error_value = |
||
1015 | { 0, 0, TYPE_INVALID, NO_OFFSET, NO_EXTRA }; |
||
1016 | |||
1017 | /** |
||
1018 | * Find the struct value_desc corresponding to the enum 'pname'. |
||
1019 | * |
||
1020 | * We hash the enum value to get an index into the 'table' array, |
||
1021 | * which holds the index in the 'values' array of struct value_desc. |
||
1022 | * Once we've found the entry, we do the extra checks, if any, then |
||
1023 | * look up the value and return a pointer to it. |
||
1024 | * |
||
1025 | * If the value has to be computed (for example, it's the result of a |
||
1026 | * function call or we need to add 1 to it), we use the tmp 'v' to |
||
1027 | * store the result. |
||
1028 | * |
||
1029 | * \param func name of glGet*v() func for error reporting |
||
1030 | * \param pname the enum value we're looking up |
||
1031 | * \param p is were we return the pointer to the value |
||
1032 | * \param v a tmp union value variable in the calling glGet*v() function |
||
1033 | * |
||
1034 | * \return the struct value_desc corresponding to the enum or a struct |
||
1035 | * value_desc of TYPE_INVALID if not found. This lets the calling |
||
1036 | * glGet*v() function jump right into a switch statement and |
||
1037 | * handle errors there instead of having to check for NULL. |
||
1038 | */ |
||
1039 | static const struct value_desc * |
||
1040 | find_value(const char *func, GLenum pname, void **p, union value *v) |
||
1041 | { |
||
1042 | GET_CURRENT_CONTEXT(ctx); |
||
1043 | struct gl_texture_unit *unit; |
||
1044 | int mask, hash; |
||
1045 | const struct value_desc *d; |
||
1046 | int api; |
||
1047 | |||
1048 | api = ctx->API; |
||
1049 | /* We index into the table_set[] list of per-API hash tables using the API's |
||
1050 | * value in the gl_api enum. Since GLES 3 doesn't have an API_OPENGL* enum |
||
1051 | * value since it's compatible with GLES2 its entry in table_set[] is at the |
||
1052 | * end. |
||
1053 | */ |
||
1054 | STATIC_ASSERT(Elements(table_set) == API_OPENGL_LAST + 2); |
||
1055 | if (_mesa_is_gles3(ctx)) { |
||
1056 | api = API_OPENGL_LAST + 1; |
||
1057 | } |
||
1058 | mask = Elements(table(api)) - 1; |
||
1059 | hash = (pname * prime_factor); |
||
1060 | while (1) { |
||
1061 | int idx = table(api)[hash & mask]; |
||
1062 | |||
1063 | /* If the enum isn't valid, the hash walk ends with index 0, |
||
1064 | * pointing to the first entry of values[] which doesn't hold |
||
1065 | * any valid enum. */ |
||
1066 | if (unlikely(idx == 0)) { |
||
1067 | _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=%s)", func, |
||
1068 | _mesa_lookup_enum_by_nr(pname)); |
||
1069 | return &error_value; |
||
1070 | } |
||
1071 | |||
1072 | d = &values[idx]; |
||
1073 | if (likely(d->pname == pname)) |
||
1074 | break; |
||
1075 | |||
1076 | hash += prime_step; |
||
1077 | } |
||
1078 | |||
1079 | if (unlikely(d->extra && !check_extra(ctx, func, d))) |
||
1080 | return &error_value; |
||
1081 | |||
1082 | switch (d->location) { |
||
1083 | case LOC_BUFFER: |
||
1084 | *p = ((char *) ctx->DrawBuffer + d->offset); |
||
1085 | return d; |
||
1086 | case LOC_CONTEXT: |
||
1087 | *p = ((char *) ctx + d->offset); |
||
1088 | return d; |
||
1089 | case LOC_ARRAY: |
||
1090 | *p = ((char *) ctx->Array.ArrayObj + d->offset); |
||
1091 | return d; |
||
1092 | case LOC_TEXUNIT: |
||
1093 | unit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; |
||
1094 | *p = ((char *) unit + d->offset); |
||
1095 | return d; |
||
1096 | case LOC_CUSTOM: |
||
1097 | find_custom_value(ctx, d, v); |
||
1098 | *p = v; |
||
1099 | return d; |
||
1100 | default: |
||
1101 | assert(0); |
||
1102 | break; |
||
1103 | } |
||
1104 | |||
1105 | /* silence warning */ |
||
1106 | return &error_value; |
||
1107 | } |
||
1108 | |||
1109 | static const int transpose[] = { |
||
1110 | 0, 4, 8, 12, |
||
1111 | 1, 5, 9, 13, |
||
1112 | 2, 6, 10, 14, |
||
1113 | 3, 7, 11, 15 |
||
1114 | }; |
||
1115 | |||
1116 | void GLAPIENTRY |
||
1117 | _mesa_GetBooleanv(GLenum pname, GLboolean *params) |
||
1118 | { |
||
1119 | const struct value_desc *d; |
||
1120 | union value v; |
||
1121 | GLmatrix *m; |
||
1122 | int shift, i; |
||
1123 | void *p; |
||
1124 | |||
1125 | d = find_value("glGetBooleanv", pname, &p, &v); |
||
1126 | switch (d->type) { |
||
1127 | case TYPE_INVALID: |
||
1128 | break; |
||
1129 | case TYPE_CONST: |
||
1130 | params[0] = INT_TO_BOOLEAN(d->offset); |
||
1131 | break; |
||
1132 | |||
1133 | case TYPE_FLOAT_4: |
||
1134 | case TYPE_FLOATN_4: |
||
1135 | params[3] = FLOAT_TO_BOOLEAN(((GLfloat *) p)[3]); |
||
1136 | case TYPE_FLOAT_3: |
||
1137 | case TYPE_FLOATN_3: |
||
1138 | params[2] = FLOAT_TO_BOOLEAN(((GLfloat *) p)[2]); |
||
1139 | case TYPE_FLOAT_2: |
||
1140 | case TYPE_FLOATN_2: |
||
1141 | params[1] = FLOAT_TO_BOOLEAN(((GLfloat *) p)[1]); |
||
1142 | case TYPE_FLOAT: |
||
1143 | case TYPE_FLOATN: |
||
1144 | params[0] = FLOAT_TO_BOOLEAN(((GLfloat *) p)[0]); |
||
1145 | break; |
||
1146 | |||
1147 | case TYPE_DOUBLEN: |
||
1148 | params[0] = FLOAT_TO_BOOLEAN(((GLdouble *) p)[0]); |
||
1149 | break; |
||
1150 | |||
1151 | case TYPE_INT_4: |
||
1152 | params[3] = INT_TO_BOOLEAN(((GLint *) p)[3]); |
||
1153 | case TYPE_INT_3: |
||
1154 | params[2] = INT_TO_BOOLEAN(((GLint *) p)[2]); |
||
1155 | case TYPE_INT_2: |
||
1156 | case TYPE_ENUM_2: |
||
1157 | params[1] = INT_TO_BOOLEAN(((GLint *) p)[1]); |
||
1158 | case TYPE_INT: |
||
1159 | case TYPE_ENUM: |
||
1160 | params[0] = INT_TO_BOOLEAN(((GLint *) p)[0]); |
||
1161 | break; |
||
1162 | |||
1163 | case TYPE_INT_N: |
||
1164 | for (i = 0; i < v.value_int_n.n; i++) |
||
1165 | params[i] = INT_TO_BOOLEAN(v.value_int_n.ints[i]); |
||
1166 | break; |
||
1167 | |||
1168 | case TYPE_INT64: |
||
1169 | params[0] = INT64_TO_BOOLEAN(((GLint64 *) p)[0]); |
||
1170 | break; |
||
1171 | |||
1172 | case TYPE_BOOLEAN: |
||
1173 | params[0] = ((GLboolean*) p)[0]; |
||
1174 | break; |
||
1175 | |||
1176 | case TYPE_MATRIX: |
||
1177 | m = *(GLmatrix **) p; |
||
1178 | for (i = 0; i < 16; i++) |
||
1179 | params[i] = FLOAT_TO_BOOLEAN(m->m[i]); |
||
1180 | break; |
||
1181 | |||
1182 | case TYPE_MATRIX_T: |
||
1183 | m = *(GLmatrix **) p; |
||
1184 | for (i = 0; i < 16; i++) |
||
1185 | params[i] = FLOAT_TO_BOOLEAN(m->m[transpose[i]]); |
||
1186 | break; |
||
1187 | |||
1188 | case TYPE_BIT_0: |
||
1189 | case TYPE_BIT_1: |
||
1190 | case TYPE_BIT_2: |
||
1191 | case TYPE_BIT_3: |
||
1192 | case TYPE_BIT_4: |
||
1193 | case TYPE_BIT_5: |
||
1194 | case TYPE_BIT_6: |
||
1195 | case TYPE_BIT_7: |
||
1196 | shift = d->type - TYPE_BIT_0; |
||
1197 | params[0] = (*(GLbitfield *) p >> shift) & 1; |
||
1198 | break; |
||
1199 | } |
||
1200 | } |
||
1201 | |||
1202 | void GLAPIENTRY |
||
1203 | _mesa_GetFloatv(GLenum pname, GLfloat *params) |
||
1204 | { |
||
1205 | const struct value_desc *d; |
||
1206 | union value v; |
||
1207 | GLmatrix *m; |
||
1208 | int shift, i; |
||
1209 | void *p; |
||
1210 | |||
1211 | d = find_value("glGetFloatv", pname, &p, &v); |
||
1212 | switch (d->type) { |
||
1213 | case TYPE_INVALID: |
||
1214 | break; |
||
1215 | case TYPE_CONST: |
||
1216 | params[0] = (GLfloat) d->offset; |
||
1217 | break; |
||
1218 | |||
1219 | case TYPE_FLOAT_4: |
||
1220 | case TYPE_FLOATN_4: |
||
1221 | params[3] = ((GLfloat *) p)[3]; |
||
1222 | case TYPE_FLOAT_3: |
||
1223 | case TYPE_FLOATN_3: |
||
1224 | params[2] = ((GLfloat *) p)[2]; |
||
1225 | case TYPE_FLOAT_2: |
||
1226 | case TYPE_FLOATN_2: |
||
1227 | params[1] = ((GLfloat *) p)[1]; |
||
1228 | case TYPE_FLOAT: |
||
1229 | case TYPE_FLOATN: |
||
1230 | params[0] = ((GLfloat *) p)[0]; |
||
1231 | break; |
||
1232 | |||
1233 | case TYPE_DOUBLEN: |
||
1234 | params[0] = (GLfloat) (((GLdouble *) p)[0]); |
||
1235 | break; |
||
1236 | |||
1237 | case TYPE_INT_4: |
||
1238 | params[3] = (GLfloat) (((GLint *) p)[3]); |
||
1239 | case TYPE_INT_3: |
||
1240 | params[2] = (GLfloat) (((GLint *) p)[2]); |
||
1241 | case TYPE_INT_2: |
||
1242 | case TYPE_ENUM_2: |
||
1243 | params[1] = (GLfloat) (((GLint *) p)[1]); |
||
1244 | case TYPE_INT: |
||
1245 | case TYPE_ENUM: |
||
1246 | params[0] = (GLfloat) (((GLint *) p)[0]); |
||
1247 | break; |
||
1248 | |||
1249 | case TYPE_INT_N: |
||
1250 | for (i = 0; i < v.value_int_n.n; i++) |
||
1251 | params[i] = INT_TO_FLOAT(v.value_int_n.ints[i]); |
||
1252 | break; |
||
1253 | |||
1254 | case TYPE_INT64: |
||
1255 | params[0] = (GLfloat) (((GLint64 *) p)[0]); |
||
1256 | break; |
||
1257 | |||
1258 | case TYPE_BOOLEAN: |
||
1259 | params[0] = BOOLEAN_TO_FLOAT(*(GLboolean*) p); |
||
1260 | break; |
||
1261 | |||
1262 | case TYPE_MATRIX: |
||
1263 | m = *(GLmatrix **) p; |
||
1264 | for (i = 0; i < 16; i++) |
||
1265 | params[i] = m->m[i]; |
||
1266 | break; |
||
1267 | |||
1268 | case TYPE_MATRIX_T: |
||
1269 | m = *(GLmatrix **) p; |
||
1270 | for (i = 0; i < 16; i++) |
||
1271 | params[i] = m->m[transpose[i]]; |
||
1272 | break; |
||
1273 | |||
1274 | case TYPE_BIT_0: |
||
1275 | case TYPE_BIT_1: |
||
1276 | case TYPE_BIT_2: |
||
1277 | case TYPE_BIT_3: |
||
1278 | case TYPE_BIT_4: |
||
1279 | case TYPE_BIT_5: |
||
1280 | case TYPE_BIT_6: |
||
1281 | case TYPE_BIT_7: |
||
1282 | shift = d->type - TYPE_BIT_0; |
||
1283 | params[0] = BOOLEAN_TO_FLOAT((*(GLbitfield *) p >> shift) & 1); |
||
1284 | break; |
||
1285 | } |
||
1286 | } |
||
1287 | |||
1288 | void GLAPIENTRY |
||
1289 | _mesa_GetIntegerv(GLenum pname, GLint *params) |
||
1290 | { |
||
1291 | const struct value_desc *d; |
||
1292 | union value v; |
||
1293 | GLmatrix *m; |
||
1294 | int shift, i; |
||
1295 | void *p; |
||
1296 | |||
1297 | d = find_value("glGetIntegerv", pname, &p, &v); |
||
1298 | switch (d->type) { |
||
1299 | case TYPE_INVALID: |
||
1300 | break; |
||
1301 | case TYPE_CONST: |
||
1302 | params[0] = d->offset; |
||
1303 | break; |
||
1304 | |||
1305 | case TYPE_FLOAT_4: |
||
1306 | params[3] = IROUND(((GLfloat *) p)[3]); |
||
1307 | case TYPE_FLOAT_3: |
||
1308 | params[2] = IROUND(((GLfloat *) p)[2]); |
||
1309 | case TYPE_FLOAT_2: |
||
1310 | params[1] = IROUND(((GLfloat *) p)[1]); |
||
1311 | case TYPE_FLOAT: |
||
1312 | params[0] = IROUND(((GLfloat *) p)[0]); |
||
1313 | break; |
||
1314 | |||
1315 | case TYPE_FLOATN_4: |
||
1316 | params[3] = FLOAT_TO_INT(((GLfloat *) p)[3]); |
||
1317 | case TYPE_FLOATN_3: |
||
1318 | params[2] = FLOAT_TO_INT(((GLfloat *) p)[2]); |
||
1319 | case TYPE_FLOATN_2: |
||
1320 | params[1] = FLOAT_TO_INT(((GLfloat *) p)[1]); |
||
1321 | case TYPE_FLOATN: |
||
1322 | params[0] = FLOAT_TO_INT(((GLfloat *) p)[0]); |
||
1323 | break; |
||
1324 | |||
1325 | case TYPE_DOUBLEN: |
||
1326 | params[0] = FLOAT_TO_INT(((GLdouble *) p)[0]); |
||
1327 | break; |
||
1328 | |||
1329 | case TYPE_INT_4: |
||
1330 | params[3] = ((GLint *) p)[3]; |
||
1331 | case TYPE_INT_3: |
||
1332 | params[2] = ((GLint *) p)[2]; |
||
1333 | case TYPE_INT_2: |
||
1334 | case TYPE_ENUM_2: |
||
1335 | params[1] = ((GLint *) p)[1]; |
||
1336 | case TYPE_INT: |
||
1337 | case TYPE_ENUM: |
||
1338 | params[0] = ((GLint *) p)[0]; |
||
1339 | break; |
||
1340 | |||
1341 | case TYPE_INT_N: |
||
1342 | for (i = 0; i < v.value_int_n.n; i++) |
||
1343 | params[i] = v.value_int_n.ints[i]; |
||
1344 | break; |
||
1345 | |||
1346 | case TYPE_INT64: |
||
1347 | params[0] = INT64_TO_INT(((GLint64 *) p)[0]); |
||
1348 | break; |
||
1349 | |||
1350 | case TYPE_BOOLEAN: |
||
1351 | params[0] = BOOLEAN_TO_INT(*(GLboolean*) p); |
||
1352 | break; |
||
1353 | |||
1354 | case TYPE_MATRIX: |
||
1355 | m = *(GLmatrix **) p; |
||
1356 | for (i = 0; i < 16; i++) |
||
1357 | params[i] = FLOAT_TO_INT(m->m[i]); |
||
1358 | break; |
||
1359 | |||
1360 | case TYPE_MATRIX_T: |
||
1361 | m = *(GLmatrix **) p; |
||
1362 | for (i = 0; i < 16; i++) |
||
1363 | params[i] = FLOAT_TO_INT(m->m[transpose[i]]); |
||
1364 | break; |
||
1365 | |||
1366 | case TYPE_BIT_0: |
||
1367 | case TYPE_BIT_1: |
||
1368 | case TYPE_BIT_2: |
||
1369 | case TYPE_BIT_3: |
||
1370 | case TYPE_BIT_4: |
||
1371 | case TYPE_BIT_5: |
||
1372 | case TYPE_BIT_6: |
||
1373 | case TYPE_BIT_7: |
||
1374 | shift = d->type - TYPE_BIT_0; |
||
1375 | params[0] = (*(GLbitfield *) p >> shift) & 1; |
||
1376 | break; |
||
1377 | } |
||
1378 | } |
||
1379 | |||
1380 | void GLAPIENTRY |
||
1381 | _mesa_GetInteger64v(GLenum pname, GLint64 *params) |
||
1382 | { |
||
1383 | const struct value_desc *d; |
||
1384 | union value v; |
||
1385 | GLmatrix *m; |
||
1386 | int shift, i; |
||
1387 | void *p; |
||
1388 | |||
1389 | d = find_value("glGetInteger64v", pname, &p, &v); |
||
1390 | switch (d->type) { |
||
1391 | case TYPE_INVALID: |
||
1392 | break; |
||
1393 | case TYPE_CONST: |
||
1394 | params[0] = d->offset; |
||
1395 | break; |
||
1396 | |||
1397 | case TYPE_FLOAT_4: |
||
1398 | params[3] = IROUND64(((GLfloat *) p)[3]); |
||
1399 | case TYPE_FLOAT_3: |
||
1400 | params[2] = IROUND64(((GLfloat *) p)[2]); |
||
1401 | case TYPE_FLOAT_2: |
||
1402 | params[1] = IROUND64(((GLfloat *) p)[1]); |
||
1403 | case TYPE_FLOAT: |
||
1404 | params[0] = IROUND64(((GLfloat *) p)[0]); |
||
1405 | break; |
||
1406 | |||
1407 | case TYPE_FLOATN_4: |
||
1408 | params[3] = FLOAT_TO_INT64(((GLfloat *) p)[3]); |
||
1409 | case TYPE_FLOATN_3: |
||
1410 | params[2] = FLOAT_TO_INT64(((GLfloat *) p)[2]); |
||
1411 | case TYPE_FLOATN_2: |
||
1412 | params[1] = FLOAT_TO_INT64(((GLfloat *) p)[1]); |
||
1413 | case TYPE_FLOATN: |
||
1414 | params[0] = FLOAT_TO_INT64(((GLfloat *) p)[0]); |
||
1415 | break; |
||
1416 | |||
1417 | case TYPE_DOUBLEN: |
||
1418 | params[0] = FLOAT_TO_INT64(((GLdouble *) p)[0]); |
||
1419 | break; |
||
1420 | |||
1421 | case TYPE_INT_4: |
||
1422 | params[3] = ((GLint *) p)[3]; |
||
1423 | case TYPE_INT_3: |
||
1424 | params[2] = ((GLint *) p)[2]; |
||
1425 | case TYPE_INT_2: |
||
1426 | case TYPE_ENUM_2: |
||
1427 | params[1] = ((GLint *) p)[1]; |
||
1428 | case TYPE_INT: |
||
1429 | case TYPE_ENUM: |
||
1430 | params[0] = ((GLint *) p)[0]; |
||
1431 | break; |
||
1432 | |||
1433 | case TYPE_INT_N: |
||
1434 | for (i = 0; i < v.value_int_n.n; i++) |
||
1435 | params[i] = INT_TO_BOOLEAN(v.value_int_n.ints[i]); |
||
1436 | break; |
||
1437 | |||
1438 | case TYPE_INT64: |
||
1439 | params[0] = ((GLint64 *) p)[0]; |
||
1440 | break; |
||
1441 | |||
1442 | case TYPE_BOOLEAN: |
||
1443 | params[0] = ((GLboolean*) p)[0]; |
||
1444 | break; |
||
1445 | |||
1446 | case TYPE_MATRIX: |
||
1447 | m = *(GLmatrix **) p; |
||
1448 | for (i = 0; i < 16; i++) |
||
1449 | params[i] = FLOAT_TO_INT64(m->m[i]); |
||
1450 | break; |
||
1451 | |||
1452 | case TYPE_MATRIX_T: |
||
1453 | m = *(GLmatrix **) p; |
||
1454 | for (i = 0; i < 16; i++) |
||
1455 | params[i] = FLOAT_TO_INT64(m->m[transpose[i]]); |
||
1456 | break; |
||
1457 | |||
1458 | case TYPE_BIT_0: |
||
1459 | case TYPE_BIT_1: |
||
1460 | case TYPE_BIT_2: |
||
1461 | case TYPE_BIT_3: |
||
1462 | case TYPE_BIT_4: |
||
1463 | case TYPE_BIT_5: |
||
1464 | case TYPE_BIT_6: |
||
1465 | case TYPE_BIT_7: |
||
1466 | shift = d->type - TYPE_BIT_0; |
||
1467 | params[0] = (*(GLbitfield *) p >> shift) & 1; |
||
1468 | break; |
||
1469 | } |
||
1470 | } |
||
1471 | |||
1472 | void GLAPIENTRY |
||
1473 | _mesa_GetDoublev(GLenum pname, GLdouble *params) |
||
1474 | { |
||
1475 | const struct value_desc *d; |
||
1476 | union value v; |
||
1477 | GLmatrix *m; |
||
1478 | int shift, i; |
||
1479 | void *p; |
||
1480 | |||
1481 | d = find_value("glGetDoublev", pname, &p, &v); |
||
1482 | switch (d->type) { |
||
1483 | case TYPE_INVALID: |
||
1484 | break; |
||
1485 | case TYPE_CONST: |
||
1486 | params[0] = d->offset; |
||
1487 | break; |
||
1488 | |||
1489 | case TYPE_FLOAT_4: |
||
1490 | case TYPE_FLOATN_4: |
||
1491 | params[3] = ((GLfloat *) p)[3]; |
||
1492 | case TYPE_FLOAT_3: |
||
1493 | case TYPE_FLOATN_3: |
||
1494 | params[2] = ((GLfloat *) p)[2]; |
||
1495 | case TYPE_FLOAT_2: |
||
1496 | case TYPE_FLOATN_2: |
||
1497 | params[1] = ((GLfloat *) p)[1]; |
||
1498 | case TYPE_FLOAT: |
||
1499 | case TYPE_FLOATN: |
||
1500 | params[0] = ((GLfloat *) p)[0]; |
||
1501 | break; |
||
1502 | |||
1503 | case TYPE_DOUBLEN: |
||
1504 | params[0] = ((GLdouble *) p)[0]; |
||
1505 | break; |
||
1506 | |||
1507 | case TYPE_INT_4: |
||
1508 | params[3] = ((GLint *) p)[3]; |
||
1509 | case TYPE_INT_3: |
||
1510 | params[2] = ((GLint *) p)[2]; |
||
1511 | case TYPE_INT_2: |
||
1512 | case TYPE_ENUM_2: |
||
1513 | params[1] = ((GLint *) p)[1]; |
||
1514 | case TYPE_INT: |
||
1515 | case TYPE_ENUM: |
||
1516 | params[0] = ((GLint *) p)[0]; |
||
1517 | break; |
||
1518 | |||
1519 | case TYPE_INT_N: |
||
1520 | for (i = 0; i < v.value_int_n.n; i++) |
||
1521 | params[i] = v.value_int_n.ints[i]; |
||
1522 | break; |
||
1523 | |||
1524 | case TYPE_INT64: |
||
1525 | params[0] = (GLdouble) (((GLint64 *) p)[0]); |
||
1526 | break; |
||
1527 | |||
1528 | case TYPE_BOOLEAN: |
||
1529 | params[0] = *(GLboolean*) p; |
||
1530 | break; |
||
1531 | |||
1532 | case TYPE_MATRIX: |
||
1533 | m = *(GLmatrix **) p; |
||
1534 | for (i = 0; i < 16; i++) |
||
1535 | params[i] = m->m[i]; |
||
1536 | break; |
||
1537 | |||
1538 | case TYPE_MATRIX_T: |
||
1539 | m = *(GLmatrix **) p; |
||
1540 | for (i = 0; i < 16; i++) |
||
1541 | params[i] = m->m[transpose[i]]; |
||
1542 | break; |
||
1543 | |||
1544 | case TYPE_BIT_0: |
||
1545 | case TYPE_BIT_1: |
||
1546 | case TYPE_BIT_2: |
||
1547 | case TYPE_BIT_3: |
||
1548 | case TYPE_BIT_4: |
||
1549 | case TYPE_BIT_5: |
||
1550 | case TYPE_BIT_6: |
||
1551 | case TYPE_BIT_7: |
||
1552 | shift = d->type - TYPE_BIT_0; |
||
1553 | params[0] = (*(GLbitfield *) p >> shift) & 1; |
||
1554 | break; |
||
1555 | } |
||
1556 | } |
||
1557 | |||
1558 | static enum value_type |
||
1559 | find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v) |
||
1560 | { |
||
1561 | GET_CURRENT_CONTEXT(ctx); |
||
1562 | |||
1563 | switch (pname) { |
||
1564 | |||
1565 | case GL_BLEND: |
||
1566 | if (index >= ctx->Const.MaxDrawBuffers) |
||
1567 | goto invalid_value; |
||
1568 | if (!ctx->Extensions.EXT_draw_buffers2) |
||
1569 | goto invalid_enum; |
||
1570 | v->value_int = (ctx->Color.BlendEnabled >> index) & 1; |
||
1571 | return TYPE_INT; |
||
1572 | |||
1573 | case GL_BLEND_SRC: |
||
1574 | /* fall-through */ |
||
1575 | case GL_BLEND_SRC_RGB: |
||
1576 | if (index >= ctx->Const.MaxDrawBuffers) |
||
1577 | goto invalid_value; |
||
1578 | if (!ctx->Extensions.ARB_draw_buffers_blend) |
||
1579 | goto invalid_enum; |
||
1580 | v->value_int = ctx->Color.Blend[index].SrcRGB; |
||
1581 | return TYPE_INT; |
||
1582 | case GL_BLEND_SRC_ALPHA: |
||
1583 | if (index >= ctx->Const.MaxDrawBuffers) |
||
1584 | goto invalid_value; |
||
1585 | if (!ctx->Extensions.ARB_draw_buffers_blend) |
||
1586 | goto invalid_enum; |
||
1587 | v->value_int = ctx->Color.Blend[index].SrcA; |
||
1588 | return TYPE_INT; |
||
1589 | case GL_BLEND_DST: |
||
1590 | /* fall-through */ |
||
1591 | case GL_BLEND_DST_RGB: |
||
1592 | if (index >= ctx->Const.MaxDrawBuffers) |
||
1593 | goto invalid_value; |
||
1594 | if (!ctx->Extensions.ARB_draw_buffers_blend) |
||
1595 | goto invalid_enum; |
||
1596 | v->value_int = ctx->Color.Blend[index].DstRGB; |
||
1597 | return TYPE_INT; |
||
1598 | case GL_BLEND_DST_ALPHA: |
||
1599 | if (index >= ctx->Const.MaxDrawBuffers) |
||
1600 | goto invalid_value; |
||
1601 | if (!ctx->Extensions.ARB_draw_buffers_blend) |
||
1602 | goto invalid_enum; |
||
1603 | v->value_int = ctx->Color.Blend[index].DstA; |
||
1604 | return TYPE_INT; |
||
1605 | case GL_BLEND_EQUATION_RGB: |
||
1606 | if (index >= ctx->Const.MaxDrawBuffers) |
||
1607 | goto invalid_value; |
||
1608 | if (!ctx->Extensions.ARB_draw_buffers_blend) |
||
1609 | goto invalid_enum; |
||
1610 | v->value_int = ctx->Color.Blend[index].EquationRGB; |
||
1611 | return TYPE_INT; |
||
1612 | case GL_BLEND_EQUATION_ALPHA: |
||
1613 | if (index >= ctx->Const.MaxDrawBuffers) |
||
1614 | goto invalid_value; |
||
1615 | if (!ctx->Extensions.ARB_draw_buffers_blend) |
||
1616 | goto invalid_enum; |
||
1617 | v->value_int = ctx->Color.Blend[index].EquationA; |
||
1618 | return TYPE_INT; |
||
1619 | |||
1620 | case GL_COLOR_WRITEMASK: |
||
1621 | if (index >= ctx->Const.MaxDrawBuffers) |
||
1622 | goto invalid_value; |
||
1623 | if (!ctx->Extensions.EXT_draw_buffers2) |
||
1624 | goto invalid_enum; |
||
1625 | v->value_int_4[0] = ctx->Color.ColorMask[index][RCOMP] ? 1 : 0; |
||
1626 | v->value_int_4[1] = ctx->Color.ColorMask[index][GCOMP] ? 1 : 0; |
||
1627 | v->value_int_4[2] = ctx->Color.ColorMask[index][BCOMP] ? 1 : 0; |
||
1628 | v->value_int_4[3] = ctx->Color.ColorMask[index][ACOMP] ? 1 : 0; |
||
1629 | return TYPE_INT_4; |
||
1630 | |||
1631 | case GL_TRANSFORM_FEEDBACK_BUFFER_START: |
||
1632 | if (index >= ctx->Const.MaxTransformFeedbackBuffers) |
||
1633 | goto invalid_value; |
||
1634 | if (!ctx->Extensions.EXT_transform_feedback) |
||
1635 | goto invalid_enum; |
||
1636 | v->value_int64 = ctx->TransformFeedback.CurrentObject->Offset[index]; |
||
1637 | return TYPE_INT64; |
||
1638 | |||
1639 | case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: |
||
1640 | if (index >= ctx->Const.MaxTransformFeedbackBuffers) |
||
1641 | goto invalid_value; |
||
1642 | if (!ctx->Extensions.EXT_transform_feedback) |
||
1643 | goto invalid_enum; |
||
1644 | v->value_int64 |
||
1645 | = ctx->TransformFeedback.CurrentObject->RequestedSize[index]; |
||
1646 | return TYPE_INT64; |
||
1647 | |||
1648 | case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: |
||
1649 | if (index >= ctx->Const.MaxTransformFeedbackBuffers) |
||
1650 | goto invalid_value; |
||
1651 | if (!ctx->Extensions.EXT_transform_feedback) |
||
1652 | goto invalid_enum; |
||
1653 | v->value_int = ctx->TransformFeedback.CurrentObject->BufferNames[index]; |
||
1654 | return TYPE_INT; |
||
1655 | |||
1656 | case GL_UNIFORM_BUFFER_BINDING: |
||
1657 | if (index >= ctx->Const.MaxUniformBufferBindings) |
||
1658 | goto invalid_value; |
||
1659 | if (!ctx->Extensions.ARB_uniform_buffer_object) |
||
1660 | goto invalid_enum; |
||
1661 | v->value_int = ctx->UniformBufferBindings[index].BufferObject->Name; |
||
1662 | return TYPE_INT; |
||
1663 | |||
1664 | case GL_UNIFORM_BUFFER_START: |
||
1665 | if (index >= ctx->Const.MaxUniformBufferBindings) |
||
1666 | goto invalid_value; |
||
1667 | if (!ctx->Extensions.ARB_uniform_buffer_object) |
||
1668 | goto invalid_enum; |
||
1669 | v->value_int = ctx->UniformBufferBindings[index].Offset; |
||
1670 | return TYPE_INT; |
||
1671 | |||
1672 | case GL_UNIFORM_BUFFER_SIZE: |
||
1673 | if (index >= ctx->Const.MaxUniformBufferBindings) |
||
1674 | goto invalid_value; |
||
1675 | if (!ctx->Extensions.ARB_uniform_buffer_object) |
||
1676 | goto invalid_enum; |
||
1677 | v->value_int = ctx->UniformBufferBindings[index].Size; |
||
1678 | return TYPE_INT; |
||
1679 | |||
1680 | /* ARB_texture_multisample / GL3.2 */ |
||
1681 | case GL_SAMPLE_MASK_VALUE: |
||
1682 | if (index != 0) |
||
1683 | goto invalid_value; |
||
1684 | if (!ctx->Extensions.ARB_texture_multisample) |
||
1685 | goto invalid_enum; |
||
1686 | v->value_int = ctx->Multisample.SampleMaskValue; |
||
1687 | return TYPE_INT; |
||
1688 | } |
||
1689 | |||
1690 | invalid_enum: |
||
1691 | _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=%s)", func, |
||
1692 | _mesa_lookup_enum_by_nr(pname)); |
||
1693 | return TYPE_INVALID; |
||
1694 | invalid_value: |
||
1695 | _mesa_error(ctx, GL_INVALID_VALUE, "%s(pname=%s)", func, |
||
1696 | _mesa_lookup_enum_by_nr(pname)); |
||
1697 | return TYPE_INVALID; |
||
1698 | } |
||
1699 | |||
1700 | void GLAPIENTRY |
||
1701 | _mesa_GetBooleani_v( GLenum pname, GLuint index, GLboolean *params ) |
||
1702 | { |
||
1703 | union value v; |
||
1704 | enum value_type type = |
||
1705 | find_value_indexed("glGetBooleani_v", pname, index, &v); |
||
1706 | |||
1707 | switch (type) { |
||
1708 | case TYPE_INT: |
||
1709 | params[0] = INT_TO_BOOLEAN(v.value_int); |
||
1710 | break; |
||
1711 | case TYPE_INT_4: |
||
1712 | params[0] = INT_TO_BOOLEAN(v.value_int_4[0]); |
||
1713 | params[1] = INT_TO_BOOLEAN(v.value_int_4[1]); |
||
1714 | params[2] = INT_TO_BOOLEAN(v.value_int_4[2]); |
||
1715 | params[3] = INT_TO_BOOLEAN(v.value_int_4[3]); |
||
1716 | break; |
||
1717 | case TYPE_INT64: |
||
1718 | params[0] = INT64_TO_BOOLEAN(v.value_int); |
||
1719 | break; |
||
1720 | default: |
||
1721 | ; /* nothing - GL error was recorded */ |
||
1722 | } |
||
1723 | } |
||
1724 | |||
1725 | void GLAPIENTRY |
||
1726 | _mesa_GetIntegeri_v( GLenum pname, GLuint index, GLint *params ) |
||
1727 | { |
||
1728 | union value v; |
||
1729 | enum value_type type = |
||
1730 | find_value_indexed("glGetIntegeri_v", pname, index, &v); |
||
1731 | |||
1732 | switch (type) { |
||
1733 | case TYPE_INT: |
||
1734 | params[0] = v.value_int; |
||
1735 | break; |
||
1736 | case TYPE_INT_4: |
||
1737 | params[0] = v.value_int_4[0]; |
||
1738 | params[1] = v.value_int_4[1]; |
||
1739 | params[2] = v.value_int_4[2]; |
||
1740 | params[3] = v.value_int_4[3]; |
||
1741 | break; |
||
1742 | case TYPE_INT64: |
||
1743 | params[0] = INT64_TO_INT(v.value_int); |
||
1744 | break; |
||
1745 | default: |
||
1746 | ; /* nothing - GL error was recorded */ |
||
1747 | } |
||
1748 | } |
||
1749 | |||
1750 | void GLAPIENTRY |
||
1751 | _mesa_GetInteger64i_v( GLenum pname, GLuint index, GLint64 *params ) |
||
1752 | { |
||
1753 | union value v; |
||
1754 | enum value_type type = |
||
1755 | find_value_indexed("glGetInteger64i_v", pname, index, &v); |
||
1756 | |||
1757 | switch (type) { |
||
1758 | case TYPE_INT: |
||
1759 | params[0] = v.value_int; |
||
1760 | break; |
||
1761 | case TYPE_INT_4: |
||
1762 | params[0] = v.value_int_4[0]; |
||
1763 | params[1] = v.value_int_4[1]; |
||
1764 | params[2] = v.value_int_4[2]; |
||
1765 | params[3] = v.value_int_4[3]; |
||
1766 | break; |
||
1767 | case TYPE_INT64: |
||
1768 | params[0] = v.value_int; |
||
1769 | break; |
||
1770 | default: |
||
1771 | ; /* nothing - GL error was recorded */ |
||
1772 | } |
||
1773 | } |
||
1774 | |||
1775 | void GLAPIENTRY |
||
1776 | _mesa_GetFixedv(GLenum pname, GLfixed *params) |
||
1777 | { |
||
1778 | const struct value_desc *d; |
||
1779 | union value v; |
||
1780 | GLmatrix *m; |
||
1781 | int shift, i; |
||
1782 | void *p; |
||
1783 | |||
1784 | d = find_value("glGetDoublev", pname, &p, &v); |
||
1785 | switch (d->type) { |
||
1786 | case TYPE_INVALID: |
||
1787 | break; |
||
1788 | case TYPE_CONST: |
||
1789 | params[0] = INT_TO_FIXED(d->offset); |
||
1790 | break; |
||
1791 | |||
1792 | case TYPE_FLOAT_4: |
||
1793 | case TYPE_FLOATN_4: |
||
1794 | params[3] = FLOAT_TO_FIXED(((GLfloat *) p)[3]); |
||
1795 | case TYPE_FLOAT_3: |
||
1796 | case TYPE_FLOATN_3: |
||
1797 | params[2] = FLOAT_TO_FIXED(((GLfloat *) p)[2]); |
||
1798 | case TYPE_FLOAT_2: |
||
1799 | case TYPE_FLOATN_2: |
||
1800 | params[1] = FLOAT_TO_FIXED(((GLfloat *) p)[1]); |
||
1801 | case TYPE_FLOAT: |
||
1802 | case TYPE_FLOATN: |
||
1803 | params[0] = FLOAT_TO_FIXED(((GLfloat *) p)[0]); |
||
1804 | break; |
||
1805 | |||
1806 | case TYPE_DOUBLEN: |
||
1807 | params[0] = FLOAT_TO_FIXED(((GLdouble *) p)[0]); |
||
1808 | break; |
||
1809 | |||
1810 | case TYPE_INT_4: |
||
1811 | params[3] = INT_TO_FIXED(((GLint *) p)[3]); |
||
1812 | case TYPE_INT_3: |
||
1813 | params[2] = INT_TO_FIXED(((GLint *) p)[2]); |
||
1814 | case TYPE_INT_2: |
||
1815 | case TYPE_ENUM_2: |
||
1816 | params[1] = INT_TO_FIXED(((GLint *) p)[1]); |
||
1817 | case TYPE_INT: |
||
1818 | case TYPE_ENUM: |
||
1819 | params[0] = INT_TO_FIXED(((GLint *) p)[0]); |
||
1820 | break; |
||
1821 | |||
1822 | case TYPE_INT_N: |
||
1823 | for (i = 0; i < v.value_int_n.n; i++) |
||
1824 | params[i] = INT_TO_FIXED(v.value_int_n.ints[i]); |
||
1825 | break; |
||
1826 | |||
1827 | case TYPE_INT64: |
||
1828 | params[0] = ((GLint64 *) p)[0]; |
||
1829 | break; |
||
1830 | |||
1831 | case TYPE_BOOLEAN: |
||
1832 | params[0] = BOOLEAN_TO_FIXED(((GLboolean*) p)[0]); |
||
1833 | break; |
||
1834 | |||
1835 | case TYPE_MATRIX: |
||
1836 | m = *(GLmatrix **) p; |
||
1837 | for (i = 0; i < 16; i++) |
||
1838 | params[i] = FLOAT_TO_FIXED(m->m[i]); |
||
1839 | break; |
||
1840 | |||
1841 | case TYPE_MATRIX_T: |
||
1842 | m = *(GLmatrix **) p; |
||
1843 | for (i = 0; i < 16; i++) |
||
1844 | params[i] = FLOAT_TO_FIXED(m->m[transpose[i]]); |
||
1845 | break; |
||
1846 | |||
1847 | case TYPE_BIT_0: |
||
1848 | case TYPE_BIT_1: |
||
1849 | case TYPE_BIT_2: |
||
1850 | case TYPE_BIT_3: |
||
1851 | case TYPE_BIT_4: |
||
1852 | case TYPE_BIT_5: |
||
1853 | case TYPE_BIT_6: |
||
1854 | case TYPE_BIT_7: |
||
1855 | shift = d->type - TYPE_BIT_0; |
||
1856 | params[0] = BOOLEAN_TO_FIXED((*(GLbitfield *) p >> shift) & 1); |
||
1857 | break; |
||
1858 | } |
||
1859 | }>>>>>>>>>>>>>>>>>>=>><>>>>>>>><>>>> |