2 * Mesa 3-D graphics library
5 * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
26 #include "egldriver.h"
27 #include "eglcurrent.h"
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 #include "util/u_atomic.h"
37 #include "egl_g3d_api.h"
38 #include "egl_g3d_st.h"
39 #include "egl_g3d_loader.h"
43 egl_g3d_invalid_surface(struct native_display
*ndpy
,
44 struct native_surface
*nsurf
,
47 /* XXX not thread safe? */
48 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(nsurf
->user_data
);
50 if (gsurf
&& gsurf
->stfbi
)
51 p_atomic_inc(&gsurf
->stfbi
->stamp
);
54 static struct pipe_screen
*
55 egl_g3d_new_drm_screen(struct native_display
*ndpy
, const char *name
, int fd
)
57 _EGLDisplay
*dpy
= (_EGLDisplay
*) ndpy
->user_data
;
58 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
59 return gdpy
->loader
->create_drm_screen(name
, fd
);
62 static struct pipe_screen
*
63 egl_g3d_new_sw_screen(struct native_display
*ndpy
, struct sw_winsys
*ws
)
65 _EGLDisplay
*dpy
= (_EGLDisplay
*) ndpy
->user_data
;
66 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
67 return gdpy
->loader
->create_sw_screen(ws
);
70 static struct pipe_resource
*
71 egl_g3d_lookup_egl_image(struct native_display
*ndpy
, void *egl_image
)
73 _EGLDisplay
*dpy
= (_EGLDisplay
*) ndpy
->user_data
;
74 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
75 struct st_egl_image img
;
76 struct pipe_resource
*resource
= NULL
;
78 memset(&img
, 0, sizeof(img
));
79 if (gdpy
->smapi
->get_egl_image(gdpy
->smapi
, egl_image
, &img
))
80 resource
= img
.texture
;
85 static const struct native_event_handler egl_g3d_native_event_handler
= {
86 egl_g3d_invalid_surface
,
87 egl_g3d_new_drm_screen
,
88 egl_g3d_new_sw_screen
,
89 egl_g3d_lookup_egl_image
93 * Get the native platform.
95 static const struct native_platform
*
96 egl_g3d_get_platform(_EGLDriver
*drv
, _EGLPlatformType plat
)
98 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
100 if (!gdrv
->platforms
[plat
]) {
101 const char *plat_name
= NULL
;
102 const struct native_platform
*nplat
= NULL
;
105 case _EGL_PLATFORM_WINDOWS
:
106 plat_name
= "Windows";
107 #ifdef HAVE_GDI_BACKEND
108 nplat
= native_get_gdi_platform(&egl_g3d_native_event_handler
);
111 case _EGL_PLATFORM_X11
:
113 #ifdef HAVE_X11_BACKEND
114 nplat
= native_get_x11_platform(&egl_g3d_native_event_handler
);
117 case _EGL_PLATFORM_WAYLAND
:
118 plat_name
= "wayland";
119 #ifdef HAVE_WAYLAND_BACKEND
120 nplat
= native_get_wayland_platform(&egl_g3d_native_event_handler
);
123 case _EGL_PLATFORM_DRM
:
125 #ifdef HAVE_DRM_BACKEND
126 nplat
= native_get_drm_platform(&egl_g3d_native_event_handler
);
129 case _EGL_PLATFORM_FBDEV
:
131 #ifdef HAVE_FBDEV_BACKEND
132 nplat
= native_get_fbdev_platform(&egl_g3d_native_event_handler
);
135 case _EGL_PLATFORM_NULL
:
137 #ifdef HAVE_NULL_BACKEND
138 nplat
= native_get_null_platform(&egl_g3d_native_event_handler
);
141 case _EGL_PLATFORM_ANDROID
:
142 plat_name
= "Android";
143 #ifdef HAVE_ANDROID_BACKEND
144 nplat
= native_get_android_platform(&egl_g3d_native_event_handler
);
152 _eglLog(_EGL_WARNING
, "unsupported platform %s", plat_name
);
154 gdrv
->platforms
[plat
] = nplat
;
157 return gdrv
->platforms
[plat
];
160 #ifdef EGL_MESA_screen_surface
163 egl_g3d_add_screens(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
165 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
166 const struct native_connector
**native_connectors
;
167 EGLint num_connectors
, i
;
170 gdpy
->native
->modeset
->get_connectors(gdpy
->native
, &num_connectors
, NULL
);
171 if (!num_connectors
) {
172 if (native_connectors
)
173 FREE(native_connectors
);
177 for (i
= 0; i
< num_connectors
; i
++) {
178 const struct native_connector
*nconn
= native_connectors
[i
];
179 struct egl_g3d_screen
*gscr
;
180 const struct native_mode
**native_modes
;
183 /* TODO support for hotplug */
185 gdpy
->native
->modeset
->get_modes(gdpy
->native
, nconn
, &num_modes
);
192 gscr
= CALLOC_STRUCT(egl_g3d_screen
);
198 _eglInitScreen(&gscr
->base
, dpy
, num_modes
);
199 for (j
= 0; j
< gscr
->base
.NumModes
; j
++) {
200 const struct native_mode
*nmode
= native_modes
[j
];
201 _EGLMode
*mode
= &gscr
->base
.Modes
[j
];
203 mode
->Width
= nmode
->width
;
204 mode
->Height
= nmode
->height
;
205 mode
->RefreshRate
= nmode
->refresh_rate
;
206 mode
->Optimal
= EGL_FALSE
;
207 mode
->Interlaced
= EGL_FALSE
;
208 /* no need to strdup() */
209 mode
->Name
= nmode
->desc
;
212 gscr
->native
= nconn
;
213 gscr
->native_modes
= native_modes
;
215 _eglLinkScreen(&gscr
->base
);
218 FREE(native_connectors
);
221 #endif /* EGL_MESA_screen_surface */
224 * Initialize and validate the EGL config attributes.
227 init_config_attributes(_EGLConfig
*conf
, const struct native_config
*nconf
,
228 EGLint api_mask
, enum pipe_format depth_stencil_format
,
229 EGLint preserve_buffer
, EGLint max_swap_interval
,
230 EGLBoolean pre_alpha
)
232 uint rgba
[4], depth_stencil
[2], buffer_size
;
236 /* get the color and depth/stencil component sizes */
237 assert(nconf
->color_format
!= PIPE_FORMAT_NONE
);
239 for (i
= 0; i
< 4; i
++) {
240 rgba
[i
] = util_format_get_component_bits(nconf
->color_format
,
241 UTIL_FORMAT_COLORSPACE_RGB
, i
);
242 buffer_size
+= rgba
[i
];
244 for (i
= 0; i
< 2; i
++) {
245 if (depth_stencil_format
!= PIPE_FORMAT_NONE
) {
247 util_format_get_component_bits(depth_stencil_format
,
248 UTIL_FORMAT_COLORSPACE_ZS
, i
);
251 depth_stencil
[i
] = 0;
256 /* pixmap surfaces should be EGL_SINGLE_BUFFER */
257 if (nconf
->buffer_mask
& (1 << NATIVE_ATTACHMENT_FRONT_LEFT
)) {
258 if (nconf
->pixmap_bit
)
259 surface_type
|= EGL_PIXMAP_BIT
;
261 /* the others surfaces should be EGL_BACK_BUFFER (or settable) */
262 if (nconf
->buffer_mask
& (1 << NATIVE_ATTACHMENT_BACK_LEFT
)) {
263 if (nconf
->window_bit
)
264 surface_type
|= EGL_WINDOW_BIT
;
265 #ifdef EGL_MESA_screen_surface
266 if (nconf
->scanout_bit
)
267 surface_type
|= EGL_SCREEN_BIT_MESA
;
269 surface_type
|= EGL_PBUFFER_BIT
;
273 surface_type
|= EGL_SWAP_BEHAVIOR_PRESERVED_BIT
;
275 if (pre_alpha
&& rgba
[3]) {
276 surface_type
|= EGL_VG_ALPHA_FORMAT_PRE_BIT
;
277 /* st/vega does not support premultiplied alpha yet */
278 api_mask
&= ~EGL_OPENVG_BIT
;
281 conf
->Conformant
= api_mask
;
282 conf
->RenderableType
= api_mask
;
284 conf
->RedSize
= rgba
[0];
285 conf
->GreenSize
= rgba
[1];
286 conf
->BlueSize
= rgba
[2];
287 conf
->AlphaSize
= rgba
[3];
288 conf
->BufferSize
= buffer_size
;
290 conf
->DepthSize
= depth_stencil
[0];
291 conf
->StencilSize
= depth_stencil
[1];
293 /* st/vega will allocate the mask on demand */
294 if (api_mask
& EGL_OPENVG_BIT
)
295 conf
->AlphaMaskSize
= 8;
297 conf
->SurfaceType
= surface_type
;
299 conf
->NativeRenderable
= EGL_TRUE
;
300 if (surface_type
& EGL_WINDOW_BIT
) {
301 conf
->NativeVisualID
= nconf
->native_visual_id
;
302 conf
->NativeVisualType
= nconf
->native_visual_type
;
305 if (surface_type
& EGL_PBUFFER_BIT
) {
306 conf
->BindToTextureRGB
= EGL_TRUE
;
308 conf
->BindToTextureRGBA
= EGL_TRUE
;
310 conf
->MaxPbufferWidth
= 4096;
311 conf
->MaxPbufferHeight
= 4096;
312 conf
->MaxPbufferPixels
= 4096 * 4096;
315 conf
->Level
= nconf
->level
;
317 if (nconf
->transparent_rgb
) {
318 conf
->TransparentType
= EGL_TRANSPARENT_RGB
;
319 conf
->TransparentRedValue
= nconf
->transparent_rgb_values
[0];
320 conf
->TransparentGreenValue
= nconf
->transparent_rgb_values
[1];
321 conf
->TransparentBlueValue
= nconf
->transparent_rgb_values
[2];
324 conf
->MinSwapInterval
= 0;
325 conf
->MaxSwapInterval
= max_swap_interval
;
327 return _eglValidateConfig(conf
, EGL_FALSE
);
331 * Initialize an EGL config from the native config.
334 egl_g3d_init_config(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
335 _EGLConfig
*conf
, const struct native_config
*nconf
,
336 enum pipe_format depth_stencil_format
,
337 int preserve_buffer
, int max_swap_interval
,
340 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
345 if (nconf
->buffer_mask
& (1 << NATIVE_ATTACHMENT_FRONT_LEFT
))
346 buffer_mask
|= ST_ATTACHMENT_FRONT_LEFT_MASK
;
347 if (nconf
->buffer_mask
& (1 << NATIVE_ATTACHMENT_BACK_LEFT
))
348 buffer_mask
|= ST_ATTACHMENT_BACK_LEFT_MASK
;
349 if (nconf
->buffer_mask
& (1 << NATIVE_ATTACHMENT_FRONT_RIGHT
))
350 buffer_mask
|= ST_ATTACHMENT_FRONT_RIGHT_MASK
;
351 if (nconf
->buffer_mask
& (1 << NATIVE_ATTACHMENT_BACK_RIGHT
))
352 buffer_mask
|= ST_ATTACHMENT_BACK_RIGHT_MASK
;
354 gconf
->stvis
.buffer_mask
= buffer_mask
;
355 gconf
->stvis
.color_format
= nconf
->color_format
;
356 gconf
->stvis
.depth_stencil_format
= depth_stencil_format
;
357 gconf
->stvis
.accum_format
= PIPE_FORMAT_NONE
;
358 gconf
->stvis
.samples
= 0;
360 /* will be overridden per surface */
361 gconf
->stvis
.render_buffer
= (buffer_mask
& ST_ATTACHMENT_BACK_LEFT_MASK
) ?
362 ST_ATTACHMENT_BACK_LEFT
: ST_ATTACHMENT_FRONT_LEFT
;
364 valid
= init_config_attributes(&gconf
->base
,
365 nconf
, dpy
->ClientAPIs
, depth_stencil_format
,
366 preserve_buffer
, max_swap_interval
, pre_alpha
);
368 _eglLog(_EGL_DEBUG
, "skip invalid config 0x%x", nconf
->native_visual_id
);
372 gconf
->native
= nconf
;
378 * Get all interested depth/stencil formats of a display.
381 egl_g3d_fill_depth_stencil_formats(_EGLDisplay
*dpy
,
382 enum pipe_format formats
[8])
384 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
385 struct pipe_screen
*screen
= gdpy
->native
->screen
;
386 const EGLint candidates
[] = {
387 1, PIPE_FORMAT_Z16_UNORM
,
388 1, PIPE_FORMAT_Z32_UNORM
,
389 2, PIPE_FORMAT_Z24_UNORM_S8_UINT
, PIPE_FORMAT_S8_UINT_Z24_UNORM
,
390 2, PIPE_FORMAT_Z24X8_UNORM
, PIPE_FORMAT_X8Z24_UNORM
,
393 const EGLint
*fmt
= candidates
;
397 formats
[count
++] = PIPE_FORMAT_NONE
;
400 EGLint i
, n
= *fmt
++;
402 /* pick the first supported format */
403 for (i
= 0; i
< n
; i
++) {
404 if (screen
->is_format_supported(screen
, fmt
[i
],
405 PIPE_TEXTURE_2D
, 0, PIPE_BIND_DEPTH_STENCIL
)) {
406 formats
[count
++] = fmt
[i
];
418 * Add configs to display and return the next config ID.
421 egl_g3d_add_configs(_EGLDriver
*drv
, _EGLDisplay
*dpy
, EGLint id
)
423 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
424 const struct native_config
**native_configs
;
425 enum pipe_format depth_stencil_formats
[8];
426 int num_formats
, num_configs
, i
, j
;
427 int preserve_buffer
, max_swap_interval
, premultiplied_alpha
;
429 native_configs
= gdpy
->native
->get_configs(gdpy
->native
, &num_configs
);
432 FREE(native_configs
);
437 gdpy
->native
->get_param(gdpy
->native
, NATIVE_PARAM_PRESERVE_BUFFER
);
439 gdpy
->native
->get_param(gdpy
->native
, NATIVE_PARAM_MAX_SWAP_INTERVAL
);
440 premultiplied_alpha
=
441 gdpy
->native
->get_param(gdpy
->native
, NATIVE_PARAM_PREMULTIPLIED_ALPHA
);
443 num_formats
= egl_g3d_fill_depth_stencil_formats(dpy
,
444 depth_stencil_formats
);
446 for (i
= 0; i
< num_configs
; i
++) {
447 for (j
= 0; j
< num_formats
; j
++) {
448 struct egl_g3d_config
*gconf
;
450 gconf
= CALLOC_STRUCT(egl_g3d_config
);
452 _eglInitConfig(&gconf
->base
, dpy
, id
);
453 if (!egl_g3d_init_config(drv
, dpy
, &gconf
->base
,
454 native_configs
[i
], depth_stencil_formats
[j
],
455 preserve_buffer
, max_swap_interval
,
456 premultiplied_alpha
)) {
461 _eglLinkConfig(&gconf
->base
);
467 FREE(native_configs
);
472 egl_g3d_free_config(void *conf
)
474 struct egl_g3d_config
*gconf
= egl_g3d_config((_EGLConfig
*) conf
);
479 egl_g3d_free_screen(void *scr
)
481 #ifdef EGL_MESA_screen_surface
482 struct egl_g3d_screen
*gscr
= egl_g3d_screen((_EGLScreen
*) scr
);
483 FREE(gscr
->native_modes
);
489 egl_g3d_terminate(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
491 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
493 _eglReleaseDisplayResources(drv
, dpy
);
496 _eglDestroyArray(dpy
->Configs
, egl_g3d_free_config
);
500 _eglDestroyArray(dpy
->Screens
, egl_g3d_free_screen
);
504 _eglCleanupDisplay(dpy
);
507 egl_g3d_destroy_st_manager(gdpy
->smapi
);
510 gdpy
->native
->destroy(gdpy
->native
);
513 dpy
->DriverData
= NULL
;
519 egl_g3d_initialize(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
521 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
522 struct egl_g3d_display
*gdpy
;
523 const struct native_platform
*nplat
;
525 nplat
= egl_g3d_get_platform(drv
, dpy
->Platform
);
529 if (dpy
->Options
.TestOnly
)
532 gdpy
= CALLOC_STRUCT(egl_g3d_display
);
534 _eglError(EGL_BAD_ALLOC
, "eglInitialize");
537 gdpy
->loader
= gdrv
->loader
;
538 dpy
->DriverData
= gdpy
;
540 _eglLog(_EGL_INFO
, "use %s for display %p",
541 nplat
->name
, dpy
->PlatformDisplay
);
543 nplat
->create_display(dpy
->PlatformDisplay
, dpy
->Options
.UseFallback
);
545 _eglError(EGL_NOT_INITIALIZED
, "eglInitialize(no usable display)");
548 gdpy
->native
->user_data
= (void *) dpy
;
549 if (!gdpy
->native
->init_screen(gdpy
->native
)) {
550 _eglError(EGL_NOT_INITIALIZED
,
551 "eglInitialize(failed to initialize screen)");
555 if (gdpy
->loader
->profile_masks
[ST_API_OPENGL
] & ST_PROFILE_DEFAULT_MASK
)
556 dpy
->ClientAPIs
|= EGL_OPENGL_BIT
;
557 if (gdpy
->loader
->profile_masks
[ST_API_OPENGL
] & ST_PROFILE_OPENGL_ES1_MASK
)
558 dpy
->ClientAPIs
|= EGL_OPENGL_ES_BIT
;
559 if (gdpy
->loader
->profile_masks
[ST_API_OPENGL
] & ST_PROFILE_OPENGL_ES2_MASK
)
560 dpy
->ClientAPIs
|= EGL_OPENGL_ES2_BIT
;
561 if (gdpy
->loader
->profile_masks
[ST_API_OPENVG
] & ST_PROFILE_DEFAULT_MASK
)
562 dpy
->ClientAPIs
|= EGL_OPENVG_BIT
;
564 gdpy
->smapi
= egl_g3d_create_st_manager(dpy
);
566 _eglError(EGL_NOT_INITIALIZED
,
567 "eglInitialize(failed to create st manager)");
571 #ifdef EGL_MESA_screen_surface
572 /* enable MESA_screen_surface before adding (and validating) configs */
573 if (gdpy
->native
->modeset
) {
574 dpy
->Extensions
.MESA_screen_surface
= EGL_TRUE
;
575 egl_g3d_add_screens(drv
, dpy
);
579 dpy
->Extensions
.KHR_image_base
= EGL_TRUE
;
580 if (gdpy
->native
->get_param(gdpy
->native
, NATIVE_PARAM_USE_NATIVE_BUFFER
))
581 dpy
->Extensions
.KHR_image_pixmap
= EGL_TRUE
;
583 dpy
->Extensions
.KHR_reusable_sync
= EGL_TRUE
;
584 dpy
->Extensions
.KHR_fence_sync
= EGL_TRUE
;
586 dpy
->Extensions
.KHR_surfaceless_gles1
= EGL_TRUE
;
587 dpy
->Extensions
.KHR_surfaceless_gles2
= EGL_TRUE
;
588 dpy
->Extensions
.KHR_surfaceless_opengl
= EGL_TRUE
;
590 if (dpy
->Platform
== _EGL_PLATFORM_DRM
) {
591 dpy
->Extensions
.MESA_drm_display
= EGL_TRUE
;
592 if (gdpy
->native
->buffer
)
593 dpy
->Extensions
.MESA_drm_image
= EGL_TRUE
;
596 if (dpy
->Platform
== _EGL_PLATFORM_WAYLAND
&& gdpy
->native
->buffer
)
597 dpy
->Extensions
.MESA_drm_image
= EGL_TRUE
;
599 #ifdef EGL_ANDROID_image_native_buffer
600 if (dpy
->Platform
== _EGL_PLATFORM_ANDROID
&& gdpy
->native
->buffer
)
601 dpy
->Extensions
.ANDROID_image_native_buffer
= EGL_TRUE
;
604 #ifdef EGL_WL_bind_wayland_display
605 if (gdpy
->native
->wayland_bufmgr
)
606 dpy
->Extensions
.WL_bind_wayland_display
= EGL_TRUE
;
609 if (gdpy
->native
->get_param(gdpy
->native
, NATIVE_PARAM_PRESENT_REGION
) &&
610 gdpy
->native
->get_param(gdpy
->native
, NATIVE_PARAM_PRESERVE_BUFFER
)) {
611 #ifdef EGL_NOK_swap_region
612 dpy
->Extensions
.NOK_swap_region
= EGL_TRUE
;
614 dpy
->Extensions
.NV_post_sub_buffer
= EGL_TRUE
;
617 if (egl_g3d_add_configs(drv
, dpy
, 1) == 1) {
618 _eglError(EGL_NOT_INITIALIZED
, "eglInitialize(unable to add configs)");
622 dpy
->VersionMajor
= 1;
623 dpy
->VersionMinor
= 4;
629 egl_g3d_terminate(drv
, dpy
);
634 egl_g3d_get_proc_address(_EGLDriver
*drv
, const char *procname
)
636 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
637 struct st_api
*stapi
= NULL
;
639 if (procname
&& procname
[0] == 'v' && procname
[1] == 'g')
640 stapi
= gdrv
->loader
->get_st_api(ST_API_OPENVG
);
641 else if (procname
&& procname
[0] == 'g' && procname
[1] == 'l')
642 stapi
= gdrv
->loader
->get_st_api(ST_API_OPENGL
);
644 return (_EGLProc
) ((stapi
) ?
645 stapi
->get_proc_address(stapi
, procname
) : NULL
);
649 egl_g3d_create_driver(const struct egl_g3d_loader
*loader
)
651 struct egl_g3d_driver
*gdrv
;
653 gdrv
= CALLOC_STRUCT(egl_g3d_driver
);
657 gdrv
->loader
= loader
;
659 egl_g3d_init_driver_api(&gdrv
->base
);
660 gdrv
->base
.API
.Initialize
= egl_g3d_initialize
;
661 gdrv
->base
.API
.Terminate
= egl_g3d_terminate
;
662 gdrv
->base
.API
.GetProcAddress
= egl_g3d_get_proc_address
;
664 /* to be filled by the caller */
665 gdrv
->base
.Name
= NULL
;
666 gdrv
->base
.Unload
= NULL
;
672 egl_g3d_destroy_driver(_EGLDriver
*drv
)
674 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);