~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/egl/drivers/dri2/egl_dri2.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 <krh@bitplanet.net>
26
 
 */
27
 
 
28
 
#include <stdbool.h>
29
 
#include <stdint.h>
30
 
#include <stdbool.h>
31
 
#include <stdlib.h>
32
 
#include <string.h>
33
 
#include <stdio.h>
34
 
#include <limits.h>
35
 
#include <dlfcn.h>
36
 
#include <fcntl.h>
37
 
#include <errno.h>
38
 
#include <unistd.h>
39
 
#include <c11/threads.h>
40
 
#include <time.h>
41
 
#ifdef HAVE_LIBDRM
42
 
#include <xf86drm.h>
43
 
#include "drm-uapi/drm_fourcc.h"
44
 
#endif
45
 
#include <GL/gl.h>
46
 
#include <GL/internal/dri_interface.h>
47
 
#include <sys/types.h>
48
 
#include <sys/stat.h>
49
 
 
50
 
#ifdef HAVE_WAYLAND_PLATFORM
51
 
#include <wayland-client.h>
52
 
#include "wayland-drm.h"
53
 
#include "wayland-drm-client-protocol.h"
54
 
#include "linux-dmabuf-unstable-v1-client-protocol.h"
55
 
#endif
56
 
 
57
 
#ifdef HAVE_X11_PLATFORM
58
 
#include "X11/Xlibint.h"
59
 
#endif
60
 
 
61
 
#include "egldefines.h"
62
 
#include "egl_dri2.h"
63
 
#include "GL/mesa_glinterop.h"
64
 
#include "loader/loader.h"
65
 
#include "util/libsync.h"
66
 
#include "util/os_file.h"
67
 
#include "util/u_atomic.h"
68
 
#include "util/u_vector.h"
69
 
#include "mapi/glapi/glapi.h"
70
 
#include "util/bitscan.h"
71
 
#include "util/u_math.h"
72
 
 
73
 
#define NUM_ATTRIBS 12
74
 
 
75
 
static const struct dri2_pbuffer_visual {
76
 
   const char *format_name;
77
 
   unsigned int dri_image_format;
78
 
   int rgba_shifts[4];
79
 
   unsigned int rgba_sizes[4];
80
 
} dri2_pbuffer_visuals[] = {
81
 
   {
82
 
      "ABGR16F",
83
 
      __DRI_IMAGE_FORMAT_ABGR16161616F,
84
 
      { 0, 16, 32, 48 },
85
 
      { 16, 16, 16, 16 }
86
 
   },
87
 
   {
88
 
      "XBGR16F",
89
 
      __DRI_IMAGE_FORMAT_XBGR16161616F,
90
 
      { 0, 16, 32, -1 },
91
 
      { 16, 16, 16, 0 }
92
 
   },
93
 
   {
94
 
      "A2RGB10",
95
 
      __DRI_IMAGE_FORMAT_ARGB2101010,
96
 
      { 20, 10, 0, 30 },
97
 
      { 10, 10, 10, 2 }
98
 
   },
99
 
   {
100
 
      "X2RGB10",
101
 
      __DRI_IMAGE_FORMAT_XRGB2101010,
102
 
      { 20, 10, 0, -1 },
103
 
      { 10, 10, 10, 0 }
104
 
   },
105
 
   {
106
 
      "ARGB8888",
107
 
      __DRI_IMAGE_FORMAT_ARGB8888,
108
 
      { 16, 8, 0, 24 },
109
 
      { 8, 8, 8, 8 }
110
 
   },
111
 
   {
112
 
      "RGB888",
113
 
      __DRI_IMAGE_FORMAT_XRGB8888,
114
 
      { 16, 8, 0, -1 },
115
 
      { 8, 8, 8, 0 }
116
 
   },
117
 
   {
118
 
      "RGB565",
119
 
      __DRI_IMAGE_FORMAT_RGB565,
120
 
      { 11, 5, 0, -1 },
121
 
      { 5, 6, 5, 0 }
122
 
   },
123
 
};
124
 
 
125
 
static void
126
 
dri_set_background_context(void *loaderPrivate)
127
 
{
128
 
   _EGLContext *ctx = _eglGetCurrentContext();
129
 
   _EGLThreadInfo *t = _eglGetCurrentThread();
130
 
 
131
 
   _eglBindContextToThread(ctx, t);
132
 
}
133
 
 
134
 
static void
135
 
dri2_gl_flush()
136
 
{
137
 
   static void (*glFlush)(void);
138
 
   static mtx_t glFlushMutex = _MTX_INITIALIZER_NP;
139
 
 
140
 
   mtx_lock(&glFlushMutex);
141
 
   if (!glFlush)
142
 
      glFlush = _glapi_get_proc_address("glFlush");
143
 
   mtx_unlock(&glFlushMutex);
144
 
 
145
 
   /* if glFlush is not available things are horribly broken */
146
 
   if (!glFlush) {
147
 
      _eglLog(_EGL_WARNING, "DRI2: failed to find glFlush entry point");
148
 
      return;
149
 
   }
150
 
 
151
 
   glFlush();
152
 
}
153
 
 
154
 
static GLboolean
155
 
dri_is_thread_safe(void *loaderPrivate)
156
 
{
157
 
   struct dri2_egl_surface *dri2_surf = loaderPrivate;
158
 
   UNUSED _EGLDisplay *display =  dri2_surf->base.Resource.Display;
159
 
 
160
 
#ifdef HAVE_X11_PLATFORM
161
 
   Display *xdpy = (Display*)display->PlatformDisplay;
162
 
 
163
 
   /* Check Xlib is running in thread safe mode when running on EGL/X11-xlib
164
 
    * platform
165
 
    *
166
 
    * 'lock_fns' is the XLockDisplay function pointer of the X11 display 'dpy'.
167
 
    * It wll be NULL if XInitThreads wasn't called.
168
 
    */
169
 
   if (display->Platform == _EGL_PLATFORM_X11 && xdpy && !xdpy->lock_fns)
170
 
      return false;
171
 
#endif
172
 
 
173
 
   return true;
174
 
}
175
 
 
176
 
const __DRIbackgroundCallableExtension background_callable_extension = {
177
 
   .base = { __DRI_BACKGROUND_CALLABLE, 2 },
178
 
 
179
 
   .setBackgroundContext = dri_set_background_context,
180
 
   .isThreadSafe         = dri_is_thread_safe,
181
 
};
182
 
 
183
 
const __DRIuseInvalidateExtension use_invalidate = {
184
 
   .base = { __DRI_USE_INVALIDATE, 1 }
185
 
};
186
 
 
187
 
static void
188
 
dri2_get_pbuffer_drawable_info(__DRIdrawable * draw,
189
 
                               int *x, int *y, int *w, int *h,
190
 
                               void *loaderPrivate)
191
 
{
192
 
   struct dri2_egl_surface *dri2_surf = loaderPrivate;
193
 
 
194
 
   *x = *y = 0;
195
 
   *w = dri2_surf->base.Width;
196
 
   *h = dri2_surf->base.Height;
197
 
}
198
 
 
199
 
static int
200
 
dri2_get_bytes_per_pixel(struct dri2_egl_surface *dri2_surf)
201
 
{
202
 
   const int depth = dri2_surf->base.Config->BufferSize;
203
 
   return depth ? util_next_power_of_two(depth / 8) : 0;
204
 
}
205
 
 
206
 
static void
207
 
dri2_put_image(__DRIdrawable * draw, int op,
208
 
               int x, int y, int w, int h,
209
 
               char *data, void *loaderPrivate)
210
 
{
211
 
   struct dri2_egl_surface *dri2_surf = loaderPrivate;
212
 
   const int bpp = dri2_get_bytes_per_pixel(dri2_surf);
213
 
   const int width = dri2_surf->base.Width;
214
 
   const int height = dri2_surf->base.Height;
215
 
   const int dst_stride = width*bpp;
216
 
   const int src_stride = w*bpp;
217
 
   const int x_offset = x*bpp;
218
 
   int copy_width = src_stride;
219
 
 
220
 
   if (!dri2_surf->swrast_device_buffer)
221
 
      dri2_surf->swrast_device_buffer = malloc(height*dst_stride);
222
 
 
223
 
   if (dri2_surf->swrast_device_buffer) {
224
 
      const char *src = data;
225
 
      char *dst = dri2_surf->swrast_device_buffer;
226
 
 
227
 
      dst += x_offset;
228
 
      dst += y*dst_stride;
229
 
 
230
 
      /* Drivers are allowed to submit OOB PutImage requests, so clip here. */
231
 
      if (copy_width > dst_stride - x_offset)
232
 
         copy_width = dst_stride - x_offset;
233
 
      if (h > height - y)
234
 
         h = height - y;
235
 
 
236
 
      for (; 0 < h; --h) {
237
 
         memcpy(dst, src, copy_width);
238
 
         dst += dst_stride;
239
 
         src += src_stride;
240
 
      }
241
 
   }
242
 
}
243
 
 
244
 
static void
245
 
dri2_get_image(__DRIdrawable * read,
246
 
               int x, int y, int w, int h,
247
 
               char *data, void *loaderPrivate)
248
 
{
249
 
   struct dri2_egl_surface *dri2_surf = loaderPrivate;
250
 
   const int bpp = dri2_get_bytes_per_pixel(dri2_surf);
251
 
   const int width = dri2_surf->base.Width;
252
 
   const int height = dri2_surf->base.Height;
253
 
   const int src_stride = width*bpp;
254
 
   const int dst_stride = w*bpp;
255
 
   const int x_offset = x*bpp;
256
 
   int copy_width = dst_stride;
257
 
   const char *src = dri2_surf->swrast_device_buffer;
258
 
   char *dst = data;
259
 
 
260
 
   if (!src) {
261
 
      memset(data, 0, copy_width * h);
262
 
      return;
263
 
   }
264
 
 
265
 
   src += x_offset;
266
 
   src += y*src_stride;
267
 
 
268
 
   /* Drivers are allowed to submit OOB GetImage requests, so clip here. */
269
 
   if (copy_width > src_stride - x_offset)
270
 
      copy_width = src_stride - x_offset;
271
 
   if (h > height - y)
272
 
      h = height - y;
273
 
 
274
 
   for (; 0 < h; --h) {
275
 
      memcpy(dst, src, copy_width);
276
 
      src += src_stride;
277
 
      dst += dst_stride;
278
 
   }
279
 
 
280
 
}
281
 
 
282
 
/* HACK: technically we should have swrast_null, instead of these.
283
 
 */
284
 
const __DRIswrastLoaderExtension swrast_pbuffer_loader_extension = {
285
 
   .base            = { __DRI_SWRAST_LOADER, 1 },
286
 
   .getDrawableInfo = dri2_get_pbuffer_drawable_info,
287
 
   .putImage        = dri2_put_image,
288
 
   .getImage        = dri2_get_image,
289
 
};
290
 
 
291
 
static const EGLint dri2_to_egl_attribute_map[__DRI_ATTRIB_MAX] = {
292
 
   [__DRI_ATTRIB_BUFFER_SIZE ]          = EGL_BUFFER_SIZE,
293
 
   [__DRI_ATTRIB_LEVEL]                 = EGL_LEVEL,
294
 
   [__DRI_ATTRIB_LUMINANCE_SIZE]        = EGL_LUMINANCE_SIZE,
295
 
   [__DRI_ATTRIB_DEPTH_SIZE]            = EGL_DEPTH_SIZE,
296
 
   [__DRI_ATTRIB_STENCIL_SIZE]          = EGL_STENCIL_SIZE,
297
 
   [__DRI_ATTRIB_SAMPLE_BUFFERS]        = EGL_SAMPLE_BUFFERS,
298
 
   [__DRI_ATTRIB_SAMPLES]               = EGL_SAMPLES,
299
 
   [__DRI_ATTRIB_MAX_PBUFFER_WIDTH]     = EGL_MAX_PBUFFER_WIDTH,
300
 
   [__DRI_ATTRIB_MAX_PBUFFER_HEIGHT]    = EGL_MAX_PBUFFER_HEIGHT,
301
 
   [__DRI_ATTRIB_MAX_PBUFFER_PIXELS]    = EGL_MAX_PBUFFER_PIXELS,
302
 
   [__DRI_ATTRIB_MAX_SWAP_INTERVAL]     = EGL_MAX_SWAP_INTERVAL,
303
 
   [__DRI_ATTRIB_MIN_SWAP_INTERVAL]     = EGL_MIN_SWAP_INTERVAL,
304
 
   [__DRI_ATTRIB_YINVERTED]             = EGL_Y_INVERTED_NOK,
305
 
};
306
 
 
307
 
const __DRIconfig *
308
 
dri2_get_dri_config(struct dri2_egl_config *conf, EGLint surface_type,
309
 
                    EGLenum colorspace)
310
 
{
311
 
   const bool double_buffer = surface_type == EGL_WINDOW_BIT;
312
 
   const bool srgb = colorspace == EGL_GL_COLORSPACE_SRGB_KHR;
313
 
 
314
 
   return conf->dri_config[double_buffer][srgb];
315
 
}
316
 
 
317
 
static EGLBoolean
318
 
dri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria)
319
 
{
320
 
   if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0)
321
 
      return EGL_FALSE;
322
 
 
323
 
   if (!_eglMatchConfig(conf, criteria))
324
 
      return EGL_FALSE;
325
 
 
326
 
   return EGL_TRUE;
327
 
}
328
 
 
329
 
void
330
 
dri2_get_shifts_and_sizes(const __DRIcoreExtension *core,
331
 
                          const __DRIconfig *config, int *shifts,
332
 
                          unsigned int *sizes)
333
 
{
334
 
   unsigned int mask;
335
 
 
336
 
   if (core->getConfigAttrib(config, __DRI_ATTRIB_RED_SHIFT, (unsigned int *)&shifts[0])) {
337
 
      core->getConfigAttrib(config, __DRI_ATTRIB_GREEN_SHIFT, (unsigned int *)&shifts[1]);
338
 
      core->getConfigAttrib(config, __DRI_ATTRIB_BLUE_SHIFT, (unsigned int *)&shifts[2]);
339
 
      core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_SHIFT, (unsigned int *)&shifts[3]);
340
 
   } else {
341
 
      /* Driver isn't exposing shifts, so convert masks to shifts */
342
 
      core->getConfigAttrib(config, __DRI_ATTRIB_RED_MASK, &mask);
343
 
      shifts[0] = ffs(mask) - 1;
344
 
      core->getConfigAttrib(config, __DRI_ATTRIB_GREEN_MASK, &mask);
345
 
      shifts[1] = ffs(mask) - 1;
346
 
      core->getConfigAttrib(config, __DRI_ATTRIB_BLUE_MASK, &mask);
347
 
      shifts[2] = ffs(mask) - 1;
348
 
      core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_MASK, &mask);
349
 
      shifts[3] = ffs(mask) - 1;
350
 
   }
351
 
 
352
 
   core->getConfigAttrib(config, __DRI_ATTRIB_RED_SIZE, &sizes[0]);
353
 
   core->getConfigAttrib(config, __DRI_ATTRIB_GREEN_SIZE, &sizes[1]);
354
 
   core->getConfigAttrib(config, __DRI_ATTRIB_BLUE_SIZE, &sizes[2]);
355
 
   core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_SIZE, &sizes[3]);
356
 
}
357
 
 
358
 
void
359
 
dri2_get_render_type_float(const __DRIcoreExtension *core,
360
 
                           const __DRIconfig *config,
361
 
                           bool *is_float)
362
 
{
363
 
   unsigned int render_type;
364
 
 
365
 
   core->getConfigAttrib(config, __DRI_ATTRIB_RENDER_TYPE, &render_type);
366
 
   *is_float = (render_type & __DRI_ATTRIB_FLOAT_BIT) ? true : false;
367
 
}
368
 
 
369
 
unsigned int
370
 
dri2_image_format_for_pbuffer_config(struct dri2_egl_display *dri2_dpy,
371
 
                                     const __DRIconfig *config)
372
 
{
373
 
   int shifts[4];
374
 
   unsigned int sizes[4];
375
 
 
376
 
   dri2_get_shifts_and_sizes(dri2_dpy->core, config, shifts, sizes);
377
 
 
378
 
   for (unsigned i = 0; i < ARRAY_SIZE(dri2_pbuffer_visuals); ++i) {
379
 
      const struct dri2_pbuffer_visual *visual = &dri2_pbuffer_visuals[i];
380
 
 
381
 
      if (shifts[0] == visual->rgba_shifts[0] &&
382
 
          shifts[1] == visual->rgba_shifts[1] &&
383
 
          shifts[2] == visual->rgba_shifts[2] &&
384
 
          shifts[3] == visual->rgba_shifts[3] &&
385
 
          sizes[0] == visual->rgba_sizes[0] &&
386
 
          sizes[1] == visual->rgba_sizes[1] &&
387
 
          sizes[2] == visual->rgba_sizes[2] &&
388
 
          sizes[3] == visual->rgba_sizes[3]) {
389
 
         return visual->dri_image_format;
390
 
      }
391
 
   }
392
 
 
393
 
   return __DRI_IMAGE_FORMAT_NONE;
394
 
}
395
 
 
396
 
struct dri2_egl_config *
397
 
dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
398
 
                EGLint surface_type, const EGLint *attr_list,
399
 
                const int *rgba_shifts, const unsigned int *rgba_sizes)
400
 
{
401
 
   struct dri2_egl_config *conf;
402
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
403
 
   _EGLConfig base;
404
 
   unsigned int attrib, value, double_buffer;
405
 
   bool srgb = false;
406
 
   EGLint key, bind_to_texture_rgb, bind_to_texture_rgba;
407
 
   int dri_shifts[4] = { -1, -1, -1, -1 };
408
 
   unsigned int dri_sizes[4] = { 0, 0, 0, 0 };
409
 
   _EGLConfig *matching_config;
410
 
   EGLint num_configs = 0;
411
 
   EGLint config_id;
412
 
 
413
 
   _eglInitConfig(&base, disp, id);
414
 
 
415
 
   double_buffer = 0;
416
 
   bind_to_texture_rgb = 0;
417
 
   bind_to_texture_rgba = 0;
418
 
 
419
 
   for (int i = 0; i < __DRI_ATTRIB_MAX; ++i) {
420
 
      if (!dri2_dpy->core->indexConfigAttrib(dri_config, i, &attrib, &value))
421
 
         break;
422
 
 
423
 
      switch (attrib) {
424
 
      case __DRI_ATTRIB_RENDER_TYPE:
425
 
         if (value & __DRI_ATTRIB_FLOAT_BIT)
426
 
            base.ComponentType = EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT;
427
 
         if (value & __DRI_ATTRIB_RGBA_BIT)
428
 
            value = EGL_RGB_BUFFER;
429
 
         else if (value & __DRI_ATTRIB_LUMINANCE_BIT)
430
 
            value = EGL_LUMINANCE_BUFFER;
431
 
         else
432
 
            return NULL;
433
 
         base.ColorBufferType = value;
434
 
         break;
435
 
 
436
 
      case __DRI_ATTRIB_CONFIG_CAVEAT:
437
 
         if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
438
 
            value = EGL_NON_CONFORMANT_CONFIG;
439
 
         else if (value & __DRI_ATTRIB_SLOW_BIT)
440
 
            value = EGL_SLOW_CONFIG;
441
 
         else
442
 
            value = EGL_NONE;
443
 
         base.ConfigCaveat = value;
444
 
         break;
445
 
 
446
 
      case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB:
447
 
         bind_to_texture_rgb = value;
448
 
         break;
449
 
 
450
 
      case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA:
451
 
         bind_to_texture_rgba = value;
452
 
         break;
453
 
 
454
 
      case __DRI_ATTRIB_DOUBLE_BUFFER:
455
 
         double_buffer = value;
456
 
         break;
457
 
 
458
 
      case __DRI_ATTRIB_RED_SIZE:
459
 
         dri_sizes[0] = value;
460
 
         base.RedSize = value;
461
 
         break;
462
 
 
463
 
      case __DRI_ATTRIB_RED_MASK:
464
 
         dri_shifts[0] = ffs(value) - 1;
465
 
         break;
466
 
 
467
 
      case __DRI_ATTRIB_RED_SHIFT:
468
 
         dri_shifts[0] = value;
469
 
         break;
470
 
 
471
 
      case __DRI_ATTRIB_GREEN_SIZE:
472
 
         dri_sizes[1] = value;
473
 
         base.GreenSize = value;
474
 
         break;
475
 
 
476
 
      case __DRI_ATTRIB_GREEN_MASK:
477
 
         dri_shifts[1] = ffs(value) - 1;
478
 
         break;
479
 
 
480
 
      case __DRI_ATTRIB_GREEN_SHIFT:
481
 
         dri_shifts[1] = value;
482
 
         break;
483
 
 
484
 
      case __DRI_ATTRIB_BLUE_SIZE:
485
 
         dri_sizes[2] = value;
486
 
         base.BlueSize = value;
487
 
         break;
488
 
 
489
 
      case __DRI_ATTRIB_BLUE_MASK:
490
 
         dri_shifts[2] = ffs(value) - 1;
491
 
         break;
492
 
 
493
 
      case __DRI_ATTRIB_BLUE_SHIFT:
494
 
         dri_shifts[2] = value;
495
 
         break;
496
 
 
497
 
     case __DRI_ATTRIB_ALPHA_SIZE:
498
 
         dri_sizes[3] = value;
499
 
         base.AlphaSize = value;
500
 
         break;
501
 
 
502
 
      case __DRI_ATTRIB_ALPHA_MASK:
503
 
         dri_shifts[3] = ffs(value) - 1;
504
 
         break;
505
 
 
506
 
      case __DRI_ATTRIB_ALPHA_SHIFT:
507
 
         dri_shifts[3] = value;
508
 
         break;
509
 
 
510
 
      case __DRI_ATTRIB_ACCUM_RED_SIZE:
511
 
      case __DRI_ATTRIB_ACCUM_GREEN_SIZE:
512
 
      case __DRI_ATTRIB_ACCUM_BLUE_SIZE:
513
 
      case __DRI_ATTRIB_ACCUM_ALPHA_SIZE:
514
 
         /* Don't expose visuals with the accumulation buffer. */
515
 
         if (value > 0)
516
 
            return NULL;
517
 
         break;
518
 
 
519
 
      case __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE:
520
 
         srgb = value != 0;
521
 
         if (!disp->Extensions.KHR_gl_colorspace && srgb)
522
 
            return NULL;
523
 
         break;
524
 
 
525
 
      case __DRI_ATTRIB_MAX_PBUFFER_WIDTH:
526
 
         base.MaxPbufferWidth = _EGL_MAX_PBUFFER_WIDTH;
527
 
         break;
528
 
      case __DRI_ATTRIB_MAX_PBUFFER_HEIGHT:
529
 
         base.MaxPbufferHeight = _EGL_MAX_PBUFFER_HEIGHT;
530
 
         break;
531
 
      case __DRI_ATTRIB_MUTABLE_RENDER_BUFFER:
532
 
         if (disp->Extensions.KHR_mutable_render_buffer)
533
 
            surface_type |= EGL_MUTABLE_RENDER_BUFFER_BIT_KHR;
534
 
         break;
535
 
      default:
536
 
         key = dri2_to_egl_attribute_map[attrib];
537
 
         if (key != 0)
538
 
            _eglSetConfigKey(&base, key, value);
539
 
         break;
540
 
      }
541
 
   }
542
 
 
543
 
   if (attr_list)
544
 
      for (int i = 0; attr_list[i] != EGL_NONE; i += 2)
545
 
         _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]);
