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