1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2011 Intel Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18bf215546Sopenharmony_ci * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19bf215546Sopenharmony_ci * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20bf215546Sopenharmony_ci * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
23bf215546Sopenharmony_ci *
24bf215546Sopenharmony_ci * Authors:
25bf215546Sopenharmony_ci *    Benjamin Franzke <benjaminfranzke@googlemail.com>
26bf215546Sopenharmony_ci */
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include <stdio.h>
29bf215546Sopenharmony_ci#include <stdlib.h>
30bf215546Sopenharmony_ci#include <stddef.h>
31bf215546Sopenharmony_ci#include <stdint.h>
32bf215546Sopenharmony_ci#include <stdbool.h>
33bf215546Sopenharmony_ci#include <string.h>
34bf215546Sopenharmony_ci#include <errno.h>
35bf215546Sopenharmony_ci#include <limits.h>
36bf215546Sopenharmony_ci#include <assert.h>
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci#include <sys/types.h>
39bf215546Sopenharmony_ci#include <unistd.h>
40bf215546Sopenharmony_ci#include <dlfcn.h>
41bf215546Sopenharmony_ci#include <xf86drm.h>
42bf215546Sopenharmony_ci#include "drm-uapi/drm_fourcc.h"
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_ci#include <GL/gl.h> /* dri_interface needs GL types */
45bf215546Sopenharmony_ci#include <GL/internal/dri_interface.h>
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_ci#include "gbm_driint.h"
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci#include "gbmint.h"
50bf215546Sopenharmony_ci#include "loader_dri_helper.h"
51bf215546Sopenharmony_ci#include "kopper_interface.h"
52bf215546Sopenharmony_ci#include "loader.h"
53bf215546Sopenharmony_ci#include "util/debug.h"
54bf215546Sopenharmony_ci#include "util/macros.h"
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci/* For importing wl_buffer */
57bf215546Sopenharmony_ci#if HAVE_WAYLAND_PLATFORM
58bf215546Sopenharmony_ci#include "wayland-drm.h"
59bf215546Sopenharmony_ci#endif
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_cistatic __DRIimage *
62bf215546Sopenharmony_cidri_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
63bf215546Sopenharmony_ci{
64bf215546Sopenharmony_ci   struct gbm_dri_device *dri = data;
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci   if (dri->lookup_image == NULL)
67bf215546Sopenharmony_ci      return NULL;
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ci   return dri->lookup_image(screen, image, dri->lookup_user_data);
70bf215546Sopenharmony_ci}
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_cistatic GLboolean
73bf215546Sopenharmony_cidri_validate_egl_image(void *image, void *data)
74bf215546Sopenharmony_ci{
75bf215546Sopenharmony_ci   struct gbm_dri_device *dri = data;
76bf215546Sopenharmony_ci
77bf215546Sopenharmony_ci   if (dri->validate_image == NULL)
78bf215546Sopenharmony_ci      return false;
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci   return dri->validate_image(image, dri->lookup_user_data);
81bf215546Sopenharmony_ci}
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_cistatic __DRIimage *
84bf215546Sopenharmony_cidri_lookup_egl_image_validated(void *image, void *data)
85bf215546Sopenharmony_ci{
86bf215546Sopenharmony_ci   struct gbm_dri_device *dri = data;
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci   if (dri->lookup_image_validated == NULL)
89bf215546Sopenharmony_ci      return NULL;
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci   return dri->lookup_image_validated(image, dri->lookup_user_data);
92bf215546Sopenharmony_ci}
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_cistatic __DRIbuffer *
95bf215546Sopenharmony_cidri_get_buffers(__DRIdrawable * driDrawable,
96bf215546Sopenharmony_ci		 int *width, int *height,
97bf215546Sopenharmony_ci		 unsigned int *attachments, int count,
98bf215546Sopenharmony_ci		 int *out_count, void *data)
99bf215546Sopenharmony_ci{
100bf215546Sopenharmony_ci   struct gbm_dri_surface *surf = data;
101bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci   if (dri->get_buffers == NULL)
104bf215546Sopenharmony_ci      return NULL;
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci   return dri->get_buffers(driDrawable, width, height, attachments,
107bf215546Sopenharmony_ci                           count, out_count, surf->dri_private);
108bf215546Sopenharmony_ci}
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_cistatic void
111bf215546Sopenharmony_cidri_flush_front_buffer(__DRIdrawable * driDrawable, void *data)
112bf215546Sopenharmony_ci{
113bf215546Sopenharmony_ci   struct gbm_dri_surface *surf = data;
114bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci   if (dri->flush_front_buffer != NULL)
117bf215546Sopenharmony_ci      dri->flush_front_buffer(driDrawable, surf->dri_private);
118bf215546Sopenharmony_ci}
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_cistatic __DRIbuffer *
121bf215546Sopenharmony_cidri_get_buffers_with_format(__DRIdrawable * driDrawable,
122bf215546Sopenharmony_ci                            int *width, int *height,
123bf215546Sopenharmony_ci                            unsigned int *attachments, int count,
124bf215546Sopenharmony_ci                            int *out_count, void *data)
125bf215546Sopenharmony_ci{
126bf215546Sopenharmony_ci   struct gbm_dri_surface *surf = data;
127bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_ci   if (dri->get_buffers_with_format == NULL)
130bf215546Sopenharmony_ci      return NULL;
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci   return
133bf215546Sopenharmony_ci      dri->get_buffers_with_format(driDrawable, width, height, attachments,
134bf215546Sopenharmony_ci                                   count, out_count, surf->dri_private);
135bf215546Sopenharmony_ci}
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_cistatic unsigned
138bf215546Sopenharmony_cidri_get_capability(void *loaderPrivate, enum dri_loader_cap cap)
139bf215546Sopenharmony_ci{
140bf215546Sopenharmony_ci   /* Note: loaderPrivate is _EGLDisplay* */
141bf215546Sopenharmony_ci   switch (cap) {
142bf215546Sopenharmony_ci   case DRI_LOADER_CAP_FP16:
143bf215546Sopenharmony_ci      return 1;
144bf215546Sopenharmony_ci   default:
145bf215546Sopenharmony_ci      return 0;
146bf215546Sopenharmony_ci   }
147bf215546Sopenharmony_ci}
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_cistatic int
150bf215546Sopenharmony_ciimage_get_buffers(__DRIdrawable *driDrawable,
151bf215546Sopenharmony_ci                  unsigned int format,
152bf215546Sopenharmony_ci                  uint32_t *stamp,
153bf215546Sopenharmony_ci                  void *loaderPrivate,
154bf215546Sopenharmony_ci                  uint32_t buffer_mask,
155bf215546Sopenharmony_ci                  struct __DRIimageList *buffers)
156bf215546Sopenharmony_ci{
157bf215546Sopenharmony_ci   struct gbm_dri_surface *surf = loaderPrivate;
158bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
159bf215546Sopenharmony_ci
160bf215546Sopenharmony_ci   if (dri->image_get_buffers == NULL)
161bf215546Sopenharmony_ci      return 0;
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_ci   return dri->image_get_buffers(driDrawable, format, stamp,
164bf215546Sopenharmony_ci                                 surf->dri_private, buffer_mask, buffers);
165bf215546Sopenharmony_ci}
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_cistatic void
168bf215546Sopenharmony_ciswrast_get_drawable_info(__DRIdrawable *driDrawable,
169bf215546Sopenharmony_ci                         int           *x,
170bf215546Sopenharmony_ci                         int           *y,
171bf215546Sopenharmony_ci                         int           *width,
172bf215546Sopenharmony_ci                         int           *height,
173bf215546Sopenharmony_ci                         void          *loaderPrivate)
174bf215546Sopenharmony_ci{
175bf215546Sopenharmony_ci   struct gbm_dri_surface *surf = loaderPrivate;
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_ci   *x = 0;
178bf215546Sopenharmony_ci   *y = 0;
179bf215546Sopenharmony_ci   *width = surf->base.v0.width;
180bf215546Sopenharmony_ci   *height = surf->base.v0.height;
181bf215546Sopenharmony_ci}
182bf215546Sopenharmony_ci
183bf215546Sopenharmony_cistatic void
184bf215546Sopenharmony_ciswrast_put_image2(__DRIdrawable *driDrawable,
185bf215546Sopenharmony_ci                  int            op,
186bf215546Sopenharmony_ci                  int            x,
187bf215546Sopenharmony_ci                  int            y,
188bf215546Sopenharmony_ci                  int            width,
189bf215546Sopenharmony_ci                  int            height,
190bf215546Sopenharmony_ci                  int            stride,
191bf215546Sopenharmony_ci                  char          *data,
192bf215546Sopenharmony_ci                  void          *loaderPrivate)
193bf215546Sopenharmony_ci{
194bf215546Sopenharmony_ci   struct gbm_dri_surface *surf = loaderPrivate;
195bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci   dri->swrast_put_image2(driDrawable,
198bf215546Sopenharmony_ci                          op, x, y,
199bf215546Sopenharmony_ci                          width, height, stride,
200bf215546Sopenharmony_ci                          data, surf->dri_private);
201bf215546Sopenharmony_ci}
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_cistatic void
204bf215546Sopenharmony_ciswrast_put_image(__DRIdrawable *driDrawable,
205bf215546Sopenharmony_ci                 int            op,
206bf215546Sopenharmony_ci                 int            x,
207bf215546Sopenharmony_ci                 int            y,
208bf215546Sopenharmony_ci                 int            width,
209bf215546Sopenharmony_ci                 int            height,
210bf215546Sopenharmony_ci                 char          *data,
211bf215546Sopenharmony_ci                 void          *loaderPrivate)
212bf215546Sopenharmony_ci{
213bf215546Sopenharmony_ci   swrast_put_image2(driDrawable, op, x, y, width, height,
214bf215546Sopenharmony_ci                            width * 4, data, loaderPrivate);
215bf215546Sopenharmony_ci}
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_cistatic void
218bf215546Sopenharmony_ciswrast_get_image(__DRIdrawable *driDrawable,
219bf215546Sopenharmony_ci                 int            x,
220bf215546Sopenharmony_ci                 int            y,
221bf215546Sopenharmony_ci                 int            width,
222bf215546Sopenharmony_ci                 int            height,
223bf215546Sopenharmony_ci                 char          *data,
224bf215546Sopenharmony_ci                 void          *loaderPrivate)
225bf215546Sopenharmony_ci{
226bf215546Sopenharmony_ci   struct gbm_dri_surface *surf = loaderPrivate;
227bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
228bf215546Sopenharmony_ci
229bf215546Sopenharmony_ci   dri->swrast_get_image(driDrawable,
230bf215546Sopenharmony_ci                         x, y,
231bf215546Sopenharmony_ci                         width, height,
232bf215546Sopenharmony_ci                         data, surf->dri_private);
233bf215546Sopenharmony_ci}
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_cistatic const __DRIuseInvalidateExtension use_invalidate = {
236bf215546Sopenharmony_ci   .base = { __DRI_USE_INVALIDATE, 1 }
237bf215546Sopenharmony_ci};
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_cistatic const __DRIimageLookupExtension image_lookup_extension = {
240bf215546Sopenharmony_ci   .base = { __DRI_IMAGE_LOOKUP, 2 },
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_ci   .lookupEGLImage          = dri_lookup_egl_image,
243bf215546Sopenharmony_ci   .validateEGLImage        = dri_validate_egl_image,
244bf215546Sopenharmony_ci   .lookupEGLImageValidated = dri_lookup_egl_image_validated,
245bf215546Sopenharmony_ci};
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_cistatic const __DRIdri2LoaderExtension dri2_loader_extension = {
248bf215546Sopenharmony_ci   .base = { __DRI_DRI2_LOADER, 4 },
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci   .getBuffers              = dri_get_buffers,
251bf215546Sopenharmony_ci   .flushFrontBuffer        = dri_flush_front_buffer,
252bf215546Sopenharmony_ci   .getBuffersWithFormat    = dri_get_buffers_with_format,
253bf215546Sopenharmony_ci   .getCapability           = dri_get_capability,
254bf215546Sopenharmony_ci};
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_cistatic const __DRIimageLoaderExtension image_loader_extension = {
257bf215546Sopenharmony_ci   .base = { __DRI_IMAGE_LOADER, 2 },
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci   .getBuffers          = image_get_buffers,
260bf215546Sopenharmony_ci   .flushFrontBuffer    = dri_flush_front_buffer,
261bf215546Sopenharmony_ci   .getCapability       = dri_get_capability,
262bf215546Sopenharmony_ci};
263bf215546Sopenharmony_ci
264bf215546Sopenharmony_cistatic const __DRIswrastLoaderExtension swrast_loader_extension = {
265bf215546Sopenharmony_ci   .base = { __DRI_SWRAST_LOADER, 2 },
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_ci   .getDrawableInfo = swrast_get_drawable_info,
268bf215546Sopenharmony_ci   .putImage        = swrast_put_image,
269bf215546Sopenharmony_ci   .getImage        = swrast_get_image,
270bf215546Sopenharmony_ci   .putImage2       = swrast_put_image2
271bf215546Sopenharmony_ci};
272bf215546Sopenharmony_ci
273bf215546Sopenharmony_cistatic const __DRIkopperLoaderExtension kopper_loader_extension = {
274bf215546Sopenharmony_ci    .base = { __DRI_KOPPER_LOADER, 1 },
275bf215546Sopenharmony_ci
276bf215546Sopenharmony_ci    .SetSurfaceCreateInfo   = NULL,
277bf215546Sopenharmony_ci};
278bf215546Sopenharmony_ci
279bf215546Sopenharmony_cistatic const __DRIextension *gbm_dri_screen_extensions[] = {
280bf215546Sopenharmony_ci   &image_lookup_extension.base,
281bf215546Sopenharmony_ci   &use_invalidate.base,
282bf215546Sopenharmony_ci   &dri2_loader_extension.base,
283bf215546Sopenharmony_ci   &image_loader_extension.base,
284bf215546Sopenharmony_ci   &swrast_loader_extension.base,
285bf215546Sopenharmony_ci   &kopper_loader_extension.base,
286bf215546Sopenharmony_ci   NULL,
287bf215546Sopenharmony_ci};
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_cistruct dri_extension_match {
290bf215546Sopenharmony_ci   const char *name;
291bf215546Sopenharmony_ci   int version;
292bf215546Sopenharmony_ci   int offset;
293bf215546Sopenharmony_ci   bool optional;
294bf215546Sopenharmony_ci};
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_cistatic struct dri_extension_match dri_core_extensions[] = {
297bf215546Sopenharmony_ci   { __DRI2_FLUSH, 1, offsetof(struct gbm_dri_device, flush), false },
298bf215546Sopenharmony_ci   { __DRI_IMAGE, 1, offsetof(struct gbm_dri_device, image), false },
299bf215546Sopenharmony_ci   { __DRI2_FENCE, 1, offsetof(struct gbm_dri_device, fence), true },
300bf215546Sopenharmony_ci};
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_cistatic struct dri_extension_match gbm_dri_device_extensions[] = {
303bf215546Sopenharmony_ci   { __DRI_CORE, 1, offsetof(struct gbm_dri_device, core), false },
304bf215546Sopenharmony_ci   { __DRI_DRI2, 1, offsetof(struct gbm_dri_device, dri2), false },
305bf215546Sopenharmony_ci};
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_cistatic struct dri_extension_match gbm_swrast_device_extensions[] = {
308bf215546Sopenharmony_ci   { __DRI_CORE, 1, offsetof(struct gbm_dri_device, core), false },
309bf215546Sopenharmony_ci   { __DRI_SWRAST, 1, offsetof(struct gbm_dri_device, swrast), false },
310bf215546Sopenharmony_ci   { __DRI_KOPPER, 1, offsetof(struct gbm_dri_device, kopper), true },
311bf215546Sopenharmony_ci};
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_cistatic bool
314bf215546Sopenharmony_cidri_bind_extensions(struct gbm_dri_device *dri,
315bf215546Sopenharmony_ci                    struct dri_extension_match *matches, size_t num_matches,
316bf215546Sopenharmony_ci                    const __DRIextension **extensions)
317bf215546Sopenharmony_ci{
318bf215546Sopenharmony_ci   bool ret = true;
319bf215546Sopenharmony_ci   void *field;
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_ci   for (size_t i = 0; extensions[i]; i++) {
322bf215546Sopenharmony_ci      for (size_t j = 0; j < num_matches; j++) {
323bf215546Sopenharmony_ci         if (strcmp(extensions[i]->name, matches[j].name) == 0 &&
324bf215546Sopenharmony_ci             extensions[i]->version >= matches[j].version) {
325bf215546Sopenharmony_ci            field = ((char *) dri + matches[j].offset);
326bf215546Sopenharmony_ci            *(const __DRIextension **) field = extensions[i];
327bf215546Sopenharmony_ci         }
328bf215546Sopenharmony_ci      }
329bf215546Sopenharmony_ci   }
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_ci   for (size_t j = 0; j < num_matches; j++) {
332bf215546Sopenharmony_ci      field = ((char *) dri + matches[j].offset);
333bf215546Sopenharmony_ci      if ((*(const __DRIextension **) field == NULL) && !matches[j].optional) {
334bf215546Sopenharmony_ci         fprintf(stderr, "gbm: did not find extension %s version %d\n",
335bf215546Sopenharmony_ci                 matches[j].name, matches[j].version);
336bf215546Sopenharmony_ci         ret = false;
337bf215546Sopenharmony_ci      }
338bf215546Sopenharmony_ci   }
339bf215546Sopenharmony_ci
340bf215546Sopenharmony_ci   return ret;
341bf215546Sopenharmony_ci}
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_cistatic const __DRIextension **
344bf215546Sopenharmony_cidri_open_driver(struct gbm_dri_device *dri)
345bf215546Sopenharmony_ci{
346bf215546Sopenharmony_ci   /* Temporarily work around dri driver libs that need symbols in libglapi
347bf215546Sopenharmony_ci    * but don't automatically link it in.
348bf215546Sopenharmony_ci    */
349bf215546Sopenharmony_ci   /* XXX: Library name differs on per platforms basis. Update this as
350bf215546Sopenharmony_ci    * osx/cygwin/windows/bsd gets support for GBM..
351bf215546Sopenharmony_ci    */
352bf215546Sopenharmony_ci   dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL);
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_ci   static const char *search_path_vars[] = {
355bf215546Sopenharmony_ci      /* Read GBM_DRIVERS_PATH first for compatibility, but LIBGL_DRIVERS_PATH
356bf215546Sopenharmony_ci       * is recommended over GBM_DRIVERS_PATH.
357bf215546Sopenharmony_ci       */
358bf215546Sopenharmony_ci      "GBM_DRIVERS_PATH",
359bf215546Sopenharmony_ci      /* Read LIBGL_DRIVERS_PATH if GBM_DRIVERS_PATH was not set.
360bf215546Sopenharmony_ci       * LIBGL_DRIVERS_PATH is recommended over GBM_DRIVERS_PATH.
361bf215546Sopenharmony_ci       */
362bf215546Sopenharmony_ci      "LIBGL_DRIVERS_PATH",
363bf215546Sopenharmony_ci      NULL
364bf215546Sopenharmony_ci   };
365bf215546Sopenharmony_ci   return loader_open_driver(dri->driver_name, &dri->driver, search_path_vars);
366bf215546Sopenharmony_ci}
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_cistatic int
369bf215546Sopenharmony_cidri_load_driver(struct gbm_dri_device *dri)
370bf215546Sopenharmony_ci{
371bf215546Sopenharmony_ci   const __DRIextension **extensions;
372bf215546Sopenharmony_ci
373bf215546Sopenharmony_ci   extensions = dri_open_driver(dri);
374bf215546Sopenharmony_ci   if (!extensions)
375bf215546Sopenharmony_ci      return -1;
376bf215546Sopenharmony_ci
377bf215546Sopenharmony_ci   if (!dri_bind_extensions(dri, gbm_dri_device_extensions,
378bf215546Sopenharmony_ci                            ARRAY_SIZE(gbm_dri_device_extensions),
379bf215546Sopenharmony_ci                            extensions)) {
380bf215546Sopenharmony_ci      dlclose(dri->driver);
381bf215546Sopenharmony_ci      fprintf(stderr, "failed to bind extensions\n");
382bf215546Sopenharmony_ci      return -1;
383bf215546Sopenharmony_ci   }
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_ci   dri->driver_extensions = extensions;
386bf215546Sopenharmony_ci
387bf215546Sopenharmony_ci   return 0;
388bf215546Sopenharmony_ci}
389bf215546Sopenharmony_ci
390bf215546Sopenharmony_cistatic int
391bf215546Sopenharmony_cidri_load_driver_swrast(struct gbm_dri_device *dri)
392bf215546Sopenharmony_ci{
393bf215546Sopenharmony_ci   const __DRIextension **extensions;
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci   extensions = dri_open_driver(dri);
396bf215546Sopenharmony_ci   if (!extensions)
397bf215546Sopenharmony_ci      return -1;
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci   if (!dri_bind_extensions(dri, gbm_swrast_device_extensions,
400bf215546Sopenharmony_ci                            ARRAY_SIZE(gbm_swrast_device_extensions),
401bf215546Sopenharmony_ci                            extensions)) {
402bf215546Sopenharmony_ci      dlclose(dri->driver);
403bf215546Sopenharmony_ci      fprintf(stderr, "failed to bind extensions\n");
404bf215546Sopenharmony_ci      return -1;
405bf215546Sopenharmony_ci   }
406bf215546Sopenharmony_ci
407bf215546Sopenharmony_ci   dri->driver_extensions = extensions;
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_ci   return 0;
410bf215546Sopenharmony_ci}
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_cistatic int
413bf215546Sopenharmony_cidri_screen_create_dri2(struct gbm_dri_device *dri, char *driver_name)
414bf215546Sopenharmony_ci{
415bf215546Sopenharmony_ci   const __DRIextension **extensions;
416bf215546Sopenharmony_ci   int ret = 0;
417bf215546Sopenharmony_ci
418bf215546Sopenharmony_ci   dri->driver_name = driver_name;
419bf215546Sopenharmony_ci   if (dri->driver_name == NULL)
420bf215546Sopenharmony_ci      return -1;
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_ci   ret = dri_load_driver(dri);
423bf215546Sopenharmony_ci   if (ret) {
424bf215546Sopenharmony_ci      fprintf(stderr, "failed to load driver: %s\n", dri->driver_name);
425bf215546Sopenharmony_ci      return ret;
426bf215546Sopenharmony_ci   }
427bf215546Sopenharmony_ci
428bf215546Sopenharmony_ci   dri->loader_extensions = gbm_dri_screen_extensions;
429bf215546Sopenharmony_ci
430bf215546Sopenharmony_ci   if (dri->dri2 == NULL)
431bf215546Sopenharmony_ci      return -1;
432bf215546Sopenharmony_ci
433bf215546Sopenharmony_ci   if (dri->dri2->base.version >= 4) {
434bf215546Sopenharmony_ci      dri->screen = dri->dri2->createNewScreen2(0, dri->base.v0.fd,
435bf215546Sopenharmony_ci                                                dri->loader_extensions,
436bf215546Sopenharmony_ci                                                dri->driver_extensions,
437bf215546Sopenharmony_ci                                                &dri->driver_configs, dri);
438bf215546Sopenharmony_ci   } else {
439bf215546Sopenharmony_ci      dri->screen = dri->dri2->createNewScreen(0, dri->base.v0.fd,
440bf215546Sopenharmony_ci                                               dri->loader_extensions,
441bf215546Sopenharmony_ci                                               &dri->driver_configs, dri);
442bf215546Sopenharmony_ci   }
443bf215546Sopenharmony_ci   if (dri->screen == NULL)
444bf215546Sopenharmony_ci      return -1;
445bf215546Sopenharmony_ci
446bf215546Sopenharmony_ci   extensions = dri->core->getExtensions(dri->screen);
447bf215546Sopenharmony_ci   if (!dri_bind_extensions(dri, dri_core_extensions,
448bf215546Sopenharmony_ci                            ARRAY_SIZE(dri_core_extensions),
449bf215546Sopenharmony_ci                            extensions)) {
450bf215546Sopenharmony_ci      ret = -1;
451bf215546Sopenharmony_ci      goto free_screen;
452bf215546Sopenharmony_ci   }
453bf215546Sopenharmony_ci
454bf215546Sopenharmony_ci   dri->lookup_image = NULL;
455bf215546Sopenharmony_ci   dri->lookup_user_data = NULL;
456bf215546Sopenharmony_ci
457bf215546Sopenharmony_ci   return 0;
458bf215546Sopenharmony_ci
459bf215546Sopenharmony_cifree_screen:
460bf215546Sopenharmony_ci   dri->core->destroyScreen(dri->screen);
461bf215546Sopenharmony_ci
462bf215546Sopenharmony_ci   return ret;
463bf215546Sopenharmony_ci}
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_cistatic int
466bf215546Sopenharmony_cidri_screen_create_swrast(struct gbm_dri_device *dri)
467bf215546Sopenharmony_ci{
468bf215546Sopenharmony_ci   int ret;
469bf215546Sopenharmony_ci
470bf215546Sopenharmony_ci   dri->driver_name = strdup("swrast");
471bf215546Sopenharmony_ci   if (dri->driver_name == NULL)
472bf215546Sopenharmony_ci      return -1;
473bf215546Sopenharmony_ci
474bf215546Sopenharmony_ci   ret = dri_load_driver_swrast(dri);
475bf215546Sopenharmony_ci   if (ret) {
476bf215546Sopenharmony_ci      fprintf(stderr, "failed to load swrast driver\n");
477bf215546Sopenharmony_ci      return ret;
478bf215546Sopenharmony_ci   }
479bf215546Sopenharmony_ci
480bf215546Sopenharmony_ci   dri->loader_extensions = gbm_dri_screen_extensions;
481bf215546Sopenharmony_ci
482bf215546Sopenharmony_ci   if (dri->swrast == NULL)
483bf215546Sopenharmony_ci      return -1;
484bf215546Sopenharmony_ci
485bf215546Sopenharmony_ci   if (dri->swrast->base.version >= 4) {
486bf215546Sopenharmony_ci      dri->screen = dri->swrast->createNewScreen2(0, dri->loader_extensions,
487bf215546Sopenharmony_ci                                                  dri->driver_extensions,
488bf215546Sopenharmony_ci                                                  &dri->driver_configs, dri);
489bf215546Sopenharmony_ci   } else {
490bf215546Sopenharmony_ci      dri->screen = dri->swrast->createNewScreen(0, dri->loader_extensions,
491bf215546Sopenharmony_ci                                                 &dri->driver_configs, dri);
492bf215546Sopenharmony_ci   }
493bf215546Sopenharmony_ci   if (dri->screen == NULL)
494bf215546Sopenharmony_ci      return -1;
495bf215546Sopenharmony_ci
496bf215546Sopenharmony_ci   dri->lookup_image = NULL;
497bf215546Sopenharmony_ci   dri->lookup_user_data = NULL;
498bf215546Sopenharmony_ci
499bf215546Sopenharmony_ci   return 0;
500bf215546Sopenharmony_ci}
501bf215546Sopenharmony_ci
502bf215546Sopenharmony_cistatic int
503bf215546Sopenharmony_cidri_screen_create(struct gbm_dri_device *dri)
504bf215546Sopenharmony_ci{
505bf215546Sopenharmony_ci   char *driver_name;
506bf215546Sopenharmony_ci
507bf215546Sopenharmony_ci   driver_name = loader_get_driver_for_fd(dri->base.v0.fd);
508bf215546Sopenharmony_ci   if (!driver_name)
509bf215546Sopenharmony_ci      return -1;
510bf215546Sopenharmony_ci
511bf215546Sopenharmony_ci   return dri_screen_create_dri2(dri, driver_name);
512bf215546Sopenharmony_ci}
513bf215546Sopenharmony_ci
514bf215546Sopenharmony_cistatic int
515bf215546Sopenharmony_cidri_screen_create_sw(struct gbm_dri_device *dri)
516bf215546Sopenharmony_ci{
517bf215546Sopenharmony_ci   char *driver_name;
518bf215546Sopenharmony_ci   int ret;
519bf215546Sopenharmony_ci
520bf215546Sopenharmony_ci   driver_name = strdup("zink");
521bf215546Sopenharmony_ci   if (!driver_name)
522bf215546Sopenharmony_ci      return -errno;
523bf215546Sopenharmony_ci
524bf215546Sopenharmony_ci   ret = dri_screen_create_dri2(dri, driver_name);
525bf215546Sopenharmony_ci   if (ret != 0) {
526bf215546Sopenharmony_ci      driver_name = strdup("kms_swrast");
527bf215546Sopenharmony_ci      if (!driver_name)
528bf215546Sopenharmony_ci         return -errno;
529bf215546Sopenharmony_ci
530bf215546Sopenharmony_ci      ret = dri_screen_create_dri2(dri, driver_name);
531bf215546Sopenharmony_ci      if (ret != 0)
532bf215546Sopenharmony_ci         ret = dri_screen_create_swrast(dri);
533bf215546Sopenharmony_ci      if (ret != 0)
534bf215546Sopenharmony_ci         return ret;
535bf215546Sopenharmony_ci   }
536bf215546Sopenharmony_ci
537bf215546Sopenharmony_ci   dri->software = true;
538bf215546Sopenharmony_ci   return 0;
539bf215546Sopenharmony_ci}
540bf215546Sopenharmony_ci
541bf215546Sopenharmony_cistatic const struct gbm_dri_visual gbm_dri_visuals_table[] = {
542bf215546Sopenharmony_ci   {
543bf215546Sopenharmony_ci     GBM_FORMAT_R8, __DRI_IMAGE_FORMAT_R8,
544bf215546Sopenharmony_ci     { 0, -1, -1, -1 },
545bf215546Sopenharmony_ci     { 8, 0, 0, 0 },
546bf215546Sopenharmony_ci   },
547bf215546Sopenharmony_ci   {
548bf215546Sopenharmony_ci     GBM_FORMAT_R16, __DRI_IMAGE_FORMAT_R16,
549bf215546Sopenharmony_ci     { 0, -1, -1, -1 },
550bf215546Sopenharmony_ci     { 16, 0, 0, 0 },
551bf215546Sopenharmony_ci   },
552bf215546Sopenharmony_ci   {
553bf215546Sopenharmony_ci     GBM_FORMAT_GR88, __DRI_IMAGE_FORMAT_GR88,
554bf215546Sopenharmony_ci     { 0, 8, -1, -1 },
555bf215546Sopenharmony_ci     { 8, 8, 0, 0 },
556bf215546Sopenharmony_ci   },
557bf215546Sopenharmony_ci   {
558bf215546Sopenharmony_ci     GBM_FORMAT_GR1616, __DRI_IMAGE_FORMAT_GR1616,
559bf215546Sopenharmony_ci     { 0, 16, -1, -1 },
560bf215546Sopenharmony_ci     { 16, 16, 0, 0 },
561bf215546Sopenharmony_ci   },
562bf215546Sopenharmony_ci   {
563bf215546Sopenharmony_ci     GBM_FORMAT_ARGB1555, __DRI_IMAGE_FORMAT_ARGB1555,
564bf215546Sopenharmony_ci     { 10, 5, 0, 11 },
565bf215546Sopenharmony_ci     { 5, 5, 5, 1 },
566bf215546Sopenharmony_ci   },
567bf215546Sopenharmony_ci   {
568bf215546Sopenharmony_ci     GBM_FORMAT_RGB565, __DRI_IMAGE_FORMAT_RGB565,
569bf215546Sopenharmony_ci     { 11, 5, 0, -1 },
570bf215546Sopenharmony_ci     { 5, 6, 5, 0 },
571bf215546Sopenharmony_ci   },
572bf215546Sopenharmony_ci   {
573bf215546Sopenharmony_ci     GBM_FORMAT_XRGB8888, __DRI_IMAGE_FORMAT_XRGB8888,
574bf215546Sopenharmony_ci     { 16, 8, 0, -1 },
575bf215546Sopenharmony_ci     { 8, 8, 8, 0 },
576bf215546Sopenharmony_ci   },
577bf215546Sopenharmony_ci   {
578bf215546Sopenharmony_ci     GBM_FORMAT_ARGB8888, __DRI_IMAGE_FORMAT_ARGB8888,
579bf215546Sopenharmony_ci     { 16, 8, 0, 24 },
580bf215546Sopenharmony_ci     { 8, 8, 8, 8 },
581bf215546Sopenharmony_ci   },
582bf215546Sopenharmony_ci   {
583bf215546Sopenharmony_ci     GBM_FORMAT_XBGR8888, __DRI_IMAGE_FORMAT_XBGR8888,
584bf215546Sopenharmony_ci     { 0, 8, 16, -1 },
585bf215546Sopenharmony_ci     { 8, 8, 8, 0 },
586bf215546Sopenharmony_ci   },
587bf215546Sopenharmony_ci   {
588bf215546Sopenharmony_ci     GBM_FORMAT_ABGR8888, __DRI_IMAGE_FORMAT_ABGR8888,
589bf215546Sopenharmony_ci     { 0, 8, 16, 24 },
590bf215546Sopenharmony_ci     { 8, 8, 8, 8 },
591bf215546Sopenharmony_ci   },
592bf215546Sopenharmony_ci   {
593bf215546Sopenharmony_ci     GBM_FORMAT_XRGB2101010, __DRI_IMAGE_FORMAT_XRGB2101010,
594bf215546Sopenharmony_ci     { 20, 10, 0, -1 },
595bf215546Sopenharmony_ci     { 10, 10, 10, 0 },
596bf215546Sopenharmony_ci   },
597bf215546Sopenharmony_ci   {
598bf215546Sopenharmony_ci     GBM_FORMAT_ARGB2101010, __DRI_IMAGE_FORMAT_ARGB2101010,
599bf215546Sopenharmony_ci     { 20, 10, 0, 30 },
600bf215546Sopenharmony_ci     { 10, 10, 10, 2 },
601bf215546Sopenharmony_ci   },
602bf215546Sopenharmony_ci   {
603bf215546Sopenharmony_ci     GBM_FORMAT_XBGR2101010, __DRI_IMAGE_FORMAT_XBGR2101010,
604bf215546Sopenharmony_ci     { 0, 10, 20, -1 },
605bf215546Sopenharmony_ci     { 10, 10, 10, 0 },
606bf215546Sopenharmony_ci   },
607bf215546Sopenharmony_ci   {
608bf215546Sopenharmony_ci     GBM_FORMAT_ABGR2101010, __DRI_IMAGE_FORMAT_ABGR2101010,
609bf215546Sopenharmony_ci     { 0, 10, 20, 30 },
610bf215546Sopenharmony_ci     { 10, 10, 10, 2 },
611bf215546Sopenharmony_ci   },
612bf215546Sopenharmony_ci   {
613bf215546Sopenharmony_ci     GBM_FORMAT_XBGR16161616, __DRI_IMAGE_FORMAT_XBGR16161616,
614bf215546Sopenharmony_ci     { 0, 16, 32, -1 },
615bf215546Sopenharmony_ci     { 16, 16, 16, 0 },
616bf215546Sopenharmony_ci   },
617bf215546Sopenharmony_ci   {
618bf215546Sopenharmony_ci     GBM_FORMAT_ABGR16161616, __DRI_IMAGE_FORMAT_ABGR16161616,
619bf215546Sopenharmony_ci     { 0, 16, 32, 48 },
620bf215546Sopenharmony_ci     { 16, 16, 16, 16 },
621bf215546Sopenharmony_ci   },
622bf215546Sopenharmony_ci   {
623bf215546Sopenharmony_ci     GBM_FORMAT_XBGR16161616F, __DRI_IMAGE_FORMAT_XBGR16161616F,
624bf215546Sopenharmony_ci     { 0, 16, 32, -1 },
625bf215546Sopenharmony_ci     { 16, 16, 16, 0 },
626bf215546Sopenharmony_ci     true,
627bf215546Sopenharmony_ci   },
628bf215546Sopenharmony_ci   {
629bf215546Sopenharmony_ci     GBM_FORMAT_ABGR16161616F, __DRI_IMAGE_FORMAT_ABGR16161616F,
630bf215546Sopenharmony_ci     { 0, 16, 32, 48 },
631bf215546Sopenharmony_ci     { 16, 16, 16, 16 },
632bf215546Sopenharmony_ci     true,
633bf215546Sopenharmony_ci   },
634bf215546Sopenharmony_ci};
635bf215546Sopenharmony_ci
636bf215546Sopenharmony_cistatic int
637bf215546Sopenharmony_cigbm_format_to_dri_format(uint32_t gbm_format)
638bf215546Sopenharmony_ci{
639bf215546Sopenharmony_ci   gbm_format = gbm_core.v0.format_canonicalize(gbm_format);
640bf215546Sopenharmony_ci   for (size_t i = 0; i < ARRAY_SIZE(gbm_dri_visuals_table); i++) {
641bf215546Sopenharmony_ci      if (gbm_dri_visuals_table[i].gbm_format == gbm_format)
642bf215546Sopenharmony_ci         return gbm_dri_visuals_table[i].dri_image_format;
643bf215546Sopenharmony_ci   }
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_ci   return 0;
646bf215546Sopenharmony_ci}
647bf215546Sopenharmony_ci
648bf215546Sopenharmony_cistatic uint32_t
649bf215546Sopenharmony_cigbm_dri_to_gbm_format(int dri_format)
650bf215546Sopenharmony_ci{
651bf215546Sopenharmony_ci   for (size_t i = 0; i < ARRAY_SIZE(gbm_dri_visuals_table); i++) {
652bf215546Sopenharmony_ci      if (gbm_dri_visuals_table[i].dri_image_format == dri_format)
653bf215546Sopenharmony_ci         return gbm_dri_visuals_table[i].gbm_format;
654bf215546Sopenharmony_ci   }
655bf215546Sopenharmony_ci
656bf215546Sopenharmony_ci   return 0;
657bf215546Sopenharmony_ci}
658bf215546Sopenharmony_ci
659bf215546Sopenharmony_cistatic int
660bf215546Sopenharmony_cigbm_dri_is_format_supported(struct gbm_device *gbm,
661bf215546Sopenharmony_ci                            uint32_t format,
662bf215546Sopenharmony_ci                            uint32_t usage)
663bf215546Sopenharmony_ci{
664bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(gbm);
665bf215546Sopenharmony_ci   int count;
666bf215546Sopenharmony_ci
667bf215546Sopenharmony_ci   if ((usage & GBM_BO_USE_CURSOR) && (usage & GBM_BO_USE_RENDERING))
668bf215546Sopenharmony_ci      return 0;
669bf215546Sopenharmony_ci
670bf215546Sopenharmony_ci   format = gbm_core.v0.format_canonicalize(format);
671bf215546Sopenharmony_ci   if (gbm_format_to_dri_format(format) == 0)
672bf215546Sopenharmony_ci      return 0;
673bf215546Sopenharmony_ci
674bf215546Sopenharmony_ci   /* If there is no query, fall back to the small table which was originally
675bf215546Sopenharmony_ci    * here. */
676bf215546Sopenharmony_ci   if (dri->image->base.version <= 15 || !dri->image->queryDmaBufModifiers) {
677bf215546Sopenharmony_ci      switch (format) {
678bf215546Sopenharmony_ci      case GBM_FORMAT_XRGB8888:
679bf215546Sopenharmony_ci      case GBM_FORMAT_ARGB8888:
680bf215546Sopenharmony_ci      case GBM_FORMAT_XBGR8888:
681bf215546Sopenharmony_ci         return 1;
682bf215546Sopenharmony_ci      default:
683bf215546Sopenharmony_ci         return 0;
684bf215546Sopenharmony_ci      }
685bf215546Sopenharmony_ci   }
686bf215546Sopenharmony_ci
687bf215546Sopenharmony_ci   /* This returns false if the format isn't supported */
688bf215546Sopenharmony_ci   if (!dri->image->queryDmaBufModifiers(dri->screen, format, 0, NULL, NULL,
689bf215546Sopenharmony_ci                                         &count))
690bf215546Sopenharmony_ci      return 0;
691bf215546Sopenharmony_ci
692bf215546Sopenharmony_ci   return 1;
693bf215546Sopenharmony_ci}
694bf215546Sopenharmony_ci
695bf215546Sopenharmony_cistatic int
696bf215546Sopenharmony_cigbm_dri_get_format_modifier_plane_count(struct gbm_device *gbm,
697bf215546Sopenharmony_ci                                        uint32_t format,
698bf215546Sopenharmony_ci                                        uint64_t modifier)
699bf215546Sopenharmony_ci{
700bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(gbm);
701bf215546Sopenharmony_ci   uint64_t plane_count;
702bf215546Sopenharmony_ci
703bf215546Sopenharmony_ci   if (dri->image->base.version < 16 ||
704bf215546Sopenharmony_ci       !dri->image->queryDmaBufFormatModifierAttribs)
705bf215546Sopenharmony_ci      return -1;
706bf215546Sopenharmony_ci
707bf215546Sopenharmony_ci   format = gbm_core.v0.format_canonicalize(format);
708bf215546Sopenharmony_ci   if (gbm_format_to_dri_format(format) == 0)
709bf215546Sopenharmony_ci      return -1;
710bf215546Sopenharmony_ci
711bf215546Sopenharmony_ci   if (!dri->image->queryDmaBufFormatModifierAttribs(
712bf215546Sopenharmony_ci         dri->screen, format, modifier,
713bf215546Sopenharmony_ci         __DRI_IMAGE_FORMAT_MODIFIER_ATTRIB_PLANE_COUNT, &plane_count))
714bf215546Sopenharmony_ci      return -1;
715bf215546Sopenharmony_ci
716bf215546Sopenharmony_ci   return plane_count;
717bf215546Sopenharmony_ci}
718bf215546Sopenharmony_ci
719bf215546Sopenharmony_cistatic int
720bf215546Sopenharmony_cigbm_dri_bo_write(struct gbm_bo *_bo, const void *buf, size_t count)
721bf215546Sopenharmony_ci{
722bf215546Sopenharmony_ci   struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
723bf215546Sopenharmony_ci
724bf215546Sopenharmony_ci   if (bo->image != NULL) {
725bf215546Sopenharmony_ci      errno = EINVAL;
726bf215546Sopenharmony_ci      return -1;
727bf215546Sopenharmony_ci   }
728bf215546Sopenharmony_ci
729bf215546Sopenharmony_ci   memcpy(bo->map, buf, count);
730bf215546Sopenharmony_ci
731bf215546Sopenharmony_ci   return 0;
732bf215546Sopenharmony_ci}
733bf215546Sopenharmony_ci
734bf215546Sopenharmony_cistatic int
735bf215546Sopenharmony_cigbm_dri_bo_get_fd(struct gbm_bo *_bo)
736bf215546Sopenharmony_ci{
737bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
738bf215546Sopenharmony_ci   struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
739bf215546Sopenharmony_ci   int fd;
740bf215546Sopenharmony_ci
741bf215546Sopenharmony_ci   if (bo->image == NULL)
742bf215546Sopenharmony_ci      return -1;
743bf215546Sopenharmony_ci
744bf215546Sopenharmony_ci   if (!dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_FD, &fd))
745bf215546Sopenharmony_ci      return -1;
746bf215546Sopenharmony_ci
747bf215546Sopenharmony_ci   return fd;
748bf215546Sopenharmony_ci}
749bf215546Sopenharmony_ci
750bf215546Sopenharmony_cistatic int
751bf215546Sopenharmony_ciget_number_planes(struct gbm_dri_device *dri, __DRIimage *image)
752bf215546Sopenharmony_ci{
753bf215546Sopenharmony_ci   int num_planes = 0;
754bf215546Sopenharmony_ci
755bf215546Sopenharmony_ci   /* Dumb buffers are single-plane only. */
756bf215546Sopenharmony_ci   if (!image)
757bf215546Sopenharmony_ci      return 1;
758bf215546Sopenharmony_ci
759bf215546Sopenharmony_ci   dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_NUM_PLANES, &num_planes);
760bf215546Sopenharmony_ci
761bf215546Sopenharmony_ci   if (num_planes <= 0)
762bf215546Sopenharmony_ci      num_planes = 1;
763bf215546Sopenharmony_ci
764bf215546Sopenharmony_ci   return num_planes;
765bf215546Sopenharmony_ci}
766bf215546Sopenharmony_ci
767bf215546Sopenharmony_cistatic int
768bf215546Sopenharmony_cigbm_dri_bo_get_planes(struct gbm_bo *_bo)
769bf215546Sopenharmony_ci{
770bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
771bf215546Sopenharmony_ci   struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
772bf215546Sopenharmony_ci
773bf215546Sopenharmony_ci   return get_number_planes(dri, bo->image);
774bf215546Sopenharmony_ci}
775bf215546Sopenharmony_ci
776bf215546Sopenharmony_cistatic union gbm_bo_handle
777bf215546Sopenharmony_cigbm_dri_bo_get_handle_for_plane(struct gbm_bo *_bo, int plane)
778bf215546Sopenharmony_ci{
779bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
780bf215546Sopenharmony_ci   struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
781bf215546Sopenharmony_ci   union gbm_bo_handle ret;
782bf215546Sopenharmony_ci   ret.s32 = -1;
783bf215546Sopenharmony_ci
784bf215546Sopenharmony_ci   if (!dri->image || dri->image->base.version < 13 || !dri->image->fromPlanar) {
785bf215546Sopenharmony_ci      /* Preserve legacy behavior if plane is 0 */
786bf215546Sopenharmony_ci      if (plane == 0) {
787bf215546Sopenharmony_ci         /* NOTE: return _bo->handle, *NOT* bo->handle which is invalid at this point */
788bf215546Sopenharmony_ci         return _bo->v0.handle;
789bf215546Sopenharmony_ci      }
790bf215546Sopenharmony_ci
791bf215546Sopenharmony_ci      errno = ENOSYS;
792bf215546Sopenharmony_ci      return ret;
793bf215546Sopenharmony_ci   }
794bf215546Sopenharmony_ci
795bf215546Sopenharmony_ci   if (plane >= get_number_planes(dri, bo->image)) {
796bf215546Sopenharmony_ci      errno = EINVAL;
797bf215546Sopenharmony_ci      return ret;
798bf215546Sopenharmony_ci   }
799bf215546Sopenharmony_ci
800bf215546Sopenharmony_ci   /* dumb BOs can only utilize non-planar formats */
801bf215546Sopenharmony_ci   if (!bo->image) {
802bf215546Sopenharmony_ci      assert(plane == 0);
803bf215546Sopenharmony_ci      ret.s32 = bo->handle;
804bf215546Sopenharmony_ci      return ret;
805bf215546Sopenharmony_ci   }
806bf215546Sopenharmony_ci
807bf215546Sopenharmony_ci   __DRIimage *image = dri->image->fromPlanar(bo->image, plane, NULL);
808bf215546Sopenharmony_ci   if (image) {
809bf215546Sopenharmony_ci      dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_HANDLE, &ret.s32);
810bf215546Sopenharmony_ci      dri->image->destroyImage(image);
811bf215546Sopenharmony_ci   } else {
812bf215546Sopenharmony_ci      assert(plane == 0);
813bf215546Sopenharmony_ci      dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE, &ret.s32);
814bf215546Sopenharmony_ci   }
815bf215546Sopenharmony_ci
816bf215546Sopenharmony_ci   return ret;
817bf215546Sopenharmony_ci}
818bf215546Sopenharmony_ci
819bf215546Sopenharmony_cistatic int
820bf215546Sopenharmony_cigbm_dri_bo_get_plane_fd(struct gbm_bo *_bo, int plane)
821bf215546Sopenharmony_ci{
822bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
823bf215546Sopenharmony_ci   struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
824bf215546Sopenharmony_ci   int fd = -1;
825bf215546Sopenharmony_ci
826bf215546Sopenharmony_ci   if (!dri->image || dri->image->base.version < 13 || !dri->image->fromPlanar) {
827bf215546Sopenharmony_ci      /* Preserve legacy behavior if plane is 0 */
828bf215546Sopenharmony_ci      if (plane == 0)
829bf215546Sopenharmony_ci         return gbm_dri_bo_get_fd(_bo);
830bf215546Sopenharmony_ci
831bf215546Sopenharmony_ci      errno = ENOSYS;
832bf215546Sopenharmony_ci      return -1;
833bf215546Sopenharmony_ci   }
834bf215546Sopenharmony_ci
835bf215546Sopenharmony_ci   /* dumb BOs can only utilize non-planar formats */
836bf215546Sopenharmony_ci   if (!bo->image) {
837bf215546Sopenharmony_ci      errno = EINVAL;
838bf215546Sopenharmony_ci      return -1;
839bf215546Sopenharmony_ci   }
840bf215546Sopenharmony_ci
841bf215546Sopenharmony_ci   if (plane >= get_number_planes(dri, bo->image)) {
842bf215546Sopenharmony_ci      errno = EINVAL;
843bf215546Sopenharmony_ci      return -1;
844bf215546Sopenharmony_ci   }
845bf215546Sopenharmony_ci
846bf215546Sopenharmony_ci   __DRIimage *image = dri->image->fromPlanar(bo->image, plane, NULL);
847bf215546Sopenharmony_ci   if (image) {
848bf215546Sopenharmony_ci      dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_FD, &fd);
849bf215546Sopenharmony_ci      dri->image->destroyImage(image);
850bf215546Sopenharmony_ci   } else {
851bf215546Sopenharmony_ci      assert(plane == 0);
852bf215546Sopenharmony_ci      dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_FD, &fd);
853bf215546Sopenharmony_ci   }
854bf215546Sopenharmony_ci
855bf215546Sopenharmony_ci   return fd;
856bf215546Sopenharmony_ci}
857bf215546Sopenharmony_ci
858bf215546Sopenharmony_cistatic uint32_t
859bf215546Sopenharmony_cigbm_dri_bo_get_stride(struct gbm_bo *_bo, int plane)
860bf215546Sopenharmony_ci{
861bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
862bf215546Sopenharmony_ci   struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
863bf215546Sopenharmony_ci   __DRIimage *image;
864bf215546Sopenharmony_ci   int stride = 0;
865bf215546Sopenharmony_ci
866bf215546Sopenharmony_ci   if (!dri->image || dri->image->base.version < 11 || !dri->image->fromPlanar) {
867bf215546Sopenharmony_ci      /* Preserve legacy behavior if plane is 0 */
868bf215546Sopenharmony_ci      if (plane == 0)
869bf215546Sopenharmony_ci         return _bo->v0.stride;
870bf215546Sopenharmony_ci
871bf215546Sopenharmony_ci      errno = ENOSYS;
872bf215546Sopenharmony_ci      return 0;
873bf215546Sopenharmony_ci   }
874bf215546Sopenharmony_ci
875bf215546Sopenharmony_ci   if (plane >= get_number_planes(dri, bo->image)) {
876bf215546Sopenharmony_ci      errno = EINVAL;
877bf215546Sopenharmony_ci      return 0;
878bf215546Sopenharmony_ci   }
879bf215546Sopenharmony_ci
880bf215546Sopenharmony_ci   if (bo->image == NULL) {
881bf215546Sopenharmony_ci      assert(plane == 0);
882bf215546Sopenharmony_ci      return _bo->v0.stride;
883bf215546Sopenharmony_ci   }
884bf215546Sopenharmony_ci
885bf215546Sopenharmony_ci   image = dri->image->fromPlanar(bo->image, plane, NULL);
886bf215546Sopenharmony_ci   if (image) {
887bf215546Sopenharmony_ci      dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride);
888bf215546Sopenharmony_ci      dri->image->destroyImage(image);
889bf215546Sopenharmony_ci   } else {
890bf215546Sopenharmony_ci      assert(plane == 0);
891bf215546Sopenharmony_ci      dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, &stride);
892bf215546Sopenharmony_ci   }
893bf215546Sopenharmony_ci
894bf215546Sopenharmony_ci   return (uint32_t)stride;
895bf215546Sopenharmony_ci}
896bf215546Sopenharmony_ci
897bf215546Sopenharmony_cistatic uint32_t
898bf215546Sopenharmony_cigbm_dri_bo_get_offset(struct gbm_bo *_bo, int plane)
899bf215546Sopenharmony_ci{
900bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
901bf215546Sopenharmony_ci   struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
902bf215546Sopenharmony_ci   int offset = 0;
903bf215546Sopenharmony_ci
904bf215546Sopenharmony_ci   /* These error cases do not actually return an error code, as the user
905bf215546Sopenharmony_ci    * will also fail to obtain the handle/FD from the BO. In that case, the
906bf215546Sopenharmony_ci    * offset is irrelevant, as they have no buffer to offset into, so
907bf215546Sopenharmony_ci    * returning 0 is harmless.
908bf215546Sopenharmony_ci    */
909bf215546Sopenharmony_ci   if (!dri->image || dri->image->base.version < 13 || !dri->image->fromPlanar)
910bf215546Sopenharmony_ci      return 0;
911bf215546Sopenharmony_ci
912bf215546Sopenharmony_ci   if (plane >= get_number_planes(dri, bo->image))
913bf215546Sopenharmony_ci      return 0;
914bf215546Sopenharmony_ci
915bf215546Sopenharmony_ci    /* Dumb images have no offset */
916bf215546Sopenharmony_ci   if (bo->image == NULL) {
917bf215546Sopenharmony_ci      assert(plane == 0);
918bf215546Sopenharmony_ci      return 0;
919bf215546Sopenharmony_ci   }
920bf215546Sopenharmony_ci
921bf215546Sopenharmony_ci   __DRIimage *image = dri->image->fromPlanar(bo->image, plane, NULL);
922bf215546Sopenharmony_ci   if (image) {
923bf215546Sopenharmony_ci      dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_OFFSET, &offset);
924bf215546Sopenharmony_ci      dri->image->destroyImage(image);
925bf215546Sopenharmony_ci   } else {
926bf215546Sopenharmony_ci      assert(plane == 0);
927bf215546Sopenharmony_ci      dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_OFFSET, &offset);
928bf215546Sopenharmony_ci   }
929bf215546Sopenharmony_ci
930bf215546Sopenharmony_ci   return (uint32_t)offset;
931bf215546Sopenharmony_ci}
932bf215546Sopenharmony_ci
933bf215546Sopenharmony_cistatic uint64_t
934bf215546Sopenharmony_cigbm_dri_bo_get_modifier(struct gbm_bo *_bo)
935bf215546Sopenharmony_ci{
936bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
937bf215546Sopenharmony_ci   struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
938bf215546Sopenharmony_ci
939bf215546Sopenharmony_ci   if (!dri->image || dri->image->base.version < 14) {
940bf215546Sopenharmony_ci      errno = ENOSYS;
941bf215546Sopenharmony_ci      return DRM_FORMAT_MOD_INVALID;
942bf215546Sopenharmony_ci   }
943bf215546Sopenharmony_ci
944bf215546Sopenharmony_ci   /* Dumb buffers have no modifiers */
945bf215546Sopenharmony_ci   if (!bo->image)
946bf215546Sopenharmony_ci      return DRM_FORMAT_MOD_LINEAR;
947bf215546Sopenharmony_ci
948bf215546Sopenharmony_ci   uint64_t ret = 0;
949bf215546Sopenharmony_ci   int mod;
950bf215546Sopenharmony_ci   if (!dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_MODIFIER_UPPER,
951bf215546Sopenharmony_ci                               &mod))
952bf215546Sopenharmony_ci      return DRM_FORMAT_MOD_INVALID;
953bf215546Sopenharmony_ci
954bf215546Sopenharmony_ci   ret = (uint64_t)mod << 32;
955bf215546Sopenharmony_ci
956bf215546Sopenharmony_ci   if (!dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_MODIFIER_LOWER,
957bf215546Sopenharmony_ci                               &mod))
958bf215546Sopenharmony_ci      return DRM_FORMAT_MOD_INVALID;
959bf215546Sopenharmony_ci
960bf215546Sopenharmony_ci   ret |= (uint64_t)(mod & 0xffffffff);
961bf215546Sopenharmony_ci
962bf215546Sopenharmony_ci   return ret;
963bf215546Sopenharmony_ci}
964bf215546Sopenharmony_ci
965bf215546Sopenharmony_cistatic void
966bf215546Sopenharmony_cigbm_dri_bo_destroy(struct gbm_bo *_bo)
967bf215546Sopenharmony_ci{
968bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
969bf215546Sopenharmony_ci   struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
970bf215546Sopenharmony_ci   struct drm_mode_destroy_dumb arg;
971bf215546Sopenharmony_ci
972bf215546Sopenharmony_ci   if (bo->image != NULL) {
973bf215546Sopenharmony_ci      dri->image->destroyImage(bo->image);
974bf215546Sopenharmony_ci   } else {
975bf215546Sopenharmony_ci      gbm_dri_bo_unmap_dumb(bo);
976bf215546Sopenharmony_ci      memset(&arg, 0, sizeof(arg));
977bf215546Sopenharmony_ci      arg.handle = bo->handle;
978bf215546Sopenharmony_ci      drmIoctl(dri->base.v0.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg);
979bf215546Sopenharmony_ci   }
980bf215546Sopenharmony_ci
981bf215546Sopenharmony_ci   free(bo);
982bf215546Sopenharmony_ci}
983bf215546Sopenharmony_ci
984bf215546Sopenharmony_cistatic struct gbm_bo *
985bf215546Sopenharmony_cigbm_dri_bo_import(struct gbm_device *gbm,
986bf215546Sopenharmony_ci                  uint32_t type, void *buffer, uint32_t usage)
987bf215546Sopenharmony_ci{
988bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(gbm);
989bf215546Sopenharmony_ci   struct gbm_dri_bo *bo;
990bf215546Sopenharmony_ci   __DRIimage *image;
991bf215546Sopenharmony_ci   unsigned dri_use = 0;
992bf215546Sopenharmony_ci   int gbm_format;
993bf215546Sopenharmony_ci
994bf215546Sopenharmony_ci   /* Required for query image WIDTH & HEIGHT */
995bf215546Sopenharmony_ci   if (dri->image == NULL || dri->image->base.version < 4) {
996bf215546Sopenharmony_ci      errno = ENOSYS;
997bf215546Sopenharmony_ci      return NULL;
998bf215546Sopenharmony_ci   }
999bf215546Sopenharmony_ci
1000bf215546Sopenharmony_ci   switch (type) {
1001bf215546Sopenharmony_ci#if HAVE_WAYLAND_PLATFORM
1002bf215546Sopenharmony_ci   case GBM_BO_IMPORT_WL_BUFFER:
1003bf215546Sopenharmony_ci   {
1004bf215546Sopenharmony_ci      struct wl_drm_buffer *wb;
1005bf215546Sopenharmony_ci
1006bf215546Sopenharmony_ci      if (!dri->wl_drm) {
1007bf215546Sopenharmony_ci         errno = EINVAL;
1008bf215546Sopenharmony_ci         return NULL;
1009bf215546Sopenharmony_ci      }
1010bf215546Sopenharmony_ci
1011bf215546Sopenharmony_ci      wb = wayland_drm_buffer_get(dri->wl_drm, (struct wl_resource *) buffer);
1012bf215546Sopenharmony_ci      if (!wb) {
1013bf215546Sopenharmony_ci         errno = EINVAL;
1014bf215546Sopenharmony_ci         return NULL;
1015bf215546Sopenharmony_ci      }
1016bf215546Sopenharmony_ci
1017bf215546Sopenharmony_ci      image = dri->image->dupImage(wb->driver_buffer, NULL);
1018bf215546Sopenharmony_ci
1019bf215546Sopenharmony_ci      /* GBM_FORMAT_* is identical to WL_DRM_FORMAT_*, so no conversion
1020bf215546Sopenharmony_ci       * required. */
1021bf215546Sopenharmony_ci      gbm_format = wb->format;
1022bf215546Sopenharmony_ci      break;
1023bf215546Sopenharmony_ci   }
1024bf215546Sopenharmony_ci#endif
1025bf215546Sopenharmony_ci
1026bf215546Sopenharmony_ci   case GBM_BO_IMPORT_EGL_IMAGE:
1027bf215546Sopenharmony_ci   {
1028bf215546Sopenharmony_ci      int dri_format;
1029bf215546Sopenharmony_ci      if (dri->lookup_image == NULL) {
1030bf215546Sopenharmony_ci         errno = EINVAL;
1031bf215546Sopenharmony_ci         return NULL;
1032bf215546Sopenharmony_ci      }
1033bf215546Sopenharmony_ci
1034bf215546Sopenharmony_ci      image = dri->lookup_image(dri->screen, buffer, dri->lookup_user_data);
1035bf215546Sopenharmony_ci      image = dri->image->dupImage(image, NULL);
1036bf215546Sopenharmony_ci      dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &dri_format);
1037bf215546Sopenharmony_ci      gbm_format = gbm_dri_to_gbm_format(dri_format);
1038bf215546Sopenharmony_ci      if (gbm_format == 0) {
1039bf215546Sopenharmony_ci         errno = EINVAL;
1040bf215546Sopenharmony_ci         dri->image->destroyImage(image);
1041bf215546Sopenharmony_ci         return NULL;
1042bf215546Sopenharmony_ci      }
1043bf215546Sopenharmony_ci      break;
1044bf215546Sopenharmony_ci   }
1045bf215546Sopenharmony_ci
1046bf215546Sopenharmony_ci   case GBM_BO_IMPORT_FD:
1047bf215546Sopenharmony_ci   {
1048bf215546Sopenharmony_ci      struct gbm_import_fd_data *fd_data = buffer;
1049bf215546Sopenharmony_ci      int stride = fd_data->stride, offset = 0;
1050bf215546Sopenharmony_ci      int fourcc;
1051bf215546Sopenharmony_ci
1052bf215546Sopenharmony_ci      /* GBM's GBM_FORMAT_* tokens are a strict superset of the DRI FourCC
1053bf215546Sopenharmony_ci       * tokens accepted by createImageFromFds, except for not supporting
1054bf215546Sopenharmony_ci       * the sARGB format. */
1055bf215546Sopenharmony_ci      fourcc = gbm_core.v0.format_canonicalize(fd_data->format);
1056bf215546Sopenharmony_ci
1057bf215546Sopenharmony_ci      image = dri->image->createImageFromFds(dri->screen,
1058bf215546Sopenharmony_ci                                             fd_data->width,
1059bf215546Sopenharmony_ci                                             fd_data->height,
1060bf215546Sopenharmony_ci                                             fourcc,
1061bf215546Sopenharmony_ci                                             &fd_data->fd, 1,
1062bf215546Sopenharmony_ci                                             &stride, &offset,
1063bf215546Sopenharmony_ci                                             NULL);
1064bf215546Sopenharmony_ci      if (image == NULL) {
1065bf215546Sopenharmony_ci         errno = EINVAL;
1066bf215546Sopenharmony_ci         return NULL;
1067bf215546Sopenharmony_ci      }
1068bf215546Sopenharmony_ci      gbm_format = fd_data->format;
1069bf215546Sopenharmony_ci      break;
1070bf215546Sopenharmony_ci   }
1071bf215546Sopenharmony_ci
1072bf215546Sopenharmony_ci   case GBM_BO_IMPORT_FD_MODIFIER:
1073bf215546Sopenharmony_ci   {
1074bf215546Sopenharmony_ci      struct gbm_import_fd_modifier_data *fd_data = buffer;
1075bf215546Sopenharmony_ci      unsigned int error;
1076bf215546Sopenharmony_ci      int fourcc;
1077bf215546Sopenharmony_ci
1078bf215546Sopenharmony_ci      /* Import with modifier requires createImageFromDmaBufs2 */
1079bf215546Sopenharmony_ci      if (dri->image == NULL || dri->image->base.version < 15 ||
1080bf215546Sopenharmony_ci          dri->image->createImageFromDmaBufs2 == NULL) {
1081bf215546Sopenharmony_ci         errno = ENOSYS;
1082bf215546Sopenharmony_ci         return NULL;
1083bf215546Sopenharmony_ci      }
1084bf215546Sopenharmony_ci
1085bf215546Sopenharmony_ci      /* GBM's GBM_FORMAT_* tokens are a strict superset of the DRI FourCC
1086bf215546Sopenharmony_ci       * tokens accepted by createImageFromDmaBufs2, except for not supporting
1087bf215546Sopenharmony_ci       * the sARGB format. */
1088bf215546Sopenharmony_ci      fourcc = gbm_core.v0.format_canonicalize(fd_data->format);
1089bf215546Sopenharmony_ci
1090bf215546Sopenharmony_ci      image = dri->image->createImageFromDmaBufs2(dri->screen, fd_data->width,
1091bf215546Sopenharmony_ci                                                  fd_data->height, fourcc,
1092bf215546Sopenharmony_ci                                                  fd_data->modifier,
1093bf215546Sopenharmony_ci                                                  fd_data->fds,
1094bf215546Sopenharmony_ci                                                  fd_data->num_fds,
1095bf215546Sopenharmony_ci                                                  fd_data->strides,
1096bf215546Sopenharmony_ci                                                  fd_data->offsets,
1097bf215546Sopenharmony_ci                                                  0, 0, 0, 0,
1098bf215546Sopenharmony_ci                                                  &error, NULL);
1099bf215546Sopenharmony_ci      if (image == NULL) {
1100bf215546Sopenharmony_ci         errno = ENOSYS;
1101bf215546Sopenharmony_ci         return NULL;
1102bf215546Sopenharmony_ci      }
1103bf215546Sopenharmony_ci
1104bf215546Sopenharmony_ci      gbm_format = fourcc;
1105bf215546Sopenharmony_ci      break;
1106bf215546Sopenharmony_ci   }
1107bf215546Sopenharmony_ci
1108bf215546Sopenharmony_ci   default:
1109bf215546Sopenharmony_ci      errno = ENOSYS;
1110bf215546Sopenharmony_ci      return NULL;
1111bf215546Sopenharmony_ci   }
1112bf215546Sopenharmony_ci
1113bf215546Sopenharmony_ci
1114bf215546Sopenharmony_ci   bo = calloc(1, sizeof *bo);
1115bf215546Sopenharmony_ci   if (bo == NULL) {
1116bf215546Sopenharmony_ci      dri->image->destroyImage(image);
1117bf215546Sopenharmony_ci      return NULL;
1118bf215546Sopenharmony_ci   }
1119bf215546Sopenharmony_ci
1120bf215546Sopenharmony_ci   bo->image = image;
1121bf215546Sopenharmony_ci
1122bf215546Sopenharmony_ci   if (usage & GBM_BO_USE_SCANOUT)
1123bf215546Sopenharmony_ci      dri_use |= __DRI_IMAGE_USE_SCANOUT;
1124bf215546Sopenharmony_ci   if (usage & GBM_BO_USE_CURSOR)
1125bf215546Sopenharmony_ci      dri_use |= __DRI_IMAGE_USE_CURSOR;
1126bf215546Sopenharmony_ci   if (dri->image->base.version >= 2 &&
1127bf215546Sopenharmony_ci       !dri->image->validateUsage(bo->image, dri_use)) {
1128bf215546Sopenharmony_ci      errno = EINVAL;
1129bf215546Sopenharmony_ci      dri->image->destroyImage(bo->image);
1130bf215546Sopenharmony_ci      free(bo);
1131bf215546Sopenharmony_ci      return NULL;
1132bf215546Sopenharmony_ci   }
1133bf215546Sopenharmony_ci
1134bf215546Sopenharmony_ci   bo->base.gbm = gbm;
1135bf215546Sopenharmony_ci   bo->base.v0.format = gbm_format;
1136bf215546Sopenharmony_ci
1137bf215546Sopenharmony_ci   dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_WIDTH,
1138bf215546Sopenharmony_ci                          (int*)&bo->base.v0.width);
1139bf215546Sopenharmony_ci   dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HEIGHT,
1140bf215546Sopenharmony_ci                          (int*)&bo->base.v0.height);
1141bf215546Sopenharmony_ci   dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE,
1142bf215546Sopenharmony_ci                          (int*)&bo->base.v0.stride);
1143bf215546Sopenharmony_ci   dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE,
1144bf215546Sopenharmony_ci                          &bo->base.v0.handle.s32);
1145bf215546Sopenharmony_ci
1146bf215546Sopenharmony_ci   return &bo->base;
1147bf215546Sopenharmony_ci}
1148bf215546Sopenharmony_ci
1149bf215546Sopenharmony_cistatic struct gbm_bo *
1150bf215546Sopenharmony_cicreate_dumb(struct gbm_device *gbm,
1151bf215546Sopenharmony_ci                  uint32_t width, uint32_t height,
1152bf215546Sopenharmony_ci                  uint32_t format, uint32_t usage)
1153bf215546Sopenharmony_ci{
1154bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(gbm);
1155bf215546Sopenharmony_ci   struct drm_mode_create_dumb create_arg;
1156bf215546Sopenharmony_ci   struct gbm_dri_bo *bo;
1157bf215546Sopenharmony_ci   struct drm_mode_destroy_dumb destroy_arg;
1158bf215546Sopenharmony_ci   int ret;
1159bf215546Sopenharmony_ci   int is_cursor, is_scanout;
1160bf215546Sopenharmony_ci
1161bf215546Sopenharmony_ci   is_cursor = (usage & GBM_BO_USE_CURSOR) != 0 &&
1162bf215546Sopenharmony_ci      format == GBM_FORMAT_ARGB8888;
1163bf215546Sopenharmony_ci   is_scanout = (usage & GBM_BO_USE_SCANOUT) != 0 &&
1164bf215546Sopenharmony_ci      (format == GBM_FORMAT_XRGB8888 || format == GBM_FORMAT_XBGR8888);
1165bf215546Sopenharmony_ci   if (!is_cursor && !is_scanout) {
1166bf215546Sopenharmony_ci      errno = EINVAL;
1167bf215546Sopenharmony_ci      return NULL;
1168bf215546Sopenharmony_ci   }
1169bf215546Sopenharmony_ci
1170bf215546Sopenharmony_ci   bo = calloc(1, sizeof *bo);
1171bf215546Sopenharmony_ci   if (bo == NULL)
1172bf215546Sopenharmony_ci      return NULL;
1173bf215546Sopenharmony_ci
1174bf215546Sopenharmony_ci   memset(&create_arg, 0, sizeof(create_arg));
1175bf215546Sopenharmony_ci   create_arg.bpp = 32;
1176bf215546Sopenharmony_ci   create_arg.width = width;
1177bf215546Sopenharmony_ci   create_arg.height = height;
1178bf215546Sopenharmony_ci
1179bf215546Sopenharmony_ci   ret = drmIoctl(dri->base.v0.fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg);
1180bf215546Sopenharmony_ci   if (ret)
1181bf215546Sopenharmony_ci      goto free_bo;
1182bf215546Sopenharmony_ci
1183bf215546Sopenharmony_ci   bo->base.gbm = gbm;
1184bf215546Sopenharmony_ci   bo->base.v0.width = width;
1185bf215546Sopenharmony_ci   bo->base.v0.height = height;
1186bf215546Sopenharmony_ci   bo->base.v0.stride = create_arg.pitch;
1187bf215546Sopenharmony_ci   bo->base.v0.format = format;
1188bf215546Sopenharmony_ci   bo->base.v0.handle.u32 = create_arg.handle;
1189bf215546Sopenharmony_ci   bo->handle = create_arg.handle;
1190bf215546Sopenharmony_ci   bo->size = create_arg.size;
1191bf215546Sopenharmony_ci
1192bf215546Sopenharmony_ci   if (gbm_dri_bo_map_dumb(bo) == NULL)
1193bf215546Sopenharmony_ci      goto destroy_dumb;
1194bf215546Sopenharmony_ci
1195bf215546Sopenharmony_ci   return &bo->base;
1196bf215546Sopenharmony_ci
1197bf215546Sopenharmony_cidestroy_dumb:
1198bf215546Sopenharmony_ci   memset(&destroy_arg, 0, sizeof destroy_arg);
1199bf215546Sopenharmony_ci   destroy_arg.handle = create_arg.handle;
1200bf215546Sopenharmony_ci   drmIoctl(dri->base.v0.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
1201bf215546Sopenharmony_cifree_bo:
1202bf215546Sopenharmony_ci   free(bo);
1203bf215546Sopenharmony_ci
1204bf215546Sopenharmony_ci   return NULL;
1205bf215546Sopenharmony_ci}
1206bf215546Sopenharmony_ci
1207bf215546Sopenharmony_cistatic struct gbm_bo *
1208bf215546Sopenharmony_cigbm_dri_bo_create(struct gbm_device *gbm,
1209bf215546Sopenharmony_ci                  uint32_t width, uint32_t height,
1210bf215546Sopenharmony_ci                  uint32_t format, uint32_t usage,
1211bf215546Sopenharmony_ci                  const uint64_t *modifiers,
1212bf215546Sopenharmony_ci                  const unsigned int count)
1213bf215546Sopenharmony_ci{
1214bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(gbm);
1215bf215546Sopenharmony_ci   struct gbm_dri_bo *bo;
1216bf215546Sopenharmony_ci   int dri_format;
1217bf215546Sopenharmony_ci   unsigned dri_use = 0;
1218bf215546Sopenharmony_ci
1219bf215546Sopenharmony_ci   format = gbm_core.v0.format_canonicalize(format);
1220bf215546Sopenharmony_ci
1221bf215546Sopenharmony_ci   if (usage & GBM_BO_USE_WRITE || dri->image == NULL)
1222bf215546Sopenharmony_ci      return create_dumb(gbm, width, height, format, usage);
1223bf215546Sopenharmony_ci
1224bf215546Sopenharmony_ci   bo = calloc(1, sizeof *bo);
1225bf215546Sopenharmony_ci   if (bo == NULL)
1226bf215546Sopenharmony_ci      return NULL;
1227bf215546Sopenharmony_ci
1228bf215546Sopenharmony_ci   bo->base.gbm = gbm;
1229bf215546Sopenharmony_ci   bo->base.v0.width = width;
1230bf215546Sopenharmony_ci   bo->base.v0.height = height;
1231bf215546Sopenharmony_ci   bo->base.v0.format = format;
1232bf215546Sopenharmony_ci
1233bf215546Sopenharmony_ci   dri_format = gbm_format_to_dri_format(format);
1234bf215546Sopenharmony_ci   if (dri_format == 0) {
1235bf215546Sopenharmony_ci      errno = EINVAL;
1236bf215546Sopenharmony_ci      goto failed;
1237bf215546Sopenharmony_ci   }
1238bf215546Sopenharmony_ci
1239bf215546Sopenharmony_ci   if (usage & GBM_BO_USE_SCANOUT)
1240bf215546Sopenharmony_ci      dri_use |= __DRI_IMAGE_USE_SCANOUT;
1241bf215546Sopenharmony_ci   if (usage & GBM_BO_USE_CURSOR)
1242bf215546Sopenharmony_ci      dri_use |= __DRI_IMAGE_USE_CURSOR;
1243bf215546Sopenharmony_ci   if (usage & GBM_BO_USE_LINEAR)
1244bf215546Sopenharmony_ci      dri_use |= __DRI_IMAGE_USE_LINEAR;
1245bf215546Sopenharmony_ci   if (usage & GBM_BO_USE_PROTECTED)
1246bf215546Sopenharmony_ci      dri_use |= __DRI_IMAGE_USE_PROTECTED;
1247bf215546Sopenharmony_ci
1248bf215546Sopenharmony_ci   /* Gallium drivers requires shared in order to get the handle/stride */
1249bf215546Sopenharmony_ci   dri_use |= __DRI_IMAGE_USE_SHARE;
1250bf215546Sopenharmony_ci
1251bf215546Sopenharmony_ci   if (modifiers && (dri->image->base.version < 14 ||
1252bf215546Sopenharmony_ci       !dri->image->createImageWithModifiers)) {
1253bf215546Sopenharmony_ci      errno = ENOSYS;
1254bf215546Sopenharmony_ci      goto failed;
1255bf215546Sopenharmony_ci   }
1256bf215546Sopenharmony_ci
1257bf215546Sopenharmony_ci   bo->image = loader_dri_create_image(dri->screen, dri->image, width, height,
1258bf215546Sopenharmony_ci                                       dri_format, dri_use, modifiers, count,
1259bf215546Sopenharmony_ci                                       bo);
1260bf215546Sopenharmony_ci   if (bo->image == NULL)
1261bf215546Sopenharmony_ci      goto failed;
1262bf215546Sopenharmony_ci
1263bf215546Sopenharmony_ci   if (modifiers)
1264bf215546Sopenharmony_ci      assert(gbm_dri_bo_get_modifier(&bo->base) != DRM_FORMAT_MOD_INVALID);
1265bf215546Sopenharmony_ci
1266bf215546Sopenharmony_ci   dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE,
1267bf215546Sopenharmony_ci                          &bo->base.v0.handle.s32);
1268bf215546Sopenharmony_ci   dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE,
1269bf215546Sopenharmony_ci                          (int *) &bo->base.v0.stride);
1270bf215546Sopenharmony_ci
1271bf215546Sopenharmony_ci   return &bo->base;
1272bf215546Sopenharmony_ci
1273bf215546Sopenharmony_cifailed:
1274bf215546Sopenharmony_ci   free(bo);
1275bf215546Sopenharmony_ci   return NULL;
1276bf215546Sopenharmony_ci}
1277bf215546Sopenharmony_ci
1278bf215546Sopenharmony_cistatic void *
1279bf215546Sopenharmony_cigbm_dri_bo_map(struct gbm_bo *_bo,
1280bf215546Sopenharmony_ci              uint32_t x, uint32_t y,
1281bf215546Sopenharmony_ci              uint32_t width, uint32_t height,
1282bf215546Sopenharmony_ci              uint32_t flags, uint32_t *stride, void **map_data)
1283bf215546Sopenharmony_ci{
1284bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
1285bf215546Sopenharmony_ci   struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
1286bf215546Sopenharmony_ci
1287bf215546Sopenharmony_ci   /* If it's a dumb buffer, we already have a mapping */
1288bf215546Sopenharmony_ci   if (bo->map) {
1289bf215546Sopenharmony_ci      *map_data = (char *)bo->map + (bo->base.v0.stride * y) + (x * 4);
1290bf215546Sopenharmony_ci      *stride = bo->base.v0.stride;
1291bf215546Sopenharmony_ci      return *map_data;
1292bf215546Sopenharmony_ci   }
1293bf215546Sopenharmony_ci
1294bf215546Sopenharmony_ci   if (!dri->image || dri->image->base.version < 12 || !dri->image->mapImage) {
1295bf215546Sopenharmony_ci      errno = ENOSYS;
1296bf215546Sopenharmony_ci      return NULL;
1297bf215546Sopenharmony_ci   }
1298bf215546Sopenharmony_ci
1299bf215546Sopenharmony_ci   mtx_lock(&dri->mutex);
1300bf215546Sopenharmony_ci   if (!dri->context)
1301bf215546Sopenharmony_ci      dri->context = dri->dri2->createNewContext(dri->screen, NULL,
1302bf215546Sopenharmony_ci                                                 NULL, NULL);
1303bf215546Sopenharmony_ci   assert(dri->context);
1304bf215546Sopenharmony_ci   mtx_unlock(&dri->mutex);
1305bf215546Sopenharmony_ci
1306bf215546Sopenharmony_ci   /* GBM flags and DRI flags are the same, so just pass them on */
1307bf215546Sopenharmony_ci   return dri->image->mapImage(dri->context, bo->image, x, y,
1308bf215546Sopenharmony_ci                               width, height, flags, (int *)stride,
1309bf215546Sopenharmony_ci                               map_data);
1310bf215546Sopenharmony_ci}
1311bf215546Sopenharmony_ci
1312bf215546Sopenharmony_cistatic void
1313bf215546Sopenharmony_cigbm_dri_bo_unmap(struct gbm_bo *_bo, void *map_data)
1314bf215546Sopenharmony_ci{
1315bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
1316bf215546Sopenharmony_ci   struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
1317bf215546Sopenharmony_ci
1318bf215546Sopenharmony_ci   /* Check if it's a dumb buffer and check the pointer is in range */
1319bf215546Sopenharmony_ci   if (bo->map) {
1320bf215546Sopenharmony_ci      assert(map_data >= bo->map);
1321bf215546Sopenharmony_ci      assert(map_data < (bo->map + bo->size));
1322bf215546Sopenharmony_ci      return;
1323bf215546Sopenharmony_ci   }
1324bf215546Sopenharmony_ci
1325bf215546Sopenharmony_ci   if (!dri->context || !dri->image ||
1326bf215546Sopenharmony_ci       dri->image->base.version < 12 || !dri->image->unmapImage)
1327bf215546Sopenharmony_ci      return;
1328bf215546Sopenharmony_ci
1329bf215546Sopenharmony_ci   dri->image->unmapImage(dri->context, bo->image, map_data);
1330bf215546Sopenharmony_ci
1331bf215546Sopenharmony_ci   /*
1332bf215546Sopenharmony_ci    * Not all DRI drivers use direct maps. They may queue up DMA operations
1333bf215546Sopenharmony_ci    * on the mapping context. Since there is no explicit gbm flush
1334bf215546Sopenharmony_ci    * mechanism, we need to flush here.
1335bf215546Sopenharmony_ci    */
1336bf215546Sopenharmony_ci   if (dri->flush->base.version >= 4)
1337bf215546Sopenharmony_ci      dri->flush->flush_with_flags(dri->context, NULL, __DRI2_FLUSH_CONTEXT, 0);
1338bf215546Sopenharmony_ci}
1339bf215546Sopenharmony_ci
1340bf215546Sopenharmony_ci
1341bf215546Sopenharmony_cistatic struct gbm_surface *
1342bf215546Sopenharmony_cigbm_dri_surface_create(struct gbm_device *gbm,
1343bf215546Sopenharmony_ci                       uint32_t width, uint32_t height,
1344bf215546Sopenharmony_ci		       uint32_t format, uint32_t flags,
1345bf215546Sopenharmony_ci                       const uint64_t *modifiers, const unsigned count)
1346bf215546Sopenharmony_ci{
1347bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(gbm);
1348bf215546Sopenharmony_ci   struct gbm_dri_surface *surf;
1349bf215546Sopenharmony_ci
1350bf215546Sopenharmony_ci   if (modifiers &&
1351bf215546Sopenharmony_ci       (!dri->image || dri->image->base.version < 14 ||
1352bf215546Sopenharmony_ci        !dri->image->createImageWithModifiers)) {
1353bf215546Sopenharmony_ci      errno = ENOSYS;
1354bf215546Sopenharmony_ci      return NULL;
1355bf215546Sopenharmony_ci   }
1356bf215546Sopenharmony_ci
1357bf215546Sopenharmony_ci   if (count)
1358bf215546Sopenharmony_ci      assert(modifiers);
1359bf215546Sopenharmony_ci
1360bf215546Sopenharmony_ci   /* It's acceptable to create an image with INVALID modifier in the list,
1361bf215546Sopenharmony_ci    * but it cannot be on the only modifier (since it will certainly fail
1362bf215546Sopenharmony_ci    * later). While we could easily catch this after modifier creation, doing
1363bf215546Sopenharmony_ci    * the check here is a convenient debug check likely pointing at whatever
1364bf215546Sopenharmony_ci    * interface the client is using to build its modifier list.
1365bf215546Sopenharmony_ci    */
1366bf215546Sopenharmony_ci   if (count == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID) {
1367bf215546Sopenharmony_ci      fprintf(stderr, "Only invalid modifier specified\n");
1368bf215546Sopenharmony_ci      errno = EINVAL;
1369bf215546Sopenharmony_ci   }
1370bf215546Sopenharmony_ci
1371bf215546Sopenharmony_ci   surf = calloc(1, sizeof *surf);
1372bf215546Sopenharmony_ci   if (surf == NULL) {
1373bf215546Sopenharmony_ci      errno = ENOMEM;
1374bf215546Sopenharmony_ci      return NULL;
1375bf215546Sopenharmony_ci   }
1376bf215546Sopenharmony_ci
1377bf215546Sopenharmony_ci   surf->base.gbm = gbm;
1378bf215546Sopenharmony_ci   surf->base.v0.width = width;
1379bf215546Sopenharmony_ci   surf->base.v0.height = height;
1380bf215546Sopenharmony_ci   surf->base.v0.format = gbm_core.v0.format_canonicalize(format);
1381bf215546Sopenharmony_ci   surf->base.v0.flags = flags;
1382bf215546Sopenharmony_ci   if (!modifiers) {
1383bf215546Sopenharmony_ci      assert(!count);
1384bf215546Sopenharmony_ci      return &surf->base;
1385bf215546Sopenharmony_ci   }
1386bf215546Sopenharmony_ci
1387bf215546Sopenharmony_ci   surf->base.v0.modifiers = calloc(count, sizeof(*modifiers));
1388bf215546Sopenharmony_ci   if (count && !surf->base.v0.modifiers) {
1389bf215546Sopenharmony_ci      errno = ENOMEM;
1390bf215546Sopenharmony_ci      free(surf);
1391bf215546Sopenharmony_ci      return NULL;
1392bf215546Sopenharmony_ci   }
1393bf215546Sopenharmony_ci
1394bf215546Sopenharmony_ci   /* TODO: We are deferring validation of modifiers until the image is actually
1395bf215546Sopenharmony_ci    * created. This deferred creation can fail due to a modifier-format
1396bf215546Sopenharmony_ci    * mismatch. The result is the client has a surface but no object to back it.
1397bf215546Sopenharmony_ci    */
1398bf215546Sopenharmony_ci   surf->base.v0.count = count;
1399bf215546Sopenharmony_ci   memcpy(surf->base.v0.modifiers, modifiers, count * sizeof(*modifiers));
1400bf215546Sopenharmony_ci
1401bf215546Sopenharmony_ci   return &surf->base;
1402bf215546Sopenharmony_ci}
1403bf215546Sopenharmony_ci
1404bf215546Sopenharmony_cistatic void
1405bf215546Sopenharmony_cigbm_dri_surface_destroy(struct gbm_surface *_surf)
1406bf215546Sopenharmony_ci{
1407bf215546Sopenharmony_ci   struct gbm_dri_surface *surf = gbm_dri_surface(_surf);
1408bf215546Sopenharmony_ci
1409bf215546Sopenharmony_ci   free(surf->base.v0.modifiers);
1410bf215546Sopenharmony_ci   free(surf);
1411bf215546Sopenharmony_ci}
1412bf215546Sopenharmony_ci
1413bf215546Sopenharmony_cistatic void
1414bf215546Sopenharmony_cidri_destroy(struct gbm_device *gbm)
1415bf215546Sopenharmony_ci{
1416bf215546Sopenharmony_ci   struct gbm_dri_device *dri = gbm_dri_device(gbm);
1417bf215546Sopenharmony_ci   unsigned i;
1418bf215546Sopenharmony_ci
1419bf215546Sopenharmony_ci   if (dri->context)
1420bf215546Sopenharmony_ci      dri->core->destroyContext(dri->context);
1421bf215546Sopenharmony_ci
1422bf215546Sopenharmony_ci   dri->core->destroyScreen(dri->screen);
1423bf215546Sopenharmony_ci   for (i = 0; dri->driver_configs[i]; i++)
1424bf215546Sopenharmony_ci      free((__DRIconfig *) dri->driver_configs[i]);
1425bf215546Sopenharmony_ci   free(dri->driver_configs);
1426bf215546Sopenharmony_ci   dlclose(dri->driver);
1427bf215546Sopenharmony_ci   free(dri->driver_name);
1428bf215546Sopenharmony_ci
1429bf215546Sopenharmony_ci   free(dri);
1430bf215546Sopenharmony_ci}
1431bf215546Sopenharmony_ci
1432bf215546Sopenharmony_cistatic struct gbm_device *
1433bf215546Sopenharmony_cidri_device_create(int fd, uint32_t gbm_backend_version)
1434bf215546Sopenharmony_ci{
1435bf215546Sopenharmony_ci   struct gbm_dri_device *dri;
1436bf215546Sopenharmony_ci   int ret;
1437bf215546Sopenharmony_ci   bool force_sw;
1438bf215546Sopenharmony_ci
1439bf215546Sopenharmony_ci   /*
1440bf215546Sopenharmony_ci    * Since the DRI backend is built-in to the loader, the loader ABI version is
1441bf215546Sopenharmony_ci    * guaranteed to match this backend's ABI version
1442bf215546Sopenharmony_ci    */
1443bf215546Sopenharmony_ci   assert(gbm_core.v0.core_version == GBM_BACKEND_ABI_VERSION);
1444bf215546Sopenharmony_ci   assert(gbm_core.v0.core_version == gbm_backend_version);
1445bf215546Sopenharmony_ci
1446bf215546Sopenharmony_ci   dri = calloc(1, sizeof *dri);
1447bf215546Sopenharmony_ci   if (!dri)
1448bf215546Sopenharmony_ci      return NULL;
1449bf215546Sopenharmony_ci
1450bf215546Sopenharmony_ci   dri->base.v0.fd = fd;
1451bf215546Sopenharmony_ci   dri->base.v0.backend_version = gbm_backend_version;
1452bf215546Sopenharmony_ci   dri->base.v0.bo_create = gbm_dri_bo_create;
1453bf215546Sopenharmony_ci   dri->base.v0.bo_import = gbm_dri_bo_import;
1454bf215546Sopenharmony_ci   dri->base.v0.bo_map = gbm_dri_bo_map;
1455bf215546Sopenharmony_ci   dri->base.v0.bo_unmap = gbm_dri_bo_unmap;
1456bf215546Sopenharmony_ci   dri->base.v0.is_format_supported = gbm_dri_is_format_supported;
1457bf215546Sopenharmony_ci   dri->base.v0.get_format_modifier_plane_count =
1458bf215546Sopenharmony_ci      gbm_dri_get_format_modifier_plane_count;
1459bf215546Sopenharmony_ci   dri->base.v0.bo_write = gbm_dri_bo_write;
1460bf215546Sopenharmony_ci   dri->base.v0.bo_get_fd = gbm_dri_bo_get_fd;
1461bf215546Sopenharmony_ci   dri->base.v0.bo_get_planes = gbm_dri_bo_get_planes;
1462bf215546Sopenharmony_ci   dri->base.v0.bo_get_handle = gbm_dri_bo_get_handle_for_plane;
1463bf215546Sopenharmony_ci   dri->base.v0.bo_get_plane_fd = gbm_dri_bo_get_plane_fd;
1464bf215546Sopenharmony_ci   dri->base.v0.bo_get_stride = gbm_dri_bo_get_stride;
1465bf215546Sopenharmony_ci   dri->base.v0.bo_get_offset = gbm_dri_bo_get_offset;
1466bf215546Sopenharmony_ci   dri->base.v0.bo_get_modifier = gbm_dri_bo_get_modifier;
1467bf215546Sopenharmony_ci   dri->base.v0.bo_destroy = gbm_dri_bo_destroy;
1468bf215546Sopenharmony_ci   dri->base.v0.destroy = dri_destroy;
1469bf215546Sopenharmony_ci   dri->base.v0.surface_create = gbm_dri_surface_create;
1470bf215546Sopenharmony_ci   dri->base.v0.surface_destroy = gbm_dri_surface_destroy;
1471bf215546Sopenharmony_ci
1472bf215546Sopenharmony_ci   dri->base.v0.name = "drm";
1473bf215546Sopenharmony_ci
1474bf215546Sopenharmony_ci   dri->visual_table = gbm_dri_visuals_table;
1475bf215546Sopenharmony_ci   dri->num_visuals = ARRAY_SIZE(gbm_dri_visuals_table);
1476bf215546Sopenharmony_ci
1477bf215546Sopenharmony_ci   mtx_init(&dri->mutex, mtx_plain);
1478bf215546Sopenharmony_ci
1479bf215546Sopenharmony_ci   force_sw = env_var_as_boolean("GBM_ALWAYS_SOFTWARE", false);
1480bf215546Sopenharmony_ci   if (!force_sw) {
1481bf215546Sopenharmony_ci      ret = dri_screen_create(dri);
1482bf215546Sopenharmony_ci      if (ret)
1483bf215546Sopenharmony_ci         ret = dri_screen_create_sw(dri);
1484bf215546Sopenharmony_ci   } else {
1485bf215546Sopenharmony_ci      ret = dri_screen_create_sw(dri);
1486bf215546Sopenharmony_ci   }
1487bf215546Sopenharmony_ci
1488bf215546Sopenharmony_ci   if (ret)
1489bf215546Sopenharmony_ci      goto err_dri;
1490bf215546Sopenharmony_ci
1491bf215546Sopenharmony_ci   return &dri->base;
1492bf215546Sopenharmony_ci
1493bf215546Sopenharmony_cierr_dri:
1494bf215546Sopenharmony_ci   free(dri);
1495bf215546Sopenharmony_ci
1496bf215546Sopenharmony_ci   return NULL;
1497bf215546Sopenharmony_ci}
1498bf215546Sopenharmony_ci
1499bf215546Sopenharmony_cistruct gbm_backend gbm_dri_backend = {
1500bf215546Sopenharmony_ci   .v0.backend_version = GBM_BACKEND_ABI_VERSION,
1501bf215546Sopenharmony_ci   .v0.backend_name = "dri",
1502bf215546Sopenharmony_ci   .v0.create_device = dri_device_create,
1503bf215546Sopenharmony_ci};
1504