546
 
 
547
 
   if (rgba_shifts && memcmp(rgba_shifts, dri_shifts, sizeof(dri_shifts)))
548
 
      return NULL;
549
 
 
550
 
   if (rgba_sizes && memcmp(rgba_sizes, dri_sizes, sizeof(dri_sizes)))
551
 
      return NULL;
552
 
 
553
 
   base.NativeRenderable = EGL_TRUE;
554
 
 
555
 
   base.SurfaceType = surface_type;
556
 
   if (surface_type & (EGL_PBUFFER_BIT |
557
 
       (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) {
558
 
      base.BindToTextureRGB = bind_to_texture_rgb;
559
 
      if (base.AlphaSize > 0)
560
 
         base.BindToTextureRGBA = bind_to_texture_rgba;
561
 
   }
562
 
 
563
 
   if (double_buffer) {
564
 
      surface_type &= ~EGL_PIXMAP_BIT;
565
 
   }
566
 
 
567
 
   if (!surface_type)
568
 
      return NULL;
569
 
 
570
 
   base.RenderableType = disp->ClientAPIs;
571
 
   base.Conformant = disp->ClientAPIs;
572
 
 
573
 
   base.MinSwapInterval = dri2_dpy->min_swap_interval;
574
 
   base.MaxSwapInterval = dri2_dpy->max_swap_interval;
575
 
 
576
 
   if (!_eglValidateConfig(&base, EGL_FALSE)) {
577
 
      _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id);
578
 
      return NULL;
579
 
   }
580
 
 
581
 
   config_id = base.ConfigID;
582
 
   base.ConfigID    = EGL_DONT_CARE;
583
 
   base.SurfaceType = EGL_DONT_CARE;
584
 
   num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1,
585
 
                                 (_EGLArrayForEach) dri2_match_config, &base);
586
 
 
587
 
   if (num_configs == 1) {
588
 
      conf = (struct dri2_egl_config *) matching_config;
589
 
 
590
 
      if (!conf->dri_config[double_buffer][srgb])
591
 
         conf->dri_config[double_buffer][srgb] = dri_config;
592
 
      else
593
 
         /* a similar config type is already added (unlikely) => discard */
594
 
         return NULL;
595
 
   }
596
 
   else if (num_configs == 0) {
597
 
      conf = calloc(1, sizeof *conf);
598
 
      if (conf == NULL)
599
 
         return NULL;
600
 
 
601
 
      conf->dri_config[double_buffer][srgb] = dri_config;
602
 
 
603
 
      memcpy(&conf->base, &base, sizeof base);
604
 
      conf->base.SurfaceType = 0;
605
 
      conf->base.ConfigID = config_id;
606
 
 
607
 
      _eglLinkConfig(&conf->base);
608
 
   }
609
 
   else {
610
 
      unreachable("duplicates should not be possible");
611
 
      return NULL;
612
 
   }
613
 
 
614
 
   conf->base.SurfaceType |= surface_type;
615
 
 
616
 
   return conf;
617
 
}
618
 
 
619
 
EGLBoolean
620
 
dri2_add_pbuffer_configs_for_visuals(_EGLDisplay *disp)
621
 
{
622
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
623
 
   unsigned int format_count[ARRAY_SIZE(dri2_pbuffer_visuals)] = { 0 };
624
 
   unsigned int config_count = 0;
625
 
 
626
 
   for (unsigned i = 0; dri2_dpy->driver_configs[i] != NULL; i++) {
627
 
      for (unsigned j = 0; j < ARRAY_SIZE(dri2_pbuffer_visuals); j++) {
628
 
         struct dri2_egl_config *dri2_conf;
629
 
 
630
 
         dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i],
631
 
               config_count + 1, EGL_PBUFFER_BIT, NULL,
632
 
               dri2_pbuffer_visuals[j].rgba_shifts, dri2_pbuffer_visuals[j].rgba_sizes);
633
 
 
634
 
         if (dri2_conf) {
635
 
            if (dri2_conf->base.ConfigID == config_count + 1)
636
 
               config_count++;
637
 
            format_count[j]++;
638
 
         }
639
 
      }
640
 
   }
641
 
 
642
 
   for (unsigned i = 0; i < ARRAY_SIZE(format_count); i++) {
643
 
      if (!format_count[i]) {
644
 
         _eglLog(_EGL_DEBUG, "No DRI config supports native format %s",
645
 
               dri2_pbuffer_visuals[i].format_name);
646
 
      }
647
 
   }
648
 
 
649
 
   return (config_count != 0);
650
 
}
651
 
 
652
 
GLboolean
653
 
dri2_validate_egl_image(void *image, void *data)
654
 
{
655
 
   _EGLDisplay *disp = data;
656
 
   _EGLImage *img;
657
 
 
658
 
   mtx_lock(&disp->Mutex);
659
 
   img = _eglLookupImage(image, disp);
660
 
   mtx_unlock(&disp->Mutex);
661
 
 
662
 
   if (img == NULL) {
663
 
      _eglError(EGL_BAD_PARAMETER, "dri2_validate_egl_image");
664
 
      return false;
665
 
   }
666
 
 
667
 
   return true;
668
 
}
669
 
 
670
 
__DRIimage *
671
 
dri2_lookup_egl_image_validated(void *image, void *data)
672
 
{
673
 
   struct dri2_egl_image *dri2_img;
674
 
 
675
 
   (void)data;
676
 
 
677
 
   dri2_img = dri2_egl_image(image);
678
 
 
679
 
   return dri2_img->dri_image;
680
 
}
681
 
 
682
 
__DRIimage *
683
 
dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
684
 
{
685
 
   (void) screen;
686
 
 
687
 
   if (!dri2_validate_egl_image(image, data))
688
 
      return NULL;
689
 
 
690
 
   return dri2_lookup_egl_image_validated(image, data);
691
 
}
692
 
 
693
 
const __DRIimageLookupExtension image_lookup_extension = {
694
 
   .base = { __DRI_IMAGE_LOOKUP, 2 },
695
 
 
696
 
   .lookupEGLImage       = dri2_lookup_egl_image,
697
 
   .validateEGLImage     = dri2_validate_egl_image,
698
 
   .lookupEGLImageValidated = dri2_lookup_egl_image_validated,
699
 
};
700
 
 
701
 
struct dri2_extension_match {
702
 
   const char *name;
703
 
   int version;
704
 
   int offset;
705
 
};
706
 
 
707
 
static const struct dri2_extension_match dri3_driver_extensions[] = {
708
 
   { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
709
 
   { __DRI_IMAGE_DRIVER, 1, offsetof(struct dri2_egl_display, image_driver) },
710
 
   { NULL, 0, 0 }
711
 
};
712
 
 
713
 
static const struct dri2_extension_match dri2_driver_extensions[] = {
714
 
   { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
715
 
   { __DRI_DRI2, 2, offsetof(struct dri2_egl_display, dri2) },
716
 
   { NULL, 0, 0 }
717
 
};
718
 
 
719
 
static const struct dri2_extension_match dri2_core_extensions[] = {
720
 
   { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) },
721
 
   { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
722
 
   { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) },
723
 
   { NULL, 0, 0 }
724
 
};
725
 
 
726
 
static const struct dri2_extension_match swrast_driver_extensions[] = {
727
 
   { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
728
 
   { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) },
729
 
   { NULL, 0, 0 }
730
 
};
731
 
 
732
 
static const struct dri2_extension_match swrast_core_extensions[] = {
733
 
   { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
734
 
   { NULL, 0, 0 }
735
 
};
736
 
 
737
 
static const struct dri2_extension_match optional_driver_extensions[] = {
738
 
   { __DRI_CONFIG_OPTIONS, 1, offsetof(struct dri2_egl_display, configOptions) },
739
 
   { NULL, 0, 0 }
740
 
};
741
 
 
742
 
static const struct dri2_extension_match optional_core_extensions[] = {
743
 
   { __DRI2_ROBUSTNESS, 1, offsetof(struct dri2_egl_display, robustness) },
744
 
   { __DRI2_CONFIG_QUERY, 1, offsetof(struct dri2_egl_display, config) },
745
 
   { __DRI2_FENCE, 1, offsetof(struct dri2_egl_display, fence) },
746
 
   { __DRI2_BUFFER_DAMAGE, 1, offsetof(struct dri2_egl_display, buffer_damage) },
747
 
   { __DRI2_RENDERER_QUERY, 1, offsetof(struct dri2_egl_display, rendererQuery) },
748
 
   { __DRI2_INTEROP, 1, offsetof(struct dri2_egl_display, interop) },
749
 
   { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) },
750
 
   { __DRI2_FLUSH_CONTROL, 1, offsetof(struct dri2_egl_display, flush_control) },
751
 
   { __DRI2_BLOB, 1, offsetof(struct dri2_egl_display, blob) },
752
 
   { __DRI_MUTABLE_RENDER_BUFFER_DRIVER, 1, offsetof(struct dri2_egl_display, mutable_render_buffer) },
753
 
   { __DRI_KOPPER, 1, offsetof(struct dri2_egl_display, kopper) },
754
 
   { NULL, 0, 0 }
755
 
};
756
 
 
757
 
static EGLBoolean
758
 
dri2_bind_extensions(struct dri2_egl_display *dri2_dpy,
759
 
                     const struct dri2_extension_match *matches,
760
 
                     const __DRIextension **extensions,
761
 
                     bool optional)
762
 
{
763
 
   int ret = EGL_TRUE;
764
 
   void *field;
765
 
 
766
 
   for (int i = 0; extensions[i]; i++) {
767
 
      _eglLog(_EGL_DEBUG, "found extension `%s'", extensions[i]->name);
768
 
      for (int j = 0; matches[j].name; j++) {
769
 
         if (strcmp(extensions[i]->name, matches[j].name) == 0 &&
770
 
             extensions[i]->version >= matches[j].version) {
771
 
            field = ((char *) dri2_dpy + matches[j].offset);
772
 
            *(const __DRIextension **) field = extensions[i];
773
 
            _eglLog(_EGL_INFO, "found extension %s version %d",
774
 
                    extensions[i]->name, extensions[i]->version);
775
 
            break;
776
 
         }
777
 
      }
778
 
   }
779
 
 
780
 
   for (int j = 0; matches[j].name; j++) {
781
 
      field = ((char *) dri2_dpy + matches[j].offset);
782
 
      if (*(const __DRIextension **) field == NULL) {
783
 
         if (optional) {
784
 
            _eglLog(_EGL_DEBUG, "did not find optional extension %s version %d",
785
 
                    matches[j].name, matches[j].version);
786
 
         } else {
787
 
            _eglLog(_EGL_WARNING, "did not find extension %s version %d",
788
 
                    matches[j].name, matches[j].version);
789
 
            ret = EGL_FALSE;
790
 
         }
791
 
      }
792
 
   }
793
 
 
794
 
   return ret;
795
 
}
796
 
 
797
 
static const __DRIextension **
798
 
dri2_open_driver(_EGLDisplay *disp)
799
 
{
800
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
801
 
   static const char *search_path_vars[] = {
802
 
      "LIBGL_DRIVERS_PATH",
803
 
      NULL,
804
 
   };
805
 
 
806
 
   return loader_open_driver(dri2_dpy->driver_name,
807
 
                             &dri2_dpy->driver,
808
 
                             search_path_vars);
809
 
}
810
 
 
811
 
static EGLBoolean
812
 
dri2_load_driver_common(_EGLDisplay *disp,
813
 
                        const struct dri2_extension_match *driver_extensions)
814
 
{
815
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
816
 
   const __DRIextension **extensions;
817
 
 
818
 
   extensions = dri2_open_driver(disp);
819
 
   if (!extensions)
820
 
      return EGL_FALSE;
821
 
 
822
 
   if (!dri2_bind_extensions(dri2_dpy, driver_extensions, extensions, false)) {
823
 
      dlclose(dri2_dpy->driver);
824
 
      dri2_dpy->driver = NULL;
825
 
      return EGL_FALSE;
826
 
   }
827
 
   dri2_dpy->driver_extensions = extensions;
828
 
 
829
 
   dri2_bind_extensions(dri2_dpy, optional_driver_extensions, extensions, true);
830
 
 
831
 
   return EGL_TRUE;
832
 
}
833
 
 
834
 
EGLBoolean
835
 
dri2_load_driver(_EGLDisplay *disp)
836
 
{
837
 
   return dri2_load_driver_common(disp, dri2_driver_extensions);
838
 
}
839
 
 
840
 
EGLBoolean
841
 
dri2_load_driver_dri3(_EGLDisplay *disp)
842
 
{
843
 
   return dri2_load_driver_common(disp, dri3_driver_extensions);
844
 
}
845
 
 
846
 
EGLBoolean
847
 
dri2_load_driver_swrast(_EGLDisplay *disp)
848
 
{
849
 
   return dri2_load_driver_common(disp, swrast_driver_extensions);
850
 
}
851
 
 
852
 
static unsigned
853
 
dri2_renderer_query_integer(struct dri2_egl_display *dri2_dpy, int param)
854
 
{
855
 
   const __DRI2rendererQueryExtension *rendererQuery = dri2_dpy->rendererQuery;
856
 
   unsigned int value = 0;
857
 
 
858
 
   if (!rendererQuery ||
859
 
       rendererQuery->queryInteger(dri2_dpy->dri_screen, param, &value) == -1)
860
 
      return 0;
861
 
 
862
 
   return value;
863
 
}
864
 
 
865
 
static const char *
866
 
dri2_query_driver_name(_EGLDisplay *disp)
867
 
{
868
 
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
869
 
    return dri2_dpy->driver_name;
870
 
}
871
 
 
872
 
static char *
873
 
dri2_query_driver_config(_EGLDisplay *disp)
874
 
{
875
 
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
876
 
    const __DRIconfigOptionsExtension *ext = dri2_dpy->configOptions;
877
 
 
878
 
    if (ext->base.version >= 2)
879
 
        return ext->getXml(dri2_dpy->driver_name);
880
 
 
881
 
    return strdup(ext->xml);
882
 
}
883
 
 
884
 
 
885
 
void
886
 
dri2_setup_screen(_EGLDisplay *disp)
887
 
{
888
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
889
 
   unsigned int api_mask;
890
 
 
891
 
   /*
892
 
    * EGL 1.5 specification defines the default value to 1. Moreover,
893
 
    * eglSwapInterval() is required to clamp requested value to the supported
894
 
    * range. Since the default value is implicitly assumed to be supported,
895
 
    * use it as both minimum and maximum for the platforms that do not allow
896
 
    * changing the interval. Platforms, which allow it (e.g. x11, wayland)
897
 
    * override these values already.
898
 
    */
899
 
   dri2_dpy->min_swap_interval = 1;
900
 
   dri2_dpy->max_swap_interval = 1;
901
 
   dri2_dpy->default_swap_interval = 1;
902
 
 
903
 
   if (dri2_dpy->image_driver) {
904
 
      api_mask = dri2_dpy->image_driver->getAPIMask(dri2_dpy->dri_screen);
905
 
   } else if (dri2_dpy->dri2) {
906
 
      api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
907
 
   } else {
908
 
      assert(dri2_dpy->swrast);
909
 
      api_mask = 1 << __DRI_API_OPENGL |
910
 
                 1 << __DRI_API_GLES |
911
 
                 1 << __DRI_API_GLES2 |
912
 
                 1 << __DRI_API_GLES3;
913
 
   }
914
 
 
915
 
   disp->ClientAPIs = 0;
916
 
   if ((api_mask & (1 <<__DRI_API_OPENGL)) && _eglIsApiValid(EGL_OPENGL_API))
917
 
      disp->ClientAPIs |= EGL_OPENGL_BIT;
918
 
   if ((api_mask & (1 << __DRI_API_GLES)) && _eglIsApiValid(EGL_OPENGL_ES_API))
919
 
      disp->ClientAPIs |= EGL_OPENGL_ES_BIT;
920
 
   if ((api_mask & (1 << __DRI_API_GLES2)) && _eglIsApiValid(EGL_OPENGL_ES_API))
921
 
      disp->ClientAPIs |= EGL_OPENGL_ES2_BIT;
922
 
   if ((api_mask & (1 << __DRI_API_GLES3)) && _eglIsApiValid(EGL_OPENGL_ES_API))
923
 
      disp->ClientAPIs |= EGL_OPENGL_ES3_BIT_KHR;
924
 
 
925
 
   assert(dri2_dpy->image_driver || dri2_dpy->dri2 || dri2_dpy->swrast);
926
 
   disp->Extensions.KHR_no_config_context = EGL_TRUE;
927
 
   disp->Extensions.KHR_surfaceless_context = EGL_TRUE;
928
 
 
929
 
   if (dri2_dpy->configOptions) {
930
 
       disp->Extensions.MESA_query_driver = EGL_TRUE;
931
 
   }
932
 
 
933
 
   /* Report back to EGL the bitmask of priorities supported */
934
 
   disp->Extensions.IMG_context_priority =
935
 
      dri2_renderer_query_integer(dri2_dpy,
936
 
                                  __DRI2_RENDERER_HAS_CONTEXT_PRIORITY);
937
 
 
938
 
   disp->Extensions.EXT_pixel_format_float = EGL_TRUE;
939
 
 
940
 
   if (dri2_renderer_query_integer(dri2_dpy,
941
 
                                   __DRI2_RENDERER_HAS_FRAMEBUFFER_SRGB))
942
 
      disp->Extensions.KHR_gl_colorspace = EGL_TRUE;
943
 
 
944
 
   if (dri2_dpy->image_driver ||
945
 
       (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) ||
946
 
       (dri2_dpy->swrast && dri2_dpy->swrast->base.version >= 3)) {
947
 
      disp->Extensions.KHR_create_context = EGL_TRUE;
948
 
 
949
 
      if (dri2_dpy->robustness)
950
 
         disp->Extensions.EXT_create_context_robustness = EGL_TRUE;
951
 
   }
952
 
 
953
 
   if (dri2_renderer_query_integer(dri2_dpy,
954
 
                                   __DRI2_RENDERER_HAS_NO_ERROR_CONTEXT))
955
 
      disp->Extensions.KHR_create_context_no_error = EGL_TRUE;
956
 
 
957
 
   if (dri2_dpy->fence) {
958
 
      disp->Extensions.KHR_fence_sync = EGL_TRUE;
959
 
      disp->Extensions.KHR_wait_sync = EGL_TRUE;
960
 
      if (dri2_dpy->fence->get_fence_from_cl_event)
961
 
         disp->Extensions.KHR_cl_event2 = EGL_TRUE;
962
 
      if (dri2_dpy->fence->base.version >= 2 &&
963
 
          dri2_dpy->fence->get_capabilities) {
964
 
         unsigned capabilities =
965
 
            dri2_dpy->fence->get_capabilities(dri2_dpy->dri_screen);
966
 
         disp->Extensions.ANDROID_native_fence_sync =
967
 
            (capabilities & __DRI_FENCE_CAP_NATIVE_FD) != 0;
968
 
      }
969
 
   }
970
 
 
971
 
   if (dri2_dpy->blob)
972
 
      disp->Extensions.ANDROID_blob_cache = EGL_TRUE;
973
 
 
974
 
   disp->Extensions.KHR_reusable_sync = EGL_TRUE;
975
 
 
976
 
   if (dri2_dpy->image) {
977
 
      if (dri2_dpy->image->base.version >= 10 &&
978
 
          dri2_dpy->image->getCapabilities != NULL) {
979
 
         int capabilities;
980
 
 
981
 
         capabilities = dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen);
982
 
         disp->Extensions.MESA_drm_image = (capabilities & __DRI_IMAGE_CAP_GLOBAL_NAMES) != 0;
983
 
 
984
 
         if (dri2_dpy->image->base.version >= 11)
985
 
            disp->Extensions.MESA_image_dma_buf_export = EGL_TRUE;
986
 
      } else {
987
 
         disp->Extensions.MESA_drm_image = EGL_TRUE;
988
 
         if (dri2_dpy->image->base.version >= 11)
989
 
            disp->Extensions.MESA_image_dma_buf_export = EGL_TRUE;
990
 
      }
991
 
 
992
 
      disp->Extensions.KHR_image_base = EGL_TRUE;
993
 
      disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
994
 
      if (dri2_dpy->image->base.version >= 5 &&
995
 
          dri2_dpy->image->createImageFromTexture) {
996
 
         disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
997
 
         disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE;
998
 
 
999
 
         if (dri2_renderer_query_integer(dri2_dpy,
1000
 
                                         __DRI2_RENDERER_HAS_TEXTURE_3D))
1001
 
             disp->Extensions.KHR_gl_texture_3D_image = EGL_TRUE;
1002
 
      }
1003
 
#ifdef HAVE_LIBDRM
1004
 
      if (dri2_dpy->image->base.version >= 8 &&
1005
 
          dri2_dpy->image->createImageFromDmaBufs) {
1006
 
         disp->Extensions.EXT_image_dma_buf_import = EGL_TRUE;
1007
 
         disp->Extensions.EXT_image_dma_buf_import_modifiers = EGL_TRUE;
1008
 
      }
1009
 
#endif
1010
 
   }
1011
 
 
1012
 
   if (dri2_dpy->flush_control)
1013
 
      disp->Extensions.KHR_context_flush_control = EGL_TRUE;
1014
 
 
1015
 
   if (dri2_dpy->buffer_damage && dri2_dpy->buffer_damage->set_damage_region)
1016
 
      disp->Extensions.KHR_partial_update = EGL_TRUE;
1017
 
 
1018
 
   disp->Extensions.EXT_protected_surface =
1019
 
      dri2_renderer_query_integer(dri2_dpy,
1020
 
                                  __DRI2_RENDERER_HAS_PROTECTED_CONTENT);
1021
 
}
1022
 
 
1023
 
