2 * Copyright © 2007, 2008 Red Hat, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Soft-
6 * ware"), to deal in the Software without restriction, including without
7 * limitation the rights to use, copy, modify, merge, publish, distribute,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, provided that the above copyright
10 * notice(s) and this permission notice appear in all copies of the Soft-
11 * ware and that both the above copyright notice(s) and this permission
12 * notice appear in supporting documentation.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16 * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
17 * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
18 * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
19 * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
22 * MANCE OF THIS SOFTWARE.
24 * Except as contained in this notice, the name of a copyright holder shall
25 * not be used in advertising or otherwise to promote the sale, use or
26 * other dealings in this Software without prior written authorization of
27 * the copyright holder.
30 * Kristian Høgsberg (krh@redhat.com)
33 #ifdef HAVE_XORG_CONFIG_H
34 #include <xorg-config.h>
41 #include "xf86Module.h"
43 #include "scrnintstr.h"
44 #include "windowstr.h"
45 #include "dixstruct.h"
48 #include "xf86VGAarbiter.h"
52 CARD8 dri2_major
; /* version of DRI2 supported by DDX */
55 uint32_t prime_id_allocate_bitmask
;
57 static DevPrivateKeyRec dri2ScreenPrivateKeyRec
;
59 #define dri2ScreenPrivateKey (&dri2ScreenPrivateKeyRec)
61 static DevPrivateKeyRec dri2WindowPrivateKeyRec
;
63 #define dri2WindowPrivateKey (&dri2WindowPrivateKeyRec)
65 static DevPrivateKeyRec dri2PixmapPrivateKeyRec
;
67 #define dri2PixmapPrivateKey (&dri2PixmapPrivateKeyRec)
69 static DevPrivateKeyRec dri2ClientPrivateKeyRec
;
71 #define dri2ClientPrivateKey (&dri2ClientPrivateKeyRec)
73 #define dri2ClientPrivate(_pClient) (dixLookupPrivate(&(_pClient)->devPrivates, \
74 dri2ClientPrivateKey))
76 typedef struct _DRI2Client
{
78 } DRI2ClientRec
, *DRI2ClientPtr
;
80 static RESTYPE dri2DrawableRes
;
82 typedef struct _DRI2Screen
*DRI2ScreenPtr
;
84 typedef struct _DRI2Drawable
{
85 DRI2ScreenPtr dri2_screen
;
87 struct xorg_list reference_list
;
90 DRI2BufferPtr
*buffers
;
92 unsigned int swapsPending
;
93 ClientPtr blockedClient
;
97 int64_t target_sbc
; /* -1 means no SBC wait outstanding */
98 CARD64 last_swap_target
; /* most recently queued swap target */
99 CARD64 last_swap_msc
; /* msc at completion of most recent swap */
100 CARD64 last_swap_ust
; /* ust at completion of most recent swap */
101 int swap_limit
; /* for N-buffering */
104 PixmapPtr prime_slave_pixmap
;
105 PixmapPtr redirectpixmap
;
106 } DRI2DrawableRec
, *DRI2DrawablePtr
;
108 typedef struct _DRI2Screen
{
111 unsigned int numDrivers
;
112 const char **driverNames
;
113 const char *deviceName
;
115 unsigned int lastSequence
;
118 DRI2CreateBufferProcPtr CreateBuffer
;
119 DRI2DestroyBufferProcPtr DestroyBuffer
;
120 DRI2CopyRegionProcPtr CopyRegion
;
121 DRI2ScheduleSwapProcPtr ScheduleSwap
;
122 DRI2GetMSCProcPtr GetMSC
;
123 DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC
;
124 DRI2AuthMagic2ProcPtr AuthMagic
;
125 DRI2AuthMagicProcPtr LegacyAuthMagic
;
126 DRI2ReuseBufferNotifyProcPtr ReuseBufferNotify
;
127 DRI2SwapLimitValidateProcPtr SwapLimitValidate
;
128 DRI2GetParamProcPtr GetParam
;
130 HandleExposuresProcPtr HandleExposures
;
132 ConfigNotifyProcPtr ConfigNotify
;
133 DRI2CreateBuffer2ProcPtr CreateBuffer2
;
134 DRI2DestroyBuffer2ProcPtr DestroyBuffer2
;
135 DRI2CopyRegion2ProcPtr CopyRegion2
;
139 destroy_buffer(DrawablePtr pDraw
, DRI2BufferPtr buffer
, int prime_id
);
142 DRI2GetScreen(ScreenPtr pScreen
)
144 return dixLookupPrivate(&pScreen
->devPrivates
, dri2ScreenPrivateKey
);
148 GetScreenPrime(ScreenPtr master
, int prime_id
)
151 if (prime_id
== 0 || xorg_list_is_empty(&master
->offload_slave_list
)) {
154 xorg_list_for_each_entry(slave
, &master
->offload_slave_list
, offload_head
) {
157 ds
= DRI2GetScreen(slave
);
158 if (ds
->prime_id
== prime_id
)
167 DRI2GetScreenPrime(ScreenPtr master
, int prime_id
)
169 ScreenPtr slave
= GetScreenPrime(master
, prime_id
);
170 return DRI2GetScreen(slave
);
173 static DRI2DrawablePtr
174 DRI2GetDrawable(DrawablePtr pDraw
)
179 switch (pDraw
->type
) {
180 case DRAWABLE_WINDOW
:
181 pWin
= (WindowPtr
) pDraw
;
182 return dixLookupPrivate(&pWin
->devPrivates
, dri2WindowPrivateKey
);
183 case DRAWABLE_PIXMAP
:
184 pPixmap
= (PixmapPtr
) pDraw
;
185 return dixLookupPrivate(&pPixmap
->devPrivates
, dri2PixmapPrivateKey
);
191 static DRI2DrawablePtr
192 DRI2AllocateDrawable(DrawablePtr pDraw
)
194 DRI2ScreenPtr ds
= DRI2GetScreen(pDraw
->pScreen
);
195 DRI2DrawablePtr pPriv
;
200 pPriv
= malloc(sizeof *pPriv
);
204 pPriv
->dri2_screen
= ds
;
205 pPriv
->drawable
= pDraw
;
206 pPriv
->width
= pDraw
->width
;
207 pPriv
->height
= pDraw
->height
;
208 pPriv
->buffers
= NULL
;
209 pPriv
->bufferCount
= 0;
210 pPriv
->swapsPending
= 0;
211 pPriv
->blockedClient
= NULL
;
212 pPriv
->blockedOnMsc
= FALSE
;
213 pPriv
->swap_count
= 0;
214 pPriv
->target_sbc
= -1;
215 pPriv
->swap_interval
= 1;
216 /* Initialize last swap target from DDX if possible */
217 if (!ds
->GetMSC
|| !(*ds
->GetMSC
) (pDraw
, &ust
, &pPriv
->last_swap_target
))
218 pPriv
->last_swap_target
= 0;
220 pPriv
->swap_limit
= 1; /* default to double buffering */
221 pPriv
->last_swap_msc
= 0;
222 pPriv
->last_swap_ust
= 0;
223 xorg_list_init(&pPriv
->reference_list
);
224 pPriv
->needInvalidate
= FALSE
;
225 pPriv
->redirectpixmap
= NULL
;
226 pPriv
->prime_slave_pixmap
= NULL
;
227 if (pDraw
->type
== DRAWABLE_WINDOW
) {
228 pWin
= (WindowPtr
) pDraw
;
229 dixSetPrivate(&pWin
->devPrivates
, dri2WindowPrivateKey
, pPriv
);
232 pPixmap
= (PixmapPtr
) pDraw
;
233 dixSetPrivate(&pPixmap
->devPrivates
, dri2PixmapPrivateKey
, pPriv
);
240 DRI2SwapLimit(DrawablePtr pDraw
, int swap_limit
)
242 DRI2DrawablePtr pPriv
= DRI2GetDrawable(pDraw
);
248 ds
= pPriv
->dri2_screen
;
250 if (!ds
->SwapLimitValidate
|| !ds
->SwapLimitValidate(pDraw
, swap_limit
))
253 pPriv
->swap_limit
= swap_limit
;
255 /* Check throttling */
256 if (pPriv
->swapsPending
>= pPriv
->swap_limit
)
259 if (pPriv
->target_sbc
== -1 && !pPriv
->blockedOnMsc
) {
260 if (pPriv
->blockedClient
) {
261 AttendClient(pPriv
->blockedClient
);
262 pPriv
->blockedClient
= NULL
;
269 typedef struct DRI2DrawableRefRec
{
272 DRI2InvalidateProcPtr invalidate
;
274 struct xorg_list link
;
275 } DRI2DrawableRefRec
, *DRI2DrawableRefPtr
;
277 static DRI2DrawableRefPtr
278 DRI2LookupDrawableRef(DRI2DrawablePtr pPriv
, XID id
)
280 DRI2DrawableRefPtr ref
;
282 xorg_list_for_each_entry(ref
, &pPriv
->reference_list
, link
) {
291 DRI2AddDrawableRef(DRI2DrawablePtr pPriv
, XID id
, XID dri2_id
,
292 DRI2InvalidateProcPtr invalidate
, void *priv
)
294 DRI2DrawableRefPtr ref
;
296 ref
= malloc(sizeof *ref
);
300 if (!AddResource(dri2_id
, dri2DrawableRes
, pPriv
)) {
304 if (!DRI2LookupDrawableRef(pPriv
, id
))
305 if (!AddResource(id
, dri2DrawableRes
, pPriv
)) {
306 FreeResourceByType(dri2_id
, dri2DrawableRes
, TRUE
);
312 ref
->dri2_id
= dri2_id
;
313 ref
->invalidate
= invalidate
;
315 xorg_list_add(&ref
->link
, &pPriv
->reference_list
);
321 DRI2CreateDrawable2(ClientPtr client
, DrawablePtr pDraw
, XID id
,
322 DRI2InvalidateProcPtr invalidate
, void *priv
,
325 DRI2DrawablePtr pPriv
;
326 DRI2ClientPtr dri2_client
= dri2ClientPrivate(client
);
330 pPriv
= DRI2GetDrawable(pDraw
);
332 pPriv
= DRI2AllocateDrawable(pDraw
);
336 pPriv
->prime_id
= dri2_client
->prime_id
;
338 dri2_id
= FakeClientID(client
->index
);
339 rc
= DRI2AddDrawableRef(pPriv
, id
, dri2_id
, invalidate
, priv
);
344 *dri2_id_out
= dri2_id
;
350 DRI2CreateDrawable(ClientPtr client
, DrawablePtr pDraw
, XID id
,
351 DRI2InvalidateProcPtr invalidate
, void *priv
)
353 return DRI2CreateDrawable2(client
, pDraw
, id
, invalidate
, priv
, NULL
);
357 DRI2DrawableGone(pointer p
, XID id
)
359 DRI2DrawablePtr pPriv
= p
;
360 DRI2DrawableRefPtr ref
, next
;
366 xorg_list_for_each_entry_safe(ref
, next
, &pPriv
->reference_list
, link
) {
367 if (ref
->dri2_id
== id
) {
368 xorg_list_del(&ref
->link
);
369 /* If this was the last ref under this X drawable XID,
370 * unregister the X drawable resource. */
371 if (!DRI2LookupDrawableRef(pPriv
, ref
->id
))
372 FreeResourceByType(ref
->id
, dri2DrawableRes
, TRUE
);
378 xorg_list_del(&ref
->link
);
379 FreeResourceByType(ref
->dri2_id
, dri2DrawableRes
, TRUE
);
384 if (!xorg_list_is_empty(&pPriv
->reference_list
))
387 pDraw
= pPriv
->drawable
;
388 if (pDraw
->type
== DRAWABLE_WINDOW
) {
389 pWin
= (WindowPtr
) pDraw
;
390 dixSetPrivate(&pWin
->devPrivates
, dri2WindowPrivateKey
, NULL
);
393 pPixmap
= (PixmapPtr
) pDraw
;
394 dixSetPrivate(&pPixmap
->devPrivates
, dri2PixmapPrivateKey
, NULL
);
397 if (pPriv
->prime_slave_pixmap
) {
398 (*pPriv
->prime_slave_pixmap
->master_pixmap
->drawable
.pScreen
->DestroyPixmap
)(pPriv
->prime_slave_pixmap
->master_pixmap
);
399 (*pPriv
->prime_slave_pixmap
->drawable
.pScreen
->DestroyPixmap
)(pPriv
->prime_slave_pixmap
);
402 if (pPriv
->buffers
!= NULL
) {
403 for (i
= 0; i
< pPriv
->bufferCount
; i
++)
404 destroy_buffer(pDraw
, pPriv
->buffers
[i
], pPriv
->prime_id
);
406 free(pPriv
->buffers
);
409 if (pPriv
->redirectpixmap
) {
410 (*pDraw
->pScreen
->ReplaceScanoutPixmap
)(pDraw
, pPriv
->redirectpixmap
, FALSE
);
411 (*pDraw
->pScreen
->DestroyPixmap
)(pPriv
->redirectpixmap
);
420 create_buffer(DrawablePtr pDraw
,
421 unsigned int attachment
, unsigned int format
)
423 ScreenPtr primeScreen
;
424 DRI2DrawablePtr pPriv
;
426 DRI2BufferPtr buffer
;
427 pPriv
= DRI2GetDrawable(pDraw
);
428 primeScreen
= GetScreenPrime(pDraw
->pScreen
, pPriv
->prime_id
);
429 ds
= DRI2GetScreenPrime(pDraw
->pScreen
, pPriv
->prime_id
);
430 if (ds
->CreateBuffer2
)
431 buffer
= (*ds
->CreateBuffer2
)(primeScreen
, pDraw
, attachment
, format
);
433 buffer
= (*ds
->CreateBuffer
)(pDraw
, attachment
, format
);
438 destroy_buffer(DrawablePtr pDraw
, DRI2BufferPtr buffer
, int prime_id
)
440 ScreenPtr primeScreen
;
442 primeScreen
= GetScreenPrime(pDraw
->pScreen
, prime_id
);
443 ds
= DRI2GetScreen(primeScreen
);
444 if (ds
->DestroyBuffer2
)
445 (*ds
->DestroyBuffer2
)(primeScreen
, pDraw
, buffer
);
447 (*ds
->DestroyBuffer
)(pDraw
, buffer
);
451 find_attachment(DRI2DrawablePtr pPriv
, unsigned attachment
)
455 if (pPriv
->buffers
== NULL
) {
459 for (i
= 0; i
< pPriv
->bufferCount
; i
++) {
460 if ((pPriv
->buffers
[i
] != NULL
)
461 && (pPriv
->buffers
[i
]->attachment
== attachment
)) {
470 allocate_or_reuse_buffer(DrawablePtr pDraw
, DRI2ScreenPtr ds
,
471 DRI2DrawablePtr pPriv
,
472 unsigned int attachment
, unsigned int format
,
473 int dimensions_match
, DRI2BufferPtr
* buffer
)
475 int old_buf
= find_attachment(pPriv
, attachment
);
478 || attachment
== DRI2BufferFrontLeft
479 || !dimensions_match
|| (pPriv
->buffers
[old_buf
]->format
!= format
)) {
480 *buffer
= create_buffer (pDraw
, attachment
, format
);
485 *buffer
= pPriv
->buffers
[old_buf
];
487 if (ds
->ReuseBufferNotify
)
488 (*ds
->ReuseBufferNotify
) (pDraw
, *buffer
);
490 pPriv
->buffers
[old_buf
] = NULL
;
496 update_dri2_drawable_buffers(DRI2DrawablePtr pPriv
, DrawablePtr pDraw
,
497 DRI2BufferPtr
* buffers
, int out_count
, int *width
,
502 if (pPriv
->buffers
!= NULL
) {
503 for (i
= 0; i
< pPriv
->bufferCount
; i
++) {
504 if (pPriv
->buffers
[i
] != NULL
) {
505 destroy_buffer(pDraw
, pPriv
->buffers
[i
], pPriv
->prime_id
);
509 free(pPriv
->buffers
);
512 pPriv
->buffers
= buffers
;
513 pPriv
->bufferCount
= out_count
;
514 pPriv
->width
= pDraw
->width
;
515 pPriv
->height
= pDraw
->height
;
516 *width
= pPriv
->width
;
517 *height
= pPriv
->height
;
520 static DRI2BufferPtr
*
521 do_get_buffers(DrawablePtr pDraw
, int *width
, int *height
,
522 unsigned int *attachments
, int count
, int *out_count
,
525 DRI2DrawablePtr pPriv
= DRI2GetDrawable(pDraw
);
527 DRI2BufferPtr
*buffers
;
528 int need_real_front
= 0;
529 int need_fake_front
= 0;
530 int have_fake_front
= 0;
531 int front_format
= 0;
532 int dimensions_match
;
533 int buffers_changed
= 0;
537 *width
= pDraw
->width
;
538 *height
= pDraw
->height
;
543 ds
= DRI2GetScreen(pDraw
->pScreen
);
545 dimensions_match
= (pDraw
->width
== pPriv
->width
)
546 && (pDraw
->height
== pPriv
->height
);
548 buffers
= calloc((count
+ 1), sizeof(buffers
[0]));
552 for (i
= 0; i
< count
; i
++) {
553 const unsigned attachment
= *(attachments
++);
554 const unsigned format
= (has_format
) ? *(attachments
++) : 0;
556 if (allocate_or_reuse_buffer(pDraw
, ds
, pPriv
, attachment
,
557 format
, dimensions_match
, &buffers
[i
]))
560 if (buffers
[i
] == NULL
)
563 /* If the drawable is a window and the front-buffer is requested,
564 * silently add the fake front-buffer to the list of requested
565 * attachments. The counting logic in the loop accounts for the case
566 * where the client requests both the fake and real front-buffer.
568 if (attachment
== DRI2BufferBackLeft
) {
570 front_format
= format
;
573 if (attachment
== DRI2BufferFrontLeft
) {
575 front_format
= format
;
577 if (pDraw
->type
== DRAWABLE_WINDOW
) {
582 if (pDraw
->type
== DRAWABLE_WINDOW
) {
583 if (attachment
== DRI2BufferFakeFrontLeft
) {
590 if (need_real_front
> 0) {
591 if (allocate_or_reuse_buffer(pDraw
, ds
, pPriv
, DRI2BufferFrontLeft
,
592 front_format
, dimensions_match
,
596 if (buffers
[i
] == NULL
)
601 if (need_fake_front
> 0) {
602 if (allocate_or_reuse_buffer(pDraw
, ds
, pPriv
, DRI2BufferFakeFrontLeft
,
603 front_format
, dimensions_match
,
607 if (buffers
[i
] == NULL
)
616 update_dri2_drawable_buffers(pPriv
, pDraw
, buffers
, *out_count
, width
,
619 /* If the client is getting a fake front-buffer, pre-fill it with the
620 * contents of the real front-buffer. This ensures correct operation of
621 * applications that call glXWaitX before calling glDrawBuffer.
623 if (have_fake_front
&& buffers_changed
) {
629 box
.x2
= pPriv
->width
;
630 box
.y2
= pPriv
->height
;
631 RegionInit(®ion
, &box
, 0);
633 DRI2CopyRegion(pDraw
, ®ion
, DRI2BufferFakeFrontLeft
,
634 DRI2BufferFrontLeft
);
637 pPriv
->needInvalidate
= TRUE
;
639 return pPriv
->buffers
;
646 for (i
= 0; i
< count
; i
++) {
647 if (buffers
[i
] != NULL
)
648 destroy_buffer(pDraw
, buffers
[i
], 0);
655 update_dri2_drawable_buffers(pPriv
, pDraw
, buffers
, *out_count
, width
,
662 DRI2GetBuffers(DrawablePtr pDraw
, int *width
, int *height
,
663 unsigned int *attachments
, int count
, int *out_count
)
665 return do_get_buffers(pDraw
, width
, height
, attachments
, count
,
670 DRI2GetBuffersWithFormat(DrawablePtr pDraw
, int *width
, int *height
,
671 unsigned int *attachments
, int count
, int *out_count
)
673 return do_get_buffers(pDraw
, width
, height
, attachments
, count
,
678 DRI2InvalidateDrawable(DrawablePtr pDraw
)
680 DRI2DrawablePtr pPriv
= DRI2GetDrawable(pDraw
);
681 DRI2DrawableRefPtr ref
;
683 if (!pPriv
|| !pPriv
->needInvalidate
)
686 pPriv
->needInvalidate
= FALSE
;
688 xorg_list_for_each_entry(ref
, &pPriv
->reference_list
, link
)
689 ref
->invalidate(pDraw
, ref
->priv
, ref
->id
);
693 * In the direct rendered case, we throttle the clients that have more
694 * than their share of outstanding swaps (and thus busy buffers) when a
695 * new GetBuffers request is received. In the AIGLX case, we allow the
696 * client to get the new buffers, but throttle when the next GLX request
697 * comes in (see __glXDRIcontextWait()).
700 DRI2ThrottleClient(ClientPtr client
, DrawablePtr pDraw
)
702 DRI2DrawablePtr pPriv
;
704 pPriv
= DRI2GetDrawable(pDraw
);
708 /* Throttle to swap limit */
709 if ((pPriv
->swapsPending
>= pPriv
->swap_limit
) && !pPriv
->blockedClient
) {
710 ResetCurrentRequest(client
);
712 IgnoreClient(client
);
713 pPriv
->blockedClient
= client
;
721 __DRI2BlockClient(ClientPtr client
, DRI2DrawablePtr pPriv
)
723 if (pPriv
->blockedClient
== NULL
) {
724 IgnoreClient(client
);
725 pPriv
->blockedClient
= client
;
730 DRI2BlockClient(ClientPtr client
, DrawablePtr pDraw
)
732 DRI2DrawablePtr pPriv
;
734 pPriv
= DRI2GetDrawable(pDraw
);
738 __DRI2BlockClient(client
, pPriv
);
739 pPriv
->blockedOnMsc
= TRUE
;
742 static inline PixmapPtr
GetDrawablePixmap(DrawablePtr drawable
)
744 if (drawable
->type
== DRAWABLE_PIXMAP
)
745 return (PixmapPtr
)drawable
;
747 struct _Window
*pWin
= (struct _Window
*)drawable
;
748 return drawable
->pScreen
->GetWindowPixmap(pWin
);
753 * A TraverseTree callback to invalidate all windows using the same
757 DRI2InvalidateWalk(WindowPtr pWin
, pointer data
)
759 if (pWin
->drawable
.pScreen
->GetWindowPixmap(pWin
) != data
)
760 return WT_DONTWALKCHILDREN
;
761 DRI2InvalidateDrawable(&pWin
->drawable
);
762 return WT_WALKCHILDREN
;
766 DRI2InvalidateDrawableAll(DrawablePtr pDraw
)
768 if (pDraw
->type
== DRAWABLE_WINDOW
) {
769 WindowPtr pWin
= (WindowPtr
) pDraw
;
770 PixmapPtr pPixmap
= pDraw
->pScreen
->GetWindowPixmap(pWin
);
773 * Find the top-most window using this pixmap
775 while (pWin
->parent
&&
776 pDraw
->pScreen
->GetWindowPixmap(pWin
->parent
) == pPixmap
)
780 * Walk the sub-tree to invalidate all of the
781 * windows using the same pixmap
783 TraverseTree(pWin
, DRI2InvalidateWalk
, pPixmap
);
784 DRI2InvalidateDrawable(&pPixmap
->drawable
);
787 DRI2InvalidateDrawable(pDraw
);
790 DrawablePtr
DRI2UpdatePrime(DrawablePtr pDraw
, DRI2BufferPtr pDest
)
792 DRI2DrawablePtr pPriv
= DRI2GetDrawable(pDraw
);
794 PixmapPtr mpix
= GetDrawablePixmap(pDraw
);
795 ScreenPtr master
, slave
;
798 master
= mpix
->drawable
.pScreen
;
800 if (pDraw
->type
== DRAWABLE_WINDOW
) {
801 WindowPtr pWin
= (WindowPtr
)pDraw
;
802 PixmapPtr pPixmap
= pDraw
->pScreen
->GetWindowPixmap(pWin
);
804 if (pDraw
->pScreen
->GetScreenPixmap(pDraw
->pScreen
) == pPixmap
) {
805 if (pPriv
->redirectpixmap
&&
806 pPriv
->redirectpixmap
->drawable
.width
== pDraw
->width
&&
807 pPriv
->redirectpixmap
->drawable
.height
== pDraw
->height
&&
808 pPriv
->redirectpixmap
->drawable
.depth
== pDraw
->depth
) {
809 mpix
= pPriv
->redirectpixmap
;
811 if (master
->ReplaceScanoutPixmap
) {
812 mpix
= (*master
->CreatePixmap
)(master
, pDraw
->width
, pDraw
->height
,
813 pDraw
->depth
, CREATE_PIXMAP_USAGE_SHARED
);
817 ret
= (*master
->ReplaceScanoutPixmap
)(pDraw
, mpix
, TRUE
);
819 (*master
->DestroyPixmap
)(mpix
);
822 pPriv
->redirectpixmap
= mpix
;
826 } else if (pPriv
->redirectpixmap
) {
827 (*master
->ReplaceScanoutPixmap
)(pDraw
, pPriv
->redirectpixmap
, FALSE
);
828 (*master
->DestroyPixmap
)(pPriv
->redirectpixmap
);
829 pPriv
->redirectpixmap
= NULL
;
833 slave
= GetScreenPrime(pDraw
->pScreen
, pPriv
->prime_id
);
835 /* check if the pixmap is still fine */
836 if (pPriv
->prime_slave_pixmap
) {
837 if (pPriv
->prime_slave_pixmap
->master_pixmap
== mpix
)
838 return &pPriv
->prime_slave_pixmap
->drawable
;
840 (*pPriv
->prime_slave_pixmap
->master_pixmap
->drawable
.pScreen
->DestroyPixmap
)(pPriv
->prime_slave_pixmap
->master_pixmap
);
841 (*slave
->DestroyPixmap
)(pPriv
->prime_slave_pixmap
);
842 pPriv
->prime_slave_pixmap
= NULL
;
846 spix
= PixmapShareToSlave(mpix
, slave
);
850 pPriv
->prime_slave_pixmap
= spix
;
852 spix
->screen_x
= mpix
->screen_x
;
853 spix
->screen_y
= mpix
->screen_y
;
856 DRI2InvalidateDrawableAll(pDraw
);
857 return &spix
->drawable
;
860 static void dri2_copy_region(DrawablePtr pDraw
, RegionPtr pRegion
,
861 DRI2BufferPtr pDest
, DRI2BufferPtr pSrc
)
863 DRI2DrawablePtr pPriv
= DRI2GetDrawable(pDraw
);
865 ScreenPtr primeScreen
;
867 primeScreen
= GetScreenPrime(pDraw
->pScreen
, pPriv
->prime_id
);
868 ds
= DRI2GetScreen(primeScreen
);
871 (*ds
->CopyRegion2
)(primeScreen
, pDraw
, pRegion
, pDest
, pSrc
);
873 (*ds
->CopyRegion
) (pDraw
, pRegion
, pDest
, pSrc
);
875 /* cause damage to the box */
876 if (pPriv
->prime_id
) {
880 box
.x2
= box
.x1
+ pDraw
->width
;
882 box
.y2
= box
.y1
+ pDraw
->height
;
883 RegionInit(®ion
, &box
, 1);
884 RegionTranslate(®ion
, pDraw
->x
, pDraw
->y
);
885 DamageRegionAppend(pDraw
, ®ion
);
886 DamageRegionProcessPending(pDraw
);
887 RegionUninit(®ion
);
892 DRI2CopyRegion(DrawablePtr pDraw
, RegionPtr pRegion
,
893 unsigned int dest
, unsigned int src
)
895 DRI2DrawablePtr pPriv
;
896 DRI2BufferPtr pDestBuffer
, pSrcBuffer
;
899 pPriv
= DRI2GetDrawable(pDraw
);
905 for (i
= 0; i
< pPriv
->bufferCount
; i
++) {
906 if (pPriv
->buffers
[i
]->attachment
== dest
)
907 pDestBuffer
= (DRI2BufferPtr
) pPriv
->buffers
[i
];
908 if (pPriv
->buffers
[i
]->attachment
== src
)
909 pSrcBuffer
= (DRI2BufferPtr
) pPriv
->buffers
[i
];
911 if (pSrcBuffer
== NULL
|| pDestBuffer
== NULL
)
914 dri2_copy_region(pDraw
, pRegion
, pDestBuffer
, pSrcBuffer
);
919 /* Can this drawable be page flipped? */
921 DRI2CanFlip(DrawablePtr pDraw
)
923 ScreenPtr pScreen
= pDraw
->pScreen
;
924 WindowPtr pWin
, pRoot
;
925 PixmapPtr pWinPixmap
, pRootPixmap
;
927 if (pDraw
->type
== DRAWABLE_PIXMAP
)
930 pRoot
= pScreen
->root
;
931 pRootPixmap
= pScreen
->GetWindowPixmap(pRoot
);
933 pWin
= (WindowPtr
) pDraw
;
934 pWinPixmap
= pScreen
->GetWindowPixmap(pWin
);
935 if (pRootPixmap
!= pWinPixmap
)
937 if (!RegionEqual(&pWin
->clipList
, &pRoot
->winSize
))
940 /* Does the window match the pixmap exactly? */
941 if (pDraw
->x
!= 0 || pDraw
->y
!= 0 ||
943 pDraw
->x
!= pWinPixmap
->screen_x
|| pDraw
->y
!= pWinPixmap
->screen_y
||
945 pDraw
->width
!= pWinPixmap
->drawable
.width
||
946 pDraw
->height
!= pWinPixmap
->drawable
.height
)
952 /* Can we do a pixmap exchange instead of a blit? */
954 DRI2CanExchange(DrawablePtr pDraw
)
960 DRI2WaitMSCComplete(ClientPtr client
, DrawablePtr pDraw
, int frame
,
961 unsigned int tv_sec
, unsigned int tv_usec
)
963 DRI2DrawablePtr pPriv
;
965 pPriv
= DRI2GetDrawable(pDraw
);
969 ProcDRI2WaitMSCReply(client
, ((CARD64
) tv_sec
* 1000000) + tv_usec
,
970 frame
, pPriv
->swap_count
);
972 if (pPriv
->blockedClient
)
973 AttendClient(pPriv
->blockedClient
);
975 pPriv
->blockedClient
= NULL
;
976 pPriv
->blockedOnMsc
= FALSE
;
980 DRI2WakeClient(ClientPtr client
, DrawablePtr pDraw
, int frame
,
981 unsigned int tv_sec
, unsigned int tv_usec
)
983 ScreenPtr pScreen
= pDraw
->pScreen
;
984 DRI2DrawablePtr pPriv
;
986 pPriv
= DRI2GetDrawable(pDraw
);
988 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
989 "[DRI2] %s: bad drawable\n", __func__
);
995 * Wake the client iff:
996 * - it was waiting on SBC
997 * - was blocked due to GLX make current
998 * - was blocked due to swap throttling
999 * - is not blocked due to an MSC wait
1001 if (pPriv
->target_sbc
!= -1 && pPriv
->target_sbc
<= pPriv
->swap_count
) {
1002 ProcDRI2WaitMSCReply(client
, ((CARD64
) tv_sec
* 1000000) + tv_usec
,
1003 frame
, pPriv
->swap_count
);
1004 pPriv
->target_sbc
= -1;
1006 AttendClient(pPriv
->blockedClient
);
1007 pPriv
->blockedClient
= NULL
;
1009 else if (pPriv
->target_sbc
== -1 && !pPriv
->blockedOnMsc
) {
1010 if (pPriv
->blockedClient
) {
1011 AttendClient(pPriv
->blockedClient
);
1012 pPriv
->blockedClient
= NULL
;
1018 DRI2SwapComplete(ClientPtr client
, DrawablePtr pDraw
, int frame
,
1019 unsigned int tv_sec
, unsigned int tv_usec
, int type
,
1020 DRI2SwapEventPtr swap_complete
, void *swap_data
)
1022 ScreenPtr pScreen
= pDraw
->pScreen
;
1023 DRI2DrawablePtr pPriv
;
1028 pPriv
= DRI2GetDrawable(pDraw
);
1029 if (pPriv
== NULL
) {
1030 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
1031 "[DRI2] %s: bad drawable\n", __func__
);
1035 pPriv
->swapsPending
--;
1036 pPriv
->swap_count
++;
1040 box
.x2
= pDraw
->width
;
1041 box
.y2
= pDraw
->height
;
1042 RegionInit(®ion
, &box
, 0);
1043 DRI2CopyRegion(pDraw
, ®ion
, DRI2BufferFakeFrontLeft
,
1044 DRI2BufferFrontLeft
);
1046 ust
= ((CARD64
) tv_sec
* 1000000) + tv_usec
;
1048 swap_complete(client
, swap_data
, type
, ust
, frame
, pPriv
->swap_count
);
1050 pPriv
->last_swap_msc
= frame
;
1051 pPriv
->last_swap_ust
= ust
;
1053 DRI2WakeClient(client
, pDraw
, frame
, tv_sec
, tv_usec
);
1057 DRI2WaitSwap(ClientPtr client
, DrawablePtr pDrawable
)
1059 DRI2DrawablePtr pPriv
= DRI2GetDrawable(pDrawable
);
1061 /* If we're currently waiting for a swap on this drawable, reset
1062 * the request and suspend the client. We only support one
1063 * blocked client per drawable. */
1064 if (pPriv
&& pPriv
->swapsPending
&& pPriv
->blockedClient
== NULL
) {
1065 ResetCurrentRequest(client
);
1067 __DRI2BlockClient(client
, pPriv
);
1077 DRI2SwapBuffers(ClientPtr client
, DrawablePtr pDraw
, CARD64 target_msc
,
1078 CARD64 divisor
, CARD64 remainder
, CARD64
* swap_target
,
1079 DRI2SwapEventPtr func
, void *data
)
1081 ScreenPtr pScreen
= pDraw
->pScreen
;
1082 DRI2ScreenPtr ds
= DRI2GetScreen(pDraw
->pScreen
);
1083 DRI2DrawablePtr pPriv
;
1084 DRI2BufferPtr pDestBuffer
= NULL
, pSrcBuffer
= NULL
;
1086 CARD64 ust
, current_msc
;
1088 pPriv
= DRI2GetDrawable(pDraw
);
1089 if (pPriv
== NULL
) {
1090 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
1091 "[DRI2] %s: bad drawable\n", __func__
);
1095 for (i
= 0; i
< pPriv
->bufferCount
; i
++) {
1096 if (pPriv
->buffers
[i
]->attachment
== DRI2BufferFrontLeft
)
1097 pDestBuffer
= (DRI2BufferPtr
) pPriv
->buffers
[i
];
1098 if (pPriv
->buffers
[i
]->attachment
== DRI2BufferBackLeft
)
1099 pSrcBuffer
= (DRI2BufferPtr
) pPriv
->buffers
[i
];
1101 if (pSrcBuffer
== NULL
|| pDestBuffer
== NULL
) {
1102 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
1103 "[DRI2] %s: drawable has no back or front?\n", __func__
);
1107 /* Old DDX or no swap interval, just blit */
1108 if (!ds
->ScheduleSwap
|| !pPriv
->swap_interval
|| pPriv
->prime_id
) {
1114 box
.x2
= pDraw
->width
;
1115 box
.y2
= pDraw
->height
;
1116 RegionInit(®ion
, &box
, 0);
1118 pPriv
->swapsPending
++;
1120 dri2_copy_region(pDraw
, ®ion
, pDestBuffer
, pSrcBuffer
);
1121 DRI2SwapComplete(client
, pDraw
, target_msc
, 0, 0, DRI2_BLIT_COMPLETE
,
1127 * In the simple glXSwapBuffers case, all params will be 0, and we just
1128 * need to schedule a swap for the last swap target + the swap interval.
1130 if (target_msc
== 0 && divisor
== 0 && remainder
== 0) {
1131 /* If the current vblank count of the drawable's crtc is lower
1132 * than the count stored in last_swap_target from a previous swap
1133 * then reinitialize last_swap_target to the current crtc's msc,
1134 * otherwise the swap will hang. This will happen if the drawable
1135 * is moved to a crtc with a lower refresh rate, or a crtc that just
1139 if (!(*ds
->GetMSC
) (pDraw
, &ust
, ¤t_msc
))
1140 pPriv
->last_swap_target
= 0;
1142 if (current_msc
< pPriv
->last_swap_target
)
1143 pPriv
->last_swap_target
= current_msc
;
1148 * Swap target for this swap is last swap target + swap interval since
1149 * we have to account for the current swap count, interval, and the
1150 * number of pending swaps.
1152 *swap_target
= pPriv
->last_swap_target
+ pPriv
->swap_interval
;
1156 /* glXSwapBuffersMscOML could have a 0 target_msc, honor it */
1157 *swap_target
= target_msc
;
1160 pPriv
->swapsPending
++;
1161 ret
= (*ds
->ScheduleSwap
) (client
, pDraw
, pDestBuffer
, pSrcBuffer
,
1162 swap_target
, divisor
, remainder
, func
, data
);
1164 pPriv
->swapsPending
--; /* didn't schedule */
1165 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
1166 "[DRI2] %s: driver failed to schedule swap\n", __func__
);
1170 pPriv
->last_swap_target
= *swap_target
;
1172 /* According to spec, return expected swapbuffers count SBC after this swap
1175 *swap_target
= pPriv
->swap_count
+ pPriv
->swapsPending
;
1177 DRI2InvalidateDrawableAll(pDraw
);
1183 DRI2SwapInterval(DrawablePtr pDrawable
, int interval
)
1185 ScreenPtr pScreen
= pDrawable
->pScreen
;
1186 DRI2DrawablePtr pPriv
= DRI2GetDrawable(pDrawable
);
1188 if (pPriv
== NULL
) {
1189 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
1190 "[DRI2] %s: bad drawable\n", __func__
);
1194 /* fixme: check against arbitrary max? */
1195 pPriv
->swap_interval
= interval
;
1199 DRI2GetMSC(DrawablePtr pDraw
, CARD64
* ust
, CARD64
* msc
, CARD64
* sbc
)
1201 ScreenPtr pScreen
= pDraw
->pScreen
;
1202 DRI2ScreenPtr ds
= DRI2GetScreen(pDraw
->pScreen
);
1203 DRI2DrawablePtr pPriv
;
1206 pPriv
= DRI2GetDrawable(pDraw
);
1207 if (pPriv
== NULL
) {
1208 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
1209 "[DRI2] %s: bad drawable\n", __func__
);
1216 *sbc
= pPriv
->swap_count
;
1221 * Spec needs to be updated to include unmapped or redirected
1225 ret
= (*ds
->GetMSC
) (pDraw
, ust
, msc
);
1229 *sbc
= pPriv
->swap_count
;
1235 DRI2WaitMSC(ClientPtr client
, DrawablePtr pDraw
, CARD64 target_msc
,
1236 CARD64 divisor
, CARD64 remainder
)
1238 DRI2ScreenPtr ds
= DRI2GetScreen(pDraw
->pScreen
);
1239 DRI2DrawablePtr pPriv
;
1242 pPriv
= DRI2GetDrawable(pDraw
);
1246 /* Old DDX just completes immediately */
1247 if (!ds
->ScheduleWaitMSC
) {
1248 DRI2WaitMSCComplete(client
, pDraw
, target_msc
, 0, 0);
1254 (*ds
->ScheduleWaitMSC
) (client
, pDraw
, target_msc
, divisor
, remainder
);
1262 DRI2WaitSBC(ClientPtr client
, DrawablePtr pDraw
, CARD64 target_sbc
)
1264 DRI2DrawablePtr pPriv
;
1266 pPriv
= DRI2GetDrawable(pDraw
);
1270 /* target_sbc == 0 means to block until all pending swaps are
1271 * finished. Recalculate target_sbc to get that behaviour.
1273 if (target_sbc
== 0)
1274 target_sbc
= pPriv
->swap_count
+ pPriv
->swapsPending
;
1276 /* If current swap count already >= target_sbc, reply and
1277 * return immediately with (ust, msc, sbc) triplet of
1278 * most recent completed swap.
1280 if (pPriv
->swap_count
>= target_sbc
) {
1281 ProcDRI2WaitMSCReply(client
, pPriv
->last_swap_ust
,
1282 pPriv
->last_swap_msc
, pPriv
->swap_count
);
1286 pPriv
->target_sbc
= target_sbc
;
1287 __DRI2BlockClient(client
, pPriv
);
1293 DRI2HasSwapControl(ScreenPtr pScreen
)
1295 DRI2ScreenPtr ds
= DRI2GetScreen(pScreen
);
1297 return ds
->ScheduleSwap
&& ds
->GetMSC
;
1301 DRI2Connect(ClientPtr client
, ScreenPtr pScreen
,
1302 unsigned int driverType
, int *fd
,
1303 const char **driverName
, const char **deviceName
)
1306 uint32_t prime_id
= DRI2DriverPrimeId(driverType
);
1307 uint32_t driver_id
= driverType
& 0xffff;
1309 if (!dixPrivateKeyRegistered(dri2ScreenPrivateKey
))
1312 ds
= DRI2GetScreenPrime(pScreen
, prime_id
);
1316 if (driver_id
>= ds
->numDrivers
||
1317 !ds
->driverNames
[driver_id
])
1320 *driverName
= ds
->driverNames
[driver_id
];
1321 *deviceName
= ds
->deviceName
;
1325 DRI2ClientPtr dri2_client
;
1326 dri2_client
= dri2ClientPrivate(client
);
1327 dri2_client
->prime_id
= prime_id
;
1334 DRI2AuthMagic (ScreenPtr pScreen
, uint32_t magic
)
1336 DRI2ScreenPtr ds
= DRI2GetScreen(pScreen
);
1340 return (*ds
->LegacyAuthMagic
) (ds
->fd
, magic
);
1344 DRI2Authenticate(ClientPtr client
, ScreenPtr pScreen
, uint32_t magic
)
1347 DRI2ClientPtr dri2_client
= dri2ClientPrivate(client
);
1348 ScreenPtr primescreen
;
1350 ds
= DRI2GetScreenPrime(pScreen
, dri2_client
->prime_id
);
1354 primescreen
= GetScreenPrime(pScreen
, dri2_client
->prime_id
);
1355 if ((*ds
->AuthMagic
)(primescreen
, magic
))
1361 DRI2ConfigNotify(WindowPtr pWin
, int x
, int y
, int w
, int h
, int bw
,
1364 DrawablePtr pDraw
= (DrawablePtr
) pWin
;
1365 ScreenPtr pScreen
= pDraw
->pScreen
;
1366 DRI2ScreenPtr ds
= DRI2GetScreen(pScreen
);
1367 DRI2DrawablePtr dd
= DRI2GetDrawable(pDraw
);
1370 if (ds
->ConfigNotify
) {
1371 pScreen
->ConfigNotify
= ds
->ConfigNotify
;
1373 ret
= (*pScreen
->ConfigNotify
) (pWin
, x
, y
, w
, h
, bw
, pSib
);
1375 ds
->ConfigNotify
= pScreen
->ConfigNotify
;
1376 pScreen
->ConfigNotify
= DRI2ConfigNotify
;
1381 if (!dd
|| (dd
->width
== w
&& dd
->height
== h
))
1384 DRI2InvalidateDrawable(pDraw
);
1388 #define MAX_PRIME DRI2DriverPrimeMask
1393 /* start at 1, prime id 0 is just normal driver */
1394 for (i
= 1; i
< MAX_PRIME
; i
++) {
1395 if (prime_id_allocate_bitmask
& (1 << i
))
1398 prime_id_allocate_bitmask
|= (1 << i
);
1405 DRI2ScreenInit(ScreenPtr pScreen
, DRI2InfoPtr info
)
1409 const char *driverTypeNames
[] = {
1410 "DRI", /* DRI2DriverDRI */
1411 "VDPAU", /* DRI2DriverVDPAU */
1416 if (info
->version
< 3)
1419 if (!xf86VGAarbiterAllowDRI(pScreen
)) {
1420 xf86DrvMsg(pScreen
->myNum
, X_WARNING
,
1421 "[DRI2] Direct rendering is not supported when VGA arb is necessary for the device\n");
1425 if (!dixRegisterPrivateKey(&dri2ScreenPrivateKeyRec
, PRIVATE_SCREEN
, 0))
1428 if (!dixRegisterPrivateKey(&dri2WindowPrivateKeyRec
, PRIVATE_WINDOW
, 0))
1431 if (!dixRegisterPrivateKey(&dri2PixmapPrivateKeyRec
, PRIVATE_PIXMAP
, 0))
1434 if (!dixRegisterPrivateKey(&dri2ClientPrivateKeyRec
, PRIVATE_CLIENT
, sizeof(DRI2ClientRec
)))
1437 ds
= calloc(1, sizeof *ds
);
1441 ds
->screen
= pScreen
;
1443 ds
->deviceName
= info
->deviceName
;
1446 ds
->CreateBuffer
= info
->CreateBuffer
;
1447 ds
->DestroyBuffer
= info
->DestroyBuffer
;
1448 ds
->CopyRegion
= info
->CopyRegion
;
1450 if (info
->version
>= 4) {
1451 ds
->ScheduleSwap
= info
->ScheduleSwap
;
1452 ds
->ScheduleWaitMSC
= info
->ScheduleWaitMSC
;
1453 ds
->GetMSC
= info
->GetMSC
;
1460 if (info
->version
>= 8) {
1461 ds
->AuthMagic
= info
->AuthMagic2
;
1463 if (info
->version
>= 5) {
1464 ds
->LegacyAuthMagic
= info
->AuthMagic
;
1467 if (info
->version
>= 6) {
1468 ds
->ReuseBufferNotify
= info
->ReuseBufferNotify
;
1469 ds
->SwapLimitValidate
= info
->SwapLimitValidate
;
1472 if (info
->version
>= 7) {
1473 ds
->GetParam
= info
->GetParam
;
1477 if (info
->version
>= 9) {
1478 ds
->CreateBuffer2
= info
->CreateBuffer2
;
1479 if (info
->CreateBuffer2
&& pScreen
->isGPU
) {
1480 ds
->prime_id
= get_prime_id();
1481 if (ds
->prime_id
== -1) {
1486 ds
->DestroyBuffer2
= info
->DestroyBuffer2
;
1487 ds
->CopyRegion2
= info
->CopyRegion2
;
1491 * if the driver doesn't provide an AuthMagic function or the info struct
1492 * version is too low, call through LegacyAuthMagic
1494 if (!ds
->AuthMagic
) {
1495 ds
->AuthMagic
= DRI2AuthMagic
;
1497 * If the driver doesn't provide an AuthMagic function
1498 * it relies on the old method (using libdrm) or fails
1500 if (!ds
->LegacyAuthMagic
)
1502 ds
->LegacyAuthMagic
= drmAuthMagic
;
1508 /* Initialize minor if needed and set to minimum provied by DDX */
1509 if (!dri2_minor
|| dri2_minor
> cur_minor
)
1510 dri2_minor
= cur_minor
;
1512 if (info
->version
== 3 || info
->numDrivers
== 0) {
1513 /* Driver too old: use the old-style driverName field */
1515 ds
->driverNames
= malloc(sizeof(*ds
->driverNames
));
1516 if (!ds
->driverNames
)
1518 ds
->driverNames
[0] = info
->driverName
;
1521 ds
->numDrivers
= info
->numDrivers
;
1522 ds
->driverNames
= malloc(info
->numDrivers
* sizeof(*ds
->driverNames
));
1523 if (!ds
->driverNames
)
1525 memcpy(ds
->driverNames
, info
->driverNames
,
1526 info
->numDrivers
* sizeof(*ds
->driverNames
));
1529 dixSetPrivate(&pScreen
->devPrivates
, dri2ScreenPrivateKey
, ds
);
1531 ds
->ConfigNotify
= pScreen
->ConfigNotify
;
1532 pScreen
->ConfigNotify
= DRI2ConfigNotify
;
1534 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[DRI2] Setup complete\n");
1535 for (i
= 0; i
< sizeof(driverTypeNames
) / sizeof(driverTypeNames
[0]); i
++) {
1536 if (i
< ds
->numDrivers
&& ds
->driverNames
[i
]) {
1537 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[DRI2] %s driver: %s\n",
1538 driverTypeNames
[i
], ds
->driverNames
[i
]);
1545 xf86DrvMsg(pScreen
->myNum
, X_WARNING
,
1546 "[DRI2] Initialization failed for info version %d.\n",
1553 DRI2CloseScreen(ScreenPtr pScreen
)
1555 DRI2ScreenPtr ds
= DRI2GetScreen(pScreen
);
1557 pScreen
->ConfigNotify
= ds
->ConfigNotify
;
1560 prime_id_allocate_bitmask
&= ~(1 << ds
->prime_id
);
1561 free(ds
->driverNames
);
1563 dixSetPrivate(&pScreen
->devPrivates
, dri2ScreenPrivateKey
, NULL
);
1566 extern Bool
DRI2ModuleSetup(void);
1568 /* Called by InitExtensions() */
1570 DRI2ModuleSetup(void)
1572 dri2DrawableRes
= CreateNewResourceType(DRI2DrawableGone
, "DRI2Drawable");
1573 if (!dri2DrawableRes
)
1580 DRI2Version(int *major
, int *minor
)
1590 DRI2GetParam(ClientPtr client
,
1591 DrawablePtr drawable
,
1593 BOOL
*is_param_recognized
,
1596 DRI2ScreenPtr ds
= DRI2GetScreen(drawable
->pScreen
);
1597 char high_byte
= (param
>> 24);
1599 switch (high_byte
) {
1601 /* Parameter names whose high_byte is 0 are reserved for the X
1602 * server. The server currently recognizes no parameters.
1604 goto not_recognized
;
1606 /* Parameter names whose high byte is 1 are reserved for the DDX. */
1608 return ds
->GetParam(client
, drawable
, param
,
1609 is_param_recognized
, value
);
1611 goto not_recognized
;
1613 /* Other parameter names are reserved for future use. They are never
1616 goto not_recognized
;
1620 *is_param_recognized
= FALSE
;