fixes for proper stride for tiled buffers
[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 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
22 #include "util.h"
24 #include <X11/Xlib.h>
25 #include <X11/Xmd.h>
26 #include <X11/Xregion.h>
27 #include <X11/extensions/dri2proto.h>
28 #include <X11/extensions/dri2.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
34 static int global_fd = 0;
36 #define to_display_x11(x) container_of(x, struct display_x11, base)
37 struct display_x11 {
38         struct display base;
39         Display *dpy;
40         Window win;
41 };
43 #define to_buffer_x11(x) container_of(x, struct buffer_x11, base)
44 struct buffer_x11 {
45         struct buffer base;
46         DRI2Buffer *dri2buf;
47 };
50 #define MAX_BUFFERS 32
52 static struct buffer **
53 get_buffers(struct display *disp, uint32_t n)
54 {
55         ERROR("unimplemented");
56         return NULL;
57 }
59 static struct buffer **
60 get_vid_buffers(struct display *disp, uint32_t n,
61                 uint32_t fourcc, uint32_t w, uint32_t h)
62 {
63         struct display_x11 *disp_x11 = to_display_x11(disp);
64         struct buffer **bufs;
65         unsigned attachments[MAX_BUFFERS+1] = {
66                         DRI2BufferFrontLeft, 32, /* always requested, never returned */
67         };
68         DRI2Buffer *dri2bufs;
69         uint32_t i, j, nbufs = 1;
71         for (i = 0; i < n; i++) {
72                 attachments[ nbufs * 2     ] = i + 1;
73                 attachments[(nbufs * 2) + 1] = fourcc;
74                 nbufs++;
75         }
77         dri2bufs = DRI2GetBuffersVid(disp_x11->dpy, disp_x11->win,
78                         w, h, attachments, nbufs, &nbufs);
79         if (!dri2bufs) {
80                 ERROR("DRI2GetBuffersVid failed");
81                 return NULL;
82         }
84         MSG("DRI2GetBuffers: nbufs=%d", nbufs);
86         if (nbufs != n) {
87                 ERROR("wrong number of bufs: %d vs %d", nbufs, n);
88                 return NULL;
89         }
91         bufs = calloc(nbufs, sizeof(struct buffer *));
93         for (i = 0; i < nbufs; i++) {
94                 struct buffer *buf;
95                 struct buffer_x11 *buf_x11;
97                 buf_x11 = calloc(1, sizeof(*buf_x11));
98                 if (!buf_x11) {
99                         ERROR("allocation failed");
100                         return NULL;
101                 }
103                 buf_x11->dri2buf = &dri2bufs[i];
105                 buf = &buf_x11->base;
107                 buf->fourcc = fourcc;
108                 buf->width = w;
109                 buf->height = h;
111                 for (j = 0; dri2bufs[i].names[j]; j++) {
112                         buf->bo[j] = omap_bo_from_name(disp->dev, dri2bufs[i].names[j]);
113                         buf->pitches[j] = dri2bufs[i].pitch[j];
114                 }
116                 buf->nbo = j;
118                 bufs[i] = buf;
119         }
121         return bufs;
124 static int
125 post_buffer(struct display *disp, struct buffer *buf)
127         MSG("unimplemented");
128         return -1;
131 static int
132 post_vid_buffer(struct display *disp, struct buffer *buf,
133                 uint32_t x, uint32_t y, uint32_t w, uint32_t h)
135         struct display_x11 *disp_x11 = to_display_x11(disp);
136         struct buffer_x11 *buf_x11 = to_buffer_x11(buf);
137         CARD64 count;
138         BoxRec b = {
139                         .x1 = x,
140                         .y1 = y,
141                         .x2 = x + w,
142                         .y2 = y + h,
143         };
145         DRI2SwapBuffersVid(disp_x11->dpy, disp_x11->win, 0, 0, 0, &count,
146                         buf_x11->dri2buf->attachment, &b);
147         MSG("DRI2SwapBuffersVid[%u]: count=%llu",
148                         buf_x11->dri2buf->attachment, count);
150         return 0;
153 void
154 disp_x11_usage(void)
156         MSG("X11 Display Options:");
157         MSG("\t-w WxH\tset window dimensions");
160 /*** Move these somewhere common ***/
161 #include <ctype.h>
162 static Bool is_fourcc(unsigned int val)
164         char *str = (char *)&val;
165         return isalnum(str[0]) && isalnum(str[1]) && isalnum(str[2]) && isalnum(str[3]);
167 #define ATOM(name) XInternAtom(dpy, name, False)
168 static inline void print_hex(int len, const unsigned char *val)
170         char buf[33];
171         int i, j;
172         for (i = 0; i < len; i += j) {
173                 for (j = 0; (j < 16) && ((i + j) < len); ++j)
174                         sprintf(&buf[j * 2], "%02x", val[i + j]);
175                 fprintf(stderr, "\t%s\n", buf);
176         }
178 /***********************************/
181 static Bool WireToEvent(Display *dpy, XExtDisplayInfo *info,
182                 XEvent *event, xEvent *wire)
184         switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
186         case DRI2_BufferSwapComplete:
187         {
188 //              xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire;
189                 MSG("BufferSwapComplete");
190                 return True;
191         }
192         default:
193                 /* client doesn't support server event */
194                 break;
195         }
197         return False;
200 static Status EventToWire(Display *dpy, XExtDisplayInfo *info,
201                 XEvent *event, xEvent *wire)
203    switch (event->type) {
204    default:
205       /* client doesn't support server event */
206       break;
207    }
209    return Success;
212 static const DRI2EventOps ops = {
213                 .WireToEvent = WireToEvent,
214                 .EventToWire = EventToWire,
215 };
217 struct display *
218 disp_x11_open(int argc, char **argv)
220         struct display_x11 *disp_x11 = NULL;
221         struct display *disp;
222         Display *dpy;
223         Window root, win;
224         drm_magic_t magic;
225         int eventBase, errorBase, major, minor;
226         char *driver, *device;
227         unsigned int nformats, *formats;
228         unsigned int i, width = 500, height = 500;
229         CARD32 *pval;
231         MSG("attempting to open X11 connection");
232         dpy = XOpenDisplay(NULL);
233         if (!dpy) {
234                 ERROR("Could not open display");
235                 goto no_x11;
236         }
238         if (!DRI2InitDisplay(dpy, &ops)) {
239                 ERROR("DRI2InitDisplay failed");
240                 goto no_x11;
241         }
243         if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) {
244                 ERROR("DRI2QueryExtension failed");
245                 goto no_x11;
246         }
248         MSG("DRI2QueryExtension: eventBase=%d, errorBase=%d", eventBase, errorBase);
250         if (!DRI2QueryVersion(dpy, &major, &minor)) {
251                 ERROR("DRI2QueryVersion failed");
252                 goto no_x11;
253         }
255         MSG("DRI2QueryVersion: major=%d, minor=%d", major, minor);
257         root = RootWindow(dpy, DefaultScreen(dpy));
259         if (!DRI2Connect(dpy, root, DRI2DriverDRI, &driver, &device)) {
260                 MSG("DRI2Connect failed");
261                 goto no_x11;
262         }
264         MSG("DRI2Connect: driver=%s, device=%s", driver, device);
266         disp_x11 = calloc(1, sizeof(*disp_x11));
267         if (!disp_x11) {
268                 ERROR("allocation failed");
269                 goto no_x11;
270         }
272         disp = &disp_x11->base;
274         if (!global_fd) {
275                 MSG("opening device: %s", device);
276                 global_fd = open(device, O_RDWR);
277                 if (global_fd < 0) {
278                         ERROR("could not open drm device: %s (%d)",
279                                         strerror(errno), errno);
280                         goto no_x11_free;
281                 }
283                 if (drmGetMagic(global_fd, &magic)) {
284                         ERROR("drmGetMagic failed");
285                         goto no_x11_free;
286                 }
288                 if (!DRI2Authenticate(dpy, root, magic)) {
289                         ERROR("DRI2Authenticate failed");
290                         goto no_x11_free;
291                 }
292         }
294         disp->fd = global_fd;
296         disp->dev = omap_device_new(disp->fd);
297         if (!disp->dev) {
298                 ERROR("couldn't create device");
299                 goto no_x11_free;
300         }
302         disp->get_buffers = get_buffers;
303         disp->get_vid_buffers = get_vid_buffers;
304         disp->post_buffer = post_buffer;
305         disp->post_vid_buffer = post_vid_buffer;
307         /* note: set args to NULL after we've parsed them so other modules know
308          * that it is already parsed (since the arg parsing is decentralized)
309          */
310         for (i = 1; i < argc; i++) {
311                 if (!argv[i]) {
312                         continue;
313                 }
314                 if (!strcmp("-w", argv[i])) {
315                         argv[i++] = NULL;
316                         if (sscanf(argv[i], "%dx%d", &width, &height) != 2) {
317                                 ERROR("invalid arg: %s", argv[i]);
318                                 goto no_x11_free;
319                         }
320                 } else {
321                         /* ignore */
322                         continue;
323                 }
324                 argv[i] = NULL;
325         }
327         win = XCreateSimpleWindow(dpy, RootWindow(dpy, 0), 1, 1,
328                         width, height, 0, BlackPixel (dpy, 0), BlackPixel(dpy, 0));
329         XMapWindow(dpy, win);
330         XFlush(dpy);
332         disp_x11->dpy = dpy;
333         disp_x11->win = win;
335         if (!DRI2GetFormats(dpy, RootWindow(dpy, DefaultScreen(dpy)),
336                         &nformats, &formats)) {
337                 ERROR("DRI2GetFormats failed");
338                 goto no_x11_free;
339         }
341         if (nformats == 0) {
342                 ERROR("no formats!");
343                 goto no_x11_free;
344         }
346         /* print out supported formats */
347         MSG("Found %d supported formats:", nformats);
348         for (i = 0; i < nformats; i++) {
349                 if (is_fourcc(formats[i])) {
350                         MSG("  %d: %08x (\"%.4s\")", i, formats[i], (char *)&formats[i]);
351                 } else {
352                         MSG("  %d: %08x (device dependent)", i, formats[i]);
353                 }
354         }
356         DRI2CreateDrawable(dpy, win);
358         /* check some attribute.. just to exercise the code-path: */
359         if (!DRI2GetAttribute(dpy, win, ATOM("XV_CSC_MATRIX"), &i, &pval)) {
360                 ERROR("DRI2GetAttribute failed");
361                 goto no_x11_free;
362         }
364         MSG("Got CSC matrix:");
365         print_hex(i*4, (const unsigned char *)pval);
367         // XXX
369         return disp;
371 no_x11_free:
372         XFree(driver);
373         XFree(device);
374 no_x11:
375         ERROR("unimplemented");
376         return NULL;