Beispiel #1
0
void
_cogl_features_init (void)
{
  CoglFeatureFlags  flags = 0;
  const char       *gl_extensions;
  GLint             max_clip_planes = 0;
  GLint             num_stencil_bits = 0;
  int               gl_major = 0, gl_minor = 0;
  int               i;

  _COGL_GET_CONTEXT (ctx, NO_RETVAL);

  _cogl_get_gl_version (&gl_major, &gl_minor);

  flags = (COGL_FEATURE_TEXTURE_READ_PIXELS
           | COGL_FEATURE_UNSIGNED_INT_INDICES);

  gl_extensions = (const char*) glGetString (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))
    {
#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

  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;

  for (i = 0; i < G_N_ELEMENTS (cogl_feature_data); i++)
    if (_cogl_feature_check (cogl_feature_data + i,
                             gl_major, gl_minor,
                             gl_extensions))
        flags |= cogl_feature_data[i].feature_flags;

  /* Cache features */
  ctx->feature_flags = flags;
  ctx->features_cached = TRUE;
}
static gboolean
clutter_backend_wayland_create_context (ClutterBackend  *backend,
					GError         **error)
{
  ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend);
  const gchar *egl_extensions = NULL;
  gboolean status;
  int retry_cookie;
  gboolean try_fallback;
  GError *try_error = NULL;

  if (backend_wayland->egl_context != EGL_NO_CONTEXT)
    return TRUE;

#if defined(HAVE_COGL_GL)
  eglBindAPI (EGL_OPENGL_API);
#else
  eglBindAPI (EGL_OPENGL_ES_API);
