1848b8605Smrg/* 2848b8605Smrg * Copyright © 2011 Intel Corporation 3848b8605Smrg * 4848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5848b8605Smrg * copy of this software and associated documentation files (the "Software"), 6848b8605Smrg * to deal in the Software without restriction, including without limitation 7848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 9848b8605Smrg * Software is furnished to do so, subject to the following conditions: 10848b8605Smrg * 11848b8605Smrg * The above copyright notice and this permission notice (including the next 12848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the 13848b8605Smrg * Software. 14848b8605Smrg * 15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16848b8605Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18848b8605Smrg * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19848b8605Smrg * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20848b8605Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21848b8605Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22848b8605Smrg * DEALINGS IN THE SOFTWARE. 23848b8605Smrg * 24848b8605Smrg * Authors: 25848b8605Smrg * Benjamin Franzke <benjaminfranzke@googlemail.com> 26848b8605Smrg */ 27848b8605Smrg 28848b8605Smrg#include <stdio.h> 29848b8605Smrg#include <stdlib.h> 30848b8605Smrg#include <stddef.h> 31848b8605Smrg#include <stdint.h> 32b8e80941Smrg#include <stdbool.h> 33848b8605Smrg#include <string.h> 34848b8605Smrg#include <errno.h> 35848b8605Smrg#include <limits.h> 36b8e80941Smrg#include <assert.h> 37848b8605Smrg 38848b8605Smrg#include <sys/types.h> 39848b8605Smrg#include <unistd.h> 40848b8605Smrg#include <dlfcn.h> 41848b8605Smrg#include <xf86drm.h> 42b8e80941Smrg#include "drm-uapi/drm_fourcc.h" 43848b8605Smrg 44848b8605Smrg#include <GL/gl.h> /* dri_interface needs GL types */ 45848b8605Smrg#include <GL/internal/dri_interface.h> 46848b8605Smrg 47848b8605Smrg#include "gbm_driint.h" 48848b8605Smrg 49848b8605Smrg#include "gbmint.h" 50848b8605Smrg#include "loader.h" 51b8e80941Smrg#include "util/debug.h" 52b8e80941Smrg#include "util/macros.h" 53848b8605Smrg 54848b8605Smrg/* For importing wl_buffer */ 55848b8605Smrg#if HAVE_WAYLAND_PLATFORM 56b8e80941Smrg#include "wayland-drm.h" 57848b8605Smrg#endif 58848b8605Smrg 59848b8605Smrgstatic __DRIimage * 60848b8605Smrgdri_lookup_egl_image(__DRIscreen *screen, void *image, void *data) 61848b8605Smrg{ 62848b8605Smrg struct gbm_dri_device *dri = data; 63848b8605Smrg 64848b8605Smrg if (dri->lookup_image == NULL) 65848b8605Smrg return NULL; 66848b8605Smrg 67848b8605Smrg return dri->lookup_image(screen, image, dri->lookup_user_data); 68848b8605Smrg} 69848b8605Smrg 70848b8605Smrgstatic __DRIbuffer * 71848b8605Smrgdri_get_buffers(__DRIdrawable * driDrawable, 72848b8605Smrg int *width, int *height, 73848b8605Smrg unsigned int *attachments, int count, 74848b8605Smrg int *out_count, void *data) 75848b8605Smrg{ 76848b8605Smrg struct gbm_dri_surface *surf = data; 77848b8605Smrg struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 78848b8605Smrg 79848b8605Smrg if (dri->get_buffers == NULL) 80848b8605Smrg return NULL; 81848b8605Smrg 82848b8605Smrg return dri->get_buffers(driDrawable, width, height, attachments, 83848b8605Smrg count, out_count, surf->dri_private); 84848b8605Smrg} 85848b8605Smrg 86848b8605Smrgstatic void 87848b8605Smrgdri_flush_front_buffer(__DRIdrawable * driDrawable, void *data) 88848b8605Smrg{ 89848b8605Smrg struct gbm_dri_surface *surf = data; 90848b8605Smrg struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 91848b8605Smrg 92848b8605Smrg if (dri->flush_front_buffer != NULL) 93848b8605Smrg dri->flush_front_buffer(driDrawable, surf->dri_private); 94848b8605Smrg} 95848b8605Smrg 96848b8605Smrgstatic __DRIbuffer * 97848b8605Smrgdri_get_buffers_with_format(__DRIdrawable * driDrawable, 98848b8605Smrg int *width, int *height, 99848b8605Smrg unsigned int *attachments, int count, 100848b8605Smrg int *out_count, void *data) 101848b8605Smrg{ 102848b8605Smrg struct gbm_dri_surface *surf = data; 103848b8605Smrg struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 104848b8605Smrg 105848b8605Smrg if (dri->get_buffers_with_format == NULL) 106848b8605Smrg return NULL; 107848b8605Smrg 108848b8605Smrg return 109848b8605Smrg dri->get_buffers_with_format(driDrawable, width, height, attachments, 110848b8605Smrg count, out_count, surf->dri_private); 111848b8605Smrg} 112848b8605Smrg 113848b8605Smrgstatic int 114848b8605Smrgimage_get_buffers(__DRIdrawable *driDrawable, 115848b8605Smrg unsigned int format, 116848b8605Smrg uint32_t *stamp, 117848b8605Smrg void *loaderPrivate, 118848b8605Smrg uint32_t buffer_mask, 119848b8605Smrg struct __DRIimageList *buffers) 120848b8605Smrg{ 121848b8605Smrg struct gbm_dri_surface *surf = loaderPrivate; 122848b8605Smrg struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 123848b8605Smrg 124848b8605Smrg if (dri->image_get_buffers == NULL) 125848b8605Smrg return 0; 126848b8605Smrg 127848b8605Smrg return dri->image_get_buffers(driDrawable, format, stamp, 128848b8605Smrg surf->dri_private, buffer_mask, buffers); 129848b8605Smrg} 130848b8605Smrg 131848b8605Smrgstatic void 132848b8605Smrgswrast_get_drawable_info(__DRIdrawable *driDrawable, 133848b8605Smrg int *x, 134848b8605Smrg int *y, 135848b8605Smrg int *width, 136848b8605Smrg int *height, 137848b8605Smrg void *loaderPrivate) 138848b8605Smrg{ 139848b8605Smrg struct gbm_dri_surface *surf = loaderPrivate; 140848b8605Smrg 141848b8605Smrg *x = 0; 142848b8605Smrg *y = 0; 143848b8605Smrg *width = surf->base.width; 144848b8605Smrg *height = surf->base.height; 145848b8605Smrg} 146848b8605Smrg 147848b8605Smrgstatic void 148848b8605Smrgswrast_put_image2(__DRIdrawable *driDrawable, 149848b8605Smrg int op, 150848b8605Smrg int x, 151848b8605Smrg int y, 152848b8605Smrg int width, 153848b8605Smrg int height, 154848b8605Smrg int stride, 155848b8605Smrg char *data, 156848b8605Smrg void *loaderPrivate) 157848b8605Smrg{ 158848b8605Smrg struct gbm_dri_surface *surf = loaderPrivate; 159848b8605Smrg struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 160848b8605Smrg 161848b8605Smrg dri->swrast_put_image2(driDrawable, 162848b8605Smrg op, x, y, 163848b8605Smrg width, height, stride, 164848b8605Smrg data, surf->dri_private); 165848b8605Smrg} 166848b8605Smrg 167848b8605Smrgstatic void 168848b8605Smrgswrast_put_image(__DRIdrawable *driDrawable, 169848b8605Smrg int op, 170848b8605Smrg int x, 171848b8605Smrg int y, 172848b8605Smrg int width, 173848b8605Smrg int height, 174848b8605Smrg char *data, 175848b8605Smrg void *loaderPrivate) 176848b8605Smrg{ 177848b8605Smrg swrast_put_image2(driDrawable, op, x, y, width, height, 178b8e80941Smrg width * 4, data, loaderPrivate); 179848b8605Smrg} 180848b8605Smrg 181848b8605Smrgstatic void 182848b8605Smrgswrast_get_image(__DRIdrawable *driDrawable, 183848b8605Smrg int x, 184848b8605Smrg int y, 185848b8605Smrg int width, 186848b8605Smrg int height, 187848b8605Smrg char *data, 188848b8605Smrg void *loaderPrivate) 189848b8605Smrg{ 190848b8605Smrg struct gbm_dri_surface *surf = loaderPrivate; 191848b8605Smrg struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 192848b8605Smrg 193848b8605Smrg dri->swrast_get_image(driDrawable, 194848b8605Smrg x, y, 195848b8605Smrg width, height, 196848b8605Smrg data, surf->dri_private); 197848b8605Smrg} 198848b8605Smrg 199848b8605Smrgstatic const __DRIuseInvalidateExtension use_invalidate = { 200848b8605Smrg .base = { __DRI_USE_INVALIDATE, 1 } 201848b8605Smrg}; 202848b8605Smrg 203848b8605Smrgstatic const __DRIimageLookupExtension image_lookup_extension = { 204848b8605Smrg .base = { __DRI_IMAGE_LOOKUP, 1 }, 205848b8605Smrg 206848b8605Smrg .lookupEGLImage = dri_lookup_egl_image 207848b8605Smrg}; 208848b8605Smrg 209848b8605Smrgstatic const __DRIdri2LoaderExtension dri2_loader_extension = { 210848b8605Smrg .base = { __DRI_DRI2_LOADER, 3 }, 211848b8605Smrg 212848b8605Smrg .getBuffers = dri_get_buffers, 213848b8605Smrg .flushFrontBuffer = dri_flush_front_buffer, 214848b8605Smrg .getBuffersWithFormat = dri_get_buffers_with_format, 215848b8605Smrg}; 216848b8605Smrg 217848b8605Smrgstatic const __DRIimageLoaderExtension image_loader_extension = { 218848b8605Smrg .base = { __DRI_IMAGE_LOADER, 1 }, 219848b8605Smrg 220848b8605Smrg .getBuffers = image_get_buffers, 221848b8605Smrg .flushFrontBuffer = dri_flush_front_buffer, 222848b8605Smrg}; 223848b8605Smrg 224848b8605Smrgstatic const __DRIswrastLoaderExtension swrast_loader_extension = { 225848b8605Smrg .base = { __DRI_SWRAST_LOADER, 2 }, 226848b8605Smrg 227848b8605Smrg .getDrawableInfo = swrast_get_drawable_info, 228848b8605Smrg .putImage = swrast_put_image, 229848b8605Smrg .getImage = swrast_get_image, 230848b8605Smrg .putImage2 = swrast_put_image2 231848b8605Smrg}; 232848b8605Smrg 233848b8605Smrgstatic const __DRIextension *gbm_dri_screen_extensions[] = { 234848b8605Smrg &image_lookup_extension.base, 235848b8605Smrg &use_invalidate.base, 236848b8605Smrg &dri2_loader_extension.base, 237848b8605Smrg &image_loader_extension.base, 238848b8605Smrg &swrast_loader_extension.base, 239848b8605Smrg NULL, 240848b8605Smrg}; 241848b8605Smrg 242848b8605Smrgstruct dri_extension_match { 243848b8605Smrg const char *name; 244848b8605Smrg int version; 245848b8605Smrg int offset; 246b8e80941Smrg int optional; 247848b8605Smrg}; 248848b8605Smrg 249848b8605Smrgstatic struct dri_extension_match dri_core_extensions[] = { 250848b8605Smrg { __DRI2_FLUSH, 1, offsetof(struct gbm_dri_device, flush) }, 251848b8605Smrg { __DRI_IMAGE, 1, offsetof(struct gbm_dri_device, image) }, 252b8e80941Smrg { __DRI2_FENCE, 1, offsetof(struct gbm_dri_device, fence), 1 }, 253848b8605Smrg { NULL, 0, 0 } 254848b8605Smrg}; 255848b8605Smrg 256848b8605Smrgstatic struct dri_extension_match gbm_dri_device_extensions[] = { 257848b8605Smrg { __DRI_CORE, 1, offsetof(struct gbm_dri_device, core) }, 258848b8605Smrg { __DRI_DRI2, 1, offsetof(struct gbm_dri_device, dri2) }, 259848b8605Smrg { NULL, 0, 0 } 260848b8605Smrg}; 261848b8605Smrg 262848b8605Smrgstatic struct dri_extension_match gbm_swrast_device_extensions[] = { 263848b8605Smrg { __DRI_CORE, 1, offsetof(struct gbm_dri_device, core), }, 264848b8605Smrg { __DRI_SWRAST, 1, offsetof(struct gbm_dri_device, swrast) }, 265848b8605Smrg { NULL, 0, 0 } 266848b8605Smrg}; 267848b8605Smrg 268848b8605Smrgstatic int 269848b8605Smrgdri_bind_extensions(struct gbm_dri_device *dri, 270848b8605Smrg struct dri_extension_match *matches, 271848b8605Smrg const __DRIextension **extensions) 272848b8605Smrg{ 273848b8605Smrg int i, j, ret = 0; 274848b8605Smrg void *field; 275848b8605Smrg 276848b8605Smrg for (i = 0; extensions[i]; i++) { 277848b8605Smrg for (j = 0; matches[j].name; j++) { 278848b8605Smrg if (strcmp(extensions[i]->name, matches[j].name) == 0 && 279848b8605Smrg extensions[i]->version >= matches[j].version) { 280848b8605Smrg field = ((char *) dri + matches[j].offset); 281848b8605Smrg *(const __DRIextension **) field = extensions[i]; 282848b8605Smrg } 283848b8605Smrg } 284848b8605Smrg } 285848b8605Smrg 286848b8605Smrg for (j = 0; matches[j].name; j++) { 287848b8605Smrg field = ((char *) dri + matches[j].offset); 288b8e80941Smrg if ((*(const __DRIextension **) field == NULL) && !matches[j].optional) { 289848b8605Smrg ret = -1; 290848b8605Smrg } 291848b8605Smrg } 292848b8605Smrg 293848b8605Smrg return ret; 294848b8605Smrg} 295848b8605Smrg 296848b8605Smrgstatic const __DRIextension ** 297848b8605Smrgdri_open_driver(struct gbm_dri_device *dri) 298848b8605Smrg{ 299b8e80941Smrg /* Temporarily work around dri driver libs that need symbols in libglapi 300b8e80941Smrg * but don't automatically link it in. 301b8e80941Smrg */ 302b8e80941Smrg /* XXX: Library name differs on per platforms basis. Update this as 303b8e80941Smrg * osx/cygwin/windows/bsd gets support for GBM.. 304b8e80941Smrg */ 305b8e80941Smrg dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL); 306b8e80941Smrg 307b8e80941Smrg static const char *search_path_vars[] = { 308848b8605Smrg /* Read GBM_DRIVERS_PATH first for compatibility, but LIBGL_DRIVERS_PATH 309848b8605Smrg * is recommended over GBM_DRIVERS_PATH. 310848b8605Smrg */ 311b8e80941Smrg "GBM_DRIVERS_PATH", 312848b8605Smrg /* Read LIBGL_DRIVERS_PATH if GBM_DRIVERS_PATH was not set. 313848b8605Smrg * LIBGL_DRIVERS_PATH is recommended over GBM_DRIVERS_PATH. 314848b8605Smrg */ 315b8e80941Smrg "LIBGL_DRIVERS_PATH", 316b8e80941Smrg NULL 317b8e80941Smrg }; 318b8e80941Smrg return loader_open_driver(dri->driver_name, &dri->driver, search_path_vars); 319848b8605Smrg} 320848b8605Smrg 321848b8605Smrgstatic int 322848b8605Smrgdri_load_driver(struct gbm_dri_device *dri) 323848b8605Smrg{ 324848b8605Smrg const __DRIextension **extensions; 325848b8605Smrg 326848b8605Smrg extensions = dri_open_driver(dri); 327848b8605Smrg if (!extensions) 328848b8605Smrg return -1; 329848b8605Smrg 330848b8605Smrg if (dri_bind_extensions(dri, gbm_dri_device_extensions, extensions) < 0) { 331848b8605Smrg dlclose(dri->driver); 332848b8605Smrg fprintf(stderr, "failed to bind extensions\n"); 333848b8605Smrg return -1; 334848b8605Smrg } 335848b8605Smrg 336848b8605Smrg dri->driver_extensions = extensions; 337848b8605Smrg 338848b8605Smrg return 0; 339848b8605Smrg} 340848b8605Smrg 341848b8605Smrgstatic int 342848b8605Smrgdri_load_driver_swrast(struct gbm_dri_device *dri) 343848b8605Smrg{ 344848b8605Smrg const __DRIextension **extensions; 345848b8605Smrg 346848b8605Smrg extensions = dri_open_driver(dri); 347848b8605Smrg if (!extensions) 348848b8605Smrg return -1; 349848b8605Smrg 350848b8605Smrg if (dri_bind_extensions(dri, gbm_swrast_device_extensions, extensions) < 0) { 351848b8605Smrg dlclose(dri->driver); 352848b8605Smrg fprintf(stderr, "failed to bind extensions\n"); 353848b8605Smrg return -1; 354848b8605Smrg } 355848b8605Smrg 356848b8605Smrg dri->driver_extensions = extensions; 357848b8605Smrg 358848b8605Smrg return 0; 359848b8605Smrg} 360848b8605Smrg 361848b8605Smrgstatic int 362b8e80941Smrgdri_screen_create_dri2(struct gbm_dri_device *dri, char *driver_name) 363848b8605Smrg{ 364848b8605Smrg const __DRIextension **extensions; 365848b8605Smrg int ret = 0; 366848b8605Smrg 367b8e80941Smrg dri->driver_name = driver_name; 368b8e80941Smrg if (dri->driver_name == NULL) 369848b8605Smrg return -1; 370848b8605Smrg 371848b8605Smrg ret = dri_load_driver(dri); 372848b8605Smrg if (ret) { 373b8e80941Smrg fprintf(stderr, "failed to load driver: %s\n", dri->driver_name); 374848b8605Smrg return ret; 375b8e80941Smrg } 376848b8605Smrg 377b8e80941Smrg dri->loader_extensions = gbm_dri_screen_extensions; 378848b8605Smrg 379848b8605Smrg if (dri->dri2 == NULL) 380848b8605Smrg return -1; 381848b8605Smrg 382848b8605Smrg if (dri->dri2->base.version >= 4) { 383b8e80941Smrg dri->screen = dri->dri2->createNewScreen2(0, dri->base.fd, 384b8e80941Smrg dri->loader_extensions, 385848b8605Smrg dri->driver_extensions, 386848b8605Smrg &dri->driver_configs, dri); 387848b8605Smrg } else { 388b8e80941Smrg dri->screen = dri->dri2->createNewScreen(0, dri->base.fd, 389b8e80941Smrg dri->loader_extensions, 390848b8605Smrg &dri->driver_configs, dri); 391848b8605Smrg } 392848b8605Smrg if (dri->screen == NULL) 393848b8605Smrg return -1; 394848b8605Smrg 395848b8605Smrg extensions = dri->core->getExtensions(dri->screen); 396848b8605Smrg if (dri_bind_extensions(dri, dri_core_extensions, extensions) < 0) { 397848b8605Smrg ret = -1; 398848b8605Smrg goto free_screen; 399848b8605Smrg } 400848b8605Smrg 401848b8605Smrg dri->lookup_image = NULL; 402848b8605Smrg dri->lookup_user_data = NULL; 403848b8605Smrg 404848b8605Smrg return 0; 405848b8605Smrg 406848b8605Smrgfree_screen: 407848b8605Smrg dri->core->destroyScreen(dri->screen); 408848b8605Smrg 409848b8605Smrg return ret; 410848b8605Smrg} 411848b8605Smrg 412848b8605Smrgstatic int 413848b8605Smrgdri_screen_create_swrast(struct gbm_dri_device *dri) 414848b8605Smrg{ 415848b8605Smrg int ret; 416848b8605Smrg 417b8e80941Smrg dri->driver_name = strdup("swrast"); 418b8e80941Smrg if (dri->driver_name == NULL) 419848b8605Smrg return -1; 420848b8605Smrg 421848b8605Smrg ret = dri_load_driver_swrast(dri); 422848b8605Smrg if (ret) { 423848b8605Smrg fprintf(stderr, "failed to load swrast driver\n"); 424848b8605Smrg return ret; 425848b8605Smrg } 426848b8605Smrg 427b8e80941Smrg dri->loader_extensions = gbm_dri_screen_extensions; 428848b8605Smrg 429848b8605Smrg if (dri->swrast == NULL) 430848b8605Smrg return -1; 431848b8605Smrg 432848b8605Smrg if (dri->swrast->base.version >= 4) { 433b8e80941Smrg dri->screen = dri->swrast->createNewScreen2(0, dri->loader_extensions, 434848b8605Smrg dri->driver_extensions, 435848b8605Smrg &dri->driver_configs, dri); 436848b8605Smrg } else { 437b8e80941Smrg dri->screen = dri->swrast->createNewScreen(0, dri->loader_extensions, 438848b8605Smrg &dri->driver_configs, dri); 439848b8605Smrg } 440848b8605Smrg if (dri->screen == NULL) 441848b8605Smrg return -1; 442848b8605Smrg 443848b8605Smrg dri->lookup_image = NULL; 444848b8605Smrg dri->lookup_user_data = NULL; 445848b8605Smrg 446848b8605Smrg return 0; 447848b8605Smrg} 448848b8605Smrg 449848b8605Smrgstatic int 450848b8605Smrgdri_screen_create(struct gbm_dri_device *dri) 451848b8605Smrg{ 452b8e80941Smrg char *driver_name; 453848b8605Smrg 454b8e80941Smrg driver_name = loader_get_driver_for_fd(dri->base.fd); 455848b8605Smrg if (!driver_name) 456848b8605Smrg return -1; 457848b8605Smrg 458848b8605Smrg return dri_screen_create_dri2(dri, driver_name); 459848b8605Smrg} 460848b8605Smrg 461848b8605Smrgstatic int 462848b8605Smrgdri_screen_create_sw(struct gbm_dri_device *dri) 463848b8605Smrg{ 464b8e80941Smrg char *driver_name; 465848b8605Smrg int ret; 466848b8605Smrg 467848b8605Smrg driver_name = strdup("kms_swrast"); 468848b8605Smrg if (!driver_name) 469848b8605Smrg return -errno; 470848b8605Smrg 471848b8605Smrg ret = dri_screen_create_dri2(dri, driver_name); 472848b8605Smrg if (ret == 0) 473848b8605Smrg return ret; 474848b8605Smrg 475848b8605Smrg return dri_screen_create_swrast(dri); 476848b8605Smrg} 477848b8605Smrg 478b8e80941Smrgstatic const struct gbm_dri_visual gbm_dri_visuals_table[] = { 479b8e80941Smrg { 480b8e80941Smrg GBM_FORMAT_R8, __DRI_IMAGE_FORMAT_R8, 481b8e80941Smrg { 0x000000ff, 0x00000000, 0x00000000, 0x00000000 }, 482b8e80941Smrg }, 483b8e80941Smrg { 484b8e80941Smrg GBM_FORMAT_GR88, __DRI_IMAGE_FORMAT_GR88, 485b8e80941Smrg { 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000 }, 486b8e80941Smrg }, 487b8e80941Smrg { 488b8e80941Smrg GBM_FORMAT_ARGB1555, __DRI_IMAGE_FORMAT_ARGB1555, 489b8e80941Smrg { 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 }, 490b8e80941Smrg }, 491b8e80941Smrg { 492b8e80941Smrg GBM_FORMAT_RGB565, __DRI_IMAGE_FORMAT_RGB565, 493b8e80941Smrg { 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 }, 494b8e80941Smrg }, 495b8e80941Smrg { 496b8e80941Smrg GBM_FORMAT_XRGB8888, __DRI_IMAGE_FORMAT_XRGB8888, 497b8e80941Smrg { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }, 498b8e80941Smrg }, 499b8e80941Smrg { 500b8e80941Smrg GBM_FORMAT_ARGB8888, __DRI_IMAGE_FORMAT_ARGB8888, 501b8e80941Smrg { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, 502b8e80941Smrg }, 503b8e80941Smrg { 504b8e80941Smrg GBM_FORMAT_XBGR8888, __DRI_IMAGE_FORMAT_XBGR8888, 505b8e80941Smrg { 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 }, 506b8e80941Smrg }, 507b8e80941Smrg { 508b8e80941Smrg GBM_FORMAT_ABGR8888, __DRI_IMAGE_FORMAT_ABGR8888, 509b8e80941Smrg { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, 510b8e80941Smrg }, 511b8e80941Smrg { 512b8e80941Smrg GBM_FORMAT_XRGB2101010, __DRI_IMAGE_FORMAT_XRGB2101010, 513b8e80941Smrg { 0x3ff00000, 0x000ffc00, 0x000003ff, 0x00000000 }, 514b8e80941Smrg }, 515b8e80941Smrg { 516b8e80941Smrg GBM_FORMAT_ARGB2101010, __DRI_IMAGE_FORMAT_ARGB2101010, 517b8e80941Smrg { 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }, 518b8e80941Smrg }, 519b8e80941Smrg { 520b8e80941Smrg GBM_FORMAT_XBGR2101010, __DRI_IMAGE_FORMAT_XBGR2101010, 521b8e80941Smrg { 0x000003ff, 0x000ffc00, 0x3ff00000, 0x00000000 }, 522b8e80941Smrg }, 523b8e80941Smrg { 524b8e80941Smrg GBM_FORMAT_ABGR2101010, __DRI_IMAGE_FORMAT_ABGR2101010, 525b8e80941Smrg { 0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000 }, 526b8e80941Smrg }, 527b8e80941Smrg}; 528b8e80941Smrg 529b8e80941Smrgstatic int 530b8e80941Smrggbm_format_to_dri_format(uint32_t gbm_format) 531b8e80941Smrg{ 532b8e80941Smrg int i; 533b8e80941Smrg 534b8e80941Smrg gbm_format = gbm_format_canonicalize(gbm_format); 535b8e80941Smrg for (i = 0; i < ARRAY_SIZE(gbm_dri_visuals_table); i++) { 536b8e80941Smrg if (gbm_dri_visuals_table[i].gbm_format == gbm_format) 537b8e80941Smrg return gbm_dri_visuals_table[i].dri_image_format; 538b8e80941Smrg } 539b8e80941Smrg 540b8e80941Smrg return 0; 541b8e80941Smrg} 542b8e80941Smrg 543b8e80941Smrgstatic uint32_t 544b8e80941Smrggbm_dri_to_gbm_format(int dri_format) 545b8e80941Smrg{ 546b8e80941Smrg int i; 547b8e80941Smrg 548b8e80941Smrg for (i = 0; i < ARRAY_SIZE(gbm_dri_visuals_table); i++) { 549b8e80941Smrg if (gbm_dri_visuals_table[i].dri_image_format == dri_format) 550b8e80941Smrg return gbm_dri_visuals_table[i].gbm_format; 551b8e80941Smrg } 552b8e80941Smrg 553b8e80941Smrg return 0; 554b8e80941Smrg} 555b8e80941Smrg 556848b8605Smrgstatic int 557848b8605Smrggbm_dri_is_format_supported(struct gbm_device *gbm, 558848b8605Smrg uint32_t format, 559848b8605Smrg uint32_t usage) 560848b8605Smrg{ 561b8e80941Smrg struct gbm_dri_device *dri = gbm_dri_device(gbm); 562b8e80941Smrg int count; 563b8e80941Smrg 564b8e80941Smrg if ((usage & GBM_BO_USE_CURSOR) && (usage & GBM_BO_USE_RENDERING)) 565848b8605Smrg return 0; 566b8e80941Smrg 567b8e80941Smrg format = gbm_format_canonicalize(format); 568b8e80941Smrg if (gbm_format_to_dri_format(format) == 0) 569b8e80941Smrg return 0; 570b8e80941Smrg 571b8e80941Smrg /* If there is no query, fall back to the small table which was originally 572b8e80941Smrg * here. */ 573b8e80941Smrg if (dri->image->base.version <= 15 || !dri->image->queryDmaBufModifiers) { 574b8e80941Smrg switch (format) { 575b8e80941Smrg case GBM_FORMAT_XRGB8888: 576b8e80941Smrg case GBM_FORMAT_ARGB8888: 577b8e80941Smrg case GBM_FORMAT_XBGR8888: 578b8e80941Smrg return 1; 579b8e80941Smrg default: 580b8e80941Smrg return 0; 581b8e80941Smrg } 582848b8605Smrg } 583848b8605Smrg 584b8e80941Smrg /* Check if the driver returns any modifiers for this format; since linear 585b8e80941Smrg * is counted as a modifier, we will have at least one modifier for any 586b8e80941Smrg * supported format. */ 587b8e80941Smrg if (!dri->image->queryDmaBufModifiers(dri->screen, format, 0, NULL, NULL, 588b8e80941Smrg &count)) 589848b8605Smrg return 0; 590848b8605Smrg 591b8e80941Smrg return (count > 0); 592b8e80941Smrg} 593b8e80941Smrg 594b8e80941Smrgstatic int 595b8e80941Smrggbm_dri_get_format_modifier_plane_count(struct gbm_device *gbm, 596b8e80941Smrg uint32_t format, 597b8e80941Smrg uint64_t modifier) 598b8e80941Smrg{ 599b8e80941Smrg struct gbm_dri_device *dri = gbm_dri_device(gbm); 600b8e80941Smrg uint64_t plane_count; 601b8e80941Smrg 602b8e80941Smrg if (dri->image->base.version < 16 || 603b8e80941Smrg !dri->image->queryDmaBufFormatModifierAttribs) 604b8e80941Smrg return -1; 605b8e80941Smrg 606b8e80941Smrg format = gbm_format_canonicalize(format); 607b8e80941Smrg if (gbm_format_to_dri_format(format) == 0) 608b8e80941Smrg return -1; 609b8e80941Smrg 610b8e80941Smrg if (!dri->image->queryDmaBufFormatModifierAttribs( 611b8e80941Smrg dri->screen, format, modifier, 612b8e80941Smrg __DRI_IMAGE_FORMAT_MODIFIER_ATTRIB_PLANE_COUNT, &plane_count)) 613b8e80941Smrg return -1; 614b8e80941Smrg 615b8e80941Smrg return plane_count; 616848b8605Smrg} 617848b8605Smrg 618848b8605Smrgstatic int 619848b8605Smrggbm_dri_bo_write(struct gbm_bo *_bo, const void *buf, size_t count) 620848b8605Smrg{ 621848b8605Smrg struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 622848b8605Smrg 623848b8605Smrg if (bo->image != NULL) { 624848b8605Smrg errno = EINVAL; 625848b8605Smrg return -1; 626848b8605Smrg } 627848b8605Smrg 628848b8605Smrg memcpy(bo->map, buf, count); 629848b8605Smrg 630848b8605Smrg return 0; 631848b8605Smrg} 632848b8605Smrg 633848b8605Smrgstatic int 634848b8605Smrggbm_dri_bo_get_fd(struct gbm_bo *_bo) 635848b8605Smrg{ 636848b8605Smrg struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 637848b8605Smrg struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 638848b8605Smrg int fd; 639848b8605Smrg 640848b8605Smrg if (bo->image == NULL) 641848b8605Smrg return -1; 642848b8605Smrg 643b8e80941Smrg if (!dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_FD, &fd)) 644b8e80941Smrg return -1; 645848b8605Smrg 646848b8605Smrg return fd; 647848b8605Smrg} 648848b8605Smrg 649b8e80941Smrgstatic int 650b8e80941Smrgget_number_planes(struct gbm_dri_device *dri, __DRIimage *image) 651b8e80941Smrg{ 652b8e80941Smrg int num_planes = 0; 653b8e80941Smrg 654b8e80941Smrg /* Dumb buffers are single-plane only. */ 655b8e80941Smrg if (!image) 656b8e80941Smrg return 1; 657b8e80941Smrg 658b8e80941Smrg dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_NUM_PLANES, &num_planes); 659b8e80941Smrg 660b8e80941Smrg if (num_planes <= 0) 661b8e80941Smrg num_planes = 1; 662b8e80941Smrg 663b8e80941Smrg return num_planes; 664b8e80941Smrg} 665b8e80941Smrg 666b8e80941Smrgstatic int 667b8e80941Smrggbm_dri_bo_get_planes(struct gbm_bo *_bo) 668848b8605Smrg{ 669848b8605Smrg struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 670848b8605Smrg struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 671848b8605Smrg 672b8e80941Smrg return get_number_planes(dri, bo->image); 673b8e80941Smrg} 674b8e80941Smrg 675b8e80941Smrgstatic union gbm_bo_handle 676b8e80941Smrggbm_dri_bo_get_handle_for_plane(struct gbm_bo *_bo, int plane) 677b8e80941Smrg{ 678b8e80941Smrg struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 679b8e80941Smrg struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 680b8e80941Smrg union gbm_bo_handle ret; 681b8e80941Smrg ret.s32 = -1; 682b8e80941Smrg 683b8e80941Smrg if (!dri->image || dri->image->base.version < 13 || !dri->image->fromPlanar) { 684b8e80941Smrg errno = ENOSYS; 685b8e80941Smrg return ret; 686b8e80941Smrg } 687b8e80941Smrg 688b8e80941Smrg if (plane >= get_number_planes(dri, bo->image)) { 689b8e80941Smrg errno = EINVAL; 690b8e80941Smrg return ret; 691b8e80941Smrg } 692b8e80941Smrg 693b8e80941Smrg /* dumb BOs can only utilize non-planar formats */ 694b8e80941Smrg if (!bo->image) { 695b8e80941Smrg assert(plane == 0); 696b8e80941Smrg ret.s32 = bo->handle; 697b8e80941Smrg return ret; 698b8e80941Smrg } 699b8e80941Smrg 700b8e80941Smrg __DRIimage *image = dri->image->fromPlanar(bo->image, plane, NULL); 701b8e80941Smrg if (image) { 702b8e80941Smrg dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_HANDLE, &ret.s32); 703b8e80941Smrg dri->image->destroyImage(image); 704848b8605Smrg } else { 705b8e80941Smrg assert(plane == 0); 706b8e80941Smrg dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE, &ret.s32); 707848b8605Smrg } 708848b8605Smrg 709b8e80941Smrg return ret; 710848b8605Smrg} 711848b8605Smrg 712848b8605Smrgstatic uint32_t 713b8e80941Smrggbm_dri_bo_get_stride(struct gbm_bo *_bo, int plane) 714848b8605Smrg{ 715b8e80941Smrg struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 716b8e80941Smrg struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 717b8e80941Smrg __DRIimage *image; 718b8e80941Smrg int stride = 0; 719848b8605Smrg 720b8e80941Smrg if (!dri->image || dri->image->base.version < 11 || !dri->image->fromPlanar) { 721b8e80941Smrg /* Preserve legacy behavior if plane is 0 */ 722b8e80941Smrg if (plane == 0) 723b8e80941Smrg return _bo->stride; 724b8e80941Smrg 725b8e80941Smrg errno = ENOSYS; 726b8e80941Smrg return 0; 727b8e80941Smrg } 728b8e80941Smrg 729b8e80941Smrg if (plane >= get_number_planes(dri, bo->image)) { 730b8e80941Smrg errno = EINVAL; 731b8e80941Smrg return 0; 732b8e80941Smrg } 733b8e80941Smrg 734b8e80941Smrg if (bo->image == NULL) { 735b8e80941Smrg assert(plane == 0); 736b8e80941Smrg return _bo->stride; 737848b8605Smrg } 738848b8605Smrg 739b8e80941Smrg image = dri->image->fromPlanar(bo->image, plane, NULL); 740b8e80941Smrg if (image) { 741b8e80941Smrg dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride); 742b8e80941Smrg dri->image->destroyImage(image); 743b8e80941Smrg } else { 744b8e80941Smrg assert(plane == 0); 745b8e80941Smrg dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, &stride); 746b8e80941Smrg } 747b8e80941Smrg 748b8e80941Smrg return (uint32_t)stride; 749b8e80941Smrg} 750b8e80941Smrg 751b8e80941Smrgstatic uint32_t 752b8e80941Smrggbm_dri_bo_get_offset(struct gbm_bo *_bo, int plane) 753b8e80941Smrg{ 754b8e80941Smrg struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 755b8e80941Smrg struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 756b8e80941Smrg int offset = 0; 757b8e80941Smrg 758b8e80941Smrg /* These error cases do not actually return an error code, as the user 759b8e80941Smrg * will also fail to obtain the handle/FD from the BO. In that case, the 760b8e80941Smrg * offset is irrelevant, as they have no buffer to offset into, so 761b8e80941Smrg * returning 0 is harmless. 762b8e80941Smrg */ 763b8e80941Smrg if (!dri->image || dri->image->base.version < 13 || !dri->image->fromPlanar) 764b8e80941Smrg return 0; 765b8e80941Smrg 766b8e80941Smrg if (plane >= get_number_planes(dri, bo->image)) 767b8e80941Smrg return 0; 768b8e80941Smrg 769b8e80941Smrg /* Dumb images have no offset */ 770b8e80941Smrg if (bo->image == NULL) { 771b8e80941Smrg assert(plane == 0); 772b8e80941Smrg return 0; 773b8e80941Smrg } 774b8e80941Smrg 775b8e80941Smrg __DRIimage *image = dri->image->fromPlanar(bo->image, plane, NULL); 776b8e80941Smrg if (image) { 777b8e80941Smrg dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_OFFSET, &offset); 778b8e80941Smrg dri->image->destroyImage(image); 779b8e80941Smrg } else { 780b8e80941Smrg assert(plane == 0); 781b8e80941Smrg dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_OFFSET, &offset); 782b8e80941Smrg } 783b8e80941Smrg 784b8e80941Smrg return (uint32_t)offset; 785b8e80941Smrg} 786b8e80941Smrg 787b8e80941Smrgstatic uint64_t 788b8e80941Smrggbm_dri_bo_get_modifier(struct gbm_bo *_bo) 789b8e80941Smrg{ 790b8e80941Smrg struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 791b8e80941Smrg struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 792b8e80941Smrg 793b8e80941Smrg if (!dri->image || dri->image->base.version < 14) { 794b8e80941Smrg errno = ENOSYS; 795b8e80941Smrg return DRM_FORMAT_MOD_INVALID; 796b8e80941Smrg } 797b8e80941Smrg 798b8e80941Smrg /* Dumb buffers have no modifiers */ 799b8e80941Smrg if (!bo->image) 800b8e80941Smrg return DRM_FORMAT_MOD_LINEAR; 801b8e80941Smrg 802b8e80941Smrg uint64_t ret = 0; 803b8e80941Smrg int mod; 804b8e80941Smrg if (!dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_MODIFIER_UPPER, 805b8e80941Smrg &mod)) 806b8e80941Smrg return DRM_FORMAT_MOD_INVALID; 807b8e80941Smrg 808b8e80941Smrg ret = (uint64_t)mod << 32; 809b8e80941Smrg 810b8e80941Smrg if (!dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_MODIFIER_LOWER, 811b8e80941Smrg &mod)) 812b8e80941Smrg return DRM_FORMAT_MOD_INVALID; 813b8e80941Smrg 814b8e80941Smrg ret |= (uint64_t)(mod & 0xffffffff); 815b8e80941Smrg 816848b8605Smrg return ret; 817848b8605Smrg} 818848b8605Smrg 819b8e80941Smrgstatic void 820b8e80941Smrggbm_dri_bo_destroy(struct gbm_bo *_bo) 821b8e80941Smrg{ 822b8e80941Smrg struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 823b8e80941Smrg struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 824b8e80941Smrg struct drm_mode_destroy_dumb arg; 825b8e80941Smrg 826b8e80941Smrg if (bo->image != NULL) { 827b8e80941Smrg dri->image->destroyImage(bo->image); 828b8e80941Smrg } else { 829b8e80941Smrg gbm_dri_bo_unmap_dumb(bo); 830b8e80941Smrg memset(&arg, 0, sizeof(arg)); 831b8e80941Smrg arg.handle = bo->handle; 832b8e80941Smrg drmIoctl(dri->base.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg); 833b8e80941Smrg } 834b8e80941Smrg 835b8e80941Smrg free(bo); 836b8e80941Smrg} 837b8e80941Smrg 838848b8605Smrgstatic struct gbm_bo * 839848b8605Smrggbm_dri_bo_import(struct gbm_device *gbm, 840848b8605Smrg uint32_t type, void *buffer, uint32_t usage) 841848b8605Smrg{ 842848b8605Smrg struct gbm_dri_device *dri = gbm_dri_device(gbm); 843848b8605Smrg struct gbm_dri_bo *bo; 844848b8605Smrg __DRIimage *image; 845848b8605Smrg unsigned dri_use = 0; 846848b8605Smrg int gbm_format; 847848b8605Smrg 848848b8605Smrg /* Required for query image WIDTH & HEIGHT */ 849848b8605Smrg if (dri->image == NULL || dri->image->base.version < 4) { 850848b8605Smrg errno = ENOSYS; 851848b8605Smrg return NULL; 852848b8605Smrg } 853848b8605Smrg 854848b8605Smrg switch (type) { 855848b8605Smrg#if HAVE_WAYLAND_PLATFORM 856848b8605Smrg case GBM_BO_IMPORT_WL_BUFFER: 857848b8605Smrg { 858848b8605Smrg struct wl_drm_buffer *wb; 859848b8605Smrg 860848b8605Smrg if (!dri->wl_drm) { 861848b8605Smrg errno = EINVAL; 862848b8605Smrg return NULL; 863848b8605Smrg } 864848b8605Smrg 865848b8605Smrg wb = wayland_drm_buffer_get(dri->wl_drm, (struct wl_resource *) buffer); 866848b8605Smrg if (!wb) { 867848b8605Smrg errno = EINVAL; 868848b8605Smrg return NULL; 869848b8605Smrg } 870848b8605Smrg 871848b8605Smrg image = dri->image->dupImage(wb->driver_buffer, NULL); 872848b8605Smrg 873b8e80941Smrg /* GBM_FORMAT_* is identical to WL_DRM_FORMAT_*, so no conversion 874b8e80941Smrg * required. */ 875b8e80941Smrg gbm_format = wb->format; 876848b8605Smrg break; 877848b8605Smrg } 878848b8605Smrg#endif 879848b8605Smrg 880848b8605Smrg case GBM_BO_IMPORT_EGL_IMAGE: 881848b8605Smrg { 882848b8605Smrg int dri_format; 883848b8605Smrg if (dri->lookup_image == NULL) { 884848b8605Smrg errno = EINVAL; 885848b8605Smrg return NULL; 886848b8605Smrg } 887848b8605Smrg 888848b8605Smrg image = dri->lookup_image(dri->screen, buffer, dri->lookup_user_data); 889848b8605Smrg image = dri->image->dupImage(image, NULL); 890848b8605Smrg dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &dri_format); 891848b8605Smrg gbm_format = gbm_dri_to_gbm_format(dri_format); 892848b8605Smrg if (gbm_format == 0) { 893848b8605Smrg errno = EINVAL; 894b8e80941Smrg dri->image->destroyImage(image); 895848b8605Smrg return NULL; 896848b8605Smrg } 897848b8605Smrg break; 898848b8605Smrg } 899848b8605Smrg 900848b8605Smrg case GBM_BO_IMPORT_FD: 901848b8605Smrg { 902848b8605Smrg struct gbm_import_fd_data *fd_data = buffer; 903848b8605Smrg int stride = fd_data->stride, offset = 0; 904b8e80941Smrg int fourcc; 905b8e80941Smrg 906b8e80941Smrg /* GBM's GBM_FORMAT_* tokens are a strict superset of the DRI FourCC 907b8e80941Smrg * tokens accepted by createImageFromFds, except for not supporting 908b8e80941Smrg * the sARGB format. */ 909b8e80941Smrg fourcc = gbm_format_canonicalize(fd_data->format); 910848b8605Smrg 911848b8605Smrg image = dri->image->createImageFromFds(dri->screen, 912848b8605Smrg fd_data->width, 913848b8605Smrg fd_data->height, 914b8e80941Smrg fourcc, 915848b8605Smrg &fd_data->fd, 1, 916848b8605Smrg &stride, &offset, 917848b8605Smrg NULL); 918b8e80941Smrg if (image == NULL) { 919b8e80941Smrg errno = EINVAL; 920b8e80941Smrg return NULL; 921b8e80941Smrg } 922848b8605Smrg gbm_format = fd_data->format; 923848b8605Smrg break; 924848b8605Smrg } 925848b8605Smrg 926b8e80941Smrg case GBM_BO_IMPORT_FD_MODIFIER: 927b8e80941Smrg { 928b8e80941Smrg struct gbm_import_fd_modifier_data *fd_data = buffer; 929b8e80941Smrg unsigned int error; 930b8e80941Smrg int fourcc; 931b8e80941Smrg 932b8e80941Smrg /* Import with modifier requires createImageFromDmaBufs2 */ 933b8e80941Smrg if (dri->image == NULL || dri->image->base.version < 15 || 934b8e80941Smrg dri->image->createImageFromDmaBufs2 == NULL) { 935b8e80941Smrg errno = ENOSYS; 936b8e80941Smrg return NULL; 937b8e80941Smrg } 938b8e80941Smrg 939b8e80941Smrg /* GBM's GBM_FORMAT_* tokens are a strict superset of the DRI FourCC 940b8e80941Smrg * tokens accepted by createImageFromDmaBufs2, except for not supporting 941b8e80941Smrg * the sARGB format. */ 942b8e80941Smrg fourcc = gbm_format_canonicalize(fd_data->format); 943b8e80941Smrg 944b8e80941Smrg image = dri->image->createImageFromDmaBufs2(dri->screen, fd_data->width, 945b8e80941Smrg fd_data->height, fourcc, 946b8e80941Smrg fd_data->modifier, 947b8e80941Smrg fd_data->fds, 948b8e80941Smrg fd_data->num_fds, 949b8e80941Smrg fd_data->strides, 950b8e80941Smrg fd_data->offsets, 951b8e80941Smrg 0, 0, 0, 0, 952b8e80941Smrg &error, NULL); 953b8e80941Smrg if (image == NULL) { 954b8e80941Smrg errno = ENOSYS; 955b8e80941Smrg return NULL; 956b8e80941Smrg } 957b8e80941Smrg 958b8e80941Smrg gbm_format = fourcc; 959b8e80941Smrg break; 960b8e80941Smrg } 961b8e80941Smrg 962848b8605Smrg default: 963848b8605Smrg errno = ENOSYS; 964848b8605Smrg return NULL; 965848b8605Smrg } 966848b8605Smrg 967848b8605Smrg 968848b8605Smrg bo = calloc(1, sizeof *bo); 969b8e80941Smrg if (bo == NULL) { 970b8e80941Smrg dri->image->destroyImage(image); 971848b8605Smrg return NULL; 972b8e80941Smrg } 973848b8605Smrg 974848b8605Smrg bo->image = image; 975848b8605Smrg 976848b8605Smrg if (usage & GBM_BO_USE_SCANOUT) 977848b8605Smrg dri_use |= __DRI_IMAGE_USE_SCANOUT; 978848b8605Smrg if (usage & GBM_BO_USE_CURSOR) 979848b8605Smrg dri_use |= __DRI_IMAGE_USE_CURSOR; 980848b8605Smrg if (dri->image->base.version >= 2 && 981848b8605Smrg !dri->image->validateUsage(bo->image, dri_use)) { 982848b8605Smrg errno = EINVAL; 983b8e80941Smrg dri->image->destroyImage(bo->image); 984848b8605Smrg free(bo); 985848b8605Smrg return NULL; 986848b8605Smrg } 987848b8605Smrg 988b8e80941Smrg bo->base.gbm = gbm; 989b8e80941Smrg bo->base.format = gbm_format; 990848b8605Smrg 991848b8605Smrg dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_WIDTH, 992b8e80941Smrg (int*)&bo->base.width); 993848b8605Smrg dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HEIGHT, 994b8e80941Smrg (int*)&bo->base.height); 995848b8605Smrg dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, 996b8e80941Smrg (int*)&bo->base.stride); 997848b8605Smrg dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE, 998b8e80941Smrg &bo->base.handle.s32); 999848b8605Smrg 1000b8e80941Smrg return &bo->base; 1001848b8605Smrg} 1002848b8605Smrg 1003848b8605Smrgstatic struct gbm_bo * 1004848b8605Smrgcreate_dumb(struct gbm_device *gbm, 1005848b8605Smrg uint32_t width, uint32_t height, 1006848b8605Smrg uint32_t format, uint32_t usage) 1007848b8605Smrg{ 1008848b8605Smrg struct gbm_dri_device *dri = gbm_dri_device(gbm); 1009848b8605Smrg struct drm_mode_create_dumb create_arg; 1010848b8605Smrg struct gbm_dri_bo *bo; 1011848b8605Smrg struct drm_mode_destroy_dumb destroy_arg; 1012848b8605Smrg int ret; 1013848b8605Smrg int is_cursor, is_scanout; 1014848b8605Smrg 1015848b8605Smrg is_cursor = (usage & GBM_BO_USE_CURSOR) != 0 && 1016848b8605Smrg format == GBM_FORMAT_ARGB8888; 1017848b8605Smrg is_scanout = (usage & GBM_BO_USE_SCANOUT) != 0 && 1018b8e80941Smrg (format == GBM_FORMAT_XRGB8888 || format == GBM_FORMAT_XBGR8888); 1019848b8605Smrg if (!is_cursor && !is_scanout) { 1020848b8605Smrg errno = EINVAL; 1021848b8605Smrg return NULL; 1022848b8605Smrg } 1023848b8605Smrg 1024848b8605Smrg bo = calloc(1, sizeof *bo); 1025848b8605Smrg if (bo == NULL) 1026848b8605Smrg return NULL; 1027848b8605Smrg 1028b8e80941Smrg memset(&create_arg, 0, sizeof(create_arg)); 1029848b8605Smrg create_arg.bpp = 32; 1030848b8605Smrg create_arg.width = width; 1031848b8605Smrg create_arg.height = height; 1032848b8605Smrg 1033b8e80941Smrg ret = drmIoctl(dri->base.fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg); 1034848b8605Smrg if (ret) 1035848b8605Smrg goto free_bo; 1036848b8605Smrg 1037b8e80941Smrg bo->base.gbm = gbm; 1038b8e80941Smrg bo->base.width = width; 1039b8e80941Smrg bo->base.height = height; 1040b8e80941Smrg bo->base.stride = create_arg.pitch; 1041b8e80941Smrg bo->base.format = format; 1042b8e80941Smrg bo->base.handle.u32 = create_arg.handle; 1043848b8605Smrg bo->handle = create_arg.handle; 1044848b8605Smrg bo->size = create_arg.size; 1045848b8605Smrg 1046b8e80941Smrg if (gbm_dri_bo_map_dumb(bo) == NULL) 1047848b8605Smrg goto destroy_dumb; 1048848b8605Smrg 1049b8e80941Smrg return &bo->base; 1050848b8605Smrg 1051848b8605Smrgdestroy_dumb: 1052848b8605Smrg memset(&destroy_arg, 0, sizeof destroy_arg); 1053848b8605Smrg destroy_arg.handle = create_arg.handle; 1054b8e80941Smrg drmIoctl(dri->base.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg); 1055848b8605Smrgfree_bo: 1056848b8605Smrg free(bo); 1057848b8605Smrg 1058848b8605Smrg return NULL; 1059848b8605Smrg} 1060848b8605Smrg 1061848b8605Smrgstatic struct gbm_bo * 1062848b8605Smrggbm_dri_bo_create(struct gbm_device *gbm, 1063848b8605Smrg uint32_t width, uint32_t height, 1064b8e80941Smrg uint32_t format, uint32_t usage, 1065b8e80941Smrg const uint64_t *modifiers, 1066b8e80941Smrg const unsigned int count) 1067848b8605Smrg{ 1068848b8605Smrg struct gbm_dri_device *dri = gbm_dri_device(gbm); 1069848b8605Smrg struct gbm_dri_bo *bo; 1070848b8605Smrg int dri_format; 1071848b8605Smrg unsigned dri_use = 0; 1072848b8605Smrg 1073b8e80941Smrg /* Callers of this may specify a modifier, or a dri usage, but not both. The 1074b8e80941Smrg * newer modifier interface deprecates the older usage flags. 1075b8e80941Smrg */ 1076b8e80941Smrg assert(!(usage && count)); 1077b8e80941Smrg 1078b8e80941Smrg format = gbm_format_canonicalize(format); 1079b8e80941Smrg 1080848b8605Smrg if (usage & GBM_BO_USE_WRITE || dri->image == NULL) 1081848b8605Smrg return create_dumb(gbm, width, height, format, usage); 1082848b8605Smrg 1083848b8605Smrg bo = calloc(1, sizeof *bo); 1084848b8605Smrg if (bo == NULL) 1085848b8605Smrg return NULL; 1086848b8605Smrg 1087b8e80941Smrg bo->base.gbm = gbm; 1088b8e80941Smrg bo->base.width = width; 1089b8e80941Smrg bo->base.height = height; 1090b8e80941Smrg bo->base.format = format; 1091848b8605Smrg 1092b8e80941Smrg dri_format = gbm_format_to_dri_format(format); 1093b8e80941Smrg if (dri_format == 0) { 1094848b8605Smrg errno = EINVAL; 1095848b8605Smrg goto failed; 1096848b8605Smrg } 1097848b8605Smrg 1098848b8605Smrg if (usage & GBM_BO_USE_SCANOUT) 1099848b8605Smrg dri_use |= __DRI_IMAGE_USE_SCANOUT; 1100848b8605Smrg if (usage & GBM_BO_USE_CURSOR) 1101848b8605Smrg dri_use |= __DRI_IMAGE_USE_CURSOR; 1102b8e80941Smrg if (usage & GBM_BO_USE_LINEAR) 1103b8e80941Smrg dri_use |= __DRI_IMAGE_USE_LINEAR; 1104848b8605Smrg 1105848b8605Smrg /* Gallium drivers requires shared in order to get the handle/stride */ 1106848b8605Smrg dri_use |= __DRI_IMAGE_USE_SHARE; 1107848b8605Smrg 1108b8e80941Smrg if (modifiers) { 1109b8e80941Smrg if (!dri->image || dri->image->base.version < 14 || 1110b8e80941Smrg !dri->image->createImageWithModifiers) { 1111b8e80941Smrg fprintf(stderr, "Modifiers specified, but DRI is too old\n"); 1112b8e80941Smrg errno = ENOSYS; 1113b8e80941Smrg goto failed; 1114b8e80941Smrg } 1115b8e80941Smrg 1116b8e80941Smrg /* It's acceptable to create an image with INVALID modifier in the list, 1117b8e80941Smrg * but it cannot be on the only modifier (since it will certainly fail 1118b8e80941Smrg * later). While we could easily catch this after modifier creation, doing 1119b8e80941Smrg * the check here is a convenient debug check likely pointing at whatever 1120b8e80941Smrg * interface the client is using to build its modifier list. 1121b8e80941Smrg */ 1122b8e80941Smrg if (count == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID) { 1123b8e80941Smrg fprintf(stderr, "Only invalid modifier specified\n"); 1124b8e80941Smrg errno = EINVAL; 1125b8e80941Smrg goto failed; 1126b8e80941Smrg } 1127b8e80941Smrg 1128b8e80941Smrg bo->image = 1129b8e80941Smrg dri->image->createImageWithModifiers(dri->screen, 1130b8e80941Smrg width, height, 1131b8e80941Smrg dri_format, 1132b8e80941Smrg modifiers, count, 1133b8e80941Smrg bo); 1134b8e80941Smrg 1135b8e80941Smrg if (bo->image) { 1136b8e80941Smrg /* The client passed in a list of invalid modifiers */ 1137b8e80941Smrg assert(gbm_dri_bo_get_modifier(&bo->base) != DRM_FORMAT_MOD_INVALID); 1138b8e80941Smrg } 1139b8e80941Smrg } else { 1140b8e80941Smrg bo->image = dri->image->createImage(dri->screen, width, height, 1141b8e80941Smrg dri_format, dri_use, bo); 1142b8e80941Smrg } 1143b8e80941Smrg 1144848b8605Smrg if (bo->image == NULL) 1145848b8605Smrg goto failed; 1146848b8605Smrg 1147848b8605Smrg dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE, 1148b8e80941Smrg &bo->base.handle.s32); 1149848b8605Smrg dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, 1150b8e80941Smrg (int *) &bo->base.stride); 1151848b8605Smrg 1152b8e80941Smrg return &bo->base; 1153848b8605Smrg 1154848b8605Smrgfailed: 1155848b8605Smrg free(bo); 1156848b8605Smrg return NULL; 1157848b8605Smrg} 1158848b8605Smrg 1159b8e80941Smrgstatic void * 1160b8e80941Smrggbm_dri_bo_map(struct gbm_bo *_bo, 1161b8e80941Smrg uint32_t x, uint32_t y, 1162b8e80941Smrg uint32_t width, uint32_t height, 1163b8e80941Smrg uint32_t flags, uint32_t *stride, void **map_data) 1164b8e80941Smrg{ 1165b8e80941Smrg struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 1166b8e80941Smrg struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 1167b8e80941Smrg 1168b8e80941Smrg /* If it's a dumb buffer, we already have a mapping */ 1169b8e80941Smrg if (bo->map) { 1170b8e80941Smrg *map_data = (char *)bo->map + (bo->base.stride * y) + (x * 4); 1171b8e80941Smrg *stride = bo->base.stride; 1172b8e80941Smrg return *map_data; 1173b8e80941Smrg } 1174b8e80941Smrg 1175b8e80941Smrg if (!dri->image || dri->image->base.version < 12 || !dri->image->mapImage) { 1176b8e80941Smrg errno = ENOSYS; 1177b8e80941Smrg return NULL; 1178b8e80941Smrg } 1179b8e80941Smrg 1180b8e80941Smrg mtx_lock(&dri->mutex); 1181b8e80941Smrg if (!dri->context) 1182b8e80941Smrg dri->context = dri->dri2->createNewContext(dri->screen, NULL, 1183b8e80941Smrg NULL, NULL); 1184b8e80941Smrg assert(dri->context); 1185b8e80941Smrg mtx_unlock(&dri->mutex); 1186b8e80941Smrg 1187b8e80941Smrg /* GBM flags and DRI flags are the same, so just pass them on */ 1188b8e80941Smrg return dri->image->mapImage(dri->context, bo->image, x, y, 1189b8e80941Smrg width, height, flags, (int *)stride, 1190b8e80941Smrg map_data); 1191b8e80941Smrg} 1192b8e80941Smrg 1193b8e80941Smrgstatic void 1194b8e80941Smrggbm_dri_bo_unmap(struct gbm_bo *_bo, void *map_data) 1195b8e80941Smrg{ 1196b8e80941Smrg struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 1197b8e80941Smrg struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 1198b8e80941Smrg 1199b8e80941Smrg /* Check if it's a dumb buffer and check the pointer is in range */ 1200b8e80941Smrg if (bo->map) { 1201b8e80941Smrg assert(map_data >= bo->map); 1202b8e80941Smrg assert(map_data < (bo->map + bo->size)); 1203b8e80941Smrg return; 1204b8e80941Smrg } 1205b8e80941Smrg 1206b8e80941Smrg if (!dri->context || !dri->image || 1207b8e80941Smrg dri->image->base.version < 12 || !dri->image->unmapImage) 1208b8e80941Smrg return; 1209b8e80941Smrg 1210b8e80941Smrg dri->image->unmapImage(dri->context, bo->image, map_data); 1211b8e80941Smrg 1212b8e80941Smrg /* 1213b8e80941Smrg * Not all DRI drivers use direct maps. They may queue up DMA operations 1214b8e80941Smrg * on the mapping context. Since there is no explicit gbm flush 1215b8e80941Smrg * mechanism, we need to flush here. 1216b8e80941Smrg */ 1217b8e80941Smrg if (dri->flush->base.version >= 4) 1218b8e80941Smrg dri->flush->flush_with_flags(dri->context, NULL, __DRI2_FLUSH_CONTEXT, 0); 1219b8e80941Smrg} 1220b8e80941Smrg 1221b8e80941Smrg 1222848b8605Smrgstatic struct gbm_surface * 1223848b8605Smrggbm_dri_surface_create(struct gbm_device *gbm, 1224848b8605Smrg uint32_t width, uint32_t height, 1225b8e80941Smrg uint32_t format, uint32_t flags, 1226b8e80941Smrg const uint64_t *modifiers, const unsigned count) 1227848b8605Smrg{ 1228b8e80941Smrg struct gbm_dri_device *dri = gbm_dri_device(gbm); 1229848b8605Smrg struct gbm_dri_surface *surf; 1230848b8605Smrg 1231b8e80941Smrg if (modifiers && 1232b8e80941Smrg (!dri->image || dri->image->base.version < 14 || 1233b8e80941Smrg !dri->image->createImageWithModifiers)) { 1234b8e80941Smrg errno = ENOSYS; 1235b8e80941Smrg return NULL; 1236b8e80941Smrg } 1237b8e80941Smrg 1238b8e80941Smrg if (count) 1239b8e80941Smrg assert(modifiers); 1240b8e80941Smrg 1241b8e80941Smrg /* It's acceptable to create an image with INVALID modifier in the list, 1242b8e80941Smrg * but it cannot be on the only modifier (since it will certainly fail 1243b8e80941Smrg * later). While we could easily catch this after modifier creation, doing 1244b8e80941Smrg * the check here is a convenient debug check likely pointing at whatever 1245b8e80941Smrg * interface the client is using to build its modifier list. 1246b8e80941Smrg */ 1247b8e80941Smrg if (count == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID) { 1248b8e80941Smrg fprintf(stderr, "Only invalid modifier specified\n"); 1249b8e80941Smrg errno = EINVAL; 1250b8e80941Smrg } 1251b8e80941Smrg 1252848b8605Smrg surf = calloc(1, sizeof *surf); 1253b8e80941Smrg if (surf == NULL) { 1254b8e80941Smrg errno = ENOMEM; 1255848b8605Smrg return NULL; 1256b8e80941Smrg } 1257848b8605Smrg 1258848b8605Smrg surf->base.gbm = gbm; 1259848b8605Smrg surf->base.width = width; 1260848b8605Smrg surf->base.height = height; 1261b8e80941Smrg surf->base.format = gbm_format_canonicalize(format); 1262848b8605Smrg surf->base.flags = flags; 1263b8e80941Smrg if (!modifiers) { 1264b8e80941Smrg assert(!count); 1265b8e80941Smrg return &surf->base; 1266b8e80941Smrg } 1267b8e80941Smrg 1268b8e80941Smrg surf->base.modifiers = calloc(count, sizeof(*modifiers)); 1269b8e80941Smrg if (count && !surf->base.modifiers) { 1270b8e80941Smrg errno = ENOMEM; 1271b8e80941Smrg free(surf); 1272b8e80941Smrg return NULL; 1273b8e80941Smrg } 1274b8e80941Smrg 1275b8e80941Smrg /* TODO: We are deferring validation of modifiers until the image is actually 1276b8e80941Smrg * created. This deferred creation can fail due to a modifier-format 1277b8e80941Smrg * mismatch. The result is the client has a surface but no object to back it. 1278b8e80941Smrg */ 1279b8e80941Smrg surf->base.count = count; 1280b8e80941Smrg memcpy(surf->base.modifiers, modifiers, count * sizeof(*modifiers)); 1281848b8605Smrg 1282848b8605Smrg return &surf->base; 1283848b8605Smrg} 1284848b8605Smrg 1285848b8605Smrgstatic void 1286848b8605Smrggbm_dri_surface_destroy(struct gbm_surface *_surf) 1287848b8605Smrg{ 1288848b8605Smrg struct gbm_dri_surface *surf = gbm_dri_surface(_surf); 1289848b8605Smrg 1290b8e80941Smrg free(surf->base.modifiers); 1291848b8605Smrg free(surf); 1292848b8605Smrg} 1293848b8605Smrg 1294848b8605Smrgstatic void 1295848b8605Smrgdri_destroy(struct gbm_device *gbm) 1296848b8605Smrg{ 1297848b8605Smrg struct gbm_dri_device *dri = gbm_dri_device(gbm); 1298b8e80941Smrg unsigned i; 1299b8e80941Smrg 1300b8e80941Smrg if (dri->context) 1301b8e80941Smrg dri->core->destroyContext(dri->context); 1302848b8605Smrg 1303848b8605Smrg dri->core->destroyScreen(dri->screen); 1304b8e80941Smrg for (i = 0; dri->driver_configs[i]; i++) 1305b8e80941Smrg free((__DRIconfig *) dri->driver_configs[i]); 1306848b8605Smrg free(dri->driver_configs); 1307848b8605Smrg dlclose(dri->driver); 1308b8e80941Smrg free(dri->driver_name); 1309848b8605Smrg 1310848b8605Smrg free(dri); 1311848b8605Smrg} 1312848b8605Smrg 1313848b8605Smrgstatic struct gbm_device * 1314848b8605Smrgdri_device_create(int fd) 1315848b8605Smrg{ 1316848b8605Smrg struct gbm_dri_device *dri; 1317b8e80941Smrg int ret; 1318b8e80941Smrg bool force_sw; 1319848b8605Smrg 1320848b8605Smrg dri = calloc(1, sizeof *dri); 1321848b8605Smrg if (!dri) 1322848b8605Smrg return NULL; 1323848b8605Smrg 1324b8e80941Smrg dri->base.fd = fd; 1325b8e80941Smrg dri->base.bo_create = gbm_dri_bo_create; 1326b8e80941Smrg dri->base.bo_import = gbm_dri_bo_import; 1327b8e80941Smrg dri->base.bo_map = gbm_dri_bo_map; 1328b8e80941Smrg dri->base.bo_unmap = gbm_dri_bo_unmap; 1329b8e80941Smrg dri->base.is_format_supported = gbm_dri_is_format_supported; 1330b8e80941Smrg dri->base.get_format_modifier_plane_count = 1331b8e80941Smrg gbm_dri_get_format_modifier_plane_count; 1332b8e80941Smrg dri->base.bo_write = gbm_dri_bo_write; 1333b8e80941Smrg dri->base.bo_get_fd = gbm_dri_bo_get_fd; 1334b8e80941Smrg dri->base.bo_get_planes = gbm_dri_bo_get_planes; 1335b8e80941Smrg dri->base.bo_get_handle = gbm_dri_bo_get_handle_for_plane; 1336b8e80941Smrg dri->base.bo_get_stride = gbm_dri_bo_get_stride; 1337b8e80941Smrg dri->base.bo_get_offset = gbm_dri_bo_get_offset; 1338b8e80941Smrg dri->base.bo_get_modifier = gbm_dri_bo_get_modifier; 1339b8e80941Smrg dri->base.bo_destroy = gbm_dri_bo_destroy; 1340b8e80941Smrg dri->base.destroy = dri_destroy; 1341b8e80941Smrg dri->base.surface_create = gbm_dri_surface_create; 1342b8e80941Smrg dri->base.surface_destroy = gbm_dri_surface_destroy; 1343b8e80941Smrg 1344b8e80941Smrg dri->base.name = "drm"; 1345b8e80941Smrg 1346b8e80941Smrg dri->visual_table = gbm_dri_visuals_table; 1347b8e80941Smrg dri->num_visuals = ARRAY_SIZE(gbm_dri_visuals_table); 1348b8e80941Smrg 1349b8e80941Smrg mtx_init(&dri->mutex, mtx_plain); 1350b8e80941Smrg 1351b8e80941Smrg force_sw = env_var_as_boolean("GBM_ALWAYS_SOFTWARE", false); 1352848b8605Smrg if (!force_sw) { 1353848b8605Smrg ret = dri_screen_create(dri); 1354848b8605Smrg if (ret) 1355848b8605Smrg ret = dri_screen_create_sw(dri); 1356848b8605Smrg } else { 1357848b8605Smrg ret = dri_screen_create_sw(dri); 1358848b8605Smrg } 1359848b8605Smrg 1360848b8605Smrg if (ret) 1361848b8605Smrg goto err_dri; 1362848b8605Smrg 1363b8e80941Smrg return &dri->base; 1364848b8605Smrg 1365848b8605Smrgerr_dri: 1366848b8605Smrg free(dri); 1367848b8605Smrg 1368848b8605Smrg return NULL; 1369848b8605Smrg} 1370848b8605Smrg 1371848b8605Smrgstruct gbm_backend gbm_dri_backend = { 1372848b8605Smrg .backend_name = "dri", 1373848b8605Smrg .create_device = dri_device_create, 1374848b8605Smrg}; 1375