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.
25 #include "util/u_memory.h"
26 #include "util/u_math.h"
27 #include "util/u_format.h"
28 #include "util/u_inlines.h"
29 #include "util/u_hash_table.h"
30 #include "pipe/p_compiler.h"
31 #include "pipe/p_screen.h"
32 #include "pipe/p_context.h"
33 #include "pipe/p_state.h"
34 #include "state_tracker/drm_api.h"
37 #include "native_x11.h"
38 #include "x11_screen.h"
40 enum dri2_surface_type
{
41 DRI2_SURFACE_TYPE_WINDOW
,
42 DRI2_SURFACE_TYPE_PIXMAP
,
43 DRI2_SURFACE_TYPE_PBUFFER
47 struct native_display base
;
51 struct native_event_handler
*event_handler
;
54 struct x11_screen
*xscr
;
56 const char *dri_driver
;
57 int dri_major
, dri_minor
;
59 struct dri2_config
*configs
;
62 struct util_hash_table
*surfaces
;
66 struct native_surface base
;
68 enum dri2_surface_type type
;
69 enum pipe_format color_format
;
70 struct dri2_display
*dri2dpy
;
72 unsigned int server_stamp
;
73 unsigned int client_stamp
;
75 struct pipe_texture
*textures
[NUM_NATIVE_ATTACHMENTS
];
78 boolean have_back
, have_fake
;
80 struct x11_drawable_buffer
*last_xbufs
;
85 struct native_config base
;
88 static INLINE
struct dri2_display
*
89 dri2_display(const struct native_display
*ndpy
)
91 return (struct dri2_display
*) ndpy
;
94 static INLINE
struct dri2_surface
*
95 dri2_surface(const struct native_surface
*nsurf
)
97 return (struct dri2_surface
*) nsurf
;
100 static INLINE
struct dri2_config
*
101 dri2_config(const struct native_config
*nconf
)
103 return (struct dri2_config
*) nconf
;
107 * Process the buffers returned by the server.
110 dri2_surface_process_drawable_buffers(struct native_surface
*nsurf
,
111 struct x11_drawable_buffer
*xbufs
,
114 struct dri2_surface
*dri2surf
= dri2_surface(nsurf
);
115 struct dri2_display
*dri2dpy
= dri2surf
->dri2dpy
;
116 struct pipe_texture templ
;
120 /* free the old textures */
121 for (i
= 0; i
< NUM_NATIVE_ATTACHMENTS
; i
++)
122 pipe_texture_reference(&dri2surf
->textures
[i
], NULL
);
123 dri2surf
->valid_mask
= 0x0;
125 dri2surf
->have_back
= FALSE
;
126 dri2surf
->have_fake
= FALSE
;
131 memset(&templ
, 0, sizeof(templ
));
132 templ
.target
= PIPE_TEXTURE_2D
;
133 templ
.last_level
= 0;
134 templ
.width0
= dri2surf
->width
;
135 templ
.height0
= dri2surf
->height
;
137 templ
.format
= dri2surf
->color_format
;
138 templ
.tex_usage
= PIPE_TEXTURE_USAGE_RENDER_TARGET
;
141 for (i
= 0; i
< num_xbufs
; i
++) {
142 struct x11_drawable_buffer
*xbuf
= &xbufs
[i
];
144 enum native_attachment natt
;
146 switch (xbuf
->attachment
) {
147 case DRI2BufferFrontLeft
:
148 natt
= NATIVE_ATTACHMENT_FRONT_LEFT
;
149 desc
= "DRI2 Front Buffer";
151 case DRI2BufferFakeFrontLeft
:
152 natt
= NATIVE_ATTACHMENT_FRONT_LEFT
;
153 desc
= "DRI2 Fake Front Buffer";
154 dri2surf
->have_fake
= TRUE
;
156 case DRI2BufferBackLeft
:
157 natt
= NATIVE_ATTACHMENT_BACK_LEFT
;
158 desc
= "DRI2 Back Buffer";
159 dri2surf
->have_back
= TRUE
;
166 if (!desc
|| dri2surf
->textures
[natt
]) {
168 _eglLog(_EGL_WARNING
, "unknown buffer %d", xbuf
->attachment
);
170 _eglLog(_EGL_WARNING
, "both real and fake front buffers are listed");
174 dri2surf
->textures
[natt
] =
175 dri2dpy
->api
->texture_from_shared_handle(dri2dpy
->api
,
176 dri2dpy
->base
.screen
, &templ
, desc
, xbuf
->pitch
, xbuf
->name
);
177 if (dri2surf
->textures
[natt
])
178 valid_mask
|= 1 << natt
;
181 dri2surf
->valid_mask
= valid_mask
;
185 * Get the buffers from the server.
188 dri2_surface_get_buffers(struct native_surface
*nsurf
, uint buffer_mask
)
190 struct dri2_surface
*dri2surf
= dri2_surface(nsurf
);
191 struct dri2_display
*dri2dpy
= dri2surf
->dri2dpy
;
192 unsigned int dri2atts
[NUM_NATIVE_ATTACHMENTS
];
193 int num_ins
, num_outs
, att
;
194 struct x11_drawable_buffer
*xbufs
;
196 /* prepare the attachments */
198 for (att
= 0; att
< NUM_NATIVE_ATTACHMENTS
; att
++) {
199 if (native_attachment_mask_test(buffer_mask
, att
)) {
200 unsigned int dri2att
;
203 case NATIVE_ATTACHMENT_FRONT_LEFT
:
204 dri2att
= DRI2BufferFrontLeft
;
206 case NATIVE_ATTACHMENT_BACK_LEFT
:
207 dri2att
= DRI2BufferBackLeft
;
209 case NATIVE_ATTACHMENT_FRONT_RIGHT
:
210 dri2att
= DRI2BufferFrontRight
;
212 case NATIVE_ATTACHMENT_BACK_RIGHT
:
213 dri2att
= DRI2BufferBackRight
;
221 dri2atts
[num_ins
] = dri2att
;
226 xbufs
= x11_drawable_get_buffers(dri2dpy
->xscr
, dri2surf
->drawable
,
227 &dri2surf
->width
, &dri2surf
->height
,
228 dri2atts
, FALSE
, num_ins
, &num_outs
);
230 /* we should be able to do better... */
231 if (xbufs
&& dri2surf
->last_num_xbufs
== num_outs
&&
232 memcmp(dri2surf
->last_xbufs
, xbufs
, sizeof(*xbufs
) * num_outs
) == 0) {
234 dri2surf
->client_stamp
= dri2surf
->server_stamp
;
238 dri2_surface_process_drawable_buffers(&dri2surf
->base
, xbufs
, num_outs
);
240 dri2surf
->server_stamp
++;
241 dri2surf
->client_stamp
= dri2surf
->server_stamp
;
243 if (dri2surf
->last_xbufs
)
244 free(dri2surf
->last_xbufs
);
245 dri2surf
->last_xbufs
= xbufs
;
246 dri2surf
->last_num_xbufs
= num_outs
;
250 * Update the buffers of the surface. This is a slow function due to the
251 * round-trip to the server.
254 dri2_surface_update_buffers(struct native_surface
*nsurf
, uint buffer_mask
)
256 struct dri2_surface
*dri2surf
= dri2_surface(nsurf
);
257 struct dri2_display
*dri2dpy
= dri2surf
->dri2dpy
;
259 /* create textures for pbuffer */
260 if (dri2surf
->type
== DRI2_SURFACE_TYPE_PBUFFER
) {
261 struct pipe_screen
*screen
= dri2dpy
->base
.screen
;
262 struct pipe_texture templ
;
263 uint new_valid
= 0x0;
266 buffer_mask
&= ~dri2surf
->valid_mask
;
270 memset(&templ
, 0, sizeof(templ
));
271 templ
.target
= PIPE_TEXTURE_2D
;
272 templ
.last_level
= 0;
273 templ
.width0
= dri2surf
->width
;
274 templ
.height0
= dri2surf
->height
;
276 templ
.format
= dri2surf
->color_format
;
277 templ
.tex_usage
= PIPE_TEXTURE_USAGE_RENDER_TARGET
;
279 for (att
= 0; att
< NUM_NATIVE_ATTACHMENTS
; att
++) {
280 if (native_attachment_mask_test(buffer_mask
, att
)) {
281 assert(!dri2surf
->textures
[att
]);
283 dri2surf
->textures
[att
] = screen
->texture_create(screen
, &templ
);
284 if (!dri2surf
->textures
[att
])
287 new_valid
|= 1 << att
;
288 if (new_valid
== buffer_mask
)
292 dri2surf
->valid_mask
|= new_valid
;
293 /* no need to update the stamps */
296 dri2_surface_get_buffers(&dri2surf
->base
, buffer_mask
);
299 return ((dri2surf
->valid_mask
& buffer_mask
) == buffer_mask
);
303 * Return TRUE if the surface receives DRI2_InvalidateBuffers events.
305 static INLINE boolean
306 dri2_surface_receive_events(struct native_surface
*nsurf
)
308 struct dri2_surface
*dri2surf
= dri2_surface(nsurf
);
309 return (dri2surf
->dri2dpy
->dri_minor
>= 3);
313 dri2_surface_flush_frontbuffer(struct native_surface
*nsurf
)
315 struct dri2_surface
*dri2surf
= dri2_surface(nsurf
);
316 struct dri2_display
*dri2dpy
= dri2surf
->dri2dpy
;
318 /* pbuffer is private */
319 if (dri2surf
->type
== DRI2_SURFACE_TYPE_PBUFFER
)
322 /* copy to real front buffer */
323 if (dri2surf
->have_fake
)
324 x11_drawable_copy_buffers(dri2dpy
->xscr
, dri2surf
->drawable
,
325 0, 0, dri2surf
->width
, dri2surf
->height
,
326 DRI2BufferFakeFrontLeft
, DRI2BufferFrontLeft
);
328 /* force buffers to be updated in next validation call */
329 if (!dri2_surface_receive_events(&dri2surf
->base
)) {
330 dri2surf
->server_stamp
++;
331 dri2dpy
->event_handler
->invalid_surface(&dri2dpy
->base
,
332 &dri2surf
->base
, dri2surf
->server_stamp
);
339 dri2_surface_swap_buffers(struct native_surface
*nsurf
)
341 struct dri2_surface
*dri2surf
= dri2_surface(nsurf
);
342 struct dri2_display
*dri2dpy
= dri2surf
->dri2dpy
;
344 /* pbuffer is private */
345 if (dri2surf
->type
== DRI2_SURFACE_TYPE_PBUFFER
)
348 /* copy to front buffer */
349 if (dri2surf
->have_back
)
350 x11_drawable_copy_buffers(dri2dpy
->xscr
, dri2surf
->drawable
,
351 0, 0, dri2surf
->width
, dri2surf
->height
,
352 DRI2BufferBackLeft
, DRI2BufferFrontLeft
);
354 /* and update fake front buffer */
355 if (dri2surf
->have_fake
)
356 x11_drawable_copy_buffers(dri2dpy
->xscr
, dri2surf
->drawable
,
357 0, 0, dri2surf
->width
, dri2surf
->height
,
358 DRI2BufferFrontLeft
, DRI2BufferFakeFrontLeft
);
360 /* force buffers to be updated in next validation call */
361 if (!dri2_surface_receive_events(&dri2surf
->base
)) {
362 dri2surf
->server_stamp
++;
363 dri2dpy
->event_handler
->invalid_surface(&dri2dpy
->base
,
364 &dri2surf
->base
, dri2surf
->server_stamp
);
371 dri2_surface_validate(struct native_surface
*nsurf
, uint attachment_mask
,
372 unsigned int *seq_num
, struct pipe_texture
**textures
,
373 int *width
, int *height
)
375 struct dri2_surface
*dri2surf
= dri2_surface(nsurf
);
377 if (dri2surf
->server_stamp
!= dri2surf
->client_stamp
||
378 (dri2surf
->valid_mask
& attachment_mask
) != attachment_mask
) {
379 if (!dri2_surface_update_buffers(&dri2surf
->base
, attachment_mask
))
384 *seq_num
= dri2surf
->client_stamp
;
388 for (att
= 0; att
< NUM_NATIVE_ATTACHMENTS
; att
++) {
389 if (native_attachment_mask_test(attachment_mask
, att
)) {
390 struct pipe_texture
*ptex
= dri2surf
->textures
[att
];
392 textures
[att
] = NULL
;
393 pipe_texture_reference(&textures
[att
], ptex
);
399 *width
= dri2surf
->width
;
401 *height
= dri2surf
->height
;
407 dri2_surface_wait(struct native_surface
*nsurf
)
409 struct dri2_surface
*dri2surf
= dri2_surface(nsurf
);
410 struct dri2_display
*dri2dpy
= dri2surf
->dri2dpy
;
412 if (dri2surf
->have_fake
) {
413 x11_drawable_copy_buffers(dri2dpy
->xscr
, dri2surf
->drawable
,
414 0, 0, dri2surf
->width
, dri2surf
->height
,
415 DRI2BufferFrontLeft
, DRI2BufferFakeFrontLeft
);
420 dri2_surface_destroy(struct native_surface
*nsurf
)
422 struct dri2_surface
*dri2surf
= dri2_surface(nsurf
);
425 if (dri2surf
->last_xbufs
)
426 free(dri2surf
->last_xbufs
);
428 for (i
= 0; i
< NUM_NATIVE_ATTACHMENTS
; i
++) {
429 struct pipe_texture
*ptex
= dri2surf
->textures
[i
];
430 pipe_texture_reference(&ptex
, NULL
);
433 if (dri2surf
->drawable
) {
434 x11_drawable_enable_dri2(dri2surf
->dri2dpy
->xscr
,
435 dri2surf
->drawable
, FALSE
);
437 util_hash_table_remove(dri2surf
->dri2dpy
->surfaces
,
438 (void *) dri2surf
->drawable
);
443 static struct dri2_surface
*
444 dri2_display_create_surface(struct native_display
*ndpy
,
445 enum dri2_surface_type type
,
447 const struct native_config
*nconf
)
449 struct dri2_display
*dri2dpy
= dri2_display(ndpy
);
450 struct dri2_config
*dri2conf
= dri2_config(nconf
);
451 struct dri2_surface
*dri2surf
;
453 dri2surf
= CALLOC_STRUCT(dri2_surface
);
457 dri2surf
->dri2dpy
= dri2dpy
;
458 dri2surf
->type
= type
;
459 dri2surf
->drawable
= drawable
;
460 dri2surf
->color_format
= dri2conf
->base
.color_format
;
462 dri2surf
->base
.destroy
= dri2_surface_destroy
;
463 dri2surf
->base
.swap_buffers
= dri2_surface_swap_buffers
;
464 dri2surf
->base
.flush_frontbuffer
= dri2_surface_flush_frontbuffer
;
465 dri2surf
->base
.validate
= dri2_surface_validate
;
466 dri2surf
->base
.wait
= dri2_surface_wait
;
469 x11_drawable_enable_dri2(dri2dpy
->xscr
, drawable
, TRUE
);
470 /* initialize the geometry */
471 dri2_surface_update_buffers(&dri2surf
->base
, 0x0);
473 util_hash_table_set(dri2surf
->dri2dpy
->surfaces
,
474 (void *) dri2surf
->drawable
, (void *) &dri2surf
->base
);
480 static struct native_surface
*
481 dri2_display_create_window_surface(struct native_display
*ndpy
,
482 EGLNativeWindowType win
,
483 const struct native_config
*nconf
)
485 struct dri2_surface
*dri2surf
;
487 dri2surf
= dri2_display_create_surface(ndpy
, DRI2_SURFACE_TYPE_WINDOW
,
488 (Drawable
) win
, nconf
);
489 return (dri2surf
) ? &dri2surf
->base
: NULL
;
492 static struct native_surface
*
493 dri2_display_create_pixmap_surface(struct native_display
*ndpy
,
494 EGLNativePixmapType pix
,
495 const struct native_config
*nconf
)
497 struct dri2_surface
*dri2surf
;
499 dri2surf
= dri2_display_create_surface(ndpy
, DRI2_SURFACE_TYPE_PIXMAP
,
500 (Drawable
) pix
, nconf
);
501 return (dri2surf
) ? &dri2surf
->base
: NULL
;
504 static struct native_surface
*
505 dri2_display_create_pbuffer_surface(struct native_display
*ndpy
,
506 const struct native_config
*nconf
,
507 uint width
, uint height
)
509 struct dri2_surface
*dri2surf
;
511 dri2surf
= dri2_display_create_surface(ndpy
, DRI2_SURFACE_TYPE_PBUFFER
,
512 (Drawable
) None
, nconf
);
514 dri2surf
->width
= width
;
515 dri2surf
->height
= height
;
517 return (dri2surf
) ? &dri2surf
->base
: NULL
;
521 choose_color_format(const __GLcontextModes
*mode
, enum pipe_format formats
[32])
525 switch (mode
->rgbBits
) {
527 formats
[count
++] = PIPE_FORMAT_B8G8R8A8_UNORM
;
528 formats
[count
++] = PIPE_FORMAT_A8R8G8B8_UNORM
;
531 formats
[count
++] = PIPE_FORMAT_B8G8R8X8_UNORM
;
532 formats
[count
++] = PIPE_FORMAT_X8R8G8B8_UNORM
;
533 formats
[count
++] = PIPE_FORMAT_B8G8R8A8_UNORM
;
534 formats
[count
++] = PIPE_FORMAT_A8R8G8B8_UNORM
;
537 formats
[count
++] = PIPE_FORMAT_B5G6R5_UNORM
;
547 choose_depth_stencil_format(const __GLcontextModes
*mode
,
548 enum pipe_format formats
[32])
552 switch (mode
->depthBits
) {
554 formats
[count
++] = PIPE_FORMAT_Z32_UNORM
;
557 if (mode
->stencilBits
) {
558 formats
[count
++] = PIPE_FORMAT_Z24S8_UNORM
;
559 formats
[count
++] = PIPE_FORMAT_S8Z24_UNORM
;
562 formats
[count
++] = PIPE_FORMAT_Z24X8_UNORM
;
563 formats
[count
++] = PIPE_FORMAT_X8Z24_UNORM
;
567 formats
[count
++] = PIPE_FORMAT_Z16_UNORM
;
577 is_format_supported(struct pipe_screen
*screen
,
578 enum pipe_format fmt
, boolean is_color
)
580 return screen
->is_format_supported(screen
, fmt
, PIPE_TEXTURE_2D
,
581 (is_color
) ? PIPE_TEXTURE_USAGE_RENDER_TARGET
:
582 PIPE_TEXTURE_USAGE_DEPTH_STENCIL
, 0);
586 dri2_display_convert_config(struct native_display
*ndpy
,
587 const __GLcontextModes
*mode
,
588 struct native_config
*nconf
)
590 enum pipe_format formats
[32];
593 if (!(mode
->renderType
& GLX_RGBA_BIT
) || !mode
->rgbMode
)
596 /* skip single-buffered configs */
597 if (!mode
->doubleBufferMode
)
601 nconf
->mode
.renderType
= GLX_RGBA_BIT
;
602 nconf
->mode
.rgbMode
= TRUE
;
603 /* pbuffer is allocated locally and is always supported */
604 nconf
->mode
.drawableType
|= GLX_PBUFFER_BIT
;
605 /* the swap method is always copy */
606 nconf
->mode
.swapMethod
= GLX_SWAP_COPY_OML
;
609 nconf
->mode
.rgbBits
=
610 nconf
->mode
.redBits
+ nconf
->mode
.greenBits
+
611 nconf
->mode
.blueBits
+ nconf
->mode
.alphaBits
;
612 if (!(nconf
->mode
.drawableType
& GLX_WINDOW_BIT
)) {
613 nconf
->mode
.visualID
= 0;
614 nconf
->mode
.visualType
= GLX_NONE
;
616 if (!(nconf
->mode
.drawableType
& GLX_PBUFFER_BIT
)) {
617 nconf
->mode
.bindToTextureRgb
= FALSE
;
618 nconf
->mode
.bindToTextureRgba
= FALSE
;
621 nconf
->color_format
= PIPE_FORMAT_NONE
;
622 nconf
->depth_format
= PIPE_FORMAT_NONE
;
623 nconf
->stencil_format
= PIPE_FORMAT_NONE
;
625 /* choose color format */
626 num_formats
= choose_color_format(mode
, formats
);
627 for (i
= 0; i
< num_formats
; i
++) {
628 if (is_format_supported(ndpy
->screen
, formats
[i
], TRUE
)) {
629 nconf
->color_format
= formats
[i
];
633 if (nconf
->color_format
== PIPE_FORMAT_NONE
)
636 /* choose depth/stencil format */
637 num_formats
= choose_depth_stencil_format(mode
, formats
);
638 for (i
= 0; i
< num_formats
; i
++) {
639 if (is_format_supported(ndpy
->screen
, formats
[i
], FALSE
)) {
640 nconf
->depth_format
= formats
[i
];
641 nconf
->stencil_format
= formats
[i
];
645 if ((nconf
->mode
.depthBits
&& nconf
->depth_format
== PIPE_FORMAT_NONE
) ||
646 (nconf
->mode
.stencilBits
&& nconf
->stencil_format
== PIPE_FORMAT_NONE
))
652 static const struct native_config
**
653 dri2_display_get_configs(struct native_display
*ndpy
, int *num_configs
)
655 struct dri2_display
*dri2dpy
= dri2_display(ndpy
);
656 const struct native_config
**configs
;
660 if (!dri2dpy
->configs
) {
661 const __GLcontextModes
*modes
;
662 int num_modes
, count
;
664 modes
= x11_screen_get_glx_configs(dri2dpy
->xscr
);
667 num_modes
= x11_context_modes_count(modes
);
669 dri2dpy
->configs
= calloc(num_modes
, sizeof(*dri2dpy
->configs
));
670 if (!dri2dpy
->configs
)
674 for (i
= 0; i
< num_modes
; i
++) {
675 struct native_config
*nconf
= &dri2dpy
->configs
[count
].base
;
676 if (dri2_display_convert_config(&dri2dpy
->base
, modes
, nconf
))
681 dri2dpy
->num_configs
= count
;
684 configs
= malloc(dri2dpy
->num_configs
* sizeof(*configs
));
686 for (i
= 0; i
< dri2dpy
->num_configs
; i
++)
687 configs
[i
] = (const struct native_config
*) &dri2dpy
->configs
[i
];
689 *num_configs
= dri2dpy
->num_configs
;
696 dri2_display_is_pixmap_supported(struct native_display
*ndpy
,
697 EGLNativePixmapType pix
,
698 const struct native_config
*nconf
)
700 struct dri2_display
*dri2dpy
= dri2_display(ndpy
);
701 uint depth
, nconf_depth
;
703 depth
= x11_drawable_get_depth(dri2dpy
->xscr
, (Drawable
) pix
);
704 nconf_depth
= util_format_get_blocksizebits(nconf
->color_format
);
706 /* simple depth match for now */
707 return (depth
== nconf_depth
|| (depth
== 24 && depth
+ 8 == nconf_depth
));
711 dri2_display_get_param(struct native_display
*ndpy
,
712 enum native_param_type param
)
717 case NATIVE_PARAM_USE_NATIVE_BUFFER
:
718 /* DRI2GetBuffers use the native buffers */
730 dri2_display_destroy(struct native_display
*ndpy
)
732 struct dri2_display
*dri2dpy
= dri2_display(ndpy
);
734 if (dri2dpy
->configs
)
735 free(dri2dpy
->configs
);
737 if (dri2dpy
->base
.screen
)
738 dri2dpy
->base
.screen
->destroy(dri2dpy
->base
.screen
);
740 if (dri2dpy
->surfaces
)
741 util_hash_table_destroy(dri2dpy
->surfaces
);
744 x11_screen_destroy(dri2dpy
->xscr
);
745 if (dri2dpy
->own_dpy
)
746 XCloseDisplay(dri2dpy
->dpy
);
747 if (dri2dpy
->api
&& dri2dpy
->api
->destroy
)
748 dri2dpy
->api
->destroy(dri2dpy
->api
);
753 dri2_display_invalidate_buffers(struct x11_screen
*xscr
, Drawable drawable
,
756 struct native_display
*ndpy
= (struct native_display
* ) user_data
;
757 struct dri2_display
*dri2dpy
= dri2_display(ndpy
);
758 struct native_surface
*nsurf
;
759 struct dri2_surface
*dri2surf
;
761 nsurf
= (struct native_surface
*)
762 util_hash_table_get(dri2dpy
->surfaces
, (void *) drawable
);
766 dri2surf
= dri2_surface(nsurf
);
768 dri2surf
->server_stamp
++;
769 dri2dpy
->event_handler
->invalid_surface(&dri2dpy
->base
,
770 &dri2surf
->base
, dri2surf
->server_stamp
);
774 * Initialize DRI2 and pipe screen.
777 dri2_display_init_screen(struct native_display
*ndpy
)
779 struct dri2_display
*dri2dpy
= dri2_display(ndpy
);
780 const char *driver
= dri2dpy
->api
->name
;
781 struct drm_create_screen_arg arg
;
784 if (!x11_screen_support(dri2dpy
->xscr
, X11_SCREEN_EXTENSION_DRI2
) ||
785 !x11_screen_support(dri2dpy
->xscr
, X11_SCREEN_EXTENSION_GLX
)) {
786 _eglLog(_EGL_WARNING
, "GLX/DRI2 is not supported");
790 dri2dpy
->dri_driver
= x11_screen_probe_dri2(dri2dpy
->xscr
,
791 &dri2dpy
->dri_major
, &dri2dpy
->dri_minor
);
792 if (!dri2dpy
->dri_driver
|| !driver
||
793 strcmp(dri2dpy
->dri_driver
, driver
) != 0) {
794 _eglLog(_EGL_WARNING
, "Driver mismatch: %s != %s",
795 dri2dpy
->dri_driver
, dri2dpy
->api
->name
);
799 fd
= x11_screen_enable_dri2(dri2dpy
->xscr
,
800 dri2_display_invalidate_buffers
, &dri2dpy
->base
);
804 memset(&arg
, 0, sizeof(arg
));
805 arg
.mode
= DRM_CREATE_NORMAL
;
806 dri2dpy
->base
.screen
= dri2dpy
->api
->create_screen(dri2dpy
->api
, fd
, &arg
);
807 if (!dri2dpy
->base
.screen
) {
808 _eglLog(_EGL_WARNING
, "failed to create DRM screen");
816 dri2_display_hash_table_hash(void *key
)
818 XID drawable
= pointer_to_uintptr(key
);
819 return (unsigned) drawable
;
823 dri2_display_hash_table_compare(void *key1
, void *key2
)
825 return (key1
- key2
);
828 struct native_display
*
829 x11_create_dri2_display(EGLNativeDisplayType dpy
,
830 struct native_event_handler
*event_handler
,
833 struct dri2_display
*dri2dpy
;
835 dri2dpy
= CALLOC_STRUCT(dri2_display
);
839 dri2dpy
->event_handler
= event_handler
;
844 dri2dpy
->dpy
= XOpenDisplay(NULL
);
846 dri2_display_destroy(&dri2dpy
->base
);
849 dri2dpy
->own_dpy
= TRUE
;
852 dri2dpy
->xscr_number
= DefaultScreen(dri2dpy
->dpy
);
853 dri2dpy
->xscr
= x11_screen_create(dri2dpy
->dpy
, dri2dpy
->xscr_number
);
854 if (!dri2dpy
->xscr
) {
855 dri2_display_destroy(&dri2dpy
->base
);
859 if (!dri2_display_init_screen(&dri2dpy
->base
)) {
860 dri2_display_destroy(&dri2dpy
->base
);
864 dri2dpy
->surfaces
= util_hash_table_create(dri2_display_hash_table_hash
,
865 dri2_display_hash_table_compare
);
866 if (!dri2dpy
->surfaces
) {
867 dri2_display_destroy(&dri2dpy
->base
);
871 dri2dpy
->base
.destroy
= dri2_display_destroy
;
872 dri2dpy
->base
.get_param
= dri2_display_get_param
;
873 dri2dpy
->base
.get_configs
= dri2_display_get_configs
;
874 dri2dpy
->base
.is_pixmap_supported
= dri2_display_is_pixmap_supported
;
875 dri2dpy
->base
.create_window_surface
= dri2_display_create_window_surface
;
876 dri2dpy
->base
.create_pixmap_surface
= dri2_display_create_pixmap_surface
;
877 dri2dpy
->base
.create_pbuffer_surface
= dri2_display_create_pbuffer_surface
;
879 return &dri2dpy
->base
;