Ejemplo n.º 1
0
static gboolean
clutter_backend_glx_create_context (ClutterBackend  *backend,
                                    gboolean         is_offscreen,
                                    GError         **error)
{
  ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
  ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);

  if (backend_glx->gl_context == None)
    {
      XVisualInfo *xvisinfo;

      xvisinfo =
        clutter_backend_x11_get_visual_info (backend_x11, is_offscreen);

      CLUTTER_NOTE (GL, "Creating GL Context (display: %p, %s)",
                    backend_x11->xdpy,
                    is_offscreen ? "offscreen" : "onscreen");

      backend_glx->gl_context = glXCreateContext (backend_x11->xdpy,
                                                  xvisinfo,
                                                  0,
                                                  is_offscreen ? False : True);

      XFree (xvisinfo);

      if (backend_glx->gl_context == None)
        {
          g_set_error (error, CLUTTER_INIT_ERROR,
                       CLUTTER_INIT_ERROR_BACKEND,
                       "Unable to create suitable %s GL context",
                       is_offscreen ? "offscreen" : "onscreen");
          return FALSE;
        }

      if (!is_offscreen)
        {
          gboolean is_direct;

          is_direct = glXIsDirect (backend_x11->xdpy,
                                   backend_glx->gl_context);

          CLUTTER_NOTE (GL, "Setting %s context",
                        is_direct ? "direct" : "indirect");
          _cogl_set_indirect_context (!is_direct);
        }
    }

  return TRUE;
}
Ejemplo n.º 2
0
static gboolean
clutter_stage_glx_realize (ClutterStageWindow *stage_window)
{
  ClutterStageX11   *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
  ClutterStageGLX   *stage_glx = CLUTTER_STAGE_GLX (stage_window);
  ClutterBackend    *backend;
  ClutterBackendGLX *backend_glx;
  ClutterBackendX11 *backend_x11;
  GError            *error;

  CLUTTER_NOTE (ACTOR, "Realizing stage '%s' [%p]",
                G_OBJECT_TYPE_NAME (stage_window),
                stage_window);

  backend     = clutter_get_default_backend ();
  backend_glx = CLUTTER_BACKEND_GLX (backend);
  backend_x11 = CLUTTER_BACKEND_X11 (backend);

  if (stage_x11->xwin == None)
    {
      XSetWindowAttributes xattr;
      unsigned long mask;
      XVisualInfo *xvisinfo;
      gfloat width, height;

      CLUTTER_NOTE (MISC, "Creating stage X window");

      xvisinfo = clutter_backend_x11_get_visual_info (backend_x11);
      if (xvisinfo == NULL)
        {
          g_critical ("Unable to find suitable GL visual.");
          return FALSE;
        }

      /* window attributes */
      xattr.background_pixel = WhitePixel (backend_x11->xdpy,
                                           backend_x11->xscreen_num);
      xattr.border_pixel = 0;
      xattr.colormap = XCreateColormap (backend_x11->xdpy,
                                        backend_x11->xwin_root,
                                        xvisinfo->visual,
                                        AllocNone);
      mask = CWBorderPixel | CWColormap;

      /* Call get_size - this will either get the geometry size (which
       * before we create the window is set to 640x480), or if a size
       * is set, it will get that. This lets you set a size on the
       * stage before it's realized.
       */
      clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper),
                              &width,
                              &height);
      stage_x11->xwin_width = (gint)width;
      stage_x11->xwin_height = (gint)height;

      stage_x11->xwin = XCreateWindow (backend_x11->xdpy,
                                       backend_x11->xwin_root,
                                       0, 0,
                                       stage_x11->xwin_width,
                                       stage_x11->xwin_height,
                                       0,
                                       xvisinfo->depth,
                                       InputOutput,
                                       xvisinfo->visual,
                                       mask, &xattr);

      CLUTTER_NOTE (BACKEND, "Stage [%p], window: 0x%x, size: %dx%d",
                    stage_window,
                    (unsigned int) stage_x11->xwin,
                    stage_x11->xwin_width,
                    stage_x11->xwin_height);

      XFree (xvisinfo);
    }

  if (stage_glx->glxwin == None)
    {
      int major;
      int minor;
      GLXFBConfig config;

      /* Try and create a GLXWindow to use with extensions dependent on
       * GLX versions >= 1.3 that don't accept regular X Windows as GLX
       * drawables. */
      if (glXQueryVersion (backend_x11->xdpy, &major, &minor) &&
          major == 1 && minor >= 3 &&
          _clutter_backend_glx_get_fbconfig (backend_glx, &config))
        {
          stage_glx->glxwin = glXCreateWindow (backend_x11->xdpy,
                                               config,
                                               stage_x11->xwin,
                                               NULL);
        }
    }

  if (clutter_x11_has_event_retrieval ())
    {
      if (clutter_x11_has_xinput ())
        {
          XSelectInput (backend_x11->xdpy, stage_x11->xwin,
                        StructureNotifyMask |
                        FocusChangeMask |
                        ExposureMask |
                        KeyPressMask | KeyReleaseMask |
                        EnterWindowMask | LeaveWindowMask |
                        PropertyChangeMask);
#ifdef HAVE_XINPUT
          _clutter_x11_select_events (stage_x11->xwin);
#endif
        }
      else
        XSelectInput (backend_x11->xdpy, stage_x11->xwin,
                      StructureNotifyMask |
                      FocusChangeMask |
                      ExposureMask |
                      PointerMotionMask |
                      KeyPressMask | KeyReleaseMask |
                      ButtonPressMask | ButtonReleaseMask |
                      EnterWindowMask | LeaveWindowMask |
                      PropertyChangeMask);

#ifdef GLX_INTEL_swap_event
      if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS))
        {
          GLXDrawable drawable =
            stage_glx->glxwin ? stage_glx->glxwin : stage_x11->xwin;
          glXSelectEvent (backend_x11->xdpy,
                          drawable,
                          GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK);
        }