void
1024
 
dri2_setup_swap_interval(_EGLDisplay *disp, int max_swap_interval)
1025
 
{
1026
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1027
 
   GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
1028
 
 
1029
 
   /* Allow driconf to override applications.*/
1030
 
   if (dri2_dpy->config)
1031
 
      dri2_dpy->config->configQueryi(dri2_dpy->dri_screen,
1032
 
                                     "vblank_mode", &vblank_mode);
1033
 
   switch (vblank_mode) {
1034
 
   case DRI_CONF_VBLANK_NEVER:
1035
 
      dri2_dpy->min_swap_interval = 0;
1036
 
      dri2_dpy->max_swap_interval = 0;
1037
 
      dri2_dpy->default_swap_interval = 0;
1038
 
      break;
1039
 
   case DRI_CONF_VBLANK_ALWAYS_SYNC:
1040
 
      dri2_dpy->min_swap_interval = 1;
1041
 
      dri2_dpy->max_swap_interval = max_swap_interval;
1042
 
      dri2_dpy->default_swap_interval = 1;
1043
 
      break;
1044
 
   case DRI_CONF_VBLANK_DEF_INTERVAL_0:
1045
 
      dri2_dpy->min_swap_interval = 0;
1046
 
      dri2_dpy->max_swap_interval = max_swap_interval;
1047
 
      dri2_dpy->default_swap_interval = 0;
1048
 
      break;
1049
 
   default:
1050
 
   case DRI_CONF_VBLANK_DEF_INTERVAL_1:
1051
 
      dri2_dpy->min_swap_interval = 0;
1052
 
      dri2_dpy->max_swap_interval = max_swap_interval;
1053
 
      dri2_dpy->default_swap_interval = 1;
1054
 
      break;
1055
 
   }
1056
 
}
1057
 
 
1058
 
/* All platforms but DRM call this function to create the screen and populate
1059
 
 * the driver_configs. DRM inherits that information from its display - GBM.
1060
 
 */
1061
 
EGLBoolean
1062
 
dri2_create_screen(_EGLDisplay *disp)
1063
 
{
1064
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1065
 
 
1066
 
   if (dri2_dpy->image_driver) {
1067
 
      dri2_dpy->dri_screen =
1068
 
         dri2_dpy->image_driver->createNewScreen2(0, dri2_dpy->fd,
1069
 
                                                  dri2_dpy->loader_extensions,
1070
 
                                                  dri2_dpy->driver_extensions,
1071
 
                                                  &dri2_dpy->driver_configs,
1072
 
                                                  disp);
1073
 
   } else if (dri2_dpy->dri2) {
1074
 
      if (dri2_dpy->dri2->base.version >= 4) {
1075
 
         dri2_dpy->dri_screen =
1076
 
            dri2_dpy->dri2->createNewScreen2(0, dri2_dpy->fd,
1077
 
                                             dri2_dpy->loader_extensions,
1078
 
                                             dri2_dpy->driver_extensions,
1079
 
                                             &dri2_dpy->driver_configs, disp);
1080
 
      } else {
1081
 
         dri2_dpy->dri_screen =
1082
 
            dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd,
1083
 
                                            dri2_dpy->loader_extensions,
1084
 
                                            &dri2_dpy->driver_configs, disp);
1085
 
      }
1086
 
   } else {
1087
 
      assert(dri2_dpy->swrast);
1088
 
      if (dri2_dpy->swrast->base.version >= 4) {
1089
 
         dri2_dpy->dri_screen =
1090
 
            dri2_dpy->swrast->createNewScreen2(0, dri2_dpy->loader_extensions,
1091
 
                                               dri2_dpy->driver_extensions,
1092
 
                                               &dri2_dpy->driver_configs, disp);
1093
 
      } else {
1094
 
         dri2_dpy->dri_screen =
1095
 
            dri2_dpy->swrast->createNewScreen(0, dri2_dpy->loader_extensions,
1096
 
                                              &dri2_dpy->driver_configs, disp);
1097
 
      }
1098
 
   }
1099
 
 
1100
 
   if (dri2_dpy->dri_screen == NULL) {
1101
 
      _eglLog(_EGL_WARNING, "egl: failed to create dri2 screen");
1102
 
      return EGL_FALSE;
1103
 
   }
1104
 
 
1105
 
   dri2_dpy->own_dri_screen = true;
1106
 
   return EGL_TRUE;
1107
 
}
1108
 
 
1109
 
EGLBoolean
1110
 
dri2_setup_extensions(_EGLDisplay *disp)
1111
 
{
1112
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1113
 
   const struct dri2_extension_match *mandatory_core_extensions;
1114
 
   const __DRIextension **extensions;
1115
 
 
1116
 
   extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
1117
 
 
1118
 
   if (dri2_dpy->image_driver || dri2_dpy->dri2)
1119
 
      mandatory_core_extensions = dri2_core_extensions;
1120
 
   else
1121
 
      mandatory_core_extensions = swrast_core_extensions;
1122
 
 
1123
 
   if (!dri2_bind_extensions(dri2_dpy, mandatory_core_extensions, extensions, false))
1124
 
      return EGL_FALSE;
1125
 
 
1126
 
#ifdef HAVE_DRI3_MODIFIERS
1127
 
   dri2_dpy->multibuffers_available =
1128
 
      (dri2_dpy->dri3_major_version > 1 || (dri2_dpy->dri3_major_version == 1 &&
1129
 
                                            dri2_dpy->dri3_minor_version >= 2)) &&
1130
 
      (dri2_dpy->present_major_version > 1 || (dri2_dpy->present_major_version == 1 &&
1131
 
                                               dri2_dpy->present_minor_version >= 2)) &&
1132
 
      (dri2_dpy->image && dri2_dpy->image->base.version >= 15);
1133
 
#endif
1134
 
 
1135
 
   dri2_bind_extensions(dri2_dpy, optional_core_extensions, extensions, true);
1136
 
   return EGL_TRUE;
1137
 
}
1138
 
 
1139
 
/**
1140
 
 * Called via eglInitialize(), drv->Initialize().
1141
 
 *
1142
 
 * This must be guaranteed to be called exactly once, even if eglInitialize is
1143
 
 * called many times (without a eglTerminate in between).
1144
 
 */
1145
 
static EGLBoolean
1146
 
dri2_initialize(_EGLDisplay *disp)
1147
 
{
1148
 
   EGLBoolean ret = EGL_FALSE;
1149
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1150
 
 
1151
 
   /* In the case where the application calls eglMakeCurrent(context1),
1152
 
    * eglTerminate, then eglInitialize again (without a call to eglReleaseThread
1153
 
    * or eglMakeCurrent(NULL) before that), dri2_dpy structure is still
1154
 
    * initialized, as we need it to be able to free context1 correctly.
1155
 
    *
1156
 
    * It would probably be safest to forcibly release the display with
1157
 
    * dri2_display_release, to make sure the display is reinitialized correctly.
1158
 
    * However, the EGL spec states that we need to keep a reference to the
1159
 
    * current context (so we cannot call dri2_make_current(NULL)), and therefore
1160
 
    * we would leak context1 as we would be missing the old display connection
1161
 
    * to free it up correctly.
1162
 
    */
1163
 
   if (dri2_dpy) {
1164
 
      dri2_dpy->ref_count++;
1165
 
      return EGL_TRUE;
1166
 
   }
1167
 
 
1168
 
   loader_set_logger(_eglLog);
1169
 
 
1170
 
   switch (disp->Platform) {
1171
 
   case _EGL_PLATFORM_SURFACELESS:
1172
 
      ret = dri2_initialize_surfaceless(disp);
1173
 
      break;
1174
 
   case _EGL_PLATFORM_DEVICE:
1175
 
      ret = dri2_initialize_device(disp);
1176
 
      break;
1177
 
   case _EGL_PLATFORM_X11:
1178
 
   case _EGL_PLATFORM_XCB:
1179
 
      ret = dri2_initialize_x11(disp);
1180
 
      break;
1181
 
   case _EGL_PLATFORM_DRM:
1182
 
      ret = dri2_initialize_drm(disp);
1183
 
      break;
1184
 
   case _EGL_PLATFORM_WAYLAND:
1185
 
      ret = dri2_initialize_wayland(disp);
1186
 
      break;
1187
 
   case _EGL_PLATFORM_ANDROID:
1188
 
      ret = dri2_initialize_android(disp);
1189
 
      break;
1190
 
   default:
1191
 
      unreachable("Callers ensure we cannot get here.");
1192
 
      return EGL_FALSE;
1193
 
   }
1194
 
 
1195
 
   if (!ret)
1196
 
      return EGL_FALSE;
1197
 
 
1198
 
   dri2_dpy = dri2_egl_display(disp);
1199
 
   dri2_dpy->ref_count++;
1200
 
 
1201
 
   return EGL_TRUE;
1202
 
}
1203
 
 
1204
 
/**
1205
 
 * Decrement display reference count, and free up display if necessary.
1206
 
 */
1207
 
static void
1208
 
dri2_display_release(_EGLDisplay *disp)
1209
 
{
1210
 
   struct dri2_egl_display *dri2_dpy;
1211
 
 
1212
 
   if (!disp)
1213
 
      return;
1214
 
 
1215
 
   dri2_dpy = dri2_egl_display(disp);
1216
 
 
1217
 
   assert(dri2_dpy->ref_count > 0);
1218
 
   dri2_dpy->ref_count--;
1219
 
 
1220
 
   if (dri2_dpy->ref_count > 0)
1221
 
      return;
1222
 
 
1223
 
   _eglCleanupDisplay(disp);
1224
 
   dri2_display_destroy(disp);
1225
 
}
1226
 
 
1227
 
void
1228
 
dri2_display_destroy(_EGLDisplay *disp)
1229
 
{
1230
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1231
 
 
1232
 
   if (dri2_dpy->own_dri_screen) {
1233
 
      if (dri2_dpy->vtbl && dri2_dpy->vtbl->close_screen_notify)
1234
 
         dri2_dpy->vtbl->close_screen_notify(disp);
1235
 
      dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
1236
 
   }
1237
 
   if (dri2_dpy->fd >= 0)
1238
 
      close(dri2_dpy->fd);
1239
 
 
1240
 
   /* Don't dlclose the driver when building with the address sanitizer, so you
1241
 
    * get good symbols from the leak reports.
1242
 
    */
1243
 
#if !BUILT_WITH_ASAN || defined(NDEBUG)
1244
 
   if (dri2_dpy->driver)
1245
 
      dlclose(dri2_dpy->driver);
1246
 
#endif
1247
 
 
1248
 
   free(dri2_dpy->driver_name);
1249
 
 
1250
 
#ifdef HAVE_WAYLAND_PLATFORM
1251
 
   free(dri2_dpy->device_name);
1252
 
#endif
1253
 
 
1254
 
   switch (disp->Platform) {
1255
 
   case _EGL_PLATFORM_X11:
1256
 
      dri2_teardown_x11(dri2_dpy);
1257
 
      break;
1258
 
   case _EGL_PLATFORM_DRM:
1259
 
      dri2_teardown_drm(dri2_dpy);
1260
 
      break;
1261
 
   case _EGL_PLATFORM_WAYLAND:
1262
 
      dri2_teardown_wayland(dri2_dpy);
1263
 
      break;
1264
 
   default:
1265
 
      /* TODO: add teardown for other platforms */
1266
 
      break;
1267
 
   }
1268
 
 
1269
 
   /* The drm platform does not create the screen/driver_configs but reuses
1270
 
    * the ones from the gbm device. As such the gbm itself is responsible
1271
 
    * for the cleanup.
1272
 
    */
1273
 
   if (disp->Platform != _EGL_PLATFORM_DRM && dri2_dpy->driver_configs) {
1274
 
      for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++)
1275
 
         free((__DRIconfig *) dri2_dpy->driver_configs[i]);
1276
 
      free(dri2_dpy->driver_configs);
1277
 
   }
1278
 
   free(dri2_dpy);
1279
 
   disp->DriverData = NULL;
1280
 
}
1281
 
 
1282
 
__DRIbuffer *
1283
 
dri2_egl_surface_alloc_local_buffer(struct dri2_egl_surface *dri2_surf,
1284
 
                                    unsigned int att, unsigned int format)
1285
 
{
1286
 
   struct dri2_egl_display *dri2_dpy =
1287
 
      dri2_egl_display(dri2_surf->base.Resource.Display);
1288
 
 
1289
 
   if (att >= ARRAY_SIZE(dri2_surf->local_buffers))
1290
 
      return NULL;
1291
 
 
1292
 
   if (!dri2_surf->local_buffers[att]) {
1293
 
      dri2_surf->local_buffers[att] =
1294
 
         dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, att, format,
1295
 
                                        dri2_surf->base.Width, dri2_surf->base.Height);
1296
 
   }
1297
 
 
1298
 
   return dri2_surf->local_buffers[att];
1299
 
}
1300
 
 
1301
 
void
1302
 
dri2_egl_surface_free_local_buffers(struct dri2_egl_surface *dri2_surf)
1303
 
{
1304
 
   struct dri2_egl_display *dri2_dpy =
1305
 
      dri2_egl_display(dri2_surf->base.Resource.Display);
1306
 
 
1307
 
   for (int i = 0; i < ARRAY_SIZE(dri2_surf->local_buffers); i++) {
1308
 
      if (dri2_surf->local_buffers[i]) {
1309
 
         dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
1310
 
                                       dri2_surf->local_buffers[i]);
1311
 
         dri2_surf->local_buffers[i] = NULL;
1312
 
      }
1313
 
   }
1314
 
}
1315
 
 
1316
 
/**
1317
 
 * Called via eglTerminate(), drv->Terminate().
1318
 
 *
1319
 
 * This must be guaranteed to be called exactly once, even if eglTerminate is
1320
 
 * called many times (without a eglInitialize in between).
1321
 
 */
1322
 
static EGLBoolean
1323
 
dri2_terminate(_EGLDisplay *disp)
1324
 
{
1325
 
   /* Release all non-current Context/Surfaces. */
1326
 
   _eglReleaseDisplayResources(disp);
1327
 
 
1328
 
   dri2_display_release(disp);
1329
 
 
1330
 
   return EGL_TRUE;
1331
 
}
1332
 
 
1333
 
/**
1334
 
 * Set the error code after a call to
1335
 
 * dri2_egl_display::dri2::createContextAttribs.
1336
 
 */
1337
 
static void
1338
 
dri2_create_context_attribs_error(int dri_error)
1339
 
{
1340
 
   EGLint egl_error;
1341
 
 
1342
 
   switch (dri_error) {
1343
 
   case __DRI_CTX_ERROR_SUCCESS:
1344
 
      return;
1345
 
 
1346
 
   case __DRI_CTX_ERROR_NO_MEMORY:
1347
 
      egl_error = EGL_BAD_ALLOC;
1348
 
      break;
1349
 
 
1350
 
  /* From the EGL_KHR_create_context spec, section "Errors":
1351
 
   *
1352
 
   *   * If <config> does not support a client API context compatible
1353
 
   *     with the requested API major and minor version, [...] context flags,
1354
 
   *     and context reset notification behavior (for client API types where
1355
 
   *     these attributes are supported), then an EGL_BAD_MATCH error is
1356
 
   *     generated.
1357
 
   *
1358
 
   *   * If an OpenGL ES context is requested and the values for
1359
 
   *     attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
1360
 
   *     EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
1361
 
   *     is not defined, than an EGL_BAD_MATCH error is generated.
1362
 
   *
1363
 
   *   * If an OpenGL context is requested, the requested version is
1364
 
   *     greater than 3.2, and the value for attribute
1365
 
   *     EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has any
1366
 
   *     bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and
1367
 
   *     EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than
1368
 
   *     one of these bits set; or if the implementation does not support
1369
 
   *     the requested profile, then an EGL_BAD_MATCH error is generated.
1370
 
   */
1371
 
   case __DRI_CTX_ERROR_BAD_API:
1372
 
   case __DRI_CTX_ERROR_BAD_VERSION:
1373
 
   case __DRI_CTX_ERROR_BAD_FLAG:
1374
 
      egl_error = EGL_BAD_MATCH;
1375
 
      break;
1376
 
 
1377
 
  /* From the EGL_KHR_create_context spec, section "Errors":
1378
 
   *
1379
 
   *   * If an attribute name or attribute value in <attrib_list> is not
1380
 
   *     recognized (including unrecognized bits in bitmask attributes),
1381
 
   *     then an EGL_BAD_ATTRIBUTE error is generated."
1382
 
   */
1383
 
   case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE:
1384
 
   case __DRI_CTX_ERROR_UNKNOWN_FLAG:
1385
 
      egl_error = EGL_BAD_ATTRIBUTE;
1386
 
      break;
1387
 
 
1388
 
   default:
1389
 
      assert(!"unknown dri_error code");
1390
 
      egl_error = EGL_BAD_MATCH;
1391
 
      break;
1392
 
   }
1393
 
 
1394
 
   _eglError(egl_error, "dri2_create_context");
1395
 
}
1396
 
 
1397
 
static bool
1398
 
dri2_fill_context_attribs(struct dri2_egl_context *dri2_ctx,
1399
 
                          struct dri2_egl_display *dri2_dpy,
1400
 
                          uint32_t *ctx_attribs,
1401
 
                          unsigned *num_attribs)
1402
 
