0cc20bbc0bf3a07273fb12954b94b7b5c647c581
[mesa.git] / src / egl / drivers / dri2 / platform_wayland.c
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
41 static void
42 sync_callback(void *data)
43 {
44 int *done = data;
45
46 *done = 1;
47 }
48
49 static void
50 force_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 */
64 static _EGLSurface *
65 dri2_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 */
143 static _EGLSurface *
144 dri2_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
152 static _EGLSurface *
153 dri2_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 */
164 static EGLBoolean
165 dri2_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
193 static void
194 dri2_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
210 static void
211 dri2_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
231 static void
232 dri2_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
257 static void
258 dri2_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
273 static void
274 dri2_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
300 static __DRIbuffer *
301 dri2_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
370 static __DRIbuffer *
371 dri2_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
404 static void
405 dri2_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
420 static struct wl_buffer *
421 wayland_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
431 static void
432 wayland_frame_callback(struct wl_surface *surface, 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
439 static inline void
440 pointer_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 */
450 static EGLBoolean
451 dri2_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 dri2_surf->wl_win->surface,
463 wayland_frame_callback, dri2_surf);
464
465 if (dri2_surf->type == DRI2_WINDOW_SURFACE) {
466 pointer_swap(
467 (const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT],
468 (const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]);
469
470 dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]->attachment =
471 __DRI_BUFFER_FRONT_LEFT;
472 dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]->attachment =
473 __DRI_BUFFER_BACK_LEFT;
474
475 pointer_swap((const void **) &dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT],
476 (const void **) &dri2_surf->wl_drm_buffer[WL_BUFFER_BACK]);
477
478 if (!dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT])
479 dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT] =
480 wayland_create_buffer(dri2_surf,
481 dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]);
482
483 wl_surface_attach(dri2_surf->wl_win->surface,
484 dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT],
485 dri2_surf->dx, dri2_surf->dy);
486
487 dri2_surf->wl_win->attached_width = dri2_surf->base.Width;
488 dri2_surf->wl_win->attached_height = dri2_surf->base.Height;
489 /* reset resize growing parameters */
490 dri2_surf->dx = 0;
491 dri2_surf->dy = 0;
492
493 wl_surface_damage(dri2_surf->wl_win->surface, 0, 0,
494 dri2_surf->base.Width, dri2_surf->base.Height);
495 }
496
497 _EGLContext *ctx;
498 if (dri2_drv->glFlush) {
499 ctx = _eglGetCurrentContext();
500 if (ctx && ctx->DrawSurface == &dri2_surf->base)
501 dri2_drv->glFlush();
502 }
503
504 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
505 (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
506
507 return EGL_TRUE;
508 }
509
510 /**
511 * Called via eglCreateImageKHR(), drv->API.CreateImageKHR().
512 */
513 static _EGLImage *
514 dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
515 EGLClientBuffer buffer, const EGLint *attr_list)
516 {
517 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
518 struct wl_egl_pixmap *wl_egl_pixmap = (struct wl_egl_pixmap *) buffer;
519 struct dri2_egl_buffer *dri2_buf;
520 EGLint wl_attr_list[] = {
521 EGL_WIDTH, 0,
522 EGL_HEIGHT, 0,
523 EGL_DRM_BUFFER_STRIDE_MESA, 0,
524 EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
525 EGL_NONE
526 };
527
528 dri2_buf = malloc(sizeof *dri2_buf);
529 if (!dri2_buf)
530 return NULL;
531
532 dri2_buf->dri2_dpy = dri2_dpy;
533 dri2_buf->dri_buffer =
534 dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
535 __DRI_BUFFER_FRONT_LEFT, 32,
536 wl_egl_pixmap->width,
537 wl_egl_pixmap->height);
538
539 wl_egl_pixmap->name = dri2_buf->dri_buffer->name;
540 wl_egl_pixmap->stride = dri2_buf->dri_buffer->pitch;
541 wl_egl_pixmap->destroy = dri2_wl_egl_pixmap_destroy;
542 wl_egl_pixmap->driver_private = dri2_buf;
543
544 wl_attr_list[1] = wl_egl_pixmap->width;
545 wl_attr_list[3] = wl_egl_pixmap->height;
546 wl_attr_list[5] = wl_egl_pixmap->stride / 4;
547
548
549 return dri2_create_image_khr(disp->Driver, disp, ctx, EGL_DRM_BUFFER_MESA,
550 (EGLClientBuffer)(intptr_t) wl_egl_pixmap->name, wl_attr_list);
551 }
552
553 static _EGLImage *
554 dri2_wayland_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
555 _EGLContext *ctx, EGLenum target,
556 EGLClientBuffer buffer, const EGLint *attr_list)
557 {
558 (void) drv;
559
560 switch (target) {
561 case EGL_NATIVE_PIXMAP_KHR:
562 return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
563 default:
564 return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
565 }
566 }
567
568 static int
569 dri2_wayland_authenticate(_EGLDisplay *disp, uint32_t id)
570 {
571 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
572 int ret = 0;
573
574 dri2_dpy->wl_dpy->authenticated = false;
575
576 wl_drm_authenticate(dri2_dpy->wl_dpy->drm, id);
577 force_roundtrip(dri2_dpy->wl_dpy->display);
578
579 if (!dri2_dpy->wl_dpy->authenticated)
580 ret = -1;
581
582 /* reset authenticated */
583 dri2_dpy->wl_dpy->authenticated = true;
584
585 return ret;
586 }
587
588 /**
589 * Called via eglTerminate(), drv->API.Terminate().
590 */
591 static EGLBoolean
592 dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
593 {
594 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
595
596 _eglReleaseDisplayResources(drv, disp);
597 _eglCleanupDisplay(disp);
598
599 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
600 close(dri2_dpy->fd);
601 dlclose(dri2_dpy->driver);
602 free(dri2_dpy->driver_name);
603 free(dri2_dpy);
604 disp->DriverData = NULL;
605
606 return EGL_TRUE;
607 }
608
609 EGLBoolean
610 dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
611 {
612 struct dri2_egl_display *dri2_dpy;
613 int i;
614
615 drv->API.CreateWindowSurface = dri2_create_window_surface;
616 drv->API.CreatePixmapSurface = dri2_create_pixmap_surface;
617 drv->API.DestroySurface = dri2_destroy_surface;
618 drv->API.SwapBuffers = dri2_swap_buffers;
619 drv->API.CreateImageKHR = dri2_wayland_create_image_khr;
620 drv->API.Terminate = dri2_terminate;
621
622 dri2_dpy = malloc(sizeof *dri2_dpy);
623 if (!dri2_dpy)
624 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
625
626 memset(dri2_dpy, 0, sizeof *dri2_dpy);
627
628 disp->DriverData = (void *) dri2_dpy;
629 dri2_dpy->wl_dpy = disp->PlatformDisplay;
630
631 if (dri2_dpy->wl_dpy->fd == -1)
632 force_roundtrip(dri2_dpy->wl_dpy->display);
633 if (dri2_dpy->wl_dpy->fd == -1)
634 goto cleanup_dpy;
635
636 dri2_dpy->fd = dup(dri2_dpy->wl_dpy->fd);
637 if (dri2_dpy->fd < 0) {
638 _eglError(EGL_BAD_ALLOC, "DRI2: failed to dup fd");
639 goto cleanup_dpy;
640 }
641
642 if (!dri2_dpy->wl_dpy->authenticated)
643 force_roundtrip(dri2_dpy->wl_dpy->display);
644 if (!dri2_dpy->wl_dpy->authenticated)
645 goto cleanup_dpy;
646
647 dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd);
648 if (dri2_dpy->driver_name == NULL) {
649 _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name");
650 goto cleanup_fd;
651 }
652
653 dri2_dpy->device_name = strdup(dri2_dpy->wl_dpy->device_name);
654 if (dri2_dpy->device_name == NULL) {
655 _eglError(EGL_BAD_ALLOC, "DRI2: failed to get device name");
656 goto cleanup_driver_name;
657 }
658
659 if (!dri2_load_driver(disp))
660 goto cleanup_device_name;
661
662 dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER;
663 dri2_dpy->dri2_loader_extension.base.version = 3;
664 dri2_dpy->dri2_loader_extension.getBuffers = dri2_get_buffers;
665 dri2_dpy->dri2_loader_extension.flushFrontBuffer = dri2_flush_front_buffer;
666 dri2_dpy->dri2_loader_extension.getBuffersWithFormat =
667 dri2_get_buffers_with_format;
668
669 dri2_dpy->extensions[0] = &dri2_dpy->dri2_loader_extension.base;
670 dri2_dpy->extensions[1] = &image_lookup_extension.base;
671 dri2_dpy->extensions[2] = NULL;
672
673 if (!dri2_create_screen(disp))
674 goto cleanup_driver;
675
676 for (i = 0; dri2_dpy->driver_configs[i]; i++)
677 dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0,
678 EGL_WINDOW_BIT | EGL_PIXMAP_BIT, NULL);
679
680
681 disp->Extensions.KHR_image_pixmap = EGL_TRUE;
682
683 disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
684 dri2_dpy->authenticate = dri2_wayland_authenticate;
685
686 /* we're supporting EGL 1.4 */
687 disp->VersionMajor = 1;
688 disp->VersionMinor = 4;
689
690 return EGL_TRUE;
691
692 cleanup_driver:
693 dlclose(dri2_dpy->driver);
694 cleanup_device_name:
695 free(dri2_dpy->device_name);
696 cleanup_driver_name:
697 free(dri2_dpy->driver_name);
698 cleanup_fd:
699 close(dri2_dpy->fd);
700 cleanup_dpy:
701 free(dri2_dpy);
702
703 return EGL_FALSE;
704 }