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"
29 #include "../glsl/glsl_parser_extras.h"
31 PUBLIC
const char __dri2ConfigOptions
[] =
33 DRI_CONF_SECTION_PERFORMANCE
34 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1
)
38 static const uint __dri2NConfigOptions
= 1;
40 #ifndef GLX_OML_sync_control
41 typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC
) (__DRIdrawable
*drawable
, int32_t *numerator
, int32_t *denominator
);
44 static void dri_get_drawable(__DRIdrawable
*pdp
);
45 static void dri_put_drawable(__DRIdrawable
*pdp
);
47 /*****************************************************************/
48 /** \name Context (un)binding functions */
49 /*****************************************************************/
55 * \param scrn the screen.
58 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
61 * This function calls __DriverAPIRec::UnbindContext, and then decrements
62 * __DRIdrawableRec::refcount which must be non-zero for a successful
65 * While casting the opaque private pointers associated with the parameters
66 * into their respective real types it also assures they are not \c NULL.
68 static int driUnbindContext(__DRIcontext
*pcp
)
75 ** Assume error checking is done properly in glXMakeCurrent before
76 ** calling driUnbindContext.
82 psp
= pcp
->driScreenPriv
;
83 pdp
= pcp
->driDrawablePriv
;
84 prp
= pcp
->driReadablePriv
;
89 /* Let driver unbind drawable from context */
90 (*psp
->DriverAPI
.UnbindContext
)(pcp
);
93 if (pdp
->refcount
== 0) {
98 dri_put_drawable(pdp
);
101 if (prp
->refcount
== 0) {
106 dri_put_drawable(prp
);
110 /* XXX this is disabled so that if we call SwapBuffers on an unbound
111 * window we can determine the last context bound to the window and
112 * use that context's lock. (BrianP, 2-Dec-2000)
114 pcp
->driDrawablePriv
= pcp
->driReadablePriv
= NULL
;
120 * This function takes both a read buffer and a draw buffer. This is needed
121 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
124 static int driBindContext(__DRIcontext
*pcp
,
128 __DRIscreen
*psp
= NULL
;
131 ** Assume error checking is done properly in glXMakeCurrent before
132 ** calling driUnbindContext.
138 /* Bind the drawable to the context */
139 psp
= pcp
->driScreenPriv
;
140 pcp
->driDrawablePriv
= pdp
;
141 pcp
->driReadablePriv
= prp
;
143 pdp
->driContextPriv
= pcp
;
144 dri_get_drawable(pdp
);
146 if (prp
&& pdp
!= prp
) {
147 dri_get_drawable(prp
);
150 /* Call device-specific MakeCurrent */
151 return (*psp
->DriverAPI
.MakeCurrent
)(pcp
, pdp
, prp
);
154 static __DRIdrawable
*
155 dri2CreateNewDrawable(__DRIscreen
*screen
,
156 const __DRIconfig
*config
,
159 __DRIdrawable
*pdraw
;
161 pdraw
= malloc(sizeof *pdraw
);
165 pdraw
->driContextPriv
= NULL
;
166 pdraw
->loaderPrivate
= loaderPrivate
;
168 pdraw
->lastStamp
= 0;
171 pdraw
->driScreenPriv
= screen
;
173 if (!(*screen
->DriverAPI
.CreateBuffer
)(screen
, pdraw
, &config
->modes
, 0)) {
178 pdraw
->dri2
.stamp
= pdraw
->lastStamp
+ 1;
184 dri2AllocateBuffer(__DRIscreen
*screen
,
185 unsigned int attachment
, unsigned int format
,
186 int width
, int height
)
188 return (*screen
->DriverAPI
.AllocateBuffer
)(screen
, attachment
, format
,
193 dri2ReleaseBuffer(__DRIscreen
*screen
, __DRIbuffer
*buffer
)
195 (*screen
->DriverAPI
.ReleaseBuffer
)(screen
, buffer
);
200 dri2ConfigQueryb(__DRIscreen
*screen
, const char *var
, GLboolean
*val
)
202 if (!driCheckOption(&screen
->optionCache
, var
, DRI_BOOL
))
205 *val
= driQueryOptionb(&screen
->optionCache
, var
);
211 dri2ConfigQueryi(__DRIscreen
*screen
, const char *var
, GLint
*val
)
213 if (!driCheckOption(&screen
->optionCache
, var
, DRI_INT
) &&
214 !driCheckOption(&screen
->optionCache
, var
, DRI_ENUM
))
217 *val
= driQueryOptioni(&screen
->optionCache
, var
);
223 dri2ConfigQueryf(__DRIscreen
*screen
, const char *var
, GLfloat
*val
)
225 if (!driCheckOption(&screen
->optionCache
, var
, DRI_FLOAT
))
228 *val
= driQueryOptionf(&screen
->optionCache
, var
);
234 static void dri_get_drawable(__DRIdrawable
*pdp
)
239 static void dri_put_drawable(__DRIdrawable
*pdp
)
248 psp
= pdp
->driScreenPriv
;
249 (*psp
->DriverAPI
.DestroyBuffer
)(pdp
);
255 driDestroyDrawable(__DRIdrawable
*pdp
)
257 dri_put_drawable(pdp
);
263 /*****************************************************************/
264 /** \name Context handling functions */
265 /*****************************************************************/
269 * Destroy the per-context private information.
272 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
273 * drmDestroyContext(), and finally frees \p contextPrivate.
276 driDestroyContext(__DRIcontext
*pcp
)
279 (*pcp
->driScreenPriv
->DriverAPI
.DestroyContext
)(pcp
);
285 dri2GetAPIMask(__DRIscreen
*screen
)
287 return screen
->api_mask
;
290 static __DRIcontext
*
291 dri2CreateNewContextForAPI(__DRIscreen
*screen
, int api
,
292 const __DRIconfig
*config
,
293 __DRIcontext
*shared
, void *data
)
295 __DRIcontext
*context
;
296 const struct gl_config
*modes
= (config
!= NULL
) ? &config
->modes
: NULL
;
297 void *shareCtx
= (shared
!= NULL
) ? shared
->driverPrivate
: NULL
;
300 if (!(screen
->api_mask
& (1 << api
)))
304 case __DRI_API_OPENGL
:
305 mesa_api
= API_OPENGL
;
308 mesa_api
= API_OPENGLES
;
310 case __DRI_API_GLES2
:
311 mesa_api
= API_OPENGLES2
;
317 context
= malloc(sizeof *context
);
321 context
->driScreenPriv
= screen
;
322 context
->driDrawablePriv
= NULL
;
323 context
->loaderPrivate
= data
;
325 if (!(*screen
->DriverAPI
.CreateContext
)(mesa_api
, modes
,
326 context
, shareCtx
) ) {
335 static __DRIcontext
*
336 dri2CreateNewContext(__DRIscreen
*screen
, const __DRIconfig
*config
,
337 __DRIcontext
*shared
, void *data
)
339 return dri2CreateNewContextForAPI(screen
, __DRI_API_OPENGL
,
340 config
, shared
, data
);
344 driCopyContext(__DRIcontext
*dest
, __DRIcontext
*src
, unsigned long mask
)
355 /*****************************************************************/
356 /** \name Screen handling functions */
357 /*****************************************************************/
361 * Destroy the per-screen private information.
364 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
365 * drmClose(), and finally frees \p screenPrivate.
367 static void driDestroyScreen(__DRIscreen
*psp
)
370 /* No interaction with the X-server is possible at this point. This
371 * routine is called after XCloseDisplay, so there is no protocol
372 * stream open to the X-server anymore.
375 _mesa_destroy_shader_compiler();
377 if (psp
->DriverAPI
.DestroyScreen
)
378 (*psp
->DriverAPI
.DestroyScreen
)(psp
);
380 driDestroyOptionCache(&psp
->optionCache
);
381 driDestroyOptionInfo(&psp
->optionInfo
);
388 setupLoaderExtensions(__DRIscreen
*psp
,
389 const __DRIextension
**extensions
)
393 for (i
= 0; extensions
[i
]; i
++) {
394 if (strcmp(extensions
[i
]->name
, __DRI_DRI2_LOADER
) == 0)
395 psp
->dri2
.loader
= (__DRIdri2LoaderExtension
*) extensions
[i
];
396 if (strcmp(extensions
[i
]->name
, __DRI_IMAGE_LOOKUP
) == 0)
397 psp
->dri2
.image
= (__DRIimageLookupExtension
*) extensions
[i
];
398 if (strcmp(extensions
[i
]->name
, __DRI_USE_INVALIDATE
) == 0)
399 psp
->dri2
.useInvalidate
= (__DRIuseInvalidateExtension
*) extensions
[i
];
407 dri2CreateNewScreen(int scrn
, int fd
,
408 const __DRIextension
**extensions
,
409 const __DRIconfig
***driver_configs
, void *data
)
411 static const __DRIextension
*emptyExtensionList
[] = { NULL
};
413 drmVersionPtr version
;
415 psp
= calloc(1, sizeof(*psp
));
419 setupLoaderExtensions(psp
, extensions
);
421 version
= drmGetVersion(fd
);
423 psp
->drm_version
.major
= version
->version_major
;
424 psp
->drm_version
.minor
= version
->version_minor
;
425 psp
->drm_version
.patch
= version
->version_patchlevel
;
426 drmFreeVersion(version
);
429 psp
->extensions
= emptyExtensionList
;
433 psp
->DriverAPI
= driDriverAPI
;
434 psp
->api_mask
= (1 << __DRI_API_OPENGL
);
435 *driver_configs
= driDriverAPI
.InitScreen(psp
);
436 if (*driver_configs
== NULL
) {
441 psp
->DriverAPI
= driDriverAPI
;
442 psp
->loaderPrivate
= data
;
444 driParseOptionInfo(&psp
->optionInfo
, __dri2ConfigOptions
,
445 __dri2NConfigOptions
);
446 driParseConfigFiles(&psp
->optionCache
, &psp
->optionInfo
, psp
->myNum
,
452 static const __DRIextension
**driGetExtensions(__DRIscreen
*psp
)
454 return psp
->extensions
;
457 /** Core interface */
458 const __DRIcoreExtension driCoreExtension
= {
459 { __DRI_CORE
, __DRI_CORE_VERSION
},
464 driIndexConfigAttrib
,
475 /** DRI2 interface */
476 const __DRIdri2Extension driDRI2Extension
= {
477 { __DRI_DRI2
, __DRI_DRI2_VERSION
},
479 dri2CreateNewDrawable
,
480 dri2CreateNewContext
,
482 dri2CreateNewContextForAPI
,
487 const __DRI2configQueryExtension dri2ConfigQueryExtension
= {
488 { __DRI2_CONFIG_QUERY
, __DRI2_CONFIG_QUERY_VERSION
},
495 dri2InvalidateDrawable(__DRIdrawable
*drawable
)
497 drawable
->dri2
.stamp
++;
501 * Check that the gl_framebuffer associated with dPriv is the right size.
502 * Resize the gl_framebuffer if needed.
503 * It's expected that the dPriv->driverPrivate member points to a
504 * gl_framebuffer object.
507 driUpdateFramebufferSize(struct gl_context
*ctx
, const __DRIdrawable
*dPriv
)
509 struct gl_framebuffer
*fb
= (struct gl_framebuffer
*) dPriv
->driverPrivate
;
510 if (fb
&& (dPriv
->w
!= fb
->Width
|| dPriv
->h
!= fb
->Height
)) {
511 ctx
->Driver
.ResizeBuffers(ctx
, fb
, dPriv
->w
, dPriv
->h
);
512 /* if the driver needs the hw lock for ResizeBuffers, the drawable
513 might have changed again by now */
514 assert(fb
->Width
== dPriv
->w
);
515 assert(fb
->Height
== dPriv
->h
);