From 3319741e6f9fc3232eb40462a261271b9af2dcb2 Mon Sep 17 00:00:00 2001 From: marha Date: Thu, 20 May 2010 07:07:37 +0000 Subject: xserver git update 20/5/2010 --- xorg-server/Xext/panoramiX.c | 4 + xorg-server/Xext/panoramiXprocs.c | 124 +- xorg-server/Xext/saver.c | 17 +- xorg-server/Xext/security.c | 19 +- xorg-server/Xext/shape.c | 21 +- xorg-server/Xext/shm.c | 6 +- xorg-server/Xext/sync.c | 4793 ++++--- xorg-server/Xext/xcalibrate.c | 4 +- xorg-server/Xext/xtest.c | 2 +- xorg-server/Xext/xvdisp.c | 25 +- xorg-server/Xext/xvdix.h | 550 +- xorg-server/Xext/xvmain.c | 35 +- xorg-server/Xext/xvmc.c | 15 +- xorg-server/Xi/exevents.c | 4 +- xorg-server/Xi/xichangecursor.c | 226 +- xorg-server/Xi/xipassivegrab.c | 2 +- xorg-server/composite/compext.c | 5 +- xorg-server/damageext/damageext.c | 10 +- xorg-server/damageext/damageextint.h | 2 +- xorg-server/dbe/dbe.c | 3356 ++--- xorg-server/dix/cursor.c | 4 +- xorg-server/dix/dispatch.c | 47 +- xorg-server/dix/dixfonts.c | 1 - xorg-server/dix/dixutils.c | 8 +- xorg-server/dix/events.c | 26 +- xorg-server/dix/gc.c | 2316 ++- xorg-server/dix/inpututils.c | 1 - xorg-server/dix/resource.c | 101 +- xorg-server/dix/selection.c | 12 +- xorg-server/dix/window.c | 8 +- xorg-server/glx/glxdri2.c | 1 - xorg-server/hw/xfree86/common/xf86.h | 3 +- xorg-server/hw/xfree86/common/xf86Bus.c | 283 +- xorg-server/hw/xfree86/common/xf86Configure.c | 11 +- xorg-server/hw/xfree86/common/xf86Init.c | 313 +- xorg-server/hw/xfree86/common/xf86Opt.h | 230 +- xorg-server/hw/xfree86/common/xf86Option.c | 47 + xorg-server/hw/xfree86/common/xf86Priv.h | 331 +- xorg-server/hw/xfree86/common/xf86ShowOpts.c | 2 + xorg-server/hw/xfree86/common/xf86pciBus.c | 160 + xorg-server/hw/xfree86/common/xf86pciBus.h | 79 +- xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c | 4 +- xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c | 7 +- xorg-server/hw/xfree86/doc/sgml/DESIGN.sgml | 14834 ++++++++++---------- xorg-server/hw/xfree86/dri2/dri2ext.c | 5 - xorg-server/hw/xquartz/applewm.c | 10 +- xorg-server/hw/xquartz/xpr/appledri.c | 8 +- xorg-server/hw/xwin/winconfig.c | 37 + xorg-server/hw/xwin/winconfig.h | 646 +- xorg-server/hw/xwin/winwindowswm.c | 4 +- xorg-server/include/inputstr.h | 1206 +- xorg-server/include/resource.h | 3 + xorg-server/mi/midispcur.c | 58 +- xorg-server/mi/miexpose.c | 5 +- xorg-server/mi/misprite.c | 86 +- xorg-server/mi/misprite.h | 164 +- xorg-server/os/io.c | 8 +- xorg-server/randr/randrstr.h | 1974 +-- xorg-server/randr/rrcrtc.c | 4 +- xorg-server/randr/rrmode.c | 1 + xorg-server/randr/rroutput.c | 2 +- xorg-server/randr/rrproperty.c | 6 - xorg-server/randr/rrscreen.c | 2 - xorg-server/record/record.c | 5 +- xorg-server/render/animcur.c | 66 +- xorg-server/render/picture.c | 2 - xorg-server/render/picturestr.h | 2 +- xorg-server/render/render.c | 6752 ++++----- xorg-server/xfixes/cursor.c | 13 +- xorg-server/xfixes/region.c | 6 +- xorg-server/xfixes/select.c | 4 +- xorg-server/xfixes/xfixes.c | 1 + xorg-server/xfixes/xfixes.h | 113 +- xorg-server/xkb/xkbEvents.c | 1 - 74 files changed, 19530 insertions(+), 19713 deletions(-) diff --git a/xorg-server/Xext/panoramiX.c b/xorg-server/Xext/panoramiX.c index e26aadc95..65af9a71f 100644 --- a/xorg-server/Xext/panoramiX.c +++ b/xorg-server/Xext/panoramiX.c @@ -519,6 +519,10 @@ void PanoramiXExtensionInit(int argc, char *argv[]) panoramiXGeneration = serverGeneration; success = TRUE; } + SetResourceTypeErrorValue(XRT_WINDOW, BadWindow); + SetResourceTypeErrorValue(XRT_PIXMAP, BadPixmap); + SetResourceTypeErrorValue(XRT_GC, BadGC); + SetResourceTypeErrorValue(XRT_COLORMAP, BadColor); } if (!success) { diff --git a/xorg-server/Xext/panoramiXprocs.c b/xorg-server/Xext/panoramiXprocs.c index 369744c8c..2fe329886 100644 --- a/xorg-server/Xext/panoramiXprocs.c +++ b/xorg-server/Xext/panoramiXprocs.c @@ -74,7 +74,7 @@ int PanoramiXCreateWindow(ClientPtr client) result = dixLookupResourceByType((pointer *)&parent, stuff->parent, XRT_WINDOW, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; if(stuff->class == CopyFromParent) stuff->class = parent->u.win.class; @@ -89,7 +89,7 @@ int PanoramiXCreateWindow(ClientPtr client) result = dixLookupResourceByType((pointer *)&backPix, tmp, XRT_PIXMAP, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadPixmap : result; + return result; } } if ((Mask)stuff->mask & CWBorderPixmap) { @@ -99,7 +99,7 @@ int PanoramiXCreateWindow(ClientPtr client) result = dixLookupResourceByType((pointer *)&bordPix, tmp, XRT_PIXMAP, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadPixmap : result; + return result; } } if ((Mask)stuff->mask & CWColormap) { @@ -109,7 +109,7 @@ int PanoramiXCreateWindow(ClientPtr client) result = dixLookupResourceByType((pointer *)&cmap, tmp, XRT_COLORMAP, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadColor : result; + return result; } } @@ -179,7 +179,7 @@ int PanoramiXChangeWindowAttributes(ClientPtr client) result = dixLookupResourceByType((pointer *)&win, stuff->window, XRT_WINDOW, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; if((win->u.win.class == InputOnly) && (stuff->valueMask & (~INPUTONLY_LEGAL_MASK))) @@ -192,7 +192,7 @@ int PanoramiXChangeWindowAttributes(ClientPtr client) result = dixLookupResourceByType((pointer *)&backPix, tmp, XRT_PIXMAP, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadPixmap : result; + return result; } } if ((Mask)stuff->valueMask & CWBorderPixmap) { @@ -202,7 +202,7 @@ int PanoramiXChangeWindowAttributes(ClientPtr client) result = dixLookupResourceByType((pointer *)&bordPix, tmp, XRT_PIXMAP, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadPixmap : result; + return result; } } if ((Mask)stuff->valueMask & CWColormap) { @@ -212,7 +212,7 @@ int PanoramiXChangeWindowAttributes(ClientPtr client) result = dixLookupResourceByType((pointer *)&cmap, tmp, XRT_COLORMAP, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadColor : result; + return result; } } @@ -242,7 +242,7 @@ int PanoramiXDestroyWindow(ClientPtr client) result = dixLookupResourceByType((pointer *)&win, stuff->id, XRT_WINDOW, client, DixDestroyAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; FOR_NSCREENS_BACKWARD(j) { stuff->id = win->info[j].id; @@ -268,7 +268,7 @@ int PanoramiXDestroySubwindows(ClientPtr client) result = dixLookupResourceByType((pointer *)&win, stuff->id, XRT_WINDOW, client, DixDestroyAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; FOR_NSCREENS_BACKWARD(j) { stuff->id = win->info[j].id; @@ -294,7 +294,7 @@ int PanoramiXChangeSaveSet(ClientPtr client) result = dixLookupResourceByType((pointer *)&win, stuff->window, XRT_WINDOW, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; FOR_NSCREENS_BACKWARD(j) { stuff->window = win->info[j].id; @@ -319,12 +319,12 @@ int PanoramiXReparentWindow(ClientPtr client) result = dixLookupResourceByType((pointer *)&win, stuff->window, XRT_WINDOW, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; result = dixLookupResourceByType((pointer *)&parent, stuff->parent, XRT_WINDOW, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; x = stuff->x; y = stuff->y; @@ -356,7 +356,7 @@ int PanoramiXMapWindow(ClientPtr client) result = dixLookupResourceByType((pointer *)&win, stuff->id, XRT_WINDOW, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; FOR_NSCREENS_FORWARD(j) { stuff->id = win->info[j].id; @@ -379,7 +379,7 @@ int PanoramiXMapSubwindows(ClientPtr client) result = dixLookupResourceByType((pointer *)&win, stuff->id, XRT_WINDOW, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; FOR_NSCREENS_FORWARD(j) { stuff->id = win->info[j].id; @@ -402,7 +402,7 @@ int PanoramiXUnmapWindow(ClientPtr client) result = dixLookupResourceByType((pointer *)&win, stuff->id, XRT_WINDOW, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; FOR_NSCREENS_FORWARD(j) { stuff->id = win->info[j].id; @@ -425,7 +425,7 @@ int PanoramiXUnmapSubwindows(ClientPtr client) result = dixLookupResourceByType((pointer *)&win, stuff->id, XRT_WINDOW, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; FOR_NSCREENS_FORWARD(j) { stuff->id = win->info[j].id; @@ -457,12 +457,12 @@ int PanoramiXConfigureWindow(ClientPtr client) result = dixLookupResourceByType((pointer *)&pWin, stuff->window, RT_WINDOW, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; result = dixLookupResourceByType((pointer *)&win, stuff->window, XRT_WINDOW, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; if ((Mask)stuff->mask & CWSibling) { XID tmp; @@ -471,7 +471,7 @@ int PanoramiXConfigureWindow(ClientPtr client) result = dixLookupResourceByType((pointer *)&sib, tmp, XRT_WINDOW, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; } } @@ -517,7 +517,7 @@ int PanoramiXCirculateWindow(ClientPtr client) result = dixLookupResourceByType((pointer *)&win, stuff->window, XRT_WINDOW, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; FOR_NSCREENS_FORWARD(j) { stuff->window = win->info[j].id; @@ -697,7 +697,7 @@ int PanoramiXFreePixmap(ClientPtr client) result = dixLookupResourceByType((pointer *)&pix, stuff->id, XRT_PIXMAP, client, DixDestroyAccess); if (result != Success) - return (result == BadValue) ? BadPixmap : result; + return result; FOR_NSCREENS_BACKWARD(j) { stuff->id = pix->info[j].id; @@ -742,7 +742,7 @@ int PanoramiXCreateGC(ClientPtr client) result = dixLookupResourceByType((pointer *)&tile, tmp, XRT_PIXMAP, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadPixmap : result; + return result; } } if ((Mask)stuff->mask & GCStipple) { @@ -751,7 +751,7 @@ int PanoramiXCreateGC(ClientPtr client) result = dixLookupResourceByType((pointer *)&stip, tmp, XRT_PIXMAP, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadPixmap : result; + return result; } } if ((Mask)stuff->mask & GCClipMask) { @@ -760,7 +760,7 @@ int PanoramiXCreateGC(ClientPtr client) result = dixLookupResourceByType((pointer *)&clip, tmp, XRT_PIXMAP, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadPixmap : result; + return result; } } @@ -813,7 +813,7 @@ int PanoramiXChangeGC(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; if ((Mask)stuff->mask & GCTile) { tile_offset = Ones((Mask)stuff->mask & (GCTile - 1)); @@ -821,7 +821,7 @@ int PanoramiXChangeGC(ClientPtr client) result = dixLookupResourceByType((pointer *)&tile, tmp, XRT_PIXMAP, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadPixmap : result; + return result; } } if ((Mask)stuff->mask & GCStipple) { @@ -830,7 +830,7 @@ int PanoramiXChangeGC(ClientPtr client) result = dixLookupResourceByType((pointer *)&stip, tmp, XRT_PIXMAP, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadPixmap : result; + return result; } } if ((Mask)stuff->mask & GCClipMask) { @@ -839,7 +839,7 @@ int PanoramiXChangeGC(ClientPtr client) result = dixLookupResourceByType((pointer *)&clip, tmp, XRT_PIXMAP, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadPixmap : result; + return result; } } @@ -871,12 +871,12 @@ int PanoramiXCopyGC(ClientPtr client) result = dixLookupResourceByType((pointer *)&srcGC, stuff->srcGC, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; result = dixLookupResourceByType((pointer *)&dstGC, stuff->dstGC, XRT_GC, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; FOR_NSCREENS(j) { stuff->srcGC = srcGC->info[j].id; @@ -900,7 +900,7 @@ int PanoramiXSetDashes(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; FOR_NSCREENS_BACKWARD(j) { stuff->gc = gc->info[j].id; @@ -923,7 +923,7 @@ int PanoramiXSetClipRectangles(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; FOR_NSCREENS_BACKWARD(j) { stuff->gc = gc->info[j].id; @@ -946,7 +946,7 @@ int PanoramiXFreeGC(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->id, XRT_GC, client, DixDestroyAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; FOR_NSCREENS_BACKWARD(j) { stuff->id = gc->info[j].id; @@ -973,7 +973,7 @@ int PanoramiXClearToBackground(ClientPtr client) result = dixLookupResourceByType((pointer *)&win, stuff->window, XRT_WINDOW, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; x = stuff->x; y = stuff->y; @@ -1033,7 +1033,7 @@ int PanoramiXCopyArea(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; if((dst->type == XRT_WINDOW) && dst->u.win.root) dstIsRoot = TRUE; @@ -1188,7 +1188,7 @@ int PanoramiXCopyPlane(ClientPtr client) rc = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (rc != Success) - return (rc == BadValue) ? BadGC : rc; + return rc; if((dst->type == XRT_WINDOW) && dst->u.win.root) dstIsRoot = TRUE; @@ -1285,7 +1285,7 @@ int PanoramiXPolyPoint(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq)); @@ -1345,7 +1345,7 @@ int PanoramiXPolyLine(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq)); @@ -1405,7 +1405,7 @@ int PanoramiXPolySegment(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; @@ -1468,7 +1468,7 @@ int PanoramiXPolyRectangle(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; @@ -1530,7 +1530,7 @@ int PanoramiXPolyArc(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; @@ -1590,7 +1590,7 @@ int PanoramiXFillPoly(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; @@ -1651,7 +1651,7 @@ int PanoramiXPolyFillRectangle(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; @@ -1712,7 +1712,7 @@ int PanoramiXPolyFillArc(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; @@ -1772,7 +1772,7 @@ int PanoramiXPutImage(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; @@ -1973,7 +1973,7 @@ PanoramiXPolyText8(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; @@ -2014,7 +2014,7 @@ PanoramiXPolyText16(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; @@ -2055,7 +2055,7 @@ int PanoramiXImageText8(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; @@ -2096,7 +2096,7 @@ int PanoramiXImageText16(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; @@ -2128,7 +2128,7 @@ int PanoramiXCreateColormap(ClientPtr client) result = dixLookupResourceByType((pointer *)&win, stuff->window, XRT_WINDOW, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; if(!(newCmap = malloc(sizeof(PanoramiXRes)))) return BadAlloc; @@ -2169,7 +2169,7 @@ int PanoramiXFreeColormap(ClientPtr client) result = dixLookupResourceByType((pointer *)&cmap, stuff->id, XRT_COLORMAP, client, DixDestroyAccess); if (result != Success) - return (result == BadValue) ? BadColor : result; + return result; FOR_NSCREENS_BACKWARD(j) { stuff->id = cmap->info[j].id; @@ -2199,7 +2199,7 @@ PanoramiXCopyColormapAndFree(ClientPtr client) XRT_COLORMAP, client, DixReadAccess | DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadColor : result; + return result; if(!(newCmap = malloc(sizeof(PanoramiXRes)))) return BadAlloc; @@ -2238,7 +2238,7 @@ int PanoramiXInstallColormap(ClientPtr client) result = dixLookupResourceByType((pointer *)&cmap, stuff->id, XRT_COLORMAP, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadColor : result; + return result; FOR_NSCREENS_BACKWARD(j){ stuff->id = cmap->info[j].id; @@ -2262,7 +2262,7 @@ int PanoramiXUninstallColormap(ClientPtr client) result = dixLookupResourceByType((pointer *)&cmap, stuff->id, XRT_COLORMAP, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadColor : result; + return result; FOR_NSCREENS_BACKWARD(j) { stuff->id = cmap->info[j].id; @@ -2286,7 +2286,7 @@ int PanoramiXAllocColor(ClientPtr client) result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, XRT_COLORMAP, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadColor : result; + return result; FOR_NSCREENS_BACKWARD(j){ stuff->cmap = cmap->info[j].id; @@ -2310,7 +2310,7 @@ int PanoramiXAllocNamedColor(ClientPtr client) result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, XRT_COLORMAP, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadColor : result; + return result; FOR_NSCREENS_BACKWARD(j){ stuff->cmap = cmap->info[j].id; @@ -2334,7 +2334,7 @@ int PanoramiXAllocColorCells(ClientPtr client) result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, XRT_COLORMAP, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadColor : result; + return result; FOR_NSCREENS_BACKWARD(j){ stuff->cmap = cmap->info[j].id; @@ -2358,7 +2358,7 @@ int PanoramiXAllocColorPlanes(ClientPtr client) result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, XRT_COLORMAP, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadColor : result; + return result; FOR_NSCREENS_BACKWARD(j){ stuff->cmap = cmap->info[j].id; @@ -2383,7 +2383,7 @@ int PanoramiXFreeColors(ClientPtr client) result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, XRT_COLORMAP, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadColor : result; + return result; FOR_NSCREENS_BACKWARD(j) { stuff->cmap = cmap->info[j].id; @@ -2406,7 +2406,7 @@ int PanoramiXStoreColors(ClientPtr client) result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, XRT_COLORMAP, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadColor : result; + return result; FOR_NSCREENS_BACKWARD(j){ stuff->cmap = cmap->info[j].id; @@ -2430,7 +2430,7 @@ int PanoramiXStoreNamedColor(ClientPtr client) result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, XRT_COLORMAP, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadColor : result; + return result; FOR_NSCREENS_BACKWARD(j){ stuff->cmap = cmap->info[j].id; diff --git a/xorg-server/Xext/saver.c b/xorg-server/Xext/saver.c index f82b4b51b..0efe5bf2a 100644 --- a/xorg-server/Xext/saver.c +++ b/xorg-server/Xext/saver.c @@ -480,7 +480,6 @@ SendScreenSaverNotify (ScreenPtr pScreen, int state, Bool forced) ScreenSaverEventPtr pEv; unsigned long mask; xScreenSaverNotifyEvent ev; - ClientPtr client; int kind; UpdateCurrentTimeIf (); @@ -499,20 +498,16 @@ SendScreenSaverNotify (ScreenPtr pScreen, int state, Bool forced) kind = ScreenSaverInternal; for (pEv = pPriv->events; pEv; pEv = pEv->next) { - client = pEv->client; - if (client->clientGone) - continue; if (!(pEv->mask & mask)) continue; ev.type = ScreenSaverNotify + ScreenSaverEventBase; ev.state = state; - ev.sequenceNumber = client->sequence; ev.timestamp = currentTime.milliseconds; ev.root = WindowTable[pScreen->myNum]->drawable.id; ev.window = savedScreenInfo[pScreen->myNum].wid; ev.kind = kind; ev.forced = forced; - WriteEventsToClient (client, 1, (xEvent *) &ev); + WriteEventsToClient (pEv->client, 1, (xEvent *) &ev); } } @@ -1048,7 +1043,6 @@ ScreenSaverSetAttributes (ClientPtr client) } else { - ret = (ret == BadValue) ? BadPixmap : ret; client->errorValue = pixID; goto PatchUp; } @@ -1086,7 +1080,6 @@ ScreenSaverSetAttributes (ClientPtr client) } else { - ret = (ret == BadValue) ? BadPixmap : ret; client->errorValue = pixID; goto PatchUp; } @@ -1168,7 +1161,6 @@ ScreenSaverSetAttributes (ClientPtr client) client, DixUseAccess); if (ret != Success) { - ret = (ret == BadValue) ? BadColor : ret; client->errorValue = cmap; goto PatchUp; } @@ -1192,7 +1184,6 @@ ScreenSaverSetAttributes (ClientPtr client) RT_CURSOR, client, DixUseAccess); if (ret != Success) { - ret = (ret == BadValue) ? BadCursor : ret; client->errorValue = cursorID; goto PatchUp; } @@ -1281,7 +1272,7 @@ ProcScreenSaverSetAttributes (ClientPtr client) XRT_PIXMAP, client, DixReadAccess); if (status != Success) - return (status == BadValue) ? BadPixmap : status; + return status; } } @@ -1293,7 +1284,7 @@ ProcScreenSaverSetAttributes (ClientPtr client) XRT_PIXMAP, client, DixReadAccess); if (status != Success) - return (status == BadValue) ? BadPixmap : status; + return status; } } @@ -1305,7 +1296,7 @@ ProcScreenSaverSetAttributes (ClientPtr client) XRT_COLORMAP, client, DixReadAccess); if (status != Success) - return (status == BadValue) ? BadColor : status; + return status; } } diff --git a/xorg-server/Xext/security.c b/xorg-server/Xext/security.c index 289f9597d..4201e583d 100644 --- a/xorg-server/Xext/security.c +++ b/xorg-server/Xext/security.c @@ -198,16 +198,10 @@ SecurityDeleteAuthorization( while ((pEventClient = pAuth->eventClients)) { /* send revocation event event */ - ClientPtr client = rClient(pEventClient); - - if (!client->clientGone) - { - xSecurityAuthorizationRevokedEvent are; - are.type = SecurityEventBase + XSecurityAuthorizationRevoked; - are.sequenceNumber = client->sequence; - are.authId = pAuth->id; - WriteEventsToClient(client, 1, (xEvent *)&are); - } + xSecurityAuthorizationRevokedEvent are; + are.type = SecurityEventBase + XSecurityAuthorizationRevoked; + are.authId = pAuth->id; + WriteEventsToClient(rClient(pEventClient), 1, (xEvent *)&are); FreeResource(pEventClient->resource, RT_NONE); } @@ -629,8 +623,7 @@ ProcSecurityRevokeAuthorization( SecurityAuthorizationResType, client, DixDestroyAccess); if (rc != Success) - return (rc == BadValue) ? - SecurityErrorBase + XSecurityBadAuthorization : rc; + return rc; FreeResource(stuff->authId, RT_NONE); return Success; @@ -1146,6 +1139,8 @@ SecurityExtensionInit(INITARGS) EventSwapVector[SecurityEventBase + XSecurityAuthorizationRevoked] = (EventSwapPtr)SwapSecurityAuthorizationRevokedEvent; + SetResourceTypeErrorValue(SecurityAuthorizationResType, SecurityErrorBase + XSecurityBadAuthorization); + /* Label objects that were created before we could register ourself */ SecurityLabelInitial(); } diff --git a/xorg-server/Xext/shape.c b/xorg-server/Xext/shape.c index edecc51ed..f57a20cbf 100644 --- a/xorg-server/Xext/shape.c +++ b/xorg-server/Xext/shape.c @@ -360,7 +360,7 @@ ProcPanoramiXShapeRectangles( result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; FOR_NSCREENS(j) { stuff->dest = win->info[j].id; @@ -415,7 +415,7 @@ ProcShapeMask (ClientPtr client) rc = dixLookupResourceByType((pointer *)&pPixmap, stuff->src, RT_PIXMAP, client, DixReadAccess); if (rc != Success) - return (rc == BadValue) ? BadPixmap : rc; + return rc; if (pPixmap->drawable.pScreen != pScreen || pPixmap->drawable.depth != 1) return BadMatch; @@ -459,13 +459,13 @@ ProcPanoramiXShapeMask( result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; if(stuff->src != None) { result = dixLookupResourceByType((pointer *)&pmap, stuff->src, XRT_PIXMAP, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadPixmap : result; + return result; } else pmap = NULL; @@ -589,12 +589,12 @@ ProcPanoramiXShapeCombine( result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; result = dixLookupResourceByType((pointer *)&win2, stuff->src, XRT_WINDOW, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; FOR_NSCREENS(j) { stuff->dest = win->info[j].id; @@ -663,7 +663,7 @@ ProcPanoramiXShapeOffset( result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW, client, DixWriteAccess); if (result != Success) - return (result == BadValue) ? BadWindow : result; + return result; FOR_NSCREENS(j) { stuff->dest = win->info[j].id; @@ -885,7 +885,6 @@ void SendShapeNotify (WindowPtr pWin, int which) { ShapeEventPtr *pHead, pShapeEvent; - ClientPtr client; xShapeNotifyEvent se; BoxRec extents; RegionPtr region; @@ -940,20 +939,16 @@ SendShapeNotify (WindowPtr pWin, int which) return; } for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) { - client = pShapeEvent->client; - if (client == serverClient || client->clientGone) - continue; se.type = ShapeNotify + ShapeEventBase; se.kind = which; se.window = pWin->drawable.id; - se.sequenceNumber = client->sequence; se.x = extents.x1; se.y = extents.y1; se.width = extents.x2 - extents.x1; se.height = extents.y2 - extents.y1; se.time = currentTime.milliseconds; se.shaped = shaped; - WriteEventsToClient (client, 1, (xEvent *) &se); + WriteEventsToClient (pShapeEvent->client, 1, (xEvent *) &se); } } diff --git a/xorg-server/Xext/shm.c b/xorg-server/Xext/shm.c index 0d78fbc06..885fd61ef 100644 --- a/xorg-server/Xext/shm.c +++ b/xorg-server/Xext/shm.c @@ -156,7 +156,7 @@ static ShmFuncs fbFuncs = {fbShmCreatePixmap, NULL}; rc = dixLookupResourceByType((pointer *)&(shmdesc), shmseg, ShmSegType, \ client, DixReadAccess); \ if (rc != Success) \ - return (rc == BadValue) ? BadShmSegCode : rc; \ + return rc; \ } #define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \ @@ -286,6 +286,7 @@ ShmExtensionInit(INITARGS) ShmReqCode = (unsigned char)extEntry->base; ShmCompletionCode = extEntry->eventBase; BadShmSegCode = extEntry->errorBase; + SetResourceTypeErrorValue(ShmSegType, BadShmSegCode); EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent; } } @@ -584,7 +585,7 @@ ProcPanoramiXShmPutImage(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; @@ -943,7 +944,6 @@ ProcShmPutImage(ClientPtr client) ev.type = ShmCompletionCode; ev.drawable = stuff->drawable; - ev.sequenceNumber = client->sequence; ev.minorEvent = X_ShmPutImage; ev.majorEvent = ShmReqCode; ev.shmseg = stuff->shmseg; diff --git a/xorg-server/Xext/sync.c b/xorg-server/Xext/sync.c index d46087a68..8eb228bf1 100644 --- a/xorg-server/Xext/sync.c +++ b/xorg-server/Xext/sync.c @@ -1,2399 +1,2394 @@ -/* - -Copyright 1991, 1993, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall -not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization -from The Open Group. - - -Copyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts, -and Olivetti Research Limited, Cambridge, England. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the names of Digital or Olivetti -not be used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. Digital and Olivetti -make no representations about the suitability of this software -for any purpose. It is provided "as is" without express or implied warranty. - -DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR -CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF -USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. - -*/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include - -#include -#include -#include -#include "misc.h" -#include "os.h" -#include "extnsionst.h" -#include "dixstruct.h" -#include "resource.h" -#include "opaque.h" -#include -#include "syncsrv.h" - -#include -#if !defined(WIN32) -#include -#endif - -#include "modinit.h" - -/* - * Local Global Variables - */ -static int SyncEventBase; -static int SyncErrorBase; -static RESTYPE RTCounter = 0; -static RESTYPE RTAwait; -static RESTYPE RTAlarm; -static RESTYPE RTAlarmClient; -static int SyncNumSystemCounters = 0; -static SyncCounter **SysCounterList = NULL; - -#define IsSystemCounter(pCounter) \ - (pCounter && (pCounter->client == NULL)) - -/* these are all the alarm attributes that pertain to the alarm's trigger */ -#define XSyncCAAllTrigger \ - (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType) - -static void SyncComputeBracketValues(SyncCounter *); - -static void SyncInitServerTime(void); - -static void SyncInitIdleTime(void); - -static DISPATCH_PROC(ProcSyncAwait); -static DISPATCH_PROC(ProcSyncChangeAlarm); -static DISPATCH_PROC(ProcSyncChangeCounter); -static DISPATCH_PROC(ProcSyncCreateAlarm); -static DISPATCH_PROC(ProcSyncCreateCounter); -static DISPATCH_PROC(ProcSyncDestroyAlarm); -static DISPATCH_PROC(ProcSyncDestroyCounter); -static DISPATCH_PROC(ProcSyncDispatch); -static DISPATCH_PROC(ProcSyncGetPriority); -static DISPATCH_PROC(ProcSyncInitialize); -static DISPATCH_PROC(ProcSyncListSystemCounters); -static DISPATCH_PROC(ProcSyncQueryAlarm); -static DISPATCH_PROC(ProcSyncQueryCounter); -static DISPATCH_PROC(ProcSyncSetCounter); -static DISPATCH_PROC(ProcSyncSetPriority); -static DISPATCH_PROC(SProcSyncAwait); -static DISPATCH_PROC(SProcSyncChangeAlarm); -static DISPATCH_PROC(SProcSyncChangeCounter); -static DISPATCH_PROC(SProcSyncCreateAlarm); -static DISPATCH_PROC(SProcSyncCreateCounter); -static DISPATCH_PROC(SProcSyncDestroyAlarm); -static DISPATCH_PROC(SProcSyncDestroyCounter); -static DISPATCH_PROC(SProcSyncDispatch); -static DISPATCH_PROC(SProcSyncGetPriority); -static DISPATCH_PROC(SProcSyncInitialize); -static DISPATCH_PROC(SProcSyncListSystemCounters); -static DISPATCH_PROC(SProcSyncQueryAlarm); -static DISPATCH_PROC(SProcSyncQueryCounter); -static DISPATCH_PROC(SProcSyncSetCounter); -static DISPATCH_PROC(SProcSyncSetPriority); - -/* Each counter maintains a simple linked list of triggers that are - * interested in the counter. The two functions below are used to - * delete and add triggers on this list. - */ -static void -SyncDeleteTriggerFromCounter(SyncTrigger *pTrigger) -{ - SyncTriggerList *pCur; - SyncTriggerList *pPrev; - - /* pCounter needs to be stored in pTrigger before calling here. */ - - if (!pTrigger->pCounter) - return; - - pPrev = NULL; - pCur = pTrigger->pCounter->pTriglist; - - while (pCur) - { - if (pCur->pTrigger == pTrigger) - { - if (pPrev) - pPrev->next = pCur->next; - else - pTrigger->pCounter->pTriglist = pCur->next; - - free(pCur); - break; - } - - pPrev = pCur; - pCur = pCur->next; - } - - if (IsSystemCounter(pTrigger->pCounter)) - SyncComputeBracketValues(pTrigger->pCounter); -} - - -static int -SyncAddTriggerToCounter(SyncTrigger *pTrigger) -{ - SyncTriggerList *pCur; - - if (!pTrigger->pCounter) - return Success; - - /* don't do anything if it's already there */ - for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next) - { - if (pCur->pTrigger == pTrigger) - return Success; - } - - if (!(pCur = malloc(sizeof(SyncTriggerList)))) - return BadAlloc; - - pCur->pTrigger = pTrigger; - pCur->next = pTrigger->pCounter->pTriglist; - pTrigger->pCounter->pTriglist = pCur; - - if (IsSystemCounter(pTrigger->pCounter)) - SyncComputeBracketValues(pTrigger->pCounter); - - return Success; -} - - -/* Below are four possible functions that can be plugged into - * pTrigger->CheckTrigger, corresponding to the four possible - * test-types. These functions are called after the counter's - * value changes but are also passed the old counter value - * so they can inspect both the old and new values. - * (PositiveTransition and NegativeTransition need to see both - * pieces of information.) These functions return the truth value - * of the trigger. - * - * All of them include the condition pTrigger->pCounter == NULL. - * This is because the spec says that a trigger with a counter value - * of None is always TRUE. - */ - -static Bool -SyncCheckTriggerPositiveComparison(SyncTrigger *pTrigger, CARD64 oldval) -{ - return (pTrigger->pCounter == NULL || - XSyncValueGreaterOrEqual(pTrigger->pCounter->value, - pTrigger->test_value)); -} - -static Bool -SyncCheckTriggerNegativeComparison(SyncTrigger *pTrigger, CARD64 oldval) -{ - return (pTrigger->pCounter == NULL || - XSyncValueLessOrEqual(pTrigger->pCounter->value, - pTrigger->test_value)); -} - -static Bool -SyncCheckTriggerPositiveTransition(SyncTrigger *pTrigger, CARD64 oldval) -{ - return (pTrigger->pCounter == NULL || - (XSyncValueLessThan(oldval, pTrigger->test_value) && - XSyncValueGreaterOrEqual(pTrigger->pCounter->value, - pTrigger->test_value))); -} - -static Bool -SyncCheckTriggerNegativeTransition(SyncTrigger *pTrigger, CARD64 oldval) -{ - return (pTrigger->pCounter == NULL || - (XSyncValueGreaterThan(oldval, pTrigger->test_value) && - XSyncValueLessOrEqual(pTrigger->pCounter->value, - pTrigger->test_value))); -} - -static int -SyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XSyncCounter counter, - Mask changes) -{ - SyncCounter *pCounter = pTrigger->pCounter; - int rc; - Bool newcounter = FALSE; - - if (changes & XSyncCACounter) - { - if (counter == None) - pCounter = NULL; - else if (Success != (rc = dixLookupResourceByType ((pointer *)&pCounter, - counter, RTCounter, client, DixReadAccess))) - { - client->errorValue = counter; - return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc; - } - if (pCounter != pTrigger->pCounter) - { /* new counter for trigger */ - SyncDeleteTriggerFromCounter(pTrigger); - pTrigger->pCounter = pCounter; - newcounter = TRUE; - } - } - - /* if system counter, ask it what the current value is */ - - if (IsSystemCounter(pCounter)) - { - (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, - &pCounter->value); - } - - if (changes & XSyncCAValueType) - { - if (pTrigger->value_type != XSyncRelative && - pTrigger->value_type != XSyncAbsolute) - { - client->errorValue = pTrigger->value_type; - return BadValue; - } - } - - if (changes & XSyncCATestType) - { - if (pTrigger->test_type != XSyncPositiveTransition && - pTrigger->test_type != XSyncNegativeTransition && - pTrigger->test_type != XSyncPositiveComparison && - pTrigger->test_type != XSyncNegativeComparison) - { - client->errorValue = pTrigger->test_type; - return BadValue; - } - /* select appropriate CheckTrigger function */ - - switch (pTrigger->test_type) - { - case XSyncPositiveTransition: - pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition; - break; - case XSyncNegativeTransition: - pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition; - break; - case XSyncPositiveComparison: - pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison; - break; - case XSyncNegativeComparison: - pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison; - break; - } - } - - if (changes & (XSyncCAValueType | XSyncCAValue)) - { - if (pTrigger->value_type == XSyncAbsolute) - pTrigger->test_value = pTrigger->wait_value; - else /* relative */ - { - Bool overflow; - if (pCounter == NULL) - return BadMatch; - - XSyncValueAdd(&pTrigger->test_value, pCounter->value, - pTrigger->wait_value, &overflow); - if (overflow) - { - client->errorValue = XSyncValueHigh32(pTrigger->wait_value); - return BadValue; - } - } - } - - /* we wait until we're sure there are no errors before registering - * a new counter on a trigger - */ - if (newcounter) - { - if ((rc = SyncAddTriggerToCounter(pTrigger)) != Success) - return rc; - } - else if (IsSystemCounter(pCounter)) - { - SyncComputeBracketValues(pCounter); - } - - return Success; -} - -/* AlarmNotify events happen in response to actions taken on an Alarm or - * the counter used by the alarm. AlarmNotify may be sent to multiple - * clients. The alarm maintains a list of clients interested in events. - */ -static void -SyncSendAlarmNotifyEvents(SyncAlarm *pAlarm) -{ - SyncAlarmClientList *pcl; - xSyncAlarmNotifyEvent ane; - SyncTrigger *pTrigger = &pAlarm->trigger; - - UpdateCurrentTime(); - - ane.type = SyncEventBase + XSyncAlarmNotify; - ane.kind = XSyncAlarmNotify; - ane.sequenceNumber = pAlarm->client->sequence; - ane.alarm = pAlarm->alarm_id; - if (pTrigger->pCounter) - { - ane.counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); - ane.counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); - } - else - { /* XXX what else can we do if there's no counter? */ - ane.counter_value_hi = ane.counter_value_lo = 0; - } - - ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value); - ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value); - ane.time = currentTime.milliseconds; - ane.state = pAlarm->state; - - /* send to owner */ - if (pAlarm->events && !pAlarm->client->clientGone) - WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane); - - /* send to other interested clients */ - for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next) - { - if (!pcl->client->clientGone) - { - ane.sequenceNumber = pcl->client->sequence; - WriteEventsToClient(pcl->client, 1, (xEvent *) &ane); - } - } -} - - -/* CounterNotify events only occur in response to an Await. The events - * go only to the Awaiting client. - */ -static void -SyncSendCounterNotifyEvents(ClientPtr client, SyncAwait **ppAwait, - int num_events) -{ - xSyncCounterNotifyEvent *pEvents, *pev; - int i; - - if (client->clientGone) - return; - pev = pEvents = malloc(num_events * sizeof(xSyncCounterNotifyEvent)); - if (!pEvents) - return; - UpdateCurrentTime(); - for (i = 0; i < num_events; i++, ppAwait++, pev++) - { - SyncTrigger *pTrigger = &(*ppAwait)->trigger; - pev->type = SyncEventBase + XSyncCounterNotify; - pev->kind = XSyncCounterNotify; - pev->sequenceNumber = client->sequence; - pev->counter = pTrigger->pCounter->id; - pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value); - pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value); - pev->counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); - pev->counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); - pev->time = currentTime.milliseconds; - pev->count = num_events - i - 1; /* events remaining */ - pev->destroyed = pTrigger->pCounter->beingDestroyed; - } - /* swapping will be taken care of by this */ - WriteEventsToClient(client, num_events, (xEvent *)pEvents); - free(pEvents); -} - - -/* This function is called when an alarm's counter is destroyed. - * It is plugged into pTrigger->CounterDestroyed (for alarm triggers). - */ -static void -SyncAlarmCounterDestroyed(SyncTrigger *pTrigger) -{ - SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; - - pAlarm->state = XSyncAlarmInactive; - SyncSendAlarmNotifyEvents(pAlarm); - pTrigger->pCounter = NULL; -} - - -/* This function is called when an alarm "goes off." - * It is plugged into pTrigger->TriggerFired (for alarm triggers). - */ -static void -SyncAlarmTriggerFired(SyncTrigger *pTrigger) -{ - SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; - CARD64 new_test_value; - - /* no need to check alarm unless it's active */ - if (pAlarm->state != XSyncAlarmActive) - return; - - /* " if the counter value is None, or if the delta is 0 and - * the test-type is PositiveComparison or NegativeComparison, - * no change is made to value (test-value) and the alarm - * state is changed to Inactive before the event is generated." - */ - if (pAlarm->trigger.pCounter == NULL - || (XSyncValueIsZero(pAlarm->delta) - && (pAlarm->trigger.test_type == XSyncPositiveComparison - || pAlarm->trigger.test_type == XSyncNegativeComparison))) - pAlarm->state = XSyncAlarmInactive; - - new_test_value = pAlarm->trigger.test_value; - - if (pAlarm->state == XSyncAlarmActive) - { - Bool overflow; - CARD64 oldvalue; - SyncTrigger *paTrigger = &pAlarm->trigger; - - /* "The alarm is updated by repeatedly adding delta to the - * value of the trigger and re-initializing it until it - * becomes FALSE." - */ - oldvalue = paTrigger->test_value; - - /* XXX really should do something smarter here */ - - do - { - XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value, - pAlarm->delta, &overflow); - } while (!overflow && - (*paTrigger->CheckTrigger)(paTrigger, - paTrigger->pCounter->value)); - - new_test_value = paTrigger->test_value; - paTrigger->test_value = oldvalue; - - /* "If this update would cause value to fall outside the range - * for an INT64...no change is made to value (test-value) and - * the alarm state is changed to Inactive before the event is - * generated." - */ - if (overflow) - { - new_test_value = oldvalue; - pAlarm->state = XSyncAlarmInactive; - } - } - /* The AlarmNotify event has to have the "new state of the alarm" - * which we can't be sure of until this point. However, it has - * to have the "old" trigger test value. That's the reason for - * all the newvalue/oldvalue shuffling above. After we send the - * events, give the trigger its new test value. - */ - SyncSendAlarmNotifyEvents(pAlarm); - pTrigger->test_value = new_test_value; -} - - -/* This function is called when an Await unblocks, either as a result - * of the trigger firing OR the counter being destroyed. - * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed - * (for Await triggers). - */ -static void -SyncAwaitTriggerFired(SyncTrigger *pTrigger) -{ - SyncAwait *pAwait = (SyncAwait *)pTrigger; - int numwaits; - SyncAwaitUnion *pAwaitUnion; - SyncAwait **ppAwait; - int num_events = 0; - - pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader; - numwaits = pAwaitUnion->header.num_waitconditions; - ppAwait = malloc(numwaits * sizeof(SyncAwait *)); - if (!ppAwait) - goto bail; - - pAwait = &(pAwaitUnion+1)->await; - - /* "When a client is unblocked, all the CounterNotify events for - * the Await request are generated contiguously. If count is 0 - * there are no more events to follow for this request. If - * count is n, there are at least n more events to follow." - * - * Thus, it is best to find all the counters for which events - * need to be sent first, so that an accurate count field can - * be stored in the events. - */ - for ( ; numwaits; numwaits--, pAwait++) - { - CARD64 diff; - Bool overflow, diffgreater, diffequal; - - /* "A CounterNotify event with the destroyed flag set to TRUE is - * always generated if the counter for one of the triggers is - * destroyed." - */ - if (pAwait->trigger.pCounter->beingDestroyed) - { - ppAwait[num_events++] = pAwait; - continue; - } - - /* "The difference between the counter and the test value is - * calculated by subtracting the test value from the value of - * the counter." - */ - XSyncValueSubtract(&diff, pAwait->trigger.pCounter->value, - pAwait->trigger.test_value, &overflow); - - /* "If the difference lies outside the range for an INT64, an - * event is not generated." - */ - if (overflow) - continue; - diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold); - diffequal = XSyncValueEqual(diff, pAwait->event_threshold); - - /* "If the test-type is PositiveTransition or - * PositiveComparison, a CounterNotify event is generated if - * the difference is at least event-threshold. If the test-type - * is NegativeTransition or NegativeComparison, a CounterNotify - * event is generated if the difference is at most - * event-threshold." - */ - - if ( ((pAwait->trigger.test_type == XSyncPositiveComparison || - pAwait->trigger.test_type == XSyncPositiveTransition) - && (diffgreater || diffequal)) - || - ((pAwait->trigger.test_type == XSyncNegativeComparison || - pAwait->trigger.test_type == XSyncNegativeTransition) - && (!diffgreater) /* less or equal */ - ) - ) - { - ppAwait[num_events++] = pAwait; - } - } - if (num_events) - SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait, - num_events); - free(ppAwait); - -bail: - /* unblock the client */ - AttendClient(pAwaitUnion->header.client); - /* delete the await */ - FreeResource(pAwaitUnion->header.delete_id, RT_NONE); -} - - -/* This function should always be used to change a counter's value so that - * any triggers depending on the counter will be checked. - */ -void -SyncChangeCounter(SyncCounter *pCounter, CARD64 newval) -{ - SyncTriggerList *ptl, *pnext; - CARD64 oldval; - - oldval = pCounter->value; - pCounter->value = newval; - - /* run through triggers to see if any become true */ - for (ptl = pCounter->pTriglist; ptl; ptl = pnext) - { - pnext = ptl->next; - if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval)) - (*ptl->pTrigger->TriggerFired)(ptl->pTrigger); - } - - if (IsSystemCounter(pCounter)) - { - SyncComputeBracketValues(pCounter); - } -} - - -/* loosely based on dix/events.c/EventSelectForWindow */ -static Bool -SyncEventSelectForAlarm(SyncAlarm *pAlarm, ClientPtr client, Bool wantevents) -{ - SyncAlarmClientList *pClients; - - if (client == pAlarm->client) /* alarm owner */ - { - pAlarm->events = wantevents; - return Success; - } - - /* see if the client is already on the list (has events selected) */ - - for (pClients = pAlarm->pEventClients; pClients; - pClients = pClients->next) - { - if (pClients->client == client) - { - /* client's presence on the list indicates desire for - * events. If the client doesn't want events, remove it - * from the list. If the client does want events, do - * nothing, since it's already got them. - */ - if (!wantevents) - { - FreeResource(pClients->delete_id, RT_NONE); - } - return Success; - } - } - - /* if we get here, this client does not currently have - * events selected on the alarm - */ - - if (!wantevents) - /* client doesn't want events, and we just discovered that it - * doesn't have them, so there's nothing to do. - */ - return Success; - - /* add new client to pAlarm->pEventClients */ - - pClients = malloc(sizeof(SyncAlarmClientList)); - if (!pClients) - return BadAlloc; - - /* register it as a resource so it will be cleaned up - * if the client dies - */ - - pClients->delete_id = FakeClientID(client->index); - if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm)) - { - free(pClients); - return BadAlloc; - } - - /* link it into list after we know all the allocations succeed */ - - pClients->next = pAlarm->pEventClients; - pAlarm->pEventClients = pClients; - pClients->client = client; - return Success; -} - -/* - * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm - */ -static int -SyncChangeAlarmAttributes(ClientPtr client, SyncAlarm *pAlarm, Mask mask, - CARD32 *values) -{ - int status; - XSyncCounter counter; - Mask origmask = mask; - - counter = pAlarm->trigger.pCounter ? pAlarm->trigger.pCounter->id : None; - - while (mask) - { - int index2 = lowbit(mask); - mask &= ~index2; - switch (index2) - { - case XSyncCACounter: - mask &= ~XSyncCACounter; - /* sanity check in SyncInitTrigger */ - counter = *values++; - break; - - case XSyncCAValueType: - mask &= ~XSyncCAValueType; - /* sanity check in SyncInitTrigger */ - pAlarm->trigger.value_type = *values++; - break; - - case XSyncCAValue: - mask &= ~XSyncCAValue; - XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]); - values += 2; - break; - - case XSyncCATestType: - mask &= ~XSyncCATestType; - /* sanity check in SyncInitTrigger */ - pAlarm->trigger.test_type = *values++; - break; - - case XSyncCADelta: - mask &= ~XSyncCADelta; - XSyncIntsToValue(&pAlarm->delta, values[1], values[0]); - values += 2; - break; - - case XSyncCAEvents: - mask &= ~XSyncCAEvents; - if ((*values != xTrue) && (*values != xFalse)) - { - client->errorValue = *values; - return BadValue; - } - status = SyncEventSelectForAlarm(pAlarm, client, - (Bool)(*values++)); - if (status != Success) - return status; - break; - - default: - client->errorValue = mask; - return BadValue; - } - } - - /* "If the test-type is PositiveComparison or PositiveTransition - * and delta is less than zero, or if the test-type is - * NegativeComparison or NegativeTransition and delta is - * greater than zero, a Match error is generated." - */ - if (origmask & (XSyncCADelta|XSyncCATestType)) - { - CARD64 zero; - XSyncIntToValue(&zero, 0); - if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) || - (pAlarm->trigger.test_type == XSyncPositiveTransition)) - && XSyncValueLessThan(pAlarm->delta, zero)) - || - (((pAlarm->trigger.test_type == XSyncNegativeComparison) || - (pAlarm->trigger.test_type == XSyncNegativeTransition)) - && XSyncValueGreaterThan(pAlarm->delta, zero)) - ) - { - return BadMatch; - } - } - - /* postpone this until now, when we're sure nothing else can go wrong */ - if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter, - origmask & XSyncCAAllTrigger)) != Success) - return status; - - /* XXX spec does not really say to do this - needs clarification */ - pAlarm->state = XSyncAlarmActive; - return Success; -} - - -static SyncCounter * -SyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue) -{ - SyncCounter *pCounter; - - if (!(pCounter = malloc(sizeof(SyncCounter)))) - return NULL; - - if (!AddResource(id, RTCounter, (pointer) pCounter)) - { - free(pCounter); - return NULL; - } - - pCounter->client = client; - pCounter->id = id; - pCounter->value = initialvalue; - pCounter->pTriglist = NULL; - pCounter->beingDestroyed = FALSE; - pCounter->pSysCounterInfo = NULL; - return pCounter; -} - -static int FreeCounter(void *, XID); - -/* - * ***** System Counter utilities - */ - -pointer -SyncCreateSystemCounter( - char *name, - CARD64 initial, - CARD64 resolution, - SyncCounterType counterType, - void (*QueryValue)(pointer /* pCounter */, - CARD64 * /* pValue_return */), - void (*BracketValues)(pointer /* pCounter */, - CARD64 * /* pbracket_less */, - CARD64 * /* pbracket_greater */) - ) -{ - SyncCounter *pCounter; - - SysCounterList = realloc(SysCounterList, - (SyncNumSystemCounters+1)*sizeof(SyncCounter *)); - if (!SysCounterList) - return NULL; - - /* this function may be called before SYNC has been initialized, so we - * have to make sure RTCounter is created. - */ - if (RTCounter == 0) - { - RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter"); - if (RTCounter == 0) - { - return NULL; - } - } - - pCounter = SyncCreateCounter(NULL, FakeClientID(0), initial); - - if (pCounter) - { - SysCounterInfo *psci; - - psci = malloc(sizeof(SysCounterInfo)); - if (!psci) - { - FreeResource(pCounter->id, RT_NONE); - return pCounter; - } - pCounter->pSysCounterInfo = psci; - psci->name = name; - psci->resolution = resolution; - psci->counterType = counterType; - psci->QueryValue = QueryValue; - psci->BracketValues = BracketValues; - XSyncMaxValue(&psci->bracket_greater); - XSyncMinValue(&psci->bracket_less); - SysCounterList[SyncNumSystemCounters++] = pCounter; - } - return pCounter; -} - -void -SyncDestroySystemCounter(pointer pSysCounter) -{ - SyncCounter *pCounter = (SyncCounter *)pSysCounter; - FreeResource(pCounter->id, RT_NONE); -} - -static void -SyncComputeBracketValues(SyncCounter *pCounter) -{ - SyncTriggerList *pCur; - SyncTrigger *pTrigger; - SysCounterInfo *psci; - CARD64 *pnewgtval = NULL; - CARD64 *pnewltval = NULL; - SyncCounterType ct; - - if (!pCounter) - return; - - psci = pCounter->pSysCounterInfo; - ct = pCounter->pSysCounterInfo->counterType; - if (ct == XSyncCounterNeverChanges) - return; - - XSyncMaxValue(&psci->bracket_greater); - XSyncMinValue(&psci->bracket_less); - - for (pCur = pCounter->pTriglist; pCur; pCur = pCur->next) - { - pTrigger = pCur->pTrigger; - - if (pTrigger->test_type == XSyncPositiveComparison && - ct != XSyncCounterNeverIncreases) - { - if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && - XSyncValueLessThan(pTrigger->test_value, - psci->bracket_greater)) - { - psci->bracket_greater = pTrigger->test_value; - pnewgtval = &psci->bracket_greater; - } - } - else if (pTrigger->test_type == XSyncNegativeComparison && - ct != XSyncCounterNeverDecreases) - { - if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && - XSyncValueGreaterThan(pTrigger->test_value, - psci->bracket_less)) - { - psci->bracket_less = pTrigger->test_value; - pnewltval = &psci->bracket_less; - } - } - else if (pTrigger->test_type == XSyncNegativeTransition && - ct != XSyncCounterNeverIncreases) - { - if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && - XSyncValueGreaterThan(pTrigger->test_value, psci->bracket_less)) - { - psci->bracket_less = pTrigger->test_value; - pnewltval = &psci->bracket_less; - } - } - else if (pTrigger->test_type == XSyncPositiveTransition && - ct != XSyncCounterNeverDecreases) - { - if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && - XSyncValueLessThan(pTrigger->test_value, psci->bracket_greater)) - { - psci->bracket_greater = pTrigger->test_value; - pnewgtval = &psci->bracket_greater; - } - } - } /* end for each trigger */ - - if (pnewgtval || pnewltval) - { - (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval); - } -} - -/* - * ***** Resource delete functions - */ - -/* ARGSUSED */ -static int -FreeAlarm(void *addr, XID id) -{ - SyncAlarm *pAlarm = (SyncAlarm *) addr; - - pAlarm->state = XSyncAlarmDestroyed; - - SyncSendAlarmNotifyEvents(pAlarm); - - /* delete event selections */ - - while (pAlarm->pEventClients) - FreeResource(pAlarm->pEventClients->delete_id, RT_NONE); - - SyncDeleteTriggerFromCounter(&pAlarm->trigger); - - free(pAlarm); - return Success; -} - - -/* - * ** Cleanup after the destruction of a Counter - */ -/* ARGSUSED */ -static int -FreeCounter(void *env, XID id) -{ - SyncCounter *pCounter = (SyncCounter *) env; - SyncTriggerList *ptl, *pnext; - - pCounter->beingDestroyed = TRUE; - /* tell all the counter's triggers that the counter has been destroyed */ - for (ptl = pCounter->pTriglist; ptl; ptl = pnext) - { - (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger); - pnext = ptl->next; - free(ptl); /* destroy the trigger list as we go */ - } - if (IsSystemCounter(pCounter)) - { - int i, found = 0; - - free(pCounter->pSysCounterInfo); - - /* find the counter in the list of system counters and remove it */ - - if (SysCounterList) - { - for (i = 0; i < SyncNumSystemCounters; i++) - { - if (SysCounterList[i] == pCounter) - { - found = i; - break; - } - } - if (found < (SyncNumSystemCounters-1)) - { - for (i = found; i < SyncNumSystemCounters-1; i++) - { - SysCounterList[i] = SysCounterList[i+1]; - } - } - } - SyncNumSystemCounters--; - } - free(pCounter); - return Success; -} - -/* - * ** Cleanup after Await - */ -/* ARGSUSED */ -static int -FreeAwait(void *addr, XID id) -{ - SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr; - SyncAwait *pAwait; - int numwaits; - - pAwait = &(pAwaitUnion+1)->await; /* first await on list */ - - /* remove triggers from counters */ - - for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits; - numwaits--, pAwait++) - { - /* If the counter is being destroyed, FreeCounter will delete - * the trigger list itself, so don't do it here. - */ - SyncCounter *pCounter = pAwait->trigger.pCounter; - if (pCounter && !pCounter->beingDestroyed) - SyncDeleteTriggerFromCounter(&pAwait->trigger); - } - free(pAwaitUnion); - return Success; -} - -/* loosely based on dix/events.c/OtherClientGone */ -static int -FreeAlarmClient(void *value, XID id) -{ - SyncAlarm *pAlarm = (SyncAlarm *)value; - SyncAlarmClientList *pCur, *pPrev; - - for (pPrev = NULL, pCur = pAlarm->pEventClients; - pCur; - pPrev = pCur, pCur = pCur->next) - { - if (pCur->delete_id == id) - { - if (pPrev) - pPrev->next = pCur->next; - else - pAlarm->pEventClients = pCur->next; - free(pCur); - return Success; - } - } - FatalError("alarm client not on event list"); - /*NOTREACHED*/ -} - - -/* - * ***** Proc functions - */ - - -/* - * ** Initialize the extension - */ -static int -ProcSyncInitialize(ClientPtr client) -{ - xSyncInitializeReply rep; - int n; - - REQUEST_SIZE_MATCH(xSyncInitializeReq); - - memset(&rep, 0, sizeof(xSyncInitializeReply)); - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.majorVersion = SYNC_MAJOR_VERSION; - rep.minorVersion = SYNC_MINOR_VERSION; - rep.length = 0; - - if (client->swapped) - { - swaps(&rep.sequenceNumber, n); - } - WriteToClient(client, sizeof(rep), (char *) &rep); - return Success; -} - -/* - * ** Get list of system counters available through the extension - */ -static int -ProcSyncListSystemCounters(ClientPtr client) -{ - xSyncListSystemCountersReply rep; - int i, len; - xSyncSystemCounter *list = NULL, *walklist = NULL; - - REQUEST_SIZE_MATCH(xSyncListSystemCountersReq); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.nCounters = SyncNumSystemCounters; - - for (i = len = 0; i < SyncNumSystemCounters; i++) - { - char *name = SysCounterList[i]->pSysCounterInfo->name; - /* pad to 4 byte boundary */ - len += pad_to_int32(sz_xSyncSystemCounter + strlen(name)); - } - - if (len) - { - walklist = list = malloc(len); - if (!list) - return BadAlloc; - } - - rep.length = bytes_to_int32(len); - - if (client->swapped) - { - char n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.nCounters, n); - } - - for (i = 0; i < SyncNumSystemCounters; i++) - { - int namelen; - char *pname_in_reply; - SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo; - - walklist->counter = SysCounterList[i]->id; - walklist->resolution_hi = XSyncValueHigh32(psci->resolution); - walklist->resolution_lo = XSyncValueLow32(psci->resolution); - namelen = strlen(psci->name); - walklist->name_length = namelen; - - if (client->swapped) - { - char n; - swapl(&walklist->counter, n); - swapl(&walklist->resolution_hi, n); - swapl(&walklist->resolution_lo, n); - swaps(&walklist->name_length, n); - } - - pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter; - strncpy(pname_in_reply, psci->name, namelen); - walklist = (xSyncSystemCounter *) (((char *)walklist) + - pad_to_int32(sz_xSyncSystemCounter + namelen)); - } - - WriteToClient(client, sizeof(rep), (char *) &rep); - if (len) - { - WriteToClient(client, len, (char *) list); - free(list); - } - - return Success; -} - -/* - * ** Set client Priority - */ -static int -ProcSyncSetPriority(ClientPtr client) -{ - REQUEST(xSyncSetPriorityReq); - ClientPtr priorityclient; - int rc; - - REQUEST_SIZE_MATCH(xSyncSetPriorityReq); - - if (stuff->id == None) - priorityclient = client; - else { - rc = dixLookupClient(&priorityclient, stuff->id, client, - DixSetAttrAccess); - if (rc != Success) - return rc; - } - - if (priorityclient->priority != stuff->priority) - { - priorityclient->priority = stuff->priority; - - /* The following will force the server back into WaitForSomething - * so that the change in this client's priority is immediately - * reflected. - */ - isItTimeToYield = TRUE; - dispatchException |= DE_PRIORITYCHANGE; - } - return Success; -} - -/* - * ** Get client Priority - */ -static int -ProcSyncGetPriority(ClientPtr client) -{ - REQUEST(xSyncGetPriorityReq); - xSyncGetPriorityReply rep; - ClientPtr priorityclient; - int rc; - - REQUEST_SIZE_MATCH(xSyncGetPriorityReq); - - if (stuff->id == None) - priorityclient = client; - else { - rc = dixLookupClient(&priorityclient, stuff->id, client, - DixGetAttrAccess); - if (rc != Success) - return rc; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.priority = priorityclient->priority; - - if (client->swapped) - { - char n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.priority, n); - } - - WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep); - - return Success; -} - -/* - * ** Create a new counter - */ -static int -ProcSyncCreateCounter(ClientPtr client) -{ - REQUEST(xSyncCreateCounterReq); - CARD64 initial; - - REQUEST_SIZE_MATCH(xSyncCreateCounterReq); - - LEGAL_NEW_RESOURCE(stuff->cid, client); - - XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi); - if (!SyncCreateCounter(client, stuff->cid, initial)) - return BadAlloc; - - return Success; -} - -/* - * ** Set Counter value - */ -static int -ProcSyncSetCounter(ClientPtr client) -{ - REQUEST(xSyncSetCounterReq); - SyncCounter *pCounter; - CARD64 newvalue; - int rc; - - REQUEST_SIZE_MATCH(xSyncSetCounterReq); - - rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter, - client, DixWriteAccess); - if (rc != Success) - return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc; - - if (IsSystemCounter(pCounter)) - { - client->errorValue = stuff->cid; - return BadAccess; - } - - XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); - SyncChangeCounter(pCounter, newvalue); - return Success; -} - -/* - * ** Change Counter value - */ -static int -ProcSyncChangeCounter(ClientPtr client) -{ - REQUEST(xSyncChangeCounterReq); - SyncCounter *pCounter; - CARD64 newvalue; - Bool overflow; - int rc; - - REQUEST_SIZE_MATCH(xSyncChangeCounterReq); - - rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter, - client, DixWriteAccess); - if (rc != Success) - return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc; - - if (IsSystemCounter(pCounter)) - { - client->errorValue = stuff->cid; - return BadAccess; - } - - XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); - XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow); - if (overflow) - { - /* XXX 64 bit value can't fit in 32 bits; do the best we can */ - client->errorValue = stuff->value_hi; - return BadValue; - } - SyncChangeCounter(pCounter, newvalue); - return Success; -} - -/* - * ** Destroy a counter - */ -static int -ProcSyncDestroyCounter(ClientPtr client) -{ - REQUEST(xSyncDestroyCounterReq); - SyncCounter *pCounter; - int rc; - - REQUEST_SIZE_MATCH(xSyncDestroyCounterReq); - - rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, RTCounter, - client, DixDestroyAccess); - if (rc != Success) - return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc; - - if (IsSystemCounter(pCounter)) - { - client->errorValue = stuff->counter; - return BadAccess; - } - FreeResource(pCounter->id, RT_NONE); - return Success; -} - - -/* - * ** Await - */ -static int -ProcSyncAwait(ClientPtr client) -{ - REQUEST(xSyncAwaitReq); - int len, items; - int i; - xSyncWaitCondition *pProtocolWaitConds; - SyncAwaitUnion *pAwaitUnion; - SyncAwait *pAwait; - int status; - - REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); - - len = client->req_len << 2; - len -= sz_xSyncAwaitReq; - items = len / sz_xSyncWaitCondition; - - if (items * sz_xSyncWaitCondition != len) - { - return BadLength; - } - if (items == 0) - { - client->errorValue = items; /* XXX protocol change */ - return BadValue; - } - - pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1]; - - /* all the memory for the entire await list is allocated - * here in one chunk - */ - pAwaitUnion = malloc((items+1) * sizeof(SyncAwaitUnion)); - if (!pAwaitUnion) - return BadAlloc; - - /* first item is the header, remainder are real wait conditions */ - - pAwaitUnion->header.delete_id = FakeClientID(client->index); - if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion)) - { - free(pAwaitUnion); - return BadAlloc; - } - - /* don't need to do any more memory allocation for this request! */ - - pAwaitUnion->header.client = client; - pAwaitUnion->header.num_waitconditions = 0; - - pAwait = &(pAwaitUnion+1)->await; /* skip over header */ - for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++) - { - if (pProtocolWaitConds->counter == None) /* XXX protocol change */ - { - /* this should take care of removing any triggers created by - * this request that have already been registered on counters - */ - FreeResource(pAwaitUnion->header.delete_id, RT_NONE); - client->errorValue = pProtocolWaitConds->counter; - return SyncErrorBase + XSyncBadCounter; - } - - /* sanity checks are in SyncInitTrigger */ - pAwait->trigger.pCounter = NULL; - pAwait->trigger.value_type = pProtocolWaitConds->value_type; - XSyncIntsToValue(&pAwait->trigger.wait_value, - pProtocolWaitConds->wait_value_lo, - pProtocolWaitConds->wait_value_hi); - pAwait->trigger.test_type = pProtocolWaitConds->test_type; - - status = SyncInitTrigger(client, &pAwait->trigger, - pProtocolWaitConds->counter, XSyncCAAllTrigger); - if (status != Success) - { - /* this should take care of removing any triggers created by - * this request that have already been registered on counters - */ - FreeResource(pAwaitUnion->header.delete_id, RT_NONE); - return status; - } - /* this is not a mistake -- same function works for both cases */ - pAwait->trigger.TriggerFired = SyncAwaitTriggerFired; - pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired; - XSyncIntsToValue(&pAwait->event_threshold, - pProtocolWaitConds->event_threshold_lo, - pProtocolWaitConds->event_threshold_hi); - pAwait->pHeader = &pAwaitUnion->header; - pAwaitUnion->header.num_waitconditions++; - } - - IgnoreClient(client); - - /* see if any of the triggers are already true */ - - pAwait = &(pAwaitUnion+1)->await; /* skip over header */ - for (i = 0; i < items; i++, pAwait++) - { - /* don't have to worry about NULL counters because the request - * errors before we get here out if they occur - */ - if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, - pAwait->trigger.pCounter->value)) - { - (*pAwait->trigger.TriggerFired)(&pAwait->trigger); - break; /* once is enough */ - } - } - return Success; -} - - -/* - * ** Query a counter - */ -static int -ProcSyncQueryCounter(ClientPtr client) -{ - REQUEST(xSyncQueryCounterReq); - xSyncQueryCounterReply rep; - SyncCounter *pCounter; - int rc; - - REQUEST_SIZE_MATCH(xSyncQueryCounterReq); - - rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, - RTCounter, client, DixReadAccess); - if (rc != Success) - return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - /* if system counter, ask it what the current value is */ - - if (IsSystemCounter(pCounter)) - { - (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, - &pCounter->value); - } - - rep.value_hi = XSyncValueHigh32(pCounter->value); - rep.value_lo = XSyncValueLow32(pCounter->value); - if (client->swapped) - { - char n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.value_hi, n); - swapl(&rep.value_lo, n); - } - WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep); - return Success; -} - - -/* - * ** Create Alarm - */ -static int -ProcSyncCreateAlarm(ClientPtr client) -{ - REQUEST(xSyncCreateAlarmReq); - SyncAlarm *pAlarm; - int status; - unsigned long len, vmask; - SyncTrigger *pTrigger; - - REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); - - LEGAL_NEW_RESOURCE(stuff->id, client); - - vmask = stuff->valueMask; - len = client->req_len - bytes_to_int32(sizeof(xSyncCreateAlarmReq)); - /* the "extra" call to Ones accounts for the presence of 64 bit values */ - if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) - return BadLength; - - if (!(pAlarm = malloc(sizeof(SyncAlarm)))) - { - return BadAlloc; - } - - /* set up defaults */ - - pTrigger = &pAlarm->trigger; - pTrigger->pCounter = NULL; - pTrigger->value_type = XSyncAbsolute; - XSyncIntToValue(&pTrigger->wait_value, 0L); - pTrigger->test_type = XSyncPositiveComparison; - pTrigger->TriggerFired = SyncAlarmTriggerFired; - pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed; - status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger); - if (status != Success) - { - free(pAlarm); - return status; - } - - pAlarm->client = client; - pAlarm->alarm_id = stuff->id; - XSyncIntToValue(&pAlarm->delta, 1L); - pAlarm->events = TRUE; - pAlarm->state = XSyncAlarmInactive; - pAlarm->pEventClients = NULL; - status = SyncChangeAlarmAttributes(client, pAlarm, vmask, - (CARD32 *)&stuff[1]); - if (status != Success) - { - free(pAlarm); - return status; - } - - if (!AddResource(stuff->id, RTAlarm, pAlarm)) - { - free(pAlarm); - return BadAlloc; - } - - /* see if alarm already triggered. NULL counter will not trigger - * in CreateAlarm and sets alarm state to Inactive. - */ - - if (!pTrigger->pCounter) - { - pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */ - } - else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value)) - { - (*pTrigger->TriggerFired)(pTrigger); - } - - return Success; -} - -/* - * ** Change Alarm - */ -static int -ProcSyncChangeAlarm(ClientPtr client) -{ - REQUEST(xSyncChangeAlarmReq); - SyncAlarm *pAlarm; - long vmask; - int len, status; - - REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); - - status = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, - client, DixWriteAccess); - if (status != Success) - return (status == BadValue) ? SyncErrorBase + XSyncBadAlarm : status; - - vmask = stuff->valueMask; - len = client->req_len - bytes_to_int32(sizeof(xSyncChangeAlarmReq)); - /* the "extra" call to Ones accounts for the presence of 64 bit values */ - if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) - return BadLength; - - if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask, - (CARD32 *)&stuff[1])) != Success) - return status; - - /* see if alarm already triggered. NULL counter WILL trigger - * in ChangeAlarm. - */ - - if (!pAlarm->trigger.pCounter || - (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger, - pAlarm->trigger.pCounter->value)) - { - (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger); - } - return Success; -} - -static int -ProcSyncQueryAlarm(ClientPtr client) -{ - REQUEST(xSyncQueryAlarmReq); - SyncAlarm *pAlarm; - xSyncQueryAlarmReply rep; - SyncTrigger *pTrigger; - int rc; - - REQUEST_SIZE_MATCH(xSyncQueryAlarmReq); - - rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, - client, DixReadAccess); - if (rc != Success) - return (rc == BadValue) ? SyncErrorBase + XSyncBadAlarm : rc; - - rep.type = X_Reply; - rep.length = bytes_to_int32(sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)); - rep.sequenceNumber = client->sequence; - - pTrigger = &pAlarm->trigger; - rep.counter = (pTrigger->pCounter) ? pTrigger->pCounter->id : None; - -#if 0 /* XXX unclear what to do, depends on whether relative value-types - * are "consumed" immediately and are considered absolute from then - * on. - */ - rep.value_type = pTrigger->value_type; - rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value); - rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value); -#else - rep.value_type = XSyncAbsolute; - rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value); - rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value); -#endif - - rep.test_type = pTrigger->test_type; - rep.delta_hi = XSyncValueHigh32(pAlarm->delta); - rep.delta_lo = XSyncValueLow32(pAlarm->delta); - rep.events = pAlarm->events; - rep.state = pAlarm->state; - - if (client->swapped) - { - char n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.counter, n); - swapl(&rep.wait_value_hi, n); - swapl(&rep.wait_value_lo, n); - swapl(&rep.test_type, n); - swapl(&rep.delta_hi, n); - swapl(&rep.delta_lo, n); - } - - WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep); - return Success; -} - -static int -ProcSyncDestroyAlarm(ClientPtr client) -{ - SyncAlarm *pAlarm; - int rc; - REQUEST(xSyncDestroyAlarmReq); - - REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq); - - rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, - client, DixDestroyAccess); - if (rc != Success) - return (rc == BadValue) ? SyncErrorBase + XSyncBadAlarm : rc; - - FreeResource(stuff->alarm, RT_NONE); - return Success; -} - -/* - * ** Given an extension request, call the appropriate request procedure - */ -static int -ProcSyncDispatch(ClientPtr client) -{ - REQUEST(xReq); - - switch (stuff->data) - { - case X_SyncInitialize: - return ProcSyncInitialize(client); - case X_SyncListSystemCounters: - return ProcSyncListSystemCounters(client); - case X_SyncCreateCounter: - return ProcSyncCreateCounter(client); - case X_SyncSetCounter: - return ProcSyncSetCounter(client); - case X_SyncChangeCounter: - return ProcSyncChangeCounter(client); - case X_SyncQueryCounter: - return ProcSyncQueryCounter(client); - case X_SyncDestroyCounter: - return ProcSyncDestroyCounter(client); - case X_SyncAwait: - return ProcSyncAwait(client); - case X_SyncCreateAlarm: - return ProcSyncCreateAlarm(client); - case X_SyncChangeAlarm: - return ProcSyncChangeAlarm(client); - case X_SyncQueryAlarm: - return ProcSyncQueryAlarm(client); - case X_SyncDestroyAlarm: - return ProcSyncDestroyAlarm(client); - case X_SyncSetPriority: - return ProcSyncSetPriority(client); - case X_SyncGetPriority: - return ProcSyncGetPriority(client); - default: - return BadRequest; - } -} - -/* - * Boring Swapping stuff ... - */ - -static int -SProcSyncInitialize(ClientPtr client) -{ - REQUEST(xSyncInitializeReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncInitializeReq); - - return ProcSyncInitialize(client); -} - -static int -SProcSyncListSystemCounters(ClientPtr client) -{ - REQUEST(xSyncListSystemCountersReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncListSystemCountersReq); - - return ProcSyncListSystemCounters(client); -} - -static int -SProcSyncCreateCounter(ClientPtr client) -{ - REQUEST(xSyncCreateCounterReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncCreateCounterReq); - swapl(&stuff->cid, n); - swapl(&stuff->initial_value_lo, n); - swapl(&stuff->initial_value_hi, n); - - return ProcSyncCreateCounter(client); -} - -static int -SProcSyncSetCounter(ClientPtr client) -{ - REQUEST(xSyncSetCounterReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncSetCounterReq); - swapl(&stuff->cid, n); - swapl(&stuff->value_lo, n); - swapl(&stuff->value_hi, n); - - return ProcSyncSetCounter(client); -} - -static int -SProcSyncChangeCounter(ClientPtr client) -{ - REQUEST(xSyncChangeCounterReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncChangeCounterReq); - swapl(&stuff->cid, n); - swapl(&stuff->value_lo, n); - swapl(&stuff->value_hi, n); - - return ProcSyncChangeCounter(client); -} - -static int -SProcSyncQueryCounter(ClientPtr client) -{ - REQUEST(xSyncQueryCounterReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncQueryCounterReq); - swapl(&stuff->counter, n); - - return ProcSyncQueryCounter(client); -} - -static int -SProcSyncDestroyCounter(ClientPtr client) -{ - REQUEST(xSyncDestroyCounterReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncDestroyCounterReq); - swapl(&stuff->counter, n); - - return ProcSyncDestroyCounter(client); -} - -static int -SProcSyncAwait(ClientPtr client) -{ - REQUEST(xSyncAwaitReq); - char n; - - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); - SwapRestL(stuff); - - return ProcSyncAwait(client); -} - -static int -SProcSyncCreateAlarm(ClientPtr client) -{ - REQUEST(xSyncCreateAlarmReq); - char n; - - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); - swapl(&stuff->id, n); - swapl(&stuff->valueMask, n); - SwapRestL(stuff); - - return ProcSyncCreateAlarm(client); -} - -static int -SProcSyncChangeAlarm(ClientPtr client) -{ - REQUEST(xSyncChangeAlarmReq); - char n; - - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); - swapl(&stuff->alarm, n); - swapl(&stuff->valueMask, n); - SwapRestL(stuff); - return ProcSyncChangeAlarm(client); -} - -static int -SProcSyncQueryAlarm(ClientPtr client) -{ - REQUEST(xSyncQueryAlarmReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncQueryAlarmReq); - swapl(&stuff->alarm, n); - - return ProcSyncQueryAlarm(client); -} - -static int -SProcSyncDestroyAlarm(ClientPtr client) -{ - REQUEST(xSyncDestroyAlarmReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq); - swapl(&stuff->alarm, n); - - return ProcSyncDestroyAlarm(client); -} - -static int -SProcSyncSetPriority(ClientPtr client) -{ - REQUEST(xSyncSetPriorityReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncSetPriorityReq); - swapl(&stuff->id, n); - swapl(&stuff->priority, n); - - return ProcSyncSetPriority(client); -} - -static int -SProcSyncGetPriority(ClientPtr client) -{ - REQUEST(xSyncGetPriorityReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncGetPriorityReq); - swapl(&stuff->id, n); - - return ProcSyncGetPriority(client); -} - - -static int -SProcSyncDispatch(ClientPtr client) -{ - REQUEST(xReq); - - switch (stuff->data) - { - case X_SyncInitialize: - return SProcSyncInitialize(client); - case X_SyncListSystemCounters: - return SProcSyncListSystemCounters(client); - case X_SyncCreateCounter: - return SProcSyncCreateCounter(client); - case X_SyncSetCounter: - return SProcSyncSetCounter(client); - case X_SyncChangeCounter: - return SProcSyncChangeCounter(client); - case X_SyncQueryCounter: - return SProcSyncQueryCounter(client); - case X_SyncDestroyCounter: - return SProcSyncDestroyCounter(client); - case X_SyncAwait: - return SProcSyncAwait(client); - case X_SyncCreateAlarm: - return SProcSyncCreateAlarm(client); - case X_SyncChangeAlarm: - return SProcSyncChangeAlarm(client); - case X_SyncQueryAlarm: - return SProcSyncQueryAlarm(client); - case X_SyncDestroyAlarm: - return SProcSyncDestroyAlarm(client); - case X_SyncSetPriority: - return SProcSyncSetPriority(client); - case X_SyncGetPriority: - return SProcSyncGetPriority(client); - default: - return BadRequest; - } -} - -/* - * Event Swapping - */ - -static void -SCounterNotifyEvent(xSyncCounterNotifyEvent *from, xSyncCounterNotifyEvent *to) -{ - to->type = from->type; - to->kind = from->kind; - cpswaps(from->sequenceNumber, to->sequenceNumber); - cpswapl(from->counter, to->counter); - cpswapl(from->wait_value_lo, to->wait_value_lo); - cpswapl(from->wait_value_hi, to->wait_value_hi); - cpswapl(from->counter_value_lo, to->counter_value_lo); - cpswapl(from->counter_value_hi, to->counter_value_hi); - cpswapl(from->time, to->time); - cpswaps(from->count, to->count); - to->destroyed = from->destroyed; -} - - -static void -SAlarmNotifyEvent(xSyncAlarmNotifyEvent *from, xSyncAlarmNotifyEvent *to) -{ - to->type = from->type; - to->kind = from->kind; - cpswaps(from->sequenceNumber, to->sequenceNumber); - cpswapl(from->alarm, to->alarm); - cpswapl(from->counter_value_lo, to->counter_value_lo); - cpswapl(from->counter_value_hi, to->counter_value_hi); - cpswapl(from->alarm_value_lo, to->alarm_value_lo); - cpswapl(from->alarm_value_hi, to->alarm_value_hi); - cpswapl(from->time, to->time); - to->state = from->state; -} - -/* - * ** Close everything down. ** This is fairly simple for now. - */ -/* ARGSUSED */ -static void -SyncResetProc(ExtensionEntry *extEntry) -{ - free(SysCounterList); - SysCounterList = NULL; - RTCounter = 0; -} - - -/* - * ** Initialise the extension. - */ -void -SyncExtensionInit(void) -{ - ExtensionEntry *extEntry; - - if (RTCounter == 0) - { - RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter"); - } - RTAlarm = CreateNewResourceType(FreeAlarm, "SyncAlarm"); - RTAwait = CreateNewResourceType(FreeAwait, "SyncAwait"); - if (RTAwait) - RTAwait |= RC_NEVERRETAIN; - RTAlarmClient = CreateNewResourceType(FreeAlarmClient, "SyncAlarmClient"); - if (RTAlarmClient) - RTAlarmClient |= RC_NEVERRETAIN; - - if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 || - RTAlarmClient == 0 || - (extEntry = AddExtension(SYNC_NAME, - XSyncNumberEvents, XSyncNumberErrors, - ProcSyncDispatch, SProcSyncDispatch, - SyncResetProc, - StandardMinorOpcode)) == NULL) - { - ErrorF("Sync Extension %d.%d failed to Initialise\n", - SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); - return; - } - - SyncEventBase = extEntry->eventBase; - SyncErrorBase = extEntry->errorBase; - EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent; - EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent; - - /* - * Although SERVERTIME is implemented by the OS layer, we initialise it - * here because doing it in OsInit() is too early. The resource database - * is not initialised when OsInit() is called. This is just about OK - * because there is always a servertime counter. - */ - SyncInitServerTime(); - SyncInitIdleTime(); - -#ifdef DEBUG - fprintf(stderr, "Sync Extension %d.%d\n", - SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); -#endif -} - - -/* - * ***** SERVERTIME implementation - should go in its own file in OS directory? - */ - - - -static pointer ServertimeCounter; -static XSyncValue Now; -static XSyncValue *pnext_time; - -#define GetTime()\ -{\ - unsigned long millis = GetTimeInMillis();\ - unsigned long maxis = XSyncValueHigh32(Now);\ - if (millis < XSyncValueLow32(Now)) maxis++;\ - XSyncIntsToValue(&Now, millis, maxis);\ -} - -/* -*** Server Block Handler -*** code inspired by multibuffer extension (now deprecated) - */ -/*ARGSUSED*/ -static void -ServertimeBlockHandler(void *env, struct timeval **wt, void *LastSelectMask) -{ - XSyncValue delay; - unsigned long timeout; - - if (pnext_time) - { - GetTime(); - - if (XSyncValueGreaterOrEqual(Now, *pnext_time)) - { - timeout = 0; - } - else - { - Bool overflow; - XSyncValueSubtract(&delay, *pnext_time, Now, &overflow); - (void)overflow; - timeout = XSyncValueLow32(delay); - } - AdjustWaitForDelay(wt, timeout); /* os/utils.c */ - } -} - -/* -*** Wakeup Handler - */ -/*ARGSUSED*/ -static void -ServertimeWakeupHandler(void *env, int rc, void *LastSelectMask) -{ - if (pnext_time) - { - GetTime(); - - if (XSyncValueGreaterOrEqual(Now, *pnext_time)) - { - SyncChangeCounter(ServertimeCounter, Now); - } - } -} - -static void -ServertimeQueryValue(void *pCounter, CARD64 *pValue_return) -{ - GetTime(); - *pValue_return = Now; -} - -static void -ServertimeBracketValues(void *pCounter, CARD64 *pbracket_less, - CARD64 *pbracket_greater) -{ - if (!pnext_time && pbracket_greater) - { - RegisterBlockAndWakeupHandlers(ServertimeBlockHandler, - ServertimeWakeupHandler, - NULL); - } - else if (pnext_time && !pbracket_greater) - { - RemoveBlockAndWakeupHandlers(ServertimeBlockHandler, - ServertimeWakeupHandler, - NULL); - } - pnext_time = pbracket_greater; -} - -static void -SyncInitServerTime(void) -{ - CARD64 resolution; - - XSyncIntsToValue(&Now, GetTimeInMillis(), 0); - XSyncIntToValue(&resolution, 4); - ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution, - XSyncCounterNeverDecreases, - ServertimeQueryValue, ServertimeBracketValues); - pnext_time = NULL; -} - - - -/* - * IDLETIME implementation - */ - -static SyncCounter *IdleTimeCounter; -static XSyncValue *pIdleTimeValueLess; -static XSyncValue *pIdleTimeValueGreater; - -static void -IdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return) -{ - CARD32 idle = GetTimeInMillis() - lastDeviceEventTime.milliseconds; - XSyncIntsToValue (pValue_return, idle, 0); -} - -static void -IdleTimeBlockHandler(pointer env, struct timeval **wt, pointer LastSelectMask) -{ - XSyncValue idle, old_idle; - SyncTriggerList *list = IdleTimeCounter->pTriglist; - SyncTrigger *trig; - - if (!pIdleTimeValueLess && !pIdleTimeValueGreater) - return; - - old_idle = IdleTimeCounter->value; - IdleTimeQueryValue (NULL, &idle); - IdleTimeCounter->value = idle; /* push, so CheckTrigger works */ - - if (pIdleTimeValueLess && - XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)) - { - /* - * We've been idle for less than the threshold value, and someone - * wants to know about that, but now we need to know whether they - * want level or edge trigger. Check the trigger list against the - * current idle time, and if any succeed, bomb out of select() - * immediately so we can reschedule. - */ - - for (list = IdleTimeCounter->pTriglist; list; list = list->next) { - trig = list->pTrigger; - if (trig->CheckTrigger(trig, old_idle)) { - AdjustWaitForDelay(wt, 0); - break; - } - } - } - else if (pIdleTimeValueGreater) - { - /* - * There's a threshold in the positive direction. If we've been - * idle less than it, schedule a wakeup for sometime in the future. - * If we've been idle more than it, and someone wants to know about - * that level-triggered, schedule an immediate wakeup. - */ - unsigned long timeout = -1; - - if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) { - XSyncValue value; - Bool overflow; - - XSyncValueSubtract (&value, *pIdleTimeValueGreater, - idle, &overflow); - timeout = min(timeout, XSyncValueLow32 (value)); - } else { - for (list = IdleTimeCounter->pTriglist; list; list = list->next) { - trig = list->pTrigger; - if (trig->CheckTrigger(trig, old_idle)) { - timeout = min(timeout, 0); - break; - } - } - } - - AdjustWaitForDelay (wt, timeout); - } - - IdleTimeCounter->value = old_idle; /* pop */ -} - -static void -IdleTimeWakeupHandler (pointer env, int rc, pointer LastSelectMask) -{ - XSyncValue idle; - - if (!pIdleTimeValueLess && !pIdleTimeValueGreater) - return; - - IdleTimeQueryValue (NULL, &idle); - - if ((pIdleTimeValueGreater && - XSyncValueGreaterOrEqual (idle, *pIdleTimeValueGreater)) || - (pIdleTimeValueLess && - XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))) - { - SyncChangeCounter (IdleTimeCounter, idle); - } -} - -static void -IdleTimeBracketValues (pointer pCounter, CARD64 *pbracket_less, - CARD64 *pbracket_greater) -{ - Bool registered = (pIdleTimeValueLess || pIdleTimeValueGreater); - - if (registered && !pbracket_less && !pbracket_greater) - { - RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler, - IdleTimeWakeupHandler, - NULL); - } - else if (!registered && (pbracket_less || pbracket_greater)) - { - RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler, - IdleTimeWakeupHandler, - NULL); - } - - pIdleTimeValueGreater = pbracket_greater; - pIdleTimeValueLess = pbracket_less; -} - -static void -SyncInitIdleTime (void) -{ - CARD64 resolution; - XSyncValue idle; - - IdleTimeQueryValue (NULL, &idle); - XSyncIntToValue (&resolution, 4); - - IdleTimeCounter = SyncCreateSystemCounter ("IDLETIME", idle, resolution, - XSyncCounterUnrestricted, - IdleTimeQueryValue, - IdleTimeBracketValues); - - pIdleTimeValueLess = pIdleTimeValueGreater = NULL; -} +/* + +Copyright 1991, 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts, +and Olivetti Research Limited, Cambridge, England. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital or Olivetti +not be used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. Digital and Olivetti +make no representations about the suitability of this software +for any purpose. It is provided "as is" without express or implied warranty. + +DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include "misc.h" +#include "os.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#include +#include "syncsrv.h" + +#include +#if !defined(WIN32) +#include +#endif + +#include "modinit.h" + +/* + * Local Global Variables + */ +static int SyncEventBase; +static int SyncErrorBase; +static RESTYPE RTCounter = 0; +static RESTYPE RTAwait; +static RESTYPE RTAlarm; +static RESTYPE RTAlarmClient; +static int SyncNumSystemCounters = 0; +static SyncCounter **SysCounterList = NULL; + +#define IsSystemCounter(pCounter) \ + (pCounter && (pCounter->client == NULL)) + +/* these are all the alarm attributes that pertain to the alarm's trigger */ +#define XSyncCAAllTrigger \ + (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType) + +static void SyncComputeBracketValues(SyncCounter *); + +static void SyncInitServerTime(void); + +static void SyncInitIdleTime(void); + +static DISPATCH_PROC(ProcSyncAwait); +static DISPATCH_PROC(ProcSyncChangeAlarm); +static DISPATCH_PROC(ProcSyncChangeCounter); +static DISPATCH_PROC(ProcSyncCreateAlarm); +static DISPATCH_PROC(ProcSyncCreateCounter); +static DISPATCH_PROC(ProcSyncDestroyAlarm); +static DISPATCH_PROC(ProcSyncDestroyCounter); +static DISPATCH_PROC(ProcSyncDispatch); +static DISPATCH_PROC(ProcSyncGetPriority); +static DISPATCH_PROC(ProcSyncInitialize); +static DISPATCH_PROC(ProcSyncListSystemCounters); +static DISPATCH_PROC(ProcSyncQueryAlarm); +static DISPATCH_PROC(ProcSyncQueryCounter); +static DISPATCH_PROC(ProcSyncSetCounter); +static DISPATCH_PROC(ProcSyncSetPriority); +static DISPATCH_PROC(SProcSyncAwait); +static DISPATCH_PROC(SProcSyncChangeAlarm); +static DISPATCH_PROC(SProcSyncChangeCounter); +static DISPATCH_PROC(SProcSyncCreateAlarm); +static DISPATCH_PROC(SProcSyncCreateCounter); +static DISPATCH_PROC(SProcSyncDestroyAlarm); +static DISPATCH_PROC(SProcSyncDestroyCounter); +static DISPATCH_PROC(SProcSyncDispatch); +static DISPATCH_PROC(SProcSyncGetPriority); +static DISPATCH_PROC(SProcSyncInitialize); +static DISPATCH_PROC(SProcSyncListSystemCounters); +static DISPATCH_PROC(SProcSyncQueryAlarm); +static DISPATCH_PROC(SProcSyncQueryCounter); +static DISPATCH_PROC(SProcSyncSetCounter); +static DISPATCH_PROC(SProcSyncSetPriority); + +/* Each counter maintains a simple linked list of triggers that are + * interested in the counter. The two functions below are used to + * delete and add triggers on this list. + */ +static void +SyncDeleteTriggerFromCounter(SyncTrigger *pTrigger) +{ + SyncTriggerList *pCur; + SyncTriggerList *pPrev; + + /* pCounter needs to be stored in pTrigger before calling here. */ + + if (!pTrigger->pCounter) + return; + + pPrev = NULL; + pCur = pTrigger->pCounter->pTriglist; + + while (pCur) + { + if (pCur->pTrigger == pTrigger) + { + if (pPrev) + pPrev->next = pCur->next; + else + pTrigger->pCounter->pTriglist = pCur->next; + + free(pCur); + break; + } + + pPrev = pCur; + pCur = pCur->next; + } + + if (IsSystemCounter(pTrigger->pCounter)) + SyncComputeBracketValues(pTrigger->pCounter); +} + + +static int +SyncAddTriggerToCounter(SyncTrigger *pTrigger) +{ + SyncTriggerList *pCur; + + if (!pTrigger->pCounter) + return Success; + + /* don't do anything if it's already there */ + for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next) + { + if (pCur->pTrigger == pTrigger) + return Success; + } + + if (!(pCur = malloc(sizeof(SyncTriggerList)))) + return BadAlloc; + + pCur->pTrigger = pTrigger; + pCur->next = pTrigger->pCounter->pTriglist; + pTrigger->pCounter->pTriglist = pCur; + + if (IsSystemCounter(pTrigger->pCounter)) + SyncComputeBracketValues(pTrigger->pCounter); + + return Success; +} + + +/* Below are four possible functions that can be plugged into + * pTrigger->CheckTrigger, corresponding to the four possible + * test-types. These functions are called after the counter's + * value changes but are also passed the old counter value + * so they can inspect both the old and new values. + * (PositiveTransition and NegativeTransition need to see both + * pieces of information.) These functions return the truth value + * of the trigger. + * + * All of them include the condition pTrigger->pCounter == NULL. + * This is because the spec says that a trigger with a counter value + * of None is always TRUE. + */ + +static Bool +SyncCheckTriggerPositiveComparison(SyncTrigger *pTrigger, CARD64 oldval) +{ + return (pTrigger->pCounter == NULL || + XSyncValueGreaterOrEqual(pTrigger->pCounter->value, + pTrigger->test_value)); +} + +static Bool +SyncCheckTriggerNegativeComparison(SyncTrigger *pTrigger, CARD64 oldval) +{ + return (pTrigger->pCounter == NULL || + XSyncValueLessOrEqual(pTrigger->pCounter->value, + pTrigger->test_value)); +} + +static Bool +SyncCheckTriggerPositiveTransition(SyncTrigger *pTrigger, CARD64 oldval) +{ + return (pTrigger->pCounter == NULL || + (XSyncValueLessThan(oldval, pTrigger->test_value) && + XSyncValueGreaterOrEqual(pTrigger->pCounter->value, + pTrigger->test_value))); +} + +static Bool +SyncCheckTriggerNegativeTransition(SyncTrigger *pTrigger, CARD64 oldval) +{ + return (pTrigger->pCounter == NULL || + (XSyncValueGreaterThan(oldval, pTrigger->test_value) && + XSyncValueLessOrEqual(pTrigger->pCounter->value, + pTrigger->test_value))); +} + +static int +SyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XSyncCounter counter, + Mask changes) +{ + SyncCounter *pCounter = pTrigger->pCounter; + int rc; + Bool newcounter = FALSE; + + if (changes & XSyncCACounter) + { + if (counter == None) + pCounter = NULL; + else if (Success != (rc = dixLookupResourceByType ((pointer *)&pCounter, + counter, RTCounter, client, DixReadAccess))) + { + client->errorValue = counter; + return rc; + } + if (pCounter != pTrigger->pCounter) + { /* new counter for trigger */ + SyncDeleteTriggerFromCounter(pTrigger); + pTrigger->pCounter = pCounter; + newcounter = TRUE; + } + } + + /* if system counter, ask it what the current value is */ + + if (IsSystemCounter(pCounter)) + { + (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, + &pCounter->value); + } + + if (changes & XSyncCAValueType) + { + if (pTrigger->value_type != XSyncRelative && + pTrigger->value_type != XSyncAbsolute) + { + client->errorValue = pTrigger->value_type; + return BadValue; + } + } + + if (changes & XSyncCATestType) + { + if (pTrigger->test_type != XSyncPositiveTransition && + pTrigger->test_type != XSyncNegativeTransition && + pTrigger->test_type != XSyncPositiveComparison && + pTrigger->test_type != XSyncNegativeComparison) + { + client->errorValue = pTrigger->test_type; + return BadValue; + } + /* select appropriate CheckTrigger function */ + + switch (pTrigger->test_type) + { + case XSyncPositiveTransition: + pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition; + break; + case XSyncNegativeTransition: + pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition; + break; + case XSyncPositiveComparison: + pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison; + break; + case XSyncNegativeComparison: + pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison; + break; + } + } + + if (changes & (XSyncCAValueType | XSyncCAValue)) + { + if (pTrigger->value_type == XSyncAbsolute) + pTrigger->test_value = pTrigger->wait_value; + else /* relative */ + { + Bool overflow; + if (pCounter == NULL) + return BadMatch; + + XSyncValueAdd(&pTrigger->test_value, pCounter->value, + pTrigger->wait_value, &overflow); + if (overflow) + { + client->errorValue = XSyncValueHigh32(pTrigger->wait_value); + return BadValue; + } + } + } + + /* we wait until we're sure there are no errors before registering + * a new counter on a trigger + */ + if (newcounter) + { + if ((rc = SyncAddTriggerToCounter(pTrigger)) != Success) + return rc; + } + else if (IsSystemCounter(pCounter)) + { + SyncComputeBracketValues(pCounter); + } + + return Success; +} + +/* AlarmNotify events happen in response to actions taken on an Alarm or + * the counter used by the alarm. AlarmNotify may be sent to multiple + * clients. The alarm maintains a list of clients interested in events. + */ +static void +SyncSendAlarmNotifyEvents(SyncAlarm *pAlarm) +{ + SyncAlarmClientList *pcl; + xSyncAlarmNotifyEvent ane; + SyncTrigger *pTrigger = &pAlarm->trigger; + + UpdateCurrentTime(); + + ane.type = SyncEventBase + XSyncAlarmNotify; + ane.kind = XSyncAlarmNotify; + ane.alarm = pAlarm->alarm_id; + if (pTrigger->pCounter) + { + ane.counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); + ane.counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); + } + else + { /* XXX what else can we do if there's no counter? */ + ane.counter_value_hi = ane.counter_value_lo = 0; + } + + ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value); + ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value); + ane.time = currentTime.milliseconds; + ane.state = pAlarm->state; + + /* send to owner */ + if (pAlarm->events) + WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane); + + /* send to other interested clients */ + for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next) + WriteEventsToClient(pcl->client, 1, (xEvent *) &ane); +} + + +/* CounterNotify events only occur in response to an Await. The events + * go only to the Awaiting client. + */ +static void +SyncSendCounterNotifyEvents(ClientPtr client, SyncAwait **ppAwait, + int num_events) +{ + xSyncCounterNotifyEvent *pEvents, *pev; + int i; + + if (client->clientGone) + return; + pev = pEvents = malloc(num_events * sizeof(xSyncCounterNotifyEvent)); + if (!pEvents) + return; + UpdateCurrentTime(); + for (i = 0; i < num_events; i++, ppAwait++, pev++) + { + SyncTrigger *pTrigger = &(*ppAwait)->trigger; + pev->type = SyncEventBase + XSyncCounterNotify; + pev->kind = XSyncCounterNotify; + pev->counter = pTrigger->pCounter->id; + pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value); + pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value); + pev->counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); + pev->counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); + pev->time = currentTime.milliseconds; + pev->count = num_events - i - 1; /* events remaining */ + pev->destroyed = pTrigger->pCounter->beingDestroyed; + } + /* swapping will be taken care of by this */ + WriteEventsToClient(client, num_events, (xEvent *)pEvents); + free(pEvents); +} + + +/* This function is called when an alarm's counter is destroyed. + * It is plugged into pTrigger->CounterDestroyed (for alarm triggers). + */ +static void +SyncAlarmCounterDestroyed(SyncTrigger *pTrigger) +{ + SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; + + pAlarm->state = XSyncAlarmInactive; + SyncSendAlarmNotifyEvents(pAlarm); + pTrigger->pCounter = NULL; +} + + +/* This function is called when an alarm "goes off." + * It is plugged into pTrigger->TriggerFired (for alarm triggers). + */ +static void +SyncAlarmTriggerFired(SyncTrigger *pTrigger) +{ + SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; + CARD64 new_test_value; + + /* no need to check alarm unless it's active */ + if (pAlarm->state != XSyncAlarmActive) + return; + + /* " if the counter value is None, or if the delta is 0 and + * the test-type is PositiveComparison or NegativeComparison, + * no change is made to value (test-value) and the alarm + * state is changed to Inactive before the event is generated." + */ + if (pAlarm->trigger.pCounter == NULL + || (XSyncValueIsZero(pAlarm->delta) + && (pAlarm->trigger.test_type == XSyncPositiveComparison + || pAlarm->trigger.test_type == XSyncNegativeComparison))) + pAlarm->state = XSyncAlarmInactive; + + new_test_value = pAlarm->trigger.test_value; + + if (pAlarm->state == XSyncAlarmActive) + { + Bool overflow; + CARD64 oldvalue; + SyncTrigger *paTrigger = &pAlarm->trigger; + + /* "The alarm is updated by repeatedly adding delta to the + * value of the trigger and re-initializing it until it + * becomes FALSE." + */ + oldvalue = paTrigger->test_value; + + /* XXX really should do something smarter here */ + + do + { + XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value, + pAlarm->delta, &overflow); + } while (!overflow && + (*paTrigger->CheckTrigger)(paTrigger, + paTrigger->pCounter->value)); + + new_test_value = paTrigger->test_value; + paTrigger->test_value = oldvalue; + + /* "If this update would cause value to fall outside the range + * for an INT64...no change is made to value (test-value) and + * the alarm state is changed to Inactive before the event is + * generated." + */ + if (overflow) + { + new_test_value = oldvalue; + pAlarm->state = XSyncAlarmInactive; + } + } + /* The AlarmNotify event has to have the "new state of the alarm" + * which we can't be sure of until this point. However, it has + * to have the "old" trigger test value. That's the reason for + * all the newvalue/oldvalue shuffling above. After we send the + * events, give the trigger its new test value. + */ + SyncSendAlarmNotifyEvents(pAlarm); + pTrigger->test_value = new_test_value; +} + + +/* This function is called when an Await unblocks, either as a result + * of the trigger firing OR the counter being destroyed. + * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed + * (for Await triggers). + */ +static void +SyncAwaitTriggerFired(SyncTrigger *pTrigger) +{ + SyncAwait *pAwait = (SyncAwait *)pTrigger; + int numwaits; + SyncAwaitUnion *pAwaitUnion; + SyncAwait **ppAwait; + int num_events = 0; + + pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader; + numwaits = pAwaitUnion->header.num_waitconditions; + ppAwait = malloc(numwaits * sizeof(SyncAwait *)); + if (!ppAwait) + goto bail; + + pAwait = &(pAwaitUnion+1)->await; + + /* "When a client is unblocked, all the CounterNotify events for + * the Await request are generated contiguously. If count is 0 + * there are no more events to follow for this request. If + * count is n, there are at least n more events to follow." + * + * Thus, it is best to find all the counters for which events + * need to be sent first, so that an accurate count field can + * be stored in the events. + */ + for ( ; numwaits; numwaits--, pAwait++) + { + CARD64 diff; + Bool overflow, diffgreater, diffequal; + + /* "A CounterNotify event with the destroyed flag set to TRUE is + * always generated if the counter for one of the triggers is + * destroyed." + */ + if (pAwait->trigger.pCounter->beingDestroyed) + { + ppAwait[num_events++] = pAwait; + continue; + } + + /* "The difference between the counter and the test value is + * calculated by subtracting the test value from the value of + * the counter." + */ + XSyncValueSubtract(&diff, pAwait->trigger.pCounter->value, + pAwait->trigger.test_value, &overflow); + + /* "If the difference lies outside the range for an INT64, an + * event is not generated." + */ + if (overflow) + continue; + diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold); + diffequal = XSyncValueEqual(diff, pAwait->event_threshold); + + /* "If the test-type is PositiveTransition or + * PositiveComparison, a CounterNotify event is generated if + * the difference is at least event-threshold. If the test-type + * is NegativeTransition or NegativeComparison, a CounterNotify + * event is generated if the difference is at most + * event-threshold." + */ + + if ( ((pAwait->trigger.test_type == XSyncPositiveComparison || + pAwait->trigger.test_type == XSyncPositiveTransition) + && (diffgreater || diffequal)) + || + ((pAwait->trigger.test_type == XSyncNegativeComparison || + pAwait->trigger.test_type == XSyncNegativeTransition) + && (!diffgreater) /* less or equal */ + ) + ) + { + ppAwait[num_events++] = pAwait; + } + } + if (num_events) + SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait, + num_events); + free(ppAwait); + +bail: + /* unblock the client */ + AttendClient(pAwaitUnion->header.client); + /* delete the await */ + FreeResource(pAwaitUnion->header.delete_id, RT_NONE); +} + + +/* This function should always be used to change a counter's value so that + * any triggers depending on the counter will be checked. + */ +void +SyncChangeCounter(SyncCounter *pCounter, CARD64 newval) +{ + SyncTriggerList *ptl, *pnext; + CARD64 oldval; + + oldval = pCounter->value; + pCounter->value = newval; + + /* run through triggers to see if any become true */ + for (ptl = pCounter->pTriglist; ptl; ptl = pnext) + { + pnext = ptl->next; + if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval)) + (*ptl->pTrigger->TriggerFired)(ptl->pTrigger); + } + + if (IsSystemCounter(pCounter)) + { + SyncComputeBracketValues(pCounter); + } +} + + +/* loosely based on dix/events.c/EventSelectForWindow */ +static Bool +SyncEventSelectForAlarm(SyncAlarm *pAlarm, ClientPtr client, Bool wantevents) +{ + SyncAlarmClientList *pClients; + + if (client == pAlarm->client) /* alarm owner */ + { + pAlarm->events = wantevents; + return Success; + } + + /* see if the client is already on the list (has events selected) */ + + for (pClients = pAlarm->pEventClients; pClients; + pClients = pClients->next) + { + if (pClients->client == client) + { + /* client's presence on the list indicates desire for + * events. If the client doesn't want events, remove it + * from the list. If the client does want events, do + * nothing, since it's already got them. + */ + if (!wantevents) + { + FreeResource(pClients->delete_id, RT_NONE); + } + return Success; + } + } + + /* if we get here, this client does not currently have + * events selected on the alarm + */ + + if (!wantevents) + /* client doesn't want events, and we just discovered that it + * doesn't have them, so there's nothing to do. + */ + return Success; + + /* add new client to pAlarm->pEventClients */ + + pClients = malloc(sizeof(SyncAlarmClientList)); + if (!pClients) + return BadAlloc; + + /* register it as a resource so it will be cleaned up + * if the client dies + */ + + pClients->delete_id = FakeClientID(client->index); + if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm)) + { + free(pClients); + return BadAlloc; + } + + /* link it into list after we know all the allocations succeed */ + + pClients->next = pAlarm->pEventClients; + pAlarm->pEventClients = pClients; + pClients->client = client; + return Success; +} + +/* + * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm + */ +static int +SyncChangeAlarmAttributes(ClientPtr client, SyncAlarm *pAlarm, Mask mask, + CARD32 *values) +{ + int status; + XSyncCounter counter; + Mask origmask = mask; + + counter = pAlarm->trigger.pCounter ? pAlarm->trigger.pCounter->id : None; + + while (mask) + { + int index2 = lowbit(mask); + mask &= ~index2; + switch (index2) + { + case XSyncCACounter: + mask &= ~XSyncCACounter; + /* sanity check in SyncInitTrigger */ + counter = *values++; + break; + + case XSyncCAValueType: + mask &= ~XSyncCAValueType; + /* sanity check in SyncInitTrigger */ + pAlarm->trigger.value_type = *values++; + break; + + case XSyncCAValue: + mask &= ~XSyncCAValue; + XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]); + values += 2; + break; + + case XSyncCATestType: + mask &= ~XSyncCATestType; + /* sanity check in SyncInitTrigger */ + pAlarm->trigger.test_type = *values++; + break; + + case XSyncCADelta: + mask &= ~XSyncCADelta; + XSyncIntsToValue(&pAlarm->delta, values[1], values[0]); + values += 2; + break; + + case XSyncCAEvents: + mask &= ~XSyncCAEvents; + if ((*values != xTrue) && (*values != xFalse)) + { + client->errorValue = *values; + return BadValue; + } + status = SyncEventSelectForAlarm(pAlarm, client, + (Bool)(*values++)); + if (status != Success) + return status; + break; + + default: + client->errorValue = mask; + return BadValue; + } + } + + /* "If the test-type is PositiveComparison or PositiveTransition + * and delta is less than zero, or if the test-type is + * NegativeComparison or NegativeTransition and delta is + * greater than zero, a Match error is generated." + */ + if (origmask & (XSyncCADelta|XSyncCATestType)) + { + CARD64 zero; + XSyncIntToValue(&zero, 0); + if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) || + (pAlarm->trigger.test_type == XSyncPositiveTransition)) + && XSyncValueLessThan(pAlarm->delta, zero)) + || + (((pAlarm->trigger.test_type == XSyncNegativeComparison) || + (pAlarm->trigger.test_type == XSyncNegativeTransition)) + && XSyncValueGreaterThan(pAlarm->delta, zero)) + ) + { + return BadMatch; + } + } + + /* postpone this until now, when we're sure nothing else can go wrong */ + if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter, + origmask & XSyncCAAllTrigger)) != Success) + return status; + + /* XXX spec does not really say to do this - needs clarification */ + pAlarm->state = XSyncAlarmActive; + return Success; +} + + +static SyncCounter * +SyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue) +{ + SyncCounter *pCounter; + + if (!(pCounter = malloc(sizeof(SyncCounter)))) + return NULL; + + if (!AddResource(id, RTCounter, (pointer) pCounter)) + { + free(pCounter); + return NULL; + } + + pCounter->client = client; + pCounter->id = id; + pCounter->value = initialvalue; + pCounter->pTriglist = NULL; + pCounter->beingDestroyed = FALSE; + pCounter->pSysCounterInfo = NULL; + return pCounter; +} + +static int FreeCounter(void *, XID); + +/* + * ***** System Counter utilities + */ + +pointer +SyncCreateSystemCounter( + char *name, + CARD64 initial, + CARD64 resolution, + SyncCounterType counterType, + void (*QueryValue)(pointer /* pCounter */, + CARD64 * /* pValue_return */), + void (*BracketValues)(pointer /* pCounter */, + CARD64 * /* pbracket_less */, + CARD64 * /* pbracket_greater */) + ) +{ + SyncCounter *pCounter; + + SysCounterList = realloc(SysCounterList, + (SyncNumSystemCounters+1)*sizeof(SyncCounter *)); + if (!SysCounterList) + return NULL; + + /* this function may be called before SYNC has been initialized, so we + * have to make sure RTCounter is created. + */ + if (RTCounter == 0) + { + RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter"); + if (RTCounter == 0) + { + return NULL; + } + } + + pCounter = SyncCreateCounter(NULL, FakeClientID(0), initial); + + if (pCounter) + { + SysCounterInfo *psci; + + psci = malloc(sizeof(SysCounterInfo)); + if (!psci) + { + FreeResource(pCounter->id, RT_NONE); + return pCounter; + } + pCounter->pSysCounterInfo = psci; + psci->name = name; + psci->resolution = resolution; + psci->counterType = counterType; + psci->QueryValue = QueryValue; + psci->BracketValues = BracketValues; + XSyncMaxValue(&psci->bracket_greater); + XSyncMinValue(&psci->bracket_less); + SysCounterList[SyncNumSystemCounters++] = pCounter; + } + return pCounter; +} + +void +SyncDestroySystemCounter(pointer pSysCounter) +{ + SyncCounter *pCounter = (SyncCounter *)pSysCounter; + FreeResource(pCounter->id, RT_NONE); +} + +static void +SyncComputeBracketValues(SyncCounter *pCounter) +{ + SyncTriggerList *pCur; + SyncTrigger *pTrigger; + SysCounterInfo *psci; + CARD64 *pnewgtval = NULL; + CARD64 *pnewltval = NULL; + SyncCounterType ct; + + if (!pCounter) + return; + + psci = pCounter->pSysCounterInfo; + ct = pCounter->pSysCounterInfo->counterType; + if (ct == XSyncCounterNeverChanges) + return; + + XSyncMaxValue(&psci->bracket_greater); + XSyncMinValue(&psci->bracket_less); + + for (pCur = pCounter->pTriglist; pCur; pCur = pCur->next) + { + pTrigger = pCur->pTrigger; + + if (pTrigger->test_type == XSyncPositiveComparison && + ct != XSyncCounterNeverIncreases) + { + if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && + XSyncValueLessThan(pTrigger->test_value, + psci->bracket_greater)) + { + psci->bracket_greater = pTrigger->test_value; + pnewgtval = &psci->bracket_greater; + } + } + else if (pTrigger->test_type == XSyncNegativeComparison && + ct != XSyncCounterNeverDecreases) + { + if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && + XSyncValueGreaterThan(pTrigger->test_value, + psci->bracket_less)) + { + psci->bracket_less = pTrigger->test_value; + pnewltval = &psci->bracket_less; + } + } + else if (pTrigger->test_type == XSyncNegativeTransition && + ct != XSyncCounterNeverIncreases) + { + if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && + XSyncValueGreaterThan(pTrigger->test_value, psci->bracket_less)) + { + psci->bracket_less = pTrigger->test_value; + pnewltval = &psci->bracket_less; + } + } + else if (pTrigger->test_type == XSyncPositiveTransition && + ct != XSyncCounterNeverDecreases) + { + if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && + XSyncValueLessThan(pTrigger->test_value, psci->bracket_greater)) + { + psci->bracket_greater = pTrigger->test_value; + pnewgtval = &psci->bracket_greater; + } + } + } /* end for each trigger */ + + if (pnewgtval || pnewltval) + { + (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval); + } +} + +/* + * ***** Resource delete functions + */ + +/* ARGSUSED */ +static int +FreeAlarm(void *addr, XID id) +{ + SyncAlarm *pAlarm = (SyncAlarm *) addr; + + pAlarm->state = XSyncAlarmDestroyed; + + SyncSendAlarmNotifyEvents(pAlarm); + + /* delete event selections */ + + while (pAlarm->pEventClients) + FreeResource(pAlarm->pEventClients->delete_id, RT_NONE); + + SyncDeleteTriggerFromCounter(&pAlarm->trigger); + + free(pAlarm); + return Success; +} + + +/* + * ** Cleanup after the destruction of a Counter + */ +/* ARGSUSED */ +static int +FreeCounter(void *env, XID id) +{ + SyncCounter *pCounter = (SyncCounter *) env; + SyncTriggerList *ptl, *pnext; + + pCounter->beingDestroyed = TRUE; + /* tell all the counter's triggers that the counter has been destroyed */ + for (ptl = pCounter->pTriglist; ptl; ptl = pnext) + { + (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger); + pnext = ptl->next; + free(ptl); /* destroy the trigger list as we go */ + } + if (IsSystemCounter(pCounter)) + { + int i, found = 0; + + free(pCounter->pSysCounterInfo); + + /* find the counter in the list of system counters and remove it */ + + if (SysCounterList) + { + for (i = 0; i < SyncNumSystemCounters; i++) + { + if (SysCounterList[i] == pCounter) + { + found = i; + break; + } + } + if (found < (SyncNumSystemCounters-1)) + { + for (i = found; i < SyncNumSystemCounters-1; i++) + { + SysCounterList[i] = SysCounterList[i+1]; + } + } + } + SyncNumSystemCounters--; + } + free(pCounter); + return Success; +} + +/* + * ** Cleanup after Await + */ +/* ARGSUSED */ +static int +FreeAwait(void *addr, XID id) +{ + SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr; + SyncAwait *pAwait; + int numwaits; + + pAwait = &(pAwaitUnion+1)->await; /* first await on list */ + + /* remove triggers from counters */ + + for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits; + numwaits--, pAwait++) + { + /* If the counter is being destroyed, FreeCounter will delete + * the trigger list itself, so don't do it here. + */ + SyncCounter *pCounter = pAwait->trigger.pCounter; + if (pCounter && !pCounter->beingDestroyed) + SyncDeleteTriggerFromCounter(&pAwait->trigger); + } + free(pAwaitUnion); + return Success; +} + +/* loosely based on dix/events.c/OtherClientGone */ +static int +FreeAlarmClient(void *value, XID id) +{ + SyncAlarm *pAlarm = (SyncAlarm *)value; + SyncAlarmClientList *pCur, *pPrev; + + for (pPrev = NULL, pCur = pAlarm->pEventClients; + pCur; + pPrev = pCur, pCur = pCur->next) + { + if (pCur->delete_id == id) + { + if (pPrev) + pPrev->next = pCur->next; + else + pAlarm->pEventClients = pCur->next; + free(pCur); + return Success; + } + } + FatalError("alarm client not on event list"); + /*NOTREACHED*/ +} + + +/* + * ***** Proc functions + */ + + +/* + * ** Initialize the extension + */ +static int +ProcSyncInitialize(ClientPtr client) +{ + xSyncInitializeReply rep; + int n; + + REQUEST_SIZE_MATCH(xSyncInitializeReq); + + memset(&rep, 0, sizeof(xSyncInitializeReply)); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SYNC_MAJOR_VERSION; + rep.minorVersion = SYNC_MINOR_VERSION; + rep.length = 0; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + } + WriteToClient(client, sizeof(rep), (char *) &rep); + return Success; +} + +/* + * ** Get list of system counters available through the extension + */ +static int +ProcSyncListSystemCounters(ClientPtr client) +{ + xSyncListSystemCountersReply rep; + int i, len; + xSyncSystemCounter *list = NULL, *walklist = NULL; + + REQUEST_SIZE_MATCH(xSyncListSystemCountersReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.nCounters = SyncNumSystemCounters; + + for (i = len = 0; i < SyncNumSystemCounters; i++) + { + char *name = SysCounterList[i]->pSysCounterInfo->name; + /* pad to 4 byte boundary */ + len += pad_to_int32(sz_xSyncSystemCounter + strlen(name)); + } + + if (len) + { + walklist = list = malloc(len); + if (!list) + return BadAlloc; + } + + rep.length = bytes_to_int32(len); + + if (client->swapped) + { + char n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.nCounters, n); + } + + for (i = 0; i < SyncNumSystemCounters; i++) + { + int namelen; + char *pname_in_reply; + SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo; + + walklist->counter = SysCounterList[i]->id; + walklist->resolution_hi = XSyncValueHigh32(psci->resolution); + walklist->resolution_lo = XSyncValueLow32(psci->resolution); + namelen = strlen(psci->name); + walklist->name_length = namelen; + + if (client->swapped) + { + char n; + swapl(&walklist->counter, n); + swapl(&walklist->resolution_hi, n); + swapl(&walklist->resolution_lo, n); + swaps(&walklist->name_length, n); + } + + pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter; + strncpy(pname_in_reply, psci->name, namelen); + walklist = (xSyncSystemCounter *) (((char *)walklist) + + pad_to_int32(sz_xSyncSystemCounter + namelen)); + } + + WriteToClient(client, sizeof(rep), (char *) &rep); + if (len) + { + WriteToClient(client, len, (char *) list); + free(list); + } + + return Success; +} + +/* + * ** Set client Priority + */ +static int +ProcSyncSetPriority(ClientPtr client) +{ + REQUEST(xSyncSetPriorityReq); + ClientPtr priorityclient; + int rc; + + REQUEST_SIZE_MATCH(xSyncSetPriorityReq); + + if (stuff->id == None) + priorityclient = client; + else { + rc = dixLookupClient(&priorityclient, stuff->id, client, + DixSetAttrAccess); + if (rc != Success) + return rc; + } + + if (priorityclient->priority != stuff->priority) + { + priorityclient->priority = stuff->priority; + + /* The following will force the server back into WaitForSomething + * so that the change in this client's priority is immediately + * reflected. + */ + isItTimeToYield = TRUE; + dispatchException |= DE_PRIORITYCHANGE; + } + return Success; +} + +/* + * ** Get client Priority + */ +static int +ProcSyncGetPriority(ClientPtr client) +{ + REQUEST(xSyncGetPriorityReq); + xSyncGetPriorityReply rep; + ClientPtr priorityclient; + int rc; + + REQUEST_SIZE_MATCH(xSyncGetPriorityReq); + + if (stuff->id == None) + priorityclient = client; + else { + rc = dixLookupClient(&priorityclient, stuff->id, client, + DixGetAttrAccess); + if (rc != Success) + return rc; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.priority = priorityclient->priority; + + if (client->swapped) + { + char n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.priority, n); + } + + WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep); + + return Success; +} + +/* + * ** Create a new counter + */ +static int +ProcSyncCreateCounter(ClientPtr client) +{ + REQUEST(xSyncCreateCounterReq); + CARD64 initial; + + REQUEST_SIZE_MATCH(xSyncCreateCounterReq); + + LEGAL_NEW_RESOURCE(stuff->cid, client); + + XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi); + if (!SyncCreateCounter(client, stuff->cid, initial)) + return BadAlloc; + + return Success; +} + +/* + * ** Set Counter value + */ +static int +ProcSyncSetCounter(ClientPtr client) +{ + REQUEST(xSyncSetCounterReq); + SyncCounter *pCounter; + CARD64 newvalue; + int rc; + + REQUEST_SIZE_MATCH(xSyncSetCounterReq); + + rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter, + client, DixWriteAccess); + if (rc != Success) + return rc; + + if (IsSystemCounter(pCounter)) + { + client->errorValue = stuff->cid; + return BadAccess; + } + + XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); + SyncChangeCounter(pCounter, newvalue); + return Success; +} + +/* + * ** Change Counter value + */ +static int +ProcSyncChangeCounter(ClientPtr client) +{ + REQUEST(xSyncChangeCounterReq); + SyncCounter *pCounter; + CARD64 newvalue; + Bool overflow; + int rc; + + REQUEST_SIZE_MATCH(xSyncChangeCounterReq); + + rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter, + client, DixWriteAccess); + if (rc != Success) + return rc; + + if (IsSystemCounter(pCounter)) + { + client->errorValue = stuff->cid; + return BadAccess; + } + + XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); + XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow); + if (overflow) + { + /* XXX 64 bit value can't fit in 32 bits; do the best we can */ + client->errorValue = stuff->value_hi; + return BadValue; + } + SyncChangeCounter(pCounter, newvalue); + return Success; +} + +/* + * ** Destroy a counter + */ +static int +ProcSyncDestroyCounter(ClientPtr client) +{ + REQUEST(xSyncDestroyCounterReq); + SyncCounter *pCounter; + int rc; + + REQUEST_SIZE_MATCH(xSyncDestroyCounterReq); + + rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, RTCounter, + client, DixDestroyAccess); + if (rc != Success) + return rc; + + if (IsSystemCounter(pCounter)) + { + client->errorValue = stuff->counter; + return BadAccess; + } + FreeResource(pCounter->id, RT_NONE); + return Success; +} + + +/* + * ** Await + */ +static int +ProcSyncAwait(ClientPtr client) +{ + REQUEST(xSyncAwaitReq); + int len, items; + int i; + xSyncWaitCondition *pProtocolWaitConds; + SyncAwaitUnion *pAwaitUnion; + SyncAwait *pAwait; + int status; + + REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); + + len = client->req_len << 2; + len -= sz_xSyncAwaitReq; + items = len / sz_xSyncWaitCondition; + + if (items * sz_xSyncWaitCondition != len) + { + return BadLength; + } + if (items == 0) + { + client->errorValue = items; /* XXX protocol change */ + return BadValue; + } + + pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1]; + + /* all the memory for the entire await list is allocated + * here in one chunk + */ + pAwaitUnion = malloc((items+1) * sizeof(SyncAwaitUnion)); + if (!pAwaitUnion) + return BadAlloc; + + /* first item is the header, remainder are real wait conditions */ + + pAwaitUnion->header.delete_id = FakeClientID(client->index); + if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion)) + { + free(pAwaitUnion); + return BadAlloc; + } + + /* don't need to do any more memory allocation for this request! */ + + pAwaitUnion->header.client = client; + pAwaitUnion->header.num_waitconditions = 0; + + pAwait = &(pAwaitUnion+1)->await; /* skip over header */ + for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++) + { + if (pProtocolWaitConds->counter == None) /* XXX protocol change */ + { + /* this should take care of removing any triggers created by + * this request that have already been registered on counters + */ + FreeResource(pAwaitUnion->header.delete_id, RT_NONE); + client->errorValue = pProtocolWaitConds->counter; + return SyncErrorBase + XSyncBadCounter; + } + + /* sanity checks are in SyncInitTrigger */ + pAwait->trigger.pCounter = NULL; + pAwait->trigger.value_type = pProtocolWaitConds->value_type; + XSyncIntsToValue(&pAwait->trigger.wait_value, + pProtocolWaitConds->wait_value_lo, + pProtocolWaitConds->wait_value_hi); + pAwait->trigger.test_type = pProtocolWaitConds->test_type; + + status = SyncInitTrigger(client, &pAwait->trigger, + pProtocolWaitConds->counter, XSyncCAAllTrigger); + if (status != Success) + { + /* this should take care of removing any triggers created by + * this request that have already been registered on counters + */ + FreeResource(pAwaitUnion->header.delete_id, RT_NONE); + return status; + } + /* this is not a mistake -- same function works for both cases */ + pAwait->trigger.TriggerFired = SyncAwaitTriggerFired; + pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired; + XSyncIntsToValue(&pAwait->event_threshold, + pProtocolWaitConds->event_threshold_lo, + pProtocolWaitConds->event_threshold_hi); + pAwait->pHeader = &pAwaitUnion->header; + pAwaitUnion->header.num_waitconditions++; + } + + IgnoreClient(client); + + /* see if any of the triggers are already true */ + + pAwait = &(pAwaitUnion+1)->await; /* skip over header */ + for (i = 0; i < items; i++, pAwait++) + { + /* don't have to worry about NULL counters because the request + * errors before we get here out if they occur + */ + if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, + pAwait->trigger.pCounter->value)) + { + (*pAwait->trigger.TriggerFired)(&pAwait->trigger); + break; /* once is enough */ + } + } + return Success; +} + + +/* + * ** Query a counter + */ +static int +ProcSyncQueryCounter(ClientPtr client) +{ + REQUEST(xSyncQueryCounterReq); + xSyncQueryCounterReply rep; + SyncCounter *pCounter; + int rc; + + REQUEST_SIZE_MATCH(xSyncQueryCounterReq); + + rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, + RTCounter, client, DixReadAccess); + if (rc != Success) + return rc; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + /* if system counter, ask it what the current value is */ + + if (IsSystemCounter(pCounter)) + { + (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, + &pCounter->value); + } + + rep.value_hi = XSyncValueHigh32(pCounter->value); + rep.value_lo = XSyncValueLow32(pCounter->value); + if (client->swapped) + { + char n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.value_hi, n); + swapl(&rep.value_lo, n); + } + WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep); + return Success; +} + + +/* + * ** Create Alarm + */ +static int +ProcSyncCreateAlarm(ClientPtr client) +{ + REQUEST(xSyncCreateAlarmReq); + SyncAlarm *pAlarm; + int status; + unsigned long len, vmask; + SyncTrigger *pTrigger; + + REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); + + LEGAL_NEW_RESOURCE(stuff->id, client); + + vmask = stuff->valueMask; + len = client->req_len - bytes_to_int32(sizeof(xSyncCreateAlarmReq)); + /* the "extra" call to Ones accounts for the presence of 64 bit values */ + if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) + return BadLength; + + if (!(pAlarm = malloc(sizeof(SyncAlarm)))) + { + return BadAlloc; + } + + /* set up defaults */ + + pTrigger = &pAlarm->trigger; + pTrigger->pCounter = NULL; + pTrigger->value_type = XSyncAbsolute; + XSyncIntToValue(&pTrigger->wait_value, 0L); + pTrigger->test_type = XSyncPositiveComparison; + pTrigger->TriggerFired = SyncAlarmTriggerFired; + pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed; + status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger); + if (status != Success) + { + free(pAlarm); + return status; + } + + pAlarm->client = client; + pAlarm->alarm_id = stuff->id; + XSyncIntToValue(&pAlarm->delta, 1L); + pAlarm->events = TRUE; + pAlarm->state = XSyncAlarmInactive; + pAlarm->pEventClients = NULL; + status = SyncChangeAlarmAttributes(client, pAlarm, vmask, + (CARD32 *)&stuff[1]); + if (status != Success) + { + free(pAlarm); + return status; + } + + if (!AddResource(stuff->id, RTAlarm, pAlarm)) + { + free(pAlarm); + return BadAlloc; + } + + /* see if alarm already triggered. NULL counter will not trigger + * in CreateAlarm and sets alarm state to Inactive. + */ + + if (!pTrigger->pCounter) + { + pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */ + } + else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value)) + { + (*pTrigger->TriggerFired)(pTrigger); + } + + return Success; +} + +/* + * ** Change Alarm + */ +static int +ProcSyncChangeAlarm(ClientPtr client) +{ + REQUEST(xSyncChangeAlarmReq); + SyncAlarm *pAlarm; + long vmask; + int len, status; + + REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); + + status = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, + client, DixWriteAccess); + if (status != Success) + return status; + + vmask = stuff->valueMask; + len = client->req_len - bytes_to_int32(sizeof(xSyncChangeAlarmReq)); + /* the "extra" call to Ones accounts for the presence of 64 bit values */ + if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) + return BadLength; + + if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask, + (CARD32 *)&stuff[1])) != Success) + return status; + + /* see if alarm already triggered. NULL counter WILL trigger + * in ChangeAlarm. + */ + + if (!pAlarm->trigger.pCounter || + (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger, + pAlarm->trigger.pCounter->value)) + { + (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger); + } + return Success; +} + +static int +ProcSyncQueryAlarm(ClientPtr client) +{ + REQUEST(xSyncQueryAlarmReq); + SyncAlarm *pAlarm; + xSyncQueryAlarmReply rep; + SyncTrigger *pTrigger; + int rc; + + REQUEST_SIZE_MATCH(xSyncQueryAlarmReq); + + rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, + client, DixReadAccess); + if (rc != Success) + return rc; + + rep.type = X_Reply; + rep.length = bytes_to_int32(sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)); + rep.sequenceNumber = client->sequence; + + pTrigger = &pAlarm->trigger; + rep.counter = (pTrigger->pCounter) ? pTrigger->pCounter->id : None; + +#if 0 /* XXX unclear what to do, depends on whether relative value-types + * are "consumed" immediately and are considered absolute from then + * on. + */ + rep.value_type = pTrigger->value_type; + rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value); + rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value); +#else + rep.value_type = XSyncAbsolute; + rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value); + rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value); +#endif + + rep.test_type = pTrigger->test_type; + rep.delta_hi = XSyncValueHigh32(pAlarm->delta); + rep.delta_lo = XSyncValueLow32(pAlarm->delta); + rep.events = pAlarm->events; + rep.state = pAlarm->state; + + if (client->swapped) + { + char n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.counter, n); + swapl(&rep.wait_value_hi, n); + swapl(&rep.wait_value_lo, n); + swapl(&rep.test_type, n); + swapl(&rep.delta_hi, n); + swapl(&rep.delta_lo, n); + } + + WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep); + return Success; +} + +static int +ProcSyncDestroyAlarm(ClientPtr client) +{ + SyncAlarm *pAlarm; + int rc; + REQUEST(xSyncDestroyAlarmReq); + + REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq); + + rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, + client, DixDestroyAccess); + if (rc != Success) + return rc; + + FreeResource(stuff->alarm, RT_NONE); + return Success; +} + +/* + * ** Given an extension request, call the appropriate request procedure + */ +static int +ProcSyncDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_SyncInitialize: + return ProcSyncInitialize(client); + case X_SyncListSystemCounters: + return ProcSyncListSystemCounters(client); + case X_SyncCreateCounter: + return ProcSyncCreateCounter(client); + case X_SyncSetCounter: + return ProcSyncSetCounter(client); + case X_SyncChangeCounter: + return ProcSyncChangeCounter(client); + case X_SyncQueryCounter: + return ProcSyncQueryCounter(client); + case X_SyncDestroyCounter: + return ProcSyncDestroyCounter(client); + case X_SyncAwait: + return ProcSyncAwait(client); + case X_SyncCreateAlarm: + return ProcSyncCreateAlarm(client); + case X_SyncChangeAlarm: + return ProcSyncChangeAlarm(client); + case X_SyncQueryAlarm: + return ProcSyncQueryAlarm(client); + case X_SyncDestroyAlarm: + return ProcSyncDestroyAlarm(client); + case X_SyncSetPriority: + return ProcSyncSetPriority(client); + case X_SyncGetPriority: + return ProcSyncGetPriority(client); + default: + return BadRequest; + } +} + +/* + * Boring Swapping stuff ... + */ + +static int +SProcSyncInitialize(ClientPtr client) +{ + REQUEST(xSyncInitializeReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncInitializeReq); + + return ProcSyncInitialize(client); +} + +static int +SProcSyncListSystemCounters(ClientPtr client) +{ + REQUEST(xSyncListSystemCountersReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncListSystemCountersReq); + + return ProcSyncListSystemCounters(client); +} + +static int +SProcSyncCreateCounter(ClientPtr client) +{ + REQUEST(xSyncCreateCounterReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncCreateCounterReq); + swapl(&stuff->cid, n); + swapl(&stuff->initial_value_lo, n); + swapl(&stuff->initial_value_hi, n); + + return ProcSyncCreateCounter(client); +} + +static int +SProcSyncSetCounter(ClientPtr client) +{ + REQUEST(xSyncSetCounterReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncSetCounterReq); + swapl(&stuff->cid, n); + swapl(&stuff->value_lo, n); + swapl(&stuff->value_hi, n); + + return ProcSyncSetCounter(client); +} + +static int +SProcSyncChangeCounter(ClientPtr client) +{ + REQUEST(xSyncChangeCounterReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncChangeCounterReq); + swapl(&stuff->cid, n); + swapl(&stuff->value_lo, n); + swapl(&stuff->value_hi, n); + + return ProcSyncChangeCounter(client); +} + +static int +SProcSyncQueryCounter(ClientPtr client) +{ + REQUEST(xSyncQueryCounterReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncQueryCounterReq); + swapl(&stuff->counter, n); + + return ProcSyncQueryCounter(client); +} + +static int +SProcSyncDestroyCounter(ClientPtr client) +{ + REQUEST(xSyncDestroyCounterReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncDestroyCounterReq); + swapl(&stuff->counter, n); + + return ProcSyncDestroyCounter(client); +} + +static int +SProcSyncAwait(ClientPtr client) +{ + REQUEST(xSyncAwaitReq); + char n; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); + SwapRestL(stuff); + + return ProcSyncAwait(client); +} + +static int +SProcSyncCreateAlarm(ClientPtr client) +{ + REQUEST(xSyncCreateAlarmReq); + char n; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); + swapl(&stuff->id, n); + swapl(&stuff->valueMask, n); + SwapRestL(stuff); + + return ProcSyncCreateAlarm(client); +} + +static int +SProcSyncChangeAlarm(ClientPtr client) +{ + REQUEST(xSyncChangeAlarmReq); + char n; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); + swapl(&stuff->alarm, n); + swapl(&stuff->valueMask, n); + SwapRestL(stuff); + return ProcSyncChangeAlarm(client); +} + +static int +SProcSyncQueryAlarm(ClientPtr client) +{ + REQUEST(xSyncQueryAlarmReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncQueryAlarmReq); + swapl(&stuff->alarm, n); + + return ProcSyncQueryAlarm(client); +} + +static int +SProcSyncDestroyAlarm(ClientPtr client) +{ + REQUEST(xSyncDestroyAlarmReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq); + swapl(&stuff->alarm, n); + + return ProcSyncDestroyAlarm(client); +} + +static int +SProcSyncSetPriority(ClientPtr client) +{ + REQUEST(xSyncSetPriorityReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncSetPriorityReq); + swapl(&stuff->id, n); + swapl(&stuff->priority, n); + + return ProcSyncSetPriority(client); +} + +static int +SProcSyncGetPriority(ClientPtr client) +{ + REQUEST(xSyncGetPriorityReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncGetPriorityReq); + swapl(&stuff->id, n); + + return ProcSyncGetPriority(client); +} + + +static int +SProcSyncDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_SyncInitialize: + return SProcSyncInitialize(client); + case X_SyncListSystemCounters: + return SProcSyncListSystemCounters(client); + case X_SyncCreateCounter: + return SProcSyncCreateCounter(client); + case X_SyncSetCounter: + return SProcSyncSetCounter(client); + case X_SyncChangeCounter: + return SProcSyncChangeCounter(client); + case X_SyncQueryCounter: + return SProcSyncQueryCounter(client); + case X_SyncDestroyCounter: + return SProcSyncDestroyCounter(client); + case X_SyncAwait: + return SProcSyncAwait(client); + case X_SyncCreateAlarm: + return SProcSyncCreateAlarm(client); + case X_SyncChangeAlarm: + return SProcSyncChangeAlarm(client); + case X_SyncQueryAlarm: + return SProcSyncQueryAlarm(client); + case X_SyncDestroyAlarm: + return SProcSyncDestroyAlarm(client); + case X_SyncSetPriority: + return SProcSyncSetPriority(client); + case X_SyncGetPriority: + return SProcSyncGetPriority(client); + default: + return BadRequest; + } +} + +/* + * Event Swapping + */ + +static void +SCounterNotifyEvent(xSyncCounterNotifyEvent *from, xSyncCounterNotifyEvent *to) +{ + to->type = from->type; + to->kind = from->kind; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->counter, to->counter); + cpswapl(from->wait_value_lo, to->wait_value_lo); + cpswapl(from->wait_value_hi, to->wait_value_hi); + cpswapl(from->counter_value_lo, to->counter_value_lo); + cpswapl(from->counter_value_hi, to->counter_value_hi); + cpswapl(from->time, to->time); + cpswaps(from->count, to->count); + to->destroyed = from->destroyed; +} + + +static void +SAlarmNotifyEvent(xSyncAlarmNotifyEvent *from, xSyncAlarmNotifyEvent *to) +{ + to->type = from->type; + to->kind = from->kind; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->alarm, to->alarm); + cpswapl(from->counter_value_lo, to->counter_value_lo); + cpswapl(from->counter_value_hi, to->counter_value_hi); + cpswapl(from->alarm_value_lo, to->alarm_value_lo); + cpswapl(from->alarm_value_hi, to->alarm_value_hi); + cpswapl(from->time, to->time); + to->state = from->state; +} + +/* + * ** Close everything down. ** This is fairly simple for now. + */ +/* ARGSUSED */ +static void +SyncResetProc(ExtensionEntry *extEntry) +{ + free(SysCounterList); + SysCounterList = NULL; + RTCounter = 0; +} + + +/* + * ** Initialise the extension. + */ +void +SyncExtensionInit(void) +{ + ExtensionEntry *extEntry; + + if (RTCounter == 0) + { + RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter"); + } + RTAlarm = CreateNewResourceType(FreeAlarm, "SyncAlarm"); + RTAwait = CreateNewResourceType(FreeAwait, "SyncAwait"); + if (RTAwait) + RTAwait |= RC_NEVERRETAIN; + RTAlarmClient = CreateNewResourceType(FreeAlarmClient, "SyncAlarmClient"); + if (RTAlarmClient) + RTAlarmClient |= RC_NEVERRETAIN; + + if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 || + RTAlarmClient == 0 || + (extEntry = AddExtension(SYNC_NAME, + XSyncNumberEvents, XSyncNumberErrors, + ProcSyncDispatch, SProcSyncDispatch, + SyncResetProc, + StandardMinorOpcode)) == NULL) + { + ErrorF("Sync Extension %d.%d failed to Initialise\n", + SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); + return; + } + + SyncEventBase = extEntry->eventBase; + SyncErrorBase = extEntry->errorBase; + EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent; + EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent; + + SetResourceTypeErrorValue(RTCounter, SyncErrorBase + XSyncBadCounter); + SetResourceTypeErrorValue(RTAlarm, SyncErrorBase + XSyncBadAlarm); + + /* + * Although SERVERTIME is implemented by the OS layer, we initialise it + * here because doing it in OsInit() is too early. The resource database + * is not initialised when OsInit() is called. This is just about OK + * because there is always a servertime counter. + */ + SyncInitServerTime(); + SyncInitIdleTime(); + +#ifdef DEBUG + fprintf(stderr, "Sync Extension %d.%d\n", + SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); +#endif +} + + +/* + * ***** SERVERTIME implementation - should go in its own file in OS directory? + */ + + + +static pointer ServertimeCounter; +static XSyncValue Now; +static XSyncValue *pnext_time; + +#define GetTime()\ +{\ + unsigned long millis = GetTimeInMillis();\ + unsigned long maxis = XSyncValueHigh32(Now);\ + if (millis < XSyncValueLow32(Now)) maxis++;\ + XSyncIntsToValue(&Now, millis, maxis);\ +} + +/* +*** Server Block Handler +*** code inspired by multibuffer extension (now deprecated) + */ +/*ARGSUSED*/ +static void +ServertimeBlockHandler(void *env, struct timeval **wt, void *LastSelectMask) +{ + XSyncValue delay; + unsigned long timeout; + + if (pnext_time) + { + GetTime(); + + if (XSyncValueGreaterOrEqual(Now, *pnext_time)) + { + timeout = 0; + } + else + { + Bool overflow; + XSyncValueSubtract(&delay, *pnext_time, Now, &overflow); + (void)overflow; + timeout = XSyncValueLow32(delay); + } + AdjustWaitForDelay(wt, timeout); /* os/utils.c */ + } +} + +/* +*** Wakeup Handler + */ +/*ARGSUSED*/ +static void +ServertimeWakeupHandler(void *env, int rc, void *LastSelectMask) +{ + if (pnext_time) + { + GetTime(); + + if (XSyncValueGreaterOrEqual(Now, *pnext_time)) + { + SyncChangeCounter(ServertimeCounter, Now); + } + } +} + +static void +ServertimeQueryValue(void *pCounter, CARD64 *pValue_return) +{ + GetTime(); + *pValue_return = Now; +} + +static void +ServertimeBracketValues(void *pCounter, CARD64 *pbracket_less, + CARD64 *pbracket_greater) +{ + if (!pnext_time && pbracket_greater) + { + RegisterBlockAndWakeupHandlers(ServertimeBlockHandler, + ServertimeWakeupHandler, + NULL); + } + else if (pnext_time && !pbracket_greater) + { + RemoveBlockAndWakeupHandlers(ServertimeBlockHandler, + ServertimeWakeupHandler, + NULL); + } + pnext_time = pbracket_greater; +} + +static void +SyncInitServerTime(void) +{ + CARD64 resolution; + + XSyncIntsToValue(&Now, GetTimeInMillis(), 0); + XSyncIntToValue(&resolution, 4); + ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution, + XSyncCounterNeverDecreases, + ServertimeQueryValue, ServertimeBracketValues); + pnext_time = NULL; +} + + + +/* + * IDLETIME implementation + */ + +static SyncCounter *IdleTimeCounter; +static XSyncValue *pIdleTimeValueLess; +static XSyncValue *pIdleTimeValueGreater; + +static void +IdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return) +{ + CARD32 idle = GetTimeInMillis() - lastDeviceEventTime.milliseconds; + XSyncIntsToValue (pValue_return, idle, 0); +} + +static void +IdleTimeBlockHandler(pointer env, struct timeval **wt, pointer LastSelectMask) +{ + XSyncValue idle, old_idle; + SyncTriggerList *list = IdleTimeCounter->pTriglist; + SyncTrigger *trig; + + if (!pIdleTimeValueLess && !pIdleTimeValueGreater) + return; + + old_idle = IdleTimeCounter->value; + IdleTimeQueryValue (NULL, &idle); + IdleTimeCounter->value = idle; /* push, so CheckTrigger works */ + + if (pIdleTimeValueLess && + XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)) + { + /* + * We've been idle for less than the threshold value, and someone + * wants to know about that, but now we need to know whether they + * want level or edge trigger. Check the trigger list against the + * current idle time, and if any succeed, bomb out of select() + * immediately so we can reschedule. + */ + + for (list = IdleTimeCounter->pTriglist; list; list = list->next) { + trig = list->pTrigger; + if (trig->CheckTrigger(trig, old_idle)) { + AdjustWaitForDelay(wt, 0); + break; + } + } + } + else if (pIdleTimeValueGreater) + { + /* + * There's a threshold in the positive direction. If we've been + * idle less than it, schedule a wakeup for sometime in the future. + * If we've been idle more than it, and someone wants to know about + * that level-triggered, schedule an immediate wakeup. + */ + unsigned long timeout = -1; + + if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) { + XSyncValue value; + Bool overflow; + + XSyncValueSubtract (&value, *pIdleTimeValueGreater, + idle, &overflow); + timeout = min(timeout, XSyncValueLow32 (value)); + } else { + for (list = IdleTimeCounter->pTriglist; list; list = list->next) { + trig = list->pTrigger; + if (trig->CheckTrigger(trig, old_idle)) { + timeout = min(timeout, 0); + break; + } + } + } + + AdjustWaitForDelay (wt, timeout); + } + + IdleTimeCounter->value = old_idle; /* pop */ +} + +static void +IdleTimeWakeupHandler (pointer env, int rc, pointer LastSelectMask) +{ + XSyncValue idle; + + if (!pIdleTimeValueLess && !pIdleTimeValueGreater) + return; + + IdleTimeQueryValue (NULL, &idle); + + if ((pIdleTimeValueGreater && + XSyncValueGreaterOrEqual (idle, *pIdleTimeValueGreater)) || + (pIdleTimeValueLess && + XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))) + { + SyncChangeCounter (IdleTimeCounter, idle); + } +} + +static void +IdleTimeBracketValues (pointer pCounter, CARD64 *pbracket_less, + CARD64 *pbracket_greater) +{ + Bool registered = (pIdleTimeValueLess || pIdleTimeValueGreater); + + if (registered && !pbracket_less && !pbracket_greater) + { + RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler, + IdleTimeWakeupHandler, + NULL); + } + else if (!registered && (pbracket_less || pbracket_greater)) + { + RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler, + IdleTimeWakeupHandler, + NULL); + } + + pIdleTimeValueGreater = pbracket_greater; + pIdleTimeValueLess = pbracket_less; +} + +static void +SyncInitIdleTime (void) +{ + CARD64 resolution; + XSyncValue idle; + + IdleTimeQueryValue (NULL, &idle); + XSyncIntToValue (&resolution, 4); + + IdleTimeCounter = SyncCreateSystemCounter ("IDLETIME", idle, resolution, + XSyncCounterUnrestricted, + IdleTimeQueryValue, + IdleTimeBracketValues); + + pIdleTimeValueLess = pIdleTimeValueGreater = NULL; +} diff --git a/xorg-server/Xext/xcalibrate.c b/xorg-server/Xext/xcalibrate.c index 029154fa0..a16c11bab 100644 --- a/xorg-server/Xext/xcalibrate.c +++ b/xorg-server/Xext/xcalibrate.c @@ -54,13 +54,11 @@ xcalibrate_event_hook (int x, int y, int pressure, void *closure) xXCalibrateRawTouchscreenEvent ev; ev.type = XCalibrateEventBase + X_XCalibrateRawTouchscreen; - ev.sequenceNumber = pClient->sequence; ev.x = x; ev.y = y; ev.pressure = pressure; - if (!pClient->clientGone) - WriteEventsToClient (pClient, 1, (xEvent *) &ev); + WriteEventsToClient (pClient, 1, (xEvent *) &ev); } static int diff --git a/xorg-server/Xext/xtest.c b/xorg-server/Xext/xtest.c index 05395a7c1..b8f5e86d8 100644 --- a/xorg-server/Xext/xtest.c +++ b/xorg-server/Xext/xtest.c @@ -153,7 +153,7 @@ ProcXTestCompareCursor(ClientPtr client) if (rc != Success) { client->errorValue = stuff->cursor; - return (rc == BadValue) ? BadCursor : rc; + return rc; } } rep.type = X_Reply; diff --git a/xorg-server/Xext/xvdisp.c b/xorg-server/Xext/xvdisp.c index 34ea61ad3..f346b6cea 100644 --- a/xorg-server/Xext/xvdisp.c +++ b/xorg-server/Xext/xvdisp.c @@ -1025,7 +1025,6 @@ typedef struct _ShmDesc { } ShmDescRec, *ShmDescPtr; extern RESTYPE ShmSegType; -extern int BadShmSegCode; extern int ShmCompletionCode; static int @@ -1077,7 +1076,7 @@ ProcXvShmPutImage(ClientPtr client) status = dixLookupResourceByType((pointer *)&shmdesc, stuff->shmseg, ShmSegType, serverClient, DixReadAccess); if (status != Success) - return (status == BadValue) ? BadShmSegCode : status; + return status; width = stuff->width; height = stuff->height; @@ -1100,7 +1099,6 @@ ProcXvShmPutImage(ClientPtr client) ev.type = ShmCompletionCode; ev.drawable = stuff->drawable; - ev.sequenceNumber = client->sequence; ev.minorEvent = xv_ShmPutImage; ev.majorEvent = XvReqCode; ev.shmseg = stuff->shmseg; @@ -1616,7 +1614,7 @@ XineramaXvStopVideo(ClientPtr client) result = dixLookupResourceByType((pointer *)&port, stuff->port, XvXRTPort, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? _XvBadPort : result; + return result; FOR_NSCREENS_BACKWARD(i) { if(port->info[i].id) { @@ -1641,7 +1639,7 @@ XineramaXvSetPortAttribute(ClientPtr client) result = dixLookupResourceByType((pointer *)&port, stuff->port, XvXRTPort, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? _XvBadPort : result; + return result; FOR_NSCREENS_BACKWARD(i) { if(port->info[i].id) { @@ -1672,12 +1670,12 @@ XineramaXvShmPutImage(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; result = dixLookupResourceByType((pointer *)&port, stuff->port, XvXRTPort, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? _XvBadPort : result; + return result; isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; @@ -1724,12 +1722,12 @@ XineramaXvPutImage(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; result = dixLookupResourceByType((pointer *)&port, stuff->port, XvXRTPort, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? _XvBadPort : result; + return result; isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; @@ -1772,12 +1770,12 @@ XineramaXvPutVideo(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; result = dixLookupResourceByType((pointer *)&port, stuff->port, XvXRTPort, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? _XvBadPort : result; + return result; isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; @@ -1820,12 +1818,12 @@ XineramaXvPutStill(ClientPtr client) result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? BadGC : result; + return result; result = dixLookupResourceByType((pointer *)&port, stuff->port, XvXRTPort, client, DixReadAccess); if (result != Success) - return (result == BadValue) ? _XvBadPort : result; + return result; isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; @@ -1911,6 +1909,7 @@ void XineramifyXv(void) XvXRTPort = CreateNewResourceType(XineramaDeleteResource, "XvXRTPort"); if (!xvsp0 || !XvXRTPort) return; + SetResourceTypeErrorValue(XvXRTPort, _XvBadPort); for(i = 0; i < xvsp0->nAdaptors; i++) { Bool isOverlay; diff --git a/xorg-server/Xext/xvdix.h b/xorg-server/Xext/xvdix.h index 44f8f6b18..5104a4def 100644 --- a/xorg-server/Xext/xvdix.h +++ b/xorg-server/Xext/xvdix.h @@ -1,275 +1,275 @@ -/*********************************************************** -Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, -and the Massachusetts Institute of Technology, Cambridge, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the names of Digital or MIT not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -******************************************************************/ - -#ifndef XVDIX_H -#define XVDIX_H -/* -** File: -** -** xvdix.h --- Xv device independent header file -** -** Author: -** -** David Carver (Digital Workstation Engineering/Project Athena) -** -** Revisions: -** -** 29.08.91 Carver -** - removed UnrealizeWindow wrapper unrealizing windows no longer -** preempts video -** -** 11.06.91 Carver -** - changed SetPortControl to SetPortAttribute -** - changed GetPortControl to GetPortAttribute -** - changed QueryBestSize -** -** 15.05.91 Carver -** - version 2.0 upgrade -** -** 24.01.91 Carver -** - version 1.4 upgrade -** -*/ - -#include "scrnintstr.h" -#include - -#ifndef XorgLoader -extern _X_EXPORT unsigned long XvExtensionGeneration; -extern _X_EXPORT unsigned long XvScreenGeneration; -extern _X_EXPORT unsigned long XvResourceGeneration; - -extern _X_EXPORT int XvReqCode; -extern _X_EXPORT int XvEventBase; -extern _X_EXPORT int XvErrorBase; - -extern _X_EXPORT unsigned long XvRTPort; -extern _X_EXPORT unsigned long XvRTEncoding; -extern _X_EXPORT unsigned long XvRTGrab; -extern _X_EXPORT unsigned long XvRTVideoNotify; -extern _X_EXPORT unsigned long XvRTVideoNotifyList; -extern _X_EXPORT unsigned long XvRTPortNotify; -#endif - -typedef struct { - int numerator; - int denominator; -} XvRationalRec, *XvRationalPtr; - -typedef struct { - char depth; - unsigned long visual; -} XvFormatRec, *XvFormatPtr; - -typedef struct { - unsigned long id; - ClientPtr client; -} XvGrabRec, *XvGrabPtr; - -typedef struct _XvVideoNotifyRec { - struct _XvVideoNotifyRec *next; - ClientPtr client; - unsigned long id; - unsigned long mask; -} XvVideoNotifyRec, *XvVideoNotifyPtr; - -typedef struct _XvPortNotifyRec { - struct _XvPortNotifyRec *next; - ClientPtr client; - unsigned long id; -} XvPortNotifyRec, *XvPortNotifyPtr; - -typedef struct { - int id; - ScreenPtr pScreen; - char *name; - unsigned short width, height; - XvRationalRec rate; -} XvEncodingRec, *XvEncodingPtr; - -typedef struct _XvAttributeRec { - int flags; - int min_value; - int max_value; - char *name; -} XvAttributeRec, *XvAttributePtr; - -typedef struct { - int id; - int type; - int byte_order; - char guid[16]; - int bits_per_pixel; - int format; - int num_planes; - - /* for RGB formats only */ - int depth; - unsigned int red_mask; - unsigned int green_mask; - unsigned int blue_mask; - - /* for YUV formats only */ - unsigned int y_sample_bits; - unsigned int u_sample_bits; - unsigned int v_sample_bits; - unsigned int horz_y_period; - unsigned int horz_u_period; - unsigned int horz_v_period; - unsigned int vert_y_period; - unsigned int vert_u_period; - unsigned int vert_v_period; - char component_order[32]; - int scanline_order; -} XvImageRec, *XvImagePtr; - -typedef struct { - unsigned long base_id; - unsigned char type; - char *name; - int nEncodings; - XvEncodingPtr pEncodings; - int nFormats; - XvFormatPtr pFormats; - int nAttributes; - XvAttributePtr pAttributes; - int nImages; - XvImagePtr pImages; - int nPorts; - struct _XvPortRec *pPorts; - ScreenPtr pScreen; - int (* ddAllocatePort)(unsigned long, struct _XvPortRec*, - struct _XvPortRec**); - int (* ddFreePort)(struct _XvPortRec*); - int (* ddPutVideo)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); - int (* ddPutStill)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); - int (* ddGetVideo)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); - int (* ddGetStill)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); - int (* ddStopVideo)(ClientPtr, struct _XvPortRec*, DrawablePtr); - int (* ddSetPortAttribute)(ClientPtr, struct _XvPortRec*, Atom, INT32); - int (* ddGetPortAttribute)(ClientPtr, struct _XvPortRec*, Atom, INT32*); - int (* ddQueryBestSize)(ClientPtr, struct _XvPortRec*, CARD8, - CARD16, CARD16,CARD16, CARD16, - unsigned int*, unsigned int*); - int (* ddPutImage)(ClientPtr, DrawablePtr, struct _XvPortRec*, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16, - XvImagePtr, unsigned char*, Bool, - CARD16, CARD16); - int (* ddQueryImageAttributes)(ClientPtr, struct _XvPortRec*, XvImagePtr, - CARD16*, CARD16*, int*, int*); - DevUnion devPriv; -} XvAdaptorRec, *XvAdaptorPtr; - -typedef struct _XvPortRec { - unsigned long id; - XvAdaptorPtr pAdaptor; - XvPortNotifyPtr pNotify; - DrawablePtr pDraw; - ClientPtr client; - XvGrabRec grab; - TimeStamp time; - DevUnion devPriv; -} XvPortRec, *XvPortPtr; - -#define VALIDATE_XV_PORT(portID, pPort, mode)\ - {\ - int rc = dixLookupResourceByType((pointer *)&(pPort), portID,\ - XvRTPort, client, mode);\ - if (rc != Success)\ - return (rc == BadValue) ? _XvBadPort : rc;\ - } - -typedef struct { - int version, revision; - int nAdaptors; - XvAdaptorPtr pAdaptors; - DestroyWindowProcPtr DestroyWindow; - DestroyPixmapProcPtr DestroyPixmap; - CloseScreenProcPtr CloseScreen; - Bool (* ddCloseScreen)(int, ScreenPtr); - int (* ddQueryAdaptors)(ScreenPtr, XvAdaptorPtr*, int*); - DevUnion devPriv; -} XvScreenRec, *XvScreenPtr; - -#define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = ((XvScreenPtr) \ - dixLookupPrivate(&(pScreen)->devPrivates, XvScreenKey))->field) - -#define SCREEN_EPILOGUE(pScreen, field, wrapper)\ - ((pScreen)->field = wrapper) - -/* Errors */ - -#define _XvBadPort (XvBadPort+XvErrorBase) -#define _XvBadEncoding (XvBadEncoding+XvErrorBase) - -#ifndef XorgLoader -extern _X_EXPORT int ProcXvDispatch(ClientPtr); -extern _X_EXPORT int SProcXvDispatch(ClientPtr); - -extern _X_EXPORT void XvExtensionInit(void); -extern _X_EXPORT int XvScreenInit(ScreenPtr); -extern _X_EXPORT DevPrivateKey XvGetScreenKey(void); -extern _X_EXPORT unsigned long XvGetRTPort(void); -extern _X_EXPORT int XvdiSendPortNotify(XvPortPtr, Atom, INT32); -extern _X_EXPORT int XvdiVideoStopped(XvPortPtr, int); - -extern _X_EXPORT int XvdiPutVideo(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); -extern _X_EXPORT int XvdiPutStill(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); -extern _X_EXPORT int XvdiGetVideo(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); -extern _X_EXPORT int XvdiGetStill(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); -extern _X_EXPORT int XvdiPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16, - XvImagePtr, unsigned char*, Bool, - CARD16, CARD16); -extern _X_EXPORT int XvdiSelectVideoNotify(ClientPtr, DrawablePtr, BOOL); -extern _X_EXPORT int XvdiSelectPortNotify(ClientPtr, XvPortPtr, BOOL); -extern _X_EXPORT int XvdiSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32); -extern _X_EXPORT int XvdiGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32*); -extern _X_EXPORT int XvdiStopVideo(ClientPtr, XvPortPtr, DrawablePtr); -extern _X_EXPORT int XvdiPreemptVideo(ClientPtr, XvPortPtr, DrawablePtr); -extern _X_EXPORT int XvdiMatchPort(XvPortPtr, DrawablePtr); -extern _X_EXPORT int XvdiGrabPort(ClientPtr, XvPortPtr, Time, int *); -extern _X_EXPORT int XvdiUngrabPort( ClientPtr, XvPortPtr, Time); -#endif /* XorgLoader */ - -#endif /* XVDIX_H */ - +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital or MIT not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef XVDIX_H +#define XVDIX_H +/* +** File: +** +** xvdix.h --- Xv device independent header file +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 29.08.91 Carver +** - removed UnrealizeWindow wrapper unrealizing windows no longer +** preempts video +** +** 11.06.91 Carver +** - changed SetPortControl to SetPortAttribute +** - changed GetPortControl to GetPortAttribute +** - changed QueryBestSize +** +** 15.05.91 Carver +** - version 2.0 upgrade +** +** 24.01.91 Carver +** - version 1.4 upgrade +** +*/ + +#include "scrnintstr.h" +#include + +#ifndef XorgLoader +extern _X_EXPORT unsigned long XvExtensionGeneration; +extern _X_EXPORT unsigned long XvScreenGeneration; +extern _X_EXPORT unsigned long XvResourceGeneration; + +extern _X_EXPORT int XvReqCode; +extern _X_EXPORT int XvEventBase; +extern _X_EXPORT int XvErrorBase; + +extern _X_EXPORT unsigned long XvRTPort; +extern _X_EXPORT unsigned long XvRTEncoding; +extern _X_EXPORT unsigned long XvRTGrab; +extern _X_EXPORT unsigned long XvRTVideoNotify; +extern _X_EXPORT unsigned long XvRTVideoNotifyList; +extern _X_EXPORT unsigned long XvRTPortNotify; +#endif + +typedef struct { + int numerator; + int denominator; +} XvRationalRec, *XvRationalPtr; + +typedef struct { + char depth; + unsigned long visual; +} XvFormatRec, *XvFormatPtr; + +typedef struct { + unsigned long id; + ClientPtr client; +} XvGrabRec, *XvGrabPtr; + +typedef struct _XvVideoNotifyRec { + struct _XvVideoNotifyRec *next; + ClientPtr client; + unsigned long id; + unsigned long mask; +} XvVideoNotifyRec, *XvVideoNotifyPtr; + +typedef struct _XvPortNotifyRec { + struct _XvPortNotifyRec *next; + ClientPtr client; + unsigned long id; +} XvPortNotifyRec, *XvPortNotifyPtr; + +typedef struct { + int id; + ScreenPtr pScreen; + char *name; + unsigned short width, height; + XvRationalRec rate; +} XvEncodingRec, *XvEncodingPtr; + +typedef struct _XvAttributeRec { + int flags; + int min_value; + int max_value; + char *name; +} XvAttributeRec, *XvAttributePtr; + +typedef struct { + int id; + int type; + int byte_order; + char guid[16]; + int bits_per_pixel; + int format; + int num_planes; + + /* for RGB formats only */ + int depth; + unsigned int red_mask; + unsigned int green_mask; + unsigned int blue_mask; + + /* for YUV formats only */ + unsigned int y_sample_bits; + unsigned int u_sample_bits; + unsigned int v_sample_bits; + unsigned int horz_y_period; + unsigned int horz_u_period; + unsigned int horz_v_period; + unsigned int vert_y_period; + unsigned int vert_u_period; + unsigned int vert_v_period; + char component_order[32]; + int scanline_order; +} XvImageRec, *XvImagePtr; + +typedef struct { + unsigned long base_id; + unsigned char type; + char *name; + int nEncodings; + XvEncodingPtr pEncodings; + int nFormats; + XvFormatPtr pFormats; + int nAttributes; + XvAttributePtr pAttributes; + int nImages; + XvImagePtr pImages; + int nPorts; + struct _XvPortRec *pPorts; + ScreenPtr pScreen; + int (* ddAllocatePort)(unsigned long, struct _XvPortRec*, + struct _XvPortRec**); + int (* ddFreePort)(struct _XvPortRec*); + int (* ddPutVideo)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); + int (* ddPutStill)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); + int (* ddGetVideo)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); + int (* ddGetStill)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); + int (* ddStopVideo)(ClientPtr, struct _XvPortRec*, DrawablePtr); + int (* ddSetPortAttribute)(ClientPtr, struct _XvPortRec*, Atom, INT32); + int (* ddGetPortAttribute)(ClientPtr, struct _XvPortRec*, Atom, INT32*); + int (* ddQueryBestSize)(ClientPtr, struct _XvPortRec*, CARD8, + CARD16, CARD16,CARD16, CARD16, + unsigned int*, unsigned int*); + int (* ddPutImage)(ClientPtr, DrawablePtr, struct _XvPortRec*, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16, + XvImagePtr, unsigned char*, Bool, + CARD16, CARD16); + int (* ddQueryImageAttributes)(ClientPtr, struct _XvPortRec*, XvImagePtr, + CARD16*, CARD16*, int*, int*); + DevUnion devPriv; +} XvAdaptorRec, *XvAdaptorPtr; + +typedef struct _XvPortRec { + unsigned long id; + XvAdaptorPtr pAdaptor; + XvPortNotifyPtr pNotify; + DrawablePtr pDraw; + ClientPtr client; + XvGrabRec grab; + TimeStamp time; + DevUnion devPriv; +} XvPortRec, *XvPortPtr; + +#define VALIDATE_XV_PORT(portID, pPort, mode)\ + {\ + int rc = dixLookupResourceByType((pointer *)&(pPort), portID,\ + XvRTPort, client, mode);\ + if (rc != Success)\ + return rc;\ + } + +typedef struct { + int version, revision; + int nAdaptors; + XvAdaptorPtr pAdaptors; + DestroyWindowProcPtr DestroyWindow; + DestroyPixmapProcPtr DestroyPixmap; + CloseScreenProcPtr CloseScreen; + Bool (* ddCloseScreen)(int, ScreenPtr); + int (* ddQueryAdaptors)(ScreenPtr, XvAdaptorPtr*, int*); + DevUnion devPriv; +} XvScreenRec, *XvScreenPtr; + +#define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = ((XvScreenPtr) \ + dixLookupPrivate(&(pScreen)->devPrivates, XvScreenKey))->field) + +#define SCREEN_EPILOGUE(pScreen, field, wrapper)\ + ((pScreen)->field = wrapper) + +/* Errors */ + +#define _XvBadPort (XvBadPort+XvErrorBase) +#define _XvBadEncoding (XvBadEncoding+XvErrorBase) + +#ifndef XorgLoader +extern _X_EXPORT int ProcXvDispatch(ClientPtr); +extern _X_EXPORT int SProcXvDispatch(ClientPtr); + +extern _X_EXPORT void XvExtensionInit(void); +extern _X_EXPORT int XvScreenInit(ScreenPtr); +extern _X_EXPORT DevPrivateKey XvGetScreenKey(void); +extern _X_EXPORT unsigned long XvGetRTPort(void); +extern _X_EXPORT int XvdiSendPortNotify(XvPortPtr, Atom, INT32); +extern _X_EXPORT int XvdiVideoStopped(XvPortPtr, int); + +extern _X_EXPORT int XvdiPutVideo(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +extern _X_EXPORT int XvdiPutStill(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +extern _X_EXPORT int XvdiGetVideo(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +extern _X_EXPORT int XvdiGetStill(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +extern _X_EXPORT int XvdiPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16, + XvImagePtr, unsigned char*, Bool, + CARD16, CARD16); +extern _X_EXPORT int XvdiSelectVideoNotify(ClientPtr, DrawablePtr, BOOL); +extern _X_EXPORT int XvdiSelectPortNotify(ClientPtr, XvPortPtr, BOOL); +extern _X_EXPORT int XvdiSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32); +extern _X_EXPORT int XvdiGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32*); +extern _X_EXPORT int XvdiStopVideo(ClientPtr, XvPortPtr, DrawablePtr); +extern _X_EXPORT int XvdiPreemptVideo(ClientPtr, XvPortPtr, DrawablePtr); +extern _X_EXPORT int XvdiMatchPort(XvPortPtr, DrawablePtr); +extern _X_EXPORT int XvdiGrabPort(ClientPtr, XvPortPtr, Time, int *); +extern _X_EXPORT int XvdiUngrabPort( ClientPtr, XvPortPtr, Time); +#endif /* XorgLoader */ + +#endif /* XVDIX_H */ + diff --git a/xorg-server/Xext/xvmain.c b/xorg-server/Xext/xvmain.c index 413b94015..58574b956 100644 --- a/xorg-server/Xext/xvmain.c +++ b/xorg-server/Xext/xvmain.c @@ -192,6 +192,7 @@ XvExtensionInit(void) EventSwapVector[XvEventBase+XvPortNotify] = (EventSwapPtr)WriteSwappedPortNotifyEvent; + SetResourceTypeErrorValue(XvRTPort, _XvBadPort); (void)MakeAtom(XvName, strlen(XvName), xTrue); } @@ -530,17 +531,12 @@ XvdiSendVideoNotify(XvPortPtr pPort, DrawablePtr pDraw, int reason) while (pn) { - if (pn->client) - { - event.u.u.type = XvEventBase + XvVideoNotify; - event.u.u.sequenceNumber = pn->client->sequence; - event.u.videoNotify.time = currentTime.milliseconds; - event.u.videoNotify.drawable = pDraw->id; - event.u.videoNotify.port = pPort->id; - event.u.videoNotify.reason = reason; - TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1, - NoEventMask, NoEventMask, NullGrab); - } + event.u.u.type = XvEventBase + XvVideoNotify; + event.u.videoNotify.time = currentTime.milliseconds; + event.u.videoNotify.drawable = pDraw->id; + event.u.videoNotify.port = pPort->id; + event.u.videoNotify.reason = reason; + WriteEventsToClient(pn->client, 1, (xEventPtr)&event); pn = pn->next; } @@ -562,17 +558,12 @@ XvdiSendPortNotify( while (pn) { - if (pn->client) - { - event.u.u.type = XvEventBase + XvPortNotify; - event.u.u.sequenceNumber = pn->client->sequence; - event.u.portNotify.time = currentTime.milliseconds; - event.u.portNotify.port = pPort->id; - event.u.portNotify.attribute = attribute; - event.u.portNotify.value = value; - TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1, - NoEventMask, NoEventMask, NullGrab); - } + event.u.u.type = XvEventBase + XvPortNotify; + event.u.portNotify.time = currentTime.milliseconds; + event.u.portNotify.port = pPort->id; + event.u.portNotify.attribute = attribute; + event.u.portNotify.value = value; + WriteEventsToClient(pn->client, 1, (xEventPtr)&event); pn = pn->next; } diff --git a/xorg-server/Xext/xvmc.c b/xorg-server/Xext/xvmc.c index 18a81c76b..4866d1d45 100644 --- a/xorg-server/Xext/xvmc.c +++ b/xorg-server/Xext/xvmc.c @@ -40,7 +40,6 @@ unsigned long XvMCGeneration = 0; int XvMCReqCode; int XvMCEventBase; -int XvMCErrorBase; unsigned long XvMCRTContext; unsigned long XvMCRTSurface; @@ -276,7 +275,7 @@ ProcXvMCDestroyContext(ClientPtr client) rc = dixLookupResourceByType(&val, stuff->context_id, XvMCRTContext, client, DixDestroyAccess); if (rc != Success) - return (rc == BadValue) ? XvMCBadContext + XvMCErrorBase : rc; + return rc; FreeResource(stuff->context_id, RT_NONE); @@ -299,7 +298,7 @@ ProcXvMCCreateSurface(ClientPtr client) result = dixLookupResourceByType((pointer *)&pContext, stuff->context_id, XvMCRTContext, client, DixUseAccess); if (result != Success) - return (result == BadValue) ? XvMCBadContext + XvMCErrorBase : result; + return result; pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); @@ -346,7 +345,7 @@ ProcXvMCDestroySurface(ClientPtr client) rc = dixLookupResourceByType(&val, stuff->surface_id, XvMCRTSurface, client, DixDestroyAccess); if (rc != Success) - return (rc == BadValue) ? XvMCBadSurface + XvMCErrorBase : rc; + return rc; FreeResource(stuff->surface_id, RT_NONE); @@ -371,7 +370,7 @@ ProcXvMCCreateSubpicture(ClientPtr client) result = dixLookupResourceByType((pointer *)&pContext, stuff->context_id, XvMCRTContext, client, DixUseAccess); if (result != Success) - return (result == BadValue) ? XvMCBadContext + XvMCErrorBase : result; + return result; pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); @@ -463,7 +462,7 @@ ProcXvMCDestroySubpicture(ClientPtr client) rc = dixLookupResourceByType(&val, stuff->subpicture_id, XvMCRTSubpicture, client, DixDestroyAccess); if (rc != Success) - return (rc == BadValue) ? XvMCBadSubpicture + XvMCErrorBase : rc; + return rc; FreeResource(stuff->subpicture_id, RT_NONE); @@ -694,7 +693,9 @@ XvMCExtensionInit(void) XvMCReqCode = extEntry->base; XvMCEventBase = extEntry->eventBase; - XvMCErrorBase = extEntry->errorBase; + SetResourceTypeErrorValue(XvMCRTContext, extEntry->errorBase + XvMCBadContext); + SetResourceTypeErrorValue(XvMCRTSurface, extEntry->errorBase + XvMCBadSurface); + SetResourceTypeErrorValue(XvMCRTSubpicture, extEntry->errorBase + XvMCBadSubpicture); } static Bool diff --git a/xorg-server/Xi/exevents.c b/xorg-server/Xi/exevents.c index 97ad6fdd2..de1048ed4 100644 --- a/xorg-server/Xi/exevents.c +++ b/xorg-server/Xi/exevents.c @@ -1445,7 +1445,7 @@ GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device, if (rc != Success) { client->errorValue = param->cursor; - return (rc == BadValue) ? BadCursor : rc; + return rc; } access_mode |= DixForceAccess; } @@ -1543,7 +1543,7 @@ GrabWindow(ClientPtr client, DeviceIntPtr dev, int type, if (rc != Success) { client->errorValue = param->cursor; - return (rc == BadValue) ? BadCursor : rc; + return rc; } access_mode |= DixForceAccess; } diff --git a/xorg-server/Xi/xichangecursor.c b/xorg-server/Xi/xichangecursor.c index f071e8406..825f8227a 100644 --- a/xorg-server/Xi/xichangecursor.c +++ b/xorg-server/Xi/xichangecursor.c @@ -1,113 +1,113 @@ -/* - * Copyright 2007-2008 Peter Hutterer - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Author: Peter Hutterer, University of South Australia, NICTA - */ - -/*********************************************************************** - * - * Request to change a given device pointer's cursor. - * - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include /* for inputstr.h */ -#include /* Request macro */ -#include "inputstr.h" /* DeviceIntPtr */ -#include "windowstr.h" /* window structure */ -#include "scrnintstr.h" /* screen structure */ -#include -#include -#include "extnsionst.h" -#include "exevents.h" -#include "exglobals.h" -#include "input.h" - -#include "xichangecursor.h" - -/*********************************************************************** - * - * This procedure allows a client to set one pointer's cursor. - * - */ - -int -SProcXIChangeCursor(ClientPtr client) -{ - char n; - - REQUEST(xXIChangeCursorReq); - swaps(&stuff->length, n); - swapl(&stuff->win, n); - swapl(&stuff->cursor, n); - swaps(&stuff->deviceid, n); - REQUEST_SIZE_MATCH(xXIChangeCursorReq); - return (ProcXIChangeCursor(client)); -} - -int ProcXIChangeCursor(ClientPtr client) -{ - int rc; - WindowPtr pWin = NULL; - DeviceIntPtr pDev = NULL; - CursorPtr pCursor = NULL; - - REQUEST(xXIChangeCursorReq); - REQUEST_SIZE_MATCH(xXIChangeCursorReq); - - rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixSetAttrAccess); - if (rc != Success) - return rc; - - if (!IsMaster(pDev) || !IsPointerDevice(pDev)) - return BadDevice; - - if (stuff->win != None) - { - rc = dixLookupWindow(&pWin, stuff->win, client, DixSetAttrAccess); - if (rc != Success) - return rc; - } - - if (stuff->cursor == None) - { - if (pWin == WindowTable[pWin->drawable.pScreen->myNum]) - pCursor = rootCursor; - else - pCursor = (CursorPtr)None; - } - else - { - rc = dixLookupResourceByType((pointer *)&pCursor, stuff->cursor, - RT_CURSOR, client, DixUseAccess); - if (rc != Success) - return (rc == BadValue) ? BadCursor : rc; - } - - ChangeWindowDeviceCursor(pWin, pDev, pCursor); - - return Success; -} - +/* + * Copyright 2007-2008 Peter Hutterer + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Peter Hutterer, University of South Australia, NICTA + */ + +/*********************************************************************** + * + * Request to change a given device pointer's cursor. + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include /* for inputstr.h */ +#include /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "scrnintstr.h" /* screen structure */ +#include +#include +#include "extnsionst.h" +#include "exevents.h" +#include "exglobals.h" +#include "input.h" + +#include "xichangecursor.h" + +/*********************************************************************** + * + * This procedure allows a client to set one pointer's cursor. + * + */ + +int +SProcXIChangeCursor(ClientPtr client) +{ + char n; + + REQUEST(xXIChangeCursorReq); + swaps(&stuff->length, n); + swapl(&stuff->win, n); + swapl(&stuff->cursor, n); + swaps(&stuff->deviceid, n); + REQUEST_SIZE_MATCH(xXIChangeCursorReq); + return (ProcXIChangeCursor(client)); +} + +int ProcXIChangeCursor(ClientPtr client) +{ + int rc; + WindowPtr pWin = NULL; + DeviceIntPtr pDev = NULL; + CursorPtr pCursor = NULL; + + REQUEST(xXIChangeCursorReq); + REQUEST_SIZE_MATCH(xXIChangeCursorReq); + + rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixSetAttrAccess); + if (rc != Success) + return rc; + + if (!IsMaster(pDev) || !IsPointerDevice(pDev)) + return BadDevice; + + if (stuff->win != None) + { + rc = dixLookupWindow(&pWin, stuff->win, client, DixSetAttrAccess); + if (rc != Success) + return rc; + } + + if (stuff->cursor == None) + { + if (pWin == WindowTable[pWin->drawable.pScreen->myNum]) + pCursor = rootCursor; + else + pCursor = (CursorPtr)None; + } + else + { + rc = dixLookupResourceByType((pointer *)&pCursor, stuff->cursor, + RT_CURSOR, client, DixUseAccess); + if (rc != Success) + return rc; + } + + ChangeWindowDeviceCursor(pWin, pDev, pCursor); + + return Success; +} + diff --git a/xorg-server/Xi/xipassivegrab.c b/xorg-server/Xi/xipassivegrab.c index 4a79ed497..fc3b9e7eb 100644 --- a/xorg-server/Xi/xipassivegrab.c +++ b/xorg-server/Xi/xipassivegrab.c @@ -147,7 +147,7 @@ ProcXIPassiveGrabDevice(ClientPtr client) if (status != Success) { client->errorValue = stuff->cursor; - return (status == BadValue) ? BadCursor : status; + return status; } } diff --git a/xorg-server/composite/compext.c b/xorg-server/composite/compext.c index 664b0fcc3..5e557dd0b 100644 --- a/xorg-server/composite/compext.c +++ b/xorg-server/composite/compext.c @@ -140,10 +140,7 @@ ProcCompositeQueryVersion (ClientPtr client) int err; \ err = dixLookupResourceByType((pointer *) &pWindow, wid, \ RT_WINDOW, client, mode); \ - if (err == BadValue) { \ - client->errorValue = wid; \ - return BadWindow; \ - } else if (err != Success) { \ + if (err != Success) { \ client->errorValue = wid; \ return err; \ } \ diff --git a/xorg-server/damageext/damageext.c b/xorg-server/damageext/damageext.c index dfb26c7d7..dc9c2e8e2 100644 --- a/xorg-server/damageext/damageext.c +++ b/xorg-server/damageext/damageext.c @@ -29,7 +29,6 @@ static unsigned char DamageReqCode; static int DamageEventBase; -static int DamageErrorBase; static RESTYPE DamageExtType; static RESTYPE DamageExtWinType; @@ -50,7 +49,6 @@ DamageExtNotify (DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes) UpdateCurrentTimeIf (); ev.type = DamageEventBase + XDamageNotify; ev.level = pDamageExt->level; - ev.sequenceNumber = pClient->sequence; ev.drawable = pDamageExt->drawable; ev.damage = pDamageExt->id; ev.timestamp = currentTime.milliseconds; @@ -69,8 +67,7 @@ DamageExtNotify (DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes) ev.area.y = pBoxes[i].y1; ev.area.width = pBoxes[i].x2 - pBoxes[i].x1; ev.area.height = pBoxes[i].y2 - pBoxes[i].y1; - if (!pClient->clientGone) - WriteEventsToClient (pClient, 1, (xEvent *) &ev); + WriteEventsToClient (pClient, 1, (xEvent *) &ev); } } else @@ -79,8 +76,7 @@ DamageExtNotify (DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes) ev.area.y = 0; ev.area.width = pDrawable->width; ev.area.height = pDrawable->height; - if (!pClient->clientGone) - WriteEventsToClient (pClient, 1, (xEvent *) &ev); + WriteEventsToClient (pClient, 1, (xEvent *) &ev); } /* Composite extension marks clients with manual Subwindows as critical */ if (pDamageClient->critical > 0) @@ -518,8 +514,8 @@ DamageExtensionInit(void) { DamageReqCode = (unsigned char)extEntry->base; DamageEventBase = extEntry->eventBase; - DamageErrorBase = extEntry->errorBase; EventSwapVector[DamageEventBase + XDamageNotify] = (EventSwapPtr) SDamageNotifyEvent; + SetResourceTypeErrorValue(DamageExtType, extEntry->errorBase + BadDamage); } } diff --git a/xorg-server/damageext/damageextint.h b/xorg-server/damageext/damageextint.h index 99bc57499..f291f043c 100644 --- a/xorg-server/damageext/damageextint.h +++ b/xorg-server/damageext/damageextint.h @@ -62,7 +62,7 @@ typedef struct _DamageExt { int rc = dixLookupResourceByType((pointer *)&(pDamageExt), rid, \ DamageExtType, client, mode); \ if (rc != Success) \ - return (rc == BadValue) ? DamageErrorBase + BadDamage : rc; \ + return rc; \ } void diff --git a/xorg-server/dbe/dbe.c b/xorg-server/dbe/dbe.c index a49a46d69..80383bfc9 100644 --- a/xorg-server/dbe/dbe.c +++ b/xorg-server/dbe/dbe.c @@ -1,1677 +1,1679 @@ -/****************************************************************************** - * - * Copyright (c) 1994, 1995 Hewlett-Packard Company - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the Hewlett-Packard - * Company shall not be used in advertising or otherwise to promote the - * sale, use or other dealings in this Software without prior written - * authorization from the Hewlett-Packard Company. - * - * DIX DBE code - * - *****************************************************************************/ - - -/* INCLUDES */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#if HAVE_STDINT_H -#include -#elif !defined(UINT32_MAX) -#define UINT32_MAX 0xffffffffU -#endif - -#include -#include -#include "scrnintstr.h" -#include "extnsionst.h" -#include "gcstruct.h" -#include "dixstruct.h" -#define NEED_DBE_PROTOCOL -#include "dbestruct.h" -#include "midbe.h" -#include "xace.h" - -/* GLOBALS */ - -/* These are static globals copied to DBE's screen private for use by DDX */ -static int dbeScreenPrivKeyIndex; -static DevPrivateKey dbeScreenPrivKey = &dbeScreenPrivKeyIndex; -static int dbeWindowPrivKeyIndex; -static DevPrivateKey dbeWindowPrivKey = &dbeWindowPrivKeyIndex; - -/* These are static globals copied to DBE's screen private for use by DDX */ -static RESTYPE dbeDrawableResType; -static RESTYPE dbeWindowPrivResType; - -/* Used to generate DBE's BadBuffer error. */ -static int dbeErrorBase; - -/****************************************************************************** - * - * DBE DIX Procedure: DbeStubScreen - * - * Description: - * - * This is function stubs the function pointers in the given DBE screen - * private and increments the number of stubbed screens. - * - *****************************************************************************/ - -static void -DbeStubScreen(DbeScreenPrivPtr pDbeScreenPriv, int *nStubbedScreens) -{ - /* Stub DIX. */ - pDbeScreenPriv->SetupBackgroundPainter = NULL; - - /* Do not unwrap PositionWindow nor DestroyWindow. If the DDX - * initialization function failed, we assume that it did not wrap - * PositionWindow. Also, DestroyWindow is only wrapped if the DDX - * initialization function succeeded. - */ - - /* Stub DDX. */ - pDbeScreenPriv->GetVisualInfo = NULL; - pDbeScreenPriv->AllocBackBufferName = NULL; - pDbeScreenPriv->SwapBuffers = NULL; - pDbeScreenPriv->BeginIdiom = NULL; - pDbeScreenPriv->EndIdiom = NULL; - pDbeScreenPriv->WinPrivDelete = NULL; - pDbeScreenPriv->ResetProc = NULL; - - (*nStubbedScreens)++; - -} /* DbeStubScreen() */ - - - -/****************************************************************************** - * - * DBE DIX Procedure: ProcDbeGetVersion - * - * Description: - * - * This function is for processing a DbeGetVersion request. - * This request returns the major and minor version numbers of this - * extension. - * - * Return Values: - * - * Success - * - *****************************************************************************/ - -static int -ProcDbeGetVersion(ClientPtr client) -{ - /* REQUEST(xDbeGetVersionReq); */ - xDbeGetVersionReply rep; - register int n; - - - REQUEST_SIZE_MATCH(xDbeGetVersionReq); - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = DBE_MAJOR_VERSION; - rep.minorVersion = DBE_MINOR_VERSION; - - if (client->swapped) - { - swaps(&rep.sequenceNumber, n); - } - - WriteToClient(client, sizeof(xDbeGetVersionReply), (char *)&rep); - - return Success; - -} /* ProcDbeGetVersion() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: ProcDbeAllocateBackBufferName - * - * Description: - * - * This function is for processing a DbeAllocateBackBufferName request. - * This request allocates a drawable ID used to refer to the back buffer - * of a window. - * - * Return Values: - * - * BadAlloc - server can not allocate resources - * BadIDChoice - id is out of range for client; id is already in use - * BadMatch - window is not an InputOutput window; - * visual of window is not on list returned by - * DBEGetVisualInfo; - * BadValue - invalid swap action is specified - * BadWindow - window is not a valid window - * Success - * - *****************************************************************************/ - -static int -ProcDbeAllocateBackBufferName(ClientPtr client) -{ - REQUEST(xDbeAllocateBackBufferNameReq); - WindowPtr pWin; - DbeScreenPrivPtr pDbeScreenPriv; - DbeWindowPrivPtr pDbeWindowPriv; - XdbeScreenVisualInfo scrVisInfo; - register int i; - Bool visualMatched = FALSE; - xDbeSwapAction swapAction; - VisualID visual; - int status; - int add_index; - - - REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq); - - /* The window must be valid. */ - status = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess); - if (status != Success) - return status; - - /* The window must be InputOutput. */ - if (pWin->drawable.class != InputOutput) - { - return(BadMatch); - } - - /* The swap action must be valid. */ - swapAction = stuff->swapAction; /* use local var for performance. */ - if ((swapAction != XdbeUndefined ) && - (swapAction != XdbeBackground) && - (swapAction != XdbeUntouched ) && - (swapAction != XdbeCopied )) - { - return(BadValue); - } - - /* The id must be in range and not already in use. */ - LEGAL_NEW_RESOURCE(stuff->buffer, client); - - /* The visual of the window must be in the list returned by - * GetVisualInfo. - */ - pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(pWin); - if (!pDbeScreenPriv->GetVisualInfo) - return(BadMatch); /* screen doesn't support double buffering */ - - if (!(*pDbeScreenPriv->GetVisualInfo)(pWin->drawable.pScreen, &scrVisInfo)) - { - /* GetVisualInfo() failed to allocate visual info data. */ - return(BadAlloc); - } - - /* See if the window's visual is on the list. */ - visual = wVisual(pWin); - for (i = 0; (i < scrVisInfo.count) && !visualMatched; i++) - { - if (scrVisInfo.visinfo[i].visual == visual) - { - visualMatched = TRUE; - } - } - - /* Free what was allocated by the GetVisualInfo() call above. */ - free(scrVisInfo.visinfo); - - if (!visualMatched) - { - return(BadMatch); - } - - if ((pDbeWindowPriv = DBE_WINDOW_PRIV(pWin)) == NULL) - { - /* There is no buffer associated with the window. - * Allocate a window priv. - */ - - pDbeWindowPriv = calloc(1, sizeof(DbeWindowPrivRec)); - if (!pDbeWindowPriv) - return(BadAlloc); - - /* Fill out window priv information. */ - pDbeWindowPriv->pWindow = pWin; - pDbeWindowPriv->width = pWin->drawable.width; - pDbeWindowPriv->height = pWin->drawable.height; - pDbeWindowPriv->x = pWin->drawable.x; - pDbeWindowPriv->y = pWin->drawable.y; - pDbeWindowPriv->nBufferIDs = 0; - - /* Set the buffer ID array pointer to the initial (static) array). */ - pDbeWindowPriv->IDs = pDbeWindowPriv->initIDs; - - /* Initialize the buffer ID list. */ - pDbeWindowPriv->maxAvailableIDs = DBE_INIT_MAX_IDS; - pDbeWindowPriv->IDs[0] = stuff->buffer; - - add_index = 0; - for (i = 0; i < DBE_INIT_MAX_IDS; i++) - { - pDbeWindowPriv->IDs[i] = DBE_FREE_ID_ELEMENT; - } - - /* Actually connect the window priv to the window. */ - dixSetPrivate(&pWin->devPrivates, dbeWindowPrivKey, pDbeWindowPriv); - - } /* if -- There is no buffer associated with the window. */ - - else - { - /* A buffer is already associated with the window. - * Add the new buffer ID to the array, reallocating the array memory - * if necessary. - */ - - /* Determine if there is a free element in the ID array. */ - for (i = 0; i < pDbeWindowPriv->maxAvailableIDs; i++) - { - if (pDbeWindowPriv->IDs[i] == DBE_FREE_ID_ELEMENT) - { - /* There is still room in the ID array. */ - break; - } - } - - if (i == pDbeWindowPriv->maxAvailableIDs) - { - /* No more room in the ID array -- reallocate another array. */ - XID *pIDs; - - /* Setup an array pointer for the realloc operation below. */ - if (pDbeWindowPriv->maxAvailableIDs == DBE_INIT_MAX_IDS) - { - /* We will malloc a new array. */ - pIDs = NULL; - } - else - { - /* We will realloc a new array. */ - pIDs = pDbeWindowPriv->IDs; - } - - /* malloc/realloc a new array and initialize all elements to 0. */ - pDbeWindowPriv->IDs = (XID *)realloc(pIDs, - (pDbeWindowPriv->maxAvailableIDs+DBE_INCR_MAX_IDS)*sizeof(XID)); - if (!pDbeWindowPriv->IDs) - { - return(BadAlloc); - } - memset(&pDbeWindowPriv->IDs[pDbeWindowPriv->nBufferIDs], 0, - (pDbeWindowPriv->maxAvailableIDs + DBE_INCR_MAX_IDS - - pDbeWindowPriv->nBufferIDs) * sizeof(XID)); - - if (pDbeWindowPriv->maxAvailableIDs == DBE_INIT_MAX_IDS) - { - /* We just went from using the initial (static) array to a - * newly allocated array. Copy the IDs from the initial array - * to the new array. - */ - memcpy(pDbeWindowPriv->IDs, pDbeWindowPriv->initIDs, - DBE_INIT_MAX_IDS * sizeof(XID)); - } - - pDbeWindowPriv->maxAvailableIDs += DBE_INCR_MAX_IDS; - } - - add_index = i; - - } /* else -- A buffer is already associated with the window. */ - - - /* Call the DDX routine to allocate the back buffer. */ - status = (*pDbeScreenPriv->AllocBackBufferName)(pWin, stuff->buffer, - stuff->swapAction); - - if (status == Success) - { - pDbeWindowPriv->IDs[add_index] = stuff->buffer; - if (!AddResource(stuff->buffer, dbeWindowPrivResType, - (pointer)pDbeWindowPriv)) - { - pDbeWindowPriv->IDs[add_index] = DBE_FREE_ID_ELEMENT; - - if (pDbeWindowPriv->nBufferIDs == 0) { - status = BadAlloc; - goto out_free; - } - } - } else { - /* The DDX buffer allocation routine failed for the first buffer of - * this window. - */ - if (pDbeWindowPriv->nBufferIDs == 0) { - goto out_free; - } - } - - /* Increment the number of buffers (XIDs) associated with this window. */ - pDbeWindowPriv->nBufferIDs++; - - /* Set swap action on all calls. */ - pDbeWindowPriv->swapAction = stuff->swapAction; - - return(status); - -out_free: - dixSetPrivate(&pWin->devPrivates, dbeWindowPrivKey, NULL); - free(pDbeWindowPriv); - return (status); - -} /* ProcDbeAllocateBackBufferName() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: ProcDbeDeallocateBackBufferName - * - * Description: - * - * This function is for processing a DbeDeallocateBackBufferName request. - * This request frees a drawable ID that was obtained by a - * DbeAllocateBackBufferName request. - * - * Return Values: - * - * BadBuffer - buffer to deallocate is not associated with a window - * Success - * - *****************************************************************************/ - -static int -ProcDbeDeallocateBackBufferName(ClientPtr client) -{ - REQUEST(xDbeDeallocateBackBufferNameReq); - DbeWindowPrivPtr pDbeWindowPriv; - int rc, i; - pointer val; - - - REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq); - - /* Buffer name must be valid */ - rc = dixLookupResourceByType((pointer *)&pDbeWindowPriv, stuff->buffer, - dbeWindowPrivResType, client, - DixDestroyAccess); - if (rc != Success) - return (rc == BadValue) ? dbeErrorBase + DbeBadBuffer : rc; - - rc = dixLookupResourceByType(&val, stuff->buffer, dbeDrawableResType, - client, DixDestroyAccess); - if (rc != Success) - return (rc == BadValue) ? dbeErrorBase + DbeBadBuffer : rc; - - /* Make sure that the id is valid for the window. - * This is paranoid code since we already looked up the ID by type - * above. - */ - - for (i = 0; i < pDbeWindowPriv->nBufferIDs; i++) - { - /* Loop through the ID list to find the ID. */ - if (pDbeWindowPriv->IDs[i] == stuff->buffer) - { - break; - } - } - - if (i == pDbeWindowPriv->nBufferIDs) - { - /* We did not find the ID in the ID list. */ - client->errorValue = stuff->buffer; - return(dbeErrorBase + DbeBadBuffer); - } - - FreeResource(stuff->buffer, RT_NONE); - - return(Success); - -} /* ProcDbeDeallocateBackBufferName() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: ProcDbeSwapBuffers - * - * Description: - * - * This function is for processing a DbeSwapBuffers request. - * This request swaps the buffers for all windows listed, applying the - * appropriate swap action for each window. - * - * Return Values: - * - * BadAlloc - local allocation failed; this return value is not defined - * by the protocol - * BadMatch - a window in request is not double-buffered; a window in - * request is listed more than once - * BadValue - invalid swap action is specified; no swap action is - * specified - * BadWindow - a window in request is not valid - * Success - * - *****************************************************************************/ - -static int -ProcDbeSwapBuffers(ClientPtr client) -{ - REQUEST(xDbeSwapBuffersReq); - WindowPtr pWin; - DbeScreenPrivPtr pDbeScreenPriv; - DbeSwapInfoPtr swapInfo; - xDbeSwapInfo *dbeSwapInfo; - int error; - register int i, j; - int nStuff; - - - REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); - nStuff = stuff->n; /* use local variable for performance. */ - - if (nStuff == 0) - { - return(Success); - } - - if (nStuff > UINT32_MAX / sizeof(DbeSwapInfoRec)) - return BadAlloc; - - /* Get to the swap info appended to the end of the request. */ - dbeSwapInfo = (xDbeSwapInfo *)&stuff[1]; - - /* Allocate array to record swap information. */ - swapInfo = (DbeSwapInfoPtr)malloc(nStuff * sizeof(DbeSwapInfoRec)); - if (swapInfo == NULL) - { - return(BadAlloc); - } - - - for (i = 0; i < nStuff; i++) - { - /* Check all windows to swap. */ - - /* Each window must be a valid window - BadWindow. */ - error = dixLookupWindow(&pWin, dbeSwapInfo[i].window, client, - DixWriteAccess); - if (error != Success) { - free(swapInfo); - return error; - } - - /* Each window must be double-buffered - BadMatch. */ - if (DBE_WINDOW_PRIV(pWin) == NULL) - { - free(swapInfo); - return(BadMatch); - } - - /* Each window must only be specified once - BadMatch. */ - for (j = i + 1; j < nStuff; j++) - { - if (dbeSwapInfo[i].window == dbeSwapInfo[j].window) - { - free(swapInfo); - return(BadMatch); - } - } - - /* Each swap action must be valid - BadValue. */ - if ((dbeSwapInfo[i].swapAction != XdbeUndefined ) && - (dbeSwapInfo[i].swapAction != XdbeBackground) && - (dbeSwapInfo[i].swapAction != XdbeUntouched ) && - (dbeSwapInfo[i].swapAction != XdbeCopied )) - { - free(swapInfo); - return(BadValue); - } - - /* Everything checks out OK. Fill in the swap info array. */ - swapInfo[i].pWindow = pWin; - swapInfo[i].swapAction = dbeSwapInfo[i].swapAction; - - } /* for (i = 0; i < nStuff; i++) */ - - - /* Call the DDX routine to perform the swap(s). The DDX routine should - * scan the swap list (swap info), swap any buffers that it knows how to - * handle, delete them from the list, and update nStuff to indicate how - * many windows it did not handle. - * - * This scheme allows a range of sophistication in the DDX SwapBuffers() - * implementation. Naive implementations could just swap the first buffer - * in the list, move the last buffer to the front, decrement nStuff, and - * return. The next level of sophistication could be to scan the whole - * list for windows on the same screen. Up another level, the DDX routine - * could deal with cross-screen synchronization. - */ - - while (nStuff > 0) - { - pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(swapInfo[0].pWindow); - error = (*pDbeScreenPriv->SwapBuffers)(client, &nStuff, swapInfo); - if (error != Success) - { - free(swapInfo); - return(error); - } - } - - free(swapInfo); - return(Success); - -} /* ProcDbeSwapBuffers() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: ProcDbeBeginIdiom - * - * Description: - * - * This function is for processing a DbeBeginIdiom request. - * This request informs the server that a complex swap will immediately - * follow this request. - * - * Return Values: - * - * Success - * - *****************************************************************************/ - -static int -ProcDbeBeginIdiom(ClientPtr client) -{ - /* REQUEST(xDbeBeginIdiomReq); */ - DbeScreenPrivPtr pDbeScreenPriv; - register int i; - - - REQUEST_SIZE_MATCH(xDbeBeginIdiomReq); - - for (i = 0; i < screenInfo.numScreens; i++) - { - pDbeScreenPriv = DBE_SCREEN_PRIV(screenInfo.screens[i]); - - /* Call the DDX begin idiom procedure if there is one. */ - if (pDbeScreenPriv->BeginIdiom) - { - (*pDbeScreenPriv->BeginIdiom)(client); - } - } - - return(Success); - -} /* ProcDbeBeginIdiom() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: ProcDbeGetVisualInfo - * - * Description: - * - * This function is for processing a ProcDbeGetVisualInfo request. - * This request returns information about which visuals support - * double buffering. - * - * Return Values: - * - * BadDrawable - value in screen specifiers is not a valid drawable - * Success - * - *****************************************************************************/ - -static int -ProcDbeGetVisualInfo(ClientPtr client) -{ - REQUEST(xDbeGetVisualInfoReq); - DbeScreenPrivPtr pDbeScreenPriv; - xDbeGetVisualInfoReply rep; - Drawable *drawables; - DrawablePtr *pDrawables = NULL; - register int i, j, n, rc; - register int count; /* number of visual infos in reply */ - register int length; /* length of reply */ - ScreenPtr pScreen; - XdbeScreenVisualInfo *pScrVisInfo; - - - REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq); - - if (stuff->n > UINT32_MAX / sizeof(DrawablePtr)) - return BadAlloc; - /* Make sure any specified drawables are valid. */ - if (stuff->n != 0) - { - if (!(pDrawables = (DrawablePtr *)malloc(stuff->n * - sizeof(DrawablePtr)))) - { - return(BadAlloc); - } - - drawables = (Drawable *)&stuff[1]; - - for (i = 0; i < stuff->n; i++) - { - rc = dixLookupDrawable(pDrawables+i, drawables[i], client, 0, - DixGetAttrAccess); - if (rc != Success) { - free(pDrawables); - return rc; - } - } - } - - count = (stuff->n == 0) ? screenInfo.numScreens : stuff->n; - if (!(pScrVisInfo = (XdbeScreenVisualInfo *)malloc(count * - sizeof(XdbeScreenVisualInfo)))) - { - if (pDrawables) - { - free(pDrawables); - } - - return(BadAlloc); - } - - length = 0; - - for (i = 0; i < count; i++) - { - pScreen = (stuff->n == 0) ? screenInfo.screens[i] : - pDrawables[i]->pScreen; - pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); - - rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess); - if ((rc != Success) || - !(*pDbeScreenPriv->GetVisualInfo)(pScreen, &pScrVisInfo[i])) - { - /* We failed to alloc pScrVisInfo[i].visinfo. */ - - /* Free visinfos that we allocated for previous screen infos.*/ - for (j = 0; j < i; j++) - { - free(pScrVisInfo[j].visinfo); - } - - /* Free pDrawables if we needed to allocate it above. */ - if (pDrawables) - { - free(pDrawables); - } - - return (rc == Success) ? BadAlloc : rc; - } - - /* Account for n, number of xDbeVisInfo items in list. */ - length += sizeof(CARD32); - - /* Account for n xDbeVisInfo items */ - length += pScrVisInfo[i].count * sizeof(xDbeVisInfo); - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = bytes_to_int32(length); - rep.m = count; - - if (client->swapped) - { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.m, n); - } - - /* Send off reply. */ - WriteToClient(client, sizeof(xDbeGetVisualInfoReply), (char *)&rep); - - for (i = 0; i < count; i++) - { - CARD32 data32; - - /* For each screen in the reply, send off the visual info */ - - /* Send off number of visuals. */ - data32 = (CARD32)pScrVisInfo[i].count; - - if (client->swapped) - { - swapl(&data32, n); - } - - WriteToClient(client, sizeof(CARD32), (char *)&data32); - - /* Now send off visual info items. */ - for (j = 0; j < pScrVisInfo[i].count; j++) - { - xDbeVisInfo visInfo; - - /* Copy the data in the client data structure to a protocol - * data structure. We will send data to the client from the - * protocol data structure. - */ - - visInfo.visualID = (CARD32)pScrVisInfo[i].visinfo[j].visual; - visInfo.depth = (CARD8) pScrVisInfo[i].visinfo[j].depth; - visInfo.perfLevel = (CARD8) pScrVisInfo[i].visinfo[j].perflevel; - - if (client->swapped) - { - swapl(&visInfo.visualID, n); - - /* We do not need to swap depth and perfLevel since they are - * already 1 byte quantities. - */ - } - - /* Write visualID(32), depth(8), perfLevel(8), and pad(16). */ - WriteToClient(client, 2*sizeof(CARD32), (char *)&visInfo.visualID); - } - } - - /* Clean up memory. */ - for (i = 0; i < count; i++) - { - free(pScrVisInfo[i].visinfo); - } - free(pScrVisInfo); - - if (pDrawables) - { - free(pDrawables); - } - - return Success; - -} /* ProcDbeGetVisualInfo() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: ProcDbeGetbackBufferAttributes - * - * Description: - * - * This function is for processing a ProcDbeGetbackBufferAttributes - * request. This request returns information about a back buffer. - * - * Return Values: - * - * Success - * - *****************************************************************************/ - -static int -ProcDbeGetBackBufferAttributes(ClientPtr client) -{ - REQUEST(xDbeGetBackBufferAttributesReq); - xDbeGetBackBufferAttributesReply rep; - DbeWindowPrivPtr pDbeWindowPriv; - int rc, n; - - - REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq); - - rc = dixLookupResourceByType((pointer *)&pDbeWindowPriv, stuff->buffer, - dbeWindowPrivResType, client, - DixGetAttrAccess); - if (rc == Success) - { - rep.attributes = pDbeWindowPriv->pWindow->drawable.id; - } - else - { - rep.attributes = None; - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - - if (client->swapped) - { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.attributes, n); - } - - WriteToClient(client, sizeof(xDbeGetBackBufferAttributesReply), - (char *)&rep); - return Success; - -} /* ProcDbeGetbackBufferAttributes() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: ProcDbeDispatch - * - * Description: - * - * This function dispatches DBE requests. - * - *****************************************************************************/ - -static int -ProcDbeDispatch(ClientPtr client) -{ - REQUEST(xReq); - - - switch (stuff->data) - { - case X_DbeGetVersion: - return(ProcDbeGetVersion(client)); - - case X_DbeAllocateBackBufferName: - return(ProcDbeAllocateBackBufferName(client)); - - case X_DbeDeallocateBackBufferName: - return(ProcDbeDeallocateBackBufferName(client)); - - case X_DbeSwapBuffers: - return(ProcDbeSwapBuffers(client)); - - case X_DbeBeginIdiom: - return(ProcDbeBeginIdiom(client)); - - case X_DbeEndIdiom: - return(Success); - - case X_DbeGetVisualInfo: - return(ProcDbeGetVisualInfo(client)); - - case X_DbeGetBackBufferAttributes: - return(ProcDbeGetBackBufferAttributes(client)); - - default: - return(BadRequest); - } - -} /* ProcDbeDispatch() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: SProcDbeGetVersion - * - * Description: - * - * This function is for processing a DbeGetVersion request on a swapped - * server. This request returns the major and minor version numbers of - * this extension. - * - * Return Values: - * - * Success - * - *****************************************************************************/ - -static int -SProcDbeGetVersion(ClientPtr client) -{ - REQUEST(xDbeGetVersionReq); - register int n; - - - swaps(&stuff->length, n); - return(ProcDbeGetVersion(client)); - -} /* SProcDbeGetVersion() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: SProcDbeAllocateBackBufferName - * - * Description: - * - * This function is for processing a DbeAllocateBackBufferName request on - * a swapped server. This request allocates a drawable ID used to refer - * to the back buffer of a window. - * - * Return Values: - * - * BadAlloc - server can not allocate resources - * BadIDChoice - id is out of range for client; id is already in use - * BadMatch - window is not an InputOutput window; - * visual of window is not on list returned by - * DBEGetVisualInfo; - * BadValue - invalid swap action is specified - * BadWindow - window is not a valid window - * Success - * - *****************************************************************************/ - -static int -SProcDbeAllocateBackBufferName(ClientPtr client) -{ - REQUEST(xDbeAllocateBackBufferNameReq); - register int n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq); - - swapl(&stuff->window, n); - swapl(&stuff->buffer, n); - /* stuff->swapAction is a byte. We do not need to swap this field. */ - - return(ProcDbeAllocateBackBufferName(client)); - -} /* SProcDbeAllocateBackBufferName() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: SProcDbeDeallocateBackBufferName - * - * Description: - * - * This function is for processing a DbeDeallocateBackBufferName request - * on a swapped server. This request frees a drawable ID that was - * obtained by a DbeAllocateBackBufferName request. - * - * Return Values: - * - * BadBuffer - buffer to deallocate is not associated with a window - * Success - * - *****************************************************************************/ - -static int -SProcDbeDeallocateBackBufferName(ClientPtr client) -{ - REQUEST (xDbeDeallocateBackBufferNameReq); - register int n; - - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq); - - swapl(&stuff->buffer, n); - - return(ProcDbeDeallocateBackBufferName(client)); - -} /* SProcDbeDeallocateBackBufferName() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: SProcDbeSwapBuffers - * - * Description: - * - * This function is for processing a DbeSwapBuffers request on a swapped - * server. This request swaps the buffers for all windows listed, - * applying the appropriate swap action for each window. - * - * Return Values: - * - * BadMatch - a window in request is not double-buffered; a window in - * request is listed more than once; all windows in request do - * not have the same root - * BadValue - invalid swap action is specified - * BadWindow - a window in request is not valid - * Success - * - *****************************************************************************/ - -static int -SProcDbeSwapBuffers(ClientPtr client) -{ - REQUEST(xDbeSwapBuffersReq); - register int i, n; - xDbeSwapInfo *pSwapInfo; - - - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); - - swapl(&stuff->n, n); - - if (stuff->n != 0) - { - pSwapInfo = (xDbeSwapInfo *)stuff+1; - - /* The swap info following the fix part of this request is a window(32) - * followed by a 1 byte swap action and then 3 pad bytes. We only need - * to swap the window information. - */ - for (i = 0; i < stuff->n; i++) - { - swapl(&pSwapInfo->window, n); - } - } - - return(ProcDbeSwapBuffers(client)); - -} /* SProcDbeSwapBuffers() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: SProcDbeBeginIdiom - * - * Description: - * - * This function is for processing a DbeBeginIdiom request on a swapped - * server. This request informs the server that a complex swap will - * immediately follow this request. - * - * Return Values: - * - * Success - * - *****************************************************************************/ - -static int -SProcDbeBeginIdiom(ClientPtr client) -{ - REQUEST(xDbeBeginIdiomReq); - register int n; - - swaps(&stuff->length, n); - return(ProcDbeBeginIdiom(client)); - -} /* SProcDbeBeginIdiom() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: SProcDbeGetVisualInfo - * - * Description: - * - * This function is for processing a ProcDbeGetVisualInfo request on a - * swapped server. This request returns information about which visuals - * support double buffering. - * - * Return Values: - * - * BadDrawable - value in screen specifiers is not a valid drawable - * Success - * - *****************************************************************************/ - -static int -SProcDbeGetVisualInfo(ClientPtr client) -{ - REQUEST(xDbeGetVisualInfoReq); - register int n; - - - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq); - - swapl(&stuff->n, n); - SwapRestL(stuff); - - return(ProcDbeGetVisualInfo(client)); - -} /* SProcDbeGetVisualInfo() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: SProcDbeGetbackBufferAttributes - * - * Description: - * - * This function is for processing a ProcDbeGetbackBufferAttributes - * request on a swapped server. This request returns information about a - * back buffer. - * - * Return Values: - * - * Success - * - *****************************************************************************/ - -static int -SProcDbeGetBackBufferAttributes(ClientPtr client) -{ - REQUEST (xDbeGetBackBufferAttributesReq); - register int n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq); - - swapl(&stuff->buffer, n); - - return(ProcDbeGetBackBufferAttributes(client)); - -} /* SProcDbeGetBackBufferAttributes() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: SProcDbeDispatch - * - * Description: - * - * This function dispatches DBE requests on a swapped server. - * - *****************************************************************************/ - -static int -SProcDbeDispatch(ClientPtr client) -{ - REQUEST(xReq); - - - switch (stuff->data) - { - case X_DbeGetVersion: - return(SProcDbeGetVersion(client)); - - case X_DbeAllocateBackBufferName: - return(SProcDbeAllocateBackBufferName(client)); - - case X_DbeDeallocateBackBufferName: - return(SProcDbeDeallocateBackBufferName(client)); - - case X_DbeSwapBuffers: - return(SProcDbeSwapBuffers(client)); - - case X_DbeBeginIdiom: - return(SProcDbeBeginIdiom(client)); - - case X_DbeEndIdiom: - return(Success); - - case X_DbeGetVisualInfo: - return(SProcDbeGetVisualInfo(client)); - - case X_DbeGetBackBufferAttributes: - return(SProcDbeGetBackBufferAttributes(client)); - - default: - return (BadRequest); - } - -} /* SProcDbeDispatch() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: DbeSetupBackgroundPainter - * - * Description: - * - * This function sets up pGC to clear pixmaps. - * - * Return Values: - * - * TRUE - setup was successful - * FALSE - the window's background state is NONE - * - *****************************************************************************/ - -static Bool -DbeSetupBackgroundPainter(WindowPtr pWin, GCPtr pGC) -{ - ChangeGCVal gcvalues[4]; - int ts_x_origin, ts_y_origin; - PixUnion background; - int backgroundState; - Mask gcmask; - - - /* First take care of any ParentRelative stuff by altering the - * tile/stipple origin to match the coordinates of the upper-left - * corner of the first ancestor without a ParentRelative background. - * This coordinate is, of course, negative. - */ - ts_x_origin = ts_y_origin = 0; - while (pWin->backgroundState == ParentRelative) - { - ts_x_origin -= pWin->origin.x; - ts_y_origin -= pWin->origin.y; - - pWin = pWin->parent; - } - backgroundState = pWin->backgroundState; - background = pWin->background; - - switch (backgroundState) - { - case BackgroundPixel: - gcvalues[0].val = background.pixel; - gcvalues[1].val = FillSolid; - gcmask = GCForeground|GCFillStyle; - break; - - case BackgroundPixmap: - gcvalues[0].val = FillTiled; - gcvalues[1].ptr = background.pixmap; - gcvalues[2].val = ts_x_origin; - gcvalues[3].val = ts_y_origin; - gcmask = GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin; - break; - - default: - /* pWin->backgroundState == None */ - return(FALSE); - } - - return ChangeGC(NullClient, pGC, gcmask, gcvalues) == 0; -} /* DbeSetupBackgroundPainter() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: DbeDrawableDelete - * - * Description: - * - * This is the resource delete function for dbeDrawableResType. - * It is registered when the drawable resource type is created in - * DbeExtensionInit(). - * - * To make resource deletion simple, we do not do anything in this function - * and leave all resource deleteion to DbeWindowPrivDelete(), which will - * eventually be called or already has been called. Deletion functions are - * not guaranteed to be called in any particular order. - * - *****************************************************************************/ -static int -DbeDrawableDelete(pointer pDrawable, XID id) -{ - return(Success); - -} /* DbeDrawableDelete() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: DbeWindowPrivDelete - * - * Description: - * - * This is the resource delete function for dbeWindowPrivResType. - * It is registered when the drawable resource type is created in - * DbeExtensionInit(). - * - *****************************************************************************/ -static int -DbeWindowPrivDelete(pointer pDbeWinPriv, XID id) -{ - DbeScreenPrivPtr pDbeScreenPriv; - DbeWindowPrivPtr pDbeWindowPriv = (DbeWindowPrivPtr)pDbeWinPriv; - int i; - - - /* - ************************************************************************** - ** Remove the buffer ID from the ID array. - ************************************************************************** - */ - - /* Find the ID in the ID array. */ - i = 0; - while ((i < pDbeWindowPriv->nBufferIDs) && (pDbeWindowPriv->IDs[i] != id)) - { - i++; - } - - if (i == pDbeWindowPriv->nBufferIDs) - { - /* We did not find the ID in the array. We should never get here. */ - return(BadValue); - } - - /* Remove the ID from the array. */ - - if (i < (pDbeWindowPriv->nBufferIDs - 1)) - { - /* Compress the buffer ID array, overwriting the ID in the process. */ - memmove(&pDbeWindowPriv->IDs[i], &pDbeWindowPriv->IDs[i+1], - (pDbeWindowPriv->nBufferIDs - i - 1) * sizeof(XID)); - } - else - { - /* We are removing the last ID in the array, in which case, the - * assignement below is all that we need to do. - */ - } - pDbeWindowPriv->IDs[pDbeWindowPriv->nBufferIDs - 1] = DBE_FREE_ID_ELEMENT; - - pDbeWindowPriv->nBufferIDs--; - - /* If an extended array was allocated, then check to see if the remaining - * buffer IDs will fit in the static array. - */ - - if ((pDbeWindowPriv->maxAvailableIDs > DBE_INIT_MAX_IDS) && - (pDbeWindowPriv->nBufferIDs == DBE_INIT_MAX_IDS)) - { - /* Copy the IDs back into the static array. */ - memcpy(pDbeWindowPriv->initIDs, pDbeWindowPriv->IDs, - DBE_INIT_MAX_IDS * sizeof(XID)); - - /* Free the extended array; use the static array. */ - free(pDbeWindowPriv->IDs); - pDbeWindowPriv->IDs = pDbeWindowPriv->initIDs; - pDbeWindowPriv->maxAvailableIDs = DBE_INIT_MAX_IDS; - } - - - /* - ************************************************************************** - ** Perform DDX level tasks. - ************************************************************************** - */ - - pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW_PRIV( - (DbeWindowPrivPtr)pDbeWindowPriv); - (*pDbeScreenPriv->WinPrivDelete)((DbeWindowPrivPtr)pDbeWindowPriv, id); - - - /* - ************************************************************************** - ** Perform miscellaneous tasks if this is the last buffer associated - ** with the window. - ************************************************************************** - */ - - if (pDbeWindowPriv->nBufferIDs == 0) - { - /* Reset the DBE window priv pointer. */ - dixSetPrivate(&pDbeWindowPriv->pWindow->devPrivates, dbeWindowPrivKey, - NULL); - - /* We are done with the window priv. */ - dixFreePrivates(pDbeWindowPriv->devPrivates); - free(pDbeWindowPriv); - } - - return(Success); - -} /* DbeWindowPrivDelete() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: DbeResetProc - * - * Description: - * - * This routine is called at the end of every server generation. - * It deallocates any memory reserved for the extension and performs any - * other tasks related to shutting down the extension. - * - *****************************************************************************/ -static void -DbeResetProc(ExtensionEntry *extEntry) -{ - int i; - ScreenPtr pScreen; - DbeScreenPrivPtr pDbeScreenPriv; - - for (i = 0; i < screenInfo.numScreens; i++) - { - pScreen = screenInfo.screens[i]; - pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); - - if (pDbeScreenPriv) - { - /* Unwrap DestroyWindow, which was wrapped in DbeExtensionInit().*/ - pScreen->DestroyWindow = pDbeScreenPriv->DestroyWindow; - - if (pDbeScreenPriv->ResetProc) - (*pDbeScreenPriv->ResetProc)(pScreen); - - free(pDbeScreenPriv); - } - } -} /* DbeResetProc() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: DbeDestroyWindow - * - * Description: - * - * This is the wrapper for pScreen->DestroyWindow. - * This function frees buffer resources for a window before it is - * destroyed. - * - *****************************************************************************/ - -static Bool -DbeDestroyWindow(WindowPtr pWin) -{ - DbeScreenPrivPtr pDbeScreenPriv; - DbeWindowPrivPtr pDbeWindowPriv; - ScreenPtr pScreen; - Bool ret; - - - /* - ************************************************************************** - ** 1. Unwrap the member routine. - ************************************************************************** - */ - - pScreen = pWin->drawable.pScreen; - pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); - pScreen->DestroyWindow = pDbeScreenPriv->DestroyWindow; - - /* - ************************************************************************** - ** 2. Do any work necessary before the member routine is called. - ** - ** Call the window priv delete function for all buffer IDs associated - ** with this window. - ************************************************************************** - */ - - if ((pDbeWindowPriv = DBE_WINDOW_PRIV(pWin))) - { - while (pDbeWindowPriv) - { - /* *DbeWinPrivDelete() will free the window private and set it to - * NULL if there are no more buffer IDs associated with this - * window. - */ - FreeResource(pDbeWindowPriv->IDs[0], RT_NONE); - pDbeWindowPriv = DBE_WINDOW_PRIV(pWin); - } - } - - /* - ************************************************************************** - ** 3. Call the member routine, saving its result if necessary. - ************************************************************************** - */ - - ret = (*pScreen->DestroyWindow)(pWin); - - /* - ************************************************************************** - ** 4. Rewrap the member routine, restoring the wrapper value first in case - ** the wrapper (or something that it wrapped) change this value. - ************************************************************************** - */ - - pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow; - pScreen->DestroyWindow = DbeDestroyWindow; - - /* - ************************************************************************** - ** 5. Do any work necessary after the member routine has been called. - ** - ** In this case we do not need to do anything. - ************************************************************************** - */ - - return(ret); - -} /* DbeDestroyWindow() */ - - -/****************************************************************************** - * - * DBE DIX Procedure: DbeExtensionInit - * - * Description: - * - * Called from InitExtensions in main() - * - *****************************************************************************/ - -void -DbeExtensionInit(void) -{ - ExtensionEntry *extEntry; - register int i, j; - ScreenPtr pScreen = NULL; - DbeScreenPrivPtr pDbeScreenPriv; - int nStubbedScreens = 0; - Bool ddxInitSuccess; - -#ifdef PANORAMIX - if(!noPanoramiXExtension) return; -#endif - - /* Create the resource types. */ - dbeDrawableResType = - CreateNewResourceType(DbeDrawableDelete, "dbeDrawable"); - if (!dbeDrawableResType) - return; - dbeDrawableResType |= RC_DRAWABLE; - - dbeWindowPrivResType = - CreateNewResourceType(DbeWindowPrivDelete, "dbeWindow"); - if (!dbeWindowPrivResType) - return; - - if (!dixRegisterPrivateOffset(dbeDrawableResType, - offsetof(PixmapRec, devPrivates))) - return; - - for (i = 0; i < screenInfo.numScreens; i++) - { - /* For each screen, set up DBE screen privates and init DIX and DDX - * interface. - */ - - pScreen = screenInfo.screens[i]; - - if (!(pDbeScreenPriv = malloc (sizeof (DbeScreenPrivRec)))) - { - /* If we can not alloc a window or screen private, - * then free any privates that we already alloc'ed and return - */ - - for (j = 0; j < i; j++) - { - free(dixLookupPrivate(&screenInfo.screens[j]->devPrivates, - dbeScreenPrivKey)); - dixSetPrivate(&screenInfo.screens[j]->devPrivates, - dbeScreenPrivKey, NULL); - } - return; - } - - dixSetPrivate(&pScreen->devPrivates, dbeScreenPrivKey, pDbeScreenPriv); - - /* Copy the resource types */ - pDbeScreenPriv->dbeDrawableResType = dbeDrawableResType; - pDbeScreenPriv->dbeWindowPrivResType = dbeWindowPrivResType; - - /* Copy the private indices */ - pDbeScreenPriv->dbeScreenPrivKey = dbeScreenPrivKey; - pDbeScreenPriv->dbeWindowPrivKey = dbeWindowPrivKey; - - { - /* We don't have DDX support for DBE anymore */ - -#ifndef DISABLE_MI_DBE_BY_DEFAULT - /* Setup DIX. */ - pDbeScreenPriv->SetupBackgroundPainter = DbeSetupBackgroundPainter; - - /* Setup DDX. */ - ddxInitSuccess = miDbeInit(pScreen, pDbeScreenPriv); - - /* DDX DBE initialization may have the side affect of - * reallocating pDbeScreenPriv, so we need to update it. - */ - pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); - - if (ddxInitSuccess) - { - /* Wrap DestroyWindow. The DDX initialization function - * already wrapped PositionWindow for us. - */ - - pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow; - pScreen->DestroyWindow = DbeDestroyWindow; - } - else - { - /* DDX initialization failed. Stub the screen. */ - DbeStubScreen(pDbeScreenPriv, &nStubbedScreens); - } -#else - DbeStubScreen(pDbeScreenPriv, &nStubbedScreens); -#endif - - } - - } /* for (i = 0; i < screenInfo.numScreens; i++) */ - - - if (nStubbedScreens == screenInfo.numScreens) - { - /* All screens stubbed. Clean up and return. */ - - for (i = 0; i < screenInfo.numScreens; i++) - { - free(dixLookupPrivate(&screenInfo.screens[i]->devPrivates, - dbeScreenPrivKey)); - dixSetPrivate(&pScreen->devPrivates, dbeScreenPrivKey, NULL); - } - return; - } - - - /* Now add the extension. */ - extEntry = AddExtension(DBE_PROTOCOL_NAME, DbeNumberEvents, - DbeNumberErrors, ProcDbeDispatch, SProcDbeDispatch, - DbeResetProc, StandardMinorOpcode); - - dbeErrorBase = extEntry->errorBase; - -} /* DbeExtensionInit() */ - +/****************************************************************************** + * + * Copyright (c) 1994, 1995 Hewlett-Packard Company + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the Hewlett-Packard + * Company shall not be used in advertising or otherwise to promote the + * sale, use or other dealings in this Software without prior written + * authorization from the Hewlett-Packard Company. + * + * DIX DBE code + * + *****************************************************************************/ + + +/* INCLUDES */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#if HAVE_STDINT_H +#include +#elif !defined(UINT32_MAX) +#define UINT32_MAX 0xffffffffU +#endif + +#include +#include +#include "scrnintstr.h" +#include "extnsionst.h" +#include "gcstruct.h" +#include "dixstruct.h" +#define NEED_DBE_PROTOCOL +#include "dbestruct.h" +#include "midbe.h" +#include "xace.h" + +/* GLOBALS */ + +/* These are static globals copied to DBE's screen private for use by DDX */ +static int dbeScreenPrivKeyIndex; +static DevPrivateKey dbeScreenPrivKey = &dbeScreenPrivKeyIndex; +static int dbeWindowPrivKeyIndex; +static DevPrivateKey dbeWindowPrivKey = &dbeWindowPrivKeyIndex; + +/* These are static globals copied to DBE's screen private for use by DDX */ +static RESTYPE dbeDrawableResType; +static RESTYPE dbeWindowPrivResType; + +/* Used to generate DBE's BadBuffer error. */ +static int dbeErrorBase; + +/****************************************************************************** + * + * DBE DIX Procedure: DbeStubScreen + * + * Description: + * + * This is function stubs the function pointers in the given DBE screen + * private and increments the number of stubbed screens. + * + *****************************************************************************/ + +static void +DbeStubScreen(DbeScreenPrivPtr pDbeScreenPriv, int *nStubbedScreens) +{ + /* Stub DIX. */ + pDbeScreenPriv->SetupBackgroundPainter = NULL; + + /* Do not unwrap PositionWindow nor DestroyWindow. If the DDX + * initialization function failed, we assume that it did not wrap + * PositionWindow. Also, DestroyWindow is only wrapped if the DDX + * initialization function succeeded. + */ + + /* Stub DDX. */ + pDbeScreenPriv->GetVisualInfo = NULL; + pDbeScreenPriv->AllocBackBufferName = NULL; + pDbeScreenPriv->SwapBuffers = NULL; + pDbeScreenPriv->BeginIdiom = NULL; + pDbeScreenPriv->EndIdiom = NULL; + pDbeScreenPriv->WinPrivDelete = NULL; + pDbeScreenPriv->ResetProc = NULL; + + (*nStubbedScreens)++; + +} /* DbeStubScreen() */ + + + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeGetVersion + * + * Description: + * + * This function is for processing a DbeGetVersion request. + * This request returns the major and minor version numbers of this + * extension. + * + * Return Values: + * + * Success + * + *****************************************************************************/ + +static int +ProcDbeGetVersion(ClientPtr client) +{ + /* REQUEST(xDbeGetVersionReq); */ + xDbeGetVersionReply rep; + register int n; + + + REQUEST_SIZE_MATCH(xDbeGetVersionReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = DBE_MAJOR_VERSION; + rep.minorVersion = DBE_MINOR_VERSION; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + } + + WriteToClient(client, sizeof(xDbeGetVersionReply), (char *)&rep); + + return Success; + +} /* ProcDbeGetVersion() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeAllocateBackBufferName + * + * Description: + * + * This function is for processing a DbeAllocateBackBufferName request. + * This request allocates a drawable ID used to refer to the back buffer + * of a window. + * + * Return Values: + * + * BadAlloc - server can not allocate resources + * BadIDChoice - id is out of range for client; id is already in use + * BadMatch - window is not an InputOutput window; + * visual of window is not on list returned by + * DBEGetVisualInfo; + * BadValue - invalid swap action is specified + * BadWindow - window is not a valid window + * Success + * + *****************************************************************************/ + +static int +ProcDbeAllocateBackBufferName(ClientPtr client) +{ + REQUEST(xDbeAllocateBackBufferNameReq); + WindowPtr pWin; + DbeScreenPrivPtr pDbeScreenPriv; + DbeWindowPrivPtr pDbeWindowPriv; + XdbeScreenVisualInfo scrVisInfo; + register int i; + Bool visualMatched = FALSE; + xDbeSwapAction swapAction; + VisualID visual; + int status; + int add_index; + + + REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq); + + /* The window must be valid. */ + status = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess); + if (status != Success) + return status; + + /* The window must be InputOutput. */ + if (pWin->drawable.class != InputOutput) + { + return(BadMatch); + } + + /* The swap action must be valid. */ + swapAction = stuff->swapAction; /* use local var for performance. */ + if ((swapAction != XdbeUndefined ) && + (swapAction != XdbeBackground) && + (swapAction != XdbeUntouched ) && + (swapAction != XdbeCopied )) + { + return(BadValue); + } + + /* The id must be in range and not already in use. */ + LEGAL_NEW_RESOURCE(stuff->buffer, client); + + /* The visual of the window must be in the list returned by + * GetVisualInfo. + */ + pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(pWin); + if (!pDbeScreenPriv->GetVisualInfo) + return(BadMatch); /* screen doesn't support double buffering */ + + if (!(*pDbeScreenPriv->GetVisualInfo)(pWin->drawable.pScreen, &scrVisInfo)) + { + /* GetVisualInfo() failed to allocate visual info data. */ + return(BadAlloc); + } + + /* See if the window's visual is on the list. */ + visual = wVisual(pWin); + for (i = 0; (i < scrVisInfo.count) && !visualMatched; i++) + { + if (scrVisInfo.visinfo[i].visual == visual) + { + visualMatched = TRUE; + } + } + + /* Free what was allocated by the GetVisualInfo() call above. */ + free(scrVisInfo.visinfo); + + if (!visualMatched) + { + return(BadMatch); + } + + if ((pDbeWindowPriv = DBE_WINDOW_PRIV(pWin)) == NULL) + { + /* There is no buffer associated with the window. + * Allocate a window priv. + */ + + pDbeWindowPriv = calloc(1, sizeof(DbeWindowPrivRec)); + if (!pDbeWindowPriv) + return(BadAlloc); + + /* Fill out window priv information. */ + pDbeWindowPriv->pWindow = pWin; + pDbeWindowPriv->width = pWin->drawable.width; + pDbeWindowPriv->height = pWin->drawable.height; + pDbeWindowPriv->x = pWin->drawable.x; + pDbeWindowPriv->y = pWin->drawable.y; + pDbeWindowPriv->nBufferIDs = 0; + + /* Set the buffer ID array pointer to the initial (static) array). */ + pDbeWindowPriv->IDs = pDbeWindowPriv->initIDs; + + /* Initialize the buffer ID list. */ + pDbeWindowPriv->maxAvailableIDs = DBE_INIT_MAX_IDS; + pDbeWindowPriv->IDs[0] = stuff->buffer; + + add_index = 0; + for (i = 0; i < DBE_INIT_MAX_IDS; i++) + { + pDbeWindowPriv->IDs[i] = DBE_FREE_ID_ELEMENT; + } + + /* Actually connect the window priv to the window. */ + dixSetPrivate(&pWin->devPrivates, dbeWindowPrivKey, pDbeWindowPriv); + + } /* if -- There is no buffer associated with the window. */ + + else + { + /* A buffer is already associated with the window. + * Add the new buffer ID to the array, reallocating the array memory + * if necessary. + */ + + /* Determine if there is a free element in the ID array. */ + for (i = 0; i < pDbeWindowPriv->maxAvailableIDs; i++) + { + if (pDbeWindowPriv->IDs[i] == DBE_FREE_ID_ELEMENT) + { + /* There is still room in the ID array. */ + break; + } + } + + if (i == pDbeWindowPriv->maxAvailableIDs) + { + /* No more room in the ID array -- reallocate another array. */ + XID *pIDs; + + /* Setup an array pointer for the realloc operation below. */ + if (pDbeWindowPriv->maxAvailableIDs == DBE_INIT_MAX_IDS) + { + /* We will malloc a new array. */ + pIDs = NULL; + } + else + { + /* We will realloc a new array. */ + pIDs = pDbeWindowPriv->IDs; + } + + /* malloc/realloc a new array and initialize all elements to 0. */ + pDbeWindowPriv->IDs = (XID *)realloc(pIDs, + (pDbeWindowPriv->maxAvailableIDs+DBE_INCR_MAX_IDS)*sizeof(XID)); + if (!pDbeWindowPriv->IDs) + { + return(BadAlloc); + } + memset(&pDbeWindowPriv->IDs[pDbeWindowPriv->nBufferIDs], 0, + (pDbeWindowPriv->maxAvailableIDs + DBE_INCR_MAX_IDS - + pDbeWindowPriv->nBufferIDs) * sizeof(XID)); + + if (pDbeWindowPriv->maxAvailableIDs == DBE_INIT_MAX_IDS) + { + /* We just went from using the initial (static) array to a + * newly allocated array. Copy the IDs from the initial array + * to the new array. + */ + memcpy(pDbeWindowPriv->IDs, pDbeWindowPriv->initIDs, + DBE_INIT_MAX_IDS * sizeof(XID)); + } + + pDbeWindowPriv->maxAvailableIDs += DBE_INCR_MAX_IDS; + } + + add_index = i; + + } /* else -- A buffer is already associated with the window. */ + + + /* Call the DDX routine to allocate the back buffer. */ + status = (*pDbeScreenPriv->AllocBackBufferName)(pWin, stuff->buffer, + stuff->swapAction); + + if (status == Success) + { + pDbeWindowPriv->IDs[add_index] = stuff->buffer; + if (!AddResource(stuff->buffer, dbeWindowPrivResType, + (pointer)pDbeWindowPriv)) + { + pDbeWindowPriv->IDs[add_index] = DBE_FREE_ID_ELEMENT; + + if (pDbeWindowPriv->nBufferIDs == 0) { + status = BadAlloc; + goto out_free; + } + } + } else { + /* The DDX buffer allocation routine failed for the first buffer of + * this window. + */ + if (pDbeWindowPriv->nBufferIDs == 0) { + goto out_free; + } + } + + /* Increment the number of buffers (XIDs) associated with this window. */ + pDbeWindowPriv->nBufferIDs++; + + /* Set swap action on all calls. */ + pDbeWindowPriv->swapAction = stuff->swapAction; + + return(status); + +out_free: + dixSetPrivate(&pWin->devPrivates, dbeWindowPrivKey, NULL); + free(pDbeWindowPriv); + return (status); + +} /* ProcDbeAllocateBackBufferName() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeDeallocateBackBufferName + * + * Description: + * + * This function is for processing a DbeDeallocateBackBufferName request. + * This request frees a drawable ID that was obtained by a + * DbeAllocateBackBufferName request. + * + * Return Values: + * + * BadBuffer - buffer to deallocate is not associated with a window + * Success + * + *****************************************************************************/ + +static int +ProcDbeDeallocateBackBufferName(ClientPtr client) +{ + REQUEST(xDbeDeallocateBackBufferNameReq); + DbeWindowPrivPtr pDbeWindowPriv; + int rc, i; + pointer val; + + + REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq); + + /* Buffer name must be valid */ + rc = dixLookupResourceByType((pointer *)&pDbeWindowPriv, stuff->buffer, + dbeWindowPrivResType, client, + DixDestroyAccess); + if (rc != Success) + return rc; + + rc = dixLookupResourceByType(&val, stuff->buffer, dbeDrawableResType, + client, DixDestroyAccess); + if (rc != Success) + return rc; + + /* Make sure that the id is valid for the window. + * This is paranoid code since we already looked up the ID by type + * above. + */ + + for (i = 0; i < pDbeWindowPriv->nBufferIDs; i++) + { + /* Loop through the ID list to find the ID. */ + if (pDbeWindowPriv->IDs[i] == stuff->buffer) + { + break; + } + } + + if (i == pDbeWindowPriv->nBufferIDs) + { + /* We did not find the ID in the ID list. */ + client->errorValue = stuff->buffer; + return(dbeErrorBase + DbeBadBuffer); + } + + FreeResource(stuff->buffer, RT_NONE); + + return(Success); + +} /* ProcDbeDeallocateBackBufferName() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeSwapBuffers + * + * Description: + * + * This function is for processing a DbeSwapBuffers request. + * This request swaps the buffers for all windows listed, applying the + * appropriate swap action for each window. + * + * Return Values: + * + * BadAlloc - local allocation failed; this return value is not defined + * by the protocol + * BadMatch - a window in request is not double-buffered; a window in + * request is listed more than once + * BadValue - invalid swap action is specified; no swap action is + * specified + * BadWindow - a window in request is not valid + * Success + * + *****************************************************************************/ + +static int +ProcDbeSwapBuffers(ClientPtr client) +{ + REQUEST(xDbeSwapBuffersReq); + WindowPtr pWin; + DbeScreenPrivPtr pDbeScreenPriv; + DbeSwapInfoPtr swapInfo; + xDbeSwapInfo *dbeSwapInfo; + int error; + register int i, j; + int nStuff; + + + REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); + nStuff = stuff->n; /* use local variable for performance. */ + + if (nStuff == 0) + { + return(Success); + } + + if (nStuff > UINT32_MAX / sizeof(DbeSwapInfoRec)) + return BadAlloc; + + /* Get to the swap info appended to the end of the request. */ + dbeSwapInfo = (xDbeSwapInfo *)&stuff[1]; + + /* Allocate array to record swap information. */ + swapInfo = (DbeSwapInfoPtr)malloc(nStuff * sizeof(DbeSwapInfoRec)); + if (swapInfo == NULL) + { + return(BadAlloc); + } + + + for (i = 0; i < nStuff; i++) + { + /* Check all windows to swap. */ + + /* Each window must be a valid window - BadWindow. */ + error = dixLookupWindow(&pWin, dbeSwapInfo[i].window, client, + DixWriteAccess); + if (error != Success) { + free(swapInfo); + return error; + } + + /* Each window must be double-buffered - BadMatch. */ + if (DBE_WINDOW_PRIV(pWin) == NULL) + { + free(swapInfo); + return(BadMatch); + } + + /* Each window must only be specified once - BadMatch. */ + for (j = i + 1; j < nStuff; j++) + { + if (dbeSwapInfo[i].window == dbeSwapInfo[j].window) + { + free(swapInfo); + return(BadMatch); + } + } + + /* Each swap action must be valid - BadValue. */ + if ((dbeSwapInfo[i].swapAction != XdbeUndefined ) && + (dbeSwapInfo[i].swapAction != XdbeBackground) && + (dbeSwapInfo[i].swapAction != XdbeUntouched ) && + (dbeSwapInfo[i].swapAction != XdbeCopied )) + { + free(swapInfo); + return(BadValue); + } + + /* Everything checks out OK. Fill in the swap info array. */ + swapInfo[i].pWindow = pWin; + swapInfo[i].swapAction = dbeSwapInfo[i].swapAction; + + } /* for (i = 0; i < nStuff; i++) */ + + + /* Call the DDX routine to perform the swap(s). The DDX routine should + * scan the swap list (swap info), swap any buffers that it knows how to + * handle, delete them from the list, and update nStuff to indicate how + * many windows it did not handle. + * + * This scheme allows a range of sophistication in the DDX SwapBuffers() + * implementation. Naive implementations could just swap the first buffer + * in the list, move the last buffer to the front, decrement nStuff, and + * return. The next level of sophistication could be to scan the whole + * list for windows on the same screen. Up another level, the DDX routine + * could deal with cross-screen synchronization. + */ + + while (nStuff > 0) + { + pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(swapInfo[0].pWindow); + error = (*pDbeScreenPriv->SwapBuffers)(client, &nStuff, swapInfo); + if (error != Success) + { + free(swapInfo); + return(error); + } + } + + free(swapInfo); + return(Success); + +} /* ProcDbeSwapBuffers() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeBeginIdiom + * + * Description: + * + * This function is for processing a DbeBeginIdiom request. + * This request informs the server that a complex swap will immediately + * follow this request. + * + * Return Values: + * + * Success + * + *****************************************************************************/ + +static int +ProcDbeBeginIdiom(ClientPtr client) +{ + /* REQUEST(xDbeBeginIdiomReq); */ + DbeScreenPrivPtr pDbeScreenPriv; + register int i; + + + REQUEST_SIZE_MATCH(xDbeBeginIdiomReq); + + for (i = 0; i < screenInfo.numScreens; i++) + { + pDbeScreenPriv = DBE_SCREEN_PRIV(screenInfo.screens[i]); + + /* Call the DDX begin idiom procedure if there is one. */ + if (pDbeScreenPriv->BeginIdiom) + { + (*pDbeScreenPriv->BeginIdiom)(client); + } + } + + return(Success); + +} /* ProcDbeBeginIdiom() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeGetVisualInfo + * + * Description: + * + * This function is for processing a ProcDbeGetVisualInfo request. + * This request returns information about which visuals support + * double buffering. + * + * Return Values: + * + * BadDrawable - value in screen specifiers is not a valid drawable + * Success + * + *****************************************************************************/ + +static int +ProcDbeGetVisualInfo(ClientPtr client) +{ + REQUEST(xDbeGetVisualInfoReq); + DbeScreenPrivPtr pDbeScreenPriv; + xDbeGetVisualInfoReply rep; + Drawable *drawables; + DrawablePtr *pDrawables = NULL; + register int i, j, n, rc; + register int count; /* number of visual infos in reply */ + register int length; /* length of reply */ + ScreenPtr pScreen; + XdbeScreenVisualInfo *pScrVisInfo; + + + REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq); + + if (stuff->n > UINT32_MAX / sizeof(DrawablePtr)) + return BadAlloc; + /* Make sure any specified drawables are valid. */ + if (stuff->n != 0) + { + if (!(pDrawables = (DrawablePtr *)malloc(stuff->n * + sizeof(DrawablePtr)))) + { + return(BadAlloc); + } + + drawables = (Drawable *)&stuff[1]; + + for (i = 0; i < stuff->n; i++) + { + rc = dixLookupDrawable(pDrawables+i, drawables[i], client, 0, + DixGetAttrAccess); + if (rc != Success) { + free(pDrawables); + return rc; + } + } + } + + count = (stuff->n == 0) ? screenInfo.numScreens : stuff->n; + if (!(pScrVisInfo = (XdbeScreenVisualInfo *)malloc(count * + sizeof(XdbeScreenVisualInfo)))) + { + if (pDrawables) + { + free(pDrawables); + } + + return(BadAlloc); + } + + length = 0; + + for (i = 0; i < count; i++) + { + pScreen = (stuff->n == 0) ? screenInfo.screens[i] : + pDrawables[i]->pScreen; + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + + rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess); + if ((rc != Success) || + !(*pDbeScreenPriv->GetVisualInfo)(pScreen, &pScrVisInfo[i])) + { + /* We failed to alloc pScrVisInfo[i].visinfo. */ + + /* Free visinfos that we allocated for previous screen infos.*/ + for (j = 0; j < i; j++) + { + free(pScrVisInfo[j].visinfo); + } + + /* Free pDrawables if we needed to allocate it above. */ + if (pDrawables) + { + free(pDrawables); + } + + return (rc == Success) ? BadAlloc : rc; + } + + /* Account for n, number of xDbeVisInfo items in list. */ + length += sizeof(CARD32); + + /* Account for n xDbeVisInfo items */ + length += pScrVisInfo[i].count * sizeof(xDbeVisInfo); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = bytes_to_int32(length); + rep.m = count; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.m, n); + } + + /* Send off reply. */ + WriteToClient(client, sizeof(xDbeGetVisualInfoReply), (char *)&rep); + + for (i = 0; i < count; i++) + { + CARD32 data32; + + /* For each screen in the reply, send off the visual info */ + + /* Send off number of visuals. */ + data32 = (CARD32)pScrVisInfo[i].count; + + if (client->swapped) + { + swapl(&data32, n); + } + + WriteToClient(client, sizeof(CARD32), (char *)&data32); + + /* Now send off visual info items. */ + for (j = 0; j < pScrVisInfo[i].count; j++) + { + xDbeVisInfo visInfo; + + /* Copy the data in the client data structure to a protocol + * data structure. We will send data to the client from the + * protocol data structure. + */ + + visInfo.visualID = (CARD32)pScrVisInfo[i].visinfo[j].visual; + visInfo.depth = (CARD8) pScrVisInfo[i].visinfo[j].depth; + visInfo.perfLevel = (CARD8) pScrVisInfo[i].visinfo[j].perflevel; + + if (client->swapped) + { + swapl(&visInfo.visualID, n); + + /* We do not need to swap depth and perfLevel since they are + * already 1 byte quantities. + */ + } + + /* Write visualID(32), depth(8), perfLevel(8), and pad(16). */ + WriteToClient(client, 2*sizeof(CARD32), (char *)&visInfo.visualID); + } + } + + /* Clean up memory. */ + for (i = 0; i < count; i++) + { + free(pScrVisInfo[i].visinfo); + } + free(pScrVisInfo); + + if (pDrawables) + { + free(pDrawables); + } + + return Success; + +} /* ProcDbeGetVisualInfo() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeGetbackBufferAttributes + * + * Description: + * + * This function is for processing a ProcDbeGetbackBufferAttributes + * request. This request returns information about a back buffer. + * + * Return Values: + * + * Success + * + *****************************************************************************/ + +static int +ProcDbeGetBackBufferAttributes(ClientPtr client) +{ + REQUEST(xDbeGetBackBufferAttributesReq); + xDbeGetBackBufferAttributesReply rep; + DbeWindowPrivPtr pDbeWindowPriv; + int rc, n; + + + REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq); + + rc = dixLookupResourceByType((pointer *)&pDbeWindowPriv, stuff->buffer, + dbeWindowPrivResType, client, + DixGetAttrAccess); + if (rc == Success) + { + rep.attributes = pDbeWindowPriv->pWindow->drawable.id; + } + else + { + rep.attributes = None; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.attributes, n); + } + + WriteToClient(client, sizeof(xDbeGetBackBufferAttributesReply), + (char *)&rep); + return Success; + +} /* ProcDbeGetbackBufferAttributes() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeDispatch + * + * Description: + * + * This function dispatches DBE requests. + * + *****************************************************************************/ + +static int +ProcDbeDispatch(ClientPtr client) +{ + REQUEST(xReq); + + + switch (stuff->data) + { + case X_DbeGetVersion: + return(ProcDbeGetVersion(client)); + + case X_DbeAllocateBackBufferName: + return(ProcDbeAllocateBackBufferName(client)); + + case X_DbeDeallocateBackBufferName: + return(ProcDbeDeallocateBackBufferName(client)); + + case X_DbeSwapBuffers: + return(ProcDbeSwapBuffers(client)); + + case X_DbeBeginIdiom: + return(ProcDbeBeginIdiom(client)); + + case X_DbeEndIdiom: + return(Success); + + case X_DbeGetVisualInfo: + return(ProcDbeGetVisualInfo(client)); + + case X_DbeGetBackBufferAttributes: + return(ProcDbeGetBackBufferAttributes(client)); + + default: + return(BadRequest); + } + +} /* ProcDbeDispatch() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeGetVersion + * + * Description: + * + * This function is for processing a DbeGetVersion request on a swapped + * server. This request returns the major and minor version numbers of + * this extension. + * + * Return Values: + * + * Success + * + *****************************************************************************/ + +static int +SProcDbeGetVersion(ClientPtr client) +{ + REQUEST(xDbeGetVersionReq); + register int n; + + + swaps(&stuff->length, n); + return(ProcDbeGetVersion(client)); + +} /* SProcDbeGetVersion() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeAllocateBackBufferName + * + * Description: + * + * This function is for processing a DbeAllocateBackBufferName request on + * a swapped server. This request allocates a drawable ID used to refer + * to the back buffer of a window. + * + * Return Values: + * + * BadAlloc - server can not allocate resources + * BadIDChoice - id is out of range for client; id is already in use + * BadMatch - window is not an InputOutput window; + * visual of window is not on list returned by + * DBEGetVisualInfo; + * BadValue - invalid swap action is specified + * BadWindow - window is not a valid window + * Success + * + *****************************************************************************/ + +static int +SProcDbeAllocateBackBufferName(ClientPtr client) +{ + REQUEST(xDbeAllocateBackBufferNameReq); + register int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq); + + swapl(&stuff->window, n); + swapl(&stuff->buffer, n); + /* stuff->swapAction is a byte. We do not need to swap this field. */ + + return(ProcDbeAllocateBackBufferName(client)); + +} /* SProcDbeAllocateBackBufferName() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeDeallocateBackBufferName + * + * Description: + * + * This function is for processing a DbeDeallocateBackBufferName request + * on a swapped server. This request frees a drawable ID that was + * obtained by a DbeAllocateBackBufferName request. + * + * Return Values: + * + * BadBuffer - buffer to deallocate is not associated with a window + * Success + * + *****************************************************************************/ + +static int +SProcDbeDeallocateBackBufferName(ClientPtr client) +{ + REQUEST (xDbeDeallocateBackBufferNameReq); + register int n; + + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq); + + swapl(&stuff->buffer, n); + + return(ProcDbeDeallocateBackBufferName(client)); + +} /* SProcDbeDeallocateBackBufferName() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeSwapBuffers + * + * Description: + * + * This function is for processing a DbeSwapBuffers request on a swapped + * server. This request swaps the buffers for all windows listed, + * applying the appropriate swap action for each window. + * + * Return Values: + * + * BadMatch - a window in request is not double-buffered; a window in + * request is listed more than once; all windows in request do + * not have the same root + * BadValue - invalid swap action is specified + * BadWindow - a window in request is not valid + * Success + * + *****************************************************************************/ + +static int +SProcDbeSwapBuffers(ClientPtr client) +{ + REQUEST(xDbeSwapBuffersReq); + register int i, n; + xDbeSwapInfo *pSwapInfo; + + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); + + swapl(&stuff->n, n); + + if (stuff->n != 0) + { + pSwapInfo = (xDbeSwapInfo *)stuff+1; + + /* The swap info following the fix part of this request is a window(32) + * followed by a 1 byte swap action and then 3 pad bytes. We only need + * to swap the window information. + */ + for (i = 0; i < stuff->n; i++) + { + swapl(&pSwapInfo->window, n); + } + } + + return(ProcDbeSwapBuffers(client)); + +} /* SProcDbeSwapBuffers() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeBeginIdiom + * + * Description: + * + * This function is for processing a DbeBeginIdiom request on a swapped + * server. This request informs the server that a complex swap will + * immediately follow this request. + * + * Return Values: + * + * Success + * + *****************************************************************************/ + +static int +SProcDbeBeginIdiom(ClientPtr client) +{ + REQUEST(xDbeBeginIdiomReq); + register int n; + + swaps(&stuff->length, n); + return(ProcDbeBeginIdiom(client)); + +} /* SProcDbeBeginIdiom() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeGetVisualInfo + * + * Description: + * + * This function is for processing a ProcDbeGetVisualInfo request on a + * swapped server. This request returns information about which visuals + * support double buffering. + * + * Return Values: + * + * BadDrawable - value in screen specifiers is not a valid drawable + * Success + * + *****************************************************************************/ + +static int +SProcDbeGetVisualInfo(ClientPtr client) +{ + REQUEST(xDbeGetVisualInfoReq); + register int n; + + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq); + + swapl(&stuff->n, n); + SwapRestL(stuff); + + return(ProcDbeGetVisualInfo(client)); + +} /* SProcDbeGetVisualInfo() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeGetbackBufferAttributes + * + * Description: + * + * This function is for processing a ProcDbeGetbackBufferAttributes + * request on a swapped server. This request returns information about a + * back buffer. + * + * Return Values: + * + * Success + * + *****************************************************************************/ + +static int +SProcDbeGetBackBufferAttributes(ClientPtr client) +{ + REQUEST (xDbeGetBackBufferAttributesReq); + register int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq); + + swapl(&stuff->buffer, n); + + return(ProcDbeGetBackBufferAttributes(client)); + +} /* SProcDbeGetBackBufferAttributes() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeDispatch + * + * Description: + * + * This function dispatches DBE requests on a swapped server. + * + *****************************************************************************/ + +static int +SProcDbeDispatch(ClientPtr client) +{ + REQUEST(xReq); + + + switch (stuff->data) + { + case X_DbeGetVersion: + return(SProcDbeGetVersion(client)); + + case X_DbeAllocateBackBufferName: + return(SProcDbeAllocateBackBufferName(client)); + + case X_DbeDeallocateBackBufferName: + return(SProcDbeDeallocateBackBufferName(client)); + + case X_DbeSwapBuffers: + return(SProcDbeSwapBuffers(client)); + + case X_DbeBeginIdiom: + return(SProcDbeBeginIdiom(client)); + + case X_DbeEndIdiom: + return(Success); + + case X_DbeGetVisualInfo: + return(SProcDbeGetVisualInfo(client)); + + case X_DbeGetBackBufferAttributes: + return(SProcDbeGetBackBufferAttributes(client)); + + default: + return (BadRequest); + } + +} /* SProcDbeDispatch() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeSetupBackgroundPainter + * + * Description: + * + * This function sets up pGC to clear pixmaps. + * + * Return Values: + * + * TRUE - setup was successful + * FALSE - the window's background state is NONE + * + *****************************************************************************/ + +static Bool +DbeSetupBackgroundPainter(WindowPtr pWin, GCPtr pGC) +{ + ChangeGCVal gcvalues[4]; + int ts_x_origin, ts_y_origin; + PixUnion background; + int backgroundState; + Mask gcmask; + + + /* First take care of any ParentRelative stuff by altering the + * tile/stipple origin to match the coordinates of the upper-left + * corner of the first ancestor without a ParentRelative background. + * This coordinate is, of course, negative. + */ + ts_x_origin = ts_y_origin = 0; + while (pWin->backgroundState == ParentRelative) + { + ts_x_origin -= pWin->origin.x; + ts_y_origin -= pWin->origin.y; + + pWin = pWin->parent; + } + backgroundState = pWin->backgroundState; + background = pWin->background; + + switch (backgroundState) + { + case BackgroundPixel: + gcvalues[0].val = background.pixel; + gcvalues[1].val = FillSolid; + gcmask = GCForeground|GCFillStyle; + break; + + case BackgroundPixmap: + gcvalues[0].val = FillTiled; + gcvalues[1].ptr = background.pixmap; + gcvalues[2].val = ts_x_origin; + gcvalues[3].val = ts_y_origin; + gcmask = GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin; + break; + + default: + /* pWin->backgroundState == None */ + return(FALSE); + } + + return ChangeGC(NullClient, pGC, gcmask, gcvalues) == 0; +} /* DbeSetupBackgroundPainter() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeDrawableDelete + * + * Description: + * + * This is the resource delete function for dbeDrawableResType. + * It is registered when the drawable resource type is created in + * DbeExtensionInit(). + * + * To make resource deletion simple, we do not do anything in this function + * and leave all resource deleteion to DbeWindowPrivDelete(), which will + * eventually be called or already has been called. Deletion functions are + * not guaranteed to be called in any particular order. + * + *****************************************************************************/ +static int +DbeDrawableDelete(pointer pDrawable, XID id) +{ + return(Success); + +} /* DbeDrawableDelete() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeWindowPrivDelete + * + * Description: + * + * This is the resource delete function for dbeWindowPrivResType. + * It is registered when the drawable resource type is created in + * DbeExtensionInit(). + * + *****************************************************************************/ +static int +DbeWindowPrivDelete(pointer pDbeWinPriv, XID id) +{ + DbeScreenPrivPtr pDbeScreenPriv; + DbeWindowPrivPtr pDbeWindowPriv = (DbeWindowPrivPtr)pDbeWinPriv; + int i; + + + /* + ************************************************************************** + ** Remove the buffer ID from the ID array. + ************************************************************************** + */ + + /* Find the ID in the ID array. */ + i = 0; + while ((i < pDbeWindowPriv->nBufferIDs) && (pDbeWindowPriv->IDs[i] != id)) + { + i++; + } + + if (i == pDbeWindowPriv->nBufferIDs) + { + /* We did not find the ID in the array. We should never get here. */ + return(BadValue); + } + + /* Remove the ID from the array. */ + + if (i < (pDbeWindowPriv->nBufferIDs - 1)) + { + /* Compress the buffer ID array, overwriting the ID in the process. */ + memmove(&pDbeWindowPriv->IDs[i], &pDbeWindowPriv->IDs[i+1], + (pDbeWindowPriv->nBufferIDs - i - 1) * sizeof(XID)); + } + else + { + /* We are removing the last ID in the array, in which case, the + * assignement below is all that we need to do. + */ + } + pDbeWindowPriv->IDs[pDbeWindowPriv->nBufferIDs - 1] = DBE_FREE_ID_ELEMENT; + + pDbeWindowPriv->nBufferIDs--; + + /* If an extended array was allocated, then check to see if the remaining + * buffer IDs will fit in the static array. + */ + + if ((pDbeWindowPriv->maxAvailableIDs > DBE_INIT_MAX_IDS) && + (pDbeWindowPriv->nBufferIDs == DBE_INIT_MAX_IDS)) + { + /* Copy the IDs back into the static array. */ + memcpy(pDbeWindowPriv->initIDs, pDbeWindowPriv->IDs, + DBE_INIT_MAX_IDS * sizeof(XID)); + + /* Free the extended array; use the static array. */ + free(pDbeWindowPriv->IDs); + pDbeWindowPriv->IDs = pDbeWindowPriv->initIDs; + pDbeWindowPriv->maxAvailableIDs = DBE_INIT_MAX_IDS; + } + + + /* + ************************************************************************** + ** Perform DDX level tasks. + ************************************************************************** + */ + + pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW_PRIV( + (DbeWindowPrivPtr)pDbeWindowPriv); + (*pDbeScreenPriv->WinPrivDelete)((DbeWindowPrivPtr)pDbeWindowPriv, id); + + + /* + ************************************************************************** + ** Perform miscellaneous tasks if this is the last buffer associated + ** with the window. + ************************************************************************** + */ + + if (pDbeWindowPriv->nBufferIDs == 0) + { + /* Reset the DBE window priv pointer. */ + dixSetPrivate(&pDbeWindowPriv->pWindow->devPrivates, dbeWindowPrivKey, + NULL); + + /* We are done with the window priv. */ + dixFreePrivates(pDbeWindowPriv->devPrivates); + free(pDbeWindowPriv); + } + + return(Success); + +} /* DbeWindowPrivDelete() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeResetProc + * + * Description: + * + * This routine is called at the end of every server generation. + * It deallocates any memory reserved for the extension and performs any + * other tasks related to shutting down the extension. + * + *****************************************************************************/ +static void +DbeResetProc(ExtensionEntry *extEntry) +{ + int i; + ScreenPtr pScreen; + DbeScreenPrivPtr pDbeScreenPriv; + + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + + if (pDbeScreenPriv) + { + /* Unwrap DestroyWindow, which was wrapped in DbeExtensionInit().*/ + pScreen->DestroyWindow = pDbeScreenPriv->DestroyWindow; + + if (pDbeScreenPriv->ResetProc) + (*pDbeScreenPriv->ResetProc)(pScreen); + + free(pDbeScreenPriv); + } + } +} /* DbeResetProc() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeDestroyWindow + * + * Description: + * + * This is the wrapper for pScreen->DestroyWindow. + * This function frees buffer resources for a window before it is + * destroyed. + * + *****************************************************************************/ + +static Bool +DbeDestroyWindow(WindowPtr pWin) +{ + DbeScreenPrivPtr pDbeScreenPriv; + DbeWindowPrivPtr pDbeWindowPriv; + ScreenPtr pScreen; + Bool ret; + + + /* + ************************************************************************** + ** 1. Unwrap the member routine. + ************************************************************************** + */ + + pScreen = pWin->drawable.pScreen; + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + pScreen->DestroyWindow = pDbeScreenPriv->DestroyWindow; + + /* + ************************************************************************** + ** 2. Do any work necessary before the member routine is called. + ** + ** Call the window priv delete function for all buffer IDs associated + ** with this window. + ************************************************************************** + */ + + if ((pDbeWindowPriv = DBE_WINDOW_PRIV(pWin))) + { + while (pDbeWindowPriv) + { + /* *DbeWinPrivDelete() will free the window private and set it to + * NULL if there are no more buffer IDs associated with this + * window. + */ + FreeResource(pDbeWindowPriv->IDs[0], RT_NONE); + pDbeWindowPriv = DBE_WINDOW_PRIV(pWin); + } + } + + /* + ************************************************************************** + ** 3. Call the member routine, saving its result if necessary. + ************************************************************************** + */ + + ret = (*pScreen->DestroyWindow)(pWin); + + /* + ************************************************************************** + ** 4. Rewrap the member routine, restoring the wrapper value first in case + ** the wrapper (or something that it wrapped) change this value. + ************************************************************************** + */ + + pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = DbeDestroyWindow; + + /* + ************************************************************************** + ** 5. Do any work necessary after the member routine has been called. + ** + ** In this case we do not need to do anything. + ************************************************************************** + */ + + return(ret); + +} /* DbeDestroyWindow() */ + + +/****************************************************************************** + * + * DBE DIX Procedure: DbeExtensionInit + * + * Description: + * + * Called from InitExtensions in main() + * + *****************************************************************************/ + +void +DbeExtensionInit(void) +{ + ExtensionEntry *extEntry; + register int i, j; + ScreenPtr pScreen = NULL; + DbeScreenPrivPtr pDbeScreenPriv; + int nStubbedScreens = 0; + Bool ddxInitSuccess; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) return; +#endif + + /* Create the resource types. */ + dbeDrawableResType = + CreateNewResourceType(DbeDrawableDelete, "dbeDrawable"); + if (!dbeDrawableResType) + return; + dbeDrawableResType |= RC_DRAWABLE; + + dbeWindowPrivResType = + CreateNewResourceType(DbeWindowPrivDelete, "dbeWindow"); + if (!dbeWindowPrivResType) + return; + + if (!dixRegisterPrivateOffset(dbeDrawableResType, + offsetof(PixmapRec, devPrivates))) + return; + + for (i = 0; i < screenInfo.numScreens; i++) + { + /* For each screen, set up DBE screen privates and init DIX and DDX + * interface. + */ + + pScreen = screenInfo.screens[i]; + + if (!(pDbeScreenPriv = malloc (sizeof (DbeScreenPrivRec)))) + { + /* If we can not alloc a window or screen private, + * then free any privates that we already alloc'ed and return + */ + + for (j = 0; j < i; j++) + { + free(dixLookupPrivate(&screenInfo.screens[j]->devPrivates, + dbeScreenPrivKey)); + dixSetPrivate(&screenInfo.screens[j]->devPrivates, + dbeScreenPrivKey, NULL); + } + return; + } + + dixSetPrivate(&pScreen->devPrivates, dbeScreenPrivKey, pDbeScreenPriv); + + /* Copy the resource types */ + pDbeScreenPriv->dbeDrawableResType = dbeDrawableResType; + pDbeScreenPriv->dbeWindowPrivResType = dbeWindowPrivResType; + + /* Copy the private indices */ + pDbeScreenPriv->dbeScreenPrivKey = dbeScreenPrivKey; + pDbeScreenPriv->dbeWindowPrivKey = dbeWindowPrivKey; + + { + /* We don't have DDX support for DBE anymore */ + +#ifndef DISABLE_MI_DBE_BY_DEFAULT + /* Setup DIX. */ + pDbeScreenPriv->SetupBackgroundPainter = DbeSetupBackgroundPainter; + + /* Setup DDX. */ + ddxInitSuccess = miDbeInit(pScreen, pDbeScreenPriv); + + /* DDX DBE initialization may have the side affect of + * reallocating pDbeScreenPriv, so we need to update it. + */ + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + + if (ddxInitSuccess) + { + /* Wrap DestroyWindow. The DDX initialization function + * already wrapped PositionWindow for us. + */ + + pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = DbeDestroyWindow; + } + else + { + /* DDX initialization failed. Stub the screen. */ + DbeStubScreen(pDbeScreenPriv, &nStubbedScreens); + } +#else + DbeStubScreen(pDbeScreenPriv, &nStubbedScreens); +#endif + + } + + } /* for (i = 0; i < screenInfo.numScreens; i++) */ + + + if (nStubbedScreens == screenInfo.numScreens) + { + /* All screens stubbed. Clean up and return. */ + + for (i = 0; i < screenInfo.numScreens; i++) + { + free(dixLookupPrivate(&screenInfo.screens[i]->devPrivates, + dbeScreenPrivKey)); + dixSetPrivate(&pScreen->devPrivates, dbeScreenPrivKey, NULL); + } + return; + } + + + /* Now add the extension. */ + extEntry = AddExtension(DBE_PROTOCOL_NAME, DbeNumberEvents, + DbeNumberErrors, ProcDbeDispatch, SProcDbeDispatch, + DbeResetProc, StandardMinorOpcode); + + dbeErrorBase = extEntry->errorBase; + SetResourceTypeErrorValue(dbeWindowPrivResType, dbeErrorBase + DbeBadBuffer); + SetResourceTypeErrorValue(dbeDrawableResType, dbeErrorBase + DbeBadBuffer); + +} /* DbeExtensionInit() */ + diff --git a/xorg-server/dix/cursor.c b/xorg-server/dix/cursor.c index 01d08bd6e..c8253bba0 100644 --- a/xorg-server/dix/cursor.c +++ b/xorg-server/dix/cursor.c @@ -316,14 +316,14 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar, if (rc != Success) { client->errorValue = source; - return (rc == BadValue) ? BadFont : rc; + return rc; } rc = dixLookupResourceByType((pointer *)&maskfont, mask, RT_FONT, client, DixUseAccess); if (rc != Success && mask != None) { client->errorValue = mask; - return (rc == BadValue) ? BadFont : rc; + return rc; } if (sourcefont != maskfont) pShare = (GlyphSharePtr)NULL; diff --git a/xorg-server/dix/dispatch.c b/xorg-server/dix/dispatch.c index fa11155cc..181fafa77 100644 --- a/xorg-server/dix/dispatch.c +++ b/xorg-server/dix/dispatch.c @@ -1240,7 +1240,7 @@ ProcCloseFont(ClientPtr client) else { client->errorValue = stuff->id; - return (rc == BadValue) ? BadFont : rc; + return rc; } } @@ -1453,7 +1453,7 @@ ProcFreePixmap(ClientPtr client) else { client->errorValue = stuff->id; - return (rc == BadValue) ? BadPixmap : rc; + return rc; } } @@ -2407,7 +2407,7 @@ ProcFreeColormap(ClientPtr client) else { client->errorValue = stuff->id; - return (rc == BadValue) ? BadColor : rc; + return rc; } } @@ -2428,7 +2428,7 @@ ProcCopyColormapAndFree(ClientPtr client) if (rc == Success) return CopyColormapAndFree(mid, pSrcMap, client->index); client->errorValue = stuff->srcCmap; - return (rc == BadValue) ? BadColor : rc; + return rc; } int @@ -2445,15 +2445,18 @@ ProcInstallColormap(ClientPtr client) goto out; rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess); - if (rc != Success) + if (rc != Success) { + if (rc == BadValue) + rc = BadColor; goto out; + } (*(pcmp->pScreen->InstallColormap)) (pcmp); return Success; out: client->errorValue = stuff->id; - return (rc == BadValue) ? BadColor : rc; + return rc; } int @@ -2470,8 +2473,11 @@ ProcUninstallColormap(ClientPtr client) goto out; rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess); - if (rc != Success) + if (rc != Success) { + if (rc == BadValue) + rc = BadColor; goto out; + } if(pcmp->mid != pcmp->pScreen->defColormap) (*(pcmp->pScreen->UninstallColormap)) (pcmp); @@ -2479,7 +2485,7 @@ ProcUninstallColormap(ClientPtr client) out: client->errorValue = stuff->id; - return (rc == BadValue) ? BadColor : rc; + return rc; } int @@ -2552,7 +2558,7 @@ ProcAllocColor (ClientPtr client) else { client->errorValue = stuff->cmap; - return (rc == BadValue) ? BadColor : rc; + return rc; } } @@ -2598,7 +2604,7 @@ ProcAllocNamedColor (ClientPtr client) else { client->errorValue = stuff->cmap; - return (rc == BadValue) ? BadColor : rc; + return rc; } } @@ -2662,7 +2668,7 @@ ProcAllocColorCells (ClientPtr client) else { client->errorValue = stuff->cmap; - return (rc == BadValue) ? BadColor : rc; + return rc; } } @@ -2724,7 +2730,7 @@ ProcAllocColorPlanes(ClientPtr client) else { client->errorValue = stuff->cmap; - return (rc == BadValue) ? BadColor : rc; + return rc; } } @@ -2751,7 +2757,7 @@ ProcFreeColors(ClientPtr client) else { client->errorValue = stuff->cmap; - return (rc == BadValue) ? BadColor : rc; + return rc; } } @@ -2778,7 +2784,7 @@ ProcStoreColors (ClientPtr client) else { client->errorValue = stuff->cmap; - return (rc == BadValue) ? BadColor : rc; + return rc; } } @@ -2808,7 +2814,7 @@ ProcStoreNamedColor (ClientPtr client) else { client->errorValue = stuff->cmap; - return (rc == BadValue) ? BadColor : rc; + return rc; } } @@ -2855,7 +2861,7 @@ ProcQueryColors(ClientPtr client) else { client->errorValue = stuff->cmap; - return (rc == BadValue) ? BadColor : rc; + return rc; } } @@ -2894,7 +2900,7 @@ ProcLookupColor(ClientPtr client) else { client->errorValue = stuff->cmap; - return (rc == BadValue) ? BadColor : rc; + return rc; } } @@ -2920,7 +2926,7 @@ ProcCreateCursor (ClientPtr client) DixReadAccess); if (rc != Success) { client->errorValue = stuff->source; - return (rc == BadValue) ? BadPixmap : rc; + return rc; } rc = dixLookupResourceByType((pointer *)&msk, stuff->mask, RT_PIXMAP, client, @@ -2930,7 +2936,7 @@ ProcCreateCursor (ClientPtr client) if (stuff->mask != None) { client->errorValue = stuff->mask; - return (rc == BadValue) ? BadPixmap : rc; + return rc; } } else if ( src->drawable.width != msk->drawable.width @@ -3031,7 +3037,7 @@ ProcFreeCursor (ClientPtr client) else { client->errorValue = stuff->id; - return (rc == BadValue) ? BadCursor : rc; + return rc; } } @@ -3741,7 +3747,6 @@ SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode, memset(&rep, 0, sizeof(xError)); rep.type = X_Error; - rep.sequenceNumber = client->sequence; rep.errorCode = errorCode; rep.majorCode = majorCode; rep.minorCode = minorCode; diff --git a/xorg-server/dix/dixfonts.c b/xorg-server/dix/dixfonts.c index 77bb52fb3..239431e2a 100644 --- a/xorg-server/dix/dixfonts.c +++ b/xorg-server/dix/dixfonts.c @@ -1238,7 +1238,6 @@ doPolyText(ClientPtr client, PTclosurePtr c) client, DixUseAccess); if (err != Success) { - err = (err == BadValue) ? BadFont : err; /* restore pFont and fid for step 4 (described below) */ pFont = oldpFont; fid = oldfid; diff --git a/xorg-server/dix/dixutils.c b/xorg-server/dix/dixutils.c index 9d5eb78eb..6b6b41d0d 100644 --- a/xorg-server/dix/dixutils.c +++ b/xorg-server/dix/dixutils.c @@ -231,9 +231,7 @@ dixLookupWindow(WindowPtr *pWin, XID id, ClientPtr client, Mask access) int dixLookupGC(GCPtr *pGC, XID id, ClientPtr client, Mask access) { - int rc; - rc = dixLookupResourceByType((pointer *)pGC, id, RT_GC, client, access); - return (rc == BadValue) ? BadGC : rc; + return dixLookupResourceByType((pointer *)pGC, id, RT_GC, client, access); } int @@ -243,10 +241,10 @@ dixLookupFontable(FontPtr *pFont, XID id, ClientPtr client, Mask access) GC *pGC; client->errorValue = id; /* EITHER font or gc */ rc = dixLookupResourceByType((pointer *) pFont, id, RT_FONT, client, access); - if (rc != BadValue) + if (rc != BadFont) return rc; rc = dixLookupResourceByType((pointer *) &pGC, id, RT_GC, client, access); - if (rc == BadValue) + if (rc == BadGC) return BadFont; if (rc == Success) *pFont = pGC->font; diff --git a/xorg-server/dix/events.c b/xorg-server/dix/events.c index a537730a9..d68eeee62 100644 --- a/xorg-server/dix/events.c +++ b/xorg-server/dix/events.c @@ -1841,7 +1841,6 @@ int TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents, int count, Mask mask, Mask filter, GrabPtr grab) { - int i; int type; #ifdef DEBUG_EVENTS @@ -1908,7 +1907,6 @@ TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents, { xEvent release = *pEvents; release.u.u.type = KeyRelease; - release.u.u.sequenceNumber = client->sequence; WriteEventsToClient(client, 1, &release); #ifdef DEBUG_EVENTS ErrorF(" (plus fake core release for repeat)"); @@ -1929,7 +1927,6 @@ TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents, { deviceKeyButtonPointer release = *(deviceKeyButtonPointer *)pEvents; release.type = DeviceKeyRelease; - release.sequenceNumber = client->sequence; #ifdef DEBUG_EVENTS ErrorF(" (plus fake xi1 release for repeat)"); #endif @@ -1943,14 +1940,6 @@ TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents, } } - type &= 0177; - if (type != KeymapNotify) - { - /* all extension events must have a sequence number */ - for (i = 0; i < count; i++) - pEvents[i].u.u.sequenceNumber = client->sequence; - } - if (BitIsOn(criticalEvents, type)) { if (client->smart_priority < SMART_MAX_PRIORITY) @@ -4708,7 +4697,7 @@ ProcChangeActivePointerGrab(ClientPtr client) if (rc != Success) { client->errorValue = stuff->cursor; - return (rc == BadValue) ? BadCursor : rc; + return rc; } } @@ -4831,7 +4820,7 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev, if (rc != Success) { client->errorValue = curs; - return (rc == BadValue) ? BadCursor : rc; + return rc; } access_mode |= DixForceAccess; } @@ -5356,7 +5345,7 @@ ProcGrabButton(ClientPtr client) if (rc != Success) { client->errorValue = stuff->cursor; - return (rc == BadValue) ? BadCursor : rc; + return rc; } access_mode |= DixForceAccess; } @@ -5619,7 +5608,7 @@ ProcRecolorCursor(ClientPtr client) if (rc != Success) { client->errorValue = stuff->cursor; - return (rc == BadValue) ? BadCursor : rc; + return rc; } pCursor->foreRed = stuff->foreRed; @@ -5669,6 +5658,13 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events) int i, eventlength = sizeof(xEvent); + if (!pClient || pClient == serverClient || pClient->clientGone) + return; + + for (i = 0; i < count; i++) + if ((events[i].u.u.type & 0x7f) != KeymapNotify) + events[i].u.u.sequenceNumber = pClient->sequence; + /* Let XKB rewrite the state, as it depends on client preferences. */ XkbFilterEvents(pClient, count, events); diff --git a/xorg-server/dix/gc.c b/xorg-server/dix/gc.c index 6281f25cd..c93b04496 100644 --- a/xorg-server/dix/gc.c +++ b/xorg-server/dix/gc.c @@ -1,1159 +1,1157 @@ -/*********************************************************** - -Copyright 1987, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -******************************************************************/ - - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include -#include "misc.h" -#include "resource.h" -#include "gcstruct.h" -#include "pixmapstr.h" -#include "dixfontstr.h" -#include "scrnintstr.h" -#include "region.h" -#include "dixstruct.h" - -#include "privates.h" -#include "dix.h" -#include "xace.h" -#include - -extern FontPtr defaultFont; - -static Bool CreateDefaultTile(GCPtr pGC); - -static unsigned char DefaultDash[2] = {4, 4}; - -void -ValidateGC(DrawablePtr pDraw, GC *pGC) -{ - (*pGC->funcs->ValidateGC) (pGC, pGC->stateChanges, pDraw); - pGC->stateChanges = 0; - pGC->serialNumber = pDraw->serialNumber; -} - - -/* - * ChangeGC/ChangeGCXIDs: - * - * The client performing the gc change must be passed so that access - * checks can be performed on any tiles, stipples, or fonts that are - * specified. ddxen can call this too; they should normally pass - * NullClient for the client since any access checking should have - * already been done at a higher level. - * - * If you have any XIDs, you must use ChangeGCXIDs: - * - * CARD32 v[2]; - * v[0] = FillTiled; - * v[1] = pid; - * ChangeGCXIDs(client, pGC, GCFillStyle|GCTile, v); - * - * However, if you need to pass a pointer to a pixmap or font, you must - * use ChangeGC: - * - * ChangeGCVal v[2]; - * v[0].val = FillTiled; - * v[1].ptr = pPixmap; - * ChangeGC(client, pGC, GCFillStyle|GCTile, v); - * - * If you have neither XIDs nor pointers, you can use either function, - * but ChangeGC will do less work. - * - * ChangeGCVal v[2]; - * v[0].val = foreground; - * v[1].val = background; - * ChangeGC(client, pGC, GCForeground|GCBackground, v); - */ - -#define NEXTVAL(_type, _var) { \ - _var = (_type)(pUnion->val); pUnion++; \ - } - -#define NEXT_PTR(_type, _var) { \ - _var = (_type)pUnion->ptr; pUnion++; } - -int -ChangeGC(ClientPtr client, GC *pGC, BITS32 mask, ChangeGCValPtr pUnion) -{ - BITS32 index2; - int error = 0; - PixmapPtr pPixmap; - BITS32 maskQ; - - assert(pUnion); - pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; - - maskQ = mask; /* save these for when we walk the GCque */ - while (mask && !error) - { - index2 = (BITS32) lowbit (mask); - mask &= ~index2; - pGC->stateChanges |= index2; - switch (index2) - { - case GCFunction: - { - CARD8 newalu; - NEXTVAL(CARD8, newalu); - if (newalu <= GXset) - pGC->alu = newalu; - else - { - if (client) - client->errorValue = newalu; - error = BadValue; - } - break; - } - case GCPlaneMask: - NEXTVAL(unsigned long, pGC->planemask); - break; - case GCForeground: - NEXTVAL(unsigned long, pGC->fgPixel); - /* - * this is for CreateGC - */ - if (!pGC->tileIsPixel && !pGC->tile.pixmap) - { - pGC->tileIsPixel = TRUE; - pGC->tile.pixel = pGC->fgPixel; - } - break; - case GCBackground: - NEXTVAL(unsigned long, pGC->bgPixel); - break; - case GCLineWidth: /* ??? line width is a CARD16 */ - NEXTVAL(CARD16, pGC->lineWidth); - break; - case GCLineStyle: - { - unsigned int newlinestyle; - NEXTVAL(unsigned int, newlinestyle); - if (newlinestyle <= LineDoubleDash) - pGC->lineStyle = newlinestyle; - else - { - if (client) - client->errorValue = newlinestyle; - error = BadValue; - } - break; - } - case GCCapStyle: - { - unsigned int newcapstyle; - NEXTVAL(unsigned int, newcapstyle); - if (newcapstyle <= CapProjecting) - pGC->capStyle = newcapstyle; - else - { - if (client) - client->errorValue = newcapstyle; - error = BadValue; - } - break; - } - case GCJoinStyle: - { - unsigned int newjoinstyle; - NEXTVAL(unsigned int, newjoinstyle); - if (newjoinstyle <= JoinBevel) - pGC->joinStyle = newjoinstyle; - else - { - if (client) - client->errorValue = newjoinstyle; - error = BadValue; - } - break; - } - case GCFillStyle: - { - unsigned int newfillstyle; - NEXTVAL(unsigned int, newfillstyle); - if (newfillstyle <= FillOpaqueStippled) - pGC->fillStyle = newfillstyle; - else - { - if (client) - client->errorValue = newfillstyle; - error = BadValue; - } - break; - } - case GCFillRule: - { - unsigned int newfillrule; - NEXTVAL(unsigned int, newfillrule); - if (newfillrule <= WindingRule) - pGC->fillRule = newfillrule; - else - { - if (client) - client->errorValue = newfillrule; - error = BadValue; - } - break; - } - case GCTile: - NEXT_PTR(PixmapPtr, pPixmap); - if ((pPixmap->drawable.depth != pGC->depth) || - (pPixmap->drawable.pScreen != pGC->pScreen)) - { - error = BadMatch; - } - else - { - pPixmap->refcnt++; - if (!pGC->tileIsPixel) - (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); - pGC->tileIsPixel = FALSE; - pGC->tile.pixmap = pPixmap; - } - break; - case GCStipple: - NEXT_PTR(PixmapPtr, pPixmap); - if ((pPixmap->drawable.depth != 1) || - (pPixmap->drawable.pScreen != pGC->pScreen)) - { - error = BadMatch; - } - else - { - pPixmap->refcnt++; - if (pGC->stipple) - (* pGC->pScreen->DestroyPixmap)(pGC->stipple); - pGC->stipple = pPixmap; - } - break; - case GCTileStipXOrigin: - NEXTVAL(INT16, pGC->patOrg.x); - break; - case GCTileStipYOrigin: - NEXTVAL(INT16, pGC->patOrg.y); - break; - case GCFont: - { - FontPtr pFont; - NEXT_PTR(FontPtr, pFont); - pFont->refcnt++; - if (pGC->font) - CloseFont(pGC->font, (Font)0); - pGC->font = pFont; - break; - } - case GCSubwindowMode: - { - unsigned int newclipmode; - NEXTVAL(unsigned int, newclipmode); - if (newclipmode <= IncludeInferiors) - pGC->subWindowMode = newclipmode; - else - { - if (client) - client->errorValue = newclipmode; - error = BadValue; - } - break; - } - case GCGraphicsExposures: - { - unsigned int newge; - NEXTVAL(unsigned int, newge); - if (newge <= xTrue) - pGC->graphicsExposures = newge; - else - { - if (client) - client->errorValue = newge; - error = BadValue; - } - break; - } - case GCClipXOrigin: - NEXTVAL(INT16, pGC->clipOrg.x); - break; - case GCClipYOrigin: - NEXTVAL(INT16, pGC->clipOrg.y); - break; - case GCClipMask: - NEXT_PTR(PixmapPtr, pPixmap); - if (pPixmap) - { - if ((pPixmap->drawable.depth != 1) || - (pPixmap->drawable.pScreen != pGC->pScreen)) - { - error = BadMatch; - break; - } - pPixmap->refcnt++; - } - (*pGC->funcs->ChangeClip)(pGC, pPixmap ? CT_PIXMAP : CT_NONE, - (pointer)pPixmap, 0); - break; - case GCDashOffset: - NEXTVAL(INT16, pGC->dashOffset); - break; - case GCDashList: - { - CARD8 newdash; - NEXTVAL(CARD8, newdash); - if (newdash == 4) - { - if (pGC->dash != DefaultDash) - { - free(pGC->dash); - pGC->numInDashList = 2; - pGC->dash = DefaultDash; - } - } - else if (newdash != 0) - { - unsigned char *dash; - - dash = malloc(2 * sizeof(unsigned char)); - if (dash) - { - if (pGC->dash != DefaultDash) - free(pGC->dash); - pGC->numInDashList = 2; - pGC->dash = dash; - dash[0] = newdash; - dash[1] = newdash; - } - else - error = BadAlloc; - } - else - { - if (client) - client->errorValue = newdash; - error = BadValue; - } - break; - } - case GCArcMode: - { - unsigned int newarcmode; - NEXTVAL(unsigned int, newarcmode); - if (newarcmode <= ArcPieSlice) - pGC->arcMode = newarcmode; - else - { - if (client) - client->errorValue = newarcmode; - error = BadValue; - } - break; - } - default: - if (client) - client->errorValue = maskQ; - error = BadValue; - break; - } - } /* end while mask && !error */ - - if (pGC->fillStyle == FillTiled && pGC->tileIsPixel) - { - if (!CreateDefaultTile (pGC)) - { - pGC->fillStyle = FillSolid; - error = BadAlloc; - } - } - (*pGC->funcs->ChangeGC)(pGC, maskQ); - return error; -} - -#undef NEXTVAL -#undef NEXT_PTR - -static const struct { - BITS32 mask; - RESTYPE type; - Mask access_mode; -} xidfields[] = { - { GCTile, RT_PIXMAP, DixReadAccess }, - { GCStipple, RT_PIXMAP, DixReadAccess }, - { GCFont, RT_FONT, DixUseAccess }, - { GCClipMask, RT_PIXMAP, DixReadAccess }, -}; - -int -ChangeGCXIDs(ClientPtr client, GC *pGC, BITS32 mask, CARD32 *pC32) -{ - ChangeGCVal vals[GCLastBit + 1]; - int i; - if (mask & ~GCAllBits) - { - client->errorValue = mask; - return BadValue; - } - for (i = Ones(mask); i--; ) - vals[i].val = pC32[i]; - for (i = 0; i < sizeof(xidfields) / sizeof(*xidfields); ++i) - { - int offset, rc; - if (!(mask & xidfields[i].mask)) - continue; - offset = Ones(mask & (xidfields[i].mask - 1)); - if (xidfields[i].mask == GCClipMask && vals[offset].val == None) - { - vals[offset].ptr = NullPixmap; - continue; - } - rc = dixLookupResourceByType(&vals[offset].ptr, vals[offset].val, - xidfields[i].type, client, xidfields[i].access_mode); - if (rc != Success) - { - client->errorValue = vals[offset].val; - if (rc == BadValue) - rc = (xidfields[i].type == RT_PIXMAP) ? BadPixmap : BadFont; - return rc; - } - } - return ChangeGC(client, pGC, mask, vals); -} - -/* CreateGC(pDrawable, mask, pval, pStatus) - creates a default GC for the given drawable, using mask to fill - in any non-default values. - Returns a pointer to the new GC on success, NULL otherwise. - returns status of non-default fields in pStatus -BUG: - should check for failure to create default tile - -*/ -GCPtr -CreateGC(DrawablePtr pDrawable, BITS32 mask, XID *pval, int *pStatus, - XID gcid, ClientPtr client) -{ - GCPtr pGC; - - pGC = malloc(sizeof(GC)); - if (!pGC) - { - *pStatus = BadAlloc; - return (GCPtr)NULL; - } - - pGC->pScreen = pDrawable->pScreen; - pGC->depth = pDrawable->depth; - pGC->alu = GXcopy; /* dst <- src */ - pGC->planemask = ~0; - pGC->serialNumber = GC_CHANGE_SERIAL_BIT; - pGC->funcs = 0; - pGC->devPrivates = NULL; - pGC->fgPixel = 0; - pGC->bgPixel = 1; - pGC->lineWidth = 0; - pGC->lineStyle = LineSolid; - pGC->capStyle = CapButt; - pGC->joinStyle = JoinMiter; - pGC->fillStyle = FillSolid; - pGC->fillRule = EvenOddRule; - pGC->arcMode = ArcPieSlice; - pGC->tile.pixel = 0; - pGC->tile.pixmap = NullPixmap; - if (mask & GCForeground) - { - /* - * magic special case -- ChangeGC checks for this condition - * and snags the Foreground value to create a pseudo default-tile - */ - pGC->tileIsPixel = FALSE; - } - else - { - pGC->tileIsPixel = TRUE; - } - - pGC->patOrg.x = 0; - pGC->patOrg.y = 0; - pGC->subWindowMode = ClipByChildren; - pGC->graphicsExposures = TRUE; - pGC->clipOrg.x = 0; - pGC->clipOrg.y = 0; - pGC->clientClipType = CT_NONE; - pGC->clientClip = (pointer)NULL; - pGC->numInDashList = 2; - pGC->dash = DefaultDash; - pGC->dashOffset = 0; - pGC->lastWinOrg.x = 0; - pGC->lastWinOrg.y = 0; - - /* use the default font and stipple */ - pGC->font = defaultFont; - defaultFont->refcnt++; - pGC->stipple = pGC->pScreen->PixmapPerDepth[0]; - pGC->stipple->refcnt++; - - /* security creation/labeling check */ - *pStatus = XaceHook(XACE_RESOURCE_ACCESS, client, gcid, RT_GC, pGC, - RT_NONE, NULL, DixCreateAccess|DixSetAttrAccess); - if (*pStatus != Success) - goto out; - - pGC->stateChanges = GCAllBits; - if (!(*pGC->pScreen->CreateGC)(pGC)) - *pStatus = BadAlloc; - else if (mask) - *pStatus = ChangeGCXIDs(client, pGC, mask, pval); - else - *pStatus = Success; - -out: - if (*pStatus != Success) - { - if (!pGC->tileIsPixel && !pGC->tile.pixmap) - pGC->tileIsPixel = TRUE; /* undo special case */ - FreeGC(pGC, (XID)0); - pGC = (GCPtr)NULL; - } - - return (pGC); -} - -static Bool -CreateDefaultTile (GCPtr pGC) -{ - ChangeGCVal tmpval[3]; - PixmapPtr pTile; - GCPtr pgcScratch; - xRectangle rect; - CARD16 w, h; - - w = 1; - h = 1; - (*pGC->pScreen->QueryBestSize)(TileShape, &w, &h, pGC->pScreen); - pTile = (PixmapPtr) - (*pGC->pScreen->CreatePixmap)(pGC->pScreen, - w, h, pGC->depth, 0); - pgcScratch = GetScratchGC(pGC->depth, pGC->pScreen); - if (!pTile || !pgcScratch) - { - if (pTile) - (*pTile->drawable.pScreen->DestroyPixmap)(pTile); - if (pgcScratch) - FreeScratchGC(pgcScratch); - return FALSE; - } - tmpval[0].val = GXcopy; - tmpval[1].val = pGC->tile.pixel; - tmpval[2].val = FillSolid; - (void)ChangeGC(NullClient, pgcScratch, GCFunction | GCForeground | GCFillStyle, tmpval); - ValidateGC((DrawablePtr)pTile, pgcScratch); - rect.x = 0; - rect.y = 0; - rect.width = w; - rect.height = h; - (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pTile, pgcScratch, 1, &rect); - /* Always remember to free the scratch graphics context after use. */ - FreeScratchGC(pgcScratch); - - pGC->tileIsPixel = FALSE; - pGC->tile.pixmap = pTile; - return TRUE; -} - -int -CopyGC(GC *pgcSrc, GC *pgcDst, BITS32 mask) -{ - BITS32 index2; - BITS32 maskQ; - int error = 0; - - if (pgcSrc == pgcDst) - return Success; - pgcDst->serialNumber |= GC_CHANGE_SERIAL_BIT; - pgcDst->stateChanges |= mask; - maskQ = mask; - while (mask) - { - index2 = (BITS32) lowbit (mask); - mask &= ~index2; - switch (index2) - { - case GCFunction: - pgcDst->alu = pgcSrc->alu; - break; - case GCPlaneMask: - pgcDst->planemask = pgcSrc->planemask; - break; - case GCForeground: - pgcDst->fgPixel = pgcSrc->fgPixel; - break; - case GCBackground: - pgcDst->bgPixel = pgcSrc->bgPixel; - break; - case GCLineWidth: - pgcDst->lineWidth = pgcSrc->lineWidth; - break; - case GCLineStyle: - pgcDst->lineStyle = pgcSrc->lineStyle; - break; - case GCCapStyle: - pgcDst->capStyle = pgcSrc->capStyle; - break; - case GCJoinStyle: - pgcDst->joinStyle = pgcSrc->joinStyle; - break; - case GCFillStyle: - pgcDst->fillStyle = pgcSrc->fillStyle; - break; - case GCFillRule: - pgcDst->fillRule = pgcSrc->fillRule; - break; - case GCTile: - { - if (EqualPixUnion(pgcDst->tileIsPixel, - pgcDst->tile, - pgcSrc->tileIsPixel, - pgcSrc->tile)) - { - break; - } - if (!pgcDst->tileIsPixel) - (* pgcDst->pScreen->DestroyPixmap)(pgcDst->tile.pixmap); - pgcDst->tileIsPixel = pgcSrc->tileIsPixel; - pgcDst->tile = pgcSrc->tile; - if (!pgcDst->tileIsPixel) - pgcDst->tile.pixmap->refcnt++; - break; - } - case GCStipple: - { - if (pgcDst->stipple == pgcSrc->stipple) - break; - if (pgcDst->stipple) - (* pgcDst->pScreen->DestroyPixmap)(pgcDst->stipple); - pgcDst->stipple = pgcSrc->stipple; - if (pgcDst->stipple) - pgcDst->stipple->refcnt ++; - break; - } - case GCTileStipXOrigin: - pgcDst->patOrg.x = pgcSrc->patOrg.x; - break; - case GCTileStipYOrigin: - pgcDst->patOrg.y = pgcSrc->patOrg.y; - break; - case GCFont: - if (pgcDst->font == pgcSrc->font) - break; - if (pgcDst->font) - CloseFont(pgcDst->font, (Font)0); - if ((pgcDst->font = pgcSrc->font) != NullFont) - (pgcDst->font)->refcnt++; - break; - case GCSubwindowMode: - pgcDst->subWindowMode = pgcSrc->subWindowMode; - break; - case GCGraphicsExposures: - pgcDst->graphicsExposures = pgcSrc->graphicsExposures; - break; - case GCClipXOrigin: - pgcDst->clipOrg.x = pgcSrc->clipOrg.x; - break; - case GCClipYOrigin: - pgcDst->clipOrg.y = pgcSrc->clipOrg.y; - break; - case GCClipMask: - (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); - break; - case GCDashOffset: - pgcDst->dashOffset = pgcSrc->dashOffset; - break; - case GCDashList: - if (pgcSrc->dash == DefaultDash) - { - if (pgcDst->dash != DefaultDash) - { - free(pgcDst->dash); - pgcDst->numInDashList = pgcSrc->numInDashList; - pgcDst->dash = pgcSrc->dash; - } - } - else - { - unsigned char *dash; - unsigned int i; - - dash = malloc(pgcSrc->numInDashList * sizeof(unsigned char)); - if (dash) - { - if (pgcDst->dash != DefaultDash) - free(pgcDst->dash); - pgcDst->numInDashList = pgcSrc->numInDashList; - pgcDst->dash = dash; - for (i=0; inumInDashList; i++) - dash[i] = pgcSrc->dash[i]; - } - else - error = BadAlloc; - } - break; - case GCArcMode: - pgcDst->arcMode = pgcSrc->arcMode; - break; - default: - FatalError ("CopyGC: Unhandled mask!\n"); - } - } - if (pgcDst->fillStyle == FillTiled && pgcDst->tileIsPixel) - { - if (!CreateDefaultTile (pgcDst)) - { - pgcDst->fillStyle = FillSolid; - error = BadAlloc; - } - } - (*pgcDst->funcs->CopyGC) (pgcSrc, maskQ, pgcDst); - return error; -} - -/** - * does the diX part of freeing the characteristics in the GC. - * - * \param value must conform to DeleteType - */ -int -FreeGC(pointer value, XID gid) -{ - GCPtr pGC = (GCPtr)value; - - CloseFont(pGC->font, (Font)0); - (* pGC->funcs->DestroyClip)(pGC); - - if (!pGC->tileIsPixel) - (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); - if (pGC->stipple) - (* pGC->pScreen->DestroyPixmap)(pGC->stipple); - - (*pGC->funcs->DestroyGC) (pGC); - if (pGC->dash != DefaultDash) - free(pGC->dash); - dixFreePrivates(pGC->devPrivates); - free(pGC); - return(Success); -} - -/* CreateScratchGC(pScreen, depth) - like CreateGC, but doesn't do the default tile or stipple, -since we can't create them without already having a GC. any code -using the tile or stipple has to set them explicitly anyway, -since the state of the scratch gc is unknown. This is OK -because ChangeGC() has to be able to deal with NULL tiles and -stipples anyway (in case the CreateGC() call has provided a -value for them -- we can't set the default tile until the -client-supplied attributes are installed, since the fgPixel -is what fills the default tile. (maybe this comment should -go with CreateGC() or ChangeGC().) -*/ - -GCPtr -CreateScratchGC(ScreenPtr pScreen, unsigned depth) -{ - GCPtr pGC; - - pGC = malloc(sizeof(GC)); - if (!pGC) - return (GCPtr)NULL; - - pGC->pScreen = pScreen; - pGC->depth = depth; - pGC->alu = GXcopy; /* dst <- src */ - pGC->planemask = ~0; - pGC->serialNumber = 0; - pGC->devPrivates = NULL; - pGC->fgPixel = 0; - pGC->bgPixel = 1; - pGC->lineWidth = 0; - pGC->lineStyle = LineSolid; - pGC->capStyle = CapButt; - pGC->joinStyle = JoinMiter; - pGC->fillStyle = FillSolid; - pGC->fillRule = EvenOddRule; - pGC->arcMode = ArcPieSlice; - pGC->font = defaultFont; - if ( pGC->font) /* necessary, because open of default font could fail */ - pGC->font->refcnt++; - pGC->tileIsPixel = TRUE; - pGC->tile.pixel = 0; - pGC->tile.pixmap = NullPixmap; - pGC->stipple = NullPixmap; - pGC->patOrg.x = 0; - pGC->patOrg.y = 0; - pGC->subWindowMode = ClipByChildren; - pGC->graphicsExposures = TRUE; - pGC->clipOrg.x = 0; - pGC->clipOrg.y = 0; - pGC->clientClipType = CT_NONE; - pGC->dashOffset = 0; - pGC->numInDashList = 2; - pGC->dash = DefaultDash; - pGC->lastWinOrg.x = 0; - pGC->lastWinOrg.y = 0; - - pGC->stateChanges = GCAllBits; - if (!(*pScreen->CreateGC)(pGC)) - { - FreeGC(pGC, (XID)0); - pGC = (GCPtr)NULL; - } - return pGC; -} - -void -FreeGCperDepth(int screenNum) -{ - int i; - ScreenPtr pScreen; - GCPtr *ppGC; - - pScreen = screenInfo.screens[screenNum]; - ppGC = pScreen->GCperDepth; - - for (i = 0; i <= pScreen->numDepths; i++) - (void)FreeGC(ppGC[i], (XID)0); - pScreen->rgf = ~0L; -} - - -Bool -CreateGCperDepth(int screenNum) -{ - int i; - ScreenPtr pScreen; - DepthPtr pDepth; - GCPtr *ppGC; - - pScreen = screenInfo.screens[screenNum]; - pScreen->rgf = 0; - ppGC = pScreen->GCperDepth; - /* do depth 1 separately because it's not included in list */ - if (!(ppGC[0] = CreateScratchGC(pScreen, 1))) - return FALSE; - ppGC[0]->graphicsExposures = FALSE; - /* Make sure we don't overflow GCperDepth[] */ - if( pScreen->numDepths > MAXFORMATS ) - return FALSE; - - pDepth = pScreen->allowedDepths; - for (i=0; inumDepths; i++, pDepth++) - { - if (!(ppGC[i+1] = CreateScratchGC(pScreen, pDepth->depth))) - { - for (; i >= 0; i--) - (void)FreeGC(ppGC[i], (XID)0); - return FALSE; - } - ppGC[i+1]->graphicsExposures = FALSE; - } - return TRUE; -} - -Bool -CreateDefaultStipple(int screenNum) -{ - ScreenPtr pScreen; - ChangeGCVal tmpval[3]; - xRectangle rect; - CARD16 w, h; - GCPtr pgcScratch; - - pScreen = screenInfo.screens[screenNum]; - - w = 16; - h = 16; - (* pScreen->QueryBestSize)(StippleShape, &w, &h, pScreen); - if (!(pScreen->PixmapPerDepth[0] = - (*pScreen->CreatePixmap)(pScreen, w, h, 1, 0))) - return FALSE; - /* fill stipple with 1 */ - tmpval[0].val = GXcopy; - tmpval[1].val = 1; - tmpval[2].val = FillSolid; - pgcScratch = GetScratchGC(1, pScreen); - if (!pgcScratch) - { - (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); - return FALSE; - } - (void)ChangeGC(NullClient, pgcScratch, GCFunction|GCForeground|GCFillStyle, tmpval); - ValidateGC((DrawablePtr)pScreen->PixmapPerDepth[0], pgcScratch); - rect.x = 0; - rect.y = 0; - rect.width = w; - rect.height = h; - (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pScreen->PixmapPerDepth[0], - pgcScratch, 1, &rect); - FreeScratchGC(pgcScratch); - return TRUE; -} - -void -FreeDefaultStipple(int screenNum) -{ - ScreenPtr pScreen = screenInfo.screens[screenNum]; - (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); -} - -int -SetDashes(GCPtr pGC, unsigned offset, unsigned ndash, unsigned char *pdash) -{ - long i; - unsigned char *p, *indash; - BITS32 maskQ = 0; - - i = ndash; - p = pdash; - while (i--) - { - if (!*p++) - { - /* dash segment must be > 0 */ - return BadValue; - } - } - - if (ndash & 1) - p = malloc(2 * ndash * sizeof(unsigned char)); - else - p = malloc(ndash * sizeof(unsigned char)); - if (!p) - return BadAlloc; - - pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; - if (offset != pGC->dashOffset) - { - pGC->dashOffset = offset; - pGC->stateChanges |= GCDashOffset; - maskQ |= GCDashOffset; - } - - if (pGC->dash != DefaultDash) - free(pGC->dash); - pGC->numInDashList = ndash; - pGC->dash = p; - if (ndash & 1) - { - pGC->numInDashList += ndash; - indash = pdash; - i = ndash; - while (i--) - *p++ = *indash++; - } - while(ndash--) - *p++ = *pdash++; - pGC->stateChanges |= GCDashList; - maskQ |= GCDashList; - - if (pGC->funcs->ChangeGC) - (*pGC->funcs->ChangeGC) (pGC, maskQ); - return Success; -} - -int -VerifyRectOrder(int nrects, xRectangle *prects, int ordering) -{ - xRectangle *prectP, *prectN; - int i; - - switch(ordering) - { - case Unsorted: - return CT_UNSORTED; - case YSorted: - if(nrects > 1) - { - for(i = 1, prectP = prects, prectN = prects + 1; - i < nrects; - i++, prectP++, prectN++) - if(prectN->y < prectP->y) - return -1; - } - return CT_YSORTED; - case YXSorted: - if(nrects > 1) - { - for(i = 1, prectP = prects, prectN = prects + 1; - i < nrects; - i++, prectP++, prectN++) - if((prectN->y < prectP->y) || - ( (prectN->y == prectP->y) && - (prectN->x < prectP->x) ) ) - return -1; - } - return CT_YXSORTED; - case YXBanded: - if(nrects > 1) - { - for(i = 1, prectP = prects, prectN = prects + 1; - i < nrects; - i++, prectP++, prectN++) - if((prectN->y != prectP->y && - prectN->y < prectP->y + (int) prectP->height) || - ((prectN->y == prectP->y) && - (prectN->height != prectP->height || - prectN->x < prectP->x + (int) prectP->width))) - return -1; - } - return CT_YXBANDED; - } - return -1; -} - -int -SetClipRects(GCPtr pGC, int xOrigin, int yOrigin, int nrects, - xRectangle *prects, int ordering) -{ - int newct, size; - xRectangle *prectsNew; - - newct = VerifyRectOrder(nrects, prects, ordering); - if (newct < 0) - return(BadMatch); - size = nrects * sizeof(xRectangle); - prectsNew = malloc(size); - if (!prectsNew && size) - return BadAlloc; - - pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; - pGC->clipOrg.x = xOrigin; - pGC->stateChanges |= GCClipXOrigin; - - pGC->clipOrg.y = yOrigin; - pGC->stateChanges |= GCClipYOrigin; - - if (size) - memmove((char *)prectsNew, (char *)prects, size); - (*pGC->funcs->ChangeClip)(pGC, newct, (pointer)prectsNew, nrects); - if (pGC->funcs->ChangeGC) - (*pGC->funcs->ChangeGC) (pGC, GCClipXOrigin|GCClipYOrigin|GCClipMask); - return Success; -} - - -/* - sets reasonable defaults - if we can get a pre-allocated one, use it and mark it as used. - if we can't, create one out of whole cloth (The Velveteen GC -- if - you use it often enough it will become real.) -*/ -GCPtr -GetScratchGC(unsigned depth, ScreenPtr pScreen) -{ - int i; - GCPtr pGC; - - for (i=0; i<=pScreen->numDepths; i++) - if ( pScreen->GCperDepth[i]->depth == depth && - !(pScreen->rgf & (1L << (i+1))) - ) - { - pScreen->rgf |= (1L << (i+1)); - pGC = (pScreen->GCperDepth[i]); - - pGC->alu = GXcopy; - pGC->planemask = ~0; - pGC->serialNumber = 0; - pGC->fgPixel = 0; - pGC->bgPixel = 1; - pGC->lineWidth = 0; - pGC->lineStyle = LineSolid; - pGC->capStyle = CapButt; - pGC->joinStyle = JoinMiter; - pGC->fillStyle = FillSolid; - pGC->fillRule = EvenOddRule; - pGC->arcMode = ArcChord; - pGC->patOrg.x = 0; - pGC->patOrg.y = 0; - pGC->subWindowMode = ClipByChildren; - pGC->graphicsExposures = FALSE; - pGC->clipOrg.x = 0; - pGC->clipOrg.y = 0; - if (pGC->clientClipType != CT_NONE) - (*pGC->funcs->ChangeClip) (pGC, CT_NONE, NULL, 0); - pGC->stateChanges = GCAllBits; - return pGC; - } - /* if we make it this far, need to roll our own */ - pGC = CreateScratchGC(pScreen, depth); - if (pGC) - pGC->graphicsExposures = FALSE; - return pGC; -} - -/* - if the gc to free is in the table of pre-existing ones, -mark it as available. - if not, free it for real -*/ -void -FreeScratchGC(GCPtr pGC) -{ - ScreenPtr pScreen = pGC->pScreen; - int i; - - for (i=0; i<=pScreen->numDepths; i++) - { - if ( pScreen->GCperDepth[i] == pGC) - { - pScreen->rgf &= ~(1L << (i+1)); - return; - } - } - (void)FreeGC(pGC, (GContext)0); -} +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include "misc.h" +#include "resource.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "dixfontstr.h" +#include "scrnintstr.h" +#include "region.h" +#include "dixstruct.h" + +#include "privates.h" +#include "dix.h" +#include "xace.h" +#include + +extern FontPtr defaultFont; + +static Bool CreateDefaultTile(GCPtr pGC); + +static unsigned char DefaultDash[2] = {4, 4}; + +void +ValidateGC(DrawablePtr pDraw, GC *pGC) +{ + (*pGC->funcs->ValidateGC) (pGC, pGC->stateChanges, pDraw); + pGC->stateChanges = 0; + pGC->serialNumber = pDraw->serialNumber; +} + + +/* + * ChangeGC/ChangeGCXIDs: + * + * The client performing the gc change must be passed so that access + * checks can be performed on any tiles, stipples, or fonts that are + * specified. ddxen can call this too; they should normally pass + * NullClient for the client since any access checking should have + * already been done at a higher level. + * + * If you have any XIDs, you must use ChangeGCXIDs: + * + * CARD32 v[2]; + * v[0] = FillTiled; + * v[1] = pid; + * ChangeGCXIDs(client, pGC, GCFillStyle|GCTile, v); + * + * However, if you need to pass a pointer to a pixmap or font, you must + * use ChangeGC: + * + * ChangeGCVal v[2]; + * v[0].val = FillTiled; + * v[1].ptr = pPixmap; + * ChangeGC(client, pGC, GCFillStyle|GCTile, v); + * + * If you have neither XIDs nor pointers, you can use either function, + * but ChangeGC will do less work. + * + * ChangeGCVal v[2]; + * v[0].val = foreground; + * v[1].val = background; + * ChangeGC(client, pGC, GCForeground|GCBackground, v); + */ + +#define NEXTVAL(_type, _var) { \ + _var = (_type)(pUnion->val); pUnion++; \ + } + +#define NEXT_PTR(_type, _var) { \ + _var = (_type)pUnion->ptr; pUnion++; } + +int +ChangeGC(ClientPtr client, GC *pGC, BITS32 mask, ChangeGCValPtr pUnion) +{ + BITS32 index2; + int error = 0; + PixmapPtr pPixmap; + BITS32 maskQ; + + assert(pUnion); + pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; + + maskQ = mask; /* save these for when we walk the GCque */ + while (mask && !error) + { + index2 = (BITS32) lowbit (mask); + mask &= ~index2; + pGC->stateChanges |= index2; + switch (index2) + { + case GCFunction: + { + CARD8 newalu; + NEXTVAL(CARD8, newalu); + if (newalu <= GXset) + pGC->alu = newalu; + else + { + if (client) + client->errorValue = newalu; + error = BadValue; + } + break; + } + case GCPlaneMask: + NEXTVAL(unsigned long, pGC->planemask); + break; + case GCForeground: + NEXTVAL(unsigned long, pGC->fgPixel); + /* + * this is for CreateGC + */ + if (!pGC->tileIsPixel && !pGC->tile.pixmap) + { + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = pGC->fgPixel; + } + break; + case GCBackground: + NEXTVAL(unsigned long, pGC->bgPixel); + break; + case GCLineWidth: /* ??? line width is a CARD16 */ + NEXTVAL(CARD16, pGC->lineWidth); + break; + case GCLineStyle: + { + unsigned int newlinestyle; + NEXTVAL(unsigned int, newlinestyle); + if (newlinestyle <= LineDoubleDash) + pGC->lineStyle = newlinestyle; + else + { + if (client) + client->errorValue = newlinestyle; + error = BadValue; + } + break; + } + case GCCapStyle: + { + unsigned int newcapstyle; + NEXTVAL(unsigned int, newcapstyle); + if (newcapstyle <= CapProjecting) + pGC->capStyle = newcapstyle; + else + { + if (client) + client->errorValue = newcapstyle; + error = BadValue; + } + break; + } + case GCJoinStyle: + { + unsigned int newjoinstyle; + NEXTVAL(unsigned int, newjoinstyle); + if (newjoinstyle <= JoinBevel) + pGC->joinStyle = newjoinstyle; + else + { + if (client) + client->errorValue = newjoinstyle; + error = BadValue; + } + break; + } + case GCFillStyle: + { + unsigned int newfillstyle; + NEXTVAL(unsigned int, newfillstyle); + if (newfillstyle <= FillOpaqueStippled) + pGC->fillStyle = newfillstyle; + else + { + if (client) + client->errorValue = newfillstyle; + error = BadValue; + } + break; + } + case GCFillRule: + { + unsigned int newfillrule; + NEXTVAL(unsigned int, newfillrule); + if (newfillrule <= WindingRule) + pGC->fillRule = newfillrule; + else + { + if (client) + client->errorValue = newfillrule; + error = BadValue; + } + break; + } + case GCTile: + NEXT_PTR(PixmapPtr, pPixmap); + if ((pPixmap->drawable.depth != pGC->depth) || + (pPixmap->drawable.pScreen != pGC->pScreen)) + { + error = BadMatch; + } + else + { + pPixmap->refcnt++; + if (!pGC->tileIsPixel) + (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); + pGC->tileIsPixel = FALSE; + pGC->tile.pixmap = pPixmap; + } + break; + case GCStipple: + NEXT_PTR(PixmapPtr, pPixmap); + if ((pPixmap->drawable.depth != 1) || + (pPixmap->drawable.pScreen != pGC->pScreen)) + { + error = BadMatch; + } + else + { + pPixmap->refcnt++; + if (pGC->stipple) + (* pGC->pScreen->DestroyPixmap)(pGC->stipple); + pGC->stipple = pPixmap; + } + break; + case GCTileStipXOrigin: + NEXTVAL(INT16, pGC->patOrg.x); + break; + case GCTileStipYOrigin: + NEXTVAL(INT16, pGC->patOrg.y); + break; + case GCFont: + { + FontPtr pFont; + NEXT_PTR(FontPtr, pFont); + pFont->refcnt++; + if (pGC->font) + CloseFont(pGC->font, (Font)0); + pGC->font = pFont; + break; + } + case GCSubwindowMode: + { + unsigned int newclipmode; + NEXTVAL(unsigned int, newclipmode); + if (newclipmode <= IncludeInferiors) + pGC->subWindowMode = newclipmode; + else + { + if (client) + client->errorValue = newclipmode; + error = BadValue; + } + break; + } + case GCGraphicsExposures: + { + unsigned int newge; + NEXTVAL(unsigned int, newge); + if (newge <= xTrue) + pGC->graphicsExposures = newge; + else + { + if (client) + client->errorValue = newge; + error = BadValue; + } + break; + } + case GCClipXOrigin: + NEXTVAL(INT16, pGC->clipOrg.x); + break; + case GCClipYOrigin: + NEXTVAL(INT16, pGC->clipOrg.y); + break; + case GCClipMask: + NEXT_PTR(PixmapPtr, pPixmap); + if (pPixmap) + { + if ((pPixmap->drawable.depth != 1) || + (pPixmap->drawable.pScreen != pGC->pScreen)) + { + error = BadMatch; + break; + } + pPixmap->refcnt++; + } + (*pGC->funcs->ChangeClip)(pGC, pPixmap ? CT_PIXMAP : CT_NONE, + (pointer)pPixmap, 0); + break; + case GCDashOffset: + NEXTVAL(INT16, pGC->dashOffset); + break; + case GCDashList: + { + CARD8 newdash; + NEXTVAL(CARD8, newdash); + if (newdash == 4) + { + if (pGC->dash != DefaultDash) + { + free(pGC->dash); + pGC->numInDashList = 2; + pGC->dash = DefaultDash; + } + } + else if (newdash != 0) + { + unsigned char *dash; + + dash = malloc(2 * sizeof(unsigned char)); + if (dash) + { + if (pGC->dash != DefaultDash) + free(pGC->dash); + pGC->numInDashList = 2; + pGC->dash = dash; + dash[0] = newdash; + dash[1] = newdash; + } + else + error = BadAlloc; + } + else + { + if (client) + client->errorValue = newdash; + error = BadValue; + } + break; + } + case GCArcMode: + { + unsigned int newarcmode; + NEXTVAL(unsigned int, newarcmode); + if (newarcmode <= ArcPieSlice) + pGC->arcMode = newarcmode; + else + { + if (client) + client->errorValue = newarcmode; + error = BadValue; + } + break; + } + default: + if (client) + client->errorValue = maskQ; + error = BadValue; + break; + } + } /* end while mask && !error */ + + if (pGC->fillStyle == FillTiled && pGC->tileIsPixel) + { + if (!CreateDefaultTile (pGC)) + { + pGC->fillStyle = FillSolid; + error = BadAlloc; + } + } + (*pGC->funcs->ChangeGC)(pGC, maskQ); + return error; +} + +#undef NEXTVAL +#undef NEXT_PTR + +static const struct { + BITS32 mask; + RESTYPE type; + Mask access_mode; +} xidfields[] = { + { GCTile, RT_PIXMAP, DixReadAccess }, + { GCStipple, RT_PIXMAP, DixReadAccess }, + { GCFont, RT_FONT, DixUseAccess }, + { GCClipMask, RT_PIXMAP, DixReadAccess }, +}; + +int +ChangeGCXIDs(ClientPtr client, GC *pGC, BITS32 mask, CARD32 *pC32) +{ + ChangeGCVal vals[GCLastBit + 1]; + int i; + if (mask & ~GCAllBits) + { + client->errorValue = mask; + return BadValue; + } + for (i = Ones(mask); i--; ) + vals[i].val = pC32[i]; + for (i = 0; i < sizeof(xidfields) / sizeof(*xidfields); ++i) + { + int offset, rc; + if (!(mask & xidfields[i].mask)) + continue; + offset = Ones(mask & (xidfields[i].mask - 1)); + if (xidfields[i].mask == GCClipMask && vals[offset].val == None) + { + vals[offset].ptr = NullPixmap; + continue; + } + rc = dixLookupResourceByType(&vals[offset].ptr, vals[offset].val, + xidfields[i].type, client, xidfields[i].access_mode); + if (rc != Success) + { + client->errorValue = vals[offset].val; + return rc; + } + } + return ChangeGC(client, pGC, mask, vals); +} + +/* CreateGC(pDrawable, mask, pval, pStatus) + creates a default GC for the given drawable, using mask to fill + in any non-default values. + Returns a pointer to the new GC on success, NULL otherwise. + returns status of non-default fields in pStatus +BUG: + should check for failure to create default tile + +*/ +GCPtr +CreateGC(DrawablePtr pDrawable, BITS32 mask, XID *pval, int *pStatus, + XID gcid, ClientPtr client) +{ + GCPtr pGC; + + pGC = malloc(sizeof(GC)); + if (!pGC) + { + *pStatus = BadAlloc; + return (GCPtr)NULL; + } + + pGC->pScreen = pDrawable->pScreen; + pGC->depth = pDrawable->depth; + pGC->alu = GXcopy; /* dst <- src */ + pGC->planemask = ~0; + pGC->serialNumber = GC_CHANGE_SERIAL_BIT; + pGC->funcs = 0; + pGC->devPrivates = NULL; + pGC->fgPixel = 0; + pGC->bgPixel = 1; + pGC->lineWidth = 0; + pGC->lineStyle = LineSolid; + pGC->capStyle = CapButt; + pGC->joinStyle = JoinMiter; + pGC->fillStyle = FillSolid; + pGC->fillRule = EvenOddRule; + pGC->arcMode = ArcPieSlice; + pGC->tile.pixel = 0; + pGC->tile.pixmap = NullPixmap; + if (mask & GCForeground) + { + /* + * magic special case -- ChangeGC checks for this condition + * and snags the Foreground value to create a pseudo default-tile + */ + pGC->tileIsPixel = FALSE; + } + else + { + pGC->tileIsPixel = TRUE; + } + + pGC->patOrg.x = 0; + pGC->patOrg.y = 0; + pGC->subWindowMode = ClipByChildren; + pGC->graphicsExposures = TRUE; + pGC->clipOrg.x = 0; + pGC->clipOrg.y = 0; + pGC->clientClipType = CT_NONE; + pGC->clientClip = (pointer)NULL; + pGC->numInDashList = 2; + pGC->dash = DefaultDash; + pGC->dashOffset = 0; + pGC->lastWinOrg.x = 0; + pGC->lastWinOrg.y = 0; + + /* use the default font and stipple */ + pGC->font = defaultFont; + defaultFont->refcnt++; + pGC->stipple = pGC->pScreen->PixmapPerDepth[0]; + pGC->stipple->refcnt++; + + /* security creation/labeling check */ + *pStatus = XaceHook(XACE_RESOURCE_ACCESS, client, gcid, RT_GC, pGC, + RT_NONE, NULL, DixCreateAccess|DixSetAttrAccess); + if (*pStatus != Success) + goto out; + + pGC->stateChanges = GCAllBits; + if (!(*pGC->pScreen->CreateGC)(pGC)) + *pStatus = BadAlloc; + else if (mask) + *pStatus = ChangeGCXIDs(client, pGC, mask, pval); + else + *pStatus = Success; + +out: + if (*pStatus != Success) + { + if (!pGC->tileIsPixel && !pGC->tile.pixmap) + pGC->tileIsPixel = TRUE; /* undo special case */ + FreeGC(pGC, (XID)0); + pGC = (GCPtr)NULL; + } + + return (pGC); +} + +static Bool +CreateDefaultTile (GCPtr pGC) +{ + ChangeGCVal tmpval[3]; + PixmapPtr pTile; + GCPtr pgcScratch; + xRectangle rect; + CARD16 w, h; + + w = 1; + h = 1; + (*pGC->pScreen->QueryBestSize)(TileShape, &w, &h, pGC->pScreen); + pTile = (PixmapPtr) + (*pGC->pScreen->CreatePixmap)(pGC->pScreen, + w, h, pGC->depth, 0); + pgcScratch = GetScratchGC(pGC->depth, pGC->pScreen); + if (!pTile || !pgcScratch) + { + if (pTile) + (*pTile->drawable.pScreen->DestroyPixmap)(pTile); + if (pgcScratch) + FreeScratchGC(pgcScratch); + return FALSE; + } + tmpval[0].val = GXcopy; + tmpval[1].val = pGC->tile.pixel; + tmpval[2].val = FillSolid; + (void)ChangeGC(NullClient, pgcScratch, GCFunction | GCForeground | GCFillStyle, tmpval); + ValidateGC((DrawablePtr)pTile, pgcScratch); + rect.x = 0; + rect.y = 0; + rect.width = w; + rect.height = h; + (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pTile, pgcScratch, 1, &rect); + /* Always remember to free the scratch graphics context after use. */ + FreeScratchGC(pgcScratch); + + pGC->tileIsPixel = FALSE; + pGC->tile.pixmap = pTile; + return TRUE; +} + +int +CopyGC(GC *pgcSrc, GC *pgcDst, BITS32 mask) +{ + BITS32 index2; + BITS32 maskQ; + int error = 0; + + if (pgcSrc == pgcDst) + return Success; + pgcDst->serialNumber |= GC_CHANGE_SERIAL_BIT; + pgcDst->stateChanges |= mask; + maskQ = mask; + while (mask) + { + index2 = (BITS32) lowbit (mask); + mask &= ~index2; + switch (index2) + { + case GCFunction: + pgcDst->alu = pgcSrc->alu; + break; + case GCPlaneMask: + pgcDst->planemask = pgcSrc->planemask; + break; + case GCForeground: + pgcDst->fgPixel = pgcSrc->fgPixel; + break; + case GCBackground: + pgcDst->bgPixel = pgcSrc->bgPixel; + break; + case GCLineWidth: + pgcDst->lineWidth = pgcSrc->lineWidth; + break; + case GCLineStyle: + pgcDst->lineStyle = pgcSrc->lineStyle; + break; + case GCCapStyle: + pgcDst->capStyle = pgcSrc->capStyle; + break; + case GCJoinStyle: + pgcDst->joinStyle = pgcSrc->joinStyle; + break; + case GCFillStyle: + pgcDst->fillStyle = pgcSrc->fillStyle; + break; + case GCFillRule: + pgcDst->fillRule = pgcSrc->fillRule; + break; + case GCTile: + { + if (EqualPixUnion(pgcDst->tileIsPixel, + pgcDst->tile, + pgcSrc->tileIsPixel, + pgcSrc->tile)) + { + break; + } + if (!pgcDst->tileIsPixel) + (* pgcDst->pScreen->DestroyPixmap)(pgcDst->tile.pixmap); + pgcDst->tileIsPixel = pgcSrc->tileIsPixel; + pgcDst->tile = pgcSrc->tile; + if (!pgcDst->tileIsPixel) + pgcDst->tile.pixmap->refcnt++; + break; + } + case GCStipple: + { + if (pgcDst->stipple == pgcSrc->stipple) + break; + if (pgcDst->stipple) + (* pgcDst->pScreen->DestroyPixmap)(pgcDst->stipple); + pgcDst->stipple = pgcSrc->stipple; + if (pgcDst->stipple) + pgcDst->stipple->refcnt ++; + break; + } + case GCTileStipXOrigin: + pgcDst->patOrg.x = pgcSrc->patOrg.x; + break; + case GCTileStipYOrigin: + pgcDst->patOrg.y = pgcSrc->patOrg.y; + break; + case GCFont: + if (pgcDst->font == pgcSrc->font) + break; + if (pgcDst->font) + CloseFont(pgcDst->font, (Font)0); + if ((pgcDst->font = pgcSrc->font) != NullFont) + (pgcDst->font)->refcnt++; + break; + case GCSubwindowMode: + pgcDst->subWindowMode = pgcSrc->subWindowMode; + break; + case GCGraphicsExposures: + pgcDst->graphicsExposures = pgcSrc->graphicsExposures; + break; + case GCClipXOrigin: + pgcDst->clipOrg.x = pgcSrc->clipOrg.x; + break; + case GCClipYOrigin: + pgcDst->clipOrg.y = pgcSrc->clipOrg.y; + break; + case GCClipMask: + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + break; + case GCDashOffset: + pgcDst->dashOffset = pgcSrc->dashOffset; + break; + case GCDashList: + if (pgcSrc->dash == DefaultDash) + { + if (pgcDst->dash != DefaultDash) + { + free(pgcDst->dash); + pgcDst->numInDashList = pgcSrc->numInDashList; + pgcDst->dash = pgcSrc->dash; + } + } + else + { + unsigned char *dash; + unsigned int i; + + dash = malloc(pgcSrc->numInDashList * sizeof(unsigned char)); + if (dash) + { + if (pgcDst->dash != DefaultDash) + free(pgcDst->dash); + pgcDst->numInDashList = pgcSrc->numInDashList; + pgcDst->dash = dash; + for (i=0; inumInDashList; i++) + dash[i] = pgcSrc->dash[i]; + } + else + error = BadAlloc; + } + break; + case GCArcMode: + pgcDst->arcMode = pgcSrc->arcMode; + break; + default: + FatalError ("CopyGC: Unhandled mask!\n"); + } + } + if (pgcDst->fillStyle == FillTiled && pgcDst->tileIsPixel) + { + if (!CreateDefaultTile (pgcDst)) + { + pgcDst->fillStyle = FillSolid; + error = BadAlloc; + } + } + (*pgcDst->funcs->CopyGC) (pgcSrc, maskQ, pgcDst); + return error; +} + +/** + * does the diX part of freeing the characteristics in the GC. + * + * \param value must conform to DeleteType + */ +int +FreeGC(pointer value, XID gid) +{ + GCPtr pGC = (GCPtr)value; + + CloseFont(pGC->font, (Font)0); + (* pGC->funcs->DestroyClip)(pGC); + + if (!pGC->tileIsPixel) + (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); + if (pGC->stipple) + (* pGC->pScreen->DestroyPixmap)(pGC->stipple); + + (*pGC->funcs->DestroyGC) (pGC); + if (pGC->dash != DefaultDash) + free(pGC->dash); + dixFreePrivates(pGC->devPrivates); + free(pGC); + return(Success); +} + +/* CreateScratchGC(pScreen, depth) + like CreateGC, but doesn't do the default tile or stipple, +since we can't create them without already having a GC. any code +using the tile or stipple has to set them explicitly anyway, +since the state of the scratch gc is unknown. This is OK +because ChangeGC() has to be able to deal with NULL tiles and +stipples anyway (in case the CreateGC() call has provided a +value for them -- we can't set the default tile until the +client-supplied attributes are installed, since the fgPixel +is what fills the default tile. (maybe this comment should +go with CreateGC() or ChangeGC().) +*/ + +GCPtr +CreateScratchGC(ScreenPtr pScreen, unsigned depth) +{ + GCPtr pGC; + + pGC = malloc(sizeof(GC)); + if (!pGC) + return (GCPtr)NULL; + + pGC->pScreen = pScreen; + pGC->depth = depth; + pGC->alu = GXcopy; /* dst <- src */ + pGC->planemask = ~0; + pGC->serialNumber = 0; + pGC->devPrivates = NULL; + pGC->fgPixel = 0; + pGC->bgPixel = 1; + pGC->lineWidth = 0; + pGC->lineStyle = LineSolid; + pGC->capStyle = CapButt; + pGC->joinStyle = JoinMiter; + pGC->fillStyle = FillSolid; + pGC->fillRule = EvenOddRule; + pGC->arcMode = ArcPieSlice; + pGC->font = defaultFont; + if ( pGC->font) /* necessary, because open of default font could fail */ + pGC->font->refcnt++; + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = 0; + pGC->tile.pixmap = NullPixmap; + pGC->stipple = NullPixmap; + pGC->patOrg.x = 0; + pGC->patOrg.y = 0; + pGC->subWindowMode = ClipByChildren; + pGC->graphicsExposures = TRUE; + pGC->clipOrg.x = 0; + pGC->clipOrg.y = 0; + pGC->clientClipType = CT_NONE; + pGC->dashOffset = 0; + pGC->numInDashList = 2; + pGC->dash = DefaultDash; + pGC->lastWinOrg.x = 0; + pGC->lastWinOrg.y = 0; + + pGC->stateChanges = GCAllBits; + if (!(*pScreen->CreateGC)(pGC)) + { + FreeGC(pGC, (XID)0); + pGC = (GCPtr)NULL; + } + return pGC; +} + +void +FreeGCperDepth(int screenNum) +{ + int i; + ScreenPtr pScreen; + GCPtr *ppGC; + + pScreen = screenInfo.screens[screenNum]; + ppGC = pScreen->GCperDepth; + + for (i = 0; i <= pScreen->numDepths; i++) + (void)FreeGC(ppGC[i], (XID)0); + pScreen->rgf = ~0L; +} + + +Bool +CreateGCperDepth(int screenNum) +{ + int i; + ScreenPtr pScreen; + DepthPtr pDepth; + GCPtr *ppGC; + + pScreen = screenInfo.screens[screenNum]; + pScreen->rgf = 0; + ppGC = pScreen->GCperDepth; + /* do depth 1 separately because it's not included in list */ + if (!(ppGC[0] = CreateScratchGC(pScreen, 1))) + return FALSE; + ppGC[0]->graphicsExposures = FALSE; + /* Make sure we don't overflow GCperDepth[] */ + if( pScreen->numDepths > MAXFORMATS ) + return FALSE; + + pDepth = pScreen->allowedDepths; + for (i=0; inumDepths; i++, pDepth++) + { + if (!(ppGC[i+1] = CreateScratchGC(pScreen, pDepth->depth))) + { + for (; i >= 0; i--) + (void)FreeGC(ppGC[i], (XID)0); + return FALSE; + } + ppGC[i+1]->graphicsExposures = FALSE; + } + return TRUE; +} + +Bool +CreateDefaultStipple(int screenNum) +{ + ScreenPtr pScreen; + ChangeGCVal tmpval[3]; + xRectangle rect; + CARD16 w, h; + GCPtr pgcScratch; + + pScreen = screenInfo.screens[screenNum]; + + w = 16; + h = 16; + (* pScreen->QueryBestSize)(StippleShape, &w, &h, pScreen); + if (!(pScreen->PixmapPerDepth[0] = + (*pScreen->CreatePixmap)(pScreen, w, h, 1, 0))) + return FALSE; + /* fill stipple with 1 */ + tmpval[0].val = GXcopy; + tmpval[1].val = 1; + tmpval[2].val = FillSolid; + pgcScratch = GetScratchGC(1, pScreen); + if (!pgcScratch) + { + (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); + return FALSE; + } + (void)ChangeGC(NullClient, pgcScratch, GCFunction|GCForeground|GCFillStyle, tmpval); + ValidateGC((DrawablePtr)pScreen->PixmapPerDepth[0], pgcScratch); + rect.x = 0; + rect.y = 0; + rect.width = w; + rect.height = h; + (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pScreen->PixmapPerDepth[0], + pgcScratch, 1, &rect); + FreeScratchGC(pgcScratch); + return TRUE; +} + +void +FreeDefaultStipple(int screenNum) +{ + ScreenPtr pScreen = screenInfo.screens[screenNum]; + (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); +} + +int +SetDashes(GCPtr pGC, unsigned offset, unsigned ndash, unsigned char *pdash) +{ + long i; + unsigned char *p, *indash; + BITS32 maskQ = 0; + + i = ndash; + p = pdash; + while (i--) + { + if (!*p++) + { + /* dash segment must be > 0 */ + return BadValue; + } + } + + if (ndash & 1) + p = malloc(2 * ndash * sizeof(unsigned char)); + else + p = malloc(ndash * sizeof(unsigned char)); + if (!p) + return BadAlloc; + + pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; + if (offset != pGC->dashOffset) + { + pGC->dashOffset = offset; + pGC->stateChanges |= GCDashOffset; + maskQ |= GCDashOffset; + } + + if (pGC->dash != DefaultDash) + free(pGC->dash); + pGC->numInDashList = ndash; + pGC->dash = p; + if (ndash & 1) + { + pGC->numInDashList += ndash; + indash = pdash; + i = ndash; + while (i--) + *p++ = *indash++; + } + while(ndash--) + *p++ = *pdash++; + pGC->stateChanges |= GCDashList; + maskQ |= GCDashList; + + if (pGC->funcs->ChangeGC) + (*pGC->funcs->ChangeGC) (pGC, maskQ); + return Success; +} + +int +VerifyRectOrder(int nrects, xRectangle *prects, int ordering) +{ + xRectangle *prectP, *prectN; + int i; + + switch(ordering) + { + case Unsorted: + return CT_UNSORTED; + case YSorted: + if(nrects > 1) + { + for(i = 1, prectP = prects, prectN = prects + 1; + i < nrects; + i++, prectP++, prectN++) + if(prectN->y < prectP->y) + return -1; + } + return CT_YSORTED; + case YXSorted: + if(nrects > 1) + { + for(i = 1, prectP = prects, prectN = prects + 1; + i < nrects; + i++, prectP++, prectN++) + if((prectN->y < prectP->y) || + ( (prectN->y == prectP->y) && + (prectN->x < prectP->x) ) ) + return -1; + } + return CT_YXSORTED; + case YXBanded: + if(nrects > 1) + { + for(i = 1, prectP = prects, prectN = prects + 1; + i < nrects; + i++, prectP++, prectN++) + if((prectN->y != prectP->y && + prectN->y < prectP->y + (int) prectP->height) || + ((prectN->y == prectP->y) && + (prectN->height != prectP->height || + prectN->x < prectP->x + (int) prectP->width))) + return -1; + } + return CT_YXBANDED; + } + return -1; +} + +int +SetClipRects(GCPtr pGC, int xOrigin, int yOrigin, int nrects, + xRectangle *prects, int ordering) +{ + int newct, size; + xRectangle *prectsNew; + + newct = VerifyRectOrder(nrects, prects, ordering); + if (newct < 0) + return(BadMatch); + size = nrects * sizeof(xRectangle); + prectsNew = malloc(size); + if (!prectsNew && size) + return BadAlloc; + + pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; + pGC->clipOrg.x = xOrigin; + pGC->stateChanges |= GCClipXOrigin; + + pGC->clipOrg.y = yOrigin; + pGC->stateChanges |= GCClipYOrigin; + + if (size) + memmove((char *)prectsNew, (char *)prects, size); + (*pGC->funcs->ChangeClip)(pGC, newct, (pointer)prectsNew, nrects); + if (pGC->funcs->ChangeGC) + (*pGC->funcs->ChangeGC) (pGC, GCClipXOrigin|GCClipYOrigin|GCClipMask); + return Success; +} + + +/* + sets reasonable defaults + if we can get a pre-allocated one, use it and mark it as used. + if we can't, create one out of whole cloth (The Velveteen GC -- if + you use it often enough it will become real.) +*/ +GCPtr +GetScratchGC(unsigned depth, ScreenPtr pScreen) +{ + int i; + GCPtr pGC; + + for (i=0; i<=pScreen->numDepths; i++) + if ( pScreen->GCperDepth[i]->depth == depth && + !(pScreen->rgf & (1L << (i+1))) + ) + { + pScreen->rgf |= (1L << (i+1)); + pGC = (pScreen->GCperDepth[i]); + + pGC->alu = GXcopy; + pGC->planemask = ~0; + pGC->serialNumber = 0; + pGC->fgPixel = 0; + pGC->bgPixel = 1; + pGC->lineWidth = 0; + pGC->lineStyle = LineSolid; + pGC->capStyle = CapButt; + pGC->joinStyle = JoinMiter; + pGC->fillStyle = FillSolid; + pGC->fillRule = EvenOddRule; + pGC->arcMode = ArcChord; + pGC->patOrg.x = 0; + pGC->patOrg.y = 0; + pGC->subWindowMode = ClipByChildren; + pGC->graphicsExposures = FALSE; + pGC->clipOrg.x = 0; + pGC->clipOrg.y = 0; + if (pGC->clientClipType != CT_NONE) + (*pGC->funcs->ChangeClip) (pGC, CT_NONE, NULL, 0); + pGC->stateChanges = GCAllBits; + return pGC; + } + /* if we make it this far, need to roll our own */ + pGC = CreateScratchGC(pScreen, depth); + if (pGC) + pGC->graphicsExposures = FALSE; + return pGC; +} + +/* + if the gc to free is in the table of pre-existing ones, +mark it as available. + if not, free it for real +*/ +void +FreeScratchGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + int i; + + for (i=0; i<=pScreen->numDepths; i++) + { + if ( pScreen->GCperDepth[i] == pGC) + { + pScreen->rgf &= ~(1L << (i+1)); + return; + } + } + (void)FreeGC(pGC, (GContext)0); +} diff --git a/xorg-server/dix/inpututils.c b/xorg-server/dix/inpututils.c index 55c27e80f..d2d36bd95 100644 --- a/xorg-server/dix/inpututils.c +++ b/xorg-server/dix/inpututils.c @@ -88,7 +88,6 @@ do_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client) if (!XIShouldNotify(clients[i], dev)) continue; - core_mn.u.u.sequenceNumber = clients[i]->sequence; WriteEventsToClient(clients[i], 1, &core_mn); } diff --git a/xorg-server/dix/resource.c b/xorg-server/dix/resource.c index 00b3368a0..1d33c9aad 100644 --- a/xorg-server/dix/resource.c +++ b/xorg-server/dix/resource.c @@ -183,7 +183,54 @@ RESTYPE lastResourceType; static RESTYPE lastResourceClass; RESTYPE TypeMask; -static DeleteType *DeleteFuncs = (DeleteType *)NULL; +struct ResourceType { + DeleteType deleteFunc; + int errorValue; +}; + +static struct ResourceType *resourceTypes; +static const struct ResourceType predefTypes[] = { + [RT_NONE & (RC_LASTPREDEF - 1)] = { + .deleteFunc = (DeleteType)NoopDDA, + .errorValue = BadValue, + }, + [RT_WINDOW & (RC_LASTPREDEF - 1)] = { + .deleteFunc = DeleteWindow, + .errorValue = BadWindow, + }, + [RT_PIXMAP & (RC_LASTPREDEF - 1)] = { + .deleteFunc = dixDestroyPixmap, + .errorValue = BadPixmap, + }, + [RT_GC & (RC_LASTPREDEF - 1)] = { + .deleteFunc = FreeGC, + .errorValue = BadGC, + }, + [RT_FONT & (RC_LASTPREDEF - 1)] = { + .deleteFunc = CloseFont, + .errorValue = BadFont, + }, + [RT_CURSOR & (RC_LASTPREDEF - 1)] = { + .deleteFunc = FreeCursor, + .errorValue = BadCursor, + }, + [RT_COLORMAP & (RC_LASTPREDEF - 1)] = { + .deleteFunc = FreeColormap, + .errorValue = BadColor, + }, + [RT_CMAPENTRY & (RC_LASTPREDEF - 1)] = { + .deleteFunc = FreeClientPixels, + .errorValue = BadColor, + }, + [RT_OTHERCLIENT & (RC_LASTPREDEF - 1)] = { + .deleteFunc = OtherClientGone, + .errorValue = BadValue, + }, + [RT_PASSIVEGRAB & (RC_LASTPREDEF - 1)] = { + .deleteFunc = DeletePassiveGrab, + .errorValue = BadValue, + }, +}; CallbackListPtr ResourceStateCallback; @@ -200,20 +247,20 @@ RESTYPE CreateNewResourceType(DeleteType deleteFunc, char *name) { RESTYPE next = lastResourceType + 1; - DeleteType *funcs; + struct ResourceType *types; if (next & lastResourceClass) return 0; - funcs = (DeleteType *)realloc(DeleteFuncs, - (next + 1) * sizeof(DeleteType)); - if (!funcs) + types = realloc(resourceTypes, (next + 1) * sizeof(*resourceTypes)); + if (!types) return 0; if (!dixRegisterPrivateOffset(next, -1)) return 0; lastResourceType = next; - DeleteFuncs = funcs; - DeleteFuncs[next] = deleteFunc; + resourceTypes = types; + resourceTypes[next].deleteFunc = deleteFunc; + resourceTypes[next].errorValue = BadValue; /* Called even if name is NULL, to remove any previous entry */ RegisterResourceName(next, name); @@ -221,6 +268,12 @@ CreateNewResourceType(DeleteType deleteFunc, char *name) return next; } +void +SetResourceTypeErrorValue(RESTYPE type, int errorValue) +{ + resourceTypes[type & TypeMask].errorValue = errorValue; +} + RESTYPE CreateNewResourceClass(void) { @@ -251,21 +304,11 @@ InitClientResources(ClientPtr client) lastResourceType = RT_LASTPREDEF; lastResourceClass = RC_LASTPREDEF; TypeMask = RC_LASTPREDEF - 1; - if (DeleteFuncs) - free(DeleteFuncs); - DeleteFuncs = malloc((lastResourceType + 1) * sizeof(DeleteType)); - if (!DeleteFuncs) + free(resourceTypes); + resourceTypes = malloc(sizeof(predefTypes)); + if (!resourceTypes) return FALSE; - DeleteFuncs[RT_NONE & TypeMask] = (DeleteType)NoopDDA; - DeleteFuncs[RT_WINDOW & TypeMask] = DeleteWindow; - DeleteFuncs[RT_PIXMAP & TypeMask] = dixDestroyPixmap; - DeleteFuncs[RT_GC & TypeMask] = FreeGC; - DeleteFuncs[RT_FONT & TypeMask] = CloseFont; - DeleteFuncs[RT_CURSOR & TypeMask] = FreeCursor; - DeleteFuncs[RT_COLORMAP & TypeMask] = FreeColormap; - DeleteFuncs[RT_CMAPENTRY & TypeMask] = FreeClientPixels; - DeleteFuncs[RT_OTHERCLIENT & TypeMask] = OtherClientGone; - DeleteFuncs[RT_PASSIVEGRAB & TypeMask] = DeletePassiveGrab; + memcpy(resourceTypes, predefTypes, sizeof(predefTypes)); } clientTable[i = client->index].resources = malloc(INITBUCKETS*sizeof(ResourcePtr)); @@ -462,7 +505,7 @@ AddResource(XID id, RESTYPE type, pointer value) res = malloc(sizeof(ResourceRec)); if (!res) { - (*DeleteFuncs[type & TypeMask])(value, id); + (*resourceTypes[type & TypeMask].deleteFunc)(value, id); return FALSE; } res->next = *head; @@ -557,7 +600,7 @@ FreeResource(XID id, RESTYPE skipDeleteFuncType) CallResourceStateCallback(ResourceStateFreeing, res); if (rtype != skipDeleteFuncType) - (*DeleteFuncs[rtype & TypeMask])(res->value, res->id); + (*resourceTypes[rtype & TypeMask].deleteFunc)(res->value, res->id); free(res); if (*eltptr != elements) prev = head; /* prev may no longer be valid */ @@ -594,7 +637,7 @@ FreeResourceByType(XID id, RESTYPE type, Bool skipFree) CallResourceStateCallback(ResourceStateFreeing, res); if (!skipFree) - (*DeleteFuncs[type & TypeMask])(res->value, res->id); + (*resourceTypes[type & TypeMask].deleteFunc)(res->value, res->id); free(res); break; } @@ -761,7 +804,7 @@ FreeClientNeverRetainResources(ClientPtr client) CallResourceStateCallback(ResourceStateFreeing, this); elements = *eltptr; - (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); + (*resourceTypes[rtype & TypeMask].deleteFunc)(this->value, this->id); free(this); if (*eltptr != elements) prev = &resources[j]; /* prev may no longer be valid */ @@ -815,7 +858,7 @@ FreeClientResources(ClientPtr client) CallResourceStateCallback(ResourceStateFreeing, this); - (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); + (*resourceTypes[rtype & TypeMask].deleteFunc)(this->value, this->id); free(this); } } @@ -873,6 +916,8 @@ dixLookupResourceByType(pointer *result, XID id, RESTYPE rtype, ResourcePtr res = NULL; *result = NULL; + if ((rtype & TypeMask) > lastResourceType) + return BadImplementation; if ((cid < MAXCLIENTS) && clientTable[cid].buckets) { res = clientTable[cid].resources[Hash(cid, id)]; @@ -882,12 +927,14 @@ dixLookupResourceByType(pointer *result, XID id, RESTYPE rtype, break; } if (!res) - return BadValue; + return resourceTypes[rtype & TypeMask].errorValue; if (client) { client->errorValue = id; cid = XaceHook(XACE_RESOURCE_ACCESS, client, id, res->type, res->value, RT_NONE, NULL, mode); + if (cid == BadValue) + return resourceTypes[rtype & TypeMask].errorValue; if (cid != Success) return cid; } diff --git a/xorg-server/dix/selection.c b/xorg-server/dix/selection.c index 947fc8d18..8763a2d5a 100644 --- a/xorg-server/dix/selection.c +++ b/xorg-server/dix/selection.c @@ -189,8 +189,7 @@ ProcSetSelectionOwner(ClientPtr client) event.u.selectionClear.time = time.milliseconds; event.u.selectionClear.window = pSel->window; event.u.selectionClear.atom = pSel->selection; - TryClientEvents(pSel->client, NULL, &event, 1, NoEventMask, - NoEventMask /* CantBeFiltered */, NullGrab); + WriteEventsToClient(pSel->client, 1, &event); } } else if (rc == BadMatch) @@ -296,9 +295,11 @@ ProcConvertSelection(ClientPtr client) event.u.selectionRequest.selection = stuff->selection; event.u.selectionRequest.target = stuff->target; event.u.selectionRequest.property = stuff->property; - if (TryClientEvents(pSel->client, NULL, &event, 1, NoEventMask, - NoEventMask /* CantBeFiltered */, NullGrab)) + if (pSel->client && pSel->client != serverClient && !pSel->client->clientGone) + { + WriteEventsToClient(pSel->client, 1, &event); return Success; + } } event.u.u.type = SelectionNotify; @@ -307,7 +308,6 @@ ProcConvertSelection(ClientPtr client) event.u.selectionNotify.selection = stuff->selection; event.u.selectionNotify.target = stuff->target; event.u.selectionNotify.property = None; - TryClientEvents(client, NULL, &event, 1, NoEventMask, - NoEventMask /* CantBeFiltered */, NullGrab); + WriteEventsToClient(client, 1, &event); return Success; } diff --git a/xorg-server/dix/window.c b/xorg-server/dix/window.c index 6a12c9d05..5109885e9 100644 --- a/xorg-server/dix/window.c +++ b/xorg-server/dix/window.c @@ -1056,7 +1056,7 @@ ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client) } else { - error = (rc == BadValue) ? BadPixmap : rc; + error = rc; client->errorValue = pixID; goto PatchUp; } @@ -1116,7 +1116,7 @@ ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client) } else { - error = (rc == BadValue) ? BadPixmap : rc; + error = rc; client->errorValue = pixID; goto PatchUp; } @@ -1264,7 +1264,7 @@ ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client) client, DixUseAccess); if (rc != Success) { - error = (rc == BadValue) ? BadColor : rc; + error = rc; client->errorValue = cmap; goto PatchUp; } @@ -1340,7 +1340,7 @@ ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client) RT_CURSOR, client, DixUseAccess); if (rc != Success) { - error = (rc == BadValue) ? BadCursor : rc; + error = rc; client->errorValue = cursorID; goto PatchUp; } diff --git a/xorg-server/glx/glxdri2.c b/xorg-server/glx/glxdri2.c index a02e71a71..1faefb002 100644 --- a/xorg-server/glx/glxdri2.c +++ b/xorg-server/glx/glxdri2.c @@ -187,7 +187,6 @@ __glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust, /* unknown swap completion type */ break; } - wire.sequenceNumber = client->sequence; wire.drawable = drawable->drawId; wire.ust_hi = ust >> 32; wire.ust_lo = ust & 0xffffffff; diff --git a/xorg-server/hw/xfree86/common/xf86.h b/xorg-server/hw/xfree86/common/xf86.h index cddca37a3..2a8b7e0a9 100644 --- a/xorg-server/hw/xfree86/common/xf86.h +++ b/xorg-server/hw/xfree86/common/xf86.h @@ -64,7 +64,7 @@ extern _X_EXPORT ScrnInfoPtr *xf86Screens; /* List of pointers to ScrnInfoRecs * extern _X_EXPORT const unsigned char byte_reversed[256]; extern _X_EXPORT Bool pciSlotClaimed; extern _X_EXPORT Bool fbSlotClaimed; -#if defined(__sparc__) || defined(__sparc) +#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) extern _X_EXPORT Bool sbusSlotClaimed; #endif extern _X_EXPORT confDRIRec xf86ConfigDRI; @@ -104,7 +104,6 @@ extern _X_EXPORT void xf86FormatPciBusNumber(int busnum, char *buffer); extern _X_EXPORT int xf86GetFbInfoForScreen(int scrnIndex); extern _X_EXPORT int xf86ClaimFbSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool active); extern _X_EXPORT int xf86ClaimNoSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool active); -extern _X_EXPORT void xf86EnableAccess(ScrnInfoPtr pScrn); extern _X_EXPORT Bool xf86IsPrimaryPci(struct pci_device * pPci); /* new RAC */ extern _X_EXPORT Bool xf86DriverHasEntities(DriverPtr drvp); diff --git a/xorg-server/hw/xfree86/common/xf86Bus.c b/xorg-server/hw/xfree86/common/xf86Bus.c index 5c1668644..09b94654c 100644 --- a/xorg-server/hw/xfree86/common/xf86Bus.c +++ b/xorg-server/hw/xfree86/common/xf86Bus.c @@ -58,9 +58,139 @@ static int xf86EntityPrivateCount = 0; BusRec primaryBus = { BUS_NONE, { 0 } }; -static Bool xf86ResAccessEnter = FALSE; +/** + * Call the driver's correct probe function. + * + * If the driver implements the \c DriverRec::PciProbe entry-point and an + * appropriate PCI device (with matching Device section in the xorg.conf file) + * is found, it is called. If \c DriverRec::PciProbe or no devices can be + * successfully probed with it (e.g., only non-PCI devices are available), + * the driver's \c DriverRec::Probe function is called. + * + * \param drv Driver to probe + * + * \return + * If a device can be successfully probed by the driver, \c TRUE is + * returned. Otherwise, \c FALSE is returned. + */ +Bool +xf86CallDriverProbe( DriverPtr drv, Bool detect_only ) +{ + Bool foundScreen = FALSE; + + if (drv->PciProbe != NULL) { + if (xf86DoConfigure && xf86DoConfigurePass1) { + assert(detect_only); + foundScreen = xf86PciAddMatchingDev(drv); + } + else { + assert(! detect_only); + foundScreen = xf86PciProbeDev(drv); + } + } + + if (!foundScreen && (drv->Probe != NULL)) { + xf86Msg( X_WARNING, "Falling back to old probe method for %s\n", + drv->driverName); + foundScreen = (*drv->Probe)(drv, (detect_only) ? PROBE_DETECT + : PROBE_DEFAULT); + } + + return foundScreen; +} + +/** + * @return TRUE if all buses are configured and set up correctly and FALSE + * otherwise. + */ +Bool +xf86BusConfig(void) +{ + screenLayoutPtr layout; + int i, j; + + /* Enable full I/O access */ + if (xorgHWAccess) + xorgHWAccess = xf86EnableIO(); + + /* Locate bus slot that had register IO enabled at server startup */ + if (xorgHWAccess) + xf86FindPrimaryDevice(); + + /* + * Now call each of the Probe functions. Each successful probe will + * result in an extra entry added to the xf86Screens[] list for each + * instance of the hardware found. + */ + for (i = 0; i < xf86NumDrivers; i++) { + xorgHWFlags flags; + if (!xorgHWAccess) { + if (!xf86DriverList[i]->driverFunc + || !xf86DriverList[i]->driverFunc(NULL, + GET_REQUIRED_HW_INTERFACES, + &flags) + || NEED_IO_ENABLED(flags)) + continue; + } + + xf86CallDriverProbe(xf86DriverList[i], FALSE); + } + + /* If nothing was detected, return now */ + if (xf86NumScreens == 0) { + xf86Msg(X_ERROR, "No devices detected.\n"); + return FALSE; + } + + xf86VGAarbiterInit(); + + /* + * Match up the screens found by the probes against those specified + * in the config file. Remove the ones that won't be used. Sort + * them in the order specified. + * + * What is the best way to do this? + * + * For now, go through the screens allocated by the probes, and + * look for screen config entry which refers to the same device + * section as picked out by the probe. + * + */ + for (i = 0; i < xf86NumScreens; i++) { + for (layout = xf86ConfigLayout.screens; layout->screen != NULL; + layout++) { + Bool found = FALSE; + for (j = 0; j < xf86Screens[i]->numEntities; j++) { + + GDevPtr dev = xf86GetDevFromEntity( + xf86Screens[i]->entityList[j], + xf86Screens[i]->entityInstanceList[j]); + if (dev == layout->screen->device) { + /* A match has been found */ + xf86Screens[i]->confScreen = layout->screen; + found = TRUE; + break; + } + } + if (found) break; + } + if (layout->screen == NULL) { + /* No match found */ + xf86Msg(X_ERROR, + "Screen %d deleted because of no matching config section.\n", i); + xf86DeleteScreen(i--, 0); + } + } -static Bool doFramebufferMode = FALSE; + /* If no screens left, return now. */ + if (xf86NumScreens == 0) { + xf86Msg(X_ERROR, + "Device(s) detected, but none match those in the config file.\n"); + return FALSE; + } + + return TRUE; +} /* * Call the bus probes relevant to the architecture. @@ -112,21 +242,6 @@ StringToBusType(const char* busID, const char **retID) return ret; } -/* - * Entity related code. - */ - -void -xf86EntityInit(void) -{ - int i; - - for (i = 0; i < xf86NumEntities; i++) - if (xf86Entities[i]->entityInit) { - xf86Entities[i]->entityInit(i,xf86Entities[i]->private); - } -} - int xf86AllocateEntity(void) { @@ -139,28 +254,6 @@ xf86AllocateEntity(void) return (xf86NumEntities - 1); } -static void -EntityEnter(void) -{ - int i; - - for (i = 0; i < xf86NumEntities; i++) - if (xf86Entities[i]->entityEnter) { - xf86Entities[i]->entityEnter(i,xf86Entities[i]->private); - } -} - -static void -EntityLeave(void) -{ - int i; - - for (i = 0; i < xf86NumEntities; i++) - if (xf86Entities[i]->entityLeave) { - xf86Entities[i]->entityLeave(i,xf86Entities[i]->private); - } -} - Bool xf86IsEntityPrimary(int entityIndex) { @@ -385,16 +478,6 @@ xf86GetDevFromEntity(int entityIndex, int instance) return xf86Entities[entityIndex]->devices[i]; } -/* - * xf86AccessInit() - set up everything needed for access control - * called only once on first server generation. - */ -void -xf86AccessInit(void) -{ - xf86ResAccessEnter = TRUE; -} - /* * xf86AccessEnter() -- gets called to save the text mode VGA IO * resources when reentering the server after a VT switch. @@ -402,56 +485,23 @@ xf86AccessInit(void) void xf86AccessEnter(void) { - if (xf86ResAccessEnter) - return; + int i; + + for (i = 0; i < xf86NumEntities; i++) + if (xf86Entities[i]->entityEnter) + xf86Entities[i]->entityEnter(i,xf86Entities[i]->private); - /* - * on enter we simply disable routing of special resources - * to any bus and let the RAC code to "open" the right bridges. - */ - EntityEnter(); xf86EnterServerState(SETUP); - xf86ResAccessEnter = TRUE; } -/* - * xf86AccessLeave() -- prepares access for and calls the - * entityLeave() functions. - * xf86AccessLeaveState() --- gets called to restore the - * access to the VGA IO resources when switching VT or on - * server exit. - * This was split to call xf86AccessLeaveState() from - * ddxGiveUp(). - */ void xf86AccessLeave(void) { - if (!xf86ResAccessEnter) - return; - EntityLeave(); -} - -/* - * xf86EnableAccess() -- enable access to controlled resources. - * To reduce latency when switching access the ScrnInfoRec has - * a linked list of the EntityAccPtr of all screen entities. - */ -/* - * switching access needs to be done in te following oder: - * disable - * 1. disable old entity - * 2. reroute bus - * 3. enable new entity - * Otherwise resources needed for access control might be shadowed - * by other resources! - */ - -void -xf86EnableAccess(ScrnInfoPtr pScrn) -{ - DebugF("Enable access %i\n",pScrn->scrnIndex); + int i; - return; + for (i = 0; i < xf86NumEntities; i++) + if (xf86Entities[i]->entityLeave) + xf86Entities[i]->entityLeave(i,xf86Entities[i]->private); } /* @@ -460,12 +510,17 @@ xf86EnableAccess(ScrnInfoPtr pScrn) typedef enum { TRI_UNSET, TRI_TRUE, TRI_FALSE } TriState; -static void -SetSIGIOForState(xf86State state) +void +xf86EnterServerState(xf86State state) { static int sigio_state; static TriState sigio_blocked = TRI_UNSET; + /* + * This is a good place to block SIGIO during SETUP state. SIGIO should be + * blocked in SETUP state otherwise (u)sleep() might get interrupted + * early. We take care not to call xf86BlockSIGIO() twice. + */ if ((state == SETUP) && (sigio_blocked != TRI_TRUE)) { sigio_state = xf86BlockSIGIO(); sigio_blocked = TRI_TRUE; @@ -475,24 +530,6 @@ SetSIGIOForState(xf86State state) } } -void -xf86EnterServerState(xf86State state) -{ - /* - * This is a good place to block SIGIO during SETUP state. - * SIGIO should be blocked in SETUP state otherwise (u)sleep() - * might get interrupted early. - * We take care not to call xf86BlockSIGIO() twice. - */ - SetSIGIOForState(state); - if (state == SETUP) - DebugF("Entering SETUP state\n"); - else - DebugF("Entering OPERATING state\n"); - - return; -} - /* * xf86PostProbe() -- Allocate all non conflicting resources * This function gets called by xf86Init(). @@ -500,35 +537,25 @@ xf86EnterServerState(xf86State state) void xf86PostProbe(void) { - if (fbSlotClaimed) { - if (pciSlotClaimed + int i; + + if (fbSlotClaimed && (pciSlotClaimed #if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) || sbusSlotClaimed #endif - ) { + )) FatalError("Cannot run in framebuffer mode. Please specify busIDs " " for all framebuffer devices\n"); - return; - } else { - xf86Msg(X_INFO,"Running in FRAMEBUFFER Mode\n"); - doFramebufferMode = TRUE; - return; - } - } + for (i = 0; i < xf86NumEntities; i++) + if (xf86Entities[i]->entityInit) + xf86Entities[i]->entityInit(i,xf86Entities[i]->private); } void xf86PostScreenInit(void) { - if (doFramebufferMode) { - SetSIGIOForState(OPERATING); - return; - } - xf86VGAarbiterWrapFunctions(); - - DebugF("PostScreenInit generation: %i\n",serverGeneration); xf86EnterServerState(OPERATING); } diff --git a/xorg-server/hw/xfree86/common/xf86Configure.c b/xorg-server/hw/xfree86/common/xf86Configure.c index 883c666a6..11dfcb848 100644 --- a/xorg-server/hw/xfree86/common/xf86Configure.c +++ b/xorg-server/hw/xfree86/common/xf86Configure.c @@ -322,7 +322,7 @@ configureScreenSection (int screennum) } static const char* -optionTypeToSting(OptionValueType type) +optionTypeToString(OptionValueType type) { switch (type) { case OPTV_NONE: @@ -339,6 +339,8 @@ optionTypeToSting(OptionValueType type) return "[]"; case OPTV_FREQ: return ""; + case OPTV_PERCENT: + return ""; default: return ""; } @@ -384,7 +386,8 @@ configureDeviceSection (int screennum) " ### Available Driver options are:-\n" " ### Values: : integer, : float, " ": \"True\"/\"False\",\n" - " ### : \"String\", : \" Hz/kHz/MHz\"\n" + " ### : \"String\", : \" Hz/kHz/MHz\",\n" + " ### : \"%\"\n" " ### [arg]: arg optional\n"; ptr->dev_comment = xstrdup(descrip); if (ptr->dev_comment) { @@ -394,7 +397,7 @@ configureDeviceSection (int screennum) const char *prefix = " #Option "; const char *middle = " \t# "; const char *suffix = "\n"; - const char *opttype = optionTypeToSting(p->type); + const char *opttype = optionTypeToString(p->type); char *optname; int len = strlen(ptr->dev_comment) + strlen(prefix) + strlen(middle) + strlen(suffix) + 1; @@ -818,7 +821,6 @@ DoConfigure(void) } xf86PostProbe(); - xf86EntityInit(); for (j = 0; j < xf86NumScreens; j++) { xf86Screens[j]->scrnIndex = j; @@ -834,7 +836,6 @@ DoConfigure(void) ConfiguredMonitor = NULL; - xf86EnableAccess(xf86Screens[dev2screen[j]]); if ((*xf86Screens[dev2screen[j]]->PreInit)(xf86Screens[dev2screen[j]], PROBE_DETECT) && ConfiguredMonitor) { diff --git a/xorg-server/hw/xfree86/common/xf86Init.c b/xorg-server/hw/xfree86/common/xf86Init.c index d78d3d1db..ed9aca67c 100644 --- a/xorg-server/hw/xfree86/common/xf86Init.c +++ b/xorg-server/hw/xfree86/common/xf86Init.c @@ -76,6 +76,7 @@ #include "xf86InPriv.h" #include "picturestr.h" +#include "xf86Bus.h" #include "xf86VGAarbiter.h" #include "globals.h" @@ -83,16 +84,8 @@ #include #include "dpmsproc.h" #endif - -#include -#include "Pci.h" -#include "xf86Bus.h" - #include -/* forward declarations */ -static Bool probe_devices_from_device_sections(DriverPtr drvp); -static Bool add_matching_devices_to_configure_list(DriverPtr drvp); #ifdef XF86PM void (*xf86OSPMClose)(void) = NULL; @@ -335,201 +328,6 @@ InstallSignalHandlers(void) } } - -#define END_OF_MATCHES(m) \ - (((m).vendor_id == 0) && ((m).device_id == 0) && ((m).subvendor_id == 0)) - -Bool -probe_devices_from_device_sections(DriverPtr drvp) -{ - int i, j; - struct pci_device * pPci; - Bool foundScreen = FALSE; - const struct pci_id_match * const devices = drvp->supported_devices; - GDevPtr *devList; - const unsigned numDevs = xf86MatchDevice(drvp->driverName, & devList); - - - for ( i = 0 ; i < numDevs ; i++ ) { - struct pci_device_iterator *iter; - unsigned device_id; - - - /* Find the pciVideoRec associated with this device section. - */ - iter = pci_id_match_iterator_create(NULL); - while ((pPci = pci_device_next(iter)) != NULL) { - if (devList[i]->busID && *devList[i]->busID) { - if (xf86ComparePciBusString(devList[i]->busID, - ((pPci->domain << 8) - | pPci->bus), - pPci->dev, - pPci->func)) { - break; - } - } - else if (xf86IsPrimaryPci(pPci)) { - break; - } - } - - pci_iterator_destroy(iter); - - if (pPci == NULL) { - continue; - } - - device_id = (devList[i]->chipID > 0) - ? devList[i]->chipID : pPci->device_id; - - - /* Once the pciVideoRec is found, determine if the device is supported - * by the driver. If it is, probe it! - */ - for ( j = 0 ; ! END_OF_MATCHES( devices[j] ) ; j++ ) { - if ( PCI_ID_COMPARE( devices[j].vendor_id, pPci->vendor_id ) - && PCI_ID_COMPARE( devices[j].device_id, device_id ) - && ((devices[j].device_class_mask & pPci->device_class) - == devices[j].device_class) ) { - int entry; - - /* Allow the same entity to be used more than once for - * devices with multiple screens per entity. This assumes - * implicitly that there will be a screen == 0 instance. - * - * FIXME Need to make sure that two different drivers don't - * FIXME claim the same screen > 0 instance. - */ - if ( (devList[i]->screen == 0) && !xf86CheckPciSlot( pPci ) ) - continue; - - DebugF("%s: card at %d:%d:%d is claimed by a Device section\n", - drvp->driverName, pPci->bus, pPci->dev, pPci->func); - - /* Allocate an entry in the lists to be returned */ - entry = xf86ClaimPciSlot(pPci, drvp, device_id, - devList[i], devList[i]->active); - - if ((entry == -1) && (devList[i]->screen > 0)) { - unsigned k; - - for ( k = 0; k < xf86NumEntities; k++ ) { - EntityPtr pEnt = xf86Entities[k]; - if (pEnt->bus.type != BUS_PCI) - continue; - - if (pEnt->bus.id.pci == pPci) { - entry = k; - xf86AddDevToEntity(k, devList[i]); - break; - } - } - } - - if (entry != -1) { - if ((*drvp->PciProbe)(drvp, entry, pPci, - devices[j].match_data)) { - foundScreen = TRUE; - } else - xf86UnclaimPciSlot(pPci); - } - - break; - } - } - } - free(devList); - - return foundScreen; -} - - -Bool -add_matching_devices_to_configure_list(DriverPtr drvp) -{ - const struct pci_id_match * const devices = drvp->supported_devices; - int j; - struct pci_device *pPci; - struct pci_device_iterator *iter; - int numFound = 0; - - - iter = pci_id_match_iterator_create(NULL); - while ((pPci = pci_device_next(iter)) != NULL) { - /* Determine if this device is supported by the driver. If it is, - * add it to the list of devices to configure. - */ - for (j = 0 ; ! END_OF_MATCHES(devices[j]) ; j++) { - if ( PCI_ID_COMPARE( devices[j].vendor_id, pPci->vendor_id ) - && PCI_ID_COMPARE( devices[j].device_id, pPci->device_id ) - && ((devices[j].device_class_mask & pPci->device_class) - == devices[j].device_class) ) { - if (xf86CheckPciSlot(pPci)) { - GDevPtr pGDev = xf86AddBusDeviceToConfigure( - drvp->driverName, BUS_PCI, pPci, -1); - if (pGDev != NULL) { - /* After configure pass 1, chipID and chipRev are - * treated as over-rides, so clobber them here. - */ - pGDev->chipID = -1; - pGDev->chipRev = -1; - } - - numFound++; - } - - break; - } - } - } - - pci_iterator_destroy(iter); - - - return (numFound != 0); -} - -/** - * Call the driver's correct probe function. - * - * If the driver implements the \c DriverRec::PciProbe entry-point and an - * appropriate PCI device (with matching Device section in the xorg.conf file) - * is found, it is called. If \c DriverRec::PciProbe or no devices can be - * successfully probed with it (e.g., only non-PCI devices are available), - * the driver's \c DriverRec::Probe function is called. - * - * \param drv Driver to probe - * - * \return - * If a device can be successfully probed by the driver, \c TRUE is - * returned. Otherwise, \c FALSE is returned. - */ -Bool -xf86CallDriverProbe( DriverPtr drv, Bool detect_only ) -{ - Bool foundScreen = FALSE; - - if ( drv->PciProbe != NULL ) { - if ( xf86DoConfigure && xf86DoConfigurePass1 ) { - assert( detect_only ); - foundScreen = add_matching_devices_to_configure_list( drv ); - } - else { - assert( ! detect_only ); - foundScreen = probe_devices_from_device_sections( drv ); - } - } - - if ( ! foundScreen && (drv->Probe != NULL) ) { - xf86Msg( X_WARNING, "Falling back to old probe method for %s\n", - drv->driverName ); - foundScreen = (*drv->Probe)( drv, (detect_only) ? PROBE_DETECT - : PROBE_DEFAULT ); - } - - return foundScreen; -} - /* * InitOutput -- * Initialize screenInfo for all actually accessible framebuffers. @@ -542,7 +340,6 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv) int i, j, k, scr_index; char **modulelist; pointer *optionlist; - screenLayoutPtr layout; Pix24Flags screenpix24, pix24; MessageType pix24From = X_DEFAULT; Bool pix24Fail = FALSE; @@ -693,102 +490,10 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv) else xf86Info.dontVTSwitch = TRUE; - /* Enable full I/O access */ - if (xorgHWAccess) - xorgHWAccess = xf86EnableIO(); - - /* - * Locate bus slot that had register IO enabled at server startup - */ - if (xorgHWAccess) { - xf86AccessInit(); - xf86FindPrimaryDevice(); - } - /* - * Now call each of the Probe functions. Each successful probe will - * result in an extra entry added to the xf86Screens[] list for each - * instance of the hardware found. - */ - - for (i = 0; i < xf86NumDrivers; i++) { - xorgHWFlags flags; - if (!xorgHWAccess) { - if (!xf86DriverList[i]->driverFunc - || !xf86DriverList[i]->driverFunc(NULL, - GET_REQUIRED_HW_INTERFACES, - &flags) - || NEED_IO_ENABLED(flags)) - continue; - } - - xf86CallDriverProbe( xf86DriverList[i], FALSE ); - } - - /* - * If nothing was detected, return now. - */ - - if (xf86NumScreens == 0) { - xf86Msg(X_ERROR, "No devices detected.\n"); - return; - } - - xf86VGAarbiterInit(); - - /* - * Match up the screens found by the probes against those specified - * in the config file. Remove the ones that won't be used. Sort - * them in the order specified. - */ - - /* - * What is the best way to do this? - * - * For now, go through the screens allocated by the probes, and - * look for screen config entry which refers to the same device - * section as picked out by the probe. - * - */ - - for (i = 0; i < xf86NumScreens; i++) { - for (layout = xf86ConfigLayout.screens; layout->screen != NULL; - layout++) { - Bool found = FALSE; - for (j = 0; j < xf86Screens[i]->numEntities; j++) { - - GDevPtr dev = - xf86GetDevFromEntity(xf86Screens[i]->entityList[j], - xf86Screens[i]->entityInstanceList[j]); - - if (dev == layout->screen->device) { - /* A match has been found */ - xf86Screens[i]->confScreen = layout->screen; - found = TRUE; - break; - } - } - if (found) break; - } - if (layout->screen == NULL) { - /* No match found */ - xf86Msg(X_ERROR, - "Screen %d deleted because of no matching config section.\n", i); - xf86DeleteScreen(i--, 0); - } - } - - /* - * If no screens left, return now. - */ - - if (xf86NumScreens == 0) { - xf86Msg(X_ERROR, - "Device(s) detected, but none match those in the config file.\n"); - return; - } + if (xf86BusConfig() == FALSE) + return; xf86PostProbe(); - xf86EntityInit(); /* * Sort the drivers to match the requested ording. Using a slow @@ -1635,20 +1340,12 @@ ddxProcessArgument(int argc, char **argv, int i) } if (!strcmp(argv[i], "-isolateDevice")) { - int bus, device, func; CHECK_FOR_REQUIRED_ARGUMENT(); if (strncmp(argv[++i], "PCI:", 4)) { FatalError("Bus types other than PCI not yet isolable\n"); } - if (sscanf(argv[i], "PCI:%d:%d:%d", &bus, &device, &func) == 3) { - xf86IsolateDevice.domain = PCI_DOM_FROM_BUS(bus); - xf86IsolateDevice.bus = PCI_BUS_NO_DOMAIN(bus); - xf86IsolateDevice.dev = device; - xf86IsolateDevice.func = func; - return 2; - } else { - FatalError("Invalid isolated device specification\n"); - } + xf86PciIsolateDevice(argv[i]); + return 2; } /* Notice cmdline xkbdir, but pass to dix as well */ if (!strcmp(argv[i], "-xkbdir")) diff --git a/xorg-server/hw/xfree86/common/xf86Opt.h b/xorg-server/hw/xfree86/common/xf86Opt.h index ce3d76724..3af4b4069 100644 --- a/xorg-server/hw/xfree86/common/xf86Opt.h +++ b/xorg-server/hw/xfree86/common/xf86Opt.h @@ -1,113 +1,117 @@ - -/* - * Copyright (c) 1998-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) shall not be used in advertising or otherwise to promote - * the sale, use or other dealings in this Software without prior written - * authorization from the copyright holder(s) and author(s). - */ - -/* Option handling things that ModuleSetup procs can use */ - -#ifndef _XF86_OPT_H_ -#define _XF86_OPT_H_ - -typedef struct { - double freq; - int units; -} OptFrequency; - -typedef union { - unsigned long num; - char * str; - double realnum; - Bool bool; - OptFrequency freq; -} ValueUnion; - -typedef enum { - OPTV_NONE = 0, - OPTV_INTEGER, - OPTV_STRING, /* a non-empty string */ - OPTV_ANYSTR, /* Any string, including an empty one */ - OPTV_REAL, - OPTV_BOOLEAN, - OPTV_FREQ -} OptionValueType; - -typedef enum { - OPTUNITS_HZ = 1, - OPTUNITS_KHZ, - OPTUNITS_MHZ -} OptFreqUnits; - -typedef struct { - int token; - const char* name; - OptionValueType type; - ValueUnion value; - Bool found; -} OptionInfoRec, *OptionInfoPtr; - -extern _X_EXPORT int xf86SetIntOption(pointer optlist, const char *name, int deflt); -extern _X_EXPORT double xf86SetRealOption(pointer optlist, const char *name, double deflt); -extern _X_EXPORT char *xf86SetStrOption(pointer optlist, const char *name, char *deflt); -extern _X_EXPORT int xf86SetBoolOption(pointer list, const char *name, int deflt ); -extern _X_EXPORT int xf86CheckIntOption(pointer optlist, const char *name, int deflt); -extern _X_EXPORT double xf86CheckRealOption(pointer optlist, const char *name, double deflt); -extern _X_EXPORT char *xf86CheckStrOption(pointer optlist, const char *name, char *deflt); -extern _X_EXPORT int xf86CheckBoolOption(pointer list, const char *name, int deflt ); -extern _X_EXPORT pointer xf86AddNewOption(pointer head, const char *name, const char *val ); -extern _X_EXPORT pointer xf86NewOption(char *name, char *value ); -extern _X_EXPORT pointer xf86NextOption(pointer list ); -extern _X_EXPORT pointer xf86OptionListCreate(const char **options, int count, int used); -extern _X_EXPORT pointer xf86OptionListMerge(pointer head, pointer tail); -extern _X_EXPORT void xf86OptionListFree(pointer opt); -extern _X_EXPORT char *xf86OptionName(pointer opt); -extern _X_EXPORT char *xf86OptionValue(pointer opt); -extern _X_EXPORT void xf86OptionListReport(pointer parm); -extern _X_EXPORT pointer xf86FindOption(pointer options, const char *name); -extern _X_EXPORT char *xf86FindOptionValue(pointer options, const char *name); -extern _X_EXPORT void xf86MarkOptionUsed(pointer option); -extern _X_EXPORT void xf86MarkOptionUsedByName(pointer options, const char *name); -extern _X_EXPORT Bool xf86CheckIfOptionUsed(pointer option); -extern _X_EXPORT Bool xf86CheckIfOptionUsedByName(pointer options, const char *name); -extern _X_EXPORT void xf86ShowUnusedOptions(int scrnIndex, pointer options); -extern _X_EXPORT void xf86ProcessOptions(int scrnIndex, pointer options, OptionInfoPtr optinfo); -extern _X_EXPORT OptionInfoPtr xf86TokenToOptinfo(const OptionInfoRec *table, int token); -extern _X_EXPORT const char *xf86TokenToOptName(const OptionInfoRec *table, int token); -extern _X_EXPORT Bool xf86IsOptionSet(const OptionInfoRec *table, int token); -extern _X_EXPORT char *xf86GetOptValString(const OptionInfoRec *table, int token); -extern _X_EXPORT Bool xf86GetOptValInteger(const OptionInfoRec *table, int token, int *value); -extern _X_EXPORT Bool xf86GetOptValULong(const OptionInfoRec *table, int token, unsigned long *value); -extern _X_EXPORT Bool xf86GetOptValReal(const OptionInfoRec *table, int token, double *value); -extern _X_EXPORT Bool xf86GetOptValFreq(const OptionInfoRec *table, int token, - OptFreqUnits expectedUnits, double *value); -extern _X_EXPORT Bool xf86GetOptValBool(const OptionInfoRec *table, int token, Bool *value); -extern _X_EXPORT Bool xf86ReturnOptValBool(const OptionInfoRec *table, int token, Bool def); -extern _X_EXPORT int xf86NameCmp(const char *s1, const char *s2); -extern _X_EXPORT char *xf86NormalizeName(const char *s); -extern _X_EXPORT pointer xf86ReplaceIntOption(pointer optlist, const char *name, const int val); -extern _X_EXPORT pointer xf86ReplaceRealOption(pointer optlist, const char *name, const double val); -extern _X_EXPORT pointer xf86ReplaceBoolOption(pointer optlist, const char *name, const Bool val); -extern _X_EXPORT pointer xf86ReplaceStrOption(pointer optlist, const char *name, const char* val); -#endif + +/* + * Copyright (c) 1998-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* Option handling things that ModuleSetup procs can use */ + +#ifndef _XF86_OPT_H_ +#define _XF86_OPT_H_ + +typedef struct { + double freq; + int units; +} OptFrequency; + +typedef union { + unsigned long num; + char * str; + double realnum; + Bool bool; + OptFrequency freq; +} ValueUnion; + +typedef enum { + OPTV_NONE = 0, + OPTV_INTEGER, + OPTV_STRING, /* a non-empty string */ + OPTV_ANYSTR, /* Any string, including an empty one */ + OPTV_REAL, + OPTV_BOOLEAN, + OPTV_PERCENT, + OPTV_FREQ +} OptionValueType; + +typedef enum { + OPTUNITS_HZ = 1, + OPTUNITS_KHZ, + OPTUNITS_MHZ +} OptFreqUnits; + +typedef struct { + int token; + const char* name; + OptionValueType type; + ValueUnion value; + Bool found; +} OptionInfoRec, *OptionInfoPtr; + +extern _X_EXPORT int xf86SetIntOption(pointer optlist, const char *name, int deflt); +extern _X_EXPORT double xf86SetRealOption(pointer optlist, const char *name, double deflt); +extern _X_EXPORT char *xf86SetStrOption(pointer optlist, const char *name, char *deflt); +extern _X_EXPORT int xf86SetBoolOption(pointer list, const char *name, int deflt ); +extern _X_EXPORT double xf86SetPercentOption(pointer list, const char *name, double deflt ); +extern _X_EXPORT int xf86CheckIntOption(pointer optlist, const char *name, int deflt); +extern _X_EXPORT double xf86CheckRealOption(pointer optlist, const char *name, double deflt); +extern _X_EXPORT char *xf86CheckStrOption(pointer optlist, const char *name, char *deflt); +extern _X_EXPORT int xf86CheckBoolOption(pointer list, const char *name, int deflt ); +extern _X_EXPORT double xf86CheckPercentOption(pointer list, const char *name, double deflt ); +extern _X_EXPORT pointer xf86AddNewOption(pointer head, const char *name, const char *val ); +extern _X_EXPORT pointer xf86NewOption(char *name, char *value ); +extern _X_EXPORT pointer xf86NextOption(pointer list ); +extern _X_EXPORT pointer xf86OptionListCreate(const char **options, int count, int used); +extern _X_EXPORT pointer xf86OptionListMerge(pointer head, pointer tail); +extern _X_EXPORT void xf86OptionListFree(pointer opt); +extern _X_EXPORT char *xf86OptionName(pointer opt); +extern _X_EXPORT char *xf86OptionValue(pointer opt); +extern _X_EXPORT void xf86OptionListReport(pointer parm); +extern _X_EXPORT pointer xf86FindOption(pointer options, const char *name); +extern _X_EXPORT char *xf86FindOptionValue(pointer options, const char *name); +extern _X_EXPORT void xf86MarkOptionUsed(pointer option); +extern _X_EXPORT void xf86MarkOptionUsedByName(pointer options, const char *name); +extern _X_EXPORT Bool xf86CheckIfOptionUsed(pointer option); +extern _X_EXPORT Bool xf86CheckIfOptionUsedByName(pointer options, const char *name); +extern _X_EXPORT void xf86ShowUnusedOptions(int scrnIndex, pointer options); +extern _X_EXPORT void xf86ProcessOptions(int scrnIndex, pointer options, OptionInfoPtr optinfo); +extern _X_EXPORT OptionInfoPtr xf86TokenToOptinfo(const OptionInfoRec *table, int token); +extern _X_EXPORT const char *xf86TokenToOptName(const OptionInfoRec *table, int token); +extern _X_EXPORT Bool xf86IsOptionSet(const OptionInfoRec *table, int token); +extern _X_EXPORT char *xf86GetOptValString(const OptionInfoRec *table, int token); +extern _X_EXPORT Bool xf86GetOptValInteger(const OptionInfoRec *table, int token, int *value); +extern _X_EXPORT Bool xf86GetOptValULong(const OptionInfoRec *table, int token, unsigned long *value); +extern _X_EXPORT Bool xf86GetOptValReal(const OptionInfoRec *table, int token, double *value); +extern _X_EXPORT Bool xf86GetOptValFreq(const OptionInfoRec *table, int token, + OptFreqUnits expectedUnits, double *value); +extern _X_EXPORT Bool xf86GetOptValBool(const OptionInfoRec *table, int token, Bool *value); +extern _X_EXPORT Bool xf86ReturnOptValBool(const OptionInfoRec *table, int token, Bool def); +extern _X_EXPORT int xf86NameCmp(const char *s1, const char *s2); +extern _X_EXPORT char *xf86NormalizeName(const char *s); +extern _X_EXPORT pointer xf86ReplaceIntOption(pointer optlist, const char *name, const int val); +extern _X_EXPORT pointer xf86ReplaceRealOption(pointer optlist, const char *name, const double val); +extern _X_EXPORT pointer xf86ReplaceBoolOption(pointer optlist, const char *name, const Bool val); +extern _X_EXPORT pointer xf86ReplacePercentOption(pointer optlist, const char *name, const double val); +extern _X_EXPORT pointer xf86ReplaceStrOption(pointer optlist, const char *name, const char* val); +#endif diff --git a/xorg-server/hw/xfree86/common/xf86Option.c b/xorg-server/hw/xfree86/common/xf86Option.c index 965ce4c7d..9856a6352 100644 --- a/xorg-server/hw/xfree86/common/xf86Option.c +++ b/xorg-server/hw/xfree86/common/xf86Option.c @@ -223,6 +223,18 @@ LookupBoolOption(pointer optlist, const char *name, int deflt, Bool markUsed) return deflt; } +static int +LookupPercentOption(pointer optlist, const char *name, double deflt, Bool markUsed) +{ + OptionInfoRec o; + + o.name = name; + o.type = OPTV_PERCENT; + if (ParseOptionValue(-1, optlist, &o, markUsed)) + deflt = o.value.realnum; + return deflt; +} + /* These xf86Set* functions are intended for use by non-screen specific code */ int @@ -252,6 +264,12 @@ xf86SetBoolOption(pointer optlist, const char *name, int deflt) return LookupBoolOption(optlist, name, deflt, TRUE); } +double +xf86SetPercentOption(pointer optlist, const char *name, double deflt) +{ + return LookupPercentOption(optlist, name, deflt, TRUE); +} + /* * These are like the Set*Option functions, but they don't mark the options * as used. @@ -283,6 +301,12 @@ xf86CheckBoolOption(pointer optlist, const char *name, int deflt) return LookupBoolOption(optlist, name, deflt, FALSE); } + +double +xf86CheckPercentOption(pointer optlist, const char *name, double deflt) +{ + return LookupPercentOption(optlist, name, deflt, FALSE); +} /* * addNewOption() has the required property of replacing the option value * if the option is already present. @@ -309,6 +333,14 @@ xf86ReplaceBoolOption(pointer optlist, const char *name, const Bool val) return xf86AddNewOption(optlist,name,val?"True":"False"); } +pointer +xf86ReplacePercentOption(pointer optlist, const char *name, const double val) +{ + char tmp[16]; + sprintf(tmp, "%lf%%", val); + return xf86AddNewOption(optlist,name,tmp); +} + pointer xf86ReplaceStrOption(pointer optlist, const char *name, const char* val) { @@ -533,6 +565,21 @@ ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, p->found = FALSE; } break; + case OPTV_PERCENT: + { + char tmp = 0; + /* awkward match, but %% doesn't increase the match counter, + * hence 100 looks the same as 100% to the caller of sccanf + */ + if (sscanf(s, "%lf%c", &p->value.realnum, &tmp) != 2 || tmp != '%') { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a percent value\n", p->name); + p->found = FALSE; + } else { + p->found = TRUE; + } + } + break; case OPTV_FREQ: if (*s == '\0') { xf86DrvMsg(scrnIndex, X_WARNING, diff --git a/xorg-server/hw/xfree86/common/xf86Priv.h b/xorg-server/hw/xfree86/common/xf86Priv.h index 0612c9c4e..b0a0f44cc 100644 --- a/xorg-server/hw/xfree86/common/xf86Priv.h +++ b/xorg-server/hw/xfree86/common/xf86Priv.h @@ -1,166 +1,165 @@ -/* - * Copyright (c) 1997-2002 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) shall not be used in advertising or otherwise to promote - * the sale, use or other dealings in this Software without prior written - * authorization from the copyright holder(s) and author(s). - */ - -/* - * This file contains declarations for private XFree86 functions and variables, - * and definitions of private macros. - * - * "private" means not available to video drivers. - */ - -#ifndef _XF86PRIV_H -#define _XF86PRIV_H - -#include - -#include "xf86Privstr.h" -#include "propertyst.h" -#include "input.h" - -/* - * Parameters set ONLY from the command line options - * The global state of these things is held in xf86InfoRec (when appropriate). - */ -extern _X_EXPORT const char *xf86ConfigFile; -extern _X_EXPORT const char *xf86ConfigDir; -extern _X_EXPORT Bool xf86AllowMouseOpenFail; -#ifdef XF86VIDMODE -extern _X_EXPORT Bool xf86VidModeDisabled; -extern _X_EXPORT Bool xf86VidModeAllowNonLocal; -#endif -extern _X_EXPORT Bool xf86fpFlag; -extern _X_EXPORT Bool xf86sFlag; -extern _X_EXPORT Bool xf86bsEnableFlag; -extern _X_EXPORT Bool xf86bsDisableFlag; -extern _X_EXPORT Bool xf86silkenMouseDisableFlag; -extern _X_EXPORT Bool xf86xkbdirFlag; -#ifdef HAVE_ACPI -extern _X_EXPORT Bool xf86acpiDisableFlag; -#endif -extern _X_EXPORT char *xf86LayoutName; -extern _X_EXPORT char *xf86ScreenName; -extern _X_EXPORT char *xf86PointerName; -extern _X_EXPORT char *xf86KeyboardName; -extern _X_EXPORT int xf86FbBpp; -extern _X_EXPORT int xf86Depth; -extern _X_EXPORT Pix24Flags xf86Pix24; -extern _X_EXPORT rgb xf86Weight; -extern _X_EXPORT Bool xf86FlipPixels; -extern _X_EXPORT Gamma xf86Gamma; -extern _X_EXPORT char *xf86ServerName; -extern _X_EXPORT struct pci_slot_match xf86IsolateDevice; - -/* Other parameters */ - -extern _X_EXPORT xf86InfoRec xf86Info; -extern _X_EXPORT const char *xf86ModulePath; -extern _X_EXPORT MessageType xf86ModPathFrom; -extern _X_EXPORT const char *xf86LogFile; -extern _X_EXPORT MessageType xf86LogFileFrom; -extern _X_EXPORT Bool xf86LogFileWasOpened; -extern _X_EXPORT serverLayoutRec xf86ConfigLayout; - -extern _X_EXPORT DriverPtr *xf86DriverList; -extern _X_EXPORT int xf86NumDrivers; -extern _X_EXPORT Bool xf86Resetting; -extern _X_EXPORT Bool xf86Initialising; -extern _X_EXPORT int xf86NumScreens; -extern _X_EXPORT const char *xf86VisualNames[]; -extern _X_EXPORT int xf86Verbose; /* verbosity level */ -extern _X_EXPORT int xf86LogVerbose; /* log file verbosity level */ -extern _X_EXPORT Bool xorgHWAccess; - -extern _X_EXPORT RootWinPropPtr *xf86RegisteredPropertiesTable; - -#ifndef DEFAULT_VERBOSE -#define DEFAULT_VERBOSE 0 -#endif -#ifndef DEFAULT_LOG_VERBOSE -#define DEFAULT_LOG_VERBOSE 3 -#endif -#ifndef DEFAULT_DPI -#define DEFAULT_DPI 96 -#endif - -/* Function Prototypes */ -#ifndef _NO_XF86_PROTOTYPES - -/* xf86Bus.c */ - -extern _X_EXPORT void xf86BusProbe(void); -extern _X_EXPORT void xf86AccessInit(void); -extern _X_EXPORT void xf86AccessEnter(void); -extern _X_EXPORT void xf86AccessLeave(void); -extern _X_EXPORT void xf86EntityInit(void); - -extern _X_EXPORT void xf86FindPrimaryDevice(void); -/* new RAC */ -extern _X_EXPORT void xf86PostProbe(void); -extern _X_EXPORT void xf86ClearEntityListForScreen(int scrnIndex); -extern _X_EXPORT void xf86AddDevToEntity(int entityIndex, GDevPtr dev); -extern _X_EXPORT void xf86PostScreenInit(void); - -/* xf86Config.c */ - -extern _X_EXPORT Bool xf86PathIsSafe(const char *path); - -/* xf86DefaultModes */ - -extern _X_EXPORT const DisplayModeRec xf86DefaultModes[]; -extern _X_EXPORT const int xf86NumDefaultModes; - -/* xf86Configure.c */ -extern _X_EXPORT void DoConfigure(void); - -/* xf86ShowOpts.c */ -extern _X_EXPORT void DoShowOptions(void); - -/* xf86Events.c */ - -extern _X_EXPORT void xf86Wakeup(pointer blockData, int err, pointer pReadmask); -extern _X_HIDDEN int xf86SigWrapper(int signo); -extern _X_EXPORT void xf86HandlePMEvents(int fd, pointer data); -extern _X_EXPORT int (*xf86PMGetEventFromOs)(int fd,pmEvent *events,int num); -extern _X_EXPORT pmWait (*xf86PMConfirmEventToOs)(int fd,pmEvent event); - -/* xf86Helper.c */ -extern _X_EXPORT void xf86LogInit(void); -extern _X_EXPORT void xf86CloseLog(void); - -/* xf86Init.c */ -extern _X_EXPORT Bool xf86LoadModules(char **list, pointer *optlist); -extern _X_EXPORT int xf86SetVerbosity(int verb); -extern _X_EXPORT int xf86SetLogVerbosity(int verb); -extern _X_EXPORT Bool xf86CallDriverProbe( struct _DriverRec * drv, Bool detect_only ); - -/* xf86Xinput.c */ -extern _X_EXPORT EventList *xf86Events; - -#endif /* _NO_XF86_PROTOTYPES */ - - -#endif /* _XF86PRIV_H */ +/* + * Copyright (c) 1997-2002 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * This file contains declarations for private XFree86 functions and variables, + * and definitions of private macros. + * + * "private" means not available to video drivers. + */ + +#ifndef _XF86PRIV_H +#define _XF86PRIV_H + +#include + +#include "xf86Privstr.h" +#include "propertyst.h" +#include "input.h" + +/* + * Parameters set ONLY from the command line options + * The global state of these things is held in xf86InfoRec (when appropriate). + */ +extern _X_EXPORT const char *xf86ConfigFile; +extern _X_EXPORT const char *xf86ConfigDir; +extern _X_EXPORT Bool xf86AllowMouseOpenFail; +#ifdef XF86VIDMODE +extern _X_EXPORT Bool xf86VidModeDisabled; +extern _X_EXPORT Bool xf86VidModeAllowNonLocal; +#endif +extern _X_EXPORT Bool xf86fpFlag; +extern _X_EXPORT Bool xf86sFlag; +extern _X_EXPORT Bool xf86bsEnableFlag; +extern _X_EXPORT Bool xf86bsDisableFlag; +extern _X_EXPORT Bool xf86silkenMouseDisableFlag; +extern _X_EXPORT Bool xf86xkbdirFlag; +#ifdef HAVE_ACPI +extern _X_EXPORT Bool xf86acpiDisableFlag; +#endif +extern _X_EXPORT char *xf86LayoutName; +extern _X_EXPORT char *xf86ScreenName; +extern _X_EXPORT char *xf86PointerName; +extern _X_EXPORT char *xf86KeyboardName; +extern _X_EXPORT int xf86FbBpp; +extern _X_EXPORT int xf86Depth; +extern _X_EXPORT Pix24Flags xf86Pix24; +extern _X_EXPORT rgb xf86Weight; +extern _X_EXPORT Bool xf86FlipPixels; +extern _X_EXPORT Gamma xf86Gamma; +extern _X_EXPORT char *xf86ServerName; +extern _X_EXPORT struct pci_slot_match xf86IsolateDevice; + +/* Other parameters */ + +extern _X_EXPORT xf86InfoRec xf86Info; +extern _X_EXPORT const char *xf86ModulePath; +extern _X_EXPORT MessageType xf86ModPathFrom; +extern _X_EXPORT const char *xf86LogFile; +extern _X_EXPORT MessageType xf86LogFileFrom; +extern _X_EXPORT Bool xf86LogFileWasOpened; +extern _X_EXPORT serverLayoutRec xf86ConfigLayout; + +extern _X_EXPORT DriverPtr *xf86DriverList; +extern _X_EXPORT int xf86NumDrivers; +extern _X_EXPORT Bool xf86Resetting; +extern _X_EXPORT Bool xf86Initialising; +extern _X_EXPORT int xf86NumScreens; +extern _X_EXPORT const char *xf86VisualNames[]; +extern _X_EXPORT int xf86Verbose; /* verbosity level */ +extern _X_EXPORT int xf86LogVerbose; /* log file verbosity level */ +extern _X_EXPORT Bool xorgHWAccess; + +extern _X_EXPORT RootWinPropPtr *xf86RegisteredPropertiesTable; + +#ifndef DEFAULT_VERBOSE +#define DEFAULT_VERBOSE 0 +#endif +#ifndef DEFAULT_LOG_VERBOSE +#define DEFAULT_LOG_VERBOSE 3 +#endif +#ifndef DEFAULT_DPI +#define DEFAULT_DPI 96 +#endif + +/* Function Prototypes */ +#ifndef _NO_XF86_PROTOTYPES + +/* xf86Bus.c */ + +extern _X_EXPORT Bool xf86BusConfig(void); +extern _X_EXPORT void xf86BusProbe(void); +extern _X_EXPORT void xf86AccessEnter(void); +extern _X_EXPORT void xf86AccessLeave(void); + +extern _X_EXPORT void xf86FindPrimaryDevice(void); +/* new RAC */ +extern _X_EXPORT void xf86PostProbe(void); +extern _X_EXPORT void xf86ClearEntityListForScreen(int scrnIndex); +extern _X_EXPORT void xf86AddDevToEntity(int entityIndex, GDevPtr dev); +extern _X_EXPORT void xf86PostScreenInit(void); + +/* xf86Config.c */ + +extern _X_EXPORT Bool xf86PathIsSafe(const char *path); + +/* xf86DefaultModes */ + +extern _X_EXPORT const DisplayModeRec xf86DefaultModes[]; +extern _X_EXPORT const int xf86NumDefaultModes; + +/* xf86Configure.c */ +extern _X_EXPORT void DoConfigure(void); + +/* xf86ShowOpts.c */ +extern _X_EXPORT void DoShowOptions(void); + +/* xf86Events.c */ + +extern _X_EXPORT void xf86Wakeup(pointer blockData, int err, pointer pReadmask); +extern _X_HIDDEN int xf86SigWrapper(int signo); +extern _X_EXPORT void xf86HandlePMEvents(int fd, pointer data); +extern _X_EXPORT int (*xf86PMGetEventFromOs)(int fd,pmEvent *events,int num); +extern _X_EXPORT pmWait (*xf86PMConfirmEventToOs)(int fd,pmEvent event); + +/* xf86Helper.c */ +extern _X_EXPORT void xf86LogInit(void); +extern _X_EXPORT void xf86CloseLog(void); + +/* xf86Init.c */ +extern _X_EXPORT Bool xf86LoadModules(char **list, pointer *optlist); +extern _X_EXPORT int xf86SetVerbosity(int verb); +extern _X_EXPORT int xf86SetLogVerbosity(int verb); +extern _X_EXPORT Bool xf86CallDriverProbe( struct _DriverRec * drv, Bool detect_only ); + +/* xf86Xinput.c */ +extern _X_EXPORT EventList *xf86Events; + +#endif /* _NO_XF86_PROTOTYPES */ + + +#endif /* _XF86PRIV_H */ diff --git a/xorg-server/hw/xfree86/common/xf86ShowOpts.c b/xorg-server/hw/xfree86/common/xf86ShowOpts.c index 77f156486..831e6b787 100644 --- a/xorg-server/hw/xfree86/common/xf86ShowOpts.c +++ b/xorg-server/hw/xfree86/common/xf86ShowOpts.c @@ -70,6 +70,8 @@ optionTypeToSting(OptionValueType type) return ""; case OPTV_FREQ: return ""; + case OPTV_PERCENT: + return ""; default: return ""; } diff --git a/xorg-server/hw/xfree86/common/xf86pciBus.c b/xorg-server/hw/xfree86/common/xf86pciBus.c index b3164730c..925751256 100644 --- a/xorg-server/hw/xfree86/common/xf86pciBus.c +++ b/xorg-server/hw/xfree86/common/xf86pciBus.c @@ -420,4 +420,164 @@ xf86CheckPciSlot(const struct pci_device *d) return TRUE; } +#define END_OF_MATCHES(m) \ + (((m).vendor_id == 0) && ((m).device_id == 0) && ((m).subvendor_id == 0)) +Bool +xf86PciAddMatchingDev(DriverPtr drvp) +{ + const struct pci_id_match * const devices = drvp->supported_devices; + int j; + struct pci_device *pPci; + struct pci_device_iterator *iter; + int numFound = 0; + + + iter = pci_id_match_iterator_create(NULL); + while ((pPci = pci_device_next(iter)) != NULL) { + /* Determine if this device is supported by the driver. If it is, + * add it to the list of devices to configure. + */ + for (j = 0 ; ! END_OF_MATCHES(devices[j]) ; j++) { + if ( PCI_ID_COMPARE( devices[j].vendor_id, pPci->vendor_id ) + && PCI_ID_COMPARE( devices[j].device_id, pPci->device_id ) + && ((devices[j].device_class_mask & pPci->device_class) + == devices[j].device_class) ) { + if (xf86CheckPciSlot(pPci)) { + GDevPtr pGDev = xf86AddBusDeviceToConfigure( + drvp->driverName, BUS_PCI, pPci, -1); + if (pGDev != NULL) { + /* After configure pass 1, chipID and chipRev are + * treated as over-rides, so clobber them here. + */ + pGDev->chipID = -1; + pGDev->chipRev = -1; + } + + numFound++; + } + + break; + } + } + } + + pci_iterator_destroy(iter); + + return (numFound != 0); +} + +Bool +xf86PciProbeDev(DriverPtr drvp) +{ + int i, j; + struct pci_device * pPci; + Bool foundScreen = FALSE; + const struct pci_id_match * const devices = drvp->supported_devices; + GDevPtr *devList; + const unsigned numDevs = xf86MatchDevice(drvp->driverName, & devList); + + for ( i = 0 ; i < numDevs ; i++ ) { + struct pci_device_iterator *iter; + unsigned device_id; + + + /* Find the pciVideoRec associated with this device section. + */ + iter = pci_id_match_iterator_create(NULL); + while ((pPci = pci_device_next(iter)) != NULL) { + if (devList[i]->busID && *devList[i]->busID) { + if (xf86ComparePciBusString(devList[i]->busID, + ((pPci->domain << 8) + | pPci->bus), + pPci->dev, + pPci->func)) { + break; + } + } + else if (xf86IsPrimaryPci(pPci)) { + break; + } + } + + pci_iterator_destroy(iter); + + if (pPci == NULL) { + continue; + } + device_id = (devList[i]->chipID > 0) + ? devList[i]->chipID : pPci->device_id; + + + /* Once the pciVideoRec is found, determine if the device is supported + * by the driver. If it is, probe it! + */ + for ( j = 0 ; ! END_OF_MATCHES( devices[j] ) ; j++ ) { + if ( PCI_ID_COMPARE( devices[j].vendor_id, pPci->vendor_id ) + && PCI_ID_COMPARE( devices[j].device_id, device_id ) + && ((devices[j].device_class_mask & pPci->device_class) + == devices[j].device_class) ) { + int entry; + + /* Allow the same entity to be used more than once for + * devices with multiple screens per entity. This assumes + * implicitly that there will be a screen == 0 instance. + * + * FIXME Need to make sure that two different drivers don't + * FIXME claim the same screen > 0 instance. + */ + if ((devList[i]->screen == 0) && !xf86CheckPciSlot(pPci)) + continue; + + DebugF("%s: card at %d:%d:%d is claimed by a Device section\n", + drvp->driverName, pPci->bus, pPci->dev, pPci->func); + + /* Allocate an entry in the lists to be returned */ + entry = xf86ClaimPciSlot(pPci, drvp, device_id, + devList[i], devList[i]->active); + + if ((entry == -1) && (devList[i]->screen > 0)) { + unsigned k; + + for (k = 0; k < xf86NumEntities; k++ ) { + EntityPtr pEnt = xf86Entities[k]; + if (pEnt->bus.type != BUS_PCI) + continue; + if (pEnt->bus.id.pci == pPci) { + entry = k; + xf86AddDevToEntity(k, devList[i]); + break; + } + } + } + + if (entry != -1) { + if ((*drvp->PciProbe)(drvp, entry, pPci, + devices[j].match_data)) { + foundScreen = TRUE; + } else + xf86UnclaimPciSlot(pPci); + } + + break; + } + } + } + free(devList); + + return foundScreen; +} + +void +xf86PciIsolateDevice(char *argument) +{ + int bus, device, func; + + if (sscanf(argument, "PCI:%d:%d:%d", &bus, &device, &func) == 3) { + xf86IsolateDevice.domain = PCI_DOM_FROM_BUS(bus); + xf86IsolateDevice.bus = PCI_BUS_NO_DOMAIN(bus); + xf86IsolateDevice.dev = device; + xf86IsolateDevice.func = func; + } else + FatalError("Invalid isolated device specification\n"); +} diff --git a/xorg-server/hw/xfree86/common/xf86pciBus.h b/xorg-server/hw/xfree86/common/xf86pciBus.h index 3125e0db8..b534645ee 100644 --- a/xorg-server/hw/xfree86/common/xf86pciBus.h +++ b/xorg-server/hw/xfree86/common/xf86pciBus.h @@ -1,38 +1,41 @@ - -/* - * Copyright (c) 1999-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) shall not be used in advertising or otherwise to promote - * the sale, use or other dealings in this Software without prior written - * authorization from the copyright holder(s) and author(s). - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#ifndef _XF86_PCI_BUS_H -#define _XF86_PCI_BUS_H - -void xf86PciProbe(void); - -#endif /* _XF86_PCI_BUS_H */ + +/* + * Copyright (c) 1999-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#ifndef _XF86_PCI_BUS_H +#define _XF86_PCI_BUS_H + +void xf86PciProbe(void); +Bool xf86PciAddMatchingDev(DriverPtr drvp); +Bool xf86PciProbeDev(DriverPtr drvp); +void xf86PciIsolateDevice(char *argument); + +#endif /* _XF86_PCI_BUS_H */ diff --git a/xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c b/xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c index fae8d8b5d..0b7d62dca 100644 --- a/xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c +++ b/xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c @@ -436,7 +436,7 @@ ProcXDGAInstallColormap(ClientPtr client) rc = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, RT_COLORMAP, client, DixInstallAccess); if (rc != Success) - return (rc == BadValue) ? BadColor : rc; + return rc; DGAInstallCmap(cmap); return Success; } @@ -878,7 +878,7 @@ ProcXF86DGAInstallColormap(ClientPtr client) DGAInstallCmap(pcmp); return Success; } else { - return (rc == BadValue) ? BadColor : rc; + return rc; } } diff --git a/xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c b/xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c index 483b92ab1..f29f5bad2 100644 --- a/xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c +++ b/xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c @@ -331,7 +331,6 @@ SendXF86VidModeNotify(ScreenPtr pScreen, int state, Bool forced) XF86VidModeEventPtr pEv; unsigned long mask; xXF86VidModeNotifyEvent ev; - ClientPtr client; int kind; UpdateCurrentTimeIf (); @@ -343,19 +342,15 @@ SendXF86VidModeNotify(ScreenPtr pScreen, int state, Bool forced) kind = XF86VidModeModeChange; for (pEv = pPriv->events; pEv; pEv = pEv->next) { - client = pEv->client; - if (client->clientGone) - continue; if (!(pEv->mask & mask)) continue; ev.type = XF86VidModeNotify + XF86VidModeEventBase; ev.state = state; - ev.sequenceNumber = client->sequence; ev.timestamp = currentTime.milliseconds; ev.root = WindowTable[pScreen->myNum]->drawable.id; ev.kind = kind; ev.forced = forced; - WriteEventsToClient (client, 1, (xEvent *) &ev); + WriteEventsToClient (pEv->client, 1, (xEvent *) &ev); } } diff --git a/xorg-server/hw/xfree86/doc/sgml/DESIGN.sgml b/xorg-server/hw/xfree86/doc/sgml/DESIGN.sgml index e95df7999..c6fc63edb 100644 --- a/xorg-server/hw/xfree86/doc/sgml/DESIGN.sgml +++ b/xorg-server/hw/xfree86/doc/sgml/DESIGN.sgml @@ -1,7414 +1,7420 @@ - %defs; - - - - - - - - - - - - - - - - - - - - - - -] > - -
- -XFree86 server 4.x Design (DRAFT) -<author>The XFree86 Project, Inc -<and>Updates for X11R&relvers; by Jim Gettys -<date>19 December 2003 - - - - - - - -<ident> -$XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/DESIGN.sgml,v 1.53 2003/08/23 14:10:14 dawes Exp $ -</ident> - - -<p> -<bf>NOTE</bf>: This is a DRAFT document, and the interfaces described here -are subject to change without notice. - - -<sect>Preface -<p> - -The broad design principles are: -<itemize> - <item>keep it reasonable - <itemize> - <item>We cannot rewrite the complete server - <item>We don't want to re-invent the wheel - </itemize> - <item>keep it modular - <itemize> - <item>As many things as possible should go into modules - <item>The basic loader binary should be minimal - <item>A clean design with well defined layering is important - <item>DDX specific global variables are a nono - <item>The structure should be flexible enough to allow - future extensions - <item> The structure should minimize duplication of common code - </itemize> - <item>keep important features in mind - <itemize> - <item>multiple screens, including multiple instances of drivers - <item>mixing different color depths and visuals on different - and ideally even on the same screen - <item>better control of the PCI device used - <item>better config file parser - <item>get rid of all VGA compatibility assumptions - </itemize> -</itemize> - -Unless we find major deficiencies in the DIX layer, we should avoid -making changes there. - -<sect>The xorg.conf File -<p> - -The xorg.conf file format is similar to the old format, with the following -changes: - -<sect1>&k.device; section -<p> - - The &k.device; sections are similar to what they used to be, and - describe hardware-specific information for a single video card. - &k.device; - Some new keywords are added: - - - <descrip> - <tag>Driver "drivername"</tag> - Specifies the name of the driver to be used for the card. This - is mandatory. - <tag>BusID "busslot"</tag> - Specifies uniquely the location of the card on the bus. The - purpose is to identify particular cards in a multi-headed - configuration. The format of the argument is intentionally - vague, and may be architecture dependent. For a PCI bus, it - is something like "bus:slot:func". - </descrip> - - A &k.device; section is considered ``active'' if there is a reference - to it in an active &k.screen; section. - -<sect1>&k.screen; section -<p> - - The &k.screen; sections are similar to what they used to be. They - no longer have a &k.driver; keyword, but an &k.identifier; keyword - is added. (The &k.driver; keyword may be accepted in place of the - &k.identifier; keyword for compatibility purposes.) The identifier - can be used to identify which screen is to be active when multiple - &k.screen sections are present. It is possible to specify the active - screen from the command line. A default is chosen in the absence - of one being specified. A &k.screen; section is considered ``active'' - if there is a reference to it either from the command line, or from - an active &k.serverlayout; section. - -<sect1>&k.inputdevice; section -<p> - - The &k.inputdevice; section is a new section that describes - configuration information for input devices. It replaces the old - &s.key;Keyboard&e.key;, &s.key;Pointer&e.key; and &s.key;XInput&e.key; - sections. Like the &k.device; section, it has two mandatory keywords: - &k.identifier; and &k.driver;. For compatibility purposes the old - &s.key;Keyboard&e.key; and &s.key;Pointer&e.key; sections are - converted by the parser into &k.inputdevice; sections as follows: - - <descrip> - <tag>&s.key;Keyboard&e.key;</tag> - &k.identifier; "Implicit Core Keyboard"<newline> - &k.driver; "keyboard" - <tag>&s.key;Pointer&e.key;</tag> - &k.identifier; "Implicit Core Pointer"<newline> - &k.driver; "mouse" - </descrip> - - An &k.inputdevice; section is considered active if there is a - reference to it in an active &k.serverlayout; section. An - &k.inputdevice; section may also be referenced implicitly if there - is no &k.serverlayout; section, if the &s.cmd;-screen&e.cmd; command - line options is used, or if the &k.serverlayout; section doesn't - reference any &k.inputdevice; sections. In this case, the first - sections with drivers "keyboard" and "mouse" are used as the core - keyboard and pointer respectively. - -<sect1>&k.serverlayout; section -<p> - - The &k.serverlayout; section is a new section that is used to identify - which &k.screen; sections are to be used in a multi-headed configuration, - and the relative layout of those screens. It also identifies which - &k.inputdevice; sections are to be used. Each &k.serverlayout section - has an identifier, a list of &k.screen; section identifiers, and a list of - &k.inputdevice; section identifiers. &k.serverflags; options may also be - included in a &k.serverlayout; section, making it possible to override - the global values in the &k.serverflags; section. - - A &k.serverlayout; section can be made active by being referenced on - the command line. In the absence of this, a default will be chosen - (the first one found). The screen names may optionally be followed - by a number specifying the preferred screen number, and optionally - by information specifying the physical positioning of the screen, - either in absolute terms or relative to another screen (or screens). - When no screen number is specified, they are numbered according to - the order in which they are listed. The old (now obsolete) method - of providing the positioning information is to give the names of - the four adjacent screens. The order of these is top, bottom, left, - right. Here is an example of a &k.serverlayout; section for two - screens using the old method, with the second located to the right - of the first: - - <code> - Section "ServerLayout" - Identifier "Main Layout" - Screen 0 "Screen 1" "" "" "" "Screen 2" - Screen 1 "Screen 2" - Screen "Screen 3" - EndSection - </code> - - The preferred way of specifying the layout is to explicitly specify - the screen's location in absolute terms or relative to another - screen. - - In the absolute case, the upper left corner's coordinates are given - after the &s.key;Absolute&e.key; keyword. If the coordinates are - omitted, a value of &s.code;(0,0)&e.code; is assumed. An example - of absolute positioning follows: - - <code> - Section "ServerLayout" - Identifier "Main Layout" - Screen 0 "Screen 1" Absolute 0 0 - Screen 1 "Screen 2" Absolute 1024 0 - Screen "Screen 3" Absolute 2048 0 - EndSection - </code> - - In the relative case, the position is specified by either using one of - the following keywords followed by the name of the reference screen: - - <quote> - &s.key;RightOf&nl; - LeftOf&nl; - Above&nl; - Below&nl; - Relative&e.key; - </quote> - - When the &s.key;Relative&e.key; keyword is used, the reference screen - name is followed by the coordinates of the new screen's origin - relative to reference screen. The following example shows how to use - some of the relative positioning options. - - <code> - Section "ServerLayout" - Identifier "Main Layout" - Screen 0 "Screen 1" - Screen 1 "Screen 2" RightOf "Screen 1" - Screen "Screen 3" Relative "Screen 1" 2048 0 - EndSection - </code> - -<sect1>Options -<p> - - Options are used more extensively. They may appear in most sections - now. Options related to drivers can be present in the &k.screen;, - &k.device; and &k.monitor; sections and the &k.display; subsections. - The order of precedence is &k.display;, &k.screen;, &k.monitor;, - &k.device;. Options have been extended to allow an optional value - to be specified in addition to the option name. For more details - about options, see the <ref id="options" name="Options"> section - for details. - -<sect>Driver Interface -<p> - -The driver interface consists of a minimal set of entry points that are -required based on the external events that the driver must react to. -No non-essential structure is imposed on the way they are used beyond -that. This is a significant difference compared with the old design. - -The entry points for drawing operations are already taken care of by -the framebuffer code (including, XAA). Extensions and enhancements to -framebuffer code are outside the scope of this document. - -This approach to the driver interface provides good flexibility, but does -increase the complexity of drivers. To help address this, the XFree86 -common layer provides a set of ``helper'' functions to take care of things -that most drivers need. These helpers help minimise the amount of code -duplication between drivers. The use of helper functions by drivers is -however optional, though encouraged. The basic philosophy behind the -helper functions is that they should be useful to many drivers, that -they should balance this against the complexity of their interface. It -is inevitable that some drivers may find some helpers unsuitable and -need to provide their own code. - -Events that a driver needs to react to are: - - <descrip> - <tag>ScreenInit</tag> - - An initialisation function is called from the DIX layer for each - screen at the start of each server generation. - - <tag>Enter VT</tag> - - The server takes control of the console. - - <tag>Leave VT</tag> - - The server releases control of the console. - - <tag>Mode Switch</tag> - - Change video mode. - - <tag>ViewPort change</tag> - - Change the origin of the physical view port. - - <tag>ScreenSaver state change</tag> - - Screen saver activation/deactivation. - - <tag>CloseScreen</tag> - - A close screen function is called from the DIX layer for each screen - at the end of each server generation. - </descrip> - - -In addition to these events, the following functions are required by -the XFree86 common layer: - - <descrip> - <tag>Identify</tag> - - Print a driver identifying message. - - <tag>Probe</tag> - - This is how a driver identifies if there is any hardware present that - it knows how to drive. - - <tag>PreInit</tag> - - Process information from the xorg.conf file, determine the - full characteristics of the hardware, and determine if a valid - configuration is present. - </descrip> - -The VidMode extension also requires: - - <descrip> - <tag>ValidMode</tag> - - Identify if a new mode is usable with the current configuration. - The PreInit function (and/or helpers it calls) may also make use - of the ValidMode function or something similar. - </descrip> - - -Other extensions may require other entry points. The drivers will -inform the common layer of these in such cases. - -<sect>Resource Access Control Introduction -<p> - -Graphics devices are accessed through ranges in I/O or memory space. -While most modern graphics devices allow relocation of such ranges many -of them still require the use of well established interfaces such as -VGA memory and IO ranges or 8514/A IO ranges. With modern buses (like -PCI) it is possible for multiple video devices to share access to these -resources. The RAC (Resource Access Control) subsystem provides a -mechanism for this. - -<sect1>Terms and Definitions -<p> - -<sect2>Bus -<p> - - ``Bus'' is ambiguous as it is used for different things: it may refer - to physical incompatible extension connectors in a computer system. - The RAC system knows two such systems: The ISA bus and the PCI bus. - (On the software level EISA, MCA and VL buses are currently treated - like ISA buses). ``Bus'' may also refer to logically different - entities on a single bus system which are connected via bridges. A - PCI system may have several distinct PCI buses connecting each other - by PCI-PCI bridges or to the host CPU by HOST-PCI bridges. - - Systems that host more than one bus system link these together using - bridges. Bridges are a concern to RAC as they might block or pass - specific resources. PCI-PCI bridges may be set up to pass VGA - resources to the secondary bus. PCI-ISA buses pass any resources not - decoded on the primary PCI bus to the ISA bus. This way VGA resources - (although exclusive on the ISA bus) can be shared by ISA and PCI - cards. Currently HOST-PCI bridges are not yet handled by RAC as they - require specific drivers. - -<sect2>Entity -<p> - - The smallest independently addressable unit on a system bus is - referred to as an entity. So far we know ISA and PCI entities. PCI - entities can be located on the PCI bus by an unique ID consisting of - the bus, card and function number. - -<sect2>Resource -<p> - - ``Resource'' refers to a range of memory or I/O addresses an entity - can decode. - - If a device is capable of disabling this decoding the resource is - called sharable. For PCI devices a generic method is provided to - control resource decoding. Other devices will have to provide a - device specific function to control decoding. - - If the entity is capable of decoding this range at a different - location this resource is considered relocatable. - - Resources which start at a specific address and occupy a single - continuous range are called block resources. - - Alternatively resource addresses can be decoded in a way that they - satisfy the conditions: - <quote><verb> - address & mask == base - </verb></quote> - and - <quote><verb> - base & mask == base - </verb></quote> - Resources addressed in such a way are called sparse resources. - -<sect2>Server States -<p> - - The resource access control system knows two server states: the - SETUP and the OPERATING state. The SETUP state is entered whenever - a mode change takes place or the server exits or does VT switching. - During this state all entity resources are under resource access - control. During OPERATING state only those entities are controlled - which actually have shared resources that conflict with others. - -<sect>Control Flow in the Server and Mandatory Driver Functions -<p> - -At the start of each server generation, &s.code;main()&e.code; -(&s.code;dix/main.c&e.code;) calls the DDX function -&s.code;InitOutput()&e.code;. This is the first place that the DDX gets -control. &s.code;InitOutput()&e.code; is expected to fill in the global -&s.code;screenInfo&e.code; struct, and one -&s.code;screenInfo.screen[]&e.code; entry for each screen present. Here -is what &s.code;InitOutput()&e.code; does: - -<sect1>Parse the xorg.conf file -<p> - - This is done at the start of the first server generation only. - - The xorg.conf file is read in full, and the resulting information - stored in data structures. None of the parsed information is - processed at this point. The parser data structures are opaque to - the video drivers and to most of the common layer code. - - The entire file is parsed first to remove any section ordering - requirements. - - -<sect1>Initial processing of parsed information and command line options -<p> - - This is done at the start of the first server generation only. - - The initial processing is to determine paths like the - &s.key;ModulePath&e.key;, etc, and to determine which &k.serverlayout;, - &k.screen; and &k.device; sections are active. - - -<sect1>Enable port I/O access -<p> - - Port I/O access is controlled from the XFree86 common layer, and is - ``all or nothing''. It is enabled prior to calling driver probes, at - the start of subsequent server generations, and when VT switching - back to the Xserver. It is disabled at the end of server generations, - and when VT switching away from the Xserver. - - The implementation details of this may vary on different platforms. - - -<sect1>General bus probe -<p> - - This is done at the start of the first server generation only. - - In the case of ix86 machines, this will be a general PCI probe. - The full information obtained here will be available to the drivers. - This information persists for the life of the Xserver. In the PCI - case, the PCI information for all video cards found is available by - calling &s.code;xf86GetPciVideoInfo()&e.code;. - - <quote> - &s.code;pciVideoPtr *xf86GetPciVideoInfo(void)&e.code; - <quote><p> - returns a pointer to a list of pointers to - &s.code;pciVideoRec&e.code; entries, of which there is one for - each detected PCI video card. The list is terminated with a - &s.code;NULL&e.code; pointer. If no PCI video cards were - detected, the return value is &s.code;NULL&e.code;. - - </quote> - </quote> - - After the bus probe, the resource broker is initialised. - - -<sect1>Load initial set of modules -<p> - - This is done at the start of the first server generation only. - - The core server contains a list of mandatory modules. These are loaded - first. Currently the only module on this list is the bitmap font module. - - The next set of modules loaded are those specified explicitly in the - &k.module; section of the config file. - - The final set of initial modules are the driver modules referenced - by the active &k.device; and &k.inputdevice; sections in the config - file. Each of these modules is loaded exactly once. - - -<sect1>Register Video and Input Drivers -<p> - - This is done at the start of the first server generation only. - - When a driver module is loaded, the loader calls its - &s.code;Setup&e.code; function. For video drivers, this function - calls &s.code;xf86AddDriver()&e.code; to register the driver's - &s.code;DriverRec&e.code;, which contains a small set of essential - details and driver entry points required during the early phase of - &s.code;InitOutput()&e.code;. &s.code;xf86AddDriver()&e.code; adds - it to the global &s.code;xf86DriverList[]&e.code; array. - - The &s.code;DriverRec&e.code; contains the driver canonical name, - the &s.code;Identify()&e.code;, - &s.code;Probe()&e.code; and &s.code;AvailableOptions()&e.code; - function entry points as well as a pointer - to the driver's module (as returned from the loader when the driver - was loaded) and a reference count which keeps track of how many - screens are using the driver. The entry driver entry points are - those required prior to the driver allocating and filling in its - &s.code;ScrnInfoRec&e.code;. - - For a static server, the &s.code;xf86DriverList[]&e.code; array is - initialised at build time, and the loading of modules is not done. - - A similar procedure is used for input drivers. The input driver's - &s.code;Setup&e.code; function calls - &s.code;xf86AddInputDriver()&e.code; to register the driver's - &s.code;InputDriverRec&e.code;, which contains a small set of - essential details and driver entry points required during the early - phase of &s.code;InitInput()&e.code;. - &s.code;xf86AddInputDriver()&e.code; adds it to the global - &s.code;xf86InputDriverList[]&e.code; array. For a static server, - the &s.code;xf86InputDriverList[]&e.code; array is initialised at - build time. - - Both the &s.code;xf86DriverList[]&e.code; and - &s.code;xf86InputDriverList[]&e.code; arrays have been initialised - by the end of this stage. - - Once all the drivers are registered, their - &s.code;ChipIdentify()&e.code; functions are called. - - <quote> - &s.code;void ChipIdentify(int flags)&e.code; - <quote> - This is expected to print a message indicating the driver name, - a short summary of what it supports, and a list of the chipset - names that it supports. It may use the xf86PrintChipsets() helper - to do this. - </quote> - </quote> - - <quote> - &s.code;void xf86PrintChipsets(const char *drvname, const char *drvmsg, - &f.indent;SymTabPtr chips)&e.code; - <quote> - This function provides an easy way for a driver's ChipIdentify - function to format the identification message. - </quote> - </quote> - -<sect1>Initialise Access Control -<p> - - This is done at the start of the first server generation only. - - The Resource Access Control (RAC) subsystem is initialised before - calling any driver functions that may access hardware. All generic - bus information is probed and saved (for restoration later). All - (shared resource) video devices are disabled at the generic bus - level, and a probe is done to find the ``primary'' video device. These - devices remain disabled for the next step. - - -<sect1>Video Driver Probe<label id="probe"> -<p> - This is done at the start of the first server generation only. The - &s.code;ChipProbe()&e.code; function of each registered video driver - is called. - - <quote><p> - &s.code;Bool ChipProbe(DriverPtr drv, int flags)&e.code; - <quote><p> - The purpose of this is to identify all instances of hardware - supported by the driver. The flags value is currently either 0, - &s.code;PROBE_DEFAULT&e.code; or &s.code;PROBE_DETECT&e.code;. - &s.code;PROBE_DETECT&e.code; is used if "-configure" or "-probe" - command line arguments are given and indicates to the - &s.code;Probe()&e.code; function that it should not configure the - bus entities and that no xorg.conf information is available. - - The probe must find the active device sections that match the - driver by calling &s.code;xf86MatchDevice()&e.code;. The number - of matches found limits the maximum number of instances for this - driver. If no matches are found, the function should return - &s.code;FALSE&e.code; immediately. - - Devices that cannot be identified by using device-independent - methods should be probed at this stage (keeping in mind that access - to all resources that can be disabled in a device-independent way - are disabled during this phase). The probe must be a minimal - probe. It should just determine if there is a card present that - the driver can drive. It should use the least intrusive probe - methods possible. It must not do anything that is not essential, - like probing for other details such as the amount of memory - installed, etc. It is recommended that the - &s.code;xf86MatchPciInstances()&e.code; helper function be used - for identifying matching PCI devices, and similarly the - &s.code;xf86MatchIsaInstances()&e.code; for ISA (non-PCI) devices - (see the <ref id="rac" name="RAC"> section). These helpers also - checks and claims the appropriate entity. When not using the - helper, that should be done with &s.code;xf86CheckPciSlot()&e.code; - and &s.code;xf86ClaimPciSlot()&e.code; for PCI devices and - &s.code;xf86ClaimIsaSlot()&e.code; for ISA devices (see the - <ref id="rac" name="RAC"> section). - - The probe must register all non-relocatable resources at this - stage. If a resource conflict is found between exclusive resources - the driver will fail immediately. This is usually best done with - the &s.code;xf86ConfigPciEntity()&e.code; helper function - for PCI and &s.code;xf86ConfigIsaEntity()&e.code; for ISA - (see the <ref id="rac" name="RAC"> section). It is possible to - register some entity specific functions with those helpers. When - not using the helpers, the &s.code;xf86AddEntityToScreen()&e.code; - &s.code;xf86ClaimFixedResources()&e.code; and - &s.code;xf86SetEntityFuncs()&e.code; should be used instead (see - the <ref id="rac" name="RAC"> section). - - If a chipset is specified in an active device section which the - driver considers relevant (ie it has no driver specified, or the - driver specified matches the driver doing the probe), the Probe - must return &s.code;FALSE&e.code; if the chipset doesn't match - one supported by the driver. - - If there are no active device sections that the driver considers - relevant, it must return &s.code;FALSE&e.code;. - - Allocate a &s.code;ScrnInfoRec&e.code; for each active instance of the - hardware found, and fill in the basic information, including the - other driver entry points. This is best done with the - &s.code;xf86ConfigIsaEntity()&e.code; helper function for ISA - instances or &s.code;xf86ConfigPciEntity()&e.code; for PCI instances. - These functions allocate a &s.code;ScrnInfoRec&e.code; for active - entities. Optionally &s.code;xf86AllocateScreen()&e.code; - function may also be used to allocate the &s.code;ScrnInfoRec&e.code;. - Any of these functions take care of initialising fields to defined - ``unused'' values. - - Claim the entities for each instance of the hardware found. This - prevents other drivers from claiming the same hardware. - - Must leave hardware in the same state it found it in, and must not - do any hardware initialisation. - - All detection can be overridden via the config file, and that - parsed information is available to the driver at this stage. - - Returns &s.code;TRUE&e.code; if one or more instances are found, - and &s.code;FALSE&e.code; otherwise. - - </quote> - - &s.code;int xf86MatchDevice(const char *drivername, - &f.indent;GDevPtr **driversectlist)&e.code; - <quote><p> - - This function takes the name of the driver and returns via - &s.code;driversectlist&e.code; a list of device sections that - match the driver name. The function return value is the number - of matches found. If a fatal error is encountered the return - value is &s.code;-1&e.code;. - - The caller should use &s.code;xfree()&e.code; to free - &s.code;*driversectlist&e.code; when it is no longer needed. - - </quote> - - &s.code;ScrnInfoPtr xf86AllocateScreen(DriverPtr drv, int flags)&e.code; - <quote><p> - This function allocates a new &s.code;ScrnInfoRec&e.code; in the - &s.code;xf86Screens[]&e.code; array. This function is normally - called by the video driver &s.code;ChipProbe()&e.code; functions. - The return value is a pointer to the newly allocated - &s.code;ScrnInfoRec&e.code;. The &s.code;scrnIndex&e.code;, - &s.code;origIndex&e.code;, &s.code;module&e.code; and - &s.code;drv&e.code; fields are initialised. The reference count - in &s.code;drv&e.code; is incremented. The storage for any - currently allocated ``privates'' pointers is also allocated and - the &s.code;privates&e.code; field initialised (the privates data - is of course not allocated or initialised). This function never - returns on failure. If the allocation fails, the server exits - with a fatal error. The flags value is not currently used, and - should be set to zero. - </quote> - </quote> - - At the completion of this, a list of &s.code;ScrnInfoRecs&e.code; - have been allocated in the &s.code;xf86Screens[]&e.code; array, and - the associated entities and fixed resources have been claimed. The - following &s.code;ScrnInfoRec&e.code; fields must be initialised at - this point: - - <quote><verb> - driverVersion - driverName - scrnIndex(*) - origIndex(*) - drv(*) - module(*) - name - Probe - PreInit - ScreenInit - EnterVT - LeaveVT - numEntities - entityList - access - </verb></quote> - - <tt>(*)</tt> These are initialised when the &s.code;ScrnInfoRec&e.code; - is allocated, and not explicitly by the driver. - - The following &s.code;ScrnInfoRec&e.code; fields must be initialised - if the driver is going to use them: - - <quote><verb> - SwitchMode - AdjustFrame - FreeScreen - ValidMode - </verb></quote> - -<sect1>Matching Screens -<p> - - This is done at the start of the first server generation only. - - After the Probe phase is finished, there will be some number of - &s.code;ScrnInfoRecs&e.code;. These are then matched with the active - &k.screen; sections in the xorg.conf, and those not having an active - &k.screen; section are deleted. If the number of remaining screens - is 0, &s.code;InitOutput()&e.code; sets - &s.code;screenInfo.numScreens&e.code; to &s.code;0&e.code; and - returns. - - At this point the following fields of the &s.code;ScrnInfoRecs&e.code; - must be initialised: - - <quote><verb> - confScreen - </verb></quote> - - -<sect1>Allocate non-conflicting resources -<p> - - This is done at the start of the first server generation only. - - Before calling the drivers again, the resource information collected - from the Probe phase is processed. This includes checking the extent - of PCI resources for the probed devices, and resolving any conflicts - in the relocatable PCI resources. It also reports conflicts, checks - bus routing issues, and anything else that is needed to enable the - entities for the next phase. - - If any drivers registered an &s.code;EntityInit()&e.code; function - during the Probe phase, then they are called here. - - -<sect1>Sort the Screens and pre-check Monitor Information -<p> - - This is done at the start of the first server generation only. - - The list of screens is sorted to match the ordering requested in the - config file. - - The list of modes for each active monitor is checked against the - monitor's parameters. Invalid modes are pruned. - - -<sect1>PreInit -<p> - - This is done at the start of the first server generation only. - - For each &s.code;ScrnInfoRec&e.code;, enable access to the screens entities and call - the &s.code;ChipPreInit()&e.code; function. - - <quote><p> - &s.code;Bool ChipPreInit(ScrnInfoRec screen, int flags)&e.code; - <quote><p> - The purpose of this function is to find out all the information - required to determine if the configuration is usable, and to - initialise those parts of the &s.code;ScrnInfoRec&e.code; that - can be set once at the beginning of the first server generation. - - The number of entities registered for the screen should be checked - against the expected number (most drivers expect only one). The - entity information for each of them should be retrieved (with - &s.code;xf86GetEntityInfo()&e.code;) and checked for the correct - bus type and that none of the sharable resources registered during - the Probe phase was rejected. - - Access to resources for the entities that can be controlled in a - device-independent way are enabled before this function is called. - If the driver needs to access any resources that it has disabled - in an &s.code;EntityInit()&e.code; function that it registered, - then it may enable them here providing that it disables them before - this function returns. - - This includes probing for video memory, clocks, ramdac, and all - other HW info that is needed. It includes determining the - depth/bpp/visual and related info. It includes validating and - determining the set of video modes that will be used (and anything - that is required to determine that). - - This information should be determined in the least intrusive way - possible. The state of the HW must remain unchanged by this - function. Although video memory (including MMIO) may be mapped - within this function, it must be unmapped before returning. Driver - specific information should be stored in a structure hooked into - the &s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; - field. Any other modules which require persistent data (ie data - that persists across server generations) should be initialised in - this function, and they should allocate a ``privates'' index to - hook their data into by calling - &s.code;xf86AllocateScrnInfoPrivateIndex().&e.code; The ``privates'' - data is persistent. - - Helper functions for some of these things are provided at the - XFree86 common level, and the driver can choose to make use of - them. - - All additional resources that the screen needs must be registered - here. This should be done with - &s.code;xf86RegisterResources()&e.code;. If some of the fixed - resources registered in the Probe phase are not needed or not - decoded by the hardware when in the OPERATING server state, their - status should be updated with - &s.code;xf86SetOperatingState()&e.code;. - - Modules may be loaded at any point in this function, and all - modules that the driver will need must be loaded before the end - of this function. Either the &s.code;xf86LoadSubModule()&e.code; - or the &s.code;xf86LoadDrvSubModule()&e.code; function should be - used to load modules depending on whether a - &s.code;ScrnInfoRec&e.code; has been set up. A driver may unload - a module within this function if it was only needed temporarily, - and the &s.code;xf86UnloadSubModule()&e.code; function should be used - to do that. Otherwise there is no need to explicitly unload modules - because the loader takes care of module dependencies and will - unload submodules automatically if/when the driver module is - unloaded. - - The bulk of the &s.code;ScrnInfoRec&e.code; fields should be filled - out in this function. - - &s.code;ChipPreInit()&e.code; returns &s.code;FALSE&e.code; when - the configuration is unusable in some way (unsupported depth, no - valid modes, not enough video memory, etc), and &s.code;TRUE&e.code; - if it is usable. - - It is expected that if the &s.code;ChipPreInit()&e.code; function - returns &s.code;TRUE&e.code;, then the only reasons that subsequent - stages in the driver might fail are lack or resources (like xalloc - failures). All other possible reasons for failure should be - determined by the &s.code;ChipPreInit()&e.code; function. - - </quote> - </quote> - - The &s.code;ScrnInfoRecs&e.code; for screens where the &s.code;ChipPreInit()&e.code; fails are removed. - If none remain, &s.code;InitOutput()&e.code; sets &s.code;screenInfo.numScreens&e.code; to &s.code;0&e.code; and returns. - - At this point, further fields of the &s.code;ScrnInfoRecs&e.code; would normally be - filled in. Most are not strictly mandatory, but many are required - by other layers and/or helper functions that the driver may choose - to use. The documentation for those layers and helper functions - indicates which they require. - - The following fields of the &s.code;ScrnInfoRecs&e.code; should be filled in if the - driver is going to use them: - - <quote><verb> - monitor - display - depth - pixmapBPP - bitsPerPixel - weight (>8bpp only) - mask (>8bpp only) - offset (>8bpp only) - rgbBits (8bpp only) - gamma - defaultVisual - maxHValue - maxVValue - virtualX - virtualY - displayWidth - frameX0 - frameY0 - frameX1 - frameY1 - zoomLocked - modePool - modes - currentMode - progClock (TRUE if clock is programmable) - chipset - ramdac - clockchip - numClocks (if not programmable) - clock[] (if not programmable) - videoRam - biosBase - memBase - memClk - driverPrivate - chipID - chipRev - </verb></quote> - - <quote><p> - &s.code;pointer xf86LoadSubModule(ScrnInfoPtr pScrn, const char *name)&e.code: - and - &s.code;pointer xf86LoadDrvSubModule(DriverPtr drv, const char *name)&e.code: - <quote><p> - Load a module that a driver depends on. This function loads the - module &s.code;name&e.code; as a sub module of the driver. The - return value is a handle identifying the new module. If the load - fails, the return value will be &s.code;NULL&e.code;. If a driver - needs to explicitly unload a module it has loaded in this way, - the return value must be saved and passed to - &s.code;xf86UnloadSubModule()&e.code; when unloading. - - </quote> - - &s.code;void xf86UnloadSubModule(pointer module)&e.code; - <quote><p> - Unloads the module referenced by &s.code;module&e.code;. - &s.code;module&e.code; should be a pointer returned previously - by &s.code;xf86LoadSubModule()&e.code; or - &s.code;xf86LoadDrvSubModule()&e.code; . - - </quote> - </quote> - -<sect1>Cleaning up Unused Drivers -<p> - - At this point it is known which screens will be in use, and which - drivers are being used. Unreferenced drivers (and modules they - may have loaded) are unloaded here. - - -<sect1>Consistency Checks -<p> - - The parameters that must be global to the server, like pixmap formats, - bitmap bit order, bitmap scanline unit and image byte order are - compared for each of the screens. If a mismatch is found, the server - exits with an appropriate message. - - -<sect1>Check if Resource Control is Needed -<p> - - Determine if resource access control is needed. This is the case - if more than one screen is used. If necessary the RAC wrapper module - is loaded. - -<sect1>AddScreen (ScreenInit) -<p> - - At this point, the valid screens are known. - &s.code;AddScreen()&e.code; is called for each of them, passing - &s.code;ChipScreenInit()&e.code; as the argument. - &s.code;AddScreen()&e.code; is a DIX function that allocates a new - &s.code;screenInfo.screen[]&e.code; entry (aka - &s.code;pScreen&e.code;), and does some basic initialisation of it. - It then calls the &s.code;ChipScreenInit()&e.code; function, with - &s.code;pScreen&e.code; as one of its arguments. If - &s.code;ChipScreenInit()&e.code; returns &s.code;FALSE&e.code;, - &s.code;AddScreen()&e.code; returns &s.code;-1&e.code;. Otherwise - it returns the index of the screen. &s.code;AddScreen()&e.code; - should only fail because of programming errors or failure to allocate - resources (like memory). All configuration problems should be - detected BEFORE this point. - - <quote><p> - &s.code;Bool ChipScreenInit(int index, ScreenPtr pScreen, - &f.indent;int argc, char **argv)&e.code; - <quote><p> - This is called at the start of each server generation. - - Fill in all of &s.code;pScreen&e.code;, possibly doing some of - this by calling ScreenInit functions from other layers like mi, - framebuffers (cfb, etc), and extensions. - - Decide which operations need to be placed under resource access - control. The classes of operations are the frame buffer operations - (&s.code;RAC_FB&e.code;), the pointer operations - (&s.code;RAC_CURSOR&e.code;), the viewport change operations - (&s.code;RAC_VIEWPORT&e.code;) and the colormap operations - (&s.code;RAC_COLORMAP&e.code;). Any operation that requires - resources which might be disabled during OPERATING state should - be set to use RAC. This can be specified separately for memory - and IO resources (the &s.code;racMemFlags&e.code; and - &s.code;racIoFlags&e.code; fields of the &s.code;ScrnInfoRec&e.code; - respectively). - - Map any video memory or other memory regions. - - Save the video card state. Enough state must be saved so that - the original state can later be restored. - - Initialise the initial video mode. The &s.code;ScrnInfoRec&e.code;'s - &s.code;vtSema&e.code; field should be set to &s.code;TRUE&e.code; - just prior to changing the video hardware's state. - - </quote> - </quote> - - - The &s.code;ChipScreenInit()&e.code; function (or functions from other - layers that it calls) should allocate entries in the - &s.code;ScreenRec&e.code;'s &s.code;devPrivates&e.code; area by - calling &s.code;AllocateScreenPrivateIndex()&e.code; if it needs - per-generation storage. Since the &s.code;ScreenRec&e.code;'s - &s.code;devPrivates&e.code; information is cleared for each server - generation, this is the correct place to initialise it. - - After &s.code;AddScreen()&e.code; has successfully returned, the - following &s.code;ScrnInfoRec&e.code; fields are initialised: - - <quote><verb> - pScreen - racMemFlags - racIoFlags - </verb></quote> - - The &s.code;ChipScreenInit()&e.code; function should initialise the - &s.code;CloseScreen&e.code; and &s.code;SaveScreen&e.code; fields - of &s.code;pScreen&e.code;. The old value of - &s.code;pScreen->CloseScreen&e.code; should be saved as part of - the driver's per-screen private data, allowing it to be called from - &s.code;ChipCloseScreen()&e.code;. This means that the existing - &s.code;CloseScreen()&e.code; function is wrapped. - -<sect1>Finalising RAC Initialisation -<p> - - After all the &s.code;ChipScreenInit()&e.code; functions have been - called, each screen has registered its RAC requirements. This - information is used to determine which shared resources are requested - by more than one driver and set the access functions accordingly. - This is done following these rules: - - <enum> - <item>The sharable resources registered by each entity are compared. - If a resource is registered by more than one entity the entity - will be marked to indicate that it needs to share this resources - type (IO or MEM). - - <item>A resource marked ``disabled'' during OPERATING state will be - ignored entirely. - - <item>A resource marked ``unused'' will only conflict with an overlapping - resource of an other entity if the second is actually in use - during OPERATING state. - - <item>If an ``unused'' resource was found to conflict but the entity - does not use any other resource of this type the entire resource - type will be disabled for that entity. - </enum> - - -<sect1>Finishing InitOutput() -<p> - - At this point &s.code;InitOutput()&e.code; is finished, and all the - screens have been setup in their initial video mode. - - -<sect1>Mode Switching -<p> - - When a SwitchMode event is received, &s.code;ChipSwitchMode()&e.code; - is called (when it exists): - - <quote><p> - &s.code;Bool ChipSwitchMode(int index, DisplayModePtr mode, int flags)&e.code; - <quote><p> - Initialises the new mode for the screen identified by - &s.code;index;&e.code;. The viewport may need to be adjusted - also. - - </quote> - </quote> - - -<sect1>Changing Viewport -<p> - - When a Change Viewport event is received, - &s.code;ChipAdjustFrame()&e.code; is called (when it exists): - - <quote><p> - &s.code;void ChipAdjustFrame(int index, int x, int y, int flags)&e.code; - <quote><p> - Changes the viewport for the screen identified by - &s.code;index;&e.code;. - - It should be noted that many chipsets impose restrictions on where the - viewport may be placed in the virtual resolution, either for alignment - reasons, or to prevent the start of the viewport from being positioned - within a pixel (as can happen in a 24bpp mode). After calculating the - value the chipset's panning registers need to be set to for non-DGA - modes, this function should recalculate the ScrnInfoRec's - &s.code;frameX0&e.code;, &s.code;frameY0&e.code, &s.code;frameX1&e.code; - and &s.code;frameY1&e.code; fields to correspond to that value. If - this is not done, switching to another mode might cause the position - of a hardware cursor to change. - - </quote> - </quote> - - -<sect1>VT Switching -<p> - - When a VT switch event is received, &s.code;xf86VTSwitch()&e.code; - is called. &s.code;xf86VTSwitch()&e.code; does the following: - - <descrip> - <tag>On ENTER:</tag> - <itemize> - <item>enable port I/O access - - <item>save and initialise the bus/resource state - - <item>enter the SETUP server state - - <item>calls &s.code;ChipEnterVT()&e.code; for each screen - - <item>enter the OPERATING server state - - <item>validate GCs - - <item>Restore fb from saved pixmap for each screen - - <item>Enable all input devices - </itemize> - <tag>On LEAVE:</tag> - <itemize> - <item>Save fb to pixmap for each screen - - <item>validate GCs - - <item>enter the SETUP server state - - <item>calls &s.code;ChipLeaveVT()&e.code; for each screen - - <item>disable all input devices - - <item>restore bus/resource state - - <item>disables port I/O access - </itemize> - </descrip> - - <quote><p> - &s.code;Bool ChipEnterVT(int index, int flags)&e.code; - <quote><p> - This function should initialise the current video mode and - initialise the viewport, turn on the HW cursor if appropriate, - etc. - - Should it re-save the video state before initialising the video - mode? - - </quote> - - &s.code;void ChipLeaveVT(int index, int flags)&e.code; - <quote><p> - This function should restore the saved video state. If - appropriate it should also turn off the HW cursor, and invalidate - any pixmap/font caches. - - </quote> - - Optionally, &s.code;ChipLeaveVT()&e.code; may also unmap memory - regions. If so, &s.code;ChipEnterVT()&e.code; will need to remap - them. Additionally, if an aperture used to access video memory is - unmapped and remapped in this fashion, &s.code;ChipEnterVT()&e.code; - will also need to notify the framebuffer layers of the aperture's new - location in virtual memory. This is done with a call to the screen's - &s.code;ModifyPixmapHeader()&e.code; function, as follows - - <quote><p> - &s.code;(*pScreen->ModifyPixmapHeader)(pScrn->ppix, - &f.indent;-1, -1, -1, -1, -1, <it>NewApertureAddress</it>);&e.code; - <quote><p> - where the &s.code``ppix''&e.code; field in a ScrnInfoRec - points to the pixmap used by the screen's - &s.code;SaveRestoreImage()&e.code; function to hold the screen's - contents while switched out. - - </quote> - </quote> - - Currently, aperture remapping, as described here, should not be - attempted if the driver uses the &s.code;xf8_16bpp&e.code; or - &s.code;xf8_32bpp&e.code; framebuffer layers. A pending - restructuring of VT switching will address this restriction in - the near future. - - </quote> - - Other layers may wrap the &s.code;ChipEnterVT()&e.code; and - &s.code;ChipLeaveVT()&e.code; functions if they need to take some - action when these events are received. - -<sect1>End of server generation -<p> - - At the end of each server generation, the DIX layer calls - &s.code;ChipCloseScreen()&e.code; for each screen: - - <quote><p> - &s.code;Bool ChipCloseScreen(int index, ScreenPtr pScreen)&e.code; - <quote><p> - This function should restore the saved video state and unmap the - memory regions. - - It should also free per-screen data structures allocated by the - driver. Note that the persistent data held in the - &s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; field - should not be freed here because it is needed by subsequent server - generations. - - The &s.code;ScrnInfoRec&e.code;'s &s.code;vtSema&e.code; field - should be set to &s.code;FALSE&e.code; once the video HW state - has been restored. - - Before freeing the per-screen driver data the saved - &s.code;CloseScreen&e.code; value should be restored to - &s.code;pScreen->CloseScreen&e.code;, and that function should - be called after freeing the data. - - </quote> - </quote> - -<sect>Optional Driver Functions -<p> - -The functions outlined here can be called from the XFree86 common layer, -but their presence is optional. - -<sect1>Mode Validation -<p> - - When a mode validation helper supplied by the XFree86-common layer is - being used, it can be useful to provide a function to check for hw - specific mode constraints: - - <quote><p> - &s.code;ModeStatus ChipValidMode(int index, DisplayModePtr mode, - &f.indent;Bool verbose, int flags)&e.code; - <quote><p> - Check the passed mode for hw-specific constraints, and return the - appropriate status value. - - </quote> - </quote> - -<p> -This function may also modify the effective timings and clock of the passed -mode. These have been stored in the mode's &s.code;Crtc*&e.code; and -&s.code;SynthClock&e.code; elements, and have already been adjusted for -interlacing, doublescanning, multiscanning and clock multipliers and dividers. -The function should not modify any other mode field, unless it wants to modify -the mode timings reported to the user by &s.code;xf86PrintModes()&e.code;. - -<p> -The function is called once for every mode in the xorg.conf Monitor section -assigned to the screen, with &s.code;flags&e.code; set to -&s.code;MODECHECK_INITIAL&e.code;. It is subsequently called for every mode -in the xorg.conf Display subsection assigned to the screen, with -&s.code;flags&e.code; set to &s.code;MODECHECK_FINAL&e.code;. In the second -case, the mode will have successfully passed all other tests. In addition, -the &s.code;ScrnInfoRec&e.code;'s &s.code;virtualX&e.code;, -&s.code;virtualY&e.code; and &s.code;displayWidth&e.code; fields will have been -set as if the mode to be validated were to be the last mode accepted. - -<p> -In effect, calls with MODECHECK_INITIAL are intended for checks that do not -depend on any mode other than the one being validated, while calls with -MODECHECK_FINAL are intended for checks that may involve more than one mode. - -<sect1>Free screen data -<p> - - When a screen is deleted prior to the completion of the ScreenInit - phase the &s.code;ChipFreeScreen()&e.code; function is called when defined. - - <quote><p> - &s.code;void ChipFreeScreen(int scrnindex, int flags)&e.code; - <quote><p> - Free any driver-allocated data that may have been allocated up to - and including an unsuccessful &s.code;ChipScreenInit()&e.code; - call. This would predominantly be data allocated by - &s.code;ChipPreInit()&e.code; that persists across server - generations. It would include the &s.code;driverPrivate&e.code;, - and any ``privates'' entries that modules may have allocated. - - </quote> - </quote> - - -<sect>Recommended driver functions -<p> - -The functions outlined here are for internal use by the driver only. -They are entirely optional, and are never accessed directly from higher -layers. The sample function declarations shown here are just examples. -The interface (if any) used is up to the driver. - -<sect1>Save -<p> - - Save the video state. This could be called from &s.code;ChipScreenInit()&e.code; and - (possibly) &s.code;ChipEnterVT()&e.code;. - - <quote><p> - &s.code;void ChipSave(ScrnInfoPtr pScrn)&e.code; - <quote><p> - Saves the current state. This will only be saving pre-server - states or states before returning to the server. There is only - one current saved state per screen and it is stored in private - storage in the screen. - - </quote> - </quote> - -<sect1>Restore -<p> - - Restore the original video state. This could be called from the - &s.code;ChipLeaveVT()&e.code; and &s.code;ChipCloseScreen()&e.code; - functions. - - <quote><p> - &s.code;void ChipRestore(ScrnInfoPtr pScrn)&e.code; - <quote><p> - Restores the saved state from the private storage. Usually only - used for restoring text modes. - - </quote> - </quote> - - -<sect1>Initialise Mode -<p> - - Initialise a video mode. This could be called from the - &s.code;ChipScreenInit()&e.code;, &s.code;ChipSwitchMode()&e.code; - and &s.code;ChipEnterVT()&e.code; functions. - - <quote><p> - &s.code;Bool ChipModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)&e.code; - <quote><p> - Programs the hardware for the given video mode. - - </quote> - </quote> - - -<sect>Data and Data Structures -<p> - -<sect1>Command line data -<p> - -Command line options are typically global, and are stored in global -variables. These variables are read-only and are available to drivers -via a function call interface. Most of these command line values are -processed via helper functions to ensure that they are treated consistently -by all drivers. The other means of access is provided for cases where -the supplied helper functions might not be appropriate. - -Some of them are: - -<quote><verb> - xf86Verbose verbosity level - xf86Bpp -bpp from the command line - xf86Depth -depth from the command line - xf86Weight -weight from the command line - xf86Gamma -{r,g,b,}gamma from the command line - xf86FlipPixels -flippixels from the command line - xf86ProbeOnly -probeonly from the command line - defaultColorVisualClass -cc from the command line -</verb></quote> - -If we ever do allow for screen-specific command line options, we may -need to rethink this. - -These can be accessed in a read-only manner by drivers with the following -functions: - - <quote><p> - &s.code;int xf86GetVerbosity()&e.code; - <quote><p> - Returns the value of &s.code;xf86Verbose&e.code;. - - </quote> - - &s.code;int xf86GetDepth()&e.code; - <quote><p> - Returns the &s.cmd;-depth&e.cmd; command line setting. If not - set on the command line, &s.code;-1&e.code; is returned. - - </quote> - - &s.code;rgb xf86GetWeight()&e.code; - <quote><p> - Returns the &s.cmd;-weight&e.cmd; command line setting. If not - set on the command line, &s.code;{0, 0, 0}&e.code; is returned. - - </quote> - - &s.code;Gamma xf86GetGamma()&e.code; - <quote><p> - Returns the &s.cmd;-gamma&e.cmd; or &s.cmd;-rgamma&e.cmd;, - &s.cmd;-ggamma&e.cmd;, &s.cmd;-bgamma&e.cmd; command line settings. - If not set on the command line, &s.code;{0.0, 0.0, 0.0}&e.code; - is returned. - - </quote> - - &s.code;Bool xf86GetFlipPixels()&e.code; - <quote><p> - Returns &s.code;TRUE&e.code; if &s.cmd;-flippixels&e.cmd; is - present on the command line, and &s.code;FALSE&e.code; otherwise. - - </quote> - - &s.code;const char *xf86GetServerName()&e.code; - <quote><p> - Returns the name of the X server from the command line. - - </quote> - </quote> - -<sect1>Data handling -<p> - -Config file data contains parts that are global, and parts that are -Screen specific. All of it is parsed into data structures that neither -the drivers or most other parts of the server need to know about. - -The global data is typically not required by drivers, and as such, most -of it is stored in the private &s.code;xf86InfoRec&e.code;. - -The screen-specific data collected from the config file is stored in -screen, device, display, monitor-specific data structures that are separate -from the &s.code;ScrnInfoRecs&e.code;, with the appropriate elements/fields -hooked into the &s.code;ScrnInfoRecs&e.code; as required. The screen -config data is held in &s.code;confScreenRec&e.code;, device data in -the &s.code;GDevRec&e.code;, monitor data in the &s.code;MonRec&e.code;, -and display data in the &s.code;DispRec&e.code;. - -The XFree86 common layer's screen specific data (the actual data in use -for each screen) is held in the &s.code;ScrnInfoRecs&e.code;. As has -been outlined above, the &s.code;ScrnInfoRecs&e.code; are allocated at probe -time, and it is the responsibility of the Drivers' &s.code;Probe()&e.code; -and &s.code;PreInit()&e.code; functions to finish filling them in based -on both data provided on the command line and data provided from the -Config file. The precedence for this is: - - <quote> - command line -> config file -> probed/default data - </quote> - -For most things in this category there are helper functions that the -drivers can use to ensure that the above precedence is consistently -used. - -As well as containing screen-specific data that the XFree86 common layer -(including essential parts of the server infrastructure as well as helper -functions) needs to access, it also contains some data that drivers use -internally. When considering whether to add a new field to the -&s.code;ScrnInfoRec&e.code;, consider the balance between the convenience -of things that lots of drivers need and the size/obscurity of the -&s.code;ScrnInfoRec&e.code;. - -Per-screen driver specific data that cannot be accommodated with the -static &s.code;ScrnInfoRec&e.code; fields is held in a driver-defined -data structure, a pointer to which is assigned to the -&s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; field. This -is per-screen data that persists across server generations (as does the -bulk of the static &s.code;ScrnInfoRec&e.code; data). It would typically -also include the video card's saved state. - -Per-screen data for other modules that the driver uses (for example, -the XAA module) that is reset for each server generation is hooked into -the &s.code;ScrnInfoRec&e.code; through it's &s.code;privates&e.code; -field. - -Once it has stabilised, the data structures and variables accessible to -video drivers will be documented here. In the meantime, those things -defined in the &s.code;xf86.h&e.code; and &s.code;xf86str.h&e.code; -files are visible to video drivers. Things defined in -&s.code;xf86Priv.h&e.code; and &s.code;xf86Privstr.h&e.code; are NOT -intended to be visible to video drivers, and it is an error for a driver -to include those files. - - -<sect1>Accessing global data -<p> - -Some other global state information that the drivers may access via -functions is as follows: - - <quote><p> - &s.code;Bool xf86ServerIsExiting()&e.code; - <quote><p> - Returns &s.code;TRUE&e.code; if the server is at the end of a - generation and is in the process of exiting, and - &s.code;FALSE&e.code; otherwise. - - </quote> - - &s.code;Bool xf86ServerIsResetting()&e.code; - <quote><p> - Returns &s.code;TRUE&e.code; if the server is at the end of a - generation and is in the process of resetting, and - &s.code;FALSE&e.code; otherwise. - - </quote> - - &s.code;Bool xf86ServerIsInitialising()&e.code; - <quote><p> - Returns &s.code;TRUE&e.code; if the server is at the beginning of - a generation and is in the process of initialising, and - &s.code;FALSE&e.code; otherwise. - - </quote> - - &s.code;Bool xf86ServerIsOnlyProbing()&e.code; - <quote><p> - Returns &s.code;TRUE&e.code; if the -probeonly command line flag - was specified, and &s.code;FALSE&e.code; otherwise. - - </quote> - - &s.code;Bool xf86CaughtSignal()&e.code; - <quote><p> - Returns &s.code;TRUE&e.code; if the server has caught a signal, - and &s.code;FALSE&e.code; otherwise. - - </quote> - </quote> - -<sect1>Allocating private data -<p> - -A driver and any module it uses may allocate per-screen private storage -in either the &s.code;ScreenRec&e.code; (DIX level) or -&s.code;ScrnInfoRec&e.code; (XFree86 common layer level). -&s.code;ScreenRec&e.code; storage persists only for a single server -generation, and &s.code;ScrnInfoRec&e.code; storage persists across -generations for the lifetime of the server. - -The &s.code;ScreenRec&e.code; &s.code;devPrivates&e.code; data must be -reallocated/initialised at the start of each new generation. This is -normally done from the &s.code;ChipScreenInit()&e.code; function, and -Init functions for other modules that it calls. Data allocated in this -way should be freed by the driver's &s.code;ChipCloseScreen()&e.code; -functions, and Close functions for other modules that it calls. A new -&s.code;devPrivates&e.code; entry is allocated by calling the -&s.code;AllocateScreenPrivateIndex()&e.code; function. - - <quote><p> - &s.code;int AllocateScreenPrivateIndex()&e.code; - <quote><p> - This function allocates a new element in the - &s.code;devPrivates&e.code; field of all currently existing - &s.code;ScreenRecs&e.code;. The return value is the index of this - new element in the &s.code;devPrivates&e.code; array. The - &s.code;devPrivates&e.code; field is of type - &s.code;DevUnion&e.code;: - - <verb> - typedef union _DevUnion { - pointer ptr; - long val; - unsigned long uval; - pointer (*fptr)(void); - } DevUnion; - </verb> - - which allows the element to be used for any of the above types. - It is commonly used as a pointer to data that the caller allocates - after the new index has been allocated. - - This function will return &s.code;-1&e.code; when there is an - error allocating the new index. - - </quote> - </quote> - -The &s.code;ScrnInfoRec&e.code; &s.code;privates&e.code; data persists -for the life of the server, so only needs to be allocated once. This -should be done from the &s.code;ChipPreInit()&e.code; function, and Init -functions for other modules that it calls. Data allocated in this way -should be freed by the driver's &s.code;ChipFreeScreen()&e.code; functions, -and Free functions for other modules that it calls. A new -&s.code;privates&e.code; entry is allocated by calling the -&s.code;xf86AllocateScrnInfoPrivateIndex()&e.code; function. - - - <quote><p> - &s.code;int xf86AllocateScrnInfoPrivateIndex()&e.code; - <quote><p> - This function allocates a new element in the &s.code;privates&e.code; - field of all currently existing &s.code;ScrnInfoRecs&e.code;. - The return value is the index of this new element in the - &s.code;privates&e.code; array. The &s.code;privates&e.code; - field is of type &s.code;DevUnion&e.code;: - - <verb> - typedef union _DevUnion { - pointer ptr; - long val; - unsigned long uval; - pointer (*fptr)(void); - } DevUnion; - </verb> - - which allows the element to be used for any of the above types. - It is commonly used as a pointer to data that the caller allocates - after the new index has been allocated. - - This function will not return when there is an error allocating - the new index. When there is an error it will cause the server - to exit with a fatal error. The similar function for allocation - privates in the &s.code;ScreenRec&e.code; - (&s.code;AllocateScreenPrivateIndex()&e.code;) differs in this - respect by returning &s.code;-1&e.code; when the allocation fails. - - </quote> - </quote> - -<sect>Keeping Track of Bus Resources<label id="rac"> -<p> - -<sect1>Theory of Operation -<p> - -The XFree86 common layer has knowledge of generic access control mechanisms -for devices on certain bus systems (currently the PCI bus) as well as -of methods to enable or disable access to the buses itself. Furthermore -it can access information on resources decoded by these devices and if -necessary modify it. - -When first starting the Xserver collects all this information, saves it -for restoration, checks it for consistency, and if necessary, corrects -it. Finally it disables all resources on a generic level prior to -calling any driver function. - -When the &s.code;Probe()&e.code; function of each driver is called the -device sections are matched against the devices found in the system. -The driver may probe devices at this stage that cannot be identified by -using device independent methods. Access to all resources that can be -controlled in a device independent way is disabled. The -&s.code;Probe()&e.code; function should register all non-relocatable -resources at this stage. If a resource conflict is found between -exclusive resources the driver will fail immediately. Optionally the -driver might specify an &s.code;EntityInit()&e.code;, -&s.code;EntityLeave()&e.code; and &s.code;EntityEnter()&e.code; function. - -&s.code;EntityInit()&e.code; can be used to disable any shared resources -that are not controlled by the generic access control functions. It is -called prior to the PreInit phase regardless if an entity is active or -not. When calling the &s.code;EntityInit()&e.code;, -&s.code;EntityEnter()&e.code; and &s.code;EntityLeave()&e.code; functions -the common level will disable access to all other entities on a generic -level. Since the common level has no knowledge of device specific -methods to disable access to resources it cannot be guaranteed that -certain resources are not decoded by any other entity until the -&s.code;EntityInit()&e.code; or &s.code;EntityEnter()&e.code; phase is -finished. Device drivers should therefore register all those resources -which they are going to disable. If these resources are never to be -used by any driver function they may be flagged &s.code;ResInit&e.code; -so that they can be removed from the resource list after processing all -&s.code;EntityInit()&e.code; functions. &s.code;EntityEnter()&e.code; -should disable decoding of all resources which are not registered as -exclusive and which are not handled by the generic access control in -the common level. The difference to &s.code;EntityInit()&e.code; is -that the latter one is only called once during lifetime of the server. -It can therefore be used to set up variables prior to disabling resources. -&s.code;EntityLeave()&e.code; should restore the original state when -exiting the server or switching to a different VT. It also needs to -disable device specific access functions if they need to be disabled on -server exit or VT switch. The default state is to enable them before -giving up the VT. - -In &s.code;PreInit()&e.code; phase each driver should check if any -sharable resources it has registered during &s.code;Probe()&e.code; has -been denied and take appropriate action which could simply be to fail. -If it needs to access resources it has disabled during -&s.code;EntitySetup()&e.code; it can do so provided it has registered -these and will disable them before returning from -&s.code;PreInit()&e.code;. This also applies to all other driver -functions. Several functions are provided to request resource ranges, -register these, correct PCI config space and add replacements for the -generic access functions. Resources may be marked ``disabled'' or -``unused'' during OPERATING stage. Although these steps could also be -performed in &s.code;ScreenInit()&e.code;, this is not desirable. - -Following &s.code;PreInit()&e.code; phase the common level determines -if resource access control is needed. This is the case if more than -one screen is used. If necessary the RAC wrapper module is loaded. In -&s.code;ScreenInit()&e.code; the drivers can decide which operations -need to be placed under RAC. Available are the frame buffer operations, -the pointer operations and the colormap operations. Any operation that -requires resources which might be disabled during OPERATING state should -be set to use RAC. This can be specified separately for memory and IO -resources. - -When &s.code;ScreenInit()&e.code; phase is done the common level will -determine which shared resources are requested by more than one driver -and set the access functions accordingly. This is done following these -rules: - -<enum> -<item>The sharable resources registered by each entity are compared. If - a resource is registered by more than one entity the entity will be - marked to need to share this resources type (&s.code;IO&e.code; or - &s.code;MEM&e.code;). - -<item>A resource marked ``disabled'' during OPERATING state will be ignored - entirely. - -<item>A resource marked ``unused'' will only conflicts with an overlapping - resource of an other entity if the second is actually in use during - OPERATING state. - -<item>If an ``unused'' resource was found to conflict however the entity - does not use any other resource of this type the entire resource type - will be disabled for that entity. -</enum> - -The driver has the choice among different ways to control access to -certain resources: - -<enum> -<item>It can rely on the generic access functions. This is probably the - most common case. Here the driver only needs to register any resource - it is going to use. - -<item>It can replace the generic access functions by driver specific - ones. This will mostly be used in cases where no generic access - functions are available. In this case the driver has to make sure - these resources are disabled when entering the &s.code;PreInit()&e.code; - stage. Since the replacement functions are registered in - &s.code;PreInit()&e.code; the driver will have to enable these - resources itself if it needs to access them during this state. The - driver can specify if the replacement functions can control memory - and/or I/O resources separately. - -<item>The driver can enable resources itself when it needs them. Each - driver function enabling them needs to disable them before it will - return. This should be used if a resource which can be controlled - in a device dependent way is only required during SETUP state. This - way it can be marked ``unused'' during OPERATING state. -</enum> - -A resource which is decoded during OPERATING state however never accessed -by the driver should be marked unused. - -Since access switching latencies are an issue during Xserver operation, -the common level attempts to minimize the number of entities that need -to be placed under RAC control. When a wrapped operation is called, -the &s.code;EnableAccess()&e.code; function is called before control is -passed on. &s.code;EnableAccess()&e.code; checks if a screen is under -access control. If not it just establishes bus routing and returns. -If the screen needs to be under access control, -&s.code;EnableAccess()&e.code; determines which resource types -(&s.code;MEM&e.code;, &s.code;IO&e.code;) are required. Then it tests -if this access is already established. If so it simply returns. If -not it disables the currently established access, fixes bus routing and -enables access to all entities registered for this screen. - -Whenever a mode switch or a VT-switch is performed the common level will -return to SETUP state. - -<sect1>Resource Types -<p> - -Resource have certain properties. When registering resources each range -is accompanied by a flag consisting of the ORed flags of the different -properties the resource has. Each resource range may be classified -according to - -<itemize> - <item>its physical properties i.e., if it addresses - memory (&s.code;ResMem&e.code;) or - I/O space (&s.code;ResIo&e.code;), - <item>if it addresses a - block (&s.code;ResBlock&e.code;) or - sparse (&s.code;ResSparse&e.code;) - range, - <item>its access properties. -</itemize> - -There are two known access properties: - -<itemize> - <item>&s.code;ResExclusive&e.code; - for resources which may not be shared with any other device and - <item>&s.code;ResShared&e.code; - for resources which can be disabled and therefore can be shared. -</itemize> - -If it is necessary to test a resource against any type a generic access -type &s.code;ResAny&e.code; is provided. If this is set the resource -will conflict with any resource of a different entity intersecting its -range. Further it can be specified that a resource is decoded however -never used during any stage (&s.code;ResUnused&e.code;) or during -OPERATING state (&s.code;ResUnusedOpr&e.code;). A resource only visible -during the init functions (ie. &s.code;EntityInit()&e.code;, -&s.code;EntityEnter()&e.code; and &s.code;EntityLeave()&e.code; should -be registered with the flag &s.code;ResInit&e.code;. A resource that -might conflict with background resource ranges may be flagged with -&s.code;ResBios&e.code;. This might be useful when registering resources -ranges that were assigned by the system Bios. - -Several predefined resource lists are available for VGA and 8514/A -resources in &s.code;common/xf86Resources.h&e.code;. - -<sect1>Available Functions<label id="avail"> -<p> - -The functions provided for resource management are listed in their order -of use in the driver. - - -<sect2>Probe Phase -<p> - -In this phase each driver detects those resources it is able to drive, -creates an entity record for each of them, registers non-relocatable -resources and allocates screens and adds the resources to screens. - -Two helper functions are provided for matching device sections in the -xorg.conf file to the devices: - - <quote><p> - &s.code;int xf86MatchPciInstances(const char *driverName, int vendorID, - &f.indent;SymTabPtr chipsets, PciChipsets *PCIchipsets, - &f.indent;GDevPtr *devList, int numDevs, DriverPtr drvp, - &f.indent;int **foundEntities)&e.code; - <quote><p> - This function finds matches between PCI cards that a driver supports - and config file device sections. It is intended for use in the - &s.code;ChipProbe()&e.code; function of drivers for PCI cards. - Only probed PCI devices with a vendor ID matching - &s.code;vendorID&e.code; are considered. &s.code;devList&e.code; - and &s.code;numDevs&e.code; are typically those found from - calling &s.code;xf86MatchDevice()&e.code;, and represent the active - config file device sections relevant to the driver. - &s.code;PCIchipsets&e.code; is a table that provides a mapping - between the PCI device IDs, the driver's internal chipset tokens - and a list of fixed resources. - - When a device section doesn't have a &s.key;BusID&e.key; entry it - can only match the primary video device. Secondary devices are - only matched with device sections that have a matching - &s.key;BusID&e.key; entry. - - Once the preliminary matches have been found, a final match is - confirmed by checking if the chipset override, ChipID override or - probed PCI chipset type match one of those given in the - &s.code;chipsets&e.code; and &s.code;PCIchipsets&e.code; lists. - The &s.code;PCIchipsets&e.code; list includes a list of the PCI - device IDs supported by the driver. The list should be terminated - with an entry with PCI ID &s.code;-1&e.code;". The - &s.code;chipsets&e.code; list is a table mapping the driver's - internal chipset tokens to names, and should be terminated with - a &s.code;NULL&e.code; entry. Only those entries with a - corresponding entry in the &s.code;PCIchipsets&e.code; list are - considered. The order of precedence is: config file chipset, - config file ChipID, probed PCI device ID. - - In cases where a driver handles PCI chipsets with more than one - vendor ID, it may set &s.code;vendorID&e.code; to - &s.code;0&e.code;, and OR each devID in the list with (the - vendor ID << 16). - - Entity index numbers for confirmed matches are returned as an - array via &s.code;foundEntities&e.code;. The PCI information, - chipset token and device section for each match are found in the - &s.code;EntityInfoRec&e.code; referenced by the indices. - - The function return value is the number of confirmed matches. A - return value of &s.code;-1&e.code; indicates an internal error. - The returned &s.code;foundEntities&e.code; array should be freed - by the driver with &s.code;xfree()&e.code; when it is no longer - needed in cases where the return value is greater than zero. - - </quote> - - &s.code;int xf86MatchIsaInstances(const char *driverName, - &f.indent;SymTabPtr chipsets, IsaChipsets *ISAchipsets, - &f.indent;DriverPtr drvp, FindIsaDevProc FindIsaDevice, - &f.indent;GDevPtr *devList, int numDevs, - int **foundEntities)&e.code; - <quote><p> - This function finds matches between ISA cards that a driver supports - and config file device sections. It is intended for use in the - &s.code;ChipProbe()&e.code; function of drivers for ISA cards. - &s.code;devList&e.code; and &s.code;numDevs&e.code; are - typically those found from calling &s.code;xf86MatchDevice()&e.code;, - and represent the active config file device sections relevant to - the driver. &s.code;ISAchipsets&e.code; is a table that provides - a mapping between the driver's internal chipset tokens and the - resource classes. &s.code;FindIsaDevice&e.code; is a - driver-provided function that probes the hardware and returns the - chipset token corresponding to what was detected, and - &s.code;-1&e.code; if nothing was detected. - - If the config file device section contains a chipset entry, then - it is checked against the &s.code;chipsets&e.code; list. When - no chipset entry is present, the &s.code;FindIsaDevice&e.code; - function is called instead. - - Entity index numbers for confirmed matches are returned as an - array via &s.code;foundEntities&e.code;. The chipset token and - device section for each match are found in the - &s.code;EntityInfoRec&e.code; referenced by the indices. - - The function return value is the number of confirmed matches. A - return value of &s.code;-1&e.code; indicates an internal error. - The returned &s.code;foundEntities&e.code; array should be freed - by the driver with &s.code;xfree()&e.code; when it is no longer - needed in cases where the return value is greater than zero. - - </quote> - </quote> - -These two helper functions make use of several core functions that are -available at the driver level: - - <quote><p> - &s.code;Bool xf86ParsePciBusString(const char *busID, int *bus, - &f.indent;int *device, int *func)&e.code; - <quote><p> - Takes a &s.code;BusID&e.code; string, and if it is in the correct - format, returns the PCI &s.code;bus&e.code;, &s.code;device&e.code;, - &s.code;func&e.code; values that it indicates. The format of the - string is expected to be "PCI:bus:device:func" where each of `bus', - `device' and `func' are decimal integers. The ":func" part may - be omitted, and the func value assumed to be zero, but this isn't - encouraged. The "PCI" prefix may also be omitted. The prefix - "AGP" is currently equivalent to the "PCI" prefix. If the string - isn't a valid PCI BusID, the return value is &s.code;FALSE&e.code;. - - </quote> - - - &s.code;Bool xf86ComparePciBusString(const char *busID, int bus, - &f.indent;int device, int func)&e.code; - <quote><p> - Compares a &s.code;BusID&e.code; string with PCI &s.code;bus&e.code;, - &s.code;device&e.code;, &s.code;func&e.code; values. If they - match &s.code;TRUE&e.code; is returned, and &s.code;FALSE&e.code; - if they don't. - - </quote> - - &s.code;Bool xf86ParseIsaBusString(const char *busID)&e.code; - <quote><p> - Compares a &s.code;BusID&e.code; string with the ISA bus ID string - ("ISA" or "ISA:"). If they match &s.code;TRUE&e.code; is returned, - and &s.code;FALSE&e.code; if they don't. - - </quote> - - &s.code;Bool xf86CheckPciSlot(int bus, int device, int func)&e.code; - <quote><p> - Checks if the PCI slot &s.code;bus:device:func&e.code; has been - claimed. If so, it returns &s.code;FALSE&e.code;, and otherwise - &s.code;TRUE&e.code;. - - </quote> - - &s.code;int xf86ClaimPciSlot(int bus, int device, int func, DriverPtr drvp, - &f.indent;int chipset, GDevPtr dev, Bool active)&e.code; - <quote><p> - This function is used to claim a PCI slot, allocate the associated - entity record and initialise their data structures. The return - value is the index of the newly allocated entity record, or - &s.code;-1&e.code; if the claim fails. This function should always - succeed if &s.code;xf86CheckPciSlot()&e.code; returned - &s.code;TRUE&e.code; for the same PCI slot. - - </quote> - - &s.code;Bool xf86IsPrimaryPci(void)&e.code; - <quote><p> - This function returns &s.code;TRUE&e.code; if the primary card is - a PCI device, and &s.code;FALSE&e.code; otherwise. - - </quote> - - &s.code;int xf86ClaimIsaSlot(DriverPtr drvp, int chipset, - &f.indent;GDevPtr dev, Bool active)&e.code; - <quote><p> - This allocates an entity record entity and initialise the data - structures. The return value is the index of the newly allocated - entity record. - - </quote> - - &s.code;Bool xf86IsPrimaryIsa(void)&e.code; - <quote><p> - This function returns &s.code;TRUE&e.code; if the primary card is - an ISA (non-PCI) device, and &s.code;FALSE&e.code; otherwise. - - </quote> - </quote> - -Two helper functions are provided to aid configuring entities: - <quote><p> - &s.code;ScrnInfoPtr xf86ConfigPciEntity(ScrnInfoPtr pScrn, - &f.indent;int scrnFlag, int entityIndex, - &f.indent;PciChipsets *p_chip, - &f.indent;resList res, EntityProc init, - &f.indent;EntityProc enter, EntityProc leave, - &f.indent;pointer private)&e.code; - <p> - &s.code;ScrnInfoPtr xf86ConfigIsaEntity(ScrnInfoPtr pScrn, - &f.indent;int scrnFlag, int entityIndex, - &f.indent;IsaChipsets *i_chip, - &f.indent;resList res, EntityProc init, - &f.indent;EntityProc enter, EntityProc leave, - &f.indent;pointer private)&e.code; - <quote><p> - These functions are used to register the non-relocatable resources - for an entity, and the optional entity-specific &s.code;Init&e.code;, &s.code;Enter&e.code; and - &s.code;Leave&e.code; functions. Usually the list of fixed resources is obtained - from the Isa/PciChipsets lists. However an additional list of - resources may be passed. Generally this is not required. - For active entities a &s.code;ScrnInfoRec&e.code; is allocated - if the &s.code;pScrn&e.code; argument is &s.code;NULL&e.code;. -The - return value is &s.code;TRUE&e.code; when successful. The init, enter, leave - functions are defined as follows: - - <quote> - &s.code;typedef void (*EntityProc)(int entityIndex, - &f.indent;pointer private)&e.code; - </quote> - - They are passed the entity index and a pointer to a private scratch - area. This can be set up during &s.code;Probe()&e.code; and - its address can be passed to - &s.code;xf86ConfigIsaEntity()&e.code; and - &s.code;xf86ConfigPciEntity()&e.code; as the last argument. - - </quote> - </quote> - -These two helper functions make use of several core functions that are -available at the driver level: - <quote><p> - &s.code;void xf86ClaimFixedResources(resList list, int entityIndex)&e.code; - <quote><p> - This function registers the non-relocatable resources which cannot - be disabled and which therefore would cause the server to fail - immediately if they were found to conflict. It also records - non-relocatable but sharable resources for processing after the - &s.code;Probe()&e.code; phase. - - </quote> - - &s.code;Bool xf86SetEntityFuncs(int entityIndex, EntityProc init, - &f.indent;EntityProc enter, EntityProc leave, pointer)&e.code; - <quote><p> - This function registers with an entity the &s.code;init&e.code;, - &s.code;enter&e.code;, &s.code;leave&e.code; functions along - with the pointer to their private area. - - </quote> - - &s.code;void xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex)&e.code; - <quote><p> - This function associates the entity referenced by - &s.code;entityIndex&e.code; with the screen. - - </quote> - </quote> - -<sect2>PreInit Phase -<p> - -During this phase the remaining resources should be registered. -&s.code;PreInit()&e.code; should call &s.code;xf86GetEntityInfo()&e.code; -to obtain a pointer to an &s.code;EntityInfoRec&e.code; for each entity -it is able to drive and check if any resource are listed in its -&s.code;resources&e.code; field. If resources registered in the Probe -phase have been rejected in the post-Probe phase -(&s.code;resources&e.code; is non-&s.code;NULL&e.code;), then the driver should -decide if it can continue without using these or if it should fail. - - <quote><p> - &s.code;EntityInfoPtr xf86GetEntityInfo(int entityIndex)&e.code; - <quote><p> - This function returns a pointer to the &s.code;EntityInfoRec&e.code; - referenced by &s.code;entityIndex&e.code;. The returned - &s.code;EntityInfoRec&e.code; should be freed with - &s.code;xfree()&e.code; when no longer needed. - - </quote> - </quote> -Several functions are provided to simplify resource registration: - <quote><p> - &s.code;Bool xf86IsEntityPrimary(int entityIndex)&e.code; - <quote><p> - This function returns &s.code;TRUE&e.code; if the entity referenced - by &s.code;entityIndex&e.code; is the primary display device (i.e., - the one initialised at boot time and used in text mode). - - </quote> - - &s.code;Bool xf86IsScreenPrimary(int scrnIndex)&e.code; - <quote><p> - This function returns &s.code;TRUE&e.code; if the primary entity - is registered with the screen referenced by - &s.code;scrnIndex&e.code;. - - </quote> - - &s.code;pciVideoPtr xf86GetPciInfoForEntity(int entityIndex)&e.code; - <quote><p> - This function returns a pointer to the &s.code;pciVideoRec&e.code; - for the specified entity. If the entity is not a PCI device, - &s.code;NULL&e.code; is returned. - - </quote> - </quote> - -The primary function for registration of resources is: - <quote><p> - &s.code;resPtr xf86RegisterResources(int entityIndex, resList list, - &f.indent;int access)&e.code; - <quote><p> - This function tries to register the resources in - &s.code;list&e.code;. If list is &s.code;NULL&e.code; it tries - to determine the resources automatically. This only works for - entities that provide a generic way to read out the resource ranges - they decode. So far this is only the case for PCI devices. By - default the PCI resources are registered as shared - (&s.code;ResShared&e.code;) if the driver wants to set a different - access type it can do so by specifying the access flags in the - third argument. A value of &s.code;0&e.code; means to use the - default settings. If for any reason the resource broker is not - able to register some of the requested resources the function will - return a pointer to a list of the failed ones. In this case the - driver may be able to move the resource to different locations. - In case of PCI bus entities this is done by passing the list of - failed resources to &s.code;xf86ReallocatePciResources()&e.code;. - When the registration succeeds, the return value is - &s.code;NULL&e.code;. - - </quote> - - &s.code;resPtr xf86ReallocatePciResources(int entityIndex, resPtr pRes)&e.code; - <quote><p> - This function takes a list of PCI resources that need to be - reallocated and returns &s.code;NULL&e.code when all relocations are - successful. - &s.code;xf86RegisterResources()&e.code; should be called again to - register the relocated resources with the broker. - If the reallocation fails, a list of the resources that could not be - relocated is returned. - - </quote> - </quote> - -Two functions are provided to obtain a resource range of a given type: - <quote><p> - &s.code;resRange xf86GetBlock(long type, memType size, - &f.indent;memType window_start, memType window_end, - &f.indent;memType align_mask, resPtr avoid)&e.code; - <quote><p> - This function tries to find a block range of size - &s.code;size&e.code; and type &s.code;type&e.code; in a window - bound by &s.code;window_start&e.code; and &s.code;window_end&e.code; - with the alignment specified in &s.code;align_mask&e.code;. - Optionally a list of resource ranges which should be avoided within - the window can be supplied. On failure a zero-length range of - type &s.code;ResEnd&e.code; will be returned. - - </quote> - &s.code;resRange xf86GetSparse(long type, memType fixed_bits, - &f.indent;memType decode_mask, memType address_mask, - &f.indent;resPtr avoid)&e.code; - <quote><p> - This function is like the previous one, but attempts to find a - sparse range instead of a block range. Here three values have to - be specified: the &s.code;address_mask&e.code; which marks all - bits of the mask part of the address, the &s.code;decode_mask&e.code; - which masks out the bits which are hardcoded and are therefore - not available for relocation and the values of the fixed bits. - The function tries to find a base that satisfies the given condition. - If the function fails it will return a zero range of type - &s.code;ResEnd&e.code;. Optionally it might be passed a list of - resource ranges to avoid. - - </quote> - </quote> - -Some PCI devices are broken in the sense that they return invalid size -information for a certain resource. In this case the driver can supply -the correct size and make sure that the resource range allocated for -the card is large enough to hold the address range decoded by the card. -The function &s.code;xf86FixPciResource()&e.code; can be used to do this: - <quote><p> - &s.code;Bool xf86FixPciResource(int entityIndex, unsigned int prt, - &f.indent;CARD32 alignment, long type)&e.code; - <quote><p> - This function fixes a PCI resource allocation. The - &s.code;prt&e.code; parameter contains the number of the PCI base - register that needs to be fixed (&s.code;0-5&e.code;, and - &s.code;6&e.code; for the BIOS base register). The size is - specified by the alignment. Since PCI resources need to span an - integral range of size &s.code;2^n&e.code;, the alignment also - specifies the number of addresses that will be decoded. If the - driver specifies a type mask it can override the default type for - PCI resources which is &s.code;ResShared&e.code;. The resource - broker needs to know that to find a matching resource range. This - function should be called before calling - &s.code;xf86RegisterResources()&e.code;. The return value is - &s.code;TRUE&e.code; when the function succeeds. - - </quote> - - &s.code;Bool xf86CheckPciMemBase(pciVideoPtr pPci, memType base)&e.code; - <quote><p> - This function checks that the memory base address specified matches - one of the PCI base address register values for the given PCI - device. This is mostly used to check that an externally provided - base address (e.g., from a config file) matches an actual value - allocated to a device. - - </quote> - </quote> - -The driver may replace the generic access control functions for an entity. -This is done with the &s.code;xf86SetAccessFuncs()&e.code;: - <quote><p> - &s.code;void xf86SetAccessFuncs(EntityInfoPtr pEnt, - &f.indent;xf86SetAccessFuncPtr funcs, - &f.indent;xf86SetAccessFuncPtr oldFuncs)&e.code; - <quote><p> - with: - </quote> - - <verb> - typedef struct { - xf86AccessPtr mem; - xf86AccessPtr io; - xf86AccessPtr io_mem; - } xf86SetAccessFuncRec, *xf86SetAccessFuncPtr; - </verb> - - <quote><p> - The driver can pass three functions: one for I/O access, one for - memory access and one for combined memory and I/O access. If the - memory access and combined access functions are identical the - common level assumes that the memory access cannot be controlled - independently of I/O access, if the I/O access function and the - combined access functions are the same it is assumed that I/O can - not be controlled independently. If memory and I/O have to be - controlled together all three values should be the same. If a - non &s.code;NULL&e.code; value is passed as third argument it is - interpreted as an address where to store the old access record. - If the third argument is &s.code;NULL&e.code; it will be assumed - that the generic access should be enabled before replacing the - access functions. Otherwise it will be disabled. The driver may - enable them itself using the returned values. It should do this - from its replacement access functions as the generic access may - be disabled by the common level on certain occasions. If replacement - functions are specified they must control all resources of the - specific type registered for the entity. - - </quote> - </quote> - -To find out if a specific resource range conflicts with another -resource the &s.code;xf86ChkConflict()&e.code; function may be used: - <quote><p> - &s.code;memType xf86ChkConflict(resRange *rgp, int entityIndex)&e.code; - <quote><p> - This function checks if the resource range &s.code;rgp&e.code; of - for the specified entity conflicts with with another resource. - If a conflict is found, the address of the start of the conflict - is returned. The return value is zero when there is no conflict. - - </quote> - </quote> - -The OPERATING state properties of previously registered fixed resources -can be set with the &s.code;xf86SetOperatingState()&e.code; function: - <quote><p> - &s.code;resPtr xf86SetOperatingState(resList list, int entityIndex, - &f.indent;int mask)&e.code; - <quote><p> - This function is used to set the status of a resource during - OPERATING state. &s.code;list&e.code; holds a list to which - &s.code;mask&e.code; is to be applied. The parameter - &s.code;mask&e.code; may have the value &s.code;ResUnusedOpr&e.code; - and &s.code;ResDisableOpr&e.code;. The first one should be used - if a resource isn't used by the driver during OPERATING state - although it is decoded by the device, while the latter one indicates - that the resource is not decoded during OPERATING state. Note - that the resource ranges have to match those specified during - registration. If a range has been specified starting at - &s.code;A&e.code; and ending at &s.code;B&e.code; and suppose - &s.code;C&e.code; us a value satisfying - &s.code;A < C < B&e.code; one may not - specify the resource range &s.code;(A,B)&e.code; by splitting it - into two ranges &s.code;(A,C)&e.code; and &s.code;(C,B)&e.code;. - - </quote> - </quote> - -The following two functions are provided for special cases: - <quote><p> - &s.code;void xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn, int entityIndex)&e.code; - <quote><p> - This function may be used to remove an entity from a screen. This - only makes sense if a screen has more than one entity assigned or - the screen is to be deleted. No test is made if the screen has - any entities left. - - </quote> - - &s.code;void xf86DeallocateResourcesForEntity(int entityIndex, long type)&e.code; - <quote><p> - This function deallocates all resources of a given type registered - for a certain entity from the resource broker list. - - </quote> - </quote> - -<sect2>ScreenInit Phase -<p> - -All that is required in this phase is to setup the RAC flags. Note that -it is also permissible to set these flags up in the PreInit phase. The -RAC flags are held in the &s.code;racIoFlags&e.code; and &s.code;racMemFlags&e.code; fields of the -&s.code;ScrnInfoRec&e.code; for each screen. They specify which graphics operations -might require the use of shared resources. This can be specified -separately for memory and I/O resources. The available flags are defined -in &s.code;rac/xf86RAC.h&e.code;. They are: - - &s.code;RAC_FB&e.code; - <quote> - for framebuffer operations (including hw acceleration) - </quote> - &s.code;RAC_CURSOR&e.code; - <quote> - for Cursor operations - (??? I'm not sure if we need this for SW cursor it depends - on which level the sw cursor is drawn) - </quote> - &s.code;RAC_COLORMAP&e.code; - <quote> - for colormap operations - </quote> - &s.code;RAC_VIEWPORT&e.code; - <quote> - for the call to &s.code;ChipAdjustFrame()&e.code; </quote> - - -The flags are ORed together. - -<sect>Config file ``Option'' entries<label id="options"> -<p> - -Option entries are permitted in most sections and subsections of the -config file. There are two forms of option entries: - -<descrip> -<tag>Option "option-name"</tag> - A boolean option. -<tag>Option "option-name" "option-value"</tag> - An option with an arbitrary value. -</descrip> - -The option entries are handled by the parser, and a list of the parsed -options is included with each of the appropriate data structures that -the drivers have access to. The data structures used to hold the option -information are opaque to the driver, and a driver must not access the -option data directly. Instead, the common layer provides a set of -functions that may be used to access, check and manipulate the option -data. - -First, the low level option handling functions. In most cases drivers -would not need to use these directly. - - <quote><p> - &s.code;pointer xf86FindOption(pointer options, const char *name)&e.code; - <quote><p> - Takes a list of options and an option name, and returns a handle - for the first option entry in the list matching the name. Returns - &s.code;NULL&e.code; if no match is found. - - </quote> - - &s.code;char *xf86FindOptionValue(pointer options, const char *name)&e.code; - <quote><p> - Takes a list of options and an option name, and returns the value - associated with the first option entry in the list matching the - name. If the matching option has no value, an empty string - (&s.code;""&e.code;) is returned. Returns &s.code;NULL&e.code; - if no match is found. - - </quote> - - &s.code;void xf86MarkOptionUsed(pointer option)&e.code; - <quote><p> - Takes a handle for an option, and marks that option as used. - - </quote> - - &s.code;void xf86MarkOptionUsedByName(pointer options, const char *name)&e.code; - <quote><p> - Takes a list of options and an option name and marks the first - option entry in the list matching the name as used. - - </quote> - </quote> - - -Next, the higher level functions that most drivers would use. - <quote><p> - &s.code;void xf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts)&e.code; - <quote><p> - Collect the options from each of the config file sections used by - the screen (&s.code;pScrn&e.code;) and return the merged list as - &s.code;pScrn->options&e.code;. This function requires that - &s.code;pScrn->confScreen&e.code;, &s.code;pScrn->display&e.code;, - &s.code;pScrn->monitor&e.code;, - &s.code;pScrn->numEntities&e.code;, and - &s.code;pScrn->entityList&e.code; are initialised. - &s.code;extraOpts&e.code; may optionally be set to an additional - list of options to be combined with the others. The order of - precedence for options is &s.code;extraOpts&e.code;, display, - confScreen, monitor, device. - - </quote> - - &s.code;void xf86ProcessOptions(int scrnIndex, pointer options, - &f.indent;OptionInfoPtr optinfo)&e.code; - <quote><p> - Processes a list of options according to the information in the - array of &s.code;OptionInfoRecs&e.code; (&s.code;optinfo&e.code;). - The resulting information is stored in the &s.code;value&e.code; - fields of the appropriate &s.code;optinfo&e.code; entries. The - &s.code;found&e.code; fields are set to &s.code;TRUE&e.code; - when an option with a value of the correct type if found, and - &s.code;FALSE&e.code; otherwise. The &s.code;type&e.code; field - is used to determine the expected value type for each option. - Each option in the list of options for which there is a name match - (but not necessarily a value type match) is marked as used. - Warning messages are printed when option values don't match the - types specified in the optinfo data. - - NOTE: If this function is called before a driver's screen number - is known (e.g., from the &s.code;ChipProbe()&e.code; function) a - &s.code;scrnIndex&e.code; value of &s.code;-1&e.code; should be - used. - - NOTE 2: Given that this function stores into the - &s.code;OptionInfoRecs&e.code; pointed to by &s.code;optinfo&e.code, - the caller should ensure the &s.code;OptionInfoRecs&e.code; are - (re-)initialised before the call, especially if the caller expects - to use the predefined option values as defaults. - - The &s.code;OptionInfoRec&e.code; is defined as follows: - - <verb> - typedef struct { - double freq; - int units; - } OptFrequency; - - typedef union { - unsigned long num; - char * str; - double realnum; - Bool bool; - OptFrequency freq; - } ValueUnion; - - typedef enum { - OPTV_NONE = 0, - OPTV_INTEGER, - OPTV_STRING, /* a non-empty string */ - OPTV_ANYSTR, /* Any string, including an empty one */ - OPTV_REAL, - OPTV_BOOLEAN, - OPTV_FREQ - } OptionValueType; - - typedef enum { - OPTUNITS_HZ = 1, - OPTUNITS_KHZ, - OPTUNITS_MHZ - } OptFreqUnits; - - typedef struct { - int token; - const char* name; - OptionValueType type; - ValueUnion value; - Bool found; - } OptionInfoRec, *OptionInfoPtr; - </verb> - - &s.code;OPTV_FREQ&e.code; can be used for options values that are - frequencies. These values are a floating point number with an - optional unit name appended. The unit name can be one of "Hz", - "kHz", "k", "MHz", "M". The multiplier associated with the unit - is stored in &s.code;freq.units&e.code;, and the scaled frequency - is stored in &s.code;freq.freq&e.code;. When no unit is specified, - &s.code;freq.units&e.code; is set to &s.code;0&e.code;, and - &s.code;freq.freq&e.code; is unscaled. - - Typical usage is to setup an array of - &s.code;OptionInfoRecs&e.code; with all fields initialised. - The &s.code;value&e.code; and &s.code;found&e.code; fields get - set by &s.code;xf86ProcessOptions()&e.code;. For cases where the - value parsing is more complex, the driver should specify - &s.code;OPTV_STRING&e.code;, and parse the string itself. An - example of using this option handling is included in the - <ref id="sample" name="Sample Driver"> section. - - </quote> - - &s.code;void xf86ShowUnusedOptions(int scrnIndex, pointer options)&e.code; - <quote><p> - Prints out warning messages for each option in the list of options - that isn't marked as used. This is intended to show options that - the driver hasn't recognised. It would normally be called near - the end of the &s.code;ChipScreenInit()&e.code; function, but only - when &s.code;serverGeneration == 1&e.code;. - - </quote> - - &s.code;OptionInfoPtr xf86TokenToOptinfo(const OptionInfoRec *table, - &f.indent;int token)&e.code; - - <quote><p> - Returns a pointer to the &s.code;OptionInfoRec&e.code; in - &s.code;table&e.code; with a token field matching - &s.code;token&e.code;. Returns &s.code;NULL&e.code; if no match - is found. - - </quote> - - &s.code;Bool xf86IsOptionSet(const OptionInfoRec *table, int token)&e.code; - <quote><p> - Returns the &s.code;found&e.code; field of the - &s.code;OptionInfoRec&e.code; in &s.code;table&e.code; with a - &s.code;token&e.code; field matching &s.code;token&e.code;. This - can be used for options of all types. Note that for options of - type &s.code;OPTV_BOOLEAN&e.code;, it isn't sufficient to check - this to determine the value of the option. Returns - &s.code;FALSE&e.code; if no match is found. - - </quote> - - &s.code;char *xf86GetOptValString(const OptionInfoRec *table, int token)&e.code; - <quote><p> - Returns the &s.code;value.str&e.code; field of the - &s.code;OptionInfoRec&e.code; in &s.code;table&e.code; with a - token field matching &s.code;token&e.code;. Returns - &s.code;NULL&e.code; if no match is found. - - </quote> - - &s.code;Bool xf86GetOptValInteger(const OptionInfoRec *table, int token, - &f.indent;int *value)&e.code; - <quote><p> - Returns via &s.code;*value&e.code; the &s.code;value.num&e.code; - field of the &s.code;OptionInfoRec&e.code; in &s.code;table&e.code; - with a &s.code;token&e.code; field matching &s.code;token&e.code;. - &s.code;*value&e.code; is only changed when a match is found so - it can be safely initialised with a default prior to calling this - function. The function return value is as for - &s.code;xf86IsOptionSet()&e.code;. - - </quote> - - &s.code;Bool xf86GetOptValULong(const OptionInfoRec *table, int token, - &f.indent;unsigned long *value)&e.code; - <quote><p> - Like &s.code;xf86GetOptValInteger()&e.code;, except the value is - treated as an &s.code;unsigned long&e.code;. - - </quote> - - &s.code;Bool xf86GetOptValReal(const OptionInfoRec *table, int token, - &f.indent;double *value)&e.code; - <quote><p> - Like &s.code;xf86GetOptValInteger()&e.code;, except that - &s.code;value.realnum&e.code; is used. - - </quote> - - &s.code;Bool xf86GetOptValFreq(const OptionInfoRec *table, int token, - &f.indent;OptFreqUnits expectedUnits, double *value)&e.code; - <quote><p> - Like &s.code;xf86GetOptValInteger()&e.code;, except that the - &s.code;value.freq&e.code; data is returned. The frequency value - is scaled to the units indicated by &s.code;expectedUnits&e.code;. - The scaling is exact when the units were specified explicitly in - the option's value. Otherwise, the &s.code;expectedUnits&e.code; - field is used as a hint when doing the scaling. In this case, - values larger than &s.code;1000&e.code; are assumed to have be - specified in the next smallest units. For example, if the Option - value is "10000" and expectedUnits is &s.code;OPTUNITS_MHZ&e.code;, - the value returned is &s.code;10&e.code;. - - </quote> - - &s.code;Bool xf86GetOptValBool(const OptionInfoRec *table, int token, Bool *value)&e.code; - <quote><p> - This function is used to check boolean options - (&s.code;OPTV_BOOLEAN&e.code;). If the function return value is - &s.code;FALSE&e.code;, it means the option wasn't set. Otherwise - &s.code;*value&e.code; is set to the boolean value indicated by - the option's value. No option &s.code;value&e.code; is interpreted - as &s.code;TRUE&e.code;. Option values meaning &s.code;TRUE&e.code; - are "1", "yes", "on", "true", and option values meaning - &s.code;FALSE&e.code; are "0", "no", "off", "false". Option names - both with the "no" prefix in their names, and with that prefix - removed are also checked and handled in the obvious way. - &s.code;*value&e.code; is not changed when the option isn't present. - It should normally be set to a default value before calling this - function. - - </quote> - - &s.code;Bool xf86ReturnOptValBool(const OptionInfoRec *table, int token, Bool def)&e.code; - <quote><p> - This function is used to check boolean options - (&s.code;OPTV_BOOLEAN&e.code;). If the option is set, its value - is returned. If the options is not set, the default value specified - by &s.code;def&e.code; is returned. The option interpretation is - the same as for &s.code;xf86GetOptValBool()&e.code;. - - </quote> - - &s.code;int xf86NameCmp(const char *s1, const char *s2)&e.code; - <quote><p> - This function should be used when comparing strings from the config - file with expected values. It works like &s.code;strcmp()&e.code;, - but is not case sensitive and space, tab, and `<tt>_</tt>' characters - are ignored in the comparison. The use of this function isn't - restricted to parsing option values. It may be used anywhere - where this functionality required. - - </quote> - </quote> - -<sect>Modules, Drivers, Include Files and Interface Issues -<p> - -NOTE: this section is incomplete. - - -<sect1>Include files -<p> - -The following include files are typically required by video drivers: - - <quote><p> - All drivers should include these: - <quote> - &s.code;"xf86.h"&nl; - "xf86_OSproc.h"&nl; - "xf86_ansic.h"&nl; - "xf86Resources.h"&e.code; - </quote> - Wherever inb/outb (and related things) are used the following should be - included: - <quote> - &s.code;"compiler.h"&e.code; - </quote> - Note: in drivers, this must be included after &s.code;"xf86_ansic.h"&e.code;. - - Drivers that need to access PCI vendor/device definitions need this: - <quote> - &s.code;"xf86PciInfo.h"&e.code; - </quote> - - Drivers that need to access the PCI config space need this: - <quote> - &s.code;"xf86Pci.h"&e.code; - </quote> - - Drivers that initialise a SW cursor need this: - <quote> - &s.code;"mipointer.h"&e.code; - </quote> - - All drivers implementing backing store need this: - <quote> - &s.code;"mibstore.h"&e.code; - </quote> - - All drivers using the mi colourmap code need this: - <quote> - &s.code;"micmap.h"&e.code; - </quote> - - If a driver uses the vgahw module, it needs this: - <quote> - &s.code;"vgaHW.h"&e.code; - </quote> - - Drivers supporting VGA or Hercules monochrome screens need: - <quote> - &s.code;"xf1bpp.h"&e.code; - </quote> - - Drivers supporting VGA or EGC 16-colour screens need: - <quote> - &s.code;"xf4bpp.h"&e.code; - </quote> - - Drivers using cfb need: - <quote> - &s.code;#define PSZ 8&nl; - #include "cfb.h"&nl; - #undef PSZ&e.code; - </quote> - - Drivers supporting bpp 16, 24 or 32 with cfb need one or more of: - <quote> - &s.code;"cfb16.h"&nl; - "cfb24.h"&nl; - "cfb32.h"&e.code; - </quote> - - If a driver uses XAA, it needs these: - <quote> - &s.code;"xaa.h"&nl; - "xaalocal.h"&e.code; - </quote> - - If a driver uses the fb manager, it needs this: - <quote> - &s.code;"xf86fbman.h"&e.code; - </quote> - </quote> - -Non-driver modules should include &s.code;"xf86_ansic.h"&e.code; to get the correct -wrapping of ANSI C/libc functions. - -All modules must NOT include any system include files, or the following: - - <quote> - &s.code;"xf86Priv.h"&nl; - "xf86Privstr.h"&nl; - "xf86_OSlib.h"&nl; - "Xos.h"&e.code; - </quote> - -In addition, "xf86_libc.h" must not be included explicitly. It is -included implicitly by "xf86_ansic.h". - - -<sect>Offscreen Memory Manager -<p> - -Management of offscreen video memory may be handled by the XFree86 -framebuffer manager. Once the offscreen memory manager is running, -drivers or extensions may allocate, free or resize areas of offscreen -video memory using the following functions (definitions taken from -&s.code;xf86fbman.h&e.code;): - -<code> - typedef struct _FBArea { - ScreenPtr pScreen; - BoxRec box; - int granularity; - void (*MoveAreaCallback)(struct _FBArea*, struct _FBArea*) - void (*RemoveAreaCallback)(struct _FBArea*) - DevUnion devPrivate; - } FBArea, *FBAreaPtr; - - typedef void (*MoveAreaCallbackProcPtr)(FBAreaPtr from, FBAreaPtr to) - typedef void (*RemoveAreaCallbackProcPtr)(FBAreaPtr) - - FBAreaPtr xf86AllocateOffscreenArea ( - ScreenPtr pScreen, - int width, int height, - int granularity, - MoveAreaCallbackProcPtr MoveAreaCallback, - RemoveAreaCallbackProcPtr RemoveAreaCallback, - pointer privData - ) - - void xf86FreeOffscreenArea (FBAreaPtr area) - - Bool xf86ResizeOffscreenArea ( - FBAreaPtr area - int w, int h - ) -</code> - -The function: -<quote> - &s.code;Bool xf86FBManagerRunning(ScreenPtr pScreen)&e.code; -</quote> - -can be used by an extension to check if the driver has initialized -the memory manager. The manager is not available if this returns -&s.code;FALSE&e.code; and the functions above will all fail. - - -&s.code;xf86AllocateOffscreenArea()&e.code; can be used to request a -rectangle of dimensions &s.code;width&e.code; x &s.code;height&e.code; -(in pixels) from unused offscreen memory. &s.code;granularity&e.code; -specifies that the leftmost edge of the rectangle must lie on some -multiple of &s.code;granularity&e.code; pixels. A granularity of zero -means the same thing as a granularity of one - no alignment preference. -A &s.code;MoveAreaCallback&e.code; can be provided to notify the requester -when the offscreen area is moved. If no &s.code;MoveAreaCallback&e.code; -is supplied then the area is considered to be immovable. The -&s.code;privData&e.code; field will be stored in the manager's internal -structure for that allocated area and will be returned to the requester -in the &s.code;FBArea&e.code; passed via the -&s.code;MoveAreaCallback&e.code;. An optional -&s.code;RemoveAreaCallback&e.code; is provided. If the driver provides -this it indicates that the area should be allocated with a lower priority. -Such an area may be removed when a higher priority request (one that -doesn't have a &s.code;RemoveAreaCallback&e.code;) is made. When this -function is called, the driver will have an opportunity to do whatever -cleanup it needs to do to deal with the loss of the area, but it must -finish its cleanup before the function exits since the offscreen memory -manager will free the area immediately after. - -&s.code;xf86AllocateOffscreenArea()&e.code; returns &s.code;NULL&e.code; -if it was unable to allocate the requested area. When no longer needed, -areas should be freed with &s.code;xf86FreeOffscreenArea()&e.code;. - -&s.code;xf86ResizeOffscreenArea()&e.code; resizes an existing -&s.code;FBArea&e.code;. &s.code;xf86ResizeOffscreenArea()&e.code; -returns &s.code;TRUE&e.code; if the resize was successful. If -&s.code;xf86ResizeOffscreenArea()&e.code; returns &s.code;FALSE&e.code;, -the original &s.code;FBArea&e.code; is left unmodified. Resizing an -area maintains the area's original &s.code;granularity&e.code;, -&s.code;devPrivate&e.code;, and &s.code;MoveAreaCallback&e.code;. -&s.code;xf86ResizeOffscreenArea()&e.code; has considerably less overhead -than freeing the old area then reallocating the new size, so it should -be used whenever possible. - -The function: - <quote> - &s.code;Bool xf86QueryLargestOffscreenArea( - &f.indent;ScreenPtr pScreen, - &f.indent;int *width, int *height, - &f.indent;int granularity, - &f.indent;int preferences, - &f.indent;int priority - &nl)&e.code; - </quote> - -is provided to query the width and height of the largest single -&s.code;FBArea&e.code; allocatable given a particular priority. -&s.code;preferences&e.code; can be one of the following to indicate -whether width, height or area should be considered when determining -which is the largest single &s.code;FBArea&e.code; available. - - <quote> - &s.code;FAVOR_AREA_THEN_WIDTH&nl; - FAVOR_AREA_THEN_HEIGHT&nl; - FAVOR_WIDTH_THEN_AREA&nl; - FAVOR_HEIGHT_THEN_AREA&e.code; - </quote> - -&s.code;priority&e.code; is one of the following: - - <quote><p> - &s.code;PRIORITY_LOW&e.code; - <quote><p> - Return the largest block available without stealing anyone else's - space. This corresponds to the priority of allocating a - &s.code;FBArea&e.code; when a &s.code;RemoveAreaCallback&e.code; - is provided. - - </quote> - &s.code;PRIORITY_NORMAL&e.code; - <quote><p> - Return the largest block available if it is acceptable to steal a - lower priority area from someone. This corresponds to the priority - of allocating a &s.code;FBArea&e.code; without providing a - &s.code;RemoveAreaCallback&e.code;. - - </quote> - &s.code;PRIORITY_EXTREME&e.code; - <quote><p> - Return the largest block available if all &s.code;FBAreas&e.code; - that aren't locked down were expunged from memory first. This - corresponds to any allocation made directly after a call to - &s.code;xf86PurgeUnlockedOffscreenAreas()&e.code;. - - </quote> - </quote> - - -The function: - - <quote> - &s.code;Bool xf86PurgeUnlockedOffscreenAreas(ScreenPtr pScreen)&e.code; - </quote> - -is provided as an extreme method to free up offscreen memory. This -will remove all removable &s.code;FBArea&e.code; allocations. - - -Initialization of the XFree86 framebuffer manager is done via - - <quote> - &s.code;Bool xf86InitFBManager(ScreenPtr pScreen, BoxPtr FullBox)&e.code; - </quote> - -&s.code;FullBox&e.code; represents the area of the framebuffer that the -manager is allowed to manage. This is typically a box with a width of -&s.code;pScrn->displayWidth&e.code; and a height of as many lines as -can be fit within the total video memory, however, the driver can reserve -areas at the extremities by passing a smaller area to the manager. - -&s.code;xf86InitFBManager()&e.code; must be called before XAA is -initialized since XAA uses the manager for it's pixmap cache. - -An alternative function is provided to allow the driver to initialize -the framebuffer manager with a Region rather than a box. - - <quote> - &s.code;Bool xf86InitFBManagerRegion(ScreenPtr pScreen, - &f.indent;RegionPtr FullRegion)&e.code; - </quote> - -&s.code;xf86InitFBManagerRegion()&e.code;, unlike -&s.code;xf86InitFBManager()&e.code;, does not remove the area used for -the visible screen so that area should not be included in the region -passed to the function. &s.code;xf86InitFBManagerRegion()&e.code; is -useful when non-contiguous areas are available to be managed, and is -required when multiple framebuffers are stored in video memory (as in -the case where an overlay of a different depth is stored as a second -framebuffer in offscreen memory). - - -<sect>Colormap Handling<label id="cmap"> -<p> - -A generic colormap handling layer is provided within the XFree86 common -layer. This layer takes care of most of the details, and only requires -a function from the driver that loads the hardware palette when required. -To use the colormap layer, a driver calls the -&s.code;xf86HandleColormaps()&e.code; function. - - <quote><p> - &s.code;Bool xf86HandleColormaps(ScreenPtr pScreen, int maxColors, - &f.indent;int sigRGBbits, LoadPaletteFuncPtr loadPalette, - &f.indent;SetOverscanFuncPtr setOverscan, - unsigned int flags)&e.code; - <quote><p> - This function must be called after the default colormap has been - initialised. The &s.code;pScrn->gamma&e.code; field must also - be initialised, preferably by calling &s.code;xf86SetGamma()&e.code;. - &s.code;maxColors&e.code; is the number of entries in the palette. - &s.code;sigRGBbits&e.code; is the size in bits of each color - component in the DAC's palette. &s.code;loadPalette&e.code; - is a driver-provided function for loading a colormap into the - hardware, and is described below. &s.code;setOverscan&e.code; is - an optional function that may be provided when the overscan color - is an index from the standard LUT and when it needs to be adjusted - to keep it as close to black as possible. The - &s.code;setOverscan&e.code; function programs the overscan index. - It shouldn't normally be used for depths other than 8. - &s.code;setOverscan&e.code; should be set to &s.code;NULL&e.code; - when it isn't needed. &s.code;flags&e.code; may be set to the - following (which may be ORed together): - - &s.code;CMAP_PALETTED_TRUECOLOR&e.code; - <quote><p> - the TrueColor visual is paletted and is - just a special case of DirectColor. - This flag is only valid for - &s.code;bpp > 8&e.code;. - - </quote> - - &s.code;CMAP_RELOAD_ON_MODE_SWITCH&e.code; - <quote><p> - reload the colormap automatically - after mode switches. This is useful - for when the driver is resetting the - hardware during mode switches and - corrupting or erasing the hardware - palette. - - </quote> - - &s.code;CMAP_LOAD_EVEN_IF_OFFSCREEN&e.code; - <quote><p> - reload the colormap even if the screen - is switched out of the server's VC. - The palette is <it>not</it> reloaded when - the screen is switched back in, nor after - mode switches. This is useful when the - driver needs to keep track of palette - changes. - - </quote> - - The colormap layer normally reloads the palette after VT enters so it - is not necessary for the driver to save and restore the palette - when switching VTs. The driver must, however, still save the - initial palette during server start up and restore it during - server exit. - - </quote> - - &s.code;void LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, - &f.indent;LOCO *colors, VisualPtr pVisual)&e.code; - <quote><p> - &s.code;LoadPalette()&e.code; is a driver-provided function for - loading a colormap into hardware. &s.code;colors&e.code; is the - array of RGB values that represent the full colormap. - &s.code;indices&e.code; is a list of index values into the colors - array. These indices indicate the entries that need to be updated. - &s.code;numColors&e.code; is the number of the indices to be - updated. - - </quote> - - &s.code;void SetOverscan(ScrnInfoPtr pScrn, int overscan)&e.code; - <quote><p> - &s.code;SetOverscan()&e.code; is a driver-provided function for - programming the &s.code;overscan&e.code; index. As described - above, it is normally only appropriate for LUT modes where all - colormap entries are available for the display, but where one of - them is also used for the overscan (typically 8bpp for VGA compatible - LUTs). It isn't required in cases where the overscan area is - never visible. - - </quote> - </quote> - - -<sect>DPMS Extension -<p> - -Support code for the DPMS extension is included in the XFree86 common layer. -This code provides an interface between the main extension code, and a means -for drivers to initialise DPMS when they support it. One function is -available to drivers to do this initialisation, and it is always available, -even when the DPMS extension is not supported by the core server (in -which case it returns a failure result). - - - <quote><p> - &s.code;Bool xf86DPMSInit(ScreenPtr pScreen, DPMSSetProcPtr set, int flags)&e.code; - <quote><p> - This function registers a driver's DPMS level programming function - &s.code;set&e.code;. It also checks - &s.code;pScrn->options&e.code; for the "dpms" option, and when - present marks DPMS as being enabled for that screen. The - &s.code;set&e.code; function is called whenever the DPMS level - changes, and is used to program the requested level. - &s.code;flags&e.code; is currently not used, and should be - &s.code;0&e.code;. If the initialisation fails for any reason, - including when there is no DPMS support in the core server, the - function returns &s.code;FALSE&e.code;. - - </quote> - </quote> - - -Drivers that implement DPMS support must provide the following function, -that gets called when the DPMS level is changed: - - - <quote><p> - &s.code;void ChipDPMSSet(ScrnInfoPtr pScrn, int level, int flags)&e.code; - <quote><p> - Program the DPMS level specified by &s.code;level&e.code;. Valid - values of &s.code;level&e.code; are &s.code;DPMSModeOn&e.code;, - &s.code;DPMSModeStandby&e.code;, &s.code;DPMSModeSuspend&e.code;, - &s.code;DPMSModeOff&e.code;. These values are defined in - &s.code;"extensions/dpms.h"&e.code;. - - </quote> - </quote> - - -<sect>DGA Extension -<p> - -Drivers can support the XFree86 Direct Graphics Architecture (DGA) by -filling out a structure of function pointers and a list of modes and -passing them to DGAInit. - - <quote><p> - &s.code;Bool DGAInit(ScreenPtr pScreen, DGAFunctionPtr funcs, - &f.indent;DGAModePtr modes, int num)&e.code; - <quote><p> - <verb> -/** The DGAModeRec **/ - -typedef struct { - int num; - DisplayModePtr mode; - int flags; - int imageWidth; - int imageHeight; - int pixmapWidth; - int pixmapHeight; - int bytesPerScanline; - int byteOrder; - int depth; - int bitsPerPixel; - unsigned long red_mask; - unsigned long green_mask; - unsigned long blue_mask; - int viewportWidth; - int viewportHeight; - int xViewportStep; - int yViewportStep; - int maxViewportX; - int maxViewportY; - int viewportFlags; - int offset; - unsigned char *address; - int reserved1; - int reserved2; -} DGAModeRec, *DGAModePtr; -</verb> - - &s.code;num&e.code; - <quote> - Can be ignored. The DGA DDX will assign these numbers. - </quote> - - &s.code;mode&e.code; - <quote> - A pointer to the &s.code;DisplayModeRec&e.code; for this mode. - </quote> - - &s.code;flags&e.code; - <quote><p> - The following flags are defined and may be OR'd together: - - &s.code;DGA_CONCURRENT_ACCESS&e.code; - <quote><p> - Indicates that the driver supports concurrent graphics - accelerator and linear framebuffer access. - - </quote> - - &s.code;DGA_FILL_RECT&nl; - DGA_BLIT_RECT&nl; - DGA_BLIT_RECT_TRANS&e.code; - <quote><p> - Indicates that the driver supports the FillRect, BlitRect - or BlitTransRect functions in this mode. - - </quote> - - &s.code;DGA_PIXMAP_AVAILABLE&e.code; - <quote><p> - Indicates that Xlib may be used on the framebuffer. - This flag will usually be set unless the driver wishes - to prohibit this for some reason. - - </quote> - - &s.code;DGA_INTERLACED&nl; - DGA_DOUBLESCAN&e.code; - <quote><p> - Indicates that these are interlaced or double scan modes. - - </quote> - </quote> - - &s.code;imageWidth&nl; - imageHeight&e.code; - <quote><p> - These are the dimensions of the linear framebuffer - accessible by the client. - - </quote> - - &s.code;pixmapWidth&nl; - pixmapHeight&e.code; - <quote><p> - These are the dimensions of the area of the - framebuffer accessible by the graphics accelerator. - - </quote> - - &s.code;bytesPerScanline&e.code; - <quote><p> - Pitch of the framebuffer in bytes. - - </quote> - - &s.code;byteOrder&e.code; - <quote><p> - Usually the same as - &s.code;pScrn->imageByteOrder&e.code;. - - </quote> - - &s.code;depth&e.code; - <quote><p> - The depth of the framebuffer in this mode. - - </quote> - - &s.code;bitsPerPixel&e.code; - <quote><p> - The number of bits per pixel in this mode. - - </quote> - - &s.code;red_mask&nl; - green_mask&nl; - blue_mask&e.code; - <quote><p> - The RGB masks for this mode, if applicable. - - </quote> - - &s.code;viewportWidth&nl; - viewportHeight&e.code; - <quote><p> - Dimensions of the visible part of the framebuffer. - Usually &s.code;mode->HDisplay&e.code; and - &s.code;mode->VDisplay&e.code;. - - </quote> - - &s.code;xViewportStep&nl; - yViewportStep&e.code; - <quote><p> - The granularity of x and y viewport positions that - the driver supports in this mode. - - </quote> - - &s.code;maxViewportX&nl; - maxViewportY&e.code; - <quote><p> - The maximum viewport position supported by the - driver in this mode. - - </quote> - - &s.code;viewportFlags&e.code; - <quote><p> - The following may be OR'd together: - - &s.code;DGA_FLIP_IMMEDIATE&e.code; - <quote><p> - The driver supports immediate viewport changes. - - </quote> - &s.code;DGA_FLIP_RETRACE&e.code; - <quote<p> - The driver supports viewport changes at retrace. - - </quote> - </quote> - - &s.code;offset&e.code; - <quote><p> - The offset into the linear framebuffer that corresponds to - pixel (0,0) for this mode. - - </quote> - - &s.code;address&e.code; - <quote><p> - The virtual address of the framebuffer as mapped by the driver. - This is needed when DGA_PIXMAP_AVAILABLE is set. - - </quote> - - <verb> -/** The DGAFunctionRec **/ - -typedef struct { - Bool (*OpenFramebuffer)( - ScrnInfoPtr pScrn, - char **name, - unsigned char **mem, - int *size, - int *offset, - int *extra - ); - void (*CloseFramebuffer)(ScrnInfoPtr pScrn); - Bool (*SetMode)(ScrnInfoPtr pScrn, DGAModePtr pMode); - void (*SetViewport)(ScrnInfoPtr pScrn, int x, int y, int flags); - int (*GetViewport)(ScrnInfoPtr pScrn); - void (*Sync)(ScrnInfoPtr); - void (*FillRect)( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned long color - ); - void (*BlitRect)( - ScrnInfoPtr pScrn, - int srcx, int srcy, - int w, int h, - int dstx, int dsty - ); - void (*BlitTransRect)( - ScrnInfoPtr pScrn, - int srcx, int srcy, - int w, int h, - int dstx, int dsty, - unsigned long color - ); -} DGAFunctionRec, *DGAFunctionPtr; -</verb> - - </quote> - - &s.code;Bool OpenFramebuffer (pScrn, name, mem, size, offset, extra)&e.code; - <quote><p> - &s.code;OpenFramebuffer()&e.code; should pass the client everything - it needs to know to be able to open the framebuffer. These - parameters are OS specific and their meanings are to be interpreted - by an OS specific client library. - - &s.code;name&e.code; - <quote><p> - The name of the device to open or &s.code;NULL&e.code; if - there is no special device to open. A &s.code;NULL&e.code; - name tells the client that it should open whatever device - one would usually open to access physical memory. - - </quote> - &s.code;mem&e.code; - <quote><p> - The physical address of the start of the framebuffer. - - </quote> - &s.code;size&e.code; - <quote><p> - The size of the framebuffer in bytes. - - </quote> - &s.code;offset&e.code; - <quote><p> - Any offset into the device, if applicable. - - </quote> - &s.code;flags&e.code; - <quote><p> - Any additional information that the client may need. - Currently, only the &s.code;DGA_NEED_ROOT&e.code; flag is - defined. - - </quote> - </quote> - - &s.code;void CloseFramebuffer (pScrn)&e.code; - <quote><p> - &s.code;CloseFramebuffer()&e.code; merely informs the driver (if it - even cares) that client no longer needs to access the framebuffer - directly. This function is optional. - - </quote> - - &s.code;Bool SetMode (pScrn, pMode)&e.code; - <quote><p> - &s.code;SetMode()&e.code; tells the driver to initialize the mode - passed to it. If &s.code;pMode&e.code; is &s.code;NULL&e.code;, - then the driver should restore the original pre-DGA mode. - - </quote> - - &s.code;void SetViewport (pScrn, x, y, flags)&e.code; - <quote><p> - &s.code;SetViewport()&e.code; tells the driver to make the upper - left-hand corner of the visible screen correspond to coordinate - &s.code;(x,y)&e.code; on the framebuffer. &s.code;Flags&e.code; - currently defined are: - - &s.code;DGA_FLIP_IMMEDIATE&e.code; - <quote><p> - The viewport change should occur immediately. - - </quote> - &s.code;DGA_FLIP_RETRACE&e.code; - <quote><p> - The viewport change should occur at the - vertical retrace, but this function should - return sooner if possible. - - </quote> - The &s.code;(x,y)&e.code; locations will be passed as the client - specified them, however, the driver is expected to round these - locations down to the next supported location as specified by the - &s.code;xViewportStep&e.code; and &s.code;yViewportStep&e.code; - for the current mode. - - </quote> - - &s.code;int GetViewport (pScrn)&e.code; - <quote><p> - &s.code;GetViewport()&e.code; gets the current page flip status. - Set bits in the returned int correspond to viewport change requests - still pending. For instance, set bit zero if the last SetViewport - request is still pending, bit one if the one before that is still - pending, etc. - - </quote> - - &s.code;void Sync (pScrn)&e.code; - <quote><p> - This function should ensure that any graphics accelerator operations - have finished. This function should not return until the graphics - accelerator is idle. - - </quote> - - &s.code;void FillRect (pScrn, x, y, w, h, color)&e.code; - <quote><p> - This optional function should fill a rectangle - &s.code;w × h&e.code; located at - &s.code;(x,y)&e.code; in the given color. - - </quote> - - &s.code;void BlitRect (pScrn, srcx, srcy, w, h, dstx, dsty)&e.code; - <quote><p> - This optional function should copy an area - &s.code;w × h&e.code; located at - &s.code;(srcx,srcy)&e.code; to location &s.code;(dstx,dsty)&e.code;. - This function will need to handle copy directions as appropriate. - - </quote> - - &s.code;void BlitTransRect (pScrn, srcx, srcy, w, h, dstx, dsty, color)&e.code; - <quote><p> - This optional function is the same as BlitRect except that pixels - in the source corresponding to the color key &s.code;color&e.code; - should be skipped. - - </quote> - </quote> - -<sect>The XFree86 X Video Extension (Xv) Device Dependent Layer -<p> - -XFree86 offers the X Video Extension which allows clients to treat video -as any another primitive and ``Put'' video into drawables. By default, -the extension reports no video adaptors as being available since the -DDX layer has not been initialized. The driver can initialize the DDX -layer by filling out one or more &s.code;XF86VideoAdaptorRecs&e.code; -as described later in this document and passing a list of -&s.code;XF86VideoAdaptorPtr&e.code; pointers to the following function: - - <quote> - &s.code;Bool xf86XVScreenInit( - &f.indent;ScreenPtr pScreen, - &f.indent;XF86VideoAdaptorPtr *adaptPtrs, - &f.indent;int num)&e.code; - </quote> - -After doing this, the extension will report video adaptors as being -available, providing the data in their respective -&s.code;XF86VideoAdaptorRecs&e.code; was valid. -&s.code;xf86XVScreenInit()&e.code; <em>copies</em> data from the structure -passed to it so the driver may free it after the initialization. At -the moment, the DDX only supports rendering into Window drawables. -Pixmap rendering will be supported after a sufficient survey of suitable -hardware is completed. - -The &s.code;XF86VideoAdaptorRec&e.code;: - -<quote><p> -<verb> -typedef struct { - unsigned int type; - int flags; - char *name; - int nEncodings; - XF86VideoEncodingPtr pEncodings; - int nFormats; - XF86VideoFormatPtr pFormats; - int nPorts; - DevUnion *pPortPrivates; - int nAttributes; - XF86AttributePtr pAttributes; - int nImages; - XF86ImagePtr pImages; - PutVideoFuncPtr PutVideo; - PutStillFuncPtr PutStill; - GetVideoFuncPtr GetVideo; - GetStillFuncPtr GetStill; - StopVideoFuncPtr StopVideo; - SetPortAttributeFuncPtr SetPortAttribute; - GetPortAttributeFuncPtr GetPortAttribute; - QueryBestSizeFuncPtr QueryBestSize; - PutImageFuncPtr PutImage; - QueryImageAttributesFuncPtr QueryImageAttributes; -} XF86VideoAdaptorRec, *XF86VideoAdaptorPtr; -</verb> - - Each adaptor will have its own XF86VideoAdaptorRec. The fields are - as follows: - - &s.code;type&e.code; - <quote><p> - This can be any of the following flags OR'd together. - - &s.code;XvInputMask&e.code; - &s.code;XvOutputMask&e.code; - <quote><p> - These refer to the target drawable and are similar to a Window's - class. &s.code;XvInputMask&e.code; indicates that the adaptor - can put video into a drawable. &s.code;XvOutputMask&e.code; - indicates that the adaptor can get video from a drawable. - </quote> - - &s.code;XvVideoMask&e.code; - &s.code;XvStillMask&e.code; - &s.code;XvImageMask&e.code; - <quote><p> - These indicate that the adaptor supports video, still or - image primitives respectively. - </quote> - - &s.code;XvWindowMask&e.code; - &s.code;XvPixmapMask&e.code; - <quote><p> - These indicate the types of drawables the adaptor is capable - of rendering into. At the moment, Pixmap rendering is not - supported and the &s.code;XvPixmapMask&e.code; flag is ignored. - </quote> - - </quote> - - &s.code;flags&e.code; - <quote><p> - Currently, the following flags are defined: - - &s.code;VIDEO_NO_CLIPPING&e.code; - <quote><p> - This indicates that the video adaptor does not support - clipping. The driver will never receive ``Put'' requests - where less than the entire area determined by - &s.code;drw_x&e.code;, &s.code;drw_y&e.code;, - &s.code;drw_w&e.code; and &s.code;drw_h&e.code; is visible. - This flag does not apply to ``Get'' requests. Hardware - that is incapable of clipping ``Gets'' may punt or get - the extents of the clipping region passed to it. - - </quote> - - &s.code;VIDEO_INVERT_CLIPLIST&e.code; - <quote><p> - This indicates that the video driver requires the clip - list to contain the regions which are obscured rather - than the regions which are are visible. - - </quote> - - &s.code;VIDEO_OVERLAID_STILLS&e.code; - <quote><p> - Implementing PutStill for hardware that does video as an - overlay can be awkward since it's unclear how long to leave - the video up for. When this flag is set, StopVideo will be - called whenever the destination gets clipped or moved so that - the still can be left up until then. - - </quote> - - &s.code;VIDEO_OVERLAID_IMAGES&e.code; - <quote><p> - Same as &s.code;VIDEO_OVERLAID_STILLS&e.code; but for images. - </quote> - - &s.code;VIDEO_CLIP_TO_VIEWPORT&e.code; - <quote><p> - Indicates that the clip region passed to the driver functions - should be clipped to the visible portion of the screen in the - case where the viewport is smaller than the virtual desktop. - </quote> - - </quote> - - &s.code;name&e.code; - <quote><p> - The name of the adaptor. - - </quote> - - &s.code;nEncodings&nl; - pEncodings&e.code; - <quote><p> - The number of encodings the adaptor is capable of and pointer - to the &s.code;XF86VideoEncodingRec&e.code; array. The - &s.code;XF86VideoEncodingRec&e.code; is described later on. - For drivers that only support XvImages there should be an encoding - named "XV_IMAGE" and the width and height should specify - the maximum size source image supported. - - </quote> - - &s.code;nFormats&nl; - pFormats&e.code; - <quote><p> - The number of formats the adaptor is capable of and pointer to - the &s.code;XF86VideoFormatRec&e.code; array. The - &s.code;XF86VideoFormatRec&e.code; is described later on. - - </quote> - - &s.code;nPorts&nl; - pPortPrivates&e.code; - <quote><p> - The number of ports is the number of separate data streams which - the adaptor can handle simultaneously. If you have more than - one port, the adaptor is expected to be able to render into more - than one window at a time. &s.code;pPortPrivates&e.code; is - an array of pointers or ints - one for each port. A port's - private data will be passed to the driver any time the port is - requested to do something like put the video or stop the video. - In the case where there may be many ports, this enables the - driver to know which port the request is intended for. Most - commonly, this will contain a pointer to the data structure - containing information about the port. In Xv, all ports on - a particular adaptor are expected to be identical in their - functionality. - - </quote> - - &s.code;nAttributes&nl; - pAttributes&e.code; - <quote><p> - The number of attributes recognized by the adaptor and a pointer to - the array of &s.code;XF86AttributeRecs&e.code;. The - &s.code;XF86AttributeRec&e.code; is described later on. - - </quote> - - &s.code;nImages&nl; - pImages&e.code; - <quote><p> - The number of &s.code;XF86ImageRecs&e.code; supported by the adaptor - and a pointer to the array of &s.code;XF86ImageRecs&e.code;. The - &s.code;XF86ImageRec&e.code; is described later on. - - </quote> - - - &s.code;PutVideo PutStill GetVideo GetStill StopVideo - SetPortAttribute GetPortAttribute QueryBestSize PutImage - QueryImageAttributes&e.code; - <quote><p> - These functions define the DDX->driver interface. In each - case, the pointer &s.code;data&e.code; is passed to the driver. - This is the port private for that port as described above. All - fields are required except under the following conditions: - - <enum> - <item>&s.code;PutVideo&e.code;, &s.code;PutStill&e.code; and - the image routines &s.code;PutImage&e.code; and - &s.code;QueryImageAttributes&e.code; are not required when the - adaptor type does not contain &s.code;XvInputMask&e.code;. - - <item>&s.code;GetVideo&e.code; and &s.code;GetStill&e.code; - are not required when the adaptor type does not contain - &s.code;XvOutputMask&e.code;. - - <item>&s.code;GetVideo&e.code; and &s.code;PutVideo&e.code; - are not required when the adaptor type does not contain - &s.code;XvVideoMask&e.code;. - - <item>&s.code;GetStill&e.code; and &s.code;PutStill&e.code; - are not required when the adaptor type does not contain - &s.code;XvStillMask&e.code;. - - <item>&s.code;PutImage&e.code; and &s.code;QueryImageAttributes&e.code; - are not required when the adaptor type does not contain - &s.code;XvImageMask&e.code;. - - </enum> - - With the exception of &s.code;QueryImageAttributes&e.code;, these - functions should return &s.code;Success&e.code; if the operation was - completed successfully. They can return &s.code;XvBadAlloc&e.code; - otherwise. &s.code;QueryImageAttributes&e.code; returns the size - of the XvImage queried. - - If the &s.code;VIDEO_NO_CLIPPING&e.code; - flag is set, the &s.code;clipBoxes&e.code; may be ignored by - the driver. &s.code;ClipBoxes&e.code; is an &s.code;X-Y&e.code; - banded region identical to those used throughout the server. - The clipBoxes represent the visible portions of the area determined - by &s.code;drw_x&e.code;, &s.code;drw_y&e.code;, - &s.code;drw_w&e.code; and &s.code;drw_h&e.code; in the Get/Put - function. The boxes are in screen coordinates, are guaranteed - not to overlap and an empty region will never be passed. - If the driver has specified &s.code;VIDEO_INVERT_CLIPLIST&e.code;, - &s.code;clipBoxes&e.code; will indicate the areas of the primitive - which are obscured rather than the areas visible. - - </quote> - - &s.code;typedef int (* PutVideoFuncPtr)( ScrnInfoPtr pScrn, - &f.indent;short vid_x, short vid_y, short drw_x, short drw_y, - &f.indent;short vid_w, short vid_h, short drw_w, short drw_h, - &f.indent;RegionPtr clipBoxes, pointer data )&e.code; - <quote><p> - This indicates that the driver should take a subsection - &s.code;vid_w&e.code; by &s.code;vid_h&e.code; at location - &s.code;(vid_x,vid_y)&e.code; from the video stream and direct - it into the rectangle &s.code;drw_w&e.code; by &s.code;drw_h&e.code; - at location &s.code;(drw_x,drw_y)&e.code; on the screen, scaling as - necessary. Due to the large variations in capabilities of - the various hardware expected to be used with this extension, - it is not expected that all hardware will be able to do this - exactly as described. In that case the driver should just do - ``the best it can,'' scaling as closely to the target rectangle - as it can without rendering outside of it. In the worst case, - the driver can opt to just not turn on the video. - - </quote> - - &s.code;typedef int (* PutStillFuncPtr)( ScrnInfoPtr pScrn, - &f.indent;short vid_x, short vid_y, short drw_x, short drw_y, - &f.indent;short vid_w, short vid_h, short drw_w, short drw_h, - &f.indent;RegionPtr clipBoxes, pointer data )&e.code; - <quote><p> - This is same as &s.code;PutVideo&e.code; except that the driver - should place only one frame from the stream on the screen. - - </quote> - - &s.code;typedef int (* GetVideoFuncPtr)( ScrnInfoPtr pScrn, - &f.indent;short vid_x, short vid_y, short drw_x, short drw_y, - &f.indent;short vid_w, short vid_h, short drw_w, short drw_h, - &f.indent;RegionPtr clipBoxes, pointer data )&e.code; - <quote><p> - This is same as &s.code;PutVideo&e.code; except that the driver - gets video from the screen and outputs it. The driver should - do the best it can to get the requested dimensions correct - without reading from an area larger than requested. - - </quote> - - &s.code;typedef int (* GetStillFuncPtr)( ScrnInfoPtr pScrn, - &f.indent;short vid_x, short vid_y, short drw_x, short drw_y, - &f.indent;short vid_w, short vid_h, short drw_w, short drw_h, - &f.indent;RegionPtr clipBoxes, pointer data )&e.code; - <quote><p> - This is the same as &s.code;GetVideo&e.code; except that the - driver should place only one frame from the screen into the - output stream. - - </quote> - - &s.code;typedef void (* StopVideoFuncPtr)(ScrnInfoPtr pScrn, - &f.indent;pointer data, Bool cleanup)&e.code; - <quote><p> - This indicates the driver should stop displaying the video. - This is used to stop both input and output video. The - &s.code;cleanup&e.code; field indicates that the video is - being stopped because the client requested it to stop or - because the server is exiting the current VT. In that case - the driver should deallocate any offscreen memory areas (if - there are any) being used to put the video to the screen. If - &s.code;cleanup&e.code; is not set, the video is being stopped - temporarily due to clipping or moving of the window, etc... - and video will likely be restarted soon so the driver should - not deallocate any offscreen areas associated with that port. - - </quote> - &s.code;typedef int (* SetPortAttributeFuncPtr)(ScrnInfoPtr pScrn, - &f.indent;Atom attribute,INT32 value, pointer data)&e.code; - - &s.code;typedef int (* GetPortAttributeFuncPtr)(ScrnInfoPtr pScrn, - &f.indent;Atom attribute,INT32 *value, pointer data)&e.code; - - <quote><p> - A port may have particular attributes such as hue, - saturation, brightness or contrast. Xv clients set and - get these attribute values by sending attribute strings - (Atoms) to the server. Such requests end up at these - driver functions. It is recommended that the driver provide - at least the following attributes mentioned in the Xv client - library docs: - <quote> - &s.code;XV_ENCODING&nl; - XV_HUE&nl; - XV_SATURATION&nl; - XV_BRIGHTNESS&nl; - XV_CONTRAST&e.code; - </quote> - but the driver may recognize as many atoms as it wishes. If - a requested attribute is unknown by the driver it should return - &s.code;BadMatch&e.code;. &s.code;XV_ENCODING&e.code; is the - attribute intended to let the client specify which video - encoding the particular port should be using (see the description - of &s.code;XF86VideoEncodingRec&e.code; below). If the - requested encoding is unsupported, the driver should return - &s.code;XvBadEncoding&e.code;. If the value lies outside the - advertised range &s.code;BadValue&e.code; may be returned. - &s.code;Success&e.code; should be returned otherwise. - - </quote> - - &s.code;typedef void (* QueryBestSizeFuncPtr)(ScrnInfoPtr pScrn, - &f.indent;Bool motion, short vid_w, short vid_h, - &f.indent;short drw_w, short drw_h, - &f.indent;unsigned int *p_w, unsigned int *p_h, pointer data)&e.code; - <quote><p> - &s.code;QueryBestSize&e.code; provides the client with a way - to query what the destination dimensions would end up being - if they were to request that an area - &s.code;vid_w&e.code by &s.code;vid_h&e.code; from the video - stream be scaled to rectangle of - &s.code;drw_w&e.code; by &s.code;drw_h&e.code; on the screen. - Since it is not expected that all hardware will be able to - get the target dimensions exactly, it is important that the - driver provide this function. - - </quote> - - &s.code;typedef int (* PutImageFuncPtr)( ScrnInfoPtr pScrn, - &f.indent;short src_x, short src_y, short drw_x, short drw_y, - &f.indent;short src_w, short src_h, short drw_w, short drw_h, - &f.indent;int image, char *buf, short width, short height, - &f.indent;Bool sync, RegionPtr clipBoxes, pointer data )&e.code; - <quote><p> - This is similar to &s.code;PutStill&e.code; except that the - source of the video is not a port but the data stored in a system - memory buffer at &s.code;buf&e.code;. The data is in the format - indicated by the &s.code;image&e.code; descriptor and represents a - source of size &s.code;width&e.code; by &s.code;height&e.code;. - If &s.code;sync&e.code; is TRUE the driver should not return - from this function until it is through reading the data - from &s.code;buf&e.code;. Returning when &s.code;sync&e.code; - is TRUE indicates that it is safe for the data at &s.code;buf&e.code; - to be replaced, freed, or modified. - - </quote> - - &s.code;typedef int (* QueryImageAttributesFuncPtr)( ScrnInfoPtr pScrn, - &f.indent;int image, short *width, short *height, - &f.indent;int *pitches, int *offsets)&e.code; - <quote><p> - This function is called to let the driver specify how data for - a particular &s.code;image&e.code; of size &s.code;width&e.code; - by &s.code;height&e.code; should be stored. Sometimes only - the size and corrected width and height are needed. In that - case &s.code;pitches&e.code; and &s.code;offsets&e.code; are - NULL. The size of the memory required for the image is returned - by this function. The &s.code;width&e.code; and - &s.code;height&e.code; of the requested image can be altered by - the driver to reflect format limitations (such as component - sampling periods that are larger than one). If - &s.code;pitches&e.code; and &s.code;offsets&e.code; are not NULL, - these will be arrays with as many elements in them as there - are planes in the &s.code;image&e.code; format. The driver - should specify the pitch (in bytes) of each scanline in the - particular plane as well as the offset to that plane (in bytes) - from the beginning of the image. - - </quote> - - </quote> - -The XF86VideoEncodingRec: -<quote><p> -<verb> -typedef struct { - int id; - char *name; - unsigned short width, height; - XvRationalRec rate; -} XF86VideoEncodingRec, *XF86VideoEncodingPtr; - -</verb> - The &s.code;XF86VideoEncodingRec&e.code; specifies what encodings - the adaptor can support. Most of this data is just informational - and for the client's benefit, and is what will be reported by - &s.code;XvQueryEncodings&e.code;. The &s.code;id&e.code; field is - expected to be a unique identifier to allow the client to request a - certain encoding via the &s.code;XV_ENCODING&e.code; attribute string. - -</quote> - -The XF86VideoFormatRec: - -<quote><p> -<verb> -typedef struct { - char depth; - short class; -} XF86VideoFormatRec, *XF86VideoFormatPtr; -</verb> - - This specifies what visuals the video is viewable in. - &s.code;depth&e.code; is the depth of the visual (not bpp). - &s.code;class&e.code; is the visual class such as - &s.code;TrueColor&e.code;, &s.code;DirectColor&e.code; or - &s.code;PseudoColor&e.code;. Initialization of an adaptor will fail - if none of the visuals on that screen are supported. - -</quote> - -The XF86AttributeRec: - -<quote><p> -<verb> -typedef struct { - int flags; - int min_value; - int max_value; - char *name; -} XF86AttributeListRec, *XF86AttributeListPtr; - -</verb> - - Each adaptor may have an array of these advertising the attributes - for its ports. Currently defined flags are &s.code;XvGettable&e.code; - and &s.code;XvSettable&e.code; which may be OR'd together indicating that - attribute is ``gettable'' or ``settable'' by the client. The - &s.code;min&e.code; and &s.code;max&e.code; field specify the valid range - for the value. &s.code;Name&e.code; is a text string describing the - attribute by name. - -</quote> - -The XF86ImageRec: - -<quote><p> -<verb> -typedef struct { - int id; - int type; - int byte_order; - char guid[16]; - int bits_per_pixel; - int format; - int num_planes; - - /* for RGB formats */ - int depth; - unsigned int red_mask; - unsigned int green_mask; - unsigned int blue_mask; - - /* for YUV formats */ - unsigned int y_sample_bits; - unsigned int u_sample_bits; - unsigned int v_sample_bits; - unsigned int horz_y_period; - unsigned int horz_u_period; - unsigned int horz_v_period; - unsigned int vert_y_period; - unsigned int vert_u_period; - unsigned int vert_v_period; - char component_order[32]; - int scanline_order; -} XF86ImageRec, *XF86ImagePtr; -</verb> - - XF86ImageRec describes how video source data is laid out in memory. - The fields are as follows: - - &s.code;id&e.code; - <quote><p> - This is a unique descriptor for the format. It is often good to - set this value to the FOURCC for the format when applicable. - </quote> - - &s.code;type&e.code; - <quote><p> - This is &s.code;XvRGB&e.code; or &s.code;XvYUV&e.code;. - </quote> - - &s.code;byte_order&e.code; - <quote><p> - This is &s.code;LSBFirst&e.code; or &s.code;MSBFirst&e.code;. - </quote> - - &s.code;guid&e.code; - <quote><p> - This is the Globally Unique IDentifier for the format. When - not applicable, all characters should be NULL. - </quote> - - &s.code;bits_per_pixel&e.code; - <quote><p> - The number of bits taken up (but not necessarily used) by each - pixel. Note that for some planar formats which have fractional - bits per pixel (such as IF09) this number may be rounded _down_. - </quote> - - &s.code;format&e.code; - <quote><p> - This is &s.code;XvPlanar&e.code; or &s.code;XvPacked&e.code;. - </quote> - - &s.code;num_planes&e.code; - <quote><p> - The number of planes in planar formats. This should be set to - one for packed formats. - </quote> - - &s.code;depth&e.code; - <quote><p> - The significant bits per pixel in RGB formats (analgous to the - depth of a pixmap format). - </quote> - - &s.code;red_mask&e.code; - &s.code;green_mask&e.code; - &s.code;blue_mask&e.code; - <quote><p> - The red, green and blue bitmasks for packed RGB formats. - </quote> - - &s.code;y_sample_bits&e.code; - &s.code;u_sample_bits&e.code; - &s.code;v_sample_bits&e.code; - <quote><p> - The y, u and v sample sizes (in bits). - </quote> - - &s.code;horz_y_period&e.code; - &s.code;horz_u_period&e.code; - &s.code;horz_v_period&e.code; - <quote><p> - The y, u and v sampling periods in the horizontal direction. - </quote> - - &s.code;vert_y_period&e.code; - &s.code;vert_u_period&e.code; - &s.code;vert_v_period&e.code; - <quote><p> - The y, u and v sampling periods in the vertical direction. - </quote> - - &s.code;component_order&e.code; - <quote><p> - Uppercase ascii characters representing the order that - samples are stored within packed formats. For planar formats - this represents the ordering of the planes. Unused characters - in the 32 byte string should be set to NULL. - </quote> - - &s.code;scanline_order&e.code; - <quote><p> - This is &s.code;XvTopToBottom&e.code; or &s.code;XvBottomToTop&e.code;. - </quote> - - Since some formats (particular some planar YUV formats) may not -be completely defined by the parameters above, the guid, when -available, should provide the most accurate description of the -format. - -</quote> - -<sect>The Loader -<p> - -This section describes the interfaces to the module loader. The loader -interfaces can be divided into two groups: those that are only available to -the XFree86 common layer, and those that are also available to modules. - -<sect1>Loader Overview -<p> - -The loader is capable of loading modules in a range of object formats, -and knowledge of these formats is built in to the loader. Knowledge of -new object formats can be added to the loader in a straightforward -manner. This makes it possible to provide OS-independent modules (for -a given CPU architecture type). In addition to this, the loader can -load modules via the OS-provided &s.code;dlopen(3)&e.code; service where -available. Such modules are not platform independent, and the semantics -of &s.code;dlopen()&e.code; on most systems results in significant -limitations in the use of modules of this type. Support for -&s.code;dlopen()&e.code; modules in the loader is primarily for -experimental and development purposes. - -Symbols exported by the loader (on behalf of the core X server) to -modules are determined at compile time. Only those symbols explicitly -exported are available to modules. All external symbols of loaded -modules are exported to other modules, and to the core X server. The -loader can be requested to check for unresolved symbols at any time, -and the action to be taken for unresolved symbols can be controlled by -the caller of the loader. Typically the caller identifies which symbols -can safely remain unresolved and which cannot. - -NOTE: Now that ISO-C allows pointers to functions and pointers to data to -have different internal representations, some of the following interfaces -will need to be revisited. - -<sect1>Semi-private Loader Interface -<p> - -The following is the semi-private loader interface that is available to the -XFree86 common layer. - - <quote><p> - &s.code;void LoaderInit(void)&e.code; - <quote><p> - The &s.code;LoaderInit()&e.code; function initialises the loader, - and it must be called once before calling any other loader functions. - This function initialises the tables of exported symbols, and anything - else that might need to be initialised. - - </quote> - - &s.code;void LoaderSetPath(const char *path)&e.code; - <quote><p> - The &s.code;LoaderSetPath()&e.code; function initialises a default - module search path. This must be called if calls to other functions - are to be made without explicitly specifying a module search path. - The search path &s.code;path&e.code; must be a string of one or more - comma separated absolute paths. Modules are expected to be located - below these paths, possibly in subdirectories of these paths. - - </quote> - - &s.code;pointer LoadModule(const char *module, const char *path, - &f.indent;const char **subdirlist, const char **patternlist, - &f.indent;pointer options, const XF86ModReqInfo * modreq, - &f.indent;int *errmaj, int *errmin)&e.code; - <quote><p> - The &s.code;LoadModule()&e.code; function loads the module called - &s.code;module&e.code;. The return value is a module handle, and - may be used in future calls to the loader that require a reference - to a loaded module. The module name &s.code;module&e.code; is - normally the module's canonical name, which doesn't contain any - directory path information, or any object/library file prefixes of - suffixes. Currently a full pathname and/or filename is also accepted. - This might change. The other parameters are: - - &s.code;path&e.code; - <quote><p> - An optional comma-separated list of module search paths. - When &s.code;NULL&e.code;, the default search path is used. - - </quote> - - &s.code;subdirlist&e.code; - <quote><p> - An optional &s.code;NULL&e.code; terminated list of - subdirectories to search. When &s.code;NULL&e.code;, - the default built-in list is used (refer to - &s.code;stdSubdirs&e.code; in &s.code;loadmod.c&e.code;). - The default list is also substituted for entries in - &s.code;subdirlist&e.code; with the value - &s.code;DEFAULT_LIST&e.code;. This makes is possible - to augment the default list instead of replacing it. - Subdir elements must be relative, and must not contain - &s.code;".."&e.code;. If any violate this requirement, - the load fails. - - </quote> - - &s.code;patternlist&e.code; - <quote><p> - An optional &s.code;NULL&e.code; terminated list of - POSIX regular expressions used to connect module - filenames with canonical module names. Each regex - should contain exactly one subexpression that corresponds - to the canonical module name. When &s.code;NULL&e.code;, - the default built-in list is used (refer to - &s.code;stdPatterns&e.code; in - &s.code;loadmod.c&e.code;). The default list is also - substituted for entries in &s.code;patternlist&e.code; - with the value &s.code;DEFAULT_LIST&e.code;. This - makes it possible to augment the default list instead - of replacing it. - - </quote> - - &s.code;options&e.code; - <quote><p> - An optional parameter that is passed to the newly - loaded module's &s.code;SetupProc&e.code; function - (if it has one). This argument is normally a - &s.code;NULL&e.code; terminated list of - &s.code;Options&e.code;, and must be interpreted that - way by modules loaded directly by the XFree86 common - layer. However, it may be used for application-specific - parameter passing in other situations. - - When loading ``external'' modules (modules that don't - have the standard entry point, for example a - special shared library) the options parameter can be - set to &s.code;EXTERN_MODULE&e.code; to tell the - loader not to reject the module when it doesn't find - the standard entry point. - - </quote> - - &s.code;modreq&e.code; - <quote><p> - An optional &s.code;XF86ModReqInfo*&e.code; containing - version/ABI/vendor information to requirements to - check the newly loaded module against. The main - purpose of this is to allow the loader to verify that - a module of the correct type/version before running - its &s.code;SetupProc&e.code; function. - - The &s.code;XF86ModReqInfo&e.code; struct is defined - as follows: -<verb> -typedef struct { - CARD8 majorversion; /* MAJOR_UNSPEC */ - CARD8 minorversion; /* MINOR_UNSPEC */ - CARD16 patchlevel; /* PATCH_UNSPEC */ - const char * abiclass; /* ABI_CLASS_NONE */ - CARD32 abiversion; /* ABI_VERS_UNSPEC */ - const char * moduleclass; /* MOD_CLASS_NONE */ -} XF86ModReqInfo; -</verb> - - The information here is compared against the equivalent - information in the module's - &s.code;XF86ModuleVersionInfo&e.code; record (which - is described below). The values in comments above - indicate ``don't care'' settings for each of the fields. - The comparisons made are as follows: - - &s.code;majorversion&e.code; - <quote><p> - Must match the module's majorversion - exactly. - - </quote> - &s.code;minorversion&e.code; - <quote><p> - The module's minor version must be - no less than this value. This - comparison is only made if - &s.code;majorversion&e.code; is - specified and matches. - - </quote> - &s.code;patchlevel&e.code; - <quote><p> - The module's patchlevel must be no - less than this value. This comparison - is only made if - &s.code;minorversion&e.code; is - specified and matches. - - </quote> - &s.code;abiclass&e.code; - <quote><p> - String must match the module's abiclass - string. - - </quote> - &s.code;abiversion&e.code; - <quote><p> - Must be consistent with the module's - abiversion (major equal, minor no - older). - - </quote> - &s.code;moduleclass&e.code; - <quote><p> - String must match the module's - moduleclass string. - - </quote> - - </quote> - - &s.code;errmaj&e.code; - <quote><p> - An optional pointer to a variable holding the major - part or the error code. When provided, - &s.code;*errmaj&e.code; is filled in when - &s.code;LoadModule()&e.code; fails. - - </quote> - - &s.code;errmin&e.code; - <quote><p> - Like &s.code;errmaj&e.code;, but for the minor part - of the error code. - - </quote> - - </quote> - - &s.code;void UnloadModule(pointer mod)&e.code; - <quote><p> - This function unloads the module referred to by the handle mod. - All child modules are also unloaded recursively. This function must - not be used to directly unload modules that are child modules (i.e., - those that have been loaded with the &s.code;LoadSubModule()&e.code; - described below). - - </quote> - </quote> - -<sect1>Module Requirements -<p> - -Modules must provide information about themselves to the loader, and -may optionally provide entry points for "setup" and "teardown" functions -(those two functions are referred to here as &s.code;SetupProc&e.code; -and &s.code;TearDownProc&e.code;). - -The module information is contained in the -&s.code;XF86ModuleVersionInfo&e.code; struct, which is defined as follows: - -<quote><p><verb> -typedef struct { - const char * modname; /* name of module, e.g. "foo" */ - const char * vendor; /* vendor specific string */ - CARD32 _modinfo1_; /* constant MODINFOSTRING1/2 to find */ - CARD32 _modinfo2_; /* infoarea with a binary editor/sign tool */ - CARD32 xf86version; /* contains XF86_VERSION_CURRENT */ - CARD8 majorversion; /* module-specific major version */ - CARD8 minorversion; /* module-specific minor version */ - CARD16 patchlevel; /* module-specific patch level */ - const char * abiclass; /* ABI class that the module uses */ - CARD32 abiversion; /* ABI version */ - const char * moduleclass; /* module class */ - CARD32 checksum[4]; /* contains a digital signature of the */ - /* version info structure */ -} XF86ModuleVersionInfo; -</verb> - -The fields are used as follows: - - &s.code;modname&e.code; - <quote><p> - The module's name. This field is currently only for - informational purposes, but the loader may be modified - in future to require it to match the module's canonical - name. - - </quote> - - &s.code;vendor&e.code; - <quote><p> - The module vendor. This field is for informational purposes - only. - - </quote> - - &s.code;_modinfo1_&e.code; - <quote><p> - This field holds the first part of a signature that can - be used to locate this structure in the binary. It should - always be initialised to &s.code;MODINFOSTRING1&e.code;. - - </quote> - - &s.code;_modinfo2_&e.code; - <quote><p> - This field holds the second part of a signature that can - be used to locate this structure in the binary. It should - always be initialised to &s.code;MODINFOSTRING2&e.code;. - - </quote> - - &s.code;xf86version&e.code; - <quote><p> - The XFree86 version against which the module was compiled. - This is mostly for informational/diagnostic purposes. It - should be initialised to &s.code;XF86_VERSION_CURRENT&e.code;, which is - defined in &s.code;xf86Version.h&e.code;. - - </quote> - - &s.code;majorversion&e.code; - <quote><p> - The module-specific major version. For modules where this - version is used for more than simply informational - purposes, the major version should only change (be - incremented) when ABI incompatibilities are introduced, - or ABI components are removed. - - </quote> - - &s.code;minorversion&e.code; - <quote><p> - The module-specific minor version. For modules where this - version is used for more than simply informational - purposes, the minor version should only change (be - incremented) when ABI additions are made in a backward - compatible way. It should be reset to zero when the major - version is increased. - - </quote> - - &s.code;patchlevel&e.code; - <quote><p> - The module-specific patch level. The patch level should - increase with new revisions of the module where there - are no ABI changes, and it should be reset to zero when - the minor version is increased. - - </quote> - - &s.code;abiclass&e.code; - <quote><p> - The ABI class that the module requires. The class is - specified as a string for easy extensibility. It should - indicate which (if any) of the X server's built-in ABI - classes that the module relies on, or a third-party ABI - if appropriate. Built-in ABI classes currently defined are: - - <quote> - &s.code;ABI_CLASS_NONE&e.code; - <quote>no class</quote> - &s.code;ABI_CLASS_ANSIC&e.code; - <quote>only requires the ANSI C interfaces</quote> - &s.code;ABI_CLASS_VIDEODRV&e.code; - <quote>requires the video driver ABI</quote> - &s.code;ABI_CLASS_XINPUT&e.code; - <quote>requires the XInput driver ABI</quote> - &s.code;ABI_CLASS_EXTENSION&e.code; - <quote>requires the extension module ABI</quote> - &s.code;ABI_CLASS_FONT&e.code; - <quote>requires the font module ABI</quote> - </quote> - - </quote> - - &s.code;abiversion&e.code; - <quote><p> - The version of abiclass that the module requires. The - version consists of major and minor components. The - major version must match and the minor version must be - no newer than that provided by the server or parent - module. Version identifiers for the built-in classes - currently defined are: - - <quote> - &s.code;ABI_ANSIC_VERSION&nl; - ABI_VIDEODRV_VERSION&nl; - ABI_XINPUT_VERSION&nl; - ABI_EXTENSION_VERSION&nl; - ABI_FONT_VERSION&e.code; - </quote> - - </quote> - - &s.code;moduleclass&e.code; - <quote><p> - This is similar to the abiclass field, except that it - defines the type of module rather than the ABI it - requires. For example, although all video drivers require - the video driver ABI, not all modules that require the - video driver ABI are video drivers. This distinction - can be made with the moduleclass. Currently pre-defined - module classes are: - - <quote> - &s.code;MOD_CLASS_NONE&nl; - MOD_CLASS_VIDEODRV&nl; - MOD_CLASS_XINPUT&nl; - MOD_CLASS_FONT&nl; - MOD_CLASS_EXTENSION&e.code; - </quote> - - </quote> - - &s.code;checksum&e.code; - <quote><p> - Not currently used. - - </quote> - -</quote> - -The module version information, and the optional &s.code;SetupProc&e.code; -and &s.code;TearDownProc&e.code; entry points are found by the loader -by locating a data object in the module called "modnameModuleData", -where "modname" is the canonical name of the module. Modules must -contain such a data object, and it must be declared with global scope, -be compile-time initialised, and is of the following type: - -<quote> -<verb> -typedef struct { - XF86ModuleVersionInfo * vers; - ModuleSetupProc setup; - ModuleTearDownProc teardown; -} XF86ModuleData; -</verb> -</quote> - -The vers parameter must be initialised to a pointer to a correctly -initialised &s.code;XF86ModuleVersionInfo&e.code; struct. The other -two parameter are optional, and should be initialised to -&s.code;NULL&e.code; when not required. The other parameters are defined -as - - <quote><p> - &s.code;typedef pointer (*ModuleSetupProc)(pointer, pointer, int *, int *)&e.code; - - &s.code;typedef void (*ModuleTearDownProc)(pointer)&e.code; - - - &s.code;pointer SetupProc(pointer module, pointer options, - &f.indent;int *errmaj, int *errmin)&e.code; - <quote><p> - When defined, this function is called by the loader after successfully - loading a module. module is a handle for the newly loaded module, - and maybe used by the &s.code;SetupProc&e.code; if it calls other - loader functions that require a reference to it. The remaining - arguments are those that were passed to the - &s.code;LoadModule()&e.code; (or &s.code;LoadSubModule()&e.code;), - and are described above. When the &s.code;SetupProc&e.code; is - successful it must return a non-&s.code;NULL&e.code; value. The - loader checks this, and if it is &s.code;NULL&e.code; it unloads - the module and reports the failure to the caller of - &s.code;LoadModule()&e.code;. If the &s.code;SetupProc&e.code; - does things that need to be undone when the module is unloaded, - it should define a &s.code;TearDownProc&e.code;, and return a - pointer that the &s.code;TearDownProc&e.code; can use to undo what - has been done. - - When a module is loaded multiple times, the &s.code;SetupProc&e.code; - is called once for each time it is loaded. - - </quote> - - &s.code;void TearDownProc(pointer tearDownData)&e.code; - <quote><p> - When defined, this function is called when the loader unloads a - module. The &s.code;tearDownData&e.code; parameter is the return - value of the &s.code;SetupProc()&e.code; that was called when the - module was loaded. The purpose of this function is to clean up - before the module is unloaded (for example, by freeing allocated - resources). - - </quote> - </quote> - -<sect1>Public Loader Interface -<p> - -The following is the Loader interface that is available to any part of -the server, and may also be used from within modules. - - <quote><p> - &s.code;pointer LoadSubModule(pointer parent, const char *module, - &f.indent;const char **subdirlist, const char **patternlist, - &f.indent;pointer options, const XF86ModReqInfo * modreq, - &f.indent;int *errmaj, int *errmin)&e.code; - <quote><p> - This function is like the &s.code;LoadModule()&e.code; function - described above, except that the module loaded is registered as a - child of the calling module. The &s.code;parent&e.code; parameter - is the calling module's handle. Modules loaded with this function - are automatically unloaded when the parent module is unloaded. The - other difference is that the path parameter may not be specified. - The module search path used for modules loaded with this function - is the default search path as initialised with - &s.code;LoaderSetPath()&e.code;. - - </quote> - - &s.code;void UnloadSubModule(pointer module)&e.code; - <quote><p> - This function unloads the module with handle &s.code;module&e.code;. - If that module itself has children, they are also unloaded. It is - like &s.code;UnloadModule()&e.code;, except that it is safe to use - for unloading child modules. - - </quote> - - &s.code;pointer LoaderSymbol(const char *symbol)&e.code; - <quote><p> - This function returns the address of the symbol with name - &s.code;symbol&e.code;. This may be used to locate a module entry - point with a known name. - - </quote> - - &s.code;char **LoaderlistDirs(const char **subdirlist, - &f.indent;const char **patternlist)&e.code; - <quote><p> - This function returns a &s.code;NULL&e.code; terminated list of - canonical modules names for modules found in the default module - search path. The &s.code;subdirlist&e.code; and - &s.code;patternlist&e.code; parameters are as described above, and - can be used to control the locations and names that are searched. - If no modules are found, the return value is &s.code;NULL&e.code;. - The returned list should be freed by calling - &s.code;LoaderFreeDirList()&e.code; when it is no longer needed. - - </quote> - - &s.code;void LoaderFreeDirList(char **list)&e.code; - <quote><p> - This function frees a module list created by - &s.code;LoaderlistDirs()&e.code;. - - </quote> - - &s.code;void LoaderReqSymLists(const char **list0, ...)&e.code; - <quote><p> - This function allows the registration of required symbols with the - loader. It is normally used by a caller of - &s.code;LoadSubModule()&e.code;. If any symbols registered in this - way are found to be unresolved when - &s.code;LoaderCheckUnresolved()&e.code; is called then - &s.code;LoaderCheckUnresolved()&e.code; will report a failure. - The function takes one or more &s.code;NULL&e.code; terminated - lists of symbols. The end of the argument list is indicated by a - &s.code;NULL&e.code; argument. - - </quote> - - &s.code;void LoaderReqSymbols(const char *sym0, ...)&e.code; - <quote><p> - This function is like &s.code;LoaderReqSymLists()&e.code; except - that its arguments are symbols rather than lists of symbols. This - function is more convenient when single functions are to be registered, - especially when the single function might depend on runtime factors. - The end of the argument list is indicated by a &s.code;NULL&e.code; - argument. - - </quote> - - &s.code;void LoaderRefSymLists(const char **list0, ...)&e.code; - <quote><p> - This function allows the registration of possibly unresolved symbols - with the loader. When &s.code;LoaderCheckUnresolved()&e.code; is - run it won't generate warnings for symbols registered in this way - unless they were also registered as required symbols. - The function takes one or more &s.code;NULL&e.code; terminated - lists of symbols. The end of the argument list is indicated by a - &s.code;NULL&e.code; argument. - - </quote> - - &s.code;void LoaderRefSymbols(const char *sym0, ...)&e.code; - <quote><p> - This function is like &s.code;LoaderRefSymLists()&e.code; except - that its arguments are symbols rather than lists of symbols. This - function is more convenient when single functions are to be registered, - especially when the single function might depend on runtime factors. - The end of the argument list is indicated by a &s.code;NULL&e.code; - argument. - - </quote> - - &s.code;int LoaderCheckUnresolved(int delayflag)&e.code; - <quote><p> - This function checks for unresolved symbols. It generates warnings - for unresolved symbols that have not been registered with - &s.code;LoaderRefSymLists()&e.code;, and maps them to a dummy - function. This behaviour may change in future. If unresolved - symbols are found that have been registered with - &s.code;LoaderReqSymLists()&e.code; or - &s.code;LoaderReqSymbols()&e.code; then this function returns a - non-zero value. If none of these symbols are unresolved the return - value is zero, indicating success. - - The &s.code;delayflag&e.code; parameter should normally be set to - &s.code;LD_RESOLV_IFDONE&e.code;. - - </quote> - - &s.code;LoaderErrorMsg(const char *name, const char *modname, - &f.indent;int errmaj, int errmin)&e.code; - <quote><p> - This function prints an error message that includes the text ``Failed - to load module'', the module name &s.code;modname&e.code;, a message - specific to the &s.code;errmaj&e.code; value, and the value if - &s.code;errmin&e.code;. If &s.code;name&e.code; is - non-&s.code;NULL&e.code;, it is printed as an identifying prefix - to the message (followed by a `:'). - - </quote> - </quote> - -<sect1>Special Registration Functions -<p> - -The loader contains some functions for registering some classes of modules. -These may be moved out of the loader at some point. - - <quote><p> - &s.code;void LoadExtension(ExtensionModule *ext)&e.code; - <quote><p> - This registers the entry points for the extension identified by - &s.code;ext&e.code;. The &s.code;ExtensionModule&e.code; struct is - defined as: - -<quote> -<verb> -typedef struct { - InitExtension initFunc; - char * name; - Bool *disablePtr; - InitExtension setupFunc; -} ExtensionModule; -</verb> -</quote> - - </quote> - - &s.code;void LoadFont(FontModule *font)&e.code; - <quote><p> - This registers the entry points for the font rasteriser module - identified by &s.code;font&e.code;. The &s.code;FontModule&e.code; - struct is defined as: - -<quote> -<verb> -typedef struct { - InitFont initFunc; - char * name; - pointer module; -} FontModule; -</verb> -</quote> - - </quote> - </quote> - -</sect> - - -<sect>Helper Functions -<p> - -This section describe ``helper'' functions that video driver -might find useful. While video drivers are not required to use any of -these to be considered ``compliant'', the use of appropriate helpers is -strongly encouraged to improve the consistency of driver behaviour. - -<sect1>Functions for printing messages -<p> - - <quote><p> - &s.code;ErrorF(const char *format, ...)&e.code; - <quote><p> - This is the basic function for writing to the error log (typically - stderr and/or a log file). Video drivers should usually avoid - using this directly in favour of the more specialised functions - described below. This function is useful for printing messages - while debugging a driver. - - </quote> - - &s.code;FatalError(const char *format, ...)&e.code; - <quote><p> - This prints a message and causes the Xserver to abort. It should - rarely be used within a video driver, as most error conditions - should be flagged by the return values of the driver functions. - This allows the higher layers to decide how to proceed. In rare - cases, this can be used within a driver if a fatal unexpected - condition is found. - - </quote> - - &s.code;xf86ErrorF(const char *format, ...)&e.code; - <quote><p> - This is like &s.code;ErrorF()&e.code;, except that the message is - only printed when the Xserver's verbosity level is set to the - default (&s.code;1&e.code;) or higher. It means that the messages - are not printed when the server is started with the - &s.cmd;-quiet&e.cmd; flag. Typically this function would only be - used for continuing messages started with one of the more specialised - functions described below. - - </quote> - - &s.code;xf86ErrorFVerb(int verb, const char *format, ...)&e.code; - <quote><p> - Like &s.code;xf86ErrorF()&e.code;, except the minimum verbosity - level for which the message is to be printed is given explicitly. - Passing a &s.code;verb&e.code; value of zero means the message - is always printed. A value higher than &s.code;1&e.code; can be - used for information would normally not be needed, but which might - be useful when diagnosing problems. - - </quote> - - &s.code;xf86Msg(MessageType type, const char *format, ...)&e.code; - <quote><p> - This is like &s.code;xf86ErrorF()&e.code;, except that the message - is prefixed with a marker determined by the value of - &s.code;type&e.code;. The marker is used to indicate the type of - message (warning, error, probed value, config value, etc). Note - the &s.code;xf86Verbose&e.code; value is ignored for messages of - type &s.code;X_ERROR&e.code;. - - The marker values are: - - <quote> - &s.code;X_PROBED&e.code; - <quote>Value was probed.</quote> - &s.code;X_CONFIG&e.code; - <quote>Value was given in the config file.</quote> - &s.code;X_DEFAULT&e.code; - <quote>Value is a default.</quote> - &s.code;X_CMDLINE&e.code; - <quote>Value was given on the command line.</quote> - &s.code;X_NOTICE&e.code; - <quote>Notice.</quote> - &s.code;X_ERROR&e.code; - <quote>Error message.</quote> - &s.code;X_WARNING&e.code; - <quote>Warning message.</quote> - &s.code;X_INFO&e.code; - <quote>Informational message.</quote> - &s.code;X_NONE&e.code; - <quote>No prefix.</quote> - &s.code;X_NOT_IMPLEMENTED&e.code; - <quote>The message relates to functionality that is not yet - implemented.</quote> - </quote> - - - </quote> - - &s.code;xf86MsgVerb(MessageType type, int verb, const char *format, ...)&e.code; - <quote><p> - Like &s.code;xf86Msg()&e.code;, but with the verbosity level given - explicitly. - - </quote> - - &s.code;xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...)&e.code; - <quote><p> - This is like &s.code;xf86Msg()&e.code; except that the driver's - name (the &s.code;name&e.code; field of the - &s.code;ScrnInfoRec&e.code;) followed by the - &s.code;scrnIndex&e.code; in parentheses is printed following the - prefix. This should be used by video drivers in most cases as it - clearly indicates which driver/screen the message is for. If - &s.code;scrnIndex&e.code; is negative, this function behaves - exactly like &s.code;xf86Msg()&e.code;. - - NOTE: This function can only be used after the - &s.code;ScrnInfoRec&e.code; and its &s.code;name&e.code; field - have been allocated. Normally, this means that it can not be - used before the END of the &s.code;ChipProbe()&e.code; function. - Prior to that, use &s.code;xf86Msg()&e.code;, providing the - driver's name explicitly. No screen number can be supplied at - that point. - - </quote> - - &s.code;xf86DrvMsgVerb(int scrnIndex, MessageType type, int verb, - &f.indent;const char *format, ...)&e.code; - <quote><p> - Like &s.code;xf86DrvMsg()&e.code;, but with the verbosity level - given explicitly. - - </quote> - </quote> - - -<sect1>Functions for setting values based on command line and config file -<p> - - <quote><p> - &s.code;Bool xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int bpp, - &f.indent;int fbbpp, int depth24flags)&e.code; - <quote><p> - This function sets the &s.code;depth&e.code;, &s.code;pixmapBPP&e.code; and &s.code;bitsPerPixel&e.code; fields - of the &s.code;ScrnInfoRec&e.code;. It also determines the defaults for display-wide - attributes and pixmap formats the screen will support, and finds - the Display subsection that matches the depth/bpp. This function - should normally be called very early from the - &s.code;ChipPreInit()&e.code; function. - - It requires that the &s.code;confScreen&e.code; field of the &s.code;ScrnInfoRec&e.code; be - initialised prior to calling it. This is done by the XFree86 - common layer prior to calling &s.code;ChipPreInit()&e.code;. - - The parameters passed are: - - &s.code;depth&e.code; - <quote><p> - driver's preferred default depth if no other is given. - If zero, use the overall server default. - - </quote> - &s.code;bpp&e.code; - <quote><p> - Same, but for the pixmap bpp. - - </quote> - &s.code;fbbpp&e.code; - <quote><p> - Same, but for the framebuffer bpp. - - </quote> - &s.code;depth24flags&e.code; - <quote><p> - Flags that indicate the level of 24/32bpp support - and whether conversion between different framebuffer - and pixmap formats is supported. The flags for this - argument are defined as follows, and multiple flags - may be ORed together: - - &s.code;NoDepth24Support&e.code; - <quote>No depth 24 formats supported</quote> - &s.code;Support24bppFb&e.code; - <quote>24bpp framebuffer supported</quote> - &s.code;Support32bppFb&e.code; - <quote>32bpp framebuffer supported</quote> - &s.code;SupportConvert24to32&e.code; - <quote>Can convert 24bpp pixmap to 32bpp fb</quote> - &s.code;SupportConvert32to24&e.code; - <quote>Can convert 32bpp pixmap to 24bpp fb</quote> - &s.code;ForceConvert24to32&e.code; - <quote>Force 24bpp pixmap to 32bpp fb conversion</quote> - &s.code;ForceConvert32to24&e.code; - <quote>Force 32bpp pixmap to 24bpp fb conversion</quote> - - </quote> - - It uses the command line, config file, and default values in the - correct order of precedence to determine the depth and bpp values. - It is up to the driver to check the results to see that it supports - them. If not the &s.code;ChipPreInit()&e.code; function should - return &s.code;FALSE&e.code;. - - If only one of depth/bpp is given, the other is set to a reasonable - (and consistent) default. - - If a driver finds that the initial &s.code;depth24flags&e.code; - it uses later results in a fb format that requires more video - memory than is available it may call this function a second time - with a different &s.code;depth24flags&e.code; setting. - - On success, the return value is &s.code;TRUE&e.code;. On failure - it prints an error message and returns &s.code;FALSE&e.code;. - - The following fields of the &s.code;ScrnInfoRec&e.code; are - initialised by this function: - - <quote> - &s.code;depth&e.code;, &s.code;bitsPerPixel&e.code;, - &s.code;display&e.code;, &s.code;imageByteOrder&e.code;, - &s.code;bitmapScanlinePad&e.code;, - &s.code;bitmapScanlineUnit&e.code;, &s.code;bitmapBitOrder&e.code;, - &s.code;numFormats&e.code;, &s.code;formats&e.code;, - &s.code;fbFormat&e.code;. - </quote> - - </quote> - - &s.code;void xf86PrintDepthBpp(scrnInfoPtr scrp)&e.code; - <quote><p> - This function can be used to print out the depth and bpp settings. - It should be called after the final call to - &s.code;xf86SetDepthBpp()&e.code;. - - </quote> - - &s.code;Bool xf86SetWeight(ScrnInfoPtr scrp, rgb weight, rgb mask)&e.code; - <quote><p> - This function sets the &s.code;weight&e.code;, &s.code;mask&e.code;, - &s.code;offset&e.code; and &s.code;rgbBits&e.code; fields of the - &s.code;ScrnInfoRec&e.code;. It would normally be called fairly - early in the &s.code;ChipPreInit()&e.code; function for - depths > 8bpp. - - It requires that the &s.code;depth&e.code; and - &s.code;display&e.code; fields of the &s.code;ScrnInfoRec&e.code; - be initialised prior to calling it. - - The parameters passed are: - - &s.code;weight&e.code; - <quote><p> - driver's preferred default weight if no other is given. - If zero, use the overall server default. - - </quote> - - &s.code;mask&e.code; - <quote><p> - Same, but for mask. - - </quote> - - It uses the command line, config file, and default values in the - correct order of precedence to determine the weight value. It - derives the mask and offset values from the weight and the defaults. - It is up to the driver to check the results to see that it supports - them. If not the &s.code;ChipPreInit()&e.code; function should - return &s.code;FALSE&e.code;. - - On success, this function prints a message showing the weight - values selected, and returns &s.code;TRUE&e.code;. - - On failure it prints an error message and returns &s.code;FALSE&e.code;. - - The following fields of the &s.code;ScrnInfoRec&e.code; are - initialised by this function: - - <quote> - &s.code;weight&e.code;, &s.code;mask&e.code;, &s.code;offset&e.code;. - </quote> - - </quote> - - &s.code;Bool xf86SetDefaultVisual(ScrnInfoPtr scrp, int visual)&e.code; - <quote><p> - This function sets the &s.code;defaultVisual&e.code; field of the - &s.code;ScrnInfoRec&e.code;. It would normally be called fairly - early from the &s.code;ChipPreInit()&e.code; function. - - It requires that the &s.code;depth&e.code; and - &s.code;display&e.code; fields of the &s.code;ScrnInfoRec&e.code; - be initialised prior to calling it. - - The parameters passed are: - - &s.code;visual&e.code; - <quote><p> - driver's preferred default visual if no other is given. - If &s.code;-1&e.code;, use the overall server default. - - </quote> - - It uses the command line, config file, and default values in the - correct order of precedence to determine the default visual value. - It is up to the driver to check the result to see that it supports - it. If not the &s.code;ChipPreInit()&e.code; function should - return &s.code;FALSE&e.code;. - - On success, this function prints a message showing the default visual - selected, and returns &s.code;TRUE&e.code;. - - On failure it prints an error message and returns &s.code;FALSE&e.code;. - - </quote> - - &s.code;Bool xf86SetGamma(ScrnInfoPtr scrp, Gamma gamma)&e.code; - <quote><p> - This function sets the &s.code;gamma&e.code; field of the - &s.code;ScrnInfoRec&e.code;. It would normally be called fairly - early from the &s.code;ChipPreInit()&e.code; function in cases - where the driver supports gamma correction. - - It requires that the &s.code;monitor&e.code; field of the - &s.code;ScrnInfoRec&e.code; be initialised prior to calling it. - - The parameters passed are: - - &s.code;gamma&e.code; - <quote><p> - driver's preferred default gamma if no other is given. - If zero (&s.code;< 0.01&e.code;), use the overall server - default. - - </quote> - - It uses the command line, config file, and default values in the - correct order of precedence to determine the gamma value. It is - up to the driver to check the results to see that it supports - them. If not the &s.code;ChipPreInit()&e.code; function should - return &s.code;FALSE&e.code;. - - On success, this function prints a message showing the gamma - value selected, and returns &s.code;TRUE&e.code;. - - On failure it prints an error message and returns &s.code;FALSE&e.code;. - - </quote> - - &s.code;void xf86SetDpi(ScrnInfoPtr pScrn, int x, int y)&e.code; - <quote><p> - This function sets the &s.code;xDpi&e.code; and &s.code;yDpi&e.code; - fields of the &s.code;ScrnInfoRec&e.code;. The driver can specify - preferred defaults by setting &s.code;x&e.code; and &s.code;y&e.code; - to non-zero values. The &s.cmd;-dpi&e.cmd; command line option - overrides all other settings. Otherwise, if the - &s.key;DisplaySize&e.key; entry is present in the screen's &k.monitor; - config file section, it is used together with the virtual size to - calculate the dpi values. This function should be called after - all the mode resolution has been done. - - </quote> - - &s.code;void xf86SetBlackWhitePixels(ScrnInfoPtr pScrn)&e.code; - <quote><p> - This functions sets the &s.code;blackPixel&e.code; and - &s.code;whitePixel&e.code; fields of the &s.code;ScrnInfoRec&e.code; - according to whether or not the &s.cmd;-flipPixels&e.cmd; command - line options is present. - - </quote> - - &s.code;const char *xf86GetVisualName(int visual)&e.code; - <quote><p> - Returns a printable string with the visual name matching the - numerical visual class provided. If the value is outside the - range of valid visual classes, &s.code;NULL&e.code; is returned. - - </quote> - </quote> - - -<sect1>Primary Mode functions -<p> - -The primary mode helper functions are those which would normally be -used by a driver, unless it has unusual requirements which cannot -be catered for the by the helpers. - - <quote><p> - &s.code;int xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, - &f.indent;char **modeNames, ClockRangePtr clockRanges, - &f.indent;int *linePitches, int minPitch, int maxPitch, - &f.indent;int pitchInc, int minHeight, int maxHeight, - &f.indent;int virtualX, int virtualY, - &f.indent;unsigned long apertureSize, - &f.indent;LookupModeFlags strategy)&e.code; - <quote><p> - This function basically selects the set of modes to use based on - those available and the various constraints. It also sets some - other related parameters. It is normally called near the end of - the &s.code;ChipPreInit()&e.code; function. - - The parameters passed to the function are: - - &s.code;availModes&e.code; - <quote><p> - List of modes available for the monitor. - - </quote> - &s.code;modeNames&e.code; - <quote><p> - List of mode names that the screen is requesting. - - </quote> - &s.code;clockRanges&e.code; - <quote><p> - A list of clock ranges allowed by the driver. Each - range includes whether interlaced or multiscan modes - are supported for that range. See below for more on - &s.code;clockRanges&e.code;. - - </quote> - &s.code;linePitches&e.code; - <quote><p> - List of line pitches supported by the driver. - This is optional and should be &s.code;NULL&e.code; when - not used. - - </quote> - &s.code;minPitch&e.code; - <quote><p> - Minimum line pitch supported by the driver. This must - be supplied when &s.code;linePitches&e.code; is - &s.code;NULL&e.code;, and is ignored otherwise. - - </quote> - &s.code;maxPitch&e.code; - <quote><p> - Maximum line pitch supported by the driver. This is - required when &s.code;minPitch&e.code; is required. - - </quote> - &s.code;pitchInc&e.code; - <quote><p> - Granularity of horizontal pitch values as supported by - the chipset. This is expressed in bits. This must be - supplied. - - </quote> - &s.code;minHeight&e.code; - <quote><p> - minimum virtual height allowed. If zero, no limit is - imposed. - - </quote> - &s.code;maxHeight&e.code; - <quote><p> - maximum virtual height allowed. If zero, no limit is - imposed. - - </quote> - &s.code;virtualX&e.code; - <quote><p> - If greater than zero, this is the virtual width value - that will be used. Otherwise, the virtual width is - chosen to be the smallest that can accommodate the modes - selected. - - </quote> - &s.code;virtualY&e.code; - <quote><p> - If greater than zero, this is the virtual height value - that will be used. Otherwise, the virtual height is - chosen to be the smallest that can accommodate the modes - selected. - - </quote> - &s.code;apertureSize&e.code; - <quote><p> - The size (in bytes) of the aperture used to access video - memory. - - </quote> - &s.code;strategy&e.code; - <quote><p> - The strategy to use when choosing from multiple modes - with the same name. The options are: - - &s.code;LOOKUP_DEFAULT&e.code; - <quote>???</quote> - &s.code;LOOKUP_BEST_REFRESH&e.code; - <quote>mode with best refresh rate</quote> - &s.code;LOOKUP_CLOSEST_CLOCK&e.code; - <quote>mode with closest matching clock</quote> - &s.code;LOOKUP_LIST_ORDER&e.code; - <quote>first usable mode in list</quote> - - The following options can also be combined (OR'ed) with - one of the above: - - &s.code;LOOKUP_CLKDIV2&e.code; - <quote>Allow halved clocks</quote> - &s.code;LOOKUP_OPTIONAL_TOLERANCES&e.code; - <quote>Allow missing horizontal sync and/or vertical refresh - ranges in the xorg.conf Monitor section</quote> - - &s.code;LOOKUP_OPTIONAL_TOLERANCES&e.code; should only be - specified when the driver can ensure all modes it generates - can sync on, or at least not damage, the monitor or digital - flat panel. Horizontal sync and/or vertical refresh ranges - specified by the user will still be honoured (and acted upon). - - </quote> - - This function requires that the following fields of the - &s.code;ScrnInfoRec&e.code; are initialised prior to calling it: - - &s.code;clock[]&e.code; - <quote>List of discrete clocks (when non-programmable)</quote> - &s.code;numClocks&e.code; - <quote>Number of discrete clocks (when non-programmable)</quote> - &s.code;progClock&e.code; - <quote>Whether the clock is programmable or not</quote> - &s.code;monitor&e.code; - <quote>Pointer to the applicable xorg.conf monitor section</quote> - &s.code;fdFormat&e.code; - <quote>Format of the screen buffer</quote> - &s.code;videoRam&e.code; - <quote>total video memory size (in bytes)</quote> - &s.code;maxHValue&e.code; - <quote>Maximum horizontal timing value allowed</quote> - &s.code;maxVValue&e.code; - <quote>Maximum vertical timing value allowed</quote> - &s.code;xInc&e.code; - <quote>Horizontal timing increment in pixels (defaults to 8)</quote> - - This function fills in the following &s.code;ScrnInfoRec&e.code; - fields: - - &s.code;modePool&e.code; - <quote><p> - A subset of the modes available to the monitor which - are compatible with the driver. - - </quote> - &s.code;modes&e.code; - <quote><p> - One mode entry for each of the requested modes, with - the status field of each filled in to indicate if - the mode has been accepted or not. This list of - modes is a circular list. - - </quote> - &s.code;virtualX&e.code; - <quote><p> - The resulting virtual width. - - </quote> - &s.code;virtualY&e.code; - <quote><p> - The resulting virtual height. - - </quote> - &s.code;displayWidth&e.code; - <quote><p> - The resulting line pitch. - - </quote> - &s.code;virtualFrom&e.code; - <quote><p> - Where the virtual size was determined from. - - </quote> - - The first stage of this function checks that the - &s.code;virtualX&e.code; and &s.code;virtualY&e.code; values - supplied (if greater than zero) are consistent with the line pitch - and &s.code;maxHeight&e.code; limitations. If not, an error - message is printed, and the return value is &s.code;-1&e.code;. - - The second stage sets up the mode pool, eliminating immediately - any modes that exceed the driver's line pitch limits, and also - the virtual width and height limits (if greater than zero). For - each mode removed an informational message is printed at verbosity - level &s.code;2&e.code;. If the mode pool ends up being empty, - a warning message is printed, and the return value is - &s.code;0&e.code;. - - The final stage is to lookup each mode name, and fill in the remaining - parameters. If an error condition is encountered, a message is - printed, and the return value is &s.code;-1&e.code;. Otherwise, - the return value is the number of valid modes found - (&s.code;0&e.code; if none are found). - - Even if the supplied mode names include duplicates, no two names will - ever match the same mode. Furthermore, if the supplied mode names do not - yield a valid mode (including the case where no names are passed at all), - the function will continue looking through the mode pool until it finds - a mode that survives all checks, or until the mode pool is exhausted. - - A message is only printed by this function when a fundamental - problem is found. It is intended that this function may be called - more than once if there is more than one set of constraints that - the driver can work within. - - If this function returns &s.code;-1&e.code;, the - &s.code;ChipPreInit()&e.code; function should return - &s.code;FALSE&e.code;. - - &s.code;clockRanges&e.code; is a linked list of clock ranges - allowed by the driver. If a mode doesn't fit in any of the defined - &s.code;clockRanges&e.code;, it is rejected. The first - &s.code;clockRange&e.code; that matches all requirements is used. - This structure needs to be initialized to NULL when allocated. - - &s.code;clockRanges&e.code; contains the following fields: - - &s.code;minClock&nl; - maxClock&e.code; - <quote><p> - The lower and upper mode clock bounds for which the rest - of the &s.code;clockRange&e.code; parameters apply. - Since these are the mode clocks, they are not scaled - with the &s.code;ClockMulFactor&e.code; and - &s.code;ClockDivFactor&e.code;. It is up to the driver - to adjust these values if they depend on the clock - scaling factors. - - </quote> - &s.code;clockIndex&e.code; - <quote><p> - (not used yet) &s.code;-1&e.code; for programmable clocks - - </quote> - &s.code;interlaceAllowed&e.code; - <quote><p> - &s.code;TRUE&e.code; if interlacing is allowed for this - range - - </quote> - &s.code;doubleScanAllowed&e.code; - <quote><p> - &s.code;TRUE&e.code; if doublescan or multiscan is allowed - for this range - - </quote> - &s.code;ClockMulFactor&nl; - ClockDivFactor&e.code; - <quote><p> - Scaling factors that are applied to the mode clocks ONLY - before selecting a clock index (when there is no - programmable clock) or a &s.code;SynthClock&e.code; - value. This is useful for drivers that support pixel - multiplexing or that need to scale the clocks because - of hardware restrictions (like sending 24bpp data to an - 8 bit RAMDAC using a tripled clock). - - Note that these parameters describe what must be done - to the mode clock to achieve the data transport clock - between graphics controller and RAMDAC. For example - for &s.code;2:1&e.code; pixel multiplexing, two pixels - are sent to the RAMDAC on each clock. This allows the - RAMDAC clock to be half of the actual pixel clock. - Hence, &s.code;ClockMulFactor=1&e.code; and - &s.code;ClockDivFactor=2&e.code;. This means that the - clock used for clock selection (ie, determining the - correct clock index from the list of discrete clocks) - or for the &s.code;SynthClock&e.code; field in case of - a programmable clock is: (&s.code;mode->Clock * - ClockMulFactor) / ClockDivFactor&e.code;. - - </quote> - &s.code;PrivFlags&e.code; - <quote><p> - This field is copied into the - &s.code;mode->PrivFlags&e.code; field when this - &s.code;clockRange&e.code; is selected by - &s.code;xf86ValidateModes()&e.code;. It allows the - driver to find out what clock range was selected, so it - knows it needs to set up pixel multiplexing or any other - range-dependent feature. This field is purely - driver-defined: it may contain flag bits, an index or - anything else (as long as it is an &s.code;INT&e.code;). - </quote> - - Note that the &s.code;mode->SynthClock&e.code; field is always - filled in by &s.code;xf86ValidateModes()&e.code;: it will contain - the ``data transport clock'', which is the clock that will have - to be programmed in the chip when it has a programmable clock, or - the clock that will be picked from the clocks list when it is not - a programmable one. Thus: - - &s.code;mode->SynthClock = - &f.indent;(mode->Clock * ClockMulFactor) / ClockDivFactor&e.code; - - </quote> - - &s.code;void xf86PruneDriverModes(ScrnInfoPtr scrp)&e.code; - <quote><p> - This function deletes modes in the modes field of the - &s.code;ScrnInfoRec&e.code; that have been marked as invalid. - This is normally run after having run - &s.code;xf86ValidateModes()&e.code; for the last time. For each - mode that is deleted, a warning message is printed out indicating - the reason for it being deleted. - - </quote> - - &s.code;void xf86SetCrtcForModes(ScrnInfoPtr scrp, int adjustFlags)&e.code; - <quote><p> - This function fills in the &s.code;Crtc*&e.code; fields for all - the modes in the &s.code;modes&e.code; field of the - &s.code;ScrnInfoRec&e.code;. The &s.code;adjustFlags&e.code; - parameter determines how the vertical CRTC values are scaled for - interlaced modes. They are halved if it is - &s.code;INTERLACE_HALVE_V&e.code;. The vertical CRTC values are - doubled for doublescan modes, and are further multiplied by the - &s.code;VScan&e.code; value. - - This function is normally called after calling - &s.code;xf86PruneDriverModes()&e.code;. - - </quote> - - &s.code;void xf86PrintModes(ScrnInfoPtr scrp)&e.code; - <quote><p> - This function prints out the virtual size setting, and the line - pitch being used. It also prints out two lines for each mode being - used. The first line includes the mode's pixel clock, horizontal sync - rate, refresh rate, and whether it is interlaced, doublescanned and/or - multi-scanned. The second line is the mode's Modeline. - - This function is normally called after calling - &s.code;xf86SetCrtcForModes()&e.code;. - - </quote> - </quote> - - -<sect1>Secondary Mode functions -<p> - -The secondary mode helper functions are functions which are normally -used by the primary mode helper functions, and which are not normally -called directly by a driver. If a driver has unusual requirements -and needs to do its own mode validation, it might be able to make -use of some of these secondary mode helper functions. - - <quote><p> - &s.code;int xf86GetNearestClock(ScrnInfoPtr scrp, int freq, Bool allowDiv2, - &f.indent;int *divider)&e.code; - <quote><p> - This function returns the index of the closest clock to the - frequency &s.code;freq&e.code; given (in kHz). It assumes that - the number of clocks is greater than zero. It requires that the - &s.code;numClocks&e.code; and &s.code;clock&e.code; fields of the - &s.code;ScrnInfoRec&e.code; are initialised. The - &s.code;allowDiv2&e.code; field determines if the clocks can be - halved. The &s.code;*divider&e.code; return value indicates - whether clock division is used when determining the clock returned. - - This function is only for non-programmable clocks. - - </quote> - - &s.code;const char *xf86ModeStatusToString(ModeStatus status)&e.code; - <quote><p> - This function converts the &s.code;status&e.code; value to a - descriptive printable string. - - </quote> - - &s.code;ModeStatus xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep, - &f.indent;ClockRangePtr clockRanges, LookupModeFlags strategy)&e.code; - <quote><p> - This function takes a pointer to a mode with the name filled in, - and looks for a mode in the &s.code;modePool&e.code; list which - matches. The parameters of the matching mode are filled in to - &s.code;*modep&e.code;. The &s.code;clockRanges&e.code; and - &s.code;strategy&e.code; parameters are as for the - &s.code;xf86ValidateModes()&e.code; function above. - - This function requires the &s.code;modePool&e.code;, - &s.code;clock[]&e.code;, &s.code;numClocks&e.code; and - &s.code;progClock&e.code; fields of the &s.code;ScrnInfoRec&e.code; - to be initialised before being called. - - The return value is &s.code;MODE_OK&e.code; if a mode was found. - Otherwise it indicates why a matching mode could not be found. - - </quote> - - &s.code;ModeStatus xf86InitialCheckModeForDriver(ScrnInfoPtr scrp, - &f.indent;DisplayModePtr mode, ClockRangePtr clockRanges, - &f.indent;LookupModeFlags strategy, int maxPitch, - &f.indent;int virtualX, int virtualY)&e.code; - <quote><p> - This function checks the passed mode against some basic driver - constraints. Apart from the ones passed explicitly, the - &s.code;maxHValue&e.code; and &s.code;maxVValue&e.code; fields of - the &s.code;ScrnInfoRec&e.code; are also used. If the - &s.code;ValidMode&e.code; field of the &s.code;ScrnInfoRec&e.code; - is set, that function is also called to check the mode. Next, the - mode is checked against the monitor's constraints. - - If the mode is consistent with all constraints, the return value - is &s.code;MODE_OK&e.code;. Otherwise the return value indicates - which constraint wasn't met. - - </quote> - - &s.code;void xf86DeleteMode(DisplayModePtr *modeList, DisplayModePtr mode)&e.code; - <quote><p> - This function deletes the &s.code;mode&e.code; given from the - &s.code;modeList&e.code;. It never prints any messages, so it is - up to the caller to print a message if required. - - </quote> - </quote> - -<sect1>Functions for handling strings and tokens -<p> - - Tables associating strings and numerical tokens combined with the - following functions provide a compact way of handling strings from - the config file, and for converting tokens into printable strings. - The table data structure is: - -<quote><verb> -typedef struct { - int token; - const char * name; -} SymTabRec, *SymTabPtr; -</verb></quote> - - A table is an initialised array of &s.code;SymTabRec&e.code;. The - tokens must be non-negative integers. Multiple names may be mapped - to a single token. The table is terminated with an element with a - &s.code;token&e.code; value of &s.code;-1&e.code; and - &s.code;NULL&e.code; for the &s.code;name&e.code;. - - - <quote><p> - &s.code;const char *xf86TokenToString(SymTabPtr table, int token)&e.code; - <quote><p> - This function returns the first string in &s.code;table&e.code; - that matches &s.code;token&e.code;. If no match is found, - &s.code;NULL&e.code; is returned (NOTE, older versions of this - function would return the string "unknown" when no match is found). - - </quote> - - &s.code;int xf86StringToToken(SymTabPtr table, const char *string)&e.code; - <quote><p> - This function returns the first token in &s.code;table&e.code; - that matches &s.code;string&e.code;. The - &s.code;xf86NameCmp()&e.code; function is used to determine the - match. If no match is found, &s.code;-1&e.code; is returned. - - </quote> - </quote> - - -<sect1>Functions for finding which config file entries to use -<p> - - These functions can be used to select the appropriate config file - entries that match the detected hardware. They are described above - in the <ref id="probe" name="Probe"> and - <ref id="avail" name="Available Functions"> sections. - - -<sect1>Probing discrete clocks on old hardware -<p> - - The &s.code;xf86GetClocks()&e.code; function may be used to assist - in finding the discrete pixel clock values on older hardware. - - - <quote><p> - &s.code;void xf86GetClocks(ScrnInfoPtr pScrn, int num, - &f.indent;Bool (*ClockFunc)(ScrnInfoPtr, int), - &f.indent;void (*ProtectRegs)(ScrnInfoPtr, Bool), - &f.indent;void (*BlankScreen)(ScrnInfoPtr, Bool), - &f.indent;int vertsyncreg, int maskval, int knownclkindex, - &f.indent;int knownclkvalue)&e.code; - <quote><p> - This function uses a comparative sampling method to measure the - discrete pixel clock values. The number of discrete clocks to - measure is given by &s.code;num&e.code;. &s.code;clockFunc&e.code; - is a function that selects the &s.code;n&e.code;'th clock. It - should also save or restore any state affected by programming the - clocks when the index passed is &s.code;CLK_REG_SAVE&e.code; or - &s.code;CLK_REG_RESTORE&e.code;. &s.code;ProtectRegs&e.code; is - a function that does whatever is required to protect the hardware - state while selecting a new clock. &s.code;BlankScreen&e.code; - is a function that blanks the screen. &s.code;vertsyncreg&e.code; - and &s.code;maskval&e.code; are the register and bitmask to - check for the presence of vertical sync pulses. - &s.code;knownclkindex&e.code; and &s.code;knownclkvalue&e.code; - are the index and value of a known clock. These are the known - references on which the comparative measurements are based. The - number of clocks probed is set in &s.code;pScrn->numClocks&e.code;, - and the probed clocks are set in the &s.code;pScrn->clock[]&e.code; - array. All of the clock values are in units of kHz. - - </quote> - - &s.code;void xf86ShowClocks(ScrnInfoPtr scrp, MessageType from)&e.code; - <quote><p> - Print out the pixel clocks &s.code;scrp->clock[]&e.code;. - &s.code;from&e.code; indicates whether the clocks were probed - or from the config file. - - </quote> - </quote> - -<sect1>Other helper functions -<p> - <quote><p> - &s.code;Bool xf86IsUnblank(int mode)&e.code; - <quote><p> - Returns &s.code;TRUE&e.code; when the screen saver mode specified - by &s.code;mode&e.code; requires the screen be unblanked, - and &s.code;FALSE&e.code; otherwise. The screen saver modes that - require blanking are &s.code;SCREEN_SAVER_ON&e.code; and - &s.code;SCREEN_SAVER_CYCLE&e.code;, and the screen saver modes that - require unblanking are &s.code;SCREEN_SAVER_OFF&e.code; and - &s.code;SCREEN_SAVER_FORCER&e.code;. Drivers may call this helper - from their &s.code;SaveScreen()&e.code; function to interpret the - screen saver modes. - - </quote> - </quote> - -<sect>The vgahw module -<p> - -The vgahw modules provides an interface for saving, restoring and -programming the standard VGA registers, and for handling VGA colourmaps. - -<sect1>Data Structures -<p> - - The public data structures used by the vgahw module are - &s.code;vgaRegRec&e.code; and &s.code;vgaHWRec&e.code;. They are - defined in &s.code;vgaHW.h.&e.code; - - -<sect1>General vgahw Functions -<p> - - <quote><p> - &s.code;Bool vgaHWGetHWRec(ScrnInfoPtr pScrn)&e.code; - <quote><p> - This function allocates a &s.code;vgaHWRec&e.code; structure, and - hooks it into the &s.code;ScrnInfoRec&e.code;'s - &s.code;privates&e.code;. Like all information hooked into the - &s.code;privates&e.code;, it is persistent, and only needs to be - allocated once per screen. This function should normally be called - from the driver's &s.code;ChipPreInit()&e.code; function. The - &s.code;vgaHWRec&e.code; is zero-allocated, and the following - fields are explicitly initialised: - - &s.code;ModeReg.DAC[]&e.code; - <quote>initialised with a default colourmap</quote> - &s.code;ModeReg.Attribute[0x11]&e.code; - <quote>initialised with the default overscan index</quote> - &s.code;ShowOverscan&e.code; - <quote>initialised according to the "ShowOverscan" option</quote> - &s.code;paletteEnabled&e.code; - <quote>initialised to FALSE</quote> - &s.code;cmapSaved&e.code; - <quote>initialised to FALSE</quote> - &s.code;pScrn&e.code; - <quote>initialised to pScrn</quote> - - In addition to the above, &s.code;vgaHWSetStdFuncs()&e.code; is - called to initialise the register access function fields with the - standard VGA set of functions. - - Once allocated, a pointer to the &s.code;vgaHWRec&e.code; can be - obtained from the &s.code;ScrnInfoPtr&e.code; with the - &s.code;VGAHWPTR(pScrn)&e.code; macro. - - </quote> - - &s.code;void vgaHWFreeHWRec(ScrnInfoPtr pScrn)&e.code; - <quote><p> - This function frees a &s.code;vgaHWRec&e.code; structure. It - should be called from a driver's &s.code;ChipFreeScreen()&e.code; - function. - - </quote> - - &s.code;Bool vgaHWSetRegCounts(ScrnInfoPtr pScrn, int numCRTC, - &f.indent;int numSequencer, int numGraphics, int numAttribute)&e.code; - <quote><p> - This function allows the number of CRTC, Sequencer, Graphics and - Attribute registers to be changed. This makes it possible for - extended registers to be saved and restored with - &s.code;vgaHWSave()&e.code; and &s.code;vgaHWRestore()&e.code;. - This function should be called after a &s.code;vgaHWRec&e.code; - has been allocated with &s.code;vgaHWGetHWRec()&e.code;. The - default values are defined in &s.code;vgaHW.h&e.code; as follows: - - <quote><verb> -#define VGA_NUM_CRTC 25 -#define VGA_NUM_SEQ 5 -#define VGA_NUM_GFX 9 -#define VGA_NUM_ATTR 21 - </verb></quote> - - </quote> - - &s.code;Bool vgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src)&e.code; - <quote><p> - This function copies the contents of the VGA saved registers in - &s.code;src&e.code; to &s.code;dst&e.code;. Note that it isn't - possible to simply do this with &s.code;memcpy()&e.code; (or - similar). This function returns &s.code;TRUE&e.code; unless there - is a problem allocating space for the &s.code;CRTC&e.code and - related fields in &s.code;dst&e.code;. - - </quote> - - &s.code;void vgaHWSetStdFuncs(vgaHWPtr hwp)&e.code; - <quote><p> - This function initialises the register access function fields of - &s.code;hwp&e.code; with the standard VGA set of functions. This - is called by &s.code;vgaHWGetHWRec()&e.code;, so there is usually - no need to call this explicitly. The register access functions - are described below. If the registers are shadowed in some other - port I/O space (for example a PCI I/O region), these functions - can be used to access the shadowed registers if - &s.code;hwp->PIOOffset&e.code; is initialised with - &s.code;offset&e.code;, calculated in such a way that when the - standard VGA I/O port value is added to it the correct offset into - the PIO area results. This value is initialised to zero in - &s.code;vgaHWGetHWRec()&e.code;. (Note: the PIOOffset functionality - is present in XFree86 4.1.0 and later.) - - </quote> - - &s.code;void vgaHWSetMmioFuncs(vgaHWPtr hwp, CARD8 *base, int offset)&e.code; - <quote><p> - This function initialised the register access function fields of - hwp with a generic MMIO set of functions. - &s.code;hwp->MMIOBase&e.code; is initialised with - &s.code;base&e.code;, which must be the virtual address that the - start of MMIO area is mapped to. &s.code;hwp->MMIOOffset&e.code; - is initialised with &s.code;offset&e.code;, which must be calculated - in such a way that when the standard VGA I/O port value is added - to it the correct offset into the MMIO area results. That means - that these functions are only suitable when the VGA I/O ports are - made available in a direct mapping to the MMIO space. If that is - not the case, the driver will need to provide its own register - access functions. The register access functions are described - below. - - </quote> - - &s.code;Bool vgaHWMapMem(ScrnInfoPtr pScrn)&e.code; - <quote><p> - This function maps the VGA memory window. It requires that the - &s.code;vgaHWRec&e.code; be allocated. If a driver requires - non-default &s.code;MapPhys&e.code; or &s.code;MapSize&e.code; - settings (the physical location and size of the VGA memory window) - then those fields of the &s.code;vgaHWRec&e.code; must be initialised - before calling this function. Otherwise, this function initialiases - the default values of &s.code;0xA0000&e.code; for - &s.code;MapPhys&e.code; and &s.code;(64 * 1024)&e.code; for - &s.code;MapSize&e.code;. This function must be called before - attempting to save or restore the VGA state. If the driver doesn't - call it explicitly, the &s.code;vgaHWSave()&e.code; and - &s.code;vgaHWRestore()&e.code; functions may call it if they need - to access the VGA memory (in which case they will also call - &s.code;vgaHWUnmapMem()&e.code; to unmap the VGA memory before - exiting). - - </quote> - - &s.code;void vgaHWUnmapMem(ScrnInfoPtr pScrn)&e.code; - <quote><p> - This function unmaps the VGA memory window. It must only be called - after the memory has been mapped. The &s.code;Base&e.code; field - of the &s.code;vgaHWRec&e.code; field is set to &s.code;NULL&e.code; - to indicate that the memory is no longer mapped. - - </quote> - - &s.code;void vgaHWGetIOBase(vgaHWPtr hwp)&e.code; - <quote><p> - This function initialises the &s.code;IOBase&e.code; field of the - &s.code;vgaHWRec&e.code;. This function must be called before - using any other functions that access the video hardware. - - A macro &s.code;VGAHW_GET_IOBASE()&e.code; is also available in - &s.code;vgaHW.h&e.code; that returns the I/O base, and this may - be used when the vgahw module is not loaded (for example, in the - &s.code;ChipProbe()&e.code; function). - - </quote> - - &s.code;void vgaHWUnlock(vgaHWPtr hwp)&e.code; - <quote><p> - This function unlocks the VGA &s.code;CRTC[0-7]&e.code; registers, - and must be called before attempting to write to those registers. - - </quote> - - &s.code;void vgaHWLock(vgaHWPtr hwp)&e.code; - <quote><p> - This function locks the VGA &s.code;CRTC[0-7]&e.code; registers. - - </quote> - - &s.code;void vgaHWEnable(vgaHWPtr hwp)&e.code; - <quote><p> - This function enables the VGA subsystem. (Note, this function is - present in XFree86 4.1.0 and later.). - - </quote> - - &s.code;void vgaHWDisable(vgaHWPtr hwp)&e.code; - <quote><p> - This function disables the VGA subsystem. (Note, this function is - present in XFree86 4.1.0 and later.). - - </quote> - - &s.code;void vgaHWSave(ScrnInfoPtr pScrn, vgaRegPtr save, int flags)&e.code; - <quote><p> - This function saves the VGA state. The state is written to the - &s.code;vgaRegRec&e.code; pointed to by &s.code;save&e.code;. - &s.code;flags&e.code; is set to one or more of the following flags - ORed together: - - &s.code;VGA_SR_MODE&e.code; - <quote>the mode setting registers are saved</quote> - &s.code;VGA_SR_FONTS&e.code; - <quote>the text mode font/text data is saved</quote> - &s.code;VGA_SR_CMAP&e.code; - <quote>the colourmap (LUT) is saved</quote> - &s.code;VGA_SR_ALL&e.code; - <quote>all of the above are saved</quote> - - The &s.code;vgaHWRec&e.code; and its &s.code;IOBase&e.code; fields - must be initialised before this function is called. If - &s.code;VGA_SR_FONTS&e.code; is set in &s.code;flags&e.code;, the - VGA memory window must be mapped. If it isn't then - &s.code;vgaHWMapMem()&e.code; will be called to map it, and - &s.code;vgaHWUnmapMem()&e.code; will be called to unmap it - afterwards. &s.code;vgaHWSave()&e.code; uses the three functions - below in the order &s.code;vgaHWSaveColormap()&e.code;, - &s.code;vgaHWSaveMode()&e.code;, &s.code;vgaHWSaveFonts()&e.code; to - carry out the different save phases. It is undecided at this - stage whether they will remain part of the vgahw module's public - interface or not. - - </quote> - - &s.code;void vgaHWSaveMode(ScrnInfoPtr pScrn, vgaRegPtr save)&e.code; - <quote><p> - This function saves the VGA mode registers. They are saved to - the &s.code;vgaRegRec&e.code; pointed to by &s.code;save&e.code;. - The registers saved are: - - <quote> - &s.code;MiscOut&nl; - CRTC[0-0x18]&nl; - Attribute[0-0x14]&nl; - Graphics[0-8]&nl; - Sequencer[0-4]&e.code; - </quote> - - The number of registers actually saved may be modified by a prior call - to &s.code;vgaHWSetRegCounts()&e.code;. - - </quote> - - &s.code;void vgaHWSaveFonts(ScrnInfoPtr pScrn, vgaRegPtr save)&e.code; - <quote><p> - This function saves the text mode font and text data held in the - video memory. If called while in a graphics mode, no save is - done. The VGA memory window must be mapped with - &s.code;vgaHWMapMem()&e.code; before to calling this function. - - On some platforms, one or more of the font/text plane saves may be - no-ops. This is the case when the platform's VC driver already - takes care of this. - - </quote> - - &s.code;void vgaHWSaveColormap(ScrnInfoPtr pScrn, vgaRegPtr save)&e.code; - <quote><p> - This function saves the VGA colourmap (LUT). Before saving it, it - attempts to verify that the colourmap is readable. In rare cases - where it isn't readable, a default colourmap is saved instead. - - </quote> - - &s.code;void vgaHWRestore(ScrnInfoPtr pScrn, vgaRegPtr restore, int flags)&e.code; - <quote><p> - This function programs the VGA state. The state programmed is - that contained in the &s.code;vgaRegRec&e.code; pointed to by - &s.code;restore&e.code;. &s.code;flags&e.code; is the same - as described above for the &s.code;vgaHWSave()&e.code; function. - - The &s.code;vgaHWRec&e.code; and its &s.code;IOBase&e.code; fields - must be initialised before this function is called. If - &s.code;VGA_SR_FONTS&e.code; is set in &s.code;flags&e.code;, the - VGA memory window must be mapped. If it isn't then - &s.code;vgaHWMapMem()&e.code; will be called to map it, and - &s.code;vgaHWUnmapMem()&e.code; will be called to unmap it - afterwards. &s.code;vgaHWRestore()&e.code; uses the three functions - below in the order &s.code;vgaHWRestoreFonts()&e.code;, - &s.code;vgaHWRestoreMode()&e.code;, - &s.code;vgaHWRestoreColormap()&e.code; to carry out the different - restore phases. It is undecided at this stage whether they will - remain part of the vgahw module's public interface or not. - - </quote> - - &s.code;void vgaHWRestoreMode(ScrnInfoPtr pScrn, vgaRegPtr restore)&e.code; - <quote><p> - This function restores the VGA mode registers. They are restored - from the data in the &s.code;vgaRegRec&e.code; pointed to by - &s.code;restore&e.code;. The registers restored are: - - <quote> - &s.code;MiscOut&nl; - CRTC[0-0x18]&nl; - Attribute[0-0x14]&nl; - Graphics[0-8]&nl; - Sequencer[0-4]&e.code; - </quote> - - The number of registers actually restored may be modified by a prior call - to &s.code;vgaHWSetRegCounts()&e.code;. - - </quote> - - &s.code;void vgaHWRestoreFonts(ScrnInfoPtr pScrn, vgaRegPtr restore)&e.code; - <quote><p> - This function restores the text mode font and text data to the - video memory. The VGA memory window must be mapped with - &s.code;vgaHWMapMem()&e.code; before to calling this function. - - On some platforms, one or more of the font/text plane restores - may be no-ops. This is the case when the platform's VC driver - already takes care of this. - - </quote> - - &s.code;void vgaHWRestoreColormap(ScrnInfoPtr pScrn, vgaRegPtr restore)&e.code; - <quote><p> - This function restores the VGA colourmap (LUT). - - </quote> - - &s.code;void vgaHWInit(ScrnInfoPtr pScrn, DisplayModePtr mode)&e.code; - <quote><p> - This function fills in the &s.code;vgaHWRec&e.code;'s - &s.code;ModeReg&e.code; field with the values appropriate for - programming the given video mode. It requires that the - &s.code;ScrnInfoRec&e.code;'s &s.code;depth&e.code; field is - initialised, which determines how the registers are programmed. - - </quote> - - &s.code;void vgaHWSeqReset(vgaHWPtr hwp, Bool start)&e.code; - <quote><p> - Do a VGA sequencer reset. If start is &s.code;TRUE&e.code;, the - reset is started. If start is &s.code;FALSE&e.code;, the reset - is ended. - - </quote> - - &s.code;void vgaHWProtect(ScrnInfoPtr pScrn, Bool on)&e.code; - <quote><p> - This function protects VGA registers and memory from corruption - during loads. It is typically called with on set to - &s.code;TRUE&e.code; before programming, and with on set to - &s.code;FALSE&e.code; after programming. - - </quote> - - &s.code;Bool vgaHWSaveScreen(ScreenPtr pScreen, int mode)&e.code; - <quote><p> - This function blanks and unblanks the screen. It is blanked when - &s.code;mode&e.code; is &s.code;SCREEN_SAVER_ON&e.code; or - &s.code;SCREEN_SAVER_CYCLE&e.code;, and unblanked when - &s.code;mode&e.code; is &s.code;SCREEN_SAVER_OFF&e.code; or - &s.code;SCREEN_SAVER_FORCER&e.code;. - - </quote> - - &s.code;void vgaHWBlankScreen(ScrnInfoPtr pScrn, Bool on)&e.code; - <quote><p> - This function blanks and unblanks the screen. It is blanked when - &s.code;on&e.code; is &s.code;FALSE&e.code;, and unblanked when - &s.code;on&e.code; is &s.code;TRUE&e.code;. This function is - provided for use in cases where the &s.code;ScrnInfoRec&e.code; - can't be derived from the &s.code;ScreenRec&e.code; (while probing - for clocks, for example). - - </quote> - </quote> - -<sect1>VGA Colormap Functions -<p> - - The vgahw module uses the standard colormap support (see the - <ref id="cmap" name="Colormap Handling"> section. This is initialised - with the following function: - - <quote> - &s.code;Bool vgaHWHandleColormaps(ScreenPtr pScreen)&e.code; - </quote> - - -<sect1>VGA Register Access Functions -<p> - - The vgahw module abstracts access to the standard VGA registers by - using a set of functions held in the &s.code;vgaHWRec&e.code;. When - the &s.code;vgaHWRec&e.code; is created these function pointers are - initialised with the set of standard VGA I/O register access functions. - In addition to these, the vgahw module includes a basic set of MMIO - register access functions, and the &s.code;vgaHWRec&e.code; function - pointers can be initialised to these by calling the - &s.code;vgaHWSetMmioFuncs()&e.code; function described above. Some - drivers/platforms may require a different set of functions for VGA - access. The access functions are described here. - - - <quote><p> - &s.code;void writeCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)&e.code; - <quote><p> - Write &s.code;value&e.code; to CRTC register &s.code;index&e.code;. - - </quote> - - &s.code;CARD8 readCrtc(vgaHWPtr hwp, CARD8 index)&e.code; - <quote><p> - Return the value read from CRTC register &s.code;index&e.code;. - - </quote> - - &s.code;void writeGr(vgaHWPtr hwp, CARD8 index, CARD8 value)&e.code; - <quote><p> - Write &s.code;value&e.code; to Graphics Controller register - &s.code;index&e.code;. - - </quote> - - &s.code;CARD8 readGR(vgaHWPtr hwp, CARD8 index)&e.code; - <quote><p> - Return the value read from Graphics Controller register - &s.code;index&e.code;. - - </quote> - - &s.code;void writeSeq(vgaHWPtr hwp, CARD8 index, CARD8, value)&e.code; - <quote><p> - Write &s.code;value&e.code; to Sequencer register - &s.code;index&e.code;. - - </quote> - - &s.code;CARD8 readSeq(vgaHWPtr hwp, CARD8 index)&e.code; - <quote><p> - Return the value read from Sequencer register &s.code;index&e.code;. - - </quote> - - &s.code;void writeAttr(vgaHWPtr hwp, CARD8 index, CARD8, value)&e.code; - <quote><p> - Write &s.code;value&e.code; to Attribute Controller register - &s.code;index&e.code;. When writing out the index value this - function should set bit 5 (&s.code;0x20&e.code;) according to the - setting of &s.code;hwp->paletteEnabled&e.code; in order to - preserve the palette access state. It should be cleared when - &s.code;hwp->paletteEnabled&e.code; is &s.code;TRUE&e.code; - and set when it is &s.code;FALSE&e.code;. - - </quote> - - &s.code;CARD8 readAttr(vgaHWPtr hwp, CARD8 index)&e.code; - <quote><p> - Return the value read from Attribute Controller register - &s.code;index&e.code;. When writing out the index value this - function should set bit 5 (&s.code;0x20&e.code;) according to the - setting of &s.code;hwp->paletteEnabled&e.code; in order to - preserve the palette access state. It should be cleared when - &s.code;hwp->paletteEnabled&e.code; is &s.code;TRUE&e.code; - and set when it is &s.code;FALSE&e.code;. - - </quote> - - &s.code;void writeMiscOut(vgaHWPtr hwp, CARD8 value)&e.code; - <quote><p> - Write `&s.code;value&e.code;' to the Miscellaneous Output register. - - </quote> - - &s.code;CARD8 readMiscOut(vgwHWPtr hwp)&e.code; - <quote><p> - Return the value read from the Miscellaneous Output register. - - </quote> - - &s.code;void enablePalette(vgaHWPtr hwp)&e.code; - <quote><p> - Clear the palette address source bit in the Attribute Controller - index register and set &s.code;hwp->paletteEnabled&e.code; to - &s.code;TRUE&e.code;. - - </quote> - - &s.code;void disablePalette(vgaHWPtr hwp)&e.code; - <quote><p> - Set the palette address source bit in the Attribute Controller - index register and set &s.code;hwp->paletteEnabled&e.code; to - &s.code;FALSE&e.code;. - - </quote> - - &s.code;void writeDacMask(vgaHWPtr hwp, CARD8 value)&e.code; - <quote><p> - Write &s.code;value&e.code; to the DAC Mask register. - - </quote> - - &s.code;CARD8 readDacMask(vgaHWptr hwp)&e.code; - <quote><p> - Return the value read from the DAC Mask register. - - </quote> - - &s.code;void writeDacReadAddress(vgaHWPtr hwp, CARD8 value)&e.code; - <quote><p> - Write &s.code;value&e.code; to the DAC Read Address register. - - </quote> - - &s.code;void writeDacWriteAddress(vgaHWPtr hwp, CARD8 value)&e.code; - <quote><p> - Write &s.code;value&e.code; to the DAC Write Address register. - - </quote> - - &s.code;void writeDacData(vgaHWPtr hwp, CARD8 value)&e.code; - <quote><p> - Write &s.code;value&e.code; to the DAC Data register. - - </quote> - - &s.code;CARD8 readDacData(vgaHWptr hwp)&e.code; - <quote><p> - Return the value read from the DAC Data register. - - </quote> - - &s.code;CARD8 readEnable(vgaHWptr hwp)&e.code; - <quote><p> - Return the value read from the VGA Enable register. (Note: This - function is present in XFree86 4.1.0 and later.) - - </quote> - - &s.code;void writeEnable(vgaHWPtr hwp, CARD8 value)&e.code; - <quote><p> - Write &s.code;value&e.code; to the VGA Enable register. (Note: This - function is present in XFree86 4.1.0 and later.) - - </quote> - </quote> - -<sect>Some notes about writing a driver<label id="sample"> -<p> - -<em>NOTE: some parts of this are not up to date</em> - -The following is an outline for writing a basic unaccelerated driver -for a PCI video card with a linear mapped framebuffer, and which has a -VGA core. It is includes some general information that is relevant to -most drivers (even those which don't fit that basic description). - -The information here is based on the initial conversion of the Matrox -Millennium driver to the ``new design''. For a fleshing out and sample -implementation of some of the bits outlined here, refer to that driver. -Note that this is an example only. The approach used here will not be -appropriate for all drivers. - -Each driver must reserve a unique driver name, and a string that is used -to prefix all of its externally visible symbols. This is to avoid name -space clashes when loading multiple drivers. The examples here are for -the ``ZZZ'' driver, which uses the ``ZZZ'' or ``zzz'' prefix for its externally -visible symbols. - - -<sect1>Include files -<p> - - All drivers normally include the following headers: - <quote> - &s.code;"xf86.h"&nl; - "xf86_OSproc.h"&nl; - "xf86_ansic.h"&nl; - "xf86Resources.h"&e.code; - </quote> - Wherever inb/outb (and related things) are used the following should be - included: - <quote> - &s.code;"compiler.h"&e.code; - </quote> - Note: in drivers, this must be included after &s.code;"xf86_ansic.h"&e.code;. - - Drivers that need to access PCI vendor/device definitions need this: - <quote> - &s.code;"xf86PciInfo.h"&e.code; - </quote> - - Drivers that need to access the PCI config space need this: - <quote> - &s.code;"xf86Pci.h"&e.code; - </quote> - - Drivers using the mi banking wrapper need: - - <quote> - &s.code;"mibank.h"&e.code; - </quote> - - Drivers that initialise a SW cursor need this: - <quote> - &s.code;"mipointer.h"&e.code; - </quote> - - All drivers implementing backing store need this: - <quote> - &s.code;"mibstore.h"&e.code; - </quote> - - All drivers using the mi colourmap code need this: - <quote> - &s.code;"micmap.h"&e.code; - </quote> - - If a driver uses the vgahw module, it needs this: - <quote> - &s.code;"vgaHW.h"&e.code; - </quote> - - Drivers supporting VGA or Hercules monochrome screens need: - <quote> - &s.code;"xf1bpp.h"&e.code; - </quote> - - Drivers supporting VGA or EGC 16-colour screens need: - <quote> - &s.code;"xf4bpp.h"&e.code; - </quote> - - Drivers using cfb need: - <quote> - &s.code;#define PSZ 8&nl; - #include "cfb.h"&nl; - #undef PSZ&e.code; - </quote> - - Drivers supporting bpp 16, 24 or 32 with cfb need one or more of: - <quote> - &s.code;"cfb16.h"&nl; - "cfb24.h"&nl; - "cfb32.h"&e.code; - </quote> - - The driver's own header file: - <quote> - &s.code;"zzz.h"&e.code; - </quote> - - Drivers must NOT include the following: - - <quote> - &s.code;"xf86Priv.h"&nl; - "xf86Privstr.h"&nl; - "xf86_libc.h"&nl; - "xf86_OSlib.h"&nl; - "Xos.h"&e.code;&nl; - any OS header - </quote> - - -<sect1>Data structures and initialisation -<p> - -<itemize> - <item>The following macros should be defined: - <code> -#define VERSION <version-as-an-int> -#define ZZZ_NAME "ZZZ" /* the name used to prefix messages */ -#define ZZZ_DRIVER_NAME "zzz" /* the driver name as used in config file */ -#define ZZZ_MAJOR_VERSION <int> -#define ZZZ_MINOR_VERSION <int> -#define ZZZ_PATCHLEVEL <int> - </code> -<p> - NOTE: &s.code;ZZZ_DRIVER_NAME&e.code; should match the name of the - driver module without things like the "lib" prefix, the "_drv" suffix - or filename extensions. -<p> - - <item>A DriverRec must be defined, which includes the functions required - at the pre-probe phase. The name of this DriverRec must be an - upper-case version of ZZZ_DRIVER_NAME (for the purposes of static - linking). -<p> - <code> -DriverRec ZZZ = { - VERSION, - ZZZ_DRIVER_NAME, - ZZZIdentify, - ZZZProbe, - ZZZAvailableOptions, - NULL, - 0 -}; - </code> - - <item>Define list of supported chips and their matching ID: -<p> - <code> -static SymTabRec ZZZChipsets[] = { - { PCI_CHIP_ZZZ1234, "zzz1234a" }, - { PCI_CHIP_ZZZ5678, "zzz5678a" }, - { -1, NULL } -}; - </code> -<p> - The token field may be any integer value that the driver may use to - uniquely identify the supported chipsets. For drivers that support - only PCI devices using the PCI device IDs might be a natural choice, - but this isn't mandatory. For drivers that support both PCI and other - devices (like ISA), some other ID should probably used. When other - IDs are used as the tokens it is recommended that the names be - defined as an &s.code;enum&e.code; type. -<p> - <item>If the driver uses the &s.code;xf86MatchPciInstances(&e.code;) - helper (recommended for drivers that support PCI cards) a list that - maps PCI IDs to chip IDs and fixed resources must be defined: -<p> - <code> -static PciChipsets ZZZPciChipsets[] = { - { PCI_CHIP_ZZZ1234, PCI_CHIP_ZZZ1234, RES_SHARED_VGA }, - { PCI_CHIP_ZZZ5678, PCI_CHIP_ZZZ5678, RES_SHARED_VGA }, - { -1, -1, RES_UNDEFINED } -} - </code> -<p> - <item>Define the &s.code;XF86ModuleVersionInfo&e.code; struct for the - driver. This is required for the dynamically loaded version: -<p> - <code> -static XF86ModuleVersionInfo zzzVersRec = -{ - "zzz", - MODULEVENDORSTRING, - MODINFOSTRING1, - MODINFOSTRING2, - XF86_VERSION_CURRENT, - ZZZ_MAJOR_VERSION, ZZZ_MINOR_VERSION, ZZZ_PATCHLEVEL, - ABI_CLASS_VIDEODRV, - ABI_VIDEODRV_VERSION, - MOD_CLASS_VIDEODRV, - {0,0,0,0} -}; - </code> -<p> - <item>Define a data structure to hold the driver's screen-specific data. - This must be used instead of global variables. This would be defined - in the &s.code;"zzz.h"&e.code; file, something like: -<p> - <code> -typedef struct { - type1 field1; - type2 field2; - int fooHack; - Bool pciRetry; - Bool noAccel; - Bool hwCursor; - CloseScreenProcPtr CloseScreen; - OptionInfoPtr Options; - ... -} ZZZRec, *ZZZPtr; - </code> -<p> - <item>Define the list of config file Options that the driver accepts. For - consistency between drivers those in the list of ``standard'' options - should be used where appropriate before inventing new options. -<p> - <code> -typedef enum { - OPTION_FOO_HACK, - OPTION_PCI_RETRY, - OPTION_HW_CURSOR, - OPTION_NOACCEL -} ZZZOpts; - -static const OptionInfoRec ZZZOptions[] = { - { OPTION_FOO_HACK, "FooHack", OPTV_INTEGER, {0}, FALSE }, - { OPTION_PCI_RETRY, "PciRetry", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, - { -1, NULL, OPTV_NONE, {0}, FALSE } -}; - </code> -<p> -</itemize> - -<sect1>Functions -<p> - - -<sect2>SetupProc -<p> - - For dynamically loaded modules, a &s.code;ModuleData&e.code; - variable is required. It is should be the name of the driver - prepended to "ModuleData". A &s.code;Setup()&e.code; function is - also required, which calls &s.code;xf86AddDriver()&e.code; to add - the driver to the main list of drivers. - - <code> -static MODULESETUPPROTO(zzzSetup); - -XF86ModuleData zzzModuleData = { &zzzVersRec, zzzSetup, NULL }; - -static pointer -zzzSetup(pointer module, pointer opts, int *errmaj, int *errmin) -{ - static Bool setupDone = FALSE; - - /* This module should be loaded only once, but check to be sure. */ - - if (!setupDone) { - /* - * Modules that this driver always requires may be loaded - * here by calling LoadSubModule(). - */ - - setupDone = TRUE; - xf86AddDriver(&MGA, module, 0); - - /* - * The return value must be non-NULL on success even though - * there is no TearDownProc. - */ - return (pointer)1; - } else { - if (errmaj) *errmaj = LDR_ONCEONLY; - return NULL; - } -} - </code> - -<sect2>GetRec, FreeRec -<p> - - A function is usually required to allocate the driver's - screen-specific data structure and hook it into the - &s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; field. - The &s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; is - initialised to &s.code;NULL&e.code;, so it is easy to check if the - initialisation has already been done. After allocating it, initialise - the fields. By using &s.code;xnfcalloc()&e.code; to do the allocation - it is zeroed, and if the allocation fails the server exits. -<p> - NOTE: - When allocating structures from inside the driver which are defined - on the common level it is important to initialize the structure to - zero. - Only this guarantees that the server remains source compatible to - future changes in common level structures. - - <code> -static Bool -ZZZGetRec(ScrnInfoPtr pScrn) -{ - if (pScrn->driverPrivate != NULL) - return TRUE; - pScrn->driverPrivate = xnfcalloc(sizeof(ZZZRec), 1); - /* Initialise as required */ - ... - return TRUE; -} - </code> - - Define a macro in &s.code;"zzz.h"&e.code; which gets a pointer to - the &s.code;ZZZRec&e.code; when given &s.code;pScrn&e.code;: - - <code> -#define ZZZPTR(p) ((ZZZPtr)((p)->driverPrivate)) - </code> - - Define a function to free the above, setting it to &s.code;NULL&e.code; - once it has been freed: - - <code> -static void -ZZZFreeRec(ScrnInfoPtr pScrn) -{ - if (pScrn->driverPrivate == NULL) - return; - xfree(pScrn->driverPrivate); - pScrn->driverPrivate = NULL; -} - </code> - -<sect2>Identify -<p> - - Define the &s.code;Identify()&e.code; function. It is run before - the Probe, and typically prints out an identifying message, which - might include the chipsets it supports. This function is mandatory: - - <code> -static void -ZZZIdentify(int flags) -{ - xf86PrintChipsets(ZZZ_NAME, "driver for ZZZ Tech chipsets", - ZZZChipsets); -} - </code> - -<sect2>Probe -<p> - - Define the &s.code;Probe()&e.code; function. The purpose of this - is to find all instances of the hardware that the driver supports, - and for the ones not already claimed by another driver, claim the - slot, and allocate a &s.code;ScrnInfoRec&e.code;. This should be - a minimal probe, and it should under no circumstances leave the - state of the hardware changed. Because a device is found, don't - assume that it will be used. Don't do any initialisations other - than the required &s.code;ScrnInfoRec&e.code; initialisations. - Don't allocate any new data structures. - - This function is mandatory. - - NOTE: The &s.code;xf86DrvMsg()&e.code; functions cannot be used from - the Probe. - - <code> -static Bool -ZZZProbe(DriverPtr drv, int flags) -{ - Bool foundScreen = FALSE; - int numDevSections, numUsed; - GDevPtr *devSections; - int *usedChips; - int i; - - /* - * Find the config file Device sections that match this - * driver, and return if there are none. - */ - if ((numDevSections = xf86MatchDevice(ZZZ_DRIVER_NAME, - &devSections)) <= 0) { - return FALSE; - } - - /* - * Since this is a PCI card, "probing" just amounts to checking - * the PCI data that the server has already collected. If there - * is none, return. - * - * Although the config file is allowed to override things, it - * is reasonable to not allow it to override the detection - * of no PCI video cards. - * - * The provided xf86MatchPciInstances() helper takes care of - * the details. - */ - /* test if PCI bus present */ - if (xf86GetPciVideoInfo()) { - - numUsed = xf86MatchPciInstances(ZZZ_NAME, PCI_VENDOR_ZZZ, - ZZZChipsets, ZZZPciChipsets, devSections, - numDevSections, drv, &usedChips); - - for (i = 0; i < numUsed; i++) { - ScrnInfoPtr pScrn = NULL; - if ((pScrn = xf86ConfigPciEntity(pScrn, flags, usedChips[i], - ZZZPciChipsets, NULL, NULL, - NULL, NULL, NULL))) { - /* Allocate a ScrnInfoRec */ - pScrn->driverVersion = VERSION; - pScrn->driverName = ZZZ_DRIVER_NAME; - pScrn->name = ZZZ_NAME; - pScrn->Probe = ZZZProbe; - pScrn->PreInit = ZZZPreInit; - pScrn->ScreenInit = ZZZScreenInit; - pScrn->SwitchMode = ZZZSwitchMode; - pScrn->AdjustFrame = ZZZAdjustFrame; - pScrn->EnterVT = ZZZEnterVT; - pScrn->LeaveVT = ZZZLeaveVT; - pScrn->FreeScreen = ZZZFreeScreen; - pScrn->ValidMode = ZZZValidMode; - foundScreen = TRUE; - /* add screen to entity */ - } - } - xfree(usedChips); - } - -#ifdef HAS_ISA_DEVS - /* - * If the driver supports ISA hardware, the following block - * can be included too. - */ - numUsed = xf86MatchIsaInstances(ZZZ_NAME, ZZZChipsets, - ZZZIsaChipsets, drv, ZZZFindIsaDevice, - devSections, numDevSections, &usedChips); - for (i = 0; i < numUsed; i++) { - ScrnInfoPtr pScrn = NULL; - if ((pScrn = xf86ConfigIsaEntity(pScrn, flags, usedChips[i], - ZZZIsaChipsets, NULL, NULL, NULL, - NULL, NULL))) { - pScrn->driverVersion = VERSION; - pScrn->driverName = ZZZ_DRIVER_NAME; - pScrn->name = ZZZ_NAME; - pScrn->Probe = ZZZProbe; - pScrn->PreInit = ZZZPreInit; - pScrn->ScreenInit = ZZZScreenInit; - pScrn->SwitchMode = ZZZSwitchMode; - pScrn->AdjustFrame = ZZZAdjustFrame; - pScrn->EnterVT = ZZZEnterVT; - pScrn->LeaveVT = ZZZLeaveVT; - pScrn->FreeScreen = ZZZFreeScreen; - pScrn->ValidMode = ZZZValidMode; - foundScreen = TRUE; - } - } - xfree(usedChips); -#endif /* HAS_ISA_DEVS */ - - xfree(devSections); - return foundScreen; - </code> - -<sect2>AvailableOptions -<p> - - Define the &s.code;AvailableOptions()&e.code; function. The purpose - of this is to return the available driver options back to the - -configure option, so that an xorg.conf file can be built and the - user can see which options are available for them to use. - -<sect2>PreInit -<p> - - Define the &s.code;PreInit()&e.code; function. The purpose of - this is to find all the information required to determine if the - configuration is usable, and to initialise those parts of the - &s.code;ScrnInfoRec&e.code; that can be set once at the beginning - of the first server generation. The information should be found in - the least intrusive way possible. - - This function is mandatory. - - NOTES: - <enum> - <item>The &s.code;PreInit()&e.code; function is only called once - during the life of the X server (at the start of the first - generation). - - <item>Data allocated here must be of the type that persists for - the life of the X server. This means that data that hooks into - the &s.code;ScrnInfoRec&e.code;'s &s.code;privates&e.code; - field should be allocated here, but data that hooks into the - &s.code;ScreenRec&e.code;'s &s.code;devPrivates&e.code; field - should not be allocated here. The &s.code;driverPrivate&e.code; - field should also be allocated here. - - <item>Although the &s.code;ScrnInfoRec&e.code; has been allocated - before this function is called, the &s.code;ScreenRec&e.code; - has not been allocated. That means that things requiring it - cannot be used in this function. - - <item>Very little of the &s.code;ScrnInfoRec&e.code; has been - initialised when this function is called. It is important to - get the order of doing things right in this function. - - </enum> - - <code> -static Bool -ZZZPreInit(ScrnInfoPtr pScrn, int flags) -{ - /* Fill in the monitor field */ - pScrn->monitor = pScrn->confScreen->monitor; - - /* - * If using the vgahw module, it will typically be loaded - * here by calling xf86LoadSubModule(pScrn, "vgahw"); - */ - - /* - * Set the depth/bpp. Use the globally preferred depth/bpp. If the - * driver has special default depth/bpp requirements, the defaults should - * be specified here explicitly. - * We support both 24bpp and 32bpp framebuffer layouts. - * This sets pScrn->display also. - */ - if (!xf86SetDepthBpp(pScrn, 0, 0, 0, - Support24bppFb | Support32bppFb)) { - return FALSE; - } else { - if (depth/bpp isn't one we support) { - print error message; - return FALSE; - } - } - /* Print out the depth/bpp that was set */ - xf86PrintDepthBpp(pScrn); - - /* Set bits per RGB for 8bpp */ - if (pScrn->depth <= 8) { - /* Take into account a dac_6_bit option here */ - pScrn->rgbBits = 6 or 8; - } - - /* - * xf86SetWeight() and xf86SetDefaultVisual() must be called - * after pScrn->display is initialised. - */ - - /* Set weight/mask/offset for depth > 8 */ - if (pScrn->depth > 8) { - if (!xf86SetWeight(pScrn, defaultWeight, defaultMask)) { - return FALSE; - } else { - if (weight isn't one we support) { - print error message; - return FALSE; - } - } - } - - /* Set the default visual. */ - if (!xf86SetDefaultVisual(pScrn, -1)) { - return FALSE; - } else { - if (visual isn't one we support) { - print error message; - return FALSE; - } - } - - /* If the driver supports gamma correction, set the gamma. */ - if (!xf86SetGamma(pScrn, default_gamma)) { - return FALSE; - } - - /* This driver uses a programmable clock */ - pScrn->progClock = TRUE; - - /* Allocate the ZZZRec driverPrivate */ - if (!ZZZGetRec(pScrn)) { - return FALSE; - } - - pZzz = ZZZPTR(pScrn); - - /* Collect all of the option flags (fill in pScrn->options) */ - xf86CollectOptions(pScrn, NULL); - - /* - * Process the options based on the information in ZZZOptions. - * The results are written to pZzz->Options. If all of the options - * processing is done within this function a local variable "options" - * can be used instead of pZzz->Options. - */ - if (!(pZzz->Options = xalloc(sizeof(ZZZOptions)))) - return FALSE; - (void)memcpy(pZzz->Options, ZZZOptions, sizeof(ZZZOptions)); - xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pZzz->Options); - - /* - * Set various fields of ScrnInfoRec and/or ZZZRec based on - * the options found. - */ - from = X_DEFAULT; - pZzz->hwCursor = FALSE; - if (xf86IsOptionSet(pZzz->Options, OPTION_HW_CURSOR)) { - from = X_CONFIG; - pZzz->hwCursor = TRUE; - } - xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", - pZzz->hwCursor ? "HW" : "SW"); - if (xf86IsOptionSet(pZzz->Options, OPTION_NOACCEL)) { - pZzz->noAccel = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "Acceleration disabled\n"); - } else { - pZzz->noAccel = FALSE; - } - if (xf86IsOptionSet(pZzz->Options, OPTION_PCI_RETRY)) { - pZzz->UsePCIRetry = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n"); - } - pZzz->fooHack = 0; - if (xf86GetOptValInteger(pZzz->Options, OPTION_FOO_HACK, - &pZzz->fooHack)) { - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Foo Hack set to %d\n", - pZzz->fooHack); - } - - /* - * Find the PCI slot(s) that this screen claimed in the probe. - * In this case, exactly one is expected, so complain otherwise. - * Note in this case we're not interested in the card types so - * that parameter is set to NULL. - */ - if ((i = xf86GetPciInfoForScreen(pScrn->scrnIndex, &pciList, NULL)) - != 1) { - print error message; - ZZZFreeRec(pScrn); - if (i > 0) - xfree(pciList); - return FALSE; - } - /* Note that pciList should be freed below when no longer needed */ - - /* - * Determine the chipset, allowing config file chipset and - * chipid values to override the probed information. The config - * chipset value has precedence over its chipid value if both - * are present. - * - * It isn't necessary to fill in pScrn->chipset if the driver - * keeps track of the chipset in its ZZZRec. - */ - - ... - - /* - * Determine video memory, fb base address, I/O addresses, etc, - * allowing the config file to override probed values. - * - * Set the appropriate pScrn fields (videoRam is probably the - * most important one that other code might require), and - * print out the settings. - */ - - ... - - /* Initialise a clockRanges list. */ - - ... - - /* Set any other chipset specific things in the ZZZRec */ - - ... - - /* Select valid modes from those available */ - - i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, - pScrn->display->modes, clockRanges, - NULL, minPitch, maxPitch, rounding, - minHeight, maxHeight, - pScrn->display->virtualX, - pScrn->display->virtualY, - pScrn->videoRam * 1024, - LOOKUP_BEST_REFRESH); - if (i == -1) { - ZZZFreeRec(pScrn); - return FALSE; - } - - /* Prune the modes marked as invalid */ - - xf86PruneDriverModes(pScrn); - - /* If no valid modes, return */ - - if (i == 0 || pScrn->modes == NULL) { - print error message; - ZZZFreeRec(pScrn); - return FALSE; - } - - /* - * Initialise the CRTC fields for the modes. This driver expects - * vertical values to be halved for interlaced modes. - */ - xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); - - /* Set the current mode to the first in the list. */ - pScrn->currentMode = pScrn->modes; - - /* Print the list of modes being used. */ - xf86PrintModes(pScrn); - - /* Set the DPI */ - xf86SetDpi(pScrn, 0, 0); - - /* Load bpp-specific modules */ - switch (pScrn->bitsPerPixel) { - case 1: - mod = "xf1bpp"; - break; - case 4: - mod = "xf4bpp"; - break; - case 8: - mod = "cfb"; - break; - case 16: - mod = "cfb16"; - break; - case 24: - mod = "cfb24"; - break; - case 32: - mod = "cfb32"; - break; - } - if (mod && !xf86LoadSubModule(pScrn, mod)) - ZZZFreeRec(pScrn); - return FALSE; - - /* Load XAA if needed */ - if (!pZzz->noAccel || pZzz->hwCursor) - if (!xf86LoadSubModule(pScrn, "xaa")) { - ZZZFreeRec(pScrn); - return FALSE; - } - - /* Done */ - return TRUE; -} - </code> - -<sect2>MapMem, UnmapMem -<p> - - Define functions to map and unmap the video memory and any other - memory apertures required. These functions are not mandatory, but - it is often useful to have such functions. - - <code> -static Bool -ZZZMapMem(ScrnInfoPtr pScrn) -{ - /* Call xf86MapPciMem() to map each PCI memory area */ - ... - return TRUE or FALSE; -} - -static Bool -ZZZUnmapMem(ScrnInfoPtr pScrn) -{ - /* Call xf86UnMapVidMem() to unmap each memory area */ - ... - return TRUE or FALSE; -} - </code> - -<sect2>Save, Restore -<p> - - Define functions to save and restore the original video state. These - functions are not mandatory, but are often useful. - - <code> -static void -ZZZSave(ScrnInfoPtr pScrn) -{ - /* - * Save state into per-screen data structures. - * If using the vgahw module, vgaHWSave will typically be - * called here. - */ - ... -} - -static void -ZZZRestore(ScrnInfoPtr pScrn) -{ - /* - * Restore state from per-screen data structures. - * If using the vgahw module, vgaHWRestore will typically be - * called here. - */ - ... -} - </code> - -<sect2>ModeInit -<p> - - Define a function to initialise a new video mode. This function isn't - mandatory, but is often useful. - - <code> -static Bool -ZZZModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) -{ - /* - * Program a video mode. If using the vgahw module, - * vgaHWInit and vgaRestore will typically be called here. - * Once up to the point where there can't be a failure - * set pScrn->vtSema to TRUE. - */ - ... -} - </code> - -<sect2>ScreenInit -<p> - - Define the &s.code;ScreenInit()&e.code; function. This is called - at the start of each server generation, and should fill in as much - of the &s.code;ScreenRec&e.code; as possible as well as any other - data that is initialised once per generation. It should initialise - the framebuffer layers it is using, and initialise the initial video - mode. - - This function is mandatory. - - NOTE: The &s.code;ScreenRec&e.code; (&s.code;pScreen&e.code;) is - passed to this driver, but it and the - &s.code;ScrnInfoRecs&e.code; are not yet hooked into each - other. This means that in this function, and functions it - calls, one cannot be found from the other. - - <code> -static Bool -ZZZScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) -{ - /* Get the ScrnInfoRec */ - pScrn = xf86Screens[pScreen->myNum]; - - /* - * If using the vgahw module, its data structures and related - * things are typically initialised/mapped here. - */ - - /* Save the current video state */ - ZZZSave(pScrn); - - /* Initialise the first mode */ - ZZZModeInit(pScrn, pScrn->currentMode); - - /* Set the viewport if supported */ - - ZZZAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); - - /* - * Setup the screen's visuals, and initialise the framebuffer - * code. - */ - - /* Reset the visual list */ - miClearVisualTypes(); - - /* - * Setup the visuals supported. This driver only supports - * TrueColor for bpp > 8, so the default set of visuals isn't - * acceptable. To deal with this, call miSetVisualTypes with - * the appropriate visual mask. - */ - - if (pScrn->bitsPerPixel > 8) { - if (!miSetVisualTypes(pScrn->depth, TrueColorMask, - pScrn->rgbBits, pScrn->defaultVisual)) - return FALSE; - } else { - if (!miSetVisualTypes(pScrn->depth, - miGetDefaultVisualMask(pScrn->depth), - pScrn->rgbBits, pScrn->defaultVisual)) - return FALSE; - } - - /* - * Initialise the framebuffer. - */ - - switch (pScrn->bitsPerPixel) { - case 1: - ret = xf1bppScreenInit(pScreen, FbBase, - pScrn->virtualX, pScrn->virtualY, - pScrn->xDpi, pScrn->yDpi, - pScrn->displayWidth); - break; - case 4: - ret = xf4bppScreenInit(pScreen, FbBase, - pScrn->virtualX, pScrn->virtualY, - pScrn->xDpi, pScrn->yDpi, - pScrn->displayWidth); - break; - case 8: - ret = cfbScreenInit(pScreen, FbBase, - pScrn->virtualX, pScrn->virtualY, - pScrn->xDpi, pScrn->yDpi, - pScrn->displayWidth); - break; - case 16: - ret = cfb16ScreenInit(pScreen, FbBase, - pScrn->virtualX, pScrn->virtualY, - pScrn->xDpi, pScrn->yDpi, - pScrn->displayWidth); - break; - case 24: - ret = cfb24ScreenInit(pScreen, FbBase, - pScrn->virtualX, pScrn->virtualY, - pScrn->xDpi, pScrn->yDpi, - pScrn->displayWidth); - break; - case 32: - ret = cfb32ScreenInit(pScreen, FbBase, - pScrn->virtualX, pScrn->virtualY, - pScrn->xDpi, pScrn->yDpi, - pScrn->displayWidth); - break; - default: - print a message about an internal error; - ret = FALSE; - break; - } - - if (!ret) - return FALSE; - - /* Override the default mask/offset settings */ - if (pScrn->bitsPerPixel > 8) { - for (i = 0, visual = pScreen->visuals; - i < pScreen->numVisuals; i++, visual++) { - if ((visual->class | DynamicClass) == DirectColor) { - visual->offsetRed = pScrn->offset.red; - visual->offsetGreen = pScrn->offset.green; - visual->offsetBlue = pScrn->offset.blue; - visual->redMask = pScrn->mask.red; - visual->greenMask = pScrn->mask.green; - visual->blueMask = pScrn->mask.blue; - } - } - } - - /* - * If banking is needed, initialise an miBankInfoRec (defined in - * "mibank.h"), and call miInitializeBanking(). - */ - if (!miInitializeBanking(pScreen, pScrn->virtualX, pScrn->virtualY, - pScrn->displayWidth, pBankInfo)) - return FALSE; - - /* - * If backing store is to be supported (as is usually the case), - * initialise it. - */ - miInitializeBackingStore(pScreen); - - /* - * Set initial black & white colourmap indices. - */ - xf86SetBlackWhitePixels(pScreen); - - /* - * Install colourmap functions. If using the vgahw module, - * vgaHandleColormaps would usually be called here. - */ - - ... - - /* - * Initialise cursor functions. This example is for the mi - * software cursor. - */ - miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); - - /* Initialise the default colourmap */ - switch (pScrn->depth) { - case 1: - if (!xf1bppCreateDefColormap(pScreen)) - return FALSE; - break; - case 4: - if (!xf4bppCreateDefColormap(pScreen)) - return FALSE; - break; - default: - if (!cfbCreateDefColormap(pScreen)) - return FALSE; - break; - } - - /* - * Wrap the CloseScreen vector and set SaveScreen. - */ - ZZZPTR(pScrn)->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = ZZZCloseScreen; - pScreen->SaveScreen = ZZZSaveScreen; - - /* Report any unused options (only for the first generation) */ - if (serverGeneration == 1) { - xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); - } - - /* Done */ - return TRUE; -} - </code> - - -<sect2>SwitchMode -<p> - - Define the &s.code;SwitchMode()&e.code; function if mode switching - is supported by the driver. - - <code> -static Bool -ZZZSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) -{ - return ZZZModeInit(xf86Screens[scrnIndex], mode); -} - </code> - - -<sect2>AdjustFrame -<p> - - Define the &s.code;AdjustFrame()&e.code; function if the driver - supports this. - - <code> -static void -ZZZAdjustFrame(int scrnIndex, int x, int y, int flags) -{ - /* Adjust the viewport */ -} - </code> - - -<sect2>EnterVT, LeaveVT -<p> - - Define the &s.code;EnterVT()&e.code; and &s.code;LeaveVT()&e.code; - functions. - - These functions are mandatory. - - <code> -static Bool -ZZZEnterVT(int scrnIndex, int flags) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - return ZZZModeInit(pScrn, pScrn->currentMode); -} - -static void -ZZZLeaveVT(int scrnIndex, int flags) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - ZZZRestore(pScrn); -} - </code> - -<sect2>CloseScreen -<p> - - Define the &s.code;CloseScreen()&e.code; function: - - This function is mandatory. Note that it unwraps the previously - wrapped &s.code;pScreen->CloseScreen&e.code;, and finishes by - calling it. - - <code> -static Bool -ZZZCloseScreen(int scrnIndex, ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - if (pScrn->vtSema) { - ZZZRestore(pScrn); - ZZZUnmapMem(pScrn); - } - pScrn->vtSema = FALSE; - pScreen->CloseScreen = ZZZPTR(pScrn)->CloseScreen; - return (*pScreen->CloseScreen)(scrnIndex, pScreen); -} - </code> - -<sect2>SaveScreen -<p> - - Define the &s.code;SaveScreen()&e.code; function (the screen - blanking function). When using the vgahw module, this will typically - be: - - <code> -static Bool -ZZZSaveScreen(ScreenPtr pScreen, int mode) -{ - return vgaHWSaveScreen(pScreen, mode); -} - </code> - - This function is mandatory. Before modifying any hardware register - directly this function needs to make sure that the Xserver is active - by checking if &s.code;pScrn&e.code; is non-NULL and for - &s.code;pScrn->vtSema == TRUE&e.code;. - -<sect2>FreeScreen -<p> - - Define the &s.code;FreeScreen()&e.code; function. This function - is optional. It should be defined if the &s.code;ScrnInfoRec&e.code; - &s.code;driverPrivate&e.code; field is used so that it can be freed - when a screen is deleted by the common layer for reasons possibly - beyond the driver's control. This function is not used in during - normal (error free) operation. The per-generation data is freed by - the &s.code;CloseScreen()&e.code; function. - - <code> -static void -ZZZFreeScreen(int scrnIndex, int flags) -{ - /* - * If the vgahw module is used vgaHWFreeHWRec() would be called - * here. - */ - ZZZFreeRec(xf86Screens[scrnIndex]); -} - </code> - - -</article> +<!DOCTYPE linuxdoc PUBLIC "-//Xorg//DTD linuxdoc//EN" [ + <!ENTITY % defs SYSTEM "X11/defs.ent"> %defs; + <!-- config file keyword markup --> + <!ENTITY s.key STARTTAG "bf"> + <!ENTITY e.key ENDTAG "bf"> + <!-- specific config file keywords --> + <!ENTITY k.device "&s.key;Device&e.key;"> + <!ENTITY k.monitor "&s.key;Monitor&e.key;"> + <!ENTITY k.display "&s.key;Display&e.key;"> + <!ENTITY k.inputdevice "&s.key;InputDevice&e.key;"> + <!ENTITY k.screen "&s.key;Screen&e.key;"> + <!ENTITY k.serverlayout "&s.key;ServerLayout&e.key;"> + <!ENTITY k.driver "&s.key;Driver&e.key;"> + <!ENTITY k.module "&s.key;Module&e.key;"> + <!ENTITY k.identifier "&s.key;Identifier&e.key;"> + <!ENTITY k.serverflags "&s.key;ServerFlags&e.key;"> + <!-- command line markup --> + <!ENTITY s.cmd STARTTAG "tt"> + <!ENTITY e.cmd ENDTAG "tt"> + <!-- inline code markup --> + <!ENTITY s.code STARTTAG "tt"> + <!ENTITY e.code ENDTAG "tt"> + <!-- function indent --> + <!ENTITY f.indent "&nl          "> +] > + +<article> + +<title>XFree86 server 4.x Design (DRAFT) +<author>The XFree86 Project, Inc +<and>Updates for X11R&relvers; by Jim Gettys +<date>19 December 2003 + + + + + + + +<ident> +$XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/DESIGN.sgml,v 1.53 2003/08/23 14:10:14 dawes Exp $ +</ident> + + +<p> +<bf>NOTE</bf>: This is a DRAFT document, and the interfaces described here +are subject to change without notice. + + +<sect>Preface +<p> + +The broad design principles are: +<itemize> + <item>keep it reasonable + <itemize> + <item>We cannot rewrite the complete server + <item>We don't want to re-invent the wheel + </itemize> + <item>keep it modular + <itemize> + <item>As many things as possible should go into modules + <item>The basic loader binary should be minimal + <item>A clean design with well defined layering is important + <item>DDX specific global variables are a nono + <item>The structure should be flexible enough to allow + future extensions + <item> The structure should minimize duplication of common code + </itemize> + <item>keep important features in mind + <itemize> + <item>multiple screens, including multiple instances of drivers + <item>mixing different color depths and visuals on different + and ideally even on the same screen + <item>better control of the PCI device used + <item>better config file parser + <item>get rid of all VGA compatibility assumptions + </itemize> +</itemize> + +Unless we find major deficiencies in the DIX layer, we should avoid +making changes there. + +<sect>The xorg.conf File +<p> + +The xorg.conf file format is similar to the old format, with the following +changes: + +<sect1>&k.device; section +<p> + + The &k.device; sections are similar to what they used to be, and + describe hardware-specific information for a single video card. + &k.device; + Some new keywords are added: + + + <descrip> + <tag>Driver "drivername"</tag> + Specifies the name of the driver to be used for the card. This + is mandatory. + <tag>BusID "busslot"</tag> + Specifies uniquely the location of the card on the bus. The + purpose is to identify particular cards in a multi-headed + configuration. The format of the argument is intentionally + vague, and may be architecture dependent. For a PCI bus, it + is something like "bus:slot:func". + </descrip> + + A &k.device; section is considered ``active'' if there is a reference + to it in an active &k.screen; section. + +<sect1>&k.screen; section +<p> + + The &k.screen; sections are similar to what they used to be. They + no longer have a &k.driver; keyword, but an &k.identifier; keyword + is added. (The &k.driver; keyword may be accepted in place of the + &k.identifier; keyword for compatibility purposes.) The identifier + can be used to identify which screen is to be active when multiple + &k.screen sections are present. It is possible to specify the active + screen from the command line. A default is chosen in the absence + of one being specified. A &k.screen; section is considered ``active'' + if there is a reference to it either from the command line, or from + an active &k.serverlayout; section. + +<sect1>&k.inputdevice; section +<p> + + The &k.inputdevice; section is a new section that describes + configuration information for input devices. It replaces the old + &s.key;Keyboard&e.key;, &s.key;Pointer&e.key; and &s.key;XInput&e.key; + sections. Like the &k.device; section, it has two mandatory keywords: + &k.identifier; and &k.driver;. For compatibility purposes the old + &s.key;Keyboard&e.key; and &s.key;Pointer&e.key; sections are + converted by the parser into &k.inputdevice; sections as follows: + + <descrip> + <tag>&s.key;Keyboard&e.key;</tag> + &k.identifier; "Implicit Core Keyboard"<newline> + &k.driver; "keyboard" + <tag>&s.key;Pointer&e.key;</tag> + &k.identifier; "Implicit Core Pointer"<newline> + &k.driver; "mouse" + </descrip> + + An &k.inputdevice; section is considered active if there is a + reference to it in an active &k.serverlayout; section. An + &k.inputdevice; section may also be referenced implicitly if there + is no &k.serverlayout; section, if the &s.cmd;-screen&e.cmd; command + line options is used, or if the &k.serverlayout; section doesn't + reference any &k.inputdevice; sections. In this case, the first + sections with drivers "keyboard" and "mouse" are used as the core + keyboard and pointer respectively. + +<sect1>&k.serverlayout; section +<p> + + The &k.serverlayout; section is a new section that is used to identify + which &k.screen; sections are to be used in a multi-headed configuration, + and the relative layout of those screens. It also identifies which + &k.inputdevice; sections are to be used. Each &k.serverlayout section + has an identifier, a list of &k.screen; section identifiers, and a list of + &k.inputdevice; section identifiers. &k.serverflags; options may also be + included in a &k.serverlayout; section, making it possible to override + the global values in the &k.serverflags; section. + + A &k.serverlayout; section can be made active by being referenced on + the command line. In the absence of this, a default will be chosen + (the first one found). The screen names may optionally be followed + by a number specifying the preferred screen number, and optionally + by information specifying the physical positioning of the screen, + either in absolute terms or relative to another screen (or screens). + When no screen number is specified, they are numbered according to + the order in which they are listed. The old (now obsolete) method + of providing the positioning information is to give the names of + the four adjacent screens. The order of these is top, bottom, left, + right. Here is an example of a &k.serverlayout; section for two + screens using the old method, with the second located to the right + of the first: + + <code> + Section "ServerLayout" + Identifier "Main Layout" + Screen 0 "Screen 1" "" "" "" "Screen 2" + Screen 1 "Screen 2" + Screen "Screen 3" + EndSection + </code> + + The preferred way of specifying the layout is to explicitly specify + the screen's location in absolute terms or relative to another + screen. + + In the absolute case, the upper left corner's coordinates are given + after the &s.key;Absolute&e.key; keyword. If the coordinates are + omitted, a value of &s.code;(0,0)&e.code; is assumed. An example + of absolute positioning follows: + + <code> + Section "ServerLayout" + Identifier "Main Layout" + Screen 0 "Screen 1" Absolute 0 0 + Screen 1 "Screen 2" Absolute 1024 0 + Screen "Screen 3" Absolute 2048 0 + EndSection + </code> + + In the relative case, the position is specified by either using one of + the following keywords followed by the name of the reference screen: + + <quote> + &s.key;RightOf&nl; + LeftOf&nl; + Above&nl; + Below&nl; + Relative&e.key; + </quote> + + When the &s.key;Relative&e.key; keyword is used, the reference screen + name is followed by the coordinates of the new screen's origin + relative to reference screen. The following example shows how to use + some of the relative positioning options. + + <code> + Section "ServerLayout" + Identifier "Main Layout" + Screen 0 "Screen 1" + Screen 1 "Screen 2" RightOf "Screen 1" + Screen "Screen 3" Relative "Screen 1" 2048 0 + EndSection + </code> + +<sect1>Options +<p> + + Options are used more extensively. They may appear in most sections + now. Options related to drivers can be present in the &k.screen;, + &k.device; and &k.monitor; sections and the &k.display; subsections. + The order of precedence is &k.display;, &k.screen;, &k.monitor;, + &k.device;. Options have been extended to allow an optional value + to be specified in addition to the option name. For more details + about options, see the <ref id="options" name="Options"> section + for details. + +<sect>Driver Interface +<p> + +The driver interface consists of a minimal set of entry points that are +required based on the external events that the driver must react to. +No non-essential structure is imposed on the way they are used beyond +that. This is a significant difference compared with the old design. + +The entry points for drawing operations are already taken care of by +the framebuffer code (including, XAA). Extensions and enhancements to +framebuffer code are outside the scope of this document. + +This approach to the driver interface provides good flexibility, but does +increase the complexity of drivers. To help address this, the XFree86 +common layer provides a set of ``helper'' functions to take care of things +that most drivers need. These helpers help minimise the amount of code +duplication between drivers. The use of helper functions by drivers is +however optional, though encouraged. The basic philosophy behind the +helper functions is that they should be useful to many drivers, that +they should balance this against the complexity of their interface. It +is inevitable that some drivers may find some helpers unsuitable and +need to provide their own code. + +Events that a driver needs to react to are: + + <descrip> + <tag>ScreenInit</tag> + + An initialisation function is called from the DIX layer for each + screen at the start of each server generation. + + <tag>Enter VT</tag> + + The server takes control of the console. + + <tag>Leave VT</tag> + + The server releases control of the console. + + <tag>Mode Switch</tag> + + Change video mode. + + <tag>ViewPort change</tag> + + Change the origin of the physical view port. + + <tag>ScreenSaver state change</tag> + + Screen saver activation/deactivation. + + <tag>CloseScreen</tag> + + A close screen function is called from the DIX layer for each screen + at the end of each server generation. + </descrip> + + +In addition to these events, the following functions are required by +the XFree86 common layer: + + <descrip> + <tag>Identify</tag> + + Print a driver identifying message. + + <tag>Probe</tag> + + This is how a driver identifies if there is any hardware present that + it knows how to drive. + + <tag>PreInit</tag> + + Process information from the xorg.conf file, determine the + full characteristics of the hardware, and determine if a valid + configuration is present. + </descrip> + +The VidMode extension also requires: + + <descrip> + <tag>ValidMode</tag> + + Identify if a new mode is usable with the current configuration. + The PreInit function (and/or helpers it calls) may also make use + of the ValidMode function or something similar. + </descrip> + + +Other extensions may require other entry points. The drivers will +inform the common layer of these in such cases. + +<sect>Resource Access Control Introduction +<p> + +Graphics devices are accessed through ranges in I/O or memory space. +While most modern graphics devices allow relocation of such ranges many +of them still require the use of well established interfaces such as +VGA memory and IO ranges or 8514/A IO ranges. With modern buses (like +PCI) it is possible for multiple video devices to share access to these +resources. The RAC (Resource Access Control) subsystem provides a +mechanism for this. + +<sect1>Terms and Definitions +<p> + +<sect2>Bus +<p> + + ``Bus'' is ambiguous as it is used for different things: it may refer + to physical incompatible extension connectors in a computer system. + The RAC system knows two such systems: The ISA bus and the PCI bus. + (On the software level EISA, MCA and VL buses are currently treated + like ISA buses). ``Bus'' may also refer to logically different + entities on a single bus system which are connected via bridges. A + PCI system may have several distinct PCI buses connecting each other + by PCI-PCI bridges or to the host CPU by HOST-PCI bridges. + + Systems that host more than one bus system link these together using + bridges. Bridges are a concern to RAC as they might block or pass + specific resources. PCI-PCI bridges may be set up to pass VGA + resources to the secondary bus. PCI-ISA buses pass any resources not + decoded on the primary PCI bus to the ISA bus. This way VGA resources + (although exclusive on the ISA bus) can be shared by ISA and PCI + cards. Currently HOST-PCI bridges are not yet handled by RAC as they + require specific drivers. + +<sect2>Entity +<p> + + The smallest independently addressable unit on a system bus is + referred to as an entity. So far we know ISA and PCI entities. PCI + entities can be located on the PCI bus by an unique ID consisting of + the bus, card and function number. + +<sect2>Resource +<p> + + ``Resource'' refers to a range of memory or I/O addresses an entity + can decode. + + If a device is capable of disabling this decoding the resource is + called sharable. For PCI devices a generic method is provided to + control resource decoding. Other devices will have to provide a + device specific function to control decoding. + + If the entity is capable of decoding this range at a different + location this resource is considered relocatable. + + Resources which start at a specific address and occupy a single + continuous range are called block resources. + + Alternatively resource addresses can be decoded in a way that they + satisfy the conditions: + <quote><verb> + address & mask == base + </verb></quote> + and + <quote><verb> + base & mask == base + </verb></quote> + Resources addressed in such a way are called sparse resources. + +<sect2>Server States +<p> + + The resource access control system knows two server states: the + SETUP and the OPERATING state. The SETUP state is entered whenever + a mode change takes place or the server exits or does VT switching. + During this state all entity resources are under resource access + control. During OPERATING state only those entities are controlled + which actually have shared resources that conflict with others. + +<sect>Control Flow in the Server and Mandatory Driver Functions +<p> + +At the start of each server generation, &s.code;main()&e.code; +(&s.code;dix/main.c&e.code;) calls the DDX function +&s.code;InitOutput()&e.code;. This is the first place that the DDX gets +control. &s.code;InitOutput()&e.code; is expected to fill in the global +&s.code;screenInfo&e.code; struct, and one +&s.code;screenInfo.screen[]&e.code; entry for each screen present. Here +is what &s.code;InitOutput()&e.code; does: + +<sect1>Parse the xorg.conf file +<p> + + This is done at the start of the first server generation only. + + The xorg.conf file is read in full, and the resulting information + stored in data structures. None of the parsed information is + processed at this point. The parser data structures are opaque to + the video drivers and to most of the common layer code. + + The entire file is parsed first to remove any section ordering + requirements. + + +<sect1>Initial processing of parsed information and command line options +<p> + + This is done at the start of the first server generation only. + + The initial processing is to determine paths like the + &s.key;ModulePath&e.key;, etc, and to determine which &k.serverlayout;, + &k.screen; and &k.device; sections are active. + + +<sect1>Enable port I/O access +<p> + + Port I/O access is controlled from the XFree86 common layer, and is + ``all or nothing''. It is enabled prior to calling driver probes, at + the start of subsequent server generations, and when VT switching + back to the Xserver. It is disabled at the end of server generations, + and when VT switching away from the Xserver. + + The implementation details of this may vary on different platforms. + + +<sect1>General bus probe +<p> + + This is done at the start of the first server generation only. + + In the case of ix86 machines, this will be a general PCI probe. + The full information obtained here will be available to the drivers. + This information persists for the life of the Xserver. In the PCI + case, the PCI information for all video cards found is available by + calling &s.code;xf86GetPciVideoInfo()&e.code;. + + <quote> + &s.code;pciVideoPtr *xf86GetPciVideoInfo(void)&e.code; + <quote><p> + returns a pointer to a list of pointers to + &s.code;pciVideoRec&e.code; entries, of which there is one for + each detected PCI video card. The list is terminated with a + &s.code;NULL&e.code; pointer. If no PCI video cards were + detected, the return value is &s.code;NULL&e.code;. + + </quote> + </quote> + + After the bus probe, the resource broker is initialised. + + +<sect1>Load initial set of modules +<p> + + This is done at the start of the first server generation only. + + The core server contains a list of mandatory modules. These are loaded + first. Currently the only module on this list is the bitmap font module. + + The next set of modules loaded are those specified explicitly in the + &k.module; section of the config file. + + The final set of initial modules are the driver modules referenced + by the active &k.device; and &k.inputdevice; sections in the config + file. Each of these modules is loaded exactly once. + + +<sect1>Register Video and Input Drivers +<p> + + This is done at the start of the first server generation only. + + When a driver module is loaded, the loader calls its + &s.code;Setup&e.code; function. For video drivers, this function + calls &s.code;xf86AddDriver()&e.code; to register the driver's + &s.code;DriverRec&e.code;, which contains a small set of essential + details and driver entry points required during the early phase of + &s.code;InitOutput()&e.code;. &s.code;xf86AddDriver()&e.code; adds + it to the global &s.code;xf86DriverList[]&e.code; array. + + The &s.code;DriverRec&e.code; contains the driver canonical name, + the &s.code;Identify()&e.code;, + &s.code;Probe()&e.code; and &s.code;AvailableOptions()&e.code; + function entry points as well as a pointer + to the driver's module (as returned from the loader when the driver + was loaded) and a reference count which keeps track of how many + screens are using the driver. The entry driver entry points are + those required prior to the driver allocating and filling in its + &s.code;ScrnInfoRec&e.code;. + + For a static server, the &s.code;xf86DriverList[]&e.code; array is + initialised at build time, and the loading of modules is not done. + + A similar procedure is used for input drivers. The input driver's + &s.code;Setup&e.code; function calls + &s.code;xf86AddInputDriver()&e.code; to register the driver's + &s.code;InputDriverRec&e.code;, which contains a small set of + essential details and driver entry points required during the early + phase of &s.code;InitInput()&e.code;. + &s.code;xf86AddInputDriver()&e.code; adds it to the global + &s.code;xf86InputDriverList[]&e.code; array. For a static server, + the &s.code;xf86InputDriverList[]&e.code; array is initialised at + build time. + + Both the &s.code;xf86DriverList[]&e.code; and + &s.code;xf86InputDriverList[]&e.code; arrays have been initialised + by the end of this stage. + + Once all the drivers are registered, their + &s.code;ChipIdentify()&e.code; functions are called. + + <quote> + &s.code;void ChipIdentify(int flags)&e.code; + <quote> + This is expected to print a message indicating the driver name, + a short summary of what it supports, and a list of the chipset + names that it supports. It may use the xf86PrintChipsets() helper + to do this. + </quote> + </quote> + + <quote> + &s.code;void xf86PrintChipsets(const char *drvname, const char *drvmsg, + &f.indent;SymTabPtr chips)&e.code; + <quote> + This function provides an easy way for a driver's ChipIdentify + function to format the identification message. + </quote> + </quote> + +<sect1>Initialise Access Control +<p> + + This is done at the start of the first server generation only. + + The Resource Access Control (RAC) subsystem is initialised before + calling any driver functions that may access hardware. All generic + bus information is probed and saved (for restoration later). All + (shared resource) video devices are disabled at the generic bus + level, and a probe is done to find the ``primary'' video device. These + devices remain disabled for the next step. + + +<sect1>Video Driver Probe<label id="probe"> +<p> + This is done at the start of the first server generation only. The + &s.code;ChipProbe()&e.code; function of each registered video driver + is called. + + <quote><p> + &s.code;Bool ChipProbe(DriverPtr drv, int flags)&e.code; + <quote><p> + The purpose of this is to identify all instances of hardware + supported by the driver. The flags value is currently either 0, + &s.code;PROBE_DEFAULT&e.code; or &s.code;PROBE_DETECT&e.code;. + &s.code;PROBE_DETECT&e.code; is used if "-configure" or "-probe" + command line arguments are given and indicates to the + &s.code;Probe()&e.code; function that it should not configure the + bus entities and that no xorg.conf information is available. + + The probe must find the active device sections that match the + driver by calling &s.code;xf86MatchDevice()&e.code;. The number + of matches found limits the maximum number of instances for this + driver. If no matches are found, the function should return + &s.code;FALSE&e.code; immediately. + + Devices that cannot be identified by using device-independent + methods should be probed at this stage (keeping in mind that access + to all resources that can be disabled in a device-independent way + are disabled during this phase). The probe must be a minimal + probe. It should just determine if there is a card present that + the driver can drive. It should use the least intrusive probe + methods possible. It must not do anything that is not essential, + like probing for other details such as the amount of memory + installed, etc. It is recommended that the + &s.code;xf86MatchPciInstances()&e.code; helper function be used + for identifying matching PCI devices, and similarly the + &s.code;xf86MatchIsaInstances()&e.code; for ISA (non-PCI) devices + (see the <ref id="rac" name="RAC"> section). These helpers also + checks and claims the appropriate entity. When not using the + helper, that should be done with &s.code;xf86CheckPciSlot()&e.code; + and &s.code;xf86ClaimPciSlot()&e.code; for PCI devices and + &s.code;xf86ClaimIsaSlot()&e.code; for ISA devices (see the + <ref id="rac" name="RAC"> section). + + The probe must register all non-relocatable resources at this + stage. If a resource conflict is found between exclusive resources + the driver will fail immediately. This is usually best done with + the &s.code;xf86ConfigPciEntity()&e.code; helper function + for PCI and &s.code;xf86ConfigIsaEntity()&e.code; for ISA + (see the <ref id="rac" name="RAC"> section). It is possible to + register some entity specific functions with those helpers. When + not using the helpers, the &s.code;xf86AddEntityToScreen()&e.code; + &s.code;xf86ClaimFixedResources()&e.code; and + &s.code;xf86SetEntityFuncs()&e.code; should be used instead (see + the <ref id="rac" name="RAC"> section). + + If a chipset is specified in an active device section which the + driver considers relevant (ie it has no driver specified, or the + driver specified matches the driver doing the probe), the Probe + must return &s.code;FALSE&e.code; if the chipset doesn't match + one supported by the driver. + + If there are no active device sections that the driver considers + relevant, it must return &s.code;FALSE&e.code;. + + Allocate a &s.code;ScrnInfoRec&e.code; for each active instance of the + hardware found, and fill in the basic information, including the + other driver entry points. This is best done with the + &s.code;xf86ConfigIsaEntity()&e.code; helper function for ISA + instances or &s.code;xf86ConfigPciEntity()&e.code; for PCI instances. + These functions allocate a &s.code;ScrnInfoRec&e.code; for active + entities. Optionally &s.code;xf86AllocateScreen()&e.code; + function may also be used to allocate the &s.code;ScrnInfoRec&e.code;. + Any of these functions take care of initialising fields to defined + ``unused'' values. + + Claim the entities for each instance of the hardware found. This + prevents other drivers from claiming the same hardware. + + Must leave hardware in the same state it found it in, and must not + do any hardware initialisation. + + All detection can be overridden via the config file, and that + parsed information is available to the driver at this stage. + + Returns &s.code;TRUE&e.code; if one or more instances are found, + and &s.code;FALSE&e.code; otherwise. + + </quote> + + &s.code;int xf86MatchDevice(const char *drivername, + &f.indent;GDevPtr **driversectlist)&e.code; + <quote><p> + + This function takes the name of the driver and returns via + &s.code;driversectlist&e.code; a list of device sections that + match the driver name. The function return value is the number + of matches found. If a fatal error is encountered the return + value is &s.code;-1&e.code;. + + The caller should use &s.code;xfree()&e.code; to free + &s.code;*driversectlist&e.code; when it is no longer needed. + + </quote> + + &s.code;ScrnInfoPtr xf86AllocateScreen(DriverPtr drv, int flags)&e.code; + <quote><p> + This function allocates a new &s.code;ScrnInfoRec&e.code; in the + &s.code;xf86Screens[]&e.code; array. This function is normally + called by the video driver &s.code;ChipProbe()&e.code; functions. + The return value is a pointer to the newly allocated + &s.code;ScrnInfoRec&e.code;. The &s.code;scrnIndex&e.code;, + &s.code;origIndex&e.code;, &s.code;module&e.code; and + &s.code;drv&e.code; fields are initialised. The reference count + in &s.code;drv&e.code; is incremented. The storage for any + currently allocated ``privates'' pointers is also allocated and + the &s.code;privates&e.code; field initialised (the privates data + is of course not allocated or initialised). This function never + returns on failure. If the allocation fails, the server exits + with a fatal error. The flags value is not currently used, and + should be set to zero. + </quote> + </quote> + + At the completion of this, a list of &s.code;ScrnInfoRecs&e.code; + have been allocated in the &s.code;xf86Screens[]&e.code; array, and + the associated entities and fixed resources have been claimed. The + following &s.code;ScrnInfoRec&e.code; fields must be initialised at + this point: + + <quote><verb> + driverVersion + driverName + scrnIndex(*) + origIndex(*) + drv(*) + module(*) + name + Probe + PreInit + ScreenInit + EnterVT + LeaveVT + numEntities + entityList + access + </verb></quote> + + <tt>(*)</tt> These are initialised when the &s.code;ScrnInfoRec&e.code; + is allocated, and not explicitly by the driver. + + The following &s.code;ScrnInfoRec&e.code; fields must be initialised + if the driver is going to use them: + + <quote><verb> + SwitchMode + AdjustFrame + FreeScreen + ValidMode + </verb></quote> + +<sect1>Matching Screens +<p> + + This is done at the start of the first server generation only. + + After the Probe phase is finished, there will be some number of + &s.code;ScrnInfoRecs&e.code;. These are then matched with the active + &k.screen; sections in the xorg.conf, and those not having an active + &k.screen; section are deleted. If the number of remaining screens + is 0, &s.code;InitOutput()&e.code; sets + &s.code;screenInfo.numScreens&e.code; to &s.code;0&e.code; and + returns. + + At this point the following fields of the &s.code;ScrnInfoRecs&e.code; + must be initialised: + + <quote><verb> + confScreen + </verb></quote> + + +<sect1>Allocate non-conflicting resources +<p> + + This is done at the start of the first server generation only. + + Before calling the drivers again, the resource information collected + from the Probe phase is processed. This includes checking the extent + of PCI resources for the probed devices, and resolving any conflicts + in the relocatable PCI resources. It also reports conflicts, checks + bus routing issues, and anything else that is needed to enable the + entities for the next phase. + + If any drivers registered an &s.code;EntityInit()&e.code; function + during the Probe phase, then they are called here. + + +<sect1>Sort the Screens and pre-check Monitor Information +<p> + + This is done at the start of the first server generation only. + + The list of screens is sorted to match the ordering requested in the + config file. + + The list of modes for each active monitor is checked against the + monitor's parameters. Invalid modes are pruned. + + +<sect1>PreInit +<p> + + This is done at the start of the first server generation only. + + For each &s.code;ScrnInfoRec&e.code;, enable access to the screens entities and call + the &s.code;ChipPreInit()&e.code; function. + + <quote><p> + &s.code;Bool ChipPreInit(ScrnInfoRec screen, int flags)&e.code; + <quote><p> + The purpose of this function is to find out all the information + required to determine if the configuration is usable, and to + initialise those parts of the &s.code;ScrnInfoRec&e.code; that + can be set once at the beginning of the first server generation. + + The number of entities registered for the screen should be checked + against the expected number (most drivers expect only one). The + entity information for each of them should be retrieved (with + &s.code;xf86GetEntityInfo()&e.code;) and checked for the correct + bus type and that none of the sharable resources registered during + the Probe phase was rejected. + + Access to resources for the entities that can be controlled in a + device-independent way are enabled before this function is called. + If the driver needs to access any resources that it has disabled + in an &s.code;EntityInit()&e.code; function that it registered, + then it may enable them here providing that it disables them before + this function returns. + + This includes probing for video memory, clocks, ramdac, and all + other HW info that is needed. It includes determining the + depth/bpp/visual and related info. It includes validating and + determining the set of video modes that will be used (and anything + that is required to determine that). + + This information should be determined in the least intrusive way + possible. The state of the HW must remain unchanged by this + function. Although video memory (including MMIO) may be mapped + within this function, it must be unmapped before returning. Driver + specific information should be stored in a structure hooked into + the &s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; + field. Any other modules which require persistent data (ie data + that persists across server generations) should be initialised in + this function, and they should allocate a ``privates'' index to + hook their data into by calling + &s.code;xf86AllocateScrnInfoPrivateIndex().&e.code; The ``privates'' + data is persistent. + + Helper functions for some of these things are provided at the + XFree86 common level, and the driver can choose to make use of + them. + + All additional resources that the screen needs must be registered + here. This should be done with + &s.code;xf86RegisterResources()&e.code;. If some of the fixed + resources registered in the Probe phase are not needed or not + decoded by the hardware when in the OPERATING server state, their + status should be updated with + &s.code;xf86SetOperatingState()&e.code;. + + Modules may be loaded at any point in this function, and all + modules that the driver will need must be loaded before the end + of this function. Either the &s.code;xf86LoadSubModule()&e.code; + or the &s.code;xf86LoadDrvSubModule()&e.code; function should be + used to load modules depending on whether a + &s.code;ScrnInfoRec&e.code; has been set up. A driver may unload + a module within this function if it was only needed temporarily, + and the &s.code;xf86UnloadSubModule()&e.code; function should be used + to do that. Otherwise there is no need to explicitly unload modules + because the loader takes care of module dependencies and will + unload submodules automatically if/when the driver module is + unloaded. + + The bulk of the &s.code;ScrnInfoRec&e.code; fields should be filled + out in this function. + + &s.code;ChipPreInit()&e.code; returns &s.code;FALSE&e.code; when + the configuration is unusable in some way (unsupported depth, no + valid modes, not enough video memory, etc), and &s.code;TRUE&e.code; + if it is usable. + + It is expected that if the &s.code;ChipPreInit()&e.code; function + returns &s.code;TRUE&e.code;, then the only reasons that subsequent + stages in the driver might fail are lack or resources (like xalloc + failures). All other possible reasons for failure should be + determined by the &s.code;ChipPreInit()&e.code; function. + + </quote> + </quote> + + The &s.code;ScrnInfoRecs&e.code; for screens where the &s.code;ChipPreInit()&e.code; fails are removed. + If none remain, &s.code;InitOutput()&e.code; sets &s.code;screenInfo.numScreens&e.code; to &s.code;0&e.code; and returns. + + At this point, further fields of the &s.code;ScrnInfoRecs&e.code; would normally be + filled in. Most are not strictly mandatory, but many are required + by other layers and/or helper functions that the driver may choose + to use. The documentation for those layers and helper functions + indicates which they require. + + The following fields of the &s.code;ScrnInfoRecs&e.code; should be filled in if the + driver is going to use them: + + <quote><verb> + monitor + display + depth + pixmapBPP + bitsPerPixel + weight (>8bpp only) + mask (>8bpp only) + offset (>8bpp only) + rgbBits (8bpp only) + gamma + defaultVisual + maxHValue + maxVValue + virtualX + virtualY + displayWidth + frameX0 + frameY0 + frameX1 + frameY1 + zoomLocked + modePool + modes + currentMode + progClock (TRUE if clock is programmable) + chipset + ramdac + clockchip + numClocks (if not programmable) + clock[] (if not programmable) + videoRam + biosBase + memBase + memClk + driverPrivate + chipID + chipRev + </verb></quote> + + <quote><p> + &s.code;pointer xf86LoadSubModule(ScrnInfoPtr pScrn, const char *name)&e.code: + and + &s.code;pointer xf86LoadDrvSubModule(DriverPtr drv, const char *name)&e.code: + <quote><p> + Load a module that a driver depends on. This function loads the + module &s.code;name&e.code; as a sub module of the driver. The + return value is a handle identifying the new module. If the load + fails, the return value will be &s.code;NULL&e.code;. If a driver + needs to explicitly unload a module it has loaded in this way, + the return value must be saved and passed to + &s.code;xf86UnloadSubModule()&e.code; when unloading. + + </quote> + + &s.code;void xf86UnloadSubModule(pointer module)&e.code; + <quote><p> + Unloads the module referenced by &s.code;module&e.code;. + &s.code;module&e.code; should be a pointer returned previously + by &s.code;xf86LoadSubModule()&e.code; or + &s.code;xf86LoadDrvSubModule()&e.code; . + + </quote> + </quote> + +<sect1>Cleaning up Unused Drivers +<p> + + At this point it is known which screens will be in use, and which + drivers are being used. Unreferenced drivers (and modules they + may have loaded) are unloaded here. + + +<sect1>Consistency Checks +<p> + + The parameters that must be global to the server, like pixmap formats, + bitmap bit order, bitmap scanline unit and image byte order are + compared for each of the screens. If a mismatch is found, the server + exits with an appropriate message. + + +<sect1>Check if Resource Control is Needed +<p> + + Determine if resource access control is needed. This is the case + if more than one screen is used. If necessary the RAC wrapper module + is loaded. + +<sect1>AddScreen (ScreenInit) +<p> + + At this point, the valid screens are known. + &s.code;AddScreen()&e.code; is called for each of them, passing + &s.code;ChipScreenInit()&e.code; as the argument. + &s.code;AddScreen()&e.code; is a DIX function that allocates a new + &s.code;screenInfo.screen[]&e.code; entry (aka + &s.code;pScreen&e.code;), and does some basic initialisation of it. + It then calls the &s.code;ChipScreenInit()&e.code; function, with + &s.code;pScreen&e.code; as one of its arguments. If + &s.code;ChipScreenInit()&e.code; returns &s.code;FALSE&e.code;, + &s.code;AddScreen()&e.code; returns &s.code;-1&e.code;. Otherwise + it returns the index of the screen. &s.code;AddScreen()&e.code; + should only fail because of programming errors or failure to allocate + resources (like memory). All configuration problems should be + detected BEFORE this point. + + <quote><p> + &s.code;Bool ChipScreenInit(int index, ScreenPtr pScreen, + &f.indent;int argc, char **argv)&e.code; + <quote><p> + This is called at the start of each server generation. + + Fill in all of &s.code;pScreen&e.code;, possibly doing some of + this by calling ScreenInit functions from other layers like mi, + framebuffers (cfb, etc), and extensions. + + Decide which operations need to be placed under resource access + control. The classes of operations are the frame buffer operations + (&s.code;RAC_FB&e.code;), the pointer operations + (&s.code;RAC_CURSOR&e.code;), the viewport change operations + (&s.code;RAC_VIEWPORT&e.code;) and the colormap operations + (&s.code;RAC_COLORMAP&e.code;). Any operation that requires + resources which might be disabled during OPERATING state should + be set to use RAC. This can be specified separately for memory + and IO resources (the &s.code;racMemFlags&e.code; and + &s.code;racIoFlags&e.code; fields of the &s.code;ScrnInfoRec&e.code; + respectively). + + Map any video memory or other memory regions. + + Save the video card state. Enough state must be saved so that + the original state can later be restored. + + Initialise the initial video mode. The &s.code;ScrnInfoRec&e.code;'s + &s.code;vtSema&e.code; field should be set to &s.code;TRUE&e.code; + just prior to changing the video hardware's state. + + </quote> + </quote> + + + The &s.code;ChipScreenInit()&e.code; function (or functions from other + layers that it calls) should allocate entries in the + &s.code;ScreenRec&e.code;'s &s.code;devPrivates&e.code; area by + calling &s.code;AllocateScreenPrivateIndex()&e.code; if it needs + per-generation storage. Since the &s.code;ScreenRec&e.code;'s + &s.code;devPrivates&e.code; information is cleared for each server + generation, this is the correct place to initialise it. + + After &s.code;AddScreen()&e.code; has successfully returned, the + following &s.code;ScrnInfoRec&e.code; fields are initialised: + + <quote><verb> + pScreen + racMemFlags + racIoFlags + </verb></quote> + + The &s.code;ChipScreenInit()&e.code; function should initialise the + &s.code;CloseScreen&e.code; and &s.code;SaveScreen&e.code; fields + of &s.code;pScreen&e.code;. The old value of + &s.code;pScreen->CloseScreen&e.code; should be saved as part of + the driver's per-screen private data, allowing it to be called from + &s.code;ChipCloseScreen()&e.code;. This means that the existing + &s.code;CloseScreen()&e.code; function is wrapped. + +<sect1>Finalising RAC Initialisation +<p> + + After all the &s.code;ChipScreenInit()&e.code; functions have been + called, each screen has registered its RAC requirements. This + information is used to determine which shared resources are requested + by more than one driver and set the access functions accordingly. + This is done following these rules: + + <enum> + <item>The sharable resources registered by each entity are compared. + If a resource is registered by more than one entity the entity + will be marked to indicate that it needs to share this resources + type (IO or MEM). + + <item>A resource marked ``disabled'' during OPERATING state will be + ignored entirely. + + <item>A resource marked ``unused'' will only conflict with an overlapping + resource of an other entity if the second is actually in use + during OPERATING state. + + <item>If an ``unused'' resource was found to conflict but the entity + does not use any other resource of this type the entire resource + type will be disabled for that entity. + </enum> + + +<sect1>Finishing InitOutput() +<p> + + At this point &s.code;InitOutput()&e.code; is finished, and all the + screens have been setup in their initial video mode. + + +<sect1>Mode Switching +<p> + + When a SwitchMode event is received, &s.code;ChipSwitchMode()&e.code; + is called (when it exists): + + <quote><p> + &s.code;Bool ChipSwitchMode(int index, DisplayModePtr mode, int flags)&e.code; + <quote><p> + Initialises the new mode for the screen identified by + &s.code;index;&e.code;. The viewport may need to be adjusted + also. + + </quote> + </quote> + + +<sect1>Changing Viewport +<p> + + When a Change Viewport event is received, + &s.code;ChipAdjustFrame()&e.code; is called (when it exists): + + <quote><p> + &s.code;void ChipAdjustFrame(int index, int x, int y, int flags)&e.code; + <quote><p> + Changes the viewport for the screen identified by + &s.code;index;&e.code;. + + It should be noted that many chipsets impose restrictions on where the + viewport may be placed in the virtual resolution, either for alignment + reasons, or to prevent the start of the viewport from being positioned + within a pixel (as can happen in a 24bpp mode). After calculating the + value the chipset's panning registers need to be set to for non-DGA + modes, this function should recalculate the ScrnInfoRec's + &s.code;frameX0&e.code;, &s.code;frameY0&e.code, &s.code;frameX1&e.code; + and &s.code;frameY1&e.code; fields to correspond to that value. If + this is not done, switching to another mode might cause the position + of a hardware cursor to change. + + </quote> + </quote> + + +<sect1>VT Switching +<p> + + When a VT switch event is received, &s.code;xf86VTSwitch()&e.code; + is called. &s.code;xf86VTSwitch()&e.code; does the following: + + <descrip> + <tag>On ENTER:</tag> + <itemize> + <item>enable port I/O access + + <item>save and initialise the bus/resource state + + <item>enter the SETUP server state + + <item>calls &s.code;ChipEnterVT()&e.code; for each screen + + <item>enter the OPERATING server state + + <item>validate GCs + + <item>Restore fb from saved pixmap for each screen + + <item>Enable all input devices + </itemize> + <tag>On LEAVE:</tag> + <itemize> + <item>Save fb to pixmap for each screen + + <item>validate GCs + + <item>enter the SETUP server state + + <item>calls &s.code;ChipLeaveVT()&e.code; for each screen + + <item>disable all input devices + + <item>restore bus/resource state + + <item>disables port I/O access + </itemize> + </descrip> + + <quote><p> + &s.code;Bool ChipEnterVT(int index, int flags)&e.code; + <quote><p> + This function should initialise the current video mode and + initialise the viewport, turn on the HW cursor if appropriate, + etc. + + Should it re-save the video state before initialising the video + mode? + + </quote> + + &s.code;void ChipLeaveVT(int index, int flags)&e.code; + <quote><p> + This function should restore the saved video state. If + appropriate it should also turn off the HW cursor, and invalidate + any pixmap/font caches. + + </quote> + + Optionally, &s.code;ChipLeaveVT()&e.code; may also unmap memory + regions. If so, &s.code;ChipEnterVT()&e.code; will need to remap + them. Additionally, if an aperture used to access video memory is + unmapped and remapped in this fashion, &s.code;ChipEnterVT()&e.code; + will also need to notify the framebuffer layers of the aperture's new + location in virtual memory. This is done with a call to the screen's + &s.code;ModifyPixmapHeader()&e.code; function, as follows + + <quote><p> + &s.code;(*pScreen->ModifyPixmapHeader)(pScrn->ppix, + &f.indent;-1, -1, -1, -1, -1, <it>NewApertureAddress</it>);&e.code; + <quote><p> + where the &s.code``ppix''&e.code; field in a ScrnInfoRec + points to the pixmap used by the screen's + &s.code;SaveRestoreImage()&e.code; function to hold the screen's + contents while switched out. + + </quote> + </quote> + + Currently, aperture remapping, as described here, should not be + attempted if the driver uses the &s.code;xf8_16bpp&e.code; or + &s.code;xf8_32bpp&e.code; framebuffer layers. A pending + restructuring of VT switching will address this restriction in + the near future. + + </quote> + + Other layers may wrap the &s.code;ChipEnterVT()&e.code; and + &s.code;ChipLeaveVT()&e.code; functions if they need to take some + action when these events are received. + +<sect1>End of server generation +<p> + + At the end of each server generation, the DIX layer calls + &s.code;ChipCloseScreen()&e.code; for each screen: + + <quote><p> + &s.code;Bool ChipCloseScreen(int index, ScreenPtr pScreen)&e.code; + <quote><p> + This function should restore the saved video state and unmap the + memory regions. + + It should also free per-screen data structures allocated by the + driver. Note that the persistent data held in the + &s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; field + should not be freed here because it is needed by subsequent server + generations. + + The &s.code;ScrnInfoRec&e.code;'s &s.code;vtSema&e.code; field + should be set to &s.code;FALSE&e.code; once the video HW state + has been restored. + + Before freeing the per-screen driver data the saved + &s.code;CloseScreen&e.code; value should be restored to + &s.code;pScreen->CloseScreen&e.code;, and that function should + be called after freeing the data. + + </quote> + </quote> + +<sect>Optional Driver Functions +<p> + +The functions outlined here can be called from the XFree86 common layer, +but their presence is optional. + +<sect1>Mode Validation +<p> + + When a mode validation helper supplied by the XFree86-common layer is + being used, it can be useful to provide a function to check for hw + specific mode constraints: + + <quote><p> + &s.code;ModeStatus ChipValidMode(int index, DisplayModePtr mode, + &f.indent;Bool verbose, int flags)&e.code; + <quote><p> + Check the passed mode for hw-specific constraints, and return the + appropriate status value. + + </quote> + </quote> + +<p> +This function may also modify the effective timings and clock of the passed +mode. These have been stored in the mode's &s.code;Crtc*&e.code; and +&s.code;SynthClock&e.code; elements, and have already been adjusted for +interlacing, doublescanning, multiscanning and clock multipliers and dividers. +The function should not modify any other mode field, unless it wants to modify +the mode timings reported to the user by &s.code;xf86PrintModes()&e.code;. + +<p> +The function is called once for every mode in the xorg.conf Monitor section +assigned to the screen, with &s.code;flags&e.code; set to +&s.code;MODECHECK_INITIAL&e.code;. It is subsequently called for every mode +in the xorg.conf Display subsection assigned to the screen, with +&s.code;flags&e.code; set to &s.code;MODECHECK_FINAL&e.code;. In the second +case, the mode will have successfully passed all other tests. In addition, +the &s.code;ScrnInfoRec&e.code;'s &s.code;virtualX&e.code;, +&s.code;virtualY&e.code; and &s.code;displayWidth&e.code; fields will have been +set as if the mode to be validated were to be the last mode accepted. + +<p> +In effect, calls with MODECHECK_INITIAL are intended for checks that do not +depend on any mode other than the one being validated, while calls with +MODECHECK_FINAL are intended for checks that may involve more than one mode. + +<sect1>Free screen data +<p> + + When a screen is deleted prior to the completion of the ScreenInit + phase the &s.code;ChipFreeScreen()&e.code; function is called when defined. + + <quote><p> + &s.code;void ChipFreeScreen(int scrnindex, int flags)&e.code; + <quote><p> + Free any driver-allocated data that may have been allocated up to + and including an unsuccessful &s.code;ChipScreenInit()&e.code; + call. This would predominantly be data allocated by + &s.code;ChipPreInit()&e.code; that persists across server + generations. It would include the &s.code;driverPrivate&e.code;, + and any ``privates'' entries that modules may have allocated. + + </quote> + </quote> + + +<sect>Recommended driver functions +<p> + +The functions outlined here are for internal use by the driver only. +They are entirely optional, and are never accessed directly from higher +layers. The sample function declarations shown here are just examples. +The interface (if any) used is up to the driver. + +<sect1>Save +<p> + + Save the video state. This could be called from &s.code;ChipScreenInit()&e.code; and + (possibly) &s.code;ChipEnterVT()&e.code;. + + <quote><p> + &s.code;void ChipSave(ScrnInfoPtr pScrn)&e.code; + <quote><p> + Saves the current state. This will only be saving pre-server + states or states before returning to the server. There is only + one current saved state per screen and it is stored in private + storage in the screen. + + </quote> + </quote> + +<sect1>Restore +<p> + + Restore the original video state. This could be called from the + &s.code;ChipLeaveVT()&e.code; and &s.code;ChipCloseScreen()&e.code; + functions. + + <quote><p> + &s.code;void ChipRestore(ScrnInfoPtr pScrn)&e.code; + <quote><p> + Restores the saved state from the private storage. Usually only + used for restoring text modes. + + </quote> + </quote> + + +<sect1>Initialise Mode +<p> + + Initialise a video mode. This could be called from the + &s.code;ChipScreenInit()&e.code;, &s.code;ChipSwitchMode()&e.code; + and &s.code;ChipEnterVT()&e.code; functions. + + <quote><p> + &s.code;Bool ChipModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)&e.code; + <quote><p> + Programs the hardware for the given video mode. + + </quote> + </quote> + + +<sect>Data and Data Structures +<p> + +<sect1>Command line data +<p> + +Command line options are typically global, and are stored in global +variables. These variables are read-only and are available to drivers +via a function call interface. Most of these command line values are +processed via helper functions to ensure that they are treated consistently +by all drivers. The other means of access is provided for cases where +the supplied helper functions might not be appropriate. + +Some of them are: + +<quote><verb> + xf86Verbose verbosity level + xf86Bpp -bpp from the command line + xf86Depth -depth from the command line + xf86Weight -weight from the command line + xf86Gamma -{r,g,b,}gamma from the command line + xf86FlipPixels -flippixels from the command line + xf86ProbeOnly -probeonly from the command line + defaultColorVisualClass -cc from the command line +</verb></quote> + +If we ever do allow for screen-specific command line options, we may +need to rethink this. + +These can be accessed in a read-only manner by drivers with the following +functions: + + <quote><p> + &s.code;int xf86GetVerbosity()&e.code; + <quote><p> + Returns the value of &s.code;xf86Verbose&e.code;. + + </quote> + + &s.code;int xf86GetDepth()&e.code; + <quote><p> + Returns the &s.cmd;-depth&e.cmd; command line setting. If not + set on the command line, &s.code;-1&e.code; is returned. + + </quote> + + &s.code;rgb xf86GetWeight()&e.code; + <quote><p> + Returns the &s.cmd;-weight&e.cmd; command line setting. If not + set on the command line, &s.code;{0, 0, 0}&e.code; is returned. + + </quote> + + &s.code;Gamma xf86GetGamma()&e.code; + <quote><p> + Returns the &s.cmd;-gamma&e.cmd; or &s.cmd;-rgamma&e.cmd;, + &s.cmd;-ggamma&e.cmd;, &s.cmd;-bgamma&e.cmd; command line settings. + If not set on the command line, &s.code;{0.0, 0.0, 0.0}&e.code; + is returned. + + </quote> + + &s.code;Bool xf86GetFlipPixels()&e.code; + <quote><p> + Returns &s.code;TRUE&e.code; if &s.cmd;-flippixels&e.cmd; is + present on the command line, and &s.code;FALSE&e.code; otherwise. + + </quote> + + &s.code;const char *xf86GetServerName()&e.code; + <quote><p> + Returns the name of the X server from the command line. + + </quote> + </quote> + +<sect1>Data handling +<p> + +Config file data contains parts that are global, and parts that are +Screen specific. All of it is parsed into data structures that neither +the drivers or most other parts of the server need to know about. + +The global data is typically not required by drivers, and as such, most +of it is stored in the private &s.code;xf86InfoRec&e.code;. + +The screen-specific data collected from the config file is stored in +screen, device, display, monitor-specific data structures that are separate +from the &s.code;ScrnInfoRecs&e.code;, with the appropriate elements/fields +hooked into the &s.code;ScrnInfoRecs&e.code; as required. The screen +config data is held in &s.code;confScreenRec&e.code;, device data in +the &s.code;GDevRec&e.code;, monitor data in the &s.code;MonRec&e.code;, +and display data in the &s.code;DispRec&e.code;. + +The XFree86 common layer's screen specific data (the actual data in use +for each screen) is held in the &s.code;ScrnInfoRecs&e.code;. As has +been outlined above, the &s.code;ScrnInfoRecs&e.code; are allocated at probe +time, and it is the responsibility of the Drivers' &s.code;Probe()&e.code; +and &s.code;PreInit()&e.code; functions to finish filling them in based +on both data provided on the command line and data provided from the +Config file. The precedence for this is: + + <quote> + command line -> config file -> probed/default data + </quote> + +For most things in this category there are helper functions that the +drivers can use to ensure that the above precedence is consistently +used. + +As well as containing screen-specific data that the XFree86 common layer +(including essential parts of the server infrastructure as well as helper +functions) needs to access, it also contains some data that drivers use +internally. When considering whether to add a new field to the +&s.code;ScrnInfoRec&e.code;, consider the balance between the convenience +of things that lots of drivers need and the size/obscurity of the +&s.code;ScrnInfoRec&e.code;. + +Per-screen driver specific data that cannot be accommodated with the +static &s.code;ScrnInfoRec&e.code; fields is held in a driver-defined +data structure, a pointer to which is assigned to the +&s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; field. This +is per-screen data that persists across server generations (as does the +bulk of the static &s.code;ScrnInfoRec&e.code; data). It would typically +also include the video card's saved state. + +Per-screen data for other modules that the driver uses (for example, +the XAA module) that is reset for each server generation is hooked into +the &s.code;ScrnInfoRec&e.code; through it's &s.code;privates&e.code; +field. + +Once it has stabilised, the data structures and variables accessible to +video drivers will be documented here. In the meantime, those things +defined in the &s.code;xf86.h&e.code; and &s.code;xf86str.h&e.code; +files are visible to video drivers. Things defined in +&s.code;xf86Priv.h&e.code; and &s.code;xf86Privstr.h&e.code; are NOT +intended to be visible to video drivers, and it is an error for a driver +to include those files. + + +<sect1>Accessing global data +<p> + +Some other global state information that the drivers may access via +functions is as follows: + + <quote><p> + &s.code;Bool xf86ServerIsExiting()&e.code; + <quote><p> + Returns &s.code;TRUE&e.code; if the server is at the end of a + generation and is in the process of exiting, and + &s.code;FALSE&e.code; otherwise. + + </quote> + + &s.code;Bool xf86ServerIsResetting()&e.code; + <quote><p> + Returns &s.code;TRUE&e.code; if the server is at the end of a + generation and is in the process of resetting, and + &s.code;FALSE&e.code; otherwise. + + </quote> + + &s.code;Bool xf86ServerIsInitialising()&e.code; + <quote><p> + Returns &s.code;TRUE&e.code; if the server is at the beginning of + a generation and is in the process of initialising, and + &s.code;FALSE&e.code; otherwise. + + </quote> + + &s.code;Bool xf86ServerIsOnlyProbing()&e.code; + <quote><p> + Returns &s.code;TRUE&e.code; if the -probeonly command line flag + was specified, and &s.code;FALSE&e.code; otherwise. + + </quote> + + &s.code;Bool xf86CaughtSignal()&e.code; + <quote><p> + Returns &s.code;TRUE&e.code; if the server has caught a signal, + and &s.code;FALSE&e.code; otherwise. + + </quote> + </quote> + +<sect1>Allocating private data +<p> + +A driver and any module it uses may allocate per-screen private storage +in either the &s.code;ScreenRec&e.code; (DIX level) or +&s.code;ScrnInfoRec&e.code; (XFree86 common layer level). +&s.code;ScreenRec&e.code; storage persists only for a single server +generation, and &s.code;ScrnInfoRec&e.code; storage persists across +generations for the lifetime of the server. + +The &s.code;ScreenRec&e.code; &s.code;devPrivates&e.code; data must be +reallocated/initialised at the start of each new generation. This is +normally done from the &s.code;ChipScreenInit()&e.code; function, and +Init functions for other modules that it calls. Data allocated in this +way should be freed by the driver's &s.code;ChipCloseScreen()&e.code; +functions, and Close functions for other modules that it calls. A new +&s.code;devPrivates&e.code; entry is allocated by calling the +&s.code;AllocateScreenPrivateIndex()&e.code; function. + + <quote><p> + &s.code;int AllocateScreenPrivateIndex()&e.code; + <quote><p> + This function allocates a new element in the + &s.code;devPrivates&e.code; field of all currently existing + &s.code;ScreenRecs&e.code;. The return value is the index of this + new element in the &s.code;devPrivates&e.code; array. The + &s.code;devPrivates&e.code; field is of type + &s.code;DevUnion&e.code;: + + <verb> + typedef union _DevUnion { + pointer ptr; + long val; + unsigned long uval; + pointer (*fptr)(void); + } DevUnion; + </verb> + + which allows the element to be used for any of the above types. + It is commonly used as a pointer to data that the caller allocates + after the new index has been allocated. + + This function will return &s.code;-1&e.code; when there is an + error allocating the new index. + + </quote> + </quote> + +The &s.code;ScrnInfoRec&e.code; &s.code;privates&e.code; data persists +for the life of the server, so only needs to be allocated once. This +should be done from the &s.code;ChipPreInit()&e.code; function, and Init +functions for other modules that it calls. Data allocated in this way +should be freed by the driver's &s.code;ChipFreeScreen()&e.code; functions, +and Free functions for other modules that it calls. A new +&s.code;privates&e.code; entry is allocated by calling the +&s.code;xf86AllocateScrnInfoPrivateIndex()&e.code; function. + + + <quote><p> + &s.code;int xf86AllocateScrnInfoPrivateIndex()&e.code; + <quote><p> + This function allocates a new element in the &s.code;privates&e.code; + field of all currently existing &s.code;ScrnInfoRecs&e.code;. + The return value is the index of this new element in the + &s.code;privates&e.code; array. The &s.code;privates&e.code; + field is of type &s.code;DevUnion&e.code;: + + <verb> + typedef union _DevUnion { + pointer ptr; + long val; + unsigned long uval; + pointer (*fptr)(void); + } DevUnion; + </verb> + + which allows the element to be used for any of the above types. + It is commonly used as a pointer to data that the caller allocates + after the new index has been allocated. + + This function will not return when there is an error allocating + the new index. When there is an error it will cause the server + to exit with a fatal error. The similar function for allocation + privates in the &s.code;ScreenRec&e.code; + (&s.code;AllocateScreenPrivateIndex()&e.code;) differs in this + respect by returning &s.code;-1&e.code; when the allocation fails. + + </quote> + </quote> + +<sect>Keeping Track of Bus Resources<label id="rac"> +<p> + +<sect1>Theory of Operation +<p> + +The XFree86 common layer has knowledge of generic access control mechanisms +for devices on certain bus systems (currently the PCI bus) as well as +of methods to enable or disable access to the buses itself. Furthermore +it can access information on resources decoded by these devices and if +necessary modify it. + +When first starting the Xserver collects all this information, saves it +for restoration, checks it for consistency, and if necessary, corrects +it. Finally it disables all resources on a generic level prior to +calling any driver function. + +When the &s.code;Probe()&e.code; function of each driver is called the +device sections are matched against the devices found in the system. +The driver may probe devices at this stage that cannot be identified by +using device independent methods. Access to all resources that can be +controlled in a device independent way is disabled. The +&s.code;Probe()&e.code; function should register all non-relocatable +resources at this stage. If a resource conflict is found between +exclusive resources the driver will fail immediately. Optionally the +driver might specify an &s.code;EntityInit()&e.code;, +&s.code;EntityLeave()&e.code; and &s.code;EntityEnter()&e.code; function. + +&s.code;EntityInit()&e.code; can be used to disable any shared resources +that are not controlled by the generic access control functions. It is +called prior to the PreInit phase regardless if an entity is active or +not. When calling the &s.code;EntityInit()&e.code;, +&s.code;EntityEnter()&e.code; and &s.code;EntityLeave()&e.code; functions +the common level will disable access to all other entities on a generic +level. Since the common level has no knowledge of device specific +methods to disable access to resources it cannot be guaranteed that +certain resources are not decoded by any other entity until the +&s.code;EntityInit()&e.code; or &s.code;EntityEnter()&e.code; phase is +finished. Device drivers should therefore register all those resources +which they are going to disable. If these resources are never to be +used by any driver function they may be flagged &s.code;ResInit&e.code; +so that they can be removed from the resource list after processing all +&s.code;EntityInit()&e.code; functions. &s.code;EntityEnter()&e.code; +should disable decoding of all resources which are not registered as +exclusive and which are not handled by the generic access control in +the common level. The difference to &s.code;EntityInit()&e.code; is +that the latter one is only called once during lifetime of the server. +It can therefore be used to set up variables prior to disabling resources. +&s.code;EntityLeave()&e.code; should restore the original state when +exiting the server or switching to a different VT. It also needs to +disable device specific access functions if they need to be disabled on +server exit or VT switch. The default state is to enable them before +giving up the VT. + +In &s.code;PreInit()&e.code; phase each driver should check if any +sharable resources it has registered during &s.code;Probe()&e.code; has +been denied and take appropriate action which could simply be to fail. +If it needs to access resources it has disabled during +&s.code;EntitySetup()&e.code; it can do so provided it has registered +these and will disable them before returning from +&s.code;PreInit()&e.code;. This also applies to all other driver +functions. Several functions are provided to request resource ranges, +register these, correct PCI config space and add replacements for the +generic access functions. Resources may be marked ``disabled'' or +``unused'' during OPERATING stage. Although these steps could also be +performed in &s.code;ScreenInit()&e.code;, this is not desirable. + +Following &s.code;PreInit()&e.code; phase the common level determines +if resource access control is needed. This is the case if more than +one screen is used. If necessary the RAC wrapper module is loaded. In +&s.code;ScreenInit()&e.code; the drivers can decide which operations +need to be placed under RAC. Available are the frame buffer operations, +the pointer operations and the colormap operations. Any operation that +requires resources which might be disabled during OPERATING state should +be set to use RAC. This can be specified separately for memory and IO +resources. + +When &s.code;ScreenInit()&e.code; phase is done the common level will +determine which shared resources are requested by more than one driver +and set the access functions accordingly. This is done following these +rules: + +<enum> +<item>The sharable resources registered by each entity are compared. If + a resource is registered by more than one entity the entity will be + marked to need to share this resources type (&s.code;IO&e.code; or + &s.code;MEM&e.code;). + +<item>A resource marked ``disabled'' during OPERATING state will be ignored + entirely. + +<item>A resource marked ``unused'' will only conflicts with an overlapping + resource of an other entity if the second is actually in use during + OPERATING state. + +<item>If an ``unused'' resource was found to conflict however the entity + does not use any other resource of this type the entire resource type + will be disabled for that entity. +</enum> + +The driver has the choice among different ways to control access to +certain resources: + +<enum> +<item>It can rely on the generic access functions. This is probably the + most common case. Here the driver only needs to register any resource + it is going to use. + +<item>It can replace the generic access functions by driver specific + ones. This will mostly be used in cases where no generic access + functions are available. In this case the driver has to make sure + these resources are disabled when entering the &s.code;PreInit()&e.code; + stage. Since the replacement functions are registered in + &s.code;PreInit()&e.code; the driver will have to enable these + resources itself if it needs to access them during this state. The + driver can specify if the replacement functions can control memory + and/or I/O resources separately. + +<item>The driver can enable resources itself when it needs them. Each + driver function enabling them needs to disable them before it will + return. This should be used if a resource which can be controlled + in a device dependent way is only required during SETUP state. This + way it can be marked ``unused'' during OPERATING state. +</enum> + +A resource which is decoded during OPERATING state however never accessed +by the driver should be marked unused. + +Since access switching latencies are an issue during Xserver operation, +the common level attempts to minimize the number of entities that need +to be placed under RAC control. When a wrapped operation is called, +the &s.code;EnableAccess()&e.code; function is called before control is +passed on. &s.code;EnableAccess()&e.code; checks if a screen is under +access control. If not it just establishes bus routing and returns. +If the screen needs to be under access control, +&s.code;EnableAccess()&e.code; determines which resource types +(&s.code;MEM&e.code;, &s.code;IO&e.code;) are required. Then it tests +if this access is already established. If so it simply returns. If +not it disables the currently established access, fixes bus routing and +enables access to all entities registered for this screen. + +Whenever a mode switch or a VT-switch is performed the common level will +return to SETUP state. + +<sect1>Resource Types +<p> + +Resource have certain properties. When registering resources each range +is accompanied by a flag consisting of the ORed flags of the different +properties the resource has. Each resource range may be classified +according to + +<itemize> + <item>its physical properties i.e., if it addresses + memory (&s.code;ResMem&e.code;) or + I/O space (&s.code;ResIo&e.code;), + <item>if it addresses a + block (&s.code;ResBlock&e.code;) or + sparse (&s.code;ResSparse&e.code;) + range, + <item>its access properties. +</itemize> + +There are two known access properties: + +<itemize> + <item>&s.code;ResExclusive&e.code; + for resources which may not be shared with any other device and + <item>&s.code;ResShared&e.code; + for resources which can be disabled and therefore can be shared. +</itemize> + +If it is necessary to test a resource against any type a generic access +type &s.code;ResAny&e.code; is provided. If this is set the resource +will conflict with any resource of a different entity intersecting its +range. Further it can be specified that a resource is decoded however +never used during any stage (&s.code;ResUnused&e.code;) or during +OPERATING state (&s.code;ResUnusedOpr&e.code;). A resource only visible +during the init functions (ie. &s.code;EntityInit()&e.code;, +&s.code;EntityEnter()&e.code; and &s.code;EntityLeave()&e.code; should +be registered with the flag &s.code;ResInit&e.code;. A resource that +might conflict with background resource ranges may be flagged with +&s.code;ResBios&e.code;. This might be useful when registering resources +ranges that were assigned by the system Bios. + +Several predefined resource lists are available for VGA and 8514/A +resources in &s.code;common/xf86Resources.h&e.code;. + +<sect1>Available Functions<label id="avail"> +<p> + +The functions provided for resource management are listed in their order +of use in the driver. + + +<sect2>Probe Phase +<p> + +In this phase each driver detects those resources it is able to drive, +creates an entity record for each of them, registers non-relocatable +resources and allocates screens and adds the resources to screens. + +Two helper functions are provided for matching device sections in the +xorg.conf file to the devices: + + <quote><p> + &s.code;int xf86MatchPciInstances(const char *driverName, int vendorID, + &f.indent;SymTabPtr chipsets, PciChipsets *PCIchipsets, + &f.indent;GDevPtr *devList, int numDevs, DriverPtr drvp, + &f.indent;int **foundEntities)&e.code; + <quote><p> + This function finds matches between PCI cards that a driver supports + and config file device sections. It is intended for use in the + &s.code;ChipProbe()&e.code; function of drivers for PCI cards. + Only probed PCI devices with a vendor ID matching + &s.code;vendorID&e.code; are considered. &s.code;devList&e.code; + and &s.code;numDevs&e.code; are typically those found from + calling &s.code;xf86MatchDevice()&e.code;, and represent the active + config file device sections relevant to the driver. + &s.code;PCIchipsets&e.code; is a table that provides a mapping + between the PCI device IDs, the driver's internal chipset tokens + and a list of fixed resources. + + When a device section doesn't have a &s.key;BusID&e.key; entry it + can only match the primary video device. Secondary devices are + only matched with device sections that have a matching + &s.key;BusID&e.key; entry. + + Once the preliminary matches have been found, a final match is + confirmed by checking if the chipset override, ChipID override or + probed PCI chipset type match one of those given in the + &s.code;chipsets&e.code; and &s.code;PCIchipsets&e.code; lists. + The &s.code;PCIchipsets&e.code; list includes a list of the PCI + device IDs supported by the driver. The list should be terminated + with an entry with PCI ID &s.code;-1&e.code;". The + &s.code;chipsets&e.code; list is a table mapping the driver's + internal chipset tokens to names, and should be terminated with + a &s.code;NULL&e.code; entry. Only those entries with a + corresponding entry in the &s.code;PCIchipsets&e.code; list are + considered. The order of precedence is: config file chipset, + config file ChipID, probed PCI device ID. + + In cases where a driver handles PCI chipsets with more than one + vendor ID, it may set &s.code;vendorID&e.code; to + &s.code;0&e.code;, and OR each devID in the list with (the + vendor ID << 16). + + Entity index numbers for confirmed matches are returned as an + array via &s.code;foundEntities&e.code;. The PCI information, + chipset token and device section for each match are found in the + &s.code;EntityInfoRec&e.code; referenced by the indices. + + The function return value is the number of confirmed matches. A + return value of &s.code;-1&e.code; indicates an internal error. + The returned &s.code;foundEntities&e.code; array should be freed + by the driver with &s.code;xfree()&e.code; when it is no longer + needed in cases where the return value is greater than zero. + + </quote> + + &s.code;int xf86MatchIsaInstances(const char *driverName, + &f.indent;SymTabPtr chipsets, IsaChipsets *ISAchipsets, + &f.indent;DriverPtr drvp, FindIsaDevProc FindIsaDevice, + &f.indent;GDevPtr *devList, int numDevs, + int **foundEntities)&e.code; + <quote><p> + This function finds matches between ISA cards that a driver supports + and config file device sections. It is intended for use in the + &s.code;ChipProbe()&e.code; function of drivers for ISA cards. + &s.code;devList&e.code; and &s.code;numDevs&e.code; are + typically those found from calling &s.code;xf86MatchDevice()&e.code;, + and represent the active config file device sections relevant to + the driver. &s.code;ISAchipsets&e.code; is a table that provides + a mapping between the driver's internal chipset tokens and the + resource classes. &s.code;FindIsaDevice&e.code; is a + driver-provided function that probes the hardware and returns the + chipset token corresponding to what was detected, and + &s.code;-1&e.code; if nothing was detected. + + If the config file device section contains a chipset entry, then + it is checked against the &s.code;chipsets&e.code; list. When + no chipset entry is present, the &s.code;FindIsaDevice&e.code; + function is called instead. + + Entity index numbers for confirmed matches are returned as an + array via &s.code;foundEntities&e.code;. The chipset token and + device section for each match are found in the + &s.code;EntityInfoRec&e.code; referenced by the indices. + + The function return value is the number of confirmed matches. A + return value of &s.code;-1&e.code; indicates an internal error. + The returned &s.code;foundEntities&e.code; array should be freed + by the driver with &s.code;xfree()&e.code; when it is no longer + needed in cases where the return value is greater than zero. + + </quote> + </quote> + +These two helper functions make use of several core functions that are +available at the driver level: + + <quote><p> + &s.code;Bool xf86ParsePciBusString(const char *busID, int *bus, + &f.indent;int *device, int *func)&e.code; + <quote><p> + Takes a &s.code;BusID&e.code; string, and if it is in the correct + format, returns the PCI &s.code;bus&e.code;, &s.code;device&e.code;, + &s.code;func&e.code; values that it indicates. The format of the + string is expected to be "PCI:bus:device:func" where each of `bus', + `device' and `func' are decimal integers. The ":func" part may + be omitted, and the func value assumed to be zero, but this isn't + encouraged. The "PCI" prefix may also be omitted. The prefix + "AGP" is currently equivalent to the "PCI" prefix. If the string + isn't a valid PCI BusID, the return value is &s.code;FALSE&e.code;. + + </quote> + + + &s.code;Bool xf86ComparePciBusString(const char *busID, int bus, + &f.indent;int device, int func)&e.code; + <quote><p> + Compares a &s.code;BusID&e.code; string with PCI &s.code;bus&e.code;, + &s.code;device&e.code;, &s.code;func&e.code; values. If they + match &s.code;TRUE&e.code; is returned, and &s.code;FALSE&e.code; + if they don't. + + </quote> + + &s.code;Bool xf86ParseIsaBusString(const char *busID)&e.code; + <quote><p> + Compares a &s.code;BusID&e.code; string with the ISA bus ID string + ("ISA" or "ISA:"). If they match &s.code;TRUE&e.code; is returned, + and &s.code;FALSE&e.code; if they don't. + + </quote> + + &s.code;Bool xf86CheckPciSlot(int bus, int device, int func)&e.code; + <quote><p> + Checks if the PCI slot &s.code;bus:device:func&e.code; has been + claimed. If so, it returns &s.code;FALSE&e.code;, and otherwise + &s.code;TRUE&e.code;. + + </quote> + + &s.code;int xf86ClaimPciSlot(int bus, int device, int func, DriverPtr drvp, + &f.indent;int chipset, GDevPtr dev, Bool active)&e.code; + <quote><p> + This function is used to claim a PCI slot, allocate the associated + entity record and initialise their data structures. The return + value is the index of the newly allocated entity record, or + &s.code;-1&e.code; if the claim fails. This function should always + succeed if &s.code;xf86CheckPciSlot()&e.code; returned + &s.code;TRUE&e.code; for the same PCI slot. + + </quote> + + &s.code;Bool xf86IsPrimaryPci(void)&e.code; + <quote><p> + This function returns &s.code;TRUE&e.code; if the primary card is + a PCI device, and &s.code;FALSE&e.code; otherwise. + + </quote> + + &s.code;int xf86ClaimIsaSlot(DriverPtr drvp, int chipset, + &f.indent;GDevPtr dev, Bool active)&e.code; + <quote><p> + This allocates an entity record entity and initialise the data + structures. The return value is the index of the newly allocated + entity record. + + </quote> + + &s.code;Bool xf86IsPrimaryIsa(void)&e.code; + <quote><p> + This function returns &s.code;TRUE&e.code; if the primary card is + an ISA (non-PCI) device, and &s.code;FALSE&e.code; otherwise. + + </quote> + </quote> + +Two helper functions are provided to aid configuring entities: + <quote><p> + &s.code;ScrnInfoPtr xf86ConfigPciEntity(ScrnInfoPtr pScrn, + &f.indent;int scrnFlag, int entityIndex, + &f.indent;PciChipsets *p_chip, + &f.indent;resList res, EntityProc init, + &f.indent;EntityProc enter, EntityProc leave, + &f.indent;pointer private)&e.code; + <p> + &s.code;ScrnInfoPtr xf86ConfigIsaEntity(ScrnInfoPtr pScrn, + &f.indent;int scrnFlag, int entityIndex, + &f.indent;IsaChipsets *i_chip, + &f.indent;resList res, EntityProc init, + &f.indent;EntityProc enter, EntityProc leave, + &f.indent;pointer private)&e.code; + <quote><p> + These functions are used to register the non-relocatable resources + for an entity, and the optional entity-specific &s.code;Init&e.code;, &s.code;Enter&e.code; and + &s.code;Leave&e.code; functions. Usually the list of fixed resources is obtained + from the Isa/PciChipsets lists. However an additional list of + resources may be passed. Generally this is not required. + For active entities a &s.code;ScrnInfoRec&e.code; is allocated + if the &s.code;pScrn&e.code; argument is &s.code;NULL&e.code;. +The + return value is &s.code;TRUE&e.code; when successful. The init, enter, leave + functions are defined as follows: + + <quote> + &s.code;typedef void (*EntityProc)(int entityIndex, + &f.indent;pointer private)&e.code; + </quote> + + They are passed the entity index and a pointer to a private scratch + area. This can be set up during &s.code;Probe()&e.code; and + its address can be passed to + &s.code;xf86ConfigIsaEntity()&e.code; and + &s.code;xf86ConfigPciEntity()&e.code; as the last argument. + + </quote> + </quote> + +These two helper functions make use of several core functions that are +available at the driver level: + <quote><p> + &s.code;void xf86ClaimFixedResources(resList list, int entityIndex)&e.code; + <quote><p> + This function registers the non-relocatable resources which cannot + be disabled and which therefore would cause the server to fail + immediately if they were found to conflict. It also records + non-relocatable but sharable resources for processing after the + &s.code;Probe()&e.code; phase. + + </quote> + + &s.code;Bool xf86SetEntityFuncs(int entityIndex, EntityProc init, + &f.indent;EntityProc enter, EntityProc leave, pointer)&e.code; + <quote><p> + This function registers with an entity the &s.code;init&e.code;, + &s.code;enter&e.code;, &s.code;leave&e.code; functions along + with the pointer to their private area. + + </quote> + + &s.code;void xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex)&e.code; + <quote><p> + This function associates the entity referenced by + &s.code;entityIndex&e.code; with the screen. + + </quote> + </quote> + +<sect2>PreInit Phase +<p> + +During this phase the remaining resources should be registered. +&s.code;PreInit()&e.code; should call &s.code;xf86GetEntityInfo()&e.code; +to obtain a pointer to an &s.code;EntityInfoRec&e.code; for each entity +it is able to drive and check if any resource are listed in its +&s.code;resources&e.code; field. If resources registered in the Probe +phase have been rejected in the post-Probe phase +(&s.code;resources&e.code; is non-&s.code;NULL&e.code;), then the driver should +decide if it can continue without using these or if it should fail. + + <quote><p> + &s.code;EntityInfoPtr xf86GetEntityInfo(int entityIndex)&e.code; + <quote><p> + This function returns a pointer to the &s.code;EntityInfoRec&e.code; + referenced by &s.code;entityIndex&e.code;. The returned + &s.code;EntityInfoRec&e.code; should be freed with + &s.code;xfree()&e.code; when no longer needed. + + </quote> + </quote> +Several functions are provided to simplify resource registration: + <quote><p> + &s.code;Bool xf86IsEntityPrimary(int entityIndex)&e.code; + <quote><p> + This function returns &s.code;TRUE&e.code; if the entity referenced + by &s.code;entityIndex&e.code; is the primary display device (i.e., + the one initialised at boot time and used in text mode). + + </quote> + + &s.code;Bool xf86IsScreenPrimary(int scrnIndex)&e.code; + <quote><p> + This function returns &s.code;TRUE&e.code; if the primary entity + is registered with the screen referenced by + &s.code;scrnIndex&e.code;. + + </quote> + + &s.code;pciVideoPtr xf86GetPciInfoForEntity(int entityIndex)&e.code; + <quote><p> + This function returns a pointer to the &s.code;pciVideoRec&e.code; + for the specified entity. If the entity is not a PCI device, + &s.code;NULL&e.code; is returned. + + </quote> + </quote> + +The primary function for registration of resources is: + <quote><p> + &s.code;resPtr xf86RegisterResources(int entityIndex, resList list, + &f.indent;int access)&e.code; + <quote><p> + This function tries to register the resources in + &s.code;list&e.code;. If list is &s.code;NULL&e.code; it tries + to determine the resources automatically. This only works for + entities that provide a generic way to read out the resource ranges + they decode. So far this is only the case for PCI devices. By + default the PCI resources are registered as shared + (&s.code;ResShared&e.code;) if the driver wants to set a different + access type it can do so by specifying the access flags in the + third argument. A value of &s.code;0&e.code; means to use the + default settings. If for any reason the resource broker is not + able to register some of the requested resources the function will + return a pointer to a list of the failed ones. In this case the + driver may be able to move the resource to different locations. + In case of PCI bus entities this is done by passing the list of + failed resources to &s.code;xf86ReallocatePciResources()&e.code;. + When the registration succeeds, the return value is + &s.code;NULL&e.code;. + + </quote> + + &s.code;resPtr xf86ReallocatePciResources(int entityIndex, resPtr pRes)&e.code; + <quote><p> + This function takes a list of PCI resources that need to be + reallocated and returns &s.code;NULL&e.code when all relocations are + successful. + &s.code;xf86RegisterResources()&e.code; should be called again to + register the relocated resources with the broker. + If the reallocation fails, a list of the resources that could not be + relocated is returned. + + </quote> + </quote> + +Two functions are provided to obtain a resource range of a given type: + <quote><p> + &s.code;resRange xf86GetBlock(long type, memType size, + &f.indent;memType window_start, memType window_end, + &f.indent;memType align_mask, resPtr avoid)&e.code; + <quote><p> + This function tries to find a block range of size + &s.code;size&e.code; and type &s.code;type&e.code; in a window + bound by &s.code;window_start&e.code; and &s.code;window_end&e.code; + with the alignment specified in &s.code;align_mask&e.code;. + Optionally a list of resource ranges which should be avoided within + the window can be supplied. On failure a zero-length range of + type &s.code;ResEnd&e.code; will be returned. + + </quote> + &s.code;resRange xf86GetSparse(long type, memType fixed_bits, + &f.indent;memType decode_mask, memType address_mask, + &f.indent;resPtr avoid)&e.code; + <quote><p> + This function is like the previous one, but attempts to find a + sparse range instead of a block range. Here three values have to + be specified: the &s.code;address_mask&e.code; which marks all + bits of the mask part of the address, the &s.code;decode_mask&e.code; + which masks out the bits which are hardcoded and are therefore + not available for relocation and the values of the fixed bits. + The function tries to find a base that satisfies the given condition. + If the function fails it will return a zero range of type + &s.code;ResEnd&e.code;. Optionally it might be passed a list of + resource ranges to avoid. + + </quote> + </quote> + +Some PCI devices are broken in the sense that they return invalid size +information for a certain resource. In this case the driver can supply +the correct size and make sure that the resource range allocated for +the card is large enough to hold the address range decoded by the card. +The function &s.code;xf86FixPciResource()&e.code; can be used to do this: + <quote><p> + &s.code;Bool xf86FixPciResource(int entityIndex, unsigned int prt, + &f.indent;CARD32 alignment, long type)&e.code; + <quote><p> + This function fixes a PCI resource allocation. The + &s.code;prt&e.code; parameter contains the number of the PCI base + register that needs to be fixed (&s.code;0-5&e.code;, and + &s.code;6&e.code; for the BIOS base register). The size is + specified by the alignment. Since PCI resources need to span an + integral range of size &s.code;2^n&e.code;, the alignment also + specifies the number of addresses that will be decoded. If the + driver specifies a type mask it can override the default type for + PCI resources which is &s.code;ResShared&e.code;. The resource + broker needs to know that to find a matching resource range. This + function should be called before calling + &s.code;xf86RegisterResources()&e.code;. The return value is + &s.code;TRUE&e.code; when the function succeeds. + + </quote> + + &s.code;Bool xf86CheckPciMemBase(pciVideoPtr pPci, memType base)&e.code; + <quote><p> + This function checks that the memory base address specified matches + one of the PCI base address register values for the given PCI + device. This is mostly used to check that an externally provided + base address (e.g., from a config file) matches an actual value + allocated to a device. + + </quote> + </quote> + +The driver may replace the generic access control functions for an entity. +This is done with the &s.code;xf86SetAccessFuncs()&e.code;: + <quote><p> + &s.code;void xf86SetAccessFuncs(EntityInfoPtr pEnt, + &f.indent;xf86SetAccessFuncPtr funcs, + &f.indent;xf86SetAccessFuncPtr oldFuncs)&e.code; + <quote><p> + with: + </quote> + + <verb> + typedef struct { + xf86AccessPtr mem; + xf86AccessPtr io; + xf86AccessPtr io_mem; + } xf86SetAccessFuncRec, *xf86SetAccessFuncPtr; + </verb> + + <quote><p> + The driver can pass three functions: one for I/O access, one for + memory access and one for combined memory and I/O access. If the + memory access and combined access functions are identical the + common level assumes that the memory access cannot be controlled + independently of I/O access, if the I/O access function and the + combined access functions are the same it is assumed that I/O can + not be controlled independently. If memory and I/O have to be + controlled together all three values should be the same. If a + non &s.code;NULL&e.code; value is passed as third argument it is + interpreted as an address where to store the old access record. + If the third argument is &s.code;NULL&e.code; it will be assumed + that the generic access should be enabled before replacing the + access functions. Otherwise it will be disabled. The driver may + enable them itself using the returned values. It should do this + from its replacement access functions as the generic access may + be disabled by the common level on certain occasions. If replacement + functions are specified they must control all resources of the + specific type registered for the entity. + + </quote> + </quote> + +To find out if a specific resource range conflicts with another +resource the &s.code;xf86ChkConflict()&e.code; function may be used: + <quote><p> + &s.code;memType xf86ChkConflict(resRange *rgp, int entityIndex)&e.code; + <quote><p> + This function checks if the resource range &s.code;rgp&e.code; of + for the specified entity conflicts with with another resource. + If a conflict is found, the address of the start of the conflict + is returned. The return value is zero when there is no conflict. + + </quote> + </quote> + +The OPERATING state properties of previously registered fixed resources +can be set with the &s.code;xf86SetOperatingState()&e.code; function: + <quote><p> + &s.code;resPtr xf86SetOperatingState(resList list, int entityIndex, + &f.indent;int mask)&e.code; + <quote><p> + This function is used to set the status of a resource during + OPERATING state. &s.code;list&e.code; holds a list to which + &s.code;mask&e.code; is to be applied. The parameter + &s.code;mask&e.code; may have the value &s.code;ResUnusedOpr&e.code; + and &s.code;ResDisableOpr&e.code;. The first one should be used + if a resource isn't used by the driver during OPERATING state + although it is decoded by the device, while the latter one indicates + that the resource is not decoded during OPERATING state. Note + that the resource ranges have to match those specified during + registration. If a range has been specified starting at + &s.code;A&e.code; and ending at &s.code;B&e.code; and suppose + &s.code;C&e.code; us a value satisfying + &s.code;A < C < B&e.code; one may not + specify the resource range &s.code;(A,B)&e.code; by splitting it + into two ranges &s.code;(A,C)&e.code; and &s.code;(C,B)&e.code;. + + </quote> + </quote> + +The following two functions are provided for special cases: + <quote><p> + &s.code;void xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn, int entityIndex)&e.code; + <quote><p> + This function may be used to remove an entity from a screen. This + only makes sense if a screen has more than one entity assigned or + the screen is to be deleted. No test is made if the screen has + any entities left. + + </quote> + + &s.code;void xf86DeallocateResourcesForEntity(int entityIndex, long type)&e.code; + <quote><p> + This function deallocates all resources of a given type registered + for a certain entity from the resource broker list. + + </quote> + </quote> + +<sect2>ScreenInit Phase +<p> + +All that is required in this phase is to setup the RAC flags. Note that +it is also permissible to set these flags up in the PreInit phase. The +RAC flags are held in the &s.code;racIoFlags&e.code; and &s.code;racMemFlags&e.code; fields of the +&s.code;ScrnInfoRec&e.code; for each screen. They specify which graphics operations +might require the use of shared resources. This can be specified +separately for memory and I/O resources. The available flags are defined +in &s.code;rac/xf86RAC.h&e.code;. They are: + + &s.code;RAC_FB&e.code; + <quote> + for framebuffer operations (including hw acceleration) + </quote> + &s.code;RAC_CURSOR&e.code; + <quote> + for Cursor operations + (??? I'm not sure if we need this for SW cursor it depends + on which level the sw cursor is drawn) + </quote> + &s.code;RAC_COLORMAP&e.code; + <quote> + for colormap operations + </quote> + &s.code;RAC_VIEWPORT&e.code; + <quote> + for the call to &s.code;ChipAdjustFrame()&e.code; </quote> + + +The flags are ORed together. + +<sect>Config file ``Option'' entries<label id="options"> +<p> + +Option entries are permitted in most sections and subsections of the +config file. There are two forms of option entries: + +<descrip> +<tag>Option "option-name"</tag> + A boolean option. +<tag>Option "option-name" "option-value"</tag> + An option with an arbitrary value. +</descrip> + +The option entries are handled by the parser, and a list of the parsed +options is included with each of the appropriate data structures that +the drivers have access to. The data structures used to hold the option +information are opaque to the driver, and a driver must not access the +option data directly. Instead, the common layer provides a set of +functions that may be used to access, check and manipulate the option +data. + +First, the low level option handling functions. In most cases drivers +would not need to use these directly. + + <quote><p> + &s.code;pointer xf86FindOption(pointer options, const char *name)&e.code; + <quote><p> + Takes a list of options and an option name, and returns a handle + for the first option entry in the list matching the name. Returns + &s.code;NULL&e.code; if no match is found. + + </quote> + + &s.code;char *xf86FindOptionValue(pointer options, const char *name)&e.code; + <quote><p> + Takes a list of options and an option name, and returns the value + associated with the first option entry in the list matching the + name. If the matching option has no value, an empty string + (&s.code;""&e.code;) is returned. Returns &s.code;NULL&e.code; + if no match is found. + + </quote> + + &s.code;void xf86MarkOptionUsed(pointer option)&e.code; + <quote><p> + Takes a handle for an option, and marks that option as used. + + </quote> + + &s.code;void xf86MarkOptionUsedByName(pointer options, const char *name)&e.code; + <quote><p> + Takes a list of options and an option name and marks the first + option entry in the list matching the name as used. + + </quote> + </quote> + + +Next, the higher level functions that most drivers would use. + <quote><p> + &s.code;void xf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts)&e.code; + <quote><p> + Collect the options from each of the config file sections used by + the screen (&s.code;pScrn&e.code;) and return the merged list as + &s.code;pScrn->options&e.code;. This function requires that + &s.code;pScrn->confScreen&e.code;, &s.code;pScrn->display&e.code;, + &s.code;pScrn->monitor&e.code;, + &s.code;pScrn->numEntities&e.code;, and + &s.code;pScrn->entityList&e.code; are initialised. + &s.code;extraOpts&e.code; may optionally be set to an additional + list of options to be combined with the others. The order of + precedence for options is &s.code;extraOpts&e.code;, display, + confScreen, monitor, device. + + </quote> + + &s.code;void xf86ProcessOptions(int scrnIndex, pointer options, + &f.indent;OptionInfoPtr optinfo)&e.code; + <quote><p> + Processes a list of options according to the information in the + array of &s.code;OptionInfoRecs&e.code; (&s.code;optinfo&e.code;). + The resulting information is stored in the &s.code;value&e.code; + fields of the appropriate &s.code;optinfo&e.code; entries. The + &s.code;found&e.code; fields are set to &s.code;TRUE&e.code; + when an option with a value of the correct type if found, and + &s.code;FALSE&e.code; otherwise. The &s.code;type&e.code; field + is used to determine the expected value type for each option. + Each option in the list of options for which there is a name match + (but not necessarily a value type match) is marked as used. + Warning messages are printed when option values don't match the + types specified in the optinfo data. + + NOTE: If this function is called before a driver's screen number + is known (e.g., from the &s.code;ChipProbe()&e.code; function) a + &s.code;scrnIndex&e.code; value of &s.code;-1&e.code; should be + used. + + NOTE 2: Given that this function stores into the + &s.code;OptionInfoRecs&e.code; pointed to by &s.code;optinfo&e.code, + the caller should ensure the &s.code;OptionInfoRecs&e.code; are + (re-)initialised before the call, especially if the caller expects + to use the predefined option values as defaults. + + The &s.code;OptionInfoRec&e.code; is defined as follows: + + <verb> + typedef struct { + double freq; + int units; + } OptFrequency; + + typedef union { + unsigned long num; + char * str; + double realnum; + Bool bool; + OptFrequency freq; + } ValueUnion; + + typedef enum { + OPTV_NONE = 0, + OPTV_INTEGER, + OPTV_STRING, /* a non-empty string */ + OPTV_ANYSTR, /* Any string, including an empty one */ + OPTV_REAL, + OPTV_BOOLEAN, + OPTV_PERCENT, + OPTV_FREQ + } OptionValueType; + + typedef enum { + OPTUNITS_HZ = 1, + OPTUNITS_KHZ, + OPTUNITS_MHZ + } OptFreqUnits; + + typedef struct { + int token; + const char* name; + OptionValueType type; + ValueUnion value; + Bool found; + } OptionInfoRec, *OptionInfoPtr; + </verb> + + &s.code;OPTV_FREQ&e.code; can be used for options values that are + frequencies. These values are a floating point number with an + optional unit name appended. The unit name can be one of "Hz", + "kHz", "k", "MHz", "M". The multiplier associated with the unit + is stored in &s.code;freq.units&e.code;, and the scaled frequency + is stored in &s.code;freq.freq&e.code;. When no unit is specified, + &s.code;freq.units&e.code; is set to &s.code;0&e.code;, and + &s.code;freq.freq&e.code; is unscaled. + + &s.code;OPTV_PERCENT&e.code; can be used for option values that are + specified in percent (e.g. "20%"). These values are a floating point + number with a percent sign appended. If the percent sign is missing, + the parser will fail to match the value. + + Typical usage is to setup an array of + &s.code;OptionInfoRecs&e.code; with all fields initialised. + The &s.code;value&e.code; and &s.code;found&e.code; fields get + set by &s.code;xf86ProcessOptions()&e.code;. For cases where the + value parsing is more complex, the driver should specify + &s.code;OPTV_STRING&e.code;, and parse the string itself. An + example of using this option handling is included in the + <ref id="sample" name="Sample Driver"> section. + + </quote> + + &s.code;void xf86ShowUnusedOptions(int scrnIndex, pointer options)&e.code; + <quote><p> + Prints out warning messages for each option in the list of options + that isn't marked as used. This is intended to show options that + the driver hasn't recognised. It would normally be called near + the end of the &s.code;ChipScreenInit()&e.code; function, but only + when &s.code;serverGeneration == 1&e.code;. + + </quote> + + &s.code;OptionInfoPtr xf86TokenToOptinfo(const OptionInfoRec *table, + &f.indent;int token)&e.code; + + <quote><p> + Returns a pointer to the &s.code;OptionInfoRec&e.code; in + &s.code;table&e.code; with a token field matching + &s.code;token&e.code;. Returns &s.code;NULL&e.code; if no match + is found. + + </quote> + + &s.code;Bool xf86IsOptionSet(const OptionInfoRec *table, int token)&e.code; + <quote><p> + Returns the &s.code;found&e.code; field of the + &s.code;OptionInfoRec&e.code; in &s.code;table&e.code; with a + &s.code;token&e.code; field matching &s.code;token&e.code;. This + can be used for options of all types. Note that for options of + type &s.code;OPTV_BOOLEAN&e.code;, it isn't sufficient to check + this to determine the value of the option. Returns + &s.code;FALSE&e.code; if no match is found. + + </quote> + + &s.code;char *xf86GetOptValString(const OptionInfoRec *table, int token)&e.code; + <quote><p> + Returns the &s.code;value.str&e.code; field of the + &s.code;OptionInfoRec&e.code; in &s.code;table&e.code; with a + token field matching &s.code;token&e.code;. Returns + &s.code;NULL&e.code; if no match is found. + + </quote> + + &s.code;Bool xf86GetOptValInteger(const OptionInfoRec *table, int token, + &f.indent;int *value)&e.code; + <quote><p> + Returns via &s.code;*value&e.code; the &s.code;value.num&e.code; + field of the &s.code;OptionInfoRec&e.code; in &s.code;table&e.code; + with a &s.code;token&e.code; field matching &s.code;token&e.code;. + &s.code;*value&e.code; is only changed when a match is found so + it can be safely initialised with a default prior to calling this + function. The function return value is as for + &s.code;xf86IsOptionSet()&e.code;. + + </quote> + + &s.code;Bool xf86GetOptValULong(const OptionInfoRec *table, int token, + &f.indent;unsigned long *value)&e.code; + <quote><p> + Like &s.code;xf86GetOptValInteger()&e.code;, except the value is + treated as an &s.code;unsigned long&e.code;. + + </quote> + + &s.code;Bool xf86GetOptValReal(const OptionInfoRec *table, int token, + &f.indent;double *value)&e.code; + <quote><p> + Like &s.code;xf86GetOptValInteger()&e.code;, except that + &s.code;value.realnum&e.code; is used. + + </quote> + + &s.code;Bool xf86GetOptValFreq(const OptionInfoRec *table, int token, + &f.indent;OptFreqUnits expectedUnits, double *value)&e.code; + <quote><p> + Like &s.code;xf86GetOptValInteger()&e.code;, except that the + &s.code;value.freq&e.code; data is returned. The frequency value + is scaled to the units indicated by &s.code;expectedUnits&e.code;. + The scaling is exact when the units were specified explicitly in + the option's value. Otherwise, the &s.code;expectedUnits&e.code; + field is used as a hint when doing the scaling. In this case, + values larger than &s.code;1000&e.code; are assumed to have be + specified in the next smallest units. For example, if the Option + value is "10000" and expectedUnits is &s.code;OPTUNITS_MHZ&e.code;, + the value returned is &s.code;10&e.code;. + + </quote> + + &s.code;Bool xf86GetOptValBool(const OptionInfoRec *table, int token, Bool *value)&e.code; + <quote><p> + This function is used to check boolean options + (&s.code;OPTV_BOOLEAN&e.code;). If the function return value is + &s.code;FALSE&e.code;, it means the option wasn't set. Otherwise + &s.code;*value&e.code; is set to the boolean value indicated by + the option's value. No option &s.code;value&e.code; is interpreted + as &s.code;TRUE&e.code;. Option values meaning &s.code;TRUE&e.code; + are "1", "yes", "on", "true", and option values meaning + &s.code;FALSE&e.code; are "0", "no", "off", "false". Option names + both with the "no" prefix in their names, and with that prefix + removed are also checked and handled in the obvious way. + &s.code;*value&e.code; is not changed when the option isn't present. + It should normally be set to a default value before calling this + function. + + </quote> + + &s.code;Bool xf86ReturnOptValBool(const OptionInfoRec *table, int token, Bool def)&e.code; + <quote><p> + This function is used to check boolean options + (&s.code;OPTV_BOOLEAN&e.code;). If the option is set, its value + is returned. If the options is not set, the default value specified + by &s.code;def&e.code; is returned. The option interpretation is + the same as for &s.code;xf86GetOptValBool()&e.code;. + + </quote> + + &s.code;int xf86NameCmp(const char *s1, const char *s2)&e.code; + <quote><p> + This function should be used when comparing strings from the config + file with expected values. It works like &s.code;strcmp()&e.code;, + but is not case sensitive and space, tab, and `<tt>_</tt>' characters + are ignored in the comparison. The use of this function isn't + restricted to parsing option values. It may be used anywhere + where this functionality required. + + </quote> + </quote> + +<sect>Modules, Drivers, Include Files and Interface Issues +<p> + +NOTE: this section is incomplete. + + +<sect1>Include files +<p> + +The following include files are typically required by video drivers: + + <quote><p> + All drivers should include these: + <quote> + &s.code;"xf86.h"&nl; + "xf86_OSproc.h"&nl; + "xf86_ansic.h"&nl; + "xf86Resources.h"&e.code; + </quote> + Wherever inb/outb (and related things) are used the following should be + included: + <quote> + &s.code;"compiler.h"&e.code; + </quote> + Note: in drivers, this must be included after &s.code;"xf86_ansic.h"&e.code;. + + Drivers that need to access PCI vendor/device definitions need this: + <quote> + &s.code;"xf86PciInfo.h"&e.code; + </quote> + + Drivers that need to access the PCI config space need this: + <quote> + &s.code;"xf86Pci.h"&e.code; + </quote> + + Drivers that initialise a SW cursor need this: + <quote> + &s.code;"mipointer.h"&e.code; + </quote> + + All drivers implementing backing store need this: + <quote> + &s.code;"mibstore.h"&e.code; + </quote> + + All drivers using the mi colourmap code need this: + <quote> + &s.code;"micmap.h"&e.code; + </quote> + + If a driver uses the vgahw module, it needs this: + <quote> + &s.code;"vgaHW.h"&e.code; + </quote> + + Drivers supporting VGA or Hercules monochrome screens need: + <quote> + &s.code;"xf1bpp.h"&e.code; + </quote> + + Drivers supporting VGA or EGC 16-colour screens need: + <quote> + &s.code;"xf4bpp.h"&e.code; + </quote> + + Drivers using cfb need: + <quote> + &s.code;#define PSZ 8&nl; + #include "cfb.h"&nl; + #undef PSZ&e.code; + </quote> + + Drivers supporting bpp 16, 24 or 32 with cfb need one or more of: + <quote> + &s.code;"cfb16.h"&nl; + "cfb24.h"&nl; + "cfb32.h"&e.code; + </quote> + + If a driver uses XAA, it needs these: + <quote> + &s.code;"xaa.h"&nl; + "xaalocal.h"&e.code; + </quote> + + If a driver uses the fb manager, it needs this: + <quote> + &s.code;"xf86fbman.h"&e.code; + </quote> + </quote> + +Non-driver modules should include &s.code;"xf86_ansic.h"&e.code; to get the correct +wrapping of ANSI C/libc functions. + +All modules must NOT include any system include files, or the following: + + <quote> + &s.code;"xf86Priv.h"&nl; + "xf86Privstr.h"&nl; + "xf86_OSlib.h"&nl; + "Xos.h"&e.code; + </quote> + +In addition, "xf86_libc.h" must not be included explicitly. It is +included implicitly by "xf86_ansic.h". + + +<sect>Offscreen Memory Manager +<p> + +Management of offscreen video memory may be handled by the XFree86 +framebuffer manager. Once the offscreen memory manager is running, +drivers or extensions may allocate, free or resize areas of offscreen +video memory using the following functions (definitions taken from +&s.code;xf86fbman.h&e.code;): + +<code> + typedef struct _FBArea { + ScreenPtr pScreen; + BoxRec box; + int granularity; + void (*MoveAreaCallback)(struct _FBArea*, struct _FBArea*) + void (*RemoveAreaCallback)(struct _FBArea*) + DevUnion devPrivate; + } FBArea, *FBAreaPtr; + + typedef void (*MoveAreaCallbackProcPtr)(FBAreaPtr from, FBAreaPtr to) + typedef void (*RemoveAreaCallbackProcPtr)(FBAreaPtr) + + FBAreaPtr xf86AllocateOffscreenArea ( + ScreenPtr pScreen, + int width, int height, + int granularity, + MoveAreaCallbackProcPtr MoveAreaCallback, + RemoveAreaCallbackProcPtr RemoveAreaCallback, + pointer privData + ) + + void xf86FreeOffscreenArea (FBAreaPtr area) + + Bool xf86ResizeOffscreenArea ( + FBAreaPtr area + int w, int h + ) +</code> + +The function: +<quote> + &s.code;Bool xf86FBManagerRunning(ScreenPtr pScreen)&e.code; +</quote> + +can be used by an extension to check if the driver has initialized +the memory manager. The manager is not available if this returns +&s.code;FALSE&e.code; and the functions above will all fail. + + +&s.code;xf86AllocateOffscreenArea()&e.code; can be used to request a +rectangle of dimensions &s.code;width&e.code; x &s.code;height&e.code; +(in pixels) from unused offscreen memory. &s.code;granularity&e.code; +specifies that the leftmost edge of the rectangle must lie on some +multiple of &s.code;granularity&e.code; pixels. A granularity of zero +means the same thing as a granularity of one - no alignment preference. +A &s.code;MoveAreaCallback&e.code; can be provided to notify the requester +when the offscreen area is moved. If no &s.code;MoveAreaCallback&e.code; +is supplied then the area is considered to be immovable. The +&s.code;privData&e.code; field will be stored in the manager's internal +structure for that allocated area and will be returned to the requester +in the &s.code;FBArea&e.code; passed via the +&s.code;MoveAreaCallback&e.code;. An optional +&s.code;RemoveAreaCallback&e.code; is provided. If the driver provides +this it indicates that the area should be allocated with a lower priority. +Such an area may be removed when a higher priority request (one that +doesn't have a &s.code;RemoveAreaCallback&e.code;) is made. When this +function is called, the driver will have an opportunity to do whatever +cleanup it needs to do to deal with the loss of the area, but it must +finish its cleanup before the function exits since the offscreen memory +manager will free the area immediately after. + +&s.code;xf86AllocateOffscreenArea()&e.code; returns &s.code;NULL&e.code; +if it was unable to allocate the requested area. When no longer needed, +areas should be freed with &s.code;xf86FreeOffscreenArea()&e.code;. + +&s.code;xf86ResizeOffscreenArea()&e.code; resizes an existing +&s.code;FBArea&e.code;. &s.code;xf86ResizeOffscreenArea()&e.code; +returns &s.code;TRUE&e.code; if the resize was successful. If +&s.code;xf86ResizeOffscreenArea()&e.code; returns &s.code;FALSE&e.code;, +the original &s.code;FBArea&e.code; is left unmodified. Resizing an +area maintains the area's original &s.code;granularity&e.code;, +&s.code;devPrivate&e.code;, and &s.code;MoveAreaCallback&e.code;. +&s.code;xf86ResizeOffscreenArea()&e.code; has considerably less overhead +than freeing the old area then reallocating the new size, so it should +be used whenever possible. + +The function: + <quote> + &s.code;Bool xf86QueryLargestOffscreenArea( + &f.indent;ScreenPtr pScreen, + &f.indent;int *width, int *height, + &f.indent;int granularity, + &f.indent;int preferences, + &f.indent;int priority + &nl)&e.code; + </quote> + +is provided to query the width and height of the largest single +&s.code;FBArea&e.code; allocatable given a particular priority. +&s.code;preferences&e.code; can be one of the following to indicate +whether width, height or area should be considered when determining +which is the largest single &s.code;FBArea&e.code; available. + + <quote> + &s.code;FAVOR_AREA_THEN_WIDTH&nl; + FAVOR_AREA_THEN_HEIGHT&nl; + FAVOR_WIDTH_THEN_AREA&nl; + FAVOR_HEIGHT_THEN_AREA&e.code; + </quote> + +&s.code;priority&e.code; is one of the following: + + <quote><p> + &s.code;PRIORITY_LOW&e.code; + <quote><p> + Return the largest block available without stealing anyone else's + space. This corresponds to the priority of allocating a + &s.code;FBArea&e.code; when a &s.code;RemoveAreaCallback&e.code; + is provided. + + </quote> + &s.code;PRIORITY_NORMAL&e.code; + <quote><p> + Return the largest block available if it is acceptable to steal a + lower priority area from someone. This corresponds to the priority + of allocating a &s.code;FBArea&e.code; without providing a + &s.code;RemoveAreaCallback&e.code;. + + </quote> + &s.code;PRIORITY_EXTREME&e.code; + <quote><p> + Return the largest block available if all &s.code;FBAreas&e.code; + that aren't locked down were expunged from memory first. This + corresponds to any allocation made directly after a call to + &s.code;xf86PurgeUnlockedOffscreenAreas()&e.code;. + + </quote> + </quote> + + +The function: + + <quote> + &s.code;Bool xf86PurgeUnlockedOffscreenAreas(ScreenPtr pScreen)&e.code; + </quote> + +is provided as an extreme method to free up offscreen memory. This +will remove all removable &s.code;FBArea&e.code; allocations. + + +Initialization of the XFree86 framebuffer manager is done via + + <quote> + &s.code;Bool xf86InitFBManager(ScreenPtr pScreen, BoxPtr FullBox)&e.code; + </quote> + +&s.code;FullBox&e.code; represents the area of the framebuffer that the +manager is allowed to manage. This is typically a box with a width of +&s.code;pScrn->displayWidth&e.code; and a height of as many lines as +can be fit within the total video memory, however, the driver can reserve +areas at the extremities by passing a smaller area to the manager. + +&s.code;xf86InitFBManager()&e.code; must be called before XAA is +initialized since XAA uses the manager for it's pixmap cache. + +An alternative function is provided to allow the driver to initialize +the framebuffer manager with a Region rather than a box. + + <quote> + &s.code;Bool xf86InitFBManagerRegion(ScreenPtr pScreen, + &f.indent;RegionPtr FullRegion)&e.code; + </quote> + +&s.code;xf86InitFBManagerRegion()&e.code;, unlike +&s.code;xf86InitFBManager()&e.code;, does not remove the area used for +the visible screen so that area should not be included in the region +passed to the function. &s.code;xf86InitFBManagerRegion()&e.code; is +useful when non-contiguous areas are available to be managed, and is +required when multiple framebuffers are stored in video memory (as in +the case where an overlay of a different depth is stored as a second +framebuffer in offscreen memory). + + +<sect>Colormap Handling<label id="cmap"> +<p> + +A generic colormap handling layer is provided within the XFree86 common +layer. This layer takes care of most of the details, and only requires +a function from the driver that loads the hardware palette when required. +To use the colormap layer, a driver calls the +&s.code;xf86HandleColormaps()&e.code; function. + + <quote><p> + &s.code;Bool xf86HandleColormaps(ScreenPtr pScreen, int maxColors, + &f.indent;int sigRGBbits, LoadPaletteFuncPtr loadPalette, + &f.indent;SetOverscanFuncPtr setOverscan, + unsigned int flags)&e.code; + <quote><p> + This function must be called after the default colormap has been + initialised. The &s.code;pScrn->gamma&e.code; field must also + be initialised, preferably by calling &s.code;xf86SetGamma()&e.code;. + &s.code;maxColors&e.code; is the number of entries in the palette. + &s.code;sigRGBbits&e.code; is the size in bits of each color + component in the DAC's palette. &s.code;loadPalette&e.code; + is a driver-provided function for loading a colormap into the + hardware, and is described below. &s.code;setOverscan&e.code; is + an optional function that may be provided when the overscan color + is an index from the standard LUT and when it needs to be adjusted + to keep it as close to black as possible. The + &s.code;setOverscan&e.code; function programs the overscan index. + It shouldn't normally be used for depths other than 8. + &s.code;setOverscan&e.code; should be set to &s.code;NULL&e.code; + when it isn't needed. &s.code;flags&e.code; may be set to the + following (which may be ORed together): + + &s.code;CMAP_PALETTED_TRUECOLOR&e.code; + <quote><p> + the TrueColor visual is paletted and is + just a special case of DirectColor. + This flag is only valid for + &s.code;bpp > 8&e.code;. + + </quote> + + &s.code;CMAP_RELOAD_ON_MODE_SWITCH&e.code; + <quote><p> + reload the colormap automatically + after mode switches. This is useful + for when the driver is resetting the + hardware during mode switches and + corrupting or erasing the hardware + palette. + + </quote> + + &s.code;CMAP_LOAD_EVEN_IF_OFFSCREEN&e.code; + <quote><p> + reload the colormap even if the screen + is switched out of the server's VC. + The palette is <it>not</it> reloaded when + the screen is switched back in, nor after + mode switches. This is useful when the + driver needs to keep track of palette + changes. + + </quote> + + The colormap layer normally reloads the palette after VT enters so it + is not necessary for the driver to save and restore the palette + when switching VTs. The driver must, however, still save the + initial palette during server start up and restore it during + server exit. + + </quote> + + &s.code;void LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, + &f.indent;LOCO *colors, VisualPtr pVisual)&e.code; + <quote><p> + &s.code;LoadPalette()&e.code; is a driver-provided function for + loading a colormap into hardware. &s.code;colors&e.code; is the + array of RGB values that represent the full colormap. + &s.code;indices&e.code; is a list of index values into the colors + array. These indices indicate the entries that need to be updated. + &s.code;numColors&e.code; is the number of the indices to be + updated. + + </quote> + + &s.code;void SetOverscan(ScrnInfoPtr pScrn, int overscan)&e.code; + <quote><p> + &s.code;SetOverscan()&e.code; is a driver-provided function for + programming the &s.code;overscan&e.code; index. As described + above, it is normally only appropriate for LUT modes where all + colormap entries are available for the display, but where one of + them is also used for the overscan (typically 8bpp for VGA compatible + LUTs). It isn't required in cases where the overscan area is + never visible. + + </quote> + </quote> + + +<sect>DPMS Extension +<p> + +Support code for the DPMS extension is included in the XFree86 common layer. +This code provides an interface between the main extension code, and a means +for drivers to initialise DPMS when they support it. One function is +available to drivers to do this initialisation, and it is always available, +even when the DPMS extension is not supported by the core server (in +which case it returns a failure result). + + + <quote><p> + &s.code;Bool xf86DPMSInit(ScreenPtr pScreen, DPMSSetProcPtr set, int flags)&e.code; + <quote><p> + This function registers a driver's DPMS level programming function + &s.code;set&e.code;. It also checks + &s.code;pScrn->options&e.code; for the "dpms" option, and when + present marks DPMS as being enabled for that screen. The + &s.code;set&e.code; function is called whenever the DPMS level + changes, and is used to program the requested level. + &s.code;flags&e.code; is currently not used, and should be + &s.code;0&e.code;. If the initialisation fails for any reason, + including when there is no DPMS support in the core server, the + function returns &s.code;FALSE&e.code;. + + </quote> + </quote> + + +Drivers that implement DPMS support must provide the following function, +that gets called when the DPMS level is changed: + + + <quote><p> + &s.code;void ChipDPMSSet(ScrnInfoPtr pScrn, int level, int flags)&e.code; + <quote><p> + Program the DPMS level specified by &s.code;level&e.code;. Valid + values of &s.code;level&e.code; are &s.code;DPMSModeOn&e.code;, + &s.code;DPMSModeStandby&e.code;, &s.code;DPMSModeSuspend&e.code;, + &s.code;DPMSModeOff&e.code;. These values are defined in + &s.code;"extensions/dpms.h"&e.code;. + + </quote> + </quote> + + +<sect>DGA Extension +<p> + +Drivers can support the XFree86 Direct Graphics Architecture (DGA) by +filling out a structure of function pointers and a list of modes and +passing them to DGAInit. + + <quote><p> + &s.code;Bool DGAInit(ScreenPtr pScreen, DGAFunctionPtr funcs, + &f.indent;DGAModePtr modes, int num)&e.code; + <quote><p> + <verb> +/** The DGAModeRec **/ + +typedef struct { + int num; + DisplayModePtr mode; + int flags; + int imageWidth; + int imageHeight; + int pixmapWidth; + int pixmapHeight; + int bytesPerScanline; + int byteOrder; + int depth; + int bitsPerPixel; + unsigned long red_mask; + unsigned long green_mask; + unsigned long blue_mask; + int viewportWidth; + int viewportHeight; + int xViewportStep; + int yViewportStep; + int maxViewportX; + int maxViewportY; + int viewportFlags; + int offset; + unsigned char *address; + int reserved1; + int reserved2; +} DGAModeRec, *DGAModePtr; +</verb> + + &s.code;num&e.code; + <quote> + Can be ignored. The DGA DDX will assign these numbers. + </quote> + + &s.code;mode&e.code; + <quote> + A pointer to the &s.code;DisplayModeRec&e.code; for this mode. + </quote> + + &s.code;flags&e.code; + <quote><p> + The following flags are defined and may be OR'd together: + + &s.code;DGA_CONCURRENT_ACCESS&e.code; + <quote><p> + Indicates that the driver supports concurrent graphics + accelerator and linear framebuffer access. + + </quote> + + &s.code;DGA_FILL_RECT&nl; + DGA_BLIT_RECT&nl; + DGA_BLIT_RECT_TRANS&e.code; + <quote><p> + Indicates that the driver supports the FillRect, BlitRect + or BlitTransRect functions in this mode. + + </quote> + + &s.code;DGA_PIXMAP_AVAILABLE&e.code; + <quote><p> + Indicates that Xlib may be used on the framebuffer. + This flag will usually be set unless the driver wishes + to prohibit this for some reason. + + </quote> + + &s.code;DGA_INTERLACED&nl; + DGA_DOUBLESCAN&e.code; + <quote><p> + Indicates that these are interlaced or double scan modes. + + </quote> + </quote> + + &s.code;imageWidth&nl; + imageHeight&e.code; + <quote><p> + These are the dimensions of the linear framebuffer + accessible by the client. + + </quote> + + &s.code;pixmapWidth&nl; + pixmapHeight&e.code; + <quote><p> + These are the dimensions of the area of the + framebuffer accessible by the graphics accelerator. + + </quote> + + &s.code;bytesPerScanline&e.code; + <quote><p> + Pitch of the framebuffer in bytes. + + </quote> + + &s.code;byteOrder&e.code; + <quote><p> + Usually the same as + &s.code;pScrn->imageByteOrder&e.code;. + + </quote> + + &s.code;depth&e.code; + <quote><p> + The depth of the framebuffer in this mode. + + </quote> + + &s.code;bitsPerPixel&e.code; + <quote><p> + The number of bits per pixel in this mode. + + </quote> + + &s.code;red_mask&nl; + green_mask&nl; + blue_mask&e.code; + <quote><p> + The RGB masks for this mode, if applicable. + + </quote> + + &s.code;viewportWidth&nl; + viewportHeight&e.code; + <quote><p> + Dimensions of the visible part of the framebuffer. + Usually &s.code;mode->HDisplay&e.code; and + &s.code;mode->VDisplay&e.code;. + + </quote> + + &s.code;xViewportStep&nl; + yViewportStep&e.code; + <quote><p> + The granularity of x and y viewport positions that + the driver supports in this mode. + + </quote> + + &s.code;maxViewportX&nl; + maxViewportY&e.code; + <quote><p> + The maximum viewport position supported by the + driver in this mode. + + </quote> + + &s.code;viewportFlags&e.code; + <quote><p> + The following may be OR'd together: + + &s.code;DGA_FLIP_IMMEDIATE&e.code; + <quote><p> + The driver supports immediate viewport changes. + + </quote> + &s.code;DGA_FLIP_RETRACE&e.code; + <quote<p> + The driver supports viewport changes at retrace. + + </quote> + </quote> + + &s.code;offset&e.code; + <quote><p> + The offset into the linear framebuffer that corresponds to + pixel (0,0) for this mode. + + </quote> + + &s.code;address&e.code; + <quote><p> + The virtual address of the framebuffer as mapped by the driver. + This is needed when DGA_PIXMAP_AVAILABLE is set. + + </quote> + + <verb> +/** The DGAFunctionRec **/ + +typedef struct { + Bool (*OpenFramebuffer)( + ScrnInfoPtr pScrn, + char **name, + unsigned char **mem, + int *size, + int *offset, + int *extra + ); + void (*CloseFramebuffer)(ScrnInfoPtr pScrn); + Bool (*SetMode)(ScrnInfoPtr pScrn, DGAModePtr pMode); + void (*SetViewport)(ScrnInfoPtr pScrn, int x, int y, int flags); + int (*GetViewport)(ScrnInfoPtr pScrn); + void (*Sync)(ScrnInfoPtr); + void (*FillRect)( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned long color + ); + void (*BlitRect)( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty + ); + void (*BlitTransRect)( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty, + unsigned long color + ); +} DGAFunctionRec, *DGAFunctionPtr; +</verb> + + </quote> + + &s.code;Bool OpenFramebuffer (pScrn, name, mem, size, offset, extra)&e.code; + <quote><p> + &s.code;OpenFramebuffer()&e.code; should pass the client everything + it needs to know to be able to open the framebuffer. These + parameters are OS specific and their meanings are to be interpreted + by an OS specific client library. + + &s.code;name&e.code; + <quote><p> + The name of the device to open or &s.code;NULL&e.code; if + there is no special device to open. A &s.code;NULL&e.code; + name tells the client that it should open whatever device + one would usually open to access physical memory. + + </quote> + &s.code;mem&e.code; + <quote><p> + The physical address of the start of the framebuffer. + + </quote> + &s.code;size&e.code; + <quote><p> + The size of the framebuffer in bytes. + + </quote> + &s.code;offset&e.code; + <quote><p> + Any offset into the device, if applicable. + + </quote> + &s.code;flags&e.code; + <quote><p> + Any additional information that the client may need. + Currently, only the &s.code;DGA_NEED_ROOT&e.code; flag is + defined. + + </quote> + </quote> + + &s.code;void CloseFramebuffer (pScrn)&e.code; + <quote><p> + &s.code;CloseFramebuffer()&e.code; merely informs the driver (if it + even cares) that client no longer needs to access the framebuffer + directly. This function is optional. + + </quote> + + &s.code;Bool SetMode (pScrn, pMode)&e.code; + <quote><p> + &s.code;SetMode()&e.code; tells the driver to initialize the mode + passed to it. If &s.code;pMode&e.code; is &s.code;NULL&e.code;, + then the driver should restore the original pre-DGA mode. + + </quote> + + &s.code;void SetViewport (pScrn, x, y, flags)&e.code; + <quote><p> + &s.code;SetViewport()&e.code; tells the driver to make the upper + left-hand corner of the visible screen correspond to coordinate + &s.code;(x,y)&e.code; on the framebuffer. &s.code;Flags&e.code; + currently defined are: + + &s.code;DGA_FLIP_IMMEDIATE&e.code; + <quote><p> + The viewport change should occur immediately. + + </quote> + &s.code;DGA_FLIP_RETRACE&e.code; + <quote><p> + The viewport change should occur at the + vertical retrace, but this function should + return sooner if possible. + + </quote> + The &s.code;(x,y)&e.code; locations will be passed as the client + specified them, however, the driver is expected to round these + locations down to the next supported location as specified by the + &s.code;xViewportStep&e.code; and &s.code;yViewportStep&e.code; + for the current mode. + + </quote> + + &s.code;int GetViewport (pScrn)&e.code; + <quote><p> + &s.code;GetViewport()&e.code; gets the current page flip status. + Set bits in the returned int correspond to viewport change requests + still pending. For instance, set bit zero if the last SetViewport + request is still pending, bit one if the one before that is still + pending, etc. + + </quote> + + &s.code;void Sync (pScrn)&e.code; + <quote><p> + This function should ensure that any graphics accelerator operations + have finished. This function should not return until the graphics + accelerator is idle. + + </quote> + + &s.code;void FillRect (pScrn, x, y, w, h, color)&e.code; + <quote><p> + This optional function should fill a rectangle + &s.code;w × h&e.code; located at + &s.code;(x,y)&e.code; in the given color. + + </quote> + + &s.code;void BlitRect (pScrn, srcx, srcy, w, h, dstx, dsty)&e.code; + <quote><p> + This optional function should copy an area + &s.code;w × h&e.code; located at + &s.code;(srcx,srcy)&e.code; to location &s.code;(dstx,dsty)&e.code;. + This function will need to handle copy directions as appropriate. + + </quote> + + &s.code;void BlitTransRect (pScrn, srcx, srcy, w, h, dstx, dsty, color)&e.code; + <quote><p> + This optional function is the same as BlitRect except that pixels + in the source corresponding to the color key &s.code;color&e.code; + should be skipped. + + </quote> + </quote> + +<sect>The XFree86 X Video Extension (Xv) Device Dependent Layer +<p> + +XFree86 offers the X Video Extension which allows clients to treat video +as any another primitive and ``Put'' video into drawables. By default, +the extension reports no video adaptors as being available since the +DDX layer has not been initialized. The driver can initialize the DDX +layer by filling out one or more &s.code;XF86VideoAdaptorRecs&e.code; +as described later in this document and passing a list of +&s.code;XF86VideoAdaptorPtr&e.code; pointers to the following function: + + <quote> + &s.code;Bool xf86XVScreenInit( + &f.indent;ScreenPtr pScreen, + &f.indent;XF86VideoAdaptorPtr *adaptPtrs, + &f.indent;int num)&e.code; + </quote> + +After doing this, the extension will report video adaptors as being +available, providing the data in their respective +&s.code;XF86VideoAdaptorRecs&e.code; was valid. +&s.code;xf86XVScreenInit()&e.code; <em>copies</em> data from the structure +passed to it so the driver may free it after the initialization. At +the moment, the DDX only supports rendering into Window drawables. +Pixmap rendering will be supported after a sufficient survey of suitable +hardware is completed. + +The &s.code;XF86VideoAdaptorRec&e.code;: + +<quote><p> +<verb> +typedef struct { + unsigned int type; + int flags; + char *name; + int nEncodings; + XF86VideoEncodingPtr pEncodings; + int nFormats; + XF86VideoFormatPtr pFormats; + int nPorts; + DevUnion *pPortPrivates; + int nAttributes; + XF86AttributePtr pAttributes; + int nImages; + XF86ImagePtr pImages; + PutVideoFuncPtr PutVideo; + PutStillFuncPtr PutStill; + GetVideoFuncPtr GetVideo; + GetStillFuncPtr GetStill; + StopVideoFuncPtr StopVideo; + SetPortAttributeFuncPtr SetPortAttribute; + GetPortAttributeFuncPtr GetPortAttribute; + QueryBestSizeFuncPtr QueryBestSize; + PutImageFuncPtr PutImage; + QueryImageAttributesFuncPtr QueryImageAttributes; +} XF86VideoAdaptorRec, *XF86VideoAdaptorPtr; +</verb> + + Each adaptor will have its own XF86VideoAdaptorRec. The fields are + as follows: + + &s.code;type&e.code; + <quote><p> + This can be any of the following flags OR'd together. + + &s.code;XvInputMask&e.code; + &s.code;XvOutputMask&e.code; + <quote><p> + These refer to the target drawable and are similar to a Window's + class. &s.code;XvInputMask&e.code; indicates that the adaptor + can put video into a drawable. &s.code;XvOutputMask&e.code; + indicates that the adaptor can get video from a drawable. + </quote> + + &s.code;XvVideoMask&e.code; + &s.code;XvStillMask&e.code; + &s.code;XvImageMask&e.code; + <quote><p> + These indicate that the adaptor supports video, still or + image primitives respectively. + </quote> + + &s.code;XvWindowMask&e.code; + &s.code;XvPixmapMask&e.code; + <quote><p> + These indicate the types of drawables the adaptor is capable + of rendering into. At the moment, Pixmap rendering is not + supported and the &s.code;XvPixmapMask&e.code; flag is ignored. + </quote> + + </quote> + + &s.code;flags&e.code; + <quote><p> + Currently, the following flags are defined: + + &s.code;VIDEO_NO_CLIPPING&e.code; + <quote><p> + This indicates that the video adaptor does not support + clipping. The driver will never receive ``Put'' requests + where less than the entire area determined by + &s.code;drw_x&e.code;, &s.code;drw_y&e.code;, + &s.code;drw_w&e.code; and &s.code;drw_h&e.code; is visible. + This flag does not apply to ``Get'' requests. Hardware + that is incapable of clipping ``Gets'' may punt or get + the extents of the clipping region passed to it. + + </quote> + + &s.code;VIDEO_INVERT_CLIPLIST&e.code; + <quote><p> + This indicates that the video driver requires the clip + list to contain the regions which are obscured rather + than the regions which are are visible. + + </quote> + + &s.code;VIDEO_OVERLAID_STILLS&e.code; + <quote><p> + Implementing PutStill for hardware that does video as an + overlay can be awkward since it's unclear how long to leave + the video up for. When this flag is set, StopVideo will be + called whenever the destination gets clipped or moved so that + the still can be left up until then. + + </quote> + + &s.code;VIDEO_OVERLAID_IMAGES&e.code; + <quote><p> + Same as &s.code;VIDEO_OVERLAID_STILLS&e.code; but for images. + </quote> + + &s.code;VIDEO_CLIP_TO_VIEWPORT&e.code; + <quote><p> + Indicates that the clip region passed to the driver functions + should be clipped to the visible portion of the screen in the + case where the viewport is smaller than the virtual desktop. + </quote> + + </quote> + + &s.code;name&e.code; + <quote><p> + The name of the adaptor. + + </quote> + + &s.code;nEncodings&nl; + pEncodings&e.code; + <quote><p> + The number of encodings the adaptor is capable of and pointer + to the &s.code;XF86VideoEncodingRec&e.code; array. The + &s.code;XF86VideoEncodingRec&e.code; is described later on. + For drivers that only support XvImages there should be an encoding + named "XV_IMAGE" and the width and height should specify + the maximum size source image supported. + + </quote> + + &s.code;nFormats&nl; + pFormats&e.code; + <quote><p> + The number of formats the adaptor is capable of and pointer to + the &s.code;XF86VideoFormatRec&e.code; array. The + &s.code;XF86VideoFormatRec&e.code; is described later on. + + </quote> + + &s.code;nPorts&nl; + pPortPrivates&e.code; + <quote><p> + The number of ports is the number of separate data streams which + the adaptor can handle simultaneously. If you have more than + one port, the adaptor is expected to be able to render into more + than one window at a time. &s.code;pPortPrivates&e.code; is + an array of pointers or ints - one for each port. A port's + private data will be passed to the driver any time the port is + requested to do something like put the video or stop the video. + In the case where there may be many ports, this enables the + driver to know which port the request is intended for. Most + commonly, this will contain a pointer to the data structure + containing information about the port. In Xv, all ports on + a particular adaptor are expected to be identical in their + functionality. + + </quote> + + &s.code;nAttributes&nl; + pAttributes&e.code; + <quote><p> + The number of attributes recognized by the adaptor and a pointer to + the array of &s.code;XF86AttributeRecs&e.code;. The + &s.code;XF86AttributeRec&e.code; is described later on. + + </quote> + + &s.code;nImages&nl; + pImages&e.code; + <quote><p> + The number of &s.code;XF86ImageRecs&e.code; supported by the adaptor + and a pointer to the array of &s.code;XF86ImageRecs&e.code;. The + &s.code;XF86ImageRec&e.code; is described later on. + + </quote> + + + &s.code;PutVideo PutStill GetVideo GetStill StopVideo + SetPortAttribute GetPortAttribute QueryBestSize PutImage + QueryImageAttributes&e.code; + <quote><p> + These functions define the DDX->driver interface. In each + case, the pointer &s.code;data&e.code; is passed to the driver. + This is the port private for that port as described above. All + fields are required except under the following conditions: + + <enum> + <item>&s.code;PutVideo&e.code;, &s.code;PutStill&e.code; and + the image routines &s.code;PutImage&e.code; and + &s.code;QueryImageAttributes&e.code; are not required when the + adaptor type does not contain &s.code;XvInputMask&e.code;. + + <item>&s.code;GetVideo&e.code; and &s.code;GetStill&e.code; + are not required when the adaptor type does not contain + &s.code;XvOutputMask&e.code;. + + <item>&s.code;GetVideo&e.code; and &s.code;PutVideo&e.code; + are not required when the adaptor type does not contain + &s.code;XvVideoMask&e.code;. + + <item>&s.code;GetStill&e.code; and &s.code;PutStill&e.code; + are not required when the adaptor type does not contain + &s.code;XvStillMask&e.code;. + + <item>&s.code;PutImage&e.code; and &s.code;QueryImageAttributes&e.code; + are not required when the adaptor type does not contain + &s.code;XvImageMask&e.code;. + + </enum> + + With the exception of &s.code;QueryImageAttributes&e.code;, these + functions should return &s.code;Success&e.code; if the operation was + completed successfully. They can return &s.code;XvBadAlloc&e.code; + otherwise. &s.code;QueryImageAttributes&e.code; returns the size + of the XvImage queried. + + If the &s.code;VIDEO_NO_CLIPPING&e.code; + flag is set, the &s.code;clipBoxes&e.code; may be ignored by + the driver. &s.code;ClipBoxes&e.code; is an &s.code;X-Y&e.code; + banded region identical to those used throughout the server. + The clipBoxes represent the visible portions of the area determined + by &s.code;drw_x&e.code;, &s.code;drw_y&e.code;, + &s.code;drw_w&e.code; and &s.code;drw_h&e.code; in the Get/Put + function. The boxes are in screen coordinates, are guaranteed + not to overlap and an empty region will never be passed. + If the driver has specified &s.code;VIDEO_INVERT_CLIPLIST&e.code;, + &s.code;clipBoxes&e.code; will indicate the areas of the primitive + which are obscured rather than the areas visible. + + </quote> + + &s.code;typedef int (* PutVideoFuncPtr)( ScrnInfoPtr pScrn, + &f.indent;short vid_x, short vid_y, short drw_x, short drw_y, + &f.indent;short vid_w, short vid_h, short drw_w, short drw_h, + &f.indent;RegionPtr clipBoxes, pointer data )&e.code; + <quote><p> + This indicates that the driver should take a subsection + &s.code;vid_w&e.code; by &s.code;vid_h&e.code; at location + &s.code;(vid_x,vid_y)&e.code; from the video stream and direct + it into the rectangle &s.code;drw_w&e.code; by &s.code;drw_h&e.code; + at location &s.code;(drw_x,drw_y)&e.code; on the screen, scaling as + necessary. Due to the large variations in capabilities of + the various hardware expected to be used with this extension, + it is not expected that all hardware will be able to do this + exactly as described. In that case the driver should just do + ``the best it can,'' scaling as closely to the target rectangle + as it can without rendering outside of it. In the worst case, + the driver can opt to just not turn on the video. + + </quote> + + &s.code;typedef int (* PutStillFuncPtr)( ScrnInfoPtr pScrn, + &f.indent;short vid_x, short vid_y, short drw_x, short drw_y, + &f.indent;short vid_w, short vid_h, short drw_w, short drw_h, + &f.indent;RegionPtr clipBoxes, pointer data )&e.code; + <quote><p> + This is same as &s.code;PutVideo&e.code; except that the driver + should place only one frame from the stream on the screen. + + </quote> + + &s.code;typedef int (* GetVideoFuncPtr)( ScrnInfoPtr pScrn, + &f.indent;short vid_x, short vid_y, short drw_x, short drw_y, + &f.indent;short vid_w, short vid_h, short drw_w, short drw_h, + &f.indent;RegionPtr clipBoxes, pointer data )&e.code; + <quote><p> + This is same as &s.code;PutVideo&e.code; except that the driver + gets video from the screen and outputs it. The driver should + do the best it can to get the requested dimensions correct + without reading from an area larger than requested. + + </quote> + + &s.code;typedef int (* GetStillFuncPtr)( ScrnInfoPtr pScrn, + &f.indent;short vid_x, short vid_y, short drw_x, short drw_y, + &f.indent;short vid_w, short vid_h, short drw_w, short drw_h, + &f.indent;RegionPtr clipBoxes, pointer data )&e.code; + <quote><p> + This is the same as &s.code;GetVideo&e.code; except that the + driver should place only one frame from the screen into the + output stream. + + </quote> + + &s.code;typedef void (* StopVideoFuncPtr)(ScrnInfoPtr pScrn, + &f.indent;pointer data, Bool cleanup)&e.code; + <quote><p> + This indicates the driver should stop displaying the video. + This is used to stop both input and output video. The + &s.code;cleanup&e.code; field indicates that the video is + being stopped because the client requested it to stop or + because the server is exiting the current VT. In that case + the driver should deallocate any offscreen memory areas (if + there are any) being used to put the video to the screen. If + &s.code;cleanup&e.code; is not set, the video is being stopped + temporarily due to clipping or moving of the window, etc... + and video will likely be restarted soon so the driver should + not deallocate any offscreen areas associated with that port. + + </quote> + &s.code;typedef int (* SetPortAttributeFuncPtr)(ScrnInfoPtr pScrn, + &f.indent;Atom attribute,INT32 value, pointer data)&e.code; + + &s.code;typedef int (* GetPortAttributeFuncPtr)(ScrnInfoPtr pScrn, + &f.indent;Atom attribute,INT32 *value, pointer data)&e.code; + + <quote><p> + A port may have particular attributes such as hue, + saturation, brightness or contrast. Xv clients set and + get these attribute values by sending attribute strings + (Atoms) to the server. Such requests end up at these + driver functions. It is recommended that the driver provide + at least the following attributes mentioned in the Xv client + library docs: + <quote> + &s.code;XV_ENCODING&nl; + XV_HUE&nl; + XV_SATURATION&nl; + XV_BRIGHTNESS&nl; + XV_CONTRAST&e.code; + </quote> + but the driver may recognize as many atoms as it wishes. If + a requested attribute is unknown by the driver it should return + &s.code;BadMatch&e.code;. &s.code;XV_ENCODING&e.code; is the + attribute intended to let the client specify which video + encoding the particular port should be using (see the description + of &s.code;XF86VideoEncodingRec&e.code; below). If the + requested encoding is unsupported, the driver should return + &s.code;XvBadEncoding&e.code;. If the value lies outside the + advertised range &s.code;BadValue&e.code; may be returned. + &s.code;Success&e.code; should be returned otherwise. + + </quote> + + &s.code;typedef void (* QueryBestSizeFuncPtr)(ScrnInfoPtr pScrn, + &f.indent;Bool motion, short vid_w, short vid_h, + &f.indent;short drw_w, short drw_h, + &f.indent;unsigned int *p_w, unsigned int *p_h, pointer data)&e.code; + <quote><p> + &s.code;QueryBestSize&e.code; provides the client with a way + to query what the destination dimensions would end up being + if they were to request that an area + &s.code;vid_w&e.code by &s.code;vid_h&e.code; from the video + stream be scaled to rectangle of + &s.code;drw_w&e.code; by &s.code;drw_h&e.code; on the screen. + Since it is not expected that all hardware will be able to + get the target dimensions exactly, it is important that the + driver provide this function. + + </quote> + + &s.code;typedef int (* PutImageFuncPtr)( ScrnInfoPtr pScrn, + &f.indent;short src_x, short src_y, short drw_x, short drw_y, + &f.indent;short src_w, short src_h, short drw_w, short drw_h, + &f.indent;int image, char *buf, short width, short height, + &f.indent;Bool sync, RegionPtr clipBoxes, pointer data )&e.code; + <quote><p> + This is similar to &s.code;PutStill&e.code; except that the + source of the video is not a port but the data stored in a system + memory buffer at &s.code;buf&e.code;. The data is in the format + indicated by the &s.code;image&e.code; descriptor and represents a + source of size &s.code;width&e.code; by &s.code;height&e.code;. + If &s.code;sync&e.code; is TRUE the driver should not return + from this function until it is through reading the data + from &s.code;buf&e.code;. Returning when &s.code;sync&e.code; + is TRUE indicates that it is safe for the data at &s.code;buf&e.code; + to be replaced, freed, or modified. + + </quote> + + &s.code;typedef int (* QueryImageAttributesFuncPtr)( ScrnInfoPtr pScrn, + &f.indent;int image, short *width, short *height, + &f.indent;int *pitches, int *offsets)&e.code; + <quote><p> + This function is called to let the driver specify how data for + a particular &s.code;image&e.code; of size &s.code;width&e.code; + by &s.code;height&e.code; should be stored. Sometimes only + the size and corrected width and height are needed. In that + case &s.code;pitches&e.code; and &s.code;offsets&e.code; are + NULL. The size of the memory required for the image is returned + by this function. The &s.code;width&e.code; and + &s.code;height&e.code; of the requested image can be altered by + the driver to reflect format limitations (such as component + sampling periods that are larger than one). If + &s.code;pitches&e.code; and &s.code;offsets&e.code; are not NULL, + these will be arrays with as many elements in them as there + are planes in the &s.code;image&e.code; format. The driver + should specify the pitch (in bytes) of each scanline in the + particular plane as well as the offset to that plane (in bytes) + from the beginning of the image. + + </quote> + + </quote> + +The XF86VideoEncodingRec: +<quote><p> +<verb> +typedef struct { + int id; + char *name; + unsigned short width, height; + XvRationalRec rate; +} XF86VideoEncodingRec, *XF86VideoEncodingPtr; + +</verb> + The &s.code;XF86VideoEncodingRec&e.code; specifies what encodings + the adaptor can support. Most of this data is just informational + and for the client's benefit, and is what will be reported by + &s.code;XvQueryEncodings&e.code;. The &s.code;id&e.code; field is + expected to be a unique identifier to allow the client to request a + certain encoding via the &s.code;XV_ENCODING&e.code; attribute string. + +</quote> + +The XF86VideoFormatRec: + +<quote><p> +<verb> +typedef struct { + char depth; + short class; +} XF86VideoFormatRec, *XF86VideoFormatPtr; +</verb> + + This specifies what visuals the video is viewable in. + &s.code;depth&e.code; is the depth of the visual (not bpp). + &s.code;class&e.code; is the visual class such as + &s.code;TrueColor&e.code;, &s.code;DirectColor&e.code; or + &s.code;PseudoColor&e.code;. Initialization of an adaptor will fail + if none of the visuals on that screen are supported. + +</quote> + +The XF86AttributeRec: + +<quote><p> +<verb> +typedef struct { + int flags; + int min_value; + int max_value; + char *name; +} XF86AttributeListRec, *XF86AttributeListPtr; + +</verb> + + Each adaptor may have an array of these advertising the attributes + for its ports. Currently defined flags are &s.code;XvGettable&e.code; + and &s.code;XvSettable&e.code; which may be OR'd together indicating that + attribute is ``gettable'' or ``settable'' by the client. The + &s.code;min&e.code; and &s.code;max&e.code; field specify the valid range + for the value. &s.code;Name&e.code; is a text string describing the + attribute by name. + +</quote> + +The XF86ImageRec: + +<quote><p> +<verb> +typedef struct { + int id; + int type; + int byte_order; + char guid[16]; + int bits_per_pixel; + int format; + int num_planes; + + /* for RGB formats */ + int depth; + unsigned int red_mask; + unsigned int green_mask; + unsigned int blue_mask; + + /* for YUV formats */ + unsigned int y_sample_bits; + unsigned int u_sample_bits; + unsigned int v_sample_bits; + unsigned int horz_y_period; + unsigned int horz_u_period; + unsigned int horz_v_period; + unsigned int vert_y_period; + unsigned int vert_u_period; + unsigned int vert_v_period; + char component_order[32]; + int scanline_order; +} XF86ImageRec, *XF86ImagePtr; +</verb> + + XF86ImageRec describes how video source data is laid out in memory. + The fields are as follows: + + &s.code;id&e.code; + <quote><p> + This is a unique descriptor for the format. It is often good to + set this value to the FOURCC for the format when applicable. + </quote> + + &s.code;type&e.code; + <quote><p> + This is &s.code;XvRGB&e.code; or &s.code;XvYUV&e.code;. + </quote> + + &s.code;byte_order&e.code; + <quote><p> + This is &s.code;LSBFirst&e.code; or &s.code;MSBFirst&e.code;. + </quote> + + &s.code;guid&e.code; + <quote><p> + This is the Globally Unique IDentifier for the format. When + not applicable, all characters should be NULL. + </quote> + + &s.code;bits_per_pixel&e.code; + <quote><p> + The number of bits taken up (but not necessarily used) by each + pixel. Note that for some planar formats which have fractional + bits per pixel (such as IF09) this number may be rounded _down_. + </quote> + + &s.code;format&e.code; + <quote><p> + This is &s.code;XvPlanar&e.code; or &s.code;XvPacked&e.code;. + </quote> + + &s.code;num_planes&e.code; + <quote><p> + The number of planes in planar formats. This should be set to + one for packed formats. + </quote> + + &s.code;depth&e.code; + <quote><p> + The significant bits per pixel in RGB formats (analgous to the + depth of a pixmap format). + </quote> + + &s.code;red_mask&e.code; + &s.code;green_mask&e.code; + &s.code;blue_mask&e.code; + <quote><p> + The red, green and blue bitmasks for packed RGB formats. + </quote> + + &s.code;y_sample_bits&e.code; + &s.code;u_sample_bits&e.code; + &s.code;v_sample_bits&e.code; + <quote><p> + The y, u and v sample sizes (in bits). + </quote> + + &s.code;horz_y_period&e.code; + &s.code;horz_u_period&e.code; + &s.code;horz_v_period&e.code; + <quote><p> + The y, u and v sampling periods in the horizontal direction. + </quote> + + &s.code;vert_y_period&e.code; + &s.code;vert_u_period&e.code; + &s.code;vert_v_period&e.code; + <quote><p> + The y, u and v sampling periods in the vertical direction. + </quote> + + &s.code;component_order&e.code; + <quote><p> + Uppercase ascii characters representing the order that + samples are stored within packed formats. For planar formats + this represents the ordering of the planes. Unused characters + in the 32 byte string should be set to NULL. + </quote> + + &s.code;scanline_order&e.code; + <quote><p> + This is &s.code;XvTopToBottom&e.code; or &s.code;XvBottomToTop&e.code;. + </quote> + + Since some formats (particular some planar YUV formats) may not +be completely defined by the parameters above, the guid, when +available, should provide the most accurate description of the +format. + +</quote> + +<sect>The Loader +<p> + +This section describes the interfaces to the module loader. The loader +interfaces can be divided into two groups: those that are only available to +the XFree86 common layer, and those that are also available to modules. + +<sect1>Loader Overview +<p> + +The loader is capable of loading modules in a range of object formats, +and knowledge of these formats is built in to the loader. Knowledge of +new object formats can be added to the loader in a straightforward +manner. This makes it possible to provide OS-independent modules (for +a given CPU architecture type). In addition to this, the loader can +load modules via the OS-provided &s.code;dlopen(3)&e.code; service where +available. Such modules are not platform independent, and the semantics +of &s.code;dlopen()&e.code; on most systems results in significant +limitations in the use of modules of this type. Support for +&s.code;dlopen()&e.code; modules in the loader is primarily for +experimental and development purposes. + +Symbols exported by the loader (on behalf of the core X server) to +modules are determined at compile time. Only those symbols explicitly +exported are available to modules. All external symbols of loaded +modules are exported to other modules, and to the core X server. The +loader can be requested to check for unresolved symbols at any time, +and the action to be taken for unresolved symbols can be controlled by +the caller of the loader. Typically the caller identifies which symbols +can safely remain unresolved and which cannot. + +NOTE: Now that ISO-C allows pointers to functions and pointers to data to +have different internal representations, some of the following interfaces +will need to be revisited. + +<sect1>Semi-private Loader Interface +<p> + +The following is the semi-private loader interface that is available to the +XFree86 common layer. + + <quote><p> + &s.code;void LoaderInit(void)&e.code; + <quote><p> + The &s.code;LoaderInit()&e.code; function initialises the loader, + and it must be called once before calling any other loader functions. + This function initialises the tables of exported symbols, and anything + else that might need to be initialised. + + </quote> + + &s.code;void LoaderSetPath(const char *path)&e.code; + <quote><p> + The &s.code;LoaderSetPath()&e.code; function initialises a default + module search path. This must be called if calls to other functions + are to be made without explicitly specifying a module search path. + The search path &s.code;path&e.code; must be a string of one or more + comma separated absolute paths. Modules are expected to be located + below these paths, possibly in subdirectories of these paths. + + </quote> + + &s.code;pointer LoadModule(const char *module, const char *path, + &f.indent;const char **subdirlist, const char **patternlist, + &f.indent;pointer options, const XF86ModReqInfo * modreq, + &f.indent;int *errmaj, int *errmin)&e.code; + <quote><p> + The &s.code;LoadModule()&e.code; function loads the module called + &s.code;module&e.code;. The return value is a module handle, and + may be used in future calls to the loader that require a reference + to a loaded module. The module name &s.code;module&e.code; is + normally the module's canonical name, which doesn't contain any + directory path information, or any object/library file prefixes of + suffixes. Currently a full pathname and/or filename is also accepted. + This might change. The other parameters are: + + &s.code;path&e.code; + <quote><p> + An optional comma-separated list of module search paths. + When &s.code;NULL&e.code;, the default search path is used. + + </quote> + + &s.code;subdirlist&e.code; + <quote><p> + An optional &s.code;NULL&e.code; terminated list of + subdirectories to search. When &s.code;NULL&e.code;, + the default built-in list is used (refer to + &s.code;stdSubdirs&e.code; in &s.code;loadmod.c&e.code;). + The default list is also substituted for entries in + &s.code;subdirlist&e.code; with the value + &s.code;DEFAULT_LIST&e.code;. This makes is possible + to augment the default list instead of replacing it. + Subdir elements must be relative, and must not contain + &s.code;".."&e.code;. If any violate this requirement, + the load fails. + + </quote> + + &s.code;patternlist&e.code; + <quote><p> + An optional &s.code;NULL&e.code; terminated list of + POSIX regular expressions used to connect module + filenames with canonical module names. Each regex + should contain exactly one subexpression that corresponds + to the canonical module name. When &s.code;NULL&e.code;, + the default built-in list is used (refer to + &s.code;stdPatterns&e.code; in + &s.code;loadmod.c&e.code;). The default list is also + substituted for entries in &s.code;patternlist&e.code; + with the value &s.code;DEFAULT_LIST&e.code;. This + makes it possible to augment the default list instead + of replacing it. + + </quote> + + &s.code;options&e.code; + <quote><p> + An optional parameter that is passed to the newly + loaded module's &s.code;SetupProc&e.code; function + (if it has one). This argument is normally a + &s.code;NULL&e.code; terminated list of + &s.code;Options&e.code;, and must be interpreted that + way by modules loaded directly by the XFree86 common + layer. However, it may be used for application-specific + parameter passing in other situations. + + When loading ``external'' modules (modules that don't + have the standard entry point, for example a + special shared library) the options parameter can be + set to &s.code;EXTERN_MODULE&e.code; to tell the + loader not to reject the module when it doesn't find + the standard entry point. + + </quote> + + &s.code;modreq&e.code; + <quote><p> + An optional &s.code;XF86ModReqInfo*&e.code; containing + version/ABI/vendor information to requirements to + check the newly loaded module against. The main + purpose of this is to allow the loader to verify that + a module of the correct type/version before running + its &s.code;SetupProc&e.code; function. + + The &s.code;XF86ModReqInfo&e.code; struct is defined + as follows: +<verb> +typedef struct { + CARD8 majorversion; /* MAJOR_UNSPEC */ + CARD8 minorversion; /* MINOR_UNSPEC */ + CARD16 patchlevel; /* PATCH_UNSPEC */ + const char * abiclass; /* ABI_CLASS_NONE */ + CARD32 abiversion; /* ABI_VERS_UNSPEC */ + const char * moduleclass; /* MOD_CLASS_NONE */ +} XF86ModReqInfo; +</verb> + + The information here is compared against the equivalent + information in the module's + &s.code;XF86ModuleVersionInfo&e.code; record (which + is described below). The values in comments above + indicate ``don't care'' settings for each of the fields. + The comparisons made are as follows: + + &s.code;majorversion&e.code; + <quote><p> + Must match the module's majorversion + exactly. + + </quote> + &s.code;minorversion&e.code; + <quote><p> + The module's minor version must be + no less than this value. This + comparison is only made if + &s.code;majorversion&e.code; is + specified and matches. + + </quote> + &s.code;patchlevel&e.code; + <quote><p> + The module's patchlevel must be no + less than this value. This comparison + is only made if + &s.code;minorversion&e.code; is + specified and matches. + + </quote> + &s.code;abiclass&e.code; + <quote><p> + String must match the module's abiclass + string. + + </quote> + &s.code;abiversion&e.code; + <quote><p> + Must be consistent with the module's + abiversion (major equal, minor no + older). + + </quote> + &s.code;moduleclass&e.code; + <quote><p> + String must match the module's + moduleclass string. + + </quote> + + </quote> + + &s.code;errmaj&e.code; + <quote><p> + An optional pointer to a variable holding the major + part or the error code. When provided, + &s.code;*errmaj&e.code; is filled in when + &s.code;LoadModule()&e.code; fails. + + </quote> + + &s.code;errmin&e.code; + <quote><p> + Like &s.code;errmaj&e.code;, but for the minor part + of the error code. + + </quote> + + </quote> + + &s.code;void UnloadModule(pointer mod)&e.code; + <quote><p> + This function unloads the module referred to by the handle mod. + All child modules are also unloaded recursively. This function must + not be used to directly unload modules that are child modules (i.e., + those that have been loaded with the &s.code;LoadSubModule()&e.code; + described below). + + </quote> + </quote> + +<sect1>Module Requirements +<p> + +Modules must provide information about themselves to the loader, and +may optionally provide entry points for "setup" and "teardown" functions +(those two functions are referred to here as &s.code;SetupProc&e.code; +and &s.code;TearDownProc&e.code;). + +The module information is contained in the +&s.code;XF86ModuleVersionInfo&e.code; struct, which is defined as follows: + +<quote><p><verb> +typedef struct { + const char * modname; /* name of module, e.g. "foo" */ + const char * vendor; /* vendor specific string */ + CARD32 _modinfo1_; /* constant MODINFOSTRING1/2 to find */ + CARD32 _modinfo2_; /* infoarea with a binary editor/sign tool */ + CARD32 xf86version; /* contains XF86_VERSION_CURRENT */ + CARD8 majorversion; /* module-specific major version */ + CARD8 minorversion; /* module-specific minor version */ + CARD16 patchlevel; /* module-specific patch level */ + const char * abiclass; /* ABI class that the module uses */ + CARD32 abiversion; /* ABI version */ + const char * moduleclass; /* module class */ + CARD32 checksum[4]; /* contains a digital signature of the */ + /* version info structure */ +} XF86ModuleVersionInfo; +</verb> + +The fields are used as follows: + + &s.code;modname&e.code; + <quote><p> + The module's name. This field is currently only for + informational purposes, but the loader may be modified + in future to require it to match the module's canonical + name. + + </quote> + + &s.code;vendor&e.code; + <quote><p> + The module vendor. This field is for informational purposes + only. + + </quote> + + &s.code;_modinfo1_&e.code; + <quote><p> + This field holds the first part of a signature that can + be used to locate this structure in the binary. It should + always be initialised to &s.code;MODINFOSTRING1&e.code;. + + </quote> + + &s.code;_modinfo2_&e.code; + <quote><p> + This field holds the second part of a signature that can + be used to locate this structure in the binary. It should + always be initialised to &s.code;MODINFOSTRING2&e.code;. + + </quote> + + &s.code;xf86version&e.code; + <quote><p> + The XFree86 version against which the module was compiled. + This is mostly for informational/diagnostic purposes. It + should be initialised to &s.code;XF86_VERSION_CURRENT&e.code;, which is + defined in &s.code;xf86Version.h&e.code;. + + </quote> + + &s.code;majorversion&e.code; + <quote><p> + The module-specific major version. For modules where this + version is used for more than simply informational + purposes, the major version should only change (be + incremented) when ABI incompatibilities are introduced, + or ABI components are removed. + + </quote> + + &s.code;minorversion&e.code; + <quote><p> + The module-specific minor version. For modules where this + version is used for more than simply informational + purposes, the minor version should only change (be + incremented) when ABI additions are made in a backward + compatible way. It should be reset to zero when the major + version is increased. + + </quote> + + &s.code;patchlevel&e.code; + <quote><p> + The module-specific patch level. The patch level should + increase with new revisions of the module where there + are no ABI changes, and it should be reset to zero when + the minor version is increased. + + </quote> + + &s.code;abiclass&e.code; + <quote><p> + The ABI class that the module requires. The class is + specified as a string for easy extensibility. It should + indicate which (if any) of the X server's built-in ABI + classes that the module relies on, or a third-party ABI + if appropriate. Built-in ABI classes currently defined are: + + <quote> + &s.code;ABI_CLASS_NONE&e.code; + <quote>no class</quote> + &s.code;ABI_CLASS_ANSIC&e.code; + <quote>only requires the ANSI C interfaces</quote> + &s.code;ABI_CLASS_VIDEODRV&e.code; + <quote>requires the video driver ABI</quote> + &s.code;ABI_CLASS_XINPUT&e.code; + <quote>requires the XInput driver ABI</quote> + &s.code;ABI_CLASS_EXTENSION&e.code; + <quote>requires the extension module ABI</quote> + &s.code;ABI_CLASS_FONT&e.code; + <quote>requires the font module ABI</quote> + </quote> + + </quote> + + &s.code;abiversion&e.code; + <quote><p> + The version of abiclass that the module requires. The + version consists of major and minor components. The + major version must match and the minor version must be + no newer than that provided by the server or parent + module. Version identifiers for the built-in classes + currently defined are: + + <quote> + &s.code;ABI_ANSIC_VERSION&nl; + ABI_VIDEODRV_VERSION&nl; + ABI_XINPUT_VERSION&nl; + ABI_EXTENSION_VERSION&nl; + ABI_FONT_VERSION&e.code; + </quote> + + </quote> + + &s.code;moduleclass&e.code; + <quote><p> + This is similar to the abiclass field, except that it + defines the type of module rather than the ABI it + requires. For example, although all video drivers require + the video driver ABI, not all modules that require the + video driver ABI are video drivers. This distinction + can be made with the moduleclass. Currently pre-defined + module classes are: + + <quote> + &s.code;MOD_CLASS_NONE&nl; + MOD_CLASS_VIDEODRV&nl; + MOD_CLASS_XINPUT&nl; + MOD_CLASS_FONT&nl; + MOD_CLASS_EXTENSION&e.code; + </quote> + + </quote> + + &s.code;checksum&e.code; + <quote><p> + Not currently used. + + </quote> + +</quote> + +The module version information, and the optional &s.code;SetupProc&e.code; +and &s.code;TearDownProc&e.code; entry points are found by the loader +by locating a data object in the module called "modnameModuleData", +where "modname" is the canonical name of the module. Modules must +contain such a data object, and it must be declared with global scope, +be compile-time initialised, and is of the following type: + +<quote> +<verb> +typedef struct { + XF86ModuleVersionInfo * vers; + ModuleSetupProc setup; + ModuleTearDownProc teardown; +} XF86ModuleData; +</verb> +</quote> + +The vers parameter must be initialised to a pointer to a correctly +initialised &s.code;XF86ModuleVersionInfo&e.code; struct. The other +two parameter are optional, and should be initialised to +&s.code;NULL&e.code; when not required. The other parameters are defined +as + + <quote><p> + &s.code;typedef pointer (*ModuleSetupProc)(pointer, pointer, int *, int *)&e.code; + + &s.code;typedef void (*ModuleTearDownProc)(pointer)&e.code; + + + &s.code;pointer SetupProc(pointer module, pointer options, + &f.indent;int *errmaj, int *errmin)&e.code; + <quote><p> + When defined, this function is called by the loader after successfully + loading a module. module is a handle for the newly loaded module, + and maybe used by the &s.code;SetupProc&e.code; if it calls other + loader functions that require a reference to it. The remaining + arguments are those that were passed to the + &s.code;LoadModule()&e.code; (or &s.code;LoadSubModule()&e.code;), + and are described above. When the &s.code;SetupProc&e.code; is + successful it must return a non-&s.code;NULL&e.code; value. The + loader checks this, and if it is &s.code;NULL&e.code; it unloads + the module and reports the failure to the caller of + &s.code;LoadModule()&e.code;. If the &s.code;SetupProc&e.code; + does things that need to be undone when the module is unloaded, + it should define a &s.code;TearDownProc&e.code;, and return a + pointer that the &s.code;TearDownProc&e.code; can use to undo what + has been done. + + When a module is loaded multiple times, the &s.code;SetupProc&e.code; + is called once for each time it is loaded. + + </quote> + + &s.code;void TearDownProc(pointer tearDownData)&e.code; + <quote><p> + When defined, this function is called when the loader unloads a + module. The &s.code;tearDownData&e.code; parameter is the return + value of the &s.code;SetupProc()&e.code; that was called when the + module was loaded. The purpose of this function is to clean up + before the module is unloaded (for example, by freeing allocated + resources). + + </quote> + </quote> + +<sect1>Public Loader Interface +<p> + +The following is the Loader interface that is available to any part of +the server, and may also be used from within modules. + + <quote><p> + &s.code;pointer LoadSubModule(pointer parent, const char *module, + &f.indent;const char **subdirlist, const char **patternlist, + &f.indent;pointer options, const XF86ModReqInfo * modreq, + &f.indent;int *errmaj, int *errmin)&e.code; + <quote><p> + This function is like the &s.code;LoadModule()&e.code; function + described above, except that the module loaded is registered as a + child of the calling module. The &s.code;parent&e.code; parameter + is the calling module's handle. Modules loaded with this function + are automatically unloaded when the parent module is unloaded. The + other difference is that the path parameter may not be specified. + The module search path used for modules loaded with this function + is the default search path as initialised with + &s.code;LoaderSetPath()&e.code;. + + </quote> + + &s.code;void UnloadSubModule(pointer module)&e.code; + <quote><p> + This function unloads the module with handle &s.code;module&e.code;. + If that module itself has children, they are also unloaded. It is + like &s.code;UnloadModule()&e.code;, except that it is safe to use + for unloading child modules. + + </quote> + + &s.code;pointer LoaderSymbol(const char *symbol)&e.code; + <quote><p> + This function returns the address of the symbol with name + &s.code;symbol&e.code;. This may be used to locate a module entry + point with a known name. + + </quote> + + &s.code;char **LoaderlistDirs(const char **subdirlist, + &f.indent;const char **patternlist)&e.code; + <quote><p> + This function returns a &s.code;NULL&e.code; terminated list of + canonical modules names for modules found in the default module + search path. The &s.code;subdirlist&e.code; and + &s.code;patternlist&e.code; parameters are as described above, and + can be used to control the locations and names that are searched. + If no modules are found, the return value is &s.code;NULL&e.code;. + The returned list should be freed by calling + &s.code;LoaderFreeDirList()&e.code; when it is no longer needed. + + </quote> + + &s.code;void LoaderFreeDirList(char **list)&e.code; + <quote><p> + This function frees a module list created by + &s.code;LoaderlistDirs()&e.code;. + + </quote> + + &s.code;void LoaderReqSymLists(const char **list0, ...)&e.code; + <quote><p> + This function allows the registration of required symbols with the + loader. It is normally used by a caller of + &s.code;LoadSubModule()&e.code;. If any symbols registered in this + way are found to be unresolved when + &s.code;LoaderCheckUnresolved()&e.code; is called then + &s.code;LoaderCheckUnresolved()&e.code; will report a failure. + The function takes one or more &s.code;NULL&e.code; terminated + lists of symbols. The end of the argument list is indicated by a + &s.code;NULL&e.code; argument. + + </quote> + + &s.code;void LoaderReqSymbols(const char *sym0, ...)&e.code; + <quote><p> + This function is like &s.code;LoaderReqSymLists()&e.code; except + that its arguments are symbols rather than lists of symbols. This + function is more convenient when single functions are to be registered, + especially when the single function might depend on runtime factors. + The end of the argument list is indicated by a &s.code;NULL&e.code; + argument. + + </quote> + + &s.code;void LoaderRefSymLists(const char **list0, ...)&e.code; + <quote><p> + This function allows the registration of possibly unresolved symbols + with the loader. When &s.code;LoaderCheckUnresolved()&e.code; is + run it won't generate warnings for symbols registered in this way + unless they were also registered as required symbols. + The function takes one or more &s.code;NULL&e.code; terminated + lists of symbols. The end of the argument list is indicated by a + &s.code;NULL&e.code; argument. + + </quote> + + &s.code;void LoaderRefSymbols(const char *sym0, ...)&e.code; + <quote><p> + This function is like &s.code;LoaderRefSymLists()&e.code; except + that its arguments are symbols rather than lists of symbols. This + function is more convenient when single functions are to be registered, + especially when the single function might depend on runtime factors. + The end of the argument list is indicated by a &s.code;NULL&e.code; + argument. + + </quote> + + &s.code;int LoaderCheckUnresolved(int delayflag)&e.code; + <quote><p> + This function checks for unresolved symbols. It generates warnings + for unresolved symbols that have not been registered with + &s.code;LoaderRefSymLists()&e.code;, and maps them to a dummy + function. This behaviour may change in future. If unresolved + symbols are found that have been registered with + &s.code;LoaderReqSymLists()&e.code; or + &s.code;LoaderReqSymbols()&e.code; then this function returns a + non-zero value. If none of these symbols are unresolved the return + value is zero, indicating success. + + The &s.code;delayflag&e.code; parameter should normally be set to + &s.code;LD_RESOLV_IFDONE&e.code;. + + </quote> + + &s.code;LoaderErrorMsg(const char *name, const char *modname, + &f.indent;int errmaj, int errmin)&e.code; + <quote><p> + This function prints an error message that includes the text ``Failed + to load module'', the module name &s.code;modname&e.code;, a message + specific to the &s.code;errmaj&e.code; value, and the value if + &s.code;errmin&e.code;. If &s.code;name&e.code; is + non-&s.code;NULL&e.code;, it is printed as an identifying prefix + to the message (followed by a `:'). + + </quote> + </quote> + +<sect1>Special Registration Functions +<p> + +The loader contains some functions for registering some classes of modules. +These may be moved out of the loader at some point. + + <quote><p> + &s.code;void LoadExtension(ExtensionModule *ext)&e.code; + <quote><p> + This registers the entry points for the extension identified by + &s.code;ext&e.code;. The &s.code;ExtensionModule&e.code; struct is + defined as: + +<quote> +<verb> +typedef struct { + InitExtension initFunc; + char * name; + Bool *disablePtr; + InitExtension setupFunc; +} ExtensionModule; +</verb> +</quote> + + </quote> + + &s.code;void LoadFont(FontModule *font)&e.code; + <quote><p> + This registers the entry points for the font rasteriser module + identified by &s.code;font&e.code;. The &s.code;FontModule&e.code; + struct is defined as: + +<quote> +<verb> +typedef struct { + InitFont initFunc; + char * name; + pointer module; +} FontModule; +</verb> +</quote> + + </quote> + </quote> + +</sect> + + +<sect>Helper Functions +<p> + +This section describe ``helper'' functions that video driver +might find useful. While video drivers are not required to use any of +these to be considered ``compliant'', the use of appropriate helpers is +strongly encouraged to improve the consistency of driver behaviour. + +<sect1>Functions for printing messages +<p> + + <quote><p> + &s.code;ErrorF(const char *format, ...)&e.code; + <quote><p> + This is the basic function for writing to the error log (typically + stderr and/or a log file). Video drivers should usually avoid + using this directly in favour of the more specialised functions + described below. This function is useful for printing messages + while debugging a driver. + + </quote> + + &s.code;FatalError(const char *format, ...)&e.code; + <quote><p> + This prints a message and causes the Xserver to abort. It should + rarely be used within a video driver, as most error conditions + should be flagged by the return values of the driver functions. + This allows the higher layers to decide how to proceed. In rare + cases, this can be used within a driver if a fatal unexpected + condition is found. + + </quote> + + &s.code;xf86ErrorF(const char *format, ...)&e.code; + <quote><p> + This is like &s.code;ErrorF()&e.code;, except that the message is + only printed when the Xserver's verbosity level is set to the + default (&s.code;1&e.code;) or higher. It means that the messages + are not printed when the server is started with the + &s.cmd;-quiet&e.cmd; flag. Typically this function would only be + used for continuing messages started with one of the more specialised + functions described below. + + </quote> + + &s.code;xf86ErrorFVerb(int verb, const char *format, ...)&e.code; + <quote><p> + Like &s.code;xf86ErrorF()&e.code;, except the minimum verbosity + level for which the message is to be printed is given explicitly. + Passing a &s.code;verb&e.code; value of zero means the message + is always printed. A value higher than &s.code;1&e.code; can be + used for information would normally not be needed, but which might + be useful when diagnosing problems. + + </quote> + + &s.code;xf86Msg(MessageType type, const char *format, ...)&e.code; + <quote><p> + This is like &s.code;xf86ErrorF()&e.code;, except that the message + is prefixed with a marker determined by the value of + &s.code;type&e.code;. The marker is used to indicate the type of + message (warning, error, probed value, config value, etc). Note + the &s.code;xf86Verbose&e.code; value is ignored for messages of + type &s.code;X_ERROR&e.code;. + + The marker values are: + + <quote> + &s.code;X_PROBED&e.code; + <quote>Value was probed.</quote> + &s.code;X_CONFIG&e.code; + <quote>Value was given in the config file.</quote> + &s.code;X_DEFAULT&e.code; + <quote>Value is a default.</quote> + &s.code;X_CMDLINE&e.code; + <quote>Value was given on the command line.</quote> + &s.code;X_NOTICE&e.code; + <quote>Notice.</quote> + &s.code;X_ERROR&e.code; + <quote>Error message.</quote> + &s.code;X_WARNING&e.code; + <quote>Warning message.</quote> + &s.code;X_INFO&e.code; + <quote>Informational message.</quote> + &s.code;X_NONE&e.code; + <quote>No prefix.</quote> + &s.code;X_NOT_IMPLEMENTED&e.code; + <quote>The message relates to functionality that is not yet + implemented.</quote> + </quote> + + + </quote> + + &s.code;xf86MsgVerb(MessageType type, int verb, const char *format, ...)&e.code; + <quote><p> + Like &s.code;xf86Msg()&e.code;, but with the verbosity level given + explicitly. + + </quote> + + &s.code;xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...)&e.code; + <quote><p> + This is like &s.code;xf86Msg()&e.code; except that the driver's + name (the &s.code;name&e.code; field of the + &s.code;ScrnInfoRec&e.code;) followed by the + &s.code;scrnIndex&e.code; in parentheses is printed following the + prefix. This should be used by video drivers in most cases as it + clearly indicates which driver/screen the message is for. If + &s.code;scrnIndex&e.code; is negative, this function behaves + exactly like &s.code;xf86Msg()&e.code;. + + NOTE: This function can only be used after the + &s.code;ScrnInfoRec&e.code; and its &s.code;name&e.code; field + have been allocated. Normally, this means that it can not be + used before the END of the &s.code;ChipProbe()&e.code; function. + Prior to that, use &s.code;xf86Msg()&e.code;, providing the + driver's name explicitly. No screen number can be supplied at + that point. + + </quote> + + &s.code;xf86DrvMsgVerb(int scrnIndex, MessageType type, int verb, + &f.indent;const char *format, ...)&e.code; + <quote><p> + Like &s.code;xf86DrvMsg()&e.code;, but with the verbosity level + given explicitly. + + </quote> + </quote> + + +<sect1>Functions for setting values based on command line and config file +<p> + + <quote><p> + &s.code;Bool xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int bpp, + &f.indent;int fbbpp, int depth24flags)&e.code; + <quote><p> + This function sets the &s.code;depth&e.code;, &s.code;pixmapBPP&e.code; and &s.code;bitsPerPixel&e.code; fields + of the &s.code;ScrnInfoRec&e.code;. It also determines the defaults for display-wide + attributes and pixmap formats the screen will support, and finds + the Display subsection that matches the depth/bpp. This function + should normally be called very early from the + &s.code;ChipPreInit()&e.code; function. + + It requires that the &s.code;confScreen&e.code; field of the &s.code;ScrnInfoRec&e.code; be + initialised prior to calling it. This is done by the XFree86 + common layer prior to calling &s.code;ChipPreInit()&e.code;. + + The parameters passed are: + + &s.code;depth&e.code; + <quote><p> + driver's preferred default depth if no other is given. + If zero, use the overall server default. + + </quote> + &s.code;bpp&e.code; + <quote><p> + Same, but for the pixmap bpp. + + </quote> + &s.code;fbbpp&e.code; + <quote><p> + Same, but for the framebuffer bpp. + + </quote> + &s.code;depth24flags&e.code; + <quote><p> + Flags that indicate the level of 24/32bpp support + and whether conversion between different framebuffer + and pixmap formats is supported. The flags for this + argument are defined as follows, and multiple flags + may be ORed together: + + &s.code;NoDepth24Support&e.code; + <quote>No depth 24 formats supported</quote> + &s.code;Support24bppFb&e.code; + <quote>24bpp framebuffer supported</quote> + &s.code;Support32bppFb&e.code; + <quote>32bpp framebuffer supported</quote> + &s.code;SupportConvert24to32&e.code; + <quote>Can convert 24bpp pixmap to 32bpp fb</quote> + &s.code;SupportConvert32to24&e.code; + <quote>Can convert 32bpp pixmap to 24bpp fb</quote> + &s.code;ForceConvert24to32&e.code; + <quote>Force 24bpp pixmap to 32bpp fb conversion</quote> + &s.code;ForceConvert32to24&e.code; + <quote>Force 32bpp pixmap to 24bpp fb conversion</quote> + + </quote> + + It uses the command line, config file, and default values in the + correct order of precedence to determine the depth and bpp values. + It is up to the driver to check the results to see that it supports + them. If not the &s.code;ChipPreInit()&e.code; function should + return &s.code;FALSE&e.code;. + + If only one of depth/bpp is given, the other is set to a reasonable + (and consistent) default. + + If a driver finds that the initial &s.code;depth24flags&e.code; + it uses later results in a fb format that requires more video + memory than is available it may call this function a second time + with a different &s.code;depth24flags&e.code; setting. + + On success, the return value is &s.code;TRUE&e.code;. On failure + it prints an error message and returns &s.code;FALSE&e.code;. + + The following fields of the &s.code;ScrnInfoRec&e.code; are + initialised by this function: + + <quote> + &s.code;depth&e.code;, &s.code;bitsPerPixel&e.code;, + &s.code;display&e.code;, &s.code;imageByteOrder&e.code;, + &s.code;bitmapScanlinePad&e.code;, + &s.code;bitmapScanlineUnit&e.code;, &s.code;bitmapBitOrder&e.code;, + &s.code;numFormats&e.code;, &s.code;formats&e.code;, + &s.code;fbFormat&e.code;. + </quote> + + </quote> + + &s.code;void xf86PrintDepthBpp(scrnInfoPtr scrp)&e.code; + <quote><p> + This function can be used to print out the depth and bpp settings. + It should be called after the final call to + &s.code;xf86SetDepthBpp()&e.code;. + + </quote> + + &s.code;Bool xf86SetWeight(ScrnInfoPtr scrp, rgb weight, rgb mask)&e.code; + <quote><p> + This function sets the &s.code;weight&e.code;, &s.code;mask&e.code;, + &s.code;offset&e.code; and &s.code;rgbBits&e.code; fields of the + &s.code;ScrnInfoRec&e.code;. It would normally be called fairly + early in the &s.code;ChipPreInit()&e.code; function for + depths > 8bpp. + + It requires that the &s.code;depth&e.code; and + &s.code;display&e.code; fields of the &s.code;ScrnInfoRec&e.code; + be initialised prior to calling it. + + The parameters passed are: + + &s.code;weight&e.code; + <quote><p> + driver's preferred default weight if no other is given. + If zero, use the overall server default. + + </quote> + + &s.code;mask&e.code; + <quote><p> + Same, but for mask. + + </quote> + + It uses the command line, config file, and default values in the + correct order of precedence to determine the weight value. It + derives the mask and offset values from the weight and the defaults. + It is up to the driver to check the results to see that it supports + them. If not the &s.code;ChipPreInit()&e.code; function should + return &s.code;FALSE&e.code;. + + On success, this function prints a message showing the weight + values selected, and returns &s.code;TRUE&e.code;. + + On failure it prints an error message and returns &s.code;FALSE&e.code;. + + The following fields of the &s.code;ScrnInfoRec&e.code; are + initialised by this function: + + <quote> + &s.code;weight&e.code;, &s.code;mask&e.code;, &s.code;offset&e.code;. + </quote> + + </quote> + + &s.code;Bool xf86SetDefaultVisual(ScrnInfoPtr scrp, int visual)&e.code; + <quote><p> + This function sets the &s.code;defaultVisual&e.code; field of the + &s.code;ScrnInfoRec&e.code;. It would normally be called fairly + early from the &s.code;ChipPreInit()&e.code; function. + + It requires that the &s.code;depth&e.code; and + &s.code;display&e.code; fields of the &s.code;ScrnInfoRec&e.code; + be initialised prior to calling it. + + The parameters passed are: + + &s.code;visual&e.code; + <quote><p> + driver's preferred default visual if no other is given. + If &s.code;-1&e.code;, use the overall server default. + + </quote> + + It uses the command line, config file, and default values in the + correct order of precedence to determine the default visual value. + It is up to the driver to check the result to see that it supports + it. If not the &s.code;ChipPreInit()&e.code; function should + return &s.code;FALSE&e.code;. + + On success, this function prints a message showing the default visual + selected, and returns &s.code;TRUE&e.code;. + + On failure it prints an error message and returns &s.code;FALSE&e.code;. + + </quote> + + &s.code;Bool xf86SetGamma(ScrnInfoPtr scrp, Gamma gamma)&e.code; + <quote><p> + This function sets the &s.code;gamma&e.code; field of the + &s.code;ScrnInfoRec&e.code;. It would normally be called fairly + early from the &s.code;ChipPreInit()&e.code; function in cases + where the driver supports gamma correction. + + It requires that the &s.code;monitor&e.code; field of the + &s.code;ScrnInfoRec&e.code; be initialised prior to calling it. + + The parameters passed are: + + &s.code;gamma&e.code; + <quote><p> + driver's preferred default gamma if no other is given. + If zero (&s.code;< 0.01&e.code;), use the overall server + default. + + </quote> + + It uses the command line, config file, and default values in the + correct order of precedence to determine the gamma value. It is + up to the driver to check the results to see that it supports + them. If not the &s.code;ChipPreInit()&e.code; function should + return &s.code;FALSE&e.code;. + + On success, this function prints a message showing the gamma + value selected, and returns &s.code;TRUE&e.code;. + + On failure it prints an error message and returns &s.code;FALSE&e.code;. + + </quote> + + &s.code;void xf86SetDpi(ScrnInfoPtr pScrn, int x, int y)&e.code; + <quote><p> + This function sets the &s.code;xDpi&e.code; and &s.code;yDpi&e.code; + fields of the &s.code;ScrnInfoRec&e.code;. The driver can specify + preferred defaults by setting &s.code;x&e.code; and &s.code;y&e.code; + to non-zero values. The &s.cmd;-dpi&e.cmd; command line option + overrides all other settings. Otherwise, if the + &s.key;DisplaySize&e.key; entry is present in the screen's &k.monitor; + config file section, it is used together with the virtual size to + calculate the dpi values. This function should be called after + all the mode resolution has been done. + + </quote> + + &s.code;void xf86SetBlackWhitePixels(ScrnInfoPtr pScrn)&e.code; + <quote><p> + This functions sets the &s.code;blackPixel&e.code; and + &s.code;whitePixel&e.code; fields of the &s.code;ScrnInfoRec&e.code; + according to whether or not the &s.cmd;-flipPixels&e.cmd; command + line options is present. + + </quote> + + &s.code;const char *xf86GetVisualName(int visual)&e.code; + <quote><p> + Returns a printable string with the visual name matching the + numerical visual class provided. If the value is outside the + range of valid visual classes, &s.code;NULL&e.code; is returned. + + </quote> + </quote> + + +<sect1>Primary Mode functions +<p> + +The primary mode helper functions are those which would normally be +used by a driver, unless it has unusual requirements which cannot +be catered for the by the helpers. + + <quote><p> + &s.code;int xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, + &f.indent;char **modeNames, ClockRangePtr clockRanges, + &f.indent;int *linePitches, int minPitch, int maxPitch, + &f.indent;int pitchInc, int minHeight, int maxHeight, + &f.indent;int virtualX, int virtualY, + &f.indent;unsigned long apertureSize, + &f.indent;LookupModeFlags strategy)&e.code; + <quote><p> + This function basically selects the set of modes to use based on + those available and the various constraints. It also sets some + other related parameters. It is normally called near the end of + the &s.code;ChipPreInit()&e.code; function. + + The parameters passed to the function are: + + &s.code;availModes&e.code; + <quote><p> + List of modes available for the monitor. + + </quote> + &s.code;modeNames&e.code; + <quote><p> + List of mode names that the screen is requesting. + + </quote> + &s.code;clockRanges&e.code; + <quote><p> + A list of clock ranges allowed by the driver. Each + range includes whether interlaced or multiscan modes + are supported for that range. See below for more on + &s.code;clockRanges&e.code;. + + </quote> + &s.code;linePitches&e.code; + <quote><p> + List of line pitches supported by the driver. + This is optional and should be &s.code;NULL&e.code; when + not used. + + </quote> + &s.code;minPitch&e.code; + <quote><p> + Minimum line pitch supported by the driver. This must + be supplied when &s.code;linePitches&e.code; is + &s.code;NULL&e.code;, and is ignored otherwise. + + </quote> + &s.code;maxPitch&e.code; + <quote><p> + Maximum line pitch supported by the driver. This is + required when &s.code;minPitch&e.code; is required. + + </quote> + &s.code;pitchInc&e.code; + <quote><p> + Granularity of horizontal pitch values as supported by + the chipset. This is expressed in bits. This must be + supplied. + + </quote> + &s.code;minHeight&e.code; + <quote><p> + minimum virtual height allowed. If zero, no limit is + imposed. + + </quote> + &s.code;maxHeight&e.code; + <quote><p> + maximum virtual height allowed. If zero, no limit is + imposed. + + </quote> + &s.code;virtualX&e.code; + <quote><p> + If greater than zero, this is the virtual width value + that will be used. Otherwise, the virtual width is + chosen to be the smallest that can accommodate the modes + selected. + + </quote> + &s.code;virtualY&e.code; + <quote><p> + If greater than zero, this is the virtual height value + that will be used. Otherwise, the virtual height is + chosen to be the smallest that can accommodate the modes + selected. + + </quote> + &s.code;apertureSize&e.code; + <quote><p> + The size (in bytes) of the aperture used to access video + memory. + + </quote> + &s.code;strategy&e.code; + <quote><p> + The strategy to use when choosing from multiple modes + with the same name. The options are: + + &s.code;LOOKUP_DEFAULT&e.code; + <quote>???</quote> + &s.code;LOOKUP_BEST_REFRESH&e.code; + <quote>mode with best refresh rate</quote> + &s.code;LOOKUP_CLOSEST_CLOCK&e.code; + <quote>mode with closest matching clock</quote> + &s.code;LOOKUP_LIST_ORDER&e.code; + <quote>first usable mode in list</quote> + + The following options can also be combined (OR'ed) with + one of the above: + + &s.code;LOOKUP_CLKDIV2&e.code; + <quote>Allow halved clocks</quote> + &s.code;LOOKUP_OPTIONAL_TOLERANCES&e.code; + <quote>Allow missing horizontal sync and/or vertical refresh + ranges in the xorg.conf Monitor section</quote> + + &s.code;LOOKUP_OPTIONAL_TOLERANCES&e.code; should only be + specified when the driver can ensure all modes it generates + can sync on, or at least not damage, the monitor or digital + flat panel. Horizontal sync and/or vertical refresh ranges + specified by the user will still be honoured (and acted upon). + + </quote> + + This function requires that the following fields of the + &s.code;ScrnInfoRec&e.code; are initialised prior to calling it: + + &s.code;clock[]&e.code; + <quote>List of discrete clocks (when non-programmable)</quote> + &s.code;numClocks&e.code; + <quote>Number of discrete clocks (when non-programmable)</quote> + &s.code;progClock&e.code; + <quote>Whether the clock is programmable or not</quote> + &s.code;monitor&e.code; + <quote>Pointer to the applicable xorg.conf monitor section</quote> + &s.code;fdFormat&e.code; + <quote>Format of the screen buffer</quote> + &s.code;videoRam&e.code; + <quote>total video memory size (in bytes)</quote> + &s.code;maxHValue&e.code; + <quote>Maximum horizontal timing value allowed</quote> + &s.code;maxVValue&e.code; + <quote>Maximum vertical timing value allowed</quote> + &s.code;xInc&e.code; + <quote>Horizontal timing increment in pixels (defaults to 8)</quote> + + This function fills in the following &s.code;ScrnInfoRec&e.code; + fields: + + &s.code;modePool&e.code; + <quote><p> + A subset of the modes available to the monitor which + are compatible with the driver. + + </quote> + &s.code;modes&e.code; + <quote><p> + One mode entry for each of the requested modes, with + the status field of each filled in to indicate if + the mode has been accepted or not. This list of + modes is a circular list. + + </quote> + &s.code;virtualX&e.code; + <quote><p> + The resulting virtual width. + + </quote> + &s.code;virtualY&e.code; + <quote><p> + The resulting virtual height. + + </quote> + &s.code;displayWidth&e.code; + <quote><p> + The resulting line pitch. + + </quote> + &s.code;virtualFrom&e.code; + <quote><p> + Where the virtual size was determined from. + + </quote> + + The first stage of this function checks that the + &s.code;virtualX&e.code; and &s.code;virtualY&e.code; values + supplied (if greater than zero) are consistent with the line pitch + and &s.code;maxHeight&e.code; limitations. If not, an error + message is printed, and the return value is &s.code;-1&e.code;. + + The second stage sets up the mode pool, eliminating immediately + any modes that exceed the driver's line pitch limits, and also + the virtual width and height limits (if greater than zero). For + each mode removed an informational message is printed at verbosity + level &s.code;2&e.code;. If the mode pool ends up being empty, + a warning message is printed, and the return value is + &s.code;0&e.code;. + + The final stage is to lookup each mode name, and fill in the remaining + parameters. If an error condition is encountered, a message is + printed, and the return value is &s.code;-1&e.code;. Otherwise, + the return value is the number of valid modes found + (&s.code;0&e.code; if none are found). + + Even if the supplied mode names include duplicates, no two names will + ever match the same mode. Furthermore, if the supplied mode names do not + yield a valid mode (including the case where no names are passed at all), + the function will continue looking through the mode pool until it finds + a mode that survives all checks, or until the mode pool is exhausted. + + A message is only printed by this function when a fundamental + problem is found. It is intended that this function may be called + more than once if there is more than one set of constraints that + the driver can work within. + + If this function returns &s.code;-1&e.code;, the + &s.code;ChipPreInit()&e.code; function should return + &s.code;FALSE&e.code;. + + &s.code;clockRanges&e.code; is a linked list of clock ranges + allowed by the driver. If a mode doesn't fit in any of the defined + &s.code;clockRanges&e.code;, it is rejected. The first + &s.code;clockRange&e.code; that matches all requirements is used. + This structure needs to be initialized to NULL when allocated. + + &s.code;clockRanges&e.code; contains the following fields: + + &s.code;minClock&nl; + maxClock&e.code; + <quote><p> + The lower and upper mode clock bounds for which the rest + of the &s.code;clockRange&e.code; parameters apply. + Since these are the mode clocks, they are not scaled + with the &s.code;ClockMulFactor&e.code; and + &s.code;ClockDivFactor&e.code;. It is up to the driver + to adjust these values if they depend on the clock + scaling factors. + + </quote> + &s.code;clockIndex&e.code; + <quote><p> + (not used yet) &s.code;-1&e.code; for programmable clocks + + </quote> + &s.code;interlaceAllowed&e.code; + <quote><p> + &s.code;TRUE&e.code; if interlacing is allowed for this + range + + </quote> + &s.code;doubleScanAllowed&e.code; + <quote><p> + &s.code;TRUE&e.code; if doublescan or multiscan is allowed + for this range + + </quote> + &s.code;ClockMulFactor&nl; + ClockDivFactor&e.code; + <quote><p> + Scaling factors that are applied to the mode clocks ONLY + before selecting a clock index (when there is no + programmable clock) or a &s.code;SynthClock&e.code; + value. This is useful for drivers that support pixel + multiplexing or that need to scale the clocks because + of hardware restrictions (like sending 24bpp data to an + 8 bit RAMDAC using a tripled clock). + + Note that these parameters describe what must be done + to the mode clock to achieve the data transport clock + between graphics controller and RAMDAC. For example + for &s.code;2:1&e.code; pixel multiplexing, two pixels + are sent to the RAMDAC on each clock. This allows the + RAMDAC clock to be half of the actual pixel clock. + Hence, &s.code;ClockMulFactor=1&e.code; and + &s.code;ClockDivFactor=2&e.code;. This means that the + clock used for clock selection (ie, determining the + correct clock index from the list of discrete clocks) + or for the &s.code;SynthClock&e.code; field in case of + a programmable clock is: (&s.code;mode->Clock * + ClockMulFactor) / ClockDivFactor&e.code;. + + </quote> + &s.code;PrivFlags&e.code; + <quote><p> + This field is copied into the + &s.code;mode->PrivFlags&e.code; field when this + &s.code;clockRange&e.code; is selected by + &s.code;xf86ValidateModes()&e.code;. It allows the + driver to find out what clock range was selected, so it + knows it needs to set up pixel multiplexing or any other + range-dependent feature. This field is purely + driver-defined: it may contain flag bits, an index or + anything else (as long as it is an &s.code;INT&e.code;). + </quote> + + Note that the &s.code;mode->SynthClock&e.code; field is always + filled in by &s.code;xf86ValidateModes()&e.code;: it will contain + the ``data transport clock'', which is the clock that will have + to be programmed in the chip when it has a programmable clock, or + the clock that will be picked from the clocks list when it is not + a programmable one. Thus: + + &s.code;mode->SynthClock = + &f.indent;(mode->Clock * ClockMulFactor) / ClockDivFactor&e.code; + + </quote> + + &s.code;void xf86PruneDriverModes(ScrnInfoPtr scrp)&e.code; + <quote><p> + This function deletes modes in the modes field of the + &s.code;ScrnInfoRec&e.code; that have been marked as invalid. + This is normally run after having run + &s.code;xf86ValidateModes()&e.code; for the last time. For each + mode that is deleted, a warning message is printed out indicating + the reason for it being deleted. + + </quote> + + &s.code;void xf86SetCrtcForModes(ScrnInfoPtr scrp, int adjustFlags)&e.code; + <quote><p> + This function fills in the &s.code;Crtc*&e.code; fields for all + the modes in the &s.code;modes&e.code; field of the + &s.code;ScrnInfoRec&e.code;. The &s.code;adjustFlags&e.code; + parameter determines how the vertical CRTC values are scaled for + interlaced modes. They are halved if it is + &s.code;INTERLACE_HALVE_V&e.code;. The vertical CRTC values are + doubled for doublescan modes, and are further multiplied by the + &s.code;VScan&e.code; value. + + This function is normally called after calling + &s.code;xf86PruneDriverModes()&e.code;. + + </quote> + + &s.code;void xf86PrintModes(ScrnInfoPtr scrp)&e.code; + <quote><p> + This function prints out the virtual size setting, and the line + pitch being used. It also prints out two lines for each mode being + used. The first line includes the mode's pixel clock, horizontal sync + rate, refresh rate, and whether it is interlaced, doublescanned and/or + multi-scanned. The second line is the mode's Modeline. + + This function is normally called after calling + &s.code;xf86SetCrtcForModes()&e.code;. + + </quote> + </quote> + + +<sect1>Secondary Mode functions +<p> + +The secondary mode helper functions are functions which are normally +used by the primary mode helper functions, and which are not normally +called directly by a driver. If a driver has unusual requirements +and needs to do its own mode validation, it might be able to make +use of some of these secondary mode helper functions. + + <quote><p> + &s.code;int xf86GetNearestClock(ScrnInfoPtr scrp, int freq, Bool allowDiv2, + &f.indent;int *divider)&e.code; + <quote><p> + This function returns the index of the closest clock to the + frequency &s.code;freq&e.code; given (in kHz). It assumes that + the number of clocks is greater than zero. It requires that the + &s.code;numClocks&e.code; and &s.code;clock&e.code; fields of the + &s.code;ScrnInfoRec&e.code; are initialised. The + &s.code;allowDiv2&e.code; field determines if the clocks can be + halved. The &s.code;*divider&e.code; return value indicates + whether clock division is used when determining the clock returned. + + This function is only for non-programmable clocks. + + </quote> + + &s.code;const char *xf86ModeStatusToString(ModeStatus status)&e.code; + <quote><p> + This function converts the &s.code;status&e.code; value to a + descriptive printable string. + + </quote> + + &s.code;ModeStatus xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep, + &f.indent;ClockRangePtr clockRanges, LookupModeFlags strategy)&e.code; + <quote><p> + This function takes a pointer to a mode with the name filled in, + and looks for a mode in the &s.code;modePool&e.code; list which + matches. The parameters of the matching mode are filled in to + &s.code;*modep&e.code;. The &s.code;clockRanges&e.code; and + &s.code;strategy&e.code; parameters are as for the + &s.code;xf86ValidateModes()&e.code; function above. + + This function requires the &s.code;modePool&e.code;, + &s.code;clock[]&e.code;, &s.code;numClocks&e.code; and + &s.code;progClock&e.code; fields of the &s.code;ScrnInfoRec&e.code; + to be initialised before being called. + + The return value is &s.code;MODE_OK&e.code; if a mode was found. + Otherwise it indicates why a matching mode could not be found. + + </quote> + + &s.code;ModeStatus xf86InitialCheckModeForDriver(ScrnInfoPtr scrp, + &f.indent;DisplayModePtr mode, ClockRangePtr clockRanges, + &f.indent;LookupModeFlags strategy, int maxPitch, + &f.indent;int virtualX, int virtualY)&e.code; + <quote><p> + This function checks the passed mode against some basic driver + constraints. Apart from the ones passed explicitly, the + &s.code;maxHValue&e.code; and &s.code;maxVValue&e.code; fields of + the &s.code;ScrnInfoRec&e.code; are also used. If the + &s.code;ValidMode&e.code; field of the &s.code;ScrnInfoRec&e.code; + is set, that function is also called to check the mode. Next, the + mode is checked against the monitor's constraints. + + If the mode is consistent with all constraints, the return value + is &s.code;MODE_OK&e.code;. Otherwise the return value indicates + which constraint wasn't met. + + </quote> + + &s.code;void xf86DeleteMode(DisplayModePtr *modeList, DisplayModePtr mode)&e.code; + <quote><p> + This function deletes the &s.code;mode&e.code; given from the + &s.code;modeList&e.code;. It never prints any messages, so it is + up to the caller to print a message if required. + + </quote> + </quote> + +<sect1>Functions for handling strings and tokens +<p> + + Tables associating strings and numerical tokens combined with the + following functions provide a compact way of handling strings from + the config file, and for converting tokens into printable strings. + The table data structure is: + +<quote><verb> +typedef struct { + int token; + const char * name; +} SymTabRec, *SymTabPtr; +</verb></quote> + + A table is an initialised array of &s.code;SymTabRec&e.code;. The + tokens must be non-negative integers. Multiple names may be mapped + to a single token. The table is terminated with an element with a + &s.code;token&e.code; value of &s.code;-1&e.code; and + &s.code;NULL&e.code; for the &s.code;name&e.code;. + + + <quote><p> + &s.code;const char *xf86TokenToString(SymTabPtr table, int token)&e.code; + <quote><p> + This function returns the first string in &s.code;table&e.code; + that matches &s.code;token&e.code;. If no match is found, + &s.code;NULL&e.code; is returned (NOTE, older versions of this + function would return the string "unknown" when no match is found). + + </quote> + + &s.code;int xf86StringToToken(SymTabPtr table, const char *string)&e.code; + <quote><p> + This function returns the first token in &s.code;table&e.code; + that matches &s.code;string&e.code;. The + &s.code;xf86NameCmp()&e.code; function is used to determine the + match. If no match is found, &s.code;-1&e.code; is returned. + + </quote> + </quote> + + +<sect1>Functions for finding which config file entries to use +<p> + + These functions can be used to select the appropriate config file + entries that match the detected hardware. They are described above + in the <ref id="probe" name="Probe"> and + <ref id="avail" name="Available Functions"> sections. + + +<sect1>Probing discrete clocks on old hardware +<p> + + The &s.code;xf86GetClocks()&e.code; function may be used to assist + in finding the discrete pixel clock values on older hardware. + + + <quote><p> + &s.code;void xf86GetClocks(ScrnInfoPtr pScrn, int num, + &f.indent;Bool (*ClockFunc)(ScrnInfoPtr, int), + &f.indent;void (*ProtectRegs)(ScrnInfoPtr, Bool), + &f.indent;void (*BlankScreen)(ScrnInfoPtr, Bool), + &f.indent;int vertsyncreg, int maskval, int knownclkindex, + &f.indent;int knownclkvalue)&e.code; + <quote><p> + This function uses a comparative sampling method to measure the + discrete pixel clock values. The number of discrete clocks to + measure is given by &s.code;num&e.code;. &s.code;clockFunc&e.code; + is a function that selects the &s.code;n&e.code;'th clock. It + should also save or restore any state affected by programming the + clocks when the index passed is &s.code;CLK_REG_SAVE&e.code; or + &s.code;CLK_REG_RESTORE&e.code;. &s.code;ProtectRegs&e.code; is + a function that does whatever is required to protect the hardware + state while selecting a new clock. &s.code;BlankScreen&e.code; + is a function that blanks the screen. &s.code;vertsyncreg&e.code; + and &s.code;maskval&e.code; are the register and bitmask to + check for the presence of vertical sync pulses. + &s.code;knownclkindex&e.code; and &s.code;knownclkvalue&e.code; + are the index and value of a known clock. These are the known + references on which the comparative measurements are based. The + number of clocks probed is set in &s.code;pScrn->numClocks&e.code;, + and the probed clocks are set in the &s.code;pScrn->clock[]&e.code; + array. All of the clock values are in units of kHz. + + </quote> + + &s.code;void xf86ShowClocks(ScrnInfoPtr scrp, MessageType from)&e.code; + <quote><p> + Print out the pixel clocks &s.code;scrp->clock[]&e.code;. + &s.code;from&e.code; indicates whether the clocks were probed + or from the config file. + + </quote> + </quote> + +<sect1>Other helper functions +<p> + <quote><p> + &s.code;Bool xf86IsUnblank(int mode)&e.code; + <quote><p> + Returns &s.code;TRUE&e.code; when the screen saver mode specified + by &s.code;mode&e.code; requires the screen be unblanked, + and &s.code;FALSE&e.code; otherwise. The screen saver modes that + require blanking are &s.code;SCREEN_SAVER_ON&e.code; and + &s.code;SCREEN_SAVER_CYCLE&e.code;, and the screen saver modes that + require unblanking are &s.code;SCREEN_SAVER_OFF&e.code; and + &s.code;SCREEN_SAVER_FORCER&e.code;. Drivers may call this helper + from their &s.code;SaveScreen()&e.code; function to interpret the + screen saver modes. + + </quote> + </quote> + +<sect>The vgahw module +<p> + +The vgahw modules provides an interface for saving, restoring and +programming the standard VGA registers, and for handling VGA colourmaps. + +<sect1>Data Structures +<p> + + The public data structures used by the vgahw module are + &s.code;vgaRegRec&e.code; and &s.code;vgaHWRec&e.code;. They are + defined in &s.code;vgaHW.h.&e.code; + + +<sect1>General vgahw Functions +<p> + + <quote><p> + &s.code;Bool vgaHWGetHWRec(ScrnInfoPtr pScrn)&e.code; + <quote><p> + This function allocates a &s.code;vgaHWRec&e.code; structure, and + hooks it into the &s.code;ScrnInfoRec&e.code;'s + &s.code;privates&e.code;. Like all information hooked into the + &s.code;privates&e.code;, it is persistent, and only needs to be + allocated once per screen. This function should normally be called + from the driver's &s.code;ChipPreInit()&e.code; function. The + &s.code;vgaHWRec&e.code; is zero-allocated, and the following + fields are explicitly initialised: + + &s.code;ModeReg.DAC[]&e.code; + <quote>initialised with a default colourmap</quote> + &s.code;ModeReg.Attribute[0x11]&e.code; + <quote>initialised with the default overscan index</quote> + &s.code;ShowOverscan&e.code; + <quote>initialised according to the "ShowOverscan" option</quote> + &s.code;paletteEnabled&e.code; + <quote>initialised to FALSE</quote> + &s.code;cmapSaved&e.code; + <quote>initialised to FALSE</quote> + &s.code;pScrn&e.code; + <quote>initialised to pScrn</quote> + + In addition to the above, &s.code;vgaHWSetStdFuncs()&e.code; is + called to initialise the register access function fields with the + standard VGA set of functions. + + Once allocated, a pointer to the &s.code;vgaHWRec&e.code; can be + obtained from the &s.code;ScrnInfoPtr&e.code; with the + &s.code;VGAHWPTR(pScrn)&e.code; macro. + + </quote> + + &s.code;void vgaHWFreeHWRec(ScrnInfoPtr pScrn)&e.code; + <quote><p> + This function frees a &s.code;vgaHWRec&e.code; structure. It + should be called from a driver's &s.code;ChipFreeScreen()&e.code; + function. + + </quote> + + &s.code;Bool vgaHWSetRegCounts(ScrnInfoPtr pScrn, int numCRTC, + &f.indent;int numSequencer, int numGraphics, int numAttribute)&e.code; + <quote><p> + This function allows the number of CRTC, Sequencer, Graphics and + Attribute registers to be changed. This makes it possible for + extended registers to be saved and restored with + &s.code;vgaHWSave()&e.code; and &s.code;vgaHWRestore()&e.code;. + This function should be called after a &s.code;vgaHWRec&e.code; + has been allocated with &s.code;vgaHWGetHWRec()&e.code;. The + default values are defined in &s.code;vgaHW.h&e.code; as follows: + + <quote><verb> +#define VGA_NUM_CRTC 25 +#define VGA_NUM_SEQ 5 +#define VGA_NUM_GFX 9 +#define VGA_NUM_ATTR 21 + </verb></quote> + + </quote> + + &s.code;Bool vgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src)&e.code; + <quote><p> + This function copies the contents of the VGA saved registers in + &s.code;src&e.code; to &s.code;dst&e.code;. Note that it isn't + possible to simply do this with &s.code;memcpy()&e.code; (or + similar). This function returns &s.code;TRUE&e.code; unless there + is a problem allocating space for the &s.code;CRTC&e.code and + related fields in &s.code;dst&e.code;. + + </quote> + + &s.code;void vgaHWSetStdFuncs(vgaHWPtr hwp)&e.code; + <quote><p> + This function initialises the register access function fields of + &s.code;hwp&e.code; with the standard VGA set of functions. This + is called by &s.code;vgaHWGetHWRec()&e.code;, so there is usually + no need to call this explicitly. The register access functions + are described below. If the registers are shadowed in some other + port I/O space (for example a PCI I/O region), these functions + can be used to access the shadowed registers if + &s.code;hwp->PIOOffset&e.code; is initialised with + &s.code;offset&e.code;, calculated in such a way that when the + standard VGA I/O port value is added to it the correct offset into + the PIO area results. This value is initialised to zero in + &s.code;vgaHWGetHWRec()&e.code;. (Note: the PIOOffset functionality + is present in XFree86 4.1.0 and later.) + + </quote> + + &s.code;void vgaHWSetMmioFuncs(vgaHWPtr hwp, CARD8 *base, int offset)&e.code; + <quote><p> + This function initialised the register access function fields of + hwp with a generic MMIO set of functions. + &s.code;hwp->MMIOBase&e.code; is initialised with + &s.code;base&e.code;, which must be the virtual address that the + start of MMIO area is mapped to. &s.code;hwp->MMIOOffset&e.code; + is initialised with &s.code;offset&e.code;, which must be calculated + in such a way that when the standard VGA I/O port value is added + to it the correct offset into the MMIO area results. That means + that these functions are only suitable when the VGA I/O ports are + made available in a direct mapping to the MMIO space. If that is + not the case, the driver will need to provide its own register + access functions. The register access functions are described + below. + + </quote> + + &s.code;Bool vgaHWMapMem(ScrnInfoPtr pScrn)&e.code; + <quote><p> + This function maps the VGA memory window. It requires that the + &s.code;vgaHWRec&e.code; be allocated. If a driver requires + non-default &s.code;MapPhys&e.code; or &s.code;MapSize&e.code; + settings (the physical location and size of the VGA memory window) + then those fields of the &s.code;vgaHWRec&e.code; must be initialised + before calling this function. Otherwise, this function initialiases + the default values of &s.code;0xA0000&e.code; for + &s.code;MapPhys&e.code; and &s.code;(64 * 1024)&e.code; for + &s.code;MapSize&e.code;. This function must be called before + attempting to save or restore the VGA state. If the driver doesn't + call it explicitly, the &s.code;vgaHWSave()&e.code; and + &s.code;vgaHWRestore()&e.code; functions may call it if they need + to access the VGA memory (in which case they will also call + &s.code;vgaHWUnmapMem()&e.code; to unmap the VGA memory before + exiting). + + </quote> + + &s.code;void vgaHWUnmapMem(ScrnInfoPtr pScrn)&e.code; + <quote><p> + This function unmaps the VGA memory window. It must only be called + after the memory has been mapped. The &s.code;Base&e.code; field + of the &s.code;vgaHWRec&e.code; field is set to &s.code;NULL&e.code; + to indicate that the memory is no longer mapped. + + </quote> + + &s.code;void vgaHWGetIOBase(vgaHWPtr hwp)&e.code; + <quote><p> + This function initialises the &s.code;IOBase&e.code; field of the + &s.code;vgaHWRec&e.code;. This function must be called before + using any other functions that access the video hardware. + + A macro &s.code;VGAHW_GET_IOBASE()&e.code; is also available in + &s.code;vgaHW.h&e.code; that returns the I/O base, and this may + be used when the vgahw module is not loaded (for example, in the + &s.code;ChipProbe()&e.code; function). + + </quote> + + &s.code;void vgaHWUnlock(vgaHWPtr hwp)&e.code; + <quote><p> + This function unlocks the VGA &s.code;CRTC[0-7]&e.code; registers, + and must be called before attempting to write to those registers. + + </quote> + + &s.code;void vgaHWLock(vgaHWPtr hwp)&e.code; + <quote><p> + This function locks the VGA &s.code;CRTC[0-7]&e.code; registers. + + </quote> + + &s.code;void vgaHWEnable(vgaHWPtr hwp)&e.code; + <quote><p> + This function enables the VGA subsystem. (Note, this function is + present in XFree86 4.1.0 and later.). + + </quote> + + &s.code;void vgaHWDisable(vgaHWPtr hwp)&e.code; + <quote><p> + This function disables the VGA subsystem. (Note, this function is + present in XFree86 4.1.0 and later.). + + </quote> + + &s.code;void vgaHWSave(ScrnInfoPtr pScrn, vgaRegPtr save, int flags)&e.code; + <quote><p> + This function saves the VGA state. The state is written to the + &s.code;vgaRegRec&e.code; pointed to by &s.code;save&e.code;. + &s.code;flags&e.code; is set to one or more of the following flags + ORed together: + + &s.code;VGA_SR_MODE&e.code; + <quote>the mode setting registers are saved</quote> + &s.code;VGA_SR_FONTS&e.code; + <quote>the text mode font/text data is saved</quote> + &s.code;VGA_SR_CMAP&e.code; + <quote>the colourmap (LUT) is saved</quote> + &s.code;VGA_SR_ALL&e.code; + <quote>all of the above are saved</quote> + + The &s.code;vgaHWRec&e.code; and its &s.code;IOBase&e.code; fields + must be initialised before this function is called. If + &s.code;VGA_SR_FONTS&e.code; is set in &s.code;flags&e.code;, the + VGA memory window must be mapped. If it isn't then + &s.code;vgaHWMapMem()&e.code; will be called to map it, and + &s.code;vgaHWUnmapMem()&e.code; will be called to unmap it + afterwards. &s.code;vgaHWSave()&e.code; uses the three functions + below in the order &s.code;vgaHWSaveColormap()&e.code;, + &s.code;vgaHWSaveMode()&e.code;, &s.code;vgaHWSaveFonts()&e.code; to + carry out the different save phases. It is undecided at this + stage whether they will remain part of the vgahw module's public + interface or not. + + </quote> + + &s.code;void vgaHWSaveMode(ScrnInfoPtr pScrn, vgaRegPtr save)&e.code; + <quote><p> + This function saves the VGA mode registers. They are saved to + the &s.code;vgaRegRec&e.code; pointed to by &s.code;save&e.code;. + The registers saved are: + + <quote> + &s.code;MiscOut&nl; + CRTC[0-0x18]&nl; + Attribute[0-0x14]&nl; + Graphics[0-8]&nl; + Sequencer[0-4]&e.code; + </quote> + + The number of registers actually saved may be modified by a prior call + to &s.code;vgaHWSetRegCounts()&e.code;. + + </quote> + + &s.code;void vgaHWSaveFonts(ScrnInfoPtr pScrn, vgaRegPtr save)&e.code; + <quote><p> + This function saves the text mode font and text data held in the + video memory. If called while in a graphics mode, no save is + done. The VGA memory window must be mapped with + &s.code;vgaHWMapMem()&e.code; before to calling this function. + + On some platforms, one or more of the font/text plane saves may be + no-ops. This is the case when the platform's VC driver already + takes care of this. + + </quote> + + &s.code;void vgaHWSaveColormap(ScrnInfoPtr pScrn, vgaRegPtr save)&e.code; + <quote><p> + This function saves the VGA colourmap (LUT). Before saving it, it + attempts to verify that the colourmap is readable. In rare cases + where it isn't readable, a default colourmap is saved instead. + + </quote> + + &s.code;void vgaHWRestore(ScrnInfoPtr pScrn, vgaRegPtr restore, int flags)&e.code; + <quote><p> + This function programs the VGA state. The state programmed is + that contained in the &s.code;vgaRegRec&e.code; pointed to by + &s.code;restore&e.code;. &s.code;flags&e.code; is the same + as described above for the &s.code;vgaHWSave()&e.code; function. + + The &s.code;vgaHWRec&e.code; and its &s.code;IOBase&e.code; fields + must be initialised before this function is called. If + &s.code;VGA_SR_FONTS&e.code; is set in &s.code;flags&e.code;, the + VGA memory window must be mapped. If it isn't then + &s.code;vgaHWMapMem()&e.code; will be called to map it, and + &s.code;vgaHWUnmapMem()&e.code; will be called to unmap it + afterwards. &s.code;vgaHWRestore()&e.code; uses the three functions + below in the order &s.code;vgaHWRestoreFonts()&e.code;, + &s.code;vgaHWRestoreMode()&e.code;, + &s.code;vgaHWRestoreColormap()&e.code; to carry out the different + restore phases. It is undecided at this stage whether they will + remain part of the vgahw module's public interface or not. + + </quote> + + &s.code;void vgaHWRestoreMode(ScrnInfoPtr pScrn, vgaRegPtr restore)&e.code; + <quote><p> + This function restores the VGA mode registers. They are restored + from the data in the &s.code;vgaRegRec&e.code; pointed to by + &s.code;restore&e.code;. The registers restored are: + + <quote> + &s.code;MiscOut&nl; + CRTC[0-0x18]&nl; + Attribute[0-0x14]&nl; + Graphics[0-8]&nl; + Sequencer[0-4]&e.code; + </quote> + + The number of registers actually restored may be modified by a prior call + to &s.code;vgaHWSetRegCounts()&e.code;. + + </quote> + + &s.code;void vgaHWRestoreFonts(ScrnInfoPtr pScrn, vgaRegPtr restore)&e.code; + <quote><p> + This function restores the text mode font and text data to the + video memory. The VGA memory window must be mapped with + &s.code;vgaHWMapMem()&e.code; before to calling this function. + + On some platforms, one or more of the font/text plane restores + may be no-ops. This is the case when the platform's VC driver + already takes care of this. + + </quote> + + &s.code;void vgaHWRestoreColormap(ScrnInfoPtr pScrn, vgaRegPtr restore)&e.code; + <quote><p> + This function restores the VGA colourmap (LUT). + + </quote> + + &s.code;void vgaHWInit(ScrnInfoPtr pScrn, DisplayModePtr mode)&e.code; + <quote><p> + This function fills in the &s.code;vgaHWRec&e.code;'s + &s.code;ModeReg&e.code; field with the values appropriate for + programming the given video mode. It requires that the + &s.code;ScrnInfoRec&e.code;'s &s.code;depth&e.code; field is + initialised, which determines how the registers are programmed. + + </quote> + + &s.code;void vgaHWSeqReset(vgaHWPtr hwp, Bool start)&e.code; + <quote><p> + Do a VGA sequencer reset. If start is &s.code;TRUE&e.code;, the + reset is started. If start is &s.code;FALSE&e.code;, the reset + is ended. + + </quote> + + &s.code;void vgaHWProtect(ScrnInfoPtr pScrn, Bool on)&e.code; + <quote><p> + This function protects VGA registers and memory from corruption + during loads. It is typically called with on set to + &s.code;TRUE&e.code; before programming, and with on set to + &s.code;FALSE&e.code; after programming. + + </quote> + + &s.code;Bool vgaHWSaveScreen(ScreenPtr pScreen, int mode)&e.code; + <quote><p> + This function blanks and unblanks the screen. It is blanked when + &s.code;mode&e.code; is &s.code;SCREEN_SAVER_ON&e.code; or + &s.code;SCREEN_SAVER_CYCLE&e.code;, and unblanked when + &s.code;mode&e.code; is &s.code;SCREEN_SAVER_OFF&e.code; or + &s.code;SCREEN_SAVER_FORCER&e.code;. + + </quote> + + &s.code;void vgaHWBlankScreen(ScrnInfoPtr pScrn, Bool on)&e.code; + <quote><p> + This function blanks and unblanks the screen. It is blanked when + &s.code;on&e.code; is &s.code;FALSE&e.code;, and unblanked when + &s.code;on&e.code; is &s.code;TRUE&e.code;. This function is + provided for use in cases where the &s.code;ScrnInfoRec&e.code; + can't be derived from the &s.code;ScreenRec&e.code; (while probing + for clocks, for example). + + </quote> + </quote> + +<sect1>VGA Colormap Functions +<p> + + The vgahw module uses the standard colormap support (see the + <ref id="cmap" name="Colormap Handling"> section. This is initialised + with the following function: + + <quote> + &s.code;Bool vgaHWHandleColormaps(ScreenPtr pScreen)&e.code; + </quote> + + +<sect1>VGA Register Access Functions +<p> + + The vgahw module abstracts access to the standard VGA registers by + using a set of functions held in the &s.code;vgaHWRec&e.code;. When + the &s.code;vgaHWRec&e.code; is created these function pointers are + initialised with the set of standard VGA I/O register access functions. + In addition to these, the vgahw module includes a basic set of MMIO + register access functions, and the &s.code;vgaHWRec&e.code; function + pointers can be initialised to these by calling the + &s.code;vgaHWSetMmioFuncs()&e.code; function described above. Some + drivers/platforms may require a different set of functions for VGA + access. The access functions are described here. + + + <quote><p> + &s.code;void writeCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)&e.code; + <quote><p> + Write &s.code;value&e.code; to CRTC register &s.code;index&e.code;. + + </quote> + + &s.code;CARD8 readCrtc(vgaHWPtr hwp, CARD8 index)&e.code; + <quote><p> + Return the value read from CRTC register &s.code;index&e.code;. + + </quote> + + &s.code;void writeGr(vgaHWPtr hwp, CARD8 index, CARD8 value)&e.code; + <quote><p> + Write &s.code;value&e.code; to Graphics Controller register + &s.code;index&e.code;. + + </quote> + + &s.code;CARD8 readGR(vgaHWPtr hwp, CARD8 index)&e.code; + <quote><p> + Return the value read from Graphics Controller register + &s.code;index&e.code;. + + </quote> + + &s.code;void writeSeq(vgaHWPtr hwp, CARD8 index, CARD8, value)&e.code; + <quote><p> + Write &s.code;value&e.code; to Sequencer register + &s.code;index&e.code;. + + </quote> + + &s.code;CARD8 readSeq(vgaHWPtr hwp, CARD8 index)&e.code; + <quote><p> + Return the value read from Sequencer register &s.code;index&e.code;. + + </quote> + + &s.code;void writeAttr(vgaHWPtr hwp, CARD8 index, CARD8, value)&e.code; + <quote><p> + Write &s.code;value&e.code; to Attribute Controller register + &s.code;index&e.code;. When writing out the index value this + function should set bit 5 (&s.code;0x20&e.code;) according to the + setting of &s.code;hwp->paletteEnabled&e.code; in order to + preserve the palette access state. It should be cleared when + &s.code;hwp->paletteEnabled&e.code; is &s.code;TRUE&e.code; + and set when it is &s.code;FALSE&e.code;. + + </quote> + + &s.code;CARD8 readAttr(vgaHWPtr hwp, CARD8 index)&e.code; + <quote><p> + Return the value read from Attribute Controller register + &s.code;index&e.code;. When writing out the index value this + function should set bit 5 (&s.code;0x20&e.code;) according to the + setting of &s.code;hwp->paletteEnabled&e.code; in order to + preserve the palette access state. It should be cleared when + &s.code;hwp->paletteEnabled&e.code; is &s.code;TRUE&e.code; + and set when it is &s.code;FALSE&e.code;. + + </quote> + + &s.code;void writeMiscOut(vgaHWPtr hwp, CARD8 value)&e.code; + <quote><p> + Write `&s.code;value&e.code;' to the Miscellaneous Output register. + + </quote> + + &s.code;CARD8 readMiscOut(vgwHWPtr hwp)&e.code; + <quote><p> + Return the value read from the Miscellaneous Output register. + + </quote> + + &s.code;void enablePalette(vgaHWPtr hwp)&e.code; + <quote><p> + Clear the palette address source bit in the Attribute Controller + index register and set &s.code;hwp->paletteEnabled&e.code; to + &s.code;TRUE&e.code;. + + </quote> + + &s.code;void disablePalette(vgaHWPtr hwp)&e.code; + <quote><p> + Set the palette address source bit in the Attribute Controller + index register and set &s.code;hwp->paletteEnabled&e.code; to + &s.code;FALSE&e.code;. + + </quote> + + &s.code;void writeDacMask(vgaHWPtr hwp, CARD8 value)&e.code; + <quote><p> + Write &s.code;value&e.code; to the DAC Mask register. + + </quote> + + &s.code;CARD8 readDacMask(vgaHWptr hwp)&e.code; + <quote><p> + Return the value read from the DAC Mask register. + + </quote> + + &s.code;void writeDacReadAddress(vgaHWPtr hwp, CARD8 value)&e.code; + <quote><p> + Write &s.code;value&e.code; to the DAC Read Address register. + + </quote> + + &s.code;void writeDacWriteAddress(vgaHWPtr hwp, CARD8 value)&e.code; + <quote><p> + Write &s.code;value&e.code; to the DAC Write Address register. + + </quote> + + &s.code;void writeDacData(vgaHWPtr hwp, CARD8 value)&e.code; + <quote><p> + Write &s.code;value&e.code; to the DAC Data register. + + </quote> + + &s.code;CARD8 readDacData(vgaHWptr hwp)&e.code; + <quote><p> + Return the value read from the DAC Data register. + + </quote> + + &s.code;CARD8 readEnable(vgaHWptr hwp)&e.code; + <quote><p> + Return the value read from the VGA Enable register. (Note: This + function is present in XFree86 4.1.0 and later.) + + </quote> + + &s.code;void writeEnable(vgaHWPtr hwp, CARD8 value)&e.code; + <quote><p> + Write &s.code;value&e.code; to the VGA Enable register. (Note: This + function is present in XFree86 4.1.0 and later.) + + </quote> + </quote> + +<sect>Some notes about writing a driver<label id="sample"> +<p> + +<em>NOTE: some parts of this are not up to date</em> + +The following is an outline for writing a basic unaccelerated driver +for a PCI video card with a linear mapped framebuffer, and which has a +VGA core. It is includes some general information that is relevant to +most drivers (even those which don't fit that basic description). + +The information here is based on the initial conversion of the Matrox +Millennium driver to the ``new design''. For a fleshing out and sample +implementation of some of the bits outlined here, refer to that driver. +Note that this is an example only. The approach used here will not be +appropriate for all drivers. + +Each driver must reserve a unique driver name, and a string that is used +to prefix all of its externally visible symbols. This is to avoid name +space clashes when loading multiple drivers. The examples here are for +the ``ZZZ'' driver, which uses the ``ZZZ'' or ``zzz'' prefix for its externally +visible symbols. + + +<sect1>Include files +<p> + + All drivers normally include the following headers: + <quote> + &s.code;"xf86.h"&nl; + "xf86_OSproc.h"&nl; + "xf86_ansic.h"&nl; + "xf86Resources.h"&e.code; + </quote> + Wherever inb/outb (and related things) are used the following should be + included: + <quote> + &s.code;"compiler.h"&e.code; + </quote> + Note: in drivers, this must be included after &s.code;"xf86_ansic.h"&e.code;. + + Drivers that need to access PCI vendor/device definitions need this: + <quote> + &s.code;"xf86PciInfo.h"&e.code; + </quote> + + Drivers that need to access the PCI config space need this: + <quote> + &s.code;"xf86Pci.h"&e.code; + </quote> + + Drivers using the mi banking wrapper need: + + <quote> + &s.code;"mibank.h"&e.code; + </quote> + + Drivers that initialise a SW cursor need this: + <quote> + &s.code;"mipointer.h"&e.code; + </quote> + + All drivers implementing backing store need this: + <quote> + &s.code;"mibstore.h"&e.code; + </quote> + + All drivers using the mi colourmap code need this: + <quote> + &s.code;"micmap.h"&e.code; + </quote> + + If a driver uses the vgahw module, it needs this: + <quote> + &s.code;"vgaHW.h"&e.code; + </quote> + + Drivers supporting VGA or Hercules monochrome screens need: + <quote> + &s.code;"xf1bpp.h"&e.code; + </quote> + + Drivers supporting VGA or EGC 16-colour screens need: + <quote> + &s.code;"xf4bpp.h"&e.code; + </quote> + + Drivers using cfb need: + <quote> + &s.code;#define PSZ 8&nl; + #include "cfb.h"&nl; + #undef PSZ&e.code; + </quote> + + Drivers supporting bpp 16, 24 or 32 with cfb need one or more of: + <quote> + &s.code;"cfb16.h"&nl; + "cfb24.h"&nl; + "cfb32.h"&e.code; + </quote> + + The driver's own header file: + <quote> + &s.code;"zzz.h"&e.code; + </quote> + + Drivers must NOT include the following: + + <quote> + &s.code;"xf86Priv.h"&nl; + "xf86Privstr.h"&nl; + "xf86_libc.h"&nl; + "xf86_OSlib.h"&nl; + "Xos.h"&e.code;&nl; + any OS header + </quote> + + +<sect1>Data structures and initialisation +<p> + +<itemize> + <item>The following macros should be defined: + <code> +#define VERSION <version-as-an-int> +#define ZZZ_NAME "ZZZ" /* the name used to prefix messages */ +#define ZZZ_DRIVER_NAME "zzz" /* the driver name as used in config file */ +#define ZZZ_MAJOR_VERSION <int> +#define ZZZ_MINOR_VERSION <int> +#define ZZZ_PATCHLEVEL <int> + </code> +<p> + NOTE: &s.code;ZZZ_DRIVER_NAME&e.code; should match the name of the + driver module without things like the "lib" prefix, the "_drv" suffix + or filename extensions. +<p> + + <item>A DriverRec must be defined, which includes the functions required + at the pre-probe phase. The name of this DriverRec must be an + upper-case version of ZZZ_DRIVER_NAME (for the purposes of static + linking). +<p> + <code> +DriverRec ZZZ = { + VERSION, + ZZZ_DRIVER_NAME, + ZZZIdentify, + ZZZProbe, + ZZZAvailableOptions, + NULL, + 0 +}; + </code> + + <item>Define list of supported chips and their matching ID: +<p> + <code> +static SymTabRec ZZZChipsets[] = { + { PCI_CHIP_ZZZ1234, "zzz1234a" }, + { PCI_CHIP_ZZZ5678, "zzz5678a" }, + { -1, NULL } +}; + </code> +<p> + The token field may be any integer value that the driver may use to + uniquely identify the supported chipsets. For drivers that support + only PCI devices using the PCI device IDs might be a natural choice, + but this isn't mandatory. For drivers that support both PCI and other + devices (like ISA), some other ID should probably used. When other + IDs are used as the tokens it is recommended that the names be + defined as an &s.code;enum&e.code; type. +<p> + <item>If the driver uses the &s.code;xf86MatchPciInstances(&e.code;) + helper (recommended for drivers that support PCI cards) a list that + maps PCI IDs to chip IDs and fixed resources must be defined: +<p> + <code> +static PciChipsets ZZZPciChipsets[] = { + { PCI_CHIP_ZZZ1234, PCI_CHIP_ZZZ1234, RES_SHARED_VGA }, + { PCI_CHIP_ZZZ5678, PCI_CHIP_ZZZ5678, RES_SHARED_VGA }, + { -1, -1, RES_UNDEFINED } +} + </code> +<p> + <item>Define the &s.code;XF86ModuleVersionInfo&e.code; struct for the + driver. This is required for the dynamically loaded version: +<p> + <code> +static XF86ModuleVersionInfo zzzVersRec = +{ + "zzz", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + ZZZ_MAJOR_VERSION, ZZZ_MINOR_VERSION, ZZZ_PATCHLEVEL, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_VIDEODRV, + {0,0,0,0} +}; + </code> +<p> + <item>Define a data structure to hold the driver's screen-specific data. + This must be used instead of global variables. This would be defined + in the &s.code;"zzz.h"&e.code; file, something like: +<p> + <code> +typedef struct { + type1 field1; + type2 field2; + int fooHack; + Bool pciRetry; + Bool noAccel; + Bool hwCursor; + CloseScreenProcPtr CloseScreen; + OptionInfoPtr Options; + ... +} ZZZRec, *ZZZPtr; + </code> +<p> + <item>Define the list of config file Options that the driver accepts. For + consistency between drivers those in the list of ``standard'' options + should be used where appropriate before inventing new options. +<p> + <code> +typedef enum { + OPTION_FOO_HACK, + OPTION_PCI_RETRY, + OPTION_HW_CURSOR, + OPTION_NOACCEL +} ZZZOpts; + +static const OptionInfoRec ZZZOptions[] = { + { OPTION_FOO_HACK, "FooHack", OPTV_INTEGER, {0}, FALSE }, + { OPTION_PCI_RETRY, "PciRetry", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + </code> +<p> +</itemize> + +<sect1>Functions +<p> + + +<sect2>SetupProc +<p> + + For dynamically loaded modules, a &s.code;ModuleData&e.code; + variable is required. It is should be the name of the driver + prepended to "ModuleData". A &s.code;Setup()&e.code; function is + also required, which calls &s.code;xf86AddDriver()&e.code; to add + the driver to the main list of drivers. + + <code> +static MODULESETUPPROTO(zzzSetup); + +XF86ModuleData zzzModuleData = { &zzzVersRec, zzzSetup, NULL }; + +static pointer +zzzSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + + /* This module should be loaded only once, but check to be sure. */ + + if (!setupDone) { + /* + * Modules that this driver always requires may be loaded + * here by calling LoadSubModule(). + */ + + setupDone = TRUE; + xf86AddDriver(&MGA, module, 0); + + /* + * The return value must be non-NULL on success even though + * there is no TearDownProc. + */ + return (pointer)1; + } else { + if (errmaj) *errmaj = LDR_ONCEONLY; + return NULL; + } +} + </code> + +<sect2>GetRec, FreeRec +<p> + + A function is usually required to allocate the driver's + screen-specific data structure and hook it into the + &s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; field. + The &s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; is + initialised to &s.code;NULL&e.code;, so it is easy to check if the + initialisation has already been done. After allocating it, initialise + the fields. By using &s.code;xnfcalloc()&e.code; to do the allocation + it is zeroed, and if the allocation fails the server exits. +<p> + NOTE: + When allocating structures from inside the driver which are defined + on the common level it is important to initialize the structure to + zero. + Only this guarantees that the server remains source compatible to + future changes in common level structures. + + <code> +static Bool +ZZZGetRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate != NULL) + return TRUE; + pScrn->driverPrivate = xnfcalloc(sizeof(ZZZRec), 1); + /* Initialise as required */ + ... + return TRUE; +} + </code> + + Define a macro in &s.code;"zzz.h"&e.code; which gets a pointer to + the &s.code;ZZZRec&e.code; when given &s.code;pScrn&e.code;: + + <code> +#define ZZZPTR(p) ((ZZZPtr)((p)->driverPrivate)) + </code> + + Define a function to free the above, setting it to &s.code;NULL&e.code; + once it has been freed: + + <code> +static void +ZZZFreeRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate == NULL) + return; + xfree(pScrn->driverPrivate); + pScrn->driverPrivate = NULL; +} + </code> + +<sect2>Identify +<p> + + Define the &s.code;Identify()&e.code; function. It is run before + the Probe, and typically prints out an identifying message, which + might include the chipsets it supports. This function is mandatory: + + <code> +static void +ZZZIdentify(int flags) +{ + xf86PrintChipsets(ZZZ_NAME, "driver for ZZZ Tech chipsets", + ZZZChipsets); +} + </code> + +<sect2>Probe +<p> + + Define the &s.code;Probe()&e.code; function. The purpose of this + is to find all instances of the hardware that the driver supports, + and for the ones not already claimed by another driver, claim the + slot, and allocate a &s.code;ScrnInfoRec&e.code;. This should be + a minimal probe, and it should under no circumstances leave the + state of the hardware changed. Because a device is found, don't + assume that it will be used. Don't do any initialisations other + than the required &s.code;ScrnInfoRec&e.code; initialisations. + Don't allocate any new data structures. + + This function is mandatory. + + NOTE: The &s.code;xf86DrvMsg()&e.code; functions cannot be used from + the Probe. + + <code> +static Bool +ZZZProbe(DriverPtr drv, int flags) +{ + Bool foundScreen = FALSE; + int numDevSections, numUsed; + GDevPtr *devSections; + int *usedChips; + int i; + + /* + * Find the config file Device sections that match this + * driver, and return if there are none. + */ + if ((numDevSections = xf86MatchDevice(ZZZ_DRIVER_NAME, + &devSections)) <= 0) { + return FALSE; + } + + /* + * Since this is a PCI card, "probing" just amounts to checking + * the PCI data that the server has already collected. If there + * is none, return. + * + * Although the config file is allowed to override things, it + * is reasonable to not allow it to override the detection + * of no PCI video cards. + * + * The provided xf86MatchPciInstances() helper takes care of + * the details. + */ + /* test if PCI bus present */ + if (xf86GetPciVideoInfo()) { + + numUsed = xf86MatchPciInstances(ZZZ_NAME, PCI_VENDOR_ZZZ, + ZZZChipsets, ZZZPciChipsets, devSections, + numDevSections, drv, &usedChips); + + for (i = 0; i < numUsed; i++) { + ScrnInfoPtr pScrn = NULL; + if ((pScrn = xf86ConfigPciEntity(pScrn, flags, usedChips[i], + ZZZPciChipsets, NULL, NULL, + NULL, NULL, NULL))) { + /* Allocate a ScrnInfoRec */ + pScrn->driverVersion = VERSION; + pScrn->driverName = ZZZ_DRIVER_NAME; + pScrn->name = ZZZ_NAME; + pScrn->Probe = ZZZProbe; + pScrn->PreInit = ZZZPreInit; + pScrn->ScreenInit = ZZZScreenInit; + pScrn->SwitchMode = ZZZSwitchMode; + pScrn->AdjustFrame = ZZZAdjustFrame; + pScrn->EnterVT = ZZZEnterVT; + pScrn->LeaveVT = ZZZLeaveVT; + pScrn->FreeScreen = ZZZFreeScreen; + pScrn->ValidMode = ZZZValidMode; + foundScreen = TRUE; + /* add screen to entity */ + } + } + xfree(usedChips); + } + +#ifdef HAS_ISA_DEVS + /* + * If the driver supports ISA hardware, the following block + * can be included too. + */ + numUsed = xf86MatchIsaInstances(ZZZ_NAME, ZZZChipsets, + ZZZIsaChipsets, drv, ZZZFindIsaDevice, + devSections, numDevSections, &usedChips); + for (i = 0; i < numUsed; i++) { + ScrnInfoPtr pScrn = NULL; + if ((pScrn = xf86ConfigIsaEntity(pScrn, flags, usedChips[i], + ZZZIsaChipsets, NULL, NULL, NULL, + NULL, NULL))) { + pScrn->driverVersion = VERSION; + pScrn->driverName = ZZZ_DRIVER_NAME; + pScrn->name = ZZZ_NAME; + pScrn->Probe = ZZZProbe; + pScrn->PreInit = ZZZPreInit; + pScrn->ScreenInit = ZZZScreenInit; + pScrn->SwitchMode = ZZZSwitchMode; + pScrn->AdjustFrame = ZZZAdjustFrame; + pScrn->EnterVT = ZZZEnterVT; + pScrn->LeaveVT = ZZZLeaveVT; + pScrn->FreeScreen = ZZZFreeScreen; + pScrn->ValidMode = ZZZValidMode; + foundScreen = TRUE; + } + } + xfree(usedChips); +#endif /* HAS_ISA_DEVS */ + + xfree(devSections); + return foundScreen; + </code> + +<sect2>AvailableOptions +<p> + + Define the &s.code;AvailableOptions()&e.code; function. The purpose + of this is to return the available driver options back to the + -configure option, so that an xorg.conf file can be built and the + user can see which options are available for them to use. + +<sect2>PreInit +<p> + + Define the &s.code;PreInit()&e.code; function. The purpose of + this is to find all the information required to determine if the + configuration is usable, and to initialise those parts of the + &s.code;ScrnInfoRec&e.code; that can be set once at the beginning + of the first server generation. The information should be found in + the least intrusive way possible. + + This function is mandatory. + + NOTES: + <enum> + <item>The &s.code;PreInit()&e.code; function is only called once + during the life of the X server (at the start of the first + generation). + + <item>Data allocated here must be of the type that persists for + the life of the X server. This means that data that hooks into + the &s.code;ScrnInfoRec&e.code;'s &s.code;privates&e.code; + field should be allocated here, but data that hooks into the + &s.code;ScreenRec&e.code;'s &s.code;devPrivates&e.code; field + should not be allocated here. The &s.code;driverPrivate&e.code; + field should also be allocated here. + + <item>Although the &s.code;ScrnInfoRec&e.code; has been allocated + before this function is called, the &s.code;ScreenRec&e.code; + has not been allocated. That means that things requiring it + cannot be used in this function. + + <item>Very little of the &s.code;ScrnInfoRec&e.code; has been + initialised when this function is called. It is important to + get the order of doing things right in this function. + + </enum> + + <code> +static Bool +ZZZPreInit(ScrnInfoPtr pScrn, int flags) +{ + /* Fill in the monitor field */ + pScrn->monitor = pScrn->confScreen->monitor; + + /* + * If using the vgahw module, it will typically be loaded + * here by calling xf86LoadSubModule(pScrn, "vgahw"); + */ + + /* + * Set the depth/bpp. Use the globally preferred depth/bpp. If the + * driver has special default depth/bpp requirements, the defaults should + * be specified here explicitly. + * We support both 24bpp and 32bpp framebuffer layouts. + * This sets pScrn->display also. + */ + if (!xf86SetDepthBpp(pScrn, 0, 0, 0, + Support24bppFb | Support32bppFb)) { + return FALSE; + } else { + if (depth/bpp isn't one we support) { + print error message; + return FALSE; + } + } + /* Print out the depth/bpp that was set */ + xf86PrintDepthBpp(pScrn); + + /* Set bits per RGB for 8bpp */ + if (pScrn->depth <= 8) { + /* Take into account a dac_6_bit option here */ + pScrn->rgbBits = 6 or 8; + } + + /* + * xf86SetWeight() and xf86SetDefaultVisual() must be called + * after pScrn->display is initialised. + */ + + /* Set weight/mask/offset for depth > 8 */ + if (pScrn->depth > 8) { + if (!xf86SetWeight(pScrn, defaultWeight, defaultMask)) { + return FALSE; + } else { + if (weight isn't one we support) { + print error message; + return FALSE; + } + } + } + + /* Set the default visual. */ + if (!xf86SetDefaultVisual(pScrn, -1)) { + return FALSE; + } else { + if (visual isn't one we support) { + print error message; + return FALSE; + } + } + + /* If the driver supports gamma correction, set the gamma. */ + if (!xf86SetGamma(pScrn, default_gamma)) { + return FALSE; + } + + /* This driver uses a programmable clock */ + pScrn->progClock = TRUE; + + /* Allocate the ZZZRec driverPrivate */ + if (!ZZZGetRec(pScrn)) { + return FALSE; + } + + pZzz = ZZZPTR(pScrn); + + /* Collect all of the option flags (fill in pScrn->options) */ + xf86CollectOptions(pScrn, NULL); + + /* + * Process the options based on the information in ZZZOptions. + * The results are written to pZzz->Options. If all of the options + * processing is done within this function a local variable "options" + * can be used instead of pZzz->Options. + */ + if (!(pZzz->Options = xalloc(sizeof(ZZZOptions)))) + return FALSE; + (void)memcpy(pZzz->Options, ZZZOptions, sizeof(ZZZOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pZzz->Options); + + /* + * Set various fields of ScrnInfoRec and/or ZZZRec based on + * the options found. + */ + from = X_DEFAULT; + pZzz->hwCursor = FALSE; + if (xf86IsOptionSet(pZzz->Options, OPTION_HW_CURSOR)) { + from = X_CONFIG; + pZzz->hwCursor = TRUE; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", + pZzz->hwCursor ? "HW" : "SW"); + if (xf86IsOptionSet(pZzz->Options, OPTION_NOACCEL)) { + pZzz->noAccel = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Acceleration disabled\n"); + } else { + pZzz->noAccel = FALSE; + } + if (xf86IsOptionSet(pZzz->Options, OPTION_PCI_RETRY)) { + pZzz->UsePCIRetry = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n"); + } + pZzz->fooHack = 0; + if (xf86GetOptValInteger(pZzz->Options, OPTION_FOO_HACK, + &pZzz->fooHack)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Foo Hack set to %d\n", + pZzz->fooHack); + } + + /* + * Find the PCI slot(s) that this screen claimed in the probe. + * In this case, exactly one is expected, so complain otherwise. + * Note in this case we're not interested in the card types so + * that parameter is set to NULL. + */ + if ((i = xf86GetPciInfoForScreen(pScrn->scrnIndex, &pciList, NULL)) + != 1) { + print error message; + ZZZFreeRec(pScrn); + if (i > 0) + xfree(pciList); + return FALSE; + } + /* Note that pciList should be freed below when no longer needed */ + + /* + * Determine the chipset, allowing config file chipset and + * chipid values to override the probed information. The config + * chipset value has precedence over its chipid value if both + * are present. + * + * It isn't necessary to fill in pScrn->chipset if the driver + * keeps track of the chipset in its ZZZRec. + */ + + ... + + /* + * Determine video memory, fb base address, I/O addresses, etc, + * allowing the config file to override probed values. + * + * Set the appropriate pScrn fields (videoRam is probably the + * most important one that other code might require), and + * print out the settings. + */ + + ... + + /* Initialise a clockRanges list. */ + + ... + + /* Set any other chipset specific things in the ZZZRec */ + + ... + + /* Select valid modes from those available */ + + i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, + pScrn->display->modes, clockRanges, + NULL, minPitch, maxPitch, rounding, + minHeight, maxHeight, + pScrn->display->virtualX, + pScrn->display->virtualY, + pScrn->videoRam * 1024, + LOOKUP_BEST_REFRESH); + if (i == -1) { + ZZZFreeRec(pScrn); + return FALSE; + } + + /* Prune the modes marked as invalid */ + + xf86PruneDriverModes(pScrn); + + /* If no valid modes, return */ + + if (i == 0 || pScrn->modes == NULL) { + print error message; + ZZZFreeRec(pScrn); + return FALSE; + } + + /* + * Initialise the CRTC fields for the modes. This driver expects + * vertical values to be halved for interlaced modes. + */ + xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); + + /* Set the current mode to the first in the list. */ + pScrn->currentMode = pScrn->modes; + + /* Print the list of modes being used. */ + xf86PrintModes(pScrn); + + /* Set the DPI */ + xf86SetDpi(pScrn, 0, 0); + + /* Load bpp-specific modules */ + switch (pScrn->bitsPerPixel) { + case 1: + mod = "xf1bpp"; + break; + case 4: + mod = "xf4bpp"; + break; + case 8: + mod = "cfb"; + break; + case 16: + mod = "cfb16"; + break; + case 24: + mod = "cfb24"; + break; + case 32: + mod = "cfb32"; + break; + } + if (mod && !xf86LoadSubModule(pScrn, mod)) + ZZZFreeRec(pScrn); + return FALSE; + + /* Load XAA if needed */ + if (!pZzz->noAccel || pZzz->hwCursor) + if (!xf86LoadSubModule(pScrn, "xaa")) { + ZZZFreeRec(pScrn); + return FALSE; + } + + /* Done */ + return TRUE; +} + </code> + +<sect2>MapMem, UnmapMem +<p> + + Define functions to map and unmap the video memory and any other + memory apertures required. These functions are not mandatory, but + it is often useful to have such functions. + + <code> +static Bool +ZZZMapMem(ScrnInfoPtr pScrn) +{ + /* Call xf86MapPciMem() to map each PCI memory area */ + ... + return TRUE or FALSE; +} + +static Bool +ZZZUnmapMem(ScrnInfoPtr pScrn) +{ + /* Call xf86UnMapVidMem() to unmap each memory area */ + ... + return TRUE or FALSE; +} + </code> + +<sect2>Save, Restore +<p> + + Define functions to save and restore the original video state. These + functions are not mandatory, but are often useful. + + <code> +static void +ZZZSave(ScrnInfoPtr pScrn) +{ + /* + * Save state into per-screen data structures. + * If using the vgahw module, vgaHWSave will typically be + * called here. + */ + ... +} + +static void +ZZZRestore(ScrnInfoPtr pScrn) +{ + /* + * Restore state from per-screen data structures. + * If using the vgahw module, vgaHWRestore will typically be + * called here. + */ + ... +} + </code> + +<sect2>ModeInit +<p> + + Define a function to initialise a new video mode. This function isn't + mandatory, but is often useful. + + <code> +static Bool +ZZZModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + /* + * Program a video mode. If using the vgahw module, + * vgaHWInit and vgaRestore will typically be called here. + * Once up to the point where there can't be a failure + * set pScrn->vtSema to TRUE. + */ + ... +} + </code> + +<sect2>ScreenInit +<p> + + Define the &s.code;ScreenInit()&e.code; function. This is called + at the start of each server generation, and should fill in as much + of the &s.code;ScreenRec&e.code; as possible as well as any other + data that is initialised once per generation. It should initialise + the framebuffer layers it is using, and initialise the initial video + mode. + + This function is mandatory. + + NOTE: The &s.code;ScreenRec&e.code; (&s.code;pScreen&e.code;) is + passed to this driver, but it and the + &s.code;ScrnInfoRecs&e.code; are not yet hooked into each + other. This means that in this function, and functions it + calls, one cannot be found from the other. + + <code> +static Bool +ZZZScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) +{ + /* Get the ScrnInfoRec */ + pScrn = xf86Screens[pScreen->myNum]; + + /* + * If using the vgahw module, its data structures and related + * things are typically initialised/mapped here. + */ + + /* Save the current video state */ + ZZZSave(pScrn); + + /* Initialise the first mode */ + ZZZModeInit(pScrn, pScrn->currentMode); + + /* Set the viewport if supported */ + + ZZZAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + /* + * Setup the screen's visuals, and initialise the framebuffer + * code. + */ + + /* Reset the visual list */ + miClearVisualTypes(); + + /* + * Setup the visuals supported. This driver only supports + * TrueColor for bpp > 8, so the default set of visuals isn't + * acceptable. To deal with this, call miSetVisualTypes with + * the appropriate visual mask. + */ + + if (pScrn->bitsPerPixel > 8) { + if (!miSetVisualTypes(pScrn->depth, TrueColorMask, + pScrn->rgbBits, pScrn->defaultVisual)) + return FALSE; + } else { + if (!miSetVisualTypes(pScrn->depth, + miGetDefaultVisualMask(pScrn->depth), + pScrn->rgbBits, pScrn->defaultVisual)) + return FALSE; + } + + /* + * Initialise the framebuffer. + */ + + switch (pScrn->bitsPerPixel) { + case 1: + ret = xf1bppScreenInit(pScreen, FbBase, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth); + break; + case 4: + ret = xf4bppScreenInit(pScreen, FbBase, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth); + break; + case 8: + ret = cfbScreenInit(pScreen, FbBase, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth); + break; + case 16: + ret = cfb16ScreenInit(pScreen, FbBase, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth); + break; + case 24: + ret = cfb24ScreenInit(pScreen, FbBase, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth); + break; + case 32: + ret = cfb32ScreenInit(pScreen, FbBase, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth); + break; + default: + print a message about an internal error; + ret = FALSE; + break; + } + + if (!ret) + return FALSE; + + /* Override the default mask/offset settings */ + if (pScrn->bitsPerPixel > 8) { + for (i = 0, visual = pScreen->visuals; + i < pScreen->numVisuals; i++, visual++) { + if ((visual->class | DynamicClass) == DirectColor) { + visual->offsetRed = pScrn->offset.red; + visual->offsetGreen = pScrn->offset.green; + visual->offsetBlue = pScrn->offset.blue; + visual->redMask = pScrn->mask.red; + visual->greenMask = pScrn->mask.green; + visual->blueMask = pScrn->mask.blue; + } + } + } + + /* + * If banking is needed, initialise an miBankInfoRec (defined in + * "mibank.h"), and call miInitializeBanking(). + */ + if (!miInitializeBanking(pScreen, pScrn->virtualX, pScrn->virtualY, + pScrn->displayWidth, pBankInfo)) + return FALSE; + + /* + * If backing store is to be supported (as is usually the case), + * initialise it. + */ + miInitializeBackingStore(pScreen); + + /* + * Set initial black & white colourmap indices. + */ + xf86SetBlackWhitePixels(pScreen); + + /* + * Install colourmap functions. If using the vgahw module, + * vgaHandleColormaps would usually be called here. + */ + + ... + + /* + * Initialise cursor functions. This example is for the mi + * software cursor. + */ + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + + /* Initialise the default colourmap */ + switch (pScrn->depth) { + case 1: + if (!xf1bppCreateDefColormap(pScreen)) + return FALSE; + break; + case 4: + if (!xf4bppCreateDefColormap(pScreen)) + return FALSE; + break; + default: + if (!cfbCreateDefColormap(pScreen)) + return FALSE; + break; + } + + /* + * Wrap the CloseScreen vector and set SaveScreen. + */ + ZZZPTR(pScrn)->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = ZZZCloseScreen; + pScreen->SaveScreen = ZZZSaveScreen; + + /* Report any unused options (only for the first generation) */ + if (serverGeneration == 1) { + xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); + } + + /* Done */ + return TRUE; +} + </code> + + +<sect2>SwitchMode +<p> + + Define the &s.code;SwitchMode()&e.code; function if mode switching + is supported by the driver. + + <code> +static Bool +ZZZSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +{ + return ZZZModeInit(xf86Screens[scrnIndex], mode); +} + </code> + + +<sect2>AdjustFrame +<p> + + Define the &s.code;AdjustFrame()&e.code; function if the driver + supports this. + + <code> +static void +ZZZAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + /* Adjust the viewport */ +} + </code> + + +<sect2>EnterVT, LeaveVT +<p> + + Define the &s.code;EnterVT()&e.code; and &s.code;LeaveVT()&e.code; + functions. + + These functions are mandatory. + + <code> +static Bool +ZZZEnterVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + return ZZZModeInit(pScrn, pScrn->currentMode); +} + +static void +ZZZLeaveVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + ZZZRestore(pScrn); +} + </code> + +<sect2>CloseScreen +<p> + + Define the &s.code;CloseScreen()&e.code; function: + + This function is mandatory. Note that it unwraps the previously + wrapped &s.code;pScreen->CloseScreen&e.code;, and finishes by + calling it. + + <code> +static Bool +ZZZCloseScreen(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + if (pScrn->vtSema) { + ZZZRestore(pScrn); + ZZZUnmapMem(pScrn); + } + pScrn->vtSema = FALSE; + pScreen->CloseScreen = ZZZPTR(pScrn)->CloseScreen; + return (*pScreen->CloseScreen)(scrnIndex, pScreen); +} + </code> + +<sect2>SaveScreen +<p> + + Define the &s.code;SaveScreen()&e.code; function (the screen + blanking function). When using the vgahw module, this will typically + be: + + <code> +static Bool +ZZZSaveScreen(ScreenPtr pScreen, int mode) +{ + return vgaHWSaveScreen(pScreen, mode); +} + </code> + + This function is mandatory. Before modifying any hardware register + directly this function needs to make sure that the Xserver is active + by checking if &s.code;pScrn&e.code; is non-NULL and for + &s.code;pScrn->vtSema == TRUE&e.code;. + +<sect2>FreeScreen +<p> + + Define the &s.code;FreeScreen()&e.code; function. This function + is optional. It should be defined if the &s.code;ScrnInfoRec&e.code; + &s.code;driverPrivate&e.code; field is used so that it can be freed + when a screen is deleted by the common layer for reasons possibly + beyond the driver's control. This function is not used in during + normal (error free) operation. The per-generation data is freed by + the &s.code;CloseScreen()&e.code; function. + + <code> +static void +ZZZFreeScreen(int scrnIndex, int flags) +{ + /* + * If the vgahw module is used vgaHWFreeHWRec() would be called + * here. + */ + ZZZFreeRec(xf86Screens[scrnIndex]); +} + </code> + + +</article> diff --git a/xorg-server/hw/xfree86/dri2/dri2ext.c b/xorg-server/hw/xfree86/dri2/dri2ext.c index 38efc86e0..adbc9647b 100644 --- a/xorg-server/hw/xfree86/dri2/dri2ext.c +++ b/xorg-server/hw/xfree86/dri2/dri2ext.c @@ -160,11 +160,7 @@ DRI2InvalidateBuffersEvent(DrawablePtr pDraw, void *priv) xDRI2InvalidateBuffers event; ClientPtr client = priv; - if (client->clientGone) - return; - event.type = DRI2EventBase + DRI2_InvalidateBuffers; - event.sequenceNumber = client->sequence; event.drawable = pDraw->id; WriteEventsToClient(client, 1, (xEvent *)&event); @@ -366,7 +362,6 @@ DRI2SwapEvent(ClientPtr client, void *data, int type, CARD64 ust, CARD64 msc, DrawablePtr pDrawable = data; event.type = DRI2EventBase + DRI2_BufferSwapComplete; - event.sequenceNumber = client->sequence; event.event_type = type; event.drawable = pDrawable->id; event.ust_hi = (CARD64)ust >> 32; diff --git a/xorg-server/hw/xquartz/applewm.c b/xorg-server/hw/xquartz/applewm.c index b0f811750..64851e791 100644 --- a/xorg-server/hw/xquartz/applewm.c +++ b/xorg-server/hw/xquartz/applewm.c @@ -341,7 +341,6 @@ ProcAppleWMSelectInput (register ClientPtr client) void AppleWMSendEvent (int type, unsigned int mask, int which, int arg) { WMEventPtr *pHead, pEvent; - ClientPtr client; xAppleWMNotifyEvent se; int i; @@ -349,18 +348,13 @@ AppleWMSendEvent (int type, unsigned int mask, int which, int arg) { if (i != Success || !pHead) return; for (pEvent = *pHead; pEvent; pEvent = pEvent->next) { - client = pEvent->client; - if ((pEvent->mask & mask) == 0 - || client == serverClient || client->clientGone) - { + if ((pEvent->mask & mask) == 0) continue; - } se.type = type + WMEventBase; se.kind = which; se.arg = arg; - se.sequenceNumber = client->sequence; se.time = currentTime.milliseconds; - WriteEventsToClient (client, 1, (xEvent *) &se); + WriteEventsToClient (pEvent->client, 1, (xEvent *) &se); } } diff --git a/xorg-server/hw/xquartz/xpr/appledri.c b/xorg-server/hw/xquartz/xpr/appledri.c index 87cb9016a..1fceb525c 100644 --- a/xorg-server/hw/xquartz/xpr/appledri.c +++ b/xorg-server/hw/xquartz/xpr/appledri.c @@ -192,22 +192,16 @@ static void surface_notify( { DRISurfaceNotifyArg *arg = _arg; int client_index = (int) x_cvt_vptr_to_uint(data); - ClientPtr client; xAppleDRINotifyEvent se; if (client_index < 0 || client_index >= currentMaxClients) return; - client = clients[client_index]; - if (client == NULL || client == serverClient || client->clientGone) - return; - se.type = DRIEventBase + AppleDRISurfaceNotify; se.kind = arg->kind; se.arg = arg->id; - se.sequenceNumber = client->sequence; se.time = currentTime.milliseconds; - WriteEventsToClient (client, 1, (xEvent *) &se); + WriteEventsToClient (clients[client_index], 1, (xEvent *) &se); } static int diff --git a/xorg-server/hw/xwin/winconfig.c b/xorg-server/hw/xwin/winconfig.c index c972bbcad..d09173197 100644 --- a/xorg-server/hw/xwin/winconfig.c +++ b/xorg-server/hw/xwin/winconfig.c @@ -673,6 +673,18 @@ winSetRealOption (pointer optlist, const char *name, double deflt) deflt = o.value.realnum; return deflt; } + +double +winSetPercentOption (pointer optlist, const char *name, double deflt) +{ + OptionInfoRec o; + + o.name = name; + o.type = OPTV_PERCENT; + if (ParseOptionValue (-1, optlist, &o)) + deflt = o.value.realnum; + return deflt; +} #endif @@ -851,6 +863,31 @@ ParseOptionValue (int scrnIndex, pointer options, OptionInfoPtr p) p->found = FALSE; } break; + case OPTV_PERCENT: + if (*s == '\0') + { + winDrvMsg (scrnIndex, X_WARNING, + "Option \"%s\" requires a percent value\n", + p->name); + p->found = FALSE; + } + else + { + double percent = strtod (s, &end); + + if (end != s && winNameCompare (end, "%")) + { + p->found = TRUE; + p->value.realnum = percent; + } + else + { + winDrvMsg (scrnIndex, X_WARNING, + "Option \"%s\" requires a frequency value\n", + p->name); + p->found = FALSE; + } + } case OPTV_FREQ: if (*s == '\0') { diff --git a/xorg-server/hw/xwin/winconfig.h b/xorg-server/hw/xwin/winconfig.h index 058884abc..7f533cff0 100644 --- a/xorg-server/hw/xwin/winconfig.h +++ b/xorg-server/hw/xwin/winconfig.h @@ -1,322 +1,324 @@ -#ifndef __WIN_CONFIG_H__ -#define __WIN_CONFIG_H__ -/* - *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. - * - *Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - *"Software"), to deal in the Software without restriction, including - *without limitation the rights to use, copy, modify, merge, publish, - *distribute, sublicense, and/or sell copies of the Software, and to - *permit persons to whom the Software is furnished to do so, subject to - *the following conditions: - * - *The above copyright notice and this permission notice shall be - *included in all copies or substantial portions of the Software. - * - *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR - *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - *Except as contained in this notice, the name of the XFree86 Project - *shall not be used in advertising or otherwise to promote the sale, use - *or other dealings in this Software without prior written authorization - *from the XFree86 Project. - * - * Authors: Alexander Gottwald - */ - -#include "win.h" -#ifdef XWIN_XF86CONFIG -#include "../xfree86/parser/xf86Parser.h" -#endif - - -/* These are taken from hw/xfree86/common/xf86str.h */ - -typedef struct -{ - CARD32 red, green, blue; -} -rgb; - - -typedef struct -{ - float red, green, blue; -} -Gamma; - - -typedef struct -{ - char *identifier; - char *vendor; - char *board; - char *chipset; - char *ramdac; - char *driver; - struct _confscreenrec *myScreenSection; - Bool claimed; - Bool active; - Bool inUse; - int videoRam; - int textClockFreq; - pointer options; - int screen; /* For multi-CRTC cards */ -} -GDevRec, *GDevPtr; - - -typedef struct -{ - char *identifier; - char *driver; - pointer commonOptions; - pointer extraOptions; -} -IDevRec, *IDevPtr; - - -typedef struct -{ - int frameX0; - int frameY0; - int virtualX; - int virtualY; - int depth; - int fbbpp; - rgb weight; - rgb blackColour; - rgb whiteColour; - int defaultVisual; - char **modes; - pointer options; -} -DispRec, *DispPtr; - - -typedef struct _confxvportrec -{ - char *identifier; - pointer options; -} -confXvPortRec, *confXvPortPtr; - - -typedef struct _confxvadaptrec -{ - char *identifier; - int numports; - confXvPortPtr ports; - pointer options; -} -confXvAdaptorRec, *confXvAdaptorPtr; - - -typedef struct _confscreenrec -{ - char *id; - int screennum; - int defaultdepth; - int defaultbpp; - int defaultfbbpp; - GDevPtr device; - int numdisplays; - DispPtr displays; - int numxvadaptors; - confXvAdaptorPtr xvadaptors; - pointer options; -} -confScreenRec, *confScreenPtr; - - -typedef enum -{ - PosObsolete = -1, - PosAbsolute = 0, - PosRightOf, - PosLeftOf, - PosAbove, - PosBelow, - PosRelative -} -PositionType; - - -typedef struct _screenlayoutrec -{ - confScreenPtr screen; - char *topname; - confScreenPtr top; - char *bottomname; - confScreenPtr bottom; - char *leftname; - confScreenPtr left; - char *rightname; - confScreenPtr right; - PositionType where; - int x; - int y; - char *refname; - confScreenPtr refscreen; -} -screenLayoutRec, *screenLayoutPtr; - - -typedef struct _serverlayoutrec -{ - char *id; - screenLayoutPtr screens; - GDevPtr inactives; - IDevPtr inputs; - pointer options; -} -serverLayoutRec, *serverLayoutPtr; - - -/* - * winconfig.c - */ - -typedef struct -{ - /* Files */ -#ifdef XWIN_XF86CONFIG - char *configFile; - char *configDir; -#endif - char *fontPath; - /* input devices - keyboard */ -#ifdef XWIN_XF86CONFIG - char *keyboard; -#endif - char *xkbRules; - char *xkbModel; - char *xkbLayout; - char *xkbVariant; - char *xkbOptions; - /* layout */ - char *screenname; - /* mouse settings */ - char *mouse; - Bool emulate3buttons; - long emulate3timeout; -} -WinCmdlineRec, *WinCmdlinePtr; - - -extern WinCmdlineRec g_cmdline; -#ifdef XWIN_XF86CONFIG -extern XF86ConfigPtr g_xf86configptr; -#endif -extern serverLayoutRec g_winConfigLayout; - - -/* - * Function prototypes - */ - -Bool winReadConfigfile (void); -Bool winConfigFiles (void); -Bool winConfigOptions (void); -Bool winConfigScreens (void); -Bool winConfigKeyboard (DeviceIntPtr pDevice); -Bool winConfigMouse (DeviceIntPtr pDevice); - - -typedef struct -{ - double freq; - int units; -} -OptFrequency; - - -typedef union -{ - unsigned long num; - char *str; - double realnum; - Bool bool; - OptFrequency freq; -} -ValueUnion; - - -typedef enum -{ - OPTV_NONE = 0, - OPTV_INTEGER, - OPTV_STRING, /* a non-empty string */ - OPTV_ANYSTR, /* Any string, including an empty one */ - OPTV_REAL, - OPTV_BOOLEAN, - OPTV_FREQ -} -OptionValueType; - - -typedef enum -{ - OPTUNITS_HZ = 1, - OPTUNITS_KHZ, - OPTUNITS_MHZ -} -OptFreqUnits; - - -typedef struct -{ - int token; - const char *name; - OptionValueType type; - ValueUnion value; - Bool found; -} -OptionInfoRec, *OptionInfoPtr; - - -/* - * Function prototypes - */ - -char *winSetStrOption (pointer optlist, const char *name, char *deflt); -int winSetBoolOption (pointer optlist, const char *name, int deflt); -int winSetIntOption (pointer optlist, const char *name, int deflt); -double winSetRealOption (pointer optlist, const char *name, double deflt); -#ifdef XWIN_XF86CONFIG -XF86OptionPtr winFindOption (XF86OptionPtr list, const char *name); -char *winFindOptionValue (XF86OptionPtr list, const char *name); -#endif -int winNameCompare (const char *s1, const char *s2); -char *winNormalizeName (const char *s); - - -typedef struct -{ - struct - { - long leds; - long delay; - long rate; - } - keyboard; - XkbRMLVOSet xkb; - struct - { - Bool emulate3Buttons; - long emulate3Timeout; - } - pointer; -} -winInfoRec, *winInfoPtr; - - -extern winInfoRec g_winInfo; - -#endif +#ifndef __WIN_CONFIG_H__ +#define __WIN_CONFIG_H__ +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *The above copyright notice and this permission notice shall be + *included in all copies or substantial portions of the Software. + * + *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR + *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + *Except as contained in this notice, the name of the XFree86 Project + *shall not be used in advertising or otherwise to promote the sale, use + *or other dealings in this Software without prior written authorization + *from the XFree86 Project. + * + * Authors: Alexander Gottwald + */ + +#include "win.h" +#ifdef XWIN_XF86CONFIG +#include "../xfree86/parser/xf86Parser.h" +#endif + + +/* These are taken from hw/xfree86/common/xf86str.h */ + +typedef struct +{ + CARD32 red, green, blue; +} +rgb; + + +typedef struct +{ + float red, green, blue; +} +Gamma; + + +typedef struct +{ + char *identifier; + char *vendor; + char *board; + char *chipset; + char *ramdac; + char *driver; + struct _confscreenrec *myScreenSection; + Bool claimed; + Bool active; + Bool inUse; + int videoRam; + int textClockFreq; + pointer options; + int screen; /* For multi-CRTC cards */ +} +GDevRec, *GDevPtr; + + +typedef struct +{ + char *identifier; + char *driver; + pointer commonOptions; + pointer extraOptions; +} +IDevRec, *IDevPtr; + + +typedef struct +{ + int frameX0; + int frameY0; + int virtualX; + int virtualY; + int depth; + int fbbpp; + rgb weight; + rgb blackColour; + rgb whiteColour; + int defaultVisual; + char **modes; + pointer options; +} +DispRec, *DispPtr; + + +typedef struct _confxvportrec +{ + char *identifier; + pointer options; +} +confXvPortRec, *confXvPortPtr; + + +typedef struct _confxvadaptrec +{ + char *identifier; + int numports; + confXvPortPtr ports; + pointer options; +} +confXvAdaptorRec, *confXvAdaptorPtr; + + +typedef struct _confscreenrec +{ + char *id; + int screennum; + int defaultdepth; + int defaultbpp; + int defaultfbbpp; + GDevPtr device; + int numdisplays; + DispPtr displays; + int numxvadaptors; + confXvAdaptorPtr xvadaptors; + pointer options; +} +confScreenRec, *confScreenPtr; + + +typedef enum +{ + PosObsolete = -1, + PosAbsolute = 0, + PosRightOf, + PosLeftOf, + PosAbove, + PosBelow, + PosRelative +} +PositionType; + + +typedef struct _screenlayoutrec +{ + confScreenPtr screen; + char *topname; + confScreenPtr top; + char *bottomname; + confScreenPtr bottom; + char *leftname; + confScreenPtr left; + char *rightname; + confScreenPtr right; + PositionType where; + int x; + int y; + char *refname; + confScreenPtr refscreen; +} +screenLayoutRec, *screenLayoutPtr; + + +typedef struct _serverlayoutrec +{ + char *id; + screenLayoutPtr screens; + GDevPtr inactives; + IDevPtr inputs; + pointer options; +} +serverLayoutRec, *serverLayoutPtr; + + +/* + * winconfig.c + */ + +typedef struct +{ + /* Files */ +#ifdef XWIN_XF86CONFIG + char *configFile; + char *configDir; +#endif + char *fontPath; + /* input devices - keyboard */ +#ifdef XWIN_XF86CONFIG + char *keyboard; +#endif + char *xkbRules; + char *xkbModel; + char *xkbLayout; + char *xkbVariant; + char *xkbOptions; + /* layout */ + char *screenname; + /* mouse settings */ + char *mouse; + Bool emulate3buttons; + long emulate3timeout; +} +WinCmdlineRec, *WinCmdlinePtr; + + +extern WinCmdlineRec g_cmdline; +#ifdef XWIN_XF86CONFIG +extern XF86ConfigPtr g_xf86configptr; +#endif +extern serverLayoutRec g_winConfigLayout; + + +/* + * Function prototypes + */ + +Bool winReadConfigfile (void); +Bool winConfigFiles (void); +Bool winConfigOptions (void); +Bool winConfigScreens (void); +Bool winConfigKeyboard (DeviceIntPtr pDevice); +Bool winConfigMouse (DeviceIntPtr pDevice); + + +typedef struct +{ + double freq; + int units; +} +OptFrequency; + + +typedef union +{ + unsigned long num; + char *str; + double realnum; + Bool bool; + OptFrequency freq; +} +ValueUnion; + + +typedef enum +{ + OPTV_NONE = 0, + OPTV_INTEGER, + OPTV_STRING, /* a non-empty string */ + OPTV_ANYSTR, /* Any string, including an empty one */ + OPTV_REAL, + OPTV_BOOLEAN, + OPTV_PERCENT, + OPTV_FREQ +} +OptionValueType; + + +typedef enum +{ + OPTUNITS_HZ = 1, + OPTUNITS_KHZ, + OPTUNITS_MHZ +} +OptFreqUnits; + + +typedef struct +{ + int token; + const char *name; + OptionValueType type; + ValueUnion value; + Bool found; +} +OptionInfoRec, *OptionInfoPtr; + + +/* + * Function prototypes + */ + +char *winSetStrOption (pointer optlist, const char *name, char *deflt); +int winSetBoolOption (pointer optlist, const char *name, int deflt); +int winSetIntOption (pointer optlist, const char *name, int deflt); +double winSetRealOption (pointer optlist, const char *name, double deflt); +double winSetPercentOption (pointer optlist, const char *name, double deflt); +#ifdef XWIN_XF86CONFIG +XF86OptionPtr winFindOption (XF86OptionPtr list, const char *name); +char *winFindOptionValue (XF86OptionPtr list, const char *name); +#endif +int winNameCompare (const char *s1, const char *s2); +char *winNormalizeName (const char *s); + + +typedef struct +{ + struct + { + long leds; + long delay; + long rate; + } + keyboard; + XkbRMLVOSet xkb; + struct + { + Bool emulate3Buttons; + long emulate3Timeout; + } + pointer; +} +winInfoRec, *winInfoPtr; + + +extern winInfoRec g_winInfo; + +#endif diff --git a/xorg-server/hw/xwin/winwindowswm.c b/xorg-server/hw/xwin/winwindowswm.c index d8cacdc99..218fddb6a 100644 --- a/xorg-server/hw/xwin/winwindowswm.c +++ b/xorg-server/hw/xwin/winwindowswm.c @@ -304,8 +304,7 @@ winWindowsWMSendEvent (int type, unsigned int mask, int which, int arg, #if CYGMULTIWINDOW_DEBUG ErrorF ("winWindowsWMSendEvent - x%08x\n", (int) client); #endif - if ((pEvent->mask & mask) == 0 - || client == serverClient || client->clientGone) + if ((pEvent->mask & mask) == 0) { continue; } @@ -320,7 +319,6 @@ winWindowsWMSendEvent (int type, unsigned int mask, int which, int arg, se.y = y; se.w = w; se.h = h; - se.sequenceNumber = client->sequence; se.time = currentTime.milliseconds; WriteEventsToClient (client, 1, (xEvent *) &se); } diff --git a/xorg-server/include/inputstr.h b/xorg-server/include/inputstr.h index 6da3f38e4..fa21c7b3a 100644 --- a/xorg-server/include/inputstr.h +++ b/xorg-server/include/inputstr.h @@ -1,599 +1,607 @@ -/************************************************************ - -Copyright 1987, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -********************************************************/ - - -#ifndef INPUTSTRUCT_H -#define INPUTSTRUCT_H - -#include "input.h" -#include "window.h" -#include "dixstruct.h" -#include "cursorstr.h" -#include "geext.h" -#include "privates.h" - -#define BitIsOn(ptr, bit) (((BYTE *) (ptr))[(bit)>>3] & (1 << ((bit) & 7))) -#define SetBit(ptr, bit) (((BYTE *) (ptr))[(bit)>>3] |= (1 << ((bit) & 7))) -#define ClearBit(ptr, bit) (((BYTE *)(ptr))[(bit)>>3] &= ~(1 << ((bit) & 7))) - -#define SameClient(obj,client) \ - (CLIENT_BITS((obj)->resource) == (client)->clientAsMask) - -#define EMASKSIZE MAXDEVICES + 2 - -/* This is the last XI2 event supported by the server. If you add - * events to the protocol, the server will not support these events until - * this number here is bumped. - */ -#define XI2LASTEVENT 17 /* XI_RawMotion */ -#define XI2MASKSIZE ((XI2LASTEVENT + 7)/8) /* no of bits for masks */ - -/** - * This struct stores the core event mask for each client except the client - * that created the window. - * - * Each window that has events selected from other clients has at least one of - * these masks. If multiple clients selected for events on the same window, - * these masks are in a linked list. - * - * The event mask for the client that created the window is stored in - * win->eventMask instead. - * - * The resource id is simply a fake client ID to associate this mask with a - * client. - * - * Kludge: OtherClients and InputClients must be compatible, see code. - */ -typedef struct _OtherClients { - OtherClientsPtr next; /**< Pointer to the next mask */ - XID resource; /**< id for putting into resource manager */ - Mask mask; /**< Core event mask */ -} OtherClients; - -/** - * This struct stores the XI event mask for each client. - * - * Each window that has events selected has at least one of these masks. If - * multiple client selected for events on the same window, these masks are in - * a linked list. - */ -typedef struct _InputClients { - InputClientsPtr next; /**< Pointer to the next mask */ - XID resource; /**< id for putting into resource manager */ - Mask mask[EMASKSIZE]; /**< Actual XI event mask, deviceid is index */ - /** XI2 event masks. One per device, each bit is a mask of (1 << type) */ - unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE]; -} InputClients; - -/** - * Combined XI event masks from all devices. - * - * This is the XI equivalent of the deliverableEvents, eventMask and - * dontPropagate mask of the WindowRec (or WindowOptRec). - * - * A window that has an XI client selecting for events has exactly one - * OtherInputMasks struct and exactly one InputClients struct hanging off - * inputClients. Each further client appends to the inputClients list. - * Each Mask field is per-device, with the device id as the index. - * Exception: for non-device events (Presence events), the MAXDEVICES - * deviceid is used. - */ -typedef struct _OtherInputMasks { - /** - * Bitwise OR of all masks by all clients and the window's parent's masks. - */ - Mask deliverableEvents[EMASKSIZE]; - /** - * Bitwise OR of all masks by all clients on this window. - */ - Mask inputEvents[EMASKSIZE]; - /** The do-not-propagate masks for each device. */ - Mask dontPropagateMask[EMASKSIZE]; - /** The clients that selected for events */ - InputClientsPtr inputClients; - /* XI2 event masks. One per device, each bit is a mask of (1 << type) */ - unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE]; -} OtherInputMasks; - -/* - * The following structure gets used for both active and passive grabs. For - * active grabs some of the fields (e.g. modifiers) are not used. However, - * that is not much waste since there aren't many active grabs (one per - * keyboard/pointer device) going at once in the server. - */ - -#define MasksPerDetailMask 8 /* 256 keycodes and 256 possible - modifier combinations, but only - 3 buttons. */ - -typedef struct _DetailRec { /* Grab details may be bit masks */ - unsigned int exact; - Mask *pMask; -} DetailRec; - -typedef enum { - GRABTYPE_CORE, - GRABTYPE_XI, - GRABTYPE_XI2 -} GrabType; - -union _GrabMask { - Mask core; - Mask xi; - char xi2mask[EMASKSIZE][XI2MASKSIZE]; -}; - -/** - * Central struct for device grabs. - * The same struct is used for both core grabs and device grabs, with - * different fields being set. - * If the grab is a core grab (GrabPointer/GrabKeyboard), then the eventMask - * is a combination of standard event masks (i.e. PointerMotionMask | - * ButtonPressMask). - * If the grab is a device grab (GrabDevice), then the eventMask is a - * combination of event masks for a given XI event type (see SetEventInfo). - * - * If the grab is a result of a ButtonPress, then eventMask is the core mask - * and deviceMask is set to the XI event mask for the grab. - */ -typedef struct _GrabRec { - GrabPtr next; /* for chain of passive grabs */ - XID resource; - DeviceIntPtr device; - WindowPtr window; - unsigned ownerEvents:1; - unsigned keyboardMode:1; - unsigned pointerMode:1; - GrabType grabtype; - CARD8 type; /* event type */ - DetailRec modifiersDetail; - DeviceIntPtr modifierDevice; - DetailRec detail; /* key or button */ - WindowPtr confineTo; /* always NULL for keyboards */ - CursorPtr cursor; /* always NULL for keyboards */ - Mask eventMask; - Mask deviceMask; - /* XI2 event masks. One per device, each bit is a mask of (1 << type) */ - unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE]; -} GrabRec; - -typedef struct _KeyClassRec { - int sourceid; - CARD8 down[DOWN_LENGTH]; - CARD8 postdown[DOWN_LENGTH]; - int modifierKeyCount[8]; - struct _XkbSrvInfo *xkbInfo; -} KeyClassRec, *KeyClassPtr; - -typedef struct _AxisInfo { - int resolution; - int min_resolution; - int max_resolution; - int min_value; - int max_value; - Atom label; -} AxisInfo, *AxisInfoPtr; - -typedef struct _ValuatorAccelerationRec { - int number; - PointerAccelSchemeProc AccelSchemeProc; - void *accelData; /* at disposal of AccelScheme */ - DeviceCallbackProc AccelCleanupProc; -} ValuatorAccelerationRec, *ValuatorAccelerationPtr; - -typedef struct _ValuatorClassRec { - int sourceid; - int numMotionEvents; - int first_motion; - int last_motion; - void *motion; /* motion history buffer. Different layout - for MDs and SDs!*/ - WindowPtr motionHintWindow; - - AxisInfoPtr axes; - unsigned short numAxes; - double *axisVal; /* always absolute, but device-coord system */ - CARD8 mode; - ValuatorAccelerationRec accelScheme; -} ValuatorClassRec, *ValuatorClassPtr; - -typedef struct _ButtonClassRec { - int sourceid; - CARD8 numButtons; - CARD8 buttonsDown; /* number of buttons currently down - This counts logical buttons, not - physical ones, i.e if some buttons - are mapped to 0, they're not counted - here */ - unsigned short state; - Mask motionMask; - CARD8 down[DOWN_LENGTH]; - CARD8 postdown[DOWN_LENGTH]; - CARD8 map[MAP_LENGTH]; - union _XkbAction *xkb_acts; - Atom labels[MAX_BUTTONS]; -} ButtonClassRec, *ButtonClassPtr; - -typedef struct _FocusClassRec { - int sourceid; - WindowPtr win; /* May be set to a int constant (e.g. PointerRootWin)! */ - int revert; - TimeStamp time; - WindowPtr *trace; - int traceSize; - int traceGood; -} FocusClassRec, *FocusClassPtr; - -typedef struct _ProximityClassRec { - int sourceid; - char pad; -} ProximityClassRec, *ProximityClassPtr; - -typedef struct _AbsoluteClassRec { - int sourceid; - /* Calibration. */ - int min_x; - int max_x; - int min_y; - int max_y; - int flip_x; - int flip_y; - int rotation; - int button_threshold; - - /* Area. */ - int offset_x; - int offset_y; - int width; - int height; - int screen; - XID following; -} AbsoluteClassRec, *AbsoluteClassPtr; - -typedef struct _KbdFeedbackClassRec *KbdFeedbackPtr; -typedef struct _PtrFeedbackClassRec *PtrFeedbackPtr; -typedef struct _IntegerFeedbackClassRec *IntegerFeedbackPtr; -typedef struct _StringFeedbackClassRec *StringFeedbackPtr; -typedef struct _BellFeedbackClassRec *BellFeedbackPtr; -typedef struct _LedFeedbackClassRec *LedFeedbackPtr; - -typedef struct _KbdFeedbackClassRec { - BellProcPtr BellProc; - KbdCtrlProcPtr CtrlProc; - KeybdCtrl ctrl; - KbdFeedbackPtr next; - struct _XkbSrvLedInfo *xkb_sli; -} KbdFeedbackClassRec; - -typedef struct _PtrFeedbackClassRec { - PtrCtrlProcPtr CtrlProc; - PtrCtrl ctrl; - PtrFeedbackPtr next; -} PtrFeedbackClassRec; - -typedef struct _IntegerFeedbackClassRec { - IntegerCtrlProcPtr CtrlProc; - IntegerCtrl ctrl; - IntegerFeedbackPtr next; -} IntegerFeedbackClassRec; - -typedef struct _StringFeedbackClassRec { - StringCtrlProcPtr CtrlProc; - StringCtrl ctrl; - StringFeedbackPtr next; -} StringFeedbackClassRec; - -typedef struct _BellFeedbackClassRec { - BellProcPtr BellProc; - BellCtrlProcPtr CtrlProc; - BellCtrl ctrl; - BellFeedbackPtr next; -} BellFeedbackClassRec; - -typedef struct _LedFeedbackClassRec { - LedCtrlProcPtr CtrlProc; - LedCtrl ctrl; - LedFeedbackPtr next; - struct _XkbSrvLedInfo *xkb_sli; -} LedFeedbackClassRec; - - -typedef struct _ClassesRec { - KeyClassPtr key; - ValuatorClassPtr valuator; - ButtonClassPtr button; - FocusClassPtr focus; - ProximityClassPtr proximity; - AbsoluteClassPtr absolute; - KbdFeedbackPtr kbdfeed; - PtrFeedbackPtr ptrfeed; - IntegerFeedbackPtr intfeed; - StringFeedbackPtr stringfeed; - BellFeedbackPtr bell; - LedFeedbackPtr leds; -} ClassesRec; - - -/** - * Sprite information for a device. - */ -typedef struct { - CursorPtr current; - BoxRec hotLimits; /* logical constraints of hot spot */ - Bool confined; /* confined to screen */ - RegionPtr hotShape; /* additional logical shape constraint */ - BoxRec physLimits; /* physical constraints of hot spot */ - WindowPtr win; /* window of logical position */ - HotSpot hot; /* logical pointer position */ - HotSpot hotPhys; /* physical pointer position */ -#ifdef PANORAMIX - ScreenPtr screen; /* all others are in Screen 0 coordinates */ - RegionRec Reg1; /* Region 1 for confining motion */ - RegionRec Reg2; /* Region 2 for confining virtual motion */ - WindowPtr windows[MAXSCREENS]; - WindowPtr confineWin; /* confine window */ -#endif - /* The window trace information is used at dix/events.c to avoid having - * to compute all the windows between the root and the current pointer - * window each time a button or key goes down. The grabs on each of those - * windows must be checked. - * spriteTraces should only be used at dix/events.c! */ - WindowPtr *spriteTrace; - int spriteTraceSize; - int spriteTraceGood; - - /* Due to delays between event generation and event processing, it is - * possible that the pointer has crossed screen boundaries between the - * time in which it begins generating events and the time when - * those events are processed. - * - * pEnqueueScreen: screen the pointer was on when the event was generated - * pDequeueScreen: screen the pointer was on when the event is processed - */ - ScreenPtr pEnqueueScreen; - ScreenPtr pDequeueScreen; - -} SpriteRec, *SpritePtr; - -/* Device properties */ -typedef struct _XIPropertyValue -{ - Atom type; /* ignored by server */ - short format; /* format of data for swapping - 8,16,32 */ - long size; /* size of data in (format/8) bytes */ - pointer data; /* private to client */ -} XIPropertyValueRec; - -typedef struct _XIProperty -{ - struct _XIProperty *next; - Atom propertyName; - BOOL deletable; /* clients can delete this prop? */ - XIPropertyValueRec value; -} XIPropertyRec; - -typedef XIPropertyRec *XIPropertyPtr; -typedef XIPropertyValueRec *XIPropertyValuePtr; - - -typedef struct _XIPropertyHandler -{ - struct _XIPropertyHandler* next; - long id; - int (*SetProperty) (DeviceIntPtr dev, - Atom property, - XIPropertyValuePtr prop, - BOOL checkonly); - int (*GetProperty) (DeviceIntPtr dev, - Atom property); - int (*DeleteProperty) (DeviceIntPtr dev, - Atom property); -} XIPropertyHandler, *XIPropertyHandlerPtr; - -/* states for devices */ - -#define NOT_GRABBED 0 -#define THAWED 1 -#define THAWED_BOTH 2 /* not a real state */ -#define FREEZE_NEXT_EVENT 3 -#define FREEZE_BOTH_NEXT_EVENT 4 -#define FROZEN 5 /* any state >= has device frozen */ -#define FROZEN_NO_EVENT 5 -#define FROZEN_WITH_EVENT 6 -#define THAW_OTHERS 7 - - -typedef struct _GrabInfoRec { - TimeStamp grabTime; - Bool fromPassiveGrab; /* true if from passive grab */ - Bool implicitGrab; /* implicit from ButtonPress */ - GrabRec activeGrab; - GrabPtr grab; - CARD8 activatingKey; - void (*ActivateGrab) ( - DeviceIntPtr /*device*/, - GrabPtr /*grab*/, - TimeStamp /*time*/, - Bool /*autoGrab*/); - void (*DeactivateGrab)( - DeviceIntPtr /*device*/); - struct { - Bool frozen; - int state; - GrabPtr other; /* if other grab has this frozen */ - DeviceEvent *event; /* saved to be replayed */ - } sync; -} GrabInfoRec, *GrabInfoPtr; - -typedef struct _SpriteInfoRec { - /* sprite must always point to a valid sprite. For devices sharing the - * sprite, let sprite point to a paired spriteOwner's sprite. */ - SpritePtr sprite; /* sprite information */ - Bool spriteOwner; /* True if device owns the sprite */ - DeviceIntPtr paired; /* The paired device. Keyboard if - spriteOwner is TRUE, otherwise the - pointer that owns the sprite. */ -} SpriteInfoRec, *SpriteInfoPtr; - -/* device types */ -#define MASTER_POINTER 1 -#define MASTER_KEYBOARD 2 -#define SLAVE 3 - -typedef struct _DeviceIntRec { - DeviceRec public; - DeviceIntPtr next; - Bool startup; /* true if needs to be turned on at - server intialization time */ - DeviceProc deviceProc; /* proc(DevicePtr, DEVICE_xx). It is - used to initialize, turn on, or - turn off the device */ - Bool inited; /* TRUE if INIT returns Success */ - Bool enabled; /* TRUE if ON returns Success */ - Bool coreEvents; /* TRUE if device also sends core */ - GrabInfoRec deviceGrab; /* grab on the device */ - int type; /* MASTER_POINTER, MASTER_KEYBOARD, SLAVE */ - Atom xinput_type; - char *name; - int id; - KeyClassPtr key; - ValuatorClassPtr valuator; - ButtonClassPtr button; - FocusClassPtr focus; - ProximityClassPtr proximity; - AbsoluteClassPtr absolute; - KbdFeedbackPtr kbdfeed; - PtrFeedbackPtr ptrfeed; - IntegerFeedbackPtr intfeed; - StringFeedbackPtr stringfeed; - BellFeedbackPtr bell; - LedFeedbackPtr leds; - struct _XkbInterest *xkb_interest; - char *config_info; /* used by the hotplug layer */ - ClassesPtr unused_classes; /* for master devices */ - int saved_master_id; /* for slaves while grabbed */ - PrivateRec *devPrivates; - DeviceUnwrapProc unwrapProc; - SpriteInfoPtr spriteInfo; - union { - DeviceIntPtr master; /* master device */ - DeviceIntPtr lastSlave; /* last slave device used */ - } u; - - /* last valuator values recorded, not posted to client; - * for slave devices, valuators is in device coordinates - * for master devices, valuators is in screen coordinates - * see dix/getevents.c - * remainder supports acceleration - */ - struct { - int valuators[MAX_VALUATORS]; - float remainder[MAX_VALUATORS]; - int numValuators; - DeviceIntPtr slave; - } last; - - /* Input device property handling. */ - struct { - XIPropertyPtr properties; - XIPropertyHandlerPtr handlers; /* NULL-terminated */ - } properties; -} DeviceIntRec; - -typedef struct { - int numDevices; /* total number of devices */ - DeviceIntPtr devices; /* all devices turned on */ - DeviceIntPtr off_devices; /* all devices turned off */ - DeviceIntPtr keyboard; /* the main one for the server */ - DeviceIntPtr pointer; - DeviceIntPtr all_devices; - DeviceIntPtr all_master_devices; -} InputInfo; - -extern _X_EXPORT InputInfo inputInfo; - -/* for keeping the events for devices grabbed synchronously */ -typedef struct _QdEvent *QdEventPtr; -typedef struct _QdEvent { - QdEventPtr next; - DeviceIntPtr device; - ScreenPtr pScreen; /* what screen the pointer was on */ - unsigned long months; /* milliseconds is in the event */ - InternalEvent *event; -} QdEventRec; - -/** - * syncEvents is the global structure for queued events. - * - * Devices can be frozen through GrabModeSync pointer grabs. If this is the - * case, events from these devices are added to "pending" instead of being - * processed normally. When the device is unfrozen, events in "pending" are - * replayed and processed as if they would come from the device directly. - */ -typedef struct _EventSyncInfo { - QdEventPtr pending, /**< list of queued events */ - *pendtail; /**< last event in list */ - /** The device to replay events for. Only set in AllowEvents(), in which - * case it is set to the device specified in the request. */ - DeviceIntPtr replayDev; /* kludgy rock to put flag for */ - - /** - * The window the events are supposed to be replayed on. - * This window may be set to the grab's window (but only when - * Replay{Pointer|Keyboard} is given in the XAllowEvents() - * request. */ - WindowPtr replayWin; /* ComputeFreezes */ - /** - * Flag to indicate whether we're in the process of - * replaying events. Only set in ComputeFreezes(). */ - Bool playingEvents; - TimeStamp time; -} EventSyncInfoRec, *EventSyncInfoPtr; - -extern EventSyncInfoRec syncEvents; - -#endif /* INPUTSTRUCT_H */ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + + +#ifndef INPUTSTRUCT_H +#define INPUTSTRUCT_H + +#include "input.h" +#include "window.h" +#include "dixstruct.h" +#include "cursorstr.h" +#include "geext.h" +#include "privates.h" + +#define BitIsOn(ptr, bit) (((BYTE *) (ptr))[(bit)>>3] & (1 << ((bit) & 7))) +#define SetBit(ptr, bit) (((BYTE *) (ptr))[(bit)>>3] |= (1 << ((bit) & 7))) +#define ClearBit(ptr, bit) (((BYTE *)(ptr))[(bit)>>3] &= ~(1 << ((bit) & 7))) + +#define SameClient(obj,client) \ + (CLIENT_BITS((obj)->resource) == (client)->clientAsMask) + +#define EMASKSIZE MAXDEVICES + 2 + +/* This is the last XI2 event supported by the server. If you add + * events to the protocol, the server will not support these events until + * this number here is bumped. + */ +#define XI2LASTEVENT 17 /* XI_RawMotion */ +#define XI2MASKSIZE ((XI2LASTEVENT + 7)/8) /* no of bits for masks */ + +/** + * This struct stores the core event mask for each client except the client + * that created the window. + * + * Each window that has events selected from other clients has at least one of + * these masks. If multiple clients selected for events on the same window, + * these masks are in a linked list. + * + * The event mask for the client that created the window is stored in + * win->eventMask instead. + * + * The resource id is simply a fake client ID to associate this mask with a + * client. + * + * Kludge: OtherClients and InputClients must be compatible, see code. + */ +typedef struct _OtherClients { + OtherClientsPtr next; /**< Pointer to the next mask */ + XID resource; /**< id for putting into resource manager */ + Mask mask; /**< Core event mask */ +} OtherClients; + +/** + * This struct stores the XI event mask for each client. + * + * Each window that has events selected has at least one of these masks. If + * multiple client selected for events on the same window, these masks are in + * a linked list. + */ +typedef struct _InputClients { + InputClientsPtr next; /**< Pointer to the next mask */ + XID resource; /**< id for putting into resource manager */ + Mask mask[EMASKSIZE]; /**< Actual XI event mask, deviceid is index */ + /** XI2 event masks. One per device, each bit is a mask of (1 << type) */ + unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE]; +} InputClients; + +/** + * Combined XI event masks from all devices. + * + * This is the XI equivalent of the deliverableEvents, eventMask and + * dontPropagate mask of the WindowRec (or WindowOptRec). + * + * A window that has an XI client selecting for events has exactly one + * OtherInputMasks struct and exactly one InputClients struct hanging off + * inputClients. Each further client appends to the inputClients list. + * Each Mask field is per-device, with the device id as the index. + * Exception: for non-device events (Presence events), the MAXDEVICES + * deviceid is used. + */ +typedef struct _OtherInputMasks { + /** + * Bitwise OR of all masks by all clients and the window's parent's masks. + */ + Mask deliverableEvents[EMASKSIZE]; + /** + * Bitwise OR of all masks by all clients on this window. + */ + Mask inputEvents[EMASKSIZE]; + /** The do-not-propagate masks for each device. */ + Mask dontPropagateMask[EMASKSIZE]; + /** The clients that selected for events */ + InputClientsPtr inputClients; + /* XI2 event masks. One per device, each bit is a mask of (1 << type) */ + unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE]; +} OtherInputMasks; + +/* + * The following structure gets used for both active and passive grabs. For + * active grabs some of the fields (e.g. modifiers) are not used. However, + * that is not much waste since there aren't many active grabs (one per + * keyboard/pointer device) going at once in the server. + */ + +#define MasksPerDetailMask 8 /* 256 keycodes and 256 possible + modifier combinations, but only + 3 buttons. */ + +typedef struct _DetailRec { /* Grab details may be bit masks */ + unsigned int exact; + Mask *pMask; +} DetailRec; + +typedef enum { + GRABTYPE_CORE, + GRABTYPE_XI, + GRABTYPE_XI2 +} GrabType; + +union _GrabMask { + Mask core; + Mask xi; + char xi2mask[EMASKSIZE][XI2MASKSIZE]; +}; + +/** + * Central struct for device grabs. + * The same struct is used for both core grabs and device grabs, with + * different fields being set. + * If the grab is a core grab (GrabPointer/GrabKeyboard), then the eventMask + * is a combination of standard event masks (i.e. PointerMotionMask | + * ButtonPressMask). + * If the grab is a device grab (GrabDevice), then the eventMask is a + * combination of event masks for a given XI event type (see SetEventInfo). + * + * If the grab is a result of a ButtonPress, then eventMask is the core mask + * and deviceMask is set to the XI event mask for the grab. + */ +typedef struct _GrabRec { + GrabPtr next; /* for chain of passive grabs */ + XID resource; + DeviceIntPtr device; + WindowPtr window; + unsigned ownerEvents:1; + unsigned keyboardMode:1; + unsigned pointerMode:1; + GrabType grabtype; + CARD8 type; /* event type */ + DetailRec modifiersDetail; + DeviceIntPtr modifierDevice; + DetailRec detail; /* key or button */ + WindowPtr confineTo; /* always NULL for keyboards */ + CursorPtr cursor; /* always NULL for keyboards */ + Mask eventMask; + Mask deviceMask; + /* XI2 event masks. One per device, each bit is a mask of (1 << type) */ + unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE]; +} GrabRec; + +typedef struct _KeyClassRec { + int sourceid; + CARD8 down[DOWN_LENGTH]; + CARD8 postdown[DOWN_LENGTH]; + int modifierKeyCount[8]; + struct _XkbSrvInfo *xkbInfo; +} KeyClassRec, *KeyClassPtr; + +typedef struct _AxisInfo { + int resolution; + int min_resolution; + int max_resolution; + int min_value; + int max_value; + Atom label; +} AxisInfo, *AxisInfoPtr; + +typedef struct _ValuatorAccelerationRec { + int number; + PointerAccelSchemeProc AccelSchemeProc; + void *accelData; /* at disposal of AccelScheme */ + DeviceCallbackProc AccelCleanupProc; +} ValuatorAccelerationRec, *ValuatorAccelerationPtr; + +typedef struct _ValuatorClassRec { + int sourceid; + int numMotionEvents; + int first_motion; + int last_motion; + void *motion; /* motion history buffer. Different layout + for MDs and SDs!*/ + WindowPtr motionHintWindow; + + AxisInfoPtr axes; + unsigned short numAxes; + double *axisVal; /* always absolute, but device-coord system */ + CARD8 mode; + ValuatorAccelerationRec accelScheme; +} ValuatorClassRec, *ValuatorClassPtr; + +typedef struct _ButtonClassRec { + int sourceid; + CARD8 numButtons; + CARD8 buttonsDown; /* number of buttons currently down + This counts logical buttons, not + physical ones, i.e if some buttons + are mapped to 0, they're not counted + here */ + unsigned short state; + Mask motionMask; + CARD8 down[DOWN_LENGTH]; + CARD8 postdown[DOWN_LENGTH]; + CARD8 map[MAP_LENGTH]; + union _XkbAction *xkb_acts; + Atom labels[MAX_BUTTONS]; +} ButtonClassRec, *ButtonClassPtr; + +typedef struct _FocusClassRec { + int sourceid; + WindowPtr win; /* May be set to a int constant (e.g. PointerRootWin)! */ + int revert; + TimeStamp time; + WindowPtr *trace; + int traceSize; + int traceGood; +} FocusClassRec, *FocusClassPtr; + +typedef struct _ProximityClassRec { + int sourceid; + char pad; +} ProximityClassRec, *ProximityClassPtr; + +typedef struct _AbsoluteClassRec { + int sourceid; + /* Calibration. */ + int min_x; + int max_x; + int min_y; + int max_y; + int flip_x; + int flip_y; + int rotation; + int button_threshold; + + /* Area. */ + int offset_x; + int offset_y; + int width; + int height; + int screen; + XID following; +} AbsoluteClassRec, *AbsoluteClassPtr; + +typedef struct _KbdFeedbackClassRec *KbdFeedbackPtr; +typedef struct _PtrFeedbackClassRec *PtrFeedbackPtr; +typedef struct _IntegerFeedbackClassRec *IntegerFeedbackPtr; +typedef struct _StringFeedbackClassRec *StringFeedbackPtr; +typedef struct _BellFeedbackClassRec *BellFeedbackPtr; +typedef struct _LedFeedbackClassRec *LedFeedbackPtr; + +typedef struct _KbdFeedbackClassRec { + BellProcPtr BellProc; + KbdCtrlProcPtr CtrlProc; + KeybdCtrl ctrl; + KbdFeedbackPtr next; + struct _XkbSrvLedInfo *xkb_sli; +} KbdFeedbackClassRec; + +typedef struct _PtrFeedbackClassRec { + PtrCtrlProcPtr CtrlProc; + PtrCtrl ctrl; + PtrFeedbackPtr next; +} PtrFeedbackClassRec; + +typedef struct _IntegerFeedbackClassRec { + IntegerCtrlProcPtr CtrlProc; + IntegerCtrl ctrl; + IntegerFeedbackPtr next; +} IntegerFeedbackClassRec; + +typedef struct _StringFeedbackClassRec { + StringCtrlProcPtr CtrlProc; + StringCtrl ctrl; + StringFeedbackPtr next; +} StringFeedbackClassRec; + +typedef struct _BellFeedbackClassRec { + BellProcPtr BellProc; + BellCtrlProcPtr CtrlProc; + BellCtrl ctrl; + BellFeedbackPtr next; +} BellFeedbackClassRec; + +typedef struct _LedFeedbackClassRec { + LedCtrlProcPtr CtrlProc; + LedCtrl ctrl; + LedFeedbackPtr next; + struct _XkbSrvLedInfo *xkb_sli; +} LedFeedbackClassRec; + + +typedef struct _ClassesRec { + KeyClassPtr key; + ValuatorClassPtr valuator; + ButtonClassPtr button; + FocusClassPtr focus; + ProximityClassPtr proximity; + AbsoluteClassPtr absolute; + KbdFeedbackPtr kbdfeed; + PtrFeedbackPtr ptrfeed; + IntegerFeedbackPtr intfeed; + StringFeedbackPtr stringfeed; + BellFeedbackPtr bell; + LedFeedbackPtr leds; +} ClassesRec; + + +/** + * Sprite information for a device. + */ +typedef struct { + CursorPtr current; + BoxRec hotLimits; /* logical constraints of hot spot */ + Bool confined; /* confined to screen */ + RegionPtr hotShape; /* additional logical shape constraint */ + BoxRec physLimits; /* physical constraints of hot spot */ + WindowPtr win; /* window of logical position */ + HotSpot hot; /* logical pointer position */ + HotSpot hotPhys; /* physical pointer position */ +#ifdef PANORAMIX + ScreenPtr screen; /* all others are in Screen 0 coordinates */ + RegionRec Reg1; /* Region 1 for confining motion */ + RegionRec Reg2; /* Region 2 for confining virtual motion */ + WindowPtr windows[MAXSCREENS]; + WindowPtr confineWin; /* confine window */ +#endif + /* The window trace information is used at dix/events.c to avoid having + * to compute all the windows between the root and the current pointer + * window each time a button or key goes down. The grabs on each of those + * windows must be checked. + * spriteTraces should only be used at dix/events.c! */ + WindowPtr *spriteTrace; + int spriteTraceSize; + int spriteTraceGood; + + /* Due to delays between event generation and event processing, it is + * possible that the pointer has crossed screen boundaries between the + * time in which it begins generating events and the time when + * those events are processed. + * + * pEnqueueScreen: screen the pointer was on when the event was generated + * pDequeueScreen: screen the pointer was on when the event is processed + */ + ScreenPtr pEnqueueScreen; + ScreenPtr pDequeueScreen; + +} SpriteRec, *SpritePtr; + +/* Device properties */ +typedef struct _XIPropertyValue +{ + Atom type; /* ignored by server */ + short format; /* format of data for swapping - 8,16,32 */ + long size; /* size of data in (format/8) bytes */ + pointer data; /* private to client */ +} XIPropertyValueRec; + +typedef struct _XIProperty +{ + struct _XIProperty *next; + Atom propertyName; + BOOL deletable; /* clients can delete this prop? */ + XIPropertyValueRec value; +} XIPropertyRec; + +typedef XIPropertyRec *XIPropertyPtr; +typedef XIPropertyValueRec *XIPropertyValuePtr; + + +typedef struct _XIPropertyHandler +{ + struct _XIPropertyHandler* next; + long id; + int (*SetProperty) (DeviceIntPtr dev, + Atom property, + XIPropertyValuePtr prop, + BOOL checkonly); + int (*GetProperty) (DeviceIntPtr dev, + Atom property); + int (*DeleteProperty) (DeviceIntPtr dev, + Atom property); +} XIPropertyHandler, *XIPropertyHandlerPtr; + +/* states for devices */ + +#define NOT_GRABBED 0 +#define THAWED 1 +#define THAWED_BOTH 2 /* not a real state */ +#define FREEZE_NEXT_EVENT 3 +#define FREEZE_BOTH_NEXT_EVENT 4 +#define FROZEN 5 /* any state >= has device frozen */ +#define FROZEN_NO_EVENT 5 +#define FROZEN_WITH_EVENT 6 +#define THAW_OTHERS 7 + + +typedef struct _GrabInfoRec { + TimeStamp grabTime; + Bool fromPassiveGrab; /* true if from passive grab */ + Bool implicitGrab; /* implicit from ButtonPress */ + GrabRec activeGrab; + GrabPtr grab; + CARD8 activatingKey; + void (*ActivateGrab) ( + DeviceIntPtr /*device*/, + GrabPtr /*grab*/, + TimeStamp /*time*/, + Bool /*autoGrab*/); + void (*DeactivateGrab)( + DeviceIntPtr /*device*/); + struct { + Bool frozen; + int state; + GrabPtr other; /* if other grab has this frozen */ + DeviceEvent *event; /* saved to be replayed */ + } sync; +} GrabInfoRec, *GrabInfoPtr; + +typedef struct _SpriteInfoRec { + /* sprite must always point to a valid sprite. For devices sharing the + * sprite, let sprite point to a paired spriteOwner's sprite. */ + SpritePtr sprite; /* sprite information */ + Bool spriteOwner; /* True if device owns the sprite */ + DeviceIntPtr paired; /* The paired device. Keyboard if + spriteOwner is TRUE, otherwise the + pointer that owns the sprite. */ + + /* keep states for animated cursor */ + struct { + CursorPtr pCursor; + ScreenPtr pScreen; + int elt; + CARD32 time; + } anim; +} SpriteInfoRec, *SpriteInfoPtr; + +/* device types */ +#define MASTER_POINTER 1 +#define MASTER_KEYBOARD 2 +#define SLAVE 3 + +typedef struct _DeviceIntRec { + DeviceRec public; + DeviceIntPtr next; + Bool startup; /* true if needs to be turned on at + server intialization time */ + DeviceProc deviceProc; /* proc(DevicePtr, DEVICE_xx). It is + used to initialize, turn on, or + turn off the device */ + Bool inited; /* TRUE if INIT returns Success */ + Bool enabled; /* TRUE if ON returns Success */ + Bool coreEvents; /* TRUE if device also sends core */ + GrabInfoRec deviceGrab; /* grab on the device */ + int type; /* MASTER_POINTER, MASTER_KEYBOARD, SLAVE */ + Atom xinput_type; + char *name; + int id; + KeyClassPtr key; + ValuatorClassPtr valuator; + ButtonClassPtr button; + FocusClassPtr focus; + ProximityClassPtr proximity; + AbsoluteClassPtr absolute; + KbdFeedbackPtr kbdfeed; + PtrFeedbackPtr ptrfeed; + IntegerFeedbackPtr intfeed; + StringFeedbackPtr stringfeed; + BellFeedbackPtr bell; + LedFeedbackPtr leds; + struct _XkbInterest *xkb_interest; + char *config_info; /* used by the hotplug layer */ + ClassesPtr unused_classes; /* for master devices */ + int saved_master_id; /* for slaves while grabbed */ + PrivateRec *devPrivates; + DeviceUnwrapProc unwrapProc; + SpriteInfoPtr spriteInfo; + union { + DeviceIntPtr master; /* master device */ + DeviceIntPtr lastSlave; /* last slave device used */ + } u; + + /* last valuator values recorded, not posted to client; + * for slave devices, valuators is in device coordinates + * for master devices, valuators is in screen coordinates + * see dix/getevents.c + * remainder supports acceleration + */ + struct { + int valuators[MAX_VALUATORS]; + float remainder[MAX_VALUATORS]; + int numValuators; + DeviceIntPtr slave; + } last; + + /* Input device property handling. */ + struct { + XIPropertyPtr properties; + XIPropertyHandlerPtr handlers; /* NULL-terminated */ + } properties; +} DeviceIntRec; + +typedef struct { + int numDevices; /* total number of devices */ + DeviceIntPtr devices; /* all devices turned on */ + DeviceIntPtr off_devices; /* all devices turned off */ + DeviceIntPtr keyboard; /* the main one for the server */ + DeviceIntPtr pointer; + DeviceIntPtr all_devices; + DeviceIntPtr all_master_devices; +} InputInfo; + +extern _X_EXPORT InputInfo inputInfo; + +/* for keeping the events for devices grabbed synchronously */ +typedef struct _QdEvent *QdEventPtr; +typedef struct _QdEvent { + QdEventPtr next; + DeviceIntPtr device; + ScreenPtr pScreen; /* what screen the pointer was on */ + unsigned long months; /* milliseconds is in the event */ + InternalEvent *event; +} QdEventRec; + +/** + * syncEvents is the global structure for queued events. + * + * Devices can be frozen through GrabModeSync pointer grabs. If this is the + * case, events from these devices are added to "pending" instead of being + * processed normally. When the device is unfrozen, events in "pending" are + * replayed and processed as if they would come from the device directly. + */ +typedef struct _EventSyncInfo { + QdEventPtr pending, /**< list of queued events */ + *pendtail; /**< last event in list */ + /** The device to replay events for. Only set in AllowEvents(), in which + * case it is set to the device specified in the request. */ + DeviceIntPtr replayDev; /* kludgy rock to put flag for */ + + /** + * The window the events are supposed to be replayed on. + * This window may be set to the grab's window (but only when + * Replay{Pointer|Keyboard} is given in the XAllowEvents() + * request. */ + WindowPtr replayWin; /* ComputeFreezes */ + /** + * Flag to indicate whether we're in the process of + * replaying events. Only set in ComputeFreezes(). */ + Bool playingEvents; + TimeStamp time; +} EventSyncInfoRec, *EventSyncInfoPtr; + +extern EventSyncInfoRec syncEvents; + +#endif /* INPUTSTRUCT_H */ diff --git a/xorg-server/include/resource.h b/xorg-server/include/resource.h index d2a8422b4..aa719aa0a 100644 --- a/xorg-server/include/resource.h +++ b/xorg-server/include/resource.h @@ -157,6 +157,9 @@ typedef Bool (*FindComplexResType)( extern _X_EXPORT RESTYPE CreateNewResourceType( DeleteType /*deleteFunc*/, char * /*name*/); +extern _X_EXPORT void SetResourceTypeErrorValue( + RESTYPE /*type*/, int /*errorValue*/); + extern _X_EXPORT RESTYPE CreateNewResourceClass(void); extern _X_EXPORT Bool InitClientResources( diff --git a/xorg-server/mi/midispcur.c b/xorg-server/mi/midispcur.c index d4b7f132b..d8fe26ada 100644 --- a/xorg-server/mi/midispcur.c +++ b/xorg-server/mi/midispcur.c @@ -97,44 +97,6 @@ typedef struct { #endif } miDCCursorRec, *miDCCursorPtr; -/* - * sprite/cursor method table - */ - -static Bool miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); -static Bool miDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); -static Bool miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor, int x, int y, - unsigned long source, unsigned long mask); -static Bool miDCSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y, - int w, int h); -static Bool miDCRestoreUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y, - int w, int h); -static Bool miDCMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor, int x, int y, - int w, int h, int dx, int dy, - unsigned long source, unsigned long mask); -static Bool miDCChangeSave(DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y, int w, int h, - int dx, int dy); - -static Bool miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen); -static void miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen); - -static miSpriteCursorFuncRec miDCFuncs = { - miDCRealizeCursor, - miDCUnrealizeCursor, - miDCPutUpCursor, - miDCSaveUnderCursor, - miDCRestoreUnderCursor, - miDCMoveCursor, - miDCChangeSave, - miDCDeviceInitialize, - miDCDeviceCleanup -}; - Bool miDCInitialize (ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs) { @@ -150,7 +112,7 @@ miDCInitialize (ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs) dixSetPrivate(&pScreen->devPrivates, miDCScreenKey, pScreenPriv); - if (!miSpriteInitialize (pScreen, &miDCFuncs, screenFuncs)) + if (!miSpriteInitialize (pScreen, screenFuncs)) { free((pointer) pScreenPriv); return FALSE; @@ -170,7 +132,7 @@ miDCCloseScreen (int index, ScreenPtr pScreen) return (*pScreen->CloseScreen) (index, pScreen); } -static Bool +Bool miDCRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) { if (pCursor->bits->refcnt <= 1) @@ -329,7 +291,7 @@ miDCRealize (ScreenPtr pScreen, CursorPtr pCursor) return pPriv; } -static Bool +Bool miDCUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) { miDCCursorPtr pPriv; @@ -426,7 +388,7 @@ miDCMakeGC(WindowPtr pWin) } -static Bool +Bool miDCPutUpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y, unsigned long source, unsigned long mask) { @@ -471,7 +433,7 @@ miDCPutUpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, return TRUE; } -static Bool +Bool miDCSaveUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y, int w, int h) { @@ -505,7 +467,7 @@ miDCSaveUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen, return TRUE; } -static Bool +Bool miDCRestoreUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y, int w, int h) { @@ -532,7 +494,7 @@ miDCRestoreUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen, return TRUE; } -static Bool +Bool miDCChangeSave (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y, int w, int h, int dx, int dy) { @@ -665,7 +627,7 @@ miDCChangeSave (DeviceIntPtr pDev, ScreenPtr pScreen, return TRUE; } -static Bool +Bool miDCMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y, int w, int h, int dx, int dy, unsigned long source, unsigned long mask) @@ -764,7 +726,7 @@ miDCMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, return TRUE; } -static Bool +Bool miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) { miDCBufferPtr pBuffer; @@ -839,7 +801,7 @@ failure: return FALSE; } -static void +void miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) { miDCBufferPtr pBuffer; diff --git a/xorg-server/mi/miexpose.c b/xorg-server/mi/miexpose.c index f6f195daa..2fc19f6ec 100644 --- a/xorg-server/mi/miexpose.c +++ b/xorg-server/mi/miexpose.c @@ -374,6 +374,8 @@ miSendGraphicsExpose (ClientPtr client, RegionPtr pRgn, XID drawable, pe->u.graphicsExposure.majorEvent = major; pe->u.graphicsExposure.minorEvent = minor; } + /* GraphicsExpose is a "critical event", which TryClientEvents + * handles specially. */ TryClientEvents(client, NULL, pEvent, numRects, (Mask)0, NoEventMask, NullGrab); free(pEvent); @@ -386,8 +388,7 @@ miSendGraphicsExpose (ClientPtr client, RegionPtr pRgn, XID drawable, event.u.noExposure.drawable = drawable; event.u.noExposure.majorEvent = major; event.u.noExposure.minorEvent = minor; - TryClientEvents(client, NULL, &event, 1, - (Mask)0, NoEventMask, NullGrab); + WriteEventsToClient(client, 1, &event); } } diff --git a/xorg-server/mi/misprite.c b/xorg-server/mi/misprite.c index b0f7ecd39..69494b9dc 100644 --- a/xorg-server/mi/misprite.c +++ b/xorg-server/mi/misprite.c @@ -94,7 +94,6 @@ typedef struct { ColormapPtr pInstalledMap; ColormapPtr pColormap; VisualPtr pVisual; - miSpriteCursorFuncPtr funcs; DamagePtr pDamage; /* damage tracking structure */ Bool damageRegistered; } miSpriteScreenRec, *miSpriteScreenPtr; @@ -258,12 +257,9 @@ static void miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure) { ScreenPtr pScreen = closure; - miSpriteScreenPtr pScreenPriv; miCursorInfoPtr pCursorInfo; DeviceIntPtr pDev; - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { if (DevHasCursor(pDev)) @@ -289,7 +285,6 @@ miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure) Bool miSpriteInitialize (ScreenPtr pScreen, - miSpriteCursorFuncPtr cursorFuncs, miPointerScreenFuncPtr screenFuncs) { miSpriteScreenPtr pScreenPriv; @@ -336,7 +331,6 @@ miSpriteInitialize (ScreenPtr pScreen, pScreenPriv->pInstalledMap = NULL; pScreenPriv->pColormap = NULL; - pScreenPriv->funcs = cursorFuncs; pScreenPriv->colors[SOURCE_COLOR].red = 0; pScreenPriv->colors[SOURCE_COLOR].green = 0; pScreenPriv->colors[SOURCE_COLOR].blue = 0; @@ -397,7 +391,6 @@ miSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h, char *pdstLine) { ScreenPtr pScreen = pDrawable->pScreen; - miSpriteScreenPtr pScreenPriv; DeviceIntPtr pDev; miCursorInfoPtr pCursorInfo; @@ -405,7 +398,6 @@ miSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h, if (pDrawable->type == DRAWABLE_WINDOW) { - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates,miSpriteScreenKey); for(pDev = inputInfo.devices; pDev; pDev = pDev->next) { if (DevHasCursor(pDev)) @@ -433,7 +425,6 @@ miSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart) { ScreenPtr pScreen = pDrawable->pScreen; - miSpriteScreenPtr pScreenPriv; DeviceIntPtr pDev; miCursorInfoPtr pCursorInfo; @@ -441,8 +432,6 @@ miSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, if (pDrawable->type == DRAWABLE_WINDOW) { - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates,miSpriteScreenKey); - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) { if (DevHasCursor(pDev)) @@ -487,7 +476,6 @@ miSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width, int height) { ScreenPtr pScreen = pDrawable->pScreen; - miSpriteScreenPtr pScreenPriv; DeviceIntPtr pDev; miCursorInfoPtr pCursorInfo; @@ -495,8 +483,6 @@ miSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width, if (pDrawable->type == DRAWABLE_WINDOW) { - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates,miSpriteScreenKey); - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) { if (DevHasCursor(pDev)) @@ -523,14 +509,11 @@ static void miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) { ScreenPtr pScreen = pWindow->drawable.pScreen; - miSpriteScreenPtr pScreenPriv; DeviceIntPtr pDev; miCursorInfoPtr pCursorInfo; SCREEN_PROLOGUE (pScreen, CopyWindow); - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) { if (DevHasCursor(pDev)) @@ -760,10 +743,8 @@ miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen) static Bool miSpriteRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) { - miSpriteScreenPtr pScreenPriv; miCursorInfoPtr pCursorInfo; - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); if (!IsMaster(pDev) && !pDev->u.master) return FALSE; @@ -772,27 +753,21 @@ miSpriteRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) if (pCursor == pCursorInfo->pCursor) pCursorInfo->checkPixels = TRUE; - return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor); + return miDCRealizeCursor(pScreen, pCursor); } static Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) { - miSpriteScreenPtr pScreenPriv; - - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor); + return miDCUnrealizeCursor(pScreen, pCursor); } static void miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y) { - miSpriteScreenPtr pScreenPriv; miCursorInfoPtr pPointer; - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - if (!IsMaster(pDev) && !pDev->u.master) return; @@ -861,7 +836,7 @@ miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen, pointer->saved.y1 -= dy; pointer->saved.x2 -= dx; pointer->saved.y2 -= dy; - (void) (*pScreenPriv->funcs->ChangeSave) (pScreen, + (void) miDCChangeSave(pScreen, pointer->saved.x1, pointer->saved.y1, pointer->saved.x2 - @@ -870,7 +845,7 @@ miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen, pointer->saved.y1, dx, dy); } - (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor, + (void) miDCMoveCursor(pScreen, pCursor, pointer->saved.x1, pointer->saved.y1, pointer->saved.x2 - @@ -904,10 +879,8 @@ miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen, static void miSpriteMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) { - miSpriteScreenPtr pScreenPriv; CursorPtr pCursor; - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); if (!IsMaster(pDev) && !pDev->u.master) return; @@ -920,12 +893,9 @@ miSpriteMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) static Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) { - miSpriteScreenPtr pScreenPriv; miCursorInfoPtr pCursorInfo; int ret = FALSE; - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - pCursorInfo = malloc(sizeof(miCursorInfoRec)); if (!pCursorInfo) return FALSE; @@ -940,7 +910,7 @@ miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) pCursorInfo->checkPixels = TRUE; pCursorInfo->pScreen = FALSE; - ret = (*pScreenPriv->funcs->DeviceCursorInitialize)(pDev, pScreen); + ret = miDCDeviceInitialize(pDev, pScreen); if (!ret) { free(pCursorInfo); @@ -954,13 +924,7 @@ static void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) { if (DevHasCursor(pDev)) - { - miSpriteScreenPtr pScreenPriv; - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, - miSpriteScreenKey); - - (*pScreenPriv->funcs->DeviceCursorCleanup)(pDev, pScreen); - } + miDCDeviceCleanup(pDev, pScreen); } /* @@ -984,16 +948,16 @@ miSpriteRemoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen) miSpriteIsDown(pCursorInfo); pCursorInfo->pCacheWin = NullWindow; miSpriteDisableDamage(pScreen, pScreenPriv); - if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pDev, - pScreen, - pCursorInfo->saved.x1, - pCursorInfo->saved.y1, - pCursorInfo->saved.x2 - - pCursorInfo->saved.x1, - pCursorInfo->saved.y2 - - pCursorInfo->saved.y1)) + if (!miDCRestoreUnderCursor(pDev, + pScreen, + pCursorInfo->saved.x1, + pCursorInfo->saved.y1, + pCursorInfo->saved.x2 - + pCursorInfo->saved.x1, + pCursorInfo->saved.y2 - + pCursorInfo->saved.y1)) { - miSpriteIsUp(pCursorInfo); + miSpriteIsUp(pCursorInfo); } miSpriteEnableDamage(pScreen, pScreenPriv); DamageDrawInternal (pScreen, FALSE); @@ -1026,14 +990,14 @@ miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen) y = pCursorInfo->y - (int)pCursor->bits->yhot; miSpriteDisableDamage(pScreen, pScreenPriv); - (*pScreenPriv->funcs->SaveUnderCursor) (pDev, - pScreen, - pCursorInfo->saved.x1, - pCursorInfo->saved.y1, - pCursorInfo->saved.x2 - - pCursorInfo->saved.x1, - pCursorInfo->saved.y2 - - pCursorInfo->saved.y1); + miDCSaveUnderCursor(pDev, + pScreen, + pCursorInfo->saved.x1, + pCursorInfo->saved.y1, + pCursorInfo->saved.x2 - + pCursorInfo->saved.x1, + pCursorInfo->saved.y2 - + pCursorInfo->saved.y1); SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id)); miSpriteEnableDamage(pScreen, pScreenPriv); DamageDrawInternal (pScreen, FALSE); @@ -1069,7 +1033,7 @@ miSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen) SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id)); if (pCursorInfo->checkPixels) miSpriteFindColors (pCursorInfo, pScreen); - if ((*pScreenPriv->funcs->PutUpCursor) (pDev, pScreen, + if (miDCPutUpCursor(pDev, pScreen, pCursor, x, y, pScreenPriv->colors[SOURCE_COLOR].pixel, pScreenPriv->colors[MASK_COLOR].pixel)) @@ -1088,7 +1052,6 @@ miSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen) static void miSpriteComputeSaved (DeviceIntPtr pDev, ScreenPtr pScreen) { - miSpriteScreenPtr pScreenPriv; int x, y, w, h; int wpad, hpad; CursorPtr pCursor; @@ -1097,7 +1060,6 @@ miSpriteComputeSaved (DeviceIntPtr pDev, ScreenPtr pScreen) if (!IsMaster(pDev) && !pDev->u.master) return; - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); pCursorInfo = MISPRITE(pDev); pCursor = pCursorInfo->pCursor; diff --git a/xorg-server/mi/misprite.h b/xorg-server/mi/misprite.h index 72dc06fc7..6dbc48460 100644 --- a/xorg-server/mi/misprite.h +++ b/xorg-server/mi/misprite.h @@ -1,107 +1,57 @@ -/* - * misprite.h - * - * software-sprite/sprite drawing interface spec - * - * mi versions of these routines exist. - */ - - -/* - -Copyright 1989, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. -*/ - -typedef struct { - Bool (*RealizeCursor)( - ScreenPtr /*pScreen*/, - CursorPtr /*pCursor*/ -); - Bool (*UnrealizeCursor)( - ScreenPtr /*pScreen*/, - CursorPtr /*pCursor*/ -); - Bool (*PutUpCursor)( - DeviceIntPtr /*pDev*/, - ScreenPtr /*pScreen*/, - CursorPtr /*pCursor*/, - int /*x*/, - int /*y*/, - unsigned long /*source*/, - unsigned long /*mask*/ -); - Bool (*SaveUnderCursor)( - DeviceIntPtr /*pDev*/, - ScreenPtr /*pScreen*/, - int /*x*/, - int /*y*/, - int /*w*/, - int /*h*/ -); - Bool (*RestoreUnderCursor)( - DeviceIntPtr /*pDev*/, - ScreenPtr /*pScreen*/, - int /*x*/, - int /*y*/, - int /*w*/, - int /*h*/ -); - Bool (*MoveCursor)( - DeviceIntPtr /*pDev*/, - ScreenPtr /*pScreen*/, - CursorPtr /*pCursor*/, - int /*x*/, - int /*y*/, - int /*w*/, - int /*h*/, - int /*dx*/, - int /*dy*/, - unsigned long /*source*/, - unsigned long /*mask*/ -); - Bool (*ChangeSave)( - DeviceIntPtr /*pDev*/, - ScreenPtr /*pScreen*/, - int /*x*/, - int /*y*/, - int /*w*/, - int /*h*/, - int /*dx*/, - int /*dy*/ -); - Bool (*DeviceCursorInitialize)( - DeviceIntPtr /*pDev*/, - ScreenPtr /*pScreen*/ -); - void (*DeviceCursorCleanup)( - DeviceIntPtr /*pDev*/, - ScreenPtr /*pScreen*/ -); - -} miSpriteCursorFuncRec, *miSpriteCursorFuncPtr; - -extern Bool miSpriteInitialize( - ScreenPtr /*pScreen*/, - miSpriteCursorFuncPtr /*cursorFuncs*/, - miPointerScreenFuncPtr /*screenFuncs*/ -); +/* + * misprite.h + * + * software-sprite/sprite drawing interface spec + * + * mi versions of these routines exist. + */ + + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +extern Bool miSpriteInitialize( + ScreenPtr /*pScreen*/, + miPointerScreenFuncPtr /*screenFuncs*/ +); + +extern Bool miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); +extern Bool miDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); +extern Bool miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, int x, int y, + unsigned long source, unsigned long mask); +extern Bool miDCSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, int w, int h); +extern Bool miDCRestoreUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, int w, int h); +extern Bool miDCMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, int x, int y, + int w, int h, int dx, int dy, + unsigned long source, unsigned long mask); +extern Bool miDCChangeSave(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, int w, int h, + int dx, int dy); +extern Bool miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen); +extern void miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen); diff --git a/xorg-server/os/io.c b/xorg-server/os/io.c index a963d8653..82a2c5875 100644 --- a/xorg-server/os/io.c +++ b/xorg-server/os/io.c @@ -698,15 +698,17 @@ SetCriticalOutputPending(void) int WriteToClient (ClientPtr who, int count, const void *__buf) { - OsCommPtr oc = (OsCommPtr)who->osPrivate; - ConnectionOutputPtr oco = oc->output; + OsCommPtr oc; + ConnectionOutputPtr oco; int padBytes; const char *buf = __buf; #ifdef DEBUG_COMMUNICATION Bool multicount = FALSE; #endif - if (!count) + if (!count || !who || who == serverClient || who->clientGone) return(0); + oc = who->osPrivate; + oco = oc->output; #ifdef DEBUG_COMMUNICATION { char info[128]; diff --git a/xorg-server/randr/randrstr.h b/xorg-server/randr/randrstr.h index b163a73da..aa938d651 100644 --- a/xorg-server/randr/randrstr.h +++ b/xorg-server/randr/randrstr.h @@ -1,987 +1,987 @@ -/* - * Copyright © 2000 Compaq Computer Corporation - * Copyright © 2002 Hewlett-Packard Company - * Copyright © 2006 Intel Corporation - * Copyright © 2008 Red Hat, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - * - * Author: Jim Gettys, Hewlett-Packard Company, Inc. - * Keith Packard, Intel Corporation - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#ifndef _RANDRSTR_H_ -#define _RANDRSTR_H_ - -#include <X11/X.h> -#include <X11/Xproto.h> -#include "misc.h" -#include "os.h" -#include "dixstruct.h" -#include "resource.h" -#include "scrnintstr.h" -#include "windowstr.h" -#include "pixmapstr.h" -#include "extnsionst.h" -#include "servermd.h" -#include "rrtransform.h" -#include <X11/extensions/randr.h> -#include <X11/extensions/randrproto.h> -#include <X11/extensions/render.h> /* we share subpixel order information */ -#include "picturestr.h" -#include <X11/Xfuncproto.h> - -/* required for ABI compatibility for now */ -#define RANDR_10_INTERFACE 1 -#define RANDR_12_INTERFACE 1 -#define RANDR_13_INTERFACE 1 /* requires RANDR_12_INTERFACE */ -#define RANDR_GET_CRTC_INTERFACE 1 - -#define RANDR_INTERFACE_VERSION 0x0103 - -typedef XID RRMode; -typedef XID RROutput; -typedef XID RRCrtc; - -extern _X_EXPORT int RREventBase, RRErrorBase; - -extern _X_EXPORT int (*ProcRandrVector[RRNumberRequests])(ClientPtr); -extern _X_EXPORT int (*SProcRandrVector[RRNumberRequests])(ClientPtr); - -/* - * Modeline for a monitor. Name follows directly after this struct - */ - -#define RRModeName(pMode) ((char *) (pMode + 1)) -typedef struct _rrMode RRModeRec, *RRModePtr; -typedef struct _rrPropertyValue RRPropertyValueRec, *RRPropertyValuePtr; -typedef struct _rrProperty RRPropertyRec, *RRPropertyPtr; -typedef struct _rrCrtc RRCrtcRec, *RRCrtcPtr; -typedef struct _rrOutput RROutputRec, *RROutputPtr; - -struct _rrMode { - int refcnt; - xRRModeInfo mode; - char *name; - ScreenPtr userScreen; -}; - -struct _rrPropertyValue { - Atom type; /* ignored by server */ - short format; /* format of data for swapping - 8,16,32 */ - long size; /* size of data in (format/8) bytes */ - pointer data; /* private to client */ -}; - -struct _rrProperty { - RRPropertyPtr next; - ATOM propertyName; - Bool is_pending; - Bool range; - Bool immutable; - int num_valid; - INT32 *valid_values; - RRPropertyValueRec current, pending; -}; - -struct _rrCrtc { - RRCrtc id; - ScreenPtr pScreen; - RRModePtr mode; - int x, y; - Rotation rotation; - Rotation rotations; - Bool changed; - int numOutputs; - RROutputPtr *outputs; - int gammaSize; - CARD16 *gammaRed; - CARD16 *gammaBlue; - CARD16 *gammaGreen; - void *devPrivate; - Bool transforms; - RRTransformRec client_pending_transform; - RRTransformRec client_current_transform; - PictTransform transform; - struct pict_f_transform f_transform; - struct pict_f_transform f_inverse; -}; - -struct _rrOutput { - RROutput id; - ScreenPtr pScreen; - char *name; - int nameLength; - CARD8 connection; - CARD8 subpixelOrder; - int mmWidth; - int mmHeight; - RRCrtcPtr crtc; - int numCrtcs; - RRCrtcPtr *crtcs; - int numClones; - RROutputPtr *clones; - int numModes; - int numPreferred; - RRModePtr *modes; - int numUserModes; - RRModePtr *userModes; - Bool changed; - RRPropertyPtr properties; - Bool pendingProperties; - void *devPrivate; -}; - -#if RANDR_12_INTERFACE -typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr pScreen, - CARD16 width, - CARD16 height, - CARD32 mmWidth, - CARD32 mmHeight); - -typedef Bool (*RRCrtcSetProcPtr) (ScreenPtr pScreen, - RRCrtcPtr crtc, - RRModePtr mode, - int x, - int y, - Rotation rotation, - int numOutputs, - RROutputPtr *outputs); - -typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr pScreen, - RRCrtcPtr crtc); - -typedef Bool (*RRCrtcGetGammaProcPtr) (ScreenPtr pScreen, - RRCrtcPtr crtc); - -typedef Bool (*RROutputSetPropertyProcPtr) (ScreenPtr pScreen, - RROutputPtr output, - Atom property, - RRPropertyValuePtr value); - -typedef Bool (*RROutputValidateModeProcPtr) (ScreenPtr pScreen, - RROutputPtr output, - RRModePtr mode); - -typedef void (*RRModeDestroyProcPtr) (ScreenPtr pScreen, - RRModePtr mode); - -#endif - -#if RANDR_13_INTERFACE -typedef Bool (*RROutputGetPropertyProcPtr) (ScreenPtr pScreen, - RROutputPtr output, - Atom property); -typedef Bool (*RRGetPanningProcPtr) (ScreenPtr pScrn, - RRCrtcPtr crtc, - BoxPtr totalArea, - BoxPtr trackingArea, - INT16 *border); -typedef Bool (*RRSetPanningProcPtr) (ScreenPtr pScrn, - RRCrtcPtr crtc, - BoxPtr totalArea, - BoxPtr trackingArea, - INT16 *border); - -#endif /* RANDR_13_INTERFACE */ - -typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations); -typedef Bool (*RRCloseScreenProcPtr) ( int i, ScreenPtr pscreen); - -/* These are for 1.0 compatibility */ - -typedef struct _rrRefresh { - CARD16 rate; - RRModePtr mode; -} RRScreenRate, *RRScreenRatePtr; - -typedef struct _rrScreenSize { - int id; - short width, height; - short mmWidth, mmHeight; - int nRates; - RRScreenRatePtr pRates; -} RRScreenSize, *RRScreenSizePtr; - -#ifdef RANDR_10_INTERFACE - -typedef Bool (*RRSetConfigProcPtr) (ScreenPtr pScreen, - Rotation rotation, - int rate, - RRScreenSizePtr pSize); - -#endif - - -typedef struct _rrScrPriv { - /* - * 'public' part of the structure; DDXen fill this in - * as they initialize - */ -#if RANDR_10_INTERFACE - RRSetConfigProcPtr rrSetConfig; -#endif - RRGetInfoProcPtr rrGetInfo; -#if RANDR_12_INTERFACE - RRScreenSetSizeProcPtr rrScreenSetSize; - RRCrtcSetProcPtr rrCrtcSet; - RRCrtcSetGammaProcPtr rrCrtcSetGamma; - RRCrtcGetGammaProcPtr rrCrtcGetGamma; - RROutputSetPropertyProcPtr rrOutputSetProperty; - RROutputValidateModeProcPtr rrOutputValidateMode; - RRModeDestroyProcPtr rrModeDestroy; -#endif -#if RANDR_13_INTERFACE - RROutputGetPropertyProcPtr rrOutputGetProperty; - RRGetPanningProcPtr rrGetPanning; - RRSetPanningProcPtr rrSetPanning; -#endif - - /* - * Private part of the structure; not considered part of the ABI - */ - TimeStamp lastSetTime; /* last changed by client */ - TimeStamp lastConfigTime; /* possible configs changed */ - RRCloseScreenProcPtr CloseScreen; - - Bool changed; /* some config changed */ - Bool configChanged; /* configuration changed */ - Bool layoutChanged; /* screen layout changed */ - - CARD16 minWidth, minHeight; - CARD16 maxWidth, maxHeight; - CARD16 width, height; /* last known screen size */ - CARD16 mmWidth, mmHeight; /* last known screen size */ - - int numOutputs; - RROutputPtr *outputs; - RROutputPtr primaryOutput; - - int numCrtcs; - RRCrtcPtr *crtcs; - - /* Last known pointer position */ - RRCrtcPtr pointerCrtc; - -#ifdef RANDR_10_INTERFACE - /* - * Configuration information - */ - Rotation rotations; - CARD16 reqWidth, reqHeight; - - int nSizes; - RRScreenSizePtr pSizes; - - Rotation rotation; - int rate; - int size; -#endif -} rrScrPrivRec, *rrScrPrivPtr; - -extern _X_EXPORT DevPrivateKey rrPrivKey; - -#define rrGetScrPriv(pScr) ((rrScrPrivPtr)dixLookupPrivate(&(pScr)->devPrivates, rrPrivKey)) -#define rrScrPriv(pScr) rrScrPrivPtr pScrPriv = rrGetScrPriv(pScr) -#define SetRRScreen(s,p) dixSetPrivate(&(s)->devPrivates, rrPrivKey, p) - -/* - * each window has a list of clients requesting - * RRNotify events. Each client has a resource - * for each window it selects RRNotify input for, - * this resource is used to delete the RRNotifyRec - * entry from the per-window queue. - */ - -typedef struct _RREvent *RREventPtr; - -typedef struct _RREvent { - RREventPtr next; - ClientPtr client; - WindowPtr window; - XID clientResource; - int mask; -} RREventRec; - -typedef struct _RRTimes { - TimeStamp setTime; - TimeStamp configTime; -} RRTimesRec, *RRTimesPtr; - -typedef struct _RRClient { - int major_version; - int minor_version; -/* RRTimesRec times[0]; */ -} RRClientRec, *RRClientPtr; - -extern _X_EXPORT RESTYPE RRClientType, RREventType; /* resource types for event masks */ -extern _X_EXPORT DevPrivateKey RRClientPrivateKey; -extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType; - -#define VERIFY_RR_OUTPUT(id, ptr, a)\ - {\ - int rc = dixLookupResourceByType((pointer *)&(ptr), id,\ - RROutputType, client, a);\ - if (rc != Success) {\ - client->errorValue = id;\ - return (rc == BadValue) ? RRErrorBase + BadRROutput : rc;\ - }\ - } - -#define VERIFY_RR_CRTC(id, ptr, a)\ - {\ - int rc = dixLookupResourceByType((pointer *)&(ptr), id,\ - RRCrtcType, client, a);\ - if (rc != Success) {\ - client->errorValue = id;\ - return (rc == BadValue) ? RRErrorBase + BadRRCrtc : rc;\ - }\ - } - -#define VERIFY_RR_MODE(id, ptr, a)\ - {\ - int rc = dixLookupResourceByType((pointer *)&(ptr), id,\ - RRModeType, client, a);\ - if (rc != Success) {\ - client->errorValue = id;\ - return (rc == BadValue) ? RRErrorBase + BadRRMode : rc;\ - }\ - } - -#define GetRRClient(pClient) ((RRClientPtr)dixLookupPrivate(&(pClient)->devPrivates, RRClientPrivateKey)) -#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient) - -/* Initialize the extension */ -extern _X_EXPORT void -RRExtensionInit (void); - -#ifdef RANDR_12_INTERFACE -/* - * Set the range of sizes for the screen - */ -extern _X_EXPORT void -RRScreenSetSizeRange (ScreenPtr pScreen, - CARD16 minWidth, - CARD16 minHeight, - CARD16 maxWidth, - CARD16 maxHeight); -#endif - -/* rrscreen.c */ -/* - * Notify the extension that the screen size has been changed. - * The driver is responsible for calling this whenever it has changed - * the size of the screen - */ -extern _X_EXPORT void -RRScreenSizeNotify (ScreenPtr pScreen); - -/* - * Request that the screen be resized - */ -extern _X_EXPORT Bool -RRScreenSizeSet (ScreenPtr pScreen, - CARD16 width, - CARD16 height, - CARD32 mmWidth, - CARD32 mmHeight); - -/* - * Send ConfigureNotify event to root window when 'something' happens - */ -extern _X_EXPORT void -RRSendConfigNotify (ScreenPtr pScreen); - -/* - * screen dispatch - */ -extern _X_EXPORT int -ProcRRGetScreenSizeRange (ClientPtr client); - -extern _X_EXPORT int -ProcRRSetScreenSize (ClientPtr client); - -extern _X_EXPORT int -ProcRRGetScreenResources (ClientPtr client); - -extern _X_EXPORT int -ProcRRGetScreenResourcesCurrent (ClientPtr client); - -extern _X_EXPORT int -ProcRRSetScreenConfig (ClientPtr client); - -extern _X_EXPORT int -ProcRRGetScreenInfo (ClientPtr client); - -/* - * Deliver a ScreenNotify event - */ -extern _X_EXPORT void -RRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen); - -/* mirandr.c */ -extern _X_EXPORT Bool -miRandRInit (ScreenPtr pScreen); - -extern _X_EXPORT Bool -miRRGetInfo (ScreenPtr pScreen, Rotation *rotations); - -extern _X_EXPORT Bool -miRRCrtcSet (ScreenPtr pScreen, - RRCrtcPtr crtc, - RRModePtr mode, - int x, - int y, - Rotation rotation, - int numOutput, - RROutputPtr *outputs); - -extern _X_EXPORT Bool -miRROutputSetProperty (ScreenPtr pScreen, - RROutputPtr output, - Atom property, - RRPropertyValuePtr value); - -extern _X_EXPORT Bool -miRROutputGetProperty (ScreenPtr pScreen, - RROutputPtr output, - Atom property); - -extern _X_EXPORT Bool -miRROutputValidateMode (ScreenPtr pScreen, - RROutputPtr output, - RRModePtr mode); - -extern _X_EXPORT void -miRRModeDestroy (ScreenPtr pScreen, - RRModePtr mode); - -/* randr.c */ -/* - * Send all pending events - */ -extern _X_EXPORT void -RRTellChanged (ScreenPtr pScreen); - -/* - * Poll the driver for changed information - */ -extern _X_EXPORT Bool -RRGetInfo (ScreenPtr pScreen, Bool force_query); - -extern _X_EXPORT Bool RRInit (void); - -extern _X_EXPORT Bool RRScreenInit(ScreenPtr pScreen); - -extern _X_EXPORT RROutputPtr -RRFirstOutput (ScreenPtr pScreen); - -extern _X_EXPORT Rotation -RRGetRotation (ScreenPtr pScreen); - -extern _X_EXPORT CARD16 -RRVerticalRefresh (xRRModeInfo *mode); - -#ifdef RANDR_10_INTERFACE -/* - * This is the old interface, deprecated but left - * around for compatibility - */ - -/* - * Then, register the specific size with the screen - */ - -extern _X_EXPORT RRScreenSizePtr -RRRegisterSize (ScreenPtr pScreen, - short width, - short height, - short mmWidth, - short mmHeight); - -extern _X_EXPORT Bool -RRRegisterRate (ScreenPtr pScreen, - RRScreenSizePtr pSize, - int rate); - -/* - * Finally, set the current configuration of the screen - */ - -extern _X_EXPORT void -RRSetCurrentConfig (ScreenPtr pScreen, - Rotation rotation, - int rate, - RRScreenSizePtr pSize); - -extern _X_EXPORT Bool RRScreenInit (ScreenPtr pScreen); - -extern _X_EXPORT Rotation -RRGetRotation (ScreenPtr pScreen); - -#endif - -/* rrcrtc.c */ - -/* - * Notify the CRTC of some change; layoutChanged indicates that - * some position or size element changed - */ -extern _X_EXPORT void -RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged); - -/* - * Create a CRTC - */ -extern _X_EXPORT RRCrtcPtr -RRCrtcCreate (ScreenPtr pScreen, void *devPrivate); - -/* - * Set the allowed rotations on a CRTC - */ -extern _X_EXPORT void -RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations); - -/* - * Set whether transforms are allowed on a CRTC - */ -extern _X_EXPORT void -RRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms); - -/* - * Notify the extension that the Crtc has been reconfigured, - * the driver calls this whenever it has updated the mode - */ -extern _X_EXPORT Bool -RRCrtcNotify (RRCrtcPtr crtc, - RRModePtr mode, - int x, - int y, - Rotation rotation, - RRTransformPtr transform, - int numOutputs, - RROutputPtr *outputs); - -extern _X_EXPORT void -RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc); - -/* - * Request that the Crtc be reconfigured - */ -extern _X_EXPORT Bool -RRCrtcSet (RRCrtcPtr crtc, - RRModePtr mode, - int x, - int y, - Rotation rotation, - int numOutput, - RROutputPtr *outputs); - -/* - * Request that the Crtc gamma be changed - */ - -extern _X_EXPORT Bool -RRCrtcGammaSet (RRCrtcPtr crtc, - CARD16 *red, - CARD16 *green, - CARD16 *blue); - -/* - * Request current gamma back from the DDX (if possible). - * This includes gamma size. - */ - -extern _X_EXPORT Bool -RRCrtcGammaGet(RRCrtcPtr crtc); - -/* - * Notify the extension that the Crtc gamma has been changed - * The driver calls this whenever it has changed the gamma values - * in the RRCrtcRec - */ - -extern _X_EXPORT Bool -RRCrtcGammaNotify (RRCrtcPtr crtc); - -/* - * Set the size of the gamma table at server startup time - */ - -extern _X_EXPORT Bool -RRCrtcGammaSetSize (RRCrtcPtr crtc, - int size); - -/* - * Return the area of the frame buffer scanned out by the crtc, - * taking into account the current mode and rotation - */ - -extern _X_EXPORT void -RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height); - -/* - * Compute the complete transformation matrix including - * client-specified transform, rotation/reflection values and the crtc - * offset. - * - * Return TRUE if the resulting transform is not a simple translation. - */ -extern _X_EXPORT Bool -RRTransformCompute (int x, - int y, - int width, - int height, - Rotation rotation, - RRTransformPtr rr_transform, - - PictTransformPtr transform, - struct pict_f_transform *f_transform, - struct pict_f_transform *f_inverse); - -/* - * Return crtc transform - */ -extern _X_EXPORT RRTransformPtr -RRCrtcGetTransform (RRCrtcPtr crtc); - -/* - * Check whether the pending and current transforms are the same - */ -extern _X_EXPORT Bool -RRCrtcPendingTransform (RRCrtcPtr crtc); - -/* - * Destroy a Crtc at shutdown - */ -extern _X_EXPORT void -RRCrtcDestroy (RRCrtcPtr crtc); - - -/* - * Set the pending CRTC transformation - */ - -extern _X_EXPORT int -RRCrtcTransformSet (RRCrtcPtr crtc, - PictTransformPtr transform, - struct pict_f_transform *f_transform, - struct pict_f_transform *f_inverse, - char *filter, - int filter_len, - xFixed *params, - int nparams); - -/* - * Initialize crtc type - */ -extern _X_EXPORT Bool -RRCrtcInit (void); - -/* - * Crtc dispatch - */ - -extern _X_EXPORT int -ProcRRGetCrtcInfo (ClientPtr client); - -extern _X_EXPORT int -ProcRRSetCrtcConfig (ClientPtr client); - -extern _X_EXPORT int -ProcRRGetCrtcGammaSize (ClientPtr client); - -extern _X_EXPORT int -ProcRRGetCrtcGamma (ClientPtr client); - -extern _X_EXPORT int -ProcRRSetCrtcGamma (ClientPtr client); - -extern _X_EXPORT int -ProcRRSetCrtcTransform (ClientPtr client); - -extern _X_EXPORT int -ProcRRGetCrtcTransform (ClientPtr client); - -int -ProcRRGetPanning (ClientPtr client); - -int -ProcRRSetPanning (ClientPtr client); - -/* rrdispatch.c */ -extern _X_EXPORT Bool -RRClientKnowsRates (ClientPtr pClient); - -/* rrmode.c */ -/* - * Find, and if necessary, create a mode - */ - -extern _X_EXPORT RRModePtr -RRModeGet (xRRModeInfo *modeInfo, - const char *name); - -/* - * Destroy a mode. - */ - -extern _X_EXPORT void -RRModeDestroy (RRModePtr mode); - -/* - * Return a list of modes that are valid for some output in pScreen - */ -extern _X_EXPORT RRModePtr * -RRModesForScreen (ScreenPtr pScreen, int *num_ret); - -/* - * Initialize mode type - */ -extern _X_EXPORT Bool -RRModeInit (void); - -extern _X_EXPORT int -ProcRRCreateMode (ClientPtr client); - -extern _X_EXPORT int -ProcRRDestroyMode (ClientPtr client); - -extern _X_EXPORT int -ProcRRAddOutputMode (ClientPtr client); - -extern _X_EXPORT int -ProcRRDeleteOutputMode (ClientPtr client); - -/* rroutput.c */ - -/* - * Notify the output of some change. configChanged indicates whether - * any external configuration (mode list, clones, connected status) - * has changed, or whether the change was strictly internal - * (which crtc is in use) - */ -extern _X_EXPORT void -RROutputChanged (RROutputPtr output, Bool configChanged); - -/* - * Create an output - */ - -extern _X_EXPORT RROutputPtr -RROutputCreate (ScreenPtr pScreen, - const char *name, - int nameLength, - void *devPrivate); - -/* - * Notify extension that output parameters have been changed - */ -extern _X_EXPORT Bool -RROutputSetClones (RROutputPtr output, - RROutputPtr *clones, - int numClones); - -extern _X_EXPORT Bool -RROutputSetModes (RROutputPtr output, - RRModePtr *modes, - int numModes, - int numPreferred); - -extern _X_EXPORT int -RROutputAddUserMode (RROutputPtr output, - RRModePtr mode); - -extern _X_EXPORT int -RROutputDeleteUserMode (RROutputPtr output, - RRModePtr mode); - -extern _X_EXPORT Bool -RROutputSetCrtcs (RROutputPtr output, - RRCrtcPtr *crtcs, - int numCrtcs); - -extern _X_EXPORT Bool -RROutputSetConnection (RROutputPtr output, - CARD8 connection); - -extern _X_EXPORT Bool -RROutputSetSubpixelOrder (RROutputPtr output, - int subpixelOrder); - -extern _X_EXPORT Bool -RROutputSetPhysicalSize (RROutputPtr output, - int mmWidth, - int mmHeight); - -extern _X_EXPORT void -RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output); - -extern _X_EXPORT void -RROutputDestroy (RROutputPtr output); - -extern _X_EXPORT int -ProcRRGetOutputInfo (ClientPtr client); - -extern _X_EXPORT int -ProcRRSetOutputPrimary (ClientPtr client); - -extern _X_EXPORT int -ProcRRGetOutputPrimary (ClientPtr client); - -/* - * Initialize output type - */ -extern _X_EXPORT Bool -RROutputInit (void); - -/* rrpointer.c */ -extern _X_EXPORT void -RRPointerMoved (ScreenPtr pScreen, int x, int y); - -extern _X_EXPORT void -RRPointerScreenConfigured (ScreenPtr pScreen); - -/* rrproperty.c */ - -extern _X_EXPORT void -RRDeleteAllOutputProperties (RROutputPtr output); - -extern _X_EXPORT RRPropertyValuePtr -RRGetOutputProperty (RROutputPtr output, Atom property, Bool pending); - -extern _X_EXPORT RRPropertyPtr -RRQueryOutputProperty (RROutputPtr output, Atom property); - -extern _X_EXPORT void -RRDeleteOutputProperty (RROutputPtr output, Atom property); - -extern _X_EXPORT Bool -RRPostPendingProperties (RROutputPtr output); - -extern _X_EXPORT int -RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type, - int format, int mode, unsigned long len, - pointer value, Bool sendevent, Bool pending); - -extern _X_EXPORT int -RRConfigureOutputProperty (RROutputPtr output, Atom property, - Bool pending, Bool range, Bool immutable, - int num_values, INT32 *values); -extern _X_EXPORT int -ProcRRChangeOutputProperty (ClientPtr client); - -extern _X_EXPORT int -ProcRRGetOutputProperty (ClientPtr client); - -extern _X_EXPORT int -ProcRRListOutputProperties (ClientPtr client); - -extern _X_EXPORT int -ProcRRQueryOutputProperty (ClientPtr client); - -extern _X_EXPORT int -ProcRRConfigureOutputProperty (ClientPtr client); - -extern _X_EXPORT int -ProcRRDeleteOutputProperty (ClientPtr client); - -/* rrxinerama.c */ -#ifdef XINERAMA -extern _X_EXPORT void -RRXineramaExtensionInit(void); -#endif - -#endif /* _RANDRSTR_H_ */ - -/* - -randr extension implementation structure - -Query state: - ProcRRGetScreenInfo/ProcRRGetScreenResources - RRGetInfo - - • Request configuration from driver, either 1.0 or 1.2 style - • These functions only record state changes, all - other actions are pended until RRTellChanged is called - - ->rrGetInfo - 1.0: - RRRegisterSize - RRRegisterRate - RRSetCurrentConfig - 1.2: - RRScreenSetSizeRange - RROutputSetCrtcs - RRModeGet - RROutputSetModes - RROutputSetConnection - RROutputSetSubpixelOrder - RROutputSetClones - RRCrtcNotify - - • Must delay scanning configuration until after ->rrGetInfo returns - because some drivers will call SetCurrentConfig in the middle - of the ->rrGetInfo operation. - - 1.0: - - • Scan old configuration, mirror to new structures - - RRScanOldConfig - RRCrtcCreate - RROutputCreate - RROutputSetCrtcs - RROutputSetConnection - RROutputSetSubpixelOrder - RROldModeAdd • This adds modes one-at-a-time - RRModeGet - RRCrtcNotify - - • send events, reset pointer if necessary - - RRTellChanged - WalkTree (sending events) - - • when layout has changed: - RRPointerScreenConfigured - RRSendConfigNotify - -Asynchronous state setting (1.2 only) - When setting state asynchronously, the driver invokes the - ->rrGetInfo function and then calls RRTellChanged to flush - the changes to the clients and reset pointer if necessary - -Set state - - ProcRRSetScreenConfig - RRCrtcSet - 1.2: - ->rrCrtcSet - RRCrtcNotify - 1.0: - ->rrSetConfig - RRCrtcNotify - RRTellChanged - */ +/* + * Copyright © 2000 Compaq Computer Corporation + * Copyright © 2002 Hewlett-Packard Company + * Copyright © 2006 Intel Corporation + * Copyright © 2008 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + * + * Author: Jim Gettys, Hewlett-Packard Company, Inc. + * Keith Packard, Intel Corporation + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef _RANDRSTR_H_ +#define _RANDRSTR_H_ + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "servermd.h" +#include "rrtransform.h" +#include <X11/extensions/randr.h> +#include <X11/extensions/randrproto.h> +#include <X11/extensions/render.h> /* we share subpixel order information */ +#include "picturestr.h" +#include <X11/Xfuncproto.h> + +/* required for ABI compatibility for now */ +#define RANDR_10_INTERFACE 1 +#define RANDR_12_INTERFACE 1 +#define RANDR_13_INTERFACE 1 /* requires RANDR_12_INTERFACE */ +#define RANDR_GET_CRTC_INTERFACE 1 + +#define RANDR_INTERFACE_VERSION 0x0103 + +typedef XID RRMode; +typedef XID RROutput; +typedef XID RRCrtc; + +extern _X_EXPORT int RREventBase, RRErrorBase; + +extern _X_EXPORT int (*ProcRandrVector[RRNumberRequests])(ClientPtr); +extern _X_EXPORT int (*SProcRandrVector[RRNumberRequests])(ClientPtr); + +/* + * Modeline for a monitor. Name follows directly after this struct + */ + +#define RRModeName(pMode) ((char *) (pMode + 1)) +typedef struct _rrMode RRModeRec, *RRModePtr; +typedef struct _rrPropertyValue RRPropertyValueRec, *RRPropertyValuePtr; +typedef struct _rrProperty RRPropertyRec, *RRPropertyPtr; +typedef struct _rrCrtc RRCrtcRec, *RRCrtcPtr; +typedef struct _rrOutput RROutputRec, *RROutputPtr; + +struct _rrMode { + int refcnt; + xRRModeInfo mode; + char *name; + ScreenPtr userScreen; +}; + +struct _rrPropertyValue { + Atom type; /* ignored by server */ + short format; /* format of data for swapping - 8,16,32 */ + long size; /* size of data in (format/8) bytes */ + pointer data; /* private to client */ +}; + +struct _rrProperty { + RRPropertyPtr next; + ATOM propertyName; + Bool is_pending; + Bool range; + Bool immutable; + int num_valid; + INT32 *valid_values; + RRPropertyValueRec current, pending; +}; + +struct _rrCrtc { + RRCrtc id; + ScreenPtr pScreen; + RRModePtr mode; + int x, y; + Rotation rotation; + Rotation rotations; + Bool changed; + int numOutputs; + RROutputPtr *outputs; + int gammaSize; + CARD16 *gammaRed; + CARD16 *gammaBlue; + CARD16 *gammaGreen; + void *devPrivate; + Bool transforms; + RRTransformRec client_pending_transform; + RRTransformRec client_current_transform; + PictTransform transform; + struct pict_f_transform f_transform; + struct pict_f_transform f_inverse; +}; + +struct _rrOutput { + RROutput id; + ScreenPtr pScreen; + char *name; + int nameLength; + CARD8 connection; + CARD8 subpixelOrder; + int mmWidth; + int mmHeight; + RRCrtcPtr crtc; + int numCrtcs; + RRCrtcPtr *crtcs; + int numClones; + RROutputPtr *clones; + int numModes; + int numPreferred; + RRModePtr *modes; + int numUserModes; + RRModePtr *userModes; + Bool changed; + RRPropertyPtr properties; + Bool pendingProperties; + void *devPrivate; +}; + +#if RANDR_12_INTERFACE +typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr pScreen, + CARD16 width, + CARD16 height, + CARD32 mmWidth, + CARD32 mmHeight); + +typedef Bool (*RRCrtcSetProcPtr) (ScreenPtr pScreen, + RRCrtcPtr crtc, + RRModePtr mode, + int x, + int y, + Rotation rotation, + int numOutputs, + RROutputPtr *outputs); + +typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr pScreen, + RRCrtcPtr crtc); + +typedef Bool (*RRCrtcGetGammaProcPtr) (ScreenPtr pScreen, + RRCrtcPtr crtc); + +typedef Bool (*RROutputSetPropertyProcPtr) (ScreenPtr pScreen, + RROutputPtr output, + Atom property, + RRPropertyValuePtr value); + +typedef Bool (*RROutputValidateModeProcPtr) (ScreenPtr pScreen, + RROutputPtr output, + RRModePtr mode); + +typedef void (*RRModeDestroyProcPtr) (ScreenPtr pScreen, + RRModePtr mode); + +#endif + +#if RANDR_13_INTERFACE +typedef Bool (*RROutputGetPropertyProcPtr) (ScreenPtr pScreen, + RROutputPtr output, + Atom property); +typedef Bool (*RRGetPanningProcPtr) (ScreenPtr pScrn, + RRCrtcPtr crtc, + BoxPtr totalArea, + BoxPtr trackingArea, + INT16 *border); +typedef Bool (*RRSetPanningProcPtr) (ScreenPtr pScrn, + RRCrtcPtr crtc, + BoxPtr totalArea, + BoxPtr trackingArea, + INT16 *border); + +#endif /* RANDR_13_INTERFACE */ + +typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations); +typedef Bool (*RRCloseScreenProcPtr) ( int i, ScreenPtr pscreen); + +/* These are for 1.0 compatibility */ + +typedef struct _rrRefresh { + CARD16 rate; + RRModePtr mode; +} RRScreenRate, *RRScreenRatePtr; + +typedef struct _rrScreenSize { + int id; + short width, height; + short mmWidth, mmHeight; + int nRates; + RRScreenRatePtr pRates; +} RRScreenSize, *RRScreenSizePtr; + +#ifdef RANDR_10_INTERFACE + +typedef Bool (*RRSetConfigProcPtr) (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize); + +#endif + + +typedef struct _rrScrPriv { + /* + * 'public' part of the structure; DDXen fill this in + * as they initialize + */ +#if RANDR_10_INTERFACE + RRSetConfigProcPtr rrSetConfig; +#endif + RRGetInfoProcPtr rrGetInfo; +#if RANDR_12_INTERFACE + RRScreenSetSizeProcPtr rrScreenSetSize; + RRCrtcSetProcPtr rrCrtcSet; + RRCrtcSetGammaProcPtr rrCrtcSetGamma; + RRCrtcGetGammaProcPtr rrCrtcGetGamma; + RROutputSetPropertyProcPtr rrOutputSetProperty; + RROutputValidateModeProcPtr rrOutputValidateMode; + RRModeDestroyProcPtr rrModeDestroy; +#endif +#if RANDR_13_INTERFACE + RROutputGetPropertyProcPtr rrOutputGetProperty; + RRGetPanningProcPtr rrGetPanning; + RRSetPanningProcPtr rrSetPanning; +#endif + + /* + * Private part of the structure; not considered part of the ABI + */ + TimeStamp lastSetTime; /* last changed by client */ + TimeStamp lastConfigTime; /* possible configs changed */ + RRCloseScreenProcPtr CloseScreen; + + Bool changed; /* some config changed */ + Bool configChanged; /* configuration changed */ + Bool layoutChanged; /* screen layout changed */ + + CARD16 minWidth, minHeight; + CARD16 maxWidth, maxHeight; + CARD16 width, height; /* last known screen size */ + CARD16 mmWidth, mmHeight; /* last known screen size */ + + int numOutputs; + RROutputPtr *outputs; + RROutputPtr primaryOutput; + + int numCrtcs; + RRCrtcPtr *crtcs; + + /* Last known pointer position */ + RRCrtcPtr pointerCrtc; + +#ifdef RANDR_10_INTERFACE + /* + * Configuration information + */ + Rotation rotations; + CARD16 reqWidth, reqHeight; + + int nSizes; + RRScreenSizePtr pSizes; + + Rotation rotation; + int rate; + int size; +#endif +} rrScrPrivRec, *rrScrPrivPtr; + +extern _X_EXPORT DevPrivateKey rrPrivKey; + +#define rrGetScrPriv(pScr) ((rrScrPrivPtr)dixLookupPrivate(&(pScr)->devPrivates, rrPrivKey)) +#define rrScrPriv(pScr) rrScrPrivPtr pScrPriv = rrGetScrPriv(pScr) +#define SetRRScreen(s,p) dixSetPrivate(&(s)->devPrivates, rrPrivKey, p) + +/* + * each window has a list of clients requesting + * RRNotify events. Each client has a resource + * for each window it selects RRNotify input for, + * this resource is used to delete the RRNotifyRec + * entry from the per-window queue. + */ + +typedef struct _RREvent *RREventPtr; + +typedef struct _RREvent { + RREventPtr next; + ClientPtr client; + WindowPtr window; + XID clientResource; + int mask; +} RREventRec; + +typedef struct _RRTimes { + TimeStamp setTime; + TimeStamp configTime; +} RRTimesRec, *RRTimesPtr; + +typedef struct _RRClient { + int major_version; + int minor_version; +/* RRTimesRec times[0]; */ +} RRClientRec, *RRClientPtr; + +extern _X_EXPORT RESTYPE RRClientType, RREventType; /* resource types for event masks */ +extern _X_EXPORT DevPrivateKey RRClientPrivateKey; +extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType; + +#define VERIFY_RR_OUTPUT(id, ptr, a)\ + {\ + int rc = dixLookupResourceByType((pointer *)&(ptr), id,\ + RROutputType, client, a);\ + if (rc != Success) {\ + client->errorValue = id;\ + return rc;\ + }\ + } + +#define VERIFY_RR_CRTC(id, ptr, a)\ + {\ + int rc = dixLookupResourceByType((pointer *)&(ptr), id,\ + RRCrtcType, client, a);\ + if (rc != Success) {\ + client->errorValue = id;\ + return rc;\ + }\ + } + +#define VERIFY_RR_MODE(id, ptr, a)\ + {\ + int rc = dixLookupResourceByType((pointer *)&(ptr), id,\ + RRModeType, client, a);\ + if (rc != Success) {\ + client->errorValue = id;\ + return rc;\ + }\ + } + +#define GetRRClient(pClient) ((RRClientPtr)dixLookupPrivate(&(pClient)->devPrivates, RRClientPrivateKey)) +#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient) + +/* Initialize the extension */ +extern _X_EXPORT void +RRExtensionInit (void); + +#ifdef RANDR_12_INTERFACE +/* + * Set the range of sizes for the screen + */ +extern _X_EXPORT void +RRScreenSetSizeRange (ScreenPtr pScreen, + CARD16 minWidth, + CARD16 minHeight, + CARD16 maxWidth, + CARD16 maxHeight); +#endif + +/* rrscreen.c */ +/* + * Notify the extension that the screen size has been changed. + * The driver is responsible for calling this whenever it has changed + * the size of the screen + */ +extern _X_EXPORT void +RRScreenSizeNotify (ScreenPtr pScreen); + +/* + * Request that the screen be resized + */ +extern _X_EXPORT Bool +RRScreenSizeSet (ScreenPtr pScreen, + CARD16 width, + CARD16 height, + CARD32 mmWidth, + CARD32 mmHeight); + +/* + * Send ConfigureNotify event to root window when 'something' happens + */ +extern _X_EXPORT void +RRSendConfigNotify (ScreenPtr pScreen); + +/* + * screen dispatch + */ +extern _X_EXPORT int +ProcRRGetScreenSizeRange (ClientPtr client); + +extern _X_EXPORT int +ProcRRSetScreenSize (ClientPtr client); + +extern _X_EXPORT int +ProcRRGetScreenResources (ClientPtr client); + +extern _X_EXPORT int +ProcRRGetScreenResourcesCurrent (ClientPtr client); + +extern _X_EXPORT int +ProcRRSetScreenConfig (ClientPtr client); + +extern _X_EXPORT int +ProcRRGetScreenInfo (ClientPtr client); + +/* + * Deliver a ScreenNotify event + */ +extern _X_EXPORT void +RRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen); + +/* mirandr.c */ +extern _X_EXPORT Bool +miRandRInit (ScreenPtr pScreen); + +extern _X_EXPORT Bool +miRRGetInfo (ScreenPtr pScreen, Rotation *rotations); + +extern _X_EXPORT Bool +miRRCrtcSet (ScreenPtr pScreen, + RRCrtcPtr crtc, + RRModePtr mode, + int x, + int y, + Rotation rotation, + int numOutput, + RROutputPtr *outputs); + +extern _X_EXPORT Bool +miRROutputSetProperty (ScreenPtr pScreen, + RROutputPtr output, + Atom property, + RRPropertyValuePtr value); + +extern _X_EXPORT Bool +miRROutputGetProperty (ScreenPtr pScreen, + RROutputPtr output, + Atom property); + +extern _X_EXPORT Bool +miRROutputValidateMode (ScreenPtr pScreen, + RROutputPtr output, + RRModePtr mode); + +extern _X_EXPORT void +miRRModeDestroy (ScreenPtr pScreen, + RRModePtr mode); + +/* randr.c */ +/* + * Send all pending events + */ +extern _X_EXPORT void +RRTellChanged (ScreenPtr pScreen); + +/* + * Poll the driver for changed information + */ +extern _X_EXPORT Bool +RRGetInfo (ScreenPtr pScreen, Bool force_query); + +extern _X_EXPORT Bool RRInit (void); + +extern _X_EXPORT Bool RRScreenInit(ScreenPtr pScreen); + +extern _X_EXPORT RROutputPtr +RRFirstOutput (ScreenPtr pScreen); + +extern _X_EXPORT Rotation +RRGetRotation (ScreenPtr pScreen); + +extern _X_EXPORT CARD16 +RRVerticalRefresh (xRRModeInfo *mode); + +#ifdef RANDR_10_INTERFACE +/* + * This is the old interface, deprecated but left + * around for compatibility + */ + +/* + * Then, register the specific size with the screen + */ + +extern _X_EXPORT RRScreenSizePtr +RRRegisterSize (ScreenPtr pScreen, + short width, + short height, + short mmWidth, + short mmHeight); + +extern _X_EXPORT Bool +RRRegisterRate (ScreenPtr pScreen, + RRScreenSizePtr pSize, + int rate); + +/* + * Finally, set the current configuration of the screen + */ + +extern _X_EXPORT void +RRSetCurrentConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize); + +extern _X_EXPORT Bool RRScreenInit (ScreenPtr pScreen); + +extern _X_EXPORT Rotation +RRGetRotation (ScreenPtr pScreen); + +#endif + +/* rrcrtc.c */ + +/* + * Notify the CRTC of some change; layoutChanged indicates that + * some position or size element changed + */ +extern _X_EXPORT void +RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged); + +/* + * Create a CRTC + */ +extern _X_EXPORT RRCrtcPtr +RRCrtcCreate (ScreenPtr pScreen, void *devPrivate); + +/* + * Set the allowed rotations on a CRTC + */ +extern _X_EXPORT void +RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations); + +/* + * Set whether transforms are allowed on a CRTC + */ +extern _X_EXPORT void +RRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms); + +/* + * Notify the extension that the Crtc has been reconfigured, + * the driver calls this whenever it has updated the mode + */ +extern _X_EXPORT Bool +RRCrtcNotify (RRCrtcPtr crtc, + RRModePtr mode, + int x, + int y, + Rotation rotation, + RRTransformPtr transform, + int numOutputs, + RROutputPtr *outputs); + +extern _X_EXPORT void +RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc); + +/* + * Request that the Crtc be reconfigured + */ +extern _X_EXPORT Bool +RRCrtcSet (RRCrtcPtr crtc, + RRModePtr mode, + int x, + int y, + Rotation rotation, + int numOutput, + RROutputPtr *outputs); + +/* + * Request that the Crtc gamma be changed + */ + +extern _X_EXPORT Bool +RRCrtcGammaSet (RRCrtcPtr crtc, + CARD16 *red, + CARD16 *green, + CARD16 *blue); + +/* + * Request current gamma back from the DDX (if possible). + * This includes gamma size. + */ + +extern _X_EXPORT Bool +RRCrtcGammaGet(RRCrtcPtr crtc); + +/* + * Notify the extension that the Crtc gamma has been changed + * The driver calls this whenever it has changed the gamma values + * in the RRCrtcRec + */ + +extern _X_EXPORT Bool +RRCrtcGammaNotify (RRCrtcPtr crtc); + +/* + * Set the size of the gamma table at server startup time + */ + +extern _X_EXPORT Bool +RRCrtcGammaSetSize (RRCrtcPtr crtc, + int size); + +/* + * Return the area of the frame buffer scanned out by the crtc, + * taking into account the current mode and rotation + */ + +extern _X_EXPORT void +RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height); + +/* + * Compute the complete transformation matrix including + * client-specified transform, rotation/reflection values and the crtc + * offset. + * + * Return TRUE if the resulting transform is not a simple translation. + */ +extern _X_EXPORT Bool +RRTransformCompute (int x, + int y, + int width, + int height, + Rotation rotation, + RRTransformPtr rr_transform, + + PictTransformPtr transform, + struct pict_f_transform *f_transform, + struct pict_f_transform *f_inverse); + +/* + * Return crtc transform + */ +extern _X_EXPORT RRTransformPtr +RRCrtcGetTransform (RRCrtcPtr crtc); + +/* + * Check whether the pending and current transforms are the same + */ +extern _X_EXPORT Bool +RRCrtcPendingTransform (RRCrtcPtr crtc); + +/* + * Destroy a Crtc at shutdown + */ +extern _X_EXPORT void +RRCrtcDestroy (RRCrtcPtr crtc); + + +/* + * Set the pending CRTC transformation + */ + +extern _X_EXPORT int +RRCrtcTransformSet (RRCrtcPtr crtc, + PictTransformPtr transform, + struct pict_f_transform *f_transform, + struct pict_f_transform *f_inverse, + char *filter, + int filter_len, + xFixed *params, + int nparams); + +/* + * Initialize crtc type + */ +extern _X_EXPORT Bool +RRCrtcInit (void); + +/* + * Crtc dispatch + */ + +extern _X_EXPORT int +ProcRRGetCrtcInfo (ClientPtr client); + +extern _X_EXPORT int +ProcRRSetCrtcConfig (ClientPtr client); + +extern _X_EXPORT int +ProcRRGetCrtcGammaSize (ClientPtr client); + +extern _X_EXPORT int +ProcRRGetCrtcGamma (ClientPtr client); + +extern _X_EXPORT int +ProcRRSetCrtcGamma (ClientPtr client); + +extern _X_EXPORT int +ProcRRSetCrtcTransform (ClientPtr client); + +extern _X_EXPORT int +ProcRRGetCrtcTransform (ClientPtr client); + +int +ProcRRGetPanning (ClientPtr client); + +int +ProcRRSetPanning (ClientPtr client); + +/* rrdispatch.c */ +extern _X_EXPORT Bool +RRClientKnowsRates (ClientPtr pClient); + +/* rrmode.c */ +/* + * Find, and if necessary, create a mode + */ + +extern _X_EXPORT RRModePtr +RRModeGet (xRRModeInfo *modeInfo, + const char *name); + +/* + * Destroy a mode. + */ + +extern _X_EXPORT void +RRModeDestroy (RRModePtr mode); + +/* + * Return a list of modes that are valid for some output in pScreen + */ +extern _X_EXPORT RRModePtr * +RRModesForScreen (ScreenPtr pScreen, int *num_ret); + +/* + * Initialize mode type + */ +extern _X_EXPORT Bool +RRModeInit (void); + +extern _X_EXPORT int +ProcRRCreateMode (ClientPtr client); + +extern _X_EXPORT int +ProcRRDestroyMode (ClientPtr client); + +extern _X_EXPORT int +ProcRRAddOutputMode (ClientPtr client); + +extern _X_EXPORT int +ProcRRDeleteOutputMode (ClientPtr client); + +/* rroutput.c */ + +/* + * Notify the output of some change. configChanged indicates whether + * any external configuration (mode list, clones, connected status) + * has changed, or whether the change was strictly internal + * (which crtc is in use) + */ +extern _X_EXPORT void +RROutputChanged (RROutputPtr output, Bool configChanged); + +/* + * Create an output + */ + +extern _X_EXPORT RROutputPtr +RROutputCreate (ScreenPtr pScreen, + const char *name, + int nameLength, + void *devPrivate); + +/* + * Notify extension that output parameters have been changed + */ +extern _X_EXPORT Bool +RROutputSetClones (RROutputPtr output, + RROutputPtr *clones, + int numClones); + +extern _X_EXPORT Bool +RROutputSetModes (RROutputPtr output, + RRModePtr *modes, + int numModes, + int numPreferred); + +extern _X_EXPORT int +RROutputAddUserMode (RROutputPtr output, + RRModePtr mode); + +extern _X_EXPORT int +RROutputDeleteUserMode (RROutputPtr output, + RRModePtr mode); + +extern _X_EXPORT Bool +RROutputSetCrtcs (RROutputPtr output, + RRCrtcPtr *crtcs, + int numCrtcs); + +extern _X_EXPORT Bool +RROutputSetConnection (RROutputPtr output, + CARD8 connection); + +extern _X_EXPORT Bool +RROutputSetSubpixelOrder (RROutputPtr output, + int subpixelOrder); + +extern _X_EXPORT Bool +RROutputSetPhysicalSize (RROutputPtr output, + int mmWidth, + int mmHeight); + +extern _X_EXPORT void +RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output); + +extern _X_EXPORT void +RROutputDestroy (RROutputPtr output); + +extern _X_EXPORT int +ProcRRGetOutputInfo (ClientPtr client); + +extern _X_EXPORT int +ProcRRSetOutputPrimary (ClientPtr client); + +extern _X_EXPORT int +ProcRRGetOutputPrimary (ClientPtr client); + +/* + * Initialize output type + */ +extern _X_EXPORT Bool +RROutputInit (void); + +/* rrpointer.c */ +extern _X_EXPORT void +RRPointerMoved (ScreenPtr pScreen, int x, int y); + +extern _X_EXPORT void +RRPointerScreenConfigured (ScreenPtr pScreen); + +/* rrproperty.c */ + +extern _X_EXPORT void +RRDeleteAllOutputProperties (RROutputPtr output); + +extern _X_EXPORT RRPropertyValuePtr +RRGetOutputProperty (RROutputPtr output, Atom property, Bool pending); + +extern _X_EXPORT RRPropertyPtr +RRQueryOutputProperty (RROutputPtr output, Atom property); + +extern _X_EXPORT void +RRDeleteOutputProperty (RROutputPtr output, Atom property); + +extern _X_EXPORT Bool +RRPostPendingProperties (RROutputPtr output); + +extern _X_EXPORT int +RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type, + int format, int mode, unsigned long len, + pointer value, Bool sendevent, Bool pending); + +extern _X_EXPORT int +RRConfigureOutputProperty (RROutputPtr output, Atom property, + Bool pending, Bool range, Bool immutable, + int num_values, INT32 *values); +extern _X_EXPORT int +ProcRRChangeOutputProperty (ClientPtr client); + +extern _X_EXPORT int +ProcRRGetOutputProperty (ClientPtr client); + +extern _X_EXPORT int +ProcRRListOutputProperties (ClientPtr client); + +extern _X_EXPORT int +ProcRRQueryOutputProperty (ClientPtr client); + +extern _X_EXPORT int +ProcRRConfigureOutputProperty (ClientPtr client); + +extern _X_EXPORT int +ProcRRDeleteOutputProperty (ClientPtr client); + +/* rrxinerama.c */ +#ifdef XINERAMA +extern _X_EXPORT void +RRXineramaExtensionInit(void); +#endif + +#endif /* _RANDRSTR_H_ */ + +/* + +randr extension implementation structure + +Query state: + ProcRRGetScreenInfo/ProcRRGetScreenResources + RRGetInfo + + • Request configuration from driver, either 1.0 or 1.2 style + • These functions only record state changes, all + other actions are pended until RRTellChanged is called + + ->rrGetInfo + 1.0: + RRRegisterSize + RRRegisterRate + RRSetCurrentConfig + 1.2: + RRScreenSetSizeRange + RROutputSetCrtcs + RRModeGet + RROutputSetModes + RROutputSetConnection + RROutputSetSubpixelOrder + RROutputSetClones + RRCrtcNotify + + • Must delay scanning configuration until after ->rrGetInfo returns + because some drivers will call SetCurrentConfig in the middle + of the ->rrGetInfo operation. + + 1.0: + + • Scan old configuration, mirror to new structures + + RRScanOldConfig + RRCrtcCreate + RROutputCreate + RROutputSetCrtcs + RROutputSetConnection + RROutputSetSubpixelOrder + RROldModeAdd • This adds modes one-at-a-time + RRModeGet + RRCrtcNotify + + • send events, reset pointer if necessary + + RRTellChanged + WalkTree (sending events) + + • when layout has changed: + RRPointerScreenConfigured + RRSendConfigNotify + +Asynchronous state setting (1.2 only) + When setting state asynchronously, the driver invokes the + ->rrGetInfo function and then calls RRTellChanged to flush + the changes to the clients and reset pointer if necessary + +Set state + + ProcRRSetScreenConfig + RRCrtcSet + 1.2: + ->rrCrtcSet + RRCrtcNotify + 1.0: + ->rrSetConfig + RRCrtcNotify + RRTellChanged + */ diff --git a/xorg-server/randr/rrcrtc.c b/xorg-server/randr/rrcrtc.c index 2544903e9..278b7ff77 100644 --- a/xorg-server/randr/rrcrtc.c +++ b/xorg-server/randr/rrcrtc.c @@ -254,7 +254,6 @@ RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc) ce.type = RRNotify + RREventBase; ce.subCode = RRNotify_CrtcChange; - ce.sequenceNumber = client->sequence; ce.timestamp = pScrPriv->lastSetTime.milliseconds; ce.window = pWin->drawable.id; ce.crtc = crtc->id; @@ -635,6 +634,7 @@ RRCrtcInit (void) RRCrtcType = CreateNewResourceType (RRCrtcDestroyResource, "CRTC"); if (!RRCrtcType) return FALSE; + SetResourceTypeErrorValue(RRCrtcType, RRErrorBase + BadRRCrtc); return TRUE; } @@ -807,7 +807,7 @@ ProcRRSetCrtcConfig (ClientPtr client) { if (outputs) free(outputs); - return (rc == BadValue) ? RRErrorBase + BadRROutput : rc; + return rc; } /* validate crtc for this output */ for (j = 0; j < outputs[i]->numCrtcs; j++) diff --git a/xorg-server/randr/rrmode.c b/xorg-server/randr/rrmode.c index 7412e6f3e..a28d9ca6c 100644 --- a/xorg-server/randr/rrmode.c +++ b/xorg-server/randr/rrmode.c @@ -268,6 +268,7 @@ RRModeInit (void) RRModeType = CreateNewResourceType (RRModeDestroyResource, "MODE"); if (!RRModeType) return FALSE; + SetResourceTypeErrorValue(RRModeType, RRErrorBase + BadRRMode); return TRUE; } diff --git a/xorg-server/randr/rroutput.c b/xorg-server/randr/rroutput.c index a65b45912..51ebaa861 100644 --- a/xorg-server/randr/rroutput.c +++ b/xorg-server/randr/rroutput.c @@ -337,7 +337,6 @@ RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output) oe.type = RRNotify + RREventBase; oe.subCode = RRNotify_OutputChange; - oe.sequenceNumber = client->sequence; oe.timestamp = pScrPriv->lastSetTime.milliseconds; oe.configTimestamp = pScrPriv->lastConfigTime.milliseconds; oe.window = pWin->drawable.id; @@ -424,6 +423,7 @@ RROutputInit (void) RROutputType = CreateNewResourceType (RROutputDestroyResource, "OUTPUT"); if (!RROutputType) return FALSE; + SetResourceTypeErrorValue(RROutputType, RRErrorBase + BadRROutput); return TRUE; } diff --git a/xorg-server/randr/rrproperty.c b/xorg-server/randr/rrproperty.c index 20f07f42a..898730eef 100644 --- a/xorg-server/randr/rrproperty.c +++ b/xorg-server/randr/rrproperty.c @@ -29,7 +29,6 @@ DeliverPropertyEvent(WindowPtr pWin, void *value) { xRROutputPropertyNotifyEvent *event = value; RREventPtr *pHead, pRREvent; - ClientPtr client; dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, RREventType, serverClient, DixReadAccess); @@ -38,14 +37,9 @@ DeliverPropertyEvent(WindowPtr pWin, void *value) for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) { - client = pRREvent->client; - if (client == serverClient || client->clientGone) - continue; - if (!(pRREvent->mask & RROutputPropertyNotifyMask)) continue; - event->sequenceNumber = client->sequence; event->window = pRREvent->window->drawable.id; WriteEventsToClient(pRREvent->client, 1, (xEvent *)event); } diff --git a/xorg-server/randr/rrscreen.c b/xorg-server/randr/rrscreen.c index 526e95177..a5e01dced 100644 --- a/xorg-server/randr/rrscreen.c +++ b/xorg-server/randr/rrscreen.c @@ -102,13 +102,11 @@ RRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen) se.type = RRScreenChangeNotify + RREventBase; se.rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0); se.timestamp = pScrPriv->lastSetTime.milliseconds; - se.sequenceNumber = client->sequence; se.configTimestamp = pScrPriv->lastConfigTime.milliseconds; se.root = pRoot->drawable.id; se.window = pWin->drawable.id; se.subpixelOrder = PictureGetSubpixelOrder (pScreen); - se.sequenceNumber = client->sequence; se.sizeID = RR10CurrentSizeID (pScreen); if (se.rotation & (RR_Rotate_90 | RR_Rotate_270)) { diff --git a/xorg-server/record/record.c b/xorg-server/record/record.c index f79a5a889..a2698d1f3 100644 --- a/xorg-server/record/record.c +++ b/xorg-server/record/record.c @@ -58,7 +58,6 @@ and Jim Haggerty of Metheus. #include "protocol-versions.h" static RESTYPE RTContext; /* internal resource type for Record contexts */ -static int RecordErrorBase; /* first Record error number */ /* How many bytes of protocol data to buffer in a context. Don't set to less * than 32. @@ -133,7 +132,7 @@ static int numEnabledRCAPs; int rc = dixLookupResourceByType((pointer *)&(_pContext), _contextid, \ RTContext, _client, DixUseAccess); \ if (rc != Success) \ - return (rc == BadValue) ? RecordErrorBase + XRecordBadContext : rc; \ + return rc; \ } static int RecordDeleteContext( @@ -2911,7 +2910,7 @@ RecordExtensionInit(void) DeleteCallback(&ClientStateCallback, RecordAClientStateChange, NULL); return; } - RecordErrorBase = extentry->errorBase; + SetResourceTypeErrorValue(RTContext, extentry->errorBase + XRecordBadContext); } /* RecordExtensionInit */ diff --git a/xorg-server/render/animcur.c b/xorg-server/render/animcur.c index dd44bd17f..13f09d387 100644 --- a/xorg-server/render/animcur.c +++ b/xorg-server/render/animcur.c @@ -58,10 +58,6 @@ typedef struct _AnimCur { } AnimCurRec, *AnimCurPtr; typedef struct _AnimScrPriv { - CursorPtr pCursor; - int elt; - CARD32 time; - CloseScreenProcPtr CloseScreen; ScreenBlockHandlerProcPtr BlockHandler; @@ -74,31 +70,18 @@ typedef struct _AnimScrPriv { RecolorCursorProcPtr RecolorCursor; } AnimCurScreenRec, *AnimCurScreenPtr; -typedef struct _AnimCurState { - CursorPtr pCursor; - ScreenPtr pScreen; - int elt; - CARD32 time; -} AnimCurStateRec, *AnimCurStatePtr; - -/* What a waste. But we need an API change to alloc it per device only. */ -static AnimCurStateRec animCurState[MAXDEVICES]; - static unsigned char empty[4]; static CursorBits animCursorBits = { empty, empty, 2, 1, 1, 0, 0, 1 }; -static int AnimCurGeneration; - static int AnimCurScreenPrivateKeyIndex; static DevPrivateKey AnimCurScreenPrivateKey = &AnimCurScreenPrivateKeyIndex; #define IsAnimCur(c) ((c) && ((c)->bits == &animCursorBits)) #define GetAnimCur(c) ((AnimCurPtr) ((c) + 1)) #define GetAnimCurScreen(s) ((AnimCurScreenPtr)dixLookupPrivate(&(s)->devPrivates, AnimCurScreenPrivateKey)) -#define GetAnimCurScreenIfSet(s) GetAnimCurScreen(s) #define SetAnimCurScreen(s,p) dixSetPrivate(&(s)->devPrivates, AnimCurScreenPrivateKey, p) #define Wrap(as,s,elt,func) (((as)->elt = (s)->elt), (s)->elt = func) @@ -172,14 +155,14 @@ AnimCurScreenBlockHandler (int screenNum, for (dev = inputInfo.devices; dev; dev = dev->next) { - if (IsPointerDevice(dev) && pScreen == animCurState[dev->id].pScreen) + if (IsPointerDevice(dev) && pScreen == dev->spriteInfo->anim.pScreen) { if (!now) now = GetTimeInMillis (); - if ((INT32) (now - animCurState[dev->id].time) >= 0) + if ((INT32) (now - dev->spriteInfo->anim.time) >= 0) { - AnimCurPtr ac = GetAnimCur(animCurState[dev->id].pCursor); - int elt = (animCurState[dev->id].elt + 1) % ac->nelt; + AnimCurPtr ac = GetAnimCur(dev->spriteInfo->anim.pCursor); + int elt = (dev->spriteInfo->anim.elt + 1) % ac->nelt; DisplayCursorProcPtr DisplayCursor; /* @@ -195,12 +178,12 @@ AnimCurScreenBlockHandler (int screenNum, as->DisplayCursor = pScreen->DisplayCursor; pScreen->DisplayCursor = DisplayCursor; - animCurState[dev->id].elt = elt; - animCurState[dev->id].time = now + ac->elts[elt].delay; + dev->spriteInfo->anim.elt = elt; + dev->spriteInfo->anim.time = now + ac->elts[elt].delay; } - if (soonest > animCurState[dev->id].time) - soonest = animCurState[dev->id].time; + if (soonest > dev->spriteInfo->anim.time) + soonest = dev->spriteInfo->anim.time; } } @@ -223,7 +206,7 @@ AnimCurDisplayCursor (DeviceIntPtr pDev, Unwrap (as, pScreen, DisplayCursor); if (IsAnimCur(pCursor)) { - if (pCursor != animCurState[pDev->id].pCursor) + if (pCursor != pDev->spriteInfo->anim.pCursor) { AnimCurPtr ac = GetAnimCur(pCursor); @@ -231,10 +214,10 @@ AnimCurDisplayCursor (DeviceIntPtr pDev, (pDev, pScreen, ac->elts[0].pCursor); if (ret) { - animCurState[pDev->id].elt = 0; - animCurState[pDev->id].time = GetTimeInMillis () + ac->elts[0].delay; - animCurState[pDev->id].pCursor = pCursor; - animCurState[pDev->id].pScreen = pScreen; + pDev->spriteInfo->anim.elt = 0; + pDev->spriteInfo->anim.time = GetTimeInMillis () + ac->elts[0].delay; + pDev->spriteInfo->anim.pCursor = pCursor; + pDev->spriteInfo->anim.pScreen = pScreen; } } else @@ -242,8 +225,8 @@ AnimCurDisplayCursor (DeviceIntPtr pDev, } else { - animCurState[pDev->id].pCursor = 0; - animCurState[pDev->id].pScreen = 0; + pDev->spriteInfo->anim.pCursor = 0; + pDev->spriteInfo->anim.pScreen = 0; ret = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor); } Wrap (as, pScreen, DisplayCursor, AnimCurDisplayCursor); @@ -261,8 +244,8 @@ AnimCurSetCursorPosition (DeviceIntPtr pDev, Bool ret; Unwrap (as, pScreen, SetCursorPosition); - if (animCurState[pDev->id].pCursor) - animCurState[pDev->id].pScreen = pScreen; + if (pDev->spriteInfo->anim.pCursor) + pDev->spriteInfo->anim.pScreen = pScreen; ret = (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent); Wrap (as, pScreen, SetCursorPosition, AnimCurSetCursorPosition); return ret; @@ -327,7 +310,7 @@ AnimCurRecolorCursor (DeviceIntPtr pDev, for (i = 0; i < ac->nelt; i++) (*pScreen->RecolorCursor) (pDev, pScreen, ac->elts[i].pCursor, displayed && - animCurState[pDev->id].elt == i); + pDev->spriteInfo->anim.elt == i); } else (*pScreen->RecolorCursor) (pDev, pScreen, pCursor, displayed); @@ -339,17 +322,6 @@ AnimCurInit (ScreenPtr pScreen) { AnimCurScreenPtr as; - if (AnimCurGeneration != serverGeneration) - { - int i; - AnimCurGeneration = serverGeneration; - for (i = 0; i < MAXDEVICES; i++) { - animCurState[i].pCursor = 0; - animCurState[i].pScreen = 0; - animCurState[i].elt = 0; - animCurState[i].time = 0; - } - } as = (AnimCurScreenPtr) malloc(sizeof (AnimCurScreenRec)); if (!as) return FALSE; @@ -375,7 +347,7 @@ AnimCursorCreate (CursorPtr *cursors, CARD32 *deltas, int ncursor, CursorPtr *pp AnimCurPtr ac; for (i = 0; i < screenInfo.numScreens; i++) - if (!GetAnimCurScreenIfSet (screenInfo.screens[i])) + if (!GetAnimCurScreen (screenInfo.screens[i])) return BadImplementation; for (i = 0; i < ncursor; i++) diff --git a/xorg-server/render/picture.c b/xorg-server/render/picture.c index 12d1cee93..a67a95888 100644 --- a/xorg-server/render/picture.c +++ b/xorg-server/render/picture.c @@ -1115,7 +1115,6 @@ ChangePicture (PicturePtr pPicture, if (error != Success) { client->errorValue = pid; - error = (error == BadValue) ? RenderErrBase + BadPicture : error; break; } if (pAlpha->pDrawable == NULL || @@ -1176,7 +1175,6 @@ ChangePicture (PicturePtr pPicture, if (error != Success) { client->errorValue = pid; - error = (error == BadValue) ? BadPixmap : error; break; } } diff --git a/xorg-server/render/picturestr.h b/xorg-server/render/picturestr.h index 6b265d77f..7d04deacf 100644 --- a/xorg-server/render/picturestr.h +++ b/xorg-server/render/picturestr.h @@ -412,7 +412,7 @@ extern _X_EXPORT RESTYPE GlyphSetType; int rc = dixLookupResourceByType((pointer)&(pPicture), pid,\ PictureType, client, mode);\ if (rc != Success)\ - return (rc == BadValue) ? RenderErrBase + BadPicture : rc;\ + return rc;\ } #define VERIFY_ALPHA(pPicture, pid, client, mode) {\ diff --git a/xorg-server/render/render.c b/xorg-server/render/render.c index 9aabcfb20..600ffc645 100644 --- a/xorg-server/render/render.c +++ b/xorg-server/render/render.c @@ -1,3370 +1,3382 @@ -/* - * - * Copyright © 2000 SuSE, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of SuSE not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. SuSE makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE - * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Keith Packard, SuSE, Inc. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#include "misc.h" -#include "os.h" -#include "dixstruct.h" -#include "resource.h" -#include "scrnintstr.h" -#include "windowstr.h" -#include "pixmapstr.h" -#include "colormapst.h" -#include "extnsionst.h" -#include "servermd.h" -#include <X11/extensions/render.h> -#include <X11/extensions/renderproto.h> -#include "picturestr.h" -#include "glyphstr.h" -#include <X11/Xfuncproto.h> -#include "cursorstr.h" -#include "xace.h" -#include "protocol-versions.h" - -#if HAVE_STDINT_H -#include <stdint.h> -#elif !defined(UINT32_MAX) -#define UINT32_MAX 0xffffffffU -#endif - -static int ProcRenderQueryVersion (ClientPtr pClient); -static int ProcRenderQueryPictFormats (ClientPtr pClient); -static int ProcRenderQueryPictIndexValues (ClientPtr pClient); -static int ProcRenderQueryDithers (ClientPtr pClient); -static int ProcRenderCreatePicture (ClientPtr pClient); -static int ProcRenderChangePicture (ClientPtr pClient); -static int ProcRenderSetPictureClipRectangles (ClientPtr pClient); -static int ProcRenderFreePicture (ClientPtr pClient); -static int ProcRenderComposite (ClientPtr pClient); -static int ProcRenderScale (ClientPtr pClient); -static int ProcRenderTrapezoids (ClientPtr pClient); -static int ProcRenderTriangles (ClientPtr pClient); -static int ProcRenderTriStrip (ClientPtr pClient); -static int ProcRenderTriFan (ClientPtr pClient); -static int ProcRenderColorTrapezoids (ClientPtr pClient); -static int ProcRenderColorTriangles (ClientPtr pClient); -static int ProcRenderTransform (ClientPtr pClient); -static int ProcRenderCreateGlyphSet (ClientPtr pClient); -static int ProcRenderReferenceGlyphSet (ClientPtr pClient); -static int ProcRenderFreeGlyphSet (ClientPtr pClient); -static int ProcRenderAddGlyphs (ClientPtr pClient); -static int ProcRenderAddGlyphsFromPicture (ClientPtr pClient); -static int ProcRenderFreeGlyphs (ClientPtr pClient); -static int ProcRenderCompositeGlyphs (ClientPtr pClient); -static int ProcRenderFillRectangles (ClientPtr pClient); -static int ProcRenderCreateCursor (ClientPtr pClient); -static int ProcRenderSetPictureTransform (ClientPtr pClient); -static int ProcRenderQueryFilters (ClientPtr pClient); -static int ProcRenderSetPictureFilter (ClientPtr pClient); -static int ProcRenderCreateAnimCursor (ClientPtr pClient); -static int ProcRenderAddTraps (ClientPtr pClient); -static int ProcRenderCreateSolidFill (ClientPtr pClient); -static int ProcRenderCreateLinearGradient (ClientPtr pClient); -static int ProcRenderCreateRadialGradient (ClientPtr pClient); -static int ProcRenderCreateConicalGradient (ClientPtr pClient); - -static int ProcRenderDispatch (ClientPtr pClient); - -static int SProcRenderQueryVersion (ClientPtr pClient); -static int SProcRenderQueryPictFormats (ClientPtr pClient); -static int SProcRenderQueryPictIndexValues (ClientPtr pClient); -static int SProcRenderQueryDithers (ClientPtr pClient); -static int SProcRenderCreatePicture (ClientPtr pClient); -static int SProcRenderChangePicture (ClientPtr pClient); -static int SProcRenderSetPictureClipRectangles (ClientPtr pClient); -static int SProcRenderFreePicture (ClientPtr pClient); -static int SProcRenderComposite (ClientPtr pClient); -static int SProcRenderScale (ClientPtr pClient); -static int SProcRenderTrapezoids (ClientPtr pClient); -static int SProcRenderTriangles (ClientPtr pClient); -static int SProcRenderTriStrip (ClientPtr pClient); -static int SProcRenderTriFan (ClientPtr pClient); -static int SProcRenderColorTrapezoids (ClientPtr pClient); -static int SProcRenderColorTriangles (ClientPtr pClient); -static int SProcRenderTransform (ClientPtr pClient); -static int SProcRenderCreateGlyphSet (ClientPtr pClient); -static int SProcRenderReferenceGlyphSet (ClientPtr pClient); -static int SProcRenderFreeGlyphSet (ClientPtr pClient); -static int SProcRenderAddGlyphs (ClientPtr pClient); -static int SProcRenderAddGlyphsFromPicture (ClientPtr pClient); -static int SProcRenderFreeGlyphs (ClientPtr pClient); -static int SProcRenderCompositeGlyphs (ClientPtr pClient); -static int SProcRenderFillRectangles (ClientPtr pClient); -static int SProcRenderCreateCursor (ClientPtr pClient); -static int SProcRenderSetPictureTransform (ClientPtr pClient); -static int SProcRenderQueryFilters (ClientPtr pClient); -static int SProcRenderSetPictureFilter (ClientPtr pClient); -static int SProcRenderCreateAnimCursor (ClientPtr pClient); -static int SProcRenderAddTraps (ClientPtr pClient); -static int SProcRenderCreateSolidFill (ClientPtr pClient); -static int SProcRenderCreateLinearGradient (ClientPtr pClient); -static int SProcRenderCreateRadialGradient (ClientPtr pClient); -static int SProcRenderCreateConicalGradient (ClientPtr pClient); - -static int SProcRenderDispatch (ClientPtr pClient); - -int (*ProcRenderVector[RenderNumberRequests])(ClientPtr) = { - ProcRenderQueryVersion, - ProcRenderQueryPictFormats, - ProcRenderQueryPictIndexValues, - ProcRenderQueryDithers, - ProcRenderCreatePicture, - ProcRenderChangePicture, - ProcRenderSetPictureClipRectangles, - ProcRenderFreePicture, - ProcRenderComposite, - ProcRenderScale, - ProcRenderTrapezoids, - ProcRenderTriangles, - ProcRenderTriStrip, - ProcRenderTriFan, - ProcRenderColorTrapezoids, - ProcRenderColorTriangles, - ProcRenderTransform, - ProcRenderCreateGlyphSet, - ProcRenderReferenceGlyphSet, - ProcRenderFreeGlyphSet, - ProcRenderAddGlyphs, - ProcRenderAddGlyphsFromPicture, - ProcRenderFreeGlyphs, - ProcRenderCompositeGlyphs, - ProcRenderCompositeGlyphs, - ProcRenderCompositeGlyphs, - ProcRenderFillRectangles, - ProcRenderCreateCursor, - ProcRenderSetPictureTransform, - ProcRenderQueryFilters, - ProcRenderSetPictureFilter, - ProcRenderCreateAnimCursor, - ProcRenderAddTraps, - ProcRenderCreateSolidFill, - ProcRenderCreateLinearGradient, - ProcRenderCreateRadialGradient, - ProcRenderCreateConicalGradient -}; - -int (*SProcRenderVector[RenderNumberRequests])(ClientPtr) = { - SProcRenderQueryVersion, - SProcRenderQueryPictFormats, - SProcRenderQueryPictIndexValues, - SProcRenderQueryDithers, - SProcRenderCreatePicture, - SProcRenderChangePicture, - SProcRenderSetPictureClipRectangles, - SProcRenderFreePicture, - SProcRenderComposite, - SProcRenderScale, - SProcRenderTrapezoids, - SProcRenderTriangles, - SProcRenderTriStrip, - SProcRenderTriFan, - SProcRenderColorTrapezoids, - SProcRenderColorTriangles, - SProcRenderTransform, - SProcRenderCreateGlyphSet, - SProcRenderReferenceGlyphSet, - SProcRenderFreeGlyphSet, - SProcRenderAddGlyphs, - SProcRenderAddGlyphsFromPicture, - SProcRenderFreeGlyphs, - SProcRenderCompositeGlyphs, - SProcRenderCompositeGlyphs, - SProcRenderCompositeGlyphs, - SProcRenderFillRectangles, - SProcRenderCreateCursor, - SProcRenderSetPictureTransform, - SProcRenderQueryFilters, - SProcRenderSetPictureFilter, - SProcRenderCreateAnimCursor, - SProcRenderAddTraps, - SProcRenderCreateSolidFill, - SProcRenderCreateLinearGradient, - SProcRenderCreateRadialGradient, - SProcRenderCreateConicalGradient -}; - -int RenderErrBase; -static int RenderClientPrivateKeyIndex; -DevPrivateKey RenderClientPrivateKey = &RenderClientPrivateKeyIndex; - -typedef struct _RenderClient { - int major_version; - int minor_version; -} RenderClientRec, *RenderClientPtr; - -#define GetRenderClient(pClient) ((RenderClientPtr)dixLookupPrivate(&(pClient)->devPrivates, RenderClientPrivateKey)) - -static void -RenderClientCallback (CallbackListPtr *list, - pointer closure, - pointer data) -{ - NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; - ClientPtr pClient = clientinfo->client; - RenderClientPtr pRenderClient = GetRenderClient (pClient); - - pRenderClient->major_version = 0; - pRenderClient->minor_version = 0; -} - -void -RenderExtensionInit (void) -{ - ExtensionEntry *extEntry; - - if (!PictureType) - return; - if (!PictureFinishInit ()) - return; - if (!dixRequestPrivate(RenderClientPrivateKey, sizeof(RenderClientRec))) - return; - if (!AddCallback (&ClientStateCallback, RenderClientCallback, 0)) - return; - - extEntry = AddExtension (RENDER_NAME, 0, RenderNumberErrors, - ProcRenderDispatch, SProcRenderDispatch, - NULL, StandardMinorOpcode); - if (!extEntry) - return; - RenderErrBase = extEntry->errorBase; -} - -static int -ProcRenderQueryVersion (ClientPtr client) -{ - RenderClientPtr pRenderClient = GetRenderClient (client); - xRenderQueryVersionReply rep; - register int n; - REQUEST(xRenderQueryVersionReq); - - pRenderClient->major_version = stuff->majorVersion; - pRenderClient->minor_version = stuff->minorVersion; - - REQUEST_SIZE_MATCH(xRenderQueryVersionReq); - memset(&rep, 0, sizeof(xRenderQueryVersionReply)); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - if ((stuff->majorVersion * 1000 + stuff->minorVersion) < - (SERVER_RENDER_MAJOR_VERSION * 1000 + SERVER_RENDER_MINOR_VERSION)) - { - rep.majorVersion = stuff->majorVersion; - rep.minorVersion = stuff->minorVersion; - } else - { - rep.majorVersion = SERVER_RENDER_MAJOR_VERSION; - rep.minorVersion = SERVER_RENDER_MINOR_VERSION; - } - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.majorVersion, n); - swapl(&rep.minorVersion, n); - } - WriteToClient(client, sizeof(xRenderQueryVersionReply), (char *)&rep); - return Success; -} - -static VisualPtr -findVisual (ScreenPtr pScreen, VisualID vid) -{ - VisualPtr pVisual; - int v; - - for (v = 0; v < pScreen->numVisuals; v++) - { - pVisual = pScreen->visuals + v; - if (pVisual->vid == vid) - return pVisual; - } - return 0; -} - -static int -ProcRenderQueryPictFormats (ClientPtr client) -{ - RenderClientPtr pRenderClient = GetRenderClient (client); - xRenderQueryPictFormatsReply *reply; - xPictScreen *pictScreen; - xPictDepth *pictDepth; - xPictVisual *pictVisual; - xPictFormInfo *pictForm; - CARD32 *pictSubpixel; - ScreenPtr pScreen; - VisualPtr pVisual; - DepthPtr pDepth; - int v, d; - PictureScreenPtr ps; - PictFormatPtr pFormat; - int nformat; - int ndepth; - int nvisual; - int rlength; - int s; - int n; - int numScreens; - int numSubpixel; -/* REQUEST(xRenderQueryPictFormatsReq); */ - - REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq); - -#ifdef PANORAMIX - if (noPanoramiXExtension) - numScreens = screenInfo.numScreens; - else - numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; -#else - numScreens = screenInfo.numScreens; -#endif - ndepth = nformat = nvisual = 0; - for (s = 0; s < numScreens; s++) - { - pScreen = screenInfo.screens[s]; - for (d = 0; d < pScreen->numDepths; d++) - { - pDepth = pScreen->allowedDepths + d; - ++ndepth; - - for (v = 0; v < pDepth->numVids; v++) - { - pVisual = findVisual (pScreen, pDepth->vids[v]); - if (pVisual && PictureMatchVisual (pScreen, pDepth->depth, pVisual)) - ++nvisual; - } - } - ps = GetPictureScreenIfSet(pScreen); - if (ps) - nformat += ps->nformats; - } - if (pRenderClient->major_version == 0 && pRenderClient->minor_version < 6) - numSubpixel = 0; - else - numSubpixel = numScreens; - - rlength = (sizeof (xRenderQueryPictFormatsReply) + - nformat * sizeof (xPictFormInfo) + - numScreens * sizeof (xPictScreen) + - ndepth * sizeof (xPictDepth) + - nvisual * sizeof (xPictVisual) + - numSubpixel * sizeof (CARD32)); - reply = (xRenderQueryPictFormatsReply *) calloc(1, rlength); - if (!reply) - return BadAlloc; - reply->type = X_Reply; - reply->sequenceNumber = client->sequence; - reply->length = bytes_to_int32(rlength - sizeof(xGenericReply)); - reply->numFormats = nformat; - reply->numScreens = numScreens; - reply->numDepths = ndepth; - reply->numVisuals = nvisual; - reply->numSubpixel = numSubpixel; - - pictForm = (xPictFormInfo *) (reply + 1); - - for (s = 0; s < numScreens; s++) - { - pScreen = screenInfo.screens[s]; - ps = GetPictureScreenIfSet(pScreen); - if (ps) - { - for (nformat = 0, pFormat = ps->formats; - nformat < ps->nformats; - nformat++, pFormat++) - { - pictForm->id = pFormat->id; - pictForm->type = pFormat->type; - pictForm->depth = pFormat->depth; - pictForm->direct.red = pFormat->direct.red; - pictForm->direct.redMask = pFormat->direct.redMask; - pictForm->direct.green = pFormat->direct.green; - pictForm->direct.greenMask = pFormat->direct.greenMask; - pictForm->direct.blue = pFormat->direct.blue; - pictForm->direct.blueMask = pFormat->direct.blueMask; - pictForm->direct.alpha = pFormat->direct.alpha; - pictForm->direct.alphaMask = pFormat->direct.alphaMask; - if (pFormat->type == PictTypeIndexed && pFormat->index.pColormap) - pictForm->colormap = pFormat->index.pColormap->mid; - else - pictForm->colormap = None; - if (client->swapped) - { - swapl (&pictForm->id, n); - swaps (&pictForm->direct.red, n); - swaps (&pictForm->direct.redMask, n); - swaps (&pictForm->direct.green, n); - swaps (&pictForm->direct.greenMask, n); - swaps (&pictForm->direct.blue, n); - swaps (&pictForm->direct.blueMask, n); - swaps (&pictForm->direct.alpha, n); - swaps (&pictForm->direct.alphaMask, n); - swapl (&pictForm->colormap, n); - } - pictForm++; - } - } - } - - pictScreen = (xPictScreen *) pictForm; - for (s = 0; s < numScreens; s++) - { - pScreen = screenInfo.screens[s]; - pictDepth = (xPictDepth *) (pictScreen + 1); - ndepth = 0; - for (d = 0; d < pScreen->numDepths; d++) - { - pictVisual = (xPictVisual *) (pictDepth + 1); - pDepth = pScreen->allowedDepths + d; - - nvisual = 0; - for (v = 0; v < pDepth->numVids; v++) - { - pVisual = findVisual (pScreen, pDepth->vids[v]); - if (pVisual && (pFormat = PictureMatchVisual (pScreen, - pDepth->depth, - pVisual))) - { - pictVisual->visual = pVisual->vid; - pictVisual->format = pFormat->id; - if (client->swapped) - { - swapl (&pictVisual->visual, n); - swapl (&pictVisual->format, n); - } - pictVisual++; - nvisual++; - } - } - pictDepth->depth = pDepth->depth; - pictDepth->nPictVisuals = nvisual; - if (client->swapped) - { - swaps (&pictDepth->nPictVisuals, n); - } - ndepth++; - pictDepth = (xPictDepth *) pictVisual; - } - pictScreen->nDepth = ndepth; - ps = GetPictureScreenIfSet(pScreen); - if (ps) - pictScreen->fallback = ps->fallback->id; - else - pictScreen->fallback = 0; - if (client->swapped) - { - swapl (&pictScreen->nDepth, n); - swapl (&pictScreen->fallback, n); - } - pictScreen = (xPictScreen *) pictDepth; - } - pictSubpixel = (CARD32 *) pictScreen; - - for (s = 0; s < numSubpixel; s++) - { - pScreen = screenInfo.screens[s]; - ps = GetPictureScreenIfSet(pScreen); - if (ps) - *pictSubpixel = ps->subpixel; - else - *pictSubpixel = SubPixelUnknown; - if (client->swapped) - { - swapl (pictSubpixel, n); - } - ++pictSubpixel; - } - - if (client->swapped) - { - swaps (&reply->sequenceNumber, n); - swapl (&reply->length, n); - swapl (&reply->numFormats, n); - swapl (&reply->numScreens, n); - swapl (&reply->numDepths, n); - swapl (&reply->numVisuals, n); - swapl (&reply->numSubpixel, n); - } - WriteToClient(client, rlength, (char *) reply); - free(reply); - return Success; -} - -static int -ProcRenderQueryPictIndexValues (ClientPtr client) -{ - PictFormatPtr pFormat; - int rc, num; - int rlength; - int i, n; - REQUEST(xRenderQueryPictIndexValuesReq); - xRenderQueryPictIndexValuesReply *reply; - xIndexValue *values; - - REQUEST_AT_LEAST_SIZE(xRenderQueryPictIndexValuesReq); - - rc = dixLookupResourceByType((pointer *)&pFormat, stuff->format, - PictFormatType, client, DixReadAccess); - if (rc != Success) - return (rc == BadValue) ? RenderErrBase + BadPictFormat : rc; - - if (pFormat->type != PictTypeIndexed) - { - client->errorValue = stuff->format; - return BadMatch; - } - num = pFormat->index.nvalues; - rlength = (sizeof (xRenderQueryPictIndexValuesReply) + - num * sizeof(xIndexValue)); - reply = (xRenderQueryPictIndexValuesReply *) malloc(rlength); - if (!reply) - return BadAlloc; - - reply->type = X_Reply; - reply->sequenceNumber = client->sequence; - reply->length = bytes_to_int32(rlength - sizeof(xGenericReply)); - reply->numIndexValues = num; - - values = (xIndexValue *) (reply + 1); - - memcpy (reply + 1, pFormat->index.pValues, num * sizeof (xIndexValue)); - - if (client->swapped) - { - for (i = 0; i < num; i++) - { - swapl (&values[i].pixel, n); - swaps (&values[i].red, n); - swaps (&values[i].green, n); - swaps (&values[i].blue, n); - swaps (&values[i].alpha, n); - } - swaps (&reply->sequenceNumber, n); - swapl (&reply->length, n); - swapl (&reply->numIndexValues, n); - } - - WriteToClient(client, rlength, (char *) reply); - free(reply); - return Success; -} - -static int -ProcRenderQueryDithers (ClientPtr client) -{ - return BadImplementation; -} - -static int -ProcRenderCreatePicture (ClientPtr client) -{ - PicturePtr pPicture; - DrawablePtr pDrawable; - PictFormatPtr pFormat; - int len, error, rc; - REQUEST(xRenderCreatePictureReq); - - REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); - - LEGAL_NEW_RESOURCE(stuff->pid, client); - rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, - DixReadAccess|DixAddAccess); - if (rc != Success) - return rc; - - rc = dixLookupResourceByType((pointer *)&pFormat, stuff->format, - PictFormatType, client, DixReadAccess); - if (rc != Success) - return (rc == BadValue) ? RenderErrBase + BadPictFormat : rc; - - if (pFormat->depth != pDrawable->depth) - return BadMatch; - len = client->req_len - bytes_to_int32(sizeof(xRenderCreatePictureReq)); - if (Ones(stuff->mask) != len) - return BadLength; - - pPicture = CreatePicture (stuff->pid, - pDrawable, - pFormat, - stuff->mask, - (XID *) (stuff + 1), - client, - &error); - if (!pPicture) - return error; - if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) - return BadAlloc; - return Success; -} - -static int -ProcRenderChangePicture (ClientPtr client) -{ - PicturePtr pPicture; - REQUEST(xRenderChangePictureReq); - int len; - - REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq); - VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess); - - len = client->req_len - bytes_to_int32(sizeof(xRenderChangePictureReq)); - if (Ones(stuff->mask) != len) - return BadLength; - - return ChangePicture (pPicture, stuff->mask, (XID *) (stuff + 1), - (DevUnion *) 0, client); -} - -static int -ProcRenderSetPictureClipRectangles (ClientPtr client) -{ - REQUEST(xRenderSetPictureClipRectanglesReq); - PicturePtr pPicture; - int nr; - - REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); - VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess); - if (!pPicture->pDrawable) - return BadDrawable; - - nr = (client->req_len << 2) - sizeof(xRenderSetPictureClipRectanglesReq); - if (nr & 4) - return BadLength; - nr >>= 3; - return SetPictureClipRects (pPicture, - stuff->xOrigin, stuff->yOrigin, - nr, (xRectangle *) &stuff[1]); -} - -static int -ProcRenderFreePicture (ClientPtr client) -{ - PicturePtr pPicture; - REQUEST(xRenderFreePictureReq); - - REQUEST_SIZE_MATCH(xRenderFreePictureReq); - - VERIFY_PICTURE (pPicture, stuff->picture, client, DixDestroyAccess); - FreeResource (stuff->picture, RT_NONE); - return Success; -} - -static Bool -PictOpValid (CARD8 op) -{ - if (/*PictOpMinimum <= op && */ op <= PictOpMaximum) - return TRUE; - if (PictOpDisjointMinimum <= op && op <= PictOpDisjointMaximum) - return TRUE; - if (PictOpConjointMinimum <= op && op <= PictOpConjointMaximum) - return TRUE; - if (PictOpBlendMinimum <= op && op <= PictOpBlendMaximum) - return TRUE; - return FALSE; -} - -static int -ProcRenderComposite (ClientPtr client) -{ - PicturePtr pSrc, pMask, pDst; - REQUEST(xRenderCompositeReq); - - REQUEST_SIZE_MATCH(xRenderCompositeReq); - if (!PictOpValid (stuff->op)) - { - client->errorValue = stuff->op; - return BadValue; - } - VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); - if (!pDst->pDrawable) - return BadDrawable; - VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); - VERIFY_ALPHA (pMask, stuff->mask, client, DixReadAccess); - if ((pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) || - (pMask && pMask->pDrawable && pDst->pDrawable->pScreen != pMask->pDrawable->pScreen)) - return BadMatch; - CompositePicture (stuff->op, - pSrc, - pMask, - pDst, - stuff->xSrc, - stuff->ySrc, - stuff->xMask, - stuff->yMask, - stuff->xDst, - stuff->yDst, - stuff->width, - stuff->height); - return Success; -} - -static int -ProcRenderScale (ClientPtr client) -{ - return BadImplementation; -} - -static int -ProcRenderTrapezoids (ClientPtr client) -{ - int rc, ntraps; - PicturePtr pSrc, pDst; - PictFormatPtr pFormat; - REQUEST(xRenderTrapezoidsReq); - - REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); - if (!PictOpValid (stuff->op)) - { - client->errorValue = stuff->op; - return BadValue; - } - VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); - VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); - if (!pDst->pDrawable) - return BadDrawable; - if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) - return BadMatch; - if (stuff->maskFormat) - { - rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat, - PictFormatType, client, DixReadAccess); - if (rc != Success) - return (rc == BadValue) ? RenderErrBase + BadPictFormat : rc; - } - else - pFormat = 0; - ntraps = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq); - if (ntraps % sizeof (xTrapezoid)) - return BadLength; - ntraps /= sizeof (xTrapezoid); - if (ntraps) - CompositeTrapezoids (stuff->op, pSrc, pDst, pFormat, - stuff->xSrc, stuff->ySrc, - ntraps, (xTrapezoid *) &stuff[1]); - return Success; -} - -static int -ProcRenderTriangles (ClientPtr client) -{ - int rc, ntris; - PicturePtr pSrc, pDst; - PictFormatPtr pFormat; - REQUEST(xRenderTrianglesReq); - - REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); - if (!PictOpValid (stuff->op)) - { - client->errorValue = stuff->op; - return BadValue; - } - VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); - VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); - if (!pDst->pDrawable) - return BadDrawable; - if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) - return BadMatch; - if (stuff->maskFormat) - { - rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat, - PictFormatType, client, DixReadAccess); - if (rc != Success) - return (rc == BadValue) ? RenderErrBase + BadPictFormat : rc; - } - else - pFormat = 0; - ntris = (client->req_len << 2) - sizeof (xRenderTrianglesReq); - if (ntris % sizeof (xTriangle)) - return BadLength; - ntris /= sizeof (xTriangle); - if (ntris) - CompositeTriangles (stuff->op, pSrc, pDst, pFormat, - stuff->xSrc, stuff->ySrc, - ntris, (xTriangle *) &stuff[1]); - return Success; -} - -static int -ProcRenderTriStrip (ClientPtr client) -{ - int rc, npoints; - PicturePtr pSrc, pDst; - PictFormatPtr pFormat; - REQUEST(xRenderTrianglesReq); - - REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); - if (!PictOpValid (stuff->op)) - { - client->errorValue = stuff->op; - return BadValue; - } - VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); - VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); - if (!pDst->pDrawable) - return BadDrawable; - if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) - return BadMatch; - if (stuff->maskFormat) - { - rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat, - PictFormatType, client, DixReadAccess); - if (rc != Success) - return (rc == BadValue) ? RenderErrBase + BadPictFormat : rc; - } - else - pFormat = 0; - npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); - if (npoints & 4) - return(BadLength); - npoints >>= 3; - if (npoints >= 3) - CompositeTriStrip (stuff->op, pSrc, pDst, pFormat, - stuff->xSrc, stuff->ySrc, - npoints, (xPointFixed *) &stuff[1]); - return Success; -} - -static int -ProcRenderTriFan (ClientPtr client) -{ - int rc, npoints; - PicturePtr pSrc, pDst; - PictFormatPtr pFormat; - REQUEST(xRenderTrianglesReq); - - REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); - if (!PictOpValid (stuff->op)) - { - client->errorValue = stuff->op; - return BadValue; - } - VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); - VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); - if (!pDst->pDrawable) - return BadDrawable; - if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) - return BadMatch; - if (stuff->maskFormat) - { - rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat, - PictFormatType, client, DixReadAccess); - if (rc != Success) - return (rc == BadValue) ? RenderErrBase + BadPictFormat : rc; - } - else - pFormat = 0; - npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); - if (npoints & 4) - return(BadLength); - npoints >>= 3; - if (npoints >= 3) - CompositeTriFan (stuff->op, pSrc, pDst, pFormat, - stuff->xSrc, stuff->ySrc, - npoints, (xPointFixed *) &stuff[1]); - return Success; -} - -static int -ProcRenderColorTrapezoids (ClientPtr client) -{ - return BadImplementation; -} - -static int -ProcRenderColorTriangles (ClientPtr client) -{ - return BadImplementation; -} - -static int -ProcRenderTransform (ClientPtr client) -{ - return BadImplementation; -} - -static int -ProcRenderCreateGlyphSet (ClientPtr client) -{ - GlyphSetPtr glyphSet; - PictFormatPtr format; - int rc, f; - REQUEST(xRenderCreateGlyphSetReq); - - REQUEST_SIZE_MATCH(xRenderCreateGlyphSetReq); - - LEGAL_NEW_RESOURCE(stuff->gsid, client); - rc = dixLookupResourceByType((pointer *)&format, stuff->format, - PictFormatType, client, DixReadAccess); - if (rc != Success) - return (rc == BadValue) ? RenderErrBase + BadPictFormat : rc; - - switch (format->depth) { - case 1: - f = GlyphFormat1; - break; - case 4: - f = GlyphFormat4; - break; - case 8: - f = GlyphFormat8; - break; - case 16: - f = GlyphFormat16; - break; - case 32: - f = GlyphFormat32; - break; - default: - return BadMatch; - } - if (format->type != PictTypeDirect) - return BadMatch; - glyphSet = AllocateGlyphSet (f, format); - if (!glyphSet) - return BadAlloc; - /* security creation/labeling check */ - rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->gsid, GlyphSetType, - glyphSet, RT_NONE, NULL, DixCreateAccess); - if (rc != Success) - return rc; - if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) - return BadAlloc; - return Success; -} - -static int -ProcRenderReferenceGlyphSet (ClientPtr client) -{ - GlyphSetPtr glyphSet; - int rc; - REQUEST(xRenderReferenceGlyphSetReq); - - REQUEST_SIZE_MATCH(xRenderReferenceGlyphSetReq); - - LEGAL_NEW_RESOURCE(stuff->gsid, client); - - rc = dixLookupResourceByType((pointer *)&glyphSet, stuff->existing, GlyphSetType, - client, DixGetAttrAccess); - if (rc != Success) - { - client->errorValue = stuff->existing; - return (rc == BadValue) ? RenderErrBase + BadGlyphSet : rc; - } - glyphSet->refcnt++; - if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) - return BadAlloc; - return Success; -} - -#define NLOCALDELTA 64 -#define NLOCALGLYPH 256 - -static int -ProcRenderFreeGlyphSet (ClientPtr client) -{ - GlyphSetPtr glyphSet; - int rc; - REQUEST(xRenderFreeGlyphSetReq); - - REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq); - rc = dixLookupResourceByType((pointer *)&glyphSet, stuff->glyphset, GlyphSetType, - client, DixDestroyAccess); - if (rc != Success) - { - client->errorValue = stuff->glyphset; - return (rc == BadValue) ? RenderErrBase + BadGlyphSet : rc; - } - FreeResource (stuff->glyphset, RT_NONE); - return Success; -} - -typedef struct _GlyphNew { - Glyph id; - GlyphPtr glyph; - Bool found; - unsigned char sha1[20]; -} GlyphNewRec, *GlyphNewPtr; - -#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) - -static int -ProcRenderAddGlyphs (ClientPtr client) -{ - GlyphSetPtr glyphSet; - REQUEST(xRenderAddGlyphsReq); - GlyphNewRec glyphsLocal[NLOCALGLYPH]; - GlyphNewPtr glyphsBase, glyphs, glyph_new; - int remain, nglyphs; - CARD32 *gids; - xGlyphInfo *gi; - CARD8 *bits; - unsigned int size; - int err; - int i, screen; - PicturePtr pSrc = NULL, pDst = NULL; - PixmapPtr pSrcPix = NULL, pDstPix = NULL; - CARD32 component_alpha; - - REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq); - err = dixLookupResourceByType((pointer *)&glyphSet, stuff->glyphset, GlyphSetType, - client, DixAddAccess); - if (err != Success) - { - client->errorValue = stuff->glyphset; - return (err == BadValue) ? RenderErrBase + BadGlyphSet : err; - } - - err = BadAlloc; - nglyphs = stuff->nglyphs; - if (nglyphs > UINT32_MAX / sizeof(GlyphNewRec)) - return BadAlloc; - - component_alpha = NeedsComponent (glyphSet->format->format); - - if (nglyphs <= NLOCALGLYPH) { - memset (glyphsLocal, 0, sizeof (glyphsLocal)); - glyphsBase = glyphsLocal; - } - else - { - glyphsBase = (GlyphNewPtr)calloc(nglyphs, sizeof (GlyphNewRec)); - if (!glyphsBase) - return BadAlloc; - } - - remain = (client->req_len << 2) - sizeof (xRenderAddGlyphsReq); - - glyphs = glyphsBase; - - gids = (CARD32 *) (stuff + 1); - gi = (xGlyphInfo *) (gids + nglyphs); - bits = (CARD8 *) (gi + nglyphs); - remain -= (sizeof (CARD32) + sizeof (xGlyphInfo)) * nglyphs; - for (i = 0; i < nglyphs; i++) - { - size_t padded_width; - glyph_new = &glyphs[i]; - - padded_width = PixmapBytePad (gi[i].width, - glyphSet->format->depth); - - if (gi[i].height && padded_width > (UINT32_MAX - sizeof(GlyphRec))/gi[i].height) - break; - - size = gi[i].height * padded_width; - if (remain < size) - break; - - err = HashGlyph (&gi[i], bits, size, glyph_new->sha1); - if (err) - goto bail; - - glyph_new->glyph = FindGlyphByHash (glyph_new->sha1, - glyphSet->fdepth); - - if (glyph_new->glyph && glyph_new->glyph != DeletedGlyph) - { - glyph_new->found = TRUE; - } - else - { - GlyphPtr glyph; - - glyph_new->found = FALSE; - glyph_new->glyph = glyph = AllocateGlyph (&gi[i], glyphSet->fdepth); - if (! glyph) - { - err = BadAlloc; - goto bail; - } - - for (screen = 0; screen < screenInfo.numScreens; screen++) - { - int width = gi[i].width; - int height = gi[i].height; - int depth = glyphSet->format->depth; - ScreenPtr pScreen; - int error; - - /* Skip work if it's invisibly small anyway */ - if (!width || !height) - break; - - pScreen = screenInfo.screens[screen]; - pSrcPix = GetScratchPixmapHeader (pScreen, - width, height, - depth, depth, - -1, bits); - if (! pSrcPix) - { - err = BadAlloc; - goto bail; - } - - pSrc = CreatePicture (0, &pSrcPix->drawable, - glyphSet->format, 0, NULL, - serverClient, &error); - if (! pSrc) - { - err = BadAlloc; - goto bail; - } - - pDstPix = (pScreen->CreatePixmap) (pScreen, - width, height, depth, - CREATE_PIXMAP_USAGE_GLYPH_PICTURE); - - if (!pDstPix) - { - err = BadAlloc; - goto bail; - } - - GlyphPicture (glyph)[screen] = pDst = - CreatePicture (0, &pDstPix->drawable, - glyphSet->format, - CPComponentAlpha, &component_alpha, - serverClient, &error); - - /* The picture takes a reference to the pixmap, so we - drop ours. */ - (pScreen->DestroyPixmap) (pDstPix); - pDstPix = NULL; - - if (! pDst) - { - err = BadAlloc; - goto bail; - } - - CompositePicture (PictOpSrc, - pSrc, - None, - pDst, - 0, 0, - 0, 0, - 0, 0, - width, height); - - FreePicture ((pointer) pSrc, 0); - pSrc = NULL; - FreeScratchPixmapHeader (pSrcPix); - pSrcPix = NULL; - } - - memcpy (glyph_new->glyph->sha1, glyph_new->sha1, 20); - } - - glyph_new->id = gids[i]; - - if (size & 3) - size += 4 - (size & 3); - bits += size; - remain -= size; - } - if (remain || i < nglyphs) - { - err = BadLength; - goto bail; - } - if (!ResizeGlyphSet (glyphSet, nglyphs)) - { - err = BadAlloc; - goto bail; - } - for (i = 0; i < nglyphs; i++) - AddGlyph (glyphSet, glyphs[i].glyph, glyphs[i].id); - - if (glyphsBase != glyphsLocal) - free(glyphsBase); - return Success; -bail: - if (pSrc) - FreePicture ((pointer) pSrc, 0); - if (pSrcPix) - FreeScratchPixmapHeader (pSrcPix); - for (i = 0; i < nglyphs; i++) - if (glyphs[i].glyph && ! glyphs[i].found) - free(glyphs[i].glyph); - if (glyphsBase != glyphsLocal) - free(glyphsBase); - return err; -} - -static int -ProcRenderAddGlyphsFromPicture (ClientPtr client) -{ - return BadImplementation; -} - -static int -ProcRenderFreeGlyphs (ClientPtr client) -{ - REQUEST(xRenderFreeGlyphsReq); - GlyphSetPtr glyphSet; - int rc, nglyph; - CARD32 *gids; - CARD32 glyph; - - REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq); - rc = dixLookupResourceByType((pointer *)&glyphSet, stuff->glyphset, GlyphSetType, - client, DixRemoveAccess); - if (rc != Success) - { - client->errorValue = stuff->glyphset; - return (rc == BadValue) ? RenderErrBase + BadGlyphSet : rc; - } - nglyph = bytes_to_int32((client->req_len << 2) - sizeof (xRenderFreeGlyphsReq)); - gids = (CARD32 *) (stuff + 1); - while (nglyph-- > 0) - { - glyph = *gids++; - if (!DeleteGlyph (glyphSet, glyph)) - { - client->errorValue = glyph; - return RenderErrBase + BadGlyph; - } - } - return Success; -} - -static int -ProcRenderCompositeGlyphs (ClientPtr client) -{ - GlyphSetPtr glyphSet; - GlyphSet gs; - PicturePtr pSrc, pDst; - PictFormatPtr pFormat; - GlyphListRec listsLocal[NLOCALDELTA]; - GlyphListPtr lists, listsBase; - GlyphPtr glyphsLocal[NLOCALGLYPH]; - Glyph glyph; - GlyphPtr *glyphs, *glyphsBase; - xGlyphElt *elt; - CARD8 *buffer, *end; - int nglyph; - int nlist; - int space; - int size; - int rc, n; - - REQUEST(xRenderCompositeGlyphsReq); - - REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); - - switch (stuff->renderReqType) { - default: size = 1; break; - case X_RenderCompositeGlyphs16: size = 2; break; - case X_RenderCompositeGlyphs32: size = 4; break; - } - - if (!PictOpValid (stuff->op)) - { - client->errorValue = stuff->op; - return BadValue; - } - VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); - VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); - if (!pDst->pDrawable) - return BadDrawable; - if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) - return BadMatch; - if (stuff->maskFormat) - { - rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat, - PictFormatType, client, DixReadAccess); - if (rc != Success) - return (rc == BadValue) ? RenderErrBase + BadPictFormat : rc; - } - else - pFormat = 0; - - rc = dixLookupResourceByType((pointer *)&glyphSet, stuff->glyphset, - GlyphSetType, client, DixUseAccess); - if (rc != Success) - return (rc == BadValue) ? RenderErrBase + BadGlyphSet : rc; - - buffer = (CARD8 *) (stuff + 1); - end = (CARD8 *) stuff + (client->req_len << 2); - nglyph = 0; - nlist = 0; - while (buffer + sizeof (xGlyphElt) < end) - { - elt = (xGlyphElt *) buffer; - buffer += sizeof (xGlyphElt); - - if (elt->len == 0xff) - { - buffer += 4; - } - else - { - nlist++; - nglyph += elt->len; - space = size * elt->len; - if (space & 3) - space += 4 - (space & 3); - buffer += space; - } - } - if (nglyph <= NLOCALGLYPH) - glyphsBase = glyphsLocal; - else - { - glyphsBase = (GlyphPtr *) malloc(nglyph * sizeof (GlyphPtr)); - if (!glyphsBase) - return BadAlloc; - } - if (nlist <= NLOCALDELTA) - listsBase = listsLocal; - else - { - listsBase = (GlyphListPtr) malloc(nlist * sizeof (GlyphListRec)); - if (!listsBase) - return BadAlloc; - } - buffer = (CARD8 *) (stuff + 1); - glyphs = glyphsBase; - lists = listsBase; - while (buffer + sizeof (xGlyphElt) < end) - { - elt = (xGlyphElt *) buffer; - buffer += sizeof (xGlyphElt); - - if (elt->len == 0xff) - { - if (buffer + sizeof (GlyphSet) < end) - { - memcpy(&gs, buffer, sizeof(GlyphSet)); - rc = dixLookupResourceByType((pointer *)&glyphSet, gs, - GlyphSetType, client, - DixUseAccess); - if (rc != Success) - { - if (glyphsBase != glyphsLocal) - free(glyphsBase); - if (listsBase != listsLocal) - free(listsBase); - return (rc == BadValue) ? RenderErrBase + BadGlyphSet : rc; - } - } - buffer += 4; - } - else - { - lists->xOff = elt->deltax; - lists->yOff = elt->deltay; - lists->format = glyphSet->format; - lists->len = 0; - n = elt->len; - while (n--) - { - if (buffer + size <= end) - { - switch (size) { - case 1: - glyph = *((CARD8 *)buffer); break; - case 2: - glyph = *((CARD16 *)buffer); break; - case 4: - default: - glyph = *((CARD32 *)buffer); break; - } - if ((*glyphs = FindGlyph (glyphSet, glyph))) - { - lists->len++; - glyphs++; - } - } - buffer += size; - } - space = size * elt->len; - if (space & 3) - buffer += 4 - (space & 3); - lists++; - } - } - if (buffer > end) - return BadLength; - - CompositeGlyphs (stuff->op, - pSrc, - pDst, - pFormat, - stuff->xSrc, - stuff->ySrc, - nlist, - listsBase, - glyphsBase); - - if (glyphsBase != glyphsLocal) - free(glyphsBase); - if (listsBase != listsLocal) - free(listsBase); - - return Success; -} - -static int -ProcRenderFillRectangles (ClientPtr client) -{ - PicturePtr pDst; - int things; - REQUEST(xRenderFillRectanglesReq); - - REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); - if (!PictOpValid (stuff->op)) - { - client->errorValue = stuff->op; - return BadValue; - } - VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); - if (!pDst->pDrawable) - return BadDrawable; - - things = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq); - if (things & 4) - return(BadLength); - things >>= 3; - - CompositeRects (stuff->op, - pDst, - &stuff->color, - things, - (xRectangle *) &stuff[1]); - - return Success; -} - -static void -RenderSetBit (unsigned char *line, int x, int bit) -{ - unsigned char mask; - - if (screenInfo.bitmapBitOrder == LSBFirst) - mask = (1 << (x & 7)); - else - mask = (0x80 >> (x & 7)); - /* XXX assumes byte order is host byte order */ - line += (x >> 3); - if (bit) - *line |= mask; - else - *line &= ~mask; -} - -#define DITHER_DIM 2 - -static CARD32 orderedDither[DITHER_DIM][DITHER_DIM] = { - { 1, 3, }, - { 4, 2, }, -}; - -#define DITHER_SIZE ((sizeof orderedDither / sizeof orderedDither[0][0]) + 1) - -static int -ProcRenderCreateCursor (ClientPtr client) -{ - REQUEST(xRenderCreateCursorReq); - PicturePtr pSrc; - ScreenPtr pScreen; - unsigned short width, height; - CARD32 *argbbits, *argb; - unsigned char *srcbits, *srcline; - unsigned char *mskbits, *mskline; - int stride; - int x, y; - int nbytes_mono; - CursorMetricRec cm; - CursorPtr pCursor; - CARD32 twocolor[3]; - int rc, ncolor; - - REQUEST_SIZE_MATCH (xRenderCreateCursorReq); - LEGAL_NEW_RESOURCE(stuff->cid, client); - - VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); - if (!pSrc->pDrawable) - return BadDrawable; - pScreen = pSrc->pDrawable->pScreen; - width = pSrc->pDrawable->width; - height = pSrc->pDrawable->height; - if (height && width > UINT32_MAX/(height*sizeof(CARD32))) - return BadAlloc; - if ( stuff->x > width - || stuff->y > height ) - return (BadMatch); - argbbits = malloc(width * height * sizeof (CARD32)); - if (!argbbits) - return (BadAlloc); - - stride = BitmapBytePad(width); - nbytes_mono = stride*height; - srcbits = calloc(1, nbytes_mono); - if (!srcbits) - { - free(argbbits); - return (BadAlloc); - } - mskbits = calloc(1, nbytes_mono); - if (!mskbits) - { - free(argbbits); - free(srcbits); - return (BadAlloc); - } - - if (pSrc->format == PICT_a8r8g8b8) - { - (*pScreen->GetImage) (pSrc->pDrawable, - 0, 0, width, height, ZPixmap, - 0xffffffff, (pointer) argbbits); - } - else - { - PixmapPtr pPixmap; - PicturePtr pPicture; - PictFormatPtr pFormat; - int error; - - pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); - if (!pFormat) - { - free(argbbits); - free(srcbits); - free(mskbits); - return (BadImplementation); - } - pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 32, - CREATE_PIXMAP_USAGE_SCRATCH); - if (!pPixmap) - { - free(argbbits); - free(srcbits); - free(mskbits); - return (BadAlloc); - } - pPicture = CreatePicture (0, &pPixmap->drawable, pFormat, 0, 0, - client, &error); - if (!pPicture) - { - free(argbbits); - free(srcbits); - free(mskbits); - return error; - } - (*pScreen->DestroyPixmap) (pPixmap); - CompositePicture (PictOpSrc, - pSrc, 0, pPicture, - 0, 0, 0, 0, 0, 0, width, height); - (*pScreen->GetImage) (pPicture->pDrawable, - 0, 0, width, height, ZPixmap, - 0xffffffff, (pointer) argbbits); - FreePicture (pPicture, 0); - } - /* - * Check whether the cursor can be directly supported by - * the core cursor code - */ - ncolor = 0; - argb = argbbits; - for (y = 0; ncolor <= 2 && y < height; y++) - { - for (x = 0; ncolor <= 2 && x < width; x++) - { - CARD32 p = *argb++; - CARD32 a = (p >> 24); - - if (a == 0) /* transparent */ - continue; - if (a == 0xff) /* opaque */ - { - int n; - for (n = 0; n < ncolor; n++) - if (p == twocolor[n]) - break; - if (n == ncolor) - twocolor[ncolor++] = p; - } - else - ncolor = 3; - } - } - - /* - * Convert argb image to two plane cursor - */ - srcline = srcbits; - mskline = mskbits; - argb = argbbits; - for (y = 0; y < height; y++) - { - for (x = 0; x < width; x++) - { - CARD32 p = *argb++; - - if (ncolor <= 2) - { - CARD32 a = ((p >> 24)); - - RenderSetBit (mskline, x, a != 0); - RenderSetBit (srcline, x, a != 0 && p == twocolor[0]); - } - else - { - CARD32 a = ((p >> 24) * DITHER_SIZE + 127) / 255; - CARD32 i = ((CvtR8G8B8toY15(p) >> 7) * DITHER_SIZE + 127) / 255; - CARD32 d = orderedDither[y&(DITHER_DIM-1)][x&(DITHER_DIM-1)]; - /* Set mask from dithered alpha value */ - RenderSetBit(mskline, x, a > d); - /* Set src from dithered intensity value */ - RenderSetBit(srcline, x, a > d && i <= d); - } - } - srcline += stride; - mskline += stride; - } - /* - * Dither to white and black if the cursor has more than two colors - */ - if (ncolor > 2) - { - twocolor[0] = 0xff000000; - twocolor[1] = 0xffffffff; - } - else - { - free(argbbits); - argbbits = 0; - } - -#define GetByte(p,s) (((p) >> (s)) & 0xff) -#define GetColor(p,s) (GetByte(p,s) | (GetByte(p,s) << 8)) - - cm.width = width; - cm.height = height; - cm.xhot = stuff->x; - cm.yhot = stuff->y; - rc = AllocARGBCursor(srcbits, mskbits, argbbits, &cm, - GetColor(twocolor[0], 16), - GetColor(twocolor[0], 8), - GetColor(twocolor[0], 0), - GetColor(twocolor[1], 16), - GetColor(twocolor[1], 8), - GetColor(twocolor[1], 0), - &pCursor, client, stuff->cid); - if (rc != Success) - return rc; - if (!AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) - return BadAlloc; - - return Success; -} - -static int -ProcRenderSetPictureTransform (ClientPtr client) -{ - REQUEST(xRenderSetPictureTransformReq); - PicturePtr pPicture; - - REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); - VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess); - return SetPictureTransform (pPicture, (PictTransform *) &stuff->transform); -} - -static int -ProcRenderQueryFilters (ClientPtr client) -{ - REQUEST (xRenderQueryFiltersReq); - DrawablePtr pDrawable; - xRenderQueryFiltersReply *reply; - int nbytesName; - int nnames; - ScreenPtr pScreen; - PictureScreenPtr ps; - int i, j, len, total_bytes, rc; - INT16 *aliases; - char *names; - - REQUEST_SIZE_MATCH(xRenderQueryFiltersReq); - rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, - DixGetAttrAccess); - if (rc != Success) - return rc; - - pScreen = pDrawable->pScreen; - nbytesName = 0; - nnames = 0; - ps = GetPictureScreenIfSet(pScreen); - if (ps) - { - for (i = 0; i < ps->nfilters; i++) - nbytesName += 1 + strlen (ps->filters[i].name); - for (i = 0; i < ps->nfilterAliases; i++) - nbytesName += 1 + strlen (ps->filterAliases[i].alias); - nnames = ps->nfilters + ps->nfilterAliases; - } - len = ((nnames + 1) >> 1) + bytes_to_int32(nbytesName); - total_bytes = sizeof (xRenderQueryFiltersReply) + (len << 2); - reply = (xRenderQueryFiltersReply *) malloc(total_bytes); - if (!reply) - return BadAlloc; - aliases = (INT16 *) (reply + 1); - names = (char *) (aliases + ((nnames + 1) & ~1)); - - reply->type = X_Reply; - reply->sequenceNumber = client->sequence; - reply->length = len; - reply->numAliases = nnames; - reply->numFilters = nnames; - if (ps) - { - - /* fill in alias values */ - for (i = 0; i < ps->nfilters; i++) - aliases[i] = FilterAliasNone; - for (i = 0; i < ps->nfilterAliases; i++) - { - for (j = 0; j < ps->nfilters; j++) - if (ps->filterAliases[i].filter_id == ps->filters[j].id) - break; - if (j == ps->nfilters) - { - for (j = 0; j < ps->nfilterAliases; j++) - if (ps->filterAliases[i].filter_id == - ps->filterAliases[j].alias_id) - { - break; - } - if (j == ps->nfilterAliases) - j = FilterAliasNone; - else - j = j + ps->nfilters; - } - aliases[i + ps->nfilters] = j; - } - - /* fill in filter names */ - for (i = 0; i < ps->nfilters; i++) - { - j = strlen (ps->filters[i].name); - *names++ = j; - strncpy (names, ps->filters[i].name, j); - names += j; - } - - /* fill in filter alias names */ - for (i = 0; i < ps->nfilterAliases; i++) - { - j = strlen (ps->filterAliases[i].alias); - *names++ = j; - strncpy (names, ps->filterAliases[i].alias, j); - names += j; - } - } - - if (client->swapped) - { - register int n; - - for (i = 0; i < reply->numAliases; i++) - { - swaps (&aliases[i], n); - } - swaps(&reply->sequenceNumber, n); - swapl(&reply->length, n); - swapl(&reply->numAliases, n); - swapl(&reply->numFilters, n); - } - WriteToClient(client, total_bytes, (char *) reply); - free(reply); - - return Success; -} - -static int -ProcRenderSetPictureFilter (ClientPtr client) -{ - REQUEST (xRenderSetPictureFilterReq); - PicturePtr pPicture; - int result; - xFixed *params; - int nparams; - char *name; - - REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); - VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess); - name = (char *) (stuff + 1); - params = (xFixed *) (name + pad_to_int32(stuff->nbytes)); - nparams = ((xFixed *) stuff + client->req_len) - params; - result = SetPictureFilter (pPicture, name, stuff->nbytes, params, nparams); - return result; -} - -static int -ProcRenderCreateAnimCursor (ClientPtr client) -{ - REQUEST(xRenderCreateAnimCursorReq); - CursorPtr *cursors; - CARD32 *deltas; - CursorPtr pCursor; - int ncursor; - xAnimCursorElt *elt; - int i; - int ret; - - REQUEST_AT_LEAST_SIZE(xRenderCreateAnimCursorReq); - LEGAL_NEW_RESOURCE(stuff->cid, client); - if (client->req_len & 1) - return BadLength; - ncursor = (client->req_len - (bytes_to_int32(sizeof(xRenderCreateAnimCursorReq)))) >> 1; - cursors = malloc(ncursor * (sizeof (CursorPtr) + sizeof (CARD32))); - if (!cursors) - return BadAlloc; - deltas = (CARD32 *) (cursors + ncursor); - elt = (xAnimCursorElt *) (stuff + 1); - for (i = 0; i < ncursor; i++) - { - ret = dixLookupResourceByType((pointer *)(cursors + i), elt->cursor, - RT_CURSOR, client, DixReadAccess); - if (ret != Success) - { - free(cursors); - return (ret == BadValue) ? BadCursor : ret; - } - deltas[i] = elt->delay; - elt++; - } - ret = AnimCursorCreate (cursors, deltas, ncursor, &pCursor, client, - stuff->cid); - free(cursors); - if (ret != Success) - return ret; - - if (AddResource (stuff->cid, RT_CURSOR, (pointer)pCursor)) - return Success; - return BadAlloc; -} - -static int -ProcRenderAddTraps (ClientPtr client) -{ - int ntraps; - PicturePtr pPicture; - REQUEST(xRenderAddTrapsReq); - - REQUEST_AT_LEAST_SIZE(xRenderAddTrapsReq); - VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess); - if (!pPicture->pDrawable) - return BadDrawable; - ntraps = (client->req_len << 2) - sizeof (xRenderAddTrapsReq); - if (ntraps % sizeof (xTrap)) - return BadLength; - ntraps /= sizeof (xTrap); - if (ntraps) - AddTraps (pPicture, - stuff->xOff, stuff->yOff, - ntraps, (xTrap *) &stuff[1]); - return Success; -} - -static int ProcRenderCreateSolidFill(ClientPtr client) -{ - PicturePtr pPicture; - int error = 0; - REQUEST(xRenderCreateSolidFillReq); - - REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq); - - LEGAL_NEW_RESOURCE(stuff->pid, client); - - pPicture = CreateSolidPicture(stuff->pid, &stuff->color, &error); - if (!pPicture) - return error; - /* security creation/labeling check */ - error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType, - pPicture, RT_NONE, NULL, DixCreateAccess); - if (error != Success) - return error; - if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) - return BadAlloc; - return Success; -} - -static int ProcRenderCreateLinearGradient (ClientPtr client) -{ - PicturePtr pPicture; - int len; - int error = 0; - xFixed *stops; - xRenderColor *colors; - REQUEST(xRenderCreateLinearGradientReq); - - REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq); - - LEGAL_NEW_RESOURCE(stuff->pid, client); - - len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq); - if (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor))) - return BadLength; - if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) - return BadLength; - - stops = (xFixed *)(stuff + 1); - colors = (xRenderColor *)(stops + stuff->nStops); - - pPicture = CreateLinearGradientPicture (stuff->pid, &stuff->p1, &stuff->p2, - stuff->nStops, stops, colors, &error); - if (!pPicture) - return error; - /* security creation/labeling check */ - error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType, - pPicture, RT_NONE, NULL, DixCreateAccess); - if (error != Success) - return error; - if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) - return BadAlloc; - return Success; -} - -static int ProcRenderCreateRadialGradient (ClientPtr client) -{ - PicturePtr pPicture; - int len; - int error = 0; - xFixed *stops; - xRenderColor *colors; - REQUEST(xRenderCreateRadialGradientReq); - - REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq); - - LEGAL_NEW_RESOURCE(stuff->pid, client); - - len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq); - if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) - return BadLength; - - stops = (xFixed *)(stuff + 1); - colors = (xRenderColor *)(stops + stuff->nStops); - - pPicture = CreateRadialGradientPicture (stuff->pid, &stuff->inner, &stuff->outer, - stuff->inner_radius, stuff->outer_radius, - stuff->nStops, stops, colors, &error); - if (!pPicture) - return error; - /* security creation/labeling check */ - error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType, - pPicture, RT_NONE, NULL, DixCreateAccess); - if (error != Success) - return error; - if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) - return BadAlloc; - return Success; -} - -static int ProcRenderCreateConicalGradient (ClientPtr client) -{ - PicturePtr pPicture; - int len; - int error = 0; - xFixed *stops; - xRenderColor *colors; - REQUEST(xRenderCreateConicalGradientReq); - - REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq); - - LEGAL_NEW_RESOURCE(stuff->pid, client); - - len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq); - if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) - return BadLength; - - stops = (xFixed *)(stuff + 1); - colors = (xRenderColor *)(stops + stuff->nStops); - - pPicture = CreateConicalGradientPicture (stuff->pid, &stuff->center, stuff->angle, - stuff->nStops, stops, colors, &error); - if (!pPicture) - return error; - /* security creation/labeling check */ - error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType, - pPicture, RT_NONE, NULL, DixCreateAccess); - if (error != Success) - return error; - if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) - return BadAlloc; - return Success; -} - - -static int -ProcRenderDispatch (ClientPtr client) -{ - REQUEST(xReq); - - if (stuff->data < RenderNumberRequests) - return (*ProcRenderVector[stuff->data]) (client); - else - return BadRequest; -} - -static int -SProcRenderQueryVersion (ClientPtr client) -{ - register int n; - REQUEST(xRenderQueryVersionReq); - - swaps(&stuff->length, n); - swapl(&stuff->majorVersion, n); - swapl(&stuff->minorVersion, n); - return (*ProcRenderVector[stuff->renderReqType])(client); -} - -static int -SProcRenderQueryPictFormats (ClientPtr client) -{ - register int n; - REQUEST(xRenderQueryPictFormatsReq); - swaps(&stuff->length, n); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderQueryPictIndexValues (ClientPtr client) -{ - register int n; - REQUEST(xRenderQueryPictIndexValuesReq); - swaps(&stuff->length, n); - swapl(&stuff->format, n); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderQueryDithers (ClientPtr client) -{ - return BadImplementation; -} - -static int -SProcRenderCreatePicture (ClientPtr client) -{ - register int n; - REQUEST(xRenderCreatePictureReq); - swaps(&stuff->length, n); - swapl(&stuff->pid, n); - swapl(&stuff->drawable, n); - swapl(&stuff->format, n); - swapl(&stuff->mask, n); - SwapRestL(stuff); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderChangePicture (ClientPtr client) -{ - register int n; - REQUEST(xRenderChangePictureReq); - swaps(&stuff->length, n); - swapl(&stuff->picture, n); - swapl(&stuff->mask, n); - SwapRestL(stuff); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderSetPictureClipRectangles (ClientPtr client) -{ - register int n; - REQUEST(xRenderSetPictureClipRectanglesReq); - swaps(&stuff->length, n); - swapl(&stuff->picture, n); - swaps(&stuff->xOrigin, n); - swaps(&stuff->yOrigin, n); - SwapRestS(stuff); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderFreePicture (ClientPtr client) -{ - register int n; - REQUEST(xRenderFreePictureReq); - swaps(&stuff->length, n); - swapl(&stuff->picture, n); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderComposite (ClientPtr client) -{ - register int n; - REQUEST(xRenderCompositeReq); - swaps(&stuff->length, n); - swapl(&stuff->src, n); - swapl(&stuff->mask, n); - swapl(&stuff->dst, n); - swaps(&stuff->xSrc, n); - swaps(&stuff->ySrc, n); - swaps(&stuff->xMask, n); - swaps(&stuff->yMask, n); - swaps(&stuff->xDst, n); - swaps(&stuff->yDst, n); - swaps(&stuff->width, n); - swaps(&stuff->height, n); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderScale (ClientPtr client) -{ - register int n; - REQUEST(xRenderScaleReq); - swaps(&stuff->length, n); - swapl(&stuff->src, n); - swapl(&stuff->dst, n); - swapl(&stuff->colorScale, n); - swapl(&stuff->alphaScale, n); - swaps(&stuff->xSrc, n); - swaps(&stuff->ySrc, n); - swaps(&stuff->xDst, n); - swaps(&stuff->yDst, n); - swaps(&stuff->width, n); - swaps(&stuff->height, n); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderTrapezoids (ClientPtr client) -{ - register int n; - REQUEST(xRenderTrapezoidsReq); - - REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); - swaps (&stuff->length, n); - swapl (&stuff->src, n); - swapl (&stuff->dst, n); - swapl (&stuff->maskFormat, n); - swaps (&stuff->xSrc, n); - swaps (&stuff->ySrc, n); - SwapRestL(stuff); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderTriangles (ClientPtr client) -{ - register int n; - REQUEST(xRenderTrianglesReq); - - REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); - swaps (&stuff->length, n); - swapl (&stuff->src, n); - swapl (&stuff->dst, n); - swapl (&stuff->maskFormat, n); - swaps (&stuff->xSrc, n); - swaps (&stuff->ySrc, n); - SwapRestL(stuff); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderTriStrip (ClientPtr client) -{ - register int n; - REQUEST(xRenderTriStripReq); - - REQUEST_AT_LEAST_SIZE(xRenderTriStripReq); - swaps (&stuff->length, n); - swapl (&stuff->src, n); - swapl (&stuff->dst, n); - swapl (&stuff->maskFormat, n); - swaps (&stuff->xSrc, n); - swaps (&stuff->ySrc, n); - SwapRestL(stuff); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderTriFan (ClientPtr client) -{ - register int n; - REQUEST(xRenderTriFanReq); - - REQUEST_AT_LEAST_SIZE(xRenderTriFanReq); - swaps (&stuff->length, n); - swapl (&stuff->src, n); - swapl (&stuff->dst, n); - swapl (&stuff->maskFormat, n); - swaps (&stuff->xSrc, n); - swaps (&stuff->ySrc, n); - SwapRestL(stuff); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderColorTrapezoids (ClientPtr client) -{ - return BadImplementation; -} - -static int -SProcRenderColorTriangles (ClientPtr client) -{ - return BadImplementation; -} - -static int -SProcRenderTransform (ClientPtr client) -{ - return BadImplementation; -} - -static int -SProcRenderCreateGlyphSet (ClientPtr client) -{ - register int n; - REQUEST(xRenderCreateGlyphSetReq); - swaps(&stuff->length, n); - swapl(&stuff->gsid, n); - swapl(&stuff->format, n); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderReferenceGlyphSet (ClientPtr client) -{ - register int n; - REQUEST(xRenderReferenceGlyphSetReq); - swaps(&stuff->length, n); - swapl(&stuff->gsid, n); - swapl(&stuff->existing, n); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderFreeGlyphSet (ClientPtr client) -{ - register int n; - REQUEST(xRenderFreeGlyphSetReq); - swaps(&stuff->length, n); - swapl(&stuff->glyphset, n); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderAddGlyphs (ClientPtr client) -{ - register int n; - register int i; - CARD32 *gids; - void *end; - xGlyphInfo *gi; - REQUEST(xRenderAddGlyphsReq); - swaps(&stuff->length, n); - swapl(&stuff->glyphset, n); - swapl(&stuff->nglyphs, n); - if (stuff->nglyphs & 0xe0000000) - return BadLength; - end = (CARD8 *) stuff + (client->req_len << 2); - gids = (CARD32 *) (stuff + 1); - gi = (xGlyphInfo *) (gids + stuff->nglyphs); - if ((char *) end - (char *) (gids + stuff->nglyphs) < 0) - return BadLength; - if ((char *) end - (char *) (gi + stuff->nglyphs) < 0) - return BadLength; - for (i = 0; i < stuff->nglyphs; i++) - { - swapl (&gids[i], n); - swaps (&gi[i].width, n); - swaps (&gi[i].height, n); - swaps (&gi[i].x, n); - swaps (&gi[i].y, n); - swaps (&gi[i].xOff, n); - swaps (&gi[i].yOff, n); - } - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderAddGlyphsFromPicture (ClientPtr client) -{ - return BadImplementation; -} - -static int -SProcRenderFreeGlyphs (ClientPtr client) -{ - register int n; - REQUEST(xRenderFreeGlyphsReq); - swaps(&stuff->length, n); - swapl(&stuff->glyphset, n); - SwapRestL(stuff); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderCompositeGlyphs (ClientPtr client) -{ - register int n; - xGlyphElt *elt; - CARD8 *buffer; - CARD8 *end; - int space; - int i; - int size; - - REQUEST(xRenderCompositeGlyphsReq); - - switch (stuff->renderReqType) { - default: size = 1; break; - case X_RenderCompositeGlyphs16: size = 2; break; - case X_RenderCompositeGlyphs32: size = 4; break; - } - - swaps(&stuff->length, n); - swapl(&stuff->src, n); - swapl(&stuff->dst, n); - swapl(&stuff->maskFormat, n); - swapl(&stuff->glyphset, n); - swaps(&stuff->xSrc, n); - swaps(&stuff->ySrc, n); - buffer = (CARD8 *) (stuff + 1); - end = (CARD8 *) stuff + (client->req_len << 2); - while (buffer + sizeof (xGlyphElt) < end) - { - elt = (xGlyphElt *) buffer; - buffer += sizeof (xGlyphElt); - - swaps (&elt->deltax, n); - swaps (&elt->deltay, n); - - i = elt->len; - if (i == 0xff) - { - swapl (buffer, n); - buffer += 4; - } - else - { - space = size * i; - switch (size) { - case 1: - buffer += i; - break; - case 2: - while (i--) - { - swaps (buffer, n); - buffer += 2; - } - break; - case 4: - while (i--) - { - swapl (buffer, n); - buffer += 4; - } - break; - } - if (space & 3) - buffer += 4 - (space & 3); - } - } - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderFillRectangles (ClientPtr client) -{ - register int n; - REQUEST(xRenderFillRectanglesReq); - - REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); - swaps(&stuff->length, n); - swapl(&stuff->dst, n); - swaps(&stuff->color.red, n); - swaps(&stuff->color.green, n); - swaps(&stuff->color.blue, n); - swaps(&stuff->color.alpha, n); - SwapRestS(stuff); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderCreateCursor (ClientPtr client) -{ - register int n; - REQUEST(xRenderCreateCursorReq); - REQUEST_SIZE_MATCH (xRenderCreateCursorReq); - - swaps(&stuff->length, n); - swapl(&stuff->cid, n); - swapl(&stuff->src, n); - swaps(&stuff->x, n); - swaps(&stuff->y, n); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderSetPictureTransform (ClientPtr client) -{ - register int n; - REQUEST(xRenderSetPictureTransformReq); - REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); - - swaps(&stuff->length, n); - swapl(&stuff->picture, n); - swapl(&stuff->transform.matrix11, n); - swapl(&stuff->transform.matrix12, n); - swapl(&stuff->transform.matrix13, n); - swapl(&stuff->transform.matrix21, n); - swapl(&stuff->transform.matrix22, n); - swapl(&stuff->transform.matrix23, n); - swapl(&stuff->transform.matrix31, n); - swapl(&stuff->transform.matrix32, n); - swapl(&stuff->transform.matrix33, n); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderQueryFilters (ClientPtr client) -{ - register int n; - REQUEST (xRenderQueryFiltersReq); - REQUEST_SIZE_MATCH (xRenderQueryFiltersReq); - - swaps(&stuff->length, n); - swapl(&stuff->drawable, n); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderSetPictureFilter (ClientPtr client) -{ - register int n; - REQUEST (xRenderSetPictureFilterReq); - REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); - - swaps(&stuff->length, n); - swapl(&stuff->picture, n); - swaps(&stuff->nbytes, n); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderCreateAnimCursor (ClientPtr client) -{ - register int n; - REQUEST (xRenderCreateAnimCursorReq); - REQUEST_AT_LEAST_SIZE (xRenderCreateAnimCursorReq); - - swaps(&stuff->length, n); - swapl(&stuff->cid, n); - SwapRestL(stuff); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderAddTraps (ClientPtr client) -{ - register int n; - REQUEST (xRenderAddTrapsReq); - REQUEST_AT_LEAST_SIZE (xRenderAddTrapsReq); - - swaps(&stuff->length, n); - swapl(&stuff->picture, n); - swaps(&stuff->xOff, n); - swaps(&stuff->yOff, n); - SwapRestL(stuff); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderCreateSolidFill(ClientPtr client) -{ - register int n; - REQUEST (xRenderCreateSolidFillReq); - REQUEST_AT_LEAST_SIZE (xRenderCreateSolidFillReq); - - swaps(&stuff->length, n); - swapl(&stuff->pid, n); - swaps(&stuff->color.alpha, n); - swaps(&stuff->color.red, n); - swaps(&stuff->color.green, n); - swaps(&stuff->color.blue, n); - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static void swapStops(void *stuff, int num) -{ - int i, n; - CARD32 *stops; - CARD16 *colors; - stops = (CARD32 *)(stuff); - for (i = 0; i < num; ++i) { - swapl(stops, n); - ++stops; - } - colors = (CARD16 *)(stops); - for (i = 0; i < 4*num; ++i) { - swaps(stops, n); - ++stops; - } -} - -static int -SProcRenderCreateLinearGradient (ClientPtr client) -{ - register int n; - int len; - REQUEST (xRenderCreateLinearGradientReq); - REQUEST_AT_LEAST_SIZE (xRenderCreateLinearGradientReq); - - swaps(&stuff->length, n); - swapl(&stuff->pid, n); - swapl(&stuff->p1.x, n); - swapl(&stuff->p1.y, n); - swapl(&stuff->p2.x, n); - swapl(&stuff->p2.y, n); - swapl(&stuff->nStops, n); - - len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq); - if (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor))) - return BadLength; - if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) - return BadLength; - - swapStops(stuff+1, stuff->nStops); - - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderCreateRadialGradient (ClientPtr client) -{ - register int n; - int len; - REQUEST (xRenderCreateRadialGradientReq); - REQUEST_AT_LEAST_SIZE (xRenderCreateRadialGradientReq); - - swaps(&stuff->length, n); - swapl(&stuff->pid, n); - swapl(&stuff->inner.x, n); - swapl(&stuff->inner.y, n); - swapl(&stuff->outer.x, n); - swapl(&stuff->outer.y, n); - swapl(&stuff->inner_radius, n); - swapl(&stuff->outer_radius, n); - swapl(&stuff->nStops, n); - - len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq); - if (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor))) - return BadLength; - if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) - return BadLength; - - swapStops(stuff+1, stuff->nStops); - - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderCreateConicalGradient (ClientPtr client) -{ - register int n; - int len; - REQUEST (xRenderCreateConicalGradientReq); - REQUEST_AT_LEAST_SIZE (xRenderCreateConicalGradientReq); - - swaps(&stuff->length, n); - swapl(&stuff->pid, n); - swapl(&stuff->center.x, n); - swapl(&stuff->center.y, n); - swapl(&stuff->angle, n); - swapl(&stuff->nStops, n); - - len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq); - if (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor))) - return BadLength; - if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) - return BadLength; - - swapStops(stuff+1, stuff->nStops); - - return (*ProcRenderVector[stuff->renderReqType]) (client); -} - -static int -SProcRenderDispatch (ClientPtr client) -{ - REQUEST(xReq); - - if (stuff->data < RenderNumberRequests) - return (*SProcRenderVector[stuff->data]) (client); - else - return BadRequest; -} - -#ifdef PANORAMIX -#include "panoramiX.h" -#include "panoramiXsrv.h" - -#define VERIFY_XIN_PICTURE(pPicture, pid, client, mode) {\ - int rc = dixLookupResourceByType((pointer *)&(pPicture), pid,\ - XRT_PICTURE, client, mode);\ - if (rc != Success)\ - return (rc == BadValue) ? RenderErrBase + BadPicture : rc;\ -} - -#define VERIFY_XIN_ALPHA(pPicture, pid, client, mode) {\ - if (pid == None) \ - pPicture = 0; \ - else { \ - VERIFY_XIN_PICTURE(pPicture, pid, client, mode); \ - } \ -} \ - -int (*PanoramiXSaveRenderVector[RenderNumberRequests])(ClientPtr); - -unsigned long XRT_PICTURE; - -static int -PanoramiXRenderCreatePicture (ClientPtr client) -{ - REQUEST(xRenderCreatePictureReq); - PanoramiXRes *refDraw, *newPict; - int result, j; - - REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); - result = dixLookupResourceByClass((pointer *)&refDraw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - if(!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes)))) - return BadAlloc; - newPict->type = XRT_PICTURE; - newPict->info[0].id = stuff->pid; - - if (refDraw->type == XRT_WINDOW && - stuff->drawable == WindowTable[0]->drawable.id) - { - newPict->u.pict.root = TRUE; - } - else - newPict->u.pict.root = FALSE; - - for(j = 1; j < PanoramiXNumScreens; j++) - newPict->info[j].id = FakeClientID(client->index); - - FOR_NSCREENS_BACKWARD(j) { - stuff->pid = newPict->info[j].id; - stuff->drawable = refDraw->info[j].id; - result = (*PanoramiXSaveRenderVector[X_RenderCreatePicture]) (client); - if(result != Success) break; - } - - if (result == Success) - AddResource(newPict->info[0].id, XRT_PICTURE, newPict); - else - free(newPict); - - return (result); -} - -static int -PanoramiXRenderChangePicture (ClientPtr client) -{ - PanoramiXRes *pict; - int result = Success, j; - REQUEST(xRenderChangePictureReq); - - REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq); - - VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess); - - FOR_NSCREENS_BACKWARD(j) { - stuff->picture = pict->info[j].id; - result = (*PanoramiXSaveRenderVector[X_RenderChangePicture]) (client); - if(result != Success) break; - } - - return (result); -} - -static int -PanoramiXRenderSetPictureClipRectangles (ClientPtr client) -{ - REQUEST(xRenderSetPictureClipRectanglesReq); - int result = Success, j; - PanoramiXRes *pict; - - REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); - - VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess); - - FOR_NSCREENS_BACKWARD(j) { - stuff->picture = pict->info[j].id; - result = (*PanoramiXSaveRenderVector[X_RenderSetPictureClipRectangles]) (client); - if(result != Success) break; - } - - return (result); -} - -static int -PanoramiXRenderSetPictureTransform (ClientPtr client) -{ - REQUEST(xRenderSetPictureTransformReq); - int result = Success, j; - PanoramiXRes *pict; - - REQUEST_AT_LEAST_SIZE(xRenderSetPictureTransformReq); - - VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess); - - FOR_NSCREENS_BACKWARD(j) { - stuff->picture = pict->info[j].id; - result = (*PanoramiXSaveRenderVector[X_RenderSetPictureTransform]) (client); - if(result != Success) break; - } - - return (result); -} - -static int -PanoramiXRenderSetPictureFilter (ClientPtr client) -{ - REQUEST(xRenderSetPictureFilterReq); - int result = Success, j; - PanoramiXRes *pict; - - REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq); - - VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess); - - FOR_NSCREENS_BACKWARD(j) { - stuff->picture = pict->info[j].id; - result = (*PanoramiXSaveRenderVector[X_RenderSetPictureFilter]) (client); - if(result != Success) break; - } - - return (result); -} - -static int -PanoramiXRenderFreePicture (ClientPtr client) -{ - PanoramiXRes *pict; - int result = Success, j; - REQUEST(xRenderFreePictureReq); - - REQUEST_SIZE_MATCH(xRenderFreePictureReq); - - client->errorValue = stuff->picture; - - VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixDestroyAccess); - - - FOR_NSCREENS_BACKWARD(j) { - stuff->picture = pict->info[j].id; - result = (*PanoramiXSaveRenderVector[X_RenderFreePicture]) (client); - if(result != Success) break; - } - - /* Since ProcRenderFreePicture is using FreeResource, it will free - our resource for us on the last pass through the loop above */ - - return (result); -} - -static int -PanoramiXRenderComposite (ClientPtr client) -{ - PanoramiXRes *src, *msk, *dst; - int result = Success, j; - xRenderCompositeReq orig; - REQUEST(xRenderCompositeReq); - - REQUEST_SIZE_MATCH(xRenderCompositeReq); - - VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess); - VERIFY_XIN_ALPHA (msk, stuff->mask, client, DixReadAccess); - VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); - - orig = *stuff; - - FOR_NSCREENS_FORWARD(j) { - stuff->src = src->info[j].id; - if (src->u.pict.root) - { - stuff->xSrc = orig.xSrc - panoramiXdataPtr[j].x; - stuff->ySrc = orig.ySrc - panoramiXdataPtr[j].y; - } - stuff->dst = dst->info[j].id; - if (dst->u.pict.root) - { - stuff->xDst = orig.xDst - panoramiXdataPtr[j].x; - stuff->yDst = orig.yDst - panoramiXdataPtr[j].y; - } - if (msk) - { - stuff->mask = msk->info[j].id; - if (msk->u.pict.root) - { - stuff->xMask = orig.xMask - panoramiXdataPtr[j].x; - stuff->yMask = orig.yMask - panoramiXdataPtr[j].y; - } - } - result = (*PanoramiXSaveRenderVector[X_RenderComposite]) (client); - if(result != Success) break; - } - - return result; -} - -static int -PanoramiXRenderCompositeGlyphs (ClientPtr client) -{ - PanoramiXRes *src, *dst; - int result = Success, j; - REQUEST(xRenderCompositeGlyphsReq); - xGlyphElt origElt, *elt; - INT16 xSrc, ySrc; - - REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); - VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess); - VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); - - if (client->req_len << 2 >= (sizeof (xRenderCompositeGlyphsReq) + - sizeof (xGlyphElt))) - { - elt = (xGlyphElt *) (stuff + 1); - origElt = *elt; - xSrc = stuff->xSrc; - ySrc = stuff->ySrc; - FOR_NSCREENS_FORWARD(j) { - stuff->src = src->info[j].id; - if (src->u.pict.root) - { - stuff->xSrc = xSrc - panoramiXdataPtr[j].x; - stuff->ySrc = ySrc - panoramiXdataPtr[j].y; - } - stuff->dst = dst->info[j].id; - if (dst->u.pict.root) - { - elt->deltax = origElt.deltax - panoramiXdataPtr[j].x; - elt->deltay = origElt.deltay - panoramiXdataPtr[j].y; - } - result = (*PanoramiXSaveRenderVector[stuff->renderReqType]) (client); - if(result != Success) break; - } - } - - return result; -} - -static int -PanoramiXRenderFillRectangles (ClientPtr client) -{ - PanoramiXRes *dst; - int result = Success, j; - REQUEST(xRenderFillRectanglesReq); - char *extra; - int extra_len; - - REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); - VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); - extra_len = (client->req_len << 2) - sizeof (xRenderFillRectanglesReq); - if (extra_len && - (extra = (char *) malloc(extra_len))) - { - memcpy (extra, stuff + 1, extra_len); - FOR_NSCREENS_FORWARD(j) { - if (j) memcpy (stuff + 1, extra, extra_len); - if (dst->u.pict.root) - { - int x_off = panoramiXdataPtr[j].x; - int y_off = panoramiXdataPtr[j].y; - - if(x_off || y_off) { - xRectangle *rects = (xRectangle *) (stuff + 1); - int i = extra_len / sizeof (xRectangle); - - while (i--) - { - rects->x -= x_off; - rects->y -= y_off; - rects++; - } - } - } - stuff->dst = dst->info[j].id; - result = (*PanoramiXSaveRenderVector[X_RenderFillRectangles]) (client); - if(result != Success) break; - } - free(extra); - } - - return result; -} - -static int -PanoramiXRenderTrapezoids(ClientPtr client) -{ - PanoramiXRes *src, *dst; - int result = Success, j; - REQUEST(xRenderTrapezoidsReq); - char *extra; - int extra_len; - - REQUEST_AT_LEAST_SIZE (xRenderTrapezoidsReq); - - VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess); - VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); - - extra_len = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq); - - if (extra_len && - (extra = (char *) malloc(extra_len))) { - memcpy (extra, stuff + 1, extra_len); - - FOR_NSCREENS_FORWARD(j) { - if (j) memcpy (stuff + 1, extra, extra_len); - if (dst->u.pict.root) { - int x_off = panoramiXdataPtr[j].x; - int y_off = panoramiXdataPtr[j].y; - - if(x_off || y_off) { - xTrapezoid *trap = (xTrapezoid *) (stuff + 1); - int i = extra_len / sizeof (xTrapezoid); - - while (i--) { - trap->top -= y_off; - trap->bottom -= y_off; - trap->left.p1.x -= x_off; - trap->left.p1.y -= y_off; - trap->left.p2.x -= x_off; - trap->left.p2.y -= y_off; - trap->right.p1.x -= x_off; - trap->right.p1.y -= y_off; - trap->right.p2.x -= x_off; - trap->right.p2.y -= y_off; - trap++; - } - } - } - - stuff->src = src->info[j].id; - stuff->dst = dst->info[j].id; - result = - (*PanoramiXSaveRenderVector[X_RenderTrapezoids]) (client); - - if(result != Success) break; - } - - free(extra); - } - - return result; -} - -static int -PanoramiXRenderTriangles(ClientPtr client) -{ - PanoramiXRes *src, *dst; - int result = Success, j; - REQUEST(xRenderTrianglesReq); - char *extra; - int extra_len; - - REQUEST_AT_LEAST_SIZE (xRenderTrianglesReq); - - VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess); - VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); - - extra_len = (client->req_len << 2) - sizeof (xRenderTrianglesReq); - - if (extra_len && - (extra = (char *) malloc(extra_len))) { - memcpy (extra, stuff + 1, extra_len); - - FOR_NSCREENS_FORWARD(j) { - if (j) memcpy (stuff + 1, extra, extra_len); - if (dst->u.pict.root) { - int x_off = panoramiXdataPtr[j].x; - int y_off = panoramiXdataPtr[j].y; - - if(x_off || y_off) { - xTriangle *tri = (xTriangle *) (stuff + 1); - int i = extra_len / sizeof (xTriangle); - - while (i--) { - tri->p1.x -= x_off; - tri->p1.y -= y_off; - tri->p2.x -= x_off; - tri->p2.y -= y_off; - tri->p3.x -= x_off; - tri->p3.y -= y_off; - tri++; - } - } - } - - stuff->src = src->info[j].id; - stuff->dst = dst->info[j].id; - result = - (*PanoramiXSaveRenderVector[X_RenderTriangles]) (client); - - if(result != Success) break; - } - - free(extra); - } - - return result; -} - -static int -PanoramiXRenderTriStrip(ClientPtr client) -{ - PanoramiXRes *src, *dst; - int result = Success, j; - REQUEST(xRenderTriStripReq); - char *extra; - int extra_len; - - REQUEST_AT_LEAST_SIZE (xRenderTriStripReq); - - VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess); - VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); - - extra_len = (client->req_len << 2) - sizeof (xRenderTriStripReq); - - if (extra_len && - (extra = (char *) malloc(extra_len))) { - memcpy (extra, stuff + 1, extra_len); - - FOR_NSCREENS_FORWARD(j) { - if (j) memcpy (stuff + 1, extra, extra_len); - if (dst->u.pict.root) { - int x_off = panoramiXdataPtr[j].x; - int y_off = panoramiXdataPtr[j].y; - - if(x_off || y_off) { - xPointFixed *fixed = (xPointFixed *) (stuff + 1); - int i = extra_len / sizeof (xPointFixed); - - while (i--) { - fixed->x -= x_off; - fixed->y -= y_off; - fixed++; - } - } - } - - stuff->src = src->info[j].id; - stuff->dst = dst->info[j].id; - result = - (*PanoramiXSaveRenderVector[X_RenderTriStrip]) (client); - - if(result != Success) break; - } - - free(extra); - } - - return result; -} - -static int -PanoramiXRenderTriFan(ClientPtr client) -{ - PanoramiXRes *src, *dst; - int result = Success, j; - REQUEST(xRenderTriFanReq); - char *extra; - int extra_len; - - REQUEST_AT_LEAST_SIZE (xRenderTriFanReq); - - VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess); - VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); - - extra_len = (client->req_len << 2) - sizeof (xRenderTriFanReq); - - if (extra_len && - (extra = (char *) malloc(extra_len))) { - memcpy (extra, stuff + 1, extra_len); - - FOR_NSCREENS_FORWARD(j) { - if (j) memcpy (stuff + 1, extra, extra_len); - if (dst->u.pict.root) { - int x_off = panoramiXdataPtr[j].x; - int y_off = panoramiXdataPtr[j].y; - - if(x_off || y_off) { - xPointFixed *fixed = (xPointFixed *) (stuff + 1); - int i = extra_len / sizeof (xPointFixed); - - while (i--) { - fixed->x -= x_off; - fixed->y -= y_off; - fixed++; - } - } - } - - stuff->src = src->info[j].id; - stuff->dst = dst->info[j].id; - result = - (*PanoramiXSaveRenderVector[X_RenderTriFan]) (client); - - if(result != Success) break; - } - - free(extra); - } - - return result; -} - -static int -PanoramiXRenderAddTraps (ClientPtr client) -{ - PanoramiXRes *picture; - int result = Success, j; - REQUEST(xRenderAddTrapsReq); - char *extra; - int extra_len; - INT16 x_off, y_off; - - REQUEST_AT_LEAST_SIZE (xRenderAddTrapsReq); - VERIFY_XIN_PICTURE (picture, stuff->picture, client, DixWriteAccess); - extra_len = (client->req_len << 2) - sizeof (xRenderAddTrapsReq); - if (extra_len && - (extra = (char *) malloc(extra_len))) - { - memcpy (extra, stuff + 1, extra_len); - x_off = stuff->xOff; - y_off = stuff->yOff; - FOR_NSCREENS_FORWARD(j) { - if (j) memcpy (stuff + 1, extra, extra_len); - stuff->picture = picture->info[j].id; - - if (picture->u.pict.root) - { - stuff->xOff = x_off + panoramiXdataPtr[j].x; - stuff->yOff = y_off + panoramiXdataPtr[j].y; - } - result = (*PanoramiXSaveRenderVector[X_RenderAddTraps]) (client); - if(result != Success) break; - } - free(extra); - } - - return result; -} - -static int -PanoramiXRenderCreateSolidFill (ClientPtr client) -{ - REQUEST(xRenderCreateSolidFillReq); - PanoramiXRes *newPict; - int result = Success, j; - - REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq); - - if(!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes)))) - return BadAlloc; - - newPict->type = XRT_PICTURE; - newPict->info[0].id = stuff->pid; - newPict->u.pict.root = FALSE; - - for(j = 1; j < PanoramiXNumScreens; j++) - newPict->info[j].id = FakeClientID(client->index); - - FOR_NSCREENS_BACKWARD(j) { - stuff->pid = newPict->info[j].id; - result = (*PanoramiXSaveRenderVector[X_RenderCreateSolidFill]) (client); - if(result != Success) break; - } - - if (result == Success) - AddResource(newPict->info[0].id, XRT_PICTURE, newPict); - else - free(newPict); - - return result; -} - -static int -PanoramiXRenderCreateLinearGradient (ClientPtr client) -{ - REQUEST(xRenderCreateLinearGradientReq); - PanoramiXRes *newPict; - int result = Success, j; - - REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq); - - if(!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes)))) - return BadAlloc; - - newPict->type = XRT_PICTURE; - newPict->info[0].id = stuff->pid; - newPict->u.pict.root = FALSE; - - for(j = 1; j < PanoramiXNumScreens; j++) - newPict->info[j].id = FakeClientID(client->index); - - FOR_NSCREENS_BACKWARD(j) { - stuff->pid = newPict->info[j].id; - result = (*PanoramiXSaveRenderVector[X_RenderCreateLinearGradient]) (client); - if(result != Success) break; - } - - if (result == Success) - AddResource(newPict->info[0].id, XRT_PICTURE, newPict); - else - free(newPict); - - return result; -} - -static int -PanoramiXRenderCreateRadialGradient (ClientPtr client) -{ - REQUEST(xRenderCreateRadialGradientReq); - PanoramiXRes *newPict; - int result = Success, j; - - REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq); - - if(!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes)))) - return BadAlloc; - - newPict->type = XRT_PICTURE; - newPict->info[0].id = stuff->pid; - newPict->u.pict.root = FALSE; - - for(j = 1; j < PanoramiXNumScreens; j++) - newPict->info[j].id = FakeClientID(client->index); - - FOR_NSCREENS_BACKWARD(j) { - stuff->pid = newPict->info[j].id; - result = (*PanoramiXSaveRenderVector[X_RenderCreateRadialGradient]) (client); - if(result != Success) break; - } - - if (result == Success) - AddResource(newPict->info[0].id, XRT_PICTURE, newPict); - else - free(newPict); - - return result; -} - -static int -PanoramiXRenderCreateConicalGradient (ClientPtr client) -{ - REQUEST(xRenderCreateConicalGradientReq); - PanoramiXRes *newPict; - int result = Success, j; - - REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq); - - if(!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes)))) - return BadAlloc; - - newPict->type = XRT_PICTURE; - newPict->info[0].id = stuff->pid; - newPict->u.pict.root = FALSE; - - for(j = 1; j < PanoramiXNumScreens; j++) - newPict->info[j].id = FakeClientID(client->index); - - FOR_NSCREENS_BACKWARD(j) { - stuff->pid = newPict->info[j].id; - result = (*PanoramiXSaveRenderVector[X_RenderCreateConicalGradient]) (client); - if(result != Success) break; - } - - if (result == Success) - AddResource(newPict->info[0].id, XRT_PICTURE, newPict); - else - free(newPict); - - return result; -} - -void -PanoramiXRenderInit (void) -{ - int i; - - XRT_PICTURE = CreateNewResourceType (XineramaDeleteResource, - "XineramaPicture"); - for (i = 0; i < RenderNumberRequests; i++) - PanoramiXSaveRenderVector[i] = ProcRenderVector[i]; - /* - * Stuff in Xinerama aware request processing hooks - */ - ProcRenderVector[X_RenderCreatePicture] = PanoramiXRenderCreatePicture; - ProcRenderVector[X_RenderChangePicture] = PanoramiXRenderChangePicture; - ProcRenderVector[X_RenderSetPictureTransform] = PanoramiXRenderSetPictureTransform; - ProcRenderVector[X_RenderSetPictureFilter] = PanoramiXRenderSetPictureFilter; - ProcRenderVector[X_RenderSetPictureClipRectangles] = PanoramiXRenderSetPictureClipRectangles; - ProcRenderVector[X_RenderFreePicture] = PanoramiXRenderFreePicture; - ProcRenderVector[X_RenderComposite] = PanoramiXRenderComposite; - ProcRenderVector[X_RenderCompositeGlyphs8] = PanoramiXRenderCompositeGlyphs; - ProcRenderVector[X_RenderCompositeGlyphs16] = PanoramiXRenderCompositeGlyphs; - ProcRenderVector[X_RenderCompositeGlyphs32] = PanoramiXRenderCompositeGlyphs; - ProcRenderVector[X_RenderFillRectangles] = PanoramiXRenderFillRectangles; - - ProcRenderVector[X_RenderTrapezoids] = PanoramiXRenderTrapezoids; - ProcRenderVector[X_RenderTriangles] = PanoramiXRenderTriangles; - ProcRenderVector[X_RenderTriStrip] = PanoramiXRenderTriStrip; - ProcRenderVector[X_RenderTriFan] = PanoramiXRenderTriFan; - ProcRenderVector[X_RenderAddTraps] = PanoramiXRenderAddTraps; - - ProcRenderVector[X_RenderCreateSolidFill] = PanoramiXRenderCreateSolidFill; - ProcRenderVector[X_RenderCreateLinearGradient] = PanoramiXRenderCreateLinearGradient; - ProcRenderVector[X_RenderCreateRadialGradient] = PanoramiXRenderCreateRadialGradient; - ProcRenderVector[X_RenderCreateConicalGradient] = PanoramiXRenderCreateConicalGradient; -} - -void -PanoramiXRenderReset (void) -{ - int i; - for (i = 0; i < RenderNumberRequests; i++) - ProcRenderVector[i] = PanoramiXSaveRenderVector[i]; -} - -#endif /* PANORAMIX */ +/* + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "colormapst.h" +#include "extnsionst.h" +#include "servermd.h" +#include <X11/extensions/render.h> +#include <X11/extensions/renderproto.h> +#include "picturestr.h" +#include "glyphstr.h" +#include <X11/Xfuncproto.h> +#include "cursorstr.h" +#include "xace.h" +#include "protocol-versions.h" + +#if HAVE_STDINT_H +#include <stdint.h> +#elif !defined(UINT32_MAX) +#define UINT32_MAX 0xffffffffU +#endif + +static int ProcRenderQueryVersion (ClientPtr pClient); +static int ProcRenderQueryPictFormats (ClientPtr pClient); +static int ProcRenderQueryPictIndexValues (ClientPtr pClient); +static int ProcRenderQueryDithers (ClientPtr pClient); +static int ProcRenderCreatePicture (ClientPtr pClient); +static int ProcRenderChangePicture (ClientPtr pClient); +static int ProcRenderSetPictureClipRectangles (ClientPtr pClient); +static int ProcRenderFreePicture (ClientPtr pClient); +static int ProcRenderComposite (ClientPtr pClient); +static int ProcRenderScale (ClientPtr pClient); +static int ProcRenderTrapezoids (ClientPtr pClient); +static int ProcRenderTriangles (ClientPtr pClient); +static int ProcRenderTriStrip (ClientPtr pClient); +static int ProcRenderTriFan (ClientPtr pClient); +static int ProcRenderColorTrapezoids (ClientPtr pClient); +static int ProcRenderColorTriangles (ClientPtr pClient); +static int ProcRenderTransform (ClientPtr pClient); +static int ProcRenderCreateGlyphSet (ClientPtr pClient); +static int ProcRenderReferenceGlyphSet (ClientPtr pClient); +static int ProcRenderFreeGlyphSet (ClientPtr pClient); +static int ProcRenderAddGlyphs (ClientPtr pClient); +static int ProcRenderAddGlyphsFromPicture (ClientPtr pClient); +static int ProcRenderFreeGlyphs (ClientPtr pClient); +static int ProcRenderCompositeGlyphs (ClientPtr pClient); +static int ProcRenderFillRectangles (ClientPtr pClient); +static int ProcRenderCreateCursor (ClientPtr pClient); +static int ProcRenderSetPictureTransform (ClientPtr pClient); +static int ProcRenderQueryFilters (ClientPtr pClient); +static int ProcRenderSetPictureFilter (ClientPtr pClient); +static int ProcRenderCreateAnimCursor (ClientPtr pClient); +static int ProcRenderAddTraps (ClientPtr pClient); +static int ProcRenderCreateSolidFill (ClientPtr pClient); +static int ProcRenderCreateLinearGradient (ClientPtr pClient); +static int ProcRenderCreateRadialGradient (ClientPtr pClient); +static int ProcRenderCreateConicalGradient (ClientPtr pClient); + +static int ProcRenderDispatch (ClientPtr pClient); + +static int SProcRenderQueryVersion (ClientPtr pClient); +static int SProcRenderQueryPictFormats (ClientPtr pClient); +static int SProcRenderQueryPictIndexValues (ClientPtr pClient); +static int SProcRenderQueryDithers (ClientPtr pClient); +static int SProcRenderCreatePicture (ClientPtr pClient); +static int SProcRenderChangePicture (ClientPtr pClient); +static int SProcRenderSetPictureClipRectangles (ClientPtr pClient); +static int SProcRenderFreePicture (ClientPtr pClient); +static int SProcRenderComposite (ClientPtr pClient); +static int SProcRenderScale (ClientPtr pClient); +static int SProcRenderTrapezoids (ClientPtr pClient); +static int SProcRenderTriangles (ClientPtr pClient); +static int SProcRenderTriStrip (ClientPtr pClient); +static int SProcRenderTriFan (ClientPtr pClient); +static int SProcRenderColorTrapezoids (ClientPtr pClient); +static int SProcRenderColorTriangles (ClientPtr pClient); +static int SProcRenderTransform (ClientPtr pClient); +static int SProcRenderCreateGlyphSet (ClientPtr pClient); +static int SProcRenderReferenceGlyphSet (ClientPtr pClient); +static int SProcRenderFreeGlyphSet (ClientPtr pClient); +static int SProcRenderAddGlyphs (ClientPtr pClient); +static int SProcRenderAddGlyphsFromPicture (ClientPtr pClient); +static int SProcRenderFreeGlyphs (ClientPtr pClient); +static int SProcRenderCompositeGlyphs (ClientPtr pClient); +static int SProcRenderFillRectangles (ClientPtr pClient); +static int SProcRenderCreateCursor (ClientPtr pClient); +static int SProcRenderSetPictureTransform (ClientPtr pClient); +static int SProcRenderQueryFilters (ClientPtr pClient); +static int SProcRenderSetPictureFilter (ClientPtr pClient); +static int SProcRenderCreateAnimCursor (ClientPtr pClient); +static int SProcRenderAddTraps (ClientPtr pClient); +static int SProcRenderCreateSolidFill (ClientPtr pClient); +static int SProcRenderCreateLinearGradient (ClientPtr pClient); +static int SProcRenderCreateRadialGradient (ClientPtr pClient); +static int SProcRenderCreateConicalGradient (ClientPtr pClient); + +static int SProcRenderDispatch (ClientPtr pClient); + +int (*ProcRenderVector[RenderNumberRequests])(ClientPtr) = { + ProcRenderQueryVersion, + ProcRenderQueryPictFormats, + ProcRenderQueryPictIndexValues, + ProcRenderQueryDithers, + ProcRenderCreatePicture, + ProcRenderChangePicture, + ProcRenderSetPictureClipRectangles, + ProcRenderFreePicture, + ProcRenderComposite, + ProcRenderScale, + ProcRenderTrapezoids, + ProcRenderTriangles, + ProcRenderTriStrip, + ProcRenderTriFan, + ProcRenderColorTrapezoids, + ProcRenderColorTriangles, + ProcRenderTransform, + ProcRenderCreateGlyphSet, + ProcRenderReferenceGlyphSet, + ProcRenderFreeGlyphSet, + ProcRenderAddGlyphs, + ProcRenderAddGlyphsFromPicture, + ProcRenderFreeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderFillRectangles, + ProcRenderCreateCursor, + ProcRenderSetPictureTransform, + ProcRenderQueryFilters, + ProcRenderSetPictureFilter, + ProcRenderCreateAnimCursor, + ProcRenderAddTraps, + ProcRenderCreateSolidFill, + ProcRenderCreateLinearGradient, + ProcRenderCreateRadialGradient, + ProcRenderCreateConicalGradient +}; + +int (*SProcRenderVector[RenderNumberRequests])(ClientPtr) = { + SProcRenderQueryVersion, + SProcRenderQueryPictFormats, + SProcRenderQueryPictIndexValues, + SProcRenderQueryDithers, + SProcRenderCreatePicture, + SProcRenderChangePicture, + SProcRenderSetPictureClipRectangles, + SProcRenderFreePicture, + SProcRenderComposite, + SProcRenderScale, + SProcRenderTrapezoids, + SProcRenderTriangles, + SProcRenderTriStrip, + SProcRenderTriFan, + SProcRenderColorTrapezoids, + SProcRenderColorTriangles, + SProcRenderTransform, + SProcRenderCreateGlyphSet, + SProcRenderReferenceGlyphSet, + SProcRenderFreeGlyphSet, + SProcRenderAddGlyphs, + SProcRenderAddGlyphsFromPicture, + SProcRenderFreeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderFillRectangles, + SProcRenderCreateCursor, + SProcRenderSetPictureTransform, + SProcRenderQueryFilters, + SProcRenderSetPictureFilter, + SProcRenderCreateAnimCursor, + SProcRenderAddTraps, + SProcRenderCreateSolidFill, + SProcRenderCreateLinearGradient, + SProcRenderCreateRadialGradient, + SProcRenderCreateConicalGradient +}; + +int RenderErrBase; +static int RenderClientPrivateKeyIndex; +DevPrivateKey RenderClientPrivateKey = &RenderClientPrivateKeyIndex; + +typedef struct _RenderClient { + int major_version; + int minor_version; +} RenderClientRec, *RenderClientPtr; + +#define GetRenderClient(pClient) ((RenderClientPtr)dixLookupPrivate(&(pClient)->devPrivates, RenderClientPrivateKey)) + +static void +RenderClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + RenderClientPtr pRenderClient = GetRenderClient (pClient); + + pRenderClient->major_version = 0; + pRenderClient->minor_version = 0; +} + +#ifdef PANORAMIX +unsigned long XRT_PICTURE; +#endif + +void +RenderExtensionInit (void) +{ + ExtensionEntry *extEntry; + + if (!PictureType) + return; + if (!PictureFinishInit ()) + return; + if (!dixRequestPrivate(RenderClientPrivateKey, sizeof(RenderClientRec))) + return; + if (!AddCallback (&ClientStateCallback, RenderClientCallback, 0)) + return; + + extEntry = AddExtension (RENDER_NAME, 0, RenderNumberErrors, + ProcRenderDispatch, SProcRenderDispatch, + NULL, StandardMinorOpcode); + if (!extEntry) + return; + RenderErrBase = extEntry->errorBase; +#ifdef PANORAMIX + if (XRT_PICTURE) + SetResourceTypeErrorValue(XRT_PICTURE, RenderErrBase + BadPicture); +#endif + SetResourceTypeErrorValue(PictureType, RenderErrBase + BadPicture); + SetResourceTypeErrorValue(PictFormatType, RenderErrBase + BadPictFormat); + SetResourceTypeErrorValue(GlyphSetType, RenderErrBase + BadGlyphSet); +} + +static int +ProcRenderQueryVersion (ClientPtr client) +{ + RenderClientPtr pRenderClient = GetRenderClient (client); + xRenderQueryVersionReply rep; + register int n; + REQUEST(xRenderQueryVersionReq); + + pRenderClient->major_version = stuff->majorVersion; + pRenderClient->minor_version = stuff->minorVersion; + + REQUEST_SIZE_MATCH(xRenderQueryVersionReq); + memset(&rep, 0, sizeof(xRenderQueryVersionReply)); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if ((stuff->majorVersion * 1000 + stuff->minorVersion) < + (SERVER_RENDER_MAJOR_VERSION * 1000 + SERVER_RENDER_MINOR_VERSION)) + { + rep.majorVersion = stuff->majorVersion; + rep.minorVersion = stuff->minorVersion; + } else + { + rep.majorVersion = SERVER_RENDER_MAJOR_VERSION; + rep.minorVersion = SERVER_RENDER_MINOR_VERSION; + } + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xRenderQueryVersionReply), (char *)&rep); + return Success; +} + +static VisualPtr +findVisual (ScreenPtr pScreen, VisualID vid) +{ + VisualPtr pVisual; + int v; + + for (v = 0; v < pScreen->numVisuals; v++) + { + pVisual = pScreen->visuals + v; + if (pVisual->vid == vid) + return pVisual; + } + return 0; +} + +static int +ProcRenderQueryPictFormats (ClientPtr client) +{ + RenderClientPtr pRenderClient = GetRenderClient (client); + xRenderQueryPictFormatsReply *reply; + xPictScreen *pictScreen; + xPictDepth *pictDepth; + xPictVisual *pictVisual; + xPictFormInfo *pictForm; + CARD32 *pictSubpixel; + ScreenPtr pScreen; + VisualPtr pVisual; + DepthPtr pDepth; + int v, d; + PictureScreenPtr ps; + PictFormatPtr pFormat; + int nformat; + int ndepth; + int nvisual; + int rlength; + int s; + int n; + int numScreens; + int numSubpixel; +/* REQUEST(xRenderQueryPictFormatsReq); */ + + REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq); + +#ifdef PANORAMIX + if (noPanoramiXExtension) + numScreens = screenInfo.numScreens; + else + numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; +#else + numScreens = screenInfo.numScreens; +#endif + ndepth = nformat = nvisual = 0; + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = pScreen->allowedDepths + d; + ++ndepth; + + for (v = 0; v < pDepth->numVids; v++) + { + pVisual = findVisual (pScreen, pDepth->vids[v]); + if (pVisual && PictureMatchVisual (pScreen, pDepth->depth, pVisual)) + ++nvisual; + } + } + ps = GetPictureScreenIfSet(pScreen); + if (ps) + nformat += ps->nformats; + } + if (pRenderClient->major_version == 0 && pRenderClient->minor_version < 6) + numSubpixel = 0; + else + numSubpixel = numScreens; + + rlength = (sizeof (xRenderQueryPictFormatsReply) + + nformat * sizeof (xPictFormInfo) + + numScreens * sizeof (xPictScreen) + + ndepth * sizeof (xPictDepth) + + nvisual * sizeof (xPictVisual) + + numSubpixel * sizeof (CARD32)); + reply = (xRenderQueryPictFormatsReply *) calloc(1, rlength); + if (!reply) + return BadAlloc; + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = bytes_to_int32(rlength - sizeof(xGenericReply)); + reply->numFormats = nformat; + reply->numScreens = numScreens; + reply->numDepths = ndepth; + reply->numVisuals = nvisual; + reply->numSubpixel = numSubpixel; + + pictForm = (xPictFormInfo *) (reply + 1); + + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + { + for (nformat = 0, pFormat = ps->formats; + nformat < ps->nformats; + nformat++, pFormat++) + { + pictForm->id = pFormat->id; + pictForm->type = pFormat->type; + pictForm->depth = pFormat->depth; + pictForm->direct.red = pFormat->direct.red; + pictForm->direct.redMask = pFormat->direct.redMask; + pictForm->direct.green = pFormat->direct.green; + pictForm->direct.greenMask = pFormat->direct.greenMask; + pictForm->direct.blue = pFormat->direct.blue; + pictForm->direct.blueMask = pFormat->direct.blueMask; + pictForm->direct.alpha = pFormat->direct.alpha; + pictForm->direct.alphaMask = pFormat->direct.alphaMask; + if (pFormat->type == PictTypeIndexed && pFormat->index.pColormap) + pictForm->colormap = pFormat->index.pColormap->mid; + else + pictForm->colormap = None; + if (client->swapped) + { + swapl (&pictForm->id, n); + swaps (&pictForm->direct.red, n); + swaps (&pictForm->direct.redMask, n); + swaps (&pictForm->direct.green, n); + swaps (&pictForm->direct.greenMask, n); + swaps (&pictForm->direct.blue, n); + swaps (&pictForm->direct.blueMask, n); + swaps (&pictForm->direct.alpha, n); + swaps (&pictForm->direct.alphaMask, n); + swapl (&pictForm->colormap, n); + } + pictForm++; + } + } + } + + pictScreen = (xPictScreen *) pictForm; + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + pictDepth = (xPictDepth *) (pictScreen + 1); + ndepth = 0; + for (d = 0; d < pScreen->numDepths; d++) + { + pictVisual = (xPictVisual *) (pictDepth + 1); + pDepth = pScreen->allowedDepths + d; + + nvisual = 0; + for (v = 0; v < pDepth->numVids; v++) + { + pVisual = findVisual (pScreen, pDepth->vids[v]); + if (pVisual && (pFormat = PictureMatchVisual (pScreen, + pDepth->depth, + pVisual))) + { + pictVisual->visual = pVisual->vid; + pictVisual->format = pFormat->id; + if (client->swapped) + { + swapl (&pictVisual->visual, n); + swapl (&pictVisual->format, n); + } + pictVisual++; + nvisual++; + } + } + pictDepth->depth = pDepth->depth; + pictDepth->nPictVisuals = nvisual; + if (client->swapped) + { + swaps (&pictDepth->nPictVisuals, n); + } + ndepth++; + pictDepth = (xPictDepth *) pictVisual; + } + pictScreen->nDepth = ndepth; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + pictScreen->fallback = ps->fallback->id; + else + pictScreen->fallback = 0; + if (client->swapped) + { + swapl (&pictScreen->nDepth, n); + swapl (&pictScreen->fallback, n); + } + pictScreen = (xPictScreen *) pictDepth; + } + pictSubpixel = (CARD32 *) pictScreen; + + for (s = 0; s < numSubpixel; s++) + { + pScreen = screenInfo.screens[s]; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + *pictSubpixel = ps->subpixel; + else + *pictSubpixel = SubPixelUnknown; + if (client->swapped) + { + swapl (pictSubpixel, n); + } + ++pictSubpixel; + } + + if (client->swapped) + { + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + swapl (&reply->numFormats, n); + swapl (&reply->numScreens, n); + swapl (&reply->numDepths, n); + swapl (&reply->numVisuals, n); + swapl (&reply->numSubpixel, n); + } + WriteToClient(client, rlength, (char *) reply); + free(reply); + return Success; +} + +static int +ProcRenderQueryPictIndexValues (ClientPtr client) +{ + PictFormatPtr pFormat; + int rc, num; + int rlength; + int i, n; + REQUEST(xRenderQueryPictIndexValuesReq); + xRenderQueryPictIndexValuesReply *reply; + xIndexValue *values; + + REQUEST_AT_LEAST_SIZE(xRenderQueryPictIndexValuesReq); + + rc = dixLookupResourceByType((pointer *)&pFormat, stuff->format, + PictFormatType, client, DixReadAccess); + if (rc != Success) + return rc; + + if (pFormat->type != PictTypeIndexed) + { + client->errorValue = stuff->format; + return BadMatch; + } + num = pFormat->index.nvalues; + rlength = (sizeof (xRenderQueryPictIndexValuesReply) + + num * sizeof(xIndexValue)); + reply = (xRenderQueryPictIndexValuesReply *) malloc(rlength); + if (!reply) + return BadAlloc; + + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = bytes_to_int32(rlength - sizeof(xGenericReply)); + reply->numIndexValues = num; + + values = (xIndexValue *) (reply + 1); + + memcpy (reply + 1, pFormat->index.pValues, num * sizeof (xIndexValue)); + + if (client->swapped) + { + for (i = 0; i < num; i++) + { + swapl (&values[i].pixel, n); + swaps (&values[i].red, n); + swaps (&values[i].green, n); + swaps (&values[i].blue, n); + swaps (&values[i].alpha, n); + } + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + swapl (&reply->numIndexValues, n); + } + + WriteToClient(client, rlength, (char *) reply); + free(reply); + return Success; +} + +static int +ProcRenderQueryDithers (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderCreatePicture (ClientPtr client) +{ + PicturePtr pPicture; + DrawablePtr pDrawable; + PictFormatPtr pFormat; + int len, error, rc; + REQUEST(xRenderCreatePictureReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, + DixReadAccess|DixAddAccess); + if (rc != Success) + return rc; + + rc = dixLookupResourceByType((pointer *)&pFormat, stuff->format, + PictFormatType, client, DixReadAccess); + if (rc != Success) + return rc; + + if (pFormat->depth != pDrawable->depth) + return BadMatch; + len = client->req_len - bytes_to_int32(sizeof(xRenderCreatePictureReq)); + if (Ones(stuff->mask) != len) + return BadLength; + + pPicture = CreatePicture (stuff->pid, + pDrawable, + pFormat, + stuff->mask, + (XID *) (stuff + 1), + client, + &error); + if (!pPicture) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int +ProcRenderChangePicture (ClientPtr client) +{ + PicturePtr pPicture; + REQUEST(xRenderChangePictureReq); + int len; + + REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess); + + len = client->req_len - bytes_to_int32(sizeof(xRenderChangePictureReq)); + if (Ones(stuff->mask) != len) + return BadLength; + + return ChangePicture (pPicture, stuff->mask, (XID *) (stuff + 1), + (DevUnion *) 0, client); +} + +static int +ProcRenderSetPictureClipRectangles (ClientPtr client) +{ + REQUEST(xRenderSetPictureClipRectanglesReq); + PicturePtr pPicture; + int nr; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess); + if (!pPicture->pDrawable) + return BadDrawable; + + nr = (client->req_len << 2) - sizeof(xRenderSetPictureClipRectanglesReq); + if (nr & 4) + return BadLength; + nr >>= 3; + return SetPictureClipRects (pPicture, + stuff->xOrigin, stuff->yOrigin, + nr, (xRectangle *) &stuff[1]); +} + +static int +ProcRenderFreePicture (ClientPtr client) +{ + PicturePtr pPicture; + REQUEST(xRenderFreePictureReq); + + REQUEST_SIZE_MATCH(xRenderFreePictureReq); + + VERIFY_PICTURE (pPicture, stuff->picture, client, DixDestroyAccess); + FreeResource (stuff->picture, RT_NONE); + return Success; +} + +static Bool +PictOpValid (CARD8 op) +{ + if (/*PictOpMinimum <= op && */ op <= PictOpMaximum) + return TRUE; + if (PictOpDisjointMinimum <= op && op <= PictOpDisjointMaximum) + return TRUE; + if (PictOpConjointMinimum <= op && op <= PictOpConjointMaximum) + return TRUE; + if (PictOpBlendMinimum <= op && op <= PictOpBlendMaximum) + return TRUE; + return FALSE; +} + +static int +ProcRenderComposite (ClientPtr client) +{ + PicturePtr pSrc, pMask, pDst; + REQUEST(xRenderCompositeReq); + + REQUEST_SIZE_MATCH(xRenderCompositeReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); + if (!pDst->pDrawable) + return BadDrawable; + VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); + VERIFY_ALPHA (pMask, stuff->mask, client, DixReadAccess); + if ((pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) || + (pMask && pMask->pDrawable && pDst->pDrawable->pScreen != pMask->pDrawable->pScreen)) + return BadMatch; + CompositePicture (stuff->op, + pSrc, + pMask, + pDst, + stuff->xSrc, + stuff->ySrc, + stuff->xMask, + stuff->yMask, + stuff->xDst, + stuff->yDst, + stuff->width, + stuff->height); + return Success; +} + +static int +ProcRenderScale (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderTrapezoids (ClientPtr client) +{ + int rc, ntraps; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrapezoidsReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); + VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat, + PictFormatType, client, DixReadAccess); + if (rc != Success) + return rc; + } + else + pFormat = 0; + ntraps = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq); + if (ntraps % sizeof (xTrapezoid)) + return BadLength; + ntraps /= sizeof (xTrapezoid); + if (ntraps) + CompositeTrapezoids (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntraps, (xTrapezoid *) &stuff[1]); + return Success; +} + +static int +ProcRenderTriangles (ClientPtr client) +{ + int rc, ntris; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); + VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat, + PictFormatType, client, DixReadAccess); + if (rc != Success) + return rc; + } + else + pFormat = 0; + ntris = (client->req_len << 2) - sizeof (xRenderTrianglesReq); + if (ntris % sizeof (xTriangle)) + return BadLength; + ntris /= sizeof (xTriangle); + if (ntris) + CompositeTriangles (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntris, (xTriangle *) &stuff[1]); + return Success; +} + +static int +ProcRenderTriStrip (ClientPtr client) +{ + int rc, npoints; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); + VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat, + PictFormatType, client, DixReadAccess); + if (rc != Success) + return rc; + } + else + pFormat = 0; + npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); + if (npoints & 4) + return(BadLength); + npoints >>= 3; + if (npoints >= 3) + CompositeTriStrip (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + npoints, (xPointFixed *) &stuff[1]); + return Success; +} + +static int +ProcRenderTriFan (ClientPtr client) +{ + int rc, npoints; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); + VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat, + PictFormatType, client, DixReadAccess); + if (rc != Success) + return rc; + } + else + pFormat = 0; + npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); + if (npoints & 4) + return(BadLength); + npoints >>= 3; + if (npoints >= 3) + CompositeTriFan (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + npoints, (xPointFixed *) &stuff[1]); + return Success; +} + +static int +ProcRenderColorTrapezoids (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderColorTriangles (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderTransform (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderCreateGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + PictFormatPtr format; + int rc, f; + REQUEST(xRenderCreateGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderCreateGlyphSetReq); + + LEGAL_NEW_RESOURCE(stuff->gsid, client); + rc = dixLookupResourceByType((pointer *)&format, stuff->format, + PictFormatType, client, DixReadAccess); + if (rc != Success) + return rc; + + switch (format->depth) { + case 1: + f = GlyphFormat1; + break; + case 4: + f = GlyphFormat4; + break; + case 8: + f = GlyphFormat8; + break; + case 16: + f = GlyphFormat16; + break; + case 32: + f = GlyphFormat32; + break; + default: + return BadMatch; + } + if (format->type != PictTypeDirect) + return BadMatch; + glyphSet = AllocateGlyphSet (f, format); + if (!glyphSet) + return BadAlloc; + /* security creation/labeling check */ + rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->gsid, GlyphSetType, + glyphSet, RT_NONE, NULL, DixCreateAccess); + if (rc != Success) + return rc; + if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) + return BadAlloc; + return Success; +} + +static int +ProcRenderReferenceGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + int rc; + REQUEST(xRenderReferenceGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderReferenceGlyphSetReq); + + LEGAL_NEW_RESOURCE(stuff->gsid, client); + + rc = dixLookupResourceByType((pointer *)&glyphSet, stuff->existing, GlyphSetType, + client, DixGetAttrAccess); + if (rc != Success) + { + client->errorValue = stuff->existing; + return rc; + } + glyphSet->refcnt++; + if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) + return BadAlloc; + return Success; +} + +#define NLOCALDELTA 64 +#define NLOCALGLYPH 256 + +static int +ProcRenderFreeGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + int rc; + REQUEST(xRenderFreeGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq); + rc = dixLookupResourceByType((pointer *)&glyphSet, stuff->glyphset, GlyphSetType, + client, DixDestroyAccess); + if (rc != Success) + { + client->errorValue = stuff->glyphset; + return rc; + } + FreeResource (stuff->glyphset, RT_NONE); + return Success; +} + +typedef struct _GlyphNew { + Glyph id; + GlyphPtr glyph; + Bool found; + unsigned char sha1[20]; +} GlyphNewRec, *GlyphNewPtr; + +#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) + +static int +ProcRenderAddGlyphs (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderAddGlyphsReq); + GlyphNewRec glyphsLocal[NLOCALGLYPH]; + GlyphNewPtr glyphsBase, glyphs, glyph_new; + int remain, nglyphs; + CARD32 *gids; + xGlyphInfo *gi; + CARD8 *bits; + unsigned int size; + int err; + int i, screen; + PicturePtr pSrc = NULL, pDst = NULL; + PixmapPtr pSrcPix = NULL, pDstPix = NULL; + CARD32 component_alpha; + + REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq); + err = dixLookupResourceByType((pointer *)&glyphSet, stuff->glyphset, GlyphSetType, + client, DixAddAccess); + if (err != Success) + { + client->errorValue = stuff->glyphset; + return err; + } + + err = BadAlloc; + nglyphs = stuff->nglyphs; + if (nglyphs > UINT32_MAX / sizeof(GlyphNewRec)) + return BadAlloc; + + component_alpha = NeedsComponent (glyphSet->format->format); + + if (nglyphs <= NLOCALGLYPH) { + memset (glyphsLocal, 0, sizeof (glyphsLocal)); + glyphsBase = glyphsLocal; + } + else + { + glyphsBase = (GlyphNewPtr)calloc(nglyphs, sizeof (GlyphNewRec)); + if (!glyphsBase) + return BadAlloc; + } + + remain = (client->req_len << 2) - sizeof (xRenderAddGlyphsReq); + + glyphs = glyphsBase; + + gids = (CARD32 *) (stuff + 1); + gi = (xGlyphInfo *) (gids + nglyphs); + bits = (CARD8 *) (gi + nglyphs); + remain -= (sizeof (CARD32) + sizeof (xGlyphInfo)) * nglyphs; + for (i = 0; i < nglyphs; i++) + { + size_t padded_width; + glyph_new = &glyphs[i]; + + padded_width = PixmapBytePad (gi[i].width, + glyphSet->format->depth); + + if (gi[i].height && padded_width > (UINT32_MAX - sizeof(GlyphRec))/gi[i].height) + break; + + size = gi[i].height * padded_width; + if (remain < size) + break; + + err = HashGlyph (&gi[i], bits, size, glyph_new->sha1); + if (err) + goto bail; + + glyph_new->glyph = FindGlyphByHash (glyph_new->sha1, + glyphSet->fdepth); + + if (glyph_new->glyph && glyph_new->glyph != DeletedGlyph) + { + glyph_new->found = TRUE; + } + else + { + GlyphPtr glyph; + + glyph_new->found = FALSE; + glyph_new->glyph = glyph = AllocateGlyph (&gi[i], glyphSet->fdepth); + if (! glyph) + { + err = BadAlloc; + goto bail; + } + + for (screen = 0; screen < screenInfo.numScreens; screen++) + { + int width = gi[i].width; + int height = gi[i].height; + int depth = glyphSet->format->depth; + ScreenPtr pScreen; + int error; + + /* Skip work if it's invisibly small anyway */ + if (!width || !height) + break; + + pScreen = screenInfo.screens[screen]; + pSrcPix = GetScratchPixmapHeader (pScreen, + width, height, + depth, depth, + -1, bits); + if (! pSrcPix) + { + err = BadAlloc; + goto bail; + } + + pSrc = CreatePicture (0, &pSrcPix->drawable, + glyphSet->format, 0, NULL, + serverClient, &error); + if (! pSrc) + { + err = BadAlloc; + goto bail; + } + + pDstPix = (pScreen->CreatePixmap) (pScreen, + width, height, depth, + CREATE_PIXMAP_USAGE_GLYPH_PICTURE); + + if (!pDstPix) + { + err = BadAlloc; + goto bail; + } + + GlyphPicture (glyph)[screen] = pDst = + CreatePicture (0, &pDstPix->drawable, + glyphSet->format, + CPComponentAlpha, &component_alpha, + serverClient, &error); + + /* The picture takes a reference to the pixmap, so we + drop ours. */ + (pScreen->DestroyPixmap) (pDstPix); + pDstPix = NULL; + + if (! pDst) + { + err = BadAlloc; + goto bail; + } + + CompositePicture (PictOpSrc, + pSrc, + None, + pDst, + 0, 0, + 0, 0, + 0, 0, + width, height); + + FreePicture ((pointer) pSrc, 0); + pSrc = NULL; + FreeScratchPixmapHeader (pSrcPix); + pSrcPix = NULL; + } + + memcpy (glyph_new->glyph->sha1, glyph_new->sha1, 20); + } + + glyph_new->id = gids[i]; + + if (size & 3) + size += 4 - (size & 3); + bits += size; + remain -= size; + } + if (remain || i < nglyphs) + { + err = BadLength; + goto bail; + } + if (!ResizeGlyphSet (glyphSet, nglyphs)) + { + err = BadAlloc; + goto bail; + } + for (i = 0; i < nglyphs; i++) + AddGlyph (glyphSet, glyphs[i].glyph, glyphs[i].id); + + if (glyphsBase != glyphsLocal) + free(glyphsBase); + return Success; +bail: + if (pSrc) + FreePicture ((pointer) pSrc, 0); + if (pSrcPix) + FreeScratchPixmapHeader (pSrcPix); + for (i = 0; i < nglyphs; i++) + if (glyphs[i].glyph && ! glyphs[i].found) + free(glyphs[i].glyph); + if (glyphsBase != glyphsLocal) + free(glyphsBase); + return err; +} + +static int +ProcRenderAddGlyphsFromPicture (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderFreeGlyphs (ClientPtr client) +{ + REQUEST(xRenderFreeGlyphsReq); + GlyphSetPtr glyphSet; + int rc, nglyph; + CARD32 *gids; + CARD32 glyph; + + REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq); + rc = dixLookupResourceByType((pointer *)&glyphSet, stuff->glyphset, GlyphSetType, + client, DixRemoveAccess); + if (rc != Success) + { + client->errorValue = stuff->glyphset; + return rc; + } + nglyph = bytes_to_int32((client->req_len << 2) - sizeof (xRenderFreeGlyphsReq)); + gids = (CARD32 *) (stuff + 1); + while (nglyph-- > 0) + { + glyph = *gids++; + if (!DeleteGlyph (glyphSet, glyph)) + { + client->errorValue = glyph; + return RenderErrBase + BadGlyph; + } + } + return Success; +} + +static int +ProcRenderCompositeGlyphs (ClientPtr client) +{ + GlyphSetPtr glyphSet; + GlyphSet gs; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + GlyphListRec listsLocal[NLOCALDELTA]; + GlyphListPtr lists, listsBase; + GlyphPtr glyphsLocal[NLOCALGLYPH]; + Glyph glyph; + GlyphPtr *glyphs, *glyphsBase; + xGlyphElt *elt; + CARD8 *buffer, *end; + int nglyph; + int nlist; + int space; + int size; + int rc, n; + + REQUEST(xRenderCompositeGlyphsReq); + + REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); + + switch (stuff->renderReqType) { + default: size = 1; break; + case X_RenderCompositeGlyphs16: size = 2; break; + case X_RenderCompositeGlyphs32: size = 4; break; + } + + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); + VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat, + PictFormatType, client, DixReadAccess); + if (rc != Success) + return rc; + } + else + pFormat = 0; + + rc = dixLookupResourceByType((pointer *)&glyphSet, stuff->glyphset, + GlyphSetType, client, DixUseAccess); + if (rc != Success) + return rc; + + buffer = (CARD8 *) (stuff + 1); + end = (CARD8 *) stuff + (client->req_len << 2); + nglyph = 0; + nlist = 0; + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + if (elt->len == 0xff) + { + buffer += 4; + } + else + { + nlist++; + nglyph += elt->len; + space = size * elt->len; + if (space & 3) + space += 4 - (space & 3); + buffer += space; + } + } + if (nglyph <= NLOCALGLYPH) + glyphsBase = glyphsLocal; + else + { + glyphsBase = (GlyphPtr *) malloc(nglyph * sizeof (GlyphPtr)); + if (!glyphsBase) + return BadAlloc; + } + if (nlist <= NLOCALDELTA) + listsBase = listsLocal; + else + { + listsBase = (GlyphListPtr) malloc(nlist * sizeof (GlyphListRec)); + if (!listsBase) + return BadAlloc; + } + buffer = (CARD8 *) (stuff + 1); + glyphs = glyphsBase; + lists = listsBase; + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + if (elt->len == 0xff) + { + if (buffer + sizeof (GlyphSet) < end) + { + memcpy(&gs, buffer, sizeof(GlyphSet)); + rc = dixLookupResourceByType((pointer *)&glyphSet, gs, + GlyphSetType, client, + DixUseAccess); + if (rc != Success) + { + if (glyphsBase != glyphsLocal) + free(glyphsBase); + if (listsBase != listsLocal) + free(listsBase); + return rc; + } + } + buffer += 4; + } + else + { + lists->xOff = elt->deltax; + lists->yOff = elt->deltay; + lists->format = glyphSet->format; + lists->len = 0; + n = elt->len; + while (n--) + { + if (buffer + size <= end) + { + switch (size) { + case 1: + glyph = *((CARD8 *)buffer); break; + case 2: + glyph = *((CARD16 *)buffer); break; + case 4: + default: + glyph = *((CARD32 *)buffer); break; + } + if ((*glyphs = FindGlyph (glyphSet, glyph))) + { + lists->len++; + glyphs++; + } + } + buffer += size; + } + space = size * elt->len; + if (space & 3) + buffer += 4 - (space & 3); + lists++; + } + } + if (buffer > end) + return BadLength; + + CompositeGlyphs (stuff->op, + pSrc, + pDst, + pFormat, + stuff->xSrc, + stuff->ySrc, + nlist, + listsBase, + glyphsBase); + + if (glyphsBase != glyphsLocal) + free(glyphsBase); + if (listsBase != listsLocal) + free(listsBase); + + return Success; +} + +static int +ProcRenderFillRectangles (ClientPtr client) +{ + PicturePtr pDst; + int things; + REQUEST(xRenderFillRectanglesReq); + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); + if (!pDst->pDrawable) + return BadDrawable; + + things = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq); + if (things & 4) + return(BadLength); + things >>= 3; + + CompositeRects (stuff->op, + pDst, + &stuff->color, + things, + (xRectangle *) &stuff[1]); + + return Success; +} + +static void +RenderSetBit (unsigned char *line, int x, int bit) +{ + unsigned char mask; + + if (screenInfo.bitmapBitOrder == LSBFirst) + mask = (1 << (x & 7)); + else + mask = (0x80 >> (x & 7)); + /* XXX assumes byte order is host byte order */ + line += (x >> 3); + if (bit) + *line |= mask; + else + *line &= ~mask; +} + +#define DITHER_DIM 2 + +static CARD32 orderedDither[DITHER_DIM][DITHER_DIM] = { + { 1, 3, }, + { 4, 2, }, +}; + +#define DITHER_SIZE ((sizeof orderedDither / sizeof orderedDither[0][0]) + 1) + +static int +ProcRenderCreateCursor (ClientPtr client) +{ + REQUEST(xRenderCreateCursorReq); + PicturePtr pSrc; + ScreenPtr pScreen; + unsigned short width, height; + CARD32 *argbbits, *argb; + unsigned char *srcbits, *srcline; + unsigned char *mskbits, *mskline; + int stride; + int x, y; + int nbytes_mono; + CursorMetricRec cm; + CursorPtr pCursor; + CARD32 twocolor[3]; + int rc, ncolor; + + REQUEST_SIZE_MATCH (xRenderCreateCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); + if (!pSrc->pDrawable) + return BadDrawable; + pScreen = pSrc->pDrawable->pScreen; + width = pSrc->pDrawable->width; + height = pSrc->pDrawable->height; + if (height && width > UINT32_MAX/(height*sizeof(CARD32))) + return BadAlloc; + if ( stuff->x > width + || stuff->y > height ) + return (BadMatch); + argbbits = malloc(width * height * sizeof (CARD32)); + if (!argbbits) + return (BadAlloc); + + stride = BitmapBytePad(width); + nbytes_mono = stride*height; + srcbits = calloc(1, nbytes_mono); + if (!srcbits) + { + free(argbbits); + return (BadAlloc); + } + mskbits = calloc(1, nbytes_mono); + if (!mskbits) + { + free(argbbits); + free(srcbits); + return (BadAlloc); + } + + if (pSrc->format == PICT_a8r8g8b8) + { + (*pScreen->GetImage) (pSrc->pDrawable, + 0, 0, width, height, ZPixmap, + 0xffffffff, (pointer) argbbits); + } + else + { + PixmapPtr pPixmap; + PicturePtr pPicture; + PictFormatPtr pFormat; + int error; + + pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); + if (!pFormat) + { + free(argbbits); + free(srcbits); + free(mskbits); + return (BadImplementation); + } + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 32, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!pPixmap) + { + free(argbbits); + free(srcbits); + free(mskbits); + return (BadAlloc); + } + pPicture = CreatePicture (0, &pPixmap->drawable, pFormat, 0, 0, + client, &error); + if (!pPicture) + { + free(argbbits); + free(srcbits); + free(mskbits); + return error; + } + (*pScreen->DestroyPixmap) (pPixmap); + CompositePicture (PictOpSrc, + pSrc, 0, pPicture, + 0, 0, 0, 0, 0, 0, width, height); + (*pScreen->GetImage) (pPicture->pDrawable, + 0, 0, width, height, ZPixmap, + 0xffffffff, (pointer) argbbits); + FreePicture (pPicture, 0); + } + /* + * Check whether the cursor can be directly supported by + * the core cursor code + */ + ncolor = 0; + argb = argbbits; + for (y = 0; ncolor <= 2 && y < height; y++) + { + for (x = 0; ncolor <= 2 && x < width; x++) + { + CARD32 p = *argb++; + CARD32 a = (p >> 24); + + if (a == 0) /* transparent */ + continue; + if (a == 0xff) /* opaque */ + { + int n; + for (n = 0; n < ncolor; n++) + if (p == twocolor[n]) + break; + if (n == ncolor) + twocolor[ncolor++] = p; + } + else + ncolor = 3; + } + } + + /* + * Convert argb image to two plane cursor + */ + srcline = srcbits; + mskline = mskbits; + argb = argbbits; + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + CARD32 p = *argb++; + + if (ncolor <= 2) + { + CARD32 a = ((p >> 24)); + + RenderSetBit (mskline, x, a != 0); + RenderSetBit (srcline, x, a != 0 && p == twocolor[0]); + } + else + { + CARD32 a = ((p >> 24) * DITHER_SIZE + 127) / 255; + CARD32 i = ((CvtR8G8B8toY15(p) >> 7) * DITHER_SIZE + 127) / 255; + CARD32 d = orderedDither[y&(DITHER_DIM-1)][x&(DITHER_DIM-1)]; + /* Set mask from dithered alpha value */ + RenderSetBit(mskline, x, a > d); + /* Set src from dithered intensity value */ + RenderSetBit(srcline, x, a > d && i <= d); + } + } + srcline += stride; + mskline += stride; + } + /* + * Dither to white and black if the cursor has more than two colors + */ + if (ncolor > 2) + { + twocolor[0] = 0xff000000; + twocolor[1] = 0xffffffff; + } + else + { + free(argbbits); + argbbits = 0; + } + +#define GetByte(p,s) (((p) >> (s)) & 0xff) +#define GetColor(p,s) (GetByte(p,s) | (GetByte(p,s) << 8)) + + cm.width = width; + cm.height = height; + cm.xhot = stuff->x; + cm.yhot = stuff->y; + rc = AllocARGBCursor(srcbits, mskbits, argbbits, &cm, + GetColor(twocolor[0], 16), + GetColor(twocolor[0], 8), + GetColor(twocolor[0], 0), + GetColor(twocolor[1], 16), + GetColor(twocolor[1], 8), + GetColor(twocolor[1], 0), + &pCursor, client, stuff->cid); + if (rc != Success) + return rc; + if (!AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return BadAlloc; + + return Success; +} + +static int +ProcRenderSetPictureTransform (ClientPtr client) +{ + REQUEST(xRenderSetPictureTransformReq); + PicturePtr pPicture; + + REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess); + return SetPictureTransform (pPicture, (PictTransform *) &stuff->transform); +} + +static int +ProcRenderQueryFilters (ClientPtr client) +{ + REQUEST (xRenderQueryFiltersReq); + DrawablePtr pDrawable; + xRenderQueryFiltersReply *reply; + int nbytesName; + int nnames; + ScreenPtr pScreen; + PictureScreenPtr ps; + int i, j, len, total_bytes, rc; + INT16 *aliases; + char *names; + + REQUEST_SIZE_MATCH(xRenderQueryFiltersReq); + rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, + DixGetAttrAccess); + if (rc != Success) + return rc; + + pScreen = pDrawable->pScreen; + nbytesName = 0; + nnames = 0; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + { + for (i = 0; i < ps->nfilters; i++) + nbytesName += 1 + strlen (ps->filters[i].name); + for (i = 0; i < ps->nfilterAliases; i++) + nbytesName += 1 + strlen (ps->filterAliases[i].alias); + nnames = ps->nfilters + ps->nfilterAliases; + } + len = ((nnames + 1) >> 1) + bytes_to_int32(nbytesName); + total_bytes = sizeof (xRenderQueryFiltersReply) + (len << 2); + reply = (xRenderQueryFiltersReply *) malloc(total_bytes); + if (!reply) + return BadAlloc; + aliases = (INT16 *) (reply + 1); + names = (char *) (aliases + ((nnames + 1) & ~1)); + + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = len; + reply->numAliases = nnames; + reply->numFilters = nnames; + if (ps) + { + + /* fill in alias values */ + for (i = 0; i < ps->nfilters; i++) + aliases[i] = FilterAliasNone; + for (i = 0; i < ps->nfilterAliases; i++) + { + for (j = 0; j < ps->nfilters; j++) + if (ps->filterAliases[i].filter_id == ps->filters[j].id) + break; + if (j == ps->nfilters) + { + for (j = 0; j < ps->nfilterAliases; j++) + if (ps->filterAliases[i].filter_id == + ps->filterAliases[j].alias_id) + { + break; + } + if (j == ps->nfilterAliases) + j = FilterAliasNone; + else + j = j + ps->nfilters; + } + aliases[i + ps->nfilters] = j; + } + + /* fill in filter names */ + for (i = 0; i < ps->nfilters; i++) + { + j = strlen (ps->filters[i].name); + *names++ = j; + strncpy (names, ps->filters[i].name, j); + names += j; + } + + /* fill in filter alias names */ + for (i = 0; i < ps->nfilterAliases; i++) + { + j = strlen (ps->filterAliases[i].alias); + *names++ = j; + strncpy (names, ps->filterAliases[i].alias, j); + names += j; + } + } + + if (client->swapped) + { + register int n; + + for (i = 0; i < reply->numAliases; i++) + { + swaps (&aliases[i], n); + } + swaps(&reply->sequenceNumber, n); + swapl(&reply->length, n); + swapl(&reply->numAliases, n); + swapl(&reply->numFilters, n); + } + WriteToClient(client, total_bytes, (char *) reply); + free(reply); + + return Success; +} + +static int +ProcRenderSetPictureFilter (ClientPtr client) +{ + REQUEST (xRenderSetPictureFilterReq); + PicturePtr pPicture; + int result; + xFixed *params; + int nparams; + char *name; + + REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess); + name = (char *) (stuff + 1); + params = (xFixed *) (name + pad_to_int32(stuff->nbytes)); + nparams = ((xFixed *) stuff + client->req_len) - params; + result = SetPictureFilter (pPicture, name, stuff->nbytes, params, nparams); + return result; +} + +static int +ProcRenderCreateAnimCursor (ClientPtr client) +{ + REQUEST(xRenderCreateAnimCursorReq); + CursorPtr *cursors; + CARD32 *deltas; + CursorPtr pCursor; + int ncursor; + xAnimCursorElt *elt; + int i; + int ret; + + REQUEST_AT_LEAST_SIZE(xRenderCreateAnimCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + if (client->req_len & 1) + return BadLength; + ncursor = (client->req_len - (bytes_to_int32(sizeof(xRenderCreateAnimCursorReq)))) >> 1; + cursors = malloc(ncursor * (sizeof (CursorPtr) + sizeof (CARD32))); + if (!cursors) + return BadAlloc; + deltas = (CARD32 *) (cursors + ncursor); + elt = (xAnimCursorElt *) (stuff + 1); + for (i = 0; i < ncursor; i++) + { + ret = dixLookupResourceByType((pointer *)(cursors + i), elt->cursor, + RT_CURSOR, client, DixReadAccess); + if (ret != Success) + { + free(cursors); + return ret; + } + deltas[i] = elt->delay; + elt++; + } + ret = AnimCursorCreate (cursors, deltas, ncursor, &pCursor, client, + stuff->cid); + free(cursors); + if (ret != Success) + return ret; + + if (AddResource (stuff->cid, RT_CURSOR, (pointer)pCursor)) + return Success; + return BadAlloc; +} + +static int +ProcRenderAddTraps (ClientPtr client) +{ + int ntraps; + PicturePtr pPicture; + REQUEST(xRenderAddTrapsReq); + + REQUEST_AT_LEAST_SIZE(xRenderAddTrapsReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess); + if (!pPicture->pDrawable) + return BadDrawable; + ntraps = (client->req_len << 2) - sizeof (xRenderAddTrapsReq); + if (ntraps % sizeof (xTrap)) + return BadLength; + ntraps /= sizeof (xTrap); + if (ntraps) + AddTraps (pPicture, + stuff->xOff, stuff->yOff, + ntraps, (xTrap *) &stuff[1]); + return Success; +} + +static int ProcRenderCreateSolidFill(ClientPtr client) +{ + PicturePtr pPicture; + int error = 0; + REQUEST(xRenderCreateSolidFillReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + + pPicture = CreateSolidPicture(stuff->pid, &stuff->color, &error); + if (!pPicture) + return error; + /* security creation/labeling check */ + error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType, + pPicture, RT_NONE, NULL, DixCreateAccess); + if (error != Success) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int ProcRenderCreateLinearGradient (ClientPtr client) +{ + PicturePtr pPicture; + int len; + int error = 0; + xFixed *stops; + xRenderColor *colors; + REQUEST(xRenderCreateLinearGradientReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + + len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq); + if (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + stops = (xFixed *)(stuff + 1); + colors = (xRenderColor *)(stops + stuff->nStops); + + pPicture = CreateLinearGradientPicture (stuff->pid, &stuff->p1, &stuff->p2, + stuff->nStops, stops, colors, &error); + if (!pPicture) + return error; + /* security creation/labeling check */ + error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType, + pPicture, RT_NONE, NULL, DixCreateAccess); + if (error != Success) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int ProcRenderCreateRadialGradient (ClientPtr client) +{ + PicturePtr pPicture; + int len; + int error = 0; + xFixed *stops; + xRenderColor *colors; + REQUEST(xRenderCreateRadialGradientReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + + len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + stops = (xFixed *)(stuff + 1); + colors = (xRenderColor *)(stops + stuff->nStops); + + pPicture = CreateRadialGradientPicture (stuff->pid, &stuff->inner, &stuff->outer, + stuff->inner_radius, stuff->outer_radius, + stuff->nStops, stops, colors, &error); + if (!pPicture) + return error; + /* security creation/labeling check */ + error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType, + pPicture, RT_NONE, NULL, DixCreateAccess); + if (error != Success) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int ProcRenderCreateConicalGradient (ClientPtr client) +{ + PicturePtr pPicture; + int len; + int error = 0; + xFixed *stops; + xRenderColor *colors; + REQUEST(xRenderCreateConicalGradientReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + + len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + stops = (xFixed *)(stuff + 1); + colors = (xRenderColor *)(stops + stuff->nStops); + + pPicture = CreateConicalGradientPicture (stuff->pid, &stuff->center, stuff->angle, + stuff->nStops, stops, colors, &error); + if (!pPicture) + return error; + /* security creation/labeling check */ + error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType, + pPicture, RT_NONE, NULL, DixCreateAccess); + if (error != Success) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + + +static int +ProcRenderDispatch (ClientPtr client) +{ + REQUEST(xReq); + + if (stuff->data < RenderNumberRequests) + return (*ProcRenderVector[stuff->data]) (client); + else + return BadRequest; +} + +static int +SProcRenderQueryVersion (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryVersionReq); + + swaps(&stuff->length, n); + swapl(&stuff->majorVersion, n); + swapl(&stuff->minorVersion, n); + return (*ProcRenderVector[stuff->renderReqType])(client); +} + +static int +SProcRenderQueryPictFormats (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryPictFormatsReq); + swaps(&stuff->length, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryPictIndexValues (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryPictIndexValuesReq); + swaps(&stuff->length, n); + swapl(&stuff->format, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryDithers (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderCreatePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreatePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->drawable, n); + swapl(&stuff->format, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderChangePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderChangePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureClipRectangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderSetPictureClipRectanglesReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swaps(&stuff->xOrigin, n); + swaps(&stuff->yOrigin, n); + SwapRestS(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFreePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderComposite (ClientPtr client) +{ + register int n; + REQUEST(xRenderCompositeReq); + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->mask, n); + swapl(&stuff->dst, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + swaps(&stuff->xMask, n); + swaps(&stuff->yMask, n); + swaps(&stuff->xDst, n); + swaps(&stuff->yDst, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderScale (ClientPtr client) +{ + register int n; + REQUEST(xRenderScaleReq); + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->dst, n); + swapl(&stuff->colorScale, n); + swapl(&stuff->alphaScale, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + swaps(&stuff->xDst, n); + swaps(&stuff->yDst, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTrapezoids (ClientPtr client) +{ + register int n; + REQUEST(xRenderTrapezoidsReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriStrip (ClientPtr client) +{ + register int n; + REQUEST(xRenderTriStripReq); + + REQUEST_AT_LEAST_SIZE(xRenderTriStripReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriFan (ClientPtr client) +{ + register int n; + REQUEST(xRenderTriFanReq); + + REQUEST_AT_LEAST_SIZE(xRenderTriFanReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderColorTrapezoids (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderColorTriangles (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderTransform (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderCreateGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreateGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->gsid, n); + swapl(&stuff->format, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderReferenceGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderReferenceGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->gsid, n); + swapl(&stuff->existing, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFreeGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreeGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddGlyphs (ClientPtr client) +{ + register int n; + register int i; + CARD32 *gids; + void *end; + xGlyphInfo *gi; + REQUEST(xRenderAddGlyphsReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + swapl(&stuff->nglyphs, n); + if (stuff->nglyphs & 0xe0000000) + return BadLength; + end = (CARD8 *) stuff + (client->req_len << 2); + gids = (CARD32 *) (stuff + 1); + gi = (xGlyphInfo *) (gids + stuff->nglyphs); + if ((char *) end - (char *) (gids + stuff->nglyphs) < 0) + return BadLength; + if ((char *) end - (char *) (gi + stuff->nglyphs) < 0) + return BadLength; + for (i = 0; i < stuff->nglyphs; i++) + { + swapl (&gids[i], n); + swaps (&gi[i].width, n); + swaps (&gi[i].height, n); + swaps (&gi[i].x, n); + swaps (&gi[i].y, n); + swaps (&gi[i].xOff, n); + swaps (&gi[i].yOff, n); + } + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddGlyphsFromPicture (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderFreeGlyphs (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreeGlyphsReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCompositeGlyphs (ClientPtr client) +{ + register int n; + xGlyphElt *elt; + CARD8 *buffer; + CARD8 *end; + int space; + int i; + int size; + + REQUEST(xRenderCompositeGlyphsReq); + + switch (stuff->renderReqType) { + default: size = 1; break; + case X_RenderCompositeGlyphs16: size = 2; break; + case X_RenderCompositeGlyphs32: size = 4; break; + } + + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->dst, n); + swapl(&stuff->maskFormat, n); + swapl(&stuff->glyphset, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + buffer = (CARD8 *) (stuff + 1); + end = (CARD8 *) stuff + (client->req_len << 2); + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + swaps (&elt->deltax, n); + swaps (&elt->deltay, n); + + i = elt->len; + if (i == 0xff) + { + swapl (buffer, n); + buffer += 4; + } + else + { + space = size * i; + switch (size) { + case 1: + buffer += i; + break; + case 2: + while (i--) + { + swaps (buffer, n); + buffer += 2; + } + break; + case 4: + while (i--) + { + swapl (buffer, n); + buffer += 4; + } + break; + } + if (space & 3) + buffer += 4 - (space & 3); + } + } + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFillRectangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderFillRectanglesReq); + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + swaps(&stuff->length, n); + swapl(&stuff->dst, n); + swaps(&stuff->color.red, n); + swaps(&stuff->color.green, n); + swaps(&stuff->color.blue, n); + swaps(&stuff->color.alpha, n); + SwapRestS(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateCursor (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreateCursorReq); + REQUEST_SIZE_MATCH (xRenderCreateCursorReq); + + swaps(&stuff->length, n); + swapl(&stuff->cid, n); + swapl(&stuff->src, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureTransform (ClientPtr client) +{ + register int n; + REQUEST(xRenderSetPictureTransformReq); + REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swapl(&stuff->transform.matrix11, n); + swapl(&stuff->transform.matrix12, n); + swapl(&stuff->transform.matrix13, n); + swapl(&stuff->transform.matrix21, n); + swapl(&stuff->transform.matrix22, n); + swapl(&stuff->transform.matrix23, n); + swapl(&stuff->transform.matrix31, n); + swapl(&stuff->transform.matrix32, n); + swapl(&stuff->transform.matrix33, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryFilters (ClientPtr client) +{ + register int n; + REQUEST (xRenderQueryFiltersReq); + REQUEST_SIZE_MATCH (xRenderQueryFiltersReq); + + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureFilter (ClientPtr client) +{ + register int n; + REQUEST (xRenderSetPictureFilterReq); + REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swaps(&stuff->nbytes, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateAnimCursor (ClientPtr client) +{ + register int n; + REQUEST (xRenderCreateAnimCursorReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateAnimCursorReq); + + swaps(&stuff->length, n); + swapl(&stuff->cid, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddTraps (ClientPtr client) +{ + register int n; + REQUEST (xRenderAddTrapsReq); + REQUEST_AT_LEAST_SIZE (xRenderAddTrapsReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swaps(&stuff->xOff, n); + swaps(&stuff->yOff, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateSolidFill(ClientPtr client) +{ + register int n; + REQUEST (xRenderCreateSolidFillReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateSolidFillReq); + + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swaps(&stuff->color.alpha, n); + swaps(&stuff->color.red, n); + swaps(&stuff->color.green, n); + swaps(&stuff->color.blue, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static void swapStops(void *stuff, int num) +{ + int i, n; + CARD32 *stops; + CARD16 *colors; + stops = (CARD32 *)(stuff); + for (i = 0; i < num; ++i) { + swapl(stops, n); + ++stops; + } + colors = (CARD16 *)(stops); + for (i = 0; i < 4*num; ++i) { + swaps(stops, n); + ++stops; + } +} + +static int +SProcRenderCreateLinearGradient (ClientPtr client) +{ + register int n; + int len; + REQUEST (xRenderCreateLinearGradientReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateLinearGradientReq); + + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->p1.x, n); + swapl(&stuff->p1.y, n); + swapl(&stuff->p2.x, n); + swapl(&stuff->p2.y, n); + swapl(&stuff->nStops, n); + + len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq); + if (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + swapStops(stuff+1, stuff->nStops); + + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateRadialGradient (ClientPtr client) +{ + register int n; + int len; + REQUEST (xRenderCreateRadialGradientReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateRadialGradientReq); + + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->inner.x, n); + swapl(&stuff->inner.y, n); + swapl(&stuff->outer.x, n); + swapl(&stuff->outer.y, n); + swapl(&stuff->inner_radius, n); + swapl(&stuff->outer_radius, n); + swapl(&stuff->nStops, n); + + len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq); + if (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + swapStops(stuff+1, stuff->nStops); + + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateConicalGradient (ClientPtr client) +{ + register int n; + int len; + REQUEST (xRenderCreateConicalGradientReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateConicalGradientReq); + + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->center.x, n); + swapl(&stuff->center.y, n); + swapl(&stuff->angle, n); + swapl(&stuff->nStops, n); + + len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq); + if (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + swapStops(stuff+1, stuff->nStops); + + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderDispatch (ClientPtr client) +{ + REQUEST(xReq); + + if (stuff->data < RenderNumberRequests) + return (*SProcRenderVector[stuff->data]) (client); + else + return BadRequest; +} + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" + +#define VERIFY_XIN_PICTURE(pPicture, pid, client, mode) {\ + int rc = dixLookupResourceByType((pointer *)&(pPicture), pid,\ + XRT_PICTURE, client, mode);\ + if (rc != Success)\ + return rc;\ +} + +#define VERIFY_XIN_ALPHA(pPicture, pid, client, mode) {\ + if (pid == None) \ + pPicture = 0; \ + else { \ + VERIFY_XIN_PICTURE(pPicture, pid, client, mode); \ + } \ +} \ + +int (*PanoramiXSaveRenderVector[RenderNumberRequests])(ClientPtr); + +static int +PanoramiXRenderCreatePicture (ClientPtr client) +{ + REQUEST(xRenderCreatePictureReq); + PanoramiXRes *refDraw, *newPict; + int result, j; + + REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); + result = dixLookupResourceByClass((pointer *)&refDraw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + if(!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes)))) + return BadAlloc; + newPict->type = XRT_PICTURE; + newPict->info[0].id = stuff->pid; + + if (refDraw->type == XRT_WINDOW && + stuff->drawable == WindowTable[0]->drawable.id) + { + newPict->u.pict.root = TRUE; + } + else + newPict->u.pict.root = FALSE; + + for(j = 1; j < PanoramiXNumScreens; j++) + newPict->info[j].id = FakeClientID(client->index); + + FOR_NSCREENS_BACKWARD(j) { + stuff->pid = newPict->info[j].id; + stuff->drawable = refDraw->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderCreatePicture]) (client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newPict->info[0].id, XRT_PICTURE, newPict); + else + free(newPict); + + return (result); +} + +static int +PanoramiXRenderChangePicture (ClientPtr client) +{ + PanoramiXRes *pict; + int result = Success, j; + REQUEST(xRenderChangePictureReq); + + REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderChangePicture]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderSetPictureClipRectangles (ClientPtr client) +{ + REQUEST(xRenderSetPictureClipRectanglesReq); + int result = Success, j; + PanoramiXRes *pict; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderSetPictureClipRectangles]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderSetPictureTransform (ClientPtr client) +{ + REQUEST(xRenderSetPictureTransformReq); + int result = Success, j; + PanoramiXRes *pict; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureTransformReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderSetPictureTransform]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderSetPictureFilter (ClientPtr client) +{ + REQUEST(xRenderSetPictureFilterReq); + int result = Success, j; + PanoramiXRes *pict; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderSetPictureFilter]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderFreePicture (ClientPtr client) +{ + PanoramiXRes *pict; + int result = Success, j; + REQUEST(xRenderFreePictureReq); + + REQUEST_SIZE_MATCH(xRenderFreePictureReq); + + client->errorValue = stuff->picture; + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixDestroyAccess); + + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderFreePicture]) (client); + if(result != Success) break; + } + + /* Since ProcRenderFreePicture is using FreeResource, it will free + our resource for us on the last pass through the loop above */ + + return (result); +} + +static int +PanoramiXRenderComposite (ClientPtr client) +{ + PanoramiXRes *src, *msk, *dst; + int result = Success, j; + xRenderCompositeReq orig; + REQUEST(xRenderCompositeReq); + + REQUEST_SIZE_MATCH(xRenderCompositeReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess); + VERIFY_XIN_ALPHA (msk, stuff->mask, client, DixReadAccess); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); + + orig = *stuff; + + FOR_NSCREENS_FORWARD(j) { + stuff->src = src->info[j].id; + if (src->u.pict.root) + { + stuff->xSrc = orig.xSrc - panoramiXdataPtr[j].x; + stuff->ySrc = orig.ySrc - panoramiXdataPtr[j].y; + } + stuff->dst = dst->info[j].id; + if (dst->u.pict.root) + { + stuff->xDst = orig.xDst - panoramiXdataPtr[j].x; + stuff->yDst = orig.yDst - panoramiXdataPtr[j].y; + } + if (msk) + { + stuff->mask = msk->info[j].id; + if (msk->u.pict.root) + { + stuff->xMask = orig.xMask - panoramiXdataPtr[j].x; + stuff->yMask = orig.yMask - panoramiXdataPtr[j].y; + } + } + result = (*PanoramiXSaveRenderVector[X_RenderComposite]) (client); + if(result != Success) break; + } + + return result; +} + +static int +PanoramiXRenderCompositeGlyphs (ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderCompositeGlyphsReq); + xGlyphElt origElt, *elt; + INT16 xSrc, ySrc; + + REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); + VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); + + if (client->req_len << 2 >= (sizeof (xRenderCompositeGlyphsReq) + + sizeof (xGlyphElt))) + { + elt = (xGlyphElt *) (stuff + 1); + origElt = *elt; + xSrc = stuff->xSrc; + ySrc = stuff->ySrc; + FOR_NSCREENS_FORWARD(j) { + stuff->src = src->info[j].id; + if (src->u.pict.root) + { + stuff->xSrc = xSrc - panoramiXdataPtr[j].x; + stuff->ySrc = ySrc - panoramiXdataPtr[j].y; + } + stuff->dst = dst->info[j].id; + if (dst->u.pict.root) + { + elt->deltax = origElt.deltax - panoramiXdataPtr[j].x; + elt->deltay = origElt.deltay - panoramiXdataPtr[j].y; + } + result = (*PanoramiXSaveRenderVector[stuff->renderReqType]) (client); + if(result != Success) break; + } + } + + return result; +} + +static int +PanoramiXRenderFillRectangles (ClientPtr client) +{ + PanoramiXRes *dst; + int result = Success, j; + REQUEST(xRenderFillRectanglesReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); + extra_len = (client->req_len << 2) - sizeof (xRenderFillRectanglesReq); + if (extra_len && + (extra = (char *) malloc(extra_len))) + { + memcpy (extra, stuff + 1, extra_len); + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) + { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xRectangle *rects = (xRectangle *) (stuff + 1); + int i = extra_len / sizeof (xRectangle); + + while (i--) + { + rects->x -= x_off; + rects->y -= y_off; + rects++; + } + } + } + stuff->dst = dst->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderFillRectangles]) (client); + if(result != Success) break; + } + free(extra); + } + + return result; +} + +static int +PanoramiXRenderTrapezoids(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderTrapezoidsReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderTrapezoidsReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); + + extra_len = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq); + + if (extra_len && + (extra = (char *) malloc(extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xTrapezoid *trap = (xTrapezoid *) (stuff + 1); + int i = extra_len / sizeof (xTrapezoid); + + while (i--) { + trap->top -= y_off; + trap->bottom -= y_off; + trap->left.p1.x -= x_off; + trap->left.p1.y -= y_off; + trap->left.p2.x -= x_off; + trap->left.p2.y -= y_off; + trap->right.p1.x -= x_off; + trap->right.p1.y -= y_off; + trap->right.p2.x -= x_off; + trap->right.p2.y -= y_off; + trap++; + } + } + } + + stuff->src = src->info[j].id; + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderTrapezoids]) (client); + + if(result != Success) break; + } + + free(extra); + } + + return result; +} + +static int +PanoramiXRenderTriangles(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderTrianglesReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderTrianglesReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); + + extra_len = (client->req_len << 2) - sizeof (xRenderTrianglesReq); + + if (extra_len && + (extra = (char *) malloc(extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xTriangle *tri = (xTriangle *) (stuff + 1); + int i = extra_len / sizeof (xTriangle); + + while (i--) { + tri->p1.x -= x_off; + tri->p1.y -= y_off; + tri->p2.x -= x_off; + tri->p2.y -= y_off; + tri->p3.x -= x_off; + tri->p3.y -= y_off; + tri++; + } + } + } + + stuff->src = src->info[j].id; + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderTriangles]) (client); + + if(result != Success) break; + } + + free(extra); + } + + return result; +} + +static int +PanoramiXRenderTriStrip(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderTriStripReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderTriStripReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); + + extra_len = (client->req_len << 2) - sizeof (xRenderTriStripReq); + + if (extra_len && + (extra = (char *) malloc(extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xPointFixed *fixed = (xPointFixed *) (stuff + 1); + int i = extra_len / sizeof (xPointFixed); + + while (i--) { + fixed->x -= x_off; + fixed->y -= y_off; + fixed++; + } + } + } + + stuff->src = src->info[j].id; + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderTriStrip]) (client); + + if(result != Success) break; + } + + free(extra); + } + + return result; +} + +static int +PanoramiXRenderTriFan(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderTriFanReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderTriFanReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); + + extra_len = (client->req_len << 2) - sizeof (xRenderTriFanReq); + + if (extra_len && + (extra = (char *) malloc(extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xPointFixed *fixed = (xPointFixed *) (stuff + 1); + int i = extra_len / sizeof (xPointFixed); + + while (i--) { + fixed->x -= x_off; + fixed->y -= y_off; + fixed++; + } + } + } + + stuff->src = src->info[j].id; + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderTriFan]) (client); + + if(result != Success) break; + } + + free(extra); + } + + return result; +} + +static int +PanoramiXRenderAddTraps (ClientPtr client) +{ + PanoramiXRes *picture; + int result = Success, j; + REQUEST(xRenderAddTrapsReq); + char *extra; + int extra_len; + INT16 x_off, y_off; + + REQUEST_AT_LEAST_SIZE (xRenderAddTrapsReq); + VERIFY_XIN_PICTURE (picture, stuff->picture, client, DixWriteAccess); + extra_len = (client->req_len << 2) - sizeof (xRenderAddTrapsReq); + if (extra_len && + (extra = (char *) malloc(extra_len))) + { + memcpy (extra, stuff + 1, extra_len); + x_off = stuff->xOff; + y_off = stuff->yOff; + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + stuff->picture = picture->info[j].id; + + if (picture->u.pict.root) + { + stuff->xOff = x_off + panoramiXdataPtr[j].x; + stuff->yOff = y_off + panoramiXdataPtr[j].y; + } + result = (*PanoramiXSaveRenderVector[X_RenderAddTraps]) (client); + if(result != Success) break; + } + free(extra); + } + + return result; +} + +static int +PanoramiXRenderCreateSolidFill (ClientPtr client) +{ + REQUEST(xRenderCreateSolidFillReq); + PanoramiXRes *newPict; + int result = Success, j; + + REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq); + + if(!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newPict->type = XRT_PICTURE; + newPict->info[0].id = stuff->pid; + newPict->u.pict.root = FALSE; + + for(j = 1; j < PanoramiXNumScreens; j++) + newPict->info[j].id = FakeClientID(client->index); + + FOR_NSCREENS_BACKWARD(j) { + stuff->pid = newPict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderCreateSolidFill]) (client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newPict->info[0].id, XRT_PICTURE, newPict); + else + free(newPict); + + return result; +} + +static int +PanoramiXRenderCreateLinearGradient (ClientPtr client) +{ + REQUEST(xRenderCreateLinearGradientReq); + PanoramiXRes *newPict; + int result = Success, j; + + REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq); + + if(!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newPict->type = XRT_PICTURE; + newPict->info[0].id = stuff->pid; + newPict->u.pict.root = FALSE; + + for(j = 1; j < PanoramiXNumScreens; j++) + newPict->info[j].id = FakeClientID(client->index); + + FOR_NSCREENS_BACKWARD(j) { + stuff->pid = newPict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderCreateLinearGradient]) (client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newPict->info[0].id, XRT_PICTURE, newPict); + else + free(newPict); + + return result; +} + +static int +PanoramiXRenderCreateRadialGradient (ClientPtr client) +{ + REQUEST(xRenderCreateRadialGradientReq); + PanoramiXRes *newPict; + int result = Success, j; + + REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq); + + if(!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newPict->type = XRT_PICTURE; + newPict->info[0].id = stuff->pid; + newPict->u.pict.root = FALSE; + + for(j = 1; j < PanoramiXNumScreens; j++) + newPict->info[j].id = FakeClientID(client->index); + + FOR_NSCREENS_BACKWARD(j) { + stuff->pid = newPict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderCreateRadialGradient]) (client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newPict->info[0].id, XRT_PICTURE, newPict); + else + free(newPict); + + return result; +} + +static int +PanoramiXRenderCreateConicalGradient (ClientPtr client) +{ + REQUEST(xRenderCreateConicalGradientReq); + PanoramiXRes *newPict; + int result = Success, j; + + REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq); + + if(!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newPict->type = XRT_PICTURE; + newPict->info[0].id = stuff->pid; + newPict->u.pict.root = FALSE; + + for(j = 1; j < PanoramiXNumScreens; j++) + newPict->info[j].id = FakeClientID(client->index); + + FOR_NSCREENS_BACKWARD(j) { + stuff->pid = newPict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderCreateConicalGradient]) (client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newPict->info[0].id, XRT_PICTURE, newPict); + else + free(newPict); + + return result; +} + +void +PanoramiXRenderInit (void) +{ + int i; + + XRT_PICTURE = CreateNewResourceType (XineramaDeleteResource, + "XineramaPicture"); + if (RenderErrBase) + SetResourceTypeErrorValue(XRT_PICTURE, RenderErrBase + BadPicture); + for (i = 0; i < RenderNumberRequests; i++) + PanoramiXSaveRenderVector[i] = ProcRenderVector[i]; + /* + * Stuff in Xinerama aware request processing hooks + */ + ProcRenderVector[X_RenderCreatePicture] = PanoramiXRenderCreatePicture; + ProcRenderVector[X_RenderChangePicture] = PanoramiXRenderChangePicture; + ProcRenderVector[X_RenderSetPictureTransform] = PanoramiXRenderSetPictureTransform; + ProcRenderVector[X_RenderSetPictureFilter] = PanoramiXRenderSetPictureFilter; + ProcRenderVector[X_RenderSetPictureClipRectangles] = PanoramiXRenderSetPictureClipRectangles; + ProcRenderVector[X_RenderFreePicture] = PanoramiXRenderFreePicture; + ProcRenderVector[X_RenderComposite] = PanoramiXRenderComposite; + ProcRenderVector[X_RenderCompositeGlyphs8] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderCompositeGlyphs16] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderCompositeGlyphs32] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderFillRectangles] = PanoramiXRenderFillRectangles; + + ProcRenderVector[X_RenderTrapezoids] = PanoramiXRenderTrapezoids; + ProcRenderVector[X_RenderTriangles] = PanoramiXRenderTriangles; + ProcRenderVector[X_RenderTriStrip] = PanoramiXRenderTriStrip; + ProcRenderVector[X_RenderTriFan] = PanoramiXRenderTriFan; + ProcRenderVector[X_RenderAddTraps] = PanoramiXRenderAddTraps; + + ProcRenderVector[X_RenderCreateSolidFill] = PanoramiXRenderCreateSolidFill; + ProcRenderVector[X_RenderCreateLinearGradient] = PanoramiXRenderCreateLinearGradient; + ProcRenderVector[X_RenderCreateRadialGradient] = PanoramiXRenderCreateRadialGradient; + ProcRenderVector[X_RenderCreateConicalGradient] = PanoramiXRenderCreateConicalGradient; +} + +void +PanoramiXRenderReset (void) +{ + int i; + for (i = 0; i < RenderNumberRequests; i++) + ProcRenderVector[i] = PanoramiXSaveRenderVector[i]; + RenderErrBase = 0; +} + +#endif /* PANORAMIX */ diff --git a/xorg-server/xfixes/cursor.c b/xorg-server/xfixes/cursor.c index 296836055..d133f8c7b 100644 --- a/xorg-server/xfixes/cursor.c +++ b/xorg-server/xfixes/cursor.c @@ -70,10 +70,7 @@ static void deleteCursorHideCountsForScreen (ScreenPtr pScreen); int err; \ err = dixLookupResourceByType((pointer *) &pCursor, cursor, \ RT_CURSOR, client, access); \ - if (err == BadValue) { \ - client->errorValue = cursor; \ - return BadCursor; \ - } else if (err != Success) { \ + if (err != Success) { \ client->errorValue = cursor; \ return err; \ } \ @@ -164,13 +161,11 @@ CursorDisplayCursor (DeviceIntPtr pDev, CursorCurrent[pDev->id] = pCursor; for (e = cursorEvents; e; e = e->next) { - if ((e->eventMask & XFixesDisplayCursorNotifyMask) && - !e->pClient->clientGone) + if ((e->eventMask & XFixesDisplayCursorNotifyMask)) { xXFixesCursorNotifyEvent ev; ev.type = XFixesEventBase + XFixesCursorNotify; ev.subtype = XFixesDisplayCursorNotify; - ev.sequenceNumber = e->pClient->sequence; ev.window = e->pWindow->drawable.id; ev.cursorSerial = pCursor->serialNumber; ev.timestamp = currentTime.milliseconds; @@ -884,7 +879,7 @@ ProcXFixesHideCursor (ClientPtr client) client, DixGetAttrAccess); if (ret != Success) { client->errorValue = stuff->window; - return (ret == BadValue) ? BadWindow : ret; + return ret; } /* @@ -947,7 +942,7 @@ ProcXFixesShowCursor (ClientPtr client) client, DixGetAttrAccess); if (rc != Success) { client->errorValue = stuff->window; - return (rc == BadValue) ? BadWindow : rc; + return rc; } /* diff --git a/xorg-server/xfixes/region.c b/xorg-server/xfixes/region.c index 2276ab8b6..7b1c40b15 100644 --- a/xorg-server/xfixes/region.c +++ b/xorg-server/xfixes/region.c @@ -119,7 +119,7 @@ ProcXFixesCreateRegionFromBitmap (ClientPtr client) if (rc != Success) { client->errorValue = stuff->bitmap; - return (rc == BadValue) ? BadPixmap : rc; + return rc; } if (pPixmap->drawable.depth != 1) return BadMatch; @@ -164,7 +164,7 @@ ProcXFixesCreateRegionFromWindow (ClientPtr client) if (rc != Success) { client->errorValue = stuff->window; - return (rc == BadValue) ? BadWindow : rc; + return rc; } switch (stuff->kind) { case WindowRegionBounding: @@ -675,7 +675,7 @@ ProcXFixesSetWindowShapeRegion (ClientPtr client) if (rc != Success) { client->errorValue = stuff->dest; - return (rc == BadValue) ? BadWindow : rc; + return rc; } VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, DixWriteAccess); pScreen = pWin->drawable.pScreen; diff --git a/xorg-server/xfixes/select.c b/xorg-server/xfixes/select.c index 044294ee1..00b693f9d 100644 --- a/xorg-server/xfixes/select.c +++ b/xorg-server/xfixes/select.c @@ -78,15 +78,13 @@ XFixesSelectionCallback (CallbackListPtr *callbacks, pointer data, pointer args) for (e = selectionEvents; e; e = e->next) { if (e->selection == selection->selection && - (e->eventMask & eventMask) && - !e->pClient->clientGone) + (e->eventMask & eventMask)) { xXFixesSelectionNotifyEvent ev; memset(&ev, 0, sizeof(xXFixesSelectionNotifyEvent)); ev.type = XFixesEventBase + XFixesSelectionNotify; ev.subtype = subtype; - ev.sequenceNumber = e->pClient->sequence; ev.window = e->pWindow->drawable.id; if (subtype == XFixesSetSelectionOwnerNotify) ev.owner = selection->window; diff --git a/xorg-server/xfixes/xfixes.c b/xorg-server/xfixes/xfixes.c index fd23a5cb7..36eda56a5 100644 --- a/xorg-server/xfixes/xfixes.c +++ b/xorg-server/xfixes/xfixes.c @@ -259,5 +259,6 @@ XFixesExtensionInit(void) (EventSwapPtr) SXFixesSelectionNotifyEvent; EventSwapVector[XFixesEventBase + XFixesCursorNotify] = (EventSwapPtr) SXFixesCursorNotifyEvent; + SetResourceTypeErrorValue(RegionResType, XFixesErrorBase + BadRegion); } } diff --git a/xorg-server/xfixes/xfixes.h b/xorg-server/xfixes/xfixes.h index 69d162ffe..f834305bf 100644 --- a/xorg-server/xfixes/xfixes.h +++ b/xorg-server/xfixes/xfixes.h @@ -1,58 +1,55 @@ -/* - * Copyright © 2002 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#ifndef _XFIXES_H_ -#define _XFIXES_H_ - -#include "resource.h" - -extern _X_EXPORT RESTYPE RegionResType; -extern _X_EXPORT int XFixesErrorBase; - -#define VERIFY_REGION(pRegion, rid, client, mode) \ - do { \ - int err; \ - err = dixLookupResourceByType((pointer *) &pRegion, rid, \ - RegionResType, client, mode); \ - if (err == BadValue) { \ - client->errorValue = rid; \ - return XFixesErrorBase + BadRegion; \ - } else if (err != Success) { \ - client->errorValue = rid; \ - return err; \ - } \ - } while (0) - -#define VERIFY_REGION_OR_NONE(pRegion, rid, client, mode) { \ - pRegion = 0; \ - if (rid) VERIFY_REGION(pRegion, rid, client, mode); \ -} - -extern _X_EXPORT RegionPtr -XFixesRegionCopy (RegionPtr pRegion); - - -#endif /* _XFIXES_H_ */ +/* + * Copyright © 2002 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef _XFIXES_H_ +#define _XFIXES_H_ + +#include "resource.h" + +extern _X_EXPORT RESTYPE RegionResType; +extern _X_EXPORT int XFixesErrorBase; + +#define VERIFY_REGION(pRegion, rid, client, mode) \ + do { \ + int err; \ + err = dixLookupResourceByType((pointer *) &pRegion, rid, \ + RegionResType, client, mode); \ + if (err != Success) { \ + client->errorValue = rid; \ + return err; \ + } \ + } while (0) + +#define VERIFY_REGION_OR_NONE(pRegion, rid, client, mode) { \ + pRegion = 0; \ + if (rid) VERIFY_REGION(pRegion, rid, client, mode); \ +} + +extern _X_EXPORT RegionPtr +XFixesRegionCopy (RegionPtr pRegion); + + +#endif /* _XFIXES_H_ */ diff --git a/xorg-server/xkb/xkbEvents.c b/xorg-server/xkb/xkbEvents.c index 659c8c89d..ee62b9947 100644 --- a/xorg-server/xkb/xkbEvents.c +++ b/xorg-server/xkb/xkbEvents.c @@ -102,7 +102,6 @@ XkbSendLegacyMapNotify(DeviceIntPtr kbd, CARD16 xkb_event, CARD16 changed, if (!XIShouldNotify(clients[i], kbd)) continue; - core_mn.u.u.sequenceNumber = clients[i]->sequence; if (keymap_changed) { core_mn.u.mappingNotify.request = MappingKeyboard; -- cgit v1.2.3