Subversion Repositories Kolibri OS

Rev

Rev 4358 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/*
2
 * Mesa 3-D graphics library
3
 *
4
 * Copyright (C) 2009-2010 Chia-I Wu 
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included
14
 * in all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
 * DEALINGS IN THE SOFTWARE.
23
 */
24
 
25
#include "egldriver.h"
26
#include "eglcurrent.h"
27
#include "egllog.h"
28
 
29
#include "pipe/p_screen.h"
30
#include "util/u_memory.h"
31
#include "util/u_format.h"
32
#include "util/u_string.h"
33
#include "util/u_atomic.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
static void
42
egl_g3d_invalid_surface(struct native_display *ndpy,
43
                        struct native_surface *nsurf,
44
                        unsigned int seq_num)
45
{
46
   /* XXX not thread safe? */
47
   struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
48
 
49
   if (gsurf && gsurf->stfbi)
50
      p_atomic_inc(&gsurf->stfbi->stamp);
51
}
52
 
53
static struct pipe_screen *
54
egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd)
55
{
56
   _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
57
   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
58
   return gdpy->loader->create_drm_screen(name, fd);
59
}
60
 
61
static struct pipe_screen *
62
egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws)
63
{
64
   _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
65
   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
66
   return gdpy->loader->create_sw_screen(ws);
67
}
68
 
69
static struct pipe_resource *
70
egl_g3d_lookup_egl_image(struct native_display *ndpy, void *egl_image)
71
{
72
   _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
73
   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
74
   struct st_egl_image img;
75
   struct pipe_resource *resource = NULL;
76
 
77
   memset(&img, 0, sizeof(img));
78
   if (gdpy->smapi->get_egl_image(gdpy->smapi, egl_image, &img))
79
      resource = img.texture;
80
 
81
   return resource;
82
}
83
 
84
static const struct native_event_handler egl_g3d_native_event_handler = {
85
   egl_g3d_invalid_surface,
86
   egl_g3d_new_drm_screen,
87
   egl_g3d_new_sw_screen,
88
   egl_g3d_lookup_egl_image
89
};
90
 
91
/**
92
 * Get the native platform.
93
 */
94
static const struct native_platform *
95
egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat)
96
{
97
   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
98
 
99
   if (!gdrv->platforms[plat]) {
100
      const char *plat_name = NULL;
101
      const struct native_platform *nplat = NULL;
102
 
5080 serge 103
      plat_name = "DRM";
104
      nplat = native_get_drm_platform(&egl_g3d_native_event_handler);
4358 Serge 105
 
106
      if (!nplat)
107
         _eglLog(_EGL_WARNING, "unsupported platform %s", plat_name);
108
 
109
      gdrv->platforms[plat] = nplat;
110
   }
111
 
112
   return gdrv->platforms[plat];
113
}
114
 
115
#ifdef EGL_MESA_screen_surface
116
 
117
static void
118
egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
119
{
120
   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
121
   const struct native_connector **native_connectors;
122
   EGLint num_connectors, i;
123
 
124
   native_connectors =
125
      gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL);
126
   if (!num_connectors) {
127
      FREE(native_connectors);
128
      return;
129
   }
130
 
131
   for (i = 0; i < num_connectors; i++) {
132
      const struct native_connector *nconn = native_connectors[i];
133
      struct egl_g3d_screen *gscr;
134
      const struct native_mode **native_modes;
135
      EGLint num_modes, j;
136
 
137
      /* TODO support for hotplug */
138
      native_modes =
139
         gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes);
140
      if (!num_modes) {
141
         FREE(native_modes);
142
         continue;
143
      }
144
 
145
      gscr = CALLOC_STRUCT(egl_g3d_screen);
146
      if (!gscr) {
147
         FREE(native_modes);
148
         continue;
149
      }
150
 
151
      _eglInitScreen(&gscr->base, dpy, num_modes);
152
      for (j = 0; j < gscr->base.NumModes; j++) {
153
         const struct native_mode *nmode = native_modes[j];
154
         _EGLMode *mode = &gscr->base.Modes[j];
155
 
156
         mode->Width = nmode->width;
157
         mode->Height = nmode->height;
158
         mode->RefreshRate = nmode->refresh_rate;
159
         mode->Optimal = EGL_FALSE;
160
         mode->Interlaced = EGL_FALSE;
161
         /* no need to strdup() */
162
         mode->Name = nmode->desc;
163
      }
