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
42 #ifndef __NOT_HAVE_DRM_H
48 #include "../glsl/glsl_parser_extras.h"
50 PUBLIC
const char __dri2ConfigOptions
[] =
52 DRI_CONF_SECTION_PERFORMANCE
53 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1
)
57 /*****************************************************************/
58 /** \name Screen handling functions */
59 /*****************************************************************/
63 setupLoaderExtensions(__DRIscreen
*psp
,
64 const __DRIextension
**extensions
)
68 for (i
= 0; extensions
[i
]; i
++) {
69 if (strcmp(extensions
[i
]->name
, __DRI_DRI2_LOADER
) == 0)
70 psp
->dri2
.loader
= (__DRIdri2LoaderExtension
*) extensions
[i
];
71 if (strcmp(extensions
[i
]->name
, __DRI_IMAGE_LOOKUP
) == 0)
72 psp
->dri2
.image
= (__DRIimageLookupExtension
*) extensions
[i
];
73 if (strcmp(extensions
[i
]->name
, __DRI_USE_INVALIDATE
) == 0)
74 psp
->dri2
.useInvalidate
= (__DRIuseInvalidateExtension
*) extensions
[i
];
75 if (strcmp(extensions
[i
]->name
, __DRI_SWRAST_LOADER
) == 0)
76 psp
->swrast_loader
= (__DRIswrastLoaderExtension
*) extensions
[i
];
81 * This is the first entrypoint in the driver called by the DRI driver loader
82 * after dlopen()ing it.
84 * It's used to create global state for the driver across contexts on the same
88 dri2CreateNewScreen(int scrn
, int fd
,
89 const __DRIextension
**extensions
,
90 const __DRIconfig
***driver_configs
, void *data
)
92 static const __DRIextension
*emptyExtensionList
[] = { NULL
};
95 psp
= calloc(1, sizeof(*psp
));
99 setupLoaderExtensions(psp
, extensions
);
101 #ifndef __NOT_HAVE_DRM_H
103 drmVersionPtr version
= drmGetVersion(fd
);
105 psp
->drm_version
.major
= version
->version_major
;
106 psp
->drm_version
.minor
= version
->version_minor
;
107 psp
->drm_version
.patch
= version
->version_patchlevel
;
108 drmFreeVersion(version
);
113 psp
->loaderPrivate
= data
;
115 psp
->extensions
= emptyExtensionList
;
119 psp
->api_mask
= (1 << __DRI_API_OPENGL
);
121 *driver_configs
= driDriverAPI
.InitScreen(psp
);
122 if (*driver_configs
== NULL
) {
127 driParseOptionInfo(&psp
->optionInfo
, __dri2ConfigOptions
);
128 driParseConfigFiles(&psp
->optionCache
, &psp
->optionInfo
, psp
->myNum
, "dri2");
133 /** swrast driver createNewScreen entrypoint. */
135 driCreateNewScreen(int scrn
, const __DRIextension
**extensions
,
136 const __DRIconfig
***driver_configs
, void *data
)
138 return dri2CreateNewScreen(scrn
, -1, extensions
, driver_configs
, data
);
142 * Destroy the per-screen private information.
145 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
146 * drmClose(), and finally frees \p screenPrivate.
148 static void driDestroyScreen(__DRIscreen
*psp
)
151 /* No interaction with the X-server is possible at this point. This
152 * routine is called after XCloseDisplay, so there is no protocol
153 * stream open to the X-server anymore.
156 _mesa_destroy_shader_compiler();
158 driDriverAPI
.DestroyScreen(psp
);
160 driDestroyOptionCache(&psp
->optionCache
);
161 driDestroyOptionInfo(&psp
->optionInfo
);
167 static const __DRIextension
**driGetExtensions(__DRIscreen
*psp
)
169 return psp
->extensions
;
175 /*****************************************************************/
176 /** \name Context handling functions */
177 /*****************************************************************/
180 static __DRIcontext
*
181 dri2CreateContextAttribs(__DRIscreen
*screen
, int api
,
182 const __DRIconfig
*config
,
183 __DRIcontext
*shared
,
184 unsigned num_attribs
,
185 const uint32_t *attribs
,
189 __DRIcontext
*context
;
190 const struct gl_config
*modes
= (config
!= NULL
) ? &config
->modes
: NULL
;
191 void *shareCtx
= (shared
!= NULL
) ? shared
->driverPrivate
: NULL
;
193 unsigned major_version
= 1;
194 unsigned minor_version
= 0;
197 assert((num_attribs
== 0) || (attribs
!= NULL
));
199 if (!(screen
->api_mask
& (1 << api
))) {
200 *error
= __DRI_CTX_ERROR_BAD_API
;
205 case __DRI_API_OPENGL
:
206 mesa_api
= API_OPENGL_COMPAT
;
209 mesa_api
= API_OPENGLES
;
211 case __DRI_API_GLES2
:
212 case __DRI_API_GLES3
:
213 mesa_api
= API_OPENGLES2
;
215 case __DRI_API_OPENGL_CORE
:
216 mesa_api
= API_OPENGL_CORE
;
219 *error
= __DRI_CTX_ERROR_BAD_API
;
223 for (unsigned i
= 0; i
< num_attribs
; i
++) {
224 switch (attribs
[i
* 2]) {
225 case __DRI_CTX_ATTRIB_MAJOR_VERSION
:
226 major_version
= attribs
[i
* 2 + 1];
228 case __DRI_CTX_ATTRIB_MINOR_VERSION
:
229 minor_version
= attribs
[i
* 2 + 1];
231 case __DRI_CTX_ATTRIB_FLAGS
:
232 flags
= attribs
[i
* 2 + 1];
235 /* We can't create a context that satisfies the requirements of an
236 * attribute that we don't understand. Return failure.
238 assert(!"Should not get here.");
239 *error
= __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE
;
244 /* Mesa does not support the GL_ARB_compatibilty extension or the
245 * compatibility profile. This means that we treat a API_OPENGL_COMPAT 3.1 as
246 * API_OPENGL_CORE and reject API_OPENGL_COMPAT 3.2+.
248 if (mesa_api
== API_OPENGL_COMPAT
&& major_version
== 3 && minor_version
== 1)
249 mesa_api
= API_OPENGL_CORE
;
251 if (mesa_api
== API_OPENGL_COMPAT
252 && ((major_version
> 3)
253 || (major_version
== 3 && minor_version
>= 2))) {
254 *error
= __DRI_CTX_ERROR_BAD_API
;
258 /* The EGL_KHR_create_context spec says:
260 * "Flags are only defined for OpenGL context creation, and specifying
261 * a flags value other than zero for other types of contexts,
262 * including OpenGL ES contexts, will generate an error."
264 * The GLX_EXT_create_context_es2_profile specification doesn't say
265 * anything specific about this case. However, none of the known flags
266 * have any meaning in an ES context, so this seems safe.
268 if (mesa_api
!= API_OPENGL_COMPAT
269 && mesa_api
!= API_OPENGL_CORE
271 *error
= __DRI_CTX_ERROR_BAD_FLAG
;
275 /* There are no forward-compatible contexts before OpenGL 3.0. The
276 * GLX_ARB_create_context spec says:
278 * "Forward-compatible contexts are defined only for OpenGL versions
281 * Forward-looking contexts are supported by silently converting the
282 * requested API to API_OPENGL_CORE.
284 * In Mesa, a debug context is the same as a regular context.
286 if ((flags
& __DRI_CTX_FLAG_FORWARD_COMPATIBLE
) != 0) {
287 mesa_api
= API_OPENGL_CORE
;
290 if ((flags
& ~(__DRI_CTX_FLAG_DEBUG
| __DRI_CTX_FLAG_FORWARD_COMPATIBLE
))
292 *error
= __DRI_CTX_ERROR_UNKNOWN_FLAG
;
296 context
= calloc(1, sizeof *context
);
298 *error
= __DRI_CTX_ERROR_NO_MEMORY
;
302 context
->loaderPrivate
= data
;
304 context
->driScreenPriv
= screen
;
305 context
->driDrawablePriv
= NULL
;
306 context
->driReadablePriv
= NULL
;
308 if (!driDriverAPI
.CreateContext(mesa_api
, modes
, context
,
309 major_version
, minor_version
,
310 flags
, error
, shareCtx
) ) {
315 *error
= __DRI_CTX_ERROR_SUCCESS
;
319 static __DRIcontext
*
320 dri2CreateNewContextForAPI(__DRIscreen
*screen
, int api
,
321 const __DRIconfig
*config
,
322 __DRIcontext
*shared
, void *data
)
326 return dri2CreateContextAttribs(screen
, api
, config
, shared
, 0, NULL
,
330 static __DRIcontext
*
331 dri2CreateNewContext(__DRIscreen
*screen
, const __DRIconfig
*config
,
332 __DRIcontext
*shared
, void *data
)
334 return dri2CreateNewContextForAPI(screen
, __DRI_API_OPENGL
,
335 config
, shared
, data
);
339 * Destroy the per-context private information.
342 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
343 * drmDestroyContext(), and finally frees \p contextPrivate.
346 driDestroyContext(__DRIcontext
*pcp
)
349 driDriverAPI
.DestroyContext(pcp
);
355 driCopyContext(__DRIcontext
*dest
, __DRIcontext
*src
, unsigned long mask
)
366 /*****************************************************************/
367 /** \name Context (un)binding functions */
368 /*****************************************************************/
371 static void dri_get_drawable(__DRIdrawable
*pdp
);
372 static void dri_put_drawable(__DRIdrawable
*pdp
);
375 * This function takes both a read buffer and a draw buffer. This is needed
376 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
379 static int driBindContext(__DRIcontext
*pcp
,
384 ** Assume error checking is done properly in glXMakeCurrent before
385 ** calling driUnbindContext.
391 /* Bind the drawable to the context */
392 pcp
->driDrawablePriv
= pdp
;
393 pcp
->driReadablePriv
= prp
;
395 pdp
->driContextPriv
= pcp
;
396 dri_get_drawable(pdp
);
398 if (prp
&& pdp
!= prp
) {
399 dri_get_drawable(prp
);
402 return driDriverAPI
.MakeCurrent(pcp
, pdp
, prp
);
408 * \param scrn the screen.
411 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
414 * This function calls __DriverAPIRec::UnbindContext, and then decrements
415 * __DRIdrawableRec::refcount which must be non-zero for a successful
418 * While casting the opaque private pointers associated with the parameters
419 * into their respective real types it also assures they are not \c NULL.
421 static int driUnbindContext(__DRIcontext
*pcp
)
427 ** Assume error checking is done properly in glXMakeCurrent before
428 ** calling driUnbindContext.
434 pdp
= pcp
->driDrawablePriv
;
435 prp
= pcp
->driReadablePriv
;
437 /* already unbound */
441 driDriverAPI
.UnbindContext(pcp
);
444 if (pdp
->refcount
== 0) {
449 dri_put_drawable(pdp
);
452 if (prp
->refcount
== 0) {
457 dri_put_drawable(prp
);
460 pcp
->driDrawablePriv
= NULL
;
461 pcp
->driReadablePriv
= NULL
;
469 static void dri_get_drawable(__DRIdrawable
*pdp
)
474 static void dri_put_drawable(__DRIdrawable
*pdp
)
481 driDriverAPI
.DestroyBuffer(pdp
);
486 static __DRIdrawable
*
487 dri2CreateNewDrawable(__DRIscreen
*screen
,
488 const __DRIconfig
*config
,
491 __DRIdrawable
*pdraw
;
493 pdraw
= malloc(sizeof *pdraw
);
497 pdraw
->loaderPrivate
= data
;
499 pdraw
->driScreenPriv
= screen
;
500 pdraw
->driContextPriv
= NULL
;
502 pdraw
->lastStamp
= 0;
506 dri_get_drawable(pdraw
);
508 if (!driDriverAPI
.CreateBuffer(screen
, pdraw
, &config
->modes
, GL_FALSE
)) {
513 pdraw
->dri2
.stamp
= pdraw
->lastStamp
+ 1;
519 driDestroyDrawable(__DRIdrawable
*pdp
)
521 dri_put_drawable(pdp
);
525 dri2AllocateBuffer(__DRIscreen
*screen
,
526 unsigned int attachment
, unsigned int format
,
527 int width
, int height
)
529 return driDriverAPI
.AllocateBuffer(screen
, attachment
, format
,
534 dri2ReleaseBuffer(__DRIscreen
*screen
, __DRIbuffer
*buffer
)
536 driDriverAPI
.ReleaseBuffer(screen
, buffer
);
541 dri2ConfigQueryb(__DRIscreen
*screen
, const char *var
, GLboolean
*val
)
543 if (!driCheckOption(&screen
->optionCache
, var
, DRI_BOOL
))
546 *val
= driQueryOptionb(&screen
->optionCache
, var
);
552 dri2ConfigQueryi(__DRIscreen
*screen
, const char *var
, GLint
*val
)
554 if (!driCheckOption(&screen
->optionCache
, var
, DRI_INT
) &&
555 !driCheckOption(&screen
->optionCache
, var
, DRI_ENUM
))
558 *val
= driQueryOptioni(&screen
->optionCache
, var
);
564 dri2ConfigQueryf(__DRIscreen
*screen
, const char *var
, GLfloat
*val
)
566 if (!driCheckOption(&screen
->optionCache
, var
, DRI_FLOAT
))
569 *val
= driQueryOptionf(&screen
->optionCache
, var
);
575 dri2GetAPIMask(__DRIscreen
*screen
)
577 return screen
->api_mask
;
581 * swrast swapbuffers entrypoint.
583 * DRI2 implements this inside the loader with only flushes handled by the
587 driSwapBuffers(__DRIdrawable
*pdp
)
589 assert(pdp
->driScreenPriv
->swrast_loader
);
591 driDriverAPI
.SwapBuffers(pdp
);
594 /** Core interface */
595 const __DRIcoreExtension driCoreExtension
= {
596 .base
= { __DRI_CORE
, __DRI_CORE_VERSION
},
598 .createNewScreen
= NULL
,
599 .destroyScreen
= driDestroyScreen
,
600 .getExtensions
= driGetExtensions
,
601 .getConfigAttrib
= driGetConfigAttrib
,
602 .indexConfigAttrib
= driIndexConfigAttrib
,
603 .createNewDrawable
= NULL
,
604 .destroyDrawable
= driDestroyDrawable
,
605 .swapBuffers
= driSwapBuffers
, /* swrast */
606 .createNewContext
= dri2CreateNewContext
, /* swrast */
607 .copyContext
= driCopyContext
,
608 .destroyContext
= driDestroyContext
,
609 .bindContext
= driBindContext
,
610 .unbindContext
= driUnbindContext
613 /** DRI2 interface */
614 const __DRIdri2Extension driDRI2Extension
= {
615 .base
= { __DRI_DRI2
, 3 },
617 .createNewScreen
= dri2CreateNewScreen
,
618 .createNewDrawable
= dri2CreateNewDrawable
,
619 .createNewContext
= dri2CreateNewContext
,
620 .getAPIMask
= dri2GetAPIMask
,
621 .createNewContextForAPI
= dri2CreateNewContextForAPI
,
622 .allocateBuffer
= dri2AllocateBuffer
,
623 .releaseBuffer
= dri2ReleaseBuffer
,
624 .createContextAttribs
= dri2CreateContextAttribs
627 const __DRIswrastExtension driSWRastExtension
= {
628 { __DRI_SWRAST
, __DRI_SWRAST_VERSION
},
630 dri2CreateNewDrawable
,
631 dri2CreateNewContextForAPI
,
632 dri2CreateContextAttribs
635 const __DRI2configQueryExtension dri2ConfigQueryExtension
= {
636 .base
= { __DRI2_CONFIG_QUERY
, __DRI2_CONFIG_QUERY_VERSION
},
638 .configQueryb
= dri2ConfigQueryb
,
639 .configQueryi
= dri2ConfigQueryi
,
640 .configQueryf
= dri2ConfigQueryf
,
644 dri2InvalidateDrawable(__DRIdrawable
*drawable
)
646 drawable
->dri2
.stamp
++;
650 * Check that the gl_framebuffer associated with dPriv is the right size.
651 * Resize the gl_framebuffer if needed.
652 * It's expected that the dPriv->driverPrivate member points to a
653 * gl_framebuffer object.
656 driUpdateFramebufferSize(struct gl_context
*ctx
, const __DRIdrawable
*dPriv
)
658 struct gl_framebuffer
*fb
= (struct gl_framebuffer
*) dPriv
->driverPrivate
;
659 if (fb
&& (dPriv
->w
!= fb
->Width
|| dPriv
->h
!= fb
->Height
)) {
660 ctx
->Driver
.ResizeBuffers(ctx
, fb
, dPriv
->w
, dPriv
->h
);
661 /* if the driver needs the hw lock for ResizeBuffers, the drawable
662 might have changed again by now */
663 assert(fb
->Width
== dPriv
->w
);
664 assert(fb
->Height
== dPriv
->h
);