2 * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * DRI utility functions.
30 * This module acts as glue between GLX and the actual hardware driver. A DRI
31 * driver doesn't really \e have to use any of this - it's optional. But, some
32 * useful stuff is done here that otherwise would have to be duplicated in most
35 * Basically, these utility functions take care of some of the dirty details of
36 * screen initialization, context creation, context binding, DRM setup, etc.
38 * These functions are compiled into each DRI driver so libGL.so knows nothing
50 #define MAP_FAILED ((void *)-1)
57 #include "drm_sarea.h"
60 #ifndef GLX_OML_sync_control
61 typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC
) (__DRIdrawable
*drawable
, int32_t *numerator
, int32_t *denominator
);
65 * This is just a token extension used to signal that the driver
66 * supports setting a read drawable.
68 const __DRIextension driReadDrawableExtension
= {
69 __DRI_READ_DRAWABLE
, __DRI_READ_DRAWABLE_VERSION
73 * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
76 * Is called from the drivers.
78 * \param f \c printf like format string.
81 __driUtilMessage(const char *f
, ...)
85 if (getenv("LIBGL_DEBUG")) {
86 fprintf(stderr
, "libGL error: \n");
88 vfprintf(stderr
, f
, args
);
90 fprintf(stderr
, "\n");
95 driIntersectArea( drm_clip_rect_t rect1
, drm_clip_rect_t rect2
)
97 if (rect2
.x1
> rect1
.x1
) rect1
.x1
= rect2
.x1
;
98 if (rect2
.x2
< rect1
.x2
) rect1
.x2
= rect2
.x2
;
99 if (rect2
.y1
> rect1
.y1
) rect1
.y1
= rect2
.y1
;
100 if (rect2
.y2
< rect1
.y2
) rect1
.y2
= rect2
.y2
;
102 if (rect1
.x1
> rect1
.x2
|| rect1
.y1
> rect1
.y2
) return 0;
104 return (rect1
.x2
- rect1
.x1
) * (rect1
.y2
- rect1
.y1
);
107 static __DRIdrawable
*__driFindDrawable(void *drawHash
, __DRIid draw
)
110 __DRIdrawable
*pdraw
;
112 retcode
= drmHashLookup(drawHash
, draw
, (void *)&pdraw
);
121 * Find drawables in the local hash that have been destroyed on the
124 * \param drawHash Hash-table containing all known drawables.
126 static void __driGarbageCollectDrawables(void *drawHash
)
129 __DRInativeDisplay
*dpy
;
130 __DRIdrawable
*pdraw
;
132 if (drmHashFirst(drawHash
, &draw
, (void *)&pdraw
) == 1) {
134 __DRIdrawablePrivate
*pdp
= (__DRIdrawablePrivate
*)pdraw
->private;
135 dpy
= pdp
->driScreenPriv
->display
;
136 if (! (*dri_interface
->windowExists
)(dpy
, draw
)) {
137 /* Destroy the local drawable data, if the drawable no
138 longer exists in the Xserver */
139 (*pdraw
->destroyDrawable
)(dpy
, pdraw
->private);
142 } while (drmHashNext(drawHash
, &draw
, (void *)&pdraw
) == 1);
146 /*****************************************************************/
147 /** \name Context (un)binding functions */
148 /*****************************************************************/
154 * \param scrn the screen.
157 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
160 * This function calls __DriverAPIRec::UnbindContext, and then decrements
161 * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
164 * While casting the opaque private pointers associated with the parameters
165 * into their respective real types it also assures they are not \c NULL.
167 static int driUnbindContext(__DRIcontext
*pcp
)
174 ** Assume error checking is done properly in glXMakeCurrent before
175 ** calling driUnbindContext.
181 psp
= pcp
->driScreenPriv
;
182 pdp
= pcp
->driDrawablePriv
;
183 prp
= pcp
->driReadablePriv
;
185 /* Let driver unbind drawable from context */
186 (*psp
->DriverAPI
.UnbindContext
)(pcp
);
188 if (pdp
->refcount
== 0) {
196 if (prp
->refcount
== 0) {
204 /* destroy the drawables if they no longer exist on the server */
205 if ((pdp
->refcount
== 0) || (prp
->refcount
== 0)) {
206 /* probably shouldn't need the collector here,
207 as we know the affected drawables (or could there be others?) */
208 __driGarbageCollectDrawables(pdp
->driScreenPriv
->drawHash
);
211 /* XXX this is disabled so that if we call SwapBuffers on an unbound
212 * window we can determine the last context bound to the window and
213 * use that context's lock. (BrianP, 2-Dec-2000)
216 /* Unbind the drawable */
217 pcp
->driDrawablePriv
= NULL
;
218 pdp
->driContextPriv
= &psp
->dummyContextPriv
;
226 * This function takes both a read buffer and a draw buffer. This is needed
227 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
230 static int driBindContext(__DRIcontext
*pcp
,
234 __DRIscreenPrivate
*psp
= pcp
->driScreenPriv
;
237 ** Assume error checking is done properly in glXMakeCurrent before
238 ** calling driBindContext.
241 if (pcp
== NULL
|| pdp
== None
|| prp
== None
)
244 /* Bind the drawable to the context */
245 pcp
->driDrawablePriv
= pdp
;
246 pcp
->driReadablePriv
= prp
;
247 pdp
->driContextPriv
= pcp
;
254 ** Now that we have a context associated with this drawable, we can
255 ** initialize the drawable information if has not been done before.
258 if (psp
->dri2
.enabled
) {
259 __driParseEvents(pcp
, pdp
);
260 __driParseEvents(pcp
, prp
);
262 if (!pdp
->pStamp
|| *pdp
->pStamp
!= pdp
->lastStamp
) {
263 DRM_SPINLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
264 __driUtilUpdateDrawableInfo(pdp
);
265 DRM_SPINUNLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
268 if ((pdp
!= prp
) && (!prp
->pStamp
|| *prp
->pStamp
!= prp
->lastStamp
)) {
269 DRM_SPINLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
270 __driUtilUpdateDrawableInfo(prp
);
271 DRM_SPINUNLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
275 /* Call device-specific MakeCurrent */
276 (*psp
->DriverAPI
.MakeCurrent
)(pcp
, pdp
, prp
);
284 /*****************************************************************/
285 /** \name Drawable handling functions */
286 /*****************************************************************/
290 * Update private drawable information.
292 * \param pdp pointer to the private drawable information to update.
294 * This function basically updates the __DRIdrawablePrivate struct's
295 * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo.
296 * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
297 * compares the __DRIdrwablePrivate pStamp and lastStamp values. If
298 * the values are different that means we have to update the clipping
302 __driUtilUpdateDrawableInfo(__DRIdrawablePrivate
*pdp
)
304 __DRIscreenPrivate
*psp
= pdp
->driScreenPriv
;
305 __DRIcontextPrivate
*pcp
= pdp
->driContextPriv
;
308 || ((pdp
!= pcp
->driDrawablePriv
) && (pdp
!= pcp
->driReadablePriv
))) {
310 * ...but we must ignore it. There can be many contexts bound to a
315 if (pdp
->pClipRects
) {
316 _mesa_free(pdp
->pClipRects
);
317 pdp
->pClipRects
= NULL
;
320 if (pdp
->pBackClipRects
) {
321 _mesa_free(pdp
->pBackClipRects
);
322 pdp
->pBackClipRects
= NULL
;
325 DRM_SPINUNLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
327 if (! (*psp
->getDrawableInfo
->getDrawableInfo
)(pdp
,
328 &pdp
->index
, &pdp
->lastStamp
,
329 &pdp
->x
, &pdp
->y
, &pdp
->w
, &pdp
->h
,
330 &pdp
->numClipRects
, &pdp
->pClipRects
,
333 &pdp
->numBackClipRects
,
334 &pdp
->pBackClipRects
,
335 pdp
->loaderPrivate
)) {
336 /* Error -- eg the window may have been destroyed. Keep going
339 pdp
->pStamp
= &pdp
->lastStamp
; /* prevent endless loop */
340 pdp
->numClipRects
= 0;
341 pdp
->pClipRects
= NULL
;
342 pdp
->numBackClipRects
= 0;
343 pdp
->pBackClipRects
= NULL
;
346 pdp
->pStamp
= &(psp
->pSAREA
->drawableTable
[pdp
->index
].stamp
);
348 DRM_SPINLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
353 __driParseEvents(__DRIcontextPrivate
*pcp
, __DRIdrawablePrivate
*pdp
)
355 __DRIscreenPrivate
*psp
= pdp
->driScreenPriv
;
356 __DRIDrawableConfigEvent
*dc
, *last_dc
;
357 __DRIBufferAttachEvent
*ba
, *last_ba
;
358 unsigned int tail
, mask
, *p
, end
, total
, size
, changed
;
362 /* Check for wraparound. */
363 if (pcp
&& psp
->dri2
.buffer
->prealloc
- pdp
->dri2
.tail
> psp
->dri2
.buffer
->size
) {
364 /* If prealloc overlaps into what we just parsed, the
365 * server overwrote it and we have to reset our tail
367 DRM_UNLOCK(psp
->fd
, psp
->lock
, pcp
->hHWContext
);
368 (*psp
->dri2
.loader
->reemitDrawableInfo
)(pdp
, &pdp
->dri2
.tail
,
370 DRM_LIGHT_LOCK(psp
->fd
, psp
->lock
, pcp
->hHWContext
);
373 total
= psp
->dri2
.buffer
->head
- pdp
->dri2
.tail
;
374 mask
= psp
->dri2
.buffer
->size
- 1;
375 end
= psp
->dri2
.buffer
->head
;
376 data
= psp
->dri2
.buffer
->data
;
382 for (tail
= pdp
->dri2
.tail
; tail
!= end
; tail
+= size
) {
383 p
= (unsigned int *) (data
+ (tail
& mask
));
384 size
= DRI2_EVENT_SIZE(*p
);
385 if (size
> total
|| (tail
& mask
) + size
> psp
->dri2
.buffer
->size
) {
386 /* illegal data, bail out. */
387 fprintf(stderr
, "illegal event size\n");
391 switch (DRI2_EVENT_TYPE(*p
)) {
392 case DRI2_EVENT_DRAWABLE_CONFIG
:
393 dc
= (__DRIDrawableConfigEvent
*) p
;
394 if (dc
->drawable
== pdp
->dri2
.drawable_id
)
398 case DRI2_EVENT_BUFFER_ATTACH
:
399 ba
= (__DRIBufferAttachEvent
*) p
;
400 if (ba
->drawable
== pdp
->dri2
.drawable_id
&&
401 ba
->buffer
.attachment
== DRI_DRAWABLE_BUFFER_FRONT_LEFT
)
408 if (pdp
->w
!= last_dc
->width
|| pdp
->h
!= last_dc
->height
)
413 pdp
->w
= last_dc
->width
;
414 pdp
->h
= last_dc
->height
;
418 pdp
->numBackClipRects
= 1;
419 pdp
->pBackClipRects
[0].x1
= 0;
420 pdp
->pBackClipRects
[0].y1
= 0;
421 pdp
->pBackClipRects
[0].x2
= pdp
->w
;
422 pdp
->pBackClipRects
[0].y2
= pdp
->h
;
424 pdp
->numClipRects
= last_dc
->num_rects
;
425 _mesa_free(pdp
->pClipRects
);
426 rect_size
= last_dc
->num_rects
* sizeof last_dc
->rects
[0];
427 pdp
->pClipRects
= _mesa_malloc(rect_size
);
428 memcpy(pdp
->pClipRects
, last_dc
->rects
, rect_size
);
431 /* We only care about the most recent drawable config. */
432 if (last_dc
&& changed
)
433 (*psp
->DriverAPI
.HandleDrawableConfig
)(pdp
, pcp
, last_dc
);
435 /* Front buffer attachments are special, they typically mean that
436 * we're rendering to a redirected window (or a child window of a
437 * redirected window) and that it got resized. Resizing the root
438 * window on randr events is a special case of this. Other causes
439 * may be a window transitioning between redirected and
440 * non-redirected, or a window getting reparented between parents
441 * with different window pixmaps (eg two redirected windows).
442 * These events are special in that the X server allocates the
443 * buffer and that the buffer may be shared by other child
444 * windows. When our window share the window pixmap with its
445 * parent, drawable config events doesn't affect the front buffer.
446 * We only care about the last such event in the buffer; in fact,
447 * older events will refer to invalid buffer objects.*/
449 (*psp
->DriverAPI
.HandleBufferAttach
)(pdp
, pcp
, last_ba
);
451 /* If there was a drawable config event in the buffer and it
452 * changed the size of the window, all buffer auxillary buffer
453 * attachments prior to that are invalid (as opposed to the front
454 * buffer case discussed above). In that case we can start
455 * looking for buffer attachment after the last drawable config
456 * event. If there is no drawable config event in this batch of
457 * events, we have to assume that the last batch might have had
458 * one and process all buffer attach events.*/
459 if (last_dc
&& changed
)
460 tail
= (unsigned char *) last_dc
- data
;
462 tail
= pdp
->dri2
.tail
;
464 for ( ; tail
!= end
; tail
+= size
) {
465 ba
= (__DRIBufferAttachEvent
*) (data
+ (tail
& mask
));
466 size
= DRI2_EVENT_SIZE(ba
->event_header
);
468 if (DRI2_EVENT_TYPE(ba
->event_header
) != DRI2_EVENT_BUFFER_ATTACH
)
470 if (ba
->drawable
!= pdp
->dri2
.drawable_id
)
475 (*psp
->DriverAPI
.HandleBufferAttach
)(pdp
, pcp
, ba
);
479 pdp
->dri2
.tail
= tail
;
481 return changed
|| last_ba
;
486 /*****************************************************************/
487 /** \name GLX callbacks */
488 /*****************************************************************/
491 static void driReportDamage(__DRIdrawable
*pdp
,
492 struct drm_clip_rect
*pClipRects
, int numClipRects
)
494 __DRIscreen
*psp
= pdp
->driScreenPriv
;
496 /* Check that we actually have the new damage report method */
497 if (psp
->dri2
.enabled
) {
498 (*psp
->dri2
.loader
->postDamage
)(pdp
,
502 } else if (psp
->damage
) {
503 /* Report the damage. Currently, all our drivers draw
504 * directly to the front buffer, so we report the damage there
505 * rather than to the backing storein (if any).
507 (*psp
->damage
->reportDamage
)(pdp
,
509 pClipRects
, numClipRects
,
510 GL_TRUE
, pdp
->loaderPrivate
);
518 * \param drawablePrivate opaque pointer to the per-drawable private info.
521 * This function calls __DRIdrawablePrivate::swapBuffers.
523 * Is called directly from glXSwapBuffers().
525 static void driSwapBuffers(__DRIdrawable
*dPriv
)
527 __DRIscreen
*psp
= dPriv
->driScreenPriv
;
529 if (!dPriv
->numClipRects
)
532 if (psp
->dri2
.enabled
)
533 __driParseEvents(NULL
, dPriv
);
535 psp
->DriverAPI
.SwapBuffers(dPriv
);
537 driReportDamage(dPriv
, dPriv
->pClipRects
, dPriv
->numClipRects
);
540 static int driDrawableGetMSC( __DRIscreen
*sPriv
, __DRIdrawable
*dPriv
,
543 return sPriv
->DriverAPI
.GetDrawableMSC(sPriv
, dPriv
, msc
);
547 static int driWaitForMSC(__DRIdrawable
*dPriv
, int64_t target_msc
,
548 int64_t divisor
, int64_t remainder
,
549 int64_t * msc
, int64_t * sbc
)
554 status
= dPriv
->driScreenPriv
->DriverAPI
.WaitForMSC( dPriv
, target_msc
,
558 /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
559 * is supported but GLX_OML_sync_control is not. Therefore, don't return
560 * an error value if GetSwapInfo() is not implemented.
563 && dPriv
->driScreenPriv
->DriverAPI
.GetSwapInfo
) {
564 status
= dPriv
->driScreenPriv
->DriverAPI
.GetSwapInfo( dPriv
, & sInfo
);
565 *sbc
= sInfo
.swap_count
;
572 const __DRImediaStreamCounterExtension driMediaStreamCounterExtension
= {
573 { __DRI_MEDIA_STREAM_COUNTER
, __DRI_MEDIA_STREAM_COUNTER_VERSION
},
579 static void driCopySubBuffer(__DRIdrawable
*dPriv
,
580 int x
, int y
, int w
, int h
)
582 drm_clip_rect_t rect
;
585 rect
.y1
= dPriv
->h
- y
- h
;
587 rect
.y2
= rect
.y1
+ h
;
588 driReportDamage(dPriv
, &rect
, 1);
590 dPriv
->driScreenPriv
->DriverAPI
.CopySubBuffer(dPriv
, x
, y
, w
, h
);
593 const __DRIcopySubBufferExtension driCopySubBufferExtension
= {
594 { __DRI_COPY_SUB_BUFFER
, __DRI_COPY_SUB_BUFFER_VERSION
},
598 static void driSetSwapInterval(__DRIdrawable
*dPriv
, unsigned int interval
)
600 dPriv
->swap_interval
= interval
;
603 static unsigned int driGetSwapInterval(__DRIdrawable
*dPriv
)
605 return dPriv
->swap_interval
;
608 const __DRIswapControlExtension driSwapControlExtension
= {
609 { __DRI_SWAP_CONTROL
, __DRI_SWAP_CONTROL_VERSION
},
616 * This is called via __DRIscreenRec's createNewDrawable pointer.
618 static __DRIdrawable
*
619 driCreateNewDrawable(__DRIscreen
*psp
, const __DRIconfig
*config
,
620 drm_drawable_t hwDrawable
, int renderType
,
621 const int *attrs
, void *data
)
625 /* Since pbuffers are not yet supported, no drawable attributes are
630 pdp
= _mesa_malloc(sizeof *pdp
);
635 pdp
->loaderPrivate
= data
;
636 pdp
->hHWDrawable
= hwDrawable
;
645 pdp
->numClipRects
= 0;
646 pdp
->numBackClipRects
= 0;
647 pdp
->pClipRects
= NULL
;
648 pdp
->pBackClipRects
= NULL
;
652 pdp
->driScreenPriv
= psp
;
653 pdp
->driContextPriv
= &psp
->dummyContextPriv
;
655 if (!(*psp
->DriverAPI
.CreateBuffer
)(psp
, pdp
, &config
->modes
,
656 renderType
== GLX_PIXMAP_BIT
)) {
663 /* This special default value is replaced with the configured
664 * default value when the drawable is first bound to a direct
667 pdp
->swap_interval
= (unsigned)-1;
673 static __DRIdrawable
*
674 dri2CreateNewDrawable(__DRIscreen
*screen
, const __DRIconfig
*config
,
675 unsigned int drawable_id
, unsigned int head
, void *data
)
677 __DRIdrawable
*pdraw
;
679 pdraw
= driCreateNewDrawable(screen
, config
, 0, 0, NULL
, data
);
683 pdraw
->dri2
.drawable_id
= drawable_id
;
684 pdraw
->dri2
.tail
= head
;
685 pdraw
->pBackClipRects
= _mesa_malloc(sizeof *pdraw
->pBackClipRects
);
692 driDestroyDrawable(__DRIdrawable
*pdp
)
694 __DRIscreenPrivate
*psp
;
697 psp
= pdp
->driScreenPriv
;
698 (*psp
->DriverAPI
.DestroyBuffer
)(pdp
);
699 if (pdp
->pClipRects
) {
700 _mesa_free(pdp
->pClipRects
);
701 pdp
->pClipRects
= NULL
;
703 if (pdp
->pBackClipRects
) {
704 _mesa_free(pdp
->pBackClipRects
);
705 pdp
->pBackClipRects
= NULL
;
714 /*****************************************************************/
715 /** \name Context handling functions */
716 /*****************************************************************/
720 * Destroy the per-context private information.
723 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
724 * drmDestroyContext(), and finally frees \p contextPrivate.
727 driDestroyContext(__DRIcontext
*pcp
)
730 (*pcp
->driScreenPriv
->DriverAPI
.DestroyContext
)(pcp
);
737 * Create the per-drawable private driver information.
739 * \param render_type Type of rendering target. \c GLX_RGBA is the only
740 * type likely to ever be supported for direct-rendering.
741 * \param shared Context with which to share textures, etc. or NULL
743 * \returns An opaque pointer to the per-context private information on
744 * success, or \c NULL on failure.
747 * This function allocates and fills a __DRIcontextPrivateRec structure. It
748 * performs some device independent initialization and passes all the
749 * relevent information to __DriverAPIRec::CreateContext to create the
753 static __DRIcontext
*
754 driCreateNewContext(__DRIscreen
*psp
, const __DRIconfig
*config
,
755 int render_type
, __DRIcontext
*shared
,
756 drm_context_t hwContext
, void *data
)
759 void * const shareCtx
= (shared
!= NULL
) ? shared
->driverPrivate
: NULL
;
761 pcp
= _mesa_malloc(sizeof *pcp
);
765 pcp
->driScreenPriv
= psp
;
766 pcp
->driDrawablePriv
= NULL
;
768 /* When the first context is created for a screen, initialize a "dummy"
772 if (!psp
->dri2
.enabled
&& !psp
->dummyContextPriv
.driScreenPriv
) {
773 psp
->dummyContextPriv
.hHWContext
= psp
->pSAREA
->dummy_context
;
774 psp
->dummyContextPriv
.driScreenPriv
= psp
;
775 psp
->dummyContextPriv
.driDrawablePriv
= NULL
;
776 psp
->dummyContextPriv
.driverPrivate
= NULL
;
777 /* No other fields should be used! */
780 pcp
->hHWContext
= hwContext
;
782 if ( !(*psp
->DriverAPI
.CreateContext
)(&config
->modes
, pcp
, shareCtx
) ) {
791 static __DRIcontext
*
792 dri2CreateNewContext(__DRIscreen
*screen
, const __DRIconfig
*config
,
793 __DRIcontext
*shared
, void *data
)
795 drm_context_t hwContext
;
798 /* DRI2 doesn't use kernel with context IDs, we just need an ID that's
799 * different from the kernel context ID to make drmLock() happy. */
802 hwContext
= screen
->dri2
.lock
->next_id
;
803 DRM_CAS(&screen
->dri2
.lock
->next_id
, hwContext
, hwContext
+ 1, ret
);
806 return driCreateNewContext(screen
, config
, 0, shared
, hwContext
, data
);
811 driCopyContext(__DRIcontext
*dest
, __DRIcontext
*src
, unsigned long mask
)
819 /*****************************************************************/
820 /** \name Screen handling functions */
821 /*****************************************************************/
825 * Destroy the per-screen private information.
828 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
829 * drmClose(), and finally frees \p screenPrivate.
831 static void driDestroyScreen(__DRIscreen
*psp
)
834 /* No interaction with the X-server is possible at this point. This
835 * routine is called after XCloseDisplay, so there is no protocol
836 * stream open to the X-server anymore.
839 if (psp
->DriverAPI
.DestroyScreen
)
840 (*psp
->DriverAPI
.DestroyScreen
)(psp
);
842 if (psp
->dri2
.enabled
) {
844 drmBOUnmap(psp
->fd
, &psp
->dri2
.sareaBO
);
845 drmBOUnreference(psp
->fd
, &psp
->dri2
.sareaBO
);
848 (void)drmUnmap((drmAddress
)psp
->pSAREA
, SAREA_MAX
);
849 (void)drmUnmap((drmAddress
)psp
->pFB
, psp
->fbSize
);
850 (void)drmCloseOnce(psp
->fd
);
858 setupLoaderExtensions(__DRIscreen
*psp
,
859 const __DRIextension
**extensions
)
863 for (i
= 0; extensions
[i
]; i
++) {
864 if (strcmp(extensions
[i
]->name
, __DRI_GET_DRAWABLE_INFO
) == 0)
865 psp
->getDrawableInfo
= (__DRIgetDrawableInfoExtension
*) extensions
[i
];
866 if (strcmp(extensions
[i
]->name
, __DRI_DAMAGE
) == 0)
867 psp
->damage
= (__DRIdamageExtension
*) extensions
[i
];
868 if (strcmp(extensions
[i
]->name
, __DRI_SYSTEM_TIME
) == 0)
869 psp
->systemTime
= (__DRIsystemTimeExtension
*) extensions
[i
];
870 if (strcmp(extensions
[i
]->name
, __DRI_LOADER
) == 0)
871 psp
->dri2
.loader
= (__DRIloaderExtension
*) extensions
[i
];
876 * This is the bootstrap function for the driver. libGL supplies all of the
877 * requisite information about the system, and the driver initializes itself.
878 * This routine also fills in the linked list pointed to by \c driver_modes
879 * with the \c __GLcontextModes that the driver can support for windows or
884 * \param scrn Index of the screen
885 * \param ddx_version Version of the 2D DDX. This may not be meaningful for
887 * \param dri_version Version of the "server-side" DRI.
888 * \param drm_version Version of the kernel DRM.
889 * \param frame_buffer Data describing the location and layout of the
891 * \param pSAREA Pointer the the SAREA.
892 * \param fd Device handle for the DRM.
893 * \param extensions ??
894 * \param driver_modes Returns modes suppoted by the driver
895 * \param loaderPrivate ??
897 * \note There is no need to check the minimum API version in this
898 * function. Since the name of this function is versioned, it is
899 * impossible for a loader that is too old to even load this driver.
902 driCreateNewScreen(int scrn
,
903 const __DRIversion
*ddx_version
,
904 const __DRIversion
*dri_version
,
905 const __DRIversion
*drm_version
,
906 const __DRIframebuffer
*frame_buffer
,
907 drmAddress pSAREA
, int fd
,
908 const __DRIextension
**extensions
,
909 const __DRIconfig
***driver_modes
,
912 static const __DRIextension
*emptyExtensionList
[] = { NULL
};
915 psp
= _mesa_malloc(sizeof *psp
);
919 setupLoaderExtensions(psp
, extensions
);
922 ** NOT_DONE: This is used by the X server to detect when the client
923 ** has died while holding the drawable lock. The client sets the
924 ** drawable lock to this value.
928 psp
->drm_version
= *drm_version
;
929 psp
->ddx_version
= *ddx_version
;
930 psp
->dri_version
= *dri_version
;
932 psp
->pSAREA
= pSAREA
;
933 psp
->lock
= (drmLock
*) &psp
->pSAREA
->lock
;
935 psp
->pFB
= frame_buffer
->base
;
936 psp
->fbSize
= frame_buffer
->size
;
937 psp
->fbStride
= frame_buffer
->stride
;
938 psp
->fbWidth
= frame_buffer
->width
;
939 psp
->fbHeight
= frame_buffer
->height
;
940 psp
->devPrivSize
= frame_buffer
->dev_priv_size
;
941 psp
->pDevPriv
= frame_buffer
->dev_priv
;
942 psp
->fbBPP
= psp
->fbStride
* 8 / frame_buffer
->width
;
944 psp
->extensions
= emptyExtensionList
;
947 psp
->dri2
.enabled
= GL_FALSE
;
950 ** Do not init dummy context here; actual initialization will be
951 ** done when the first DRI context is created. Init screen priv ptr
952 ** to NULL to let CreateContext routine that it needs to be inited.
954 psp
->dummyContextPriv
.driScreenPriv
= NULL
;
956 psp
->DriverAPI
= driDriverAPI
;
958 *driver_modes
= driDriverAPI
.InitScreen(psp
);
959 if (*driver_modes
== NULL
) {
972 dri2CreateNewScreen(int scrn
, int fd
, unsigned int sarea_handle
,
973 const __DRIextension
**extensions
,
974 const __DRIconfig
***driver_configs
, void *data
)
977 static const __DRIextension
*emptyExtensionList
[] = { NULL
};
980 drmVersionPtr version
;
982 if (driDriverAPI
.InitScreen2
== NULL
)
985 psp
= _mesa_malloc(sizeof(*psp
));
989 setupLoaderExtensions(psp
, extensions
);
991 version
= drmGetVersion(fd
);
993 psp
->drm_version
.major
= version
->version_major
;
994 psp
->drm_version
.minor
= version
->version_minor
;
995 psp
->drm_version
.patch
= version
->version_patchlevel
;
996 drmFreeVersion(version
);
999 psp
->extensions
= emptyExtensionList
;
1002 psp
->dri2
.enabled
= GL_TRUE
;
1004 if (drmBOReference(psp
->fd
, sarea_handle
, &psp
->dri2
.sareaBO
)) {
1005 fprintf(stderr
, "Failed to reference DRI2 sarea BO\n");
1010 if (drmBOMap(psp
->fd
, &psp
->dri2
.sareaBO
,
1011 DRM_BO_FLAG_READ
| DRM_BO_FLAG_WRITE
, 0, &psp
->dri2
.sarea
)) {
1012 drmBOUnreference(psp
->fd
, &psp
->dri2
.sareaBO
);
1017 p
= psp
->dri2
.sarea
;
1018 while (DRI2_SAREA_BLOCK_TYPE(*p
)) {
1019 switch (DRI2_SAREA_BLOCK_TYPE(*p
)) {
1020 case DRI2_SAREA_BLOCK_LOCK
:
1021 psp
->dri2
.lock
= (__DRILock
*) p
;
1023 case DRI2_SAREA_BLOCK_EVENT_BUFFER
:
1024 psp
->dri2
.buffer
= (__DRIEventBuffer
*) p
;
1027 p
= DRI2_SAREA_BLOCK_NEXT(p
);
1030 psp
->lock
= (drmLock
*) &psp
->dri2
.lock
->lock
;
1032 psp
->DriverAPI
= driDriverAPI
;
1033 *driver_configs
= driDriverAPI
.InitScreen2(psp
);
1034 if (*driver_configs
== NULL
) {
1035 drmBOUnmap(psp
->fd
, &psp
->dri2
.sareaBO
);
1036 drmBOUnreference(psp
->fd
, &psp
->dri2
.sareaBO
);
1041 psp
->DriverAPI
= driDriverAPI
;
1049 static const __DRIextension
**driGetExtensions(__DRIscreen
*psp
)
1051 return psp
->extensions
;
1054 /** Legacy DRI interface */
1055 const __DRIlegacyExtension driLegacyExtension
= {
1056 { __DRI_LEGACY
, __DRI_LEGACY_VERSION
},
1058 driCreateNewDrawable
,
1062 /** DRI2 interface */
1063 const __DRIcoreExtension driCoreExtension
= {
1064 { __DRI_CORE
, __DRI_CORE_VERSION
},
1065 dri2CreateNewScreen
,
1069 driIndexConfigAttrib
,
1070 dri2CreateNewDrawable
,
1073 dri2CreateNewContext
,
1080 /* This is the table of extensions that the loader will dlsym() for. */
1081 PUBLIC
const __DRIextension
*__driDriverExtensions
[] = {
1082 &driCoreExtension
.base
,
1083 &driLegacyExtension
.base
,
1088 driFrameTracking(__DRIdrawable
*drawable
, GLboolean enable
)
1090 return GLX_BAD_CONTEXT
;
1094 driQueryFrameTracking(__DRIdrawable
*dpriv
,
1095 int64_t * sbc
, int64_t * missedFrames
,
1096 float * lastMissedUsage
, float * usage
)
1098 __DRIswapInfo sInfo
;
1101 __DRIscreenPrivate
*psp
= dpriv
->driScreenPriv
;
1103 status
= dpriv
->driScreenPriv
->DriverAPI
.GetSwapInfo( dpriv
, & sInfo
);
1104 if ( status
== 0 ) {
1105 *sbc
= sInfo
.swap_count
;
1106 *missedFrames
= sInfo
.swap_missed_count
;
1107 *lastMissedUsage
= sInfo
.swap_missed_usage
;
1109 (*psp
->systemTime
->getUST
)( & ust
);
1110 *usage
= driCalculateSwapUsage( dpriv
, sInfo
.swap_ust
, ust
);
1116 const __DRIframeTrackingExtension driFrameTrackingExtension
= {
1117 { __DRI_FRAME_TRACKING
, __DRI_FRAME_TRACKING_VERSION
},
1119 driQueryFrameTracking
1123 * Calculate amount of swap interval used between GLX buffer swaps.
1125 * The usage value, on the range [0,max], is the fraction of total swap
1126 * interval time used between GLX buffer swaps is calculated.
1128 * \f$p = t_d / (i * t_r)\f$
1130 * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
1131 * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
1132 * required for a single vertical refresh period (as returned by \c
1133 * glXGetMscRateOML).
1135 * See the documentation for the GLX_MESA_swap_frame_usage extension for more
1138 * \param dPriv Pointer to the private drawable structure.
1139 * \return If less than a single swap interval time period was required
1140 * between GLX buffer swaps, a number greater than 0 and less than
1141 * 1.0 is returned. If exactly one swap interval time period is
1142 * required, 1.0 is returned, and if more than one is required then
1143 * a number greater than 1.0 will be returned.
1145 * \sa glXSwapIntervalSGI glXGetMscRateOML
1147 * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
1148 * be possible to cache the sync rate?
1151 driCalculateSwapUsage( __DRIdrawablePrivate
*dPriv
, int64_t last_swap_ust
,
1152 int64_t current_ust
)
1158 __DRIscreenPrivate
*psp
= dPriv
->driScreenPriv
;
1160 if ( (*psp
->systemTime
->getMSCRate
)(dPriv
, &n
, &d
, dPriv
->loaderPrivate
) ) {
1161 interval
= (dPriv
->swap_interval
!= 0) ? dPriv
->swap_interval
: 1;
1164 /* We want to calculate
1165 * (current_UST - last_swap_UST) / (interval * us_per_refresh). We get
1166 * current_UST by calling __glXGetUST. last_swap_UST is stored in
1167 * dPriv->swap_ust. interval has already been calculated.
1169 * The only tricky part is us_per_refresh. us_per_refresh is
1170 * 1000000 / MSC_rate. We know the MSC_rate is n / d. We can flip it
1171 * around and say us_per_refresh = 1000000 * d / n. Since this goes in
1172 * the denominator of the final calculation, we calculate
1173 * (interval * 1000000 * d) and move n into the numerator.
1176 usage
= (current_ust
- last_swap_ust
);
1178 usage
/= (interval
* d
);