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