{
1403
 
   int pos = 0;
1404
 
 
1405
 
   assert(*num_attribs >= NUM_ATTRIBS);
1406
 
 
1407
 
   ctx_attribs[pos++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
1408
 
   ctx_attribs[pos++] = dri2_ctx->base.ClientMajorVersion;
1409
 
   ctx_attribs[pos++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
1410
 
   ctx_attribs[pos++] = dri2_ctx->base.ClientMinorVersion;
1411
 
 
1412
 
   if (dri2_ctx->base.Flags != 0) {
1413
 
      /* If the implementation doesn't support the __DRI2_ROBUSTNESS
1414
 
       * extension, don't even try to send it the robust-access flag.
1415
 
       * It may explode.  Instead, generate the required EGL error here.
1416
 
       */
1417
 
      if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0
1418
 
            && !dri2_dpy->robustness) {
1419
 
         _eglError(EGL_BAD_MATCH, "eglCreateContext");
1420
 
         return false;
1421
 
      }
1422
 
 
1423
 
      ctx_attribs[pos++] = __DRI_CTX_ATTRIB_FLAGS;
1424
 
      ctx_attribs[pos++] = dri2_ctx->base.Flags;
1425
 
   }
1426
 
 
1427
 
   if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) {
1428
 
      /* If the implementation doesn't support the __DRI2_ROBUSTNESS
1429
 
       * extension, don't even try to send it a reset strategy.  It may
1430
 
       * explode.  Instead, generate the required EGL error here.
1431
 
       */
1432
 
      if (!dri2_dpy->robustness) {
1433
 
         _eglError(EGL_BAD_CONFIG, "eglCreateContext");
1434
 
         return false;
1435
 
      }
1436
 
 
1437
 
      ctx_attribs[pos++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
1438
 
      ctx_attribs[pos++] = __DRI_CTX_RESET_LOSE_CONTEXT;
1439
 
   }
1440
 
 
1441
 
   if (dri2_ctx->base.ContextPriority != EGL_CONTEXT_PRIORITY_MEDIUM_IMG) {
1442
 
      unsigned val;
1443
 
 
1444
 
      switch (dri2_ctx->base.ContextPriority) {
1445
 
      case EGL_CONTEXT_PRIORITY_HIGH_IMG:
1446
 
         val = __DRI_CTX_PRIORITY_HIGH;
1447
 
         break;
1448
 
      case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
1449
 
         val = __DRI_CTX_PRIORITY_MEDIUM;
1450
 
         break;
1451
 
      case EGL_CONTEXT_PRIORITY_LOW_IMG:
1452
 
         val = __DRI_CTX_PRIORITY_LOW;
1453
 
         break;
1454
 
      default:
1455
 
         _eglError(EGL_BAD_CONFIG, "eglCreateContext");
1456
 
         return false;
1457
 
      }
1458
 
 
1459
 
      ctx_attribs[pos++] = __DRI_CTX_ATTRIB_PRIORITY;
1460
 
      ctx_attribs[pos++] = val;
1461
 
   }
1462
 
 
1463
 
   if (dri2_ctx->base.ReleaseBehavior == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR) {
1464
 
      ctx_attribs[pos++] = __DRI_CTX_ATTRIB_RELEASE_BEHAVIOR;
1465
 
      ctx_attribs[pos++] = __DRI_CTX_RELEASE_BEHAVIOR_NONE;
1466
 
   }
1467
 
 
1468
 
   if (dri2_ctx->base.NoError) {
1469
 
      ctx_attribs[pos++] = __DRI_CTX_ATTRIB_NO_ERROR;
1470
 
      ctx_attribs[pos++] = true;
1471
 
   }
1472
 
 
1473
 
   *num_attribs = pos;
1474
 
 
1475
 
   return true;
1476
 
}
1477
 
 
1478
 
/**
1479
 
 * Called via eglCreateContext(), drv->CreateContext().
1480
 
 */
1481
 
static _EGLContext *
1482
 
dri2_create_context(_EGLDisplay *disp, _EGLConfig *conf,
1483
 
                    _EGLContext *share_list, const EGLint *attrib_list)
1484
 
{
1485
 
   struct dri2_egl_context *dri2_ctx;
1486
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1487
 
   struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list);
1488
 
   __DRIcontext *shared =
1489
 
      dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL;
1490
 
   struct dri2_egl_config *dri2_config = dri2_egl_config(conf);
1491
 
   const __DRIconfig *dri_config;
1492
 
   int api;
1493
 
   unsigned error;
1494
 
   unsigned num_attribs = NUM_ATTRIBS;
1495
 
   uint32_t ctx_attribs[NUM_ATTRIBS];
1496
 
 
1497
 
   dri2_ctx = malloc(sizeof *dri2_ctx);
1498
 
   if (!dri2_ctx) {
1499
 
      _eglError(EGL_BAD_ALLOC, "eglCreateContext");
1500
 
      return NULL;
1501
 
   }
1502
 
 
1503
 
   if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list))
1504
 
      goto cleanup;
1505
 
 
1506
 
   /* The EGL_EXT_create_context_robustness spec says:
1507
 
    *
1508
 
    *    "Add to the eglCreateContext context creation errors: [...]
1509
 
    *
1510
 
    *     * If the reset notification behavior of <share_context> and the
1511
 
    *       newly created context are different then an EGL_BAD_MATCH error is
1512
 
    *       generated."
1513
 
    */
1514
 
   if (share_list && share_list->ResetNotificationStrategy !=
1515
 
                     dri2_ctx->base.ResetNotificationStrategy) {
1516
 
      _eglError(EGL_BAD_MATCH, "eglCreateContext");
1517
 
      goto cleanup;
1518
 
   }
1519
 
 
1520
 
   /* The EGL_KHR_create_context_no_error spec says:
1521
 
    *
1522
 
    *    "BAD_MATCH is generated if the value of EGL_CONTEXT_OPENGL_NO_ERROR_KHR
1523
 
    *    used to create <share_context> does not match the value of
1524
 
    *    EGL_CONTEXT_OPENGL_NO_ERROR_KHR for the context being created."
1525
 
    */
1526
 
   if (share_list && share_list->NoError != dri2_ctx->base.NoError) {
1527
 
      _eglError(EGL_BAD_MATCH, "eglCreateContext");
1528
 
      goto cleanup;
1529
 
   }
1530
 
 
1531
 
   switch (dri2_ctx->base.ClientAPI) {
1532
 
   case EGL_OPENGL_ES_API:
1533
 
      switch (dri2_ctx->base.ClientMajorVersion) {
1534
 
      case 1:
1535
 
         api = __DRI_API_GLES;
1536
 
         break;
1537
 
      case 2:
1538
 
         api = __DRI_API_GLES2;
1539
 
         break;
1540
 
      case 3:
1541
 
         api = __DRI_API_GLES3;
1542
 
         break;
1543
 
      default:
1544
 
         _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
1545
 
         free(dri2_ctx);
1546
 
         return NULL;
1547
 
      }
1548
 
      break;
1549
 
   case EGL_OPENGL_API:
1550
 
      if ((dri2_ctx->base.ClientMajorVersion >= 4
1551
 
           || (dri2_ctx->base.ClientMajorVersion == 3
1552
 
               && dri2_ctx->base.ClientMinorVersion >= 2))
1553
 
          && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
1554
 
         api = __DRI_API_OPENGL_CORE;
1555
 
      else if (dri2_ctx->base.ClientMajorVersion == 3 &&
1556
 
               dri2_ctx->base.ClientMinorVersion == 1)
1557
 
         api = __DRI_API_OPENGL_CORE;
1558
 
      else
1559
 
         api = __DRI_API_OPENGL;
1560
 
      break;
1561
 
   default:
1562
 
      _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
1563
 
      free(dri2_ctx);
1564
 
      return NULL;
1565
 
   }
1566
 
 
1567
 
   if (conf != NULL) {
1568
 
      /* The config chosen here isn't necessarily
1569
 
       * used for surfaces later.
1570
 
       * A pixmap surface will use the single config.
1571
 
       * This opportunity depends on disabling the
1572
 
       * doubleBufferMode check in
1573
 
       * src/mesa/main/context.c:check_compatible()
1574
 
       */
1575
 
      if (dri2_config->dri_config[1][0])
1576
 
         dri_config = dri2_config->dri_config[1][0];
1577
 
      else
1578
 
         dri_config = dri2_config->dri_config[0][0];
1579
 
   }
1580
 
   else
1581
 
      dri_config = NULL;
1582
 
 
1583
 
   if (!dri2_fill_context_attribs(dri2_ctx, dri2_dpy, ctx_attribs,
1584
 
                                  &num_attribs))
1585
 
      goto cleanup;
1586
 
 
1587
 
   if (dri2_dpy->image_driver) {
1588
 
      dri2_ctx->dri_context =
1589
 
         dri2_dpy->image_driver->createContextAttribs(dri2_dpy->dri_screen,
1590
 
                                                      api,
1591
 
                                                      dri_config,
1592
 
                                                      shared,
1593
 
                                                      num_attribs / 2,
1594
 
                                                      ctx_attribs,
1595
 
                                                      & error,
1596
 
                                                      dri2_ctx);
1597
 
      dri2_create_context_attribs_error(error);
1598
 
   } else if (dri2_dpy->dri2) {
1599
 
      if (dri2_dpy->dri2->base.version >= 3) {
1600
 
         dri2_ctx->dri_context =
1601
 
            dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen,
1602
 
                                                 api,
1603
 
                                                 dri_config,
1604
 
                                                 shared,
1605
 
                                                 num_attribs / 2,
1606
 
                                                 ctx_attribs,
1607
 
                                                 & error,
1608
 
                                                 dri2_ctx);
1609
 
         dri2_create_context_attribs_error(error);
1610
 
      } else {
1611
 
         dri2_ctx->dri_context =
1612
 
            dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
1613
 
                                                   api,
1614
 
                                                   dri_config,
1615
 
                                                   shared,
1616
 
                                                   dri2_ctx);
1617
 
      }
1618
 
   } else {
1619
 
      assert(dri2_dpy->swrast);
1620
 
      if (dri2_dpy->swrast->base.version >= 3) {
1621
 
         dri2_ctx->dri_context =
1622
 
            dri2_dpy->swrast->createContextAttribs(dri2_dpy->dri_screen,
1623
 
                                                   api,
1624
 
                                                   dri_config,
1625
 
                                                   shared,
1626
 
                                                   num_attribs / 2,
1627
 
                                                   ctx_attribs,
1628
 
                                                   & error,
1629
 
                                                   dri2_ctx);
1630
 
         dri2_create_context_attribs_error(error);
1631
 
      } else {
1632
 
         dri2_ctx->dri_context =
1633
 
            dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen,
1634
 
                                                     api,
1635
 
                                                     dri_config,
1636
 
                                                     shared,
1637
 
                                                     dri2_ctx);
1638
 
      }
1639
 
   }
1640
 
 
1641
 
   if (!dri2_ctx->dri_context)
1642
 
      goto cleanup;
1643
 
 
1644
 
   return &dri2_ctx->base;
1645
 
 
1646
 
 cleanup:
1647
 
   free(dri2_ctx);
1648
 
   return NULL;
1649
 
}
1650
 
 
1651
 
/**
1652
 
 * Called via eglDestroyContext(), drv->DestroyContext().
1653
 
 */
1654
 
static EGLBoolean
1655
 
dri2_destroy_context(_EGLDisplay *disp, _EGLContext *ctx)
1656
 
{
1657
 
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1658
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1659
 
 
1660
 
   if (_eglPutContext(ctx)) {
1661
 
      dri2_dpy->core->destroyContext(dri2_ctx->dri_context);
1662
 
      free(dri2_ctx);
1663
 
   }
1664
 
 
1665
 
   return EGL_TRUE;
1666
 
}
1667
 
 
1668
 
EGLBoolean
1669
 
dri2_init_surface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type,
1670
 
        _EGLConfig *conf, const EGLint *attrib_list,
1671
 
        EGLBoolean enable_out_fence, void *native_surface)
1672
 
{
1673
 
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1674
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1675
 
 
1676
 
   dri2_surf->out_fence_fd = -1;
1677
 
   dri2_surf->enable_out_fence = false;
1678
 
   if (dri2_dpy->fence && dri2_dpy->fence->base.version >= 2 &&
1679
 
       dri2_dpy->fence->get_capabilities &&
1680
 
       (dri2_dpy->fence->get_capabilities(dri2_dpy->dri_screen) &
1681
 
        __DRI_FENCE_CAP_NATIVE_FD)) {
1682
 
      dri2_surf->enable_out_fence = enable_out_fence;
1683
 
   }
1684
 
 
1685
 
   return _eglInitSurface(surf, disp, type, conf, attrib_list, native_surface);
1686
 
}
1687
 
 
1688
 
static void
1689
 
dri2_surface_set_out_fence_fd( _EGLSurface *surf, int fence_fd)
1690
 
{
1691
 
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1692
 
 
1693
 
   if (dri2_surf->out_fence_fd >= 0)
1694
 
      close(dri2_surf->out_fence_fd);
1695
 
 
1696
 
   dri2_surf->out_fence_fd = fence_fd;
1697
 
}
1698
 
 
1699
 
void
1700
 
dri2_fini_surface(_EGLSurface *surf)
1701
 
{
1702
 
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1703
 
 
1704
 
   dri2_surface_set_out_fence_fd(surf, -1);
1705
 
   dri2_surf->enable_out_fence = false;
1706
 
}
1707
 
 
1708
 
static EGLBoolean
1709
 
dri2_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
1710
 
{
1711
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1712
 
 
1713
 
   if (!_eglPutSurface(surf))
1714
 
      return EGL_TRUE;
1715
 
 
1716
 
   return dri2_dpy->vtbl->destroy_surface(disp, surf);
1717
 
}
1718
 
 
1719
 
static void
1720
 
dri2_surf_update_fence_fd(_EGLContext *ctx,
1721
 
                          _EGLDisplay *disp, _EGLSurface *surf)
1722
 
{
1723
 
   __DRIcontext *dri_ctx = dri2_egl_context(ctx)->dri_context;
1724
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1725
 
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1726
 
   int fence_fd = -1;
1727
 
   void *fence;
1728
 
 
1729
 
   if (!dri2_surf->enable_out_fence)
1730
 
      return;
1731
 
 
1732
 
   fence = dri2_dpy->fence->create_fence_fd(dri_ctx, -1);
1733
 
   if (fence) {
1734
 
      fence_fd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen,
1735
 
                                               fence);
1736
 
      dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, fence);
1737
 
   }
1738
 
   dri2_surface_set_out_fence_fd(surf, fence_fd);
1739
 
}
1740
 
 
1741
 
EGLBoolean
1742
 
dri2_create_drawable(struct dri2_egl_display *dri2_dpy,
1743
 
                     const __DRIconfig *config,
1744
 
                     struct dri2_egl_surface *dri2_surf,
1745
 
                     void *loaderPrivate)
1746
 
{
1747
 
   if (dri2_dpy->kopper) {
1748
 
      dri2_surf->dri_drawable =
1749
 
          dri2_dpy->kopper->createNewDrawable(dri2_dpy->dri_screen, config, loaderPrivate,
1750
 
                                              dri2_surf->base.Type == EGL_PBUFFER_BIT ||
1751
 
                                              dri2_surf->base.Type == EGL_PIXMAP_BIT);
1752
 
   } else {
1753
 
      __DRIcreateNewDrawableFunc createNewDrawable;
1754
 
      if (dri2_dpy->image_driver)
1755
 
         createNewDrawable = dri2_dpy->image_driver->createNewDrawable;
1756
 
      else if (dri2_dpy->dri2)
1757
 
         createNewDrawable = dri2_dpy->dri2->createNewDrawable;
1758
 
      else if (dri2_dpy->swrast)
1759
 
         createNewDrawable = dri2_dpy->swrast->createNewDrawable;
1760
 
      else
1761
 
         return _eglError(EGL_BAD_ALLOC, "no createNewDrawable");
1762
 
 
1763
 
      dri2_surf->dri_drawable = createNewDrawable(dri2_dpy->dri_screen,
1764
 
                                                  config, loaderPrivate);
1765
 
   }
1766
 
   if (dri2_surf->dri_drawable == NULL)
1767
 
      return _eglError(EGL_BAD_ALLOC, "createNewDrawable");
1768
 
 
1769
 
   return EGL_TRUE;
1770
 
}
1771
 
 
1772
 
/**
1773
 
 * Called via eglMakeCurrent(), drv->MakeCurrent().
1774
 
 */
1775
 
static EGLBoolean
1776
 
dri2_make_current(_EGLDisplay *disp, _EGLSurface *dsurf,
1777
 
                  _EGLSurface *rsurf, _EGLContext *ctx)
1778
 
{
1779
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1780
 
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1781
 
   _EGLDisplay *old_disp = NULL;
1782
 
   struct dri2_egl_display *old_dri2_dpy = NULL;
1783
 
   _EGLContext *old_ctx;
1784
 
   _EGLSurface *old_dsurf, *old_rsurf;
1785
 
   _EGLSurface *tmp_dsurf, *tmp_rsurf;
1786
 
   __DRIdrawable *ddraw, *rdraw;
1787
 
   __DRIcontext *cctx;
1788
 
   EGLint egl_error = EGL_SUCCESS;
1789
 
 
1790
 
   if (!dri2_dpy)
1791
 
      return _eglError(EGL_NOT_INITIALIZED, "eglMakeCurrent");
1792
 
 
1793
 
   /* make new bindings, set the EGL error otherwise */
1794
 
   if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
1795
 
      return EGL_FALSE;
1796
 
 
1797
 
   if (old_ctx == ctx && old_dsurf == dsurf && old_rsurf == rsurf) {
1798
 
      _eglPutSurface(old_dsurf);
1799
 
      _eglPutSurface(old_rsurf);
1800
 
      _eglPutContext(old_ctx);
1801
 
      return EGL_TRUE;
1802
 
   }
1803
 
 
1804
 
   if (old_ctx) {
1805
 
      __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context;
1806
 
      old_disp = old_ctx->Resource.Display;
1807
 
      old_dri2_dpy = dri2_egl_display(old_disp);
1808
 
 
1809
 
      /* Disable shared buffer mode */
1810
 
      if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) &&
1811
 
          old_dri2_dpy->vtbl->set_shared_buffer_mode) {
1812
 
         old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, false);
1813
 
      }
1814
 
 
1815
 
      dri2_dpy->core->unbindContext(old_cctx);
1816
 
 
1817
 
      if (old_dsurf)
1818
 
         dri2_surf_update_fence_fd(old_ctx, disp, old_dsurf);
1819
 
   }
1820
 
 
1821
 
   ddraw = (dsurf) ? dri2_dpy->vtbl->get_dri_drawable(dsurf) : NULL;
1822
 
   rdraw = (rsurf) ? dri2_dpy->vtbl->get_dri_drawable(rsurf) : NULL;
1823
 
   cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL;
1824
 
 
1825
 
   if (cctx || ddraw || rdraw) {
1826
 
      if (!dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
1827
 
         _EGLContext *tmp_ctx;
1828
 
 
1829
 
         /* dri2_dpy->core->bindContext failed. We cannot tell for sure why, but
1830
 
          * setting the error to EGL_BAD_MATCH is surely better than leaving it
1831
 
          * as EGL_SUCCESS.
1832
 
          */
1833
 
         egl_error = EGL_BAD_MATCH;
1834
 
 
1835
 
         /* undo the previous _eglBindContext */
1836
 
         _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &tmp_dsurf, &tmp_rsurf);
1837
 
         assert(&dri2_ctx->base == ctx &&
1838
 
                tmp_dsurf == dsurf &&
1839
 
                tmp_rsurf == rsurf);
1840
 
 
1841
 
         _eglPutSurface(dsurf);
1842
 
         _eglPutSurface(rsurf);
1843
 
         _eglPutContext(ctx);
1844
 
 
1845
 
         _eglPutSurface(old_dsurf);
1846
 
         _eglPutSurface(old_rsurf);
1847
 
         _eglPutContext(old_ctx);
1848
 
 
1849
 
         ddraw = (old_dsurf) ? dri2_dpy->vtbl->get_dri_drawable(old_dsurf) : NULL;
1850
 
         rdraw = (old_rsurf) ? dri2_dpy->vtbl->get_dri_drawable(old_rsurf) : NULL;
1851
 
         cctx = (old_ctx) ? dri2_egl_context(old_ctx)->dri_context : NULL;
1852
 
 
1853
 
         /* undo the previous dri2_dpy->core->unbindContext */
1854
 
         if (dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
1855
 
            if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) &&
1856
 
                old_dri2_dpy->vtbl->set_shared_buffer_mode) {
1857
 
               old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, true);
1858
 
            }
1859
 
 
1860
 
            return _eglError(egl_error, "eglMakeCurrent");
1861
 
         }
1862
 
 
1863
 
         /* We cannot restore the same state as it was before calling
1864
 
          * eglMakeCurrent() and the spec isn't clear about what to do. We
1865
 
          * can prevent EGL from calling into the DRI driver with no DRI
1866
 
          * context bound.
1867
 
          */
1868
 
         dsurf = rsurf = NULL;
1869
 
         ctx = NULL;
1870
 
 
1871
 
         _eglBindContext(ctx, dsurf, rsurf, &tmp_ctx, &tmp_dsurf, &tmp_rsurf);
1872
 
         assert(tmp_ctx == old_ctx && tmp_dsurf == old_dsurf &&
1873
 
                tmp_rsurf == old_rsurf);
1874
 
 
1875
 
         _eglLog(_EGL_WARNING, "DRI2: failed to rebind the previous context");
