diff options
Diffstat (limited to 'xorg-server/hw/xfree86/common/xf86DGA.c')
-rw-r--r-- | xorg-server/hw/xfree86/common/xf86DGA.c | 1160 |
1 files changed, 1092 insertions, 68 deletions
diff --git a/xorg-server/hw/xfree86/common/xf86DGA.c b/xorg-server/hw/xfree86/common/xf86DGA.c index 64163721f..a441dee99 100644 --- a/xorg-server/hw/xfree86/common/xf86DGA.c +++ b/xorg-server/hw/xfree86/common/xf86DGA.c @@ -1,4 +1,6 @@ /* + * Copyright (c) 1995 Jon Tombs + * Copyright (c) 1995, 1996, 1999 XFree86 Inc * Copyright (c) 1998-2002 by The XFree86 Project, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -27,10 +29,20 @@ * Written by Mark Vojkovich */ +/* + * This is quite literally just two files glued together: + * hw/xfree86/common/xf86DGA.c is the first part, and + * hw/xfree86/dixmods/extmod/xf86dga2.c is the second part. One day, if + * someone actually cares about DGA, it'd be nice to clean this up. But trust + * me, I am not that person. + */ + #ifdef HAVE_XORG_CONFIG_H #include <xorg-config.h> #endif +#include <X11/X.h> +#include <X11/Xproto.h> #include "xf86.h" #include "xf86str.h" #include "xf86Priv.h" @@ -48,9 +60,24 @@ #include "exevents.h" #include "eventstr.h" #include "eventconvert.h" +#include "xf86Extensions.h" #include "mi.h" +#include "misc.h" +#include "dixstruct.h" +#include "dixevents.h" +#include "extnsionst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "swaprep.h" +#include "dgaproc.h" +#include "protocol-versions.h" + +#include <string.h> + +#define DGA_PROTOCOL_OLD_SUPPORT 1 + static DevPrivateKeyRec DGAScreenKeyRec; #define DGAScreenKeyRegistered dixPrivateKeyRegistered(&DGAScreenKeyRec) @@ -66,7 +93,9 @@ static void DGAHandleEvent(int screen_num, InternalEvent *event, static void DGACopyModeInfo(DGAModePtr mode, XDGAModePtr xmode); -int *XDGAEventBase = NULL; +static unsigned char DGAReqCode = 0; +static int DGAErrorBase; +static int DGAEventBase; #define DGA_GET_SCREEN_PRIV(pScreen) ((DGAScreenPtr) \ dixLookupPrivate(&(pScreen)->devPrivates, &DGAScreenKeyRec)) @@ -521,18 +550,27 @@ DGAChangePixmapMode(int index, int *x, int *y, int mode) } Bool -DGAAvailable(int index) +DGAScreenAvailable(ScreenPtr pScreen) { if (!DGAScreenKeyRegistered) return FALSE; - if (DGA_GET_SCREEN_PRIV(screenInfo.screens[index])) + if (DGA_GET_SCREEN_PRIV(pScreen)) return TRUE; - return FALSE; } Bool +DGAAvailable(int index) +{ + ScreenPtr pScreen; + + assert(index < MAXSCREENS); + pScreen = screenInfo.screens[index]; + return DGAScreenAvailable(pScreen); +} + +Bool DGAActive(int index) { DGAScreenPtr pScreenPriv; @@ -891,15 +929,16 @@ DGAStealKeyEvent(DeviceIntPtr dev, int index, int key_code, int is_down) if (!pScreenPriv || !pScreenPriv->grabKeyboard) /* no direct mode */ return FALSE; - memset(&event, 0, sizeof(event)); - event.header = ET_Internal; - event.type = ET_DGAEvent; - event.length = sizeof(event); - event.time = GetTimeInMillis(); - event.subtype = (is_down ? ET_KeyPress : ET_KeyRelease); - event.detail = key_code; - event.dx = 0; - event.dy = 0; + event = (DGAEvent) { + .header = ET_Internal, + .type = ET_DGAEvent, + .length = sizeof(event), + .time = GetTimeInMillis(), + .subtype = (is_down ? ET_KeyPress : ET_KeyRelease), + .detail = key_code, + .dx = 0, + .dy = 0 + }; mieqEnqueue(dev, (InternalEvent *) &event); return TRUE; @@ -919,15 +958,16 @@ DGAStealMotionEvent(DeviceIntPtr dev, int index, int dx, int dy) if (!pScreenPriv || !pScreenPriv->grabMouse) /* no direct mode */ return FALSE; - memset(&event, 0, sizeof(event)); - event.header = ET_Internal; - event.type = ET_DGAEvent; - event.length = sizeof(event); - event.time = GetTimeInMillis(); - event.subtype = ET_Motion; - event.detail = 0; - event.dx = dx; - event.dy = dy; + event = (DGAEvent) { + .header = ET_Internal, + .type = ET_DGAEvent, + .length = sizeof(event), + .time = GetTimeInMillis(), + .subtype = ET_Motion, + .detail = 0, + .dx = dx, + .dy = dy + }; mieqEnqueue(dev, (InternalEvent *) &event); return TRUE; } @@ -946,15 +986,16 @@ DGAStealButtonEvent(DeviceIntPtr dev, int index, int button, int is_down) if (!pScreenPriv || !pScreenPriv->grabMouse) return FALSE; - memset(&event, 0, sizeof(event)); - event.header = ET_Internal; - event.type = ET_DGAEvent; - event.length = sizeof(event); - event.time = GetTimeInMillis(); - event.subtype = (is_down ? ET_ButtonPress : ET_ButtonRelease); - event.detail = button; - event.dx = 0; - event.dy = 0; + event = (DGAEvent) { + .header = ET_Internal, + .type = ET_DGAEvent, + .length = sizeof(event), + .time = GetTimeInMillis(), + .subtype = (is_down ? ET_ButtonPress : ET_ButtonRelease), + .detail = button, + .dx = 0, + .dy = 0 + }; mieqEnqueue(dev, (InternalEvent *) &event); return TRUE; @@ -979,16 +1020,15 @@ DGAProcessKeyboardEvent(ScreenPtr pScreen, DGAEvent * event, DeviceIntPtr keybd) KeyClassPtr keyc = keybd->key; DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); DeviceIntPtr pointer = GetMaster(keybd, POINTER_OR_FLOAT); - DeviceEvent ev; - - memset(&ev, 0, sizeof(ev)); - ev.header = ET_Internal; - ev.length = sizeof(ev); - ev.detail.key = event->detail; - ev.type = event->subtype; - ev.root_x = 0; - ev.root_y = 0; - ev.corestate = XkbStateFieldFromRec(&keyc->xkbInfo->state); + DeviceEvent ev = { + .header = ET_Internal, + .length = sizeof(ev), + .detail.key = event->detail, + .type = event->subtype, + .root_x = 0, + .root_y = 0, + .corestate = XkbStateFieldFromRec(&keyc->xkbInfo->state) + }; ev.corestate |= pointer->button->state; UpdateDeviceState(keybd, &ev); @@ -997,15 +1037,15 @@ DGAProcessKeyboardEvent(ScreenPtr pScreen, DGAEvent * event, DeviceIntPtr keybd) * Deliver the DGA event */ if (pScreenPriv->client) { - dgaEvent de; - - de.u.u.type = *XDGAEventBase + GetCoreType(ev.type); + dgaEvent de = { + .u.event.time = event->time, + .u.event.dx = event->dx, + .u.event.dy = event->dy, + .u.event.screen = pScreen->myNum, + .u.event.state = ev.corestate + }; + de.u.u.type = DGAEventBase + GetCoreType(ev.type); de.u.u.detail = event->detail; - de.u.event.time = event->time; - de.u.event.dx = event->dx; - de.u.event.dy = event->dy; - de.u.event.screen = pScreen->myNum; - de.u.event.state = ev.corestate; /* If the DGA client has selected input, then deliver based on the usual filter */ TryClientEvents(pScreenPriv->client, keybd, (xEvent *) &de, 1, @@ -1030,14 +1070,14 @@ DGAProcessPointerEvent(ScreenPtr pScreen, DGAEvent * event, DeviceIntPtr mouse) { ButtonClassPtr butc = mouse->button; DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); - DeviceEvent ev; DeviceIntPtr master = GetMaster(mouse, MASTER_KEYBOARD); + DeviceEvent ev = { + .header = ET_Internal, + .length = sizeof(ev), + .type = event->subtype, + .corestate = butc ? butc->state : 0 + }; - memset(&ev, 0, sizeof(ev)); - ev.header = ET_Internal; - ev.length = sizeof(ev); - ev.type = event->subtype; - ev.corestate = butc ? butc->state : 0; if (master && master->key) ev.corestate |= XkbStateFieldFromRec(&master->key->xkbInfo->state); @@ -1047,18 +1087,16 @@ DGAProcessPointerEvent(ScreenPtr pScreen, DGAEvent * event, DeviceIntPtr mouse) * Deliver the DGA event */ if (pScreenPriv->client) { - dgaEvent de; - int coreEquiv; - - coreEquiv = GetCoreType(ev.type); - - de.u.u.type = *XDGAEventBase + coreEquiv; + int coreEquiv = GetCoreType(ev.type); + dgaEvent de = { + .u.event.time = event->time, + .u.event.dx = event->dx, + .u.event.dy = event->dy, + .u.event.screen = pScreen->myNum, + .u.event.state = ev.corestate + }; + de.u.u.type = DGAEventBase + coreEquiv; de.u.u.detail = event->detail; - de.u.event.time = event->time; - de.u.event.dx = event->dx; - de.u.event.dy = event->dy; - de.u.event.screen = pScreen->myNum; - de.u.event.state = ev.corestate; /* If the DGA client has selected input, then deliver based on the usual filter */ TryClientEvents(pScreenPriv->client, mouse, (xEvent *) &de, 1, @@ -1144,8 +1182,8 @@ DGAHandleEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device) DGAScreenPtr pScreenPriv; /* no DGA */ - if (!DGAScreenKeyRegistered || XDGAEventBase == 0) - return; + if (!DGAScreenKeyRegistered || noXFree86DGAExtension) + return; pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); /* DGA not initialized on this screen */ @@ -1169,3 +1207,989 @@ DGAHandleEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device) break; } } + +static void XDGAResetProc(ExtensionEntry * extEntry); + +static void DGAClientStateChange(CallbackListPtr *, pointer, pointer); + +static DevPrivateKeyRec DGAScreenPrivateKeyRec; + +#define DGAScreenPrivateKey (&DGAScreenPrivateKeyRec) +#define DGAScreenPrivateKeyRegistered (DGAScreenPrivateKeyRec.initialized) +static DevPrivateKeyRec DGAClientPrivateKeyRec; + +#define DGAClientPrivateKey (&DGAClientPrivateKeyRec) +static int DGACallbackRefCount = 0; + +/* This holds the client's version information */ +typedef struct { + int major; + int minor; +} DGAPrivRec, *DGAPrivPtr; + +#define DGA_GETCLIENT(idx) ((ClientPtr) \ + dixLookupPrivate(&screenInfo.screens[idx]->devPrivates, DGAScreenPrivateKey)) +#define DGA_SETCLIENT(idx,p) \ + dixSetPrivate(&screenInfo.screens[idx]->devPrivates, DGAScreenPrivateKey, p) + +#define DGA_GETPRIV(c) ((DGAPrivPtr) \ + dixLookupPrivate(&(c)->devPrivates, DGAClientPrivateKey)) +#define DGA_SETPRIV(c,p) \ + dixSetPrivate(&(c)->devPrivates, DGAClientPrivateKey, p) + +static void +XDGAResetProc(ExtensionEntry * extEntry) +{ + DeleteCallback(&ClientStateCallback, DGAClientStateChange, NULL); + DGACallbackRefCount = 0; +} + +static int +ProcXDGAQueryVersion(ClientPtr client) +{ + xXDGAQueryVersionReply rep; + + REQUEST_SIZE_MATCH(xXDGAQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SERVER_XDGA_MAJOR_VERSION; + rep.minorVersion = SERVER_XDGA_MINOR_VERSION; + + WriteToClient(client, sizeof(xXDGAQueryVersionReply), (char *) &rep); + return Success; +} + +static int +ProcXDGAOpenFramebuffer(ClientPtr client) +{ + REQUEST(xXDGAOpenFramebufferReq); + xXDGAOpenFramebufferReply rep; + char *deviceName; + int nameSize; + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (!DGAAvailable(stuff->screen)) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + REQUEST_SIZE_MATCH(xXDGAOpenFramebufferReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!DGAOpenFramebuffer(stuff->screen, &deviceName, + (unsigned char **) (&rep.mem1), + (int *) &rep.size, (int *) &rep.offset, + (int *) &rep.extra)) { + return BadAlloc; + } + + nameSize = deviceName ? (strlen(deviceName) + 1) : 0; + rep.length = bytes_to_int32(nameSize); + + WriteToClient(client, sizeof(xXDGAOpenFramebufferReply), (char *) &rep); + if (rep.length) + WriteToClient(client, nameSize, deviceName); + + return Success; +} + +static int +ProcXDGACloseFramebuffer(ClientPtr client) +{ + REQUEST(xXDGACloseFramebufferReq); + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (!DGAAvailable(stuff->screen)) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + REQUEST_SIZE_MATCH(xXDGACloseFramebufferReq); + + DGACloseFramebuffer(stuff->screen); + + return Success; +} + +static int +ProcXDGAQueryModes(ClientPtr client) +{ + int i, num, size; + + REQUEST(xXDGAQueryModesReq); + xXDGAQueryModesReply rep; + xXDGAModeInfo info; + XDGAModePtr mode; + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXDGAQueryModesReq); + rep.type = X_Reply; + rep.length = 0; + rep.number = 0; + rep.sequenceNumber = client->sequence; + + if (!DGAAvailable(stuff->screen)) { + rep.number = 0; + rep.length = 0; + WriteToClient(client, sz_xXDGAQueryModesReply, (char *) &rep); + return Success; + } + + if (!(num = DGAGetModes(stuff->screen))) { + WriteToClient(client, sz_xXDGAQueryModesReply, (char *) &rep); + return Success; + } + + if (!(mode = (XDGAModePtr) malloc(num * sizeof(XDGAModeRec)))) + return BadAlloc; + + for (i = 0; i < num; i++) + DGAGetModeInfo(stuff->screen, mode + i, i + 1); + + size = num * sz_xXDGAModeInfo; + for (i = 0; i < num; i++) + size += pad_to_int32(strlen(mode[i].name) + 1); /* plus NULL */ + + rep.number = num; + rep.length = bytes_to_int32(size); + + WriteToClient(client, sz_xXDGAQueryModesReply, (char *) &rep); + + for (i = 0; i < num; i++) { + size = strlen(mode[i].name) + 1; + + info.byte_order = mode[i].byteOrder; + info.depth = mode[i].depth; + info.num = mode[i].num; + info.bpp = mode[i].bitsPerPixel; + info.name_size = (size + 3) & ~3L; + info.vsync_num = mode[i].VSync_num; + info.vsync_den = mode[i].VSync_den; + info.flags = mode[i].flags; + info.image_width = mode[i].imageWidth; + info.image_height = mode[i].imageHeight; + info.pixmap_width = mode[i].pixmapWidth; + info.pixmap_height = mode[i].pixmapHeight; + info.bytes_per_scanline = mode[i].bytesPerScanline; + info.red_mask = mode[i].red_mask; + info.green_mask = mode[i].green_mask; + info.blue_mask = mode[i].blue_mask; + info.visual_class = mode[i].visualClass; + info.viewport_width = mode[i].viewportWidth; + info.viewport_height = mode[i].viewportHeight; + info.viewport_xstep = mode[i].xViewportStep; + info.viewport_ystep = mode[i].yViewportStep; + info.viewport_xmax = mode[i].maxViewportX; + info.viewport_ymax = mode[i].maxViewportY; + info.viewport_flags = mode[i].viewportFlags; + info.reserved1 = mode[i].reserved1; + info.reserved2 = mode[i].reserved2; + + WriteToClient(client, sz_xXDGAModeInfo, (char *) (&info)); + WriteToClient(client, size, mode[i].name); + } + + free(mode); + + return Success; +} + +static void +DGAClientStateChange(CallbackListPtr *pcbl, pointer nulldata, pointer calldata) +{ + NewClientInfoRec *pci = (NewClientInfoRec *) calldata; + ClientPtr client = NULL; + int i; + + for (i = 0; i < screenInfo.numScreens; i++) { + if (DGA_GETCLIENT(i) == pci->client) { + client = pci->client; + break; + } + } + + if (client && + ((client->clientState == ClientStateGone) || + (client->clientState == ClientStateRetained))) { + XDGAModeRec mode; + PixmapPtr pPix; + + DGA_SETCLIENT(i, NULL); + DGASelectInput(i, NULL, 0); + DGASetMode(i, 0, &mode, &pPix); + + if (--DGACallbackRefCount == 0) + DeleteCallback(&ClientStateCallback, DGAClientStateChange, NULL); + } +} + +static int +ProcXDGASetMode(ClientPtr client) +{ + REQUEST(xXDGASetModeReq); + xXDGASetModeReply rep; + XDGAModeRec mode; + xXDGAModeInfo info; + PixmapPtr pPix; + ClientPtr owner; + int size; + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + owner = DGA_GETCLIENT(stuff->screen); + + REQUEST_SIZE_MATCH(xXDGASetModeReq); + rep.type = X_Reply; + rep.length = 0; + rep.offset = 0; + rep.flags = 0; + rep.sequenceNumber = client->sequence; + + if (!DGAAvailable(stuff->screen)) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + if (owner && owner != client) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + if (!stuff->mode) { + if (owner) { + if (--DGACallbackRefCount == 0) + DeleteCallback(&ClientStateCallback, DGAClientStateChange, + NULL); + } + DGA_SETCLIENT(stuff->screen, NULL); + DGASelectInput(stuff->screen, NULL, 0); + DGASetMode(stuff->screen, 0, &mode, &pPix); + WriteToClient(client, sz_xXDGASetModeReply, (char *) &rep); + return Success; + } + + if (Success != DGASetMode(stuff->screen, stuff->mode, &mode, &pPix)) + return BadValue; + + if (!owner) { + if (DGACallbackRefCount++ == 0) + AddCallback(&ClientStateCallback, DGAClientStateChange, NULL); + } + + DGA_SETCLIENT(stuff->screen, client); + + if (pPix) { + if (AddResource(stuff->pid, RT_PIXMAP, (pointer) (pPix))) { + pPix->drawable.id = (int) stuff->pid; + rep.flags = DGA_PIXMAP_AVAILABLE; + } + } + + size = strlen(mode.name) + 1; + + info.byte_order = mode.byteOrder; + info.depth = mode.depth; + info.num = mode.num; + info.bpp = mode.bitsPerPixel; + info.name_size = (size + 3) & ~3L; + info.vsync_num = mode.VSync_num; + info.vsync_den = mode.VSync_den; + info.flags = mode.flags; + info.image_width = mode.imageWidth; + info.image_height = mode.imageHeight; + info.pixmap_width = mode.pixmapWidth; + info.pixmap_height = mode.pixmapHeight; + info.bytes_per_scanline = mode.bytesPerScanline; + info.red_mask = mode.red_mask; + info.green_mask = mode.green_mask; + info.blue_mask = mode.blue_mask; + info.visual_class = mode.visualClass; + info.viewport_width = mode.viewportWidth; + info.viewport_height = mode.viewportHeight; + info.viewport_xstep = mode.xViewportStep; + info.viewport_ystep = mode.yViewportStep; + info.viewport_xmax = mode.maxViewportX; + info.viewport_ymax = mode.maxViewportY; + info.viewport_flags = mode.viewportFlags; + info.reserved1 = mode.reserved1; + info.reserved2 = mode.reserved2; + + rep.length = bytes_to_int32(sz_xXDGAModeInfo + info.name_size); + + WriteToClient(client, sz_xXDGASetModeReply, (char *) &rep); + WriteToClient(client, sz_xXDGAModeInfo, (char *) (&info)); + WriteToClient(client, size, mode.name); + + return Success; +} + +static int +ProcXDGASetViewport(ClientPtr client) +{ + REQUEST(xXDGASetViewportReq); + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGASetViewportReq); + + DGASetViewport(stuff->screen, stuff->x, stuff->y, stuff->flags); + + return Success; +} + +static int +ProcXDGAInstallColormap(ClientPtr client) +{ + ColormapPtr cmap; + int rc; + + REQUEST(xXDGAInstallColormapReq); + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGAInstallColormapReq); + + rc = dixLookupResourceByType((pointer *) &cmap, stuff->cmap, RT_COLORMAP, + client, DixInstallAccess); + if (rc != Success) + return rc; + DGAInstallCmap(cmap); + return Success; +} + +static int +ProcXDGASelectInput(ClientPtr client) +{ + REQUEST(xXDGASelectInputReq); + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGASelectInputReq); + + if (DGA_GETCLIENT(stuff->screen) == client) + DGASelectInput(stuff->screen, client, stuff->mask); + + return Success; +} + +static int +ProcXDGAFillRectangle(ClientPtr client) +{ + REQUEST(xXDGAFillRectangleReq); + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGAFillRectangleReq); + + if (Success != DGAFillRect(stuff->screen, stuff->x, stuff->y, + stuff->width, stuff->height, stuff->color)) + return BadMatch; + + return Success; +} + +static int +ProcXDGACopyArea(ClientPtr client) +{ + REQUEST(xXDGACopyAreaReq); + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGACopyAreaReq); + + if (Success != DGABlitRect(stuff->screen, stuff->srcx, stuff->srcy, + stuff->width, stuff->height, stuff->dstx, + stuff->dsty)) + return BadMatch; + + return Success; +} + +static int +ProcXDGACopyTransparentArea(ClientPtr client) +{ + REQUEST(xXDGACopyTransparentAreaReq); + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGACopyTransparentAreaReq); + + if (Success != DGABlitTransRect(stuff->screen, stuff->srcx, stuff->srcy, + stuff->width, stuff->height, stuff->dstx, + stuff->dsty, stuff->key)) + return BadMatch; + + return Success; +} + +static int +ProcXDGAGetViewportStatus(ClientPtr client) +{ + REQUEST(xXDGAGetViewportStatusReq); + xXDGAGetViewportStatusReply rep; + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGAGetViewportStatusReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rep.status = DGAGetViewportStatus(stuff->screen); + + WriteToClient(client, sizeof(xXDGAGetViewportStatusReply), (char *) &rep); + return Success; +} + +static int +ProcXDGASync(ClientPtr client) +{ + REQUEST(xXDGASyncReq); + xXDGASyncReply rep; + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGASyncReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + DGASync(stuff->screen); + + WriteToClient(client, sizeof(xXDGASyncReply), (char *) &rep); + return Success; +} + +static int +ProcXDGASetClientVersion(ClientPtr client) +{ + REQUEST(xXDGASetClientVersionReq); + + DGAPrivPtr pPriv; + + REQUEST_SIZE_MATCH(xXDGASetClientVersionReq); + if ((pPriv = DGA_GETPRIV(client)) == NULL) { + pPriv = malloc(sizeof(DGAPrivRec)); + /* XXX Need to look into freeing this */ + if (!pPriv) + return BadAlloc; + DGA_SETPRIV(client, pPriv); + } + pPriv->major = stuff->major; + pPriv->minor = stuff->minor; + + return Success; +} + +static int +ProcXDGAChangePixmapMode(ClientPtr client) +{ + REQUEST(xXDGAChangePixmapModeReq); + xXDGAChangePixmapModeReply rep; + int x, y; + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGAChangePixmapModeReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + x = stuff->x; + y = stuff->y; + + if (!DGAChangePixmapMode(stuff->screen, &x, &y, stuff->flags)) + return BadMatch; + + rep.x = x; + rep.y = y; + WriteToClient(client, sizeof(xXDGAChangePixmapModeReply), (char *) &rep); + + return Success; +} + +static int +ProcXDGACreateColormap(ClientPtr client) +{ + REQUEST(xXDGACreateColormapReq); + int result; + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGACreateColormapReq); + + if (!stuff->mode) + return BadValue; + + result = DGACreateColormap(stuff->screen, client, stuff->id, + stuff->mode, stuff->alloc); + if (result != Success) + return result; + + return Success; +} + +/* + * + * Support for the old DGA protocol, used to live in xf86dga.c + * + */ + +#ifdef DGA_PROTOCOL_OLD_SUPPORT + +static int +ProcXF86DGAGetVideoLL(ClientPtr client) +{ + REQUEST(xXF86DGAGetVideoLLReq); + xXF86DGAGetVideoLLReply rep; + XDGAModeRec mode; + int num, offset, flags; + char *name; + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86DGAGetVideoLLReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!DGAAvailable(stuff->screen)) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + if (!(num = DGAGetOldDGAMode(stuff->screen))) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + /* get the parameters for the mode that best matches */ + DGAGetModeInfo(stuff->screen, &mode, num); + + if (!DGAOpenFramebuffer(stuff->screen, &name, + (unsigned char **) (&rep.offset), + (int *) (&rep.bank_size), &offset, &flags)) + return BadAlloc; + + rep.offset += mode.offset; + rep.width = mode.bytesPerScanline / (mode.bitsPerPixel >> 3); + rep.ram_size = rep.bank_size >> 10; + + WriteToClient(client, SIZEOF(xXF86DGAGetVideoLLReply), (char *) &rep); + return Success; +} + +static int +ProcXF86DGADirectVideo(ClientPtr client) +{ + int num; + PixmapPtr pix; + XDGAModeRec mode; + ClientPtr owner; + + REQUEST(xXF86DGADirectVideoReq); + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + REQUEST_SIZE_MATCH(xXF86DGADirectVideoReq); + + if (!DGAAvailable(stuff->screen)) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + owner = DGA_GETCLIENT(stuff->screen); + + if (owner && owner != client) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + if (stuff->enable & XF86DGADirectGraphics) { + if (!(num = DGAGetOldDGAMode(stuff->screen))) + return DGAErrorBase + XF86DGANoDirectVideoMode; + } + else + num = 0; + + if (Success != DGASetMode(stuff->screen, num, &mode, &pix)) + return DGAErrorBase + XF86DGAScreenNotActive; + + DGASetInputMode(stuff->screen, + (stuff->enable & XF86DGADirectKeyb) != 0, + (stuff->enable & XF86DGADirectMouse) != 0); + + /* We need to track the client and attach the teardown callback */ + if (stuff->enable & + (XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse)) { + if (!owner) { + if (DGACallbackRefCount++ == 0) + AddCallback(&ClientStateCallback, DGAClientStateChange, NULL); + } + + DGA_SETCLIENT(stuff->screen, client); + } + else { + if (owner) { + if (--DGACallbackRefCount == 0) + DeleteCallback(&ClientStateCallback, DGAClientStateChange, + NULL); + } + + DGA_SETCLIENT(stuff->screen, NULL); + } + + return Success; +} + +static int +ProcXF86DGAGetViewPortSize(ClientPtr client) +{ + int num; + XDGAModeRec mode; + + REQUEST(xXF86DGAGetViewPortSizeReq); + xXF86DGAGetViewPortSizeReply rep; + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86DGAGetViewPortSizeReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!DGAAvailable(stuff->screen)) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + if (!(num = DGAGetOldDGAMode(stuff->screen))) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + DGAGetModeInfo(stuff->screen, &mode, num); + + rep.width = mode.viewportWidth; + rep.height = mode.viewportHeight; + + WriteToClient(client, SIZEOF(xXF86DGAGetViewPortSizeReply), (char *) &rep); + return Success; +} + +static int +ProcXF86DGASetViewPort(ClientPtr client) +{ + REQUEST(xXF86DGASetViewPortReq); + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXF86DGASetViewPortReq); + + if (!DGAAvailable(stuff->screen)) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + if (!DGAActive(stuff->screen)) + return DGAErrorBase + XF86DGADirectNotActivated; + + if (DGASetViewport(stuff->screen, stuff->x, stuff->y, DGA_FLIP_RETRACE) + != Success) + return DGAErrorBase + XF86DGADirectNotActivated; + + return Success; +} + +static int +ProcXF86DGAGetVidPage(ClientPtr client) +{ + REQUEST(xXF86DGAGetVidPageReq); + xXF86DGAGetVidPageReply rep; + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86DGAGetVidPageReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.vpage = 0; /* silently fail */ + + WriteToClient(client, SIZEOF(xXF86DGAGetVidPageReply), (char *) &rep); + return Success; +} + +static int +ProcXF86DGASetVidPage(ClientPtr client) +{ + REQUEST(xXF86DGASetVidPageReq); + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86DGASetVidPageReq); + + /* silently fail */ + + return Success; +} + +static int +ProcXF86DGAInstallColormap(ClientPtr client) +{ + ColormapPtr pcmp; + int rc; + + REQUEST(xXF86DGAInstallColormapReq); + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXF86DGAInstallColormapReq); + + if (!DGAActive(stuff->screen)) + return DGAErrorBase + XF86DGADirectNotActivated; + + rc = dixLookupResourceByType((pointer *) &pcmp, stuff->id, RT_COLORMAP, + client, DixInstallAccess); + if (rc == Success) { + DGAInstallCmap(pcmp); + return Success; + } + else { + return rc; + } +} + +static int +ProcXF86DGAQueryDirectVideo(ClientPtr client) +{ + REQUEST(xXF86DGAQueryDirectVideoReq); + xXF86DGAQueryDirectVideoReply rep; + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86DGAQueryDirectVideoReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.flags = 0; + + if (DGAAvailable(stuff->screen)) + rep.flags = XF86DGADirectPresent; + + WriteToClient(client, SIZEOF(xXF86DGAQueryDirectVideoReply), (char *) &rep); + return Success; +} + +static int +ProcXF86DGAViewPortChanged(ClientPtr client) +{ + REQUEST(xXF86DGAViewPortChangedReq); + xXF86DGAViewPortChangedReply rep; + + if (stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXF86DGAViewPortChangedReq); + + if (!DGAActive(stuff->screen)) + return DGAErrorBase + XF86DGADirectNotActivated; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.result = 1; + + WriteToClient(client, SIZEOF(xXF86DGAViewPortChangedReply), (char *) &rep); + return Success; +} + +#endif /* DGA_PROTOCOL_OLD_SUPPORT */ + +static int +SProcXDGADispatch(ClientPtr client) +{ + return DGAErrorBase + XF86DGAClientNotLocal; +} + +#if 0 +#define DGA_REQ_DEBUG +#endif + +#ifdef DGA_REQ_DEBUG +static char *dgaMinor[] = { + "QueryVersion", + "GetVideoLL", + "DirectVideo", + "GetViewPortSize", + "SetViewPort", + "GetVidPage", + "SetVidPage", + "InstallColormap", + "QueryDirectVideo", + "ViewPortChanged", + "10", + "11", + "QueryModes", + "SetMode", + "SetViewport", + "InstallColormap", + "SelectInput", + "FillRectangle", + "CopyArea", + "CopyTransparentArea", + "GetViewportStatus", + "Sync", + "OpenFramebuffer", + "CloseFramebuffer", + "SetClientVersion", + "ChangePixmapMode", + "CreateColormap", +}; +#endif + +static int +ProcXDGADispatch(ClientPtr client) +{ + REQUEST(xReq); + + if (!LocalClient(client)) + return DGAErrorBase + XF86DGAClientNotLocal; + +#ifdef DGA_REQ_DEBUG + if (stuff->data <= X_XDGACreateColormap) + fprintf(stderr, " DGA %s\n", dgaMinor[stuff->data]); +#endif + + switch (stuff->data) { + /* + * DGA2 Protocol + */ + case X_XDGAQueryVersion: + return ProcXDGAQueryVersion(client); + case X_XDGAQueryModes: + return ProcXDGAQueryModes(client); + case X_XDGASetMode: + return ProcXDGASetMode(client); + case X_XDGAOpenFramebuffer: + return ProcXDGAOpenFramebuffer(client); + case X_XDGACloseFramebuffer: + return ProcXDGACloseFramebuffer(client); + case X_XDGASetViewport: + return ProcXDGASetViewport(client); + case X_XDGAInstallColormap: + return ProcXDGAInstallColormap(client); + case X_XDGASelectInput: + return ProcXDGASelectInput(client); + case X_XDGAFillRectangle: + return ProcXDGAFillRectangle(client); + case X_XDGACopyArea: + return ProcXDGACopyArea(client); + case X_XDGACopyTransparentArea: + return ProcXDGACopyTransparentArea(client); + case X_XDGAGetViewportStatus: + return ProcXDGAGetViewportStatus(client); + case X_XDGASync: + return ProcXDGASync(client); + case X_XDGASetClientVersion: + return ProcXDGASetClientVersion(client); + case X_XDGAChangePixmapMode: + return ProcXDGAChangePixmapMode(client); + case X_XDGACreateColormap: + return ProcXDGACreateColormap(client); + /* + * Old DGA Protocol + */ +#ifdef DGA_PROTOCOL_OLD_SUPPORT + case X_XF86DGAGetVideoLL: + return ProcXF86DGAGetVideoLL(client); + case X_XF86DGADirectVideo: + return ProcXF86DGADirectVideo(client); + case X_XF86DGAGetViewPortSize: + return ProcXF86DGAGetViewPortSize(client); + case X_XF86DGASetViewPort: + return ProcXF86DGASetViewPort(client); + case X_XF86DGAGetVidPage: + return ProcXF86DGAGetVidPage(client); + case X_XF86DGASetVidPage: + return ProcXF86DGASetVidPage(client); + case X_XF86DGAInstallColormap: + return ProcXF86DGAInstallColormap(client); + case X_XF86DGAQueryDirectVideo: + return ProcXF86DGAQueryDirectVideo(client); + case X_XF86DGAViewPortChanged: + return ProcXF86DGAViewPortChanged(client); +#endif /* DGA_PROTOCOL_OLD_SUPPORT */ + default: + return BadRequest; + } +} + +void +XFree86DGAExtensionInit(void) +{ + ExtensionEntry *extEntry; + + if (!dixRegisterPrivateKey(&DGAClientPrivateKeyRec, PRIVATE_CLIENT, 0)) + return; + + if (!dixRegisterPrivateKey(&DGAScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) + return; + + if ((extEntry = AddExtension(XF86DGANAME, + XF86DGANumberEvents, + XF86DGANumberErrors, + ProcXDGADispatch, + SProcXDGADispatch, + XDGAResetProc, StandardMinorOpcode))) { + int i; + + DGAReqCode = (unsigned char) extEntry->base; + DGAErrorBase = extEntry->errorBase; + DGAEventBase = extEntry->eventBase; + for (i = KeyPress; i <= MotionNotify; i++) + SetCriticalEvent(DGAEventBase + i); + } +} |