Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/*
2
 * Copyright © 2010 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 
26
 */
27
 
28
#define WL_HIDE_DEPRECATED
29
 
30
#include 
31
#include 
32
#include 
33
#include 
34
#include 
35
#include 
36
#include 
37
#include 
38
#include 
39
#ifdef HAVE_LIBDRM
40
#include 
41
#include 
42
#endif
43
#include 
44
#include 
45
#include 
46
#include 
47
 
48
#ifdef HAVE_WAYLAND_PLATFORM
49
#include "wayland-drm.h"
50
#include "wayland-drm-client-protocol.h"
51
#endif
52
 
53
#include "egl_dri2.h"
54
#include "../util/u_atomic.h"
55
 
56
const __DRIuseInvalidateExtension use_invalidate = {
57
   .base = { __DRI_USE_INVALIDATE, 1 }
58
};
59
 
60
EGLint dri2_to_egl_attribute_map[] = {
61
   0,
62
   EGL_BUFFER_SIZE,		/* __DRI_ATTRIB_BUFFER_SIZE */
63
   EGL_LEVEL,			/* __DRI_ATTRIB_LEVEL */
64
   EGL_RED_SIZE,		/* __DRI_ATTRIB_RED_SIZE */
65
   EGL_GREEN_SIZE,		/* __DRI_ATTRIB_GREEN_SIZE */
66
   EGL_BLUE_SIZE,		/* __DRI_ATTRIB_BLUE_SIZE */
67
   EGL_LUMINANCE_SIZE,		/* __DRI_ATTRIB_LUMINANCE_SIZE */
68
   EGL_ALPHA_SIZE,		/* __DRI_ATTRIB_ALPHA_SIZE */
69
   0,				/* __DRI_ATTRIB_ALPHA_MASK_SIZE */
70
   EGL_DEPTH_SIZE,		/* __DRI_ATTRIB_DEPTH_SIZE */
71
   EGL_STENCIL_SIZE,		/* __DRI_ATTRIB_STENCIL_SIZE */
72
   0,				/* __DRI_ATTRIB_ACCUM_RED_SIZE */
73
   0,				/* __DRI_ATTRIB_ACCUM_GREEN_SIZE */
74
   0,				/* __DRI_ATTRIB_ACCUM_BLUE_SIZE */
75
   0,				/* __DRI_ATTRIB_ACCUM_ALPHA_SIZE */
76
   EGL_SAMPLE_BUFFERS,		/* __DRI_ATTRIB_SAMPLE_BUFFERS */
77
   EGL_SAMPLES,			/* __DRI_ATTRIB_SAMPLES */
78
   0,				/* __DRI_ATTRIB_RENDER_TYPE, */
79
   0,				/* __DRI_ATTRIB_CONFIG_CAVEAT */
80
   0,				/* __DRI_ATTRIB_CONFORMANT */
81
   0,				/* __DRI_ATTRIB_DOUBLE_BUFFER */
82
   0,				/* __DRI_ATTRIB_STEREO */
83
   0,				/* __DRI_ATTRIB_AUX_BUFFERS */
84
   0,				/* __DRI_ATTRIB_TRANSPARENT_TYPE */
85
   0,				/* __DRI_ATTRIB_TRANSPARENT_INDEX_VALUE */
86
   0,				/* __DRI_ATTRIB_TRANSPARENT_RED_VALUE */
87
   0,				/* __DRI_ATTRIB_TRANSPARENT_GREEN_VALUE */
88
   0,				/* __DRI_ATTRIB_TRANSPARENT_BLUE_VALUE */
89
   0,				/* __DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE */
90
   0,				/* __DRI_ATTRIB_FLOAT_MODE (deprecated) */
91
   0,				/* __DRI_ATTRIB_RED_MASK */
92
   0,				/* __DRI_ATTRIB_GREEN_MASK */
93
   0,				/* __DRI_ATTRIB_BLUE_MASK */
94
   0,				/* __DRI_ATTRIB_ALPHA_MASK */
95
   EGL_MAX_PBUFFER_WIDTH,	/* __DRI_ATTRIB_MAX_PBUFFER_WIDTH */
96
   EGL_MAX_PBUFFER_HEIGHT,	/* __DRI_ATTRIB_MAX_PBUFFER_HEIGHT */
97
   EGL_MAX_PBUFFER_PIXELS,	/* __DRI_ATTRIB_MAX_PBUFFER_PIXELS */
98
   0,				/* __DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH */
99
   0,				/* __DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT */
100
   0,				/* __DRI_ATTRIB_VISUAL_SELECT_GROUP */
101
   0,				/* __DRI_ATTRIB_SWAP_METHOD */
102
   EGL_MAX_SWAP_INTERVAL,	/* __DRI_ATTRIB_MAX_SWAP_INTERVAL */
103
   EGL_MIN_SWAP_INTERVAL,	/* __DRI_ATTRIB_MIN_SWAP_INTERVAL */
104
   0,				/* __DRI_ATTRIB_BIND_TO_TEXTURE_RGB */
105
   0,				/* __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA */
106
   0,				/* __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE */
107
   0,				/* __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS */
108
   EGL_Y_INVERTED_NOK,		/* __DRI_ATTRIB_YINVERTED */
109
   0,				/* __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE */
110
};
111
 
112
static EGLBoolean
113
dri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria)
114
{
115
   if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0)
116
      return EGL_FALSE;
117
 
118
   if (!_eglMatchConfig(conf, criteria))
119
      return EGL_FALSE;
120
 
121
   return EGL_TRUE;
122
}
123
 
124
struct dri2_egl_config *
125
dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
126
		EGLint surface_type, const EGLint *attr_list,
127
		const unsigned int *rgba_masks)
128
{
129
   struct dri2_egl_config *conf;
130
   struct dri2_egl_display *dri2_dpy;
131
   _EGLConfig base;
132
   unsigned int attrib, value, double_buffer;
133
   EGLint key, bind_to_texture_rgb, bind_to_texture_rgba;
134
   unsigned int dri_masks[4] = { 0, 0, 0, 0 };
135
   _EGLConfig *matching_config;
136
   EGLint num_configs = 0;
137
   EGLint config_id;
138
   int i;
139
 
140
   dri2_dpy = disp->DriverData;
141
   _eglInitConfig(&base, disp, id);
142
 
143
   i = 0;
144
   double_buffer = 0;
145
   bind_to_texture_rgb = 0;
146
   bind_to_texture_rgba = 0;
147
 
148
   while (dri2_dpy->core->indexConfigAttrib(dri_config, i++, &attrib, &value)) {
149
      switch (attrib) {
150
      case __DRI_ATTRIB_RENDER_TYPE:
151
	 if (value & __DRI_ATTRIB_RGBA_BIT)
152
	    value = EGL_RGB_BUFFER;
153
	 else if (value & __DRI_ATTRIB_LUMINANCE_BIT)
154
	    value = EGL_LUMINANCE_BUFFER;
155
	 else
156
	    return NULL;
157
	 _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value);
158
	 break;
159
 
160
      case __DRI_ATTRIB_CONFIG_CAVEAT:
161
         if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
162
            value = EGL_NON_CONFORMANT_CONFIG;
163
         else if (value & __DRI_ATTRIB_SLOW_BIT)
164
            value = EGL_SLOW_CONFIG;
165
	 else
166
	    value = EGL_NONE;
167
	 _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value);
168
         break;
169
 
170
      case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB:
171
	 bind_to_texture_rgb = value;
172
	 break;
173
 
174
      case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA:
175
	 bind_to_texture_rgba = value;
176
	 break;
177
 
178
      case __DRI_ATTRIB_DOUBLE_BUFFER:
179
	 double_buffer = value;
180
	 break;
181
 
182
      case __DRI_ATTRIB_RED_MASK:
183
         dri_masks[0] = value;
184
         break;
185
 
186
      case __DRI_ATTRIB_GREEN_MASK:
187
         dri_masks[1] = value;
188
         break;
189
 
190
      case __DRI_ATTRIB_BLUE_MASK:
191
         dri_masks[2] = value;
192
         break;
193
 
194
      case __DRI_ATTRIB_ALPHA_MASK:
195
         dri_masks[3] = value;
196
         break;
197
 
198
      case __DRI_ATTRIB_ACCUM_RED_SIZE:
199
      case __DRI_ATTRIB_ACCUM_GREEN_SIZE:
200
      case __DRI_ATTRIB_ACCUM_BLUE_SIZE:
201
      case __DRI_ATTRIB_ACCUM_ALPHA_SIZE:
202
         /* Don't expose visuals with the accumulation buffer. */
203
         if (value > 0)
204
            return NULL;
205
         break;
206
 
207
      default:
208
	 key = dri2_to_egl_attribute_map[attrib];
209
	 if (key != 0)
210
	    _eglSetConfigKey(&base, key, value);
211
	 break;
212
      }
213
   }
214
 
215
   if (attr_list)
216
      for (i = 0; attr_list[i] != EGL_NONE; i += 2)
217
         _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]);
218
 
219
   if (rgba_masks && memcmp(rgba_masks, dri_masks, sizeof(dri_masks)))
220
      return NULL;
221
 
222
   base.NativeRenderable = EGL_TRUE;
223
 
224
   base.SurfaceType = surface_type;
225
   if (surface_type & (EGL_PBUFFER_BIT |
226
       (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) {
227
      base.BindToTextureRGB = bind_to_texture_rgb;
228
      if (base.AlphaSize > 0)
229
         base.BindToTextureRGBA = bind_to_texture_rgba;
230
   }
231
 
232
   base.RenderableType = disp->ClientAPIs;
233
   base.Conformant = disp->ClientAPIs;
234
 
235
   base.MinSwapInterval = dri2_dpy->min_swap_interval;
236
   base.MaxSwapInterval = dri2_dpy->max_swap_interval;
237
 
238
   if (!_eglValidateConfig(&base, EGL_FALSE)) {
239
      _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id);
240
      return NULL;
241
   }
242
 
243
   config_id = base.ConfigID;
244
   base.ConfigID    = EGL_DONT_CARE;
245
   base.SurfaceType = EGL_DONT_CARE;
246
   num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1,
247
                                 (_EGLArrayForEach) dri2_match_config, &base);
248
 
249
   if (num_configs == 1) {
250
      conf = (struct dri2_egl_config *) matching_config;
251
 
252
      if (double_buffer && !conf->dri_double_config)
253
         conf->dri_double_config = dri_config;
254
      else if (!double_buffer && !conf->dri_single_config)
255
         conf->dri_single_config = dri_config;
256
      else
257
         /* a similar config type is already added (unlikely) => discard */
258
         return NULL;
259
   }
260
   else if (num_configs == 0) {
261
      conf = malloc(sizeof *conf);
262
      if (conf == NULL)
263
         return NULL;
264
 
265
      memcpy(&conf->base, &base, sizeof base);
266
      if (double_buffer) {
267
         conf->dri_double_config = dri_config;
268
         conf->dri_single_config = NULL;
269
      } else {
270
         conf->dri_single_config = dri_config;
271
         conf->dri_double_config = NULL;
272
      }
273
      conf->base.SurfaceType = 0;
274
      conf->base.ConfigID = config_id;
275
 
276
      _eglLinkConfig(&conf->base);
277
   }
278
   else {
279
      assert(0);
280
      return NULL;
281
   }
282
 
