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