494d6dd8b6d6b679a62cbc6c70434c547b7ded74
[mesa.git] / src / gallium / state_trackers / egl / common / egl_g3d.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.8
4 *
5 * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25
26 #include "egldriver.h"
27 #include "eglcurrent.h"
28 #include "egllog.h"
29
30 #include "pipe/p_screen.h"
31 #include "util/u_memory.h"
32 #include "util/u_format.h"
33 #include "util/u_string.h"
34
35 #include "egl_g3d.h"
36 #include "egl_g3d_api.h"
37 #include "egl_g3d_st.h"
38 #include "egl_g3d_loader.h"
39 #include "native.h"
40
41 /**
42 * Get the native platform.
43 */
44 static const struct native_platform *
45 egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat)
46 {
47 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
48
49 if (!gdrv->platforms[plat]) {
50 const char *plat_name = NULL;
51 const struct native_platform *nplat = NULL;
52
53 switch (plat) {
54 case _EGL_PLATFORM_WINDOWS:
55 plat_name = "Windows";
56 #ifdef HAVE_GDI_BACKEND
57 nplat = native_get_gdi_platform();
58 #endif
59 break;
60 case _EGL_PLATFORM_X11:
61 plat_name = "X11";
62 #ifdef HAVE_X11_BACKEND
63 nplat = native_get_x11_platform();
64 #endif
65 break;
66 case _EGL_PLATFORM_DRM:
67 plat_name = "DRM";
68 #ifdef HAVE_KMS_BACKEND
69 nplat = native_get_kms_platform();
70 #endif
71 break;
72 case _EGL_PLATFORM_FBDEV:
73 plat_name = "FBDEV";
74 #ifdef HAVE_FBDEV_BACKEND
75 nplat = native_get_fbdev_platform();
76 #endif
77 break;
78 default:
79 break;
80 }
81
82 if (!nplat)
83 _eglLog(_EGL_WARNING, "unsupported platform %s", plat_name);
84
85 gdrv->platforms[plat] = nplat;
86 }
87
88 return gdrv->platforms[plat];
89 }
90
91 /**
92 * Get the probe result of the display.
93 *
94 * Note that this function may be called before the display is initialized.
95 */
96 static enum native_probe_result
97 egl_g3d_get_probe_result(_EGLDriver *drv, _EGLDisplay *dpy)
98 {
99 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
100 struct native_probe *nprobe;
101 const struct native_platform *nplat;
102
103 nplat = egl_g3d_get_platform(drv, dpy->Platform);
104 if (!nplat || !nplat->create_probe)
105 return NATIVE_PROBE_UNKNOWN;
106
107 nprobe = (struct native_probe *) _eglGetProbeCache(gdrv->probe_key);
108 if (!nprobe || nprobe->display != dpy->PlatformDisplay) {
109 if (nprobe)
110 nprobe->destroy(nprobe);
111 nprobe = nplat->create_probe(dpy->PlatformDisplay);
112 _eglSetProbeCache(gdrv->probe_key, (void *) nprobe);
113 }
114
115 return nplat->get_probe_result(nprobe);
116 }
117
118 /**
119 * Destroy the probe object of the display. The display may be NULL.
120 *
121 * Note that this function may be called before the display is initialized.
122 */
123 static void
124 egl_g3d_destroy_probe(_EGLDriver *drv, _EGLDisplay *dpy)
125 {
126 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
127 struct native_probe *nprobe;
128
129 nprobe = (struct native_probe *) _eglGetProbeCache(gdrv->probe_key);
130 if (nprobe && (!dpy || nprobe->display == dpy->PlatformDisplay)) {
131 nprobe->destroy(nprobe);
132 _eglSetProbeCache(gdrv->probe_key, NULL);
133 }
134 }
135
136 #ifdef EGL_MESA_screen_surface
137
138 static void
139 egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
140 {
141 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
142 const struct native_connector **native_connectors;
143 EGLint num_connectors, i;
144
145 native_connectors =
146 gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL);
147 if (!num_connectors) {
148 if (native_connectors)
149 FREE(native_connectors);
150 return;
151 }
152
153 for (i = 0; i < num_connectors; i++) {
154 const struct native_connector *nconn = native_connectors[i];
155 struct egl_g3d_screen *gscr;
156 const struct native_mode **native_modes;
157 EGLint num_modes, j;
158
159 /* TODO support for hotplug */
160 native_modes =
161 gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes);
162 if (!num_modes) {
163 if (native_modes)
164 FREE(native_modes);
165 continue;
166 }
167
168 gscr = CALLOC_STRUCT(egl_g3d_screen);
169 if (!gscr) {
170 FREE(native_modes);
171 continue;
172 }
173
174 _eglInitScreen(&gscr->base);
175
176 for (j = 0; j < num_modes; j++) {
177 const struct native_mode *nmode = native_modes[j];
178 _EGLMode *mode;
179
180 mode = _eglAddNewMode(&gscr->base, nmode->width, nmode->height,
181 nmode->refresh_rate, nmode->desc);
182 if (!mode)
183 break;
184 /* gscr->native_modes and gscr->base.Modes should be consistent */
185 assert(mode == &gscr->base.Modes[j]);
186 }
187
188 gscr->native = nconn;
189 gscr->native_modes = native_modes;
190
191 _eglAddScreen(dpy, &gscr->base);
192 }
193
194 FREE(native_connectors);
195 }
196
197 #endif /* EGL_MESA_screen_surface */
198
199 /**
200 * Initialize and validate the EGL config attributes.
201 */
202 static EGLBoolean
203 init_config_attributes(_EGLConfig *conf, const struct native_config *nconf,
204 EGLint api_mask, enum pipe_format depth_stencil_format)
205 {
206 uint rgba[4], depth_stencil[2], buffer_size;
207 EGLint surface_type;
208 EGLint i;
209
210 /* get the color and depth/stencil component sizes */
211 assert(nconf->color_format != PIPE_FORMAT_NONE);
212 buffer_size = 0;
213 for (i = 0; i < 4; i++) {
214 rgba[i] = util_format_get_component_bits(nconf->color_format,
215 UTIL_FORMAT_COLORSPACE_RGB, i);
216 buffer_size += rgba[i];
217 }
218 for (i = 0; i < 2; i++) {
219 if (depth_stencil_format != PIPE_FORMAT_NONE) {
220 depth_stencil[i] =
221 util_format_get_component_bits(depth_stencil_format,
222 UTIL_FORMAT_COLORSPACE_ZS, i);
223 }
224 else {
225 depth_stencil[i] = 0;
226 }
227 }
228
229 surface_type = 0x0;
230 if (nconf->window_bit)
231 surface_type |= EGL_WINDOW_BIT;
232 if (nconf->pixmap_bit)
233 surface_type |= EGL_PIXMAP_BIT;
234 #ifdef EGL_MESA_screen_surface
235 if (nconf->scanout_bit)
236 surface_type |= EGL_SCREEN_BIT_MESA;
237 #endif
238
239 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT))
240 surface_type |= EGL_PBUFFER_BIT;
241
242 SET_CONFIG_ATTRIB(conf, EGL_CONFORMANT, api_mask);
243 SET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE, api_mask);
244
245 SET_CONFIG_ATTRIB(conf, EGL_RED_SIZE, rgba[0]);
246 SET_CONFIG_ATTRIB(conf, EGL_GREEN_SIZE, rgba[1]);
247 SET_CONFIG_ATTRIB(conf, EGL_BLUE_SIZE, rgba[2]);
248 SET_CONFIG_ATTRIB(conf, EGL_ALPHA_SIZE, rgba[3]);
249 SET_CONFIG_ATTRIB(conf, EGL_BUFFER_SIZE, buffer_size);
250
251 SET_CONFIG_ATTRIB(conf, EGL_DEPTH_SIZE, depth_stencil[0]);
252 SET_CONFIG_ATTRIB(conf, EGL_STENCIL_SIZE, depth_stencil[1]);
253
254 SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, surface_type);
255
256 SET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE, EGL_TRUE);
257 if (surface_type & EGL_WINDOW_BIT) {
258 SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID, nconf->native_visual_id);
259 SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE,
260 nconf->native_visual_type);
261 }
262
263 if (surface_type & EGL_PBUFFER_BIT) {
264 SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
265 if (rgba[3])
266 SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
267
268 SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_WIDTH, 4096);
269 SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_HEIGHT, 4096);
270 SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_PIXELS, 4096 * 4096);
271 }
272
273 SET_CONFIG_ATTRIB(conf, EGL_LEVEL, nconf->level);
274 SET_CONFIG_ATTRIB(conf, EGL_SAMPLES, nconf->samples);
275 SET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS, 1);
276
277 if (nconf->slow_config)
278 SET_CONFIG_ATTRIB(conf, EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG);
279
280 if (nconf->transparent_rgb) {
281 rgba[0] = nconf->transparent_rgb_values[0];
282 rgba[1] = nconf->transparent_rgb_values[1];
283 rgba[2] = nconf->transparent_rgb_values[2];
284
285 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_RGB);
286 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_RED_VALUE, rgba[0]);
287 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_GREEN_VALUE, rgba[1]);
288 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_BLUE_VALUE, rgba[2]);
289 }
290
291 return _eglValidateConfig(conf, EGL_FALSE);
292 }
293
294 /**
295 * Initialize an EGL config from the native config.
296 */
297 static EGLBoolean
298 egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy,
299 _EGLConfig *conf, const struct native_config *nconf,
300 enum pipe_format depth_stencil_format)
301 {
302 struct egl_g3d_config *gconf = egl_g3d_config(conf);
303 EGLint buffer_mask, api_mask;
304 EGLBoolean valid;
305
306 buffer_mask = 0x0;
307 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT))
308 buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
309 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT))
310 buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
311 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_RIGHT))
312 buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
313 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_RIGHT))
314 buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
315
316 gconf->stvis.buffer_mask = buffer_mask;
317 gconf->stvis.color_format = nconf->color_format;
318 gconf->stvis.depth_stencil_format = depth_stencil_format;
319 gconf->stvis.accum_format = PIPE_FORMAT_NONE;
320 gconf->stvis.samples = nconf->samples;
321
322 gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ?
323 ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT;
324
325 api_mask = dpy->ClientAPIsMask;
326 /* this is required by EGL, not by OpenGL ES */
327 if (nconf->window_bit &&
328 gconf->stvis.render_buffer != ST_ATTACHMENT_BACK_LEFT)
329 api_mask &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT);
330
331 if (!api_mask) {
332 _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x",
333 nconf->native_visual_id);
334 }
335
336 valid = init_config_attributes(&gconf->base,
337 nconf, api_mask, depth_stencil_format);
338 if (!valid) {
339 _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id);
340 return EGL_FALSE;
341 }
342
343 gconf->native = nconf;
344
345 return EGL_TRUE;
346 }
347
348 /**
349 * Get all interested depth/stencil formats of a display.
350 */
351 static EGLint
352 egl_g3d_fill_depth_stencil_formats(_EGLDisplay *dpy,
353 enum pipe_format formats[8])
354 {
355 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
356 struct pipe_screen *screen = gdpy->native->screen;
357 const EGLint candidates[] = {
358 1, PIPE_FORMAT_Z16_UNORM,
359 1, PIPE_FORMAT_Z32_UNORM,
360 2, PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_FORMAT_S8_USCALED_Z24_UNORM,
361 2, PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_X8Z24_UNORM,
362 0
363 };
364 const EGLint *fmt = candidates;
365 EGLint count;
366
367 count = 0;
368 formats[count++] = PIPE_FORMAT_NONE;
369
370 while (*fmt) {
371 EGLint i, n = *fmt++;
372
373 /* pick the first supported format */
374 for (i = 0; i < n; i++) {
375 if (screen->is_format_supported(screen, fmt[i],
376 PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL, 0)) {
377 formats[count++] = fmt[i];
378 break;
379 }
380 }
381
382 fmt += n;
383 }
384
385 return count;
386 }
387
388 /**
389 * Add configs to display and return the next config ID.
390 */
391 static EGLint
392 egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
393 {
394 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
395 const struct native_config **native_configs;
396 enum pipe_format depth_stencil_formats[8];
397 int num_formats, num_configs, i, j;
398
399 native_configs = gdpy->native->get_configs(gdpy->native, &num_configs);
400 if (!num_configs) {
401 if (native_configs)
402 FREE(native_configs);
403 return id;
404 }
405
406 num_formats = egl_g3d_fill_depth_stencil_formats(dpy,
407 depth_stencil_formats);
408
409 for (i = 0; i < num_configs; i++) {
410 for (j = 0; j < num_formats; j++) {
411 struct egl_g3d_config *gconf;
412
413 gconf = CALLOC_STRUCT(egl_g3d_config);
414 if (gconf) {
415 _eglInitConfig(&gconf->base, dpy, id);
416 if (!egl_g3d_init_config(drv, dpy, &gconf->base,
417 native_configs[i], depth_stencil_formats[j])) {
418 FREE(gconf);
419 break;
420 }
421
422 _eglAddConfig(dpy, &gconf->base);
423 id++;
424 }
425 }
426 }
427
428 FREE(native_configs);
429 return id;
430 }
431
432 static void
433 egl_g3d_invalid_surface(struct native_display *ndpy,
434 struct native_surface *nsurf,
435 unsigned int seq_num)
436 {
437 /* XXX not thread safe? */
438 struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
439 struct egl_g3d_context *gctx;
440
441 /*
442 * Some functions such as egl_g3d_copy_buffers create a temporary native
443 * surface. There is no gsurf associated with it.
444 */
445 gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL;
446 if (gctx)
447 gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi);
448 }
449
450 static struct pipe_screen *
451 egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd)
452 {
453 _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
454 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
455 return gdpy->loader->create_drm_screen(name, fd);
456 }
457
458 static struct pipe_screen *
459 egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws)
460 {
461 _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
462 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
463 return gdpy->loader->create_sw_screen(ws);
464 }
465
466 static struct native_event_handler egl_g3d_native_event_handler = {
467 egl_g3d_invalid_surface,
468 egl_g3d_new_drm_screen,
469 egl_g3d_new_sw_screen
470 };
471
472 static EGLBoolean
473 egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
474 {
475 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
476 EGLint i;
477
478 _eglReleaseDisplayResources(drv, dpy);
479 _eglCleanupDisplay(dpy);
480
481 if (gdpy->pipe)
482 gdpy->pipe->destroy(gdpy->pipe);
483
484 if (dpy->Screens) {
485 for (i = 0; i < dpy->NumScreens; i++) {
486 struct egl_g3d_screen *gscr = egl_g3d_screen(dpy->Screens[i]);
487 FREE(gscr->native_modes);
488 FREE(gscr);
489 }
490 FREE(dpy->Screens);
491 }
492
493 if (gdpy->smapi)
494 egl_g3d_destroy_st_manager(gdpy->smapi);
495
496 if (gdpy->native)
497 gdpy->native->destroy(gdpy->native);
498
499 FREE(gdpy);
500 dpy->DriverData = NULL;
501
502 return EGL_TRUE;
503 }
504
505 static EGLBoolean
506 egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
507 EGLint *major, EGLint *minor)
508 {
509 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
510 struct egl_g3d_display *gdpy;
511 const struct native_platform *nplat;
512
513 /* the probe object is unlikely to be needed again */
514 egl_g3d_destroy_probe(drv, dpy);
515
516 nplat = egl_g3d_get_platform(drv, dpy->Platform);
517 if (!nplat)
518 return EGL_FALSE;
519
520 gdpy = CALLOC_STRUCT(egl_g3d_display);
521 if (!gdpy) {
522 _eglError(EGL_BAD_ALLOC, "eglInitialize");
523 goto fail;
524 }
525 gdpy->loader = gdrv->loader;
526 dpy->DriverData = gdpy;
527
528 _eglLog(_EGL_INFO, "use %s for display %p", nplat->name, dpy->PlatformDisplay);
529 gdpy->native = nplat->create_display(dpy->PlatformDisplay,
530 &egl_g3d_native_event_handler, (void *) dpy);
531 if (!gdpy->native) {
532 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
533 goto fail;
534 }
535
536 if (gdpy->loader->api_mask & (1 << ST_API_OPENGL))
537 dpy->ClientAPIsMask |= EGL_OPENGL_BIT;
538 if (gdpy->loader->api_mask & (1 << ST_API_OPENGL_ES1))
539 dpy->ClientAPIsMask |= EGL_OPENGL_ES_BIT;
540 if (gdpy->loader->api_mask & (1 << ST_API_OPENGL_ES2))
541 dpy->ClientAPIsMask |= EGL_OPENGL_ES2_BIT;
542 if (gdpy->loader->api_mask & (1 << ST_API_OPENVG))
543 dpy->ClientAPIsMask |= EGL_OPENVG_BIT;
544
545 gdpy->smapi = egl_g3d_create_st_manager(dpy);
546 if (!gdpy->smapi) {
547 _eglError(EGL_NOT_INITIALIZED,
548 "eglInitialize(failed to create st manager)");
549 goto fail;
550 }
551
552 #ifdef EGL_MESA_screen_surface
553 /* enable MESA_screen_surface before adding (and validating) configs */
554 if (gdpy->native->modeset) {
555 dpy->Extensions.MESA_screen_surface = EGL_TRUE;
556 egl_g3d_add_screens(drv, dpy);
557 }
558 #endif
559
560 dpy->Extensions.KHR_image_base = EGL_TRUE;
561 if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER))
562 dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
563
564 if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
565 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
566 goto fail;
567 }
568
569 *major = 1;
570 *minor = 4;
571
572 return EGL_TRUE;
573
574 fail:
575 if (gdpy)
576 egl_g3d_terminate(drv, dpy);
577 return EGL_FALSE;
578 }
579
580 static _EGLProc
581 egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
582 {
583 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
584 struct st_api *stapi = NULL;
585
586 if (procname && procname[0] == 'v' && procname[1] == 'g')
587 stapi = gdrv->loader->get_st_api(ST_API_OPENVG);
588 else if (procname && procname[0] == 'g' && procname[1] == 'l')
589 stapi = gdrv->loader->guess_gl_api();
590
591 return (_EGLProc) ((stapi) ?
592 stapi->get_proc_address(stapi, procname) : NULL);
593 }
594
595 static EGLint
596 egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy)
597 {
598 enum native_probe_result res;
599 EGLint score;
600
601 res = egl_g3d_get_probe_result(drv, dpy);
602
603 switch (res) {
604 case NATIVE_PROBE_UNKNOWN:
605 default:
606 score = 0;
607 break;
608 case NATIVE_PROBE_FALLBACK:
609 score = 40;
610 break;
611 case NATIVE_PROBE_SUPPORTED:
612 score = 50;
613 break;
614 case NATIVE_PROBE_EXACT:
615 score = 100;
616 break;
617 }
618
619 return score;
620 }
621
622 _EGLDriver *
623 egl_g3d_create_driver(const struct egl_g3d_loader *loader)
624 {
625 struct egl_g3d_driver *gdrv;
626
627 gdrv = CALLOC_STRUCT(egl_g3d_driver);
628 if (!gdrv)
629 return NULL;
630
631 gdrv->loader = loader;
632
633 egl_g3d_init_driver_api(&gdrv->base);
634 gdrv->base.API.Initialize = egl_g3d_initialize;
635 gdrv->base.API.Terminate = egl_g3d_terminate;
636 gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
637
638 gdrv->base.Probe = egl_g3d_probe;
639
640 /* the key is " EGL G3D" */
641 gdrv->probe_key = 0x0E61063D;
642
643 /* to be filled by the caller */
644 gdrv->base.Name = NULL;
645 gdrv->base.Unload = NULL;
646
647 return &gdrv->base;
648 }
649
650 void
651 egl_g3d_destroy_driver(_EGLDriver *drv)
652 {
653 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
654 FREE(gdrv);
655 }