10 #define extern extern __attribute__((weak))
12 #include <X11/Xlibint.h>
13 #include <X11/extensions/dri2tokens.h>
14 #include <X11/extensions/dri2proto.h>
15 #include <X11/extensions/extutil.h>
18 static void *driOpenDriver(const char *driverName
)
20 void *glhandle
, *handle
;
21 const char *libPaths
, *p
, *next
;
22 char realDriverName
[200];
25 /* Attempt to make sure libGL symbols will be visible to the driver */
26 glhandle
= dlopen("libGL.so.1", RTLD_NOW
| RTLD_GLOBAL
);
29 if (geteuid() == getuid()) {
30 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
31 libPaths
= getenv("LIBGL_DRIVERS_PATH");
33 libPaths
= getenv("LIBGL_DRIVERS_DIR"); /* deprecated */
37 libPaths
= "/usr/lib/dri";
40 for (p
= libPaths
; *p
; p
= next
) {
41 next
= strchr(p
, ':');
50 snprintf(realDriverName
, sizeof realDriverName
,
51 "%.*s/tls/%s_dri.so", len
, p
, driverName
);
53 handle
= dlopen(realDriverName
, RTLD_NOW
| RTLD_GLOBAL
);
55 if ( handle
== NULL
) {
56 snprintf(realDriverName
, sizeof realDriverName
,
57 "%.*s/%s_dri.so", len
, p
, driverName
);
58 handle
= dlopen(realDriverName
, RTLD_NOW
| RTLD_GLOBAL
);
72 drm_open_driver(const char* driver_name
, struct drm_api
** papi
)
75 struct drm_api
* (*p_drm_api_create
)(void);
78 driver
= driOpenDriver(driver_name
);
82 // TODO: this is not necessarily public. We may want to use _egl Main instead; note that we need to check that the name is "DRM/Gallium/Win" since it may be non-Gallium
83 p_drm_api_create
= dlsym(driver
, "drm_api_create");
84 if(!p_drm_api_create
) // non-Gallium driver
87 api
= p_drm_api_create();
99 extern __attribute__((weak
)) ssize_t
getline(char **lineptr
, size_t *n
, FILE *stream
);
102 drm_get_driver_name(int card
)
113 snprintf(path
, sizeof(path
), "/sys/class/drm/card%d/dri_library_name", card
);
115 f
= fopen(path
, "r");
119 driver
= malloc(sizeof(PATH_MAX
));
122 len
= getline(&driver
, &driver_len
, f
); /* this is Linux-only so we must have glibc */
127 /* remove the trailing newline from sysfs */
128 driver
[len
- 1] = '\0';
136 drmIoctl(int fd
, unsigned long request
, void *arg
)
141 ret
= ioctl(fd
, request
, arg
);
142 } while (ret
== -1 && (errno
== EINTR
|| errno
== EAGAIN
));
149 char path
[ NAME_MAX
];
151 drm_set_version_t sv
;
153 sprintf(path
, "/dev/dri/card%d", card
);
154 fd
= open(path
, O_RDWR
, 0);
158 /* Set the interface version, asking for 1.2 */
161 sv
.drm_dd_major
= -1;
162 sv
.drm_dd_minor
= -1;
164 if (drmIoctl(fd
, DRM_IOCTL_SET_VERSION
, &sv
))
174 static cairo_space_t
*
175 _cairo_gallium_drm_space_create (int fd
, void* driver
, struct drm_api
* api
, unsigned flags
)
177 cairo_gpu_space_t
* space
;
178 struct pipe_screen
* screen
;
179 struct drm_create_screen_arg arg
;
181 arg
.mode
= DRM_CREATE_NORMAL
;
182 screen
= api
->create_screen(api
, fd
, &arg
);
184 space
= _cairo_gpu_space__begin_create();
187 screen
->destroy(screen
);
191 space
->api
= API_DRM
;
192 space
->drm
.driver
= driver
;
194 space
->drm
.api
= api
;
195 space
->screen
= screen
;
196 space
->owns_screen
= 1;
198 _cairo_gpu_space__finish_create(space
, flags
);
203 cairo_gallium_drm_space_wrap(struct drm_api
* api
, struct pipe_screen
* screen
, unsigned flags
)
205 cairo_gpu_space_t
* space
= _cairo_gpu_space__begin_create();
209 space
->api
= API_DRM
;
210 space
->drm
.api
= api
;
212 space
->screen
= screen
;
213 space
->owns_screen
= 1;
215 _cairo_gpu_space__finish_create(space
, flags
);
220 cairo_gallium_drm_space_create (int card
, unsigned flags
)
222 cairo_space_t
* space
;
230 driver_name
= drm_get_driver_name(0);
234 driver
= drm_open_driver(driver_name
, &api
);
243 if (drmIoctl(fd
, DRM_IOCTL_GET_MAGIC
, &auth
))
246 if (drmIoctl(fd
, DRM_IOCTL_AUTH_MAGIC
, &auth
))
249 space
= _cairo_gallium_drm_space_create(fd
, driver
, api
, flags
);
260 static char dri2ExtensionName
[] = DRI2_NAME
;
261 static XExtensionInfo
*dri2Info
;
262 static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay
, dri2Info
);
263 static /* const */ XExtensionHooks dri2ExtensionHooks
= {
264 NULL
, /* create_gc */
268 NULL
, /* create_font */
269 NULL
, /* free_font */
270 DRI2CloseDisplay
, /* close_display */
271 NULL
, /* wire_to_event */
272 NULL
, /* event_to_wire */
274 NULL
, /* error_string */
277 static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay
, dri2Info
,
282 static Bool
DRI2Connect(Display
*dpy
, XID window
,
283 char **driverName
, char **deviceName
)
285 XExtDisplayInfo
*info
= DRI2FindDisplay(dpy
);
286 xDRI2ConnectReply rep
;
287 xDRI2ConnectReq
*req
;
289 XextCheckExtension (dpy
, info
, DRI2_NAME
, False
);
292 GetReq(DRI2Connect
, req
);
293 req
->reqType
= info
->codes
->major_opcode
;
294 req
->dri2ReqType
= X_DRI2Connect
;
295 req
->window
= window
;
296 req
->driverType
= DRI2DriverDRI
;
297 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
303 if (rep
.driverNameLength
== 0 && rep
.deviceNameLength
== 0) {
309 *driverName
= Xmalloc(rep
.driverNameLength
+ 1);
310 if (*driverName
== NULL
) {
312 ((rep
.driverNameLength
+ 3) & ~3) +
313 ((rep
.deviceNameLength
+ 3) & ~3));
318 _XReadPad(dpy
, *driverName
, rep
.driverNameLength
);
319 (*driverName
)[rep
.driverNameLength
] = '\0';
321 *deviceName
= Xmalloc(rep
.deviceNameLength
+ 1);
322 if (*deviceName
== NULL
) {
324 _XEatData(dpy
, ((rep
.deviceNameLength
+ 3) & ~3));
329 _XReadPad(dpy
, *deviceName
, rep
.deviceNameLength
);
330 (*deviceName
)[rep
.deviceNameLength
] = '\0';
338 static Bool
DRI2Authenticate(Display
*dpy
, XID window
, drm_magic_t magic
)
340 XExtDisplayInfo
*info
= DRI2FindDisplay(dpy
);
341 xDRI2AuthenticateReq
*req
;
342 xDRI2AuthenticateReply rep
;
344 XextCheckExtension (dpy
, info
, DRI2_NAME
, False
);
347 GetReq(DRI2Authenticate
, req
);
348 req
->reqType
= info
->codes
->major_opcode
;
349 req
->dri2ReqType
= X_DRI2Authenticate
;
350 req
->window
= window
;
353 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
362 return rep
.authenticated
;
366 cairo_gallium_x11_space_wrap (Display
* dpy
, int scr
, cairo_bool_t owns_dpy
, unsigned flags
)
368 cairo_space_t
* space
;
369 char *driver_name
, *device_name
;
375 if (!DRI2Connect(dpy
, RootWindow(dpy
, scr
), &driver_name
, &device_name
))
378 driver
= drm_open_driver(driver_name
, &api
);
386 fd
= open(device_name
, O_RDWR
);
391 if (drmIoctl(fd
, DRM_IOCTL_GET_MAGIC
, &auth
))
394 if(!DRI2Authenticate(dpy
, RootWindow(dpy
, scr
), auth
.magic
))
397 space
= _cairo_gallium_drm_space_create(fd
, driver
, api
, flags
);
402 ((cairo_gpu_space_t
*)space
)->drm
.dpy
= dpy
;
413 cairo_gallium_x11_space_create (const char* name
, unsigned flags
)
415 cairo_space_t
* space
;
419 dpy
= XOpenDisplay(name
);
420 space
= cairo_gallium_x11_space_wrap(dpy
, DefaultScreen(dpy
), 1, flags
);
427 _cairo_gpu_drm_space_destroy(cairo_gpu_space_t
* space
)
429 if(space
->drm
.driver
)
430 dlclose(space
->drm
.driver
);
431 if(space
->drm
.fd
>= 0)
432 close(space
->drm
.fd
);
434 XCloseDisplay(space
->drm
.dpy
);