appledri.c revision 35c4bbdf
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
276    REQUEST_SIZE_MATCH(xAppleDRICreatePixmapReq);
277
278    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
279                           DixReadAccess);
280
281    if (rc != Success)
282        return rc;
283
284    if (!DRICreatePixmap(screenInfo.screens[stuff->screen],
285                         (Drawable)stuff->drawable,
286                         pDrawable,
287                         path, PATH_MAX)) {
288        return BadValue;
289    }
290
291    if (!DRIGetPixmapData(pDrawable, &width, &height,
292                          &pitch, &bpp, &ptr)) {
293        return BadValue;
294    }
295
296    rep.stringLength = strlen(path) + 1;
297
298    rep.type = X_Reply;
299    rep.length = bytes_to_int32(rep.stringLength);
300    rep.sequenceNumber = client->sequence;
301    rep.width = width;
302    rep.height = height;
303    rep.pitch = pitch;
304    rep.bpp = bpp;
305    rep.size = pitch * height;
306
307    if (sizeof(rep) != sz_xAppleDRICreatePixmapReply)
308        ErrorF("error sizeof(rep) is %zu\n", sizeof(rep));
309
310    if (client->swapped) {
311        swaps(&rep.sequenceNumber);
312        swapl(&rep.length);
313        swapl(&rep.stringLength);
314        swapl(&rep.width);
315        swapl(&rep.height);
316        swapl(&rep.pitch);
317        swapl(&rep.bpp);
318        swapl(&rep.size);
319    }
320
321    WriteToClient(client, sizeof(rep), &rep);
322    WriteToClient(client, rep.stringLength, path);
323
324    return Success;
325}
326
327static int
328ProcAppleDRIDestroyPixmap(ClientPtr client)
329{
330    DrawablePtr pDrawable;
331    int rc;
332    REQUEST(xAppleDRIDestroyPixmapReq);
333    REQUEST_SIZE_MATCH(xAppleDRIDestroyPixmapReq);
334
335    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
336                           DixReadAccess);
337
338    if (rc != Success)
339        return rc;
340
341    DRIDestroyPixmap(pDrawable);
342
343    return Success;
344}
345
346/* dispatch */
347
348static int
349ProcAppleDRIDispatch(register ClientPtr client)
350{
351    REQUEST(xReq);
352
353    switch (stuff->data) {
354    case X_AppleDRIQueryVersion:
355        return ProcAppleDRIQueryVersion(client);
356
357    case X_AppleDRIQueryDirectRenderingCapable:
358        return ProcAppleDRIQueryDirectRenderingCapable(client);
359    }
360
361    if (!client->local)
362        return DRIErrorBase + AppleDRIClientNotLocal;
363
364    switch (stuff->data) {
365    case X_AppleDRIAuthConnection:
366        return ProcAppleDRIAuthConnection(client);
367
368    case X_AppleDRICreateSurface:
369        return ProcAppleDRICreateSurface(client);
370
371    case X_AppleDRIDestroySurface:
372        return ProcAppleDRIDestroySurface(client);
373
374    case X_AppleDRICreatePixmap:
375        return ProcAppleDRICreatePixmap(client);
376
377    case X_AppleDRIDestroyPixmap:
378        return ProcAppleDRIDestroyPixmap(client);
379
380    default:
381        return BadRequest;
382    }
383}
384
385static void
386SNotifyEvent(xAppleDRINotifyEvent *from,
387             xAppleDRINotifyEvent *to)
388{
389    to->type = from->type;
390    to->kind = from->kind;
391    cpswaps(from->sequenceNumber, to->sequenceNumber);
392    cpswapl(from->time, to->time);
393    cpswapl(from->arg, to->arg);
394}
395
396static int
397SProcAppleDRIQueryVersion(register ClientPtr client)
398{
399    REQUEST(xAppleDRIQueryVersionReq);
400    swaps(&stuff->length);
401    return ProcAppleDRIQueryVersion(client);
402}
403
404static int
405SProcAppleDRIQueryDirectRenderingCapable(register ClientPtr client)
406{
407    REQUEST(xAppleDRIQueryDirectRenderingCapableReq);
408    swaps(&stuff->length);
409    REQUEST_SIZE_MATCH(xAppleDRIQueryDirectRenderingCapableReq);
410    swapl(&stuff->screen);
411    return ProcAppleDRIQueryDirectRenderingCapable(client);
412}
413
414static int
415SProcAppleDRIAuthConnection(register ClientPtr client)
416{
417    REQUEST(xAppleDRIAuthConnectionReq);
418    swaps(&stuff->length);
419    REQUEST_SIZE_MATCH(xAppleDRIAuthConnectionReq);
420    swapl(&stuff->screen);
421    swapl(&stuff->magic);
422    return ProcAppleDRIAuthConnection(client);
423}
424
425static int
426SProcAppleDRICreateSurface(register ClientPtr client)
427{
428    REQUEST(xAppleDRICreateSurfaceReq);
429    swaps(&stuff->length);
430    REQUEST_SIZE_MATCH(xAppleDRICreateSurfaceReq);
431    swapl(&stuff->screen);
432    swapl(&stuff->drawable);
433    swapl(&stuff->client_id);
434    return ProcAppleDRICreateSurface(client);
435}
436
437static int
438SProcAppleDRIDestroySurface(register ClientPtr client)
439{
440    REQUEST(xAppleDRIDestroySurfaceReq);
441    swaps(&stuff->length);
442    REQUEST_SIZE_MATCH(xAppleDRIDestroySurfaceReq);
443    swapl(&stuff->screen);
444    swapl(&stuff->drawable);
445    return ProcAppleDRIDestroySurface(client);
446}
447
448static int
449SProcAppleDRICreatePixmap(register ClientPtr client)
450{
451    REQUEST(xAppleDRICreatePixmapReq);
452    swaps(&stuff->length);
453    REQUEST_SIZE_MATCH(xAppleDRICreatePixmapReq);
454    swapl(&stuff->screen);
455    swapl(&stuff->drawable);
456    return ProcAppleDRICreatePixmap(client);
457}
458
459static int
460SProcAppleDRIDestroyPixmap(register ClientPtr client)
461{
462    REQUEST(xAppleDRIDestroyPixmapReq);
463    swaps(&stuff->length);
464    REQUEST_SIZE_MATCH(xAppleDRIDestroyPixmapReq);
465    swapl(&stuff->drawable);
466    return ProcAppleDRIDestroyPixmap(client);
467}
468
469static int
470SProcAppleDRIDispatch(register ClientPtr client)
471{
472    REQUEST(xReq);
473
474    switch (stuff->data) {
475    case X_AppleDRIQueryVersion:
476        return SProcAppleDRIQueryVersion(client);
477
478    case X_AppleDRIQueryDirectRenderingCapable:
479        return SProcAppleDRIQueryDirectRenderingCapable(client);
480    }
481
482    if (!client->local)
483        return DRIErrorBase + AppleDRIClientNotLocal;
484
485    switch (stuff->data) {
486    case X_AppleDRIAuthConnection:
487        return SProcAppleDRIAuthConnection(client);
488
489    case X_AppleDRICreateSurface:
490        return SProcAppleDRICreateSurface(client);
491
492    case X_AppleDRIDestroySurface:
493        return SProcAppleDRIDestroySurface(client);
494
495    case X_AppleDRICreatePixmap:
496        return SProcAppleDRICreatePixmap(client);
497
498    case X_AppleDRIDestroyPixmap:
499        return SProcAppleDRIDestroyPixmap(client);
500
501    default:
502        return BadRequest;
503    }
504}
505
506void
507AppleDRIExtensionInit(void)
508{
509    ExtensionEntry* extEntry;
510
511    if (DRIExtensionInit() &&
512        (extEntry = AddExtension(APPLEDRINAME,
513                                 AppleDRINumberEvents,
514                                 AppleDRINumberErrors,
515                                 ProcAppleDRIDispatch,
516                                 SProcAppleDRIDispatch,
517                                 AppleDRIResetProc,
518                                 StandardMinorOpcode))) {
519        size_t i;
520        DRIReqCode = (unsigned char)extEntry->base;
521        DRIErrorBase = extEntry->errorBase;
522        DRIEventBase = extEntry->eventBase;
523        for (i = 0; i < AppleDRINumberEvents; i++)
524            EventSwapVector[DRIEventBase + i] = (EventSwapPtr)SNotifyEvent;
525    }
526}
527