st/egl: Refactor dri2_surface_get_buffers.
[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
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.
23 */
24
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 "pipe/p_compiler.h"
30 #include "pipe/p_screen.h"
31 #include "pipe/p_context.h"
32 #include "pipe/p_state.h"
33 #include "state_tracker/drm_api.h"
34 #include "egllog.h"
35
36 #include "native_x11.h"
37 #include "x11_screen.h"
38
39 enum dri2_surface_type {
40 DRI2_SURFACE_TYPE_WINDOW,
41 DRI2_SURFACE_TYPE_PIXMAP,
42 DRI2_SURFACE_TYPE_PBUFFER
43 };
44
45 struct dri2_display {
46 struct native_display base;
47 Display *dpy;
48 boolean own_dpy;
49
50 struct drm_api *api;
51 struct x11_screen *xscr;
52 int xscr_number;
53 const char *dri_driver;
54 int dri_major, dri_minor;
55
56 struct dri2_config *configs;
57 int num_configs;
58 };
59
60 struct dri2_surface {
61 struct native_surface base;
62 Drawable drawable;
63 enum dri2_surface_type type;
64 enum pipe_format color_format;
65 struct dri2_display *dri2dpy;
66
67 unsigned int sequence_number;
68 int width, height;
69 struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
70 uint valid_mask;
71
72 boolean have_back, have_fake;
73
74 struct x11_drawable_buffer *last_xbufs;
75 int last_num_xbufs;
76 };
77
78 struct dri2_config {
79 struct native_config base;
80 };
81
82 static INLINE struct dri2_display *
83 dri2_display(const struct native_display *ndpy)
84 {
85 return (struct dri2_display *) ndpy;
86 }
87
88 static INLINE struct dri2_surface *
89 dri2_surface(const struct native_surface *nsurf)
90 {
91 return (struct dri2_surface *) nsurf;
92 }
93
94 static INLINE struct dri2_config *
95 dri2_config(const struct native_config *nconf)
96 {
97 return (struct dri2_config *) nconf;
98 }
99
100 /**
101 * Process the buffers returned by the server.
102 */
103 static void
104 dri2_surface_process_drawable_buffers(struct native_surface *nsurf,
105 struct x11_drawable_buffer *xbufs,
106 int num_xbufs)
107 {
108 struct dri2_surface *dri2surf = dri2_surface(nsurf);
109 struct dri2_display *dri2dpy = dri2surf->dri2dpy;
110 struct pipe_texture templ;
111 uint valid_mask;
112 int i;
113
114 /* free the old textures */
115 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++)
116 pipe_texture_reference(&dri2surf->textures[i], NULL);
117 dri2surf->valid_mask = 0x0;
118
119 dri2surf->have_back = FALSE;
120 dri2surf->have_fake = FALSE;
121
122 if (!xbufs)
123 return;
124
125 memset(&templ, 0, sizeof(templ));
126 templ.target = PIPE_TEXTURE_2D;
127 templ.last_level = 0;
128 templ.width0 = dri2surf->width;
129 templ.height0 = dri2surf->height;
130 templ.depth0 = 1;
131 templ.format = dri2surf->color_format;
132 templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
133
134 valid_mask = 0x0;
135 for (i = 0; i < num_xbufs; i++) {
136 struct x11_drawable_buffer *xbuf = &xbufs[i];
137 const char *desc;
138 enum native_attachment natt;
139
140 switch (xbuf->attachment) {
141 case DRI2BufferFrontLeft:
142 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
143 desc = "DRI2 Front Buffer";
144 break;
145 case DRI2BufferFakeFrontLeft:
146 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
147 desc = "DRI2 Fake Front Buffer";
148 dri2surf->have_fake = TRUE;
149 break;
150 case DRI2BufferBackLeft:
151 natt = NATIVE_ATTACHMENT_BACK_LEFT;
152 desc = "DRI2 Back Buffer";
153 dri2surf->have_back = TRUE;
154 break;
155 default:
156 desc = NULL;
157 break;
158 }
159
160 if (!desc || dri2surf->textures[natt]) {
161 if (!desc)
162 _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment);
163 else
164 _eglLog(_EGL_WARNING, "both real and fake front buffers are listed");
165 continue;
166 }
167
168 dri2surf->textures[natt] =
169 dri2dpy->api->texture_from_shared_handle(dri2dpy->api,
170 dri2dpy->base.screen, &templ, desc, xbuf->pitch, xbuf->name);
171 if (dri2surf->textures[natt])
172 valid_mask |= 1 << natt;
173 }
174
175 dri2surf->valid_mask = valid_mask;
176 }
177
178 /**
179 * Get the buffers from the server.
180 */
181 static void
182 dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask)
183 {
184 struct dri2_surface *dri2surf = dri2_surface(nsurf);
185 struct dri2_display *dri2dpy = dri2surf->dri2dpy;
186 unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS];
187 int num_ins, num_outs, att;
188 struct x11_drawable_buffer *xbufs;
189
190 /* prepare the attachments */
191 num_ins = 0;
192 for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
193 if (native_attachment_mask_test(buffer_mask, att)) {
194 unsigned int dri2att;
195
196 switch (att) {
197 case NATIVE_ATTACHMENT_FRONT_LEFT:
198 dri2att = DRI2BufferFrontLeft;
199 break;
200 case NATIVE_ATTACHMENT_BACK_LEFT:
201 dri2att = DRI2BufferBackLeft;
202 break;
203 case NATIVE_ATTACHMENT_FRONT_RIGHT:
204 dri2att = DRI2BufferFrontRight;
205 break;
206 case NATIVE_ATTACHMENT_BACK_RIGHT:
207 dri2att = DRI2BufferBackRight;
208 break;
209 default:
210 assert(0);
211 dri2att = 0;
212 break;
213 }
214
215 dri2atts[num_ins] = dri2att;
216 num_ins++;
217 }
218 }
219
220 xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable,
221 &dri2surf->width, &dri2surf->height,
222 dri2atts, FALSE, num_ins, &num_outs);
223
224 /* we should be able to do better... */
225 if (xbufs && dri2surf->last_num_xbufs == num_outs &&
226 memcmp(dri2surf->last_xbufs, xbufs, sizeof(*xbufs) * num_outs) == 0) {
227 free(xbufs);
228 return;
229 }
230
231 dri2_surface_process_drawable_buffers(&dri2surf->base, xbufs, num_outs);
232
233 dri2surf->sequence_number++;
234
235 if (dri2surf->last_xbufs)
236 free(dri2surf->last_xbufs);
237 dri2surf->last_xbufs = xbufs;
238 dri2surf->last_num_xbufs = num_outs;
239 }
240
241 /**
242 * Update the buffers of the surface. This is a slow function due to the
243 * round-trip to the server.
244 */
245 static boolean
246 dri2_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask)
247 {
248 struct dri2_surface *dri2surf = dri2_surface(nsurf);
249 struct dri2_display *dri2dpy = dri2surf->dri2dpy;
250
251 /* create textures for pbuffer */
252 if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) {
253 struct pipe_screen *screen = dri2dpy->base.screen;
254 struct pipe_texture templ;
255 uint new_valid = 0x0;
256 int att;
257
258 buffer_mask &= ~dri2surf->valid_mask;
259 if (!buffer_mask)
260 return TRUE;
261
262 memset(&templ, 0, sizeof(templ));
263 templ.target = PIPE_TEXTURE_2D;
264 templ.last_level = 0;
265 templ.width0 = dri2surf->width;
266 templ.height0 = dri2surf->height;
267 templ.depth0 = 1;
268 templ.format = dri2surf->color_format;
269 templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
270
271 for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
272 if (native_attachment_mask_test(buffer_mask, att)) {
273 assert(!dri2surf->textures[att]);
274
275 dri2surf->textures[att] = screen->texture_create(screen, &templ);
276 if (!dri2surf->textures[att])
277 break;
278
279 new_valid |= 1 << att;
280 if (new_valid == buffer_mask)
281 break;
282 }
283 }
284 dri2surf->valid_mask |= new_valid;
285 /* no need to update sequence number */
286 }
287 else {
288 dri2_surface_get_buffers(&dri2surf->base, buffer_mask);
289 }
290
291 return ((dri2surf->valid_mask & buffer_mask) == buffer_mask);
292 }
293
294 static boolean
295 dri2_surface_flush_frontbuffer(struct native_surface *nsurf)
296 {
297 struct dri2_surface *dri2surf = dri2_surface(nsurf);
298 struct dri2_display *dri2dpy = dri2surf->dri2dpy;
299
300 /* pbuffer is private */
301 if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER)
302 return TRUE;
303
304 /* copy to real front buffer */
305 if (dri2surf->have_fake)
306 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
307 0, 0, dri2surf->width, dri2surf->height,
308 DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
309
310 return TRUE;
311 }
312
313 static boolean
314 dri2_surface_swap_buffers(struct native_surface *nsurf)
315 {
316 struct dri2_surface *dri2surf = dri2_surface(nsurf);
317 struct dri2_display *dri2dpy = dri2surf->dri2dpy;
318
319 /* pbuffer is private */
320 if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER)
321 return TRUE;
322
323 /* copy to front buffer */
324 if (dri2surf->have_back)
325 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
326 0, 0, dri2surf->width, dri2surf->height,
327 DRI2BufferBackLeft, DRI2BufferFrontLeft);
328
329 /* and update fake front buffer */
330 if (dri2surf->have_fake)
331 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
332 0, 0, dri2surf->width, dri2surf->height,
333 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
334
335 return TRUE;
336 }
337
338 static boolean
339 dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask,
340 unsigned int *seq_num, struct pipe_texture **textures,
341 int *width, int *height)
342 {
343 struct dri2_surface *dri2surf = dri2_surface(nsurf);
344
345 if (!dri2_surface_update_buffers(&dri2surf->base, attachment_mask))
346 return FALSE;
347
348 if (seq_num)
349 *seq_num = dri2surf->sequence_number;
350
351 if (textures) {
352 int att;
353 for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
354 if (native_attachment_mask_test(attachment_mask, att)) {
355 struct pipe_texture *ptex = dri2surf->textures[att];
356
357 textures[att] = NULL;
358 pipe_texture_reference(&textures[att], ptex);
359 }
360 }
361 }
362
363 if (width)
364 *width = dri2surf->width;
365 if (height)
366 *height = dri2surf->height;
367
368 return TRUE;
369 }
370
371 static void
372 dri2_surface_wait(struct native_surface *nsurf)
373 {
374 struct dri2_surface *dri2surf = dri2_surface(nsurf);
375 struct dri2_display *dri2dpy = dri2surf->dri2dpy;
376
377 if (dri2surf->have_fake) {
378 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
379 0, 0, dri2surf->width, dri2surf->height,
380 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
381 }
382 }
383
384 static void
385 dri2_surface_destroy(struct native_surface *nsurf)
386 {
387 struct dri2_surface *dri2surf = dri2_surface(nsurf);
388 int i;
389
390 if (dri2surf->last_xbufs)
391 free(dri2surf->last_xbufs);
392
393 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
394 struct pipe_texture *ptex = dri2surf->textures[i];
395 pipe_texture_reference(&ptex, NULL);
396 }
397
398 if (dri2surf->drawable)
399 x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr,
400 dri2surf->drawable, FALSE);
401 free(dri2surf);
402 }
403
404 static struct dri2_surface *
405 dri2_display_create_surface(struct native_display *ndpy,
406 enum dri2_surface_type type,
407 Drawable drawable,
408 const struct native_config *nconf)
409 {
410 struct dri2_display *dri2dpy = dri2_display(ndpy);
411 struct dri2_config *dri2conf = dri2_config(nconf);
412 struct dri2_surface *dri2surf;
413
414 dri2surf = CALLOC_STRUCT(dri2_surface);
415 if (!dri2surf)
416 return NULL;
417
418 dri2surf->dri2dpy = dri2dpy;
419 dri2surf->type = type;
420 dri2surf->drawable = drawable;
421 dri2surf->color_format = dri2conf->base.color_format;
422
423 dri2surf->base.destroy = dri2_surface_destroy;
424 dri2surf->base.swap_buffers = dri2_surface_swap_buffers;
425 dri2surf->base.flush_frontbuffer = dri2_surface_flush_frontbuffer;
426 dri2surf->base.validate = dri2_surface_validate;
427 dri2surf->base.wait = dri2_surface_wait;
428
429 if (drawable)
430 x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE);
431
432 return dri2surf;
433 }
434
435 static struct native_surface *
436 dri2_display_create_window_surface(struct native_display *ndpy,
437 EGLNativeWindowType win,
438 const struct native_config *nconf)
439 {
440 struct dri2_surface *dri2surf;
441
442 dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_WINDOW,
443 (Drawable) win, nconf);
444 return (dri2surf) ? &dri2surf->base : NULL;
445 }
446
447 static struct native_surface *
448 dri2_display_create_pixmap_surface(struct native_display *ndpy,
449 EGLNativePixmapType pix,
450 const struct native_config *nconf)
451 {
452 struct dri2_surface *dri2surf;
453
454 dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_PIXMAP,
455 (Drawable) pix, nconf);
456 return (dri2surf) ? &dri2surf->base : NULL;
457 }
458
459 static struct native_surface *
460 dri2_display_create_pbuffer_surface(struct native_display *ndpy,
461 const struct native_config *nconf,
462 uint width, uint height)
463 {
464 struct dri2_surface *dri2surf;
465
466 dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_PBUFFER,
467 (Drawable) None, nconf);
468 if (dri2surf) {
469 dri2surf->width = width;
470 dri2surf->height = height;
471 }
472 return (dri2surf) ? &dri2surf->base : NULL;
473 }
474
475 static int
476 choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32])
477 {
478 int count = 0;
479
480 switch (mode->rgbBits) {
481 case 32:
482 formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
483 formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
484 break;
485 case 24:
486 formats[count++] = PIPE_FORMAT_X8R8G8B8_UNORM;
487 formats[count++] = PIPE_FORMAT_B8G8R8X8_UNORM;
488 formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
489 formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
490 break;
491 case 16:
492 formats[count++] = PIPE_FORMAT_R5G6B5_UNORM;
493 break;
494 default:
495 break;
496 }
497
498 return count;
499 }
500
501 static int
502 choose_depth_stencil_format(const __GLcontextModes *mode,
503 enum pipe_format formats[32])
504 {
505 int count = 0;
506
507 switch (mode->depthBits) {
508 case 32:
509 formats[count++] = PIPE_FORMAT_Z32_UNORM;
510 break;
511 case 24:
512 if (mode->stencilBits) {
513 formats[count++] = PIPE_FORMAT_S8Z24_UNORM;
514 formats[count++] = PIPE_FORMAT_Z24S8_UNORM;
515 }
516 else {
517 formats[count++] = PIPE_FORMAT_X8Z24_UNORM;
518 formats[count++] = PIPE_FORMAT_Z24X8_UNORM;
519 }
520 break;
521 case 16:
522 formats[count++] = PIPE_FORMAT_Z16_UNORM;
523 break;
524 default:
525 break;
526 }
527
528 return count;
529 }
530
531 static boolean
532 is_format_supported(struct pipe_screen *screen,
533 enum pipe_format fmt, boolean is_color)
534 {
535 return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D,
536 (is_color) ? PIPE_TEXTURE_USAGE_RENDER_TARGET :
537 PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
538 }
539
540 static boolean
541 dri2_display_convert_config(struct native_display *ndpy,
542 const __GLcontextModes *mode,
543 struct native_config *nconf)
544 {
545 enum pipe_format formats[32];
546 int num_formats, i;
547
548 if (!(mode->renderType & GLX_RGBA_BIT) || !mode->rgbMode)
549 return FALSE;
550
551 /* skip single-buffered configs */
552 if (!mode->doubleBufferMode)
553 return FALSE;
554
555 nconf->mode = *mode;
556 nconf->mode.renderType = GLX_RGBA_BIT;
557 nconf->mode.rgbMode = TRUE;
558 /* pbuffer is allocated locally and is always supported */
559 nconf->mode.drawableType |= GLX_PBUFFER_BIT;
560 /* the swap method is always copy */
561 nconf->mode.swapMethod = GLX_SWAP_COPY_OML;
562
563 /* fix up */
564 nconf->mode.rgbBits =
565 nconf->mode.redBits + nconf->mode.greenBits +
566 nconf->mode.blueBits + nconf->mode.alphaBits;
567 if (!(nconf->mode.drawableType & GLX_WINDOW_BIT)) {
568 nconf->mode.visualID = 0;
569 nconf->mode.visualType = GLX_NONE;
570 }
571 if (!(nconf->mode.drawableType & GLX_PBUFFER_BIT)) {
572 nconf->mode.bindToTextureRgb = FALSE;
573 nconf->mode.bindToTextureRgba = FALSE;
574 }
575
576 nconf->color_format = PIPE_FORMAT_NONE;
577 nconf->depth_format = PIPE_FORMAT_NONE;
578 nconf->stencil_format = PIPE_FORMAT_NONE;
579
580 /* choose color format */
581 num_formats = choose_color_format(mode, formats);
582 for (i = 0; i < num_formats; i++) {
583 if (is_format_supported(ndpy->screen, formats[i], TRUE)) {
584 nconf->color_format = formats[i];
585 break;
586 }
587 }
588 if (nconf->color_format == PIPE_FORMAT_NONE)
589 return FALSE;
590
591 /* choose depth/stencil format */
592 num_formats = choose_depth_stencil_format(mode, formats);
593 for (i = 0; i < num_formats; i++) {
594 if (is_format_supported(ndpy->screen, formats[i], FALSE)) {
595 nconf->depth_format = formats[i];
596 nconf->stencil_format = formats[i];
597 break;
598 }
599 }
600 if ((nconf->mode.depthBits && nconf->depth_format == PIPE_FORMAT_NONE) ||
601 (nconf->mode.stencilBits && nconf->stencil_format == PIPE_FORMAT_NONE))
602 return FALSE;
603
604 return TRUE;
605 }
606
607 static const struct native_config **
608 dri2_display_get_configs(struct native_display *ndpy, int *num_configs)
609 {
610 struct dri2_display *dri2dpy = dri2_display(ndpy);
611 const struct native_config **configs;
612 int i;
613
614 /* first time */
615 if (!dri2dpy->configs) {
616 const __GLcontextModes *modes;
617 int num_modes, count;
618
619 modes = x11_screen_get_glx_configs(dri2dpy->xscr);
620 if (!modes)
621 return NULL;
622 num_modes = x11_context_modes_count(modes);
623
624 dri2dpy->configs = calloc(num_modes, sizeof(*dri2dpy->configs));
625 if (!dri2dpy->configs)
626 return NULL;
627
628 count = 0;
629 for (i = 0; i < num_modes; i++) {
630 struct native_config *nconf = &dri2dpy->configs[count].base;
631 if (dri2_display_convert_config(&dri2dpy->base, modes, nconf))
632 count++;
633 modes = modes->next;
634 }
635
636 dri2dpy->num_configs = count;
637 }
638
639 configs = malloc(dri2dpy->num_configs * sizeof(*configs));
640 if (configs) {
641 for (i = 0; i < dri2dpy->num_configs; i++)
642 configs[i] = (const struct native_config *) &dri2dpy->configs[i];
643 if (num_configs)
644 *num_configs = dri2dpy->num_configs;
645 }
646
647 return configs;
648 }
649
650 static boolean
651 dri2_display_is_pixmap_supported(struct native_display *ndpy,
652 EGLNativePixmapType pix,
653 const struct native_config *nconf)
654 {
655 struct dri2_display *dri2dpy = dri2_display(ndpy);
656 uint depth, nconf_depth;
657
658 depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix);
659 nconf_depth = util_format_get_blocksizebits(nconf->color_format);
660
661 /* simple depth match for now */
662 return (depth == nconf_depth || (depth == 24 && depth + 8 == nconf_depth));
663 }
664
665 static void
666 dri2_display_destroy(struct native_display *ndpy)
667 {
668 struct dri2_display *dri2dpy = dri2_display(ndpy);
669
670 if (dri2dpy->configs)
671 free(dri2dpy->configs);
672
673 if (dri2dpy->base.screen)
674 dri2dpy->base.screen->destroy(dri2dpy->base.screen);
675
676 if (dri2dpy->xscr)
677 x11_screen_destroy(dri2dpy->xscr);
678 if (dri2dpy->own_dpy)
679 XCloseDisplay(dri2dpy->dpy);
680 if (dri2dpy->api && dri2dpy->api->destroy)
681 dri2dpy->api->destroy(dri2dpy->api);
682 free(dri2dpy);
683 }
684
685 /**
686 * Initialize DRI2 and pipe screen.
687 */
688 static boolean
689 dri2_display_init_screen(struct native_display *ndpy)
690 {
691 struct dri2_display *dri2dpy = dri2_display(ndpy);
692 const char *driver = dri2dpy->api->name;
693 struct drm_create_screen_arg arg;
694 int fd;
695
696 if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) ||
697 !x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_GLX)) {
698 _eglLog(_EGL_WARNING, "GLX/DRI2 is not supported");
699 return FALSE;
700 }
701
702 dri2dpy->dri_driver = x11_screen_probe_dri2(dri2dpy->xscr,
703 &dri2dpy->dri_major, &dri2dpy->dri_minor);
704 if (!dri2dpy->dri_driver || !driver ||
705 strcmp(dri2dpy->dri_driver, driver) != 0) {
706 _eglLog(_EGL_WARNING, "Driver mismatch: %s != %s",
707 dri2dpy->dri_driver, dri2dpy->api->name);
708 return FALSE;
709 }
710
711 fd = x11_screen_enable_dri2(dri2dpy->xscr, NULL, NULL);
712 if (fd < 0)
713 return FALSE;
714
715 memset(&arg, 0, sizeof(arg));
716 arg.mode = DRM_CREATE_NORMAL;
717 dri2dpy->base.screen = dri2dpy->api->create_screen(dri2dpy->api, fd, &arg);
718 if (!dri2dpy->base.screen) {
719 _eglLog(_EGL_WARNING, "failed to create DRM screen");
720 return FALSE;
721 }
722
723 return TRUE;
724 }
725
726 struct native_display *
727 x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api)
728 {
729 struct dri2_display *dri2dpy;
730
731 dri2dpy = CALLOC_STRUCT(dri2_display);
732 if (!dri2dpy)
733 return NULL;
734
735 dri2dpy->api = api;
736 if (!dri2dpy->api) {
737 _eglLog(_EGL_WARNING, "failed to create DRM API");
738 free(dri2dpy);
739 return NULL;
740 }
741
742 dri2dpy->dpy = dpy;
743 if (!dri2dpy->dpy) {
744 dri2dpy->dpy = XOpenDisplay(NULL);
745 if (!dri2dpy->dpy) {
746 dri2_display_destroy(&dri2dpy->base);
747 return NULL;
748 }
749 dri2dpy->own_dpy = TRUE;
750 }
751
752 dri2dpy->xscr_number = DefaultScreen(dri2dpy->dpy);
753 dri2dpy->xscr = x11_screen_create(dri2dpy->dpy, dri2dpy->xscr_number);
754 if (!dri2dpy->xscr) {
755 dri2_display_destroy(&dri2dpy->base);
756 return NULL;
757 }
758
759 if (!dri2_display_init_screen(&dri2dpy->base)) {
760 dri2_display_destroy(&dri2dpy->base);
761 return NULL;
762 }
763
764 dri2dpy->base.destroy = dri2_display_destroy;
765 dri2dpy->base.get_configs = dri2_display_get_configs;
766 dri2dpy->base.is_pixmap_supported = dri2_display_is_pixmap_supported;
767 dri2dpy->base.create_window_surface = dri2_display_create_window_surface;
768 dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface;
769 dri2dpy->base.create_pbuffer_surface = dri2_display_create_pbuffer_surface;
770
771 return &dri2dpy->base;
772 }