Subversion Repositories Kolibri OS

Rev

Rev 4401 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/*
2
 * Copyright © 2010 Intel Corporation
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the "Software"),
6
 * to deal in the Software without restriction, including without limitation
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 * and/or sell copies of the Software, and to permit persons to whom the
9
 * Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice (including the next
12
 * paragraph) shall be included in all copies or substantial portions of the
13
 * Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
 * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
 * DEALINGS IN THE SOFTWARE.
23
 *
24
 * Authors:
25
 *    Kristian Høgsberg 
26
 */
27
 
28
#include 
29
#include 
30
#include 
31
#include 
32
#include 
33
#include 
34
#include 
35
#include 
36
#include 
37
#include 
38
#include 
39
#include 
40
 
41
#define EGL_EGLEXT_PROTOTYPES
42
#include 
43
#include 
44
 
45
#include "eglmode.h"
46
#include "eglscreen.h"
47
 
48
#include "egl_dri2.h"
49
 
50
typedef unsigned int lib_handle;
51
 
52
lib_handle load_library(const char *name);
53
void *get_proc_address(lib_handle lib, char *proc_name);
54
 
55
const __DRIuseInvalidateExtension use_invalidate = {
56
   { __DRI_USE_INVALIDATE, 1 }
57
};
58
 
59
EGLint dri2_to_egl_attribute_map[] = {
60
   0,
61
   EGL_BUFFER_SIZE,		/* __DRI_ATTRIB_BUFFER_SIZE */
62
   EGL_LEVEL,			/* __DRI_ATTRIB_LEVEL */
63
   EGL_RED_SIZE,		/* __DRI_ATTRIB_RED_SIZE */
64
   EGL_GREEN_SIZE,		/* __DRI_ATTRIB_GREEN_SIZE */
65
   EGL_BLUE_SIZE,		/* __DRI_ATTRIB_BLUE_SIZE */
66
   EGL_LUMINANCE_SIZE,		/* __DRI_ATTRIB_LUMINANCE_SIZE */
67
   EGL_ALPHA_SIZE,		/* __DRI_ATTRIB_ALPHA_SIZE */
68
   0,				/* __DRI_ATTRIB_ALPHA_MASK_SIZE */
69
   EGL_DEPTH_SIZE,		/* __DRI_ATTRIB_DEPTH_SIZE */
70
   EGL_STENCIL_SIZE,		/* __DRI_ATTRIB_STENCIL_SIZE */
71
   0,				/* __DRI_ATTRIB_ACCUM_RED_SIZE */
72
   0,				/* __DRI_ATTRIB_ACCUM_GREEN_SIZE */
73
   0,				/* __DRI_ATTRIB_ACCUM_BLUE_SIZE */
74
   0,				/* __DRI_ATTRIB_ACCUM_ALPHA_SIZE */
75
   EGL_SAMPLE_BUFFERS,		/* __DRI_ATTRIB_SAMPLE_BUFFERS */
76
   EGL_SAMPLES,			/* __DRI_ATTRIB_SAMPLES */
77
   0,				/* __DRI_ATTRIB_RENDER_TYPE, */
78
   0,				/* __DRI_ATTRIB_CONFIG_CAVEAT */
79
   0,				/* __DRI_ATTRIB_CONFORMANT */
80
   0,				/* __DRI_ATTRIB_DOUBLE_BUFFER */
81
   0,				/* __DRI_ATTRIB_STEREO */
82
   0,				/* __DRI_ATTRIB_AUX_BUFFERS */
83
   0,				/* __DRI_ATTRIB_TRANSPARENT_TYPE */
84
   0,				/* __DRI_ATTRIB_TRANSPARENT_INDEX_VALUE */
85
   0,				/* __DRI_ATTRIB_TRANSPARENT_RED_VALUE */
86
   0,				/* __DRI_ATTRIB_TRANSPARENT_GREEN_VALUE */
87
   0,				/* __DRI_ATTRIB_TRANSPARENT_BLUE_VALUE */
88
   0,				/* __DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE */
89
   0,				/* __DRI_ATTRIB_FLOAT_MODE (deprecated) */
90
   0,				/* __DRI_ATTRIB_RED_MASK */
91
   0,				/* __DRI_ATTRIB_GREEN_MASK */
92
   0,				/* __DRI_ATTRIB_BLUE_MASK */
93
   0,				/* __DRI_ATTRIB_ALPHA_MASK */
94
   EGL_MAX_PBUFFER_WIDTH,	/* __DRI_ATTRIB_MAX_PBUFFER_WIDTH */
95
   EGL_MAX_PBUFFER_HEIGHT,	/* __DRI_ATTRIB_MAX_PBUFFER_HEIGHT */
96
   EGL_MAX_PBUFFER_PIXELS,	/* __DRI_ATTRIB_MAX_PBUFFER_PIXELS */
97
   0,				/* __DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH */
98
   0,				/* __DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT */
99
   0,				/* __DRI_ATTRIB_VISUAL_SELECT_GROUP */
100
   0,				/* __DRI_ATTRIB_SWAP_METHOD */
101
   EGL_MAX_SWAP_INTERVAL,	/* __DRI_ATTRIB_MAX_SWAP_INTERVAL */
102
   EGL_MIN_SWAP_INTERVAL,	/* __DRI_ATTRIB_MIN_SWAP_INTERVAL */
103
   0,				/* __DRI_ATTRIB_BIND_TO_TEXTURE_RGB */
104
   0,				/* __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA */
105
   0,				/* __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE */
106
   0,				/* __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS */
107
   EGL_Y_INVERTED_NOK,		/* __DRI_ATTRIB_YINVERTED */
108
   0,				/* __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE */
109
};
110
 
111
static EGLBoolean
112
dri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria)
113
{
114
   if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0)
115
      return EGL_FALSE;
116
 
117
   if (!_eglMatchConfig(conf, criteria))
118
      return EGL_FALSE;
119
 
120
   return EGL_TRUE;
121
}
122
 
123
struct dri2_egl_config *
124
dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
125
		int depth, EGLint surface_type, const EGLint *attr_list,
126
		const unsigned int *rgba_masks)
127
{
128
   struct dri2_egl_config *conf;
129
   struct dri2_egl_display *dri2_dpy;
130
   _EGLConfig base;
131
   unsigned int attrib, value, double_buffer;
132
   EGLint key, bind_to_texture_rgb, bind_to_texture_rgba;
133
   unsigned int dri_masks[4] = { 0, 0, 0, 0 };
134
   _EGLConfig *matching_config;
135
   EGLint num_configs = 0;
136
   EGLint config_id;
137
   int i;
138
 
139
   dri2_dpy = disp->DriverData;
140
   _eglInitConfig(&base, disp, id);
141
 
142
   i = 0;
143
   double_buffer = 0;
144
   bind_to_texture_rgb = 0;
145
   bind_to_texture_rgba = 0;
146
 
147
   while (dri2_dpy->core->indexConfigAttrib(dri_config, i++, &attrib, &value)) {
148
      switch (attrib) {
149
      case __DRI_ATTRIB_RENDER_TYPE:
150
	 if (value & __DRI_ATTRIB_RGBA_BIT)
151
	    value = EGL_RGB_BUFFER;
152
	 else if (value & __DRI_ATTRIB_LUMINANCE_BIT)
153
	    value = EGL_LUMINANCE_BUFFER;
154
	 else
155
	    return NULL;
156
	 _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value);
157
	 break;
158
 
159
      case __DRI_ATTRIB_CONFIG_CAVEAT:
160
         if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
161
            value = EGL_NON_CONFORMANT_CONFIG;
162
         else if (value & __DRI_ATTRIB_SLOW_BIT)
163
            value = EGL_SLOW_CONFIG;
164
	 else
165
	    value = EGL_NONE;
166
	 _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value);
167
         break;
168
 
169
      case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB:
170
	 bind_to_texture_rgb = value;
171
	 break;
172
 
173
      case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA:
174
	 bind_to_texture_rgba = value;
175
	 break;
176
 
177
      case __DRI_ATTRIB_DOUBLE_BUFFER:
178
	 double_buffer = value;
179
	 break;
180
 
181
      case __DRI_ATTRIB_RED_MASK:
182
         dri_masks[0] = value;
183
         break;
184
 
185
      case __DRI_ATTRIB_GREEN_MASK:
186
         dri_masks[1] = value;
187
         break;
188
 
189
      case __DRI_ATTRIB_BLUE_MASK:
190
         dri_masks[2] = value;
191
         break;
192
 
193
      case __DRI_ATTRIB_ALPHA_MASK:
194
         dri_masks[3] = value;
195
         break;
196
 
197
      default:
198
	 key = dri2_to_egl_attribute_map[attrib];
199
	 if (key != 0)
200
	    _eglSetConfigKey(&base, key, value);
201
	 break;
202
      }
