dri: Drop unused driCalculateSwapUsage
[mesa.git] / src / mesa / drivers / dri / common / dri_util.c
1 /**
2 * \file dri_util.c
3 * DRI utility functions.
4 *
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
8 * drivers.
9 *
10 * Basically, these utility functions take care of some of the dirty details of
11 * screen initialization, context creation, context binding, DRM setup, etc.
12 *
13 * These functions are compiled into each DRI driver so libGL.so knows nothing
14 * about them.
15 */
16
17
18 #include <assert.h>
19 #include <stdarg.h>
20 #include <unistd.h>
21 #include <sys/mman.h>
22 #include <stdio.h>
23
24 #ifndef MAP_FAILED
25 #define MAP_FAILED ((void *)-1)
26 #endif
27
28 #include "main/imports.h"
29 #define None 0
30
31 #include "dri_util.h"
32 #include "drm_sarea.h"
33 #include "utils.h"
34 #include "xmlpool.h"
35 #include "../glsl/glsl_parser_extras.h"
36
37 PUBLIC const char __dri2ConfigOptions[] =
38 DRI_CONF_BEGIN
39 DRI_CONF_SECTION_PERFORMANCE
40 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1)
41 DRI_CONF_SECTION_END
42 DRI_CONF_END;
43
44 static const uint __dri2NConfigOptions = 1;
45
46 #ifndef GLX_OML_sync_control
47 typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator);
48 #endif
49
50 static void dri_get_drawable(__DRIdrawable *pdp);
51 static void dri_put_drawable(__DRIdrawable *pdp);
52
53 /*****************************************************************/
54 /** \name Context (un)binding functions */
55 /*****************************************************************/
56 /*@{*/
57
58 /**
59 * Unbind context.
60 *
61 * \param scrn the screen.
62 * \param gc context.
63 *
64 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
65 *
66 * \internal
67 * This function calls __DriverAPIRec::UnbindContext, and then decrements
68 * __DRIdrawableRec::refcount which must be non-zero for a successful
69 * return.
70 *
71 * While casting the opaque private pointers associated with the parameters
72 * into their respective real types it also assures they are not \c NULL.
73 */
74 static int driUnbindContext(__DRIcontext *pcp)
75 {
76 __DRIscreen *psp;
77 __DRIdrawable *pdp;
78 __DRIdrawable *prp;
79
80 /*
81 ** Assume error checking is done properly in glXMakeCurrent before
82 ** calling driUnbindContext.
83 */
84
85 if (pcp == NULL)
86 return GL_FALSE;
87
88 psp = pcp->driScreenPriv;
89 pdp = pcp->driDrawablePriv;
90 prp = pcp->driReadablePriv;
91
92 /* already unbound */
93 if (!pdp && !prp)
94 return GL_TRUE;
95 /* Let driver unbind drawable from context */
96 (*psp->DriverAPI.UnbindContext)(pcp);
97
98 assert(pdp);
99 if (pdp->refcount == 0) {
100 /* ERROR!!! */
101 return GL_FALSE;
102 }
103
104 dri_put_drawable(pdp);
105
106 if (prp != pdp) {
107 if (prp->refcount == 0) {
108 /* ERROR!!! */
109 return GL_FALSE;
110 }
111
112 dri_put_drawable(prp);
113 }
114
115
116 /* XXX this is disabled so that if we call SwapBuffers on an unbound
117 * window we can determine the last context bound to the window and
118 * use that context's lock. (BrianP, 2-Dec-2000)
119 */
120 pcp->driDrawablePriv = pcp->driReadablePriv = NULL;
121
122 return GL_TRUE;
123 }
124
125 /**
126 * This function takes both a read buffer and a draw buffer. This is needed
127 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
128 * function.
129 */
130 static int driBindContext(__DRIcontext *pcp,
131 __DRIdrawable *pdp,
132 __DRIdrawable *prp)
133 {
134 __DRIscreen *psp = NULL;
135
136 /*
137 ** Assume error checking is done properly in glXMakeCurrent before
138 ** calling driUnbindContext.
139 */
140
141 if (!pcp)
142 return GL_FALSE;
143
144 /* Bind the drawable to the context */
145 psp = pcp->driScreenPriv;
146 pcp->driDrawablePriv = pdp;
147 pcp->driReadablePriv = prp;
148 if (pdp) {
149 pdp->driContextPriv = pcp;
150 dri_get_drawable(pdp);
151 }
152 if (prp && pdp != prp) {
153 dri_get_drawable(prp);
154 }
155
156 /* Call device-specific MakeCurrent */
157 return (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
158 }
159
160 static __DRIdrawable *
161 dri2CreateNewDrawable(__DRIscreen *screen,
162 const __DRIconfig *config,
163 void *loaderPrivate)
164 {
165 __DRIdrawable *pdraw;
166
167 pdraw = malloc(sizeof *pdraw);
168 if (!pdraw)
169 return NULL;
170
171 pdraw->driContextPriv = NULL;
172 pdraw->loaderPrivate = loaderPrivate;
173 pdraw->hHWDrawable = 0;
174 pdraw->refcount = 1;
175 pdraw->pStamp = NULL;
176 pdraw->lastStamp = 0;
177 pdraw->index = 0;
178 pdraw->x = 0;
179 pdraw->y = 0;
180 pdraw->w = 0;
181 pdraw->h = 0;
182 pdraw->numClipRects = 0;
183 pdraw->numBackClipRects = 0;
184 pdraw->pClipRects = NULL;
185 pdraw->pBackClipRects = NULL;
186 pdraw->vblSeq = 0;
187 pdraw->vblFlags = 0;
188
189 pdraw->driScreenPriv = screen;
190
191 if (!(*screen->DriverAPI.CreateBuffer)(screen, pdraw, &config->modes, 0)) {
192 free(pdraw);
193 return NULL;
194 }
195
196 pdraw->msc_base = 0;
197
198 /* This special default value is replaced with the configured
199 * default value when the drawable is first bound to a direct
200 * rendering context.
201 */
202 pdraw->swap_interval = (unsigned)-1;
203
204 pdraw->pClipRects = &pdraw->dri2.clipRect;
205 pdraw->pBackClipRects = &pdraw->dri2.clipRect;
206
207 pdraw->pStamp = &pdraw->dri2.stamp;
208 *pdraw->pStamp = pdraw->lastStamp + 1;
209
210 return pdraw;
211 }
212
213 static __DRIbuffer *
214 dri2AllocateBuffer(__DRIscreen *screen,
215 unsigned int attachment, unsigned int format,
216 int width, int height)
217 {
218 return (*screen->DriverAPI.AllocateBuffer)(screen, attachment, format,
219 width, height);
220 }
221
222 static void
223 dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer)
224 {
225 (*screen->DriverAPI.ReleaseBuffer)(screen, buffer);
226 }
227
228
229 static int
230 dri2ConfigQueryb(__DRIscreen *screen, const char *var, GLboolean *val)
231 {
232 if (!driCheckOption(&screen->optionCache, var, DRI_BOOL))
233 return -1;
234
235 *val = driQueryOptionb(&screen->optionCache, var);
236
237 return 0;
238 }
239
240 static int
241 dri2ConfigQueryi(__DRIscreen *screen, const char *var, GLint *val)
242 {
243 if (!driCheckOption(&screen->optionCache, var, DRI_INT) &&
244 !driCheckOption(&screen->optionCache, var, DRI_ENUM))
245 return -1;
246
247 *val = driQueryOptioni(&screen->optionCache, var);
248
249 return 0;
250 }
251
252 static int
253 dri2ConfigQueryf(__DRIscreen *screen, const char *var, GLfloat *val)
254 {
255 if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT))
256 return -1;
257
258 *val = driQueryOptionf(&screen->optionCache, var);
259
260 return 0;
261 }
262
263
264 static void dri_get_drawable(__DRIdrawable *pdp)
265 {
266 pdp->refcount++;
267 }
268
269 static void dri_put_drawable(__DRIdrawable *pdp)
270 {
271 __DRIscreen *psp;
272
273 if (pdp) {
274 pdp->refcount--;
275 if (pdp->refcount)
276 return;
277
278 psp = pdp->driScreenPriv;
279 (*psp->DriverAPI.DestroyBuffer)(pdp);
280 if (pdp->pClipRects && pdp->pClipRects != &pdp->dri2.clipRect) {
281 free(pdp->pClipRects);
282 pdp->pClipRects = NULL;
283 }
284 if (pdp->pBackClipRects && pdp->pClipRects != &pdp->dri2.clipRect) {
285 free(pdp->pBackClipRects);
286 pdp->pBackClipRects = NULL;
287 }
288 free(pdp);
289 }
290 }
291
292 static void
293 driDestroyDrawable(__DRIdrawable *pdp)
294 {
295 dri_put_drawable(pdp);
296 }
297
298 /*@}*/
299
300
301 /*****************************************************************/
302 /** \name Context handling functions */
303 /*****************************************************************/
304 /*@{*/
305
306 /**
307 * Destroy the per-context private information.
308 *
309 * \internal
310 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
311 * drmDestroyContext(), and finally frees \p contextPrivate.
312 */
313 static void
314 driDestroyContext(__DRIcontext *pcp)
315 {
316 if (pcp) {
317 (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
318 free(pcp);
319 }
320 }
321
322 static unsigned int
323 dri2GetAPIMask(__DRIscreen *screen)
324 {
325 return screen->api_mask;
326 }
327
328 static __DRIcontext *
329 dri2CreateNewContextForAPI(__DRIscreen *screen, int api,
330 const __DRIconfig *config,
331 __DRIcontext *shared, void *data)
332 {
333 __DRIcontext *context;
334 const struct gl_config *modes = (config != NULL) ? &config->modes : NULL;
335 void *shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
336 gl_api mesa_api;
337
338 if (!(screen->api_mask & (1 << api)))
339 return NULL;
340
341 switch (api) {
342 case __DRI_API_OPENGL:
343 mesa_api = API_OPENGL;
344 break;
345 case __DRI_API_GLES:
346 mesa_api = API_OPENGLES;
347 break;
348 case __DRI_API_GLES2:
349 mesa_api = API_OPENGLES2;
350 break;
351 default:
352 return NULL;
353 }
354
355 context = malloc(sizeof *context);
356 if (!context)
357 return NULL;
358
359 context->driScreenPriv = screen;
360 context->driDrawablePriv = NULL;
361 context->loaderPrivate = data;
362
363 if (!(*screen->DriverAPI.CreateContext)(mesa_api, modes,
364 context, shareCtx) ) {
365 free(context);
366 return NULL;
367 }
368
369 return context;
370 }
371
372
373 static __DRIcontext *
374 dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
375 __DRIcontext *shared, void *data)
376 {
377 return dri2CreateNewContextForAPI(screen, __DRI_API_OPENGL,
378 config, shared, data);
379 }
380
381 static int
382 driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask)
383 {
384 (void) dest;
385 (void) src;
386 (void) mask;
387 return GL_FALSE;
388 }
389
390 /*@}*/
391
392
393 /*****************************************************************/
394 /** \name Screen handling functions */
395 /*****************************************************************/
396 /*@{*/
397
398 /**
399 * Destroy the per-screen private information.
400 *
401 * \internal
402 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
403 * drmClose(), and finally frees \p screenPrivate.
404 */
405 static void driDestroyScreen(__DRIscreen *psp)
406 {
407 if (psp) {
408 /* No interaction with the X-server is possible at this point. This
409 * routine is called after XCloseDisplay, so there is no protocol
410 * stream open to the X-server anymore.
411 */
412
413 _mesa_destroy_shader_compiler();
414
415 if (psp->DriverAPI.DestroyScreen)
416 (*psp->DriverAPI.DestroyScreen)(psp);
417
418 if (!psp->dri2.enabled) {
419 (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
420 (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
421 (void)drmCloseOnce(psp->fd);
422 } else {
423 driDestroyOptionCache(&psp->optionCache);
424 driDestroyOptionInfo(&psp->optionInfo);
425 }
426
427 free(psp);
428 }
429 }
430
431 static void
432 setupLoaderExtensions(__DRIscreen *psp,
433 const __DRIextension **extensions)
434 {
435 int i;
436
437 for (i = 0; extensions[i]; i++) {
438 if (strcmp(extensions[i]->name, __DRI_GET_DRAWABLE_INFO) == 0)
439 psp->getDrawableInfo = (__DRIgetDrawableInfoExtension *) extensions[i];
440 if (strcmp(extensions[i]->name, __DRI_DAMAGE) == 0)
441 psp->damage = (__DRIdamageExtension *) extensions[i];
442 if (strcmp(extensions[i]->name, __DRI_SYSTEM_TIME) == 0)
443 psp->systemTime = (__DRIsystemTimeExtension *) extensions[i];
444 if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0)
445 psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i];
446 if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0)
447 psp->dri2.image = (__DRIimageLookupExtension *) extensions[i];
448 if (strcmp(extensions[i]->name, __DRI_USE_INVALIDATE) == 0)
449 psp->dri2.useInvalidate = (__DRIuseInvalidateExtension *) extensions[i];
450 }
451 }
452
453 /**
454 * DRI2
455 */
456 static __DRIscreen *
457 dri2CreateNewScreen(int scrn, int fd,
458 const __DRIextension **extensions,
459 const __DRIconfig ***driver_configs, void *data)
460 {
461 static const __DRIextension *emptyExtensionList[] = { NULL };
462 __DRIscreen *psp;
463 drmVersionPtr version;
464
465 if (driDriverAPI.InitScreen2 == NULL)
466 return NULL;
467
468 psp = calloc(1, sizeof(*psp));
469 if (!psp)
470 return NULL;
471
472 setupLoaderExtensions(psp, extensions);
473
474 version = drmGetVersion(fd);
475 if (version) {
476 psp->drm_version.major = version->version_major;
477 psp->drm_version.minor = version->version_minor;
478 psp->drm_version.patch = version->version_patchlevel;
479 drmFreeVersion(version);
480 }
481
482 psp->extensions = emptyExtensionList;
483 psp->fd = fd;
484 psp->myNum = scrn;
485 psp->dri2.enabled = GL_TRUE;
486
487 psp->DriverAPI = driDriverAPI;
488 psp->api_mask = (1 << __DRI_API_OPENGL);
489 *driver_configs = driDriverAPI.InitScreen2(psp);
490 if (*driver_configs == NULL) {
491 free(psp);
492 return NULL;
493 }
494
495 psp->DriverAPI = driDriverAPI;
496 psp->loaderPrivate = data;
497
498 driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions,
499 __dri2NConfigOptions);
500 driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum,
501 "dri2");
502
503 return psp;
504 }
505
506 static const __DRIextension **driGetExtensions(__DRIscreen *psp)
507 {
508 return psp->extensions;
509 }
510
511 /** Core interface */
512 const __DRIcoreExtension driCoreExtension = {
513 { __DRI_CORE, __DRI_CORE_VERSION },
514 NULL,
515 driDestroyScreen,
516 driGetExtensions,
517 driGetConfigAttrib,
518 driIndexConfigAttrib,
519 NULL,
520 driDestroyDrawable,
521 NULL,
522 NULL,
523 driCopyContext,
524 driDestroyContext,
525 driBindContext,
526 driUnbindContext
527 };
528
529 /** DRI2 interface */
530 const __DRIdri2Extension driDRI2Extension = {
531 { __DRI_DRI2, __DRI_DRI2_VERSION },
532 dri2CreateNewScreen,
533 dri2CreateNewDrawable,
534 dri2CreateNewContext,
535 dri2GetAPIMask,
536 dri2CreateNewContextForAPI,
537 dri2AllocateBuffer,
538 dri2ReleaseBuffer
539 };
540
541 const __DRI2configQueryExtension dri2ConfigQueryExtension = {
542 { __DRI2_CONFIG_QUERY, __DRI2_CONFIG_QUERY_VERSION },
543 dri2ConfigQueryb,
544 dri2ConfigQueryi,
545 dri2ConfigQueryf,
546 };
547
548 void
549 dri2InvalidateDrawable(__DRIdrawable *drawable)
550 {
551 drawable->dri2.stamp++;
552 }
553
554 /*@}*/