164
 
165
      gscr->native = nconn;
166
      gscr->native_modes = native_modes;
167
 
168
      _eglLinkScreen(&gscr->base);
169
   }
170
 
171
   FREE(native_connectors);
172
}
173
 
174
#endif /* EGL_MESA_screen_surface */
175
 
176
/**
177
 * Initialize and validate the EGL config attributes.
178
 */
179
static EGLBoolean
180
init_config_attributes(_EGLConfig *conf, const struct native_config *nconf,
181
                       EGLint api_mask, enum pipe_format depth_stencil_format,
182
                       EGLint preserve_buffer, EGLint max_swap_interval,
183
                       EGLBoolean pre_alpha)
184
{
185
   uint rgba[4], depth_stencil[2], buffer_size;
186
   EGLint surface_type;
187
   EGLint i;
188
 
189
   /* get the color and depth/stencil component sizes */
190
   assert(nconf->color_format != PIPE_FORMAT_NONE);
191
   buffer_size = 0;
192
   for (i = 0; i < 4; i++) {
193
      rgba[i] = util_format_get_component_bits(nconf->color_format,
194
            UTIL_FORMAT_COLORSPACE_RGB, i);
195
      buffer_size += rgba[i];
196
   }
197
   for (i = 0; i < 2; i++) {
198
      if (depth_stencil_format != PIPE_FORMAT_NONE) {
199
         depth_stencil[i] =
200
            util_format_get_component_bits(depth_stencil_format,
201
               UTIL_FORMAT_COLORSPACE_ZS, i);
202
      }
203
      else {
204
         depth_stencil[i] = 0;
205
      }
206
   }
207
 
208
   surface_type = 0x0;
209
   /* pixmap surfaces should be EGL_SINGLE_BUFFER */
210
   if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT)) {
211
      if (nconf->pixmap_bit)
212
         surface_type |= EGL_PIXMAP_BIT;
213
   }
214
   /* the others surfaces should be EGL_BACK_BUFFER (or settable) */
215
   if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) {
216
      if (nconf->window_bit)
217
         surface_type |= EGL_WINDOW_BIT;
218
#ifdef EGL_MESA_screen_surface
219
      if (nconf->scanout_bit)
220
         surface_type |= EGL_SCREEN_BIT_MESA;
221
#endif
222
      surface_type |= EGL_PBUFFER_BIT;
223
   }
224
 
225
   if (preserve_buffer)
226
      surface_type |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
227
 
228
   if (pre_alpha && rgba[3]) {
229
      surface_type |= EGL_VG_ALPHA_FORMAT_PRE_BIT;
230
      /* st/vega does not support premultiplied alpha yet */
231
      api_mask &= ~EGL_OPENVG_BIT;
232
   }
233
 
234
   conf->Conformant = api_mask;
235
   conf->RenderableType = api_mask;
236
 
237
   conf->RedSize = rgba[0];
238
   conf->GreenSize = rgba[1];
239
   conf->BlueSize = rgba[2];
240
   conf->AlphaSize = rgba[3];
241
   conf->BufferSize = buffer_size;
242
 
243
   conf->DepthSize = depth_stencil[0];
244
   conf->StencilSize = depth_stencil[1];
245
 
246
   /* st/vega will allocate the mask on demand */
247
   if (api_mask & EGL_OPENVG_BIT)
248
      conf->AlphaMaskSize = 8;
249
 
250
   conf->SurfaceType = surface_type;
251
 
252
   conf->NativeRenderable = EGL_TRUE;
253
   if (surface_type & EGL_WINDOW_BIT) {
254
      conf->NativeVisualID = nconf->native_visual_id;
255
      conf->NativeVisualType = nconf->native_visual_type;
256
   }
257
 
258
   if (surface_type & EGL_PBUFFER_BIT) {
259
      conf->BindToTextureRGB = EGL_TRUE;
260
      if (rgba[3])
261
         conf->BindToTextureRGBA = EGL_TRUE;
262
 
263
      conf->MaxPbufferWidth = 4096;
264
      conf->MaxPbufferHeight = 4096;
265
      conf->MaxPbufferPixels = 4096 * 4096;
266
   }