#endif
  egl_extensions = eglQueryString (backend_wayland->edpy, EGL_EXTENSIONS);

  if (!_cogl_check_extension (_COGL_SURFACELESS_EXTENSION, egl_extensions))
    {
      g_debug("Could not find the " _COGL_SURFACELESS_EXTENSION
              " extension; falling back to binding a dummy surface");
      if (!make_dummy_surface(backend_wayland))
        {
          g_set_error (error, CLUTTER_INIT_ERROR,
                       CLUTTER_INIT_ERROR_BACKEND,
                       "Could not create dummy surface");
          return FALSE;
        }
    }
  else
    {
      backend_wayland->egl_config = NULL;
      backend_wayland->egl_surface = EGL_NO_SURFACE;
    }

  retry_cookie = 0;
  while (!(status = try_create_context (backend,
                                        retry_cookie,
                                        &try_fallback,
                                        &try_error)) &&
         try_fallback)
    {
      g_warning ("Failed to create context: %s\nWill try fallback...",
                 try_error->message);
      g_error_free (try_error);
      try_error = NULL;
      retry_cookie++;
    }
  if (!status)
    g_propagate_error (error, try_error);

  return status;
}
Beispiel #3
0
gboolean
_cogl_check_driver_valid (GError **error)
{
  int major, minor;
  const char *gl_extensions;

  if (!_cogl_get_gl_version (&major, &minor))
    {
      g_set_error (error,
                   COGL_DRIVER_ERROR,
                   COGL_DRIVER_ERROR_UNKNOWN_VERSION,
                   "The OpenGL version could not be determined");
      return FALSE;
    }

  /* GL 1.3 supports all of the required functionality in core */
  if (COGL_CHECK_GL_VERSION (major, minor, 1, 3))
    return TRUE;

  gl_extensions = (const char*) glGetString (GL_EXTENSIONS);

  /* OpenGL 1.2 is only supported if we have the multitexturing
     extension */
  if (!_cogl_check_extension ("GL_ARB_multitexture", gl_extensions))
    {
      g_set_error (error,
                   COGL_DRIVER_ERROR,
                   COGL_DRIVER_ERROR_INVALID_VERSION,
                   "The OpenGL driver is missing "
                   "the GL_ARB_multitexture extension");
      return FALSE;
    }

  /* OpenGL 1.2 is required */
  if (!COGL_CHECK_GL_VERSION (major, minor, 1, 2))
    {
      g_set_error (error,
                   COGL_DRIVER_ERROR,
                   COGL_DRIVER_ERROR_INVALID_VERSION,
                   "The OpenGL version of your driver (%i.%i) "
                   "is not compatible with Cogl",
                   major, minor);
      return FALSE;
    }

  return TRUE;
}
Beispiel #4
0
static CoglBool
check_gl_version (CoglContext *ctx,
                  char **gl_extensions,
                  CoglError **error)
{
  int major, minor;

  if (!_cogl_get_gl_version (ctx, &major, &minor))
    {
      _cogl_set_error (error,
                   COGL_DRIVER_ERROR,
                   COGL_DRIVER_ERROR_UNKNOWN_VERSION,
                   "The OpenGL version could not be determined");
      return FALSE;
    }

  /* GL 1.3 supports all of the required functionality in core */
  if (COGL_CHECK_GL_VERSION (major, minor, 1, 3))
    return TRUE;

  /* OpenGL 1.2 is only supported if we have the multitexturing
     extension */
  if (!_cogl_check_extension ("GL_ARB_multitexture", gl_extensions))
    {
      _cogl_set_error (error,
                   COGL_DRIVER_ERROR,
                   COGL_DRIVER_ERROR_INVALID_VERSION,
                   "The OpenGL driver is missing "
                   "the GL_ARB_multitexture extension");
      return FALSE;
    }

  /* OpenGL 1.2 is required */
  if (!COGL_CHECK_GL_VERSION (major, minor, 1, 2))
    {
      _cogl_set_error (error,
                   COGL_DRIVER_ERROR,
                   COGL_DRIVER_ERROR_INVALID_VERSION,
                   "The OpenGL version of your driver (%i.%i) "
                   "is not compatible with Cogl",
                   major, minor);
      return FALSE;
    }

  return TRUE;
}
static ClutterFeatureFlags
clutter_backend_glx_get_features (ClutterBackend *backend)
{
  ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
  const gchar *glx_extensions = NULL;
  const gchar *gl_extensions = NULL;
  ClutterFeatureFlags flags;
  gboolean use_dri = FALSE;

  flags = clutter_backend_x11_get_features (backend);
  flags |= CLUTTER_FEATURE_STAGE_MULTIPLE;

  /* this will make sure that the GL context exists */
  g_assert (backend_glx->gl_context != None);
  g_assert (glXGetCurrentDrawable () != None);

  CLUTTER_NOTE (BACKEND,
                "Checking features\n"
                "  GL_VENDOR: %s\n"
                "  GL_RENDERER: %s\n"
                "  GL_VERSION: %s\n"
                "  GL_EXTENSIONS: %s",
                glGetString (GL_VENDOR),
                glGetString (GL_RENDERER),
                glGetString (GL_VERSION),
                glGetString (GL_EXTENSIONS));

  glx_extensions =
    glXQueryExtensionsString (clutter_x11_get_default_display (),
                              clutter_x11_get_default_screen ());

  CLUTTER_NOTE (BACKEND, "  GLX Extensions: %s", glx_extensions);

  gl_extensions = (const gchar *)glGetString (GL_EXTENSIONS);

  /* When using glBlitFramebuffer or glXCopySubBufferMESA for sub stage
   * redraws, we cannot rely on glXSwapIntervalSGI to throttle the blits
   * so we need to resort to manually synchronizing with the vblank so we
   * always check for the video_sync extension...
   */
  if (_cogl_check_extension ("GLX_SGI_video_sync", glx_extensions) &&
      /* Note: the GLX_SGI_video_sync spec explicitly states this extension
       * only works for direct contexts. */
      glXIsDirect (clutter_x11_get_default_display (),
                   backend_glx->gl_context))
    {
      backend_glx->get_video_sync =
        (GetVideoSyncProc) cogl_get_proc_address ("glXGetVideoSyncSGI");

      backend_glx->wait_video_sync =
        (WaitVideoSyncProc) cogl_get_proc_address ("glXWaitVideoSyncSGI");
    }

  use_dri = check_vblank_env ("dri");

  /* First check for explicit disabling or it set elsewhere (eg NVIDIA) */
  if (check_vblank_env ("none"))
    {
      CLUTTER_NOTE (BACKEND, "vblank sync: disabled at user request");
      goto vblank_setup_done;
    }

  if (g_getenv ("__GL_SYNC_TO_VBLANK") != NULL)
    {
      backend_glx->vblank_type = CLUTTER_VBLANK_GLX_SWAP;
      flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;

      CLUTTER_NOTE (BACKEND, "Using __GL_SYNC_TO_VBLANK hint");
      goto vblank_setup_done;
    }

  /* We try two GL vblank syncing mechanisms.
   * glXSwapIntervalSGI is tried first, then glXGetVideoSyncSGI.
   *
   * glXSwapIntervalSGI is known to work with Mesa and in particular
   * the Intel drivers. glXGetVideoSyncSGI has serious problems with
   * Intel drivers causing terrible frame rate so it only tried as a
   * fallback.
   *
   * How well glXGetVideoSyncSGI works with other driver (ATI etc) needs
   * to be investigated. glXGetVideoSyncSGI on ATI at least seems to have
   * no effect.
   */
  if (!use_dri &&
      _cogl_check_extension ("GLX_SGI_swap_control", glx_extensions))
    {
      backend_glx->swap_interval =
        (SwapIntervalProc) cogl_get_proc_address ("glXSwapIntervalSGI");

      CLUTTER_NOTE (BACKEND, "attempting glXSwapIntervalSGI vblank setup");

      if (backend_glx->swap_interval != NULL &&
          backend_glx->swap_interval (1) == 0)
        {
          backend_glx->vblank_type = CLUTTER_VBLANK_GLX_SWAP;
          flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;

          CLUTTER_NOTE (BACKEND, "glXSwapIntervalSGI setup success");

#ifdef GLX_INTEL_swap_event
          /* GLX_INTEL_swap_event allows us to avoid blocking the CPU
           * while we wait for glXSwapBuffers to complete, and instead
           * we get an X event notifying us of completion...
           */
          if (!(clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_SWAP_EVENTS) &&
              _cogl_check_extension ("GLX_INTEL_swap_event", glx_extensions))
            {
              flags |= CLUTTER_FEATURE_SWAP_EVENTS;
            }
#endif /* GLX_INTEL_swap_event */

          goto vblank_setup_done;
        }

      CLUTTER_NOTE (BACKEND, "glXSwapIntervalSGI vblank setup failed");
    }

  if (!use_dri &&
      !(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK) &&
      _cogl_check_extension ("GLX_SGI_video_sync", glx_extensions))
    {
      CLUTTER_NOTE (BACKEND, "attempting glXGetVideoSyncSGI vblank setup");

      if ((backend_glx->get_video_sync != NULL) &&
          (backend_glx->wait_video_sync != NULL))
        {
          CLUTTER_NOTE (BACKEND, "glXGetVideoSyncSGI vblank setup success");

          backend_glx->vblank_type = CLUTTER_VBLANK_GLX;
          flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;

          goto vblank_setup_done;
        }

      CLUTTER_NOTE (BACKEND, "glXGetVideoSyncSGI vblank setup failed");
    }

#ifdef __linux__
  /*
   * DRI is really an extreme fallback -rumoured to work with Via chipsets
   */
  if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK))
    {
      CLUTTER_NOTE (BACKEND, "attempting DRI vblank setup");

      backend_glx->dri_fd = open("/dev/dri/card0", O_RDWR);
      if (backend_glx->dri_fd >= 0)
        {
          CLUTTER_NOTE (BACKEND, "DRI vblank setup success");

          backend_glx->vblank_type = CLUTTER_VBLANK_DRI;
          flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;

          goto vblank_setup_done;
        }

      CLUTTER_NOTE (BACKEND, "DRI vblank setup failed");
    }
