"Initial commit to Gerrit"
[profile/ivi/cogl.git] / cogl / driver / gl / cogl-gl.c
1 /*
2  * Cogl
3  *
4  * An object oriented GL/GLES Abstraction/Utility Layer
5  *
6  * Copyright (C) 2007,2008,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-private.h"
31 #include "cogl-internal.h"
32 #include "cogl-context-private.h"
33 #include "cogl-feature-private.h"
34 #include "cogl-renderer-private.h"
35
36 static gboolean
37 _cogl_get_gl_version (int *major_out, int *minor_out)
38 {
39   const char *version_string, *major_end, *minor_end;
40   int major = 0, minor = 0;
41
42   _COGL_GET_CONTEXT (ctx, FALSE);
43
44   /* Get the OpenGL version number */
45   if ((version_string = (const char *) ctx->glGetString (GL_VERSION)) == NULL)
46     return FALSE;
47
48   /* Extract the major number */
49   for (major_end = version_string; *major_end >= '0'
50          && *major_end <= '9'; major_end++)
51     major = (major * 10) + *major_end - '0';
52   /* If there were no digits or the major number isn't followed by a
53      dot then it is invalid */
54   if (major_end == version_string || *major_end != '.')
55     return FALSE;
56
57   /* Extract the minor number */
58   for (minor_end = major_end + 1; *minor_end >= '0'
59          && *minor_end <= '9'; minor_end++)
60     minor = (minor * 10) + *minor_end - '0';
61   /* If there were no digits or there is an unexpected character then
62      it is invalid */
63   if (minor_end == major_end + 1
64       || (*minor_end && *minor_end != ' ' && *minor_end != '.'))
65     return FALSE;
66
67   *major_out = major;
68   *minor_out = minor;
69
70   return TRUE;
71 }
72
73 static gboolean
74 check_gl_version (CoglContext *ctx,
75                   GError **error)
76 {
77   int major, minor;
78   const char *gl_extensions;
79
80   if (!_cogl_get_gl_version (&major, &minor))
81     {
82       g_set_error (error,
83                    COGL_DRIVER_ERROR,
84                    COGL_DRIVER_ERROR_UNKNOWN_VERSION,
85                    "The OpenGL version could not be determined");
86       return FALSE;
87     }
88
89   /* GL 1.3 supports all of the required functionality in core */
90   if (COGL_CHECK_GL_VERSION (major, minor, 1, 3))
91     return TRUE;
92
93   gl_extensions = (const char*) ctx->glGetString (GL_EXTENSIONS);
94
95   /* OpenGL 1.2 is only supported if we have the multitexturing
96      extension */
97   if (!_cogl_check_extension ("GL_ARB_multitexture", gl_extensions))
98     {
99       g_set_error (error,
100                    COGL_DRIVER_ERROR,
101                    COGL_DRIVER_ERROR_INVALID_VERSION,
102                    "The OpenGL driver is missing "
103                    "the GL_ARB_multitexture extension");
104       return FALSE;
105     }
106
107   /* OpenGL 1.2 is required */
108   if (!COGL_CHECK_GL_VERSION (major, minor, 1, 2))
109     {
110       g_set_error (error,
111                    COGL_DRIVER_ERROR,
112                    COGL_DRIVER_ERROR_INVALID_VERSION,
113                    "The OpenGL version of your driver (%i.%i) "
114                    "is not compatible with Cogl",
115                    major, minor);
116       return FALSE;
117     }
118
119   return TRUE;
120 }
121
122 gboolean
123 _cogl_gl_update_features (CoglContext *context,
124                           GError **error)
125 {
126   CoglPrivateFeatureFlags private_flags = 0;
127   CoglFeatureFlags flags = 0;
128   const char *gl_extensions;
129   int max_clip_planes = 0;
130   int num_stencil_bits = 0;
131   int gl_major = 0, gl_minor = 0;
132
133   _COGL_GET_CONTEXT (ctx, FALSE);
134
135   /* We have to special case getting the pointer to the glGetString
136      function because we need to use it to determine what functions we
137      can expect */
138   context->glGetString =
139     (void *) _cogl_renderer_get_proc_address (context->display->renderer,
140                                               "glGetString");
141
142   if (!check_gl_version (context, error))
143     return FALSE;
144
145   COGL_NOTE (WINSYS,
146              "Checking features\n"
147              "  GL_VENDOR: %s\n"
148              "  GL_RENDERER: %s\n"
149              "  GL_VERSION: %s\n"
150              "  GL_EXTENSIONS: %s",
151              ctx->glGetString (GL_VENDOR),
152              ctx->glGetString (GL_RENDERER),
153              ctx->glGetString (GL_VERSION),
154              ctx->glGetString (GL_EXTENSIONS));
155
156   _cogl_get_gl_version (&gl_major, &gl_minor);
157
158   flags = (COGL_FEATURE_TEXTURE_READ_PIXELS
159            | COGL_FEATURE_UNSIGNED_INT_INDICES
160            | COGL_FEATURE_DEPTH_RANGE);
161   COGL_FLAGS_SET (ctx->features,
162                   COGL_FEATURE_ID_UNSIGNED_INT_INDICES, TRUE);
163   COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_DEPTH_RANGE, TRUE);
164
165   if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 1, 4))
166     COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_MIRRORED_REPEAT, TRUE);
167
168   gl_extensions = (const char *)ctx->glGetString (GL_EXTENSIONS);
169
170   _cogl_feature_check_ext_functions (context,
171                                      gl_major,
172                                      gl_minor,
173                                      gl_extensions);
174
175   if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 0) ||
176       _cogl_check_extension ("GL_ARB_texture_non_power_of_two", gl_extensions))
177     {
178       flags |= COGL_FEATURE_TEXTURE_NPOT
179         | COGL_FEATURE_TEXTURE_NPOT_BASIC
180         | COGL_FEATURE_TEXTURE_NPOT_MIPMAP
181         | COGL_FEATURE_TEXTURE_NPOT_REPEAT;
182       COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_TEXTURE_NPOT, TRUE);
183       COGL_FLAGS_SET (ctx->features,
184                       COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE);
185       COGL_FLAGS_SET (ctx->features,
186                       COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP, TRUE);
187       COGL_FLAGS_SET (ctx->features,
188                       COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT, TRUE);
189     }
190
191   if (_cogl_check_extension ("GL_MESA_pack_invert", gl_extensions))
192     private_flags |= COGL_PRIVATE_FEATURE_MESA_PACK_INVERT;
193
194   GE( ctx, glGetIntegerv (GL_STENCIL_BITS, &num_stencil_bits) );
195   /* We need at least three stencil bits to combine clips */
196   if (num_stencil_bits > 2)
197     private_flags |= COGL_PRIVATE_FEATURE_STENCIL_BUFFER;
198
199   GE( ctx, glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) );
200   if (max_clip_planes >= 4)
201     private_flags |= COGL_PRIVATE_FEATURE_FOUR_CLIP_PLANES;
202
203   if (context->glGenRenderbuffers)
204     {
205       flags |= COGL_FEATURE_OFFSCREEN;
206       COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_OFFSCREEN, TRUE);
207     }
208
209   if (context->glBlitFramebuffer)
210     private_flags |= COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT;
211
212   if (context->glRenderbufferStorageMultisampleIMG)
213     {
214       flags |= COGL_FEATURE_OFFSCREEN_MULTISAMPLE;
215       COGL_FLAGS_SET (ctx->features,
216                       COGL_FEATURE_ID_OFFSCREEN_MULTISAMPLE, TRUE);
217     }
218
219   if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 1) ||
220       _cogl_check_extension ("GL_EXT_pixel_buffer_object", gl_extensions))
221     private_flags |= COGL_PRIVATE_FEATURE_PBOS;
222
223   if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 0) ||
224       _cogl_check_extension ("GL_ARB_point_sprite", gl_extensions))
225     {
226       flags |= COGL_FEATURE_POINT_SPRITE;
227       COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_POINT_SPRITE, TRUE);
228     }
229
230   if (context->glGenPrograms)
231     {
232       flags |= COGL_FEATURE_SHADERS_ARBFP;
233       COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_ARBFP, TRUE);
234     }
235
236   if (context->glCreateProgram)
237     {
238       flags |= COGL_FEATURE_SHADERS_GLSL;
239       COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_GLSL, TRUE);
240     }
241
242   if (context->glGenBuffers)
243     {
244       private_flags |= COGL_PRIVATE_FEATURE_VBOS;
245       flags |= (COGL_FEATURE_MAP_BUFFER_FOR_READ |
246                 COGL_FEATURE_MAP_BUFFER_FOR_WRITE);
247       COGL_FLAGS_SET (ctx->features,
248                          COGL_FEATURE_ID_MAP_BUFFER_FOR_READ, TRUE);
249       COGL_FLAGS_SET (ctx->features,
250                       COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE, TRUE);
251     }
252
253   if (_cogl_check_extension ("GL_ARB_texture_rectangle", gl_extensions))
254     {
255       flags |= COGL_FEATURE_TEXTURE_RECTANGLE;
256       COGL_FLAGS_SET (ctx->features,
257                       COGL_FEATURE_ID_TEXTURE_RECTANGLE, TRUE);
258     }
259
260   if (context->glTexImage3D)
261     {
262       flags |= COGL_FEATURE_TEXTURE_3D;
263       COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_TEXTURE_3D, TRUE);
264     }
265
266   if (context->glEGLImageTargetTexture2D)
267     private_flags |= COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE;
268
269   if (_cogl_check_extension ("GL_EXT_packed_depth_stencil", gl_extensions))
270     private_flags |= COGL_PRIVATE_FEATURE_EXT_PACKED_DEPTH_STENCIL;
271
272   /* Cache features */
273   context->private_feature_flags |= private_flags;
274   context->feature_flags |= flags;
275
276   return TRUE;
277 }