283
   if (double_buffer) {
284
      surface_type &= ~EGL_PIXMAP_BIT;
285
   }
286
 
287
   conf->base.SurfaceType |= surface_type;
288
 
289
   return conf;
290
}
291
 
292
__DRIimage *
293
dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
294
{
295
   _EGLDisplay *disp = data;
296
   struct dri2_egl_image *dri2_img;
297
   _EGLImage *img;
298
 
299
   (void) screen;
300
 
301
   img = _eglLookupImage(image, disp);
302
   if (img == NULL) {
303
      _eglError(EGL_BAD_PARAMETER, "dri2_lookup_egl_image");
304
      return NULL;
305
   }
306
 
307
   dri2_img = dri2_egl_image(image);
308
 
309
   return dri2_img->dri_image;
310
}
311
 
312
const __DRIimageLookupExtension image_lookup_extension = {
313
   .base = { __DRI_IMAGE_LOOKUP, 1 },
314
 
315
   .lookupEGLImage       = dri2_lookup_egl_image
316
};
317
 
318
struct dri2_extension_match {
319
   const char *name;
320
   int version;
321
   int offset;
322
};
323
 
324
static struct dri2_extension_match dri2_driver_extensions[] = {
325
   { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
326
   { __DRI_DRI2, 2, offsetof(struct dri2_egl_display, dri2) },
327
   { NULL, 0, 0 }
328
};
329
 
330
static struct dri2_extension_match dri2_core_extensions[] = {
331
   { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) },
332
   { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
333
   { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) },
334
   { NULL, 0, 0 }
335
};
336
 
337
static struct dri2_extension_match swrast_driver_extensions[] = {
338
   { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
339
   { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) },
340
   { NULL, 0, 0 }
341
};
342
 
343
static struct dri2_extension_match swrast_core_extensions[] = {
344
   { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
345
   { NULL, 0, 0 }
346
};
347
 
348
static EGLBoolean
349
dri2_bind_extensions(struct dri2_egl_display *dri2_dpy,
350
		     struct dri2_extension_match *matches,
351
		     const __DRIextension **extensions)
352
{
353
   int i, j, ret = EGL_TRUE;
354
   void *field;
355
 
356
   for (i = 0; extensions[i]; i++) {
357
      _eglLog(_EGL_DEBUG, "DRI2: found extension `%s'", extensions[i]->name);
358
      for (j = 0; matches[j].name; j++) {
359
	 if (strcmp(extensions[i]->name, matches[j].name) == 0 &&
360
	     extensions[i]->version >= matches[j].version) {
361
	    field = ((char *) dri2_dpy + matches[j].offset);
362
	    *(const __DRIextension **) field = extensions[i];
363
	    _eglLog(_EGL_INFO, "DRI2: found extension %s version %d",
364
		    extensions[i]->name, extensions[i]->version);
365
	 }
366
      }
367
   }
368
 
369
   for (j = 0; matches[j].name; j++) {
370
      field = ((char *) dri2_dpy + matches[j].offset);
371
      if (*(const __DRIextension **) field == NULL) {
372
	 _eglLog(_EGL_WARNING, "DRI2: did not find extension %s version %d",
373
		 matches[j].name, matches[j].version);
374
	 ret = EGL_FALSE;
375
      }
376
   }
377
 
378
   return ret;
379
}
380
 
381
#if 0
382
 
383
static const __DRIextension **
384
dri2_open_driver(_EGLDisplay *disp)
385
{
386
   struct dri2_egl_display *dri2_dpy = disp->DriverData;
387
   const __DRIextension **extensions = NULL;
388
   char path[PATH_MAX], *search_paths, *p, *next, *end;
389
   char *get_extensions_name;
390
   const __DRIextension **(*get_extensions)(void);
391
 
392
   search_paths = NULL;
393
   if (geteuid() == getuid()) {
394
      /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
395
      search_paths = getenv("LIBGL_DRIVERS_PATH");
396
   }
397
   if (search_paths == NULL)
398
      search_paths = DEFAULT_DRIVER_DIR;
399
 
400
   dri2_dpy->driver = NULL;
401
   end = search_paths + strlen(search_paths);
402
   for (p = search_paths; p < end && dri2_dpy->driver == NULL; p = next + 1) {
403
      int len;
404
      next = strchr(p, ':');
405
      if (next == NULL)
406
         next = end;
407
 
408
      len = next - p;
409
#if GLX_USE_TLS
410
      snprintf(path, sizeof path,
411
	       "%.*s/tls/%s_dri.so", len, p, dri2_dpy->driver_name);
412
      dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
413
#endif
414
      if (dri2_dpy->driver == NULL) {
415
	 snprintf(path, sizeof path,
416
		  "%.*s/%s_dri.so", len, p, dri2_dpy->driver_name);
417
	 dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
418
	 if (dri2_dpy->driver == NULL)
419
	    _eglLog(_EGL_DEBUG, "failed to open %s: %s\n", path, dlerror());
420
      }
421
      /* not need continue to loop all paths once the driver is found */
422
      if (dri2_dpy->driver != NULL)
423
         break;
424
   }
425
 
426
   if (dri2_dpy->driver == NULL) {
427
      _eglLog(_EGL_WARNING,
428
	      "DRI2: failed to open %s (search paths %s)",
429
	      dri2_dpy->driver_name, search_paths);
430
      return NULL;
431
   }
432
 
433
   _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path);
434
 
435
   if (asprintf(&get_extensions_name, "%s_%s",
436
                __DRI_DRIVER_GET_EXTENSIONS, dri2_dpy->driver_name) != -1) {
437
      get_extensions = dlsym(dri2_dpy->driver, get_extensions_name);
438
      if (get_extensions) {
439
         extensions = get_extensions();
440
      } else {
441
         _eglLog(_EGL_DEBUG, "driver does not expose %s(): %s\n",
442
                 get_extensions_name, dlerror());
443
      }
444
      free(get_extensions_name);
445
   }
446
 
447
   if (!extensions)
448
      extensions = dlsym(dri2_dpy->driver, __DRI_DRIVER_EXTENSIONS);
449
   if (extensions == NULL) {
450
      _eglLog(_EGL_WARNING,
451
	      "DRI2: driver exports no extensions (%s)", dlerror());
452
      dlclose(dri2_dpy->driver);
453
   }
454
 
455
   return extensions;
456
}
457
 
458
EGLBoolean
459
dri2_load_driver(_EGLDisplay *disp)
460
{
461
   struct dri2_egl_display *dri2_dpy = disp->DriverData;
462
   const __DRIextension **extensions;
463
 
464
   extensions = dri2_open_driver(disp);
465
   if (!extensions)
466
      return EGL_FALSE;
467
 
468
   if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) {
469
      dlclose(dri2_dpy->driver);
470
      return EGL_FALSE;
471
   }
472
   dri2_dpy->driver_extensions = extensions;
473
 
474
   return EGL_TRUE;
475
}
476
 
477
EGLBoolean
478
dri2_load_driver_swrast(_EGLDisplay *disp)
479
{
480
   struct dri2_egl_display *dri2_dpy = disp->DriverData;
481
   const __DRIextension **extensions;
482
 
483
   extensions = dri2_open_driver(disp);
484
   if (!extensions)
485
      return EGL_FALSE;
486
 
487
   if (!dri2_bind_extensions(dri2_dpy, swrast_driver_extensions, extensions)) {
488
      dlclose(dri2_dpy->driver);
489
      return EGL_FALSE;
490
   }
491
   dri2_dpy->driver_extensions = extensions;
492
 
493
   return EGL_TRUE;
494
}
495
#endif
496
 
497
void
498
dri2_setup_screen(_EGLDisplay *disp)
499
{
500
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
501
   unsigned int api_mask;
502
 
503
   if (dri2_dpy->dri2) {
504
      api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
505
   } else {
506
      assert(dri2_dpy->swrast);
507
      api_mask = 1 << __DRI_API_OPENGL |
508
                 1 << __DRI_API_GLES |
509
                 1 << __DRI_API_GLES2 |
510
                 1 << __DRI_API_GLES3;
511
   }
512
 
513
   disp->ClientAPIs = 0;
514
   if (api_mask & (1 <<__DRI_API_OPENGL))
515
      disp->ClientAPIs |= EGL_OPENGL_BIT;
516
   if (api_mask & (1 <<__DRI_API_GLES))
517
      disp->ClientAPIs |= EGL_OPENGL_ES_BIT;
518
   if (api_mask & (1 << __DRI_API_GLES2))
519
      disp->ClientAPIs |= EGL_OPENGL_ES2_BIT;
520
   if (api_mask & (1 << __DRI_API_GLES3))
521
      disp->ClientAPIs |= EGL_OPENGL_ES3_BIT_KHR;
522
 
523
   assert(dri2_dpy->dri2 || dri2_dpy->swrast);
524
   disp->Extensions.KHR_surfaceless_context = EGL_TRUE;
525
   disp->Extensions.MESA_configless_context = EGL_TRUE;
526
 
527
   if (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) {
528
      disp->Extensions.KHR_create_context = EGL_TRUE;
529
 
530
      if (dri2_dpy->robustness)
531
         disp->Extensions.EXT_create_context_robustness = EGL_TRUE;
532
   }
533
 
534
   if (dri2_dpy->fence) {
535
      disp->Extensions.KHR_fence_sync = EGL_TRUE;
536
      disp->Extensions.KHR_wait_sync = EGL_TRUE;
537
      if (dri2_dpy->fence->get_fence_from_cl_event)
538
         disp->Extensions.KHR_cl_event2 = EGL_TRUE;
539
   }
540
 
541
   if (dri2_dpy->image) {
542
      if (dri2_dpy->image->base.version >= 10 &&
543
          dri2_dpy->image->getCapabilities != NULL) {
544
         int capabilities;
545
 
546
         capabilities = dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen);
547
         disp->Extensions.MESA_drm_image = (capabilities & __DRI_IMAGE_CAP_GLOBAL_NAMES) != 0;
548
 
549
         if (dri2_dpy->image->base.version >= 11)
550
            disp->Extensions.MESA_image_dma_buf_export = EGL_TRUE;
551
      } else {
552
         disp->Extensions.MESA_drm_image = EGL_TRUE;
553
         if (dri2_dpy->image->base.version >= 11)
554
            disp->Extensions.MESA_image_dma_buf_export = EGL_TRUE;
555
      }
556
 
557
      disp->Extensions.KHR_image_base = EGL_TRUE;
558
      disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
559
      if (dri2_dpy->image->base.version >= 5 &&
560
          dri2_dpy->image->createImageFromTexture) {
561
         disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
562
         disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE;
563
      }
564
#ifdef HAVE_LIBDRM
565
      if (dri2_dpy->image->base.version >= 8 &&
566
          dri2_dpy->image->createImageFromDmaBufs) {
567
         disp->Extensions.EXT_image_dma_buf_import = EGL_TRUE;
568
      }
569
#endif
570
   }
571
}
572
 
573
/* All platforms but DRM call this function to create the screen, query the
574
 * dri extensions, setup the vtables and populate the driver_configs.
575
 * DRM inherits all that information from its display - GBM.
576
 */
