appledri.c revision d9252ffb
1/**************************************************************************
2
3   Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4   Copyright 2000 VA Linux Systems, Inc.
5   Copyright (c) 2002, 2009-2012 Apple 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 *   Jeremy Huddleston <jeremyhu@apple.com>
36 *
37 */
38
39#ifdef HAVE_DIX_CONFIG_H
40#include <dix-config.h>
41#endif
42
43#include <X11/X.h>
44#include <X11/Xproto.h>
45#include "misc.h"
46#include "dixstruct.h"
47#include "extnsionst.h"
48#include "colormapst.h"
49#include "cursorstr.h"
50#include "scrnintstr.h"
51#include "servermd.h"
52#define _APPLEDRI_SERVER_
53#include "appledristr.h"
54#include "swaprep.h"
55#include "dri.h"
56#include "dristruct.h"
57#include "xpr.h"
58#include "x-hash.h"
59#include "protocol-versions.h"
60
61static int DRIErrorBase = 0;
62
63static void
64AppleDRIResetProc(ExtensionEntry* extEntry);
65static int
66ProcAppleDRICreatePixmap(ClientPtr client);
67
68static unsigned char DRIReqCode = 0;
69static int DRIEventBase = 0;
70
71static void
72SNotifyEvent(xAppleDRINotifyEvent *from, xAppleDRINotifyEvent *to);
73
74typedef struct _DRIEvent *DRIEventPtr;
75typedef struct _DRIEvent {
76    DRIEventPtr next;
77    ClientPtr client;
78    XID clientResource;
79    unsigned int mask;
80} DRIEventRec;
81
82/*ARGSUSED*/
83static void
84AppleDRIResetProc(ExtensionEntry* extEntry)
85{
86    DRIReset();
87}
88
89static int
90ProcAppleDRIQueryVersion(register ClientPtr client)
91{
92    xAppleDRIQueryVersionReply rep;
93
94    REQUEST_SIZE_MATCH(xAppleDRIQueryVersionReq);
95    rep.type = X_Reply;
96    rep.length = 0;
97    rep.sequenceNumber = client->sequence;
98    rep.majorVersion = SERVER_APPLEDRI_MAJOR_VERSION;
99    rep.minorVersion = SERVER_APPLEDRI_MINOR_VERSION;
100    rep.patchVersion = SERVER_APPLEDRI_PATCH_VERSION;
101    if (client->swapped) {
102        swaps(&rep.sequenceNumber);
103        swapl(&rep.length);
104        swaps(&rep.majorVersion);
105        swaps(&rep.minorVersion);
106        swapl(&rep.patchVersion);
107    }
108    WriteToClient(client, sizeof(xAppleDRIQueryVersionReply), &rep);
109    return Success;
110}
111
112/* surfaces */
113
114static int
115ProcAppleDRIQueryDirectRenderingCapable(register ClientPtr client)
116{
117    xAppleDRIQueryDirectRenderingCapableReply rep;
118    Bool isCapable;
119
120    REQUEST(xAppleDRIQueryDirectRenderingCapableReq);
121    REQUEST_SIZE_MATCH(xAppleDRIQueryDirectRenderingCapableReq);
122    rep.type = X_Reply;
123    rep.length = 0;
124    rep.sequenceNumber = client->sequence;
125
126    if (stuff->screen >= screenInfo.numScreens) {
127        return BadValue;
128    }
129
130    if (!DRIQueryDirectRenderingCapable(screenInfo.screens[stuff->screen],
131                                        &isCapable)) {
132        return BadValue;
133    }
134    rep.isCapable = isCapable;
135
136    if (!client->local)
137        rep.isCapable = 0;
138
139    if (client->swapped) {
140        swaps(&rep.sequenceNumber);
141        swapl(&rep.length);
142    }
143
144    WriteToClient(client,
145                  sizeof(xAppleDRIQueryDirectRenderingCapableReply),
146                  &rep);
147    return Success;
148}
149
150static int
151ProcAppleDRIAuthConnection(register ClientPtr client)
152{
153    xAppleDRIAuthConnectionReply rep;
154
155    REQUEST(xAppleDRIAuthConnectionReq);
156    REQUEST_SIZE_MATCH(xAppleDRIAuthConnectionReq);
157
158    rep.type = X_Reply;
159    rep.length = 0;
160    rep.sequenceNumber = client->sequence;
161    rep.authenticated = 1;
162
163    if (!DRIAuthConnection(screenInfo.screens[stuff->screen],
164                           stuff->magic)) {
165        ErrorF("Failed to authenticate %u\n", (unsigned int)stuff->magic);
166        rep.authenticated = 0;
167    }
168
169    if (client->swapped) {
170        swaps(&rep.sequenceNumber);
171        swapl(&rep.length);
172        swapl(&rep.authenticated); /* Yes, this is a CARD32 ... sigh */
173    }
174
175    WriteToClient(client, sizeof(xAppleDRIAuthConnectionReply), &rep);
176    return Success;
177}
178
179static void
180surface_notify(void *_arg,
181               void *data)
182{
183    DRISurfaceNotifyArg *arg = _arg;
184    int client_index = (int)x_cvt_vptr_to_uint(data);
185    xAppleDRINotifyEvent se;
186
187    if (client_index < 0 || client_index >= currentMaxClients)
188        return;
189
190    se.type = DRIEventBase + AppleDRISurfaceNotify;
191    se.kind = arg->kind;
192    se.arg = arg->id;
193    se.time = currentTime.milliseconds;
194    WriteEventsToClient(clients[client_index], 1, (xEvent *)&se);
195}
196
197static int
198ProcAppleDRICreateSurface(ClientPtr client)
199{
200    xAppleDRICreateSurfaceReply rep;
201    DrawablePtr pDrawable;
202    xp_surface_id sid;
203    unsigned int key[2];
204    int rc;
205
206    REQUEST(xAppleDRICreateSurfaceReq);
207    REQUEST_SIZE_MATCH(xAppleDRICreateSurfaceReq);
208    rep.type = X_Reply;
209    rep.length = 0;
210    rep.sequenceNumber = client->sequence;
211
212    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
213                           DixReadAccess);
214    if (rc != Success)
215        return rc;
216
217    rep.key_0 = rep.key_1 = rep.uid = 0;
218
219    if (!DRICreateSurface(screenInfo.screens[stuff->screen],
220                          (Drawable)stuff->drawable, pDrawable,
221                          stuff->client_id, &sid, key,
222                          surface_notify,
223                          x_cvt_uint_to_vptr(client->index))) {
224        return BadValue;
225    }
226
227    rep.key_0 = key[0];
228    rep.key_1 = key[1];
229    rep.uid = sid;
230
231    if (client->swapped) {
232        swaps(&rep.sequenceNumber);
233        swapl(&rep.length);
234        swapl(&rep.key_0);
235        swapl(&rep.key_1);
236        swapl(&rep.uid);
237    }
238
239    WriteToClient(client, sizeof(xAppleDRICreateSurfaceReply), &rep);
240    return Success;
241}
242
243static int
244ProcAppleDRIDestroySurface(register ClientPtr client)
245{
246    int rc;
247    REQUEST(xAppleDRIDestroySurfaceReq);
248    DrawablePtr pDrawable;
249    REQUEST_SIZE_MATCH(xAppleDRIDestroySurfaceReq);
250
251    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
252                           DixReadAccess);
253    if (rc != Success)
254        return rc;
255
256    if (!DRIDestroySurface(screenInfo.screens[stuff->screen],
257                           (Drawable)stuff->drawable,
258                           pDrawable, NULL, NULL)) {
259        return BadValue;
260    }
261
262    return Success;
263}
264
265static int
266ProcAppleDRICreatePixmap(ClientPtr client)
267{
268    REQUEST(xAppleDRICreatePixmapReq);
269    DrawablePtr pDrawable;
270    int rc;
271    char path[PATH_MAX];
272    xAppleDRICreatePixmapReply rep;
273    int width, height, pitch, bpp;
274    void *ptr;
275    CARD32 stringLength;
276
277    REQUEST_SIZE_MATCH(xAppleDRICreatePixmapReq);
278
279    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
280                           DixReadAccess);
281
282    if (rc != Success)
283        return rc;
284
285    if (!DRICreatePixmap(screenInfo.screens[stuff->screen],
286                         (Drawable)stuff->drawable,
287                         pDrawable,
288                         path, PATH_MAX)) {
289        return BadValue;
290    }
291
292    if (!DRIGetPixmapData(pDrawable, &width, &height,
293                          &pitch, &bpp, &ptr)) {
294        return BadValue;
295    }
296
297    rep.stringLength = strlen(path) + 1;
298
299    rep.type = X_Reply;
300    rep.length = bytes_to_int32(rep.stringLength);
301    rep.sequenceNumber = client->sequence;
302    rep.width = width;
303    rep.height = height;
304    rep.pitch = pitch;
305    rep.bpp = bpp;
306    rep.size = pitch * height;
307
308    if (sizeof(rep) != sz_xAppleDRICreatePixmapReply)
309        ErrorF("error sizeof(rep) is %zu\n", sizeof(rep));
310
311    stringLength = rep.stringLength;  /* save unswapped value */
312    if (client->swapped) {
313        swaps(&rep.sequenceNumber);
314        swapl(&rep.length);
315        swapl(&rep.stringLength);
316        swapl(&rep.width);
317        swapl(&rep.height);
318        swapl(&rep.pitch);
319        swapl(&rep.bpp);
320        swapl(&rep.size);
321    }
322
323    WriteToClient(client, sizeof(rep), &rep);
324    WriteToClient(client, stringLength, path);
325
326    return Success;
327}
328
329static int
330ProcAppleDRIDestroyPixmap(ClientPtr client)
331{
332    DrawablePtr pDrawable;
333    int rc;
334    REQUEST(xAppleDRIDestroyPixmapReq);
335    REQUEST_SIZE_MATCH(xAppleDRIDestroyPixmapReq);
336
337    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
338                           DixReadAccess);
339
340    if (rc != Success)
341        return rc;
342
343    DRIDestroyPixmap(pDrawable);
344
345    return Success;
346}
347
348/* dispatch */
349
350static int
351ProcAppleDRIDispatch(register ClientPtr client)
352{
353    REQUEST(xReq);
354
355    switch (stuff->data) {
356    case X_AppleDRIQueryVersion:
357        return ProcAppleDRIQueryVersion(client);
358
359    case X_AppleDRIQueryDirectRenderingCapable:
360        return ProcAppleDRIQueryDirectRenderingCapable(client);
361    }
362
363    if (!client->local)
364        return DRIErrorBase + AppleDRIClientNotLocal;
365
366    switch (stuff->data) {
367    case X_AppleDRIAuthConnection:
368        return ProcAppleDRIAuthConnection(client);
369
370    case X_AppleDRICreateSurface:
371        return ProcAppleDRICreateSurface(client);
372
373    case X_AppleDRIDestroySurface:
374        return ProcAppleDRIDestroySurface(client);
375
376    case X_AppleDRICreatePixmap:
377        return ProcAppleDRICreatePixmap(client);
378
379    case X_AppleDRIDestroyPixmap:
380        return ProcAppleDRIDestroyPixmap(client);
381
382    default:
383        return BadRequest;
384    }
385}
386
387static void
388SNotifyEvent(xAppleDRINotifyEvent *from,
389             xAppleDRINotifyEvent *to)
390{
391    to->type = from->type;
392    to->kind = from->kind;
393    cpswaps(from->sequenceNumber, to->sequenceNumber);
394    cpswapl(from->time, to->time);
395    cpswapl(from->arg, to->arg);
396}
397
398static int
399SProcAppleDRIQueryVersion(register ClientPtr client)
400{
401    REQUEST(xAppleDRIQueryVersionReq);
402    swaps(&stuff->length);
403    return ProcAppleDRIQueryVersion(client);
404}
405
406static int
407SProcAppleDRIQueryDirectRenderingCapable(register ClientPtr client)
408{
409    REQUEST(xAppleDRIQueryDirectRenderingCapableReq);
410    swaps(&stuff->length);
411    REQUEST_SIZE_MATCH(xAppleDRIQueryDirectRenderingCapableReq);
412    swapl(&stuff->screen);
413    return ProcAppleDRIQueryDirectRenderingCapable(client);
414}
415
416static int
417SProcAppleDRIAuthConnection(register ClientPtr client)
418{
419    REQUEST(xAppleDRIAuthConnectionReq);
420    swaps(&stuff->length);
421    REQUEST_SIZE_MATCH(xAppleDRIAuthConnectionReq);
422    swapl(&stuff->screen);
423    swapl(&stuff->magic);
424    return ProcAppleDRIAuthConnection(client);
425}
426
427static int
428SProcAppleDRICreateSurface(register ClientPtr client)
429{
430    REQUEST(xAppleDRICreateSurfaceReq);
431    swaps(&stuff->length);
432    REQUEST_SIZE_MATCH(xAppleDRICreateSurfaceReq);
433    swapl(&stuff->screen);
434    swapl(&stuff->drawable);
435    swapl(&stuff->client_id);
436    return ProcAppleDRICreateSurface(client);
437}
438
439static int
440SProcAppleDRIDestroySurface(register ClientPtr client)
441{
442    REQUEST(xAppleDRIDestroySurfaceReq);
443    swaps(&stuff->length);
444    REQUEST_SIZE_MATCH(xAppleDRIDestroySurfaceReq);
445    swapl(&stuff->screen);
446    swapl(&stuff->drawable);
447    return ProcAppleDRIDestroySurface(client);
448}
449
450static int
451SProcAppleDRICreatePixmap(register ClientPtr client)
452{
453    REQUEST(xAppleDRICreatePixmapReq);
454    swaps(&stuff->length);
455    REQUEST_SIZE_MATCH(xAppleDRICreatePixmapReq);
456    swapl(&stuff->screen);
457    swapl(&stuff->drawable);
458    return ProcAppleDRICreatePixmap(client);
459}
460
461static int
462SProcAppleDRIDestroyPixmap(register ClientPtr client)
463{
464    REQUEST(xAppleDRIDestroyPixmapReq);
465    swaps(&stuff->length);
466    REQUEST_SIZE_MATCH(xAppleDRIDestroyPixmapReq);
467    swapl(&stuff->drawable);
468    return ProcAppleDRIDestroyPixmap(client);
469}
470
471static int
472SProcAppleDRIDispatch(register ClientPtr client)
473{
474    REQUEST(xReq);
475
476    switch (stuff->data) {
477    case X_AppleDRIQueryVersion:
478        return SProcAppleDRIQueryVersion(client);
479
480    case X_AppleDRIQueryDirectRenderingCapable:
481        return SProcAppleDRIQueryDirectRenderingCapable(client);
482    }
483
484    if (!client->local)
485        return DRIErrorBase + AppleDRIClientNotLocal;
486
487    switch (stuff->data) {
488    case X_AppleDRIAuthConnection:
489        return SProcAppleDRIAuthConnection(client);
490
491    case X_AppleDRICreateSurface:
492        return SProcAppleDRICreateSurface(client);
493
494    case X_AppleDRIDestroySurface:
495        return SProcAppleDRIDestroySurface(client);
496
497    case X_AppleDRICreatePixmap:
498        return SProcAppleDRICreatePixmap(client);
499
500    case X_AppleDRIDestroyPixmap:
501        return SProcAppleDRIDestroyPixmap(client);
502
503    default:
504        return BadRequest;
505    }
506}
507
508void
509AppleDRIExtensionInit(void)
510{
511    ExtensionEntry* extEntry;
512
513    if (DRIExtensionInit() &&
514        (extEntry = AddExtension(APPLEDRINAME,
515                                 AppleDRINumberEvents,
516                                 AppleDRINumberErrors,
517                                 ProcAppleDRIDispatch,
518                                 SProcAppleDRIDispatch,
519                                 AppleDRIResetProc,
520                                 StandardMinorOpcode))) {
521        size_t i;
522        DRIReqCode = (unsigned char)extEntry->base;
523        DRIErrorBase = extEntry->errorBase;
524        DRIEventBase = extEntry->eventBase;
525        for (i = 0; i < AppleDRINumberEvents; i++)
526            EventSwapVector[DRIEventBase + i] = (EventSwapPtr)SNotifyEvent;
527    }
528}
529