st/egl: Add support for EGL_NV_post_sub_buffer
[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 #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
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 *
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 *
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 *
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 *
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
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
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
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
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
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
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
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
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
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_gles1 = EGL_TRUE;
587 dpy->Extensions.KHR_surfaceless_gles2 = EGL_TRUE;
588 dpy->Extensions.KHR_surfaceless_opengl = EGL_TRUE;
589
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;
594 }
595
596 if (dpy->Platform == _EGL_PLATFORM_WAYLAND && gdpy->native->buffer)
597 dpy->Extensions.MESA_drm_image = EGL_TRUE;
598
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;
602 #endif
603
604 #ifdef EGL_WL_bind_wayland_display
605 if (gdpy->native->wayland_bufmgr)
606 dpy->Extensions.WL_bind_wayland_display = EGL_TRUE;
607 #endif
608
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;
613 #endif
614 dpy->Extensions.NV_post_sub_buffer = EGL_TRUE;
615 }
616
617 if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
618 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
619 goto fail;
620 }
621
622 dpy->VersionMajor = 1;
623 dpy->VersionMinor = 4;
624
625 return EGL_TRUE;
626
627 fail:
628 if (gdpy)
629 egl_g3d_terminate(drv, dpy);
630 return EGL_FALSE;
631 }
632
633 static _EGLProc
634 egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
635 {
636 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
637 struct st_api *stapi = NULL;
638
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);
643
644 return (_EGLProc) ((stapi) ?
645 stapi->get_proc_address(stapi, procname) : NULL);
646 }
647
648 _EGLDriver *
649 egl_g3d_create_driver(const struct egl_g3d_loader *loader)
650 {
651 struct egl_g3d_driver *gdrv;
652
653 gdrv = CALLOC_STRUCT(egl_g3d_driver);
654 if (!gdrv)
655 return NULL;
656
657 gdrv->loader = loader;
658
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;
663
664 /* to be filled by the caller */
665 gdrv->base.Name = NULL;
666 gdrv->base.Unload = NULL;
667
668 return &gdrv->base;
669 }
670
671 void
672 egl_g3d_destroy_driver(_EGLDriver *drv)
673 {
674 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
675 FREE(gdrv);
676 }