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