initial commit
[profile/ivi/xorg-x11-server.git] / hw / xquartz / xpr / appledri.c
1 /**************************************************************************
2
3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4 Copyright 2000 VA Linux Systems, Inc.
5 Copyright (c) 2002, 2009 Apple Computer, Inc.
6 All Rights Reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sub license, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial portions
18 of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
24 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 SOFTWARE 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
60 static int DRIErrorBase = 0;
61
62 static DISPATCH_PROC(ProcAppleDRIDispatch);
63 static DISPATCH_PROC(SProcAppleDRIDispatch);
64
65 static void AppleDRIResetProc(ExtensionEntry* extEntry);
66 static int ProcAppleDRICreatePixmap(ClientPtr client);
67
68 static unsigned char DRIReqCode = 0;
69 static int DRIEventBase = 0;
70
71 static void SNotifyEvent(xAppleDRINotifyEvent *from, xAppleDRINotifyEvent *to);
72
73 typedef struct _DRIEvent *DRIEventPtr;
74 typedef struct _DRIEvent {
75     DRIEventPtr     next;
76     ClientPtr       client;
77     XID             clientResource;
78     unsigned int    mask;
79 } DRIEventRec;
80
81
82 void
83 AppleDRIExtensionInit(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*/
103 static void
104 AppleDRIResetProc (
105     ExtensionEntry* extEntry
106 )
107 {
108     DRIReset();
109 }
110
111 static int
112 ProcAppleDRIQueryVersion(
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
137 static int
138 ProcAppleDRIQueryDirectRenderingCapable(
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
165 static int
166 ProcAppleDRIAuthConnection(
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
188 static 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
207 static int
208 ProcAppleDRICreateSurface(
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
247 static int
248 ProcAppleDRIDestroySurface(
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
271 static int
272 ProcAppleDRICreatePixmap(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
323 static int
324 ProcAppleDRIDestroyPixmap(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
344 static int
345 ProcAppleDRIDispatch (
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
380 static void
381 SNotifyEvent(
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
393 static int
394 SProcAppleDRIQueryVersion(
395     register ClientPtr client
396 )
397 {
398     register int n;
399     REQUEST(xAppleDRIQueryVersionReq);
400     swaps(&stuff->length, n);
401     return ProcAppleDRIQueryVersion(client);
402 }
403
404 static int
405 SProcAppleDRIDispatch (
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 }