1428d7b3dSmrg/*
2428d7b3dSmrg * Copyright (c) 2014 Intel Corporation
3428d7b3dSmrg *
4428d7b3dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5428d7b3dSmrg * copy of this software and associated documentation files (the "Software"),
6428d7b3dSmrg * to deal in the Software without restriction, including without limitation
7428d7b3dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8428d7b3dSmrg * and/or sell copies of the Software, and to permit persons to whom the
9428d7b3dSmrg * Software is furnished to do so, subject to the following conditions:
10428d7b3dSmrg *
11428d7b3dSmrg * The above copyright notice and this permission notice (including the next
12428d7b3dSmrg * paragraph) shall be included in all copies or substantial portions of the
13428d7b3dSmrg * Software.
14428d7b3dSmrg *
15428d7b3dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16428d7b3dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17428d7b3dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18428d7b3dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19428d7b3dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20428d7b3dSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21428d7b3dSmrg * SOFTWARE.
22428d7b3dSmrg *
23428d7b3dSmrg */
24428d7b3dSmrg
25428d7b3dSmrg#include <X11/Xlib.h>
26428d7b3dSmrg#include <X11/Xlib-xcb.h>
27428d7b3dSmrg#include <X11/xshmfence.h>
28428d7b3dSmrg#include <xcb/xcb.h>
29428d7b3dSmrg#include <xcb/dri3.h>
30428d7b3dSmrg#include <xcb/sync.h>
31428d7b3dSmrg#include <unistd.h>
32428d7b3dSmrg
33428d7b3dSmrg#include "dri3.h"
34428d7b3dSmrg
35428d7b3dSmrgPixmap dri3_create_pixmap(Display *dpy,
36428d7b3dSmrg			  Drawable draw,
37428d7b3dSmrg			  int width, int height, int depth,
38428d7b3dSmrg			  int fd, int bpp, int stride, int size)
39428d7b3dSmrg{
40428d7b3dSmrg	xcb_connection_t *c = XGetXCBConnection(dpy);
41428d7b3dSmrg	if (fd >= 0) {
42428d7b3dSmrg		xcb_pixmap_t pixmap = xcb_generate_id(c);
43428d7b3dSmrg		xcb_dri3_pixmap_from_buffer(c, pixmap, draw, size, width, height, stride, depth, bpp, fd);
44428d7b3dSmrg		return pixmap;
45428d7b3dSmrg	}
46428d7b3dSmrg	return 0;
47428d7b3dSmrg}
48428d7b3dSmrg
49428d7b3dSmrgint dri3_create_fd(Display *dpy,
50428d7b3dSmrg		   Pixmap pixmap,
51428d7b3dSmrg		   int *stride)
52428d7b3dSmrg{
53428d7b3dSmrg	xcb_connection_t *c = XGetXCBConnection(dpy);
54428d7b3dSmrg	xcb_dri3_buffer_from_pixmap_cookie_t cookie;
55428d7b3dSmrg	xcb_dri3_buffer_from_pixmap_reply_t *reply;
56428d7b3dSmrg
57428d7b3dSmrg	cookie = xcb_dri3_buffer_from_pixmap(c, pixmap);
58428d7b3dSmrg	reply = xcb_dri3_buffer_from_pixmap_reply(c, cookie, NULL);
59428d7b3dSmrg	if (!reply)
60428d7b3dSmrg		return -1;
61428d7b3dSmrg
62428d7b3dSmrg	if (reply->nfd != 1)
63428d7b3dSmrg		return -1;
64428d7b3dSmrg
65428d7b3dSmrg	*stride = reply->stride;
66428d7b3dSmrg	return xcb_dri3_buffer_from_pixmap_reply_fds(c, reply)[0];
67428d7b3dSmrg}
68428d7b3dSmrg
69428d7b3dSmrgint dri3_create_fence(Display *dpy, Pixmap pixmap, struct dri3_fence *fence)
70428d7b3dSmrg{
71428d7b3dSmrg	xcb_connection_t *c = XGetXCBConnection(dpy);
72428d7b3dSmrg	struct dri3_fence f;
73428d7b3dSmrg	int fd;
74428d7b3dSmrg
75428d7b3dSmrg	fd = xshmfence_alloc_shm();
76428d7b3dSmrg	if (fd < 0)
77428d7b3dSmrg		return -1;
78428d7b3dSmrg
79428d7b3dSmrg	f.addr = xshmfence_map_shm(fd);
80428d7b3dSmrg	if (f.addr == NULL) {
81428d7b3dSmrg		close(fd);
82428d7b3dSmrg		return -1;
83428d7b3dSmrg	}
84428d7b3dSmrg
85428d7b3dSmrg	f.xid = xcb_generate_id(c);
86428d7b3dSmrg	xcb_dri3_fence_from_fd(c, pixmap, f.xid, 0, fd);
87428d7b3dSmrg
88428d7b3dSmrg	*fence = f;
89428d7b3dSmrg	return 0;
90428d7b3dSmrg}
91428d7b3dSmrg
92428d7b3dSmrgvoid dri3_fence_sync(Display *dpy, struct dri3_fence *fence)
93428d7b3dSmrg{
94428d7b3dSmrg	xcb_connection_t *c = XGetXCBConnection(dpy);
95428d7b3dSmrg
96428d7b3dSmrg	xshmfence_reset(fence->addr);
97428d7b3dSmrg
98428d7b3dSmrg	xcb_sync_trigger_fence(c, fence->xid);
99428d7b3dSmrg	xcb_flush(c);
100428d7b3dSmrg
101428d7b3dSmrg	xshmfence_await(fence->addr);
102428d7b3dSmrg}
103428d7b3dSmrg
104428d7b3dSmrgvoid dri3_fence_free(Display *dpy, struct dri3_fence *fence)
105428d7b3dSmrg{
106428d7b3dSmrg	xcb_connection_t *c = XGetXCBConnection(dpy);
107428d7b3dSmrg
108428d7b3dSmrg	xshmfence_unmap_shm(fence->addr);
109428d7b3dSmrg	xcb_sync_destroy_fence(c, fence->xid);
110428d7b3dSmrg}
111428d7b3dSmrg
112428d7b3dSmrgint dri3_open__full(Display *dpy, Window root, unsigned provider)
113428d7b3dSmrg{
114428d7b3dSmrg	xcb_connection_t *c = XGetXCBConnection(dpy);
115428d7b3dSmrg	xcb_dri3_open_cookie_t cookie;
116428d7b3dSmrg	xcb_dri3_open_reply_t *reply;
117428d7b3dSmrg
118428d7b3dSmrg	cookie = xcb_dri3_open(c, root, provider);
119428d7b3dSmrg	reply = xcb_dri3_open_reply(c, cookie, NULL);
120428d7b3dSmrg
121428d7b3dSmrg	if (!reply)
122428d7b3dSmrg		return -1;
123428d7b3dSmrg
124428d7b3dSmrg	if (reply->nfd != 1)
125428d7b3dSmrg		return -1;
126428d7b3dSmrg
127428d7b3dSmrg	return xcb_dri3_open_reply_fds(c, reply)[0];
128428d7b3dSmrg}
129428d7b3dSmrg
130428d7b3dSmrgint dri3_open(Display *dpy)
131428d7b3dSmrg{
132428d7b3dSmrg	return dri3_open__full(dpy, RootWindow(dpy, DefaultScreen(dpy)), None);
133428d7b3dSmrg}
134