dri3_request.c revision e23ec014
135c4bbdfSmrg/*
235c4bbdfSmrg * Copyright © 2013 Keith Packard
335c4bbdfSmrg *
435c4bbdfSmrg * Permission to use, copy, modify, distribute, and sell this software and its
535c4bbdfSmrg * documentation for any purpose is hereby granted without fee, provided that
635c4bbdfSmrg * the above copyright notice appear in all copies and that both that copyright
735c4bbdfSmrg * notice and this permission notice appear in supporting documentation, and
835c4bbdfSmrg * that the name of the copyright holders not be used in advertising or
935c4bbdfSmrg * publicity pertaining to distribution of the software without specific,
1035c4bbdfSmrg * written prior permission.  The copyright holders make no representations
1135c4bbdfSmrg * about the suitability of this software for any purpose.  It is provided "as
1235c4bbdfSmrg * is" without express or implied warranty.
1335c4bbdfSmrg *
1435c4bbdfSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1535c4bbdfSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1635c4bbdfSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1735c4bbdfSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1835c4bbdfSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1935c4bbdfSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
2035c4bbdfSmrg * OF THIS SOFTWARE.
2135c4bbdfSmrg */
2235c4bbdfSmrg
2335c4bbdfSmrg#ifdef HAVE_XORG_CONFIG_H
2435c4bbdfSmrg#include <xorg-config.h>
2535c4bbdfSmrg#endif
2635c4bbdfSmrg
2735c4bbdfSmrg#include "dri3_priv.h"
2835c4bbdfSmrg#include <syncsrv.h>
2935c4bbdfSmrg#include <unistd.h>
3035c4bbdfSmrg#include <xace.h>
3135c4bbdfSmrg#include "../Xext/syncsdk.h"
3235c4bbdfSmrg#include <protocol-versions.h>
331b5d61b8Smrg#include <drm_fourcc.h>
341b5d61b8Smrg
351b5d61b8Smrgstatic Bool
361b5d61b8Smrgdri3_screen_can_one_point_two(ScreenPtr screen)
371b5d61b8Smrg{
381b5d61b8Smrg    dri3_screen_priv_ptr dri3 = dri3_screen_priv(screen);
391b5d61b8Smrg
401b5d61b8Smrg    if (dri3 && dri3->info && dri3->info->version >= 2 &&
411b5d61b8Smrg        dri3->info->pixmap_from_fds && dri3->info->fds_from_pixmap &&
421b5d61b8Smrg        dri3->info->get_formats && dri3->info->get_modifiers &&
431b5d61b8Smrg        dri3->info->get_drawable_modifiers)
441b5d61b8Smrg        return TRUE;
451b5d61b8Smrg
461b5d61b8Smrg    return FALSE;
471b5d61b8Smrg}
4835c4bbdfSmrg
4935c4bbdfSmrgstatic int
5035c4bbdfSmrgproc_dri3_query_version(ClientPtr client)
5135c4bbdfSmrg{
5235c4bbdfSmrg    REQUEST(xDRI3QueryVersionReq);
5335c4bbdfSmrg    xDRI3QueryVersionReply rep = {
5435c4bbdfSmrg        .type = X_Reply,
5535c4bbdfSmrg        .sequenceNumber = client->sequence,
5635c4bbdfSmrg        .length = 0,
5735c4bbdfSmrg        .majorVersion = SERVER_DRI3_MAJOR_VERSION,
5835c4bbdfSmrg        .minorVersion = SERVER_DRI3_MINOR_VERSION
5935c4bbdfSmrg    };
6035c4bbdfSmrg
6135c4bbdfSmrg    REQUEST_SIZE_MATCH(xDRI3QueryVersionReq);
621b5d61b8Smrg
631b5d61b8Smrg    for (int i = 0; i < screenInfo.numScreens; i++) {
641b5d61b8Smrg        if (!dri3_screen_can_one_point_two(screenInfo.screens[i])) {
651b5d61b8Smrg            rep.minorVersion = 0;
661b5d61b8Smrg            break;
671b5d61b8Smrg        }
681b5d61b8Smrg    }
691b5d61b8Smrg
701b5d61b8Smrg    for (int i = 0; i < screenInfo.numGPUScreens; i++) {
711b5d61b8Smrg        if (!dri3_screen_can_one_point_two(screenInfo.gpuscreens[i])) {
721b5d61b8Smrg            rep.minorVersion = 0;
731b5d61b8Smrg            break;
741b5d61b8Smrg        }
751b5d61b8Smrg    }
761b5d61b8Smrg
771b5d61b8Smrg    /* From DRI3 proto:
781b5d61b8Smrg     *
791b5d61b8Smrg     * The client sends the highest supported version to the server
801b5d61b8Smrg     * and the server sends the highest version it supports, but no
811b5d61b8Smrg     * higher than the requested version.
821b5d61b8Smrg     */
831b5d61b8Smrg
841b5d61b8Smrg    if (rep.majorVersion > stuff->majorVersion ||
851b5d61b8Smrg        (rep.majorVersion == stuff->majorVersion &&
861b5d61b8Smrg         rep.minorVersion > stuff->minorVersion)) {
871b5d61b8Smrg        rep.majorVersion = stuff->majorVersion;
881b5d61b8Smrg        rep.minorVersion = stuff->minorVersion;
891b5d61b8Smrg    }
901b5d61b8Smrg
9135c4bbdfSmrg    if (client->swapped) {
9235c4bbdfSmrg        swaps(&rep.sequenceNumber);
9335c4bbdfSmrg        swapl(&rep.length);
9435c4bbdfSmrg        swapl(&rep.majorVersion);
9535c4bbdfSmrg        swapl(&rep.minorVersion);
9635c4bbdfSmrg    }
9735c4bbdfSmrg    WriteToClient(client, sizeof(rep), &rep);
9835c4bbdfSmrg    return Success;
9935c4bbdfSmrg}
10035c4bbdfSmrg
10135c4bbdfSmrgint
10235c4bbdfSmrgdri3_send_open_reply(ClientPtr client, int fd)
10335c4bbdfSmrg{
10435c4bbdfSmrg    xDRI3OpenReply rep = {
10535c4bbdfSmrg        .type = X_Reply,
10635c4bbdfSmrg        .nfd = 1,
10735c4bbdfSmrg        .sequenceNumber = client->sequence,
10835c4bbdfSmrg        .length = 0,
10935c4bbdfSmrg    };
11035c4bbdfSmrg
11135c4bbdfSmrg    if (client->swapped) {
11235c4bbdfSmrg        swaps(&rep.sequenceNumber);
11335c4bbdfSmrg        swapl(&rep.length);
11435c4bbdfSmrg    }
11535c4bbdfSmrg
11635c4bbdfSmrg    if (WriteFdToClient(client, fd, TRUE) < 0) {
11735c4bbdfSmrg        close(fd);
11835c4bbdfSmrg        return BadAlloc;
11935c4bbdfSmrg    }
12035c4bbdfSmrg
12135c4bbdfSmrg    WriteToClient(client, sizeof (rep), &rep);
12235c4bbdfSmrg
12335c4bbdfSmrg    return Success;
12435c4bbdfSmrg}
12535c4bbdfSmrg
12635c4bbdfSmrgstatic int
12735c4bbdfSmrgproc_dri3_open(ClientPtr client)
12835c4bbdfSmrg{
12935c4bbdfSmrg    REQUEST(xDRI3OpenReq);
13035c4bbdfSmrg    RRProviderPtr provider;
13135c4bbdfSmrg    DrawablePtr drawable;
13235c4bbdfSmrg    ScreenPtr screen;
13335c4bbdfSmrg    int fd;
13435c4bbdfSmrg    int status;
13535c4bbdfSmrg
13635c4bbdfSmrg    REQUEST_SIZE_MATCH(xDRI3OpenReq);
13735c4bbdfSmrg
138e23ec014Smrg    status = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixGetAttrAccess);
13935c4bbdfSmrg    if (status != Success)
14035c4bbdfSmrg        return status;
14135c4bbdfSmrg
14235c4bbdfSmrg    if (stuff->provider == None)
14335c4bbdfSmrg        provider = NULL;
14435c4bbdfSmrg    else if (!RRProviderType) {
14535c4bbdfSmrg        return BadMatch;
14635c4bbdfSmrg    } else {
14735c4bbdfSmrg        VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
14835c4bbdfSmrg        if (drawable->pScreen != provider->pScreen)
14935c4bbdfSmrg            return BadMatch;
15035c4bbdfSmrg    }
15135c4bbdfSmrg    screen = drawable->pScreen;
15235c4bbdfSmrg
15335c4bbdfSmrg    status = dri3_open(client, screen, provider, &fd);
15435c4bbdfSmrg    if (status != Success)
15535c4bbdfSmrg        return status;
15635c4bbdfSmrg
15735c4bbdfSmrg    if (client->ignoreCount == 0)
15835c4bbdfSmrg        return dri3_send_open_reply(client, fd);
15935c4bbdfSmrg
16035c4bbdfSmrg    return Success;
16135c4bbdfSmrg}
16235c4bbdfSmrg
16335c4bbdfSmrgstatic int
16435c4bbdfSmrgproc_dri3_pixmap_from_buffer(ClientPtr client)
16535c4bbdfSmrg{
16635c4bbdfSmrg    REQUEST(xDRI3PixmapFromBufferReq);
16735c4bbdfSmrg    int fd;
16835c4bbdfSmrg    DrawablePtr drawable;
16935c4bbdfSmrg    PixmapPtr pixmap;
1701b5d61b8Smrg    CARD32 stride, offset;
17135c4bbdfSmrg    int rc;
17235c4bbdfSmrg
17335c4bbdfSmrg    SetReqFds(client, 1);
17435c4bbdfSmrg    REQUEST_SIZE_MATCH(xDRI3PixmapFromBufferReq);
17535c4bbdfSmrg    LEGAL_NEW_RESOURCE(stuff->pixmap, client);
17635c4bbdfSmrg    rc = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
17735c4bbdfSmrg    if (rc != Success) {
17835c4bbdfSmrg        client->errorValue = stuff->drawable;
17935c4bbdfSmrg        return rc;
18035c4bbdfSmrg    }
18135c4bbdfSmrg
18235c4bbdfSmrg    if (!stuff->width || !stuff->height) {
18335c4bbdfSmrg        client->errorValue = 0;
18435c4bbdfSmrg        return BadValue;
18535c4bbdfSmrg    }
18635c4bbdfSmrg
18735c4bbdfSmrg    if (stuff->width > 32767 || stuff->height > 32767)
18835c4bbdfSmrg        return BadAlloc;
18935c4bbdfSmrg
19035c4bbdfSmrg    if (stuff->depth != 1) {
19135c4bbdfSmrg        DepthPtr depth = drawable->pScreen->allowedDepths;
19235c4bbdfSmrg        int i;
19335c4bbdfSmrg        for (i = 0; i < drawable->pScreen->numDepths; i++, depth++)
19435c4bbdfSmrg            if (depth->depth == stuff->depth)
19535c4bbdfSmrg                break;
19635c4bbdfSmrg        if (i == drawable->pScreen->numDepths) {
19735c4bbdfSmrg            client->errorValue = stuff->depth;
19835c4bbdfSmrg            return BadValue;
19935c4bbdfSmrg        }
20035c4bbdfSmrg    }
20135c4bbdfSmrg
20235c4bbdfSmrg    fd = ReadFdFromClient(client);
20335c4bbdfSmrg    if (fd < 0)
20435c4bbdfSmrg        return BadValue;
20535c4bbdfSmrg
2061b5d61b8Smrg    offset = 0;
2071b5d61b8Smrg    stride = stuff->stride;
2081b5d61b8Smrg    rc = dri3_pixmap_from_fds(&pixmap,
2091b5d61b8Smrg                              drawable->pScreen, 1, &fd,
2101b5d61b8Smrg                              stuff->width, stuff->height,
2111b5d61b8Smrg                              &stride, &offset,
2121b5d61b8Smrg                              stuff->depth, stuff->bpp,
2131b5d61b8Smrg                              DRM_FORMAT_MOD_INVALID);
21435c4bbdfSmrg    close (fd);
21535c4bbdfSmrg    if (rc != Success)
21635c4bbdfSmrg        return rc;
21735c4bbdfSmrg
21835c4bbdfSmrg    pixmap->drawable.id = stuff->pixmap;
21935c4bbdfSmrg
22035c4bbdfSmrg    /* security creation/labeling check */
22135c4bbdfSmrg    rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP,
22235c4bbdfSmrg                  pixmap, RT_NONE, NULL, DixCreateAccess);
22335c4bbdfSmrg
22435c4bbdfSmrg    if (rc != Success) {
22535c4bbdfSmrg        (*drawable->pScreen->DestroyPixmap) (pixmap);
22635c4bbdfSmrg        return rc;
22735c4bbdfSmrg    }
2281b5d61b8Smrg    if (!AddResource(stuff->pixmap, RT_PIXMAP, (void *) pixmap))
2291b5d61b8Smrg        return BadAlloc;
23035c4bbdfSmrg
23135c4bbdfSmrg    return Success;
23235c4bbdfSmrg}
23335c4bbdfSmrg
23435c4bbdfSmrgstatic int
23535c4bbdfSmrgproc_dri3_buffer_from_pixmap(ClientPtr client)
23635c4bbdfSmrg{
23735c4bbdfSmrg    REQUEST(xDRI3BufferFromPixmapReq);
23835c4bbdfSmrg    xDRI3BufferFromPixmapReply rep = {
23935c4bbdfSmrg        .type = X_Reply,
24035c4bbdfSmrg        .nfd = 1,
24135c4bbdfSmrg        .sequenceNumber = client->sequence,
24235c4bbdfSmrg        .length = 0,
24335c4bbdfSmrg    };
24435c4bbdfSmrg    int rc;
24535c4bbdfSmrg    int fd;
24635c4bbdfSmrg    PixmapPtr pixmap;
24735c4bbdfSmrg
24835c4bbdfSmrg    REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq);
24935c4bbdfSmrg    rc = dixLookupResourceByType((void **) &pixmap, stuff->pixmap, RT_PIXMAP,
25035c4bbdfSmrg                                 client, DixWriteAccess);
25135c4bbdfSmrg    if (rc != Success) {
25235c4bbdfSmrg        client->errorValue = stuff->pixmap;
25335c4bbdfSmrg        return rc;
25435c4bbdfSmrg    }
25535c4bbdfSmrg
25635c4bbdfSmrg    rep.width = pixmap->drawable.width;
25735c4bbdfSmrg    rep.height = pixmap->drawable.height;
25835c4bbdfSmrg    rep.depth = pixmap->drawable.depth;
25935c4bbdfSmrg    rep.bpp = pixmap->drawable.bitsPerPixel;
26035c4bbdfSmrg
2611b5d61b8Smrg    fd = dri3_fd_from_pixmap(pixmap, &rep.stride, &rep.size);
2621b5d61b8Smrg    if (fd < 0)
2631b5d61b8Smrg        return BadPixmap;
26435c4bbdfSmrg
26535c4bbdfSmrg    if (client->swapped) {
26635c4bbdfSmrg        swaps(&rep.sequenceNumber);
26735c4bbdfSmrg        swapl(&rep.length);
26835c4bbdfSmrg        swapl(&rep.size);
26935c4bbdfSmrg        swaps(&rep.width);
27035c4bbdfSmrg        swaps(&rep.height);
27135c4bbdfSmrg        swaps(&rep.stride);
27235c4bbdfSmrg    }
27335c4bbdfSmrg    if (WriteFdToClient(client, fd, TRUE) < 0) {
27435c4bbdfSmrg        close(fd);
27535c4bbdfSmrg        return BadAlloc;
27635c4bbdfSmrg    }
27735c4bbdfSmrg
27835c4bbdfSmrg    WriteToClient(client, sizeof(rep), &rep);
27935c4bbdfSmrg
2801b5d61b8Smrg    return Success;
28135c4bbdfSmrg}
28235c4bbdfSmrg
28335c4bbdfSmrgstatic int
28435c4bbdfSmrgproc_dri3_fence_from_fd(ClientPtr client)
28535c4bbdfSmrg{
28635c4bbdfSmrg    REQUEST(xDRI3FenceFromFDReq);
28735c4bbdfSmrg    DrawablePtr drawable;
28835c4bbdfSmrg    int fd;
28935c4bbdfSmrg    int status;
29035c4bbdfSmrg
29135c4bbdfSmrg    SetReqFds(client, 1);
29235c4bbdfSmrg    REQUEST_SIZE_MATCH(xDRI3FenceFromFDReq);
29335c4bbdfSmrg    LEGAL_NEW_RESOURCE(stuff->fence, client);
29435c4bbdfSmrg
29535c4bbdfSmrg    status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
29635c4bbdfSmrg    if (status != Success)
29735c4bbdfSmrg        return status;
29835c4bbdfSmrg
29935c4bbdfSmrg    fd = ReadFdFromClient(client);
30035c4bbdfSmrg    if (fd < 0)
30135c4bbdfSmrg        return BadValue;
30235c4bbdfSmrg
30335c4bbdfSmrg    status = SyncCreateFenceFromFD(client, drawable, stuff->fence,
30435c4bbdfSmrg                                   fd, stuff->initially_triggered);
30535c4bbdfSmrg
30635c4bbdfSmrg    return status;
30735c4bbdfSmrg}
30835c4bbdfSmrg
30935c4bbdfSmrgstatic int
31035c4bbdfSmrgproc_dri3_fd_from_fence(ClientPtr client)
31135c4bbdfSmrg{
31235c4bbdfSmrg    REQUEST(xDRI3FDFromFenceReq);
31335c4bbdfSmrg    xDRI3FDFromFenceReply rep = {
31435c4bbdfSmrg        .type = X_Reply,
31535c4bbdfSmrg        .nfd = 1,
31635c4bbdfSmrg        .sequenceNumber = client->sequence,
31735c4bbdfSmrg        .length = 0,
31835c4bbdfSmrg    };
31935c4bbdfSmrg    DrawablePtr drawable;
32035c4bbdfSmrg    int fd;
32135c4bbdfSmrg    int status;
32235c4bbdfSmrg    SyncFence *fence;
32335c4bbdfSmrg
32435c4bbdfSmrg    REQUEST_SIZE_MATCH(xDRI3FDFromFenceReq);
32535c4bbdfSmrg
32635c4bbdfSmrg    status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
32735c4bbdfSmrg    if (status != Success)
32835c4bbdfSmrg        return status;
32935c4bbdfSmrg    status = SyncVerifyFence(&fence, stuff->fence, client, DixWriteAccess);
33035c4bbdfSmrg    if (status != Success)
33135c4bbdfSmrg        return status;
33235c4bbdfSmrg
33335c4bbdfSmrg    fd = SyncFDFromFence(client, drawable, fence);
33435c4bbdfSmrg    if (fd < 0)
33535c4bbdfSmrg        return BadMatch;
33635c4bbdfSmrg
33735c4bbdfSmrg    if (client->swapped) {
33835c4bbdfSmrg        swaps(&rep.sequenceNumber);
33935c4bbdfSmrg        swapl(&rep.length);
34035c4bbdfSmrg    }
34135c4bbdfSmrg    if (WriteFdToClient(client, fd, FALSE) < 0)
34235c4bbdfSmrg        return BadAlloc;
34335c4bbdfSmrg
34435c4bbdfSmrg    WriteToClient(client, sizeof(rep), &rep);
34535c4bbdfSmrg
3461b5d61b8Smrg    return Success;
3471b5d61b8Smrg}
3481b5d61b8Smrg
3491b5d61b8Smrgstatic int
3501b5d61b8Smrgproc_dri3_get_supported_modifiers(ClientPtr client)
3511b5d61b8Smrg{
3521b5d61b8Smrg    REQUEST(xDRI3GetSupportedModifiersReq);
3531b5d61b8Smrg    xDRI3GetSupportedModifiersReply rep = {
3541b5d61b8Smrg        .type = X_Reply,
3551b5d61b8Smrg        .sequenceNumber = client->sequence,
3561b5d61b8Smrg    };
3571b5d61b8Smrg    WindowPtr window;
3581b5d61b8Smrg    ScreenPtr pScreen;
3591b5d61b8Smrg    CARD64 *window_modifiers = NULL;
3601b5d61b8Smrg    CARD64 *screen_modifiers = NULL;
3611b5d61b8Smrg    CARD32 nwindowmodifiers = 0;
3621b5d61b8Smrg    CARD32 nscreenmodifiers = 0;
3631b5d61b8Smrg    int status;
3641b5d61b8Smrg    int i;
3651b5d61b8Smrg
3661b5d61b8Smrg    REQUEST_SIZE_MATCH(xDRI3GetSupportedModifiersReq);
3671b5d61b8Smrg
368e23ec014Smrg    status = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
3691b5d61b8Smrg    if (status != Success)
3701b5d61b8Smrg        return status;
3711b5d61b8Smrg    pScreen = window->drawable.pScreen;
3721b5d61b8Smrg
3731b5d61b8Smrg    dri3_get_supported_modifiers(pScreen, &window->drawable,
3741b5d61b8Smrg				 stuff->depth, stuff->bpp,
3751b5d61b8Smrg                                 &nwindowmodifiers, &window_modifiers,
3761b5d61b8Smrg                                 &nscreenmodifiers, &screen_modifiers);
3771b5d61b8Smrg
3781b5d61b8Smrg    rep.numWindowModifiers = nwindowmodifiers;
3791b5d61b8Smrg    rep.numScreenModifiers = nscreenmodifiers;
3801b5d61b8Smrg    rep.length = bytes_to_int32(rep.numWindowModifiers * sizeof(CARD64)) +
3811b5d61b8Smrg                 bytes_to_int32(rep.numScreenModifiers * sizeof(CARD64));
3821b5d61b8Smrg
3831b5d61b8Smrg    if (client->swapped) {
3841b5d61b8Smrg        swaps(&rep.sequenceNumber);
3851b5d61b8Smrg        swapl(&rep.length);
3861b5d61b8Smrg        swapl(&rep.numWindowModifiers);
3871b5d61b8Smrg        swapl(&rep.numScreenModifiers);
3881b5d61b8Smrg        for (i = 0; i < nwindowmodifiers; i++)
3891b5d61b8Smrg            swapll(&window_modifiers[i]);
3901b5d61b8Smrg        for (i = 0; i < nscreenmodifiers; i++)
3911b5d61b8Smrg            swapll(&screen_modifiers[i]);
3921b5d61b8Smrg    }
3931b5d61b8Smrg
3941b5d61b8Smrg    WriteToClient(client, sizeof(rep), &rep);
3951b5d61b8Smrg    WriteToClient(client, nwindowmodifiers * sizeof(CARD64), window_modifiers);
3961b5d61b8Smrg    WriteToClient(client, nscreenmodifiers * sizeof(CARD64), screen_modifiers);
3971b5d61b8Smrg
3981b5d61b8Smrg    free(window_modifiers);
3991b5d61b8Smrg    free(screen_modifiers);
4001b5d61b8Smrg
4011b5d61b8Smrg    return Success;
4021b5d61b8Smrg}
4031b5d61b8Smrg
4041b5d61b8Smrgstatic int
4051b5d61b8Smrgproc_dri3_pixmap_from_buffers(ClientPtr client)
4061b5d61b8Smrg{
4071b5d61b8Smrg    REQUEST(xDRI3PixmapFromBuffersReq);
4081b5d61b8Smrg    int fds[4];
4091b5d61b8Smrg    CARD32 strides[4], offsets[4];
4101b5d61b8Smrg    ScreenPtr screen;
4111b5d61b8Smrg    WindowPtr window;
4121b5d61b8Smrg    PixmapPtr pixmap;
4131b5d61b8Smrg    int rc;
4141b5d61b8Smrg    int i;
4151b5d61b8Smrg
4161b5d61b8Smrg    SetReqFds(client, stuff->num_buffers);
4171b5d61b8Smrg    REQUEST_SIZE_MATCH(xDRI3PixmapFromBuffersReq);
4181b5d61b8Smrg    LEGAL_NEW_RESOURCE(stuff->pixmap, client);
4191b5d61b8Smrg    rc = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
4201b5d61b8Smrg    if (rc != Success) {
4211b5d61b8Smrg        client->errorValue = stuff->window;
4221b5d61b8Smrg        return rc;
4231b5d61b8Smrg    }
4241b5d61b8Smrg    screen = window->drawable.pScreen;
4251b5d61b8Smrg
4261b5d61b8Smrg    if (!stuff->width || !stuff->height || !stuff->bpp || !stuff->depth) {
4271b5d61b8Smrg        client->errorValue = 0;
4281b5d61b8Smrg        return BadValue;
4291b5d61b8Smrg    }
4301b5d61b8Smrg
4311b5d61b8Smrg    if (stuff->width > 32767 || stuff->height > 32767)
4321b5d61b8Smrg        return BadAlloc;
4331b5d61b8Smrg
4341b5d61b8Smrg    if (stuff->depth != 1) {
4351b5d61b8Smrg        DepthPtr depth = screen->allowedDepths;
4361b5d61b8Smrg        int j;
4371b5d61b8Smrg        for (j = 0; j < screen->numDepths; j++, depth++)
4381b5d61b8Smrg            if (depth->depth == stuff->depth)
4391b5d61b8Smrg                break;
4401b5d61b8Smrg        if (j == screen->numDepths) {
4411b5d61b8Smrg            client->errorValue = stuff->depth;
4421b5d61b8Smrg            return BadValue;
4431b5d61b8Smrg        }
4441b5d61b8Smrg    }
4451b5d61b8Smrg
4461b5d61b8Smrg    if (!stuff->num_buffers || stuff->num_buffers > 4) {
4471b5d61b8Smrg        client->errorValue = stuff->num_buffers;
4481b5d61b8Smrg        return BadValue;
4491b5d61b8Smrg    }
4501b5d61b8Smrg
4511b5d61b8Smrg    for (i = 0; i < stuff->num_buffers; i++) {
4521b5d61b8Smrg        fds[i] = ReadFdFromClient(client);
4531b5d61b8Smrg        if (fds[i] < 0) {
4541b5d61b8Smrg            while (--i >= 0)
4551b5d61b8Smrg                close(fds[i]);
4561b5d61b8Smrg            return BadValue;
4571b5d61b8Smrg        }
4581b5d61b8Smrg    }
4591b5d61b8Smrg
4601b5d61b8Smrg    strides[0] = stuff->stride0;
4611b5d61b8Smrg    strides[1] = stuff->stride1;
4621b5d61b8Smrg    strides[2] = stuff->stride2;
4631b5d61b8Smrg    strides[3] = stuff->stride3;
4641b5d61b8Smrg    offsets[0] = stuff->offset0;
4651b5d61b8Smrg    offsets[1] = stuff->offset1;
4661b5d61b8Smrg    offsets[2] = stuff->offset2;
4671b5d61b8Smrg    offsets[3] = stuff->offset3;
4681b5d61b8Smrg
4691b5d61b8Smrg    rc = dri3_pixmap_from_fds(&pixmap, screen,
4701b5d61b8Smrg                              stuff->num_buffers, fds,
4711b5d61b8Smrg                              stuff->width, stuff->height,
4721b5d61b8Smrg                              strides, offsets,
4731b5d61b8Smrg                              stuff->depth, stuff->bpp,
4741b5d61b8Smrg                              stuff->modifier);
4751b5d61b8Smrg
4761b5d61b8Smrg    for (i = 0; i < stuff->num_buffers; i++)
4771b5d61b8Smrg        close (fds[i]);
4781b5d61b8Smrg
4791b5d61b8Smrg    if (rc != Success)
4801b5d61b8Smrg        return rc;
4811b5d61b8Smrg
4821b5d61b8Smrg    pixmap->drawable.id = stuff->pixmap;
4831b5d61b8Smrg
4841b5d61b8Smrg    /* security creation/labeling check */
4851b5d61b8Smrg    rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP,
4861b5d61b8Smrg                  pixmap, RT_NONE, NULL, DixCreateAccess);
4871b5d61b8Smrg
4881b5d61b8Smrg    if (rc != Success) {
4891b5d61b8Smrg        (*screen->DestroyPixmap) (pixmap);
4901b5d61b8Smrg        return rc;
4911b5d61b8Smrg    }
4921b5d61b8Smrg    if (!AddResource(stuff->pixmap, RT_PIXMAP, (void *) pixmap))
4931b5d61b8Smrg        return BadAlloc;
4941b5d61b8Smrg
4951b5d61b8Smrg    return Success;
4961b5d61b8Smrg}
4971b5d61b8Smrg
4981b5d61b8Smrgstatic int
4991b5d61b8Smrgproc_dri3_buffers_from_pixmap(ClientPtr client)
5001b5d61b8Smrg{
5011b5d61b8Smrg    REQUEST(xDRI3BuffersFromPixmapReq);
5021b5d61b8Smrg    xDRI3BuffersFromPixmapReply rep = {
5031b5d61b8Smrg        .type = X_Reply,
5041b5d61b8Smrg        .sequenceNumber = client->sequence,
5051b5d61b8Smrg    };
5061b5d61b8Smrg    int rc;
5071b5d61b8Smrg    int fds[4];
5081b5d61b8Smrg    int num_fds;
5091b5d61b8Smrg    uint32_t strides[4], offsets[4];
5101b5d61b8Smrg    uint64_t modifier;
5111b5d61b8Smrg    int i;
5121b5d61b8Smrg    PixmapPtr pixmap;
5131b5d61b8Smrg
5141b5d61b8Smrg    REQUEST_SIZE_MATCH(xDRI3BuffersFromPixmapReq);
5151b5d61b8Smrg    rc = dixLookupResourceByType((void **) &pixmap, stuff->pixmap, RT_PIXMAP,
5161b5d61b8Smrg                                 client, DixWriteAccess);
5171b5d61b8Smrg    if (rc != Success) {
5181b5d61b8Smrg        client->errorValue = stuff->pixmap;
5191b5d61b8Smrg        return rc;
5201b5d61b8Smrg    }
5211b5d61b8Smrg
5221b5d61b8Smrg    num_fds = dri3_fds_from_pixmap(pixmap, fds, strides, offsets, &modifier);
5231b5d61b8Smrg    if (num_fds == 0)
5241b5d61b8Smrg        return BadPixmap;
5251b5d61b8Smrg
5261b5d61b8Smrg    rep.nfd = num_fds;
5271b5d61b8Smrg    rep.length = bytes_to_int32(num_fds * 2 * sizeof(CARD32));
5281b5d61b8Smrg    rep.width = pixmap->drawable.width;
5291b5d61b8Smrg    rep.height = pixmap->drawable.height;
5301b5d61b8Smrg    rep.depth = pixmap->drawable.depth;
5311b5d61b8Smrg    rep.bpp = pixmap->drawable.bitsPerPixel;
5321b5d61b8Smrg    rep.modifier = modifier;
5331b5d61b8Smrg
5341b5d61b8Smrg    if (client->swapped) {
5351b5d61b8Smrg        swaps(&rep.sequenceNumber);
5361b5d61b8Smrg        swapl(&rep.length);
5371b5d61b8Smrg        swaps(&rep.width);
5381b5d61b8Smrg        swaps(&rep.height);
5391b5d61b8Smrg        swapll(&rep.modifier);
5401b5d61b8Smrg        for (i = 0; i < num_fds; i++) {
5411b5d61b8Smrg            swapl(&strides[i]);
5421b5d61b8Smrg            swapl(&offsets[i]);
5431b5d61b8Smrg        }
5441b5d61b8Smrg    }
5451b5d61b8Smrg
5461b5d61b8Smrg    for (i = 0; i < num_fds; i++) {
5471b5d61b8Smrg        if (WriteFdToClient(client, fds[i], TRUE) < 0) {
5481b5d61b8Smrg            while (i--)
5491b5d61b8Smrg                close(fds[i]);
5501b5d61b8Smrg            return BadAlloc;
5511b5d61b8Smrg        }
5521b5d61b8Smrg    }
5531b5d61b8Smrg
5541b5d61b8Smrg    WriteToClient(client, sizeof(rep), &rep);
5551b5d61b8Smrg    WriteToClient(client, num_fds * sizeof(CARD32), strides);
5561b5d61b8Smrg    WriteToClient(client, num_fds * sizeof(CARD32), offsets);
5571b5d61b8Smrg
5581b5d61b8Smrg    return Success;
55935c4bbdfSmrg}
56035c4bbdfSmrg
56135c4bbdfSmrgint (*proc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = {
56235c4bbdfSmrg    proc_dri3_query_version,            /* 0 */
56335c4bbdfSmrg    proc_dri3_open,                     /* 1 */
56435c4bbdfSmrg    proc_dri3_pixmap_from_buffer,       /* 2 */
56535c4bbdfSmrg    proc_dri3_buffer_from_pixmap,       /* 3 */
56635c4bbdfSmrg    proc_dri3_fence_from_fd,            /* 4 */
56735c4bbdfSmrg    proc_dri3_fd_from_fence,            /* 5 */
5681b5d61b8Smrg    proc_dri3_get_supported_modifiers,  /* 6 */
5691b5d61b8Smrg    proc_dri3_pixmap_from_buffers,      /* 7 */
5701b5d61b8Smrg    proc_dri3_buffers_from_pixmap,      /* 8 */
57135c4bbdfSmrg};
57235c4bbdfSmrg
57335c4bbdfSmrgint
57435c4bbdfSmrgproc_dri3_dispatch(ClientPtr client)
57535c4bbdfSmrg{
57635c4bbdfSmrg    REQUEST(xReq);
57735c4bbdfSmrg    if (!client->local)
57835c4bbdfSmrg        return BadMatch;
57935c4bbdfSmrg    if (stuff->data >= DRI3NumberRequests || !proc_dri3_vector[stuff->data])
58035c4bbdfSmrg        return BadRequest;
58135c4bbdfSmrg    return (*proc_dri3_vector[stuff->data]) (client);
58235c4bbdfSmrg}
58335c4bbdfSmrg
5841b5d61b8Smrgstatic int _X_COLD
58535c4bbdfSmrgsproc_dri3_query_version(ClientPtr client)
58635c4bbdfSmrg{
58735c4bbdfSmrg    REQUEST(xDRI3QueryVersionReq);
58835c4bbdfSmrg    REQUEST_SIZE_MATCH(xDRI3QueryVersionReq);
58935c4bbdfSmrg
59035c4bbdfSmrg    swaps(&stuff->length);
59135c4bbdfSmrg    swapl(&stuff->majorVersion);
59235c4bbdfSmrg    swapl(&stuff->minorVersion);
59335c4bbdfSmrg    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
59435c4bbdfSmrg}
59535c4bbdfSmrg
5961b5d61b8Smrgstatic int _X_COLD
59735c4bbdfSmrgsproc_dri3_open(ClientPtr client)
59835c4bbdfSmrg{
59935c4bbdfSmrg    REQUEST(xDRI3OpenReq);
60035c4bbdfSmrg    REQUEST_SIZE_MATCH(xDRI3OpenReq);
60135c4bbdfSmrg
60235c4bbdfSmrg    swaps(&stuff->length);
60335c4bbdfSmrg    swapl(&stuff->drawable);
60435c4bbdfSmrg    swapl(&stuff->provider);
60535c4bbdfSmrg    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
60635c4bbdfSmrg}
60735c4bbdfSmrg
6081b5d61b8Smrgstatic int _X_COLD
60935c4bbdfSmrgsproc_dri3_pixmap_from_buffer(ClientPtr client)
61035c4bbdfSmrg{
61135c4bbdfSmrg    REQUEST(xDRI3PixmapFromBufferReq);
61235c4bbdfSmrg    REQUEST_SIZE_MATCH(xDRI3PixmapFromBufferReq);
61335c4bbdfSmrg
61435c4bbdfSmrg    swaps(&stuff->length);
61535c4bbdfSmrg    swapl(&stuff->pixmap);
61635c4bbdfSmrg    swapl(&stuff->drawable);
61735c4bbdfSmrg    swapl(&stuff->size);
61835c4bbdfSmrg    swaps(&stuff->width);
61935c4bbdfSmrg    swaps(&stuff->height);
62035c4bbdfSmrg    swaps(&stuff->stride);
62135c4bbdfSmrg    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
62235c4bbdfSmrg}
62335c4bbdfSmrg
6241b5d61b8Smrgstatic int _X_COLD
62535c4bbdfSmrgsproc_dri3_buffer_from_pixmap(ClientPtr client)
62635c4bbdfSmrg{
62735c4bbdfSmrg    REQUEST(xDRI3BufferFromPixmapReq);
62835c4bbdfSmrg    REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq);
62935c4bbdfSmrg
63035c4bbdfSmrg    swaps(&stuff->length);
63135c4bbdfSmrg    swapl(&stuff->pixmap);
63235c4bbdfSmrg    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
63335c4bbdfSmrg}
63435c4bbdfSmrg
6351b5d61b8Smrgstatic int _X_COLD
63635c4bbdfSmrgsproc_dri3_fence_from_fd(ClientPtr client)
63735c4bbdfSmrg{
63835c4bbdfSmrg    REQUEST(xDRI3FenceFromFDReq);
63935c4bbdfSmrg    REQUEST_SIZE_MATCH(xDRI3FenceFromFDReq);
64035c4bbdfSmrg
64135c4bbdfSmrg    swaps(&stuff->length);
64235c4bbdfSmrg    swapl(&stuff->drawable);
64335c4bbdfSmrg    swapl(&stuff->fence);
64435c4bbdfSmrg    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
64535c4bbdfSmrg}
64635c4bbdfSmrg
6471b5d61b8Smrgstatic int _X_COLD
64835c4bbdfSmrgsproc_dri3_fd_from_fence(ClientPtr client)
64935c4bbdfSmrg{
65035c4bbdfSmrg    REQUEST(xDRI3FDFromFenceReq);
65135c4bbdfSmrg    REQUEST_SIZE_MATCH(xDRI3FDFromFenceReq);
65235c4bbdfSmrg
65335c4bbdfSmrg    swaps(&stuff->length);
65435c4bbdfSmrg    swapl(&stuff->drawable);
65535c4bbdfSmrg    swapl(&stuff->fence);
65635c4bbdfSmrg    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
65735c4bbdfSmrg}
65835c4bbdfSmrg
6591b5d61b8Smrgstatic int _X_COLD
6601b5d61b8Smrgsproc_dri3_get_supported_modifiers(ClientPtr client)
6611b5d61b8Smrg{
6621b5d61b8Smrg    REQUEST(xDRI3GetSupportedModifiersReq);
6631b5d61b8Smrg    REQUEST_SIZE_MATCH(xDRI3GetSupportedModifiersReq);
6641b5d61b8Smrg
6651b5d61b8Smrg    swaps(&stuff->length);
6661b5d61b8Smrg    swapl(&stuff->window);
6671b5d61b8Smrg    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
6681b5d61b8Smrg}
6691b5d61b8Smrg
6701b5d61b8Smrgstatic int _X_COLD
6711b5d61b8Smrgsproc_dri3_pixmap_from_buffers(ClientPtr client)
6721b5d61b8Smrg{
6731b5d61b8Smrg    REQUEST(xDRI3PixmapFromBuffersReq);
6741b5d61b8Smrg    REQUEST_SIZE_MATCH(xDRI3PixmapFromBuffersReq);
6751b5d61b8Smrg
6761b5d61b8Smrg    swaps(&stuff->length);
6771b5d61b8Smrg    swapl(&stuff->pixmap);
6781b5d61b8Smrg    swapl(&stuff->window);
6791b5d61b8Smrg    swaps(&stuff->width);
6801b5d61b8Smrg    swaps(&stuff->height);
6811b5d61b8Smrg    swapl(&stuff->stride0);
6821b5d61b8Smrg    swapl(&stuff->offset0);
6831b5d61b8Smrg    swapl(&stuff->stride1);
6841b5d61b8Smrg    swapl(&stuff->offset1);
6851b5d61b8Smrg    swapl(&stuff->stride2);
6861b5d61b8Smrg    swapl(&stuff->offset2);
6871b5d61b8Smrg    swapl(&stuff->stride3);
6881b5d61b8Smrg    swapl(&stuff->offset3);
6891b5d61b8Smrg    swapll(&stuff->modifier);
6901b5d61b8Smrg    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
6911b5d61b8Smrg}
6921b5d61b8Smrg
6931b5d61b8Smrgstatic int _X_COLD
6941b5d61b8Smrgsproc_dri3_buffers_from_pixmap(ClientPtr client)
6951b5d61b8Smrg{
6961b5d61b8Smrg    REQUEST(xDRI3BuffersFromPixmapReq);
6971b5d61b8Smrg    REQUEST_SIZE_MATCH(xDRI3BuffersFromPixmapReq);
6981b5d61b8Smrg
6991b5d61b8Smrg    swaps(&stuff->length);
7001b5d61b8Smrg    swapl(&stuff->pixmap);
7011b5d61b8Smrg    return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
7021b5d61b8Smrg}
7031b5d61b8Smrg
70435c4bbdfSmrgint (*sproc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = {
70535c4bbdfSmrg    sproc_dri3_query_version,           /* 0 */
70635c4bbdfSmrg    sproc_dri3_open,                    /* 1 */
70735c4bbdfSmrg    sproc_dri3_pixmap_from_buffer,      /* 2 */
70835c4bbdfSmrg    sproc_dri3_buffer_from_pixmap,      /* 3 */
70935c4bbdfSmrg    sproc_dri3_fence_from_fd,           /* 4 */
71035c4bbdfSmrg    sproc_dri3_fd_from_fence,           /* 5 */
7111b5d61b8Smrg    sproc_dri3_get_supported_modifiers, /* 6 */
7121b5d61b8Smrg    sproc_dri3_pixmap_from_buffers,     /* 7 */
7131b5d61b8Smrg    sproc_dri3_buffers_from_pixmap,     /* 8 */
71435c4bbdfSmrg};
71535c4bbdfSmrg
7161b5d61b8Smrgint _X_COLD
71735c4bbdfSmrgsproc_dri3_dispatch(ClientPtr client)
71835c4bbdfSmrg{
71935c4bbdfSmrg    REQUEST(xReq);
72035c4bbdfSmrg    if (!client->local)
72135c4bbdfSmrg        return BadMatch;
72235c4bbdfSmrg    if (stuff->data >= DRI3NumberRequests || !sproc_dri3_vector[stuff->data])
72335c4bbdfSmrg        return BadRequest;
72435c4bbdfSmrg    return (*sproc_dri3_vector[stuff->data]) (client);
72535c4bbdfSmrg}
726