b3e6b126287d07cab321cf124d1f15c671c0b628
[profile/ivi/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 GLint
54 driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 )
55 {
56    if (rect2.x1 > rect1.x1) rect1.x1 = rect2.x1;
57    if (rect2.x2 < rect1.x2) rect1.x2 = rect2.x2;
58    if (rect2.y1 > rect1.y1) rect1.y1 = rect2.y1;
59    if (rect2.y2 < rect1.y2) rect1.y2 = rect2.y2;
60
61    if (rect1.x1 > rect1.x2 || rect1.y1 > rect1.y2) return 0;
62
63    return (rect1.x2 - rect1.x1) * (rect1.y2 - rect1.y1);
64 }
65
66 /*****************************************************************/
67 /** \name Context (un)binding functions                          */
68 /*****************************************************************/
69 /*@{*/
70
71 /**
72  * Unbind context.
73  * 
74  * \param scrn the screen.
75  * \param gc context.
76  *
77  * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
78  * 
79  * \internal
80  * This function calls __DriverAPIRec::UnbindContext, and then decrements
81  * __DRIdrawableRec::refcount which must be non-zero for a successful
82  * return.
83  * 
84  * While casting the opaque private pointers associated with the parameters
85  * into their respective real types it also assures they are not \c NULL. 
86  */
87 static int driUnbindContext(__DRIcontext *pcp)
88 {
89     __DRIscreen *psp;
90     __DRIdrawable *pdp;
91     __DRIdrawable *prp;
92
93     /*
94     ** Assume error checking is done properly in glXMakeCurrent before
95     ** calling driUnbindContext.
96     */
97
98     if (pcp == NULL)
99         return GL_FALSE;
100
101     psp = pcp->driScreenPriv;
102     pdp = pcp->driDrawablePriv;
103     prp = pcp->driReadablePriv;
104
105     /* already unbound */
106     if (!pdp && !prp)
107       return GL_TRUE;
108     /* Let driver unbind drawable from context */
109     (*psp->DriverAPI.UnbindContext)(pcp);
110
111     assert(pdp);
112     if (pdp->refcount == 0) {
113         /* ERROR!!! */
114         return GL_FALSE;
115     }
116
117     dri_put_drawable(pdp);
118
119     if (prp != pdp) {
120         if (prp->refcount == 0) {
121             /* ERROR!!! */
122             return GL_FALSE;
123         }
124
125         dri_put_drawable(prp);
126     }
127
128
129     /* XXX this is disabled so that if we call SwapBuffers on an unbound
130      * window we can determine the last context bound to the window and
131      * use that context's lock. (BrianP, 2-Dec-2000)
132      */
133     pcp->driDrawablePriv = pcp->driReadablePriv = NULL;
134
135     return GL_TRUE;
136 }
137
138 /**
139  * This function takes both a read buffer and a draw buffer.  This is needed
140  * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
141  * function.
142  */
143 static int driBindContext(__DRIcontext *pcp,
144                           __DRIdrawable *pdp,
145                           __DRIdrawable *prp)
146 {
147     __DRIscreen *psp = NULL;
148
149     /*
150     ** Assume error checking is done properly in glXMakeCurrent before
151     ** calling driUnbindContext.
152     */
153
154     if (!pcp)
155         return GL_FALSE;
156
157     /* Bind the drawable to the context */
158     psp = pcp->driScreenPriv;
159     pcp->driDrawablePriv = pdp;
160     pcp->driReadablePriv = prp;
161     if (pdp) {
162         pdp->driContextPriv = pcp;
163         dri_get_drawable(pdp);
164     }
165     if (prp && pdp != prp) {
166         dri_get_drawable(prp);
167     }
168
169     /*
170     ** Now that we have a context associated with this drawable, we can
171     ** initialize the drawable information if has not been done before.
172     */
173
174     if (!psp->dri2.enabled) {
175         if (pdp && !pdp->pStamp) {
176             DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
177             __driUtilUpdateDrawableInfo(pdp);
178             DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
179         }
180         if (prp && pdp != prp && !prp->pStamp) {
181             DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
182             __driUtilUpdateDrawableInfo(prp);
183             DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
184         }
185     }
186
187     /* Call device-specific MakeCurrent */
188     return (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
189 }
190
191 /*@}*/
192
193
194 /*****************************************************************/
195 /** \name Drawable handling functions                            */
196 /*****************************************************************/
197 /*@{*/
198
199 /**
200  * Update private drawable information.
201  *
202  * \param pdp pointer to the private drawable information to update.
203  * 
204  * This function basically updates the __DRIdrawable struct's
205  * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo.
206  * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
207  * compares the __DRIdrwablePrivate pStamp and lastStamp values.  If
208  * the values are different that means we have to update the clipping
209  * info.
210  */
211 void
212 __driUtilUpdateDrawableInfo(__DRIdrawable *pdp)
213 {
214     __DRIscreen *psp = pdp->driScreenPriv;
215     __DRIcontext *pcp = pdp->driContextPriv;
216     
217     if (!pcp 
218         || ((pdp != pcp->driDrawablePriv) && (pdp != pcp->driReadablePriv))) {
219         /* ERROR!!! 
220          * ...but we must ignore it. There can be many contexts bound to a
221          * drawable.
222          */
223     }
224
225     if (pdp->pClipRects) {
226         free(pdp->pClipRects); 
227         pdp->pClipRects = NULL;
228     }
229
230     if (pdp->pBackClipRects) {
231         free(pdp->pBackClipRects); 
232         pdp->pBackClipRects = NULL;
233     }
234
235     DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
236
237     if (! (*psp->getDrawableInfo->getDrawableInfo)(pdp,
238                           &pdp->index, &pdp->lastStamp,
239                           &pdp->x, &pdp->y, &pdp->w, &pdp->h,
240                           &pdp->numClipRects, &pdp->pClipRects,
241                           &pdp->backX,
242                           &pdp->backY,
243                           &pdp->numBackClipRects,
244                           &pdp->pBackClipRects,
245                           pdp->loaderPrivate)) {
246         /* Error -- eg the window may have been destroyed.  Keep going
247          * with no cliprects.
248          */
249         pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
250         pdp->numClipRects = 0;
251         pdp->pClipRects = NULL;
252         pdp->numBackClipRects = 0;
253         pdp->pBackClipRects = NULL;
254     }
255     else
256        pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
257
258     DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
259 }
260
261 static __DRIdrawable *
262 dri2CreateNewDrawable(__DRIscreen *screen,
263                       const __DRIconfig *config,
264                       void *loaderPrivate)
265 {
266     __DRIdrawable *pdraw;
267
268     pdraw = malloc(sizeof *pdraw);
269     if (!pdraw)
270         return NULL;
271
272     pdraw->driContextPriv = NULL;
273     pdraw->loaderPrivate = loaderPrivate;
274     pdraw->hHWDrawable = 0;
275     pdraw->refcount = 1;
276     pdraw->pStamp = NULL;
277     pdraw->lastStamp = 0;
278     pdraw->index = 0;
279     pdraw->x = 0;
280     pdraw->y = 0;
281     pdraw->w = 0;
282     pdraw->h = 0;
283     pdraw->numClipRects = 0;
284     pdraw->numBackClipRects = 0;
285     pdraw->pClipRects = NULL;
286     pdraw->pBackClipRects = NULL;
287     pdraw->vblSeq = 0;
288     pdraw->vblFlags = 0;
289
290     pdraw->driScreenPriv = screen;
291
292     if (!(*screen->DriverAPI.CreateBuffer)(screen, pdraw, &config->modes, 0)) {
293        free(pdraw);
294        return NULL;
295     }
296
297     pdraw->msc_base = 0;
298
299     /* This special default value is replaced with the configured
300      * default value when the drawable is first bound to a direct
301      * rendering context. 
302      */
303     pdraw->swap_interval = (unsigned)-1;
304
305     pdraw->pClipRects = &pdraw->dri2.clipRect;
306     pdraw->pBackClipRects = &pdraw->dri2.clipRect;
307
308     pdraw->pStamp = &pdraw->dri2.stamp;
309     *pdraw->pStamp = pdraw->lastStamp + 1;
310
311     return pdraw;
312 }
313
314 static __DRIbuffer *
315 dri2AllocateBuffer(__DRIscreen *screen,
316                    unsigned int attachment, unsigned int format,
317                    int width, int height)
318 {
319     return (*screen->DriverAPI.AllocateBuffer)(screen, attachment, format,
320                                                width, height);
321 }
322
323 static void
324 dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer)
325 {
326    (*screen->DriverAPI.ReleaseBuffer)(screen, buffer);
327 }
328
329
330 static int
331 dri2ConfigQueryb(__DRIscreen *screen, const char *var, GLboolean *val)
332 {
333    if (!driCheckOption(&screen->optionCache, var, DRI_BOOL))
334       return -1;
335
336    *val = driQueryOptionb(&screen->optionCache, var);
337
338    return 0;
339 }
340
341 static int
342 dri2ConfigQueryi(__DRIscreen *screen, const char *var, GLint *val)
343 {
344    if (!driCheckOption(&screen->optionCache, var, DRI_INT) &&
345        !driCheckOption(&screen->optionCache, var, DRI_ENUM))
346       return -1;
347
348     *val = driQueryOptioni(&screen->optionCache, var);
349
350     return 0;
351 }
352
353 static int
354 dri2ConfigQueryf(__DRIscreen *screen, const char *var, GLfloat *val)
355 {
356    if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT))
357       return -1;
358
359     *val = driQueryOptionf(&screen->optionCache, var);
360
361     return 0;
362 }
363
364
365 static void dri_get_drawable(__DRIdrawable *pdp)
366 {
367     pdp->refcount++;
368 }
369         
370 static void dri_put_drawable(__DRIdrawable *pdp)
371 {
372     __DRIscreen *psp;
373
374     if (pdp) {
375         pdp->refcount--;
376         if (pdp->refcount)
377             return;
378
379         psp = pdp->driScreenPriv;
380         (*psp->DriverAPI.DestroyBuffer)(pdp);
381         if (pdp->pClipRects && pdp->pClipRects != &pdp->dri2.clipRect) {
382             free(pdp->pClipRects);
383             pdp->pClipRects = NULL;
384         }
385         if (pdp->pBackClipRects && pdp->pClipRects != &pdp->dri2.clipRect) {
386             free(pdp->pBackClipRects);
387             pdp->pBackClipRects = NULL;
388         }
389         free(pdp);
390     }
391 }
392
393 static void
394 driDestroyDrawable(__DRIdrawable *pdp)
395 {
396     dri_put_drawable(pdp);
397 }
398
399 /*@}*/
400
401
402 /*****************************************************************/
403 /** \name Context handling functions                             */
404 /*****************************************************************/
405 /*@{*/
406
407 /**
408  * Destroy the per-context private information.
409  * 
410  * \internal
411  * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
412  * drmDestroyContext(), and finally frees \p contextPrivate.
413  */
414 static void
415 driDestroyContext(__DRIcontext *pcp)
416 {
417     if (pcp) {
418         (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
419         free(pcp);
420     }
421 }
422
423 static unsigned int
424 dri2GetAPIMask(__DRIscreen *screen)
425 {
426     return screen->api_mask;
427 }
428
429 static __DRIcontext *
430 dri2CreateNewContextForAPI(__DRIscreen *screen, int api,
431                            const __DRIconfig *config,
432                            __DRIcontext *shared, void *data)
433 {
434     __DRIcontext *context;
435     const struct gl_config *modes = (config != NULL) ? &config->modes : NULL;
436     void *shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
437     gl_api mesa_api;
438
439     if (!(screen->api_mask & (1 << api)))
440         return NULL;
441
442     switch (api) {
443     case __DRI_API_OPENGL:
444             mesa_api = API_OPENGL;
445             break;
446     case __DRI_API_GLES:
447             mesa_api = API_OPENGLES;
448             break;
449     case __DRI_API_GLES2:
450             mesa_api = API_OPENGLES2;
451             break;
452     default:
453             return NULL;
454     }
455
456     context = malloc(sizeof *context);
457     if (!context)
458         return NULL;
459
460     context->driScreenPriv = screen;
461     context->driDrawablePriv = NULL;
462     context->loaderPrivate = data;
463     
464     if (!(*screen->DriverAPI.CreateContext)(mesa_api, modes,
465                                             context, shareCtx) ) {
466         free(context);
467         return NULL;
468     }
469
470     return context;
471 }
472
473
474 static __DRIcontext *
475 dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
476                       __DRIcontext *shared, void *data)
477 {
478    return dri2CreateNewContextForAPI(screen, __DRI_API_OPENGL,
479                                      config, shared, data);
480 }
481
482 static int
483 driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask)
484 {
485     (void) dest;
486     (void) src;
487     (void) mask;
488     return GL_FALSE;
489 }
490
491 /*@}*/
492
493
494 /*****************************************************************/
495 /** \name Screen handling functions                              */
496 /*****************************************************************/
497 /*@{*/
498
499 /**
500  * Destroy the per-screen private information.
501  * 
502  * \internal
503  * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
504  * drmClose(), and finally frees \p screenPrivate.
505  */
506 static void driDestroyScreen(__DRIscreen *psp)
507 {
508     if (psp) {
509         /* No interaction with the X-server is possible at this point.  This
510          * routine is called after XCloseDisplay, so there is no protocol
511          * stream open to the X-server anymore.
512          */
513
514        _mesa_destroy_shader_compiler();
515
516         if (psp->DriverAPI.DestroyScreen)
517             (*psp->DriverAPI.DestroyScreen)(psp);
518
519         if (!psp->dri2.enabled) {
520            (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
521            (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
522            (void)drmCloseOnce(psp->fd);
523         } else {
524            driDestroyOptionCache(&psp->optionCache);
525            driDestroyOptionInfo(&psp->optionInfo);
526         }
527
528         free(psp);
529     }
530 }
531
532 static void
533 setupLoaderExtensions(__DRIscreen *psp,
534                       const __DRIextension **extensions)
535 {
536     int i;
537
538     for (i = 0; extensions[i]; i++) {
539         if (strcmp(extensions[i]->name, __DRI_GET_DRAWABLE_INFO) == 0)
540             psp->getDrawableInfo = (__DRIgetDrawableInfoExtension *) extensions[i];
541         if (strcmp(extensions[i]->name, __DRI_DAMAGE) == 0)
542             psp->damage = (__DRIdamageExtension *) extensions[i];
543         if (strcmp(extensions[i]->name, __DRI_SYSTEM_TIME) == 0)
544             psp->systemTime = (__DRIsystemTimeExtension *) extensions[i];
545         if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0)
546             psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i];
547         if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0)
548             psp->dri2.image = (__DRIimageLookupExtension *) extensions[i];
549         if (strcmp(extensions[i]->name, __DRI_USE_INVALIDATE) == 0)
550             psp->dri2.useInvalidate = (__DRIuseInvalidateExtension *) extensions[i];
551     }
552 }
553
554 /**
555  * DRI2
556  */
557 static __DRIscreen *
558 dri2CreateNewScreen(int scrn, int fd,
559                     const __DRIextension **extensions,
560                     const __DRIconfig ***driver_configs, void *data)
561 {
562     static const __DRIextension *emptyExtensionList[] = { NULL };
563     __DRIscreen *psp;
564     drmVersionPtr version;
565
566     if (driDriverAPI.InitScreen2 == NULL)
567         return NULL;
568
569     psp = calloc(1, sizeof(*psp));
570     if (!psp)
571         return NULL;
572
573     setupLoaderExtensions(psp, extensions);
574
575     version = drmGetVersion(fd);
576     if (version) {
577         psp->drm_version.major = version->version_major;
578         psp->drm_version.minor = version->version_minor;
579         psp->drm_version.patch = version->version_patchlevel;
580         drmFreeVersion(version);
581     }
582
583     psp->extensions = emptyExtensionList;
584     psp->fd = fd;
585     psp->myNum = scrn;
586     psp->dri2.enabled = GL_TRUE;
587
588     psp->DriverAPI = driDriverAPI;
589     psp->api_mask = (1 << __DRI_API_OPENGL);
590     *driver_configs = driDriverAPI.InitScreen2(psp);
591     if (*driver_configs == NULL) {
592         free(psp);
593         return NULL;
594     }
595
596     psp->DriverAPI = driDriverAPI;
597     psp->loaderPrivate = data;
598
599     driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions,
600                        __dri2NConfigOptions);
601     driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum,
602                         "dri2");
603
604     return psp;
605 }
606
607 static const __DRIextension **driGetExtensions(__DRIscreen *psp)
608 {
609     return psp->extensions;
610 }
611
612 /** Core interface */
613 const __DRIcoreExtension driCoreExtension = {
614     { __DRI_CORE, __DRI_CORE_VERSION },
615     NULL,
616     driDestroyScreen,
617     driGetExtensions,
618     driGetConfigAttrib,
619     driIndexConfigAttrib,
620     NULL,
621     driDestroyDrawable,
622     NULL,
623     NULL,
624     driCopyContext,
625     driDestroyContext,
626     driBindContext,
627     driUnbindContext
628 };
629
630 /** DRI2 interface */
631 const __DRIdri2Extension driDRI2Extension = {
632     { __DRI_DRI2, __DRI_DRI2_VERSION },
633     dri2CreateNewScreen,
634     dri2CreateNewDrawable,
635     dri2CreateNewContext,
636     dri2GetAPIMask,
637     dri2CreateNewContextForAPI,
638     dri2AllocateBuffer,
639     dri2ReleaseBuffer
640 };
641
642 const __DRI2configQueryExtension dri2ConfigQueryExtension = {
643    { __DRI2_CONFIG_QUERY, __DRI2_CONFIG_QUERY_VERSION },
644    dri2ConfigQueryb,
645    dri2ConfigQueryi,
646    dri2ConfigQueryf,
647 };
648
649 /**
650  * Calculate amount of swap interval used between GLX buffer swaps.
651  * 
652  * The usage value, on the range [0,max], is the fraction of total swap
653  * interval time used between GLX buffer swaps is calculated.
654  *
655  *            \f$p = t_d / (i * t_r)\f$
656  * 
657  * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
658  * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
659  * required for a single vertical refresh period (as returned by \c
660  * glXGetMscRateOML).
661  * 
662  * See the documentation for the GLX_MESA_swap_frame_usage extension for more
663  * details.
664  *
665  * \param   dPriv  Pointer to the private drawable structure.
666  * \return  If less than a single swap interval time period was required
667  *          between GLX buffer swaps, a number greater than 0 and less than
668  *          1.0 is returned.  If exactly one swap interval time period is
669  *          required, 1.0 is returned, and if more than one is required then
670  *          a number greater than 1.0 will be returned.
671  *
672  * \sa glXSwapIntervalSGI glXGetMscRateOML
673  * 
674  * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
675  *       be possible to cache the sync rate?
676  */
677 float
678 driCalculateSwapUsage( __DRIdrawable *dPriv, int64_t last_swap_ust,
679                        int64_t current_ust )
680 {
681    int32_t   n;
682    int32_t   d;
683    int       interval;
684    float     usage = 1.0;
685    __DRIscreen *psp = dPriv->driScreenPriv;
686
687    if ( (*psp->systemTime->getMSCRate)(dPriv, &n, &d, dPriv->loaderPrivate) ) {
688       interval = (dPriv->swap_interval != 0) ? dPriv->swap_interval : 1;
689
690
691       /* We want to calculate
692        * (current_UST - last_swap_UST) / (interval * us_per_refresh).  We get
693        * current_UST by calling __glXGetUST.  last_swap_UST is stored in
694        * dPriv->swap_ust.  interval has already been calculated.
695        *
696        * The only tricky part is us_per_refresh.  us_per_refresh is
697        * 1000000 / MSC_rate.  We know the MSC_rate is n / d.  We can flip it
698        * around and say us_per_refresh = 1000000 * d / n.  Since this goes in
699        * the denominator of the final calculation, we calculate
700        * (interval * 1000000 * d) and move n into the numerator.
701        */
702
703       usage = (current_ust - last_swap_ust);
704       usage *= n;
705       usage /= (interval * d);
706       usage /= 1000000.0;
707    }
708    
709    return usage;
710 }
711
712 void
713 dri2InvalidateDrawable(__DRIdrawable *drawable)
714 {
715     drawable->dri2.stamp++;
716 }
717
718 /*@}*/