Merge branch 'xa_branch'
[mesa.git] / src / gallium / state_trackers / egl / x11 / native_dri2.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.8
4 *
5 * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
6 *
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:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
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.
24 */
25
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"
36 #include "egllog.h"
37
38 #include "native_x11.h"
39 #include "x11_screen.h"
40
41 #include "common/native_helper.h"
42 #ifdef HAVE_WAYLAND_BACKEND
43 #include "common/native_wayland_drm_bufmgr_helper.h"
44 #endif
45
46 #ifdef GLX_DIRECT_RENDERING
47
48 struct dri2_display {
49 struct native_display base;
50 Display *dpy;
51 boolean own_dpy;
52
53 const struct native_event_handler *event_handler;
54
55 struct x11_screen *xscr;
56 int xscr_number;
57 const char *dri_driver;
58 int dri_major, dri_minor;
59
60 struct dri2_config *configs;
61 int num_configs;
62
63 struct util_hash_table *surfaces;
64 #ifdef HAVE_WAYLAND_BACKEND
65 struct wl_drm *wl_server_drm; /* for EGL_WL_bind_wayland_display */
66 #endif
67 };
68
69 struct dri2_surface {
70 struct native_surface base;
71 Drawable drawable;
72 enum pipe_format color_format;
73 struct dri2_display *dri2dpy;
74
75 unsigned int server_stamp;
76 unsigned int client_stamp;
77 int width, height;
78 struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS];
79 uint valid_mask;
80
81 boolean have_back, have_fake;
82
83 struct x11_drawable_buffer *last_xbufs;
84 int last_num_xbufs;
85 };
86
87 struct dri2_config {
88 struct native_config base;
89 };
90
91 static INLINE struct dri2_display *
92 dri2_display(const struct native_display *ndpy)
93 {
94 return (struct dri2_display *) ndpy;
95 }
96
97 static INLINE struct dri2_surface *
98 dri2_surface(const struct native_surface *nsurf)
99 {
100 return (struct dri2_surface *) nsurf;
101 }
102
103 static INLINE struct dri2_config *
104 dri2_config(const struct native_config *nconf)
105 {
106 return (struct dri2_config *) nconf;
107 }
108
109 /**
110 * Process the buffers returned by the server.
111 */
112 static void
113 dri2_surface_process_drawable_buffers(struct native_surface *nsurf,
114 struct x11_drawable_buffer *xbufs,
115 int num_xbufs)
116 {
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;
121 uint valid_mask;
122 int i;
123
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;
128
129 dri2surf->have_back = FALSE;
130 dri2surf->have_fake = FALSE;
131
132 if (!xbufs)
133 return;
134
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;
140 templ.depth0 = 1;
141 templ.array_size = 1;
142 templ.format = dri2surf->color_format;
143 templ.bind = PIPE_BIND_RENDER_TARGET;
144
145 valid_mask = 0x0;
146 for (i = 0; i < num_xbufs; i++) {
147 struct x11_drawable_buffer *xbuf = &xbufs[i];
148 const char *desc;
149 enum native_attachment natt;
150
151 switch (xbuf->attachment) {
152 case DRI2BufferFrontLeft:
153 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
154 desc = "DRI2 Front Buffer";
155 break;
156 case DRI2BufferFakeFrontLeft:
157 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
158 desc = "DRI2 Fake Front Buffer";
159 dri2surf->have_fake = TRUE;
160 break;
161 case DRI2BufferBackLeft:
162 natt = NATIVE_ATTACHMENT_BACK_LEFT;
163 desc = "DRI2 Back Buffer";
164 dri2surf->have_back = TRUE;
165 break;
166 default:
167 desc = NULL;
168 break;
169 }
170
171 if (!desc || dri2surf->textures[natt]) {
172 if (!desc)
173 _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment);
174 else
175 _eglLog(_EGL_WARNING, "both real and fake front buffers are listed");
176 continue;
177 }
178
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;
186 }
187
188 dri2surf->valid_mask = valid_mask;
189 }
190
191 /**
192 * Get the buffers from the server.
193 */
194 static void
195 dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask)
196 {
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 */
204
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) {
209 with_format = FALSE;
210 buffer_mask |= (1 << NATIVE_ATTACHMENT_FRONT_LEFT);
211 }
212
213 /* prepare the attachments */
214 num_ins = 0;
215 for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
216 if (native_attachment_mask_test(buffer_mask, att)) {
217 unsigned int dri2att;
218
219 switch (att) {
220 case NATIVE_ATTACHMENT_FRONT_LEFT:
221 dri2att = DRI2BufferFrontLeft;
222 break;
223 case NATIVE_ATTACHMENT_BACK_LEFT:
224 dri2att = DRI2BufferBackLeft;
225 break;
226 case NATIVE_ATTACHMENT_FRONT_RIGHT:
227 dri2att = DRI2BufferFrontRight;
228 break;
229 case NATIVE_ATTACHMENT_BACK_RIGHT:
230 dri2att = DRI2BufferBackRight;
231 break;
232 default:
233 assert(0);
234 dri2att = 0;
235 break;
236 }
237
238 dri2atts[num_ins++] = dri2att;
239 if (with_format)
240 dri2atts[num_ins++] = bpp;
241 }
242 }
243 if (with_format)
244 num_ins /= 2;
245
246 xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable,
247 &dri2surf->width, &dri2surf->height,
248 dri2atts, with_format, num_ins, &num_outs);
249
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) {
253 FREE(xbufs);
254 dri2surf->client_stamp = dri2surf->server_stamp;
255 return;
256 }
257
258 dri2_surface_process_drawable_buffers(&dri2surf->base, xbufs, num_outs);
259
260 dri2surf->server_stamp++;
261 dri2surf->client_stamp = dri2surf->server_stamp;
262
263 if (dri2surf->last_xbufs)
264 FREE(dri2surf->last_xbufs);
265 dri2surf->last_xbufs = xbufs;
266 dri2surf->last_num_xbufs = num_outs;
267 }
268
269 /**
270 * Update the buffers of the surface. This is a slow function due to the
271 * round-trip to the server.
272 */
273 static boolean
274 dri2_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask)
275 {
276 struct dri2_surface *dri2surf = dri2_surface(nsurf);
277
278 dri2_surface_get_buffers(&dri2surf->base, buffer_mask);
279
280 return ((dri2surf->valid_mask & buffer_mask) == buffer_mask);
281 }
282
283 /**
284 * Return TRUE if the surface receives DRI2_InvalidateBuffers events.
285 */
286 static INLINE boolean
287 dri2_surface_receive_events(struct native_surface *nsurf)
288 {
289 struct dri2_surface *dri2surf = dri2_surface(nsurf);
290 return (dri2surf->dri2dpy->dri_minor >= 3);
291 }
292
293 static boolean
294 dri2_surface_flush_frontbuffer(struct native_surface *nsurf)
295 {
296 struct dri2_surface *dri2surf = dri2_surface(nsurf);
297 struct dri2_display *dri2dpy = dri2surf->dri2dpy;
298
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);
304
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);
310 }
311
312 return TRUE;
313 }
314
315 static boolean
316 dri2_surface_swap_buffers(struct native_surface *nsurf)
317 {
318 struct dri2_surface *dri2surf = dri2_surface(nsurf);
319 struct dri2_display *dri2dpy = dri2surf->dri2dpy;
320
321 /* copy to front buffer */
322 if (dri2surf->have_back)
323 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
324 0, 0, dri2surf->width, dri2surf->height,
325 DRI2BufferBackLeft, DRI2BufferFrontLeft);
326
327 /* and update fake front buffer */
328 if (dri2surf->have_fake)
329 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
330 0, 0, dri2surf->width, dri2surf->height,
331 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
332
333 /* force buffers to be updated in next validation call */
334 if (!dri2_surface_receive_events(&dri2surf->base)) {
335 dri2surf->server_stamp++;
336 dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
337 &dri2surf->base, dri2surf->server_stamp);
338 }
339
340 return TRUE;
341 }
342
343 static boolean
344 dri2_surface_present(struct native_surface *nsurf,
345 enum native_attachment natt,
346 boolean preserve,
347 uint swap_interval)
348 {
349 boolean ret;
350
351 if (swap_interval)
352 return FALSE;
353
354 switch (natt) {
355 case NATIVE_ATTACHMENT_FRONT_LEFT:
356 ret = dri2_surface_flush_frontbuffer(nsurf);
357 break;
358 case NATIVE_ATTACHMENT_BACK_LEFT:
359 ret = dri2_surface_swap_buffers(nsurf);
360 break;
361 default:
362 ret = FALSE;
363 break;
364 }
365
366 return ret;
367 }
368
369 static boolean
370 dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask,
371 unsigned int *seq_num, struct pipe_resource **textures,
372 int *width, int *height)
373 {
374 struct dri2_surface *dri2surf = dri2_surface(nsurf);
375
376 if (dri2surf->server_stamp != dri2surf->client_stamp ||
377 (dri2surf->valid_mask & attachment_mask) != attachment_mask) {
378 if (!dri2_surface_update_buffers(&dri2surf->base, attachment_mask))
379 return FALSE;
380 }
381
382 if (seq_num)
383 *seq_num = dri2surf->client_stamp;
384
385 if (textures) {
386 int att;
387 for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
388 if (native_attachment_mask_test(attachment_mask, att)) {
389 struct pipe_resource *ptex = dri2surf->textures[att];
390
391 textures[att] = NULL;
392 pipe_resource_reference(&textures[att], ptex);
393 }
394 }
395 }
396
397 if (width)
398 *width = dri2surf->width;
399 if (height)
400 *height = dri2surf->height;
401
402 return TRUE;
403 }
404
405 static void
406 dri2_surface_wait(struct native_surface *nsurf)
407 {
408 struct dri2_surface *dri2surf = dri2_surface(nsurf);
409 struct dri2_display *dri2dpy = dri2surf->dri2dpy;
410
411 if (dri2surf->have_fake) {
412 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
413 0, 0, dri2surf->width, dri2surf->height,
414 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
415 }
416 }
417
418 static void
419 dri2_surface_destroy(struct native_surface *nsurf)
420 {
421 struct dri2_surface *dri2surf = dri2_surface(nsurf);
422 int i;
423
424 if (dri2surf->last_xbufs)
425 FREE(dri2surf->last_xbufs);
426
427 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
428 struct pipe_resource *ptex = dri2surf->textures[i];
429 pipe_resource_reference(&ptex, NULL);
430 }
431
432 if (dri2surf->drawable) {
433 x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr,
434 dri2surf->drawable, FALSE);
435
436 util_hash_table_remove(dri2surf->dri2dpy->surfaces,
437 (void *) dri2surf->drawable);
438 }
439 FREE(dri2surf);
440 }
441
442 static struct dri2_surface *
443 dri2_display_create_surface(struct native_display *ndpy,
444 Drawable drawable,
445 enum pipe_format color_format)
446 {
447 struct dri2_display *dri2dpy = dri2_display(ndpy);
448 struct dri2_surface *dri2surf;
449
450 dri2surf = CALLOC_STRUCT(dri2_surface);
451 if (!dri2surf)
452 return NULL;
453
454 dri2surf->dri2dpy = dri2dpy;
455 dri2surf->drawable = drawable;
456 dri2surf->color_format = color_format;
457
458 dri2surf->base.destroy = dri2_surface_destroy;
459 dri2surf->base.present = dri2_surface_present;
460 dri2surf->base.validate = dri2_surface_validate;
461 dri2surf->base.wait = dri2_surface_wait;
462
463 if (drawable) {
464 x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE);
465 /* initialize the geometry */
466 dri2_surface_update_buffers(&dri2surf->base, 0x0);
467
468 util_hash_table_set(dri2surf->dri2dpy->surfaces,
469 (void *) dri2surf->drawable, (void *) &dri2surf->base);
470 }
471
472 return dri2surf;
473 }
474
475 static struct native_surface *
476 dri2_display_create_window_surface(struct native_display *ndpy,
477 EGLNativeWindowType win,
478 const struct native_config *nconf)
479 {
480 struct dri2_surface *dri2surf;
481
482 dri2surf = dri2_display_create_surface(ndpy,
483 (Drawable) win, nconf->color_format);
484 return (dri2surf) ? &dri2surf->base : NULL;
485 }
486
487 static struct native_surface *
488 dri2_display_create_pixmap_surface(struct native_display *ndpy,
489 EGLNativePixmapType pix,
490 const struct native_config *nconf)
491 {
492 struct dri2_surface *dri2surf;
493
494 if (!nconf) {
495 struct dri2_display *dri2dpy = dri2_display(ndpy);
496 uint depth, nconf_depth;
497 int i;
498
499 depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix);
500 for (i = 0; i < dri2dpy->num_configs; i++) {
501 nconf_depth = util_format_get_blocksizebits(
502 dri2dpy->configs[i].base.color_format);
503 /* simple depth match for now */
504 if (depth == nconf_depth ||
505 (depth == 24 && depth + 8 == nconf_depth)) {
506 nconf = &dri2dpy->configs[i].base;
507 break;
508 }
509 }
510
511 if (!nconf)
512 return NULL;
513 }
514
515 dri2surf = dri2_display_create_surface(ndpy,
516 (Drawable) pix, nconf->color_format);
517 return (dri2surf) ? &dri2surf->base : NULL;
518 }
519
520 static int
521 choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32])
522 {
523 int count = 0;
524
525 switch (mode->rgbBits) {
526 case 32:
527 formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
528 formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
529 break;
530 case 24:
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;
535 break;
536 case 16:
537 formats[count++] = PIPE_FORMAT_B5G6R5_UNORM;
538 break;
539 default:
540 break;
541 }
542
543 return count;
544 }
545
546 static boolean
547 is_format_supported(struct pipe_screen *screen,
548 enum pipe_format fmt, unsigned sample_count, boolean is_color)
549 {
550 return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D, sample_count,
551 (is_color) ? PIPE_BIND_RENDER_TARGET :
552 PIPE_BIND_DEPTH_STENCIL);
553 }
554
555 static boolean
556 dri2_display_convert_config(struct native_display *ndpy,
557 const __GLcontextModes *mode,
558 struct native_config *nconf)
559 {
560 enum pipe_format formats[32];
561 int num_formats, i;
562 int sample_count = 0;
563
564 if (!(mode->renderType & GLX_RGBA_BIT) || !mode->rgbMode)
565 return FALSE;
566
567 /* only interested in native renderable configs */
568 if (!mode->xRenderable || !mode->drawableType)
569 return FALSE;
570
571 /* fast/slow configs are probably not relevant */
572 if (mode->visualRating == GLX_SLOW_CONFIG)
573 return FALSE;
574
575 nconf->buffer_mask = 1 << NATIVE_ATTACHMENT_FRONT_LEFT;
576 if (mode->doubleBufferMode)
577 nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_LEFT;
578 if (mode->stereoMode) {
579 nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_FRONT_RIGHT;
580 if (mode->doubleBufferMode)
581 nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_RIGHT;
582 }
583
584 /* choose color format */
585 num_formats = choose_color_format(mode, formats);
586 for (i = 0; i < num_formats; i++) {
587 if (is_format_supported(ndpy->screen, formats[i], sample_count, TRUE)) {
588 nconf->color_format = formats[i];
589 break;
590 }
591 }
592 if (nconf->color_format == PIPE_FORMAT_NONE)
593 return FALSE;
594
595 if ((mode->drawableType & GLX_WINDOW_BIT) && mode->visualID)
596 nconf->window_bit = TRUE;
597 if (mode->drawableType & GLX_PIXMAP_BIT)
598 nconf->pixmap_bit = TRUE;
599
600 nconf->native_visual_id = mode->visualID;
601 switch (mode->visualType) {
602 case GLX_TRUE_COLOR:
603 nconf->native_visual_type = TrueColor;
604 break;
605 case GLX_DIRECT_COLOR:
606 nconf->native_visual_type = DirectColor;
607 break;
608 case GLX_PSEUDO_COLOR:
609 nconf->native_visual_type = PseudoColor;
610 break;
611 case GLX_STATIC_COLOR:
612 nconf->native_visual_type = StaticColor;
613 break;
614 case GLX_GRAY_SCALE:
615 nconf->native_visual_type = GrayScale;
616 break;
617 case GLX_STATIC_GRAY:
618 nconf->native_visual_type = StaticGray;
619 break;
620 }
621 nconf->level = mode->level;
622
623 if (mode->transparentPixel == GLX_TRANSPARENT_RGB) {
624 nconf->transparent_rgb = TRUE;
625 nconf->transparent_rgb_values[0] = mode->transparentRed;
626 nconf->transparent_rgb_values[1] = mode->transparentGreen;
627 nconf->transparent_rgb_values[2] = mode->transparentBlue;
628 }
629
630 return TRUE;
631 }
632
633 static const struct native_config **
634 dri2_display_get_configs(struct native_display *ndpy, int *num_configs)
635 {
636 struct dri2_display *dri2dpy = dri2_display(ndpy);
637 const struct native_config **configs;
638 int i;
639
640 /* first time */
641 if (!dri2dpy->configs) {
642 const __GLcontextModes *modes;
643 int num_modes, count;
644
645 modes = x11_screen_get_glx_configs(dri2dpy->xscr);
646 if (!modes)
647 return NULL;
648 num_modes = x11_context_modes_count(modes);
649
650 dri2dpy->configs = CALLOC(num_modes, sizeof(*dri2dpy->configs));
651 if (!dri2dpy->configs)
652 return NULL;
653
654 count = 0;
655 for (i = 0; i < num_modes; i++) {
656 struct native_config *nconf = &dri2dpy->configs[count].base;
657
658 if (dri2_display_convert_config(&dri2dpy->base, modes, nconf)) {
659 int j;
660 /* look for duplicates */
661 for (j = 0; j < count; j++) {
662 if (memcmp(&dri2dpy->configs[j], nconf, sizeof(*nconf)) == 0)
663 break;
664 }
665 if (j == count)
666 count++;
667 }
668 modes = modes->next;
669 }
670
671 dri2dpy->num_configs = count;
672 }
673
674 configs = MALLOC(dri2dpy->num_configs * sizeof(*configs));
675 if (configs) {
676 for (i = 0; i < dri2dpy->num_configs; i++)
677 configs[i] = (const struct native_config *) &dri2dpy->configs[i];
678 if (num_configs)
679 *num_configs = dri2dpy->num_configs;
680 }
681
682 return configs;
683 }
684
685 static boolean
686 dri2_display_get_pixmap_format(struct native_display *ndpy,
687 EGLNativePixmapType pix,
688 enum pipe_format *format)
689 {
690 struct dri2_display *dri2dpy = dri2_display(ndpy);
691 boolean ret = EGL_TRUE;
692 uint depth;
693
694 depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix);
695 switch (depth) {
696 case 32:
697 case 24:
698 *format = PIPE_FORMAT_B8G8R8A8_UNORM;
699 break;
700 case 16:
701 *format = PIPE_FORMAT_B5G6R5_UNORM;
702 break;
703 default:
704 *format = PIPE_FORMAT_NONE;
705 ret = EGL_FALSE;
706 break;
707 }
708
709 return ret;
710 }
711
712 static int
713 dri2_display_get_param(struct native_display *ndpy,
714 enum native_param_type param)
715 {
716 int val;
717
718 switch (param) {
719 case NATIVE_PARAM_USE_NATIVE_BUFFER:
720 /* DRI2GetBuffers uses the native buffers */
721 val = TRUE;
722 break;
723 case NATIVE_PARAM_PRESERVE_BUFFER:
724 /* DRI2CopyRegion is used */
725 val = TRUE;
726 break;
727 case NATIVE_PARAM_MAX_SWAP_INTERVAL:
728 default:
729 val = 0;
730 break;
731 }
732
733 return val;
734 }
735
736 static void
737 dri2_display_destroy(struct native_display *ndpy)
738 {
739 struct dri2_display *dri2dpy = dri2_display(ndpy);
740
741 if (dri2dpy->configs)
742 FREE(dri2dpy->configs);
743
744 if (dri2dpy->base.screen)
745 dri2dpy->base.screen->destroy(dri2dpy->base.screen);
746
747 if (dri2dpy->surfaces)
748 util_hash_table_destroy(dri2dpy->surfaces);
749
750 if (dri2dpy->xscr)
751 x11_screen_destroy(dri2dpy->xscr);
752 if (dri2dpy->own_dpy)
753 XCloseDisplay(dri2dpy->dpy);
754 FREE(dri2dpy);
755 }
756
757 static void
758 dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable,
759 void *user_data)
760 {
761 struct native_display *ndpy = (struct native_display* ) user_data;
762 struct dri2_display *dri2dpy = dri2_display(ndpy);
763 struct native_surface *nsurf;
764 struct dri2_surface *dri2surf;
765
766 nsurf = (struct native_surface *)
767 util_hash_table_get(dri2dpy->surfaces, (void *) drawable);
768 if (!nsurf)
769 return;
770
771 dri2surf = dri2_surface(nsurf);
772
773 dri2surf->server_stamp++;
774 dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
775 &dri2surf->base, dri2surf->server_stamp);
776 }
777
778 /**
779 * Initialize DRI2 and pipe screen.
780 */
781 static boolean
782 dri2_display_init_screen(struct native_display *ndpy)
783 {
784 struct dri2_display *dri2dpy = dri2_display(ndpy);
785 int fd;
786
787 if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) ||
788 !x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_GLX)) {
789 _eglLog(_EGL_WARNING, "GLX/DRI2 is not supported");
790 return FALSE;
791 }
792
793 dri2dpy->dri_driver = x11_screen_probe_dri2(dri2dpy->xscr,
794 &dri2dpy->dri_major, &dri2dpy->dri_minor);
795
796 fd = x11_screen_enable_dri2(dri2dpy->xscr,
797 dri2_display_invalidate_buffers, &dri2dpy->base);
798 if (fd < 0)
799 return FALSE;
800
801 dri2dpy->base.screen =
802 dri2dpy->event_handler->new_drm_screen(&dri2dpy->base,
803 dri2dpy->dri_driver, fd);
804 if (!dri2dpy->base.screen) {
805 _eglLog(_EGL_DEBUG, "failed to create DRM screen");
806 return FALSE;
807 }
808
809 return TRUE;
810 }
811
812 static unsigned
813 dri2_display_hash_table_hash(void *key)
814 {
815 XID drawable = pointer_to_uintptr(key);
816 return (unsigned) drawable;
817 }
818
819 static int
820 dri2_display_hash_table_compare(void *key1, void *key2)
821 {
822 return ((char *) key1 - (char *) key2);
823 }
824
825 static int
826 dri2_display_authenticate(void *user_data, uint32_t magic)
827 {
828 struct native_display *ndpy = user_data;
829 struct dri2_display *dri2dpy = dri2_display(ndpy);
830
831 return x11_screen_authenticate(dri2dpy->xscr, magic);
832 }
833
834 #ifdef HAVE_WAYLAND_BACKEND
835
836 static struct wayland_drm_callbacks wl_drm_callbacks = {
837 dri2_display_authenticate,
838 egl_g3d_wl_drm_helper_reference_buffer,
839 egl_g3d_wl_drm_helper_unreference_buffer
840 };
841
842 static boolean
843 dri2_display_bind_wayland_display(struct native_display *ndpy,
844 struct wl_display *wl_dpy)
845 {
846 struct dri2_display *dri2dpy = dri2_display(ndpy);
847
848 if (dri2dpy->wl_server_drm)
849 return FALSE;
850
851 dri2dpy->wl_server_drm = wayland_drm_init(wl_dpy,
852 x11_screen_get_device_name(dri2dpy->xscr),
853 &wl_drm_callbacks, ndpy);
854
855 if (!dri2dpy->wl_server_drm)
856 return FALSE;
857
858 return TRUE;
859 }
860
861 static boolean
862 dri2_display_unbind_wayland_display(struct native_display *ndpy,
863 struct wl_display *wl_dpy)
864 {
865 struct dri2_display *dri2dpy = dri2_display(ndpy);
866
867 if (!dri2dpy->wl_server_drm)
868 return FALSE;
869
870 wayland_drm_uninit(dri2dpy->wl_server_drm);
871 dri2dpy->wl_server_drm = NULL;
872
873 return TRUE;
874 }
875
876 static struct native_display_wayland_bufmgr dri2_display_wayland_bufmgr = {
877 dri2_display_bind_wayland_display,
878 dri2_display_unbind_wayland_display,
879 egl_g3d_wl_drm_common_wl_buffer_get_resource
880 };
881
882 #endif /* HAVE_WAYLAND_BACKEND */
883
884 struct native_display *
885 x11_create_dri2_display(Display *dpy,
886 const struct native_event_handler *event_handler)
887 {
888 struct dri2_display *dri2dpy;
889
890 dri2dpy = CALLOC_STRUCT(dri2_display);
891 if (!dri2dpy)
892 return NULL;
893
894 dri2dpy->event_handler = event_handler;
895
896 dri2dpy->dpy = dpy;
897 if (!dri2dpy->dpy) {
898 dri2dpy->dpy = XOpenDisplay(NULL);
899 if (!dri2dpy->dpy) {
900 dri2_display_destroy(&dri2dpy->base);
901 return NULL;
902 }
903 dri2dpy->own_dpy = TRUE;
904 }
905
906 dri2dpy->xscr_number = DefaultScreen(dri2dpy->dpy);
907 dri2dpy->xscr = x11_screen_create(dri2dpy->dpy, dri2dpy->xscr_number);
908 if (!dri2dpy->xscr) {
909 dri2_display_destroy(&dri2dpy->base);
910 return NULL;
911 }
912
913 dri2dpy->surfaces = util_hash_table_create(dri2_display_hash_table_hash,
914 dri2_display_hash_table_compare);
915 if (!dri2dpy->surfaces) {
916 dri2_display_destroy(&dri2dpy->base);
917 return NULL;
918 }
919
920 dri2dpy->base.init_screen = dri2_display_init_screen;
921 dri2dpy->base.destroy = dri2_display_destroy;
922 dri2dpy->base.get_param = dri2_display_get_param;
923 dri2dpy->base.get_configs = dri2_display_get_configs;
924 dri2dpy->base.get_pixmap_format = dri2_display_get_pixmap_format;
925 dri2dpy->base.copy_to_pixmap = native_display_copy_to_pixmap;
926 dri2dpy->base.create_window_surface = dri2_display_create_window_surface;
927 dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface;
928 #ifdef HAVE_WAYLAND_BACKEND
929 dri2dpy->base.wayland_bufmgr = &dri2_display_wayland_bufmgr;
930 #endif
931
932 return &dri2dpy->base;
933 }
934
935 #else /* GLX_DIRECT_RENDERING */
936
937 struct native_display *
938 x11_create_dri2_display(Display *dpy,
939 const struct native_event_handler *event_handler)
940 {
941 return NULL;
942 }
943
944 #endif /* GLX_DIRECT_RENDERING */