267
 
268
   conf->Level = nconf->level;
269
 
270
   if (nconf->transparent_rgb) {
271
      conf->TransparentType = EGL_TRANSPARENT_RGB;
272
      conf->TransparentRedValue = nconf->transparent_rgb_values[0];
273
      conf->TransparentGreenValue = nconf->transparent_rgb_values[1];
274
      conf->TransparentBlueValue = nconf->transparent_rgb_values[2];
275
   }
276
 
277
   conf->MinSwapInterval = 0;
278
   conf->MaxSwapInterval = max_swap_interval;
279
 
280
   return _eglValidateConfig(conf, EGL_FALSE);
281
}
282
 
283
/**
284
 * Initialize an EGL config from the native config.
285
 */
286
static EGLBoolean
287
egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy,
288
                    _EGLConfig *conf, const struct native_config *nconf,
289
                    enum pipe_format depth_stencil_format,
290
                    int preserve_buffer, int max_swap_interval,
291
                    int pre_alpha)
292
{
293
   struct egl_g3d_config *gconf = egl_g3d_config(conf);
294
   EGLint buffer_mask;
295
   EGLBoolean valid;
296
 
297
   buffer_mask = 0x0;
298
   if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT))
299
      buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
300
   if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT))
301
      buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
302
   if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_RIGHT))
303
      buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
304
   if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_RIGHT))
305
      buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
306
 
307
   gconf->stvis.buffer_mask = buffer_mask;
308
   gconf->stvis.color_format = nconf->color_format;
309
   gconf->stvis.depth_stencil_format = depth_stencil_format;
310
   gconf->stvis.accum_format = PIPE_FORMAT_NONE;
311
   gconf->stvis.samples = 0;
312
 
313
   /* will be overridden per surface */
314
   gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ?
315
      ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT;
316
 
317
   valid = init_config_attributes(&gconf->base,
318
         nconf, dpy->ClientAPIs, depth_stencil_format,
319
         preserve_buffer, max_swap_interval, pre_alpha);
320
   if (!valid) {
321
      _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id);
322
      return EGL_FALSE;
323
   }
324
 
325
   gconf->native = nconf;
326
 
327
   return EGL_TRUE;
328
}
329
 
330
/**
331
 * Get all interested depth/stencil formats of a display.
332
 */
333
static EGLint
334
egl_g3d_fill_depth_stencil_formats(_EGLDisplay *dpy,
335
                                   enum pipe_format formats[8])
336
{
337
   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
338
   struct pipe_screen *screen = gdpy->native->screen;
339
   const EGLint candidates[] = {
340
      1, PIPE_FORMAT_Z16_UNORM,
341
      1, PIPE_FORMAT_Z32_UNORM,
342
      2, PIPE_FORMAT_Z24_UNORM_S8_UINT, PIPE_FORMAT_S8_UINT_Z24_UNORM,
343
      2, PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_X8Z24_UNORM,
344
 
345
   };
346
   const EGLint *fmt = candidates;
347
   EGLint count;
348
 
349
   count = 0;
350
   formats[count++] = PIPE_FORMAT_NONE;
351
 
352
   while (*fmt) {
353
      EGLint i, n = *fmt++;
354
 
355
      /* pick the first supported format */
356
      for (i = 0; i < n; i++) {
357
         if (screen->is_format_supported(screen, fmt[i],
358
                  PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL)) {
359
            formats[count++] = fmt[i];
360
            break;
361
         }
362
      }
363
 
364
      fmt += n;
365
   }
366
 
367
   return count;
368
}
369
 
370
/**
371
 * Add configs to display and return the next config ID.
372
 */
373
static EGLint
374
egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
375
{
376
   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
377
   const struct native_config **native_configs;
378
   enum pipe_format depth_stencil_formats[8];
379
   int num_formats, num_configs, i, j;
380
   int preserve_buffer, max_swap_interval, premultiplied_alpha;
381
 
382
   native_configs = gdpy->native->get_configs(gdpy->native, &num_configs);
383
   if (!num_configs) {
384
      FREE(native_configs);
385
      return id;
386
   }
387
 
388
   preserve_buffer =
389
      gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESERVE_BUFFER);
