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