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