Merge branch '7.8'
[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
35 #ifndef GLX_OML_sync_control
36 typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator);
37 #endif
38
39 static void dri_get_drawable(__DRIdrawable *pdp);
40 static void dri_put_drawable(__DRIdrawable *pdp);
41
42 /**
43 * This is just a token extension used to signal that the driver
44 * supports setting a read drawable.
45 */
46 const __DRIextension driReadDrawableExtension = {
47 __DRI_READ_DRAWABLE, __DRI_READ_DRAWABLE_VERSION
48 };
49
50 GLint
51 driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 )
52 {
53 if (rect2.x1 > rect1.x1) rect1.x1 = rect2.x1;
54 if (rect2.x2 < rect1.x2) rect1.x2 = rect2.x2;
55 if (rect2.y1 > rect1.y1) rect1.y1 = rect2.y1;
56 if (rect2.y2 < rect1.y2) rect1.y2 = rect2.y2;
57
58 if (rect1.x1 > rect1.x2 || rect1.y1 > rect1.y2) return 0;
59
60 return (rect1.x2 - rect1.x1) * (rect1.y2 - rect1.y1);
61 }
62
63 /*****************************************************************/
64 /** \name Context (un)binding functions */
65 /*****************************************************************/
66 /*@{*/
67
68 /**
69 * Unbind context.
70 *
71 * \param scrn the screen.
72 * \param gc context.
73 *
74 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
75 *
76 * \internal
77 * This function calls __DriverAPIRec::UnbindContext, and then decrements
78 * __DRIdrawableRec::refcount which must be non-zero for a successful
79 * return.
80 *
81 * While casting the opaque private pointers associated with the parameters
82 * into their respective real types it also assures they are not \c NULL.
83 */
84 static int driUnbindContext(__DRIcontext *pcp)
85 {
86 __DRIscreen *psp;
87 __DRIdrawable *pdp;
88 __DRIdrawable *prp;
89
90 /*
91 ** Assume error checking is done properly in glXMakeCurrent before
92 ** calling driUnbindContext.
93 */
94
95 if (pcp == NULL)
96 return GL_FALSE;
97
98 psp = pcp->driScreenPriv;
99 pdp = pcp->driDrawablePriv;
100 prp = pcp->driReadablePriv;
101
102 /* already unbound */
103 if (!pdp && !prp)
104 return GL_TRUE;
105 /* Let driver unbind drawable from context */
106 (*psp->DriverAPI.UnbindContext)(pcp);
107
108 assert(pdp);
109 if (pdp->refcount == 0) {
110 /* ERROR!!! */
111 return GL_FALSE;
112 }
113
114 dri_put_drawable(pdp);
115
116 if (prp != pdp) {
117 if (prp->refcount == 0) {
118 /* ERROR!!! */
119 return GL_FALSE;
120 }
121
122 dri_put_drawable(prp);
123 }
124
125
126 /* XXX this is disabled so that if we call SwapBuffers on an unbound
127 * window we can determine the last context bound to the window and
128 * use that context's lock. (BrianP, 2-Dec-2000)
129 */
130 pcp->driDrawablePriv = pcp->driReadablePriv = NULL;
131
132 #if 0
133 /* Unbind the drawable */
134 pdp->driContextPriv = &psp->dummyContextPriv;
135 #endif
136
137 return GL_TRUE;
138 }
139
140 /**
141 * This function takes both a read buffer and a draw buffer. This is needed
142 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
143 * function.
144 */
145 static int driBindContext(__DRIcontext *pcp,
146 __DRIdrawable *pdp,
147 __DRIdrawable *prp)
148 {
149 __DRIscreen *psp = NULL;
150
151 /* Bind the drawable to the context */
152
153 if (pcp) {
154 psp = pcp->driScreenPriv;
155 pcp->driDrawablePriv = pdp;
156 pcp->driReadablePriv = prp;
157 if (pdp) {
158 pdp->driContextPriv = pcp;
159 dri_get_drawable(pdp);
160 }
161 if ( prp && pdp != prp ) {
162 dri_get_drawable(prp);
163 }
164 }
165
166 /*
167 ** Now that we have a context associated with this drawable, we can
168 ** initialize the drawable information if has not been done before.
169 */
170
171 assert(psp);
172 if (!psp->dri2.enabled) {
173 if (pdp && !pdp->pStamp) {
174 DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
175 __driUtilUpdateDrawableInfo(pdp);
176 DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
177 }
178 if (prp && pdp != prp && !prp->pStamp) {
179 DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
180 __driUtilUpdateDrawableInfo(prp);
181 DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
182 }
183 }
184
185 /* Call device-specific MakeCurrent */
186
187 return (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
188 }
189
190 /*@}*/
191
192
193 /*****************************************************************/
194 /** \name Drawable handling functions */
195 /*****************************************************************/
196 /*@{*/
197
198 /**
199 * Update private drawable information.
200 *
201 * \param pdp pointer to the private drawable information to update.
202 *
203 * This function basically updates the __DRIdrawable struct's
204 * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo.
205 * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
206 * compares the __DRIdrwablePrivate pStamp and lastStamp values. If
207 * the values are different that means we have to update the clipping
208 * info.
209 */
210 void
211 __driUtilUpdateDrawableInfo(__DRIdrawable *pdp)
212 {
213 __DRIscreen *psp = pdp->driScreenPriv;
214 __DRIcontext *pcp = pdp->driContextPriv;
215
216 if (!pcp
217 || ((pdp != pcp->driDrawablePriv) && (pdp != pcp->driReadablePriv))) {
218 /* ERROR!!!
219 * ...but we must ignore it. There can be many contexts bound to a
220 * drawable.
221 */
222 }
223
224 if (pdp->pClipRects) {
225 free(pdp->pClipRects);
226 pdp->pClipRects = NULL;
227 }
228
229 if (pdp->pBackClipRects) {
230 free(pdp->pBackClipRects);
231 pdp->pBackClipRects = NULL;
232 }
233
234 DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
235
236 if (! (*psp->getDrawableInfo->getDrawableInfo)(pdp,
237 &pdp->index, &pdp->lastStamp,
238 &pdp->x, &pdp->y, &pdp->w, &pdp->h,
239 &pdp->numClipRects, &pdp->pClipRects,
240 &pdp->backX,
241 &pdp->backY,
242 &pdp->numBackClipRects,
243 &pdp->pBackClipRects,
244 pdp->loaderPrivate)) {
245 /* Error -- eg the window may have been destroyed. Keep going
246 * with no cliprects.
247 */
248 pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
249 pdp->numClipRects = 0;
250 pdp->pClipRects = NULL;
251 pdp->numBackClipRects = 0;
252 pdp->pBackClipRects = NULL;
253 }
254 else
255 pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
256
257 DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
258 }
259
260 /*@}*/
261
262 /*****************************************************************/
263 /** \name GLX callbacks */
264 /*****************************************************************/
265 /*@{*/
266
267 static void driReportDamage(__DRIdrawable *pdp,
268 struct drm_clip_rect *pClipRects, int numClipRects)
269 {
270 __DRIscreen *psp = pdp->driScreenPriv;
271
272 /* Check that we actually have the new damage report method */
273 if (psp->damage) {
274 /* Report the damage. Currently, all our drivers draw
275 * directly to the front buffer, so we report the damage there
276 * rather than to the backing storein (if any).
277 */
278 (*psp->damage->reportDamage)(pdp,
279 pdp->x, pdp->y,
280 pClipRects, numClipRects,
281 GL_TRUE, pdp->loaderPrivate);
282 }
283 }
284
285
286 /**
287 * Swap buffers.
288 *
289 * \param drawablePrivate opaque pointer to the per-drawable private info.
290 *
291 * \internal
292 * This function calls __DRIdrawable::swapBuffers.
293 *
294 * Is called directly from glXSwapBuffers().
295 */
296 static void driSwapBuffers(__DRIdrawable *dPriv)
297 {
298 __DRIscreen *psp = dPriv->driScreenPriv;
299 drm_clip_rect_t *rects;
300 int i;
301
302 psp->DriverAPI.SwapBuffers(dPriv);
303
304 if (!dPriv->numClipRects)
305 return;
306
307 rects = malloc(sizeof(*rects) * dPriv->numClipRects);
308
309 if (!rects)
310 return;
311
312 for (i = 0; i < dPriv->numClipRects; i++) {
313 rects[i].x1 = dPriv->pClipRects[i].x1 - dPriv->x;
314 rects[i].y1 = dPriv->pClipRects[i].y1 - dPriv->y;
315 rects[i].x2 = dPriv->pClipRects[i].x2 - dPriv->x;
316 rects[i].y2 = dPriv->pClipRects[i].y2 - dPriv->y;
317 }
318
319 driReportDamage(dPriv, rects, dPriv->numClipRects);
320 free(rects);
321 }
322
323 static int driDrawableGetMSC( __DRIscreen *sPriv, __DRIdrawable *dPriv,
324 int64_t *msc )
325 {
326 return sPriv->DriverAPI.GetDrawableMSC(sPriv, dPriv, msc);
327 }
328
329
330 static int driWaitForMSC(__DRIdrawable *dPriv, int64_t target_msc,
331 int64_t divisor, int64_t remainder,
332 int64_t * msc, int64_t * sbc)
333 {
334 __DRIswapInfo sInfo;
335 int status;
336
337 status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
338 divisor, remainder,
339 msc );
340
341 /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
342 * is supported but GLX_OML_sync_control is not. Therefore, don't return
343 * an error value if GetSwapInfo() is not implemented.
344 */
345 if ( status == 0
346 && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) {
347 status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
348 *sbc = sInfo.swap_count;
349 }
350
351 return status;
352 }
353
354
355 const __DRImediaStreamCounterExtension driMediaStreamCounterExtension = {
356 { __DRI_MEDIA_STREAM_COUNTER, __DRI_MEDIA_STREAM_COUNTER_VERSION },
357 driWaitForMSC,
358 driDrawableGetMSC,
359 };
360
361
362 static void driCopySubBuffer(__DRIdrawable *dPriv,
363 int x, int y, int w, int h)
364 {
365 drm_clip_rect_t rect;
366
367 rect.x1 = x;
368 rect.y1 = dPriv->h - y - h;
369 rect.x2 = x + w;
370 rect.y2 = rect.y1 + h;
371 driReportDamage(dPriv, &rect, 1);
372
373 dPriv->driScreenPriv->DriverAPI.CopySubBuffer(dPriv, x, y, w, h);
374 }
375
376 const __DRIcopySubBufferExtension driCopySubBufferExtension = {
377 { __DRI_COPY_SUB_BUFFER, __DRI_COPY_SUB_BUFFER_VERSION },
378 driCopySubBuffer
379 };
380
381 static void driSetSwapInterval(__DRIdrawable *dPriv, unsigned int interval)
382 {
383 dPriv->swap_interval = interval;
384 }
385
386 static unsigned int driGetSwapInterval(__DRIdrawable *dPriv)
387 {
388 return dPriv->swap_interval;
389 }
390
391 const __DRIswapControlExtension driSwapControlExtension = {
392 { __DRI_SWAP_CONTROL, __DRI_SWAP_CONTROL_VERSION },
393 driSetSwapInterval,
394 driGetSwapInterval
395 };
396
397
398 /**
399 * This is called via __DRIscreenRec's createNewDrawable pointer.
400 */
401 static __DRIdrawable *
402 driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config,
403 drm_drawable_t hwDrawable, int renderType,
404 const int *attrs, void *data)
405 {
406 __DRIdrawable *pdp;
407
408 /* Since pbuffers are not yet supported, no drawable attributes are
409 * supported either.
410 */
411 (void) attrs;
412
413 pdp = malloc(sizeof *pdp);
414 if (!pdp) {
415 return NULL;
416 }
417
418 pdp->loaderPrivate = data;
419 pdp->hHWDrawable = hwDrawable;
420 pdp->refcount = 1;
421 pdp->pStamp = NULL;
422 pdp->lastStamp = 0;
423 pdp->index = 0;
424 pdp->x = 0;
425 pdp->y = 0;
426 pdp->w = 0;
427 pdp->h = 0;
428 pdp->numClipRects = 0;
429 pdp->numBackClipRects = 0;
430 pdp->pClipRects = NULL;
431 pdp->pBackClipRects = NULL;
432 pdp->vblSeq = 0;
433 pdp->vblFlags = 0;
434
435 pdp->driScreenPriv = psp;
436 pdp->driContextPriv = &psp->dummyContextPriv;
437
438 if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes,
439 renderType == GLX_PIXMAP_BIT)) {
440 free(pdp);
441 return NULL;
442 }
443
444 pdp->msc_base = 0;
445
446 /* This special default value is replaced with the configured
447 * default value when the drawable is first bound to a direct
448 * rendering context.
449 */
450 pdp->swap_interval = (unsigned)-1;
451
452 return pdp;
453 }
454
455
456 static __DRIdrawable *
457 dri2CreateNewDrawable(__DRIscreen *screen,
458 const __DRIconfig *config,
459 void *loaderPrivate)
460 {
461 __DRIdrawable *pdraw;
462
463 pdraw = driCreateNewDrawable(screen, config, 0, 0, NULL, loaderPrivate);
464 if (!pdraw)
465 return NULL;
466
467 pdraw->pClipRects = &pdraw->dri2.clipRect;
468 pdraw->pBackClipRects = &pdraw->dri2.clipRect;
469
470 pdraw->pStamp = &pdraw->dri2.stamp;
471 *pdraw->pStamp = pdraw->lastStamp + 1;
472
473 return pdraw;
474 }
475
476 static void dri_get_drawable(__DRIdrawable *pdp)
477 {
478 pdp->refcount++;
479 }
480
481 static void dri_put_drawable(__DRIdrawable *pdp)
482 {
483 __DRIscreen *psp;
484
485 if (pdp) {
486 pdp->refcount--;
487 if (pdp->refcount)
488 return;
489
490 psp = pdp->driScreenPriv;
491 (*psp->DriverAPI.DestroyBuffer)(pdp);
492 if (pdp->pClipRects && pdp->pClipRects != &pdp->dri2.clipRect) {
493 free(pdp->pClipRects);
494 pdp->pClipRects = NULL;
495 }
496 if (pdp->pBackClipRects && pdp->pClipRects != &pdp->dri2.clipRect) {
497 free(pdp->pBackClipRects);
498 pdp->pBackClipRects = NULL;
499 }
500 free(pdp);
501 }
502 }
503
504 static void
505 driDestroyDrawable(__DRIdrawable *pdp)
506 {
507 dri_put_drawable(pdp);
508 }
509
510 /*@}*/
511
512
513 /*****************************************************************/
514 /** \name Context handling functions */
515 /*****************************************************************/
516 /*@{*/
517
518 /**
519 * Destroy the per-context private information.
520 *
521 * \internal
522 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
523 * drmDestroyContext(), and finally frees \p contextPrivate.
524 */
525 static void
526 driDestroyContext(__DRIcontext *pcp)
527 {
528 if (pcp) {
529 (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
530 free(pcp);
531 }
532 }
533
534
535 /**
536 * Create the per-drawable private driver information.
537 *
538 * \param render_type Type of rendering target. \c GLX_RGBA is the only
539 * type likely to ever be supported for direct-rendering.
540 * \param shared Context with which to share textures, etc. or NULL
541 *
542 * \returns An opaque pointer to the per-context private information on
543 * success, or \c NULL on failure.
544 *
545 * \internal
546 * This function allocates and fills a __DRIcontextRec structure. It
547 * performs some device independent initialization and passes all the
548 * relevent information to __DriverAPIRec::CreateContext to create the
549 * context.
550 *
551 */
552 static __DRIcontext *
553 driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config,
554 int render_type, __DRIcontext *shared,
555 drm_context_t hwContext, void *data)
556 {
557 __DRIcontext *pcp;
558 void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
559
560 pcp = malloc(sizeof *pcp);
561 if (!pcp)
562 return NULL;
563
564 pcp->driScreenPriv = psp;
565 pcp->driDrawablePriv = NULL;
566 pcp->loaderPrivate = data;
567
568 pcp->dri2.draw_stamp = 0;
569 pcp->dri2.read_stamp = 0;
570 /* When the first context is created for a screen, initialize a "dummy"
571 * context.
572 */
573
574 if (!psp->dri2.enabled && !psp->dummyContextPriv.driScreenPriv) {
575 psp->dummyContextPriv.hHWContext = psp->pSAREA->dummy_context;
576 psp->dummyContextPriv.driScreenPriv = psp;
577 psp->dummyContextPriv.driDrawablePriv = NULL;
578 psp->dummyContextPriv.driverPrivate = NULL;
579 /* No other fields should be used! */
580 }
581
582 pcp->hHWContext = hwContext;
583
584 if ( !(*psp->DriverAPI.CreateContext)(&config->modes, pcp, shareCtx) ) {
585 free(pcp);
586 return NULL;
587 }
588
589 return pcp;
590 }
591
592
593 static __DRIcontext *
594 dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
595 __DRIcontext *shared, void *data)
596 {
597 return driCreateNewContext(screen, config, 0, shared, 0, data);
598 }
599
600
601 static int
602 driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask)
603 {
604 return GL_FALSE;
605 }
606
607 /*@}*/
608
609
610 /*****************************************************************/
611 /** \name Screen handling functions */
612 /*****************************************************************/
613 /*@{*/
614
615 /**
616 * Destroy the per-screen private information.
617 *
618 * \internal
619 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
620 * drmClose(), and finally frees \p screenPrivate.
621 */
622 static void driDestroyScreen(__DRIscreen *psp)
623 {
624 if (psp) {
625 /* No interaction with the X-server is possible at this point. This
626 * routine is called after XCloseDisplay, so there is no protocol
627 * stream open to the X-server anymore.
628 */
629
630 if (psp->DriverAPI.DestroyScreen)
631 (*psp->DriverAPI.DestroyScreen)(psp);
632
633 if (!psp->dri2.enabled) {
634 (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
635 (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
636 (void)drmCloseOnce(psp->fd);
637 }
638
639 free(psp);
640 }
641 }
642
643 static void
644 setupLoaderExtensions(__DRIscreen *psp,
645 const __DRIextension **extensions)
646 {
647 int i;
648
649 for (i = 0; extensions[i]; i++) {
650 if (strcmp(extensions[i]->name, __DRI_GET_DRAWABLE_INFO) == 0)
651 psp->getDrawableInfo = (__DRIgetDrawableInfoExtension *) extensions[i];
652 if (strcmp(extensions[i]->name, __DRI_DAMAGE) == 0)
653 psp->damage = (__DRIdamageExtension *) extensions[i];
654 if (strcmp(extensions[i]->name, __DRI_SYSTEM_TIME) == 0)
655 psp->systemTime = (__DRIsystemTimeExtension *) extensions[i];
656 if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0)
657 psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i];
658 if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0)
659 psp->dri2.image = (__DRIimageLookupExtension *) extensions[i];
660 }
661 }
662
663 /**
664 * This is the bootstrap function for the driver. libGL supplies all of the
665 * requisite information about the system, and the driver initializes itself.
666 * This routine also fills in the linked list pointed to by \c driver_modes
667 * with the \c __GLcontextModes that the driver can support for windows or
668 * pbuffers.
669 *
670 * For legacy DRI.
671 *
672 * \param scrn Index of the screen
673 * \param ddx_version Version of the 2D DDX. This may not be meaningful for
674 * all drivers.
675 * \param dri_version Version of the "server-side" DRI.
676 * \param drm_version Version of the kernel DRM.
677 * \param frame_buffer Data describing the location and layout of the
678 * framebuffer.
679 * \param pSAREA Pointer to the SAREA.
680 * \param fd Device handle for the DRM.
681 * \param extensions ??
682 * \param driver_modes Returns modes suppoted by the driver
683 * \param loaderPrivate ??
684 *
685 * \note There is no need to check the minimum API version in this
686 * function. Since the name of this function is versioned, it is
687 * impossible for a loader that is too old to even load this driver.
688 */
689 static __DRIscreen *
690 driCreateNewScreen(int scrn,
691 const __DRIversion *ddx_version,
692 const __DRIversion *dri_version,
693 const __DRIversion *drm_version,
694 const __DRIframebuffer *frame_buffer,
695 drmAddress pSAREA, int fd,
696 const __DRIextension **extensions,
697 const __DRIconfig ***driver_modes,
698 void *loaderPrivate)
699 {
700 static const __DRIextension *emptyExtensionList[] = { NULL };
701 __DRIscreen *psp;
702
703 psp = calloc(1, sizeof *psp);
704 if (!psp)
705 return NULL;
706
707 setupLoaderExtensions(psp, extensions);
708
709 /*
710 ** NOT_DONE: This is used by the X server to detect when the client
711 ** has died while holding the drawable lock. The client sets the
712 ** drawable lock to this value.
713 */
714 psp->drawLockID = 1;
715
716 psp->drm_version = *drm_version;
717 psp->ddx_version = *ddx_version;
718 psp->dri_version = *dri_version;
719
720 psp->pSAREA = pSAREA;
721 psp->lock = (drmLock *) &psp->pSAREA->lock;
722
723 psp->pFB = frame_buffer->base;
724 psp->fbSize = frame_buffer->size;
725 psp->fbStride = frame_buffer->stride;
726 psp->fbWidth = frame_buffer->width;
727 psp->fbHeight = frame_buffer->height;
728 psp->devPrivSize = frame_buffer->dev_priv_size;
729 psp->pDevPriv = frame_buffer->dev_priv;
730 psp->fbBPP = psp->fbStride * 8 / frame_buffer->width;
731
732 psp->extensions = emptyExtensionList;
733 psp->fd = fd;
734 psp->myNum = scrn;
735 psp->dri2.enabled = GL_FALSE;
736
737 /*
738 ** Do not init dummy context here; actual initialization will be
739 ** done when the first DRI context is created. Init screen priv ptr
740 ** to NULL to let CreateContext routine that it needs to be inited.
741 */
742 psp->dummyContextPriv.driScreenPriv = NULL;
743
744 psp->DriverAPI = driDriverAPI;
745
746 *driver_modes = driDriverAPI.InitScreen(psp);
747 if (*driver_modes == NULL) {
748 free(psp);
749 return NULL;
750 }
751
752 return psp;
753 }
754
755 /**
756 * DRI2
757 */
758 static __DRIscreen *
759 dri2CreateNewScreen(int scrn, int fd,
760 const __DRIextension **extensions,
761 const __DRIconfig ***driver_configs, void *data)
762 {
763 static const __DRIextension *emptyExtensionList[] = { NULL };
764 __DRIscreen *psp;
765 drmVersionPtr version;
766
767 if (driDriverAPI.InitScreen2 == NULL)
768 return NULL;
769
770 psp = calloc(1, sizeof(*psp));
771 if (!psp)
772 return NULL;
773
774 setupLoaderExtensions(psp, extensions);
775
776 version = drmGetVersion(fd);
777 if (version) {
778 psp->drm_version.major = version->version_major;
779 psp->drm_version.minor = version->version_minor;
780 psp->drm_version.patch = version->version_patchlevel;
781 drmFreeVersion(version);
782 }
783
784 psp->extensions = emptyExtensionList;
785 psp->fd = fd;
786 psp->myNum = scrn;
787 psp->dri2.enabled = GL_TRUE;
788
789 psp->DriverAPI = driDriverAPI;
790 *driver_configs = driDriverAPI.InitScreen2(psp);
791 if (*driver_configs == NULL) {
792 free(psp);
793 return NULL;
794 }
795
796 psp->DriverAPI = driDriverAPI;
797
798 return psp;
799 }
800
801 static const __DRIextension **driGetExtensions(__DRIscreen *psp)
802 {
803 return psp->extensions;
804 }
805
806 /** Core interface */
807 const __DRIcoreExtension driCoreExtension = {
808 { __DRI_CORE, __DRI_CORE_VERSION },
809 NULL,
810 driDestroyScreen,
811 driGetExtensions,
812 driGetConfigAttrib,
813 driIndexConfigAttrib,
814 NULL,
815 driDestroyDrawable,
816 driSwapBuffers,
817 NULL,
818 driCopyContext,
819 driDestroyContext,
820 driBindContext,
821 driUnbindContext
822 };
823
824 /** Legacy DRI interface */
825 const __DRIlegacyExtension driLegacyExtension = {
826 { __DRI_LEGACY, __DRI_LEGACY_VERSION },
827 driCreateNewScreen,
828 driCreateNewDrawable,
829 driCreateNewContext,
830 };
831
832 /** DRI2 interface */
833 const __DRIdri2Extension driDRI2Extension = {
834 { __DRI_DRI2, __DRI_DRI2_VERSION },
835 dri2CreateNewScreen,
836 dri2CreateNewDrawable,
837 dri2CreateNewContext,
838 };
839
840 static int
841 driFrameTracking(__DRIdrawable *drawable, GLboolean enable)
842 {
843 return GLX_BAD_CONTEXT;
844 }
845
846 static int
847 driQueryFrameTracking(__DRIdrawable *dpriv,
848 int64_t * sbc, int64_t * missedFrames,
849 float * lastMissedUsage, float * usage)
850 {
851 __DRIswapInfo sInfo;
852 int status;
853 int64_t ust;
854 __DRIscreen *psp = dpriv->driScreenPriv;
855
856 status = dpriv->driScreenPriv->DriverAPI.GetSwapInfo( dpriv, & sInfo );
857 if ( status == 0 ) {
858 *sbc = sInfo.swap_count;
859 *missedFrames = sInfo.swap_missed_count;
860 *lastMissedUsage = sInfo.swap_missed_usage;
861
862 (*psp->systemTime->getUST)( & ust );
863 *usage = driCalculateSwapUsage( dpriv, sInfo.swap_ust, ust );
864 }
865
866 return status;
867 }
868
869 const __DRIframeTrackingExtension driFrameTrackingExtension = {
870 { __DRI_FRAME_TRACKING, __DRI_FRAME_TRACKING_VERSION },
871 driFrameTracking,
872 driQueryFrameTracking
873 };
874
875 /**
876 * Calculate amount of swap interval used between GLX buffer swaps.
877 *
878 * The usage value, on the range [0,max], is the fraction of total swap
879 * interval time used between GLX buffer swaps is calculated.
880 *
881 * \f$p = t_d / (i * t_r)\f$
882 *
883 * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
884 * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
885 * required for a single vertical refresh period (as returned by \c
886 * glXGetMscRateOML).
887 *
888 * See the documentation for the GLX_MESA_swap_frame_usage extension for more
889 * details.
890 *
891 * \param dPriv Pointer to the private drawable structure.
892 * \return If less than a single swap interval time period was required
893 * between GLX buffer swaps, a number greater than 0 and less than
894 * 1.0 is returned. If exactly one swap interval time period is
895 * required, 1.0 is returned, and if more than one is required then
896 * a number greater than 1.0 will be returned.
897 *
898 * \sa glXSwapIntervalSGI glXGetMscRateOML
899 *
900 * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
901 * be possible to cache the sync rate?
902 */
903 float
904 driCalculateSwapUsage( __DRIdrawable *dPriv, int64_t last_swap_ust,
905 int64_t current_ust )
906 {
907 int32_t n;
908 int32_t d;
909 int interval;
910 float usage = 1.0;
911 __DRIscreen *psp = dPriv->driScreenPriv;
912
913 if ( (*psp->systemTime->getMSCRate)(dPriv, &n, &d, dPriv->loaderPrivate) ) {
914 interval = (dPriv->swap_interval != 0) ? dPriv->swap_interval : 1;
915
916
917 /* We want to calculate
918 * (current_UST - last_swap_UST) / (interval * us_per_refresh). We get
919 * current_UST by calling __glXGetUST. last_swap_UST is stored in
920 * dPriv->swap_ust. interval has already been calculated.
921 *
922 * The only tricky part is us_per_refresh. us_per_refresh is
923 * 1000000 / MSC_rate. We know the MSC_rate is n / d. We can flip it
924 * around and say us_per_refresh = 1000000 * d / n. Since this goes in
925 * the denominator of the final calculation, we calculate
926 * (interval * 1000000 * d) and move n into the numerator.
927 */
928
929 usage = (current_ust - last_swap_ust);
930 usage *= n;
931 usage /= (interval * d);
932 usage /= 1000000.0;
933 }
934
935 return usage;
936 }
937
938 void
939 dri2InvalidateDrawable(__DRIdrawable *drawable)
940 {
941 drawable->dri2.stamp++;
942 }
943
944 /*@}*/