1 /*
2 * (C) Copyright IBM Corporation 2002, 2004
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * 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 NON-INFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file dri_util.c
27 * DRI utility functions.
28 *
29 * This module acts as glue between GLX and the actual hardware driver. A DRI
30 * driver doesn't really \e have to use any of this - it's optional. But, some
31 * useful stuff is done here that otherwise would have to be duplicated in most
32 * drivers.
33 *
34 * Basically, these utility functions take care of some of the dirty details of
35 * screen initialization, context creation, context binding, DRM setup, etc.
36 *
37 * These functions are compiled into each DRI driver so libGL.so knows nothing
38 * about them.
39 */
40
41
42 #include <stdbool.h>
43 #include "dri_util.h"
44 #include "dri_context.h"
45 #include "dri_screen.h"
46 #include "util/u_endian.h"
47 #include "util/driconf.h"
48 #include "main/framebuffer.h"
49 #include "main/version.h"
50 #include "main/debug_output.h"
51 #include "main/errors.h"
52
53 driOptionDescription __dri2ConfigOptions[] = {
54 DRI_CONF_SECTION_DEBUG
55 DRI_CONF_GLX_EXTENSION_OVERRIDE()
56 DRI_CONF_INDIRECT_GL_EXTENSION_OVERRIDE()
57 DRI_CONF_SECTION_END
58
59 DRI_CONF_SECTION_PERFORMANCE
60 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1)
61 DRI_CONF_SECTION_END
62 };
63
64 /*****************************************************************/
65 /** \name Screen handling functions */
66 /*****************************************************************/
67 /*@{*/
68
69 static void
setupLoaderExtensions(__DRIscreen * psp,const __DRIextension ** extensions)70 setupLoaderExtensions(__DRIscreen *psp,
71 const __DRIextension **extensions)
72 {
73 int i;
74
75 for (i = 0; extensions[i]; i++) {
76 if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0)
77 psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i];
78 if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0)
79 psp->dri2.image = (__DRIimageLookupExtension *) extensions[i];
80 if (strcmp(extensions[i]->name, __DRI_USE_INVALIDATE) == 0)
81 psp->dri2.useInvalidate = (__DRIuseInvalidateExtension *) extensions[i];
82 if (strcmp(extensions[i]->name, __DRI_BACKGROUND_CALLABLE) == 0)
83 psp->dri2.backgroundCallable = (__DRIbackgroundCallableExtension *) extensions[i];
84 if (strcmp(extensions[i]->name, __DRI_SWRAST_LOADER) == 0)
85 psp->swrast_loader = (__DRIswrastLoaderExtension *) extensions[i];
86 if (strcmp(extensions[i]->name, __DRI_IMAGE_LOADER) == 0)
87 psp->image.loader = (__DRIimageLoaderExtension *) extensions[i];
88 if (strcmp(extensions[i]->name, __DRI_MUTABLE_RENDER_BUFFER_LOADER) == 0)
89 psp->mutableRenderBuffer.loader = (__DRImutableRenderBufferLoaderExtension *) extensions[i];
90 if (strcmp(extensions[i]->name, __DRI_KOPPER_LOADER) == 0)
91 psp->kopper_loader = (__DRIkopperLoaderExtension *) extensions[i];
92 }
93 }
94
95 /**
96 * This is the first entrypoint in the driver called by the DRI driver loader
97 * after dlopen()ing it.
98 *
99 * It's used to create global state for the driver across contexts on the same
100 * Display.
101 */
102 static __DRIscreen *
driCreateNewScreen2(int scrn,int fd,const __DRIextension ** extensions,const __DRIextension ** driver_extensions,const __DRIconfig *** driver_configs,void * data)103 driCreateNewScreen2(int scrn, int fd,
104 const __DRIextension **extensions,
105 const __DRIextension **driver_extensions,
106 const __DRIconfig ***driver_configs, void *data)
107 {
108 static const __DRIextension *emptyExtensionList[] = { NULL };
109 __DRIscreen *psp;
110
111 psp = calloc(1, sizeof(*psp));
112 if (!psp)
113 return NULL;
114
115 assert(driver_extensions);
116 for (int i = 0; driver_extensions[i]; i++) {
117 if (strcmp(driver_extensions[i]->name, __DRI_DRIVER_VTABLE) == 0) {
118 psp->driver =
119 ((__DRIDriverVtableExtension *)driver_extensions[i])->vtable;
120 }
121 }
122
123 setupLoaderExtensions(psp, extensions);
124 // dri2 drivers require working invalidate
125 if (fd != -1 && !psp->dri2.useInvalidate) {
126 free(psp);
127 return NULL;
128 }
129
130 psp->loaderPrivate = data;
131
132 psp->extensions = emptyExtensionList;
133 psp->fd = fd;
134 psp->myNum = scrn;
135
136 /* Option parsing before ->InitScreen(), as some options apply there. */
137 driParseOptionInfo(&psp->optionInfo,
138 __dri2ConfigOptions, ARRAY_SIZE(__dri2ConfigOptions));
139 driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum,
140 "dri2", NULL, NULL, NULL, 0, NULL, 0);
141
142 *driver_configs = psp->driver->InitScreen(psp);
143 if (*driver_configs == NULL) {
144 free(psp);
145 return NULL;
146 }
147
148 struct gl_constants consts = { 0 };
149 gl_api api;
150 unsigned version;
151
152 api = API_OPENGLES2;
153 if (_mesa_override_gl_version_contextless(&consts, &api, &version))
154 psp->max_gl_es2_version = version;
155
156 api = API_OPENGL_COMPAT;
157 if (_mesa_override_gl_version_contextless(&consts, &api, &version)) {
158 psp->max_gl_core_version = version;
159 if (api == API_OPENGL_COMPAT)
160 psp->max_gl_compat_version = version;
161 }
162
163 psp->api_mask = 0;
164 if (psp->max_gl_compat_version > 0)
165 psp->api_mask |= (1 << __DRI_API_OPENGL);
166 if (psp->max_gl_core_version > 0)
167 psp->api_mask |= (1 << __DRI_API_OPENGL_CORE);
168 if (psp->max_gl_es1_version > 0)
169 psp->api_mask |= (1 << __DRI_API_GLES);
170 if (psp->max_gl_es2_version > 0)
171 psp->api_mask |= (1 << __DRI_API_GLES2);
172 if (psp->max_gl_es2_version >= 30)
173 psp->api_mask |= (1 << __DRI_API_GLES3);
174
175 return psp;
176 }
177
178 static __DRIscreen *
dri2CreateNewScreen(int scrn,int fd,const __DRIextension ** extensions,const __DRIconfig *** driver_configs,void * data)179 dri2CreateNewScreen(int scrn, int fd,
180 const __DRIextension **extensions,
181 const __DRIconfig ***driver_configs, void *data)
182 {
183 return driCreateNewScreen2(scrn, fd, extensions,
184 galliumdrm_driver_extensions,
185 driver_configs, data);
186 }
187
188 static __DRIscreen *
swkmsCreateNewScreen(int scrn,int fd,const __DRIextension ** extensions,const __DRIconfig *** driver_configs,void * data)189 swkmsCreateNewScreen(int scrn, int fd,
190 const __DRIextension **extensions,
191 const __DRIconfig ***driver_configs, void *data)
192 {
193 return driCreateNewScreen2(scrn, fd, extensions,
194 dri_swrast_kms_driver_extensions,
195 driver_configs, data);
196 }
197
198 /** swrast driver createNewScreen entrypoint. */
199 static __DRIscreen *
driSWRastCreateNewScreen(int scrn,const __DRIextension ** extensions,const __DRIconfig *** driver_configs,void * data)200 driSWRastCreateNewScreen(int scrn, const __DRIextension **extensions,
201 const __DRIconfig ***driver_configs, void *data)
202 {
203 return driCreateNewScreen2(scrn, -1, extensions,
204 galliumsw_driver_extensions,
205 driver_configs, data);
206 }
207
208 static __DRIscreen *
driSWRastCreateNewScreen2(int scrn,const __DRIextension ** extensions,const __DRIextension ** driver_extensions,const __DRIconfig *** driver_configs,void * data)209 driSWRastCreateNewScreen2(int scrn, const __DRIextension **extensions,
210 const __DRIextension **driver_extensions,
211 const __DRIconfig ***driver_configs, void *data)
212 {
213 return driCreateNewScreen2(scrn, -1, extensions, driver_extensions,
214 driver_configs, data);
215 }
216
217 /**
218 * Destroy the per-screen private information.
219 *
220 * \internal
221 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
222 * drmClose(), and finally frees \p screenPrivate.
223 */
driDestroyScreen(__DRIscreen * psp)224 static void driDestroyScreen(__DRIscreen *psp)
225 {
226 if (psp) {
227 /* No interaction with the X-server is possible at this point. This
228 * routine is called after XCloseDisplay, so there is no protocol
229 * stream open to the X-server anymore.
230 */
231
232 psp->driver->DestroyScreen(psp);
233
234 driDestroyOptionCache(&psp->optionCache);
235 driDestroyOptionInfo(&psp->optionInfo);
236
237 free(psp);
238 }
239 }
240
driGetExtensions(__DRIscreen * psp)241 static const __DRIextension **driGetExtensions(__DRIscreen *psp)
242 {
243 return psp->extensions;
244 }
245
246 /*@}*/
247
248 /* WARNING: HACK: Local defines to avoid pulling glx.h.
249 */
250 #define GLX_NONE 0x8000
251 #define GLX_DONT_CARE 0xFFFFFFFF
252
253 #define __ATTRIB(attrib, field) case attrib: *value = config->modes.field; break
254
255 /**
256 * Return the value of a configuration attribute. The attribute is
257 * indicated by the index.
258 */
259 static int
driGetConfigAttribIndex(const __DRIconfig * config,unsigned int index,unsigned int * value)260 driGetConfigAttribIndex(const __DRIconfig *config,
261 unsigned int index, unsigned int *value)
262 {
263 switch (index + 1) {
264 __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits);
265 __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits);
266 __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits);
267 __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits);
268 case __DRI_ATTRIB_LEVEL:
269 case __DRI_ATTRIB_LUMINANCE_SIZE:
270 case __DRI_ATTRIB_AUX_BUFFERS:
271 *value = 0;
272 break;
273 __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits);
274 case __DRI_ATTRIB_ALPHA_MASK_SIZE:
275 /* I have no idea what this value was ever meant to mean, it's
276 * never been set to anything, just say 0.
277 */
278 *value = 0;
279 break;
280 __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits);
281 __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits);
282 __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits);
283 __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits);
284 __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits);
285 __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits);
286 case __DRI_ATTRIB_SAMPLE_BUFFERS:
287 *value = !!config->modes.samples;
288 break;
289 __ATTRIB(__DRI_ATTRIB_SAMPLES, samples);
290 case __DRI_ATTRIB_RENDER_TYPE:
291 /* no support for color index mode */
292 *value = __DRI_ATTRIB_RGBA_BIT;
293 if (config->modes.floatMode)
294 *value |= __DRI_ATTRIB_FLOAT_BIT;
295 break;
296 case __DRI_ATTRIB_CONFIG_CAVEAT:
297 if (config->modes.accumRedBits != 0)
298 *value = __DRI_ATTRIB_SLOW_BIT;
299 else
300 *value = 0;
301 break;
302 case __DRI_ATTRIB_CONFORMANT:
303 *value = GL_TRUE;
304 break;
305 __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode);
306 __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode);
307 case __DRI_ATTRIB_TRANSPARENT_TYPE:
308 case __DRI_ATTRIB_TRANSPARENT_INDEX_VALUE: /* horrible bc hack */
309 *value = GLX_NONE;
310 break;
311 case __DRI_ATTRIB_TRANSPARENT_RED_VALUE:
312 case __DRI_ATTRIB_TRANSPARENT_GREEN_VALUE:
313 case __DRI_ATTRIB_TRANSPARENT_BLUE_VALUE:
314 case __DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE:
315 *value = GLX_DONT_CARE;
316 break;
317 case __DRI_ATTRIB_FLOAT_MODE:
318 *value = config->modes.floatMode;
319 break;
320 __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask);
321 __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask);
322 __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask);
323 __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask);
324 case __DRI_ATTRIB_MAX_PBUFFER_WIDTH:
325 case __DRI_ATTRIB_MAX_PBUFFER_HEIGHT:
326 case __DRI_ATTRIB_MAX_PBUFFER_PIXELS:
327 case __DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH:
328 case __DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT:
329 case __DRI_ATTRIB_VISUAL_SELECT_GROUP:
330 *value = 0;
331 break;
332 __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod);
333 case __DRI_ATTRIB_MAX_SWAP_INTERVAL:
334 *value = INT_MAX;
335 break;
336 case __DRI_ATTRIB_MIN_SWAP_INTERVAL:
337 *value = 0;
338 break;
339 case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB:
340 case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA:
341 case __DRI_ATTRIB_YINVERTED:
342 *value = GL_TRUE;
343 break;
344 case __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE:
345 *value = GL_FALSE;
346 break;
347 case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS:
348 *value = __DRI_ATTRIB_TEXTURE_1D_BIT |
349 __DRI_ATTRIB_TEXTURE_2D_BIT |
350 __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT;
351 break;
352 __ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE, sRGBCapable);
353 case __DRI_ATTRIB_MUTABLE_RENDER_BUFFER:
354 *value = GL_FALSE;
355 break;
356 __ATTRIB(__DRI_ATTRIB_RED_SHIFT, redShift);
357 __ATTRIB(__DRI_ATTRIB_GREEN_SHIFT, greenShift);
358 __ATTRIB(__DRI_ATTRIB_BLUE_SHIFT, blueShift);
359 __ATTRIB(__DRI_ATTRIB_ALPHA_SHIFT, alphaShift);
360 default:
361 /* XXX log an error or smth */
362 return GL_FALSE;
363 }
364
365 return GL_TRUE;
366 }
367
368 /**
369 * Get the value of a configuration attribute.
370 * \param attrib the attribute (one of the _DRI_ATTRIB_x tokens)
371 * \param value returns the attribute's value
372 * \return 1 for success, 0 for failure
373 */
374 static int
driGetConfigAttrib(const __DRIconfig * config,unsigned int attrib,unsigned int * value)375 driGetConfigAttrib(const __DRIconfig *config,
376 unsigned int attrib, unsigned int *value)
377 {
378 return driGetConfigAttribIndex(config, attrib - 1, value);
379 }
380
381 /**
382 * Get a configuration attribute name and value, given an index.
383 * \param index which field of the __DRIconfig to query
384 * \param attrib returns the attribute name (one of the _DRI_ATTRIB_x tokens)
385 * \param value returns the attribute's value
386 * \return 1 for success, 0 for failure
387 */
388 static int
driIndexConfigAttrib(const __DRIconfig * config,int index,unsigned int * attrib,unsigned int * value)389 driIndexConfigAttrib(const __DRIconfig *config, int index,
390 unsigned int *attrib, unsigned int *value)
391 {
392 if (driGetConfigAttribIndex(config, index, value)) {
393 *attrib = index + 1;
394 return GL_TRUE;
395 }
396
397 return GL_FALSE;
398 }
399
400 static bool
validate_context_version(__DRIscreen * screen,int mesa_api,unsigned major_version,unsigned minor_version,unsigned * dri_ctx_error)401 validate_context_version(__DRIscreen *screen,
402 int mesa_api,
403 unsigned major_version,
404 unsigned minor_version,
405 unsigned *dri_ctx_error)
406 {
407 unsigned req_version = 10 * major_version + minor_version;
408 unsigned max_version = 0;
409
410 switch (mesa_api) {
411 case API_OPENGL_COMPAT:
412 max_version = screen->max_gl_compat_version;
413 break;
414 case API_OPENGL_CORE:
415 max_version = screen->max_gl_core_version;
416 break;
417 case API_OPENGLES:
418 max_version = screen->max_gl_es1_version;
419 break;
420 case API_OPENGLES2:
421 max_version = screen->max_gl_es2_version;
422 break;
423 default:
424 max_version = 0;
425 break;
426 }
427
428 if (max_version == 0) {
429 *dri_ctx_error = __DRI_CTX_ERROR_BAD_API;
430 return false;
431 } else if (req_version > max_version) {
432 *dri_ctx_error = __DRI_CTX_ERROR_BAD_VERSION;
433 return false;
434 }
435
436 return true;
437 }
438
439 /*****************************************************************/
440 /** \name Context handling functions */
441 /*****************************************************************/
442 /*@{*/
443
444 static __DRIcontext *
driCreateContextAttribs(__DRIscreen * screen,int api,const __DRIconfig * config,__DRIcontext * shared,unsigned num_attribs,const uint32_t * attribs,unsigned * error,void * data)445 driCreateContextAttribs(__DRIscreen *screen, int api,
446 const __DRIconfig *config,
447 __DRIcontext *shared,
448 unsigned num_attribs,
449 const uint32_t *attribs,
450 unsigned *error,
451 void *data)
452 {
453 __DRIcontext *context;
454 const struct gl_config *modes = (config != NULL) ? &config->modes : NULL;
455 void *shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
456 gl_api mesa_api;
457 struct __DriverContextConfig ctx_config;
458
459 ctx_config.major_version = 1;
460 ctx_config.minor_version = 0;
461 ctx_config.flags = 0;
462 ctx_config.attribute_mask = 0;
463 ctx_config.priority = __DRI_CTX_PRIORITY_MEDIUM;
464
465 assert((num_attribs == 0) || (attribs != NULL));
466
467 if (!(screen->api_mask & (1 << api))) {
468 *error = __DRI_CTX_ERROR_BAD_API;
469 return NULL;
470 }
471
472 switch (api) {
473 case __DRI_API_OPENGL:
474 mesa_api = API_OPENGL_COMPAT;
475 break;
476 case __DRI_API_GLES:
477 mesa_api = API_OPENGLES;
478 break;
479 case __DRI_API_GLES2:
480 case __DRI_API_GLES3:
481 mesa_api = API_OPENGLES2;
482 break;
483 case __DRI_API_OPENGL_CORE:
484 mesa_api = API_OPENGL_CORE;
485 break;
486 default:
487 *error = __DRI_CTX_ERROR_BAD_API;
488 return NULL;
489 }
490
491 for (unsigned i = 0; i < num_attribs; i++) {
492 switch (attribs[i * 2]) {
493 case __DRI_CTX_ATTRIB_MAJOR_VERSION:
494 ctx_config.major_version = attribs[i * 2 + 1];
495 break;
496 case __DRI_CTX_ATTRIB_MINOR_VERSION:
497 ctx_config.minor_version = attribs[i * 2 + 1];
498 break;
499 case __DRI_CTX_ATTRIB_FLAGS:
500 ctx_config.flags = attribs[i * 2 + 1];
501 break;
502 case __DRI_CTX_ATTRIB_RESET_STRATEGY:
503 if (attribs[i * 2 + 1] != __DRI_CTX_RESET_NO_NOTIFICATION) {
504 ctx_config.attribute_mask |=
505 __DRIVER_CONTEXT_ATTRIB_RESET_STRATEGY;
506 ctx_config.reset_strategy = attribs[i * 2 + 1];
507 } else {
508 ctx_config.attribute_mask &=
509 ~__DRIVER_CONTEXT_ATTRIB_RESET_STRATEGY;
510 }
511 break;
512 case __DRI_CTX_ATTRIB_PRIORITY:
513 ctx_config.attribute_mask |= __DRIVER_CONTEXT_ATTRIB_PRIORITY;
514 ctx_config.priority = attribs[i * 2 + 1];
515 break;
516 case __DRI_CTX_ATTRIB_RELEASE_BEHAVIOR:
517 if (attribs[i * 2 + 1] != __DRI_CTX_RELEASE_BEHAVIOR_FLUSH) {
518 ctx_config.attribute_mask |=
519 __DRIVER_CONTEXT_ATTRIB_RELEASE_BEHAVIOR;
520 ctx_config.release_behavior = attribs[i * 2 + 1];
521 } else {
522 ctx_config.attribute_mask &=
523 ~__DRIVER_CONTEXT_ATTRIB_RELEASE_BEHAVIOR;
524 }
525 break;
526 case __DRI_CTX_ATTRIB_NO_ERROR:
527 if (attribs[i * 2 + 1] != 0) {
528 ctx_config.attribute_mask |=
529 __DRIVER_CONTEXT_ATTRIB_NO_ERROR;
530 ctx_config.no_error = attribs[i * 2 + 1];
531 } else {
532 ctx_config.attribute_mask &=
533 ~__DRIVER_CONTEXT_ATTRIB_NO_ERROR;
534 }
535 break;
536 default:
537 /* We can't create a context that satisfies the requirements of an
538 * attribute that we don't understand. Return failure.
539 */
540 assert(!"Should not get here.");
541 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
542 return NULL;
543 }
544 }
545
546 /* The specific Mesa driver may not support the GL_ARB_compatibilty
547 * extension or the compatibility profile. In that case, we treat an
548 * API_OPENGL_COMPAT 3.1 as API_OPENGL_CORE. We reject API_OPENGL_COMPAT
549 * 3.2+ in any case.
550 */
551 if (mesa_api == API_OPENGL_COMPAT &&
552 ctx_config.major_version == 3 && ctx_config.minor_version == 1 &&
553 screen->max_gl_compat_version < 31)
554 mesa_api = API_OPENGL_CORE;
555
556 /* The latest version of EGL_KHR_create_context spec says:
557 *
558 * "If the EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR flag bit is set in
559 * EGL_CONTEXT_FLAGS_KHR, then a <debug context> will be created.
560 * [...] This bit is supported for OpenGL and OpenGL ES contexts.
561 *
562 * No other EGL_CONTEXT_OPENGL_*_BIT is legal for an ES context.
563 *
564 * However, Mesa's EGL layer translates the context attribute
565 * EGL_CONTEXT_OPENGL_ROBUST_ACCESS into the context flag
566 * __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS. That attribute is legal for ES
567 * (with EGL 1.5 or EGL_EXT_create_context_robustness) and GL (only with
568 * EGL 1.5).
569 *
570 * From the EGL_EXT_create_context_robustness spec:
571 *
572 * This extension is written against the OpenGL ES 2.0 Specification
573 * but can apply to OpenGL ES 1.1 and up.
574 *
575 * From the EGL 1.5 (2014.08.27) spec, p55:
576 *
577 * If the EGL_CONTEXT_OPENGL_ROBUST_ACCESS attribute is set to
578 * EGL_TRUE, a context supporting robust buffer access will be created.
579 * OpenGL contexts must support the GL_ARB_robustness extension, or
580 * equivalent core API functional- ity. OpenGL ES contexts must support
581 * the GL_EXT_robustness extension, or equivalent core API
582 * functionality.
583 */
584 if (mesa_api != API_OPENGL_COMPAT
585 && mesa_api != API_OPENGL_CORE
586 && (ctx_config.flags & ~(__DRI_CTX_FLAG_DEBUG |
587 __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS))) {
588 *error = __DRI_CTX_ERROR_BAD_FLAG;
589 return NULL;
590 }
591
592 /* There are no forward-compatible contexts before OpenGL 3.0. The
593 * GLX_ARB_create_context spec says:
594 *
595 * "Forward-compatible contexts are defined only for OpenGL versions
596 * 3.0 and later."
597 *
598 * Forward-looking contexts are supported by silently converting the
599 * requested API to API_OPENGL_CORE.
600 *
601 * In Mesa, a debug context is the same as a regular context.
602 */
603 if ((ctx_config.flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) {
604 mesa_api = API_OPENGL_CORE;
605 }
606
607 const uint32_t allowed_flags = (__DRI_CTX_FLAG_DEBUG
608 | __DRI_CTX_FLAG_FORWARD_COMPATIBLE
609 | __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS
610 | __DRI_CTX_FLAG_RESET_ISOLATION);
611 if (ctx_config.flags & ~allowed_flags) {
612 *error = __DRI_CTX_ERROR_UNKNOWN_FLAG;
613 return NULL;
614 }
615
616 if (!validate_context_version(screen, mesa_api,
617 ctx_config.major_version,
618 ctx_config.minor_version,
619 error))
620 return NULL;
621
622 context = calloc(1, sizeof *context);
623 if (!context) {
624 *error = __DRI_CTX_ERROR_NO_MEMORY;
625 return NULL;
626 }
627
628 context->loaderPrivate = data;
629
630 context->driScreenPriv = screen;
631 context->driDrawablePriv = NULL;
632 context->driReadablePriv = NULL;
633
634 if (!dri_create_context(mesa_api, modes, context, &ctx_config, error,
635 shareCtx)) {
636 free(context);
637 return NULL;
638 }
639
640 *error = __DRI_CTX_ERROR_SUCCESS;
641 return context;
642 }
643
644 static __DRIcontext *
driCreateNewContextForAPI(__DRIscreen * screen,int api,const __DRIconfig * config,__DRIcontext * shared,void * data)645 driCreateNewContextForAPI(__DRIscreen *screen, int api,
646 const __DRIconfig *config,
647 __DRIcontext *shared, void *data)
648 {
649 unsigned error;
650
651 return driCreateContextAttribs(screen, api, config, shared, 0, NULL,
652 &error, data);
653 }
654
655 static __DRIcontext *
driCreateNewContext(__DRIscreen * screen,const __DRIconfig * config,__DRIcontext * shared,void * data)656 driCreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
657 __DRIcontext *shared, void *data)
658 {
659 return driCreateNewContextForAPI(screen, __DRI_API_OPENGL,
660 config, shared, data);
661 }
662
663 /**
664 * Destroy the per-context private information.
665 *
666 * \internal
667 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
668 * drmDestroyContext(), and finally frees \p contextPrivate.
669 */
670 static void
driDestroyContext(__DRIcontext * pcp)671 driDestroyContext(__DRIcontext *pcp)
672 {
673 if (pcp) {
674 dri_destroy_context(pcp);
675 free(pcp);
676 }
677 }
678
679 static int
driCopyContext(__DRIcontext * dest,__DRIcontext * src,unsigned long mask)680 driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask)
681 {
682 (void) dest;
683 (void) src;
684 (void) mask;
685 return GL_FALSE;
686 }
687
688 /*@}*/
689
690
691 /*****************************************************************/
692 /** \name Context (un)binding functions */
693 /*****************************************************************/
694 /*@{*/
695
696 static void dri_get_drawable(__DRIdrawable *pdp);
697 static void dri_put_drawable(__DRIdrawable *pdp);
698
699 /**
700 * This function takes both a read buffer and a draw buffer. This is needed
701 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
702 * function.
703 */
driBindContext(__DRIcontext * pcp,__DRIdrawable * pdp,__DRIdrawable * prp)704 static int driBindContext(__DRIcontext *pcp,
705 __DRIdrawable *pdp,
706 __DRIdrawable *prp)
707 {
708 /*
709 ** Assume error checking is done properly in glXMakeCurrent before
710 ** calling driUnbindContext.
711 */
712
713 if (!pcp)
714 return GL_FALSE;
715
716 /* Bind the drawable to the context */
717 pcp->driDrawablePriv = pdp;
718 pcp->driReadablePriv = prp;
719 if (pdp) {
720 pdp->driContextPriv = pcp;
721 dri_get_drawable(pdp);
722 }
723 if (prp && pdp != prp) {
724 dri_get_drawable(prp);
725 }
726
727 return dri_make_current(pcp, pdp, prp);
728 }
729
730 /**
731 * Unbind context.
732 *
733 * \param scrn the screen.
734 * \param gc context.
735 *
736 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
737 *
738 * \internal
739 * This function calls __DriverAPIRec::UnbindContext, and then decrements
740 * __DRIdrawableRec::refcount which must be non-zero for a successful
741 * return.
742 *
743 * While casting the opaque private pointers associated with the parameters
744 * into their respective real types it also assures they are not \c NULL.
745 */
driUnbindContext(__DRIcontext * pcp)746 static int driUnbindContext(__DRIcontext *pcp)
747 {
748 __DRIdrawable *pdp;
749 __DRIdrawable *prp;
750
751 /*
752 ** Assume error checking is done properly in glXMakeCurrent before
753 ** calling driUnbindContext.
754 */
755
756 if (pcp == NULL)
757 return GL_FALSE;
758
759 /*
760 ** Call dri_unbind_context before checking for valid drawables
761 ** to handle surfaceless contexts properly.
762 */
763 dri_unbind_context(pcp);
764
765 pdp = pcp->driDrawablePriv;
766 prp = pcp->driReadablePriv;
767
768 /* already unbound */
769 if (!pdp && !prp)
770 return GL_TRUE;
771
772 assert(pdp);
773 if (pdp->refcount == 0) {
774 /* ERROR!!! */
775 return GL_FALSE;
776 }
777
778 dri_put_drawable(pdp);
779
780 if (prp != pdp) {
781 if (prp->refcount == 0) {
782 /* ERROR!!! */
783 return GL_FALSE;
784 }
785
786 dri_put_drawable(prp);
787 }
788
789 pcp->driDrawablePriv = NULL;
790 pcp->driReadablePriv = NULL;
791
792 return GL_TRUE;
793 }
794
795 /*@}*/
796
797
dri_get_drawable(__DRIdrawable * pdp)798 static void dri_get_drawable(__DRIdrawable *pdp)
799 {
800 pdp->refcount++;
801 }
802
dri_put_drawable(__DRIdrawable * pdp)803 static void dri_put_drawable(__DRIdrawable *pdp)
804 {
805 if (pdp) {
806 pdp->refcount--;
807 if (pdp->refcount)
808 return;
809
810 pdp->driScreenPriv->driver->DestroyBuffer(pdp);
811 free(pdp);
812 }
813 }
814
815 static __DRIdrawable *
driCreateNewDrawable(__DRIscreen * screen,const __DRIconfig * config,void * data)816 driCreateNewDrawable(__DRIscreen *screen,
817 const __DRIconfig *config,
818 void *data)
819 {
820 __DRIdrawable *pdraw;
821
822 assert(data != NULL);
823
824 pdraw = malloc(sizeof *pdraw);
825 if (!pdraw)
826 return NULL;
827
828 pdraw->loaderPrivate = data;
829
830 pdraw->driScreenPriv = screen;
831 pdraw->driContextPriv = NULL;
832 pdraw->refcount = 0;
833 pdraw->lastStamp = 0;
834 pdraw->w = 0;
835 pdraw->h = 0;
836
837 dri_get_drawable(pdraw);
838
839 if (!screen->driver->CreateBuffer(screen, pdraw, &config->modes,
840 GL_FALSE)) {
841 free(pdraw);
842 return NULL;
843 }
844
845 pdraw->dri2.stamp = pdraw->lastStamp + 1;
846
847 return pdraw;
848 }
849
850 static void
driDestroyDrawable(__DRIdrawable * pdp)851 driDestroyDrawable(__DRIdrawable *pdp)
852 {
853 /*
854 * The loader's data structures are going away, even if pdp itself stays
855 * around for the time being because it is currently bound. This happens
856 * when a currently bound GLX pixmap is destroyed.
857 *
858 * Clear out the pointer back into the loader's data structures to avoid
859 * accessing an outdated pointer.
860 */
861 pdp->loaderPrivate = NULL;
862
863 dri_put_drawable(pdp);
864 }
865
866 static __DRIbuffer *
dri2AllocateBuffer(__DRIscreen * screen,unsigned int attachment,unsigned int format,int width,int height)867 dri2AllocateBuffer(__DRIscreen *screen,
868 unsigned int attachment, unsigned int format,
869 int width, int height)
870 {
871 return screen->driver->AllocateBuffer(screen, attachment, format,
872 width, height);
873 }
874
875 static void
dri2ReleaseBuffer(__DRIscreen * screen,__DRIbuffer * buffer)876 dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer)
877 {
878 screen->driver->ReleaseBuffer(screen, buffer);
879 }
880
881
882 static int
dri2ConfigQueryb(__DRIscreen * screen,const char * var,unsigned char * val)883 dri2ConfigQueryb(__DRIscreen *screen, const char *var, unsigned char *val)
884 {
885 if (!driCheckOption(&screen->optionCache, var, DRI_BOOL))
886 return -1;
887
888 *val = driQueryOptionb(&screen->optionCache, var);
889
890 return 0;
891 }
892
893 static int
dri2ConfigQueryi(__DRIscreen * screen,const char * var,int * val)894 dri2ConfigQueryi(__DRIscreen *screen, const char *var, int *val)
895 {
896 if (!driCheckOption(&screen->optionCache, var, DRI_INT) &&
897 !driCheckOption(&screen->optionCache, var, DRI_ENUM))
898 return -1;
899
900 *val = driQueryOptioni(&screen->optionCache, var);
901
902 return 0;
903 }
904
905 static int
dri2ConfigQueryf(__DRIscreen * screen,const char * var,float * val)906 dri2ConfigQueryf(__DRIscreen *screen, const char *var, float *val)
907 {
908 if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT))
909 return -1;
910
911 *val = driQueryOptionf(&screen->optionCache, var);
912
913 return 0;
914 }
915
916 static int
dri2ConfigQuerys(__DRIscreen * screen,const char * var,char ** val)917 dri2ConfigQuerys(__DRIscreen *screen, const char *var, char **val)
918 {
919 if (!driCheckOption(&screen->optionCache, var, DRI_STRING))
920 return -1;
921
922 *val = driQueryOptionstr(&screen->optionCache, var);
923
924 return 0;
925 }
926
927 static unsigned int
driGetAPIMask(__DRIscreen * screen)928 driGetAPIMask(__DRIscreen *screen)
929 {
930 return screen->api_mask;
931 }
932
933 /**
934 * swrast swapbuffers entrypoint.
935 *
936 * DRI2 implements this inside the loader with only flushes handled by the
937 * driver.
938 */
939 static void
driSwapBuffers(__DRIdrawable * pdp)940 driSwapBuffers(__DRIdrawable *pdp)
941 {
942 assert(pdp->driScreenPriv->swrast_loader);
943
944 pdp->driScreenPriv->driver->SwapBuffers(pdp);
945 }
946
947 /** Core interface */
948 const __DRIcoreExtension driCoreExtension = {
949 .base = { __DRI_CORE, 2 },
950
951 .createNewScreen = NULL,
952 .destroyScreen = driDestroyScreen,
953 .getExtensions = driGetExtensions,
954 .getConfigAttrib = driGetConfigAttrib,
955 .indexConfigAttrib = driIndexConfigAttrib,
956 .createNewDrawable = NULL,
957 .destroyDrawable = driDestroyDrawable,
958 .swapBuffers = driSwapBuffers, /* swrast */
959 .createNewContext = driCreateNewContext, /* swrast */
960 .copyContext = driCopyContext,
961 .destroyContext = driDestroyContext,
962 .bindContext = driBindContext,
963 .unbindContext = driUnbindContext
964 };
965
966 #if HAVE_DRI2
967
968 /** DRI2 interface */
969 const __DRIdri2Extension driDRI2Extension = {
970 .base = { __DRI_DRI2, 4 },
971
972 .createNewScreen = dri2CreateNewScreen,
973 .createNewDrawable = driCreateNewDrawable,
974 .createNewContext = driCreateNewContext,
975 .getAPIMask = driGetAPIMask,
976 .createNewContextForAPI = driCreateNewContextForAPI,
977 .allocateBuffer = dri2AllocateBuffer,
978 .releaseBuffer = dri2ReleaseBuffer,
979 .createContextAttribs = driCreateContextAttribs,
980 .createNewScreen2 = driCreateNewScreen2,
981 };
982
983 const __DRIdri2Extension swkmsDRI2Extension = {
984 .base = { __DRI_DRI2, 4 },
985
986 .createNewScreen = swkmsCreateNewScreen,
987 .createNewDrawable = driCreateNewDrawable,
988 .createNewContext = driCreateNewContext,
989 .getAPIMask = driGetAPIMask,
990 .createNewContextForAPI = driCreateNewContextForAPI,
991 .allocateBuffer = dri2AllocateBuffer,
992 .releaseBuffer = dri2ReleaseBuffer,
993 .createContextAttribs = driCreateContextAttribs,
994 .createNewScreen2 = driCreateNewScreen2,
995 };
996
997 #endif
998
999 const __DRIswrastExtension driSWRastExtension = {
1000 .base = { __DRI_SWRAST, 4 },
1001
1002 .createNewScreen = driSWRastCreateNewScreen,
1003 .createNewDrawable = driCreateNewDrawable,
1004 .createNewContextForAPI = driCreateNewContextForAPI,
1005 .createContextAttribs = driCreateContextAttribs,
1006 .createNewScreen2 = driSWRastCreateNewScreen2,
1007 };
1008
1009 const __DRI2configQueryExtension dri2ConfigQueryExtension = {
1010 .base = { __DRI2_CONFIG_QUERY, 2 },
1011
1012 .configQueryb = dri2ConfigQueryb,
1013 .configQueryi = dri2ConfigQueryi,
1014 .configQueryf = dri2ConfigQueryf,
1015 .configQuerys = dri2ConfigQuerys,
1016 };
1017
1018 const __DRI2flushControlExtension dri2FlushControlExtension = {
1019 .base = { __DRI2_FLUSH_CONTROL, 1 }
1020 };
1021
1022 /*
1023 * Note: the first match is returned, which is important for formats like
1024 * __DRI_IMAGE_FORMAT_R8 which maps to both MESA_FORMAT_{R,L}_UNORM8
1025 */
1026 static const struct {
1027 uint32_t image_format;
1028 mesa_format mesa_format;
1029 GLenum internal_format;
1030 } format_mapping[] = {
1031 {
1032 .image_format = __DRI_IMAGE_FORMAT_RGB565,
1033 .mesa_format = MESA_FORMAT_B5G6R5_UNORM,
1034 .internal_format = GL_RGB565,
1035 },
1036 {
1037 .image_format = __DRI_IMAGE_FORMAT_ARGB1555,
1038 .mesa_format = MESA_FORMAT_B5G5R5A1_UNORM,
1039 .internal_format = GL_RGB5_A1,
1040 },
1041 {
1042 .image_format = __DRI_IMAGE_FORMAT_XRGB8888,
1043 .mesa_format = MESA_FORMAT_B8G8R8X8_UNORM,
1044 .internal_format = GL_RGB8,
1045 },
1046 {
1047 .image_format = __DRI_IMAGE_FORMAT_ABGR16161616F,
1048 .mesa_format = MESA_FORMAT_RGBA_FLOAT16,
1049 .internal_format = GL_RGBA16F,
1050 },
1051 {
1052 .image_format = __DRI_IMAGE_FORMAT_XBGR16161616F,
1053 .mesa_format = MESA_FORMAT_RGBX_FLOAT16,
1054 .internal_format = GL_RGBA16F,
1055 },
1056 {
1057 .image_format = __DRI_IMAGE_FORMAT_ABGR16161616,
1058 .mesa_format = MESA_FORMAT_RGBA_UNORM16,
1059 .internal_format = GL_RGBA16,
1060 },
1061 {
1062 .image_format = __DRI_IMAGE_FORMAT_XBGR16161616,
1063 .mesa_format = MESA_FORMAT_RGBX_UNORM16,
1064 .internal_format = GL_RGBA16,
1065 },
1066 {
1067 .image_format = __DRI_IMAGE_FORMAT_ARGB2101010,
1068 .mesa_format = MESA_FORMAT_B10G10R10A2_UNORM,
1069 .internal_format = GL_RGB10_A2,
1070 },
1071 {
1072 .image_format = __DRI_IMAGE_FORMAT_XRGB2101010,
1073 .mesa_format = MESA_FORMAT_B10G10R10X2_UNORM,
1074 .internal_format = GL_RGB10_A2,
1075 },
1076 {
1077 .image_format = __DRI_IMAGE_FORMAT_ABGR2101010,
1078 .mesa_format = MESA_FORMAT_R10G10B10A2_UNORM,
1079 .internal_format = GL_RGB10_A2,
1080 },
1081 {
1082 .image_format = __DRI_IMAGE_FORMAT_XBGR2101010,
1083 .mesa_format = MESA_FORMAT_R10G10B10X2_UNORM,
1084 .internal_format = GL_RGB10_A2,
1085 },
1086 {
1087 .image_format = __DRI_IMAGE_FORMAT_ARGB8888,
1088 .mesa_format = MESA_FORMAT_B8G8R8A8_UNORM,
1089 .internal_format = GL_RGBA8,
1090 },
1091 {
1092 .image_format = __DRI_IMAGE_FORMAT_ABGR8888,
1093 .mesa_format = MESA_FORMAT_R8G8B8A8_UNORM,
1094 .internal_format = GL_RGBA8,
1095 },
1096 {
1097 .image_format = __DRI_IMAGE_FORMAT_XBGR8888,
1098 .mesa_format = MESA_FORMAT_R8G8B8X8_UNORM,
1099 .internal_format = GL_RGB8,
1100 },
1101 {
1102 .image_format = __DRI_IMAGE_FORMAT_R8,
1103 .mesa_format = MESA_FORMAT_R_UNORM8,
1104 .internal_format = GL_R8,
1105 },
1106 {
1107 .image_format = __DRI_IMAGE_FORMAT_R8,
1108 .mesa_format = MESA_FORMAT_L_UNORM8,
1109 .internal_format = GL_R8,
1110 },
1111 #if UTIL_ARCH_LITTLE_ENDIAN
1112 {
1113 .image_format = __DRI_IMAGE_FORMAT_GR88,
1114 .mesa_format = MESA_FORMAT_RG_UNORM8,
1115 .internal_format = GL_RG8,
1116 },
1117 {
1118 .image_format = __DRI_IMAGE_FORMAT_GR88,
1119 .mesa_format = MESA_FORMAT_LA_UNORM8,
1120 .internal_format = GL_RG8,
1121 },
1122 #endif
1123 {
1124 .image_format = __DRI_IMAGE_FORMAT_SABGR8,
1125 .mesa_format = MESA_FORMAT_R8G8B8A8_SRGB,
1126 .internal_format = GL_SRGB8_ALPHA8,
1127 },
1128 {
1129 .image_format = __DRI_IMAGE_FORMAT_SARGB8,
1130 .mesa_format = MESA_FORMAT_B8G8R8A8_SRGB,
1131 .internal_format = GL_SRGB8_ALPHA8,
1132 },
1133 {
1134 .image_format = __DRI_IMAGE_FORMAT_SXRGB8,
1135 .mesa_format = MESA_FORMAT_B8G8R8X8_SRGB,
1136 .internal_format = GL_SRGB8_ALPHA8,
1137 },
1138 {
1139 .image_format = __DRI_IMAGE_FORMAT_R16,
1140 .mesa_format = MESA_FORMAT_R_UNORM16,
1141 .internal_format = GL_R16,
1142 },
1143 {
1144 .image_format = __DRI_IMAGE_FORMAT_R16,
1145 .mesa_format = MESA_FORMAT_L_UNORM16,
1146 .internal_format = GL_R16,
1147 },
1148 #if UTIL_ARCH_LITTLE_ENDIAN
1149 {
1150 .image_format = __DRI_IMAGE_FORMAT_GR1616,
1151 .mesa_format = MESA_FORMAT_RG_UNORM16,
1152 .internal_format = GL_RG16,
1153 },
1154 {
1155 .image_format = __DRI_IMAGE_FORMAT_GR1616,
1156 .mesa_format = MESA_FORMAT_LA_UNORM16,
1157 .internal_format = GL_RG16,
1158 },
1159 #endif
1160 };
1161
1162 uint32_t
driGLFormatToImageFormat(mesa_format format)1163 driGLFormatToImageFormat(mesa_format format)
1164 {
1165 for (size_t i = 0; i < ARRAY_SIZE(format_mapping); i++)
1166 if (format_mapping[i].mesa_format == format)
1167 return format_mapping[i].image_format;
1168
1169 return __DRI_IMAGE_FORMAT_NONE;
1170 }
1171
1172 uint32_t
driGLFormatToSizedInternalGLFormat(mesa_format format)1173 driGLFormatToSizedInternalGLFormat(mesa_format format)
1174 {
1175 for (size_t i = 0; i < ARRAY_SIZE(format_mapping); i++)
1176 if (format_mapping[i].mesa_format == format)
1177 return format_mapping[i].internal_format;
1178
1179 return GL_NONE;
1180 }
1181
1182 mesa_format
driImageFormatToGLFormat(uint32_t image_format)1183 driImageFormatToGLFormat(uint32_t image_format)
1184 {
1185 for (size_t i = 0; i < ARRAY_SIZE(format_mapping); i++)
1186 if (format_mapping[i].image_format == image_format)
1187 return format_mapping[i].mesa_format;
1188
1189 return MESA_FORMAT_NONE;
1190 }
1191
1192 /** Image driver interface */
1193 const __DRIimageDriverExtension driImageDriverExtension = {
1194 .base = { __DRI_IMAGE_DRIVER, 1 },
1195
1196 .createNewScreen2 = driCreateNewScreen2,
1197 .createNewDrawable = driCreateNewDrawable,
1198 .getAPIMask = driGetAPIMask,
1199 .createContextAttribs = driCreateContextAttribs,
1200 };
1201