]> git.cworth.org Git - apitrace/blob - wrappers/glcaps.cpp
Use skiplist-based FastCallSet within trace::CallSet
[apitrace] / wrappers / glcaps.cpp
1 /**************************************************************************
2  *
3  * Copyright 2011 Jose Fonseca
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * 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 THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26
27 /*
28  * Manipulation of GL extensions.
29  *
30  * So far we insert GREMEDY extensions, but in the future we could also clamp
31  * the GL extensions to core GL versions here.
32  */
33
34
35 #include <assert.h>
36 #include <string.h>
37 #include <stdlib.h>
38
39 #include <string>
40 #include <map>
41
42 #include "glproc.hpp"
43 #include "gltrace.hpp"
44
45
46 namespace gltrace {
47
48
49 typedef std::map<std::string, const char *> ExtensionsMap;
50
51 // Cache of the translated extensions strings
52 static ExtensionsMap extensionsMap;
53
54
55 // Additional extensions to be advertised
56 static const char *
57 extraExtension_stringsFull[] = {
58     "GL_GREMEDY_string_marker",
59     "GL_GREMEDY_frame_terminator",
60 };
61
62 static const char *
63 extraExtension_stringsES[] = {
64     "GL_EXT_debug_marker",
65 };
66
67 // Description of additional extensions we want to advertise
68 struct ExtensionsDesc
69 {
70     unsigned numStrings;
71     const char **strings;
72 };
73
74 #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
75
76 const struct ExtensionsDesc
77 extraExtensionsFull = {
78     ARRAY_SIZE(extraExtension_stringsFull),
79     extraExtension_stringsFull
80 };
81
82 const struct ExtensionsDesc
83 extraExtensionsES = {
84     ARRAY_SIZE(extraExtension_stringsES),
85     extraExtension_stringsES
86 };
87
88
89 const struct ExtensionsDesc *
90 getExtraExtensions(void)
91 {
92     Context *ctx = getContext();
93
94     switch (ctx->profile) {
95     case PROFILE_COMPAT:
96         return &extraExtensionsFull;
97     case PROFILE_ES1:
98     case PROFILE_ES2:
99         return &extraExtensionsES;
100     default:
101         assert(0);
102         return &extraExtensionsFull;
103     }
104 }
105
106
107 /**
108  * Translate the GL extensions string, adding new extensions.
109  */
110 static const char *
111 overrideExtensionsString(const char *extensions)
112 {
113     const ExtensionsDesc *desc = getExtraExtensions();
114     size_t i;
115
116     ExtensionsMap::const_iterator it = extensionsMap.find(extensions);
117     if (it != extensionsMap.end()) {
118         return it->second;
119     }
120
121     size_t extensionsLen = strlen(extensions);
122
123     size_t extraExtensionsLen = 0;
124     for (i = 0; i < desc->numStrings; ++i) {
125         const char * extraExtension = desc->strings[i];
126         size_t extraExtensionLen = strlen(extraExtension);
127         extraExtensionsLen += extraExtensionLen + 1;
128     }
129
130     // We use malloc memory instead of a std::string because we need to ensure
131     // that extensions strings will not move in memory as the extensionsMap is
132     // updated.
133     size_t newExtensionsLen = extensionsLen + 1 + extraExtensionsLen + 1;
134     char *newExtensions = (char *)malloc(newExtensionsLen);
135     if (!newExtensions) {
136         return extensions;
137     }
138
139     if (extensionsLen) {
140         memcpy(newExtensions, extensions, extensionsLen);
141
142         // Add space separator if necessary
143         if (newExtensions[extensionsLen - 1] != ' ') {
144             newExtensions[extensionsLen++] = ' ';
145         }
146     }
147
148     for (i = 0; i < desc->numStrings; ++i) {
149         const char * extraExtension = desc->strings[i];
150         size_t extraExtensionLen = strlen(extraExtension);
151         memcpy(newExtensions + extensionsLen, extraExtension, extraExtensionLen);
152         extensionsLen += extraExtensionLen;
153         newExtensions[extensionsLen++] = ' ';
154     }
155     newExtensions[extensionsLen++] = '\0';
156     assert(extensionsLen <= newExtensionsLen);
157
158     extensionsMap[extensions] = newExtensions;
159
160     return newExtensions;
161 }
162
163
164 const GLubyte *
165 _glGetString_override(GLenum name)
166 {
167     const GLubyte *result = _glGetString(name);
168
169     if (result) {
170         switch (name) {
171         case GL_EXTENSIONS:
172             result = (const GLubyte *)overrideExtensionsString((const char *)result);
173             break;
174         default:
175             break;
176         }
177     }
178
179     return result;
180 }
181
182
183 void
184 _glGetIntegerv_override(GLenum pname, GLint *params)
185 {
186     _glGetIntegerv(pname, params);
187
188     if (params) {
189         switch (pname) {
190         case GL_NUM_EXTENSIONS:
191             {
192                 const ExtensionsDesc *desc = getExtraExtensions();
193                 *params += desc->numStrings;
194             }
195             break;
196         default:
197             break;
198         }
199     }
200 }
201
202
203 const GLubyte *
204 _glGetStringi_override(GLenum name, GLuint index)
205 {
206     switch (name) {
207     case GL_EXTENSIONS:
208         {
209             const ExtensionsDesc *desc = getExtraExtensions();
210             GLint numExtensions = 0;
211             _glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
212             if ((GLuint)numExtensions <= index && index < (GLuint)numExtensions + desc->numStrings) {
213                 return (const GLubyte *)desc->strings[index - (GLuint)numExtensions];
214             }
215         }
216         break;
217     default:
218         break;
219     }
220
221     return _glGetStringi(name, index);
222 }
223
224
225 } /* namespace gltrace */
226