Merge branch 'gallium-0.1' into gallium-0.2
[mesa.git] / src / mesa / drivers / dri / common / dri_util.c
1 /*
2 * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
3 * All Rights Reserved.
4 *
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:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
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.
24 */
25
26 /**
27 * \file dri_util.c
28 * DRI utility functions.
29 *
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
33 * drivers.
34 *
35 * Basically, these utility functions take care of some of the dirty details of
36 * screen initialization, context creation, context binding, DRM setup, etc.
37 *
38 * These functions are compiled into each DRI driver so libGL.so knows nothing
39 * about them.
40 */
41
42
43 #include <assert.h>
44 #include <stdarg.h>
45 #include <unistd.h>
46 #include <sys/mman.h>
47 #include <stdio.h>
48
49 #ifndef MAP_FAILED
50 #define MAP_FAILED ((void *)-1)
51 #endif
52
53 #include "imports.h"
54 #define None 0
55
56 #include "dri_util.h"
57 #include "drm_sarea.h"
58 #include "utils.h"
59
60 #ifndef GLX_OML_sync_control
61 typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator);
62 #endif
63
64 /**
65 * This is just a token extension used to signal that the driver
66 * supports setting a read drawable.
67 */
68 const __DRIextension driReadDrawableExtension = {
69 __DRI_READ_DRAWABLE, __DRI_READ_DRAWABLE_VERSION
70 };
71
72 /**
73 * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
74 * is set.
75 *
76 * Is called from the drivers.
77 *
78 * \param f \c printf like format string.
79 */
80 void
81 __driUtilMessage(const char *f, ...)
82 {
83 va_list args;
84
85 if (getenv("LIBGL_DEBUG")) {
86 fprintf(stderr, "libGL error: \n");
87 va_start(args, f);
88 vfprintf(stderr, f, args);
89 va_end(args);
90 fprintf(stderr, "\n");
91 }
92 }
93
94 GLint
95 driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 )
96 {
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;
101
102 if (rect1.x1 > rect1.x2 || rect1.y1 > rect1.y2) return 0;
103
104 return (rect1.x2 - rect1.x1) * (rect1.y2 - rect1.y1);
105 }
106
107 static __DRIdrawable *__driFindDrawable(void *drawHash, __DRIid draw)
108 {
109 int retcode;
110 __DRIdrawable *pdraw;
111
112 retcode = drmHashLookup(drawHash, draw, (void *)&pdraw);
113 if (retcode)
114 return NULL;
115
116 return pdraw;
117 }
118
119
120 /**
121 * Find drawables in the local hash that have been destroyed on the
122 * server.
123 *
124 * \param drawHash Hash-table containing all known drawables.
125 */
126 static void __driGarbageCollectDrawables(void *drawHash)
127 {
128 __DRIid draw;
129 __DRInativeDisplay *dpy;
130 __DRIdrawable *pdraw;
131
132 if (drmHashFirst(drawHash, &draw, (void *)&pdraw) == 1) {
133 do {
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);
140 _mesa_free(pdraw);
141 }
142 } while (drmHashNext(drawHash, &draw, (void *)&pdraw) == 1);
143 }
144 }
145
146 /*****************************************************************/
147 /** \name Context (un)binding functions */
148 /*****************************************************************/
149 /*@{*/
150
151 /**
152 * Unbind context.
153 *
154 * \param scrn the screen.
155 * \param gc context.
156 *
157 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
158 *
159 * \internal
160 * This function calls __DriverAPIRec::UnbindContext, and then decrements
161 * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
162 * return.
163 *
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.
166 */
167 static int driUnbindContext(__DRIcontext *pcp)
168 {
169 __DRIscreen *psp;
170 __DRIdrawable *pdp;
171 __DRIdrawable *prp;
172
173 /*
174 ** Assume error checking is done properly in glXMakeCurrent before
175 ** calling driUnbindContext.
176 */
177
178 if (pcp == NULL)
179 return GL_FALSE;
180
181 psp = pcp->driScreenPriv;
182 pdp = pcp->driDrawablePriv;
183 prp = pcp->driReadablePriv;
184
185 /* Let driver unbind drawable from context */
186 (*psp->DriverAPI.UnbindContext)(pcp);
187
188 if (pdp->refcount == 0) {
189 /* ERROR!!! */
190 return GL_FALSE;
191 }
192
193 pdp->refcount--;
194
195 if (prp != pdp) {
196 if (prp->refcount == 0) {
197 /* ERROR!!! */
198 return GL_FALSE;
199 }
200
201 prp->refcount--;
202 }
203
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);
209 }
210
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)
214 */
215 #if 0
216 /* Unbind the drawable */
217 pcp->driDrawablePriv = NULL;
218 pdp->driContextPriv = &psp->dummyContextPriv;
219 #endif
220
221 return GL_TRUE;
222 }
223
224
225 /**
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
228 * function.
229 */
230 static int driBindContext(__DRIcontext *pcp,
231 __DRIdrawable *pdp,
232 __DRIdrawable *prp)
233 {
234 __DRIscreenPrivate *psp = pcp->driScreenPriv;
235
236 /*
237 ** Assume error checking is done properly in glXMakeCurrent before
238 ** calling driBindContext.
239 */
240
241 if (pcp == NULL || pdp == None || prp == None)
242 return GL_FALSE;
243
244 /* Bind the drawable to the context */
245 pcp->driDrawablePriv = pdp;
246 pcp->driReadablePriv = prp;
247 pdp->driContextPriv = pcp;
248 pdp->refcount++;
249 if ( pdp != prp ) {
250 prp->refcount++;
251 }
252
253 /*
254 ** Now that we have a context associated with this drawable, we can
255 ** initialize the drawable information if has not been done before.
256 */
257
258 if (psp->dri2.enabled) {
259 __driParseEvents(pcp, pdp);
260 __driParseEvents(pcp, prp);
261 } else {
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);
266 }
267
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);
272 }
273 }
274
275 /* Call device-specific MakeCurrent */
276 (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
277
278 return GL_TRUE;
279 }
280
281 /*@}*/
282
283
284 /*****************************************************************/
285 /** \name Drawable handling functions */
286 /*****************************************************************/
287 /*@{*/
288
289 /**
290 * Update private drawable information.
291 *
292 * \param pdp pointer to the private drawable information to update.
293 *
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
299 * info.
300 */
301 void
302 __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
303 {
304 __DRIscreenPrivate *psp = pdp->driScreenPriv;
305 __DRIcontextPrivate *pcp = pdp->driContextPriv;
306
307 if (!pcp
308 || ((pdp != pcp->driDrawablePriv) && (pdp != pcp->driReadablePriv))) {
309 /* ERROR!!!
310 * ...but we must ignore it. There can be many contexts bound to a
311 * drawable.
312 */
313 }
314
315 if (pdp->pClipRects) {
316 _mesa_free(pdp->pClipRects);
317 pdp->pClipRects = NULL;
318 }
319
320 if (pdp->pBackClipRects) {
321 _mesa_free(pdp->pBackClipRects);
322 pdp->pBackClipRects = NULL;
323 }
324
325 DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
326
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,
331 &pdp->backX,
332 &pdp->backY,
333 &pdp->numBackClipRects,
334 &pdp->pBackClipRects,
335 pdp->loaderPrivate)) {
336 /* Error -- eg the window may have been destroyed. Keep going
337 * with no cliprects.
338 */
339 pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
340 pdp->numClipRects = 0;
341 pdp->pClipRects = NULL;
342 pdp->numBackClipRects = 0;
343 pdp->pBackClipRects = NULL;
344 }
345 else
346 pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
347
348 DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
349 }
350
351
352 int
353 __driParseEvents(__DRIcontextPrivate *pcp, __DRIdrawablePrivate *pdp)
354 {
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;
359 unsigned char *data;
360 size_t rect_size;
361
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
366 * pointer. */
367 DRM_UNLOCK(psp->fd, psp->lock, pcp->hHWContext);
368 (*psp->dri2.loader->reemitDrawableInfo)(pdp, &pdp->dri2.tail,
369 pdp->loaderPrivate);
370 DRM_LIGHT_LOCK(psp->fd, psp->lock, pcp->hHWContext);
371 }
372
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;
377
378 changed = 0;
379 last_dc = NULL;
380 last_ba = NULL;
381
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");
388 break;
389 }
390
391 switch (DRI2_EVENT_TYPE(*p)) {
392 case DRI2_EVENT_DRAWABLE_CONFIG:
393 dc = (__DRIDrawableConfigEvent *) p;
394 if (dc->drawable == pdp->dri2.drawable_id)
395 last_dc = dc;
396 break;
397
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)
402 last_ba = ba;
403 break;
404 }
405 }
406
407 if (last_dc) {
408 if (pdp->w != last_dc->width || pdp->h != last_dc->height)
409 changed = 1;
410
411 pdp->x = last_dc->x;
412 pdp->y = last_dc->y;
413 pdp->w = last_dc->width;
414 pdp->h = last_dc->height;
415
416 pdp->backX = 0;
417 pdp->backY = 0;
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;
423
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);
429 }
430
431 /* We only care about the most recent drawable config. */
432 if (last_dc && changed)
433 (*psp->DriverAPI.HandleDrawableConfig)(pdp, pcp, last_dc);
434
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.*/
448 if (last_ba)
449 (*psp->DriverAPI.HandleBufferAttach)(pdp, pcp, last_ba);
450
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;
461 else
462 tail = pdp->dri2.tail;
463
464 for ( ; tail != end; tail += size) {
465 ba = (__DRIBufferAttachEvent *) (data + (tail & mask));
466 size = DRI2_EVENT_SIZE(ba->event_header);
467
468 if (DRI2_EVENT_TYPE(ba->event_header) != DRI2_EVENT_BUFFER_ATTACH)
469 continue;
470 if (ba->drawable != pdp->dri2.drawable_id)
471 continue;
472 if (last_ba == ba)
473 continue;
474
475 (*psp->DriverAPI.HandleBufferAttach)(pdp, pcp, ba);
476 changed = 1;
477 }
478
479 pdp->dri2.tail = tail;
480
481 return changed || last_ba;
482 }
483
484 /*@}*/
485
486 /*****************************************************************/
487 /** \name GLX callbacks */
488 /*****************************************************************/
489 /*@{*/
490
491 static void driReportDamage(__DRIdrawable *pdp,
492 struct drm_clip_rect *pClipRects, int numClipRects)
493 {
494 __DRIscreen *psp = pdp->driScreenPriv;
495
496 /* Check that we actually have the new damage report method */
497 if (psp->dri2.enabled) {
498 (*psp->dri2.loader->postDamage)(pdp,
499 pClipRects,
500 numClipRects,
501 pdp->loaderPrivate);
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).
506 */
507 (*psp->damage->reportDamage)(pdp,
508 pdp->x, pdp->y,
509 pClipRects, numClipRects,
510 GL_TRUE, pdp->loaderPrivate);
511 }
512 }
513
514
515 /**
516 * Swap buffers.
517 *
518 * \param drawablePrivate opaque pointer to the per-drawable private info.
519 *
520 * \internal
521 * This function calls __DRIdrawablePrivate::swapBuffers.
522 *
523 * Is called directly from glXSwapBuffers().
524 */
525 static void driSwapBuffers(__DRIdrawable *dPriv)
526 {
527 __DRIscreen *psp = dPriv->driScreenPriv;
528
529 if (!dPriv->numClipRects)
530 return;
531
532 if (psp->dri2.enabled)
533 __driParseEvents(NULL, dPriv);
534
535 psp->DriverAPI.SwapBuffers(dPriv);
536
537 driReportDamage(dPriv, dPriv->pClipRects, dPriv->numClipRects);
538 }
539
540 static int driDrawableGetMSC( __DRIscreen *sPriv, __DRIdrawable *dPriv,
541 int64_t *msc )
542 {
543 return sPriv->DriverAPI.GetDrawableMSC(sPriv, dPriv, msc);
544 }
545
546
547 static int driWaitForMSC(__DRIdrawable *dPriv, int64_t target_msc,
548 int64_t divisor, int64_t remainder,
549 int64_t * msc, int64_t * sbc)
550 {
551 __DRIswapInfo sInfo;
552 int status;
553
554 status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
555 divisor, remainder,
556 msc );
557
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.
561 */
562 if ( status == 0
563 && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) {
564 status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
565 *sbc = sInfo.swap_count;
566 }
567
568 return status;
569 }
570
571
572 const __DRImediaStreamCounterExtension driMediaStreamCounterExtension = {
573 { __DRI_MEDIA_STREAM_COUNTER, __DRI_MEDIA_STREAM_COUNTER_VERSION },
574 driWaitForMSC,
575 driDrawableGetMSC,
576 };
577
578
579 static void driCopySubBuffer(__DRIdrawable *dPriv,
580 int x, int y, int w, int h)
581 {
582 drm_clip_rect_t rect;
583
584 rect.x1 = x;
585 rect.y1 = dPriv->h - y - h;
586 rect.x2 = x + w;
587 rect.y2 = rect.y1 + h;
588 driReportDamage(dPriv, &rect, 1);
589
590 dPriv->driScreenPriv->DriverAPI.CopySubBuffer(dPriv, x, y, w, h);
591 }
592
593 const __DRIcopySubBufferExtension driCopySubBufferExtension = {
594 { __DRI_COPY_SUB_BUFFER, __DRI_COPY_SUB_BUFFER_VERSION },
595 driCopySubBuffer
596 };
597
598 static void driSetSwapInterval(__DRIdrawable *dPriv, unsigned int interval)
599 {
600 dPriv->swap_interval = interval;
601 }
602
603 static unsigned int driGetSwapInterval(__DRIdrawable *dPriv)
604 {
605 return dPriv->swap_interval;
606 }
607
608 const __DRIswapControlExtension driSwapControlExtension = {
609 { __DRI_SWAP_CONTROL, __DRI_SWAP_CONTROL_VERSION },
610 driSetSwapInterval,
611 driGetSwapInterval
612 };
613
614
615 /**
616 * This is called via __DRIscreenRec's createNewDrawable pointer.
617 */
618 static __DRIdrawable *
619 driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config,
620 drm_drawable_t hwDrawable, int renderType,
621 const int *attrs, void *data)
622 {
623 __DRIdrawable *pdp;
624
625 /* Since pbuffers are not yet supported, no drawable attributes are
626 * supported either.
627 */
628 (void) attrs;
629
630 pdp = _mesa_malloc(sizeof *pdp);
631 if (!pdp) {
632 return NULL;
633 }
634
635 pdp->loaderPrivate = data;
636 pdp->hHWDrawable = hwDrawable;
637 pdp->refcount = 0;
638 pdp->pStamp = NULL;
639 pdp->lastStamp = 0;
640 pdp->index = 0;
641 pdp->x = 0;
642 pdp->y = 0;
643 pdp->w = 0;
644 pdp->h = 0;
645 pdp->numClipRects = 0;
646 pdp->numBackClipRects = 0;
647 pdp->pClipRects = NULL;
648 pdp->pBackClipRects = NULL;
649 pdp->vblSeq = 0;
650 pdp->vblFlags = 0;
651
652 pdp->driScreenPriv = psp;
653 pdp->driContextPriv = &psp->dummyContextPriv;
654
655 if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes,
656 renderType == GLX_PIXMAP_BIT)) {
657 _mesa_free(pdp);
658 return NULL;
659 }
660
661 pdp->msc_base = 0;
662
663 /* This special default value is replaced with the configured
664 * default value when the drawable is first bound to a direct
665 * rendering context.
666 */
667 pdp->swap_interval = (unsigned)-1;
668
669 return pdp;
670 }
671
672
673 static __DRIdrawable *
674 dri2CreateNewDrawable(__DRIscreen *screen, const __DRIconfig *config,
675 unsigned int drawable_id, unsigned int head, void *data)
676 {
677 __DRIdrawable *pdraw;
678
679 pdraw = driCreateNewDrawable(screen, config, 0, 0, NULL, data);
680 if (!pdraw)
681 return NULL;
682
683 pdraw->dri2.drawable_id = drawable_id;
684 pdraw->dri2.tail = head;
685 pdraw->pBackClipRects = _mesa_malloc(sizeof *pdraw->pBackClipRects);
686
687 return pdraw;
688 }
689
690
691 static void
692 driDestroyDrawable(__DRIdrawable *pdp)
693 {
694 __DRIscreenPrivate *psp;
695
696 if (pdp) {
697 psp = pdp->driScreenPriv;
698 (*psp->DriverAPI.DestroyBuffer)(pdp);
699 if (pdp->pClipRects) {
700 _mesa_free(pdp->pClipRects);
701 pdp->pClipRects = NULL;
702 }
703 if (pdp->pBackClipRects) {
704 _mesa_free(pdp->pBackClipRects);
705 pdp->pBackClipRects = NULL;
706 }
707 _mesa_free(pdp);
708 }
709 }
710
711 /*@}*/
712
713
714 /*****************************************************************/
715 /** \name Context handling functions */
716 /*****************************************************************/
717 /*@{*/
718
719 /**
720 * Destroy the per-context private information.
721 *
722 * \internal
723 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
724 * drmDestroyContext(), and finally frees \p contextPrivate.
725 */
726 static void
727 driDestroyContext(__DRIcontext *pcp)
728 {
729 if (pcp) {
730 (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
731 _mesa_free(pcp);
732 }
733 }
734
735
736 /**
737 * Create the per-drawable private driver information.
738 *
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
742 *
743 * \returns An opaque pointer to the per-context private information on
744 * success, or \c NULL on failure.
745 *
746 * \internal
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
750 * context.
751 *
752 */
753 static __DRIcontext *
754 driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config,
755 int render_type, __DRIcontext *shared,
756 drm_context_t hwContext, void *data)
757 {
758 __DRIcontext *pcp;
759 void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
760
761 pcp = _mesa_malloc(sizeof *pcp);
762 if (!pcp)
763 return NULL;
764
765 pcp->driScreenPriv = psp;
766 pcp->driDrawablePriv = NULL;
767
768 /* When the first context is created for a screen, initialize a "dummy"
769 * context.
770 */
771
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! */
778 }
779
780 pcp->hHWContext = hwContext;
781
782 if ( !(*psp->DriverAPI.CreateContext)(&config->modes, pcp, shareCtx) ) {
783 _mesa_free(pcp);
784 return NULL;
785 }
786
787 return pcp;
788 }
789
790
791 static __DRIcontext *
792 dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
793 __DRIcontext *shared, void *data)
794 {
795 drm_context_t hwContext;
796 DRM_CAS_RESULT(ret);
797
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. */
800
801 do {
802 hwContext = screen->dri2.lock->next_id;
803 DRM_CAS(&screen->dri2.lock->next_id, hwContext, hwContext + 1, ret);
804 } while (ret);
805
806 return driCreateNewContext(screen, config, 0, shared, hwContext, data);
807 }
808
809
810 static int
811 driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask)
812 {
813 return GL_FALSE;
814 }
815
816 /*@}*/
817
818
819 /*****************************************************************/
820 /** \name Screen handling functions */
821 /*****************************************************************/
822 /*@{*/
823
824 /**
825 * Destroy the per-screen private information.
826 *
827 * \internal
828 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
829 * drmClose(), and finally frees \p screenPrivate.
830 */
831 static void driDestroyScreen(__DRIscreen *psp)
832 {
833 if (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.
837 */
838
839 if (psp->DriverAPI.DestroyScreen)
840 (*psp->DriverAPI.DestroyScreen)(psp);
841
842 if (psp->dri2.enabled) {
843 #ifdef TTM_API
844 drmBOUnmap(psp->fd, &psp->dri2.sareaBO);
845 drmBOUnreference(psp->fd, &psp->dri2.sareaBO);
846 #endif
847 } else {
848 (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
849 (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
850 (void)drmCloseOnce(psp->fd);
851 }
852
853 _mesa_free(psp);
854 }
855 }
856
857 static void
858 setupLoaderExtensions(__DRIscreen *psp,
859 const __DRIextension **extensions)
860 {
861 int i;
862
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];
872 }
873 }
874
875 /**
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
880 * pbuffers.
881 *
882 * For legacy DRI.
883 *
884 * \param scrn Index of the screen
885 * \param ddx_version Version of the 2D DDX. This may not be meaningful for
886 * all drivers.
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
890 * framebuffer.
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 ??
896 *
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.
900 */
901 static __DRIscreen *
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,
910 void *loaderPrivate)
911 {
912 static const __DRIextension *emptyExtensionList[] = { NULL };
913 __DRIscreen *psp;
914
915 psp = _mesa_malloc(sizeof *psp);
916 if (!psp)
917 return NULL;
918
919 setupLoaderExtensions(psp, extensions);
920
921 /*
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.
925 */
926 psp->drawLockID = 1;
927
928 psp->drm_version = *drm_version;
929 psp->ddx_version = *ddx_version;
930 psp->dri_version = *dri_version;
931
932 psp->pSAREA = pSAREA;
933 psp->lock = (drmLock *) &psp->pSAREA->lock;
934
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;
943
944 psp->extensions = emptyExtensionList;
945 psp->fd = fd;
946 psp->myNum = scrn;
947 psp->dri2.enabled = GL_FALSE;
948
949 /*
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.
953 */
954 psp->dummyContextPriv.driScreenPriv = NULL;
955
956 psp->DriverAPI = driDriverAPI;
957
958 *driver_modes = driDriverAPI.InitScreen(psp);
959 if (*driver_modes == NULL) {
960 _mesa_free(psp);
961 return NULL;
962 }
963
964 return psp;
965 }
966
967
968 /**
969 * DRI2
970 */
971 static __DRIscreen *
972 dri2CreateNewScreen(int scrn, int fd, unsigned int sarea_handle,
973 const __DRIextension **extensions,
974 const __DRIconfig ***driver_configs, void *data)
975 {
976 #ifdef TTM_API
977 static const __DRIextension *emptyExtensionList[] = { NULL };
978 __DRIscreen *psp;
979 unsigned int *p;
980 drmVersionPtr version;
981
982 if (driDriverAPI.InitScreen2 == NULL)
983 return NULL;
984
985 psp = _mesa_malloc(sizeof(*psp));
986 if (!psp)
987 return NULL;
988
989 setupLoaderExtensions(psp, extensions);
990
991 version = drmGetVersion(fd);
992 if (version) {
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);
997 }
998
999 psp->extensions = emptyExtensionList;
1000 psp->fd = fd;
1001 psp->myNum = scrn;
1002 psp->dri2.enabled = GL_TRUE;
1003
1004 if (drmBOReference(psp->fd, sarea_handle, &psp->dri2.sareaBO)) {
1005 fprintf(stderr, "Failed to reference DRI2 sarea BO\n");
1006 _mesa_free(psp);
1007 return NULL;
1008 }
1009
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);
1013 _mesa_free(psp);
1014 return NULL;
1015 }
1016
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;
1022 break;
1023 case DRI2_SAREA_BLOCK_EVENT_BUFFER:
1024 psp->dri2.buffer = (__DRIEventBuffer *) p;
1025 break;
1026 }
1027 p = DRI2_SAREA_BLOCK_NEXT(p);
1028 }
1029
1030 psp->lock = (drmLock *) &psp->dri2.lock->lock;
1031
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);
1037 _mesa_free(psp);
1038 return NULL;
1039 }
1040
1041 psp->DriverAPI = driDriverAPI;
1042
1043 return psp;
1044 #else
1045 return NULL;
1046 #endif
1047 }
1048
1049 static const __DRIextension **driGetExtensions(__DRIscreen *psp)
1050 {
1051 return psp->extensions;
1052 }
1053
1054 /** Legacy DRI interface */
1055 const __DRIlegacyExtension driLegacyExtension = {
1056 { __DRI_LEGACY, __DRI_LEGACY_VERSION },
1057 driCreateNewScreen,
1058 driCreateNewDrawable,
1059 driCreateNewContext
1060 };
1061
1062 /** DRI2 interface */
1063 const __DRIcoreExtension driCoreExtension = {
1064 { __DRI_CORE, __DRI_CORE_VERSION },
1065 dri2CreateNewScreen,
1066 driDestroyScreen,
1067 driGetExtensions,
1068 driGetConfigAttrib,
1069 driIndexConfigAttrib,
1070 dri2CreateNewDrawable,
1071 driDestroyDrawable,
1072 driSwapBuffers,
1073 dri2CreateNewContext,
1074 driCopyContext,
1075 driDestroyContext,
1076 driBindContext,
1077 driUnbindContext
1078 };
1079
1080 /* This is the table of extensions that the loader will dlsym() for. */
1081 PUBLIC const __DRIextension *__driDriverExtensions[] = {
1082 &driCoreExtension.base,
1083 &driLegacyExtension.base,
1084 NULL
1085 };
1086
1087 static int
1088 driFrameTracking(__DRIdrawable *drawable, GLboolean enable)
1089 {
1090 return GLX_BAD_CONTEXT;
1091 }
1092
1093 static int
1094 driQueryFrameTracking(__DRIdrawable *dpriv,
1095 int64_t * sbc, int64_t * missedFrames,
1096 float * lastMissedUsage, float * usage)
1097 {
1098 __DRIswapInfo sInfo;
1099 int status;
1100 int64_t ust;
1101 __DRIscreenPrivate *psp = dpriv->driScreenPriv;
1102
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;
1108
1109 (*psp->systemTime->getUST)( & ust );
1110 *usage = driCalculateSwapUsage( dpriv, sInfo.swap_ust, ust );
1111 }
1112
1113 return status;
1114 }
1115
1116 const __DRIframeTrackingExtension driFrameTrackingExtension = {
1117 { __DRI_FRAME_TRACKING, __DRI_FRAME_TRACKING_VERSION },
1118 driFrameTracking,
1119 driQueryFrameTracking
1120 };
1121
1122 /**
1123 * Calculate amount of swap interval used between GLX buffer swaps.
1124 *
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.
1127 *
1128 * \f$p = t_d / (i * t_r)\f$
1129 *
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).
1134 *
1135 * See the documentation for the GLX_MESA_swap_frame_usage extension for more
1136 * details.
1137 *
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.
1144 *
1145 * \sa glXSwapIntervalSGI glXGetMscRateOML
1146 *
1147 * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
1148 * be possible to cache the sync rate?
1149 */
1150 float
1151 driCalculateSwapUsage( __DRIdrawablePrivate *dPriv, int64_t last_swap_ust,
1152 int64_t current_ust )
1153 {
1154 int32_t n;
1155 int32_t d;
1156 int interval;
1157 float usage = 1.0;
1158 __DRIscreenPrivate *psp = dPriv->driScreenPriv;
1159
1160 if ( (*psp->systemTime->getMSCRate)(dPriv, &n, &d, dPriv->loaderPrivate) ) {
1161 interval = (dPriv->swap_interval != 0) ? dPriv->swap_interval : 1;
1162
1163
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.
1168 *
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.
1174 */
1175
1176 usage = (current_ust - last_swap_ust);
1177 usage *= n;
1178 usage /= (interval * d);
1179 usage /= 1000000.0;
1180 }
1181
1182 return usage;
1183 }
1184
1185 /*@}*/