gbm: rename gbm_dri_bo_{map,unmap} to gbm_dri_bo_{map,unmap}_dumb
[mesa.git] / src / gbm / backends / dri / gbm_dri.c
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 <string.h>
33 #include <errno.h>
34 #include <limits.h>
35
36 #include <sys/types.h>
37 #include <unistd.h>
38 #include <dlfcn.h>
39 #include <xf86drm.h>
40
41 #include <GL/gl.h> /* dri_interface needs GL types */
42 #include <GL/internal/dri_interface.h>
43
44 #include "gbm_driint.h"
45
46 #include "gbmint.h"
47 #include "loader.h"
48
49 /* For importing wl_buffer */
50 #if HAVE_WAYLAND_PLATFORM
51 #include "../../../egl/wayland/wayland-drm/wayland-drm.h"
52 #endif
53
54 static __DRIimage *
55 dri_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
56 {
57 struct gbm_dri_device *dri = data;
58
59 if (dri->lookup_image == NULL)
60 return NULL;
61
62 return dri->lookup_image(screen, image, dri->lookup_user_data);
63 }
64
65 static __DRIbuffer *
66 dri_get_buffers(__DRIdrawable * driDrawable,
67 int *width, int *height,
68 unsigned int *attachments, int count,
69 int *out_count, void *data)
70 {
71 struct gbm_dri_surface *surf = data;
72 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
73
74 if (dri->get_buffers == NULL)
75 return NULL;
76
77 return dri->get_buffers(driDrawable, width, height, attachments,
78 count, out_count, surf->dri_private);
79 }
80
81 static void
82 dri_flush_front_buffer(__DRIdrawable * driDrawable, void *data)
83 {
84 struct gbm_dri_surface *surf = data;
85 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
86
87 if (dri->flush_front_buffer != NULL)
88 dri->flush_front_buffer(driDrawable, surf->dri_private);
89 }
90
91 static __DRIbuffer *
92 dri_get_buffers_with_format(__DRIdrawable * driDrawable,
93 int *width, int *height,
94 unsigned int *attachments, int count,
95 int *out_count, void *data)
96 {
97 struct gbm_dri_surface *surf = data;
98 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
99
100 if (dri->get_buffers_with_format == NULL)
101 return NULL;
102
103 return
104 dri->get_buffers_with_format(driDrawable, width, height, attachments,
105 count, out_count, surf->dri_private);
106 }
107
108 static int
109 image_get_buffers(__DRIdrawable *driDrawable,
110 unsigned int format,
111 uint32_t *stamp,
112 void *loaderPrivate,
113 uint32_t buffer_mask,
114 struct __DRIimageList *buffers)
115 {
116 struct gbm_dri_surface *surf = loaderPrivate;
117 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
118
119 if (dri->image_get_buffers == NULL)
120 return 0;
121
122 return dri->image_get_buffers(driDrawable, format, stamp,
123 surf->dri_private, buffer_mask, buffers);
124 }
125
126 static void
127 swrast_get_drawable_info(__DRIdrawable *driDrawable,
128 int *x,
129 int *y,
130 int *width,
131 int *height,
132 void *loaderPrivate)
133 {
134 struct gbm_dri_surface *surf = loaderPrivate;
135
136 *x = 0;
137 *y = 0;
138 *width = surf->base.width;
139 *height = surf->base.height;
140 }
141
142 static void
143 swrast_put_image2(__DRIdrawable *driDrawable,
144 int op,
145 int x,
146 int y,
147 int width,
148 int height,
149 int stride,
150 char *data,
151 void *loaderPrivate)
152 {
153 struct gbm_dri_surface *surf = loaderPrivate;
154 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
155
156 dri->swrast_put_image2(driDrawable,
157 op, x, y,
158 width, height, stride,
159 data, surf->dri_private);
160 }
161
162 static void
163 swrast_put_image(__DRIdrawable *driDrawable,
164 int op,
165 int x,
166 int y,
167 int width,
168 int height,
169 char *data,
170 void *loaderPrivate)
171 {
172 return swrast_put_image2(driDrawable, op, x, y, width, height,
173 width * 4, data, loaderPrivate);
174 }
175
176 static void
177 swrast_get_image(__DRIdrawable *driDrawable,
178 int x,
179 int y,
180 int width,
181 int height,
182 char *data,
183 void *loaderPrivate)
184 {
185 struct gbm_dri_surface *surf = loaderPrivate;
186 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
187
188 dri->swrast_get_image(driDrawable,
189 x, y,
190 width, height,
191 data, surf->dri_private);
192 }
193
194 static const __DRIuseInvalidateExtension use_invalidate = {
195 .base = { __DRI_USE_INVALIDATE, 1 }
196 };
197
198 static const __DRIimageLookupExtension image_lookup_extension = {
199 .base = { __DRI_IMAGE_LOOKUP, 1 },
200
201 .lookupEGLImage = dri_lookup_egl_image
202 };
203
204 static const __DRIdri2LoaderExtension dri2_loader_extension = {
205 .base = { __DRI_DRI2_LOADER, 3 },
206
207 .getBuffers = dri_get_buffers,
208 .flushFrontBuffer = dri_flush_front_buffer,
209 .getBuffersWithFormat = dri_get_buffers_with_format,
210 };
211
212 static const __DRIimageLoaderExtension image_loader_extension = {
213 .base = { __DRI_IMAGE_LOADER, 1 },
214
215 .getBuffers = image_get_buffers,
216 .flushFrontBuffer = dri_flush_front_buffer,
217 };
218
219 static const __DRIswrastLoaderExtension swrast_loader_extension = {
220 .base = { __DRI_SWRAST_LOADER, 2 },
221
222 .getDrawableInfo = swrast_get_drawable_info,
223 .putImage = swrast_put_image,
224 .getImage = swrast_get_image,
225 .putImage2 = swrast_put_image2
226 };
227
228 static const __DRIextension *gbm_dri_screen_extensions[] = {
229 &image_lookup_extension.base,
230 &use_invalidate.base,
231 &dri2_loader_extension.base,
232 &image_loader_extension.base,
233 &swrast_loader_extension.base,
234 NULL,
235 };
236
237 struct dri_extension_match {
238 const char *name;
239 int version;
240 int offset;
241 };
242
243 static struct dri_extension_match dri_core_extensions[] = {
244 { __DRI2_FLUSH, 1, offsetof(struct gbm_dri_device, flush) },
245 { __DRI_IMAGE, 1, offsetof(struct gbm_dri_device, image) },
246 { NULL, 0, 0 }
247 };
248
249 static struct dri_extension_match gbm_dri_device_extensions[] = {
250 { __DRI_CORE, 1, offsetof(struct gbm_dri_device, core) },
251 { __DRI_DRI2, 1, offsetof(struct gbm_dri_device, dri2) },
252 { NULL, 0, 0 }
253 };
254
255 static struct dri_extension_match gbm_swrast_device_extensions[] = {
256 { __DRI_CORE, 1, offsetof(struct gbm_dri_device, core), },
257 { __DRI_SWRAST, 1, offsetof(struct gbm_dri_device, swrast) },
258 { NULL, 0, 0 }
259 };
260
261 static int
262 dri_bind_extensions(struct gbm_dri_device *dri,
263 struct dri_extension_match *matches,
264 const __DRIextension **extensions)
265 {
266 int i, j, ret = 0;
267 void *field;
268
269 for (i = 0; extensions[i]; i++) {
270 for (j = 0; matches[j].name; j++) {
271 if (strcmp(extensions[i]->name, matches[j].name) == 0 &&
272 extensions[i]->version >= matches[j].version) {
273 field = ((char *) dri + matches[j].offset);
274 *(const __DRIextension **) field = extensions[i];
275 }
276 }
277 }
278
279 for (j = 0; matches[j].name; j++) {
280 field = ((char *) dri + matches[j].offset);
281 if (*(const __DRIextension **) field == NULL) {
282 ret = -1;
283 }
284 }
285
286 return ret;
287 }
288
289 static const __DRIextension **
290 dri_open_driver(struct gbm_dri_device *dri)
291 {
292 const __DRIextension **extensions = NULL;
293 char path[PATH_MAX], *search_paths, *p, *next, *end;
294 char *get_extensions_name;
295
296 search_paths = NULL;
297 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH or GBM_DRIVERS_PATH */
298 if (geteuid() == getuid()) {
299 /* Read GBM_DRIVERS_PATH first for compatibility, but LIBGL_DRIVERS_PATH
300 * is recommended over GBM_DRIVERS_PATH.
301 */
302 search_paths = getenv("GBM_DRIVERS_PATH");
303
304 /* Read LIBGL_DRIVERS_PATH if GBM_DRIVERS_PATH was not set.
305 * LIBGL_DRIVERS_PATH is recommended over GBM_DRIVERS_PATH.
306 */
307 if (search_paths == NULL) {
308 search_paths = getenv("LIBGL_DRIVERS_PATH");
309 }
310 }
311 if (search_paths == NULL)
312 search_paths = DEFAULT_DRIVER_DIR;
313
314 /* Temporarily work around dri driver libs that need symbols in libglapi
315 * but don't automatically link it in.
316 */
317 /* XXX: Library name differs on per platforms basis. Update this as
318 * osx/cygwin/windows/bsd gets support for GBM..
319 */
320 dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL);
321
322 dri->driver = NULL;
323 end = search_paths + strlen(search_paths);
324 for (p = search_paths; p < end && dri->driver == NULL; p = next + 1) {
325 int len;
326 next = strchr(p, ':');
327 if (next == NULL)
328 next = end;
329
330 len = next - p;
331 #if GLX_USE_TLS
332 snprintf(path, sizeof path,
333 "%.*s/tls/%s_dri.so", len, p, dri->base.driver_name);
334 dri->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
335 #endif
336 if (dri->driver == NULL) {
337 snprintf(path, sizeof path,
338 "%.*s/%s_dri.so", len, p, dri->base.driver_name);
339 dri->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
340 }
341 /* not need continue to loop all paths once the driver is found */
342 if (dri->driver != NULL)
343 break;
344
345 #ifdef ANDROID
346 snprintf(path, sizeof path, "%.*s/gallium_dri.so", len, p);
347 dri->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
348 if (dri->driver == NULL)
349 sprintf("failed to open %s: %s\n", path, dlerror());
350 else
351 break;
352 #endif
353 }
354
355 if (dri->driver == NULL) {
356 fprintf(stderr, "gbm: failed to open any driver (search paths %s)\n",
357 search_paths);
358 fprintf(stderr, "gbm: Last dlopen error: %s\n", dlerror());
359 return NULL;
360 }
361
362 if (asprintf(&get_extensions_name, "%s_%s",
363 __DRI_DRIVER_GET_EXTENSIONS, dri->base.driver_name) != -1) {
364 const __DRIextension **(*get_extensions)(void);
365
366 get_extensions = dlsym(dri->driver, get_extensions_name);
367 free(get_extensions_name);
368
369 if (get_extensions)
370 extensions = get_extensions();
371 }
372
373 if (!extensions)
374 extensions = dlsym(dri->driver, __DRI_DRIVER_EXTENSIONS);
375 if (extensions == NULL) {
376 fprintf(stderr, "gbm: driver exports no extensions (%s)", dlerror());
377 dlclose(dri->driver);
378 }
379
380 return extensions;
381 }
382
383 static int
384 dri_load_driver(struct gbm_dri_device *dri)
385 {
386 const __DRIextension **extensions;
387
388 extensions = dri_open_driver(dri);
389 if (!extensions)
390 return -1;
391
392 if (dri_bind_extensions(dri, gbm_dri_device_extensions, extensions) < 0) {
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
403 static int
404 dri_load_driver_swrast(struct gbm_dri_device *dri)
405 {
406 const __DRIextension **extensions;
407
408 extensions = dri_open_driver(dri);
409 if (!extensions)
410 return -1;
411
412 if (dri_bind_extensions(dri, gbm_swrast_device_extensions, extensions) < 0) {
413 dlclose(dri->driver);
414 fprintf(stderr, "failed to bind extensions\n");
415 return -1;
416 }
417
418 dri->driver_extensions = extensions;
419
420 return 0;
421 }
422
423 static int
424 dri_screen_create_dri2(struct gbm_dri_device *dri, char *driver_name)
425 {
426 const __DRIextension **extensions;
427 int ret = 0;
428
429 dri->base.driver_name = driver_name;
430 if (dri->base.driver_name == NULL)
431 return -1;
432
433 ret = dri_load_driver(dri);
434 if (ret) {
435 fprintf(stderr, "failed to load driver: %s\n", dri->base.driver_name);
436 return ret;
437 };
438
439 dri->extensions = gbm_dri_screen_extensions;
440
441 if (dri->dri2 == NULL)
442 return -1;
443
444 if (dri->dri2->base.version >= 4) {
445 dri->screen = dri->dri2->createNewScreen2(0, dri->base.base.fd,
446 dri->extensions,
447 dri->driver_extensions,
448 &dri->driver_configs, dri);
449 } else {
450 dri->screen = dri->dri2->createNewScreen(0, dri->base.base.fd,
451 dri->extensions,
452 &dri->driver_configs, dri);
453 }
454 if (dri->screen == NULL)
455 return -1;
456
457 extensions = dri->core->getExtensions(dri->screen);
458 if (dri_bind_extensions(dri, dri_core_extensions, extensions) < 0) {
459 ret = -1;
460 goto free_screen;
461 }
462
463 dri->lookup_image = NULL;
464 dri->lookup_user_data = NULL;
465
466 return 0;
467
468 free_screen:
469 dri->core->destroyScreen(dri->screen);
470
471 return ret;
472 }
473
474 static int
475 dri_screen_create_swrast(struct gbm_dri_device *dri)
476 {
477 int ret;
478
479 dri->base.driver_name = strdup("swrast");
480 if (dri->base.driver_name == NULL)
481 return -1;
482
483 ret = dri_load_driver_swrast(dri);
484 if (ret) {
485 fprintf(stderr, "failed to load swrast driver\n");
486 return ret;
487 }
488
489 dri->extensions = gbm_dri_screen_extensions;
490
491 if (dri->swrast == NULL)
492 return -1;
493
494 if (dri->swrast->base.version >= 4) {
495 dri->screen = dri->swrast->createNewScreen2(0, dri->extensions,
496 dri->driver_extensions,
497 &dri->driver_configs, dri);
498 } else {
499 dri->screen = dri->swrast->createNewScreen(0, dri->extensions,
500 &dri->driver_configs, dri);
501 }
502 if (dri->screen == NULL)
503 return -1;
504
505 dri->lookup_image = NULL;
506 dri->lookup_user_data = NULL;
507
508 return 0;
509 }
510
511 static int
512 dri_screen_create(struct gbm_dri_device *dri)
513 {
514 char *driver_name;
515
516 driver_name = loader_get_driver_for_fd(dri->base.base.fd, 0);
517 if (!driver_name)
518 return -1;
519
520 return dri_screen_create_dri2(dri, driver_name);
521 }
522
523 static int
524 dri_screen_create_sw(struct gbm_dri_device *dri)
525 {
526 char *driver_name;
527 int ret;
528
529 driver_name = strdup("kms_swrast");
530 if (!driver_name)
531 return -errno;
532
533 ret = dri_screen_create_dri2(dri, driver_name);
534 if (ret == 0)
535 return ret;
536
537 return dri_screen_create_swrast(dri);
538 }
539
540 static int
541 gbm_dri_is_format_supported(struct gbm_device *gbm,
542 uint32_t format,
543 uint32_t usage)
544 {
545 switch (format) {
546 case GBM_BO_FORMAT_XRGB8888:
547 case GBM_FORMAT_XBGR8888:
548 case GBM_FORMAT_XRGB8888:
549 break;
550 case GBM_BO_FORMAT_ARGB8888:
551 case GBM_FORMAT_ARGB8888:
552 if (usage & GBM_BO_USE_SCANOUT)
553 return 0;
554 break;
555 default:
556 return 0;
557 }
558
559 if (usage & GBM_BO_USE_CURSOR &&
560 usage & GBM_BO_USE_RENDERING)
561 return 0;
562
563 return 1;
564 }
565
566 static int
567 gbm_dri_bo_write(struct gbm_bo *_bo, const void *buf, size_t count)
568 {
569 struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
570
571 if (bo->image != NULL) {
572 errno = EINVAL;
573 return -1;
574 }
575
576 memcpy(bo->map, buf, count);
577
578 return 0;
579 }
580
581 static int
582 gbm_dri_bo_get_fd(struct gbm_bo *_bo)
583 {
584 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
585 struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
586 int fd;
587
588 if (bo->image == NULL)
589 return -1;
590
591 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_FD, &fd);
592
593 return fd;
594 }
595
596 static void
597 gbm_dri_bo_destroy(struct gbm_bo *_bo)
598 {
599 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
600 struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
601 struct drm_mode_destroy_dumb arg;
602
603 if (bo->image != NULL) {
604 dri->image->destroyImage(bo->image);
605 } else {
606 gbm_dri_bo_unmap_dumb(bo);
607 memset(&arg, 0, sizeof(arg));
608 arg.handle = bo->handle;
609 drmIoctl(dri->base.base.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg);
610 }
611
612 free(bo);
613 }
614
615 static uint32_t
616 gbm_dri_to_gbm_format(uint32_t dri_format)
617 {
618 uint32_t ret = 0;
619
620 switch (dri_format) {
621 case __DRI_IMAGE_FORMAT_RGB565:
622 ret = GBM_FORMAT_RGB565;
623 break;
624 case __DRI_IMAGE_FORMAT_XRGB8888:
625 ret = GBM_FORMAT_XRGB8888;
626 break;
627 case __DRI_IMAGE_FORMAT_ARGB8888:
628 ret = GBM_FORMAT_ARGB8888;
629 break;
630 case __DRI_IMAGE_FORMAT_XBGR8888:
631 ret = GBM_FORMAT_XBGR8888;
632 break;
633 case __DRI_IMAGE_FORMAT_ABGR8888:
634 ret = GBM_FORMAT_ABGR8888;
635 break;
636 default:
637 ret = 0;
638 break;
639 }
640
641 return ret;
642 }
643
644 static struct gbm_bo *
645 gbm_dri_bo_import(struct gbm_device *gbm,
646 uint32_t type, void *buffer, uint32_t usage)
647 {
648 struct gbm_dri_device *dri = gbm_dri_device(gbm);
649 struct gbm_dri_bo *bo;
650 __DRIimage *image;
651 unsigned dri_use = 0;
652 int gbm_format;
653
654 /* Required for query image WIDTH & HEIGHT */
655 if (dri->image == NULL || dri->image->base.version < 4) {
656 errno = ENOSYS;
657 return NULL;
658 }
659
660 switch (type) {
661 #if HAVE_WAYLAND_PLATFORM
662 case GBM_BO_IMPORT_WL_BUFFER:
663 {
664 struct wl_drm_buffer *wb;
665
666 if (!dri->wl_drm) {
667 errno = EINVAL;
668 return NULL;
669 }
670
671 wb = wayland_drm_buffer_get(dri->wl_drm, (struct wl_resource *) buffer);
672 if (!wb) {
673 errno = EINVAL;
674 return NULL;
675 }
676
677 image = dri->image->dupImage(wb->driver_buffer, NULL);
678
679 switch (wb->format) {
680 case WL_DRM_FORMAT_XRGB8888:
681 gbm_format = GBM_FORMAT_XRGB8888;
682 break;
683 case WL_DRM_FORMAT_ARGB8888:
684 gbm_format = GBM_FORMAT_ARGB8888;
685 break;
686 case WL_DRM_FORMAT_RGB565:
687 gbm_format = GBM_FORMAT_RGB565;
688 break;
689 case WL_DRM_FORMAT_YUYV:
690 gbm_format = GBM_FORMAT_YUYV;
691 break;
692 default:
693 return NULL;
694 }
695 break;
696 }
697 #endif
698
699 case GBM_BO_IMPORT_EGL_IMAGE:
700 {
701 int dri_format;
702 if (dri->lookup_image == NULL) {
703 errno = EINVAL;
704 return NULL;
705 }
706
707 image = dri->lookup_image(dri->screen, buffer, dri->lookup_user_data);
708 image = dri->image->dupImage(image, NULL);
709 dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &dri_format);
710 gbm_format = gbm_dri_to_gbm_format(dri_format);
711 if (gbm_format == 0) {
712 errno = EINVAL;
713 return NULL;
714 }
715 break;
716 }
717
718 case GBM_BO_IMPORT_FD:
719 {
720 struct gbm_import_fd_data *fd_data = buffer;
721 int stride = fd_data->stride, offset = 0;
722 int dri_format;
723
724 switch (fd_data->format) {
725 case GBM_BO_FORMAT_XRGB8888:
726 dri_format = GBM_FORMAT_XRGB8888;
727 break;
728 case GBM_BO_FORMAT_ARGB8888:
729 dri_format = GBM_FORMAT_ARGB8888;
730 break;
731 default:
732 dri_format = fd_data->format;
733 }
734
735 image = dri->image->createImageFromFds(dri->screen,
736 fd_data->width,
737 fd_data->height,
738 dri_format,
739 &fd_data->fd, 1,
740 &stride, &offset,
741 NULL);
742 if (image == NULL) {
743 errno = EINVAL;
744 return NULL;
745 }
746 gbm_format = fd_data->format;
747 break;
748 }
749
750 default:
751 errno = ENOSYS;
752 return NULL;
753 }
754
755
756 bo = calloc(1, sizeof *bo);
757 if (bo == NULL)
758 return NULL;
759
760 bo->image = image;
761
762 if (usage & GBM_BO_USE_SCANOUT)
763 dri_use |= __DRI_IMAGE_USE_SCANOUT;
764 if (usage & GBM_BO_USE_CURSOR)
765 dri_use |= __DRI_IMAGE_USE_CURSOR;
766 if (dri->image->base.version >= 2 &&
767 !dri->image->validateUsage(bo->image, dri_use)) {
768 errno = EINVAL;
769 free(bo);
770 return NULL;
771 }
772
773 bo->base.base.gbm = gbm;
774 bo->base.base.format = gbm_format;
775
776 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_WIDTH,
777 (int*)&bo->base.base.width);
778 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HEIGHT,
779 (int*)&bo->base.base.height);
780 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE,
781 (int*)&bo->base.base.stride);
782 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE,
783 &bo->base.base.handle.s32);
784
785 return &bo->base.base;
786 }
787
788 static struct gbm_bo *
789 create_dumb(struct gbm_device *gbm,
790 uint32_t width, uint32_t height,
791 uint32_t format, uint32_t usage)
792 {
793 struct gbm_dri_device *dri = gbm_dri_device(gbm);
794 struct drm_mode_create_dumb create_arg;
795 struct gbm_dri_bo *bo;
796 struct drm_mode_destroy_dumb destroy_arg;
797 int ret;
798 int is_cursor, is_scanout;
799
800 is_cursor = (usage & GBM_BO_USE_CURSOR) != 0 &&
801 format == GBM_FORMAT_ARGB8888;
802 is_scanout = (usage & GBM_BO_USE_SCANOUT) != 0 &&
803 format == GBM_FORMAT_XRGB8888;
804 if (!is_cursor && !is_scanout) {
805 errno = EINVAL;
806 return NULL;
807 }
808
809 bo = calloc(1, sizeof *bo);
810 if (bo == NULL)
811 return NULL;
812
813 memset(&create_arg, 0, sizeof(create_arg));
814 create_arg.bpp = 32;
815 create_arg.width = width;
816 create_arg.height = height;
817
818 ret = drmIoctl(dri->base.base.fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg);
819 if (ret)
820 goto free_bo;
821
822 bo->base.base.gbm = gbm;
823 bo->base.base.width = width;
824 bo->base.base.height = height;
825 bo->base.base.stride = create_arg.pitch;
826 bo->base.base.format = format;
827 bo->base.base.handle.u32 = create_arg.handle;
828 bo->handle = create_arg.handle;
829 bo->size = create_arg.size;
830
831 if (gbm_dri_bo_map_dumb(bo) == NULL)
832 goto destroy_dumb;
833
834 return &bo->base.base;
835
836 destroy_dumb:
837 memset(&destroy_arg, 0, sizeof destroy_arg);
838 destroy_arg.handle = create_arg.handle;
839 drmIoctl(dri->base.base.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
840 free_bo:
841 free(bo);
842
843 return NULL;
844 }
845
846 static struct gbm_bo *
847 gbm_dri_bo_create(struct gbm_device *gbm,
848 uint32_t width, uint32_t height,
849 uint32_t format, uint32_t usage)
850 {
851 struct gbm_dri_device *dri = gbm_dri_device(gbm);
852 struct gbm_dri_bo *bo;
853 int dri_format;
854 unsigned dri_use = 0;
855
856 if (usage & GBM_BO_USE_WRITE || dri->image == NULL)
857 return create_dumb(gbm, width, height, format, usage);
858
859 bo = calloc(1, sizeof *bo);
860 if (bo == NULL)
861 return NULL;
862
863 bo->base.base.gbm = gbm;
864 bo->base.base.width = width;
865 bo->base.base.height = height;
866 bo->base.base.format = format;
867
868 switch (format) {
869 case GBM_FORMAT_RGB565:
870 dri_format =__DRI_IMAGE_FORMAT_RGB565;
871 break;
872 case GBM_FORMAT_XRGB8888:
873 case GBM_BO_FORMAT_XRGB8888:
874 dri_format = __DRI_IMAGE_FORMAT_XRGB8888;
875 break;
876 case GBM_FORMAT_ARGB8888:
877 case GBM_BO_FORMAT_ARGB8888:
878 dri_format = __DRI_IMAGE_FORMAT_ARGB8888;
879 break;
880 case GBM_FORMAT_ABGR8888:
881 dri_format = __DRI_IMAGE_FORMAT_ABGR8888;
882 break;
883 case GBM_FORMAT_XBGR8888:
884 dri_format = __DRI_IMAGE_FORMAT_XBGR8888;
885 break;
886 case GBM_FORMAT_ARGB2101010:
887 dri_format = __DRI_IMAGE_FORMAT_ARGB2101010;
888 break;
889 case GBM_FORMAT_XRGB2101010:
890 dri_format = __DRI_IMAGE_FORMAT_XRGB2101010;
891 break;
892 default:
893 errno = EINVAL;
894 goto failed;
895 }
896
897 if (usage & GBM_BO_USE_SCANOUT)
898 dri_use |= __DRI_IMAGE_USE_SCANOUT;
899 if (usage & GBM_BO_USE_CURSOR)
900 dri_use |= __DRI_IMAGE_USE_CURSOR;
901 if (usage & GBM_BO_USE_LINEAR)
902 dri_use |= __DRI_IMAGE_USE_LINEAR;
903
904 /* Gallium drivers requires shared in order to get the handle/stride */
905 dri_use |= __DRI_IMAGE_USE_SHARE;
906
907 bo->image =
908 dri->image->createImage(dri->screen,
909 width, height,
910 dri_format, dri_use,
911 bo);
912 if (bo->image == NULL)
913 goto failed;
914
915 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE,
916 &bo->base.base.handle.s32);
917 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE,
918 (int *) &bo->base.base.stride);
919
920 return &bo->base.base;
921
922 failed:
923 free(bo);
924 return NULL;
925 }
926
927 static struct gbm_surface *
928 gbm_dri_surface_create(struct gbm_device *gbm,
929 uint32_t width, uint32_t height,
930 uint32_t format, uint32_t flags)
931 {
932 struct gbm_dri_surface *surf;
933
934 surf = calloc(1, sizeof *surf);
935 if (surf == NULL)
936 return NULL;
937
938 surf->base.gbm = gbm;
939 surf->base.width = width;
940 surf->base.height = height;
941 surf->base.format = format;
942 surf->base.flags = flags;
943
944 return &surf->base;
945 }
946
947 static void
948 gbm_dri_surface_destroy(struct gbm_surface *_surf)
949 {
950 struct gbm_dri_surface *surf = gbm_dri_surface(_surf);
951
952 free(surf);
953 }
954
955 static void
956 dri_destroy(struct gbm_device *gbm)
957 {
958 struct gbm_dri_device *dri = gbm_dri_device(gbm);
959 unsigned i;
960
961 dri->core->destroyScreen(dri->screen);
962 for (i = 0; dri->driver_configs[i]; i++)
963 free((__DRIconfig *) dri->driver_configs[i]);
964 free(dri->driver_configs);
965 dlclose(dri->driver);
966 free(dri->base.driver_name);
967
968 free(dri);
969 }
970
971 static struct gbm_device *
972 dri_device_create(int fd)
973 {
974 struct gbm_dri_device *dri;
975 int ret, force_sw;
976
977 dri = calloc(1, sizeof *dri);
978 if (!dri)
979 return NULL;
980
981 dri->base.base.fd = fd;
982 dri->base.base.bo_create = gbm_dri_bo_create;
983 dri->base.base.bo_import = gbm_dri_bo_import;
984 dri->base.base.is_format_supported = gbm_dri_is_format_supported;
985 dri->base.base.bo_write = gbm_dri_bo_write;
986 dri->base.base.bo_get_fd = gbm_dri_bo_get_fd;
987 dri->base.base.bo_destroy = gbm_dri_bo_destroy;
988 dri->base.base.destroy = dri_destroy;
989 dri->base.base.surface_create = gbm_dri_surface_create;
990 dri->base.base.surface_destroy = gbm_dri_surface_destroy;
991
992 dri->base.type = GBM_DRM_DRIVER_TYPE_DRI;
993 dri->base.base.name = "drm";
994
995 force_sw = getenv("GBM_ALWAYS_SOFTWARE") != NULL;
996 if (!force_sw) {
997 ret = dri_screen_create(dri);
998 if (ret)
999 ret = dri_screen_create_sw(dri);
1000 } else {
1001 ret = dri_screen_create_sw(dri);
1002 }
1003
1004 if (ret)
1005 goto err_dri;
1006
1007 return &dri->base.base;
1008
1009 err_dri:
1010 free(dri);
1011
1012 return NULL;
1013 }
1014
1015 struct gbm_backend gbm_dri_backend = {
1016 .backend_name = "dri",
1017 .create_device = dri_device_create,
1018 };