static void _cogl_winsys_egl_onscreen_deinit (CoglOnscreen *onscreen) { CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); CoglContext *context = framebuffer->context; CoglRenderer *renderer = context->display->renderer; CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer); CoglXlibTrapState old_state; CoglOnscreenEGL *egl_onscreen = onscreen->winsys; CoglOnscreenXlib *xlib_onscreen = egl_onscreen->platform; _cogl_xlib_renderer_trap_errors (renderer, &old_state); if (!xlib_onscreen->is_foreign_xwin && xlib_onscreen->xwin != None) { XDestroyWindow (xlib_renderer->xdpy, xlib_onscreen->xwin); xlib_onscreen->xwin = None; } else xlib_onscreen->xwin = None; XSync (xlib_renderer->xdpy, False); if (_cogl_xlib_renderer_untrap_errors (renderer, &old_state) != Success) g_warning ("X Error while destroying X window"); g_slice_free (CoglOnscreenXlib, xlib_onscreen); }
static CoglBool _cogl_winsys_egl_onscreen_init (CoglOnscreen *onscreen, EGLConfig egl_config, CoglError **error) { CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); CoglContext *context = framebuffer->context; CoglDisplay *display = context->display; CoglRenderer *renderer = display->renderer; CoglRendererEGL *egl_renderer = renderer->winsys; CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer); CoglOnscreenXlib *xlib_onscreen; CoglOnscreenEGL *egl_onscreen = onscreen->winsys; Window xwin; /* FIXME: We need to explicitly Select for ConfigureNotify events. * For foreign windows we need to be careful not to mess up any * existing event mask. * We need to document that for windows we create then toolkits * must be careful not to clear event mask bits that we select. */ /* XXX: Note we ignore the user's original width/height when * given a foreign X window. */ if (onscreen->foreign_xid) { Status status; CoglXlibTrapState state; XWindowAttributes attr; int xerror; xwin = onscreen->foreign_xid; _cogl_xlib_renderer_trap_errors (display->renderer, &state); status = XGetWindowAttributes (xlib_renderer->xdpy, xwin, &attr); xerror = _cogl_xlib_renderer_untrap_errors (display->renderer, &state); if (status == 0 || xerror) { char message[1000]; XGetErrorText (xlib_renderer->xdpy, xerror, message, sizeof (message)); _cogl_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_ONSCREEN, "Unable to query geometry of foreign " "xid 0x%08lX: %s", xwin, message); return FALSE; } _cogl_framebuffer_winsys_update_size (framebuffer, attr.width, attr.height); /* Make sure the app selects for the events we require... */ onscreen->foreign_update_mask_callback (onscreen, COGL_ONSCREEN_X11_EVENT_MASK, onscreen-> foreign_update_mask_data); } else { int width; int height; CoglXlibTrapState state; XVisualInfo *xvisinfo; XSetWindowAttributes xattr; unsigned long mask; int xerror; width = cogl_framebuffer_get_width (framebuffer); height = cogl_framebuffer_get_height (framebuffer); _cogl_xlib_renderer_trap_errors (display->renderer, &state); xvisinfo = get_visual_info (display, egl_config); if (xvisinfo == NULL) { _cogl_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_ONSCREEN, "Unable to retrieve the X11 visual of context's " "fbconfig"); return FALSE; } /* window attributes */ xattr.background_pixel = WhitePixel (xlib_renderer->xdpy, DefaultScreen (xlib_renderer->xdpy)); xattr.border_pixel = 0; /* XXX: is this an X resource that we are leaking‽... */ xattr.colormap = XCreateColormap (xlib_renderer->xdpy, DefaultRootWindow (xlib_renderer->xdpy), xvisinfo->visual, AllocNone); xattr.event_mask = COGL_ONSCREEN_X11_EVENT_MASK; mask = CWBorderPixel | CWColormap | CWEventMask; xwin = XCreateWindow (xlib_renderer->xdpy, DefaultRootWindow (xlib_renderer->xdpy), 0, 0, width, height, 0, xvisinfo->depth, InputOutput, xvisinfo->visual, mask, &xattr); XFree (xvisinfo); XSync (xlib_renderer->xdpy, False); xerror = _cogl_xlib_renderer_untrap_errors (display->renderer, &state); if (xerror) { char message[1000]; XGetErrorText (xlib_renderer->xdpy, xerror, message, sizeof (message)); _cogl_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_ONSCREEN, "X error while creating Window for CoglOnscreen: %s", message); return FALSE; } } xlib_onscreen = g_slice_new (CoglOnscreenXlib); egl_onscreen->platform = xlib_onscreen; xlib_onscreen->xwin = xwin; xlib_onscreen->is_foreign_xwin = onscreen->foreign_xid ? TRUE : FALSE; egl_onscreen->egl_surface = eglCreateWindowSurface (egl_renderer->edpy, egl_config, (EGLNativeWindowType) xlib_onscreen->xwin, NULL); return TRUE; }
static void update_outputs (CoglRenderer *renderer, gboolean notify) { CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer); XRRScreenResources *resources; CoglXlibTrapState state; gboolean error = FALSE; GList *new_outputs = NULL; GList *l, *m; gboolean changed = FALSE; int i; xlib_renderer->outputs_update_serial = XNextRequest (xlib_renderer->xdpy); resources = XRRGetScreenResources (xlib_renderer->xdpy, DefaultRootWindow (xlib_renderer->xdpy)); _cogl_xlib_renderer_trap_errors (renderer, &state); for (i = 0; resources && i < resources->ncrtc && !error; i++) { XRRCrtcInfo *crtc_info = NULL; XRROutputInfo *output_info = NULL; CoglOutput *output; float refresh_rate = 0; int j; crtc_info = XRRGetCrtcInfo (xlib_renderer->xdpy, resources, resources->crtcs[i]); if (crtc_info == NULL) { error = TRUE; goto next; } if (crtc_info->mode == None) goto next; for (j = 0; j < resources->nmode; j++) { if (resources->modes[j].id == crtc_info->mode) refresh_rate = (resources->modes[j].dotClock / ((float)resources->modes[j].hTotal * resources->modes[j].vTotal)); } output_info = XRRGetOutputInfo (xlib_renderer->xdpy, resources, crtc_info->outputs[0]); if (output_info == NULL) { error = TRUE; goto next; } output = _cogl_output_new (output_info->name); output->x = crtc_info->x; output->y = crtc_info->y; output->width = crtc_info->width; output->height = crtc_info->height; if ((crtc_info->rotation & (RR_Rotate_90 | RR_Rotate_270)) != 0) { output->mm_width = output_info->mm_height; output->mm_height = output_info->mm_width; } else { output->mm_width = output_info->mm_width; output->mm_height = output_info->mm_height; } output->refresh_rate = refresh_rate; switch (output_info->subpixel_order) { case SubPixelUnknown: default: output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN; break; case SubPixelNone: output->subpixel_order = COGL_SUBPIXEL_ORDER_NONE; break; case SubPixelHorizontalRGB: output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB; break; case SubPixelHorizontalBGR: output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR; break; case SubPixelVerticalRGB: output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_RGB; break; case SubPixelVerticalBGR: output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_BGR; break; } output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB; /* Handle the effect of rotation and reflection on subpixel order (ugh) */ for (j = 0; j < 6; j++) { if ((crtc_info->rotation & (1 << j)) != 0) output->subpixel_order = subpixel_map[j][output->subpixel_order]; } new_outputs = g_list_prepend (new_outputs, output); next: if (crtc_info != NULL) XFree (crtc_info); if (output_info != NULL) XFree (output_info); } XFree (resources); if (!error) { new_outputs = g_list_sort (new_outputs, (GCompareFunc)compare_outputs); l = new_outputs; m = renderer->outputs; while (l || m) { int cmp; CoglOutput *output_l = l ? (CoglOutput *)l->data : NULL; CoglOutput *output_m = m ? (CoglOutput *)m->data : NULL; if (l && m) cmp = compare_outputs (output_l, output_m); else if (l) cmp = -1; else cmp = 1; if (cmp == 0) { GList *m_next = m->next; if (!_cogl_output_values_equal (output_l, output_m)) { renderer->outputs = g_list_remove_link (renderer->outputs, m); renderer->outputs = g_list_insert_before (renderer->outputs, m_next, output_l); cogl_object_ref (output_l); changed = TRUE; } l = l->next; m = m_next; } else if (cmp < 0) { renderer->outputs = g_list_insert_before (renderer->outputs, m, output_l); cogl_object_ref (output_l); changed = TRUE; l = l->next; } else { GList *m_next = m->next; renderer->outputs = g_list_remove_link (renderer->outputs, m); changed = TRUE; m = m_next; } } } g_list_free_full (new_outputs, (GDestroyNotify)cogl_object_unref); _cogl_xlib_renderer_untrap_errors (renderer, &state); if (changed) { const CoglWinsysVtable *winsys = renderer->winsys_vtable; if (notify) COGL_NOTE (WINSYS, "Outputs changed:"); else COGL_NOTE (WINSYS, "Outputs:"); for (l = renderer->outputs; l; l = l->next) { CoglOutput *output = l->data; const char *subpixel_string; switch (output->subpixel_order) { case COGL_SUBPIXEL_ORDER_UNKNOWN: default: subpixel_string = "unknown"; break; case COGL_SUBPIXEL_ORDER_NONE: subpixel_string = "none"; break; case COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB: subpixel_string = "horizontal_rgb"; break; case COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR: subpixel_string = "horizontal_bgr"; break; case COGL_SUBPIXEL_ORDER_VERTICAL_RGB: subpixel_string = "vertical_rgb"; break; case COGL_SUBPIXEL_ORDER_VERTICAL_BGR: subpixel_string = "vertical_bgr"; break; } COGL_NOTE (WINSYS, " %10s: +%d+%dx%dx%d mm=%dx%d dpi=%.1fx%.1f " "subpixel_order=%s refresh_rate=%.3f", output->name, output->x, output->y, output->width, output->height, output->mm_width, output->mm_height, output->width / (output->mm_width / 25.4), output->height / (output->mm_height / 25.4), subpixel_string, output->refresh_rate); } if (notify && winsys->renderer_outputs_changed != NULL) winsys->renderer_outputs_changed (renderer); } }