3a03e4d0b0161fbbad4994268d4e26f78d9bf48e
[mesa.git] / src / mesa / drivers / dri / common / dri_util.c
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 "utils.h"
45 #include "util/u_endian.h"
46 #include "util/xmlpool.h"
47 #include "main/mtypes.h"
48 #include "main/framebuffer.h"
49 #include "main/version.h"
50 #include "main/debug_output.h"
51 #include "main/errors.h"
52 #include "main/macros.h"
53
54 const char __dri2ConfigOptions[] =
55 DRI_CONF_BEGIN
56 DRI_CONF_SECTION_PERFORMANCE
57 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1)
58 DRI_CONF_SECTION_END
59 DRI_CONF_END;
60
61 /*****************************************************************/
62 /** \name Screen handling functions */
63 /*****************************************************************/
64 /*@{*/
65
66 static void
67 setupLoaderExtensions(__DRIscreen *psp,
68 const __DRIextension **extensions)
69 {
70 int i;
71
72 for (i = 0; extensions[i]; i++) {
73 if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0)
74 psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i];
75 if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0)
76 psp->dri2.image = (__DRIimageLookupExtension *) extensions[i];
77 if (strcmp(extensions[i]->name, __DRI_USE_INVALIDATE) == 0)
78 psp->dri2.useInvalidate = (__DRIuseInvalidateExtension *) extensions[i];
79 if (strcmp(extensions[i]->name, __DRI_BACKGROUND_CALLABLE) == 0)
80 psp->dri2.backgroundCallable = (__DRIbackgroundCallableExtension *) extensions[i];
81 if (strcmp(extensions[i]->name, __DRI_SWRAST_LOADER) == 0)
82 psp->swrast_loader = (__DRIswrastLoaderExtension *) extensions[i];
83 if (strcmp(extensions[i]->name, __DRI_IMAGE_LOADER) == 0)
84 psp->image.loader = (__DRIimageLoaderExtension *) extensions[i];
85 if (strcmp(extensions[i]->name, __DRI_MUTABLE_RENDER_BUFFER_LOADER) == 0)
86 psp->mutableRenderBuffer.loader = (__DRImutableRenderBufferLoaderExtension *) extensions[i];
87 }
88 }
89
90 /**
91 * This pointer determines which driver API we'll use in the case of the
92 * loader not passing us an explicit driver extensions list (that would,
93 * itself, contain a pointer to a driver API.)
94 *
95 * A driver's driDriverGetExtensions_drivername() can update this pointer to
96 * what it's returning, and a loader that is ignorant of createNewScreen2()
97 * will get the correct driver screen created, as long as no other
98 * driDriverGetExtensions() happened in between the first one and the
99 * createNewScreen().
100 *
101 * This allows the X Server to not require the significant dri_interface.h
102 * updates for doing createNewScreen2(), which would discourage backporting of
103 * the X Server patches to support the new loader interface.
104 */
105 const struct __DriverAPIRec *globalDriverAPI = &driDriverAPI;
106
107 /**
108 * This is the first entrypoint in the driver called by the DRI driver loader
109 * after dlopen()ing it.
110 *
111 * It's used to create global state for the driver across contexts on the same
112 * Display.
113 */
114 static __DRIscreen *
115 driCreateNewScreen2(int scrn, int fd,
116 const __DRIextension **extensions,
117 const __DRIextension **driver_extensions,
118 const __DRIconfig ***driver_configs, void *data)
119 {
120 static const __DRIextension *emptyExtensionList[] = { NULL };
121 __DRIscreen *psp;
122
123 psp = calloc(1, sizeof(*psp));
124 if (!psp)
125 return NULL;
126
127 /* By default, use the global driDriverAPI symbol (non-megadrivers). */
128 psp->driver = globalDriverAPI;
129
130 /* If the driver exposes its vtable through its extensions list
131 * (megadrivers), use that instead.
132 */
133 if (driver_extensions) {
134 for (int i = 0; driver_extensions[i]; i++) {
135 if (strcmp(driver_extensions[i]->name, __DRI_DRIVER_VTABLE) == 0) {
136 psp->driver =
137 ((__DRIDriverVtableExtension *)driver_extensions[i])->vtable;
138 }
139 }
140 }
141
142 setupLoaderExtensions(psp, extensions);
143
144 psp->loaderPrivate = data;
145
146 psp->extensions = emptyExtensionList;
147 psp->fd = fd;
148 psp->myNum = scrn;
149
150 /* Option parsing before ->InitScreen(), as some options apply there. */
151 driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions);
152 driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum,
153 "dri2", NULL, NULL, 0);
154
155 *driver_configs = psp->driver->InitScreen(psp);
156 if (*driver_configs == NULL) {
157 free(psp);
158 return NULL;
159 }
160
161 struct gl_constants consts = { 0 };
162 gl_api api;
163 unsigned version;
164
165 api = API_OPENGLES2;
166 if (_mesa_override_gl_version_contextless(&consts, &api, &version))
167 psp->max_gl_es2_version = version;
168
169 api = API_OPENGL_COMPAT;
170 if (_mesa_override_gl_version_contextless(&consts, &api, &version)) {
171 psp->max_gl_core_version = version;
172 if (api == API_OPENGL_COMPAT)
173 psp->max_gl_compat_version = version;
174 }
175
176 psp->api_mask = 0;
177 if (psp->max_gl_compat_version > 0)
178 psp->api_mask |= (1 << __DRI_API_OPENGL);
179 if (psp->max_gl_core_version > 0)
180 psp->api_mask |= (1 << __DRI_API_OPENGL_CORE);
181 if (psp->max_gl_es1_version > 0)
182 psp->api_mask |= (1 << __DRI_API_GLES);
183 if (psp->max_gl_es2_version > 0)
184 psp->api_mask |= (1 << __DRI_API_GLES2);
185 if (psp->max_gl_es2_version >= 30)
186 psp->api_mask |= (1 << __DRI_API_GLES3);
187
188 return psp;
189 }
190
191 static __DRIscreen *
192 dri2CreateNewScreen(int scrn, int fd,
193 const __DRIextension **extensions,
194 const __DRIconfig ***driver_configs, void *data)
195 {
196 return driCreateNewScreen2(scrn, fd, extensions, NULL,
197 driver_configs, data);
198 }
199
200 /** swrast driver createNewScreen entrypoint. */
201 static __DRIscreen *
202 driSWRastCreateNewScreen(int scrn, const __DRIextension **extensions,
203 const __DRIconfig ***driver_configs, void *data)
204 {
205 return driCreateNewScreen2(scrn, -1, extensions, NULL,
206 driver_configs, data);
207 }
208
209 static __DRIscreen *
210 driSWRastCreateNewScreen2(int scrn, const __DRIextension **extensions,
211 const __DRIextension **driver_extensions,
212 const __DRIconfig ***driver_configs, void *data)
213 {
214 return driCreateNewScreen2(scrn, -1, extensions, driver_extensions,
215 driver_configs, data);
216 }
217
218 /**
219 * Destroy the per-screen private information.
220 *
221 * \internal
222 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
223 * drmClose(), and finally frees \p screenPrivate.
224 */
225 static void driDestroyScreen(__DRIscreen *psp)
226 {
227 if (psp) {
228 /* No interaction with the X-server is possible at this point. This
229 * routine is called after XCloseDisplay, so there is no protocol
230 * stream open to the X-server anymore.
231 */
232
233 psp->driver->DestroyScreen(psp);
234
235 driDestroyOptionCache(&psp->optionCache);
236 driDestroyOptionInfo(&psp->optionInfo);
237
238 free(psp);
239 }
240 }
241
242 static const __DRIextension **driGetExtensions(__DRIscreen *psp)
243 {
244 return psp->extensions;
245 }
246
247 /*@}*/
248
249
250 static bool
251 validate_context_version(__DRIscreen *screen,
252 int mesa_api,
253 unsigned major_version,
254 unsigned minor_version,
255 unsigned *dri_ctx_error)
256 {
257 unsigned req_version = 10 * major_version + minor_version;
258 unsigned max_version = 0;
259
260 switch (mesa_api) {
261 case API_OPENGL_COMPAT:
262 max_version = screen->max_gl_compat_version;
263 break;
264 case API_OPENGL_CORE:
265 max_version = screen->max_gl_core_version;
266 break;
267 case API_OPENGLES:
268 max_version = screen->max_gl_es1_version;
269 break;
270 case API_OPENGLES2:
271 max_version = screen->max_gl_es2_version;
272 break;
273 default:
274 max_version = 0;
275 break;
276 }
277
278 if (max_version == 0) {
279 *dri_ctx_error = __DRI_CTX_ERROR_BAD_API;
280 return false;
281 } else if (req_version > max_version) {
282 *dri_ctx_error = __DRI_CTX_ERROR_BAD_VERSION;
283 return false;
284 }
285
286 return true;
287 }
288
289 /*****************************************************************/
290 /** \name Context handling functions */
291 /*****************************************************************/
292 /*@{*/
293
294 static __DRIcontext *
295 driCreateContextAttribs(__DRIscreen *screen, int api,
296 const __DRIconfig *config,
297 __DRIcontext *shared,
298 unsigned num_attribs,
299 const uint32_t *attribs,
300 unsigned *error,
301 void *data)
302 {
303 __DRIcontext *context;
304 const struct gl_config *modes = (config != NULL) ? &config->modes : NULL;
305 void *shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
306 gl_api mesa_api;
307 struct __DriverContextConfig ctx_config;
308
309 ctx_config.major_version = 1;
310 ctx_config.minor_version = 0;
311 ctx_config.flags = 0;
312 ctx_config.attribute_mask = 0;
313 ctx_config.priority = __DRI_CTX_PRIORITY_MEDIUM;
314
315 assert((num_attribs == 0) || (attribs != NULL));
316
317 if (!(screen->api_mask & (1 << api))) {
318 *error = __DRI_CTX_ERROR_BAD_API;
319 return NULL;
320 }
321
322 switch (api) {
323 case __DRI_API_OPENGL:
324 mesa_api = API_OPENGL_COMPAT;
325 break;
326 case __DRI_API_GLES:
327 mesa_api = API_OPENGLES;
328 break;
329 case __DRI_API_GLES2:
330 case __DRI_API_GLES3:
331 mesa_api = API_OPENGLES2;
332 break;
333 case __DRI_API_OPENGL_CORE:
334 mesa_api = API_OPENGL_CORE;
335 break;
336 default:
337 *error = __DRI_CTX_ERROR_BAD_API;
338 return NULL;
339 }
340
341 for (unsigned i = 0; i < num_attribs; i++) {
342 switch (attribs[i * 2]) {
343 case __DRI_CTX_ATTRIB_MAJOR_VERSION:
344 ctx_config.major_version = attribs[i * 2 + 1];
345 break;
346 case __DRI_CTX_ATTRIB_MINOR_VERSION:
347 ctx_config.minor_version = attribs[i * 2 + 1];
348 break;
349 case __DRI_CTX_ATTRIB_FLAGS:
350 ctx_config.flags = attribs[i * 2 + 1];
351 break;
352 case __DRI_CTX_ATTRIB_RESET_STRATEGY:
353 if (attribs[i * 2 + 1] != __DRI_CTX_RESET_NO_NOTIFICATION) {
354 ctx_config.attribute_mask |=
355 __DRIVER_CONTEXT_ATTRIB_RESET_STRATEGY;
356 ctx_config.reset_strategy = attribs[i * 2 + 1];
357 } else {
358 ctx_config.attribute_mask &=
359 ~__DRIVER_CONTEXT_ATTRIB_RESET_STRATEGY;
360 }
361 break;
362 case __DRI_CTX_ATTRIB_PRIORITY:
363 ctx_config.attribute_mask |= __DRIVER_CONTEXT_ATTRIB_PRIORITY;
364 ctx_config.priority = attribs[i * 2 + 1];
365 break;
366 case __DRI_CTX_ATTRIB_RELEASE_BEHAVIOR:
367 if (attribs[i * 2 + 1] != __DRI_CTX_RELEASE_BEHAVIOR_FLUSH) {
368 ctx_config.attribute_mask |=
369 __DRIVER_CONTEXT_ATTRIB_RELEASE_BEHAVIOR;
370 ctx_config.release_behavior = attribs[i * 2 + 1];
371 } else {
372 ctx_config.attribute_mask &=
373 ~__DRIVER_CONTEXT_ATTRIB_RELEASE_BEHAVIOR;
374 }
375 break;
376 default:
377 /* We can't create a context that satisfies the requirements of an
378 * attribute that we don't understand. Return failure.
379 */
380 assert(!"Should not get here.");
381 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
382 return NULL;
383 }
384 }
385
386 /* The specific Mesa driver may not support the GL_ARB_compatibilty
387 * extension or the compatibility profile. In that case, we treat an
388 * API_OPENGL_COMPAT 3.1 as API_OPENGL_CORE. We reject API_OPENGL_COMPAT
389 * 3.2+ in any case.
390 */
391 if (mesa_api == API_OPENGL_COMPAT &&
392 ctx_config.major_version == 3 && ctx_config.minor_version == 1 &&
393 screen->max_gl_compat_version < 31)
394 mesa_api = API_OPENGL_CORE;
395
396 /* The latest version of EGL_KHR_create_context spec says:
397 *
398 * "If the EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR flag bit is set in
399 * EGL_CONTEXT_FLAGS_KHR, then a <debug context> will be created.
400 * [...] This bit is supported for OpenGL and OpenGL ES contexts.
401 *
402 * No other EGL_CONTEXT_OPENGL_*_BIT is legal for an ES context.
403 *
404 * However, Mesa's EGL layer translates the context attribute
405 * EGL_CONTEXT_OPENGL_ROBUST_ACCESS into the context flag
406 * __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS. That attribute is legal for ES
407 * (with EGL 1.5 or EGL_EXT_create_context_robustness) and GL (only with
408 * EGL 1.5).
409 *
410 * From the EGL_EXT_create_context_robustness spec:
411 *
412 * This extension is written against the OpenGL ES 2.0 Specification
413 * but can apply to OpenGL ES 1.1 and up.
414 *
415 * From the EGL 1.5 (2014.08.27) spec, p55:
416 *
417 * If the EGL_CONTEXT_OPENGL_ROBUST_ACCESS attribute is set to
418 * EGL_TRUE, a context supporting robust buffer access will be created.
419 * OpenGL contexts must support the GL_ARB_robustness extension, or
420 * equivalent core API functional- ity. OpenGL ES contexts must support
421 * the GL_EXT_robustness extension, or equivalent core API
422 * functionality.
423 */
424 if (mesa_api != API_OPENGL_COMPAT
425 && mesa_api != API_OPENGL_CORE
426 && (ctx_config.flags & ~(__DRI_CTX_FLAG_DEBUG |
427 __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS |
428 __DRI_CTX_FLAG_NO_ERROR))) {
429 *error = __DRI_CTX_ERROR_BAD_FLAG;
430 return NULL;
431 }
432
433 /* There are no forward-compatible contexts before OpenGL 3.0. The
434 * GLX_ARB_create_context spec says:
435 *
436 * "Forward-compatible contexts are defined only for OpenGL versions
437 * 3.0 and later."
438 *
439 * Forward-looking contexts are supported by silently converting the
440 * requested API to API_OPENGL_CORE.
441 *
442 * In Mesa, a debug context is the same as a regular context.
443 */
444 if ((ctx_config.flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) {
445 mesa_api = API_OPENGL_CORE;
446 }
447
448 const uint32_t allowed_flags = (__DRI_CTX_FLAG_DEBUG
449 | __DRI_CTX_FLAG_FORWARD_COMPATIBLE
450 | __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS
451 | __DRI_CTX_FLAG_NO_ERROR);
452 if (ctx_config.flags & ~allowed_flags) {
453 *error = __DRI_CTX_ERROR_UNKNOWN_FLAG;
454 return NULL;
455 }
456
457 if (!validate_context_version(screen, mesa_api,
458 ctx_config.major_version,
459 ctx_config.minor_version,
460 error))
461 return NULL;
462
463 context = calloc(1, sizeof *context);
464 if (!context) {
465 *error = __DRI_CTX_ERROR_NO_MEMORY;
466 return NULL;
467 }
468
469 context->loaderPrivate = data;
470
471 context->driScreenPriv = screen;
472 context->driDrawablePriv = NULL;
473 context->driReadablePriv = NULL;
474
475 if (!screen->driver->CreateContext(mesa_api, modes, context,
476 &ctx_config, error, shareCtx)) {
477 free(context);
478 return NULL;
479 }
480
481 *error = __DRI_CTX_ERROR_SUCCESS;
482 return context;
483 }
484
485 void
486 driContextSetFlags(struct gl_context *ctx, uint32_t flags)
487 {
488 if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0)
489 ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT;
490 if ((flags & __DRI_CTX_FLAG_DEBUG) != 0) {
491 _mesa_set_debug_state_int(ctx, GL_DEBUG_OUTPUT, GL_TRUE);
492 ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT;
493 }
494 if ((flags & __DRI_CTX_FLAG_NO_ERROR) != 0)
495 ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR;
496 }
497
498 static __DRIcontext *
499 driCreateNewContextForAPI(__DRIscreen *screen, int api,
500 const __DRIconfig *config,
501 __DRIcontext *shared, void *data)
502 {
503 unsigned error;
504
505 return driCreateContextAttribs(screen, api, config, shared, 0, NULL,
506 &error, data);
507 }
508
509 static __DRIcontext *
510 driCreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
511 __DRIcontext *shared, void *data)
512 {
513 return driCreateNewContextForAPI(screen, __DRI_API_OPENGL,
514 config, shared, data);
515 }
516
517 /**
518 * Destroy the per-context private information.
519 *
520 * \internal
521 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
522 * drmDestroyContext(), and finally frees \p contextPrivate.
523 */
524 static void
525 driDestroyContext(__DRIcontext *pcp)
526 {
527 if (pcp) {
528 pcp->driScreenPriv->driver->DestroyContext(pcp);
529 free(pcp);
530 }
531 }
532
533 static int
534 driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask)
535 {
536 (void) dest;
537 (void) src;
538 (void) mask;
539 return GL_FALSE;
540 }
541
542 /*@}*/
543
544
545 /*****************************************************************/
546 /** \name Context (un)binding functions */
547 /*****************************************************************/
548 /*@{*/
549
550 static void dri_get_drawable(__DRIdrawable *pdp);
551 static void dri_put_drawable(__DRIdrawable *pdp);
552
553 /**
554 * This function takes both a read buffer and a draw buffer. This is needed
555 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
556 * function.
557 */
558 static int driBindContext(__DRIcontext *pcp,
559 __DRIdrawable *pdp,
560 __DRIdrawable *prp)
561 {
562 /*
563 ** Assume error checking is done properly in glXMakeCurrent before
564 ** calling driUnbindContext.
565 */
566
567 if (!pcp)
568 return GL_FALSE;
569
570 /* Bind the drawable to the context */
571 pcp->driDrawablePriv = pdp;
572 pcp->driReadablePriv = prp;
573 if (pdp) {
574 pdp->driContextPriv = pcp;
575 dri_get_drawable(pdp);
576 }
577 if (prp && pdp != prp) {
578 dri_get_drawable(prp);
579 }
580
581 return pcp->driScreenPriv->driver->MakeCurrent(pcp, pdp, prp);
582 }
583
584 /**
585 * Unbind context.
586 *
587 * \param scrn the screen.
588 * \param gc context.
589 *
590 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
591 *
592 * \internal
593 * This function calls __DriverAPIRec::UnbindContext, and then decrements
594 * __DRIdrawableRec::refcount which must be non-zero for a successful
595 * return.
596 *
597 * While casting the opaque private pointers associated with the parameters
598 * into their respective real types it also assures they are not \c NULL.
599 */
600 static int driUnbindContext(__DRIcontext *pcp)
601 {
602 __DRIdrawable *pdp;
603 __DRIdrawable *prp;
604
605 /*
606 ** Assume error checking is done properly in glXMakeCurrent before
607 ** calling driUnbindContext.
608 */
609
610 if (pcp == NULL)
611 return GL_FALSE;
612
613 /*
614 ** Call driUnbindContext before checking for valid drawables
615 ** to handle surfaceless contexts properly.
616 */
617 pcp->driScreenPriv->driver->UnbindContext(pcp);
618
619 pdp = pcp->driDrawablePriv;
620 prp = pcp->driReadablePriv;
621
622 /* already unbound */
623 if (!pdp && !prp)
624 return GL_TRUE;
625
626 assert(pdp);
627 if (pdp->refcount == 0) {
628 /* ERROR!!! */
629 return GL_FALSE;
630 }
631
632 dri_put_drawable(pdp);
633
634 if (prp != pdp) {
635 if (prp->refcount == 0) {
636 /* ERROR!!! */
637 return GL_FALSE;
638 }
639
640 dri_put_drawable(prp);
641 }
642
643 pcp->driDrawablePriv = NULL;
644 pcp->driReadablePriv = NULL;
645
646 return GL_TRUE;
647 }
648
649 /*@}*/
650
651
652 static void dri_get_drawable(__DRIdrawable *pdp)
653 {
654 pdp->refcount++;
655 }
656
657 static void dri_put_drawable(__DRIdrawable *pdp)
658 {
659 if (pdp) {
660 pdp->refcount--;
661 if (pdp->refcount)
662 return;
663
664 pdp->driScreenPriv->driver->DestroyBuffer(pdp);
665 free(pdp);
666 }
667 }
668
669 static __DRIdrawable *
670 driCreateNewDrawable(__DRIscreen *screen,
671 const __DRIconfig *config,
672 void *data)
673 {
674 __DRIdrawable *pdraw;
675
676 assert(data != NULL);
677
678 pdraw = malloc(sizeof *pdraw);
679 if (!pdraw)
680 return NULL;
681
682 pdraw->loaderPrivate = data;
683
684 pdraw->driScreenPriv = screen;
685 pdraw->driContextPriv = NULL;
686 pdraw->refcount = 0;
687 pdraw->lastStamp = 0;
688 pdraw->w = 0;
689 pdraw->h = 0;
690
691 dri_get_drawable(pdraw);
692
693 if (!screen->driver->CreateBuffer(screen, pdraw, &config->modes,
694 GL_FALSE)) {
695 free(pdraw);
696 return NULL;
697 }
698
699 pdraw->dri2.stamp = pdraw->lastStamp + 1;
700
701 return pdraw;
702 }
703
704 static void
705 driDestroyDrawable(__DRIdrawable *pdp)
706 {
707 /*
708 * The loader's data structures are going away, even if pdp itself stays
709 * around for the time being because it is currently bound. This happens
710 * when a currently bound GLX pixmap is destroyed.
711 *
712 * Clear out the pointer back into the loader's data structures to avoid
713 * accessing an outdated pointer.
714 */
715 pdp->loaderPrivate = NULL;
716
717 dri_put_drawable(pdp);
718 }
719
720 static __DRIbuffer *
721 dri2AllocateBuffer(__DRIscreen *screen,
722 unsigned int attachment, unsigned int format,
723 int width, int height)
724 {
725 return screen->driver->AllocateBuffer(screen, attachment, format,
726 width, height);
727 }
728
729 static void
730 dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer)
731 {
732 screen->driver->ReleaseBuffer(screen, buffer);
733 }
734
735
736 static int
737 dri2ConfigQueryb(__DRIscreen *screen, const char *var, unsigned char *val)
738 {
739 if (!driCheckOption(&screen->optionCache, var, DRI_BOOL))
740 return -1;
741
742 *val = driQueryOptionb(&screen->optionCache, var);
743
744 return 0;
745 }
746
747 static int
748 dri2ConfigQueryi(__DRIscreen *screen, const char *var, int *val)
749 {
750 if (!driCheckOption(&screen->optionCache, var, DRI_INT) &&
751 !driCheckOption(&screen->optionCache, var, DRI_ENUM))
752 return -1;
753
754 *val = driQueryOptioni(&screen->optionCache, var);
755
756 return 0;
757 }
758
759 static int
760 dri2ConfigQueryf(__DRIscreen *screen, const char *var, float *val)
761 {
762 if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT))
763 return -1;
764
765 *val = driQueryOptionf(&screen->optionCache, var);
766
767 return 0;
768 }
769
770 static unsigned int
771 driGetAPIMask(__DRIscreen *screen)
772 {
773 return screen->api_mask;
774 }
775
776 /**
777 * swrast swapbuffers entrypoint.
778 *
779 * DRI2 implements this inside the loader with only flushes handled by the
780 * driver.
781 */
782 static void
783 driSwapBuffers(__DRIdrawable *pdp)
784 {
785 assert(pdp->driScreenPriv->swrast_loader);
786
787 pdp->driScreenPriv->driver->SwapBuffers(pdp);
788 }
789
790 /** Core interface */
791 const __DRIcoreExtension driCoreExtension = {
792 .base = { __DRI_CORE, 2 },
793
794 .createNewScreen = NULL,
795 .destroyScreen = driDestroyScreen,
796 .getExtensions = driGetExtensions,
797 .getConfigAttrib = driGetConfigAttrib,
798 .indexConfigAttrib = driIndexConfigAttrib,
799 .createNewDrawable = NULL,
800 .destroyDrawable = driDestroyDrawable,
801 .swapBuffers = driSwapBuffers, /* swrast */
802 .createNewContext = driCreateNewContext, /* swrast */
803 .copyContext = driCopyContext,
804 .destroyContext = driDestroyContext,
805 .bindContext = driBindContext,
806 .unbindContext = driUnbindContext
807 };
808
809 /** DRI2 interface */
810 const __DRIdri2Extension driDRI2Extension = {
811 .base = { __DRI_DRI2, 4 },
812
813 .createNewScreen = dri2CreateNewScreen,
814 .createNewDrawable = driCreateNewDrawable,
815 .createNewContext = driCreateNewContext,
816 .getAPIMask = driGetAPIMask,
817 .createNewContextForAPI = driCreateNewContextForAPI,
818 .allocateBuffer = dri2AllocateBuffer,
819 .releaseBuffer = dri2ReleaseBuffer,
820 .createContextAttribs = driCreateContextAttribs,
821 .createNewScreen2 = driCreateNewScreen2,
822 };
823
824 const __DRIswrastExtension driSWRastExtension = {
825 .base = { __DRI_SWRAST, 4 },
826
827 .createNewScreen = driSWRastCreateNewScreen,
828 .createNewDrawable = driCreateNewDrawable,
829 .createNewContextForAPI = driCreateNewContextForAPI,
830 .createContextAttribs = driCreateContextAttribs,
831 .createNewScreen2 = driSWRastCreateNewScreen2,
832 };
833
834 const __DRI2configQueryExtension dri2ConfigQueryExtension = {
835 .base = { __DRI2_CONFIG_QUERY, 1 },
836
837 .configQueryb = dri2ConfigQueryb,
838 .configQueryi = dri2ConfigQueryi,
839 .configQueryf = dri2ConfigQueryf,
840 };
841
842 const __DRI2flushControlExtension dri2FlushControlExtension = {
843 .base = { __DRI2_FLUSH_CONTROL, 1 }
844 };
845
846 void
847 dri2InvalidateDrawable(__DRIdrawable *drawable)
848 {
849 drawable->dri2.stamp++;
850 }
851
852 /**
853 * Check that the gl_framebuffer associated with dPriv is the right size.
854 * Resize the gl_framebuffer if needed.
855 * It's expected that the dPriv->driverPrivate member points to a
856 * gl_framebuffer object.
857 */
858 void
859 driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv)
860 {
861 struct gl_framebuffer *fb = (struct gl_framebuffer *) dPriv->driverPrivate;
862 if (fb && (dPriv->w != fb->Width || dPriv->h != fb->Height)) {
863 _mesa_resize_framebuffer(ctx, fb, dPriv->w, dPriv->h);
864 /* if the driver needs the hw lock for ResizeBuffers, the drawable
865 might have changed again by now */
866 assert(fb->Width == dPriv->w);
867 assert(fb->Height == dPriv->h);
868 }
869 }
870
871 /*
872 * Note: the first match is returned, which is important for formats like
873 * __DRI_IMAGE_FORMAT_R8 which maps to both MESA_FORMAT_{R,L}_UNORM8
874 */
875 static const struct {
876 uint32_t image_format;
877 mesa_format mesa_format;
878 } format_mapping[] = {
879 {
880 .image_format = __DRI_IMAGE_FORMAT_RGB565,
881 .mesa_format = MESA_FORMAT_B5G6R5_UNORM,
882 },
883 {
884 .image_format = __DRI_IMAGE_FORMAT_ARGB1555,
885 .mesa_format = MESA_FORMAT_B5G5R5A1_UNORM,
886 },
887 {
888 .image_format = __DRI_IMAGE_FORMAT_XRGB8888,
889 .mesa_format = MESA_FORMAT_B8G8R8X8_UNORM,
890 },
891 {
892 .image_format = __DRI_IMAGE_FORMAT_ABGR16161616F,
893 .mesa_format = MESA_FORMAT_RGBA_FLOAT16,
894 },
895 {
896 .image_format = __DRI_IMAGE_FORMAT_XBGR16161616F,
897 .mesa_format = MESA_FORMAT_RGBX_FLOAT16,
898 },
899 {
900 .image_format = __DRI_IMAGE_FORMAT_ARGB2101010,
901 .mesa_format = MESA_FORMAT_B10G10R10A2_UNORM,
902 },
903 {
904 .image_format = __DRI_IMAGE_FORMAT_XRGB2101010,
905 .mesa_format = MESA_FORMAT_B10G10R10X2_UNORM,
906 },
907 {
908 .image_format = __DRI_IMAGE_FORMAT_ABGR2101010,
909 .mesa_format = MESA_FORMAT_R10G10B10A2_UNORM,
910 },
911 {
912 .image_format = __DRI_IMAGE_FORMAT_XBGR2101010,
913 .mesa_format = MESA_FORMAT_R10G10B10X2_UNORM,
914 },
915 {
916 .image_format = __DRI_IMAGE_FORMAT_ARGB8888,
917 .mesa_format = MESA_FORMAT_B8G8R8A8_UNORM,
918 },
919 {
920 .image_format = __DRI_IMAGE_FORMAT_ABGR8888,
921 .mesa_format = MESA_FORMAT_R8G8B8A8_UNORM,
922 },
923 {
924 .image_format = __DRI_IMAGE_FORMAT_XBGR8888,
925 .mesa_format = MESA_FORMAT_R8G8B8X8_UNORM,
926 },
927 {
928 .image_format = __DRI_IMAGE_FORMAT_R8,
929 .mesa_format = MESA_FORMAT_R_UNORM8,
930 },
931 {
932 .image_format = __DRI_IMAGE_FORMAT_R8,
933 .mesa_format = MESA_FORMAT_L_UNORM8,
934 },
935 #if UTIL_ARCH_LITTLE_ENDIAN
936 {
937 .image_format = __DRI_IMAGE_FORMAT_GR88,
938 .mesa_format = MESA_FORMAT_RG_UNORM8,
939 },
940 {
941 .image_format = __DRI_IMAGE_FORMAT_GR88,
942 .mesa_format = MESA_FORMAT_LA_UNORM8,
943 },
944 #endif
945 {
946 .image_format = __DRI_IMAGE_FORMAT_SABGR8,
947 .mesa_format = MESA_FORMAT_R8G8B8A8_SRGB,
948 },
949 {
950 .image_format = __DRI_IMAGE_FORMAT_SARGB8,
951 .mesa_format = MESA_FORMAT_B8G8R8A8_SRGB,
952 },
953 {
954 .image_format = __DRI_IMAGE_FORMAT_R16,
955 .mesa_format = MESA_FORMAT_R_UNORM16,
956 },
957 {
958 .image_format = __DRI_IMAGE_FORMAT_R16,
959 .mesa_format = MESA_FORMAT_L_UNORM16,
960 },
961 #if UTIL_ARCH_LITTLE_ENDIAN
962 {
963 .image_format = __DRI_IMAGE_FORMAT_GR1616,
964 .mesa_format = MESA_FORMAT_RG_UNORM16,
965 },
966 {
967 .image_format = __DRI_IMAGE_FORMAT_GR1616,
968 .mesa_format = MESA_FORMAT_LA_UNORM16,
969 },
970 #endif
971 };
972
973 uint32_t
974 driGLFormatToImageFormat(mesa_format format)
975 {
976 for (size_t i = 0; i < ARRAY_SIZE(format_mapping); i++)
977 if (format_mapping[i].mesa_format == format)
978 return format_mapping[i].image_format;
979
980 return __DRI_IMAGE_FORMAT_NONE;
981 }
982
983 mesa_format
984 driImageFormatToGLFormat(uint32_t image_format)
985 {
986 for (size_t i = 0; i < ARRAY_SIZE(format_mapping); i++)
987 if (format_mapping[i].image_format == image_format)
988 return format_mapping[i].mesa_format;
989
990 return MESA_FORMAT_NONE;
991 }
992
993 /** Image driver interface */
994 const __DRIimageDriverExtension driImageDriverExtension = {
995 .base = { __DRI_IMAGE_DRIVER, 1 },
996
997 .createNewScreen2 = driCreateNewScreen2,
998 .createNewDrawable = driCreateNewDrawable,
999 .getAPIMask = driGetAPIMask,
1000 .createContextAttribs = driCreateContextAttribs,
1001 };
1002
1003 /* swrast copy sub buffer entrypoint. */
1004 static void driCopySubBuffer(__DRIdrawable *pdp, int x, int y,
1005 int w, int h)
1006 {
1007 assert(pdp->driScreenPriv->swrast_loader);
1008
1009 pdp->driScreenPriv->driver->CopySubBuffer(pdp, x, y, w, h);
1010 }
1011
1012 /* for swrast only */
1013 const __DRIcopySubBufferExtension driCopySubBufferExtension = {
1014 .base = { __DRI_COPY_SUB_BUFFER, 1 },
1015
1016 .copySubBuffer = driCopySubBuffer,
1017 };
1018
1019 const __DRInoErrorExtension dri2NoErrorExtension = {
1020 .base = { __DRI2_NO_ERROR, 1 },
1021 };