1 /*
2 * Cogl
3 *
4 * A Low Level GPU Graphics and Utilities API
5 *
6 * Copyright (C) 2009 Intel Corporation.
7 *
8 * Permission is hereby granted, free of charge, to any person
9 * obtaining a copy of this software and associated documentation
10 * files (the "Software"), to deal in the Software without
11 * restriction, including without limitation the rights to use, copy,
12 * modify, merge, publish, distribute, sublicense, and/or sell copies
13 * of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be
17 * included in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
23 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
24 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 *
28 *
29 */
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <string.h>
36
37 #include "cogl-context-private.h"
38
39 #include "cogl-feature-private.h"
40 #include "cogl-renderer-private.h"
41 #include "cogl-private.h"
42
43 CoglBool
_cogl_feature_check(CoglRenderer * renderer,const char * driver_prefix,const CoglFeatureData * data,int gl_major,int gl_minor,CoglDriver driver,char * const * extensions,void * function_table)44 _cogl_feature_check (CoglRenderer *renderer,
45 const char *driver_prefix,
46 const CoglFeatureData *data,
47 int gl_major,
48 int gl_minor,
49 CoglDriver driver,
50 char * const *extensions,
51 void *function_table)
52
53 {
54 const char *suffix = NULL;
55 int func_num;
56 CoglExtGlesAvailability gles_availability = 0;
57 CoglBool in_core;
58
59 switch (driver)
60 {
61 case COGL_DRIVER_GLES1:
62 gles_availability = COGL_EXT_IN_GLES;
63 break;
64 case COGL_DRIVER_GLES2:
65 gles_availability = COGL_EXT_IN_GLES2;
66
67 if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 3, 0))
68 gles_availability |= COGL_EXT_IN_GLES3;
69 break;
70 case COGL_DRIVER_ANY:
71 g_assert_not_reached ();
72 case COGL_DRIVER_WEBGL:
73 /* FIXME: WebGL should probably have its own COGL_EXT_IN_WEBGL flag */
74 break;
75 case COGL_DRIVER_NOP:
76 case COGL_DRIVER_GL:
77 case COGL_DRIVER_GL3:
78 break;
79 }
80
81 /* First check whether the functions should be directly provided by
82 GL */
83 if (((driver == COGL_DRIVER_GL ||
84 driver == COGL_DRIVER_GL3) &&
85 COGL_CHECK_GL_VERSION (gl_major, gl_minor,
86 data->min_gl_major, data->min_gl_minor)) ||
87 (data->gles_availability & gles_availability))
88 {
89 suffix = "";
90 in_core = TRUE;
91 }
92 else
93 {
94 /* Otherwise try all of the extensions */
95 const char *namespace, *namespace_suffix;
96 unsigned int namespace_len;
97
98 for (namespace = data->namespaces;
99 *namespace;
100 namespace += strlen (namespace) + 1)
101 {
102 const char *extension;
103 GString *full_extension_name = g_string_new ("");
104
105 /* If the namespace part contains a ':' then the suffix for
106 the function names is different from the name space */
107 if ((namespace_suffix = strchr (namespace, ':')))
108 {
109 namespace_len = namespace_suffix - namespace;
110 namespace_suffix++;
111 }
112 else
113 {
114 namespace_len = strlen (namespace);
115 namespace_suffix = namespace;
116 }
117
118 for (extension = data->extension_names;
119 *extension;
120 extension += strlen (extension) + 1)
121 {
122 g_string_assign (full_extension_name, driver_prefix);
123 g_string_append_c (full_extension_name, '_');
124 g_string_append_len (full_extension_name,
125 namespace, namespace_len);
126 g_string_append_c (full_extension_name, '_');
127 g_string_append (full_extension_name, extension);
128 if (_cogl_check_extension (full_extension_name->str,
129 extensions))
130 break;
131 }
132
133 g_string_free (full_extension_name, TRUE);
134
135 /* If we found an extension with this namespace then use it
136 as the suffix */
137 if (*extension)
138 {
139 suffix = namespace_suffix;
140 break;
141 }
142 }
143
144 in_core = FALSE;
145 }
146
147 /* If we couldn't find anything that provides the functions then
148 give up */
149 if (suffix == NULL)
150 goto error;
151
152 /* Try to get all of the entry points */
153 for (func_num = 0; data->functions[func_num].name; func_num++)
154 {
155 void *func;
156 char *full_function_name;
157
158 full_function_name = g_strconcat (data->functions[func_num].name,
159 suffix, NULL);
160 func = _cogl_renderer_get_proc_address (renderer,
161 full_function_name,
162 in_core);
163 g_free (full_function_name);
164
165 if (func == NULL)
166 goto error;
167
168 /* Set the function pointer in the context */
169 *(void **) ((uint8_t *) function_table +
170 data->functions[func_num].pointer_offset) = func;
171 }
172
173 return TRUE;
174
175 /* If the extension isn't found or one of the functions wasn't found
176 * then set all of the functions pointers to NULL so Cogl can safely
177 * do feature testing by just looking at the function pointers */
178 error:
179 for (func_num = 0; data->functions[func_num].name; func_num++)
180 *(void **) ((uint8_t *) function_table +
181 data->functions[func_num].pointer_offset) = NULL;
182
183 return FALSE;
184 }
185
186 /* Define a set of arrays containing the functions required from GL
187 for each feature */
188 #define COGL_EXT_BEGIN(name, \
189 min_gl_major, min_gl_minor, \
190 gles_availability, \
191 namespaces, extension_names) \
192 static const CoglFeatureFunction cogl_ext_ ## name ## _funcs[] = {
193 #define COGL_EXT_FUNCTION(ret, name, args) \
194 { G_STRINGIFY (name), G_STRUCT_OFFSET (CoglContext, name) },
195 #define COGL_EXT_END() \
196 { NULL, 0 }, \
197 };
198 #include "gl-prototypes/cogl-all-functions.h"
199
200 /* Define an array of features */
201 #undef COGL_EXT_BEGIN
202 #define COGL_EXT_BEGIN(name, \
203 min_gl_major, min_gl_minor, \
204 gles_availability, \
205 namespaces, extension_names) \
206 { min_gl_major, min_gl_minor, gles_availability, namespaces, \
207 extension_names, 0, 0, 0, \
208 cogl_ext_ ## name ## _funcs },
209 #undef COGL_EXT_FUNCTION
210 #define COGL_EXT_FUNCTION(ret, name, args)
211 #undef COGL_EXT_END
212 #define COGL_EXT_END()
213
214 static const CoglFeatureData
215 cogl_feature_ext_functions_data[] =
216 {
217 #include "gl-prototypes/cogl-all-functions.h"
218 };
219
220 void
_cogl_feature_check_ext_functions(CoglContext * context,int gl_major,int gl_minor,char * const * gl_extensions)221 _cogl_feature_check_ext_functions (CoglContext *context,
222 int gl_major,
223 int gl_minor,
224 char * const *gl_extensions)
225 {
226 int i;
227
228 for (i = 0; i < G_N_ELEMENTS (cogl_feature_ext_functions_data); i++)
229 _cogl_feature_check (context->display->renderer,
230 "GL", cogl_feature_ext_functions_data + i,
231 gl_major, gl_minor, context->driver,
232 gl_extensions,
233 context);
234 }
235