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