577
EGLBoolean
578
dri2_create_screen(_EGLDisplay *disp)
579
{
580
   const __DRIextension **extensions;
581
   struct dri2_egl_display *dri2_dpy;
582
   unsigned i;
583
 
584
   dri2_dpy = disp->DriverData;
585
 
586
   if (dri2_dpy->dri2) {
587
      if (dri2_dpy->dri2->base.version >= 4) {
588
         dri2_dpy->dri_screen =
589
            dri2_dpy->dri2->createNewScreen2(0, dri2_dpy->fd,
590
                                             dri2_dpy->extensions,
591
                                             dri2_dpy->driver_extensions,
592
                                             &dri2_dpy->driver_configs, disp);
593
      } else {
594
         dri2_dpy->dri_screen =
595
            dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd,
596
                                            dri2_dpy->extensions,
597
                                            &dri2_dpy->driver_configs, disp);
598
      }
599
   } else {
600
      assert(dri2_dpy->swrast);
601
      if (dri2_dpy->swrast->base.version >= 4) {
602
         dri2_dpy->dri_screen =
603
            dri2_dpy->swrast->createNewScreen2(0, dri2_dpy->extensions,
604
                                               dri2_dpy->driver_extensions,
605
                                               &dri2_dpy->driver_configs, disp);
606
      } else {
607
         dri2_dpy->dri_screen =
608
            dri2_dpy->swrast->createNewScreen(0, dri2_dpy->extensions,
609
                                              &dri2_dpy->driver_configs, disp);
610
      }
611
   }
612
 
613
   if (dri2_dpy->dri_screen == NULL) {
614
      _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
615
      return EGL_FALSE;
616
   }
617
 
618
   dri2_dpy->own_dri_screen = 1;
619
 
620
   extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
621
 
622
   if (dri2_dpy->dri2) {
623
      if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
624
         goto cleanup_dri_screen;
625
   } else {
626
      assert(dri2_dpy->swrast);
627
      if (!dri2_bind_extensions(dri2_dpy, swrast_core_extensions, extensions))
628
         goto cleanup_dri_screen;
629
   }
630
 
631
   for (i = 0; extensions[i]; i++) {
632
      if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0) {
633
         dri2_dpy->robustness = (__DRIrobustnessExtension *) extensions[i];
634
      }
635
      if (strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0) {
636
         dri2_dpy->config = (__DRI2configQueryExtension *) extensions[i];
637
      }
638
      if (strcmp(extensions[i]->name, __DRI2_FENCE) == 0) {
639
         dri2_dpy->fence = (__DRI2fenceExtension *) extensions[i];
640
      }
641
   }
642
 
643
   dri2_setup_screen(disp);
644
 
645
   return EGL_TRUE;
646
 
647
 cleanup_dri_screen:
648
   dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
649
 
650
   return EGL_FALSE;
651
}
652
 
653
/**
654
 * Called via eglInitialize(), GLX_drv->API.Initialize().
655
 */
656
static EGLBoolean
657
dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp)
658
{
659
   /* not until swrast_dri is supported */
660
   if (disp->Options.UseFallback)
661
      return EGL_FALSE;
662
 
663
   return dri2_initialize_drm(drv, disp);
664
 
665
#if 0
666
   switch (disp->Platform) {
667
#ifdef HAVE_X11_PLATFORM
668
   case _EGL_PLATFORM_X11:
669
      if (disp->Options.TestOnly)
670
         return EGL_TRUE;
671
      return dri2_initialize_x11(drv, disp);
672
#endif
673
 
674
#ifdef HAVE_DRM_PLATFORM
675
   case _EGL_PLATFORM_DRM:
676
      if (disp->Options.TestOnly)
677
         return EGL_TRUE;
678
      return dri2_initialize_drm(drv, disp);
679
#endif
680
#ifdef HAVE_WAYLAND_PLATFORM
681
   case _EGL_PLATFORM_WAYLAND:
682
      if (disp->Options.TestOnly)
683
         return EGL_TRUE;
684
      return dri2_initialize_wayland(drv, disp);
685
#endif
686
#ifdef HAVE_ANDROID_PLATFORM
687
   case _EGL_PLATFORM_ANDROID:
688
      if (disp->Options.TestOnly)
689
         return EGL_TRUE;
690
      return dri2_initialize_android(drv, disp);
691
#endif
692
 
693
   default:
694
      _eglLog(_EGL_WARNING, "No EGL platform enabled.");
695
      return EGL_FALSE;
696
   }
697
#endif
698
}
699
 
700
/**
701
 * Called via eglTerminate(), drv->API.Terminate().
702
 */
703
static EGLBoolean
704
dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
705
{
706
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
707
   unsigned i;
708
 
709
   _eglReleaseDisplayResources(drv, disp);
710
   _eglCleanupDisplay(disp);
711
 
712
   if (dri2_dpy->own_dri_screen)
713
      dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
714
   if (dri2_dpy->fd)
715
      close(dri2_dpy->fd);
716
   if (dri2_dpy->driver)
717
      dlclose(dri2_dpy->driver);
718
   free(dri2_dpy->device_name);
719
   free(dri2_dpy->driver_name);
720
 
721
   switch (disp->Platform) {
722
#ifdef HAVE_X11_PLATFORM
723
   case _EGL_PLATFORM_X11:
724
      if (dri2_dpy->own_device) {
725
         xcb_disconnect(dri2_dpy->conn);
726
      }
727
      break;
728
#endif
729
#ifdef HAVE_DRM_PLATFORM
730
   case _EGL_PLATFORM_DRM:
731
      if (dri2_dpy->own_device) {
732
         gbm_device_destroy(&dri2_dpy->gbm_dri->base.base);
733
      }
734
      break;
735
#endif
736
#ifdef HAVE_WAYLAND_PLATFORM
737
   case _EGL_PLATFORM_WAYLAND:
738
      if (dri2_dpy->wl_drm)
739
          wl_drm_destroy(dri2_dpy->wl_drm);
740
      if (dri2_dpy->wl_shm)
741
          wl_shm_destroy(dri2_dpy->wl_shm);
742
      wl_registry_destroy(dri2_dpy->wl_registry);
743
      wl_event_queue_destroy(dri2_dpy->wl_queue);
744
      if (dri2_dpy->own_device) {
745
         wl_display_disconnect(dri2_dpy->wl_dpy);
746
      }
747
      break;
748
#endif
749
   default:
750
      break;
751
   }
752
 
753
   /* The drm platform does not create the screen/driver_configs but reuses
754
    * the ones from the gbm device. As such the gbm itself is responsible
755
    * for the cleanup.
756
    */
757
   if (disp->Platform != _EGL_PLATFORM_DRM) {
758
      for (i = 0; dri2_dpy->driver_configs[i]; i++)
759
         free((__DRIconfig *) dri2_dpy->driver_configs[i]);
760
      free(dri2_dpy->driver_configs);
761
   }
762
   free(dri2_dpy);
763
   disp->DriverData = NULL;
764
 
765
   return EGL_TRUE;
766
}
767
 
768
/**
769
 * Set the error code after a call to
770
 * dri2_egl_display::dri2::createContextAttribs.
771
 */
772
static void
773
dri2_create_context_attribs_error(int dri_error)
774
{
775
   EGLint egl_error;
776
 
777
   switch (dri_error) {
778
   case __DRI_CTX_ERROR_SUCCESS:
779
      return;
780
 
781
   case __DRI_CTX_ERROR_NO_MEMORY:
782
      egl_error = EGL_BAD_ALLOC;
783
      break;
784
 
785
  /* From the EGL_KHR_create_context spec, section "Errors":
786
   *
787
   *   * If  does not support a client API context compatible
788
   *     with the requested API major and minor version, [...] context flags,
789
   *     and context reset notification behavior (for client API types where
790
   *     these attributes are supported), then an EGL_BAD_MATCH error is
791
   *     generated.
792
   *
793
   *   * If an OpenGL ES context is requested and the values for
794
   *     attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
795
   *     EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
796
   *     is not defined, than an EGL_BAD_MATCH error is generated.
797
   *
798
   *   * If an OpenGL context is requested, the requested version is
799
   *     greater than 3.2, and the value for attribute
800
   *     EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has any
801
   *     bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and
802
   *     EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than
803
   *     one of these bits set; or if the implementation does not support
804
   *     the requested profile, then an EGL_BAD_MATCH error is generated.
805
   */
806
   case __DRI_CTX_ERROR_BAD_API:
807
   case __DRI_CTX_ERROR_BAD_VERSION:
808
   case __DRI_CTX_ERROR_BAD_FLAG:
809
      egl_error = EGL_BAD_MATCH;
810
      break;
811
 
812
  /* From the EGL_KHR_create_context spec, section "Errors":
813
   *
814
   *   * If an attribute name or attribute value in  is not
815
   *     recognized (including unrecognized bits in bitmask attributes),
816
   *     then an EGL_BAD_ATTRIBUTE error is generated."
817
   */
818
   case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE:
819
   case __DRI_CTX_ERROR_UNKNOWN_FLAG:
820
      egl_error = EGL_BAD_ATTRIBUTE;
821
      break;
822
 
823
   default:
824
      assert(0);
825
      egl_error = EGL_BAD_MATCH;
826
      break;
827
   }
828
 
829
   _eglError(egl_error, "dri2_create_context");
830
}
831
 
832
/**
833
 * Called via eglCreateContext(), drv->API.CreateContext().
834
 */
835
static _EGLContext *
836
dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
837
		    _EGLContext *share_list, const EGLint *attrib_list)
838
{
839
   struct dri2_egl_context *dri2_ctx;
840
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
841
   struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list);
842
   __DRIcontext *shared =
843
      dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL;
844
   struct dri2_egl_config *dri2_config = dri2_egl_config(conf);
845
   const __DRIconfig *dri_config;
846
   int api;
847
 
848
   (void) drv;
849
 
850
   dri2_ctx = malloc(sizeof *dri2_ctx);
851
   if (!dri2_ctx) {
852
      _eglError(EGL_BAD_ALLOC, "eglCreateContext");
853
      return NULL;
854
   }
855
 
856
   if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list))
857
      goto cleanup;
858
 
