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