1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Mesa 3-D graphics library
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Copyright 2018 Collabora
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Based on platform_surfaceless, which has:
7bf215546Sopenharmony_ci *
8bf215546Sopenharmony_ci * Copyright (c) 2014 The Chromium OS Authors.
9bf215546Sopenharmony_ci * Copyright © 2011 Intel Corporation
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
12bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
13bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
14bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
16bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included
19bf215546Sopenharmony_ci * in all copies or substantial portions of the Software.
20bf215546Sopenharmony_ci *
21bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
28bf215546Sopenharmony_ci */
29bf215546Sopenharmony_ci#ifdef HAVE_LIBDRM
30bf215546Sopenharmony_ci#include <xf86drm.h>
31bf215546Sopenharmony_ci#endif
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci#include <stdlib.h>
34bf215546Sopenharmony_ci#include <stdio.h>
35bf215546Sopenharmony_ci#include <string.h>
36bf215546Sopenharmony_ci#include <dlfcn.h>
37bf215546Sopenharmony_ci#include <sys/types.h>
38bf215546Sopenharmony_ci#include <sys/stat.h>
39bf215546Sopenharmony_ci#include <fcntl.h>
40bf215546Sopenharmony_ci#include <unistd.h>
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci#include "egl_dri2.h"
43bf215546Sopenharmony_ci#include "loader.h"
44bf215546Sopenharmony_ci#include "kopper_interface.h"
45bf215546Sopenharmony_ci#include "util/debug.h"
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_cistatic __DRIimage*
48bf215546Sopenharmony_cidevice_alloc_image(struct dri2_egl_display *dri2_dpy,
49bf215546Sopenharmony_ci                   struct dri2_egl_surface *dri2_surf)
50bf215546Sopenharmony_ci{
51bf215546Sopenharmony_ci   return dri2_dpy->image->createImage(
52bf215546Sopenharmony_ci            dri2_dpy->dri_screen,
53bf215546Sopenharmony_ci            dri2_surf->base.Width,
54bf215546Sopenharmony_ci            dri2_surf->base.Height,
55bf215546Sopenharmony_ci            dri2_surf->visual,
56bf215546Sopenharmony_ci            0,
57bf215546Sopenharmony_ci            NULL);
58bf215546Sopenharmony_ci}
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_cistatic void
61bf215546Sopenharmony_cidevice_free_images(struct dri2_egl_surface *dri2_surf)
62bf215546Sopenharmony_ci{
63bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy =
64bf215546Sopenharmony_ci      dri2_egl_display(dri2_surf->base.Resource.Display);
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci   if (dri2_surf->front) {
67bf215546Sopenharmony_ci      dri2_dpy->image->destroyImage(dri2_surf->front);
68bf215546Sopenharmony_ci      dri2_surf->front = NULL;
69bf215546Sopenharmony_ci   }
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_ci   free(dri2_surf->swrast_device_buffer);
72bf215546Sopenharmony_ci   dri2_surf->swrast_device_buffer = NULL;
73bf215546Sopenharmony_ci}
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_cistatic int
76bf215546Sopenharmony_cidevice_image_get_buffers(__DRIdrawable *driDrawable,
77bf215546Sopenharmony_ci                         unsigned int format,
78bf215546Sopenharmony_ci                         uint32_t *stamp,
79bf215546Sopenharmony_ci                         void *loaderPrivate,
80bf215546Sopenharmony_ci                         uint32_t buffer_mask,
81bf215546Sopenharmony_ci                         struct __DRIimageList *buffers)
82bf215546Sopenharmony_ci{
83bf215546Sopenharmony_ci   struct dri2_egl_surface *dri2_surf = loaderPrivate;
84bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy =
85bf215546Sopenharmony_ci      dri2_egl_display(dri2_surf->base.Resource.Display);
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci   buffers->image_mask = 0;
88bf215546Sopenharmony_ci   buffers->front = NULL;
89bf215546Sopenharmony_ci   buffers->back = NULL;
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci   /* The EGL 1.5 spec states that pbuffers are single-buffered. Specifically,
92bf215546Sopenharmony_ci    * the spec states that they have a back buffer but no front buffer, in
93bf215546Sopenharmony_ci    * contrast to pixmaps, which have a front buffer but no back buffer.
94bf215546Sopenharmony_ci    *
95bf215546Sopenharmony_ci    * Single-buffered surfaces with no front buffer confuse Mesa; so we deviate
96bf215546Sopenharmony_ci    * from the spec, following the precedent of Mesa's EGL X11 platform. The
97bf215546Sopenharmony_ci    * X11 platform correctly assigns pbuffers to single-buffered configs, but
98bf215546Sopenharmony_ci    * assigns the pbuffer a front buffer instead of a back buffer.
99bf215546Sopenharmony_ci    *
100bf215546Sopenharmony_ci    * Pbuffers in the X11 platform mostly work today, so let's just copy its
101bf215546Sopenharmony_ci    * behavior instead of trying to fix (and hence potentially breaking) the
102bf215546Sopenharmony_ci    * world.
103bf215546Sopenharmony_ci    */
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci   if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci      if (!dri2_surf->front)
108bf215546Sopenharmony_ci         dri2_surf->front =
109bf215546Sopenharmony_ci            device_alloc_image(dri2_dpy, dri2_surf);
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_ci      buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
112bf215546Sopenharmony_ci      buffers->front = dri2_surf->front;
113bf215546Sopenharmony_ci   }
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci   return 1;
116bf215546Sopenharmony_ci}
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_cistatic _EGLSurface *
119bf215546Sopenharmony_cidri2_device_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf,
120bf215546Sopenharmony_ci                           const EGLint *attrib_list)
121bf215546Sopenharmony_ci{
122bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
123bf215546Sopenharmony_ci   struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
124bf215546Sopenharmony_ci   struct dri2_egl_surface *dri2_surf;
125bf215546Sopenharmony_ci   const __DRIconfig *config;
126bf215546Sopenharmony_ci
127bf215546Sopenharmony_ci   /* Make sure to calloc so all pointers
128bf215546Sopenharmony_ci    * are originally NULL.
129bf215546Sopenharmony_ci    */
130bf215546Sopenharmony_ci   dri2_surf = calloc(1, sizeof *dri2_surf);
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci   if (!dri2_surf) {
133bf215546Sopenharmony_ci      _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
134bf215546Sopenharmony_ci      return NULL;
135bf215546Sopenharmony_ci   }
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci   if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list,
138bf215546Sopenharmony_ci                          false, NULL))
139bf215546Sopenharmony_ci      goto cleanup_surface;
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci   config = dri2_get_dri_config(dri2_conf, type,
142bf215546Sopenharmony_ci                                dri2_surf->base.GLColorspace);
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci   if (!config) {
145bf215546Sopenharmony_ci      _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration");
146bf215546Sopenharmony_ci      goto cleanup_surface;
147bf215546Sopenharmony_ci   }
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci   dri2_surf->visual = dri2_image_format_for_pbuffer_config(dri2_dpy, config);
150bf215546Sopenharmony_ci   if (dri2_surf->visual == __DRI_IMAGE_FORMAT_NONE)
151bf215546Sopenharmony_ci      goto cleanup_surface;
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci   if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf))
154bf215546Sopenharmony_ci      goto cleanup_surface;
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci   return &dri2_surf->base;
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci   cleanup_surface:
159bf215546Sopenharmony_ci      free(dri2_surf);
160bf215546Sopenharmony_ci      return NULL;
161bf215546Sopenharmony_ci}
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_cistatic EGLBoolean
164bf215546Sopenharmony_cidevice_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
165bf215546Sopenharmony_ci{
166bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
167bf215546Sopenharmony_ci   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci   device_free_images(dri2_surf);
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci   dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci   dri2_fini_surface(surf);
174bf215546Sopenharmony_ci   free(dri2_surf);
175bf215546Sopenharmony_ci   return EGL_TRUE;
176bf215546Sopenharmony_ci}
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_cistatic _EGLSurface *
179bf215546Sopenharmony_cidri2_device_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
180bf215546Sopenharmony_ci                                   const EGLint *attrib_list)
181bf215546Sopenharmony_ci{
182bf215546Sopenharmony_ci   return dri2_device_create_surface(disp, EGL_PBUFFER_BIT, conf, attrib_list);
183bf215546Sopenharmony_ci}
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_cistatic const struct dri2_egl_display_vtbl dri2_device_display_vtbl = {
186bf215546Sopenharmony_ci   .create_pbuffer_surface = dri2_device_create_pbuffer_surface,
187bf215546Sopenharmony_ci   .destroy_surface = device_destroy_surface,
188bf215546Sopenharmony_ci   .create_image = dri2_create_image_khr,
189bf215546Sopenharmony_ci   .get_dri_drawable = dri2_surface_get_dri_drawable,
190bf215546Sopenharmony_ci};
191bf215546Sopenharmony_ci
192bf215546Sopenharmony_cistatic void
193bf215546Sopenharmony_cidevice_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate)
194bf215546Sopenharmony_ci{
195bf215546Sopenharmony_ci}
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_cistatic unsigned
198bf215546Sopenharmony_cidevice_get_capability(void *loaderPrivate, enum dri_loader_cap cap)
199bf215546Sopenharmony_ci{
200bf215546Sopenharmony_ci   /* Note: loaderPrivate is _EGLDisplay* */
201bf215546Sopenharmony_ci   switch (cap) {
202bf215546Sopenharmony_ci   case DRI_LOADER_CAP_FP16:
203bf215546Sopenharmony_ci      return 1;
204bf215546Sopenharmony_ci   default:
205bf215546Sopenharmony_ci      return 0;
206bf215546Sopenharmony_ci   }
207bf215546Sopenharmony_ci}
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_cistatic const __DRIimageLoaderExtension image_loader_extension = {
210bf215546Sopenharmony_ci   .base             = { __DRI_IMAGE_LOADER, 2 },
211bf215546Sopenharmony_ci   .getBuffers       = device_image_get_buffers,
212bf215546Sopenharmony_ci   .flushFrontBuffer = device_flush_front_buffer,
213bf215546Sopenharmony_ci   .getCapability    = device_get_capability,
214bf215546Sopenharmony_ci};
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_cistatic const __DRIkopperLoaderExtension kopper_loader_extension = {
217bf215546Sopenharmony_ci    .base = { __DRI_KOPPER_LOADER, 1 },
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ci    .SetSurfaceCreateInfo   = NULL,
220bf215546Sopenharmony_ci};
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_cistatic const __DRIextension *image_loader_extensions[] = {
223bf215546Sopenharmony_ci   &image_loader_extension.base,
224bf215546Sopenharmony_ci   &image_lookup_extension.base,
225bf215546Sopenharmony_ci   &use_invalidate.base,
226bf215546Sopenharmony_ci   &kopper_loader_extension.base,
227bf215546Sopenharmony_ci   NULL,
228bf215546Sopenharmony_ci};
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_cistatic const __DRIextension *swrast_loader_extensions[] = {
231bf215546Sopenharmony_ci   &swrast_pbuffer_loader_extension.base,
232bf215546Sopenharmony_ci   &image_lookup_extension.base,
233bf215546Sopenharmony_ci   &use_invalidate.base,
234bf215546Sopenharmony_ci   &kopper_loader_extension.base,
235bf215546Sopenharmony_ci   NULL,
236bf215546Sopenharmony_ci};
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_cistatic int
239bf215546Sopenharmony_cidevice_get_fd(_EGLDisplay *disp, _EGLDevice *dev)
240bf215546Sopenharmony_ci{
241bf215546Sopenharmony_ci#ifdef HAVE_LIBDRM
242bf215546Sopenharmony_ci   int fd = disp->Options.fd;
243bf215546Sopenharmony_ci   /* The fcntl() code in _eglGetDeviceDisplay() ensures that valid fd >= 3,
244bf215546Sopenharmony_ci    * and invalid one is 0.
245bf215546Sopenharmony_ci    */
246bf215546Sopenharmony_ci   if (fd) {
247bf215546Sopenharmony_ci      /* According to the spec - if the FD does not match the EGLDevice
248bf215546Sopenharmony_ci       * behaviour is undefined.
249bf215546Sopenharmony_ci       *
250bf215546Sopenharmony_ci       * Add a trivial sanity check since it doesn't cost us anything.
251bf215546Sopenharmony_ci       */
252bf215546Sopenharmony_ci      if (dev != _eglAddDevice(fd, false))
253bf215546Sopenharmony_ci         return -1;
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci      /* No EGL_EXT_output* extensions are supported, hence no master perms
256bf215546Sopenharmony_ci       * are needed. Get the render one - otherwise drivers might error out.
257bf215546Sopenharmony_ci       */
258bf215546Sopenharmony_ci      char *node = drmGetRenderDeviceNameFromFd(fd);
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_ci      /* Don't close the internal fd, get render node one based on it. */
261bf215546Sopenharmony_ci      fd = loader_open_device(node);
262bf215546Sopenharmony_ci      free(node);
263bf215546Sopenharmony_ci      return fd;
264bf215546Sopenharmony_ci   }
265bf215546Sopenharmony_ci   const char *node = _eglGetDRMDeviceRenderNode(dev);
266bf215546Sopenharmony_ci   return loader_open_device(node);
267bf215546Sopenharmony_ci#else
268bf215546Sopenharmony_ci   _eglLog(_EGL_FATAL, "Driver bug: Built without libdrm, yet using a HW device");
269bf215546Sopenharmony_ci   return -1;
270bf215546Sopenharmony_ci#endif
271bf215546Sopenharmony_ci}
272bf215546Sopenharmony_ci
273bf215546Sopenharmony_cistatic bool
274bf215546Sopenharmony_cidevice_probe_device(_EGLDisplay *disp)
275bf215546Sopenharmony_ci{
276bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
277bf215546Sopenharmony_ci   bool request_software = env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false);
278bf215546Sopenharmony_ci
279bf215546Sopenharmony_ci   if (request_software)
280bf215546Sopenharmony_ci      _eglLog(_EGL_WARNING, "Not allowed to force software rendering when "
281bf215546Sopenharmony_ci                            "API explicitly selects a hardware device.");
282bf215546Sopenharmony_ci   dri2_dpy->fd = device_get_fd(disp, disp->Device);
283bf215546Sopenharmony_ci   if (dri2_dpy->fd < 0)
284bf215546Sopenharmony_ci      return false;
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_ci   dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
287bf215546Sopenharmony_ci   if (!dri2_dpy->driver_name)
288bf215546Sopenharmony_ci      goto err_name;
289bf215546Sopenharmony_ci
290bf215546Sopenharmony_ci   /* When doing software rendering, some times user still want to explicitly
291bf215546Sopenharmony_ci    * choose the render node device since cross node import doesn't work between
292bf215546Sopenharmony_ci    * vgem/virtio_gpu yet. It would be nice to have a new EXTENSION for this.
293bf215546Sopenharmony_ci    * For now, just fallback to kms_swrast. */
294bf215546Sopenharmony_ci   if (disp->Options.ForceSoftware && !request_software &&
295bf215546Sopenharmony_ci       (strcmp(dri2_dpy->driver_name, "vgem") == 0 ||
296bf215546Sopenharmony_ci        strcmp(dri2_dpy->driver_name, "virtio_gpu") == 0)) {
297bf215546Sopenharmony_ci      free(dri2_dpy->driver_name);
298bf215546Sopenharmony_ci      _eglLog(_EGL_WARNING, "NEEDS EXTENSION: falling back to kms_swrast");
299bf215546Sopenharmony_ci      dri2_dpy->driver_name = strdup("kms_swrast");
300bf215546Sopenharmony_ci   }
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_ci   if (!dri2_load_driver_dri3(disp))
303bf215546Sopenharmony_ci      goto err_load;
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci   dri2_dpy->loader_extensions = image_loader_extensions;
306bf215546Sopenharmony_ci   return true;
307bf215546Sopenharmony_ci
308bf215546Sopenharmony_cierr_load:
309bf215546Sopenharmony_ci   free(dri2_dpy->driver_name);
310bf215546Sopenharmony_ci   dri2_dpy->driver_name = NULL;
311bf215546Sopenharmony_ci
312bf215546Sopenharmony_cierr_name:
313bf215546Sopenharmony_ci   close(dri2_dpy->fd);
314bf215546Sopenharmony_ci   dri2_dpy->fd = -1;
315bf215546Sopenharmony_ci   return false;
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci}
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_cistatic bool
320bf215546Sopenharmony_cidevice_probe_device_sw(_EGLDisplay *disp)
321bf215546Sopenharmony_ci{
322bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_ci   dri2_dpy->fd = -1;
325bf215546Sopenharmony_ci   dri2_dpy->driver_name = strdup(disp->Options.Zink ? "zink" : "swrast");
326bf215546Sopenharmony_ci   if (!dri2_dpy->driver_name)
327bf215546Sopenharmony_ci      return false;
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ci   /* HACK: should be driver_swrast_null */
330bf215546Sopenharmony_ci   if (!dri2_load_driver_swrast(disp)) {
331bf215546Sopenharmony_ci      free(dri2_dpy->driver_name);
332bf215546Sopenharmony_ci      dri2_dpy->driver_name = NULL;
333bf215546Sopenharmony_ci      return false;
334bf215546Sopenharmony_ci   }
335bf215546Sopenharmony_ci
336bf215546Sopenharmony_ci   dri2_dpy->loader_extensions = swrast_loader_extensions;
337bf215546Sopenharmony_ci   return true;
338bf215546Sopenharmony_ci}
339bf215546Sopenharmony_ci
340bf215546Sopenharmony_ciEGLBoolean
341bf215546Sopenharmony_cidri2_initialize_device(_EGLDisplay *disp)
342bf215546Sopenharmony_ci{
343bf215546Sopenharmony_ci   _EGLDevice *dev;
344bf215546Sopenharmony_ci   struct dri2_egl_display *dri2_dpy;
345bf215546Sopenharmony_ci   const char* err;
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_ci   dri2_dpy = calloc(1, sizeof *dri2_dpy);
348bf215546Sopenharmony_ci   if (!dri2_dpy)
349bf215546Sopenharmony_ci      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci   /* Extension requires a PlatformDisplay - the EGLDevice. */
352bf215546Sopenharmony_ci   dev = disp->PlatformDisplay;
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_ci   dri2_dpy->fd = -1;
355bf215546Sopenharmony_ci   disp->Device = dev;
356bf215546Sopenharmony_ci   disp->DriverData = (void *) dri2_dpy;
357bf215546Sopenharmony_ci   err = "DRI2: failed to load driver";
358bf215546Sopenharmony_ci   if (_eglDeviceSupports(dev, _EGL_DEVICE_DRM)) {
359bf215546Sopenharmony_ci      if (!device_probe_device(disp))
360bf215546Sopenharmony_ci         goto cleanup;
361bf215546Sopenharmony_ci   } else if (_eglDeviceSupports(dev, _EGL_DEVICE_SOFTWARE)) {
362bf215546Sopenharmony_ci      if (!device_probe_device_sw(disp))
363bf215546Sopenharmony_ci         goto cleanup;
364bf215546Sopenharmony_ci   } else {
365bf215546Sopenharmony_ci      _eglLog(_EGL_FATAL, "Driver bug: exposed device is neither DRM nor SOFTWARE one");
366bf215546Sopenharmony_ci      return EGL_FALSE;
367bf215546Sopenharmony_ci   }
368bf215546Sopenharmony_ci
369bf215546Sopenharmony_ci   if (!dri2_create_screen(disp)) {
370bf215546Sopenharmony_ci      err = "DRI2: failed to create screen";
371bf215546Sopenharmony_ci      goto cleanup;
372bf215546Sopenharmony_ci   }
373bf215546Sopenharmony_ci
374bf215546Sopenharmony_ci   if (!dri2_setup_extensions(disp)) {
375bf215546Sopenharmony_ci      err = "DRI2: failed to find required DRI extensions";
376bf215546Sopenharmony_ci      goto cleanup;
377bf215546Sopenharmony_ci   }
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci   dri2_setup_screen(disp);
380bf215546Sopenharmony_ci#ifdef HAVE_WAYLAND_PLATFORM
381bf215546Sopenharmony_ci   dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd);
382bf215546Sopenharmony_ci#endif
383bf215546Sopenharmony_ci   dri2_set_WL_bind_wayland_display(disp);
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_ci   if (!dri2_add_pbuffer_configs_for_visuals(disp)) {
386bf215546Sopenharmony_ci      err = "DRI2: failed to add configs";
387bf215546Sopenharmony_ci      goto cleanup;
388bf215546Sopenharmony_ci   }
389bf215546Sopenharmony_ci
390bf215546Sopenharmony_ci   /* Fill vtbl last to prevent accidentally calling virtual function during
391bf215546Sopenharmony_ci    * initialization.
392bf215546Sopenharmony_ci    */
393bf215546Sopenharmony_ci   dri2_dpy->vtbl = &dri2_device_display_vtbl;
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci   return EGL_TRUE;
396bf215546Sopenharmony_ci
397bf215546Sopenharmony_cicleanup:
398bf215546Sopenharmony_ci   dri2_display_destroy(disp);
399bf215546Sopenharmony_ci   return _eglError(EGL_NOT_INITIALIZED, err);
400bf215546Sopenharmony_ci}
401