appledri.c revision 6747b715
1/**************************************************************************
2
3Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4Copyright 2000 VA Linux Systems, Inc.
5Copyright (c) 2002, 2009 Apple Computer, Inc.
6All Rights Reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining a
9copy of this software and associated documentation files (the
10"Software"), to deal in the Software without restriction, including
11without limitation the rights to use, copy, modify, merge, publish,
12distribute, sub license, and/or sell copies of the Software, and to
13permit persons to whom the Software is furnished to do so, subject to
14the following conditions:
15
16The above copyright notice and this permission notice (including the
17next paragraph) shall be included in all copies or substantial portions
18of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
24ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28**************************************************************************/
29
30/*
31 * Authors:
32 *   Kevin E. Martin <martin@valinux.com>
33 *   Jens Owen <jens@valinux.com>
34 *   Rickard E. (Rik) Faith <faith@valinux.com>
35 *
36 */
37
38#ifdef HAVE_DIX_CONFIG_H
39#include <dix-config.h>
40#endif
41
42#include <X11/X.h>
43#include <X11/Xproto.h>
44#include "misc.h"
45#include "dixstruct.h"
46#include "extnsionst.h"
47#include "colormapst.h"
48#include "cursorstr.h"
49#include "scrnintstr.h"
50#include "servermd.h"
51#define _APPLEDRI_SERVER_
52#include "appledristr.h"
53#include "swaprep.h"
54#include "dri.h"
55#include "dristruct.h"
56#include "xpr.h"
57#include "x-hash.h"
58#include "protocol-versions.h"
59
60static int DRIErrorBase = 0;
61
62static DISPATCH_PROC(ProcAppleDRIDispatch);
63static DISPATCH_PROC(SProcAppleDRIDispatch);
64
65static void AppleDRIResetProc(ExtensionEntry* extEntry);
66static int ProcAppleDRICreatePixmap(ClientPtr client);
67
68static unsigned char DRIReqCode = 0;
69static int DRIEventBase = 0;
70
71static void SNotifyEvent(xAppleDRINotifyEvent *from, xAppleDRINotifyEvent *to);
72
73typedef struct _DRIEvent *DRIEventPtr;
74typedef struct _DRIEvent {
75    DRIEventPtr     next;
76    ClientPtr       client;
77    XID             clientResource;
78    unsigned int    mask;
79} DRIEventRec;
80
81
82void
83AppleDRIExtensionInit(void)
84{
85    ExtensionEntry* extEntry;
86
87    if (DRIExtensionInit() &&
88        (extEntry = AddExtension(APPLEDRINAME,
89                                 AppleDRINumberEvents,
90                                 AppleDRINumberErrors,
91                                 ProcAppleDRIDispatch,
92                                 SProcAppleDRIDispatch,
93                                 AppleDRIResetProc,
94                                 StandardMinorOpcode))) {
95        DRIReqCode = (unsigned char)extEntry->base;
96        DRIErrorBase = extEntry->errorBase;
97        DRIEventBase = extEntry->eventBase;
98        EventSwapVector[DRIEventBase] = (EventSwapPtr) SNotifyEvent;
99    }
100}
101
102/*ARGSUSED*/
103static void
104AppleDRIResetProc (
105    ExtensionEntry* extEntry
106)
107{
108    DRIReset();
109}
110
111static int
112ProcAppleDRIQueryVersion(
113    register ClientPtr client
114)
115{
116    xAppleDRIQueryVersionReply rep;
117    register int n;
118
119    REQUEST_SIZE_MATCH(xAppleDRIQueryVersionReq);
120    rep.type = X_Reply;
121    rep.length = 0;
122    rep.sequenceNumber = client->sequence;
123    rep.majorVersion = SERVER_APPLEDRI_MAJOR_VERSION;
124    rep.minorVersion = SERVER_APPLEDRI_MINOR_VERSION;
125    rep.patchVersion = SERVER_APPLEDRI_PATCH_VERSION;
126    if (client->swapped) {
127        swaps(&rep.sequenceNumber, n);
128        swapl(&rep.length, n);
129    }
130    WriteToClient(client, sizeof(xAppleDRIQueryVersionReply), (char *)&rep);
131    return Success;
132}
133
134
135/* surfaces */
136
137static int
138ProcAppleDRIQueryDirectRenderingCapable(
139    register ClientPtr client
140)
141{
142    xAppleDRIQueryDirectRenderingCapableReply rep;
143    Bool isCapable;
144
145    REQUEST(xAppleDRIQueryDirectRenderingCapableReq);
146    REQUEST_SIZE_MATCH(xAppleDRIQueryDirectRenderingCapableReq);
147    rep.type = X_Reply;
148    rep.length = 0;
149    rep.sequenceNumber = client->sequence;
150
151    if (!DRIQueryDirectRenderingCapable( screenInfo.screens[stuff->screen],
152                                         &isCapable)) {
153        return BadValue;
154    }
155    rep.isCapable = isCapable;
156
157    if (!LocalClient(client))
158        rep.isCapable = 0;
159
160    WriteToClient(client,
161        sizeof(xAppleDRIQueryDirectRenderingCapableReply), (char *)&rep);
162    return Success;
163}
164
165static int
166ProcAppleDRIAuthConnection(
167    register ClientPtr client
168)
169{
170    xAppleDRIAuthConnectionReply rep;
171
172    REQUEST(xAppleDRIAuthConnectionReq);
173    REQUEST_SIZE_MATCH(xAppleDRIAuthConnectionReq);
174
175    rep.type = X_Reply;
176    rep.length = 0;
177    rep.sequenceNumber = client->sequence;
178    rep.authenticated = 1;
179
180    if (!DRIAuthConnection( screenInfo.screens[stuff->screen], stuff->magic)) {
181        ErrorF("Failed to authenticate %u\n", (unsigned int)stuff->magic);
182        rep.authenticated = 0;
183    }
184    WriteToClient(client, sizeof(xAppleDRIAuthConnectionReply), (char *)&rep);
185    return Success;
186}
187
188static void surface_notify(
189    void *_arg,
190    void *data
191)
192{
193    DRISurfaceNotifyArg *arg = _arg;
194    int client_index = (int) x_cvt_vptr_to_uint(data);
195    xAppleDRINotifyEvent se;
196
197    if (client_index < 0 || client_index >= currentMaxClients)
198        return;
199
200    se.type = DRIEventBase + AppleDRISurfaceNotify;
201    se.kind = arg->kind;
202    se.arg = arg->id;
203    se.time = currentTime.milliseconds;
204    WriteEventsToClient (clients[client_index], 1, (xEvent *) &se);
205}
206
207static int
208ProcAppleDRICreateSurface(
209    ClientPtr client
210)
211{
212    xAppleDRICreateSurfaceReply rep;
213    DrawablePtr pDrawable;
214    xp_surface_id sid;
215    unsigned int key[2];
216    int rc;
217
218    REQUEST(xAppleDRICreateSurfaceReq);
219    REQUEST_SIZE_MATCH(xAppleDRICreateSurfaceReq);
220    rep.type = X_Reply;
221    rep.length = 0;
222    rep.sequenceNumber = client->sequence;
223
224    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
225			   DixReadAccess);
226    if (rc != Success)
227	return rc;
228
229    rep.key_0 = rep.key_1 = rep.uid = 0;
230
231    if (!DRICreateSurface( screenInfo.screens[stuff->screen],
232                           (Drawable)stuff->drawable, pDrawable,
233                           stuff->client_id, &sid, key,
234                           surface_notify,
235                           x_cvt_uint_to_vptr(client->index))) {
236        return BadValue;
237    }
238
239    rep.key_0 = key[0];
240    rep.key_1 = key[1];
241    rep.uid = sid;
242
243    WriteToClient(client, sizeof(xAppleDRICreateSurfaceReply), (char *)&rep);
244    return Success;
245}
246
247static int
248ProcAppleDRIDestroySurface(
249    register ClientPtr client
250)
251{
252    int rc;
253    REQUEST(xAppleDRIDestroySurfaceReq);
254    DrawablePtr pDrawable;
255    REQUEST_SIZE_MATCH(xAppleDRIDestroySurfaceReq);
256
257    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
258			   DixReadAccess);
259    if (rc != Success)
260	return rc;
261
262    if (!DRIDestroySurface( screenInfo.screens[stuff->screen],
263                            (Drawable)stuff->drawable,
264                            pDrawable, NULL, NULL)) {
265        return BadValue;
266    }
267
268    return Success;
269}
270
271static int
272ProcAppleDRICreatePixmap(ClientPtr client)
273{
274    REQUEST(xAppleDRICreatePixmapReq);
275    DrawablePtr pDrawable;
276    int rc;
277    char path[PATH_MAX];
278    xAppleDRICreatePixmapReply rep;
279    int width, height, pitch, bpp;
280    void *ptr;
281
282    REQUEST_SIZE_MATCH(xAppleDRICreatePixmapReq);
283
284    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
285                           DixReadAccess);
286
287    if(rc != Success)
288        return rc;
289
290    if(!DRICreatePixmap(screenInfo.screens[stuff->screen],
291                              (Drawable)stuff->drawable,
292                              pDrawable,
293			      path, PATH_MAX)) {
294        return BadValue;
295    }
296
297    if(!DRIGetPixmapData(pDrawable, &width, &height,
298			 &pitch, &bpp, &ptr)) {
299	return BadValue;
300    }
301
302    rep.stringLength = strlen(path) + 1;
303
304    /* No need for swapping, because this only runs if LocalClient is true. */
305    rep.type = X_Reply;
306    rep.length = sizeof(rep) + rep.stringLength;
307    rep.sequenceNumber = client->sequence;
308    rep.width = width;
309    rep.height = height;
310    rep.pitch = pitch;
311    rep.bpp = bpp;
312    rep.size = pitch * height;
313
314    if(sizeof(rep) != sz_xAppleDRICreatePixmapReply)
315	ErrorF("error sizeof(rep) is %zu\n", sizeof(rep));
316
317    WriteReplyToClient(client, sizeof(rep), &rep);
318    (void)WriteToClient(client, rep.stringLength, path);
319
320    return Success;
321}
322
323static int
324ProcAppleDRIDestroyPixmap(ClientPtr client)
325{
326    DrawablePtr pDrawable;
327    int rc;
328    REQUEST(xAppleDRIDestroyPixmapReq);
329    REQUEST_SIZE_MATCH(xAppleDRIDestroyPixmapReq);
330
331    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
332			    DixReadAccess);
333
334    if(rc != Success)
335	return rc;
336
337    DRIDestroyPixmap(pDrawable);
338
339    return Success;
340}
341
342/* dispatch */
343
344static int
345ProcAppleDRIDispatch (
346    register ClientPtr client
347)
348{
349    REQUEST(xReq);
350
351    switch (stuff->data)
352    {
353    case X_AppleDRIQueryVersion:
354        return ProcAppleDRIQueryVersion(client);
355    case X_AppleDRIQueryDirectRenderingCapable:
356        return ProcAppleDRIQueryDirectRenderingCapable(client);
357    }
358
359    if (!LocalClient(client))
360        return DRIErrorBase + AppleDRIClientNotLocal;
361
362    switch (stuff->data)
363    {
364    case X_AppleDRIAuthConnection:
365        return ProcAppleDRIAuthConnection(client);
366    case X_AppleDRICreateSurface:
367        return ProcAppleDRICreateSurface(client);
368    case X_AppleDRIDestroySurface:
369        return ProcAppleDRIDestroySurface(client);
370    case X_AppleDRICreatePixmap:
371	return ProcAppleDRICreatePixmap(client);
372    case X_AppleDRIDestroyPixmap:
373	return ProcAppleDRIDestroyPixmap(client);
374
375    default:
376        return BadRequest;
377    }
378}
379
380static void
381SNotifyEvent(
382    xAppleDRINotifyEvent *from,
383    xAppleDRINotifyEvent *to
384)
385{
386    to->type = from->type;
387    to->kind = from->kind;
388    cpswaps (from->sequenceNumber, to->sequenceNumber);
389    cpswapl (from->time, to->time);
390    cpswapl (from->arg, to->arg);
391}
392
393static int
394SProcAppleDRIQueryVersion(
395    register ClientPtr client
396)
397{
398    register int n;
399    REQUEST(xAppleDRIQueryVersionReq);
400    swaps(&stuff->length, n);
401    return ProcAppleDRIQueryVersion(client);
402}
403
404static int
405SProcAppleDRIDispatch (
406    register ClientPtr client
407)
408{
409    REQUEST(xReq);
410
411    /* It is bound to be non-local when there is byte swapping */
412    if (!LocalClient(client))
413        return DRIErrorBase + AppleDRIClientNotLocal;
414
415    /* only local clients are allowed DRI access */
416    switch (stuff->data)
417    {
418    case X_AppleDRIQueryVersion:
419        return SProcAppleDRIQueryVersion(client);
420    default:
421        return BadRequest;
422    }
423}
424