platform_wayland.c revision 6b369c4c7cd8a52f99bbff2a57fb316b33a87495
1/*
2 * Copyright © 2011 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 *    Kristian Høgsberg <krh@bitplanet.net>
26 *    Benjamin Franzke <benjaminfranzke@googlemail.com>
27 */
28
29#include <stdlib.h>
30#include <string.h>
31#include <limits.h>
32#include <dlfcn.h>
33#include <errno.h>
34#include <unistd.h>
35
36#include "egl_dri2.h"
37
38#include <wayland-client.h>
39#include "wayland-drm-client-protocol.h"
40
41static void
42sync_callback(void *data)
43{
44   int *done = data;
45
46   *done = 1;
47}
48
49static void
50force_roundtrip(struct wl_display *display)
51{
52   int done = 0;
53
54   wl_display_sync_callback(display, sync_callback, &done);
55   wl_display_iterate(display, WL_DISPLAY_WRITABLE);
56   while (!done)
57      wl_display_iterate(display, WL_DISPLAY_READABLE);
58}
59
60
61/**
62 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
63 */
64static _EGLSurface *
65dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
66		    _EGLConfig *conf, EGLNativeWindowType window,
67		    const EGLint *attrib_list)
68{
69   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
70   struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
71   struct dri2_egl_surface *dri2_surf;
72   struct dri2_egl_buffer *dri2_buf;
73   int i;
74
75   (void) drv;
76
77   dri2_surf = malloc(sizeof *dri2_surf);
78   if (!dri2_surf) {
79      _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
80      return NULL;
81   }
82
83   if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
84      goto cleanup_surf;
85
86   for (i = 0; i < WL_BUFFER_COUNT; ++i)
87      dri2_surf->wl_drm_buffer[i] = NULL;
88
89   for (i = 0; i < __DRI_BUFFER_COUNT; ++i)
90      dri2_surf->dri_buffers[i] = NULL;
91
92   dri2_surf->pending_buffer = NULL;
93   dri2_surf->block_swap_buffers = EGL_FALSE;
94
95   switch (type) {
96   case EGL_WINDOW_BIT:
97      dri2_surf->wl_win = (struct wl_egl_window *) window;
98      dri2_surf->type = DRI2_WINDOW_SURFACE;
99
100      dri2_surf->base.Width =  -1;
101      dri2_surf->base.Height = -1;
102      break;
103   case EGL_PIXMAP_BIT:
104      dri2_surf->wl_pix = (struct wl_egl_pixmap *) window;
105      dri2_surf->type = DRI2_PIXMAP_SURFACE;
106
107      dri2_surf->base.Width  = dri2_surf->wl_pix->width;
108      dri2_surf->base.Height = dri2_surf->wl_pix->height;
109
110      if (dri2_surf->wl_pix->name > 0) {
111         dri2_buf = dri2_surf->wl_pix->driver_private;
112         dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT] = dri2_buf->dri_buffer;
113      }
114      break;
115   default:
116      goto cleanup_surf;
117   }
118
119   dri2_surf->dri_drawable =
120      (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
121					    type == EGL_WINDOW_BIT ?
122					    dri2_conf->dri_double_config :
123					    dri2_conf->dri_single_config,
124					    dri2_surf);
125   if (dri2_surf->dri_drawable == NULL) {
126      _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
127      goto cleanup_dri_drawable;
128   }
129
130   return &dri2_surf->base;
131
132 cleanup_dri_drawable:
133   dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
134 cleanup_surf:
135   free(dri2_surf);
136
137   return NULL;
138}
139
140/**
141 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
142 */
143static _EGLSurface *
144dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
145			   _EGLConfig *conf, EGLNativeWindowType window,
146			   const EGLint *attrib_list)
147{
148   return dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
149			      window, attrib_list);
150}
151
152static _EGLSurface *
153dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
154			   _EGLConfig *conf, EGLNativePixmapType pixmap,
155			   const EGLint *attrib_list)
156{
157   return dri2_create_surface(drv, disp, EGL_PIXMAP_BIT, conf,
158			      pixmap, attrib_list);
159}
160
161/**
162 * Called via eglDestroySurface(), drv->API.DestroySurface().
163 */
164static EGLBoolean
165dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
166{
167   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
168   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
169   int i;
170
171   (void) drv;
172
173   if (!_eglPutSurface(surf))
174      return EGL_TRUE;
175
176   (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
177
178   for (i = 0; i < WL_BUFFER_COUNT; ++i)
179      if (dri2_surf->wl_drm_buffer[i])
180         wl_buffer_destroy(dri2_surf->wl_drm_buffer[i]);
181
182   for (i = 0; i < __DRI_BUFFER_COUNT; ++i)
183      if (dri2_surf->dri_buffers[i] && !(i == __DRI_BUFFER_FRONT_LEFT &&
184          dri2_surf->type == DRI2_PIXMAP_SURFACE))
185         dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
186                                       dri2_surf->dri_buffers[i]);
187
188   free(surf);
189
190   return EGL_TRUE;
191}
192
193static void
194dri2_wl_egl_pixmap_destroy(struct wl_egl_pixmap *egl_pixmap)
195{
196   struct dri2_egl_buffer *dri2_buf = egl_pixmap->driver_private;
197
198   assert(dri2_buf);
199
200   dri2_buf->dri2_dpy->dri2->releaseBuffer(dri2_buf->dri2_dpy->dri_screen,
201                                           dri2_buf->dri_buffer);
202
203   free(dri2_buf);
204
205   egl_pixmap->driver_private = NULL;
206   egl_pixmap->destroy = NULL;
207   egl_pixmap->name = 0;
208}
209
210static void
211dri2_process_back_buffer(struct dri2_egl_surface *dri2_surf, unsigned format)
212{
213   struct dri2_egl_display *dri2_dpy =
214      dri2_egl_display(dri2_surf->base.Resource.Display);
215
216   (void) format;
217
218   switch (dri2_surf->type) {
219   case DRI2_WINDOW_SURFACE:
220      /* allocate a front buffer for our double-buffered window*/
221      dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT] =
222         dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
223               __DRI_BUFFER_FRONT_LEFT, format,
224               dri2_surf->base.Width, dri2_surf->base.Height);
225      break;
226   default:
227      break;
228   }
229}
230
231static void
232dri2_process_front_buffer(struct dri2_egl_surface *dri2_surf, unsigned format)
233{
234   struct dri2_egl_display *dri2_dpy =
235      dri2_egl_display(dri2_surf->base.Resource.Display);
236   struct dri2_egl_buffer *dri2_buf;
237
238   switch (dri2_surf->type) {
239   case DRI2_PIXMAP_SURFACE:
240      dri2_buf = malloc(sizeof *dri2_buf);
241      if (!dri2_buf)
242         return;
243
244      dri2_buf->dri_buffer = dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT];
245      dri2_buf->dri2_dpy   = dri2_dpy;
246
247      dri2_surf->wl_pix->name           = dri2_buf->dri_buffer->name;
248      dri2_surf->wl_pix->stride         = dri2_buf->dri_buffer->pitch;
249      dri2_surf->wl_pix->driver_private = dri2_buf;
250      dri2_surf->wl_pix->destroy        = dri2_wl_egl_pixmap_destroy;
251      break;
252   default:
253      break;
254   }
255}
256
257static void
258dri2_release_pending_buffer(void *data)
259{
260   struct dri2_egl_surface *dri2_surf = data;
261   struct dri2_egl_display *dri2_dpy =
262      dri2_egl_display(dri2_surf->base.Resource.Display);
263
264   /* FIXME: print internal error */
265   if (!dri2_surf->pending_buffer)
266      return;
267
268   dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
269                                 dri2_surf->pending_buffer);
270   dri2_surf->pending_buffer = NULL;
271}
272
273static void
274dri2_release_buffers(struct dri2_egl_surface *dri2_surf)
275{
276   struct dri2_egl_display *dri2_dpy =
277      dri2_egl_display(dri2_surf->base.Resource.Display);
278   int i;
279
280   for (i = 0; i < __DRI_BUFFER_COUNT; ++i) {
281      if (dri2_surf->dri_buffers[i]) {
282         switch (i) {
283         case __DRI_BUFFER_FRONT_LEFT:
284            if (dri2_surf->pending_buffer)
285               force_roundtrip(dri2_dpy->wl_dpy->display);
286            dri2_surf->pending_buffer = dri2_surf->dri_buffers[i];
287            wl_display_sync_callback(dri2_dpy->wl_dpy->display,
288                                     dri2_release_pending_buffer, dri2_surf);
289            break;
290         default:
291            dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
292                                          dri2_surf->dri_buffers[i]);
293            break;
294         }
295         dri2_surf->dri_buffers[i] = NULL;
296      }
297   }
298}
299
300static __DRIbuffer *
301dri2_get_buffers_with_format(__DRIdrawable * driDrawable,
302			     int *width, int *height,
303			     unsigned int *attachments, int count,
304			     int *out_count, void *loaderPrivate)
305{
306   struct dri2_egl_surface *dri2_surf = loaderPrivate;
307   struct dri2_egl_display *dri2_dpy =
308      dri2_egl_display(dri2_surf->base.Resource.Display);
309   int i;
310
311   if (dri2_surf->type == DRI2_WINDOW_SURFACE &&
312       (dri2_surf->base.Width != dri2_surf->wl_win->width ||
313        dri2_surf->base.Height != dri2_surf->wl_win->height)) {
314
315      dri2_release_buffers(dri2_surf);
316
317      dri2_surf->base.Width  = dri2_surf->wl_win->width;
318      dri2_surf->base.Height = dri2_surf->wl_win->height;
319      dri2_surf->dx = dri2_surf->wl_win->dx;
320      dri2_surf->dy = dri2_surf->wl_win->dy;
321
322      for (i = 0; i < WL_BUFFER_COUNT; ++i) {
323         if (dri2_surf->wl_drm_buffer[i])
324            wl_buffer_destroy(dri2_surf->wl_drm_buffer[i]);
325         dri2_surf->wl_drm_buffer[i]  = NULL;
326      }
327   }
328
329   dri2_surf->buffer_count = 0;
330   for (i = 0; i < 2*count; i+=2) {
331      assert(attachments[i] < __DRI_BUFFER_COUNT);
332      assert(dri2_surf->buffer_count < 5);
333
334      if (dri2_surf->dri_buffers[attachments[i]] == NULL) {
335
336         dri2_surf->dri_buffers[attachments[i]] =
337            dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
338                  attachments[i], attachments[i+1],
339                  dri2_surf->base.Width, dri2_surf->base.Height);
340
341         if (!dri2_surf->dri_buffers[attachments[i]])
342            continue;
343
344         if (attachments[i] == __DRI_BUFFER_FRONT_LEFT)
345            dri2_process_front_buffer(dri2_surf, attachments[i+1]);
346         else if (attachments[i] == __DRI_BUFFER_BACK_LEFT)
347            dri2_process_back_buffer(dri2_surf, attachments[i+1]);
348      }
349
350      memcpy(&dri2_surf->buffers[dri2_surf->buffer_count],
351             dri2_surf->dri_buffers[attachments[i]],
352             sizeof(__DRIbuffer));
353
354      dri2_surf->buffer_count++;
355   }
356
357   assert(dri2_surf->type == DRI2_PIXMAP_SURFACE ||
358          dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]);
359
360   *out_count = dri2_surf->buffer_count;
361   if (dri2_surf->buffer_count == 0)
362	   return NULL;
363
364   *width = dri2_surf->base.Width;
365   *height = dri2_surf->base.Height;
366
367   return dri2_surf->buffers;
368}
369
370static __DRIbuffer *
371dri2_get_buffers(__DRIdrawable * driDrawable,
372		 int *width, int *height,
373		 unsigned int *attachments, int count,
374		 int *out_count, void *loaderPrivate)
375{
376   unsigned int *attachments_with_format;
377   __DRIbuffer *buffer;
378   const unsigned int format = 32;
379   int i;
380
381   attachments_with_format = calloc(count * 2, sizeof(unsigned int));
382   if (!attachments_with_format) {
383      *out_count = 0;
384      return NULL;
385   }
386
387   for (i = 0; i < count; ++i) {
388      attachments_with_format[2*i] = attachments[i];
389      attachments_with_format[2*i + 1] = format;
390   }
391
392   buffer =
393      dri2_get_buffers_with_format(driDrawable,
394				   width, height,
395				   attachments_with_format, count,
396				   out_count, loaderPrivate);
397
398   free(attachments_with_format);
399
400   return buffer;
401}
402
403
404static void
405dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
406{
407   (void) driDrawable;
408
409   /* FIXME: Does EGL support front buffer rendering at all? */
410
411#if 0
412   struct dri2_egl_surface *dri2_surf = loaderPrivate;
413
414   dri2WaitGL(dri2_surf);
415#else
416   (void) loaderPrivate;
417#endif
418}
419
420static struct wl_buffer *
421wayland_create_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
422{
423   struct dri2_egl_display *dri2_dpy =
424      dri2_egl_display(dri2_surf->base.Resource.Display);
425
426   return wl_drm_create_buffer(dri2_dpy->wl_dpy->drm, buffer->name,
427                               dri2_surf->base.Width, dri2_surf->base.Height,
428                               buffer->pitch, dri2_surf->wl_win->visual);
429}
430
431static void
432wayland_frame_callback(void *data, uint32_t time)
433{
434   struct dri2_egl_surface *dri2_surf = data;
435
436   dri2_surf->block_swap_buffers = EGL_FALSE;
437}
438
439static inline void
440pointer_swap(const void **p1, const void **p2)
441{
442   const void *tmp = *p1;
443   *p1 = *p2;
444   *p2 = tmp;
445}
446
447/**
448 * Called via eglSwapBuffers(), drv->API.SwapBuffers().
449 */
450static EGLBoolean
451dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
452{
453   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
454   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
455   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
456
457   while (dri2_surf->block_swap_buffers)
458      wl_display_iterate(dri2_dpy->wl_dpy->display, WL_DISPLAY_READABLE);
459
460   dri2_surf->block_swap_buffers = EGL_TRUE;
461   wl_display_frame_callback(dri2_dpy->wl_dpy->display,
462	 wayland_frame_callback, dri2_surf);
463
464   if (dri2_surf->type == DRI2_WINDOW_SURFACE) {
465      pointer_swap(
466	    (const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT],
467	    (const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]);
468
469      dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]->attachment =
470	 __DRI_BUFFER_FRONT_LEFT;
471      dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]->attachment =
472	 __DRI_BUFFER_BACK_LEFT;
473
474      pointer_swap((const void **) &dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT],
475		   (const void **) &dri2_surf->wl_drm_buffer[WL_BUFFER_BACK]);
476
477      if (!dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT])
478	 dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT] =
479	    wayland_create_buffer(dri2_surf,
480		  dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]);
481
482      wl_surface_attach(dri2_surf->wl_win->surface,
483	    dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT],
484	    dri2_surf->dx, dri2_surf->dy);
485
486      dri2_surf->wl_win->attached_width  = dri2_surf->base.Width;
487      dri2_surf->wl_win->attached_height = dri2_surf->base.Height;
488      /* reset resize growing parameters */
489      dri2_surf->dx = 0;
490      dri2_surf->dy = 0;
491
492      wl_surface_damage(dri2_surf->wl_win->surface, 0, 0,
493	    dri2_surf->base.Width, dri2_surf->base.Height);
494   }
495
496   _EGLContext *ctx;
497   if (dri2_drv->glFlush) {
498      ctx = _eglGetCurrentContext();
499      if (ctx && ctx->DrawSurface == &dri2_surf->base)
500         dri2_drv->glFlush();
501   }
502
503   (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
504   (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
505
506   return EGL_TRUE;
507}
508
509/**
510 * Called via eglCreateImageKHR(), drv->API.CreateImageKHR().
511 */
512static _EGLImage *
513dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
514			     EGLClientBuffer buffer, const EGLint *attr_list)
515{
516   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
517   struct wl_egl_pixmap *wl_egl_pixmap = (struct wl_egl_pixmap *) buffer;
518   struct dri2_egl_buffer *dri2_buf;
519   EGLint wl_attr_list[] = {
520		EGL_WIDTH,		0,
521		EGL_HEIGHT,		0,
522		EGL_DRM_BUFFER_STRIDE_MESA,	0,
523		EGL_DRM_BUFFER_FORMAT_MESA,	EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
524		EGL_NONE
525   };
526
527   dri2_buf = malloc(sizeof *dri2_buf);
528   if (!dri2_buf)
529           return NULL;
530
531   dri2_buf->dri2_dpy = dri2_dpy;
532   dri2_buf->dri_buffer =
533      dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
534				     __DRI_BUFFER_FRONT_LEFT, 32,
535				     wl_egl_pixmap->width,
536				     wl_egl_pixmap->height);
537
538   wl_egl_pixmap->name    = dri2_buf->dri_buffer->name;
539   wl_egl_pixmap->stride  = dri2_buf->dri_buffer->pitch;
540   wl_egl_pixmap->destroy = dri2_wl_egl_pixmap_destroy;
541   wl_egl_pixmap->driver_private = dri2_buf;
542
543   wl_attr_list[1] = wl_egl_pixmap->width;
544   wl_attr_list[3] = wl_egl_pixmap->height;
545   wl_attr_list[5] = wl_egl_pixmap->stride / 4;
546
547
548   return dri2_create_image_khr(disp->Driver, disp, ctx, EGL_DRM_BUFFER_MESA,
549	       (EGLClientBuffer)(intptr_t) wl_egl_pixmap->name, wl_attr_list);
550}
551
552static _EGLImage *
553dri2_wayland_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
554			      _EGLContext *ctx, EGLenum target,
555			      EGLClientBuffer buffer, const EGLint *attr_list)
556{
557   (void) drv;
558
559   switch (target) {
560   case EGL_NATIVE_PIXMAP_KHR:
561      return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
562   default:
563      return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
564   }
565}
566
567static int
568dri2_wayland_authenticate(_EGLDisplay *disp, uint32_t id)
569{
570   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
571   int ret = 0;
572
573   dri2_dpy->wl_dpy->authenticated = false;
574
575   wl_drm_authenticate(dri2_dpy->wl_dpy->drm, id);
576   force_roundtrip(dri2_dpy->wl_dpy->display);
577
578   if (!dri2_dpy->wl_dpy->authenticated)
579      ret = -1;
580
581   /* reset authenticated */
582   dri2_dpy->wl_dpy->authenticated = true;
583
584   return ret;
585}
586
587/**
588 * Called via eglTerminate(), drv->API.Terminate().
589 */
590static EGLBoolean
591dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
592{
593   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
594
595   _eglReleaseDisplayResources(drv, disp);
596   _eglCleanupDisplay(disp);
597
598   dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
599   close(dri2_dpy->fd);
600   dlclose(dri2_dpy->driver);
601   free(dri2_dpy->driver_name);
602   free(dri2_dpy);
603   disp->DriverData = NULL;
604
605   return EGL_TRUE;
606}
607
608EGLBoolean
609dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
610{
611   struct dri2_egl_display *dri2_dpy;
612   int i;
613
614   drv->API.CreateWindowSurface = dri2_create_window_surface;
615   drv->API.CreatePixmapSurface = dri2_create_pixmap_surface;
616   drv->API.DestroySurface = dri2_destroy_surface;
617   drv->API.SwapBuffers = dri2_swap_buffers;
618   drv->API.CreateImageKHR = dri2_wayland_create_image_khr;
619   drv->API.Terminate = dri2_terminate;
620
621   dri2_dpy = malloc(sizeof *dri2_dpy);
622   if (!dri2_dpy)
623      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
624
625   memset(dri2_dpy, 0, sizeof *dri2_dpy);
626
627   disp->DriverData = (void *) dri2_dpy;
628   dri2_dpy->wl_dpy = disp->PlatformDisplay;
629
630   if (dri2_dpy->wl_dpy->fd == -1)
631      force_roundtrip(dri2_dpy->wl_dpy->display);
632   if (dri2_dpy->wl_dpy->fd == -1)
633      goto cleanup_dpy;
634
635   dri2_dpy->fd = dup(dri2_dpy->wl_dpy->fd);
636   if (dri2_dpy->fd < 0) {
637      _eglError(EGL_BAD_ALLOC, "DRI2: failed to dup fd");
638      goto cleanup_dpy;
639   }
640
641   if (!dri2_dpy->wl_dpy->authenticated)
642      force_roundtrip(dri2_dpy->wl_dpy->display);
643   if (!dri2_dpy->wl_dpy->authenticated)
644      goto cleanup_dpy;
645
646   dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd);
647   if (dri2_dpy->driver_name == NULL) {
648      _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name");
649      goto cleanup_fd;
650   }
651
652   dri2_dpy->device_name = strdup(dri2_dpy->wl_dpy->device_name);
653   if (dri2_dpy->device_name == NULL) {
654      _eglError(EGL_BAD_ALLOC, "DRI2: failed to get device name");
655      goto cleanup_driver_name;
656   }
657
658   if (!dri2_load_driver(disp))
659      goto cleanup_device_name;
660
661   dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER;
662   dri2_dpy->dri2_loader_extension.base.version = 3;
663   dri2_dpy->dri2_loader_extension.getBuffers = dri2_get_buffers;
664   dri2_dpy->dri2_loader_extension.flushFrontBuffer = dri2_flush_front_buffer;
665   dri2_dpy->dri2_loader_extension.getBuffersWithFormat =
666      dri2_get_buffers_with_format;
667
668   dri2_dpy->extensions[0] = &dri2_dpy->dri2_loader_extension.base;
669   dri2_dpy->extensions[1] = &image_lookup_extension.base;
670   dri2_dpy->extensions[2] = NULL;
671
672   if (!dri2_create_screen(disp))
673      goto cleanup_driver;
674
675   for (i = 0; dri2_dpy->driver_configs[i]; i++)
676      dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0,
677		      EGL_WINDOW_BIT | EGL_PIXMAP_BIT, NULL);
678
679
680   disp->Extensions.MESA_drm_image = EGL_TRUE;
681   disp->Extensions.KHR_image_base = EGL_TRUE;
682   disp->Extensions.KHR_image_pixmap = EGL_TRUE;
683   disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
684   disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
685
686   disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
687   dri2_dpy->authenticate = dri2_wayland_authenticate;
688
689   /* we're supporting EGL 1.4 */
690   disp->VersionMajor = 1;
691   disp->VersionMinor = 4;
692
693   return EGL_TRUE;
694
695 cleanup_driver:
696   dlclose(dri2_dpy->driver);
697 cleanup_device_name:
698   free(dri2_dpy->device_name);
699 cleanup_driver_name:
700   free(dri2_dpy->driver_name);
701 cleanup_fd:
702   close(dri2_dpy->fd);
703 cleanup_dpy:
704   free(dri2_dpy);
705
706   return EGL_FALSE;
707}
708