203
   }
204
 
205
   if (attr_list)
206
      for (i = 0; attr_list[i] != EGL_NONE; i += 2)
207
         _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]);
208
 
209
   /* Allow a 24-bit RGB visual to match a 32-bit RGBA EGLConfig.  Otherwise
210
    * it will only match a 32-bit RGBA visual.  On a composited window manager
211
    * on X11, this will make all of the EGLConfigs with destination alpha get
212
    * blended by the compositor.  This is probably not what the application
213
    * wants... especially on drivers that only have 32-bit RGBA EGLConfigs!
214
    */
215
   if (depth > 0 && depth != base.BufferSize
216
       && !(depth == 24 && base.BufferSize == 32))
217
      return NULL;
218
 
219
   if (rgba_masks && memcmp(rgba_masks, dri_masks, sizeof(dri_masks)))
220
      return NULL;
221
 
222
   base.NativeRenderable = EGL_TRUE;
223
 
224
   base.SurfaceType = surface_type;
225
   if (surface_type & (EGL_PBUFFER_BIT |
226
       (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) {
227
      base.BindToTextureRGB = bind_to_texture_rgb;
228
      if (base.AlphaSize > 0)
229
         base.BindToTextureRGBA = bind_to_texture_rgba;
230
   }
231
 
232
   base.RenderableType = disp->ClientAPIs;
233
   base.Conformant = disp->ClientAPIs;
234
 
235
   base.MinSwapInterval = dri2_dpy->min_swap_interval;
236
   base.MaxSwapInterval = dri2_dpy->max_swap_interval;
237
 
238
   if (!_eglValidateConfig(&base, EGL_FALSE)) {
239
      _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id);
240
      return NULL;
241
   }
242
 
243
   config_id = base.ConfigID;
244
   base.ConfigID    = EGL_DONT_CARE;
245
   base.SurfaceType = EGL_DONT_CARE;
246
   num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1,
247
                                 (_EGLArrayForEach) dri2_match_config, &base);
248
 
249
   if (num_configs == 1) {
250
      conf = (struct dri2_egl_config *) matching_config;
251
 
252
      if (double_buffer && !conf->dri_double_config)
253
         conf->dri_double_config = dri_config;
254
      else if (!double_buffer && !conf->dri_single_config)
255
         conf->dri_single_config = dri_config;
256
      else
257
         /* a similar config type is already added (unlikely) => discard */
258
         return NULL;
259
   }
260
   else if (num_configs == 0) {
261
      conf = malloc(sizeof *conf);
262
      if (conf == NULL)
263
         return NULL;
264
 
265
      memcpy(&conf->base, &base, sizeof base);
266
      if (double_buffer) {
267
         conf->dri_double_config = dri_config;
268
         conf->dri_single_config = NULL;
269
      } else {
270
         conf->dri_single_config = dri_config;
271
         conf->dri_double_config = NULL;
272
      }
273
      conf->base.SurfaceType = 0;
274
      conf->base.ConfigID = config_id;
275
 
276
      _eglLinkConfig(&conf->base);
277
   }
278
   else {
279
      assert(0);
280
      return NULL;
281
   }
282
 
283
   if (double_buffer) {
284
      surface_type &= ~EGL_PIXMAP_BIT;
285
   }
286
 
287
   conf->base.SurfaceType |= surface_type;
288
 
289
   return conf;
290
}
291
 
292
__DRIimage *
293
dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
294
{
295
   _EGLDisplay *disp = data;
296
   struct dri2_egl_image *dri2_img;
297
   _EGLImage *img;
298
 
299
   (void) screen;
300
 
301
   img = _eglLookupImage(image, disp);
302
   if (img == NULL) {
303
      _eglError(EGL_BAD_PARAMETER, "dri2_lookup_egl_image");
304
      return NULL;
305
   }
306
 
307
   dri2_img = dri2_egl_image(image);
308
 
309
   return dri2_img->dri_image;
310
}
311
 
312
const __DRIimageLookupExtension image_lookup_extension = {
313
   { __DRI_IMAGE_LOOKUP, 1 },
314
   dri2_lookup_egl_image
315
};
316
 
317
static const char dri_driver_path[] = "";//DEFAULT_DRIVER_DIR;
318
 
319
struct dri2_extension_match {
320
   const char *name;
321
   int version;
322
   int offset;
323
};
324
 
325
static struct dri2_extension_match dri2_driver_extensions[] = {
326
   { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
327
   { __DRI_DRI2, 2, offsetof(struct dri2_egl_display, dri2) },
328
   { NULL, 0, 0 }
329
};
330
 
331
static struct dri2_extension_match dri2_core_extensions[] = {
332
   { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) },
333
   { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
334
   { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) },
335
   { NULL, 0, 0 }
336
};
337
 
338
static struct dri2_extension_match swrast_driver_extensions[] = {
339
   { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
340
   { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) },
341
   { NULL, 0, 0 }
342
};
343
 
344
static struct dri2_extension_match swrast_core_extensions[] = {
345
   { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
346
   { NULL, 0, 0 }
347
};
348
 
349
static EGLBoolean
350
dri2_bind_extensions(struct dri2_egl_display *dri2_dpy,
351
		     struct dri2_extension_match *matches,
352
		     const __DRIextension **extensions)
353
{
354
   int i, j, ret = EGL_TRUE;
355
   void *field;
356
 
357
   for (i = 0; extensions[i]; i++) {
358
      _eglLog(_EGL_DEBUG, "DRI2: found extension `%s'", extensions[i]->name);
359
      for (j = 0; matches[j].name; j++) {
360
	 if (strcmp(extensions[i]->name, matches[j].name) == 0 &&
361
	     extensions[i]->version >= matches[j].version) {
362
	    field = ((char *) dri2_dpy + matches[j].offset);
363
	    *(const __DRIextension **) field = extensions[i];
364
	    _eglLog(_EGL_INFO, "DRI2: found extension %s version %d",
365
		    extensions[i]->name, extensions[i]->version);
366
	 }
367
      }
368
   }
369
 
370
   for (j = 0; matches[j].name; j++) {
371
      field = ((char *) dri2_dpy + matches[j].offset);
372
      if (*(const __DRIextension **) field == NULL) {
373
	 _eglLog(_EGL_FATAL, "DRI2: did not find extension %s version %d",
374
		 matches[j].name, matches[j].version);
375
	 ret = EGL_FALSE;
376
      }
377
   }
378
 
379
   return ret;
380
}
381
 
382
#if 0
383
 
384
static const __DRIextension **
385
dri2_open_driver(_EGLDisplay *disp)
386
{
387
   struct dri2_egl_display *dri2_dpy = disp->DriverData;
388
   const __DRIextension **extensions;
389
   char path[PATH_MAX], *search_paths, *p, *next, *end;
390
 
391
   search_paths = NULL;
392
   if (geteuid() == getuid()) {
393
      /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
394
      search_paths = getenv("LIBGL_DRIVERS_PATH");
395
   }
396
//   if (search_paths == NULL)
397
//      search_paths = DEFAULT_DRIVER_DIR;
398
 
399
   dri2_dpy->driver = NULL;
400
   end = search_paths + strlen(search_paths);
401
   for (p = search_paths; p < end && dri2_dpy->driver == NULL; p = next + 1) {
402
      int len;
403
      next = strchr(p, ':');
404
      if (next == NULL)
405
         next = end;
406
 
407
      len = next - p;
408
#if GLX_USE_TLS
409
      snprintf(path, sizeof path,
410
	       "%.*s/tls/%s_dri.so", len, p, dri2_dpy->driver_name);
411
      dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
412
#endif
413
      if (dri2_dpy->driver == NULL) {
414
	 snprintf(path, sizeof path,
415
		  "%.*s/%s_dri.so", len, p, dri2_dpy->driver_name);
416
	 dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
417
	 if (dri2_dpy->driver == NULL)
418
	    _eglLog(_EGL_DEBUG, "failed to open %s: %s\n", path, dlerror());
419
      }
420
   }
421
 
422
   if (dri2_dpy->driver == NULL) {
423
      _eglLog(_EGL_WARNING,
424
	      "DRI2: failed to open %s (search paths %s)",
425
	      dri2_dpy->driver_name, search_paths);
426
      return NULL;
427
   }
428
 
429
   _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path);
430
   extensions = dlsym(dri2_dpy->driver, __DRI_DRIVER_EXTENSIONS);
431
   if (extensions == NULL) {
432
      _eglLog(_EGL_WARNING,
433
	      "DRI2: driver exports no extensions (%s)", dlerror());
434
      dlclose(dri2_dpy->driver);
435
   }
436
 
437
   return extensions;
438
}
439
 
