DRI2: Drop DriverAPI.UpdateBuffer.
[mesa.git] / src / mesa / drivers / dri / common / dri_util.c
1 /* $XFree86: xc/lib/GL/dri/dri_util.c,v 1.7 2003/04/28 17:01:25 dawes Exp $ */
2 /**
3 * \file dri_util.c
4 * DRI utility functions.
5 *
6 * This module acts as glue between GLX and the actual hardware driver. A DRI
7 * driver doesn't really \e have to use any of this - it's optional. But, some
8 * useful stuff is done here that otherwise would have to be duplicated in most
9 * drivers.
10 *
11 * Basically, these utility functions take care of some of the dirty details of
12 * screen initialization, context creation, context binding, DRM setup, etc.
13 *
14 * These functions are compiled into each DRI driver so libGL.so knows nothing
15 * about them.
16 */
17
18
19 #include <assert.h>
20 #include <stdarg.h>
21 #include <unistd.h>
22 #include <sys/mman.h>
23 #include <stdio.h>
24 #include <dlfcn.h>
25
26 #ifndef MAP_FAILED
27 #define MAP_FAILED ((void *)-1)
28 #endif
29
30 #include "imports.h"
31 #define None 0
32
33 #include "dri_util.h"
34 #include "drm_sarea.h"
35
36 #ifndef GLX_OML_sync_control
37 typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator);
38 #endif
39
40 /**
41 * This is just a token extension used to signal that the driver
42 * supports setting a read drawable.
43 */
44 const __DRIextension driReadDrawableExtension = {
45 __DRI_READ_DRAWABLE, __DRI_READ_DRAWABLE_VERSION
46 };
47
48 static void *driCreateNewDrawable(__DRIscreen *screen,
49 const __GLcontextModes *modes,
50 __DRIdrawable *pdraw,
51 drm_drawable_t hwDrawable,
52 unsigned int head,
53 int renderType, const int *attrs);
54
55 static void driDestroyDrawable(__DRIdrawable *drawable);
56
57
58 /**
59 * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
60 * is set.
61 *
62 * Is called from the drivers.
63 *
64 * \param f \c printf like format string.
65 */
66 void
67 __driUtilMessage(const char *f, ...)
68 {
69 va_list args;
70
71 if (getenv("LIBGL_DEBUG")) {
72 fprintf(stderr, "libGL error: \n");
73 va_start(args, f);
74 vfprintf(stderr, f, args);
75 va_end(args);
76 fprintf(stderr, "\n");
77 }
78 }
79
80
81 /*****************************************************************/
82 /** \name Context (un)binding functions */
83 /*****************************************************************/
84 /*@{*/
85
86 /**
87 * Unbind context.
88 *
89 * \param scrn the screen.
90 * \param gc context.
91 *
92 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
93 *
94 * \internal
95 * This function calls __DriverAPIRec::UnbindContext, and then decrements
96 * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
97 * return.
98 *
99 * While casting the opaque private pointers associated with the parameters
100 * into their respective real types it also assures they are not \c NULL.
101 */
102 static GLboolean driUnbindContext(__DRIcontext *ctx)
103 {
104 __DRIcontextPrivate *pcp;
105 __DRIscreenPrivate *psp;
106 __DRIdrawablePrivate *pdp;
107 __DRIdrawablePrivate *prp;
108
109 /*
110 ** Assume error checking is done properly in glXMakeCurrent before
111 ** calling driUnbindContext.
112 */
113
114 if (ctx == NULL)
115 return GL_FALSE;
116
117 pcp = (__DRIcontextPrivate *)ctx->private;
118 psp = (__DRIscreenPrivate *)pcp->driScreenPriv;
119 pdp = (__DRIdrawablePrivate *)pcp->driDrawablePriv;
120 prp = (__DRIdrawablePrivate *)pcp->driReadablePriv;
121
122 /* Let driver unbind drawable from context */
123 (*psp->DriverAPI.UnbindContext)(pcp);
124
125 if (pdp->refcount == 0) {
126 /* ERROR!!! */
127 return GL_FALSE;
128 }
129
130 pdp->refcount--;
131
132 if (prp != pdp) {
133 if (prp->refcount == 0) {
134 /* ERROR!!! */
135 return GL_FALSE;
136 }
137
138 prp->refcount--;
139 }
140
141
142 /* XXX this is disabled so that if we call SwapBuffers on an unbound
143 * window we can determine the last context bound to the window and
144 * use that context's lock. (BrianP, 2-Dec-2000)
145 */
146 #if 0
147 /* Unbind the drawable */
148 pcp->driDrawablePriv = NULL;
149 pdp->driContextPriv = &psp->dummyContextPriv;
150 #endif
151
152 return GL_TRUE;
153 }
154
155
156 /**
157 * This function takes both a read buffer and a draw buffer. This is needed
158 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
159 * function.
160 */
161 static GLboolean driBindContext(__DRIcontext * ctx,
162 __DRIdrawable *pdraw,
163 __DRIdrawable *pread)
164 {
165 __DRIdrawablePrivate *pdp;
166 __DRIdrawablePrivate *prp;
167 __DRIcontextPrivate * const pcp = ctx->private;
168 __DRIscreenPrivate *psp = pcp->driScreenPriv;
169
170 /*
171 ** Assume error checking is done properly in glXMakeCurrent before
172 ** calling driBindContext.
173 */
174
175 if (ctx == NULL || pdraw == None || pread == None)
176 return GL_FALSE;
177
178 pdp = (__DRIdrawablePrivate *) pdraw->private;
179 prp = (__DRIdrawablePrivate *) pread->private;
180
181 /* Bind the drawable to the context */
182 pcp->driDrawablePriv = pdp;
183 pcp->driReadablePriv = prp;
184 pdp->driContextPriv = pcp;
185 pdp->refcount++;
186 if ( pdp != prp ) {
187 prp->refcount++;
188 }
189
190 /*
191 ** Now that we have a context associated with this drawable, we can
192 ** initialize the drawable information if has not been done before.
193 */
194
195 if (psp->dri2.enabled) {
196 __driParseEvents(pcp, pdp);
197 __driParseEvents(pcp, prp);
198 } else {
199 if (!pdp->pStamp || *pdp->pStamp != pdp->lastStamp) {
200 DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
201 __driUtilUpdateDrawableInfo(pdp);
202 DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
203 }
204
205 if ((pdp != prp) && (!prp->pStamp || *prp->pStamp != prp->lastStamp)) {
206 DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
207 __driUtilUpdateDrawableInfo(prp);
208 DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
209 }
210 }
211
212 /* Call device-specific MakeCurrent */
213 (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
214
215 return GL_TRUE;
216 }
217
218 /*@}*/
219
220
221 /*****************************************************************/
222 /** \name Drawable handling functions */
223 /*****************************************************************/
224 /*@{*/
225
226 /**
227 * Update private drawable information.
228 *
229 * \param pdp pointer to the private drawable information to update.
230 *
231 * This function basically updates the __DRIdrawablePrivate struct's
232 * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo.
233 * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
234 * compares the __DRIdrwablePrivate pStamp and lastStamp values. If
235 * the values are different that means we have to update the clipping
236 * info.
237 */
238 void
239 __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
240 {
241 __DRIscreenPrivate *psp = pdp->driScreenPriv;
242 __DRIcontextPrivate *pcp = pdp->driContextPriv;
243
244 if (!pcp
245 || ((pdp != pcp->driDrawablePriv) && (pdp != pcp->driReadablePriv))) {
246 /* ERROR!!!
247 * ...but we must ignore it. There can be many contexts bound to a
248 * drawable.
249 */
250 }
251
252 if (pdp->pClipRects) {
253 _mesa_free(pdp->pClipRects);
254 pdp->pClipRects = NULL;
255 }
256
257 if (pdp->pBackClipRects) {
258 _mesa_free(pdp->pBackClipRects);
259 pdp->pBackClipRects = NULL;
260 }
261
262 DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
263
264 if (! (*psp->getDrawableInfo->getDrawableInfo)(pdp->pdraw,
265 &pdp->index, &pdp->lastStamp,
266 &pdp->x, &pdp->y, &pdp->w, &pdp->h,
267 &pdp->numClipRects, &pdp->pClipRects,
268 &pdp->backX,
269 &pdp->backY,
270 &pdp->numBackClipRects,
271 &pdp->pBackClipRects )) {
272 /* Error -- eg the window may have been destroyed. Keep going
273 * with no cliprects.
274 */
275 pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
276 pdp->numClipRects = 0;
277 pdp->pClipRects = NULL;
278 pdp->numBackClipRects = 0;
279 pdp->pBackClipRects = NULL;
280 }
281 else
282 pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
283
284 DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
285
286 }
287
288 int
289 __driParseEvents(__DRIcontextPrivate *pcp, __DRIdrawablePrivate *pdp)
290 {
291 __DRIscreenPrivate *psp = pcp->driScreenPriv;
292 __DRIDrawableConfigEvent *dc, *last_dc;
293 __DRIBufferAttachEvent *ba, *last_ba;
294 unsigned int tail, mask, *p, end, total, size, changed;
295 unsigned char *data;
296 size_t rect_size;
297
298 /* Check for wraparound. */
299 if (psp->dri2.buffer->prealloc - pdp->dri2.tail > psp->dri2.buffer->size) {
300 /* If prealloc overlaps into what we just parsed, the
301 * server overwrote it and we have to reset our tail
302 * pointer. */
303 DRM_UNLOCK(psp->fd, psp->lock, pcp->hHWContext);
304 (*psp->dri2.core->reemitDrawableInfo)(pdp->pdraw, &pdp->dri2.tail);
305 DRM_LIGHT_LOCK(psp->fd, psp->lock, pcp->hHWContext);
306 }
307
308 total = psp->dri2.buffer->head - pdp->dri2.tail;
309 mask = psp->dri2.buffer->size - 1;
310 end = psp->dri2.buffer->head;
311 data = psp->dri2.buffer->data;
312
313 changed = 0;
314 last_dc = NULL;
315 last_ba = NULL;
316
317 for (tail = pdp->dri2.tail; tail != end; tail += size) {
318 p = (unsigned int *) (data + (tail & mask));
319 size = DRI2_EVENT_SIZE(*p);
320 if (size > total || (tail & mask) + size > psp->dri2.buffer->size) {
321 /* illegal data, bail out. */
322 fprintf(stderr, "illegal event size\n");
323 break;
324 }
325
326 switch (DRI2_EVENT_TYPE(*p)) {
327 case DRI2_EVENT_DRAWABLE_CONFIG:
328 dc = (__DRIDrawableConfigEvent *) p;
329 if (dc->drawable == pdp->hHWDrawable)
330 last_dc = dc;
331 break;
332
333 case DRI2_EVENT_BUFFER_ATTACH:
334 ba = (__DRIBufferAttachEvent *) p;
335 if (ba->drawable == pdp->hHWDrawable &&
336 ba->buffer.attachment == DRI_DRAWABLE_BUFFER_FRONT_LEFT)
337 last_ba = ba;
338 break;
339 }
340 }
341
342 if (last_dc) {
343 if (pdp->w != last_dc->width || pdp->h != last_dc->height)
344 changed = 1;
345
346 pdp->x = last_dc->x;
347 pdp->y = last_dc->y;
348 pdp->w = last_dc->width;
349 pdp->h = last_dc->height;
350
351 pdp->backX = 0;
352 pdp->backY = 0;
353 pdp->numBackClipRects = 1;
354 pdp->pBackClipRects[0].x1 = 0;
355 pdp->pBackClipRects[0].y1 = 0;
356 pdp->pBackClipRects[0].x2 = pdp->w;
357 pdp->pBackClipRects[0].y2 = pdp->h;
358
359 pdp->numClipRects = last_dc->num_rects;
360 _mesa_free(pdp->pClipRects);
361 rect_size = last_dc->num_rects * sizeof last_dc->rects[0];
362 pdp->pClipRects = _mesa_malloc(rect_size);
363 memcpy(pdp->pClipRects, last_dc->rects, rect_size);
364
365 if (changed)
366 (*psp->DriverAPI.HandleDrawableConfig)(pdp, pcp, last_dc);
367 }
368
369 /* Front buffer attachments are special, they typically mean that
370 * we're rendering to a redirected window (or a child window of a
371 * redirected window) and that it got resized. Resizing the root
372 * window on randr events is a special case of this. Other causes
373 * may be a window transitioning between redirected and
374 * non-redirected, or a window getting reparented between parents
375 * with different window pixmaps (eg two redirected windows).
376 * These events are special in that the X server allocates the
377 * buffer and that the buffer may be shared by other child
378 * windows. When our window share the window pixmap with its
379 * parent, drawable config events doesn't affect the front buffer.
380 * We only care about the last such event in the buffer; in fact,
381 * older events will refer to invalid buffer objects.*/
382 if (last_ba)
383 (*psp->DriverAPI.HandleBufferAttach)(pdp, pcp, last_ba);
384
385 /* Like for buffer attachments, we only care about the most recent
386 * drawable config. */
387 if (last_dc)
388 (*psp->DriverAPI.HandleDrawableConfig)(pdp, pcp, last_dc);
389
390 /* If there was a drawable config event in the buffer and it
391 * changed the size of the window, all buffer auxillary buffer
392 * attachments prior to that are invalid (as opposed to the front
393 * buffer case discussed above). In that case we can start
394 * looking for buffer attachment after the last drawable config
395 * event. If there is no drawable config event in this batch of
396 * events, we have to assume that the last batch might have had
397 * one and process all buffer attach events.*/
398 if (last_dc && changed)
399 tail = (unsigned char *) last_dc - data;
400 else
401 tail = pdp->dri2.tail;
402
403 for ( ; tail != end; tail += size) {
404 ba = (__DRIBufferAttachEvent *) (data + (tail & mask));
405 size = DRI2_EVENT_SIZE(ba->event_header);
406
407 if (DRI2_EVENT_TYPE(ba->event_header) != DRI2_EVENT_BUFFER_ATTACH)
408 continue;
409 if (ba->drawable != pdp->hHWDrawable)
410 continue;
411 if (last_ba == ba)
412 continue;
413
414 (*psp->DriverAPI.HandleBufferAttach)(pdp, pcp, ba);
415 }
416
417 pdp->dri2.tail = tail;
418
419 /* FIXME: Return whether we changed anything. This check always
420 * returns true if we received events, but we could refine the
421 * check to only return TRUE if the drawable actually changed. */
422
423 return total > 0;
424 }
425
426 /*@}*/
427
428 /*****************************************************************/
429 /** \name GLX callbacks */
430 /*****************************************************************/
431 /*@{*/
432
433 /**
434 * Swap buffers.
435 *
436 * \param drawablePrivate opaque pointer to the per-drawable private info.
437 *
438 * \internal
439 * This function calls __DRIdrawablePrivate::swapBuffers.
440 *
441 * Is called directly from glXSwapBuffers().
442 */
443 static void driSwapBuffers(__DRIdrawable *drawable)
444 {
445 __DRIdrawablePrivate *dPriv = drawable->private;
446 __DRIscreenPrivate *psp = dPriv->driScreenPriv;
447 drm_clip_rect_t rect;
448
449 if (!dPriv->numClipRects)
450 return;
451
452 dPriv->swapBuffers(dPriv);
453
454 /* Check that we actually have the new damage report method */
455 if (psp->damage == NULL)
456 return;
457
458 /* Assume it's affecting the whole drawable for now */
459 rect.x1 = 0;
460 rect.y1 = 0;
461 rect.x2 = rect.x1 + dPriv->w;
462 rect.y2 = rect.y1 + dPriv->h;
463
464 /* Report the damage. Currently, all our drivers draw directly to the
465 * front buffer, so we report the damage there rather than to the backing
466 * store (if any).
467 */
468 (*psp->damage->reportDamage)(dPriv->pdraw,
469 dPriv->x, dPriv->y, &rect, 1, GL_TRUE);
470 }
471
472 static int driDrawableGetMSC( __DRIscreen *screen, __DRIdrawable *drawable,
473 int64_t *msc )
474 {
475 __DRIscreenPrivate *sPriv = screen->private;
476 __DRIdrawablePrivate *dPriv = drawable->private;
477
478 return sPriv->DriverAPI.GetDrawableMSC(sPriv, dPriv, msc);
479 }
480
481 static int driWaitForMSC(__DRIdrawable *drawable, int64_t target_msc,
482 int64_t divisor, int64_t remainder,
483 int64_t * msc, int64_t * sbc)
484 {
485 __DRIdrawablePrivate *dPriv = drawable->private;
486 __DRIswapInfo sInfo;
487 int status;
488
489
490 status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
491 divisor, remainder,
492 msc );
493
494 /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
495 * is supported but GLX_OML_sync_control is not. Therefore, don't return
496 * an error value if GetSwapInfo() is not implemented.
497 */
498 if ( status == 0
499 && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) {
500 status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
501 *sbc = sInfo.swap_count;
502 }
503
504 return status;
505 }
506
507 const __DRImediaStreamCounterExtension driMediaStreamCounterExtension = {
508 { __DRI_MEDIA_STREAM_COUNTER, __DRI_MEDIA_STREAM_COUNTER_VERSION },
509 driWaitForMSC,
510 driDrawableGetMSC,
511 };
512
513 static void driCopySubBuffer(__DRIdrawable *drawable,
514 int x, int y, int w, int h)
515 {
516 __DRIdrawablePrivate *dPriv = drawable->private;
517 dPriv->driScreenPriv->DriverAPI.CopySubBuffer(dPriv, x, y, w, h);
518 }
519
520 const __DRIcopySubBufferExtension driCopySubBufferExtension = {
521 { __DRI_COPY_SUB_BUFFER, __DRI_COPY_SUB_BUFFER_VERSION },
522 driCopySubBuffer
523 };
524
525 static void driSetSwapInterval(__DRIdrawable *drawable, unsigned int interval)
526 {
527 __DRIdrawablePrivate *dpriv = drawable->private;
528
529 dpriv->swap_interval = interval;
530 }
531
532 static unsigned int driGetSwapInterval(__DRIdrawable *drawable)
533 {
534 __DRIdrawablePrivate *dpriv = drawable->private;
535
536 return dpriv->swap_interval;
537 }
538
539 const __DRIswapControlExtension driSwapControlExtension = {
540 { __DRI_SWAP_CONTROL, __DRI_SWAP_CONTROL_VERSION },
541 driSetSwapInterval,
542 driGetSwapInterval
543 };
544
545
546 /**
547 * This is called via __DRIscreenRec's createNewDrawable pointer.
548 */
549 static void *driCreateNewDrawable(__DRIscreen *screen,
550 const __GLcontextModes *modes,
551 __DRIdrawable *pdraw,
552 drm_drawable_t hwDrawable,
553 unsigned int head,
554 int renderType,
555 const int *attrs)
556 {
557 __DRIscreenPrivate *psp;
558 __DRIdrawablePrivate *pdp;
559
560 pdraw->private = NULL;
561
562 /* Since pbuffers are not yet supported, no drawable attributes are
563 * supported either.
564 */
565 (void) attrs;
566
567 pdp = (__DRIdrawablePrivate *)_mesa_malloc(sizeof(__DRIdrawablePrivate));
568 if (!pdp) {
569 return NULL;
570 }
571
572 pdp->hHWDrawable = hwDrawable;
573 pdp->pdraw = pdraw;
574 pdp->refcount = 0;
575 pdp->pStamp = NULL;
576 pdp->lastStamp = 0;
577 pdp->index = 0;
578 pdp->x = 0;
579 pdp->y = 0;
580 pdp->w = 0;
581 pdp->h = 0;
582 pdp->numClipRects = 0;
583 pdp->numBackClipRects = 0;
584 pdp->pClipRects = NULL;
585 pdp->pBackClipRects = NULL;
586 pdp->vblSeq = 0;
587 pdp->vblFlags = 0;
588
589 psp = (__DRIscreenPrivate *)screen->private;
590 pdp->driScreenPriv = psp;
591 pdp->driContextPriv = &psp->dummyContextPriv;
592
593 if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, modes,
594 renderType == GLX_PIXMAP_BIT)) {
595 _mesa_free(pdp);
596 return NULL;
597 }
598
599 pdraw->private = pdp;
600 pdraw->destroyDrawable = driDestroyDrawable;
601 pdraw->swapBuffers = driSwapBuffers; /* called by glXSwapBuffers() */
602 pdp->msc_base = 0;
603
604 /* This special default value is replaced with the configured
605 * default value when the drawable is first bound to a direct
606 * rendering context.
607 */
608 pdp->swap_interval = (unsigned)-1;
609
610 pdp->swapBuffers = psp->DriverAPI.SwapBuffers;
611
612 if (psp->dri2.enabled) {
613 pdp->dri2.tail = head;
614 pdp->pBackClipRects = _mesa_malloc(sizeof *pdp->pBackClipRects);
615 }
616
617 return (void *) pdp;
618 }
619
620 static void
621 driDestroyDrawable(__DRIdrawable *drawable)
622 {
623 __DRIdrawablePrivate *pdp = drawable->private;
624 __DRIscreenPrivate *psp;
625
626 if (pdp) {
627 psp = pdp->driScreenPriv;
628 (*psp->DriverAPI.DestroyBuffer)(pdp);
629 if (pdp->pClipRects) {
630 _mesa_free(pdp->pClipRects);
631 pdp->pClipRects = NULL;
632 }
633 if (pdp->pBackClipRects) {
634 _mesa_free(pdp->pBackClipRects);
635 pdp->pBackClipRects = NULL;
636 }
637 _mesa_free(pdp);
638 }
639 }
640
641 /*@}*/
642
643
644 /*****************************************************************/
645 /** \name Context handling functions */
646 /*****************************************************************/
647 /*@{*/
648
649 /**
650 * Destroy the per-context private information.
651 *
652 * \param contextPrivate opaque pointer to the per-drawable private info.
653 *
654 * \internal
655 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
656 * drmDestroyContext(), and finally frees \p contextPrivate.
657 */
658 static void
659 driDestroyContext(__DRIcontext *context)
660 {
661 __DRIcontextPrivate *pcp = context->private;
662
663 if (pcp) {
664 (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
665 _mesa_free(pcp);
666 }
667 }
668
669
670 /**
671 * Create the per-drawable private driver information.
672 *
673 * \param dpy The display handle.
674 * \param modes Mode used to create the new context.
675 * \param render_type Type of rendering target. \c GLX_RGBA is the only
676 * type likely to ever be supported for direct-rendering.
677 * \param shared The shared context dependent methods or \c NULL if
678 * non-existent.
679 * \param pctx DRI context to receive the context dependent methods.
680 *
681 * \returns An opaque pointer to the per-context private information on
682 * success, or \c NULL on failure.
683 *
684 * \internal
685 * This function allocates and fills a __DRIcontextPrivateRec structure. It
686 * performs some device independent initialization and passes all the
687 * relevent information to __DriverAPIRec::CreateContext to create the
688 * context.
689 *
690 */
691 static void *
692 driCreateNewContext(__DRIscreen *screen, const __GLcontextModes *modes,
693 int render_type, __DRIcontext *shared,
694 drm_context_t hwContext, __DRIcontext *pctx)
695 {
696 __DRIcontextPrivate *pcp;
697 __DRIcontextPrivate *pshare = (shared != NULL) ? shared->private : NULL;
698 __DRIscreenPrivate *psp;
699 void * const shareCtx = (pshare != NULL) ? pshare->driverPrivate : NULL;
700
701 psp = (__DRIscreenPrivate *)screen->private;
702
703 pcp = (__DRIcontextPrivate *)_mesa_malloc(sizeof(__DRIcontextPrivate));
704 if (!pcp) {
705 return NULL;
706 }
707
708 pcp->hHWContext = hwContext;
709 pcp->driScreenPriv = psp;
710 pcp->driDrawablePriv = NULL;
711
712 /* When the first context is created for a screen, initialize a "dummy"
713 * context.
714 */
715
716 if (!psp->dri2.enabled && !psp->dummyContextPriv.driScreenPriv) {
717 psp->dummyContextPriv.hHWContext = psp->pSAREA->dummy_context;
718 psp->dummyContextPriv.driScreenPriv = psp;
719 psp->dummyContextPriv.driDrawablePriv = NULL;
720 psp->dummyContextPriv.driverPrivate = NULL;
721 /* No other fields should be used! */
722 }
723
724 pctx->destroyContext = driDestroyContext;
725 pctx->bindContext = driBindContext;
726 pctx->unbindContext = driUnbindContext;
727
728 if ( !(*psp->DriverAPI.CreateContext)(modes, pcp, shareCtx) ) {
729 _mesa_free(pcp);
730 return NULL;
731 }
732
733 return pcp;
734 }
735 /*@}*/
736
737
738 static const __DRIextension **
739 driGetExtensions(__DRIscreen *screen)
740 {
741 __DRIscreenPrivate *psp = screen->private;
742
743 return psp->extensions;
744 }
745
746 /*****************************************************************/
747 /** \name Screen handling functions */
748 /*****************************************************************/
749 /*@{*/
750
751 /**
752 * Destroy the per-screen private information.
753 *
754 * \param dpy the display handle.
755 * \param scrn the screen number.
756 * \param screenPrivate opaque pointer to the per-screen private information.
757 *
758 * \internal
759 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
760 * drmClose(), and finally frees \p screenPrivate.
761 */
762 static void driDestroyScreen(__DRIscreen *screen)
763 {
764 __DRIscreenPrivate *psp = screen->private;
765
766 if (psp) {
767 /* No interaction with the X-server is possible at this point. This
768 * routine is called after XCloseDisplay, so there is no protocol
769 * stream open to the X-server anymore.
770 */
771
772 if (psp->DriverAPI.DestroyScreen)
773 (*psp->DriverAPI.DestroyScreen)(psp);
774
775 if (psp->dri2.enabled) {
776 drmBOUnmap(psp->fd, &psp->dri2.sareaBO);
777 drmBOUnreference(psp->fd, &psp->dri2.sareaBO);
778 } else {
779 (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
780 (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
781 (void)drmCloseOnce(psp->fd);
782 }
783
784 _mesa_free(psp);
785 }
786 }
787
788 static void
789 setupLoaderExtensions(__DRIscreenPrivate *psp,
790 const __DRIextension **extensions)
791 {
792 int i;
793
794 for (i = 0; extensions[i]; i++) {
795 if (strcmp(extensions[i]->name, __DRI_CONTEXT_MODES) == 0)
796 psp->contextModes = (__DRIcontextModesExtension *) extensions[i];
797 if (strcmp(extensions[i]->name, __DRI_GET_DRAWABLE_INFO) == 0)
798 psp->getDrawableInfo = (__DRIgetDrawableInfoExtension *) extensions[i];
799 if (strcmp(extensions[i]->name, __DRI_DAMAGE) == 0)
800 psp->damage = (__DRIdamageExtension *) extensions[i];
801 if (strcmp(extensions[i]->name, __DRI_SYSTEM_TIME) == 0)
802 psp->systemTime = (__DRIsystemTimeExtension *) extensions[i];
803 if (strcmp(extensions[i]->name, __DRI_CORE_DRI2) == 0)
804 psp->dri2.core = (__DRIcoreDRI2Extension *) extensions[i];
805 }
806 }
807
808 /**
809 * This is the bootstrap function for the driver. libGL supplies all of the
810 * requisite information about the system, and the driver initializes itself.
811 * This routine also fills in the linked list pointed to by \c driver_modes
812 * with the \c __GLcontextModes that the driver can support for windows or
813 * pbuffers.
814 *
815 * \param scrn Index of the screen
816 * \param psc DRI screen data (not driver private)
817 * \param modes Linked list of known display modes. This list is, at a
818 * minimum, a list of modes based on the current display mode.
819 * These roughly match the set of available X11 visuals, but it
820 * need not be limited to X11! The calling libGL should create
821 * a list that will inform the driver of the current display
822 * mode (i.e., color buffer depth, depth buffer depth, etc.).
823 * \param ddx_version Version of the 2D DDX. This may not be meaningful for
824 * all drivers.
825 * \param dri_version Version of the "server-side" DRI.
826 * \param drm_version Version of the kernel DRM.
827 * \param frame_buffer Data describing the location and layout of the
828 * framebuffer.
829 * \param pSAREA Pointer the the SAREA.
830 * \param fd Device handle for the DRM.
831 * \param internal_api_version Version of the internal interface between the
832 * driver and libGL.
833 * \param driverAPI Driver API functions used by other routines in dri_util.c.
834 *
835 * \note There is no need to check the minimum API version in this
836 * function. Since the name of this function is versioned, it is
837 * impossible for a loader that is too old to even load this driver.
838 */
839 PUBLIC
840 void * __DRI_CREATE_NEW_SCREEN( int scrn, __DRIscreen *psc,
841 const __DRIversion * ddx_version,
842 const __DRIversion * dri_version,
843 const __DRIversion * drm_version,
844 const __DRIframebuffer * frame_buffer,
845 drmAddress pSAREA, int fd,
846 const __DRIextension ** extensions,
847 __GLcontextModes ** driver_modes )
848
849 {
850 __DRIscreenPrivate *psp;
851 static const __DRIextension *emptyExtensionList[] = { NULL };
852
853 psp = _mesa_malloc(sizeof(*psp));
854 if (!psp)
855 return NULL;
856
857 psp->psc = psc;
858
859 setupLoaderExtensions(psp, extensions);
860
861 /*
862 ** NOT_DONE: This is used by the X server to detect when the client
863 ** has died while holding the drawable lock. The client sets the
864 ** drawable lock to this value.
865 */
866 psp->drawLockID = 1;
867
868 psp->drm_version = *drm_version;
869 psp->ddx_version = *ddx_version;
870 psp->dri_version = *dri_version;
871
872 psp->pSAREA = pSAREA;
873 psp->lock = (drmLock *) &psp->pSAREA->lock;
874
875 psp->pFB = frame_buffer->base;
876 psp->fbSize = frame_buffer->size;
877 psp->fbStride = frame_buffer->stride;
878 psp->fbWidth = frame_buffer->width;
879 psp->fbHeight = frame_buffer->height;
880 psp->devPrivSize = frame_buffer->dev_priv_size;
881 psp->pDevPriv = frame_buffer->dev_priv;
882 psp->fbBPP = psp->fbStride * 8 / frame_buffer->width;
883
884 psp->extensions = emptyExtensionList;
885 psp->fd = fd;
886 psp->myNum = scrn;
887 psp->dri2.enabled = GL_FALSE;
888
889 /*
890 ** Do not init dummy context here; actual initialization will be
891 ** done when the first DRI context is created. Init screen priv ptr
892 ** to NULL to let CreateContext routine that it needs to be inited.
893 */
894 psp->dummyContextPriv.driScreenPriv = NULL;
895
896 psc->destroyScreen = driDestroyScreen;
897 psc->getExtensions = driGetExtensions;
898 psc->createNewDrawable = driCreateNewDrawable;
899 psc->createNewContext = driCreateNewContext;
900
901 *driver_modes = __driDriverInitScreen(psp);
902 if (*driver_modes == NULL) {
903 _mesa_free(psp);
904 return NULL;
905 }
906
907 return psp;
908 }
909
910 PUBLIC void *
911 __DRI2_CREATE_NEW_SCREEN(int scrn, __DRIscreen *psc,
912 int fd, unsigned int sarea_handle,
913 const __DRIextension **extensions,
914 __GLcontextModes **driver_modes)
915 {
916 __DRIscreenPrivate *psp;
917 static const __DRIextension *emptyExtensionList[] = { NULL };
918 unsigned int *p;
919 drmVersionPtr version;
920 __GLcontextModes *(*initScreen)(__DRIscreenPrivate *psc);
921
922 initScreen = dlsym(NULL, "__dri2DriverInitScreen");
923 if (initScreen == NULL)
924 return NULL;
925
926 psp = _mesa_malloc(sizeof(*psp));
927 if (!psp)
928 return NULL;
929
930 setupLoaderExtensions(psp, extensions);
931
932 psp->psc = psc;
933
934 version = drmGetVersion(fd);
935 if (version) {
936 psp->drm_version.major = version->version_major;
937 psp->drm_version.minor = version->version_minor;
938 psp->drm_version.patch = version->version_patchlevel;
939 drmFreeVersion(version);
940 }
941
942 psp->extensions = emptyExtensionList;
943 psp->fd = fd;
944 psp->myNum = scrn;
945 psp->dri2.enabled = GL_TRUE;
946
947 if (drmBOReference(psp->fd, sarea_handle, &psp->dri2.sareaBO)) {
948 fprintf(stderr, "Failed to reference DRI2 sarea BO\n");
949 _mesa_free(psp);
950 return NULL;
951 }
952
953 if (drmBOMap(psp->fd, &psp->dri2.sareaBO,
954 DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &psp->dri2.sarea)) {
955 drmBOUnreference(psp->fd, &psp->dri2.sareaBO);
956 _mesa_free(psp);
957 return NULL;
958 }
959
960 p = psp->dri2.sarea;
961 while (DRI2_SAREA_BLOCK_TYPE(*p)) {
962 switch (DRI2_SAREA_BLOCK_TYPE(*p)) {
963 case DRI2_SAREA_BLOCK_LOCK:
964 psp->dri2.lock = (__DRILock *) p;
965 break;
966 case DRI2_SAREA_BLOCK_EVENT_BUFFER:
967 psp->dri2.buffer = (__DRIEventBuffer *) p;
968 break;
969 }
970 p = DRI2_SAREA_BLOCK_NEXT(p);
971 }
972
973 psp->lock = (drmLock *) &psp->dri2.lock->lock;
974
975 psc->destroyScreen = driDestroyScreen;
976 psc->getExtensions = driGetExtensions;
977 psc->createNewDrawable = driCreateNewDrawable;
978 psc->createNewContext = driCreateNewContext;
979
980 *driver_modes = initScreen(psp);
981 if (*driver_modes == NULL) {
982 drmBOUnmap(psp->fd, &psp->dri2.sareaBO);
983 drmBOUnreference(psp->fd, &psp->dri2.sareaBO);
984 _mesa_free(psp);
985 return NULL;
986 }
987
988 return psp;
989 }
990
991 static int
992 driFrameTracking(__DRIdrawable *drawable, GLboolean enable)
993 {
994 return GLX_BAD_CONTEXT;
995 }
996
997 static int
998 driQueryFrameTracking(__DRIdrawable *drawable,
999 int64_t * sbc, int64_t * missedFrames,
1000 float * lastMissedUsage, float * usage)
1001 {
1002 __DRIswapInfo sInfo;
1003 int status;
1004 int64_t ust;
1005 __DRIdrawablePrivate * dpriv = drawable->private;
1006 __DRIscreenPrivate *psp = dpriv->driScreenPriv;
1007
1008 status = dpriv->driScreenPriv->DriverAPI.GetSwapInfo( dpriv, & sInfo );
1009 if ( status == 0 ) {
1010 *sbc = sInfo.swap_count;
1011 *missedFrames = sInfo.swap_missed_count;
1012 *lastMissedUsage = sInfo.swap_missed_usage;
1013
1014 (*psp->systemTime->getUST)( & ust );
1015 *usage = driCalculateSwapUsage( dpriv, sInfo.swap_ust, ust );
1016 }
1017
1018 return status;
1019 }
1020
1021 const __DRIframeTrackingExtension driFrameTrackingExtension = {
1022 { __DRI_FRAME_TRACKING, __DRI_FRAME_TRACKING_VERSION },
1023 driFrameTracking,
1024 driQueryFrameTracking
1025 };
1026
1027 /**
1028 * Calculate amount of swap interval used between GLX buffer swaps.
1029 *
1030 * The usage value, on the range [0,max], is the fraction of total swap
1031 * interval time used between GLX buffer swaps is calculated.
1032 *
1033 * \f$p = t_d / (i * t_r)\f$
1034 *
1035 * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
1036 * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
1037 * required for a single vertical refresh period (as returned by \c
1038 * glXGetMscRateOML).
1039 *
1040 * See the documentation for the GLX_MESA_swap_frame_usage extension for more
1041 * details.
1042 *
1043 * \param dPriv Pointer to the private drawable structure.
1044 * \return If less than a single swap interval time period was required
1045 * between GLX buffer swaps, a number greater than 0 and less than
1046 * 1.0 is returned. If exactly one swap interval time period is
1047 * required, 1.0 is returned, and if more than one is required then
1048 * a number greater than 1.0 will be returned.
1049 *
1050 * \sa glXSwapIntervalSGI glXGetMscRateOML
1051 *
1052 * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
1053 * be possible to cache the sync rate?
1054 */
1055 float
1056 driCalculateSwapUsage( __DRIdrawablePrivate *dPriv, int64_t last_swap_ust,
1057 int64_t current_ust )
1058 {
1059 int32_t n;
1060 int32_t d;
1061 int interval;
1062 float usage = 1.0;
1063 __DRIscreenPrivate *psp = dPriv->driScreenPriv;
1064
1065 if ( (*psp->systemTime->getMSCRate)(dPriv->pdraw, &n, &d) ) {
1066 interval = (dPriv->swap_interval != 0) ? dPriv->swap_interval : 1;
1067
1068
1069 /* We want to calculate
1070 * (current_UST - last_swap_UST) / (interval * us_per_refresh). We get
1071 * current_UST by calling __glXGetUST. last_swap_UST is stored in
1072 * dPriv->swap_ust. interval has already been calculated.
1073 *
1074 * The only tricky part is us_per_refresh. us_per_refresh is
1075 * 1000000 / MSC_rate. We know the MSC_rate is n / d. We can flip it
1076 * around and say us_per_refresh = 1000000 * d / n. Since this goes in
1077 * the denominator of the final calculation, we calculate
1078 * (interval * 1000000 * d) and move n into the numerator.
1079 */
1080
1081 usage = (current_ust - last_swap_ust);
1082 usage *= n;
1083 usage /= (interval * d);
1084 usage /= 1000000.0;
1085 }
1086
1087 return usage;
1088 }
1089
1090 /*@}*/