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
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #include <sys/types.h>
29 #include <X11/Xlibint.h>
30 #include <X11/extensions/XShm.h>
31 #include "util/u_memory.h"
32 #include "util/u_math.h"
33 #include "util/u_format.h"
37 #include "x11_screen.h"
46 * This is used to fetch GLX visuals/fbconfigs. It uses code from egl_xdri.
47 * It might be better to rewrite the part in Xlib or XCB.
49 __GLXdisplayPrivate
*glx_dpy
;
51 int dri_major
, dri_minor
;
59 /* cached values for x11_drawable_get_depth */
60 Drawable last_drawable
;
61 unsigned int last_depth
;
66 * Create a X11 screen.
69 x11_screen_create(Display
*dpy
, int screen
)
71 struct x11_screen
*xscr
;
73 if (screen
>= ScreenCount(dpy
))
76 xscr
= CALLOC_STRUCT(x11_screen
);
79 xscr
->number
= screen
;
88 * Destroy a X11 screen.
91 x11_screen_destroy(struct x11_screen
*xscr
)
93 if (xscr
->dri_fd
>= 0)
96 Xfree(xscr
->dri_driver
);
98 Xfree(xscr
->dri_device
);
100 /* xscr->glx_dpy will be destroyed with the X display */
103 XFree(xscr
->visuals
);
108 x11_screen_init_dri2(struct x11_screen
*xscr
)
110 if (xscr
->dri_major
< 0) {
111 int eventBase
, errorBase
;
113 if (!DRI2QueryExtension(xscr
->dpy
, &eventBase
, &errorBase
) ||
114 !DRI2QueryVersion(xscr
->dpy
, &xscr
->dri_major
, &xscr
->dri_minor
))
115 xscr
->dri_major
= -1;
117 return (xscr
->dri_major
>= 0);
121 x11_screen_init_glx(struct x11_screen
*xscr
)
124 xscr
->glx_dpy
= __glXInitialize(xscr
->dpy
);
125 return (xscr
->glx_dpy
!= NULL
);
129 * Return true if the screen supports the extension.
132 x11_screen_support(struct x11_screen
*xscr
, enum x11_screen_extension ext
)
134 boolean supported
= FALSE
;
137 case X11_SCREEN_EXTENSION_XSHM
:
138 supported
= XShmQueryExtension(xscr
->dpy
);
140 case X11_SCREEN_EXTENSION_GLX
:
141 supported
= x11_screen_init_glx(xscr
);
143 case X11_SCREEN_EXTENSION_DRI2
:
144 supported
= x11_screen_init_dri2(xscr
);
154 * Return the X visuals.
157 x11_screen_get_visuals(struct x11_screen
*xscr
, int *num_visuals
)
159 if (!xscr
->visuals
) {
160 XVisualInfo vinfo_template
;
161 vinfo_template
.screen
= xscr
->number
;
162 xscr
->visuals
= XGetVisualInfo(xscr
->dpy
, VisualScreenMask
,
163 &vinfo_template
, &xscr
->num_visuals
);
167 *num_visuals
= xscr
->num_visuals
;
168 return xscr
->visuals
;
172 x11_screen_convert_visual(struct x11_screen
*xscr
, const XVisualInfo
*visual
,
173 __GLcontextModes
*mode
)
178 r
= util_bitcount(visual
->red_mask
);
179 g
= util_bitcount(visual
->green_mask
);
180 b
= util_bitcount(visual
->blue_mask
);
181 a
= visual
->depth
- (r
+ g
+ b
);
182 #if defined(__cplusplus) || defined(c_plusplus)
183 visual_type
= visual
->c_class
;
185 visual_type
= visual
->class;
188 /* convert to GLX visual type */
189 switch (visual_type
) {
191 visual_type
= GLX_TRUE_COLOR
;
194 visual_type
= GLX_DIRECT_COLOR
;
197 visual_type
= GLX_PSEUDO_COLOR
;
200 visual_type
= GLX_STATIC_COLOR
;
203 visual_type
= GLX_GRAY_SCALE
;
206 visual_type
= GLX_STATIC_GRAY
;
209 visual_type
= GLX_NONE
;
213 mode
->rgbBits
= r
+ g
+ b
+ a
;
218 mode
->visualID
= visual
->visualid
;
219 mode
->visualType
= visual_type
;
222 mode
->renderType
= GLX_RGBA_BIT
;
223 mode
->rgbMode
= TRUE
;
224 mode
->visualRating
= GLX_SLOW_CONFIG
;
225 mode
->xRenderable
= TRUE
;
229 * Return the GLX fbconfigs.
231 const __GLcontextModes
*
232 x11_screen_get_glx_configs(struct x11_screen
*xscr
)
234 return (x11_screen_init_glx(xscr
))
235 ? xscr
->glx_dpy
->screenConfigs
[xscr
->number
].configs
240 * Return the GLX visuals.
242 const __GLcontextModes
*
243 x11_screen_get_glx_visuals(struct x11_screen
*xscr
)
245 return (x11_screen_init_glx(xscr
))
246 ? xscr
->glx_dpy
->screenConfigs
[xscr
->number
].visuals
251 x11_screen_is_driver_equal(struct x11_screen
*xscr
, const char *driver
)
253 return (strcmp(xscr
->dri_driver
, driver
) == 0);
257 * Probe the screen for the DRI2 driver name.
260 x11_screen_probe_dri2(struct x11_screen
*xscr
)
262 /* get the driver name and the device name */
263 if (!xscr
->dri_driver
) {
264 if (!DRI2Connect(xscr
->dpy
, RootWindow(xscr
->dpy
, xscr
->number
),
265 &xscr
->dri_driver
, &xscr
->dri_device
))
266 xscr
->dri_driver
= xscr
->dri_device
= NULL
;
269 return xscr
->dri_driver
;
273 * Enable DRI2 and returns the file descriptor of the DRM device. The file
274 * descriptor will be closed automatically when the screen is destoryed.
277 x11_screen_enable_dri2(struct x11_screen
*xscr
, const char *driver
)
279 if (xscr
->dri_fd
< 0) {
283 /* get the driver name and the device name first */
284 if (!x11_screen_probe_dri2(xscr
))
287 if (!x11_screen_is_driver_equal(xscr
, driver
)) {
288 _eglLog(_EGL_WARNING
, "Driver mismatch: %s != %s",
289 xscr
->dri_driver
, driver
);
293 fd
= open(xscr
->dri_device
, O_RDWR
);
295 _eglLog(_EGL_WARNING
, "failed to open %s", xscr
->dri_device
);
299 memset(&magic
, 0, sizeof(magic
));
300 if (drmGetMagic(fd
, &magic
)) {
301 _eglLog(_EGL_WARNING
, "failed to get magic");
306 if (!DRI2Authenticate(xscr
->dpy
,
307 RootWindow(xscr
->dpy
, xscr
->number
), magic
)) {
308 _eglLog(_EGL_WARNING
, "failed to authenticate magic");
320 * Create/Destroy the DRI drawable.
323 x11_drawable_enable_dri2(struct x11_screen
*xscr
,
324 Drawable drawable
, boolean on
)
327 DRI2CreateDrawable(xscr
->dpy
, drawable
);
329 DRI2DestroyDrawable(xscr
->dpy
, drawable
);
333 * Copy between buffers of the DRI2 drawable.
336 x11_drawable_copy_buffers(struct x11_screen
*xscr
, Drawable drawable
,
337 int x
, int y
, int width
, int height
,
338 int src_buf
, int dst_buf
)
341 XserverRegion region
;
346 rect
.height
= height
;
348 region
= XFixesCreateRegion(xscr
->dpy
, &rect
, 1);
349 DRI2CopyRegion(xscr
->dpy
, drawable
, region
, dst_buf
, src_buf
);
350 XFixesDestroyRegion(xscr
->dpy
, region
);
354 * Get the buffers of the DRI2 drawable. The returned array should be freed.
356 struct x11_drawable_buffer
*
357 x11_drawable_get_buffers(struct x11_screen
*xscr
, Drawable drawable
,
358 int *width
, int *height
, unsigned int *attachments
,
359 boolean with_format
, int num_ins
, int *num_outs
)
361 DRI2Buffer
*dri2bufs
;
364 dri2bufs
= DRI2GetBuffersWithFormat(xscr
->dpy
, drawable
, width
, height
,
365 attachments
, num_ins
, num_outs
);
367 dri2bufs
= DRI2GetBuffers(xscr
->dpy
, drawable
, width
, height
,
368 attachments
, num_ins
, num_outs
);
370 return (struct x11_drawable_buffer
*) dri2bufs
;
374 * Return the depth of a drawable.
376 * Unlike other drawable functions, the drawable needs not be a DRI2 drawable.
379 x11_drawable_get_depth(struct x11_screen
*xscr
, Drawable drawable
)
383 if (drawable
!= xscr
->last_drawable
) {
386 unsigned int w
, h
, border
;
389 ok
= XGetGeometry(xscr
->dpy
, drawable
, &root
,
390 &x
, &y
, &w
, &h
, &border
, &depth
);
394 xscr
->last_drawable
= drawable
;
395 xscr
->last_depth
= depth
;
398 depth
= xscr
->last_depth
;
405 * Create a mode list of the given size.
408 x11_context_modes_create(unsigned count
)
410 const size_t size
= sizeof(__GLcontextModes
);
411 __GLcontextModes
*base
= NULL
;
412 __GLcontextModes
**next
;
416 for (i
= 0; i
< count
; i
++) {
417 *next
= (__GLcontextModes
*) calloc(1, size
);
419 x11_context_modes_destroy(base
);
423 next
= &((*next
)->next
);
430 * Destroy a mode list.
433 x11_context_modes_destroy(__GLcontextModes
*modes
)
435 while (modes
!= NULL
) {
436 __GLcontextModes
*next
= modes
->next
;
443 * Return the number of the modes in the mode list.
446 x11_context_modes_count(const __GLcontextModes
*modes
)
448 const __GLcontextModes
*mode
;
450 for (mode
= modes
; mode
; mode
= mode
->next
)