texenvprogram: fix for ARB_draw_buffers.
[mesa.git] / src / gallium / state_trackers / egl / common / egl_st.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
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 #include <dlfcn.h>
26 #include "pipe/p_compiler.h"
27 #include "util/u_memory.h"
28 #include "egllog.h"
29 #include "EGL/egl.h" /* for EGL_api_BIT */
30
31 #include "egl_st.h"
32
33 #ifndef HAVE_DLADDR
34 #define HAVE_DLADDR 1
35 #endif
36
37 #if HAVE_DLADDR
38
39 static const char *
40 egl_g3d_st_names[] = {
41 #define ST_PUBLIC(name, ...) #name,
42 #include "st_public_tmp.h"
43 NULL
44 };
45
46 static boolean
47 egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym)
48 {
49 st_proc *procs = (st_proc *) stapi;
50 void *handle;
51 Dl_info info;
52 const char **name;
53
54 if (!dladdr(sym, &info))
55 return FALSE;
56 handle = dlopen(info.dli_fname, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE);
57 if (!handle)
58 return FALSE;
59
60 for (name = egl_g3d_st_names; *name; name++) {
61 st_proc proc = (st_proc) dlsym(handle, *name);
62 if (!proc) {
63 _eglLog(_EGL_WARNING, "%s is missing in %s", *name, info.dli_fname);
64 memset(stapi, 0, sizeof(*stapi));
65 dlclose(handle);
66 return FALSE;
67 }
68 *procs++ = proc;
69 }
70
71 dlclose(handle);
72 return TRUE;
73 }
74
75 #else /* HAVE_DLADDR */
76
77 static boolean
78 egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym)
79 {
80 #define ST_PUBLIC(name, ...) stapi->name = name;
81 #include "st_public_tmp.h"
82 return TRUE;
83 }
84
85 #endif /* HAVE_DLADDR */
86
87 static boolean
88 egl_g3d_init_st(struct egl_g3d_st *stapi, const char *api)
89 {
90 void *handle, *sym;
91 boolean res = FALSE;
92
93 /* already initialized */
94 if (stapi->st_notify_swapbuffers != NULL)
95 return TRUE;
96
97 handle = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL);
98 if (!handle)
99 return FALSE;
100
101 sym = dlsym(handle, api);
102 if (sym && egl_g3d_fill_st(stapi, sym))
103 res = TRUE;
104
105 dlclose(handle);
106 return res;
107 }
108
109 static struct {
110 const char *symbol;
111 EGLint api_bit;
112 } egl_g3d_st_info[NUM_EGL_G3D_STS] = {
113 { "st_api_OpenGL_ES1", EGL_OPENGL_ES_BIT },
114 { "st_api_OpenVG", EGL_OPENVG_BIT },
115 { "st_api_OpenGL_ES2", EGL_OPENGL_ES2_BIT },
116 { "st_api_OpenGL", EGL_OPENGL_BIT },
117 };
118
119 const struct egl_g3d_st *
120 egl_g3d_get_st(enum egl_g3d_st_api api)
121 {
122 static struct egl_g3d_st all_trackers[NUM_EGL_G3D_STS];
123
124 if (egl_g3d_init_st(&all_trackers[api], egl_g3d_st_info[api].symbol)) {
125 all_trackers[api].api_bit = egl_g3d_st_info[api].api_bit;
126 return &all_trackers[api];
127 }
128 else {
129 return NULL;
130 }
131 }