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 #include <stdio.h>
34 #include <X11/Xlibint.h>
35 #include <X11/extensions/Xext.h>
36 #include <X11/extensions/extutil.h>
37 #include <X11/extensions/dri2proto.h>
38 #include <X11/extensions/dri2tokens.h>
39 #include <xf86drm.h>
40 #include <drm.h>
41 #include <fcntl.h>
42 #include <unistd.h>
43
44 #include "dri2.h"
45
46 static char dri2ExtensionName[] = DRI2_NAME;
47 static XExtensionInfo *dri2Info;
48 static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info)
49
50 static /* const */ XExtensionHooks dri2ExtensionHooks = {
51 NULL, /* create_gc */
52 NULL, /* copy_gc */
53 NULL, /* flush_gc */
54 NULL, /* free_gc */
55 NULL, /* create_font */
56 NULL, /* free_font */
57 DRI2CloseDisplay, /* close_display */
58 };
59
60 static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
61 dri2Info,
62 dri2ExtensionName,
63 &dri2ExtensionHooks,
64 0, NULL)
65
66 static Bool
DRI2Connect(Display * dpy,XID window,char ** driverName,char ** deviceName)67 DRI2Connect(Display *dpy, XID window, char **driverName, char **deviceName)
68 {
69 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
70 xDRI2ConnectReply rep;
71 xDRI2ConnectReq *req;
72
73 XextCheckExtension(dpy, info, dri2ExtensionName, False);
74
75 LockDisplay(dpy);
76 GetReq(DRI2Connect, req);
77 req->reqType = info->codes->major_opcode;
78 req->dri2ReqType = X_DRI2Connect;
79 req->window = window;
80 req->driverType = DRI2DriverDRI;
81 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
82 UnlockDisplay(dpy);
83 SyncHandle();
84 return False;
85 }
86
87 if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
88 UnlockDisplay(dpy);
89 SyncHandle();
90 return False;
91 }
92
93 *driverName = Xmalloc(rep.driverNameLength + 1);
94 if (*driverName == NULL) {
95 _XEatData(dpy,
96 ((rep.driverNameLength + 3) & ~3) +
97 ((rep.deviceNameLength + 3) & ~3));
98 UnlockDisplay(dpy);
99 SyncHandle();
100 return False;
101 }
102 _XReadPad(dpy, *driverName, rep.driverNameLength);
103 (*driverName)[rep.driverNameLength] = '\0';
104
105 *deviceName = Xmalloc(rep.deviceNameLength + 1);
106 if (*deviceName == NULL) {
107 Xfree(*driverName);
108 _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
109 UnlockDisplay(dpy);
110 SyncHandle();
111 return False;
112 }
113 _XReadPad(dpy, *deviceName, rep.deviceNameLength);
114 (*deviceName)[rep.deviceNameLength] = '\0';
115
116 UnlockDisplay(dpy);
117 SyncHandle();
118
119 return True;
120 }
121
122 static Bool
DRI2Authenticate(Display * dpy,XID window,unsigned int magic)123 DRI2Authenticate(Display * dpy, XID window, unsigned int magic)
124 {
125 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
126 xDRI2AuthenticateReq *req;
127 xDRI2AuthenticateReply rep;
128
129 XextCheckExtension(dpy, info, dri2ExtensionName, False);
130
131 LockDisplay(dpy);
132 GetReq(DRI2Authenticate, req);
133 req->reqType = info->codes->major_opcode;
134 req->dri2ReqType = X_DRI2Authenticate;
135 req->window = window;
136 req->magic = magic;
137
138 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
139 UnlockDisplay(dpy);
140 SyncHandle();
141 return False;
142 }
143
144 UnlockDisplay(dpy);
145 SyncHandle();
146
147 return rep.authenticated;
148 }
149
dri2_open(Display * dpy)150 int dri2_open(Display *dpy)
151 {
152 drm_auth_t auth;
153 char *driver, *device;
154 int fd;
155
156 if (!DRI2Connect(dpy, DefaultRootWindow(dpy), &driver, &device))
157 return -1;
158
159 fd = open(device, O_RDWR);
160 if (fd < 0)
161 return -1;
162
163 if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth))
164 goto err_fd;
165
166 if (!DRI2Authenticate(dpy, DefaultRootWindow(dpy), auth.magic))
167 goto err_fd;
168
169 return fd;
170
171 err_fd:
172 close(fd);
173 return -1;
174 }
175