859
   switch (dri2_ctx->base.ClientAPI) {
860
   case EGL_OPENGL_ES_API:
861
      switch (dri2_ctx->base.ClientMajorVersion) {
862
      case 1:
863
         api = __DRI_API_GLES;
864
         break;
865
      case 2:
866
         api = __DRI_API_GLES2;
867
         break;
868
      case 3:
869
         api = __DRI_API_GLES3;
870
         break;
871
      default:
872
         _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
873
         free(dri2_ctx);
874
         return NULL;
875
      }
876
      break;
877
   case EGL_OPENGL_API:
878
      if ((dri2_ctx->base.ClientMajorVersion >= 4
879
           || (dri2_ctx->base.ClientMajorVersion == 3
880
               && dri2_ctx->base.ClientMinorVersion >= 2))
881
          && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
882
         api = __DRI_API_OPENGL_CORE;
883
      else
884
         api = __DRI_API_OPENGL;
885
      break;
886
   default:
887
      _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
888
      free(dri2_ctx);
889
      return NULL;
890
   }
891
 
892
   if (conf != NULL) {
893
      /* The config chosen here isn't necessarily
894
       * used for surfaces later.
895
       * A pixmap surface will use the single config.
896
       * This opportunity depends on disabling the
897
       * doubleBufferMode check in
898
       * src/mesa/main/context.c:check_compatible()
899
       */
900
      if (dri2_config->dri_double_config)
901
         dri_config = dri2_config->dri_double_config;
902
      else
903
         dri_config = dri2_config->dri_single_config;
904
 
905
      /* EGL_WINDOW_BIT is set only when there is a dri_double_config.  This
906
       * makes sure the back buffer will always be used.
907
       */
908
      if (conf->SurfaceType & EGL_WINDOW_BIT)
909
         dri2_ctx->base.WindowRenderBuffer = EGL_BACK_BUFFER;
910
   }
911
   else
912
      dri_config = NULL;
913
 
914
   if (dri2_dpy->dri2) {
915
      if (dri2_dpy->dri2->base.version >= 3) {
916
         unsigned error;
917
         unsigned num_attribs = 0;
918
         uint32_t ctx_attribs[8];
919
 
920
         ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
921
         ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMajorVersion;
922
         ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
923
         ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMinorVersion;
924
 
925
         if (dri2_ctx->base.Flags != 0) {
926
            /* If the implementation doesn't support the __DRI2_ROBUSTNESS
927
             * extension, don't even try to send it the robust-access flag.
928
             * It may explode.  Instead, generate the required EGL error here.
929
             */
930
            if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0
931
                && !dri2_dpy->robustness) {
932
               _eglError(EGL_BAD_MATCH, "eglCreateContext");
933
               goto cleanup;
934
            }
935
 
936
            ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
937
            ctx_attribs[num_attribs++] = dri2_ctx->base.Flags;
938
         }
939
 
940
         if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) {
941
            /* If the implementation doesn't support the __DRI2_ROBUSTNESS
942
             * extension, don't even try to send it a reset strategy.  It may
943
             * explode.  Instead, generate the required EGL error here.
944
             */
945
            if (!dri2_dpy->robustness) {
946
               _eglError(EGL_BAD_CONFIG, "eglCreateContext");
947
               goto cleanup;
948
            }
949
 
950
            ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
951
            ctx_attribs[num_attribs++] = __DRI_CTX_RESET_LOSE_CONTEXT;
952
         }
953
 
954
         assert(num_attribs <= ARRAY_SIZE(ctx_attribs));
955
 
956
	 dri2_ctx->dri_context =
957
	    dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen,
958
                                                 api,
959
                                                 dri_config,
960
                                                 shared,
961
                                                 num_attribs / 2,
962
                                                 ctx_attribs,
963
                                                 & error,
964
                                                 dri2_ctx);
965
	 dri2_create_context_attribs_error(error);
966
      } else {
967
	 dri2_ctx->dri_context =
968
	    dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
969
						   api,
970
						   dri_config,
971
                                                   shared,
972
						   dri2_ctx);
973
      }
974
   } else {
975
      assert(dri2_dpy->swrast);
976
      dri2_ctx->dri_context =
977
         dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen,
978
                                                  api,
979
                                                  dri_config,
980
                                                  shared,
981
                                                  dri2_ctx);
982
   }
983
 
984
   if (!dri2_ctx->dri_context)
985
      goto cleanup;
986
 
987
   return &dri2_ctx->base;
988
 
989
 cleanup:
990
   free(dri2_ctx);
991
   return NULL;
992
}
993
 
994
/**
995
 * Called via eglDestroyContext(), drv->API.DestroyContext().
996
 */
997
static EGLBoolean
998
dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
999
{
1000
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1001
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1002
 
1003
   if (_eglPutContext(ctx)) {
1004
      dri2_dpy->core->destroyContext(dri2_ctx->dri_context);
1005
      free(dri2_ctx);
1006
   }
1007
 
1008
   return EGL_TRUE;
1009
}
1010
 
1011
/**
1012
 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
1013
 */
1014
static EGLBoolean
1015
dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
1016
		  _EGLSurface *rsurf, _EGLContext *ctx)
1017
{
1018
   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
1019
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1020
   struct dri2_egl_surface *dri2_dsurf = dri2_egl_surface(dsurf);
1021
   struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf);
1022
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1023
   _EGLContext *old_ctx;
1024
   _EGLSurface *old_dsurf, *old_rsurf;
1025
   __DRIdrawable *ddraw, *rdraw;
1026
   __DRIcontext *cctx;
1027
 
1028
   /* make new bindings */
1029
   if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
1030
      return EGL_FALSE;
1031
 
1032
   /* flush before context switch */
1033
   if (old_ctx && dri2_drv->glFlush)
1034
      dri2_drv->glFlush();
1035
 
1036
   ddraw = (dri2_dsurf) ? dri2_dsurf->dri_drawable : NULL;
1037
   rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL;
1038
   cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL;
1039
 
1040
   if (old_ctx) {
1041
      __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context;
1042
      dri2_dpy->core->unbindContext(old_cctx);
1043
   }
1044
 
1045
   if ((cctx == NULL && ddraw == NULL && rdraw == NULL) ||
1046
       dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
1047
      if (old_dsurf)
1048
         drv->API.DestroySurface(drv, disp, old_dsurf);
1049
      if (old_rsurf)
1050
         drv->API.DestroySurface(drv, disp, old_rsurf);
1051
      if (old_ctx)
1052
         drv->API.DestroyContext(drv, disp, old_ctx);
1053
 
1054
      return EGL_TRUE;
1055
   } else {
1056
      /* undo the previous _eglBindContext */
1057
      _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf);
1058
      assert(&dri2_ctx->base == ctx &&
1059
             &dri2_dsurf->base == dsurf &&
1060
             &dri2_rsurf->base == rsurf);
1061
 
1062
      _eglPutSurface(dsurf);
1063
      _eglPutSurface(rsurf);
1064
      _eglPutContext(ctx);
1065
 
1066
      _eglPutSurface(old_dsurf);
1067
      _eglPutSurface(old_rsurf);
1068
      _eglPutContext(old_ctx);
1069
 
1070
      return EGL_FALSE;
1071
   }
1072
}
1073
 
1074
/*
1075
 * Called from eglGetProcAddress() via drv->API.GetProcAddress().
1076
 */
1077
static _EGLProc
1078
dri2_get_proc_address(_EGLDriver *drv, const char *procname)
1079
{
1080
   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
1081
 
1082
   return dri2_drv->get_proc_address(procname);
1083
}
1084
 
1085
static _EGLSurface*
1086
dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy,
1087
                           _EGLConfig *conf, void *native_window,
1088
                           const EGLint *attrib_list)
1089
{
1090
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1091
   return dri2_dpy->vtbl->create_window_surface(drv, dpy, conf, native_window,
1092
                                                attrib_list);
1093
}
1094
 
1095
static _EGLSurface*
1096
dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy,
1097
                           _EGLConfig *conf, void *native_pixmap,
1098
                           const EGLint *attrib_list)
1099
{
1100
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1101
   return dri2_dpy->vtbl->create_pixmap_surface(drv, dpy, conf, native_pixmap,
1102
                                                attrib_list);
1103
}
1104
 
1105
static _EGLSurface*
1106
dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy,
1107
                           _EGLConfig *conf, const EGLint *attrib_list)
1108
{
1109
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1110
   return dri2_dpy->vtbl->create_pbuffer_surface(drv, dpy, conf, attrib_list);
1111
}
1112
 
1113
static EGLBoolean
1114
dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
1115
{
1116
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1117
   return dri2_dpy->vtbl->destroy_surface(drv, dpy, surf);
1118
}
1119
 
1120
static EGLBoolean
1121
dri2_swap_interval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
1122
                   EGLint interval)
1123
{
1124
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1125
   return dri2_dpy->vtbl->swap_interval(drv, dpy, surf, interval);
1126
}
1127
 
1128
/**
1129
 * Asks the client API to flush any rendering to the drawable so that we can
1130
 * do our swapbuffers.
1131
 */
1132
void
1133
dri2_flush_drawable_for_swapbuffers(_EGLDisplay *disp, _EGLSurface *draw)
1134
{
1135
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1136
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
1137
 
1138
   if (dri2_dpy->flush) {
1139
      if (dri2_dpy->flush->base.version >= 4) {
1140
         /* We know there's a current context because:
1141
          *
1142
          *     "If surface is not bound to the calling thread’s current
1143
          *      context, an EGL_BAD_SURFACE error is generated."
1144
         */
1145
         _EGLContext *ctx = _eglGetCurrentContext();
1146
         struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1147
 
1148
         /* From the EGL 1.4 spec (page 52):
1149
          *
1150
          *     "The contents of ancillary buffers are always undefined
1151
          *      after calling eglSwapBuffers."
1152
          */
1153
         dri2_dpy->flush->flush_with_flags(dri2_ctx->dri_context,
1154
                                           dri2_surf->dri_drawable,
1155
                                           __DRI2_FLUSH_DRAWABLE |
1156
                                           __DRI2_FLUSH_INVALIDATE_ANCILLARY,
1157
                                           __DRI2_THROTTLE_SWAPBUFFER);
1158
      } else {
1159
         dri2_dpy->flush->flush(dri2_surf->dri_drawable);
1160
      }
1161
   }
1162
}
1163
 
1164
static EGLBoolean
1165
dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
1166
{
1167
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1168
   return dri2_dpy->vtbl->swap_buffers(drv, dpy, surf);
1169
}
1170
 
1171
static EGLBoolean
1172
dri2_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *dpy,
1173
                              _EGLSurface *surf,
1174
                              const EGLint *rects, EGLint n_rects)
1175
{
1176
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1177
   return dri2_dpy->vtbl->swap_buffers_with_damage(drv, dpy, surf,
1178
                                                   rects, n_rects);
1179
}
1180
 
1181
static EGLBoolean
1182
dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
1183
                         EGLint numRects, const EGLint *rects)
1184
{
1185
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1186
   return dri2_dpy->vtbl->swap_buffers_region(drv, dpy, surf, numRects, rects);
1187
}
1188
 
1189
static EGLBoolean
1190
dri2_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
1191
                     EGLint x, EGLint y, EGLint width, EGLint height)
1192
{
1193
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1194
   return dri2_dpy->vtbl->post_sub_buffer(drv, dpy, surf, x, y, width, height);
1195
}
1196
 
1197
static EGLBoolean
1198
dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
1199
                  void *native_pixmap_target)
1200
{
1201
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1202
   return dri2_dpy->vtbl->copy_buffers(drv, dpy, surf, native_pixmap_target);
1203
}
1204
 
1205
static EGLint
1206
dri2_query_buffer_age(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
1207
{
1208
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1209
   return dri2_dpy->vtbl->query_buffer_age(drv, dpy, surf);
1210
}
1211
 
1212
static EGLBoolean
1213
dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
1214
{
1215
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1216
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(ctx->DrawSurface);
1217
 
1218
   (void) drv;
1219
 
1220
   /* FIXME: If EGL allows frontbuffer rendering for window surfaces,
1221
    * we need to copy fake to real here.*/
1222
 
1223
   if (dri2_dpy->flush != NULL)
1224
      dri2_dpy->flush->flush(dri2_surf->dri_drawable);
1225
 
1226
   return EGL_TRUE;
1227
}
1228
 
1229
static EGLBoolean
1230
dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine)
1231
{
1232
   (void) drv;
1233
   (void) disp;
1234
 
1235
   if (engine != EGL_CORE_NATIVE_ENGINE)
1236
      return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
1237
   /* glXWaitX(); */
1238
 
1239
   return EGL_TRUE;
1240
}
1241
 
