• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
54 driOptionDescription __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 
70 static void
setupLoaderExtensions(__DRIscreen * psp,const __DRIextension ** extensions)71 setupLoaderExtensions(__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  */
109 const 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  */
118 static __DRIscreen *
driCreateNewScreen2(int scrn,int fd,const __DRIextension ** extensions,const __DRIextension ** driver_extensions,const __DRIconfig *** driver_configs,void * data)119 driCreateNewScreen2(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 
196 static __DRIscreen *
dri2CreateNewScreen(int scrn,int fd,const __DRIextension ** extensions,const __DRIconfig *** driver_configs,void * data)197 dri2CreateNewScreen(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. */
206 static __DRIscreen *
driSWRastCreateNewScreen(int scrn,const __DRIextension ** extensions,const __DRIconfig *** driver_configs,void * data)207 driSWRastCreateNewScreen(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 
214 static __DRIscreen *
driSWRastCreateNewScreen2(int scrn,const __DRIextension ** extensions,const __DRIextension ** driver_extensions,const __DRIconfig *** driver_configs,void * data)215 driSWRastCreateNewScreen2(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  */
driDestroyScreen(__DRIscreen * psp)230 static 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 
driGetExtensions(__DRIscreen * psp)247 static const __DRIextension **driGetExtensions(__DRIscreen *psp)
248 {
249     return psp->extensions;
250 }
251 
252 /*@}*/
253 
254 
255 static bool
validate_context_version(__DRIscreen * screen,int mesa_api,unsigned major_version,unsigned minor_version,unsigned * dri_ctx_error)256 validate_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 
299 static __DRIcontext *
driCreateContextAttribs(__DRIscreen * screen,int api,const __DRIconfig * config,__DRIcontext * shared,unsigned num_attribs,const uint32_t * attribs,unsigned * error,void * data)300 driCreateContextAttribs(__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 
490 void
driContextSetFlags(struct gl_context * ctx,uint32_t flags)491 driContextSetFlags(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 
503 static __DRIcontext *
driCreateNewContextForAPI(__DRIscreen * screen,int api,const __DRIconfig * config,__DRIcontext * shared,void * data)504 driCreateNewContextForAPI(__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 
514 static __DRIcontext *
driCreateNewContext(__DRIscreen * screen,const __DRIconfig * config,__DRIcontext * shared,void * data)515 driCreateNewContext(__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  */
529 static void
driDestroyContext(__DRIcontext * pcp)530 driDestroyContext(__DRIcontext *pcp)
531 {
532     if (pcp) {
533 	pcp->driScreenPriv->driver->DestroyContext(pcp);
534 	free(pcp);
535     }
536 }
537 
538 static int
driCopyContext(__DRIcontext * dest,__DRIcontext * src,unsigned long mask)539 driCopyContext(__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 
555 static void dri_get_drawable(__DRIdrawable *pdp);
556 static 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  */
driBindContext(__DRIcontext * pcp,__DRIdrawable * pdp,__DRIdrawable * prp)563 static 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  */
driUnbindContext(__DRIcontext * pcp)605 static 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 
dri_get_drawable(__DRIdrawable * pdp)657 static void dri_get_drawable(__DRIdrawable *pdp)
658 {
659     pdp->refcount++;
660 }
661 
dri_put_drawable(__DRIdrawable * pdp)662 static 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 
674 static __DRIdrawable *
driCreateNewDrawable(__DRIscreen * screen,const __DRIconfig * config,void * data)675 driCreateNewDrawable(__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 
709 static void
driDestroyDrawable(__DRIdrawable * pdp)710 driDestroyDrawable(__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 
725 static __DRIbuffer *
dri2AllocateBuffer(__DRIscreen * screen,unsigned int attachment,unsigned int format,int width,int height)726 dri2AllocateBuffer(__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 
734 static void
dri2ReleaseBuffer(__DRIscreen * screen,__DRIbuffer * buffer)735 dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer)
736 {
737     screen->driver->ReleaseBuffer(screen, buffer);
738 }
739 
740 
741 static int
dri2ConfigQueryb(__DRIscreen * screen,const char * var,unsigned char * val)742 dri2ConfigQueryb(__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 
752 static int
dri2ConfigQueryi(__DRIscreen * screen,const char * var,int * val)753 dri2ConfigQueryi(__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 
764 static int
dri2ConfigQueryf(__DRIscreen * screen,const char * var,float * val)765 dri2ConfigQueryf(__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 
775 static int
dri2ConfigQuerys(__DRIscreen * screen,const char * var,char ** val)776 dri2ConfigQuerys(__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 
786 static unsigned int
driGetAPIMask(__DRIscreen * screen)787 driGetAPIMask(__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  */
798 static void
driSwapBuffers(__DRIdrawable * pdp)799 driSwapBuffers(__DRIdrawable *pdp)
800 {
801     assert(pdp->driScreenPriv->swrast_loader);
802 
803     pdp->driScreenPriv->driver->SwapBuffers(pdp);
804 }
805 
806 /** Core interface */
807 const __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 */
826 const __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 
840 const __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 
850 const __DRI2configQueryExtension dri2ConfigQueryExtension = {
851    .base = { __DRI2_CONFIG_QUERY, 2 },
852 
853    .configQueryb        = dri2ConfigQueryb,
854    .configQueryi        = dri2ConfigQueryi,
855    .configQueryf        = dri2ConfigQueryf,
856    .configQuerys        = dri2ConfigQuerys,
857 };
858 
859 const __DRI2flushControlExtension dri2FlushControlExtension = {
860    .base = { __DRI2_FLUSH_CONTROL, 1 }
861 };
862 
863 void
dri2InvalidateDrawable(__DRIdrawable * drawable)864 dri2InvalidateDrawable(__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  */
875 void
driUpdateFramebufferSize(struct gl_context * ctx,const __DRIdrawable * dPriv)876 driUpdateFramebufferSize(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  */
892 static 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 
1018 uint32_t
driGLFormatToImageFormat(mesa_format format)1019 driGLFormatToImageFormat(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 
1028 uint32_t
driGLFormatToSizedInternalGLFormat(mesa_format format)1029 driGLFormatToSizedInternalGLFormat(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 
1038 mesa_format
driImageFormatToGLFormat(uint32_t image_format)1039 driImageFormatToGLFormat(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 */
1049 const __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. */
driCopySubBuffer(__DRIdrawable * pdp,int x,int y,int w,int h)1059 static 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 */
1068 const __DRIcopySubBufferExtension driCopySubBufferExtension = {
1069    .base = { __DRI_COPY_SUB_BUFFER, 1 },
1070 
1071    .copySubBuffer               = driCopySubBuffer,
1072 };
1073 
1074 const __DRInoErrorExtension dri2NoErrorExtension = {
1075    .base = { __DRI2_NO_ERROR, 1 },
1076 };
1077