1876
 
      } else {
1877
 
         /* dri2_dpy->core->bindContext succeeded, so take a reference on the
1878
 
          * dri2_dpy. This prevents dri2_dpy from being reinitialized when a
1879
 
          * EGLDisplay is terminated and then initialized again while a
1880
 
          * context is still bound. See dri2_intitialize() for a more in depth
1881
 
          * explanation. */
1882
 
         dri2_dpy->ref_count++;
1883
 
      }
1884
 
   }
1885
 
 
1886
 
   dri2_destroy_surface(disp, old_dsurf);
1887
 
   dri2_destroy_surface(disp, old_rsurf);
1888
 
 
1889
 
   if (old_ctx) {
1890
 
      dri2_destroy_context(disp, old_ctx);
1891
 
      dri2_display_release(old_disp);
1892
 
   }
1893
 
 
1894
 
   if (egl_error != EGL_SUCCESS)
1895
 
      return _eglError(egl_error, "eglMakeCurrent");
1896
 
 
1897
 
   if (dsurf && _eglSurfaceHasMutableRenderBuffer(dsurf) &&
1898
 
       dri2_dpy->vtbl->set_shared_buffer_mode) {
1899
 
      /* Always update the shared buffer mode. This is obviously needed when
1900
 
       * the active EGL_RENDER_BUFFER is EGL_SINGLE_BUFFER. When
1901
 
       * EGL_RENDER_BUFFER is EGL_BACK_BUFFER, the update protects us in the
1902
 
       * case where external non-EGL API may have changed window's shared
1903
 
       * buffer mode since we last saw it.
1904
 
       */
1905
 
      bool mode = (dsurf->ActiveRenderBuffer == EGL_SINGLE_BUFFER);
1906
 
      dri2_dpy->vtbl->set_shared_buffer_mode(disp, dsurf, mode);
1907
 
   }
1908
 
 
1909
 
   return EGL_TRUE;
1910
 
}
1911
 
 
1912
 
__DRIdrawable *
1913
 
dri2_surface_get_dri_drawable(_EGLSurface *surf)
1914
 
{
1915
 
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1916
 
 
1917
 
   return dri2_surf->dri_drawable;
1918
 
}
1919
 
 
1920
 
/*
1921
 
 * Called from eglGetProcAddress() via drv->GetProcAddress().
1922
 
 */
1923
 
static _EGLProc
1924
 
dri2_get_proc_address(const char *procname)
1925
 
{
1926
 
   return _glapi_get_proc_address(procname);
1927
 
}
1928
 
 
1929
 
static _EGLSurface*
1930
 
dri2_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
1931
 
                           void *native_window, const EGLint *attrib_list)
1932
 
{
1933
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1934
 
   return dri2_dpy->vtbl->create_window_surface(disp, conf, native_window,
1935
 
                                                attrib_list);
1936
 
}
1937
 
 
1938
 
static _EGLSurface*
1939
 
dri2_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf,
1940
 
                           void *native_pixmap, const EGLint *attrib_list)
1941
 
{
1942
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1943
 
   if (!dri2_dpy->vtbl->create_pixmap_surface)
1944
 
      return NULL;
1945
 
   return dri2_dpy->vtbl->create_pixmap_surface(disp, conf, native_pixmap,
1946
 
                                                attrib_list);
1947
 
}
1948
 
 
1949
 
static _EGLSurface*
1950
 
dri2_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
1951
 
                            const EGLint *attrib_list)
1952
 
{
1953
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1954
 
   if (!dri2_dpy->vtbl->create_pbuffer_surface)
1955
 
      return NULL;
1956
 
   return dri2_dpy->vtbl->create_pbuffer_surface(disp, conf, attrib_list);
1957
 
}
1958
 
 
1959
 
static EGLBoolean
1960
 
dri2_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval)
1961
 
{
1962
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1963
 
   if (!dri2_dpy->vtbl->swap_interval)
1964
 
      return EGL_TRUE;
1965
 
   return dri2_dpy->vtbl->swap_interval(disp, surf, interval);
1966
 
}
1967
 
 
1968
 
/**
1969
 
 * Asks the client API to flush any rendering to the drawable so that we can
1970
 
 * do our swapbuffers.
1971
 
 */
1972
 
void
1973
 
dri2_flush_drawable_for_swapbuffers(_EGLDisplay *disp, _EGLSurface *draw)
1974
 
{
1975
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1976
 
   __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(draw);
1977
 
 
1978
 
   if (dri2_dpy->flush) {
1979
 
      if (dri2_dpy->flush->base.version >= 4) {
1980
 
         /* We know there's a current context because:
1981
 
          *
1982
 
          *     "If surface is not bound to the calling thread’s current
1983
 
          *      context, an EGL_BAD_SURFACE error is generated."
1984
 
         */
1985
 
         _EGLContext *ctx = _eglGetCurrentContext();
1986
 
         struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1987
 
 
1988
 
         /* From the EGL 1.4 spec (page 52):
1989
 
          *
1990
 
          *     "The contents of ancillary buffers are always undefined
1991
 
          *      after calling eglSwapBuffers."
1992
 
          */
1993
 
         dri2_dpy->flush->flush_with_flags(dri2_ctx->dri_context,
1994
 
                                           dri_drawable,
1995
 
                                           __DRI2_FLUSH_DRAWABLE |
1996
 
                                           __DRI2_FLUSH_INVALIDATE_ANCILLARY,
1997
 
                                           __DRI2_THROTTLE_SWAPBUFFER);
1998
 
      } else {
1999
 
         dri2_dpy->flush->flush(dri_drawable);
2000
 
      }
2001
 
   }
2002
 
}
2003
 
 
2004
 
static EGLBoolean
2005
 
dri2_swap_buffers(_EGLDisplay *disp, _EGLSurface *surf)
2006
 
{
2007
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2008
 
   __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2009
 
   _EGLContext *ctx = _eglGetCurrentContext();
2010
 
   EGLBoolean ret;
2011
 
 
2012
 
   if (ctx && surf)
2013
 
      dri2_surf_update_fence_fd(ctx, disp, surf);
2014
 
   ret = dri2_dpy->vtbl->swap_buffers(disp, surf);
2015
 
 
2016
 
   /* SwapBuffers marks the end of the frame; reset the damage region for
2017
 
    * use again next time.
2018
 
    */
2019
 
   if (ret && dri2_dpy->buffer_damage &&
2020
 
       dri2_dpy->buffer_damage->set_damage_region)
2021
 
      dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL);
2022
 
 
2023
 
   return ret;
2024
 
}
2025
 
 
2026
 
static EGLBoolean
2027
 
dri2_swap_buffers_with_damage(_EGLDisplay *disp, _EGLSurface *surf,
2028
 
                              const EGLint *rects, EGLint n_rects)
2029
 
{
2030
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2031
 
   __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2032
 
   _EGLContext *ctx = _eglGetCurrentContext();
2033
 
   EGLBoolean ret;
2034
 
 
2035
 
   if (ctx && surf)
2036
 
      dri2_surf_update_fence_fd(ctx, disp, surf);
2037
 
   if (dri2_dpy->vtbl->swap_buffers_with_damage)
2038
 
      ret = dri2_dpy->vtbl->swap_buffers_with_damage(disp, surf,
2039
 
                                                     rects, n_rects);
2040
 
   else
2041
 
      ret = dri2_dpy->vtbl->swap_buffers(disp, surf);
2042
 
 
2043
 
   /* SwapBuffers marks the end of the frame; reset the damage region for
2044
 
    * use again next time.
2045
 
    */
2046
 
   if (ret && dri2_dpy->buffer_damage &&
2047
 
       dri2_dpy->buffer_damage->set_damage_region)
2048
 
      dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL);
2049
 
 
2050
 
   return ret;
2051
 
}
2052
 
 
2053
 
static EGLBoolean
2054
 
dri2_swap_buffers_region(_EGLDisplay *disp, _EGLSurface *surf,
2055
 
                         EGLint numRects, const EGLint *rects)
2056
 
{
2057
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2058
 
   __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2059
 
   EGLBoolean ret;
2060
 
 
2061
 
   if (!dri2_dpy->vtbl->swap_buffers_region)
2062
 
      return EGL_FALSE;
2063
 
   ret = dri2_dpy->vtbl->swap_buffers_region(disp, surf, numRects, rects);
2064
 
 
2065
 
   /* SwapBuffers marks the end of the frame; reset the damage region for
2066
 
    * use again next time.
2067
 
    */
2068
 
   if (ret && dri2_dpy->buffer_damage &&
2069
 
       dri2_dpy->buffer_damage->set_damage_region)
2070
 
      dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL);
2071
 
 
2072
 
   return ret;
2073
 
}
2074
 
 
2075
 
static EGLBoolean
2076
 
dri2_set_damage_region(_EGLDisplay *disp, _EGLSurface *surf,
2077
 
                       EGLint *rects, EGLint n_rects)
2078
 
{
2079
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2080
 
   __DRIdrawable *drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2081
 
 
2082
 
   if (!dri2_dpy->buffer_damage || !dri2_dpy->buffer_damage->set_damage_region)
2083
 
      return EGL_FALSE;
2084
 
 
2085
 
   dri2_dpy->buffer_damage->set_damage_region(drawable, n_rects, rects);
2086
 
   return EGL_TRUE;
2087
 
}
2088
 
 
2089
 
static EGLBoolean
2090
 
dri2_post_sub_buffer(_EGLDisplay *disp, _EGLSurface *surf,
2091
 
                     EGLint x, EGLint y, EGLint width, EGLint height)
2092
 
{
2093
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2094
 
   if (!dri2_dpy->vtbl->post_sub_buffer)
2095
 
      return EGL_FALSE;
2096
 
   return dri2_dpy->vtbl->post_sub_buffer(disp, surf, x, y, width, height);
2097
 
}
2098
 
 
2099
 
static EGLBoolean
2100
 
dri2_copy_buffers(_EGLDisplay *disp, _EGLSurface *surf, void *native_pixmap_target)
2101
 
{
2102
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2103
 
   if (!dri2_dpy->vtbl->copy_buffers)
2104
 
      return _eglError(EGL_BAD_NATIVE_PIXMAP, "no support for native pixmaps");
2105
 
   return dri2_dpy->vtbl->copy_buffers(disp, surf, native_pixmap_target);
2106
 
}
2107
 
 
2108
 
static EGLint
2109
 
dri2_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surf)
2110
 
{
2111
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2112
 
   if (!dri2_dpy->vtbl->query_buffer_age)
2113
 
      return 0;
2114
 
   return dri2_dpy->vtbl->query_buffer_age(disp, surf);
2115
 
}
2116
 
 
2117
 
static EGLBoolean
2118
 
dri2_wait_client(_EGLDisplay *disp, _EGLContext *ctx)
2119
 
{
2120
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2121
 
   _EGLSurface *surf = ctx->DrawSurface;
2122
 
   __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2123
 
 
2124
 
   /* FIXME: If EGL allows frontbuffer rendering for window surfaces,
2125
 
    * we need to copy fake to real here.*/
2126
 
 
2127
 
   if (dri2_dpy->flush != NULL)
2128
 
      dri2_dpy->flush->flush(dri_drawable);
2129
 
 
2130
 
   return EGL_TRUE;
2131
 
}
2132
 
 
2133
 
static EGLBoolean
2134
 
dri2_wait_native(EGLint engine)
2135
 
{
2136
 
   if (engine != EGL_CORE_NATIVE_ENGINE)
2137
 
      return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
2138
 
   /* glXWaitX(); */
2139
 
 
2140
 
   return EGL_TRUE;
2141
 
}
2142
 
 
2143
 
static EGLBoolean
2144
 
dri2_bind_tex_image(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
2145
 
{
2146
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2147
 
   struct dri2_egl_context *dri2_ctx;
2148
 
   _EGLContext *ctx;
2149
 
   GLint format, target;
2150
 
   __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2151
 
 
2152
 
   ctx = _eglGetCurrentContext();
2153
 
   dri2_ctx = dri2_egl_context(ctx);
2154
 
 
2155
 
   if (!_eglBindTexImage(disp, surf, buffer))
2156
 
      return EGL_FALSE;
2157
 
 
2158
 
   switch (surf->TextureFormat) {
2159
 
   case EGL_TEXTURE_RGB:
2160
 
      format = __DRI_TEXTURE_FORMAT_RGB;
2161
 
      break;
2162
 
   case EGL_TEXTURE_RGBA:
2163
 
      format = __DRI_TEXTURE_FORMAT_RGBA;
2164
 
      break;
2165
 
   default:
2166
 
      assert(!"Unexpected texture format in dri2_bind_tex_image()");
2167
 
      format = __DRI_TEXTURE_FORMAT_RGBA;
2168
 
   }
2169
 
 
2170
 
   switch (surf->TextureTarget) {
2171
 
   case EGL_TEXTURE_2D:
2172
 
      target = GL_TEXTURE_2D;
2173
 
      break;
2174
 
   default:
2175
 
      target = GL_TEXTURE_2D;
2176
 
      assert(!"Unexpected texture target in dri2_bind_tex_image()");
2177
 
   }
2178
 
 
2179
 
   dri2_dpy->tex_buffer->setTexBuffer2(dri2_ctx->dri_context,
2180
 
                                       target, format,
2181
 
                                       dri_drawable);
2182
 
 
2183
 
   return EGL_TRUE;
2184
 
}
2185
 
 
2186
 
static EGLBoolean
2187
 
dri2_release_tex_image(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
2188
 
{
2189
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2190
 
   struct dri2_egl_context *dri2_ctx;
2191
 
   _EGLContext *ctx;
2192
 
   GLint  target;
2193
 
   __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf);
2194
 
 
2195
 
   ctx = _eglGetCurrentContext();
2196
 
   dri2_ctx = dri2_egl_context(ctx);
2197
 
 
2198
 
   if (!_eglReleaseTexImage(disp, surf, buffer))
2199
 
      return EGL_FALSE;
2200
 
 
2201
 
   switch (surf->TextureTarget) {
2202
 
   case EGL_TEXTURE_2D:
2203
 
      target = GL_TEXTURE_2D;
2204
 
      break;
2205
 
   default:
2206
 
      assert(!"missing texture target");
2207
 
   }
2208
 
 
2209
 
   if (dri2_dpy->tex_buffer->base.version >= 3 &&
2210
 
       dri2_dpy->tex_buffer->releaseTexBuffer != NULL) {
2211
 
      dri2_dpy->tex_buffer->releaseTexBuffer(dri2_ctx->dri_context,
2212
 
                                             target, dri_drawable);
2213
 
   }
2214
 
 
2215
 
   return EGL_TRUE;
2216
 
}
2217
 
 
2218
 
static _EGLImage*
2219
 
dri2_create_image(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
2220
 
                  EGLClientBuffer buffer, const EGLint *attr_list)
2221
 
{
2222
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2223
 
   return dri2_dpy->vtbl->create_image(disp, ctx, target, buffer,
2224
 
                                       attr_list);
2225
 
}
2226
 
 
2227
 
_EGLImage *
2228
 
dri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image)
2229
 
{
2230
 
   struct dri2_egl_image *dri2_img;
2231
 
 
2232
 
   if (dri_image == NULL) {
2233
 
      _eglError(EGL_BAD_ALLOC, "dri2_create_image");
2234
 
      return NULL;
2235
 
   }
2236
 
 
2237
 
   dri2_img = malloc(sizeof *dri2_img);
2238
 
   if (!dri2_img) {
2239
 
      _eglError(EGL_BAD_ALLOC, "dri2_create_image");
2240
 
      return NULL;
2241
 
   }
2242
 
 
2243
 
   _eglInitImage(&dri2_img->base, disp);
2244
 
 
2245
 
   dri2_img->dri_image = dri_image;
2246
 
 
2247
 
   return &dri2_img->base;
2248
 
}
2249
 
 
2250
 
/**
2251
 
 * Translate a DRI Image extension error code into an EGL error code.
2252
 
 */
2253
 
static EGLint
2254
 
egl_error_from_dri_image_error(int dri_error)
2255
 
{
2256
 
   switch (dri_error) {
2257
 
   case __DRI_IMAGE_ERROR_SUCCESS:
2258
 
      return EGL_SUCCESS;
2259
 
   case __DRI_IMAGE_ERROR_BAD_ALLOC:
2260
 
      return EGL_BAD_ALLOC;
2261
 
   case __DRI_IMAGE_ERROR_BAD_MATCH:
2262
 
      return EGL_BAD_MATCH;
2263
 
   case __DRI_IMAGE_ERROR_BAD_PARAMETER:
2264
 
      return EGL_BAD_PARAMETER;
2265
 
   case __DRI_IMAGE_ERROR_BAD_ACCESS:
2266
 
      return EGL_BAD_ACCESS;
2267
 
   default:
2268
 
      assert(!"unknown dri_error code");
2269
 
      return EGL_BAD_ALLOC;
2270
 
   }
2271
 
}
2272
 
 
2273
 
static _EGLImage *
2274
 
dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
2275
 
                                   EGLClientBuffer buffer,
2276
 
                                   const EGLint *attr_list)
2277
 
{
2278
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2279
 
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
2280
 
   GLuint renderbuffer = (GLuint) (uintptr_t) buffer;
2281
 
   __DRIimage *dri_image;
2282
 
 
2283
 
   if (renderbuffer == 0) {
2284
 
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2285
 
      return EGL_NO_IMAGE_KHR;
2286
 
   }
2287
 
 
2288
 
   if (!disp->Extensions.KHR_gl_renderbuffer_image) {
2289
 
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2290
 
      return EGL_NO_IMAGE_KHR;
2291
 
   }
2292
 
 
2293
 
   if (dri2_dpy->image->base.version >= 17 &&
2294
 
       dri2_dpy->image->createImageFromRenderbuffer2) {
2295
 
      unsigned error = ~0;
2296
 
 
2297
 
      dri_image = dri2_dpy->image->createImageFromRenderbuffer2(
2298
 
               dri2_ctx->dri_context, renderbuffer, NULL, &error);
2299
 
 
2300
 
      assert(!!dri_image == (error == __DRI_IMAGE_ERROR_SUCCESS));
2301
 
 
2302
 
      if (!dri_image) {
2303
 
         _eglError(egl_error_from_dri_image_error(error), "dri2_create_image_khr");
2304
 
         return EGL_NO_IMAGE_KHR;
2305
 
      }
2306
 
   } else {
2307
 
      dri_image = dri2_dpy->image->createImageFromRenderbuffer(
2308
 
               dri2_ctx->dri_context, renderbuffer, NULL);
2309
 
      if (!dri_image) {
2310
 
         _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
2311
 
         return EGL_NO_IMAGE_KHR;
2312
 
      }
2313
 
   }
2314
 
 
2315
 
   return dri2_create_image_from_dri(disp, dri_image);
2316
 
}
2317
 
 
2318
 
#ifdef HAVE_WAYLAND_PLATFORM
2319
 
 
2320
 
/* This structure describes how a wl_buffer maps to one or more
2321
 
 * __DRIimages.  A wl_drm_buffer stores the wl_drm format code and the
2322
 
 * offsets and strides of the planes in the buffer.  This table maps a
2323
 
 * wl_drm format code to a description of the planes in the buffer
2324
 
 * that lets us create a __DRIimage for each of the planes. */
2325
 
 
2326
 
static const struct wl_drm_components_descriptor {
2327
 
   uint32_t dri_components;
2328
 
   EGLint components;
2329
 
   int nplanes;
2330
 
} wl_drm_components[] = {
2331
 
   { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 },
2332
 
   { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 },
2333
 
   { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 },
2334
 
   { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 },
2335
 
   { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 },
2336
 
};
2337
 
 
2338
 
static _EGLImage *
2339
 
dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
2340
 
                                    EGLClientBuffer _buffer,
2341
 
                                    const EGLint *attr_list)
2342
 
{
2343
 
   struct wl_drm_buffer *buffer;
2344
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2345
 
   const struct wl_drm_components_descriptor *f;
2346
 
   __DRIimage *dri_image;
2347
 
   _EGLImageAttribs attrs;
2348
 
   int32_t plane;
2349
 
 
2350
 
   buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm,
2351
 
                                   (struct wl_resource *) _buffer);
2352
 
   if (!buffer)
2353
 
       return NULL;
2354
 
 
2355
 
   if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2356
 
      return NULL;
2357
 
 
2358
 
   plane = attrs.PlaneWL;
2359
 
   f = buffer->driver_format;
2360
 
   if (plane < 0 || plane >= f->nplanes) {
2361
 
      _eglError(EGL_BAD_PARAMETER,
2362
 
                "dri2_create_image_wayland_wl_buffer (plane out of bounds)");
2363
 
      return NULL;
2364
 
   }
2365
 
 
2366
 
   dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL);
2367
 
   if (dri_image == NULL && plane == 0)
2368
 
      dri_image = dri2_dpy->image->dupImage(buffer->driver_buffer, NULL);
2369
 
   if (dri_image == NULL) {
2370
 
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
2371
 
      return NULL;
2372
 
   }
2373
 
 
2374
 
   return dri2_create_image_from_dri(disp, dri_image);
2375
 
}
2376
 
