1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Mesa 3-D graphics library 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Copyright (c) 2014 The Chromium OS Authors. 5bf215546Sopenharmony_ci * Copyright © 2011 Intel Corporation 6bf215546Sopenharmony_ci * 7bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 8bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 9bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 10bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 12bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included 15bf215546Sopenharmony_ci * in all copies or substantial portions of the Software. 16bf215546Sopenharmony_ci * 17bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 24bf215546Sopenharmony_ci */ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include <stdlib.h> 27bf215546Sopenharmony_ci#include <stdio.h> 28bf215546Sopenharmony_ci#include <string.h> 29bf215546Sopenharmony_ci#include <xf86drm.h> 30bf215546Sopenharmony_ci#include <dlfcn.h> 31bf215546Sopenharmony_ci#include <sys/types.h> 32bf215546Sopenharmony_ci#include <sys/stat.h> 33bf215546Sopenharmony_ci#include <fcntl.h> 34bf215546Sopenharmony_ci#include <unistd.h> 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci#include "egl_dri2.h" 37bf215546Sopenharmony_ci#include "loader.h" 38bf215546Sopenharmony_ci#include "kopper_interface.h" 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_cistatic __DRIimage* 41bf215546Sopenharmony_cisurfaceless_alloc_image(struct dri2_egl_display *dri2_dpy, 42bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf) 43bf215546Sopenharmony_ci{ 44bf215546Sopenharmony_ci return dri2_dpy->image->createImage( 45bf215546Sopenharmony_ci dri2_dpy->dri_screen, 46bf215546Sopenharmony_ci dri2_surf->base.Width, 47bf215546Sopenharmony_ci dri2_surf->base.Height, 48bf215546Sopenharmony_ci dri2_surf->visual, 49bf215546Sopenharmony_ci 0, 50bf215546Sopenharmony_ci NULL); 51bf215546Sopenharmony_ci} 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_cistatic void 54bf215546Sopenharmony_cisurfaceless_free_images(struct dri2_egl_surface *dri2_surf) 55bf215546Sopenharmony_ci{ 56bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = 57bf215546Sopenharmony_ci dri2_egl_display(dri2_surf->base.Resource.Display); 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci if (dri2_surf->front) { 60bf215546Sopenharmony_ci dri2_dpy->image->destroyImage(dri2_surf->front); 61bf215546Sopenharmony_ci dri2_surf->front = NULL; 62bf215546Sopenharmony_ci } 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci free(dri2_surf->swrast_device_buffer); 65bf215546Sopenharmony_ci dri2_surf->swrast_device_buffer = NULL; 66bf215546Sopenharmony_ci} 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_cistatic int 69bf215546Sopenharmony_cisurfaceless_image_get_buffers(__DRIdrawable *driDrawable, 70bf215546Sopenharmony_ci unsigned int format, 71bf215546Sopenharmony_ci uint32_t *stamp, 72bf215546Sopenharmony_ci void *loaderPrivate, 73bf215546Sopenharmony_ci uint32_t buffer_mask, 74bf215546Sopenharmony_ci struct __DRIimageList *buffers) 75bf215546Sopenharmony_ci{ 76bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = loaderPrivate; 77bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = 78bf215546Sopenharmony_ci dri2_egl_display(dri2_surf->base.Resource.Display); 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci buffers->image_mask = 0; 81bf215546Sopenharmony_ci buffers->front = NULL; 82bf215546Sopenharmony_ci buffers->back = NULL; 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci /* The EGL 1.5 spec states that pbuffers are single-buffered. Specifically, 85bf215546Sopenharmony_ci * the spec states that they have a back buffer but no front buffer, in 86bf215546Sopenharmony_ci * contrast to pixmaps, which have a front buffer but no back buffer. 87bf215546Sopenharmony_ci * 88bf215546Sopenharmony_ci * Single-buffered surfaces with no front buffer confuse Mesa; so we deviate 89bf215546Sopenharmony_ci * from the spec, following the precedent of Mesa's EGL X11 platform. The 90bf215546Sopenharmony_ci * X11 platform correctly assigns pbuffers to single-buffered configs, but 91bf215546Sopenharmony_ci * assigns the pbuffer a front buffer instead of a back buffer. 92bf215546Sopenharmony_ci * 93bf215546Sopenharmony_ci * Pbuffers in the X11 platform mostly work today, so let's just copy its 94bf215546Sopenharmony_ci * behavior instead of trying to fix (and hence potentially breaking) the 95bf215546Sopenharmony_ci * world. 96bf215546Sopenharmony_ci */ 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) { 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci if (!dri2_surf->front) 101bf215546Sopenharmony_ci dri2_surf->front = 102bf215546Sopenharmony_ci surfaceless_alloc_image(dri2_dpy, dri2_surf); 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT; 105bf215546Sopenharmony_ci buffers->front = dri2_surf->front; 106bf215546Sopenharmony_ci } 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci return 1; 109bf215546Sopenharmony_ci} 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_cistatic _EGLSurface * 112bf215546Sopenharmony_cidri2_surfaceless_create_surface(_EGLDisplay *disp, EGLint type, 113bf215546Sopenharmony_ci _EGLConfig *conf, const EGLint *attrib_list) 114bf215546Sopenharmony_ci{ 115bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 116bf215546Sopenharmony_ci struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); 117bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf; 118bf215546Sopenharmony_ci const __DRIconfig *config; 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci /* Make sure to calloc so all pointers 121bf215546Sopenharmony_ci * are originally NULL. 122bf215546Sopenharmony_ci */ 123bf215546Sopenharmony_ci dri2_surf = calloc(1, sizeof *dri2_surf); 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci if (!dri2_surf) { 126bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); 127bf215546Sopenharmony_ci return NULL; 128bf215546Sopenharmony_ci } 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list, 131bf215546Sopenharmony_ci false, NULL)) 132bf215546Sopenharmony_ci goto cleanup_surface; 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci config = dri2_get_dri_config(dri2_conf, type, 135bf215546Sopenharmony_ci dri2_surf->base.GLColorspace); 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci if (!config) { 138bf215546Sopenharmony_ci _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration"); 139bf215546Sopenharmony_ci goto cleanup_surface; 140bf215546Sopenharmony_ci } 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci dri2_surf->visual = dri2_image_format_for_pbuffer_config(dri2_dpy, config); 143bf215546Sopenharmony_ci if (dri2_surf->visual == __DRI_IMAGE_FORMAT_NONE) 144bf215546Sopenharmony_ci goto cleanup_surface; 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf)) 147bf215546Sopenharmony_ci goto cleanup_surface; 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci return &dri2_surf->base; 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci cleanup_surface: 152bf215546Sopenharmony_ci free(dri2_surf); 153bf215546Sopenharmony_ci return NULL; 154bf215546Sopenharmony_ci} 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_cistatic EGLBoolean 157bf215546Sopenharmony_cisurfaceless_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf) 158bf215546Sopenharmony_ci{ 159bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 160bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci surfaceless_free_images(dri2_surf); 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci dri2_fini_surface(surf); 167bf215546Sopenharmony_ci free(dri2_surf); 168bf215546Sopenharmony_ci return EGL_TRUE; 169bf215546Sopenharmony_ci} 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_cistatic _EGLSurface * 172bf215546Sopenharmony_cidri2_surfaceless_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf, 173bf215546Sopenharmony_ci const EGLint *attrib_list) 174bf215546Sopenharmony_ci{ 175bf215546Sopenharmony_ci return dri2_surfaceless_create_surface(disp, EGL_PBUFFER_BIT, conf, 176bf215546Sopenharmony_ci attrib_list); 177bf215546Sopenharmony_ci} 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_cistatic const struct dri2_egl_display_vtbl dri2_surfaceless_display_vtbl = { 180bf215546Sopenharmony_ci .create_pbuffer_surface = dri2_surfaceless_create_pbuffer_surface, 181bf215546Sopenharmony_ci .destroy_surface = surfaceless_destroy_surface, 182bf215546Sopenharmony_ci .create_image = dri2_create_image_khr, 183bf215546Sopenharmony_ci .get_dri_drawable = dri2_surface_get_dri_drawable, 184bf215546Sopenharmony_ci}; 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_cistatic void 187bf215546Sopenharmony_cisurfaceless_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate) 188bf215546Sopenharmony_ci{ 189bf215546Sopenharmony_ci} 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_cistatic unsigned 192bf215546Sopenharmony_cisurfaceless_get_capability(void *loaderPrivate, enum dri_loader_cap cap) 193bf215546Sopenharmony_ci{ 194bf215546Sopenharmony_ci /* Note: loaderPrivate is _EGLDisplay* */ 195bf215546Sopenharmony_ci switch (cap) { 196bf215546Sopenharmony_ci case DRI_LOADER_CAP_FP16: 197bf215546Sopenharmony_ci return 1; 198bf215546Sopenharmony_ci default: 199bf215546Sopenharmony_ci return 0; 200bf215546Sopenharmony_ci } 201bf215546Sopenharmony_ci} 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_cistatic const __DRIkopperLoaderExtension kopper_loader_extension = { 204bf215546Sopenharmony_ci .base = { __DRI_KOPPER_LOADER, 1 }, 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci .SetSurfaceCreateInfo = NULL, 207bf215546Sopenharmony_ci}; 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_cistatic const __DRIimageLoaderExtension image_loader_extension = { 210bf215546Sopenharmony_ci .base = { __DRI_IMAGE_LOADER, 2 }, 211bf215546Sopenharmony_ci .getBuffers = surfaceless_image_get_buffers, 212bf215546Sopenharmony_ci .flushFrontBuffer = surfaceless_flush_front_buffer, 213bf215546Sopenharmony_ci .getCapability = surfaceless_get_capability, 214bf215546Sopenharmony_ci}; 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_cistatic const __DRIextension *image_loader_extensions[] = { 217bf215546Sopenharmony_ci &image_loader_extension.base, 218bf215546Sopenharmony_ci &image_lookup_extension.base, 219bf215546Sopenharmony_ci &use_invalidate.base, 220bf215546Sopenharmony_ci &background_callable_extension.base, 221bf215546Sopenharmony_ci &kopper_loader_extension.base, 222bf215546Sopenharmony_ci NULL, 223bf215546Sopenharmony_ci}; 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_cistatic const __DRIextension *swrast_loader_extensions[] = { 226bf215546Sopenharmony_ci &swrast_pbuffer_loader_extension.base, 227bf215546Sopenharmony_ci &image_loader_extension.base, 228bf215546Sopenharmony_ci &image_lookup_extension.base, 229bf215546Sopenharmony_ci &use_invalidate.base, 230bf215546Sopenharmony_ci &kopper_loader_extension.base, 231bf215546Sopenharmony_ci NULL, 232bf215546Sopenharmony_ci}; 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_cistatic bool 235bf215546Sopenharmony_cisurfaceless_probe_device(_EGLDisplay *disp, bool swrast) 236bf215546Sopenharmony_ci{ 237bf215546Sopenharmony_ci#define MAX_DRM_DEVICES 64 238bf215546Sopenharmony_ci const unsigned node_type = swrast ? DRM_NODE_PRIMARY : DRM_NODE_RENDER; 239bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 240bf215546Sopenharmony_ci drmDevicePtr device, devices[MAX_DRM_DEVICES] = { NULL }; 241bf215546Sopenharmony_ci int i, num_devices; 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci num_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices)); 244bf215546Sopenharmony_ci if (num_devices < 0) 245bf215546Sopenharmony_ci return false; 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci for (i = 0; i < num_devices; ++i) { 248bf215546Sopenharmony_ci device = devices[i]; 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci if (!(device->available_nodes & (1 << node_type))) 251bf215546Sopenharmony_ci continue; 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci dri2_dpy->fd = loader_open_device(device->nodes[node_type]); 254bf215546Sopenharmony_ci if (dri2_dpy->fd < 0) 255bf215546Sopenharmony_ci continue; 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci disp->Device = _eglAddDevice(dri2_dpy->fd, swrast); 258bf215546Sopenharmony_ci if (!disp->Device) { 259bf215546Sopenharmony_ci close(dri2_dpy->fd); 260bf215546Sopenharmony_ci dri2_dpy->fd = -1; 261bf215546Sopenharmony_ci continue; 262bf215546Sopenharmony_ci } 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci char *driver_name = loader_get_driver_for_fd(dri2_dpy->fd); 265bf215546Sopenharmony_ci if (swrast) { 266bf215546Sopenharmony_ci /* Use kms swrast only with vgem / virtio_gpu. 267bf215546Sopenharmony_ci * virtio-gpu fallbacks to software rendering when 3D features 268bf215546Sopenharmony_ci * are unavailable since 6c5ab, and kms_swrast is more 269bf215546Sopenharmony_ci * feature complete than swrast. 270bf215546Sopenharmony_ci */ 271bf215546Sopenharmony_ci if (driver_name && 272bf215546Sopenharmony_ci (strcmp(driver_name, "vgem") == 0 || 273bf215546Sopenharmony_ci strcmp(driver_name, "virtio_gpu") == 0)) 274bf215546Sopenharmony_ci dri2_dpy->driver_name = strdup("kms_swrast"); 275bf215546Sopenharmony_ci free(driver_name); 276bf215546Sopenharmony_ci } else { 277bf215546Sopenharmony_ci /* Use the given hardware driver */ 278bf215546Sopenharmony_ci dri2_dpy->driver_name = driver_name; 279bf215546Sopenharmony_ci } 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci if (dri2_dpy->driver_name && dri2_load_driver_dri3(disp)) 282bf215546Sopenharmony_ci break; 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci free(dri2_dpy->driver_name); 285bf215546Sopenharmony_ci dri2_dpy->driver_name = NULL; 286bf215546Sopenharmony_ci close(dri2_dpy->fd); 287bf215546Sopenharmony_ci dri2_dpy->fd = -1; 288bf215546Sopenharmony_ci } 289bf215546Sopenharmony_ci drmFreeDevices(devices, num_devices); 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci if (i == num_devices) 292bf215546Sopenharmony_ci return false; 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci if (swrast) 295bf215546Sopenharmony_ci dri2_dpy->loader_extensions = swrast_loader_extensions; 296bf215546Sopenharmony_ci else 297bf215546Sopenharmony_ci dri2_dpy->loader_extensions = image_loader_extensions; 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci return true; 300bf215546Sopenharmony_ci} 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_cistatic bool 303bf215546Sopenharmony_cisurfaceless_probe_device_sw(_EGLDisplay *disp) 304bf215546Sopenharmony_ci{ 305bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci dri2_dpy->fd = -1; 308bf215546Sopenharmony_ci disp->Device = _eglAddDevice(dri2_dpy->fd, true); 309bf215546Sopenharmony_ci assert(disp->Device); 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_ci dri2_dpy->driver_name = strdup(disp->Options.Zink ? "zink" : "swrast"); 312bf215546Sopenharmony_ci if (!dri2_dpy->driver_name) 313bf215546Sopenharmony_ci return false; 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci if (!dri2_load_driver_swrast(disp)) { 316bf215546Sopenharmony_ci free(dri2_dpy->driver_name); 317bf215546Sopenharmony_ci dri2_dpy->driver_name = NULL; 318bf215546Sopenharmony_ci return false; 319bf215546Sopenharmony_ci } 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci dri2_dpy->loader_extensions = swrast_loader_extensions; 322bf215546Sopenharmony_ci return true; 323bf215546Sopenharmony_ci} 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ciEGLBoolean 326bf215546Sopenharmony_cidri2_initialize_surfaceless(_EGLDisplay *disp) 327bf215546Sopenharmony_ci{ 328bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy; 329bf215546Sopenharmony_ci const char* err; 330bf215546Sopenharmony_ci bool driver_loaded = false; 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_ci dri2_dpy = calloc(1, sizeof *dri2_dpy); 333bf215546Sopenharmony_ci if (!dri2_dpy) 334bf215546Sopenharmony_ci return _eglError(EGL_BAD_ALLOC, "eglInitialize"); 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_ci dri2_dpy->fd = -1; 337bf215546Sopenharmony_ci disp->DriverData = (void *) dri2_dpy; 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_ci /* When ForceSoftware is false, we try the HW driver. When ForceSoftware 340bf215546Sopenharmony_ci * is true, we try kms_swrast and swrast in order. 341bf215546Sopenharmony_ci */ 342bf215546Sopenharmony_ci driver_loaded = surfaceless_probe_device(disp, disp->Options.ForceSoftware); 343bf215546Sopenharmony_ci if (!driver_loaded && disp->Options.ForceSoftware) { 344bf215546Sopenharmony_ci _eglLog(_EGL_DEBUG, "Falling back to surfaceless swrast without DRM."); 345bf215546Sopenharmony_ci driver_loaded = surfaceless_probe_device_sw(disp); 346bf215546Sopenharmony_ci } 347bf215546Sopenharmony_ci 348bf215546Sopenharmony_ci if (!driver_loaded) { 349bf215546Sopenharmony_ci err = "DRI2: failed to load driver"; 350bf215546Sopenharmony_ci goto cleanup; 351bf215546Sopenharmony_ci } 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_ci if (!dri2_create_screen(disp)) { 354bf215546Sopenharmony_ci err = "DRI2: failed to create screen"; 355bf215546Sopenharmony_ci goto cleanup; 356bf215546Sopenharmony_ci } 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci if (!dri2_setup_extensions(disp)) { 359bf215546Sopenharmony_ci err = "DRI2: failed to find required DRI extensions"; 360bf215546Sopenharmony_ci goto cleanup; 361bf215546Sopenharmony_ci } 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci dri2_setup_screen(disp); 364bf215546Sopenharmony_ci#ifdef HAVE_WAYLAND_PLATFORM 365bf215546Sopenharmony_ci dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd); 366bf215546Sopenharmony_ci#endif 367bf215546Sopenharmony_ci dri2_set_WL_bind_wayland_display(disp); 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_ci if (!dri2_add_pbuffer_configs_for_visuals(disp)) { 370bf215546Sopenharmony_ci err = "DRI2: failed to add configs"; 371bf215546Sopenharmony_ci goto cleanup; 372bf215546Sopenharmony_ci } 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci /* Fill vtbl last to prevent accidentally calling virtual function during 375bf215546Sopenharmony_ci * initialization. 376bf215546Sopenharmony_ci */ 377bf215546Sopenharmony_ci dri2_dpy->vtbl = &dri2_surfaceless_display_vtbl; 378bf215546Sopenharmony_ci 379bf215546Sopenharmony_ci return EGL_TRUE; 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_cicleanup: 382bf215546Sopenharmony_ci dri2_display_destroy(disp); 383bf215546Sopenharmony_ci return _eglError(EGL_NOT_INITIALIZED, err); 384bf215546Sopenharmony_ci} 385