Subversion Repositories Kolibri OS

Rev

Rev 4358 | 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;
1207
   default:
1208
      _eglError(EGL_BAD_PARAMETER,
1209
		"dri2_create_image_khr: unsupported pixmap depth");
1210
      return NULL;
1211
   }
1212
 
1213
   dri_image =
1214
      dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
1215
					   attrs.Width,
1216
					   attrs.Height,
1217
					   format,
1218
					   name,
1219
					   pitch,
1220
					   NULL);
1221
 
1222
   return dri2_create_image(disp, dri_image);
1223
}
1224
 
1225
#ifdef HAVE_WAYLAND_PLATFORM
1226
 
1227
/* This structure describes how a wl_buffer maps to one or more
1228
 * __DRIimages.  A wl_drm_buffer stores the wl_drm format code and the
1229
 * offsets and strides of the planes in the buffer.  This table maps a
1230
 * wl_drm format code to a description of the planes in the buffer
1231
 * that lets us create a __DRIimage for each of the planes. */
1232
 
1233
static const struct wl_drm_components_descriptor {
1234
   uint32_t dri_components;
1235
   EGLint components;
1236
   int nplanes;
1237
} wl_drm_components[] = {
1238
   { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 },
1239
   { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 },
1240
   { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 },
1241
   { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 },
1242
   { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 },
1243
};
1244
 
1245
static _EGLImage *
1246
dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
1247
				    EGLClientBuffer _buffer,
1248
				    const EGLint *attr_list)
1249
{
1250
   struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) _buffer;
1251
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1252
   const struct wl_drm_components_descriptor *f;
1253
   __DRIimage *dri_image;
1254
   _EGLImageAttribs attrs;
1255
   EGLint err;
1256
   int32_t plane;
1257
 
4401 Serge 1258
   if (!wayland_buffer_is_drm(dri2_dpy->wl_server_drm, &buffer->buffer))
4358 Serge 1259
       return NULL;
1260
 
1261
   err = _eglParseImageAttribList(&attrs, disp, attr_list);
1262
   plane = attrs.PlaneWL;
1263
   if (err != EGL_SUCCESS) {
1264
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
1265
      return NULL;
1266
   }
1267
 
1268
   f = buffer->driver_format;
1269
   if (plane < 0 || plane >= f->nplanes) {
1270
      _eglError(EGL_BAD_PARAMETER,
1271
                "dri2_create_image_wayland_wl_buffer (plane out of bounds)");
1272
      return NULL;
1273
   }
1274
 
1275
   dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL);
1276
 
1277
   if (dri_image == NULL) {
1278
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
1279
      return NULL;
1280
   }
1281
 
1282
   return dri2_create_image(disp, dri_image);
1283
}
1284
#endif
1285
 
1286
/**
1287
 * Set the error code after a call to
1288
 * dri2_egl_image::dri_image::createImageFromTexture.
1289
 */
1290
static void
1291
dri2_create_image_khr_texture_error(int dri_error)
1292
{
1293
   EGLint egl_error;
1294
 
1295
   switch (dri_error) {
1296
   case __DRI_IMAGE_ERROR_SUCCESS:
1297
      return;
1298
 
1299
   case __DRI_IMAGE_ERROR_BAD_ALLOC:
1300
      egl_error = EGL_BAD_ALLOC;
1301
      break;
1302
 
1303
   case __DRI_IMAGE_ERROR_BAD_MATCH:
1304
      egl_error = EGL_BAD_MATCH;
1305
      break;
1306
 
1307
   case __DRI_IMAGE_ERROR_BAD_PARAMETER:
1308
      egl_error = EGL_BAD_PARAMETER;
1309
      break;
1310
 
1311
   default:
1312
      assert(0);
1313
      egl_error = EGL_BAD_MATCH;
1314
      break;
1315
   }
1316
 
1317
   _eglError(egl_error, "dri2_create_image_khr_texture");
1318
}
1319
 
1320
static _EGLImage *
1321
dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
1322
				   EGLenum target,
1323
				   EGLClientBuffer buffer,
