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); ClutterBackendX11 *backend_x11; ClutterBackendGLX *backend_glx; CLUTTER_NOTE (ACTOR, "Realizing stage '%s' [%p]", G_OBJECT_TYPE_NAME (stage_window), stage_window); if (!_clutter_stage_x11_create_window (stage_x11)) return FALSE; backend_x11 = stage_x11->backend; backend_glx = CLUTTER_BACKEND_GLX (backend_x11); 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); } } #ifdef GLX_INTEL_swap_event if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS)) { GLXDrawable drawable = stage_glx->glxwin ? stage_glx->glxwin : stage_x11->xwin; /* we unconditionally select this event because we rely on it to * advance the master clock, and drive redraw/relayout, animations * and event handling. */ glXSelectEvent (backend_x11->xdpy, drawable, GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK); } #endif /* GLX_INTEL_swap_event */ /* chain up to the StageX11 implementation */ return clutter_stage_window_parent_iface->realize (stage_window); }
static XVisualInfo * clutter_backend_glx_get_visual_info (ClutterBackendX11 *backend_x11) { ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend_x11); GLXFBConfig config; if (!_clutter_backend_glx_get_fbconfig (backend_glx, &config)) return NULL; return glXGetVisualFromFBConfig (backend_x11->xdpy, config); }
static gboolean clutter_backend_glx_create_context (ClutterBackend *backend, GError **error) { ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend); ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); GLXFBConfig config; gboolean is_direct; Window root_xwin; XSetWindowAttributes attrs; XVisualInfo *xvisinfo; Display *xdisplay; int major; int minor; GLXDrawable dummy_drawable; if (backend_glx->gl_context != None) return TRUE; xdisplay = clutter_x11_get_default_display (); root_xwin = clutter_x11_get_root_window (); if (!_clutter_backend_glx_get_fbconfig (backend_glx, &config)) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, "Unable to find suitable fbconfig for the GLX context"); return FALSE; } CLUTTER_NOTE (BACKEND, "Creating GLX Context (display: %p)", xdisplay); backend_glx->gl_context = glXCreateNewContext (xdisplay, config, GLX_RGBA_TYPE, NULL, True); if (backend_glx->gl_context == None) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, "Unable to create suitable GL context"); return FALSE; } is_direct = glXIsDirect (xdisplay, backend_glx->gl_context); CLUTTER_NOTE (GL, "Setting %s context", is_direct ? "direct" : "indirect"); _cogl_set_indirect_context (!is_direct); /* COGL assumes that there is always a GL context selected; in order * to make sure that a GLX 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 * * XXX - we need to do this dance because GLX does not allow creating * a context and querying it for basic information (even the function * pointers) unless it's made current to a real Drawable. it should be * possible to avoid this in future releases of Mesa and X11, but right * now this is the best solution available. */ xvisinfo = glXGetVisualFromFBConfig (xdisplay, config); if (xvisinfo == None) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, "Unable to retrieve the X11 visual"); return FALSE; } clutter_x11_trap_x_errors (); attrs.override_redirect = True; attrs.colormap = XCreateColormap (xdisplay, root_xwin, xvisinfo->visual, AllocNone); attrs.border_pixel = 0; backend_glx->dummy_xwin = XCreateWindow (xdisplay, root_xwin, -100, -100, 1, 1, 0, xvisinfo->depth, CopyFromParent, xvisinfo->visual, CWOverrideRedirect | CWColormap | CWBorderPixel, &attrs); /* 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) { backend_glx->dummy_glxwin = glXCreateWindow (backend_x11->xdpy, config, backend_glx->dummy_xwin, NULL); } if (backend_glx->dummy_glxwin) dummy_drawable = backend_glx->dummy_glxwin; else dummy_drawable = backend_glx->dummy_xwin; CLUTTER_NOTE (BACKEND, "Selecting dummy 0x%x for the GLX context", (unsigned int) dummy_drawable); glXMakeContextCurrent (xdisplay, dummy_drawable, dummy_drawable, backend_glx->gl_context); XFree (xvisinfo); if (clutter_x11_untrap_x_errors ()) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, "Unable to select the newly created GLX context"); return FALSE; } return TRUE; }
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); }