blob: 7d921f84ef995752d45e8375dc215bc4f6489e30 [file] [log] [blame]
Kristian Høgsberg2889d962011-02-02 22:10:40 -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
Chad Versace31cd0fe2014-01-28 18:52:00 -080028#include <stdbool.h>
Emil Velikovbf0e4d22015-02-28 17:12:40 +000029#include <stdint.h>
Kristian Høgsberg2889d962011-02-02 22:10:40 -050030#include <stdlib.h>
31#include <string.h>
32#include <stdio.h>
33#include <limits.h>
34#include <dlfcn.h>
35#include <fcntl.h>
36#include <errno.h>
37#include <unistd.h>
Tapani Pällia057b832013-12-01 11:53:55 +020038#ifdef HAVE_LIBDRM
Kristian Høgsberg2889d962011-02-02 22:10:40 -050039#include <xf86drm.h>
Samuel Thibaulta594cec2013-11-10 19:32:01 +010040#endif
Kristian Høgsberg2889d962011-02-02 22:10:40 -050041#include <sys/types.h>
42#include <sys/stat.h>
43
44#include "egl_dri2.h"
Chad Versace8b9298a2014-01-28 12:34:19 -080045#include "egl_dri2_fallbacks.h"
Derek Foreman4f8f7902015-06-17 11:28:51 -050046#include "loader.h"
Kristian Høgsberg2889d962011-02-02 22:10:40 -050047
Boyan Dingf35198b2015-07-21 23:44:00 +080048#ifdef HAVE_DRI3
49#include "platform_x11_dri3.h"
50#endif
51
Chad Versacea2187652014-01-27 16:42:10 -080052static EGLBoolean
53dri2_x11_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
54 EGLint interval);
55
Haitao Fengf55d0272011-02-16 23:05:15 -050056static void
57swrastCreateDrawable(struct dri2_egl_display * dri2_dpy,
José Fonseca11a955a2015-01-19 23:07:17 +000058 struct dri2_egl_surface * dri2_surf)
Haitao Fengf55d0272011-02-16 23:05:15 -050059{
60 uint32_t mask;
61 const uint32_t function = GXcopy;
62 uint32_t valgc[2];
Boyan Ding052b3d42015-06-13 15:36:27 +080063
Haitao Fengf55d0272011-02-16 23:05:15 -050064 /* create GC's */
65 dri2_surf->gc = xcb_generate_id(dri2_dpy->conn);
66 mask = XCB_GC_FUNCTION;
67 xcb_create_gc(dri2_dpy->conn, dri2_surf->gc, dri2_surf->drawable, mask, &function);
68
69 dri2_surf->swapgc = xcb_generate_id(dri2_dpy->conn);
70 mask = XCB_GC_FUNCTION | XCB_GC_GRAPHICS_EXPOSURES;
71 valgc[0] = function;
72 valgc[1] = False;
73 xcb_create_gc(dri2_dpy->conn, dri2_surf->swapgc, dri2_surf->drawable, mask, valgc);
José Fonseca11a955a2015-01-19 23:07:17 +000074 switch (dri2_surf->depth) {
Haitao Fengf55d0272011-02-16 23:05:15 -050075 case 32:
76 case 24:
77 dri2_surf->bytes_per_pixel = 4;
78 break;
79 case 16:
80 dri2_surf->bytes_per_pixel = 2;
81 break;
82 case 8:
83 dri2_surf->bytes_per_pixel = 1;
84 break;
85 case 0:
86 dri2_surf->bytes_per_pixel = 0;
87 break;
88 default:
José Fonseca11a955a2015-01-19 23:07:17 +000089 _eglLog(_EGL_WARNING, "unsupported depth %d", dri2_surf->depth);
Haitao Fengf55d0272011-02-16 23:05:15 -050090 }
91}
92
93static void
94swrastDestroyDrawable(struct dri2_egl_display * dri2_dpy,
95 struct dri2_egl_surface * dri2_surf)
96{
97 xcb_free_gc(dri2_dpy->conn, dri2_surf->gc);
98 xcb_free_gc(dri2_dpy->conn, dri2_surf->swapgc);
99}
100
101static void
102swrastGetDrawableInfo(__DRIdrawable * draw,
103 int *x, int *y, int *w, int *h,
104 void *loaderPrivate)
105{
106 struct dri2_egl_surface *dri2_surf = loaderPrivate;
107 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
108
109 xcb_get_geometry_cookie_t cookie;
110 xcb_get_geometry_reply_t *reply;
111 xcb_generic_error_t *error;
112
113 *w = *h = 0;
114 cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable);
115 reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error);
116 if (reply == NULL)
117 return;
118
119 if (error != NULL) {
120 _eglLog(_EGL_WARNING, "error in xcb_get_geometry");
121 free(error);
122 } else {
123 *w = reply->width;
124 *h = reply->height;
125 }
126 free(reply);
127}
128
129static void
130swrastPutImage(__DRIdrawable * draw, int op,
131 int x, int y, int w, int h,
132 char *data, void *loaderPrivate)
133{
134 struct dri2_egl_surface *dri2_surf = loaderPrivate;
135 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
136
137 xcb_gcontext_t gc;
138
139 switch (op) {
140 case __DRI_SWRAST_IMAGE_OP_DRAW:
141 gc = dri2_surf->gc;
142 break;
143 case __DRI_SWRAST_IMAGE_OP_SWAP:
144 gc = dri2_surf->swapgc;
145 break;
146 default:
147 return;
148 }
149
150 xcb_put_image(dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, dri2_surf->drawable,
151 gc, w, h, x, y, 0, dri2_surf->depth,
152 w*h*dri2_surf->bytes_per_pixel, (const uint8_t *)data);
153}
154
155static void
156swrastGetImage(__DRIdrawable * read,
157 int x, int y, int w, int h,
158 char *data, void *loaderPrivate)
159{
160 struct dri2_egl_surface *dri2_surf = loaderPrivate;
161 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
162
163 xcb_get_image_cookie_t cookie;
164 xcb_get_image_reply_t *reply;
165 xcb_generic_error_t *error;
166
167 cookie = xcb_get_image (dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP,
168 dri2_surf->drawable, x, y, w, h, ~0);
169 reply = xcb_get_image_reply (dri2_dpy->conn, cookie, &error);
170 if (reply == NULL)
171 return;
172
173 if (error != NULL) {
174 _eglLog(_EGL_WARNING, "error in xcb_get_image");
175 free(error);
176 } else {
177 uint32_t bytes = xcb_get_image_data_length(reply);
178 uint8_t *idata = xcb_get_image_data(reply);
179 memcpy(data, idata, bytes);
180 }
181 free(reply);
182}
183
184
Marek Olšák0b56e232014-08-20 00:33:34 +0200185static xcb_screen_t *
186get_xcb_screen(xcb_screen_iterator_t iter, int screen)
187{
188 for (; iter.rem; --screen, xcb_screen_next(&iter))
189 if (screen == 0)
190 return iter.data;
191
192 return NULL;
193}
194
195
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500196/**
197 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
198 */
199static _EGLSurface *
Chad Versaced019cd82014-01-28 12:47:38 -0800200dri2_x11_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
Chad Versace6d1f83e2014-01-07 14:54:51 -0800201 _EGLConfig *conf, void *native_surface,
Chad Versaced019cd82014-01-28 12:47:38 -0800202 const EGLint *attrib_list)
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500203{
204 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
205 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
206 struct dri2_egl_surface *dri2_surf;
207 xcb_get_geometry_cookie_t cookie;
208 xcb_get_geometry_reply_t *reply;
209 xcb_screen_iterator_t s;
210 xcb_generic_error_t *error;
Chad Versace6d1f83e2014-01-07 14:54:51 -0800211 xcb_drawable_t drawable;
Juha-Pekka Heikkila4ed23fd2014-09-08 15:03:35 +0300212 xcb_screen_t *screen;
Emil Velikov4ea5ed92015-09-13 12:36:54 +0100213 const __DRIconfig *config;
Chad Versace6d1f83e2014-01-07 14:54:51 -0800214
215 STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_surface));
216 drawable = (uintptr_t) native_surface;
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500217
218 (void) drv;
219
220 dri2_surf = malloc(sizeof *dri2_surf);
221 if (!dri2_surf) {
222 _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
223 return NULL;
224 }
225
226 if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
227 goto cleanup_surf;
228
229 dri2_surf->region = XCB_NONE;
230 if (type == EGL_PBUFFER_BIT) {
Tapani Pälli3386e952014-09-29 15:02:57 +0300231 s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
Juha-Pekka Heikkila4ed23fd2014-09-08 15:03:35 +0300232 screen = get_xcb_screen(s, dri2_dpy->screen);
233 if (!screen) {
Frank Binns2900e8c2015-08-04 14:32:43 +0100234 _eglError(EGL_BAD_ALLOC, "failed to get xcb screen");
Juha-Pekka Heikkila4ed23fd2014-09-08 15:03:35 +0300235 goto cleanup_surf;
236 }
237
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500238 dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn);
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500239 xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize,
Juha-Pekka Heikkila4ed23fd2014-09-08 15:03:35 +0300240 dri2_surf->drawable, screen->root,
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500241 dri2_surf->base.Width, dri2_surf->base.Height);
242 } else {
Emil Velikovaf2aea42015-06-18 20:39:28 +0100243 if (!drawable) {
Frank Binns2900e8c2015-08-04 14:32:43 +0100244 if (type == EGL_WINDOW_BIT)
245 _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_create_surface");
246 else
247 _eglError(EGL_BAD_NATIVE_PIXMAP, "dri2_create_surface");
Emil Velikovaf2aea42015-06-18 20:39:28 +0100248 goto cleanup_surf;
249 }
Chad Versace6d1f83e2014-01-07 14:54:51 -0800250 dri2_surf->drawable = drawable;
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500251 }
252
Emil Velikov4ea5ed92015-09-13 12:36:54 +0100253 config = dri2_get_dri_config(dri2_conf, type,
254 dri2_surf->base.GLColorspace);
Marek Olšákc2c2e9a2015-06-10 02:49:29 +0200255
Emil Velikov4ea5ed92015-09-13 12:36:54 +0100256 if (dri2_dpy->dri2) {
Marek Olšákc2c2e9a2015-06-10 02:49:29 +0200257 dri2_surf->dri_drawable =
258 (*dri2_dpy->dri2->createNewDrawable)(dri2_dpy->dri_screen, config,
259 dri2_surf);
Haitao Fengf55d0272011-02-16 23:05:15 -0500260 } else {
261 assert(dri2_dpy->swrast);
262 dri2_surf->dri_drawable =
Emil Velikov4ea5ed92015-09-13 12:36:54 +0100263 (*dri2_dpy->swrast->createNewDrawable)(dri2_dpy->dri_screen, config,
264 dri2_surf);
Haitao Fengf55d0272011-02-16 23:05:15 -0500265 }
266
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500267 if (dri2_surf->dri_drawable == NULL) {
268 _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
269 goto cleanup_pixmap;
270 }
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500271
272 if (type != EGL_PBUFFER_BIT) {
273 cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable);
274 reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error);
Frank Binns3b491cb2015-08-04 14:32:44 +0100275 if (error != NULL) {
276 if (error->error_code == BadAlloc)
277 _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
278 else if (type == EGL_WINDOW_BIT)
279 _eglError(EGL_BAD_NATIVE_WINDOW, "xcb_get_geometry");
280 else
281 _eglError(EGL_BAD_NATIVE_PIXMAP, "xcb_get_geometry");
282 free(error);
283 goto cleanup_dri_drawable;
284 } else if (reply == NULL) {
285 _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
286 goto cleanup_dri_drawable;
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500287 }
288
289 dri2_surf->base.Width = reply->width;
290 dri2_surf->base.Height = reply->height;
José Fonseca11a955a2015-01-19 23:07:17 +0000291 dri2_surf->depth = reply->depth;
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500292 free(reply);
293 }
294
José Fonseca11a955a2015-01-19 23:07:17 +0000295 if (dri2_dpy->dri2) {
Frank Binns9a4eae62015-08-04 14:32:45 +0100296 xcb_void_cookie_t cookie;
297 int conn_error;
298
299 cookie = xcb_dri2_create_drawable_checked(dri2_dpy->conn,
300 dri2_surf->drawable);
301 error = xcb_request_check(dri2_dpy->conn, cookie);
302 conn_error = xcb_connection_has_error(dri2_dpy->conn);
303 if (conn_error || error != NULL) {
304 if (type == EGL_PBUFFER_BIT || conn_error || error->error_code == BadAlloc)
305 _eglError(EGL_BAD_ALLOC, "xcb_dri2_create_drawable_checked");
306 else if (type == EGL_WINDOW_BIT)
307 _eglError(EGL_BAD_NATIVE_WINDOW,
308 "xcb_dri2_create_drawable_checked");
309 else
310 _eglError(EGL_BAD_NATIVE_PIXMAP,
311 "xcb_dri2_create_drawable_checked");
312 free(error);
313 goto cleanup_dri_drawable;
314 }
José Fonseca11a955a2015-01-19 23:07:17 +0000315 } else {
316 if (type == EGL_PBUFFER_BIT) {
317 dri2_surf->depth = _eglGetConfigKey(conf, EGL_BUFFER_SIZE);
318 }
319 swrastCreateDrawable(dri2_dpy, dri2_surf);
320 }
321
Chia-I Wueb7d1b92011-12-20 17:25:22 +0800322 /* we always copy the back buffer to front */
323 dri2_surf->base.PostSubBufferSupportedNV = EGL_TRUE;
Fredrik Höglund71b8fc92011-12-14 21:24:10 +0100324
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500325 return &dri2_surf->base;
326
327 cleanup_dri_drawable:
328 dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
329 cleanup_pixmap:
330 if (type == EGL_PBUFFER_BIT)
331 xcb_free_pixmap(dri2_dpy->conn, dri2_surf->drawable);
332 cleanup_surf:
333 free(dri2_surf);
334
335 return NULL;
336}
337
338/**
339 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
340 */
341static _EGLSurface *
Chad Versaced019cd82014-01-28 12:47:38 -0800342dri2_x11_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
Chad Versace6d1f83e2014-01-07 14:54:51 -0800343 _EGLConfig *conf, void *native_window,
Chad Versaced019cd82014-01-28 12:47:38 -0800344 const EGLint *attrib_list)
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500345{
Eric Anholt7e9bd2b2012-09-25 14:05:30 -0700346 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
347 _EGLSurface *surf;
348
Chad Versaced019cd82014-01-28 12:47:38 -0800349 surf = dri2_x11_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
Chad Versace6d1f83e2014-01-07 14:54:51 -0800350 native_window, attrib_list);
Ian Romanickf730c212013-04-08 20:00:30 -0700351 if (surf != NULL) {
352 /* When we first create the DRI2 drawable, its swap interval on the
353 * server side is 1.
354 */
355 surf->SwapInterval = 1;
Eric Anholt7e9bd2b2012-09-25 14:05:30 -0700356
Ian Romanickf730c212013-04-08 20:00:30 -0700357 /* Override that with a driconf-set value. */
Chad Versacea2187652014-01-27 16:42:10 -0800358 dri2_x11_swap_interval(drv, disp, surf, dri2_dpy->default_swap_interval);
Ian Romanickf730c212013-04-08 20:00:30 -0700359 }
Eric Anholt7e9bd2b2012-09-25 14:05:30 -0700360
361 return surf;
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500362}
363
364static _EGLSurface *
Chad Versaced019cd82014-01-28 12:47:38 -0800365dri2_x11_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
Chad Versace6d1f83e2014-01-07 14:54:51 -0800366 _EGLConfig *conf, void *native_pixmap,
Chad Versaced019cd82014-01-28 12:47:38 -0800367 const EGLint *attrib_list)
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500368{
Chad Versaced019cd82014-01-28 12:47:38 -0800369 return dri2_x11_create_surface(drv, disp, EGL_PIXMAP_BIT, conf,
Chad Versace6d1f83e2014-01-07 14:54:51 -0800370 native_pixmap, attrib_list);
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500371}
372
373static _EGLSurface *
Chad Versaced019cd82014-01-28 12:47:38 -0800374dri2_x11_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
375 _EGLConfig *conf, const EGLint *attrib_list)
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500376{
Chad Versaced019cd82014-01-28 12:47:38 -0800377 return dri2_x11_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
378 XCB_WINDOW_NONE, attrib_list);
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500379}
380
381static EGLBoolean
Chad Versaced019cd82014-01-28 12:47:38 -0800382dri2_x11_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500383{
384 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
385 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
386
387 (void) drv;
388
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500389 (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
390
Haitao Fengf55d0272011-02-16 23:05:15 -0500391 if (dri2_dpy->dri2) {
392 xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->drawable);
393 } else {
394 assert(dri2_dpy->swrast);
395 swrastDestroyDrawable(dri2_dpy, dri2_surf);
396 }
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500397
398 if (surf->Type == EGL_PBUFFER_BIT)
399 xcb_free_pixmap (dri2_dpy->conn, dri2_surf->drawable);
400
401 free(surf);
402
403 return EGL_TRUE;
404}
405
406/**
407 * Process list of buffer received from the server
408 *
409 * Processes the list of buffers received in a reply from the server to either
410 * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
411 */
412static void
Chad Versaced019cd82014-01-28 12:47:38 -0800413dri2_x11_process_buffers(struct dri2_egl_surface *dri2_surf,
414 xcb_dri2_dri2_buffer_t *buffers, unsigned count)
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500415{
416 struct dri2_egl_display *dri2_dpy =
417 dri2_egl_display(dri2_surf->base.Resource.Display);
418 xcb_rectangle_t rectangle;
419 unsigned i;
420
421 dri2_surf->buffer_count = count;
422 dri2_surf->have_fake_front = 0;
423
424 /* This assumes the DRI2 buffer attachment tokens matches the
425 * __DRIbuffer tokens. */
426 for (i = 0; i < count; i++) {
427 dri2_surf->buffers[i].attachment = buffers[i].attachment;
428 dri2_surf->buffers[i].name = buffers[i].name;
429 dri2_surf->buffers[i].pitch = buffers[i].pitch;
430 dri2_surf->buffers[i].cpp = buffers[i].cpp;
431 dri2_surf->buffers[i].flags = buffers[i].flags;
432
433 /* We only use the DRI drivers single buffer configs. This
434 * means that if we try to render to a window, DRI2 will give us
435 * the fake front buffer, which we'll use as a back buffer.
436 * Note that EGL doesn't require that several clients rendering
437 * to the same window must see the same aux buffers. */
438 if (dri2_surf->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
439 dri2_surf->have_fake_front = 1;
440 }
441
442 if (dri2_surf->region != XCB_NONE)
443 xcb_xfixes_destroy_region(dri2_dpy->conn, dri2_surf->region);
444
445 rectangle.x = 0;
446 rectangle.y = 0;
447 rectangle.width = dri2_surf->base.Width;
448 rectangle.height = dri2_surf->base.Height;
449 dri2_surf->region = xcb_generate_id(dri2_dpy->conn);
450 xcb_xfixes_create_region(dri2_dpy->conn, dri2_surf->region, 1, &rectangle);
451}
452
453static __DRIbuffer *
Chad Versaced019cd82014-01-28 12:47:38 -0800454dri2_x11_get_buffers(__DRIdrawable * driDrawable,
455 int *width, int *height,
456 unsigned int *attachments, int count,
457 int *out_count, void *loaderPrivate)
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500458{
459 struct dri2_egl_surface *dri2_surf = loaderPrivate;
460 struct dri2_egl_display *dri2_dpy =
461 dri2_egl_display(dri2_surf->base.Resource.Display);
462 xcb_dri2_dri2_buffer_t *buffers;
463 xcb_dri2_get_buffers_reply_t *reply;
464 xcb_dri2_get_buffers_cookie_t cookie;
465
466 (void) driDrawable;
467
468 cookie = xcb_dri2_get_buffers_unchecked (dri2_dpy->conn,
469 dri2_surf->drawable,
470 count, count, attachments);
471 reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, cookie, NULL);
Daniel Czarnowski5d87a7c2016-02-11 14:03:58 +0200472 if (reply == NULL)
473 return NULL;
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500474 buffers = xcb_dri2_get_buffers_buffers (reply);
475 if (buffers == NULL)
476 return NULL;
477
478 *out_count = reply->count;
479 dri2_surf->base.Width = *width = reply->width;
480 dri2_surf->base.Height = *height = reply->height;
Chad Versaced019cd82014-01-28 12:47:38 -0800481 dri2_x11_process_buffers(dri2_surf, buffers, *out_count);
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500482
483 free(reply);
484
485 return dri2_surf->buffers;
486}
487
488static __DRIbuffer *
Chad Versaced019cd82014-01-28 12:47:38 -0800489dri2_x11_get_buffers_with_format(__DRIdrawable * driDrawable,
490 int *width, int *height,
491 unsigned int *attachments, int count,
492 int *out_count, void *loaderPrivate)
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500493{
494 struct dri2_egl_surface *dri2_surf = loaderPrivate;
495 struct dri2_egl_display *dri2_dpy =
496 dri2_egl_display(dri2_surf->base.Resource.Display);
497 xcb_dri2_dri2_buffer_t *buffers;
498 xcb_dri2_get_buffers_with_format_reply_t *reply;
499 xcb_dri2_get_buffers_with_format_cookie_t cookie;
500 xcb_dri2_attach_format_t *format_attachments;
501
502 (void) driDrawable;
503
504 format_attachments = (xcb_dri2_attach_format_t *) attachments;
505 cookie = xcb_dri2_get_buffers_with_format_unchecked (dri2_dpy->conn,
506 dri2_surf->drawable,
507 count, count,
508 format_attachments);
509
510 reply = xcb_dri2_get_buffers_with_format_reply (dri2_dpy->conn,
511 cookie, NULL);
512 if (reply == NULL)
513 return NULL;
514
515 buffers = xcb_dri2_get_buffers_with_format_buffers (reply);
516 dri2_surf->base.Width = *width = reply->width;
517 dri2_surf->base.Height = *height = reply->height;
518 *out_count = reply->count;
Chad Versaced019cd82014-01-28 12:47:38 -0800519 dri2_x11_process_buffers(dri2_surf, buffers, *out_count);
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500520
521 free(reply);
522
523 return dri2_surf->buffers;
524}
525
526static void
Chad Versaced019cd82014-01-28 12:47:38 -0800527dri2_x11_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500528{
529 (void) driDrawable;
530
531 /* FIXME: Does EGL support front buffer rendering at all? */
532
533#if 0
534 struct dri2_egl_surface *dri2_surf = loaderPrivate;
535
536 dri2WaitGL(dri2_surf);
537#else
538 (void) loaderPrivate;
539#endif
540}
541
Jonathan Gray9bbf3732016-04-19 12:29:36 +1000542static int
Mark Kettenisb8e59292016-04-29 17:31:10 +0100543dri2_x11_do_authenticate(struct dri2_egl_display *dri2_dpy, uint32_t id)
Jonathan Gray9bbf3732016-04-19 12:29:36 +1000544{
545 xcb_dri2_authenticate_reply_t *authenticate;
546 xcb_dri2_authenticate_cookie_t authenticate_cookie;
547 xcb_screen_iterator_t s;
548 xcb_screen_t *screen;
549 int ret = 0;
550
551 s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
552
553 screen = get_xcb_screen(s, dri2_dpy->screen);
554 if (!screen) {
555 _eglLog(_EGL_WARNING, "DRI2: failed to get xcb screen");
556 return -1;
557 }
558
559 authenticate_cookie =
560 xcb_dri2_authenticate_unchecked(dri2_dpy->conn, screen->root, id);
561 authenticate =
562 xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL);
563
564 if (authenticate == NULL || !authenticate->authenticated)
565 ret = -1;
566
567 free(authenticate);
568
569 return ret;
570}
571
572static EGLBoolean
573dri2_x11_local_authenticate(struct dri2_egl_display *dri2_dpy)
574{
575#ifdef HAVE_LIBDRM
576 drm_magic_t magic;
577
578 if (drmGetMagic(dri2_dpy->fd, &magic)) {
579 _eglLog(_EGL_WARNING, "DRI2: failed to get drm magic");
580 return EGL_FALSE;
581 }
582
Mark Kettenisb8e59292016-04-29 17:31:10 +0100583 if (dri2_x11_do_authenticate(dri2_dpy, magic) < 0) {
Jonathan Gray9bbf3732016-04-19 12:29:36 +1000584 _eglLog(_EGL_WARNING, "DRI2: failed to authenticate");
585 return EGL_FALSE;
586 }
587#endif
588 return EGL_TRUE;
589}
590
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500591static EGLBoolean
Chad Versaced019cd82014-01-28 12:47:38 -0800592dri2_x11_connect(struct dri2_egl_display *dri2_dpy)
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500593{
594 xcb_xfixes_query_version_reply_t *xfixes_query;
595 xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
596 xcb_dri2_query_version_reply_t *dri2_query;
597 xcb_dri2_query_version_cookie_t dri2_query_cookie;
598 xcb_dri2_connect_reply_t *connect;
599 xcb_dri2_connect_cookie_t connect_cookie;
600 xcb_generic_error_t *error;
601 xcb_screen_iterator_t s;
Juha-Pekka Heikkila4ed23fd2014-09-08 15:03:35 +0300602 xcb_screen_t *screen;
Emil Velikov45e110b2015-07-29 17:19:06 +0100603 char *driver_name, *loader_driver_name, *device_name;
Benjamin Franzke80636ff2011-06-19 23:48:39 +0200604 const xcb_query_extension_reply_t *extension;
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500605
606 xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id);
607 xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri2_id);
608
Benjamin Franzke80636ff2011-06-19 23:48:39 +0200609 extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_xfixes_id);
610 if (!(extension && extension->present))
611 return EGL_FALSE;
612
613 extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_dri2_id);
614 if (!(extension && extension->present))
615 return EGL_FALSE;
616
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500617 xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn,
618 XCB_XFIXES_MAJOR_VERSION,
619 XCB_XFIXES_MINOR_VERSION);
620
621 dri2_query_cookie = xcb_dri2_query_version (dri2_dpy->conn,
622 XCB_DRI2_MAJOR_VERSION,
623 XCB_DRI2_MINOR_VERSION);
624
625 s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
Juha-Pekka Heikkila4ed23fd2014-09-08 15:03:35 +0300626 screen = get_xcb_screen(s, dri2_dpy->screen);
627 if (!screen) {
Frank Binns2900e8c2015-08-04 14:32:43 +0100628 _eglLog(_EGL_WARNING, "DRI2: failed to get xcb screen");
Juha-Pekka Heikkila4ed23fd2014-09-08 15:03:35 +0300629 return EGL_FALSE;
630 }
631 connect_cookie = xcb_dri2_connect_unchecked(dri2_dpy->conn, screen->root,
Marek Olšák0b56e232014-08-20 00:33:34 +0200632 XCB_DRI2_DRIVER_TYPE_DRI);
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500633
634 xfixes_query =
635 xcb_xfixes_query_version_reply (dri2_dpy->conn,
636 xfixes_query_cookie, &error);
637 if (xfixes_query == NULL ||
638 error != NULL || xfixes_query->major_version < 2) {
Haitao Fengf55d0272011-02-16 23:05:15 -0500639 _eglLog(_EGL_WARNING, "DRI2: failed to query xfixes version");
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500640 free(error);
641 return EGL_FALSE;
642 }
643 free(xfixes_query);
644
645 dri2_query =
646 xcb_dri2_query_version_reply (dri2_dpy->conn, dri2_query_cookie, &error);
647 if (dri2_query == NULL || error != NULL) {
Haitao Fengf55d0272011-02-16 23:05:15 -0500648 _eglLog(_EGL_WARNING, "DRI2: failed to query version");
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500649 free(error);
650 return EGL_FALSE;
651 }
652 dri2_dpy->dri2_major = dri2_query->major_version;
653 dri2_dpy->dri2_minor = dri2_query->minor_version;
654 free(dri2_query);
655
656 connect = xcb_dri2_connect_reply (dri2_dpy->conn, connect_cookie, NULL);
657 if (connect == NULL ||
658 connect->driver_name_length + connect->device_name_length == 0) {
Haitao Fengf55d0272011-02-16 23:05:15 -0500659 _eglLog(_EGL_WARNING, "DRI2: failed to authenticate");
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500660 return EGL_FALSE;
661 }
662
Benjamin Franzke4ca075a2011-03-02 21:23:04 +0100663 device_name = xcb_dri2_connect_device_name (connect);
Benjamin Franzke4ca075a2011-03-02 21:23:04 +0100664
Frank Binnsd6f669b2016-06-17 18:41:22 +0100665 dri2_dpy->fd = loader_open_device(device_name);
Emil Velikovfaf0f812015-07-29 17:19:05 +0100666 if (dri2_dpy->fd == -1) {
667 _eglLog(_EGL_WARNING,
Frank Binnsd6f669b2016-06-17 18:41:22 +0100668 "DRI2: could not open %s (%s)", device_name, strerror(errno));
Emil Velikovfaf0f812015-07-29 17:19:05 +0100669 free(connect);
670 return EGL_FALSE;
671 }
672
Jonathan Gray9bbf3732016-04-19 12:29:36 +1000673 if (!dri2_x11_local_authenticate(dri2_dpy)) {
674 close(dri2_dpy->fd);
Jonathan Gray9bbf3732016-04-19 12:29:36 +1000675 free(connect);
676 return EGL_FALSE;
677 }
678
Emil Velikovbeddb0a2015-07-29 17:19:04 +0100679 driver_name = xcb_dri2_connect_driver_name (connect);
Emil Velikov45e110b2015-07-29 17:19:06 +0100680
681 /* If Mesa knows about the appropriate driver for this fd, then trust it.
682 * Otherwise, default to the server's value.
683 */
684 loader_driver_name = loader_get_driver_for_fd(dri2_dpy->fd, 0);
685 if (loader_driver_name) {
Boyan Ding27141f92015-08-08 17:23:28 +0800686 dri2_dpy->driver_name = loader_driver_name;
687 } else {
688 dri2_dpy->driver_name =
689 strndup(driver_name,
690 xcb_dri2_connect_driver_name_length(connect));
Emil Velikov45e110b2015-07-29 17:19:06 +0100691 }
692
Frank Binnsd6f669b2016-06-17 18:41:22 +0100693 if (dri2_dpy->driver_name == NULL) {
Emil Velikovfaf0f812015-07-29 17:19:05 +0100694 close(dri2_dpy->fd);
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500695 free(dri2_dpy->driver_name);
696 free(connect);
697 return EGL_FALSE;
698 }
Frank Binnsd6f669b2016-06-17 18:41:22 +0100699
700#ifdef HAVE_WAYLAND_PLATFORM
701 dri2_dpy->device_name =
702 strndup(device_name,
703 xcb_dri2_connect_device_name_length(connect));
704#endif
705
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500706 free(connect);
707
708 return EGL_TRUE;
709}
710
Mark Kettenisb8e59292016-04-29 17:31:10 +0100711static int
712dri2_x11_authenticate(_EGLDisplay *disp, uint32_t id)
713{
714 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
715
716 return dri2_x11_do_authenticate(dri2_dpy, id);
717}
718
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500719static EGLBoolean
Chad Versaced019cd82014-01-28 12:47:38 -0800720dri2_x11_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
Boyan Dingf35198b2015-07-21 23:44:00 +0800721 _EGLDisplay *disp, bool supports_preserved)
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500722{
723 xcb_screen_iterator_t s;
724 xcb_depth_iterator_t d;
725 xcb_visualtype_t *visuals;
726 int i, j, id;
Kristian Høgsberge3d0a0e2013-09-14 23:06:36 -0700727 unsigned int rgba_masks[4];
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500728 EGLint surface_type;
Benjamin Franzke87dde5b2011-02-09 15:30:20 +0100729 EGLint config_attrs[] = {
730 EGL_NATIVE_VISUAL_ID, 0,
731 EGL_NATIVE_VISUAL_TYPE, 0,
732 EGL_NONE
733 };
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500734
735 s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
Marek Olšák0b56e232014-08-20 00:33:34 +0200736 d = xcb_screen_allowed_depths_iterator(get_xcb_screen(s, dri2_dpy->screen));
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500737 id = 1;
738
739 surface_type =
740 EGL_WINDOW_BIT |
741 EGL_PIXMAP_BIT |
Boyan Dingf35198b2015-07-21 23:44:00 +0800742 EGL_PBUFFER_BIT;
743
744 if (supports_preserved)
745 surface_type |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500746
747 while (d.rem > 0) {
748 EGLBoolean class_added[6] = { 0, };
749
750 visuals = xcb_depth_visuals(d.data);
751 for (i = 0; i < xcb_depth_visuals_length(d.data); i++) {
752 if (class_added[visuals[i]._class])
753 continue;
754
755 class_added[visuals[i]._class] = EGL_TRUE;
756 for (j = 0; dri2_dpy->driver_configs[j]; j++) {
Benjamin Franzke87dde5b2011-02-09 15:30:20 +0100757 config_attrs[1] = visuals[i].visual_id;
758 config_attrs[3] = visuals[i]._class;
759
Kristian Høgsberge3d0a0e2013-09-14 23:06:36 -0700760 rgba_masks[0] = visuals[i].red_mask;
761 rgba_masks[1] = visuals[i].green_mask;
762 rgba_masks[2] = visuals[i].blue_mask;
763 rgba_masks[3] = 0;
Benjamin Franzke87dde5b2011-02-09 15:30:20 +0100764 dri2_add_config(disp, dri2_dpy->driver_configs[j], id++,
Kristian Høgsberg44e584a2013-09-14 23:13:22 -0700765 surface_type, config_attrs, rgba_masks);
Kristian Høgsberge3d0a0e2013-09-14 23:06:36 -0700766
767 /* Allow a 24-bit RGB visual to match a 32-bit RGBA EGLConfig.
768 * Otherwise it will only match a 32-bit RGBA visual. On a
769 * composited window manager on X11, this will make all of the
770 * EGLConfigs with destination alpha get blended by the
771 * compositor. This is probably not what the application
772 * wants... especially on drivers that only have 32-bit RGBA
773 * EGLConfigs! */
774 if (d.data->depth == 24) {
775 rgba_masks[3] =
776 ~(rgba_masks[0] | rgba_masks[1] | rgba_masks[2]);
777 dri2_add_config(disp, dri2_dpy->driver_configs[j], id++,
Kristian Høgsberg44e584a2013-09-14 23:13:22 -0700778 surface_type, config_attrs, rgba_masks);
Kristian Høgsberge3d0a0e2013-09-14 23:06:36 -0700779 }
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500780 }
781 }
782
783 xcb_depth_next(&d);
784 }
785
786 if (!_eglGetArraySize(disp->Configs)) {
787 _eglLog(_EGL_WARNING, "DRI2: failed to create any config");
788 return EGL_FALSE;
789 }
790
791 return EGL_TRUE;
792}
793
794static EGLBoolean
795dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp,
796 _EGLSurface *draw, xcb_xfixes_region_t region)
797{
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500798 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
799 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
Benjamin Franzke87dde5b2011-02-09 15:30:20 +0100800 enum xcb_dri2_attachment_t render_attachment;
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500801 xcb_dri2_copy_region_cookie_t cookie;
802
Fredrik Höglund352c8892011-12-20 17:38:45 +0100803 /* No-op for a pixmap or pbuffer surface */
804 if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT)
805 return EGL_TRUE;
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500806
Fredrik Höglund352c8892011-12-20 17:38:45 +0100807 if (dri2_dpy->flush)
808 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500809
Benjamin Franzke87dde5b2011-02-09 15:30:20 +0100810 if (dri2_surf->have_fake_front)
811 render_attachment = XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT;
812 else
813 render_attachment = XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT;
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500814
815 cookie = xcb_dri2_copy_region_unchecked(dri2_dpy->conn,
816 dri2_surf->drawable,
817 region,
818 XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT,
Benjamin Franzke87dde5b2011-02-09 15:30:20 +0100819 render_attachment);
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500820 free(xcb_dri2_copy_region_reply(dri2_dpy->conn, cookie, NULL));
821
822 return EGL_TRUE;
823}
824
Fredrik Höglund352c8892011-12-20 17:38:45 +0100825static int64_t
Chad Versaced019cd82014-01-28 12:47:38 -0800826dri2_x11_swap_buffers_msc(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
827 int64_t msc, int64_t divisor, int64_t remainder)
Fredrik Höglund352c8892011-12-20 17:38:45 +0100828{
Fredrik Höglund352c8892011-12-20 17:38:45 +0100829 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
830 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
831 uint32_t msc_hi = msc >> 32;
832 uint32_t msc_lo = msc & 0xffffffff;
833 uint32_t divisor_hi = divisor >> 32;
834 uint32_t divisor_lo = divisor & 0xffffffff;
835 uint32_t remainder_hi = remainder >> 32;
836 uint32_t remainder_lo = remainder & 0xffffffff;
837 xcb_dri2_swap_buffers_cookie_t cookie;
838 xcb_dri2_swap_buffers_reply_t *reply;
839 int64_t swap_count = -1;
840
841 /* No-op for a pixmap or pbuffer surface */
842 if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT)
843 return 0;
844
845 if (draw->SwapBehavior == EGL_BUFFER_PRESERVED || !dri2_dpy->swap_available)
846 return dri2_copy_region(drv, disp, draw, dri2_surf->region) ? 0 : -1;
847
Eric Anholt70e8ccc2014-12-21 11:51:33 -0800848 dri2_flush_drawable_for_swapbuffers(disp, draw);
Fredrik Höglund352c8892011-12-20 17:38:45 +0100849
850 cookie = xcb_dri2_swap_buffers_unchecked(dri2_dpy->conn, dri2_surf->drawable,
851 msc_hi, msc_lo, divisor_hi, divisor_lo, remainder_hi, remainder_lo);
852
853 reply = xcb_dri2_swap_buffers_reply(dri2_dpy->conn, cookie, NULL);
854
855 if (reply) {
856 swap_count = (((int64_t)reply->swap_hi) << 32) | reply->swap_lo;
857 free(reply);
858 }
859
Eric Anholteed0a802013-06-21 15:34:52 -0700860 /* Since we aren't watching for the server's invalidate events like we're
861 * supposed to (due to XCB providing no mechanism for filtering the events
862 * the way xlib does), and SwapBuffers is a common cause of invalidate
863 * events, just shove one down to the driver, even though we haven't told
864 * the driver that we're the kind of loader that provides reliable
865 * invalidate events. This causes the driver to request buffers again at
866 * its next draw, so that we get the correct buffers if a pageflip
867 * happened. The driver should still be using the viewport hack to catch
868 * window resizes.
869 */
870 if (dri2_dpy->flush &&
871 dri2_dpy->flush->base.version >= 3 && dri2_dpy->flush->invalidate)
872 (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
873
Fredrik Höglund352c8892011-12-20 17:38:45 +0100874 return swap_count;
Fredrik Höglund352c8892011-12-20 17:38:45 +0100875}
876
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500877static EGLBoolean
Chad Versaced019cd82014-01-28 12:47:38 -0800878dri2_x11_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500879{
Haitao Fengf55d0272011-02-16 23:05:15 -0500880 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500881 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
882
Fredrik Höglund352c8892011-12-20 17:38:45 +0100883 if (dri2_dpy->dri2) {
Daniel Czarnowskie6f1a44d2016-02-15 09:31:09 +0200884 if (dri2_x11_swap_buffers_msc(drv, disp, draw, 0, 0, 0) != -1) {
885 return EGL_TRUE;
886 }
887 /* Swap failed with a window drawable. */
888 _eglError(EGL_BAD_NATIVE_WINDOW, __FUNCTION__);
889 return EGL_FALSE;
Haitao Fengf55d0272011-02-16 23:05:15 -0500890 } else {
891 assert(dri2_dpy->swrast);
Fredrik Höglund352c8892011-12-20 17:38:45 +0100892
Haitao Fengf55d0272011-02-16 23:05:15 -0500893 dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable);
894 return EGL_TRUE;
895 }
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500896}
897
898static EGLBoolean
Chad Versaced019cd82014-01-28 12:47:38 -0800899dri2_x11_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp,
900 _EGLSurface *draw,
901 EGLint numRects, const EGLint *rects)
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500902{
903 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
904 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
905 EGLBoolean ret;
906 xcb_xfixes_region_t region;
907 xcb_rectangle_t rectangles[16];
908 int i;
909
910 if (numRects > (int)ARRAY_SIZE(rectangles))
911 return dri2_copy_region(drv, disp, draw, dri2_surf->region);
912
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500913 for (i = 0; i < numRects; i++) {
914 rectangles[i].x = rects[i * 4];
Robert Bragg0a523a82012-09-18 16:10:03 +0100915 rectangles[i].y = dri2_surf->base.Height - rects[i * 4 + 1] - rects[i * 4 + 3];
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500916 rectangles[i].width = rects[i * 4 + 2];
917 rectangles[i].height = rects[i * 4 + 3];
918 }
919
920 region = xcb_generate_id(dri2_dpy->conn);
921 xcb_xfixes_create_region(dri2_dpy->conn, region, numRects, rectangles);
922 ret = dri2_copy_region(drv, disp, draw, region);
923 xcb_xfixes_destroy_region(dri2_dpy->conn, region);
924
925 return ret;
926}
927
928static EGLBoolean
Chad Versaced019cd82014-01-28 12:47:38 -0800929dri2_x11_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
Fredrik Höglund71b8fc92011-12-14 21:24:10 +0100930 EGLint x, EGLint y, EGLint width, EGLint height)
931{
Fredrik Höglundf4251892012-11-06 17:36:34 +0100932 const EGLint rect[4] = { x, y, width, height };
Fredrik Höglund71b8fc92011-12-14 21:24:10 +0100933
Chia-I Wueb7d1b92011-12-20 17:25:22 +0800934 if (x < 0 || y < 0 || width < 0 || height < 0)
935 _eglError(EGL_BAD_PARAMETER, "eglPostSubBufferNV");
936
Chad Versaced019cd82014-01-28 12:47:38 -0800937 return dri2_x11_swap_buffers_region(drv, disp, draw, 1, rect);
Fredrik Höglund71b8fc92011-12-14 21:24:10 +0100938}
939
940static EGLBoolean
Chad Versaced019cd82014-01-28 12:47:38 -0800941dri2_x11_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
942 EGLint interval)
Fredrik Höglund655f2c12011-12-20 17:17:02 +0100943{
Fredrik Höglund655f2c12011-12-20 17:17:02 +0100944 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
945 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
946
Fredrik Höglund655f2c12011-12-20 17:17:02 +0100947 if (interval > surf->Config->MaxSwapInterval)
948 interval = surf->Config->MaxSwapInterval;
949 else if (interval < surf->Config->MinSwapInterval)
950 interval = surf->Config->MinSwapInterval;
951
952 if (interval != surf->SwapInterval && dri2_dpy->swap_available)
953 xcb_dri2_swap_interval(dri2_dpy->conn, dri2_surf->drawable, interval);
954
955 surf->SwapInterval = interval;
956
957 return EGL_TRUE;
Fredrik Höglund655f2c12011-12-20 17:17:02 +0100958}
959
960static EGLBoolean
Chad Versaced019cd82014-01-28 12:47:38 -0800961dri2_x11_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
Chad Versace6d1f83e2014-01-07 14:54:51 -0800962 void *native_pixmap_target)
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500963{
964 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
965 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
966 xcb_gcontext_t gc;
Chad Versace6d1f83e2014-01-07 14:54:51 -0800967 xcb_pixmap_t target;
968
969 STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_pixmap_target));
970 target = (uintptr_t) native_pixmap_target;
Kristian Høgsberg2889d962011-02-02 22:10:40 -0500971
972 (void) drv;
973
974 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
975
976 gc = xcb_generate_id(dri2_dpy->conn);
977 xcb_create_gc(dri2_dpy->conn, gc, target, 0, NULL);
978 xcb_copy_area(dri2_dpy->conn,
979 dri2_surf->drawable,
980 target,
981 gc,
982 0, 0,
983 0, 0,
984 dri2_surf->base.Width,
985 dri2_surf->base.Height);
986 xcb_free_gc(dri2_dpy->conn, gc);
987
988 return EGL_TRUE;
989}
990
991static _EGLImage *
992dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
993 EGLClientBuffer buffer, const EGLint *attr_list)
994{
995 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
996 struct dri2_egl_image *dri2_img;
997 unsigned int attachments[1];
998 xcb_drawable_t drawable;
999 xcb_dri2_get_buffers_cookie_t buffers_cookie;
1000 xcb_dri2_get_buffers_reply_t *buffers_reply;
1001 xcb_dri2_dri2_buffer_t *buffers;
1002 xcb_get_geometry_cookie_t geometry_cookie;
1003 xcb_get_geometry_reply_t *geometry_reply;
1004 xcb_generic_error_t *error;
1005 int stride, format;
1006
1007 (void) ctx;
1008
José Fonseca6a661892011-05-12 15:12:16 +01001009 drawable = (xcb_drawable_t) (uintptr_t) buffer;
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001010 xcb_dri2_create_drawable (dri2_dpy->conn, drawable);
1011 attachments[0] = XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT;
1012 buffers_cookie =
1013 xcb_dri2_get_buffers_unchecked (dri2_dpy->conn,
1014 drawable, 1, 1, attachments);
1015 geometry_cookie = xcb_get_geometry (dri2_dpy->conn, drawable);
1016 buffers_reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn,
1017 buffers_cookie, NULL);
Emil Velikovb9c5c4a2016-03-05 21:25:44 +00001018 if (buffers_reply == NULL)
1019 return NULL;
1020
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001021 buffers = xcb_dri2_get_buffers_buffers (buffers_reply);
1022 if (buffers == NULL) {
1023 return NULL;
1024 }
1025
1026 geometry_reply = xcb_get_geometry_reply (dri2_dpy->conn,
1027 geometry_cookie, &error);
1028 if (geometry_reply == NULL || error != NULL) {
1029 _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
1030 free(error);
1031 free(buffers_reply);
Chia-I Wubf0c5652011-02-20 12:23:54 -07001032 return NULL;
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001033 }
1034
1035 switch (geometry_reply->depth) {
1036 case 16:
1037 format = __DRI_IMAGE_FORMAT_RGB565;
1038 break;
1039 case 24:
1040 format = __DRI_IMAGE_FORMAT_XRGB8888;
1041 break;
1042 case 32:
1043 format = __DRI_IMAGE_FORMAT_ARGB8888;
1044 break;
1045 default:
1046 _eglError(EGL_BAD_PARAMETER,
1047 "dri2_create_image_khr: unsupported pixmap depth");
1048 free(buffers_reply);
1049 free(geometry_reply);
1050 return NULL;
1051 }
1052
1053 dri2_img = malloc(sizeof *dri2_img);
1054 if (!dri2_img) {
1055 free(buffers_reply);
1056 free(geometry_reply);
1057 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
1058 return EGL_NO_IMAGE_KHR;
1059 }
1060
1061 if (!_eglInitImage(&dri2_img->base, disp)) {
1062 free(buffers_reply);
1063 free(geometry_reply);
Völgyes Dávidf747d032011-07-06 10:10:20 -04001064 free(dri2_img);
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001065 return EGL_NO_IMAGE_KHR;
1066 }
1067
1068 stride = buffers[0].pitch / buffers[0].cpp;
1069 dri2_img->dri_image =
1070 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
1071 buffers_reply->width,
1072 buffers_reply->height,
1073 format,
1074 buffers[0].name,
1075 stride,
1076 dri2_img);
1077
1078 free(buffers_reply);
1079 free(geometry_reply);
1080
1081 return &dri2_img->base;
1082}
1083
1084static _EGLImage *
1085dri2_x11_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
1086 _EGLContext *ctx, EGLenum target,
1087 EGLClientBuffer buffer, const EGLint *attr_list)
1088{
1089 (void) drv;
1090
1091 switch (target) {
1092 case EGL_NATIVE_PIXMAP_KHR:
1093 return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
1094 default:
1095 return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
1096 }
1097}
1098
Sarah Sharpc524f3e2014-05-06 12:10:57 -07001099static EGLBoolean
1100dri2_x11_get_sync_values(_EGLDisplay *display, _EGLSurface *surface,
1101 EGLuint64KHR *ust, EGLuint64KHR *msc,
1102 EGLuint64KHR *sbc)
1103{
1104 struct dri2_egl_display *dri2_dpy = dri2_egl_display(display);
1105 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
1106 xcb_dri2_get_msc_cookie_t cookie;
1107 xcb_dri2_get_msc_reply_t *reply;
1108
1109 cookie = xcb_dri2_get_msc(dri2_dpy->conn, dri2_surf->drawable);
1110 reply = xcb_dri2_get_msc_reply(dri2_dpy->conn, cookie, NULL);
1111
1112 if (!reply) {
1113 _eglError(EGL_BAD_ACCESS, __func__);
1114 return EGL_FALSE;
1115 }
1116
1117 *ust = ((EGLuint64KHR) reply->ust_hi << 32) | reply->ust_lo;
1118 *msc = ((EGLuint64KHR) reply->msc_hi << 32) | reply->msc_lo;
1119 *sbc = ((EGLuint64KHR) reply->sbc_hi << 32) | reply->sbc_lo;
1120 free(reply);
1121
1122 return EGL_TRUE;
1123}
1124
Chad Versace90502b12014-01-28 11:41:46 -08001125static struct dri2_egl_display_vtbl dri2_x11_swrast_display_vtbl = {
1126 .authenticate = NULL,
Chad Versace0a0c8812014-01-28 16:39:09 -08001127 .create_window_surface = dri2_x11_create_window_surface,
Chad Versacebc8b07a2014-01-28 16:45:07 -08001128 .create_pixmap_surface = dri2_x11_create_pixmap_surface,
Chad Versacebf200762014-01-28 17:03:03 -08001129 .create_pbuffer_surface = dri2_x11_create_pbuffer_surface,
Chad Versace958dd802014-01-28 17:03:03 -08001130 .destroy_surface = dri2_x11_destroy_surface,
Axel Davyf1cc4782015-05-01 11:12:46 +02001131 .create_image = dri2_fallback_create_image_khr,
Chad Versace8b9298a2014-01-28 12:34:19 -08001132 .swap_interval = dri2_fallback_swap_interval,
Chad Versacead173bc2014-01-28 16:21:21 -08001133 .swap_buffers = dri2_x11_swap_buffers,
Chad Versace75d398e2014-01-28 17:03:03 -08001134 .swap_buffers_region = dri2_fallback_swap_buffers_region,
Chad Versace688a0e82014-01-28 17:03:03 -08001135 .post_sub_buffer = dri2_fallback_post_sub_buffer,
Chad Versacebc2cbc02014-01-28 17:03:03 -08001136 .copy_buffers = dri2_x11_copy_buffers,
Chad Versace3fdfbd22014-01-28 17:03:03 -08001137 .query_buffer_age = dri2_fallback_query_buffer_age,
Chad Versaceeadd5e02014-01-28 17:03:03 -08001138 .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
Sarah Sharpc524f3e2014-05-06 12:10:57 -07001139 .get_sync_values = dri2_fallback_get_sync_values,
Boyan Dinga25df542015-07-21 23:43:59 +08001140 .get_dri_drawable = dri2_surface_get_dri_drawable,
Chad Versace90502b12014-01-28 11:41:46 -08001141};
1142
1143static struct dri2_egl_display_vtbl dri2_x11_display_vtbl = {
1144 .authenticate = dri2_x11_authenticate,
Chad Versace0a0c8812014-01-28 16:39:09 -08001145 .create_window_surface = dri2_x11_create_window_surface,
Chad Versacebc8b07a2014-01-28 16:45:07 -08001146 .create_pixmap_surface = dri2_x11_create_pixmap_surface,
Chad Versacebf200762014-01-28 17:03:03 -08001147 .create_pbuffer_surface = dri2_x11_create_pbuffer_surface,
Chad Versace958dd802014-01-28 17:03:03 -08001148 .destroy_surface = dri2_x11_destroy_surface,
Chad Versaceeef68a92014-01-28 17:03:03 -08001149 .create_image = dri2_x11_create_image_khr,
Chad Versace8b9298a2014-01-28 12:34:19 -08001150 .swap_interval = dri2_x11_swap_interval,
Chad Versacead173bc2014-01-28 16:21:21 -08001151 .swap_buffers = dri2_x11_swap_buffers,
Chad Versaced03948a2014-01-28 16:26:44 -08001152 .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage,
Chad Versace75d398e2014-01-28 17:03:03 -08001153 .swap_buffers_region = dri2_x11_swap_buffers_region,
Chad Versace688a0e82014-01-28 17:03:03 -08001154 .post_sub_buffer = dri2_x11_post_sub_buffer,
Chad Versacebc2cbc02014-01-28 17:03:03 -08001155 .copy_buffers = dri2_x11_copy_buffers,
Chad Versace3fdfbd22014-01-28 17:03:03 -08001156 .query_buffer_age = dri2_fallback_query_buffer_age,
Chad Versaceeadd5e02014-01-28 17:03:03 -08001157 .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
Sarah Sharpc524f3e2014-05-06 12:10:57 -07001158 .get_sync_values = dri2_x11_get_sync_values,
Boyan Dinga25df542015-07-21 23:43:59 +08001159 .get_dri_drawable = dri2_surface_get_dri_drawable,
Chad Versace90502b12014-01-28 11:41:46 -08001160};
1161
Haitao Fengf55d0272011-02-16 23:05:15 -05001162static EGLBoolean
1163dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp)
1164{
1165 struct dri2_egl_display *dri2_dpy;
1166
Matt Turner6bda0272012-09-04 23:09:22 -07001167 dri2_dpy = calloc(1, sizeof *dri2_dpy);
Haitao Fengf55d0272011-02-16 23:05:15 -05001168 if (!dri2_dpy)
1169 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
1170
Haitao Fengf55d0272011-02-16 23:05:15 -05001171 disp->DriverData = (void *) dri2_dpy;
1172 if (disp->PlatformDisplay == NULL) {
Marek Olšák0b56e232014-08-20 00:33:34 +02001173 dri2_dpy->conn = xcb_connect(0, &dri2_dpy->screen);
Chad Versace31cd0fe2014-01-28 18:52:00 -08001174 dri2_dpy->own_device = true;
Haitao Fengf55d0272011-02-16 23:05:15 -05001175 } else {
Marek Olšák0b56e232014-08-20 00:33:34 +02001176 Display *dpy = disp->PlatformDisplay;
1177
1178 dri2_dpy->conn = XGetXCBConnection(dpy);
1179 dri2_dpy->screen = DefaultScreen(dpy);
Haitao Fengf55d0272011-02-16 23:05:15 -05001180 }
1181
Emil Velikov6de9a032015-08-07 19:20:48 +01001182 if (!dri2_dpy->conn || xcb_connection_has_error(dri2_dpy->conn)) {
Haitao Fengf55d0272011-02-16 23:05:15 -05001183 _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed");
1184 goto cleanup_dpy;
1185 }
1186
Emil Velikov5cb1cad2014-06-02 12:26:17 +01001187 /*
1188 * Every hardware driver_name is set using strdup. Doing the same in
1189 * here will allow is to simply free the memory at dri2_terminate().
1190 */
Emil Velikova1ac7422015-09-10 14:41:38 +01001191 dri2_dpy->fd = -1;
Emil Velikov5cb1cad2014-06-02 12:26:17 +01001192 dri2_dpy->driver_name = strdup("swrast");
Chia-I Wucf69eea2011-06-08 16:33:55 +08001193 if (!dri2_load_driver_swrast(disp))
Haitao Fengf55d0272011-02-16 23:05:15 -05001194 goto cleanup_conn;
1195
1196 dri2_dpy->swrast_loader_extension.base.name = __DRI_SWRAST_LOADER;
Boyan Ding997fc802015-06-16 11:08:33 +08001197 dri2_dpy->swrast_loader_extension.base.version = 2;
Haitao Fengf55d0272011-02-16 23:05:15 -05001198 dri2_dpy->swrast_loader_extension.getDrawableInfo = swrastGetDrawableInfo;
1199 dri2_dpy->swrast_loader_extension.putImage = swrastPutImage;
1200 dri2_dpy->swrast_loader_extension.getImage = swrastGetImage;
1201
1202 dri2_dpy->extensions[0] = &dri2_dpy->swrast_loader_extension.base;
1203 dri2_dpy->extensions[1] = NULL;
1204 dri2_dpy->extensions[2] = NULL;
1205
1206 if (!dri2_create_screen(disp))
1207 goto cleanup_driver;
1208
Boyan Dingf35198b2015-07-21 23:44:00 +08001209 if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, true))
Emil Velikov6de9a032015-08-07 19:20:48 +01001210 goto cleanup_configs;
Haitao Fengf55d0272011-02-16 23:05:15 -05001211
Chad Versace90502b12014-01-28 11:41:46 -08001212 /* Fill vtbl last to prevent accidentally calling virtual function during
1213 * initialization.
1214 */
1215 dri2_dpy->vtbl = &dri2_x11_swrast_display_vtbl;
1216
Haitao Fengf55d0272011-02-16 23:05:15 -05001217 return EGL_TRUE;
1218
1219 cleanup_configs:
1220 _eglCleanupDisplay(disp);
1221 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
1222 cleanup_driver:
1223 dlclose(dri2_dpy->driver);
1224 cleanup_conn:
Emil Velikov5cb1cad2014-06-02 12:26:17 +01001225 free(dri2_dpy->driver_name);
Haitao Fengf55d0272011-02-16 23:05:15 -05001226 if (disp->PlatformDisplay == NULL)
1227 xcb_disconnect(dri2_dpy->conn);
1228 cleanup_dpy:
1229 free(dri2_dpy);
Jan Ziak769ac1e2016-07-31 15:44:18 +02001230 disp->DriverData = NULL;
Haitao Fengf55d0272011-02-16 23:05:15 -05001231
1232 return EGL_FALSE;
1233}
1234
Eric Anholt7e9bd2b2012-09-25 14:05:30 -07001235static void
Chad Versaced019cd82014-01-28 12:47:38 -08001236dri2_x11_setup_swap_interval(struct dri2_egl_display *dri2_dpy)
Eric Anholt7e9bd2b2012-09-25 14:05:30 -07001237{
1238 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
1239 int arbitrary_max_interval = 1000;
1240
1241 /* default behavior for no SwapBuffers support: no vblank syncing
1242 * either.
1243 */
1244 dri2_dpy->min_swap_interval = 0;
1245 dri2_dpy->max_swap_interval = 0;
1246
1247 if (!dri2_dpy->swap_available)
1248 return;
1249
1250 /* If we do have swapbuffers, then we can support pretty much any swap
1251 * interval, but we allow driconf to override applications.
1252 */
1253 if (dri2_dpy->config)
1254 dri2_dpy->config->configQueryi(dri2_dpy->dri_screen,
1255 "vblank_mode", &vblank_mode);
1256 switch (vblank_mode) {
1257 case DRI_CONF_VBLANK_NEVER:
1258 dri2_dpy->min_swap_interval = 0;
1259 dri2_dpy->max_swap_interval = 0;
1260 dri2_dpy->default_swap_interval = 0;
1261 break;
1262 case DRI_CONF_VBLANK_ALWAYS_SYNC:
1263 dri2_dpy->min_swap_interval = 1;
1264 dri2_dpy->max_swap_interval = arbitrary_max_interval;
1265 dri2_dpy->default_swap_interval = 1;
1266 break;
1267 case DRI_CONF_VBLANK_DEF_INTERVAL_0:
1268 dri2_dpy->min_swap_interval = 0;
1269 dri2_dpy->max_swap_interval = arbitrary_max_interval;
1270 dri2_dpy->default_swap_interval = 0;
1271 break;
1272 default:
1273 case DRI_CONF_VBLANK_DEF_INTERVAL_1:
1274 dri2_dpy->min_swap_interval = 0;
1275 dri2_dpy->max_swap_interval = arbitrary_max_interval;
1276 dri2_dpy->default_swap_interval = 1;
1277 break;
1278 }
1279}
Haitao Fengf55d0272011-02-16 23:05:15 -05001280
Boyan Dingf35198b2015-07-21 23:44:00 +08001281#ifdef HAVE_DRI3
1282static EGLBoolean
1283dri2_initialize_x11_dri3(_EGLDriver *drv, _EGLDisplay *disp)
1284{
1285 struct dri2_egl_display *dri2_dpy;
1286
1287 dri2_dpy = calloc(1, sizeof *dri2_dpy);
1288 if (!dri2_dpy)
1289 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
1290
1291 disp->DriverData = (void *) dri2_dpy;
1292 if (disp->PlatformDisplay == NULL) {
1293 dri2_dpy->conn = xcb_connect(0, &dri2_dpy->screen);
1294 dri2_dpy->own_device = true;
1295 } else {
1296 Display *dpy = disp->PlatformDisplay;
1297
1298 dri2_dpy->conn = XGetXCBConnection(dpy);
1299 dri2_dpy->screen = DefaultScreen(dpy);
1300 }
1301
1302 if (xcb_connection_has_error(dri2_dpy->conn)) {
Martin Peres4518eea2015-10-30 17:16:35 +02001303 _eglLog(_EGL_WARNING, "DRI3: xcb_connect failed");
Boyan Dingf35198b2015-07-21 23:44:00 +08001304 goto cleanup_dpy;
1305 }
1306
1307 if (dri2_dpy->conn) {
1308 if (!dri3_x11_connect(dri2_dpy))
1309 goto cleanup_conn;
1310 }
1311
1312 if (!dri2_load_driver_dri3(disp))
1313 goto cleanup_conn;
1314
1315 dri2_dpy->extensions[0] = &dri3_image_loader_extension.base;
1316 dri2_dpy->extensions[1] = &use_invalidate.base;
1317 dri2_dpy->extensions[2] = &image_lookup_extension.base;
1318 dri2_dpy->extensions[3] = NULL;
1319
1320 dri2_dpy->swap_available = true;
1321 dri2_dpy->invalidate_available = true;
1322
1323 if (!dri2_create_screen(disp))
1324 goto cleanup_fd;
1325
1326 dri2_x11_setup_swap_interval(dri2_dpy);
1327
Boyan Dingfcdc7982015-07-21 23:44:02 +08001328 if (!dri2_dpy->is_different_gpu)
1329 disp->Extensions.KHR_image_pixmap = EGL_TRUE;
Boyan Dingf35198b2015-07-21 23:44:00 +08001330 disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE;
1331 disp->Extensions.CHROMIUM_sync_control = EGL_TRUE;
1332 disp->Extensions.EXT_buffer_age = EGL_TRUE;
1333
1334#ifdef HAVE_WAYLAND_PLATFORM
Frank Binns4c28c912016-06-17 18:41:20 +01001335 if (dri2_dpy->device_name)
1336 disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
Boyan Dingf35198b2015-07-21 23:44:00 +08001337#endif
1338
1339 if (dri2_dpy->conn) {
1340 if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, false))
1341 goto cleanup_configs;
1342 }
1343
1344 dri2_dpy->loader_dri3_ext.core = dri2_dpy->core;
1345 dri2_dpy->loader_dri3_ext.image_driver = dri2_dpy->image_driver;
1346 dri2_dpy->loader_dri3_ext.flush = dri2_dpy->flush;
1347 dri2_dpy->loader_dri3_ext.tex_buffer = dri2_dpy->tex_buffer;
1348 dri2_dpy->loader_dri3_ext.image = dri2_dpy->image;
1349 dri2_dpy->loader_dri3_ext.config = dri2_dpy->config;
1350
1351 /* Fill vtbl last to prevent accidentally calling virtual function during
1352 * initialization.
1353 */
1354 dri2_dpy->vtbl = &dri3_x11_display_vtbl;
1355
Martin Peres4518eea2015-10-30 17:16:35 +02001356 _eglLog(_EGL_INFO, "Using DRI3");
1357
Boyan Dingf35198b2015-07-21 23:44:00 +08001358 return EGL_TRUE;
1359
1360 cleanup_configs:
1361 _eglCleanupDisplay(disp);
1362 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
1363 dlclose(dri2_dpy->driver);
1364 cleanup_fd:
1365 close(dri2_dpy->fd);
1366 cleanup_conn:
1367 if (disp->PlatformDisplay == NULL)
1368 xcb_disconnect(dri2_dpy->conn);
1369 cleanup_dpy:
1370 free(dri2_dpy);
Jan Ziak769ac1e2016-07-31 15:44:18 +02001371 disp->DriverData = NULL;
Boyan Dingf35198b2015-07-21 23:44:00 +08001372
1373 return EGL_FALSE;
1374}
1375#endif
1376
Emil Velikov3963a5f2016-08-16 18:29:34 +01001377static const __DRIdri2LoaderExtension dri2_loader_extension_old = {
1378 .base = { __DRI_DRI2_LOADER, 2 },
1379
1380 .getBuffers = dri2_x11_get_buffers,
1381 .flushFrontBuffer = dri2_x11_flush_front_buffer,
1382 .getBuffersWithFormat = NULL,
1383};
1384
1385static const __DRIdri2LoaderExtension dri2_loader_extension = {
1386 .base = { __DRI_DRI2_LOADER, 3 },
1387
1388 .getBuffers = dri2_x11_get_buffers,
1389 .flushFrontBuffer = dri2_x11_flush_front_buffer,
1390 .getBuffersWithFormat = dri2_x11_get_buffers_with_format,
1391};
1392
Haitao Fengf55d0272011-02-16 23:05:15 -05001393static EGLBoolean
1394dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001395{
1396 struct dri2_egl_display *dri2_dpy;
1397
Matt Turner6bda0272012-09-04 23:09:22 -07001398 dri2_dpy = calloc(1, sizeof *dri2_dpy);
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001399 if (!dri2_dpy)
1400 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
1401
1402 disp->DriverData = (void *) dri2_dpy;
1403 if (disp->PlatformDisplay == NULL) {
Marek Olšák0b56e232014-08-20 00:33:34 +02001404 dri2_dpy->conn = xcb_connect(0, &dri2_dpy->screen);
Chad Versace31cd0fe2014-01-28 18:52:00 -08001405 dri2_dpy->own_device = true;
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001406 } else {
Marek Olšák0b56e232014-08-20 00:33:34 +02001407 Display *dpy = disp->PlatformDisplay;
1408
1409 dri2_dpy->conn = XGetXCBConnection(dpy);
1410 dri2_dpy->screen = DefaultScreen(dpy);
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001411 }
1412
Emil Velikov60e9c352015-07-29 17:19:02 +01001413 if (!dri2_dpy->conn || xcb_connection_has_error(dri2_dpy->conn)) {
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001414 _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed");
1415 goto cleanup_dpy;
1416 }
1417
Emil Velikovbf669882015-07-29 17:19:03 +01001418 if (!dri2_x11_connect(dri2_dpy))
1419 goto cleanup_conn;
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001420
Emil Velikov2c7b6cf2015-07-29 17:19:07 +01001421 if (!dri2_load_driver(disp))
1422 goto cleanup_fd;
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001423
Emil Velikov3963a5f2016-08-16 18:29:34 +01001424 if (dri2_dpy->dri2_minor >= 1)
1425 dri2_dpy->extensions[0] = &dri2_loader_extension.base;
1426 else
1427 dri2_dpy->extensions[0] = &dri2_loader_extension_old.base;
1428
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001429 dri2_dpy->extensions[1] = &image_lookup_extension.base;
1430 dri2_dpy->extensions[2] = NULL;
1431
Fredrik Höglund655f2c12011-12-20 17:17:02 +01001432 dri2_dpy->swap_available = (dri2_dpy->dri2_minor >= 2);
Fredrik Höglund352c8892011-12-20 17:38:45 +01001433 dri2_dpy->invalidate_available = (dri2_dpy->dri2_minor >= 3);
Fredrik Höglund655f2c12011-12-20 17:17:02 +01001434
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001435 if (!dri2_create_screen(disp))
Emil Velikovfaf0f812015-07-29 17:19:05 +01001436 goto cleanup_driver;
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001437
Chad Versaced019cd82014-01-28 12:47:38 -08001438 dri2_x11_setup_swap_interval(dri2_dpy);
1439
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001440 disp->Extensions.KHR_image_pixmap = EGL_TRUE;
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001441 disp->Extensions.NOK_swap_region = EGL_TRUE;
1442 disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE;
Fredrik Höglund71b8fc92011-12-14 21:24:10 +01001443 disp->Extensions.NV_post_sub_buffer = EGL_TRUE;
Sarah Sharpc524f3e2014-05-06 12:10:57 -07001444 disp->Extensions.CHROMIUM_sync_control = EGL_TRUE;
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001445
Benjamin Franzke6b369c42011-02-21 16:22:34 +01001446#ifdef HAVE_WAYLAND_PLATFORM
1447 disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
1448#endif
Tapani Pällif8c5b8a2014-01-08 15:17:58 +02001449
Boyan Dingf35198b2015-07-21 23:44:00 +08001450 if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, true))
Emil Velikovbf669882015-07-29 17:19:03 +01001451 goto cleanup_configs;
Tapani Pällif8c5b8a2014-01-08 15:17:58 +02001452
Chad Versace90502b12014-01-28 11:41:46 -08001453 /* Fill vtbl last to prevent accidentally calling virtual function during
1454 * initialization.
1455 */
1456 dri2_dpy->vtbl = &dri2_x11_display_vtbl;
1457
Martin Peres4518eea2015-10-30 17:16:35 +02001458 _eglLog(_EGL_INFO, "Using DRI2");
1459
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001460 return EGL_TRUE;
1461
1462 cleanup_configs:
1463 _eglCleanupDisplay(disp);
1464 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001465 cleanup_driver:
1466 dlclose(dri2_dpy->driver);
Emil Velikovfaf0f812015-07-29 17:19:05 +01001467 cleanup_fd:
1468 close(dri2_dpy->fd);
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001469 cleanup_conn:
1470 if (disp->PlatformDisplay == NULL)
1471 xcb_disconnect(dri2_dpy->conn);
1472 cleanup_dpy:
1473 free(dri2_dpy);
Jan Ziak769ac1e2016-07-31 15:44:18 +02001474 disp->DriverData = NULL;
Kristian Høgsberg2889d962011-02-02 22:10:40 -05001475
1476 return EGL_FALSE;
1477}
Haitao Fengf55d0272011-02-16 23:05:15 -05001478
1479EGLBoolean
1480dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp)
1481{
1482 EGLBoolean initialized = EGL_TRUE;
1483
1484 int x11_dri2_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
1485
1486 if (x11_dri2_accel) {
Boyan Dingf35198b2015-07-21 23:44:00 +08001487#ifdef HAVE_DRI3
1488 if (getenv("LIBGL_DRI3_DISABLE") != NULL ||
1489 !dri2_initialize_x11_dri3(drv, disp)) {
1490#endif
1491 if (!dri2_initialize_x11_dri2(drv, disp)) {
1492 initialized = dri2_initialize_x11_swrast(drv, disp);
1493 }
1494#ifdef HAVE_DRI3
Haitao Fengf55d0272011-02-16 23:05:15 -05001495 }
Boyan Dingf35198b2015-07-21 23:44:00 +08001496#endif
Haitao Fengf55d0272011-02-16 23:05:15 -05001497 } else {
1498 initialized = dri2_initialize_x11_swrast(drv, disp);
1499 }
1500
1501 return initialized;
1502}
1503