appledri.c revision 4642e01f
1/**************************************************************************
2
3Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4Copyright 2000 VA Linux Systems, Inc.
5Copyright (c) 2002 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#define NEED_REPLIES
43#define NEED_EVENTS
44#include <X11/X.h>
45#include <X11/Xproto.h>
46#include "misc.h"
47#include "dixstruct.h"
48#include "extnsionst.h"
49#include "colormapst.h"
50#include "cursorstr.h"
51#include "scrnintstr.h"
52#include "servermd.h"
53#define _APPLEDRI_SERVER_
54#include "appledristr.h"
55#include "swaprep.h"
56#include "dri.h"
57#include "dristruct.h"
58#include "xpr.h"
59#include "x-hash.h"
60
61static int DRIErrorBase = 0;
62
63static DISPATCH_PROC(ProcAppleDRIDispatch);
64static DISPATCH_PROC(SProcAppleDRIDispatch);
65
66static void AppleDRIResetProc(ExtensionEntry* extEntry);
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 = APPLE_DRI_MAJOR_VERSION;
124    rep.minorVersion = APPLE_DRI_MINOR_VERSION;
125    rep.patchVersion = APPLE_DRI_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 (client->noClientException);
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 (client->noClientException);
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 (client->noClientException);
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    ClientPtr client;
196    xAppleDRINotifyEvent se;
197
198    if (client_index < 0 || client_index >= currentMaxClients)
199        return;
200
201    client = clients[client_index];
202    if (client == NULL || client == serverClient || client->clientGone)
203        return;
204
205    se.type = DRIEventBase + AppleDRISurfaceNotify;
206    se.kind = arg->kind;
207    se.arg = arg->id;
208    se.sequenceNumber = client->sequence;
209    se.time = currentTime.milliseconds;
210    WriteEventsToClient (client, 1, (xEvent *) &se);
211}
212
213static int
214ProcAppleDRICreateSurface(
215    ClientPtr client
216)
217{
218    xAppleDRICreateSurfaceReply rep;
219    DrawablePtr pDrawable;
220    xp_surface_id sid;
221    unsigned int key[2];
222    int rc;
223
224    REQUEST(xAppleDRICreateSurfaceReq);
225    REQUEST_SIZE_MATCH(xAppleDRICreateSurfaceReq);
226    rep.type = X_Reply;
227    rep.length = 0;
228    rep.sequenceNumber = client->sequence;
229
230    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
231			   DixReadAccess);
232    if (rc != Success)
233	return rc;
234
235    rep.key_0 = rep.key_1 = rep.uid = 0;
236
237    if (!DRICreateSurface( screenInfo.screens[stuff->screen],
238                           (Drawable)stuff->drawable, pDrawable,
239                           stuff->client_id, &sid, key,
240                           surface_notify,
241                           x_cvt_uint_to_vptr(client->index))) {
242        return BadValue;
243    }
244
245    rep.key_0 = key[0];
246    rep.key_1 = key[1];
247    rep.uid = sid;
248
249    WriteToClient(client, sizeof(xAppleDRICreateSurfaceReply), (char *)&rep);
250    return (client->noClientException);
251}
252
253static int
254ProcAppleDRIDestroySurface(
255    register ClientPtr client
256)
257{
258    REQUEST(xAppleDRIDestroySurfaceReq);
259    DrawablePtr pDrawable;
260    REQUEST_SIZE_MATCH(xAppleDRIDestroySurfaceReq);
261    int rc;
262
263    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
264			   DixReadAccess);
265    if (rc != Success)
266	return rc;
267
268    if (!DRIDestroySurface( screenInfo.screens[stuff->screen],
269                            (Drawable)stuff->drawable,
270                            pDrawable, NULL, NULL)) {
271        return BadValue;
272    }
273
274    return (client->noClientException);
275}
276
277
278/* dispatch */
279
280static int
281ProcAppleDRIDispatch (
282    register ClientPtr client
283)
284{
285    REQUEST(xReq);
286
287    switch (stuff->data)
288    {
289    case X_AppleDRIQueryVersion:
290        return ProcAppleDRIQueryVersion(client);
291    case X_AppleDRIQueryDirectRenderingCapable:
292        return ProcAppleDRIQueryDirectRenderingCapable(client);
293    }
294
295    if (!LocalClient(client))
296        return DRIErrorBase + AppleDRIClientNotLocal;
297
298    switch (stuff->data)
299    {
300    case X_AppleDRIAuthConnection:
301        return ProcAppleDRIAuthConnection(client);
302    case X_AppleDRICreateSurface:
303        return ProcAppleDRICreateSurface(client);
304    case X_AppleDRIDestroySurface:
305        return ProcAppleDRIDestroySurface(client);
306    default:
307        return BadRequest;
308    }
309}
310
311static void
312SNotifyEvent(
313    xAppleDRINotifyEvent *from,
314    xAppleDRINotifyEvent *to
315)
316{
317    to->type = from->type;
318    to->kind = from->kind;
319    cpswaps (from->sequenceNumber, to->sequenceNumber);
320    cpswapl (from->time, to->time);
321    cpswapl (from->arg, to->arg);
322}
323
324static int
325SProcAppleDRIQueryVersion(
326    register ClientPtr client
327)
328{
329    register int n;
330    REQUEST(xAppleDRIQueryVersionReq);
331    swaps(&stuff->length, n);
332    return ProcAppleDRIQueryVersion(client);
333}
334
335static int
336SProcAppleDRIDispatch (
337    register ClientPtr client
338)
339{
340    REQUEST(xReq);
341
342    /* It is bound to be non-local when there is byte swapping */
343    if (!LocalClient(client))
344        return DRIErrorBase + AppleDRIClientNotLocal;
345
346    /* only local clients are allowed DRI access */
347    switch (stuff->data)
348    {
349    case X_AppleDRIQueryVersion:
350        return SProcAppleDRIQueryVersion(client);
351    default:
352        return BadRequest;
353    }
354}
355