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#include "dri3_priv.h" 2435c4bbdfSmrg#include <syncsrv.h> 2535c4bbdfSmrg#include <unistd.h> 2635c4bbdfSmrg#include <xace.h> 2735c4bbdfSmrg#include "../Xext/syncsdk.h" 2835c4bbdfSmrg#include <protocol-versions.h> 291b5d61b8Smrg#include <drm_fourcc.h> 301b5d61b8Smrg 311b5d61b8Smrgstatic Bool 321b5d61b8Smrgdri3_screen_can_one_point_two(ScreenPtr screen) 331b5d61b8Smrg{ 341b5d61b8Smrg dri3_screen_priv_ptr dri3 = dri3_screen_priv(screen); 351b5d61b8Smrg 361b5d61b8Smrg if (dri3 && dri3->info && dri3->info->version >= 2 && 371b5d61b8Smrg dri3->info->pixmap_from_fds && dri3->info->fds_from_pixmap && 381b5d61b8Smrg dri3->info->get_formats && dri3->info->get_modifiers && 391b5d61b8Smrg dri3->info->get_drawable_modifiers) 401b5d61b8Smrg return TRUE; 411b5d61b8Smrg 421b5d61b8Smrg return FALSE; 431b5d61b8Smrg} 4435c4bbdfSmrg 4535c4bbdfSmrgstatic int 4635c4bbdfSmrgproc_dri3_query_version(ClientPtr client) 4735c4bbdfSmrg{ 4835c4bbdfSmrg REQUEST(xDRI3QueryVersionReq); 4935c4bbdfSmrg xDRI3QueryVersionReply rep = { 5035c4bbdfSmrg .type = X_Reply, 5135c4bbdfSmrg .sequenceNumber = client->sequence, 5235c4bbdfSmrg .length = 0, 5335c4bbdfSmrg .majorVersion = SERVER_DRI3_MAJOR_VERSION, 5435c4bbdfSmrg .minorVersion = SERVER_DRI3_MINOR_VERSION 5535c4bbdfSmrg }; 5635c4bbdfSmrg 5735c4bbdfSmrg REQUEST_SIZE_MATCH(xDRI3QueryVersionReq); 581b5d61b8Smrg 591b5d61b8Smrg for (int i = 0; i < screenInfo.numScreens; i++) { 601b5d61b8Smrg if (!dri3_screen_can_one_point_two(screenInfo.screens[i])) { 611b5d61b8Smrg rep.minorVersion = 0; 621b5d61b8Smrg break; 631b5d61b8Smrg } 641b5d61b8Smrg } 651b5d61b8Smrg 661b5d61b8Smrg for (int i = 0; i < screenInfo.numGPUScreens; i++) { 671b5d61b8Smrg if (!dri3_screen_can_one_point_two(screenInfo.gpuscreens[i])) { 681b5d61b8Smrg rep.minorVersion = 0; 691b5d61b8Smrg break; 701b5d61b8Smrg } 711b5d61b8Smrg } 721b5d61b8Smrg 731b5d61b8Smrg /* From DRI3 proto: 741b5d61b8Smrg * 751b5d61b8Smrg * The client sends the highest supported version to the server 761b5d61b8Smrg * and the server sends the highest version it supports, but no 771b5d61b8Smrg * higher than the requested version. 781b5d61b8Smrg */ 791b5d61b8Smrg 801b5d61b8Smrg if (rep.majorVersion > stuff->majorVersion || 811b5d61b8Smrg (rep.majorVersion == stuff->majorVersion && 821b5d61b8Smrg rep.minorVersion > stuff->minorVersion)) { 831b5d61b8Smrg rep.majorVersion = stuff->majorVersion; 841b5d61b8Smrg rep.minorVersion = stuff->minorVersion; 851b5d61b8Smrg } 861b5d61b8Smrg 8735c4bbdfSmrg if (client->swapped) { 8835c4bbdfSmrg swaps(&rep.sequenceNumber); 8935c4bbdfSmrg swapl(&rep.length); 9035c4bbdfSmrg swapl(&rep.majorVersion); 9135c4bbdfSmrg swapl(&rep.minorVersion); 9235c4bbdfSmrg } 9335c4bbdfSmrg WriteToClient(client, sizeof(rep), &rep); 9435c4bbdfSmrg return Success; 9535c4bbdfSmrg} 9635c4bbdfSmrg 9735c4bbdfSmrgint 9835c4bbdfSmrgdri3_send_open_reply(ClientPtr client, int fd) 9935c4bbdfSmrg{ 10035c4bbdfSmrg xDRI3OpenReply rep = { 10135c4bbdfSmrg .type = X_Reply, 10235c4bbdfSmrg .nfd = 1, 10335c4bbdfSmrg .sequenceNumber = client->sequence, 10435c4bbdfSmrg .length = 0, 10535c4bbdfSmrg }; 10635c4bbdfSmrg 10735c4bbdfSmrg if (client->swapped) { 10835c4bbdfSmrg swaps(&rep.sequenceNumber); 10935c4bbdfSmrg swapl(&rep.length); 11035c4bbdfSmrg } 11135c4bbdfSmrg 11235c4bbdfSmrg if (WriteFdToClient(client, fd, TRUE) < 0) { 11335c4bbdfSmrg close(fd); 11435c4bbdfSmrg return BadAlloc; 11535c4bbdfSmrg } 11635c4bbdfSmrg 11735c4bbdfSmrg WriteToClient(client, sizeof (rep), &rep); 11835c4bbdfSmrg 11935c4bbdfSmrg return Success; 12035c4bbdfSmrg} 12135c4bbdfSmrg 12235c4bbdfSmrgstatic int 12335c4bbdfSmrgproc_dri3_open(ClientPtr client) 12435c4bbdfSmrg{ 12535c4bbdfSmrg REQUEST(xDRI3OpenReq); 12635c4bbdfSmrg RRProviderPtr provider; 12735c4bbdfSmrg DrawablePtr drawable; 12835c4bbdfSmrg ScreenPtr screen; 12935c4bbdfSmrg int fd; 13035c4bbdfSmrg int status; 13135c4bbdfSmrg 13235c4bbdfSmrg REQUEST_SIZE_MATCH(xDRI3OpenReq); 13335c4bbdfSmrg 134e23ec014Smrg status = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixGetAttrAccess); 13535c4bbdfSmrg if (status != Success) 13635c4bbdfSmrg return status; 13735c4bbdfSmrg 13835c4bbdfSmrg if (stuff->provider == None) 13935c4bbdfSmrg provider = NULL; 14035c4bbdfSmrg else if (!RRProviderType) { 14135c4bbdfSmrg return BadMatch; 14235c4bbdfSmrg } else { 14335c4bbdfSmrg VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); 14435c4bbdfSmrg if (drawable->pScreen != provider->pScreen) 14535c4bbdfSmrg return BadMatch; 14635c4bbdfSmrg } 14735c4bbdfSmrg screen = drawable->pScreen; 14835c4bbdfSmrg 14935c4bbdfSmrg status = dri3_open(client, screen, provider, &fd); 15035c4bbdfSmrg if (status != Success) 15135c4bbdfSmrg return status; 15235c4bbdfSmrg 15335c4bbdfSmrg if (client->ignoreCount == 0) 15435c4bbdfSmrg return dri3_send_open_reply(client, fd); 15535c4bbdfSmrg 15635c4bbdfSmrg return Success; 15735c4bbdfSmrg} 15835c4bbdfSmrg 15935c4bbdfSmrgstatic int 16035c4bbdfSmrgproc_dri3_pixmap_from_buffer(ClientPtr client) 16135c4bbdfSmrg{ 16235c4bbdfSmrg REQUEST(xDRI3PixmapFromBufferReq); 16335c4bbdfSmrg int fd; 16435c4bbdfSmrg DrawablePtr drawable; 16535c4bbdfSmrg PixmapPtr pixmap; 1661b5d61b8Smrg CARD32 stride, offset; 16735c4bbdfSmrg int rc; 16835c4bbdfSmrg 16935c4bbdfSmrg SetReqFds(client, 1); 17035c4bbdfSmrg REQUEST_SIZE_MATCH(xDRI3PixmapFromBufferReq); 17135c4bbdfSmrg LEGAL_NEW_RESOURCE(stuff->pixmap, client); 17235c4bbdfSmrg rc = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess); 17335c4bbdfSmrg if (rc != Success) { 17435c4bbdfSmrg client->errorValue = stuff->drawable; 17535c4bbdfSmrg return rc; 17635c4bbdfSmrg } 17735c4bbdfSmrg 17835c4bbdfSmrg if (!stuff->width || !stuff->height) { 17935c4bbdfSmrg client->errorValue = 0; 18035c4bbdfSmrg return BadValue; 18135c4bbdfSmrg } 18235c4bbdfSmrg 18335c4bbdfSmrg if (stuff->width > 32767 || stuff->height > 32767) 18435c4bbdfSmrg return BadAlloc; 18535c4bbdfSmrg 18635c4bbdfSmrg if (stuff->depth != 1) { 18735c4bbdfSmrg DepthPtr depth = drawable->pScreen->allowedDepths; 18835c4bbdfSmrg int i; 18935c4bbdfSmrg for (i = 0; i < drawable->pScreen->numDepths; i++, depth++) 19035c4bbdfSmrg if (depth->depth == stuff->depth) 19135c4bbdfSmrg break; 19235c4bbdfSmrg if (i == drawable->pScreen->numDepths) { 19335c4bbdfSmrg client->errorValue = stuff->depth; 19435c4bbdfSmrg return BadValue; 19535c4bbdfSmrg } 19635c4bbdfSmrg } 19735c4bbdfSmrg 19835c4bbdfSmrg fd = ReadFdFromClient(client); 19935c4bbdfSmrg if (fd < 0) 20035c4bbdfSmrg return BadValue; 20135c4bbdfSmrg 2021b5d61b8Smrg offset = 0; 2031b5d61b8Smrg stride = stuff->stride; 2041b5d61b8Smrg rc = dri3_pixmap_from_fds(&pixmap, 2051b5d61b8Smrg drawable->pScreen, 1, &fd, 2061b5d61b8Smrg stuff->width, stuff->height, 2071b5d61b8Smrg &stride, &offset, 2081b5d61b8Smrg stuff->depth, stuff->bpp, 2091b5d61b8Smrg DRM_FORMAT_MOD_INVALID); 21035c4bbdfSmrg close (fd); 21135c4bbdfSmrg if (rc != Success) 21235c4bbdfSmrg return rc; 21335c4bbdfSmrg 21435c4bbdfSmrg pixmap->drawable.id = stuff->pixmap; 21535c4bbdfSmrg 21635c4bbdfSmrg /* security creation/labeling check */ 21735c4bbdfSmrg rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP, 21835c4bbdfSmrg pixmap, RT_NONE, NULL, DixCreateAccess); 21935c4bbdfSmrg 22035c4bbdfSmrg if (rc != Success) { 22135c4bbdfSmrg (*drawable->pScreen->DestroyPixmap) (pixmap); 22235c4bbdfSmrg return rc; 22335c4bbdfSmrg } 2241b5d61b8Smrg if (!AddResource(stuff->pixmap, RT_PIXMAP, (void *) pixmap)) 2251b5d61b8Smrg return BadAlloc; 22635c4bbdfSmrg 22735c4bbdfSmrg return Success; 22835c4bbdfSmrg} 22935c4bbdfSmrg 23035c4bbdfSmrgstatic int 23135c4bbdfSmrgproc_dri3_buffer_from_pixmap(ClientPtr client) 23235c4bbdfSmrg{ 23335c4bbdfSmrg REQUEST(xDRI3BufferFromPixmapReq); 23435c4bbdfSmrg xDRI3BufferFromPixmapReply rep = { 23535c4bbdfSmrg .type = X_Reply, 23635c4bbdfSmrg .nfd = 1, 23735c4bbdfSmrg .sequenceNumber = client->sequence, 23835c4bbdfSmrg .length = 0, 23935c4bbdfSmrg }; 24035c4bbdfSmrg int rc; 24135c4bbdfSmrg int fd; 24235c4bbdfSmrg PixmapPtr pixmap; 24335c4bbdfSmrg 24435c4bbdfSmrg REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq); 24535c4bbdfSmrg rc = dixLookupResourceByType((void **) &pixmap, stuff->pixmap, RT_PIXMAP, 24635c4bbdfSmrg client, DixWriteAccess); 24735c4bbdfSmrg if (rc != Success) { 24835c4bbdfSmrg client->errorValue = stuff->pixmap; 24935c4bbdfSmrg return rc; 25035c4bbdfSmrg } 25135c4bbdfSmrg 25235c4bbdfSmrg rep.width = pixmap->drawable.width; 25335c4bbdfSmrg rep.height = pixmap->drawable.height; 25435c4bbdfSmrg rep.depth = pixmap->drawable.depth; 25535c4bbdfSmrg rep.bpp = pixmap->drawable.bitsPerPixel; 25635c4bbdfSmrg 2571b5d61b8Smrg fd = dri3_fd_from_pixmap(pixmap, &rep.stride, &rep.size); 2581b5d61b8Smrg if (fd < 0) 2591b5d61b8Smrg return BadPixmap; 26035c4bbdfSmrg 26135c4bbdfSmrg if (client->swapped) { 26235c4bbdfSmrg swaps(&rep.sequenceNumber); 26335c4bbdfSmrg swapl(&rep.length); 26435c4bbdfSmrg swapl(&rep.size); 26535c4bbdfSmrg swaps(&rep.width); 26635c4bbdfSmrg swaps(&rep.height); 26735c4bbdfSmrg swaps(&rep.stride); 26835c4bbdfSmrg } 26935c4bbdfSmrg if (WriteFdToClient(client, fd, TRUE) < 0) { 27035c4bbdfSmrg close(fd); 27135c4bbdfSmrg return BadAlloc; 27235c4bbdfSmrg } 27335c4bbdfSmrg 27435c4bbdfSmrg WriteToClient(client, sizeof(rep), &rep); 27535c4bbdfSmrg 2761b5d61b8Smrg return Success; 27735c4bbdfSmrg} 27835c4bbdfSmrg 27935c4bbdfSmrgstatic int 28035c4bbdfSmrgproc_dri3_fence_from_fd(ClientPtr client) 28135c4bbdfSmrg{ 28235c4bbdfSmrg REQUEST(xDRI3FenceFromFDReq); 28335c4bbdfSmrg DrawablePtr drawable; 28435c4bbdfSmrg int fd; 28535c4bbdfSmrg int status; 28635c4bbdfSmrg 28735c4bbdfSmrg SetReqFds(client, 1); 28835c4bbdfSmrg REQUEST_SIZE_MATCH(xDRI3FenceFromFDReq); 28935c4bbdfSmrg LEGAL_NEW_RESOURCE(stuff->fence, client); 29035c4bbdfSmrg 29135c4bbdfSmrg status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess); 29235c4bbdfSmrg if (status != Success) 29335c4bbdfSmrg return status; 29435c4bbdfSmrg 29535c4bbdfSmrg fd = ReadFdFromClient(client); 29635c4bbdfSmrg if (fd < 0) 29735c4bbdfSmrg return BadValue; 29835c4bbdfSmrg 29935c4bbdfSmrg status = SyncCreateFenceFromFD(client, drawable, stuff->fence, 30035c4bbdfSmrg fd, stuff->initially_triggered); 30135c4bbdfSmrg 30235c4bbdfSmrg return status; 30335c4bbdfSmrg} 30435c4bbdfSmrg 30535c4bbdfSmrgstatic int 30635c4bbdfSmrgproc_dri3_fd_from_fence(ClientPtr client) 30735c4bbdfSmrg{ 30835c4bbdfSmrg REQUEST(xDRI3FDFromFenceReq); 30935c4bbdfSmrg xDRI3FDFromFenceReply rep = { 31035c4bbdfSmrg .type = X_Reply, 31135c4bbdfSmrg .nfd = 1, 31235c4bbdfSmrg .sequenceNumber = client->sequence, 31335c4bbdfSmrg .length = 0, 31435c4bbdfSmrg }; 31535c4bbdfSmrg DrawablePtr drawable; 31635c4bbdfSmrg int fd; 31735c4bbdfSmrg int status; 31835c4bbdfSmrg SyncFence *fence; 31935c4bbdfSmrg 32035c4bbdfSmrg REQUEST_SIZE_MATCH(xDRI3FDFromFenceReq); 32135c4bbdfSmrg 32235c4bbdfSmrg status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess); 32335c4bbdfSmrg if (status != Success) 32435c4bbdfSmrg return status; 32535c4bbdfSmrg status = SyncVerifyFence(&fence, stuff->fence, client, DixWriteAccess); 32635c4bbdfSmrg if (status != Success) 32735c4bbdfSmrg return status; 32835c4bbdfSmrg 32935c4bbdfSmrg fd = SyncFDFromFence(client, drawable, fence); 33035c4bbdfSmrg if (fd < 0) 33135c4bbdfSmrg return BadMatch; 33235c4bbdfSmrg 33335c4bbdfSmrg if (client->swapped) { 33435c4bbdfSmrg swaps(&rep.sequenceNumber); 33535c4bbdfSmrg swapl(&rep.length); 33635c4bbdfSmrg } 33735c4bbdfSmrg if (WriteFdToClient(client, fd, FALSE) < 0) 33835c4bbdfSmrg return BadAlloc; 33935c4bbdfSmrg 34035c4bbdfSmrg WriteToClient(client, sizeof(rep), &rep); 34135c4bbdfSmrg 3421b5d61b8Smrg return Success; 3431b5d61b8Smrg} 3441b5d61b8Smrg 3451b5d61b8Smrgstatic int 3461b5d61b8Smrgproc_dri3_get_supported_modifiers(ClientPtr client) 3471b5d61b8Smrg{ 3481b5d61b8Smrg REQUEST(xDRI3GetSupportedModifiersReq); 3491b5d61b8Smrg xDRI3GetSupportedModifiersReply rep = { 3501b5d61b8Smrg .type = X_Reply, 3511b5d61b8Smrg .sequenceNumber = client->sequence, 3521b5d61b8Smrg }; 3531b5d61b8Smrg WindowPtr window; 3541b5d61b8Smrg ScreenPtr pScreen; 3551b5d61b8Smrg CARD64 *window_modifiers = NULL; 3561b5d61b8Smrg CARD64 *screen_modifiers = NULL; 3571b5d61b8Smrg CARD32 nwindowmodifiers = 0; 3581b5d61b8Smrg CARD32 nscreenmodifiers = 0; 3591b5d61b8Smrg int status; 3601b5d61b8Smrg int i; 3611b5d61b8Smrg 3621b5d61b8Smrg REQUEST_SIZE_MATCH(xDRI3GetSupportedModifiersReq); 3631b5d61b8Smrg 364e23ec014Smrg status = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess); 3651b5d61b8Smrg if (status != Success) 3661b5d61b8Smrg return status; 3671b5d61b8Smrg pScreen = window->drawable.pScreen; 3681b5d61b8Smrg 3691b5d61b8Smrg dri3_get_supported_modifiers(pScreen, &window->drawable, 3701b5d61b8Smrg stuff->depth, stuff->bpp, 3711b5d61b8Smrg &nwindowmodifiers, &window_modifiers, 3721b5d61b8Smrg &nscreenmodifiers, &screen_modifiers); 3731b5d61b8Smrg 3741b5d61b8Smrg rep.numWindowModifiers = nwindowmodifiers; 3751b5d61b8Smrg rep.numScreenModifiers = nscreenmodifiers; 3761b5d61b8Smrg rep.length = bytes_to_int32(rep.numWindowModifiers * sizeof(CARD64)) + 3771b5d61b8Smrg bytes_to_int32(rep.numScreenModifiers * sizeof(CARD64)); 3781b5d61b8Smrg 3791b5d61b8Smrg if (client->swapped) { 3801b5d61b8Smrg swaps(&rep.sequenceNumber); 3811b5d61b8Smrg swapl(&rep.length); 3821b5d61b8Smrg swapl(&rep.numWindowModifiers); 3831b5d61b8Smrg swapl(&rep.numScreenModifiers); 3841b5d61b8Smrg for (i = 0; i < nwindowmodifiers; i++) 3851b5d61b8Smrg swapll(&window_modifiers[i]); 3861b5d61b8Smrg for (i = 0; i < nscreenmodifiers; i++) 3871b5d61b8Smrg swapll(&screen_modifiers[i]); 3881b5d61b8Smrg } 3891b5d61b8Smrg 3901b5d61b8Smrg WriteToClient(client, sizeof(rep), &rep); 3911b5d61b8Smrg WriteToClient(client, nwindowmodifiers * sizeof(CARD64), window_modifiers); 3921b5d61b8Smrg WriteToClient(client, nscreenmodifiers * sizeof(CARD64), screen_modifiers); 3931b5d61b8Smrg 3941b5d61b8Smrg free(window_modifiers); 3951b5d61b8Smrg free(screen_modifiers); 3961b5d61b8Smrg 3971b5d61b8Smrg return Success; 3981b5d61b8Smrg} 3991b5d61b8Smrg 4001b5d61b8Smrgstatic int 4011b5d61b8Smrgproc_dri3_pixmap_from_buffers(ClientPtr client) 4021b5d61b8Smrg{ 4031b5d61b8Smrg REQUEST(xDRI3PixmapFromBuffersReq); 4041b5d61b8Smrg int fds[4]; 4051b5d61b8Smrg CARD32 strides[4], offsets[4]; 4061b5d61b8Smrg ScreenPtr screen; 4071b5d61b8Smrg WindowPtr window; 4081b5d61b8Smrg PixmapPtr pixmap; 4091b5d61b8Smrg int rc; 4101b5d61b8Smrg int i; 4111b5d61b8Smrg 4121b5d61b8Smrg SetReqFds(client, stuff->num_buffers); 4131b5d61b8Smrg REQUEST_SIZE_MATCH(xDRI3PixmapFromBuffersReq); 4141b5d61b8Smrg LEGAL_NEW_RESOURCE(stuff->pixmap, client); 4151b5d61b8Smrg rc = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess); 4161b5d61b8Smrg if (rc != Success) { 4171b5d61b8Smrg client->errorValue = stuff->window; 4181b5d61b8Smrg return rc; 4191b5d61b8Smrg } 4201b5d61b8Smrg screen = window->drawable.pScreen; 4211b5d61b8Smrg 4221b5d61b8Smrg if (!stuff->width || !stuff->height || !stuff->bpp || !stuff->depth) { 4231b5d61b8Smrg client->errorValue = 0; 4241b5d61b8Smrg return BadValue; 4251b5d61b8Smrg } 4261b5d61b8Smrg 4271b5d61b8Smrg if (stuff->width > 32767 || stuff->height > 32767) 4281b5d61b8Smrg return BadAlloc; 4291b5d61b8Smrg 4301b5d61b8Smrg if (stuff->depth != 1) { 4311b5d61b8Smrg DepthPtr depth = screen->allowedDepths; 4321b5d61b8Smrg int j; 4331b5d61b8Smrg for (j = 0; j < screen->numDepths; j++, depth++) 4341b5d61b8Smrg if (depth->depth == stuff->depth) 4351b5d61b8Smrg break; 4361b5d61b8Smrg if (j == screen->numDepths) { 4371b5d61b8Smrg client->errorValue = stuff->depth; 4381b5d61b8Smrg return BadValue; 4391b5d61b8Smrg } 4401b5d61b8Smrg } 4411b5d61b8Smrg 4421b5d61b8Smrg if (!stuff->num_buffers || stuff->num_buffers > 4) { 4431b5d61b8Smrg client->errorValue = stuff->num_buffers; 4441b5d61b8Smrg return BadValue; 4451b5d61b8Smrg } 4461b5d61b8Smrg 4471b5d61b8Smrg for (i = 0; i < stuff->num_buffers; i++) { 4481b5d61b8Smrg fds[i] = ReadFdFromClient(client); 4491b5d61b8Smrg if (fds[i] < 0) { 4501b5d61b8Smrg while (--i >= 0) 4511b5d61b8Smrg close(fds[i]); 4521b5d61b8Smrg return BadValue; 4531b5d61b8Smrg } 4541b5d61b8Smrg } 4551b5d61b8Smrg 4561b5d61b8Smrg strides[0] = stuff->stride0; 4571b5d61b8Smrg strides[1] = stuff->stride1; 4581b5d61b8Smrg strides[2] = stuff->stride2; 4591b5d61b8Smrg strides[3] = stuff->stride3; 4601b5d61b8Smrg offsets[0] = stuff->offset0; 4611b5d61b8Smrg offsets[1] = stuff->offset1; 4621b5d61b8Smrg offsets[2] = stuff->offset2; 4631b5d61b8Smrg offsets[3] = stuff->offset3; 4641b5d61b8Smrg 4651b5d61b8Smrg rc = dri3_pixmap_from_fds(&pixmap, screen, 4661b5d61b8Smrg stuff->num_buffers, fds, 4671b5d61b8Smrg stuff->width, stuff->height, 4681b5d61b8Smrg strides, offsets, 4691b5d61b8Smrg stuff->depth, stuff->bpp, 4701b5d61b8Smrg stuff->modifier); 4711b5d61b8Smrg 4721b5d61b8Smrg for (i = 0; i < stuff->num_buffers; i++) 4731b5d61b8Smrg close (fds[i]); 4741b5d61b8Smrg 4751b5d61b8Smrg if (rc != Success) 4761b5d61b8Smrg return rc; 4771b5d61b8Smrg 4781b5d61b8Smrg pixmap->drawable.id = stuff->pixmap; 4791b5d61b8Smrg 4801b5d61b8Smrg /* security creation/labeling check */ 4811b5d61b8Smrg rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP, 4821b5d61b8Smrg pixmap, RT_NONE, NULL, DixCreateAccess); 4831b5d61b8Smrg 4841b5d61b8Smrg if (rc != Success) { 4851b5d61b8Smrg (*screen->DestroyPixmap) (pixmap); 4861b5d61b8Smrg return rc; 4871b5d61b8Smrg } 4881b5d61b8Smrg if (!AddResource(stuff->pixmap, RT_PIXMAP, (void *) pixmap)) 4891b5d61b8Smrg return BadAlloc; 4901b5d61b8Smrg 4911b5d61b8Smrg return Success; 4921b5d61b8Smrg} 4931b5d61b8Smrg 4941b5d61b8Smrgstatic int 4951b5d61b8Smrgproc_dri3_buffers_from_pixmap(ClientPtr client) 4961b5d61b8Smrg{ 4971b5d61b8Smrg REQUEST(xDRI3BuffersFromPixmapReq); 4981b5d61b8Smrg xDRI3BuffersFromPixmapReply rep = { 4991b5d61b8Smrg .type = X_Reply, 5001b5d61b8Smrg .sequenceNumber = client->sequence, 5011b5d61b8Smrg }; 5021b5d61b8Smrg int rc; 5031b5d61b8Smrg int fds[4]; 5041b5d61b8Smrg int num_fds; 5051b5d61b8Smrg uint32_t strides[4], offsets[4]; 5061b5d61b8Smrg uint64_t modifier; 5071b5d61b8Smrg int i; 5081b5d61b8Smrg PixmapPtr pixmap; 5091b5d61b8Smrg 5101b5d61b8Smrg REQUEST_SIZE_MATCH(xDRI3BuffersFromPixmapReq); 5111b5d61b8Smrg rc = dixLookupResourceByType((void **) &pixmap, stuff->pixmap, RT_PIXMAP, 5121b5d61b8Smrg client, DixWriteAccess); 5131b5d61b8Smrg if (rc != Success) { 5141b5d61b8Smrg client->errorValue = stuff->pixmap; 5151b5d61b8Smrg return rc; 5161b5d61b8Smrg } 5171b5d61b8Smrg 5181b5d61b8Smrg num_fds = dri3_fds_from_pixmap(pixmap, fds, strides, offsets, &modifier); 5191b5d61b8Smrg if (num_fds == 0) 5201b5d61b8Smrg return BadPixmap; 5211b5d61b8Smrg 5221b5d61b8Smrg rep.nfd = num_fds; 5231b5d61b8Smrg rep.length = bytes_to_int32(num_fds * 2 * sizeof(CARD32)); 5241b5d61b8Smrg rep.width = pixmap->drawable.width; 5251b5d61b8Smrg rep.height = pixmap->drawable.height; 5261b5d61b8Smrg rep.depth = pixmap->drawable.depth; 5271b5d61b8Smrg rep.bpp = pixmap->drawable.bitsPerPixel; 5281b5d61b8Smrg rep.modifier = modifier; 5291b5d61b8Smrg 5301b5d61b8Smrg if (client->swapped) { 5311b5d61b8Smrg swaps(&rep.sequenceNumber); 5321b5d61b8Smrg swapl(&rep.length); 5331b5d61b8Smrg swaps(&rep.width); 5341b5d61b8Smrg swaps(&rep.height); 5351b5d61b8Smrg swapll(&rep.modifier); 5361b5d61b8Smrg for (i = 0; i < num_fds; i++) { 5371b5d61b8Smrg swapl(&strides[i]); 5381b5d61b8Smrg swapl(&offsets[i]); 5391b5d61b8Smrg } 5401b5d61b8Smrg } 5411b5d61b8Smrg 5421b5d61b8Smrg for (i = 0; i < num_fds; i++) { 5431b5d61b8Smrg if (WriteFdToClient(client, fds[i], TRUE) < 0) { 5441b5d61b8Smrg while (i--) 5451b5d61b8Smrg close(fds[i]); 5461b5d61b8Smrg return BadAlloc; 5471b5d61b8Smrg } 5481b5d61b8Smrg } 5491b5d61b8Smrg 5501b5d61b8Smrg WriteToClient(client, sizeof(rep), &rep); 5511b5d61b8Smrg WriteToClient(client, num_fds * sizeof(CARD32), strides); 5521b5d61b8Smrg WriteToClient(client, num_fds * sizeof(CARD32), offsets); 5531b5d61b8Smrg 5541b5d61b8Smrg return Success; 55535c4bbdfSmrg} 55635c4bbdfSmrg 55735c4bbdfSmrgint (*proc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = { 55835c4bbdfSmrg proc_dri3_query_version, /* 0 */ 55935c4bbdfSmrg proc_dri3_open, /* 1 */ 56035c4bbdfSmrg proc_dri3_pixmap_from_buffer, /* 2 */ 56135c4bbdfSmrg proc_dri3_buffer_from_pixmap, /* 3 */ 56235c4bbdfSmrg proc_dri3_fence_from_fd, /* 4 */ 56335c4bbdfSmrg proc_dri3_fd_from_fence, /* 5 */ 5641b5d61b8Smrg proc_dri3_get_supported_modifiers, /* 6 */ 5651b5d61b8Smrg proc_dri3_pixmap_from_buffers, /* 7 */ 5661b5d61b8Smrg proc_dri3_buffers_from_pixmap, /* 8 */ 56735c4bbdfSmrg}; 56835c4bbdfSmrg 56935c4bbdfSmrgint 57035c4bbdfSmrgproc_dri3_dispatch(ClientPtr client) 57135c4bbdfSmrg{ 57235c4bbdfSmrg REQUEST(xReq); 57335c4bbdfSmrg if (!client->local) 57435c4bbdfSmrg return BadMatch; 57535c4bbdfSmrg if (stuff->data >= DRI3NumberRequests || !proc_dri3_vector[stuff->data]) 57635c4bbdfSmrg return BadRequest; 57735c4bbdfSmrg return (*proc_dri3_vector[stuff->data]) (client); 57835c4bbdfSmrg} 57935c4bbdfSmrg 5801b5d61b8Smrgstatic int _X_COLD 58135c4bbdfSmrgsproc_dri3_query_version(ClientPtr client) 58235c4bbdfSmrg{ 58335c4bbdfSmrg REQUEST(xDRI3QueryVersionReq); 58435c4bbdfSmrg REQUEST_SIZE_MATCH(xDRI3QueryVersionReq); 58535c4bbdfSmrg 58635c4bbdfSmrg swaps(&stuff->length); 58735c4bbdfSmrg swapl(&stuff->majorVersion); 58835c4bbdfSmrg swapl(&stuff->minorVersion); 58935c4bbdfSmrg return (*proc_dri3_vector[stuff->dri3ReqType]) (client); 59035c4bbdfSmrg} 59135c4bbdfSmrg 5921b5d61b8Smrgstatic int _X_COLD 59335c4bbdfSmrgsproc_dri3_open(ClientPtr client) 59435c4bbdfSmrg{ 59535c4bbdfSmrg REQUEST(xDRI3OpenReq); 59635c4bbdfSmrg REQUEST_SIZE_MATCH(xDRI3OpenReq); 59735c4bbdfSmrg 59835c4bbdfSmrg swaps(&stuff->length); 59935c4bbdfSmrg swapl(&stuff->drawable); 60035c4bbdfSmrg swapl(&stuff->provider); 60135c4bbdfSmrg return (*proc_dri3_vector[stuff->dri3ReqType]) (client); 60235c4bbdfSmrg} 60335c4bbdfSmrg 6041b5d61b8Smrgstatic int _X_COLD 60535c4bbdfSmrgsproc_dri3_pixmap_from_buffer(ClientPtr client) 60635c4bbdfSmrg{ 60735c4bbdfSmrg REQUEST(xDRI3PixmapFromBufferReq); 60835c4bbdfSmrg REQUEST_SIZE_MATCH(xDRI3PixmapFromBufferReq); 60935c4bbdfSmrg 61035c4bbdfSmrg swaps(&stuff->length); 61135c4bbdfSmrg swapl(&stuff->pixmap); 61235c4bbdfSmrg swapl(&stuff->drawable); 61335c4bbdfSmrg swapl(&stuff->size); 61435c4bbdfSmrg swaps(&stuff->width); 61535c4bbdfSmrg swaps(&stuff->height); 61635c4bbdfSmrg swaps(&stuff->stride); 61735c4bbdfSmrg return (*proc_dri3_vector[stuff->dri3ReqType]) (client); 61835c4bbdfSmrg} 61935c4bbdfSmrg 6201b5d61b8Smrgstatic int _X_COLD 62135c4bbdfSmrgsproc_dri3_buffer_from_pixmap(ClientPtr client) 62235c4bbdfSmrg{ 62335c4bbdfSmrg REQUEST(xDRI3BufferFromPixmapReq); 62435c4bbdfSmrg REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq); 62535c4bbdfSmrg 62635c4bbdfSmrg swaps(&stuff->length); 62735c4bbdfSmrg swapl(&stuff->pixmap); 62835c4bbdfSmrg return (*proc_dri3_vector[stuff->dri3ReqType]) (client); 62935c4bbdfSmrg} 63035c4bbdfSmrg 6311b5d61b8Smrgstatic int _X_COLD 63235c4bbdfSmrgsproc_dri3_fence_from_fd(ClientPtr client) 63335c4bbdfSmrg{ 63435c4bbdfSmrg REQUEST(xDRI3FenceFromFDReq); 63535c4bbdfSmrg REQUEST_SIZE_MATCH(xDRI3FenceFromFDReq); 63635c4bbdfSmrg 63735c4bbdfSmrg swaps(&stuff->length); 63835c4bbdfSmrg swapl(&stuff->drawable); 63935c4bbdfSmrg swapl(&stuff->fence); 64035c4bbdfSmrg return (*proc_dri3_vector[stuff->dri3ReqType]) (client); 64135c4bbdfSmrg} 64235c4bbdfSmrg 6431b5d61b8Smrgstatic int _X_COLD 64435c4bbdfSmrgsproc_dri3_fd_from_fence(ClientPtr client) 64535c4bbdfSmrg{ 64635c4bbdfSmrg REQUEST(xDRI3FDFromFenceReq); 64735c4bbdfSmrg REQUEST_SIZE_MATCH(xDRI3FDFromFenceReq); 64835c4bbdfSmrg 64935c4bbdfSmrg swaps(&stuff->length); 65035c4bbdfSmrg swapl(&stuff->drawable); 65135c4bbdfSmrg swapl(&stuff->fence); 65235c4bbdfSmrg return (*proc_dri3_vector[stuff->dri3ReqType]) (client); 65335c4bbdfSmrg} 65435c4bbdfSmrg 6551b5d61b8Smrgstatic int _X_COLD 6561b5d61b8Smrgsproc_dri3_get_supported_modifiers(ClientPtr client) 6571b5d61b8Smrg{ 6581b5d61b8Smrg REQUEST(xDRI3GetSupportedModifiersReq); 6591b5d61b8Smrg REQUEST_SIZE_MATCH(xDRI3GetSupportedModifiersReq); 6601b5d61b8Smrg 6611b5d61b8Smrg swaps(&stuff->length); 6621b5d61b8Smrg swapl(&stuff->window); 6631b5d61b8Smrg return (*proc_dri3_vector[stuff->dri3ReqType]) (client); 6641b5d61b8Smrg} 6651b5d61b8Smrg 6661b5d61b8Smrgstatic int _X_COLD 6671b5d61b8Smrgsproc_dri3_pixmap_from_buffers(ClientPtr client) 6681b5d61b8Smrg{ 6691b5d61b8Smrg REQUEST(xDRI3PixmapFromBuffersReq); 6701b5d61b8Smrg REQUEST_SIZE_MATCH(xDRI3PixmapFromBuffersReq); 6711b5d61b8Smrg 6721b5d61b8Smrg swaps(&stuff->length); 6731b5d61b8Smrg swapl(&stuff->pixmap); 6741b5d61b8Smrg swapl(&stuff->window); 6751b5d61b8Smrg swaps(&stuff->width); 6761b5d61b8Smrg swaps(&stuff->height); 6771b5d61b8Smrg swapl(&stuff->stride0); 6781b5d61b8Smrg swapl(&stuff->offset0); 6791b5d61b8Smrg swapl(&stuff->stride1); 6801b5d61b8Smrg swapl(&stuff->offset1); 6811b5d61b8Smrg swapl(&stuff->stride2); 6821b5d61b8Smrg swapl(&stuff->offset2); 6831b5d61b8Smrg swapl(&stuff->stride3); 6841b5d61b8Smrg swapl(&stuff->offset3); 6851b5d61b8Smrg swapll(&stuff->modifier); 6861b5d61b8Smrg return (*proc_dri3_vector[stuff->dri3ReqType]) (client); 6871b5d61b8Smrg} 6881b5d61b8Smrg 6891b5d61b8Smrgstatic int _X_COLD 6901b5d61b8Smrgsproc_dri3_buffers_from_pixmap(ClientPtr client) 6911b5d61b8Smrg{ 6921b5d61b8Smrg REQUEST(xDRI3BuffersFromPixmapReq); 6931b5d61b8Smrg REQUEST_SIZE_MATCH(xDRI3BuffersFromPixmapReq); 6941b5d61b8Smrg 6951b5d61b8Smrg swaps(&stuff->length); 6961b5d61b8Smrg swapl(&stuff->pixmap); 6971b5d61b8Smrg return (*proc_dri3_vector[stuff->dri3ReqType]) (client); 6981b5d61b8Smrg} 6991b5d61b8Smrg 70035c4bbdfSmrgint (*sproc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = { 70135c4bbdfSmrg sproc_dri3_query_version, /* 0 */ 70235c4bbdfSmrg sproc_dri3_open, /* 1 */ 70335c4bbdfSmrg sproc_dri3_pixmap_from_buffer, /* 2 */ 70435c4bbdfSmrg sproc_dri3_buffer_from_pixmap, /* 3 */ 70535c4bbdfSmrg sproc_dri3_fence_from_fd, /* 4 */ 70635c4bbdfSmrg sproc_dri3_fd_from_fence, /* 5 */ 7071b5d61b8Smrg sproc_dri3_get_supported_modifiers, /* 6 */ 7081b5d61b8Smrg sproc_dri3_pixmap_from_buffers, /* 7 */ 7091b5d61b8Smrg sproc_dri3_buffers_from_pixmap, /* 8 */ 71035c4bbdfSmrg}; 71135c4bbdfSmrg 7121b5d61b8Smrgint _X_COLD 71335c4bbdfSmrgsproc_dri3_dispatch(ClientPtr client) 71435c4bbdfSmrg{ 71535c4bbdfSmrg REQUEST(xReq); 71635c4bbdfSmrg if (!client->local) 71735c4bbdfSmrg return BadMatch; 71835c4bbdfSmrg if (stuff->data >= DRI3NumberRequests || !sproc_dri3_vector[stuff->data]) 71935c4bbdfSmrg return BadRequest; 72035c4bbdfSmrg return (*sproc_dri3_vector[stuff->data]) (client); 72135c4bbdfSmrg} 722