440
EGLBoolean
441
dri2_load_driver(_EGLDisplay *disp)
442
{
443
   struct dri2_egl_display *dri2_dpy = disp->DriverData;
444
   const __DRIextension **extensions;
445
 
446
   extensions = dri2_open_driver(disp);
447
   if (!extensions)
448
      return EGL_FALSE;
449
 
450
   if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) {
451
      dlclose(dri2_dpy->driver);
452
      return EGL_FALSE;
453
   }
454
 
455
   return EGL_TRUE;
456
}
457
 
458
EGLBoolean
459
dri2_load_driver_swrast(_EGLDisplay *disp)
460
{
461
   struct dri2_egl_display *dri2_dpy = disp->DriverData;
462
   const __DRIextension **extensions;
463
 
464
   dri2_dpy->driver_name = "swrast";
465
   extensions = dri2_open_driver(disp);
466
 
467
   if (!extensions)
468
      return EGL_FALSE;
469
 
470
   if (!dri2_bind_extensions(dri2_dpy, swrast_driver_extensions, extensions)) {
471
      dlclose(dri2_dpy->driver);
472
      return EGL_FALSE;
473
   }
474
 
475
   return EGL_TRUE;
476
}
477
#endif
478
 
479
void
480
dri2_setup_screen(_EGLDisplay *disp)
481
{
482
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
483
   unsigned int api_mask;
484
 
485
   if (dri2_dpy->dri2) {
486
      api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
487
   } else {
488
      assert(dri2_dpy->swrast);
489
      api_mask = 1 << __DRI_API_OPENGL |
490
                 1 << __DRI_API_GLES |
491
                 1 << __DRI_API_GLES2 |
492
                 1 << __DRI_API_GLES3;
493
   }
494
 
495
   disp->ClientAPIs = 0;
496
   if (api_mask & (1 <<__DRI_API_OPENGL))
497
      disp->ClientAPIs |= EGL_OPENGL_BIT;
498
   if (api_mask & (1 <<__DRI_API_GLES))
499
      disp->ClientAPIs |= EGL_OPENGL_ES_BIT;
500
   if (api_mask & (1 << __DRI_API_GLES2))
501
      disp->ClientAPIs |= EGL_OPENGL_ES2_BIT;
502
   if (api_mask & (1 << __DRI_API_GLES3))
503
      disp->ClientAPIs |= EGL_OPENGL_ES3_BIT_KHR;
504
 
505
   assert(dri2_dpy->dri2 || dri2_dpy->swrast);
506
   disp->Extensions.KHR_surfaceless_context = EGL_TRUE;
507
 
508
   disp->Extensions.MESA_screen_surface = EGL_TRUE;
509
 
510
   if (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) {
511
      disp->Extensions.KHR_create_context = EGL_TRUE;
512
 
513
      if (dri2_dpy->robustness)
514
         disp->Extensions.EXT_create_context_robustness = EGL_TRUE;
515
   }
516
 
517
   if (dri2_dpy->image) {
518
      disp->Extensions.MESA_drm_image = EGL_TRUE;
519
      disp->Extensions.KHR_image_base = EGL_TRUE;
520
      disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
521
      if (dri2_dpy->image->base.version >= 5 &&
522
          dri2_dpy->image->createImageFromTexture) {
523
         disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
524
         disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE;
525
      }
526
   }
527
    {
528
        _EGLMode *mode;
529
        _EGLScreen *screen = malloc(sizeof(*screen));
530
 
531
        _eglInitScreen(screen, disp, 3);
532
        mode = &screen->Modes[0];
533
        mode->Width = 800;
534
        mode->Height = 600;
535
        mode->RefreshRate = 60;
536
        mode->Optimal = EGL_FALSE;
537
        mode->Interlaced = EGL_FALSE;
538
        mode->Name = "800 x 600 60Hz";
539
 
540
 
541
        mode = &screen->Modes[1];
542
        mode->Width = 1024;
543
        mode->Height = 768;
544
        mode->RefreshRate = 60;
545
        mode->Optimal = EGL_FALSE;
546
        mode->Interlaced = EGL_FALSE;
547
        mode->Name = "1024 x 768 60Hz";
548
 
549
        mode = &screen->Modes[2];
550
        mode->Width = 1280;
551
        mode->Height = 1024;
552
        mode->RefreshRate = 60;
553
        mode->Optimal = EGL_FALSE;
554
        mode->Interlaced = EGL_FALSE;
555
        mode->Name = "1280 x 1024 60Hz";
556
 
557
        _eglLinkScreen(screen);
558
    }
559
}
560
 
561
EGLBoolean
562
dri2_create_screen(_EGLDisplay *disp)
563
{
564
   const __DRIextension **extensions;
565
   struct dri2_egl_display *dri2_dpy;
566
 
567
   dri2_dpy = disp->DriverData;
568
 
569
   if (dri2_dpy->dri2) {
570
      dri2_dpy->dri_screen =
571
         dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions,
572
				         &dri2_dpy->driver_configs, disp);
573
   } else {
574
      assert(dri2_dpy->swrast);
575
      dri2_dpy->dri_screen =
576
         dri2_dpy->swrast->createNewScreen(0, dri2_dpy->extensions,
577
                                           &dri2_dpy->driver_configs, disp);
578
   }
579
 
580
   if (dri2_dpy->dri_screen == NULL) {
581
      _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
582
      return EGL_FALSE;
583
   }
584
 
585
   dri2_dpy->own_dri_screen = 1;
586
 
587
   extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
588
 
589
   if (dri2_dpy->dri2) {
590
      unsigned i;
591
 
592
      if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
593
         goto cleanup_dri_screen;
594
 
595
      for (i = 0; extensions[i]; i++) {
596
	 if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0) {
597
            dri2_dpy->robustness = (__DRIrobustnessExtension *) extensions[i];
598
	 }
599
	 if (strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0) {
600
	    dri2_dpy->config = (__DRI2configQueryExtension *) extensions[i];
601
	 }
602
      }
603
   } else {
604
      assert(dri2_dpy->swrast);
605
      if (!dri2_bind_extensions(dri2_dpy, swrast_core_extensions, extensions))
606
         goto cleanup_dri_screen;
607
   }
608
 
609
   dri2_setup_screen(disp);
610
 
611
   return EGL_TRUE;
612
 
613
 cleanup_dri_screen:
614
   dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
615
 
