2 * (C) Copyright IBM Corporation 2002, 2004
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:
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
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.
27 * DRI utility functions.
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
34 * Basically, these utility functions take care of some of the dirty details of
35 * screen initialization, context creation, context binding, DRM setup, etc.
37 * These functions are compiled into each DRI driver so libGL.so knows nothing
43 #ifndef __NOT_HAVE_DRM_H
49 #include "../glsl/glsl_parser_extras.h"
50 #include "main/mtypes.h"
51 #include "main/version.h"
52 #include "main/macros.h"
54 PUBLIC
const char __dri2ConfigOptions
[] =
56 DRI_CONF_SECTION_PERFORMANCE
57 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1
)
61 /*****************************************************************/
62 /** \name Screen handling functions */
63 /*****************************************************************/
67 setupLoaderExtensions(__DRIscreen
*psp
,
68 const __DRIextension
**extensions
)
72 for (i
= 0; extensions
[i
]; i
++) {
73 if (strcmp(extensions
[i
]->name
, __DRI_DRI2_LOADER
) == 0)
74 psp
->dri2
.loader
= (__DRIdri2LoaderExtension
*) extensions
[i
];
75 if (strcmp(extensions
[i
]->name
, __DRI_IMAGE_LOOKUP
) == 0)
76 psp
->dri2
.image
= (__DRIimageLookupExtension
*) extensions
[i
];
77 if (strcmp(extensions
[i
]->name
, __DRI_USE_INVALIDATE
) == 0)
78 psp
->dri2
.useInvalidate
= (__DRIuseInvalidateExtension
*) extensions
[i
];
79 if (strcmp(extensions
[i
]->name
, __DRI_SWRAST_LOADER
) == 0)
80 psp
->swrast_loader
= (__DRIswrastLoaderExtension
*) extensions
[i
];
85 * This is the first entrypoint in the driver called by the DRI driver loader
86 * after dlopen()ing it.
88 * It's used to create global state for the driver across contexts on the same
92 dri2CreateNewScreen2(int scrn
, int fd
,
93 const __DRIextension
**extensions
,
94 const __DRIextension
**driver_extensions
,
95 const __DRIconfig
***driver_configs
, void *data
)
97 static const __DRIextension
*emptyExtensionList
[] = { NULL
};
100 psp
= calloc(1, sizeof(*psp
));
104 /* By default, use the global driDriverAPI symbol (non-megadrivers). */
105 psp
->driver
= &driDriverAPI
;
107 /* If the driver exposes its vtable through its extensions list
108 * (megadrivers), use that instead.
110 if (driver_extensions
) {
111 for (int i
= 0; driver_extensions
[i
]; i
++) {
112 if (strcmp(driver_extensions
[i
]->name
, __DRI_DRIVER_VTABLE
) == 0) {
114 ((__DRIDriverVtableExtension
*)driver_extensions
[i
])->vtable
;
119 setupLoaderExtensions(psp
, extensions
);
121 #ifndef __NOT_HAVE_DRM_H
123 drmVersionPtr version
= drmGetVersion(fd
);
125 psp
->drm_version
.major
= version
->version_major
;
126 psp
->drm_version
.minor
= version
->version_minor
;
127 psp
->drm_version
.patch
= version
->version_patchlevel
;
128 drmFreeVersion(version
);
133 psp
->loaderPrivate
= data
;
135 psp
->extensions
= emptyExtensionList
;
139 *driver_configs
= psp
->driver
->InitScreen(psp
);
140 if (*driver_configs
== NULL
) {
145 int gl_version_override
= _mesa_get_gl_version_override();
146 if (gl_version_override
>= 31) {
147 psp
->max_gl_core_version
= MAX2(psp
->max_gl_core_version
,
148 gl_version_override
);
150 psp
->max_gl_compat_version
= MAX2(psp
->max_gl_compat_version
,
151 gl_version_override
);
154 psp
->api_mask
= (1 << __DRI_API_OPENGL
);
155 if (psp
->max_gl_core_version
> 0)
156 psp
->api_mask
|= (1 << __DRI_API_OPENGL_CORE
);
157 if (psp
->max_gl_es1_version
> 0)
158 psp
->api_mask
|= (1 << __DRI_API_GLES
);
159 if (psp
->max_gl_es2_version
> 0)
160 psp
->api_mask
|= (1 << __DRI_API_GLES2
);
161 if (psp
->max_gl_es2_version
>= 30)
162 psp
->api_mask
|= (1 << __DRI_API_GLES3
);
164 driParseOptionInfo(&psp
->optionInfo
, __dri2ConfigOptions
);
165 driParseConfigFiles(&psp
->optionCache
, &psp
->optionInfo
, psp
->myNum
, "dri2");
172 dri2CreateNewScreen(int scrn
, int fd
,
173 const __DRIextension
**extensions
,
174 const __DRIconfig
***driver_configs
, void *data
)
176 return dri2CreateNewScreen2(scrn
, fd
, extensions
, NULL
,
177 driver_configs
, data
);
180 /** swrast driver createNewScreen entrypoint. */
182 driSWRastCreateNewScreen(int scrn
, const __DRIextension
**extensions
,
183 const __DRIconfig
***driver_configs
, void *data
)
185 return dri2CreateNewScreen2(scrn
, -1, extensions
, NULL
,
186 driver_configs
, data
);
190 driSWRastCreateNewScreen2(int scrn
, const __DRIextension
**extensions
,
191 const __DRIextension
**driver_extensions
,
192 const __DRIconfig
***driver_configs
, void *data
)
194 return dri2CreateNewScreen2(scrn
, -1, extensions
, driver_extensions
,
195 driver_configs
, data
);
199 * Destroy the per-screen private information.
202 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
203 * drmClose(), and finally frees \p screenPrivate.
205 static void driDestroyScreen(__DRIscreen
*psp
)
208 /* No interaction with the X-server is possible at this point. This
209 * routine is called after XCloseDisplay, so there is no protocol
210 * stream open to the X-server anymore.
213 _mesa_destroy_shader_compiler();
215 psp
->driver
->DestroyScreen(psp
);
217 driDestroyOptionCache(&psp
->optionCache
);
218 driDestroyOptionInfo(&psp
->optionInfo
);
224 static const __DRIextension
**driGetExtensions(__DRIscreen
*psp
)
226 return psp
->extensions
;
233 validate_context_version(__DRIscreen
*screen
,
235 unsigned major_version
,
236 unsigned minor_version
,
237 unsigned *dri_ctx_error
)
239 unsigned req_version
= 10 * major_version
+ minor_version
;
240 unsigned max_version
= 0;
243 case API_OPENGL_COMPAT
:
244 max_version
= screen
->max_gl_compat_version
;
246 case API_OPENGL_CORE
:
247 max_version
= screen
->max_gl_core_version
;
250 max_version
= screen
->max_gl_es1_version
;
253 max_version
= screen
->max_gl_es2_version
;
260 if (max_version
== 0) {
261 *dri_ctx_error
= __DRI_CTX_ERROR_BAD_API
;
263 } else if (req_version
> max_version
) {
264 *dri_ctx_error
= __DRI_CTX_ERROR_BAD_VERSION
;
271 /*****************************************************************/
272 /** \name Context handling functions */
273 /*****************************************************************/
276 static __DRIcontext
*
277 dri2CreateContextAttribs(__DRIscreen
*screen
, int api
,
278 const __DRIconfig
*config
,
279 __DRIcontext
*shared
,
280 unsigned num_attribs
,
281 const uint32_t *attribs
,
285 __DRIcontext
*context
;
286 const struct gl_config
*modes
= (config
!= NULL
) ? &config
->modes
: NULL
;
287 void *shareCtx
= (shared
!= NULL
) ? shared
->driverPrivate
: NULL
;
289 unsigned major_version
= 1;
290 unsigned minor_version
= 0;
293 assert((num_attribs
== 0) || (attribs
!= NULL
));
295 if (!(screen
->api_mask
& (1 << api
))) {
296 *error
= __DRI_CTX_ERROR_BAD_API
;
301 case __DRI_API_OPENGL
:
302 mesa_api
= API_OPENGL_COMPAT
;
305 mesa_api
= API_OPENGLES
;
307 case __DRI_API_GLES2
:
308 case __DRI_API_GLES3
:
309 mesa_api
= API_OPENGLES2
;
311 case __DRI_API_OPENGL_CORE
:
312 mesa_api
= API_OPENGL_CORE
;
315 *error
= __DRI_CTX_ERROR_BAD_API
;
319 for (unsigned i
= 0; i
< num_attribs
; i
++) {
320 switch (attribs
[i
* 2]) {
321 case __DRI_CTX_ATTRIB_MAJOR_VERSION
:
322 major_version
= attribs
[i
* 2 + 1];
324 case __DRI_CTX_ATTRIB_MINOR_VERSION
:
325 minor_version
= attribs
[i
* 2 + 1];
327 case __DRI_CTX_ATTRIB_FLAGS
:
328 flags
= attribs
[i
* 2 + 1];
331 /* We can't create a context that satisfies the requirements of an
332 * attribute that we don't understand. Return failure.
334 assert(!"Should not get here.");
335 *error
= __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE
;
340 /* Mesa does not support the GL_ARB_compatibilty extension or the
341 * compatibility profile. This means that we treat a API_OPENGL_COMPAT 3.1 as
342 * API_OPENGL_CORE and reject API_OPENGL_COMPAT 3.2+.
344 if (mesa_api
== API_OPENGL_COMPAT
&& major_version
== 3 && minor_version
== 1)
345 mesa_api
= API_OPENGL_CORE
;
347 if (mesa_api
== API_OPENGL_COMPAT
348 && ((major_version
> 3)
349 || (major_version
== 3 && minor_version
>= 2))) {
350 *error
= __DRI_CTX_ERROR_BAD_API
;
354 /* The EGL_KHR_create_context spec says:
356 * "Flags are only defined for OpenGL context creation, and specifying
357 * a flags value other than zero for other types of contexts,
358 * including OpenGL ES contexts, will generate an error."
360 * The GLX_EXT_create_context_es2_profile specification doesn't say
361 * anything specific about this case. However, none of the known flags
362 * have any meaning in an ES context, so this seems safe.
364 if (mesa_api
!= API_OPENGL_COMPAT
365 && mesa_api
!= API_OPENGL_CORE
367 *error
= __DRI_CTX_ERROR_BAD_FLAG
;
371 /* There are no forward-compatible contexts before OpenGL 3.0. The
372 * GLX_ARB_create_context spec says:
374 * "Forward-compatible contexts are defined only for OpenGL versions
377 * Forward-looking contexts are supported by silently converting the
378 * requested API to API_OPENGL_CORE.
380 * In Mesa, a debug context is the same as a regular context.
382 if ((flags
& __DRI_CTX_FLAG_FORWARD_COMPATIBLE
) != 0) {
383 mesa_api
= API_OPENGL_CORE
;
386 if ((flags
& ~(__DRI_CTX_FLAG_DEBUG
| __DRI_CTX_FLAG_FORWARD_COMPATIBLE
))
388 *error
= __DRI_CTX_ERROR_UNKNOWN_FLAG
;
392 if (!validate_context_version(screen
, mesa_api
,
393 major_version
, minor_version
, error
))
396 context
= calloc(1, sizeof *context
);
398 *error
= __DRI_CTX_ERROR_NO_MEMORY
;
402 context
->loaderPrivate
= data
;
404 context
->driScreenPriv
= screen
;
405 context
->driDrawablePriv
= NULL
;
406 context
->driReadablePriv
= NULL
;
408 if (!screen
->driver
->CreateContext(mesa_api
, modes
, context
,
409 major_version
, minor_version
,
410 flags
, error
, shareCtx
) ) {
415 struct gl_context
*ctx
= context
->driverPrivate
;
416 if ((flags
& __DRI_CTX_FLAG_FORWARD_COMPATIBLE
) != 0)
417 ctx
->Const
.ContextFlags
|= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT
;
418 if ((flags
& __DRI_CTX_FLAG_DEBUG
) != 0) {
419 ctx
->Const
.ContextFlags
|= GL_CONTEXT_FLAG_DEBUG_BIT
;
420 ctx
->Debug
.DebugOutput
= GL_TRUE
;
423 *error
= __DRI_CTX_ERROR_SUCCESS
;
427 static __DRIcontext
*
428 dri2CreateNewContextForAPI(__DRIscreen
*screen
, int api
,
429 const __DRIconfig
*config
,
430 __DRIcontext
*shared
, void *data
)
434 return dri2CreateContextAttribs(screen
, api
, config
, shared
, 0, NULL
,
438 static __DRIcontext
*
439 dri2CreateNewContext(__DRIscreen
*screen
, const __DRIconfig
*config
,
440 __DRIcontext
*shared
, void *data
)
442 return dri2CreateNewContextForAPI(screen
, __DRI_API_OPENGL
,
443 config
, shared
, data
);
447 * Destroy the per-context private information.
450 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
451 * drmDestroyContext(), and finally frees \p contextPrivate.
454 driDestroyContext(__DRIcontext
*pcp
)
457 pcp
->driScreenPriv
->driver
->DestroyContext(pcp
);
463 driCopyContext(__DRIcontext
*dest
, __DRIcontext
*src
, unsigned long mask
)
474 /*****************************************************************/
475 /** \name Context (un)binding functions */
476 /*****************************************************************/
479 static void dri_get_drawable(__DRIdrawable
*pdp
);
480 static void dri_put_drawable(__DRIdrawable
*pdp
);
483 * This function takes both a read buffer and a draw buffer. This is needed
484 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
487 static int driBindContext(__DRIcontext
*pcp
,
492 ** Assume error checking is done properly in glXMakeCurrent before
493 ** calling driUnbindContext.
499 /* Bind the drawable to the context */
500 pcp
->driDrawablePriv
= pdp
;
501 pcp
->driReadablePriv
= prp
;
503 pdp
->driContextPriv
= pcp
;
504 dri_get_drawable(pdp
);
506 if (prp
&& pdp
!= prp
) {
507 dri_get_drawable(prp
);
510 return pcp
->driScreenPriv
->driver
->MakeCurrent(pcp
, pdp
, prp
);
516 * \param scrn the screen.
519 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
522 * This function calls __DriverAPIRec::UnbindContext, and then decrements
523 * __DRIdrawableRec::refcount which must be non-zero for a successful
526 * While casting the opaque private pointers associated with the parameters
527 * into their respective real types it also assures they are not \c NULL.
529 static int driUnbindContext(__DRIcontext
*pcp
)
535 ** Assume error checking is done properly in glXMakeCurrent before
536 ** calling driUnbindContext.
542 pdp
= pcp
->driDrawablePriv
;
543 prp
= pcp
->driReadablePriv
;
545 /* already unbound */
549 pcp
->driScreenPriv
->driver
->UnbindContext(pcp
);
552 if (pdp
->refcount
== 0) {
557 dri_put_drawable(pdp
);
560 if (prp
->refcount
== 0) {
565 dri_put_drawable(prp
);
568 pcp
->driDrawablePriv
= NULL
;
569 pcp
->driReadablePriv
= NULL
;
577 static void dri_get_drawable(__DRIdrawable
*pdp
)
582 static void dri_put_drawable(__DRIdrawable
*pdp
)
589 pdp
->driScreenPriv
->driver
->DestroyBuffer(pdp
);
594 static __DRIdrawable
*
595 dri2CreateNewDrawable(__DRIscreen
*screen
,
596 const __DRIconfig
*config
,
599 __DRIdrawable
*pdraw
;
601 pdraw
= malloc(sizeof *pdraw
);
605 pdraw
->loaderPrivate
= data
;
607 pdraw
->driScreenPriv
= screen
;
608 pdraw
->driContextPriv
= NULL
;
610 pdraw
->lastStamp
= 0;
614 dri_get_drawable(pdraw
);
616 if (!screen
->driver
->CreateBuffer(screen
, pdraw
, &config
->modes
,
622 pdraw
->dri2
.stamp
= pdraw
->lastStamp
+ 1;
628 driDestroyDrawable(__DRIdrawable
*pdp
)
630 dri_put_drawable(pdp
);
634 dri2AllocateBuffer(__DRIscreen
*screen
,
635 unsigned int attachment
, unsigned int format
,
636 int width
, int height
)
638 return screen
->driver
->AllocateBuffer(screen
, attachment
, format
,
643 dri2ReleaseBuffer(__DRIscreen
*screen
, __DRIbuffer
*buffer
)
645 screen
->driver
->ReleaseBuffer(screen
, buffer
);
650 dri2ConfigQueryb(__DRIscreen
*screen
, const char *var
, GLboolean
*val
)
652 if (!driCheckOption(&screen
->optionCache
, var
, DRI_BOOL
))
655 *val
= driQueryOptionb(&screen
->optionCache
, var
);
661 dri2ConfigQueryi(__DRIscreen
*screen
, const char *var
, GLint
*val
)
663 if (!driCheckOption(&screen
->optionCache
, var
, DRI_INT
) &&
664 !driCheckOption(&screen
->optionCache
, var
, DRI_ENUM
))
667 *val
= driQueryOptioni(&screen
->optionCache
, var
);
673 dri2ConfigQueryf(__DRIscreen
*screen
, const char *var
, GLfloat
*val
)
675 if (!driCheckOption(&screen
->optionCache
, var
, DRI_FLOAT
))
678 *val
= driQueryOptionf(&screen
->optionCache
, var
);
684 dri2GetAPIMask(__DRIscreen
*screen
)
686 return screen
->api_mask
;
690 * swrast swapbuffers entrypoint.
692 * DRI2 implements this inside the loader with only flushes handled by the
696 driSwapBuffers(__DRIdrawable
*pdp
)
698 assert(pdp
->driScreenPriv
->swrast_loader
);
700 pdp
->driScreenPriv
->driver
->SwapBuffers(pdp
);
703 /** Core interface */
704 const __DRIcoreExtension driCoreExtension
= {
705 .base
= { __DRI_CORE
, __DRI_CORE_VERSION
},
707 .createNewScreen
= NULL
,
708 .destroyScreen
= driDestroyScreen
,
709 .getExtensions
= driGetExtensions
,
710 .getConfigAttrib
= driGetConfigAttrib
,
711 .indexConfigAttrib
= driIndexConfigAttrib
,
712 .createNewDrawable
= NULL
,
713 .destroyDrawable
= driDestroyDrawable
,
714 .swapBuffers
= driSwapBuffers
, /* swrast */
715 .createNewContext
= dri2CreateNewContext
, /* swrast */
716 .copyContext
= driCopyContext
,
717 .destroyContext
= driDestroyContext
,
718 .bindContext
= driBindContext
,
719 .unbindContext
= driUnbindContext
722 /** DRI2 interface */
723 const __DRIdri2Extension driDRI2Extension
= {
724 .base
= { __DRI_DRI2
, 4 },
726 .createNewScreen
= dri2CreateNewScreen
,
727 .createNewDrawable
= dri2CreateNewDrawable
,
728 .createNewContext
= dri2CreateNewContext
,
729 .getAPIMask
= dri2GetAPIMask
,
730 .createNewContextForAPI
= dri2CreateNewContextForAPI
,
731 .allocateBuffer
= dri2AllocateBuffer
,
732 .releaseBuffer
= dri2ReleaseBuffer
,
733 .createContextAttribs
= dri2CreateContextAttribs
,
734 .createNewScreen2
= dri2CreateNewScreen2
,
737 const __DRIswrastExtension driSWRastExtension
= {
739 driSWRastCreateNewScreen
,
740 dri2CreateNewDrawable
,
741 dri2CreateNewContextForAPI
,
742 dri2CreateContextAttribs
,
743 driSWRastCreateNewScreen2
,
746 const __DRI2configQueryExtension dri2ConfigQueryExtension
= {
747 .base
= { __DRI2_CONFIG_QUERY
, __DRI2_CONFIG_QUERY_VERSION
},
749 .configQueryb
= dri2ConfigQueryb
,
750 .configQueryi
= dri2ConfigQueryi
,
751 .configQueryf
= dri2ConfigQueryf
,
755 dri2InvalidateDrawable(__DRIdrawable
*drawable
)
757 drawable
->dri2
.stamp
++;
761 * Check that the gl_framebuffer associated with dPriv is the right size.
762 * Resize the gl_framebuffer if needed.
763 * It's expected that the dPriv->driverPrivate member points to a
764 * gl_framebuffer object.
767 driUpdateFramebufferSize(struct gl_context
*ctx
, const __DRIdrawable
*dPriv
)
769 struct gl_framebuffer
*fb
= (struct gl_framebuffer
*) dPriv
->driverPrivate
;
770 if (fb
&& (dPriv
->w
!= fb
->Width
|| dPriv
->h
!= fb
->Height
)) {
771 ctx
->Driver
.ResizeBuffers(ctx
, fb
, dPriv
->w
, dPriv
->h
);
772 /* if the driver needs the hw lock for ResizeBuffers, the drawable
773 might have changed again by now */
774 assert(fb
->Width
== dPriv
->w
);
775 assert(fb
->Height
== dPriv
->h
);