Enable DRI2 based on Dodji Seketeli's DRI work
[xephyr-with-gl-acceleration:xephyr-with-gl-acceleration.git] / xserver / hw / kdrive / ephyr / dri2.c
1 /*
2  * Copyright © 2008 Red Hat, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Soft-
6  * ware"), to deal in the Software without restriction, including without
7  * limitation the rights to use, copy, modify, merge, publish, distribute,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, provided that the above copyright
10  * notice(s) and this permission notice appear in all copies of the Soft-
11  * ware and that both the above copyright notice(s) and this permission
12  * notice appear in supporting documentation.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16  * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
17  * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
18  * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
19  * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
22  * MANCE OF THIS SOFTWARE.
23  *
24  * Except as contained in this notice, the name of a copyright holder shall
25  * not be used in advertising or otherwise to promote the sale, use or
26  * other dealings in this Software without prior written authorization of
27  * the copyright holder.
28  *
29  * Authors:
30  *   Kristian Høgsberg (krh@redhat.com)
31  */
32
33 /* 
34  * Copied from Mesa source codes
35  */
36
37 #define NEED_REPLIES
38 #include <stdio.h>
39 #include <X11/Xlibint.h>
40 #include <X11/extensions/Xext.h>
41 #include <X11/extensions/extutil.h>
42 #include <X11/extensions/dri2proto.h>
43 #include "xf86drm.h"
44 #include "dri2.h"
45
46 /* Allow the build to work with an older versions of dri2proto.h and
47  * dri2tokens.h.
48  */
49 #if DRI2_MINOR < 1
50 #undef DRI2_MINOR
51 #define DRI2_MINOR 1
52 #define X_DRI2GetBuffersWithFormat 7
53 #endif
54
55
56 static char dri2ExtensionName[] = DRI2_NAME;
57 static XExtensionInfo *dri2Info;
58 static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info)
59
60 static Bool
61 DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire);
62 static Status
63 DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire);
64
65 static /* const */ XExtensionHooks dri2ExtensionHooks = {
66   NULL,                   /* create_gc */
67   NULL,                   /* copy_gc */
68   NULL,                   /* flush_gc */
69   NULL,                   /* free_gc */
70   NULL,                   /* create_font */
71   NULL,                   /* free_font */
72   DRI2CloseDisplay,       /* close_display */
73   DRI2WireToEvent,        /* wire_to_event */
74   DRI2EventToWire,        /* event_to_wire */
75   NULL,                   /* error */
76   NULL,                   /* error_string */
77 };
78
79 static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
80                                    dri2Info,
81                                    dri2ExtensionName,
82                                    &dri2ExtensionHooks,
83                                    0, NULL)
84
85 static Bool
86 DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
87 {
88 #if 0
89    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
90    XExtDisplayInfo *glx_info = glXFindDisplay(dpy);
91    XextCheckExtension(dpy, info, dri2ExtensionName, False);
92    switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
93
94 #ifdef X_DRI2SwapBuffers
95    case DRI2_BufferSwapComplete:
96    {
97       GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
98       xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire;
99       aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
100       aevent->type =
101           (glx_info->codes->first_event + GLX_BufferSwapComplete) & 0x75;
102       aevent->send_event = (awire->type & 0x80) != 0;
103       aevent->display = dpy;
104       aevent->drawable = awire->drawable;
105       switch (awire->event_type) {
106       case DRI2_EXCHANGE_COMPLETE:
107          aevent->event_type = GLX_EXCHANGE_COMPLETE_INTEL;
108          break;
109       case DRI2_BLIT_COMPLETE:
110          aevent->event_type = GLX_BLIT_COMPLETE_INTEL;
111          break;
112       case DRI2_FLIP_COMPLETE:
113          aevent->event_type = GLX_FLIP_COMPLETE_INTEL;
114          break;
115       default:
116          /* unknown swap completion type */
117          return False;
118       }
119       aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
120       aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
121       aevent->sbc = ((CARD64)awire->sbc_hi << 32) | awire->sbc_lo;
122       return True;
123    }
124 #endif
125 #ifdef DRI2_InvalidateBuffers
126    case DRI2_InvalidateBuffers:
127    {
128       xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire;
129
130       dri2InvalidateBuffers(dpy, awire->drawable);
131       return False;
132    }
133 #endif
134    default:
135       /* client doesn't support server event */
136       break;
137    }
138 #endif
139    return False;
140 }
141
142 /* We don't actually support this.  It doesn't make sense for clients to
143  * send each other DRI2 events.
144  */
145 static Status
146 DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire)
147 {
148    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
149
150    XextCheckExtension(dpy, info, dri2ExtensionName, False);
151
152    switch (event->type) {
153    default:
154       /* client doesn't support server event */
155       break;
156    }
157
158    return Success;
159 }
160
161 Bool
162 DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase)
163 {
164    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
165
166    if (XextHasExtension(info)) {
167       *eventBase = info->codes->first_event;
168       *errorBase = info->codes->first_error;
169       return True;
170    }
171
172    return False;
173 }
174
175 Bool
176 DRI2QueryVersion(Display * dpy, int *major, int *minor)
177 {
178    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
179    xDRI2QueryVersionReply rep;
180    xDRI2QueryVersionReq *req;
181    int i, nevents;
182
183    XextCheckExtension(dpy, info, dri2ExtensionName, False);
184
185    LockDisplay(dpy);
186    GetReq(DRI2QueryVersion, req);
187    req->reqType = info->codes->major_opcode;
188    req->dri2ReqType = X_DRI2QueryVersion;
189    req->majorVersion = DRI2_MAJOR;
190    req->minorVersion = DRI2_MINOR;
191    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
192       UnlockDisplay(dpy);
193       SyncHandle();
194       return False;
195    }
196    *major = rep.majorVersion;
197    *minor = rep.minorVersion;
198    UnlockDisplay(dpy);
199    SyncHandle();
200
201    switch (rep.minorVersion) {
202    case 1:
203            nevents = 0;
204            break;
205    case 2:
206            nevents = 1;
207            break;
208    case 3:
209    default:
210            nevents = 2;
211            break;
212    }
213
214    for (i = 0; i < nevents; i++) {
215        XESetWireToEvent (dpy, info->codes->first_event + i, DRI2WireToEvent);
216        XESetEventToWire (dpy, info->codes->first_event + i, DRI2EventToWire);
217    }
218
219    return True;
220 }
221
222 Bool
223 DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName)
224 {
225    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
226    xDRI2ConnectReply rep;
227    xDRI2ConnectReq *req;
228
229    XextCheckExtension(dpy, info, dri2ExtensionName, False);
230
231    LockDisplay(dpy);
232    GetReq(DRI2Connect, req);
233    req->reqType = info->codes->major_opcode;
234    req->dri2ReqType = X_DRI2Connect;
235    req->window = window;
236    req->driverType = DRI2DriverDRI;
237    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
238       UnlockDisplay(dpy);
239       SyncHandle();
240       return False;
241    }
242
243    if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
244       UnlockDisplay(dpy);
245       SyncHandle();
246       return False;
247    }
248
249    *driverName = Xmalloc(rep.driverNameLength + 1);
250    if (*driverName == NULL) {
251       _XEatData(dpy,
252                 ((rep.driverNameLength + 3) & ~3) +
253                 ((rep.deviceNameLength + 3) & ~3));
254       UnlockDisplay(dpy);
255       SyncHandle();
256       return False;
257    }
258    _XReadPad(dpy, *driverName, rep.driverNameLength);
259    (*driverName)[rep.driverNameLength] = '\0';
260
261    *deviceName = Xmalloc(rep.deviceNameLength + 1);
262    if (*deviceName == NULL) {
263       Xfree(*driverName);
264       _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
265       UnlockDisplay(dpy);
266       SyncHandle();
267       return False;
268    }
269    _XReadPad(dpy, *deviceName, rep.deviceNameLength);
270    (*deviceName)[rep.deviceNameLength] = '\0';
271
272    UnlockDisplay(dpy);
273    SyncHandle();
274
275    return True;
276 }
277
278 Bool
279 DRI2Authenticate(Display * dpy, XID window, drm_magic_t magic)
280 {
281    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
282    xDRI2AuthenticateReq *req;
283    xDRI2AuthenticateReply rep;
284
285    XextCheckExtension(dpy, info, dri2ExtensionName, False);
286
287    LockDisplay(dpy);
288    GetReq(DRI2Authenticate, req);
289    req->reqType = info->codes->major_opcode;
290    req->dri2ReqType = X_DRI2Authenticate;
291    req->window = window;
292    req->magic = magic;
293
294    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
295       UnlockDisplay(dpy);
296       SyncHandle();
297       return False;
298    }
299
300    UnlockDisplay(dpy);
301    SyncHandle();
302
303    return rep.authenticated;
304 }
305
306 void
307 DRI2CreateDrawable(Display * dpy, XID drawable)
308 {
309    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
310    xDRI2CreateDrawableReq *req;
311
312    XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
313
314    LockDisplay(dpy);
315    GetReq(DRI2CreateDrawable, req);
316    req->reqType = info->codes->major_opcode;
317    req->dri2ReqType = X_DRI2CreateDrawable;
318    req->drawable = drawable;
319    UnlockDisplay(dpy);
320    SyncHandle();
321 }
322
323 void
324 DRI2DestroyDrawable(Display * dpy, XID drawable)
325 {
326    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
327    xDRI2DestroyDrawableReq *req;
328
329    XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
330
331    XSync(dpy, False);
332
333    LockDisplay(dpy);
334    GetReq(DRI2DestroyDrawable, req);
335    req->reqType = info->codes->major_opcode;
336    req->dri2ReqType = X_DRI2DestroyDrawable;
337    req->drawable = drawable;
338    UnlockDisplay(dpy);
339    SyncHandle();
340 }
341
342 DRI2Buffer *
343 DRI2GetBuffers(Display * dpy, XID drawable,
344                int *width, int *height,
345                unsigned int *attachments, int count, int *outCount)
346 {
347    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
348    xDRI2GetBuffersReply rep;
349    xDRI2GetBuffersReq *req;
350    DRI2Buffer *buffers;
351    xDRI2Buffer repBuffer;
352    CARD32 *p;
353    int i;
354
355    XextCheckExtension(dpy, info, dri2ExtensionName, False);
356
357    LockDisplay(dpy);
358    GetReqExtra(DRI2GetBuffers, count * 4, req);
359    req->reqType = info->codes->major_opcode;
360    req->dri2ReqType = X_DRI2GetBuffers;
361    req->drawable = drawable;
362    req->count = count;
363    p = (CARD32 *) & req[1];
364    for (i = 0; i < count; i++)
365       p[i] = attachments[i];
366
367    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
368       UnlockDisplay(dpy);
369       SyncHandle();
370       return NULL;
371    }
372
373    *width = rep.width;
374    *height = rep.height;
375    *outCount = rep.count;
376
377    buffers = Xmalloc(rep.count * sizeof buffers[0]);
378    if (buffers == NULL) {
379       _XEatData(dpy, rep.count * sizeof repBuffer);
380       UnlockDisplay(dpy);
381       SyncHandle();
382       return NULL;
383    }
384
385    for (i = 0; i < rep.count; i++) {
386       _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
387       buffers[i].attachment = repBuffer.attachment;
388       buffers[i].name = repBuffer.name;
389       buffers[i].pitch = repBuffer.pitch;
390       buffers[i].cpp = repBuffer.cpp;
391       buffers[i].flags = repBuffer.flags;
392    }
393
394    UnlockDisplay(dpy);
395    SyncHandle();
396
397    return buffers;
398 }
399
400
401 DRI2Buffer *
402 DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
403                          int *width, int *height,
404                          unsigned int *attachments, int count, int *outCount)
405 {
406    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
407    xDRI2GetBuffersReply rep;
408    xDRI2GetBuffersReq *req;
409    DRI2Buffer *buffers;
410    xDRI2Buffer repBuffer;
411    CARD32 *p;
412    int i;
413
414    XextCheckExtension(dpy, info, dri2ExtensionName, False);
415
416    LockDisplay(dpy);
417    GetReqExtra(DRI2GetBuffers, count * (4 * 2), req);
418    req->reqType = info->codes->major_opcode;
419    req->dri2ReqType = X_DRI2GetBuffersWithFormat;
420    req->drawable = drawable;
421    req->count = count;
422    p = (CARD32 *) & req[1];
423    for (i = 0; i < (count * 2); i++)
424       p[i] = attachments[i];
425
426    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
427           fprintf(stderr, "GetBuffersWithFormat fails\n");
428       UnlockDisplay(dpy);
429       SyncHandle();
430       return NULL;
431    }
432
433    *width = rep.width;
434    *height = rep.height;
435    *outCount = rep.count;
436
437    buffers = Xmalloc(rep.count * sizeof buffers[0]);
438    if (buffers == NULL) {
439       _XEatData(dpy, rep.count * sizeof repBuffer);
440       UnlockDisplay(dpy);
441       SyncHandle();
442       return NULL;
443    }
444
445    for (i = 0; i < rep.count; i++) {
446       _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
447       buffers[i].attachment = repBuffer.attachment;
448       buffers[i].name = repBuffer.name;
449       buffers[i].pitch = repBuffer.pitch;
450       buffers[i].cpp = repBuffer.cpp;
451       buffers[i].flags = repBuffer.flags;
452    }
453
454    UnlockDisplay(dpy);
455    SyncHandle();
456
457    return buffers;
458 }
459
460
461 void
462 DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
463                CARD32 dest, CARD32 src)
464 {
465    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
466    xDRI2CopyRegionReq *req;
467    xDRI2CopyRegionReply rep;
468
469    XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
470
471    LockDisplay(dpy);
472    GetReq(DRI2CopyRegion, req);
473    req->reqType = info->codes->major_opcode;
474    req->dri2ReqType = X_DRI2CopyRegion;
475    req->drawable = drawable;
476    req->region = region;
477    req->dest = dest;
478    req->src = src;
479
480    _XReply(dpy, (xReply *) & rep, 0, xFalse);
481
482    UnlockDisplay(dpy);
483    SyncHandle();
484 }