platform_wayland.c revision dc520d4fefa6a92b3a8f2eed3c5a1044dfccb3ff
1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2011 Intel Corporation 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copy of this software and associated documentation files (the "Software"), 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to deal in the Software without restriction, including without limitation 7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * and/or sell copies of the Software, and to permit persons to whom the 9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * Software is furnished to do so, subject to the following conditions: 10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * 117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * The above copyright notice and this permission notice (including the next 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * paragraph) shall be included in all copies or substantial portions of the 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Software. 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DEALINGS IN THE SOFTWARE. 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Authors: 253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch * Kristian Høgsberg <krh@bitplanet.net> 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Benjamin Franzke <benjaminfranzke@googlemail.com> 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <stdlib.h> 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits.h> 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dlfcn.h> 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h> 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h> 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <xf86drm.h> 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "egl_dri2.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <wayland-client.h> 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "wayland-drm-client-protocol.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sync_callback(void *data) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int *done = data; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *done = 1; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)force_roundtrip(struct wl_display *display) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int done = 0; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wl_display_sync_callback(display, sync_callback, &done); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wl_display_iterate(display, WL_DISPLAY_WRITABLE); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!done) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wl_display_iterate(display, WL_DISPLAY_READABLE); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static _EGLSurface * 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _EGLConfig *conf, EGLNativeWindowType window, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const EGLint *attrib_list) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct dri2_egl_surface *dri2_surf; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct dri2_egl_buffer *dri2_buf; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) drv; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf = malloc(sizeof *dri2_surf); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dri2_surf) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list)) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto cleanup_surf; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < WL_BUFFER_COUNT; ++i) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf->wl_drm_buffer[i] = NULL; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < __DRI_BUFFER_COUNT; ++i) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf->dri_buffers[i] = NULL; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf->pending_buffer = NULL; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf->block_swap_buffers = EGL_FALSE; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EGL_WINDOW_BIT: 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf->wl_win = (struct wl_egl_window *) window; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf->type = DRI2_WINDOW_SURFACE; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf->base.Width = -1; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf->base.Height = -1; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EGL_PIXMAP_BIT: 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf->wl_pix = (struct wl_egl_pixmap *) window; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf->type = DRI2_PIXMAP_SURFACE; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf->base.Width = dri2_surf->wl_pix->width; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf->base.Height = dri2_surf->wl_pix->height; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dri2_surf->wl_pix->driver_private) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_buf = dri2_surf->wl_pix->driver_private; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT] = dri2_buf->dri_buffer; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto cleanup_surf; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf->dri_drawable = 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen, 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type == EGL_WINDOW_BIT ? 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_conf->dri_double_config : 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_conf->dri_single_config, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dri2_surf->dri_drawable == NULL) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto cleanup_dri_drawable; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &dri2_surf->base; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cleanup_dri_drawable: 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cleanup_surf: 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(dri2_surf); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static _EGLSurface * 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, 147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) _EGLConfig *conf, EGLNativeWindowType window, 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const EGLint *attrib_list) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf, 151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) window, attrib_list); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static _EGLSurface * 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp, 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _EGLConfig *conf, EGLNativePixmapType pixmap, 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const EGLint *attrib_list) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dri2_create_surface(drv, disp, EGL_PIXMAP_BIT, conf, 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pixmap, attrib_list); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called via eglDestroySurface(), drv->API.DestroySurface(). 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static EGLBoolean 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) drv; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!_eglPutSurface(surf)) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return EGL_TRUE; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < WL_BUFFER_COUNT; ++i) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dri2_surf->wl_drm_buffer[i]) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wl_buffer_destroy(dri2_surf->wl_drm_buffer[i]); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (i = 0; i < __DRI_BUFFER_COUNT; ++i) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dri2_surf->dri_buffers[i] && !(i == __DRI_BUFFER_FRONT_LEFT && 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf->type == DRI2_PIXMAP_SURFACE)) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen, 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf->dri_buffers[i]); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(surf); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return EGL_TRUE; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dri2_wl_egl_pixmap_destroy(struct wl_egl_pixmap *egl_pixmap) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct dri2_egl_buffer *dri2_buf = egl_pixmap->driver_private; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(dri2_buf); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_buf->dri2_dpy->dri2->releaseBuffer(dri2_buf->dri2_dpy->dri_screen, 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_buf->dri_buffer); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(dri2_buf); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) egl_pixmap->driver_private = NULL; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) egl_pixmap->destroy = NULL; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct wl_buffer * 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)wayland_create_buffer(struct dri2_egl_surface *dri2_surf, 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __DRIbuffer *buffer, 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct wl_visual *visual) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct dri2_egl_display *dri2_dpy = 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_egl_display(dri2_surf->base.Resource.Display); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return wl_drm_create_buffer(dri2_dpy->wl_drm, buffer->name, 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_surf->base.Width, dri2_surf->base.Height, 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer->pitch, visual); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dri2_process_back_buffer(struct dri2_egl_surface *dri2_surf, unsigned format) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct dri2_egl_display *dri2_dpy = 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dri2_egl_display(dri2_surf->base.Resource.Display); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) format; 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) switch (dri2_surf->type) { 233 case DRI2_WINDOW_SURFACE: 234 /* allocate a front buffer for our double-buffered window*/ 235 dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT] = 236 dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, 237 __DRI_BUFFER_FRONT_LEFT, format, 238 dri2_surf->base.Width, dri2_surf->base.Height); 239 break; 240 default: 241 break; 242 } 243} 244 245static void 246dri2_process_front_buffer(struct dri2_egl_surface *dri2_surf, unsigned format) 247{ 248 struct dri2_egl_display *dri2_dpy = 249 dri2_egl_display(dri2_surf->base.Resource.Display); 250 struct dri2_egl_buffer *dri2_buf; 251 252 switch (dri2_surf->type) { 253 case DRI2_PIXMAP_SURFACE: 254 dri2_buf = malloc(sizeof *dri2_buf); 255 if (!dri2_buf) 256 return; 257 258 dri2_buf->dri_buffer = dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]; 259 dri2_buf->dri2_dpy = dri2_dpy; 260 261 dri2_surf->wl_pix->driver_private = dri2_buf; 262 dri2_surf->wl_pix->destroy = dri2_wl_egl_pixmap_destroy; 263 break; 264 default: 265 break; 266 } 267} 268 269static void 270dri2_release_pending_buffer(void *data) 271{ 272 struct dri2_egl_surface *dri2_surf = data; 273 struct dri2_egl_display *dri2_dpy = 274 dri2_egl_display(dri2_surf->base.Resource.Display); 275 276 /* FIXME: print internal error */ 277 if (!dri2_surf->pending_buffer) 278 return; 279 280 dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen, 281 dri2_surf->pending_buffer); 282 dri2_surf->pending_buffer = NULL; 283} 284 285static void 286dri2_release_buffers(struct dri2_egl_surface *dri2_surf) 287{ 288 struct dri2_egl_display *dri2_dpy = 289 dri2_egl_display(dri2_surf->base.Resource.Display); 290 int i; 291 292 for (i = 0; i < __DRI_BUFFER_COUNT; ++i) { 293 if (dri2_surf->dri_buffers[i]) { 294 switch (i) { 295 case __DRI_BUFFER_FRONT_LEFT: 296 if (dri2_surf->pending_buffer) 297 force_roundtrip(dri2_dpy->wl_dpy); 298 dri2_surf->pending_buffer = dri2_surf->dri_buffers[i]; 299 wl_display_sync_callback(dri2_dpy->wl_dpy, 300 dri2_release_pending_buffer, dri2_surf); 301 break; 302 default: 303 dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen, 304 dri2_surf->dri_buffers[i]); 305 break; 306 } 307 dri2_surf->dri_buffers[i] = NULL; 308 } 309 } 310} 311 312static __DRIbuffer * 313dri2_get_buffers_with_format(__DRIdrawable * driDrawable, 314 int *width, int *height, 315 unsigned int *attachments, int count, 316 int *out_count, void *loaderPrivate) 317{ 318 struct dri2_egl_surface *dri2_surf = loaderPrivate; 319 struct dri2_egl_display *dri2_dpy = 320 dri2_egl_display(dri2_surf->base.Resource.Display); 321 int i; 322 323 if (dri2_surf->type == DRI2_WINDOW_SURFACE && 324 (dri2_surf->base.Width != dri2_surf->wl_win->width || 325 dri2_surf->base.Height != dri2_surf->wl_win->height)) { 326 327 dri2_release_buffers(dri2_surf); 328 329 dri2_surf->base.Width = dri2_surf->wl_win->width; 330 dri2_surf->base.Height = dri2_surf->wl_win->height; 331 dri2_surf->dx = dri2_surf->wl_win->dx; 332 dri2_surf->dy = dri2_surf->wl_win->dy; 333 334 for (i = 0; i < WL_BUFFER_COUNT; ++i) { 335 if (dri2_surf->wl_drm_buffer[i]) 336 wl_buffer_destroy(dri2_surf->wl_drm_buffer[i]); 337 dri2_surf->wl_drm_buffer[i] = NULL; 338 } 339 } 340 341 dri2_surf->buffer_count = 0; 342 for (i = 0; i < 2*count; i+=2) { 343 assert(attachments[i] < __DRI_BUFFER_COUNT); 344 assert(dri2_surf->buffer_count < 5); 345 346 if (dri2_surf->dri_buffers[attachments[i]] == NULL) { 347 348 dri2_surf->dri_buffers[attachments[i]] = 349 dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, 350 attachments[i], attachments[i+1], 351 dri2_surf->base.Width, dri2_surf->base.Height); 352 353 if (!dri2_surf->dri_buffers[attachments[i]]) 354 continue; 355 356 if (attachments[i] == __DRI_BUFFER_FRONT_LEFT) 357 dri2_process_front_buffer(dri2_surf, attachments[i+1]); 358 else if (attachments[i] == __DRI_BUFFER_BACK_LEFT) 359 dri2_process_back_buffer(dri2_surf, attachments[i+1]); 360 } 361 362 memcpy(&dri2_surf->buffers[dri2_surf->buffer_count], 363 dri2_surf->dri_buffers[attachments[i]], 364 sizeof(__DRIbuffer)); 365 366 dri2_surf->buffer_count++; 367 } 368 369 assert(dri2_surf->type == DRI2_PIXMAP_SURFACE || 370 dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]); 371 372 if (dri2_surf->type == DRI2_PIXMAP_SURFACE && !dri2_surf->wl_pix->buffer) 373 dri2_surf->wl_pix->buffer = 374 wayland_create_buffer(dri2_surf, 375 dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT], 376 dri2_surf->wl_pix->visual); 377 378 *out_count = dri2_surf->buffer_count; 379 if (dri2_surf->buffer_count == 0) 380 return NULL; 381 382 *width = dri2_surf->base.Width; 383 *height = dri2_surf->base.Height; 384 385 return dri2_surf->buffers; 386} 387 388static __DRIbuffer * 389dri2_get_buffers(__DRIdrawable * driDrawable, 390 int *width, int *height, 391 unsigned int *attachments, int count, 392 int *out_count, void *loaderPrivate) 393{ 394 unsigned int *attachments_with_format; 395 __DRIbuffer *buffer; 396 const unsigned int format = 32; 397 int i; 398 399 attachments_with_format = calloc(count * 2, sizeof(unsigned int)); 400 if (!attachments_with_format) { 401 *out_count = 0; 402 return NULL; 403 } 404 405 for (i = 0; i < count; ++i) { 406 attachments_with_format[2*i] = attachments[i]; 407 attachments_with_format[2*i + 1] = format; 408 } 409 410 buffer = 411 dri2_get_buffers_with_format(driDrawable, 412 width, height, 413 attachments_with_format, count, 414 out_count, loaderPrivate); 415 416 free(attachments_with_format); 417 418 return buffer; 419} 420 421 422static void 423dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) 424{ 425 (void) driDrawable; 426 427 /* FIXME: Does EGL support front buffer rendering at all? */ 428 429#if 0 430 struct dri2_egl_surface *dri2_surf = loaderPrivate; 431 432 dri2WaitGL(dri2_surf); 433#else 434 (void) loaderPrivate; 435#endif 436} 437 438static void 439wayland_frame_callback(struct wl_surface *surface, void *data, uint32_t time) 440{ 441 struct dri2_egl_surface *dri2_surf = data; 442 443 dri2_surf->block_swap_buffers = EGL_FALSE; 444} 445 446static inline void 447pointer_swap(const void **p1, const void **p2) 448{ 449 const void *tmp = *p1; 450 *p1 = *p2; 451 *p2 = tmp; 452} 453 454/** 455 * Called via eglSwapBuffers(), drv->API.SwapBuffers(). 456 */ 457static EGLBoolean 458dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) 459{ 460 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 461 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); 462 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 463 464 while (dri2_surf->block_swap_buffers) 465 wl_display_iterate(dri2_dpy->wl_dpy, WL_DISPLAY_READABLE); 466 467 dri2_surf->block_swap_buffers = EGL_TRUE; 468 wl_display_frame_callback(dri2_dpy->wl_dpy, 469 dri2_surf->wl_win->surface, 470 wayland_frame_callback, dri2_surf); 471 472 if (dri2_surf->type == DRI2_WINDOW_SURFACE) { 473 pointer_swap( 474 (const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT], 475 (const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]); 476 477 dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]->attachment = 478 __DRI_BUFFER_FRONT_LEFT; 479 dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]->attachment = 480 __DRI_BUFFER_BACK_LEFT; 481 482 pointer_swap((const void **) &dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT], 483 (const void **) &dri2_surf->wl_drm_buffer[WL_BUFFER_BACK]); 484 485 if (!dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT]) 486 dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT] = 487 wayland_create_buffer(dri2_surf, 488 dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT], 489 dri2_surf->wl_win->visual); 490 491 wl_buffer_damage(dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT], 0, 0, 492 dri2_surf->base.Width, dri2_surf->base.Height); 493 wl_surface_attach(dri2_surf->wl_win->surface, 494 dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT], 495 dri2_surf->dx, dri2_surf->dy); 496 497 dri2_surf->wl_win->attached_width = dri2_surf->base.Width; 498 dri2_surf->wl_win->attached_height = dri2_surf->base.Height; 499 /* reset resize growing parameters */ 500 dri2_surf->dx = 0; 501 dri2_surf->dy = 0; 502 503 wl_surface_damage(dri2_surf->wl_win->surface, 0, 0, 504 dri2_surf->base.Width, dri2_surf->base.Height); 505 } 506 507 _EGLContext *ctx; 508 if (dri2_drv->glFlush) { 509 ctx = _eglGetCurrentContext(); 510 if (ctx && ctx->DrawSurface == &dri2_surf->base) 511 dri2_drv->glFlush(); 512 } 513 514 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); 515 (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable); 516 517 return EGL_TRUE; 518} 519 520/** 521 * Called via eglCreateImageKHR(), drv->API.CreateImageKHR(). 522 */ 523static _EGLImage * 524dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, 525 EGLClientBuffer buffer, const EGLint *attr_list) 526{ 527 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 528 struct wl_egl_pixmap *wl_egl_pixmap = (struct wl_egl_pixmap *) buffer; 529 struct dri2_egl_buffer *dri2_buf; 530 EGLint wl_attr_list[] = { 531 EGL_WIDTH, 0, 532 EGL_HEIGHT, 0, 533 EGL_DRM_BUFFER_STRIDE_MESA, 0, 534 EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, 535 EGL_NONE 536 }; 537 538 dri2_buf = malloc(sizeof *dri2_buf); 539 if (!dri2_buf) 540 return NULL; 541 542 dri2_buf->dri2_dpy = dri2_dpy; 543 dri2_buf->dri_buffer = 544 dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, 545 __DRI_BUFFER_FRONT_LEFT, 32, 546 wl_egl_pixmap->width, 547 wl_egl_pixmap->height); 548 549 wl_egl_pixmap->destroy = dri2_wl_egl_pixmap_destroy; 550 wl_egl_pixmap->driver_private = dri2_buf; 551 552 wl_egl_pixmap->buffer = 553 wl_drm_create_buffer(dri2_dpy->wl_drm, 554 dri2_buf->dri_buffer->name, 555 wl_egl_pixmap->width, 556 wl_egl_pixmap->height, 557 dri2_buf->dri_buffer->pitch, 558 wl_egl_pixmap->visual); 559 560 wl_attr_list[1] = wl_egl_pixmap->width; 561 wl_attr_list[3] = wl_egl_pixmap->height; 562 wl_attr_list[5] = dri2_buf->dri_buffer->pitch / 4; 563 564 return dri2_create_image_khr(disp->Driver, disp, ctx, EGL_DRM_BUFFER_MESA, 565 (EGLClientBuffer)(intptr_t) dri2_buf->dri_buffer->name, wl_attr_list); 566} 567 568static _EGLImage * 569dri2_wayland_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, 570 _EGLContext *ctx, EGLenum target, 571 EGLClientBuffer buffer, const EGLint *attr_list) 572{ 573 (void) drv; 574 575 switch (target) { 576 case EGL_NATIVE_PIXMAP_KHR: 577 return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list); 578 default: 579 return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list); 580 } 581} 582 583static int 584dri2_wayland_authenticate(_EGLDisplay *disp, uint32_t id) 585{ 586 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 587 int ret = 0; 588 589 dri2_dpy->authenticated = false; 590 591 wl_drm_authenticate(dri2_dpy->wl_drm, id); 592 force_roundtrip(dri2_dpy->wl_dpy); 593 594 if (!dri2_dpy->authenticated) 595 ret = -1; 596 597 /* reset authenticated */ 598 dri2_dpy->authenticated = true; 599 600 return ret; 601} 602 603/** 604 * Called via eglTerminate(), drv->API.Terminate(). 605 */ 606static EGLBoolean 607dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp) 608{ 609 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 610 611 _eglReleaseDisplayResources(drv, disp); 612 _eglCleanupDisplay(disp); 613 614 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 615 close(dri2_dpy->fd); 616 dlclose(dri2_dpy->driver); 617 free(dri2_dpy->driver_name); 618 free(dri2_dpy); 619 disp->DriverData = NULL; 620 621 return EGL_TRUE; 622} 623 624static void 625drm_handle_device(void *data, struct wl_drm *drm, const char *device) 626{ 627 struct dri2_egl_display *dri2_dpy = data; 628 drm_magic_t magic; 629 630 dri2_dpy->device_name = strdup(device); 631 if (!dri2_dpy->device_name) 632 return; 633 634 dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR); 635 if (dri2_dpy->fd == -1) { 636 _eglLog(_EGL_WARNING, "wayland-egl: could not open %s (%s)", 637 dri2_dpy->device_name, strerror(errno)); 638 return; 639 } 640 641 drmGetMagic(dri2_dpy->fd, &magic); 642 wl_drm_authenticate(dri2_dpy->wl_drm, magic); 643} 644 645static void 646drm_handle_authenticated(void *data, struct wl_drm *drm) 647{ 648 struct dri2_egl_display *dri2_dpy = data; 649 650 dri2_dpy->authenticated = true; 651} 652 653static const struct wl_drm_listener drm_listener = { 654 drm_handle_device, 655 drm_handle_authenticated 656}; 657 658EGLBoolean 659dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp) 660{ 661 struct dri2_egl_display *dri2_dpy; 662 uint32_t id; 663 int i; 664 665 drv->API.CreateWindowSurface = dri2_create_window_surface; 666 drv->API.CreatePixmapSurface = dri2_create_pixmap_surface; 667 drv->API.DestroySurface = dri2_destroy_surface; 668 drv->API.SwapBuffers = dri2_swap_buffers; 669 drv->API.CreateImageKHR = dri2_wayland_create_image_khr; 670 drv->API.Terminate = dri2_terminate; 671 672 dri2_dpy = malloc(sizeof *dri2_dpy); 673 if (!dri2_dpy) 674 return _eglError(EGL_BAD_ALLOC, "eglInitialize"); 675 676 memset(dri2_dpy, 0, sizeof *dri2_dpy); 677 678 disp->DriverData = (void *) dri2_dpy; 679 dri2_dpy->wl_dpy = disp->PlatformDisplay; 680 681 id = wl_display_get_global(dri2_dpy->wl_dpy, "wl_drm", 1); 682 if (id == 0) 683 force_roundtrip(dri2_dpy->wl_dpy); 684 id = wl_display_get_global(dri2_dpy->wl_dpy, "wl_drm", 1); 685 if (id == 0) 686 goto cleanup_dpy; 687 dri2_dpy->wl_drm = wl_drm_create(dri2_dpy->wl_dpy, id, 1); 688 if (!dri2_dpy->wl_drm) 689 goto cleanup_dpy; 690 wl_drm_add_listener(dri2_dpy->wl_drm, &drm_listener, dri2_dpy); 691 force_roundtrip(dri2_dpy->wl_dpy); 692 if (dri2_dpy->fd == -1) 693 goto cleanup_drm; 694 695 force_roundtrip(dri2_dpy->wl_dpy); 696 if (!dri2_dpy->authenticated) 697 goto cleanup_fd; 698 699 dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd); 700 if (dri2_dpy->driver_name == NULL) { 701 _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name"); 702 goto cleanup_fd; 703 } 704 705 if (!dri2_load_driver(disp)) 706 goto cleanup_driver_name; 707 708 dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER; 709 dri2_dpy->dri2_loader_extension.base.version = 3; 710 dri2_dpy->dri2_loader_extension.getBuffers = dri2_get_buffers; 711 dri2_dpy->dri2_loader_extension.flushFrontBuffer = dri2_flush_front_buffer; 712 dri2_dpy->dri2_loader_extension.getBuffersWithFormat = 713 dri2_get_buffers_with_format; 714 715 dri2_dpy->extensions[0] = &dri2_dpy->dri2_loader_extension.base; 716 dri2_dpy->extensions[1] = &image_lookup_extension.base; 717 dri2_dpy->extensions[2] = NULL; 718 719 if (!dri2_create_screen(disp)) 720 goto cleanup_driver; 721 722 for (i = 0; dri2_dpy->driver_configs[i]; i++) 723 dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, 724 EGL_WINDOW_BIT | EGL_PIXMAP_BIT, NULL); 725 726 727 disp->Extensions.KHR_image_pixmap = EGL_TRUE; 728 729 disp->Extensions.WL_bind_wayland_display = EGL_TRUE; 730 dri2_dpy->authenticate = dri2_wayland_authenticate; 731 732 /* we're supporting EGL 1.4 */ 733 disp->VersionMajor = 1; 734 disp->VersionMinor = 4; 735 736 return EGL_TRUE; 737 738 cleanup_driver: 739 dlclose(dri2_dpy->driver); 740 cleanup_driver_name: 741 free(dri2_dpy->driver_name); 742 cleanup_fd: 743 close(dri2_dpy->fd); 744 cleanup_drm: 745 free(dri2_dpy->device_name); 746 wl_drm_destroy(dri2_dpy->wl_drm); 747 cleanup_dpy: 748 free(dri2_dpy); 749 750 return EGL_FALSE; 751} 752