~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/mesa/main/extensions.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Mesa 3-D graphics library
3
 
 *
4
 
 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5
 
 * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
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
 
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21
 
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22
 
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 
 * OTHER DEALINGS IN THE SOFTWARE.
24
 
 */
25
 
 
26
 
 
27
 
/**
28
 
 * \file
29
 
 * \brief Extension handling
30
 
 */
31
 
 
32
 
#include "util/os_misc.h"
33
 
 
34
 
#include "glheader.h"
35
 
 
36
 
#include "context.h"
37
 
#include "extensions.h"
38
 
#include "macros.h"
39
 
#include "mtypes.h"
40
 
 
41
 
struct gl_extensions _mesa_extension_override_enables;
42
 
struct gl_extensions _mesa_extension_override_disables;
43
 
 
44
 
#define MAX_UNRECOGNIZED_EXTENSIONS 16
45
 
static struct {
46
 
   char *env;
47
 
   const char *names[MAX_UNRECOGNIZED_EXTENSIONS];
48
 
} unrecognized_extensions;
49
 
 
50
 
/**
51
 
 * Given a member \c x of struct gl_extensions, return offset of
52
 
 * \c x in bytes.
53
 
 */
54
 
#define o(x) offsetof(struct gl_extensions, x)
55
 
 
56
 
static int
57
 
extension_name_compare(const void *name, const void *elem)
58
 
{
59
 
   const struct mesa_extension *entry = elem;
60
 
   return strcmp(name, entry->name);
61
 
}
62
 
 
63
 
/**
64
 
 * Given an extension name, lookup up the corresponding member of struct
65
 
 * gl_extensions and return that member's index.  If the name is
66
 
 * not found in the \c _mesa_extension_table, return -1.
67
 
 *
68
 
 * \param name Name of extension.
69
 
 * \return Index of member in struct gl_extensions.
70
 
 */
71
 
static int
72
 
name_to_index(const char* name)
73
 
{
74
 
   const struct mesa_extension *entry;
75
 
 
76
 
   if (!name)
77
 
      return -1;
78
 
 
79
 
   entry = bsearch(name,
80
 
                   _mesa_extension_table, MESA_EXTENSION_COUNT,
81
 
                   sizeof(_mesa_extension_table[0]),
82
 
                   extension_name_compare);
83
 
 
84
 
   if (entry)
85
 
      return entry - _mesa_extension_table;
86
 
 
87
 
   return -1;
88
 
}
89
 
 
90
 
/**
91
 
 * Overrides extensions in \c ctx based on the values in
92
 
 * _mesa_extension_override_enables and _mesa_extension_override_disables.
93
 
 */
94
 
void
95
 
_mesa_override_extensions(struct gl_context *ctx)
96
 
{
97
 
   unsigned i;
98
 
   const GLboolean *enables =
99
 
      (GLboolean*) &_mesa_extension_override_enables;
100
 
   const GLboolean *disables =
101
 
      (GLboolean*) &_mesa_extension_override_disables;
102
 
   GLboolean *ctx_ext = (GLboolean*)&ctx->Extensions;
103
 
 
104
 
   for (i = 0; i < MESA_EXTENSION_COUNT; ++i) {
105
 
      size_t offset = _mesa_extension_table[i].offset;
106
 
 
107
 
      assert(!enables[offset] || !disables[offset]);
108
 
      if (enables[offset]) {
109
 
         ctx_ext[offset] = 1;
110
 
      } else if (disables[offset]) {
111
 
         ctx_ext[offset] = 0;
112
 
      }
113
 
   }
114
 
}
115
 
 
116
 
/**
117
 
 * Either enable or disable the named extension.
118
 
 * \return offset of extensions withint `ext' or 0 if extension is not known
119
 
 */
120
 
static size_t
121
 
set_extension(struct gl_extensions *ext, int i, GLboolean state)
122
 