616
   return EGL_FALSE;
617
}
618
 
619
/**
620
 * Called via eglInitialize(), GLX_drv->API.Initialize().
621
 */
622
static EGLBoolean
623
dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp)
624
{
625
   /* not until swrast_dri is supported */
626
   if (disp->Options.UseFallback)
627
      return EGL_FALSE;
628
 
629
   return dri2_initialize_drm(drv, disp);
630
 
631
#if 0
632
   switch (disp->Platform) {
633
#ifdef HAVE_X11_PLATFORM
634
   case _EGL_PLATFORM_X11:
635
      if (disp->Options.TestOnly)
636
         return EGL_TRUE;
637
      return dri2_initialize_x11(drv, disp);
638
#endif
639
 
640
#ifdef HAVE_LIBUDEV
641
#ifdef HAVE_DRM_PLATFORM
642
   case _EGL_PLATFORM_DRM:
643
      if (disp->Options.TestOnly)
644
         return EGL_TRUE;
645
      return dri2_initialize_drm(drv, disp);
646
#endif
647
#ifdef HAVE_WAYLAND_PLATFORM
648
   case _EGL_PLATFORM_WAYLAND:
649
      if (disp->Options.TestOnly)
650
         return EGL_TRUE;
651
      return dri2_initialize_wayland(drv, disp);
652
#endif
653
#endif
654
#ifdef HAVE_ANDROID_PLATFORM
655
   case _EGL_PLATFORM_ANDROID:
656
      if (disp->Options.TestOnly)
657
         return EGL_TRUE;
658
      return dri2_initialize_android(drv, disp);
659
#endif
660
 
661
   default:
662
      return EGL_FALSE;
663
   }
664
#endif
665
}
666
 
667
/**
668
 * Called via eglTerminate(), drv->API.Terminate().
669
 */
670
static EGLBoolean
671
dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
672
{
673
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
674
 
675
   _eglReleaseDisplayResources(drv, disp);
676
   _eglCleanupDisplay(disp);
677
 
678
   if (dri2_dpy->own_dri_screen)
679
      dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
680
//   if (dri2_dpy->fd)
681
//      close(dri2_dpy->fd);
682
//   if (dri2_dpy->driver)
683
//      dlclose(dri2_dpy->driver);
684
   free(dri2_dpy->device_name);
685
 
686
   if (disp->PlatformDisplay == NULL) {
687
      switch (disp->Platform) {
688
#ifdef HAVE_X11_PLATFORM
689
      case _EGL_PLATFORM_X11:
690
         xcb_disconnect(dri2_dpy->conn);
691
         break;
692
#endif
693
#ifdef HAVE_DRM_PLATFORM
694
      case _EGL_PLATFORM_DRM:
695
         if (dri2_dpy->own_device) {
696
            gbm_device_destroy(&dri2_dpy->gbm_dri->base.base);
697
         }
698
         break;
699
#endif
700
      default:
701
         break;
702
      }
703
   }
704
 
705
   free(dri2_dpy);
706
   disp->DriverData = NULL;
707
 
708
   return EGL_TRUE;
709
}
710
 
711
/**
712
 * Set the error code after a call to
713
 * dri2_egl_display::dri2::createContextAttribs.
714
 */
715
static void
716
dri2_create_context_attribs_error(int dri_error)
717
{
718
   EGLint egl_error;
719
 
720
   switch (dri_error) {
721
   case __DRI_CTX_ERROR_SUCCESS:
722
      return;
723
 
724
   case __DRI_CTX_ERROR_NO_MEMORY:
725
      egl_error = EGL_BAD_ALLOC;
726
      break;
727
 
728
  /* From the EGL_KHR_create_context spec, section "Errors":
729
   *
730
   *   * If  does not support a client API context compatible
731
   *     with the requested API major and minor version, [...] context flags,
732
   *     and context reset notification behavior (for client API types where
733
   *     these attributes are supported), then an EGL_BAD_MATCH error is
734
   *     generated.
735
   *
736
   *   * If an OpenGL ES context is requested and the values for
737
   *     attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
738
   *     EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
739
   *     is not defined, than an EGL_BAD_MATCH error is generated.
740
   *
741
   *   * If an OpenGL context is requested, the requested version is
742
   *     greater than 3.2, and the value for attribute
743
   *     EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has any
744
   *     bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and
745
   *     EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than
746
   *     one of these bits set; or if the implementation does not support
747
   *     the requested profile, then an EGL_BAD_MATCH error is generated.
748
   */
749
   case __DRI_CTX_ERROR_BAD_API:
750
   case __DRI_CTX_ERROR_BAD_VERSION:
751
   case __DRI_CTX_ERROR_BAD_FLAG:
752
      egl_error = EGL_BAD_MATCH;
753
      break;
754
 
755
  /* From the EGL_KHR_create_context spec, section "Errors":
756
   *
757
   *   * If an attribute name or attribute value in  is not
758
   *     recognized (including unrecognized bits in bitmask attributes),
759
   *     then an EGL_BAD_ATTRIBUTE error is generated."
760
   */
761
   case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE:
762
   case __DRI_CTX_ERROR_UNKNOWN_FLAG:
763
      egl_error = EGL_BAD_ATTRIBUTE;
764
      break;
765
 
766
   default:
767
      assert(0);
768
      egl_error = EGL_BAD_MATCH;
769
      break;
770
   }
771
 
772
   _eglError(egl_error, "dri2_create_context");
773
}
774
 
775
/**
776
 * Called via eglCreateContext(), drv->API.CreateContext().
777
 */
778
static _EGLContext *
779
dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
780
		    _EGLContext *share_list, const EGLint *attrib_list)
781
{
782
   struct dri2_egl_context *dri2_ctx;
783
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
784
   struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list);
785
   __DRIcontext *shared =
786
      dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL;
787
   struct dri2_egl_config *dri2_config = dri2_egl_config(conf);
788
   const __DRIconfig *dri_config;
789
   int api;
790
 
791
   (void) drv;
792
 
793
   dri2_ctx = malloc(sizeof *dri2_ctx);
794
   if (!dri2_ctx) {
795
      _eglError(EGL_BAD_ALLOC, "eglCreateContext");
796
      return NULL;
797
   }
798
 
799
   if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list))
800
      goto cleanup;
801
 
