• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "util/u_atomic.h"
35 
36 #include "egl_g3d.h"
37 #include "egl_g3d_api.h"
38 #include "egl_g3d_st.h"
39 #include "egl_g3d_loader.h"
40 #include "native.h"
41 
42 static void
egl_g3d_invalid_surface(struct native_display * ndpy,struct native_surface * nsurf,unsigned int seq_num)43 egl_g3d_invalid_surface(struct native_display *ndpy,
44                         struct native_surface *nsurf,
45                         unsigned int seq_num)
46 {
47    /* XXX not thread safe? */
48    struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
49 
50    if (gsurf && gsurf->stfbi)
51       p_atomic_inc(&gsurf->stfbi->stamp);
52 }
53 
54 static struct pipe_screen *
egl_g3d_new_drm_screen(struct native_display * ndpy,const char * name,int fd)55 egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd)
56 {
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);
60 }
61 
62 static struct pipe_screen *
egl_g3d_new_sw_screen(struct native_display * ndpy,struct sw_winsys * ws)63 egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws)
64 {
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);
68 }
69 
70 static struct pipe_resource *
egl_g3d_lookup_egl_image(struct native_display * ndpy,void * egl_image)71 egl_g3d_lookup_egl_image(struct native_display *ndpy, void *egl_image)
72 {
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;
77 
78    memset(&img, 0, sizeof(img));
79    if (gdpy->smapi->get_egl_image(gdpy->smapi, egl_image, &img))
80       resource = img.texture;
81 
82    return resource;
83 }
84 
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
90 };
91 
92 /**
93  * Get the native platform.
94  */
95 static const struct native_platform *
egl_g3d_get_platform(_EGLDriver * drv,_EGLPlatformType plat)96 egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat)
97 {
98    struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
99 
100    if (!gdrv->platforms[plat]) {
101       const char *plat_name = NULL;
102       const struct native_platform *nplat = NULL;
103 
104       switch (plat) {
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);
109 #endif
110          break;
111       case _EGL_PLATFORM_X11:
112          plat_name = "X11";
113 #ifdef HAVE_X11_BACKEND
114          nplat = native_get_x11_platform(&egl_g3d_native_event_handler);
115 #endif
116 	 break;
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);
121 #endif
122          break;
123       case _EGL_PLATFORM_DRM:
124          plat_name = "DRM";
125 #ifdef HAVE_DRM_BACKEND
126          nplat = native_get_drm_platform(&egl_g3d_native_event_handler);
127 #endif
128          break;
129       case _EGL_PLATFORM_FBDEV:
130          plat_name = "FBDEV";
131 #ifdef HAVE_FBDEV_BACKEND
132          nplat = native_get_fbdev_platform(&egl_g3d_native_event_handler);
133 #endif
134          break;
135       case _EGL_PLATFORM_NULL:
136          plat_name = "NULL";
137 #ifdef HAVE_NULL_BACKEND
138          nplat = native_get_null_platform(&egl_g3d_native_event_handler);
139 #endif
140          break;
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);
145 #endif
146          break;
147       default:
148          break;
149       }
150 
151       if (!nplat)
152          _eglLog(_EGL_WARNING, "unsupported platform %s", plat_name);
153 
154       gdrv->platforms[plat] = nplat;
155    }
156 
157    return gdrv->platforms[plat];
158 }
159 
160 #ifdef EGL_MESA_screen_surface
161 
162 static void
egl_g3d_add_screens(_EGLDriver * drv,_EGLDisplay * dpy)163 egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
164 {
165    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
166    const struct native_connector **native_connectors;
167    EGLint num_connectors, i;
168 
169    native_connectors =
170       gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL);
171    if (!num_connectors) {
172       if (native_connectors)
173          FREE(native_connectors);
174       return;
175    }
176 
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;
181       EGLint num_modes, j;
182 
183       /* TODO support for hotplug */
184       native_modes =
185          gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes);
186       if (!num_modes) {
187          if (native_modes)
188             FREE(native_modes);
189          continue;
190       }
191 
192       gscr = CALLOC_STRUCT(egl_g3d_screen);
193       if (!gscr) {
194          FREE(native_modes);
195          continue;
196       }
197 
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];
202 
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;
210       }
211 
212       gscr->native = nconn;
213       gscr->native_modes = native_modes;
214 
215       _eglLinkScreen(&gscr->base);
216    }
217 
218    FREE(native_connectors);
219 }
220 
221 #endif /* EGL_MESA_screen_surface */
222 
223 /**
224  * Initialize and validate the EGL config attributes.
225  */
226 static EGLBoolean
init_config_attributes(_EGLConfig * conf,const struct native_config * nconf,EGLint api_mask,enum pipe_format depth_stencil_format,EGLint preserve_buffer,EGLint max_swap_interval,EGLBoolean pre_alpha)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)
231 {
232    uint rgba[4], depth_stencil[2], buffer_size;
233    EGLint surface_type;
234    EGLint i;
235 
236    /* get the color and depth/stencil component sizes */
237    assert(nconf->color_format != PIPE_FORMAT_NONE);
238    buffer_size = 0;
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];
243    }
244    for (i = 0; i < 2; i++) {
245       if (depth_stencil_format != PIPE_FORMAT_NONE) {
246          depth_stencil[i] =
247             util_format_get_component_bits(depth_stencil_format,
248                UTIL_FORMAT_COLORSPACE_ZS, i);
249       }
250       else {
251          depth_stencil[i] = 0;
252       }
253    }
254 
255    surface_type = 0x0;
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;
260    }
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;
268 #endif
269       surface_type |= EGL_PBUFFER_BIT;
270    }
271 
272    if (preserve_buffer)
273       surface_type |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
274 
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;
279    }
280 
281    conf->Conformant = api_mask;
282    conf->RenderableType = api_mask;
283 
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;
289 
290    conf->DepthSize = depth_stencil[0];
291    conf->StencilSize = depth_stencil[1];
292 
293    /* st/vega will allocate the mask on demand */
294    if (api_mask & EGL_OPENVG_BIT)
295       conf->AlphaMaskSize = 8;
296 
297    conf->SurfaceType = surface_type;
298 
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;
303    }
304 
305    if (surface_type & EGL_PBUFFER_BIT) {
306       conf->BindToTextureRGB = EGL_TRUE;
307       if (rgba[3])
308          conf->BindToTextureRGBA = EGL_TRUE;
309 
310       conf->MaxPbufferWidth = 4096;
311       conf->MaxPbufferHeight = 4096;
312       conf->MaxPbufferPixels = 4096 * 4096;
313    }
314 
315    conf->Level = nconf->level;
316 
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];
322    }
323 
324    conf->MinSwapInterval = 0;
325    conf->MaxSwapInterval = max_swap_interval;
326 
327    return _eglValidateConfig(conf, EGL_FALSE);
328 }
329 
330 /**
331  * Initialize an EGL config from the native config.
332  */
333 static EGLBoolean
egl_g3d_init_config(_EGLDriver * drv,_EGLDisplay * dpy,_EGLConfig * conf,const struct native_config * nconf,enum pipe_format depth_stencil_format,int preserve_buffer,int max_swap_interval,int pre_alpha)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,
338                     int pre_alpha)
339 {
340    struct egl_g3d_config *gconf = egl_g3d_config(conf);
341    EGLint buffer_mask;
342    EGLBoolean valid;
343 
344    buffer_mask = 0x0;
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;
353 
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;
359 
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;
363 
364    valid = init_config_attributes(&gconf->base,
365          nconf, dpy->ClientAPIs, depth_stencil_format,
366          preserve_buffer, max_swap_interval, pre_alpha);
367    if (!valid) {
368       _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id);
369       return EGL_FALSE;
370    }
371 
372    gconf->native = nconf;
373 
374    return EGL_TRUE;
375 }
376 
377 /**
378  * Get all interested depth/stencil formats of a display.
379  */
380 static EGLint
egl_g3d_fill_depth_stencil_formats(_EGLDisplay * dpy,enum pipe_format formats[8])381 egl_g3d_fill_depth_stencil_formats(_EGLDisplay *dpy,
382                                    enum pipe_format formats[8])
383 {
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,
391       0
392    };
393    const EGLint *fmt = candidates;
394    EGLint count;
395 
396    count = 0;
397    formats[count++] = PIPE_FORMAT_NONE;
398 
399    while (*fmt) {
400       EGLint i, n = *fmt++;
401 
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];
407             break;
408          }
409       }
410 
411       fmt += n;
412    }
413 
414    return count;
415 }
416 
417 /**
418  * Add configs to display and return the next config ID.
419  */
420 static EGLint
egl_g3d_add_configs(_EGLDriver * drv,_EGLDisplay * dpy,EGLint id)421 egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
422 {
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;
428 
429    native_configs = gdpy->native->get_configs(gdpy->native, &num_configs);
430    if (!num_configs) {
431       if (native_configs)
432          FREE(native_configs);
433       return id;
434    }
435 
436    preserve_buffer =
437       gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESERVE_BUFFER);
438    max_swap_interval =
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);
442 
443    num_formats = egl_g3d_fill_depth_stencil_formats(dpy,
444          depth_stencil_formats);
445 
446    for (i = 0; i < num_configs; i++) {
447       for (j = 0; j < num_formats; j++) {
448          struct egl_g3d_config *gconf;
449 
450          gconf = CALLOC_STRUCT(egl_g3d_config);
451          if (gconf) {
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)) {
457                FREE(gconf);
458                break;
459             }
460 
461             _eglLinkConfig(&gconf->base);
462             id++;
463          }
464       }
465    }
466 
467    FREE(native_configs);
468    return id;
469 }
470 
471 static void
egl_g3d_free_config(void * conf)472 egl_g3d_free_config(void *conf)
473 {
474    struct egl_g3d_config *gconf = egl_g3d_config((_EGLConfig *) conf);
475    FREE(gconf);
476 }
477 
478 static void
egl_g3d_free_screen(void * scr)479 egl_g3d_free_screen(void *scr)
480 {
481 #ifdef EGL_MESA_screen_surface
482    struct egl_g3d_screen *gscr = egl_g3d_screen((_EGLScreen *) scr);
483    FREE(gscr->native_modes);
484    FREE(gscr);
485 #endif
486 }
487 
488 static EGLBoolean
egl_g3d_terminate(_EGLDriver * drv,_EGLDisplay * dpy)489 egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
490 {
491    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
492 
493    _eglReleaseDisplayResources(drv, dpy);
494 
495    if (dpy->Configs) {
496       _eglDestroyArray(dpy->Configs, egl_g3d_free_config);
497       dpy->Configs = NULL;
498    }
499    if (dpy->Screens) {
500       _eglDestroyArray(dpy->Screens, egl_g3d_free_screen);
501       dpy->Screens = NULL;
502    }
503 
504    _eglCleanupDisplay(dpy);
505 
506    if (gdpy->smapi)
507       egl_g3d_destroy_st_manager(gdpy->smapi);
508 
509    if (gdpy->native)
510       gdpy->native->destroy(gdpy->native);
511 
512    FREE(gdpy);
513    dpy->DriverData = NULL;
514 
515    return EGL_TRUE;
516 }
517 
518 static EGLBoolean
egl_g3d_initialize(_EGLDriver * drv,_EGLDisplay * dpy)519 egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy)
520 {
521    struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
522    struct egl_g3d_display *gdpy;
523    const struct native_platform *nplat;
524 
525    nplat = egl_g3d_get_platform(drv, dpy->Platform);
526    if (!nplat)
527       return EGL_FALSE;
528 
529    if (dpy->Options.TestOnly)
530       return EGL_TRUE;
531 
532    gdpy = CALLOC_STRUCT(egl_g3d_display);
533    if (!gdpy) {
534       _eglError(EGL_BAD_ALLOC, "eglInitialize");
535       goto fail;
536    }
537    gdpy->loader = gdrv->loader;
538    dpy->DriverData = gdpy;
539 
540    _eglLog(_EGL_INFO, "use %s for display %p",
541          nplat->name, dpy->PlatformDisplay);
542    gdpy->native =
543       nplat->create_display(dpy->PlatformDisplay, dpy->Options.UseFallback);
544    if (!gdpy->native) {
545       _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
546       goto fail;
547    }
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)");
552       goto fail;
553    }
554 
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;
563 
564    gdpy->smapi = egl_g3d_create_st_manager(dpy);
565    if (!gdpy->smapi) {
566       _eglError(EGL_NOT_INITIALIZED,
567             "eglInitialize(failed to create st manager)");
568       goto fail;
569    }
570 
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);
576    }
577 #endif
578 
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;
582 
583    dpy->Extensions.KHR_reusable_sync = EGL_TRUE;
584    dpy->Extensions.KHR_fence_sync = EGL_TRUE;
585 
586    dpy->Extensions.KHR_surfaceless_context = EGL_TRUE;
587 
588    if (dpy->Platform == _EGL_PLATFORM_DRM) {
589       dpy->Extensions.MESA_drm_display = EGL_TRUE;
590       if (gdpy->native->buffer)
591          dpy->Extensions.MESA_drm_image = EGL_TRUE;
592    }
593 
594    if (dpy->Platform == _EGL_PLATFORM_WAYLAND && gdpy->native->buffer)
595       dpy->Extensions.MESA_drm_image = EGL_TRUE;
596 
597 #ifdef EGL_ANDROID_image_native_buffer
598    if (dpy->Platform == _EGL_PLATFORM_ANDROID && gdpy->native->buffer)
599       dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE;
600 #endif
601 
602 #ifdef EGL_WL_bind_wayland_display
603    if (gdpy->native->wayland_bufmgr)
604       dpy->Extensions.WL_bind_wayland_display = EGL_TRUE;
605 #endif
606 
607    if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESENT_REGION) &&
608        gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESERVE_BUFFER)) {
609 #ifdef EGL_NOK_swap_region
610       dpy->Extensions.NOK_swap_region = EGL_TRUE;
611 #endif
612       dpy->Extensions.NV_post_sub_buffer = EGL_TRUE;
613    }
614 
615    if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
616       _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
617       goto fail;
618    }
619 
620    dpy->VersionMajor = 1;
621    dpy->VersionMinor = 4;
622 
623    return EGL_TRUE;
624 
625 fail:
626    if (gdpy)
627       egl_g3d_terminate(drv, dpy);
628    return EGL_FALSE;
629 }
630 
631 static _EGLProc
egl_g3d_get_proc_address(_EGLDriver * drv,const char * procname)632 egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
633 {
634    struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
635    struct st_api *stapi = NULL;
636 
637    if (procname && procname[0] == 'v' && procname[1] == 'g')
638       stapi = gdrv->loader->get_st_api(ST_API_OPENVG);
639    else if (procname && procname[0] == 'g' && procname[1] == 'l')
640       stapi = gdrv->loader->get_st_api(ST_API_OPENGL);
641 
642    return (_EGLProc) ((stapi) ?
643          stapi->get_proc_address(stapi, procname) : NULL);
644 }
645 
646 _EGLDriver *
egl_g3d_create_driver(const struct egl_g3d_loader * loader)647 egl_g3d_create_driver(const struct egl_g3d_loader *loader)
648 {
649    struct egl_g3d_driver *gdrv;
650 
651    gdrv = CALLOC_STRUCT(egl_g3d_driver);
652    if (!gdrv)
653       return NULL;
654 
655    gdrv->loader = loader;
656 
657    egl_g3d_init_driver_api(&gdrv->base);
658    gdrv->base.API.Initialize = egl_g3d_initialize;
659    gdrv->base.API.Terminate = egl_g3d_terminate;
660    gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
661 
662    /* to be filled by the caller */
663    gdrv->base.Name = NULL;
664    gdrv->base.Unload = NULL;
665 
666    return &gdrv->base;
667 }
668 
669 void
egl_g3d_destroy_driver(_EGLDriver * drv)670 egl_g3d_destroy_driver(_EGLDriver *drv)
671 {
672    struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
673    FREE(gdrv);
674 }
675