native_dri2.c revision ed47d65c7c05d7dd5a5b4cafaa32afbd4fff0bef
1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Mesa 3-D graphics library
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Version:  7.8
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Permission is hereby granted, free of charge, to any person obtaining a
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * copy of this software and associated documentation files (the "Software"),
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * to deal in the Software without restriction, including without limitation
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * and/or sell copies of the Software, and to permit persons to whom the
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Software is furnished to do so, subject to the following conditions:
13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * The above copyright notice and this permission notice shall be included
15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in all copies or substantial portions of the Software.
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
170c836bfad33cbd3517e2c145cc24241fb98967d8pbos@webrtc.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
180c836bfad33cbd3517e2c145cc24241fb98967d8pbos@webrtc.org * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
190c836bfad33cbd3517e2c145cc24241fb98967d8pbos@webrtc.org * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * DEALINGS IN THE SOFTWARE.
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "util/u_memory.h"
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "util/u_math.h"
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "util/u_format.h"
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "util/u_inlines.h"
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "util/u_hash_table.h"
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "pipe/p_compiler.h"
32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "pipe/p_screen.h"
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "pipe/p_context.h"
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "pipe/p_state.h"
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "state_tracker/drm_driver.h"
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "egllog.h"
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "native_x11.h"
39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "x11_screen.h"
40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "common/native_helper.h"
42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef HAVE_WAYLAND_BACKEND
43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "common/native_wayland_drm_bufmgr_helper.h"
44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif
45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef GLX_DIRECT_RENDERING
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstruct dri2_display {
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   struct native_display base;
5074f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org   Display *dpy;
5174f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org   boolean own_dpy;
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
5374f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org   const struct native_event_handler *event_handler;
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   struct x11_screen *xscr;
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   int xscr_number;
5774f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org   const char *dri_driver;
58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   int dri_major, dri_minor;
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   struct dri2_config *configs;
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   int num_configs;
62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   struct util_hash_table *surfaces;
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef HAVE_WAYLAND_BACKEND
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   struct wl_drm *wl_server_drm; /* for EGL_WL_bind_wayland_display */
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org};
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstruct dri2_surface {
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   struct native_surface base;
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   Drawable drawable;
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   enum pipe_format color_format;
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   struct dri2_display *dri2dpy;
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
7574f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org   unsigned int server_stamp;
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   unsigned int client_stamp;
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   int width, height;
78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS];
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   uint valid_mask;
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   boolean have_back, have_fake;
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   struct x11_drawable_buffer *last_xbufs;
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   int last_num_xbufs;
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org};
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstruct dri2_config {
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   struct native_config base;
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org};
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic INLINE struct dri2_display *
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgdri2_display(const struct native_display *ndpy)
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   return (struct dri2_display *) ndpy;
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
9774f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.orgstatic INLINE struct dri2_surface *
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgdri2_surface(const struct native_surface *nsurf)
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   return (struct dri2_surface *) nsurf;
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic INLINE struct dri2_config *
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgdri2_config(const struct native_config *nconf)
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   return (struct dri2_config *) nconf;
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/**
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Process the buffers returned by the server.
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic void
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgdri2_surface_process_drawable_buffers(struct native_surface *nsurf,
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      struct x11_drawable_buffer *xbufs,
11574f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org                                      int num_xbufs)
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   struct dri2_surface *dri2surf = dri2_surface(nsurf);
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   struct dri2_display *dri2dpy = dri2surf->dri2dpy;
119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   struct pipe_resource templ;
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   struct winsys_handle whandle;
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   uint valid_mask;
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   int i;
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   /* free the old textures */
12574f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org   for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++)
12674f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org      pipe_resource_reference(&dri2surf->textures[i], NULL);
12774f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org   dri2surf->valid_mask = 0x0;
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   dri2surf->have_back = FALSE;
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   dri2surf->have_fake = FALSE;
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   if (!xbufs)
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return;
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   memset(&templ, 0, sizeof(templ));
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   templ.target = PIPE_TEXTURE_2D;
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   templ.last_level = 0;
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   templ.width0 = dri2surf->width;
139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   templ.height0 = dri2surf->height;
140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   templ.depth0 = 1;
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   templ.array_size = 1;
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   templ.format = dri2surf->color_format;
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   templ.bind = PIPE_BIND_RENDER_TARGET;
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   valid_mask = 0x0;
146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   for (i = 0; i < num_xbufs; i++) {
147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      struct x11_drawable_buffer *xbuf = &xbufs[i];
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      const char *desc;
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      enum native_attachment natt;
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      switch (xbuf->attachment) {
152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      case DRI2BufferFrontLeft:
153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         natt = NATIVE_ATTACHMENT_FRONT_LEFT;
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         desc = "DRI2 Front Buffer";
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         break;
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      case DRI2BufferFakeFrontLeft:
157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         natt = NATIVE_ATTACHMENT_FRONT_LEFT;
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         desc = "DRI2 Fake Front Buffer";
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         dri2surf->have_fake = TRUE;
16074f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org         break;
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      case DRI2BufferBackLeft:
16274f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org         natt = NATIVE_ATTACHMENT_BACK_LEFT;
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         desc = "DRI2 Back Buffer";
164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         dri2surf->have_back = TRUE;
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         break;
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      default:
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         desc = NULL;
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         break;
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (!desc || dri2surf->textures[natt]) {
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         if (!desc)
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment);
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         else
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            _eglLog(_EGL_WARNING, "both real and fake front buffers are listed");
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         continue;
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      memset(&whandle, 0, sizeof(whandle));
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      whandle.stride = xbuf->pitch;
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      whandle.handle = xbuf->name;
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      dri2surf->textures[natt] = dri2dpy->base.screen->resource_from_handle(
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         dri2dpy->base.screen, &templ, &whandle);
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (dri2surf->textures[natt])
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         valid_mask |= 1 << natt;
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   }
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   dri2surf->valid_mask = valid_mask;
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/**
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Get the buffers from the server.
193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic void
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgdri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask)
196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1973b89e10f31160da35b408fd00cb8f89d2b08862dpbos@webrtc.org   struct dri2_surface *dri2surf = dri2_surface(nsurf);
198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   struct dri2_display *dri2dpy = dri2surf->dri2dpy;
199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   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 */
273static boolean
274dri2_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 */
286static INLINE boolean
287dri2_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
293static boolean
294dri2_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
315static boolean
316dri2_surface_swap_buffers(struct native_surface *nsurf)
317{
318   struct dri2_surface *dri2surf = dri2_surface(nsurf);
319   struct dri2_display *dri2dpy = dri2surf->dri2dpy;
320
321   /* copy to front buffer */
322   if (dri2surf->have_back)
323      x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
324            0, 0, dri2surf->width, dri2surf->height,
325            DRI2BufferBackLeft, DRI2BufferFrontLeft);
326
327   /* and update fake front buffer */
328   if (dri2surf->have_fake)
329      x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
330            0, 0, dri2surf->width, dri2surf->height,
331            DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
332
333   /* force buffers to be updated in next validation call */
334   if (!dri2_surface_receive_events(&dri2surf->base)) {
335      dri2surf->server_stamp++;
336      dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
337            &dri2surf->base, dri2surf->server_stamp);
338   }
339
340   return TRUE;
341}
342
343static boolean
344dri2_surface_present(struct native_surface *nsurf,
345                     enum native_attachment natt,
346                     boolean preserve,
347                     uint swap_interval)
348{
349   boolean ret;
350
351   if (swap_interval)
352      return FALSE;
353
354   switch (natt) {
355   case NATIVE_ATTACHMENT_FRONT_LEFT:
356      ret = dri2_surface_flush_frontbuffer(nsurf);
357      break;
358   case NATIVE_ATTACHMENT_BACK_LEFT:
359      ret = dri2_surface_swap_buffers(nsurf);
360      break;
361   default:
362      ret = FALSE;
363      break;
364   }
365
366   return ret;
367}
368
369static boolean
370dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask,
371                      unsigned int *seq_num, struct pipe_resource **textures,
372                      int *width, int *height)
373{
374   struct dri2_surface *dri2surf = dri2_surface(nsurf);
375
376   if (dri2surf->server_stamp != dri2surf->client_stamp ||
377       (dri2surf->valid_mask & attachment_mask) != attachment_mask) {
378      if (!dri2_surface_update_buffers(&dri2surf->base, attachment_mask))
379         return FALSE;
380   }
381
382   if (seq_num)
383      *seq_num = dri2surf->client_stamp;
384
385   if (textures) {
386      int att;
387      for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
388         if (native_attachment_mask_test(attachment_mask, att)) {
389            struct pipe_resource *ptex = dri2surf->textures[att];
390
391            textures[att] = NULL;
392            pipe_resource_reference(&textures[att], ptex);
393         }
394      }
395   }
396
397   if (width)
398      *width = dri2surf->width;
399   if (height)
400      *height = dri2surf->height;
401
402   return TRUE;
403}
404
405static void
406dri2_surface_wait(struct native_surface *nsurf)
407{
408   struct dri2_surface *dri2surf = dri2_surface(nsurf);
409   struct dri2_display *dri2dpy = dri2surf->dri2dpy;
410
411   if (dri2surf->have_fake) {
412      x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
413            0, 0, dri2surf->width, dri2surf->height,
414            DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
415   }
416}
417
418static void
419dri2_surface_destroy(struct native_surface *nsurf)
420{
421   struct dri2_surface *dri2surf = dri2_surface(nsurf);
422   int i;
423
424   if (dri2surf->last_xbufs)
425      FREE(dri2surf->last_xbufs);
426
427   for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
428      struct pipe_resource *ptex = dri2surf->textures[i];
429      pipe_resource_reference(&ptex, NULL);
430   }
431
432   if (dri2surf->drawable) {
433      x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr,
434            dri2surf->drawable, FALSE);
435
436      util_hash_table_remove(dri2surf->dri2dpy->surfaces,
437            (void *) dri2surf->drawable);
438   }
439   FREE(dri2surf);
440}
441
442static struct dri2_surface *
443dri2_display_create_surface(struct native_display *ndpy,
444                            Drawable drawable,
445                            enum pipe_format color_format)
446{
447   struct dri2_display *dri2dpy = dri2_display(ndpy);
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->drawable = drawable;
456   dri2surf->color_format = color_format;
457
458   dri2surf->base.destroy = dri2_surface_destroy;
459   dri2surf->base.present = dri2_surface_present;
460   dri2surf->base.validate = dri2_surface_validate;
461   dri2surf->base.wait = dri2_surface_wait;
462
463   if (drawable) {
464      x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE);
465      /* initialize the geometry */
466      dri2_surface_update_buffers(&dri2surf->base, 0x0);
467
468      util_hash_table_set(dri2surf->dri2dpy->surfaces,
469            (void *) dri2surf->drawable, (void *) &dri2surf->base);
470   }
471
472   return dri2surf;
473}
474
475static struct native_surface *
476dri2_display_create_window_surface(struct native_display *ndpy,
477                                   EGLNativeWindowType win,
478                                   const struct native_config *nconf)
479{
480   struct dri2_surface *dri2surf;
481
482   dri2surf = dri2_display_create_surface(ndpy,
483         (Drawable) win, nconf->color_format);
484   return (dri2surf) ? &dri2surf->base : NULL;
485}
486
487static struct native_surface *
488dri2_display_create_pixmap_surface(struct native_display *ndpy,
489                                   EGLNativePixmapType pix,
490                                   const struct native_config *nconf)
491{
492   struct dri2_surface *dri2surf;
493
494   if (!nconf) {
495      struct dri2_display *dri2dpy = dri2_display(ndpy);
496      uint depth, nconf_depth;
497      int i;
498
499      depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix);
500      for (i = 0; i < dri2dpy->num_configs; i++) {
501         nconf_depth = util_format_get_blocksizebits(
502               dri2dpy->configs[i].base.color_format);
503         /* simple depth match for now */
504         if (depth == nconf_depth ||
505             (depth == 24 && depth + 8 == nconf_depth)) {
506            nconf = &dri2dpy->configs[i].base;
507            break;
508         }
509      }
510
511      if (!nconf)
512         return NULL;
513   }
514
515   dri2surf = dri2_display_create_surface(ndpy,
516         (Drawable) pix, nconf->color_format);
517   return (dri2surf) ? &dri2surf->base : NULL;
518}
519
520static int
521choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32])
522{
523   int count = 0;
524
525   switch (mode->rgbBits) {
526   case 32:
527      formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
528      formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
529      break;
530   case 24:
531      formats[count++] = PIPE_FORMAT_B8G8R8X8_UNORM;
532      formats[count++] = PIPE_FORMAT_X8R8G8B8_UNORM;
533      formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
534      formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
535      break;
536   case 16:
537      formats[count++] = PIPE_FORMAT_B5G6R5_UNORM;
538      break;
539   default:
540      break;
541   }
542
543   return count;
544}
545
546static boolean
547is_format_supported(struct pipe_screen *screen,
548                    enum pipe_format fmt, unsigned sample_count, boolean is_color)
549{
550   return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D, sample_count,
551         (is_color) ? PIPE_BIND_RENDER_TARGET :
552         PIPE_BIND_DEPTH_STENCIL);
553}
554
555static boolean
556dri2_display_convert_config(struct native_display *ndpy,
557                            const __GLcontextModes *mode,
558                            struct native_config *nconf)
559{
560   enum pipe_format formats[32];
561   int num_formats, i;
562   int sample_count = 0;
563
564   if (!(mode->renderType & GLX_RGBA_BIT) || !mode->rgbMode)
565      return FALSE;
566
567   /* only interested in native renderable configs */
568   if (!mode->xRenderable || !mode->drawableType)
569      return FALSE;
570
571   /* fast/slow configs are probably not relevant */
572   if (mode->visualRating == GLX_SLOW_CONFIG)
573      return FALSE;
574
575   nconf->buffer_mask = 1 << NATIVE_ATTACHMENT_FRONT_LEFT;
576   if (mode->doubleBufferMode)
577      nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_LEFT;
578   if (mode->stereoMode) {
579      nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_FRONT_RIGHT;
580      if (mode->doubleBufferMode)
581         nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_RIGHT;
582   }
583
584   /* choose color format */
585   num_formats = choose_color_format(mode, formats);
586   for (i = 0; i < num_formats; i++) {
587      if (is_format_supported(ndpy->screen, formats[i], sample_count, TRUE)) {
588         nconf->color_format = formats[i];
589         break;
590      }
591   }
592   if (nconf->color_format == PIPE_FORMAT_NONE)
593      return FALSE;
594
595   if ((mode->drawableType & GLX_WINDOW_BIT) && mode->visualID)
596      nconf->window_bit = TRUE;
597   if (mode->drawableType & GLX_PIXMAP_BIT)
598      nconf->pixmap_bit = TRUE;
599
600   nconf->native_visual_id = mode->visualID;
601   switch (mode->visualType) {
602   case GLX_TRUE_COLOR:
603      nconf->native_visual_type = TrueColor;
604      break;
605   case GLX_DIRECT_COLOR:
606      nconf->native_visual_type = DirectColor;
607      break;
608   case GLX_PSEUDO_COLOR:
609      nconf->native_visual_type = PseudoColor;
610      break;
611   case GLX_STATIC_COLOR:
612      nconf->native_visual_type = StaticColor;
613      break;
614   case GLX_GRAY_SCALE:
615      nconf->native_visual_type = GrayScale;
616      break;
617   case GLX_STATIC_GRAY:
618      nconf->native_visual_type = StaticGray;
619      break;
620   }
621   nconf->level = mode->level;
622
623   if (mode->transparentPixel == GLX_TRANSPARENT_RGB) {
624      nconf->transparent_rgb = TRUE;
625      nconf->transparent_rgb_values[0] = mode->transparentRed;
626      nconf->transparent_rgb_values[1] = mode->transparentGreen;
627      nconf->transparent_rgb_values[2] = mode->transparentBlue;
628   }
629
630   return TRUE;
631}
632
633static const struct native_config **
634dri2_display_get_configs(struct native_display *ndpy, int *num_configs)
635{
636   struct dri2_display *dri2dpy = dri2_display(ndpy);
637   const struct native_config **configs;
638   int i;
639
640   /* first time */
641   if (!dri2dpy->configs) {
642      const __GLcontextModes *modes;
643      int num_modes, count;
644
645      modes = x11_screen_get_glx_configs(dri2dpy->xscr);
646      if (!modes)
647         return NULL;
648      num_modes = x11_context_modes_count(modes);
649
650      dri2dpy->configs = CALLOC(num_modes, sizeof(*dri2dpy->configs));
651      if (!dri2dpy->configs)
652         return NULL;
653
654      count = 0;
655      for (i = 0; i < num_modes; i++) {
656         struct native_config *nconf = &dri2dpy->configs[count].base;
657
658         if (dri2_display_convert_config(&dri2dpy->base, modes, nconf)) {
659            int j;
660            /* look for duplicates */
661            for (j = 0; j < count; j++) {
662               if (memcmp(&dri2dpy->configs[j], nconf, sizeof(*nconf)) == 0)
663                  break;
664            }
665            if (j == count)
666               count++;
667         }
668         modes = modes->next;
669      }
670
671      dri2dpy->num_configs = count;
672   }
673
674   configs = MALLOC(dri2dpy->num_configs * sizeof(*configs));
675   if (configs) {
676      for (i = 0; i < dri2dpy->num_configs; i++)
677         configs[i] = (const struct native_config *) &dri2dpy->configs[i];
678      if (num_configs)
679         *num_configs = dri2dpy->num_configs;
680   }
681
682   return configs;
683}
684
685static boolean
686dri2_display_get_pixmap_format(struct native_display *ndpy,
687                               EGLNativePixmapType pix,
688                               enum pipe_format *format)
689{
690   struct dri2_display *dri2dpy = dri2_display(ndpy);
691   boolean ret = EGL_TRUE;
692   uint depth;
693
694   depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix);
695   switch (depth) {
696   case 32:
697   case 24:
698      *format = PIPE_FORMAT_B8G8R8A8_UNORM;
699      break;
700   case 16:
701      *format = PIPE_FORMAT_B5G6R5_UNORM;
702      break;
703   default:
704      *format = PIPE_FORMAT_NONE;
705      ret = EGL_FALSE;
706      break;
707   }
708
709   return ret;
710}
711
712static int
713dri2_display_get_param(struct native_display *ndpy,
714                       enum native_param_type param)
715{
716   int val;
717
718   switch (param) {
719   case NATIVE_PARAM_USE_NATIVE_BUFFER:
720      /* DRI2GetBuffers uses the native buffers */
721      val = TRUE;
722      break;
723   case NATIVE_PARAM_PRESERVE_BUFFER:
724      /* DRI2CopyRegion is used */
725      val = TRUE;
726      break;
727   case NATIVE_PARAM_MAX_SWAP_INTERVAL:
728   default:
729      val = 0;
730      break;
731   }
732
733   return val;
734}
735
736static void
737dri2_display_destroy(struct native_display *ndpy)
738{
739   struct dri2_display *dri2dpy = dri2_display(ndpy);
740
741   if (dri2dpy->configs)
742      FREE(dri2dpy->configs);
743
744   if (dri2dpy->base.screen)
745      dri2dpy->base.screen->destroy(dri2dpy->base.screen);
746
747   if (dri2dpy->surfaces)
748      util_hash_table_destroy(dri2dpy->surfaces);
749
750   if (dri2dpy->xscr)
751      x11_screen_destroy(dri2dpy->xscr);
752   if (dri2dpy->own_dpy)
753      XCloseDisplay(dri2dpy->dpy);
754   FREE(dri2dpy);
755}
756
757static void
758dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable,
759                                void *user_data)
760{
761   struct native_display *ndpy = (struct native_display* ) user_data;
762   struct dri2_display *dri2dpy = dri2_display(ndpy);
763   struct native_surface *nsurf;
764   struct dri2_surface *dri2surf;
765
766   nsurf = (struct native_surface *)
767      util_hash_table_get(dri2dpy->surfaces, (void *) drawable);
768   if (!nsurf)
769      return;
770
771   dri2surf = dri2_surface(nsurf);
772
773   dri2surf->server_stamp++;
774   dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
775         &dri2surf->base, dri2surf->server_stamp);
776}
777
778/**
779 * Initialize DRI2 and pipe screen.
780 */
781static boolean
782dri2_display_init_screen(struct native_display *ndpy)
783{
784   struct dri2_display *dri2dpy = dri2_display(ndpy);
785   int fd;
786
787   if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) ||
788       !x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_GLX)) {
789      _eglLog(_EGL_WARNING, "GLX/DRI2 is not supported");
790      return FALSE;
791   }
792
793   dri2dpy->dri_driver = x11_screen_probe_dri2(dri2dpy->xscr,
794         &dri2dpy->dri_major, &dri2dpy->dri_minor);
795
796   fd = x11_screen_enable_dri2(dri2dpy->xscr,
797         dri2_display_invalidate_buffers, &dri2dpy->base);
798   if (fd < 0)
799      return FALSE;
800
801   dri2dpy->base.screen =
802      dri2dpy->event_handler->new_drm_screen(&dri2dpy->base,
803            dri2dpy->dri_driver, fd);
804   if (!dri2dpy->base.screen) {
805      _eglLog(_EGL_DEBUG, "failed to create DRM screen");
806      return FALSE;
807   }
808
809   return TRUE;
810}
811
812static unsigned
813dri2_display_hash_table_hash(void *key)
814{
815   XID drawable = pointer_to_uintptr(key);
816   return (unsigned) drawable;
817}
818
819static int
820dri2_display_hash_table_compare(void *key1, void *key2)
821{
822   return ((char *) key1 - (char *) key2);
823}
824
825static int
826dri2_display_authenticate(void *user_data, uint32_t magic)
827{
828   struct native_display *ndpy = user_data;
829   struct dri2_display *dri2dpy = dri2_display(ndpy);
830
831   return x11_screen_authenticate(dri2dpy->xscr, magic);
832}
833
834#ifdef HAVE_WAYLAND_BACKEND
835
836static struct wayland_drm_callbacks wl_drm_callbacks = {
837   dri2_display_authenticate,
838   egl_g3d_wl_drm_helper_reference_buffer,
839   egl_g3d_wl_drm_helper_unreference_buffer
840};
841
842static boolean
843dri2_display_bind_wayland_display(struct native_display *ndpy,
844                                  struct wl_display *wl_dpy)
845{
846   struct dri2_display *dri2dpy = dri2_display(ndpy);
847
848   if (dri2dpy->wl_server_drm)
849      return FALSE;
850
851   dri2dpy->wl_server_drm = wayland_drm_init(wl_dpy,
852         x11_screen_get_device_name(dri2dpy->xscr),
853         &wl_drm_callbacks, ndpy);
854
855   if (!dri2dpy->wl_server_drm)
856      return FALSE;
857
858   return TRUE;
859}
860
861static boolean
862dri2_display_unbind_wayland_display(struct native_display *ndpy,
863                                    struct wl_display *wl_dpy)
864{
865   struct dri2_display *dri2dpy = dri2_display(ndpy);
866
867   if (!dri2dpy->wl_server_drm)
868      return FALSE;
869
870   wayland_drm_uninit(dri2dpy->wl_server_drm);
871   dri2dpy->wl_server_drm = NULL;
872
873   return TRUE;
874}
875
876static struct native_display_wayland_bufmgr dri2_display_wayland_bufmgr = {
877   dri2_display_bind_wayland_display,
878   dri2_display_unbind_wayland_display,
879   egl_g3d_wl_drm_common_wl_buffer_get_resource
880};
881
882#endif /* HAVE_WAYLAND_BACKEND */
883
884struct native_display *
885x11_create_dri2_display(Display *dpy,
886                        const struct native_event_handler *event_handler)
887{
888   struct dri2_display *dri2dpy;
889
890   dri2dpy = CALLOC_STRUCT(dri2_display);
891   if (!dri2dpy)
892      return NULL;
893
894   dri2dpy->event_handler = event_handler;
895
896   dri2dpy->dpy = dpy;
897   if (!dri2dpy->dpy) {
898      dri2dpy->dpy = XOpenDisplay(NULL);
899      if (!dri2dpy->dpy) {
900         dri2_display_destroy(&dri2dpy->base);
901         return NULL;
902      }
903      dri2dpy->own_dpy = TRUE;
904   }
905
906   dri2dpy->xscr_number = DefaultScreen(dri2dpy->dpy);
907   dri2dpy->xscr = x11_screen_create(dri2dpy->dpy, dri2dpy->xscr_number);
908   if (!dri2dpy->xscr) {
909      dri2_display_destroy(&dri2dpy->base);
910      return NULL;
911   }
912
913   dri2dpy->surfaces = util_hash_table_create(dri2_display_hash_table_hash,
914         dri2_display_hash_table_compare);
915   if (!dri2dpy->surfaces) {
916      dri2_display_destroy(&dri2dpy->base);
917      return NULL;
918   }
919
920   dri2dpy->base.init_screen = dri2_display_init_screen;
921   dri2dpy->base.destroy = dri2_display_destroy;
922   dri2dpy->base.get_param = dri2_display_get_param;
923   dri2dpy->base.get_configs = dri2_display_get_configs;
924   dri2dpy->base.get_pixmap_format = dri2_display_get_pixmap_format;
925   dri2dpy->base.copy_to_pixmap = native_display_copy_to_pixmap;
926   dri2dpy->base.create_window_surface = dri2_display_create_window_surface;
927   dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface;
928#ifdef HAVE_WAYLAND_BACKEND
929   dri2dpy->base.wayland_bufmgr = &dri2_display_wayland_bufmgr;
930#endif
931
932   return &dri2dpy->base;
933}
934
935#else /* GLX_DIRECT_RENDERING */
936
937struct native_display *
938x11_create_dri2_display(Display *dpy,
939                        const struct native_event_handler *event_handler)
940{
941   return NULL;
942}
943
944#endif /* GLX_DIRECT_RENDERING */
945