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