2f9cb2a75ce56d18829e8d43d02981c673aabcef
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>
35 #define to_display_x11(x) container_of(x, struct display_x11, base)
36 struct display_x11 {
37 struct display base;
38 Display *dpy;
39 Window win;
40 };
42 #define to_buffer_x11(x) container_of(x, struct buffer_x11, base)
43 struct buffer_x11 {
44 struct buffer base;
45 DRI2Buffer *dri2buf;
46 };
49 #define MAX_BUFFERS 32
51 static struct buffer **
52 get_buffers(struct display *disp, uint32_t n)
53 {
54 ERROR("unimplemented");
55 return NULL;
56 }
58 static struct buffer **
59 get_vid_buffers(struct display *disp, uint32_t n,
60 uint32_t fourcc, uint32_t w, uint32_t h)
61 {
62 struct display_x11 *disp_x11 = to_display_x11(disp);
63 struct buffer **bufs;
64 unsigned attachments[MAX_BUFFERS+1] = {
65 DRI2BufferFrontLeft, 32, /* always requested, never returned */
66 };
67 DRI2Buffer *dri2bufs;
68 uint32_t i, j, nbufs = 1;
70 for (i = 0; i < n; i++) {
71 attachments[ nbufs * 2 ] = i + 1;
72 attachments[(nbufs * 2) + 1] = fourcc;
73 nbufs++;
74 }
76 dri2bufs = DRI2GetBuffersVid(disp_x11->dpy, disp_x11->win,
77 w, h, attachments, nbufs, &nbufs);
78 if (!dri2bufs) {
79 ERROR("DRI2GetBuffersVid failed");
80 return NULL;
81 }
83 MSG("DRI2GetBuffers: nbufs=%d", nbufs);
85 if (nbufs != n) {
86 ERROR("wrong number of bufs: %d vs %d", nbufs, n);
87 return NULL;
88 }
90 bufs = calloc(nbufs, sizeof(struct buffer *));
92 for (i = 0; i < nbufs; i++) {
93 struct buffer *buf;
94 struct buffer_x11 *buf_x11;
96 buf_x11 = calloc(1, sizeof(*buf_x11));
97 if (!buf_x11) {
98 ERROR("allocation failed");
99 return NULL;
100 }
102 buf_x11->dri2buf = &dri2bufs[i];
104 buf = &buf_x11->base;
106 buf->fourcc = fourcc;
107 buf->width = w;
108 buf->height = h;
110 for (j = 0; dri2bufs[i].names[j]; j++) {
111 buf->bo[j] = omap_bo_from_name(disp->dev, dri2bufs[i].names[j]);
112 }
113 buf->nbo = j;
115 bufs[i] = buf;
116 }
118 return bufs;
119 }
121 static int
122 post_buffer(struct display *disp, struct buffer *buf)
123 {
124 MSG("unimplemented");
125 return -1;
126 }
128 static int
129 post_vid_buffer(struct display *disp, struct buffer *buf,
130 uint32_t x, uint32_t y, uint32_t w, uint32_t h)
131 {
132 struct display_x11 *disp_x11 = to_display_x11(disp);
133 struct buffer_x11 *buf_x11 = to_buffer_x11(buf);
134 CARD64 count;
135 BoxRec b = {
136 .x1 = x,
137 .y1 = y,
138 .x2 = x + w,
139 .y2 = y + h,
140 };
142 DRI2SwapBuffersVid(disp_x11->dpy, disp_x11->win, 0, 0, 0, &count,
143 buf_x11->dri2buf->attachment, &b);
144 MSG("DRI2SwapBuffersVid[%u]: count=%llu",
145 buf_x11->dri2buf->attachment, count);
147 return 0;
148 }
150 void
151 disp_x11_usage(void)
152 {
153 MSG("X11 Display Options:");
154 MSG("\t-w WxH\tset window dimensions");
155 }
157 /*** Move these somewhere common ***/
158 #include <ctype.h>
159 static Bool is_fourcc(unsigned int val)
160 {
161 char *str = (char *)&val;
162 return isalnum(str[0]) && isalnum(str[1]) && isalnum(str[2]) && isalnum(str[3]);
163 }
164 #define ATOM(name) XInternAtom(dpy, name, False)
165 static inline void print_hex(int len, const unsigned char *val)
166 {
167 char buf[33];
168 int i, j;
169 for (i = 0; i < len; i += j) {
170 for (j = 0; (j < 16) && ((i + j) < len); ++j)
171 sprintf(&buf[j * 2], "%02x", val[i + j]);
172 fprintf(stderr, "\t%s\n", buf);
173 }
174 }
175 /***********************************/
178 static Bool WireToEvent(Display *dpy, XExtDisplayInfo *info,
179 XEvent *event, xEvent *wire)
180 {
181 switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
183 case DRI2_BufferSwapComplete:
184 {
185 // xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire;
186 MSG("BufferSwapComplete");
187 return True;
188 }
189 default:
190 /* client doesn't support server event */
191 break;
192 }
194 return False;
195 }
197 static Status EventToWire(Display *dpy, XExtDisplayInfo *info,
198 XEvent *event, xEvent *wire)
199 {
200 switch (event->type) {
201 default:
202 /* client doesn't support server event */
203 break;
204 }
206 return Success;
207 }
209 static const DRI2EventOps ops = {
210 .WireToEvent = WireToEvent,
211 .EventToWire = EventToWire,
212 };
214 struct display *
215 disp_x11_open(int argc, char **argv)
216 {
217 struct display_x11 *disp_x11 = NULL;
218 struct display *disp;
219 Display *dpy;
220 Window root, win;
221 drm_magic_t magic;
222 int eventBase, errorBase, major, minor;
223 char *driver, *device;
224 unsigned int nformats, *formats;
225 unsigned int i, width = 500, height = 500;
226 CARD32 *pval;
228 MSG("attempting to open X11 connection");
229 dpy = XOpenDisplay(NULL);
230 if (!dpy) {
231 ERROR("Could not open display");
232 goto no_x11;
233 }
235 if (!DRI2InitDisplay(dpy, &ops)) {
236 ERROR("DRI2InitDisplay failed");
237 goto no_x11;
238 }
240 if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) {
241 ERROR("DRI2QueryExtension failed");
242 goto no_x11;
243 }
245 MSG("DRI2QueryExtension: eventBase=%d, errorBase=%d", eventBase, errorBase);
247 if (!DRI2QueryVersion(dpy, &major, &minor)) {
248 ERROR("DRI2QueryVersion failed");
249 goto no_x11;
250 }
252 MSG("DRI2QueryVersion: major=%d, minor=%d", major, minor);
254 root = RootWindow(dpy, DefaultScreen(dpy));
256 if (!DRI2Connect(dpy, root, DRI2DriverDRI, &driver, &device)) {
257 MSG("DRI2Connect failed");
258 goto no_x11;
259 }
261 MSG("DRI2Connect: driver=%s, device=%s", driver, device);
263 disp_x11 = calloc(1, sizeof(*disp_x11));
264 if (!disp_x11) {
265 ERROR("allocation failed");
266 goto no_x11;
267 }
269 disp = &disp_x11->base;
271 disp->fd = open(device, O_RDWR);
272 if (disp->fd < 0) {
273 ERROR("could not open drm device: %s (%d)", strerror(errno), errno);
274 goto no_x11_free;
275 }
277 if (drmGetMagic(disp->fd, &magic)) {
278 ERROR("drmGetMagic failed");
279 goto no_x11_free;
280 }
282 if (!DRI2Authenticate(dpy, root, magic)) {
283 ERROR("DRI2Authenticate failed");
284 goto no_x11_free;
285 }
287 disp->dev = omap_device_new(disp->fd);
288 if (!disp->dev) {
289 ERROR("couldn't create device");
290 goto no_x11_free;
291 }
293 disp->get_buffers = get_buffers;
294 disp->get_vid_buffers = get_vid_buffers;
295 disp->post_buffer = post_buffer;
296 disp->post_vid_buffer = post_vid_buffer;
298 /* note: set args to NULL after we've parsed them so other modules know
299 * that it is already parsed (since the arg parsing is decentralized)
300 */
301 for (i = 1; i < argc; i++) {
302 if (!argv[i]) {
303 continue;
304 }
305 if (!strcmp("-w", argv[i])) {
306 argv[i++] = NULL;
307 if (sscanf(argv[i], "%dx%d", &width, &height) != 2) {
308 ERROR("invalid arg: %s", argv[i]);
309 goto no_x11_free;
310 }
311 } else {
312 /* ignore */
313 continue;
314 }
315 argv[i] = NULL;
316 }
318 win = XCreateSimpleWindow(dpy, RootWindow(dpy, 0), 1, 1,
319 width, height, 0, BlackPixel (dpy, 0), BlackPixel(dpy, 0));
320 XMapWindow(dpy, win);
321 XFlush(dpy);
323 disp_x11->dpy = dpy;
324 disp_x11->win = win;
326 if (!DRI2GetFormats(dpy, RootWindow(dpy, DefaultScreen(dpy)),
327 &nformats, &formats)) {
328 ERROR("DRI2GetFormats failed");
329 goto no_x11_free;
330 }
332 if (nformats == 0) {
333 ERROR("no formats!");
334 goto no_x11_free;
335 }
337 /* print out supported formats */
338 MSG("Found %d supported formats:", nformats);
339 for (i = 0; i < nformats; i++) {
340 if (is_fourcc(formats[i])) {
341 MSG(" %d: %08x (\"%.4s\")", i, formats[i], (char *)&formats[i]);
342 } else {
343 MSG(" %d: %08x (device dependent)", i, formats[i]);
344 }
345 }
347 DRI2CreateDrawable(dpy, win);
349 /* check some attribute.. just to exercise the code-path: */
350 if (!DRI2GetAttribute(dpy, win, ATOM("XV_CSC_MATRIX"), &i, &pval)) {
351 ERROR("DRI2GetAttribute failed");
352 goto no_x11_free;
353 }
355 MSG("Got CSC matrix:");
356 print_hex(i*4, (const unsigned char *)pval);
358 // XXX
360 return disp;
362 no_x11_free:
363 XFree(driver);
364 XFree(device);
365 no_x11:
366 ERROR("unimplemented");
367 return NULL;
368 }