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