blob: 6227bc94cd5bcb05a7206046fb158af69c57c9c3 [file] [log] [blame]
Kristian Høgsberg9dc5de52011-02-02 22:21:13 -05001/*
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 * Kristian Høgsberg <krh@bitplanet.net>
26 */
27
28#include <stdlib.h>
Kristian Høgsberg9dc5de52011-02-02 22:21:13 -050029#include <stdio.h>
Benjamin Franzke7f881c42011-05-30 10:49:55 +020030#include <string.h>
Kristian Høgsberg9dc5de52011-02-02 22:21:13 -050031#include <xf86drm.h>
Benjamin Franzkeac3c2c82011-06-07 22:19:21 +020032#include <dlfcn.h>
Benjamin Franzke32f4cf32011-06-29 08:49:39 +020033#include <sys/types.h>
34#include <sys/stat.h>
35#include <fcntl.h>
36#include <unistd.h>
Kristian Høgsberg9dc5de52011-02-02 22:21:13 -050037
38#include "egl_dri2.h"
Chad Versace8b9298a2014-01-28 12:34:19 -080039#include "egl_dri2_fallbacks.h"
Emil Velikov8d4357b2014-01-11 04:52:48 +000040#include "loader.h"
Kristian Høgsberg9dc5de52011-02-02 22:21:13 -050041
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +020042static struct gbm_bo *
43lock_front_buffer(struct gbm_surface *_surf)
44{
45 struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
46 struct dri2_egl_surface *dri2_surf = surf->dri_private;
47 struct gbm_bo *bo;
48
49 if (dri2_surf->current == NULL) {
50 _eglError(EGL_BAD_SURFACE, "no front buffer");
51 return NULL;
52 }
53
54 bo = dri2_surf->current->bo;
55 dri2_surf->current->locked = 1;
56 dri2_surf->current = NULL;
57
58 return bo;
59}
60
61static void
62release_buffer(struct gbm_surface *_surf, struct gbm_bo *bo)
63{
64 struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
65 struct dri2_egl_surface *dri2_surf = surf->dri_private;
66 int i;
67
68 for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
69 if (dri2_surf->color_buffers[i].bo == bo) {
70 dri2_surf->color_buffers[i].locked = 0;
71 }
72 }
73}
74
75static int
76has_free_buffers(struct gbm_surface *_surf)
77{
78 struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
79 struct dri2_egl_surface *dri2_surf = surf->dri_private;
80 int i;
81
82 for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
83 if (!dri2_surf->color_buffers[i].locked)
84 return 1;
85
86 return 0;
87}
88
89static _EGLSurface *
Chad Versaced019cd82014-01-28 12:47:38 -080090dri2_drm_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
Chad Versace6d1f83e2014-01-07 14:54:51 -080091 _EGLConfig *conf, void *native_window,
Chad Versaced019cd82014-01-28 12:47:38 -080092 const EGLint *attrib_list)
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +020093{
94 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
95 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
96 struct dri2_egl_surface *dri2_surf;
Chad Versace6d1f83e2014-01-07 14:54:51 -080097 struct gbm_surface *window = native_window;
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +020098 struct gbm_dri_surface *surf;
99
100 (void) drv;
101
Matt Turner6bda0272012-09-04 23:09:22 -0700102 dri2_surf = calloc(1, sizeof *dri2_surf);
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200103 if (!dri2_surf) {
104 _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
105 return NULL;
106 }
107
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200108 if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
109 goto cleanup_surf;
110
111 switch (type) {
112 case EGL_WINDOW_BIT:
Elvis Leecf775c92012-07-11 11:13:51 +0900113 if (!window)
114 return NULL;
Chad Versace6d1f83e2014-01-07 14:54:51 -0800115 surf = gbm_dri_surface(window);
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200116 dri2_surf->gbm_surf = surf;
117 dri2_surf->base.Width = surf->base.width;
118 dri2_surf->base.Height = surf->base.height;
119 surf->dri_private = dri2_surf;
120 break;
121 default:
122 goto cleanup_surf;
123 }
124
125 dri2_surf->dri_drawable =
126 (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
127 dri2_conf->dri_double_config,
128 dri2_surf->gbm_surf);
129
130 if (dri2_surf->dri_drawable == NULL) {
131 _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
132 goto cleanup_surf;
133 }
134
135 return &dri2_surf->base;
136
137 cleanup_surf:
138 free(dri2_surf);
139
140 return NULL;
141}
142
143static _EGLSurface *
Chad Versaced019cd82014-01-28 12:47:38 -0800144dri2_drm_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
Chad Versace6d1f83e2014-01-07 14:54:51 -0800145 _EGLConfig *conf, void *native_window,
Chad Versaced019cd82014-01-28 12:47:38 -0800146 const EGLint *attrib_list)
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200147{
Chad Versaced019cd82014-01-28 12:47:38 -0800148 return dri2_drm_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
Chad Versace6d1f83e2014-01-07 14:54:51 -0800149 native_window, attrib_list);
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200150}
151
Chad Versace1787f562014-02-09 09:13:08 -0800152static _EGLSurface *
153dri2_drm_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
154 _EGLConfig *conf, void *native_window,
155 const EGLint *attrib_list)
156{
157 /* From the EGL_MESA_platform_gbm spec, version 5:
158 *
159 * It is not valid to call eglCreatePlatformPixmapSurfaceEXT with a <dpy>
160 * that belongs to the GBM platform. Any such call fails and generates
161 * EGL_BAD_PARAMETER.
162 */
163 _eglError(EGL_BAD_PARAMETER, "cannot create EGL pixmap surfaces on GBM");
164 return NULL;
165}
166
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200167static EGLBoolean
Chad Versaced019cd82014-01-28 12:47:38 -0800168dri2_drm_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200169{
170 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
171 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
172 int i;
173
174 if (!_eglPutSurface(surf))
175 return EGL_TRUE;
176
177 (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
178
179 for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
180 if (dri2_surf->color_buffers[i].bo)
181 gbm_bo_destroy(dri2_surf->color_buffers[i].bo);
182 }
183
184 for (i = 0; i < __DRI_BUFFER_COUNT; i++) {
185 if (dri2_surf->dri_buffers[i])
186 dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
187 dri2_surf->dri_buffers[i]);
188 }
189
190 free(surf);
191
192 return EGL_TRUE;
193}
194
195static int
Kristian Høgsberg04e3ef02013-11-08 22:06:51 -0800196get_back_bo(struct dri2_egl_surface *dri2_surf)
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200197{
198 struct dri2_egl_display *dri2_dpy =
199 dri2_egl_display(dri2_surf->base.Resource.Display);
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200200 struct gbm_dri_surface *surf = dri2_surf->gbm_surf;
Kristian Høgsberg04e3ef02013-11-08 22:06:51 -0800201 int i;
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200202
203 if (dri2_surf->back == NULL) {
204 for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
205 if (!dri2_surf->color_buffers[i].locked) {
206 dri2_surf->back = &dri2_surf->color_buffers[i];
207 break;
208 }
209 }
210 }
211
212 if (dri2_surf->back == NULL)
213 return -1;
214 if (dri2_surf->back->bo == NULL)
215 dri2_surf->back->bo = gbm_bo_create(&dri2_dpy->gbm_dri->base.base,
216 surf->base.width, surf->base.height,
217 surf->base.format, surf->base.flags);
218 if (dri2_surf->back->bo == NULL)
219 return -1;
220
Kristian Høgsberg04e3ef02013-11-08 22:06:51 -0800221 return 0;
222}
223
224static void
225back_bo_to_dri_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
226{
227 struct dri2_egl_display *dri2_dpy =
228 dri2_egl_display(dri2_surf->base.Resource.Display);
229 struct gbm_dri_bo *bo;
230 int name, pitch;
231
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200232 bo = (struct gbm_dri_bo *) dri2_surf->back->bo;
233
234 dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_NAME, &name);
235 dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
236
237 buffer->attachment = __DRI_BUFFER_BACK_LEFT;
238 buffer->name = name;
239 buffer->pitch = pitch;
240 buffer->cpp = 4;
241 buffer->flags = 0;
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200242}
243
244static int
245get_aux_bo(struct dri2_egl_surface *dri2_surf,
246 unsigned int attachment, unsigned int format, __DRIbuffer *buffer)
247{
248 struct dri2_egl_display *dri2_dpy =
249 dri2_egl_display(dri2_surf->base.Resource.Display);
Mandeep Singh Baines0695cf62012-04-10 14:48:14 -0700250 __DRIbuffer *b = dri2_surf->dri_buffers[attachment];
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200251
Mandeep Singh Baines0695cf62012-04-10 14:48:14 -0700252 if (b == NULL) {
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200253 b = dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
254 attachment, format,
255 dri2_surf->base.Width,
256 dri2_surf->base.Height);
Mandeep Singh Baines0695cf62012-04-10 14:48:14 -0700257 dri2_surf->dri_buffers[attachment] = b;
258 }
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200259 if (b == NULL)
260 return -1;
261
262 memcpy(buffer, b, sizeof *buffer);
263
264 return 0;
265}
266
267static __DRIbuffer *
Chad Versaced019cd82014-01-28 12:47:38 -0800268dri2_drm_get_buffers_with_format(__DRIdrawable *driDrawable,
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200269 int *width, int *height,
270 unsigned int *attachments, int count,
271 int *out_count, void *loaderPrivate)
272{
273 struct dri2_egl_surface *dri2_surf = loaderPrivate;
274 int i, j;
275
276 dri2_surf->buffer_count = 0;
277 for (i = 0, j = 0; i < 2 * count; i += 2, j++) {
278 assert(attachments[i] < __DRI_BUFFER_COUNT);
279 assert(dri2_surf->buffer_count < 5);
280
281 switch (attachments[i]) {
282 case __DRI_BUFFER_BACK_LEFT:
Kristian Høgsberg04e3ef02013-11-08 22:06:51 -0800283 if (get_back_bo(dri2_surf) < 0) {
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200284 _eglError(EGL_BAD_ALLOC, "failed to allocate color buffer");
285 return NULL;
286 }
Kristian Høgsberg04e3ef02013-11-08 22:06:51 -0800287 back_bo_to_dri_buffer(dri2_surf, &dri2_surf->buffers[j]);
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200288 break;
289 default:
290 if (get_aux_bo(dri2_surf, attachments[i], attachments[i + 1],
291 &dri2_surf->buffers[j]) < 0) {
292 _eglError(EGL_BAD_ALLOC, "failed to allocate aux buffer");
293 return NULL;
294 }
295 break;
296 }
297 }
298
299 *out_count = j;
300 if (j == 0)
301 return NULL;
302
303 *width = dri2_surf->base.Width;
304 *height = dri2_surf->base.Height;
305
306 return dri2_surf->buffers;
307}
308
309static __DRIbuffer *
Chad Versaced019cd82014-01-28 12:47:38 -0800310dri2_drm_get_buffers(__DRIdrawable * driDrawable,
311 int *width, int *height,
312 unsigned int *attachments, int count,
313 int *out_count, void *loaderPrivate)
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200314{
315 unsigned int *attachments_with_format;
316 __DRIbuffer *buffer;
317 const unsigned int format = 32;
318 int i;
319
320 attachments_with_format = calloc(count * 2, sizeof(unsigned int));
321 if (!attachments_with_format) {
322 *out_count = 0;
323 return NULL;
324 }
325
326 for (i = 0; i < count; ++i) {
327 attachments_with_format[2*i] = attachments[i];
328 attachments_with_format[2*i + 1] = format;
329 }
330
331 buffer =
Chad Versaced019cd82014-01-28 12:47:38 -0800332 dri2_drm_get_buffers_with_format(driDrawable,
333 width, height,
334 attachments_with_format, count,
335 out_count, loaderPrivate);
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200336
337 free(attachments_with_format);
338
339 return buffer;
340}
341
Kristian Høgsberg04e3ef02013-11-08 22:06:51 -0800342static int
Chad Versaced019cd82014-01-28 12:47:38 -0800343dri2_drm_image_get_buffers(__DRIdrawable *driDrawable,
344 unsigned int format,
345 uint32_t *stamp,
346 void *loaderPrivate,
347 uint32_t buffer_mask,
348 struct __DRIimageList *buffers)
Kristian Høgsberg04e3ef02013-11-08 22:06:51 -0800349{
350 struct dri2_egl_surface *dri2_surf = loaderPrivate;
351 struct gbm_dri_bo *bo;
352
353 if (get_back_bo(dri2_surf) < 0)
354 return 0;
355
356 bo = (struct gbm_dri_bo *) dri2_surf->back->bo;
357 buffers->image_mask = __DRI_IMAGE_BUFFER_BACK;
358 buffers->back = bo->image;
359
360 return 1;
361}
362
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200363static void
Chad Versaced019cd82014-01-28 12:47:38 -0800364dri2_drm_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200365{
366 (void) driDrawable;
367 (void) loaderPrivate;
368}
369
370static EGLBoolean
Chad Versaced019cd82014-01-28 12:47:38 -0800371dri2_drm_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200372{
373 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
374 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
Kristian Høgsberg4e42e562012-12-13 23:39:45 -0500375 int i;
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200376
377 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
378 if (dri2_surf->current)
379 _eglError(EGL_BAD_SURFACE, "dri2_swap_buffers");
Kristian Høgsberg4e42e562012-12-13 23:39:45 -0500380 for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
381 if (dri2_surf->color_buffers[i].age > 0)
382 dri2_surf->color_buffers[i].age++;
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200383 dri2_surf->current = dri2_surf->back;
Kristian Høgsberg4e42e562012-12-13 23:39:45 -0500384 dri2_surf->current->age = 1;
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200385 dri2_surf->back = NULL;
386 }
387
388 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
389 (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
390
391 return EGL_TRUE;
392}
393
Kristian Høgsberg4e42e562012-12-13 23:39:45 -0500394static EGLint
Chad Versaced019cd82014-01-28 12:47:38 -0800395dri2_drm_query_buffer_age(_EGLDriver *drv,
396 _EGLDisplay *disp, _EGLSurface *surface)
Kristian Høgsberg4e42e562012-12-13 23:39:45 -0500397{
398 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
Kristian Høgsberg4e42e562012-12-13 23:39:45 -0500399
Kristian Høgsberg04e3ef02013-11-08 22:06:51 -0800400 if (get_back_bo(dri2_surf) < 0) {
Kristian Høgsberg4e42e562012-12-13 23:39:45 -0500401 _eglError(EGL_BAD_ALLOC, "dri2_query_buffer_age");
402 return 0;
403 }
404
405 return dri2_surf->back->age;
406}
407
Benjamin Franzkee5fc4c82011-05-30 10:50:52 +0200408static _EGLImage *
Chad Versaced019cd82014-01-28 12:47:38 -0800409dri2_drm_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
410 EGLClientBuffer buffer, const EGLint *attr_list)
Benjamin Franzkee5fc4c82011-05-30 10:50:52 +0200411{
412 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
413 struct gbm_dri_bo *dri_bo = gbm_dri_bo((struct gbm_bo *) buffer);
414 struct dri2_egl_image *dri2_img;
415
416 dri2_img = malloc(sizeof *dri2_img);
417 if (!dri2_img) {
418 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
419 return NULL;
420 }
421
422 if (!_eglInitImage(&dri2_img->base, disp)) {
423 free(dri2_img);
424 return NULL;
425 }
426
427 dri2_img->dri_image = dri2_dpy->image->dupImage(dri_bo->image, dri2_img);
428 if (dri2_img->dri_image == NULL) {
429 free(dri2_img);
430 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
431 return NULL;
432 }
433
434 return &dri2_img->base;
435}
436
437static _EGLImage *
438dri2_drm_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
439 _EGLContext *ctx, EGLenum target,
440 EGLClientBuffer buffer, const EGLint *attr_list)
441{
442 (void) drv;
443
444 switch (target) {
445 case EGL_NATIVE_PIXMAP_KHR:
Chad Versaced019cd82014-01-28 12:47:38 -0800446 return dri2_drm_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
Benjamin Franzkee5fc4c82011-05-30 10:50:52 +0200447 default:
448 return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
449 }
450}
451
Benjamin Franzke6b369c42011-02-21 16:22:34 +0100452static int
453dri2_drm_authenticate(_EGLDisplay *disp, uint32_t id)
454{
455 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
456
457 return drmAuthMagic(dri2_dpy->fd, id);
458}
459
Chad Versace90502b12014-01-28 11:41:46 -0800460static struct dri2_egl_display_vtbl dri2_drm_display_vtbl = {
461 .authenticate = dri2_drm_authenticate,
Chad Versace0a0c8812014-01-28 16:39:09 -0800462 .create_window_surface = dri2_drm_create_window_surface,
Chad Versace1787f562014-02-09 09:13:08 -0800463 .create_pixmap_surface = dri2_drm_create_pixmap_surface,
Chad Versacebf200762014-01-28 17:03:03 -0800464 .create_pbuffer_surface = dri2_fallback_create_pbuffer_surface,
Chad Versace958dd802014-01-28 17:03:03 -0800465 .destroy_surface = dri2_drm_destroy_surface,
Chad Versaceeef68a92014-01-28 17:03:03 -0800466 .create_image = dri2_drm_create_image_khr,
Chad Versace8b9298a2014-01-28 12:34:19 -0800467 .swap_interval = dri2_fallback_swap_interval,
Chad Versacead173bc2014-01-28 16:21:21 -0800468 .swap_buffers = dri2_drm_swap_buffers,
Chad Versaced03948a2014-01-28 16:26:44 -0800469 .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage,
Chad Versace75d398e2014-01-28 17:03:03 -0800470 .swap_buffers_region = dri2_fallback_swap_buffers_region,
Chad Versace688a0e82014-01-28 17:03:03 -0800471 .post_sub_buffer = dri2_fallback_post_sub_buffer,
Chad Versacebc2cbc02014-01-28 17:03:03 -0800472 .copy_buffers = dri2_fallback_copy_buffers,
Chad Versace3fdfbd22014-01-28 17:03:03 -0800473 .query_buffer_age = dri2_drm_query_buffer_age,
Chad Versaceeadd5e02014-01-28 17:03:03 -0800474 .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
Sarah Sharpc524f3e2014-05-06 12:10:57 -0700475 .get_sync_values = dri2_fallback_get_sync_values,
Chad Versace90502b12014-01-28 11:41:46 -0800476};
477
Kristian Høgsberg9dc5de52011-02-02 22:21:13 -0500478EGLBoolean
479dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
480{
481 struct dri2_egl_display *dri2_dpy;
Benjamin Franzkee5fc4c82011-05-30 10:50:52 +0200482 struct gbm_device *gbm;
Benjamin Franzke32f4cf32011-06-29 08:49:39 +0200483 int fd = -1;
Kristian Høgsberg9dc5de52011-02-02 22:21:13 -0500484 int i;
485
Emil Velikov8d4357b2014-01-11 04:52:48 +0000486 loader_set_logger(_eglLog);
487
Matt Turner6bda0272012-09-04 23:09:22 -0700488 dri2_dpy = calloc(1, sizeof *dri2_dpy);
Kristian Høgsberg9dc5de52011-02-02 22:21:13 -0500489 if (!dri2_dpy)
490 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
Benjamin Franzkee5fc4c82011-05-30 10:50:52 +0200491
Kristian Høgsberg9dc5de52011-02-02 22:21:13 -0500492 disp->DriverData = (void *) dri2_dpy;
Kristian Høgsberg9dc5de52011-02-02 22:21:13 -0500493
Benjamin Franzke32f4cf32011-06-29 08:49:39 +0200494 gbm = disp->PlatformDisplay;
495 if (gbm == NULL) {
Jonathan Grayc973e442014-04-03 16:22:26 +1100496 char buf[64];
497 int n = snprintf(buf, sizeof(buf), DRM_DEV_NAME, DRM_DIR_NAME, 0);
498 if (n != -1 && n < sizeof(buf))
499 fd = open(buf, O_RDWR);
500 if (fd < 0)
501 fd = open("/dev/dri/card0", O_RDWR);
Benjamin Franzke2a584532011-12-13 14:43:48 +0100502 dri2_dpy->own_device = 1;
Benjamin Franzke32f4cf32011-06-29 08:49:39 +0200503 gbm = gbm_create_device(fd);
504 if (gbm == NULL)
505 return EGL_FALSE;
506 }
507
Benjamin Franzkee5fc4c82011-05-30 10:50:52 +0200508 if (strcmp(gbm_device_get_backend_name(gbm), "drm") != 0) {
509 free(dri2_dpy);
510 return EGL_FALSE;
Benjamin Franzke6b369c42011-02-21 16:22:34 +0100511 }
512
Benjamin Franzkee5fc4c82011-05-30 10:50:52 +0200513 dri2_dpy->gbm_dri = gbm_dri_device(gbm);
514 if (dri2_dpy->gbm_dri->base.type != GBM_DRM_DRIVER_TYPE_DRI) {
515 free(dri2_dpy);
516 return EGL_FALSE;
517 }
Kristian Høgsberg9dc5de52011-02-02 22:21:13 -0500518
Benjamin Franzke32f4cf32011-06-29 08:49:39 +0200519 if (fd < 0) {
520 fd = dup(gbm_device_get_fd(gbm));
521 if (fd < 0) {
522 free(dri2_dpy);
523 return EGL_FALSE;
524 }
525 }
526
527 dri2_dpy->fd = fd;
Emil Velikov8d4357b2014-01-11 04:52:48 +0000528 dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd);
Emil Velikov5cb1cad2014-06-02 12:26:17 +0100529 dri2_dpy->driver_name = strdup(dri2_dpy->gbm_dri->base.driver_name);
Kristian Høgsberg9dc5de52011-02-02 22:21:13 -0500530
Benjamin Franzkee5fc4c82011-05-30 10:50:52 +0200531 dri2_dpy->dri_screen = dri2_dpy->gbm_dri->screen;
532 dri2_dpy->core = dri2_dpy->gbm_dri->core;
533 dri2_dpy->dri2 = dri2_dpy->gbm_dri->dri2;
534 dri2_dpy->image = dri2_dpy->gbm_dri->image;
Ander Conselvan de Oliveira410aa3e2012-01-25 16:24:15 +0200535 dri2_dpy->flush = dri2_dpy->gbm_dri->flush;
Benjamin Franzkee5fc4c82011-05-30 10:50:52 +0200536 dri2_dpy->driver_configs = dri2_dpy->gbm_dri->driver_configs;
537
538 dri2_dpy->gbm_dri->lookup_image = dri2_lookup_egl_image;
539 dri2_dpy->gbm_dri->lookup_user_data = disp;
540
Chad Versaced019cd82014-01-28 12:47:38 -0800541 dri2_dpy->gbm_dri->get_buffers = dri2_drm_get_buffers;
542 dri2_dpy->gbm_dri->flush_front_buffer = dri2_drm_flush_front_buffer;
543 dri2_dpy->gbm_dri->get_buffers_with_format = dri2_drm_get_buffers_with_format;
544 dri2_dpy->gbm_dri->image_get_buffers = dri2_drm_image_get_buffers;
Ander Conselvan de Oliveira4a976b62012-01-25 16:24:17 +0200545
546 dri2_dpy->gbm_dri->base.base.surface_lock_front_buffer = lock_front_buffer;
547 dri2_dpy->gbm_dri->base.base.surface_release_buffer = release_buffer;
548 dri2_dpy->gbm_dri->base.base.surface_has_free_buffers = has_free_buffers;
549
Benjamin Franzkee5fc4c82011-05-30 10:50:52 +0200550 dri2_setup_screen(disp);
Kristian Høgsberg9dc5de52011-02-02 22:21:13 -0500551
Kristian Høgsbergdf479cf2013-09-25 14:57:22 -0700552 for (i = 0; dri2_dpy->driver_configs[i]; i++) {
553 EGLint format, attr_list[3];
554 unsigned int mask;
555
556 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
557 __DRI_ATTRIB_RED_MASK, &mask);
558 if (mask == 0x3ff00000)
559 format = GBM_FORMAT_XRGB2101010;
560 else if (mask == 0x00ff0000)
561 format = GBM_FORMAT_XRGB8888;
562 else if (mask == 0xf800)
563 format = GBM_FORMAT_RGB565;
564 else
565 continue;
566
567 attr_list[0] = EGL_NATIVE_VISUAL_ID;
568 attr_list[1] = format;
569 attr_list[2] = EGL_NONE;
570
Benjamin Franzkee5fc4c82011-05-30 10:50:52 +0200571 dri2_add_config(disp, dri2_dpy->driver_configs[i],
Kristian Høgsbergdf479cf2013-09-25 14:57:22 -0700572 i + 1, EGL_WINDOW_BIT, attr_list, NULL);
573 }
Benjamin Franzkee5fc4c82011-05-30 10:50:52 +0200574
Kristian Høgsberg4e42e562012-12-13 23:39:45 -0500575 disp->Extensions.EXT_buffer_age = EGL_TRUE;
Kristian Høgsberg9dc5de52011-02-02 22:21:13 -0500576
Benjamin Franzke6b369c42011-02-21 16:22:34 +0100577#ifdef HAVE_WAYLAND_PLATFORM
578 disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
579#endif
Benjamin Franzkee5fc4c82011-05-30 10:50:52 +0200580
Kristian Høgsberg9dc5de52011-02-02 22:21:13 -0500581 /* we're supporting EGL 1.4 */
582 disp->VersionMajor = 1;
583 disp->VersionMinor = 4;
584
Chad Versace90502b12014-01-28 11:41:46 -0800585 /* Fill vtbl last to prevent accidentally calling virtual function during
586 * initialization.
587 */
588 dri2_dpy->vtbl = &dri2_drm_display_vtbl;
589
Kristian Høgsberg9dc5de52011-02-02 22:21:13 -0500590 return EGL_TRUE;
Kristian Høgsberg9dc5de52011-02-02 22:21:13 -0500591}