static CoglBool _cogl_driver_update_features (CoglContext *context, CoglError **error) { CoglPrivateFeatureFlags private_flags = 0; CoglFeatureFlags flags = 0; const char *gl_extensions; int num_stencil_bits = 0; /* We have to special case getting the pointer to the glGetString function because we need to use it to determine what functions we can expect */ context->glGetString = (void *) _cogl_renderer_get_proc_address (context->display->renderer, "glGetString", TRUE); COGL_NOTE (WINSYS, "Checking features\n" " GL_VENDOR: %s\n" " GL_RENDERER: %s\n" " GL_VERSION: %s\n" " GL_EXTENSIONS: %s", context->glGetString (GL_VENDOR), context->glGetString (GL_RENDERER), _cogl_context_get_gl_version (context), _cogl_context_get_gl_extensions (context)); _cogl_gpu_info_init (context, &context->gpu); gl_extensions = _cogl_context_get_gl_extensions (context); _cogl_feature_check_ext_functions (context, -1 /* GL major version */, -1 /* GL minor version */, gl_extensions); GE( context, glGetIntegerv (GL_STENCIL_BITS, &num_stencil_bits) ); /* We need at least three stencil bits to combine clips */ if (num_stencil_bits > 2) private_flags |= COGL_PRIVATE_FEATURE_STENCIL_BUFFER; #ifdef HAVE_COGL_GLES if (context->driver == COGL_DRIVER_GLES1) { int max_clip_planes; GE( context, glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) ); if (max_clip_planes >= 4) private_flags |= COGL_PRIVATE_FEATURE_FOUR_CLIP_PLANES; } #endif if (context->driver == COGL_DRIVER_GLES2) { flags |= COGL_FEATURE_SHADERS_GLSL | COGL_FEATURE_OFFSCREEN; /* Note GLES 2 core doesn't support mipmaps for npot textures or * repeat modes other than CLAMP_TO_EDGE. */ flags |= COGL_FEATURE_TEXTURE_NPOT_BASIC; flags |= COGL_FEATURE_DEPTH_RANGE; COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_GLSL, TRUE); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_OFFSCREEN, TRUE); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_DEPTH_RANGE, TRUE); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_MIRRORED_REPEAT, TRUE); } private_flags |= COGL_PRIVATE_FEATURE_VBOS; /* Both GLES 1.1 and GLES 2.0 support point sprites in core */ flags |= COGL_FEATURE_POINT_SPRITE; COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_POINT_SPRITE, TRUE); if (context->glGenRenderbuffers) { flags |= COGL_FEATURE_OFFSCREEN; COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_OFFSCREEN, TRUE); } if (context->glBlitFramebuffer) private_flags |= COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT; if (_cogl_check_extension ("GL_OES_element_index_uint", gl_extensions)) { flags |= COGL_FEATURE_UNSIGNED_INT_INDICES; COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_UNSIGNED_INT_INDICES, TRUE); } if (_cogl_check_extension ("GL_OES_depth_texture", gl_extensions)) { flags |= COGL_FEATURE_DEPTH_TEXTURE; COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_DEPTH_TEXTURE, TRUE); } if (_cogl_check_extension ("GL_OES_texture_npot", gl_extensions)) { flags |= (COGL_FEATURE_TEXTURE_NPOT | COGL_FEATURE_TEXTURE_NPOT_BASIC | COGL_FEATURE_TEXTURE_NPOT_MIPMAP | COGL_FEATURE_TEXTURE_NPOT_REPEAT); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_NPOT, TRUE); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP, TRUE); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT, TRUE); } else if (_cogl_check_extension ("GL_IMG_texture_npot", gl_extensions)) { flags |= (COGL_FEATURE_TEXTURE_NPOT_BASIC | COGL_FEATURE_TEXTURE_NPOT_MIPMAP); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP, TRUE); } if (context->glTexImage3D) { flags |= COGL_FEATURE_TEXTURE_3D; COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_3D, TRUE); } if (context->glMapBuffer) { /* The GL_OES_mapbuffer extension doesn't support mapping for read */ flags |= COGL_FEATURE_MAP_BUFFER_FOR_WRITE; COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE, TRUE); } if (context->glEGLImageTargetTexture2D) private_flags |= COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE; if (_cogl_check_extension ("GL_OES_packed_depth_stencil", gl_extensions)) private_flags |= COGL_PRIVATE_FEATURE_OES_PACKED_DEPTH_STENCIL; if (_cogl_check_extension ("GL_EXT_texture_format_BGRA8888", gl_extensions)) private_flags |= COGL_PRIVATE_FEATURE_TEXTURE_FORMAT_BGRA8888; if (_cogl_check_extension ("GL_EXT_unpack_subimage", gl_extensions)) private_flags |= COGL_PRIVATE_FEATURE_UNPACK_SUBIMAGE; /* Cache features */ context->private_feature_flags |= private_flags; context->feature_flags |= flags; return TRUE; }
static CoglBool _cogl_driver_update_features (CoglContext *ctx, CoglError **error) { CoglPrivateFeatureFlags private_flags = 0; char **gl_extensions; int gl_major = 0, gl_minor = 0; /* We have to special case getting the pointer to the glGetString* functions because we need to use them to determine what functions we can expect */ ctx->glGetString = (void *) _cogl_renderer_get_proc_address (ctx->display->renderer, "glGetString", TRUE); ctx->glGetStringi = (void *) _cogl_renderer_get_proc_address (ctx->display->renderer, "glGetStringi", TRUE); ctx->glGetIntegerv = (void *) _cogl_renderer_get_proc_address (ctx->display->renderer, "glGetIntegerv", TRUE); gl_extensions = _cogl_context_get_gl_extensions (ctx); if (!check_gl_version (ctx, gl_extensions, error)) return FALSE; if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_WINSYS))) { char *all_extensions = g_strjoinv (" ", gl_extensions); COGL_NOTE (WINSYS, "Checking features\n" " GL_VENDOR: %s\n" " GL_RENDERER: %s\n" " GL_VERSION: %s\n" " GL_EXTENSIONS: %s", ctx->glGetString (GL_VENDOR), ctx->glGetString (GL_RENDERER), _cogl_context_get_gl_version (ctx), all_extensions); g_free (all_extensions); } _cogl_get_gl_version (ctx, &gl_major, &gl_minor); _cogl_gpu_info_init (ctx, &ctx->gpu); ctx->glsl_major = 1; ctx->glsl_minor = 1; if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 0)) { const char *glsl_version = (char *)ctx->glGetString (GL_SHADING_LANGUAGE_VERSION); parse_gl_version (glsl_version, &ctx->glsl_major, &ctx->glsl_minor); } COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_UNSIGNED_INT_INDICES, TRUE); COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_DEPTH_RANGE, TRUE); if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 1, 4)) COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_MIRRORED_REPEAT, TRUE); _cogl_feature_check_ext_functions (ctx, gl_major, gl_minor, gl_extensions); if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 0) || _cogl_check_extension ("GL_ARB_texture_non_power_of_two", gl_extensions)) { COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_TEXTURE_NPOT, TRUE); COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE); COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP, TRUE); COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT, TRUE); } if (_cogl_check_extension ("GL_MESA_pack_invert", gl_extensions)) private_flags |= COGL_PRIVATE_FEATURE_MESA_PACK_INVERT; if (ctx->glGenRenderbuffers) { COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_OFFSCREEN, TRUE); private_flags |= COGL_PRIVATE_FEATURE_QUERY_FRAMEBUFFER_BITS; } if (ctx->glBlitFramebuffer) private_flags |= COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT; if (ctx->glRenderbufferStorageMultisampleIMG) COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_OFFSCREEN_MULTISAMPLE, TRUE); if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 3, 0) || _cogl_check_extension ("GL_ARB_depth_texture", gl_extensions)) COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_DEPTH_TEXTURE, TRUE); if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 1) || _cogl_check_extension ("GL_EXT_pixel_buffer_object", gl_extensions)) private_flags |= COGL_PRIVATE_FEATURE_PBOS; if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 1, 4) || _cogl_check_extension ("GL_EXT_blend_color", gl_extensions)) private_flags |= COGL_PRIVATE_FEATURE_BLEND_CONSTANT; if (ctx->glGenPrograms) private_flags |= COGL_PRIVATE_FEATURE_ARBFP; if (ctx->glCreateProgram) COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_GLSL, TRUE); else { /* If all of the old GLSL extensions are available then we can fake * the GL 2.0 GLSL support by diverting to the old function names */ if (ctx->glCreateProgramObject && /* GL_ARB_shader_objects */ ctx->glVertexAttribPointer && /* GL_ARB_vertex_shader */ _cogl_check_extension ("GL_ARB_fragment_shader", gl_extensions)) { ctx->glCreateShader = ctx->glCreateShaderObject; ctx->glCreateProgram = ctx->glCreateProgramObject; ctx->glDeleteShader = ctx->glDeleteObject; ctx->glDeleteProgram = ctx->glDeleteObject; ctx->glAttachShader = ctx->glAttachObject; ctx->glUseProgram = ctx->glUseProgramObject; ctx->glGetProgramInfoLog = ctx->glGetInfoLog; ctx->glGetShaderInfoLog = ctx->glGetInfoLog; ctx->glGetShaderiv = ctx->glGetObjectParameteriv; ctx->glGetProgramiv = ctx->glGetObjectParameteriv; ctx->glDetachShader = ctx->glDetachObject; ctx->glGetAttachedShaders = ctx->glGetAttachedObjects; /* FIXME: there doesn't seem to be an equivalent for glIsShader * and glIsProgram. This doesn't matter for now because Cogl * doesn't use these but if we add support for simulating a * GLES2 context on top of regular GL then we'll need to do * something here */ COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_GLSL, TRUE); } } if ((COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 0) || _cogl_check_extension ("GL_ARB_point_sprite", gl_extensions)) && /* If GLSL is supported then we only enable point sprite support * too if we have glsl >= 1.2 otherwise we don't have the * gl_PointCoord builtin which we depend on in the glsl backend. */ (!COGL_FLAGS_GET (ctx->features, COGL_FEATURE_ID_GLSL) || COGL_CHECK_GL_VERSION (ctx->glsl_major, ctx->glsl_minor, 1, 2))) { COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_POINT_SPRITE, TRUE); } if (ctx->glGenBuffers) { private_flags |= COGL_PRIVATE_FEATURE_VBOS; COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_MAP_BUFFER_FOR_READ, TRUE); COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE, TRUE); } if (_cogl_check_extension ("GL_ARB_texture_rectangle", gl_extensions)) COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_TEXTURE_RECTANGLE, TRUE); if (ctx->glTexImage3D) COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_TEXTURE_3D, TRUE); if (ctx->glEGLImageTargetTexture2D) private_flags |= COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE; if (_cogl_check_extension ("GL_EXT_packed_depth_stencil", gl_extensions)) private_flags |= COGL_PRIVATE_FEATURE_EXT_PACKED_DEPTH_STENCIL; if (ctx->glGenSamplers) private_flags |= COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS; if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 3, 3) || _cogl_check_extension ("GL_ARB_texture_swizzle", gl_extensions) || _cogl_check_extension ("GL_EXT_texture_swizzle", gl_extensions)) private_flags |= COGL_PRIVATE_FEATURE_TEXTURE_SWIZZLE; /* The per-vertex point size is only available via GLSL with the * gl_PointSize builtin. This is only available in GL 2.0 (not the * GLSL extensions) */ if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 0)) { COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE, TRUE); private_flags |= COGL_PRIVATE_FEATURE_ENABLE_PROGRAM_POINT_SIZE; } if (ctx->driver == COGL_DRIVER_GL) { int max_clip_planes = 0; /* Features which are not available in GL 3 */ private_flags |= (COGL_PRIVATE_FEATURE_GL_FIXED | COGL_PRIVATE_FEATURE_ALPHA_TEST | COGL_PRIVATE_FEATURE_QUADS | COGL_PRIVATE_FEATURE_ALPHA_TEXTURES); GE( ctx, glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) ); if (max_clip_planes >= 4) private_flags |= COGL_PRIVATE_FEATURE_FOUR_CLIP_PLANES; } private_flags |= (COGL_PRIVATE_FEATURE_READ_PIXELS_ANY_FORMAT | COGL_PRIVATE_FEATURE_ANY_GL | COGL_PRIVATE_FEATURE_FORMAT_CONVERSION | COGL_PRIVATE_FEATURE_BLEND_CONSTANT | COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM | COGL_PRIVATE_FEATURE_QUERY_TEXTURE_PARAMETERS | COGL_PRIVATE_FEATURE_TEXTURE_MAX_LEVEL); if (ctx->glFenceSync) COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_FENCE, TRUE); /* Cache features */ ctx->private_feature_flags |= private_flags; g_strfreev (gl_extensions); if ((private_flags & (COGL_PRIVATE_FEATURE_ALPHA_TEXTURES | COGL_PRIVATE_FEATURE_TEXTURE_SWIZZLE)) == 0) { _cogl_set_error (error, COGL_DRIVER_ERROR, COGL_DRIVER_ERROR_NO_SUITABLE_DRIVER_FOUND, "The GL_ARB_texture_swizzle extension is required " "to use the GL3 driver"); return FALSE; } return TRUE; }
static CoglBool _cogl_driver_update_features (CoglContext *context, CoglError **error) { CoglPrivateFeatureFlags private_flags = 0; char **gl_extensions; /* We have to special case getting the pointer to the glGetString function because we need to use it to determine what functions we can expect */ context->glGetString = (void *) _cogl_renderer_get_proc_address (context->display->renderer, "glGetString", TRUE); gl_extensions = _cogl_context_get_gl_extensions (context); if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_WINSYS))) { char *all_extensions = g_strjoinv (" ", gl_extensions); COGL_NOTE (WINSYS, "Checking features\n" " GL_VENDOR: %s\n" " GL_RENDERER: %s\n" " GL_VERSION: %s\n" " GL_EXTENSIONS: %s", context->glGetString (GL_VENDOR), context->glGetString (GL_RENDERER), _cogl_context_get_gl_version (context), all_extensions); g_free (all_extensions); } context->glsl_major = 1; context->glsl_minor = 0; _cogl_gpu_info_init (context, &context->gpu); _cogl_feature_check_ext_functions (context, -1 /* GL major version */, -1 /* GL minor version */, gl_extensions); #ifdef HAVE_COGL_GLES if (context->driver == COGL_DRIVER_GLES1) { int max_clip_planes; GE( context, glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) ); if (max_clip_planes >= 4) private_flags |= COGL_PRIVATE_FEATURE_FOUR_CLIP_PLANES; } #endif if (context->driver == COGL_DRIVER_GLES2) { /* Note GLES 2 core doesn't support mipmaps for npot textures or * repeat modes other than CLAMP_TO_EDGE. */ COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_GLSL, TRUE); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_OFFSCREEN, TRUE); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_DEPTH_RANGE, TRUE); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_MIRRORED_REPEAT, TRUE); private_flags |= COGL_PRIVATE_FEATURE_BLEND_CONSTANT; } else if (context->driver == COGL_DRIVER_GLES1) private_flags |= (COGL_PRIVATE_FEATURE_FIXED_FUNCTION | COGL_PRIVATE_FEATURE_ALPHA_TEST | COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM); private_flags |= (COGL_PRIVATE_FEATURE_VBOS | COGL_PRIVATE_FEATURE_ANY_GL | COGL_PRIVATE_FEATURE_ALPHA_TEXTURES); /* Both GLES 1.1 and GLES 2.0 support point sprites in core */ COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_POINT_SPRITE, TRUE); if (context->glGenRenderbuffers) COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_OFFSCREEN, TRUE); if (context->glBlitFramebuffer) private_flags |= COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT; if (_cogl_check_extension ("GL_OES_element_index_uint", gl_extensions)) COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_UNSIGNED_INT_INDICES, TRUE); if (_cogl_check_extension ("GL_OES_depth_texture", gl_extensions)) COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_DEPTH_TEXTURE, TRUE); if (_cogl_check_extension ("GL_OES_texture_npot", gl_extensions)) { COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_NPOT, TRUE); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP, TRUE); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT, TRUE); } else if (_cogl_check_extension ("GL_IMG_texture_npot", gl_extensions)) { COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP, TRUE); } if (context->glTexImage3D) COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_3D, TRUE); if (context->glMapBuffer) /* The GL_OES_mapbuffer extension doesn't support mapping for read */ COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE, TRUE); if (context->glEGLImageTargetTexture2D) private_flags |= COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE; if (_cogl_check_extension ("GL_OES_packed_depth_stencil", gl_extensions)) private_flags |= COGL_PRIVATE_FEATURE_OES_PACKED_DEPTH_STENCIL; if (_cogl_check_extension ("GL_EXT_texture_format_BGRA8888", gl_extensions)) private_flags |= COGL_PRIVATE_FEATURE_TEXTURE_FORMAT_BGRA8888; if (_cogl_check_extension ("GL_EXT_unpack_subimage", gl_extensions)) private_flags |= COGL_PRIVATE_FEATURE_UNPACK_SUBIMAGE; /* Cache features */ context->private_feature_flags |= private_flags; g_strfreev (gl_extensions); return TRUE; }