1242
static EGLBoolean
1243
dri2_bind_tex_image(_EGLDriver *drv,
1244
		    _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
1245
{
1246
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1247
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1248
   struct dri2_egl_context *dri2_ctx;
1249
   _EGLContext *ctx;
1250
   GLint format, target;
1251
 
1252
   ctx = _eglGetCurrentContext();
1253
   dri2_ctx = dri2_egl_context(ctx);
1254
 
1255
   if (!_eglBindTexImage(drv, disp, surf, buffer))
1256
      return EGL_FALSE;
1257
 
1258
   switch (dri2_surf->base.TextureFormat) {
1259
   case EGL_TEXTURE_RGB:
1260
      format = __DRI_TEXTURE_FORMAT_RGB;
1261
      break;
1262
   case EGL_TEXTURE_RGBA:
1263
      format = __DRI_TEXTURE_FORMAT_RGBA;
1264
      break;
1265
   default:
1266
      assert(0);
1267
   }
1268
 
1269
   switch (dri2_surf->base.TextureTarget) {
1270
   case EGL_TEXTURE_2D:
1271
      target = GL_TEXTURE_2D;
1272
      break;
1273
   default:
1274
      assert(0);
1275
   }
1276
 
1277
   (*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context,
1278
					  target, format,
1279
					  dri2_surf->dri_drawable);
1280
 
1281
   return EGL_TRUE;
1282
}
1283
 
1284
static EGLBoolean
1285
dri2_release_tex_image(_EGLDriver *drv,
1286
		       _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
1287
{
1288
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1289
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1290
   struct dri2_egl_context *dri2_ctx;
1291
   _EGLContext *ctx;
1292
   GLint  target;
1293
 
1294
   ctx = _eglGetCurrentContext();
1295
   dri2_ctx = dri2_egl_context(ctx);
1296
 
1297
   if (!_eglReleaseTexImage(drv, disp, surf, buffer))
1298
      return EGL_FALSE;
1299
 
1300
   switch (dri2_surf->base.TextureTarget) {
1301
   case EGL_TEXTURE_2D:
1302
      target = GL_TEXTURE_2D;
1303
      break;
1304
   default:
1305
      assert(0);
1306
   }
1307
 
1308
   if (dri2_dpy->tex_buffer->base.version >= 3 &&
1309
       dri2_dpy->tex_buffer->releaseTexBuffer != NULL) {
1310
      (*dri2_dpy->tex_buffer->releaseTexBuffer)(dri2_ctx->dri_context,
1311
                                                target,
1312
                                                dri2_surf->dri_drawable);
1313
   }
1314
 
1315
   return EGL_TRUE;
1316
}
1317
 
1318
static _EGLImage*
1319
dri2_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
1320
                  EGLenum target, EGLClientBuffer buffer,
1321
                  const EGLint *attr_list)
1322
{
1323
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1324
   return dri2_dpy->vtbl->create_image(drv, dpy, ctx, target, buffer,
1325
                                       attr_list);
1326
}
1327
 
1328
static _EGLImage *
1329
dri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image)
1330
{
1331
   struct dri2_egl_image *dri2_img;
1332
 
1333
   if (dri_image == NULL) {
1334
      _eglError(EGL_BAD_ALLOC, "dri2_create_image");
1335
      return NULL;
1336
   }
1337
 
1338
   dri2_img = malloc(sizeof *dri2_img);
1339
   if (!dri2_img) {
1340
      _eglError(EGL_BAD_ALLOC, "dri2_create_image");
1341
      return NULL;
1342
   }
1343
 
1344
   if (!_eglInitImage(&dri2_img->base, disp)) {
1345
      free(dri2_img);
1346
      return NULL;
1347
   }
1348
 
1349
   dri2_img->dri_image = dri_image;
1350
 
1351
   return &dri2_img->base;
1352
}
1353
 
1354
static _EGLImage *
1355
dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
1356
				   EGLClientBuffer buffer,
1357
				   const EGLint *attr_list)
1358
{
1359
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1360
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1361
   GLuint renderbuffer = (GLuint) (uintptr_t) buffer;
1362
   __DRIimage *dri_image;
1363
 
1364
   if (renderbuffer == 0) {
1365
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
1366
      return EGL_NO_IMAGE_KHR;
1367
   }
1368
 
1369
   dri_image =
1370
      dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context,
1371
                                                   renderbuffer, NULL);
1372
 
1373
   return dri2_create_image_from_dri(disp, dri_image);
1374
}
1375
 
1376
#ifdef HAVE_LIBDRM
1377
static _EGLImage *
1378
dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
1379
				  EGLClientBuffer buffer, const EGLint *attr_list)
1380
{
1381
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1382
   EGLint format, name, pitch, err;
1383
   _EGLImageAttribs attrs;
1384
   __DRIimage *dri_image;
1385
 
1386
   name = (EGLint) (uintptr_t) buffer;
1387
 
1388
   err = _eglParseImageAttribList(&attrs, disp, attr_list);
1389
   if (err != EGL_SUCCESS)
1390
      return NULL;
1391
 
1392
   if (attrs.Width <= 0 || attrs.Height <= 0 ||
1393
       attrs.DRMBufferStrideMESA <= 0) {
1394
      _eglError(EGL_BAD_PARAMETER,
1395
		"bad width, height or stride");
1396
      return NULL;
1397
   }
1398
 
1399
   switch (attrs.DRMBufferFormatMESA) {
1400
   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
1401
      format = __DRI_IMAGE_FORMAT_ARGB8888;
1402
      pitch = attrs.DRMBufferStrideMESA;
1403
      break;
1404
   default:
1405
      _eglError(EGL_BAD_PARAMETER,
1406
		"dri2_create_image_khr: unsupported pixmap depth");
1407
      return NULL;
1408
   }
1409
 
1410
   dri_image =
1411
      dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
1412
					   attrs.Width,
1413
					   attrs.Height,
1414
					   format,
1415
					   name,
1416
					   pitch,
1417
					   NULL);
1418
 
1419
   return dri2_create_image_from_dri(disp, dri_image);
1420
}
1421
#endif
1422
 
1423
#ifdef HAVE_WAYLAND_PLATFORM
1424
 
1425
/* This structure describes how a wl_buffer maps to one or more
1426
 * __DRIimages.  A wl_drm_buffer stores the wl_drm format code and the
1427
 * offsets and strides of the planes in the buffer.  This table maps a
1428
 * wl_drm format code to a description of the planes in the buffer
1429
 * that lets us create a __DRIimage for each of the planes. */
1430
 
1431
static const struct wl_drm_components_descriptor {
1432
   uint32_t dri_components;
1433
   EGLint components;
1434
   int nplanes;
1435
} wl_drm_components[] = {
1436
   { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 },
1437
   { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 },
1438
   { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 },
1439
   { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 },
1440
   { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 },
1441
};
1442
 
1443
static _EGLImage *
1444
dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
1445
				    EGLClientBuffer _buffer,
1446
				    const EGLint *attr_list)
1447
{
1448
   struct wl_drm_buffer *buffer;
1449
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1450
   const struct wl_drm_components_descriptor *f;
1451
   __DRIimage *dri_image;
1452
   _EGLImageAttribs attrs;
1453
   EGLint err;
1454
   int32_t plane;
1455
 
1456
   buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm,
1457
                                   (struct wl_resource *) _buffer);
1458
   if (!buffer)
1459
       return NULL;
1460
 
1461
   err = _eglParseImageAttribList(&attrs, disp, attr_list);
1462
   plane = attrs.PlaneWL;
1463
   if (err != EGL_SUCCESS) {
1464
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
1465
      return NULL;
1466
   }
1467
 
1468
   f = buffer->driver_format;
1469
   if (plane < 0 || plane >= f->nplanes) {
1470
      _eglError(EGL_BAD_PARAMETER,
1471
                "dri2_create_image_wayland_wl_buffer (plane out of bounds)");
1472
      return NULL;
1473
   }
1474
 
1475
   dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL);
1476
 
1477
   if (dri_image == NULL) {
1478
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
1479
      return NULL;
1480
   }
1481
 
1482
   return dri2_create_image_from_dri(disp, dri_image);
1483
}
1484
#endif
1485
 
1486
static EGLBoolean
1487
dri2_get_sync_values_chromium(_EGLDisplay *dpy, _EGLSurface *surf,
1488
                              EGLuint64KHR *ust, EGLuint64KHR *msc,
1489
                              EGLuint64KHR *sbc)
1490
{
1491
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1492
   return dri2_dpy->vtbl->get_sync_values(dpy, surf, ust, msc, sbc);
1493
}
1494
 
1495
/**
1496
 * Set the error code after a call to
1497
 * dri2_egl_image::dri_image::createImageFromTexture.
1498
 */
1499
static void
1500
dri2_create_image_khr_texture_error(int dri_error)
1501
{
1502
   EGLint egl_error;
1503
 
1504
   switch (dri_error) {
1505
   case __DRI_IMAGE_ERROR_SUCCESS:
1506
      return;
1507
 
1508
   case __DRI_IMAGE_ERROR_BAD_ALLOC:
1509
      egl_error = EGL_BAD_ALLOC;
1510
      break;
1511
 
1512
   case __DRI_IMAGE_ERROR_BAD_MATCH:
1513
      egl_error = EGL_BAD_MATCH;
1514
      break;
1515
 
1516
   case __DRI_IMAGE_ERROR_BAD_PARAMETER:
1517
      egl_error = EGL_BAD_PARAMETER;
1518
      break;
1519
 
1520
   default:
1521
      assert(0);
1522
      egl_error = EGL_BAD_MATCH;
1523
      break;
1524
   }
1525
 
1526
   _eglError(egl_error, "dri2_create_image_khr_texture");
1527
}
1528
 
1529
static _EGLImage *
1530
dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
1531
				   EGLenum target,
1532
				   EGLClientBuffer buffer,
1533
				   const EGLint *attr_list)
1534
{
1535
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1536
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1537
   struct dri2_egl_image *dri2_img;
1538
   GLuint texture = (GLuint) (uintptr_t) buffer;
1539
   _EGLImageAttribs attrs;
1540
   GLuint depth;
1541
   GLenum gl_target;
1542
   unsigned error;
1543
 
1544
   if (texture == 0) {
1545
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
1546
      return EGL_NO_IMAGE_KHR;
1547
   }
1548
 
1549
   if (_eglParseImageAttribList(&attrs, disp, attr_list) != EGL_SUCCESS)
1550
      return EGL_NO_IMAGE_KHR;
1551
 
1552
   switch (target) {
1553
   case EGL_GL_TEXTURE_2D_KHR:
1554
      depth = 0;
1555
      gl_target = GL_TEXTURE_2D;
1556
      break;
1557
   case EGL_GL_TEXTURE_3D_KHR:
1558
      depth = attrs.GLTextureZOffset;
1559
      gl_target = GL_TEXTURE_3D;
1560
      break;
1561
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
1562
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
1563
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
1564
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
1565
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
1566
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
1567
      depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
1568
      gl_target = GL_TEXTURE_CUBE_MAP;
1569
      break;
1570
   default:
1571
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
1572
      return EGL_NO_IMAGE_KHR;
1573
   }
1574
 
1575
   dri2_img = malloc(sizeof *dri2_img);
1576
   if (!dri2_img) {
1577
      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
1578
      return EGL_NO_IMAGE_KHR;
1579
   }
1580
 
1581
   if (!_eglInitImage(&dri2_img->base, disp)) {
1582
      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
1583
      free(dri2_img);
1584
      return EGL_NO_IMAGE_KHR;
1585
   }
1586
 
1587
   dri2_img->dri_image =
1588
      dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context,
1589
                                              gl_target,
1590
                                              texture,
1591
                                              depth,
1592
                                              attrs.GLTextureLevel,
1593
                                              &error,
1594
                                              dri2_img);
