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