802
   switch (dri2_ctx->base.ClientAPI) {
803
   case EGL_OPENGL_ES_API:
804
      switch (dri2_ctx->base.ClientMajorVersion) {
805
      case 1:
806
         api = __DRI_API_GLES;
807
         break;
808
      case 2:
809
         api = __DRI_API_GLES2;
810
         break;
811
      case 3:
812
         api = __DRI_API_GLES3;
813
         break;
814
      default:
815
	 _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
816
	 return NULL;
817
      }
818
      break;
819
   case EGL_OPENGL_API:
820
      if ((dri2_ctx->base.ClientMajorVersion >= 4
821
           || (dri2_ctx->base.ClientMajorVersion == 3
822
               && dri2_ctx->base.ClientMinorVersion >= 2))
823
          && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
824
         api = __DRI_API_OPENGL_CORE;
825
      else
826
         api = __DRI_API_OPENGL;
827
      break;
828
   default:
829
      _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
830
      free(dri2_ctx);
831
      return NULL;
832
   }
833
 
834
   if (conf != NULL) {
835
      /* The config chosen here isn't necessarily
836
       * used for surfaces later.
837
       * A pixmap surface will use the single config.
838
       * This opportunity depends on disabling the
839
       * doubleBufferMode check in
840
       * src/mesa/main/context.c:check_compatible()
841
       */
842
      if (dri2_config->dri_double_config)
843
         dri_config = dri2_config->dri_double_config;
844
      else
845
         dri_config = dri2_config->dri_single_config;
846
 
847
      /* EGL_WINDOW_BIT is set only when there is a dri_double_config.  This
848
       * makes sure the back buffer will always be used.
849
       */
850
      if (conf->SurfaceType & EGL_WINDOW_BIT)
851
         dri2_ctx->base.WindowRenderBuffer = EGL_BACK_BUFFER;
852
   }
853
   else
854
      dri_config = NULL;
855
 
856
   if (dri2_dpy->dri2) {
857
      if (dri2_dpy->dri2->base.version >= 3) {
858
         unsigned error;
859
         unsigned num_attribs = 0;
860
         uint32_t ctx_attribs[8];
861
 
862
         ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
863
         ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMajorVersion;
864
         ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
865
         ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMinorVersion;
866
 
867
         if (dri2_ctx->base.Flags != 0) {
868
            /* If the implementation doesn't support the __DRI2_ROBUSTNESS
869
             * extension, don't even try to send it the robust-access flag.
870
             * It may explode.  Instead, generate the required EGL error here.
871
             */
872
            if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0
873
                && !dri2_dpy->robustness) {
874
               _eglError(EGL_BAD_MATCH, "eglCreateContext");
875
               goto cleanup;
876
            }
877
 
878
            ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
879
            ctx_attribs[num_attribs++] = dri2_ctx->base.Flags;
880
         }
881
 
882
         if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) {
883
            /* If the implementation doesn't support the __DRI2_ROBUSTNESS
884
             * extension, don't even try to send it a reset strategy.  It may
885
             * explode.  Instead, generate the required EGL error here.
886
             */
887
            if (!dri2_dpy->robustness) {
888
               _eglError(EGL_BAD_CONFIG, "eglCreateContext");
889
               goto cleanup;
890
            }
891
 
892
            ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
893
            ctx_attribs[num_attribs++] = __DRI_CTX_RESET_LOSE_CONTEXT;
894
         }
895
 
896
         assert(num_attribs <= ARRAY_SIZE(ctx_attribs));
897
 
898
	 dri2_ctx->dri_context =
899
	    dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen,
900
                                                 api,
901
                                                 dri_config,
902
                                                 shared,
903
                                                 num_attribs / 2,
904
                                                 ctx_attribs,
905
                                                 & error,
906
                                                 dri2_ctx);
907
	 dri2_create_context_attribs_error(error);
908
      } else {
909
	 dri2_ctx->dri_context =
910
	    dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
911
						   api,
912
						   dri_config,
913
                                                   shared,
914
						   dri2_ctx);
915
      }
916
   } else {
917
      assert(dri2_dpy->swrast);
918
      dri2_ctx->dri_context =
919
         dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen,
920
                                                  api,
921
                                                  dri_config,
922
                                                  shared,
923
                                                  dri2_ctx);
924
   }
925
 
926
   if (!dri2_ctx->dri_context)
927
      goto cleanup;
928
 
929
   return &dri2_ctx->base;
930
 
931
 cleanup:
932
   free(dri2_ctx);
933
   return NULL;
934
}
935
 
936
/**
937
 * Called via eglDestroyContext(), drv->API.DestroyContext().
938
 */
939
static EGLBoolean
940
dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
941
{
942
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
943
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
944
 
945
   if (_eglPutContext(ctx)) {
946
      dri2_dpy->core->destroyContext(dri2_ctx->dri_context);
947
      free(dri2_ctx);
948
   }
949
 
950
   return EGL_TRUE;
951
}
952
 
953
/**
954
 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
955
 */
956
static EGLBoolean
957
dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
958
		  _EGLSurface *rsurf, _EGLContext *ctx)
959
{
960
   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
961
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
962
   struct dri2_egl_surface *dri2_dsurf = dri2_egl_surface(dsurf);
963
   struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf);
964
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
965
   _EGLContext *old_ctx;
966
   _EGLSurface *old_dsurf, *old_rsurf;
967
   __DRIdrawable *ddraw, *rdraw;
968
   __DRIcontext *cctx;
969
 
970
   /* make new bindings */
971
   if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
972
      return EGL_FALSE;
973
 
974
   /* flush before context switch */
975
   if (old_ctx && dri2_drv->glFlush)
976
      dri2_drv->glFlush();
977
 
978
   ddraw = (dri2_dsurf) ? dri2_dsurf->dri_drawable : NULL;
979
   rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL;
980
   cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL;
981
 
982
   if (old_ctx) {
983
      __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context;
984
      dri2_dpy->core->unbindContext(old_cctx);
985
   }
986
 
987
   if ((cctx == NULL && ddraw == NULL && rdraw == NULL) ||
988
       dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
989
      if (old_dsurf)
990
         drv->API.DestroySurface(drv, disp, old_dsurf);
991
      if (old_rsurf)
992
         drv->API.DestroySurface(drv, disp, old_rsurf);
993
      if (old_ctx)
994
         drv->API.DestroyContext(drv, disp, old_ctx);
995
 
996
      return EGL_TRUE;
997
   } else {
998
      /* undo the previous _eglBindContext */
999
      _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf);
1000
      assert(&dri2_ctx->base == ctx &&
1001
             &dri2_dsurf->base == dsurf &&
1002
             &dri2_rsurf->base == rsurf);
1003
 
1004
      _eglPutSurface(dsurf);
1005
      _eglPutSurface(rsurf);
1006
      _eglPutContext(ctx);
1007
 
1008
      _eglPutSurface(old_dsurf);
1009
      _eglPutSurface(old_rsurf);
1010
      _eglPutContext(old_ctx);
1011
 
1012
      return EGL_FALSE;
1013
   }
1014
}
1015
 
1016
/*
1017
 * Called from eglGetProcAddress() via drv->API.GetProcAddress().
1018
 */
1019
static _EGLProc
1020
dri2_get_proc_address(_EGLDriver *drv, const char *procname)
1021
{
1022
   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
1023
 
1024
   return dri2_drv->get_proc_address(procname);
1025
}
1026
 
1027
static EGLBoolean
1028
dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
1029
{
1030
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1031
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(ctx->DrawSurface);
1032
 
1033
   (void) drv;
1034
 
1035
   /* FIXME: If EGL allows frontbuffer rendering for window surfaces,
1036
    * we need to copy fake to real here.*/
1037
 
1038
   if (dri2_dpy->flush != NULL)
1039
      dri2_dpy->flush->flush(dri2_surf->dri_drawable);
1040
 
1041
   return EGL_TRUE;
1042
}
1043
 
1044
static EGLBoolean
1045
dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine)
1046
{
1047
   (void) drv;
1048
   (void) disp;
1049
 
1050
   if (engine != EGL_CORE_NATIVE_ENGINE)
1051
      return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
1052
   /* glXWaitX(); */
1053
 
1054
   return EGL_TRUE;
1055
}
1056
 