{
123
 
   size_t offset;
124
 
 
125
 
   offset = i < 0 ? 0 : _mesa_extension_table[i].offset;
126
 
   if (offset != 0 && (offset != o(dummy_true) || state != GL_FALSE)) {
127
 
      ((GLboolean *) ext)[offset] = state;
128
 
   }
129
 
 
130
 
   return offset;
131
 
}
132
 
 
133
 
 
134
 
/**
135
 
 * \brief Free string pointed by unrecognized_extensions
136
 
 *
137
 
 * This string is allocated early during the first context creation by
138
 
 * _mesa_one_time_init_extension_overrides.
139
 
 */
140
 
static void
141
 
free_unknown_extensions_strings(void)
142
 
{
143
 
   free(unrecognized_extensions.env);
144
 
   for (int i = 0; i < MAX_UNRECOGNIZED_EXTENSIONS; ++i)
145
 
      unrecognized_extensions.names[i] = NULL;
146
 
}
147
 
 
148
 
 
149
 
/**
150
 
 * \brief Initialize extension override tables based on \c override
151
 
 *
152
 
 * This should be called one time early during first context initialization.
153
 
 
154
 
 * \c override is a space-separated list of extensions to
155
 
 * enable or disable. The list is processed thus:
156
 
 *    - Enable recognized extension names that are prefixed with '+'.
157
 
 *    - Disable recognized extension names that are prefixed with '-'.
158
 
 *    - Enable recognized extension names that are not prefixed.
159
 
 *    - Collect unrecognized extension names in a new string.
160
 
 */
161
 
void
162
 
_mesa_one_time_init_extension_overrides(const char *override)
163
 
{
164
 
   char *env;
165
 
   char *ext;
166
 
   size_t offset;
167
 
   unsigned unknown_ext = 0;
168
 
 
169
 
   memset(&_mesa_extension_override_enables, 0, sizeof(struct gl_extensions));
170
 
   memset(&_mesa_extension_override_disables, 0, sizeof(struct gl_extensions));
171
 
 
172
 
   if (override == NULL || override[0] == '\0') {
173
 
      return;
174
 
   }
175
 
 
176
 
   /* Copy 'override' because strtok() is destructive. */
177
 
   env = strdup(override);
178
 
 
179
 
   if (env == NULL)
180
 
      return;
181
 
 
182
 
   for (ext = strtok(env, " "); ext != NULL; ext = strtok(NULL, " ")) {
183
 
      int enable;
184
 
      int i;
185
 
      bool recognized;
186
 
      switch (ext[0]) {
187
 
      case '+':
188
 
         enable = 1;
189
 
         ++ext;
190
 
         break;
191
 
      case '-':
192
 
         enable = 0;
193
 
         ++ext;
194
 
         break;
195
 
      default:
196
 
         enable = 1;
197
 
         break;
198
 
      }
199
 
 
200
 
      i = name_to_index(ext);
201
 
      offset = set_extension(&_mesa_extension_override_enables, i, enable);
202
 
      offset = set_extension(&_mesa_extension_override_disables, i, !enable);
203
 
      if (offset != 0)
204
 
         recognized = true;
205
 
      else
206
 
         recognized = false;
207
 
 
208
 
      if (!enable && recognized && offset <= 1) {
209
 
         printf("Warning: extension '%s' cannot be disabled\n", ext);
210
 
         offset = set_extension(&_mesa_extension_override_disables, i, 0);
211
 
      }
212
 
 
213
 
      if (!recognized && enable) {
214
 
         if (unknown_ext >= MAX_UNRECOGNIZED_EXTENSIONS) {
215
 
            static bool warned;
216
 
 
217
 
            if (!warned) {
218
 
               warned = true;
219
 
               _mesa_problem(NULL, "Trying to enable too many unknown extension. "
220
 
                                   "Only the first %d will be honoured",
221
 
                                   MAX_UNRECOGNIZED_EXTENSIONS);
222
 
            }
223
 
         } else {
224
 
            unrecognized_extensions.names[unknown_ext] = ext;
225
 
            unknown_ext++;
226
 
            _mesa_problem(NULL, "Trying to enable unknown extension: %s", ext);
227
 
         }
228
 
      }
229
 
   }
230
 
 
231
 
   if (!unknown_ext) {
232
 
      free(env);
233
 
   } else {
234
 
      unrecognized_extensions.env = env;
235
 
      atexit(free_unknown_extensions_strings);
236
 
   }
237
 
}
238
 
 
239
 
 
240
 
