105b261ecSmrg/**************************************************************************
205b261ecSmrg
305b261ecSmrgCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
405b261ecSmrgCopyright 2000 VA Linux Systems, Inc.
505b261ecSmrgAll Rights Reserved.
605b261ecSmrg
705b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a
805b261ecSmrgcopy of this software and associated documentation files (the
905b261ecSmrg"Software"), to deal in the Software without restriction, including
1005b261ecSmrgwithout limitation the rights to use, copy, modify, merge, publish,
1105b261ecSmrgdistribute, sub license, and/or sell copies of the Software, and to
1205b261ecSmrgpermit persons to whom the Software is furnished to do so, subject to
1305b261ecSmrgthe following conditions:
1405b261ecSmrg
1505b261ecSmrgThe above copyright notice and this permission notice (including the
1605b261ecSmrgnext paragraph) shall be included in all copies or substantial portions
1705b261ecSmrgof the Software.
1805b261ecSmrg
1905b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2005b261ecSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2105b261ecSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2205b261ecSmrgIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
2305b261ecSmrgANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2405b261ecSmrgTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2505b261ecSmrgSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2605b261ecSmrg
2705b261ecSmrg**************************************************************************/
2805b261ecSmrg
2905b261ecSmrg/*
3005b261ecSmrg * Authors:
3105b261ecSmrg *   Kevin E. Martin <martin@valinux.com>
3205b261ecSmrg *   Jens Owen <jens@tungstengraphics.com>
3305b261ecSmrg *   Rickard E. (Rik) Faith <faith@valinux.com>
3405b261ecSmrg *
3505b261ecSmrg */
3605b261ecSmrg
3705b261ecSmrg#ifdef HAVE_XORG_CONFIG_H
3805b261ecSmrg#include <xorg-config.h>
3905b261ecSmrg#endif
4005b261ecSmrg
4105b261ecSmrg#include <string.h>
4205b261ecSmrg
4305b261ecSmrg#include "xf86.h"
4405b261ecSmrg
4505b261ecSmrg#include <X11/X.h>
4605b261ecSmrg#include <X11/Xproto.h>
4705b261ecSmrg#include "misc.h"
4805b261ecSmrg#include "dixstruct.h"
4905b261ecSmrg#include "extnsionst.h"
5035c4bbdfSmrg#include "extinit.h"
5105b261ecSmrg#include "colormapst.h"
5205b261ecSmrg#include "cursorstr.h"
5305b261ecSmrg#include "scrnintstr.h"
5405b261ecSmrg#include "servermd.h"
5505b261ecSmrg#define _XF86DRI_SERVER_
566747b715Smrg#include <X11/dri/xf86driproto.h>
5705b261ecSmrg#include "swaprep.h"
5805b261ecSmrg#include "xf86str.h"
5905b261ecSmrg#include "dri.h"
6005b261ecSmrg#include "sarea.h"
6105b261ecSmrg#include "dristruct.h"
6205b261ecSmrg#include "xf86drm.h"
636747b715Smrg#include "protocol-versions.h"
6435c4bbdfSmrg#include "xf86Extensions.h"
6505b261ecSmrg
6605b261ecSmrgstatic int DRIErrorBase;
6705b261ecSmrg
6835c4bbdfSmrgstatic void XF86DRIResetProc(ExtensionEntry *extEntry);
6905b261ecSmrg
7005b261ecSmrgstatic unsigned char DRIReqCode = 0;
7105b261ecSmrg
7205b261ecSmrg/*ARGSUSED*/
7305b261ecSmrgstatic void
7435c4bbdfSmrgXF86DRIResetProc(ExtensionEntry *extEntry)
7505b261ecSmrg{
7605b261ecSmrg    DRIReset();
7705b261ecSmrg}
7805b261ecSmrg
7905b261ecSmrgstatic int
8035c4bbdfSmrgProcXF86DRIQueryVersion(register ClientPtr client)
8105b261ecSmrg{
8235c4bbdfSmrg    xXF86DRIQueryVersionReply rep = {
8335c4bbdfSmrg        .type = X_Reply,
8435c4bbdfSmrg        .sequenceNumber = client->sequence,
8535c4bbdfSmrg        .length = 0,
8635c4bbdfSmrg        .majorVersion = SERVER_XF86DRI_MAJOR_VERSION,
8735c4bbdfSmrg        .minorVersion = SERVER_XF86DRI_MINOR_VERSION,
8835c4bbdfSmrg        .patchVersion = SERVER_XF86DRI_PATCH_VERSION
8935c4bbdfSmrg    };
9005b261ecSmrg
9105b261ecSmrg    REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq);
9205b261ecSmrg    if (client->swapped) {
9335c4bbdfSmrg        swaps(&rep.sequenceNumber);
9435c4bbdfSmrg        swapl(&rep.length);
9535c4bbdfSmrg        swaps(&rep.majorVersion);
9635c4bbdfSmrg        swaps(&rep.minorVersion);
9735c4bbdfSmrg        swapl(&rep.patchVersion);
9805b261ecSmrg    }
9935c4bbdfSmrg    WriteToClient(client, sizeof(xXF86DRIQueryVersionReply), &rep);
1006747b715Smrg    return Success;
10105b261ecSmrg}
10205b261ecSmrg
10305b261ecSmrgstatic int
10435c4bbdfSmrgProcXF86DRIQueryDirectRenderingCapable(register ClientPtr client)
10505b261ecSmrg{
10635c4bbdfSmrg    xXF86DRIQueryDirectRenderingCapableReply rep;
10705b261ecSmrg    Bool isCapable;
10805b261ecSmrg
10905b261ecSmrg    REQUEST(xXF86DRIQueryDirectRenderingCapableReq);
11005b261ecSmrg    REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq);
11105b261ecSmrg    if (stuff->screen >= screenInfo.numScreens) {
11235c4bbdfSmrg        client->errorValue = stuff->screen;
11335c4bbdfSmrg        return BadValue;
11405b261ecSmrg    }
11505b261ecSmrg
11635c4bbdfSmrg    if (!DRIQueryDirectRenderingCapable(screenInfo.screens[stuff->screen],
11735c4bbdfSmrg                                        &isCapable)) {
11835c4bbdfSmrg        return BadValue;
11905b261ecSmrg    }
12005b261ecSmrg
12135c4bbdfSmrg    if (!client->local || client->swapped)
12235c4bbdfSmrg        isCapable = 0;
12335c4bbdfSmrg
12435c4bbdfSmrg    rep = (xXF86DRIQueryDirectRenderingCapableReply) {
12535c4bbdfSmrg        .type = X_Reply,
12635c4bbdfSmrg        .sequenceNumber = client->sequence,
12735c4bbdfSmrg        .length = 0,
12835c4bbdfSmrg        .isCapable = isCapable
12935c4bbdfSmrg    };
13005b261ecSmrg
13105b261ecSmrg    if (client->swapped) {
13235c4bbdfSmrg        swaps(&rep.sequenceNumber);
13335c4bbdfSmrg        swapl(&rep.length);
13405b261ecSmrg    }
13505b261ecSmrg
13635c4bbdfSmrg    WriteToClient(client,
13735c4bbdfSmrg                  sizeof(xXF86DRIQueryDirectRenderingCapableReply),
13835c4bbdfSmrg                  &rep);
1396747b715Smrg    return Success;
14005b261ecSmrg}
14105b261ecSmrg
14205b261ecSmrgstatic int
14335c4bbdfSmrgProcXF86DRIOpenConnection(register ClientPtr client)
14405b261ecSmrg{
14505b261ecSmrg    xXF86DRIOpenConnectionReply rep;
14635c4bbdfSmrg    drm_handle_t hSAREA;
14735c4bbdfSmrg    char *busIdString;
14835c4bbdfSmrg    CARD32 busIdStringLength = 0;
14905b261ecSmrg
15005b261ecSmrg    REQUEST(xXF86DRIOpenConnectionReq);
15105b261ecSmrg    REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq);
15205b261ecSmrg    if (stuff->screen >= screenInfo.numScreens) {
15335c4bbdfSmrg        client->errorValue = stuff->screen;
15435c4bbdfSmrg        return BadValue;
15505b261ecSmrg    }
15605b261ecSmrg
15735c4bbdfSmrg    if (!DRIOpenConnection(screenInfo.screens[stuff->screen],
15835c4bbdfSmrg                           &hSAREA, &busIdString)) {
15935c4bbdfSmrg        return BadValue;
16005b261ecSmrg    }
16105b261ecSmrg
16205b261ecSmrg    if (busIdString)
16335c4bbdfSmrg        busIdStringLength = strlen(busIdString);
16405b261ecSmrg
16535c4bbdfSmrg    rep = (xXF86DRIOpenConnectionReply) {
16635c4bbdfSmrg        .type = X_Reply,
16735c4bbdfSmrg        .sequenceNumber = client->sequence,
16835c4bbdfSmrg        .length = bytes_to_int32(SIZEOF(xXF86DRIOpenConnectionReply) -
16935c4bbdfSmrg                                 SIZEOF(xGenericReply) +
17035c4bbdfSmrg                                 pad_to_int32(busIdStringLength)),
17135c4bbdfSmrg        .busIdStringLength = busIdStringLength,
17235c4bbdfSmrg
17335c4bbdfSmrg        .hSAREALow = (CARD32) (hSAREA & 0xffffffff),
17405b261ecSmrg#if defined(LONG64) && !defined(__linux__)
17535c4bbdfSmrg        .hSAREAHigh = (CARD32) (hSAREA >> 32),
17605b261ecSmrg#else
17735c4bbdfSmrg        .hSAREAHigh = 0
17805b261ecSmrg#endif
17935c4bbdfSmrg    };
18005b261ecSmrg
18135c4bbdfSmrg    WriteToClient(client, sizeof(xXF86DRIOpenConnectionReply), &rep);
18235c4bbdfSmrg    if (busIdStringLength)
18335c4bbdfSmrg        WriteToClient(client, busIdStringLength, busIdString);
1846747b715Smrg    return Success;
18505b261ecSmrg}
18605b261ecSmrg
18705b261ecSmrgstatic int
18835c4bbdfSmrgProcXF86DRIAuthConnection(register ClientPtr client)
18905b261ecSmrg{
19035c4bbdfSmrg    xXF86DRIAuthConnectionReply rep = {
19135c4bbdfSmrg        .type = X_Reply,
19235c4bbdfSmrg        .sequenceNumber = client->sequence,
19335c4bbdfSmrg        .length = 0,
19435c4bbdfSmrg        .authenticated = 1
19535c4bbdfSmrg    };
19635c4bbdfSmrg
19705b261ecSmrg    REQUEST(xXF86DRIAuthConnectionReq);
19805b261ecSmrg    REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq);
19905b261ecSmrg    if (stuff->screen >= screenInfo.numScreens) {
20035c4bbdfSmrg        client->errorValue = stuff->screen;
20135c4bbdfSmrg        return BadValue;
20205b261ecSmrg    }
20305b261ecSmrg
20435c4bbdfSmrg    if (!DRIAuthConnection(screenInfo.screens[stuff->screen], stuff->magic)) {
20535c4bbdfSmrg        ErrorF("Failed to authenticate %lu\n", (unsigned long) stuff->magic);
20635c4bbdfSmrg        rep.authenticated = 0;
20705b261ecSmrg    }
20835c4bbdfSmrg    WriteToClient(client, sizeof(xXF86DRIAuthConnectionReply), &rep);
2096747b715Smrg    return Success;
21005b261ecSmrg}
21105b261ecSmrg
21205b261ecSmrgstatic int
21335c4bbdfSmrgProcXF86DRICloseConnection(register ClientPtr client)
21405b261ecSmrg{
21505b261ecSmrg    REQUEST(xXF86DRICloseConnectionReq);
21605b261ecSmrg    REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq);
21705b261ecSmrg    if (stuff->screen >= screenInfo.numScreens) {
21835c4bbdfSmrg        client->errorValue = stuff->screen;
21935c4bbdfSmrg        return BadValue;
22005b261ecSmrg    }
22105b261ecSmrg
22235c4bbdfSmrg    DRICloseConnection(screenInfo.screens[stuff->screen]);
22305b261ecSmrg
2246747b715Smrg    return Success;
22505b261ecSmrg}
22605b261ecSmrg
22705b261ecSmrgstatic int
22835c4bbdfSmrgProcXF86DRIGetClientDriverName(register ClientPtr client)
22905b261ecSmrg{
23035c4bbdfSmrg    xXF86DRIGetClientDriverNameReply rep = {
23135c4bbdfSmrg        .type = X_Reply,
23235c4bbdfSmrg        .sequenceNumber = client->sequence,
23335c4bbdfSmrg        .clientDriverNameLength = 0
23435c4bbdfSmrg    };
23535c4bbdfSmrg    char *clientDriverName;
23605b261ecSmrg
23705b261ecSmrg    REQUEST(xXF86DRIGetClientDriverNameReq);
23805b261ecSmrg    REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq);
23905b261ecSmrg    if (stuff->screen >= screenInfo.numScreens) {
24035c4bbdfSmrg        client->errorValue = stuff->screen;
24135c4bbdfSmrg        return BadValue;
24205b261ecSmrg    }
24305b261ecSmrg
24435c4bbdfSmrg    DRIGetClientDriverName(screenInfo.screens[stuff->screen],
24535c4bbdfSmrg                           (int *) &rep.ddxDriverMajorVersion,
24635c4bbdfSmrg                           (int *) &rep.ddxDriverMinorVersion,
24735c4bbdfSmrg                           (int *) &rep.ddxDriverPatchVersion,
24835c4bbdfSmrg                           &clientDriverName);
24905b261ecSmrg
25005b261ecSmrg    if (clientDriverName)
25135c4bbdfSmrg        rep.clientDriverNameLength = strlen(clientDriverName);
2526747b715Smrg    rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetClientDriverNameReply) -
25335c4bbdfSmrg                                SIZEOF(xGenericReply) +
25435c4bbdfSmrg                                pad_to_int32(rep.clientDriverNameLength));
25505b261ecSmrg
25635c4bbdfSmrg    WriteToClient(client, sizeof(xXF86DRIGetClientDriverNameReply), &rep);
25705b261ecSmrg    if (rep.clientDriverNameLength)
25835c4bbdfSmrg        WriteToClient(client, rep.clientDriverNameLength, clientDriverName);
2596747b715Smrg    return Success;
26005b261ecSmrg}
26105b261ecSmrg
26205b261ecSmrgstatic int
26335c4bbdfSmrgProcXF86DRICreateContext(register ClientPtr client)
26405b261ecSmrg{
26535c4bbdfSmrg    xXF86DRICreateContextReply rep = {
26635c4bbdfSmrg        .type = X_Reply,
26735c4bbdfSmrg        .sequenceNumber = client->sequence,
26835c4bbdfSmrg        .length = 0
26935c4bbdfSmrg    };
27005b261ecSmrg    ScreenPtr pScreen;
27105b261ecSmrg
27205b261ecSmrg    REQUEST(xXF86DRICreateContextReq);
27305b261ecSmrg    REQUEST_SIZE_MATCH(xXF86DRICreateContextReq);
27405b261ecSmrg    if (stuff->screen >= screenInfo.numScreens) {
27535c4bbdfSmrg        client->errorValue = stuff->screen;
27635c4bbdfSmrg        return BadValue;
27705b261ecSmrg    }
27805b261ecSmrg
27905b261ecSmrg    pScreen = screenInfo.screens[stuff->screen];
28005b261ecSmrg
28135c4bbdfSmrg    if (!DRICreateContext(pScreen,
28235c4bbdfSmrg                          NULL,
28335c4bbdfSmrg                          stuff->context, (drm_context_t *) &rep.hHWContext)) {
28435c4bbdfSmrg        return BadValue;
28505b261ecSmrg    }
28605b261ecSmrg
28735c4bbdfSmrg    WriteToClient(client, sizeof(xXF86DRICreateContextReply), &rep);
2886747b715Smrg    return Success;
28905b261ecSmrg}
29005b261ecSmrg
29105b261ecSmrgstatic int
29235c4bbdfSmrgProcXF86DRIDestroyContext(register ClientPtr client)
29305b261ecSmrg{
29405b261ecSmrg    REQUEST(xXF86DRIDestroyContextReq);
29505b261ecSmrg    REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq);
29605b261ecSmrg    if (stuff->screen >= screenInfo.numScreens) {
29735c4bbdfSmrg        client->errorValue = stuff->screen;
29835c4bbdfSmrg        return BadValue;
29905b261ecSmrg    }
30005b261ecSmrg
30135c4bbdfSmrg    if (!DRIDestroyContext(screenInfo.screens[stuff->screen], stuff->context)) {
30235c4bbdfSmrg        return BadValue;
30305b261ecSmrg    }
30405b261ecSmrg
3056747b715Smrg    return Success;
30605b261ecSmrg}
30705b261ecSmrg
30805b261ecSmrgstatic int
30935c4bbdfSmrgProcXF86DRICreateDrawable(ClientPtr client)
31005b261ecSmrg{
31135c4bbdfSmrg    xXF86DRICreateDrawableReply rep = {
31235c4bbdfSmrg        .type = X_Reply,
31335c4bbdfSmrg        .sequenceNumber = client->sequence,
31435c4bbdfSmrg        .length = 0
31535c4bbdfSmrg    };
31605b261ecSmrg    DrawablePtr pDrawable;
31705b261ecSmrg    int rc;
31805b261ecSmrg
31905b261ecSmrg    REQUEST(xXF86DRICreateDrawableReq);
32005b261ecSmrg    REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq);
32105b261ecSmrg    if (stuff->screen >= screenInfo.numScreens) {
32235c4bbdfSmrg        client->errorValue = stuff->screen;
32335c4bbdfSmrg        return BadValue;
32405b261ecSmrg    }
32505b261ecSmrg
32605b261ecSmrg    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
32735c4bbdfSmrg                           DixReadAccess);
32805b261ecSmrg    if (rc != Success)
32935c4bbdfSmrg        return rc;
33005b261ecSmrg
33105b261ecSmrg    if (!DRICreateDrawable(screenInfo.screens[stuff->screen], client,
33235c4bbdfSmrg                           pDrawable, (drm_drawable_t *) &rep.hHWDrawable)) {
33335c4bbdfSmrg        return BadValue;
33405b261ecSmrg    }
33505b261ecSmrg
33635c4bbdfSmrg    WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), &rep);
3376747b715Smrg    return Success;
33805b261ecSmrg}
33905b261ecSmrg
34005b261ecSmrgstatic int
34135c4bbdfSmrgProcXF86DRIDestroyDrawable(register ClientPtr client)
34205b261ecSmrg{
34305b261ecSmrg    REQUEST(xXF86DRIDestroyDrawableReq);
34405b261ecSmrg    DrawablePtr pDrawable;
34505b261ecSmrg    int rc;
34635c4bbdfSmrg
3476747b715Smrg    REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq);
34805b261ecSmrg
34905b261ecSmrg    if (stuff->screen >= screenInfo.numScreens) {
35035c4bbdfSmrg        client->errorValue = stuff->screen;
35135c4bbdfSmrg        return BadValue;
35205b261ecSmrg    }
35305b261ecSmrg
35405b261ecSmrg    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
35535c4bbdfSmrg                           DixReadAccess);
35605b261ecSmrg    if (rc != Success)
35735c4bbdfSmrg        return rc;
35805b261ecSmrg
35905b261ecSmrg    if (!DRIDestroyDrawable(screenInfo.screens[stuff->screen], client,
36035c4bbdfSmrg                            pDrawable)) {
36135c4bbdfSmrg        return BadValue;
36205b261ecSmrg    }
36305b261ecSmrg
3646747b715Smrg    return Success;
36505b261ecSmrg}
36605b261ecSmrg
36705b261ecSmrgstatic int
36835c4bbdfSmrgProcXF86DRIGetDrawableInfo(register ClientPtr client)
36905b261ecSmrg{
37035c4bbdfSmrg    xXF86DRIGetDrawableInfoReply rep = {
37135c4bbdfSmrg        .type = X_Reply,
37235c4bbdfSmrg        .sequenceNumber = client->sequence,
37335c4bbdfSmrg        .length = 0
37435c4bbdfSmrg    };
37505b261ecSmrg    DrawablePtr pDrawable;
37605b261ecSmrg    int X, Y, W, H;
37735c4bbdfSmrg    drm_clip_rect_t *pClipRects, *pClippedRects;
37835c4bbdfSmrg    drm_clip_rect_t *pBackClipRects;
37905b261ecSmrg    int backX, backY, rc;
38005b261ecSmrg
38105b261ecSmrg    REQUEST(xXF86DRIGetDrawableInfoReq);
38205b261ecSmrg    REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq);
38305b261ecSmrg    if (stuff->screen >= screenInfo.numScreens) {
38435c4bbdfSmrg        client->errorValue = stuff->screen;
38535c4bbdfSmrg        return BadValue;
38605b261ecSmrg    }
38705b261ecSmrg
38805b261ecSmrg    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
38935c4bbdfSmrg                           DixReadAccess);
39005b261ecSmrg    if (rc != Success)
39135c4bbdfSmrg        return rc;
39235c4bbdfSmrg
39335c4bbdfSmrg    if (!DRIGetDrawableInfo(screenInfo.screens[stuff->screen],
39435c4bbdfSmrg                            pDrawable,
39535c4bbdfSmrg                            (unsigned int *) &rep.drawableTableIndex,
39635c4bbdfSmrg                            (unsigned int *) &rep.drawableTableStamp,
39735c4bbdfSmrg                            (int *) &X,
39835c4bbdfSmrg                            (int *) &Y,
39935c4bbdfSmrg                            (int *) &W,
40035c4bbdfSmrg                            (int *) &H,
40135c4bbdfSmrg                            (int *) &rep.numClipRects,
40235c4bbdfSmrg                            &pClipRects,
40335c4bbdfSmrg                            &backX,
40435c4bbdfSmrg                            &backY,
40535c4bbdfSmrg                            (int *) &rep.numBackClipRects, &pBackClipRects)) {
40635c4bbdfSmrg        return BadValue;
40705b261ecSmrg    }
40805b261ecSmrg
40905b261ecSmrg    rep.drawableX = X;
41005b261ecSmrg    rep.drawableY = Y;
41105b261ecSmrg    rep.drawableWidth = W;
41205b261ecSmrg    rep.drawableHeight = H;
41335c4bbdfSmrg    rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) - SIZEOF(xGenericReply));
41405b261ecSmrg
41505b261ecSmrg    rep.backX = backX;
41605b261ecSmrg    rep.backY = backY;
41735c4bbdfSmrg
41835c4bbdfSmrg    if (rep.numBackClipRects)
41935c4bbdfSmrg        rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects;
42005b261ecSmrg
42105b261ecSmrg    pClippedRects = pClipRects;
42205b261ecSmrg
42305b261ecSmrg    if (rep.numClipRects) {
42435c4bbdfSmrg        /* Clip cliprects to screen dimensions (redirected windows) */
42535c4bbdfSmrg        pClippedRects = xallocarray(rep.numClipRects, sizeof(drm_clip_rect_t));
42635c4bbdfSmrg
42735c4bbdfSmrg        if (pClippedRects) {
42835c4bbdfSmrg            ScreenPtr pScreen = screenInfo.screens[stuff->screen];
42935c4bbdfSmrg            int i, j;
43035c4bbdfSmrg
43135c4bbdfSmrg            for (i = 0, j = 0; i < rep.numClipRects; i++) {
43235c4bbdfSmrg                pClippedRects[j].x1 = max(pClipRects[i].x1, 0);
43335c4bbdfSmrg                pClippedRects[j].y1 = max(pClipRects[i].y1, 0);
43435c4bbdfSmrg                pClippedRects[j].x2 = min(pClipRects[i].x2, pScreen->width);
43535c4bbdfSmrg                pClippedRects[j].y2 = min(pClipRects[i].y2, pScreen->height);
43635c4bbdfSmrg
43735c4bbdfSmrg                if (pClippedRects[j].x1 < pClippedRects[j].x2 &&
43835c4bbdfSmrg                    pClippedRects[j].y1 < pClippedRects[j].y2) {
43935c4bbdfSmrg                    j++;
44035c4bbdfSmrg                }
44135c4bbdfSmrg            }
44235c4bbdfSmrg
44335c4bbdfSmrg            rep.numClipRects = j;
44435c4bbdfSmrg        }
44535c4bbdfSmrg        else {
44635c4bbdfSmrg            rep.numClipRects = 0;
44735c4bbdfSmrg        }
44835c4bbdfSmrg
44935c4bbdfSmrg        rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects;
45005b261ecSmrg    }
45135c4bbdfSmrg
4526747b715Smrg    rep.length = bytes_to_int32(rep.length);
45305b261ecSmrg
45435c4bbdfSmrg    WriteToClient(client, sizeof(xXF86DRIGetDrawableInfoReply), &rep);
45505b261ecSmrg
45605b261ecSmrg    if (rep.numClipRects) {
45735c4bbdfSmrg        WriteToClient(client,
45835c4bbdfSmrg                      sizeof(drm_clip_rect_t) * rep.numClipRects,
45935c4bbdfSmrg                      pClippedRects);
46035c4bbdfSmrg        free(pClippedRects);
46105b261ecSmrg    }
46205b261ecSmrg
46305b261ecSmrg    if (rep.numBackClipRects) {
46435c4bbdfSmrg        WriteToClient(client,
46535c4bbdfSmrg                      sizeof(drm_clip_rect_t) * rep.numBackClipRects,
46635c4bbdfSmrg                      pBackClipRects);
46705b261ecSmrg    }
46805b261ecSmrg
4696747b715Smrg    return Success;
47005b261ecSmrg}
47105b261ecSmrg
47205b261ecSmrgstatic int
47335c4bbdfSmrgProcXF86DRIGetDeviceInfo(register ClientPtr client)
47405b261ecSmrg{
47535c4bbdfSmrg    xXF86DRIGetDeviceInfoReply rep = {
47635c4bbdfSmrg        .type = X_Reply,
47735c4bbdfSmrg        .sequenceNumber = client->sequence,
47835c4bbdfSmrg        .length = 0
47935c4bbdfSmrg    };
48005b261ecSmrg    drm_handle_t hFrameBuffer;
48105b261ecSmrg    void *pDevPrivate;
48205b261ecSmrg
48305b261ecSmrg    REQUEST(xXF86DRIGetDeviceInfoReq);
48405b261ecSmrg    REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq);
48505b261ecSmrg    if (stuff->screen >= screenInfo.numScreens) {
48635c4bbdfSmrg        client->errorValue = stuff->screen;
48735c4bbdfSmrg        return BadValue;
48805b261ecSmrg    }
48905b261ecSmrg
49035c4bbdfSmrg    if (!DRIGetDeviceInfo(screenInfo.screens[stuff->screen],
49135c4bbdfSmrg                          &hFrameBuffer,
49235c4bbdfSmrg                          (int *) &rep.framebufferOrigin,
49335c4bbdfSmrg                          (int *) &rep.framebufferSize,
49435c4bbdfSmrg                          (int *) &rep.framebufferStride,
49535c4bbdfSmrg                          (int *) &rep.devPrivateSize, &pDevPrivate)) {
49635c4bbdfSmrg        return BadValue;
49705b261ecSmrg    }
49805b261ecSmrg
49935c4bbdfSmrg    rep.hFrameBufferLow = (CARD32) (hFrameBuffer & 0xffffffff);
50005b261ecSmrg#if defined(LONG64) && !defined(__linux__)
50135c4bbdfSmrg    rep.hFrameBufferHigh = (CARD32) (hFrameBuffer >> 32);
50205b261ecSmrg#else
50305b261ecSmrg    rep.hFrameBufferHigh = 0;
50405b261ecSmrg#endif
50505b261ecSmrg
50605b261ecSmrg    if (rep.devPrivateSize) {
50735c4bbdfSmrg        rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetDeviceInfoReply) -
50835c4bbdfSmrg                                    SIZEOF(xGenericReply) +
50935c4bbdfSmrg                                    pad_to_int32(rep.devPrivateSize));
51005b261ecSmrg    }
51105b261ecSmrg
51235c4bbdfSmrg    WriteToClient(client, sizeof(xXF86DRIGetDeviceInfoReply), &rep);
51305b261ecSmrg    if (rep.length) {
51435c4bbdfSmrg        WriteToClient(client, rep.devPrivateSize, pDevPrivate);
51505b261ecSmrg    }
5166747b715Smrg    return Success;
51705b261ecSmrg}
51805b261ecSmrg
51905b261ecSmrgstatic int
52035c4bbdfSmrgProcXF86DRIDispatch(register ClientPtr client)
52105b261ecSmrg{
52205b261ecSmrg    REQUEST(xReq);
52305b261ecSmrg
52435c4bbdfSmrg    switch (stuff->data) {
52505b261ecSmrg    case X_XF86DRIQueryVersion:
52635c4bbdfSmrg        return ProcXF86DRIQueryVersion(client);
52705b261ecSmrg    case X_XF86DRIQueryDirectRenderingCapable:
52835c4bbdfSmrg        return ProcXF86DRIQueryDirectRenderingCapable(client);
52905b261ecSmrg    }
53005b261ecSmrg
53135c4bbdfSmrg    if (!client->local)
53235c4bbdfSmrg        return DRIErrorBase + XF86DRIClientNotLocal;
53305b261ecSmrg
53435c4bbdfSmrg    switch (stuff->data) {
53505b261ecSmrg    case X_XF86DRIOpenConnection:
53635c4bbdfSmrg        return ProcXF86DRIOpenConnection(client);
53705b261ecSmrg    case X_XF86DRICloseConnection:
53835c4bbdfSmrg        return ProcXF86DRICloseConnection(client);
53905b261ecSmrg    case X_XF86DRIGetClientDriverName:
54035c4bbdfSmrg        return ProcXF86DRIGetClientDriverName(client);
54105b261ecSmrg    case X_XF86DRICreateContext:
54235c4bbdfSmrg        return ProcXF86DRICreateContext(client);
54305b261ecSmrg    case X_XF86DRIDestroyContext:
54435c4bbdfSmrg        return ProcXF86DRIDestroyContext(client);
54505b261ecSmrg    case X_XF86DRICreateDrawable:
54635c4bbdfSmrg        return ProcXF86DRICreateDrawable(client);
54705b261ecSmrg    case X_XF86DRIDestroyDrawable:
54835c4bbdfSmrg        return ProcXF86DRIDestroyDrawable(client);
54905b261ecSmrg    case X_XF86DRIGetDrawableInfo:
55035c4bbdfSmrg        return ProcXF86DRIGetDrawableInfo(client);
55105b261ecSmrg    case X_XF86DRIGetDeviceInfo:
55235c4bbdfSmrg        return ProcXF86DRIGetDeviceInfo(client);
55305b261ecSmrg    case X_XF86DRIAuthConnection:
55435c4bbdfSmrg        return ProcXF86DRIAuthConnection(client);
55535c4bbdfSmrg        /* {Open,Close}FullScreen are deprecated now */
55605b261ecSmrg    default:
55735c4bbdfSmrg        return BadRequest;
55805b261ecSmrg    }
55905b261ecSmrg}
56005b261ecSmrg
5617e31ba66Smrgstatic int _X_COLD
56235c4bbdfSmrgSProcXF86DRIQueryVersion(register ClientPtr client)
56305b261ecSmrg{
56405b261ecSmrg    REQUEST(xXF86DRIQueryVersionReq);
56535c4bbdfSmrg    swaps(&stuff->length);
56605b261ecSmrg    return ProcXF86DRIQueryVersion(client);
56705b261ecSmrg}
56805b261ecSmrg
5697e31ba66Smrgstatic int _X_COLD
57035c4bbdfSmrgSProcXF86DRIQueryDirectRenderingCapable(register ClientPtr client)
57105b261ecSmrg{
57205b261ecSmrg    REQUEST(xXF86DRIQueryDirectRenderingCapableReq);
5736e78d31fSmrg    REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq);
57435c4bbdfSmrg    swaps(&stuff->length);
57535c4bbdfSmrg    swapl(&stuff->screen);
57605b261ecSmrg    return ProcXF86DRIQueryDirectRenderingCapable(client);
57705b261ecSmrg}
57805b261ecSmrg
5797e31ba66Smrgstatic int _X_COLD
58035c4bbdfSmrgSProcXF86DRIDispatch(register ClientPtr client)
58105b261ecSmrg{
58205b261ecSmrg    REQUEST(xReq);
58305b261ecSmrg
58405b261ecSmrg    /*
58505b261ecSmrg     * Only local clients are allowed DRI access, but remote clients still need
58605b261ecSmrg     * these requests to find out cleanly.
58705b261ecSmrg     */
58835c4bbdfSmrg    switch (stuff->data) {
58905b261ecSmrg    case X_XF86DRIQueryVersion:
59035c4bbdfSmrg        return SProcXF86DRIQueryVersion(client);
59105b261ecSmrg    case X_XF86DRIQueryDirectRenderingCapable:
59235c4bbdfSmrg        return SProcXF86DRIQueryDirectRenderingCapable(client);
59305b261ecSmrg    default:
59435c4bbdfSmrg        return DRIErrorBase + XF86DRIClientNotLocal;
59505b261ecSmrg    }
59605b261ecSmrg}
5979ace9065Smrg
5989ace9065Smrgvoid
5999ace9065SmrgXFree86DRIExtensionInit(void)
6009ace9065Smrg{
60135c4bbdfSmrg    ExtensionEntry *extEntry;
6029ace9065Smrg
60335c4bbdfSmrg    if (DRIExtensionInit() &&
60435c4bbdfSmrg        (extEntry = AddExtension(XF86DRINAME,
60535c4bbdfSmrg                                 XF86DRINumberEvents,
60635c4bbdfSmrg                                 XF86DRINumberErrors,
60735c4bbdfSmrg                                 ProcXF86DRIDispatch,
60835c4bbdfSmrg                                 SProcXF86DRIDispatch,
60935c4bbdfSmrg                                 XF86DRIResetProc, StandardMinorOpcode))) {
61035c4bbdfSmrg        DRIReqCode = (unsigned char) extEntry->base;
61135c4bbdfSmrg        DRIErrorBase = extEntry->errorBase;
6129ace9065Smrg    }
6139ace9065Smrg}
614