1595
   dri2_create_image_khr_texture_error(error);
1596
 
1597
   if (!dri2_img->dri_image) {
1598
      free(dri2_img);
1599
      return EGL_NO_IMAGE_KHR;
1600
   }
1601
   return &dri2_img->base;
1602
}
1603
 
1604
static struct wl_buffer*
1605
dri2_create_wayland_buffer_from_image(_EGLDriver *drv, _EGLDisplay *dpy,
1606
                                      _EGLImage *img)
1607
{
1608
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1609
   return dri2_dpy->vtbl->create_wayland_buffer_from_image(drv, dpy, img);
1610
}
1611
 
1612
#ifdef HAVE_LIBDRM
1613
static EGLBoolean
1614
dri2_check_dma_buf_attribs(const _EGLImageAttribs *attrs)
1615
{
1616
   unsigned i;
1617
 
1618
   /**
1619
     * The spec says:
1620
     *
1621
     * "Required attributes and their values are as follows:
1622
     *
1623
     *  * EGL_WIDTH & EGL_HEIGHT: The logical dimensions of the buffer in pixels
1624
     *
1625
     *  * EGL_LINUX_DRM_FOURCC_EXT: The pixel format of the buffer, as specified
1626
     *    by drm_fourcc.h and used as the pixel_format parameter of the
1627
     *    drm_mode_fb_cmd2 ioctl."
1628
     *
1629
     * and
1630
     *
1631
     * "* If  is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is
1632
     *    incomplete, EGL_BAD_PARAMETER is generated."
1633
     */
1634
   if (attrs->Width <= 0 || attrs->Height <= 0 ||
1635
       !attrs->DMABufFourCC.IsPresent) {
1636
      _eglError(EGL_BAD_PARAMETER, "attribute(s) missing");
1637
      return EGL_FALSE;
1638
   }
1639
 
1640
   /**
1641
    * Also:
1642
    *
1643
    * "If  is EGL_LINUX_DMA_BUF_EXT and one or more of the values
1644
    *  specified for a plane's pitch or offset isn't supported by EGL,
1645
    *  EGL_BAD_ACCESS is generated."
1646
    */
1647
   for (i = 0; i < ARRAY_SIZE(attrs->DMABufPlanePitches); ++i) {
1648
      if (attrs->DMABufPlanePitches[i].IsPresent &&
1649
          attrs->DMABufPlanePitches[i].Value <= 0) {
1650
         _eglError(EGL_BAD_ACCESS, "invalid pitch");
1651
         return EGL_FALSE;
1652
      }
1653
   }
1654
 
1655
   return EGL_TRUE;
1656
}
1657
 
1658
/* Returns the total number of file descriptors. Zero indicates an error. */
1659
static unsigned
1660
dri2_check_dma_buf_format(const _EGLImageAttribs *attrs)
1661
{
1662
   unsigned i, plane_n;
1663
 
1664
   switch (attrs->DMABufFourCC.Value) {
1665
   case DRM_FORMAT_RGB332:
1666
   case DRM_FORMAT_BGR233:
1667
   case DRM_FORMAT_XRGB4444:
1668
   case DRM_FORMAT_XBGR4444:
1669
   case DRM_FORMAT_RGBX4444:
1670
   case DRM_FORMAT_BGRX4444:
1671
   case DRM_FORMAT_ARGB4444:
1672
   case DRM_FORMAT_ABGR4444:
1673
   case DRM_FORMAT_RGBA4444:
1674
   case DRM_FORMAT_BGRA4444:
1675
   case DRM_FORMAT_XRGB1555:
1676
   case DRM_FORMAT_XBGR1555:
1677
   case DRM_FORMAT_RGBX5551:
1678
   case DRM_FORMAT_BGRX5551:
1679
   case DRM_FORMAT_ARGB1555:
1680
   case DRM_FORMAT_ABGR1555:
1681
   case DRM_FORMAT_RGBA5551:
1682
   case DRM_FORMAT_BGRA5551:
1683
   case DRM_FORMAT_RGB565:
1684
   case DRM_FORMAT_BGR565:
1685
   case DRM_FORMAT_RGB888:
1686
   case DRM_FORMAT_BGR888:
1687
   case DRM_FORMAT_XRGB8888:
1688
   case DRM_FORMAT_XBGR8888:
1689
   case DRM_FORMAT_RGBX8888:
1690
   case DRM_FORMAT_BGRX8888:
1691
   case DRM_FORMAT_ARGB8888:
1692
   case DRM_FORMAT_ABGR8888:
1693
   case DRM_FORMAT_RGBA8888:
1694
   case DRM_FORMAT_BGRA8888:
1695
   case DRM_FORMAT_XRGB2101010:
1696
   case DRM_FORMAT_XBGR2101010:
1697
   case DRM_FORMAT_RGBX1010102:
1698
   case DRM_FORMAT_BGRX1010102:
1699
   case DRM_FORMAT_ARGB2101010:
1700
   case DRM_FORMAT_ABGR2101010:
1701
   case DRM_FORMAT_RGBA1010102:
1702
   case DRM_FORMAT_BGRA1010102:
1703
   case DRM_FORMAT_YUYV:
1704
   case DRM_FORMAT_YVYU:
1705
   case DRM_FORMAT_UYVY:
1706
   case DRM_FORMAT_VYUY:
1707
      plane_n = 1;
1708
      break;
1709
   case DRM_FORMAT_NV12:
1710
   case DRM_FORMAT_NV21:
1711
   case DRM_FORMAT_NV16:
1712
   case DRM_FORMAT_NV61:
1713
      plane_n = 2;
1714
      break;
1715
   case DRM_FORMAT_YUV410:
1716
   case DRM_FORMAT_YVU410:
1717
   case DRM_FORMAT_YUV411:
1718
   case DRM_FORMAT_YVU411:
1719
   case DRM_FORMAT_YUV420:
1720
   case DRM_FORMAT_YVU420:
1721
   case DRM_FORMAT_YUV422:
1722
   case DRM_FORMAT_YVU422:
1723
   case DRM_FORMAT_YUV444:
1724
   case DRM_FORMAT_YVU444:
1725
      plane_n = 3;
1726
      break;
1727
   default:
1728
      _eglError(EGL_BAD_ATTRIBUTE, "invalid format");
1729
      return 0;
1730
   }
1731
 
1732
   /**
1733
     * The spec says:
1734
     *
1735
     * "* If  is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is
1736
     *    incomplete, EGL_BAD_PARAMETER is generated."
1737
     */
1738
   for (i = 0; i < plane_n; ++i) {
1739
      if (!attrs->DMABufPlaneFds[i].IsPresent ||
1740
          !attrs->DMABufPlaneOffsets[i].IsPresent ||
1741
          !attrs->DMABufPlanePitches[i].IsPresent) {
1742
         _eglError(EGL_BAD_PARAMETER, "plane attribute(s) missing");
1743
         return 0;
1744
      }
1745
   }
1746
 
1747
   /**
1748
    * The spec also says:
1749
    *
1750
    * "If  is EGL_LINUX_DMA_BUF_EXT, and the EGL_LINUX_DRM_FOURCC_EXT
1751
    *  attribute indicates a single-plane format, EGL_BAD_ATTRIBUTE is
1752
    *  generated if any of the EGL_DMA_BUF_PLANE1_* or EGL_DMA_BUF_PLANE2_*
1753
    *  attributes are specified."
1754
    */
1755
   for (i = plane_n; i < 3; ++i) {
1756
      if (attrs->DMABufPlaneFds[i].IsPresent ||
1757
          attrs->DMABufPlaneOffsets[i].IsPresent ||
1758
          attrs->DMABufPlanePitches[i].IsPresent) {
1759
         _eglError(EGL_BAD_ATTRIBUTE, "too many plane attributes");
1760
         return 0;
1761
      }
1762
   }
1763
 
1764
   return plane_n;
1765
}
1766
 
1767
/**
1768
 * The spec says:
1769
 *
1770
 * "If eglCreateImageKHR is successful for a EGL_LINUX_DMA_BUF_EXT target, the
1771
 *  EGL will take a reference to the dma_buf(s) which it will release at any
1772
 *  time while the EGLDisplay is initialized. It is the responsibility of the
1773
 *  application to close the dma_buf file descriptors."
1774
 *
1775
 * Therefore we must never close or otherwise modify the file descriptors.
1776
 */
1777
static _EGLImage *
1778
dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
1779
			  EGLClientBuffer buffer, const EGLint *attr_list)
1780
{
1781
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1782
   _EGLImage *res;
1783
   EGLint err;
1784
   _EGLImageAttribs attrs;
1785
   __DRIimage *dri_image;
1786
   unsigned num_fds;
1787
   unsigned i;
1788
   int fds[3];
1789
   int pitches[3];
1790
   int offsets[3];
1791
   unsigned error;
1792
 
1793
   /**
1794
    * The spec says:
1795
    *
1796
    * ""* If  is EGL_LINUX_DMA_BUF_EXT and  is not NULL, the
1797
    *     error EGL_BAD_PARAMETER is generated."
1798
    */
1799
   if (buffer != NULL) {
1800
      _eglError(EGL_BAD_PARAMETER, "buffer not NULL");
1801
      return NULL;
1802
   }
1803
 
1804
   err = _eglParseImageAttribList(&attrs, disp, attr_list);
1805
   if (err != EGL_SUCCESS) {
1806
      _eglError(err, "bad attribute");
1807
      return NULL;
1808
   }
1809
 
1810
   if (!dri2_check_dma_buf_attribs(&attrs))
1811
      return NULL;
1812
 
1813
   num_fds = dri2_check_dma_buf_format(&attrs);
1814
   if (!num_fds)
1815
      return NULL;
1816
 
1817
   for (i = 0; i < num_fds; ++i) {
1818
      fds[i] = attrs.DMABufPlaneFds[i].Value;
1819
      pitches[i] = attrs.DMABufPlanePitches[i].Value;
1820
      offsets[i] = attrs.DMABufPlaneOffsets[i].Value;
1821
   }
1822
 
1823
   dri_image =
1824
      dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen,
1825
         attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
1826
         fds, num_fds, pitches, offsets,
1827
         attrs.DMABufYuvColorSpaceHint.Value,
1828
         attrs.DMABufSampleRangeHint.Value,
1829
         attrs.DMABufChromaHorizontalSiting.Value,
1830
         attrs.DMABufChromaVerticalSiting.Value,
1831
         &error,
1832
         NULL);
1833
   dri2_create_image_khr_texture_error(error);
1834
 
1835
   if (!dri_image)
1836
      return EGL_NO_IMAGE_KHR;
1837
 
1838
   res = dri2_create_image_from_dri(disp, dri_image);
1839
 
1840
   return res;
1841
}
1842
#endif
1843
 
1844
_EGLImage *
1845
dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
1846
		      _EGLContext *ctx, EGLenum target,