1057
static EGLBoolean
1058
dri2_bind_tex_image(_EGLDriver *drv,
1059
		    _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
1060
{
1061
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1062
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1063
   struct dri2_egl_context *dri2_ctx;
1064
   _EGLContext *ctx;
1065
   GLint format, target;
1066
 
1067
   ctx = _eglGetCurrentContext();
1068
   dri2_ctx = dri2_egl_context(ctx);
1069
 
1070
   if (!_eglBindTexImage(drv, disp, surf, buffer))
1071
      return EGL_FALSE;
1072
 
1073
   switch (dri2_surf->base.TextureFormat) {
1074
   case EGL_TEXTURE_RGB:
1075
      format = __DRI_TEXTURE_FORMAT_RGB;
1076
      break;
1077
   case EGL_TEXTURE_RGBA:
1078
      format = __DRI_TEXTURE_FORMAT_RGBA;
1079
      break;
1080
   default:
1081
      assert(0);
1082
   }
1083
 
1084
   switch (dri2_surf->base.TextureTarget) {
1085
   case EGL_TEXTURE_2D:
1086
      target = GL_TEXTURE_2D;
1087
      break;
1088
   default:
1089
      assert(0);
1090
   }
1091
 
1092
   (*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context,
1093
					  target, format,
1094
					  dri2_surf->dri_drawable);
1095
 
1096
   return EGL_TRUE;
1097
}
1098
 
1099
static EGLBoolean
1100
dri2_release_tex_image(_EGLDriver *drv,
1101
		       _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
1102
{
1103
#if __DRI_TEX_BUFFER_VERSION >= 3
1104
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1105
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1106
   struct dri2_egl_context *dri2_ctx;
1107
   _EGLContext *ctx;
1108
   GLint  target;
1109
 
1110
   ctx = _eglGetCurrentContext();
1111
   dri2_ctx = dri2_egl_context(ctx);
1112
 
1113
   if (!_eglReleaseTexImage(drv, disp, surf, buffer))
1114
      return EGL_FALSE;
1115
 
1116
   switch (dri2_surf->base.TextureTarget) {
1117
   case EGL_TEXTURE_2D:
1118
      target = GL_TEXTURE_2D;
1119
      break;
1120
   default:
1121
      assert(0);
1122
   }
1123
   if (dri2_dpy->tex_buffer->releaseTexBuffer!=NULL)
1124
    (*dri2_dpy->tex_buffer->releaseTexBuffer)(dri2_ctx->dri_context,
1125
                                             target,
1126
                                             dri2_surf->dri_drawable);
1127
#endif
1128
 
1129
   return EGL_TRUE;
1130
}
1131
 
1132
static _EGLImage *
1133
dri2_create_image(_EGLDisplay *disp, __DRIimage *dri_image)
1134
{
1135
   struct dri2_egl_image *dri2_img;
1136
 
1137
   if (dri_image == NULL) {
1138
      _eglError(EGL_BAD_ALLOC, "dri2_create_image");
1139
      return NULL;
1140
   }
1141
 
1142
   dri2_img = malloc(sizeof *dri2_img);
1143
   if (!dri2_img) {
1144
      _eglError(EGL_BAD_ALLOC, "dri2_create_image");
1145
      return NULL;
1146
   }
1147
 
1148
   if (!_eglInitImage(&dri2_img->base, disp)) {
1149
      free(dri2_img);
1150
      return NULL;
1151
   }
1152
 
1153
   dri2_img->dri_image = dri_image;
1154
 
1155
   return &dri2_img->base;
1156
}
1157
 
1158
static _EGLImage *
1159
dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
1160
				   EGLClientBuffer buffer,
1161
				   const EGLint *attr_list)
1162
{
1163
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1164
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1165
   GLuint renderbuffer = (GLuint) (uintptr_t) buffer;
1166
   __DRIimage *dri_image;
1167
 
1168
   if (renderbuffer == 0) {
1169
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
1170
      return EGL_NO_IMAGE_KHR;
1171
   }
1172
 
1173
   dri_image =
1174
      dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context,
1175
                                                   renderbuffer, NULL);
1176
 
1177
   return dri2_create_image(disp, dri_image);
1178
}
1179
 
1180
static _EGLImage *
1181
dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
1182
				  EGLClientBuffer buffer, const EGLint *attr_list)
1183
{
1184
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1185
   EGLint format, name, pitch, err;
1186
   _EGLImageAttribs attrs;
1187
   __DRIimage *dri_image;
1188
 
1189
   name = (EGLint) (uintptr_t) buffer;
1190
 
1191
   err = _eglParseImageAttribList(&attrs, disp, attr_list);
1192
   if (err != EGL_SUCCESS)
1193
      return NULL;
1194
 
1195
   if (attrs.Width <= 0 || attrs.Height <= 0 ||
1196
       attrs.DRMBufferStrideMESA <= 0) {
1197
      _eglError(EGL_BAD_PARAMETER,
1198
		"bad width, height or stride");
1199
      return NULL;
1200
   }
1201
 
1202
   switch (attrs.DRMBufferFormatMESA) {
1203
   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
1204
      format = __DRI_IMAGE_FORMAT_ARGB8888;
1205
      pitch = attrs.DRMBufferStrideMESA;
1206
      break;
4525 Serge 1207
   case EGL_DRM_BUFFER_FORMAT_R8_MESA:
1208
      format = __DRI_IMAGE_FORMAT_R8;
1209
      pitch = attrs.DRMBufferStrideMESA;
1210
      break;
1211
 
4358 Serge 1212
   default:
1213
      _eglError(EGL_BAD_PARAMETER,
1214
		"dri2_create_image_khr: unsupported pixmap depth");
1215
      return NULL;
1216
   }
1217
 
1218
   dri_image =
1219
      dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
1220
					   attrs.Width,
1221
					   attrs.Height,
1222
					   format,
1223
					   name,
1224
					   pitch,
1225
					   NULL);
1226
 
1227
   return dri2_create_image(disp, dri_image);
1228
}
1229
 
1230
#ifdef HAVE_WAYLAND_PLATFORM
1231
 
1232
/* This structure describes how a wl_buffer maps to one or more
1233
 * __DRIimages.  A wl_drm_buffer stores the wl_drm format code and the
1234
 * offsets and strides of the planes in the buffer.  This table maps a
1235
 * wl_drm format code to a description of the planes in the buffer
1236
 * that lets us create a __DRIimage for each of the planes. */
1237
 
1238
static const struct wl_drm_components_descriptor {
1239
   uint32_t dri_components;
1240
   EGLint components;
1241
   int nplanes;
1242
} wl_drm_components[] = {
1243
   { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 },
1244
   { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 },
1245
   { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 },
1246
   { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 },
1247
   { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 },
1248
};
1249
 
1250
static _EGLImage *
1251
dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
1252
				    EGLClientBuffer _buffer,
1253
				    const EGLint *attr_list)
1254
{
1255
   struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) _buffer;
1256
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1257
   const struct wl_drm_components_descriptor *f;
1258
   __DRIimage *dri_image;
1259
   _EGLImageAttribs attrs;
1260
   EGLint err;
1261
   int32_t plane;
1262
 
4401 Serge 1263
   if (!wayland_buffer_is_drm(dri2_dpy->wl_server_drm, &buffer->buffer))
4358 Serge 1264
       return NULL;
1265
 
1266
   err = _eglParseImageAttribList(&attrs, disp, attr_list);
1267
   plane = attrs.PlaneWL;
1268
   if (err != EGL_SUCCESS) {
1269
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
1270
      return NULL;
1271
   }
1272
 
1273
   f = buffer->driver_format;
1274
   if (plane < 0 || plane >= f->nplanes) {
1275
      _eglError(EGL_BAD_PARAMETER,
1276
                "dri2_create_image_wayland_wl_buffer (plane out of bounds)");
1277
      return NULL;
1278
   }
1279
 
1280
   dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL);
1281
 
1282
   if (dri_image == NULL) {
1283
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
1284
      return NULL;
1285
   }
1286
 
1287
   return dri2_create_image(disp, dri_image);
1288
}
1289
#endif
1290
 
1291
/**
1292
 * Set the error code after a call to
1293
 * dri2_egl_image::dri_image::createImageFromTexture.
1294
 */
1295
static void
1296
dri2_create_image_khr_texture_error(int dri_error)
1297
{
1298
   EGLint egl_error;
1299
 
1300
   switch (dri_error) {
1301
   case __DRI_IMAGE_ERROR_SUCCESS:
1302
      return;
1303
 
1304
   case __DRI_IMAGE_ERROR_BAD_ALLOC:
1305
      egl_error = EGL_BAD_ALLOC;
1306
      break;
1307
 
1308
   case __DRI_IMAGE_ERROR_BAD_MATCH:
1309
      egl_error = EGL_BAD_MATCH;
1310
      break;
1311
 
1312
   case __DRI_IMAGE_ERROR_BAD_PARAMETER:
1313
      egl_error = EGL_BAD_PARAMETER;
1314
      break;
1315
 
1316
   default:
1317
      assert(0);
1318
      egl_error = EGL_BAD_MATCH;
1319
      break;
1320
   }
1321
 
1322
   _eglError(egl_error, "dri2_create_image_khr_texture");
1323
}
1324
 
1325
static _EGLImage *
1326
dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
1327
				   EGLenum target,
