static cairo_surface_t * _xcb_drm_create_surface_for_drawable (cairo_xcb_connection_t *connection, cairo_xcb_screen_t *screen, xcb_drawable_t drawable, pixman_format_code_t pixman_format, int width, int height) { uint32_t attachments[] = { XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT }; xcb_dri2_get_buffers_reply_t *buffers; xcb_dri2_dri2_buffer_t *buffer; cairo_surface_t *surface; if (! _cairo_drm_size_is_valid (screen->device, width, height)) return NULL; xcb_dri2_create_drawable (connection->xcb_connection, drawable); buffers = xcb_dri2_get_buffers_reply (connection->xcb_connection, xcb_dri2_get_buffers (connection->xcb_connection, drawable, 1, ARRAY_LENGTH (attachments), attachments), 0); if (buffers == NULL) { xcb_dri2_destroy_drawable (connection->xcb_connection, drawable); return NULL; } /* If the drawable is a window, we expect to receive an extra fake front, * which would involve copying on each flush - contrary to the user * expectations. But that is likely to be preferable to mixing drm/xcb * operations. */ buffer = xcb_dri2_get_buffers_buffers (buffers); if (buffers->count == 1 && buffer[0].attachment == XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT) { assert (buffer[0].cpp == PIXMAN_FORMAT_BPP (pixman_format) / 8); surface = cairo_drm_surface_create_for_name (screen->device, buffer[0].name, _cairo_format_from_pixman_format (pixman_format), width, height, buffer[0].pitch); } else { xcb_dri2_destroy_drawable (connection->xcb_connection, drawable); surface = NULL; } free (buffers); return surface; }
static EGLBoolean dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); (void) drv; if (!_eglPutSurface(surf)) return EGL_TRUE; (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable); if (dri2_dpy->dri2) { xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->drawable); } else { assert(dri2_dpy->swrast); swrastDestroyDrawable(dri2_dpy, dri2_surf); } if (surf->Type == EGL_PBUFFER_BIT) xcb_free_pixmap (dri2_dpy->conn, dri2_surf->drawable); free(surf); return EGL_TRUE; }
static cairo_status_t _cairo_xcb_surface_finish (void *abstract_surface) { cairo_xcb_surface_t *surface = abstract_surface; cairo_status_t status; if (surface->fallback != NULL) { cairo_surface_finish (surface->fallback); cairo_surface_destroy (surface->fallback); } cairo_list_del (&surface->link); #if CAIRO_HAS_DRM_SURFACE && CAIRO_HAS_XCB_DRM_FUNCTIONS if (surface->drm != NULL) { cairo_surface_finish (surface->drm); cairo_surface_destroy (surface->drm); xcb_dri2_destroy_drawable (surface->connection->xcb_connection, surface->drawable); } #endif status = _cairo_xcb_connection_acquire (surface->connection); if (status == CAIRO_STATUS_SUCCESS) { if (_cairo_xcb_connection_take_socket (surface->connection) == CAIRO_STATUS_SUCCESS) { if (surface->picture != XCB_NONE) { _cairo_xcb_connection_render_free_picture (surface->connection, surface->picture); } if (surface->owns_pixmap) _cairo_xcb_connection_free_pixmap (surface->connection, surface->drawable); } _cairo_xcb_connection_release (surface->connection); } _cairo_xcb_connection_destroy (surface->connection); return status; }