xref: /OK3568_Linux_fs/external/xserver/hw/xfree86/dri2/dri2.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright © 2007, 2008 Red Hat, Inc.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining a
5*4882a593Smuzhiyun  * copy of this software and associated documentation files (the "Soft-
6*4882a593Smuzhiyun  * ware"), to deal in the Software without restriction, including without
7*4882a593Smuzhiyun  * limitation the rights to use, copy, modify, merge, publish, distribute,
8*4882a593Smuzhiyun  * and/or sell copies of the Software, and to permit persons to whom the
9*4882a593Smuzhiyun  * Software is furnished to do so, provided that the above copyright
10*4882a593Smuzhiyun  * notice(s) and this permission notice appear in all copies of the Soft-
11*4882a593Smuzhiyun  * ware and that both the above copyright notice(s) and this permission
12*4882a593Smuzhiyun  * notice appear in supporting documentation.
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15*4882a593Smuzhiyun  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16*4882a593Smuzhiyun  * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
17*4882a593Smuzhiyun  * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
18*4882a593Smuzhiyun  * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
19*4882a593Smuzhiyun  * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20*4882a593Smuzhiyun  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21*4882a593Smuzhiyun  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
22*4882a593Smuzhiyun  * MANCE OF THIS SOFTWARE.
23*4882a593Smuzhiyun  *
24*4882a593Smuzhiyun  * Except as contained in this notice, the name of a copyright holder shall
25*4882a593Smuzhiyun  * not be used in advertising or otherwise to promote the sale, use or
26*4882a593Smuzhiyun  * other dealings in this Software without prior written authorization of
27*4882a593Smuzhiyun  * the copyright holder.
28*4882a593Smuzhiyun  *
29*4882a593Smuzhiyun  * Authors:
30*4882a593Smuzhiyun  *   Kristian Høgsberg (krh@redhat.com)
31*4882a593Smuzhiyun  */
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #ifdef HAVE_XORG_CONFIG_H
34*4882a593Smuzhiyun #include <xorg-config.h>
35*4882a593Smuzhiyun #endif
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #include <errno.h>
38*4882a593Smuzhiyun #ifdef WITH_LIBDRM
39*4882a593Smuzhiyun #include <xf86drm.h>
40*4882a593Smuzhiyun #endif
41*4882a593Smuzhiyun #include "xf86Module.h"
42*4882a593Smuzhiyun #include "list.h"
43*4882a593Smuzhiyun #include "scrnintstr.h"
44*4882a593Smuzhiyun #include "windowstr.h"
45*4882a593Smuzhiyun #include "dixstruct.h"
46*4882a593Smuzhiyun #include "dri2.h"
47*4882a593Smuzhiyun #include "dri2int.h"
48*4882a593Smuzhiyun #include "xf86VGAarbiter.h"
49*4882a593Smuzhiyun #include "damage.h"
50*4882a593Smuzhiyun #include "xf86.h"
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun CARD8 dri2_major;               /* version of DRI2 supported by DDX */
53*4882a593Smuzhiyun CARD8 dri2_minor;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun uint32_t prime_id_allocate_bitmask;
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun static DevPrivateKeyRec dri2ScreenPrivateKeyRec;
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun #define dri2ScreenPrivateKey (&dri2ScreenPrivateKeyRec)
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun static DevPrivateKeyRec dri2WindowPrivateKeyRec;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun #define dri2WindowPrivateKey (&dri2WindowPrivateKeyRec)
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun static DevPrivateKeyRec dri2PixmapPrivateKeyRec;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun #define dri2PixmapPrivateKey (&dri2PixmapPrivateKeyRec)
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun static DevPrivateKeyRec dri2ClientPrivateKeyRec;
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun #define dri2ClientPrivateKey (&dri2ClientPrivateKeyRec)
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun #define dri2ClientPrivate(_pClient) (dixLookupPrivate(&(_pClient)->devPrivates, \
74*4882a593Smuzhiyun                                                       dri2ClientPrivateKey))
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun typedef struct _DRI2Client {
77*4882a593Smuzhiyun     int prime_id;
78*4882a593Smuzhiyun } DRI2ClientRec, *DRI2ClientPtr;
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun static RESTYPE dri2DrawableRes;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun typedef struct _DRI2Screen *DRI2ScreenPtr;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun typedef struct _DRI2Drawable {
85*4882a593Smuzhiyun     DRI2ScreenPtr dri2_screen;
86*4882a593Smuzhiyun     DrawablePtr drawable;
87*4882a593Smuzhiyun     struct xorg_list reference_list;
88*4882a593Smuzhiyun     int width;
89*4882a593Smuzhiyun     int height;
90*4882a593Smuzhiyun     DRI2BufferPtr *buffers;
91*4882a593Smuzhiyun     int bufferCount;
92*4882a593Smuzhiyun     unsigned int swapsPending;
93*4882a593Smuzhiyun     int swap_interval;
94*4882a593Smuzhiyun     CARD64 swap_count;
95*4882a593Smuzhiyun     int64_t target_sbc;         /* -1 means no SBC wait outstanding */
96*4882a593Smuzhiyun     CARD64 last_swap_target;    /* most recently queued swap target */
97*4882a593Smuzhiyun     CARD64 last_swap_msc;       /* msc at completion of most recent swap */
98*4882a593Smuzhiyun     CARD64 last_swap_ust;       /* ust at completion of most recent swap */
99*4882a593Smuzhiyun     int swap_limit;             /* for N-buffering */
100*4882a593Smuzhiyun     unsigned blocked[3];
101*4882a593Smuzhiyun     Bool needInvalidate;
102*4882a593Smuzhiyun     int prime_id;
103*4882a593Smuzhiyun     PixmapPtr prime_slave_pixmap;
104*4882a593Smuzhiyun     PixmapPtr redirectpixmap;
105*4882a593Smuzhiyun } DRI2DrawableRec, *DRI2DrawablePtr;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun typedef struct _DRI2Screen {
108*4882a593Smuzhiyun     ScreenPtr screen;
109*4882a593Smuzhiyun     int refcnt;
110*4882a593Smuzhiyun     unsigned int numDrivers;
111*4882a593Smuzhiyun     const char **driverNames;
112*4882a593Smuzhiyun     const char *deviceName;
113*4882a593Smuzhiyun     const char *driverName;
114*4882a593Smuzhiyun     int fd;
115*4882a593Smuzhiyun     unsigned int lastSequence;
116*4882a593Smuzhiyun     int prime_id;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun     DRI2CreateBufferProcPtr CreateBuffer;
119*4882a593Smuzhiyun     DRI2DestroyBufferProcPtr DestroyBuffer;
120*4882a593Smuzhiyun     DRI2CopyRegionProcPtr CopyRegion;
121*4882a593Smuzhiyun     DRI2ScheduleSwapProcPtr ScheduleSwap;
122*4882a593Smuzhiyun     DRI2GetMSCProcPtr GetMSC;
123*4882a593Smuzhiyun     DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC;
124*4882a593Smuzhiyun     DRI2AuthMagic2ProcPtr AuthMagic;
125*4882a593Smuzhiyun     DRI2AuthMagicProcPtr LegacyAuthMagic;
126*4882a593Smuzhiyun     DRI2ReuseBufferNotifyProcPtr ReuseBufferNotify;
127*4882a593Smuzhiyun     DRI2SwapLimitValidateProcPtr SwapLimitValidate;
128*4882a593Smuzhiyun     DRI2GetParamProcPtr GetParam;
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun     HandleExposuresProcPtr HandleExposures;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun     ConfigNotifyProcPtr ConfigNotify;
133*4882a593Smuzhiyun     SetWindowPixmapProcPtr SetWindowPixmap;
134*4882a593Smuzhiyun     DRI2CreateBuffer2ProcPtr CreateBuffer2;
135*4882a593Smuzhiyun     DRI2DestroyBuffer2ProcPtr DestroyBuffer2;
136*4882a593Smuzhiyun     DRI2CopyRegion2ProcPtr CopyRegion2;
137*4882a593Smuzhiyun } DRI2ScreenRec;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun static void
140*4882a593Smuzhiyun destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, int prime_id);
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun enum DRI2WakeType {
143*4882a593Smuzhiyun     WAKE_SBC,
144*4882a593Smuzhiyun     WAKE_MSC,
145*4882a593Smuzhiyun     WAKE_SWAP,
146*4882a593Smuzhiyun };
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun #define Wake(c, t) (void *)((uintptr_t)(c) | (t))
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun static Bool
dri2WakeClient(ClientPtr client,void * closure)151*4882a593Smuzhiyun dri2WakeClient(ClientPtr client, void *closure)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun     ClientWakeup(client);
154*4882a593Smuzhiyun     return TRUE;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun static Bool
dri2WakeAll(ClientPtr client,DRI2DrawablePtr pPriv,enum DRI2WakeType t)158*4882a593Smuzhiyun dri2WakeAll(ClientPtr client, DRI2DrawablePtr pPriv, enum DRI2WakeType t)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun     int count;
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun     if (!pPriv->blocked[t])
163*4882a593Smuzhiyun         return FALSE;
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun     count = ClientSignalAll(client, dri2WakeClient, Wake(pPriv, t));
166*4882a593Smuzhiyun     pPriv->blocked[t] -= count;
167*4882a593Smuzhiyun     return count;
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun static Bool
dri2Sleep(ClientPtr client,DRI2DrawablePtr pPriv,enum DRI2WakeType t)171*4882a593Smuzhiyun dri2Sleep(ClientPtr client, DRI2DrawablePtr pPriv, enum DRI2WakeType t)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun     if (ClientSleep(client, dri2WakeClient, Wake(pPriv, t))) {
174*4882a593Smuzhiyun         pPriv->blocked[t]++;
175*4882a593Smuzhiyun         return TRUE;
176*4882a593Smuzhiyun     }
177*4882a593Smuzhiyun     return FALSE;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun static DRI2ScreenPtr
DRI2GetScreen(ScreenPtr pScreen)181*4882a593Smuzhiyun DRI2GetScreen(ScreenPtr pScreen)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun     return dixLookupPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey);
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun static ScreenPtr
GetScreenPrime(ScreenPtr master,int prime_id)187*4882a593Smuzhiyun GetScreenPrime(ScreenPtr master, int prime_id)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun     ScreenPtr slave;
190*4882a593Smuzhiyun     if (prime_id == 0) {
191*4882a593Smuzhiyun         return master;
192*4882a593Smuzhiyun     }
193*4882a593Smuzhiyun     xorg_list_for_each_entry(slave, &master->slave_list, slave_head) {
194*4882a593Smuzhiyun         DRI2ScreenPtr ds;
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun         if (!slave->is_offload_slave)
197*4882a593Smuzhiyun             continue;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun         ds = DRI2GetScreen(slave);
200*4882a593Smuzhiyun         if (ds == NULL)
201*4882a593Smuzhiyun             continue;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun         if (ds->prime_id == prime_id)
204*4882a593Smuzhiyun             return slave;
205*4882a593Smuzhiyun     }
206*4882a593Smuzhiyun     return master;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun static DRI2ScreenPtr
DRI2GetScreenPrime(ScreenPtr master,int prime_id)210*4882a593Smuzhiyun DRI2GetScreenPrime(ScreenPtr master, int prime_id)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun     ScreenPtr slave = GetScreenPrime(master, prime_id);
213*4882a593Smuzhiyun     return DRI2GetScreen(slave);
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun static DRI2DrawablePtr
DRI2GetDrawable(DrawablePtr pDraw)217*4882a593Smuzhiyun DRI2GetDrawable(DrawablePtr pDraw)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun     WindowPtr pWin;
220*4882a593Smuzhiyun     PixmapPtr pPixmap;
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun     switch (pDraw->type) {
223*4882a593Smuzhiyun     case DRAWABLE_WINDOW:
224*4882a593Smuzhiyun         pWin = (WindowPtr) pDraw;
225*4882a593Smuzhiyun         return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
226*4882a593Smuzhiyun     case DRAWABLE_PIXMAP:
227*4882a593Smuzhiyun         pPixmap = (PixmapPtr) pDraw;
228*4882a593Smuzhiyun         return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
229*4882a593Smuzhiyun     default:
230*4882a593Smuzhiyun         return NULL;
231*4882a593Smuzhiyun     }
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun static DRI2DrawablePtr
DRI2AllocateDrawable(DrawablePtr pDraw)235*4882a593Smuzhiyun DRI2AllocateDrawable(DrawablePtr pDraw)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun     DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
238*4882a593Smuzhiyun     DRI2DrawablePtr pPriv;
239*4882a593Smuzhiyun     CARD64 ust;
240*4882a593Smuzhiyun     WindowPtr pWin;
241*4882a593Smuzhiyun     PixmapPtr pPixmap;
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun     pPriv = malloc(sizeof *pPriv);
244*4882a593Smuzhiyun     if (pPriv == NULL)
245*4882a593Smuzhiyun         return NULL;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun     pPriv->dri2_screen = ds;
248*4882a593Smuzhiyun     pPriv->drawable = pDraw;
249*4882a593Smuzhiyun     pPriv->width = pDraw->width;
250*4882a593Smuzhiyun     pPriv->height = pDraw->height;
251*4882a593Smuzhiyun     pPriv->buffers = NULL;
252*4882a593Smuzhiyun     pPriv->bufferCount = 0;
253*4882a593Smuzhiyun     pPriv->swapsPending = 0;
254*4882a593Smuzhiyun     pPriv->swap_count = 0;
255*4882a593Smuzhiyun     pPriv->target_sbc = -1;
256*4882a593Smuzhiyun     pPriv->swap_interval = 1;
257*4882a593Smuzhiyun     /* Initialize last swap target from DDX if possible */
258*4882a593Smuzhiyun     if (!ds->GetMSC || !(*ds->GetMSC) (pDraw, &ust, &pPriv->last_swap_target))
259*4882a593Smuzhiyun         pPriv->last_swap_target = 0;
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun     memset(pPriv->blocked, 0, sizeof(pPriv->blocked));
262*4882a593Smuzhiyun     pPriv->swap_limit = 1;      /* default to double buffering */
263*4882a593Smuzhiyun     pPriv->last_swap_msc = 0;
264*4882a593Smuzhiyun     pPriv->last_swap_ust = 0;
265*4882a593Smuzhiyun     xorg_list_init(&pPriv->reference_list);
266*4882a593Smuzhiyun     pPriv->needInvalidate = FALSE;
267*4882a593Smuzhiyun     pPriv->redirectpixmap = NULL;
268*4882a593Smuzhiyun     pPriv->prime_slave_pixmap = NULL;
269*4882a593Smuzhiyun     if (pDraw->type == DRAWABLE_WINDOW) {
270*4882a593Smuzhiyun         pWin = (WindowPtr) pDraw;
271*4882a593Smuzhiyun         dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv);
272*4882a593Smuzhiyun     }
273*4882a593Smuzhiyun     else {
274*4882a593Smuzhiyun         pPixmap = (PixmapPtr) pDraw;
275*4882a593Smuzhiyun         dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv);
276*4882a593Smuzhiyun     }
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun     return pPriv;
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun Bool
DRI2SwapLimit(DrawablePtr pDraw,int swap_limit)282*4882a593Smuzhiyun DRI2SwapLimit(DrawablePtr pDraw, int swap_limit)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun     DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
285*4882a593Smuzhiyun     DRI2ScreenPtr ds;
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun     if (!pPriv)
288*4882a593Smuzhiyun         return FALSE;
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun     ds = pPriv->dri2_screen;
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun     if (!ds->SwapLimitValidate || !ds->SwapLimitValidate(pDraw, swap_limit))
293*4882a593Smuzhiyun         return FALSE;
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun     pPriv->swap_limit = swap_limit;
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun     /* Check throttling */
298*4882a593Smuzhiyun     if (pPriv->swapsPending >= pPriv->swap_limit)
299*4882a593Smuzhiyun         return TRUE;
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun     dri2WakeAll(CLIENT_SIGNAL_ANY, pPriv, WAKE_SWAP);
302*4882a593Smuzhiyun     return TRUE;
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun typedef struct DRI2DrawableRefRec {
306*4882a593Smuzhiyun     XID id;
307*4882a593Smuzhiyun     XID dri2_id;
308*4882a593Smuzhiyun     DRI2InvalidateProcPtr invalidate;
309*4882a593Smuzhiyun     void *priv;
310*4882a593Smuzhiyun     struct xorg_list link;
311*4882a593Smuzhiyun } DRI2DrawableRefRec, *DRI2DrawableRefPtr;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun static DRI2DrawableRefPtr
DRI2LookupDrawableRef(DRI2DrawablePtr pPriv,XID id)314*4882a593Smuzhiyun DRI2LookupDrawableRef(DRI2DrawablePtr pPriv, XID id)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun     DRI2DrawableRefPtr ref;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun     xorg_list_for_each_entry(ref, &pPriv->reference_list, link) {
319*4882a593Smuzhiyun         if (ref->id == id)
320*4882a593Smuzhiyun             return ref;
321*4882a593Smuzhiyun     }
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun     return NULL;
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun static int
DRI2AddDrawableRef(DRI2DrawablePtr pPriv,XID id,XID dri2_id,DRI2InvalidateProcPtr invalidate,void * priv)327*4882a593Smuzhiyun DRI2AddDrawableRef(DRI2DrawablePtr pPriv, XID id, XID dri2_id,
328*4882a593Smuzhiyun                    DRI2InvalidateProcPtr invalidate, void *priv)
329*4882a593Smuzhiyun {
330*4882a593Smuzhiyun     DRI2DrawableRefPtr ref;
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun     ref = malloc(sizeof *ref);
333*4882a593Smuzhiyun     if (ref == NULL)
334*4882a593Smuzhiyun         return BadAlloc;
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun     if (!AddResource(dri2_id, dri2DrawableRes, pPriv)) {
337*4882a593Smuzhiyun         free(ref);
338*4882a593Smuzhiyun         return BadAlloc;
339*4882a593Smuzhiyun     }
340*4882a593Smuzhiyun     if (!DRI2LookupDrawableRef(pPriv, id))
341*4882a593Smuzhiyun         if (!AddResource(id, dri2DrawableRes, pPriv)) {
342*4882a593Smuzhiyun             FreeResourceByType(dri2_id, dri2DrawableRes, TRUE);
343*4882a593Smuzhiyun             free(ref);
344*4882a593Smuzhiyun             return BadAlloc;
345*4882a593Smuzhiyun         }
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun     ref->id = id;
348*4882a593Smuzhiyun     ref->dri2_id = dri2_id;
349*4882a593Smuzhiyun     ref->invalidate = invalidate;
350*4882a593Smuzhiyun     ref->priv = priv;
351*4882a593Smuzhiyun     xorg_list_add(&ref->link, &pPriv->reference_list);
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun     return Success;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun int
DRI2CreateDrawable2(ClientPtr client,DrawablePtr pDraw,XID id,DRI2InvalidateProcPtr invalidate,void * priv,XID * dri2_id_out)357*4882a593Smuzhiyun DRI2CreateDrawable2(ClientPtr client, DrawablePtr pDraw, XID id,
358*4882a593Smuzhiyun                     DRI2InvalidateProcPtr invalidate, void *priv,
359*4882a593Smuzhiyun                     XID *dri2_id_out)
360*4882a593Smuzhiyun {
361*4882a593Smuzhiyun     DRI2DrawablePtr pPriv;
362*4882a593Smuzhiyun     DRI2ClientPtr dri2_client = dri2ClientPrivate(client);
363*4882a593Smuzhiyun     XID dri2_id;
364*4882a593Smuzhiyun     int rc;
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun     pPriv = DRI2GetDrawable(pDraw);
367*4882a593Smuzhiyun     if (pPriv == NULL)
368*4882a593Smuzhiyun         pPriv = DRI2AllocateDrawable(pDraw);
369*4882a593Smuzhiyun     if (pPriv == NULL)
370*4882a593Smuzhiyun         return BadAlloc;
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun     pPriv->prime_id = dri2_client->prime_id;
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun     dri2_id = FakeClientID(client->index);
375*4882a593Smuzhiyun     rc = DRI2AddDrawableRef(pPriv, id, dri2_id, invalidate, priv);
376*4882a593Smuzhiyun     if (rc != Success)
377*4882a593Smuzhiyun         return rc;
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun     if (dri2_id_out)
380*4882a593Smuzhiyun         *dri2_id_out = dri2_id;
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun     return Success;
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun int
DRI2CreateDrawable(ClientPtr client,DrawablePtr pDraw,XID id,DRI2InvalidateProcPtr invalidate,void * priv)386*4882a593Smuzhiyun DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id,
387*4882a593Smuzhiyun                    DRI2InvalidateProcPtr invalidate, void *priv)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun     return DRI2CreateDrawable2(client, pDraw, id, invalidate, priv, NULL);
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun static int
DRI2DrawableGone(void * p,XID id)393*4882a593Smuzhiyun DRI2DrawableGone(void *p, XID id)
394*4882a593Smuzhiyun {
395*4882a593Smuzhiyun     DRI2DrawablePtr pPriv = p;
396*4882a593Smuzhiyun     DRI2DrawableRefPtr ref, next;
397*4882a593Smuzhiyun     WindowPtr pWin;
398*4882a593Smuzhiyun     PixmapPtr pPixmap;
399*4882a593Smuzhiyun     DrawablePtr pDraw;
400*4882a593Smuzhiyun     int i;
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun     xorg_list_for_each_entry_safe(ref, next, &pPriv->reference_list, link) {
403*4882a593Smuzhiyun         if (ref->dri2_id == id) {
404*4882a593Smuzhiyun             xorg_list_del(&ref->link);
405*4882a593Smuzhiyun             /* If this was the last ref under this X drawable XID,
406*4882a593Smuzhiyun              * unregister the X drawable resource. */
407*4882a593Smuzhiyun             if (!DRI2LookupDrawableRef(pPriv, ref->id))
408*4882a593Smuzhiyun                 FreeResourceByType(ref->id, dri2DrawableRes, TRUE);
409*4882a593Smuzhiyun             free(ref);
410*4882a593Smuzhiyun             break;
411*4882a593Smuzhiyun         }
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun         if (ref->id == id) {
414*4882a593Smuzhiyun             xorg_list_del(&ref->link);
415*4882a593Smuzhiyun             FreeResourceByType(ref->dri2_id, dri2DrawableRes, TRUE);
416*4882a593Smuzhiyun             free(ref);
417*4882a593Smuzhiyun         }
418*4882a593Smuzhiyun     }
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun     if (!xorg_list_is_empty(&pPriv->reference_list))
421*4882a593Smuzhiyun         return Success;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun     pDraw = pPriv->drawable;
424*4882a593Smuzhiyun     if (pDraw->type == DRAWABLE_WINDOW) {
425*4882a593Smuzhiyun         pWin = (WindowPtr) pDraw;
426*4882a593Smuzhiyun         dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
427*4882a593Smuzhiyun     }
428*4882a593Smuzhiyun     else {
429*4882a593Smuzhiyun         pPixmap = (PixmapPtr) pDraw;
430*4882a593Smuzhiyun         dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
431*4882a593Smuzhiyun     }
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun     if (pPriv->prime_slave_pixmap) {
434*4882a593Smuzhiyun         (*pPriv->prime_slave_pixmap->master_pixmap->drawable.pScreen->DestroyPixmap)(pPriv->prime_slave_pixmap->master_pixmap);
435*4882a593Smuzhiyun         (*pPriv->prime_slave_pixmap->drawable.pScreen->DestroyPixmap)(pPriv->prime_slave_pixmap);
436*4882a593Smuzhiyun     }
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun     if (pPriv->buffers != NULL) {
439*4882a593Smuzhiyun         for (i = 0; i < pPriv->bufferCount; i++)
440*4882a593Smuzhiyun             destroy_buffer(pDraw, pPriv->buffers[i], pPriv->prime_id);
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun         free(pPriv->buffers);
443*4882a593Smuzhiyun     }
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun     if (pPriv->redirectpixmap) {
446*4882a593Smuzhiyun         (*pDraw->pScreen->ReplaceScanoutPixmap)(pDraw, pPriv->redirectpixmap, FALSE);
447*4882a593Smuzhiyun         (*pDraw->pScreen->DestroyPixmap)(pPriv->redirectpixmap);
448*4882a593Smuzhiyun     }
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun     dri2WakeAll(CLIENT_SIGNAL_ANY, pPriv, WAKE_SWAP);
451*4882a593Smuzhiyun     dri2WakeAll(CLIENT_SIGNAL_ANY, pPriv, WAKE_MSC);
452*4882a593Smuzhiyun     dri2WakeAll(CLIENT_SIGNAL_ANY, pPriv, WAKE_SBC);
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun     free(pPriv);
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun     return Success;
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun static DRI2BufferPtr
create_buffer(DRI2ScreenPtr ds,DrawablePtr pDraw,unsigned int attachment,unsigned int format)460*4882a593Smuzhiyun create_buffer(DRI2ScreenPtr ds, DrawablePtr pDraw,
461*4882a593Smuzhiyun               unsigned int attachment, unsigned int format)
462*4882a593Smuzhiyun {
463*4882a593Smuzhiyun     DRI2BufferPtr buffer;
464*4882a593Smuzhiyun     if (ds->CreateBuffer2)
465*4882a593Smuzhiyun         buffer = (*ds->CreateBuffer2)(GetScreenPrime(pDraw->pScreen,
466*4882a593Smuzhiyun                                                      DRI2GetDrawable(pDraw)->prime_id),
467*4882a593Smuzhiyun                                       pDraw, attachment, format);
468*4882a593Smuzhiyun     else
469*4882a593Smuzhiyun         buffer = (*ds->CreateBuffer)(pDraw, attachment, format);
470*4882a593Smuzhiyun     return buffer;
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun static void
destroy_buffer(DrawablePtr pDraw,DRI2BufferPtr buffer,int prime_id)474*4882a593Smuzhiyun destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, int prime_id)
475*4882a593Smuzhiyun {
476*4882a593Smuzhiyun     ScreenPtr primeScreen;
477*4882a593Smuzhiyun     DRI2ScreenPtr ds;
478*4882a593Smuzhiyun     primeScreen = GetScreenPrime(pDraw->pScreen, prime_id);
479*4882a593Smuzhiyun     ds = DRI2GetScreen(primeScreen);
480*4882a593Smuzhiyun     if (ds->DestroyBuffer2)
481*4882a593Smuzhiyun         (*ds->DestroyBuffer2)(primeScreen, pDraw, buffer);
482*4882a593Smuzhiyun     else
483*4882a593Smuzhiyun         (*ds->DestroyBuffer)(pDraw, buffer);
484*4882a593Smuzhiyun }
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun static int
find_attachment(DRI2DrawablePtr pPriv,unsigned attachment)487*4882a593Smuzhiyun find_attachment(DRI2DrawablePtr pPriv, unsigned attachment)
488*4882a593Smuzhiyun {
489*4882a593Smuzhiyun     int i;
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun     if (pPriv->buffers == NULL) {
492*4882a593Smuzhiyun         return -1;
493*4882a593Smuzhiyun     }
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun     for (i = 0; i < pPriv->bufferCount; i++) {
496*4882a593Smuzhiyun         if ((pPriv->buffers[i] != NULL)
497*4882a593Smuzhiyun             && (pPriv->buffers[i]->attachment == attachment)) {
498*4882a593Smuzhiyun             return i;
499*4882a593Smuzhiyun         }
500*4882a593Smuzhiyun     }
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun     return -1;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun static Bool
allocate_or_reuse_buffer(DrawablePtr pDraw,DRI2ScreenPtr ds,DRI2DrawablePtr pPriv,unsigned int attachment,unsigned int format,int dimensions_match,DRI2BufferPtr * buffer)506*4882a593Smuzhiyun allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr ds,
507*4882a593Smuzhiyun                          DRI2DrawablePtr pPriv,
508*4882a593Smuzhiyun                          unsigned int attachment, unsigned int format,
509*4882a593Smuzhiyun                          int dimensions_match, DRI2BufferPtr * buffer)
510*4882a593Smuzhiyun {
511*4882a593Smuzhiyun     int old_buf = find_attachment(pPriv, attachment);
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun     if ((old_buf < 0)
514*4882a593Smuzhiyun         || attachment == DRI2BufferFrontLeft
515*4882a593Smuzhiyun         || !dimensions_match || (pPriv->buffers[old_buf]->format != format)) {
516*4882a593Smuzhiyun         *buffer = create_buffer(ds, pDraw, attachment, format);
517*4882a593Smuzhiyun         return TRUE;
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun     }
520*4882a593Smuzhiyun     else {
521*4882a593Smuzhiyun         *buffer = pPriv->buffers[old_buf];
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun         if (ds->ReuseBufferNotify)
524*4882a593Smuzhiyun             (*ds->ReuseBufferNotify) (pDraw, *buffer);
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun         pPriv->buffers[old_buf] = NULL;
527*4882a593Smuzhiyun         return FALSE;
528*4882a593Smuzhiyun     }
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun static void
update_dri2_drawable_buffers(DRI2DrawablePtr pPriv,DrawablePtr pDraw,DRI2BufferPtr * buffers,int out_count,int * width,int * height)532*4882a593Smuzhiyun update_dri2_drawable_buffers(DRI2DrawablePtr pPriv, DrawablePtr pDraw,
533*4882a593Smuzhiyun                              DRI2BufferPtr * buffers, int out_count, int *width,
534*4882a593Smuzhiyun                              int *height)
535*4882a593Smuzhiyun {
536*4882a593Smuzhiyun     int i;
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun     if (pPriv->buffers != NULL) {
539*4882a593Smuzhiyun         for (i = 0; i < pPriv->bufferCount; i++) {
540*4882a593Smuzhiyun             if (pPriv->buffers[i] != NULL) {
541*4882a593Smuzhiyun                 destroy_buffer(pDraw, pPriv->buffers[i], pPriv->prime_id);
542*4882a593Smuzhiyun             }
543*4882a593Smuzhiyun         }
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun         free(pPriv->buffers);
546*4882a593Smuzhiyun     }
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun     pPriv->buffers = buffers;
549*4882a593Smuzhiyun     pPriv->bufferCount = out_count;
550*4882a593Smuzhiyun     pPriv->width = pDraw->width;
551*4882a593Smuzhiyun     pPriv->height = pDraw->height;
552*4882a593Smuzhiyun     *width = pPriv->width;
553*4882a593Smuzhiyun     *height = pPriv->height;
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun static DRI2BufferPtr *
do_get_buffers(DrawablePtr pDraw,int * width,int * height,unsigned int * attachments,int count,int * out_count,int has_format)557*4882a593Smuzhiyun do_get_buffers(DrawablePtr pDraw, int *width, int *height,
558*4882a593Smuzhiyun                unsigned int *attachments, int count, int *out_count,
559*4882a593Smuzhiyun                int has_format)
560*4882a593Smuzhiyun {
561*4882a593Smuzhiyun     DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
562*4882a593Smuzhiyun     DRI2ScreenPtr ds;
563*4882a593Smuzhiyun     DRI2BufferPtr *buffers;
564*4882a593Smuzhiyun     int need_real_front = 0;
565*4882a593Smuzhiyun     int need_fake_front = 0;
566*4882a593Smuzhiyun     int have_fake_front = 0;
567*4882a593Smuzhiyun     int front_format = 0;
568*4882a593Smuzhiyun     int dimensions_match;
569*4882a593Smuzhiyun     int buffers_changed = 0;
570*4882a593Smuzhiyun     int i;
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun     if (!pPriv) {
573*4882a593Smuzhiyun         *width = pDraw->width;
574*4882a593Smuzhiyun         *height = pDraw->height;
575*4882a593Smuzhiyun         *out_count = 0;
576*4882a593Smuzhiyun         return NULL;
577*4882a593Smuzhiyun     }
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun     ds = DRI2GetScreenPrime(pDraw->pScreen, pPriv->prime_id);
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun     dimensions_match = (pDraw->width == pPriv->width)
582*4882a593Smuzhiyun         && (pDraw->height == pPriv->height);
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun     buffers = calloc((count + 1), sizeof(buffers[0]));
585*4882a593Smuzhiyun     if (!buffers)
586*4882a593Smuzhiyun         goto err_out;
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun     for (i = 0; i < count; i++) {
589*4882a593Smuzhiyun         const unsigned attachment = *(attachments++);
590*4882a593Smuzhiyun         const unsigned format = (has_format) ? *(attachments++) : 0;
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun         if (allocate_or_reuse_buffer(pDraw, ds, pPriv, attachment,
593*4882a593Smuzhiyun                                      format, dimensions_match, &buffers[i]))
594*4882a593Smuzhiyun             buffers_changed = 1;
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun         if (buffers[i] == NULL)
597*4882a593Smuzhiyun             goto err_out;
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun         /* If the drawable is a window and the front-buffer is requested,
600*4882a593Smuzhiyun          * silently add the fake front-buffer to the list of requested
601*4882a593Smuzhiyun          * attachments.  The counting logic in the loop accounts for the case
602*4882a593Smuzhiyun          * where the client requests both the fake and real front-buffer.
603*4882a593Smuzhiyun          */
604*4882a593Smuzhiyun         if (attachment == DRI2BufferBackLeft) {
605*4882a593Smuzhiyun             need_real_front++;
606*4882a593Smuzhiyun             front_format = format;
607*4882a593Smuzhiyun         }
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun         if (attachment == DRI2BufferFrontLeft) {
610*4882a593Smuzhiyun             need_real_front--;
611*4882a593Smuzhiyun             front_format = format;
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun             if (pDraw->type == DRAWABLE_WINDOW) {
614*4882a593Smuzhiyun                 need_fake_front++;
615*4882a593Smuzhiyun             }
616*4882a593Smuzhiyun         }
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun         if (pDraw->type == DRAWABLE_WINDOW) {
619*4882a593Smuzhiyun             if (attachment == DRI2BufferFakeFrontLeft) {
620*4882a593Smuzhiyun                 need_fake_front--;
621*4882a593Smuzhiyun                 have_fake_front = 1;
622*4882a593Smuzhiyun             }
623*4882a593Smuzhiyun         }
624*4882a593Smuzhiyun     }
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun     if (need_real_front > 0) {
627*4882a593Smuzhiyun         if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFrontLeft,
628*4882a593Smuzhiyun                                      front_format, dimensions_match,
629*4882a593Smuzhiyun                                      &buffers[i]))
630*4882a593Smuzhiyun             buffers_changed = 1;
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun         if (buffers[i] == NULL)
633*4882a593Smuzhiyun             goto err_out;
634*4882a593Smuzhiyun         i++;
635*4882a593Smuzhiyun     }
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun     if (need_fake_front > 0) {
638*4882a593Smuzhiyun         if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFakeFrontLeft,
639*4882a593Smuzhiyun                                      front_format, dimensions_match,
640*4882a593Smuzhiyun                                      &buffers[i]))
641*4882a593Smuzhiyun             buffers_changed = 1;
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun         if (buffers[i] == NULL)
644*4882a593Smuzhiyun             goto err_out;
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun         i++;
647*4882a593Smuzhiyun         have_fake_front = 1;
648*4882a593Smuzhiyun     }
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun     *out_count = i;
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun     update_dri2_drawable_buffers(pPriv, pDraw, buffers, *out_count, width,
653*4882a593Smuzhiyun                                  height);
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun     /* If the client is getting a fake front-buffer, pre-fill it with the
656*4882a593Smuzhiyun      * contents of the real front-buffer.  This ensures correct operation of
657*4882a593Smuzhiyun      * applications that call glXWaitX before calling glDrawBuffer.
658*4882a593Smuzhiyun      */
659*4882a593Smuzhiyun     if (have_fake_front && buffers_changed) {
660*4882a593Smuzhiyun         BoxRec box;
661*4882a593Smuzhiyun         RegionRec region;
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun         box.x1 = 0;
664*4882a593Smuzhiyun         box.y1 = 0;
665*4882a593Smuzhiyun         box.x2 = pPriv->width;
666*4882a593Smuzhiyun         box.y2 = pPriv->height;
667*4882a593Smuzhiyun         RegionInit(&region, &box, 0);
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun         DRI2CopyRegion(pDraw, &region, DRI2BufferFakeFrontLeft,
670*4882a593Smuzhiyun                        DRI2BufferFrontLeft);
671*4882a593Smuzhiyun     }
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun     pPriv->needInvalidate = TRUE;
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun     return pPriv->buffers;
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun  err_out:
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun     *out_count = 0;
680*4882a593Smuzhiyun 
681*4882a593Smuzhiyun     if (buffers) {
682*4882a593Smuzhiyun         for (i = 0; i < count; i++) {
683*4882a593Smuzhiyun             if (buffers[i] != NULL)
684*4882a593Smuzhiyun                 destroy_buffer(pDraw, buffers[i], 0);
685*4882a593Smuzhiyun         }
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun         free(buffers);
688*4882a593Smuzhiyun         buffers = NULL;
689*4882a593Smuzhiyun     }
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun     update_dri2_drawable_buffers(pPriv, pDraw, buffers, *out_count, width,
692*4882a593Smuzhiyun                                  height);
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun     return buffers;
695*4882a593Smuzhiyun }
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun DRI2BufferPtr *
DRI2GetBuffers(DrawablePtr pDraw,int * width,int * height,unsigned int * attachments,int count,int * out_count)698*4882a593Smuzhiyun DRI2GetBuffers(DrawablePtr pDraw, int *width, int *height,
699*4882a593Smuzhiyun                unsigned int *attachments, int count, int *out_count)
700*4882a593Smuzhiyun {
701*4882a593Smuzhiyun     return do_get_buffers(pDraw, width, height, attachments, count,
702*4882a593Smuzhiyun                           out_count, FALSE);
703*4882a593Smuzhiyun }
704*4882a593Smuzhiyun 
705*4882a593Smuzhiyun DRI2BufferPtr *
DRI2GetBuffersWithFormat(DrawablePtr pDraw,int * width,int * height,unsigned int * attachments,int count,int * out_count)706*4882a593Smuzhiyun DRI2GetBuffersWithFormat(DrawablePtr pDraw, int *width, int *height,
707*4882a593Smuzhiyun                          unsigned int *attachments, int count, int *out_count)
708*4882a593Smuzhiyun {
709*4882a593Smuzhiyun     return do_get_buffers(pDraw, width, height, attachments, count,
710*4882a593Smuzhiyun                           out_count, TRUE);
711*4882a593Smuzhiyun }
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun static void
DRI2InvalidateDrawable(DrawablePtr pDraw)714*4882a593Smuzhiyun DRI2InvalidateDrawable(DrawablePtr pDraw)
715*4882a593Smuzhiyun {
716*4882a593Smuzhiyun     DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
717*4882a593Smuzhiyun     DRI2DrawableRefPtr ref;
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun     if (!pPriv || !pPriv->needInvalidate)
720*4882a593Smuzhiyun         return;
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun     pPriv->needInvalidate = FALSE;
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun     xorg_list_for_each_entry(ref, &pPriv->reference_list, link)
725*4882a593Smuzhiyun         ref->invalidate(pDraw, ref->priv, ref->id);
726*4882a593Smuzhiyun }
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun /*
729*4882a593Smuzhiyun  * In the direct rendered case, we throttle the clients that have more
730*4882a593Smuzhiyun  * than their share of outstanding swaps (and thus busy buffers) when a
731*4882a593Smuzhiyun  * new GetBuffers request is received.  In the AIGLX case, we allow the
732*4882a593Smuzhiyun  * client to get the new buffers, but throttle when the next GLX request
733*4882a593Smuzhiyun  * comes in (see __glXDRIcontextWait()).
734*4882a593Smuzhiyun  */
735*4882a593Smuzhiyun Bool
DRI2ThrottleClient(ClientPtr client,DrawablePtr pDraw)736*4882a593Smuzhiyun DRI2ThrottleClient(ClientPtr client, DrawablePtr pDraw)
737*4882a593Smuzhiyun {
738*4882a593Smuzhiyun     DRI2DrawablePtr pPriv;
739*4882a593Smuzhiyun 
740*4882a593Smuzhiyun     pPriv = DRI2GetDrawable(pDraw);
741*4882a593Smuzhiyun     if (pPriv == NULL)
742*4882a593Smuzhiyun         return FALSE;
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun     /* Throttle to swap limit */
745*4882a593Smuzhiyun     if (pPriv->swapsPending >= pPriv->swap_limit) {
746*4882a593Smuzhiyun         if (dri2Sleep(client, pPriv, WAKE_SWAP)) {
747*4882a593Smuzhiyun             ResetCurrentRequest(client);
748*4882a593Smuzhiyun             client->sequence--;
749*4882a593Smuzhiyun             return TRUE;
750*4882a593Smuzhiyun         }
751*4882a593Smuzhiyun     }
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun     return FALSE;
754*4882a593Smuzhiyun }
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun void
DRI2BlockClient(ClientPtr client,DrawablePtr pDraw)757*4882a593Smuzhiyun DRI2BlockClient(ClientPtr client, DrawablePtr pDraw)
758*4882a593Smuzhiyun {
759*4882a593Smuzhiyun     DRI2DrawablePtr pPriv;
760*4882a593Smuzhiyun 
761*4882a593Smuzhiyun     pPriv = DRI2GetDrawable(pDraw);
762*4882a593Smuzhiyun     if (pPriv == NULL)
763*4882a593Smuzhiyun         return;
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun     dri2Sleep(client, pPriv, WAKE_MSC);
766*4882a593Smuzhiyun }
767*4882a593Smuzhiyun 
GetDrawablePixmap(DrawablePtr drawable)768*4882a593Smuzhiyun static inline PixmapPtr GetDrawablePixmap(DrawablePtr drawable)
769*4882a593Smuzhiyun {
770*4882a593Smuzhiyun     if (drawable->type == DRAWABLE_PIXMAP)
771*4882a593Smuzhiyun         return (PixmapPtr)drawable;
772*4882a593Smuzhiyun     else {
773*4882a593Smuzhiyun         struct _Window *pWin = (struct _Window *)drawable;
774*4882a593Smuzhiyun         return drawable->pScreen->GetWindowPixmap(pWin);
775*4882a593Smuzhiyun     }
776*4882a593Smuzhiyun }
777*4882a593Smuzhiyun 
778*4882a593Smuzhiyun /*
779*4882a593Smuzhiyun  * A TraverseTree callback to invalidate all windows using the same
780*4882a593Smuzhiyun  * pixmap
781*4882a593Smuzhiyun  */
782*4882a593Smuzhiyun static int
DRI2InvalidateWalk(WindowPtr pWin,void * data)783*4882a593Smuzhiyun DRI2InvalidateWalk(WindowPtr pWin, void *data)
784*4882a593Smuzhiyun {
785*4882a593Smuzhiyun     if (pWin->drawable.pScreen->GetWindowPixmap(pWin) != data)
786*4882a593Smuzhiyun         return WT_DONTWALKCHILDREN;
787*4882a593Smuzhiyun     DRI2InvalidateDrawable(&pWin->drawable);
788*4882a593Smuzhiyun     return WT_WALKCHILDREN;
789*4882a593Smuzhiyun }
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun static void
DRI2InvalidateDrawableAll(DrawablePtr pDraw)792*4882a593Smuzhiyun DRI2InvalidateDrawableAll(DrawablePtr pDraw)
793*4882a593Smuzhiyun {
794*4882a593Smuzhiyun     if (pDraw->type == DRAWABLE_WINDOW) {
795*4882a593Smuzhiyun         WindowPtr pWin = (WindowPtr) pDraw;
796*4882a593Smuzhiyun         PixmapPtr pPixmap = pDraw->pScreen->GetWindowPixmap(pWin);
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun         /*
799*4882a593Smuzhiyun          * Find the top-most window using this pixmap
800*4882a593Smuzhiyun          */
801*4882a593Smuzhiyun         while (pWin->parent &&
802*4882a593Smuzhiyun                pDraw->pScreen->GetWindowPixmap(pWin->parent) == pPixmap)
803*4882a593Smuzhiyun             pWin = pWin->parent;
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun         /*
806*4882a593Smuzhiyun          * Walk the sub-tree to invalidate all of the
807*4882a593Smuzhiyun          * windows using the same pixmap
808*4882a593Smuzhiyun          */
809*4882a593Smuzhiyun         TraverseTree(pWin, DRI2InvalidateWalk, pPixmap);
810*4882a593Smuzhiyun         DRI2InvalidateDrawable(&pPixmap->drawable);
811*4882a593Smuzhiyun     }
812*4882a593Smuzhiyun     else
813*4882a593Smuzhiyun         DRI2InvalidateDrawable(pDraw);
814*4882a593Smuzhiyun }
815*4882a593Smuzhiyun 
DRI2UpdatePrime(DrawablePtr pDraw,DRI2BufferPtr pDest)816*4882a593Smuzhiyun DrawablePtr DRI2UpdatePrime(DrawablePtr pDraw, DRI2BufferPtr pDest)
817*4882a593Smuzhiyun {
818*4882a593Smuzhiyun     DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
819*4882a593Smuzhiyun     PixmapPtr spix;
820*4882a593Smuzhiyun     PixmapPtr mpix = GetDrawablePixmap(pDraw);
821*4882a593Smuzhiyun     ScreenPtr master, slave;
822*4882a593Smuzhiyun     Bool ret;
823*4882a593Smuzhiyun 
824*4882a593Smuzhiyun     master = mpix->drawable.pScreen;
825*4882a593Smuzhiyun 
826*4882a593Smuzhiyun     if (pDraw->type == DRAWABLE_WINDOW) {
827*4882a593Smuzhiyun         WindowPtr pWin = (WindowPtr)pDraw;
828*4882a593Smuzhiyun         PixmapPtr pPixmap = pDraw->pScreen->GetWindowPixmap(pWin);
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun         if (pDraw->pScreen->GetScreenPixmap(pDraw->pScreen) == pPixmap) {
831*4882a593Smuzhiyun             if (pPriv->redirectpixmap &&
832*4882a593Smuzhiyun                 pPriv->redirectpixmap->drawable.width == pDraw->width &&
833*4882a593Smuzhiyun                 pPriv->redirectpixmap->drawable.height == pDraw->height &&
834*4882a593Smuzhiyun                 pPriv->redirectpixmap->drawable.depth == pDraw->depth) {
835*4882a593Smuzhiyun                 mpix = pPriv->redirectpixmap;
836*4882a593Smuzhiyun             } else {
837*4882a593Smuzhiyun                 if (master->ReplaceScanoutPixmap) {
838*4882a593Smuzhiyun                     mpix = (*master->CreatePixmap)(master, pDraw->width, pDraw->height,
839*4882a593Smuzhiyun                                                    pDraw->depth, CREATE_PIXMAP_USAGE_SHARED);
840*4882a593Smuzhiyun                     if (!mpix)
841*4882a593Smuzhiyun                         return NULL;
842*4882a593Smuzhiyun 
843*4882a593Smuzhiyun                     ret = (*master->ReplaceScanoutPixmap)(pDraw, mpix, TRUE);
844*4882a593Smuzhiyun                     if (ret == FALSE) {
845*4882a593Smuzhiyun                         (*master->DestroyPixmap)(mpix);
846*4882a593Smuzhiyun                         return NULL;
847*4882a593Smuzhiyun                     }
848*4882a593Smuzhiyun                     pPriv->redirectpixmap = mpix;
849*4882a593Smuzhiyun                 } else
850*4882a593Smuzhiyun                     return NULL;
851*4882a593Smuzhiyun             }
852*4882a593Smuzhiyun         } else if (pPriv->redirectpixmap) {
853*4882a593Smuzhiyun             (*master->ReplaceScanoutPixmap)(pDraw, pPriv->redirectpixmap, FALSE);
854*4882a593Smuzhiyun             (*master->DestroyPixmap)(pPriv->redirectpixmap);
855*4882a593Smuzhiyun             pPriv->redirectpixmap = NULL;
856*4882a593Smuzhiyun         }
857*4882a593Smuzhiyun     }
858*4882a593Smuzhiyun 
859*4882a593Smuzhiyun     slave = GetScreenPrime(pDraw->pScreen, pPriv->prime_id);
860*4882a593Smuzhiyun 
861*4882a593Smuzhiyun     /* check if the pixmap is still fine */
862*4882a593Smuzhiyun     if (pPriv->prime_slave_pixmap) {
863*4882a593Smuzhiyun         if (pPriv->prime_slave_pixmap->master_pixmap == mpix)
864*4882a593Smuzhiyun             return &pPriv->prime_slave_pixmap->drawable;
865*4882a593Smuzhiyun         else {
866*4882a593Smuzhiyun             PixmapUnshareSlavePixmap(pPriv->prime_slave_pixmap);
867*4882a593Smuzhiyun             (*pPriv->prime_slave_pixmap->master_pixmap->drawable.pScreen->DestroyPixmap)(pPriv->prime_slave_pixmap->master_pixmap);
868*4882a593Smuzhiyun             (*slave->DestroyPixmap)(pPriv->prime_slave_pixmap);
869*4882a593Smuzhiyun             pPriv->prime_slave_pixmap = NULL;
870*4882a593Smuzhiyun         }
871*4882a593Smuzhiyun     }
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun     spix = PixmapShareToSlave(mpix, slave);
874*4882a593Smuzhiyun     if (!spix)
875*4882a593Smuzhiyun         return NULL;
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun     pPriv->prime_slave_pixmap = spix;
878*4882a593Smuzhiyun #ifdef COMPOSITE
879*4882a593Smuzhiyun     spix->screen_x = mpix->screen_x;
880*4882a593Smuzhiyun     spix->screen_y = mpix->screen_y;
881*4882a593Smuzhiyun #endif
882*4882a593Smuzhiyun 
883*4882a593Smuzhiyun     DRI2InvalidateDrawableAll(pDraw);
884*4882a593Smuzhiyun     return &spix->drawable;
885*4882a593Smuzhiyun }
886*4882a593Smuzhiyun 
dri2_copy_region(DrawablePtr pDraw,RegionPtr pRegion,DRI2BufferPtr pDest,DRI2BufferPtr pSrc)887*4882a593Smuzhiyun static void dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion,
888*4882a593Smuzhiyun                              DRI2BufferPtr pDest, DRI2BufferPtr pSrc)
889*4882a593Smuzhiyun {
890*4882a593Smuzhiyun     DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
891*4882a593Smuzhiyun     DRI2ScreenPtr ds;
892*4882a593Smuzhiyun     ScreenPtr primeScreen;
893*4882a593Smuzhiyun 
894*4882a593Smuzhiyun     primeScreen = GetScreenPrime(pDraw->pScreen, pPriv->prime_id);
895*4882a593Smuzhiyun     ds = DRI2GetScreen(primeScreen);
896*4882a593Smuzhiyun 
897*4882a593Smuzhiyun     if (ds->CopyRegion2)
898*4882a593Smuzhiyun         (*ds->CopyRegion2)(primeScreen, pDraw, pRegion, pDest, pSrc);
899*4882a593Smuzhiyun     else
900*4882a593Smuzhiyun         (*ds->CopyRegion) (pDraw, pRegion, pDest, pSrc);
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun     /* cause damage to the box */
903*4882a593Smuzhiyun     if (pPriv->prime_id) {
904*4882a593Smuzhiyun        BoxRec box;
905*4882a593Smuzhiyun        RegionRec region;
906*4882a593Smuzhiyun        box.x1 = 0;
907*4882a593Smuzhiyun        box.x2 = box.x1 + pDraw->width;
908*4882a593Smuzhiyun        box.y1 = 0;
909*4882a593Smuzhiyun        box.y2 = box.y1 + pDraw->height;
910*4882a593Smuzhiyun        RegionInit(&region, &box, 1);
911*4882a593Smuzhiyun        RegionTranslate(&region, pDraw->x, pDraw->y);
912*4882a593Smuzhiyun        DamageRegionAppend(pDraw, &region);
913*4882a593Smuzhiyun        DamageRegionProcessPending(pDraw);
914*4882a593Smuzhiyun        RegionUninit(&region);
915*4882a593Smuzhiyun     }
916*4882a593Smuzhiyun }
917*4882a593Smuzhiyun 
918*4882a593Smuzhiyun int
DRI2CopyRegion(DrawablePtr pDraw,RegionPtr pRegion,unsigned int dest,unsigned int src)919*4882a593Smuzhiyun DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
920*4882a593Smuzhiyun                unsigned int dest, unsigned int src)
921*4882a593Smuzhiyun {
922*4882a593Smuzhiyun     DRI2DrawablePtr pPriv;
923*4882a593Smuzhiyun     DRI2BufferPtr pDestBuffer, pSrcBuffer;
924*4882a593Smuzhiyun     int i;
925*4882a593Smuzhiyun 
926*4882a593Smuzhiyun     pPriv = DRI2GetDrawable(pDraw);
927*4882a593Smuzhiyun     if (pPriv == NULL)
928*4882a593Smuzhiyun         return BadDrawable;
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun     pDestBuffer = NULL;
931*4882a593Smuzhiyun     pSrcBuffer = NULL;
932*4882a593Smuzhiyun     for (i = 0; i < pPriv->bufferCount; i++) {
933*4882a593Smuzhiyun         if (pPriv->buffers[i]->attachment == dest)
934*4882a593Smuzhiyun             pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i];
935*4882a593Smuzhiyun         if (pPriv->buffers[i]->attachment == src)
936*4882a593Smuzhiyun             pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i];
937*4882a593Smuzhiyun     }
938*4882a593Smuzhiyun     if (pSrcBuffer == NULL || pDestBuffer == NULL)
939*4882a593Smuzhiyun         return BadValue;
940*4882a593Smuzhiyun 
941*4882a593Smuzhiyun     dri2_copy_region(pDraw, pRegion, pDestBuffer, pSrcBuffer);
942*4882a593Smuzhiyun 
943*4882a593Smuzhiyun     return Success;
944*4882a593Smuzhiyun }
945*4882a593Smuzhiyun 
946*4882a593Smuzhiyun /* Can this drawable be page flipped? */
947*4882a593Smuzhiyun Bool
DRI2CanFlip(DrawablePtr pDraw)948*4882a593Smuzhiyun DRI2CanFlip(DrawablePtr pDraw)
949*4882a593Smuzhiyun {
950*4882a593Smuzhiyun     ScreenPtr pScreen = pDraw->pScreen;
951*4882a593Smuzhiyun     WindowPtr pWin, pRoot;
952*4882a593Smuzhiyun     PixmapPtr pWinPixmap, pRootPixmap;
953*4882a593Smuzhiyun 
954*4882a593Smuzhiyun     if (pDraw->type == DRAWABLE_PIXMAP)
955*4882a593Smuzhiyun         return TRUE;
956*4882a593Smuzhiyun 
957*4882a593Smuzhiyun     pRoot = pScreen->root;
958*4882a593Smuzhiyun     pRootPixmap = pScreen->GetWindowPixmap(pRoot);
959*4882a593Smuzhiyun 
960*4882a593Smuzhiyun     pWin = (WindowPtr) pDraw;
961*4882a593Smuzhiyun     pWinPixmap = pScreen->GetWindowPixmap(pWin);
962*4882a593Smuzhiyun     if (pRootPixmap != pWinPixmap)
963*4882a593Smuzhiyun         return FALSE;
964*4882a593Smuzhiyun     if (!RegionEqual(&pWin->clipList, &pRoot->winSize))
965*4882a593Smuzhiyun         return FALSE;
966*4882a593Smuzhiyun 
967*4882a593Smuzhiyun     /* Does the window match the pixmap exactly? */
968*4882a593Smuzhiyun     if (pDraw->x != 0 || pDraw->y != 0 ||
969*4882a593Smuzhiyun #ifdef COMPOSITE
970*4882a593Smuzhiyun         pDraw->x != pWinPixmap->screen_x || pDraw->y != pWinPixmap->screen_y ||
971*4882a593Smuzhiyun #endif
972*4882a593Smuzhiyun         pDraw->width != pWinPixmap->drawable.width ||
973*4882a593Smuzhiyun         pDraw->height != pWinPixmap->drawable.height)
974*4882a593Smuzhiyun         return FALSE;
975*4882a593Smuzhiyun 
976*4882a593Smuzhiyun     return TRUE;
977*4882a593Smuzhiyun }
978*4882a593Smuzhiyun 
979*4882a593Smuzhiyun /* Can we do a pixmap exchange instead of a blit? */
980*4882a593Smuzhiyun Bool
DRI2CanExchange(DrawablePtr pDraw)981*4882a593Smuzhiyun DRI2CanExchange(DrawablePtr pDraw)
982*4882a593Smuzhiyun {
983*4882a593Smuzhiyun     return FALSE;
984*4882a593Smuzhiyun }
985*4882a593Smuzhiyun 
986*4882a593Smuzhiyun void
DRI2WaitMSCComplete(ClientPtr client,DrawablePtr pDraw,int frame,unsigned int tv_sec,unsigned int tv_usec)987*4882a593Smuzhiyun DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame,
988*4882a593Smuzhiyun                     unsigned int tv_sec, unsigned int tv_usec)
989*4882a593Smuzhiyun {
990*4882a593Smuzhiyun     DRI2DrawablePtr pPriv;
991*4882a593Smuzhiyun 
992*4882a593Smuzhiyun     pPriv = DRI2GetDrawable(pDraw);
993*4882a593Smuzhiyun     if (pPriv == NULL)
994*4882a593Smuzhiyun         return;
995*4882a593Smuzhiyun 
996*4882a593Smuzhiyun     ProcDRI2WaitMSCReply(client, ((CARD64) tv_sec * 1000000) + tv_usec,
997*4882a593Smuzhiyun                          frame, pPriv->swap_count);
998*4882a593Smuzhiyun 
999*4882a593Smuzhiyun     dri2WakeAll(client, pPriv, WAKE_MSC);
1000*4882a593Smuzhiyun }
1001*4882a593Smuzhiyun 
1002*4882a593Smuzhiyun static void
DRI2WakeClient(ClientPtr client,DrawablePtr pDraw,int frame,unsigned int tv_sec,unsigned int tv_usec)1003*4882a593Smuzhiyun DRI2WakeClient(ClientPtr client, DrawablePtr pDraw, int frame,
1004*4882a593Smuzhiyun                unsigned int tv_sec, unsigned int tv_usec)
1005*4882a593Smuzhiyun {
1006*4882a593Smuzhiyun     ScreenPtr pScreen = pDraw->pScreen;
1007*4882a593Smuzhiyun     DRI2DrawablePtr pPriv;
1008*4882a593Smuzhiyun 
1009*4882a593Smuzhiyun     pPriv = DRI2GetDrawable(pDraw);
1010*4882a593Smuzhiyun     if (pPriv == NULL) {
1011*4882a593Smuzhiyun         xf86DrvMsg(pScreen->myNum, X_ERROR,
1012*4882a593Smuzhiyun                    "[DRI2] %s: bad drawable\n", __func__);
1013*4882a593Smuzhiyun         return;
1014*4882a593Smuzhiyun     }
1015*4882a593Smuzhiyun 
1016*4882a593Smuzhiyun     /*
1017*4882a593Smuzhiyun      * Swap completed.
1018*4882a593Smuzhiyun      * Wake the client iff:
1019*4882a593Smuzhiyun      *   - it was waiting on SBC
1020*4882a593Smuzhiyun      *   - was blocked due to GLX make current
1021*4882a593Smuzhiyun      *   - was blocked due to swap throttling
1022*4882a593Smuzhiyun      *   - is not blocked due to an MSC wait
1023*4882a593Smuzhiyun      */
1024*4882a593Smuzhiyun     if (pPriv->target_sbc != -1 && pPriv->target_sbc <= pPriv->swap_count) {
1025*4882a593Smuzhiyun         if (dri2WakeAll(client, pPriv, WAKE_SBC)) {
1026*4882a593Smuzhiyun             ProcDRI2WaitMSCReply(client, ((CARD64) tv_sec * 1000000) + tv_usec,
1027*4882a593Smuzhiyun                                  frame, pPriv->swap_count);
1028*4882a593Smuzhiyun             pPriv->target_sbc = -1;
1029*4882a593Smuzhiyun         }
1030*4882a593Smuzhiyun     }
1031*4882a593Smuzhiyun 
1032*4882a593Smuzhiyun     dri2WakeAll(CLIENT_SIGNAL_ANY, pPriv, WAKE_SWAP);
1033*4882a593Smuzhiyun }
1034*4882a593Smuzhiyun 
1035*4882a593Smuzhiyun void
DRI2SwapComplete(ClientPtr client,DrawablePtr pDraw,int frame,unsigned int tv_sec,unsigned int tv_usec,int type,DRI2SwapEventPtr swap_complete,void * swap_data)1036*4882a593Smuzhiyun DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
1037*4882a593Smuzhiyun                  unsigned int tv_sec, unsigned int tv_usec, int type,
1038*4882a593Smuzhiyun                  DRI2SwapEventPtr swap_complete, void *swap_data)
1039*4882a593Smuzhiyun {
1040*4882a593Smuzhiyun     ScreenPtr pScreen = pDraw->pScreen;
1041*4882a593Smuzhiyun     DRI2DrawablePtr pPriv;
1042*4882a593Smuzhiyun     CARD64 ust = 0;
1043*4882a593Smuzhiyun     BoxRec box;
1044*4882a593Smuzhiyun     RegionRec region;
1045*4882a593Smuzhiyun 
1046*4882a593Smuzhiyun     pPriv = DRI2GetDrawable(pDraw);
1047*4882a593Smuzhiyun     if (pPriv == NULL) {
1048*4882a593Smuzhiyun         xf86DrvMsg(pScreen->myNum, X_ERROR,
1049*4882a593Smuzhiyun                    "[DRI2] %s: bad drawable\n", __func__);
1050*4882a593Smuzhiyun         return;
1051*4882a593Smuzhiyun     }
1052*4882a593Smuzhiyun 
1053*4882a593Smuzhiyun     pPriv->swapsPending--;
1054*4882a593Smuzhiyun     pPriv->swap_count++;
1055*4882a593Smuzhiyun 
1056*4882a593Smuzhiyun     box.x1 = 0;
1057*4882a593Smuzhiyun     box.y1 = 0;
1058*4882a593Smuzhiyun     box.x2 = pDraw->width;
1059*4882a593Smuzhiyun     box.y2 = pDraw->height;
1060*4882a593Smuzhiyun     RegionInit(&region, &box, 0);
1061*4882a593Smuzhiyun     DRI2CopyRegion(pDraw, &region, DRI2BufferFakeFrontLeft,
1062*4882a593Smuzhiyun                    DRI2BufferFrontLeft);
1063*4882a593Smuzhiyun 
1064*4882a593Smuzhiyun     ust = ((CARD64) tv_sec * 1000000) + tv_usec;
1065*4882a593Smuzhiyun     if (swap_complete)
1066*4882a593Smuzhiyun         swap_complete(client, swap_data, type, ust, frame, pPriv->swap_count);
1067*4882a593Smuzhiyun 
1068*4882a593Smuzhiyun     pPriv->last_swap_msc = frame;
1069*4882a593Smuzhiyun     pPriv->last_swap_ust = ust;
1070*4882a593Smuzhiyun 
1071*4882a593Smuzhiyun     DRI2WakeClient(client, pDraw, frame, tv_sec, tv_usec);
1072*4882a593Smuzhiyun }
1073*4882a593Smuzhiyun 
1074*4882a593Smuzhiyun Bool
DRI2WaitSwap(ClientPtr client,DrawablePtr pDrawable)1075*4882a593Smuzhiyun DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable)
1076*4882a593Smuzhiyun {
1077*4882a593Smuzhiyun     DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable);
1078*4882a593Smuzhiyun 
1079*4882a593Smuzhiyun     /* If we're currently waiting for a swap on this drawable, reset
1080*4882a593Smuzhiyun      * the request and suspend the client. */
1081*4882a593Smuzhiyun     if (pPriv && pPriv->swapsPending) {
1082*4882a593Smuzhiyun         if (dri2Sleep(client, pPriv, WAKE_SWAP)) {
1083*4882a593Smuzhiyun             ResetCurrentRequest(client);
1084*4882a593Smuzhiyun             client->sequence--;
1085*4882a593Smuzhiyun             return TRUE;
1086*4882a593Smuzhiyun         }
1087*4882a593Smuzhiyun     }
1088*4882a593Smuzhiyun 
1089*4882a593Smuzhiyun     return FALSE;
1090*4882a593Smuzhiyun }
1091*4882a593Smuzhiyun 
1092*4882a593Smuzhiyun 
1093*4882a593Smuzhiyun 
1094*4882a593Smuzhiyun int
DRI2SwapBuffers(ClientPtr client,DrawablePtr pDraw,CARD64 target_msc,CARD64 divisor,CARD64 remainder,CARD64 * swap_target,DRI2SwapEventPtr func,void * data)1095*4882a593Smuzhiyun DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
1096*4882a593Smuzhiyun                 CARD64 divisor, CARD64 remainder, CARD64 * swap_target,
1097*4882a593Smuzhiyun                 DRI2SwapEventPtr func, void *data)
1098*4882a593Smuzhiyun {
1099*4882a593Smuzhiyun     ScreenPtr pScreen = pDraw->pScreen;
1100*4882a593Smuzhiyun     DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
1101*4882a593Smuzhiyun     DRI2DrawablePtr pPriv;
1102*4882a593Smuzhiyun     DRI2BufferPtr pDestBuffer = NULL, pSrcBuffer = NULL;
1103*4882a593Smuzhiyun     int ret, i;
1104*4882a593Smuzhiyun     CARD64 ust, current_msc;
1105*4882a593Smuzhiyun 
1106*4882a593Smuzhiyun     pPriv = DRI2GetDrawable(pDraw);
1107*4882a593Smuzhiyun     if (pPriv == NULL) {
1108*4882a593Smuzhiyun         xf86DrvMsg(pScreen->myNum, X_ERROR,
1109*4882a593Smuzhiyun                    "[DRI2] %s: bad drawable\n", __func__);
1110*4882a593Smuzhiyun         return BadDrawable;
1111*4882a593Smuzhiyun     }
1112*4882a593Smuzhiyun 
1113*4882a593Smuzhiyun     /* According to spec, return expected swapbuffers count SBC after this swap
1114*4882a593Smuzhiyun      * will complete. This is ignored unless we return Success, but it must be
1115*4882a593Smuzhiyun      * initialized on every path where we return Success or the caller will send
1116*4882a593Smuzhiyun      * an uninitialized value off the stack to the client. So let's initialize
1117*4882a593Smuzhiyun      * it as early as possible, just to be sure.
1118*4882a593Smuzhiyun      */
1119*4882a593Smuzhiyun     *swap_target = pPriv->swap_count + pPriv->swapsPending + 1;
1120*4882a593Smuzhiyun 
1121*4882a593Smuzhiyun     for (i = 0; i < pPriv->bufferCount; i++) {
1122*4882a593Smuzhiyun         if (pPriv->buffers[i]->attachment == DRI2BufferFrontLeft)
1123*4882a593Smuzhiyun             pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i];
1124*4882a593Smuzhiyun         if (pPriv->buffers[i]->attachment == DRI2BufferBackLeft)
1125*4882a593Smuzhiyun             pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i];
1126*4882a593Smuzhiyun     }
1127*4882a593Smuzhiyun     if (pSrcBuffer == NULL || pDestBuffer == NULL) {
1128*4882a593Smuzhiyun         xf86DrvMsg(pScreen->myNum, X_ERROR,
1129*4882a593Smuzhiyun                    "[DRI2] %s: drawable has no back or front?\n", __func__);
1130*4882a593Smuzhiyun         return BadDrawable;
1131*4882a593Smuzhiyun     }
1132*4882a593Smuzhiyun 
1133*4882a593Smuzhiyun     /* Old DDX or no swap interval, just blit */
1134*4882a593Smuzhiyun     if (!ds->ScheduleSwap || !pPriv->swap_interval || pPriv->prime_id) {
1135*4882a593Smuzhiyun         BoxRec box;
1136*4882a593Smuzhiyun         RegionRec region;
1137*4882a593Smuzhiyun 
1138*4882a593Smuzhiyun         box.x1 = 0;
1139*4882a593Smuzhiyun         box.y1 = 0;
1140*4882a593Smuzhiyun         box.x2 = pDraw->width;
1141*4882a593Smuzhiyun         box.y2 = pDraw->height;
1142*4882a593Smuzhiyun         RegionInit(&region, &box, 0);
1143*4882a593Smuzhiyun 
1144*4882a593Smuzhiyun         pPriv->swapsPending++;
1145*4882a593Smuzhiyun 
1146*4882a593Smuzhiyun         dri2_copy_region(pDraw, &region, pDestBuffer, pSrcBuffer);
1147*4882a593Smuzhiyun         DRI2SwapComplete(client, pDraw, target_msc, 0, 0, DRI2_BLIT_COMPLETE,
1148*4882a593Smuzhiyun                          func, data);
1149*4882a593Smuzhiyun         return Success;
1150*4882a593Smuzhiyun     }
1151*4882a593Smuzhiyun 
1152*4882a593Smuzhiyun     /*
1153*4882a593Smuzhiyun      * In the simple glXSwapBuffers case, all params will be 0, and we just
1154*4882a593Smuzhiyun      * need to schedule a swap for the last swap target + the swap interval.
1155*4882a593Smuzhiyun      */
1156*4882a593Smuzhiyun     if (target_msc == 0 && divisor == 0 && remainder == 0) {
1157*4882a593Smuzhiyun         /* If the current vblank count of the drawable's crtc is lower
1158*4882a593Smuzhiyun          * than the count stored in last_swap_target from a previous swap
1159*4882a593Smuzhiyun          * then reinitialize last_swap_target to the current crtc's msc,
1160*4882a593Smuzhiyun          * otherwise the swap will hang. This will happen if the drawable
1161*4882a593Smuzhiyun          * is moved to a crtc with a lower refresh rate, or a crtc that just
1162*4882a593Smuzhiyun          * got enabled.
1163*4882a593Smuzhiyun          */
1164*4882a593Smuzhiyun         if (ds->GetMSC) {
1165*4882a593Smuzhiyun             if (!(*ds->GetMSC) (pDraw, &ust, &current_msc))
1166*4882a593Smuzhiyun                 pPriv->last_swap_target = 0;
1167*4882a593Smuzhiyun 
1168*4882a593Smuzhiyun             if (current_msc < pPriv->last_swap_target)
1169*4882a593Smuzhiyun                 pPriv->last_swap_target = current_msc;
1170*4882a593Smuzhiyun 
1171*4882a593Smuzhiyun         }
1172*4882a593Smuzhiyun 
1173*4882a593Smuzhiyun         /*
1174*4882a593Smuzhiyun          * Swap target for this swap is last swap target + swap interval since
1175*4882a593Smuzhiyun          * we have to account for the current swap count, interval, and the
1176*4882a593Smuzhiyun          * number of pending swaps.
1177*4882a593Smuzhiyun          */
1178*4882a593Smuzhiyun         target_msc = pPriv->last_swap_target + pPriv->swap_interval;
1179*4882a593Smuzhiyun 
1180*4882a593Smuzhiyun     }
1181*4882a593Smuzhiyun 
1182*4882a593Smuzhiyun     pPriv->swapsPending++;
1183*4882a593Smuzhiyun     ret = (*ds->ScheduleSwap) (client, pDraw, pDestBuffer, pSrcBuffer,
1184*4882a593Smuzhiyun                                &target_msc, divisor, remainder, func, data);
1185*4882a593Smuzhiyun     if (!ret) {
1186*4882a593Smuzhiyun         pPriv->swapsPending--;  /* didn't schedule */
1187*4882a593Smuzhiyun         xf86DrvMsg(pScreen->myNum, X_ERROR,
1188*4882a593Smuzhiyun                    "[DRI2] %s: driver failed to schedule swap\n", __func__);
1189*4882a593Smuzhiyun         return BadDrawable;
1190*4882a593Smuzhiyun     }
1191*4882a593Smuzhiyun 
1192*4882a593Smuzhiyun     pPriv->last_swap_target = target_msc;
1193*4882a593Smuzhiyun 
1194*4882a593Smuzhiyun     DRI2InvalidateDrawableAll(pDraw);
1195*4882a593Smuzhiyun 
1196*4882a593Smuzhiyun     return Success;
1197*4882a593Smuzhiyun }
1198*4882a593Smuzhiyun 
1199*4882a593Smuzhiyun void
DRI2SwapInterval(DrawablePtr pDrawable,int interval)1200*4882a593Smuzhiyun DRI2SwapInterval(DrawablePtr pDrawable, int interval)
1201*4882a593Smuzhiyun {
1202*4882a593Smuzhiyun     ScreenPtr pScreen = pDrawable->pScreen;
1203*4882a593Smuzhiyun     DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable);
1204*4882a593Smuzhiyun 
1205*4882a593Smuzhiyun     if (pPriv == NULL) {
1206*4882a593Smuzhiyun         xf86DrvMsg(pScreen->myNum, X_ERROR,
1207*4882a593Smuzhiyun                    "[DRI2] %s: bad drawable\n", __func__);
1208*4882a593Smuzhiyun         return;
1209*4882a593Smuzhiyun     }
1210*4882a593Smuzhiyun 
1211*4882a593Smuzhiyun     /* fixme: check against arbitrary max? */
1212*4882a593Smuzhiyun     pPriv->swap_interval = interval;
1213*4882a593Smuzhiyun }
1214*4882a593Smuzhiyun 
1215*4882a593Smuzhiyun int
DRI2GetMSC(DrawablePtr pDraw,CARD64 * ust,CARD64 * msc,CARD64 * sbc)1216*4882a593Smuzhiyun DRI2GetMSC(DrawablePtr pDraw, CARD64 * ust, CARD64 * msc, CARD64 * sbc)
1217*4882a593Smuzhiyun {
1218*4882a593Smuzhiyun     ScreenPtr pScreen = pDraw->pScreen;
1219*4882a593Smuzhiyun     DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
1220*4882a593Smuzhiyun     DRI2DrawablePtr pPriv;
1221*4882a593Smuzhiyun     Bool ret;
1222*4882a593Smuzhiyun 
1223*4882a593Smuzhiyun     pPriv = DRI2GetDrawable(pDraw);
1224*4882a593Smuzhiyun     if (pPriv == NULL) {
1225*4882a593Smuzhiyun         xf86DrvMsg(pScreen->myNum, X_ERROR,
1226*4882a593Smuzhiyun                    "[DRI2] %s: bad drawable\n", __func__);
1227*4882a593Smuzhiyun         return BadDrawable;
1228*4882a593Smuzhiyun     }
1229*4882a593Smuzhiyun 
1230*4882a593Smuzhiyun     if (!ds->GetMSC) {
1231*4882a593Smuzhiyun         *ust = 0;
1232*4882a593Smuzhiyun         *msc = 0;
1233*4882a593Smuzhiyun         *sbc = pPriv->swap_count;
1234*4882a593Smuzhiyun         return Success;
1235*4882a593Smuzhiyun     }
1236*4882a593Smuzhiyun 
1237*4882a593Smuzhiyun     /*
1238*4882a593Smuzhiyun      * Spec needs to be updated to include unmapped or redirected
1239*4882a593Smuzhiyun      * drawables
1240*4882a593Smuzhiyun      */
1241*4882a593Smuzhiyun 
1242*4882a593Smuzhiyun     ret = (*ds->GetMSC) (pDraw, ust, msc);
1243*4882a593Smuzhiyun     if (!ret)
1244*4882a593Smuzhiyun         return BadDrawable;
1245*4882a593Smuzhiyun 
1246*4882a593Smuzhiyun     *sbc = pPriv->swap_count;
1247*4882a593Smuzhiyun 
1248*4882a593Smuzhiyun     return Success;
1249*4882a593Smuzhiyun }
1250*4882a593Smuzhiyun 
1251*4882a593Smuzhiyun int
DRI2WaitMSC(ClientPtr client,DrawablePtr pDraw,CARD64 target_msc,CARD64 divisor,CARD64 remainder)1252*4882a593Smuzhiyun DRI2WaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
1253*4882a593Smuzhiyun             CARD64 divisor, CARD64 remainder)
1254*4882a593Smuzhiyun {
1255*4882a593Smuzhiyun     DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
1256*4882a593Smuzhiyun     DRI2DrawablePtr pPriv;
1257*4882a593Smuzhiyun     Bool ret;
1258*4882a593Smuzhiyun 
1259*4882a593Smuzhiyun     pPriv = DRI2GetDrawable(pDraw);
1260*4882a593Smuzhiyun     if (pPriv == NULL)
1261*4882a593Smuzhiyun         return BadDrawable;
1262*4882a593Smuzhiyun 
1263*4882a593Smuzhiyun     /* Old DDX just completes immediately */
1264*4882a593Smuzhiyun     if (!ds->ScheduleWaitMSC) {
1265*4882a593Smuzhiyun         DRI2WaitMSCComplete(client, pDraw, target_msc, 0, 0);
1266*4882a593Smuzhiyun 
1267*4882a593Smuzhiyun         return Success;
1268*4882a593Smuzhiyun     }
1269*4882a593Smuzhiyun 
1270*4882a593Smuzhiyun     ret =
1271*4882a593Smuzhiyun         (*ds->ScheduleWaitMSC) (client, pDraw, target_msc, divisor, remainder);
1272*4882a593Smuzhiyun     if (!ret)
1273*4882a593Smuzhiyun         return BadDrawable;
1274*4882a593Smuzhiyun 
1275*4882a593Smuzhiyun     return Success;
1276*4882a593Smuzhiyun }
1277*4882a593Smuzhiyun 
1278*4882a593Smuzhiyun int
DRI2WaitSBC(ClientPtr client,DrawablePtr pDraw,CARD64 target_sbc)1279*4882a593Smuzhiyun DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc)
1280*4882a593Smuzhiyun {
1281*4882a593Smuzhiyun     DRI2DrawablePtr pPriv;
1282*4882a593Smuzhiyun 
1283*4882a593Smuzhiyun     pPriv = DRI2GetDrawable(pDraw);
1284*4882a593Smuzhiyun     if (pPriv == NULL)
1285*4882a593Smuzhiyun         return BadDrawable;
1286*4882a593Smuzhiyun 
1287*4882a593Smuzhiyun     if (pPriv->target_sbc != -1) /* already in use */
1288*4882a593Smuzhiyun         return BadDrawable;
1289*4882a593Smuzhiyun 
1290*4882a593Smuzhiyun     /* target_sbc == 0 means to block until all pending swaps are
1291*4882a593Smuzhiyun      * finished. Recalculate target_sbc to get that behaviour.
1292*4882a593Smuzhiyun      */
1293*4882a593Smuzhiyun     if (target_sbc == 0)
1294*4882a593Smuzhiyun         target_sbc = pPriv->swap_count + pPriv->swapsPending;
1295*4882a593Smuzhiyun 
1296*4882a593Smuzhiyun     /* If current swap count already >= target_sbc, reply and
1297*4882a593Smuzhiyun      * return immediately with (ust, msc, sbc) triplet of
1298*4882a593Smuzhiyun      * most recent completed swap.
1299*4882a593Smuzhiyun      */
1300*4882a593Smuzhiyun     if (pPriv->swap_count >= target_sbc) {
1301*4882a593Smuzhiyun         ProcDRI2WaitMSCReply(client, pPriv->last_swap_ust,
1302*4882a593Smuzhiyun                              pPriv->last_swap_msc, pPriv->swap_count);
1303*4882a593Smuzhiyun         return Success;
1304*4882a593Smuzhiyun     }
1305*4882a593Smuzhiyun 
1306*4882a593Smuzhiyun     if (!dri2Sleep(client, pPriv, WAKE_SBC))
1307*4882a593Smuzhiyun         return BadAlloc;
1308*4882a593Smuzhiyun 
1309*4882a593Smuzhiyun     pPriv->target_sbc = target_sbc;
1310*4882a593Smuzhiyun     return Success;
1311*4882a593Smuzhiyun }
1312*4882a593Smuzhiyun 
1313*4882a593Smuzhiyun Bool
DRI2HasSwapControl(ScreenPtr pScreen)1314*4882a593Smuzhiyun DRI2HasSwapControl(ScreenPtr pScreen)
1315*4882a593Smuzhiyun {
1316*4882a593Smuzhiyun     DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
1317*4882a593Smuzhiyun 
1318*4882a593Smuzhiyun     return ds->ScheduleSwap && ds->GetMSC;
1319*4882a593Smuzhiyun }
1320*4882a593Smuzhiyun 
1321*4882a593Smuzhiyun Bool
DRI2Connect(ClientPtr client,ScreenPtr pScreen,unsigned int driverType,int * fd,const char ** driverName,const char ** deviceName)1322*4882a593Smuzhiyun DRI2Connect(ClientPtr client, ScreenPtr pScreen,
1323*4882a593Smuzhiyun             unsigned int driverType, int *fd,
1324*4882a593Smuzhiyun             const char **driverName, const char **deviceName)
1325*4882a593Smuzhiyun {
1326*4882a593Smuzhiyun     DRI2ScreenPtr ds;
1327*4882a593Smuzhiyun     uint32_t prime_id = DRI2DriverPrimeId(driverType);
1328*4882a593Smuzhiyun     uint32_t driver_id = driverType & 0xffff;
1329*4882a593Smuzhiyun 
1330*4882a593Smuzhiyun     if (!dixPrivateKeyRegistered(dri2ScreenPrivateKey))
1331*4882a593Smuzhiyun         return FALSE;
1332*4882a593Smuzhiyun 
1333*4882a593Smuzhiyun     ds = DRI2GetScreenPrime(pScreen, prime_id);
1334*4882a593Smuzhiyun     if (ds == NULL)
1335*4882a593Smuzhiyun         return FALSE;
1336*4882a593Smuzhiyun 
1337*4882a593Smuzhiyun     if (driver_id >= ds->numDrivers ||
1338*4882a593Smuzhiyun         !ds->driverNames[driver_id])
1339*4882a593Smuzhiyun         return FALSE;
1340*4882a593Smuzhiyun 
1341*4882a593Smuzhiyun     *driverName = ds->driverNames[driver_id];
1342*4882a593Smuzhiyun     *deviceName = ds->deviceName;
1343*4882a593Smuzhiyun     *fd = ds->fd;
1344*4882a593Smuzhiyun 
1345*4882a593Smuzhiyun     if (client) {
1346*4882a593Smuzhiyun         DRI2ClientPtr dri2_client;
1347*4882a593Smuzhiyun         dri2_client = dri2ClientPrivate(client);
1348*4882a593Smuzhiyun         dri2_client->prime_id = prime_id;
1349*4882a593Smuzhiyun     }
1350*4882a593Smuzhiyun 
1351*4882a593Smuzhiyun     return TRUE;
1352*4882a593Smuzhiyun }
1353*4882a593Smuzhiyun 
1354*4882a593Smuzhiyun static int
DRI2AuthMagic(ScreenPtr pScreen,uint32_t magic)1355*4882a593Smuzhiyun DRI2AuthMagic (ScreenPtr pScreen, uint32_t magic)
1356*4882a593Smuzhiyun {
1357*4882a593Smuzhiyun     DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
1358*4882a593Smuzhiyun     if (ds == NULL)
1359*4882a593Smuzhiyun         return -EINVAL;
1360*4882a593Smuzhiyun 
1361*4882a593Smuzhiyun     return (*ds->LegacyAuthMagic) (ds->fd, magic);
1362*4882a593Smuzhiyun }
1363*4882a593Smuzhiyun 
1364*4882a593Smuzhiyun Bool
DRI2Authenticate(ClientPtr client,ScreenPtr pScreen,uint32_t magic)1365*4882a593Smuzhiyun DRI2Authenticate(ClientPtr client, ScreenPtr pScreen, uint32_t magic)
1366*4882a593Smuzhiyun {
1367*4882a593Smuzhiyun     DRI2ScreenPtr ds;
1368*4882a593Smuzhiyun     DRI2ClientPtr dri2_client = dri2ClientPrivate(client);
1369*4882a593Smuzhiyun     ScreenPtr primescreen;
1370*4882a593Smuzhiyun 
1371*4882a593Smuzhiyun     ds = DRI2GetScreenPrime(pScreen, dri2_client->prime_id);
1372*4882a593Smuzhiyun     if (ds == NULL)
1373*4882a593Smuzhiyun         return FALSE;
1374*4882a593Smuzhiyun 
1375*4882a593Smuzhiyun     primescreen = GetScreenPrime(pScreen, dri2_client->prime_id);
1376*4882a593Smuzhiyun     if ((*ds->AuthMagic)(primescreen, magic))
1377*4882a593Smuzhiyun         return FALSE;
1378*4882a593Smuzhiyun     return TRUE;
1379*4882a593Smuzhiyun }
1380*4882a593Smuzhiyun 
1381*4882a593Smuzhiyun static int
DRI2ConfigNotify(WindowPtr pWin,int x,int y,int w,int h,int bw,WindowPtr pSib)1382*4882a593Smuzhiyun DRI2ConfigNotify(WindowPtr pWin, int x, int y, int w, int h, int bw,
1383*4882a593Smuzhiyun                  WindowPtr pSib)
1384*4882a593Smuzhiyun {
1385*4882a593Smuzhiyun     DrawablePtr pDraw = (DrawablePtr) pWin;
1386*4882a593Smuzhiyun     ScreenPtr pScreen = pDraw->pScreen;
1387*4882a593Smuzhiyun     DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
1388*4882a593Smuzhiyun     DRI2DrawablePtr dd = DRI2GetDrawable(pDraw);
1389*4882a593Smuzhiyun     int ret;
1390*4882a593Smuzhiyun 
1391*4882a593Smuzhiyun     if (ds->ConfigNotify) {
1392*4882a593Smuzhiyun         pScreen->ConfigNotify = ds->ConfigNotify;
1393*4882a593Smuzhiyun 
1394*4882a593Smuzhiyun         ret = (*pScreen->ConfigNotify) (pWin, x, y, w, h, bw, pSib);
1395*4882a593Smuzhiyun 
1396*4882a593Smuzhiyun         ds->ConfigNotify = pScreen->ConfigNotify;
1397*4882a593Smuzhiyun         pScreen->ConfigNotify = DRI2ConfigNotify;
1398*4882a593Smuzhiyun         if (ret)
1399*4882a593Smuzhiyun             return ret;
1400*4882a593Smuzhiyun     }
1401*4882a593Smuzhiyun 
1402*4882a593Smuzhiyun     if (!dd || (dd->width == w && dd->height == h))
1403*4882a593Smuzhiyun         return Success;
1404*4882a593Smuzhiyun 
1405*4882a593Smuzhiyun     DRI2InvalidateDrawable(pDraw);
1406*4882a593Smuzhiyun     return Success;
1407*4882a593Smuzhiyun }
1408*4882a593Smuzhiyun 
1409*4882a593Smuzhiyun static void
DRI2SetWindowPixmap(WindowPtr pWin,PixmapPtr pPix)1410*4882a593Smuzhiyun DRI2SetWindowPixmap(WindowPtr pWin, PixmapPtr pPix)
1411*4882a593Smuzhiyun {
1412*4882a593Smuzhiyun     ScreenPtr pScreen = pWin->drawable.pScreen;
1413*4882a593Smuzhiyun     DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
1414*4882a593Smuzhiyun 
1415*4882a593Smuzhiyun     pScreen->SetWindowPixmap = ds->SetWindowPixmap;
1416*4882a593Smuzhiyun     (*pScreen->SetWindowPixmap) (pWin, pPix);
1417*4882a593Smuzhiyun     ds->SetWindowPixmap = pScreen->SetWindowPixmap;
1418*4882a593Smuzhiyun     pScreen->SetWindowPixmap = DRI2SetWindowPixmap;
1419*4882a593Smuzhiyun 
1420*4882a593Smuzhiyun     DRI2InvalidateDrawable(&pWin->drawable);
1421*4882a593Smuzhiyun }
1422*4882a593Smuzhiyun 
1423*4882a593Smuzhiyun #define MAX_PRIME DRI2DriverPrimeMask
1424*4882a593Smuzhiyun static int
get_prime_id(void)1425*4882a593Smuzhiyun get_prime_id(void)
1426*4882a593Smuzhiyun {
1427*4882a593Smuzhiyun     int i;
1428*4882a593Smuzhiyun     /* start at 1, prime id 0 is just normal driver */
1429*4882a593Smuzhiyun     for (i = 1; i < MAX_PRIME; i++) {
1430*4882a593Smuzhiyun          if (prime_id_allocate_bitmask & (1 << i))
1431*4882a593Smuzhiyun              continue;
1432*4882a593Smuzhiyun 
1433*4882a593Smuzhiyun          prime_id_allocate_bitmask |= (1 << i);
1434*4882a593Smuzhiyun          return i;
1435*4882a593Smuzhiyun     }
1436*4882a593Smuzhiyun     return -1;
1437*4882a593Smuzhiyun }
1438*4882a593Smuzhiyun 
1439*4882a593Smuzhiyun #include "pci_ids/pci_id_driver_map.h"
1440*4882a593Smuzhiyun 
1441*4882a593Smuzhiyun static char *
dri2_probe_driver_name(ScreenPtr pScreen,DRI2InfoPtr info)1442*4882a593Smuzhiyun dri2_probe_driver_name(ScreenPtr pScreen, DRI2InfoPtr info)
1443*4882a593Smuzhiyun {
1444*4882a593Smuzhiyun #ifdef WITH_LIBDRM
1445*4882a593Smuzhiyun     int i, j;
1446*4882a593Smuzhiyun     char *driver = NULL;
1447*4882a593Smuzhiyun     drmDevicePtr dev = NULL;
1448*4882a593Smuzhiyun 
1449*4882a593Smuzhiyun     /* For non-PCI devices and drmGetDevice fail, just assume that
1450*4882a593Smuzhiyun      * the 3D driver is named the same as the kernel driver. This is
1451*4882a593Smuzhiyun      * currently true for vc4 and msm (freedreno).
1452*4882a593Smuzhiyun      */
1453*4882a593Smuzhiyun     if (drmGetDevice(info->fd, &dev) || dev->bustype != DRM_BUS_PCI) {
1454*4882a593Smuzhiyun         drmVersionPtr version = drmGetVersion(info->fd);
1455*4882a593Smuzhiyun 
1456*4882a593Smuzhiyun         if (!version) {
1457*4882a593Smuzhiyun             xf86DrvMsg(pScreen->myNum, X_ERROR,
1458*4882a593Smuzhiyun                        "[DRI2] Couldn't drmGetVersion() on non-PCI device, "
1459*4882a593Smuzhiyun                        "no driver name found.\n");
1460*4882a593Smuzhiyun             return NULL;
1461*4882a593Smuzhiyun         }
1462*4882a593Smuzhiyun 
1463*4882a593Smuzhiyun         driver = strndup(version->name, version->name_len);
1464*4882a593Smuzhiyun         drmFreeVersion(version);
1465*4882a593Smuzhiyun         drmFreeDevice(&dev);
1466*4882a593Smuzhiyun         return driver;
1467*4882a593Smuzhiyun     }
1468*4882a593Smuzhiyun 
1469*4882a593Smuzhiyun     for (i = 0; driver_map[i].driver; i++) {
1470*4882a593Smuzhiyun         if (dev->deviceinfo.pci->vendor_id != driver_map[i].vendor_id)
1471*4882a593Smuzhiyun             continue;
1472*4882a593Smuzhiyun 
1473*4882a593Smuzhiyun         if (driver_map[i].num_chips_ids == -1) {
1474*4882a593Smuzhiyun              driver = strdup(driver_map[i].driver);
1475*4882a593Smuzhiyun              goto out;
1476*4882a593Smuzhiyun         }
1477*4882a593Smuzhiyun 
1478*4882a593Smuzhiyun         for (j = 0; j < driver_map[i].num_chips_ids; j++) {
1479*4882a593Smuzhiyun             if (driver_map[i].chip_ids[j] == dev->deviceinfo.pci->device_id) {
1480*4882a593Smuzhiyun                 driver = strdup(driver_map[i].driver);
1481*4882a593Smuzhiyun                 goto out;
1482*4882a593Smuzhiyun             }
1483*4882a593Smuzhiyun         }
1484*4882a593Smuzhiyun     }
1485*4882a593Smuzhiyun 
1486*4882a593Smuzhiyun     xf86DrvMsg(pScreen->myNum, X_ERROR,
1487*4882a593Smuzhiyun                "[DRI2] No driver mapping found for PCI device "
1488*4882a593Smuzhiyun                "0x%04x / 0x%04x\n",
1489*4882a593Smuzhiyun                dev->deviceinfo.pci->vendor_id, dev->deviceinfo.pci->device_id);
1490*4882a593Smuzhiyun out:
1491*4882a593Smuzhiyun     drmFreeDevice(&dev);
1492*4882a593Smuzhiyun     return driver;
1493*4882a593Smuzhiyun #else
1494*4882a593Smuzhiyun     return NULL;
1495*4882a593Smuzhiyun #endif
1496*4882a593Smuzhiyun }
1497*4882a593Smuzhiyun 
1498*4882a593Smuzhiyun Bool
DRI2ScreenInit(ScreenPtr pScreen,DRI2InfoPtr info)1499*4882a593Smuzhiyun DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
1500*4882a593Smuzhiyun {
1501*4882a593Smuzhiyun     DRI2ScreenPtr ds;
1502*4882a593Smuzhiyun 
1503*4882a593Smuzhiyun     const char *driverTypeNames[] = {
1504*4882a593Smuzhiyun         "DRI",                  /* DRI2DriverDRI */
1505*4882a593Smuzhiyun         "VDPAU",                /* DRI2DriverVDPAU */
1506*4882a593Smuzhiyun     };
1507*4882a593Smuzhiyun     unsigned int i;
1508*4882a593Smuzhiyun     CARD8 cur_minor;
1509*4882a593Smuzhiyun 
1510*4882a593Smuzhiyun     if (info->version < 3)
1511*4882a593Smuzhiyun         return FALSE;
1512*4882a593Smuzhiyun 
1513*4882a593Smuzhiyun     if (!xf86VGAarbiterAllowDRI(pScreen)) {
1514*4882a593Smuzhiyun         xf86DrvMsg(pScreen->myNum, X_WARNING,
1515*4882a593Smuzhiyun                    "[DRI2] Direct rendering is not supported when VGA arb is necessary for the device\n");
1516*4882a593Smuzhiyun         return FALSE;
1517*4882a593Smuzhiyun     }
1518*4882a593Smuzhiyun 
1519*4882a593Smuzhiyun     if (!dixRegisterPrivateKey(&dri2ScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
1520*4882a593Smuzhiyun         return FALSE;
1521*4882a593Smuzhiyun 
1522*4882a593Smuzhiyun     if (!dixRegisterPrivateKey(&dri2WindowPrivateKeyRec, PRIVATE_WINDOW, 0))
1523*4882a593Smuzhiyun         return FALSE;
1524*4882a593Smuzhiyun 
1525*4882a593Smuzhiyun     if (!dixRegisterPrivateKey(&dri2PixmapPrivateKeyRec, PRIVATE_PIXMAP, 0))
1526*4882a593Smuzhiyun         return FALSE;
1527*4882a593Smuzhiyun 
1528*4882a593Smuzhiyun     if (!dixRegisterPrivateKey(&dri2ClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(DRI2ClientRec)))
1529*4882a593Smuzhiyun         return FALSE;
1530*4882a593Smuzhiyun 
1531*4882a593Smuzhiyun     ds = calloc(1, sizeof *ds);
1532*4882a593Smuzhiyun     if (!ds)
1533*4882a593Smuzhiyun         return FALSE;
1534*4882a593Smuzhiyun 
1535*4882a593Smuzhiyun     ds->screen = pScreen;
1536*4882a593Smuzhiyun     ds->fd = info->fd;
1537*4882a593Smuzhiyun     ds->deviceName = info->deviceName;
1538*4882a593Smuzhiyun     dri2_major = 1;
1539*4882a593Smuzhiyun 
1540*4882a593Smuzhiyun     ds->CreateBuffer = info->CreateBuffer;
1541*4882a593Smuzhiyun     ds->DestroyBuffer = info->DestroyBuffer;
1542*4882a593Smuzhiyun     ds->CopyRegion = info->CopyRegion;
1543*4882a593Smuzhiyun     cur_minor = 1;
1544*4882a593Smuzhiyun 
1545*4882a593Smuzhiyun     if (info->version >= 4) {
1546*4882a593Smuzhiyun         ds->ScheduleSwap = info->ScheduleSwap;
1547*4882a593Smuzhiyun         ds->ScheduleWaitMSC = info->ScheduleWaitMSC;
1548*4882a593Smuzhiyun         ds->GetMSC = info->GetMSC;
1549*4882a593Smuzhiyun         cur_minor = 3;
1550*4882a593Smuzhiyun     }
1551*4882a593Smuzhiyun 
1552*4882a593Smuzhiyun     if (info->version >= 5) {
1553*4882a593Smuzhiyun         ds->LegacyAuthMagic = info->AuthMagic;
1554*4882a593Smuzhiyun     }
1555*4882a593Smuzhiyun 
1556*4882a593Smuzhiyun     if (info->version >= 6) {
1557*4882a593Smuzhiyun         ds->ReuseBufferNotify = info->ReuseBufferNotify;
1558*4882a593Smuzhiyun         ds->SwapLimitValidate = info->SwapLimitValidate;
1559*4882a593Smuzhiyun     }
1560*4882a593Smuzhiyun 
1561*4882a593Smuzhiyun     if (info->version >= 7) {
1562*4882a593Smuzhiyun         ds->GetParam = info->GetParam;
1563*4882a593Smuzhiyun         cur_minor = 4;
1564*4882a593Smuzhiyun     }
1565*4882a593Smuzhiyun 
1566*4882a593Smuzhiyun     if (info->version >= 8) {
1567*4882a593Smuzhiyun         ds->AuthMagic = info->AuthMagic2;
1568*4882a593Smuzhiyun     }
1569*4882a593Smuzhiyun 
1570*4882a593Smuzhiyun     if (info->version >= 9) {
1571*4882a593Smuzhiyun         ds->CreateBuffer2 = info->CreateBuffer2;
1572*4882a593Smuzhiyun         if (info->CreateBuffer2 && pScreen->isGPU) {
1573*4882a593Smuzhiyun             ds->prime_id = get_prime_id();
1574*4882a593Smuzhiyun             if (ds->prime_id == -1) {
1575*4882a593Smuzhiyun                 free(ds);
1576*4882a593Smuzhiyun                 return FALSE;
1577*4882a593Smuzhiyun             }
1578*4882a593Smuzhiyun         }
1579*4882a593Smuzhiyun         ds->DestroyBuffer2 = info->DestroyBuffer2;
1580*4882a593Smuzhiyun         ds->CopyRegion2 = info->CopyRegion2;
1581*4882a593Smuzhiyun     }
1582*4882a593Smuzhiyun 
1583*4882a593Smuzhiyun     /*
1584*4882a593Smuzhiyun      * if the driver doesn't provide an AuthMagic function or the info struct
1585*4882a593Smuzhiyun      * version is too low, call through LegacyAuthMagic
1586*4882a593Smuzhiyun      */
1587*4882a593Smuzhiyun     if (!ds->AuthMagic) {
1588*4882a593Smuzhiyun         ds->AuthMagic = DRI2AuthMagic;
1589*4882a593Smuzhiyun         /*
1590*4882a593Smuzhiyun          * If the driver doesn't provide an AuthMagic function
1591*4882a593Smuzhiyun          * it relies on the old method (using libdrm) or fails
1592*4882a593Smuzhiyun          */
1593*4882a593Smuzhiyun         if (!ds->LegacyAuthMagic)
1594*4882a593Smuzhiyun #ifdef WITH_LIBDRM
1595*4882a593Smuzhiyun             ds->LegacyAuthMagic = drmAuthMagic;
1596*4882a593Smuzhiyun #else
1597*4882a593Smuzhiyun             goto err_out;
1598*4882a593Smuzhiyun #endif
1599*4882a593Smuzhiyun     }
1600*4882a593Smuzhiyun 
1601*4882a593Smuzhiyun     /* Initialize minor if needed and set to minimum provied by DDX */
1602*4882a593Smuzhiyun     if (!dri2_minor || dri2_minor > cur_minor)
1603*4882a593Smuzhiyun         dri2_minor = cur_minor;
1604*4882a593Smuzhiyun 
1605*4882a593Smuzhiyun     if (info->version == 3 || info->numDrivers == 0) {
1606*4882a593Smuzhiyun         /* Driver too old: use the old-style driverName field */
1607*4882a593Smuzhiyun         ds->numDrivers = info->driverName ? 1 : 2;
1608*4882a593Smuzhiyun         ds->driverNames = xallocarray(ds->numDrivers, sizeof(*ds->driverNames));
1609*4882a593Smuzhiyun         if (!ds->driverNames)
1610*4882a593Smuzhiyun             goto err_out;
1611*4882a593Smuzhiyun 
1612*4882a593Smuzhiyun         if (info->driverName) {
1613*4882a593Smuzhiyun             ds->driverNames[0] = info->driverName;
1614*4882a593Smuzhiyun         } else {
1615*4882a593Smuzhiyun             ds->driverName = dri2_probe_driver_name(pScreen, info);
1616*4882a593Smuzhiyun             ds->driverNames[0] = ds->driverNames[1] = ds->driverName;
1617*4882a593Smuzhiyun             if (!ds->driverNames[0])
1618*4882a593Smuzhiyun                 return FALSE;
1619*4882a593Smuzhiyun         }
1620*4882a593Smuzhiyun     }
1621*4882a593Smuzhiyun     else {
1622*4882a593Smuzhiyun         ds->numDrivers = info->numDrivers;
1623*4882a593Smuzhiyun         ds->driverNames = xallocarray(info->numDrivers, sizeof(*ds->driverNames));
1624*4882a593Smuzhiyun         if (!ds->driverNames)
1625*4882a593Smuzhiyun             goto err_out;
1626*4882a593Smuzhiyun         memcpy(ds->driverNames, info->driverNames,
1627*4882a593Smuzhiyun                info->numDrivers * sizeof(*ds->driverNames));
1628*4882a593Smuzhiyun     }
1629*4882a593Smuzhiyun 
1630*4882a593Smuzhiyun     dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds);
1631*4882a593Smuzhiyun 
1632*4882a593Smuzhiyun     ds->ConfigNotify = pScreen->ConfigNotify;
1633*4882a593Smuzhiyun     pScreen->ConfigNotify = DRI2ConfigNotify;
1634*4882a593Smuzhiyun 
1635*4882a593Smuzhiyun     ds->SetWindowPixmap = pScreen->SetWindowPixmap;
1636*4882a593Smuzhiyun     pScreen->SetWindowPixmap = DRI2SetWindowPixmap;
1637*4882a593Smuzhiyun 
1638*4882a593Smuzhiyun     xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n");
1639*4882a593Smuzhiyun     for (i = 0; i < ARRAY_SIZE(driverTypeNames); i++) {
1640*4882a593Smuzhiyun         if (i < ds->numDrivers && ds->driverNames[i]) {
1641*4882a593Smuzhiyun             xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2]   %s driver: %s\n",
1642*4882a593Smuzhiyun                        driverTypeNames[i], ds->driverNames[i]);
1643*4882a593Smuzhiyun         }
1644*4882a593Smuzhiyun     }
1645*4882a593Smuzhiyun 
1646*4882a593Smuzhiyun     return TRUE;
1647*4882a593Smuzhiyun 
1648*4882a593Smuzhiyun  err_out:
1649*4882a593Smuzhiyun     xf86DrvMsg(pScreen->myNum, X_WARNING,
1650*4882a593Smuzhiyun                "[DRI2] Initialization failed for info version %d.\n",
1651*4882a593Smuzhiyun                info->version);
1652*4882a593Smuzhiyun     free(ds);
1653*4882a593Smuzhiyun     return FALSE;
1654*4882a593Smuzhiyun }
1655*4882a593Smuzhiyun 
1656*4882a593Smuzhiyun void
DRI2CloseScreen(ScreenPtr pScreen)1657*4882a593Smuzhiyun DRI2CloseScreen(ScreenPtr pScreen)
1658*4882a593Smuzhiyun {
1659*4882a593Smuzhiyun     DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
1660*4882a593Smuzhiyun 
1661*4882a593Smuzhiyun     pScreen->ConfigNotify = ds->ConfigNotify;
1662*4882a593Smuzhiyun     pScreen->SetWindowPixmap = ds->SetWindowPixmap;
1663*4882a593Smuzhiyun 
1664*4882a593Smuzhiyun     if (ds->prime_id)
1665*4882a593Smuzhiyun         prime_id_allocate_bitmask &= ~(1 << ds->prime_id);
1666*4882a593Smuzhiyun     free(ds->driverNames);
1667*4882a593Smuzhiyun     free((char *)ds->driverName);
1668*4882a593Smuzhiyun     free(ds);
1669*4882a593Smuzhiyun     dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, NULL);
1670*4882a593Smuzhiyun }
1671*4882a593Smuzhiyun 
1672*4882a593Smuzhiyun /* Called by InitExtensions() */
1673*4882a593Smuzhiyun Bool
DRI2ModuleSetup(void)1674*4882a593Smuzhiyun DRI2ModuleSetup(void)
1675*4882a593Smuzhiyun {
1676*4882a593Smuzhiyun     dri2DrawableRes = CreateNewResourceType(DRI2DrawableGone, "DRI2Drawable");
1677*4882a593Smuzhiyun     if (!dri2DrawableRes)
1678*4882a593Smuzhiyun         return FALSE;
1679*4882a593Smuzhiyun 
1680*4882a593Smuzhiyun     return TRUE;
1681*4882a593Smuzhiyun }
1682*4882a593Smuzhiyun 
1683*4882a593Smuzhiyun void
DRI2Version(int * major,int * minor)1684*4882a593Smuzhiyun DRI2Version(int *major, int *minor)
1685*4882a593Smuzhiyun {
1686*4882a593Smuzhiyun     if (major != NULL)
1687*4882a593Smuzhiyun         *major = 1;
1688*4882a593Smuzhiyun 
1689*4882a593Smuzhiyun     if (minor != NULL)
1690*4882a593Smuzhiyun         *minor = 2;
1691*4882a593Smuzhiyun }
1692*4882a593Smuzhiyun 
1693*4882a593Smuzhiyun int
DRI2GetParam(ClientPtr client,DrawablePtr drawable,CARD64 param,BOOL * is_param_recognized,CARD64 * value)1694*4882a593Smuzhiyun DRI2GetParam(ClientPtr client,
1695*4882a593Smuzhiyun              DrawablePtr drawable,
1696*4882a593Smuzhiyun              CARD64 param,
1697*4882a593Smuzhiyun              BOOL *is_param_recognized,
1698*4882a593Smuzhiyun              CARD64 *value)
1699*4882a593Smuzhiyun {
1700*4882a593Smuzhiyun     DRI2ScreenPtr ds = DRI2GetScreen(drawable->pScreen);
1701*4882a593Smuzhiyun     char high_byte = (param >> 24);
1702*4882a593Smuzhiyun 
1703*4882a593Smuzhiyun     switch (high_byte) {
1704*4882a593Smuzhiyun     case 0:
1705*4882a593Smuzhiyun         /* Parameter names whose high_byte is 0 are reserved for the X
1706*4882a593Smuzhiyun          * server. The server currently recognizes no parameters.
1707*4882a593Smuzhiyun          */
1708*4882a593Smuzhiyun         goto not_recognized;
1709*4882a593Smuzhiyun     case 1:
1710*4882a593Smuzhiyun         /* Parameter names whose high byte is 1 are reserved for the DDX. */
1711*4882a593Smuzhiyun         if (ds->GetParam)
1712*4882a593Smuzhiyun             return ds->GetParam(client, drawable, param,
1713*4882a593Smuzhiyun                                 is_param_recognized, value);
1714*4882a593Smuzhiyun         else
1715*4882a593Smuzhiyun             goto not_recognized;
1716*4882a593Smuzhiyun     default:
1717*4882a593Smuzhiyun         /* Other parameter names are reserved for future use. They are never
1718*4882a593Smuzhiyun          * recognized.
1719*4882a593Smuzhiyun          */
1720*4882a593Smuzhiyun         goto not_recognized;
1721*4882a593Smuzhiyun     }
1722*4882a593Smuzhiyun 
1723*4882a593Smuzhiyun not_recognized:
1724*4882a593Smuzhiyun     *is_param_recognized = FALSE;
1725*4882a593Smuzhiyun     return Success;
1726*4882a593Smuzhiyun }
1727