gallium: support for array textures and related changes
[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 #ifdef GLX_DIRECT_RENDERING
42
43 enum dri2_surface_type {
44 DRI2_SURFACE_TYPE_WINDOW,
45 DRI2_SURFACE_TYPE_PIXMAP,
46 };
47
48 struct dri2_display {
49 struct native_display base;
50 Display *dpy;
51 boolean own_dpy;
52
53 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 };
65
66 struct dri2_surface {
67 struct native_surface base;
68 Drawable drawable;
69 enum dri2_surface_type type;
70 enum pipe_format color_format;
71 struct dri2_display *dri2dpy;
72
73 unsigned int server_stamp;
74 unsigned int client_stamp;
75 int width, height;
76 struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS];
77 uint valid_mask;
78
79 boolean have_back, have_fake;
80
81 struct x11_drawable_buffer *last_xbufs;
82 int last_num_xbufs;
83 };
84
85 struct dri2_config {
86 struct native_config base;
87 };
88
89 static INLINE struct dri2_display *
90 dri2_display(const struct native_display *ndpy)
91 {
92 return (struct dri2_display *) ndpy;
93 }
94
95 static INLINE struct dri2_surface *
96 dri2_surface(const struct native_surface *nsurf)
97 {
98 return (struct dri2_surface *) nsurf;
99 }
100
101 static INLINE struct dri2_config *
102 dri2_config(const struct native_config *nconf)
103 {
104 return (struct dri2_config *) nconf;
105 }
106
107 /**
108 * Process the buffers returned by the server.
109 */
110 static void
111 dri2_surface_process_drawable_buffers(struct native_surface *nsurf,
112 struct x11_drawable_buffer *xbufs,
113 int num_xbufs)
114 {
115 struct dri2_surface *dri2surf = dri2_surface(nsurf);
116 struct dri2_display *dri2dpy = dri2surf->dri2dpy;
117 struct pipe_resource templ;
118 struct winsys_handle whandle;
119 uint valid_mask;
120 int i;
121
122 /* free the old textures */
123 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++)
124 pipe_resource_reference(&dri2surf->textures[i], NULL);
125 dri2surf->valid_mask = 0x0;
126
127 dri2surf->have_back = FALSE;
128 dri2surf->have_fake = FALSE;
129
130 if (!xbufs)
131 return;
132
133 memset(&templ, 0, sizeof(templ));
134 templ.target = PIPE_TEXTURE_2D;
135 templ.last_level = 0;
136 templ.width0 = dri2surf->width;
137 templ.height0 = dri2surf->height;
138 templ.depth0 = 1;
139 templ.array_size = 1;
140 templ.format = dri2surf->color_format;
141 templ.bind = PIPE_BIND_RENDER_TARGET;
142
143 valid_mask = 0x0;
144 for (i = 0; i < num_xbufs; i++) {
145 struct x11_drawable_buffer *xbuf = &xbufs[i];
146 const char *desc;
147 enum native_attachment natt;
148
149 switch (xbuf->attachment) {
150 case DRI2BufferFrontLeft:
151 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
152 desc = "DRI2 Front Buffer";
153 break;
154 case DRI2BufferFakeFrontLeft:
155 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
156 desc = "DRI2 Fake Front Buffer";
157 dri2surf->have_fake = TRUE;
158 break;
159 case DRI2BufferBackLeft:
160 natt = NATIVE_ATTACHMENT_BACK_LEFT;
161 desc = "DRI2 Back Buffer";
162 dri2surf->have_back = TRUE;
163 break;
164 default:
165 desc = NULL;
166 break;
167 }
168
169 if (!desc || dri2surf->textures[natt]) {
170 if (!desc)
171 _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment);
172 else
173 _eglLog(_EGL_WARNING, "both real and fake front buffers are listed");
174 continue;
175 }
176
177 memset(&whandle, 0, sizeof(whandle));
178 whandle.stride = xbuf->pitch;
179 whandle.handle = xbuf->name;
180 dri2surf->textures[natt] = dri2dpy->base.screen->resource_from_handle(
181 dri2dpy->base.screen, &templ, &whandle);
182 if (dri2surf->textures[natt])
183 valid_mask |= 1 << natt;
184 }
185
186 dri2surf->valid_mask = valid_mask;
187 }
188
189 /**
190 * Get the buffers from the server.
191 */
192 static void
193 dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask)
194 {
195 struct dri2_surface *dri2surf = dri2_surface(nsurf);
196 struct dri2_display *dri2dpy = dri2surf->dri2dpy;
197 unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS * 2];
198 int num_ins, num_outs, att;
199 struct x11_drawable_buffer *xbufs;
200 uint bpp = util_format_get_blocksizebits(dri2surf->color_format);
201 boolean with_format = FALSE; /* never ask for depth/stencil */
202
203 /* We must get the front on servers which doesn't support with format
204 * due to a silly bug in core dri2. You can't copy to/from a buffer
205 * that you haven't requested and you recive BadValue errors */
206 if (dri2surf->dri2dpy->dri_minor < 1) {
207 with_format = FALSE;
208 buffer_mask |= (1 << NATIVE_ATTACHMENT_FRONT_LEFT);
209 }
210
211 /* prepare the attachments */
212 num_ins = 0;
213 for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
214 if (native_attachment_mask_test(buffer_mask, att)) {
215 unsigned int dri2att;
216
217 switch (att) {
218 case NATIVE_ATTACHMENT_FRONT_LEFT:
219 dri2att = DRI2BufferFrontLeft;
220 break;
221 case NATIVE_ATTACHMENT_BACK_LEFT:
222 dri2att = DRI2BufferBackLeft;
223 break;
224 case NATIVE_ATTACHMENT_FRONT_RIGHT:
225 dri2att = DRI2BufferFrontRight;
226 break;
227 case NATIVE_ATTACHMENT_BACK_RIGHT:
228 dri2att = DRI2BufferBackRight;
229 break;
230 default:
231 assert(0);
232 dri2att = 0;
233 break;
234 }
235
236 dri2atts[num_ins++] = dri2att;
237 if (with_format)
238 dri2atts[num_ins++] = bpp;
239 }
240 }
241 if (with_format)
242 num_ins /= 2;
243
244 xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable,
245 &dri2surf->width, &dri2surf->height,
246 dri2atts, with_format, num_ins, &num_outs);
247
248 /* we should be able to do better... */
249 if (xbufs && dri2surf->last_num_xbufs == num_outs &&
250 memcmp(dri2surf->last_xbufs, xbufs, sizeof(*xbufs) * num_outs) == 0) {
251 FREE(xbufs);
252 dri2surf->client_stamp = dri2surf->server_stamp;
253 return;
254 }
255
256 dri2_surface_process_drawable_buffers(&dri2surf->base, xbufs, num_outs);
257
258 dri2surf->server_stamp++;
259 dri2surf->client_stamp = dri2surf->server_stamp;
260
261 if (dri2surf->last_xbufs)
262 FREE(dri2surf->last_xbufs);
263 dri2surf->last_xbufs = xbufs;
264 dri2surf->last_num_xbufs = num_outs;
265 }
266
267 /**
268 * Update the buffers of the surface. This is a slow function due to the
269 * round-trip to the server.
270 */
271 static boolean
272 dri2_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask)
273 {
274 struct dri2_surface *dri2surf = dri2_surface(nsurf);
275
276 dri2_surface_get_buffers(&dri2surf->base, buffer_mask);
277
278 return ((dri2surf->valid_mask & buffer_mask) == buffer_mask);
279 }
280
281 /**
282 * Return TRUE if the surface receives DRI2_InvalidateBuffers events.
283 */
284 static INLINE boolean
285 dri2_surface_receive_events(struct native_surface *nsurf)
286 {
287 struct dri2_surface *dri2surf = dri2_surface(nsurf);
288 return (dri2surf->dri2dpy->dri_minor >= 3);
289 }
290
291 static boolean
292 dri2_surface_flush_frontbuffer(struct native_surface *nsurf)
293 {
294 struct dri2_surface *dri2surf = dri2_surface(nsurf);
295 struct dri2_display *dri2dpy = dri2surf->dri2dpy;
296
297 /* copy to real front buffer */
298 if (dri2surf->have_fake)
299 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
300 0, 0, dri2surf->width, dri2surf->height,
301 DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
302
303 /* force buffers to be updated in next validation call */
304 if (!dri2_surface_receive_events(&dri2surf->base)) {
305 dri2surf->server_stamp++;
306 dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
307 &dri2surf->base, dri2surf->server_stamp);
308 }
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 /* copy to front buffer */
320 if (dri2surf->have_back)
321 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
322 0, 0, dri2surf->width, dri2surf->height,
323 DRI2BufferBackLeft, DRI2BufferFrontLeft);
324
325 /* and update fake front buffer */
326 if (dri2surf->have_fake)
327 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
328 0, 0, dri2surf->width, dri2surf->height,
329 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
330
331 /* force buffers to be updated in next validation call */
332 if (!dri2_surface_receive_events(&dri2surf->base)) {
333 dri2surf->server_stamp++;
334 dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
335 &dri2surf->base, dri2surf->server_stamp);
336 }
337
338 return TRUE;
339 }
340
341 static boolean
342 dri2_surface_present(struct native_surface *nsurf,
343 enum native_attachment natt,
344 boolean preserve,
345 uint swap_interval)
346 {
347 boolean ret;
348
349 if (swap_interval)
350 return FALSE;
351
352 switch (natt) {
353 case NATIVE_ATTACHMENT_FRONT_LEFT:
354 ret = dri2_surface_flush_frontbuffer(nsurf);
355 break;
356 case NATIVE_ATTACHMENT_BACK_LEFT:
357 ret = dri2_surface_swap_buffers(nsurf);
358 break;
359 default:
360 ret = FALSE;
361 break;
362 }
363
364 return ret;
365 }
366
367 static boolean
368 dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask,
369 unsigned int *seq_num, struct pipe_resource **textures,
370 int *width, int *height)
371 {
372 struct dri2_surface *dri2surf = dri2_surface(nsurf);
373
374 if (dri2surf->server_stamp != dri2surf->client_stamp ||
375 (dri2surf->valid_mask & attachment_mask) != attachment_mask) {
376 if (!dri2_surface_update_buffers(&dri2surf->base, attachment_mask))
377 return FALSE;
378 }
379
380 if (seq_num)
381 *seq_num = dri2surf->client_stamp;
382
383 if (textures) {
384 int att;
385 for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
386 if (native_attachment_mask_test(attachment_mask, att)) {
387 struct pipe_resource *ptex = dri2surf->textures[att];
388
389 textures[att] = NULL;
390 pipe_resource_reference(&textures[att], ptex);
391 }
392 }
393 }
394
395 if (width)
396 *width = dri2surf->width;
397 if (height)
398 *height = dri2surf->height;
399
400 return TRUE;
401 }
402
403 static void
404 dri2_surface_wait(struct native_surface *nsurf)
405 {
406 struct dri2_surface *dri2surf = dri2_surface(nsurf);
407 struct dri2_display *dri2dpy = dri2surf->dri2dpy;
408
409 if (dri2surf->have_fake) {
410 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
411 0, 0, dri2surf->width, dri2surf->height,
412 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
413 }
414 }
415
416 static void
417 dri2_surface_destroy(struct native_surface *nsurf)
418 {
419 struct dri2_surface *dri2surf = dri2_surface(nsurf);
420 int i;
421
422 if (dri2surf->last_xbufs)
423 FREE(dri2surf->last_xbufs);
424
425 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
426 struct pipe_resource *ptex = dri2surf->textures[i];
427 pipe_resource_reference(&ptex, NULL);
428 }
429
430 if (dri2surf->drawable) {
431 x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr,
432 dri2surf->drawable, FALSE);
433
434 util_hash_table_remove(dri2surf->dri2dpy->surfaces,
435 (void *) dri2surf->drawable);
436 }
437 FREE(dri2surf);
438 }
439
440 static struct dri2_surface *
441 dri2_display_create_surface(struct native_display *ndpy,
442 enum dri2_surface_type type,
443 Drawable drawable,
444 const struct native_config *nconf)
445 {
446 struct dri2_display *dri2dpy = dri2_display(ndpy);
447 struct dri2_config *dri2conf = dri2_config(nconf);
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->type = type;
456 dri2surf->drawable = drawable;
457 dri2surf->color_format = dri2conf->base.color_format;
458
459 dri2surf->base.destroy = dri2_surface_destroy;
460 dri2surf->base.present = dri2_surface_present;
461 dri2surf->base.validate = dri2_surface_validate;
462 dri2surf->base.wait = dri2_surface_wait;
463
464 if (drawable) {
465 x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE);
466 /* initialize the geometry */
467 dri2_surface_update_buffers(&dri2surf->base, 0x0);
468
469 util_hash_table_set(dri2surf->dri2dpy->surfaces,
470 (void *) dri2surf->drawable, (void *) &dri2surf->base);
471 }
472
473 return dri2surf;
474 }
475
476 static struct native_surface *
477 dri2_display_create_window_surface(struct native_display *ndpy,
478 EGLNativeWindowType win,
479 const struct native_config *nconf)
480 {
481 struct dri2_surface *dri2surf;
482
483 dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_WINDOW,
484 (Drawable) win, nconf);
485 return (dri2surf) ? &dri2surf->base : NULL;
486 }
487
488 static struct native_surface *
489 dri2_display_create_pixmap_surface(struct native_display *ndpy,
490 EGLNativePixmapType pix,
491 const struct native_config *nconf)
492 {
493 struct dri2_surface *dri2surf;
494
495 dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_PIXMAP,
496 (Drawable) pix, nconf);
497 return (dri2surf) ? &dri2surf->base : NULL;
498 }
499
500 static int
501 choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32])
502 {
503 int count = 0;
504
505 switch (mode->rgbBits) {
506 case 32:
507 formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
508 formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
509 break;
510 case 24:
511 formats[count++] = PIPE_FORMAT_B8G8R8X8_UNORM;
512 formats[count++] = PIPE_FORMAT_X8R8G8B8_UNORM;
513 formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
514 formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
515 break;
516 case 16:
517 formats[count++] = PIPE_FORMAT_B5G6R5_UNORM;
518 break;
519 default:
520 break;
521 }
522
523 return count;
524 }
525
526 static boolean
527 is_format_supported(struct pipe_screen *screen,
528 enum pipe_format fmt, unsigned sample_count, boolean is_color)
529 {
530 return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D, sample_count,
531 (is_color) ? PIPE_BIND_RENDER_TARGET :
532 PIPE_BIND_DEPTH_STENCIL, 0);
533 }
534
535 static boolean
536 dri2_display_convert_config(struct native_display *ndpy,
537 const __GLcontextModes *mode,
538 struct native_config *nconf)
539 {
540 enum pipe_format formats[32];
541 int num_formats, i;
542 int sample_count = 0;
543
544 if (!(mode->renderType & GLX_RGBA_BIT) || !mode->rgbMode)
545 return FALSE;
546
547 /* only interested in native renderable configs */
548 if (!mode->xRenderable || !mode->drawableType)
549 return FALSE;
550
551 nconf->buffer_mask = 1 << NATIVE_ATTACHMENT_FRONT_LEFT;
552 if (mode->doubleBufferMode)
553 nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_LEFT;
554 if (mode->stereoMode) {
555 nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_FRONT_RIGHT;
556 if (mode->doubleBufferMode)
557 nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_RIGHT;
558 }
559
560 /* choose color format */
561 num_formats = choose_color_format(mode, formats);
562 for (i = 0; i < num_formats; i++) {
563 if (is_format_supported(ndpy->screen, formats[i], sample_count, TRUE)) {
564 nconf->color_format = formats[i];
565 break;
566 }
567 }
568 if (nconf->color_format == PIPE_FORMAT_NONE)
569 return FALSE;
570
571 if (mode->drawableType & GLX_WINDOW_BIT)
572 nconf->window_bit = TRUE;
573 if (mode->drawableType & GLX_PIXMAP_BIT)
574 nconf->pixmap_bit = TRUE;
575
576 nconf->native_visual_id = mode->visualID;
577 nconf->native_visual_type = mode->visualType;
578 nconf->level = mode->level;
579 nconf->samples = mode->samples;
580
581 nconf->slow_config = (mode->visualRating == GLX_SLOW_CONFIG);
582
583 if (mode->transparentPixel == GLX_TRANSPARENT_RGB) {
584 nconf->transparent_rgb = TRUE;
585 nconf->transparent_rgb_values[0] = mode->transparentRed;
586 nconf->transparent_rgb_values[1] = mode->transparentGreen;
587 nconf->transparent_rgb_values[2] = mode->transparentBlue;
588 }
589
590 return TRUE;
591 }
592
593 static const struct native_config **
594 dri2_display_get_configs(struct native_display *ndpy, int *num_configs)
595 {
596 struct dri2_display *dri2dpy = dri2_display(ndpy);
597 const struct native_config **configs;
598 int i;
599
600 /* first time */
601 if (!dri2dpy->configs) {
602 const __GLcontextModes *modes;
603 int num_modes, count;
604
605 modes = x11_screen_get_glx_configs(dri2dpy->xscr);
606 if (!modes)
607 return NULL;
608 num_modes = x11_context_modes_count(modes);
609
610 dri2dpy->configs = CALLOC(num_modes, sizeof(*dri2dpy->configs));
611 if (!dri2dpy->configs)
612 return NULL;
613
614 count = 0;
615 for (i = 0; i < num_modes; i++) {
616 struct native_config *nconf = &dri2dpy->configs[count].base;
617 if (dri2_display_convert_config(&dri2dpy->base, modes, nconf))
618 count++;
619 modes = modes->next;
620 }
621
622 dri2dpy->num_configs = count;
623 }
624
625 configs = MALLOC(dri2dpy->num_configs * sizeof(*configs));
626 if (configs) {
627 for (i = 0; i < dri2dpy->num_configs; i++)
628 configs[i] = (const struct native_config *) &dri2dpy->configs[i];
629 if (num_configs)
630 *num_configs = dri2dpy->num_configs;
631 }
632
633 return configs;
634 }
635
636 static boolean
637 dri2_display_is_pixmap_supported(struct native_display *ndpy,
638 EGLNativePixmapType pix,
639 const struct native_config *nconf)
640 {
641 struct dri2_display *dri2dpy = dri2_display(ndpy);
642 uint depth, nconf_depth;
643
644 depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix);
645 nconf_depth = util_format_get_blocksizebits(nconf->color_format);
646
647 /* simple depth match for now */
648 return (depth == nconf_depth || (depth == 24 && depth + 8 == nconf_depth));
649 }
650
651 static int
652 dri2_display_get_param(struct native_display *ndpy,
653 enum native_param_type param)
654 {
655 int val;
656
657 switch (param) {
658 case NATIVE_PARAM_USE_NATIVE_BUFFER:
659 /* DRI2GetBuffers uses the native buffers */
660 val = TRUE;
661 break;
662 case NATIVE_PARAM_PRESERVE_BUFFER:
663 /* DRI2CopyRegion is used */
664 val = TRUE;
665 break;
666 case NATIVE_PARAM_MAX_SWAP_INTERVAL:
667 default:
668 val = 0;
669 break;
670 }
671
672 return val;
673 }
674
675 static void
676 dri2_display_destroy(struct native_display *ndpy)
677 {
678 struct dri2_display *dri2dpy = dri2_display(ndpy);
679
680 if (dri2dpy->configs)
681 FREE(dri2dpy->configs);
682
683 if (dri2dpy->base.screen)
684 dri2dpy->base.screen->destroy(dri2dpy->base.screen);
685
686 if (dri2dpy->surfaces)
687 util_hash_table_destroy(dri2dpy->surfaces);
688
689 if (dri2dpy->xscr)
690 x11_screen_destroy(dri2dpy->xscr);
691 if (dri2dpy->own_dpy)
692 XCloseDisplay(dri2dpy->dpy);
693 FREE(dri2dpy);
694 }
695
696 static void
697 dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable,
698 void *user_data)
699 {
700 struct native_display *ndpy = (struct native_display* ) user_data;
701 struct dri2_display *dri2dpy = dri2_display(ndpy);
702 struct native_surface *nsurf;
703 struct dri2_surface *dri2surf;
704
705 nsurf = (struct native_surface *)
706 util_hash_table_get(dri2dpy->surfaces, (void *) drawable);
707 if (!nsurf)
708 return;
709
710 dri2surf = dri2_surface(nsurf);
711
712 dri2surf->server_stamp++;
713 dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
714 &dri2surf->base, dri2surf->server_stamp);
715 }
716
717 /**
718 * Initialize DRI2 and pipe screen.
719 */
720 static boolean
721 dri2_display_init_screen(struct native_display *ndpy)
722 {
723 struct dri2_display *dri2dpy = dri2_display(ndpy);
724 int fd;
725
726 if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) ||
727 !x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_GLX)) {
728 _eglLog(_EGL_WARNING, "GLX/DRI2 is not supported");
729 return FALSE;
730 }
731
732 dri2dpy->dri_driver = x11_screen_probe_dri2(dri2dpy->xscr,
733 &dri2dpy->dri_major, &dri2dpy->dri_minor);
734
735 fd = x11_screen_enable_dri2(dri2dpy->xscr,
736 dri2_display_invalidate_buffers, &dri2dpy->base);
737 if (fd < 0)
738 return FALSE;
739
740 dri2dpy->base.screen =
741 dri2dpy->event_handler->new_drm_screen(&dri2dpy->base,
742 dri2dpy->dri_driver, fd);
743 if (!dri2dpy->base.screen) {
744 _eglLog(_EGL_WARNING, "failed to create DRM screen");
745 return FALSE;
746 }
747
748 return TRUE;
749 }
750
751 static unsigned
752 dri2_display_hash_table_hash(void *key)
753 {
754 XID drawable = pointer_to_uintptr(key);
755 return (unsigned) drawable;
756 }
757
758 static int
759 dri2_display_hash_table_compare(void *key1, void *key2)
760 {
761 return (key1 - key2);
762 }
763
764 struct native_display *
765 x11_create_dri2_display(Display *dpy,
766 struct native_event_handler *event_handler,
767 void *user_data)
768 {
769 struct dri2_display *dri2dpy;
770
771 dri2dpy = CALLOC_STRUCT(dri2_display);
772 if (!dri2dpy)
773 return NULL;
774
775 dri2dpy->event_handler = event_handler;
776 dri2dpy->base.user_data = user_data;
777
778 dri2dpy->dpy = dpy;
779 if (!dri2dpy->dpy) {
780 dri2dpy->dpy = XOpenDisplay(NULL);
781 if (!dri2dpy->dpy) {
782 dri2_display_destroy(&dri2dpy->base);
783 return NULL;
784 }
785 dri2dpy->own_dpy = TRUE;
786 }
787
788 dri2dpy->xscr_number = DefaultScreen(dri2dpy->dpy);
789 dri2dpy->xscr = x11_screen_create(dri2dpy->dpy, dri2dpy->xscr_number);
790 if (!dri2dpy->xscr) {
791 dri2_display_destroy(&dri2dpy->base);
792 return NULL;
793 }
794
795 if (!dri2_display_init_screen(&dri2dpy->base)) {
796 dri2_display_destroy(&dri2dpy->base);
797 return NULL;
798 }
799
800 dri2dpy->surfaces = util_hash_table_create(dri2_display_hash_table_hash,
801 dri2_display_hash_table_compare);
802 if (!dri2dpy->surfaces) {
803 dri2_display_destroy(&dri2dpy->base);
804 return NULL;
805 }
806
807 dri2dpy->base.destroy = dri2_display_destroy;
808 dri2dpy->base.get_param = dri2_display_get_param;
809 dri2dpy->base.get_configs = dri2_display_get_configs;
810 dri2dpy->base.is_pixmap_supported = dri2_display_is_pixmap_supported;
811 dri2dpy->base.create_window_surface = dri2_display_create_window_surface;
812 dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface;
813
814 return &dri2dpy->base;
815 }
816
817 #else /* GLX_DIRECT_RENDERING */
818
819 struct native_display *
820 x11_create_dri2_display(Display *dpy,
821 struct native_event_handler *event_handler,
822 void *user_data)
823 {
824 return NULL;
825 }
826
827 #endif /* GLX_DIRECT_RENDERING */