/**
241
 
 * \brief Initialize extension tables and enable default extensions.
242
 
 *
243
 
 * This should be called during context initialization.
244
 
 * Note: Sets gl_extensions.dummy_true to true.
245
 
 */
246
 
void
247
 
_mesa_init_extensions(struct gl_extensions *extensions)
248
 
{
249
 
   GLboolean *base = (GLboolean *) extensions;
250
 
   GLboolean *sentinel = base + o(extension_sentinel);
251
 
   GLboolean *i;
252
 
 
253
 
   /* First, turn all extensions off. */
254
 
   for (i = base; i != sentinel; ++i)
255
 
      *i = GL_FALSE;
256
 
 
257
 
   /* Then, selectively turn default extensions on. */
258
 
   extensions->dummy_true = GL_TRUE;
259
 
 
260
 
   /* Always enable these extensions for all drivers.
261
 
    * We can't use dummy_true in extensions_table.h for these
262
 
    * because this would make them non-disablable using
263
 
    * _mesa_override_extensions.
264
 
    */
265
 
   extensions->MESA_pack_invert = GL_TRUE;
266
 
   extensions->MESA_window_pos = GL_TRUE;
267
 
 
268
 
   extensions->ARB_ES2_compatibility = GL_TRUE;
269
 
   extensions->ARB_draw_elements_base_vertex = GL_TRUE;
270
 
   extensions->ARB_explicit_attrib_location = GL_TRUE;
271
 
   extensions->ARB_explicit_uniform_location = GL_TRUE;
272
 
   extensions->ARB_fragment_coord_conventions = GL_TRUE;
273
 
   extensions->ARB_fragment_program = GL_TRUE;
274
 
   extensions->ARB_fragment_shader = GL_TRUE;
275
 
   extensions->ARB_half_float_vertex = GL_TRUE;
276
 
   extensions->ARB_internalformat_query = GL_TRUE;
277
 
   extensions->ARB_internalformat_query2 = GL_TRUE;
278
 
   extensions->ARB_map_buffer_range = GL_TRUE;
279
 
   extensions->ARB_occlusion_query = GL_TRUE;
280
 
   extensions->ARB_sync = GL_TRUE;
281
 
   extensions->ARB_vertex_program = GL_TRUE;
282
 
   extensions->ARB_vertex_shader = GL_TRUE;
283
 
 
284
 
   extensions->EXT_EGL_image_storage = GL_TRUE;
285
 
   extensions->EXT_gpu_program_parameters = GL_TRUE;
286
 
   extensions->EXT_pixel_buffer_object = GL_TRUE;
287
 
   extensions->EXT_provoking_vertex = GL_TRUE;
288
 
   extensions->EXT_stencil_two_side = GL_TRUE;
289
 
   extensions->EXT_texture_env_dot3 = GL_TRUE;
290
 
 
291
 
   extensions->ATI_fragment_shader = GL_TRUE;
292
 
   extensions->ATI_texture_env_combine3 = GL_TRUE;
293
 
 
294
 
   extensions->MESA_framebuffer_flip_y = GL_TRUE;
295
 
 
296
 
   extensions->NV_copy_image = GL_TRUE;
297
 
   extensions->NV_fog_distance = GL_TRUE;
298
 
   extensions->NV_texture_env_combine4 = GL_TRUE;
299
 
   extensions->NV_texture_rectangle = GL_TRUE;
300
 
 
301
 
   extensions->OES_EGL_image = GL_TRUE;
302
 
   extensions->OES_EGL_image_external = GL_TRUE;
303
 
   extensions->OES_draw_texture = GL_TRUE;
304
 
}
305
 
 
306
 
 
307
 
