]> git.cworth.org Git - apitrace/blob - wrappers/egltrace.py
Move tracers to wrappers subdirectory.
[apitrace] / wrappers / egltrace.py
1 ##########################################################################
2 #
3 # Copyright 2011 LunarG, Inc.
4 # All Rights Reserved.
5 #
6 # Based on glxtrace.py, which has
7 #
8 #   Copyright 2011 Jose Fonseca
9 #   Copyright 2008-2010 VMware, Inc.
10 #
11 # Permission is hereby granted, free of charge, to any person obtaining a copy
12 # of this software and associated documentation files (the "Software"), to deal
13 # in the Software without restriction, including without limitation the rights
14 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 # copies of the Software, and to permit persons to whom the Software is
16 # furnished to do so, subject to the following conditions:
17 #
18 # The above copyright notice and this permission notice shall be included in
19 # all copies or substantial portions of the Software.
20 #
21 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 # THE SOFTWARE.
28 #
29 ##########################################################################/
30
31
32 """EGL tracing generator."""
33
34
35 from gltrace import GlTracer
36 from dispatch import function_pointer_type, function_pointer_value
37 from specs.stdapi import API
38 from specs.glapi import glapi
39 from specs.eglapi import eglapi
40 from specs.glesapi import glesapi
41
42
43 class EglTracer(GlTracer):
44
45     def isFunctionPublic(self, function):
46         # The symbols visible in libEGL.so can vary, so expose them all
47         return True
48
49     def traceFunctionImplBody(self, function):
50         GlTracer.traceFunctionImplBody(self, function)
51
52         if function.name == 'eglMakeCurrent':
53             print '    // update the profile'
54             print '    if (ctx != EGL_NO_CONTEXT) {'
55             print '        EGLint api = EGL_OPENGL_ES_API, version = 1;'
56             print '        gltrace::Context *tr = gltrace::getContext();'
57             print '        __eglQueryContext(dpy, ctx, EGL_CONTEXT_CLIENT_TYPE, &api);'
58             print '        __eglQueryContext(dpy, ctx, EGL_CONTEXT_CLIENT_VERSION, &version);'
59             print '        if (api == EGL_OPENGL_API)'
60             print '            tr->profile = gltrace::PROFILE_COMPAT;'
61             print '        else if (version == 1)'
62             print '            tr->profile = gltrace::PROFILE_ES1;'
63             print '        else'
64             print '            tr->profile = gltrace::PROFILE_ES2;'
65             print '    }'
66
67     def wrapRet(self, function, instance):
68         GlTracer.wrapRet(self, function, instance)
69
70         if function.name == "eglGetProcAddress":
71             print '    %s = __unwrap_proc_addr(procname, %s);' % (instance, instance)
72
73
74 if __name__ == '__main__':
75     print '#include <stdlib.h>'
76     print '#include <string.h>'
77     print '#include <dlfcn.h>'
78     print
79     print '#include "trace_writer_local.hpp"'
80     print
81     print '// To validate our prototypes'
82     print '#define GL_GLEXT_PROTOTYPES'
83     print '#define EGL_EGLEXT_PROTOTYPES'
84     print
85     print '#include "glproc.hpp"'
86     print '#include "glsize.hpp"'
87     print
88     print 'static __eglMustCastToProperFunctionPointerType __unwrap_proc_addr(const char * procname, __eglMustCastToProperFunctionPointerType procPtr);'
89     print
90
91     api = API()
92     api.addApi(eglapi)
93     api.addApi(glapi)
94     api.addApi(glesapi)
95     tracer = EglTracer()
96     tracer.trace_api(api)
97
98     print 'static __eglMustCastToProperFunctionPointerType __unwrap_proc_addr(const char * procname, __eglMustCastToProperFunctionPointerType procPtr) {'
99     print '    if (!procPtr) {'
100     print '        return procPtr;'
101     print '    }'
102     for f in api.functions:
103         ptype = function_pointer_type(f)
104         pvalue = function_pointer_value(f)
105         print '    if (!strcmp("%s", procname)) {' % f.name
106         print '        %s = (%s)procPtr;' % (pvalue, ptype)
107         print '        return (__eglMustCastToProperFunctionPointerType)&%s;' % (f.name,)
108         print '    }'
109     print '    os::log("apitrace: warning: unknown function \\"%s\\"\\n", procname);'
110     print '    return procPtr;'
111     print '}'
112     print
113     print r'''
114
115
116 /*
117  * Android does not support LD_PRELOAD.
118  */
119 #if !defined(ANDROID)
120
121
122 /*
123  * Invoke the true dlopen() function.
124  */
125 static void *__dlopen(const char *filename, int flag)
126 {
127     typedef void * (*PFNDLOPEN)(const char *, int);
128     static PFNDLOPEN dlopen_ptr = NULL;
129
130     if (!dlopen_ptr) {
131         dlopen_ptr = (PFNDLOPEN)dlsym(RTLD_NEXT, "dlopen");
132         if (!dlopen_ptr) {
133             os::log("apitrace: error: dlsym(RTLD_NEXT, \"dlopen\") failed\n");
134             return NULL;
135         }
136     }
137
138     return dlopen_ptr(filename, flag);
139 }
140
141
142 /*
143  * Several applications, such as Quake3, use dlopen("libGL.so.1"), but
144  * LD_PRELOAD does not intercept symbols obtained via dlopen/dlsym, therefore
145  * we need to intercept the dlopen() call here, and redirect to our wrapper
146  * shared object.
147  */
148 extern "C" PUBLIC
149 void * dlopen(const char *filename, int flag)
150 {
151     bool intercept = false;
152
153     if (filename) {
154         intercept =
155             strcmp(filename, "libEGL.so") == 0 ||
156             strcmp(filename, "libEGL.so.1") == 0 ||
157             strcmp(filename, "libGLESv1_CM.so") == 0 ||
158             strcmp(filename, "libGLESv1_CM.so.1") == 0 ||
159             strcmp(filename, "libGLESv2.so") == 0 ||
160             strcmp(filename, "libGLESv2.so.2") == 0 ||
161             strcmp(filename, "libGL.so") == 0 ||
162             strcmp(filename, "libGL.so.1") == 0;
163
164         if (intercept) {
165             os::log("apitrace: redirecting dlopen(\"%s\", 0x%x)\n", filename, flag);
166
167             /* The current dispatch implementation relies on core entry-points to be globally available, so force this.
168              *
169              * TODO: A better approach would be note down the entry points here and
170              * use them latter. Another alternative would be to reopen the library
171              * with RTLD_NOLOAD | RTLD_GLOBAL.
172              */
173             flag &= ~RTLD_LOCAL;
174             flag |= RTLD_GLOBAL;
175         }
176     }
177
178     void *handle = __dlopen(filename, flag);
179
180     if (intercept) {
181         // Get the file path for our shared object, and use it instead
182         static int dummy = 0xdeedbeef;
183         Dl_info info;
184         if (dladdr(&dummy, &info)) {
185             handle = __dlopen(info.dli_fname, flag);
186         } else {
187             os::log("apitrace: warning: dladdr() failed\n");
188         }
189     }
190
191     return handle;
192 }
193
194
195 #endif /* !ANDROID */
196
197
198
199 '''