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.
26 #include "util/u_memory.h"
27 #include "util/u_math.h"
28 #include "util/u_format.h"
29 #include "util/u_inlines.h"
30 #include "util/u_hash_table.h"
31 #include "pipe/p_compiler.h"
32 #include "pipe/p_screen.h"
33 #include "pipe/p_context.h"
34 #include "pipe/p_state.h"
35 #include "state_tracker/drm_driver.h"
38 #include "native_x11.h"
39 #include "x11_screen.h"
41 #include "common/native_helper.h"
42 #ifdef HAVE_WAYLAND_BACKEND
43 #include "common/native_wayland_drm_bufmgr_helper.h"
46 #ifdef GLX_DIRECT_RENDERING
49 struct native_display base
;
53 const struct native_event_handler
*event_handler
;
55 struct x11_screen
*xscr
;
57 const char *dri_driver
;
58 int dri_major
, dri_minor
;
60 struct dri2_config
*configs
;
63 struct util_hash_table
*surfaces
;
64 #ifdef HAVE_WAYLAND_BACKEND
65 struct wl_drm
*wl_server_drm
; /* for EGL_WL_bind_wayland_display */
70 struct native_surface base
;
72 enum pipe_format color_format
;
73 struct dri2_display
*dri2dpy
;
75 unsigned int server_stamp
;
76 unsigned int client_stamp
;
78 struct pipe_resource
*textures
[NUM_NATIVE_ATTACHMENTS
];
81 boolean have_back
, have_fake
;
83 struct x11_drawable_buffer
*last_xbufs
;
88 struct native_config base
;
91 static INLINE
struct dri2_display
*
92 dri2_display(const struct native_display
*ndpy
)
94 return (struct dri2_display
*) ndpy
;
97 static INLINE
struct dri2_surface
*
98 dri2_surface(const struct native_surface
*nsurf
)
100 return (struct dri2_surface
*) nsurf
;
103 static INLINE
struct dri2_config
*
104 dri2_config(const struct native_config
*nconf
)
106 return (struct dri2_config
*) nconf
;
110 * Process the buffers returned by the server.
113 dri2_surface_process_drawable_buffers(struct native_surface
*nsurf
,
114 struct x11_drawable_buffer
*xbufs
,
117 struct dri2_surface
*dri2surf
= dri2_surface(nsurf
);
118 struct dri2_display
*dri2dpy
= dri2surf
->dri2dpy
;
119 struct pipe_resource templ
;
120 struct winsys_handle whandle
;
124 /* free the old textures */
125 for (i
= 0; i
< NUM_NATIVE_ATTACHMENTS
; i
++)
126 pipe_resource_reference(&dri2surf
->textures
[i
], NULL
);
127 dri2surf
->valid_mask
= 0x0;
129 dri2surf
->have_back
= FALSE
;
130 dri2surf
->have_fake
= FALSE
;
135 memset(&templ
, 0, sizeof(templ
));
136 templ
.target
= PIPE_TEXTURE_2D
;
137 templ
.last_level
= 0;
138 templ
.width0
= dri2surf
->width
;
139 templ
.height0
= dri2surf
->height
;
141 templ
.array_size
= 1;
142 templ
.format
= dri2surf
->color_format
;
143 templ
.bind
= PIPE_BIND_RENDER_TARGET
;
146 for (i
= 0; i
< num_xbufs
; i
++) {
147 struct x11_drawable_buffer
*xbuf
= &xbufs
[i
];
149 enum native_attachment natt
;
151 switch (xbuf
->attachment
) {
152 case DRI2BufferFrontLeft
:
153 natt
= NATIVE_ATTACHMENT_FRONT_LEFT
;
154 desc
= "DRI2 Front Buffer";
156 case DRI2BufferFakeFrontLeft
:
157 natt
= NATIVE_ATTACHMENT_FRONT_LEFT
;
158 desc
= "DRI2 Fake Front Buffer";
159 dri2surf
->have_fake
= TRUE
;
161 case DRI2BufferBackLeft
:
162 natt
= NATIVE_ATTACHMENT_BACK_LEFT
;
163 desc
= "DRI2 Back Buffer";
164 dri2surf
->have_back
= TRUE
;
171 if (!desc
|| dri2surf
->textures
[natt
]) {
173 _eglLog(_EGL_WARNING
, "unknown buffer %d", xbuf
->attachment
);
175 _eglLog(_EGL_WARNING
, "both real and fake front buffers are listed");
179 memset(&whandle
, 0, sizeof(whandle
));
180 whandle
.stride
= xbuf
->pitch
;
181 whandle
.handle
= xbuf
->name
;
182 dri2surf
->textures
[natt
] = dri2dpy
->base
.screen
->resource_from_handle(
183 dri2dpy
->base
.screen
, &templ
, &whandle
);
184 if (dri2surf
->textures
[natt
])
185 valid_mask
|= 1 << natt
;
188 dri2surf
->valid_mask
= valid_mask
;
192 * Get the buffers from the server.
195 dri2_surface_get_buffers(struct native_surface
*nsurf
, uint buffer_mask
)
197 struct dri2_surface
*dri2surf
= dri2_surface(nsurf
);
198 struct dri2_display
*dri2dpy
= dri2surf
->dri2dpy
;
199 unsigned int dri2atts
[NUM_NATIVE_ATTACHMENTS
* 2];
200 int num_ins
, num_outs
, att
;
201 struct x11_drawable_buffer
*xbufs
;
202 uint bpp
= util_format_get_blocksizebits(dri2surf
->color_format
);
203 boolean with_format
= FALSE
; /* never ask for depth/stencil */
205 /* We must get the front on servers which doesn't support with format
206 * due to a silly bug in core dri2. You can't copy to/from a buffer
207 * that you haven't requested and you recive BadValue errors */
208 if (dri2surf
->dri2dpy
->dri_minor
< 1) {
210 buffer_mask
|= (1 << NATIVE_ATTACHMENT_FRONT_LEFT
);
213 /* prepare the attachments */
215 for (att
= 0; att
< NUM_NATIVE_ATTACHMENTS
; att
++) {
216 if (native_attachment_mask_test(buffer_mask
, att
)) {
217 unsigned int dri2att
;
220 case NATIVE_ATTACHMENT_FRONT_LEFT
:
221 dri2att
= DRI2BufferFrontLeft
;
223 case NATIVE_ATTACHMENT_BACK_LEFT
:
224 dri2att
= DRI2BufferBackLeft
;
226 case NATIVE_ATTACHMENT_FRONT_RIGHT
:
227 dri2att
= DRI2BufferFrontRight
;
229 case NATIVE_ATTACHMENT_BACK_RIGHT
:
230 dri2att
= DRI2BufferBackRight
;
238 dri2atts
[num_ins
++] = dri2att
;
240 dri2atts
[num_ins
++] = bpp
;
246 xbufs
= x11_drawable_get_buffers(dri2dpy
->xscr
, dri2surf
->drawable
,
247 &dri2surf
->width
, &dri2surf
->height
,
248 dri2atts
, with_format
, num_ins
, &num_outs
);
250 /* we should be able to do better... */
251 if (xbufs
&& dri2surf
->last_num_xbufs
== num_outs
&&
252 memcmp(dri2surf
->last_xbufs
, xbufs
, sizeof(*xbufs
) * num_outs
) == 0) {
254 dri2surf
->client_stamp
= dri2surf
->server_stamp
;
258 dri2_surface_process_drawable_buffers(&dri2surf
->base
, xbufs
, num_outs
);
260 dri2surf
->server_stamp
++;
261 dri2surf
->client_stamp
= dri2surf
->server_stamp
;
263 if (dri2surf
->last_xbufs
)
264 FREE(dri2surf
->last_xbufs
);
265 dri2surf
->last_xbufs
= xbufs
;
266 dri2surf
->last_num_xbufs
= num_outs
;
270 * Update the buffers of the surface. This is a slow function due to the
271 * round-trip to the server.
274 dri2_surface_update_buffers(struct native_surface
*nsurf
, uint buffer_mask
)
276 struct dri2_surface
*dri2surf
= dri2_surface(nsurf
);
278 dri2_surface_get_buffers(&dri2surf
->base
, buffer_mask
);
280 return ((dri2surf
->valid_mask
& buffer_mask
) == buffer_mask
);
284 * Return TRUE if the surface receives DRI2_InvalidateBuffers events.
286 static INLINE boolean
287 dri2_surface_receive_events(struct native_surface
*nsurf
)
289 struct dri2_surface
*dri2surf
= dri2_surface(nsurf
);
290 return (dri2surf
->dri2dpy
->dri_minor
>= 3);
294 dri2_surface_flush_frontbuffer(struct native_surface
*nsurf
)
296 struct dri2_surface
*dri2surf
= dri2_surface(nsurf
);
297 struct dri2_display
*dri2dpy
= dri2surf
->dri2dpy
;
299 /* copy to real front buffer */
300 if (dri2surf
->have_fake
)
301 x11_drawable_copy_buffers(dri2dpy
->xscr
, dri2surf
->drawable
,
302 0, 0, dri2surf
->width
, dri2surf
->height
,
303 DRI2BufferFakeFrontLeft
, DRI2BufferFrontLeft
);
305 /* force buffers to be updated in next validation call */
306 if (!dri2_surface_receive_events(&dri2surf
->base
)) {
307 dri2surf
->server_stamp
++;
308 dri2dpy
->event_handler
->invalid_surface(&dri2dpy
->base
,
309 &dri2surf
->base
, dri2surf
->server_stamp
);
316 dri2_surface_swap_buffers(struct native_surface
*nsurf
, int num_rects
,
319 struct dri2_surface
*dri2surf
= dri2_surface(nsurf
);
320 struct dri2_display
*dri2dpy
= dri2surf
->dri2dpy
;
322 /* copy to front buffer */
323 if (dri2surf
->have_back
) {
325 x11_drawable_copy_buffers_region(dri2dpy
->xscr
, dri2surf
->drawable
,
327 DRI2BufferBackLeft
, DRI2BufferFrontLeft
);
329 x11_drawable_copy_buffers(dri2dpy
->xscr
, dri2surf
->drawable
,
330 0, 0, dri2surf
->width
, dri2surf
->height
,
331 DRI2BufferBackLeft
, DRI2BufferFrontLeft
);
334 /* and update fake front buffer */
335 if (dri2surf
->have_fake
) {
337 x11_drawable_copy_buffers_region(dri2dpy
->xscr
, dri2surf
->drawable
,
339 DRI2BufferFrontLeft
, DRI2BufferFakeFrontLeft
);
341 x11_drawable_copy_buffers(dri2dpy
->xscr
, dri2surf
->drawable
,
342 0, 0, dri2surf
->width
, dri2surf
->height
,
343 DRI2BufferFrontLeft
, DRI2BufferFakeFrontLeft
);
346 /* force buffers to be updated in next validation call */
347 if (!dri2_surface_receive_events(&dri2surf
->base
)) {
348 dri2surf
->server_stamp
++;
349 dri2dpy
->event_handler
->invalid_surface(&dri2dpy
->base
,
350 &dri2surf
->base
, dri2surf
->server_stamp
);
357 dri2_surface_present(struct native_surface
*nsurf
,
358 const struct native_present_control
*ctrl
)
362 if (ctrl
->swap_interval
)
365 switch (ctrl
->natt
) {
366 case NATIVE_ATTACHMENT_FRONT_LEFT
:
367 ret
= dri2_surface_flush_frontbuffer(nsurf
);
369 case NATIVE_ATTACHMENT_BACK_LEFT
:
370 ret
= dri2_surface_swap_buffers(nsurf
, ctrl
->num_rects
, ctrl
->rects
);
381 dri2_surface_validate(struct native_surface
*nsurf
, uint attachment_mask
,
382 unsigned int *seq_num
, struct pipe_resource
**textures
,
383 int *width
, int *height
)
385 struct dri2_surface
*dri2surf
= dri2_surface(nsurf
);
387 if (dri2surf
->server_stamp
!= dri2surf
->client_stamp
||
388 (dri2surf
->valid_mask
& attachment_mask
) != attachment_mask
) {
389 if (!dri2_surface_update_buffers(&dri2surf
->base
, attachment_mask
))
394 *seq_num
= dri2surf
->client_stamp
;
398 for (att
= 0; att
< NUM_NATIVE_ATTACHMENTS
; att
++) {
399 if (native_attachment_mask_test(attachment_mask
, att
)) {
400 struct pipe_resource
*ptex
= dri2surf
->textures
[att
];
402 textures
[att
] = NULL
;
403 pipe_resource_reference(&textures
[att
], ptex
);
409 *width
= dri2surf
->width
;
411 *height
= dri2surf
->height
;
417 dri2_surface_wait(struct native_surface
*nsurf
)
419 struct dri2_surface
*dri2surf
= dri2_surface(nsurf
);
420 struct dri2_display
*dri2dpy
= dri2surf
->dri2dpy
;
422 if (dri2surf
->have_fake
) {
423 x11_drawable_copy_buffers(dri2dpy
->xscr
, dri2surf
->drawable
,
424 0, 0, dri2surf
->width
, dri2surf
->height
,
425 DRI2BufferFrontLeft
, DRI2BufferFakeFrontLeft
);
430 dri2_surface_destroy(struct native_surface
*nsurf
)
432 struct dri2_surface
*dri2surf
= dri2_surface(nsurf
);
435 if (dri2surf
->last_xbufs
)
436 FREE(dri2surf
->last_xbufs
);
438 for (i
= 0; i
< NUM_NATIVE_ATTACHMENTS
; i
++) {
439 struct pipe_resource
*ptex
= dri2surf
->textures
[i
];
440 pipe_resource_reference(&ptex
, NULL
);
443 if (dri2surf
->drawable
) {
444 x11_drawable_enable_dri2(dri2surf
->dri2dpy
->xscr
,
445 dri2surf
->drawable
, FALSE
);
447 util_hash_table_remove(dri2surf
->dri2dpy
->surfaces
,
448 (void *) dri2surf
->drawable
);
453 static struct dri2_surface
*
454 dri2_display_create_surface(struct native_display
*ndpy
,
456 enum pipe_format color_format
)
458 struct dri2_display
*dri2dpy
= dri2_display(ndpy
);
459 struct dri2_surface
*dri2surf
;
461 dri2surf
= CALLOC_STRUCT(dri2_surface
);
465 dri2surf
->dri2dpy
= dri2dpy
;
466 dri2surf
->drawable
= drawable
;
467 dri2surf
->color_format
= color_format
;
469 dri2surf
->base
.destroy
= dri2_surface_destroy
;
470 dri2surf
->base
.present
= dri2_surface_present
;
471 dri2surf
->base
.validate
= dri2_surface_validate
;
472 dri2surf
->base
.wait
= dri2_surface_wait
;
475 x11_drawable_enable_dri2(dri2dpy
->xscr
, drawable
, TRUE
);
476 /* initialize the geometry */
477 dri2_surface_update_buffers(&dri2surf
->base
, 0x0);
479 util_hash_table_set(dri2surf
->dri2dpy
->surfaces
,
480 (void *) dri2surf
->drawable
, (void *) &dri2surf
->base
);
486 static struct native_surface
*
487 dri2_display_create_window_surface(struct native_display
*ndpy
,
488 EGLNativeWindowType win
,
489 const struct native_config
*nconf
)
491 struct dri2_surface
*dri2surf
;
493 dri2surf
= dri2_display_create_surface(ndpy
,
494 (Drawable
) win
, nconf
->color_format
);
495 return (dri2surf
) ? &dri2surf
->base
: NULL
;
498 static struct native_surface
*
499 dri2_display_create_pixmap_surface(struct native_display
*ndpy
,
500 EGLNativePixmapType pix
,
501 const struct native_config
*nconf
)
503 struct dri2_surface
*dri2surf
;
506 struct dri2_display
*dri2dpy
= dri2_display(ndpy
);
507 uint depth
, nconf_depth
;
510 depth
= x11_drawable_get_depth(dri2dpy
->xscr
, (Drawable
) pix
);
511 for (i
= 0; i
< dri2dpy
->num_configs
; i
++) {
512 nconf_depth
= util_format_get_blocksizebits(
513 dri2dpy
->configs
[i
].base
.color_format
);
514 /* simple depth match for now */
515 if (depth
== nconf_depth
||
516 (depth
== 24 && depth
+ 8 == nconf_depth
)) {
517 nconf
= &dri2dpy
->configs
[i
].base
;
526 dri2surf
= dri2_display_create_surface(ndpy
,
527 (Drawable
) pix
, nconf
->color_format
);
528 return (dri2surf
) ? &dri2surf
->base
: NULL
;
532 choose_color_format(const __GLcontextModes
*mode
, enum pipe_format formats
[32])
536 switch (mode
->rgbBits
) {
538 formats
[count
++] = PIPE_FORMAT_B8G8R8A8_UNORM
;
539 formats
[count
++] = PIPE_FORMAT_A8R8G8B8_UNORM
;
542 formats
[count
++] = PIPE_FORMAT_B8G8R8X8_UNORM
;
543 formats
[count
++] = PIPE_FORMAT_X8R8G8B8_UNORM
;
544 formats
[count
++] = PIPE_FORMAT_B8G8R8A8_UNORM
;
545 formats
[count
++] = PIPE_FORMAT_A8R8G8B8_UNORM
;
548 formats
[count
++] = PIPE_FORMAT_B5G6R5_UNORM
;
558 is_format_supported(struct pipe_screen
*screen
,
559 enum pipe_format fmt
, unsigned sample_count
, boolean is_color
)
561 return screen
->is_format_supported(screen
, fmt
, PIPE_TEXTURE_2D
, sample_count
,
562 (is_color
) ? PIPE_BIND_RENDER_TARGET
:
563 PIPE_BIND_DEPTH_STENCIL
);
567 dri2_display_convert_config(struct native_display
*ndpy
,
568 const __GLcontextModes
*mode
,
569 struct native_config
*nconf
)
571 enum pipe_format formats
[32];
573 int sample_count
= 0;
575 if (!(mode
->renderType
& GLX_RGBA_BIT
) || !mode
->rgbMode
)
578 /* only interested in native renderable configs */
579 if (!mode
->xRenderable
|| !mode
->drawableType
)
582 /* fast/slow configs are probably not relevant */
583 if (mode
->visualRating
== GLX_SLOW_CONFIG
)
586 nconf
->buffer_mask
= 1 << NATIVE_ATTACHMENT_FRONT_LEFT
;
587 if (mode
->doubleBufferMode
)
588 nconf
->buffer_mask
|= 1 << NATIVE_ATTACHMENT_BACK_LEFT
;
589 if (mode
->stereoMode
) {
590 nconf
->buffer_mask
|= 1 << NATIVE_ATTACHMENT_FRONT_RIGHT
;
591 if (mode
->doubleBufferMode
)
592 nconf
->buffer_mask
|= 1 << NATIVE_ATTACHMENT_BACK_RIGHT
;
595 /* choose color format */
596 num_formats
= choose_color_format(mode
, formats
);
597 for (i
= 0; i
< num_formats
; i
++) {
598 if (is_format_supported(ndpy
->screen
, formats
[i
], sample_count
, TRUE
)) {
599 nconf
->color_format
= formats
[i
];
603 if (nconf
->color_format
== PIPE_FORMAT_NONE
)
606 if ((mode
->drawableType
& GLX_WINDOW_BIT
) && mode
->visualID
)
607 nconf
->window_bit
= TRUE
;
608 if (mode
->drawableType
& GLX_PIXMAP_BIT
)
609 nconf
->pixmap_bit
= TRUE
;
611 nconf
->native_visual_id
= mode
->visualID
;
612 switch (mode
->visualType
) {
614 nconf
->native_visual_type
= TrueColor
;
616 case GLX_DIRECT_COLOR
:
617 nconf
->native_visual_type
= DirectColor
;
619 case GLX_PSEUDO_COLOR
:
620 nconf
->native_visual_type
= PseudoColor
;
622 case GLX_STATIC_COLOR
:
623 nconf
->native_visual_type
= StaticColor
;
626 nconf
->native_visual_type
= GrayScale
;
628 case GLX_STATIC_GRAY
:
629 nconf
->native_visual_type
= StaticGray
;
632 nconf
->level
= mode
->level
;
634 if (mode
->transparentPixel
== GLX_TRANSPARENT_RGB
) {
635 nconf
->transparent_rgb
= TRUE
;
636 nconf
->transparent_rgb_values
[0] = mode
->transparentRed
;
637 nconf
->transparent_rgb_values
[1] = mode
->transparentGreen
;
638 nconf
->transparent_rgb_values
[2] = mode
->transparentBlue
;
644 static const struct native_config
**
645 dri2_display_get_configs(struct native_display
*ndpy
, int *num_configs
)
647 struct dri2_display
*dri2dpy
= dri2_display(ndpy
);
648 const struct native_config
**configs
;
652 if (!dri2dpy
->configs
) {
653 const __GLcontextModes
*modes
;
654 int num_modes
, count
;
656 modes
= x11_screen_get_glx_configs(dri2dpy
->xscr
);
659 num_modes
= x11_context_modes_count(modes
);
661 dri2dpy
->configs
= CALLOC(num_modes
, sizeof(*dri2dpy
->configs
));
662 if (!dri2dpy
->configs
)
666 for (i
= 0; i
< num_modes
; i
++) {
667 struct native_config
*nconf
= &dri2dpy
->configs
[count
].base
;
669 if (dri2_display_convert_config(&dri2dpy
->base
, modes
, nconf
)) {
671 /* look for duplicates */
672 for (j
= 0; j
< count
; j
++) {
673 if (memcmp(&dri2dpy
->configs
[j
], nconf
, sizeof(*nconf
)) == 0)
682 dri2dpy
->num_configs
= count
;
685 configs
= MALLOC(dri2dpy
->num_configs
* sizeof(*configs
));
687 for (i
= 0; i
< dri2dpy
->num_configs
; i
++)
688 configs
[i
] = (const struct native_config
*) &dri2dpy
->configs
[i
];
690 *num_configs
= dri2dpy
->num_configs
;
697 dri2_display_get_pixmap_format(struct native_display
*ndpy
,
698 EGLNativePixmapType pix
,
699 enum pipe_format
*format
)
701 struct dri2_display
*dri2dpy
= dri2_display(ndpy
);
702 boolean ret
= EGL_TRUE
;
705 depth
= x11_drawable_get_depth(dri2dpy
->xscr
, (Drawable
) pix
);
709 *format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
712 *format
= PIPE_FORMAT_B5G6R5_UNORM
;
715 *format
= PIPE_FORMAT_NONE
;
724 dri2_display_get_param(struct native_display
*ndpy
,
725 enum native_param_type param
)
730 case NATIVE_PARAM_USE_NATIVE_BUFFER
:
731 /* DRI2GetBuffers uses the native buffers */
734 case NATIVE_PARAM_PRESERVE_BUFFER
:
735 /* DRI2CopyRegion is used */
738 case NATIVE_PARAM_PRESENT_REGION
:
741 case NATIVE_PARAM_MAX_SWAP_INTERVAL
:
751 dri2_display_destroy(struct native_display
*ndpy
)
753 struct dri2_display
*dri2dpy
= dri2_display(ndpy
);
755 if (dri2dpy
->configs
)
756 FREE(dri2dpy
->configs
);
758 if (dri2dpy
->base
.screen
)
759 dri2dpy
->base
.screen
->destroy(dri2dpy
->base
.screen
);
761 if (dri2dpy
->surfaces
)
762 util_hash_table_destroy(dri2dpy
->surfaces
);
765 x11_screen_destroy(dri2dpy
->xscr
);
766 if (dri2dpy
->own_dpy
)
767 XCloseDisplay(dri2dpy
->dpy
);
772 dri2_display_invalidate_buffers(struct x11_screen
*xscr
, Drawable drawable
,
775 struct native_display
*ndpy
= (struct native_display
* ) user_data
;
776 struct dri2_display
*dri2dpy
= dri2_display(ndpy
);
777 struct native_surface
*nsurf
;
778 struct dri2_surface
*dri2surf
;
780 nsurf
= (struct native_surface
*)
781 util_hash_table_get(dri2dpy
->surfaces
, (void *) drawable
);
785 dri2surf
= dri2_surface(nsurf
);
787 dri2surf
->server_stamp
++;
788 dri2dpy
->event_handler
->invalid_surface(&dri2dpy
->base
,
789 &dri2surf
->base
, dri2surf
->server_stamp
);
793 * Initialize DRI2 and pipe screen.
796 dri2_display_init_screen(struct native_display
*ndpy
)
798 struct dri2_display
*dri2dpy
= dri2_display(ndpy
);
801 if (!x11_screen_support(dri2dpy
->xscr
, X11_SCREEN_EXTENSION_DRI2
) ||
802 !x11_screen_support(dri2dpy
->xscr
, X11_SCREEN_EXTENSION_GLX
)) {
803 _eglLog(_EGL_WARNING
, "GLX/DRI2 is not supported");
807 dri2dpy
->dri_driver
= x11_screen_probe_dri2(dri2dpy
->xscr
,
808 &dri2dpy
->dri_major
, &dri2dpy
->dri_minor
);
810 fd
= x11_screen_enable_dri2(dri2dpy
->xscr
,
811 dri2_display_invalidate_buffers
, &dri2dpy
->base
);
815 dri2dpy
->base
.screen
=
816 dri2dpy
->event_handler
->new_drm_screen(&dri2dpy
->base
,
817 dri2dpy
->dri_driver
, fd
);
818 if (!dri2dpy
->base
.screen
) {
819 _eglLog(_EGL_DEBUG
, "failed to create DRM screen");
827 dri2_display_hash_table_hash(void *key
)
829 XID drawable
= pointer_to_uintptr(key
);
830 return (unsigned) drawable
;
834 dri2_display_hash_table_compare(void *key1
, void *key2
)
836 return ((char *) key1
- (char *) key2
);
839 #ifdef HAVE_WAYLAND_BACKEND
842 dri2_display_authenticate(void *user_data
, uint32_t magic
)
844 struct native_display
*ndpy
= user_data
;
845 struct dri2_display
*dri2dpy
= dri2_display(ndpy
);
847 return x11_screen_authenticate(dri2dpy
->xscr
, magic
);
850 static struct wayland_drm_callbacks wl_drm_callbacks
= {
851 dri2_display_authenticate
,
852 egl_g3d_wl_drm_helper_reference_buffer
,
853 egl_g3d_wl_drm_helper_unreference_buffer
857 dri2_display_bind_wayland_display(struct native_display
*ndpy
,
858 struct wl_display
*wl_dpy
)
860 struct dri2_display
*dri2dpy
= dri2_display(ndpy
);
862 if (dri2dpy
->wl_server_drm
)
865 dri2dpy
->wl_server_drm
= wayland_drm_init(wl_dpy
,
866 x11_screen_get_device_name(dri2dpy
->xscr
),
867 &wl_drm_callbacks
, ndpy
);
869 if (!dri2dpy
->wl_server_drm
)
876 dri2_display_unbind_wayland_display(struct native_display
*ndpy
,
877 struct wl_display
*wl_dpy
)
879 struct dri2_display
*dri2dpy
= dri2_display(ndpy
);
881 if (!dri2dpy
->wl_server_drm
)
884 wayland_drm_uninit(dri2dpy
->wl_server_drm
);
885 dri2dpy
->wl_server_drm
= NULL
;
890 static struct native_display_wayland_bufmgr dri2_display_wayland_bufmgr
= {
891 dri2_display_bind_wayland_display
,
892 dri2_display_unbind_wayland_display
,
893 egl_g3d_wl_drm_common_wl_buffer_get_resource
,
894 egl_g3d_wl_drm_common_query_buffer
897 #endif /* HAVE_WAYLAND_BACKEND */
899 struct native_display
*
900 x11_create_dri2_display(Display
*dpy
,
901 const struct native_event_handler
*event_handler
)
903 struct dri2_display
*dri2dpy
;
905 dri2dpy
= CALLOC_STRUCT(dri2_display
);
909 dri2dpy
->event_handler
= event_handler
;
913 dri2dpy
->dpy
= XOpenDisplay(NULL
);
915 dri2_display_destroy(&dri2dpy
->base
);
918 dri2dpy
->own_dpy
= TRUE
;
921 dri2dpy
->xscr_number
= DefaultScreen(dri2dpy
->dpy
);
922 dri2dpy
->xscr
= x11_screen_create(dri2dpy
->dpy
, dri2dpy
->xscr_number
);
923 if (!dri2dpy
->xscr
) {
924 dri2_display_destroy(&dri2dpy
->base
);
928 dri2dpy
->surfaces
= util_hash_table_create(dri2_display_hash_table_hash
,
929 dri2_display_hash_table_compare
);
930 if (!dri2dpy
->surfaces
) {
931 dri2_display_destroy(&dri2dpy
->base
);
935 dri2dpy
->base
.init_screen
= dri2_display_init_screen
;
936 dri2dpy
->base
.destroy
= dri2_display_destroy
;
937 dri2dpy
->base
.get_param
= dri2_display_get_param
;
938 dri2dpy
->base
.get_configs
= dri2_display_get_configs
;
939 dri2dpy
->base
.get_pixmap_format
= dri2_display_get_pixmap_format
;
940 dri2dpy
->base
.copy_to_pixmap
= native_display_copy_to_pixmap
;
941 dri2dpy
->base
.create_window_surface
= dri2_display_create_window_surface
;
942 dri2dpy
->base
.create_pixmap_surface
= dri2_display_create_pixmap_surface
;
943 #ifdef HAVE_WAYLAND_BACKEND
944 dri2dpy
->base
.wayland_bufmgr
= &dri2_display_wayland_bufmgr
;
947 return &dri2dpy
->base
;
950 #else /* GLX_DIRECT_RENDERING */
952 struct native_display
*
953 x11_create_dri2_display(Display
*dpy
,
954 const struct native_event_handler
*event_handler
)
959 #endif /* GLX_DIRECT_RENDERING */