dri2.c revision 4642e01f
1/*
2 * Copyright © 2007, 2008 Red Hat, Inc.
3 *
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.
13 *
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.
23 *
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.
28 *
29 * Authors:
30 *   Kristian Høgsberg (krh@redhat.com)
31 */
32
33#ifdef HAVE_XORG_CONFIG_H
34#include <xorg-config.h>
35#endif
36
37#include <xf86drm.h>
38#include "xf86Module.h"
39#include "scrnintstr.h"
40#include "windowstr.h"
41#include "dri2.h"
42
43#include "xf86.h"
44
45static int dri2ScreenPrivateKeyIndex;
46static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex;
47static int dri2WindowPrivateKeyIndex;
48static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex;
49static int dri2PixmapPrivateKeyIndex;
50static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex;
51
52typedef struct _DRI2Drawable {
53    unsigned int	 refCount;
54    int			 width;
55    int			 height;
56    DRI2BufferPtr	 buffers;
57    int			 bufferCount;
58    unsigned int	 pendingSequence;
59} DRI2DrawableRec, *DRI2DrawablePtr;
60
61typedef struct _DRI2Screen {
62    const char			*driverName;
63    const char			*deviceName;
64    int				 fd;
65    unsigned int		 lastSequence;
66    DRI2CreateBuffersProcPtr	 CreateBuffers;
67    DRI2DestroyBuffersProcPtr	 DestroyBuffers;
68    DRI2CopyRegionProcPtr	 CopyRegion;
69
70    HandleExposuresProcPtr       HandleExposures;
71} DRI2ScreenRec, *DRI2ScreenPtr;
72
73static DRI2ScreenPtr
74DRI2GetScreen(ScreenPtr pScreen)
75{
76    return dixLookupPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey);
77}
78
79static DRI2DrawablePtr
80DRI2GetDrawable(DrawablePtr pDraw)
81{
82    WindowPtr		  pWin;
83    PixmapPtr		  pPixmap;
84
85    if (pDraw->type == DRAWABLE_WINDOW)
86    {
87	pWin = (WindowPtr) pDraw;
88	return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
89    }
90    else
91    {
92	pPixmap = (PixmapPtr) pDraw;
93	return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
94    }
95}
96
97int
98DRI2CreateDrawable(DrawablePtr pDraw)
99{
100    WindowPtr	    pWin;
101    PixmapPtr	    pPixmap;
102    DRI2DrawablePtr pPriv;
103
104    pPriv = DRI2GetDrawable(pDraw);
105    if (pPriv != NULL)
106    {
107	pPriv->refCount++;
108	return Success;
109    }
110
111    pPriv = xalloc(sizeof *pPriv);
112    if (pPriv == NULL)
113	return BadAlloc;
114
115    pPriv->refCount = 1;
116    pPriv->width = pDraw->width;
117    pPriv->height = pDraw->height;
118    pPriv->buffers = NULL;
119    pPriv->bufferCount = 0;
120
121    if (pDraw->type == DRAWABLE_WINDOW)
122    {
123	pWin = (WindowPtr) pDraw;
124	dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv);
125    }
126    else
127    {
128	pPixmap = (PixmapPtr) pDraw;
129	dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv);
130    }
131
132    return Success;
133}
134
135DRI2BufferPtr
136DRI2GetBuffers(DrawablePtr pDraw, int *width, int *height,
137	       unsigned int *attachments, int count, int *out_count)
138{
139    DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
140    DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
141    DRI2BufferPtr   buffers;
142
143    if (pPriv->buffers == NULL ||
144	pDraw->width != pPriv->width || pDraw->height != pPriv->height)
145    {
146	buffers = (*ds->CreateBuffers)(pDraw, attachments, count);
147	(*ds->DestroyBuffers)(pDraw, pPriv->buffers, pPriv->bufferCount);
148	pPriv->buffers = buffers;
149	pPriv->bufferCount = count;
150	pPriv->width = pDraw->width;
151	pPriv->height = pDraw->height;
152    }
153
154    *width = pPriv->width;
155    *height = pPriv->height;
156    *out_count = pPriv->bufferCount;
157
158    return pPriv->buffers;
159}
160
161int
162DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
163	       unsigned int dest, unsigned int src)
164{
165    DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
166    DRI2DrawablePtr pPriv;
167    DRI2BufferPtr   pDestBuffer, pSrcBuffer;
168    int		    i;
169
170    pPriv = DRI2GetDrawable(pDraw);
171    if (pPriv == NULL)
172	return BadDrawable;
173
174    pDestBuffer = NULL;
175    pSrcBuffer = NULL;
176    for (i = 0; i < pPriv->bufferCount; i++)
177    {
178	if (pPriv->buffers[i].attachment == dest)
179	    pDestBuffer = &pPriv->buffers[i];
180	if (pPriv->buffers[i].attachment == src)
181	    pSrcBuffer = &pPriv->buffers[i];
182    }
183    if (pSrcBuffer == NULL || pDestBuffer == NULL)
184	return BadValue;
185
186    (*ds->CopyRegion)(pDraw, pRegion, pDestBuffer, pSrcBuffer);
187
188    return Success;
189}
190
191void
192DRI2DestroyDrawable(DrawablePtr pDraw)
193{
194    DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
195    DRI2DrawablePtr pPriv;
196    WindowPtr  	    pWin;
197    PixmapPtr	    pPixmap;
198
199    pPriv = DRI2GetDrawable(pDraw);
200    if (pPriv == NULL)
201	return;
202
203    pPriv->refCount--;
204    if (pPriv->refCount > 0)
205	return;
206
207    (*ds->DestroyBuffers)(pDraw, pPriv->buffers, pPriv->bufferCount);
208    xfree(pPriv);
209
210    if (pDraw->type == DRAWABLE_WINDOW)
211    {
212	pWin = (WindowPtr) pDraw;
213	dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
214    }
215    else
216    {
217	pPixmap = (PixmapPtr) pDraw;
218	dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
219    }
220}
221
222Bool
223DRI2Connect(ScreenPtr pScreen, unsigned int driverType, int *fd,
224	    const char **driverName, const char **deviceName)
225{
226    DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
227
228    if (ds == NULL)
229	return FALSE;
230
231    if (driverType != DRI2DriverDRI)
232	return BadValue;
233
234    *fd = ds->fd;
235    *driverName = ds->driverName;
236    *deviceName = ds->deviceName;
237
238    return TRUE;
239}
240
241Bool
242DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic)
243{
244    DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
245
246    if (ds == NULL || drmAuthMagic(ds->fd, magic))
247	return FALSE;
248
249    return TRUE;
250}
251
252Bool
253DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
254{
255    DRI2ScreenPtr ds;
256
257    ds = xalloc(sizeof *ds);
258    if (!ds)
259	return FALSE;
260
261    ds->fd	       = info->fd;
262    ds->driverName     = info->driverName;
263    ds->deviceName     = info->deviceName;
264    ds->CreateBuffers  = info->CreateBuffers;
265    ds->DestroyBuffers = info->DestroyBuffers;
266    ds->CopyRegion     = info->CopyRegion;
267
268    dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds);
269
270    xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n");
271
272    return TRUE;
273}
274
275void
276DRI2CloseScreen(ScreenPtr pScreen)
277{
278    DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
279
280    xfree(ds);
281    dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, NULL);
282}
283
284extern ExtensionModule dri2ExtensionModule;
285
286static pointer
287DRI2Setup(pointer module, pointer opts, int *errmaj, int *errmin)
288{
289    static Bool setupDone = FALSE;
290
291    if (!setupDone)
292    {
293	setupDone = TRUE;
294	LoadExtension(&dri2ExtensionModule, FALSE);
295    }
296    else
297    {
298	if (errmaj)
299	    *errmaj = LDR_ONCEONLY;
300    }
301
302    return (pointer) 1;
303}
304
305static XF86ModuleVersionInfo DRI2VersRec =
306{
307    "dri2",
308    MODULEVENDORSTRING,
309    MODINFOSTRING1,
310    MODINFOSTRING2,
311    XORG_VERSION_CURRENT,
312    1, 0, 0,
313    ABI_CLASS_EXTENSION,
314    ABI_EXTENSION_VERSION,
315    MOD_CLASS_NONE,
316    { 0, 0, 0, 0 }
317};
318
319_X_EXPORT XF86ModuleData dri2ModuleData = { &DRI2VersRec, DRI2Setup, NULL };
320
321