2 * Mesa 3-D graphics library
5 * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
28 #include <sys/types.h>
31 #include <X11/Xlibint.h>
32 #include <X11/extensions/XShm.h>
34 #include "util/u_memory.h"
37 #include "x11_screen.h"
46 * This is used to fetch GLX visuals/fbconfigs. It steals code from GLX.
47 * It might be better to rewrite the part in Xlib or XCB.
49 __GLXdisplayPrivate
*glx_dpy
;
51 int dri_major
, dri_minor
;
56 x11_drawable_invalidate_buffers dri_invalidate_buffers
;
62 /* cached values for x11_drawable_get_depth */
63 Drawable last_drawable
;
64 unsigned int last_depth
;
69 * Create a X11 screen.
72 x11_screen_create(Display
*dpy
, int screen
)
74 struct x11_screen
*xscr
;
76 if (screen
>= ScreenCount(dpy
))
79 xscr
= CALLOC_STRUCT(x11_screen
);
82 xscr
->number
= screen
;
91 * Destroy a X11 screen.
94 x11_screen_destroy(struct x11_screen
*xscr
)
96 if (xscr
->dri_fd
>= 0)
99 Xfree(xscr
->dri_driver
);
100 if (xscr
->dri_device
)
101 Xfree(xscr
->dri_device
);
103 #ifdef GLX_DIRECT_RENDERING
104 /* xscr->glx_dpy will be destroyed with the X display */
106 xscr
->glx_dpy
->xscr
= NULL
;
110 XFree(xscr
->visuals
);
114 #ifdef GLX_DIRECT_RENDERING
117 x11_screen_init_dri2(struct x11_screen
*xscr
)
119 if (xscr
->dri_major
< 0) {
120 int eventBase
, errorBase
;
122 if (!DRI2QueryExtension(xscr
->dpy
, &eventBase
, &errorBase
) ||
123 !DRI2QueryVersion(xscr
->dpy
, &xscr
->dri_major
, &xscr
->dri_minor
))
124 xscr
->dri_major
= -1;
126 return (xscr
->dri_major
>= 0);
130 x11_screen_init_glx(struct x11_screen
*xscr
)
133 xscr
->glx_dpy
= __glXInitialize(xscr
->dpy
);
134 return (xscr
->glx_dpy
!= NULL
);
137 #endif /* GLX_DIRECT_RENDERING */
140 * Return true if the screen supports the extension.
143 x11_screen_support(struct x11_screen
*xscr
, enum x11_screen_extension ext
)
145 boolean supported
= FALSE
;
148 case X11_SCREEN_EXTENSION_XSHM
:
149 supported
= XShmQueryExtension(xscr
->dpy
);
151 #ifdef GLX_DIRECT_RENDERING
152 case X11_SCREEN_EXTENSION_GLX
:
153 supported
= x11_screen_init_glx(xscr
);
155 case X11_SCREEN_EXTENSION_DRI2
:
156 supported
= x11_screen_init_dri2(xscr
);
167 * Return the X visuals.
170 x11_screen_get_visuals(struct x11_screen
*xscr
, int *num_visuals
)
172 if (!xscr
->visuals
) {
173 XVisualInfo vinfo_template
;
174 vinfo_template
.screen
= xscr
->number
;
175 xscr
->visuals
= XGetVisualInfo(xscr
->dpy
, VisualScreenMask
,
176 &vinfo_template
, &xscr
->num_visuals
);
180 *num_visuals
= xscr
->num_visuals
;
181 return xscr
->visuals
;
185 * Return the depth of a drawable.
187 * Unlike other drawable functions, the drawable needs not be a DRI2 drawable.
190 x11_drawable_get_depth(struct x11_screen
*xscr
, Drawable drawable
)
194 if (drawable
!= xscr
->last_drawable
) {
197 unsigned int w
, h
, border
;
200 ok
= XGetGeometry(xscr
->dpy
, drawable
, &root
,
201 &x
, &y
, &w
, &h
, &border
, &depth
);
205 xscr
->last_drawable
= drawable
;
206 xscr
->last_depth
= depth
;
209 depth
= xscr
->last_depth
;
215 #ifdef GLX_DIRECT_RENDERING
218 * Return the GLX fbconfigs.
220 const __GLcontextModes
*
221 x11_screen_get_glx_configs(struct x11_screen
*xscr
)
223 return (x11_screen_init_glx(xscr
))
224 ? xscr
->glx_dpy
->screenConfigs
[xscr
->number
]->configs
229 * Probe the screen for the DRI2 driver name.
232 x11_screen_probe_dri2(struct x11_screen
*xscr
, int *major
, int *minor
)
234 if (!x11_screen_init_dri2(xscr
))
237 /* get the driver name and the device name */
238 if (!xscr
->dri_driver
) {
239 if (!DRI2Connect(xscr
->dpy
, RootWindow(xscr
->dpy
, xscr
->number
),
240 &xscr
->dri_driver
, &xscr
->dri_device
))
241 xscr
->dri_driver
= xscr
->dri_device
= NULL
;
244 *major
= xscr
->dri_major
;
246 *minor
= xscr
->dri_minor
;
248 return xscr
->dri_driver
;
252 * Enable DRI2 and returns the file descriptor of the DRM device. The file
253 * descriptor will be closed automatically when the screen is destoryed.
256 x11_screen_enable_dri2(struct x11_screen
*xscr
,
257 x11_drawable_invalidate_buffers invalidate_buffers
,
260 if (xscr
->dri_fd
< 0) {
264 /* get the driver name and the device name first */
265 if (!x11_screen_probe_dri2(xscr
, NULL
, NULL
))
269 fd
= open(xscr
->dri_device
, O_RDWR
| O_CLOEXEC
);
270 if (fd
== -1 && errno
== EINVAL
)
273 fd
= open(xscr
->dri_device
, O_RDWR
);
275 fcntl(fd
, F_SETFD
, fcntl(fd
, F_GETFD
) | FD_CLOEXEC
);
278 _eglLog(_EGL_WARNING
, "failed to open %s", xscr
->dri_device
);
282 memset(&magic
, 0, sizeof(magic
));
283 if (drmGetMagic(fd
, &magic
)) {
284 _eglLog(_EGL_WARNING
, "failed to get magic");
289 if (!DRI2Authenticate(xscr
->dpy
,
290 RootWindow(xscr
->dpy
, xscr
->number
), magic
)) {
291 _eglLog(_EGL_WARNING
, "failed to authenticate magic");
296 if (!x11_screen_init_glx(xscr
)) {
297 _eglLog(_EGL_WARNING
, "failed to initialize GLX");
301 if (xscr
->glx_dpy
->xscr
) {
302 _eglLog(_EGL_WARNING
,
303 "display is already managed by another x11 screen");
308 xscr
->glx_dpy
->xscr
= xscr
;
309 xscr
->dri_invalidate_buffers
= invalidate_buffers
;
310 xscr
->dri_user_data
= user_data
;
319 x11_screen_get_device_name(struct x11_screen
*xscr
)
321 return xscr
->dri_device
;
325 x11_screen_authenticate(struct x11_screen
*xscr
, uint32_t id
)
327 boolean authenticated
;
329 authenticated
= DRI2Authenticate(xscr
->dpy
,
330 RootWindow(xscr
->dpy
, xscr
->number
), id
);
332 return authenticated
? 0 : -1;
336 * Create/Destroy the DRI drawable.
339 x11_drawable_enable_dri2(struct x11_screen
*xscr
,
340 Drawable drawable
, boolean on
)
343 DRI2CreateDrawable(xscr
->dpy
, drawable
);
345 DRI2DestroyDrawable(xscr
->dpy
, drawable
);
349 * Copy between buffers of the DRI2 drawable.
352 x11_drawable_copy_buffers_region(struct x11_screen
*xscr
, Drawable drawable
,
353 int num_rects
, const int *rects
,
354 int src_buf
, int dst_buf
)
356 XserverRegion region
;
357 XRectangle
*rectangles
= CALLOC(num_rects
, sizeof(XRectangle
));
359 for (int i
= 0; i
< num_rects
; i
++) {
360 rectangles
[i
].x
= rects
[i
* 4 + 0];
361 rectangles
[i
].y
= rects
[i
* 4 + 1];
362 rectangles
[i
].width
= rects
[i
* 4 + 2];
363 rectangles
[i
].height
= rects
[i
* 4 + 3];
366 region
= XFixesCreateRegion(xscr
->dpy
, rectangles
, num_rects
);
367 DRI2CopyRegion(xscr
->dpy
, drawable
, region
, dst_buf
, src_buf
);
368 XFixesDestroyRegion(xscr
->dpy
, region
);
373 * Get the buffers of the DRI2 drawable. The returned array should be freed.
375 struct x11_drawable_buffer
*
376 x11_drawable_get_buffers(struct x11_screen
*xscr
, Drawable drawable
,
377 int *width
, int *height
, unsigned int *attachments
,
378 boolean with_format
, int num_ins
, int *num_outs
)
380 DRI2Buffer
*dri2bufs
;
383 dri2bufs
= DRI2GetBuffersWithFormat(xscr
->dpy
, drawable
, width
, height
,
384 attachments
, num_ins
, num_outs
);
386 dri2bufs
= DRI2GetBuffers(xscr
->dpy
, drawable
, width
, height
,
387 attachments
, num_ins
, num_outs
);
389 return (struct x11_drawable_buffer
*) dri2bufs
;
393 * Create a mode list of the given size.
396 x11_context_modes_create(unsigned count
)
398 const size_t size
= sizeof(__GLcontextModes
);
399 __GLcontextModes
*base
= NULL
;
400 __GLcontextModes
**next
;
404 for (i
= 0; i
< count
; i
++) {
405 *next
= (__GLcontextModes
*) CALLOC(1, size
);
407 x11_context_modes_destroy(base
);
411 next
= &((*next
)->next
);
418 * Destroy a mode list.
421 x11_context_modes_destroy(__GLcontextModes
*modes
)
423 while (modes
!= NULL
) {
424 __GLcontextModes
*next
= modes
->next
;
431 * Return the number of the modes in the mode list.
434 x11_context_modes_count(const __GLcontextModes
*modes
)
436 const __GLcontextModes
*mode
;
438 for (mode
= modes
; mode
; mode
= mode
->next
)
444 dri2InvalidateBuffers(Display
*dpy
, XID drawable
);
447 * This is called from src/glx/dri2.c.
450 dri2InvalidateBuffers(Display
*dpy
, XID drawable
)
452 __GLXdisplayPrivate
*priv
= __glXInitialize(dpy
);
453 struct x11_screen
*xscr
= NULL
;
455 if (priv
&& priv
->xscr
)
457 if (!xscr
|| !xscr
->dri_invalidate_buffers
)
460 xscr
->dri_invalidate_buffers(xscr
, drawable
, xscr
->dri_user_data
);
464 dri2GetSwapEventType(Display
*dpy
, XID drawable
);
467 dri2GetGlxDrawableFromXDrawableId(Display
*dpy
, XID id
);
470 GetGLXDrawable(Display
*dpy
, XID drawable
);
473 * This is also called from src/glx/dri2.c.
475 unsigned dri2GetSwapEventType(Display
*dpy
, XID drawable
)
481 dri2GetGlxDrawableFromXDrawableId(Display
*dpy
, XID id
)
487 GetGLXDrawable(Display
*dpy
, XID drawable
)
492 #endif /* GLX_DIRECT_RENDERING */