blob: 85a76a871f063458a6f7d988d42bfa911799b098 [file] [log] [blame]
José Fonseca1b3d3752011-07-15 10:15:19 +01001/**************************************************************************
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
José Fonsecaa08d2752011-08-25 13:26:43 +010027/*
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
José Fonseca02873842011-10-27 13:23:17 +010035#include <assert.h>
José Fonseca1b3d3752011-07-15 10:15:19 +010036#include <string.h>
37#include <stdlib.h>
Brian Paul5023f662015-01-29 17:31:29 -070038#include <stdio.h>
José Fonseca1b3d3752011-07-15 10:15:19 +010039
40#include <string>
41#include <map>
42
José Fonsecaa08d2752011-08-25 13:26:43 +010043#include "glproc.hpp"
José Fonseca1b3d3752011-07-15 10:15:19 +010044#include "gltrace.hpp"
José Fonsecae0c55fd2015-01-26 22:46:13 +000045#include "os.hpp"
Brian Paul5023f662015-01-29 17:31:29 -070046#include "config.hpp"
José Fonseca1b3d3752011-07-15 10:15:19 +010047
48
49namespace gltrace {
50
51
52typedef std::map<std::string, const char *> ExtensionsMap;
53
54// Cache of the translated extensions strings
55static ExtensionsMap extensionsMap;
56
57
58// Additional extensions to be advertised
José Fonsecaf028a8f2012-02-15 23:33:35 +000059static const char *
60extraExtension_stringsFull[] = {
José Fonsecaa08d2752011-08-25 13:26:43 +010061 "GL_GREMEDY_string_marker",
62 "GL_GREMEDY_frame_terminator",
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -070063 "GL_ARB_debug_output",
64 "GL_AMD_debug_output",
65 "GL_KHR_debug",
José Fonseca7ff82412014-02-04 19:01:22 +000066 "GL_EXT_debug_marker",
67 "GL_EXT_debug_label",
José Fonseca631dbd12014-12-15 16:34:45 +000068 "GL_VMWX_map_buffer_debug",
José Fonsecaa08d2752011-08-25 13:26:43 +010069};
José Fonsecaf028a8f2012-02-15 23:33:35 +000070
71static const char *
72extraExtension_stringsES[] = {
José Fonsecad7cd6d02014-12-15 09:58:03 +000073 "GL_KHR_debug",
José Fonsecaf028a8f2012-02-15 23:33:35 +000074 "GL_EXT_debug_marker",
José Fonseca7ff82412014-02-04 19:01:22 +000075 "GL_EXT_debug_label",
José Fonsecaf028a8f2012-02-15 23:33:35 +000076};
77
78// Description of additional extensions we want to advertise
79struct ExtensionsDesc
80{
81 unsigned numStrings;
82 const char **strings;
83};
84
85#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
86
87const struct ExtensionsDesc
88extraExtensionsFull = {
89 ARRAY_SIZE(extraExtension_stringsFull),
90 extraExtension_stringsFull
91};
92
93const struct ExtensionsDesc
94extraExtensionsES = {
95 ARRAY_SIZE(extraExtension_stringsES),
96 extraExtension_stringsES
97};
98
99
100const struct ExtensionsDesc *
José Fonsecaef5d8372015-01-08 14:07:54 +0000101getExtraExtensions(const Context *ctx)
José Fonsecaf028a8f2012-02-15 23:33:35 +0000102{
José Fonsecab0c59722015-01-05 20:45:41 +0000103 switch (ctx->profile.api) {
104 case glprofile::API_GL:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000105 return &extraExtensionsFull;
José Fonsecab0c59722015-01-05 20:45:41 +0000106 case glprofile::API_GLES:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000107 return &extraExtensionsES;
108 default:
109 assert(0);
110 return &extraExtensionsFull;
111 }
112}
José Fonseca1b3d3752011-07-15 10:15:19 +0100113
114
115/**
116 * Translate the GL extensions string, adding new extensions.
117 */
José Fonsecaa08d2752011-08-25 13:26:43 +0100118static const char *
119overrideExtensionsString(const char *extensions)
José Fonseca1b3d3752011-07-15 10:15:19 +0100120{
José Fonsecaef5d8372015-01-08 14:07:54 +0000121 const Context *ctx = getContext();
122 const ExtensionsDesc *desc = getExtraExtensions(ctx);
José Fonseca7525e6f2011-09-28 09:04:56 +0100123 size_t i;
José Fonsecaa08d2752011-08-25 13:26:43 +0100124
José Fonseca1b3d3752011-07-15 10:15:19 +0100125 ExtensionsMap::const_iterator it = extensionsMap.find(extensions);
126 if (it != extensionsMap.end()) {
127 return it->second;
128 }
129
José Fonsecaf028a8f2012-02-15 23:33:35 +0000130 size_t extensionsLen = strlen(extensions);
José Fonseca1b3d3752011-07-15 10:15:19 +0100131
José Fonsecaf028a8f2012-02-15 23:33:35 +0000132 size_t extraExtensionsLen = 0;
133 for (i = 0; i < desc->numStrings; ++i) {
134 const char * extraExtension = desc->strings[i];
135 size_t extraExtensionLen = strlen(extraExtension);
136 extraExtensionsLen += extraExtensionLen + 1;
José Fonsecaa08d2752011-08-25 13:26:43 +0100137 }
138
José Fonseca02873842011-10-27 13:23:17 +0100139 // We use malloc memory instead of a std::string because we need to ensure
140 // that extensions strings will not move in memory as the extensionsMap is
141 // updated.
José Fonsecaf028a8f2012-02-15 23:33:35 +0000142 size_t newExtensionsLen = extensionsLen + 1 + extraExtensionsLen + 1;
143 char *newExtensions = (char *)malloc(newExtensionsLen);
144 if (!newExtensions) {
José Fonseca1b3d3752011-07-15 10:15:19 +0100145 return extensions;
146 }
147
José Fonsecaf028a8f2012-02-15 23:33:35 +0000148 if (extensionsLen) {
149 memcpy(newExtensions, extensions, extensionsLen);
José Fonseca1b3d3752011-07-15 10:15:19 +0100150
151 // Add space separator if necessary
José Fonsecaf028a8f2012-02-15 23:33:35 +0000152 if (newExtensions[extensionsLen - 1] != ' ') {
153 newExtensions[extensionsLen++] = ' ';
José Fonseca1b3d3752011-07-15 10:15:19 +0100154 }
155 }
156
José Fonsecaf028a8f2012-02-15 23:33:35 +0000157 for (i = 0; i < desc->numStrings; ++i) {
158 const char * extraExtension = desc->strings[i];
159 size_t extraExtensionLen = strlen(extraExtension);
160 memcpy(newExtensions + extensionsLen, extraExtension, extraExtensionLen);
161 extensionsLen += extraExtensionLen;
162 newExtensions[extensionsLen++] = ' ';
José Fonsecaa08d2752011-08-25 13:26:43 +0100163 }
José Fonsecaf028a8f2012-02-15 23:33:35 +0000164 newExtensions[extensionsLen++] = '\0';
165 assert(extensionsLen <= newExtensionsLen);
José Fonseca1b3d3752011-07-15 10:15:19 +0100166
José Fonsecaf028a8f2012-02-15 23:33:35 +0000167 extensionsMap[extensions] = newExtensions;
José Fonseca1b3d3752011-07-15 10:15:19 +0100168
José Fonsecaf028a8f2012-02-15 23:33:35 +0000169 return newExtensions;
José Fonseca1b3d3752011-07-15 10:15:19 +0100170}
171
172
José Fonsecaa08d2752011-08-25 13:26:43 +0100173const GLubyte *
José Fonseca632a78d2012-04-19 07:18:59 +0100174_glGetString_override(GLenum name)
José Fonsecaa08d2752011-08-25 13:26:43 +0100175{
Brian Paul5023f662015-01-29 17:31:29 -0700176 const configuration *config = getConfig();
177 const GLubyte *result;
178
179 // Try getting the override string value first
180 result = getConfigString(config, name);
181 if (!result) {
182 // Ask the real GL library
183 result = _glGetString(name);
184 }
José Fonsecaa08d2752011-08-25 13:26:43 +0100185
186 if (result) {
187 switch (name) {
188 case GL_EXTENSIONS:
189 result = (const GLubyte *)overrideExtensionsString((const char *)result);
190 break;
191 default:
192 break;
193 }
194 }
195
196 return result;
197}
198
199
José Fonseca76f49b72015-02-05 16:34:21 +0000200static void
201getInteger(const configuration *config,
202 GLenum pname, GLint *params)
203{
José Fonsecae0c55fd2015-01-26 22:46:13 +0000204 // Disable ARB_get_program_binary
205 switch (pname) {
206 case GL_NUM_PROGRAM_BINARY_FORMATS:
207 if (params) {
Jose Fonsecaa245de62015-07-21 13:32:14 +0100208 GLint numProgramBinaryFormats = 0;
209 _glGetIntegerv(pname, &numProgramBinaryFormats);
210 if (numProgramBinaryFormats > 0) {
José Fonsecae0c55fd2015-01-26 22:46:13 +0000211 os::log("apitrace: warning: hiding program binary formats (https://github.com/apitrace/apitrace/issues/316)\n");
José Fonsecae0c55fd2015-01-26 22:46:13 +0000212 }
Jose Fonsecaa245de62015-07-21 13:32:14 +0100213 params[0] = 0;
José Fonsecae0c55fd2015-01-26 22:46:13 +0000214 }
215 return;
216 case GL_PROGRAM_BINARY_FORMATS:
217 // params might be NULL here, as we returned 0 for
218 // GL_NUM_PROGRAM_BINARY_FORMATS.
219 return;
220 }
221
José Fonseca76f49b72015-02-05 16:34:21 +0000222 if (params) {
223 *params = getConfigInteger(config, pname);
224 if (*params != 0) {
225 return;
226 }
227 }
228
229 // Ask the real GL library
230 _glGetIntegerv(pname, params);
231}
232
233
José Fonsecae0c55fd2015-01-26 22:46:13 +0000234/**
235 * TODO: To be thorough, we should override all glGet*v.
236 */
José Fonsecaa08d2752011-08-25 13:26:43 +0100237void
José Fonseca632a78d2012-04-19 07:18:59 +0100238_glGetIntegerv_override(GLenum pname, GLint *params)
José Fonsecaa08d2752011-08-25 13:26:43 +0100239{
Brian Paul5023f662015-01-29 17:31:29 -0700240 const configuration *config = getConfig();
241
José Fonseca76f49b72015-02-05 16:34:21 +0000242 /*
243 * It's important to handle params==NULL correctly here, which can and does
244 * happen, particularly when pname is GL_COMPRESSED_TEXTURE_FORMATS or
245 * GL_PROGRAM_BINARY_FORMATS and the implementation returns 0 for
246 * GL_NUM_COMPRESSED_TEXTURE_FORMATS or GL_NUM_PROGRAM_BINARY_FORMATS, as
247 * the application ends up calling `params = malloc(0)` or `param = new
248 * GLint[0]` which can yield NULL.
249 */
250
251 getInteger(config, pname, params);
José Fonsecaa08d2752011-08-25 13:26:43 +0100252
253 if (params) {
José Fonsecaef5d8372015-01-08 14:07:54 +0000254 const Context *ctx;
José Fonsecaa08d2752011-08-25 13:26:43 +0100255 switch (pname) {
256 case GL_NUM_EXTENSIONS:
José Fonsecaef5d8372015-01-08 14:07:54 +0000257 ctx = getContext();
258 if (ctx->profile.major >= 3) {
259 const ExtensionsDesc *desc = getExtraExtensions(ctx);
José Fonsecaf028a8f2012-02-15 23:33:35 +0000260 *params += desc->numStrings;
261 }
José Fonsecaa08d2752011-08-25 13:26:43 +0100262 break;
José Fonsecad7730002013-10-24 18:55:19 +0100263 case GL_MAX_LABEL_LENGTH:
264 /* We provide our default implementation of KHR_debug when the
265 * driver does not. So return something sensible here.
266 */
267 if (params[0] == 0) {
268 params[0] = 256;
269 }
270 break;
José Fonsecaa08d2752011-08-25 13:26:43 +0100271 }
272 }
273}
274
275
276const GLubyte *
José Fonseca632a78d2012-04-19 07:18:59 +0100277_glGetStringi_override(GLenum name, GLuint index)
José Fonsecaa08d2752011-08-25 13:26:43 +0100278{
Brian Paul5023f662015-01-29 17:31:29 -0700279 const configuration *config = getConfig();
José Fonsecaef5d8372015-01-08 14:07:54 +0000280 const Context *ctx = getContext();
Brian Paul5023f662015-01-29 17:31:29 -0700281 const GLubyte *retVal;
José Fonsecaef5d8372015-01-08 14:07:54 +0000282
283 if (ctx->profile.major >= 3) {
284 switch (name) {
285 case GL_EXTENSIONS:
286 {
287 const ExtensionsDesc *desc = getExtraExtensions(ctx);
288 GLint numExtensions = 0;
José Fonseca76f49b72015-02-05 16:34:21 +0000289 getInteger(config, GL_NUM_EXTENSIONS, &numExtensions);
José Fonsecaef5d8372015-01-08 14:07:54 +0000290 if ((GLuint)numExtensions <= index && index < (GLuint)numExtensions + desc->numStrings) {
291 return (const GLubyte *)desc->strings[index - (GLuint)numExtensions];
292 }
José Fonsecaa08d2752011-08-25 13:26:43 +0100293 }
José Fonsecaef5d8372015-01-08 14:07:54 +0000294 break;
295 default:
296 break;
José Fonsecaa08d2752011-08-25 13:26:43 +0100297 }
José Fonsecaa08d2752011-08-25 13:26:43 +0100298 }
299
Brian Paul5023f662015-01-29 17:31:29 -0700300 retVal = getConfigStringi(config, name, index);
301 if (retVal)
302 return retVal;
303
José Fonseca632a78d2012-04-19 07:18:59 +0100304 return _glGetStringi(name, index);
José Fonsecaa08d2752011-08-25 13:26:43 +0100305}
306
307
José Fonseca1b3d3752011-07-15 10:15:19 +0100308} /* namespace gltrace */
309