1328
				   EGLClientBuffer buffer,
1329
				   const EGLint *attr_list)
1330
{
1331
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1332
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1333
   struct dri2_egl_image *dri2_img;
1334
   GLuint texture = (GLuint) (uintptr_t) buffer;
1335
   _EGLImageAttribs attrs;
1336
   GLuint depth;
1337
   GLenum gl_target;
1338
   unsigned error;
1339
 
1340
   if (texture == 0) {
1341
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
1342
      return EGL_NO_IMAGE_KHR;
1343
   }
1344
 
1345
   if (_eglParseImageAttribList(&attrs, disp, attr_list) != EGL_SUCCESS)
1346
      return EGL_NO_IMAGE_KHR;
1347
 
1348
   switch (target) {
1349
   case EGL_GL_TEXTURE_2D_KHR:
1350
      depth = 0;
1351
      gl_target = GL_TEXTURE_2D;
1352
      break;
1353
   case EGL_GL_TEXTURE_3D_KHR:
1354
      depth = attrs.GLTextureZOffset;
1355
      gl_target = GL_TEXTURE_3D;
1356
      break;
1357
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
1358
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
1359
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
1360
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
1361
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
1362
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
1363
      depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
1364
      gl_target = GL_TEXTURE_CUBE_MAP;
1365
      break;
1366
   default:
1367
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
1368
      return EGL_NO_IMAGE_KHR;
1369
   }
1370
 
1371
   dri2_img = malloc(sizeof *dri2_img);
1372
   if (!dri2_img) {
1373
      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
1374
      return EGL_NO_IMAGE_KHR;
1375
   }
1376
 
1377
   if (!_eglInitImage(&dri2_img->base, disp)) {
1378
      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
1379
      free(dri2_img);
1380
      return EGL_NO_IMAGE_KHR;
1381
   }
1382
 
1383
   dri2_img->dri_image =
1384
      dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context,
1385
                                              gl_target,
1386
                                              texture,
1387
                                              depth,
1388
                                              attrs.GLTextureLevel,
1389
                                              &error,
1390
                                              dri2_img);
1391
   dri2_create_image_khr_texture_error(error);
1392
 
1393
   if (!dri2_img->dri_image) {
1394
      free(dri2_img);
1395
      return EGL_NO_IMAGE_KHR;
1396
   }
1397
   return &dri2_img->base;
1398
}
1399
 
1400
_EGLImage *
1401
dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
1402
		      _EGLContext *ctx, EGLenum target,
1403
		      EGLClientBuffer buffer, const EGLint *attr_list)
1404
{
1405
   (void) drv;
1406
 
1407
   switch (target) {
1408
   case EGL_GL_TEXTURE_2D_KHR:
1409
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
1410
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
1411
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
1412
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
1413
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
1414
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
1415
      return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
1416
   case EGL_GL_RENDERBUFFER_KHR:
1417
      return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
1418
   case EGL_DRM_BUFFER_MESA:
1419
      return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
1420
#ifdef HAVE_WAYLAND_PLATFORM
1421
   case EGL_WAYLAND_BUFFER_WL:
1422
      return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
1423
#endif
1424
   default:
1425
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
1426
      return EGL_NO_IMAGE_KHR;
1427
   }
1428
}
1429
 
1430
static EGLBoolean
1431
dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image)
1432
{
1433
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1434
   struct dri2_egl_image *dri2_img = dri2_egl_image(image);
1435
 
1436
   (void) drv;
1437
 
1438
   dri2_dpy->image->destroyImage(dri2_img->dri_image);
1439
   free(dri2_img);
1440
 
1441
   return EGL_TRUE;
1442
}
1443
 
1444
static _EGLImage *
1445
dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp,
1446
			   const EGLint *attr_list)
1447
{
1448
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1449
   struct dri2_egl_image *dri2_img;
1450
   _EGLImageAttribs attrs;
1451
   unsigned int dri_use, valid_mask;
1452
   int format;
1453
   EGLint err = EGL_SUCCESS;
1454
 
1455
   (void) drv;
1456
 
1457
   dri2_img = malloc(sizeof *dri2_img);
1458
   if (!dri2_img) {
1459
      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
1460
      return EGL_NO_IMAGE_KHR;
1461
   }
1462
 
1463
   if (!attr_list) {
1464
      err = EGL_BAD_PARAMETER;
1465
      goto cleanup_img;
1466
   }
1467
 
1468
   if (!_eglInitImage(&dri2_img->base, disp)) {
1469
      err = EGL_BAD_PARAMETER;
1470
      goto cleanup_img;
1471
   }
1472
 
1473
   err = _eglParseImageAttribList(&attrs, disp, attr_list);
1474
   if (err != EGL_SUCCESS)
1475
      goto cleanup_img;
1476
 
1477
   if (attrs.Width <= 0 || attrs.Height <= 0) {
1478
      _eglLog(_EGL_WARNING, "bad width or height (%dx%d)",
1479
            attrs.Width, attrs.Height);
1480
      goto cleanup_img;
1481
   }
1482
 
1483
   switch (attrs.DRMBufferFormatMESA) {
1484
   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
1485
      format = __DRI_IMAGE_FORMAT_ARGB8888;
1486
      break;
1487
   default:
1488
      _eglLog(_EGL_WARNING, "bad image format value 0x%04x",
1489
            attrs.DRMBufferFormatMESA);
1490
      goto cleanup_img;
1491
   }
1492
 
1493
   valid_mask =
1494
      EGL_DRM_BUFFER_USE_SCANOUT_MESA |
1495
      EGL_DRM_BUFFER_USE_SHARE_MESA |
1496
      EGL_DRM_BUFFER_USE_CURSOR_MESA;
1497
   if (attrs.DRMBufferUseMESA & ~valid_mask) {
1498
      _eglLog(_EGL_WARNING, "bad image use bit 0x%04x",
1499
            attrs.DRMBufferUseMESA & ~valid_mask);
1500
      goto cleanup_img;
1501
   }
1502
 
1503
   dri_use = 0;
1504
   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA)
1505
      dri_use |= __DRI_IMAGE_USE_SHARE;
1506
   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
1507
      dri_use |= __DRI_IMAGE_USE_SCANOUT;
1508
   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA)
1509
      dri_use |= __DRI_IMAGE_USE_CURSOR;
1510
 
1511
   dri2_img->dri_image =
1512
      dri2_dpy->image->createImage(dri2_dpy->dri_screen,
1513
				   attrs.Width, attrs.Height,
1514
                                   format, dri_use, dri2_img);
1515
   if (dri2_img->dri_image == NULL) {
1516
      err = EGL_BAD_ALLOC;
1517
      goto cleanup_img;
1518
   }
1519
 
1520
   return &dri2_img->base;
1521
 
1522
 cleanup_img:
1523
   free(dri2_img);
1524
   _eglError(err, "dri2_create_drm_image_mesa");
1525
 
1526
   return EGL_NO_IMAGE_KHR;
1527
}
1528
 
1529
static EGLBoolean
1530
dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
1531
			  EGLint *name, EGLint *handle, EGLint *stride)
1532
{
1533
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1534
   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
1535
 
1536
   (void) drv;
1537
 
1538
   if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
1539
					    __DRI_IMAGE_ATTRIB_NAME, name)) {
1540
      _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
1541
      return EGL_FALSE;
1542
   }
1543
 
1544
   if (handle)
1545
      dri2_dpy->image->queryImage(dri2_img->dri_image,
1546
				  __DRI_IMAGE_ATTRIB_HANDLE, handle);
1547
 
1548
   if (stride)
1549
      dri2_dpy->image->queryImage(dri2_img->dri_image,
1550
				  __DRI_IMAGE_ATTRIB_STRIDE, stride);
1551
 
1552
   return EGL_TRUE;
1553
}
1554
 
1555
#ifdef HAVE_WAYLAND_PLATFORM
1556
 
1557
static void
1558
dri2_wl_reference_buffer(void *user_data, uint32_t name, int fd,
1559
                         struct wl_drm_buffer *buffer)
