3 * DRI utility functions.
5 * This module acts as glue between GLX and the actual hardware driver. A DRI
6 * driver doesn't really \e have to use any of this - it's optional. But, some
7 * useful stuff is done here that otherwise would have to be duplicated in most
10 * Basically, these utility functions take care of some of the dirty details of
11 * screen initialization, context creation, context binding, DRM setup, etc.
13 * These functions are compiled into each DRI driver so libGL.so knows nothing
22 #include "../glsl/glsl_parser_extras.h"
24 PUBLIC
const char __dri2ConfigOptions
[] =
26 DRI_CONF_SECTION_PERFORMANCE
27 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1
)
31 static const uint __dri2NConfigOptions
= 1;
33 /*****************************************************************/
34 /** \name Screen handling functions */
35 /*****************************************************************/
39 setupLoaderExtensions(__DRIscreen
*psp
,
40 const __DRIextension
**extensions
)
44 for (i
= 0; extensions
[i
]; i
++) {
45 if (strcmp(extensions
[i
]->name
, __DRI_DRI2_LOADER
) == 0)
46 psp
->dri2
.loader
= (__DRIdri2LoaderExtension
*) extensions
[i
];
47 if (strcmp(extensions
[i
]->name
, __DRI_IMAGE_LOOKUP
) == 0)
48 psp
->dri2
.image
= (__DRIimageLookupExtension
*) extensions
[i
];
49 if (strcmp(extensions
[i
]->name
, __DRI_USE_INVALIDATE
) == 0)
50 psp
->dri2
.useInvalidate
= (__DRIuseInvalidateExtension
*) extensions
[i
];
55 dri2CreateNewScreen(int scrn
, int fd
,
56 const __DRIextension
**extensions
,
57 const __DRIconfig
***driver_configs
, void *data
)
59 static const __DRIextension
*emptyExtensionList
[] = { NULL
};
61 drmVersionPtr version
;
63 psp
= calloc(1, sizeof(*psp
));
67 setupLoaderExtensions(psp
, extensions
);
69 version
= drmGetVersion(fd
);
71 psp
->drm_version
.major
= version
->version_major
;
72 psp
->drm_version
.minor
= version
->version_minor
;
73 psp
->drm_version
.patch
= version
->version_patchlevel
;
74 drmFreeVersion(version
);
77 psp
->loaderPrivate
= data
;
79 psp
->extensions
= emptyExtensionList
;
83 psp
->api_mask
= (1 << __DRI_API_OPENGL
);
85 *driver_configs
= driDriverAPI
.InitScreen(psp
);
86 if (*driver_configs
== NULL
) {
91 driParseOptionInfo(&psp
->optionInfo
, __dri2ConfigOptions
, __dri2NConfigOptions
);
92 driParseConfigFiles(&psp
->optionCache
, &psp
->optionInfo
, psp
->myNum
, "dri2");
98 * Destroy the per-screen private information.
101 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
102 * drmClose(), and finally frees \p screenPrivate.
104 static void driDestroyScreen(__DRIscreen
*psp
)
107 /* No interaction with the X-server is possible at this point. This
108 * routine is called after XCloseDisplay, so there is no protocol
109 * stream open to the X-server anymore.
112 _mesa_destroy_shader_compiler();
114 driDriverAPI
.DestroyScreen(psp
);
116 driDestroyOptionCache(&psp
->optionCache
);
117 driDestroyOptionInfo(&psp
->optionInfo
);
123 static const __DRIextension
**driGetExtensions(__DRIscreen
*psp
)
125 return psp
->extensions
;
131 /*****************************************************************/
132 /** \name Context handling functions */
133 /*****************************************************************/
136 static __DRIcontext
*
137 dri2CreateContextAttribs(__DRIscreen
*screen
, int api
,
138 const __DRIconfig
*config
,
139 __DRIcontext
*shared
,
140 unsigned num_attribs
,
141 const uint32_t *attribs
,
145 __DRIcontext
*context
;
146 const struct gl_config
*modes
= (config
!= NULL
) ? &config
->modes
: NULL
;
147 void *shareCtx
= (shared
!= NULL
) ? shared
->driverPrivate
: NULL
;
149 unsigned major_version
= 1;
150 unsigned minor_version
= 0;
153 assert((num_attribs
== 0) || (attribs
!= NULL
));
155 if (!(screen
->api_mask
& (1 << api
))) {
156 *error
= __DRI_CTX_ERROR_BAD_API
;
161 case __DRI_API_OPENGL
:
162 mesa_api
= API_OPENGL
;
165 mesa_api
= API_OPENGLES
;
167 case __DRI_API_GLES2
:
168 mesa_api
= API_OPENGLES2
;
170 case __DRI_API_OPENGL_CORE
:
172 *error
= __DRI_CTX_ERROR_BAD_API
;
176 if (mesa_api
!= API_OPENGL
&& num_attribs
!= 0) {
177 *error
= __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE
;
178 assert(!"Should not get here.");
182 for (unsigned i
= 0; i
< num_attribs
; i
++) {
183 switch (attribs
[i
* 2]) {
184 case __DRI_CTX_ATTRIB_MAJOR_VERSION
:
185 major_version
= attribs
[i
* 2 + 1];
187 case __DRI_CTX_ATTRIB_MINOR_VERSION
:
188 minor_version
= attribs
[i
* 2 + 1];
190 case __DRI_CTX_ATTRIB_FLAGS
:
191 flags
= attribs
[i
* 2 + 1];
194 /* We can't create a context that satisfies the requirements of an
195 * attribute that we don't understand. Return failure.
197 assert(!"Should not get here.");
198 *error
= __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE
;
203 /* There are no forward-compatible contexts before OpenGL 3.0. The
204 * GLX_ARB_create_context spec says:
206 * "Forward-compatible contexts are defined only for OpenGL versions
209 * Moreover, Mesa can't fulfill the requirements of a forward-looking
210 * context. Return failure if a forward-looking context is requested.
212 * In Mesa, a debug context is the same as a regular context.
214 if ((flags
& __DRI_CTX_FLAG_FORWARD_COMPATIBLE
) != 0) {
215 *error
= __DRI_CTX_ERROR_BAD_FLAG
;
219 if ((flags
& ~__DRI_CTX_FLAG_DEBUG
) != 0) {
220 *error
= __DRI_CTX_ERROR_UNKNOWN_FLAG
;
224 context
= malloc(sizeof *context
);
226 *error
= __DRI_CTX_ERROR_NO_MEMORY
;
230 context
->loaderPrivate
= data
;
232 context
->driScreenPriv
= screen
;
233 context
->driDrawablePriv
= NULL
;
234 context
->driReadablePriv
= NULL
;
236 if (!driDriverAPI
.CreateContext(mesa_api
, modes
, context
,
237 major_version
, minor_version
,
238 flags
, error
, shareCtx
) ) {
243 *error
= __DRI_CTX_ERROR_SUCCESS
;
247 static __DRIcontext
*
248 dri2CreateNewContextForAPI(__DRIscreen
*screen
, int api
,
249 const __DRIconfig
*config
,
250 __DRIcontext
*shared
, void *data
)
254 return dri2CreateContextAttribs(screen
, api
, config
, shared
, 0, NULL
,
258 static __DRIcontext
*
259 dri2CreateNewContext(__DRIscreen
*screen
, const __DRIconfig
*config
,
260 __DRIcontext
*shared
, void *data
)
262 return dri2CreateNewContextForAPI(screen
, __DRI_API_OPENGL
,
263 config
, shared
, data
);
267 * Destroy the per-context private information.
270 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
271 * drmDestroyContext(), and finally frees \p contextPrivate.
274 driDestroyContext(__DRIcontext
*pcp
)
277 driDriverAPI
.DestroyContext(pcp
);
283 driCopyContext(__DRIcontext
*dest
, __DRIcontext
*src
, unsigned long mask
)
294 /*****************************************************************/
295 /** \name Context (un)binding functions */
296 /*****************************************************************/
299 static void dri_get_drawable(__DRIdrawable
*pdp
);
300 static void dri_put_drawable(__DRIdrawable
*pdp
);
303 * This function takes both a read buffer and a draw buffer. This is needed
304 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
307 static int driBindContext(__DRIcontext
*pcp
,
312 ** Assume error checking is done properly in glXMakeCurrent before
313 ** calling driUnbindContext.
319 /* Bind the drawable to the context */
320 pcp
->driDrawablePriv
= pdp
;
321 pcp
->driReadablePriv
= prp
;
323 pdp
->driContextPriv
= pcp
;
324 dri_get_drawable(pdp
);
326 if (prp
&& pdp
!= prp
) {
327 dri_get_drawable(prp
);
330 return driDriverAPI
.MakeCurrent(pcp
, pdp
, prp
);
336 * \param scrn the screen.
339 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
342 * This function calls __DriverAPIRec::UnbindContext, and then decrements
343 * __DRIdrawableRec::refcount which must be non-zero for a successful
346 * While casting the opaque private pointers associated with the parameters
347 * into their respective real types it also assures they are not \c NULL.
349 static int driUnbindContext(__DRIcontext
*pcp
)
355 ** Assume error checking is done properly in glXMakeCurrent before
356 ** calling driUnbindContext.
362 pdp
= pcp
->driDrawablePriv
;
363 prp
= pcp
->driReadablePriv
;
365 /* already unbound */
369 driDriverAPI
.UnbindContext(pcp
);
372 if (pdp
->refcount
== 0) {
377 dri_put_drawable(pdp
);
380 if (prp
->refcount
== 0) {
385 dri_put_drawable(prp
);
388 /* XXX this is disabled so that if we call SwapBuffers on an unbound
389 * window we can determine the last context bound to the window and
390 * use that context's lock. (BrianP, 2-Dec-2000)
392 pcp
->driDrawablePriv
= NULL
;
393 pcp
->driReadablePriv
= NULL
;
401 static void dri_get_drawable(__DRIdrawable
*pdp
)
406 static void dri_put_drawable(__DRIdrawable
*pdp
)
413 driDriverAPI
.DestroyBuffer(pdp
);
418 static __DRIdrawable
*
419 dri2CreateNewDrawable(__DRIscreen
*screen
,
420 const __DRIconfig
*config
,
423 __DRIdrawable
*pdraw
;
425 pdraw
= malloc(sizeof *pdraw
);
429 pdraw
->loaderPrivate
= data
;
431 pdraw
->driScreenPriv
= screen
;
432 pdraw
->driContextPriv
= NULL
;
434 pdraw
->lastStamp
= 0;
438 dri_get_drawable(pdraw
);
440 if (!driDriverAPI
.CreateBuffer(screen
, pdraw
, &config
->modes
, GL_FALSE
)) {
445 pdraw
->dri2
.stamp
= pdraw
->lastStamp
+ 1;
451 driDestroyDrawable(__DRIdrawable
*pdp
)
453 dri_put_drawable(pdp
);
457 dri2AllocateBuffer(__DRIscreen
*screen
,
458 unsigned int attachment
, unsigned int format
,
459 int width
, int height
)
461 return driDriverAPI
.AllocateBuffer(screen
, attachment
, format
,
466 dri2ReleaseBuffer(__DRIscreen
*screen
, __DRIbuffer
*buffer
)
468 driDriverAPI
.ReleaseBuffer(screen
, buffer
);
473 dri2ConfigQueryb(__DRIscreen
*screen
, const char *var
, GLboolean
*val
)
475 if (!driCheckOption(&screen
->optionCache
, var
, DRI_BOOL
))
478 *val
= driQueryOptionb(&screen
->optionCache
, var
);
484 dri2ConfigQueryi(__DRIscreen
*screen
, const char *var
, GLint
*val
)
486 if (!driCheckOption(&screen
->optionCache
, var
, DRI_INT
) &&
487 !driCheckOption(&screen
->optionCache
, var
, DRI_ENUM
))
490 *val
= driQueryOptioni(&screen
->optionCache
, var
);
496 dri2ConfigQueryf(__DRIscreen
*screen
, const char *var
, GLfloat
*val
)
498 if (!driCheckOption(&screen
->optionCache
, var
, DRI_FLOAT
))
501 *val
= driQueryOptionf(&screen
->optionCache
, var
);
507 dri2GetAPIMask(__DRIscreen
*screen
)
509 return screen
->api_mask
;
513 /** Core interface */
514 const __DRIcoreExtension driCoreExtension
= {
515 { __DRI_CORE
, __DRI_CORE_VERSION
},
520 driIndexConfigAttrib
,
531 /** DRI2 interface */
532 const __DRIdri2Extension driDRI2Extension
= {
533 { __DRI_DRI2
, __DRI_DRI2_VERSION
},
535 dri2CreateNewDrawable
,
536 dri2CreateNewContext
,
538 dri2CreateNewContextForAPI
,
541 dri2CreateContextAttribs
544 const __DRI2configQueryExtension dri2ConfigQueryExtension
= {
545 { __DRI2_CONFIG_QUERY
, __DRI2_CONFIG_QUERY_VERSION
},
552 dri2InvalidateDrawable(__DRIdrawable
*drawable
)
554 drawable
->dri2
.stamp
++;
558 * Check that the gl_framebuffer associated with dPriv is the right size.
559 * Resize the gl_framebuffer if needed.
560 * It's expected that the dPriv->driverPrivate member points to a
561 * gl_framebuffer object.
564 driUpdateFramebufferSize(struct gl_context
*ctx
, const __DRIdrawable
*dPriv
)
566 struct gl_framebuffer
*fb
= (struct gl_framebuffer
*) dPriv
->driverPrivate
;
567 if (fb
&& (dPriv
->w
!= fb
->Width
|| dPriv
->h
!= fb
->Height
)) {
568 ctx
->Driver
.ResizeBuffers(ctx
, fb
, dPriv
->w
, dPriv
->h
);
569 /* if the driver needs the hw lock for ResizeBuffers, the drawable
570 might have changed again by now */
571 assert(fb
->Width
== dPriv
->w
);
572 assert(fb
->Height
== dPriv
->h
);