st/egl: Add support for EGL_MESA_image_drm.
[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 #ifdef EGL_MESA_screen_surface
92
93 static void
94 egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
95 {
96 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
97 const struct native_connector **native_connectors;
98 EGLint num_connectors, i;
99
100 native_connectors =
101 gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL);
102 if (!num_connectors) {
103 if (native_connectors)
104 FREE(native_connectors);
105 return;
106 }
107
108 for (i = 0; i < num_connectors; i++) {
109 const struct native_connector *nconn = native_connectors[i];
110 struct egl_g3d_screen *gscr;
111 const struct native_mode **native_modes;
112 EGLint num_modes, j;
113
114 /* TODO support for hotplug */
115 native_modes =
116 gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes);
117 if (!num_modes) {
118 if (native_modes)
119 FREE(native_modes);
120 continue;
121 }
122
123 gscr = CALLOC_STRUCT(egl_g3d_screen);
124 if (!gscr) {
125 FREE(native_modes);
126 continue;
127 }
128
129 _eglInitScreen(&gscr->base);
130
131 for (j = 0; j < num_modes; j++) {
132 const struct native_mode *nmode = native_modes[j];
133 _EGLMode *mode;
134
135 mode = _eglAddNewMode(&gscr->base, nmode->width, nmode->height,
136 nmode->refresh_rate, nmode->desc);
137 if (!mode)
138 break;
139 /* gscr->native_modes and gscr->base.Modes should be consistent */
140 assert(mode == &gscr->base.Modes[j]);
141 }
142
143 gscr->native = nconn;
144 gscr->native_modes = native_modes;
145
146 _eglAddScreen(dpy, &gscr->base);
147 }
148
149 FREE(native_connectors);
150 }
151
152 #endif /* EGL_MESA_screen_surface */
153
154 /**
155 * Initialize and validate the EGL config attributes.
156 */
157 static EGLBoolean
158 init_config_attributes(_EGLConfig *conf, const struct native_config *nconf,
159 EGLint api_mask, enum pipe_format depth_stencil_format)
160 {
161 uint rgba[4], depth_stencil[2], buffer_size;
162 EGLint surface_type;
163 EGLint i;
164
165 /* get the color and depth/stencil component sizes */
166 assert(nconf->color_format != PIPE_FORMAT_NONE);
167 buffer_size = 0;
168 for (i = 0; i < 4; i++) {
169 rgba[i] = util_format_get_component_bits(nconf->color_format,
170 UTIL_FORMAT_COLORSPACE_RGB, i);
171 buffer_size += rgba[i];
172 }
173 for (i = 0; i < 2; i++) {
174 if (depth_stencil_format != PIPE_FORMAT_NONE) {
175 depth_stencil[i] =
176 util_format_get_component_bits(depth_stencil_format,
177 UTIL_FORMAT_COLORSPACE_ZS, i);
178 }
179 else {
180 depth_stencil[i] = 0;
181 }
182 }
183
184 surface_type = 0x0;
185 if (nconf->window_bit)
186 surface_type |= EGL_WINDOW_BIT;
187 if (nconf->pixmap_bit)
188 surface_type |= EGL_PIXMAP_BIT;
189 #ifdef EGL_MESA_screen_surface
190 if (nconf->scanout_bit)
191 surface_type |= EGL_SCREEN_BIT_MESA;
192 #endif
193
194 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT))
195 surface_type |= EGL_PBUFFER_BIT;
196
197 SET_CONFIG_ATTRIB(conf, EGL_CONFORMANT, api_mask);
198 SET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE, api_mask);
199
200 SET_CONFIG_ATTRIB(conf, EGL_RED_SIZE, rgba[0]);
201 SET_CONFIG_ATTRIB(conf, EGL_GREEN_SIZE, rgba[1]);
202 SET_CONFIG_ATTRIB(conf, EGL_BLUE_SIZE, rgba[2]);
203 SET_CONFIG_ATTRIB(conf, EGL_ALPHA_SIZE, rgba[3]);
204 SET_CONFIG_ATTRIB(conf, EGL_BUFFER_SIZE, buffer_size);
205
206 SET_CONFIG_ATTRIB(conf, EGL_DEPTH_SIZE, depth_stencil[0]);
207 SET_CONFIG_ATTRIB(conf, EGL_STENCIL_SIZE, depth_stencil[1]);
208
209 SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, surface_type);
210
211 SET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE, EGL_TRUE);
212 if (surface_type & EGL_WINDOW_BIT) {
213 SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID, nconf->native_visual_id);
214 SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE,
215 nconf->native_visual_type);
216 }
217
218 if (surface_type & EGL_PBUFFER_BIT) {
219 SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
220 if (rgba[3])
221 SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
222
223 SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_WIDTH, 4096);
224 SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_HEIGHT, 4096);
225 SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_PIXELS, 4096 * 4096);
226 }
227
228 SET_CONFIG_ATTRIB(conf, EGL_LEVEL, nconf->level);
229 SET_CONFIG_ATTRIB(conf, EGL_SAMPLES, nconf->samples);
230 SET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS, 1);
231
232 if (nconf->slow_config)
233 SET_CONFIG_ATTRIB(conf, EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG);
234
235 if (nconf->transparent_rgb) {
236 rgba[0] = nconf->transparent_rgb_values[0];
237 rgba[1] = nconf->transparent_rgb_values[1];
238 rgba[2] = nconf->transparent_rgb_values[2];
239
240 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_RGB);
241 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_RED_VALUE, rgba[0]);
242 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_GREEN_VALUE, rgba[1]);
243 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_BLUE_VALUE, rgba[2]);
244 }
245
246 return _eglValidateConfig(conf, EGL_FALSE);
247 }
248
249 /**
250 * Initialize an EGL config from the native config.
251 */
252 static EGLBoolean
253 egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy,
254 _EGLConfig *conf, const struct native_config *nconf,
255 enum pipe_format depth_stencil_format)
256 {
257 struct egl_g3d_config *gconf = egl_g3d_config(conf);
258 EGLint buffer_mask, api_mask;
259 EGLBoolean valid;
260
261 buffer_mask = 0x0;
262 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT))
263 buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
264 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT))
265 buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
266 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_RIGHT))
267 buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
268 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_RIGHT))
269 buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
270
271 gconf->stvis.buffer_mask = buffer_mask;
272 gconf->stvis.color_format = nconf->color_format;
273 gconf->stvis.depth_stencil_format = depth_stencil_format;
274 gconf->stvis.accum_format = PIPE_FORMAT_NONE;
275 gconf->stvis.samples = nconf->samples;
276
277 gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ?
278 ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT;
279
280 api_mask = dpy->ClientAPIsMask;
281 /* this is required by EGL, not by OpenGL ES */
282 if (nconf->window_bit &&
283 gconf->stvis.render_buffer != ST_ATTACHMENT_BACK_LEFT)
284 api_mask &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT);
285
286 if (!api_mask) {
287 _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x",
288 nconf->native_visual_id);
289 }
290
291 valid = init_config_attributes(&gconf->base,
292 nconf, api_mask, depth_stencil_format);
293 if (!valid) {
294 _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id);
295 return EGL_FALSE;
296 }
297
298 gconf->native = nconf;
299
300 return EGL_TRUE;
301 }
302
303 /**
304 * Get all interested depth/stencil formats of a display.
305 */
306 static EGLint
307 egl_g3d_fill_depth_stencil_formats(_EGLDisplay *dpy,
308 enum pipe_format formats[8])
309 {
310 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
311 struct pipe_screen *screen = gdpy->native->screen;
312 const EGLint candidates[] = {
313 1, PIPE_FORMAT_Z16_UNORM,
314 1, PIPE_FORMAT_Z32_UNORM,
315 2, PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_FORMAT_S8_USCALED_Z24_UNORM,
316 2, PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_X8Z24_UNORM,
317 0
318 };
319 const EGLint *fmt = candidates;
320 EGLint count;
321
322 count = 0;
323 formats[count++] = PIPE_FORMAT_NONE;
324
325 while (*fmt) {
326 EGLint i, n = *fmt++;
327
328 /* pick the first supported format */
329 for (i = 0; i < n; i++) {
330 if (screen->is_format_supported(screen, fmt[i],
331 PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL, 0)) {
332 formats[count++] = fmt[i];
333 break;
334 }
335 }
336
337 fmt += n;
338 }
339
340 return count;
341 }
342
343 /**
344 * Add configs to display and return the next config ID.
345 */
346 static EGLint
347 egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
348 {
349 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
350 const struct native_config **native_configs;
351 enum pipe_format depth_stencil_formats[8];
352 int num_formats, num_configs, i, j;
353
354 native_configs = gdpy->native->get_configs(gdpy->native, &num_configs);
355 if (!num_configs) {
356 if (native_configs)
357 FREE(native_configs);
358 return id;
359 }
360
361 num_formats = egl_g3d_fill_depth_stencil_formats(dpy,
362 depth_stencil_formats);
363
364 for (i = 0; i < num_configs; i++) {
365 for (j = 0; j < num_formats; j++) {
366 struct egl_g3d_config *gconf;
367
368 gconf = CALLOC_STRUCT(egl_g3d_config);
369 if (gconf) {
370 _eglInitConfig(&gconf->base, dpy, id);
371 if (!egl_g3d_init_config(drv, dpy, &gconf->base,
372 native_configs[i], depth_stencil_formats[j])) {
373 FREE(gconf);
374 break;
375 }
376
377 _eglAddConfig(dpy, &gconf->base);
378 id++;
379 }
380 }
381 }
382
383 FREE(native_configs);
384 return id;
385 }
386
387 static void
388 egl_g3d_invalid_surface(struct native_display *ndpy,
389 struct native_surface *nsurf,
390 unsigned int seq_num)
391 {
392 /* XXX not thread safe? */
393 struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
394 struct egl_g3d_context *gctx;
395
396 /*
397 * Some functions such as egl_g3d_copy_buffers create a temporary native
398 * surface. There is no gsurf associated with it.
399 */
400 gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL;
401 if (gctx)
402 gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi);
403 }
404
405 static struct pipe_screen *
406 egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd)
407 {
408 _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
409 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
410 return gdpy->loader->create_drm_screen(name, fd);
411 }
412
413 static struct pipe_screen *
414 egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws)
415 {
416 _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
417 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
418 return gdpy->loader->create_sw_screen(ws);
419 }
420
421 static struct native_event_handler egl_g3d_native_event_handler = {
422 egl_g3d_invalid_surface,
423 egl_g3d_new_drm_screen,
424 egl_g3d_new_sw_screen
425 };
426
427 static void
428 egl_g3d_free_config(void *conf)
429 {
430 struct egl_g3d_config *gconf = egl_g3d_config((_EGLConfig *) conf);
431 FREE(gconf);
432 }
433
434 static void
435 egl_g3d_free_screen(void *scr)
436 {
437 #ifdef EGL_MESA_screen_surface
438 struct egl_g3d_screen *gscr = egl_g3d_screen((_EGLScreen *) scr);
439 FREE(gscr->native_modes);
440 FREE(gscr);
441 #endif
442 }
443
444 static EGLBoolean
445 egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
446 {
447 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
448
449 _eglReleaseDisplayResources(drv, dpy);
450
451 if (gdpy->pipe)
452 gdpy->pipe->destroy(gdpy->pipe);
453
454 if (dpy->Configs) {
455 _eglDestroyArray(dpy->Configs, egl_g3d_free_config);
456 dpy->Configs = NULL;
457 }
458 if (dpy->Screens) {
459 _eglDestroyArray(dpy->Screens, egl_g3d_free_screen);
460 dpy->Screens = NULL;
461 }
462
463 _eglCleanupDisplay(dpy);
464
465 if (gdpy->smapi)
466 egl_g3d_destroy_st_manager(gdpy->smapi);
467
468 if (gdpy->native)
469 gdpy->native->destroy(gdpy->native);
470
471 FREE(gdpy);
472 dpy->DriverData = NULL;
473
474 return EGL_TRUE;
475 }
476
477 static EGLBoolean
478 egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
479 EGLint *major, EGLint *minor)
480 {
481 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
482 struct egl_g3d_display *gdpy;
483 const struct native_platform *nplat;
484
485 nplat = egl_g3d_get_platform(drv, dpy->Platform);
486 if (!nplat)
487 return EGL_FALSE;
488
489 gdpy = CALLOC_STRUCT(egl_g3d_display);
490 if (!gdpy) {
491 _eglError(EGL_BAD_ALLOC, "eglInitialize");
492 goto fail;
493 }
494 gdpy->loader = gdrv->loader;
495 dpy->DriverData = gdpy;
496
497 _eglLog(_EGL_INFO, "use %s for display %p", nplat->name, dpy->PlatformDisplay);
498 gdpy->native = nplat->create_display(dpy->PlatformDisplay,
499 &egl_g3d_native_event_handler, (void *) dpy);
500 if (!gdpy->native) {
501 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
502 goto fail;
503 }
504
505 if (gdpy->loader->api_mask & (1 << ST_API_OPENGL))
506 dpy->ClientAPIsMask |= EGL_OPENGL_BIT;
507 if (gdpy->loader->api_mask & (1 << ST_API_OPENGL_ES1))
508 dpy->ClientAPIsMask |= EGL_OPENGL_ES_BIT;
509 if (gdpy->loader->api_mask & (1 << ST_API_OPENGL_ES2))
510 dpy->ClientAPIsMask |= EGL_OPENGL_ES2_BIT;
511 if (gdpy->loader->api_mask & (1 << ST_API_OPENVG))
512 dpy->ClientAPIsMask |= EGL_OPENVG_BIT;
513
514 gdpy->smapi = egl_g3d_create_st_manager(dpy);
515 if (!gdpy->smapi) {
516 _eglError(EGL_NOT_INITIALIZED,
517 "eglInitialize(failed to create st manager)");
518 goto fail;
519 }
520
521 #ifdef EGL_MESA_screen_surface
522 /* enable MESA_screen_surface before adding (and validating) configs */
523 if (gdpy->native->modeset) {
524 dpy->Extensions.MESA_screen_surface = EGL_TRUE;
525 egl_g3d_add_screens(drv, dpy);
526 }
527 #endif
528
529 dpy->Extensions.KHR_image_base = EGL_TRUE;
530 if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER))
531 dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
532
533 dpy->Extensions.KHR_reusable_sync = EGL_TRUE;
534 dpy->Extensions.KHR_fence_sync = EGL_TRUE;
535
536 dpy->Extensions.KHR_surfaceless_gles1 = EGL_TRUE;
537 dpy->Extensions.KHR_surfaceless_gles2 = EGL_TRUE;
538 dpy->Extensions.KHR_surfaceless_opengl = EGL_TRUE;
539
540 if (dpy->Platform == _EGL_PLATFORM_DRM)
541 dpy->Extensions.MESA_drm_image = EGL_TRUE;
542
543 if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
544 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
545 goto fail;
546 }
547
548 *major = 1;
549 *minor = 4;
550
551 return EGL_TRUE;
552
553 fail:
554 if (gdpy)
555 egl_g3d_terminate(drv, dpy);
556 return EGL_FALSE;
557 }
558
559 static _EGLProc
560 egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
561 {
562 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
563 struct st_api *stapi = NULL;
564
565 if (procname && procname[0] == 'v' && procname[1] == 'g')
566 stapi = gdrv->loader->get_st_api(ST_API_OPENVG);
567 else if (procname && procname[0] == 'g' && procname[1] == 'l')
568 stapi = gdrv->loader->guess_gl_api();
569
570 return (_EGLProc) ((stapi) ?
571 stapi->get_proc_address(stapi, procname) : NULL);
572 }
573
574 static EGLint
575 egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy)
576 {
577 return (egl_g3d_get_platform(drv, dpy->Platform)) ? 90 : 0;
578 }
579
580 _EGLDriver *
581 egl_g3d_create_driver(const struct egl_g3d_loader *loader)
582 {
583 struct egl_g3d_driver *gdrv;
584
585 gdrv = CALLOC_STRUCT(egl_g3d_driver);
586 if (!gdrv)
587 return NULL;
588
589 gdrv->loader = loader;
590
591 egl_g3d_init_driver_api(&gdrv->base);
592 gdrv->base.API.Initialize = egl_g3d_initialize;
593 gdrv->base.API.Terminate = egl_g3d_terminate;
594 gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
595
596 gdrv->base.Probe = egl_g3d_probe;
597
598 /* to be filled by the caller */
599 gdrv->base.Name = NULL;
600 gdrv->base.Unload = NULL;
601
602 return &gdrv->base;
603 }
604
605 void
606 egl_g3d_destroy_driver(_EGLDriver *drv)
607 {
608 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
609 FREE(gdrv);
610 }