390
   max_swap_interval =
391
      gdpy->native->get_param(gdpy->native, NATIVE_PARAM_MAX_SWAP_INTERVAL);
392
   premultiplied_alpha =
393
      gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PREMULTIPLIED_ALPHA);
394
 
395
   num_formats = egl_g3d_fill_depth_stencil_formats(dpy,
396
         depth_stencil_formats);
397
 
398
   for (i = 0; i < num_configs; i++) {
399
      for (j = 0; j < num_formats; j++) {
400
         struct egl_g3d_config *gconf;
401
 
402
         gconf = CALLOC_STRUCT(egl_g3d_config);
403
         if (gconf) {
404
            _eglInitConfig(&gconf->base, dpy, id);
405
            if (!egl_g3d_init_config(drv, dpy, &gconf->base,
406
                     native_configs[i], depth_stencil_formats[j],
407
                     preserve_buffer, max_swap_interval,
408
                     premultiplied_alpha)) {
409
               FREE(gconf);
410
               break;
411
            }
412
 
413
            _eglLinkConfig(&gconf->base);
414
            id++;
415
         }
416
      }
417
   }
418
 
419
   FREE(native_configs);
420
   return id;
421
}
422
 
423
static void
424
egl_g3d_free_config(void *conf)
425
{
426
   struct egl_g3d_config *gconf = egl_g3d_config((_EGLConfig *) conf);
427
   FREE(gconf);
428
}
429
 
430
static void
431
egl_g3d_free_screen(void *scr)
432
{
433
#ifdef EGL_MESA_screen_surface
434
   struct egl_g3d_screen *gscr = egl_g3d_screen((_EGLScreen *) scr);
435
   FREE(gscr->native_modes);
436
   FREE(gscr);
437
#endif
438
}
439
 
440
static EGLBoolean
441
egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
442
{
443
   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
444
 
445
   _eglReleaseDisplayResources(drv, dpy);
446
 
447
   if (dpy->Configs) {
448
      _eglDestroyArray(dpy->Configs, egl_g3d_free_config);
449
      dpy->Configs = NULL;
450
   }
451
   if (dpy->Screens) {
452
      _eglDestroyArray(dpy->Screens, egl_g3d_free_screen);
453
      dpy->Screens = NULL;
454
   }
455
 
456
   _eglCleanupDisplay(dpy);
457
 
458
   if (gdpy->smapi)
459
      egl_g3d_destroy_st_manager(gdpy->smapi);
460
 
461
   if (gdpy->native)
462
      gdpy->native->destroy(gdpy->native);
463
 
464
   FREE(gdpy);
465
   dpy->DriverData = NULL;
466
 
467
   return EGL_TRUE;
468
}
469
 
470
static EGLBoolean
471
egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy)
472
{
473
   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
474
   struct egl_g3d_display *gdpy;
475
   const struct native_platform *nplat;
476
 
477
   nplat = egl_g3d_get_platform(drv, dpy->Platform);
478
   if (!nplat)
479
      return EGL_FALSE;
480
 
481
   if (dpy->Options.TestOnly)
482
      return EGL_TRUE;
483
 
484
   gdpy = CALLOC_STRUCT(egl_g3d_display);
485
   if (!gdpy) {
486
      _eglError(EGL_BAD_ALLOC, "eglInitialize");
487
      goto fail;
488
   }
489
   gdpy->loader = gdrv->loader;
490
   dpy->DriverData = gdpy;
491
 
492
   _eglLog(_EGL_INFO, "use %s for display %p",
493
         nplat->name, dpy->PlatformDisplay);
494
   gdpy->native =
495
      nplat->create_display(dpy->PlatformDisplay, dpy->Options.UseFallback);
496
   if (!gdpy->native) {
497
      _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
498
      goto fail;
499
   }
500
   gdpy->native->user_data = (void *) dpy;
501
   if (!gdpy->native->init_screen(gdpy->native)) {
502
      _eglError(EGL_NOT_INITIALIZED,
503
            "eglInitialize(failed to initialize screen)");
504
      goto fail;
505
   }
506
 
507
   if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_DEFAULT_MASK)
508
      dpy->ClientAPIs |= EGL_OPENGL_BIT;
509
   if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES1_MASK)