1324
				   const EGLint *attr_list)
1325
{
1326
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1327
   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1328
   struct dri2_egl_image *dri2_img;
1329
   GLuint texture = (GLuint) (uintptr_t) buffer;
1330
   _EGLImageAttribs attrs;
1331
   GLuint depth;
1332
   GLenum gl_target;
1333
   unsigned error;
1334
 
1335
   if (texture == 0) {
1336
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
1337
      return EGL_NO_IMAGE_KHR;
1338
   }
1339
 
1340
   if (_eglParseImageAttribList(&attrs, disp, attr_list) != EGL_SUCCESS)
1341
      return EGL_NO_IMAGE_KHR;
1342
 
1343
   switch (target) {
1344
   case EGL_GL_TEXTURE_2D_KHR:
1345
      depth = 0;
1346
      gl_target = GL_TEXTURE_2D;
1347
      break;
1348
   case EGL_GL_TEXTURE_3D_KHR:
1349
      depth = attrs.GLTextureZOffset;
1350
      gl_target = GL_TEXTURE_3D;
1351
      break;
1352
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
1353
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
1354
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
1355
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
1356
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
1357
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
1358
      depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
1359
      gl_target = GL_TEXTURE_CUBE_MAP;
1360
      break;
1361
   default:
1362
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
1363
      return EGL_NO_IMAGE_KHR;
1364
   }
1365
 
1366
   dri2_img = malloc(sizeof *dri2_img);
1367
   if (!dri2_img) {
1368
      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
1369
      return EGL_NO_IMAGE_KHR;
1370
   }
1371
 
1372
   if (!_eglInitImage(&dri2_img->base, disp)) {
1373
      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
1374
      free(dri2_img);
1375
      return EGL_NO_IMAGE_KHR;
1376
   }
1377
 
1378
   dri2_img->dri_image =
1379
      dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context,
1380
                                              gl_target,
1381
                                              texture,
1382
                                              depth,
1383
                                              attrs.GLTextureLevel,
1384
                                              &error,
1385
                                              dri2_img);
1386
   dri2_create_image_khr_texture_error(error);
1387
 
1388
   if (!dri2_img->dri_image) {
1389
      free(dri2_img);
1390
      return EGL_NO_IMAGE_KHR;
1391
   }
1392
   return &dri2_img->base;
1393
}
1394
 
1395
_EGLImage *
1396
dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
1397
		      _EGLContext *ctx, EGLenum target,
1398
		      EGLClientBuffer buffer, const EGLint *attr_list)
1399
{
1400
   (void) drv;
1401
 
1402
   switch (target) {
1403
   case EGL_GL_TEXTURE_2D_KHR:
1404
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
1405
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
1406
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
1407
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
1408
   case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
1409
   case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
1410
      return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
1411
   case EGL_GL_RENDERBUFFER_KHR:
1412
      return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
1413
   case EGL_DRM_BUFFER_MESA:
1414
      return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
1415
#ifdef HAVE_WAYLAND_PLATFORM
1416
   case EGL_WAYLAND_BUFFER_WL:
1417
      return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
1418
#endif
1419
   default:
1420
      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
1421
      return EGL_NO_IMAGE_KHR;
1422
   }
1423
}
1424
 
1425
static EGLBoolean
1426
dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image)
1427
{
1428
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1429
   struct dri2_egl_image *dri2_img = dri2_egl_image(image);
1430
 
1431
   (void) drv;
1432
 
1433
   dri2_dpy->image->destroyImage(dri2_img->dri_image);
1434
   free(dri2_img);
1435
 
1436
   return EGL_TRUE;
1437
}
1438
 
1439
static _EGLImage *
1440
dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp,
1441
			   const EGLint *attr_list)