1847
		      EGLClientBuffer buffer, const EGLint *attr_list)
1848
{
1849
   (void) drv;
1850
 
1851
   switch (target) {
1852
   case EGL_GL_TEXTURE_2D_KHR:
1853
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
1854
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
1855
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
1856
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
1857
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
1858
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
1859
      return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
1860
   case EGL_GL_RENDERBUFFER_KHR:
1861
      return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
1862
#ifdef HAVE_LIBDRM
1863
   case EGL_DRM_BUFFER_MESA:
1864
      return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
1865
#endif
1866
#ifdef HAVE_WAYLAND_PLATFORM
1867
   case EGL_WAYLAND_BUFFER_WL:
1868
      return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
1869
#endif
1870
#ifdef HAVE_LIBDRM
1871
   case EGL_LINUX_DMA_BUF_EXT:
1872
      return dri2_create_image_dma_buf(disp, ctx, buffer, attr_list);
1873
#endif
1874
   default:
1875
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
1876
      return EGL_NO_IMAGE_KHR;
1877
   }
1878
}
1879
 
1880
static EGLBoolean
1881
dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image)
1882
{
1883
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1884
   struct dri2_egl_image *dri2_img = dri2_egl_image(image);
1885
 
1886
   (void) drv;
1887
 
1888
   dri2_dpy->image->destroyImage(dri2_img->dri_image);
1889
   free(dri2_img);
1890
 
1891
   return EGL_TRUE;
1892
}
1893
 
1894
#ifdef HAVE_LIBDRM
1895
static _EGLImage *
1896
dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp,
1897
			   const EGLint *attr_list)
1898
{
1899
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1900
   struct dri2_egl_image *dri2_img;
1901
   _EGLImageAttribs attrs;
1902
   unsigned int dri_use, valid_mask;
1903
   int format;
1904
   EGLint err = EGL_SUCCESS;
1905
 
1906
   (void) drv;
1907
 
1908
   dri2_img = malloc(sizeof *dri2_img);
1909
   if (!dri2_img) {
1910
      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
1911
      return EGL_NO_IMAGE_KHR;
1912
   }
1913
 
1914
   if (!attr_list) {
1915
      err = EGL_BAD_PARAMETER;
1916
      goto cleanup_img;
1917
   }
1918
 
1919
   if (!_eglInitImage(&dri2_img->base, disp)) {
1920
      err = EGL_BAD_PARAMETER;
1921
      goto cleanup_img;
1922
   }
1923
 
1924
   err = _eglParseImageAttribList(&attrs, disp, attr_list);
1925
   if (err != EGL_SUCCESS)
1926
      goto cleanup_img;
1927
 
1928
   if (attrs.Width <= 0 || attrs.Height <= 0) {
1929
      _eglLog(_EGL_WARNING, "bad width or height (%dx%d)",
1930
            attrs.Width, attrs.Height);
1931
      goto cleanup_img;
1932
   }
1933
 
1934
   switch (attrs.DRMBufferFormatMESA) {
1935
   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
1936
      format = __DRI_IMAGE_FORMAT_ARGB8888;
1937
      break;
1938
   default:
1939
      _eglLog(_EGL_WARNING, "bad image format value 0x%04x",
1940
            attrs.DRMBufferFormatMESA);
1941
      goto cleanup_img;
1942
   }
1943
 
1944
   valid_mask =
1945
      EGL_DRM_BUFFER_USE_SCANOUT_MESA |
1946
      EGL_DRM_BUFFER_USE_SHARE_MESA |
1947
      EGL_DRM_BUFFER_USE_CURSOR_MESA;
1948
   if (attrs.DRMBufferUseMESA & ~valid_mask) {
1949
      _eglLog(_EGL_WARNING, "bad image use bit 0x%04x",
1950
            attrs.DRMBufferUseMESA & ~valid_mask);
1951
      goto cleanup_img;
1952
   }
1953
 
1954
   dri_use = 0;
1955
   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA)
1956
      dri_use |= __DRI_IMAGE_USE_SHARE;
1957
   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
1958
      dri_use |= __DRI_IMAGE_USE_SCANOUT;
1959
   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA)
1960
      dri_use |= __DRI_IMAGE_USE_CURSOR;
1961
 
1962
   dri2_img->dri_image =
1963
      dri2_dpy->image->createImage(dri2_dpy->dri_screen,
1964
				   attrs.Width, attrs.Height,
1965
                                   format, dri_use, dri2_img);
1966
   if (dri2_img->dri_image == NULL) {
1967
      err = EGL_BAD_ALLOC;
1968
      goto cleanup_img;
1969
   }
1970
 
1971
   return &dri2_img->base;
1972
 
1973
 cleanup_img:
1974
   free(dri2_img);
1975
   _eglError(err, "dri2_create_drm_image_mesa");
1976
 
1977
   return EGL_NO_IMAGE_KHR;
1978
}
1979
 
1980
static EGLBoolean
1981
dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
1982
			  EGLint *name, EGLint *handle, EGLint *stride)
1983
{
1984
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1985
   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
1986
 
1987
   (void) drv;
1988
 
1989
   if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
1990
					    __DRI_IMAGE_ATTRIB_NAME, name)) {
1991
      _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
1992
      return EGL_FALSE;
1993
   }
1994
 
1995
   if (handle)
1996
      dri2_dpy->image->queryImage(dri2_img->dri_image,
1997
				  __DRI_IMAGE_ATTRIB_HANDLE, handle);
1998
 
1999
   if (stride)
2000
      dri2_dpy->image->queryImage(dri2_img->dri_image,
2001
				  __DRI_IMAGE_ATTRIB_STRIDE, stride);
2002
 
2003
   return EGL_TRUE;
2004
}
2005
 
2006
static EGLBoolean
2007
dri2_export_dma_buf_image_query_mesa(_EGLDriver *drv, _EGLDisplay *disp,
2008
                                     _EGLImage *img,
2009
                                     EGLint *fourcc, EGLint *nplanes,
2010
                                     EGLuint64KHR *modifiers)
2011
{
2012
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2013
   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
2014
 
2015
   (void) drv;
2016
 
2017
 
2018
   if (nplanes)
2019
      dri2_dpy->image->queryImage(dri2_img->dri_image,
2020
				  __DRI_IMAGE_ATTRIB_NUM_PLANES, nplanes);
2021
   if (fourcc)
2022
      dri2_dpy->image->queryImage(dri2_img->dri_image,
2023
				  __DRI_IMAGE_ATTRIB_FOURCC, fourcc);
2024
 
2025
   if (modifiers)
2026
      *modifiers = 0;
2027
 
2028
   return EGL_TRUE;
2029
}
2030
 
2031
static EGLBoolean
2032
dri2_export_dma_buf_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
2033
                               int *fds, EGLint *strides, EGLint *offsets)
2034
{
2035
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2036
   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
2037
 
2038
   (void) drv;
2039
 
2040
   /* rework later to provide multiple fds/strides/offsets */
2041
   if (fds)
2042
      dri2_dpy->image->queryImage(dri2_img->dri_image,
2043
				  __DRI_IMAGE_ATTRIB_FD, fds);
2044
 
2045
   if (strides)
2046
      dri2_dpy->image->queryImage(dri2_img->dri_image,
2047
				  __DRI_IMAGE_ATTRIB_STRIDE, strides);
2048
 
2049
   if (offsets)
2050
      offsets[0] = 0;
2051
 
2052
   return EGL_TRUE;
2053
}
2054
#endif
2055
 
2056
#ifdef HAVE_WAYLAND_PLATFORM
2057
 
2058
static void
2059
dri2_wl_reference_buffer(void *user_data, uint32_t name, int fd,
2060
                         struct wl_drm_buffer *buffer)
2061
{
2062
   _EGLDisplay *disp = user_data;
2063
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2064
   __DRIimage *img;
2065
   int i, dri_components = 0;
2066
 
2067
   if (fd == -1)
2068
      img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen,
2069
                                                  buffer->width,
2070
                                                  buffer->height,
2071
                                                  buffer->format,
2072
                                                  (int*)&name, 1,
2073
                                                  buffer->stride,
2074
                                                  buffer->offset,
2075
                                                  NULL);
2076
   else
2077
      img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
2078
                                                buffer->width,
2079
                                                buffer->height,
2080
                                                buffer->format,
2081
                                                &fd, 1,
2082
                                                buffer->stride,
2083
                                                buffer->offset,
2084
                                                NULL);
2085
 
2086
   if (img == NULL)
2087
      return;
2088
 
2089
   dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components);
2090
 
2091
   buffer->driver_format = NULL;
2092
   for (i = 0; i < ARRAY_SIZE(wl_drm_components); i++)
2093
      if (wl_drm_components[i].dri_components == dri_components)
2094
         buffer->driver_format = &wl_drm_components[i];
2095
 
2096
   if (buffer->driver_format == NULL)
2097
      dri2_dpy->image->destroyImage(img);
2098
   else
2099
      buffer->driver_buffer = img;
2100
}
2101
 
2102
static void
2103
dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer)
2104
{
2105
   _EGLDisplay *disp = user_data;
2106
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2107
 
2108
   dri2_dpy->image->destroyImage(buffer->driver_buffer);
2109
}
2110
 
2111
static struct wayland_drm_callbacks wl_drm_callbacks = {
2112
	.authenticate = NULL,
2113
	.reference_buffer = dri2_wl_reference_buffer,
2114
	.release_buffer = dri2_wl_release_buffer
2115
};
2116
 
2117
static EGLBoolean
2118
dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
2119
			     struct wl_display *wl_dpy)
2120
{
2121
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2122
   int flags = 0;
2123
   uint64_t cap;
2124
 
2125
   (void) drv;
2126
 
2127
   if (dri2_dpy->wl_server_drm)
2128
	   return EGL_FALSE;
2129
 
2130
   wl_drm_callbacks.authenticate =
2131
      (int(*)(void *, uint32_t)) dri2_dpy->vtbl->authenticate;
2132
 
2133
#ifdef HAVE_LIBDRM
2134
   if (drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap) == 0 &&
2135
       cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT) &&
2136
       dri2_dpy->image->base.version >= 7 &&
2137
       dri2_dpy->image->createImageFromFds != NULL)
2138
      flags |= WAYLAND_DRM_PRIME;
2139
#endif
2140
 
2141
   dri2_dpy->wl_server_drm =
2142
	   wayland_drm_init(wl_dpy, dri2_dpy->device_name,
2143
                            &wl_drm_callbacks, disp, flags);
2144
 
2145
   if (!dri2_dpy->wl_server_drm)
2146
	   return EGL_FALSE;
2147
 
2148
#ifdef HAVE_DRM_PLATFORM
2149
   /* We have to share the wl_drm instance with gbm, so gbm can convert
2150
    * wl_buffers to gbm bos. */
2151
   if (dri2_dpy->gbm_dri)
2152
      dri2_dpy->gbm_dri->wl_drm = dri2_dpy->wl_server_drm;
2153
#endif
2154
 
2155
   return EGL_TRUE;
2156
}
2157
 
2158
static EGLBoolean
2159
dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
2160
			       struct wl_display *wl_dpy)
