blob: e9f142c64d1876013a1ef6dc5b8e9891cc11c44b [file] [log] [blame]
Benjamin Franzke93aea842011-02-04 12:39:40 +01001/*
Kristian Høgsberg90804e82012-12-13 23:30:45 -05002 * Copyright © 2011-2012 Intel Corporation
Benjamin Franzke93aea842011-02-04 12:39:40 +01003 *
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
Emil Velikovbf0e4d22015-02-28 17:12:40 +000029#include <stdint.h>
Benjamin Franzke93aea842011-02-04 12:39:40 +010030#include <stdlib.h>
31#include <string.h>
32#include <limits.h>
33#include <dlfcn.h>
34#include <errno.h>
35#include <unistd.h>
Kristian Høgsbergc0f8c992011-04-14 10:42:41 -040036#include <fcntl.h>
37#include <xf86drm.h>
Benjamin Franzke93aea842011-02-04 12:39:40 +010038
39#include "egl_dri2.h"
Chad Versace8b9298a2014-01-28 12:34:19 -080040#include "egl_dri2_fallbacks.h"
Emil Velikov8d4357b2014-01-11 04:52:48 +000041#include "loader.h"
Benjamin Franzke93aea842011-02-04 12:39:40 +010042
Benjamin Franzke6b369c42011-02-21 16:22:34 +010043#include <wayland-client.h>
44#include "wayland-drm-client-protocol.h"
45
Kristian Høgsberg7b1d94e2011-08-31 16:45:04 -040046enum wl_drm_format_flags {
Kristian Høgsberg58dc1b22012-01-11 14:23:24 -050047 HAS_ARGB8888 = 1,
Singh, Satyeshwar2efc97d2013-10-16 01:10:12 +000048 HAS_XRGB8888 = 2,
49 HAS_RGB565 = 4,
Kristian Høgsberg7b1d94e2011-08-31 16:45:04 -040050};
51
Chad Versacea2187652014-01-27 16:42:10 -080052static EGLBoolean
53dri2_wl_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
54 EGLint interval);
55
Benjamin Franzke51f28202011-02-11 02:23:14 +010056static void
Kristian Høgsberg0229e3a2012-10-10 22:10:42 -040057sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
58{
59 int *done = data;
60
61 *done = 1;
62 wl_callback_destroy(callback);
63}
64
65static const struct wl_callback_listener sync_listener = {
66 sync_callback
67};
68
69static int
70roundtrip(struct dri2_egl_display *dri2_dpy)
71{
72 struct wl_callback *callback;
73 int done = 0, ret = 0;
74
75 callback = wl_display_sync(dri2_dpy->wl_dpy);
76 wl_callback_add_listener(callback, &sync_listener, &done);
77 wl_proxy_set_queue((struct wl_proxy *) callback, dri2_dpy->wl_queue);
78 while (ret != -1 && !done)
79 ret = wl_display_dispatch_queue(dri2_dpy->wl_dpy, dri2_dpy->wl_queue);
80
Jonas Ådahl800ed952012-12-25 13:01:08 +010081 if (!done)
82 wl_callback_destroy(callback);
83
Kristian Høgsberg0229e3a2012-10-10 22:10:42 -040084 return ret;
85}
86
87static void
Benjamin Franzke0cb356d2011-05-06 19:13:29 +020088wl_buffer_release(void *data, struct wl_buffer *buffer)
89{
90 struct dri2_egl_surface *dri2_surf = data;
91 int i;
92
Kristian Høgsberg90804e82012-12-13 23:30:45 -050093 for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); ++i)
94 if (dri2_surf->color_buffers[i].wl_buffer == buffer)
Benjamin Franzke0cb356d2011-05-06 19:13:29 +020095 break;
96
Kristian Høgsberg90804e82012-12-13 23:30:45 -050097 if (i == ARRAY_SIZE(dri2_surf->color_buffers)) {
98 wl_buffer_destroy(buffer);
Benjamin Franzke0cb356d2011-05-06 19:13:29 +020099 return;
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500100 }
Benjamin Franzke0cb356d2011-05-06 19:13:29 +0200101
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500102 dri2_surf->color_buffers[i].locked = 0;
Benjamin Franzke0cb356d2011-05-06 19:13:29 +0200103}
104
105static struct wl_buffer_listener wl_buffer_listener = {
106 wl_buffer_release
107};
Benjamin Franzke51f28202011-02-11 02:23:14 +0100108
Ander Conselvan de Oliveiraca3ed3e2012-11-30 17:41:02 +0200109static void
110resize_callback(struct wl_egl_window *wl_win, void *data)
111{
112 struct dri2_egl_surface *dri2_surf = data;
113 struct dri2_egl_display *dri2_dpy =
114 dri2_egl_display(dri2_surf->base.Resource.Display);
115
116 (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
117}
118
Benjamin Franzke93aea842011-02-04 12:39:40 +0100119/**
120 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
121 */
122static _EGLSurface *
Axel Davycd25e522015-05-01 11:16:41 +0200123dri2_wl_create_surface(_EGLDriver *drv, _EGLDisplay *disp,
Chad Versace6d1f83e2014-01-07 14:54:51 -0800124 _EGLConfig *conf, void *native_window,
Chad Versaced019cd82014-01-28 12:47:38 -0800125 const EGLint *attrib_list)
Benjamin Franzke93aea842011-02-04 12:39:40 +0100126{
127 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
128 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
Chad Versace6d1f83e2014-01-07 14:54:51 -0800129 struct wl_egl_window *window = native_window;
Benjamin Franzke93aea842011-02-04 12:39:40 +0100130 struct dri2_egl_surface *dri2_surf;
Benjamin Franzke93aea842011-02-04 12:39:40 +0100131
132 (void) drv;
133
Matt Turnerf0a8bcd2014-09-21 21:15:26 -0700134 dri2_surf = calloc(1, sizeof *dri2_surf);
Benjamin Franzke93aea842011-02-04 12:39:40 +0100135 if (!dri2_surf) {
136 _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
137 return NULL;
138 }
139
Axel Davycd25e522015-05-01 11:16:41 +0200140 if (!_eglInitSurface(&dri2_surf->base, disp, EGL_WINDOW_BIT, conf, attrib_list))
Benjamin Franzke93aea842011-02-04 12:39:40 +0100141 goto cleanup_surf;
142
Singh, Satyeshwar2efc97d2013-10-16 01:10:12 +0000143 if (conf->RedSize == 5)
144 dri2_surf->format = WL_DRM_FORMAT_RGB565;
145 else if (conf->AlphaSize == 0)
Kristian Høgsberg58dc1b22012-01-11 14:23:24 -0500146 dri2_surf->format = WL_DRM_FORMAT_XRGB8888;
Kristian Høgsberg7b1d94e2011-08-31 16:45:04 -0400147 else
Kristian Høgsberg58dc1b22012-01-11 14:23:24 -0500148 dri2_surf->format = WL_DRM_FORMAT_ARGB8888;
Kristian Høgsberg7b1d94e2011-08-31 16:45:04 -0400149
Axel Davycd25e522015-05-01 11:16:41 +0200150 dri2_surf->wl_win = window;
Benjamin Franzke93aea842011-02-04 12:39:40 +0100151
Axel Davycd25e522015-05-01 11:16:41 +0200152 dri2_surf->wl_win->private = dri2_surf;
153 dri2_surf->wl_win->resize_callback = resize_callback;
Ander Conselvan de Oliveiraca3ed3e2012-11-30 17:41:02 +0200154
Axel Davycd25e522015-05-01 11:16:41 +0200155 dri2_surf->base.Width = -1;
156 dri2_surf->base.Height = -1;
Benjamin Franzke93aea842011-02-04 12:39:40 +0100157
158 dri2_surf->dri_drawable =
159 (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
Axel Davycd25e522015-05-01 11:16:41 +0200160 dri2_conf->dri_double_config,
Benjamin Franzke87dde5b2011-02-09 15:30:20 +0100161 dri2_surf);
Benjamin Franzke93aea842011-02-04 12:39:40 +0100162 if (dri2_surf->dri_drawable == NULL) {
163 _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
164 goto cleanup_dri_drawable;
165 }
166
167 return &dri2_surf->base;
168
169 cleanup_dri_drawable:
170 dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
171 cleanup_surf:
172 free(dri2_surf);
173
174 return NULL;
175}
176
177/**
178 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
179 */
180static _EGLSurface *
Chad Versaced019cd82014-01-28 12:47:38 -0800181dri2_wl_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
Chad Versace6d1f83e2014-01-07 14:54:51 -0800182 _EGLConfig *conf, void *native_window,
Chad Versaced019cd82014-01-28 12:47:38 -0800183 const EGLint *attrib_list)
Benjamin Franzke93aea842011-02-04 12:39:40 +0100184{
Neil Roberts992a2db2013-11-15 13:50:50 +0000185 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
186 _EGLSurface *surf;
187
Axel Davycd25e522015-05-01 11:16:41 +0200188 surf = dri2_wl_create_surface(drv, disp, conf, native_window, attrib_list);
Neil Roberts992a2db2013-11-15 13:50:50 +0000189
190 if (surf != NULL)
Chad Versacea2187652014-01-27 16:42:10 -0800191 dri2_wl_swap_interval(drv, disp, surf, dri2_dpy->default_swap_interval);
Neil Roberts992a2db2013-11-15 13:50:50 +0000192
193 return surf;
Benjamin Franzke93aea842011-02-04 12:39:40 +0100194}
195
Chad Versace9a40ee12014-02-09 09:13:27 -0800196static _EGLSurface *
197dri2_wl_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
198 _EGLConfig *conf, void *native_window,
199 const EGLint *attrib_list)
200{
201 /* From the EGL_EXT_platform_wayland spec, version 3:
202 *
203 * It is not valid to call eglCreatePlatformPixmapSurfaceEXT with a <dpy>
204 * that belongs to Wayland. Any such call fails and generates
205 * EGL_BAD_PARAMETER.
206 */
207 _eglError(EGL_BAD_PARAMETER, "cannot create EGL pixmap surfaces on "
208 "Wayland");
209 return NULL;
210}
211
Benjamin Franzke93aea842011-02-04 12:39:40 +0100212/**
213 * Called via eglDestroySurface(), drv->API.DestroySurface().
214 */
215static EGLBoolean
Chad Versaced019cd82014-01-28 12:47:38 -0800216dri2_wl_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
Benjamin Franzke93aea842011-02-04 12:39:40 +0100217{
218 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
219 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
220 int i;
221
222 (void) drv;
223
224 if (!_eglPutSurface(surf))
225 return EGL_TRUE;
226
227 (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
228
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500229 for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
230 if (dri2_surf->color_buffers[i].wl_buffer)
231 wl_buffer_destroy(dri2_surf->color_buffers[i].wl_buffer);
Kristian Høgsberg664fe6d2013-02-02 07:40:51 -0500232 if (dri2_surf->color_buffers[i].dri_image)
233 dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image);
Axel Davy4cd546d2015-05-01 01:16:24 +0200234 if (dri2_surf->color_buffers[i].linear_copy)
235 dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].linear_copy);
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500236 }
Benjamin Franzke93aea842011-02-04 12:39:40 +0100237
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500238 for (i = 0; i < __DRI_BUFFER_COUNT; i++)
239 if (dri2_surf->dri_buffers[i] &&
240 dri2_surf->dri_buffers[i]->attachment != __DRI_BUFFER_BACK_LEFT)
Benjamin Franzke93aea842011-02-04 12:39:40 +0100241 dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
242 dri2_surf->dri_buffers[i]);
243
Neil Roberts992a2db2013-11-15 13:50:50 +0000244 if (dri2_surf->throttle_callback)
245 wl_callback_destroy(dri2_surf->throttle_callback);
Jonas Ådahla3b6b2d2012-10-28 00:50:12 +0200246
Axel Davycd25e522015-05-01 11:16:41 +0200247 dri2_surf->wl_win->private = NULL;
248 dri2_surf->wl_win->resize_callback = NULL;
Ander Conselvan de Oliveiraca3ed3e2012-11-30 17:41:02 +0200249
Benjamin Franzke93aea842011-02-04 12:39:40 +0100250 free(surf);
251
252 return EGL_TRUE;
253}
254
Benjamin Franzke51f28202011-02-11 02:23:14 +0100255static void
Chad Versaced019cd82014-01-28 12:47:38 -0800256dri2_wl_release_buffers(struct dri2_egl_surface *dri2_surf)
Benjamin Franzke51f28202011-02-11 02:23:14 +0100257{
258 struct dri2_egl_display *dri2_dpy =
259 dri2_egl_display(dri2_surf->base.Resource.Display);
260 int i;
261
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500262 for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
263 if (dri2_surf->color_buffers[i].wl_buffer &&
264 !dri2_surf->color_buffers[i].locked)
265 wl_buffer_destroy(dri2_surf->color_buffers[i].wl_buffer);
Kristian Høgsberg664fe6d2013-02-02 07:40:51 -0500266 if (dri2_surf->color_buffers[i].dri_image)
267 dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image);
Axel Davy4cd546d2015-05-01 01:16:24 +0200268 if (dri2_surf->color_buffers[i].linear_copy)
269 dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].linear_copy);
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500270
271 dri2_surf->color_buffers[i].wl_buffer = NULL;
Kristian Høgsberg664fe6d2013-02-02 07:40:51 -0500272 dri2_surf->color_buffers[i].dri_image = NULL;
Axel Davy4cd546d2015-05-01 01:16:24 +0200273 dri2_surf->color_buffers[i].linear_copy = NULL;
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500274 dri2_surf->color_buffers[i].locked = 0;
Benjamin Franzke0cb356d2011-05-06 19:13:29 +0200275 }
276
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500277 for (i = 0; i < __DRI_BUFFER_COUNT; i++)
278 if (dri2_surf->dri_buffers[i] &&
279 dri2_surf->dri_buffers[i]->attachment != __DRI_BUFFER_BACK_LEFT)
280 dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
281 dri2_surf->dri_buffers[i]);
Benjamin Franzke51f28202011-02-11 02:23:14 +0100282}
283
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500284static int
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -0800285get_back_bo(struct dri2_egl_surface *dri2_surf)
Benjamin Franzke0cb356d2011-05-06 19:13:29 +0200286{
287 struct dri2_egl_display *dri2_dpy =
288 dri2_egl_display(dri2_surf->base.Resource.Display);
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -0800289 int i;
Vivek Kasireddy1e96eec2015-02-10 19:15:31 -0800290 unsigned int dri_image_format;
291
292 /* currently supports three WL DRM formats,
293 * WL_DRM_FORMAT_ARGB8888, WL_DRM_FORMAT_XRGB8888,
294 * and WL_DRM_FORMAT_RGB565
295 */
296 switch (dri2_surf->format) {
297 case WL_DRM_FORMAT_ARGB8888:
298 dri_image_format = __DRI_IMAGE_FORMAT_ARGB8888;
299 break;
300 case WL_DRM_FORMAT_XRGB8888:
301 dri_image_format = __DRI_IMAGE_FORMAT_XRGB8888;
302 break;
303 case WL_DRM_FORMAT_RGB565:
304 dri_image_format = __DRI_IMAGE_FORMAT_RGB565;
305 break;
306 default:
307 /* format is not supported */
308 return -1;
309 }
Benjamin Franzke0cb356d2011-05-06 19:13:29 +0200310
Neil Roberts992a2db2013-11-15 13:50:50 +0000311 /* We always want to throttle to some event (either a frame callback or
312 * a sync request) after the commit so that we can be sure the
313 * compositor has had a chance to handle it and send us a release event
314 * before we look for a free buffer */
315 while (dri2_surf->throttle_callback != NULL)
316 if (wl_display_dispatch_queue(dri2_dpy->wl_dpy,
317 dri2_dpy->wl_queue) == -1)
Kristian Høgsberg4ed055b2013-12-09 16:13:35 -0800318 return -1;
Benjamin Franzke0cb356d2011-05-06 19:13:29 +0200319
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500320 if (dri2_surf->back == NULL) {
321 for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
Neil Roberts992a2db2013-11-15 13:50:50 +0000322 /* Get an unlocked buffer, preferrably one with a dri_buffer
323 * already allocated. */
324 if (dri2_surf->color_buffers[i].locked)
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500325 continue;
326 if (dri2_surf->back == NULL)
Neil Roberts992a2db2013-11-15 13:50:50 +0000327 dri2_surf->back = &dri2_surf->color_buffers[i];
Kristian Høgsberg664fe6d2013-02-02 07:40:51 -0500328 else if (dri2_surf->back->dri_image == NULL)
Neil Roberts992a2db2013-11-15 13:50:50 +0000329 dri2_surf->back = &dri2_surf->color_buffers[i];
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500330 }
Benjamin Franzke0cb356d2011-05-06 19:13:29 +0200331 }
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500332
333 if (dri2_surf->back == NULL)
334 return -1;
Axel Davy4cd546d2015-05-01 01:16:24 +0200335
336 if (dri2_dpy->is_different_gpu &&
337 dri2_surf->back->linear_copy == NULL) {
338 dri2_surf->back->linear_copy =
339 dri2_dpy->image->createImage(dri2_dpy->dri_screen,
340 dri2_surf->base.Width,
341 dri2_surf->base.Height,
342 dri_image_format,
343 __DRI_IMAGE_USE_SHARE |
344 __DRI_IMAGE_USE_LINEAR,
345 NULL);
346 if (dri2_surf->back->linear_copy == NULL)
347 return -1;
348 }
349
Kristian Høgsberg664fe6d2013-02-02 07:40:51 -0500350 if (dri2_surf->back->dri_image == NULL) {
351 dri2_surf->back->dri_image =
352 dri2_dpy->image->createImage(dri2_dpy->dri_screen,
353 dri2_surf->base.Width,
354 dri2_surf->base.Height,
Vivek Kasireddy1e96eec2015-02-10 19:15:31 -0800355 dri_image_format,
Axel Davy4cd546d2015-05-01 01:16:24 +0200356 dri2_dpy->is_different_gpu ?
357 0 : __DRI_IMAGE_USE_SHARE,
Kristian Høgsberg664fe6d2013-02-02 07:40:51 -0500358 NULL);
Kristian Høgsberg6d4d4b02012-12-13 23:32:14 -0500359 dri2_surf->back->age = 0;
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500360 }
Kristian Høgsberg664fe6d2013-02-02 07:40:51 -0500361 if (dri2_surf->back->dri_image == NULL)
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500362 return -1;
363
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -0800364 dri2_surf->back->locked = 1;
365
366 return 0;
367}
368
369
370static void
371back_bo_to_dri_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
372{
373 struct dri2_egl_display *dri2_dpy =
374 dri2_egl_display(dri2_surf->base.Resource.Display);
375 __DRIimage *image;
376 int name, pitch;
377
Kristian Høgsberg664fe6d2013-02-02 07:40:51 -0500378 image = dri2_surf->back->dri_image;
379
380 dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NAME, &name);
381 dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
382
Kristian Høgsberg664fe6d2013-02-02 07:40:51 -0500383 buffer->attachment = __DRI_BUFFER_BACK_LEFT;
384 buffer->name = name;
385 buffer->pitch = pitch;
386 buffer->cpp = 4;
387 buffer->flags = 0;
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500388}
389
390static int
391get_aux_bo(struct dri2_egl_surface *dri2_surf,
392 unsigned int attachment, unsigned int format, __DRIbuffer *buffer)
393{
394 struct dri2_egl_display *dri2_dpy =
395 dri2_egl_display(dri2_surf->base.Resource.Display);
396 __DRIbuffer *b = dri2_surf->dri_buffers[attachment];
397
398 if (b == NULL) {
399 b = dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
400 attachment, format,
401 dri2_surf->base.Width,
402 dri2_surf->base.Height);
403 dri2_surf->dri_buffers[attachment] = b;
404 }
405 if (b == NULL)
406 return -1;
407
408 memcpy(buffer, b, sizeof *buffer);
409
410 return 0;
Benjamin Franzke0cb356d2011-05-06 19:13:29 +0200411}
412
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -0800413static int
414update_buffers(struct dri2_egl_surface *dri2_surf)
Benjamin Franzke93aea842011-02-04 12:39:40 +0100415{
Benjamin Franzke93aea842011-02-04 12:39:40 +0100416 struct dri2_egl_display *dri2_dpy =
417 dri2_egl_display(dri2_surf->base.Resource.Display);
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -0800418 int i;
Ander Conselvan de Oliveira60a11e22012-11-22 15:34:49 +0200419
Axel Davycd25e522015-05-01 11:16:41 +0200420 if (dri2_surf->base.Width != dri2_surf->wl_win->width ||
421 dri2_surf->base.Height != dri2_surf->wl_win->height) {
Benjamin Franzke51f28202011-02-11 02:23:14 +0100422
Chad Versaced019cd82014-01-28 12:47:38 -0800423 dri2_wl_release_buffers(dri2_surf);
Benjamin Franzke93aea842011-02-04 12:39:40 +0100424
425 dri2_surf->base.Width = dri2_surf->wl_win->width;
426 dri2_surf->base.Height = dri2_surf->wl_win->height;
427 dri2_surf->dx = dri2_surf->wl_win->dx;
428 dri2_surf->dy = dri2_surf->wl_win->dy;
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500429 }
Benjamin Franzke93aea842011-02-04 12:39:40 +0100430
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -0800431 if (get_back_bo(dri2_surf) < 0) {
432 _eglError(EGL_BAD_ALLOC, "failed to allocate color buffer");
433 return -1;
Benjamin Franzke93aea842011-02-04 12:39:40 +0100434 }
435
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500436 /* If we have an extra unlocked buffer at this point, we had to do triple
437 * buffering for a while, but now can go back to just double buffering.
438 * That means we can free any unlocked buffer now. */
439 for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
440 if (!dri2_surf->color_buffers[i].locked &&
441 dri2_surf->color_buffers[i].wl_buffer) {
442 wl_buffer_destroy(dri2_surf->color_buffers[i].wl_buffer);
Kristian Høgsberg664fe6d2013-02-02 07:40:51 -0500443 dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image);
Axel Davy4cd546d2015-05-01 01:16:24 +0200444 if (dri2_dpy->is_different_gpu)
445 dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].linear_copy);
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500446 dri2_surf->color_buffers[i].wl_buffer = NULL;
Kristian Høgsberg664fe6d2013-02-02 07:40:51 -0500447 dri2_surf->color_buffers[i].dri_image = NULL;
Axel Davy4cd546d2015-05-01 01:16:24 +0200448 dri2_surf->color_buffers[i].linear_copy = NULL;
Benjamin Franzke93aea842011-02-04 12:39:40 +0100449 }
Benjamin Franzke93aea842011-02-04 12:39:40 +0100450 }
451
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -0800452 return 0;
453}
454
455static __DRIbuffer *
Chad Versaced019cd82014-01-28 12:47:38 -0800456dri2_wl_get_buffers_with_format(__DRIdrawable * driDrawable,
457 int *width, int *height,
458 unsigned int *attachments, int count,
459 int *out_count, void *loaderPrivate)
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -0800460{
461 struct dri2_egl_surface *dri2_surf = loaderPrivate;
462 int i, j;
463
464 if (update_buffers(dri2_surf) < 0)
465 return NULL;
466
467 for (i = 0, j = 0; i < 2 * count; i += 2, j++) {
468 switch (attachments[i]) {
469 case __DRI_BUFFER_BACK_LEFT:
470 back_bo_to_dri_buffer(dri2_surf, &dri2_surf->buffers[j]);
471 break;
472 default:
473 if (get_aux_bo(dri2_surf, attachments[i], attachments[i + 1],
474 &dri2_surf->buffers[j]) < 0) {
475 _eglError(EGL_BAD_ALLOC, "failed to allocate aux buffer");
476 return NULL;
477 }
478 break;
479 }
480 }
481
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500482 *out_count = j;
483 if (j == 0)
Benjamin Franzke93aea842011-02-04 12:39:40 +0100484 return NULL;
485
486 *width = dri2_surf->base.Width;
487 *height = dri2_surf->base.Height;
488
489 return dri2_surf->buffers;
490}
491
492static __DRIbuffer *
Chad Versaced019cd82014-01-28 12:47:38 -0800493dri2_wl_get_buffers(__DRIdrawable * driDrawable,
494 int *width, int *height,
495 unsigned int *attachments, int count,
496 int *out_count, void *loaderPrivate)
Benjamin Franzke93aea842011-02-04 12:39:40 +0100497{
Vivek Kasireddy1e96eec2015-02-10 19:15:31 -0800498 struct dri2_egl_surface *dri2_surf = loaderPrivate;
Benjamin Franzke93aea842011-02-04 12:39:40 +0100499 unsigned int *attachments_with_format;
500 __DRIbuffer *buffer;
Vivek Kasireddy1e96eec2015-02-10 19:15:31 -0800501 unsigned int bpp;
502
Benjamin Franzke93aea842011-02-04 12:39:40 +0100503 int i;
504
Vivek Kasireddy1e96eec2015-02-10 19:15:31 -0800505 switch (dri2_surf->format) {
506 case WL_DRM_FORMAT_ARGB8888:
507 case WL_DRM_FORMAT_XRGB8888:
508 bpp = 32;
509 break;
510 case WL_DRM_FORMAT_RGB565:
511 bpp = 16;
512 break;
513 default:
514 /* format is not supported */
515 return NULL;
516 }
517
Carl Worthecc89e42014-09-03 14:33:18 -0700518 attachments_with_format = calloc(count, 2 * sizeof(unsigned int));
Benjamin Franzke93aea842011-02-04 12:39:40 +0100519 if (!attachments_with_format) {
520 *out_count = 0;
521 return NULL;
522 }
523
524 for (i = 0; i < count; ++i) {
525 attachments_with_format[2*i] = attachments[i];
Vivek Kasireddy1e96eec2015-02-10 19:15:31 -0800526 attachments_with_format[2*i + 1] = bpp;
Benjamin Franzke93aea842011-02-04 12:39:40 +0100527 }
528
529 buffer =
Chad Versaced019cd82014-01-28 12:47:38 -0800530 dri2_wl_get_buffers_with_format(driDrawable,
531 width, height,
532 attachments_with_format, count,
533 out_count, loaderPrivate);
Benjamin Franzke93aea842011-02-04 12:39:40 +0100534
535 free(attachments_with_format);
536
537 return buffer;
538}
539
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -0800540static int
541image_get_buffers(__DRIdrawable *driDrawable,
542 unsigned int format,
543 uint32_t *stamp,
544 void *loaderPrivate,
545 uint32_t buffer_mask,
546 struct __DRIimageList *buffers)
547{
548 struct dri2_egl_surface *dri2_surf = loaderPrivate;
549
550 if (update_buffers(dri2_surf) < 0)
551 return 0;
552
553 buffers->image_mask = __DRI_IMAGE_BUFFER_BACK;
554 buffers->back = dri2_surf->back->dri_image;
555
556 return 1;
557}
558
Benjamin Franzke93aea842011-02-04 12:39:40 +0100559static void
Chad Versaced019cd82014-01-28 12:47:38 -0800560dri2_wl_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
Benjamin Franzke93aea842011-02-04 12:39:40 +0100561{
562 (void) driDrawable;
Benjamin Franzke93aea842011-02-04 12:39:40 +0100563 (void) loaderPrivate;
Benjamin Franzke93aea842011-02-04 12:39:40 +0100564}
565
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -0800566static const __DRIimageLoaderExtension image_loader_extension = {
Emil Velikov9e627cc2014-02-12 18:32:59 +0000567 .base = { __DRI_IMAGE_LOADER, 1 },
568
569 .getBuffers = image_get_buffers,
Chad Versaced019cd82014-01-28 12:47:38 -0800570 .flushFrontBuffer = dri2_wl_flush_front_buffer,
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -0800571};
572
Benjamin Franzke93aea842011-02-04 12:39:40 +0100573static void
Neil Roberts992a2db2013-11-15 13:50:50 +0000574wayland_throttle_callback(void *data,
575 struct wl_callback *callback,
576 uint32_t time)
Benjamin Franzke93aea842011-02-04 12:39:40 +0100577{
578 struct dri2_egl_surface *dri2_surf = data;
579
Neil Roberts992a2db2013-11-15 13:50:50 +0000580 dri2_surf->throttle_callback = NULL;
Kristian Høgsberg6602bda2011-08-16 22:38:22 -0400581 wl_callback_destroy(callback);
Benjamin Franzke93aea842011-02-04 12:39:40 +0100582}
583
Neil Roberts992a2db2013-11-15 13:50:50 +0000584static const struct wl_callback_listener throttle_listener = {
585 wayland_throttle_callback
Kristian Høgsberg6602bda2011-08-16 22:38:22 -0400586};
587
Kristian Høgsbergde315f72013-02-02 12:26:12 -0500588static void
589create_wl_buffer(struct dri2_egl_surface *dri2_surf)
590{
591 struct dri2_egl_display *dri2_dpy =
592 dri2_egl_display(dri2_surf->base.Resource.Display);
Axel Davy4cd546d2015-05-01 01:16:24 +0200593 __DRIimage *image;
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -0800594 int fd, stride, name;
Kristian Høgsbergde315f72013-02-02 12:26:12 -0500595
596 if (dri2_surf->current->wl_buffer != NULL)
597 return;
598
Axel Davy4cd546d2015-05-01 01:16:24 +0200599 if (dri2_dpy->is_different_gpu) {
600 image = dri2_surf->current->linear_copy;
601 } else {
602 image = dri2_surf->current->dri_image;
603 }
Kristian Høgsbergde315f72013-02-02 12:26:12 -0500604 if (dri2_dpy->capabilities & WL_DRM_CAPABILITY_PRIME) {
Axel Davy4cd546d2015-05-01 01:16:24 +0200605 dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FD, &fd);
606 dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride);
Kristian Høgsbergde315f72013-02-02 12:26:12 -0500607
608 dri2_surf->current->wl_buffer =
609 wl_drm_create_prime_buffer(dri2_dpy->wl_drm,
610 fd,
611 dri2_surf->base.Width,
612 dri2_surf->base.Height,
613 dri2_surf->format,
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -0800614 0, stride,
Kristian Høgsbergde315f72013-02-02 12:26:12 -0500615 0, 0,
616 0, 0);
617 close(fd);
618 } else {
Axel Davy4cd546d2015-05-01 01:16:24 +0200619 dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NAME, &name);
620 dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride);
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -0800621
Kristian Høgsbergde315f72013-02-02 12:26:12 -0500622 dri2_surf->current->wl_buffer =
623 wl_drm_create_buffer(dri2_dpy->wl_drm,
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -0800624 name,
Kristian Høgsbergde315f72013-02-02 12:26:12 -0500625 dri2_surf->base.Width,
626 dri2_surf->base.Height,
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -0800627 stride,
Kristian Høgsbergde315f72013-02-02 12:26:12 -0500628 dri2_surf->format);
629 }
630
631 wl_proxy_set_queue((struct wl_proxy *) dri2_surf->current->wl_buffer,
632 dri2_dpy->wl_queue);
633 wl_buffer_add_listener(dri2_surf->current->wl_buffer,
634 &wl_buffer_listener, dri2_surf);
635}
636
Benjamin Franzke93aea842011-02-04 12:39:40 +0100637/**
638 * Called via eglSwapBuffers(), drv->API.SwapBuffers().
639 */
640static EGLBoolean
Chad Versaced019cd82014-01-28 12:47:38 -0800641dri2_wl_swap_buffers_with_damage(_EGLDriver *drv,
642 _EGLDisplay *disp,
643 _EGLSurface *draw,
644 const EGLint *rects,
645 EGLint n_rects)
Benjamin Franzke93aea842011-02-04 12:39:40 +0100646{
647 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
648 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
Neil Roberts25cc8892013-11-15 13:50:49 +0000649 int i;
Benjamin Franzke93aea842011-02-04 12:39:40 +0100650
Kristian Høgsberg6d4d4b02012-12-13 23:32:14 -0500651 for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
652 if (dri2_surf->color_buffers[i].age > 0)
653 dri2_surf->color_buffers[i].age++;
654
Kristian Høgsberg1fe00732013-02-06 15:41:54 -0500655 /* Make sure we have a back buffer in case we're swapping without ever
656 * rendering. */
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -0800657 if (get_back_bo(dri2_surf) < 0) {
Kristian Høgsberg1fe00732013-02-06 15:41:54 -0500658 _eglError(EGL_BAD_ALLOC, "dri2_swap_buffers");
659 return EGL_FALSE;
660 }
661
Neil Roberts992a2db2013-11-15 13:50:50 +0000662 if (draw->SwapInterval > 0) {
663 dri2_surf->throttle_callback =
664 wl_surface_frame(dri2_surf->wl_win->surface);
665 wl_callback_add_listener(dri2_surf->throttle_callback,
666 &throttle_listener, dri2_surf);
667 wl_proxy_set_queue((struct wl_proxy *) dri2_surf->throttle_callback,
668 dri2_dpy->wl_queue);
669 }
Neil Roberts25cc8892013-11-15 13:50:49 +0000670
Kristian Høgsberg6d4d4b02012-12-13 23:32:14 -0500671 dri2_surf->back->age = 1;
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500672 dri2_surf->current = dri2_surf->back;
673 dri2_surf->back = NULL;
Benjamin Franzke93aea842011-02-04 12:39:40 +0100674
Kristian Høgsbergde315f72013-02-02 12:26:12 -0500675 create_wl_buffer(dri2_surf);
Benjamin Franzke93aea842011-02-04 12:39:40 +0100676
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500677 wl_surface_attach(dri2_surf->wl_win->surface,
678 dri2_surf->current->wl_buffer,
679 dri2_surf->dx, dri2_surf->dy);
680
681 dri2_surf->wl_win->attached_width = dri2_surf->base.Width;
682 dri2_surf->wl_win->attached_height = dri2_surf->base.Height;
683 /* reset resize growing parameters */
684 dri2_surf->dx = 0;
685 dri2_surf->dy = 0;
686
Robert Braggf8c32422012-02-10 16:59:31 +0000687 if (n_rects == 0) {
Kristian Høgsbergbce64c62013-12-04 16:13:35 -0800688 wl_surface_damage(dri2_surf->wl_win->surface,
689 0, 0, INT32_MAX, INT32_MAX);
Robert Braggf8c32422012-02-10 16:59:31 +0000690 } else {
691 for (i = 0; i < n_rects; i++) {
692 const int *rect = &rects[i * 4];
693 wl_surface_damage(dri2_surf->wl_win->surface,
694 rect[0],
695 dri2_surf->base.Height - rect[1] - rect[3],
696 rect[2], rect[3]);
697 }
698 }
Kristian Høgsberg90804e82012-12-13 23:30:45 -0500699
Axel Davy4cd546d2015-05-01 01:16:24 +0200700 if (dri2_dpy->is_different_gpu) {
701 _EGLContext *ctx = _eglGetCurrentContext();
702 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
703 dri2_dpy->image->blitImage(dri2_ctx->dri_context,
704 dri2_surf->current->linear_copy,
705 dri2_surf->current->dri_image,
706 0, 0, dri2_surf->base.Width,
707 dri2_surf->base.Height,
708 0, 0, dri2_surf->base.Width,
709 dri2_surf->base.Height, 0);
710 }
711
Eric Anholt70e8ccc2014-12-21 11:51:33 -0800712 dri2_flush_drawable_for_swapbuffers(disp, draw);
Kristian Høgsberg89ba4362012-11-30 13:29:17 -0500713 (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
Benjamin Franzke93aea842011-02-04 12:39:40 +0100714
Kristian Høgsberg33eb5ea2013-12-04 12:08:35 -0800715 wl_surface_commit(dri2_surf->wl_win->surface);
Neil Roberts992a2db2013-11-15 13:50:50 +0000716
717 /* If we're not waiting for a frame callback then we'll at least throttle
718 * to a sync callback so that we always give a chance for the compositor to
719 * handle the commit and send a release event before checking for a free
720 * buffer */
721 if (dri2_surf->throttle_callback == NULL) {
722 dri2_surf->throttle_callback = wl_display_sync(dri2_dpy->wl_dpy);
723 wl_callback_add_listener(dri2_surf->throttle_callback,
724 &throttle_listener, dri2_surf);
725 wl_proxy_set_queue((struct wl_proxy *) dri2_surf->throttle_callback,
726 dri2_dpy->wl_queue);
727 }
728
Axel Davy402bf6e2013-12-03 17:38:09 +0100729 wl_display_flush(dri2_dpy->wl_dpy);
730
Benjamin Franzke93aea842011-02-04 12:39:40 +0100731 return EGL_TRUE;
732}
733
Kristian Høgsberg6d4d4b02012-12-13 23:32:14 -0500734static EGLint
Chad Versaced019cd82014-01-28 12:47:38 -0800735dri2_wl_query_buffer_age(_EGLDriver *drv,
736 _EGLDisplay *disp, _EGLSurface *surface)
Kristian Høgsberg6d4d4b02012-12-13 23:32:14 -0500737{
738 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
Kristian Høgsberg6d4d4b02012-12-13 23:32:14 -0500739
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -0800740 if (get_back_bo(dri2_surf) < 0) {
Kristian Høgsberg6d4d4b02012-12-13 23:32:14 -0500741 _eglError(EGL_BAD_ALLOC, "dri2_query_buffer_age");
742 return 0;
743 }
744
745 return dri2_surf->back->age;
746}
747
Robert Braggf8c32422012-02-10 16:59:31 +0000748static EGLBoolean
Chad Versaced019cd82014-01-28 12:47:38 -0800749dri2_wl_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
Robert Braggf8c32422012-02-10 16:59:31 +0000750{
Chad Versaced019cd82014-01-28 12:47:38 -0800751 return dri2_wl_swap_buffers_with_damage (drv, disp, draw, NULL, 0);
Robert Braggf8c32422012-02-10 16:59:31 +0000752}
753
Neil Roberts5cddb1c2013-10-28 15:07:03 +0000754static struct wl_buffer *
Chad Versaceeadd5e02014-01-28 17:03:03 -0800755dri2_wl_create_wayland_buffer_from_image(_EGLDriver *drv,
756 _EGLDisplay *disp,
757 _EGLImage *img)
Neil Roberts5cddb1c2013-10-28 15:07:03 +0000758{
759 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
760 struct dri2_egl_image *dri2_img = dri2_egl_image(img);
761 __DRIimage *image = dri2_img->dri_image;
762 struct wl_buffer *buffer;
763 int width, height, format, pitch;
764 enum wl_drm_format wl_format;
765
766 dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &format);
767
768 switch (format) {
769 case __DRI_IMAGE_FORMAT_ARGB8888:
770 if (!(dri2_dpy->formats & HAS_ARGB8888))
771 goto bad_format;
772 wl_format = WL_DRM_FORMAT_ARGB8888;
773 break;
774 case __DRI_IMAGE_FORMAT_XRGB8888:
775 if (!(dri2_dpy->formats & HAS_XRGB8888))
776 goto bad_format;
777 wl_format = WL_DRM_FORMAT_XRGB8888;
778 break;
779 default:
780 goto bad_format;
781 }
782
783 dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_WIDTH, &width);
784 dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_HEIGHT, &height);
785 dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
786
787 if (dri2_dpy->capabilities & WL_DRM_CAPABILITY_PRIME) {
788 int fd;
789
790 dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FD, &fd);
791
792 buffer =
793 wl_drm_create_prime_buffer(dri2_dpy->wl_drm,
794 fd,
795 width, height,
796 wl_format,
797 0, pitch,
798 0, 0,
799 0, 0);
800
801 close(fd);
802 } else {
803 int name;
804
805 dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NAME, &name);
806
807 buffer =
808 wl_drm_create_buffer(dri2_dpy->wl_drm,
809 name,
810 width, height,
811 pitch,
812 wl_format);
813 }
814
815 /* The buffer object will have been created with our internal event queue
816 * because it is using the wl_drm object as a proxy factory. We want the
817 * buffer to be used by the application so we'll reset it to the display's
818 * default event queue */
819 if (buffer)
820 wl_proxy_set_queue((struct wl_proxy *) buffer, NULL);
821
822 return buffer;
823
824bad_format:
825 _eglError(EGL_BAD_MATCH, "unsupported image format");
826 return NULL;
827}
828
Axel Davyfb0960a2015-05-01 01:30:10 +0200829static char
830is_fd_render_node(int fd)
831{
832 struct stat render;
833
834 if (fstat(fd, &render))
835 return 0;
836
837 if (!S_ISCHR(render.st_mode))
838 return 0;
839
840 if (render.st_rdev & 0x80)
841 return 1;
842 return 0;
843}
844
Benjamin Franzke6b369c42011-02-21 16:22:34 +0100845static int
Chad Versaced019cd82014-01-28 12:47:38 -0800846dri2_wl_authenticate(_EGLDisplay *disp, uint32_t id)
Benjamin Franzke6b369c42011-02-21 16:22:34 +0100847{
848 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
849 int ret = 0;
850
Axel Davyfb0960a2015-05-01 01:30:10 +0200851 if (dri2_dpy->is_render_node) {
852 _eglLog(_EGL_WARNING, "wayland-egl: client asks server to "
853 "authenticate for render-nodes");
854 return 0;
855 }
Benjamin Franzkeaa87a932011-05-31 11:45:51 +0200856 dri2_dpy->authenticated = 0;
Benjamin Franzke6b369c42011-02-21 16:22:34 +0100857
Kristian Høgsbergc0f8c992011-04-14 10:42:41 -0400858 wl_drm_authenticate(dri2_dpy->wl_drm, id);
Kristian Høgsberg0229e3a2012-10-10 22:10:42 -0400859 if (roundtrip(dri2_dpy) < 0)
860 ret = -1;
Benjamin Franzke6b369c42011-02-21 16:22:34 +0100861
Kristian Høgsbergc0f8c992011-04-14 10:42:41 -0400862 if (!dri2_dpy->authenticated)
Benjamin Franzke6b369c42011-02-21 16:22:34 +0100863 ret = -1;
864
865 /* reset authenticated */
Benjamin Franzkeaa87a932011-05-31 11:45:51 +0200866 dri2_dpy->authenticated = 1;
Benjamin Franzke6b369c42011-02-21 16:22:34 +0100867
868 return ret;
869}
870
Kristian Høgsbergc0f8c992011-04-14 10:42:41 -0400871static void
872drm_handle_device(void *data, struct wl_drm *drm, const char *device)
873{
874 struct dri2_egl_display *dri2_dpy = data;
875 drm_magic_t magic;
876
877 dri2_dpy->device_name = strdup(device);
878 if (!dri2_dpy->device_name)
879 return;
880
David Friesb6012062011-12-10 11:28:45 -0600881#ifdef O_CLOEXEC
882 dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR | O_CLOEXEC);
883 if (dri2_dpy->fd == -1 && errno == EINVAL)
884#endif
885 {
886 dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR);
887 if (dri2_dpy->fd != -1)
888 fcntl(dri2_dpy->fd, F_SETFD, fcntl(dri2_dpy->fd, F_GETFD) |
889 FD_CLOEXEC);
890 }
Kristian Høgsbergc0f8c992011-04-14 10:42:41 -0400891 if (dri2_dpy->fd == -1) {
892 _eglLog(_EGL_WARNING, "wayland-egl: could not open %s (%s)",
893 dri2_dpy->device_name, strerror(errno));
894 return;
895 }
896
Axel Davyfb0960a2015-05-01 01:30:10 +0200897 if (is_fd_render_node(dri2_dpy->fd)) {
Axel Davyfb0960a2015-05-01 01:30:10 +0200898 dri2_dpy->authenticated = 1;
899 } else {
900 drmGetMagic(dri2_dpy->fd, &magic);
901 wl_drm_authenticate(dri2_dpy->wl_drm, magic);
902 }
Kristian Høgsbergc0f8c992011-04-14 10:42:41 -0400903}
904
905static void
Kristian Høgsberg7b1d94e2011-08-31 16:45:04 -0400906drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
907{
908 struct dri2_egl_display *dri2_dpy = data;
909
910 switch (format) {
Kristian Høgsberg58dc1b22012-01-11 14:23:24 -0500911 case WL_DRM_FORMAT_ARGB8888:
912 dri2_dpy->formats |= HAS_ARGB8888;
Kristian Høgsberg7b1d94e2011-08-31 16:45:04 -0400913 break;
Kristian Høgsberg58dc1b22012-01-11 14:23:24 -0500914 case WL_DRM_FORMAT_XRGB8888:
915 dri2_dpy->formats |= HAS_XRGB8888;
Kristian Høgsberg7b1d94e2011-08-31 16:45:04 -0400916 break;
Singh, Satyeshwar2efc97d2013-10-16 01:10:12 +0000917 case WL_DRM_FORMAT_RGB565:
918 dri2_dpy->formats |= HAS_RGB565;
919 break;
Kristian Høgsberg7b1d94e2011-08-31 16:45:04 -0400920 }
921}
922
923static void
Kristian Høgsbergde315f72013-02-02 12:26:12 -0500924drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value)
925{
926 struct dri2_egl_display *dri2_dpy = data;
927
928 dri2_dpy->capabilities = value;
929}
930
931static void
Kristian Høgsbergc0f8c992011-04-14 10:42:41 -0400932drm_handle_authenticated(void *data, struct wl_drm *drm)
933{
934 struct dri2_egl_display *dri2_dpy = data;
935
Benjamin Franzkeaa87a932011-05-31 11:45:51 +0200936 dri2_dpy->authenticated = 1;
Kristian Høgsbergc0f8c992011-04-14 10:42:41 -0400937}
938
939static const struct wl_drm_listener drm_listener = {
940 drm_handle_device,
Kristian Høgsberg7b1d94e2011-08-31 16:45:04 -0400941 drm_handle_format,
Kristian Høgsbergde315f72013-02-02 12:26:12 -0500942 drm_handle_authenticated,
943 drm_handle_capabilities
Kristian Høgsbergc0f8c992011-04-14 10:42:41 -0400944};
945
Kristian Høgsberg0229e3a2012-10-10 22:10:42 -0400946static void
947registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
948 const char *interface, uint32_t version)
949{
950 struct dri2_egl_display *dri2_dpy = data;
951
Kristian Høgsbergde315f72013-02-02 12:26:12 -0500952 if (version > 1)
953 version = 2;
Kristian Høgsberg0229e3a2012-10-10 22:10:42 -0400954 if (strcmp(interface, "wl_drm") == 0) {
955 dri2_dpy->wl_drm =
Kristian Høgsbergde315f72013-02-02 12:26:12 -0500956 wl_registry_bind(registry, name, &wl_drm_interface, version);
Kristian Høgsberg0229e3a2012-10-10 22:10:42 -0400957 wl_drm_add_listener(dri2_dpy->wl_drm, &drm_listener, dri2_dpy);
958 }
959}
960
Kristian Høgsberg712269d2013-06-18 16:53:46 -0400961static void
962registry_handle_global_remove(void *data, struct wl_registry *registry,
963 uint32_t name)
964{
965}
966
Kristian Høgsberg0229e3a2012-10-10 22:10:42 -0400967static const struct wl_registry_listener registry_listener = {
Kristian Høgsberg712269d2013-06-18 16:53:46 -0400968 registry_handle_global,
969 registry_handle_global_remove
Kristian Høgsberg0229e3a2012-10-10 22:10:42 -0400970};
971
Neil Roberts992a2db2013-11-15 13:50:50 +0000972static EGLBoolean
Chad Versaced019cd82014-01-28 12:47:38 -0800973dri2_wl_swap_interval(_EGLDriver *drv,
Neil Roberts992a2db2013-11-15 13:50:50 +0000974 _EGLDisplay *disp,
975 _EGLSurface *surf,
976 EGLint interval)
977{
978 if (interval > surf->Config->MaxSwapInterval)
979 interval = surf->Config->MaxSwapInterval;
980 else if (interval < surf->Config->MinSwapInterval)
981 interval = surf->Config->MinSwapInterval;
982
983 surf->SwapInterval = interval;
984
985 return EGL_TRUE;
986}
987
988static void
Chad Versaced019cd82014-01-28 12:47:38 -0800989dri2_wl_setup_swap_interval(struct dri2_egl_display *dri2_dpy)
Neil Roberts992a2db2013-11-15 13:50:50 +0000990{
991 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
992
993 /* We can't use values greater than 1 on Wayland because we are using the
994 * frame callback to synchronise the frame and the only way we be sure to
995 * get a frame callback is to attach a new buffer. Therefore we can't just
996 * sit drawing nothing to wait until the next ‘n’ frame callbacks */
997
998 if (dri2_dpy->config)
999 dri2_dpy->config->configQueryi(dri2_dpy->dri_screen,
1000 "vblank_mode", &vblank_mode);
1001 switch (vblank_mode) {
1002 case DRI_CONF_VBLANK_NEVER:
1003 dri2_dpy->min_swap_interval = 0;
1004 dri2_dpy->max_swap_interval = 0;
1005 dri2_dpy->default_swap_interval = 0;
1006 break;
1007 case DRI_CONF_VBLANK_ALWAYS_SYNC:
1008 dri2_dpy->min_swap_interval = 1;
1009 dri2_dpy->max_swap_interval = 1;
1010 dri2_dpy->default_swap_interval = 1;
1011 break;
1012 case DRI_CONF_VBLANK_DEF_INTERVAL_0:
1013 dri2_dpy->min_swap_interval = 0;
1014 dri2_dpy->max_swap_interval = 1;
1015 dri2_dpy->default_swap_interval = 0;
1016 break;
1017 default:
1018 case DRI_CONF_VBLANK_DEF_INTERVAL_1:
1019 dri2_dpy->min_swap_interval = 0;
1020 dri2_dpy->max_swap_interval = 1;
1021 dri2_dpy->default_swap_interval = 1;
1022 break;
1023 }
1024}
1025
Chad Versace90502b12014-01-28 11:41:46 -08001026static struct dri2_egl_display_vtbl dri2_wl_display_vtbl = {
Chad Versaced019cd82014-01-28 12:47:38 -08001027 .authenticate = dri2_wl_authenticate,
Chad Versace0a0c8812014-01-28 16:39:09 -08001028 .create_window_surface = dri2_wl_create_window_surface,
Chad Versace9a40ee12014-02-09 09:13:27 -08001029 .create_pixmap_surface = dri2_wl_create_pixmap_surface,
Chad Versacebf200762014-01-28 17:03:03 -08001030 .create_pbuffer_surface = dri2_fallback_create_pbuffer_surface,
Chad Versace958dd802014-01-28 17:03:03 -08001031 .destroy_surface = dri2_wl_destroy_surface,
Chad Versaceeef68a92014-01-28 17:03:03 -08001032 .create_image = dri2_create_image_khr,
Chad Versace8b9298a2014-01-28 12:34:19 -08001033 .swap_interval = dri2_wl_swap_interval,
Chad Versacead173bc2014-01-28 16:21:21 -08001034 .swap_buffers = dri2_wl_swap_buffers,
Chad Versaced03948a2014-01-28 16:26:44 -08001035 .swap_buffers_with_damage = dri2_wl_swap_buffers_with_damage,
Chad Versace75d398e2014-01-28 17:03:03 -08001036 .swap_buffers_region = dri2_fallback_swap_buffers_region,
Chad Versace688a0e82014-01-28 17:03:03 -08001037 .post_sub_buffer = dri2_fallback_post_sub_buffer,
Chad Versacebc2cbc02014-01-28 17:03:03 -08001038 .copy_buffers = dri2_fallback_copy_buffers,
Chad Versace3fdfbd22014-01-28 17:03:03 -08001039 .query_buffer_age = dri2_wl_query_buffer_age,
Chad Versaceeadd5e02014-01-28 17:03:03 -08001040 .create_wayland_buffer_from_image = dri2_wl_create_wayland_buffer_from_image,
Sarah Sharpc524f3e2014-05-06 12:10:57 -07001041 .get_sync_values = dri2_fallback_get_sync_values,
Chad Versace90502b12014-01-28 11:41:46 -08001042};
1043
Benjamin Franzke93aea842011-02-04 12:39:40 +01001044EGLBoolean
1045dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
1046{
1047 struct dri2_egl_display *dri2_dpy;
Kristian Høgsberg7b1d94e2011-08-31 16:45:04 -04001048 const __DRIconfig *config;
Kristian Høgsberg0229e3a2012-10-10 22:10:42 -04001049 uint32_t types;
Benjamin Franzke93aea842011-02-04 12:39:40 +01001050 int i;
Kristian Høgsberg7b1d94e2011-08-31 16:45:04 -04001051 static const unsigned int argb_masks[4] =
1052 { 0xff0000, 0xff00, 0xff, 0xff000000 };
1053 static const unsigned int rgb_masks[4] = { 0xff0000, 0xff00, 0xff, 0 };
Singh, Satyeshwar2efc97d2013-10-16 01:10:12 +00001054 static const unsigned int rgb565_masks[4] = { 0xf800, 0x07e0, 0x001f, 0 };
Benjamin Franzke93aea842011-02-04 12:39:40 +01001055
Emil Velikov8d4357b2014-01-11 04:52:48 +00001056 loader_set_logger(_eglLog);
1057
Matt Turner6bda0272012-09-04 23:09:22 -07001058 dri2_dpy = calloc(1, sizeof *dri2_dpy);
Benjamin Franzke93aea842011-02-04 12:39:40 +01001059 if (!dri2_dpy)
1060 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
1061
1062 disp->DriverData = (void *) dri2_dpy;
Benjamin Franzkeb8325fd2011-06-11 22:07:02 +02001063 if (disp->PlatformDisplay == NULL) {
1064 dri2_dpy->wl_dpy = wl_display_connect(NULL);
1065 if (dri2_dpy->wl_dpy == NULL)
1066 goto cleanup_dpy;
Benjamin Franzke2a584532011-12-13 14:43:48 +01001067 dri2_dpy->own_device = 1;
Benjamin Franzkeb8325fd2011-06-11 22:07:02 +02001068 } else {
1069 dri2_dpy->wl_dpy = disp->PlatformDisplay;
1070 }
Benjamin Franzke93aea842011-02-04 12:39:40 +01001071
Kristian Høgsberg0229e3a2012-10-10 22:10:42 -04001072 dri2_dpy->wl_queue = wl_display_create_queue(dri2_dpy->wl_dpy);
Kristian Høgsberg112ccfa2013-02-26 12:49:40 -05001073
1074 if (dri2_dpy->own_device)
1075 wl_display_dispatch_pending(dri2_dpy->wl_dpy);
1076
Kristian Høgsberg0229e3a2012-10-10 22:10:42 -04001077 dri2_dpy->wl_registry = wl_display_get_registry(dri2_dpy->wl_dpy);
1078 wl_proxy_set_queue((struct wl_proxy *) dri2_dpy->wl_registry,
1079 dri2_dpy->wl_queue);
1080 wl_registry_add_listener(dri2_dpy->wl_registry,
1081 &registry_listener, dri2_dpy);
1082 if (roundtrip(dri2_dpy) < 0 || dri2_dpy->wl_drm == NULL)
Axel Davy6aaf09b2015-05-01 00:03:32 +02001083 goto cleanup_registry;
Kristian Høgsberg0229e3a2012-10-10 22:10:42 -04001084
1085 if (roundtrip(dri2_dpy) < 0 || dri2_dpy->fd == -1)
Kristian Høgsbergc0f8c992011-04-14 10:42:41 -04001086 goto cleanup_drm;
Kristian Høgsberg56758c82011-02-04 15:37:51 -05001087
Kristian Høgsberg0229e3a2012-10-10 22:10:42 -04001088 if (roundtrip(dri2_dpy) < 0 || !dri2_dpy->authenticated)
Kristian Høgsbergc0f8c992011-04-14 10:42:41 -04001089 goto cleanup_fd;
Benjamin Franzke93aea842011-02-04 12:39:40 +01001090
Axel Davy4cd546d2015-05-01 01:16:24 +02001091 dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd,
1092 &dri2_dpy->is_different_gpu);
1093 if (dri2_dpy->is_different_gpu) {
1094 free(dri2_dpy->device_name);
1095 dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd);
1096 if (!dri2_dpy->device_name) {
1097 _eglError(EGL_BAD_ALLOC, "wayland-egl: failed to get device name "
1098 "for requested GPU");
1099 goto cleanup_fd;
1100 }
1101 }
1102
1103 /* we have to do the check now, because loader_get_user_preferred_fd
1104 * will return a render-node when the requested gpu is different
1105 * to the server, but also if the client asks for the same gpu than
1106 * the server by requesting its pci-id */
1107 dri2_dpy->is_render_node = is_fd_render_node(dri2_dpy->fd);
1108
Emil Velikov8d4357b2014-01-11 04:52:48 +00001109 dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd, 0);
Benjamin Franzke93aea842011-02-04 12:39:40 +01001110 if (dri2_dpy->driver_name == NULL) {
1111 _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name");
1112 goto cleanup_fd;
1113 }
1114
Benjamin Franzke6b369c42011-02-21 16:22:34 +01001115 if (!dri2_load_driver(disp))
Kristian Høgsbergc0f8c992011-04-14 10:42:41 -04001116 goto cleanup_driver_name;
Benjamin Franzke93aea842011-02-04 12:39:40 +01001117
Axel Davyfb0960a2015-05-01 01:30:10 +02001118 dri2_dpy->extensions[0] = &image_loader_extension.base;
1119 dri2_dpy->extensions[1] = &image_lookup_extension.base;
1120 dri2_dpy->extensions[2] = &use_invalidate.base;
Kristian Høgsberg68bb26be2013-11-08 22:10:36 -08001121
Axel Davyfb0960a2015-05-01 01:30:10 +02001122 /* render nodes cannot use Gem names, and thus do not support
1123 * the __DRI_DRI2_LOADER extension */
1124 if (!dri2_dpy->is_render_node) {
1125 dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER;
1126 dri2_dpy->dri2_loader_extension.base.version = 3;
1127 dri2_dpy->dri2_loader_extension.getBuffers = dri2_wl_get_buffers;
1128 dri2_dpy->dri2_loader_extension.flushFrontBuffer = dri2_wl_flush_front_buffer;
1129 dri2_dpy->dri2_loader_extension.getBuffersWithFormat =
1130 dri2_wl_get_buffers_with_format;
1131 dri2_dpy->extensions[3] = &dri2_dpy->dri2_loader_extension.base;
1132 dri2_dpy->extensions[4] = NULL;
1133 } else
1134 dri2_dpy->extensions[3] = NULL;
Benjamin Franzke93aea842011-02-04 12:39:40 +01001135
Neil Roberts992a2db2013-11-15 13:50:50 +00001136 dri2_dpy->swap_available = EGL_TRUE;
1137
Benjamin Franzke93aea842011-02-04 12:39:40 +01001138 if (!dri2_create_screen(disp))
1139 goto cleanup_driver;
1140
Chad Versaced019cd82014-01-28 12:47:38 -08001141 dri2_wl_setup_swap_interval(dri2_dpy);
Neil Roberts992a2db2013-11-15 13:50:50 +00001142
Axel Davy4cd546d2015-05-01 01:16:24 +02001143 /* To use Prime, we must have _DRI_IMAGE v7 at least.
1144 * createImageFromFds support indicates that Prime export/import
1145 * is supported by the driver. Fall back to
1146 * gem names if we don't have Prime support. */
Kristian Høgsberg16707372013-03-19 13:20:36 -04001147
1148 if (dri2_dpy->image->base.version < 7 ||
1149 dri2_dpy->image->createImageFromFds == NULL)
Neil Roberts63d46612014-04-08 23:28:40 +03001150 dri2_dpy->capabilities &= ~WL_DRM_CAPABILITY_PRIME;
Kristian Høgsberg16707372013-03-19 13:20:36 -04001151
Axel Davyfb0960a2015-05-01 01:30:10 +02001152 /* We cannot use Gem names with render-nodes, only prime fds (dma-buf).
1153 * The server needs to accept them */
1154 if (dri2_dpy->is_render_node &&
1155 !(dri2_dpy->capabilities & WL_DRM_CAPABILITY_PRIME)) {
1156 _eglLog(_EGL_WARNING, "wayland-egl: display is not render-node capable");
1157 goto cleanup_screen;
1158 }
1159
Axel Davy4cd546d2015-05-01 01:16:24 +02001160 if (dri2_dpy->is_different_gpu &&
1161 (dri2_dpy->image->base.version < 9 ||
1162 dri2_dpy->image->blitImage == NULL)) {
1163 _eglLog(_EGL_WARNING, "wayland-egl: Different GPU selected, but the "
1164 "Image extension in the driver is not "
1165 "compatible. Version 9 or later and blitImage() "
1166 "are required");
1167 goto cleanup_screen;
1168 }
1169
Kristian Høgsberge20a0f12012-10-16 14:30:53 -04001170 types = EGL_WINDOW_BIT;
Kristian Høgsberg7b1d94e2011-08-31 16:45:04 -04001171 for (i = 0; dri2_dpy->driver_configs[i]; i++) {
1172 config = dri2_dpy->driver_configs[i];
Kristian Høgsberg58dc1b22012-01-11 14:23:24 -05001173 if (dri2_dpy->formats & HAS_XRGB8888)
Kristian Høgsberg44e584a2013-09-14 23:13:22 -07001174 dri2_add_config(disp, config, i + 1, types, NULL, rgb_masks);
Kristian Høgsberg58dc1b22012-01-11 14:23:24 -05001175 if (dri2_dpy->formats & HAS_ARGB8888)
Kristian Høgsberg44e584a2013-09-14 23:13:22 -07001176 dri2_add_config(disp, config, i + 1, types, NULL, argb_masks);
Singh, Satyeshwar2efc97d2013-10-16 01:10:12 +00001177 if (dri2_dpy->formats & HAS_RGB565)
Kristian Høgsberg44e584a2013-09-14 23:13:22 -07001178 dri2_add_config(disp, config, i + 1, types, NULL, rgb565_masks);
Kristian Høgsberg7b1d94e2011-08-31 16:45:04 -04001179 }
Benjamin Franzke93aea842011-02-04 12:39:40 +01001180
Benjamin Franzke6b369c42011-02-21 16:22:34 +01001181 disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
Axel Davy4cd546d2015-05-01 01:16:24 +02001182 /* When cannot convert EGLImage to wl_buffer when on a different gpu,
1183 * because the buffer of the EGLImage has likely a tiling mode the server
1184 * gpu won't support. These is no way to check for now. Thus do not support the
1185 * extension */
1186 if (!dri2_dpy->is_different_gpu) {
1187 disp->Extensions.WL_create_wayland_buffer_from_image = EGL_TRUE;
1188 } else {
1189 dri2_wl_display_vtbl.create_wayland_buffer_from_image =
1190 dri2_fallback_create_wayland_buffer_from_image;
1191 }
Kristian Høgsberg6d4d4b02012-12-13 23:32:14 -05001192 disp->Extensions.EXT_buffer_age = EGL_TRUE;
Benjamin Franzke6b369c42011-02-21 16:22:34 +01001193
Robert Braggf8c32422012-02-10 16:59:31 +00001194 disp->Extensions.EXT_swap_buffers_with_damage = EGL_TRUE;
1195
Benjamin Franzke93aea842011-02-04 12:39:40 +01001196 /* we're supporting EGL 1.4 */
1197 disp->VersionMajor = 1;
1198 disp->VersionMinor = 4;
1199
Chad Versace90502b12014-01-28 11:41:46 -08001200 /* Fill vtbl last to prevent accidentally calling virtual function during
1201 * initialization.
1202 */
1203 dri2_dpy->vtbl = &dri2_wl_display_vtbl;
1204
Benjamin Franzke93aea842011-02-04 12:39:40 +01001205 return EGL_TRUE;
1206
Axel Davyfb0960a2015-05-01 01:30:10 +02001207 cleanup_screen:
1208 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
Benjamin Franzke93aea842011-02-04 12:39:40 +01001209 cleanup_driver:
1210 dlclose(dri2_dpy->driver);
Benjamin Franzke93aea842011-02-04 12:39:40 +01001211 cleanup_driver_name:
1212 free(dri2_dpy->driver_name);
1213 cleanup_fd:
1214 close(dri2_dpy->fd);
Kristian Høgsbergc0f8c992011-04-14 10:42:41 -04001215 cleanup_drm:
1216 free(dri2_dpy->device_name);
1217 wl_drm_destroy(dri2_dpy->wl_drm);
Axel Davy6aaf09b2015-05-01 00:03:32 +02001218 cleanup_registry:
1219 wl_registry_destroy(dri2_dpy->wl_registry);
1220 wl_event_queue_destroy(dri2_dpy->wl_queue);
Benjamin Franzke93aea842011-02-04 12:39:40 +01001221 cleanup_dpy:
1222 free(dri2_dpy);
1223
1224 return EGL_FALSE;
1225}