#endif /* GLX_INTEL_swap_event */
    }

  /* no user resize.. */
  clutter_stage_x11_fix_window_size (stage_x11,
                                     stage_x11->xwin_width,
                                     stage_x11->xwin_height);
  clutter_stage_x11_set_wm_protocols (stage_x11);

  /* ask for a context; a no-op, if a context already exists */
  error = NULL;
  _clutter_backend_create_context (backend, &error);
  if (error)
    {
      g_critical ("Unable to realize stage: %s", error->message);
      g_error_free (error);
      return FALSE;
    }

  CLUTTER_NOTE (BACKEND, "Successfully realized stage");

  /* chain up to the StageX11 implementation */
  return clutter_stage_glx_parent_iface->realize (stage_window);
}
Ejemplo n.º 3
0
static gboolean
clutter_backend_egl_create_context (ClutterBackend  *backend,
                                    GError         **error)
{
  ClutterBackendEGL *backend_egl;
  ClutterBackendX11 *backend_x11;
  EGLConfig          config;
  EGLint             config_count = 0;
  EGLBoolean         status;
  EGLint             cfg_attribs[] = {
    /* NB: This must be the first attribute, since we may
     * try and fallback to no stencil buffer */
    EGL_STENCIL_SIZE,   8,

    EGL_RED_SIZE,       5,
    EGL_GREEN_SIZE,     6,
    EGL_BLUE_SIZE,      5,

    EGL_BUFFER_SIZE,    EGL_DONT_CARE,

#ifdef HAVE_COGL_GLES2
    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
#else /* HAVE_COGL_GLES2 */
    EGL_SURFACE_TYPE,    EGL_WINDOW_BIT,
#endif /* HAVE_COGL_GLES2 */

    EGL_NONE
  };
  EGLDisplay edpy;
  gint retry_cookie = 0;
  XVisualInfo *xvisinfo;
  XSetWindowAttributes attrs;

  backend     = clutter_get_default_backend ();
  backend_egl = CLUTTER_BACKEND_EGL (backend);

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

  backend_x11 = CLUTTER_BACKEND_X11 (backend);

  edpy = clutter_eglx_display ();

retry:
  /* Here we can change the attributes depending on the fallback count... */

  /* Some GLES hardware can't support a stencil buffer: */
  if (retry_cookie == 1)
    {
      g_warning ("Trying with stencil buffer disabled...");
      cfg_attribs[1 /* EGL_STENCIL_SIZE */] = 0;
    }

  /* XXX: at this point we only have one fallback */

  status = eglChooseConfig (edpy,
                            cfg_attribs,
                            &config, 1,
                            &config_count);
  if (status != EGL_TRUE || config_count == 0)
    {
      g_warning ("eglChooseConfig failed");
      goto fail;
    }

  if (G_UNLIKELY (backend_egl->egl_context == EGL_NO_CONTEXT))
    {
#ifdef HAVE_COGL_GLES2
      static const EGLint attribs[3]
        = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };

      backend_egl->egl_context = eglCreateContext (edpy,
                                                   config,
                                                   EGL_NO_CONTEXT,
                                                   attribs);
#else
      /* Seems some GLES implementations 1.x do not like attribs... */
      backend_egl->egl_context = eglCreateContext (edpy,
                                                   config,
                                                   EGL_NO_CONTEXT,
                                                   NULL);
#endif
      if (backend_egl->egl_context == EGL_NO_CONTEXT)
        {
          g_warning ("Unable to create a suitable EGL context");
          goto fail;
        }

      backend_egl->egl_config = config;
      CLUTTER_NOTE (GL, "Created EGL Context");
    }

  /* COGL assumes that there is always a GL context selected; in order
   * to make sure that an EGL context exists and is made current, we use
   * a dummy, offscreen override-redirect window to which we can always
   * fall back if no stage is available */

  xvisinfo = clutter_backend_x11_get_visual_info (backend_x11);
  if (xvisinfo == NULL)
    {
      g_critical ("Unable to find suitable GL visual.");
      return FALSE;
    }

  attrs.override_redirect = True;
  attrs.colormap = XCreateColormap (backend_x11->xdpy,
                                    backend_x11->xwin_root,
                                    xvisinfo->visual,
                                    AllocNone);
  attrs.border_pixel = 0;

  backend_egl->dummy_xwin = XCreateWindow (backend_x11->xdpy,
                                           backend_x11->xwin_root,
                                           -100, -100, 1, 1,
                                           0,
                                           xvisinfo->depth,
                                           CopyFromParent,
                                           xvisinfo->visual,
                                           CWOverrideRedirect |
                                           CWColormap |
                                           CWBorderPixel,
                                           &attrs);

  XFree (xvisinfo);

  backend_egl->dummy_surface =
    eglCreateWindowSurface (edpy,
                            backend_egl->egl_config,
                            (NativeWindowType) backend_egl->dummy_xwin,
                            NULL);

  if (backend_egl->dummy_surface == EGL_NO_SURFACE)
    {
      g_critical ("Unable to create an EGL surface");
      return FALSE;
    }

  eglMakeCurrent (edpy,
                  backend_egl->dummy_surface,
                  backend_egl->dummy_surface,
                  backend_egl->egl_context);

  return TRUE;

fail:

  /* NB: We currently only support a single fallback option */
  if (retry_cookie == 0)
    {
      retry_cookie = 1;
      goto retry;
    }

  return FALSE;
}