1442
{
1443
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1444
   struct dri2_egl_image *dri2_img;
1445
   _EGLImageAttribs attrs;
1446
   unsigned int dri_use, valid_mask;
1447
   int format;
1448
   EGLint err = EGL_SUCCESS;
1449
 
1450
   (void) drv;
1451
 
1452
   dri2_img = malloc(sizeof *dri2_img);
1453
   if (!dri2_img) {
1454
      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
1455
      return EGL_NO_IMAGE_KHR;
1456
   }
1457
 
1458
   if (!attr_list) {
1459
      err = EGL_BAD_PARAMETER;
1460
      goto cleanup_img;
1461
   }
1462
 
1463
   if (!_eglInitImage(&dri2_img->base, disp)) {
1464
      err = EGL_BAD_PARAMETER;
1465
      goto cleanup_img;
1466
   }
1467
 
1468
   err = _eglParseImageAttribList(&attrs, disp, attr_list);
1469
   if (err != EGL_SUCCESS)
1470
      goto cleanup_img;
1471
 
1472
   if (attrs.Width <= 0 || attrs.Height <= 0) {
1473
      _eglLog(_EGL_WARNING, "bad width or height (%dx%d)",
1474
            attrs.Width, attrs.Height);
1475
      goto cleanup_img;
1476
   }
1477
 
1478
   switch (attrs.DRMBufferFormatMESA) {
1479
   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
1480
      format = __DRI_IMAGE_FORMAT_ARGB8888;
1481
      break;
1482
   default:
1483
      _eglLog(_EGL_WARNING, "bad image format value 0x%04x",
1484
            attrs.DRMBufferFormatMESA);
1485
      goto cleanup_img;
1486
   }
1487
 
1488
   valid_mask =
1489
      EGL_DRM_BUFFER_USE_SCANOUT_MESA |
1490
      EGL_DRM_BUFFER_USE_SHARE_MESA |
1491
      EGL_DRM_BUFFER_USE_CURSOR_MESA;
1492
   if (attrs.DRMBufferUseMESA & ~valid_mask) {
1493
      _eglLog(_EGL_WARNING, "bad image use bit 0x%04x",
1494
            attrs.DRMBufferUseMESA & ~valid_mask);
1495
      goto cleanup_img;
1496
   }
1497
 
1498
   dri_use = 0;
1499
   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA)
1500
      dri_use |= __DRI_IMAGE_USE_SHARE;
1501
   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
1502
      dri_use |= __DRI_IMAGE_USE_SCANOUT;
1503
   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA)
1504
      dri_use |= __DRI_IMAGE_USE_CURSOR;
1505
 
1506
   dri2_img->dri_image =
1507
      dri2_dpy->image->createImage(dri2_dpy->dri_screen,
1508
				   attrs.Width, attrs.Height,
1509
                                   format, dri_use, dri2_img);
1510
   if (dri2_img->dri_image == NULL) {
1511
      err = EGL_BAD_ALLOC;
1512
      goto cleanup_img;
1513
   }
1514
 
1515
   return &dri2_img->base;
1516
 
1517
 cleanup_img:
1518
   free(dri2_img);
1519
   _eglError(err, "dri2_create_drm_image_mesa");
1520
 
1521
   return EGL_NO_IMAGE_KHR;
1522
}
1523
 
1524
static EGLBoolean
1525
dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
1526
			  EGLint *name, EGLint *handle, EGLint *stride)
1527
{
1528
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1529
   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
1530
 
1531
   (void) drv;
1532
 
1533
   if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
1534
					    __DRI_IMAGE_ATTRIB_NAME, name)) {
1535
      _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
1536
      return EGL_FALSE;
1537
   }
1538
 
1539
   if (handle)
1540
      dri2_dpy->image->queryImage(dri2_img->dri_image,
1541
				  __DRI_IMAGE_ATTRIB_HANDLE, handle);
1542
 
1543
   if (stride)
1544
      dri2_dpy->image->queryImage(dri2_img->dri_image,
1545
				  __DRI_IMAGE_ATTRIB_STRIDE, stride);
1546
 
1547
   return EGL_TRUE;
1548
}
1549
 
1550
#ifdef HAVE_WAYLAND_PLATFORM
1551
 
1552
static void
1553
dri2_wl_reference_buffer(void *user_data, uint32_t name, int fd,
1554
                         struct wl_drm_buffer *buffer)
