use wayland-gbm to create/destroy wl_buffer
[mesa-gbm: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 <limits.h>
34
35 #include <sys/types.h>
36 #include <unistd.h>
37 #include <dlfcn.h>
38
39 #include <GL/gl.h> /* dri_interface needs GL types */
40 #include <GL/internal/dri_interface.h>
41
42 #include "gbm_driint.h"
43
44 #include "gbmint.h"
45
46 static __DRIimage *
47 dri_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
48 {
49    struct gbm_dri_device *dri = data;
50
51    if (dri->lookup_image == NULL)
52       return NULL;
53
54    return dri->lookup_image(screen, image, dri->lookup_user_data);
55 }
56
57 static __DRIbuffer *
58 dri_get_buffers(__DRIdrawable * driDrawable,
59                  int *width, int *height,
60                  unsigned int *attachments, int count,
61                  int *out_count, void *data)
62 {
63    struct gbm_dri_surface *surf = data;
64    struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
65
66    if (dri->get_buffers == NULL)
67       return NULL;
68
69    return dri->get_buffers(driDrawable, width, height, attachments,
70                            count, out_count, surf->dri_private);
71 }
72
73 static void
74 dri_flush_front_buffer(__DRIdrawable * driDrawable, 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->flush_front_buffer != NULL)
80       dri->flush_front_buffer(driDrawable, surf->dri_private);
81 }
82
83 static __DRIbuffer *
84 dri_get_buffers_with_format(__DRIdrawable * driDrawable,
85                             int *width, int *height,
86                             unsigned int *attachments, int count,
87                             int *out_count, 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->get_buffers_with_format == NULL)
93       return NULL;
94
95    return
96       dri->get_buffers_with_format(driDrawable, width, height, attachments,
97                                    count, out_count, surf->dri_private);
98 }
99
100 static const __DRIuseInvalidateExtension use_invalidate = {
101    { __DRI_USE_INVALIDATE, 1 }
102 };
103
104 static const __DRIimageLookupExtension image_lookup_extension = {
105    { __DRI_IMAGE_LOOKUP, 1 },
106    dri_lookup_egl_image
107 };
108
109 const __DRIdri2LoaderExtension dri2_loader_extension = {
110    { __DRI_DRI2_LOADER, 3 },
111    dri_get_buffers,
112    dri_flush_front_buffer,
113    dri_get_buffers_with_format,
114 };
115
116 struct dri_extension_match {
117    const char *name;
118    int version;
119    int offset;
120 };
121
122 static struct dri_extension_match dri_core_extensions[] = {
123    { __DRI2_FLUSH, 1, offsetof(struct gbm_dri_device, flush) },
124    { __DRI_IMAGE, 1, offsetof(struct gbm_dri_device, image) },
125    { NULL, 0, 0 }
126 };
127
128 static struct dri_extension_match gbm_dri_device_extensions[] = {
129    { __DRI_CORE, 1, offsetof(struct gbm_dri_device, core) },
130    { __DRI_DRI2, 1, offsetof(struct gbm_dri_device, dri2) },
131    { NULL, 0, 0 }
132 };
133
134 static int
135 dri_bind_extensions(struct gbm_dri_device *dri,
136                     struct dri_extension_match *matches,
137                     const __DRIextension **extensions)
138 {
139    int i, j, ret = 0;
140    void *field;
141
142    for (i = 0; extensions[i]; i++) {
143       for (j = 0; matches[j].name; j++) {
144          if (strcmp(extensions[i]->name, matches[j].name) == 0 &&
145              extensions[i]->version >= matches[j].version) {
146             field = ((char *) dri + matches[j].offset);
147             *(const __DRIextension **) field = extensions[i];
148          }
149       }
150    }
151
152    for (j = 0; matches[j].name; j++) {
153       field = ((char *) dri + matches[j].offset);
154       if (*(const __DRIextension **) field == NULL) {
155          ret = -1;
156       }
157    }
158
159    return ret;
160 }
161
162 static int
163 dri_load_driver(struct gbm_dri_device *dri)
164 {
165    const __DRIextension **extensions;
166    char path[PATH_MAX], *search_paths, *p, *next, *end;
167
168    search_paths = NULL;
169    if (geteuid() == getuid()) {
170       /* don't allow setuid apps to use GBM_DRIVERS_PATH */
171       search_paths = getenv("GBM_DRIVERS_PATH");
172    }
173    if (search_paths == NULL)
174       search_paths = DEFAULT_DRIVER_DIR;
175
176    dri->driver = NULL;
177    end = search_paths + strlen(search_paths);
178    for (p = search_paths; p < end && dri->driver == NULL; p = next + 1) {
179       int len;
180       next = strchr(p, ':');
181       if (next == NULL)
182          next = end;
183
184       len = next - p;
185 #if GLX_USE_TLS
186       snprintf(path, sizeof path,
187                "%.*s/tls/%s_dri.so", len, p, dri->base.driver_name);
188       dri->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
189 #endif
190       if (dri->driver == NULL) {
191          snprintf(path, sizeof path,
192                   "%.*s/%s_dri.so", len, p, dri->base.driver_name);
193          dri->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
194          if (dri->driver == NULL)
195             fprintf(stderr, "failed to open %s: %s\n", path, dlerror());
196       }
197    }
198
199    if (dri->driver == NULL) {
200       fprintf(stderr, "gbm: failed to open any driver (search paths %s)",
201               search_paths);
202       return -1;
203    }
204
205    extensions = dlsym(dri->driver, __DRI_DRIVER_EXTENSIONS);
206    if (extensions == NULL) {
207       fprintf(stderr, "gbm: driver exports no extensions (%s)", dlerror());
208       dlclose(dri->driver);
209       return -1;
210    }
211
212
213    if (dri_bind_extensions(dri, gbm_dri_device_extensions, extensions) < 0) {
214       dlclose(dri->driver);
215       fprintf(stderr, "failed to bind extensions\n");
216       return -1;
217    }
218
219    return 0;
220 }
221
222 static int
223 dri_screen_create(struct gbm_dri_device *dri)
224 {
225    const __DRIextension **extensions;
226    int ret = 0;
227
228    dri->base.driver_name = dri_fd_get_driver_name(dri->base.base.fd);
229    if (dri->base.driver_name == NULL)
230       return -1;
231
232    ret = dri_load_driver(dri);
233    if (ret) {
234       fprintf(stderr, "failed to load driver: %s\n", dri->base.driver_name);
235       return ret;
236    };
237
238    dri->extensions[0] = &image_lookup_extension.base;
239    dri->extensions[1] = &use_invalidate.base;
240    dri->extensions[2] = &dri2_loader_extension.base;
241    dri->extensions[3] = NULL;
242
243    if (dri->dri2 == NULL)
244       return -1;
245
246    dri->screen = dri->dri2->createNewScreen(0, dri->base.base.fd,
247                                             dri->extensions,
248                                             &dri->driver_configs, dri);
249    if (dri->screen == NULL)
250       return -1;
251
252    extensions = dri->core->getExtensions(dri->screen);
253    if (dri_bind_extensions(dri, dri_core_extensions, extensions) < 0) {
254       ret = -1;
255       goto free_screen;
256    }
257
258    dri->lookup_image = NULL;
259    dri->lookup_user_data = NULL;
260
261    return 0;
262
263 free_screen:
264    dri->core->destroyScreen(dri->screen);
265
266    return ret;
267 }
268
269 static int
270 gbm_dri_is_format_supported(struct gbm_device *gbm,
271                             uint32_t format,
272                             uint32_t usage)
273 {
274    switch (format) {
275    case GBM_BO_FORMAT_XRGB8888:
276    case GBM_FORMAT_XRGB8888:
277       break;
278    case GBM_BO_FORMAT_ARGB8888:
279    case GBM_FORMAT_ARGB8888:
280       if (usage & GBM_BO_USE_SCANOUT)
281          return 0;
282       break;
283    default:
284       return 0;
285    }
286
287    if (usage & GBM_BO_USE_CURSOR_64X64 &&
288        usage & GBM_BO_USE_RENDERING)
289       return 0;
290
291    return 1;
292 }
293
294 static void
295 gbm_dri_bo_destroy(struct gbm_bo *_bo)
296 {
297    struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
298    struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
299
300    dri->image->destroyImage(bo->image);
301    free(bo);
302 }
303
304 static uint32_t
305 gbm_dri_to_gbm_format(uint32_t dri_format)
306 {
307    uint32_t ret = 0;
308
309    switch (dri_format) {
310    case __DRI_IMAGE_FORMAT_RGB565:
311       ret = GBM_FORMAT_RGB565;
312       break;
313    case __DRI_IMAGE_FORMAT_XRGB8888:
314       ret = GBM_FORMAT_XRGB8888;
315       break;
316    case __DRI_IMAGE_FORMAT_ARGB8888:
317       ret = GBM_FORMAT_ARGB8888;
318       break;
319    case __DRI_IMAGE_FORMAT_ABGR8888:
320       ret = GBM_FORMAT_ABGR8888;
321       break;
322    default:
323       ret = 0;
324       break;
325    }
326
327    return ret;
328 }
329
330 static struct gbm_bo *
331 gbm_dri_bo_create_from_egl_image(struct gbm_device *gbm,
332                                  void *egl_dpy, void *egl_img,
333                                  uint32_t width, uint32_t height,
334                                  uint32_t usage)
335 {
336    struct gbm_dri_device *dri = gbm_dri_device(gbm);
337    struct gbm_dri_bo *bo;
338    int dri_format;
339    unsigned dri_use = 0;
340
341    (void) egl_dpy;
342
343    if (dri->lookup_image == NULL)
344       return NULL;
345
346    bo = calloc(1, sizeof *bo);
347    if (bo == NULL)
348       return NULL;
349
350    bo->base.base.gbm = gbm;
351    bo->base.base.width = width;
352    bo->base.base.height = height;
353
354    __DRIimage *tmp = dri->lookup_image(dri->screen, egl_img,
355                                        dri->lookup_user_data);
356
357    bo->image = dri->image->dupImage(tmp, bo);
358    if (bo->image == NULL)
359       return NULL;
360    
361    if (usage & GBM_BO_USE_SCANOUT)
362       dri_use |= __DRI_IMAGE_USE_SCANOUT;
363    if (usage & GBM_BO_USE_CURSOR_64X64)
364       dri_use |= __DRI_IMAGE_USE_CURSOR;
365    if (dri->image->base.version >= 2 &&
366        !dri->image->validateUsage(bo->image, dri_use)) {
367       free(bo);
368       return NULL;
369    }
370
371    dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE,
372                           &bo->base.base.handle.s32);
373    dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE,
374                           (int *) &bo->base.base.pitch);
375    dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_FORMAT,
376                           &dri_format);
377
378    bo->base.base.format = gbm_dri_to_gbm_format(dri_format);
379
380    return &bo->base.base;
381 }
382
383 static struct gbm_bo *
384 gbm_dri_bo_create_from_native_handle(struct gbm_device *gbm,
385                                  union gbm_bo_handle handle, void **image ,
386                                  uint32_t width, uint32_t height, uint32_t stride, 
387                                  uint32_t format, uint32_t usage)
388 {
389    struct gbm_dri_device *dri = gbm_dri_device(gbm);
390    struct gbm_dri_bo *bo;
391    unsigned dri_use = 0;
392    int dri_format;
393    int name;
394
395    name = handle.s32;
396
397    bo = calloc(1, sizeof *bo);
398    if (bo == NULL)
399       return NULL;
400
401    bo->base.base.gbm = gbm;
402    bo->base.base.width = width;
403    bo->base.base.height = height;
404
405    switch (format) {
406    case GBM_BO_FORMAT_XRGB8888:
407       dri_format = __DRI_IMAGE_FORMAT_XRGB8888;
408       break;
409    case GBM_BO_FORMAT_ARGB8888:
410       dri_format = __DRI_IMAGE_FORMAT_ARGB8888;
411       break;
412    default:
413       return NULL;
414    }
415
416     bo->image = dri->image->createImageFromName(dri->screen,
417                      width, height, 
418                      dri_format, name, stride / 4,
419                      NULL);
420     *image = bo->image;
421    
422    if (usage & GBM_BO_USE_SCANOUT)
423       dri_use |= __DRI_IMAGE_USE_SCANOUT;
424    if (usage & GBM_BO_USE_CURSOR_64X64)
425       dri_use |= __DRI_IMAGE_USE_CURSOR;
426
427    if (dri->image->base.version >= 2 &&
428        !dri->image->validateUsage(bo->image, dri_use)) {
429       free(bo);
430       return NULL;
431    }
432
433    dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE,
434                           &bo->base.base.handle.s32);
435    dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE,
436                           (int *) &bo->base.base.pitch);
437
438    return &bo->base.base;
439 }
440
441 static struct gbm_bo *
442 gbm_dri_bo_create(struct gbm_device *gbm,
443                   uint32_t width, uint32_t height,
444                   uint32_t format, uint32_t usage)
445 {
446    struct gbm_dri_device *dri = gbm_dri_device(gbm);
447    struct gbm_dri_bo *bo;
448    int dri_format;
449    unsigned dri_use = 0;
450
451    bo = calloc(1, sizeof *bo);
452    if (bo == NULL)
453       return NULL;
454
455    bo->base.base.gbm = gbm;
456    bo->base.base.width = width;
457    bo->base.base.height = height;
458
459    switch (format) {
460    case GBM_FORMAT_RGB565:
461       dri_format =__DRI_IMAGE_FORMAT_RGB565;
462       break;
463    case GBM_FORMAT_XRGB8888:
464    case GBM_BO_FORMAT_XRGB8888:
465       dri_format = __DRI_IMAGE_FORMAT_XRGB8888;
466       break;
467    case GBM_FORMAT_ARGB8888:
468    case GBM_BO_FORMAT_ARGB8888:
469       dri_format = __DRI_IMAGE_FORMAT_ARGB8888;
470       break;
471    case GBM_FORMAT_ABGR8888:
472       dri_format = __DRI_IMAGE_FORMAT_ABGR8888;
473       break;
474    default:
475       return NULL;
476    }
477
478    if (usage & GBM_BO_USE_SCANOUT)
479       dri_use |= __DRI_IMAGE_USE_SCANOUT;
480    if (usage & GBM_BO_USE_CURSOR_64X64)
481       dri_use |= __DRI_IMAGE_USE_CURSOR;
482
483    bo->image =
484       dri->image->createImage(dri->screen,
485                               width, height,
486                               dri_format, dri_use,
487                               bo);
488    if (bo->image == NULL)
489       return NULL;
490
491    dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE,
492                           &bo->base.base.handle.s32);
493    dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE,
494                           (int *) &bo->base.base.pitch);
495
496    return &bo->base.base;
497 }
498
499 static struct gbm_surface *
500 gbm_dri_surface_create(struct gbm_device *gbm,
501                        uint32_t width, uint32_t height,
502                        uint32_t format, uint32_t flags)
503 {
504    struct gbm_dri_surface *surf;
505
506    surf = calloc(1, sizeof *surf);
507    if (surf == NULL)
508       return NULL;
509
510    surf->base.gbm = gbm;
511    surf->base.width = width;
512    surf->base.height = height;
513    surf->base.format = format;
514    surf->base.flags = flags;
515
516    return &surf->base;
517 }
518
519 static void
520 gbm_dri_surface_destroy(struct gbm_surface *_surf)
521 {
522    struct gbm_dri_surface *surf = gbm_dri_surface(_surf);
523
524    free(surf);
525 }
526
527 static void
528 dri_destroy(struct gbm_device *gbm)
529 {
530    struct gbm_dri_device *dri = gbm_dri_device(gbm);
531
532    dri->core->destroyScreen(dri->screen);
533    free(dri->driver_configs);
534    dlclose(dri->driver);
535    free(dri->base.driver_name);
536
537    free(dri);
538 }
539
540 static struct gbm_device *
541 dri_device_create(int fd)
542 {
543    struct gbm_dri_device *dri;
544    int ret;
545
546    dri = calloc(1, sizeof *dri);
547
548    dri->base.base.fd = fd;
549    dri->base.base.bo_create = gbm_dri_bo_create;
550    dri->base.base.bo_create_from_egl_image = gbm_dri_bo_create_from_egl_image;
551    dri->base.base.bo_create_from_native_handle = gbm_dri_bo_create_from_native_handle;
552    dri->base.base.is_format_supported = gbm_dri_is_format_supported;
553    dri->base.base.bo_destroy = gbm_dri_bo_destroy;
554    dri->base.base.destroy = dri_destroy;
555    dri->base.base.surface_create = gbm_dri_surface_create;
556    dri->base.base.surface_destroy = gbm_dri_surface_destroy;
557
558    dri->base.type = GBM_DRM_DRIVER_TYPE_DRI;
559    dri->base.base.name = "drm";
560
561    ret = dri_screen_create(dri);
562    if (ret) {
563       free(dri);
564       return NULL;
565    }
566
567    return &dri->base.base;
568 }
569
570 struct gbm_backend gbm_dri_backend = {
571    .backend_name = "dri",
572    .create_device = dri_device_create,
573 };