#endif
2377
 
 
2378
 
static EGLBoolean
2379
 
dri2_get_sync_values_chromium(_EGLDisplay *disp, _EGLSurface *surf,
2380
 
                              EGLuint64KHR *ust, EGLuint64KHR *msc,
2381
 
                              EGLuint64KHR *sbc)
2382
 
{
2383
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2384
 
   if (!dri2_dpy->vtbl->get_sync_values)
2385
 
      return EGL_FALSE;
2386
 
   return dri2_dpy->vtbl->get_sync_values(disp, surf, ust, msc, sbc);
2387
 
}
2388
 
 
2389
 
/**
2390
 
 * Set the error code after a call to
2391
 
 * dri2_egl_image::dri_image::createImageFromTexture.
2392
 
 */
2393
 
static void
2394
 
dri2_create_image_khr_texture_error(int dri_error)
2395
 
{
2396
 
   EGLint egl_error = egl_error_from_dri_image_error(dri_error);
2397
 
 
2398
 
   if (egl_error != EGL_SUCCESS)
2399
 
      _eglError(egl_error, "dri2_create_image_khr_texture");
2400
 
}
2401
 
 
2402
 
static _EGLImage *
2403
 
dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
2404
 
                                   EGLenum target,
2405
 
                                   EGLClientBuffer buffer,
2406
 
                                   const EGLint *attr_list)
2407
 
{
2408
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2409
 
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
2410
 
   struct dri2_egl_image *dri2_img;
2411
 
   GLuint texture = (GLuint) (uintptr_t) buffer;
2412
 
   _EGLImageAttribs attrs;
2413
 
   GLuint depth;
2414
 
   GLenum gl_target;
2415
 
   unsigned error;
2416
 
 
2417
 
   if (texture == 0) {
2418
 
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2419
 
      return EGL_NO_IMAGE_KHR;
2420
 
   }
2421
 
 
2422
 
   if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2423
 
      return EGL_NO_IMAGE_KHR;
2424
 
 
2425
 
   switch (target) {
2426
 
   case EGL_GL_TEXTURE_2D_KHR:
2427
 
      if (!disp->Extensions.KHR_gl_texture_2D_image) {
2428
 
         _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2429
 
         return EGL_NO_IMAGE_KHR;
2430
 
      }
2431
 
      depth = 0;
2432
 
      gl_target = GL_TEXTURE_2D;
2433
 
      break;
2434
 
   case EGL_GL_TEXTURE_3D_KHR:
2435
 
      if (!disp->Extensions.KHR_gl_texture_3D_image) {
2436
 
         _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2437
 
         return EGL_NO_IMAGE_KHR;
2438
 
      }
2439
 
 
2440
 
      depth = attrs.GLTextureZOffset;
2441
 
      gl_target = GL_TEXTURE_3D;
2442
 
      break;
2443
 
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
2444
 
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
2445
 
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
2446
 
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
2447
 
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
2448
 
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
2449
 
      if (!disp->Extensions.KHR_gl_texture_cubemap_image) {
2450
 
         _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2451
 
         return EGL_NO_IMAGE_KHR;
2452
 
      }
2453
 
 
2454
 
      depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
2455
 
      gl_target = GL_TEXTURE_CUBE_MAP;
2456
 
      break;
2457
 
   default:
2458
 
      unreachable("Unexpected target in dri2_create_image_khr_texture()");
2459
 
      return EGL_NO_IMAGE_KHR;
2460
 
   }
2461
 
 
2462
 
   dri2_img = malloc(sizeof *dri2_img);
2463
 
   if (!dri2_img) {
2464
 
      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
2465
 
      return EGL_NO_IMAGE_KHR;
2466
 
   }
2467
 
 
2468
 
   _eglInitImage(&dri2_img->base, disp);
2469
 
 
2470
 
   dri2_img->dri_image =
2471
 
      dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context,
2472
 
                                              gl_target,
2473
 
                                              texture,
2474
 
                                              depth,
2475
 
                                              attrs.GLTextureLevel,
2476
 
                                              &error,
2477
 
                                              NULL);
2478
 
   dri2_create_image_khr_texture_error(error);
2479
 
 
2480
 
   if (!dri2_img->dri_image) {
2481
 
      free(dri2_img);
2482
 
      return EGL_NO_IMAGE_KHR;
2483
 
   }
2484
 
   return &dri2_img->base;
2485
 
}
2486
 
 
2487
 
static EGLBoolean
2488
 
dri2_query_surface(_EGLDisplay *disp, _EGLSurface *surf,
2489
 
                   EGLint attribute, EGLint *value)
2490
 
{
2491
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2492
 
   if (!dri2_dpy->vtbl->query_surface)
2493
 
      return _eglQuerySurface(disp, surf, attribute, value);
2494
 
   return dri2_dpy->vtbl->query_surface(disp, surf, attribute, value);
2495
 
}
2496
 
 
2497
 
static struct wl_buffer*
2498
 
dri2_create_wayland_buffer_from_image(_EGLDisplay *disp, _EGLImage *img)
2499
 
{
2500
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2501
 
   if (!dri2_dpy->vtbl->create_wayland_buffer_from_image)
2502
 
      return NULL;
2503
 
   return dri2_dpy->vtbl->create_wayland_buffer_from_image(disp, img);
2504
 
}
2505
 
 
2506
 
#ifdef HAVE_LIBDRM
2507
 
static _EGLImage *
2508
 
dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
2509
 
                                  EGLClientBuffer buffer, const EGLint *attr_list)
2510
 
{
2511
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2512
 
   EGLint format, name, pitch;
2513
 
   _EGLImageAttribs attrs;
2514
 
   __DRIimage *dri_image;
2515
 
 
2516
 
   name = (EGLint) (uintptr_t) buffer;
2517
 
 
2518
 
   if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2519
 
      return NULL;
2520
 
 
2521
 
   if (attrs.Width <= 0 || attrs.Height <= 0 ||
2522
 
       attrs.DRMBufferStrideMESA <= 0) {
2523
 
      _eglError(EGL_BAD_PARAMETER,
2524
 
                "bad width, height or stride");
2525
 
      return NULL;
2526
 
   }
2527
 
 
2528
 
   switch (attrs.DRMBufferFormatMESA) {
2529
 
   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
2530
 
      format = __DRI_IMAGE_FORMAT_ARGB8888;
2531
 
      pitch = attrs.DRMBufferStrideMESA;
2532
 
      break;
2533
 
   default:
2534
 
      _eglError(EGL_BAD_PARAMETER,
2535
 
                "dri2_create_image_khr: unsupported pixmap depth");
2536
 
      return NULL;
2537
 
   }
2538
 
 
2539
 
   dri_image =
2540
 
      dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
2541
 
                                           attrs.Width,
2542
 
                                           attrs.Height,
2543
 
                                           format,
2544
 
                                           name,
2545
 
                                           pitch,
2546
 
                                           NULL);
2547
 
 
2548
 
   return dri2_create_image_from_dri(disp, dri_image);
2549
 
}
2550
 
 
2551
 
static EGLBoolean
2552
 
dri2_check_dma_buf_attribs(const _EGLImageAttribs *attrs)
2553
 
{
2554
 
   /**
2555
 
     * The spec says:
2556
 
     *
2557
 
     * "Required attributes and their values are as follows:
2558
 
     *
2559
 
     *  * EGL_WIDTH & EGL_HEIGHT: The logical dimensions of the buffer in pixels
2560
 
     *
2561
 
     *  * EGL_LINUX_DRM_FOURCC_EXT: The pixel format of the buffer, as specified
2562
 
     *    by drm_fourcc.h and used as the pixel_format parameter of the
2563
 
     *    drm_mode_fb_cmd2 ioctl."
2564
 
     *
2565
 
     * and
2566
 
     *
2567
 
     * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is
2568
 
     *    incomplete, EGL_BAD_PARAMETER is generated."
2569
 
     */
2570
 
   if (attrs->Width <= 0 || attrs->Height <= 0 ||
2571
 
       !attrs->DMABufFourCC.IsPresent)
2572
 
      return _eglError(EGL_BAD_PARAMETER, "attribute(s) missing");
2573
 
 
2574
 
   /**
2575
 
    * Also:
2576
 
    *
2577
 
    * "If <target> is EGL_LINUX_DMA_BUF_EXT and one or more of the values
2578
 
    *  specified for a plane's pitch or offset isn't supported by EGL,
2579
 
    *  EGL_BAD_ACCESS is generated."
2580
 
    */
2581
 
   for (unsigned i = 0; i < ARRAY_SIZE(attrs->DMABufPlanePitches); ++i) {
2582
 
      if (attrs->DMABufPlanePitches[i].IsPresent &&
2583
 
          attrs->DMABufPlanePitches[i].Value <= 0)
2584
 
         return _eglError(EGL_BAD_ACCESS, "invalid pitch");
2585
 
   }
2586
 
 
2587
 
   /**
2588
 
    * If <target> is EGL_LINUX_DMA_BUF_EXT, both or neither of the following
2589
 
    * attribute values may be given.
2590
 
    *
2591
 
    * This is referring to EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT and
2592
 
    * EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, and the same for other planes.
2593
 
    */
2594
 
   for (unsigned i = 0; i < DMA_BUF_MAX_PLANES; ++i) {
2595
 
      if (attrs->DMABufPlaneModifiersLo[i].IsPresent !=
2596
 
          attrs->DMABufPlaneModifiersHi[i].IsPresent)
2597
 
         return _eglError(EGL_BAD_PARAMETER, "modifier attribute lo or hi missing");
2598
 
   }
2599
 
 
2600
 
   /* Although the EGL_EXT_image_dma_buf_import_modifiers spec doesn't
2601
 
    * mandate it, we only accept the same modifier across all planes. */
2602
 
   for (unsigned i = 1; i < DMA_BUF_MAX_PLANES; ++i) {
2603
 
      if (attrs->DMABufPlaneFds[i].IsPresent) {
2604
 
         if ((attrs->DMABufPlaneModifiersLo[0].IsPresent !=
2605
 
               attrs->DMABufPlaneModifiersLo[i].IsPresent) ||
2606
 
             (attrs->DMABufPlaneModifiersLo[0].Value !=
2607
 
               attrs->DMABufPlaneModifiersLo[i].Value) ||
2608
 
             (attrs->DMABufPlaneModifiersHi[0].Value !=
2609
 
               attrs->DMABufPlaneModifiersHi[i].Value))
2610
 
            return _eglError(EGL_BAD_PARAMETER, "modifier attributes not equal");
2611
 
      }
2612
 
   }
2613
 
 
2614
 
   return EGL_TRUE;
2615
 
}
2616
 
 
2617
 
/* Returns the total number of planes for the format or zero if it isn't a
2618
 
 * valid fourcc format.
2619
 
 */
2620
 
static unsigned
2621
 
dri2_num_fourcc_format_planes(EGLint format)
2622
 
{
2623
 
   switch (format) {
2624
 
   case DRM_FORMAT_R8:
2625
 
   case DRM_FORMAT_RG88:
2626
 
   case DRM_FORMAT_GR88:
2627
 
   case DRM_FORMAT_R16:
2628
 
   case DRM_FORMAT_GR1616:
2629
 
   case DRM_FORMAT_RGB332:
2630
 
   case DRM_FORMAT_BGR233:
2631
 
   case DRM_FORMAT_XRGB4444:
2632
 
   case DRM_FORMAT_XBGR4444:
2633
 
   case DRM_FORMAT_RGBX4444:
2634
 
   case DRM_FORMAT_BGRX4444:
2635
 
   case DRM_FORMAT_ARGB4444:
2636
 
   case DRM_FORMAT_ABGR4444:
2637
 
   case DRM_FORMAT_RGBA4444:
2638
 
   case DRM_FORMAT_BGRA4444:
2639
 
   case DRM_FORMAT_XRGB1555:
2640
 
   case DRM_FORMAT_XBGR1555:
2641
 
   case DRM_FORMAT_RGBX5551:
2642
 
   case DRM_FORMAT_BGRX5551:
2643
 
   case DRM_FORMAT_ARGB1555:
2644
 
   case DRM_FORMAT_ABGR1555:
2645
 
   case DRM_FORMAT_RGBA5551:
2646
 
   case DRM_FORMAT_BGRA5551:
2647
 
   case DRM_FORMAT_RGB565:
2648
 
   case DRM_FORMAT_BGR565:
2649
 
   case DRM_FORMAT_RGB888:
2650
 
   case DRM_FORMAT_BGR888:
2651
 
   case DRM_FORMAT_XRGB8888:
2652
 
   case DRM_FORMAT_XBGR8888:
2653
 
   case DRM_FORMAT_RGBX8888:
2654
 
   case DRM_FORMAT_BGRX8888:
2655
 
   case DRM_FORMAT_ARGB8888:
2656
 
   case DRM_FORMAT_ABGR8888:
2657
 
   case DRM_FORMAT_RGBA8888:
2658
 
   case DRM_FORMAT_BGRA8888:
2659
 
   case DRM_FORMAT_XRGB2101010:
2660
 
   case DRM_FORMAT_XBGR2101010:
2661
 
   case DRM_FORMAT_RGBX1010102:
2662
 
   case DRM_FORMAT_BGRX1010102:
2663
 
   case DRM_FORMAT_ARGB2101010:
2664
 
   case DRM_FORMAT_ABGR2101010:
2665
 
   case DRM_FORMAT_RGBA1010102:
2666
 
   case DRM_FORMAT_BGRA1010102:
2667
 
   case DRM_FORMAT_XBGR16161616F:
2668
 
   case DRM_FORMAT_ABGR16161616F:
2669
 
   case DRM_FORMAT_YUYV:
2670
 
   case DRM_FORMAT_YVYU:
2671
 
   case DRM_FORMAT_UYVY:
2672
 
   case DRM_FORMAT_VYUY:
2673
 
   case DRM_FORMAT_AYUV:
2674
 
   case DRM_FORMAT_XYUV8888:
2675
 
   case DRM_FORMAT_Y210:
2676
 
   case DRM_FORMAT_Y212:
2677
 
   case DRM_FORMAT_Y216:
2678
 
   case DRM_FORMAT_Y410:
2679
 
   case DRM_FORMAT_Y412:
2680
 
   case DRM_FORMAT_Y416:
2681
 
      return 1;
2682
 
 
2683
 
   case DRM_FORMAT_NV12:
2684
 
   case DRM_FORMAT_NV21:
2685
 
   case DRM_FORMAT_NV16:
2686
 
   case DRM_FORMAT_NV61:
2687
 
   case DRM_FORMAT_P010:
2688
 
   case DRM_FORMAT_P012:
2689
 
   case DRM_FORMAT_P016:
2690
 
      return 2;
2691
 
 
2692
 
   case DRM_FORMAT_YUV410:
2693
 
   case DRM_FORMAT_YVU410:
2694
 
   case DRM_FORMAT_YUV411:
2695
 
   case DRM_FORMAT_YVU411:
2696
 
   case DRM_FORMAT_YUV420:
2697
 
   case DRM_FORMAT_YVU420:
2698
 
   case DRM_FORMAT_YUV422:
2699
 
   case DRM_FORMAT_YVU422:
2700
 
   case DRM_FORMAT_YUV444:
2701
 
   case DRM_FORMAT_YVU444:
2702
 
      return 3;
2703
 
 
2704
 
   default:
2705
 
      return 0;
2706
 
   }
2707
 
}
2708
 
 
2709
 
/* Returns the total number of file descriptors. Zero indicates an error. */
2710
 
static unsigned
2711
 
dri2_check_dma_buf_format(const _EGLImageAttribs *attrs)
2712
 
{
2713
 
   unsigned plane_n = dri2_num_fourcc_format_planes(attrs->DMABufFourCC.Value);
2714
 
   if (plane_n == 0) {
2715
 
      _eglError(EGL_BAD_MATCH, "unknown drm fourcc format");
2716
 
      return 0;
2717
 
   }
2718
 
 
2719
 
   for (unsigned i = plane_n; i < DMA_BUF_MAX_PLANES; i++) {
2720
 
      /**
2721
 
       * The modifiers extension spec says:
2722
 
       *
2723
 
       * "Modifiers may modify any attribute of a buffer import, including
2724
 
       *  but not limited to adding extra planes to a format which
2725
 
       *  otherwise does not have those planes. As an example, a modifier
2726
 
       *  may add a plane for an external compression buffer to a
2727
 
       *  single-plane format. The exact meaning and effect of any
2728
 
       *  modifier is canonically defined by drm_fourcc.h, not as part of
2729
 
       *  this extension."
2730
 
       */
2731
 
      if (attrs->DMABufPlaneModifiersLo[i].IsPresent &&
2732
 
          attrs->DMABufPlaneModifiersHi[i].IsPresent) {
2733
 
         plane_n = i + 1;
2734
 
      }
2735
 
   }
2736
 
 
2737
 
   /**
2738
 
     * The spec says:
2739
 
     *
2740
 
     * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is
2741
 
     *    incomplete, EGL_BAD_PARAMETER is generated."
2742
 
     */
2743
 
   for (unsigned i = 0; i < plane_n; ++i) {
2744
 
      if (!attrs->DMABufPlaneFds[i].IsPresent ||
2745
 
          !attrs->DMABufPlaneOffsets[i].IsPresent ||
2746
 
          !attrs->DMABufPlanePitches[i].IsPresent) {
2747
 
         _eglError(EGL_BAD_PARAMETER, "plane attribute(s) missing");
2748
 
         return 0;
2749
 
      }
2750
 
   }
2751
 
 
2752
 
   /**
2753
 
    * The spec also says:
2754
 
    *
2755
 
    * "If <target> is EGL_LINUX_DMA_BUF_EXT, and the EGL_LINUX_DRM_FOURCC_EXT
2756
 
    *  attribute indicates a single-plane format, EGL_BAD_ATTRIBUTE is
2757
 
    *  generated if any of the EGL_DMA_BUF_PLANE1_* or EGL_DMA_BUF_PLANE2_*
2758
 
    *  or EGL_DMA_BUF_PLANE3_* attributes are specified."
2759
 
    */
2760
 
   for (unsigned i = plane_n; i < DMA_BUF_MAX_PLANES; ++i) {
2761
 
      if (attrs->DMABufPlaneFds[i].IsPresent ||
2762
 
          attrs->DMABufPlaneOffsets[i].IsPresent ||
2763
 
          attrs->DMABufPlanePitches[i].IsPresent) {
2764
 
         _eglError(EGL_BAD_ATTRIBUTE, "too many plane attributes");
2765
 
         return 0;
2766
 
      }
2767
 
   }
2768
 
 
2769
 
   return plane_n;
2770
 
}
2771
 
 
2772
 
static EGLBoolean
2773
 
dri2_query_dma_buf_formats(_EGLDisplay *disp, EGLint max,
2774
 
                           EGLint *formats, EGLint *count)
2775
 
{
2776
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2777
 
   if (max < 0 || (max > 0 && formats == NULL))
2778
 
      return _eglError(EGL_BAD_PARAMETER, "invalid value for max count of formats");
2779
 
 
2780
 
   if (dri2_dpy->image->base.version < 15 ||
2781
 
       dri2_dpy->image->queryDmaBufFormats == NULL)
2782
 
      return EGL_FALSE;
2783
 
 
2784
 
   if (!dri2_dpy->image->queryDmaBufFormats(dri2_dpy->dri_screen, max,
2785
 
                                            formats, count))
2786
 
      return EGL_FALSE;
2787
 
 
2788
 
   if (max > 0) {
2789
 
      /* Assert that all of the formats returned are actually fourcc formats.
2790
 
       * Some day, if we want the internal interface function to be able to
2791
 
       * return the fake fourcc formats defined in dri_interface.h, we'll have
2792
 
       * to do something more clever here to pair the list down to just real
2793
 
       * fourcc formats so that we don't leak the fake internal ones.
2794
 
       */
2795
 
      for (int i = 0; i < *count; i++) {
2796
 
         assert(dri2_num_fourcc_format_planes(formats[i]) > 0);
2797
 
      }
2798
 
   }
2799
 
 
2800
 
   return EGL_TRUE;
2801
 
}
2802
 
 
2803
 
static EGLBoolean
2804
 
dri2_query_dma_buf_modifiers(_EGLDisplay *disp, EGLint format,
2805
 
                             EGLint max, EGLuint64KHR *modifiers,
2806
 
                             EGLBoolean *external_only, EGLint *count)
2807
 
{
2808
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2809
 
 
2810
 
   if (dri2_num_fourcc_format_planes(format) == 0)
2811
 
      return _eglError(EGL_BAD_PARAMETER, "invalid fourcc format");
2812
 
 
2813
 
   if (max < 0)
2814
 
      return _eglError(EGL_BAD_PARAMETER, "invalid value for max count of formats");
2815
 
 
2816
 
   if (max > 0 && modifiers == NULL)
2817
 
      return _eglError(EGL_BAD_PARAMETER, "invalid modifiers array");
2818
 
 
2819
 
   if (dri2_dpy->image->base.version < 15 ||
2820
 
       dri2_dpy->image->queryDmaBufModifiers == NULL)
2821
 
      return EGL_FALSE;
2822
 
 
2823
 
   if (dri2_dpy->image->queryDmaBufModifiers(dri2_dpy->dri_screen, format,
2824
 
                                             max, modifiers,
2825
 
                                             (unsigned int *) external_only,
2826
 
                                             count) == false)
2827
 
      return _eglError(EGL_BAD_PARAMETER, "invalid format");
2828
 
 
2829
 
   return EGL_TRUE;
2830
 
}
2831
 
 
2832
 