1555
{
1556
   _EGLDisplay *disp = user_data;
1557
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1558
   __DRIimage *img;
1559
   int i, dri_components = 0;
1560
 
1561
   if (fd == -1)
1562
      img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen,
1563
                                                  buffer->buffer.width,
1564
                                                  buffer->buffer.height,
1565
                                                  buffer->format,
1566
                                                  (int*)&name, 1,
1567
                                                  buffer->stride,
1568
                                                  buffer->offset,
1569
                                                  NULL);
1570
   else
1571
      img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
1572
                                                buffer->buffer.width,
1573
                                                buffer->buffer.height,
1574
                                                buffer->format,
1575
                                                &fd, 1,
1576
                                                buffer->stride,
1577
                                                buffer->offset,
1578
                                                NULL);
1579
 
1580
   if (img == NULL)
1581
      return;
1582
 
1583
   dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components);
1584
 
1585
   buffer->driver_format = NULL;
1586
   for (i = 0; i < ARRAY_SIZE(wl_drm_components); i++)
1587
      if (wl_drm_components[i].dri_components == dri_components)
1588
         buffer->driver_format = &wl_drm_components[i];
1589
 
1590
   if (buffer->driver_format == NULL)
1591
      dri2_dpy->image->destroyImage(img);
1592
   else
1593
      buffer->driver_buffer = img;
1594
}
1595
 
1596
static void
1597
dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer)
1598
{
1599
   _EGLDisplay *disp = user_data;
1600
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1601
 
1602
   dri2_dpy->image->destroyImage(buffer->driver_buffer);
1603
}
1604
 
1605
static struct wayland_drm_callbacks wl_drm_callbacks = {
1606
	.authenticate = NULL,
1607
	.reference_buffer = dri2_wl_reference_buffer,
1608
	.release_buffer = dri2_wl_release_buffer
1609
};
1610
 
1611
static EGLBoolean
1612
dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
1613
			     struct wl_display *wl_dpy)
1614
{
1615
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1616
   int ret, flags = 0;
1617
   uint64_t cap;
1618
 
1619
   (void) drv;
1620
 
1621
   if (dri2_dpy->wl_server_drm)
1622
	   return EGL_FALSE;
1623
 
1624
   wl_drm_callbacks.authenticate =
1625
      (int(*)(void *, uint32_t)) dri2_dpy->authenticate;
1626
 
1627
   ret = drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap);
1628
   if (ret == 0 && cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT) &&
1629
       dri2_dpy->image->base.version >= 7 &&
1630
       dri2_dpy->image->createImageFromFds != NULL)
1631
      flags |= WAYLAND_DRM_PRIME;
1632
 
1633
   dri2_dpy->wl_server_drm =
1634
	   wayland_drm_init(wl_dpy, dri2_dpy->device_name,
1635
                            &wl_drm_callbacks, disp, flags);
1636
 
1637
   if (!dri2_dpy->wl_server_drm)
1638
	   return EGL_FALSE;
1639
 
1640
   return EGL_TRUE;
1641
}
1642
 
1643
static EGLBoolean
1644
dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
1645
			       struct wl_display *wl_dpy)
1646
{
1647
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1648
 
1649
   (void) drv;
1650
 
1651
   if (!dri2_dpy->wl_server_drm)
1652
	   return EGL_FALSE;
1653
 
1654
   wayland_drm_uninit(dri2_dpy->wl_server_drm);
1655
   dri2_dpy->wl_server_drm = NULL;
1656
 
1657
   return EGL_TRUE;
1658
}
1659
 
1660
static EGLBoolean
1661
dri2_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *disp,
1662
                             struct wl_buffer *_buffer,
1663
                             EGLint attribute, EGLint *value)
1664
{
1665
   struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) _buffer;
4401 Serge 1666
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
4358 Serge 1667
   const struct wl_drm_components_descriptor *format;
1668
 
4401 Serge 1669
   if (!wayland_buffer_is_drm(dri2_dpy->wl_server_drm, &buffer->buffer))
