summaryrefslogtreecommitdiff
path: root/cogl/driver/gl/cogl.c
diff options
context:
space:
mode:
Diffstat (limited to 'cogl/driver/gl/cogl.c')
-rw-r--r--cogl/driver/gl/cogl.c443
1 files changed, 443 insertions, 0 deletions
diff --git a/cogl/driver/gl/cogl.c b/cogl/driver/gl/cogl.c
new file mode 100644
index 00000000..04d3b750
--- /dev/null
+++ b/cogl/driver/gl/cogl.c
@@ -0,0 +1,443 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2007,2008,2009 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "cogl.h"
+
+#include "cogl-internal.h"
+#include "cogl-context.h"
+
+gboolean
+cogl_check_extension (const gchar *name, const gchar *ext)
+{
+ gchar *end;
+ gint name_len, n;
+
+ if (name == NULL || ext == NULL)
+ return FALSE;
+
+ end = (gchar*)(ext + strlen(ext));
+
+ name_len = strlen(name);
+
+ while (ext < end)
+ {
+ n = strcspn(ext, " ");
+
+ if ((name_len == n) && (!strncmp(name, ext, n)))
+ return TRUE;
+ ext += (n + 1);
+ }
+
+ return FALSE;
+}
+
+#ifdef HAVE_CLUTTER_OSX
+static gboolean
+really_enable_npot (void)
+{
+ /* OSX backend + ATI Radeon X1600 + NPOT texture + GL_REPEAT seems to crash
+ * http://bugzilla.openedhand.com/show_bug.cgi?id=929
+ *
+ * Temporary workaround until post 0.8 we rejig the features set up a
+ * little to allow the backend to overide.
+ */
+ const char *gl_renderer;
+ const char *env_string;
+
+ /* Regardless of hardware, allow user to decide. */
+ env_string = g_getenv ("COGL_ENABLE_NPOT");
+ if (env_string != NULL)
+ return env_string[0] == '1';
+
+ gl_renderer = (char*)glGetString (GL_RENDERER);
+ if (strstr (gl_renderer, "ATI Radeon X1600") != NULL)
+ return FALSE;
+
+ return TRUE;
+}
+#endif
+
+void
+_cogl_features_init (void)
+{
+ CoglFeatureFlags flags = 0;
+ const gchar *gl_extensions;
+ GLint max_clip_planes = 0;
+ GLint num_stencil_bits = 0;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ flags = COGL_FEATURE_TEXTURE_READ_PIXELS;
+
+ gl_extensions = (const gchar*) glGetString (GL_EXTENSIONS);
+
+ if (cogl_check_extension ("GL_ARB_texture_non_power_of_two", gl_extensions))
+ {
+#ifdef HAVE_CLUTTER_OSX
+ if (really_enable_npot ())
+#endif
+ flags |= COGL_FEATURE_TEXTURE_NPOT;
+ }
+
+#ifdef GL_YCBCR_MESA
+ if (cogl_check_extension ("GL_MESA_ycbcr_texture", gl_extensions))
+ {
+ flags |= COGL_FEATURE_TEXTURE_YUV;
+ }
+#endif
+
+ if (cogl_check_extension ("GL_ARB_shader_objects", gl_extensions) &&
+ cogl_check_extension ("GL_ARB_vertex_shader", gl_extensions) &&
+ cogl_check_extension ("GL_ARB_fragment_shader", gl_extensions))
+ {
+ ctx->drv.pf_glCreateProgramObjectARB =
+ (COGL_PFNGLCREATEPROGRAMOBJECTARBPROC)
+ cogl_get_proc_address ("glCreateProgramObjectARB");
+
+ ctx->drv.pf_glCreateShaderObjectARB =
+ (COGL_PFNGLCREATESHADEROBJECTARBPROC)
+ cogl_get_proc_address ("glCreateShaderObjectARB");
+
+ ctx->drv.pf_glShaderSourceARB =
+ (COGL_PFNGLSHADERSOURCEARBPROC)
+ cogl_get_proc_address ("glShaderSourceARB");
+
+ ctx->drv.pf_glCompileShaderARB =
+ (COGL_PFNGLCOMPILESHADERARBPROC)
+ cogl_get_proc_address ("glCompileShaderARB");
+
+ ctx->drv.pf_glAttachObjectARB =
+ (COGL_PFNGLATTACHOBJECTARBPROC)
+ cogl_get_proc_address ("glAttachObjectARB");
+
+ ctx->drv.pf_glLinkProgramARB =
+ (COGL_PFNGLLINKPROGRAMARBPROC)
+ cogl_get_proc_address ("glLinkProgramARB");
+
+ ctx->drv.pf_glUseProgramObjectARB =
+ (COGL_PFNGLUSEPROGRAMOBJECTARBPROC)
+ cogl_get_proc_address ("glUseProgramObjectARB");
+
+ ctx->drv.pf_glGetUniformLocationARB =
+ (COGL_PFNGLGETUNIFORMLOCATIONARBPROC)
+ cogl_get_proc_address ("glGetUniformLocationARB");
+
+ ctx->drv.pf_glDeleteObjectARB =
+ (COGL_PFNGLDELETEOBJECTARBPROC)
+ cogl_get_proc_address ("glDeleteObjectARB");
+
+ ctx->drv.pf_glGetInfoLogARB =
+ (COGL_PFNGLGETINFOLOGARBPROC)
+ cogl_get_proc_address ("glGetInfoLogARB");
+
+ ctx->drv.pf_glGetObjectParameterivARB =
+ (COGL_PFNGLGETOBJECTPARAMETERIVARBPROC)
+ cogl_get_proc_address ("glGetObjectParameterivARB");
+
+ ctx->drv.pf_glUniform1fARB =
+ (COGL_PFNGLUNIFORM1FARBPROC)
+ cogl_get_proc_address ("glUniform1fARB");
+
+ ctx->drv.pf_glVertexAttribPointerARB =
+ (COGL_PFNGLVERTEXATTRIBPOINTERARBPROC)
+ cogl_get_proc_address ("glVertexAttribPointerARB");
+
+ ctx->drv.pf_glEnableVertexAttribArrayARB =
+ (COGL_PFNGLENABLEVERTEXATTRIBARRAYARBPROC)
+ cogl_get_proc_address ("glEnableVertexAttribArrayARB");
+
+ ctx->drv.pf_glDisableVertexAttribArrayARB =
+ (COGL_PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)
+ cogl_get_proc_address ("glDisableVertexAttribArrayARB");
+
+ ctx->drv.pf_glUniform2fARB =
+ (COGL_PFNGLUNIFORM2FARBPROC)
+ cogl_get_proc_address ("glUniform2fARB");
+
+ ctx->drv.pf_glUniform3fARB =
+ (COGL_PFNGLUNIFORM3FARBPROC)
+ cogl_get_proc_address ("glUniform3fARB");
+
+ ctx->drv.pf_glUniform4fARB =
+ (COGL_PFNGLUNIFORM4FARBPROC)
+ cogl_get_proc_address ("glUniform4fARB");
+
+ ctx->drv.pf_glUniform1fvARB =
+ (COGL_PFNGLUNIFORM1FVARBPROC)
+ cogl_get_proc_address ("glUniform1fvARB");
+
+ ctx->drv.pf_glUniform2fvARB =
+ (COGL_PFNGLUNIFORM2FVARBPROC)
+ cogl_get_proc_address ("glUniform2fvARB");
+
+ ctx->drv.pf_glUniform3fvARB =
+ (COGL_PFNGLUNIFORM3FVARBPROC)
+ cogl_get_proc_address ("glUniform3fvARB");
+
+ ctx->drv.pf_glUniform4fvARB =
+ (COGL_PFNGLUNIFORM4FVARBPROC)
+ cogl_get_proc_address ("glUniform4fvARB");
+
+ ctx->drv.pf_glUniform1iARB =
+ (COGL_PFNGLUNIFORM1IARBPROC)
+ cogl_get_proc_address ("glUniform1iARB");
+
+ ctx->drv.pf_glUniform2iARB =
+ (COGL_PFNGLUNIFORM2IARBPROC)
+ cogl_get_proc_address ("glUniform2iARB");
+
+ ctx->drv.pf_glUniform3iARB =
+ (COGL_PFNGLUNIFORM3IARBPROC)
+ cogl_get_proc_address ("glUniform3iARB");
+
+ ctx->drv.pf_glUniform4iARB =
+ (COGL_PFNGLUNIFORM4IARBPROC)
+ cogl_get_proc_address ("glUniform4iARB");
+
+ ctx->drv.pf_glUniform1ivARB =
+ (COGL_PFNGLUNIFORM1IVARBPROC)
+ cogl_get_proc_address ("glUniform1ivARB");
+
+ ctx->drv.pf_glUniform2ivARB =
+ (COGL_PFNGLUNIFORM2IVARBPROC)
+ cogl_get_proc_address ("glUniform2ivARB");
+
+ ctx->drv.pf_glUniform3ivARB =
+ (COGL_PFNGLUNIFORM3IVARBPROC)
+ cogl_get_proc_address ("glUniform3ivARB");
+
+ ctx->drv.pf_glUniform4ivARB =
+ (COGL_PFNGLUNIFORM4IVARBPROC)
+ cogl_get_proc_address ("glUniform4ivARB");
+
+ ctx->drv.pf_glUniformMatrix2fvARB =
+ (COGL_PFNGLUNIFORMMATRIX2FVARBPROC)
+ cogl_get_proc_address ("glUniformMatrix2fvARB");
+
+ ctx->drv.pf_glUniformMatrix3fvARB =
+ (COGL_PFNGLUNIFORMMATRIX3FVARBPROC)
+ cogl_get_proc_address ("glUniformMatrix3fvARB");
+
+ ctx->drv.pf_glUniformMatrix4fvARB =
+ (COGL_PFNGLUNIFORMMATRIX4FVARBPROC)
+ cogl_get_proc_address ("glUniformMatrix4fvARB");
+
+ if (ctx->drv.pf_glCreateProgramObjectARB &&
+ ctx->drv.pf_glCreateShaderObjectARB &&
+ ctx->drv.pf_glShaderSourceARB &&
+ ctx->drv.pf_glCompileShaderARB &&
+ ctx->drv.pf_glAttachObjectARB &&
+ ctx->drv.pf_glLinkProgramARB &&
+ ctx->drv.pf_glUseProgramObjectARB &&
+ ctx->drv.pf_glGetUniformLocationARB &&
+ ctx->drv.pf_glDeleteObjectARB &&
+ ctx->drv.pf_glGetInfoLogARB &&
+ ctx->drv.pf_glGetObjectParameterivARB &&
+ ctx->drv.pf_glUniform1fARB &&
+ ctx->drv.pf_glUniform2fARB &&
+ ctx->drv.pf_glUniform3fARB &&
+ ctx->drv.pf_glUniform4fARB &&
+ ctx->drv.pf_glUniform1fvARB &&
+ ctx->drv.pf_glUniform2fvARB &&
+ ctx->drv.pf_glUniform3fvARB &&
+ ctx->drv.pf_glUniform4fvARB &&
+ ctx->drv.pf_glUniform1iARB &&
+ ctx->drv.pf_glUniform2iARB &&
+ ctx->drv.pf_glUniform3iARB &&
+ ctx->drv.pf_glUniform4iARB &&
+ ctx->drv.pf_glUniform1ivARB &&
+ ctx->drv.pf_glUniform2ivARB &&
+ ctx->drv.pf_glUniform3ivARB &&
+ ctx->drv.pf_glUniform4ivARB &&
+ ctx->drv.pf_glUniformMatrix2fvARB &&
+ ctx->drv.pf_glUniformMatrix3fvARB &&
+ ctx->drv.pf_glUniformMatrix4fvARB &&
+ ctx->drv.pf_glVertexAttribPointerARB &&
+ ctx->drv.pf_glEnableVertexAttribArrayARB &&
+ ctx->drv.pf_glDisableVertexAttribArrayARB)
+ flags |= COGL_FEATURE_SHADERS_GLSL;
+ }
+
+ if (cogl_check_extension ("GL_EXT_framebuffer_object", gl_extensions) ||
+ cogl_check_extension ("GL_ARB_framebuffer_object", gl_extensions))
+ {
+ ctx->drv.pf_glGenRenderbuffersEXT =
+ (COGL_PFNGLGENRENDERBUFFERSEXTPROC)
+ cogl_get_proc_address ("glGenRenderbuffersEXT");
+
+ ctx->drv.pf_glDeleteRenderbuffersEXT =
+ (COGL_PFNGLDELETERENDERBUFFERSEXTPROC)
+ cogl_get_proc_address ("glDeleteRenderbuffersEXT");
+
+ ctx->drv.pf_glBindRenderbufferEXT =
+ (COGL_PFNGLBINDRENDERBUFFEREXTPROC)
+ cogl_get_proc_address ("glBindRenderbufferEXT");
+
+ ctx->drv.pf_glRenderbufferStorageEXT =
+ (COGL_PFNGLRENDERBUFFERSTORAGEEXTPROC)
+ cogl_get_proc_address ("glRenderbufferStorageEXT");
+
+ ctx->drv.pf_glGenFramebuffersEXT =
+ (COGL_PFNGLGENFRAMEBUFFERSEXTPROC)
+ cogl_get_proc_address ("glGenFramebuffersEXT");
+
+ ctx->drv.pf_glBindFramebufferEXT =
+ (COGL_PFNGLBINDFRAMEBUFFEREXTPROC)
+ cogl_get_proc_address ("glBindFramebufferEXT");
+
+ ctx->drv.pf_glFramebufferTexture2DEXT =
+ (COGL_PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
+ cogl_get_proc_address ("glFramebufferTexture2DEXT");
+
+ ctx->drv.pf_glFramebufferRenderbufferEXT =
+ (COGL_PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)
+ cogl_get_proc_address ("glFramebufferRenderbufferEXT");
+
+ ctx->drv.pf_glCheckFramebufferStatusEXT =
+ (COGL_PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
+ cogl_get_proc_address ("glCheckFramebufferStatusEXT");
+
+ ctx->drv.pf_glDeleteFramebuffersEXT =
+ (COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC)
+ cogl_get_proc_address ("glDeleteFramebuffersEXT");
+
+ ctx->drv.pf_glGenerateMipmapEXT =
+ (COGL_PFNGLGENERATEMIPMAPEXTPROC)
+ cogl_get_proc_address ("glGenerateMipmapEXT");
+
+ if (ctx->drv.pf_glGenRenderbuffersEXT &&
+ ctx->drv.pf_glBindRenderbufferEXT &&
+ ctx->drv.pf_glRenderbufferStorageEXT &&
+ ctx->drv.pf_glGenFramebuffersEXT &&
+ ctx->drv.pf_glBindFramebufferEXT &&
+ ctx->drv.pf_glFramebufferTexture2DEXT &&
+ ctx->drv.pf_glFramebufferRenderbufferEXT &&
+ ctx->drv.pf_glCheckFramebufferStatusEXT &&
+ ctx->drv.pf_glDeleteFramebuffersEXT &&
+ ctx->drv.pf_glGenerateMipmapEXT)
+ flags |= COGL_FEATURE_OFFSCREEN;
+ }
+
+ if (cogl_check_extension ("GL_EXT_framebuffer_blit", gl_extensions))
+ {
+ ctx->drv.pf_glBlitFramebufferEXT =
+ (COGL_PFNGLBLITFRAMEBUFFEREXTPROC)
+ cogl_get_proc_address ("glBlitFramebufferEXT");
+
+ if (ctx->drv.pf_glBlitFramebufferEXT)
+ flags |= COGL_FEATURE_OFFSCREEN_BLIT;
+ }
+
+ if (cogl_check_extension ("GL_EXT_framebuffer_multisample", gl_extensions))
+ {
+ ctx->drv.pf_glRenderbufferStorageMultisampleEXT =
+ (COGL_PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)
+ cogl_get_proc_address ("glRenderbufferStorageMultisampleEXT");
+
+ if (ctx->drv.pf_glRenderbufferStorageMultisampleEXT)
+ flags |= COGL_FEATURE_OFFSCREEN_MULTISAMPLE;
+ }
+
+ GE( glGetIntegerv (GL_STENCIL_BITS, &num_stencil_bits) );
+ /* We need at least three stencil bits to combine clips */
+ if (num_stencil_bits > 2)
+ flags |= COGL_FEATURE_STENCIL_BUFFER;
+
+ GE( glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) );
+ if (max_clip_planes >= 4)
+ flags |= COGL_FEATURE_FOUR_CLIP_PLANES;
+
+ if (cogl_check_extension ("GL_ARB_vertex_buffer_object", gl_extensions))
+ {
+ ctx->drv.pf_glGenBuffersARB =
+ (COGL_PFNGLGENBUFFERSARBPROC)
+ cogl_get_proc_address ("glGenBuffersARB");
+ ctx->drv.pf_glBindBufferARB =
+ (COGL_PFNGLBINDBUFFERARBPROC)
+ cogl_get_proc_address ("glBindBufferARB");
+ ctx->drv.pf_glBufferDataARB =
+ (COGL_PFNGLBUFFERDATAARBPROC)
+ cogl_get_proc_address ("glBufferDataARB");
+ ctx->drv.pf_glBufferSubDataARB =
+ (COGL_PFNGLBUFFERSUBDATAARBPROC)
+ cogl_get_proc_address ("glBufferSubDataARB");
+ ctx->drv.pf_glDeleteBuffersARB =
+ (COGL_PFNGLDELETEBUFFERSARBPROC)
+ cogl_get_proc_address ("glDeleteBuffersARB");
+ ctx->drv.pf_glMapBufferARB =
+ (COGL_PFNGLMAPBUFFERARBPROC)
+ cogl_get_proc_address ("glMapBufferARB");
+ ctx->drv.pf_glUnmapBufferARB =
+ (COGL_PFNGLUNMAPBUFFERARBPROC)
+ cogl_get_proc_address ("glUnmapBufferARB");
+ if (ctx->drv.pf_glGenBuffersARB
+ && ctx->drv.pf_glBindBufferARB
+ && ctx->drv.pf_glBufferDataARB
+ && ctx->drv.pf_glBufferSubDataARB
+ && ctx->drv.pf_glDeleteBuffersARB
+ && ctx->drv.pf_glMapBufferARB
+ && ctx->drv.pf_glUnmapBufferARB)
+ flags |= COGL_FEATURE_VBOS;
+ }
+
+ /* These should always be available because they are defined in GL
+ 1.2, but we can't call it directly because under Windows
+ functions > 1.1 aren't exported */
+ ctx->drv.pf_glDrawRangeElements =
+ (COGL_PFNGLDRAWRANGEELEMENTSPROC)
+ cogl_get_proc_address ("glDrawRangeElements");
+ ctx->drv.pf_glActiveTexture =
+ (COGL_PFNGLACTIVETEXTUREPROC)
+ cogl_get_proc_address ("glActiveTexture");
+ ctx->drv.pf_glClientActiveTexture =
+ (COGL_PFNGLCLIENTACTIVETEXTUREPROC)
+ cogl_get_proc_address ("glClientActiveTexture");
+
+ ctx->drv.pf_glBlendEquation =
+ (COGL_PFNGLBLENDEQUATIONPROC)
+ cogl_get_proc_address ("glBlendEquation");
+ ctx->drv.pf_glBlendColor =
+ (COGL_PFNGLBLENDCOLORPROC)
+ cogl_get_proc_address ("glBlendColor");
+
+ /* Available in 1.4 */
+ ctx->drv.pf_glBlendFuncSeparate =
+ (COGL_PFNGLBLENDFUNCSEPARATEPROC)
+ cogl_get_proc_address ("glBlendFuncSeparate");
+
+ /* Available in 2.0 */
+ ctx->drv.pf_glBlendEquationSeparate =
+ (COGL_PFNGLBLENDEQUATIONSEPARATEPROC)
+ cogl_get_proc_address ("glBlendEquationSeparate");
+
+ /* Cache features */
+ ctx->feature_flags = flags;
+ ctx->features_cached = TRUE;
+}
+