gbm_dri.c revision 6bb71b8cbe6b17a5d59e369631502e642804406e
16e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)/* 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Copyright © 2011 Intel Corporation 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * copy of this software and associated documentation files (the "Software"), 66e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * to deal in the Software without restriction, including without limitation 76e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * the rights to use, copy, modify, merge, publish, distribute, sublicense, 86e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * and/or sell copies of the Software, and to permit persons to whom the 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Software is furnished to do so, subject to the following conditions: 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * The above copyright notice and this permission notice (including the next 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * paragraph) shall be included in all copies or substantial portions of the 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Software. 146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * DEALINGS IN THE SOFTWARE. 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Authors: 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Benjamin Franzke <benjaminfranzke@googlemail.com> 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <stdio.h> 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <stdlib.h> 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <stddef.h> 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <stdint.h> 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <string.h> 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <limits.h> 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <sys/types.h> 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <unistd.h> 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <dlfcn.h> 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <GL/gl.h> /* dri_interface needs GL types */ 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <GL/internal/dri_interface.h> 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "gbm_driint.h" 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "gbmint.h" 4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)/* For importing wl_buffer */ 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if HAVE_WAYLAND_PLATFORM 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "../../../egl/wayland/wayland-drm/wayland-drm.h" 496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static __DRIimage * 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)dri_lookup_egl_image(__DRIscreen *screen, void *image, void *data) 5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles){ 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) struct gbm_dri_device *dri = data; 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (dri->lookup_image == NULL) 576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return NULL; 586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return dri->lookup_image(screen, image, dri->lookup_user_data); 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static __DRIbuffer * 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)dri_get_buffers(__DRIdrawable * driDrawable, 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int *width, int *height, 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unsigned int *attachments, int count, 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int *out_count, void *data) 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){ 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) struct gbm_dri_surface *surf = data; 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (dri->get_buffers == NULL) 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return NULL; 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return dri->get_buffers(driDrawable, width, height, attachments, 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) count, out_count, surf->dri_private); 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)dri_flush_front_buffer(__DRIdrawable * driDrawable, void *data) 806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles){ 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) struct gbm_dri_surface *surf = data; 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (dri->flush_front_buffer != NULL) 856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) dri->flush_front_buffer(driDrawable, surf->dri_private); 866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static __DRIbuffer * 896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)dri_get_buffers_with_format(__DRIdrawable * driDrawable, 906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int *width, int *height, 916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) unsigned int *attachments, int count, 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int *out_count, void *data) 936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles){ 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) struct gbm_dri_surface *surf = data; 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (dri->get_buffers_with_format == NULL) 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return NULL; 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dri->get_buffers_with_format(driDrawable, width, height, attachments, 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) count, out_count, surf->dri_private); 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const __DRIuseInvalidateExtension use_invalidate = { 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { __DRI_USE_INVALIDATE, 1 } 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const __DRIimageLookupExtension image_lookup_extension = { 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { __DRI_IMAGE_LOOKUP, 1 }, 1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) dri_lookup_egl_image 1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}; 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)const __DRIdri2LoaderExtension dri2_loader_extension = { 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { __DRI_DRI2_LOADER, 3 }, 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dri_get_buffers, 1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) dri_flush_front_buffer, 1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) dri_get_buffers_with_format, 1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}; 1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)struct dri_extension_match { 1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const char *name; 1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int version; 1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int offset; 1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}; 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static struct dri_extension_match dri_core_extensions[] = { 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { __DRI2_FLUSH, 1, offsetof(struct gbm_dri_device, flush) }, 1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) { __DRI_IMAGE, 1, offsetof(struct gbm_dri_device, image) }, 1306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) { NULL, 0, 0 } 1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}; 1326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static struct dri_extension_match gbm_dri_device_extensions[] = { 1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) { __DRI_CORE, 1, offsetof(struct gbm_dri_device, core) }, 1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) { __DRI_DRI2, 1, offsetof(struct gbm_dri_device, dri2) }, 1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) { NULL, 0, 0 } 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static int 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)dri_bind_extensions(struct gbm_dri_device *dri, 1416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) struct dri_extension_match *matches, 1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const __DRIextension **extensions) 1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles){ 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int i, j, ret = 0; 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void *field; 1466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (i = 0; extensions[i]; i++) { 1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) for (j = 0; matches[j].name; j++) { 1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (strcmp(extensions[i]->name, matches[j].name) == 0 && 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions[i]->version >= matches[j].version) { 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) field = ((char *) dri + matches[j].offset); 1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) *(const __DRIextension **) field = extensions[i]; 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) for (j = 0; matches[j].name; j++) { 1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) field = ((char *) dri + matches[j].offset); 1596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (*(const __DRIextension **) field == NULL) { 1606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ret = -1; 1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ret; 1656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static int 1686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)dri_load_driver(struct gbm_dri_device *dri) 1696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles){ 1706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const __DRIextension **extensions; 1716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) char path[PATH_MAX], *search_paths, *p, *next, *end; 1726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) search_paths = NULL; 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (geteuid() == getuid()) { 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /* don't allow setuid apps to use GBM_DRIVERS_PATH */ 1766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) search_paths = getenv("GBM_DRIVERS_PATH"); 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (search_paths == NULL) 1796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) search_paths = DEFAULT_DRIVER_DIR; 1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dri->driver = NULL; 1826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) end = search_paths + strlen(search_paths); 1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (p = search_paths; p < end && dri->driver == NULL; p = next + 1) { 1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int len; 1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) next = strchr(p, ':'); 1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (next == NULL) 1876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) next = end; 1886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) len = next - p; 1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#if GLX_USE_TLS 1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) snprintf(path, sizeof path, 1926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "%.*s/tls/%s_dri.so", len, p, dri->base.driver_name); 1936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) dri->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); 1946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif 1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (dri->driver == NULL) { 1966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) snprintf(path, sizeof path, 1976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "%.*s/%s_dri.so", len, p, dri->base.driver_name); 1986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) dri->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); 1996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (dri->driver == NULL) 2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fprintf(stderr, "failed to open %s: %s\n", path, dlerror()); 2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (dri->driver == NULL) { 2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fprintf(stderr, "gbm: failed to open any driver (search paths %s)", 2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) search_paths); 2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return -1; 2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions = dlsym(dri->driver, __DRI_DRIVER_EXTENSIONS); 2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (extensions == NULL) { 2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fprintf(stderr, "gbm: driver exports no extensions (%s)", dlerror()); 2136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) dlclose(dri->driver); 2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return -1; 2156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (dri_bind_extensions(dri, gbm_dri_device_extensions, extensions) < 0) { 2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dlclose(dri->driver); 2206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) fprintf(stderr, "failed to bind extensions\n"); 2216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return -1; 2226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return 0; 2256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 2266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static int 2286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)dri_screen_create(struct gbm_dri_device *dri) 2296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles){ 2306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const __DRIextension **extensions; 2316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int ret = 0; 2326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) dri->base.driver_name = dri_fd_get_driver_name(dri->base.base.fd); 2346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (dri->base.driver_name == NULL) 2356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return -1; 23603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 23703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ret = dri_load_driver(dri); 23803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (ret) { 2396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) fprintf(stderr, "failed to load driver: %s\n", dri->base.driver_name); 2406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ret; 2416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) }; 2426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) dri->extensions[0] = &image_lookup_extension.base; 2446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) dri->extensions[1] = &use_invalidate.base; 2456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) dri->extensions[2] = &dri2_loader_extension.base; 246 dri->extensions[3] = NULL; 247 248 if (dri->dri2 == NULL) 249 return -1; 250 251 dri->screen = dri->dri2->createNewScreen(0, dri->base.base.fd, 252 dri->extensions, 253 &dri->driver_configs, dri); 254 if (dri->screen == NULL) 255 return -1; 256 257 extensions = dri->core->getExtensions(dri->screen); 258 if (dri_bind_extensions(dri, dri_core_extensions, extensions) < 0) { 259 ret = -1; 260 goto free_screen; 261 } 262 263 dri->lookup_image = NULL; 264 dri->lookup_user_data = NULL; 265 266 return 0; 267 268free_screen: 269 dri->core->destroyScreen(dri->screen); 270 271 return ret; 272} 273 274static int 275gbm_dri_is_format_supported(struct gbm_device *gbm, 276 uint32_t format, 277 uint32_t usage) 278{ 279 switch (format) { 280 case GBM_BO_FORMAT_XRGB8888: 281 case GBM_FORMAT_XRGB8888: 282 break; 283 case GBM_BO_FORMAT_ARGB8888: 284 case GBM_FORMAT_ARGB8888: 285 if (usage & GBM_BO_USE_SCANOUT) 286 return 0; 287 break; 288 default: 289 return 0; 290 } 291 292 if (usage & GBM_BO_USE_CURSOR_64X64 && 293 usage & GBM_BO_USE_RENDERING) 294 return 0; 295 296 return 1; 297} 298 299static int 300gbm_dri_bo_write(struct gbm_bo *_bo, const void *buf, size_t count) 301{ 302 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 303 void *ptr; 304 int ret; 305 306 if (bo->bo == NULL) 307 return -1; 308 309 ret = kms_bo_map(bo->bo, &ptr); 310 if (ret < 0) 311 return -1; 312 313 memcpy(ptr, buf, count); 314 315 kms_bo_unmap(bo->bo); 316 return 0; 317} 318 319static void 320gbm_dri_bo_destroy(struct gbm_bo *_bo) 321{ 322 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 323 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 324 325 if (bo->image != NULL) 326 dri->image->destroyImage(bo->image); 327 if (bo->bo != NULL) 328 kms_bo_destroy(&bo->bo); 329 free(bo); 330} 331 332static uint32_t 333gbm_dri_to_gbm_format(uint32_t dri_format) 334{ 335 uint32_t ret = 0; 336 337 switch (dri_format) { 338 case __DRI_IMAGE_FORMAT_RGB565: 339 ret = GBM_FORMAT_RGB565; 340 break; 341 case __DRI_IMAGE_FORMAT_XRGB8888: 342 ret = GBM_FORMAT_XRGB8888; 343 break; 344 case __DRI_IMAGE_FORMAT_ARGB8888: 345 ret = GBM_FORMAT_ARGB8888; 346 break; 347 case __DRI_IMAGE_FORMAT_ABGR8888: 348 ret = GBM_FORMAT_ABGR8888; 349 break; 350 default: 351 ret = 0; 352 break; 353 } 354 355 return ret; 356} 357 358static struct gbm_bo * 359gbm_dri_bo_import(struct gbm_device *gbm, 360 uint32_t type, void *buffer, uint32_t usage) 361{ 362 struct gbm_dri_device *dri = gbm_dri_device(gbm); 363 struct gbm_dri_bo *bo; 364 __DRIimage *image; 365 unsigned dri_use = 0; 366 int dri_format, width, height, gbm_format, stride, cpp, offset; 367 368 switch (type) { 369#if HAVE_WAYLAND_PLATFORM 370 case GBM_BO_IMPORT_WL_BUFFER: 371 { 372 struct wl_drm_buffer *wb = (struct wl_drm_buffer *) buffer; 373 374 image = wb->driver_buffer; 375 stride = wb->stride[0]; 376 offset = wb->offset[0]; 377 cpp = 4; 378 switch (wb->format) { 379 case WL_DRM_FORMAT_XRGB8888: 380 dri_format = __DRI_IMAGE_FORMAT_XRGB8888; 381 gbm_format = GBM_FORMAT_XRGB8888; 382 break; 383 case WL_DRM_FORMAT_ARGB8888: 384 dri_format = __DRI_IMAGE_FORMAT_ARGB8888; 385 gbm_format = GBM_FORMAT_ARGB8888; 386 break; 387 case WL_DRM_FORMAT_YUYV: 388 dri_format = __DRI_IMAGE_FORMAT_ARGB8888; 389 gbm_format = GBM_FORMAT_YUYV; 390 break; 391 default: 392 return NULL; 393 } 394 break; 395 } 396#endif 397 398 case GBM_BO_IMPORT_EGL_IMAGE: 399 { 400 if (dri->lookup_image == NULL) 401 return NULL; 402 403 image = dri->lookup_image(dri->screen, buffer, dri->lookup_user_data); 404 dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &dri_format); 405 gbm_format = gbm_dri_to_gbm_format(dri_format); 406 dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride); 407 offset = 0; 408 cpp = 4; 409 break; 410 } 411 412 default: 413 return NULL; 414 } 415 416 417 bo = calloc(1, sizeof *bo); 418 if (bo == NULL) 419 return NULL; 420 421 dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_WIDTH, &width); 422 dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_HEIGHT, &height); 423 424 bo->image = dri->image->createSubImage(image, 425 width, height, dri_format, 426 offset, stride / cpp, NULL); 427 428 429 if (usage & GBM_BO_USE_SCANOUT) 430 dri_use |= __DRI_IMAGE_USE_SCANOUT; 431 if (usage & GBM_BO_USE_CURSOR_64X64) 432 dri_use |= __DRI_IMAGE_USE_CURSOR; 433 if (dri->image->base.version >= 2 && 434 !dri->image->validateUsage(bo->image, dri_use)) { 435 free(bo); 436 return NULL; 437 } 438 439 bo->base.base.gbm = gbm; 440 bo->base.base.width = width; 441 bo->base.base.height = height; 442 bo->base.base.stride = stride; 443 bo->base.base.format = gbm_format; 444 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE, 445 &bo->base.base.handle.s32); 446 447 return &bo->base.base; 448} 449 450static struct gbm_bo * 451gbm_dri_bo_create(struct gbm_device *gbm, 452 uint32_t width, uint32_t height, 453 uint32_t format, uint32_t usage) 454{ 455 struct gbm_dri_device *dri = gbm_dri_device(gbm); 456 struct gbm_dri_bo *bo; 457 int dri_format; 458 unsigned dri_use = 0; 459 460 bo = calloc(1, sizeof *bo); 461 if (bo == NULL) 462 return NULL; 463 464 bo->base.base.gbm = gbm; 465 bo->base.base.width = width; 466 bo->base.base.height = height; 467 468 if (usage & GBM_BO_USE_WRITE) { 469 int ret; 470 unsigned attrs[7] = { 471 KMS_WIDTH, 64, 472 KMS_HEIGHT, 64, 473 KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8, 474 KMS_TERMINATE_PROP_LIST, 475 }; 476 477 if (!(usage & GBM_BO_USE_CURSOR_64X64)) 478 return NULL; 479 480 if (dri->kms == NULL) 481 return NULL; 482 483 ret = kms_bo_create(dri->kms, attrs, &bo->bo); 484 if (ret < 0) { 485 free(bo); 486 return NULL; 487 } 488 489 kms_bo_get_prop(bo->bo, KMS_PITCH, &bo->base.base.stride); 490 kms_bo_get_prop(bo->bo, KMS_HANDLE, (unsigned*)&bo->base.base.handle); 491 492 return &bo->base.base; 493 } 494 495 switch (format) { 496 case GBM_FORMAT_RGB565: 497 dri_format =__DRI_IMAGE_FORMAT_RGB565; 498 break; 499 case GBM_FORMAT_XRGB8888: 500 case GBM_BO_FORMAT_XRGB8888: 501 dri_format = __DRI_IMAGE_FORMAT_XRGB8888; 502 break; 503 case GBM_FORMAT_ARGB8888: 504 case GBM_BO_FORMAT_ARGB8888: 505 dri_format = __DRI_IMAGE_FORMAT_ARGB8888; 506 break; 507 case GBM_FORMAT_ABGR8888: 508 dri_format = __DRI_IMAGE_FORMAT_ABGR8888; 509 break; 510 default: 511 return NULL; 512 } 513 514 if (usage & GBM_BO_USE_SCANOUT) 515 dri_use |= __DRI_IMAGE_USE_SCANOUT; 516 if (usage & GBM_BO_USE_CURSOR_64X64) 517 dri_use |= __DRI_IMAGE_USE_CURSOR; 518 519 /* Gallium drivers requires shared in order to get the handle/stride */ 520 dri_use |= __DRI_IMAGE_USE_SHARE; 521 522 bo->image = 523 dri->image->createImage(dri->screen, 524 width, height, 525 dri_format, dri_use, 526 bo); 527 if (bo->image == NULL) 528 return NULL; 529 530 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE, 531 &bo->base.base.handle.s32); 532 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, 533 (int *) &bo->base.base.stride); 534 535 return &bo->base.base; 536} 537 538static struct gbm_surface * 539gbm_dri_surface_create(struct gbm_device *gbm, 540 uint32_t width, uint32_t height, 541 uint32_t format, uint32_t flags) 542{ 543 struct gbm_dri_surface *surf; 544 545 surf = calloc(1, sizeof *surf); 546 if (surf == NULL) 547 return NULL; 548 549 surf->base.gbm = gbm; 550 surf->base.width = width; 551 surf->base.height = height; 552 surf->base.format = format; 553 surf->base.flags = flags; 554 555 return &surf->base; 556} 557 558static void 559gbm_dri_surface_destroy(struct gbm_surface *_surf) 560{ 561 struct gbm_dri_surface *surf = gbm_dri_surface(_surf); 562 563 free(surf); 564} 565 566static void 567dri_destroy(struct gbm_device *gbm) 568{ 569 struct gbm_dri_device *dri = gbm_dri_device(gbm); 570 571 dri->core->destroyScreen(dri->screen); 572 free(dri->driver_configs); 573 dlclose(dri->driver); 574 free(dri->base.driver_name); 575 576 free(dri); 577} 578 579static struct gbm_device * 580dri_device_create(int fd) 581{ 582 struct gbm_dri_device *dri; 583 int ret; 584 585 dri = calloc(1, sizeof *dri); 586 587 dri->base.base.fd = fd; 588 dri->base.base.bo_create = gbm_dri_bo_create; 589 dri->base.base.bo_import = gbm_dri_bo_import; 590 dri->base.base.is_format_supported = gbm_dri_is_format_supported; 591 dri->base.base.bo_write = gbm_dri_bo_write; 592 dri->base.base.bo_destroy = gbm_dri_bo_destroy; 593 dri->base.base.destroy = dri_destroy; 594 dri->base.base.surface_create = gbm_dri_surface_create; 595 dri->base.base.surface_destroy = gbm_dri_surface_destroy; 596 597 dri->base.type = GBM_DRM_DRIVER_TYPE_DRI; 598 dri->base.base.name = "drm"; 599 600 kms_create(fd, &dri->kms); 601 if (dri->kms == NULL) 602 goto err_kms; 603 604 ret = dri_screen_create(dri); 605 if (ret) 606 goto err_dri; 607 608 return &dri->base.base; 609 610err_dri: 611 kms_destroy(&dri->kms); 612err_kms: 613 free(dri); 614 return NULL; 615} 616 617struct gbm_backend gbm_dri_backend = { 618 .backend_name = "dri", 619 .create_device = dri_device_create, 620}; 621