4358 Serge 1670
      return EGL_FALSE;
1671
 
1672
   format = buffer->driver_format;
1673
   switch (attribute) {
1674
   case EGL_TEXTURE_FORMAT:
1675
      *value = format->components;
1676
      return EGL_TRUE;
1677
   case EGL_WIDTH:
1678
      *value = buffer->buffer.width;
1679
      return EGL_TRUE;
1680
   case EGL_HEIGHT:
1681
      *value = buffer->buffer.height;
1682
      return EGL_TRUE;
1683
   }
1684
 
1685
   return EGL_FALSE;
1686
}
1687
#endif
1688
 
1689
static void
1690
dri2_unload(_EGLDriver *drv)
1691
{
1692
   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
1693
 
1694
//   if (dri2_drv->handle)
1695
//      dlclose(dri2_drv->handle);
1696
   free(dri2_drv);
1697
}
1698
 
1699
static EGLBoolean
1700
dri2_load(_EGLDriver *drv)
1701
{
1702
   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
1703
   const char *libname = "libGL.dll";
1704
 
1705
   lib_handle handle;
1706
 
1707
   handle = load_library(libname);
1708
   if (handle) {
1709
      dri2_drv->get_proc_address = (_EGLProc (*)(const char *))
1710
         get_proc_address(handle, "_glapi_get_proc_address");
1711
      if (!dri2_drv->get_proc_address) {
1712
         /* no need to keep a reference */
1713
         handle = 0;
1714
      }
1715
   }
1716
 
1717
   /* if glapi is not available, loading DRI drivers will fail */
1718
   if (!dri2_drv->get_proc_address) {
1719
      _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address");
1720
      return EGL_FALSE;
1721
   }
1722
 
1723
   dri2_drv->glFlush = (void (*)(void))
1724
      dri2_drv->get_proc_address("glFlush");
1725
 
1726
   dri2_drv->handle = (void*)handle;
1727
 
1728
   return EGL_TRUE;
1729
}
1730
 
1731
/**
1732
 * This is the main entrypoint into the driver, called by libEGL.
1733
 * Create a new _EGLDriver object and init its dispatch table.
1734
 */
1735
_EGLDriver *
1736
_eglBuiltInDriverDRI2(const char *args)
1737
{
1738
   struct dri2_egl_driver *dri2_drv;
1739
 
1740
   (void) args;
1741
 
1742
   dri2_drv = calloc(1, sizeof *dri2_drv);
1743
   if (!dri2_drv)
1744
      return NULL;
1745
 
1746
   if (!dri2_load(&dri2_drv->base)) {
1747
      free(dri2_drv);
1748
      return NULL;
1749
   }
1750
 
1751
   _eglInitDriverFallbacks(&dri2_drv->base);
1752
   dri2_drv->base.API.Initialize = dri2_initialize;
1753
   dri2_drv->base.API.Terminate = dri2_terminate;
1754
   dri2_drv->base.API.CreateContext = dri2_create_context;
1755
   dri2_drv->base.API.DestroyContext = dri2_destroy_context;
1756
   dri2_drv->base.API.MakeCurrent = dri2_make_current;
1757
   dri2_drv->base.API.GetProcAddress = dri2_get_proc_address;
1758
   dri2_drv->base.API.WaitClient = dri2_wait_client;
1759
   dri2_drv->base.API.WaitNative = dri2_wait_native;
1760
   dri2_drv->base.API.BindTexImage = dri2_bind_tex_image;
1761
   dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image;
1762
   dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr;
1763
   dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr;
1764
   dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
1765
   dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
1766
#ifdef HAVE_WAYLAND_PLATFORM
1767
   dri2_drv->base.API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl;
1768
   dri2_drv->base.API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl;
1769
   dri2_drv->base.API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl;
1770
#endif
1771
 
1772
   dri2_drv->base.Name = "DRI2";
1773
   dri2_drv->base.Unload = dri2_unload;
1774
 
1775
   return &dri2_drv->base;
1776
}