142542f5fSchristos/* 242542f5fSchristos * Copyright (c) 2014 Intel Corporation 342542f5fSchristos * 442542f5fSchristos * Permission is hereby granted, free of charge, to any person obtaining a 542542f5fSchristos * copy of this software and associated documentation files (the "Software"), 642542f5fSchristos * to deal in the Software without restriction, including without limitation 742542f5fSchristos * the rights to use, copy, modify, merge, publish, distribute, sublicense, 842542f5fSchristos * and/or sell copies of the Software, and to permit persons to whom the 942542f5fSchristos * Software is furnished to do so, subject to the following conditions: 1042542f5fSchristos * 1142542f5fSchristos * The above copyright notice and this permission notice (including the next 1242542f5fSchristos * paragraph) shall be included in all copies or substantial portions of the 1342542f5fSchristos * Software. 1442542f5fSchristos * 1542542f5fSchristos * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1642542f5fSchristos * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1742542f5fSchristos * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1842542f5fSchristos * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1942542f5fSchristos * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2042542f5fSchristos * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2142542f5fSchristos * SOFTWARE. 2242542f5fSchristos * 2342542f5fSchristos */ 2442542f5fSchristos 2542542f5fSchristos#include <X11/Xlib.h> 2642542f5fSchristos#include <X11/Xlib-xcb.h> 2742542f5fSchristos#include <X11/xshmfence.h> 2842542f5fSchristos#include <xcb/xcb.h> 2942542f5fSchristos#include <xcb/dri3.h> 3042542f5fSchristos#include <xcb/sync.h> 3142542f5fSchristos#include <unistd.h> 32fe8aea9eSmrg#include <stdlib.h> 3342542f5fSchristos 3442542f5fSchristos#include "dri3.h" 3542542f5fSchristos 3642542f5fSchristosPixmap dri3_create_pixmap(Display *dpy, 3742542f5fSchristos Drawable draw, 3842542f5fSchristos int width, int height, int depth, 3942542f5fSchristos int fd, int bpp, int stride, int size) 4042542f5fSchristos{ 4142542f5fSchristos xcb_connection_t *c = XGetXCBConnection(dpy); 4242542f5fSchristos if (fd >= 0) { 4342542f5fSchristos xcb_pixmap_t pixmap = xcb_generate_id(c); 4442542f5fSchristos xcb_dri3_pixmap_from_buffer(c, pixmap, draw, size, width, height, stride, depth, bpp, fd); 4542542f5fSchristos return pixmap; 4642542f5fSchristos } 4742542f5fSchristos return 0; 4842542f5fSchristos} 4942542f5fSchristos 5042542f5fSchristosint dri3_create_fd(Display *dpy, 5142542f5fSchristos Pixmap pixmap, 5242542f5fSchristos int *stride) 5342542f5fSchristos{ 5442542f5fSchristos xcb_connection_t *c = XGetXCBConnection(dpy); 5542542f5fSchristos xcb_dri3_buffer_from_pixmap_cookie_t cookie; 5642542f5fSchristos xcb_dri3_buffer_from_pixmap_reply_t *reply; 5742542f5fSchristos 5842542f5fSchristos cookie = xcb_dri3_buffer_from_pixmap(c, pixmap); 5942542f5fSchristos reply = xcb_dri3_buffer_from_pixmap_reply(c, cookie, NULL); 6042542f5fSchristos if (!reply) 6142542f5fSchristos return -1; 6242542f5fSchristos 6342542f5fSchristos if (reply->nfd != 1) 6442542f5fSchristos return -1; 6542542f5fSchristos 6642542f5fSchristos *stride = reply->stride; 6742542f5fSchristos return xcb_dri3_buffer_from_pixmap_reply_fds(c, reply)[0]; 6842542f5fSchristos} 6942542f5fSchristos 7042542f5fSchristosint dri3_create_fence(Display *dpy, Pixmap pixmap, struct dri3_fence *fence) 7142542f5fSchristos{ 7242542f5fSchristos xcb_connection_t *c = XGetXCBConnection(dpy); 7342542f5fSchristos struct dri3_fence f; 7442542f5fSchristos int fd; 7542542f5fSchristos 7642542f5fSchristos fd = xshmfence_alloc_shm(); 7742542f5fSchristos if (fd < 0) 7842542f5fSchristos return -1; 7942542f5fSchristos 8042542f5fSchristos f.addr = xshmfence_map_shm(fd); 8142542f5fSchristos if (f.addr == NULL) { 8242542f5fSchristos close(fd); 8342542f5fSchristos return -1; 8442542f5fSchristos } 8542542f5fSchristos 8642542f5fSchristos f.xid = xcb_generate_id(c); 8742542f5fSchristos xcb_dri3_fence_from_fd(c, pixmap, f.xid, 0, fd); 8842542f5fSchristos 8942542f5fSchristos *fence = f; 9042542f5fSchristos return 0; 9142542f5fSchristos} 9242542f5fSchristos 9342542f5fSchristosvoid dri3_fence_sync(Display *dpy, struct dri3_fence *fence) 9442542f5fSchristos{ 9542542f5fSchristos xcb_connection_t *c = XGetXCBConnection(dpy); 9642542f5fSchristos 9742542f5fSchristos xshmfence_reset(fence->addr); 9842542f5fSchristos 9942542f5fSchristos xcb_sync_trigger_fence(c, fence->xid); 10042542f5fSchristos xcb_flush(c); 10142542f5fSchristos 10242542f5fSchristos xshmfence_await(fence->addr); 10342542f5fSchristos} 10442542f5fSchristos 10542542f5fSchristosvoid dri3_fence_free(Display *dpy, struct dri3_fence *fence) 10642542f5fSchristos{ 10742542f5fSchristos xcb_connection_t *c = XGetXCBConnection(dpy); 10842542f5fSchristos 10942542f5fSchristos xshmfence_unmap_shm(fence->addr); 11042542f5fSchristos xcb_sync_destroy_fence(c, fence->xid); 11142542f5fSchristos} 11242542f5fSchristos 113fe8aea9eSmrgstatic void dri3_query_version(xcb_connection_t *c, int *major, int *minor) 114fe8aea9eSmrg{ 115fe8aea9eSmrg xcb_dri3_query_version_reply_t *reply; 116fe8aea9eSmrg 117fe8aea9eSmrg reply = xcb_dri3_query_version_reply(c, 118fe8aea9eSmrg xcb_dri3_query_version(c, 119fe8aea9eSmrg XCB_DRI3_MAJOR_VERSION, 120fe8aea9eSmrg XCB_DRI3_MINOR_VERSION), 121fe8aea9eSmrg NULL); 122fe8aea9eSmrg if (reply != NULL) { 123fe8aea9eSmrg *major = reply->major_version; 124fe8aea9eSmrg *minor = reply->minor_version; 125fe8aea9eSmrg free(reply); 126fe8aea9eSmrg } 127fe8aea9eSmrg} 128fe8aea9eSmrg 129fe8aea9eSmrgstatic int dri3_exists(xcb_connection_t *c) 130fe8aea9eSmrg{ 131fe8aea9eSmrg const xcb_query_extension_reply_t *ext; 132fe8aea9eSmrg int major, minor; 133fe8aea9eSmrg 134fe8aea9eSmrg major = minor = -1; 135fe8aea9eSmrg 136fe8aea9eSmrg ext = xcb_get_extension_data(c, &xcb_dri3_id); 137fe8aea9eSmrg if (ext != NULL && ext->present) 138fe8aea9eSmrg dri3_query_version(c, &major, &minor); 139fe8aea9eSmrg 140fe8aea9eSmrg return major >= 0; 141fe8aea9eSmrg} 142fe8aea9eSmrg 14342542f5fSchristosint dri3_open__full(Display *dpy, Window root, unsigned provider) 14442542f5fSchristos{ 14542542f5fSchristos xcb_connection_t *c = XGetXCBConnection(dpy); 14642542f5fSchristos xcb_dri3_open_cookie_t cookie; 14742542f5fSchristos xcb_dri3_open_reply_t *reply; 14842542f5fSchristos 149fe8aea9eSmrg if (!dri3_exists(c)) 150fe8aea9eSmrg return -1; 151fe8aea9eSmrg 15242542f5fSchristos cookie = xcb_dri3_open(c, root, provider); 15342542f5fSchristos reply = xcb_dri3_open_reply(c, cookie, NULL); 15442542f5fSchristos 15542542f5fSchristos if (!reply) 15642542f5fSchristos return -1; 15742542f5fSchristos 15842542f5fSchristos if (reply->nfd != 1) 15942542f5fSchristos return -1; 16042542f5fSchristos 16142542f5fSchristos return xcb_dri3_open_reply_fds(c, reply)[0]; 16242542f5fSchristos} 16342542f5fSchristos 16442542f5fSchristosint dri3_open(Display *dpy) 16542542f5fSchristos{ 16642542f5fSchristos return dri3_open__full(dpy, RootWindow(dpy, DefaultScreen(dpy)), None); 16742542f5fSchristos} 168