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