510
      dpy->ClientAPIs |= EGL_OPENGL_ES_BIT;
511
   if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES2_MASK)
512
      dpy->ClientAPIs |= EGL_OPENGL_ES2_BIT;
513
   if (gdpy->loader->profile_masks[ST_API_OPENVG] & ST_PROFILE_DEFAULT_MASK)
514
      dpy->ClientAPIs |= EGL_OPENVG_BIT;
515
 
516
   gdpy->smapi = egl_g3d_create_st_manager(dpy);
517
   if (!gdpy->smapi) {
518
      _eglError(EGL_NOT_INITIALIZED,
519
            "eglInitialize(failed to create st manager)");
520
      goto fail;
521
   }
522
 
523
#ifdef EGL_MESA_screen_surface
524
   /* enable MESA_screen_surface before adding (and validating) configs */
525
   if (gdpy->native->modeset) {
526
      dpy->Extensions.MESA_screen_surface = EGL_TRUE;
527
      egl_g3d_add_screens(drv, dpy);
528
   }
529
#endif
530
 
531
   dpy->Extensions.KHR_image_base = EGL_TRUE;
532
   if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER))
533
      dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
534
 
535
   dpy->Extensions.KHR_reusable_sync = EGL_TRUE;
536
   dpy->Extensions.KHR_fence_sync = EGL_TRUE;
537
 
538
   dpy->Extensions.KHR_surfaceless_context = EGL_TRUE;
539
 
540
   if (dpy->Platform == _EGL_PLATFORM_DRM) {
541
      dpy->Extensions.MESA_drm_display = EGL_TRUE;
542
      if (gdpy->native->buffer)
543
         dpy->Extensions.MESA_drm_image = EGL_TRUE;
544
   }
545
 
5080 serge 546
//   if (dpy->Platform == _EGL_PLATFORM_WAYLAND && gdpy->native->buffer)
547
//      dpy->Extensions.MESA_drm_image = EGL_TRUE;
4358 Serge 548
 
549
 
550
   if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESENT_REGION) &&
551
       gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESERVE_BUFFER)) {
552
#ifdef EGL_NOK_swap_region
553
      dpy->Extensions.NOK_swap_region = EGL_TRUE;
554
#endif
555
      dpy->Extensions.NV_post_sub_buffer = EGL_TRUE;
556
   }
557
 
558
   if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
559
      _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
560
      goto fail;
561
   }
562
 
563
   dpy->VersionMajor = 1;
564
   dpy->VersionMinor = 4;
565
 
566
   return EGL_TRUE;
567
 
568
fail:
569
   if (gdpy)
570
      egl_g3d_terminate(drv, dpy);
571
   return EGL_FALSE;
572
}
573
 
574
static _EGLProc
575
egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
576
{
577
   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
578
   struct st_api *stapi = NULL;
579
 
580
   if (procname && procname[0] == 'v' && procname[1] == 'g')
581
      stapi = gdrv->loader->get_st_api(ST_API_OPENVG);
582
   else if (procname && procname[0] == 'g' && procname[1] == 'l')
583
      stapi = gdrv->loader->get_st_api(ST_API_OPENGL);
584
 
585
   return (_EGLProc) ((stapi) ?
586
         stapi->get_proc_address(stapi, procname) : NULL);
587
}
588
 
589
_EGLDriver *
590
egl_g3d_create_driver(const struct egl_g3d_loader *loader)
591
{
592
   struct egl_g3d_driver *gdrv;
593
 
594
   gdrv = CALLOC_STRUCT(egl_g3d_driver);
595
   if (!gdrv)
596
      return NULL;
597
 
598
   gdrv->loader = loader;
599
 
600
   egl_g3d_init_driver_api(&gdrv->base);
601
   gdrv->base.API.Initialize = egl_g3d_initialize;
602
   gdrv->base.API.Terminate = egl_g3d_terminate;
603
   gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
604
 
605
   /* to be filled by the caller */
606
   gdrv->base.Name = NULL;
607
   gdrv->base.Unload = NULL;
608
 
609
   return &gdrv->base;
610
}
611
 
612
void
613
egl_g3d_destroy_driver(_EGLDriver *drv)
614
{
615
   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
616
   FREE(gdrv);
617
}