"Initial commit to Gerrit"
[profile/ivi/cogl.git] / cogl / cogl-feature-private.c
1 /*
2  * Cogl
3  *
4  * An object oriented GL/GLES Abstraction/Utility Layer
5  *
6  * Copyright (C) 2009 Intel Corporation.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20  *
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <string.h>
29
30 #include "cogl-context-private.h"
31
32 #include "cogl-feature-private.h"
33 #include "cogl-renderer-private.h"
34
35 gboolean
36 _cogl_feature_check (CoglRenderer *renderer,
37                      const char *driver_prefix,
38                      const CoglFeatureData *data,
39                      int gl_major,
40                      int gl_minor,
41                      CoglDriver driver,
42                      const char *extensions_string,
43                      void *function_table)
44
45 {
46   const char *suffix = NULL;
47   int func_num;
48
49   /* First check whether the functions should be directly provided by
50      GL */
51   if ((driver == COGL_DRIVER_GL &&
52        COGL_CHECK_GL_VERSION (gl_major, gl_minor,
53                               data->min_gl_major, data->min_gl_minor)) ||
54       (driver == COGL_DRIVER_GLES1 &&
55        (data->gles_availability & COGL_EXT_IN_GLES)) ||
56       (driver == COGL_DRIVER_GLES2 &&
57        (data->gles_availability & COGL_EXT_IN_GLES2)))
58     suffix = "";
59   else
60     {
61       /* Otherwise try all of the extensions */
62       const char *namespace, *namespace_suffix;
63       unsigned int namespace_len;
64
65       for (namespace = data->namespaces;
66            *namespace;
67            namespace += strlen (namespace) + 1)
68         {
69           const char *extension;
70           GString *full_extension_name = g_string_new ("");
71
72           /* If the namespace part contains a ':' then the suffix for
73              the function names is different from the name space */
74           if ((namespace_suffix = strchr (namespace, ':')))
75             {
76               namespace_len = namespace_suffix - namespace;
77               namespace_suffix++;
78             }
79           else
80             {
81               namespace_len = strlen (namespace);
82               namespace_suffix = namespace;
83             }
84
85           for (extension = data->extension_names;
86                *extension;
87                extension += strlen (extension) + 1)
88             {
89               g_string_assign (full_extension_name, driver_prefix);
90               g_string_append_c (full_extension_name, '_');
91               g_string_append_len (full_extension_name,
92                                    namespace, namespace_len);
93               g_string_append_c (full_extension_name, '_');
94               g_string_append (full_extension_name, extension);
95               if (_cogl_check_extension (full_extension_name->str,
96                                          extensions_string))
97                 break;
98             }
99
100           g_string_free (full_extension_name, TRUE);
101
102           /* If we found an extension with this namespace then use it
103              as the suffix */
104           if (*extension)
105             {
106               suffix = namespace_suffix;
107               break;
108             }
109         }
110     }
111
112   /* If we couldn't find anything that provides the functions then
113      give up */
114   if (suffix == NULL)
115     goto error;
116
117   /* Try to get all of the entry points */
118   for (func_num = 0; data->functions[func_num].name; func_num++)
119     {
120       void *func;
121       char *full_function_name;
122
123       full_function_name = g_strconcat (data->functions[func_num].name,
124                                         suffix, NULL);
125       func = _cogl_renderer_get_proc_address (renderer, full_function_name);
126       g_free (full_function_name);
127
128       if (func == NULL)
129         goto error;
130
131       /* Set the function pointer in the context */
132       *(void **) ((guint8 *) function_table +
133                   data->functions[func_num].pointer_offset) = func;
134     }
135
136   return TRUE;
137
138   /* If the extension isn't found or one of the functions wasn't found
139    * then set all of the functions pointers to NULL so Cogl can safely
140    * do feature testing by just looking at the function pointers */
141 error:
142   for (func_num = 0; data->functions[func_num].name; func_num++)
143     *(void **) ((guint8 *) function_table +
144                 data->functions[func_num].pointer_offset) = NULL;
145
146   return FALSE;
147 }
148
149 /* Define a set of arrays containing the functions required from GL
150    for each feature */
151 #define COGL_EXT_BEGIN(name,                                            \
152                        min_gl_major, min_gl_minor,                      \
153                        gles_availability,                               \
154                        namespaces, extension_names)                     \
155   static const CoglFeatureFunction cogl_ext_ ## name ## _funcs[] = {
156 #define COGL_EXT_FUNCTION(ret, name, args)                          \
157   { G_STRINGIFY (name), G_STRUCT_OFFSET (CoglContext, name) },
158 #define COGL_EXT_END()                      \
159   { NULL, 0 },                                  \
160   };
161 #include "gl-prototypes/cogl-all-functions.h"
162
163 /* Define an array of features */
164 #undef COGL_EXT_BEGIN
165 #define COGL_EXT_BEGIN(name,                                            \
166                        min_gl_major, min_gl_minor,                      \
167                        gles_availability,                               \
168                        namespaces, extension_names)                     \
169   { min_gl_major, min_gl_minor, gles_availability, namespaces,          \
170       extension_names, 0, 0, 0,                                         \
171     cogl_ext_ ## name ## _funcs },
172 #undef COGL_EXT_FUNCTION
173 #define COGL_EXT_FUNCTION(ret, name, args)
174 #undef COGL_EXT_END
175 #define COGL_EXT_END()
176
177 static const CoglFeatureData
178 cogl_feature_ext_functions_data[] =
179   {
180 #include "gl-prototypes/cogl-all-functions.h"
181   };
182
183 void
184 _cogl_feature_check_ext_functions (CoglContext *context,
185                                    int gl_major,
186                                    int gl_minor,
187                                    const char *gl_extensions)
188 {
189   int i;
190
191   for (i = 0; i < G_N_ELEMENTS (cogl_feature_ext_functions_data); i++)
192     _cogl_feature_check (context->display->renderer,
193                          "GL", cogl_feature_ext_functions_data + i,
194                          gl_major, gl_minor, context->driver,
195                          gl_extensions,
196                          context);
197 }