typedef unsigned short extension_index;
308
 
 
309
 
 
310
 
/**
311
 
 * Given an extension enum, return whether or not the extension is supported
312
 
 * dependent on the following factors:
313
 
 * There's driver support and the OpenGL/ES version is at least that
314
 
 * specified in the _mesa_extension_table.
315
 
 */
316
 
static inline bool
317
 
_mesa_extension_supported(const struct gl_context *ctx, extension_index i)
318
 
{
319
 
   const bool *base = (bool *) &ctx->Extensions;
320
 
   const struct mesa_extension *ext = _mesa_extension_table + i;
321
 
 
322
 
   return (ctx->Version >= ext->version[ctx->API]) && base[ext->offset];
323
 
}
324
 
 
325
 
/**
326
 
 * Compare two entries of the extensions table.  Sorts first by year,
327
 
 * then by name.
328
 
 *
329
 
 * Arguments are indices into _mesa_extension_table.
330
 
 */
331
 
static int
332
 
extension_compare(const void *p1, const void *p2)
333
 
{
334
 
   extension_index i1 = * (const extension_index *) p1;
335
 
   extension_index i2 = * (const extension_index *) p2;
336
 
   const struct mesa_extension *e1 = &_mesa_extension_table[i1];
337
 
   const struct mesa_extension *e2 = &_mesa_extension_table[i2];
338
 
   int res;
339
 
 
340
 
   res = (int)e1->year - (int)e2->year;
341
 
 
342
 
   if (res == 0) {
343
 
      res = strcmp(e1->name, e2->name);
344
 
   }
345
 
 
346
 
   return res;
347
 
}
348
 
 
349
 
 
350
 
/**
351
 
 * Construct the GL_EXTENSIONS string.  Called the first time that
352
 
 * glGetString(GL_EXTENSIONS) is called.
353
 
 */
354
 
GLubyte*
355
 
_mesa_make_extension_string(struct gl_context *ctx)
356
 
