9553dc6127c35ecba204f10e826031375cbb12fa
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;
110 buf->multiplanar = false;
112 for (j = 0; dri2bufs[i].names[j]; j++) {
113 buf->bo[j] = omap_bo_from_name(disp->dev, dri2bufs[i].names[j]);
114 buf->pitches[j] = dri2bufs[i].pitch[j];
115 }
117 buf->nbo = j;
119 bufs[i] = buf;
120 }
122 return bufs;
123 }
125 static int
126 post_buffer(struct display *disp, struct buffer *buf)
127 {
128 MSG("unimplemented");
129 return -1;
130 }
132 static int
133 post_vid_buffer(struct display *disp, struct buffer *buf,
134 uint32_t x, uint32_t y, uint32_t w, uint32_t h)
135 {
136 struct display_x11 *disp_x11 = to_display_x11(disp);
137 struct buffer_x11 *buf_x11 = to_buffer_x11(buf);
138 CARD64 count;
139 BoxRec b = {
140 .x1 = x,
141 .y1 = y,
142 .x2 = x + w,
143 .y2 = y + h,
144 };
146 DRI2SwapBuffersVid(disp_x11->dpy, disp_x11->win, 0, 0, 0, &count,
147 buf_x11->dri2buf->attachment, &b);
148 DBG("DRI2SwapBuffersVid[%u]: count=%llu",
149 buf_x11->dri2buf->attachment, count);
151 return 0;
152 }
154 void
155 disp_x11_usage(void)
156 {
157 MSG("X11 Display Options:");
158 MSG("\t-w WxH\tset window dimensions");
159 }
161 /*** Move these somewhere common ***/
162 #include <ctype.h>
163 static Bool is_fourcc(unsigned int val)
164 {
165 char *str = (char *)&val;
166 return isalnum(str[0]) && isalnum(str[1]) && isalnum(str[2]) && isalnum(str[3]);
167 }
168 #define ATOM(name) XInternAtom(dpy, name, False)
169 static inline void print_hex(int len, const unsigned char *val)
170 {
171 char buf[33];
172 int i, j;
173 for (i = 0; i < len; i += j) {
174 for (j = 0; (j < 16) && ((i + j) < len); ++j)
175 sprintf(&buf[j * 2], "%02x", val[i + j]);
176 fprintf(stderr, "\t%s\n", buf);
177 }
178 }
179 /***********************************/
182 static Bool WireToEvent(Display *dpy, XExtDisplayInfo *info,
183 XEvent *event, xEvent *wire)
184 {
185 switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
187 case DRI2_BufferSwapComplete:
188 {
189 // xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire;
190 DBG("BufferSwapComplete");
191 return True;
192 }
193 default:
194 /* client doesn't support server event */
195 break;
196 }
198 return False;
199 }
201 static Status EventToWire(Display *dpy, XExtDisplayInfo *info,
202 XEvent *event, xEvent *wire)
203 {
204 switch (event->type) {
205 default:
206 /* client doesn't support server event */
207 break;
208 }
210 return Success;
211 }
213 static const DRI2EventOps ops = {
214 .WireToEvent = WireToEvent,
215 .EventToWire = EventToWire,
216 };
218 struct display *
219 disp_x11_open(int argc, char **argv)
220 {
221 struct display_x11 *disp_x11 = NULL;
222 struct display *disp;
223 Display *dpy;
224 Window root, win;
225 drm_magic_t magic;
226 int eventBase, errorBase, major, minor;
227 char *driver, *device;
228 unsigned int nformats, *formats;
229 unsigned int i, width = 500, height = 500;
230 CARD32 *pval;
232 MSG("attempting to open X11 connection");
233 dpy = XOpenDisplay(NULL);
234 if (!dpy) {
235 ERROR("Could not open display");
236 goto no_x11;
237 }
239 if (!DRI2InitDisplay(dpy, &ops)) {
240 ERROR("DRI2InitDisplay failed");
241 goto no_x11;
242 }
244 if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) {
245 ERROR("DRI2QueryExtension failed");
246 goto no_x11;
247 }
249 MSG("DRI2QueryExtension: eventBase=%d, errorBase=%d", eventBase, errorBase);
251 if (!DRI2QueryVersion(dpy, &major, &minor)) {
252 ERROR("DRI2QueryVersion failed");
253 goto no_x11;
254 }
256 MSG("DRI2QueryVersion: major=%d, minor=%d", major, minor);
258 root = RootWindow(dpy, DefaultScreen(dpy));
260 if (!DRI2Connect(dpy, root, DRI2DriverDRI, &driver, &device)) {
261 MSG("DRI2Connect failed");
262 goto no_x11;
263 }
265 MSG("DRI2Connect: driver=%s, device=%s", driver, device);
267 disp_x11 = calloc(1, sizeof(*disp_x11));
268 if (!disp_x11) {
269 ERROR("allocation failed");
270 goto no_x11;
271 }
273 disp = &disp_x11->base;
275 if (!global_fd) {
276 MSG("opening device: %s", device);
277 global_fd = open(device, O_RDWR);
278 if (global_fd < 0) {
279 ERROR("could not open drm device: %s (%d)",
280 strerror(errno), errno);
281 goto no_x11_free;
282 }
284 if (drmGetMagic(global_fd, &magic)) {
285 ERROR("drmGetMagic failed");
286 goto no_x11_free;
287 }
289 if (!DRI2Authenticate(dpy, root, magic)) {
290 ERROR("DRI2Authenticate failed");
291 goto no_x11_free;
292 }
293 }
295 disp->fd = global_fd;
297 disp->dev = omap_device_new(disp->fd);
298 if (!disp->dev) {
299 ERROR("couldn't create device");
300 goto no_x11_free;
301 }
303 disp->get_buffers = get_buffers;
304 disp->get_vid_buffers = get_vid_buffers;
305 disp->post_buffer = post_buffer;
306 disp->post_vid_buffer = post_vid_buffer;
307 disp->multiplanar = false;
309 /* note: set args to NULL after we've parsed them so other modules know
310 * that it is already parsed (since the arg parsing is decentralized)
311 */
312 for (i = 1; i < argc; i++) {
313 if (!argv[i]) {
314 continue;
315 }
316 if (!strcmp("-w", argv[i])) {
317 argv[i++] = NULL;
318 if (sscanf(argv[i], "%dx%d", &width, &height) != 2) {
319 ERROR("invalid arg: %s", argv[i]);
320 goto no_x11_free;
321 }
322 } else {
323 /* ignore */
324 continue;
325 }
326 argv[i] = NULL;
327 }
329 win = XCreateSimpleWindow(dpy, RootWindow(dpy, 0), 1, 1,
330 width, height, 0, BlackPixel (dpy, 0), BlackPixel(dpy, 0));
331 XMapWindow(dpy, win);
332 XFlush(dpy);
334 disp_x11->dpy = dpy;
335 disp_x11->win = win;
337 if (!DRI2GetFormats(dpy, RootWindow(dpy, DefaultScreen(dpy)),
338 &nformats, &formats)) {
339 ERROR("DRI2GetFormats failed");
340 goto no_x11_free;
341 }
343 if (nformats == 0) {
344 ERROR("no formats!");
345 goto no_x11_free;
346 }
348 /* print out supported formats */
349 MSG("Found %d supported formats:", nformats);
350 for (i = 0; i < nformats; i++) {
351 if (is_fourcc(formats[i])) {
352 MSG(" %d: %08x (\"%.4s\")", i, formats[i], (char *)&formats[i]);
353 } else {
354 MSG(" %d: %08x (device dependent)", i, formats[i]);
355 }
356 }
358 DRI2CreateDrawable(dpy, win);
360 /* check some attribute.. just to exercise the code-path: */
361 if (!DRI2GetAttribute(dpy, win, ATOM("XV_CSC_MATRIX"), &i, &pval)) {
362 ERROR("DRI2GetAttribute failed");
363 goto no_x11_free;
364 }
366 MSG("Got CSC matrix:");
367 print_hex(i*4, (const unsigned char *)pval);
369 // XXX
371 return disp;
373 no_x11_free:
374 XFree(driver);
375 XFree(device);
376 no_x11:
377 ERROR("unimplemented");
378 return NULL;
379 }
381 void disp_x11_close(struct display *disp)
382 {
383 struct display_x11 *disp_x11 = to_display_x11(disp);
384 XCloseDisplay(disp_x11->dpy);
385 }