/**
2833
 
 * The spec says:
2834
 
 *
2835
 
 * "If eglCreateImageKHR is successful for a EGL_LINUX_DMA_BUF_EXT target, the
2836
 
 *  EGL will take a reference to the dma_buf(s) which it will release at any
2837
 
 *  time while the EGLDisplay is initialized. It is the responsibility of the
2838
 
 *  application to close the dma_buf file descriptors."
2839
 
 *
2840
 
 * Therefore we must never close or otherwise modify the file descriptors.
2841
 
 */
2842
 
_EGLImage *
2843
 
dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
2844
 
                          EGLClientBuffer buffer, const EGLint *attr_list)
2845
 
{
2846
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2847
 
   _EGLImage *res;
2848
 
   _EGLImageAttribs attrs;
2849
 
   __DRIimage *dri_image;
2850
 
   unsigned num_fds;
2851
 
   int fds[DMA_BUF_MAX_PLANES];
2852
 
   int pitches[DMA_BUF_MAX_PLANES];
2853
 
   int offsets[DMA_BUF_MAX_PLANES];
2854
 
   uint64_t modifier;
2855
 
   bool has_modifier = false;
2856
 
   unsigned error;
2857
 
 
2858
 
   /**
2859
 
    * The spec says:
2860
 
    *
2861
 
    * ""* If <target> is EGL_LINUX_DMA_BUF_EXT and <buffer> is not NULL, the
2862
 
    *     error EGL_BAD_PARAMETER is generated."
2863
 
    */
2864
 
   if (buffer != NULL) {
2865
 
      _eglError(EGL_BAD_PARAMETER, "buffer not NULL");
2866
 
      return NULL;
2867
 
   }
2868
 
 
2869
 
   if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2870
 
      return NULL;
2871
 
 
2872
 
   if (!dri2_check_dma_buf_attribs(&attrs))
2873
 
      return NULL;
2874
 
 
2875
 
   num_fds = dri2_check_dma_buf_format(&attrs);
2876
 
   if (!num_fds)
2877
 
      return NULL;
2878
 
 
2879
 
   for (unsigned i = 0; i < num_fds; ++i) {
2880
 
      fds[i] = attrs.DMABufPlaneFds[i].Value;
2881
 
      pitches[i] = attrs.DMABufPlanePitches[i].Value;
2882
 
      offsets[i] = attrs.DMABufPlaneOffsets[i].Value;
2883
 
   }
2884
 
 
2885
 
   /* dri2_check_dma_buf_attribs ensures that the modifier, if available,
2886
 
    * will be present in attrs.DMABufPlaneModifiersLo[0] and
2887
 
    * attrs.DMABufPlaneModifiersHi[0] */
2888
 
   if (attrs.DMABufPlaneModifiersLo[0].IsPresent) {
2889
 
      modifier = combine_u32_into_u64(attrs.DMABufPlaneModifiersHi[0].Value,
2890
 
                                      attrs.DMABufPlaneModifiersLo[0].Value);
2891
 
      has_modifier = true;
2892
 
   }
2893
 
 
2894
 
   if (attrs.ProtectedContent) {
2895
 
      if (dri2_dpy->image->base.version < 18 ||
2896
 
          dri2_dpy->image->createImageFromDmaBufs3 == NULL) {
2897
 
         _eglError(EGL_BAD_MATCH, "unsupported protected_content attribute");
2898
 
         return EGL_NO_IMAGE_KHR;
2899
 
      }
2900
 
      if (!has_modifier)
2901
 
         modifier = DRM_FORMAT_MOD_INVALID;
2902
 
 
2903
 
      dri_image =
2904
 
         dri2_dpy->image->createImageFromDmaBufs3(dri2_dpy->dri_screen,
2905
 
            attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
2906
 
            modifier, fds, num_fds, pitches, offsets,
2907
 
            attrs.DMABufYuvColorSpaceHint.Value,
2908
 
            attrs.DMABufSampleRangeHint.Value,
2909
 
            attrs.DMABufChromaHorizontalSiting.Value,
2910
 
            attrs.DMABufChromaVerticalSiting.Value,
2911
 
            attrs.ProtectedContent ? __DRI_IMAGE_PROTECTED_CONTENT_FLAG : 0,
2912
 
            &error,
2913
 
            NULL);
2914
 
   }
2915
 
   else if (has_modifier) {
2916
 
      if (dri2_dpy->image->base.version < 15 ||
2917
 
          dri2_dpy->image->createImageFromDmaBufs2 == NULL) {
2918
 
         _eglError(EGL_BAD_MATCH, "unsupported dma_buf format modifier");
2919
 
         return EGL_NO_IMAGE_KHR;
2920
 
      }
2921
 
      dri_image =
2922
 
         dri2_dpy->image->createImageFromDmaBufs2(dri2_dpy->dri_screen,
2923
 
            attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
2924
 
            modifier, fds, num_fds, pitches, offsets,
2925
 
            attrs.DMABufYuvColorSpaceHint.Value,
2926
 
            attrs.DMABufSampleRangeHint.Value,
2927
 
            attrs.DMABufChromaHorizontalSiting.Value,
2928
 
            attrs.DMABufChromaVerticalSiting.Value,
2929
 
            &error,
2930
 
            NULL);
2931
 
   }
2932
 
   else {
2933
 
      dri_image =
2934
 
         dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen,
2935
 
            attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
2936
 
            fds, num_fds, pitches, offsets,
2937
 
            attrs.DMABufYuvColorSpaceHint.Value,
2938
 
            attrs.DMABufSampleRangeHint.Value,
2939
 
            attrs.DMABufChromaHorizontalSiting.Value,
2940
 
            attrs.DMABufChromaVerticalSiting.Value,
2941
 
            &error,
2942
 
            NULL);
2943
 
   }
2944
 
   dri2_create_image_khr_texture_error(error);
2945
 
 
2946
 
   if (!dri_image)
2947
 
      return EGL_NO_IMAGE_KHR;
2948
 
 
2949
 
   res = dri2_create_image_from_dri(disp, dri_image);
2950
 
 
2951
 
   return res;
2952
 
}
2953
 
static _EGLImage *
2954
 
dri2_create_drm_image_mesa(_EGLDisplay *disp, const EGLint *attr_list)
2955
 
{
2956
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2957
 
   struct dri2_egl_image *dri2_img;
2958
 
   _EGLImageAttribs attrs;
2959
 
   unsigned int dri_use, valid_mask;
2960
 
   int format;
2961
 
 
2962
 
   if (!attr_list) {
2963
 
      _eglError(EGL_BAD_PARAMETER, __func__);
2964
 
      return EGL_NO_IMAGE_KHR;
2965
 
   }
2966
 
 
2967
 
   if (!_eglParseImageAttribList(&attrs, disp, attr_list))
2968
 
      return EGL_NO_IMAGE_KHR;
2969
 
 
2970
 
   if (attrs.Width <= 0 || attrs.Height <= 0) {
2971
 
      _eglError(EGL_BAD_PARAMETER, __func__);
2972
 
      return EGL_NO_IMAGE_KHR;
2973
 
   }
2974
 
 
2975
 
   switch (attrs.DRMBufferFormatMESA) {
2976
 
   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
2977
 
      format = __DRI_IMAGE_FORMAT_ARGB8888;
2978
 
      break;
2979
 
   default:
2980
 
      _eglError(EGL_BAD_PARAMETER, __func__);
2981
 
      return EGL_NO_IMAGE_KHR;
2982
 
   }
2983
 
 
2984
 
   valid_mask =
2985
 
      EGL_DRM_BUFFER_USE_SCANOUT_MESA |
2986
 
      EGL_DRM_BUFFER_USE_SHARE_MESA |
2987
 
      EGL_DRM_BUFFER_USE_CURSOR_MESA;
2988
 
   if (attrs.DRMBufferUseMESA & ~valid_mask) {
2989
 
      _eglError(EGL_BAD_PARAMETER, __func__);
2990
 
      return EGL_NO_IMAGE_KHR;
2991
 
   }
2992
 
 
2993
 
   dri_use = 0;
2994
 
   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA)
2995
 
      dri_use |= __DRI_IMAGE_USE_SHARE;
2996
 
   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
2997
 
      dri_use |= __DRI_IMAGE_USE_SCANOUT;
2998
 
   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA)
2999
 
      dri_use |= __DRI_IMAGE_USE_CURSOR;
3000
 
 
3001
 
   dri2_img = malloc(sizeof *dri2_img);
3002
 
   if (!dri2_img) {
3003
 
      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
3004
 
      return EGL_NO_IMAGE_KHR;
3005
 
   }
3006
 
 
3007
 
   _eglInitImage(&dri2_img->base, disp);
3008
 
 
3009
 
   dri2_img->dri_image =
3010
 
      dri2_dpy->image->createImage(dri2_dpy->dri_screen,
3011
 
                                   attrs.Width, attrs.Height,
3012
 
                                   format, dri_use, dri2_img);
3013
 
   if (dri2_img->dri_image == NULL) {
3014
 
      free(dri2_img);
3015
 
       _eglError(EGL_BAD_ALLOC, "dri2_create_drm_image_mesa");
3016
 
      return EGL_NO_IMAGE_KHR;
3017
 
   }
3018
 
 
3019
 
   return &dri2_img->base;
3020
 
}
3021
 
 
3022
 
static EGLBoolean
3023
 
dri2_export_drm_image_mesa(_EGLDisplay *disp, _EGLImage *img,
3024
 
                          EGLint *name, EGLint *handle, EGLint *stride)
3025
 
{
3026
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3027
 
   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
3028
 
 
3029
 
   if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
3030
 
                                            __DRI_IMAGE_ATTRIB_NAME, name))
3031
 
      return _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
3032
 
 
3033
 
   if (handle)
3034
 
      dri2_dpy->image->queryImage(dri2_img->dri_image,
3035
 
                                  __DRI_IMAGE_ATTRIB_HANDLE, handle);
3036
 
 
3037
 
   if (stride)
3038
 
      dri2_dpy->image->queryImage(dri2_img->dri_image,
3039
 
                                  __DRI_IMAGE_ATTRIB_STRIDE, stride);
3040
 
 
3041
 
   return EGL_TRUE;
3042
 
}
3043
 
 
3044
 
/**
3045
 
 * Checks if we can support EGL_MESA_image_dma_buf_export on this image.
3046
 
 
3047
 
 * The spec provides a boolean return for the driver to reject exporting for
3048
 
 * basically any reason, but doesn't specify any particular error cases.  For
3049
 
 * now, we just fail if we don't have a DRM fourcc for the format.
3050
 
 */
3051
 
static bool
3052
 
dri2_can_export_dma_buf_image(_EGLDisplay *disp, _EGLImage *img)
3053
 
{
3054
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3055
 
   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
3056
 
   EGLint fourcc;
3057
 
 
3058
 
   if (!dri2_dpy->image->queryImage(dri2_img->dri_image,
3059
 
                                    __DRI_IMAGE_ATTRIB_FOURCC, &fourcc)) {
3060
 
      return false;
3061
 
   }
3062
 
 
3063
 
   return true;
3064
 
}
3065
 
 
3066
 
static EGLBoolean
3067
 
dri2_export_dma_buf_image_query_mesa(_EGLDisplay *disp, _EGLImage *img,
3068
 
                                     EGLint *fourcc, EGLint *nplanes,
3069
 
                                     EGLuint64KHR *modifiers)
3070
 
{
3071
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3072
 
   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
3073
 
   int num_planes;
3074
 
 
3075
 
   if (!dri2_can_export_dma_buf_image(disp, img))
3076
 
      return EGL_FALSE;
3077
 
 
3078
 
   dri2_dpy->image->queryImage(dri2_img->dri_image,
3079
 
                               __DRI_IMAGE_ATTRIB_NUM_PLANES, &num_planes);
3080
 
   if (nplanes)
3081
 
     *nplanes = num_planes;
3082
 
 
3083
 
   if (fourcc)
3084
 
      dri2_dpy->image->queryImage(dri2_img->dri_image,
3085
 
                                  __DRI_IMAGE_ATTRIB_FOURCC, fourcc);
3086
 
 
3087
 
   if (modifiers) {
3088
 
      int mod_hi, mod_lo;
3089
 
      uint64_t modifier = DRM_FORMAT_MOD_INVALID;
3090
 
      bool query;
3091
 
 
3092
 
      query = dri2_dpy->image->queryImage(dri2_img->dri_image,
3093
 
                                          __DRI_IMAGE_ATTRIB_MODIFIER_UPPER,
3094
 
                                          &mod_hi);
3095
 
      query &= dri2_dpy->image->queryImage(dri2_img->dri_image,
3096
 
                                           __DRI_IMAGE_ATTRIB_MODIFIER_LOWER,
3097
 
                                           &mod_lo);
3098
 
      if (query)
3099
 
         modifier = combine_u32_into_u64 (mod_hi, mod_lo);
3100
 
 
3101
 
      for (int i = 0; i < num_planes; i++)
3102
 
        modifiers[i] = modifier;
3103
 
   }
3104
 
 
3105
 
   return EGL_TRUE;
3106
 
}
3107
 
 
3108
 
static EGLBoolean
3109
 
dri2_export_dma_buf_image_mesa(_EGLDisplay *disp, _EGLImage *img,
3110
 
                               int *fds, EGLint *strides, EGLint *offsets)
3111
 
{
3112
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3113
 
   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
3114
 
   EGLint nplanes;
3115
 
 
3116
 
   if (!dri2_can_export_dma_buf_image(disp, img))
3117
 
      return EGL_FALSE;
3118
 
 
3119
 
   /* EGL_MESA_image_dma_buf_export spec says:
3120
 
    *    "If the number of fds is less than the number of planes, then
3121
 
    *    subsequent fd slots should contain -1."
3122
 
    */
3123
 
   if (fds) {
3124
 
      /* Query nplanes so that we know how big the given array is. */
3125
 
      dri2_dpy->image->queryImage(dri2_img->dri_image,
3126
 
                                  __DRI_IMAGE_ATTRIB_NUM_PLANES, &nplanes);
3127
 
      memset(fds, -1, nplanes * sizeof(int));
3128
 
   }
3129
 
 
3130
 
   /* rework later to provide multiple fds/strides/offsets */
3131
 
   if (fds)
3132
 
      dri2_dpy->image->queryImage(dri2_img->dri_image,
3133
 
                                  __DRI_IMAGE_ATTRIB_FD, fds);
3134
 
 
3135
 
   if (strides)
3136
 
      dri2_dpy->image->queryImage(dri2_img->dri_image,
3137
 
                                  __DRI_IMAGE_ATTRIB_STRIDE, strides);
3138
 
 
3139
 
   if (offsets) {
3140
 
      int img_offset;
3141
 
      bool ret = dri2_dpy->image->queryImage(dri2_img->dri_image,
3142
 
                     __DRI_IMAGE_ATTRIB_OFFSET, &img_offset);
3143
 
      if (ret)
3144
 
         offsets[0] = img_offset;
3145
 
      else
3146
 
         offsets[0] = 0;
3147
 
   }
3148
 
 
3149
 
   return EGL_TRUE;
3150
 
}
3151
 
 
3152
 
#endif
3153
 
 
3154
 
_EGLImage *
3155
 
dri2_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
3156
 
                      EGLClientBuffer buffer, const EGLint *attr_list)
3157
 
{
3158
 
   switch (target) {
3159
 
   case EGL_GL_TEXTURE_2D_KHR:
3160
 
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
3161
 
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
3162
 
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
3163
 
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
3164
 
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
3165
 
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
3166
 
   case EGL_GL_TEXTURE_3D_KHR:
3167
 
      return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
3168
 
   case EGL_GL_RENDERBUFFER_KHR:
3169
 
      return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
3170
 
#ifdef HAVE_LIBDRM
3171
 
   case EGL_DRM_BUFFER_MESA:
3172
 
      return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
3173
 
   case EGL_LINUX_DMA_BUF_EXT:
3174
 
      return dri2_create_image_dma_buf(disp, ctx, buffer, attr_list);
3175
 
#endif
3176
 
#ifdef HAVE_WAYLAND_PLATFORM
3177
 
   case EGL_WAYLAND_BUFFER_WL:
3178
 
      return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
3179
 
#endif
3180
 
   default:
3181
 
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
3182
 
      return EGL_NO_IMAGE_KHR;
3183
 
   }
3184
 
}
3185
 
 
3186
 
static EGLBoolean
3187
 
dri2_destroy_image_khr(_EGLDisplay *disp, _EGLImage *image)
3188
 
{
3189
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3190
 
   struct dri2_egl_image *dri2_img = dri2_egl_image(image);
3191
 
 
3192
 
   dri2_dpy->image->destroyImage(dri2_img->dri_image);
3193
 
   free(dri2_img);
3194
 
 
3195
 
   return EGL_TRUE;
3196
 
}
3197
 
 
3198
 
#ifdef HAVE_WAYLAND_PLATFORM
3199
 
 
3200
 
static void
3201
 
dri2_wl_reference_buffer(void *user_data, uint32_t name, int fd,
3202
 
                         struct wl_drm_buffer *buffer)
3203
 
{
3204
 
   _EGLDisplay *disp = user_data;
3205
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3206
 
   __DRIimage *img;
3207
 
   int dri_components = 0;
3208
 
 
3209
 
   if (fd == -1)
3210
 
      img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen,
3211
 
                                                  buffer->width,
3212
 
                                                  buffer->height,
3213
 
                                                  buffer->format,
3214
 
                                                  (int*)&name, 1,
3215
 
                                                  buffer->stride,
3216
 
                                                  buffer->offset,
3217
 
                                                  NULL);
3218
 
   else
3219
 
      img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
3220
 
                                                buffer->width,
3221
 
                                                buffer->height,
3222
 
                                                buffer->format,
3223
 
                                                &fd, 1,
3224
 
                                                buffer->stride,
3225
 
                                                buffer->offset,
3226
 
                                                NULL);
3227
 
 
3228
 
   if (img == NULL)
3229
 
      return;
3230
 
 
3231
 
   dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components);
3232
 
 
3233
 
   buffer->driver_format = NULL;
3234
 
   for (int i = 0; i < ARRAY_SIZE(wl_drm_components); i++)
3235
 
      if (wl_drm_components[i].dri_components == dri_components)
3236
 
         buffer->driver_format = &wl_drm_components[i];
3237
 
 
3238
 
   if (buffer->driver_format == NULL)
3239
 
      dri2_dpy->image->destroyImage(img);
3240
 
   else
3241
 
      buffer->driver_buffer = img;
3242
 
}
3243
 
 
3244
 
static void
3245
 
dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer)
3246
 
{
3247
 
   _EGLDisplay *disp = user_data;
3248
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3249
 
 
3250
 
   dri2_dpy->image->destroyImage(buffer->driver_buffer);
3251
 
}
3252
 
 
3253
 
static EGLBoolean
3254
 
dri2_bind_wayland_display_wl(_EGLDisplay *disp, struct wl_display *wl_dpy)
3255
 
{
3256
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3257
 
   const struct wayland_drm_callbacks wl_drm_callbacks = {
3258
 
      .authenticate = (int(*)(void *, uint32_t)) dri2_dpy->vtbl->authenticate,
3259
 
      .reference_buffer = dri2_wl_reference_buffer,
3260
 
      .release_buffer = dri2_wl_release_buffer,
3261
 
      .is_format_supported = dri2_wl_is_format_supported
3262
 
   };
3263
 
   int flags = 0;
3264
 
   char *device_name;
3265
 
   uint64_t cap;
3266
 
 
3267
 
   if (dri2_dpy->wl_server_drm)
3268
 
           return EGL_FALSE;
3269
 
 
3270
 
   device_name = drmGetRenderDeviceNameFromFd(dri2_dpy->fd);
3271
 
   if (!device_name)
3272
 
      device_name = strdup(dri2_dpy->device_name);
3273
 
   if (!device_name)
3274
 
      return EGL_FALSE;
3275
 
 
3276
 
   if (drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap) == 0 &&
3277
 
       cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT) &&
3278
 
       dri2_dpy->image->base.version >= 7 &&
3279
 
       dri2_dpy->image->createImageFromFds != NULL)
3280
 
      flags |= WAYLAND_DRM_PRIME;
3281
 
 
3282
 
   dri2_dpy->wl_server_drm =
3283
 
           wayland_drm_init(wl_dpy, device_name,
3284
 
                            &wl_drm_callbacks, disp, flags);
3285
 
 
3286
 
   free(device_name);
3287
 
 
3288
 
   if (!dri2_dpy->wl_server_drm)
3289
 
           return EGL_FALSE;
3290
 
 
3291
 
