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 "main/imports.h"
27 #include "../glsl/glsl_parser_extras.h"
29 PUBLIC
const char __dri2ConfigOptions
[] =
31 DRI_CONF_SECTION_PERFORMANCE
32 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1
)
36 static const uint __dri2NConfigOptions
= 1;
38 #ifndef GLX_OML_sync_control
39 typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC
) (__DRIdrawable
*drawable
, int32_t *numerator
, int32_t *denominator
);
42 static void dri_get_drawable(__DRIdrawable
*pdp
);
43 static void dri_put_drawable(__DRIdrawable
*pdp
);
45 /*****************************************************************/
46 /** \name Context (un)binding functions */
47 /*****************************************************************/
53 * \param scrn the screen.
56 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
59 * This function calls __DriverAPIRec::UnbindContext, and then decrements
60 * __DRIdrawableRec::refcount which must be non-zero for a successful
63 * While casting the opaque private pointers associated with the parameters
64 * into their respective real types it also assures they are not \c NULL.
66 static int driUnbindContext(__DRIcontext
*pcp
)
73 ** Assume error checking is done properly in glXMakeCurrent before
74 ** calling driUnbindContext.
80 psp
= pcp
->driScreenPriv
;
81 pdp
= pcp
->driDrawablePriv
;
82 prp
= pcp
->driReadablePriv
;
87 /* Let driver unbind drawable from context */
88 (*psp
->DriverAPI
.UnbindContext
)(pcp
);
91 if (pdp
->refcount
== 0) {
96 dri_put_drawable(pdp
);
99 if (prp
->refcount
== 0) {
104 dri_put_drawable(prp
);
108 /* XXX this is disabled so that if we call SwapBuffers on an unbound
109 * window we can determine the last context bound to the window and
110 * use that context's lock. (BrianP, 2-Dec-2000)
112 pcp
->driDrawablePriv
= pcp
->driReadablePriv
= NULL
;
118 * This function takes both a read buffer and a draw buffer. This is needed
119 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
122 static int driBindContext(__DRIcontext
*pcp
,
126 __DRIscreen
*psp
= NULL
;
129 ** Assume error checking is done properly in glXMakeCurrent before
130 ** calling driUnbindContext.
136 /* Bind the drawable to the context */
137 psp
= pcp
->driScreenPriv
;
138 pcp
->driDrawablePriv
= pdp
;
139 pcp
->driReadablePriv
= prp
;
141 pdp
->driContextPriv
= pcp
;
142 dri_get_drawable(pdp
);
144 if (prp
&& pdp
!= prp
) {
145 dri_get_drawable(prp
);
148 /* Call device-specific MakeCurrent */
149 return (*psp
->DriverAPI
.MakeCurrent
)(pcp
, pdp
, prp
);
152 static __DRIdrawable
*
153 dri2CreateNewDrawable(__DRIscreen
*screen
,
154 const __DRIconfig
*config
,
157 __DRIdrawable
*pdraw
;
159 pdraw
= malloc(sizeof *pdraw
);
163 pdraw
->driContextPriv
= NULL
;
164 pdraw
->loaderPrivate
= loaderPrivate
;
166 pdraw
->lastStamp
= 0;
169 pdraw
->driScreenPriv
= screen
;
171 if (!(*screen
->DriverAPI
.CreateBuffer
)(screen
, pdraw
, &config
->modes
, 0)) {
176 pdraw
->dri2
.stamp
= pdraw
->lastStamp
+ 1;
182 dri2AllocateBuffer(__DRIscreen
*screen
,
183 unsigned int attachment
, unsigned int format
,
184 int width
, int height
)
186 return (*screen
->DriverAPI
.AllocateBuffer
)(screen
, attachment
, format
,
191 dri2ReleaseBuffer(__DRIscreen
*screen
, __DRIbuffer
*buffer
)
193 (*screen
->DriverAPI
.ReleaseBuffer
)(screen
, buffer
);
198 dri2ConfigQueryb(__DRIscreen
*screen
, const char *var
, GLboolean
*val
)
200 if (!driCheckOption(&screen
->optionCache
, var
, DRI_BOOL
))
203 *val
= driQueryOptionb(&screen
->optionCache
, var
);
209 dri2ConfigQueryi(__DRIscreen
*screen
, const char *var
, GLint
*val
)
211 if (!driCheckOption(&screen
->optionCache
, var
, DRI_INT
) &&
212 !driCheckOption(&screen
->optionCache
, var
, DRI_ENUM
))
215 *val
= driQueryOptioni(&screen
->optionCache
, var
);
221 dri2ConfigQueryf(__DRIscreen
*screen
, const char *var
, GLfloat
*val
)
223 if (!driCheckOption(&screen
->optionCache
, var
, DRI_FLOAT
))
226 *val
= driQueryOptionf(&screen
->optionCache
, var
);
232 static void dri_get_drawable(__DRIdrawable
*pdp
)
237 static void dri_put_drawable(__DRIdrawable
*pdp
)
246 psp
= pdp
->driScreenPriv
;
247 (*psp
->DriverAPI
.DestroyBuffer
)(pdp
);
253 driDestroyDrawable(__DRIdrawable
*pdp
)
255 dri_put_drawable(pdp
);
261 /*****************************************************************/
262 /** \name Context handling functions */
263 /*****************************************************************/
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 (*pcp
->driScreenPriv
->DriverAPI
.DestroyContext
)(pcp
);
283 dri2GetAPIMask(__DRIscreen
*screen
)
285 return screen
->api_mask
;
288 static __DRIcontext
*
289 dri2CreateNewContextForAPI(__DRIscreen
*screen
, int api
,
290 const __DRIconfig
*config
,
291 __DRIcontext
*shared
, void *data
)
293 __DRIcontext
*context
;
294 const struct gl_config
*modes
= (config
!= NULL
) ? &config
->modes
: NULL
;
295 void *shareCtx
= (shared
!= NULL
) ? shared
->driverPrivate
: NULL
;
298 if (!(screen
->api_mask
& (1 << api
)))
302 case __DRI_API_OPENGL
:
303 mesa_api
= API_OPENGL
;
306 mesa_api
= API_OPENGLES
;
308 case __DRI_API_GLES2
:
309 mesa_api
= API_OPENGLES2
;
315 context
= malloc(sizeof *context
);
319 context
->driScreenPriv
= screen
;
320 context
->driDrawablePriv
= NULL
;
321 context
->loaderPrivate
= data
;
323 if (!(*screen
->DriverAPI
.CreateContext
)(mesa_api
, modes
,
324 context
, shareCtx
) ) {
333 static __DRIcontext
*
334 dri2CreateNewContext(__DRIscreen
*screen
, const __DRIconfig
*config
,
335 __DRIcontext
*shared
, void *data
)
337 return dri2CreateNewContextForAPI(screen
, __DRI_API_OPENGL
,
338 config
, shared
, data
);
342 driCopyContext(__DRIcontext
*dest
, __DRIcontext
*src
, unsigned long mask
)
353 /*****************************************************************/
354 /** \name Screen handling functions */
355 /*****************************************************************/
359 * Destroy the per-screen private information.
362 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
363 * drmClose(), and finally frees \p screenPrivate.
365 static void driDestroyScreen(__DRIscreen
*psp
)
368 /* No interaction with the X-server is possible at this point. This
369 * routine is called after XCloseDisplay, so there is no protocol
370 * stream open to the X-server anymore.
373 _mesa_destroy_shader_compiler();
375 if (psp
->DriverAPI
.DestroyScreen
)
376 (*psp
->DriverAPI
.DestroyScreen
)(psp
);
378 driDestroyOptionCache(&psp
->optionCache
);
379 driDestroyOptionInfo(&psp
->optionInfo
);
386 setupLoaderExtensions(__DRIscreen
*psp
,
387 const __DRIextension
**extensions
)
391 for (i
= 0; extensions
[i
]; i
++) {
392 if (strcmp(extensions
[i
]->name
, __DRI_DRI2_LOADER
) == 0)
393 psp
->dri2
.loader
= (__DRIdri2LoaderExtension
*) extensions
[i
];
394 if (strcmp(extensions
[i
]->name
, __DRI_IMAGE_LOOKUP
) == 0)
395 psp
->dri2
.image
= (__DRIimageLookupExtension
*) extensions
[i
];
396 if (strcmp(extensions
[i
]->name
, __DRI_USE_INVALIDATE
) == 0)
397 psp
->dri2
.useInvalidate
= (__DRIuseInvalidateExtension
*) extensions
[i
];
405 dri2CreateNewScreen(int scrn
, int fd
,
406 const __DRIextension
**extensions
,
407 const __DRIconfig
***driver_configs
, void *data
)
409 static const __DRIextension
*emptyExtensionList
[] = { NULL
};
411 drmVersionPtr version
;
413 if (driDriverAPI
.InitScreen2
== NULL
)
416 psp
= calloc(1, sizeof(*psp
));
420 setupLoaderExtensions(psp
, extensions
);
422 version
= drmGetVersion(fd
);
424 psp
->drm_version
.major
= version
->version_major
;
425 psp
->drm_version
.minor
= version
->version_minor
;
426 psp
->drm_version
.patch
= version
->version_patchlevel
;
427 drmFreeVersion(version
);
430 psp
->extensions
= emptyExtensionList
;
434 psp
->DriverAPI
= driDriverAPI
;
435 psp
->api_mask
= (1 << __DRI_API_OPENGL
);
436 *driver_configs
= driDriverAPI
.InitScreen2(psp
);
437 if (*driver_configs
== NULL
) {
442 psp
->DriverAPI
= driDriverAPI
;
443 psp
->loaderPrivate
= data
;
445 driParseOptionInfo(&psp
->optionInfo
, __dri2ConfigOptions
,
446 __dri2NConfigOptions
);
447 driParseConfigFiles(&psp
->optionCache
, &psp
->optionInfo
, psp
->myNum
,
453 static const __DRIextension
**driGetExtensions(__DRIscreen
*psp
)
455 return psp
->extensions
;
458 /** Core interface */
459 const __DRIcoreExtension driCoreExtension
= {
460 { __DRI_CORE
, __DRI_CORE_VERSION
},
465 driIndexConfigAttrib
,
476 /** DRI2 interface */
477 const __DRIdri2Extension driDRI2Extension
= {
478 { __DRI_DRI2
, __DRI_DRI2_VERSION
},
480 dri2CreateNewDrawable
,
481 dri2CreateNewContext
,
483 dri2CreateNewContextForAPI
,
488 const __DRI2configQueryExtension dri2ConfigQueryExtension
= {
489 { __DRI2_CONFIG_QUERY
, __DRI2_CONFIG_QUERY_VERSION
},
496 dri2InvalidateDrawable(__DRIdrawable
*drawable
)
498 drawable
->dri2
.stamp
++;
502 * Check that the gl_framebuffer associated with dPriv is the right size.
503 * Resize the gl_framebuffer if needed.
504 * It's expected that the dPriv->driverPrivate member points to a
505 * gl_framebuffer object.
508 driUpdateFramebufferSize(struct gl_context
*ctx
, const __DRIdrawable
*dPriv
)
510 struct gl_framebuffer
*fb
= (struct gl_framebuffer
*) dPriv
->driverPrivate
;
511 if (fb
&& (dPriv
->w
!= fb
->Width
|| dPriv
->h
!= fb
->Height
)) {
512 ctx
->Driver
.ResizeBuffers(ctx
, fb
, dPriv
->w
, dPriv
->h
);
513 /* if the driver needs the hw lock for ResizeBuffers, the drawable
514 might have changed again by now */
515 assert(fb
->Width
== dPriv
->w
);
516 assert(fb
->Height
== dPriv
->h
);