2161
{
2162
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2163
 
2164
   (void) drv;
2165
 
2166
   if (!dri2_dpy->wl_server_drm)
2167
	   return EGL_FALSE;
2168
 
2169
   wayland_drm_uninit(dri2_dpy->wl_server_drm);
2170
   dri2_dpy->wl_server_drm = NULL;
2171
 
2172
   return EGL_TRUE;
2173
}
2174
 
2175
static EGLBoolean
2176
dri2_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *disp,
2177
                             struct wl_resource *buffer_resource,
2178
                             EGLint attribute, EGLint *value)
2179
{
2180
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2181
   struct wl_drm_buffer *buffer;
2182
   const struct wl_drm_components_descriptor *format;
2183
 
2184
   buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, buffer_resource);
2185
   if (!buffer)
2186
      return EGL_FALSE;
2187
 
2188
   format = buffer->driver_format;
2189
   switch (attribute) {
2190
   case EGL_TEXTURE_FORMAT:
2191
      *value = format->components;
2192
      return EGL_TRUE;
2193
   case EGL_WIDTH:
2194
      *value = buffer->width;
2195
      return EGL_TRUE;
2196
   case EGL_HEIGHT:
2197
      *value = buffer->height;
2198
      return EGL_TRUE;
2199
   }
2200
 
2201
   return EGL_FALSE;
2202
}
2203
#endif
2204
 
2205
static void
2206
dri2_egl_ref_sync(struct dri2_egl_sync *sync)
2207
{
2208
   p_atomic_inc(&sync->refcount);
2209
}
2210
 
2211
static void
2212
dri2_egl_unref_sync(struct dri2_egl_display *dri2_dpy,
2213
                    struct dri2_egl_sync *dri2_sync)
2214
{
2215
   if (p_atomic_dec_zero(&dri2_sync->refcount)) {
2216
      dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, dri2_sync->fence);
2217
      free(dri2_sync);
2218
   }
2219
}
2220
 
2221
static _EGLSync *
2222
dri2_create_sync(_EGLDriver *drv, _EGLDisplay *dpy,
2223
                 EGLenum type, const EGLint *attrib_list,
2224
                 const EGLAttribKHR *attrib_list64)
2225
{
2226
   _EGLContext *ctx = _eglGetCurrentContext();
2227
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
2228
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
2229
   struct dri2_egl_sync *dri2_sync;
2230
 
2231
   dri2_sync = calloc(1, sizeof(struct dri2_egl_sync));
2232
   if (!dri2_sync) {
2233
      _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
2234
      return NULL;
2235
   }
2236
 
2237
   if (!_eglInitSync(&dri2_sync->base, dpy, type, attrib_list,
2238
                     attrib_list64)) {
2239
      free(dri2_sync);
2240
      return NULL;
2241
   }
2242
 
2243
   switch (type) {
2244
   case EGL_SYNC_FENCE_KHR:
2245
      dri2_sync->fence = dri2_dpy->fence->create_fence(dri2_ctx->dri_context);
2246
      if (!dri2_sync->fence) {
2247
         /* Why did it fail? DRI doesn't return an error code, so we emit
2248
          * a generic EGL error that doesn't communicate user error.
2249
          */
2250
         _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
2251
         free(dri2_sync);
2252
         return NULL;
2253
      }
2254
      break;
2255
 
2256
   case EGL_SYNC_CL_EVENT_KHR:
2257
      dri2_sync->fence = dri2_dpy->fence->get_fence_from_cl_event(
2258
                                 dri2_dpy->dri_screen,
2259
                                 dri2_sync->base.CLEvent);
2260
      /* this can only happen if the cl_event passed in is invalid. */
2261
      if (!dri2_sync->fence) {
2262
         _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
2263
         free(dri2_sync);
2264
         return NULL;
2265
      }
2266
 
2267
      /* the initial status must be "signaled" if the cl_event is signaled */
2268
      if (dri2_dpy->fence->client_wait_sync(dri2_ctx->dri_context,
2269
                                            dri2_sync->fence, 0, 0))
2270
         dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
2271
      break;
2272
   }
2273
 
2274
   p_atomic_set(&dri2_sync->refcount, 1);
2275
   return &dri2_sync->base;
2276
}
2277
 
2278
static EGLBoolean
2279
dri2_destroy_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync)
2280
{
2281
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
2282
   struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
2283
 
2284
   dri2_egl_unref_sync(dri2_dpy, dri2_sync);
2285
   return EGL_TRUE;
2286
}
2287
 
2288
static EGLint
2289
dri2_client_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
2290
                      EGLint flags, EGLTimeKHR timeout)
2291
{
2292
   _EGLContext *ctx = _eglGetCurrentContext();
2293
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
2294
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
2295
   struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
2296
   unsigned wait_flags = 0;
2297
   EGLint ret = EGL_CONDITION_SATISFIED_KHR;
2298
 
2299
   if (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)
2300
      wait_flags |= __DRI2_FENCE_FLAG_FLUSH_COMMANDS;
2301
 
2302
   /* the sync object should take a reference while waiting */
2303
   dri2_egl_ref_sync(dri2_sync);
2304
 
2305
   if (dri2_dpy->fence->client_wait_sync(dri2_ctx->dri_context,
2306
                                         dri2_sync->fence, wait_flags,
2307
                                         timeout))
2308
      dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
2309
   else
2310
      ret = EGL_TIMEOUT_EXPIRED_KHR;
2311
 
2312
   dri2_egl_unref_sync(dri2_dpy, dri2_sync);
2313
   return ret;
2314
}
2315
 
2316
static EGLint
2317
dri2_server_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync)
2318
{
2319
   _EGLContext *ctx = _eglGetCurrentContext();
2320
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
2321
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
2322
   struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
2323
 
2324
   dri2_dpy->fence->server_wait_sync(dri2_ctx->dri_context,
2325
                                     dri2_sync->fence, 0);
2326
   return EGL_TRUE;
2327
}
2328
 
2329
static void
2330
dri2_unload(_EGLDriver *drv)
2331
{
2332
   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
2333
 
2334
   if (dri2_drv->handle)
2335
      dlclose(dri2_drv->handle);
2336
   free(dri2_drv);
2337
}
2338
 
2339
static EGLBoolean
2340
dri2_load(_EGLDriver *drv)
2341
{
2342
   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
2343
#ifdef HAVE_SHARED_GLAPI
2344
#ifdef HAVE_ANDROID_PLATFORM
2345
   const char *libname = "libglapi.so";
2346
#else
2347
   const char *libname = "libglapi.so.0";
2348
#endif
2349
#else
2350
   /*
2351
    * Both libGL.so and libglapi.so are glapi providers.  There is no way to
2352
    * tell which one to load.
2353
    */
2354
   const char *libname = NULL;
2355
#endif
2356
   void *handle;
2357
 
2358
   /* RTLD_GLOBAL to make sure glapi symbols are visible to DRI drivers */
2359
   handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL);
2360
   if (handle) {
2361
      dri2_drv->get_proc_address = (_EGLProc (*)(const char *))
2362
         dlsym(handle, "_glapi_get_proc_address");
2363
      if (!dri2_drv->get_proc_address || !libname) {
2364
         /* no need to keep a reference */
2365
         dlclose(handle);
2366
         handle = NULL;
2367
      }
2368
   }
2369
 
2370
   /* if glapi is not available, loading DRI drivers will fail */
2371
   if (!dri2_drv->get_proc_address) {
2372
      _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address");
2373
      return EGL_FALSE;
2374
   }
2375
 
2376
   dri2_drv->glFlush = (void (*)(void))
2377
      dri2_drv->get_proc_address("glFlush");
2378
 
2379
   dri2_drv->handle = handle;
2380
 
2381
   return EGL_TRUE;
2382
}
2383
 
2384
/**
2385
 * This is the main entrypoint into the driver, called by libEGL.
2386
 * Create a new _EGLDriver object and init its dispatch table.
2387
 */
2388
_EGLDriver *
2389
_eglBuiltInDriverDRI2(const char *args)
2390
{
2391
   struct dri2_egl_driver *dri2_drv;
2392
 
2393
   (void) args;
2394
 
2395
   dri2_drv = calloc(1, sizeof *dri2_drv);
2396
   if (!dri2_drv)
2397
      return NULL;
2398
 
2399
   if (!dri2_load(&dri2_drv->base)) {
2400
      free(dri2_drv);
2401
      return NULL;
2402
   }
2403
 
2404
   _eglInitDriverFallbacks(&dri2_drv->base);
2405
   dri2_drv->base.API.Initialize = dri2_initialize;
2406
   dri2_drv->base.API.Terminate = dri2_terminate;
2407
   dri2_drv->base.API.CreateContext = dri2_create_context;
2408
   dri2_drv->base.API.DestroyContext = dri2_destroy_context;
2409
   dri2_drv->base.API.MakeCurrent = dri2_make_current;
2410
   dri2_drv->base.API.CreateWindowSurface = dri2_create_window_surface;
2411
   dri2_drv->base.API.CreatePixmapSurface = dri2_create_pixmap_surface;
2412
   dri2_drv->base.API.CreatePbufferSurface = dri2_create_pbuffer_surface;
2413
   dri2_drv->base.API.DestroySurface = dri2_destroy_surface;
2414
   dri2_drv->base.API.GetProcAddress = dri2_get_proc_address;
2415
   dri2_drv->base.API.WaitClient = dri2_wait_client;
2416
   dri2_drv->base.API.WaitNative = dri2_wait_native;
2417
   dri2_drv->base.API.BindTexImage = dri2_bind_tex_image;
2418
   dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image;
2419
   dri2_drv->base.API.SwapInterval = dri2_swap_interval;
2420
   dri2_drv->base.API.SwapBuffers = dri2_swap_buffers;
2421
   dri2_drv->base.API.SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage;
2422
   dri2_drv->base.API.SwapBuffersRegionNOK = dri2_swap_buffers_region;
2423
   dri2_drv->base.API.PostSubBufferNV = dri2_post_sub_buffer;
2424
   dri2_drv->base.API.CopyBuffers = dri2_copy_buffers,
2425
   dri2_drv->base.API.QueryBufferAge = dri2_query_buffer_age;
2426
   dri2_drv->base.API.CreateImageKHR = dri2_create_image;
2427
   dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr;
2428
   dri2_drv->base.API.CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image;
2429
#ifdef HAVE_LIBDRM
2430
   dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
2431
   dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
2432
   dri2_drv->base.API.ExportDMABUFImageQueryMESA = dri2_export_dma_buf_image_query_mesa;
2433
   dri2_drv->base.API.ExportDMABUFImageMESA = dri2_export_dma_buf_image_mesa;
2434
#endif
2435
#ifdef HAVE_WAYLAND_PLATFORM
2436
   dri2_drv->base.API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl;
2437
   dri2_drv->base.API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl;
2438
   dri2_drv->base.API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl;
2439
#endif
2440
   dri2_drv->base.API.GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium;
2441
   dri2_drv->base.API.CreateSyncKHR = dri2_create_sync;
2442
   dri2_drv->base.API.ClientWaitSyncKHR = dri2_client_wait_sync;
2443
   dri2_drv->base.API.WaitSyncKHR = dri2_server_wait_sync;
2444
   dri2_drv->base.API.DestroySyncKHR = dri2_destroy_sync;
2445
 
2446
   dri2_drv->base.Name = "DRI2";
2447
   dri2_drv->base.Unload = dri2_unload;
2448
 
2449
   return &dri2_drv->base;
2450
}