{
357
 
   /* The extension string. */
358
 
   char *exts = NULL;
359
 
   /* Length of extension string. */
360
 
   size_t length = 0;
361
 
   /* Number of extensions */
362
 
   unsigned count;
363
 
   /* Indices of the extensions sorted by year */
364
 
   extension_index extension_indices[MESA_EXTENSION_COUNT];
365
 
   unsigned k;
366
 
   unsigned j;
367
 
   unsigned maxYear = ~0;
368
 
 
369
 
   /* Check if the MESA_EXTENSION_MAX_YEAR env var is set */
370
 
   {
371
 
      const char *env = getenv("MESA_EXTENSION_MAX_YEAR");
372
 
      if (env) {
373
 
         maxYear = atoi(env);
374
 
         _mesa_debug(ctx, "Note: limiting GL extensions to %u or earlier\n",
375
 
                     maxYear);
376
 
      }
377
 
   }
378
 
 
379
 
   /* Compute length of the extension string. */
380
 
   count = 0;
381
 
   for (k = 0; k < MESA_EXTENSION_COUNT; ++k) {
382
 
      const struct mesa_extension *i = _mesa_extension_table + k;
383
 
 
384
 
      if (i->year <= maxYear &&
385
 
          _mesa_extension_supported(ctx, k)) {
386
 
         length += strlen(i->name) + 1; /* +1 for space */
387
 
         ++count;
388
 
      }
389
 
   }
390
 
   for (k = 0; k < MAX_UNRECOGNIZED_EXTENSIONS; k++)
391
 
      if (unrecognized_extensions.names[k])
392
 
         length += 1 + strlen(unrecognized_extensions.names[k]); /* +1 for space */
393
 
 
394
 
   exts = calloc(ALIGN(length + 1, 4), sizeof(char));
395
 
   if (exts == NULL) {
396
 
      return NULL;
397
 
   }
398
 
 
399
 
   /* Sort extensions in chronological order because idTech 2/3 games
400
 
    * (e.g., Quake3 demo) store the extension list in a fixed size buffer.
401
 
    * Some cases truncate, while others overflow the buffer. Resulting in
402
 
    * misrendering and crashes, respectively.
403
 
    * Address the former here, while the latter will be addressed by setting
404
 
    * the MESA_EXTENSION_MAX_YEAR environment variable.
405
 
    */
406
 
   j = 0;
407
 
   for (k = 0; k < MESA_EXTENSION_COUNT; ++k) {
408
 
      if (_mesa_extension_table[k].year <= maxYear &&
409
 
         _mesa_extension_supported(ctx, k)) {
410
 
         extension_indices[j++] = k;
411
 
      }
412
 
   }
413
 
   assert(j == count);
414
 
   qsort(extension_indices, count,
415
 
         sizeof *extension_indices, extension_compare);
416
 
 
417
 
   /* Build the extension string.*/
418
 
   for (j = 0; j < count; ++j) {
419
 
      const struct mesa_extension *i = &_mesa_extension_table[extension_indices[j]];
420
 
      assert(_mesa_extension_supported(ctx, extension_indices[j]));
421
 
      strcat(exts, i->name);
422
 
      strcat(exts, " ");
423
 
   }
424
 
   for (j = 0; j < MAX_UNRECOGNIZED_EXTENSIONS; j++) {
425
 
      if (unrecognized_extensions.names[j]) {
426
 
         strcat(exts, unrecognized_extensions.names[j]);
427
 
         strcat(exts, " ");
428
 
      }
429
 
   }
430
 
 
431
 
   return (GLubyte *) exts;
432
 
}
433
 
 
434
 
/**
435
 
 * Return number of enabled extensions.
436
 
 */
437
 
GLuint
438
 
_mesa_get_extension_count(struct gl_context *ctx)
439
 
{
440
 
   unsigned k;
441
 
 
442
 
   /* only count once */
443
 
   if (ctx->Extensions.Count != 0)
444
 
      return ctx->Extensions.Count;
445
 
 
446
 
   for (k = 0; k < MESA_EXTENSION_COUNT; ++k) {
447
 
      if (_mesa_extension_supported(ctx, k))
448
 
         ctx->Extensions.Count++;
449
 
   }
450
 
 
451
 
   for (k = 0; k < MAX_UNRECOGNIZED_EXTENSIONS; ++k) {
452
 
      if (unrecognized_extensions.names[k])
453
 
         ctx->Extensions.Count++;
454
 
   }
455
 
   return ctx->Extensions.Count;
456
 
}
457
 
 
458
 
/**
459
 
 * Return name of i-th enabled extension
460
 
 */
461
 
const GLubyte *
462
 
_mesa_get_enabled_extension(struct gl_context *ctx, GLuint index)
463
 
{
464
 
   size_t n = 0;
465
 
   unsigned i;
466
 
 
467
 
   for (i = 0; i < MESA_EXTENSION_COUNT; ++i) {
468
 
      if (_mesa_extension_supported(ctx, i)) {
469
 
         if (n == index)
470
 
            return (const GLubyte*) _mesa_extension_table[i].name;
471
 
         else
472
 
            ++n;
473
 
      }
474
 
   }
475
 
 
476
 
   for (i = 0; i < MAX_UNRECOGNIZED_EXTENSIONS; ++i) {
477
 
      if (unrecognized_extensions.names[i]) {
478
 
         if (n == index)
479
 
            return (const GLubyte*) unrecognized_extensions.names[i];
480
 
         else
481
 
            ++n;
482
 
      }
483
 
   }
484
 
   return NULL;
485
 
}