WIP: x11/dri2video support
[glsdk/omapdrmtest.git] / util / display-x11.c
1 /*
2  * Copyright (C) 2011 Texas Instruments
3  * Author: Rob Clark <rob.clark@linaro.org>
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 as published by
7  * the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
18 #include "util.h"
20 #include <X11/Xlib.h>
21 #include <X11/Xmd.h>
22 #include <X11/Xregion.h>
23 #include <X11/extensions/dri2proto.h>
24 #include <X11/extensions/dri2.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
31 #define to_display_x11(x) container_of(x, struct display_x11, base)
32 struct display_x11 {
33         struct display base;
34         Display *dpy;
35         Window win;
36 };
38 #define to_buffer_x11(x) container_of(x, struct buffer_x11, base)
39 struct buffer_x11 {
40         struct buffer base;
41         DRI2Buffer *dri2buf;
42 };
45 #define MAX_BUFFERS 32
47 static struct buffer **
48 get_buffers(struct display *disp, uint32_t n)
49 {
50         ERROR("unimplemented");
51         return NULL;
52 }
54 static struct buffer **
55 get_vid_buffers(struct display *disp, uint32_t n,
56                 uint32_t fourcc, uint32_t w, uint32_t h)
57 {
58         struct display_x11 *disp_x11 = to_display_x11(disp);
59         struct buffer **bufs;
60         unsigned attachments[MAX_BUFFERS+1] = {
61                         DRI2BufferFrontLeft, 32, /* always requested, never returned */
62         };
63         DRI2Buffer *dri2bufs;
64         uint32_t i, j, nbufs = 1;
66         for (i = 0; i < n; i++) {
67                 attachments[ nbufs * 2     ] = i + 1;
68                 attachments[(nbufs * 2) + 1] = fourcc;
69                 nbufs++;
70         }
72         dri2bufs = DRI2GetBuffersVid(disp_x11->dpy, disp_x11->win,
73                         w, h, attachments, nbufs, &nbufs);
74         if (!dri2bufs) {
75                 ERROR("DRI2GetBuffersVid failed");
76                 return NULL;
77         }
79         MSG("DRI2GetBuffers: nbufs=%d", nbufs);
81         if (nbufs != n) {
82                 ERROR("wrong number of bufs: %d vs %d", nbufs, n);
83                 return NULL;
84         }
86         bufs = calloc(nbufs, sizeof(struct buffer *));
88         for (i = 0; i < nbufs; i++) {
89                 struct buffer *buf;
90                 struct buffer_x11 *buf_x11;
92                 buf_x11 = calloc(1, sizeof(*buf_x11));
93                 if (!buf_x11) {
94                         ERROR("allocation failed");
95                         return NULL;
96                 }
98                 buf_x11->dri2buf = &dri2bufs[i];
100                 buf = &buf_x11->base;
102                 buf->fourcc = fourcc;
103                 buf->width = w;
104                 buf->height = h;
106                 for (j = 0; dri2bufs[i].names[j]; j++) {
107                         buf->bo[j] = omap_bo_from_name(disp->dev, dri2bufs[i].names[j]);
108                 }
109                 buf->nbo = j;
111                 bufs[i] = buf;
112         }
114         return bufs;
117 static int
118 post_buffer(struct display *disp, struct buffer *buf)
120         MSG("unimplemented");
121         return -1;
124 static int
125 post_vid_buffer(struct display *disp, struct buffer *buf,
126                 uint32_t x, uint32_t y, uint32_t w, uint32_t h)
128         struct display_x11 *disp_x11 = to_display_x11(disp);
129         struct buffer_x11 *buf_x11 = to_buffer_x11(buf);
130         CARD64 count;
131         BoxRec b = {
132                         .x1 = x,
133                         .y1 = y,
134                         .x2 = x + w,
135                         .y2 = y + h,
136         };
138         DRI2SwapBuffersVid(disp_x11->dpy, disp_x11->win, 0, 0, 0, &count,
139                         buf_x11->dri2buf->attachment, &b);
140         MSG("DRI2SwapBuffersVid[%u]: count=%llu",
141                         buf_x11->dri2buf->attachment, count);
143         return 0;
146 void
147 disp_x11_usage(void)
149         MSG("X11 Display Options:");
150         MSG("\t-w WxH\tset window dimensions");
153 /*** Move these somewhere common ***/
154 #include <ctype.h>
155 static Bool is_fourcc(unsigned int val)
157         char *str = (char *)&val;
158         return isalnum(str[0]) && isalnum(str[1]) && isalnum(str[2]) && isalnum(str[3]);
160 #define ATOM(name) XInternAtom(dpy, name, False)
161 static inline void print_hex(int len, const unsigned char *val)
163         char buf[33];
164         int i, j;
165         for (i = 0; i < len; i += j) {
166                 for (j = 0; (j < 16) && ((i + j) < len); ++j)
167                         sprintf(&buf[j * 2], "%02x", val[i + j]);
168                 fprintf(stderr, "\t%s\n", buf);
169         }
171 /***********************************/
174 static Bool WireToEvent(Display *dpy, XExtDisplayInfo *info,
175                 XEvent *event, xEvent *wire)
177         switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
179         case DRI2_BufferSwapComplete:
180         {
181 //              xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire;
182                 MSG("BufferSwapComplete");
183                 return True;
184         }
185         default:
186                 /* client doesn't support server event */
187                 break;
188         }
190         return False;
193 static Status EventToWire(Display *dpy, XExtDisplayInfo *info,
194                 XEvent *event, xEvent *wire)
196    switch (event->type) {
197    default:
198       /* client doesn't support server event */
199       break;
200    }
202    return Success;
205 static const DRI2EventOps ops = {
206                 .WireToEvent = WireToEvent,
207                 .EventToWire = EventToWire,
208 };
210 struct display *
211 disp_x11_open(int argc, char **argv)
213         struct display_x11 *disp_x11 = NULL;
214         struct display *disp;
215         Display *dpy;
216         Window root, win;
217         drm_magic_t magic;
218         int eventBase, errorBase, major, minor;
219         char *driver, *device;
220         unsigned int nformats, *formats;
221         unsigned int i, width = 500, height = 500;
222         CARD32 *pval;
224         MSG("attempting to open X11 connection");
225         dpy = XOpenDisplay(NULL);
226         if (!dpy) {
227                 ERROR("Could not open display");
228                 goto no_x11;
229         }
231         if (!DRI2InitDisplay(dpy, &ops)) {
232                 ERROR("DRI2InitDisplay failed");
233                 goto no_x11;
234         }
236         if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) {
237                 ERROR("DRI2QueryExtension failed");
238                 goto no_x11;
239         }
241         MSG("DRI2QueryExtension: eventBase=%d, errorBase=%d", eventBase, errorBase);
243         if (!DRI2QueryVersion(dpy, &major, &minor)) {
244                 ERROR("DRI2QueryVersion failed");
245                 goto no_x11;
246         }
248         MSG("DRI2QueryVersion: major=%d, minor=%d", major, minor);
250         root = RootWindow(dpy, DefaultScreen(dpy));
252         if (!DRI2Connect(dpy, root, DRI2DriverDRI, &driver, &device)) {
253                 MSG("DRI2Connect failed");
254                 goto no_x11;
255         }
257         MSG("DRI2Connect: driver=%s, device=%s", driver, device);
259         disp_x11 = calloc(1, sizeof(*disp_x11));
260         if (!disp_x11) {
261                 ERROR("allocation failed");
262                 goto no_x11;
263         }
265         disp = &disp_x11->base;
267         disp->fd = open(device, O_RDWR);
268         if (disp->fd < 0) {
269                 ERROR("could not open drm device: %s (%d)", strerror(errno), errno);
270                 goto no_x11_free;
271         }
273         if (drmGetMagic(disp->fd, &magic)) {
274                 ERROR("drmGetMagic failed");
275                 goto no_x11_free;
276         }
278         if (!DRI2Authenticate(dpy, root, magic)) {
279                 ERROR("DRI2Authenticate failed");
280                 goto no_x11_free;
281         }
283         disp->dev = omap_device_new(disp->fd);
284         if (!disp->dev) {
285                 ERROR("couldn't create device");
286                 goto no_x11_free;
287         }
289         disp->get_buffers = get_buffers;
290         disp->get_vid_buffers = get_vid_buffers;
291         disp->post_buffer = post_buffer;
292         disp->post_vid_buffer = post_vid_buffer;
294         /* note: set args to NULL after we've parsed them so other modules know
295          * that it is already parsed (since the arg parsing is decentralized)
296          */
297         for (i = 1; i < argc; i++) {
298                 if (!argv[i]) {
299                         continue;
300                 }
301                 if (!strcmp("-w", argv[i])) {
302                         argv[i++] = NULL;
303                         if (sscanf(argv[i], "%dx%d", &width, &height) != 2) {
304                                 ERROR("invalid arg: %s", argv[i]);
305                                 goto no_x11_free;
306                         }
307                 } else {
308                         /* ignore */
309                         continue;
310                 }
311                 argv[i] = NULL;
312         }
314         win = XCreateSimpleWindow(dpy, RootWindow(dpy, 0), 1, 1,
315                         width, height, 0, BlackPixel (dpy, 0), BlackPixel(dpy, 0));
316         XMapWindow(dpy, win);
317         XFlush(dpy);
319         disp_x11->dpy = dpy;
320         disp_x11->win = win;
322         if (!DRI2GetFormats(dpy, RootWindow(dpy, DefaultScreen(dpy)),
323                         &nformats, &formats)) {
324                 ERROR("DRI2GetFormats failed");
325                 goto no_x11_free;
326         }
328         if (nformats == 0) {
329                 ERROR("no formats!");
330                 goto no_x11_free;
331         }
333         /* print out supported formats */
334         MSG("Found %d supported formats:", nformats);
335         for (i = 0; i < nformats; i++) {
336                 if (is_fourcc(formats[i])) {
337                         MSG("  %d: %08x (\"%.4s\")", i, formats[i], (char *)&formats[i]);
338                 } else {
339                         MSG("  %d: %08x (device dependent)", i, formats[i]);
340                 }
341         }
343         DRI2CreateDrawable(dpy, win);
345         /* check some attribute.. just to exercise the code-path: */
346         if (!DRI2GetAttribute(dpy, win, ATOM("XV_CSC_MATRIX"), &i, &pval)) {
347                 ERROR("DRI2GetAttribute failed");
348                 goto no_x11_free;
349         }
351         MSG("Got CSC matrix:");
352         print_hex(i*4, (const unsigned char *)pval);
354         // XXX
356         return disp;
358 no_x11_free:
359         XFree(driver);
360         XFree(device);
361 no_x11:
362         ERROR("unimplemented");
363         return NULL;