1560
{
1561
   _EGLDisplay *disp = user_data;
1562
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1563
   __DRIimage *img;
1564
   int i, dri_components = 0;
1565
 
1566
   if (fd == -1)
1567
      img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen,
1568
                                                  buffer->buffer.width,
1569
                                                  buffer->buffer.height,
1570
                                                  buffer->format,
1571
                                                  (int*)&name, 1,
1572
                                                  buffer->stride,
1573
                                                  buffer->offset,
1574
                                                  NULL);
1575
   else
1576
      img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
1577
                                                buffer->buffer.width,
1578
                                                buffer->buffer.height,
1579
                                                buffer->format,
1580
                                                &fd, 1,
1581
                                                buffer->stride,
1582
                                                buffer->offset,
1583
                                                NULL);
1584
 
1585
   if (img == NULL)
1586
      return;
1587
 
1588
   dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components);
1589
 
1590
   buffer->driver_format = NULL;
1591
   for (i = 0; i < ARRAY_SIZE(wl_drm_components); i++)
1592
      if (wl_drm_components[i].dri_components == dri_components)
1593
         buffer->driver_format = &wl_drm_components[i];
1594
 
1595
   if (buffer->driver_format == NULL)
1596
      dri2_dpy->image->destroyImage(img);
1597
   else
1598
      buffer->driver_buffer = img;
1599
}
1600
 
1601
static void
1602
dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer)
1603
{
1604
   _EGLDisplay *disp = user_data;
1605
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1606
 
1607
   dri2_dpy->image->destroyImage(buffer->driver_buffer);
1608
}
1609
 
1610
static struct wayland_drm_callbacks wl_drm_callbacks = {
1611
	.authenticate = NULL,
1612
	.reference_buffer = dri2_wl_reference_buffer,
1613
	.release_buffer = dri2_wl_release_buffer
1614
};
1615
 
1616
static EGLBoolean
1617
dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
1618
			     struct wl_display *wl_dpy)
1619
{
1620
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1621
   int ret, flags = 0;
1622
   uint64_t cap;
1623
 
1624
   (void) drv;
1625
 
1626
   if (dri2_dpy->wl_server_drm)
1627
	   return EGL_FALSE;
1628
 
1629
   wl_drm_callbacks.authenticate =
1630
      (int(*)(void *, uint32_t)) dri2_dpy->authenticate;
1631
 
1632
   ret = drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap);
1633
   if (ret == 0 && cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT) &&
1634
       dri2_dpy->image->base.version >= 7 &&
1635
       dri2_dpy->image->createImageFromFds != NULL)
1636
      flags |= WAYLAND_DRM_PRIME;
1637
 
1638
   dri2_dpy->wl_server_drm =
1639
	   wayland_drm_init(wl_dpy, dri2_dpy->device_name,
1640
                            &wl_drm_callbacks, disp, flags);
1641
 
1642
   if (!dri2_dpy->wl_server_drm)
1643
	   return EGL_FALSE;
1644
 
1645
   return EGL_TRUE;
1646
}
1647
 
1648
static EGLBoolean
1649
dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
1650
			       struct wl_display *wl_dpy)
1651
{
1652
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1653
 
1654
   (void) drv;
1655
 
1656
   if (!dri2_dpy->wl_server_drm)
1657
	   return EGL_FALSE;
1658
 
1659
   wayland_drm_uninit(dri2_dpy->wl_server_drm);
1660
   dri2_dpy->wl_server_drm = NULL;
1661
 
1662
   return EGL_TRUE;
1663
}
1664
 
1665
static EGLBoolean
1666
dri2_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *disp,
1667
                             struct wl_buffer *_buffer,
1668
                             EGLint attribute, EGLint *value)
1669
{
1670
   struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) _buffer;
4401 Serge 1671
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
4358 Serge 1672
   const struct wl_drm_components_descriptor *format;
1673
 
4401 Serge 1674
   if (!wayland_buffer_is_drm(dri2_dpy->wl_server_drm, &buffer->buffer))
4358 Serge 1675
      return EGL_FALSE;
1676
 
1677
   format = buffer->driver_format;
1678
   switch (attribute) {
1679
   case EGL_TEXTURE_FORMAT:
1680
      *value = format->components;
1681
      return EGL_TRUE;
1682
   case EGL_WIDTH:
1683
      *value = buffer->buffer.width;
1684
      return EGL_TRUE;
1685
   case EGL_HEIGHT:
1686
      *value = buffer->buffer.height;
1687
      return EGL_TRUE;
1688
   }
1689
 
1690
   return EGL_FALSE;
1691
}
1692
#endif
1693
 
1694
static void
1695
dri2_unload(_EGLDriver *drv)
1696
{
1697
   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
1698
 
1699
//   if (dri2_drv->handle)
1700
//      dlclose(dri2_drv->handle);
1701
   free(dri2_drv);
1702
}
1703
 
1704
static EGLBoolean
1705
dri2_load(_EGLDriver *drv)
1706
{
1707
   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
1708
   const char *libname = "libGL.dll";
1709
 
1710
   lib_handle handle;
1711
 
1712
   handle = load_library(libname);
1713
   if (handle) {
1714
      dri2_drv->get_proc_address = (_EGLProc (*)(const char *))
1715
         get_proc_address(handle, "_glapi_get_proc_address");
1716
      if (!dri2_drv->get_proc_address) {
1717
         /* no need to keep a reference */
1718
         handle = 0;
1719
      }
1720
   }
1721
 
1722
   /* if glapi is not available, loading DRI drivers will fail */
1723
   if (!dri2_drv->get_proc_address) {
1724
      _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address");
1725
      return EGL_FALSE;
1726
   }
1727
 
1728
   dri2_drv->glFlush = (void (*)(void))
1729
      dri2_drv->get_proc_address("glFlush");
1730
 
1731
   dri2_drv->handle = (void*)handle;
1732
 
1733
   return EGL_TRUE;
1734
}
1735
 
1736
/**
1737
 * This is the main entrypoint into the driver, called by libEGL.
1738
 * Create a new _EGLDriver object and init its dispatch table.
1739
 */
1740
_EGLDriver *
1741
_eglBuiltInDriverDRI2(const char *args)
1742
{
1743
   struct dri2_egl_driver *dri2_drv;
1744
 
1745
   (void) args;
1746
 
1747
   dri2_drv = calloc(1, sizeof *dri2_drv);
1748
   if (!dri2_drv)
1749
      return NULL;
1750
 
1751
   if (!dri2_load(&dri2_drv->base)) {
1752
      free(dri2_drv);
1753
      return NULL;
1754
   }
1755
 
1756
   _eglInitDriverFallbacks(&dri2_drv->base);
1757
   dri2_drv->base.API.Initialize = dri2_initialize;
1758
   dri2_drv->base.API.Terminate = dri2_terminate;
1759
   dri2_drv->base.API.CreateContext = dri2_create_context;
1760
   dri2_drv->base.API.DestroyContext = dri2_destroy_context;
1761
   dri2_drv->base.API.MakeCurrent = dri2_make_current;
1762
   dri2_drv->base.API.GetProcAddress = dri2_get_proc_address;
1763
   dri2_drv->base.API.WaitClient = dri2_wait_client;
1764
   dri2_drv->base.API.WaitNative = dri2_wait_native;
1765
   dri2_drv->base.API.BindTexImage = dri2_bind_tex_image;
1766
   dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image;
1767
   dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr;
1768
   dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr;
1769
   dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
1770
   dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
1771
#ifdef HAVE_WAYLAND_PLATFORM
1772
   dri2_drv->base.API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl;
1773
   dri2_drv->base.API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl;
1774
   dri2_drv->base.API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl;
1775
#endif
1776
 
1777
   dri2_drv->base.Name = "DRI2";
1778
   dri2_drv->base.Unload = dri2_unload;
1779
 
1780
   return &dri2_drv->base;
1781
}