#endif /* __linux__ */

  CLUTTER_NOTE (BACKEND, "no use-able vblank mechanism found");

vblank_setup_done:

  if (_cogl_check_extension ("GLX_MESA_copy_sub_buffer", glx_extensions))
    {
      backend_glx->copy_sub_buffer =
        (CopySubBufferProc) cogl_get_proc_address ("glXCopySubBufferMESA");
      backend_glx->can_blit_sub_buffer = TRUE;
      backend_glx->blit_sub_buffer_is_synchronized = TRUE;
    }
  else if (_cogl_check_extension ("GL_EXT_framebuffer_blit", gl_extensions))
    {
      CLUTTER_NOTE (BACKEND,
                    "Using glBlitFramebuffer fallback for sub_buffer copies");
      backend_glx->blit_framebuffer =
        (BlitFramebufferProc) cogl_get_proc_address ("glBlitFramebuffer");
      backend_glx->can_blit_sub_buffer = TRUE;
      backend_glx->blit_sub_buffer_is_synchronized = FALSE;
    }

  CLUTTER_NOTE (BACKEND, "backend features checked");

  return flags;
}
Beispiel #6
0
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;
  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;
}
Beispiel #8
0
gboolean
cogl_clutter_check_extension (const char *name, const char *ext)
{
  return _cogl_check_extension (name, ext);
}
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;
}
static gboolean
try_enable_drm (ClutterBackendWayland *backend_wayland, GError **error)
{
  drm_magic_t magic;
  const gchar *exts, *glexts;

  if (backend_wayland->drm_fd < 0)
    {
      g_set_error (error, CLUTTER_INIT_ERROR,
		   CLUTTER_INIT_ERROR_BACKEND,
		   "Failed to open drm device");
      return FALSE;
    }

  glexts = glGetString(GL_EXTENSIONS);
  exts = eglQueryString (backend_wayland->edpy, EGL_EXTENSIONS);

  if (!_cogl_check_extension ("EGL_KHR_image_base", exts) ||
      !_cogl_check_extension ("EGL_MESA_drm_image", exts) ||
      !_cogl_check_extension ("GL_OES_EGL_image", glexts))
    {
      g_set_error (error, CLUTTER_INIT_ERROR,
		   CLUTTER_INIT_ERROR_BACKEND,
		   "Missing EGL extensions");
      return FALSE;
    }

  backend_wayland->create_drm_image =
    (PFNEGLCREATEDRMIMAGEMESA) eglGetProcAddress ("eglCreateDRMImageMESA");
  backend_wayland->destroy_image =
    (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress ("eglDestroyImageKHR");
  backend_wayland->export_drm_image =
    (PFNEGLEXPORTDRMIMAGEMESA) eglGetProcAddress ("eglExportDRMImageMESA");
  backend_wayland->image_target_texture_2d =
    (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress ("glEGLImageTargetTexture2DOES");

  if (backend_wayland->create_drm_image == NULL ||
      backend_wayland->destroy_image == NULL ||
      backend_wayland->export_drm_image == NULL ||
      backend_wayland->image_target_texture_2d == NULL)
    {
      g_set_error (error, CLUTTER_INIT_ERROR,
		   CLUTTER_INIT_ERROR_BACKEND,
		   "Missing EGL extensions");
      return FALSE;
    }

  if (drmGetMagic (backend_wayland->drm_fd, &magic))
    {
      g_set_error (error, CLUTTER_INIT_ERROR,
		   CLUTTER_INIT_ERROR_BACKEND,
		   "Failed to get drm magic");
      return FALSE;
    }

  wl_drm_authenticate (backend_wayland->wayland_drm, magic);
  wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_WRITABLE);
  while (!backend_wayland->authenticated)
    wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE);

  return TRUE;
};