#ifdef HAVE_DRM_PLATFORM
3292
 
   /* We have to share the wl_drm instance with gbm, so gbm can convert
3293
 
    * wl_buffers to gbm bos. */
3294
 
   if (dri2_dpy->gbm_dri)
3295
 
      dri2_dpy->gbm_dri->wl_drm = dri2_dpy->wl_server_drm;
3296
 
#endif
3297
 
 
3298
 
   return EGL_TRUE;
3299
 
}
3300
 
 
3301
 
static EGLBoolean
3302
 
dri2_unbind_wayland_display_wl(_EGLDisplay *disp, struct wl_display *wl_dpy)
3303
 
{
3304
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3305
 
 
3306
 
   if (!dri2_dpy->wl_server_drm)
3307
 
           return EGL_FALSE;
3308
 
 
3309
 
   wayland_drm_uninit(dri2_dpy->wl_server_drm);
3310
 
   dri2_dpy->wl_server_drm = NULL;
3311
 
 
3312
 
   return EGL_TRUE;
3313
 
}
3314
 
 
3315
 
static EGLBoolean
3316
 
dri2_query_wayland_buffer_wl(_EGLDisplay *disp, struct wl_resource *buffer_resource,
3317
 
                             EGLint attribute, EGLint *value)
3318
 
{
3319
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3320
 
   struct wl_drm_buffer *buffer;
3321
 
   const struct wl_drm_components_descriptor *format;
3322
 
 
3323
 
   buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, buffer_resource);
3324
 
   if (!buffer)
3325
 
      return EGL_FALSE;
3326
 
 
3327
 
   format = buffer->driver_format;
3328
 
   switch (attribute) {
3329
 
   case EGL_TEXTURE_FORMAT:
3330
 
      *value = format->components;
3331
 
      return EGL_TRUE;
3332
 
   case EGL_WIDTH:
3333
 
      *value = buffer->width;
3334
 
      return EGL_TRUE;
3335
 
   case EGL_HEIGHT:
3336
 
      *value = buffer->height;
3337
 
      return EGL_TRUE;
3338
 
   }
3339
 
 
3340
 
   return EGL_FALSE;
3341
 
}
3342
 
#endif
3343
 
 
3344
 
static void
3345
 
dri2_egl_ref_sync(struct dri2_egl_sync *sync)
3346
 
{
3347
 
   p_atomic_inc(&sync->refcount);
3348
 
}
3349
 
 
3350
 
static void
3351
 
dri2_egl_unref_sync(struct dri2_egl_display *dri2_dpy,
3352
 
                    struct dri2_egl_sync *dri2_sync)
3353
 
{
3354
 
   if (p_atomic_dec_zero(&dri2_sync->refcount)) {
3355
 
      switch (dri2_sync->base.Type) {
3356
 
      case EGL_SYNC_REUSABLE_KHR:
3357
 
         cnd_destroy(&dri2_sync->cond);
3358
 
         break;
3359
 
      case EGL_SYNC_NATIVE_FENCE_ANDROID:
3360
 
         if (dri2_sync->base.SyncFd != EGL_NO_NATIVE_FENCE_FD_ANDROID)
3361
 
            close(dri2_sync->base.SyncFd);
3362
 
         break;
3363
 
      default:
3364
 
         break;
3365
 
      }
3366
 
 
3367
 
      if (dri2_sync->fence)
3368
 
         dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, dri2_sync->fence);
3369
 
 
3370
 
      free(dri2_sync);
3371
 
   }
3372
 
}
3373
 
 
3374
 
static _EGLSync *
3375
 
dri2_create_sync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list)
3376
 
{
3377
 
   _EGLContext *ctx = _eglGetCurrentContext();
3378
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3379
 
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3380
 
   struct dri2_egl_sync *dri2_sync;
3381
 
   EGLint ret;
3382
 
   pthread_condattr_t attr;
3383
 
 
3384
 
   dri2_sync = calloc(1, sizeof(struct dri2_egl_sync));
3385
 
   if (!dri2_sync) {
3386
 
      _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
3387
 
      return NULL;
3388
 
   }
3389
 
 
3390
 
   if (!_eglInitSync(&dri2_sync->base, disp, type, attrib_list)) {
3391
 
      free(dri2_sync);
3392
 
      return NULL;
3393
 
   }
3394
 
 
3395
 
   switch (type) {
3396
 
   case EGL_SYNC_FENCE_KHR:
3397
 
      dri2_sync->fence = dri2_dpy->fence->create_fence(dri2_ctx->dri_context);
3398
 
      if (!dri2_sync->fence) {
3399
 
         /* Why did it fail? DRI doesn't return an error code, so we emit
3400
 
          * a generic EGL error that doesn't communicate user error.
3401
 
          */
3402
 
         _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
3403
 
         free(dri2_sync);
3404
 
         return NULL;
3405
 
      }
3406
 
      break;
3407
 
 
3408
 
   case EGL_SYNC_CL_EVENT_KHR:
3409
 
      dri2_sync->fence = dri2_dpy->fence->get_fence_from_cl_event(
3410
 
                                 dri2_dpy->dri_screen,
3411
 
                                 dri2_sync->base.CLEvent);
3412
 
      /* this can only happen if the cl_event passed in is invalid. */
3413
 
      if (!dri2_sync->fence) {
3414
 
         _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
3415
 
         free(dri2_sync);
3416
 
         return NULL;
3417
 
      }
3418
 
 
3419
 
      /* the initial status must be "signaled" if the cl_event is signaled */
3420
 
      if (dri2_dpy->fence->client_wait_sync(dri2_ctx->dri_context,
3421
 
                                            dri2_sync->fence, 0, 0))
3422
 
         dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
3423
 
      break;
3424
 
 
3425
 
   case EGL_SYNC_REUSABLE_KHR:
3426
 
      /* intialize attr */
3427
 
      ret = pthread_condattr_init(&attr);
3428
 
 
3429
 
      if (ret) {
3430
 
         _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR");
3431
 
         free(dri2_sync);
3432
 
         return NULL;
3433
 
      }
3434
 
 
3435
 
      /* change clock attribute to CLOCK_MONOTONIC */
3436
 
      ret = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
3437
 
 
3438
 
      if (ret) {
3439
 
         _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR");
3440
 
         free(dri2_sync);
3441
 
         return NULL;
3442
 
      }
3443
 
 
3444
 
      ret = pthread_cond_init(&dri2_sync->cond, &attr);
3445
 
 
3446
 
      if (ret) {
3447
 
         _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR");
3448
 
         free(dri2_sync);
3449
 
         return NULL;
3450
 
      }
3451
 
 
3452
 
      /* initial status of reusable sync must be "unsignaled" */
3453
 
      dri2_sync->base.SyncStatus = EGL_UNSIGNALED_KHR;
3454
 
      break;
3455
 
 
3456
 
   case EGL_SYNC_NATIVE_FENCE_ANDROID:
3457
 
      if (dri2_dpy->fence->create_fence_fd) {
3458
 
         dri2_sync->fence = dri2_dpy->fence->create_fence_fd(
3459
 
                                    dri2_ctx->dri_context,
3460
 
                                    dri2_sync->base.SyncFd);
3461
 
      }
3462
 
      if (!dri2_sync->fence) {
3463
 
         _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
3464
 
         free(dri2_sync);
3465
 
         return NULL;
3466
 
      }
3467
 
      break;
3468
 
   }
3469
 
 
3470
 
   p_atomic_set(&dri2_sync->refcount, 1);
3471
 
   return &dri2_sync->base;
3472
 
}
3473
 
 
3474
 
static EGLBoolean
3475
 
dri2_destroy_sync(_EGLDisplay *disp, _EGLSync *sync)
3476
 
{
3477
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3478
 
   struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3479
 
   EGLint ret = EGL_TRUE;
3480
 
   EGLint err;
3481
 
 
3482
 
   /* if type of sync is EGL_SYNC_REUSABLE_KHR and it is not signaled yet,
3483
 
    * then unlock all threads possibly blocked by the reusable sync before
3484
 
    * destroying it.
3485
 
    */
3486
 
   if (dri2_sync->base.Type == EGL_SYNC_REUSABLE_KHR &&
3487
 
       dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR) {
3488
 
      dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
3489
 
      /* unblock all threads currently blocked by sync */
3490
 
      err = cnd_broadcast(&dri2_sync->cond);
3491
 
 
3492
 
      if (err) {
3493
 
         _eglError(EGL_BAD_ACCESS, "eglDestroySyncKHR");
3494
 
         ret = EGL_FALSE;
3495
 
      }
3496
 
   }
3497
 
 
3498
 
   dri2_egl_unref_sync(dri2_dpy, dri2_sync);
3499
 
 
3500
 
   return ret;
3501
 
}
3502
 
 
3503
 
static EGLint
3504
 
dri2_dup_native_fence_fd(_EGLDisplay *disp, _EGLSync *sync)
3505
 
{
3506
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3507
 
   struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3508
 
 
3509
 
   assert(sync->Type == EGL_SYNC_NATIVE_FENCE_ANDROID);
3510
 
 
3511
 
   if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
3512
 
      /* try to retrieve the actual native fence fd.. if rendering is
3513
 
       * not flushed this will just return -1, aka NO_NATIVE_FENCE_FD:
3514
 
       */
3515
 
      sync->SyncFd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen,
3516
 
                                                   dri2_sync->fence);
3517
 
   }
3518
 
 
3519
 
   if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
3520
 
      /* if native fence fd still not created, return an error: */
3521
 
      _eglError(EGL_BAD_PARAMETER, "eglDupNativeFenceFDANDROID");
3522
 
      return EGL_NO_NATIVE_FENCE_FD_ANDROID;
3523
 
   }
3524
 
 
3525
 
   assert(sync_valid_fd(sync->SyncFd));
3526
 
 
3527
 
   return os_dupfd_cloexec(sync->SyncFd);
3528
 
}
3529
 
 
3530
 
static void
3531
 
dri2_set_blob_cache_funcs(_EGLDisplay *disp,
3532
 
                          EGLSetBlobFuncANDROID set,
3533
 
                          EGLGetBlobFuncANDROID get)
3534
 
{
3535
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3536
 
   dri2_dpy->blob->set_cache_funcs(dri2_dpy->dri_screen,
3537
 
                                   disp->BlobCacheSet,
3538
 
                                   disp->BlobCacheGet);
3539
 
}
3540
 
 
3541
 
static EGLint
3542
 
dri2_client_wait_sync(_EGLDisplay *disp, _EGLSync *sync,
3543
 
                      EGLint flags, EGLTime timeout)
3544
 
{
3545
 
   _EGLContext *ctx = _eglGetCurrentContext();
3546
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3547
 
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3548
 
   struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3549
 
   unsigned wait_flags = 0;
3550
 
 
3551
 
   EGLint ret = EGL_CONDITION_SATISFIED_KHR;
3552
 
 
3553
 
   /* The EGL_KHR_fence_sync spec states:
3554
 
    *
3555
 
    *    "If no context is current for the bound API,
3556
 
    *     the EGL_SYNC_FLUSH_COMMANDS_BIT_KHR bit is ignored.
3557
 
    */
3558
 
   if (dri2_ctx && flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)
3559
 
      wait_flags |= __DRI2_FENCE_FLAG_FLUSH_COMMANDS;
3560
 
 
3561
 
   /* the sync object should take a reference while waiting */
3562
 
   dri2_egl_ref_sync(dri2_sync);
3563
 
 
3564
 
   switch (sync->Type) {
3565
 
   case EGL_SYNC_FENCE_KHR:
3566
 
   case EGL_SYNC_NATIVE_FENCE_ANDROID:
3567
 
   case EGL_SYNC_CL_EVENT_KHR:
3568
 
      if (dri2_dpy->fence->client_wait_sync(dri2_ctx ? dri2_ctx->dri_context : NULL,
3569
 
                                         dri2_sync->fence, wait_flags,
3570
 
                                         timeout))
3571
 
         dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
3572
 
      else
3573
 
         ret = EGL_TIMEOUT_EXPIRED_KHR;
3574
 
      break;
3575
 
 
3576
 
   case EGL_SYNC_REUSABLE_KHR:
3577
 
      if (dri2_ctx && dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR &&
3578
 
          (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)) {
3579
 
         /* flush context if EGL_SYNC_FLUSH_COMMANDS_BIT_KHR is set */
3580
 
         dri2_gl_flush();
3581
 
      }
3582
 
 
3583
 
      /* if timeout is EGL_FOREVER_KHR, it should wait without any timeout.*/
3584
 
      if (timeout == EGL_FOREVER_KHR) {
3585
 
         mtx_lock(&dri2_sync->mutex);
3586
 
         cnd_wait(&dri2_sync->cond, &dri2_sync->mutex);
3587
 
         mtx_unlock(&dri2_sync->mutex);
3588
 
      } else {
3589
 
         /* if reusable sync has not been yet signaled */
3590
 
         if (dri2_sync->base.SyncStatus != EGL_SIGNALED_KHR) {
3591
 
            /* timespecs for cnd_timedwait */
3592
 
            struct timespec current;
3593
 
            struct timespec expire;
3594
 
 
3595
 
            /* We override the clock to monotonic when creating the condition
3596
 
             * variable. */
3597
 
            clock_gettime(CLOCK_MONOTONIC, &current);
3598
 
 
3599
 
            /* calculating when to expire */
3600
 
            expire.tv_nsec = timeout % 1000000000L;
3601
 
            expire.tv_sec = timeout / 1000000000L;
3602
 
 
3603
 
            expire.tv_nsec += current.tv_nsec;
3604
 
            expire.tv_sec += current.tv_sec;
3605
 
 
3606
 
            /* expire.nsec now is a number between 0 and 1999999998 */
3607
 
            if (expire.tv_nsec > 999999999L) {
3608
 
               expire.tv_sec++;
3609
 
               expire.tv_nsec -= 1000000000L;
3610
 
            }
3611
 
 
3612
 
            mtx_lock(&dri2_sync->mutex);
3613
 
            ret = cnd_timedwait(&dri2_sync->cond, &dri2_sync->mutex, &expire);
3614
 
            mtx_unlock(&dri2_sync->mutex);
3615
 
 
3616
 
            if (ret == thrd_timedout) {
3617
 
               if (dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR) {
3618
 
                  ret = EGL_TIMEOUT_EXPIRED_KHR;
3619
 
               } else {
3620
 
                  _eglError(EGL_BAD_ACCESS, "eglClientWaitSyncKHR");
3621
 
                  ret = EGL_FALSE;
3622
 
               }
3623
 
            }
3624
 
         }
3625
 
      }
3626
 
      break;
3627
 
  }
3628
 
  dri2_egl_unref_sync(dri2_dpy, dri2_sync);
3629
 
 
3630
 
  return ret;
3631
 
}
3632
 
 
3633
 
static EGLBoolean
3634
 
dri2_signal_sync(_EGLDisplay *disp, _EGLSync *sync, EGLenum mode)
3635
 
{
3636
 
   struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3637
 
   EGLint ret;
3638
 
 
3639
 
   if (sync->Type != EGL_SYNC_REUSABLE_KHR)
3640
 
      return _eglError(EGL_BAD_MATCH, "eglSignalSyncKHR");
3641
 
 
3642
 
   if (mode != EGL_SIGNALED_KHR && mode != EGL_UNSIGNALED_KHR)
3643
 
      return _eglError(EGL_BAD_ATTRIBUTE, "eglSignalSyncKHR");
3644
 
 
3645
 
   dri2_sync->base.SyncStatus = mode;
3646
 
 
3647
 
   if (mode == EGL_SIGNALED_KHR) {
3648
 
      ret = cnd_broadcast(&dri2_sync->cond);
3649
 
 
3650
 
      /* fail to broadcast */
3651
 
      if (ret)
3652
 
         return _eglError(EGL_BAD_ACCESS, "eglSignalSyncKHR");
3653
 
   }
3654
 
 
3655
 
   return EGL_TRUE;
3656
 
}
3657
 
 
3658
 
static EGLint
3659
 
dri2_server_wait_sync(_EGLDisplay *disp, _EGLSync *sync)
3660
 
{
3661
 
   _EGLContext *ctx = _eglGetCurrentContext();
3662
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3663
 
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3664
 
   struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
3665
 
 
3666
 
   dri2_dpy->fence->server_wait_sync(dri2_ctx->dri_context,
3667
 
                                     dri2_sync->fence, 0);
3668
 
   return EGL_TRUE;
3669
 
}
3670
 
 
3671
 
static int
3672
 
dri2_interop_query_device_info(_EGLDisplay *disp, _EGLContext *ctx,
3673
 
                               struct mesa_glinterop_device_info *out)
3674
 
{
3675
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3676
 
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3677
 
 
3678
 
   if (!dri2_dpy->interop)
3679
 
      return MESA_GLINTEROP_UNSUPPORTED;
3680
 
 
3681
 
   return dri2_dpy->interop->query_device_info(dri2_ctx->dri_context, out);
3682
 
}
3683
 
 
3684
 
static int
3685
 
dri2_interop_export_object(_EGLDisplay *disp, _EGLContext *ctx,
3686
 
                           struct mesa_glinterop_export_in *in,
3687
 
                           struct mesa_glinterop_export_out *out)
3688
 
{
3689
 
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
3690
 
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
3691
 
 
3692
 
   if (!dri2_dpy->interop)
3693
 
      return MESA_GLINTEROP_UNSUPPORTED;
3694
 
 
3695
 
   return dri2_dpy->interop->export_object(dri2_ctx->dri_context, in, out);
3696
 
}
3697
 
 
3698
 
const _EGLDriver _eglDriver = {
3699
 
   .Initialize = dri2_initialize,
3700
 
   .Terminate = dri2_terminate,
3701
 
   .CreateContext = dri2_create_context,
3702
 
   .DestroyContext = dri2_destroy_context,
3703
 
   .MakeCurrent = dri2_make_current,
3704
 
   .CreateWindowSurface = dri2_create_window_surface,
3705
 
   .CreatePixmapSurface = dri2_create_pixmap_surface,
3706
 
   .CreatePbufferSurface = dri2_create_pbuffer_surface,
3707
 
   .DestroySurface = dri2_destroy_surface,
3708
 
   .GetProcAddress = dri2_get_proc_address,
3709
 
   .WaitClient = dri2_wait_client,
3710
 
   .WaitNative = dri2_wait_native,
3711
 
   .BindTexImage = dri2_bind_tex_image,
3712
 
   .ReleaseTexImage = dri2_release_tex_image,
3713
 
   .SwapInterval = dri2_swap_interval,
3714
 
   .SwapBuffers = dri2_swap_buffers,
3715
 
   .SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage,
3716
 
   .SwapBuffersRegionNOK = dri2_swap_buffers_region,
3717
 
   .SetDamageRegion = dri2_set_damage_region,
3718
 
   .PostSubBufferNV = dri2_post_sub_buffer,
3719
 
   .CopyBuffers = dri2_copy_buffers,
3720
 
   .QueryBufferAge = dri2_query_buffer_age,
3721
 
   .CreateImageKHR = dri2_create_image,
3722
 
   .DestroyImageKHR = dri2_destroy_image_khr,
3723
 
   .CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image,
3724
 
   .QuerySurface = dri2_query_surface,
3725
 
   .QueryDriverName = dri2_query_driver_name,
3726
 
   .QueryDriverConfig = dri2_query_driver_config,
3727
 
#ifdef HAVE_LIBDRM
3728
 
   .CreateDRMImageMESA = dri2_create_drm_image_mesa,
3729
 
   .ExportDRMImageMESA = dri2_export_drm_image_mesa,
3730
 
   .ExportDMABUFImageQueryMESA = dri2_export_dma_buf_image_query_mesa,
3731
 
   .ExportDMABUFImageMESA = dri2_export_dma_buf_image_mesa,
3732
 
   .QueryDmaBufFormatsEXT = dri2_query_dma_buf_formats,
3733
 
   .QueryDmaBufModifiersEXT = dri2_query_dma_buf_modifiers,
3734
 
#endif
3735
 
#ifdef HAVE_WAYLAND_PLATFORM
3736
 
   .BindWaylandDisplayWL = dri2_bind_wayland_display_wl,
3737
 
   .UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl,
3738
 
   .QueryWaylandBufferWL = dri2_query_wayland_buffer_wl,
3739
 
#endif
3740
 
   .GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium,
3741
 
   .CreateSyncKHR = dri2_create_sync,
3742
 
   .ClientWaitSyncKHR = dri2_client_wait_sync,
3743
 
   .SignalSyncKHR = dri2_signal_sync,
3744
 
   .WaitSyncKHR = dri2_server_wait_sync,
3745
 
   .DestroySyncKHR = dri2_destroy_sync,
3746
 
   .GLInteropQueryDeviceInfo = dri2_interop_query_device_info,
3747
 
   .GLInteropExportObject = dri2_interop_export_object,
3748
 
   .DupNativeFenceFDANDROID = dri2_dup_native_fence_fd,
3749
 
   .SetBlobCacheFuncsANDROID = dri2_set_blob_cache_funcs,
3750
 
};