diff options
133 files changed, 30591 insertions, 0 deletions
diff --git a/xc/include/extensions/randr.h b/xc/include/extensions/randr.h new file mode 100644 index 000000000..da579a1c0 --- /dev/null +++ b/xc/include/extensions/randr.h @@ -0,0 +1,58 @@ +/* + * $XFree86: xc/include/extensions/randr.h,v 1.3 2001/06/07 17:54:01 keithp Exp $ + * + * Copyright © 2000 Compaq Computer Corporation, 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 Compaq not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Compaq makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * COMPAQ DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL COMPAQ + * 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, Compaq Computer Corporation, Inc. + */ + +#ifndef _RANDR_H_ +#define _RANDR_H_ + +typedef CARD16 Rotation; +typedef CARD16 VisualGroupID; +typedef CARD16 GroupOfVisualGroupID; +typedef CARD16 SizeID; + +#define RANDR_NAME "RANDR" +#define RANDR_MAJOR 0 +#define RANDR_MINOR 0 + +#define RRNumberErrors 0 +#define RRNumberEvents 1 + +#define X_RRQueryVersion 0 +#define X_RRGetScreenInfo 1 +#define X_RRSetScreenConfig 2 +#define X_RRScreenChangeSelectInput 3 + +#define RRScreenChangeNotify 0 + +#define RR_Rotate_0 1 +#define RR_Rotate_90 2 +#define RR_Rotate_180 4 +#define RR_Rotate_270 8 + +#define RRSetConfigSuccess 0 +#define RRSetConfigInvalidConfigTime 1 +#define RRSetConfigInvalidTime 2 +#define RRSetConfigFailed 3 + +#endif /* _RANDR_H_ */ diff --git a/xc/include/extensions/randrproto.h b/xc/include/extensions/randrproto.h new file mode 100644 index 000000000..e9218d9ec --- /dev/null +++ b/xc/include/extensions/randrproto.h @@ -0,0 +1,193 @@ +/* + * $XFree86: xc/include/extensions/randrproto.h,v 1.5 2001/08/01 00:44:35 tsi Exp $ + * + * Copyright © 2000 Compaq Computer Corporation + * + * 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 Compaq not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Compaq makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * COMPAQ DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL COMPAQ + * 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, Compaq Computer Corporation, Inc. + */ + +#ifndef _XRANDRP_H_ +#define _XRANDRP_H_ + +#include <X11/extensions/randr.h> + +#define Window CARD32 +#define Drawable CARD32 +#define Font CARD32 +#define Pixmap CARD32 +#define Cursor CARD32 +#define Colormap CARD32 +#define GContext CARD32 +#define Atom CARD32 +#define VisualID CARD32 +#define Time CARD32 +#define KeyCode CARD8 +#define KeySym CARD32 + +#define Rotation CARD16 +#define VisualGroupID CARD16 +#define GroupOfVisualGroupID CARD16 +#define SizeID CARD16 + +/* + * data structures + */ + +typedef struct { + CARD16 widthInPixels B16; + CARD16 heightInPixels B16; + CARD16 widthInMillimeters B16; + CARD16 heightInMillimeters B16; + GroupOfVisualGroupID visualGroup B16; + CARD16 pad1 B16; +} xScreenSizes; +#define sz_xScreenSizes 12 + + + +/* + * requests and replies + */ + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + CARD32 majorVersion B32; + CARD32 minorVersion B32; +} xRRQueryVersionReq; +#define sz_xRRQueryVersionReq 12 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 majorVersion B32; + CARD32 minorVersion B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xRRQueryVersionReply; +#define sz_xRRQueryVersionReply 32 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + Window window B32; +} xRRGetScreenInfoReq; +#define sz_xRRGetScreenInfoReq 8 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE setOfRotations; + CARD16 sequenceNumber B16; + CARD32 length B32; + Window root B32; + Time timestamp B32; + Time configTimestamp B32; + CARD16 nVisualGroups B16; + CARD16 nGroupsOfVisualGroups B16; + CARD16 nSizes B16; + SizeID sizeID B16; + VisualGroupID visualGroupID B16; + Rotation rotation B16; +} xRRGetScreenInfoReply; +#define sz_xRRGetScreenInfoReply 32 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + Drawable drawable B32; + Time timestamp B32; + Time configTimestamp B32; + SizeID sizeID B16; + Rotation rotation B16; + VisualGroupID visualGroupID B16; + CARD16 pad B16; +} xRRSetScreenConfigReq; +#define sz_xRRSetScreenConfigReq 24 + +typedef struct { + BYTE type; /* X_Reply */ + CARD8 status; + CARD16 sequenceNumber B16; + CARD32 length B32; + Time newTimestamp B32; + Time newConfigTimestamp B32; + Window root; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xRRSetScreenConfigReply; +#define sz_xRRSetScreenConfigReply 32 + +typedef struct { + CARD8 reqType; + CARD8 randrReqType; + CARD16 length B16; + Window window B32; + BYTE enable; /* xTrue -> send events */ + BYTE pad1; + CARD16 pad2 B16; +} xRRScreenChangeSelectInputReq; +#define sz_xRRScreenChangeSelectInputReq 12 + +/* + * event + */ +typedef struct { + CARD8 type; /* always evBase + ScreenChangeNotify */ + CARD8 rotation; /* new rotation */ + CARD16 sequenceNumber B16; + Time timestamp B32; /* time screen was changed */ + Time configTimestamp B32; /* time config data was changed */ + Window root B32; /* root window */ + Window window B32; /* window requesting notification */ + SizeID sizeID B16; /* new size ID */ + VisualGroupID visualGroupID B16; /* new visual group ID */ + CARD16 widthInPixels B16; /* new size */ + CARD16 heightInPixels B16; + CARD16 widthInMillimeters B16; + CARD16 heightInMillimeters B16; +} xRRScreenChangeNotifyEvent; +#define sz_xRRScreenChangeNotifyEvent 32 + +#undef Window +#undef Drawable +#undef Font +#undef Pixmap +#undef Cursor +#undef Colormap +#undef GContext +#undef Atom +#undef VisualID +#undef Time +#undef KeyCode +#undef KeySym +#undef Rotation +#undef VisualGroupID +#undef GroupOfVisualGroupID +#undef SizeID + +#endif /* _XRANDRP_H_ */ diff --git a/xc/lib/X11/Xintatom.h b/xc/lib/X11/Xintatom.h new file mode 100644 index 000000000..910c0fa21 --- /dev/null +++ b/xc/lib/X11/Xintatom.h @@ -0,0 +1,33 @@ +/* $XFree86: xc/lib/X11/Xintatom.h,v 1.1 2001/08/18 02:41:28 dawes Exp $ */ + +#ifndef _XINTATOM_H_ +#define _XINTATOM_H_ 1 + +#include <X11/Xfuncproto.h> + +/* IntAtom.c */ + +#define TABLESIZE 64 + +typedef struct _Entry { + unsigned long sig; + Atom atom; +} EntryRec, *Entry; + +#define RESERVED ((Entry) 1) + +#define EntryName(e) ((char *)(e+1)) + +typedef struct _XDisplayAtoms { + Entry table[TABLESIZE]; +} AtomTable; + +_XFUNCPROTOBEGIN + +extern void _XUpdateAtomCache(Display *dpy, const char *name, Atom atom, + unsigned long sig, int idx, int n); +extern void _XFreeAtomTable(Display *dpy); + +_XFUNCPROTOEND + +#endif /* _XINTATOM_H_ */ diff --git a/xc/lib/X11/Xintconn.h b/xc/lib/X11/Xintconn.h new file mode 100644 index 000000000..3010da4f0 --- /dev/null +++ b/xc/lib/X11/Xintconn.h @@ -0,0 +1,27 @@ +/* $XFree86: xc/lib/X11/Xintconn.h,v 1.1 2001/08/18 02:41:28 dawes Exp $ */ + +#ifndef _XINTCONN_H_ +#define _XINTCONN_H_ 1 + +#include <X11/Xfuncproto.h> + +_XFUNCPROTOBEGIN + +/* ConnDis.c */ + +extern int _XDisconnectDisplay(XtransConnInfo trans_conn); +extern Bool _XSendClientPrefix(Display *dpy, xConnClientPrefix *client, + char *auth_proto, char *auth_string, + xConnSetupPrefix *prefix); +extern XtransConnInfo _X11TransConnectDisplay(char *display_name, + char **fullnamep, int *dpynump, + int *screenp, char **auth_namep, + int *auth_namelenp, char **auth_datap, + int *auth_datalenp); + +/* OpenDis.c */ +extern void _XFreeDisplayStructure(Display *dpy); + +_XFUNCPROTOEND + +#endif /* _XINTCONN_H_ */ diff --git a/xc/lib/Xrandr/Imakefile b/xc/lib/Xrandr/Imakefile new file mode 100644 index 000000000..b429281dd --- /dev/null +++ b/xc/lib/Xrandr/Imakefile @@ -0,0 +1,33 @@ +XCOMM $XFree86: xc/lib/Xrandr/Imakefile,v 1.1 2001/05/23 03:29:44 keithp Exp $ + + +#define DoNormalLib NormalLibXrandr +#define DoSharedLib SharedLibXrandr +#define DoDebugLib DebugLibXrandr +#define DoProfileLib ProfileLibXrandr +#define LibName Xrandr +#define SoRev SOXRANDRREV +#define IncSubdir X11 +#define IncSubSubdir extensions + +#include <Threads.tmpl> + +#ifdef SharedXrandrReqs +REQUIREDLIBS = SharedXrandrReqs +#endif + +#if Malloc0ReturnsNull +ALLOC_DEFINES = -DMALLOC_0_RETURNS_NULL +#endif + + DEFINES = $(ALLOC_DEFINES) + INCLUDES = -I$(XLIBSRC) -I$(EXTINCSRC) + SRCS = Xrandr.c + OBJS = Xrandr.o + LINTLIBS = $(LINTXLIB) + +HEADERS = Xrandr.h + +#include <Library.tmpl> + +DependTarget() diff --git a/xc/lib/Xrandr/Xrandr-def.cpp b/xc/lib/Xrandr/Xrandr-def.cpp new file mode 100644 index 000000000..1c94e08a1 --- /dev/null +++ b/xc/lib/Xrandr/Xrandr-def.cpp @@ -0,0 +1,18 @@ +LIBRARY Xrandr +VERSION LIBRARY_VERSION +EXPORTS + XRRCurrentConfig + XRRFindDisplay + XRRFreeScreenInfo + XRRGetScreenInfo + XRRQueryExtension + XRRQueryVersion + XRRRootToScreen + XRRRotations + XRRScreenChangeSelectInput + XRRSetScreenConfig + XRRSizes + XRRTimes + XRRVisualIDToVisual + XRRVisualToDepth +/* $XFree86: xc/lib/Xrandr/Xrandr-def.cpp,v 1.1 2001/08/19 15:22:58 alanh Exp $ */ diff --git a/xc/lib/Xrandr/Xrandr.c b/xc/lib/Xrandr/Xrandr.c new file mode 100644 index 000000000..84dba2183 --- /dev/null +++ b/xc/lib/Xrandr/Xrandr.c @@ -0,0 +1,472 @@ +/* + * $XFree86: xc/lib/Xrandr/Xrandr.c,v 1.6 2001/06/11 01:37:53 keithp Exp $ + * + * Copyright © 2000 Compaq Computer Corporation, 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 Compaq not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Compaq makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * COMPAQ DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL COMPAQ + * 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, Compaq Computer Corporation, Inc. + */ +#include <stdio.h> +#include <X11/Xlib.h> +#include "Xrandrint.h" + +XExtensionInfo XRRExtensionInfo; +char XRRExtensionName[] = RANDR_NAME; + +static Bool XRRWireToEvent(Display *dpy, XEvent *event, xEvent *wire); +static Status XRREventToWire(Display *dpy, XEvent *event, xEvent *wire); + +static int +XRRCloseDisplay (Display *dpy, XExtCodes *codes); + +static /* const */ XExtensionHooks rr_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + XRRCloseDisplay, /* close_display */ + XRRWireToEvent, /* wire_to_event */ + XRREventToWire, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + +static Bool XRRWireToEvent(Display *dpy, XEvent *event, xEvent *wire) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + XRRScreenChangeNotifyEvent *aevent; + xRRScreenChangeNotifyEvent *awire; + + RRCheckExtension(dpy, info, False); + + switch ((wire->u.u.type & 0x7F) - info->codes->first_event) + { + case RRScreenChangeNotify: + awire = (xRRScreenChangeNotifyEvent *) wire; + aevent = (XRRScreenChangeNotifyEvent *) event; + aevent->type = awire->type & 0x7F; + aevent->serial = _XSetLastRequestRead(dpy, + (xGenericReply *) wire); + aevent->send_event = (awire->type & 0x80) != 0; + aevent->display = dpy; + aevent->window = awire->window; + aevent->root = awire->root; + aevent->timestamp = awire->timestamp; + aevent->config_timestamp = awire->configTimestamp; + aevent->size_index = awire->sizeID; + aevent->visual_group_index = awire->visualGroupID; + aevent->rotation = awire->rotation; + aevent->width = awire->widthInPixels; + aevent->height = awire->heightInPixels; + aevent->mwidth = awire->widthInMillimeters; + aevent->mheight = awire->heightInMillimeters; + return True; + } + + return False; +} + +static Status XRREventToWire(Display *dpy, XEvent *event, xEvent *wire) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + XRRScreenChangeNotifyEvent *aevent; + xRRScreenChangeNotifyEvent *awire; + + RRCheckExtension(dpy, info, False); + + switch ((event->type & 0x7F) - info->codes->first_event) + { + case RRScreenChangeNotify: + awire = (xRRScreenChangeNotifyEvent *) wire; + aevent = (XRRScreenChangeNotifyEvent *) event; + awire->type = aevent->type | (aevent->send_event ? 0x80 : 0); + awire->rotation = (CARD8) aevent->rotation; + awire->sequenceNumber = aevent->serial & 0xFFFF; + awire->timestamp = aevent->timestamp; + awire->configTimestamp = aevent->config_timestamp; + awire->root = aevent->root; + awire->window = aevent->window; + awire->sizeID = aevent->size_index; + awire->visualGroupID = aevent->visual_group_index; + awire->widthInPixels = aevent->width; + awire->heightInPixels = aevent->height; + awire->widthInMillimeters = aevent->mwidth; + awire->heightInMillimeters = aevent->mheight; + return True; + } + return False; +} + +XExtDisplayInfo * +XRRFindDisplay (Display *dpy) +{ + XExtDisplayInfo *dpyinfo; + + dpyinfo = XextFindDisplay (&XRRExtensionInfo, dpy); + if (!dpyinfo) + dpyinfo = XextAddDisplay (&XRRExtensionInfo, dpy, + XRRExtensionName, + &rr_extension_hooks, + RRNumberEvents, 0); + return dpyinfo; +} + +static int +XRRCloseDisplay (Display *dpy, XExtCodes *codes) +{ + XExtDisplayInfo *info = XRRFindDisplay (dpy); + if (info->data) XFree (info->data); + + return XextRemoveDisplay (&XRRExtensionInfo, dpy); +} + +/**************************************************************************** + * * + * RandR public interfaces * + * * + ****************************************************************************/ +int XRRVisualToDepth(Display *dpy, Visual *visual) +{ + int s; + for (s = 0; s < ScreenCount(dpy); s++) { + Screen *sp = ScreenOfDisplay(dpy, s); + int d; + for (d = 0; d < sp->ndepths; d++) { + int v; + for (v = 0; v < sp->depths[s].nvisuals; v++) { + if ( &sp->depths[s].visuals[v] == visual ) return d; + } + } + } + return -1; /* should not ever happen */ +} + +Visual *XRRVisualIDToVisual(Display *dpy, int screen, VisualID id) +{ + int d, v; + Screen *sp = ScreenOfDisplay(dpy, screen); + for (d = 0; d < sp->ndepths; d++) { + for (v = 0; v < sp->depths[d].nvisuals; v++) { + if ( sp->depths[d].visuals[v].visualid == id ) + return (&sp->depths[d].visuals[v]); + } + } + return NULL; +} + +Rotation XRRRotations(XRRScreenConfiguration *config, Rotation *current_rotation) +{ + *current_rotation = config->current_rotation; + return config->rotations; +} + +XRRScreenSize *XRRSizes(XRRScreenConfiguration *config, int *nsizes) +{ + *nsizes = config->nsizes; + return config->sizes; +} + +Time XRRTimes (XRRScreenConfiguration *config, Time *config_timestamp) +{ + *config_timestamp = config->config_timestamp; + return config->timestamp; +} + +SizeID XRRCurrentConfig (XRRScreenConfiguration *config, VisualGroupID *visual_group, Rotation *rotation) +{ + *visual_group = (VisualGroupID) config->current_visual_group; + *rotation = (Rotation) config->current_rotation; + return (SizeID) config->current_size; +} + +int XRRRootToScreen(Display *dpy, Window root) +{ + int snum; + for (snum = 0; snum < ScreenCount(dpy); snum++) { + if (RootWindow(dpy, snum) == root) return snum; + } + return -1; +} + + +Bool XRRQueryExtension (Display *dpy, int *event_basep, int *error_basep) +{ + XExtDisplayInfo *info = XRRFindDisplay (dpy); + + if (XextHasExtension(info)) { + *event_basep = info->codes->first_event; + *error_basep = info->codes->first_error; + return True; + } else { + return False; + } +} + + +Status XRRQueryVersion (Display *dpy, + int *major_versionp, + int *minor_versionp) +{ + XExtDisplayInfo *info = XRRFindDisplay (dpy); + xRRQueryVersionReply rep; + xRRQueryVersionReq *req; + + RRCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + GetReq (RRQueryVersion, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRQueryVersion; + req->majorVersion = RANDR_MAJOR; + req->minorVersion = RANDR_MINOR; + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay (dpy); + SyncHandle (); + return 0; + } + *major_versionp = rep.majorVersion; + *minor_versionp = rep.minorVersion; + UnlockDisplay (dpy); + SyncHandle (); + return 1; +} + +XRRScreenConfiguration *XRRGetScreenInfo (Display *dpy, Window window) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + xRRGetScreenInfoReply rep; + xRRGetScreenInfoReq *req; + int nbytes, rbytes; + int i, j; + int nvisuals, ngroups; + int snum; + xScreenSizes *psize; + char *data; + struct _XRRScreenConfiguration *scp; + XRRVisualGroup *vgp; + XRRGroupOfVisualGroup *gvgp; + XRRVisualGroup **gp; + XRRScreenSize *ssp; + Visual **vgpp; + CARD32 *data32; + CARD16 *data16; + + RRCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + GetReq (RRGetScreenInfo, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRGetScreenInfo; + req->window = window; + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) + { + UnlockDisplay (dpy); + SyncHandle (); + return NULL; + } + nbytes = (long) rep.length << 2; + data = (char *) Xmalloc ((unsigned) nbytes); + if (!data) + { + _XEatData (dpy, (unsigned long) nbytes); + UnlockDisplay (dpy); + SyncHandle (); + return NULL; + } + _XReadPad (dpy, data, nbytes); + UnlockDisplay (dpy); + SyncHandle (); + + /* + * first we must compute how much space to allocate for + * randr library's use; we'll allocate the structures in a single + * allocation, on cleanlyness grounds. + */ + + /* pick up in the protocol buffer after the protocol size information */ + psize = (xScreenSizes *) data; + data32 = (CARD32 *) &psize[rep.nSizes]; + vgp = (XRRVisualGroup *) ssp; /* visual groups after size structures */ + /* and groups of visual groups structures after the array of visual groups */ + gvgp = (XRRGroupOfVisualGroup *) &vgp[rep.nVisualGroups]; + + /* + * first we count up the number of groups + */ + nvisuals = 0; + for (i = 0; i < rep.nVisualGroups; i++) { + j = *data32; + data32 += j + 1; + nvisuals += j; + } + + /* + * Next comes the groups of visual groups + */ + + data16 = (CARD16 *) data32; + /* + * We count up the number of groups + */ + ngroups = 0; + for (i = 0; i < rep.nGroupsOfVisualGroups; i++) { + j = *data16; + data16 += j + 1; + ngroups += j; + } + + rbytes = sizeof (XRRScreenConfiguration) + + (rep.nVisualGroups * sizeof (XRRVisualGroup)) + + (rep.nGroupsOfVisualGroups * sizeof (XRRGroupOfVisualGroup)) + + (rep.nSizes * sizeof (XRRScreenSize)) + + (nvisuals * sizeof (Visual *)) + + (ngroups * sizeof (XRRGroupOfVisualGroup *)); + + scp = (struct _XRRScreenConfiguration *) Xmalloc(rbytes); + if (scp == NULL) return NULL; + + + ssp = (XRRScreenSize *)(scp + 1); + vgp = (XRRVisualGroup *) (&ssp[rep.nSizes]); + gvgp = (XRRGroupOfVisualGroup *) (&vgp[rep.nVisualGroups]); + vgpp = (Visual **) (&gvgp[rep.nGroupsOfVisualGroups]); + gp = (XRRVisualGroup **) (&vgpp[ngroups]); + /* set up the screen configuration structure */ + scp->screen = ScreenOfDisplay (dpy, (snum = XRRRootToScreen(dpy, rep.root))); + + scp->visual_group = vgp; + scp->groups_of_visual_groups = gvgp; + scp->sizes = ssp; + scp->rotations = rep.setOfRotations; + scp->current_size = rep.sizeID; + scp->current_visual_group = rep.visualGroupID; + scp->current_rotation = rep.rotation; + scp->timestamp = rep.timestamp; + scp->config_timestamp = rep.configTimestamp; + scp->nsizes = rep.nSizes; + + /* + * Time to unpack the data from the server. + */ + + /* + * First comes the size information + */ + psize = (xScreenSizes *) data; + for (i = 0; i < rep.nSizes; i++) { + ssp[i].width = psize[i].widthInPixels; + ssp[i].height = psize[i].heightInPixels; + ssp[i].mwidth = psize[i].widthInMillimeters; + ssp[i].mheight = psize[i].heightInMillimeters; + ssp[i].group = psize[i].visualGroup; + } + /* + * Next comes the visual groups + */ + + data32 = (CARD32 *) &psize[i]; + + for (i = 0; i < rep.nVisualGroups; i++) { + vgp[i].visuals = vgpp; + vgp[i].nvisuals = (int) *data32++; + for (j = 0; j < vgp->nvisuals; j++) { + *vgpp = XRRVisualIDToVisual(dpy, snum, (VisualID) *data32++); + vgpp += 1; + } + } + + + data16 = (CARD16 *) data32; + + for (i = 0; i < rep.nGroupsOfVisualGroups; i++) { + gvgp[i].groups = gp; + gvgp[i].ngroups = (int) *data16++; + for (j = 0; j < gvgp[i].ngroups; j++) { + gvgp[i].groups[j] = &vgp[*data16++]; + gp += 1; + } + } + + return (XRRScreenConfiguration *)(scp); +} + +void XRRFreeScreenInfo (XRRScreenConfiguration *config) +{ + Xfree (config); +} + +void XRRScreenChangeSelectInput (Display *dpy, Window window, Bool enable) +{ + XExtDisplayInfo *info = XRRFindDisplay (dpy); + xRRScreenChangeSelectInputReq *req; + + RRSimpleCheckExtension (dpy, info); + + LockDisplay (dpy); + GetReq (RRScreenChangeSelectInput, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRScreenChangeSelectInput; + req->window = window; + req->enable = xFalse; + if (enable) req->enable = xTrue; + UnlockDisplay (dpy); + SyncHandle (); + return; +} + +Status XRRSetScreenConfig (Display *dpy, + XRRScreenConfiguration *config, + Drawable draw, + int size_index, + int visual_group_index, + Rotation rotation, Time timestamp) +{ + XExtDisplayInfo *info = XRRFindDisplay (dpy); + xRRSetScreenConfigReply rep; + xRRSetScreenConfigReq *req; + + RRCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + GetReq (RRSetScreenConfig, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRSetScreenConfig; + req->drawable = draw; + req->sizeID = size_index; + req->visualGroupID = visual_group_index; + req->rotation = rotation; + req->timestamp = timestamp; + req->configTimestamp = config->config_timestamp; + (void) _XReply (dpy, (xReply *) &rep, 0, xTrue); + + if (rep.status == RRSetConfigSuccess) { + /* if we succeed, set our view of reality to what we set it to */ + config->config_timestamp = rep.newConfigTimestamp; + config->timestamp = rep.newTimestamp; + config->screen = ScreenOfDisplay (dpy, XRRRootToScreen(dpy, rep.root)); + config->current_size = size_index; + config->current_rotation = rotation; + config->current_visual_group = visual_group_index; + } + UnlockDisplay (dpy); + SyncHandle (); + return(rep.status); +} diff --git a/xc/lib/Xrandr/Xrandr.h b/xc/lib/Xrandr/Xrandr.h new file mode 100644 index 000000000..c7b5dc3ac --- /dev/null +++ b/xc/lib/Xrandr/Xrandr.h @@ -0,0 +1,107 @@ +/* + * $XFree86: xc/lib/Xrandr/Xrandr.h,v 1.7 2001/08/01 00:44:40 tsi Exp $ + * + * Copyright © 2000 Compaq Computer Corporation, 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 Compaq not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Compaq makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * COMPAQ DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL COMPAQ + * 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, Compaq Computer Corporation + */ + +#ifndef _XRANDR_H_ +#define _XRANDR_H_ + +#include <X11/extensions/randr.h> + +typedef struct { + int nvisuals; + Visual **visuals; +} XRRVisualGroup; + +typedef struct { + int ngroups; + XRRVisualGroup **groups; +} XRRGroupOfVisualGroup; + +typedef struct { + int width, height; + int mwidth, mheight; + int group; +} XRRScreenSize; + +/* + * Events + */ + +typedef struct { + int type; /* event base */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; /* window which selected for this event */ + Window root; /* Root window for changed screen */ + Time timestamp; + Time config_timestamp; + SizeID size_index; + VisualGroupID visual_group_index; + Rotation rotation; + int width; + int height; + int mwidth; + int mheight; +} XRRScreenChangeNotifyEvent; + +/* internal representation is private to the library */ +typedef struct _XRRScreenConfiguration XRRScreenConfiguration; + +Bool XRRQueryExtension (Display *dpy, int *event_basep, int *error_basep); + +Status XRRQueryVersion (Display *dpy, + int *major_versionp, + int *minor_versionp); + +XRRScreenConfiguration *XRRGetScreenInfo (Display *dpy, + Drawable draw); + +void XRRFreeScreenInfo (XRRScreenConfiguration *config); + +Status XRRSetScreenConfig (Display *dpy, + XRRScreenConfiguration *config, + Drawable draw, + int size_index, + int visual_group_index, + Rotation rotation, + Time timestamp); + +XRRScreenSize *XRRSizes(XRRScreenConfiguration *config, int *nsizes); + +void XRRScreenChangeSelectInput (Display *dpy, Window window, Bool enable); + +Visual *XRRVisualIDToVisual(Display *dpy, int screen, VisualID id); + +int XRRVisualToDepth(Display *dpy, Visual *visual); + +Rotation XRRRotations(XRRScreenConfiguration *config, Rotation *current_rotation); + +Time XRRTimes (XRRScreenConfiguration *config, Time *config_timestamp); + +SizeID XRRCurrentConfig (XRRScreenConfiguration *config, VisualGroupID *visual_group, Rotation *rotation); + +int XRRRootToScreen(Display *dpy, Window root); + +#endif /* _XRANDR_H_ */ diff --git a/xc/lib/Xrandr/Xrandrint.h b/xc/lib/Xrandr/Xrandrint.h new file mode 100644 index 000000000..dd7f08b97 --- /dev/null +++ b/xc/lib/Xrandr/Xrandrint.h @@ -0,0 +1,67 @@ +/* + * $XFree86: xc/lib/Xrandr/Xrandrint.h,v 1.2 2001/06/07 15:33:43 keithp Exp $ + * + * Copyright © 2000 Compaq Computer Corporation, 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 Compaq not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Compaq makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * COMPAQ DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL COMPAQ + * 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, Compaq Computer Corporation, Inc. + */ + +#ifndef _XRANDRINT_H_ +#define _XRANDRINT_H_ + +#define NEED_EVENTS +#define NEED_REPLIES +#include <X11/Xlibint.h> +#include <X11/Xutil.h> +#include "Xext.h" /* in ../include */ +#include "extutil.h" /* in ../include */ +#include "Xrandr.h" +#include "randr.h" +#include "randrproto.h" + +extern XExtensionInfo XrandrExtensionInfo; +extern char XrandrExtensionName[]; + +#define RRCheckExtension(dpy,i,val) \ + XextCheckExtension (dpy, i, XRRExtensionName, val) + +#define RRSimpleCheckExtension(dpy,i) \ + XextSimpleCheckExtension (dpy, i, XRRExtensionName) + +XExtDisplayInfo * +XRRFindDisplay (Display *dpy); + +/* deliberately opaque internal data structure; can be extended, + but not reordered */ +struct _XRRScreenConfiguration { + Screen *screen; /* the root window in GetScreenInfo */ + XRRVisualGroup *visual_group; + XRRGroupOfVisualGroup *groups_of_visual_groups; + XRRScreenSize *sizes; + Rotation rotations; + Rotation current_rotation; + int nsizes; + int current_size; + int current_visual_group; + Time timestamp; + Time config_timestamp; +}; + +#endif /* _XRANDRINT_H_ */ diff --git a/xc/lib/Xrandr/test.c b/xc/lib/Xrandr/test.c new file mode 100644 index 000000000..333d2a6ab --- /dev/null +++ b/xc/lib/Xrandr/test.c @@ -0,0 +1,21 @@ +/* $XFree86: xc/lib/Xrandr/test.c,v 1.2 2001/08/06 21:46:03 dawes Exp $ */ + +#include <stdio.h> +#include <X11/Xlib.h> +#include "Xrandr.h" + +main (int argc, char **argv) + +{ + char *display_name = ":0"; + Display *display; + int major, minor, status; + + if ((display = XOpenDisplay (display_name)) == NULL) { + fprintf(stderr, "Can't open display!\n"); + } + status = XRRQueryVersion (display, &major, &minor); + fprintf(stderr, "status = %d, major = %d, minor = %d\n, + status, major, minor"); + +} diff --git a/xc/lib/Xt/ShellI.h b/xc/lib/Xt/ShellI.h new file mode 100644 index 000000000..33d45dab4 --- /dev/null +++ b/xc/lib/Xt/ShellI.h @@ -0,0 +1,12 @@ +/* $XFree86: xc/lib/Xt/ShellI.h,v 1.1 2001/08/18 02:41:29 dawes Exp $ */ + +#ifndef _XtShellInternal_h +#define _XtShellInternal_h + +#include <X11/Xfuncproto.h> + +_XFUNCPROTOBEGIN + +extern void _XtShellGetCoordinates(Widget widget, Position *x, Position *y); + +#endif /* _XtShellInternal_h */ diff --git a/xc/lib/font/fontfile/fontencc.c b/xc/lib/font/fontfile/fontencc.c new file mode 100644 index 000000000..2c8bdbd14 --- /dev/null +++ b/xc/lib/font/fontfile/fontencc.c @@ -0,0 +1,74 @@ +/* +Copyright (c) 1998-2001 by Juliusz Chroboczek + +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 +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. +*/ +/* $XFree86: xc/lib/font/fontfile/fontencc.c,v 1.2 2001/08/16 14:33:46 dawes Exp $ */ + +/* Binary compatibility code. */ + +/* This file includes code to make modules compiled for earlier + versions of the fontenc interfaces link with this one. It does + *not* provide source compatibility, as many of the data structures + now have different names. */ + +#include "fontenc.h" +#include "fontencc.h" + +extern void ErrorF(const char *f, ...); + +char * +font_encoding_from_xlfd(const char * name, int length) +{ + return FontEncFromXLFD(name, length); +} + +FontEncPtr +font_encoding_find(const char *encoding_name, const char *filename) +{ + return FontEncFind(encoding_name, filename); +} + +unsigned +font_encoding_recode(unsigned code, + FontEncPtr encoding, FontMapPtr mapping) +{ + if(encoding != mapping->encoding) { + ErrorF("Inconsistent mapping/encoding\n"); + return 0; + } + return FontEncRecode(code, mapping); +} + +char * +font_encoding_name(unsigned code, + FontEncPtr encoding, FontMapPtr mapping) +{ + if(encoding != mapping->encoding) { + ErrorF("Inconsistent mapping/encoding\n"); + return 0; + } + return FontEncName(code, mapping); +} + +char ** +identifyEncodingFile(const char *filename) +{ + return FontEncIdentify(filename); +} diff --git a/xc/lib/font/include/fontencc.h b/xc/lib/font/include/fontencc.h new file mode 100644 index 000000000..8ed1d33c8 --- /dev/null +++ b/xc/lib/font/include/fontencc.h @@ -0,0 +1,36 @@ +/* +Copyright (c) 1998-2001 by Juliusz Chroboczek + +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 +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. +*/ +/* $XFree86: xc/lib/font/include/fontencc.h,v 1.1 2001/08/16 14:33:47 dawes Exp $ */ + +/* Binary compatibility entry points. */ + +/* This file includes code to make modules compiled for earlier + versions of the fontenc interfaces link with this one. It does + *not* provide source compatibility, as many of the data structures + now have different names. */ + +extern char *font_encoding_from_xlfd(const char*, int); +extern unsigned font_encoding_recode(unsigned, FontEncPtr, FontMapPtr); +extern FontEncPtr font_encoding_find(const char*, const char*); +extern char *font_encoding_name(unsigned, FontEncPtr, FontMapPtr); +extern char **identifyEncodingFile(const char *fileName); + diff --git a/xc/lib/fontenc/Imakefile b/xc/lib/fontenc/Imakefile new file mode 100644 index 000000000..b29bb8e4d --- /dev/null +++ b/xc/lib/fontenc/Imakefile @@ -0,0 +1,28 @@ +XCOMM $XFree86: xc/lib/fontenc/Imakefile,v 1.2 2001/08/16 14:33:47 dawes Exp $ + + INCLUDES = -I$(FONTINCSRC) -I$(FONTLIBSRC)/include -I$(FONTLIBSRC)/fontfile \ + -I$(XTOP)/include + +FONTENCDEFS = -DFONTENC_NO_LIBFONT \ + -DFONT_ENCODINGS_DIRECTORY=\"$(FONTDIR)/encodings/encodings.dir\" + + DEFINES = StrcasecmpDefines $(FONTENCDEFS) + + SRCS = fontenc.c encparse.c + OBJS = fontenc.o encparse.o + +#define DoNormalLib NormalLibFontEnc +#define DoSharedLib SharedLibFontEnc +#define DoDebugLib DebugLibFontEnc +#define DoProfileLib ProfileLibFontEnc +#define LibName fontenc +#define LibHeaders NO +#define SoRev SOFONTENCREV + +#include <Library.tmpl> + +LinkSourceFile(fontenc.c,$(FONTLIBSRC)/fontfile) +LinkSourceFile(encparse.c,$(FONTLIBSRC)/fontfile) + +DependTarget() + diff --git a/xc/programs/Xserver/Xext/sleepuntil.h b/xc/programs/Xserver/Xext/sleepuntil.h new file mode 100644 index 000000000..29d761a0e --- /dev/null +++ b/xc/programs/Xserver/Xext/sleepuntil.h @@ -0,0 +1,47 @@ +/* $XFree86: xc/programs/Xserver/Xext/sleepuntil.h,v 1.1 2001/08/01 00:44:44 tsi Exp $ */ +/* + * Copyright (C) 2001 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. + */ + +#ifndef _SLEEPUNTIL_H_ +#define _SLEEPUNTIL_H_ 1 + +#include "dix.h" + +extern int ClientSleepUntil( +#if NeedFunctionPrototypes + ClientPtr client, + TimeStamp *revive, + void (*notifyFunc)( +#if NeedNestedPrototypes + ClientPtr /* client */, + pointer /* closure */ +#endif + ), + pointer Closure +#endif +); + +#endif diff --git a/xc/programs/Xserver/hw/darwin/bundle/XView.h b/xc/programs/Xserver/hw/darwin/bundle/XView.h new file mode 100644 index 000000000..c6f730298 --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/bundle/XView.h @@ -0,0 +1,44 @@ +/* + * NSView subclass for Mac OS X rootless X server + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/bundle/XView.h,v 1.1 2001/07/01 02:13:40 torrey Exp $ */ + +#import <Cocoa/Cocoa.h> + +#include <drivers/event_status_driver.h> +#include "fakeBoxRec.h" + +@interface XView : NSView +{ + char *mBits; + int mBytesPerRow; + int mBitsPerSample; + int mSamplesPerPixel; + int mBitsPerPixel; + int mDepth; +} + +-(id) initWithFrame:(NSRect)aRect; +-(void) dealloc; + +-(void) drawRect:(NSRect)aRect; +-(BOOL) isFlipped; +-(BOOL) acceptsFirstResponder; +-(BOOL) acceptsFirstMouse:(NSEvent *)theEvent; +-(BOOL) shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent; + +-(void) mouseDown:(NSEvent *)anEvent; + +-(void) setFrameSize:(NSSize)newSize; + +-(void) allocBitsForSize:(NSSize)newSize; +-(char *) bits; +-(void) getBits:(char **)bits + rowBytes:(int *)rowBytes + depth:(int *)depth + bitsPerPixel:(int *)bpp; + +-(void) refreshRects:(fakeBoxRec *)rectList count:(int)count; +-(void) copyRects:(fakeBoxRec *)rectList count:(int)count; + +@end diff --git a/xc/programs/Xserver/hw/darwin/bundle/XView.m b/xc/programs/Xserver/hw/darwin/bundle/XView.m new file mode 100644 index 000000000..2cf002811 --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/bundle/XView.m @@ -0,0 +1,195 @@ +/* + * NSView subclass for Mac OS X rootless X server + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/bundle/XView.m,v 1.1 2001/07/01 02:13:41 torrey Exp $ */ + +#include <ApplicationServices/ApplicationServices.h> + +#import "XWindow.h" +#import "XView.h" +#include "fakeBoxRec.h" + +static const void *infobytes(void *info) +{ + return info; +} + + +@implementation XView + +-(id) initWithFrame:(NSRect)aRect +{ + self = [super initWithFrame:aRect]; + if (!self) return nil; + + mBitsPerSample = 8; + mSamplesPerPixel = 3; + mDepth = mBitsPerSample * mSamplesPerPixel; + mBitsPerPixel = 32; + mBits = nil; + [self allocBitsForSize:aRect.size]; + + return self; +} + +-(void) dealloc +{ + if (mBits) free(mBits); + [super dealloc]; +} + +-(void) drawRect:(NSRect)aRect +{ + // Never draw here. +} + +-(BOOL) isFlipped +{ + return NO; // YES inverts the BitmapImageRep too... +} + +-(BOOL) isOpaque +{ + // fixme + return YES; +} + +-(BOOL) acceptsFirstResponder +{ + return YES; +} + +-(BOOL) acceptsFirstMouse:(NSEvent *)theEvent +{ + return YES; +} + +-(BOOL) shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent +{ + return YES; +} + + +-(void) mouseDown:(NSEvent *)anEvent +{ + // Only X is allowed to restack windows. + [NSApp preventWindowOrdering]; + [[self nextResponder] mouseDown:anEvent]; +} + +-(void) mouseUp:(NSEvent *)anEvent +{ + // Bring app to front if necessary + // Don't bring app to front in mouseDown; mousedown-mouseup is too + // long and X gets what looks like a mouse drag. + if (! [NSApp isActive]) { + [NSApp activateIgnoringOtherApps:YES]; + [NSApp arrangeInFront:nil]; // fixme only bring some windows forward? + } + + [[self nextResponder] mouseDown:anEvent]; +} + + +// Reallocate bits. +// setFrame goes through here too. +-(void) setFrameSize:(NSSize)newSize +{ + [self allocBitsForSize:newSize]; + [super setFrameSize:newSize]; +} + +-(void) allocBitsForSize:(NSSize)newSize +{ + if (mBits) free(mBits); + mBytesPerRow = newSize.width * mBitsPerPixel / 8; + mBits = malloc(mBytesPerRow * newSize.height); +} + +-(char *) bits +{ + return mBits; +} + +-(void) getBits:(char **)bits + rowBytes:(int *)rowBytes + depth:(int *)depth + bitsPerPixel:(int *)bpp +{ + *bits = mBits; + *rowBytes = mBytesPerRow; + *depth = mDepth; + *bpp = mBitsPerPixel; +} + +-(void) refreshRects:(fakeBoxRec *)rectList count:(int)count +{ + [self lockFocus]; + [self copyRects:rectList count:count]; + [[NSGraphicsContext currentContext] flushGraphics]; + [self unlockFocus]; +} + +// rectList is X-flipped and LOCAL coords +-(void) copyRects:(fakeBoxRec *)rectList count:(int)count +{ + unsigned char *offsetbits; + + fakeBoxRec *r; + fakeBoxRec *end; + NSRect bounds; + + CGContextRef destCtx = (CGContextRef)[[NSGraphicsContext currentContext] + graphicsPort]; + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + const CGDataProviderDirectAccessCallbacks cb = { + infobytes, NULL, NULL, NULL + }; + + bounds = [self frame]; + bounds.origin.x = bounds.origin.y = 0; + + r = rectList; + end = rectList + count; + for ( ; r < end; r++) { + NSRect nsr = {{r->x1, r->y1}, {r->x2-r->x1, r->y2-r->y1}}; + CGRect destRect; + CGDataProviderRef dataProviderRef; + CGImageRef imageRef; + + // Clip to window + // (bounds origin is (0,0) so it can be used in either flip) + // fixme is this necessary with pixmap-per-window? + nsr = NSIntersectionRect(nsr, bounds); + + // Disallow empty rects + if (nsr.size.width <= 0 || nsr.size.height <= 0) continue; + + offsetbits = mBits + (int)(nsr.origin.y * mBytesPerRow + + nsr.origin.x * mBitsPerPixel/8); + + // Flip r to Cocoa-flipped + nsr.origin.y = bounds.size.height - nsr.origin.y - nsr.size.height; + destRect = CGRectMake(nsr.origin.x, nsr.origin.y, + nsr.size.width, nsr.size.height); + + // NSDrawBitmap but doesn't scale and can use more pixel layouts than + // Cocoa's RGBA. Maybe CGDrawBitmap is like this. + + dataProviderRef = CGDataProviderCreateDirectAccess(offsetbits, + destRect.size.height * mBytesPerRow, &cb); + + imageRef = CGImageCreate(destRect.size.width, destRect.size.height, + mBitsPerSample, mBitsPerPixel, + mBytesPerRow, colorSpace, + kCGImageAlphaNoneSkipFirst, // ARGB + dataProviderRef, NULL, + 1, kCGRenderingIntentDefault); + + CGContextDrawImage(destCtx, destRect, imageRef); + CGImageRelease(imageRef); + CGDataProviderRelease(dataProviderRef); + } +} + +@end diff --git a/xc/programs/Xserver/hw/darwin/bundle/XWindow.h b/xc/programs/Xserver/hw/darwin/bundle/XWindow.h new file mode 100644 index 000000000..1049fc471 --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/bundle/XWindow.h @@ -0,0 +1,37 @@ +/* + * NSWindow subclass for Mac OS X rootless X server + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/bundle/XWindow.h,v 1.1 2001/07/01 02:13:41 torrey Exp $ */ + +#import <Cocoa/Cocoa.h> +#import "XView.h" + +#include "fakeBoxRec.h" + +@interface XWindow : NSWindow +{ + XView *mView; +} + +-(id) initWithContentRect:(NSRect)aRect + isRoot:(BOOL)isRoot; +-(void) dealloc; + +-(char *) bits; +-(void) getBits:(char **)bits + rowBytes:(int *)rowBytes + depth:(int *)depth + bitsPerPixel:(int *)bpp; + +-(void) refreshRects:(fakeBoxRec *)rectList + count:(int)count; + +-(void) orderWindow:(NSWindowOrderingMode)place + relativeTo:(int)otherWindowNumber; + +-(void) sendEvent:(NSEvent *)anEvent; +-(BOOL) canBecomeMainWindow; +-(BOOL) canBecomeKeyWindow; +-(BOOL) useOptimizedDrawing; + +@end diff --git a/xc/programs/Xserver/hw/darwin/bundle/XWindow.m b/xc/programs/Xserver/hw/darwin/bundle/XWindow.m new file mode 100644 index 000000000..58ec17b58 --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/bundle/XWindow.m @@ -0,0 +1,111 @@ +/* + * NSWindow subclass for Mac OS X rootless X server + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/bundle/XWindow.m,v 1.2 2001/08/01 05:34:06 torrey Exp $ */ + +#import "XWindow.h" +#import "Xserver.h" + + +@implementation XWindow + +// XWindow MUST NOT autodisplay! Autodisplay can cause a deadlock. +// event thread - autodisplay: locks view hierarchy, then window +// X Server thread - window resize: locks window, then view hierarchy +// Deadlock occurs if each thread gets one lock and waits for the other. + +// XWindow MUST defer! Otherwise an assertion fails in +// NSViewHierarchyLock sometimes. + +-(id) initWithContentRect:(NSRect)aRect + isRoot:(BOOL)isRoot +{ + int style; + NSRect viewRect = {{0, 0}, {aRect.size.width, aRect.size.height}}; + style = NSBorderlessWindowMask; + + self = [super initWithContentRect: aRect + styleMask: style + backing: NSBackingStoreBuffered + defer: YES]; + if (! self) return NULL; + + // fixme! + // [self setBackgroundColor:[NSColor clearColor]]; // erase transparent + [self setAlphaValue:1.0]; // draw opaque + // [self setOpaque:NO]; + + [self setAutodisplay:FALSE]; // MUST NOT autodisplay! see comment above + [self setHasShadow: !isRoot]; // All windows have shadows except the root. + + // [self setAcceptsMouseMovedEvents:YES]; // MUST be AFTER orderFront? + [self setDelegate:self]; // fixme is this still needed? + + mView = [[XView alloc] initWithFrame: viewRect]; + [self setContentView:mView]; + [self setInitialFirstResponder:mView]; + + return self; +} + +-(void) dealloc +{ + [mView release]; + [super dealloc]; +} + +-(char *) bits +{ + return [mView bits]; +} + +-(void) getBits:(char **)bits + rowBytes:(int *)rowBytes + depth:(int *)depth + bitsPerPixel:(int *)bpp +{ + [mView getBits:bits rowBytes:rowBytes depth:depth bitsPerPixel:bpp]; +} + + +// rects are X-flip and LOCAL coords +-(void) refreshRects:(fakeBoxRec *)rectList count:(int)count; +{ + [mView refreshRects:rectList count:count]; +} + + +// Deferred windows don't handle mouse moved events very well. +-(void) orderWindow:(NSWindowOrderingMode)place + relativeTo:(int)otherWindowNumber +{ + [super orderWindow:place relativeTo:otherWindowNumber]; + [self setAcceptsMouseMovedEvents:YES]; +} + +-(void) sendEvent:(NSEvent *)anEvent +{ + [super sendEvent:anEvent]; + [self setAcceptsMouseMovedEvents:YES]; +} + +// XWindow may be frameless, and frameless windows default to +// NO key and NO main. +// update: we *don't* want main or key status after all +-(BOOL) canBecomeMainWindow +{ + return NO; +} + +-(BOOL) canBecomeKeyWindow +{ + return NO; +} + +// XWindow has no overlapping subviews +-(BOOL) useOptimizedDrawing +{ + return YES; +} + +@end diff --git a/xc/programs/Xserver/hw/darwin/bundle/fakeBoxRec.h b/xc/programs/Xserver/hw/darwin/bundle/fakeBoxRec.h new file mode 100644 index 000000000..1e5027cc8 --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/bundle/fakeBoxRec.h @@ -0,0 +1,15 @@ +/* $XFree86: xc/programs/Xserver/hw/darwin/bundle/fakeBoxRec.h,v 1.1 2001/07/01 02:13:41 torrey Exp $ */ + +#ifndef FAKEBOXREC_H +#define FAKEBOXREC_H + +// This struct is byte-compatible with X11's BoxRec, for use in +// code that can't include X headers. +typedef struct _fakeBox { + short x1; + short y1; + short x2; + short y2; +} fakeBoxRec; + +#endif diff --git a/xc/programs/Xserver/hw/darwin/bundle/rootless.h b/xc/programs/Xserver/hw/darwin/bundle/rootless.h new file mode 100644 index 000000000..705dbf9f2 --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/bundle/rootless.h @@ -0,0 +1,127 @@ +/* + * External interface to generic rootless mode + * + * Greg Parker gparker@cs.stanford.edu March 3, 2001 + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/bundle/rootless.h,v 1.3 2001/08/01 05:34:06 torrey Exp $ */ + +#ifndef _ROOTLESS_H +#define _ROOTLESS_H + +#include "mi.h" +#include "gcstruct.h" + +// RootlessFrameRec +// Describes a single rootless window (aka frame). +// The rootless mode keeps track of window position, and the +// rootless implementation is responsible for the pixmap. +// Multiple screens: all coordinates are SCREEN-LOCAL, not global. + + +typedef struct RootlessFrameRec { + /* Data maintained by rootless mode */ + /* position and size, including window border, in screen coordinates */ + int x; + int y; + unsigned int w; + unsigned int h; + WindowPtr win; /* the top-level window drawn in this frame */ + int isRoot; /* TRUE if this is the root window */ + + /* Data maintained by rootless implementation */ + char *pixelData; + int depth; // color bits per pixel; depth <= bitsPerPixel + int bitsPerPixel; + int bytesPerRow; + + void *devPrivate; /* for caller's use */ +} RootlessFrameRec, *RootlessFramePtr; + + +// Create a new frame. +// pUpper is the window above the new frame, or NULL if the new +// frame will be on top. +// pFrame is completely initialized. devPrivate is NULL +// The pixmap must be valid when this is done. +typedef void (*RootlessCreateFrameProc) + (ScreenPtr pScreen, RootlessFramePtr pFrame, RootlessFramePtr pUpper); + +// Destroy a frame. Caller must free any private data and the pixmap. +// All drawing is stopped and all updates are flushed before this is called. +typedef void (*RootlessDestroyFrameProc) + (ScreenPtr pScreen, RootlessFramePtr pFrame); + +// Move a frame on screen. +// The frame changes position and nothing else. +// pFrame and pFrame->win already contain the information about the +// new position. oldX and oldY are the old position. +// All updates are flushed before this is called. +// The pixmap may change during this function. +typedef void (*RootlessMoveFrameProc) + (ScreenPtr pScreen, RootlessFramePtr pFrame, int oldX, int oldY); + +// Change frame ordering (aka stacking, layering) +// pFrame->win already has its new siblings. +// pOldNext is the window that was below this one, or NULL if this was +// at the bottom. +// pNewNext is the window that is now below this one, or NULL if this is +// now at the bottom. +typedef void (*RootlessRestackFrameProc) + (ScreenPtr pScreen, RootlessFramePtr pFrame, + RootlessFramePtr pOldNext, RootlessFramePtr pNewNext); + +// Flush drawing updates to the screen. +// pDamage contains all changed pixels. +// pDamage is in frame-local coordinates. +// pDamage is clipped to the frame bounds and the frame shape. +typedef void (*RootlessUpdateRegionProc) + (ScreenPtr pScreen, RootlessFramePtr pFrame, RegionPtr pDamage); + +// Change the frame's shape. +// pNewShape is in frame-local coordinates. +// Everything outside pNewShape is no longer part of the frame. +// pNewShape is {0, 0, width, height} for a plain-shaped frame. +// fixme can the pixmap change here? +// fixme reimplement shape +typedef void (*RootlessReshapeFrameProc) + (ScreenPtr pScreen, RootlessFramePtr pFrame, RegionPtr pNewShape); + +// Frame is about to resize. +// The frame has its new position and size already. +// postconditions: +// The pixmap MUST point to a pixmap with the new size. +// The pixmap data is undefined. +// The old pixmap may be destroyed here. +typedef void (*RootlessStartResizeFrameProc) + (ScreenPtr pScreen, RootlessFramePtr pFrame, + int oldX, int oldY, unsigned int oldW, unsigned int oldH); + +// Frame is done resizing. +// Destroy the old pixmap if you haven't already. +typedef void (*RootlessFinishResizeFrameProc) + (ScreenPtr pScreen, RootlessFramePtr pFrame, + int oldX, int oldY, unsigned int oldW, unsigned int oldH); + + +// The callback function list. +// Any of these may be NULL. +typedef struct RootlessFrameProcs { + RootlessCreateFrameProc CreateFrame; + RootlessDestroyFrameProc DestroyFrame; + + RootlessMoveFrameProc MoveFrame; + RootlessStartResizeFrameProc StartResizeFrame; + RootlessFinishResizeFrameProc FinishResizeFrame; + RootlessRestackFrameProc RestackFrame; + RootlessReshapeFrameProc ReshapeFrame; + + RootlessUpdateRegionProc UpdateRegion; + + // RootlessStartDrawingProc StartDrawing; + // RootlessStopDrawingProc StopDrawing; +} RootlessFrameProcs; + +// Initialize rootless mode on the given screen. +Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcs *procs); + +#endif /* _ROOTLESS_H */ diff --git a/xc/programs/Xserver/hw/darwin/bundle/rootlessAqua.h b/xc/programs/Xserver/hw/darwin/bundle/rootlessAqua.h new file mode 100644 index 000000000..721dc1695 --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/bundle/rootlessAqua.h @@ -0,0 +1,15 @@ +/* + * Rootless setup for Aqua + * + * Greg Parker gparker@cs.stanford.edu + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/bundle/rootlessAqua.h,v 1.2 2001/08/01 05:34:06 torrey Exp $ */ + +#ifndef _ROOTLESSAQUA_H +#define _ROOTLESSAQUA_H + +Bool AquaAddScreen(int index, ScreenPtr pScreen); +Bool AquaSetupScreen(int index, ScreenPtr pScreen); +void AquaDisplayInit(void); + +#endif /* _ROOTLESSAQUA_H */ diff --git a/xc/programs/Xserver/hw/darwin/bundle/rootlessAquaGlue.c b/xc/programs/Xserver/hw/darwin/bundle/rootlessAquaGlue.c new file mode 100644 index 000000000..14815ec01 --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/bundle/rootlessAquaGlue.c @@ -0,0 +1,193 @@ +/* + * Generic rootless to Aqua specific glue code + * + * This code acts as a glue between the generic rootless X server code + * and the Aqua specific implementation, which includes definitions that + * conflict with stardard X types. + * + * Greg Parker gparker@cs.stanford.edu + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/bundle/rootlessAquaGlue.c,v 1.3 2001/08/01 05:34:06 torrey Exp $ */ + +#include "regionstr.h" +#include "scrnintstr.h" + +#include "darwin.h" +#include "quartz.h" +#include "rootlessAqua.h" +#include "rootlessAquaImp.h" +#include "rootless.h" +#include "globals.h" // dixScreenOrigins[] + + +///////////////////////////////////////// +// Rootless mode callback glue + +static void +AquaGlueCreateFrame(ScreenPtr pScreen, RootlessFramePtr pFrame, + RootlessFramePtr pUpper) +{ + int sx = dixScreenOrigins[pScreen->myNum].x; + int sy = dixScreenOrigins[pScreen->myNum].y; + + pFrame->devPrivate = AquaNewWindow(pUpper ? pUpper->devPrivate : NULL, + pFrame->x+sx, pFrame->y+sy, + pFrame->w, pFrame->h, + pFrame->isRoot); + AquaGetPixmap(pFrame->devPrivate, &pFrame->pixelData, + &pFrame->bytesPerRow, &pFrame->depth, + &pFrame->bitsPerPixel); +} + + +static void +AquaGlueDestroyFrame(ScreenPtr pScreen, RootlessFramePtr pFrame) +{ + AquaDestroyWindow(pFrame->devPrivate); +} + +static void +AquaGlueMoveFrame(ScreenPtr pScreen, RootlessFramePtr pFrame, + int oldX, int oldY) +{ + int sx = dixScreenOrigins[pScreen->myNum].x; + int sy = dixScreenOrigins[pScreen->myNum].y; + + AquaMoveWindow(pFrame->devPrivate, pFrame->x+sx, pFrame->y+sy); +} + + +static void +AquaGlueStartResizeFrame(ScreenPtr pScreen, RootlessFramePtr pFrame, + int oldX, int oldY, + unsigned int oldW, unsigned int oldH) +{ + int sx = dixScreenOrigins[pScreen->myNum].x; + int sy = dixScreenOrigins[pScreen->myNum].y; + + AquaStartResizeWindow(pFrame->devPrivate, + pFrame->x+sx, pFrame->y+sy, pFrame->w, pFrame->h); + AquaGetPixmap(pFrame->devPrivate, &pFrame->pixelData, + &pFrame->bytesPerRow, &pFrame->depth, + &pFrame->bitsPerPixel); +} + +static void +AquaGlueFinishResizeFrame(ScreenPtr pScreen, RootlessFramePtr pFrame, + int oldX, int oldY, + unsigned int oldW, unsigned int oldH) +{ + int sx = dixScreenOrigins[pScreen->myNum].x; + int sy = dixScreenOrigins[pScreen->myNum].y; + + AquaFinishResizeWindow(pFrame->devPrivate, + pFrame->x+sx, pFrame->y+sy, pFrame->w, pFrame->h); +} + + +static void +AquaGlueRestackFrame(ScreenPtr pScreen, RootlessFramePtr pFrame, + RootlessFramePtr pOldPrev, + RootlessFramePtr pNewPrev) +{ + AquaRestackWindow(pFrame->devPrivate, + pNewPrev ? pNewPrev->devPrivate : NULL); +} + +static void +AquaGlueReshapeFrame(ScreenPtr pScreen, RootlessFramePtr pFrame, + RegionPtr pNewShape) +{ + int sx = dixScreenOrigins[pScreen->myNum].x; + int sy = dixScreenOrigins[pScreen->myNum].y; + + if (pFrame->isRoot) return; // shouldn't happen; mi or dix covers this + REGION_TRANSLATE(pScreen, pNewShape, sx, sy); + AquaReshapeWindow(pFrame->devPrivate, + (fakeBoxRec *) REGION_RECTS(pNewShape), + REGION_NUM_RECTS(pNewShape)); +} + +static void +AquaGlueUpdateRegion(ScreenPtr pScreen, RootlessFramePtr pFrame, + RegionPtr pDamage) +{ + AquaUpdateRects(pFrame->devPrivate, + (fakeBoxRec *) REGION_RECTS(pDamage), + REGION_NUM_RECTS(pDamage)); +} + +#if 0 +static void +AquaGlueStartDrawing(ScreenPtr pScreen, RootlessFramePtr pFrame) +{ + AquaStartDrawing(pFrame->devPrivate, &pFrame->pixelData, + &pFrame->bytesPerRow, &pFrame->depth, + &pFrame->bitsPerPixel); +} + +static void +AquaGlueStopDrawing(ScreenPtr pScreen, RootlessFramePtr pFrame) +{ + AquaStopDrawing(pFrame->devPrivate); +} +#endif + +static RootlessFrameProcs aquaRootlessProcs = { + AquaGlueCreateFrame, + AquaGlueDestroyFrame, + AquaGlueMoveFrame, + AquaGlueStartResizeFrame, + AquaGlueFinishResizeFrame, + AquaGlueRestackFrame, + AquaGlueReshapeFrame, + AquaGlueUpdateRegion +}; + + +/////////////////////////////////////// +// Rootless mode initialization. +// Exported by rootlessAqua.h + +/* + * AquaDisplayInit + * Find all Aqua screens. + */ +void +AquaDisplayInit(void) +{ + darwinScreensFound = AquaDisplayCount(); +} + + +/* + * AquaAddScreen + * Init the framebuffer and record pixmap parameters for the screen. + */ +Bool +AquaAddScreen(int index, ScreenPtr pScreen) +{ + DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen); + + dfb->pixelInfo.pixelType = kIORGBDirectPixels; + AquaScreenInit(index, &dfb->x, &dfb->y, &dfb->width, &dfb->height, + &dfb->pitch, &dfb->pixelInfo.bitsPerComponent, + &dfb->pixelInfo.componentCount, &dfb->bitsPerPixel); + dfb->colorBitsPerPixel = dfb->pixelInfo.bitsPerComponent * + dfb->pixelInfo.componentCount; + + // No frame buffer - it's all in window pixmaps. + dfb->framebuffer = NULL; // malloc(dfb.pitch * dfb.height); + + return TRUE; +} + +/* + * AquaSetupScreen + * Setup the screen for rootless access. + */ +Bool +AquaSetupScreen(int index, ScreenPtr pScreen) +{ + return RootlessInit(pScreen, &aquaRootlessProcs); +} diff --git a/xc/programs/Xserver/hw/darwin/bundle/rootlessAquaImp.h b/xc/programs/Xserver/hw/darwin/bundle/rootlessAquaImp.h new file mode 100644 index 000000000..fe2d4e3a4 --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/bundle/rootlessAquaImp.h @@ -0,0 +1,38 @@ +/* + * Rootless implementation for Mac OS X Aqua environment + * + * Greg Parker gparker@cs.stanford.edu + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/bundle/rootlessAquaImp.h,v 1.3 2001/08/01 05:34:06 torrey Exp $ */ + +#ifndef _ROOTLESSAQUAIMP_H +#define _ROOTLESSAQUAIMP_H + +#include "fakeBoxRec.h" + +int AquaDisplayCount(); + +void AquaScreenInit(int index, int *x, int *y, int *width, int *height, + int *rowBytes, unsigned long *bps, unsigned long *spp, + int *bpp); + +void *AquaNewWindow(void *upperw, int x, int y, int w, int h, int isRoot); + +void AquaDestroyWindow(void *rw); + +void AquaMoveWindow(void *rw, int x, int y); + +void AquaStartResizeWindow(void *rw, int x, int y, int w, int h); + +void AquaFinishResizeWindow(void *rw, int x, int y, int w, int h); + +void AquaUpdateRects(void *rw, fakeBoxRec *rects, int count); + +void AquaRestackWindow(void *rw, void *lowerw); + +void AquaReshapeWindow(void *rw, fakeBoxRec *rects, int count); + +void AquaGetPixmap(void *rw, char **bits, + int *rowBytes, int *depth, int *bpp); + +#endif /* _ROOTLESSAQUAIMP_H */ diff --git a/xc/programs/Xserver/hw/darwin/bundle/rootlessAquaImp.m b/xc/programs/Xserver/hw/darwin/bundle/rootlessAquaImp.m new file mode 100644 index 000000000..f9ed35f42 --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/bundle/rootlessAquaImp.m @@ -0,0 +1,135 @@ +/* + * Rootless implementation for Mac OS X Aqua environment + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/bundle/rootlessAquaImp.m,v 1.3 2001/08/01 05:34:06 torrey Exp $ */ + +#include "rootlessAquaImp.h" +#include "XWindow.h" +#include "fakeBoxRec.h" + + +typedef struct { + XWindow *window; +} AquaWindowRec; + + +#define WINREC(rw) ((AquaWindowRec *)rw) + +int AquaDisplayCount() +{ + return [[NSScreen screens] count]; +} + +void AquaScreenInit(int index, int *x, int *y, int *width, int *height, + int *rowBytes, unsigned long *bps, unsigned long *spp, + int *bpp) +{ + NSScreen *screen = [[NSScreen screens] objectAtIndex:index]; + NSRect frame = [screen frame]; + + // fixme + *bps = 8; + *spp = 3; + *bpp = 32; + + // set x,y so (0,0) is top left of main screen + *x = frame.origin.x; + *y = [[NSScreen mainScreen] frame].size.height - + frame.size.height - frame.origin.y; + + *width = frame.size.width; + *height = frame.size.height; + *rowBytes = (*width) * (*bpp) / 8; +} + +void *AquaNewWindow(void *upperw, int x, int y, int w, int h, int isRoot) +{ + AquaWindowRec *winRec = (AquaWindowRec *)malloc(sizeof(AquaWindowRec)); + NSRect frame = {{x, y}, {w, h}}; + + frame.origin.y = [[NSScreen mainScreen] frame].size.height - y - h; + winRec->window = [[XWindow alloc] initWithContentRect:frame isRoot:isRoot]; + + if (upperw) { + AquaWindowRec *upperRec = WINREC(upperw); + int uppernum = [upperRec->window windowNumber]; + [winRec->window orderWindow:NSWindowBelow relativeTo:uppernum]; + } else { + [winRec->window orderFront:nil]; + } + + // fixme hide root for now + if (isRoot) [winRec->window orderOut:nil]; + + return winRec; +} + +void AquaDestroyWindow(void *rw) +{ + AquaWindowRec *winRec = WINREC(rw); + + [winRec->window release]; +} + +void AquaMoveWindow(void *rw, int x, int y) +{ + AquaWindowRec *winRec = WINREC(rw); + NSPoint topLeft = {x, y}; + + topLeft.y = [[NSScreen mainScreen] frame].size.height - topLeft.y; + [winRec->window setFrameTopLeftPoint:topLeft]; +} + +void AquaStartResizeWindow(void *rw, int x, int y, int w, int h) +{ + AquaWindowRec *winRec = WINREC(rw); + NSRect frame = {{x, y}, {w, h}}; + + frame.origin.y = [[NSScreen mainScreen] frame].size.height - y - h; + [winRec->window setFrame:frame display:NO]; +} + +void AquaFinishResizeWindow(void *rw, int x, int y, int w, int h) +{ + // refresh everything? fixme yes for testing + fakeBoxRec box = {0, 0, w, h}; + AquaWindowRec *winRec = WINREC(rw); + + [winRec->window refreshRects:&box count:1]; +} + +void AquaUpdateRects(void *rw, fakeBoxRec *rects, int count) +{ + AquaWindowRec *winRec = WINREC(rw); + + [winRec->window refreshRects:rects count:count]; +} + +// fixme is this upperw or lowerw? +void AquaRestackWindow(void *rw, void *upperw) +{ + AquaWindowRec *winRec = WINREC(rw); + + if (upperw) { + AquaWindowRec *upperRec = WINREC(upperw); + int uppernum = [upperRec->window windowNumber]; + [winRec->window orderWindow:NSWindowBelow relativeTo:uppernum]; + } else { + [winRec->window orderFront:nil]; + } + // [winRec->window setAcceptsMouseMovedEvents:YES]; + // fixme prefer to orderFront whenever possible - pass upperw, not lowerw +} + +void AquaReshapeWindow(void *rw, fakeBoxRec *rects, int count) +{ + // fixme reimplement shape +} + +void AquaGetPixmap(void *rw, char **bits, + int *rowBytes, int *depth, int *bpp) +{ + AquaWindowRec *winRec = WINREC(rw); + [winRec->window getBits:bits rowBytes:rowBytes depth:depth + bitsPerPixel:bpp]; +} diff --git a/xc/programs/Xserver/hw/darwin/bundle/rootlessCommon.c b/xc/programs/Xserver/hw/darwin/bundle/rootlessCommon.c new file mode 100644 index 000000000..69d8c97a3 --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/bundle/rootlessCommon.c @@ -0,0 +1,191 @@ +/* + * Common rootless definitions and code + * + * Greg Parker gparker@cs.stanford.edu + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/bundle/rootlessCommon.c,v 1.2 2001/07/01 03:24:57 torrey Exp $ */ + +#include "rootlessCommon.h" + + +RegionRec rootlessHugeRoot = {{-32767, -32767, 32767, 32767}, NULL}; + + +// Returns the top-level parent of pWindow. +// The root is the top-level parent of itself, even though the root is +// not otherwise considered to be a top-level window. +WindowPtr TopLevelParent(WindowPtr pWindow) +{ + WindowPtr top = pWindow; + + if (IsRoot(pWindow)) return pWindow; // root is top-level parent of itself + while (top && ! IsTopLevel(top)) top = top->parent; + return top; +} + + +// Returns TRUE if this window is visible inside a frame +// (e.g. it is visible and has a top-level or root parent) +Bool IsFramedWindow(WindowPtr pWin) +{ + WindowPtr top; + + if (! pWin->realized) return FALSE; + top = TopLevelParent(pWin); + return (top && WINREC(top)); +} + + +// Move the given pixmap's base address to where pixel (0, 0) +// would be if the pixmap's actual data started at (x, y) +void SetPixmapBaseToScreen(PixmapPtr pix, int x, int y) +{ + pix->devPrivate.ptr = (char *)(pix->devPrivate.ptr) - + (pix->drawable.bitsPerPixel/8 * x + y*pix->devKind); +} + + +// Update pWindow's pixmap. +// This needs to be called every time a window moves relative to +// its top-level parent, or the parent's pixmap data is reallocated. +// Three cases: +// * window is top-level with no existing pixmap: make one +// * window is top-level with existing pixmap: update it in place +// * window is descendant of top-level: point to top-level's pixmap +void UpdatePixmap(WindowPtr pWindow) +{ + WindowPtr top = TopLevelParent(pWindow); + RootlessWindowRec *winRec; + ScreenPtr pScreen = pWindow->drawable.pScreen; + PixmapPtr pix; + + RL_DEBUG_MSG("update pixmap (win 0x%x)", pWindow); + + // Don't use IsFramedWindow(); window is unrealized during RealizeWindow(). + + if (! top) { + RL_DEBUG_MSG("no parent\n"); + return; + } + winRec = WINREC(top); + if (!winRec) { + RL_DEBUG_MSG("not framed\n"); + return; + } + + if (pWindow == top) { + // This is the top window. Update its pixmap. + if (winRec->pixmap == NULL) { + // Allocate a new pixmap. + pix = GetScratchPixmapHeader(pScreen, + winRec->frame.w, winRec->frame.h, + winRec->frame.depth, + winRec->frame.bitsPerPixel, + winRec->frame.bytesPerRow, + winRec->frame.pixelData); + SetPixmapBaseToScreen(pix, winRec->frame.x, winRec->frame.y); + pScreen->SetWindowPixmap(pWindow, pix); + winRec->pixmap = pix; + } else { + // Update existing pixmap. + // Update in place so we don't have to change the children's pixmaps. + pix = winRec->pixmap; + pScreen->ModifyPixmapHeader(pix, + winRec->frame.w, winRec->frame.h, + winRec->frame.depth, + winRec->frame.bitsPerPixel, + winRec->frame.bytesPerRow, + winRec->frame.pixelData); + SetPixmapBaseToScreen(pix, winRec->frame.x, winRec->frame.y); + } + } else { + // This is not the top window. Point to the parent's pixmap. + pix = winRec->pixmap; + pScreen->SetWindowPixmap(pWindow, pix); + } + + RL_DEBUG_MSG("done\n"); +} + + +// pRegion is GLOBAL +void +RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion) +{ + pWindow = TopLevelParent(pWindow); + if (!pWindow) { + RL_DEBUG_MSG("RootlessDamageRegion: window is not framed\n"); + } else if (!WINREC(pWindow)) { + RL_DEBUG_MSG("RootlessDamageRegion: top-level window not a frame\n"); + } else { + REGION_UNION((pWindow)->drawable.pScreen, &WINREC(pWindow)->damage, + &WINREC(pWindow)->damage, (pRegion)); + } +} + + +// pBox is GLOBAL +void +RootlessDamageBox(WindowPtr pWindow, BoxPtr pBox) +{ + RegionRec region; + + REGION_INIT(pWindow->drawable.pScreen, ®ion, pBox, 1); + RootlessDamageRegion(pWindow, ®ion); +} + + +// (x, y, w, h) is WINDOW-LOCAL +void +RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h) +{ + BoxRec box; + RegionRec region; + + x += pWindow->drawable.x; + y += pWindow->drawable.y; + box.x1 = x; + box.x2 = x + w; + box.y1 = y; + box.y2 = y + h; + REGION_INIT(pWindow->drawable.pScreen, ®ion, &box, 1); + RootlessDamageRegion(pWindow, ®ion); +} + + +void +RootlessRedisplay(WindowPtr pWindow) +{ + RootlessWindowRec *winRec = WINREC(pWindow); + ScreenPtr pScreen = pWindow->drawable.pScreen; + + if (REGION_NOTEMPTY(pScreen, &winRec->damage)) { + REGION_INTERSECT(pScreen, &winRec->damage, &winRec->damage, + &pWindow->borderSize); + + // move region to window local coords + REGION_TRANSLATE(pScreen, &winRec->damage, + -winRec->frame.x, -winRec->frame.y); + CallFrameProc(pScreen, UpdateRegion, + (pScreen, &winRec->frame, &winRec->damage)); + REGION_EMPTY(pScreen, &winRec->damage); + } +} + + +void +RootlessRedisplayScreen(ScreenPtr pScreen) +{ + WindowPtr root = WindowTable[pScreen->myNum]; + + if (root) { + WindowPtr win; + + RootlessRedisplay(root); + for (win = root->firstChild; win; win = win->nextSib) { + if (WINREC(win)) { + RootlessRedisplay(win); + } + } + } +} diff --git a/xc/programs/Xserver/hw/darwin/bundle/rootlessCommon.h b/xc/programs/Xserver/hw/darwin/bundle/rootlessCommon.h new file mode 100644 index 000000000..de5c65b57 --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/bundle/rootlessCommon.h @@ -0,0 +1,209 @@ +/* + * Common internal rootless definitions and code + * + * Greg Parker gparker@cs.stanford.edu + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/bundle/rootlessCommon.h,v 1.2 2001/07/01 03:24:57 torrey Exp $ */ + +#ifndef _ROOTLESSCOMMON_H +#define _ROOTLESSCOMMON_H + +#include "rootless.h" + +#include "pixmapstr.h" +#include "windowstr.h" + +#ifdef RENDER +#include "picturestr.h" +#endif + + +// Debug output, or not. + +#ifdef ROOTLESSDEBUG +#define RL_DEBUG_MSG ErrorF +#else +#define RL_DEBUG_MSG(a, ...) +#endif + + +// Global variables +extern int rootlessGCPrivateIndex; +extern int rootlessScreenPrivateIndex; +extern int rootlessWindowPrivateIndex; + + +// RootlessGCRec: private per-gc data +typedef struct { + GCFuncs *originalFuncs; + GCOps *originalOps; +} RootlessGCRec; + + +// RootlessWindowRec: private per-window data +typedef struct RootlessWindowRec { + RootlessFrameRec frame; + RegionRec damage; + unsigned int borderWidth; // needed for MoveWindow(VTOther) (%$#@!!!) + PixmapPtr pixmap; +} RootlessWindowRec; + + +// RootlessScreenRec: per-screen private data +typedef struct { + ScreenPtr pScreen; + RootlessFrameProcs frameProcs; + + CloseScreenProcPtr CloseScreen; + + CreateWindowProcPtr CreateWindow; + DestroyWindowProcPtr DestroyWindow; + RealizeWindowProcPtr RealizeWindow; + UnrealizeWindowProcPtr UnrealizeWindow; + MoveWindowProcPtr MoveWindow; + ResizeWindowProcPtr ResizeWindow; + RestackWindowProcPtr RestackWindow; + ChangeBorderWidthProcPtr ChangeBorderWidth; + PositionWindowProcPtr PositionWindow; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + + CreateGCProcPtr CreateGC; + PaintWindowBackgroundProcPtr PaintWindowBackground; + PaintWindowBorderProcPtr PaintWindowBorder; + CopyWindowProcPtr CopyWindow; + GetImageProcPtr GetImage; + + MarkOverlappedWindowsProcPtr MarkOverlappedWindows; + ValidateTreeProcPtr ValidateTree; + +#ifdef SHAPE + SetShapeProcPtr SetShape; +#endif + +#ifdef RENDER + CompositeProcPtr Composite; + GlyphsProcPtr Glyphs; +#endif + +} RootlessScreenRec; + + +// "Definition of the Porting Layer for the X11 Sample Server" says +// unwrap and rewrap of screen functions is unnecessary, but +// screen->CreateGC changes after a call to cfbCreateGC. + +#define SCREEN_UNWRAP(screen, fn) \ + screen->fn = SCREENREC(screen)->fn; + +#define SCREEN_WRAP(screen, fn) \ + SCREENREC(screen)->fn = screen->fn; \ + screen->fn = Rootless##fn + + +// Accessors for screen and window privates + +#define SCREENREC(pScreen) \ + ((RootlessScreenRec*)(pScreen)->devPrivates[rootlessScreenPrivateIndex].ptr) + +#define WINREC(pWin) \ + ((RootlessWindowRec *)(pWin)->devPrivates[rootlessWindowPrivateIndex].ptr) + + +// Call a rootless implementation function. +// Many rootless implementation functions are allowed to be NULL. +#define CallFrameProc(pScreen, proc, params) \ + if (SCREENREC(pScreen)->frameProcs.proc) { \ + RL_DEBUG_MSG("calling frame proc " #proc " "); \ + SCREENREC(pScreen)->frameProcs.proc params; \ + } + + +// BoxRec manipulators +// Copied from shadowfb + +#define TRIM_BOX(box, pGC) { \ + BoxPtr extents = &pGC->pCompositeClip->extents;\ + if(box.x1 < extents->x1) box.x1 = extents->x1; \ + if(box.x2 > extents->x2) box.x2 = extents->x2; \ + if(box.y1 < extents->y1) box.y1 = extents->y1; \ + if(box.y2 > extents->y2) box.y2 = extents->y2; \ +} + +#define TRANSLATE_BOX(box, pDraw) { \ + box.x1 += pDraw->x; \ + box.x2 += pDraw->x; \ + box.y1 += pDraw->y; \ + box.y2 += pDraw->y; \ +} + +#define TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC) { \ + TRANSLATE_BOX(box, pDraw); \ + TRIM_BOX(box, pGC); \ +} + +#define BOX_NOT_EMPTY(box) \ + (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0)) + + +// HUGE_ROOT and NORMAL_ROOT +// We don't want to clip windows to the edge of the screen. +// HUGE_ROOT temporarily makes the root window really big. +// This is needed as a wrapper around any function that calls +// SetWinSize or SetBorderSize which clip a window against its +// parents, including the root. + +extern RegionRec rootlessHugeRoot; + +#define HUGE_ROOT(pWin) \ + { \ + WindowPtr w = pWin; \ + while (w->parent) w = w->parent; \ + saveRoot = w->winSize; \ + w->winSize = rootlessHugeRoot; \ + } + +#define NORMAL_ROOT(pWin) \ + { \ + WindowPtr w = pWin; \ + while (w->parent) w = w->parent; \ + w->winSize = saveRoot; \ + } + + +// Returns TRUE if this window is a top-level window (i.e. child of the root) +// The root is not a top-level window. +#define IsTopLevel(pWin) \ + ((pWin) && (pWin)->parent && !(pWin)->parent->parent) + +// Returns TRUE if this window is a root window +#define IsRoot(pWin) \ + ((pWin) == WindowTable[(pWin)->drawable.pScreen->myNum]) + +// Returns the top-level parent of pWindow. +// The root is the top-level parent of itself, even though the root is +// not otherwise considered to be a top-level window. +WindowPtr TopLevelParent(WindowPtr pWindow); + +// Returns TRUE if this window is visible inside a frame +// (e.g. it is visible and has a top-level or root parent) +Bool IsFramedWindow(WindowPtr pWin); + +// Move the given pixmap's base address to where pixel (0, 0) +// would be if the pixmap's actual data started at (x, y) +void SetPixmapBaseToScreen(PixmapPtr pix, int x, int y); + +// Update pWindow's pixmap. +// This needs to be called every time a window moves relative to +// its top-level parent, or the parent's pixmap data is reallocated. +void UpdatePixmap(WindowPtr pWindow); + +// Routines that cause regions to get redrawn. +// DamageRegion and DamageRect are GLOBAL coords +// DamageBox is WINDOW-LOCAL coords +void RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion); +void RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h); +void RootlessDamageBox(WindowPtr pWindow, BoxPtr pBox); +void RootlessRedisplay(WindowPtr pWindow); +void RootlessRedisplayScreen(ScreenPtr pScreen); + +#endif // _ROOTLESSCOMMON_H diff --git a/xc/programs/Xserver/hw/darwin/bundle/rootlessGC.c b/xc/programs/Xserver/hw/darwin/bundle/rootlessGC.c new file mode 100644 index 000000000..a82118b23 --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/bundle/rootlessGC.c @@ -0,0 +1,1170 @@ +/* + * Graphics Context support for Mac OS X rootless X server + * + * Greg Parker gparker@cs.stanford.edu + * + * February 2001 Created + * March 3, 2001 Restructured as generic rootless mode + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/bundle/rootlessGC.c,v 1.3 2001/07/01 03:24:57 torrey Exp $ */ + +#include "mi.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "dixfontstr.h" +#include "mivalidate.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "rootlessCommon.h" + + +// GC functions +static void RootlessValidateGC(GCPtr pGC, unsigned long changes, + DrawablePtr pDrawable); +static void RootlessChangeGC(GCPtr pGC, unsigned long mask); +static void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); +static void RootlessDestroyGC(GCPtr pGC); +static void RootlessChangeClip(GCPtr pGC, int type, pointer pvalue, + int nrects); +static void RootlessDestroyClip(GCPtr pGC); +static void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc); + +GCFuncs rootlessGCFuncs = { + RootlessValidateGC, + RootlessChangeGC, + RootlessCopyGC, + RootlessDestroyGC, + RootlessChangeClip, + RootlessDestroyClip, + RootlessCopyClip, +}; + +// GC operations +static void RootlessFillSpans(); +static void RootlessSetSpans(); +static void RootlessPutImage(); +static RegionPtr RootlessCopyArea(); +static RegionPtr RootlessCopyPlane(); +static void RootlessPolyPoint(); +static void RootlessPolylines(); +static void RootlessPolySegment(); +static void RootlessPolyRectangle(); +static void RootlessPolyArc(); +static void RootlessFillPolygon(); +static void RootlessPolyFillRect(); +static void RootlessPolyFillArc(); +static int RootlessPolyText8(); +static int RootlessPolyText16(); +static void RootlessImageText8(); +static void RootlessImageText16(); +static void RootlessImageGlyphBlt(); +static void RootlessPolyGlyphBlt(); +static void RootlessPushPixels(); + +static GCOps rootlessGCOps = { + RootlessFillSpans, + RootlessSetSpans, + RootlessPutImage, + RootlessCopyArea, + RootlessCopyPlane, + RootlessPolyPoint, + RootlessPolylines, + RootlessPolySegment, + RootlessPolyRectangle, + RootlessPolyArc, + RootlessFillPolygon, + RootlessPolyFillRect, + RootlessPolyFillArc, + RootlessPolyText8, + RootlessPolyText16, + RootlessImageText8, + RootlessImageText16, + RootlessImageGlyphBlt, + RootlessPolyGlyphBlt, + RootlessPushPixels +#ifdef NEED_LINEHELPER + , NULL +#endif +}; + + +Bool +RootlessCreateGC(GCPtr pGC) +{ + RootlessGCRec *gcrec; + RootlessScreenRec *s; + Bool result; + + SCREEN_UNWRAP(pGC->pScreen, CreateGC); + s = (RootlessScreenRec *) pGC->pScreen-> + devPrivates[rootlessScreenPrivateIndex].ptr; + result = s->CreateGC(pGC); + gcrec = (RootlessGCRec *) pGC->devPrivates[rootlessGCPrivateIndex].ptr; + gcrec->originalOps = NULL; // don't wrap ops yet + gcrec->originalFuncs = pGC->funcs; + pGC->funcs = &rootlessGCFuncs; + + SCREEN_WRAP(pGC->pScreen, CreateGC); + return result; +} + + +// GC func wrapping +// ValidateGC wraps gcOps iff dest is viewable. All others just unwrap&call. + +// GCFUN_UNRAP assumes funcs have been wrapped and +// does not assume ops have been wrapped +#define GCFUNC_UNWRAP(pGC) \ + RootlessGCRec *gcrec = (RootlessGCRec *) \ + (pGC)->devPrivates[rootlessGCPrivateIndex].ptr; \ + (pGC)->funcs = gcrec->originalFuncs; \ + if (gcrec->originalOps) { \ + (pGC)->ops = gcrec->originalOps; \ +} + +#define GCFUNC_WRAP(pGC) \ + gcrec->originalFuncs = (pGC)->funcs; \ + (pGC)->funcs = &rootlessGCFuncs; \ + if (gcrec->originalOps) { \ + gcrec->originalOps = (pGC)->ops; \ + (pGC)->ops = &rootlessGCOps; \ +} + + +static void +RootlessValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) +{ + GCFUNC_UNWRAP(pGC); + + pGC->funcs->ValidateGC(pGC, changes, pDrawable); + + gcrec->originalOps = NULL; + + if (pDrawable->type == DRAWABLE_WINDOW) { + WindowPtr pWin = (WindowPtr) pDrawable; + + if (pWin->viewable) { + gcrec->originalOps = pGC->ops; + } + } + + GCFUNC_WRAP(pGC); +} + +static void RootlessChangeGC(GCPtr pGC, unsigned long mask) +{ + GCFUNC_UNWRAP(pGC); + pGC->funcs->ChangeGC(pGC, mask); + GCFUNC_WRAP(pGC); +} + +static void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) +{ + GCFUNC_UNWRAP(pGCDst); + pGCDst->funcs->CopyGC(pGCSrc, mask, pGCDst); + GCFUNC_WRAP(pGCDst); +} + +static void RootlessDestroyGC(GCPtr pGC) +{ + GCFUNC_UNWRAP(pGC); + pGC->funcs->DestroyGC(pGC); + GCFUNC_WRAP(pGC); +} + +static void RootlessChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects) +{ + GCFUNC_UNWRAP(pGC); + pGC->funcs->ChangeClip(pGC, type, pvalue, nrects); + GCFUNC_WRAP(pGC); +} + +static void RootlessDestroyClip(GCPtr pGC) +{ + GCFUNC_UNWRAP(pGC); + pGC->funcs->DestroyClip(pGC); + GCFUNC_WRAP(pGC); +} + +static void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc) +{ + GCFUNC_UNWRAP(pgcDst); + pgcDst->funcs->CopyClip(pgcDst, pgcSrc); + GCFUNC_WRAP(pgcDst); +} + + +// GC ops +// We can't use shadowfb because shadowfb assumes one pixmap +// and our root window is a special case. +// So much of this code is copied from shadowfb. + +// assumes both funcs and ops are wrapped +#define GCOP_UNWRAP(pGC) \ + RootlessGCRec *gcrec = (RootlessGCRec *) \ + (pGC)->devPrivates[rootlessGCPrivateIndex].ptr; \ + GCFuncs *saveFuncs = pGC->funcs; \ + (pGC)->funcs = gcrec->originalFuncs; \ + (pGC)->ops = gcrec->originalOps; + +#define GCOP_WRAP(pGC) \ + gcrec->originalOps = (pGC)->ops; \ + (pGC)->funcs = saveFuncs; \ + (pGC)->ops = &rootlessGCOps; + + +static void +RootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit, + DDXPointPtr pptInit, int *pwidthInit, int sorted) +{ + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("fill spans start "); + + if (nInit <= 0) { + pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted); + } else { + DDXPointPtr ppt = pptInit; + int *pwidth = pwidthInit; + int i = nInit; + BoxRec box; + + box.x1 = ppt->x; + box.x2 = box.x1 + *pwidth; + box.y2 = box.y1 = ppt->y; + + while(--i) { + ppt++; + pwidthInit++; + if(box.x1 > ppt->x) + box.x1 = ppt->x; + if(box.x2 < (ppt->x + *pwidth)) + box.x2 = ppt->x + *pwidth; + if(box.y1 > ppt->y) + box.y1 = ppt->y; + else if(box.y2 < ppt->y) + box.y2 = ppt->y; + } + + box.y2++; + + pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted); + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("fill spans end\n"); +} + +static void +RootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc, + DDXPointPtr pptInit, int *pwidthInit, + int nspans, int sorted) +{ + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("set spans start "); + + if (nspans <= 0) { + pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, + nspans, sorted); + } else { + DDXPointPtr ppt = pptInit; + int *pwidth = pwidthInit; + int i = nspans; + BoxRec box; + + box.x1 = ppt->x; + box.x2 = box.x1 + *pwidth; + box.y2 = box.y1 = ppt->y; + + while(--i) { + ppt++; + pwidth++; + if(box.x1 > ppt->x) + box.x1 = ppt->x; + if(box.x2 < (ppt->x + *pwidth)) + box.x2 = ppt->x + *pwidth; + if(box.y1 > ppt->y) + box.y1 = ppt->y; + else if(box.y2 < ppt->y) + box.y2 = ppt->y; + } + + box.y2++; + + pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, + nspans, sorted); + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + } + GCOP_WRAP(pGC); + RL_DEBUG_MSG("set spans end\n"); +} + +static void +RootlessPutImage(DrawablePtr dst, GCPtr pGC, + int depth, int x, int y, int w, int h, + int leftPad, int format, char *pBits) +{ + BoxRec box; + + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("put image start "); + + pGC->ops->PutImage(dst, pGC, depth, x,y,w,h, leftPad, format, pBits); + + box.x1 = x + dst->x; + box.x2 = box.x1 + w; + box.y1 = y + dst->y; + box.y2 = box.y1 + h; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("put image end\n"); +} + +/* changed area is *dest* rect */ +/* If this code ever goes back go StartDrawing/StopDrawing: + * start and stop dst always + * start and stop src if src->type is DRAWABLE_WINDOW and src is framed + */ +static RegionPtr +RootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC, + int srcx, int srcy, int w, int h, + int dstx, int dsty) +{ + RegionPtr result; + BoxRec box; + + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("copy area start (src 0x%x, dst 0x%x)", pSrc, dst); + + result = pGC->ops->CopyArea(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty); + + box.x1 = dstx + dst->x; + box.x2 = box.x1 + w; + box.y1 = dsty + dst->y; + box.y2 = box.y1 + h; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("copy area end\n"); + return result; +} + +/* changed area is *dest* rect */ +/* If this code ever goes back go StartDrawing/StopDrawing: + * start and stop dst always + * start and stop src if src->type is DRAWABLE_WINDOW and src is framed + */ +static RegionPtr RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst, + GCPtr pGC, int srcx, int srcy, + int w, int h, int dstx, int dsty, + unsigned long plane) +{ + RegionPtr result; + BoxRec box; + + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("copy plane start "); + + result = pGC->ops->CopyPlane(pSrc, dst, pGC, srcx, srcy, w, h, + dstx, dsty, plane); + + box.x1 = dstx + dst->x; + box.x2 = box.x1 + w; + box.y1 = dsty + dst->y; + box.y2 = box.y1 + h; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("copy plane end\n"); + return result; +} + +// Options for size of changed area: +// 0 = box per point +// 1 = big box around all points +// 2 = accumulate point in 20 pixel radius +#define ROOTLESS_CHANGED_AREA 1 +#define abs(a) ((a) > 0 ? (a) : -(a)) + +/* changed area is box around all points */ +static void RootlessPolyPoint(DrawablePtr dst, GCPtr pGC, + int mode, int npt, DDXPointPtr pptInit) +{ + GCOP_UNWRAP(pGC); + + RL_DEBUG_MSG("polypoint start "); + + pGC->ops->PolyPoint(dst, pGC, mode, npt, pptInit); + + if (npt > 0) { +#if ROOTLESS_CHANGED_AREA==0 + // box per point + BoxRec box; + + while (npt) { + box.x1 = pptInit->x; + box.y1 = pptInit->y; + box.x2 = box.x1 + 1; + box.y2 = box.y1 + 1; + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + + npt--; + pptInit++; + } + +#elif ROOTLESS_CHANGED_AREA==1 + // one big box + BoxRec box; + + box.x2 = box.x1 = pptInit->x; + box.y2 = box.y1 = pptInit->y; + while(--npt) { + pptInit++; + if(box.x1 > pptInit->x) + box.x1 = pptInit->x; + else if(box.x2 < pptInit->x) + box.x2 = pptInit->x; + if(box.y1 > pptInit->y) + box.y1 = pptInit->y; + else if(box.y2 < pptInit->y) + box.y2 = pptInit->y; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + +#elif ROOTLESS_CHANGED_AREA==2 + // clever(?) method: accumulate point in 20-pixel radius + BoxRec box; + int firstx, firsty; + + box.x2 = box.x1 = firstx = pptInit->x; + box.y2 = box.y1 = firsty = pptInit->y; + while(--npt) { + pptInit++; + if (abs(pptInit->x - firstx) > 20 || + abs(pptInit->y - firsty) > 20) { + box.x2++; + box.y2++; + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + box.x2 = box.x1 = firstx = pptInit->x; + box.y2 = box.y1 = firsty = pptInit->y; + } else { + if (box.x1 > pptInit->x) box.x1 = pptInit->x; + else if (box.x2 < pptInit->x) box.x2 = pptInit->x; + if (box.y1 > pptInit->y) box.y1 = pptInit->y; + else if (box.y2 < pptInit->y) box.y2 = pptInit->y; + } + } + box.x2++; + box.y2++; + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); +#endif /* ROOTLESS_CHANGED_AREA */ + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("polypoint end\n"); +} + +#undef ROOTLESS_CHANGED_AREA + +/* changed area is box around each line */ +static void RootlessPolylines(DrawablePtr dst, GCPtr pGC, + int mode, int npt, DDXPointPtr pptInit) +{ + GCOP_UNWRAP(pGC); + + RL_DEBUG_MSG("poly lines start "); + + pGC->ops->Polylines(dst, pGC, mode, npt, pptInit); + + if (npt > 0) { + BoxRec box; + int extra = pGC->lineWidth >> 1; + + box.x2 = box.x1 = pptInit->x; + box.y2 = box.y1 = pptInit->y; + + if(npt > 1) { + if(pGC->joinStyle == JoinMiter) + extra = 6 * pGC->lineWidth; + else if(pGC->capStyle == CapProjecting) + extra = pGC->lineWidth; + } + + if(mode == CoordModePrevious) { + int x = box.x1; + int y = box.y1; + + while(--npt) { + pptInit++; + x += pptInit->x; + y += pptInit->y; + if(box.x1 > x) + box.x1 = x; + else if(box.x2 < x) + box.x2 = x; + if(box.y1 > y) + box.y1 = y; + else if(box.y2 < y) + box.y2 = y; + } + } else { + while(--npt) { + pptInit++; + if(box.x1 > pptInit->x) + box.x1 = pptInit->x; + else if(box.x2 < pptInit->x) + box.x2 = pptInit->x; + if(box.y1 > pptInit->y) + box.y1 = pptInit->y; + else if(box.y2 < pptInit->y) + box.y2 = pptInit->y; + } + } + + box.x2++; + box.y2++; + + if(extra) { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("poly lines end\n"); +} + +/* changed area is box around each line segment */ +static void RootlessPolySegment(DrawablePtr dst, GCPtr pGC, + int nseg, xSegment *pSeg) +{ + GCOP_UNWRAP(pGC); + + RL_DEBUG_MSG("poly segment start (win 0x%x)", dst); + + pGC->ops->PolySegment(dst, pGC, nseg, pSeg); + + if (nseg > 0) { + BoxRec box; + int extra = pGC->lineWidth; + + if(pGC->capStyle != CapProjecting) + extra >>= 1; + + if(pSeg->x2 > pSeg->x1) { + box.x1 = pSeg->x1; + box.x2 = pSeg->x2; + } else { + box.x2 = pSeg->x1; + box.x1 = pSeg->x2; + } + + if(pSeg->y2 > pSeg->y1) { + box.y1 = pSeg->y1; + box.y2 = pSeg->y2; + } else { + box.y2 = pSeg->y1; + box.y1 = pSeg->y2; + } + + while(--nseg) { + pSeg++; + if(pSeg->x2 > pSeg->x1) { + if(pSeg->x1 < box.x1) box.x1 = pSeg->x1; + if(pSeg->x2 > box.x2) box.x2 = pSeg->x2; + } else { + if(pSeg->x2 < box.x1) box.x1 = pSeg->x2; + if(pSeg->x1 > box.x2) box.x2 = pSeg->x1; + } + if(pSeg->y2 > pSeg->y1) { + if(pSeg->y1 < box.y1) box.y1 = pSeg->y1; + if(pSeg->y2 > box.y2) box.y2 = pSeg->y2; + } else { + if(pSeg->y2 < box.y1) box.y1 = pSeg->y2; + if(pSeg->y1 > box.y2) box.y2 = pSeg->y1; + } + } + + box.x2++; + box.y2++; + + if(extra) { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("poly segment end\n"); +} + +/* changed area is box around each line (not entire rects) */ +static void RootlessPolyRectangle(DrawablePtr dst, GCPtr pGC, + int nRects, xRectangle *pRects) +{ + GCOP_UNWRAP(pGC); + + RL_DEBUG_MSG("poly rectangle start "); + + pGC->ops->PolyRectangle(dst, pGC, nRects, pRects); + + if (nRects > 0) { + BoxRec box; + int offset1, offset2, offset3; + + offset2 = pGC->lineWidth; + if(!offset2) offset2 = 1; + offset1 = offset2 >> 1; + offset3 = offset2 - offset1; + + while(nRects--) { + box.x1 = pRects->x - offset1; + box.y1 = pRects->y - offset1; + box.x2 = box.x1 + pRects->width + offset2; + box.y2 = box.y1 + offset2; + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + + box.x1 = pRects->x - offset1; + box.y1 = pRects->y + offset3; + box.x2 = box.x1 + offset2; + box.y2 = box.y1 + pRects->height - offset2; + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + + box.x1 = pRects->x + pRects->width - offset1; + box.y1 = pRects->y + offset3; + box.x2 = box.x1 + offset2; + box.y2 = box.y1 + pRects->height - offset2; + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + + box.x1 = pRects->x - offset1; + box.y1 = pRects->y + pRects->height - offset1; + box.x2 = box.x1 + pRects->width + offset2; + box.y2 = box.y1 + offset2; + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + + pRects++; + } + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("poly rectangle end\n"); +} + + +/* changed area is box around each arc (assumes all arcs are 360 degrees) */ +static void RootlessPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc *parcs) +{ + GCOP_UNWRAP(pGC); + + RL_DEBUG_MSG("poly arc start "); + + pGC->ops->PolyArc(dst, pGC, narcs, parcs); + + if (narcs > 0) { + int extra = pGC->lineWidth >> 1; + BoxRec box; + + box.x1 = parcs->x; + box.x2 = box.x1 + parcs->width; + box.y1 = parcs->y; + box.y2 = box.y1 + parcs->height; + + /* should I break these up instead ? */ + + while(--narcs) { + parcs++; + if(box.x1 > parcs->x) + box.x1 = parcs->x; + if(box.x2 < (parcs->x + parcs->width)) + box.x2 = parcs->x + parcs->width; + if(box.y1 > parcs->y) + box.y1 = parcs->y; + if(box.y2 < (parcs->y + parcs->height)) + box.y2 = parcs->y + parcs->height; + } + + if(extra) { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("poly arc end\n"); +} + + +/* changed area is box around each poly */ +static void RootlessFillPolygon(DrawablePtr dst, GCPtr pGC, + int shape, int mode, int count, + DDXPointPtr pptInit) +{ + GCOP_UNWRAP(pGC); + + RL_DEBUG_MSG("fill poly start "); + + if (count <= 2) { + pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit); + } else { + DDXPointPtr ppt = pptInit; + int i = count; + BoxRec box; + + box.x2 = box.x1 = ppt->x; + box.y2 = box.y1 = ppt->y; + + if(mode != CoordModeOrigin) { + int x = box.x1; + int y = box.y1; + + while(--i) { + ppt++; + x += ppt->x; + y += ppt->y; + if(box.x1 > x) + box.x1 = x; + else if(box.x2 < x) + box.x2 = x; + if(box.y1 > y) + box.y1 = y; + else if(box.y2 < y) + box.y2 = y; + } + } else { + while(--i) { + ppt++; + if(box.x1 > ppt->x) + box.x1 = ppt->x; + else if(box.x2 < ppt->x) + box.x2 = ppt->x; + if(box.y1 > ppt->y) + box.y1 = ppt->y; + else if(box.y2 < ppt->y) + box.y2 = ppt->y; + } + } + + box.x2++; + box.y2++; + + pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit); + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("fill poly end\n"); +} + +/* changed area is the rects */ +static void RootlessPolyFillRect(DrawablePtr dst, GCPtr pGC, + int nRectsInit, xRectangle *pRectsInit) +{ + GCOP_UNWRAP(pGC); + + RL_DEBUG_MSG("fill rect start (win 0x%x)", dst); + + if (nRectsInit <= 0) { + pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit); + } else { + BoxRec box; + xRectangle *pRects = pRectsInit; + int nRects = nRectsInit; + + box.x1 = pRects->x; + box.x2 = box.x1 + pRects->width; + box.y1 = pRects->y; + box.y2 = box.y1 + pRects->height; + + while(--nRects) { + pRects++; + if(box.x1 > pRects->x) + box.x1 = pRects->x; + if(box.x2 < (pRects->x + pRects->width)) + box.x2 = pRects->x + pRects->width; + if(box.y1 > pRects->y) + box.y1 = pRects->y; + if(box.y2 < (pRects->y + pRects->height)) + box.y2 = pRects->y + pRects->height; + } + + /* cfb messes with the pRectsInit so we have to do our + calculations first */ + + pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit); + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("fill rect end\n"); +} + + +/* changed area is box around each arc (assuming arcs are all 360 degrees) */ +static void RootlessPolyFillArc(DrawablePtr dst, GCPtr pGC, + int narcs, xArc *parcs) +{ + GCOP_UNWRAP(pGC); + + RL_DEBUG_MSG("fill arc start "); + + pGC->ops->PolyFillArc(dst, pGC, narcs, parcs); + + if (narcs > 0) { + BoxRec box; + + box.x1 = parcs->x; + box.x2 = box.x1 + parcs->width; + box.y1 = parcs->y; + box.y2 = box.y1 + parcs->height; + + /* should I break these up instead ? */ + + while(--narcs) { + parcs++; + if(box.x1 > parcs->x) + box.x1 = parcs->x; + if(box.x2 < (parcs->x + parcs->width)) + box.x2 = parcs->x + parcs->width; + if(box.y1 > parcs->y) + box.y1 = parcs->y; + if(box.y2 < (parcs->y + parcs->height)) + box.y2 = parcs->y + parcs->height; + } + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("fill arc end"); +} + + +static void RootlessImageText8(DrawablePtr dst, GCPtr pGC, + int x, int y, int count, char *chars) +{ + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("imagetext8 start "); + + pGC->ops->ImageText8(dst, pGC, x, y, count, chars); + + if (count > 0) { + int top, bot, Min, Max; + BoxRec box; + + top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); + bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); + + Min = count * FONTMINBOUNDS(pGC->font, characterWidth); + if(Min > 0) Min = 0; + Max = count * FONTMAXBOUNDS(pGC->font, characterWidth); + if(Max < 0) Max = 0; + + /* ugh */ + box.x1 = dst->x + x + Min + + FONTMINBOUNDS(pGC->font, leftSideBearing); + box.x2 = dst->x + x + Max + + FONTMAXBOUNDS(pGC->font, rightSideBearing); + + box.y1 = dst->y + y - top; + box.y2 = dst->y + y + bot; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("imagetext8 end\n"); +} + +static int RootlessPolyText8(DrawablePtr dst, GCPtr pGC, + int x, int y, int count, char *chars) +{ + int width; // the result, sorta + + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("polytext8 start "); + + width = pGC->ops->PolyText8(dst, pGC, x, y, count, chars); + width -= x; + + if(width > 0) { + BoxRec box; + + /* ugh */ + box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing); + box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing); + + if(count > 1) { + if(width > 0) box.x2 += width; + else box.x1 += width; + } + + box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent); + box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent); + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("polytext8 end\n"); + return (width + x); +} + +static void RootlessImageText16(DrawablePtr dst, GCPtr pGC, + int x, int y, int count, unsigned short *chars) +{ + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("imagetext16 start "); + + pGC->ops->ImageText16(dst, pGC, x, y, count, chars); + + if (count > 0) { + int top, bot, Min, Max; + BoxRec box; + + top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); + bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); + + Min = count * FONTMINBOUNDS(pGC->font, characterWidth); + if(Min > 0) Min = 0; + Max = count * FONTMAXBOUNDS(pGC->font, characterWidth); + if(Max < 0) Max = 0; + + /* ugh */ + box.x1 = dst->x + x + Min + + FONTMINBOUNDS(pGC->font, leftSideBearing); + box.x2 = dst->x + x + Max + + FONTMAXBOUNDS(pGC->font, rightSideBearing); + + box.y1 = dst->y + y - top; + box.y2 = dst->y + y + bot; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("imagetext16 end\n"); +} + +static int RootlessPolyText16(DrawablePtr dst, GCPtr pGC, + int x, int y, int count, unsigned short *chars) +{ + int width; // the result, sorta + + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("polytext16 start "); + + width = pGC->ops->PolyText16(dst, pGC, x, y, count, chars); + width -= x; + + if (width > 0) { + BoxRec box; + + /* ugh */ + box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing); + box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing); + + if(count > 1) { + if(width > 0) box.x2 += width; + else box.x1 += width; + } + + box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent); + box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent); + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("polytext16 end\n"); + return width + x; +} + +static void RootlessImageGlyphBlt(DrawablePtr dst, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr *ppci, pointer unused) +{ + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("imageglyph start "); + + pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyph, ppci, unused); + + if (nglyph > 0) { + int top, bot, width = 0; + BoxRec box; + + top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); + bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); + + box.x1 = ppci[0]->metrics.leftSideBearing; + if(box.x1 > 0) box.x1 = 0; + box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing - + ppci[nglyph - 1]->metrics.characterWidth; + if(box.x2 < 0) box.x2 = 0; + + box.x2 += dst->x + x; + box.x1 += dst->x + x; + + while(nglyph--) { + width += (*ppci)->metrics.characterWidth; + ppci++; + } + + if(width > 0) + box.x2 += width; + else + box.x1 += width; + + box.y1 = dst->y + y - top; + box.y2 = dst->y + y + bot; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("imageglyph end\n"); +} + +static void RootlessPolyGlyphBlt(DrawablePtr dst, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr *ppci, pointer pglyphBase) +{ + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("polyglyph start "); + + pGC->ops->PolyGlyphBlt(dst, pGC, x, y, nglyph, ppci, pglyphBase); + + if (nglyph > 0) { + BoxRec box; + + /* ugh */ + box.x1 = dst->x + x + ppci[0]->metrics.leftSideBearing; + box.x2 = dst->x + x + ppci[nglyph - 1]->metrics.rightSideBearing; + + if(nglyph > 1) { + int width = 0; + + while(--nglyph) { + width += (*ppci)->metrics.characterWidth; + ppci++; + } + + if(width > 0) box.x2 += width; + else box.x1 += width; + } + + box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent); + box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent); + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("polyglyph end\n"); +} + + +/* changed area is in dest */ +static void +RootlessPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst, + int dx, int dy, int xOrg, int yOrg) +{ + BoxRec box; + GCOP_UNWRAP(pGC); + + pGC->ops->PushPixels(pGC, pBitMap, dst, dx, dy, xOrg, yOrg); + + box.x1 = xOrg + dst->x; + box.x2 = box.x1 + dx; + box.y1 = yOrg + dst->y; + box.y2 = box.y1 + dy; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + RootlessDamageBox ((WindowPtr) dst, &box); + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("push pixels end\n"); +} diff --git a/xc/programs/Xserver/hw/darwin/bundle/rootlessScreen.c b/xc/programs/Xserver/hw/darwin/bundle/rootlessScreen.c new file mode 100644 index 000000000..cbbccb9ce --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/bundle/rootlessScreen.c @@ -0,0 +1,430 @@ +/* + * Screen routines for Mac OS X rootless X server + * + * Greg Parker gparker@cs.stanford.edu + * + * February 2001 Created + * March 3, 2001 Restructured as generic rootless mode + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/bundle/rootlessScreen.c,v 1.2 2001/07/01 02:13:41 torrey Exp $ */ + + +#include "mi.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "propertyst.h" +#include "mivalidate.h" +#include "picturestr.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "rootlessCommon.h" +#include "rootlessWindow.h" + +extern int +rootlessMiValidateTree(WindowPtr pRoot, WindowPtr pChild, VTKind kind); +extern Bool +RootlessCreateGC(GCPtr pGC); + +// Initialize globals +int rootlessGCPrivateIndex = -1; +int rootlessScreenPrivateIndex = -1; +int rootlessWindowPrivateIndex = -1; + + +static Bool +RootlessCloseScreen(int i, ScreenPtr pScreen) +{ + RootlessScreenRec *s; + + s = SCREENREC(pScreen); + + // fixme unwrap everything that was wrapped? + pScreen->CloseScreen = s->CloseScreen; + + xfree(s); + return pScreen->CloseScreen(i, pScreen); +} + + +static void +RootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, + unsigned int format, unsigned long planeMask, char *pdstLine) +{ + ScreenPtr pScreen = pDrawable->pScreen; + SCREEN_UNWRAP(pScreen, GetImage); + + if (pDrawable->type == DRAWABLE_WINDOW) { + /* Many apps use GetImage to sync with the visible frame buffer */ + // fixme entire screen or just window or all screens? + RootlessRedisplayScreen(pScreen); + } + pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); + SCREEN_WRAP(pScreen, GetImage); +} + + +#ifdef RENDER + +static void +RootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, + INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + WindowPtr srcWin, maskWin, dstWin; + + srcWin = (pSrc->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr)pSrc->pDrawable : NULL; + maskWin = (pMask->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr)pMask->pDrawable : NULL; + dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr)pDst->pDrawable : NULL; + + // SCREEN_UNWRAP(ps, Composite); + ps->Composite = SCREENREC(pScreen)->Composite; + + ps->Composite(op, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, + xDst, yDst, width, height); + + if (dstWin && IsFramedWindow(dstWin)) { + RootlessDamageRect(dstWin, xDst, yDst, width, height); + } + + ps->Composite = RootlessComposite; + // SCREEN_WRAP(ps, Composite); +} + + +static void +RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int nlist, GlyphListPtr list, GlyphPtr *glyphs) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + int x, y; + int n; + GlyphPtr glyph; + WindowPtr srcWin, dstWin; + + srcWin = (pSrc->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr)pSrc->pDrawable : NULL; + dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr)pDst->pDrawable : NULL; + + //SCREEN_UNWRAP(ps, Glyphs); + ps->Glyphs = SCREENREC(pScreen)->Glyphs; + ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + ps->Glyphs = RootlessGlyphs; + //SCREEN_WRAP(ps, Glyphs); + + if (dstWin && IsFramedWindow(dstWin)) { + x = xSrc; + y = ySrc; + while (nlist--) { + x += list->xOff; + y += list->yOff; + n = list->len; + while (n--) { + glyph = *glyphs++; + RootlessDamageRect(dstWin, + x - glyph->info.x, y - glyph->info.y, + glyph->info.width, glyph->info.height); + x += glyph->info.xOff; + y += glyph->info.yOff; + } + list++; + } + } +} + +#endif // RENDER + + +// RootlessValidateTree +// ValidateTree is modified in two ways: +// * top-level windows don't clip each other +// * windows aren't clipped against root. +// These only matter when validating from the root. +static int +RootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) +{ + int result; + RegionRec saveRoot; + ScreenPtr pScreen = pParent->drawable.pScreen; + + SCREEN_UNWRAP(pScreen, ValidateTree); + RL_DEBUG_MSG("VALIDATETREE start "); + + // Use our custom version to validate from root + if (IsRoot(pParent)) { + RL_DEBUG_MSG("custom "); + result = rootlessMiValidateTree(pParent, pChild, kind); + } else { + HUGE_ROOT(pParent); + result = pScreen->ValidateTree(pParent, pChild, kind); + NORMAL_ROOT(pParent); + } + + SCREEN_WRAP(pScreen, ValidateTree); + RL_DEBUG_MSG("VALIDATETREE end\n"); + + return result; +} + + +// RootlessMarkOverlappedWindows +// MarkOverlappedWindows is modified to ignore overlapping +// top-level windows. +static Bool +RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, + WindowPtr *ppLayerWin) +{ + RegionRec saveRoot; + Bool result; + ScreenPtr pScreen = pWin->drawable.pScreen; + SCREEN_UNWRAP(pScreen, MarkOverlappedWindows); + RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start "); + + HUGE_ROOT(pWin); + if (IsRoot(pWin)) { + // root - mark nothing + RL_DEBUG_MSG("is root not marking "); + result = FALSE; + } + else if (! IsTopLevel(pWin)) { + // not top-level window - mark normally + result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin); + } + else { + //top-level window - mark children ONLY - NO overlaps with sibs (?) + // This code copied from miMarkOverlappedWindows() + + register WindowPtr pChild; + Bool anyMarked = FALSE; + void (* MarkWindow)() = pScreen->MarkWindow; + + RL_DEBUG_MSG("is top level! "); + /* single layered systems are easy */ + if (ppLayerWin) *ppLayerWin = pWin; + + if (pWin == pFirst) { + /* Blindly mark pWin and all of its inferiors. This is a slight + * overkill if there are mapped windows that outside pWin's border, + * but it's better than wasting time on RectIn checks. + */ + pChild = pWin; + while (1) { + if (pChild->viewable) { + if (REGION_BROKEN (pScreen, &pChild->winSize)) + SetWinSize (pChild); + if (REGION_BROKEN (pScreen, &pChild->borderSize)) + SetBorderSize (pChild); + (* MarkWindow)(pChild); + if (pChild->firstChild) { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } + anyMarked = TRUE; + pFirst = pFirst->nextSib; + } + if (anyMarked) + (* MarkWindow)(pWin->parent); + result = anyMarked; + } + NORMAL_ROOT(pWin); + SCREEN_WRAP(pScreen, MarkOverlappedWindows); + RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS end\n"); + return result; +} + + +static void +RootlessPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion, int what) +{ + int oldBackgroundState = 0; + PixUnion oldBackground; + ScreenPtr pScreen = pWin->drawable.pScreen; + + SCREEN_UNWRAP(pScreen, PaintWindowBackground); + RL_DEBUG_MSG("paintwindowbackground start (win 0x%x) ", pWin); + if (IsFramedWindow(pWin)) { + if (IsRoot(pWin)) { + // set root background to magic transparent color + oldBackgroundState = pWin->backgroundState; + oldBackground = pWin->background; + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = 0x00fffffe; + } + } + + pScreen->PaintWindowBackground(pWin, pRegion, what); + + if (IsFramedWindow(pWin)) { + RootlessDamageRegion(pWin, pRegion); + if (IsRoot(pWin)) { + pWin->backgroundState = oldBackgroundState; + pWin->background = oldBackground; + } + } + SCREEN_WRAP(pScreen, PaintWindowBackground); + RL_DEBUG_MSG("paintwindowbackground end\n"); +} + + +static void +RootlessPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion, int what) +{ + SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindowBorder); + RL_DEBUG_MSG("paintwindowborder start (win 0x%x) ", pWin); + pWin->drawable.pScreen->PaintWindowBorder(pWin, pRegion, what); + if (IsFramedWindow(pWin)) { + RootlessDamageRegion(pWin, pRegion); + } + SCREEN_WRAP(pWin->drawable.pScreen, PaintWindowBorder); + RL_DEBUG_MSG("paintwindowborder end\n"); +} + + +// Flush drawing before blocking on select(). +static void +RootlessBlockHandler(pointer pbdata, OSTimePtr pTimeout, pointer pReadmask) +{ + RootlessRedisplayScreen((ScreenPtr) pbdata); +} + + +static void +RootlessWakeupHandler(pointer data, int i, pointer LastSelectMask) +{ + // nothing here +} + + +static Bool +RootlessAllocatePrivates(ScreenPtr pScreen) +{ + RootlessScreenRec *s; + static int rootlessGeneration = -1; + + if (rootlessGeneration != serverGeneration) { + rootlessScreenPrivateIndex = AllocateScreenPrivateIndex(); + if (rootlessScreenPrivateIndex == -1) return FALSE; + rootlessGCPrivateIndex = AllocateGCPrivateIndex(); + if (rootlessGCPrivateIndex == -1) return FALSE; + rootlessWindowPrivateIndex = AllocateWindowPrivateIndex(); + if (rootlessWindowPrivateIndex == -1) return FALSE; + rootlessGeneration = serverGeneration; + } + + // no allocation needed for screen privates + if (!AllocateGCPrivate(pScreen, rootlessGCPrivateIndex, + sizeof(RootlessGCRec))) + return FALSE; + if (!AllocateWindowPrivate(pScreen, rootlessWindowPrivateIndex, 0)) + return FALSE; + + s = xalloc(sizeof(RootlessScreenRec)); + if (! s) return FALSE; + SCREENREC(pScreen) = s; + + return TRUE; +} + + +static void +RootlessWrap(ScreenPtr pScreen) +{ + RootlessScreenRec *s = (RootlessScreenRec*) + pScreen->devPrivates[rootlessScreenPrivateIndex].ptr; + +#define WRAP(a) \ + if (pScreen->a) { \ + s->a = pScreen->a; \ + } else { \ + RL_DEBUG_MSG("null screen fn " #a "\n"); \ + s->a = NULL; \ + } \ + pScreen->a = Rootless##a + + WRAP(CloseScreen); + WRAP(CreateGC); + WRAP(PaintWindowBackground); + WRAP(PaintWindowBorder); + WRAP(CopyWindow); + WRAP(GetImage); + WRAP(CreateWindow); + WRAP(DestroyWindow); + WRAP(RealizeWindow); + WRAP(UnrealizeWindow); + WRAP(MoveWindow); + WRAP(PositionWindow); + WRAP(ResizeWindow); + WRAP(RestackWindow); + WRAP(ChangeBorderWidth); + WRAP(MarkOverlappedWindows); + WRAP(ValidateTree); + WRAP(ChangeWindowAttributes); + +#ifdef SHAPE + WRAP(SetShape); +#endif + +#ifdef RENDER + { + // Composite and Glyphs don't use normal screen wrapping + PictureScreenPtr ps = GetPictureScreen(pScreen); + s->Composite = ps->Composite; + ps->Composite = RootlessComposite; + s->Glyphs = ps->Glyphs; + ps->Glyphs = RootlessGlyphs; + } +#endif + + // WRAP(ClearToBackground); fixme put this back? useful for shaped wins? + // WRAP(RestoreAreas); fixme put this back? + +#undef WRAP +} + + +/* + * RootlessInit + * Rootless wraps lots of stuff and needs a bunch of devPrivates. + */ +Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcs *procs) +{ + RootlessScreenRec *s; + + if (! RootlessAllocatePrivates(pScreen)) return FALSE; + s = (RootlessScreenRec*) + pScreen->devPrivates[rootlessScreenPrivateIndex].ptr; + + s->pScreen = pScreen; + s->frameProcs = *procs; + + RootlessWrap(pScreen); + + if (!RegisterBlockAndWakeupHandlers (RootlessBlockHandler, + RootlessWakeupHandler, + (pointer) pScreen)) + { + return FALSE; + } + + return TRUE; +} diff --git a/xc/programs/Xserver/hw/darwin/bundle/rootlessValTree.c b/xc/programs/Xserver/hw/darwin/bundle/rootlessValTree.c new file mode 100644 index 000000000..a6d33b6f1 --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/bundle/rootlessValTree.c @@ -0,0 +1,744 @@ +/* + * Calculate window clip lists for rootless mode + * + * This file is very closely based on mivaltree.c. + */ + /* $XFree86: xc/programs/Xserver/hw/darwin/bundle/rootlessValTree.c,v 1.1 2001/06/26 23:29:13 torrey Exp $ */ + +/* + * mivaltree.c -- + * Functions for recalculating window clip lists. Main function + * is miValidateTree. + * + +Copyright 1987, 1988, 1989, 1998 The Open Group + +All Rights Reserved. + +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, 1988, 1989 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. + * + ******************************************************************/ + +/* The panoramix components contained the following notice */ +/**************************************************************** +* * +* Copyright (c) Digital Equipment Corporation, 1991, 1997 * +* * +* All Rights Reserved. Unpublished rights reserved under * +* the copyright laws of the United States. * +* * +* The software contained on this media is proprietary to * +* and embodies the confidential technology of Digital * +* Equipment Corporation. Possession, use, duplication or * +* dissemination of the software and media is authorized only * +* pursuant to a valid written license from Digital Equipment * +* Corporation. * +* * +* RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure * +* by the U.S. Government is subject to restrictions as set * +* forth in Subparagraph (c)(1)(ii) of DFARS 252.227-7013, * +* or in FAR 52.227-19, as applicable. * +* * +*****************************************************************/ + + /* + * Aug '86: Susan Angebranndt -- original code + * July '87: Adam de Boor -- substantially modified and commented + * Summer '89: Joel McCormack -- so fast you wouldn't believe it possible. + * In particular, much improved code for window mapping and + * circulating. + * Bob Scheifler -- avoid miComputeClips for unmapped windows, + * valdata changes + */ +#include "X.h" +#include "scrnintstr.h" +#include "validate.h" +#include "windowstr.h" +#include "mi.h" +#include "regionstr.h" +#include "mivalidate.h" + +#include "globals.h" + +#ifdef SHAPE +/* + * Compute the visibility of a shaped window + */ +int +rootlessShapedWindowIn (pScreen, universe, bounding, rect, x, y) + ScreenPtr pScreen; + RegionPtr universe, bounding; + BoxPtr rect; + register int x, y; +{ + BoxRec box; + register BoxPtr boundBox; + int nbox; + Bool someIn, someOut; + register int t, x1, y1, x2, y2; + + nbox = REGION_NUM_RECTS (bounding); + boundBox = REGION_RECTS (bounding); + someIn = someOut = FALSE; + x1 = rect->x1; + y1 = rect->y1; + x2 = rect->x2; + y2 = rect->y2; + while (nbox--) + { + if ((t = boundBox->x1 + x) < x1) + t = x1; + box.x1 = t; + if ((t = boundBox->y1 + y) < y1) + t = y1; + box.y1 = t; + if ((t = boundBox->x2 + x) > x2) + t = x2; + box.x2 = t; + if ((t = boundBox->y2 + y) > y2) + t = y2; + box.y2 = t; + if (box.x1 > box.x2) + box.x2 = box.x1; + if (box.y1 > box.y2) + box.y2 = box.y1; + switch (RECT_IN_REGION(pScreen, universe, &box)) + { + case rgnIN: + if (someOut) + return rgnPART; + someIn = TRUE; + break; + case rgnOUT: + if (someIn) + return rgnPART; + someOut = TRUE; + break; + default: + return rgnPART; + } + boundBox++; + } + if (someIn) + return rgnIN; + return rgnOUT; +} +#endif + +#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \ + HasBorder(w) && \ + (w)->backgroundState == ParentRelative) + + +/* + *----------------------------------------------------------------------- + * miComputeClips -- + * Recompute the clipList, borderClip, exposed and borderExposed + * regions for pParent and its children. Only viewable windows are + * taken into account. + * + * Results: + * None. + * + * Side Effects: + * clipList, borderClip, exposed and borderExposed are altered. + * A VisibilityNotify event may be generated on the parent window. + * + *----------------------------------------------------------------------- + */ +static void +rootlessComputeClips (pParent, pScreen, universe, kind, exposed) + register WindowPtr pParent; + register ScreenPtr pScreen; + register RegionPtr universe; + VTKind kind; + RegionPtr exposed; /* for intermediate calculations */ +{ + int dx, + dy; + RegionRec childUniverse; + register WindowPtr pChild; + int oldVis, newVis; + BoxRec borderSize; + RegionRec childUnion; + Bool overlap; + RegionPtr borderVisible; + Bool resized; + /* + * Figure out the new visibility of this window. + * The extent of the universe should be the same as the extent of + * the borderSize region. If the window is unobscured, this rectangle + * will be completely inside the universe (the universe will cover it + * completely). If the window is completely obscured, none of the + * universe will cover the rectangle. + */ + borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent); + borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent); + dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent); + if (dx > 32767) + dx = 32767; + borderSize.x2 = dx; + dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent); + if (dy > 32767) + dy = 32767; + borderSize.y2 = dy; + + oldVis = pParent->visibility; + switch (RECT_IN_REGION( pScreen, universe, &borderSize)) + { + case rgnIN: + newVis = VisibilityUnobscured; + break; + case rgnPART: + newVis = VisibilityPartiallyObscured; +#ifdef SHAPE + { + RegionPtr pBounding; + + if ((pBounding = wBoundingShape (pParent))) + { + switch (rootlessShapedWindowIn (pScreen, universe, + pBounding, &borderSize, + pParent->drawable.x, + pParent->drawable.y)) + { + case rgnIN: + newVis = VisibilityUnobscured; + break; + case rgnOUT: + newVis = VisibilityFullyObscured; + break; + } + } + } +#endif + break; + default: + newVis = VisibilityFullyObscured; + break; + } + + pParent->visibility = newVis; + if (oldVis != newVis && + ((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask)) + SendVisibilityNotify(pParent); + + dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x; + dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y; + + /* + * avoid computations when dealing with simple operations + */ + + switch (kind) { + case VTMap: + case VTStack: + case VTUnmap: + break; + case VTMove: + if ((oldVis == newVis) && + ((oldVis == VisibilityFullyObscured) || + (oldVis == VisibilityUnobscured))) + { + pChild = pParent; + while (1) + { + if (pChild->viewable) + { + if (pChild->visibility != VisibilityFullyObscured) + { + REGION_TRANSLATE( pScreen, &pChild->borderClip, + dx, dy); + REGION_TRANSLATE( pScreen, &pChild->clipList, + dx, dy); + pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; + if (pScreen->ClipNotify) + (* pScreen->ClipNotify) (pChild, dx, dy); + + } + if (pChild->valdata) + { + REGION_INIT(pScreen, + &pChild->valdata->after.borderExposed, + NullBox, 0); + if (HasParentRelativeBorder(pChild)) + { + REGION_SUBTRACT(pScreen, + &pChild->valdata->after.borderExposed, + &pChild->borderClip, + &pChild->winSize); + } + REGION_INIT( pScreen, &pChild->valdata->after.exposed, + NullBox, 0); + } + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pParent)) + pChild = pChild->parent; + if (pChild == pParent) + break; + pChild = pChild->nextSib; + } + return; + } + /* fall through */ + default: + /* + * To calculate exposures correctly, we have to translate the old + * borderClip and clipList regions to the window's new location so there + * is a correspondence between pieces of the new and old clipping regions. + */ + if (dx || dy) + { + /* + * We translate the old clipList because that will be exposed or copied + * if gravity is right. + */ + REGION_TRANSLATE( pScreen, &pParent->borderClip, dx, dy); + REGION_TRANSLATE( pScreen, &pParent->clipList, dx, dy); + } + break; + case VTBroken: + REGION_EMPTY (pScreen, &pParent->borderClip); + REGION_EMPTY (pScreen, &pParent->clipList); + break; + } + + borderVisible = pParent->valdata->before.borderVisible; + resized = pParent->valdata->before.resized; + REGION_INIT( pScreen, &pParent->valdata->after.borderExposed, NullBox, 0); + REGION_INIT( pScreen, &pParent->valdata->after.exposed, NullBox, 0); + + /* + * Since the borderClip must not be clipped by the children, we do + * the border exposure first... + * + * 'universe' is the window's borderClip. To figure the exposures, remove + * the area that used to be exposed from the new. + * This leaves a region of pieces that weren't exposed before. + */ + + if (HasBorder (pParent)) + { + if (borderVisible) + { + /* + * when the border changes shape, the old visible portions + * of the border will be saved by DIX in borderVisible -- + * use that region and destroy it + */ + REGION_SUBTRACT( pScreen, exposed, universe, borderVisible); + REGION_DESTROY( pScreen, borderVisible); + } + else + { + REGION_SUBTRACT( pScreen, exposed, universe, &pParent->borderClip); + } + if (HasParentRelativeBorder(pParent) && (dx || dy)) { + REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed, + universe, + &pParent->winSize); + } else { + REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed, + exposed, &pParent->winSize); + } + + REGION_COPY( pScreen, &pParent->borderClip, universe); + + /* + * To get the right clipList for the parent, and to make doubly sure + * that no child overlaps the parent's border, we remove the parent's + * border from the universe before proceeding. + */ + + REGION_INTERSECT( pScreen, universe, universe, &pParent->winSize); + } + else + REGION_COPY( pScreen, &pParent->borderClip, universe); + + if ((pChild = pParent->firstChild) && pParent->mapped) + { + REGION_INIT(pScreen, &childUniverse, NullBox, 0); + REGION_INIT(pScreen, &childUnion, NullBox, 0); + if ((pChild->drawable.y < pParent->lastChild->drawable.y) || + ((pChild->drawable.y == pParent->lastChild->drawable.y) && + (pChild->drawable.x < pParent->lastChild->drawable.x))) + { + for (; pChild; pChild = pChild->nextSib) + { + if (pChild->viewable) + REGION_APPEND( pScreen, &childUnion, &pChild->borderSize); + } + } + else + { + for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib) + { + if (pChild->viewable) + REGION_APPEND( pScreen, &childUnion, &pChild->borderSize); + } + } + REGION_VALIDATE( pScreen, &childUnion, &overlap); + + for (pChild = pParent->firstChild; + pChild; + pChild = pChild->nextSib) + { + if (pChild->viewable) { + /* + * If the child is viewable, we want to remove its extents + * from the current universe, but we only re-clip it if + * it's been marked. + */ + if (pChild->valdata) { + /* + * Figure out the new universe from the child's + * perspective and recurse. + */ + REGION_INTERSECT( pScreen, &childUniverse, + universe, + &pChild->borderSize); + rootlessComputeClips (pChild, pScreen, &childUniverse, + kind, exposed); + } + /* + * Once the child has been processed, we remove its extents + * from the current universe, thus denying its space to any + * other sibling. + */ + if (overlap) + REGION_SUBTRACT( pScreen, universe, universe, + &pChild->borderSize); + } + } + if (!overlap) + REGION_SUBTRACT( pScreen, universe, universe, &childUnion); + REGION_UNINIT( pScreen, &childUnion); + REGION_UNINIT( pScreen, &childUniverse); + } /* if any children */ + + /* + * 'universe' now contains the new clipList for the parent window. + * + * To figure the exposure of the window we subtract the old clip from the + * new, just as for the border. + */ + + if (oldVis == VisibilityFullyObscured || + oldVis == VisibilityNotViewable) + { + REGION_COPY( pScreen, &pParent->valdata->after.exposed, universe); + } + else if (newVis != VisibilityFullyObscured && + newVis != VisibilityNotViewable) + { + REGION_SUBTRACT( pScreen, &pParent->valdata->after.exposed, + universe, &pParent->clipList); + } + + /* + * One last thing: backing storage. We have to try to save what parts of + * the window are about to be obscured. We can just subtract the universe + * from the old clipList and get the areas that were in the old but aren't + * in the new and, hence, are about to be obscured. + */ + if (pParent->backStorage && !resized) + { + REGION_SUBTRACT( pScreen, exposed, &pParent->clipList, universe); + (* pScreen->SaveDoomedAreas)(pParent, exposed, dx, dy); + } + + /* HACK ALERT - copying contents of regions, instead of regions */ + { + RegionRec tmp; + + tmp = pParent->clipList; + pParent->clipList = *universe; + *universe = tmp; + } + +#ifdef NOTDEF + REGION_COPY( pScreen, &pParent->clipList, universe); +#endif + + pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + if (pScreen->ClipNotify) + (* pScreen->ClipNotify) (pParent, dx, dy); +} + +static void +rootlessTreeObscured(pParent) + register WindowPtr pParent; +{ + register WindowPtr pChild; + register int oldVis; + + pChild = pParent; + while (1) + { + if (pChild->viewable) + { + oldVis = pChild->visibility; + if (oldVis != (pChild->visibility = VisibilityFullyObscured) && + ((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask)) + SendVisibilityNotify(pChild); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pParent)) + pChild = pChild->parent; + if (pChild == pParent) + break; + pChild = pChild->nextSib; + } +} + +/* + *----------------------------------------------------------------------- + * miValidateTree -- + * Recomputes the clip list for pParent and all its inferiors. + * + * Results: + * Always returns 1. + * + * Side Effects: + * The clipList, borderClip, exposed, and borderExposed regions for + * each marked window are altered. + * + * Notes: + * This routine assumes that all affected windows have been marked + * (valdata created) and their winSize and borderSize regions + * adjusted to correspond to their new positions. The borderClip and + * clipList regions should not have been touched. + * + * The top-most level is treated differently from all lower levels + * because pParent is unchanged. For the top level, we merge the + * regions taken up by the marked children back into the clipList + * for pParent, thus forming a region from which the marked children + * can claim their areas. For lower levels, where the old clipList + * and borderClip are invalid, we can't do this and have to do the + * extra operations done in miComputeClips, but this is much faster + * e.g. when only one child has moved... + * + *----------------------------------------------------------------------- + */ +/* + Quartz version: used for validate from root in rootless mode. + We need to make sure top-level windows don't clip each other, + and that top-level windows aren't clipped to the root window. +*/ +/*ARGSUSED*/ +// fixme this is ugly +// Xprint/ValTree.c doesn't work, but maybe that method can? +int +rootlessMiValidateTree (pRoot, pChild, kind) + WindowPtr pRoot; /* Parent to validate */ + WindowPtr pChild; /* First child of pRoot that was + * affected */ + VTKind kind; /* What kind of configuration caused call */ +{ + RegionRec totalClip; /* Total clipping region available to + * the marked children. pRoot's clipList + * merged with the borderClips of all + * the marked children. */ + RegionRec childClip; /* The new borderClip for the current + * child */ + RegionRec childUnion; /* the space covered by borderSize for + * all marked children */ + RegionRec exposed; /* For intermediate calculations */ + register ScreenPtr pScreen; + register WindowPtr pWin; + Bool overlap; + int viewvals; + Bool forward; + + pScreen = pRoot->drawable.pScreen; + if (pChild == NullWindow) + pChild = pRoot->firstChild; + + REGION_INIT(pScreen, &childClip, NullBox, 0); + REGION_INIT(pScreen, &exposed, NullBox, 0); + + /* + * compute the area of the parent window occupied + * by the marked children + the parent itself. This + * is the area which can be divied up among the marked + * children in their new configuration. + */ + REGION_INIT(pScreen, &totalClip, NullBox, 0); + viewvals = 0; + if (REGION_BROKEN (pScreen, &pRoot->clipList) && + !REGION_BROKEN (pScreen, &pRoot->borderClip)) + { + kind = VTBroken; + /* + * When rebuilding clip lists after out of memory, + * assume everything is busted. + */ + forward = TRUE; + REGION_COPY (pScreen, &totalClip, &pRoot->borderClip); + REGION_INTERSECT (pScreen, &totalClip, &totalClip, &pRoot->winSize); + + for (pWin = pRoot->firstChild; pWin != pChild; pWin = pWin->nextSib) + { + if (pWin->viewable) + REGION_SUBTRACT (pScreen, &totalClip, &totalClip, &pWin->borderSize); + } + for (pWin = pChild; pWin; pWin = pWin->nextSib) + if (pWin->valdata && pWin->viewable) + viewvals++; + + REGION_EMPTY (pScreen, &pRoot->clipList); + ErrorF("ValidateTree: BUSTED!\n"); + } + else + { + if ((pChild->drawable.y < pRoot->lastChild->drawable.y) || + ((pChild->drawable.y == pRoot->lastChild->drawable.y) && + (pChild->drawable.x < pRoot->lastChild->drawable.x))) + { + forward = TRUE; + for (pWin = pChild; pWin; pWin = pWin->nextSib) + { + if (pWin->valdata) + { + REGION_APPEND( pScreen, &totalClip, &pWin->borderClip); + if (pWin->viewable) + viewvals++; + } + } + } + else + { + forward = FALSE; + pWin = pRoot->lastChild; + while (1) + { + if (pWin->valdata) + { + REGION_APPEND( pScreen, &totalClip, &pWin->borderClip); + if (pWin->viewable) + viewvals++; + } + if (pWin == pChild) + break; + pWin = pWin->prevSib; + } + } + REGION_VALIDATE( pScreen, &totalClip, &overlap); + } + + + // calculate childUnion so we can subtract it from totalClip later + REGION_INIT(pScreen, &childUnion, NullBox, 0); + if (kind != VTStack) { + if (forward) + { + for (pWin = pChild; pWin; pWin = pWin->nextSib) + if (pWin->valdata && pWin->viewable) + REGION_APPEND( pScreen, &childUnion, + &pWin->borderSize); + } + else + { + pWin = pRoot->lastChild; + while (1) + { + if (pWin->valdata && pWin->viewable) + REGION_APPEND( pScreen, &childUnion, + &pWin->borderSize); + if (pWin == pChild) + break; + pWin = pWin->prevSib; + } + } + REGION_VALIDATE(pScreen, &childUnion, &overlap); + } + + + /* + * Now go through the children of the root and figure their new + * borderClips from the totalClip, passing that off to miComputeClips + * to handle recursively. Once that's done, we remove the child + * from the totalClip to clip any siblings below it. + */ + + for (pWin = pChild; + pWin != NullWindow; + pWin = pWin->nextSib) + { + if (pWin->viewable) { + if (pWin->valdata) { + REGION_COPY( pScreen, &childClip, &pWin->borderSize); + rootlessComputeClips (pWin, pScreen, &childClip, kind, &exposed); + } else if (pWin->visibility == VisibilityNotViewable) { + rootlessTreeObscured(pWin); + } + } else { + if (pWin->valdata) { + REGION_EMPTY( pScreen, &pWin->clipList); + if (pScreen->ClipNotify) + (* pScreen->ClipNotify) (pWin, 0, 0); + REGION_EMPTY( pScreen, &pWin->borderClip); + pWin->valdata = (ValidatePtr)NULL; + } + } + } + + REGION_UNINIT( pScreen, &childClip); + + // REGION_SUBTRACT(pScreen, &totalClip, &totalClip, &childUnion); + REGION_UNINIT(pScreen, &childUnion); + + REGION_INIT( pScreen, &pRoot->valdata->after.exposed, NullBox, 0); + REGION_INIT( pScreen, &pRoot->valdata->after.borderExposed, NullBox, 0); + + + REGION_UNINIT( pScreen, &totalClip); + REGION_UNINIT( pScreen, &exposed); + //if (pScreen->ClipNotify) + //(*pScreen->ClipNotify) (pRoot, 0, 0); + return (1); +} diff --git a/xc/programs/Xserver/hw/darwin/bundle/rootlessWindow.c b/xc/programs/Xserver/hw/darwin/bundle/rootlessWindow.c new file mode 100644 index 000000000..56418c351 --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/bundle/rootlessWindow.c @@ -0,0 +1,753 @@ +/* + * Rootless window management + * + * Greg Parker gparker@cs.stanford.edu + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/bundle/rootlessWindow.c,v 1.4 2001/08/01 05:34:06 torrey Exp $ */ + +#include "rootlessCommon.h" +#include "rootlessWindow.h" + +#include "fb.h" + +// PanoramiX/Xinerama creates a copy of every window, one per screen. +// Windows in rootless mode really can cross screens, so we only want to +// work with one copy of each. +#ifdef PANORAMIX +#include "../Xext/panoramiX.h" +#include "../Xext/panoramiXsrv.h" +// LookupIDByType doesn't find root window, but root windows are "real" here. +// LookupIDByType doesn't find anything when panoramix is off +#define IS_FAKE_WINDOW(w) \ + (!noPanoramiXExtension && \ + pWin->parent && \ + !LookupIDByType(w->drawable.id, XRT_WINDOW)) +#else +#define IS_FAKE_WINDOW(w) (0) +#endif + + +// RootlessCreateWindow +// For now, don't create a frame until the window is realized. +// Do reset the window size so it's not clipped by the root window. +Bool +RootlessCreateWindow(WindowPtr pWin) +{ + Bool result; + RegionRec saveRoot; + + WINREC(pWin) = NULL; + SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow); + if (!IsRoot(pWin)) { + // win/border size set by DIX, not by wrapped CreateWindow, so + // correct it here. + // Don't HUGE_ROOT when pWin is the root! + HUGE_ROOT(pWin); + SetWinSize(pWin); + SetBorderSize(pWin); + } + result = pWin->drawable.pScreen->CreateWindow(pWin); + if (pWin->parent) { + NORMAL_ROOT(pWin); + } + SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow); + return result; +} + + +// RootlessDestroyWindow +// For now, all window destruction takes place in UnrealizeWindow +Bool +RootlessDestroyWindow(WindowPtr pWin) +{ + Bool result; + + SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow); + result = pWin->drawable.pScreen->DestroyWindow(pWin); + SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow); + return result; +} + + +#ifdef SHAPE + +// fixme reimplement shape + +// boundingShape = outside border (like borderClip) +// clipShape = inside border (like clipList) +// Both are in window-local coordinates +// We only care about boundingShape (fixme true?) + +// RootlessReallySetShape is used in several places other than SetShape. +// Most importantly, SetShape is often called on unmapped windows, so we +// have to wait until the window is mapped to reshape the frame. +static void RootlessReallySetShape(WindowPtr pWin) +{ + RootlessWindowRec *winRec = WINREC(pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + RegionRec newShape; + + // fixme reimplement shape + return; + + if (IsRoot(pWin)) return; + if (!IsTopLevel(pWin)) return; + if (!winRec) return; + + if (wBoundingShape(pWin)) { + // wBoundingShape is relative to *inner* origin of window. + // Translate by borderWidth to get the outside-relative position. + REGION_INIT(pScreen, &newShape, NullBox, 0); + REGION_COPY(pScreen, &newShape, wBoundingShape(pWin)); + REGION_TRANSLATE(pScreen, &newShape, pWin->borderWidth, + pWin->borderWidth); + } else { + newShape.data = NULL; + newShape.extents.x1 = 0; + newShape.extents.y1 = 0; + newShape.extents.x2 = winRec->frame.w; + newShape.extents.y2 = winRec->frame.h; + } + RL_DEBUG_MSG("reshaping..."); + RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ", + REGION_NUM_RECTS(&newShape), + newShape.extents.x1, newShape.extents.y1, + newShape.extents.x2, newShape.extents.y2); + CallFrameProc(pScreen, ReshapeFrame,(pScreen, &winRec->frame, &newShape)); + REGION_UNINIT(pScreen, &newShape); +} + + +void +RootlessSetShape(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + RootlessReallySetShape(pWin); + SCREEN_UNWRAP(pScreen, SetShape); + pScreen->SetShape(pWin); + SCREEN_WRAP(pScreen, SetShape); +} + +#endif // SHAPE + + +// Disallow ParentRelative background on top-level windows +// because the root window doesn't really have the right background +// and cfb will try to draw on the root instead of on the window. +// fixme what about fb? +// fixme implement ParentRelative with real transparency? +// ParentRelative prevention is also in RealizeWindow() +Bool +RootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask) +{ + Bool result; + ScreenPtr pScreen = pWin->drawable.pScreen; + + RL_DEBUG_MSG("change window attributes start "); + + SCREEN_UNWRAP(pScreen, ChangeWindowAttributes); + result = pScreen->ChangeWindowAttributes(pWin, vmask); + SCREEN_WRAP(pScreen, ChangeWindowAttributes); + + if (WINREC(pWin)) { + // disallow ParentRelative background state + if (pWin->backgroundState == ParentRelative) { + XID pixel = 0; + ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); + } + } + + RL_DEBUG_MSG("change window attributes end\n"); + return result; +} + + +// Update the frame position now. +// (x, y) are *inside* position! +// After this, mi and fb are expecting the pixmap to be at the new location. +Bool +RootlessPositionWindow(WindowPtr pWin, int x, int y) +{ + RootlessWindowRec *winRec = WINREC(pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + Bool result; + + RL_DEBUG_MSG("positionwindow start\n"); + if (winRec) { + winRec->frame.x = x - pWin->borderWidth; + winRec->frame.y = y - pWin->borderWidth; + } + + UpdatePixmap(pWin); + + SCREEN_UNWRAP(pScreen, PositionWindow); + result = pScreen->PositionWindow(pWin, x, y); + SCREEN_WRAP(pScreen, PositionWindow); + + RL_DEBUG_MSG("positionwindow end\n"); + return result; +} + + +// RootlessRealizeWindow +// The frame is created here and not in CreateWindow. +// fixme change this? probably not - would be faster, but eat more memory +Bool +RootlessRealizeWindow(WindowPtr pWin) +{ + Bool result = FALSE; + RegionRec saveRoot; + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (IS_FAKE_WINDOW(pWin)) { + // Don't map fake windows + // They won't get a frame or take time to draw (fixme true?) + RL_DEBUG_MSG("realize window: skipping fake window\n"); + pWin->mapped = FALSE; + pWin->realized = FALSE; + pWin->viewable = FALSE; + return Success; + } + + RL_DEBUG_MSG("realizewindow start "); + + if (IsTopLevel(pWin) || IsRoot(pWin)) { + DrawablePtr d = &pWin->drawable; + RootlessWindowRec *winRec = xalloc(sizeof(RootlessWindowRec)); + + if (! winRec) goto windowcreatebad; + + winRec->frame.isRoot = (pWin == WindowTable[pScreen->myNum]); + winRec->frame.x = d->x - pWin->borderWidth; + winRec->frame.y = d->y - pWin->borderWidth; + winRec->frame.w = d->width + 2*pWin->borderWidth; + winRec->frame.h = d->height + 2*pWin->borderWidth; + winRec->frame.win = pWin; + winRec->frame.devPrivate = NULL; + + REGION_INIT(pScreen, &winRec->damage, NullBox, 0); + winRec->borderWidth = pWin->borderWidth; + + winRec->pixmap = NULL; + // UpdatePixmap() called below + + WINREC(pWin) = winRec; + + RL_DEBUG_MSG("creating frame "); + CallFrameProc(pScreen, CreateFrame, + (pScreen, &WINREC(pWin)->frame, + pWin->prevSib ? &WINREC(pWin->prevSib)->frame : NULL)); + + // fixme implement ParentRelative with transparency? + // need non-interfering fb first + // Disallow ParentRelative background state + // This might have been set before the window was mapped + if (pWin->backgroundState == ParentRelative) { + XID pixel = 0; + ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); + } + +#ifdef SHAPE + // Shape is usually set before the window is mapped, but + // (for now) we don't keep track of frames before they're mapped. + // RootlessReallySetShape(pWin); + // fixme reimplement shape +#endif + } + + UpdatePixmap(pWin); + + if (!IsRoot(pWin)) HUGE_ROOT(pWin); + SCREEN_UNWRAP(pScreen, RealizeWindow); + result = pScreen->RealizeWindow(pWin); + SCREEN_WRAP(pScreen, RealizeWindow); + if (!IsRoot(pWin)) NORMAL_ROOT(pWin); + + RL_DEBUG_MSG("realizewindow end\n"); + return result; + +windowcreatebad: + RL_DEBUG_MSG("window create bad! "); + RL_DEBUG_MSG("realizewindow end\n"); + return NULL; +} + + +Bool +RootlessUnrealizeWindow(WindowPtr pWin) +{ + Bool result; + ScreenPtr pScreen = pWin->drawable.pScreen; + + RL_DEBUG_MSG("unrealizewindow start "); + + if (IsTopLevel(pWin) || IsRoot(pWin)) { + RootlessWindowRec *winRec = WINREC(pWin); + + RootlessRedisplay(pWin); + CallFrameProc(pScreen, DestroyFrame, (pScreen, &winRec->frame)); + + REGION_UNINIT(pScreen, &winRec->damage); + + xfree(winRec); + WINREC(pWin) = NULL; + } + + SCREEN_UNWRAP(pScreen, UnrealizeWindow); + result = pScreen->UnrealizeWindow(pWin); + SCREEN_WRAP(pScreen, UnrealizeWindow); + RL_DEBUG_MSG("unrealizewindow end\n"); + return result; +} + + +void +RootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib) +{ + RegionRec saveRoot; + RootlessWindowRec *winRec = WINREC(pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + + RL_DEBUG_MSG("restackwindow start "); + if (winRec) RL_DEBUG_MSG("restack top level \n"); + + HUGE_ROOT(pWin); + SCREEN_UNWRAP(pScreen, RestackWindow); + if (pScreen->RestackWindow) pScreen->RestackWindow(pWin, pOldNextSib); + SCREEN_WRAP(pScreen, RestackWindow); + NORMAL_ROOT(pWin); + + if (winRec) { + // fixme simplify the following + + WindowPtr oldNextW, newNextW, oldPrevW, newPrevW; + RootlessFramePtr oldNext, newNext, oldPrev, newPrev; + + oldNextW = pOldNextSib; + while (oldNextW && ! WINREC(oldNextW)) oldNextW = oldNextW->nextSib; + oldNext = oldNextW ? &WINREC(oldNextW)->frame : NULL; + + newNextW = pWin->nextSib; + while (newNextW && ! WINREC(newNextW)) newNextW = newNextW->nextSib; + newNext = newNextW ? &WINREC(newNextW)->frame : NULL; + + oldPrevW= pOldNextSib ? pOldNextSib->prevSib : pWin->parent->lastChild; + while (oldPrevW && ! WINREC(oldPrevW)) oldPrevW = oldPrevW->prevSib; + oldPrev = oldPrevW ? &WINREC(oldPrevW)->frame : NULL; + + newPrevW = pWin->prevSib; + while (newPrevW && ! WINREC(newPrevW)) newPrevW = newPrevW->prevSib; + newPrev = newPrevW ? &WINREC(newPrevW)->frame : NULL; + + if (pWin->prevSib) { + WindowPtr w = pWin->prevSib; + while (w) { + RL_DEBUG_MSG("w 0x%x\n", w); + w = w->parent; + } + } + + CallFrameProc(pScreen, RestackFrame, + (pScreen, &winRec->frame, oldPrev, newPrev)); + } + + RL_DEBUG_MSG("restackwindow end\n"); +} + + +/* + * Specialized window copy procedures + */ + +// Globals needed during window resize and move. +static PixmapPtr gResizeDeathPix = NULL; +static pointer gResizeDeathBits = NULL; +static PixmapPtr gResizeCopyWindowSource = NULL; +static CopyWindowProcPtr gResizeOldCopyWindowProc = NULL; + +// CopyWindow() that doesn't do anything. +// For MoveWindow() of top-level windows. +static void +RootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ + // some code expects the region to be translated + int dx = ptOldOrg.x - pWin->drawable.x; + int dy = ptOldOrg.y - pWin->drawable.y; + RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW "); + + REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); +} + + +// CopyWindow used during ResizeWindow for gravity moves. +// Cloned from fbCopyWindow +// The original always draws on the root pixmap (which we don't have). +// Instead, draw on the parent window's pixmap. +// Resize version: the old location's pixels are in gResizeCopyWindowSource +static void +RootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + SCREEN_UNWRAP(pScreen, CopyWindow); + RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin); + + { + RegionRec rgnDst; + int dx, dy; + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); + REGION_INIT (pScreen, &rgnDst, NullBox, 0); + REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); + + fbCopyRegion (&gResizeCopyWindowSource->drawable, + &pScreen->GetWindowPixmap(pWin)->drawable, + 0, + &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); + + // don't update - resize will update everything + // fixme DO update? + REGION_UNINIT(pScreen, &rgnDst); + fbValidateDrawable (&pWin->drawable); + } + + SCREEN_WRAP(pScreen, CopyWindow); + RL_DEBUG_MSG("resizecopywindowFB end\n"); +} + + +/* Update *new* location of window. Old location is redrawn with + * PaintWindowBackground/Border. + * Cloned from fbCopyWindow + * The original always draws on the root pixmap (which we don't have). + * Instead, draw on the parent window's pixmap. + */ +void +RootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + SCREEN_UNWRAP(pScreen, CopyWindow); + RL_DEBUG_MSG("copywindowFB start (win 0x%x) ", pWin); + + { + RegionRec rgnDst; + int dx, dy; + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); + + REGION_INIT(pScreen, &rgnDst, NullBox, 0); + REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); + + fbCopyRegion ((DrawablePtr)pWin, (DrawablePtr)pWin, + 0, + &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); + + // prgnSrc has been translated to dst position + RootlessDamageRegion(pWin, prgnSrc); + REGION_UNINIT(pScreen, &rgnDst); + fbValidateDrawable (&pWin->drawable); + } + + SCREEN_WRAP(pScreen, CopyWindow); + RL_DEBUG_MSG("copywindowFB end\n"); +} + + +/* + * Window resize procedures + */ + +// Prepare to resize a window. +// The old window's pixels are saved and the implementation is told +// to change the window size. +// (x,y,w,h) is outer frame of window (outside border) +static void +StartFrameResize(WindowPtr pWin, Bool gravity, + int oldX, int oldY, + unsigned int oldW, unsigned int oldH, unsigned int oldBW, + int newX, int newY, + unsigned int newW, unsigned int newH, unsigned int newBW) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + RootlessWindowRec *winRec = WINREC(pWin); + + RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW "); + RL_DEBUG_MSG("%d %d %d %d %d %d %d %d %d %d ", + oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW); + + RootlessRedisplay(pWin); + +/* +#ifdef SHAPE + // make the frame shape a rect + // fixme reimplement shape + if (wBoundingShape(pWin)) { + RegionPtr saveShape = wBoundingShape(pWin); + + pWin->optional->boundingShape = NULL; + RL_DEBUG_MSG("RootlessReallySetShape from resize "); + RootlessReallySetShape(pWin); + pWin->optional->boundingShape = saveShape; + } +#endif // SHAPE +*/ + + // Make a copy of the current pixmap and all its data. + // The original will go away when we ask the frame manager to + // allocate the new pixmap. + + gResizeDeathBits = xalloc(winRec->frame.bytesPerRow * winRec->frame.h); + memcpy(gResizeDeathBits, winRec->frame.pixelData, + winRec->frame.bytesPerRow * winRec->frame.h); + gResizeDeathPix = + GetScratchPixmapHeader(pScreen, winRec->frame.w, winRec->frame.h, + winRec->frame.depth, winRec->frame.bitsPerPixel, + winRec->frame.bytesPerRow, gResizeDeathBits); + SetPixmapBaseToScreen(gResizeDeathPix, winRec->frame.x, winRec->frame.y); + + winRec->frame.x = newX; + winRec->frame.y = newY; + winRec->frame.w = newW; + winRec->frame.h = newH; + winRec->borderWidth = newBW; + + CallFrameProc(pScreen, StartResizeFrame, + (pScreen, &winRec->frame, oldX, oldY, oldW, oldH)); + UpdatePixmap(pWin); + + // Use custom CopyWindow when moving gravity bits around + // ResizeWindow assumes the old window contents are in the same + // pixmap, but here they're in deathPix instead. + if (gravity) { + gResizeCopyWindowSource = gResizeDeathPix; + gResizeOldCopyWindowProc = pScreen->CopyWindow; + pScreen->CopyWindow = RootlessResizeCopyWindow; + } + + // Copy pixels in intersection from src to dst. + // ResizeWindow assumes these pixels are already present when + // making gravity adjustments. + // pWin currently has new-sized pixmap but is in old position + // fixme border width change! + { + RegionRec r; + DrawablePtr src = &gResizeDeathPix->drawable; + DrawablePtr dst = &pScreen->GetWindowPixmap(pWin)->drawable; + + r.data = NULL; + r.extents.x1 = max(oldX, newX); + r.extents.y1 = max(oldY, newY); + r.extents.x2 = min(oldX + oldW, newX + newW); + r.extents.y2 = min(oldY + oldH, newY + newH); + + // r is now intersection of of old location and new location + if (r.extents.x2 > r.extents.x1 && r.extents.y2 > r.extents.y1) { +#if 0 + DDXPointRec srcPt = {r.extents.x1, r.extents.y1}; + // Correct for border width change + // fixme need to correct for border width change + int dx = newX - oldX; + int dy = newY - oldY; + REGION_TRANSLATE(pScreen, &r, dx, dy); +#endif + fbCopyRegion(src, dst, NULL, &r, 0, 0, fbCopyWindowProc, 0, 0); + } + REGION_UNINIT(pScreen, &r); + } +} + + +static void +FinishFrameResize(WindowPtr pWin, Bool gravity, + int oldX, int oldY, + unsigned int oldW, unsigned int oldH, unsigned int oldBW, + int newX, int newY, + unsigned int newW, unsigned int newH, unsigned int newBW) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + RootlessWindowRec *winRec = WINREC(pWin); + + CallFrameProc(pScreen, FinishResizeFrame, + (pScreen, &winRec->frame, oldX, oldY, oldW, oldH)); + + // Destroy temp pixmap + FreeScratchPixmapHeader(gResizeDeathPix); + xfree(gResizeDeathBits); + gResizeDeathPix = gResizeDeathBits = NULL; + + if (gravity) { + pScreen->CopyWindow = gResizeOldCopyWindowProc; + gResizeCopyWindowSource = NULL; + } +} + + +// If kind==VTOther, window border is resizing (and borderWidth is +// already changed!!@#$) This case works like window resize, not move. +void +RootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) +{ + CopyWindowProcPtr oldCopyWindowProc = NULL; + RegionRec saveRoot; + RootlessWindowRec *winRec = WINREC(pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + int oldX = 0, oldY = 0, newX = 0, newY = 0; + unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0; + + RL_DEBUG_MSG("movewindow start \n"); + + if (winRec) { + if (kind == VTMove) { + oldX = winRec->frame.x; + oldY = winRec->frame.y; + RootlessRedisplay(pWin); + } else { + RL_DEBUG_MSG("movewindow border resizing "); + oldBW = winRec->borderWidth; + oldX = winRec->frame.x; + oldY = winRec->frame.y; + oldW = winRec->frame.w; + oldH = winRec->frame.h; + newBW = pWin->borderWidth; + newX = x; + newY = y; + newW = pWin->drawable.width + 2*newBW; + newH = pWin->drawable.height + 2*newBW; + StartFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW); + } + } + + HUGE_ROOT(pWin); + SCREEN_UNWRAP(pScreen, MoveWindow); + if (winRec) { + oldCopyWindowProc = pScreen->CopyWindow; + pScreen->CopyWindow = RootlessNoCopyWindow; + } + pScreen->MoveWindow(pWin, x, y, pSib, kind); + if (winRec) { + pScreen->CopyWindow = oldCopyWindowProc; + } + NORMAL_ROOT(pWin); + SCREEN_WRAP(pScreen, MoveWindow); + + if (winRec) { + if (kind == VTMove) { + // PositionWindow has already set the new frame position. + CallFrameProc(pScreen, MoveFrame, + (pScreen, &winRec->frame, oldX, oldY)); + } else { + FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW); + } + } + + RL_DEBUG_MSG("movewindow end\n"); +} + + +// Note: (x, y, w, h) as passed to this procedure don't match +// the frame definition. +// (x,y) is corner of very outer edge, *outside* border +// w,h is width and height *inside8 border, *ignoring* border width +// The rect (x, y, w, h) doesn't mean anything. +// (x, y, w+2*bw, h+2*bw) is total rect +// (x+bw, y+bw, w, h) is inner rect + +void +RootlessResizeWindow(WindowPtr pWin, int x, int y, + unsigned int w, unsigned int h, WindowPtr pSib) +{ + RegionRec saveRoot; + RootlessWindowRec *winRec = WINREC(pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + int oldX = 0, oldY = 0, newX = 0, newY = 0; + unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0; + + RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin); + + if (winRec) { + oldBW = winRec->borderWidth; + oldX = winRec->frame.x; + oldY = winRec->frame.y; + oldW = winRec->frame.w; + oldH = winRec->frame.h; + + newBW = oldBW; + newX = x; + newY = y; + newW = w + 2*newBW; + newH = h + 2*newBW; + + StartFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW); + } + + HUGE_ROOT(pWin); + SCREEN_UNWRAP(pScreen, ResizeWindow); + pScreen->ResizeWindow(pWin, x, y, w, h, pSib); + SCREEN_WRAP(pScreen, ResizeWindow); + NORMAL_ROOT(pWin); + + if (winRec) { + FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW); + } + + RL_DEBUG_MSG("resizewindow end\n"); +} + + +// fixme untested! +// pWin inside corner stays the same +// pWin->drawable.[xy] stays the same +// frame moves and resizes +void +RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width) +{ + RegionRec saveRoot; + + RL_DEBUG_MSG("change border width "); + if (width != pWin->borderWidth) { + RootlessWindowRec *winRec = WINREC(pWin); + int oldX = 0, oldY = 0, newX = 0, newY = 0; + unsigned int oldW = 0, oldH = 0, oldBW = 0; + unsigned int newW = 0, newH = 0, newBW = 0; + + if (winRec) { + oldBW = winRec->borderWidth; + oldX = winRec->frame.x; + oldY = winRec->frame.y; + oldW = winRec->frame.w; + oldH = winRec->frame.h; + + newBW = width; + newX = pWin->drawable.x - newBW; + newY = pWin->drawable.y - newBW; + newW = pWin->drawable.width + 2*newBW; + newH = pWin->drawable.height + 2*newBW; + + StartFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW); + } + + HUGE_ROOT(pWin); + SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth); + pWin->drawable.pScreen->ChangeBorderWidth(pWin, width); + SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth); + NORMAL_ROOT(pWin); + + if (winRec) { + FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW); + } + } + RL_DEBUG_MSG("change border width end\n"); +} diff --git a/xc/programs/Xserver/hw/darwin/bundle/rootlessWindow.h b/xc/programs/Xserver/hw/darwin/bundle/rootlessWindow.h new file mode 100644 index 000000000..ba14c787a --- /dev/null +++ b/xc/programs/Xserver/hw/darwin/bundle/rootlessWindow.h @@ -0,0 +1,32 @@ +/* + * Rootless window management + * + * Greg Parker gparker@cs.stanford.edu + */ +/* $XFree86: xc/programs/Xserver/hw/darwin/bundle/rootlessWindow.h,v 1.1 2001/07/01 02:13:41 torrey Exp $ */ + +#ifndef _ROOTLESSWINDOW_H +#define _ROOTLESSWINDOW_H + +#include "rootlessCommon.h" + + +Bool RootlessCreateWindow(WindowPtr pWin); +Bool RootlessDestroyWindow(WindowPtr pWin); + +#ifdef SHAPE +void RootlessSetShape(WindowPtr pWin); +#endif // SHAPE + +Bool RootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask); +Bool RootlessPositionWindow(WindowPtr pWin, int x, int y); +Bool RootlessRealizeWindow(WindowPtr pWin); +Bool RootlessUnrealizeWindow(WindowPtr pWin); +void RootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib); +void RootlessCopyWindow(WindowPtr pWin,DDXPointRec ptOldOrg,RegionPtr prgnSrc); +void RootlessMoveWindow(WindowPtr pWin,int x,int y,WindowPtr pSib,VTKind kind); +void RootlessResizeWindow(WindowPtr pWin, int x, int y, + unsigned int w, unsigned int h, WindowPtr pSib); +void RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width); + +#endif diff --git a/xc/programs/Xserver/hw/kdrive/ipaq/Imakefile b/xc/programs/Xserver/hw/kdrive/ipaq/Imakefile new file mode 100644 index 000000000..8fb723ca2 --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/ipaq/Imakefile @@ -0,0 +1,13 @@ +XCOMM $XFree86: xc/programs/Xserver/hw/kdrive/ipaq/Imakefile,v 1.1 2001/05/23 17:28:39 alanh Exp $ +KDRIVE=.. +#include "../Kdrive.tmpl" + +SRCS = ipaq.c + +OBJS = ipaq.o + +INCLUDES = -I. $(KDINCS) -I$(KDRIVE)/fbdev -I$(KDRIVE)/pcmcia + +NormalLibraryObjectRule() +NormalLibraryTarget(ipaq,$(OBJS)) +DependTarget() diff --git a/xc/programs/Xserver/hw/kdrive/ipaq/ipaq.c b/xc/programs/Xserver/hw/kdrive/ipaq/ipaq.c new file mode 100644 index 000000000..b281c213b --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/ipaq/ipaq.c @@ -0,0 +1,89 @@ +/* + * Copyright © 1999 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. + * + * Adapted from ts300.c by Alan Hourihane <alanh@fairlite.demon.co.uk> + * For the Compaq IPAQ handheld, with the HP VGA Out Card (F1252A). + */ +/* $XFree86: xc/programs/Xserver/hw/kdrive/ipaq/ipaq.c,v 1.2 2001/05/29 17:47:55 keithp Exp $ */ + +#include "pcmcia.h" + +extern KdCardFuncs pcmciaFuncs; + +void +InitCard (char *name) +{ + KdCardAttr attr; + if (name && !strcmp(name, "pcmcia")) + KdCardInfoAdd (&pcmciaFuncs, &attr, 0); + else + KdCardInfoAdd (&fbdevFuncs, &attr, 0); +} + +void +InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv) +{ + KdInitOutput (pScreenInfo, argc, argv); +} + +void +InitInput (int argc, char **argv) +{ +#ifdef __powerpc__ + KdInitInput (&BusMouseFuncs, &LinuxKeyboardFuncs); +#else + KdInitInput (&Ps2MouseFuncs, &LinuxKeyboardFuncs); +#endif +#ifdef TOUCHSCREEN + KdInitTouchScreen (&TsFuncs); +#endif +} + +extern pcmciaDisplayModeRec pcmciaDefaultModes[]; + +int +ddxProcessArgument (int argc, char **argv, int i) +{ + int ret; + + if (!strcmp (argv[i], "-listmodes")) + { + int j = 0, bpp = 0; + ErrorF("Valid modes are....\n\n"); + + for (bpp = 8; bpp < 24; bpp += 8) { + while (pcmciaDefaultModes[j].Width != 0) { + if ((pcmciaDefaultModes[j].Width * + pcmciaDefaultModes[j].Height * bpp/8) <= 512 * 1024) { + ErrorF("%dx%dx%dx%d\n", + pcmciaDefaultModes[j].Width, + pcmciaDefaultModes[j].Height, + bpp, + pcmciaDefaultModes[j].Refresh); + } + j++; + } + j = 0; + } + exit(1); + } + return KdProcessArgument (argc, argv, i); +} diff --git a/xc/programs/Xserver/hw/kdrive/kaa.c b/xc/programs/Xserver/hw/kdrive/kaa.c new file mode 100644 index 000000000..3e362cfb8 --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/kaa.c @@ -0,0 +1,636 @@ +/* + * $XFree86: xc/programs/Xserver/hw/kdrive/kaa.c,v 1.5 2001/06/29 13:55:53 keithp Exp $ + * + * Copyright © 2001 Keith Packard, member of The XFree86 Project, 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 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. + */ + +#include "kdrive.h" +#include "fontstruct.h" +#include "dixfontstr.h" + +int kaaGeneration; +int kaaScreenPrivateIndex; + +#define KaaScreenPriv(s) KaaScreenPrivPtr pKaaScr = (KaaScreenPrivPtr) (s)->devPrivates[kaaScreenPrivateIndex].ptr + +void +kaaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, + DDXPointPtr ppt, int *pwidth, int fSorted) +{ + ScreenPtr pScreen = pDrawable->pScreen; + KdScreenPriv (pScreen); + KaaScreenPriv (pScreen); + RegionPtr pClip = fbGetCompositeClip(pGC); + BoxPtr pextent, pbox; + int nbox; + int extentX1, extentX2, extentY1, extentY2; + int fullX1, fullX2, fullY1; + int partX1, partX2; + + if (!pScreenPriv->enabled || + pGC->fillStyle != FillSolid || + !(*pKaaScr->PrepareSolid) (pDrawable, + pGC->alu, + pGC->planemask, + pGC->fgPixel)) + { + KdCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); + return; + } + + pextent = REGION_EXTENTS(pGC->pScreen, pClip); + extentX1 = pextent->x1; + extentY1 = pextent->y1; + extentX2 = pextent->x2; + extentY2 = pextent->y2; + while (n--) + { + fullX1 = ppt->x; + fullY1 = ppt->y; + fullX2 = fullX1 + (int) *pwidth; + ppt++; + pwidth++; + + if (fullY1 < extentY1 || extentY2 <= fullY1) + continue; + + if (fullX1 < extentX1) + fullX1 = extentX1; + + if (fullX2 > extentX2) + fullX2 = extentX2; + + if (fullX1 >= fullX2) + continue; + + nbox = REGION_NUM_RECTS (pClip); + if (nbox == 1) + { + (*pKaaScr->Solid) (fullX1, fullY1, fullX2, fullY1 + 1); + } + else + { + pbox = REGION_RECTS(pClip); + while(nbox--) + { + if (pbox->y1 <= fullY1 && fullY1 < pbox->y2) + { + partX1 = pbox->x1; + if (partX1 < fullX1) + partX1 = fullX1; + partX2 = pbox->x2; + if (partX2 > fullX2) + partX2 = fullX2; + if (partX2 > partX1) + (*pKaaScr->Solid) (partX1, fullY1, partX2, fullY1 + 1); + } + pbox++; + } + } + } + (*pKaaScr->DoneSolid) (); + KdMarkSync(pDrawable->pScreen); +} + +void +kaaCopyNtoN (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + KdScreenPriv (pDstDrawable->pScreen); + KaaScreenPriv (pDstDrawable->pScreen); + int srcX, srcY, dstX, dstY; + int w, h; + CARD32 flags; + CARD32 cmd; + CARD8 alu; + + if (pScreenPriv->enabled && + pSrcDrawable->type == DRAWABLE_WINDOW && + (*pKaaScr->PrepareCopy) (pSrcDrawable, + pDstDrawable, + dx, + dy, + pGC ? pGC->alu : GXcopy, + pGC ? pGC->planemask : FB_ALLONES)) + { + while (nbox--) + { + (*pKaaScr->Copy) (pbox->x1 + dx, pbox->y1 + dy, + pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + pbox++; + } + (*pKaaScr->DoneCopy) (); + KdMarkSync(pDstDrawable->pScreen); + } + else + { + KdCheckSync (pDstDrawable->pScreen); + fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, + pbox, nbox, dx, dy, reverse, upsidedown, + bitplane, closure); + } +} + +RegionPtr +kaaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, + int srcx, int srcy, int width, int height, int dstx, int dsty) +{ + return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, + dstx, dsty, kaaCopyNtoN, 0, 0); +} + +void +kaaPolyFillRect(DrawablePtr pDrawable, + GCPtr pGC, + int nrect, + xRectangle *prect) +{ + KdScreenPriv (pDrawable->pScreen); + KaaScreenPriv (pDrawable->pScreen); + RegionPtr pClip = fbGetCompositeClip(pGC); + register BoxPtr pbox; + BoxPtr pextent; + int extentX1, extentX2, extentY1, extentY2; + int fullX1, fullX2, fullY1, fullY2; + int partX1, partX2, partY1, partY2; + int xorg, yorg; + int n; + + if (!pScreenPriv->enabled || + pGC->fillStyle != FillSolid || + !(*pKaaScr->PrepareSolid) (pDrawable, + pGC->alu, + pGC->planemask, + pGC->fgPixel)) + { + KdCheckPolyFillRect (pDrawable, pGC, nrect, prect); + return; + } + + xorg = pDrawable->x; + yorg = pDrawable->y; + + pextent = REGION_EXTENTS(pGC->pScreen, pClip); + extentX1 = pextent->x1; + extentY1 = pextent->y1; + extentX2 = pextent->x2; + extentY2 = pextent->y2; + while (nrect--) + { + fullX1 = prect->x + xorg; + fullY1 = prect->y + yorg; + fullX2 = fullX1 + (int) prect->width; + fullY2 = fullY1 + (int) prect->height; + prect++; + + if (fullX1 < extentX1) + fullX1 = extentX1; + + if (fullY1 < extentY1) + fullY1 = extentY1; + + if (fullX2 > extentX2) + fullX2 = extentX2; + + if (fullY2 > extentY2) + fullY2 = extentY2; + + if ((fullX1 >= fullX2) || (fullY1 >= fullY2)) + continue; + n = REGION_NUM_RECTS (pClip); + if (n == 1) + { + (*pKaaScr->Solid) (fullX1, fullY1, fullX2, fullY2); + } + else + { + pbox = REGION_RECTS(pClip); + /* + * clip the rectangle to each box in the clip region + * this is logically equivalent to calling Intersect() + */ + while(n--) + { + partX1 = pbox->x1; + if (partX1 < fullX1) + partX1 = fullX1; + partY1 = pbox->y1; + if (partY1 < fullY1) + partY1 = fullY1; + partX2 = pbox->x2; + if (partX2 > fullX2) + partX2 = fullX2; + partY2 = pbox->y2; + if (partY2 > fullY2) + partY2 = fullY2; + + pbox++; + + if (partX1 < partX2 && partY1 < partY2) + (*pKaaScr->Solid) (partX1, partY1, + partX2, partY2); + } + } + } + (*pKaaScr->DoneSolid) (); + KdMarkSync(pDrawable->pScreen); +} + +void +kaaSolidBoxClipped (DrawablePtr pDrawable, + RegionPtr pClip, + FbBits pm, + FbBits fg, + int x1, + int y1, + int x2, + int y2) +{ + KdScreenPriv (pDrawable->pScreen); + KaaScreenPriv (pDrawable->pScreen); + BoxPtr pbox; + int nbox; + int partX1, partX2, partY1, partY2; + CARD32 cmd; + + if (!pScreenPriv->enabled || + !(*pKaaScr->PrepareSolid) (pDrawable, GXcopy, pm, fg)) + { + KdCheckSync (pDrawable->pScreen); + fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel); + fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2, + fbAnd (GXcopy, fg, pm), + fbXor (GXcopy, fg, pm)); + return; + } + for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip); + nbox--; + pbox++) + { + partX1 = pbox->x1; + if (partX1 < x1) + partX1 = x1; + + partX2 = pbox->x2; + if (partX2 > x2) + partX2 = x2; + + if (partX2 <= partX1) + continue; + + partY1 = pbox->y1; + if (partY1 < y1) + partY1 = y1; + + partY2 = pbox->y2; + if (partY2 > y2) + partY2 = y2; + + if (partY2 <= partY1) + continue; + + (*pKaaScr->Solid) (partX1, partY1, partX2, partY2); + } + (*pKaaScr->DoneSolid) (); + KdMarkSync(pDrawable->pScreen); +} + +void +kaaImageGlyphBlt (DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, + CharInfoPtr *ppciInit, + pointer pglyphBase) +{ + KaaScreenPriv (pDrawable->pScreen); + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + CharInfoPtr *ppci; + CharInfoPtr pci; + unsigned char *pglyph; /* pointer bits in glyph */ + int gWidth, gHeight; /* width and height of glyph */ + FbStride gStride; /* stride of glyph */ + Bool opaque; + int n; + int gx, gy; + void (*glyph) (FbBits *, + FbStride, + int, + FbStip *, + FbBits, + int, + int); + FbBits *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + FbBits depthMask; + + depthMask = FbFullMask(pDrawable->depth); + if ((pGC->planemask & depthMask) != depthMask) + { + KdCheckImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase); + return; + } + glyph = 0; + fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + switch (dstBpp) { + case 8: glyph = fbGlyph8; break; + case 16: glyph = fbGlyph16; break; + case 24: glyph = fbGlyph24; break; + case 32: glyph = fbGlyph32; break; + } + + x += pDrawable->x; + y += pDrawable->y; + + if (TERMINALFONT (pGC->font) && !glyph) + { + opaque = TRUE; + } + else + { + int xBack, widthBack; + int yBack, heightBack; + + ppci = ppciInit; + n = nglyph; + widthBack = 0; + while (n--) + widthBack += (*ppci++)->metrics.characterWidth; + + xBack = x; + if (widthBack < 0) + { + xBack += widthBack; + widthBack = -widthBack; + } + yBack = y - FONTASCENT(pGC->font); + heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); + kaaSolidBoxClipped (pDrawable, + fbGetCompositeClip(pGC), + pGC->planemask, + pGC->bgPixel, + xBack, + yBack, + xBack + widthBack, + yBack + heightBack); + opaque = FALSE; + } + + KdCheckSync (pDrawable->pScreen); + + ppci = ppciInit; + while (nglyph--) + { + pci = *ppci++; + pglyph = FONTGLYPHBITS(pglyphBase, pci); + gWidth = GLYPHWIDTHPIXELS(pci); + gHeight = GLYPHHEIGHTPIXELS(pci); + if (gWidth && gHeight) + { + gx = x + pci->metrics.leftSideBearing; + gy = y - pci->metrics.ascent; + if (glyph && gWidth <= sizeof (FbStip) * 8 && + fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) + { + (*glyph) (dst + (gy - dstYoff) * dstStride, + dstStride, + dstBpp, + (FbStip *) pglyph, + pPriv->fg, + gx - dstXoff, + gHeight); + } + else + { + gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip); + fbPutXYImage (pDrawable, + fbGetCompositeClip(pGC), + pPriv->fg, + pPriv->bg, + pPriv->pm, + GXcopy, + opaque, + + gx, + gy, + gWidth, gHeight, + + (FbStip *) pglyph, + gStride, + 0); + } + } + x += pci->metrics.characterWidth; + } +} + +static const GCOps kaaOps = { + kaaFillSpans, + KdCheckSetSpans, + KdCheckPutImage, + kaaCopyArea, + KdCheckCopyPlane, + KdCheckPolyPoint, + KdCheckPolylines, + KdCheckPolySegment, + miPolyRectangle, + KdCheckPolyArc, + miFillPolygon, + kaaPolyFillRect, + miPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + kaaImageGlyphBlt, + KdCheckPolyGlyphBlt, + KdCheckPushPixels, +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +void +kaaValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable) +{ + FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC); + + fbValidateGC (pGC, changes, pDrawable); + + if (pDrawable->type == DRAWABLE_WINDOW) + pGC->ops = (GCOps *) &kaaOps; + else + pGC->ops = (GCOps *) &kdAsyncPixmapGCOps; +} + +GCFuncs kaaGCFuncs = { + kaaValidateGC, + miChangeGC, + miCopyGC, + miDestroyGC, + miChangeClip, + miDestroyClip, + miCopyClip +}; + +int +kaaCreateGC (GCPtr pGC) +{ + if (!fbCreateGC (pGC)) + return FALSE; + + pGC->funcs = &kaaGCFuncs; + + return TRUE; +} + +void +kaaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + KaaScreenPriv (pScreen); + RegionRec rgnDst; + int dx, dy; + WindowPtr pwinRoot; + + pwinRoot = WindowTable[pWin->drawable.pScreen->myNum]; + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); + + REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0); + + REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc); + + fbCopyRegion ((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot, + 0, + &rgnDst, dx, dy, kaaCopyNtoN, 0, 0); + + REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); +} + +void +kaaFillRegionSolid (DrawablePtr pDrawable, + RegionPtr pRegion, + Pixel pixel) +{ + KdScreenPriv(pDrawable->pScreen); + KaaScreenPriv(pDrawable->pScreen); + + if (pScreenPriv->enabled && + (*pKaaScr->PrepareSolid) (pDrawable, GXcopy, FB_ALLONES, pixel)) + { + int nbox = REGION_NUM_RECTS (pRegion); + BoxPtr pBox = REGION_RECTS (pRegion); + + while (nbox--) + { + (*pKaaScr->Solid) (pBox->x1, pBox->y1, pBox->x2, pBox->y2); + pBox++; + } + (*pKaaScr->DoneSolid) (); + KdMarkSync(pDrawable->pScreen); + } + else + { + KdCheckSync (pDrawable->pScreen); + fbFillRegionSolid (pDrawable, pRegion, 0, + fbReplicatePixel (pixel, pDrawable->bitsPerPixel)); + } +} + +void +kaaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) +{ + PixmapPtr pTile; + + if (!REGION_NUM_RECTS(pRegion)) + return; + switch (what) { + case PW_BACKGROUND: + switch (pWin->backgroundState) { + case None: + return; + case ParentRelative: + do { + pWin = pWin->parent; + } while (pWin->backgroundState == ParentRelative); + (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion, + what); + return; + case BackgroundPixel: + kaaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel); + return; + } + break; + case PW_BORDER: + if (pWin->borderIsPixel) + { + kaaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel); + return; + } + break; + } + KdCheckPaintWindow (pWin, pRegion, what); +} + +Bool +kaaDrawInit (ScreenPtr pScreen, + KaaScreenPrivPtr pScreenPriv) +{ + if (kaaGeneration != serverGeneration) + { + kaaScreenPrivateIndex = AllocateScreenPrivateIndex(); + kaaGeneration = serverGeneration; + } + pScreen->devPrivates[kaaScreenPrivateIndex].ptr = (pointer) pScreenPriv; + + /* + * Hook up asynchronous drawing + */ + KdScreenInitAsync (pScreen); + /* + * Replace various fb screen functions + */ + pScreen->CreateGC = kaaCreateGC; + pScreen->CopyWindow = kaaCopyWindow; + pScreen->PaintWindowBackground = kaaPaintWindow; + pScreen->PaintWindowBorder = kaaPaintWindow; + + return TRUE; +} + diff --git a/xc/programs/Xserver/hw/kdrive/linux/ms.c b/xc/programs/Xserver/hw/kdrive/linux/ms.c new file mode 100644 index 000000000..9c30d2c38 --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/linux/ms.c @@ -0,0 +1,158 @@ +/* +Copyright (c) 2001 by Juliusz Chroboczek +Copyright (c) 1999 by Keith Packard + +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 +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. +*/ +/* $XFree86: xc/programs/Xserver/hw/kdrive/linux/ms.c,v 1.1 2001/08/09 20:45:15 dawes Exp $ */ + +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "kdrive.h" +#include "Xpoll.h" +#include <errno.h> +#include <termios.h> + +int +MsReadBytes (int fd, char *buf, int len, int min) +{ + int n, tot; + fd_set set; + struct timeval tv; + + tot = 0; + while (len) + { + n = read (fd, buf, len); + if (n > 0) + { + tot += n; + buf += n; + len -= n; + } + if (tot % min == 0) + break; + FD_ZERO (&set); + FD_SET (fd, &set); + tv.tv_sec = 0; + tv.tv_usec = 100 * 1000; + n = select (fd + 1, &set, 0, 0, &tv); + if (n <= 0) + break; + } + return tot; +} + +void +MsRead (int port) +{ + unsigned char buf[3 * 200]; + unsigned char *b; + int n; + int dx, dy; + unsigned long flags; + + while ((n = MsReadBytes (port, buf, sizeof (buf), 3)) > 0) + { + b = buf; + while (n >= 3) + { + flags = KD_MOUSE_DELTA; + + if (b[0] & 0x20) + flags |= KD_BUTTON_1; + if (b[0] & 0x10) + flags |= KD_BUTTON_3; + + dx = (char)(((b[0] & 0x03) << 6) | (b[1] & 0x3F)); + dy = (char)(((b[0] & 0x0C) << 4) | (b[2] & 0x3F)); + n -= 3; + b += 3; + KdEnqueueMouseEvent (flags, dx, dy); + } + } +} + +int +MsInit (void) +{ + int port; + char *device = "/dev/mouse"; + struct termios t; + int ret; + + port = open (device, O_RDWR | O_NONBLOCK); + if(port < 0) { + ErrorF("Couldn't open %s (%d)\n", device, (int)errno); + return 0; + } else if (port == 0) { + ErrorF("Opening %s returned 0! Please complain to Keith.\n", + device); + close(port); + return 0; + } + + if(!isatty(port)) { + ErrorF("%s is not a tty\n", device); + goto bail; + } + + ret = tcgetattr(port, &t); + if(ret < 0) { + ErrorF("Couldn't tcgetattr(%s): %d\n", device, errno); + goto bail; + } + t.c_iflag &= ~ (IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | + IGNCR | ICRNL | IXON | IXOFF); + t.c_oflag &= ~ OPOST; + t.c_lflag &= ~ (ECHO | ECHONL | ICANON | ISIG | IEXTEN); + t.c_cflag &= ~ (CSIZE | PARENB); + t.c_cflag |= CS8 | CLOCAL | CSTOPB; + + cfsetispeed (&t, B1200); + cfsetospeed (&t, B1200); + t.c_cc[VMIN] = 1; + t.c_cc[VTIME] = 0; + ret = tcsetattr(port, TCSANOW, &t); + if(ret < 0) { + ErrorF("Couldn't tcsetattr(%s): %d\n", device, errno); + goto bail; + } + return port; + + bail: + close(port); + return 0; +} + +void +MsFini (int port) +{ + if (port >= 0) + close(port); +} + +KdMouseFuncs MsMouseFuncs = { + MsInit, + MsRead, + MsFini +}; diff --git a/xc/programs/Xserver/hw/kdrive/mach64/Imakefile b/xc/programs/Xserver/hw/kdrive/mach64/Imakefile new file mode 100644 index 000000000..bd024c68b --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/mach64/Imakefile @@ -0,0 +1,20 @@ +XCOMM $XFree86: xc/programs/Xserver/hw/kdrive/mach64/Imakefile,v 1.2 2001/06/16 05:48:48 keithp Exp $ +KDRIVE=.. +#include "../Kdrive.tmpl" + +#if BuildXvExt +XVSRCS=mach64video.c +XVOBJS=mach64video.o +#endif + +SRCS = mach64.c mach64draw.c mach64stub.c $(XVSRCS) + +OBJS = mach64.o mach64draw.o mach64stub.o $(XVOBJS) + +DEFINES = XvExtensionDefines -DVESA /* -DUSE_PCI*/ + +INCLUDES = -I. $(KDINCS) -I$(KDRIVE)/vesa + +NormalLibraryObjectRule() +NormalLibraryTarget(mach64,$(OBJS)) +DependTarget() diff --git a/xc/programs/Xserver/hw/kdrive/mach64/mach64.c b/xc/programs/Xserver/hw/kdrive/mach64/mach64.c new file mode 100644 index 000000000..7df5c9d61 --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/mach64/mach64.c @@ -0,0 +1,450 @@ +/* + * Copyright © 2001 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. + */ +/* $XFree86: xc/programs/Xserver/hw/kdrive/mach64/mach64.c,v 1.8 2001/07/24 21:26:17 keithp Exp $ */ + +#include "mach64.h" +#include <sys/io.h> + +Bool +mach64CardInit (KdCardInfo *card) +{ + Mach64CardInfo *mach64c; + + mach64c = (Mach64CardInfo *) xalloc (sizeof (Mach64CardInfo)); + if (!mach64c) + return FALSE; + + (void) mach64MapReg (card, mach64c); + mach64c->lcdEnabled = FALSE; + + if (!vesaInitialize (card, &mach64c->vesa)) + { + xfree (mach64c); + return FALSE; + } + + card->driver = mach64c; + + return TRUE; +} + +Bool +mach64ScreenInit (KdScreenInfo *screen) +{ + Mach64CardInfo *mach64c = screen->card->driver; + Mach64ScreenInfo *mach64s; + int screen_size, memory; + + mach64s = (Mach64ScreenInfo *) xalloc (sizeof (Mach64ScreenInfo)); + if (!mach64s) + return FALSE; + memset (mach64s, '\0', sizeof (Mach64ScreenInfo)); + if (!vesaScreenInitialize (screen, &mach64s->vesa)) + { + xfree (mach64s); + return FALSE; + } + if (!mach64c->reg) + screen->dumb = TRUE; + if (mach64s->vesa.mapping != VESA_LINEAR) + screen->dumb = TRUE; + mach64s->screen = mach64s->vesa.fb; + switch (screen->fb[0].depth) { + case 8: + mach64s->colorKey = 0xff; + break; + case 15: + case 16: + mach64s->colorKey = 0x001e; + break; + case 24: + mach64s->colorKey = 0x0000fe; + break; + default: + mach64s->colorKey = 1; + break; + } + memory = mach64s->vesa.fb_size; + screen_size = screen->fb[0].byteStride * screen->height; + if (mach64s->screen && memory >= screen_size + 2048) + { + memory -= 2048; + mach64s->cursor_base = mach64s->screen + memory - 2048; + } + else + mach64s->cursor_base = 0; + screen->softCursor = TRUE; /* XXX for now */ + memory -= screen_size; + if (memory > screen->fb[0].byteStride) + { + mach64s->off_screen = mach64s->screen + screen_size; + mach64s->off_screen_size = memory; + } + else + { + mach64s->off_screen = 0; + mach64s->off_screen_size = 0; + } + screen->driver = mach64s; + return TRUE; +} + +Bool +mach64InitScreen (ScreenPtr pScreen) +{ +#ifdef XV + KdScreenPriv(pScreen); + Mach64CardInfo *mach64c = pScreenPriv->screen->card->driver; + if (mach64c->media_reg && mach64c->reg) + mach64InitVideo(pScreen); +#endif + return vesaInitScreen (pScreen); +} + +#ifdef RANDR +mach64RandRSetConfig (ScreenPtr pScreen, + Rotation rotation, + RRScreenSizePtr pSize, + RRVisualGroupPtr pVisualGroup) +{ + KdScreenPriv(pScreen); + + KdCheckSync (pScreen); + + if (!vesaRandRSetConfig (pScreen, rotation, pSize, pVisualGroup)) + return FALSE; + + return TRUE; +} + +void +mach64RandRInit (ScreenPtr pScreen) +{ + rrScrPriv(pScreen); + + pScrPriv->rrSetConfig = mach64RandRSetConfig; +} +#endif + +Bool +mach64FinishInitScreen (ScreenPtr pScreen) +{ + Bool ret; + ret = vesaFinishInitScreen (pScreen); +#ifdef RANDR + mach64RandRInit (pScreen); +#endif + return ret; +} + +CARD32 +mach64ReadLCD (Reg *reg, int id) +{ + CARD32 LCD_INDEX; + + LCD_INDEX = reg->LCD_INDEX & ~(0x3f); + reg->LCD_INDEX = (LCD_INDEX | id); + return reg->LCD_DATA; +} + +void +mach64WriteLCD (Reg *reg, int id, CARD32 data) +{ + CARD32 LCD_INDEX; + + LCD_INDEX = reg->LCD_INDEX & ~(0x3f); + reg->LCD_INDEX = (LCD_INDEX | id); + reg->LCD_DATA = data; +} + +void +mach64Preserve (KdCardInfo *card) +{ + Mach64CardInfo *mach64c = card->driver; + Reg *reg = mach64c->reg; + + vesaPreserve(card); + if (reg) + { + mach64c->save.LCD_GEN_CTRL = mach64ReadLCD (reg, 1); + } +} + +Bool +mach64MapReg (KdCardInfo *card, Mach64CardInfo *mach64c) +{ + mach64c->reg_base = (CARD8 *) KdMapDevice (MACH64_REG_BASE(card), + MACH64_REG_SIZE(card)); + + if (!mach64c->reg_base) + { + mach64c->reg = 0; + mach64c->media_reg = 0; + return FALSE; + } + + KdSetMappedMode (MACH64_REG_BASE(card), + MACH64_REG_SIZE(card), + KD_MAPPED_MODE_REGISTERS); + mach64c->reg = (Reg *) (mach64c->reg_base + MACH64_REG_OFF(card)); + mach64c->media_reg = (MediaReg *) (mach64c->reg_base + MACH64_MEDIA_REG_OFF(card)); + return TRUE; +} + +void +mach64UnmapReg (KdCardInfo *card, Mach64CardInfo *mach64c) +{ + if (mach64c->reg_base) + { + KdResetMappedMode (MACH64_REG_BASE(card), + MACH64_REG_SIZE(card), + KD_MAPPED_MODE_REGISTERS); + KdUnmapDevice ((void *) mach64c->reg_base, MACH64_REG_SIZE(card)); + mach64c->reg_base = 0; + mach64c->reg = 0; + mach64c->media_reg = 0; + } +} + +void +mach64SetMMIO (KdCardInfo *card, Mach64CardInfo *mach64c) +{ + if (!mach64c->reg_base) + mach64MapReg (card, mach64c); + if (mach64c->reg) + { + if (mach64c->reg->GUI_STAT == 0xffffffff) + FatalError ("Mach64 REG not visible\n"); + } +} + +void +mach64ResetMMIO (KdCardInfo *card, Mach64CardInfo *mach64c) +{ + mach64UnmapReg (card, mach64c); +} + +Bool +mach64Enable (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + Mach64CardInfo *mach64c = pScreenPriv->card->driver; + + if (!vesaEnable (pScreen)) + return FALSE; + + mach64SetMMIO (pScreenPriv->card, mach64c); + mach64DPMS (pScreen, KD_DPMS_NORMAL); +#ifdef XV + KdXVEnable (pScreen); +#endif + return TRUE; +} + +void +mach64Disable (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + Mach64CardInfo *mach64c = pScreenPriv->card->driver; + +#ifdef XV + KdXVDisable (pScreen); +#endif + mach64ResetMMIO (pScreenPriv->card, mach64c); + vesaDisable (pScreen); +} + +const CARD8 mach64DPMSModes[4] = { + 0x80, /* KD_DPMS_NORMAL */ + 0x8c, /* KD_DPMS_STANDBY */ + 0x8c, /* KD_DPMS_STANDBY */ + 0x8c, /* KD_DPMS_STANDBY */ +/* 0xb0, /* KD_DPMS_SUSPEND */ +/* 0xbc, /* KD_DPMS_POWERDOWN */ +}; + +#define PWR_MGT_ON (1 << 0) +#define PWR_MGT_MODE (3 << 1) +#define PWR_MGT_MODE_PIN (0 << 1) +#define PWR_MGT_MODE_REG (1 << 1) +#define PWR_MGT_MODE_TIMER (2 << 1) +#define PWR_MGR_MODE_PCI (3 << 1) +#define AUTO_PWRUP_EN (1 << 3) +#define ACTIVITY_PIN_ON (1 << 4) +#define STANDBY_POL (1 << 5) +#define SUSPEND_POL (1 << 6) +#define SELF_REFRESH (1 << 7) +#define ACTIVITY_PIN_EN (1 << 8) +#define KEYBD_SNOOP (1 << 9) +#define DONT_USE_F32KHZ (1 << 10) +#define TRISTATE_MEM_EN (1 << 11) +#define LCDENG_TEST_MODE (0xf << 12) +#define STANDBY_COUNT (0xf << 16) +#define SUSPEND_COUNT (0xf << 20) +#define BIASON (1 << 24) +#define BLON (1 << 25) +#define DIGON (1 << 26) +#define PM_D3_RST_ENB (1 << 27) +#define STANDBY_NOW (1 << 28) +#define SUSPEND_NOW (1 << 29) +#define PWR_MGT_STATUS (3 << 30) +#define PWR_MGT_STATUS_ON (0 << 30) +#define PWR_MGT_STATUS_STANDBY (1 << 30) +#define PWR_MGT_STATUS_SUSPEND (2 << 30) +#define PWR_MGT_STATUS_TRANSITION (3 << 30) + +Bool +mach64DPMS (ScreenPtr pScreen, int mode) +{ + KdScreenPriv(pScreen); + Mach64CardInfo *mach64c = pScreenPriv->card->driver; + int hsync_off, vsync_off, blank; + CARD32 CRTC_GEN_CNTL; + CARD32 LCD_GEN_CTRL; + Reg *reg = mach64c->reg; + + if (!reg) + return FALSE; + + CRTC_GEN_CNTL = reg->CRTC_GEN_CNTL; + LCD_GEN_CTRL = mach64ReadLCD (reg, 1); + + switch (mode) { + case KD_DPMS_NORMAL: + hsync_off = 0; + vsync_off = 0; + blank = 0; + break; + case KD_DPMS_STANDBY: + hsync_off = 1; + vsync_off = 0; + blank = 1; + break; + case KD_DPMS_SUSPEND: + hsync_off = 0; + vsync_off = 1; + blank = 1; + break; + case KD_DPMS_POWERDOWN: + hsync_off = 1; + vsync_off = 1; + blank = 1; + } + + if (hsync_off) + CRTC_GEN_CNTL |= (1 << 2); + else + CRTC_GEN_CNTL &= ~(1 << 2); + if (vsync_off) + CRTC_GEN_CNTL |= (1 << 3); + else + CRTC_GEN_CNTL &= ~(1 << 3); + if (blank) + { + mach64c->lcdEnabled = (LCD_GEN_CTRL & (1 << 1)) != 0; + LCD_GEN_CTRL &= ~(1 << 1); + CRTC_GEN_CNTL |= (1 << 6); + + } + else + { + if (!(LCD_GEN_CTRL & 3) || mach64c->lcdEnabled) + LCD_GEN_CTRL |= (1 << 1); + CRTC_GEN_CNTL &= ~(1 << 6); + } + + KdCheckSync (pScreen); + + mach64WriteLCD (reg, 1, LCD_GEN_CTRL); + + reg->CRTC_GEN_CNTL = CRTC_GEN_CNTL; + return TRUE; +} + +void +mach64Restore (KdCardInfo *card) +{ + Mach64CardInfo *mach64c = card->driver; + Reg *reg = mach64c->reg; + + if (reg) + { + mach64WriteLCD (reg, 1, mach64c->save.LCD_GEN_CTRL); + } + mach64ResetMMIO (card, mach64c); + vesaRestore (card); +} + +void +mach64ScreenFini (KdScreenInfo *screen) +{ + Mach64ScreenInfo *mach64s = (Mach64ScreenInfo *) screen->driver; + + vesaScreenFini (screen); + xfree (mach64s); + screen->driver = 0; +} + +void +mach64CardFini (KdCardInfo *card) +{ + Mach64CardInfo *mach64c = card->driver; + + mach64UnmapReg (card, mach64c); + vesaCardFini (card); +} + +#define mach64CursorInit 0 /* initCursor */ +#define mach64CursorEnable 0 /* enableCursor */ +#define mach64CursorDisable 0 /* disableCursor */ +#define mach64CursorFini 0 /* finiCursor */ +#define mach64RecolorCursor 0 /* recolorCursor */ + +KdCardFuncs mach64Funcs = { + mach64CardInit, /* cardinit */ + mach64ScreenInit, /* scrinit */ + mach64InitScreen, /* initScreen */ + mach64Preserve, /* preserve */ + mach64Enable, /* enable */ + mach64DPMS, /* dpms */ + mach64Disable, /* disable */ + mach64Restore, /* restore */ + mach64ScreenFini, /* scrfini */ + mach64CardFini, /* cardfini */ + + mach64CursorInit, /* initCursor */ + mach64CursorEnable, /* enableCursor */ + mach64CursorDisable, /* disableCursor */ + mach64CursorFini, /* finiCursor */ + mach64RecolorCursor, /* recolorCursor */ + + mach64DrawInit, /* initAccel */ + mach64DrawEnable, /* enableAccel */ + mach64DrawSync, /* syncAccel */ + mach64DrawDisable, /* disableAccel */ + mach64DrawFini, /* finiAccel */ + + vesaGetColors, /* getColors */ + vesaPutColors, /* putColors */ + + mach64FinishInitScreen, /* finishInitScreen */ +}; diff --git a/xc/programs/Xserver/hw/kdrive/mach64/mach64.h b/xc/programs/Xserver/hw/kdrive/mach64/mach64.h new file mode 100644 index 000000000..c54238604 --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/mach64/mach64.h @@ -0,0 +1,655 @@ +/* + * Id: mach64.h,v 1.2 1999/11/02 08:17:24 keithp Exp $ + * + * Copyright © 2001 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. + */ +/* $XFree86: xc/programs/Xserver/hw/kdrive/mach64/mach64.h,v 1.6 2001/07/24 19:06:03 keithp Exp $ */ + +#ifndef _MACH64_H_ +#define _MACH64_H_ +#include <vesa.h> +#include "kxv.h" + +/* + * offset from ioport beginning + */ + +#define MACH64_REG_BASE(c) ((c)->attr.address[1]) +#define MACH64_REG_SIZE(c) (4096) + +#define MACH64_REG_OFF(c) (1024) +#define MACH64_MEDIA_REG_OFF(c) (0) + +typedef volatile CARD8 VOL8; +typedef volatile CARD16 VOL16; +typedef volatile CARD32 VOL32; + +typedef struct _Reg { + VOL32 CRTC_H_TOTAL_DISP; /* 0x00 */ + VOL32 CRTC_H_SYNC_STRT_WID; /* 0x01 */ + VOL32 CRTC_V_TOTAL_DISP; /* 0x02 */ + VOL32 CRTC_V_SYNC_STRT_WID; /* 0x03 */ + VOL32 CRTC_VLINE_CRNT_VLINE; /* 0x04 */ + VOL32 CRTC_OFF_PITCH; /* 0x05 */ + VOL32 CRTC_INT_CNTL; /* 0x06 */ + VOL32 CRTC_GEN_CNTL; /* 0x07 */ + VOL32 DSP_CONFIG; /* 0x08 */ + VOL32 DSP_ON_OFF; /* 0x09 */ + VOL32 TIMER_CONFIG; /* 0x0a */ + VOL32 MEM_BUF_CNTL; /* 0x0b */ + VOL32 unused0; /* 0x0c */ + VOL32 MEM_ADDR_CONFIG; /* 0x0d */ + VOL32 CRT_TRAP; /* 0x0e */ + VOL32 I2C_CNTL_0; /* 0x0f */ + VOL32 OVR_CLR; /* 0x10 */ + VOL32 OVR_WID_LEFT_RIGHT; /* 0x11 */ + VOL32 OVR_WID_TOP_BOTTOM; /* 0x12 */ + VOL32 VGA_DSP_CONFIG; /* 0x13 */ + VOL32 VGA_DSP_ON_OFF; /* 0x14 */ + VOL32 DSP2_CONFIG; /* 0x15 */ + VOL32 DSP2_ON_OFF; /* 0x16 */ + VOL32 CRTC2_OFF_PITCH; /* 0x17 */ + VOL32 CUR_CLR0; /* 0x18 */ + VOL32 CUR_CLR1; /* 0x19 */ + VOL32 CUR_OFFSET; /* 0x1a */ + VOL32 CUR_HORZ_VERT_POSN; /* 0x1b */ + VOL32 CUR_HORZ_VERT_OFF; /* 0x1c */ + VOL32 TV_OUT_INDEX; /* 0x1d */ + VOL32 GP_IO; /* 0x1e */ + VOL32 HW_DEBUG; /* 0x1f */ + VOL32 SCRATCH_REG0; /* 0x20 */ + VOL32 SCRATCH_REG1; + VOL32 SCRATCH_REG2; + VOL32 SCRATCH_REG3; + VOL32 CLOCK_CNTL; + VOL32 CONFIG_STAT1; + VOL32 CONFIG_STAT2; + VOL32 TV_OUT_DATA; + VOL32 BUS_CNTL; /* 0x28 */ + VOL32 LCD_INDEX; /* 0x29 */ + VOL32 LCD_DATA; /* 0x2a */ + VOL32 EXT_MEM_CNTL; + VOL32 MEM_CNTL; + VOL32 MEM_VGA_WP_SEL; + VOL32 MEM_VGA_RP_SEL; + VOL32 I2C_CNTL_1; + VOL32 DAC_REGS; /* 0x30 */ + VOL32 DAC_CNTL; /* 0x31 */ + VOL32 unused_32; + VOL32 unused_33; + VOL32 GEN_TEST_CNTL; /* 0x34 */ + VOL32 CUSTOM_MACRO_CNTL; + VOL32 unused36; + VOL32 CONFIG_CNTL; + VOL32 CONFIG_CHIP_ID; + VOL32 CONFIG_STAT0; + VOL32 CRC_SIG; + VOL32 unused_3b; + VOL32 unused_3c; + VOL32 unused_3d; + VOL32 unused_3e; + VOL32 unused_3f; + VOL32 DST_OFF_PITCH; /* 0x40 */ + VOL32 DST_X; + VOL32 DST_Y; + VOL32 DST_Y_X; + VOL32 DST_WIDTH; + VOL32 DST_HEIGHT; + VOL32 DST_HEIGHT_WIDTH; + VOL32 DST_X_WIDTH; + VOL32 DST_BRES_LNTH; + VOL32 DST_BRES_ERR; + VOL32 DST_BRES_INC; + VOL32 DST_BRES_DEC; + VOL32 DST_CNTL; + VOL32 DST_Y_X_ALIAS; + VOL32 TRAIL_BRES_ERR; + VOL32 TRAIL_BRES_INC; + VOL32 TRAIL_BRES_DEC; + VOL32 LEAD_BRES_LNTH; + VOL32 Z_OFF_PITCH; + VOL32 Z_CNTL; + VOL32 ALPHA_TST_CNTL; + VOL32 unused55; + VOL32 SECONDARY_STW_EXP; + VOL32 SECONDARY_S_X_INC; + VOL32 SECONDARY_S_Y_INC; + VOL32 SECONDARY_S_START; + VOL32 SECONDARY_W_X_INC; + VOL32 SECONDARY_W_Y_INC; + VOL32 SECONDARY_W_START; + VOL32 SECONDARY_T_X_INC; + VOL32 SECONDARY_T_Y_INC; + VOL32 SECONDARY_T_START; + VOL32 SRC_OFF_PITCH; + VOL32 SRC_X; + VOL32 SRC_Y; + VOL32 SRC_Y_X; + VOL32 SRC_WIDTH1; + VOL32 SRC_HEIGHT1; + VOL32 SRC_HEIGHT1_WIDTH1; + VOL32 SRC_X_START; + VOL32 SRC_Y_START; + VOL32 SRC_Y_X_START; + VOL32 SRC_WIDTH2; + VOL32 SRC_HEIGHT2; + VOL32 SRC_HEIGHT2_WIDTH2; + VOL32 SRC_CNTL; + VOL32 unused6e; + VOL32 unused6f; + union { + struct { + VOL32 SCALE_OFF; /* 0x70 */ + VOL32 unused71; + VOL32 unused72; + VOL32 unused73; + VOL32 unused74; + VOL32 unused75; + VOL32 unused76; + VOL32 SCALE_WIDTH; + VOL32 SCALE_HEIGHT; + VOL32 unused79; + VOL32 unused7a; + VOL32 SCALE_PITCH; + VOL32 SCALE_X_INC; + VOL32 SCALE_Y_INC; + VOL32 SCALE_VACC; + VOL32 SCALE_3D_CNTL; /* 0x7f */ + } scaler; + struct { + VOL32 TEX_0_OFF; /* 0x70 */ + VOL32 TEX_1_OFF; + VOL32 TEX_2_OFF; + VOL32 TEX_3_OFF; + VOL32 TEX_4_OFF; + VOL32 TEX_5_OFF; + VOL32 TEX_6_OFF; + VOL32 TEX_7_OFF; + VOL32 TEX_8_OFF; + VOL32 TEX_9_OFF; + VOL32 TEX_10_OFF; + VOL32 S_Y_INC; + VOL32 RED_X_INC; + VOL32 GREEN_X_INC; /* 0x7d */ + VOL32 unused7e; + VOL32 unused7f; + } texture; + } u; + VOL32 HOST_DATA[16]; /* 0x80 */ + VOL32 HOST_CNTL; /* 0x90 */ + VOL32 BM_HOSTDATA; /* 0x91 */ + VOL32 BM_ADDR; /* 0x92 */ + VOL32 BM_GUI_TABLE_CMD; /* 0x93 */ + VOL32 unused94; /* 0x94 */ + VOL32 unused95; /* 0x95 */ + VOL32 unused96; /* 0x96 */ + VOL32 FOG_TABLE_INDEX; /* 0x97 */ + VOL32 FOG_TABLE_DATA[8]; /* 0x98 */ + VOL32 PAT_REG0; /* 0xa0 */ + VOL32 PAT_REG1; + VOL32 PAT_CNTL; + VOL32 unused_0a3; + VOL32 unused_0a4; + VOL32 unused_0a5; + VOL32 unused_0a6; + VOL32 unused_0a7; + VOL32 SC_LEFT; + VOL32 SC_RIGHT; + VOL32 SC_LEFT_RIGHT; + VOL32 SC_TOP; + VOL32 SC_BOTTOM; + VOL32 SC_TOP_BOTTOM; + VOL32 USR1_DST_OFF_PITCH; + VOL32 USR2_DST_OFF_PITCH; + VOL32 DP_BKGD_CLR; /* 0xb0 */ + VOL32 DP_FRGD_CLR; + VOL32 DP_WRITE_MSK; + VOL32 unused_0b3; + VOL32 DP_PIX_WIDTH; + VOL32 DP_MIX; + VOL32 DP_SRC; + VOL32 DP_FRGD_CLR_MIX; + VOL32 DP_FRGD_BKGD_CLR; + VOL32 unused_0b9; + VOL32 DST_X_Y; + VOL32 DST_WIDTH_HEIGHT; + VOL32 USR_DST_PITCH; + VOL32 unused_0bd; + VOL32 DP_SET_GUI_ENGINE2; + VOL32 DP_SET_GUI_ENGINE; + VOL32 CLR_CMP_CLR; /* 0xc0 */ + VOL32 CLR_CMP_MSK; + VOL32 CLR_CMP_CNTL; + VOL32 unused_0c3; + VOL32 FIFO_STAT; + VOL32 unused_0c5; + VOL32 unused_0c6; + VOL32 unused_0c7; + VOL32 unused_0c8; + VOL32 unused_0c9; + VOL32 unused_0ca; + VOL32 unused_0cb; + VOL32 GUI_TRAJ_CNTL; + VOL32 unused_0cd; + VOL32 GUI_STAT; + VOL32 unused_0cf; + VOL32 TEX_PALETTE_INDEX; + VOL32 STW_EXP; + VOL32 LOG_MAX_INC; + VOL32 S_X_INC; + VOL32 S_Y_INC_2_SCALE_PITCH; + VOL32 S_START; + VOL32 W_X_INC; + VOL32 W_Y_INC; + VOL32 W_START; + VOL32 T_X_INC; + VOL32 T_Y_INC_SECONDARY_SCALE_PITCH; + VOL32 T_START; + VOL32 TEX_SIZE_PITCH; + VOL32 TEX_CNTL; + VOL32 SECONDARY_TEX_OFFSET_SECONDARY_SCALE_OFF; + VOL32 TEX_PALETTE; + VOL32 SCALE_PITCH_BOTH; /* 0xe0 */ + VOL32 SECONDARY_SCALE_OFF_ACC; + VOL32 SCALE_OFF_ACC; + VOL32 SCALE_DST_Y_X; + VOL32 unused_0e4; + VOL32 unused_0e5; + VOL32 COMPOSITE_SHADOW_ID; + VOL32 SECONDARY_SCALE_X_INC_SPECULAR_RED_X_INC; + VOL32 SPECULAR_RED_Y_INC; + VOL32 SPECULAR_RED_START_SECONDARY_SCALE_HACC;; + VOL32 SPECULAR_GREEN_X_INC; + VOL32 SPECULAR_GREEN_Y_INC; + VOL32 SPECULAR_GREEN_START; + VOL32 SPECULAR_BLUE_X_INC; + VOL32 SPECULAR_BLUE_Y_INC; + VOL32 SPECULAR_BLUE_START; + VOL32 RED_X_INC_SCALE_X_INC; + VOL32 RED_Y_INC; + VOL32 RED_START_SCALE_HACC; + VOL32 GREEN_X_INC_SCALE_Y_INC; + VOL32 GREEN_Y_INC_SECONDARY_SCALE_Y_INC; + VOL32 GREEN_START_SECONDARY_SCALE_VACC; + VOL32 BLUE_X_INC; + VOL32 BLUE_Y_INC; + VOL32 BLUE_START; + VOL32 Z_X_INC; + VOL32 Z_Y_INC; + VOL32 Z_START; + VOL32 ALPHA_X_INC; + VOL32 FOG_X_INC; + VOL32 ALPHA_Y_INC; + VOL32 FOG_Y_INC; + VOL32 ALPHA_START; + VOL32 FOG_START; + VOL32 unused_0ff; +} Reg; /* 0x100 */ + +#define DST_X_DIR (1 << 0) +#define DST_Y_DIR (1 << 1) +#define DST_Y_MAJOR (1 << 2) +#define DST_X_TILE (1 << 3) +#define DST_Y_TILE (1 << 4) +#define DST_LAST_PEL (1 << 5) +#define DST_POLYGON_EN (1 << 6) +#define DST_24_ROT_EN (1 << 7) +#define DST_24_ROT(n) ((n) << 8) +#define DST_BRES_ZERO (1 << 11) +#define DST_POLYGON_RTEDGE_DIS (1 << 12) +#define TRAIL_X_DIR (1 << 13) +#define TRAP_FILL_DIR (1 << 14) +#define TRAIL_BRES_SIGN (1 << 15) +#define SRC_PATT_EN (1 << 16) +#define SRC_PATT_ROT_EN (1 << 17) +#define SRC_LINEAR_EN (1 << 18) +#define SRC_BYTE_ALIGN (1 << 19) +#define SRC_LINE_X_DIR (1 << 20) +#define SRC_8x8x8_BRUSH (1 << 21) +#define FAST_FILL_EN (1 << 22) +#define SRC_TRACK_DST (1 << 23) +#define PAT_MONO_EN (1 << 24) +#define PAT_CLR_4x2_EN (1 << 25) +#define PAT_CLR_8x1_EN (1 << 26) +#define HOST_BYTE_ALIGN (1 << 28) +#define HOST_BIG_ENDIAN_EN (1 << 29) + +/* BUS_CNTL bits */ +#define BUS_DBL_RESYNC (1 << 0) +#define BUS_MSTR_RESET (1 << 1) +#define BUS_FLUSH_BUF (1 << 2) +#define BUS_STOP_REQ_DIS (1 << 3) +#define BUS_APER_REG_DIS (1 << 4) +#define BUS_EXTRA_PIPE_DIS (1 << 5) +#define BUS_MASTER_DIS (1 << 6) +#define ROM_WRT_EN (1 << 7) +#define CHIP_HIDDEN_REV (3 << 8) +#define BUS_PCI_READ_RETRY_EN (1 << 13) +#define BUS_PCI_WRT_RETRY_EN (1 << 15) +#define BUS_RETRY_WS (0xf << 16) +#define BUS_MSTR_RD_MULT (1 << 20) +#define BUS_MSTR_RD_LINE (1 << 21) +#define BUS_SUSPEND (1 << 22) +#define LAT16X (1 << 23) +#define BUS_RD_DISCARD_EN (1 << 24) +#define BUS_RD_ABORT_EN (1 << 25) +#define BUS_MSTR_WS (1 << 26) +#define BUS_EXT_REG_EN (1 << 27) +#define BUS_MSTR_DISCONNECT_EN (1 << 28) +#define BUS_WRT_BURST (1 << 29) +#define BUS_READ_BURST (1 << 30) +#define BUS_RDY_READ_DLY (1 << 31) + +#define SCALE_PIX_EXPAND (1 << 0) +#define SCALE_Y2R_TEMP (1 << 1) +#define SCALE_HORZ_MODE (1 << 2) +#define SCALE_VERT_MODE (1 << 3) +#define SCALE_SIGNED_UV (1 << 4) +#define SCALE_GAMMA_SEL (3 << 5) +#define SCALE_GAMMA_BRIGHT (0 << 5) +#define SCALE_GAMMA_22 (1 << 5) +#define SCALE_GAMMA_18 (2 << 5) +#define SCALE_GAMMA_14 (3 << 5) +#define SCALE_DISP_SEL (1 << 7) +#define SCALE_BANDWIDTH (1 << 26) +#define SCALE_DIS_LIMIT (1 << 27) +#define SCALE_CLK_FORCE_ON (1 << 29) +#define SCALE_OVERLAY_EN (1 << 30) +#define SCALE_EN (1 << 31) + +#define VIDEO_IN_VYUY422 (0xb) +#define VIDEO_IN_YVYU422 (0xc) +#define SCALER_IN_15bpp (0x3 << 16) +#define SCALER_IN_16bpp (0x4 << 16) +#define SCALER_IN_32bpp (0x6 << 16) +#define SCALER_IN_YUV_9 (0x9 << 16) +#define SCALER_IN_YUV_12 (0xa << 16) +#define SCALER_IN_VYUY422 (0xb << 16) +#define SCALER_IN_YVYU422 (0xc << 16) + +#define CAP_INPUT_MODE (1 << 0) +#define CAP_BUF_MODE (1 << 2) +#define CAP_START_BUF (1 << 3) +#define CAP_BUF_TYPE_FIELD (0 << 4) +#define CAP_BUF_TYPE_ALTERNATING (1 << 4) +#define CAP_BUF_TYPE_FRAME (2 << 4) + +#define OVL_BUF_MODE (1 << 28) +#define OVL_BUF_NEXT (1 << 29) + +#define CAP_TRIGGER (3 << 0) +#define OVL_CUR_BUF (1 << 5) +#define OVL_BUF_STATUS (1 << 6) +#define CAP_BUF_STATUS (1 << 7) +#define CAPTURE_EN (1 << 31) + +typedef struct _MediaReg { + VOL32 OVERLAY_Y_X_START; /* 0x100 */ + VOL32 OVERLAY_Y_X_END; + VOL32 OVERLAY_VIDEO_KEY_CLR; + VOL32 OVERLAY_VIDEO_KEY_MSK; + VOL32 OVERLAY_GRAPHICS_KEY_CLR; + VOL32 OVERLAY_GRAPHICS_KEY_MSK; + VOL32 OVERLAY_KEY_CNTL; + VOL32 unused_107; + VOL32 OVERLAY_SCALE_INC; + VOL32 OVERLAY_SCALE_CNTL; + VOL32 SCALER_HEIGHT_WIDTH; + VOL32 SCALER_TEST; + VOL32 unused_10c; + VOL32 SCALER_BUF0_OFFSET; + VOL32 SCALER_BUF1_OFFSET; + VOL32 SCALER_BUF_PITCH; + VOL32 CAPTURE_START_END; /* 0x110 */ + VOL32 CAPTURE_X_WIDTH; + VOL32 VIDEO_FORMAT; + VOL32 VBI_START_END; + VOL32 CAPTURE_CONFIG; + VOL32 TRIG_CNTL; + VOL32 OVERLAY_EXCLUSIVE_HORZ; + VOL32 OVERLAY_EXCLUSIVE_VERT; + VOL32 VBI_WIDTH; + VOL32 CAPTURE_DEBUG; + VOL32 VIDEO_SYNC_TEST; + VOL32 unused_11b; + VOL32 SNAPSHOT_VH_COUNTS; + VOL32 SNAPSHOT_F_COUNT; + VOL32 N_VIF_COUNT; + VOL32 SNAPSHOT_VIF_COUNT; + VOL32 CAPTURE_BUF0_OFFSET; /* 0x120 */ + VOL32 CAPTURE_BUF1_OFFSET; + VOL32 ONESHOT_BUF_OFFSET; + VOL32 unused_123; + VOL32 unused_124; + VOL32 unused_125; + VOL32 unused_126; + VOL32 unused_127; + VOL32 unused_128; + VOL32 unused_129; + VOL32 unused_12a; + VOL32 unused_12b; + VOL32 SNAPSHOT2_VH_COUNTS; + VOL32 SNAPSHOT2_F_COUNT; + VOL32 N_VIF2_COUNT; + VOL32 SNAPSHOT2_VIF_COUNT; + VOL32 MPP_CONFIG; /* 0x130 */ + VOL32 MPP_STROBE_SEQ; + VOL32 MPP_ADDR; + VOL32 MPP_DATA; + VOL32 unused_134; + VOL32 unused_135; + VOL32 unused_136; + VOL32 unused_137; + VOL32 unused_138; + VOL32 unused_139; + VOL32 unused_13a; + VOL32 unused_13b; + VOL32 unused_13c; + VOL32 unused_13d; + VOL32 unused_13e; + VOL32 unused_13f; + VOL32 TVO_CNTL; /* 0x140 */ + VOL32 unused_141[15]; + VOL32 unused_150; /* 0x150 */ + VOL32 CRT_HORZ_VERT_LOAD; /* 0x151 */ + VOL32 AGP_BASE; /* 0x152 */ + VOL32 AGP_CNTL; /* 0x153 */ + VOL32 SCALER_COLOUR_CNTL; /* 0x154 */ + VOL32 SCALER_H_COEFF0; /* 0x155 */ + VOL32 SCALER_H_COEFF1; /* 0x156 */ + VOL32 SCALER_H_COEFF2; /* 0x157 */ + VOL32 SCALER_H_COEFF3; /* 0x158 */ + VOL32 SCALER_H_COEFF4; /* 0x159 */ + VOL32 unused_15a; + VOL32 unused_15b; + VOL32 GUI_CMDFIFO_DEBUG; + VOL32 GUI_CMDFIFO_DATA; + VOL32 GUI_CNTL; + VOL32 unused_15f; + VOL32 BM_FRAME_BUF_OFFSET; /* 0x160 */ + VOL32 BM_SYSTEM_MEM_ADDR; + VOL32 BM_COMMAND; + VOL32 BM_STATUS; + VOL32 unused_164[10]; + VOL32 BM_GUI_TABLE; + VOL32 BM_SYSTEM_TABLE; + VOL32 unused_170[5]; /* 0x170 */ + VOL32 SCALER_BUF0_OFFSET_U; + VOL32 SCALER_BUF0_OFFSET_V; + VOL32 SCALER_BUF1_OFFSET_U; + VOL32 SCALER_BUF1_OFFSET_V; + VOL32 unused_179[7]; + VOL32 unused_180[16]; /* 0x180 */ + VOL32 setup_engine[0x40]; /* 0x190 */ + VOL32 dvd_subpicture[0x30]; /* 0x1d0 */ +} MediaReg; + +#define MACH64_XY(x,y) (((x) & 0x7fff) | (((y) & 0x7fff) << 16)) +#define MACH64_YX(x,y) (((y) & 0x7fff) | (((x) & 0x7fff) << 16)) + +typedef struct _mach64Save { + CARD32 LCD_GEN_CTRL; +} Mach64Save; + +typedef struct _mach64CardInfo { + VesaCardPrivRec vesa; + CARD8 *reg_base; + Reg *reg; + MediaReg *media_reg; + Mach64Save save; + Bool lcdEnabled; +} Mach64CardInfo; + +#define getMach64CardInfo(kd) ((Mach64CardInfo *) ((kd)->card->driver)) +#define mach64CardInfo(kd) Mach64CardInfo *mach64c = getMach64CardInfo(kd) + +typedef struct _mach64Cursor { + int width, height; + int xhot, yhot; + Bool has_cursor; + CursorPtr pCursor; + Pixel source, mask; +} Mach64Cursor; + +#define MACH64_CURSOR_WIDTH 64 +#define MACH64_CURSOR_HEIGHT 64 + +/* + * Xv information, optional + */ +typedef struct _mach64PortPriv { + CARD32 YBuf0Offset; + + CARD32 YBuf1Offset; + + CARD8 currentBuf; + + int brightness; + int saturation; + + RegionRec clip; + CARD32 colorKey; + + Bool videoOn; + Time offTime; + Time freeTime; + CARD32 size; + CARD32 offset; +} Mach64PortPrivRec, *Mach64PortPrivPtr; + +Bool mach64InitVideo(ScreenPtr pScreen); + +typedef struct _mach64ScreenInfo { + VesaScreenPrivRec vesa; + CARD8 *cursor_base; + CARD8 *screen; + CARD8 *off_screen; + int off_screen_size; + CARD32 DP_PIX_WIDTH; + CARD32 DP_SET_GUI_ENGINE; + CARD32 USR1_DST_OFF_PITCH; + Bool bpp24; + Mach64Cursor cursor; + CARD32 colorKey; + KdVideoAdaptorPtr pAdaptor; +} Mach64ScreenInfo; + +#define getMach64ScreenInfo(kd) ((Mach64ScreenInfo *) ((kd)->screen->driver)) +#define mach64ScreenInfo(kd) Mach64ScreenInfo *mach64s = getMach64ScreenInfo(kd) + +CARD32 +mach64ReadLCD (Reg *reg, int id); + +void +mach64WriteLCD (Reg *reg, int id, CARD32 data); + +void +mach64Preserve (KdCardInfo *card); + +Bool +mach64MapReg (KdCardInfo *card, Mach64CardInfo *mach64c); + +void +mach64UnmapReg (KdCardInfo *card, Mach64CardInfo *mach64c); + +void +mach64SetMMIO (KdCardInfo *card, Mach64CardInfo *mach64c); + +void +mach64ResetMMIO (KdCardInfo *card, Mach64CardInfo *mach64c); + +Bool +mach64Enable (ScreenPtr pScreen); + +void +mach64Disable (ScreenPtr pScreen); + +void +mach64WaitAvail(Reg *reg, int n); + +void +mach64WaitIdle (Reg *reg); + +Bool +mach64DrawSetup (ScreenPtr pScreen); + +Bool +mach64DrawInit (ScreenPtr pScreen); + +void +mach64DrawReinit (ScreenPtr pScreen); + +void +mach64DrawEnable (ScreenPtr pScreen); + +void +mach64DrawSync (ScreenPtr pScreen); + +void +mach64DrawDisable (ScreenPtr pScreen); + +void +mach64DrawFini (ScreenPtr pScreen); + +CARD8 +mach64ReadIndex (Mach64CardInfo *mach64c, CARD16 port, CARD8 index); + +void +mach64WriteIndex (Mach64CardInfo *mach64c, CARD16 port, CARD8 index, CARD8 value); + +Bool +mach64CursorInit (ScreenPtr pScreen); + +void +mach64CursorEnable (ScreenPtr pScreen); + +void +mach64CursorDisable (ScreenPtr pScreen); + +void +mach64CursorFini (ScreenPtr pScreen); + +void +mach64RecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdef); + +extern KdCardFuncs mach64Funcs; + +#endif /* _MACH64_H_ */ diff --git a/xc/programs/Xserver/hw/kdrive/mach64/mach64curs.c b/xc/programs/Xserver/hw/kdrive/mach64/mach64curs.c new file mode 100644 index 000000000..fd0bdf76d --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/mach64/mach64curs.c @@ -0,0 +1,389 @@ +/* + * Id: tridentcurs.c,v 1.1 1999/11/02 03:54:47 keithp Exp $ + * + * Copyright © 1999 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. + */ +/* $XFree86: xc/programs/Xserver/hw/kdrive/mach64/mach64curs.c,v 1.1 2001/06/03 18:48:19 keithp Exp $ */ + +#include "trident.h" +#include "cursorstr.h" + +#define SetupCursor(s) KdScreenPriv(s); \ + tridentCardInfo(pScreenPriv); \ + tridentScreenInfo(pScreenPriv); \ + TridentCursor *pCurPriv = &tridents->cursor + +static void +_tridentMoveCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor(pScreen); + CARD8 xlow, xhigh, ylow, yhigh; + CARD8 xoff, yoff; + + x -= pCurPriv->xhot; + xoff = 0; + if (x < 0) + { + xoff = -x; + x = 0; + } + y -= pCurPriv->yhot; + yoff = 0; + if (y < 0) + { + yoff = -y; + y = 0; + } + xlow = (CARD8) x; + xhigh = (CARD8) (x >> 8); + ylow = (CARD8) y; + yhigh = (CARD8) (y >> 8); + + + /* This is the recommended order to move the cursor */ + + tridentWriteIndex (tridentc, 0x3d4, 0x41, xhigh); + tridentWriteIndex (tridentc, 0x3d4, 0x40, xlow); + tridentWriteIndex (tridentc, 0x3d4, 0x42, ylow); + tridentWriteIndex (tridentc, 0x3d4, 0x46, xoff); + tridentWriteIndex (tridentc, 0x3d4, 0x47, yoff); + tridentWriteIndex (tridentc, 0x3d4, 0x43, yhigh); +} + +static void +tridentMoveCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor (pScreen); + + if (!pCurPriv->has_cursor) + return; + + if (!pScreenPriv->enabled) + return; + + _tridentMoveCursor (pScreen, x, y); +} + +static void +tridentAllocCursorColors (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + + KdAllocateCursorPixels (pScreen, 0, pCursor, + &pCurPriv->source, &pCurPriv->mask); + switch (pScreenPriv->screen->fb[0].bitsPerPixel) { + case 4: + pCurPriv->source |= pCurPriv->source << 4; + pCurPriv->mask |= pCurPriv->mask << 4; + case 8: + pCurPriv->source |= pCurPriv->source << 8; + pCurPriv->mask |= pCurPriv->mask << 8; + case 16: + pCurPriv->source |= pCurPriv->source << 16; + pCurPriv->mask |= pCurPriv->mask << 16; + } +} + +static void +tridentSetCursorColors (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + CARD32 fg, bg; + + fg = pCurPriv->source; + bg = pCurPriv->mask; + tridentWriteIndex (tridentc, 0x3d4, 0x48, fg); + tridentWriteIndex (tridentc, 0x3d4, 0x49, fg >> 8); + tridentWriteIndex (tridentc, 0x3d4, 0x4a, fg >> 16); + + tridentWriteIndex (tridentc, 0x3d4, 0x4c, bg); + tridentWriteIndex (tridentc, 0x3d4, 0x4d, bg >> 8); + tridentWriteIndex (tridentc, 0x3d4, 0x4e, bg >> 16); +} + +void +tridentRecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdef) +{ + SetupCursor (pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + xColorItem sourceColor, maskColor; + + if (!pCurPriv->has_cursor || !pCursor) + return; + + if (!pScreenPriv->enabled) + return; + + if (pdef) + { + while (ndef) + { + if (pdef->pixel == pCurPriv->source || + pdef->pixel == pCurPriv->mask) + break; + ndef--; + } + if (!ndef) + return; + } + tridentAllocCursorColors (pScreen); + tridentSetCursorColors (pScreen); +} + +#define InvertBits32(v) { \ + v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555); \ + v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333); \ + v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f); \ +} + +static void +tridentLoadCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor(pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + CursorBitsPtr bits = pCursor->bits; + int w, h; + CARD32 *ram, *msk, *mskLine, *src, *srcLine; + int i, j; + int cursor_address; + int lwsrc; + unsigned char ramdac_control_; + CARD32 offset; + + /* + * Allocate new colors + */ + tridentAllocCursorColors (pScreen); + + pCurPriv->pCursor = pCursor; + pCurPriv->xhot = pCursor->bits->xhot; + pCurPriv->yhot = pCursor->bits->yhot; + + /* + * Stick new image into cursor memory + */ + ram = (CARD32 *) tridents->cursor_base; + mskLine = (CARD32 *) bits->mask; + srcLine = (CARD32 *) bits->source; + + h = bits->height; + if (h > TRIDENT_CURSOR_HEIGHT) + h = TRIDENT_CURSOR_HEIGHT; + + lwsrc = BitmapBytePad(bits->width) / 4; /* words per line */ + + for (i = 0; i < TRIDENT_CURSOR_HEIGHT; i++) { + msk = mskLine; + src = srcLine; + mskLine += lwsrc; + srcLine += lwsrc; + for (j = 0; j < TRIDENT_CURSOR_WIDTH / 32; j++) { + + CARD32 m, s; + +#if 1 + if (i < h && j < lwsrc) + { + m = *msk++; + s = *src++; + InvertBits32(m); + InvertBits32(s); + } + else + { + m = 0; + s = 0; + } +#endif + *ram++ = m; + *ram++ = s; + } + } + + /* Set address for cursor bits */ + offset = tridents->cursor_base - (CARD8 *) tridents->screen; + offset >>= 10; + tridentWriteIndex (tridentc, 0x3d4, 0x44, (CARD8) (offset & 0xff)); + tridentWriteIndex (tridentc, 0x3d4, 0x45, (CARD8) (offset >> 8)); + + /* Set new color */ + tridentSetCursorColors (pScreen); + + /* Enable the cursor */ + tridentWriteIndex (tridentc, 0x3d4, 0x50, 0xc1); + + /* Move to new position */ + tridentMoveCursor (pScreen, x, y); +} + +static void +tridentUnloadCursor (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + /* Disable cursor */ + tridentWriteIndex (tridentc, 0x3d4, 0x50, 0); +} + +static Bool +tridentRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +{ + SetupCursor(pScreen); + + if (!pScreenPriv->enabled) + return TRUE; + + /* miRecolorCursor does this */ + if (pCurPriv->pCursor == pCursor) + { + if (pCursor) + { + int x, y; + + miPointerPosition (&x, &y); + tridentLoadCursor (pScreen, x, y); + } + } + return TRUE; +} + +static Bool +tridentUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +{ + return TRUE; +} + +static void +tridentSetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y) +{ + SetupCursor(pScreen); + + pCurPriv->pCursor = pCursor; + + if (!pScreenPriv->enabled) + return; + + if (pCursor) + tridentLoadCursor (pScreen, x, y); + else + tridentUnloadCursor (pScreen); +} + +miPointerSpriteFuncRec tridentPointerSpriteFuncs = { + tridentRealizeCursor, + tridentUnrealizeCursor, + tridentSetCursor, + tridentMoveCursor, +}; + +static void +tridentQueryBestSize (int class, + unsigned short *pwidth, unsigned short *pheight, + ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + switch (class) + { + case CursorShape: + if (*pwidth > pCurPriv->width) + *pwidth = pCurPriv->width; + if (*pheight > pCurPriv->height) + *pheight = pCurPriv->height; + if (*pwidth > pScreen->width) + *pwidth = pScreen->width; + if (*pheight > pScreen->height) + *pheight = pScreen->height; + break; + default: + fbQueryBestSize (class, pwidth, pheight, pScreen); + break; + } +} + +Bool +tridentCursorInit (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (!tridents->cursor_base) + { + pCurPriv->has_cursor = FALSE; + return FALSE; + } + + pCurPriv->width = TRIDENT_CURSOR_WIDTH; + pCurPriv->height= TRIDENT_CURSOR_HEIGHT; + pScreen->QueryBestSize = tridentQueryBestSize; + miPointerInitialize (pScreen, + &tridentPointerSpriteFuncs, + &kdPointerScreenFuncs, + FALSE); + pCurPriv->has_cursor = TRUE; + pCurPriv->pCursor = NULL; + return TRUE; +} + +void +tridentCursorEnable (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (pCurPriv->has_cursor) + { + if (pCurPriv->pCursor) + { + int x, y; + + miPointerPosition (&x, &y); + tridentLoadCursor (pScreen, x, y); + } + else + tridentUnloadCursor (pScreen); + } +} + +void +tridentCursorDisable (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (!pScreenPriv->enabled) + return; + + if (pCurPriv->has_cursor) + { + if (pCurPriv->pCursor) + { + tridentUnloadCursor (pScreen); + } + } +} + +void +tridentCursorFini (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + pCurPriv->pCursor = NULL; +} diff --git a/xc/programs/Xserver/hw/kdrive/mach64/mach64draw.c b/xc/programs/Xserver/hw/kdrive/mach64/mach64draw.c new file mode 100644 index 000000000..6bd9d0d53 --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/mach64/mach64draw.c @@ -0,0 +1,420 @@ +/* + * Id: mach64draw.c,v 1.1 1999/11/02 03:54:47 keithp Exp $ + * + * Copyright © 1999 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. + */ +/* $XFree86: xc/programs/Xserver/hw/kdrive/mach64/mach64draw.c,v 1.7 2001/07/24 19:06:03 keithp Exp $ */ + +#include "mach64.h" +#include "mach64draw.h" + +#include "Xmd.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "mistruct.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "fb.h" +#include "migc.h" +#include "miline.h" +#include "picturestr.h" + +CARD8 mach64Rop[16] = { + /* GXclear */ 0x01, /* 0 */ + /* GXand */ 0x0c, /* src AND dst */ + /* GXandReverse */ 0x0d, /* src AND NOT dst */ + /* GXcopy */ 0x07, /* src */ + /* GXandInverted*/ 0x0e, /* NOT src AND dst */ + /* GXnoop */ 0x03, /* dst */ + /* GXxor */ 0x05, /* src XOR dst */ + /* GXor */ 0x0b, /* src OR dst */ + /* GXnor */ 0x0f, /* NOT src AND NOT dst */ + /* GXequiv */ 0x06, /* NOT src XOR dst */ + /* GXinvert */ 0x00, /* NOT dst */ + /* GXorReverse */ 0x0a, /* src OR NOT dst */ + /* GXcopyInverted*/ 0x04, /* NOT src */ + /* GXorInverted */ 0x09, /* NOT src OR dst */ + /* GXnand */ 0x08, /* NOT src OR NOT dst */ + /* GXset */ 0x02, /* 1 */ +}; + +#define MACH64_DRAW_COMBO_SOLID 0x1 +#define MACH64_DRAW_COMBO_COPY 0x8 + +static Reg *reg; +static CARD32 cmd; +static CARD32 avail; +static CARD32 triple; +static CARD32 combo; + +#define IDX(reg,n) (&(reg)->n - &(reg)->CRTC_H_TOTAL_DISP) + +void +mach64WaitAvail(Reg *reg, int n) +{ + if (avail < n) + { + while ((avail = ((reg->GUI_STAT) >> 16) & 0x3ff) < n) + ; + } + avail -= n; +} + +void +mach64WaitIdle (Reg *reg) +{ + while (reg->GUI_STAT & 1) + ; +} + +static Bool +mach64Setup (ScreenPtr pScreen, CARD32 combo, int wait) +{ + KdScreenPriv(pScreen); + mach64ScreenInfo(pScreenPriv); + mach64CardInfo(pScreenPriv); + + avail = 0; + reg = mach64c->reg; + triple = mach64s->bpp24; + if (!reg) + return FALSE; + + mach64WaitAvail(reg, wait + 3); + reg->DP_PIX_WIDTH = mach64s->DP_PIX_WIDTH; + reg->USR1_DST_OFF_PITCH = mach64s->USR1_DST_OFF_PITCH; + reg->DP_SET_GUI_ENGINE = mach64s->DP_SET_GUI_ENGINE | (combo << 20); + return TRUE; +} + +Bool +mach64PrepareSolid (DrawablePtr pDrawable, + int alu, + Pixel pm, + Pixel fg) +{ + if (!mach64Setup (pDrawable->pScreen, 1, 3)) + return FALSE; + reg->DP_MIX = (mach64Rop[alu] << 16) | 0; + reg->DP_WRITE_MSK = pm; + reg->DP_FRGD_CLR = fg; + return TRUE; +} + +void +mach64Solid (int x1, int y1, int x2, int y2) +{ + if (triple) + { + CARD32 traj; + + x1 *= 3; + x2 *= 3; + + traj = (DST_X_DIR | + DST_Y_DIR | + DST_24_ROT_EN | + DST_24_ROT((x1 / 4) % 6)); + mach64WaitAvail (reg, 1); + reg->GUI_TRAJ_CNTL = traj; + } + mach64WaitAvail(reg,2); + reg->DST_X_Y = MACH64_XY(x1,y1); + reg->DST_WIDTH_HEIGHT = MACH64_XY(x2-x1,y2-y1); +} + +void +mach64DoneSolid (void) +{ +} + +static int copyDx; +static int copyDy; + +Bool +mach64PrepareCopy (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + int dx, + int dy, + int alu, + Pixel pm) +{ + CARD32 combo = 8; + + if ((copyDx = dx) > 0) + combo |= 1; + if ((copyDy = dy) > 0) + combo |= 2; + if (!mach64Setup (pDstDrawable->pScreen, combo, 2)) + return FALSE; + + reg->DP_MIX = (mach64Rop[alu] << 16) | 0; + reg->DP_WRITE_MSK = pm; + return TRUE; +} + +void +mach64Copy (int srcX, + int srcY, + int dstX, + int dstY, + int w, + int h) +{ + if (triple) + { + CARD32 traj; + + srcX *= 3; + dstX *= 3; + w *= 3; + + traj = DST_24_ROT_EN | DST_24_ROT((dstX / 4) % 6); + + if (copyDx > 0) + traj |= 1; + if (copyDy > 0) + traj |= 2; + + mach64WaitAvail (reg, 1); + reg->GUI_TRAJ_CNTL = traj; + } + if (copyDx <= 0) + { + srcX += w - 1; + dstX += w - 1; + } + if (copyDy <= 0) + { + srcY += h - 1; + dstY += h - 1; + } + mach64WaitAvail (reg, 4); + reg->SRC_Y_X = MACH64_YX(srcX, srcY); + reg->SRC_WIDTH1 = w; + reg->DST_Y_X = MACH64_YX(dstX, dstY); + reg->DST_HEIGHT_WIDTH = MACH64_YX(w,h); +} + +void +mach64DoneCopy (void) +{ +} + +KaaScreenPrivRec mach64Kaa = { + mach64PrepareSolid, + mach64Solid, + mach64DoneSolid, + + mach64PrepareCopy, + mach64Copy, + mach64DoneCopy, +}; + +Bool +mach64DrawInit (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + + if (pScreenPriv->screen->fb[0].depth == 4) + return FALSE; + + if (!kaaDrawInit (pScreen, &mach64Kaa)) + return FALSE; + + return TRUE; +} + +#define PIX_FORMAT_MONO 0 +#define PIX_FORMAT_PSEUDO_8 2 +#define PIX_FORMAT_TRUE_1555 3 +#define PIX_FORMAT_TRUE_565 4 +#define PIX_FORMAT_TRUE_8888 6 +#define PIX_FORMAT_TRUE_332 7 +#define PIX_FORMAT_GRAY_8 8 +#define PIX_FORMAT_YUV_422 0xb +#define PIX_FORMAT_YUV_444 0xe +#define PIX_FORMAT_TRUE_4444 0xf + +void +mach64DrawEnable (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + mach64ScreenInfo(pScreenPriv); + CARD32 DP_PIX_WIDTH; + CARD32 DP_SET_GUI_ENGINE; + CARD32 SET_DP_DST_PIX_WIDTH; + CARD32 DST1_PITCH; + + mach64s->bpp24 = FALSE; + switch (pScreenPriv->screen->fb[0].depth) { + case 1: + DP_PIX_WIDTH = ((PIX_FORMAT_MONO << 0) | /* DP_DST_PIX_WIDTH */ + (PIX_FORMAT_TRUE_8888 << 4) | /* COMPOSITE_PIX_WIDTH */ + (PIX_FORMAT_MONO << 8) | /* DP_SRC_PIX_WIDTH */ + (0 << 13) | /* DP_HOST_TRIPLE_EN */ + (0 << 14) | /* DP_PALETTE_TYPE */ + (PIX_FORMAT_MONO << 16) | /* DP_HOST_PIX_WIDTH */ + (0 << 20) | /* DP_C14_RGB_INDEX */ + (0 << 24) | /* DP_BYTE_PIX_ORDER */ + (0 << 25) | /* DP_CONVERSION_TEMP */ + (0 << 26) | /* DP_C14_RGB_LOW_NIBBLE */ + (0 << 27) | /* DP_C14_RGB_HIGH_NIBBLE */ + (PIX_FORMAT_TRUE_8888 << 28) | /* DP_SCALE_PIX_WIDTH */ + 0); + SET_DP_DST_PIX_WIDTH = PIX_FORMAT_MONO; + break; + case 4: + FatalError ("mach64 can't accelerate 4bpp"); + break; + case 8: + DP_PIX_WIDTH = ((PIX_FORMAT_PSEUDO_8 << 0) | /* DP_DST_PIX_WIDTH */ + (PIX_FORMAT_TRUE_8888 << 4) | /* COMPOSITE_PIX_WIDTH */ + (PIX_FORMAT_PSEUDO_8 << 8) | /* DP_SRC_PIX_WIDTH */ + (0 << 13) | /* DP_HOST_TRIPLE_EN */ + (0 << 14) | /* DP_PALETTE_TYPE */ + (PIX_FORMAT_PSEUDO_8 << 16) | /* DP_HOST_PIX_WIDTH */ + (0 << 20) | /* DP_C14_RGB_INDEX */ + (0 << 24) | /* DP_BYTE_PIX_ORDER */ + (0 << 25) | /* DP_CONVERSION_TEMP */ + (0 << 26) | /* DP_C14_RGB_LOW_NIBBLE */ + (0 << 27) | /* DP_C14_RGB_HIGH_NIBBLE */ + (PIX_FORMAT_TRUE_8888 << 28) | /* DP_SCALE_PIX_WIDTH */ + 0); + SET_DP_DST_PIX_WIDTH = PIX_FORMAT_PSEUDO_8; + break; + case 15: + DP_PIX_WIDTH = ((PIX_FORMAT_TRUE_1555 << 0) | /* DP_DST_PIX_WIDTH */ + (PIX_FORMAT_TRUE_8888 << 4) | /* COMPOSITE_PIX_WIDTH */ + (PIX_FORMAT_TRUE_1555 << 8) | /* DP_SRC_PIX_WIDTH */ + (0 << 13) | /* DP_HOST_TRIPLE_EN */ + (0 << 14) | /* DP_PALETTE_TYPE */ + (PIX_FORMAT_TRUE_1555 << 16) | /* DP_HOST_PIX_WIDTH */ + (0 << 20) | /* DP_C14_RGB_INDEX */ + (0 << 24) | /* DP_BYTE_PIX_ORDER */ + (0 << 25) | /* DP_CONVERSION_TEMP */ + (0 << 26) | /* DP_C14_RGB_LOW_NIBBLE */ + (0 << 27) | /* DP_C14_RGB_HIGH_NIBBLE */ + (PIX_FORMAT_TRUE_8888 << 28) | /* DP_SCALE_PIX_WIDTH */ + 0); + SET_DP_DST_PIX_WIDTH = PIX_FORMAT_TRUE_1555; + break; + case 16: + DP_PIX_WIDTH = ((PIX_FORMAT_TRUE_565 << 0) | /* DP_DST_PIX_WIDTH */ + (PIX_FORMAT_TRUE_8888 << 4) | /* COMPOSITE_PIX_WIDTH */ + (PIX_FORMAT_TRUE_565 << 8) | /* DP_SRC_PIX_WIDTH */ + (0 << 13) | /* DP_HOST_TRIPLE_EN */ + (0 << 14) | /* DP_PALETTE_TYPE */ + (PIX_FORMAT_TRUE_565 << 16) | /* DP_HOST_PIX_WIDTH */ + (0 << 20) | /* DP_C14_RGB_INDEX */ + (0 << 24) | /* DP_BYTE_PIX_ORDER */ + (0 << 25) | /* DP_CONVERSION_TEMP */ + (0 << 26) | /* DP_C14_RGB_LOW_NIBBLE */ + (0 << 27) | /* DP_C14_RGB_HIGH_NIBBLE */ + (PIX_FORMAT_TRUE_8888 << 28) | /* DP_SCALE_PIX_WIDTH */ + 0); + SET_DP_DST_PIX_WIDTH = PIX_FORMAT_TRUE_565; + break; + case 24: + if (pScreenPriv->screen->fb[0].bitsPerPixel == 24) + { + mach64s->bpp24 = TRUE; + DP_PIX_WIDTH = ((PIX_FORMAT_PSEUDO_8 << 0) | /* DP_DST_PIX_WIDTH */ + (PIX_FORMAT_PSEUDO_8 << 4) | /* COMPOSITE_PIX_WIDTH */ + (PIX_FORMAT_PSEUDO_8 << 8) | /* DP_SRC_PIX_WIDTH */ + (0 << 13) | /* DP_HOST_TRIPLE_EN */ + (0 << 14) | /* DP_PALETTE_TYPE */ + (PIX_FORMAT_PSEUDO_8 << 16) | /* DP_HOST_PIX_WIDTH */ + (0 << 20) | /* DP_C14_RGB_INDEX */ + (0 << 24) | /* DP_BYTE_PIX_ORDER */ + (0 << 25) | /* DP_CONVERSION_TEMP */ + (0 << 26) | /* DP_C14_RGB_LOW_NIBBLE */ + (0 << 27) | /* DP_C14_RGB_HIGH_NIBBLE */ + (PIX_FORMAT_TRUE_8888 << 28) | /* DP_SCALE_PIX_WIDTH */ + 0); + SET_DP_DST_PIX_WIDTH = PIX_FORMAT_PSEUDO_8; + } + else + { + DP_PIX_WIDTH = ((PIX_FORMAT_TRUE_8888 << 0) | /* DP_DST_PIX_WIDTH */ + (PIX_FORMAT_TRUE_8888 << 4) | /* COMPOSITE_PIX_WIDTH */ + (PIX_FORMAT_TRUE_8888 << 8) | /* DP_SRC_PIX_WIDTH */ + (0 << 13) | /* DP_HOST_TRIPLE_EN */ + (0 << 14) | /* DP_PALETTE_TYPE */ + (PIX_FORMAT_TRUE_8888 << 16) | /* DP_HOST_PIX_WIDTH */ + (0 << 20) | /* DP_C14_RGB_INDEX */ + (0 << 24) | /* DP_BYTE_PIX_ORDER */ + (0 << 25) | /* DP_CONVERSION_TEMP */ + (0 << 26) | /* DP_C14_RGB_LOW_NIBBLE */ + (0 << 27) | /* DP_C14_RGB_HIGH_NIBBLE */ + (PIX_FORMAT_TRUE_8888 << 28) | /* DP_SCALE_PIX_WIDTH */ + 0); + SET_DP_DST_PIX_WIDTH = PIX_FORMAT_TRUE_8888; + } + break; + } + + mach64s->DP_PIX_WIDTH = DP_PIX_WIDTH; + DST1_PITCH = (pScreenPriv->screen->fb[0].pixelStride) >> 3; + if (mach64s->bpp24) + DST1_PITCH *= 3; + mach64s->USR1_DST_OFF_PITCH = ((0 << 0) | /* USR1_DST_OFFSET */ + (DST1_PITCH << 22) | /* USR1_DST_PITCH */ + 0); + mach64s->DP_SET_GUI_ENGINE = ((SET_DP_DST_PIX_WIDTH << 3) | + (1 << 6) | /* SET_DP_SRC_PIX_WIDTH */ + (0 << 7) | /* SET_DST_OFFSET */ + (0 << 10) | /* SET_DST_PITCH */ + (0 << 14) | /* SET_DST_PITCH_BY_2 */ + (1 << 15) | /* SET_SRC_OFFPITCH_COPY */ + (0 << 16) | /* SET_SRC_HGTWID1_2 */ + (0 << 20) | /* SET_DRAWING_COMBO */ + (1 << 24) | /* SET_BUS_MASTER_OP */ + (0 << 26) | /* SET_BUS_MASTER_EN */ + (0 << 27) | /* SET_BUS_MASTER_SYNC */ + (0 << 28) | /* DP_HOST_TRIPLE_EN */ + (0 << 29) | /* FAST_FILL_EN */ + (0 << 30) | /* BLOCK_WRITE_EN */ + 0); + KdMarkSync (pScreen); +} + +void +mach64DrawDisable (ScreenPtr pScreen) +{ +} + +void +mach64DrawFini (ScreenPtr pScreen) +{ +} + +void +mach64DrawSync (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + mach64CardInfo(pScreenPriv); + reg = mach64c->reg; + + mach64WaitIdle (reg); +} diff --git a/xc/programs/Xserver/hw/kdrive/mach64/mach64draw.h b/xc/programs/Xserver/hw/kdrive/mach64/mach64draw.h new file mode 100644 index 000000000..1a7e4cf73 --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/mach64/mach64draw.h @@ -0,0 +1,72 @@ +/* + * Id: tridentdraw.h,v 1.1 1999/11/02 03:54:47 keithp Exp $ + * + * Copyright © 1999 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. + */ +/* $XFree86: xc/programs/Xserver/hw/kdrive/mach64/mach64draw.h,v 1.1 2001/06/03 18:48:19 keithp Exp $ */ + +#ifndef _TRIDENTDRAW_H_ +#define _TRIDENTDRAW_H_ + +#define SetupTrident(s) KdScreenPriv(s); \ + tridentCardInfo(pScreenPriv); \ + Cop *cop = tridentc->cop + +#define TridentAlpha (COP_MULTI_ALPHA|COP_ALPHA_WRITE_ENABLE) + +#define _tridentInit(cop,tridentc) { \ + if ((cop)->status == 0xffffffff) tridentSetMMIO(tridentc); \ + (cop)->multi = (tridentc)->cop_depth; \ + (cop)->multi = (tridentc)->cop_stride; \ + (cop)->multi = TridentAlpha; \ +} \ + +#define _tridentSetSolidRect(cop,pix,alu,cmd) {\ + cop->multi = COP_MULTI_PATTERN; \ + cop->multi = COP_MULTI_ROP | tridentRop[alu]; \ + cop->fg = (pix); \ + cmd = COP_OP_BLT | COP_SCL_OPAQUE | COP_OP_ROP | COP_OP_FG; \ +} + +#define _tridentRect(cop,x1,y1,x2,y2,cmd) { \ + (cop)->dst_start_xy = TRI_XY (x1,y1); \ + (cop)->dst_end_xy = TRI_XY(x2,y2); \ + _tridentWaitDone(cop); \ + (cop)->command = (cmd); \ +} + +#define COP_STATUS_BUSY (COP_STATUS_BE_BUSY | \ + COP_STATUS_DPE_BUSY | \ + COP_STATUS_MI_BUSY) + +#define _tridentWaitDone(cop) { \ + int __q__ = 500000; \ + while (__q__-- && (cop)->status & COP_STATUS_BUSY) \ + ; \ + if (!__q__) \ + (cop)->status = 0; \ +} + +#define _tridentWaitIdleEmpty(cop) _tridentWaitDone(cop) + +#define sourceInvarient(alu) (((alu) & 3) == (((alu) >> 2) & 3)) + +#endif diff --git a/xc/programs/Xserver/hw/kdrive/mach64/mach64stub.c b/xc/programs/Xserver/hw/kdrive/mach64/mach64stub.c new file mode 100644 index 000000000..730275b92 --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/mach64/mach64stub.c @@ -0,0 +1,58 @@ +/* + * Id: mach64stub.c,v 1.1 1999/11/02 08:19:15 keithp Exp $ + * + * Copyright 1999 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. + */ +/* $XFree86: xc/programs/Xserver/hw/kdrive/mach64/mach64stub.c,v 1.1 2001/06/03 18:48:19 keithp Exp $ */ + +#include "mach64.h" + +void +InitCard (char *name) +{ + KdCardAttr attr; + + if (LinuxFindPci (0x1002, 0x4c4d, 0, &attr)) + KdCardInfoAdd (&mach64Funcs, &attr, 0); +} + +void +InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv) +{ + KdInitOutput (pScreenInfo, argc, argv); +} + +void +InitInput (int argc, char **argv) +{ + KdInitInput (&Ps2MouseFuncs, &LinuxKeyboardFuncs); +} + +int +ddxProcessArgument (int argc, char **argv, int i) +{ + int ret; + + if (!(ret = vesaProcessArgument (argc, argv, i))) + ret = KdProcessArgument(argc, argv, i); + return ret; +} diff --git a/xc/programs/Xserver/hw/kdrive/mach64/mach64video.c b/xc/programs/Xserver/hw/kdrive/mach64/mach64video.c new file mode 100644 index 000000000..13b83a7f5 --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/mach64/mach64video.c @@ -0,0 +1,1045 @@ +/* + * Copyright © 2001 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. + */ +/* $XFree86: xc/programs/Xserver/hw/kdrive/mach64/mach64video.c,v 1.7 2001/08/09 09:08:55 keithp Exp $ */ +#include "mach64.h" + +#include "Xv.h" +#include "../../xfree86/common/fourcc.h" + +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +static Atom xvBrightness, xvSaturation, xvColorKey; + +#define IMAGE_MAX_WIDTH 720 +#define IMAGE_MAX_HEIGHT 576 + +static void +mach64StopVideo(KdScreenInfo *screen, pointer data, Bool exit) +{ + ScreenPtr pScreen = screen->pScreen; + KdScreenPriv(pScreen); + KdCardInfo *card = pScreenPriv->card; + Mach64ScreenInfo *mach64s = (Mach64ScreenInfo *) screen->driver; + Mach64CardInfo *mach64c = (Mach64CardInfo *) card->driver; + Mach64PortPrivPtr pPortPriv = mach64s->pAdaptor->pPortPrivates[0].ptr; + Reg *reg = mach64c->reg; + MediaReg *media = mach64c->media_reg; + + REGION_EMPTY(screen->pScreen, &pPortPriv->clip); + + if (!media) + return; + + if(pPortPriv->videoOn) + { + mach64WaitIdle (reg); + /* wait for buffer to be displayed */ + while (((media->TRIG_CNTL >> 5) & 1) != pPortPriv->currentBuf) + ; + /* wait for buffer to be finished */ + while (((media->TRIG_CNTL >> 6) & 1) != 0) + ; + mach64WaitAvail (reg, 1); + media->OVERLAY_SCALE_CNTL = 0; + pPortPriv->videoOn = FALSE; + mach64WaitIdle (reg); + } +} + +static int +mach64SetPortAttribute(KdScreenInfo *screen, + Atom attribute, + int value, + pointer data) +{ + ScreenPtr pScreen = screen->pScreen; + KdScreenPriv(pScreen); + KdCardInfo *card = pScreenPriv->card; + Mach64ScreenInfo *mach64s = (Mach64ScreenInfo *) screen->driver; + Mach64CardInfo *mach64c = (Mach64CardInfo *) card->driver; + Mach64PortPrivPtr pPortPriv = mach64s->pAdaptor->pPortPrivates[0].ptr; + MediaReg *media = mach64c->media_reg; + + if(attribute == xvBrightness) + { + if(value < -1000) + value = -1000; + if (value > 1000) + value = 1000; + pPortPriv->brightness = value; + } + else if(attribute == xvSaturation) + { + if (value < -1000) + value = -1000; + if (value > 1000) + value = 1000; + pPortPriv->saturation = value; + } + else if(attribute == xvColorKey) + { + if (pPortPriv->colorKey != value) + { + pPortPriv->colorKey = value; + REGION_EMPTY(screen->pScreen, &pPortPriv->clip); + } + } + else + return BadMatch; + + return Success; +} + +static int +mach64GetPortAttribute(KdScreenInfo *screen, + Atom attribute, + int *value, + pointer data) +{ + Mach64PortPrivPtr pPortPriv = (Mach64PortPrivPtr)data; + + if(attribute == xvBrightness) + *value = pPortPriv->brightness; + else if(attribute == xvSaturation) + *value = pPortPriv->saturation; + else if(attribute == xvColorKey) + *value = pPortPriv->colorKey; + else + return BadMatch; + + return Success; +} + +static void +mach64QueryBestSize(KdScreenInfo *screen, + Bool motion, + short vid_w, + short vid_h, + short drw_w, + short drw_h, + unsigned int *p_w, + unsigned int *p_h, + pointer data) +{ + *p_w = drw_w; + *p_h = drw_h; +} + + +static void +mach64CopyPackedData(KdScreenInfo *screen, + unsigned char *buf, + int rotate, + int srcPitch, + int dstPitch, + int srcW, + int srcH, + int top, + int left, + int h, + int w) +{ + ScreenPtr pScreen = screen->pScreen; + KdScreenPriv(pScreen); + KdCardInfo *card = pScreenPriv->card; + Mach64ScreenInfo *mach64s = (Mach64ScreenInfo *) screen->driver; + Mach64CardInfo *mach64c = (Mach64CardInfo *) card->driver; + Mach64PortPrivPtr pPortPriv = mach64s->pAdaptor->pPortPrivates[0].ptr; + CARD8 *src, *dst; + int srcDown, srcRight, srcNext; + int p; + + switch (rotate) { + case 0: + src = buf; + srcDown = srcPitch; + srcRight = 2; + break; + case 90: + src = src + (srcH - 1) * 2; + srcDown = -2; + srcRight = srcPitch; + break; + case 180: + src = src + srcPitch * (srcH - 1) + (srcW - 1) * 2; + srcDown = -srcPitch; + srcRight = -2; + break; + case 270: + src = src + srcPitch * (srcW - 1); + srcDown = 2; + srcRight = -srcPitch; + break; + } + + src = src + top*srcDown + left*srcRight; + + if (pPortPriv->currentBuf == 0) + dst = (CARD8 *) mach64s->vesa.fb + pPortPriv->YBuf0Offset; + else + dst = (CARD8 *) mach64s->vesa.fb + pPortPriv->YBuf1Offset; + + w >>= 1; + srcRight >>= 1; + srcNext = srcRight >> 1; + while(h--) + { + CARD16 *s = (CARD16 *) src; + CARD32 *d = (CARD32 *) dst; + p = w; + while (p--) + { + *d++ = s[0] | (s[srcNext] << 16); + s += srcRight; + } + src += srcPitch; + dst += dstPitch; + } +} + +static void +mach64CopyPlanarData(KdScreenInfo *screen, + unsigned char *buf, + int rotate, + int srcPitch, + int srcPitch2, + int dstPitch, /* of chroma */ + int srcW, + int srcH, + int height, + int top, + int left, + int h, + int w, + int id) +{ + ScreenPtr pScreen = screen->pScreen; + KdScreenPriv(pScreen); + KdCardInfo *card = pScreenPriv->card; + Mach64ScreenInfo *mach64s = (Mach64ScreenInfo *) screen->driver; + Mach64CardInfo *mach64c = (Mach64CardInfo *) card->driver; + Mach64PortPrivPtr pPortPriv = mach64s->pAdaptor->pPortPrivates[0].ptr; + int i, j; + CARD8 *src1, *src2, *src3, *dst1; + int srcDown, srcDown2, srcRight, srcRight2, srcNext; + + /* compute source data pointers */ + src1 = buf; + src2 = src1 + height * srcPitch; + src3 = src2 + (height >> 1) * srcPitch2; + switch (rotate) { + case 0: + srcDown = srcPitch; + srcDown2 = srcPitch2; + srcRight = 2; + srcRight2 = 1; + srcNext = 1; + break; + case 90: + src1 = src1 + srcH - 1; + src2 = src2 + (srcH >> 1) - 1; + src3 = src3 + (srcH >> 1) - 1; + srcDown = -1; + srcDown2 = -1; + srcRight = srcPitch * 2; + srcRight2 = srcPitch2; + srcNext = srcPitch; + break; + case 180: + src1 = src1 + srcPitch * (srcH - 1) + (srcW - 1); + src2 = src2 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1); + src3 = src3 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1); + srcDown = -srcPitch; + srcDown2 = -srcPitch2; + srcRight = -2; + srcRight2 = -1; + srcNext = -1; + break; + case 270: + src1 = src1 + srcPitch * (srcW - 1); + src2 = src2 + srcPitch2 * ((srcW >> 1) - 1); + src3 = src3 + srcPitch2 * ((srcW >> 1) - 1); + srcDown = 1; + srcDown2 = 1; + srcRight = -srcPitch * 2; + srcRight2 = -srcPitch2; + srcNext = -srcPitch; + break; + } + + /* adjust for origin */ + src1 += top * srcDown + left * srcNext; + src2 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2; + src3 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2; + + if (id == FOURCC_I420) + { + CARD8 *srct = src2; + src2 = src3; + src3 = srct; + } + + if (pPortPriv->currentBuf == 0) + dst1 = (CARD8 *) mach64s->vesa.fb + pPortPriv->YBuf0Offset; + else + dst1 = (CARD8 *) mach64s->vesa.fb + pPortPriv->YBuf1Offset; + + w >>= 1; + for (j = 0; j < h; j++) + { + CARD32 *dst = (CARD32 *) dst1; + CARD8 *s1l = src1; + CARD8 *s1r = src1 + srcNext; + CARD8 *s2 = src2; + CARD8 *s3 = src3; + + for (i = 0; i < w; i++) + { + *dst++ = *s1l | (*s1r << 16) | (*s3 << 8) | (*s2 << 24); + s1l += srcRight; + s1r += srcRight; + s2 += srcRight2; + s3 += srcRight2; + } + src1 += srcDown; + dst1 += dstPitch; + if (j & 1) + { + src2 += srcDown2; + src3 += srcDown2; + } + } +} + +/* I really should stick this in miregion */ +static Bool +RegionsEqual(RegionPtr A, RegionPtr B) +{ + int *dataA, *dataB; + int num; + + num = REGION_NUM_RECTS(A); + if(num != REGION_NUM_RECTS(B)) + return FALSE; + + if((A->extents.x1 != B->extents.x1) || + (A->extents.x2 != B->extents.x2) || + (A->extents.y1 != B->extents.y1) || + (A->extents.y2 != B->extents.y2)) + return FALSE; + + dataA = (int*)REGION_RECTS(A); + dataB = (int*)REGION_RECTS(B); + + while(num--) { + if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])) + return FALSE; + dataA += 2; + dataB += 2; + } + + return TRUE; +} + +static void +mach64PaintRegion (ScreenPtr pScreen, RegionPtr pRgn, Pixel fg) +{ + WindowPtr pRoot = WindowTable[pScreen->myNum]; + GCPtr pGC; + CARD32 val[2]; + xRectangle *rects, *r; + BoxPtr pBox = REGION_RECTS (pRgn); + int nBox = REGION_NUM_RECTS (pRgn); + + rects = ALLOCATE_LOCAL (nBox * sizeof (xRectangle)); + if (!rects) + goto bail0; + r = rects; + while (nBox--) + { + r->x = pBox->x1; + r->y = pBox->y1; + r->width = pBox->x2 - pBox->x1; + r->height = pBox->y2 - pBox->y1; + r++; + pBox++; + } + + pGC = GetScratchGC (pRoot->drawable.depth, pScreen); + if (!pGC) + goto bail1; + + val[0] = fg; + val[1] = IncludeInferiors; + ChangeGC (pGC, GCForeground|GCSubwindowMode, val); + + ValidateGC (&pRoot->drawable, pGC); + + (*pGC->ops->PolyFillRect) (&pRoot->drawable, pGC, + REGION_NUM_RECTS (pRgn), rects); + + FreeScratchGC (pGC); +bail1: + DEALLOCATE_LOCAL (rects); +bail0: + ; +} + +/* Mach64ClipVideo - + + Takes the dst box in standard X BoxRec form (top and left + edges inclusive, bottom and right exclusive). The new dst + box is returned. The source boundaries are given (x1, y1 + inclusive, x2, y2 exclusive) and returned are the new source + boundaries in 16.16 fixed point. +*/ + +static void +Mach64ClipVideo(BoxPtr dst, + INT32 *x1, + INT32 *x2, + INT32 *y1, + INT32 *y2, + BoxPtr extents, /* extents of the clip region */ + INT32 width, + INT32 height) +{ + INT32 vscale, hscale, delta; + int diff; + + hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1); + vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1); + + *x1 <<= 16; *x2 <<= 16; + *y1 <<= 16; *y2 <<= 16; + + diff = extents->x1 - dst->x1; + if(diff > 0) { + dst->x1 = extents->x1; + *x1 += diff * hscale; + } + diff = dst->x2 - extents->x2; + if(diff > 0) { + dst->x2 = extents->x2; + *x2 -= diff * hscale; + } + diff = extents->y1 - dst->y1; + if(diff > 0) { + dst->y1 = extents->y1; + *y1 += diff * vscale; + } + diff = dst->y2 - extents->y2; + if(diff > 0) { + dst->y2 = extents->y2; + *y2 -= diff * vscale; + } + + if(*x1 < 0) { + diff = (- *x1 + hscale - 1)/ hscale; + dst->x1 += diff; + *x1 += diff * hscale; + } + delta = *x2 - (width << 16); + if(delta > 0) { + diff = (delta + hscale - 1)/ hscale; + dst->x2 -= diff; + *x2 -= diff * hscale; + } + if(*y1 < 0) { + diff = (- *y1 + vscale - 1)/ vscale; + dst->y1 += diff; + *y1 += diff * vscale; + } + delta = *y2 - (height << 16); + if(delta > 0) { + diff = (delta + vscale - 1)/ vscale; + dst->y2 -= diff; + *y2 -= diff * vscale; + } +} + +static void +mach64DisplayVideo(KdScreenInfo *screen, + int id, + int dstPitch, /* of chroma for 4:2:0 */ + int x1, + int y1, + int x2, + int y2, + int dst_x1, + int dst_y1, + int dst_x2, + int dst_y2, + short src_w, + short src_h, + short drw_w, + short drw_h) +{ + ScreenPtr pScreen = screen->pScreen; + KdScreenPriv(pScreen); + KdCardInfo *card = pScreenPriv->card; + Mach64ScreenInfo *mach64s = (Mach64ScreenInfo *) screen->driver; + Mach64CardInfo *mach64c = (Mach64CardInfo *) card->driver; + Mach64PortPrivPtr pPortPriv = mach64s->pAdaptor->pPortPrivates[0].ptr; + Reg *reg = mach64c->reg; + MediaReg *media = mach64c->media_reg; + int xscaleInt, xscaleFract, yscaleInt, yscaleFract; + int xscaleIntUV = 0, xscaleFractUV = 0; + int yscaleIntUV = 0, yscaleFractUV = 0; + int rotate = mach64s->vesa.rotate; + int HORZ_INC, VERT_INC; + CARD32 SCALER_IN; + CARD32 OVERLAY_SCALE_CNTL; + int tmp; + int left; + int bright; + int sat; + + if (id == FOURCC_UYVY) + SCALER_IN = SCALER_IN_YVYU422; + else + SCALER_IN = SCALER_IN_VYUY422; + + mach64WaitAvail (reg, 4); + + media->VIDEO_FORMAT = SCALER_IN | VIDEO_IN_VYUY422; + + /* color key */ + media->OVERLAY_GRAPHICS_KEY_MSK = (1 << screen->fb[0].depth) - 1; + media->OVERLAY_GRAPHICS_KEY_CLR = pPortPriv->colorKey; + /* set key control to obey only graphics color key */ + media->OVERLAY_KEY_CNTL = 0x50; + + mach64WaitAvail (reg, 9); + media->CAPTURE_DEBUG = 0; + /* no exclusive video region */ + media->OVERLAY_EXCLUSIVE_HORZ = 0; + media->OVERLAY_EXCLUSIVE_VERT = 0; + /* scaling coefficients */ + media->SCALER_H_COEFF0 = 0x00002000; + media->SCALER_H_COEFF1 = 0x0D06200D; + media->SCALER_H_COEFF2 = 0x0D0A1C0D; + media->SCALER_H_COEFF3 = 0x0C0E1A0C; + media->SCALER_H_COEFF4 = 0x0C14140C; + media->SCALER_TEST = 0; + + mach64WaitAvail (reg, 2); + media->OVERLAY_SCALE_CNTL = (SCALE_PIX_EXPAND | + SCALE_GAMMA_BRIGHT | + SCALE_BANDWIDTH | + SCALE_OVERLAY_EN | + SCALE_EN); + + bright = (pPortPriv->brightness * 64 / 1000); + if (bright < -0x40) + bright = -0x40; + if (bright > 0x3f) + bright = 0x3f; + bright = bright & 0x7f; + sat = ((pPortPriv->saturation * 31 + 31000) / 2000); + if (sat > 0x1f) + sat = 0x1f; + if (sat < 0) + sat = 0; + + media->SCALER_COLOUR_CNTL = ((bright << 0) | /* BRIGHTNESS */ + (sat << 8) | /* SATURATION_U */ + (sat << 16) | /* SATURATION_V */ + (0 << 21) | /* SCALER_VERT_ADJ_UV */ + (0 << 28)); /* SCALER_HORZ_ADJ_UV */ + + VERT_INC = (src_h << 12) / drw_h; + HORZ_INC = (src_w << 12) / drw_w; + + mach64WaitAvail (reg, 13); + + /* lock registers to prevent non-atomic update */ + media->OVERLAY_Y_X_START = 0x80000000 | MACH64_YX (dst_x1, dst_y1); + /* ending screen coordinate */ + media->OVERLAY_Y_X_END = 0x80000000 | MACH64_YX (dst_x2, dst_y2); + + media->OVERLAY_SCALE_INC = MACH64_YX(HORZ_INC, VERT_INC); + + media->SCALER_BUF0_OFFSET = pPortPriv->YBuf0Offset; + media->SCALER_BUF1_OFFSET = pPortPriv->YBuf1Offset; + + media->SCALER_BUF0_OFFSET_U = pPortPriv->YBuf0Offset; + media->SCALER_BUF1_OFFSET_U = pPortPriv->YBuf1Offset; + + media->SCALER_BUF0_OFFSET_V = pPortPriv->YBuf0Offset; + media->SCALER_BUF1_OFFSET_V = pPortPriv->YBuf1Offset; + + media->SCALER_BUF_PITCH = dstPitch >> 1; + media->SCALER_HEIGHT_WIDTH = MACH64_YX(src_w - (x1 >> 16), src_h - (y1 >> 16)); + + media->CAPTURE_CONFIG = pPortPriv->currentBuf << 28; + + /* set XY location and unlock */ + media->OVERLAY_Y_X_START = MACH64_YX (dst_x1, dst_y1); +} + +static int +mach64PutImage(KdScreenInfo *screen, + short src_x, + short src_y, + short drw_x, + short drw_y, + short src_w, + short src_h, + short drw_w, + short drw_h, + int id, + unsigned char *buf, + short width, + short height, + Bool sync, + RegionPtr clipBoxes, + pointer data) +{ + KdCardInfo *card = screen->card; + Mach64ScreenInfo *mach64s = (Mach64ScreenInfo *) screen->driver; + Mach64CardInfo *mach64c = (Mach64CardInfo *) card->driver; + Mach64PortPrivPtr pPortPriv = (Mach64PortPrivPtr)data; + Reg *reg = mach64c->reg; + MediaReg *media = mach64c->media_reg; + INT32 x1, x2, y1, y2; + int rotate = mach64s->vesa.rotate; + int srcPitch, srcPitch2, dstPitch; + int top, left, npixels, nlines, size; + BoxRec dstBox; + int dst_width = width, dst_height = height; + int rot_x1, rot_y1, rot_x2, rot_y2; + int dst_x1, dst_y1, dst_x2, dst_y2; + int rot_src_w, rot_src_h, rot_drw_w, rot_drw_h; + + /* Clip */ + x1 = src_x; + x2 = src_x + src_w; + y1 = src_y; + y2 = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + + Mach64ClipVideo(&dstBox, &x1, &x2, &y1, &y2, + REGION_EXTENTS(pScreen, clipBoxes), width, height); + + if((x1 >= x2) || (y1 >= y2)) + return Success; + + if (!media) + return BadAlloc; + + switch (rotate) { + case 0: + case 180: + dst_width = width; + dst_height = height; + rot_src_w = src_w; + rot_src_h = src_h; + rot_drw_w = drw_w; + rot_drw_h = drw_h; + break; + case 90: + case 270: + dst_width = height; + dst_height = width; + rot_src_w = src_h; + rot_src_h = src_w; + rot_drw_w = drw_h; + rot_drw_h = drw_w; + break; + } + + switch (rotate) { + case 0: + dst_x1 = dstBox.x1; + dst_y1 = dstBox.y1; + dst_x2 = dstBox.x2; + dst_y2 = dstBox.y2; + rot_x1 = x1; + rot_y1 = y1; + rot_x2 = x2; + rot_y2 = y2; + break; + case 90: + dst_x1 = dstBox.y1; + dst_y1 = screen->height - dstBox.x2; + dst_x2 = dstBox.y2; + dst_y2 = screen->height - dstBox.x1; + + rot_x1 = y1; + rot_y1 = (src_w << 16) - x2; + rot_x2 = y2; + rot_y2 = (src_w << 16) - x1; + break; + case 180: + dst_x1 = screen->width - dstBox.x2; + dst_y1 = screen->height - dstBox.y2; + dst_x2 = screen->width - dstBox.x1; + dst_y2 = screen->height - dstBox.y1; + rot_x1 = (src_w << 16) - x2; + rot_y1 = (src_h << 16) - y2; + rot_x2 = (src_w << 16) - x1; + rot_y2 = (src_h << 16) - y1; + break; + case 270: + dst_x1 = screen->width - dstBox.y2; + dst_y1 = dstBox.x1; + dst_x2 = screen->width - dstBox.y1; + dst_y2 = dstBox.x2; + rot_x1 = (src_h << 16) - y2; + rot_y1 = x1; + rot_x2 = (src_h << 16) - y1; + rot_y2 = x2; + break; + } + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + dstPitch = ((dst_width << 1) + 15) & ~15; + srcPitch = (width + 3) & ~3; + srcPitch2 = ((width >> 1) + 3) & ~3; + size = dstPitch * (int) dst_height; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + dstPitch = ((dst_width << 1) + 15) & ~15; + srcPitch = (width << 1); + size = dstPitch * (int) dst_height; + break; + } + + pPortPriv->offset = mach64s->off_screen - (CARD8 *) mach64s->vesa.fb; + /* fixup pointers */ + + pPortPriv->YBuf0Offset = pPortPriv->offset; + pPortPriv->YBuf1Offset = pPortPriv->offset + size; + +#if 0 + mach64WaitIdle (reg); + + if (pPortPriv->videoOn) + { + /* wait for buffer to be displayed */ + while (((media->TRIG_CNTL >> 5) & 1) != pPortPriv->currentBuf) + ; + } +#endif + /* + * Use the other buffer + */ + pPortPriv->currentBuf = 1 - pPortPriv->currentBuf; + + /* copy data */ + top = rot_y1 >> 16; + left = (rot_x1 >> 16) & ~1; + npixels = ((((rot_x2 + 0xffff) >> 16) + 1) & ~1) - left; + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + top &= ~1; + nlines = ((((rot_y2 + 0xffff) >> 16) + 1) & ~1) - top; + mach64CopyPlanarData(screen, buf, rotate, + srcPitch, srcPitch2, dstPitch, + rot_src_w, rot_src_h, height, + top, left, nlines, npixels, id); + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + nlines = ((rot_y2 + 0xffff) >> 16) - top; + mach64CopyPackedData(screen, buf, rotate, + srcPitch, dstPitch, + rot_src_w, rot_src_h, + top, left, nlines, + npixels); + break; + } + + mach64DisplayVideo(screen, id, dstPitch, + rot_x1, rot_y1, rot_x2, rot_y2, + dst_x1, dst_y1, + dst_x2, dst_y2, + rot_src_w, rot_src_h, rot_drw_w, rot_drw_h); + + /* update cliplist */ + if (!RegionsEqual (&pPortPriv->clip, clipBoxes)) + { + REGION_COPY (screen->pScreen, &pPortPriv->clip, clipBoxes); + mach64PaintRegion (screen->pScreen, &pPortPriv->clip, pPortPriv->colorKey); + } + + pPortPriv->videoOn = TRUE; + + return Success; +} + +static int +mach64QueryImageAttributes(KdScreenInfo *screen, + int id, + unsigned short *w, + unsigned short *h, + int *pitches, + int *offsets) +{ + int size, tmp; + + if(*w > IMAGE_MAX_WIDTH) + *w = IMAGE_MAX_WIDTH; + if(*h > IMAGE_MAX_HEIGHT) + *h = IMAGE_MAX_HEIGHT; + + *w = (*w + 1) & ~1; + if(offsets) offsets[0] = 0; + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + *h = (*h + 1) & ~1; + size = (*w + 3) & ~3; + if(pitches) + pitches[0] = size; + size *= *h; + if(offsets) + offsets[1] = size; + tmp = ((*w >> 1) + 3) & ~3; + if(pitches) + pitches[1] = pitches[2] = tmp; + tmp *= (*h >> 1); + size += tmp; + if(offsets) + offsets[2] = size; + size += tmp; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + size = *w << 1; + if(pitches) + pitches[0] = size; + size *= *h; + break; + } + + return size; +} + + +/* client libraries expect an encoding */ +static KdVideoEncodingRec DummyEncoding[1] = +{ + { + 0, + "XV_IMAGE", + IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, + {1, 1} + } +}; + +#define NUM_FORMATS 3 + +static KdVideoFormatRec Formats[NUM_FORMATS] = +{ + {15, TrueColor}, {16, TrueColor}, {24, TrueColor} +}; + +#define NUM_ATTRIBUTES 3 + +static KdAttributeRec Attributes[NUM_ATTRIBUTES] = +{ + {XvSettable | XvGettable, 0, ~0, "XV_COLORKEY"}, + {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, + {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"} +}; + +#define NUM_IMAGES 4 + +static KdImageRec Images[NUM_IMAGES] = +{ + XVIMAGE_YUY2, + XVIMAGE_YV12, + XVIMAGE_I420, + XVIMAGE_UYVY +}; + +static void mach64ResetVideo(KdScreenInfo *screen) +{ + ScreenPtr pScreen = screen->pScreen; + KdScreenPriv(pScreen); + KdCardInfo *card = pScreenPriv->card; + Mach64ScreenInfo *mach64s = (Mach64ScreenInfo *) screen->driver; + Mach64CardInfo *mach64c = (Mach64CardInfo *) card->driver; + Mach64PortPrivPtr pPortPriv = mach64s->pAdaptor->pPortPrivates[0].ptr; + MediaReg *media = mach64c->media_reg; + + /* + * Default to maximum image size in YV12 + */ + +} + +static int +mach64ReputImage (KdScreenInfo *screen, + short drw_x, + short drw_y, + RegionPtr clipBoxes, + pointer data) +{ + ScreenPtr pScreen = screen->pScreen; + Mach64PortPrivPtr pPortPriv = (Mach64PortPrivPtr)data; + BoxPtr pOldExtents = REGION_EXTENTS (pScreen, &pPortPriv->clip); + BoxPtr pNewExtents = REGION_EXTENTS (pScreen, clipBoxes); + + if (pOldExtents->x1 == pNewExtents->x1 && + pOldExtents->x2 == pNewExtents->x2 && + pOldExtents->y1 == pNewExtents->y1 && + pOldExtents->y2 == pNewExtents->y2) + { + /* update cliplist */ + if (!RegionsEqual (&pPortPriv->clip, clipBoxes)) + { + REGION_COPY (screen->pScreen, &pPortPriv->clip, clipBoxes); + mach64PaintRegion (screen->pScreen, &pPortPriv->clip, pPortPriv->colorKey); + } + return Success; + } + return BadMatch; +} + +static KdVideoAdaptorPtr +mach64SetupImageVideo(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + mach64CardInfo(pScreenPriv); + mach64ScreenInfo(pScreenPriv); + KdScreenInfo *screen = pScreenPriv->screen; + KdCardInfo *card = pScreenPriv->card; + KdVideoAdaptorPtr adapt; + Mach64PortPrivPtr pPortPriv; + + if(!(adapt = xcalloc(1, sizeof(KdVideoAdaptorRec) + + sizeof(Mach64PortPrivRec) + + sizeof(DevUnion)))) + return NULL; + + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adapt->name = "Mach64 Video Overlay"; + adapt->nEncodings = 1; + adapt->pEncodings = DummyEncoding; + adapt->nFormats = NUM_FORMATS; + adapt->pFormats = Formats; + adapt->nPorts = 1; + adapt->pPortPrivates = (DevUnion*)(&adapt[1]); + + pPortPriv = (Mach64PortPrivPtr)(&adapt->pPortPrivates[1]); + + adapt->pPortPrivates[0].ptr = (pointer)(pPortPriv); + adapt->pAttributes = Attributes; + adapt->nImages = NUM_IMAGES; + adapt->nAttributes = NUM_ATTRIBUTES; + adapt->pImages = Images; + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; + adapt->StopVideo = mach64StopVideo; + adapt->SetPortAttribute = mach64SetPortAttribute; + adapt->GetPortAttribute = mach64GetPortAttribute; + adapt->QueryBestSize = mach64QueryBestSize; + adapt->PutImage = mach64PutImage; + adapt->ReputImage = mach64ReputImage; + adapt->QueryImageAttributes = mach64QueryImageAttributes; + + pPortPriv->colorKey = mach64s->colorKey; + pPortPriv->videoOn = FALSE; + pPortPriv->brightness = 0; + pPortPriv->saturation = 0; + pPortPriv->currentBuf = 0; + + /* gotta uninit this someplace */ + REGION_INIT(pScreen, &pPortPriv->clip, NullBox, 0); + + mach64s->pAdaptor = adapt; + + xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); + xvSaturation = MAKE_ATOM("XV_SATURATION"); + xvColorKey = MAKE_ATOM("XV_COLORKEY"); + + mach64ResetVideo(screen); + + return adapt; +} + +Bool mach64InitVideo(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + KdVideoAdaptorPtr *adaptors, *newAdaptors = NULL; + KdVideoAdaptorPtr newAdaptor = NULL; + int num_adaptors; + KdCardInfo *card = pScreenPriv->card; + Mach64ScreenInfo *mach64s = (Mach64ScreenInfo *) screen->driver; + Mach64CardInfo *mach64c = (Mach64CardInfo *) card->driver; + + if (!mach64c->media_reg) + return FALSE; + + newAdaptor = mach64SetupImageVideo(pScreen); + + num_adaptors = KdXVListGenericAdaptors(screen, &adaptors); + + if(newAdaptor) + { + if(!num_adaptors) + { + num_adaptors = 1; + adaptors = &newAdaptor; + } + else + { + newAdaptors = xalloc((num_adaptors + 1) * + sizeof(KdVideoAdaptorPtr*)); + if(newAdaptors) + { + memcpy(newAdaptors, adaptors, + num_adaptors * sizeof(KdVideoAdaptorPtr)); + newAdaptors[num_adaptors] = newAdaptor; + adaptors = newAdaptors; + num_adaptors++; + } + } + } + + if(num_adaptors) + KdXVScreenInit(pScreen, adaptors, num_adaptors); + + if(newAdaptors) + xfree(newAdaptors); + return TRUE; +} diff --git a/xc/programs/Xserver/hw/kdrive/pcmcia/Imakefile b/xc/programs/Xserver/hw/kdrive/pcmcia/Imakefile new file mode 100644 index 000000000..4a2c059ba --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/pcmcia/Imakefile @@ -0,0 +1,13 @@ +XCOMM $XFree86: xc/programs/Xserver/hw/kdrive/pcmcia/Imakefile,v 1.1 2001/05/23 08:56:08 alanh Exp $ +KDRIVE=.. +#include "../Kdrive.tmpl" + +SRCS = pcmcia.c pcmciacurs.c pcmciastub.c pcmciashadow.c + +OBJS = pcmcia.o pcmciacurs.o pcmciastub.o pcmciashadow.o + +INCLUDES = -I. $(KDINCS) -I$(KDRIVE)/fbdev + +NormalLibraryObjectRule() +NormalLibraryTarget(pcmcia,$(OBJS)) +DependTarget() diff --git a/xc/programs/Xserver/hw/kdrive/pcmcia/modes.h b/xc/programs/Xserver/hw/kdrive/pcmcia/modes.h new file mode 100644 index 000000000..49c7d5f42 --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/pcmcia/modes.h @@ -0,0 +1,66 @@ +/* + * Copyright 2001 by Alan Hourihane, Sychdyn, North Wales, UK. + * + * 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 Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE 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. + * + * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> + */ +/* $XFree86: xc/programs/Xserver/hw/kdrive/pcmcia/modes.h,v 1.1 2001/05/23 08:56:08 alanh Exp $ */ + +#define V_NHSYNC 0x01 +#define V_NVSYNC 0x02 +#define V_PHSYNC 0x04 +#define V_PVSYNC 0x08 +#define V_INTERLACE 0x10 + +pcmciaDisplayModeRec pcmciaDefaultModes [] = { +/* 640x400 @ 70Hz (VGA) hsync: 37.9kHz */ + {640, 400, 70 ,31500, 640,672,736,832,0, 400,401,404,445,0, V_NHSYNC | V_PVSYNC}, +/* 640x480 @ 60Hz (Industry standard) hsync: 31.5kHz */ + {640, 480, 60 ,25200, 640,656,752,800,0, 480,490,492,525,0, V_NHSYNC | V_NVSYNC}, +/* 640x480 @ 72Hz (VESA) hsync: 37.9kHz */ + {640, 480, 72 ,31500, 640,664,704,832,0, 480,489,491,520,0, V_NHSYNC | V_NVSYNC}, +/* 640x480 @ 75Hz (VESA) hsync: 37.5kHz */ + {640, 480, 75 ,31500, 640,656,720,840,0, 480,481,484,500,0, V_NHSYNC | V_NVSYNC}, +/* 640x480 @ 85Hz (VESA) hsync: 43.3kHz */ + {640, 480, 85 ,36000, 640,696,752,832,0, 480,481,484,509,0, V_NHSYNC | V_NVSYNC}, +/* 800x600 @ 56Hz (VESA) hsync: 35.2kHz */ + {800, 600, 56 ,36000, 800,824,896,1024,0, 600,601,603,625,0, V_PHSYNC | V_PVSYNC}, +/* 800x600 @ 60Hz (VESA) hsync: 37.9kHz */ + {800, 600, 60 ,40000, 800,840,968,1056,0, 600,601,605,628,0, V_PHSYNC | V_PVSYNC}, +/* 800x600 @ 72Hz (VESA) hsync: 48.1kHz */ + {800, 600, 72 ,50000, 800,856,976,1040,0, 600,637,643,666,0, V_PHSYNC | V_PVSYNC}, +/* 800x600 @ 75Hz (VESA) hsync: 46.9kHz */ + {800, 600, 75 ,49500, 800,816,896,1056,0, 600,601,604,625,0, V_PHSYNC | V_PVSYNC}, +/* 800x600 @ 85Hz (VESA) hsync: 53.7kHz */ + {800, 600, 85 ,56300, 800,832,896,1048,0, 600,601,604,631,0, V_PHSYNC | V_PVSYNC}, +/* 1024x768i @ 43Hz (industry standard) hsync: 35.5kHz */ + {1024, 768, 43 ,44900, 1024,1032,1208,1264,0, 768,768,776,817,0, V_PHSYNC | V_PVSYNC | V_INTERLACE}, +/* 1024x768 @ 60Hz (VESA) hsync: 48.4kHz */ + {1024, 768, 60 ,65000, 1024,1048,1184,1344,0, 768,771,777,806,0, V_NHSYNC | V_NVSYNC}, +/* 1024x768 @ 70Hz (VESA) hsync: 56.5kHz */ + {1024, 768, 70 ,75000, 1024,1048,1184,1328,0, 768,771,777,806,0, V_NHSYNC | V_NVSYNC}, +/* 1024x768 @ 75Hz (VESA) hsync: 60.0kHz */ + {1024, 768, 75 ,78800, 1024,1040,1136,1312,0, 768,769,772,800,0, V_PHSYNC | V_PVSYNC}, +/* 1024x768 @ 85Hz (VESA) hsync: 68.7kHz */ + {1024, 768, 85 ,94500, 1024,1072,1168,1376,0, 768,769,772,808,0, V_PHSYNC | V_PVSYNC}, +/* 1152x864 @ 75Hz (VESA) hsync: 67.5kHz */ + {1152, 864, 75 ,108000, 1152,1216,1344,1600,0, 864,865,868,900,0, V_PHSYNC | V_PVSYNC}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} +}; diff --git a/xc/programs/Xserver/hw/kdrive/pcmcia/pcmcia.c b/xc/programs/Xserver/hw/kdrive/pcmcia/pcmcia.c new file mode 100644 index 000000000..88bab0237 --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/pcmcia/pcmcia.c @@ -0,0 +1,1251 @@ +/* + * Copyright 2001 by Alan Hourihane, Sychdyn, North Wales, UK. + * + * 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 Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE 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. + * + * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> + * + * A driver for the following PCMCIA cards... + * Hewlett Packards HP VGA Out (Model F1252A) + * Colorgraphics Voyager VGA + * + * Tested running under a Compaq IPAQ Pocket PC running Linux + */ +/* $XFree86: xc/programs/Xserver/hw/kdrive/pcmcia/pcmcia.c,v 1.5 2001/07/20 19:35:30 keithp Exp $ */ + +#include "pcmcia.h" +#define extern +#include <asm/io.h> +#undef extern + +#define CLOCK 14318 /* KHz */ +#define CLK_N(a,b) (a & 0xff) +#define CLK_M(a,b) ((b) & 0x3f) +#define CLK_K(a,b) (((b) >> 6) & 3) +#define CLK_FREQ(a,b) (((CLK_N(a,b) + 8) * CLOCK) / ((CLK_M(a,b)+2) << CLK_K(a,b))) + +#include "modes.h" + +extern void +tridentUpdatePacked (ScreenPtr pScreen, + shadowBufPtr pBuf); +extern void +cirrusUpdatePacked (ScreenPtr pScreen, + shadowBufPtr pBuf); + +Bool +pcmciaCardInit (KdCardInfo *card) +{ + pcmciaCardInfo *pcmciac; + CARD8 r9; + + pcmciac = (pcmciaCardInfo *) xalloc (sizeof (pcmciaCardInfo)); + if (!pcmciac) + return FALSE; + + pcmciac->cop_base = (CARD8 *) KdMapDevice (PCMCIA_COP_BASE(card), + PCMCIA_COP_SIZE(card)); + + r9 = pcmciaReadIndex (pcmciac, 0x3c4, 0x09); + /* + * Crude detection.... + * The trident chip has a read only register at 0x09, which returns 0x4. + * If it's not that, we assume the cirrus chip. + * BREAKAGE.! If we have an anonymous PCMCIA card inserted, we could + * potentially smash something here. FIXME ! + */ + if (r9 == 0x04) { + ErrorF("PCMCIA: Found HP VGA card\n"); + pcmciac->HP = TRUE; /* Select HP VGA Out Card */ + } else { + ErrorF("PCMCIA: Found Voyager VGA card\n"); + pcmciac->HP = FALSE; /* Select Voyager VGA Card */ + } + + if (pcmciac->HP) { + /* needed by the accelerator - later */ + pcmciac->cop = (Cop *) (pcmciac->cop_base + TRIDENT_COP_OFF(card)); + } + + /* + * Map frame buffer + */ + if (pcmciac->HP) + pcmciac->fb = KdMapDevice (0x2ce00000, 0x80000); + else + pcmciac->fb = KdMapDevice (0x2c0a0000, 0x10000); /*64K bank switched*/ + + if (!pcmciac->fb) + return FALSE; + + pcmciac->window = 0; + + card->driver = pcmciac; + + return TRUE; +} + +Bool +pcmciaScreenInit (KdScreenInfo *screen) +{ + pcmciaCardInfo *pcmciac = screen->card->driver; + pcmciaScreenInfo *pcmcias; + int screen_size, memory; + int i; + + pcmcias = (pcmciaScreenInfo *) xalloc (sizeof (pcmciaScreenInfo)); + if (!pcmcias) + return FALSE; + memset (pcmcias, '\0', sizeof (pcmciaScreenInfo)); + + /* if (!pcmciac->cop) */ + screen->dumb = TRUE; + + /* default to 8bpp */ + if (!screen->fb[0].depth) + screen->fb[0].depth = 8; + + /* default to 60Hz refresh */ + if (!screen->rate) + screen->rate = 60; + + i = 0; + pcmcias->Mode = -1; + while (pcmciaDefaultModes[i].Width != 0) { + if ( (screen->width == pcmciaDefaultModes[i].Width) && + (screen->height == pcmciaDefaultModes[i].Height) && + (screen->rate == pcmciaDefaultModes[i].Refresh) ) { + pcmcias->Mode = i; + break; + } + i++; + } + + if ( pcmcias->Mode == -1 ) { + ErrorF("PCMCIA: no matching vesa mode for screen selection, aborting.\n"); + ErrorF("PCMCIA: use -listmodes to check for supported list of modes.\n"); + return FALSE; /* end of list */ + } + + pcmcias->rotation = screen->rotation; + + memory = 512 * 1024; + pcmcias->screen = pcmciac->fb; + + if (pcmciac->HP && !screen->softCursor && screen->fb[0].depth == 8) { + /* Let's do hw cursor for the HP card, only in 8bit mode though */ + pcmcias->cursor_base = pcmcias->screen + memory - 4096; + memory -= 4096; + } + + if (screen->fb[0].depth == 4) { + ErrorF("PCMCIA: depth 4 isn't supported.\n"); + return FALSE; /* screen->fb[0].bitsPerPixel = 4; need fb to support it*/ + } else + if (screen->fb[0].depth == 8) + screen->fb[0].bitsPerPixel = 8; + else + if (screen->fb[0].depth == 15 || + screen->fb[0].depth == 16) + screen->fb[0].bitsPerPixel = 16; + + if ( (screen->width * screen->height * + (screen->fb[0].bitsPerPixel / 8)) > memory) { + ErrorF("PCMCIA: Not enough memory for resolution requested, aborting.\n"); + return FALSE; + } + + screen->fb[0].pixelStride = screen->width; + screen->fb[0].byteStride = screen->width * (screen->fb[0].bitsPerPixel >>3); + + screen->fb[0].frameBuffer = pcmciac->fb; + switch (screen->fb[0].depth) { + case 4: + screen->fb[0].visuals = ((1 << StaticGray) | + (1 << GrayScale) | + (1 << StaticColor)); + screen->fb[0].blueMask = 0x00; + screen->fb[0].greenMask = 0x00; + screen->fb[0].redMask = 0x00; + break; + case 8: + screen->fb[0].visuals = ((1 << StaticGray) | + (1 << GrayScale) | + (1 << StaticColor) | + (1 << PseudoColor) | + (1 << TrueColor) | + (1 << DirectColor)); + screen->fb[0].blueMask = 0x00; + screen->fb[0].greenMask = 0x00; + screen->fb[0].redMask = 0x00; + break; + case 15: + screen->fb[0].visuals = (1 << TrueColor); + screen->fb[0].blueMask = 0x001f; + screen->fb[0].greenMask = 0x03e0; + screen->fb[0].redMask = 0x7c00; + break; + case 16: + screen->fb[0].visuals = (1 << TrueColor); + screen->fb[0].blueMask = 0x001f; + screen->fb[0].greenMask = 0x07e0; + screen->fb[0].redMask = 0xf800; + break; + } + screen_size = screen->fb[0].byteStride * screen->height; + + screen->driver = pcmcias; + + return TRUE; +} + +void * +tridentWindowLinear (ScreenPtr pScreen, + CARD32 row, + CARD32 offset, + int mode, + CARD32 *size, + void *closure) +{ + KdScreenPriv(pScreen); + pcmciaCardInfo *pcmciac = pScreenPriv->card->driver; + + if (!pScreenPriv->enabled) + return 0; + + *size = pScreenPriv->screen->fb[0].byteStride; + return (CARD8 *) pcmciac->fb + row * pScreenPriv->screen->fb[0].byteStride + offset; +} + +void * +cirrusWindowWindowed (ScreenPtr pScreen, + CARD32 row, + CARD32 offset, + int mode, + CARD32 *size, + void *closure) +{ + KdScreenPriv(pScreen); + pcmciaCardInfo *pcmciac = pScreenPriv->card->driver; + int bank, boffset; + + if (!pScreenPriv->enabled) + return 0; + + bank = (row * pScreenPriv->screen->fb[0].byteStride) / 0x1000; + pcmciaWriteIndex(pcmciac, 0x3ce, 0x0B, 0x0c); + pcmciaWriteIndex(pcmciac, 0x3ce, 0x09, bank); + pcmciaWriteIndex(pcmciac, 0x3ce, 0x0A, bank); + *size = pScreenPriv->screen->fb[0].byteStride; + return (CARD8 *) pcmciac->fb + (row * pScreenPriv->screen->fb[0].byteStride) - (bank * 0x1000) + offset; +} + +LayerPtr +pcmciaLayerCreate (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + pcmciaCardInfo *pcmciac = pScreenPriv->card->driver; + pcmciaScreenInfo *pcmcias = (pcmciaScreenInfo *) pScreenPriv->screen->driver; + ShadowUpdateProc update; + ShadowWindowProc window; + KdMouseMatrix m; + PixmapPtr pPixmap; + int kind; + + switch (pcmcias->rotation) { + case 0: + pScreen->width = screen->width; + pScreen->height = screen->height; + pScreen->mmWidth = screen->width_mm; + pScreen->mmHeight = screen->height_mm; + m.matrix[0][0] = 1; m.matrix[0][1] = 0; m.matrix[0][2] = 0; + m.matrix[1][0] = 0; m.matrix[1][1] = 1; m.matrix[1][2] = 0; + break; + case 90: + pScreen->width = screen->height; + pScreen->height = screen->width; + pScreen->mmWidth = screen->height_mm; + pScreen->mmHeight = screen->width_mm; + m.matrix[0][0] = 0; m.matrix[0][1] = -1; m.matrix[0][2] = screen->height - 1; + m.matrix[1][0] = 1; m.matrix[1][1] = 0; m.matrix[1][2] = 0; + break; + case 180: + pScreen->width = screen->width; + pScreen->height = screen->height; + pScreen->mmWidth = screen->width_mm; + pScreen->mmHeight = screen->height_mm; + m.matrix[0][0] = -1; m.matrix[0][1] = 0; m.matrix[0][2] = screen->width - 1; + m.matrix[1][0] = 0; m.matrix[1][1] = -1; m.matrix[1][2] = screen->height - 1; + break; + case 270: + pScreen->width = screen->height; + pScreen->height = screen->width; + pScreen->mmWidth = screen->height_mm; + pScreen->mmHeight = screen->width_mm; + m.matrix[0][0] = 0; m.matrix[0][1] = 1; m.matrix[0][2] = 0; + m.matrix[1][0] = -1; m.matrix[1][1] = 0; m.matrix[1][2] = screen->width - 1; + break; + } + KdSetMouseMatrix (&m); + + if (pcmciac->HP) { + window = tridentWindowLinear; + switch (pcmcias->rotation) { + case 0: + update = tridentUpdatePacked; + break; + case 90: + switch (pScreenPriv->screen->fb[0].bitsPerPixel) { + case 8: + update = shadowUpdateRotate8_90; break; + case 16: + update = shadowUpdateRotate16_90; break; + } + break; + case 180: + switch (pScreenPriv->screen->fb[0].bitsPerPixel) { + case 8: + update = shadowUpdateRotate8_180; break; + case 16: + update = shadowUpdateRotate16_180; break; + } + break; + case 270: + switch (pScreenPriv->screen->fb[0].bitsPerPixel) { + case 8: + update = shadowUpdateRotate8_270; break; + case 16: + update = shadowUpdateRotate16_270; break; + } + break; + } + } else { + window = cirrusWindowWindowed; + switch (pcmcias->rotation) { + case 0: + update = cirrusUpdatePacked; + break; + case 90: + switch (pScreenPriv->screen->fb[0].bitsPerPixel) { + case 8: + update = shadowUpdateRotate8_90; break; + case 16: + update = shadowUpdateRotate16_90; break; + } + break; + case 180: + switch (pScreenPriv->screen->fb[0].bitsPerPixel) { + case 8: + update = shadowUpdateRotate8_180; break; + case 16: + update = shadowUpdateRotate16_180; break; + } + break; + case 270: + switch (pScreenPriv->screen->fb[0].bitsPerPixel) { + case 8: + update = shadowUpdateRotate8_270; break; + case 16: + update = shadowUpdateRotate16_270; break; + } + break; + } + } + + if (!update) + abort (); + + kind = LAYER_SHADOW; + pPixmap = 0; + + return LayerCreate (pScreen, kind, screen->fb[0].depth, + pPixmap, update, window, pcmcias->rotation, 0); +} + +#ifdef RANDR +Bool +pcmciaRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) +{ + KdScreenPriv(pScreen); + pcmciaCardInfo *pcmciac = pScreenPriv->card->driver; + KdScreenInfo *screen = pScreenPriv->screen; + pcmciaScreenInfo *pcmcias = (pcmciaScreenInfo *) pScreenPriv->screen->driver; + RRVisualGroupPtr pVisualGroup; + RRGroupOfVisualGroupPtr pGroupOfVisualGroup; + RRScreenSizePtr pSize; + Rotation rotateKind; + int rotation; + int n; + + *rotations = RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270; + + for (n = 0; n < pScreen->numDepths; n++) + if (pScreen->allowedDepths[n].numVids) + break; + if (n == pScreen->numDepths) + return FALSE; + + pVisualGroup = RRCreateVisualGroup (pScreen); + if (!pVisualGroup) + return FALSE; + if (!RRAddDepthToVisualGroup (pScreen, + pVisualGroup, + &pScreen->allowedDepths[n])) + { + RRDestroyVisualGroup (pScreen, pVisualGroup); + return FALSE; + } + + pVisualGroup = RRRegisterVisualGroup (pScreen, pVisualGroup); + if (!pVisualGroup) + return FALSE; + + pGroupOfVisualGroup = RRCreateGroupOfVisualGroup (pScreen); + + if (!RRAddVisualGroupToGroupOfVisualGroup (pScreen, + pGroupOfVisualGroup, + pVisualGroup)) + { + RRDestroyGroupOfVisualGroup (pScreen, pGroupOfVisualGroup); + /* pVisualGroup left until screen closed */ + return FALSE; + } + + pGroupOfVisualGroup = RRRegisterGroupOfVisualGroup (pScreen, pGroupOfVisualGroup); + if (!pGroupOfVisualGroup) + return FALSE; + + pSize = RRRegisterSize (pScreen, + screen->width, + screen->height, + screen->width_mm, + screen->height_mm, + pGroupOfVisualGroup); + + rotation = pcmcias->rotation - screen->rotation; + if (rotation < 0) + rotation += 360; + + switch (rotation) + { + case 0: + rotateKind = RR_Rotate_0; + break; + case 90: + rotateKind = RR_Rotate_90; + break; + case 180: + rotateKind = RR_Rotate_180; + break; + case 270: + rotateKind = RR_Rotate_270; + break; + } + + RRSetCurrentConfig (pScreen, rotateKind, pSize, pVisualGroup); + + return TRUE; + } + +int +pcmciaLayerAdd (WindowPtr pWin, pointer value) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + LayerPtr pLayer = (LayerPtr) value; + + if (!LayerWindowAdd (pScreen, pLayer, pWin)) + return WT_STOPWALKING; + + return WT_WALKCHILDREN; +} + +int +pcmciaLayerRemove (WindowPtr pWin, pointer value) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + LayerPtr pLayer = (LayerPtr) value; + + LayerWindowRemove (pScreen, pLayer, pWin); + + return WT_WALKCHILDREN; +} + +pcmciaRandRSetConfig (ScreenPtr pScreen, + Rotation rotateKind, + RRScreenSizePtr pSize, + RRVisualGroupPtr pVisualGroup) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + FbdevPriv *priv = pScreenPriv->card->driver; + pcmciaScreenInfo *pcmcias = (pcmciaScreenInfo *) pScreenPriv->screen->driver; + int rotation; + Bool wasEnabled = pScreenPriv->enabled; + + /* + * The only thing that can change is rotation + */ + switch (rotateKind) + { + case RR_Rotate_0: + rotation = screen->rotation; + break; + case RR_Rotate_90: + rotation = screen->rotation + 90; + break; + case RR_Rotate_180: + rotation = screen->rotation + 180; + break; + case RR_Rotate_270: + rotation = screen->rotation + 270; + break; + } + if (rotation >= 360) + rotation -= 360; + + if (pcmcias->rotation != rotation) + { + LayerPtr pNewLayer; + int kind; + int oldrotation = pcmcias->rotation; + int oldwidth = pScreen->width; + int oldheight = pScreen->height; + PixmapPtr pPixmap; + + if (wasEnabled) + KdDisableScreen (pScreen); + + pcmcias->rotation = rotation; + pNewLayer = pcmciaLayerCreate (pScreen); + if (!pNewLayer) + { + pcmcias->rotation = oldrotation; + } + if (WalkTree (pScreen, pcmciaLayerAdd, (pointer) pNewLayer) == WT_STOPWALKING) + { + WalkTree (pScreen, pcmciaLayerRemove, (pointer) pNewLayer); + LayerDestroy (pScreen, pNewLayer); + pcmcias->rotation = oldrotation; + pScreen->width = oldwidth; + pScreen->height = oldheight; + if (wasEnabled) + KdEnableScreen (pScreen); + return FALSE; + } + WalkTree (pScreen, pcmciaLayerRemove, (pointer) pcmcias->pLayer); + LayerDestroy (pScreen, pcmcias->pLayer); + pcmcias->pLayer = pNewLayer; + if (wasEnabled) + KdEnableScreen (pScreen); + } + return TRUE; +} + +Bool +pcmciaRandRInit (ScreenPtr pScreen) +{ + rrScrPrivPtr pScrPriv; + + if (!RRScreenInit (pScreen)) + return FALSE; + + pScrPriv = rrGetScrPriv(pScreen); + pScrPriv->rrGetInfo = pcmciaRandRGetInfo; + pScrPriv->rrSetConfig = pcmciaRandRSetConfig; + return TRUE; +} +#endif + +Bool +pcmciaInitScreen (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + pcmciaScreenInfo *pcmcias = (pcmciaScreenInfo *) pScreenPriv->screen->driver; + + if (!LayerStartInit (pScreen)) + return FALSE; + if (!LayerFinishInit (pScreen)) + return FALSE; + pcmcias->pLayer = pcmciaLayerCreate (pScreen); + if (!pcmcias->pLayer) + return FALSE; +#ifdef RANDR + if (!pcmciaRandRInit (pScreen)) + return FALSE; +#endif + return TRUE; +} + +CARD8 +pcmciaReadIndex (pcmciaCardInfo *pcmciac, CARD16 port, CARD8 index) +{ + CARD8 value; + + pcmciac->cop_base[port] = index; + value = pcmciac->cop_base[port+1]; + return value; +} + +void +pcmciaWriteIndex (pcmciaCardInfo *pcmciac, CARD16 port, CARD8 index, CARD8 value) +{ + pcmciac->cop_base[port] = index; + pcmciac->cop_base[port+1] = value; +} + +CARD8 +pcmciaReadReg (pcmciaCardInfo *pcmciac, CARD16 port) +{ + CARD8 value; + + value = pcmciac->cop_base[port]; + + return value; +} + +void +pcmciaWriteReg (pcmciaCardInfo *pcmciac, CARD16 port, CARD8 value) +{ + pcmciac->cop_base[port] = value; +} + + +void +pcmciaPause () +{ + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = 50 * 1000; + select (1, 0, 0, 0, &tv); +} + +void +pcmciaPreserve (KdCardInfo *card) +{ +} + +/* CLOCK_FACTOR is double the osc freq in kHz (osc = 14.31818 MHz) */ +#define CLOCK_FACTOR 28636 + +/* stability constraints for internal VCO -- MAX_VCO also determines the maximum Video pixel clock */ +#define MIN_VCO CLOCK_FACTOR +#define MAX_VCO 111000 + +/* clock in kHz is (numer * CLOCK_FACTOR / (denom & 0x3E)) >> (denom & 1) */ +#define VCOVAL(n, d) \ + ((((n) & 0x7F) * CLOCK_FACTOR / ((d) & 0x3E)) ) + +#define CLOCKVAL(n, d) \ + (VCOVAL(n, d) >> ((d) & 1)) + +int CirrusFindClock(freq, max_clock, num_out, den_out) + int freq; + int max_clock; + int *num_out; + int *den_out; +{ + int n; + int num = 0, den = 0; + int mindiff; + + /* + * If max_clock is greater than the MAX_VCO default, ignore + * MAX_VCO. On the other hand, if MAX_VCO is higher than max_clock, + * make use of the higher MAX_VCO value. + */ + if (MAX_VCO > max_clock) + max_clock = MAX_VCO; + + mindiff = freq; + for (n = 0x10; n < 0x7f; n++) { + int d; + for (d = 0x14; d < 0x3f; d++) { + int c, diff; + /* Avoid combinations that can be unstable. */ + if ((VCOVAL(n, d) < MIN_VCO) || (VCOVAL(n, d) > max_clock)) + continue; + c = CLOCKVAL(n, d); + diff = abs(c - freq); + if (diff < mindiff) { + mindiff = diff; + num = n; + den = d; + } + } + } + + *num_out = num; + *den_out = den; + + return 0; +} + + +void +tridentSetCLK(int clock, CARD8 *a, CARD8 *b) +{ + int powerup[4] = { 1,2,4,8 }; + int clock_diff = 750; + int freq, ffreq; + int m, n, k; + int p, q, r, s; + int startn, endn; + int endm, endk; + + p = q = r = s = 0; + + startn = 0; + endn = 121; + endm = 31; + endk = 1; + + freq = clock; + + for (k=0;k<=endk;k++) + for (n=startn;n<=endn;n++) + for (m=1;m<=endm;m++) + { + ffreq = ( ( ((n + 8) * CLOCK) / ((m + 2) * powerup[k]) )); + if ((ffreq > freq - clock_diff) && (ffreq < freq + clock_diff)) + { + clock_diff = (freq > ffreq) ? freq - ffreq : ffreq - freq; + p = n; q = m; r = k; s = ffreq; + } + } + +#if 0 + ErrorF ("ffreq %d clock %d\n", s, clock); +#endif + if (s == 0) + { + FatalError("Unable to set programmable clock.\n" + "Frequency %d is not a valid clock.\n" + "Please modify XF86Config for a new clock.\n", + freq); + } + + /* N is first 7bits, first M bit is 8th bit */ + *a = ((1 & q) << 7) | p; + /* first 4bits are rest of M, 1bit for K value */ + *b = (((q & 0xFE) >> 1) | (r << 4)); +} + +Bool +pcmciaEnable (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + pcmciaCardInfo *pcmciac = pScreenPriv->card->driver; + pcmciaScreenInfo *pcmcias = (pcmciaScreenInfo *) pScreenPriv->screen->driver; + int i,j; + unsigned char Sequencer[6]; + unsigned char CRTC[31]; + unsigned char Graphics[9]; + unsigned char Attribute[21]; + unsigned char MiscOutReg; + pcmciaDisplayModeRec mode = pcmciaDefaultModes[pcmcias->Mode]; + + /* + * compute correct Hsync & Vsync polarity + */ + if ((mode.Flags & (V_PHSYNC | V_NHSYNC)) + && (mode.Flags & (V_PVSYNC | V_NVSYNC))) + { + MiscOutReg = 0x23; + if (mode.Flags & V_NHSYNC) MiscOutReg |= 0x40; + if (mode.Flags & V_NVSYNC) MiscOutReg |= 0x80; + } + else + { + int VDisplay = mode.VDisplay; + if (VDisplay < 400) + MiscOutReg = 0xA3; /* +hsync -vsync */ + else if (VDisplay < 480) + MiscOutReg = 0x63; /* -hsync +vsync */ + else if (VDisplay < 768) + MiscOutReg = 0xE3; /* -hsync -vsync */ + else + MiscOutReg = 0x23; /* +hsync +vsync */ + } + + /* + * Time Sequencer + */ + if (pScreenPriv->screen->fb[0].depth == 4) + Sequencer[0] = 0x02; + else + Sequencer[0] = 0x00; + Sequencer[1] = 0x01; + Sequencer[2] = 0x0F; + Sequencer[3] = 0x00; /* Font select */ + if (pScreenPriv->screen->fb[0].depth < 8) + Sequencer[4] = 0x06; /* Misc */ + else + Sequencer[4] = 0x0E; /* Misc */ + Sequencer[5] = 0x00; + + /* + * CRTC Controller + */ + CRTC[0] = (mode.HTotal >> 3) - 5; + CRTC[1] = (mode.HDisplay >> 3) - 1; + CRTC[2] = ((min(mode.HSyncStart,mode.HDisplay)) >> 3) - 1; + CRTC[3] = ((((min(mode.HSyncEnd,mode.HTotal)) >> 3) - 1) & 0x1F) | 0x80; + i = (((mode.HSkew << 2) + 0x10) & ~0x1F); + if (i < 0x80) + CRTC[3] |= i; + CRTC[4] = (mode.HSyncStart >> 3); + CRTC[5] = (((((min(mode.HSyncEnd,mode.HTotal)) >> 3) - 1) & 0x20) << 2) + | (((mode.HSyncEnd >> 3)) & 0x1F); + CRTC[6] = (mode.VTotal - 2) & 0xFF; + CRTC[7] = (((mode.VTotal - 2) & 0x100) >> 8) + | (((mode.VDisplay - 1) & 0x100) >> 7) + | ((mode.VSyncStart & 0x100) >> 6) + | ((((min(mode.VSyncStart,mode.VDisplay)) - 1) & 0x100) >> 5) + | 0x10 + | (((mode.VTotal - 2) & 0x200) >> 4) + | (((mode.VDisplay - 1) & 0x200) >> 3) + | ((mode.VSyncStart & 0x200) >> 2); + CRTC[8] = 0x00; + CRTC[9] = ((((min(mode.VSyncStart,mode.VDisplay))-1) & 0x200) >> 4) | 0x40; + CRTC[10] = 0x00; + CRTC[11] = 0x00; + CRTC[12] = 0x00; + CRTC[13] = 0x00; + CRTC[14] = 0x00; + CRTC[15] = 0x00; + CRTC[16] = mode.VSyncStart & 0xFF; + CRTC[17] = (mode.VSyncEnd & 0x0F) | 0x20; + CRTC[18] = (mode.VDisplay - 1) & 0xFF; + if (pScreenPriv->screen->fb[0].depth == 4) + CRTC[19] = pScreenPriv->screen->fb[0].pixelStride >> 4; + else + if (pScreenPriv->screen->fb[0].depth == 8) + CRTC[19] = pScreenPriv->screen->fb[0].pixelStride >> 3; + else + if (pScreenPriv->screen->fb[0].depth == 16 || + pScreenPriv->screen->fb[0].depth == 15) + CRTC[19] = pScreenPriv->screen->fb[0].pixelStride >> 2; + CRTC[20] = 0x00; + CRTC[21] = ((min(mode.VSyncStart,mode.VDisplay)) - 1) & 0xFF; + CRTC[22] = ((min(mode.VSyncEnd,mode.VDisplay)) - 1) & 0xFF; + if (pScreenPriv->screen->fb[0].depth < 8) + CRTC[23] = 0xE3; + else + CRTC[23] = 0xC3; + CRTC[24] = 0xFF; + CRTC[25] = 0x00; + CRTC[26] = 0x00; + if (!pcmciac->HP) + if (mode.Flags & V_INTERLACE) CRTC[26] |= 0x01; + if (pcmciac->HP) + CRTC[27] = 0x00; + else + CRTC[27] = 0x22; + CRTC[28] = 0x00; + CRTC[29] = 0x00; + CRTC[30] = 0x80; + if (pcmciac->HP) + if (mode.Flags & V_INTERLACE) CRTC[30] |= 0x04; + +{ + int nExtBits = 0; + CARD32 ExtBits; + CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 6; + + CRTC[3] = (CRTC[3] & ~0x1F) + | ((((min(mode.HSyncEnd,mode.HTotal)) >> 3) - 1) & 0x1F); + CRTC[5] = (CRTC[5] & ~0x80) + | (((((min(mode.HSyncEnd,mode.HTotal)) >> 3) - 1) & 0x20) << 2); + ExtBits = (((min(mode.HSyncEnd,mode.HTotal)) >> 3) - 1) & ExtBitMask; + + /* First the horizontal case */ + if ((((min(mode.HSyncEnd,mode.HTotal)) >> 3) == (mode.HTotal >> 3))) + { + int i = (CRTC[3] & 0x1F) + | ((CRTC[5] & 0x80) >> 2) + | ExtBits; + if ((i-- > ((((min(mode.HSyncStart,mode.HDisplay)) >> 3) - 1) + & (0x3F | ExtBitMask))) + && ((min(mode.HSyncEnd,mode.HTotal)) == mode.HTotal)) + i = 0; + CRTC[3] = (CRTC[3] & ~0x1F) | (i & 0x1F); + CRTC[5] = (CRTC[5] & ~0x80) | ((i << 2) & 0x80); + ExtBits = i & ExtBitMask; + } +} +{ + CARD32 ExtBits; + CARD32 ExtBitMask = 0; + /* If width is not known nBits should be 0. In this + * case BitMask is set to 0 so we can check for it. */ + CARD32 BitMask = 0; + int VBlankStart = ((min(mode.VSyncStart,mode.VDisplay)) - 1) & 0xFF; + CRTC[22] = ((min(mode.VSyncEnd,mode.VTotal)) - 1) & 0xFF; + ExtBits = ((min(mode.VSyncEnd,mode.VTotal)) - 1) & ExtBitMask; + + if ((min(mode.VSyncEnd,mode.VTotal)) == mode.VTotal) + /* Null top overscan */ + { + int i = CRTC[22] | ExtBits; + if (((BitMask && ((i & BitMask) > (VBlankStart & BitMask))) + || ((i > VBlankStart) && /* 8-bit case */ + ((i & 0x7F) > (VBlankStart & 0x7F)))) && /* 7-bit case */ + !(CRTC[9] & 0x9F)) /* 1 scanline/row */ + i = 0; + else + i = (i - 1); + CRTC[22] = i & 0xFF; + ExtBits = i & 0xFF00; + } +} + + /* + * Graphics Display Controller + */ + Graphics[0] = 0x00; + Graphics[1] = 0x00; + Graphics[2] = 0x00; + Graphics[3] = 0x00; + Graphics[4] = 0x00; + if (pScreenPriv->screen->fb[0].depth == 4) + Graphics[5] = 0x02; + else + Graphics[5] = 0x40; + Graphics[6] = 0x05; /* only map 64k VGA memory !!!! */ + Graphics[7] = 0x0F; + Graphics[8] = 0xFF; + + Attribute[0] = 0x00; /* standard colormap translation */ + Attribute[1] = 0x01; + Attribute[2] = 0x02; + Attribute[3] = 0x03; + Attribute[4] = 0x04; + Attribute[5] = 0x05; + Attribute[6] = 0x06; + Attribute[7] = 0x07; + Attribute[8] = 0x08; + Attribute[9] = 0x09; + Attribute[10] = 0x0A; + Attribute[11] = 0x0B; + Attribute[12] = 0x0C; + Attribute[13] = 0x0D; + Attribute[14] = 0x0E; + Attribute[15] = 0x0F; + if (pScreenPriv->screen->fb[0].depth == 4) + Attribute[16] = 0x81; + else + Attribute[16] = 0x41; + if (pScreenPriv->screen->fb[0].bitsPerPixel == 16) + Attribute[17] = 0x00; + else + Attribute[17] = 0xFF; + Attribute[18] = 0x0F; + Attribute[19] = 0x00; + Attribute[20] = 0x00; + + /* Wake up the card */ + if (pcmciac->HP) { + pcmciaWriteReg(pcmciac, 0x3c3, 0x1); + pcmciaWriteReg(pcmciac, 0x46e8, 0x10); + } else { + pcmciaWriteReg(pcmciac, 0x105, 0x1); + pcmciaWriteReg(pcmciac, 0x46e8, 0x1f); + pcmciaWriteReg(pcmciac, 0x102, 0x1); + pcmciaWriteReg(pcmciac, 0x46e8, 0xf); + pcmciaWriteReg(pcmciac, 0x3c3, 0x1); + } + + if (pcmciac->HP) { + /* unlock */ + pcmciaWriteIndex(pcmciac, 0x3c4, 0x11, 0x92); + j = pcmciaReadIndex(pcmciac, 0x3c4, 0xb); + pcmciaWriteIndex(pcmciac, 0x3c4, 0xe, 0xc2); + + /* switch on dac */ + pcmciaWriteIndex(pcmciac, 0x3d4, 0x29, 0x24); + /* switch on the accelerator */ + pcmciaWriteIndex(pcmciac, 0x3d4, 0x36, 0x80); + + /* bump up memory clk */ + pcmciaWriteReg(pcmciac, 0x43c6, 0x65); + pcmciaWriteReg(pcmciac, 0x43c7, 0x00); + } else { + /* unlock */ + pcmciaWriteIndex(pcmciac, 0x3c4, 0x06, 0x12); + pcmciaWriteReg(pcmciac, 0x3c2, MiscOutReg); + } + + /* synchronous reset */ + pcmciaWriteIndex(pcmciac, 0x3c4, 0, 0); + + pcmciaWriteReg(pcmciac, 0x3da, 0x10); + + for (i=0;i<6;i++) + pcmciaWriteIndex(pcmciac, 0x3c4, i, Sequencer[i]); + + if (pcmciac->HP) { + /* Stick chip into color mode */ + pcmciaWriteIndex(pcmciac, 0x3ce, 0x2f, 0x06); + /* Switch on Linear addressing */ + pcmciaWriteIndex(pcmciac, 0x3d4, 0x21, 0x2e); + } else { + /* Stick chip into 8bit access mode - ugh! */ + pcmciaWriteIndex(pcmciac, 0x3c4, 0x0F, 0x20); /* 0x26 ? */ + /* reset mclk */ + pcmciaWriteIndex(pcmciac, 0x3c4, 0x1F, 0); + } + + pcmciaWriteIndex(pcmciac, 0x3c4, 0, 0x3); + + for (i=0;i<31;i++) + pcmciaWriteIndex(pcmciac, 0x3d4, i, CRTC[i]); + + for (i=0;i<9;i++) + pcmciaWriteIndex(pcmciac, 0x3ce, i, Graphics[i]); + + j = pcmciaReadReg(pcmciac, 0x3da); + + for (i=0;i<21;i++) { + pcmciaWriteReg(pcmciac, 0x3c0, i); + pcmciaWriteReg(pcmciac, 0x3c0, Attribute[i]); + } + + j = pcmciaReadReg(pcmciac, 0x3da); + pcmciaWriteReg(pcmciac, 0x3c0, 0x20); + + j = pcmciaReadReg(pcmciac, 0x3c8); + j = pcmciaReadReg(pcmciac, 0x3c6); + j = pcmciaReadReg(pcmciac, 0x3c6); + j = pcmciaReadReg(pcmciac, 0x3c6); + j = pcmciaReadReg(pcmciac, 0x3c6); + switch (pScreenPriv->screen->fb[0].depth) { + /* This is here for completeness, when/if we ever do 4bpp */ + case 4: + pcmciaWriteReg(pcmciac, 0x3c6, 0x0); + if (pcmciac->HP) { + pcmciaWriteIndex(pcmciac, 0x3ce, 0x0f, 0x90); + pcmciaWriteIndex(pcmciac, 0x3d4, 0x38, 0x00); + } else + pcmciaWriteIndex(pcmciac, 0x3c4, 0x07, 0x00); + break; + case 8: + pcmciaWriteReg(pcmciac, 0x3c6, 0x0); + if (pcmciac->HP) { + pcmciaWriteIndex(pcmciac, 0x3ce, 0x0f, 0x92); + pcmciaWriteIndex(pcmciac, 0x3d4, 0x38, 0x00); + } else + pcmciaWriteIndex(pcmciac, 0x3c4, 0x07, 0x01); + break; + case 15: + if (pcmciac->HP) { + pcmciaWriteReg(pcmciac, 0x3c6, 0x10); + pcmciaWriteIndex(pcmciac, 0x3ce, 0x0f, 0x9a); + pcmciaWriteIndex(pcmciac, 0x3d4, 0x38, 0x04); + } else { + pcmciaWriteReg(pcmciac, 0x3c6, 0xC0); + pcmciaWriteIndex(pcmciac, 0x3c4, 0x07, 0x03); + } + break; + case 16: + if (pcmciac->HP) { + pcmciaWriteReg(pcmciac, 0x3c6, 0x30); + pcmciaWriteIndex(pcmciac, 0x3ce, 0x0f, 0x9a); + pcmciaWriteIndex(pcmciac, 0x3d4, 0x38, 0x04); + } else { + pcmciaWriteReg(pcmciac, 0x3c6, 0xC1); + pcmciaWriteIndex(pcmciac, 0x3c4, 0x07, 0x03); + } + break; + } + j = pcmciaReadReg(pcmciac, 0x3c8); + + pcmciaWriteReg(pcmciac, 0x3c6, 0xff); + + for (i=0;i<256;i++) { + pcmciaWriteReg(pcmciac, 0x3c8, i); + pcmciaWriteReg(pcmciac, 0x3c9, i); + pcmciaWriteReg(pcmciac, 0x3c9, i); + pcmciaWriteReg(pcmciac, 0x3c9, i); + } + + /* Set the Clock */ + if (pcmciac->HP) { + CARD8 a,b; + int clock = mode.Clock; + if (pScreenPriv->screen->fb[0].bitsPerPixel == 16) + clock *= 2; + tridentSetCLK(clock, &a, &b); + pcmciaWriteReg(pcmciac, 0x43c8, a); + pcmciaWriteReg(pcmciac, 0x43c9, b); + } else { + int num, den; + unsigned char tmp; + int clock = mode.Clock; + if (pScreenPriv->screen->fb[0].bitsPerPixel == 16) + clock *= 2; + + CirrusFindClock(clock, MAX_VCO, &num, &den); + + tmp = pcmciaReadIndex(pcmciac, 0x3c4, 0x0d); + pcmciaWriteIndex(pcmciac, 0x3c4, 0x0d, (tmp & 0x80) | num); + tmp = pcmciaReadIndex(pcmciac, 0x3c4, 0x1d); + pcmciaWriteIndex(pcmciac, 0x3c4, 0x1d, (tmp & 0xc0) | den); + } + pcmciaWriteReg(pcmciac, 0x3c2, MiscOutReg | 0x08); + +#if 0 /* for debugging */ + for (i=1;i<0x3f;i++) + ErrorF("0x%x, ",pcmciaReadIndex(pcmciac, 0x3c4, i)); + + ErrorF("\n"); + + for (i=0;i<0x3f;i++) + ErrorF("0x%x, ",pcmciaReadIndex(pcmciac, 0x3ce, i)); + + ErrorF("\n"); + + for (i=0;i<0x3f;i++) + ErrorF("0x%x, ",pcmciaReadIndex(pcmciac, 0x3d4, i)); +#endif + + return TRUE; +} + +void +pcmciaDisable (ScreenPtr pScreen) +{ +} + +const CARD8 tridentDPMSModes[4] = { + 0x00, /* KD_DPMS_NORMAL */ + 0x01, /* KD_DPMS_STANDBY */ + 0x02, /* KD_DPMS_SUSPEND */ + 0x03, /* KD_DPMS_POWERDOWN */ +}; + +Bool +pcmciaDPMS (ScreenPtr pScreen, int mode) +{ + KdScreenPriv(pScreen); + pcmciaCardInfo *pcmciac = pScreenPriv->card->driver; + + if (pcmciac->HP) { + pcmciaWriteIndex (pcmciac, 0x3ce, 0x23, tridentDPMSModes[mode]); + pcmciaPause (); + } else { + /* Voyager */ + } + + return TRUE; +} + +void +pcmciaRestore (KdCardInfo *card) +{ +} + +void +pcmciaScreenFini (KdScreenInfo *screen) +{ + pcmciaScreenInfo *pcmcias = (pcmciaScreenInfo *) screen->driver; + + xfree (pcmcias); + screen->driver = 0; +} + +void +pcmciaCardFini (KdCardInfo *card) +{ + pcmciaCardInfo *pcmciac = card->driver; + + if (pcmciac->cop_base) + KdUnmapDevice ((void *) pcmciac->cop_base, PCMCIA_COP_SIZE(card)); +} + +void +pcmciaGetColors (ScreenPtr pScreen, int fb, int ndef, xColorItem *pdefs) +{ + KdScreenPriv(pScreen); + pcmciaCardInfo *pcmciac = pScreenPriv->card->driver; + + while (ndef--) + { + pcmciaWriteReg (pcmciac, 0x3C7, pdefs->pixel); + pdefs->red = pcmciaReadReg (pcmciac, 0x3C9) << 10; + pdefs->green = pcmciaReadReg (pcmciac, 0x3C9) << 10; + pdefs->blue = pcmciaReadReg (pcmciac, 0x3C9) << 10; + pdefs++; + } +} + +void +pcmciaPutColors (ScreenPtr pScreen, int fb, int ndef, xColorItem *pdefs) +{ + KdScreenPriv(pScreen); + pcmciaCardInfo *pcmciac = pScreenPriv->card->driver; + + while (ndef--) + { + pcmciaWriteReg (pcmciac, 0x3C8, pdefs->pixel); + pcmciaWriteReg (pcmciac, 0x3C9, pdefs->red >> 10); + pcmciaWriteReg (pcmciac, 0x3C9, pdefs->green >> 10); + pcmciaWriteReg (pcmciac, 0x3C9, pdefs->blue >> 10); + pdefs++; + } +} + + +KdCardFuncs pcmciaFuncs = { + pcmciaCardInit, /* cardinit */ + pcmciaScreenInit, /* scrinit */ + pcmciaInitScreen, /* initScreen */ + pcmciaPreserve, /* preserve */ + pcmciaEnable, /* enable */ + pcmciaDPMS, /* dpms */ + pcmciaDisable, /* disable */ + pcmciaRestore, /* restore */ + pcmciaScreenFini, /* scrfini */ + pcmciaCardFini, /* cardfini */ + + pcmciaCursorInit, /* initCursor */ + pcmciaCursorEnable, /* enableCursor */ + pcmciaCursorDisable, /* disableCursor */ + pcmciaCursorFini, /* finiCursor */ + pcmciaRecolorCursor, /* recolorCursor */ + +#if 0 /* not yet */ + pcmciaDrawInit, /* initAccel */ + pcmciaDrawEnable, /* enableAccel */ + pcmciaDrawSync, /* syncAccel */ + pcmciaDrawDisable, /* disableAccel */ + pcmciaDrawFini, /* finiAccel */ +#else + 0, + 0, + 0, + 0, + 0, +#endif + + pcmciaGetColors, /* getColors */ + pcmciaPutColors, /* putColors */ +}; diff --git a/xc/programs/Xserver/hw/kdrive/pcmcia/pcmcia.h b/xc/programs/Xserver/hw/kdrive/pcmcia/pcmcia.h new file mode 100644 index 000000000..58eb58bd9 --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/pcmcia/pcmcia.h @@ -0,0 +1,264 @@ +/* + * Copyright 2001 by Alan Hourihane, Sychdyn, North Wales, UK. + * + * 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 Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE 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. + * + * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> + */ +/* $XFree86: xc/programs/Xserver/hw/kdrive/pcmcia/pcmcia.h,v 1.2 2001/06/20 21:53:31 alanh Exp $ */ + +#ifndef _PCMCIA_H_ +#define _PCMCIA_H_ + +#include <fbdev.h> + +/* + * offset from ioport beginning + */ + +#define PCMCIA_COP_BASE(c) 0x20000000 +#define PCMCIA_COP_SIZE(c) 0x10000 +#define TRIDENT_COP_OFF(c) 0x2100 + +typedef volatile CARD8 VOL8; +typedef volatile CARD16 VOL16; +typedef volatile CARD32 VOL32; + +typedef struct _cop { + VOL32 src_start_xy; /* 0x00 */ + VOL32 src_end_xy; /* 0x04 */ + VOL32 dst_start_xy; /* 0x08 */ + VOL32 dst_end_xy; /* 0x0c */ + VOL32 alpha; /* 0x10 */ + CARD8 pad14[0xc]; /* 0x14 */ + VOL32 multi; /* 0x20 */ + +#define COP_MULTI_CLIP_TOP_LEFT 0x10000000 +#define COP_MULTI_DEPTH 0x40000000 +#define COP_MULTI_COLOR_KEY 0x70000000 +#define COP_MULTI_STYLE 0x50000000 +#define COP_MULTI_PATTERN 0x80000000 +#define COP_MULTI_ROP 0x90000000 +#define COP_MULTI_STRIDE 0x60000000 +#define COP_MULTI_Z 0xa0000000 +#define COP_MULTI_ALPHA 0xb0000000 +#define COP_MULTI_TEXTURE 0xd0000000 +#define COP_MULTI_TEXTURE_BOUND 0xe0000000 +#define COP_MULTI_TEXTURE_ADVANCED 0x20000000 +#define COP_MULTI_MASK 0xf0000000 + +#define COP_DEPTH_8 0x00000000 +#define COP_DEPTH_16 0x00000001 +#define COP_DEPTH_24_32 0x00000002 +#define COP_DEPTH_15 0x00000005 +#define COP_DEPTH_DITHER_DISABLE 0x00000008 + + +#define COP_ALPHA_SRC_BLEND_0 0x00000000 +#define COP_ALPHA_SRC_BLEND_1 0x00000001 +#define COP_ALPHA_SRC_BLEND_SRC_C 0x00000002 +#define COP_ALPHA_SRC_BLEND_1_SRC_C 0x00000003 +#define COP_ALPHA_SRC_BLEND_SRC_A 0x00000004 +#define COP_ALPHA_SRC_BLEND_1_SRC_A 0x00000005 +#define COP_ALPHA_SRC_BLEND_DST_A 0x00000006 +#define COP_ALPHA_SRC_BLEND_1_DST_A 0x00000007 +#define COP_ALPHA_SRC_BLEND_DST_C 0x00000008 +#define COP_ALPHA_SRC_BLEND_1_DST_C 0x00000009 +#define COP_ALPHA_SRC_BLEND_SAT 0x0000000A +#define COP_ALPHA_SRC_BLEND_BG 0x0000000B + +#define COP_ALPHA_DST_BLEND_0 0x00000000 +#define COP_ALPHA_DST_BLEND_1 0x00000010 +#define COP_ALPHA_DST_BLEND_SRC_C 0x00000020 +#define COP_ALPHA_DST_BLEND_1_SRC_C 0x00000030 +#define COP_ALPHA_DST_BLEND_SRC_A 0x00000040 +#define COP_ALPHA_DST_BLEND_1_SRC_A 0x00000050 +#define COP_ALPHA_DST_BLEND_DST_A 0x00000060 +#define COP_ALPHA_DST_BLEND_1_DST_A 0x00000070 +#define COP_ALPHA_DST_BLEND_DST_C 0x00000080 +#define COP_ALPHA_DST_BLEND_1_DST_C 0x00000090 +#define COP_ALPHA_DST_BLEND_OTHER 0x000000A0 + +#define COP_ALPHA_RESULT_ALPHA 0x00100000 +#define COP_ALPHA_DEST_ALPHA 0x00200000 +#define COP_ALPHA_SOURCE_ALPHA 0x00400000 +#define COP_ALPHA_WRITE_ENABLE 0x00800000 +#define COP_ALPHA_TEST_ENABLE 0x01000000 +#define COP_ALPHA_BLEND_ENABLE 0x02000000 +#define COP_ALPHA_DEST_VALUE 0x04000000 +#define COP_ALPHA_SOURCE_VALUE 0x08000000 + + VOL32 command; /* 0x24 */ +#define COP_OP_NULL 0x00000000 +#define COP_OP_LINE 0x20000000 +#define COP_OP_BLT 0x80000000 +#define COP_OP_TEXT 0x90000000 +#define COP_OP_POLY 0xb0000000 +#define COP_OP_POLY2 0xe0000000 +#define COP_SCL_EXPAND 0x00800000 +#define COP_SCL_OPAQUE 0x00400000 +#define COP_SCL_REVERSE 0x00200000 +#define COP_SCL_MONO_OFF 0x001c0000 +#define COP_LIT_TEXTURE 0x00004000 +#define COP_BILINEAR 0x00002000 +#define COP_OP_ZBUF 0x00000800 +#define COP_OP_ROP 0x00000400 +#define COP_OP_FG 0x00000200 +#define COP_OP_FB 0x00000080 +#define COP_X_REVERSE 0x00000004 +#define COP_CLIP 0x00000001 + VOL32 texture_format; /* 0x28 */ + CARD8 pad2c[0x4]; /* 0x2c */ + + VOL32 clip_bottom_right; /* 0x30 */ + VOL32 dataIII; /* 0x34 */ + VOL32 dataIV; /* 0x38 */ + CARD8 pad3c[0x8]; /* 0x3c */ + + VOL32 fg; /* 0x44 */ + VOL32 bg; /* 0x48 */ + CARD8 pad4c[0x4]; /* 0x4c */ + + VOL32 pattern_fg; /* 0x50 */ + VOL32 pattern_bg; /* 0x54 */ + CARD8 pad58[0xc]; /* 0x58 */ + + VOL32 status; /* 0x64 */ +#define COP_STATUS_BE_BUSY 0x80000000 +#define COP_STATUS_DPE_BUSY 0x20000000 +#define COP_STATUS_MI_BUSY 0x10000000 +#define COP_STATUS_FIFO_BUSY 0x08000000 +#define COP_STATUS_WB_BUSY 0x00800000 +#define COP_STATUS_Z_FAILED 0x00400000 +#define COP_STATUS_EFFECTIVE 0x00200000 +#define COP_STATUS_LEFT_VIEW 0x00080000 + + CARD8 pad68[0x4]; /* 0x68 */ + + VOL32 src_offset; /* 0x6c */ + VOL32 z_offset; /* 0x70 */ + CARD8 pad74[0x4]; /* 0x74 */ + + VOL32 display_offset; /* 0x78 */ + VOL32 dst_offset; /* 0x7c */ + CARD8 pad80[0x34]; /* 0x80 */ + + VOL32 semaphore; /* 0xb4 */ +} Cop; + +#define TRI_XY(x,y) ((y) << 16 | (x)) + +typedef struct _pcmciaCardInfo { + CARD8 *fb; + Bool HP; + CARD8 *cop_base; + Cop *cop; + CARD32 *window; + CARD32 cop_depth; + CARD32 cop_stride; +} pcmciaCardInfo; + +#define getpcmciaCardInfo(kd) ((pcmciaCardInfo *) ((kd)->card->driver)) +#define pcmciaCardInfo(kd) pcmciaCardInfo *pcmciac = getpcmciaCardInfo(kd) + +typedef struct _pcmciaCursor { + int width, height; + int xhot, yhot; + Bool has_cursor; + CursorPtr pCursor; + Pixel source, mask; +} pcmciaCursor; + +#define PCMCIA_CURSOR_WIDTH 64 +#define PCMCIA_CURSOR_HEIGHT 64 + +typedef struct _pcmciaScreenInfo { + int Mode; + CARD8 *cursor_base; + CARD8 *screen; + CARD8 *off_screen; + int off_screen_size; + int rotation; + LayerPtr pLayer; + pcmciaCursor cursor; +} pcmciaScreenInfo; + +#define getpcmciaScreenInfo(kd) ((pcmciaScreenInfo *) ((kd)->screen->driver)) +#define pcmciaScreenInfo(kd) pcmciaScreenInfo *pcmcias = getpcmciaScreenInfo(kd) + +Bool +pcmciaDrawInit (ScreenPtr pScreen); + +void +pcmciaDrawEnable (ScreenPtr pScreen); + +void +pcmciaDrawSync (ScreenPtr pScreen); + +void +pcmciaDrawDisable (ScreenPtr pScreen); + +void +pcmciaDrawFini (ScreenPtr pScreen); + +CARD8 +pcmciaReadIndex (pcmciaCardInfo *pcmciac, CARD16 port, CARD8 index); + +void +pcmciaWriteIndex (pcmciaCardInfo *pcmciac, CARD16 port, CARD8 index, CARD8 value); + +void +pcmciaWriteReg (pcmciaCardInfo *pcmciac, CARD16 port, CARD8 value); + +Bool +pcmciaCursorInit (ScreenPtr pScreen); + +void +pcmciaCursorEnable (ScreenPtr pScreen); + +void +pcmciaCursorDisable (ScreenPtr pScreen); + +void +pcmciaCursorFini (ScreenPtr pScreen); + +void +pcmciaRecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdef); + +typedef struct _pcmciaDisplayModeRec { + int Width; + int Height; + int Refresh; + int Clock; /* pixel clock freq */ + int HDisplay; /* horizontal timing */ + int HSyncStart; + int HSyncEnd; + int HTotal; + int HSkew; + int VDisplay; /* vertical timing */ + int VSyncStart; + int VSyncEnd; + int VTotal; + int VScan; + int Flags; +} pcmciaDisplayModeRec, *pcmciaDisplayModePtr; + +extern KdCardFuncs pcmciaFuncs; + +#endif /* _PCMCIA_H_ */ diff --git a/xc/programs/Xserver/hw/kdrive/pcmcia/pcmciacurs.c b/xc/programs/Xserver/hw/kdrive/pcmcia/pcmciacurs.c new file mode 100644 index 000000000..78d50fb75 --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/pcmcia/pcmciacurs.c @@ -0,0 +1,449 @@ +/* + * Copyright 2001 by Alan Hourihane, Sychdyn, North Wales, UK. + * + * 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 Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE 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. + * + * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> + */ +/* $XFree86: xc/programs/Xserver/hw/kdrive/pcmcia/pcmciacurs.c,v 1.1 2001/05/23 08:56:09 alanh Exp $ */ + +#include "pcmcia.h" +#include "cursorstr.h" + +#define SetupCursor(s) KdScreenPriv(s); \ + pcmciaCardInfo(pScreenPriv); \ + pcmciaScreenInfo(pScreenPriv); \ + pcmciaCursor *pCurPriv = &pcmcias->cursor + +static void +_pcmciaMoveCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor(pScreen); + CARD8 xlow, xhigh, ylow, yhigh; + CARD8 xoff, yoff; + + x -= pCurPriv->xhot; + xoff = 0; + if (x < 0) + { + xoff = -x; + x = 0; + } + y -= pCurPriv->yhot; + yoff = 0; + if (y < 0) + { + yoff = -y; + y = 0; + } + + /* This is the recommended order to move the cursor */ + if (pcmciac->HP) { + xlow = (CARD8) x; + xhigh = (CARD8) (x >> 8); + ylow = (CARD8) y; + yhigh = (CARD8) (y >> 8); + pcmciaWriteIndex (pcmciac, 0x3d4, 0x40, xlow); + pcmciaWriteIndex (pcmciac, 0x3d4, 0x41, xhigh); + pcmciaWriteIndex (pcmciac, 0x3d4, 0x42, ylow); + pcmciaWriteIndex (pcmciac, 0x3d4, 0x43, yhigh); + pcmciaWriteIndex (pcmciac, 0x3d4, 0x46, xoff); + pcmciaWriteIndex (pcmciac, 0x3d4, 0x47, yoff); + } else { + x >>= 3; + y >>= 3; + xlow = (CARD8) x; + xhigh = (CARD8) (x >> 8); + ylow = (CARD8) y; + yhigh = (CARD8) (y >> 8); + /* Don't be alarmed, yes the upper 3bits of the index are correct */ + pcmciaWriteIndex (pcmciac, 0x3c4, 0x10 | xhigh << 5, xlow); + pcmciaWriteIndex (pcmciac, 0x3c4, 0x11 | yhigh << 5, ylow); + } +} + +static void +pcmciaMoveCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor (pScreen); + + if (!pCurPriv->has_cursor) + return; + + if (!pScreenPriv->enabled) + return; + + _pcmciaMoveCursor (pScreen, x, y); +} + +static void +pcmciaAllocCursorColors (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + + KdAllocateCursorPixels (pScreen, 0, pCursor, + &pCurPriv->source, &pCurPriv->mask); + switch (pScreenPriv->screen->fb[0].bitsPerPixel) { + case 4: + pCurPriv->source |= pCurPriv->source << 4; + pCurPriv->mask |= pCurPriv->mask << 4; + case 8: + pCurPriv->source |= pCurPriv->source << 8; + pCurPriv->mask |= pCurPriv->mask << 8; + case 16: + pCurPriv->source |= pCurPriv->source << 16; + pCurPriv->mask |= pCurPriv->mask << 16; + } +} + +static void +pcmciaSetCursorColors (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + CARD32 fg, bg; + + fg = pCurPriv->source; + bg = pCurPriv->mask; + + if (pcmciac->HP) { + /* + * This trident chip uses the palette for it's cursor colors - ouch! + * We enforce it to always stay the black/white colors as we don't + * want it to muck with the overscan color. Tough. Use softCursor + * if you want to change cursor colors. + */ + pcmciaWriteReg (pcmciac, 0x3c8, 0xff); /* DAC 0 */ + pcmciaWriteReg (pcmciac, 0x3c9, 0x00); + pcmciaWriteReg (pcmciac, 0x3c9, 0x00); + pcmciaWriteReg (pcmciac, 0x3c9, 0x00); + pcmciaWriteReg (pcmciac, 0x3c8, 0x00); /* DAC 255 */ + pcmciaWriteReg (pcmciac, 0x3c9, 0x3f); + pcmciaWriteReg (pcmciac, 0x3c9, 0x3f); + pcmciaWriteReg (pcmciac, 0x3c9, 0x3f); + } else { + CARD8 temp; + temp = pcmciaReadIndex(pcmciac, 0x3c4, 0x12); + pcmciaWriteIndex (pcmciac, 0x3c4, 0x12, (temp & 0xFE) | 0x02); + + pcmciaWriteReg (pcmciac, 0x3c8, 0x00); /* DAC 256 */ + pcmciaWriteReg (pcmciac, 0x3c9, fg); + pcmciaWriteReg (pcmciac, 0x3c9, fg >> 8); + pcmciaWriteReg (pcmciac, 0x3c9, fg >> 16); + pcmciaWriteReg (pcmciac, 0x3c8, 0x00); /* DAC 257 */ + pcmciaWriteReg (pcmciac, 0x3c9, bg); + pcmciaWriteReg (pcmciac, 0x3c9, bg >> 8); + pcmciaWriteReg (pcmciac, 0x3c9, bg >> 16); + + pcmciaWriteIndex (pcmciac, 0x3c4, 0x12, temp); + } +} + +void +pcmciaRecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdef) +{ + SetupCursor (pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + xColorItem sourceColor, maskColor; + + if (!pCurPriv->has_cursor || !pCursor) + return; + + if (!pScreenPriv->enabled) + return; + + if (pdef) + { + while (ndef) + { + if (pdef->pixel == pCurPriv->source || + pdef->pixel == pCurPriv->mask) + break; + ndef--; + } + if (!ndef) + return; + } + pcmciaAllocCursorColors (pScreen); + pcmciaSetCursorColors (pScreen); +} + +#define InvertBits32(v) { \ + v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555); \ + v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333); \ + v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f); \ +} + +static void +pcmciaLoadCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor(pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + CursorBitsPtr bits = pCursor->bits; + int w, h; + CARD8 *ram; + CARD32 *msk, *mskLine, *src, *srcLine; + int i, j; + int cursor_address; + int lwsrc; + unsigned char ramdac_control_; + CARD32 offset; + + /* + * Allocate new colors + */ + pcmciaAllocCursorColors (pScreen); + + pCurPriv->pCursor = pCursor; + pCurPriv->xhot = pCursor->bits->xhot; + pCurPriv->yhot = pCursor->bits->yhot; + + /* + * Stick new image into cursor memory + */ + if (pcmciac->HP) { + ram = (CARD8 *) pcmcias->cursor_base; + } else { + /* The last bank */ + ram = (CARD8 *) pcmciac->fb; + pcmciaWriteIndex (pcmciac, 0x3ce, 0x09, 0x7f); + pcmciaWriteIndex (pcmciac, 0x3ce, 0x0A, 0x7f); + } + + mskLine = (CARD32 *) bits->mask; + srcLine = (CARD32 *) bits->source; + + h = bits->height; + if (h > PCMCIA_CURSOR_HEIGHT) + h = PCMCIA_CURSOR_HEIGHT; + + lwsrc = BitmapBytePad(bits->width) / 4; + + for (i = 0; i < PCMCIA_CURSOR_HEIGHT; i++) { + msk = mskLine; + src = srcLine; + mskLine += lwsrc; + srcLine += lwsrc; + for (j = 0; j < PCMCIA_CURSOR_WIDTH / 32; j++) { + + CARD32 m, s; + + if (i < h && j < lwsrc) + { + m = *msk++; + s = *src++; + InvertBits32(m); + InvertBits32(s); + } + else + { + m = 0; + s = 0; + } + + /* Do 8bit access */ + *ram++ = (m & 0xff); + *ram++ = (m & 0xff00) >> 8; + *ram++ = (m & 0xff0000) >> 16; + *ram++ = (m & 0xff000000) >> 24; + *ram++ = (s & 0xff); + *ram++ = (s & 0xff00) >> 8; + *ram++ = (s & 0xff0000) >> 16; + *ram++ = (s & 0xff000000) >> 24; + } + } + + /* Set address for cursor bits */ + if (pcmciac->HP) { + offset = pcmcias->cursor_base - (CARD8 *) pcmcias->screen; + offset >>= 10; + pcmciaWriteIndex (pcmciac, 0x3d4, 0x44, (CARD8) (offset & 0xff)); + pcmciaWriteIndex (pcmciac, 0x3d4, 0x45, (CARD8) (offset >> 8)); + } else { + pcmciaWriteIndex (pcmciac, 0x3c4, 0x13, 15); /* ?? */ + } + + /* Set new color */ + pcmciaSetCursorColors (pScreen); + + /* Enable the cursor */ + if (pcmciac->HP) + pcmciaWriteIndex (pcmciac, 0x3d4, 0x50, 0xc1); + else + pcmciaWriteIndex (pcmciac, 0x3c4, 0x12, 0x05); + + /* Move to new position */ + pcmciaMoveCursor (pScreen, x, y); +} + +static void +pcmciaUnloadCursor (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + /* Disable cursor */ + if (pcmciac->HP) + pcmciaWriteIndex (pcmciac, 0x3d4, 0x50, 0); + else + pcmciaWriteIndex (pcmciac, 0x3c4, 0x12, 0); +} + +static Bool +pcmciaRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +{ + SetupCursor(pScreen); + + if (!pScreenPriv->enabled) + return TRUE; + + /* miRecolorCursor does this */ + if (pCurPriv->pCursor == pCursor) + { + if (pCursor) + { + int x, y; + + miPointerPosition (&x, &y); + pcmciaLoadCursor (pScreen, x, y); + } + } + return TRUE; +} + +static Bool +pcmciaUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +{ + return TRUE; +} + +static void +pcmciaSetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y) +{ + SetupCursor(pScreen); + + pCurPriv->pCursor = pCursor; + + if (!pScreenPriv->enabled) + return; + + if (pCursor) + pcmciaLoadCursor (pScreen, x, y); + else + pcmciaUnloadCursor (pScreen); +} + +miPointerSpriteFuncRec pcmciaPointerSpriteFuncs = { + pcmciaRealizeCursor, + pcmciaUnrealizeCursor, + pcmciaSetCursor, + pcmciaMoveCursor, +}; + +static void +pcmciaQueryBestSize (int class, + unsigned short *pwidth, unsigned short *pheight, + ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + switch (class) + { + case CursorShape: + if (*pwidth > pCurPriv->width) + *pwidth = pCurPriv->width; + if (*pheight > pCurPriv->height) + *pheight = pCurPriv->height; + if (*pwidth > pScreen->width) + *pwidth = pScreen->width; + if (*pheight > pScreen->height) + *pheight = pScreen->height; + break; + default: + fbQueryBestSize (class, pwidth, pheight, pScreen); + break; + } +} + +Bool +pcmciaCursorInit (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (!pcmcias->cursor_base) + { + pCurPriv->has_cursor = FALSE; + return FALSE; + } + + pCurPriv->width = PCMCIA_CURSOR_WIDTH; + pCurPriv->height= PCMCIA_CURSOR_HEIGHT; + pScreen->QueryBestSize = pcmciaQueryBestSize; + miPointerInitialize (pScreen, + &pcmciaPointerSpriteFuncs, + &kdPointerScreenFuncs, + FALSE); + pCurPriv->has_cursor = TRUE; + pCurPriv->pCursor = NULL; + return TRUE; +} + +void +pcmciaCursorEnable (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (pCurPriv->has_cursor) + { + if (pCurPriv->pCursor) + { + int x, y; + + miPointerPosition (&x, &y); + pcmciaLoadCursor (pScreen, x, y); + } + else + pcmciaUnloadCursor (pScreen); + } +} + +void +pcmciaCursorDisable (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (!pScreenPriv->enabled) + return; + + if (pCurPriv->has_cursor) + { + if (pCurPriv->pCursor) + { + pcmciaUnloadCursor (pScreen); + } + } +} + +void +pcmciaCursorFini (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + pCurPriv->pCursor = NULL; +} diff --git a/xc/programs/Xserver/hw/kdrive/pcmcia/pcmciashadow.c b/xc/programs/Xserver/hw/kdrive/pcmcia/pcmciashadow.c new file mode 100644 index 000000000..eb6e64873 --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/pcmcia/pcmciashadow.c @@ -0,0 +1,197 @@ +/* + * Copyright 2001 by Alan Hourihane, Sychdyn, North Wales, UK. + * + * 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 Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE 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. + * + * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> + */ +/* $XFree86: xc/programs/Xserver/hw/kdrive/pcmcia/pcmciashadow.c,v 1.2 2001/05/29 17:47:55 keithp Exp $ */ + +#include "X.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "font.h" +#include "dixfontstr.h" +#include "fontstruct.h" +#include "mi.h" +#include "regionstr.h" +#include "globals.h" +#include "gcstruct.h" +#include "shadow.h" +#include "fb.h" + +void +tridentUpdatePacked (ScreenPtr pScreen, + shadowBufPtr pBuf) +{ + RegionPtr damage = &pBuf->damage; + PixmapPtr pShadow = pBuf->pPixmap; + shadowScrPriv(pScreen); + int nbox = REGION_NUM_RECTS (damage); + BoxPtr pbox = REGION_RECTS (damage); + FbBits *shaBase, *shaLine, *sha; + FbStride shaStride; + int scrBase, scrLine, scr; + int shaBpp; + int shaXoff, shaYoff; /* XXX assumed to be zero */ + int x, y, w, h, width; + int i; + FbBits *winBase, *win; + CARD32 winSize; + + fbGetDrawable (&pShadow->drawable, shaBase, shaStride, shaBpp, shaXoff, shaYoff); + while (nbox--) + { + x = pbox->x1 * shaBpp; + y = pbox->y1; + w = (pbox->x2 - pbox->x1) * shaBpp; + h = pbox->y2 - pbox->y1; + + scrLine = (x >> FB_SHIFT); + shaLine = shaBase + y * shaStride + (x >> FB_SHIFT); + + x &= FB_MASK; + w = (w + x + FB_MASK) >> FB_SHIFT; + + while (h--) + { + winSize = 0; + scrBase = 0; + width = w; + scr = scrLine; + sha = shaLine; + while (width) { + /* how much remains in this window */ + i = scrBase + winSize - scr; + if (i <= 0 || scr < scrBase) + { + winBase = (FbBits *) (*pBuf->window) (pScreen, + y, + scr * sizeof (FbBits), + SHADOW_WINDOW_WRITE, + &winSize, + pBuf->closure); + if(!winBase) + return; + scrBase = scr; + winSize /= sizeof (FbBits); + i = winSize; + } + win = winBase + (scr - scrBase); + if (i > width) + i = width; + width -= i; + scr += i; + { + CARD16 *sha16 = (CARD16*)sha; + CARD16 *win16 = (CARD16*)win; + while (i--) + { + *win16++ = *sha16++; + *win16++ = *sha16++; + } + } + } + shaLine += shaStride; + y++; + } + pbox++; + } +} + +void +cirrusUpdatePacked (ScreenPtr pScreen, + shadowBufPtr pBuf) +{ + RegionPtr damage = &pBuf->damage; + PixmapPtr pShadow = pBuf->pPixmap; + shadowScrPriv(pScreen); + int nbox = REGION_NUM_RECTS (damage); + BoxPtr pbox = REGION_RECTS (damage); + FbBits *shaBase, *shaLine, *sha; + FbStride shaStride; + int scrBase, scrLine, scr; + int shaBpp; + int shaXoff, shaYoff; /* XXX assumed to be zero */ + int x, y, w, h, width; + int i; + FbBits *winBase, *win; + CARD32 winSize; + + fbGetDrawable (&pShadow->drawable, shaBase, shaStride, shaBpp, shaXoff, shaYoff); + while (nbox--) + { + x = pbox->x1 * shaBpp; + y = pbox->y1; + w = (pbox->x2 - pbox->x1) * shaBpp; + h = pbox->y2 - pbox->y1; + + scrLine = (x >> FB_SHIFT); + shaLine = shaBase + y * shaStride + (x >> FB_SHIFT); + + x &= FB_MASK; + w = (w + x + FB_MASK) >> FB_SHIFT; + + while (h--) + { + winSize = 0; + scrBase = 0; + width = w; + scr = scrLine; + sha = shaLine; + while (width) { + /* how much remains in this window */ + i = scrBase + winSize - scr; + if (i <= 0 || scr < scrBase) + { + winBase = (FbBits *) (*pBuf->window) (pScreen, + y, + scr * sizeof (FbBits), + SHADOW_WINDOW_WRITE, + &winSize, + pBuf->closure); + if(!winBase) + return; + scrBase = scr; + winSize /= sizeof (FbBits); + i = winSize; + } + win = winBase + (scr - scrBase); + if (i > width) + i = width; + width -= i; + scr += i; + { + CARD8 *sha8 = (CARD8*)sha; + CARD8 *win8 = (CARD8*)win; + while (i--) + { + *win8++ = *sha8++; + *win8++ = *sha8++; + *win8++ = *sha8++; + *win8++ = *sha8++; + } + } + } + shaLine += shaStride; + y++; + } + pbox++; + } +} diff --git a/xc/programs/Xserver/hw/kdrive/pcmcia/pcmciastub.c b/xc/programs/Xserver/hw/kdrive/pcmcia/pcmciastub.c new file mode 100644 index 000000000..be5498ec9 --- /dev/null +++ b/xc/programs/Xserver/hw/kdrive/pcmcia/pcmciastub.c @@ -0,0 +1,54 @@ +/* + * Copyright 2001 by Alan Hourihane, Sychdyn, North Wales, UK. + * + * 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 Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE 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. + * + * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> + */ +/* $XFree86: xc/programs/Xserver/hw/kdrive/pcmcia/pcmciastub.c,v 1.1 2001/05/23 08:56:09 alanh Exp $ */ + +#include "pcmcia.h" + +void +InitCard (char *name) +{ + KdCardAttr attr; + + KdCardInfoAdd (&pcmciaFuncs, &attr, 0); +} + +void +InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv) +{ + KdInitOutput (pScreenInfo, argc, argv); +} + +void +InitInput (int argc, char **argv) +{ + KdInitInput (&Ps2MouseFuncs, &LinuxKeyboardFuncs); +} + +extern pcmciaDisplayModeRec pcmciaDefaultModes[]; + +int +ddxProcessArgument (int argc, char **argv, int i) +{ + return KdProcessArgument (argc, argv, i); +} diff --git a/xc/programs/Xserver/hw/xfree86/doc/sgml/OS2Notes.sgml b/xc/programs/Xserver/hw/xfree86/doc/sgml/OS2Notes.sgml new file mode 100644 index 000000000..832e9f63a --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/doc/sgml/OS2Notes.sgml @@ -0,0 +1,214 @@ +<!DOCTYPE linuxdoc PUBLIC "-//XFree86//DTD linuxdoc//EN"> +<article> + +<title>Notes on Rebuilding XFree86/OS2 from Scratch +<author>Holger Veit +<date>Last modified March 8th, 2000 + +<toc> + +<sect>Preface +<p> +X11 and XFree86 were initially developed on Unix-based systems. Usually +Unix systems provide a rich number of tools and utilities to get certain +things done. Under OS/2, these tools are not installed, but ports are +available which are sometimes functionally equivalent to Unix utilities +with the same name, but also differ sometimes in a subtle way. +This guide will give you hints if you intend to rebuild the system +from scratch under OS/2. +<p> +Please also read <htmlurl name=README.OS2 url=OS2.html> for end-user +information, and set at least the environment variables described there. +<p> +At the current time, the most recent version available is XFree86-4.0. +This is a full and unrestricted version which comes with complete source +code. 4.0 is a highly experimental release, so many features that might +have worked in earlier versions, may now no longer work, or work differently. +Be aware that for OS/2, XFree86-4.0 is considered to be alpha software. + +If you want to join the XFree86 developer team, e.g. to add support for +certain hardware, please send a request to BOD@XFree86.org. Please +think about such a step carefully before, though, since much work is +involved. Please use the XFree86-4.0 source code as a test example how +to compile the system. The ability to manage that is a basic requirement +for becoming a developer. + + +<sect>Tools required +<p> + +I have tried to reduce the number of external tools, but when looking back +it seems I were not very successful. At least I managed to get everything +working with the native CMD.EXE shell only. However, there is still plenty +of software required. +Most of this software is available from <tt/hobbes.nmsu.edu/ or <tt/ftp.leo.org/ +via anonymous FTP. The following shopping list shows what you will need: + +<itemize> +<item>gcc EMX/gcc emx 0.9C patch4 or later (0.9d preferred!) +<item>gzip GNU zip/unzip +<item>tar GNU tar +<item>patch Larry Wall's patch utility (attention: incompatible tool with same name in OS/2) +<item>install BSD/GNU install +<item>rm,mv,cp GNU file utilities +<item>tee,.. GNU shell utilities +<item>groff GNU nroff/troff +<item>sed GNU sed stream editor +<item>grep GNU grep +<item>gawk GNU awk +<item>make GNU make 3.71/3.72 (use the one from Xprog.zip!) +<item>flex GNU flex +<item>bison GNU bison +<item>m4 GNU m4 +<item>find GNU find (attention: incompatible tool with the same name in OS/2) +</itemize> + +If there is no version number given, any new version will do. Particularly +critical is only EMX/gcc and GNU make. Note that the second GCC implementation +which might still be available from some archives is NOT compatible. + +Furthermore, you need the XFree86 sources. These are available from +the common XFree86 repositories. Look into a directory which is +often named /pub/XFree86/4.0/source. + +<sect>Compiling and Installing +<p> + +You need about 300MB of free HPFS space for the whole system. This does not +include space for the postscript and troff documentation files. I have never +installed them. Nor did I install the test subtree. + +<enum> +<item>Install all the above utilities. Refer to the corresponding documentation. + Verify that everything works well, particularly EMX. +<item>It is a good idea to use the same or a similar structure I have. + I have made a directory <tt>\x11</tt> on the partition for compiling and have + put everything below this tree. I found that a clean tree occupies + less than the half space of the disk, this gives me the opportunity to + rename this tree to <tt>\x11old</tt> and copy a new version to the + same disk to produce diffs. Last time the complete tree was + arranged under the root directory <tt>xc</tt>, this would become + <tt>\x11\xc</tt> then. +<item>To unpack the files you would usually execute the command + <verb>gzip -dc file.tar.gz | tar xvf -</verb> + in the <tt>\x11</tt> directory. At the end you will usually see the + irritating, but non-fatal message "gzip: stdout Broken pipe". Ignore it. +<item>After that, is is likely necessary to apply some patches, either from + the XConsortium or from the XFree86 project. Before you do this, enter + <verb> + chmod -R a+rw \x11\xc + </verb> + to make certain files in the tree writable. +<item>There should be a file <tt>added-XXX</tt> accompanying the patch file + which lists the files that are newly created. The patch program has + a problem with creating new directories, so we need to create them + on advance. For each <tt/added-XXX/ file you find, execute from + <tt>\x11</tt> <verb>xc\config\util\added added-XXX</verb> + If there is no <tt>added-XXX</tt> file available, you can make one with + the following instructions: + <verb> + grep "\*\*\* xc/" patchfile >added-file + </verb> + Edit <tt/added-file/ with a text editor and remove the <tt/*** / at + the beginning and the time stamp at the end (search for a TAB and + erase to the end of the line). You get a list of file paths, one in a + line, which is the input to the added utility. +<item>After that you can apply the patches in the right order. Usually this + is done by a command + <verb> + patch -p -E <patchfile 2>&1 | tee patchlog + </verb> + from the <tt>\x11</tt> directory. Be aware to use the right + patch - OS/2 has a utility with the same name and different functionality. + Don't use the recommended <tt/-s/ option, this makes <tt/patch/ quiet, + and you won't see problems in the patchlog file. Use + <verb> + find \x11 -name *.rej -print + find \x11 -name *# -print + </verb> + to find any rejects and unapplied patches (attention: yet another OS/2 + program with wrong functionality). Normally there shouldn't + be any problems of this kind, else you have made a mistake. Finally + remove the original files with + <verb> + find \x11 -name *.orig -print -exec rm {} ; + </verb> +<item>Go to the <tt>xc/config/cf</tt> directory and edit the <tt>xf86site.def</tt> + file to match your requirements (you probably don't want to compile + all X servers). Certain changes must be set to the following values: + <itemize> + <item>Disable if not already done any PC98 server; PC98 (Japanese XFree86) + does not work yet. Porters from Japan are welcome! + <item><tt>#define WacomSupport NO + #define ElographicsSupport NO</tt> + Both options are not yet supported. + <item>Tcl* and Tk* don't need to be set explicitly. Reasonable defaults + are in the other config files, provided you have a complete + XFree86/OS2 binary tree with the tcl/tk runtime support installed. + <item><tt>#define BuildDynamicLoading NO</tt> + This does not work. + </itemize> +<item>Go to the directory <tt>xc\util\compress</tt> and + <tt>make compress.exe</tt> there. Install the program produced + there in your path. I stumbled more than once on half-ported + compress programs on OS/2 ftp servers that are defective w.r.t. + reading and writing stdin/stdout. In some stage (font compression) + otherwise you will get a core dump of mkfontdir, because all + compressed fonts are corrupt. +<item>Set the environment variable <tt/X11ROOT/ to something different than + it is; otherwise the installation process will overwrite your + original XFree86/OS2 installation. If you have not set this variable, + go back to the prefix section of this document: you have forgotten + something. +<item>Copy the file <tt>xc/programs/Xserver/hw/xfree86/etc/bindist/OS2/host.def.os2</tt> + to the location <tt>xc/config/cf/host.def</tt>. Use this file to do + any specific modifications to imake variables, rather than editing + the file xfree86.cf, imake.tmpl, or os2.cf directly. +<item>Copy the file <tt>xc/config/util/buildos2.cmd</tt> into the <tt/xc/ + directory. If this is a second or later attempt, you might need to + copy the saved toplevel Makefile.os2 back to Makefile. +<item>Execute this <tt/buildos2.cmd/ command in the <tt/xc/ directory; + it will produce a logfile <tt>buildxc.log</tt> in this directory. +<item>Go have a bucket of coffee, or better, buy new coffee - in Colombia! + The compile will need between 2 and 20 hours, depending on your + selections, and the horse power of your hardware. +<item>When finished, view the logfile for errors, and fix the problems if + there are some. I have managed to compile the whole system + flawlessly, so there is at least one configuration that works. +<item>Finally, from the <tt/xc/ dir, execute + <verb> + xmake install + xmake install.man + </verb> +<item>There are a few minor glitches in the installation: +<enum> +<item>The xdm and linkkit directories will fail in compile and installation. + This is no problem and has no effect on the rest of the system. +<item>The imake.exe which is installed in <tt/\XFree86\bin/ is usually defective. + The one which was built initially and installed in the root directory + of the drive where you have the source tree is okay. So simply copy + this <tt/\imake.exe/ to the <tt/\XFree86\bin/ directory + manually. Some day this might be fixed. +<item><tt/XF86Setup/ is not ported yet and won't work with the tcl/tk port + available for XFree86/OS2. My idea was to replace this by some native + installation tool, which I didn't find the time to do yet. Feel free + to spend a bit of time to play with XF86Setup if you like. +</enum> +</enum> + +Well, you see, this was quite easy :-) + + + + +<verb> +$XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/OS2Notes.sgml,v 1.1 2001/06/04 13:50:15 dawes Exp $ + + + + + +$XConsortium: OS2note.sgml /main/1 1996/02/24 10:08:59 kaleb $ +</verb> + +</article> diff --git a/xc/programs/Xserver/hw/xfree86/doc/sgml/QuickStart.sgml b/xc/programs/Xserver/hw/xfree86/doc/sgml/QuickStart.sgml new file mode 100644 index 000000000..af510ecd4 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/doc/sgml/QuickStart.sgml @@ -0,0 +1,679 @@ +<!DOCTYPE linuxdoc PUBLIC "-//XFree86//DTD linuxdoc//EN"> + +<article> + +<title>Quick-Start Guide to XFree86 Setup + +<author>Joe Moss +<date>27 February 1998 + +<abstract> + Current releases of XFree86 include several tools that can help +to automate the process of server configuration. Much of the existing +documentation, however, describes how to do the job manually, including +many technical details. + + For those users with esoteric hardware or with the desire to +get their hands dirty under the hood, this is great, but many users are +using common hardware and just want to get X up and running quickly. +This guide is for them. + +</abstract> + +<toc> + +<sect> Before You Start +<p> + There are a few bits of information that you will need to have + before you can setup the server: + <descrip> + <tag> The model name of your video card </tag> + Make sure you know the exact model name of the card. It + may help to also know the graphics chipset, RAMDAC, and + clock chip used on your card. + <tag> The amount of memory on your video card </tag> + Find out how many megabytes of RAM are on your video card. + <tag> Whether or not your card is VGA compatible </tag> + Most cards these days are VGA compatible, but for example, + if you have and older monochrome card, it might not be. + <tag> Your monitor's specifications </tag> + Specifically, you need to know the horizontal sync rate(s), + and vertical refresh rate(s). These are <bf>important</bf>! + Consult your monitor's manual. + <tag> The protocol used by your mouse </tag> + It will help speed up the process, if you know which protocol + is used by your mouse to communicate. Some mice are capable + of using two different protocols, although the method of + switching between them varies. In some cases, with new + Plug-n-Play mice, the protocol can be determined + automatically. + </descrip> + +<sect> What to Do - An Overview +<p> + There are three tools that can be used to set up XFree86: + <itemize> + <item>XF86Setup + <item>xf86config + <item>xvidtune + </itemize> +<p> + XF86Setup primarily uses a graphical user interface and + is the preferred tool for initial setup, but there + are a few cases where it can't be used. If you are using a + card that is not VGA compatible, have a fixed-frequency + monitor, or are running OS/2, you'll not be able to use + XF86Setup, read about xf86config instead. + If you have limited RAM or a slow system, you might be better + off using xf86config as well. +<p> + The xf86config program is text based only, but works for almost + any hardware combination. If you have a fixed frequency + monitor that won't work with standard text modes, you + will have to read the necessary documentation and + do the configuration manually. +<p> + To get things looking just right, you may need to use + <tt>xvidtune</tt>, a program that allows you to make adjustments + to the displayed image (e.g. make it wider, move it a little + to the left, etc.). XF86Setup will allow you to run xvidtune + at the appropriate time; if you use xf86config, you can use + xvidtune afterwards. +<p> + All of these are explained in detail in the following + sections. If you're the type that doesn't like to read + the documentation, but would rather just try and figure + your way through things, you can just type <tt/XF86Setup/ + now. + If you have problems, the documentation will still be here. +<p> + Although it is possible to use XF86Setup from within X to + make changes to your existing configuration, such use is + not specifically documented here. These instructions are + primarily for those initially setting up XFree86 on their + system. + +<sect> Using <tt>XF86Setup</tt> +<p> + XF86Setup will first check around to make sure certain files + are installed and that you are running as root. If a problem + is found, it will display a message and exit. Correct the + problem (e.g. install the missing files) and run it again. + + XF86Setup is internationalized. If you are Japanese and set + the LANG environment variable to ja, japan, japanese, etc., + XF86Setup's screen can be Japanized. But it is necessary that + XF86Setup is built with Japanized Tcl/Tk. Other language can + be added, if you prepare its own directory under the directory + XF86Setup/texts. Please see under the directory + XF86Setup/texts/generic. + +<sect1> Initial questions +<p> + If you have an existing XF86Config file, you will be asked if + you would like to use it to set the default values of various + configuration settings. If you've already got an (at least + somewhat) working configuration you will want to do this. + + If you are running on an OS which has a mouse driver in the + kernel (e.g. SCO or SVR4), you may be asked if you'd like to + use it. + + Once the questions (if any) are completed, you will see a message + indicating that the program is ready to switch into graphics mode. + Just press Enter. If you don't get a graphics screen saying + <it/Welcome to XFree86 Setup/ within a minute, something has + probably hung, you can try pressing Ctrl-Alt-Backspace to + switch back to text mode and you'll probably have to use + xf86config instead of XF86Setup. + +<sect1> Configuration areas +<p> + Once the VGA16 server is started, and once the program has + finished loading, you will see a screen with six + buttons along the top and three along the bottom. + The buttons along the top correspond to the general categories + of configuration settings. They can be done in any order. + Each of these areas is explained in detail below. + The bottom row consists of the <bf/Abort/, + <bf/Done/, and <bf/Help/ buttons. +<p> + <bf/Abort/ does as it name implies. It exits the program + without saving any changes that have been made. The one + possible exception is the link to the mouse device. Any + change to that is made as soon as <bf/Apply/ is selected. +<p> + <bf/Done/ should be selected when you've finished + configuration in each of the various categories. +<p> + The <bf/Help/ can be pressed at any time to get on-line + help regarding the current configuration screen. +<p> + You should start with configuring your mouse as it will make + things a lot easier to perform the configuration of other + categories. + +<sect2> Mouse +<p> + The mouse configuration screen is used to get the mouse working + properly. There are key bindings for everything so that you + can easily configure the mouse, if it's not already working. +<p> + The screen includes a representation of a white mouse with + three buttons. As you move your mouse it should show the + pointer coordinates on the mouse and the buttons should turn + black as you press the corresponding button on your mouse. + If that is not happening, then your mouse is not correctly + configured. +<p> + Along the top are some rows of buttons corresponding to + the various possible protocols. There will also be + several buttons and a couple of sliders + for other settings, a visual representation of the mouse, + and a button to apply any changes. + There may also be an entry box in which the + device can be set along with a list of possible devices. +<p> + First try moving your mouse around and see if the pointer moves + correctly. If so, try testing that the buttons are working + properly. If those are working as desired, go ahead and go on + to another configuration area. +<p> + If the mouse pointer doesn't move at all, you need to fix + either the mouse device or the protocol (or both). + You can press 'n' followed by a Tab, to move to the list + of mouse devices and select a different one. + Pressing 'p' will pick the next available protocol on the list + (protocols that are not available on your OS will be + greyed-out). If you have a PnP mouse, it may be easiest to + just select "Auto" as the protocol. + After changing these, press 'a' to apply the changes and try + again. Repeat the process until you are getting some response + from your mouse. +<p> + If the mouse pointer or button indicators do something when you + move the mouse, but the pointer is not moving properly, you + probably have the wrong protocol selected. Try with a different + one. +<p> + Most mice these days use the <bf/Microsoft/ protocol, the second + most common is <bf/MouseSystems/. Some mice do both. + These <it/dual-protocol/ mice have various methods of switching + between the two protocols. + Some have a switch on the mouse itself. + Some are switched by sending a certain signal to the mouse + when opening a connection to the mouse. + These signals can be controlled by using different + combinations of the 'ClearDTR' and 'ClearRTS' settings. + Other mice require a button to be depressed when the mouse + is opened (when the mouse driver first tries to talk to it). + If your mouse uses this method, hold down the appropriate + button while selecting apply (pressing 'a'). +<p> + Once the mouse pointer is moving correctly, test that all + three buttons are working properly. If your mouse only has + two buttons, select 'Emulate3Buttons' and you should be able + to press both buttons simultaneously to emulate the missing + middle button. If not all of the buttons are working, try + changing the 'ChordMiddle' setting or you may be using a + protocol that is similar to that of your mouse, + but not quite right. + +<sect2> Keyboard +<p> + You need to specify the model and layout of your keyboard (and + press apply) if they are not already correct. + The graphical representation of the keyboard will be + updated when you choose a different model. +<p> + For non-U.S. keyboards you may wish to choose a variant from + the list (at this time there is only one available variant: + <tt/nodeadkeys/>). +<p> + You can also pick from the options to the right, if you wish. + +<sect2> Card +<p> + Pick your card from the list. +<p> + If there are README files that may pertain to your card + the 'Read README file' button will then be usable (i.e. not + greyed out). + Please read them. +<p> + If your card is not in the list, or if there are any + special settings listed in the README file as required + by your card, you can press the 'Detailed Setup' + button to make sure that the required settings are selected. + Otherwise, you're finished with configuring your card. +<p> + To use 'Detailed Setup': + First select the appropriate server for your card. + Then read the README file corresponding to the selected + server by pressing the 'Read README file' button + (it won't do anything, if there is no README). +<p> + Next, pick the chipset, and Ramdac of your card, if + directed by the README file. + In most cases, you don't need to select these, + as the server will detect (probe) them automatically. +<p> + The clockchip should generally be picked, if your card + has one, as these are often impossible to probe + (the exception is when the clockchip is built + into one of the other chips). +<p> + Choose whatever options are appropriate (again, + according to the README). +<p> + You can also set the maximum speed of your Ramdac. + Some Ramdacs are available with various speed ratings. + The max speed cannot be detected by the server + so it will use the speed rating of the slowest version + of the specified Ramdac, if you don't specify one. +<p> + Additionally, you can also specify the amount of RAM on your + card, though the server will usually be able to detect this. + + +<sect2> Modeselect +<p> + Use this one to pick which depth you prefer to use (this + determines how many colors can be displayed at a time) + and to select all of the modes you are interested in + possibly using. +<p> + Your hardware may not be able to support all + of depth and mode combinations that can be selected. + Any unsupported combinations will automatically be + rejected by the server when it tries to startup. + Note also that if you select multiple modes, you will + get a virtual screen as large as the largest of the + usable modes. + +<sect2> Monitor +<p> + Enter the horizontal and vertical frequency ranges that your + monitor supports in the corresponding entry boxes near the + top of the screen. + You can enter specific frequencies or ranges of frequencies + (separated by hyphens). + If the monitor supports several different frequencies or + ranges, list them all, separated by commas. +<p> + If you can not find this information in you monitor's manual, + pick one of the choices from the list of common monitor + capabilities. The program will use conservative values + for each of these, so you'll get better performance if you + type in the correct values from your monitor manual. + +<sect2> Other +<p> + You can probably just skip this one. + +<sect2> Completing the configuration +<p> + Once you've finished with the above, press the 'Done' button + and then the 'Okay' button which will appear. You will then + be switched back to text mode. + +<sect1> Back to text mode +<p> + The program will now attempt to start the appropriate server + for your card, with all of the + configuration settings you selected. + If for some reason it is unable to start the server, you have + likely selected an improper setting and will be asked if you + would like to return to the graphical configuration screen + and try again. + +<sect1> The second server +<p> + This is unlikely to happen, but + if when the server starts, the display is unreadable, try + pressing Ctrl-Alt-+ (using the plus on the numeric keypad) + to switch to a different video mode. +<p> + The display will show an entry box and three buttons. +<p> + The first button allows you to run xvidtune to adjust your + video modes. One important point to keep in mind when using + xvidtune is that switching video modes with Ctrl-Alt-+ is + disabled while xvidtune is running. + You must use the 'Next' and 'Prev' buttons to switch modes. + Because of this, you should be careful not to move the mouse + when pressing either of these. If by some chance the mode + you switch to doesn't produce a readable display on your + monitor, you can then just press the mouse button again to + move to the next (hopefully readable) mode. +<p> + The second button causes the settings you've made to be + written to the filename given in the entry box. + After saving the settings a message will appear indicating + that it has finished. Just press the 'Okay' button and + you're done. +<p> + And the third button causes the program to exit without + saving any of the configuration settings. + +<sect1> Ending text +<p> + You are returned to text mode and the program will print a + `Configuration complete.' message. You should now have a + usable configuration file and can start the X server by + whichever method you wish (usually either the 'startx' + command or via 'xdm'). + +<sect> Running <tt>xf86config</tt> +<p> + From a text screen, run the <tt/xf86config/ program. This + program should be run as <it/root/ (although not absolutely + necessary, it will allow xf86config to do more of the work + for you). You can press your interrupt character (usually + Control-C or perhaps Delete), at any time to stop the program, + if you need to. You can just start it over again. + + The <tt/xf86config/ program provides instructions on screen + as to what you need to do. Following are some notes that + document the various stages in the process. They should help + you get through the process quickly and provide some + documentation for those people who like to know what they're + getting themselves into, before running a program. + +<sect1> The intro screen +<p> + First, <tt/xf86config/ begins by telling you a few things like + the fact that it can help you setup an XF86Config file or that + you can do the job yourself with an editor. Just read what + it says and press <sf/Enter/ when done. + +<sect1> Getting your <tt>PATH</tt> right +<p> + The program will next check that you have the directory + <tt>/usr/X11R6</tt> (the standard installation directory) + on your system and tell you that it needs to be in your + <tt/PATH/ environment variable. + + It will also check if you have the + <tt>/usr/X386</tt> directory as used by older (pre 3.0) + versions of XFree86. If by chance you do, it will warn you + that <tt>/usr/X11R6</tt> must be before <tt>/usr/X386</tt> + in your <tt/PATH/. + + If everything is okay, just press Enter and go on, otherwise + press Control-C to exit and make any necessary changes and + restart <tt/xf86config/. + +<sect1> Mouse setup +<p> + Pick the mouse type from the menu and enter the name of the + device to which mouse is connected, as directed. + + If you are using an OS (e.g. SVR4, SCO) that has a built in + mouse driver that the Xserver could use, you'll need to edit + the XF86Config file to setup your mouse, so just pick any + mouse from the list and press enter when asked for the device. + + If you don't know which protocol your mouse uses, you'll just + have to guess (the xf86config program will give you some hints + as to which might be most likely) and then see the + troubleshooting section if it doesn't work when you run the + server. + + The xf86config program has not been updated to allow you to + select the latest mouse protocols, so you may have to edit + the config file by hand after xf86config has finished. + +<sect1> Keyboard setup +<p> + Simply answer yes to the question regarding keyboard setup. + + If there is some reason you need to use the right-alt and + control keys for something else, you can enter no. + +<sect1> Monitor setup +<p> + Setting up a monitor consists of entering the specifications + of your monitor and a description of the model and manufacturer. + + You are first asked for the horizontal sync rate. It is + <bf/VERY/ important to enter the correct value(s) from the + manual. If one of the ranges given matches the rate of your + monitor, then pick it, otherwise pick <tt/custom/ and enter + the values from your manual. + + Next is the vertical refresh rate. Again, it is <bf/VERY/ + important that this parameter be specified correctly. + Enter it in a manner similar to the horizontal sync rate. + + <it>If either rate is mis-specified, it can result in damage + to your monitor.</it> + + Finally, you are asked for an "identifier", your monitor + manufacturer, and model. You can just press enter to + get through these quickly. + +<sect1> Selecting your card +<p> + You are next asked if you would like to view the database of + cards. Picking your card from the list will cause the answers + to the questions in the next two sections to be filled in for + you and so can save a little time. + + If your card does not appear in the list, just press <tt/q/ + and enter to skip on to the next step - where you'll have to + answer the questions yourself. + +<sect1> Server selection +<p> + If you selected your card in the previous step, then server + selection is easy - just use the recommendation from the + database. + + If you have a card which uses one of the chipsets for which a + specific server exists (Mach8, Mach32, Mach64, AGX/XGA, + 8514/A, S3, I128, P9000) you'll want to pick the + <tt/accel/ option. + + Otherwise you'll probably want to use the SVGA server. + + Next, answer yes when the program asks if you want it to + set the symbolic link for you. If you picked the <tt/accel/ + option, you'll also need to indicate which particular + accelerated server to link to. + +<sect1> Screen/Video configuration +<p> + Pick the appropriate option from the list to indicate the + amount of memory on your video card. + + Then you are asked to provide and identifier, the manufacturer, + and the model of your card. You can just press enter to skip + through these, if you wish. + + Next, the program will ask for the type of RAMDAC and Clockchip + on your card. If your card was in the database, you should + just to tell it to use the values from the database. + + If you don't have one of the listed RAMDACs or Clockchips + on your card, just press enter when asked what type you have. + If you do not have a programmable clock chip, the program will + next attempt to probe to find out what clock rates are + supported by your clock chip. + +<sect1> Mode Selection +<p> + Now you get to tell the program which video modes you would + like to be able to run. + + The program will show you the common modes that should work + with your card (some might not work with your monitor, but + if you've correctly specified the monitor's sync rates, the + X server will just ignore them when it runs). + + You could just accept the settings as they are given, but + you'll probably wish to reverse the order. For example, if + you have a card with 1 Meg RAM, it will list the modes + <tscreen><verb> + "640x480" "800x600" "1024x768" for 8bpp + </verb></tscreen> + + Select <tt/1/ to change the settings for 8bpp and the type + <tt/432/ to select the reverse order. + + When you've select the modes, in the order you wish, select + option <tt/4/ to continue. + +<sect1> Creating the <tt>XF86Config</tt> file +<p> + The program will now ask if you would like to write the + configuration settings you've selected to the file + <tt/XF86Config/. Answer yes. + +<sect1> Some final notes +<p> + Lastly, the program tells you that it's finished its part + of this process and counsels you to check the file before + using it. The next section covers the changes that are most + likely to be needed. + +<sect> Fixing the XF86Config file +<p> + Use an editor to look at the <tt/XF86Config/ file. Here are + some things that may need to be changed: + <itemize> + <item>If you are running an operating system which has + built-in mouse support, you'll want to change the + <tt/Pointer/ section. Specifically, you should set + the <tt/Protocol/ to <tt/OSMouse/ (SCO) or <tt/Xqueue/ + (SVR4, some SVR3) and you should remove the <tt/Device/ + line. + <item>If you are running a system with the Xqueue event driver + and would like to use it, change the <tt/Protocol/ + setting in the <tt/Keyboard/ section to <tt/Xqueue/. +<!-- What else should be added here? --> + </itemize> + + Once you are satisfied that the configuration is correct, copy + the XF86Config file to <tt>/usr/X11R6/lib/X11</tt> and run + the 'startx' command. + + You should now have a running X server. If it's running but + the display doesn't look as good as you think it should (i.e. + it doesn't fill the whole screen, it's off-center, it's wrapping + around on one side, etc.) see the section on <tt/xvidtune/. + If there is some other problem, see the troubleshooting section. + +<sect> Running <tt>xvidtune</tt> +<p> + If you need to make adjustments to the video display, + <tt/xvidtune/ is the tool to use. + + Simply enter the command <tt/xvidtune/ from a shell prompt + within an xterm. Read the warning and click on <tt/OK/. + Next click on the <tt/Auto/ button. + + Now click on whatever combination of <tt>Up/Down/Left/Right</tt> + <tt>Shorter/Taller/Wider/Narrower</tt> is need to adjust + the display to your liking. + + If you are using a recent S3-based card there will be some + extra buttons and entries at the bottom (InvertVCLK, EarlySC, + and Blank Delays). These can help solve problems of the + display wrapping around a few pixels. + + Once the display has been adjusted properly, press the <tt/show/ + button to printout the correct <tt/ModeLine/ to put in the + <tt/XF86Config/ to make the server always use the current + display settings. To aid in copying this information to your + XF86Config file, the modeline is also made the current + selection allowing you to just paste it into your editor. + + If you would like to adjust your other modes, you can click + on the <tt/Next/ and <tt/Prev/ buttons to switch modes. + + When you are through using <tt/xvidtune/ simply press on the + <tt/Quit/ button. + +<sect> Troubleshooting +<p> + Since you're reading this, something must not have gone + the way you had hoped (or else you just really enjoy reading). + + Below are listed some common problems that may occur + during configuration and some hints for solving them. + However, there are just too many different combinations + of hardware and software configurations, and, well, just + too many things that can go wrong, for this document + and the tools it documents, to cover every case. + + If after trying the steps in the previous sections and + checking the hints in this section, you still are unable + to get your system working, you'll have to read the full + documentation. Read the README file for your card and + OS (if they exist), the XFree86 Configuration Guide + (README.Config), and the XF86Config man page. + +<!-- + You should also look at + <url name="the XFree86 FAQ" url="http://www.XFree86.org/FAQ"> + for more up-to-date information, + especially if you are trying to configure a fairly new card. +--> + + If all else fails, you can try posting a message to + comp.windows.x.i386unix or comp.os.linux.x or send email + to XFree86@XFree86.org. + +<sect1> The mouse doesn't move correctly, it stays in one area of the screen +<p> + You've selected the wrong protocol for your mouse. Try a + different one. + +<sect1> The server doesn't start, it says the mouse is busy. +<p> + Well, it's probably right. This most often happens on + Linux systems that have <tt/gpm/ running. Kill the <tt/gpm/ + process and try <tt/startx/ again. + +<sect1> The middle button doesn't work. +<p> + There's no easy answer to this one. It's a lot of trial + and error. You need to make sure you're running the right + protocol for your mouse. + + Many three button mice are "dual protocol" which means that + they have both a 2-button and 3-button mode. The way to get + the mouse to switch into 3-button mode (which usually then + uses MouseSystems protocol) varies between different models. + + You may need to slide a switch on the mouse or hold down the + middle button when starting the server. Other methods of + switching modes can be done by the server, you just have to + find the right combination of settings for your mouse. See + the Pointer section of the XF86Config man page for a complete + list of settings. + +<sect1> The display is shifted to the left/right/top/bottom +<p> + See the section on xvidtune. + +<sect1> I don't appear to have xf86config or xvidtune on my system +<p> + Hmmm. A couple of possibilities: + <enum> + <item>Your <tt/PATH/ is not set correctly. Make sure it includes + the bin directory for the XFree86 binaries (usually, + <tt>/usr/X11R6/bin</tt> + <item>You don't have a complete installation of XFree86. + Go back to wherever you got XFree86 and get the missing + pieces. + </enum> + +<!-- Lots of things still need to be added --> + +<verb> +$XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/QuickStart.sgml,v 1.2 2001/08/10 16:38:11 dawes Exp $ +</verb> + +</article> diff --git a/xc/programs/Xserver/hw/xfree86/doc/sgml/VideoModes.sgml b/xc/programs/Xserver/hw/xfree86/doc/sgml/VideoModes.sgml new file mode 100644 index 000000000..05e646dd4 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/doc/sgml/VideoModes.sgml @@ -0,0 +1,1428 @@ +<!DOCTYPE linuxdoc PUBLIC "-//XFree86//DTD linuxdoc//EN"> + +<!-- This is the Linux Distribution HOWTO, SGML source -- > +<!-- Eric S. Raymond, esr@snark.thyrsus.com -- > +<!-- The submission address is gregh@sunsite.unc.edu -- > + +<article> + +<title>XFree86 Video Timings HOWTO +<author>Eric S. Raymond <esr@thyrsus.com> +<date>Version 3.0, 8 Aug 1997 + +<abstract> +How to compose a mode line for your card/monitor combination under XFree86. +The XFree86 distribution now includes good facilities for configuring most +standard combinations; this document is mainly useful if you are tuning a +custom mode line for a high-performance monitor or very unusual hardware. +It may also help you in using xvidtune to tweak a standard mode that is +not quite right for your monitor. +</abstract> + +<toc> + +<sect>Disclaimer +<p> + +You use the material herein SOLELY AT YOUR OWN RISK. It is possible +to harm both your monitor and yourself when driving it outside the +manufacturer's specs. Read <ref id="overd" name="Overdriving Your +Monitor"> for detailed cautions. Any damages to you or your monitor +caused by overdriving it are your problem. + +The most up-to-date version of this HOWTO can be found at the <url +url="http://sunsite.unc.edu/LDP" +name="Linux Documentation Project"> web page. + +Please direct comments, criticism, and suggestions for improvement to +<htmlurl url="mailto:esr@thyrsus.com" name="esr@snark.thyrsus.com">. Please do +<em>not</em> send email pleading for a magic solution to your +special monitor problem, as doing so will only burn up my time and +frustrate you -- everything I know about the subject is already in +here. + +<sect>Introduction<label id="intro"> +<p> + +The XFree86 server allows users to configure their video subsystem and thus +encourages best use of existing hardware. This tutorial is intended to help +you learn how to generate your own timing numbers to make optimum use of your +video card and monitor. + +We'll present a method for getting something that works, and then show you how +you can experiment starting from that base to develop settings that optimize +for your taste. + +Starting with XFree86 3.2, XFree86 provides an <bf>XF86Setup</bf>(1) +program that makes it easy to generate a working monitor mode +interactively, without messing with video timing number directly. So +you shouldn't actually need to calculate a base monitor mode in most +cases. Unfortunately, <bf>XF86Setup</bf>(1) has some limitations; it +only knows about standard video modes up to 1280x1024. If you have a +very high-performance monitor capable of 1600x1200 or more you will +still have to compute your base monitor mode yourself. + +Recent versions of XFree86 provide a tool called <bf>xvidtune</bf>(1) +which you will probably find quite useful for testing and tuning +monitor modes. It begins with a gruesome warning about the possible +consequences of mistakes with it. If you pay careful attention to +this document and learn what is behind the pretty numbers in +xvidtune's boxes, you will become able to use xvidtune effectively and +with confidence. + +If you already have a mode that almost works (in particular, if one of +predefined VESA modes gives you a stable display but one that's +displaced right or left, or too small, or too large) you can go +straight to the section on <ref id="fixes" name="Fixing Problems with the +Image">. This will enlighten you on ways to tweak the timing +numbers to achieve particular effects. + +If you have <bf>xvidtune</bf>(1), you'll be able to test new modes on the fly, +without modifying your X configuration files or even rebooting your X server. +Otherwise, XFree86 allows you to hot-key between different modes defined in +Xconfig (see XFree86.man for details). Use this capabilty to save +yourself hassles! When you want to test a new mode, give it a unique +mode label and add it to the <EM>end</EM> of your hot-key list. Leave a +known-good mode as the default to fall back on if the test mode +doesn't work. + +<sect>How Video Displays Work<label id="video"> +<p> + +Knowing how the display works is essential to understanding what numbers to put +in the various fields in the file Xconfig. Those values are used in the lowest +levels of controlling the display by the XFree86 server. + +The display generates a picture from a series of dots. The dots are arranged +from left to right to form lines. The lines are arranged from top to bottom to +form the picture. The dots emit light when they are struck by the electron +beam inside the display. To make the beam strike each dot for an equal amount +of time, the beam is swept across the display in a constant pattern. + +The pattern starts at the top left of the screen, goes across the screen to the +right in a straight line, and stops temporarily on the right side of the +screen. Then the beam is swept back to the left side of the display, but down +one line. The new line is swept from left to right just as the first line was. +This pattern is repeated until the bottom line on the display has been swept. +Then the beam is moved from the bottom right corner of the display to the top +left corner, and the pattern is started over again. + +There is one variation of this scheme known as interlacing: here only +every second line is swept during one half-frame and the others are filled in +in during a second half-frame. + +Starting the beam at the top left of the display is called the beginning of a +frame. The frame ends when the beam reaches the the top left corner again as +it comes from the bottom right corner of the display. A frame is made up of +all of the lines the beam traced from the top of the display to the bottom. + +If the electron beam were on all of the time it was sweeping through the frame, +all of the dots on the display would be illuminated. There would be no black +border around the edges of the display. At the edges of the display the +picture would become distorted because the beam is hard to control there. To +reduce the distortion, the dots around the edges of the display are not +illuminated by the beam even though the beam may be pointing at them. The +viewable area of the display is reduced this way. + +Another important thing to understand is what becomes of the beam when no spot +is being painted on the visible area. The time the beam would have been +illuminating the side borders of the display is used for sweeping the beam back +from the right edge to the left and moving the beam down to the next line. The +time the beam would have been illuminating the top and bottom borders of the +display is used for moving the beam from the bottom-right corner of the display +to the top-left corner. + +The adapter card generates the signals which cause the display to turn on the +electron beam at each dot to generate a picture. The card also controls when +the display moves the beam from the right side to the left and down a line by +generating a signal called the horizontal sync (for synchronization) pulse. +One horizontal sync pulse occurs at the end of every line. The adapter also +generates a vertical sync pulse which signals the display to move the beam to +the top-left corner of the display. A vertical sync pulse is generated near +the end of every frame. + +The display requires that there be short time periods both before and after the +horizontal and vertical sync pulses so that the position of the electron beam +can stabilize. If the beam can't stabilize, the picture will not be steady. + +In a later section, we'll come back to these basics with definitions, +formulas and examples to help you use them. + +<sect>Basic Things to Know about your Display and Adapter<label id="basic"> +<p> + +There are some fundamental things you need to know before hacking an Xconfig +entry. These are: + +<itemize> +<item>your monitor's horizontal and vertical sync frequency options +<item>your video adapter's driving clock frequency, or "dot clock" +<item>your monitor's bandwidth +</itemize> +The monitor sync frequencies: + +The horizontal sync frequency is just the number of times per second the +monitor can write a horizontal scan line; it is the single most important +statistic about your monitor. The vertical sync frequency is the number of +times per second the monitor can traverse its beam vertically. + +Sync frequencies are usually listed on the specifications page of your monitor +manual. The vertical sync frequency number is typically calibrated in Hz +(cycles per second), the horizontal one in KHz (kilocycles per second). The +usual ranges are between 50 and 150Hz vertical, and between 31 and 135KHz +horizontal. + +If you have a multisync monitor, these frequencies will be given as ranges. +Some monitors, especially lower-end ones, have multiple fixed frequencies. +These can be configured too, but your options will be severely limited by the +built-in monitor characteristics. Choose the highest frequency pair for best +resolution. And be careful --- trying to clock a fixed-frequency monitor at a +higher speed than it's designed for can easily damage it. + +Earlier versions of this guide were pretty cavalier about overdriving +multisync monitors, pushing them past their nominal highest vertical +sync frequency in order to get better performance. We have since had more +reasons pointed out to us for caution on this score; we'll cover those under +<ref id="overd" name="Overdriving Your Monitor"> below. + +The card driving clock frequency: + +Your video adapter manual's spec page will usually give you the card's dot +clock (that is, the total number of pixels per second it can write to the +screen). If you don't have this information, the X server will get it for +you. Even if your X locks up your monitor, it will emit a line of clock and +other info to standard output. If you redirect this to a file, it should be +saved even if you have to reboot to get your console back. (Recent versions +of the X servers allsupport a --probeonly option that prints out this +information and exits without actually starting up X or changing the +video mode.) + +Your X startup message should look something like one of the following +examples: + +If you're using XFree86: + +<tscreen><verb> +Xconfig: /usr/X11R6/lib/X11/Xconfig +(**) stands for supplied, (--) stands for probed/default values +(**) Mouse: type: MouseMan, device: /dev/ttyS1, baudrate: 9600 +Warning: The directory "/usr/andrew/X11fonts" does not exist. + Entry deleted from font path. +(**) FontPath set to "/usr/lib/X11/fonts/misc/,/usr/lib/X11/fonts/75dpi/" +(--) S3: card type: 386/486 localbus +(--) S3: chipset: 924 + --- + Chipset -- this is the exact chip type; an early mask of the 86C911 + +(--) S3: chipset driver: s3_generic +(--) S3: videoram: 1024k + ----- + Size of on-board frame-buffer RAM + +(**) S3: clocks: 25.00 28.00 40.00 3.00 50.00 77.00 36.00 45.00 +(**) S3: clocks: 0.00 0.00 79.00 31.00 94.00 65.00 75.00 71.00 + ------------------------------------------------------ + Possible driving frequencies in MHz + +(--) S3: Maximum allowed dot-clock: 110MHz + ------ + Bandwidth +(**) S3: Mode "1024x768": mode clock = 79.000, clock used = 79.000 +(--) S3: Virtual resolution set to 1024x768 +(--) S3: Using a banksize of 64k, line width of 1024 +(--) S3: Pixmap cache: +(--) S3: Using 2 128-pixel 4 64-pixel and 8 32-pixel slots +(--) S3: Using 8 pages of 768x255 for font caching +</verb></tscreen> + +If you're using SGCS or X/Inside X: + +<tscreen><verb> +WGA: 86C911 (mem: 1024k clocks: 25 28 40 3 50 77 36 45 0 0 79 31 94 65 75 71) +--- ------ ----- -------------------------------------------- + | | | Possible driving frequencies in MHz + | | +-- Size of on-board frame-buffer RAM + | +-- Chip type + +-- Server type +</verb></tscreen> + +Note: do this with your machine unloaded (if at all possible). Because X is +an application, its timing loops can collide with disk activity, rendering the +numbers above inaccurate. Do it several times and watch for the numbers to +stabilize; if they don't, start killing processes until they do. SVr4 users: +the mousemgr process is particularly likely to mess you up. + +In order to avoid the clock-probe inaccuracy, you should clip out the clock +timings and put them in your Xconfig as the value of the Clocks property --- +this suppresses the timing loop and gives X an exact list of the clock values +it can try. Using the data from the example above: + +<tscreen><verb> +wga + Clocks 25 28 40 3 50 77 36 45 0 0 79 31 94 65 75 71 +</verb></tscreen> +On systems with a highly variable load, this may help you avoid mysterious X +startup failures. It's possible for X to come up, get its timings wrong due +to system load, and then not be able to find a matching dot clock in its +config database --- or find the wrong one! + +<sect1>The monitor's video bandwidth: +<p> + +If you're running XFree86, your server will probe your card and tell you +what your highest-available dot clock is. + +Otherwise, your highest available dot clock is approximately the monitor's +video bandwidth. There's a lot of give here, though --- some monitors +can run as much as 30% over their nominal bandwidth. The risks here have +to do with exceeding the monitor's rated vertical-sync frequency; we'll +discuss them in detail below. + +Knowing the bandwidth will enable you to make more intelligent choices +between possible configurations. It may affect your display's visual +quality (especially sharpness for fine details). + +Your monitor's video bandwidth should be included on the manual's spec page. +If it's not, look at the monitor's higest rated resolution. As a rule of +thumb, here's how to translate these into bandwidth estimates (and thus into +rough upper bounds for the dot clock you can use): + +<tscreen><verb> + 640x480 25 + 800x600 36 + 1024x768 65 + 1024x768 interlaced 45 + 1280x1024 110 + 1600x1200 185 +</verb></tscreen> + +BTW, there's nothing magic about this table; these numbers are just +the lowest dot clocks per resolution in the standard XFree86 Modes +database (except for the last, which I interpolated). The bandwidth +of your monitor may actually be higher than the minimum needed for its +top resolution, so don't be afraid to try a dot clock a few MHz +higher. + +Also note that bandwidth is seldom an issue for dot clocks under 65MHz +or so. With an SVGA card and most hi-res monitors, you can't get +anywhere near the limit of your monitor's video bandwidth. The +following are examples: + +<tscreen><verb> + Brand Video Bandwidth + ---------- --------------- + NEC 4D 75Mhz + Nano 907a 50Mhz + Nano 9080i 60Mhz + Mitsubishi HL6615 110Mhz + Mitsubishi Diamond Scan 100Mhz + IDEK MF-5117 65Mhz + IOCOMM Thinksync-17 CM-7126 136Mhz + HP D1188A 100Mhz + Philips SC-17AS 110Mhz + Swan SW617 85Mhz + Viewsonic 21PS 185Mhz +</verb></tscreen> +Even low-end monitors usually aren't terribly bandwidth-constrained for their +rated resolutions. The NEC Multisync II makes a good example --- it can't +even display 800x600 per its spec. It can only display 800x560. For such low +resolutions you don't need high dot clocks or a lot of bandwidth; probably the +best you can do is 32Mhz or 36Mhz, both of them are still not too far from the +monitor's rated video bandwidth of 30Mhz. + +At these two driving frequencies, your screen image may not be as sharp as it +should be, but definitely of tolerable quality. Of course it would be nicer if +NEC Multisync II had a video bandwidth higher than, say, 36Mhz. But this is +not critical for common tasks like text editing, as long as the difference is +not so significant as to cause severe image distortion (your eyes would tell +you right away if this were so). + +<sect1>What these control: +<p> + +The sync frequency ranges of your monitor, together with your video adapter's +dot clock, determine the ultimate resolution that you can use. But it's up to +the driver to tap the potential of your hardware. A superior hardware +combination without an equally competent device driver is a waste of money. +On the other hand, with a versatile device driver but less capable hardware, +you can push the hardware's envelope a little. This is the design philosophy +of XFree86. + +<sect>Interpreting the Basic Specifications<label id="specs"> +<p> + +This section explains what the specifications above mean, and some other +things you'll need to know. First, some definitions. Next to each in parens +is the variable name we'll use for it when doing calculations + +<descrip> +<tag/horizontal sync frequency (HSF)/ + Horizontal scans per second (see above). + +<tag/vertical sync frequency (VSF) / + Vertical scans per second (see above). Mainly important as the upper + limit on your refresh rate. + +<tag/dot clock (DCF)/ + More formally, `driving clock frequency'; The frequency of the + crystal or VCO on your adaptor --- the maximum dots-per-second it can + emit. + +<tag/video bandwidth (VB)/ + The highest frequency you can feed into your monitor's video + input and still expect to see anything discernible. If your adaptor + produces an alternating on/off pattern, its lowest frequency is half + the DCF, so in theory bandwidth starts making sense at DCF/2. For + tolerately crisp display of fine details in the video image, however, + you don't want it much below your highest DCF, and preferably higher. + +<tag/frame length (HFL, VFL)/ + Horizontal frame length (HFL) is the number of dot-clock ticks + needed for your monitor's electron gun to scan one horizontal line, + <em>including the inactive left and right borders</em>. Vertical + frame length (VFL) is the number of scan lines in the + <em>entire</em> image, including the inactive top and bottom + borders. + +<tag/screen refresh rate (RR)/ + The number of times per second your screen is repainted (this is + also called "frame rate"). Higher frequencies are better, as they + reduce flicker. 60Hz is good, VESA-standard 72Hz is better. + Compute it as +<tscreen><verb> + RR = DCF / (HFL * VFL) +</verb></tscreen> + + Note that the product in the denominator is <em>not</em> the same + as the monitor's visible resolution, but typically somewhat larger. + We'll get to the details of this below. + +The rates for which interlaced modes are usually specified (like 87Hz +interlaced) are actually the half-frame rates: an entire screen seems +to have about that flicker frequency for typical displays, but every +single line is refreshed only half as often. + +For calculation purposes we reckon an interlaced display at its +full-frame (refresh) rate, i.e. 43.5Hz. The quality of an interlaced +mode is better than that of a non-interlaced mode with the same +full-frame rate, but definitely worse then the non-interlaced one +corresponding to the half-frame rate. +</descrip> + +<sect1>About Bandwidth: +<p> + +Monitor makers like to advertise high bandwidth because it constrains the +sharpness of intensity and color changes on the screen. A high bandwidth +means smaller visible details. + +Your monitor uses electronic signals to present an image to +your eyes. Such signals always come in in wave form once they are converted +into analog form from digitized form. They can be considered as combinations +of many simpler wave forms each one of which has a fixed frequency, many of +them are in the Mhz range, eg, 20Mhz, 40Mhz, or even 70Mhz. Your monitor +video bandwidth is, effectively, the highest-frequency analog signal it can +handle without distortion. + +For our purposes, bandwidth is mainly important as an approximate cutoff point +for the highest dot clock you can use. + +<sect1>Sync Frequencies and the Refresh Rate: +<p> + +Each horizontal scan line on the display is just the visible portion of a +frame-length scan. At any instant there is actually only one dot active on +the screen, but with a fast enough refresh rate your eye's persistence of +vision enables you to "see" the whole image. + +Here are some pictures to help: + +<code> + _______________________ + | | The horizontal sync frequency + |->->->->->->->->->->-> | is the number of times per + | )| second that the monitor's + |<-----<-----<-----<--- | electron beam can trace + | | a pattern like this + | | + | | + | | + |_______________________| + _______________________ + | ^ | The vertical sync frequency + | ^ | | is the number of times per + | | v | second that the monitor's + | ^ | | electron beam can trace + | | | | a pattern like this + | ^ | | + | | v | + | ^ | | + |_______|_v_____________| +</code> + +Remember that the actual raster scan is a very tight zigzag pattern; that is, +the beam moves left-right and at the same time up-down. + +Now we can see how the dot clock and frame size relates to refresh rate. By +definition, one hertz (hz) is one cycle per second. So, if your horizontal +frame length is HFL and your vertical frame length is VFL, then to cover the +entire screen takes (HFL * VFL) ticks. Since your card emits DCF ticks per +second by definition, then obviously your monitor's electron gun(s) can sweep +the screen from left to right and back and from bottom to top and back DCF / +(HFL * VFL) times/sec. This is your screen's refresh rate, because it's how +many times your screen can be updated (thus <em>refreshed</em>) per second! + +You need to understand this concept to design a configuration which trades off +resolution against flicker in whatever way suits your needs. + +For those of you who handle visuals better than text, here is one: + +<code> + RR VB + | min HSF max HSF | + | | R1 R2 | | +max VSF -+----|------------/----------/---|------+----- max VSF + | |:::::::::::/::::::::::/:::::\ | + | \::::::::::/::::::::::/:::::::\ | + | |::::::::/::::::::::/:::::::::| | + | |:::::::/::::::::::/::::::::::\ | + | \::::::/::::::::::/::::::::::::\ | + | \::::/::::::::::/::::::::::::::| | + | |::/::::::::::/:::::::::::::::| | + | \/::::::::::/:::::::::::::::::\| + | /\:::::::::/:::::::::::::::::::| + | / \:::::::/::::::::::::::::::::|\ + | / |:::::/:::::::::::::::::::::| | + | / \::::/::::::::::::::::::::::| \ +min VSF -+----/-------\--/-----------------------|--\--- min VSF + | / \/ | \ + +--/----------/\------------------------+----\- DCF + R1 R2 \ | \ + min HSF | max HSF + VB +</code> + +This is a generic monitor mode diagram. The x axis of the diagram +shows the clock rate (DCF), the y axis represents the refresh rate +(RR). The filled region of the diagram describes the monitor's +capabilities: every point within this region is a possible video +mode. + +The lines labeled `R1' and `R2' represent a fixed resolutions (such as +640x480); they are meant to illustrate how one resolution can be realized +by many different combinations of dot clock and refresh rate. The R2 +line would represent a higher resolution than R1. + +The top and bottom boundaries of the permitted region are simply +horizontal lines representing the limiting values for the vertical sync +frequency. The video bandwidth is an upper limit to the clock rate and +hence is represented by a vertical line bounding the capability region on +the right. + +Under <ref id="cplot" name="Plotting Monitor Capabilities">) you'll +find a program that will help you plot a diagram like +this (but much nicer, with X graphics) for your individual monitor. +That section also discusses the interesting part; the derivation of +the boundaries resulting from the limits on the horizontal sync +frequency. + +<sect>Tradeoffs in Configuring your System<label id="trade"> +<p> + +Another way to look at the formula we derived above is + +<tscreen><verb> + DCF = RR * HFL * VFL +</verb></tscreen> +That is, your dot clock is fixed. You can use those dots per second to buy +either refresh rate, horizontal resolution, or vertical resolution. If one +of those increases, one or both of the others must decrease. + +Note, though, that your refresh rate cannot be greater than the maximum +vertical sync frequency of your monitor. Thus, for any given monitor at a +given dot clock, there is a minimum product of frame lengths below which you +can't force it. + +In choosing your settings, remember: if you set RR too low, you will get +mugged by screen flicker. + +You probably do not want to pull your refresh rate below 60Hz. This is the +flicker rate of fluorescent lights; if you're sensitive to those, you need +to hang with 72Hz, the VESA ergonomic standard. + +Flicker is very eye-fatiguing, though human eyes are adaptable and peoples' +tolerance for it varies widely. If you face your monitor at a 90% viewing +angle, are using a dark background and a good contrasting color for +foreground, and stick with low to medium intensity, you *may* be comfortable +at as little as 45Hz. + +The acid test is this: open a xterm with pure white back-ground and black +foreground using <TT>xterm -bg white -fg black</TT> and make it so large as +to cover the entire viewable area. Now turn your monitor's intensity to 3/4 of +its maximum setting, and turn your face away from the monitor. Try peeking at +your monitor sideways (bringing the more sensitive peripheral-vision cells into +play). If you don't sense any flicker or if you feel the flickering is +tolerable, then that refresh rate is fine with you. Otherwise you better +configure a higher refresh rate, because that semi-invisible flicker is going +to fatigue your eyes like crazy and give you headaches, even if the screen +looks OK to normal vision. + +For interlaced modes, the amount of flicker depends on more factors +such as the current vertical resolution and the actual screen +contents. So just experiment. You won't want to go much below about +85Hz half frame rate, though. + +So let's say you've picked a minimum acceptable refresh rate. In choosing +your HFL and VFL, you'll have some room for maneuver. + +<sect>Memory Requirements<label id="sizes"> +<p> + +Available frame-buffer RAM may limit the resolution you can achieve on color or +gray-scale displays. It probably isn't a factor on displays that have only two +colors, white and black with no shades of gray in between. + +For 256-color displays, a byte of video memory is required for each visible +dot to be shown. This byte contains the information that determines what mix +of red, green, and blue is generated for its dot. To get the amount of memory +required, multiply the number of visible dots per line by the number of +visible lines. For a display with a resolution of 800x600, this would be 800 +x 600 = 480,000, which is the number of visible dots on the display. This is +also, at one byte per dot, the number of bytes of video memory that are +necessary on your adapter card. + +Thus, your memory requirement will typically be (HR * VR)/1024 Kbytes of VRAM, +rounded up. If you have more memory than strictly required, you'll have extra +for virtual-screen panning. + +However, if you only have 512K on board, then you can't use this +resolution. Even if you have a good monitor, without enough video +RAM, you can't take advantage of your monitor's potential. On the +other hand, if your SVGA has one meg, but your monitor can display at +most 800x600, then high resolution is beyond your reach anyway (see +<ref id="inter" name="Using Interlaced Modes"> for a possible +remedy). + +Don't worry if you have more memory than required; XFree86 will make +use of it by allowing you to scroll your viewable area (see the +Xconfig file documentation on the virtual screen size parameter). +Remember also that a card with 512K bytes of memory really doesn't +have 512,000 bytes installed, it has 512 x 1024 = 524,288 bytes. + +If you're running SGCS X (now called X/Inside) using an S3 card, and +are willing to live with 16 colors (4 bits per pixel), you can set +depth 4 in Xconfig and effectively double the resolution your card can +handle. S3 cards, for example, normally do 1024x768x256. You can +make them do 1280x1024x16 with depth 4. + +<sect>Computing Frame Sizes<label id="frame"> +<p> + +Warning: this method was developed for multisync monitors. It will probably +work with fixed-frequency monitors as well, but no guarantees! + +Start by dividing DCF by your highest available HSF to get a horizontal +frame length. + +For example; suppose you have a Sigma Legend SVGA with a 65MHz dot clock, and +your monitor has a 55KHz horizontal scan frequency. The quantity (DCF / HSF) +is then 1181 (65MHz = 65000KHz; 65000/55 = 1181). + +Now for our first bit of black magic. You need to round this figure to the +nearest multiple of 8. This has to do with the VGA hardware controller used by +SVGA and S3 cards; it uses an 8-bit register, left-shifted 3 bits, for what's +really an 11-bit quantity. Other card types such as ATI 8514/A may not have +this requirement, but we don't know and the correction can't hurt. So round +the usable horizontal frame length figure down to 1176. + +This figure (DCF / HSF rounded to a multiple of 8) is the minimum HFL you can +use. You can get longer HFLs (and thus, possibly, more horizontal dots on the +screen) by setting the sync pulse to produce a lower HSF. But you'll pay with +a slower and more visible flicker rate. + +As a rule of thumb, 80% of the horizontal frame length is available for +horizontal resolution, the visible part of the horizontal scan line (this +allows, roughly, for borders and sweepback time -- that is, the time required +for the beam to move from the right screen edge to the left edge of the next +raster line). In this example, that's 944 ticks. + +Now, to get the normal 4:3 screen aspect ratio, set your vertical resolution +to 3/4ths of the horizontal resolution you just calculated. For this +example, that's 708 ticks. To get your actual VFL, multiply that by 1.05 +to get 743 ticks. + +The 4:3 is not technically magic; nothing prevents you from using a +non-Golden-Section ratio if that will get the best use out of your +screen real estate. It does make figuring frame height and frame +width from the diagonal size convenient, you just multiply the +diagonal by by 0.8 to get width and 0.6 to get height. + +So, HFL=1176 and VFL=743. Dividing 65MHz by the product of the two gives +us a nice, healthy 74.4Hz refresh rate. Excellent! Better than VESA standard! +And you got 944x708 to boot, more than the 800 by 600 you were probably +expecting. Not bad at all! + +You can even improve the refresh rate further, to almost 76 Hz, by using the +fact that monitors can often sync horizontally at 2khz or so higher than rated, +and by lowering VFL somewhat (that is, taking less than 75% of 944 in the +example above). But before you try this "overdriving" maneuver, if you do, +make <em>sure</em> that your monitor electron guns can sync up to 76 Hz +vertical. (the popular NEC 4D, for instance, cannot. It goes only up to 75 Hz +VSF). (See <ref id="overd" name="Overdriving Your Monitor"> for more general +discussion of this issue. ) + +So far, most of this is simple arithmetic and basic facts about raster +displays. Hardly any black magic at all! + +<sect>Black Magic and Sync Pulses<label id="magic"> +<p> + +OK, now you've computed HFL/VFL numbers for your chosen dot clock, found the +refresh rate acceptable, and checked that you have enough VRAM. Now for the +real black magic -- you need to know when and where to place synchronization +pulses. + +The sync pulses actually control the horizontal and vertical scan frequebcies +of the monitor. The HSF and VSF you've pulled off the spec sheet are nominal, +approximate maximum sync frequencies. The sync pulse in the signal from the +adapter card tells the monitor how fast to actually run. + +Recall the two pictures above? Only part of the time required for +raster-scanning a frame is used for displaying viewable image (ie. your +resolution). + +<sect1>Horizontal Sync: +<p> + +By previous definition, it takes HFL ticks to trace the a horizontal scan line. +Let's call the visible tick count (your horizontal screen resolution) HR. Then +Obviously, HR < HFL by definition. For concreteness, let's assume both start +at the same instant as shown below: +<code> + |___ __ __ __ __ __ __ __ __ __ __ __ __ + |_ _ _ _ _ _ _ _ _ _ _ _ | + |_______________________|_______________|_____ + 0 ^ ^ unit: ticks + | ^ ^ | + HR | | HFL + | |<----->| | + |<->| HSP |<->| + HGT1 HGT2 +</code> + +Now, we would like to place a sync pulse of length HSP as shown above, ie, +between the end of clock ticks for display data and the end of clock ticks for +the entire frame. Why so? because if we can achieve this, then your screen +image won't shift to the right or to the left. It will be where it supposed to +be on the screen, covering squarely the monitor's viewable area. + +Furthermore, we want about 30 ticks of "guard time" on either side of the sync +pulse. This is represented by HGT1 and HGT2. In a typical configuration HGT1 +!= HGT2, but if you're building a configuration from scratch, you want to start +your experimentation with them equal (that is, with the sync pulse centered). + +The symptom of a misplaced sync pulse is that the image is displaced on the +screen, with one border excessively wide and the other side of the image +wrapped around the screen edge, producing a white edge line and a band of +"ghost image" on that side. A way-out-of-place vertical sync pulse can +actually cause the image to roll like a TV with a mis-adjusted vertical hold +(in fact, it's the same phenomenon at work). + +If you're lucky, your monitor's sync pulse widths will be documented on its +specification page. If not, here's where the real black magic starts... + +You'll have to do a little trial and error for this part. But most of the +time, we can safely assume that a sync pulse is about 3.5 to 4.0 microsecond +in length. + +For concretness again, let's take HSP to be 3.8 microseconds (which btw, is not +a bad value to start with when experimenting). + +Now, using the 65Mhz clock timing above, we know HSP is equivalent to 247 clock +ticks (= 65 * 10**6 * 3.8 * 10^-6) [recall M=10^6, micro=10^-6] + +Some makers like to quote their horizontal framing parameters as timings rather +than dot widths. You may see the following terms: +<descrip> +<tag/active time (HAT)/ + Corresponds to HR, but in milliseconds. HAT * DCF = HR. +<tag/blanking time (HBT)/ + Corresponds to (HFL - HR), but in milliseconds. HBT * DCF = (HFL - + HR). +<tag/front porch (HFP)/ + This is just HGT1. +<tag/sync time/ + This is just HSP. +<tag/back porch (HBP)/ + This is just HGT2. +</descrip> + +<sect1>Vertical Sync: +<p> + +Going back to the picture above, how do we place the 247 clock ticks as shown +in the picture? + +Using our example, HR is 944 and HFL is 1176. The difference between the two +is 1176 - 944=232 < 247! Obviously we have to do some adjustment here. What +can we do? + +The first thing is to raise 1176 to 1184, and lower 944 to 936. Now the +difference = 1184-936= 248. Hmm, closer. + +Next, instead using 3.8, we use 3.5 for calculating HSP; then, we have +65*3.5=227. Looks better. But 248 is not much higher than 227. It's normally +necessary to have 30 or so clock ticks between HR and the start of SP, and the +same for the end of SP and HFL. AND they have to be multiple of eight! Are we +stuck? + +No. Let's do this, 936 % 8 = 0, (936 + 32) % 8 = 0 too. But 936 + 32 = 968, +968 + 227 = 1195, 1195 + 32 = 1227. Hmm.. this looks not too bad. But it's +not a multiple of 8, so let's round it up to 1232. + +But now we have potential trouble, the sync pulse is no longer placed right in +the middle between h and H any more. Happily, using our calculator we find +1232 - 32 = 1200 is also a multiple of 8 and (1232 - 32) - 968 = 232 +corresponding using a sync pulse of 3.57 micro second long, still +reasonable. + +In addition, 936/1232 ~ 0.76 or 76%, still not far from 80%, so it should be +all right. + +Furthermore, using the current horizontal frame length, we basically ask our +monitor to sync at 52.7khz (= 65Mhz/1232) which is within its capability. No +problems. + +Using rules of thumb we mentioned before, 936*75%=702, This is our new vertical +resolution. 702 * 1.05 = 737, our new vertical frame length. + +Screen refresh rate = 65Mhz/(737*1232)=71.6 Hz. This is still excellent. + +Figuring the vertical sync pulse layout is similar: +<code> + |___ __ __ __ __ __ __ __ __ __ __ __ __ + |_ _ _ _ _ _ _ _ _ _ _ _ | + |_______________________|_______________|_____ + 0 VR VFL unit: ticks + ^ ^ ^ + | | | + |<->|<----->| + VGT VSP +</code> + +We start the sync pulse just past the end of the vertical display data ticks. +VGT is the vertical guard time required for the sync pulse. Most monitors are +comfortable with a VGT of 0 (no guard time) and we'll use that in this +example. A few need two or three ticks of guard time, and it usually doesn't +hurt to add that. + +Returning to the example: since by the defintion of frame length, a vertical +tick is the time for tracing a complete HORIZONTAL frame, therefore in our +example, it is 1232/65Mhz=18.95us. + +Experience shows that a vertical sync pulse should be in the range of 50us and +300us. As an example let's use 150us, which translates into 8 vertical clock +ticks (150us/18.95us~8). + +Some makers like to quote their vertical framing parameters as timings rather +than dot widths. You may see the following terms: + +<descrip> +<tag/active time (VAT)/ + Corresponds to VR, but in milliseconds. VAT * VSF = VR. +<tag/blanking time (VBT)/ + Corresponds to (VFL - VR), but in milliseconds. VBT * VSF = (VFL - VR). +<tag/front porch (VFP)/ + This is just VGT. +<tag/sync time/ + This is just VSP. +<tag/back porch (VBP)/ + This is like a second guard time after the vertical sync pulse. It + is often zero. +</descrip> + +<sect>Putting it All Together<label id="synth"> +<p> + +The Xconfig file Table of Video Modes contains lines of numbers, with each line +being a complete specification for one mode of X-server operation. The fields +are grouped into four sections, the name section, the clock frequency section, +the horizontal section, and the vertical section. + +The name section contains one field, the name of the video mode specified by +the rest of the line. This name is referred to on the "Modes" line of the +Graphics Driver Setup section of the Xconfig file. The name field may be +omitted if the name of a previous line is the same as the current line. + +The dot clock section contains only the dot clock (what we've called DCF) field +of the video mode line. The number in this field specifies what dot clock was +used to generate the numbers in the following sections. + +The horizontal section consists of four fields which specify how each +horizontal line on the display is to be generated. The first field of the +section contains the number of dots per line which will be illuminated to form +the picture (what we've called HR). The second field of the section indicates +at which dot the horizontal sync pulse will begin. The third field indicates +at which dot the horizontal sync pulse will end. The fourth field specifies +the toal horzontal frame length (HFL). + +The vertical section also contains four fields. The first field contains the +number of visible lines which will appear on the display (VR). The second +field indicates the line number at which the vertical sync pulse will begin. +The third field specifies the line number at which the vertical sync pulse will +end. The fourth field contains the total vertical frame length (VFL). + +Example: +<tscreen><verb> + #Modename clock horizontal timing vertical timing + + "752x564" 40 752 784 944 1088 564 567 569 611 + 44.5 752 792 976 1240 564 567 570 600 +</verb></tscreen> +(Note: stock X11R5 doesn't support fractional dot clocks.) + +For Xconfig, all of the numbers just mentioned - the number of illuminated dots +on the line, the number of dots separating the illuminated dots from the +beginning of the sync pulse, the number of dots representing the duration of +the pulse, and the number of dots after the end of the sync pulse - are added +to produce the number of dots per line. The number of horizontal dots must be +evenly divisible by eight. + +Example horizontal numbers: 800 864 1024 1088 + +This sample line has the number of illuminated dots (800) followed by the +number of the dot when the sync pulse starts (864), followed by the number of +the dot when the sync pulse ends (1024), followed by the number of the last dot +on the horizontal line (1088). + +Note again that all of the horizontal numbers (800, 864, 1024, and 1088) are +divisible by eight! This is not required of the vertical numbers. + +The number of lines from the top of the display to the bottom form the frame. +The basic timing signal for a frame is the line. A number of lines will +contain the picture. After the last illuminated line has been displayed, a +delay of a number of lines will occur before the vertical sync pulse is +generated. Then the sync pulse will last for a few lines, and finally the last +lines in the frame, the delay required after the pulse, will be generated. The +numbers that specify this mode of operation are entered in a manner similar to +the following example. + +Example vertical numbers: 600 603 609 630 + +This example indicates that there are 600 visible lines on the display, that +the vertical sync pulse starts with the 603rd line and ends with the 609th, and +that there are 630 total lines being used. + +Note that the vertical numbers don't have to be divisible by eight! + +Let's return to the example we've been working. According to the above, all +we need to do from now on is to write our result into Xconfig as follows: +<tscreen><verb> +<name> DCF HR SH1 SH2 HFL VR SV1 SV2 VFL +</verb></tscreen> +where SH1 is the start tick of the horizontal sync pulse and SH2 is its end +tick; similarly, SV1 is the start tick of the vertical sync pulse and SV2 is +its end tick. +<tscreen><verb> +#name clock horizontal timing vertical timing flag +936x702 65 936 968 1200 1232 702 702 710 737 +</verb></tscreen> +No special flag necessary; this is a non-interlaced mode. Now we are really +done. + +<sect>Overdriving Your Monitor<label id="overd"> +<p> + +You should absolutely <EM>not</EM> try exceeding your monitor's scan +rates if it's a fixed-frequency type. You can smoke your hardware +doing this! There are potentially subtler problems with overdriving a +multisync monitor which you should be aware of. + +Having a pixel clock higher than the monitor's maximum bandwidth is +rather harmless, in contrast. (Note: the theoretical limit of +discernible features is reached when the pixel clock reaches double +the monitor's bandwidth. This is a straightforward application of +Nyquist's Theorem: consider the pixels as a spatially distributed +series of samples of the drive signals and you'll see why.) + +It's exceeding the rated maximum sync frequencies that's problematic. +Some modern monitors might have protection circuitry that shuts the +monitor down at dangerous scan rates, but don't rely on it. In +particular there are older multisync monitors (like the Multisync II) +which use just one horizontal transformer. These monitors will not +have much protection against overdriving them. While you necessarily +have high voltage regulation circuitry (which can be absent in fixed +frequency monitors), it will not necessarily cover every conceivable +frequency range, especially in cheaper models. This not only implies +more wear on the circuitry, it can also cause the screen phosphors to +age faster, and cause more than the specified radiation (including X-rays) +to be emitted from the monitor. + +Another importance of the bandwidth is that the monitor's input +impedance is specified only for that range, and using higher +frequencies can cause reflections probably causing minor screen +interferences, and radio disturbance. + +However, the basic problematic magnitude in question here is the slew +rate (the steepness of the video signals) of the video output drivers, +and that is usually independent of the actual pixel frequency, but +(if your board manufacturer cares about such problems) related +to the maximum pixel frequency of the board. + +So be careful out there... + +<sect>Using Interlaced Modes<label id="inter"> +<p> + +(This section is largely due to David Kastrup +<dak@pool.informatik.rwth-aachen.de>) + +At a fixed dot clock, an interlaced display is going to have +considerably less noticable flicker than a non-interlaced display, if +the vertical circuitry of your monitor is able to support it stably. +It is because of this that interlaced modes were invented in the first +place. + +Interlaced modes got their bad repute because they are inferior to +their non-interlaced companions at the same vertical scan frequency, +VSF (which is what is usually given in advertisements). But they are +definitely superior at the same horizontal scan rate, and that's where +the decisive limits of your monitor/graphics card usually lie. + +At a fixed <EM>refresh rate</EM> (or half frame rate, or VSF) the +interlaced display will flicker more: a 90Hz interlaced display will +be inferior to a 90Hz non-interlaced display. It will, however, need +only half the video bandwidth and half the horizontal scan rate. If +you compared it to a non-interlaced mode with the same dot clock and +the same scan rates, it would be vastly superior: 45Hz non-interlaced +is intolerable. With 90Hz interlaced, I have worked for years with my +Multisync 3D (at 1024x768) and am very satisfied. I'd guess you'd need +at least a 70Hz non-interlaced display for similar comfort. + +You have to watch a few points, though: use interlaced modes only at +high resolutions, so that the alternately lighted lines are close +together. You might want to play with sync pulse widths and positions +to get the most stable line positions. If alternating lines are bright +and dark, interlace will <EM>jump</EM> at you. I have one application that +chooses such a dot pattern for a menu background (XCept, no other +application I know does that, fortunately). I switch to 800x600 for +using XCept because it really hurts my eyes otherwise. + +For the same reason, use at least 100dpi fonts, or other fonts where +horizontal beams are at least two lines thick (for high resolutions, +nothing else will make sense anyhow). + +And of course, never use an interlaced mode when your hardware would +support a non-interlaced one with similar refresh rate. + +If, however, you find that for some resolution you are pushing either +monitor or graphics card to their upper limits, and getting +dissatisfactorily flickery or outwashed (bandwidth exceeded) display, +you might want to try tackling the same resolution using an +interlaced mode. Of course this is useless if the VSF +of your monitor is already close to its limits. + +Design of interlaced modes is easy: do it like a non-interlaced +mode. Just two more considerations are necessary: you need an odd +total number of vertical lines (the last number in your mode line), and +when you specify the "interlace" flag, the actual vertical frame rate +for your monitor doubles. Your monitor needs to support a 90Hz frame +rate if the mode you specified looks like a 45Hz mode apart from the +"Interlace" flag. + +As an example, here is my modeline for 1024x768 interlaced: my +Multisync 3D will support up to 90Hz vertical and 38kHz horizontal. + +<tscreen><verb> +ModeLine "1024x768" 45 1024 1048 1208 1248 768 768 776 807 Interlace +</verb></tscreen> + +Both limits are pretty much exhausted with this mode. Specifying the +same mode, just without the "Interlace" flag, still is almost at the +limit of the monitor's horizontal capacity (and strictly speaking, a +bit under the lower limit of vertical scan rate), but produces an +intolerably flickery display. + +Basic design rules: if you have designed a mode at less than half of +your monitor's vertical capacity, make the vertical total of lines odd +and add the "Interlace" flag. The display's quality should vastly +improve in most cases. + +If you have a non-interlaced mode otherwise exhausting your monitor's +specs where the vertical scan rate lies about 30% or more under the +maximum of your monitor, hand-designing an interlaced mode (probably +with somewhat higher resolution) could deliver superior results, but I +won't promise it. + +<sect>Questions and Answers<label id="answe"> +<p> + + Q. The example you gave is not a standard screen size, can I use it? + + A. Why not? There is NO reason whatsover why you have to use 640x480, +800x600, or even 1024x768. The XFree86 servers let you configure your hardware +with a lot of freedom. It usually takes two to three tries to come up the +right one. The important thing to shoot for is high refresh rate with +reasonable viewing area. not high resolution at the price of eye-tearing +flicker! + + Q. It this the only resolution given the 65Mhz dot clock and 55Khz HSF? + + A. Absolutely not! You are encouraged to follow the general procedure and +do some trial-and-error to come up a setting that's really to your liking. +Experimenting with this can be lots of fun. Most settings may just give you +nasty video hash, but in practice a modern multi-sync monitor is usually not +damaged easily. Be sure though, that your monitor can support the frame +rates of your mode before using it for longer times. + + Beware fixed-frequency monitors! This kind of hacking around can damage +them rather quickly. Be sure you use valid refresh rates for <EM>every</EM> +experiment on them. + + Q. You just mentioned two standard resolutions. In Xconfig, there are many +standard resolutions available, can you tell me whether there's any point in +tinkering with timings? + + A. Absolutely! Take, for example, the "standard" 640x480 listed in the +current Xconfig. It employes 25Mhz driving frequency, frame lengths are 800 +and 525 => refresh rate ~ 59.5Hz. Not too bad. But 28Mhz is a commonly +available driving frequency from many SVGA boards. If we use it to drive +640x480, following the procedure we discussed above, you would get frame +lengths like 812 and 505. Now the refresh rate is raised to 68Hz, a +quite significant improvement over the standard one. + + Q. Can you summarize what we have discussed so far? + + A. In a nutshell: + +<enum> +<item> +for any fixed driving frequency, raising max resolution incurs the penalty +of lowering refresh rate and thus introducing more flicker. +<item> +if high resolution is desirable and your monitor supports it, try to +get a SVGA card that provides a matching dot clock or DCF. The higher, +the better! +</enum> + +<sect>Fixing Problems with the Image.<label id="fixes"> +<p> + +OK, so you've got your X configuration numbers. You put them in Xconfig with +a test mode label. You fire up X, hot-key to the new mode, ... and the image +doesn't look right. What do you do? Here's a list of common problems and how +to fix them. + +(Fixing these minor distortions is where <bf>xvidtune</bf>(1) really shines.) + +You <em>move</em> the image by changing the sync pulse timing. You +<em>scale</em> it by changing the frame length (you need to move the +sync pulse to keep it in the same relative position, otherwise scaling will +move the image as well). Here are some more specific recipes: + +The horizontal and vertical positions are independent. That is, moving the +image horizontally doesn't affect placement vertically, or vice-versa. +However, the same is not quite true of scaling. While changing the horizontal +size does nothing to the vertical size or vice versa, the total change in both +may be limited. In particular, if your image is too large in both dimensions +you will probably have to go to a higher dot clock to fix it. Since this +raises the usable resolution, it is seldom a problem! + +<sect1>The image is displaced to the left or right +<p> + +To fix this, move the horizontal sync pulse. That is, increment or decrement +(by a multiple of 8) the middle two numbers of the horizontal timing section +that define the leading and trailing edge of the horizontal sync pulse. + +If the image is shifted left (right border too large, you want to move +the image to the right) decrement the numbers. If the image is shifted right +(left border too large, you want it to move left) increment the sync pulse. + +<sect1>The image is displaced up or down +<p> + +To fix this, move the vertical sync pulse. That is, increment or decrement the +middle two numbers of the vertical timing section that define the leading and +trailing edge of the vertical sync pulse. + +If the image is shifted up (lower border too large, you want to move the image +down) decrement the numbers. If the image is shifted down (top border too +large, you want it to move up) increment the numbers. + +<sect1>The image is too large both horizontally and vertically +<p> + +Switch to a higher card clock speed. If you have multiple modes in your +clock file, possibly a lower-speed one is being activated by mistake. + +<sect1>The image is too wide (too narrow) horizontally +<p> + +To fix this, increase (decrease) the horizontal frame length. That is, change +the fourth number in the first timing section. To avoid moving the image, also +move the sync pulse (second and third numbers) half as far, to keep it in the +same relative position. + +<sect1>The image is too deep (too shallow) vertically +<p> + +To fix this, increase (decrease) the vertical frame length. That is, change +the fourth number in the second timing section. To avoid moving the image, +also move the sync pulse (second and third numbers) half as far, to keep it in +the same relative position. + +Any distortion that can't be handled by combining these techniques is probably +evidence of something more basically wrong, like a calculation mistake or a +faster dot clock than the monitor can handle. + +Finally, remember that increasing either frame length will decrease your +refresh rate, and vice-versa. + +<sect>Plotting Monitor Capabilities<label id="cplot"> +<p> + +To plot a monitor mode diagram, you'll need the gnuplot package (a +freeware plotting language for UNIX-like operating systems) and the +tool <TT>modeplot</TT>, a shell/gnuplot script to plot the diagram from your +monitor characteristics, entered as command-line options. + +Here is a copy of modeplot: + +<code> +#!/bin/sh +# +# modeplot -- generate X mode plot of available monitor modes +# +# Do `modeplot -?' to see the control options. +# +# (Id: video-modes.sgml,v 1.2 1997/08/08 15:07:24 esr Exp $) + +# Monitor description. Bandwidth in MHz, horizontal frequencies in kHz +# and vertical frequencies in Hz. +TITLE="Viewsonic 21PS" +BANDWIDTH=185 +MINHSF=31 +MAXHSF=85 +MINVSF=50 +MAXVSF=160 +ASPECT="4/3" +vesa=72.5 # VESA-recommended minimum refresh rate + +while [ "$1" != "" ] +do + case $1 in + -t) TITLE="$2"; shift;; + -b) BANDWIDTH="$2"; shift;; + -h) MINHSF="$2" MAXHSF="$3"; shift; shift;; + -v) MINVSF="$2" MAXVSF="$3"; shift; shift;; + -a) ASPECT="$2"; shift;; + -g) GNUOPTS="$2"; shift;; + -?) cat <<EOF +modeplot control switches: + +-t "<description>" name of monitor defaults to "Viewsonic 21PS" +-b <nn> bandwidth in MHz defaults to 185 +-h <min> <max> min & max HSF (kHz) defaults to 31 85 +-v <min> <max> min & max VSF (Hz) defaults to 50 160 +-a <aspect ratio> aspect ratio defaults to 4/3 +-g "<options>" pass options to gnuplot + +The -b, -h and -v options are required, -a, -t, -g optional. You can +use -g to pass a device type to gnuplot so that (for example) modeplot's +output can be redirected to a printer. See gnuplot(1) for details. + +The modeplot tool was created by Eric S. Raymond <esr@thyrsus.com> based on +analysis and scratch code by Martin Lottermoser <Martin.Lottermoser@mch.sni.de> + +This is modeplot Revision: 1.2 $ +EOF + exit;; + esac + shift +done + +gnuplot $GNUOPTS <<EOF +set title "$TITLE Mode Plot" + +# Magic numbers. Unfortunately, the plot is quite sensitive to changes in +# these, and they may fail to represent reality on some monitors. We need +# to fix values to get even an approximation of the mode diagram. These come +# from looking at lots of values in the ModeDB database. +F1 = 1.30 # multiplier to convert horizontal resolution to frame width +F2 = 1.05 # multiplier to convert vertical resolution to frame height + +# Function definitions (multiplication by 1.0 forces real-number arithmetic) +ac = (1.0*$ASPECT)*F1/F2 +refresh(hsync, dcf) = ac * (hsync**2)/(1.0*dcf) +dotclock(hsync, rr) = ac * (hsync**2)/(1.0*rr) +resolution(hv, dcf) = dcf * (10**6)/(hv * F1 * F2) + +# Put labels on the axes +set xlabel 'DCF (MHz)' +set ylabel 'RR (Hz)' 6 # Put it right over the Y axis + +# Generate diagram +set grid +set label "VB" at $BANDWIDTH+1, ($MAXVSF + $MINVSF) / 2 left +set arrow from $BANDWIDTH, $MINVSF to $BANDWIDTH, $MAXVSF nohead +set label "max VSF" at 1, $MAXVSF-1.5 +set arrow from 0, $MAXVSF to $BANDWIDTH, $MAXVSF nohead +set label "min VSF" at 1, $MINVSF-1.5 +set arrow from 0, $MINVSF to $BANDWIDTH, $MINVSF nohead +set label "min HSF" at dotclock($MINHSF, $MAXVSF+17), $MAXVSF + 17 right +set label "max HSF" at dotclock($MAXHSF, $MAXVSF+17), $MAXVSF + 17 right +set label "VESA $vesa" at 1, $vesa-1.5 +set arrow from 0, $vesa to $BANDWIDTH, $vesa nohead # style -1 +plot [dcf=0:1.1*$BANDWIDTH] [$MINVSF-10:$MAXVSF+20] \ + refresh($MINHSF, dcf) notitle with lines 1, \ + refresh($MAXHSF, dcf) notitle with lines 1, \ + resolution(640*480, dcf) title "640x480 " with points 2, \ + resolution(800*600, dcf) title "800x600 " with points 3, \ + resolution(1024*768, dcf) title "1024x768 " with points 4, \ + resolution(1280*1024, dcf) title "1280x1024" with points 5, \ + resolution(1600*1280, dcf) title "1600x1200" with points 6 + +pause 9999 +EOF +</code> + +Once you know you have <TT>modeplot</TT> and the gnuplot package in +place, you'll need the following monitor characteristics: + +<itemize> +<item> video bandwidth (VB) +<item> range of horizontal sync frequency (HSF) +<item> range of vertical sync frequency (VSF) +</itemize> + +The plot program needs to make some simplifying assumptions which are +not necessarily correct. This is the reason why the resulting diagram is +only a rough description. These assumptions are: + +<enum> +<item> All resolutions have a single fixed aspect ratio AR = HR/VR. +Standard resolutions have AR = 4/3 or AR = 5/4. The <TT>modeplot</TT> +programs assumes 4/3 by default, but you can override this. +<item> For the modes considered, horizontal and vertical frame lengths are +fixed multiples of horizontal and vertical resolutions, respectively: + +<tscreen><verb> + HFL = F1 * HR + VFL = F2 * VR +</verb></tscreen> +</enum> + +As a rough guide, take F1 = 1.30 and F2 = 1.05 (see <ref id=frame> +"Computing Frame Sizes"). + +Now take a particular sync frequency, HSF. Given the assumptions just +presented, every value for the clock rate DCF already determines the +refresh rate RR, i.e. for every value of HSF there is a function RR(DCF). +This can be derived as follows. + +The refresh rate is equal to the clock rate divided by the product of the +frame sizes: + +<tscreen><verb> + RR = DCF / (HFL * VFL) (*) +</verb></tscreen> + +On the other hand, the horizontal frame length is equal to the clock rate +divided by the horizontal sync frequency: + +<tscreen><verb> + HFL = DCF / HSF (**) +</verb></tscreen> + +VFL can be reduced to HFL be means of the two assumptions above: + +<tscreen><verb> + VFL = F2 * VR + = F2 * (HR / AR) + = (F2/F1) * HFL / AR (***) +</verb></tscreen> + +Inserting (**) and (***) into (*) we obtain: + +<tscreen><verb> + RR = DCF / ((F2/F1) * HFL**2 / AR) + = (F1/F2) * AR * DCF * (HSF/DCF)**2 + = (F1/F2) * AR * HSF**2 / DCF +</verb></tscreen> + +For fixed HSF, F1, F2 and AR, this is a hyperbola in our diagram. Drawing +two such curves for minimum and maximum horizontal sync frequencies we +have obtained the two remaining boundaries of the permitted region. + +The straight lines crossing the capability region represent particular +resolutions. This is based on (*) and the second assumption: + +<tscreen><verb> + RR = DCF / (HFL * VFL) = DCF / (F1 * HR * F2 * VR) +</verb></tscreen> + +By drawing such lines for all resolutions one is interested in, one +can immediately read off the possible relations between resolution, +clock rate and refresh rate of which the monitor is capable. Note that +these lines do not depend on monitor properties, but they do depend on +the second assumption. + +The <TT>modeplot</TT> tool provides you with an easy way to do this. Do +<TT>modeplot -?</TT> to see its control options. A typical invocation +looks like this: + +<tscreen><verb> + modeplot -t "Swan SW617" -b 85 -v 50 90 -h 31 58 +</verb></tscreen> + +The -b option specifies video bandwidth; -v and -h set horizontal and +vertical sync frequency ranges. + +When reading the output of <TT>modeplot</TT>, always bear in mind that +it gives only an approximate description. For example, it disregards +limitations on HFL resulting from a minimum required sync pulse width, +and it can only be accurate as far as the assumptions are. It is +therefore no substitute for a detailed calculation (involving some +black magic) as presented in <ref id="synth" name="Putting it All +Together">. However, it should give you a better feeling for what +is possible and which tradeoffs are involved. + +<sect>Credits<label id="credi"> +<p> + +The original ancestor of this document was by Chin Fang +<fangchin@leland.stanford.edu>. + +Eric S. Raymond <esr@snark.thyrsus.com> reworked, reorganized, and +massively rewrote Chin Fang's original in an attempt to understand it. In +the process, he merged in most of a different how-to by Bob Crosson +<crosson@cam.nist.gov>. + +The material on interlaced modes is largely by David Kastrup +<dak@pool.informatik.rwth-aachen.de> + +Martin Lottermoser <Martin.Lottermoser@mch.sni.de> contributed +the idea of using gnuplot to make mode diagrams and did the +mathematical analysis behind <TT>modeplot</TT>. The distributed +<TT>modeplot</TT> was redesigned and generalized by ESR from +Martin's original gnuplot code for one case. +<verb> +$XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/VideoModes.sgml,v 1.1 2001/06/04 13:50:16 dawes Exp $ + + + + + +$XConsortium: VidModes.sgml /main/7 1996/02/21 17:46:17 kaleb $ +</verb> + +</article> + +<!-- +The following sets edit modes for GNU EMACS +Local Variables: +fill-prefix:"\t" +fill-column:75 +End: +-- > diff --git a/xc/programs/Xserver/hw/xfree86/drivers/s3/Imakefile b/xc/programs/Xserver/hw/xfree86/drivers/s3/Imakefile new file mode 100644 index 000000000..ffb7ae482 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/s3/Imakefile @@ -0,0 +1,60 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3/Imakefile,v 1.9 2001/07/06 07:52:01 keithp Exp $ */ + +#define IHaveModules +#include <Server.tmpl> + +SRCS = s3_driver.c s3_IBMRGB.c s3_Trio64DAC.c s3_accel_newmmio.c \ + s3_accel_pio.c s3_cursor.c s3_bios.c s3_video.c s3_dga.c \ + s3_Ti.c + +OBJS = s3_driver.o s3_IBMRGB.o s3_Trio64DAC.o s3_accel_newmmio.o \ + s3_accel_pio.o s3_cursor.o s3_bios.o s3_video.o s3_dga.o \ + s3_Ti.o + +#if defined(XF86DriverSDK) +INCLUDES = -I. -I../../include +#else +INCLUDES = -I. -I$(XF86COMSRC) -I$(XF86OSSRC) \ + -I$(SERVERSRC)/fb -I$(SERVERSRC)/mi \ + -I$(SERVERSRC)/mfb \ + -I$(XF86SRC)/xaa -I$(SERVERSRC)/cfb \ + -I$(XF86SRC)/xf1bpp -I$(XF86SRC)/xf4bpp \ + -I$(XF86SRC)/xf24_32bpp -I$(SERVERSRC)/Xext \ + -I$(XF86SRC)/vgahw -I$(XF86SRC)/ramdac \ + -I$(XF86SRC)/rac -I$(XF86SRC)/int10 \ + -I$(XF86SRC)/fbdevhw -I$(XF86SRC)/ddc \ + -I$(XF86SRC)/i2c -I$(XF86OSSRC)/vbe \ + -I$(SERVERSRC)/include -I$(XINCLUDESRC) -I$(FONTINCSRC) \ + -I$(EXTINCSRC) -I$(SERVERSRC)/render +#endif + +#if MakeHasPosixVariableSubstitutions +SubdirLibraryRule($(OBJS)) +#endif + +NormalAsmObjectRule() + +ModuleObjectRule() +ObjectModuleTarget(s3, $(OBJS)) + +InstallObjectModule(s3,$(MODULEDIR),drivers) + +DependTarget() + +ObjectFromSpecialSource(s3_accel_pio, s3_accel, -DS3_GENERIC) +ObjectFromSpecialSource(s3_accel_newmmio, s3_accel, -DS3_NEWMMIO) +SpecialCObjectRule(s3_video,$(_NOOP_), -DS3_NEWMMIO) + +InstallDriverSDKNonExecFile(Imakefile,$(DRIVERSDKDIR)/drivers/s3) +InstallDriverSDKNonExecFile(s3.h,$(DRIVERSDKDIR)/drivers/s3) +InstallDriverSDKNonExecFile(s3_reg.h,$(DRIVERSDKDIR)/drivers/s3) +InstallDriverSDKNonExecFile(s3_driver.c,$(DRIVERSDKDIR)/drivers/s3) +InstallDriverSDKNonExecFile(s3_accel.c,$(DRIVERSDKDIR)/drivers/s3) +InstallDriverSDKNonExecFile(s3_cursor.c,$(DRIVERSDKDIR)/drivers/s3) +InstallDriverSDKNonExecFile(s3_video.c,$(DRIVERSDKDIR)/drivers/s3) +InstallDriverSDKNonExecFile(s3_dga.c,$(DRIVERSDKDIR)/drivers/s3) +InstallDriverSDKNonExecFile(s3_bios.c,$(DRIVERSDKDIR)/drivers/s3) +InstallDriverSDKNonExecFile(s3_Trio64DAC.c,$(DRIVERSDKDIR)/drivers/s3) +InstallDriverSDKNonExecFile(s3_IBMRGB.c,$(DRIVERSDKDIR)/drivers/s3) +InstallDriverSDKNonExecFile(s3_Ti.c,$(DRIVERSDKDIR)/drivers/s3) + diff --git a/xc/programs/Xserver/hw/xfree86/drivers/s3/newmmio.h b/xc/programs/Xserver/hw/xfree86/drivers/s3/newmmio.h new file mode 100644 index 000000000..15e7f3c9f --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/s3/newmmio.h @@ -0,0 +1,263 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3/newmmio.h,v 1.6 2001/07/02 10:46:04 alanh Exp $ */ + +/* + * + * Copyright 1995-1997 The XFree86 Project, Inc. + * + */ + +#ifndef _NEWMMIO_H_ +#define _NEWMMIO_H_ + +#include <Xmd.h> + + +#define int16 CARD16 +#define int32 CARD32 + +#define S3_NEWMMIO_VGABASE (S3_NEWMMIO_REGBASE + 0x8000) + +typedef struct { int16 vendor_ID; int16 device_ID; } pci_id; +typedef struct { int16 cmd; int16 devsel; } cmd_devsel; + +typedef struct { + pci_id pci_ident; + cmd_devsel cmd_device_sel; + int32 class_code; + int32 dummy5; + int32 base0; + char dummy1[0x20-sizeof(int32)]; + int32 bios_base; + char dummy2[0x3c - 0x32]; +} pci_conf_regs; + + +typedef struct { int16 filler; int16 adv_f_cntl; } adv_f_cntl; + +typedef struct { + int32 cur_point; + char dummy1[4]; + int32 dest_stp; + char dummy2[4]; + int32 err_term; + char dummy3[4]; + int32 command; + int32 short_stroke; + int32 bkgd_color; + int32 frgd_color; + int32 wrt_mask; + int32 rd_mask; + int32 color_cmp; + int32 col_mix; + int32 sciss_topleft; + int32 sciss_botright; + int32 pix_mult; + int32 mult_misc; + int32 axis_pcnt; +} packed_enhanced_regs; + +typedef struct { + int32 prim_stream_cntl; + int32 col_chroma_key_cntl; + char dummy1[0x8190 - 0x8184-sizeof(int32)]; + int32 second_stream_cntl; + int32 chroma_key_upper_bound; + int32 second_stream_stretch; + char dummy2[0x81a0 - 0x8198-sizeof(int32)]; + int32 blend_cntl; + char dummy3[0x81c0 - 0x81a0-sizeof(int32)]; + int32 prim_fbaddr0; + int32 prim_fbaddr1; + int32 prim_stream_stride; + int32 double_buffer; + int32 second_fbaddr0; + int32 second_fbaddr1; + int32 second_stream_stride; + int32 opaq_overlay_cntl; + int32 k1; + int32 k2; + int32 dda_vert; + int32 streams_fifo; + int32 prim_start_coord; + int32 prim_window_size; + int32 second_start_coord; + int32 second_window_size; +} streams_proc_regs; + +typedef struct { char atr_cntl_ind; char attr_cntl_dat; char misc_out; + char viseo_enable; } v3c0; +typedef struct { char seq_index; char seq_data; char dac_mask; + char dac_rd_index; } v3c4; +typedef struct { char dac_wr_index; char dac_data; char feature_cntl; + char filler; } v3c8; +typedef struct v3cc { char misc_out; char filler; char graph_cntl_index; + char graph_cntl_data; } v3cc; +typedef struct { + v3c0 v3c0_regs; + v3c4 v3c4_regs; + v3c8 v3c8_regs; + v3cc v3cc_regs; +} vga_3c_regs; + +typedef struct { char crt_index; char crt_data; int16 filler; } v3d4; +typedef struct { int16 filler1; char feature_cntl; char filler2;} v3d8; + +typedef struct { + int32 filler; + v3d4 v3d4_regs; + v3d8 v3d8_regs; +} vga_3bd_regs ; + +typedef struct { + int32 subsystem_csr; + int32 dummy; + adv_f_cntl adv_func_cntl; +} subsys_regs; + + +typedef struct { + int32 cur_x; + char filler1[0x8ae8 - 0x86e8 - sizeof(int32)]; + int32 dy_axstep; + char filler2[0x8ee8 - 0x8ae8 - sizeof(int32)]; + int32 dx_diastep; + char filler3[0x92e8 - 0x8ee8 - sizeof(int32)]; + int32 line_err; + char filler33[0x96e8 - 0x92e8 - sizeof(int32)]; + int32 mj_ax_pcnt; + char filler4[0x9ae8 - 0x96e8 - sizeof(int32)]; + int32 gp_stat; + char filler5[0x9ee8 - 0x9ae8 - sizeof(int32)]; + int32 stroke_vectrans; + char filler6[0xa2e8 - 0x9ee8 - sizeof(int32)]; + int32 back_color; + char filler7[0xa6e8 - 0xa2e8 - sizeof(int32)]; + int32 fore_col; + char filler8[0xaae8 - 0xa6e8 - sizeof(int32)]; + int32 bitplane_wmask; + char filler88[0xaee8 - 0xaae8 - sizeof(int32)]; + int32 bitplane_rmask; + char filler9[0xb2e8 - 0xaee8 - sizeof(int32)]; + int32 color_compare; + char filler10[0xb6e8 - 0xb2e8 - sizeof(int32)]; + int32 back_mix; + char filler101[0xbae8 - 0xb6e8 - sizeof(int32)]; + int32 fore_mix; + char filler11[0xbee8 - 0xbae8 - sizeof(int32)]; + int32 r_reg_data; + char filler12[0xe2e8 - 0xbee8 - sizeof(int32)]; + int32 pixel_data_transfer; +} enhanced_regs; + +typedef struct { + int32 lpb_mode; + int32 lpb_fifostat; + int32 lpb_intflags; + int32 lpb_fb0addr; + int32 lpb_fb1addr; + int32 lpb_direct_addr; + int32 lpb_direct_data; + int32 lpb_gpio; + int32 lpb_serial_port; + int32 lpb_input_winsize; + int32 lpb_data_offsets; + int32 lpb_hor_decimctl; + int32 lpb_vert_decimctl; + int32 lpb_line_stride; + int32 lpb_output_fifo; +} lpbus_regs; + +typedef struct { + int32 img[0x8000/4]; + union { pci_conf_regs regs; + char dummy[0x100]; + } pci_regs; + union { packed_enhanced_regs regs; + char dummy[0x80]; + } pk_enh_regs; + union { streams_proc_regs regs; + char dummy[0x82e8-0x8180]; + } streams_regs; + union { int32 cur_y; + char dummy[0x83b0 - 0x82e8]; + } cur_y; + union { vga_3bd_regs regs; + char dummy[0x83c0 - 0x83b0]; + } v3b_regs; + union { vga_3c_regs regs; + char dummy[0x83d0 - 0x83c0]; + } v3c_regs; + union { vga_3bd_regs regs; + char dummy[0x8504 - 0x83d0]; + } v3d_regs; + union { subsys_regs regs; + char dummy[0x86e8 - 0x8504]; + } subs_regs; + union { enhanced_regs regs; + char dummy[0xff00 - 0x86e8]; + } enh_regs; + union { lpbus_regs regs; + char dummy[0xff5c - 0xff00]; + } lbp_regs; +} mm_trio_regs ; + +#define mmtr volatile mm_trio_regs * + +#define s3MmioMem (pS3->MMIOBase) + +#define IMG_TRANS (((mmtr)s3MmioMem)->img) + +#define SET_WRT_MASK(msk) ((mmtr)s3MmioMem)->pk_enh_regs.regs.wrt_mask = (msk) +#define SET_RD_MASK(msk) ((mmtr)s3MmioMem)->pk_enh_regs.regs.rd_mask = (msk) +#define SET_FRGD_COLOR(col) ((mmtr)s3MmioMem)->pk_enh_regs.regs.frgd_color = (col) +#define SET_BKGD_COLOR(col) ((mmtr)s3MmioMem)->pk_enh_regs.regs.bkgd_color = (col) +#define SET_COLOR_CMP(col) ((mmtr)s3MmioMem)->pk_enh_regs.regs.color_cmp = (col) +#define SET_FRGD_MIX(fmix) ((mmtr)s3MmioMem)->enh_regs.regs.fore_mix = (fmix) +#define SET_BKGD_MIX(bmix) ((mmtr)s3MmioMem)->enh_regs.regs.back_mix = (bmix) +#define SET_PIX_CNTL(val) ((mmtr)s3MmioMem)->pk_enh_regs.regs.pix_mult = (val) | (MULT_MISC2 << 16) +#define SET_MIN_AXIS_PCNT(min) ((mmtr)s3MmioMem)->enh_regs.regs.r_reg_data = (min) & 0xffff +#define SET_MAJ_AXIS_PCNT(maj) ((mmtr)s3MmioMem)->enh_regs.regs.mj_ax_pcnt = (maj) +#define SET_CURPT(c_x, c_y) ((mmtr)s3MmioMem)->pk_enh_regs.regs.cur_point = ((c_y)&0xffff) | ((c_x) << 16) +#define SET_CUR_X(c_x) ((mmtr)s3MmioMem)->enh_regs.regs.cur_x = (c_x) +#define SET_CUR_Y(c_y) ((mmtr)s3MmioMem)->cur_y.cur_y = (c_y) +#define SET_DESTSTP(x,y) ((mmtr)s3MmioMem)->pk_enh_regs.regs.dest_stp = ((y)&0xffff) | ((x) << 16) +#define SET_AXIS_PCNT(maj, min) ((mmtr)s3MmioMem)->pk_enh_regs.regs.axis_pcnt = ((min)&0xffff) | ((maj) << 16) +#define SET_CMD(c_d) { mem_barrier(); ((mmtr)s3MmioMem)->pk_enh_regs.regs.command = (c_d); } +#define SET_ERR_TERM(e) ((mmtr)s3MmioMem)->pk_enh_regs.regs.err_term = (e) +#define SET_SCISSORS(x1,y1,x2,y2) {\ + ((mmtr)s3MmioMem)->pk_enh_regs.regs.sciss_topleft = ((y1)&0xffff) | ((x1) << 16);\ + ((mmtr)s3MmioMem)->pk_enh_regs.regs.sciss_botright = ((y2)&0xffff) | ((x2) << 16);\ + } +#define SET_SCISSORS_RB(x,y) ((mmtr)s3MmioMem)->pk_enh_regs.regs.sciss_botright = ((y)&0xffff) | ((x) << 16) +#define SET_SCISSORS_L(l) ((mmtr)s3MmioMem)->pk_enh_regs.regs.sciss_topleft = ((l) << 16); +#define SET_MULT_MISC(val) ((mmtr)s3MmioMem)->pk_enh_regs.regs.mult_misc = (val) + + +/* + * reads from GP_STAT + */ +#if !defined(__alpha__) +#define INB_GP_STAT() ((((mmtr)s3MmioMem)->enh_regs.regs.gp_stat) & 0xff) +#define INW_GP_STAT() ((((mmtr)s3MmioMem)->enh_regs.regs.gp_stat)) +#else +#define INB_GP_STAT() inb(GP_STAT) +#define INW_GP_STAT() inw(GP_STAT) +#endif + +#define SET_PIX_TRANS_L(val) ((mmtr)s3MmioMem)->img[0] = (val) +#define SET_MIX(b,f) ((mmtr)s3MmioMem)->pk_enh_regs.regs.col_mix = ((b) << 16) | (f) + + +#define WaitQueue(v) \ + if(!(pS3->PCIRetry)) { \ + mem_barrier(); \ + while(inb(GP_STAT) & (0x0100 >> (v))); \ + } + +#define CMD_REG_WIDTH 0x200 /* select 32bit command register */ + +#define WaitQueue16_32(n16,n32) \ + if((pS3->s3Bpp) <= 2) { WaitQueue(n16); } \ + else { WaitQueue(n32); } + +#endif /* _NEWMMIO_H_ */ diff --git a/xc/programs/Xserver/hw/xfree86/drivers/s3/s3.h b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3.h new file mode 100644 index 000000000..779d7a567 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3.h @@ -0,0 +1,231 @@ +/* + * Copyright 2001 Ani Joshi <ajoshi@unixbox.com> + * + * XFree86 4.x driver for S3 chipsets + * + * + * 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 Ani Joshi not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Ani Joshi makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ANI JOSHI 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. + * + * + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3/s3.h,v 1.12 2001/08/15 11:54:27 tsi Exp $ */ + + +#ifndef _S3_H +#define _S3_H + +#include "xf86.h" +#include "xf86Pci.h" +#include "xf86PciInfo.h" +#include "xf86RamDac.h" +#include "xaa.h" +#include "vbe.h" +#include "xf86_ansic.h" +#include "vgaHW.h" + + +#include "xf86xv.h" +#include "Xv.h" +#include "fourcc.h" + + +#ifndef S3_USEFB +#define PSZ 8 +#include "cfb.h" +#undef PSZ +#include "cfb16.h" +#include "cfb24.h" +#include "cfb32.h" +#endif + +typedef struct _S3RegRec { + unsigned char cr31, cr32, cr33, cr34, cr3a, cr3b, cr3c; + unsigned char cr3b2, cr3c2; + unsigned char cr40, cr42, cr43, cr44, cr45; + unsigned char cr50, cr51, cr53, cr54, cr55, cr58, cr59, cr5a, + cr5d, cr5e; + unsigned char cr60, cr61, cr62, cr65, cr66, cr67, cr6d; + unsigned char s3save[10]; + unsigned char s3syssave[46]; + unsigned char dacregs[0x101]; + unsigned char color_stack[8]; + unsigned char clock; +} S3RegRec, *S3RegPtr; + + +typedef struct { + unsigned char brightness; + unsigned char contrast; + FBAreaPtr area; + RegionRec clip; + CARD32 colorKey; + CARD32 videoStatus; + Time offTime; + Time freeTime; + int lastPort; +} S3PortPrivRec, *S3PortPrivPtr; + + +typedef struct { + int bitsPerPixel; + int depth; + int displayWidth; + int pixel_code; + int pixel_bytes; + DisplayModePtr mode; +} S3FBLayout; + + +typedef struct _S3Rec { + pciVideoPtr PciInfo; + PCITAG PciTag; + EntityInfoPtr pEnt; + CARD32 IOAddress; + CARD32 FBAddress; + unsigned char * FBBase; + unsigned char * MMIOBase; + unsigned long videoRam; + OptionInfoPtr Options; + unsigned int Flags; + Bool NoAccel; + Bool S3NewMMIO; + Bool PCIRetry; + Bool ColorExpandBug; + + XAAInfoRecPtr pXAA; + xf86CursorInfoPtr pCurs; + xf86Int10InfoPtr pInt10; + vbeInfoPtr pVBE; + XF86VideoAdaptorPtr adaptor; + S3PortPrivPtr portPrivate; + + DGAModePtr DGAModes; + int numDGAModes; + Bool DGAactive; + int DGAViewportStatus; + + S3FBLayout CurrentLayout; + + RamDacHelperRecPtr RamDac; + RamDacRecPtr RamDacRec; + + int vgaCRIndex, vgaCRReg; + + int s3Bpp, s3BppDisplayWidth, HDisplay; + int mclk, MaxClock; + int pixMuxShift; + + int Chipset, ChipRev; + int RefClock; + + int s3ScissB, s3ScissR; + unsigned short BltDir; + int trans_color; + int FBCursorOffset; + + S3RegRec SavedRegs; + S3RegRec ModeRegs; + + unsigned char SAM256; + + void (*DacPreInit)(ScrnInfoPtr pScrn); + void (*DacInit)(ScrnInfoPtr pScrn, + DisplayModePtr mode); + void (*DacSave)(ScrnInfoPtr pScrn); + void (*DacRestore)(ScrnInfoPtr pScrn); + Bool (*CursorInit)(ScreenPtr pScreen); + + void (*LoadPalette)(ScrnInfoPtr pScrn, int numColors, + int *indicies, LOCO *colors, + VisualPtr pVisual); + + Bool (*CloseScreen)(int, ScreenPtr); + + unsigned char *imageBuffer; + int imageWidth; + int imageHeight; +} S3Rec, *S3Ptr; + +#define S3PTR(p) ((S3Ptr)((p)->driverPrivate)) + + +#define DRIVER_NAME "s3" +#define DRIVER_VERSION "0.3.4" +#define VERSION_MAJOR 0 +#define VERSION_MINOR 3 +#define PATCHLEVEL 4 +#define S3_VERSION ((VERSION_MAJOR << 24) | \ + (VERSION_MINOR << 16) | PATCHLEVEL) + + + + +/* + * Prototypes + */ + +Bool S3AccelInit(ScreenPtr pScreen); +Bool S3AccelInitNewMMIO(ScreenPtr pScreen); +Bool S3AccelInitPIO(ScreenPtr pScreen); +Bool S3DGAInit(ScreenPtr pScreen); +Bool S3SwitchMode(int scrnIndex, DisplayModePtr mode, int flags); +int S3GetRefClock(ScrnInfoPtr pScrn); + +void S3InitVideo(ScreenPtr pScreen); +void S3InitStreams(ScrnInfoPtr pScrn, DisplayModePtr mode); + +/* IBMRGB */ +extern RamDacSupportedInfoRec IBMRamdacs[]; +Bool S3ProbeIBMramdac(ScrnInfoPtr pScrn); +void S3IBMRGB_PreInit(ScrnInfoPtr pScrn); +void S3IBMRGB_Init(ScrnInfoPtr pScrn, DisplayModePtr mode); +void S3IBMRGB_Save(ScrnInfoPtr pScrn); +void S3IBMRGB_Restore(ScrnInfoPtr pScrn); +Bool S3IBMRGB_CursorInit(ScreenPtr pScreen); + +/* TRIO64 */ +Bool S3Trio64DACProbe(ScrnInfoPtr pScrn); +void S3Trio64DAC_PreInit(ScrnInfoPtr pScrn); +void S3Trio64DAC_Init(ScrnInfoPtr pScrn, DisplayModePtr mode); +void S3Trio64DAC_Save(ScrnInfoPtr pScrn); +void S3Trio64DAC_Restore(ScrnInfoPtr pScrn); + +/* Ti */ +Bool S3TiDACProbe(ScrnInfoPtr pScrn); +void S3TiDAC_PreInit(ScrnInfoPtr pScrn); +void S3TiDAC_Init(ScrnInfoPtr pScrn, DisplayModePtr mode); +void S3TiDAC_Save(ScrnInfoPtr pScrn); +void S3TiDAC_Restore(ScrnInfoPtr pScrn); +void S3TiLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies, LOCO *colors, + VisualPtr pVisual); +Bool S3Ti_CursorInit(ScreenPtr pScreen); +void S3OutTiIndReg(ScrnInfoPtr pScrn, CARD32 reg, unsigned char mask, + unsigned char data); + +/* s3 gen cursor */ +Bool S3_CursorInit(ScreenPtr pScreen); + +#define TRIO64_RAMDAC 0x8811 +#define TI3025_RAMDAC 0x3025 +#define TI3020_RAMDAC 0x3020 + +#define BIOS_BSIZE 1024 +#define BIOS_BASE 0xc0000 + +#endif /* _S3_H */ diff --git a/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_IBMRGB.c b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_IBMRGB.c new file mode 100644 index 000000000..798cc24d3 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_IBMRGB.c @@ -0,0 +1,551 @@ +/* + * Copyright 2001 Ani Joshi <ajoshi@unixbox.com> + * + * XFree86 4.x driver for S3 chipsets + * + * + * 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 Ani Joshi not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Ani Joshi makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ANI JOSHI 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. + * + * + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3/s3_IBMRGB.c,v 1.1 2001/07/02 10:46:04 alanh Exp $ */ + + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +#include "compiler.h" + +#include "IBM.h" + +#include "s3.h" + + +#define IBMRGB_WRITE_ADDR 0x3C8 /* CR55 low bit == 0 */ +#define IBMRGB_RAMDAC_DATA 0x3C9 /* CR55 low bit == 0 */ +#define IBMRGB_PIXEL_MASK 0x3C6 /* CR55 low bit == 0 */ +#define IBMRGB_READ_ADDR 0x3C7 /* CR55 low bit == 0 */ +#define IBMRGB_INDEX_LOW 0x3C8 /* CR55 low bit == 1 */ +#define IBMRGB_INDEX_HIGH 0x3C9 /* CR55 low bit == 1 */ +#define IBMRGB_INDEX_DATA 0x3C6 /* CR55 low bit == 1 */ +#define IBMRGB_INDEX_CONTROL 0x3C7 /* CR55 low bit == 1 */ + + +void S3OutIBMRGBIndReg(ScrnInfoPtr pScrn, CARD32 reg, + unsigned char mask, unsigned char data) +{ + S3Ptr pS3 = S3PTR(pScrn); + unsigned char tmp, tmp2 = 0x00; + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + + outb(vgaCRIndex, 0x55); + tmp = inb(vgaCRReg) & 0xfc; + outb(vgaCRReg, tmp | 0x01); + + outb(IBMRGB_INDEX_LOW, reg); + + if (mask != 0x00) + tmp2 = inb(IBMRGB_INDEX_DATA) & mask; + outb(IBMRGB_INDEX_DATA, tmp2 | data); + + outb(vgaCRIndex, 0x55); + outb(vgaCRReg, tmp); +} + + +unsigned char S3InIBMRGBIndReg(ScrnInfoPtr pScrn, CARD32 reg) +{ + S3Ptr pS3 = S3PTR(pScrn); + unsigned char tmp, ret; + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + + outb(vgaCRIndex, 0x55); + tmp = inb(vgaCRReg) & 0xfc; + outb(vgaCRReg, tmp | 0x01); + + outb(IBMRGB_INDEX_LOW, reg); + ret = inb(IBMRGB_INDEX_DATA); + + outb(vgaCRIndex, 0x55); + outb(vgaCRReg, tmp); + + return ret; +} + + +void S3IBMWriteAddress(ScrnInfoPtr pScrn, CARD32 index) +{ + outb(IBMRGB_WRITE_ADDR, index); +} + +void S3IBMWriteData(ScrnInfoPtr pScrn, unsigned char data) +{ + outb(IBMRGB_INDEX_DATA, data); +} + +void S3IBMReadAddress(ScrnInfoPtr pScrn, CARD32 index) +{ + outb(IBMRGB_READ_ADDR, index); +} + +unsigned char S3IBMReadData(ScrnInfoPtr pScrn) +{ + return inb(IBMRGB_RAMDAC_DATA); +} + + +Bool S3ProbeIBMramdac(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + + pS3->RamDacRec = RamDacCreateInfoRec(); + pS3->RamDacRec->ReadDAC = S3InIBMRGBIndReg; + pS3->RamDacRec->WriteDAC = S3OutIBMRGBIndReg; + pS3->RamDacRec->ReadAddress = S3IBMReadAddress; + pS3->RamDacRec->WriteAddress = S3IBMWriteAddress; + pS3->RamDacRec->ReadData = S3IBMReadData; + pS3->RamDacRec->WriteData = S3IBMWriteData; + pS3->RamDacRec->LoadPalette = NULL; + + if (!RamDacInit(pScrn, pS3->RamDacRec)) { + RamDacDestroyInfoRec(pS3->RamDacRec); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RamDacInit failed\n"); + return; + } + + pS3->RamDac = IBMramdacProbe(pScrn, IBMRamdacs); + if (pS3->RamDac) + return TRUE; + + return FALSE; +} + +void S3ProgramIBMRGBClock(ScrnInfoPtr pScrn, int clk, unsigned char m, + unsigned char n, unsigned char df) +{ + S3Ptr pS3 = S3PTR(pScrn); + RamDacHWRecPtr pIBM = RAMDACHWPTR(pScrn); + RamDacRegRecPtr ramdacReg = &pIBM->ModeReg; + int tmp = 1; + + S3OutIBMRGBIndReg(pScrn, IBMRGB_misc_clock, ~1, 1); + + S3OutIBMRGBIndReg(pScrn, IBMRGB_m0+2*clk, 0, (df<<6)|(m&0x3f)); + S3OutIBMRGBIndReg(pScrn, IBMRGB_n0+2*clk, 0, n); + + S3OutIBMRGBIndReg(pScrn, IBMRGB_pll_ctrl2, 0xf0, clk); + S3OutIBMRGBIndReg(pScrn, IBMRGB_pll_ctrl1, 0xf8, 3); +} + + +void S3IBMRGBSetClock(ScrnInfoPtr pScrn, long freq, int clk, long dacspeed, + long fref) +{ + volatile double ffreq, fdacspeed, ffref; + volatile int df, n, m, max_n, min_df; + volatile int best_m=69, best_n=17, best_df=0; + volatile double diff, mindiff; + +#define FREQ_MIN 16250 +#define FREQ_MAX dacspeed + + if (freq < FREQ_MIN) + ffreq = FREQ_MIN / 1000.0; + else if (freq > FREQ_MAX) + ffreq = FREQ_MAX / 1000.0; + else + ffreq = freq / 1000.0; + + fdacspeed = dacspeed / 1e3; + ffref = fref / 1e3; + + ffreq /= ffref; + ffreq *= 16; + mindiff = ffreq; + + if (freq <= dacspeed/4) + min_df = 0; + else if (freq <= dacspeed/2) + min_df = 1; + else + min_df = 2; + + for (df=0; df<4; df++) { + ffreq /= 2; + mindiff /= 2; + if (df < min_df) + continue; + + if (df < 3) + max_n = fref / 1000 / 2; + else + max_n = fref / 1000; + if (max_n > 31) + max_n = 31; + + for (n=2; n <= max_n; n++) { + m = (int)(ffreq * n + 0.5) - 65; + if (m < 0) + m = 0; + else if (m > 63) + m = 63; + diff = (m+65.0)/n-ffreq; + if (diff < 0) + diff = -diff; + if (diff < mindiff) { + mindiff = diff; + best_n = n; + best_m = m; + best_df = df; + } + } + } + + S3ProgramIBMRGBClock(pScrn, clk, best_m, best_n, best_df); +} + +void S3IBMRGB_Restore(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + S3RegPtr restore = &pS3->SavedRegs; + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + int i; + + for(i=0; i<0x100; i++) + S3OutIBMRGBIndReg(pScrn, i, 0, restore->dacregs[i]); + + outb(vgaCRIndex, 0x22); + outb(vgaCRReg, restore->dacregs[0x100]); +} + + +void S3IBMRGB_Save(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + S3RegPtr save = &pS3->SavedRegs; + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + int i; + + for (i=0; i<0x100; i++) + save->dacregs[i] = S3InIBMRGBIndReg(pScrn, i); + + outb(vgaCRIndex, 0x22); + save->dacregs[0x100] = inb(vgaCRReg); +} + + +void S3IBMRGB_PreInit(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + unsigned char cr55, tmp; + + outb(vgaCRIndex, 0x43); + tmp = inb(vgaCRReg); + outb(vgaCRReg, tmp & ~0x02); + + outb(vgaCRIndex, 0x55); + cr55 = inb(vgaCRReg); + outb(vgaCRReg, (cr55 & ~0x03) | 0x01); /* set rs2 */ + + tmp = inb(IBMRGB_INDEX_CONTROL); + outb(IBMRGB_INDEX_CONTROL, tmp & ~1); + outb(IBMRGB_INDEX_HIGH, 0); + + outb(vgaCRIndex, 0x55); + outb(vgaCRReg, cr55 & ~0x03); + + { + int m, n, df, mclk=0; + + m = S3InIBMRGBIndReg(pScrn, IBMRGB_sysclk_vco_div); + n = S3InIBMRGBIndReg(pScrn, IBMRGB_sysclk_ref_div) & 0x1f; + df = m >> 6; + m &= 0x3f; + if (!n) { + m = 0; + n = 1; + } + mclk = ((pS3->RefClock*100 * (m+65)) / n / (8 >> df) + 50) / 100; + pS3->mclk = mclk; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MCLK %1.3f MHz\n", + mclk / 1000.0); + } +} + + +void S3IBMRGB_Init(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + S3Ptr pS3 = S3PTR(pScrn); + S3RegPtr new = &pS3->ModeRegs; + RamDacHWRecPtr pIBM = RAMDACHWPTR(pScrn); + RamDacRegRecPtr ramdacReg = &pIBM->ModeReg; + unsigned long m=0,n=0,p=0,c=0; + unsigned long clock; + unsigned char tmp, cr55, blank; + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + + S3IBMRGBSetClock(pScrn, mode->Clock, 2, pS3->MaxClock, + pS3->RefClock); + + outb(0x3c4, 1); + blank = inb(0x3c5); + outb(0x3c5, blank | 0x20); + + S3OutIBMRGBIndReg(pScrn, IBMRGB_misc_clock, 0xf0, 0x03); + S3OutIBMRGBIndReg(pScrn, IBMRGB_sync, 0, 0); + S3OutIBMRGBIndReg(pScrn, IBMRGB_hsync_pos, 0, 0); + S3OutIBMRGBIndReg(pScrn, IBMRGB_pwr_mgmt, 0, 0); + S3OutIBMRGBIndReg(pScrn, IBMRGB_dac_op, ~8, 0); + S3OutIBMRGBIndReg(pScrn, IBMRGB_dac_op, ~2, 2); + S3OutIBMRGBIndReg(pScrn, IBMRGB_pal_ctrl, 0, 0); + S3OutIBMRGBIndReg(pScrn, IBMRGB_misc1, ~0x43, 1); + S3OutIBMRGBIndReg(pScrn, IBMRGB_misc2, 0, 0x47); + + outb(vgaCRIndex, 0x22); + tmp = inb(vgaCRReg); + if (pS3->s3Bpp == 1) + outb(vgaCRReg, tmp | 8); + else + outb(vgaCRReg, tmp & ~8); + + outb(vgaCRIndex, 0x65); + outb(vgaCRReg, 0x00); /* ! 528 */ + + outb(vgaCRIndex, 0x40); + outb(vgaCRReg, 0x11); + outb(vgaCRIndex, 0x55); + outb(vgaCRReg, 0x00); + + switch (pScrn->depth) { + case 8: + S3OutIBMRGBIndReg(pScrn, IBMRGB_pix_fmt, 0xf8, 3); + S3OutIBMRGBIndReg(pScrn, IBMRGB_8bpp, 0, 0); + break; + case 15: + S3OutIBMRGBIndReg(pScrn, IBMRGB_pix_fmt, 0xf8, 4); + S3OutIBMRGBIndReg(pScrn, IBMRGB_16bpp, 0, 0xc0); + break; + case 16: + S3OutIBMRGBIndReg(pScrn, IBMRGB_pix_fmt, 0xf8, 4); + S3OutIBMRGBIndReg(pScrn, IBMRGB_16bpp, 0, 0xc2); + break; + } + + outb(vgaCRIndex, 0x66); + tmp = inb(vgaCRReg) & 0xf8; + outb(vgaCRReg, tmp); + + outb(vgaCRIndex, 0x58); + tmp = (inb(vgaCRReg) & 0xbf) | 0x40; + outb(vgaCRReg, tmp); + + outb(vgaCRIndex, 0x67); + outb(vgaCRReg, 0x11); + + switch (pScrn->bitsPerPixel) { + case 8: + tmp = 0x21; + break; + case 16: + tmp = 0x10; + break; + } + outb(vgaCRIndex, 0x6d); + outb(vgaCRReg, tmp); + + outb(0x3c4, 1); + outb(0x3c5, blank); +} + + +/* hardware cursor */ + +static void S3IBMRGBSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + unsigned char tmp; + + /* unlock sys regs */ + outb(vgaCRIndex, 0x39); + outb(vgaCRReg, 0xa5); + + outb(vgaCRIndex, 0x55); + tmp = inb(vgaCRReg) & 0xfc; + outb(vgaCRReg, tmp | 0x01); + + outb(IBMRGB_INDEX_LOW, IBMRGB_curs_col1_r); + outb(IBMRGB_INDEX_DATA, (bg & 0x00ff0000) >> 16); + outb(IBMRGB_INDEX_LOW, IBMRGB_curs_col1_g); + outb(IBMRGB_INDEX_DATA, (bg & 0x0000ff00) >> 8); + outb(IBMRGB_INDEX_LOW, IBMRGB_curs_col1_b); + outb(IBMRGB_INDEX_DATA, (bg & 0x000000ff)); + outb(IBMRGB_INDEX_LOW, IBMRGB_curs_col2_r); + outb(IBMRGB_INDEX_DATA, (fg & 0x00ff0000) >> 16); + outb(IBMRGB_INDEX_LOW, IBMRGB_curs_col2_g); + outb(IBMRGB_INDEX_DATA, (fg & 0x0000ff00) >> 8); + outb(IBMRGB_INDEX_LOW, IBMRGB_curs_col2_b); + outb(IBMRGB_INDEX_DATA, (fg & 0x000000ff)); + + outb(vgaCRReg, tmp); +} + + +static void S3IBMRGBSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + unsigned char tmp; + + /* unlock sys regs */ + outb(vgaCRIndex, 0x39); + outb(vgaCRReg, 0xa5); + + outb(vgaCRIndex, 0x55); + tmp = inb(vgaCRReg) & 0xfc; + outb(vgaCRReg, tmp | 0x01); + + outb(IBMRGB_INDEX_LOW, IBMRGB_curs_xl); + outb(IBMRGB_INDEX_DATA, x); + outb(IBMRGB_INDEX_LOW, IBMRGB_curs_xh); + outb(IBMRGB_INDEX_DATA, x >> 8); + outb(IBMRGB_INDEX_LOW, IBMRGB_curs_yl); + outb(IBMRGB_INDEX_DATA, y); + outb(IBMRGB_INDEX_LOW, IBMRGB_curs_yh); + outb(IBMRGB_INDEX_DATA, y >> 8); + + outb(vgaCRReg, tmp); +} + + +static void S3IBMRGBHideCursor(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + + /* unlock sys regs */ + outb(vgaCRIndex, 0x39); + outb(vgaCRReg, 0xa5); + + S3OutIBMRGBIndReg(pScrn, IBMRGB_curs, ~3, 0x00); +} + + +static void S3IBMRGBShowCursor(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + unsigned char tmp; + + /* unlock sys regs */ + outb(vgaCRIndex, 0x39); + outb(vgaCRReg, 0xa5); + + outb(vgaCRIndex, 0x55); + tmp = (inb(vgaCRReg) & 0xdf) | 0x20; + outb(vgaCRReg, tmp); + + outb(vgaCRIndex, 0x45); + tmp = inb(vgaCRReg) & ~0x20; + outb(vgaCRReg, tmp); + + S3OutIBMRGBIndReg(pScrn, IBMRGB_curs, 0, 0x27); +} + + +static void S3IBMRGBLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + unsigned char tmp, tmp2; + register int i; + + /* unlock sys regs */ + outb(vgaCRIndex, 0x39); + outb(vgaCRReg, 0xa5); + + outb(vgaCRIndex, 0x55); + tmp = inb(vgaCRReg) & 0xfc; + outb(vgaCRReg, tmp | 0x01); + + outb(IBMRGB_INDEX_LOW, IBMRGB_curs_hot_x); + outb(IBMRGB_INDEX_DATA, 0); + outb(IBMRGB_INDEX_LOW, IBMRGB_curs_hot_y); + outb(IBMRGB_INDEX_DATA, 0); + outb(IBMRGB_INDEX_LOW, IBMRGB_curs_xl); + outb(IBMRGB_INDEX_DATA, 0xff); + outb(IBMRGB_INDEX_LOW, IBMRGB_curs_xh); + outb(IBMRGB_INDEX_DATA, 0x7f); + outb(IBMRGB_INDEX_LOW, IBMRGB_curs_yl); + outb(IBMRGB_INDEX_DATA, 0xff); + outb(IBMRGB_INDEX_LOW, IBMRGB_curs_yh); + outb(IBMRGB_INDEX_DATA, 0x7f); + + tmp2 = inb(IBMRGB_INDEX_CONTROL) & 0xfe; + outb(IBMRGB_INDEX_CONTROL, tmp2 | 1); /* enable auto increment */ + + outb(IBMRGB_INDEX_HIGH, (unsigned char) (IBMRGB_curs_array >> 8)); + outb(IBMRGB_INDEX_LOW, (unsigned char) (IBMRGB_curs_array)); + + for (i=0; i<1024; i++) + outb(IBMRGB_INDEX_DATA, *image++); + + outb(IBMRGB_INDEX_HIGH, 0); + outb(IBMRGB_INDEX_CONTROL, tmp2); /* disable auto increment */ + outb(vgaCRIndex, 0x55); + outb(vgaCRReg, tmp); +} + + +static Bool S3IBMRGBUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) +{ + return TRUE; +} + + +Bool S3IBMRGB_CursorInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + S3Ptr pS3 = S3PTR(pScrn); + xf86CursorInfoPtr pCurs; + + if (!(pCurs = pS3->pCurs = xf86CreateCursorInfoRec())) + return FALSE; + + pCurs->MaxWidth = 64; + pCurs->MaxHeight = 64; + pCurs->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | + HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | + HARDWARE_CURSOR_NIBBLE_SWAPPED | + HARDWARE_CURSOR_BIT_ORDER_MSBFIRST; + + pCurs->SetCursorColors = S3IBMRGBSetCursorColors; + pCurs->SetCursorPosition = S3IBMRGBSetCursorPosition; + pCurs->LoadCursorImage = S3IBMRGBLoadCursorImage; + pCurs->HideCursor = S3IBMRGBHideCursor; + pCurs->ShowCursor = S3IBMRGBShowCursor; + pCurs->UseHWCursor = S3IBMRGBUseHWCursor; + + return xf86InitCursor(pScreen, pCurs); +} + + diff --git a/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_Ti.c b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_Ti.c new file mode 100644 index 000000000..8e6b7e6b7 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_Ti.c @@ -0,0 +1,754 @@ +/* + * Copyright 2001 Ani Joshi <ajoshi@unixbox.com> + * + * XFree86 4.x driver for S3 chipsets + * + * + * 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 Ani Joshi not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Ani Joshi makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ANI JOSHI 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. + * + * + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3/s3_Ti.c,v 1.1 2001/07/02 10:46:04 alanh Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +#include "compiler.h" + +#include "TI.h" + +#include "s3.h" + + +#define TI_WRITE_ADDR 0x3C8 /* CR55 low bit == 0 */ +#define TI_RAMDAC_DATA 0x3C9 /* CR55 low bit == 0 */ +#define TI_PIXEL_MASK 0x3C6 /* CR55 low bit == 0 */ +#define TI_READ_ADDR 0x3C7 /* CR55 low bit == 0 */ +#define TI_INDEX_REG 0x3C6 /* CR55 low bit == 1 */ +#define TI_DATA_REG 0x3C7 /* CR55 low bit == 1 */ + +#define TIDAC_output_clock_select 0x1b +#define TIDAC_auxiliary_ctrl 0x29 +#define TIDAC_general_io_ctrl 0x2a +#define TIDAC_general_io_data 0x2b +#define TIDAC_cursor_color_0_red 0x23 +#define TIDAC_cursor_color_0_green 0x24 +#define TIDAC_cursor_color_0_blue 0x25 +#define TIDAC_cursor_color_1_red 0x26 +#define TIDAC_cursor_color_1_green 0x27 +#define TIDAC_cursor_color_1_blue 0x28 +#define TIDAC_cursor_x_low 0x00 +#define TIDAC_cursor_x_high 0x01 +#define TIDAC_cursor_y_low 0x02 +#define TIDAC_cursor_y_high 0x03 +#define TIDAC_cursor_ram_addr_low 0x08 +#define TIDAC_cursor_ram_addr_high 0x09 +#define TIDAC_cursor_ram_data 0x0a + + +#define TI_REF_FREQ 14.31818 /* 3025 only */ + +#undef FREQ_MIN +#define FREQ_MIN 12000 +#define FREQ_MAX 220000 + + + +void S3OutTiIndReg(ScrnInfoPtr pScrn, CARD32 reg, unsigned char mask, + unsigned char data) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + unsigned char tmp, tmp1, tmp2 = 0x00; + + outb(vgaCRIndex, 0x55); + tmp = inb(vgaCRReg) & 0xfc; + outb(vgaCRReg, tmp | 0x01); + tmp1 = inb(TI_INDEX_REG); + outb(TI_INDEX_REG, reg); + + if (mask != 0x00) + tmp2 = inb(TI_DATA_REG) & mask; + outb(TI_DATA_REG, tmp2 | data); + + outb(TI_INDEX_REG, tmp1); + outb(vgaCRReg, tmp); +} + + +unsigned char S3InTiIndReg(ScrnInfoPtr pScrn, CARD32 reg) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + unsigned char tmp, tmp1, ret; + + outb(vgaCRIndex, 0x55); + tmp = inb(vgaCRReg) & 0xfc; + outb(vgaCRReg, tmp | 0x01); + tmp1 = inb(TI_INDEX_REG); + outb(TI_INDEX_REG, reg); + + ret = inb(TI_DATA_REG); + + outb(TI_INDEX_REG, tmp1); + outb(vgaCRReg, tmp); + + return ret; +} + + +Bool S3TiDACProbe(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + int found = 0; + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + unsigned char cr55, cr45, cr43, cr5c; + unsigned char TIndx, TIndx2, TIdata; + + if ((pS3->Chipset != PCI_CHIP_964_0) && + (pS3->Chipset != PCI_CHIP_964_1)) + return FALSE; + + outb(vgaCRIndex, 0x43); + cr43 = inb(vgaCRReg); + outb(vgaCRReg, cr43 & ~0x02); + + outb(vgaCRIndex, 0x55); + cr55 = inb(vgaCRReg); + + outb(vgaCRReg, (cr55 & 0xfc) | 0x01); + + TIndx = inb(TI_INDEX_REG); + outb(TI_INDEX_REG, TIDAC_id); + if(inb(TI_DATA_REG) == 0x20) { + found = TI3020_RAMDAC; + cr43 &= ~0x02; + cr45 &= ~0x20; + } else { + outb(vgaCRIndex, 0x5c); + cr5c = inb(vgaCRReg); + outb(vgaCRReg, cr5c & 0xdf); + TIndx2 = inb(TI_INDEX_REG); + outb(TI_INDEX_REG, TIDAC_ind_curs_ctrl); + TIdata = inb(TI_DATA_REG); + outb(TI_DATA_REG, TIdata & 0x7f); + + outb(TI_INDEX_REG, TIDAC_id); + if (inb(TI_DATA_REG) == 0x25) { + found = TI3025_RAMDAC; + cr43 &= ~0x02; + cr45 &= ~0x20; + } + + outb(TI_INDEX_REG, TIDAC_ind_curs_ctrl); + outb(TI_DATA_REG, TIdata); + outb(TI_INDEX_REG, TIndx2); + outb(vgaCRIndex, 0x5c); + outb(vgaCRReg, cr5c); + } + + outb(TI_INDEX_REG, TIndx); + outb(vgaCRIndex, 0x55); + outb(vgaCRReg, cr55); + + outb(vgaCRIndex, 0x45); + outb(vgaCRReg, cr45); + + outb(vgaCRIndex, 0x43); + outb(vgaCRReg, cr43); + + if (found) { + RamDacInit(pScrn, pS3->RamDacRec); + pS3->RamDac = RamDacHelperCreateInfoRec(); + pS3->RamDac->RamDacType = found; + return TRUE; + } + + return FALSE; +} + + +void S3TiDAC_Save(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + S3RegPtr save = &pS3->SavedRegs; + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + + if (pS3->RamDac->RamDacType == TI3025_RAMDAC) { + unsigned char cr5c; + + outb(vgaCRIndex, 0x5c); + cr5c = inb(vgaCRReg); + outb(vgaCRReg, cr5c & 0xdf); + + save->dacregs[TIDAC_ind_curs_ctrl] = + S3InTiIndReg(pScrn, TIDAC_ind_curs_ctrl); + S3OutTiIndReg(pScrn, TIDAC_ind_curs_ctrl, 0x7f, 0x00); + } + + save->dacregs[TIDAC_true_color_ctrl] = + S3InTiIndReg(pScrn, TIDAC_true_color_ctrl); + save->dacregs[TIDAC_multiplex_ctrl] = + S3InTiIndReg(pScrn, TIDAC_multiplex_ctrl); + save->dacregs[TIDAC_clock_select] = + S3InTiIndReg(pScrn, TIDAC_clock_select); + save->dacregs[TIDAC_output_clock_select] = + S3InTiIndReg(pScrn, TIDAC_output_clock_select); + save->dacregs[TIDAC_general_ctrl] = + S3InTiIndReg(pScrn, TIDAC_general_ctrl); + save->dacregs[TIDAC_auxiliary_ctrl] = + S3InTiIndReg(pScrn, TIDAC_auxiliary_ctrl); + S3OutTiIndReg(pScrn, TIDAC_general_io_ctrl, 0x00, 0x1f); + save->dacregs[TIDAC_general_io_data] = + S3InTiIndReg(pScrn, TIDAC_general_io_data); + + if (pS3->RamDac->RamDacType == TI3025_RAMDAC) { + save->dacregs[0x0e] = S3InTiIndReg(pScrn, 0x0e); + save->dacregs[TIDAC_misc_ctrl] = + S3InTiIndReg(pScrn, TIDAC_misc_ctrl); + S3OutTiIndReg(pScrn, TIDAC_pll_addr, 0x00, 0x00); + save->dacregs[0x40] = S3InTiIndReg(pScrn, TIDAC_pll_pixel_data); + S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00, + save->dacregs[0x40]); + save->dacregs[0x41] = S3InTiIndReg(pScrn, TIDAC_pll_pixel_data); + S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00, + save->dacregs[0x41]); + save->dacregs[0x42] = S3InTiIndReg(pScrn, TIDAC_pll_pixel_data); + S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00, + save->dacregs[0x42]); + save->dacregs[0x43] = S3InTiIndReg(pScrn, TIDAC_pll_memory_data); + S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00, + save->dacregs[0x43]); + save->dacregs[0x44] = S3InTiIndReg(pScrn, TIDAC_pll_memory_data); + S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00, + save->dacregs[0x44]); + save->dacregs[0x45] = S3InTiIndReg(pScrn, TIDAC_pll_memory_data); + S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00, + save->dacregs[0x45]); + save->dacregs[0x46] = S3InTiIndReg(pScrn, TIDAC_pll_loop_data); + S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00, + save->dacregs[0x46]); + save->dacregs[0x47] = S3InTiIndReg(pScrn, TIDAC_pll_loop_data); + S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00, + save->dacregs[0x47]); + save->dacregs[0x48] = S3InTiIndReg(pScrn, TIDAC_pll_loop_data); + S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00, + save->dacregs[0x48]); + } +} + + +void S3TiDAC_Restore(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + S3RegPtr restore = &pS3->SavedRegs; + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + + S3OutTiIndReg(pScrn, TIDAC_multiplex_ctrl, 0x00, + restore->dacregs[TIDAC_true_color_ctrl]); + S3OutTiIndReg(pScrn, TIDAC_clock_select, 0x00, + restore->dacregs[TIDAC_multiplex_ctrl]); + S3OutTiIndReg(pScrn, TIDAC_clock_select, 0x00, + restore->dacregs[TIDAC_clock_select]); + S3OutTiIndReg(pScrn, TIDAC_output_clock_select, 0x00, + restore->dacregs[TIDAC_output_clock_select]); + S3OutTiIndReg(pScrn, TIDAC_general_ctrl, 0x00, + restore->dacregs[TIDAC_general_ctrl]); + S3OutTiIndReg(pScrn, TIDAC_auxiliary_ctrl, 0x00, + restore->dacregs[TIDAC_auxiliary_ctrl]); + S3OutTiIndReg(pScrn, TIDAC_general_io_ctrl, 0x00, 0x1f); + S3OutTiIndReg(pScrn, TIDAC_general_io_data, 0x00, + restore->dacregs[TIDAC_general_io_data]); + if (pS3->RamDac->RamDacType == TI3025_RAMDAC) { + S3OutTiIndReg(pScrn, TIDAC_pll_addr, 0x00, + restore->dacregs[TIDAC_pll_addr]); + S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00, + restore->dacregs[0x40]); + S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00, + restore->dacregs[0x41]); + S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00, + restore->dacregs[0x42]); + + S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00, + restore->dacregs[0x43]); + S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00, + restore->dacregs[0x44]); + S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00, + restore->dacregs[0x45] | 0x80); + + S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00, + restore->dacregs[0x46]); + S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00, + restore->dacregs[0x47]); + S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00, + restore->dacregs[0x48]); + + S3OutTiIndReg(pScrn, 0x0e, 0x00, restore->dacregs[0x0e]); + S3OutTiIndReg(pScrn, TIDAC_misc_ctrl, 0x00, + restore->dacregs[TIDAC_misc_ctrl]); + } + + S3OutTiIndReg(pScrn, TIDAC_ind_curs_ctrl, 0x00, + restore->dacregs[TIDAC_ind_curs_ctrl]); +} + + +void S3TiDAC_PreInit(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + int mclk, m, n, p, mcc, cr5c; + + outb(vgaCRIndex, 0x5c); + cr5c = inb(vgaCRReg); + outb(vgaCRReg, cr5c & 0xdf); + + S3OutTiIndReg(pScrn, TIDAC_pll_addr, 0x00, 0x00); + n = S3InTiIndReg(pScrn, TIDAC_pll_memory_data) & 0x7f; + S3OutTiIndReg(pScrn, TIDAC_pll_addr, 0x00, 0x01); + m = S3InTiIndReg(pScrn, TIDAC_pll_memory_data) & 0x7f; + S3OutTiIndReg(pScrn, TIDAC_pll_addr, 0x00, 0x02); + p = S3InTiIndReg(pScrn, TIDAC_pll_memory_data) & 0x03; + mcc = S3InTiIndReg(pScrn, TIDAC_clock_ctrl); + if (mcc & 0x08) + mcc = (mcc & 0x07) * 2 + 2; + else + mcc = 1; + + mclk = ((1431818 * ((m+2) * 8)) / (n+2) / (1 << p) / mcc + 50) / 100; + pS3->mclk = mclk; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MCLK %1.3f MHz\n", + mclk / 1000.0); + + outb(vgaCRIndex, 0x5c); + outb(vgaCRReg, cr5c); +} + + +static void S3TiDACCalcNMP(long freq, int *calc_n, int *calc_m, int *calc_p) +{ + double ffreq; + int n, m, p; + int best_n=32, best_m=32; + double diff, mindiff; + + if (freq < FREQ_MIN) + ffreq = FREQ_MIN / 1000.0; + else if (freq > FREQ_MAX) + ffreq = FREQ_MAX / 1000.0; + else + ffreq = freq / 1000.0; + + for (p=0; p<4 && ffreq<110.0; p++) + ffreq *= 2; +#if FREQ_MIN < 110000/8 + if (p == 4) { + ffreq /= 2; + p--; + } +#endif + + ffreq /= TI_REF_FREQ; + + mindiff = ffreq; + + for (n=1; n<=(int)(TI_REF_FREQ/0.5 - 2); n++) { + m = (int)(ffreq * (n+2) / 8.0 + 0.5) - 2; + if (m < 1) + m = 1; + else if (m > 127) + m = 127; + + diff = ((m+2) * 8) / (n+2.0) - ffreq; + if (diff < 0) + diff = -diff; + + if (diff < mindiff) { + mindiff = diff; + best_n = n; + best_m = m; + } + } + + *calc_n = best_n; + *calc_m = best_m; + *calc_p = p; +} + + +static void S3TiDACProgramClock(ScrnInfoPtr pScrn, int clk, + unsigned char n, unsigned char m, + unsigned char p) +{ + S3OutTiIndReg(pScrn, TIDAC_pll_addr, 0x00, 0x00); + + if (clk != TIDAC_pll_memory_data) { + S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00, n); + S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00, m); + S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00, p | 0x08); + + S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00, 0x01); + S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00, 0x01); + S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00, p > 0 ? p : 1); + S3OutTiIndReg(pScrn, TIDAC_misc_ctrl, 0x00, 0x80 | 0x40 | 0x04); + + S3OutTiIndReg(pScrn, TIDAC_clock_select, 0x00, 0x05); + } else { + S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00, n); + S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00, m); + S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00, p | 0x80); + } +} + + +void S3TiDACSetClock(ScrnInfoPtr pScrn, long freq, int clk) +{ + int m, n, p; + + S3TiDACCalcNMP(freq, &n, &m, &p); + + S3TiDACProgramClock(pScrn, clk, n, m, p); +} + + + +void S3TiDAC_Init(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + S3Ptr pS3 = S3PTR(pScrn); + S3RegPtr new = &pS3->ModeRegs; + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr pVga = &hwp->ModeReg; + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + unsigned char tmp, tmp1, tmp2; + + S3TiDACSetClock(pScrn, mode->Clock, 2); + outb(vgaCRIndex, 0x42); + tmp = inb(vgaCRReg) & 0xf0; + outb(vgaCRReg, tmp | 0x02); + usleep(150000); + + outb(0x3c4, 1); + tmp2 = inb(0x3c5); + outb(0x3c5, tmp2 | 0x20); /* blank */ + + tmp = pVga->MiscOutReg; + pVga->MiscOutReg |= 0xc0; + tmp1 = 0x00; + if (!(tmp & 0x80)) + tmp1 |= 0x02; + if (!(tmp & 0x40)) + tmp1 |= 0x01; + + S3OutTiIndReg(pScrn, TIDAC_general_ctrl, 0x00, tmp1); + S3OutTiIndReg(pScrn, 0x0e, 0x00, 0x00); + + /* XXX do 3020 input_clock_sel */ + + outb(vgaCRIndex, 0x65); + /* XXX 3025 */ + outb(vgaCRReg, 0x00); + + /* XXX 3025 */ + outb(vgaCRIndex, 0x40); + outb(vgaCRReg, 0x11); + outb(vgaCRIndex, 0x55); + outb(vgaCRReg, 0x00); + + if (pScrn->bitsPerPixel > 8) + S3OutTiIndReg(pScrn, TIDAC_auxiliary_ctrl, 0x00, 0x00); + else + S3OutTiIndReg(pScrn, TIDAC_auxiliary_ctrl, 0x00, 0x01); + + switch (pScrn->depth) { + case 8: + S3OutTiIndReg(pScrn, TIDAC_output_clock_select, 0x00, + 0x4b); + outb(vgaCRIndex, 0x66); + tmp = inb(vgaCRReg); + if (mode->Clock > 80000) + outb(vgaCRReg, (tmp & 0xf8) | 0x02); + else + outb(vgaCRReg, (tmp & 0xf8) | 0x03); + break; + case 16: + S3OutTiIndReg(pScrn, TIDAC_output_clock_select, 0x00, + 0x4a); + outb(vgaCRIndex, 0x66); + tmp = inb(vgaCRReg); + if (mode->Clock > 80000) + outb(vgaCRReg, (tmp & 0xf8) | 0x01); + else + outb(vgaCRReg, (tmp & 0xf8) | 0x02); + break; + case 24: + S3OutTiIndReg(pScrn, TIDAC_output_clock_select, 0x00, + (0x40 | 0x08 | 0x01)); + outb(vgaCRIndex, 0x66); + tmp = inb(vgaCRReg); + if (mode->Clock > 80000) + outb(vgaCRReg, (tmp & 0xf8) | 0x00); + else + outb(vgaCRReg, (tmp & 0xf8) | 0x01); + break; + } + + outb(vgaCRIndex, 0x58); + tmp = inb(vgaCRReg); + outb(vgaCRReg, (tmp & 0xbf) | 0x40); + + switch(pScrn->depth) { + case 8: + S3OutTiIndReg(pScrn, TIDAC_true_color_ctrl, 0x00, 0x80); + S3OutTiIndReg(pScrn, TIDAC_multiplex_ctrl, 0x00, 0x1c); + break; + case 15: + S3OutTiIndReg(pScrn, TIDAC_true_color_ctrl, 0x00, 0x4c); + S3OutTiIndReg(pScrn, TIDAC_multiplex_ctrl, 0x00, 0x04); + S3OutTiIndReg(pScrn, TIDAC_key_ctrl, 0x00, 0x01); + break; + case 16: + S3OutTiIndReg(pScrn, TIDAC_true_color_ctrl, 0x00, 0x4d); + S3OutTiIndReg(pScrn, TIDAC_multiplex_ctrl, 0x00, 0x04); + S3OutTiIndReg(pScrn, TIDAC_key_ctrl, 0x00, 0x01); + break; + case 24: + S3OutTiIndReg(pScrn, TIDAC_true_color_ctrl, 0x00, 0x4e); + S3OutTiIndReg(pScrn, TIDAC_multiplex_ctrl, 0x00, 0x04); + S3OutTiIndReg(pScrn, TIDAC_key_ctrl, 0x00, 0x01); + break; + } + + S3OutTiIndReg(pScrn, TIDAC_general_io_ctrl, 0x00, 0x1f); + S3OutTiIndReg(pScrn, TIDAC_general_io_data, 0x00, 0x01); + S3OutTiIndReg(pScrn, TIDAC_general_io_ctrl, 0x00, 0x00); + S3OutTiIndReg(pScrn, TIDAC_misc_ctrl, 0xf0, (0x04 | 0x08)); + + outb(vgaCRIndex, 0x6d); + if (pS3->s3Bpp == 1) + if (mode->Clock > 80000) + outb(vgaCRReg, 0x02); + else + outb(vgaCRReg, 0x03); + else if (pS3->s3Bpp == 2) + if (mode->Clock > 80000) + outb(vgaCRReg, 0x00); + else + outb(vgaCRReg, 0x01); + else + outb(vgaCRReg, 0x00); + + S3OutTiIndReg(pScrn, TIDAC_sense_test, 0x00, 0x00); + + + if (pS3->s3Bpp > 1) + { + int j; + + outb(0x3c6, 0xff); + outb(0x3c8, 0x00); + for(j=0; j<768; j++) { + outb(0x3c9, j); + outb(0x3c9, j); + outb(0x3c9, j); + } + } + + outb(0x3c4, 1); + outb(0x3c5, tmp2); /* unblank */ +} + + +void S3TiLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies, LOCO *colors, + VisualPtr pVisual) +{ + int i; + + outb(0x3c6, 0xff); + outb(0x3c8, 0x00); + + for (i=0; i<768; i++) { + outb(0x3c9, i); + usleep(1000); + outb(0x3c9, i); + usleep(1000); + outb(0x3c9, i); + usleep(1000); + } +} + + + +/* hardware cursor */ + +static void S3TiSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + unsigned char tmp; + + /* unlock sys regs */ + outb(vgaCRIndex, 0x39); + outb(vgaCRReg, 0xa5); + + S3OutTiIndReg(pScrn, TIDAC_cursor_color_0_red, 0x00, + (bg & 0x00FF0000) >> 16); + S3OutTiIndReg(pScrn, TIDAC_cursor_color_0_green, 0x00, + (bg & 0x0000FF00) >> 8); + S3OutTiIndReg(pScrn, TIDAC_cursor_color_0_blue, 0x00, + (bg & 0x000000FF)); + + S3OutTiIndReg(pScrn, TIDAC_cursor_color_1_red, 0x00, + (fg & 0x00FF0000) >> 16); + S3OutTiIndReg(pScrn, TIDAC_cursor_color_1_green, 0x00, + (fg & 0x0000FF00) >> 8); + S3OutTiIndReg(pScrn, TIDAC_cursor_color_1_blue, 0x00, + (fg & 0x000000FF)); + +} + + +static void S3TiSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + + /* unlock sys regs */ + outb(vgaCRIndex, 0x39); + outb(vgaCRReg, 0xa5); + + S3OutTiIndReg(pScrn, TIDAC_cursor_x_low, 0x00, x & 0xff); + S3OutTiIndReg(pScrn, TIDAC_cursor_x_high, 0x00, (x >> 8) & 0x0f); + S3OutTiIndReg(pScrn, TIDAC_cursor_y_low, 0x00, y & 0xff); + S3OutTiIndReg(pScrn, TIDAC_cursor_y_high, 0x00, (y >> 8) & 0x0f); +} + + +static void S3TiHideCursor(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + + /* unlock sys regs */ + outb(vgaCRIndex, 0x39); + outb(vgaCRReg, 0xa5); + + S3OutTiIndReg(pScrn, TIDAC_ind_curs_ctrl, (unsigned char) + ~(0x40 | 0x10), 0x00); +} + + +static void S3TiShowCursor(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + unsigned char tmp; + + /* unlock sys regs */ + outb(vgaCRIndex, 0x39); + outb(vgaCRReg, 0xa5); + + outb(vgaCRIndex, 0x55); + tmp = inb(vgaCRReg) & 0xdf; + outb(vgaCRReg, tmp | 0x20); + + outb(vgaCRIndex, 0x45); + tmp = inb(vgaCRReg) & 0xdf; + outb(vgaCRReg, tmp | 0x20); + + S3OutTiIndReg(pScrn, TIDAC_ind_curs_ctrl, (unsigned char) + ~(0x40 | 0x10), (0x40 | 0x10)); +} + + +static void S3TiLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + unsigned char tmp, tmp1; + register int i; + register unsigned char *mask = image + 1; + + /* unlock sys regs */ + outb(vgaCRIndex, 0x39); + outb(vgaCRReg, 0xa5); + + outb(vgaCRIndex, 0x55); + tmp = inb(vgaCRReg) & 0xfc; + outb(vgaCRReg, tmp | 0x01); + tmp1 = inb(TI_INDEX_REG); + + outb(TI_INDEX_REG, TIDAC_cursor_ram_addr_low); + outb(TI_DATA_REG, 0x00); + outb(TI_INDEX_REG, TIDAC_cursor_ram_addr_high); + outb(TI_DATA_REG, 0x00); + outb(TI_INDEX_REG, TIDAC_cursor_ram_data); + +#if 0 + for (i=0; i<512; i++, mask+=2) + outb(TI_DATA_REG, *mask); + for (i=0; i<512; i++, image+=2) + outb(TI_DATA_REG, *image); +#else + for (i=0; i<1024; i++) { + outb(TI_DATA_REG, *image); + image++; + } +#endif + + outb(TI_INDEX_REG, tmp1); + + outb(vgaCRIndex, 0x55); + outb(vgaCRReg, tmp); +} + + + +static Bool S3TiUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) +{ + return TRUE; +} + + + +Bool S3Ti_CursorInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + S3Ptr pS3 = S3PTR(pScrn); + xf86CursorInfoPtr pCurs; + + if (!(pCurs = pS3->pCurs = xf86CreateCursorInfoRec())) + return FALSE; + + pCurs->MaxWidth = 64; + pCurs->MaxHeight = 64; + pCurs->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | + HARDWARE_CURSOR_NIBBLE_SWAPPED | + HARDWARE_CURSOR_BIT_ORDER_MSBFIRST; + + pCurs->SetCursorColors = S3TiSetCursorColors; + pCurs->SetCursorPosition = S3TiSetCursorPosition; + pCurs->LoadCursorImage = S3TiLoadCursorImage; + pCurs->HideCursor = S3TiHideCursor; + pCurs->ShowCursor = S3TiShowCursor; + pCurs->UseHWCursor = S3TiUseHWCursor; + + return xf86InitCursor(pScreen, pCurs); +} diff --git a/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_Trio64DAC.c b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_Trio64DAC.c new file mode 100644 index 000000000..e4d94332b --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_Trio64DAC.c @@ -0,0 +1,354 @@ +/* + * Copyright 2001 Ani Joshi <ajoshi@unixbox.com> + * + * XFree86 4.x driver for S3 chipsets + * + * + * 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 Ani Joshi not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Ani Joshi makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ANI JOSHI 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. + * + * + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3/s3_Trio64DAC.c,v 1.1 2001/07/02 10:46:04 alanh Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +#include "compiler.h" + +#include "s3.h" + +/* this is really quite dumb */ +Bool S3Trio64DACProbe(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + + if (pS3->Chipset != PCI_CHIP_TRIO) + return FALSE; + + RamDacInit(pScrn, pS3->RamDacRec); + + pS3->RamDac = RamDacHelperCreateInfoRec(); + pS3->RamDac->RamDacType = TRIO64_RAMDAC; + + return TRUE; +} + + +void S3Trio64DAC_Save(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + S3RegPtr save = &pS3->SavedRegs; + + outb(0x3c4, 0x08); + save->dacregs[1] = inb(0x3c5); + outb(0x3c5, 0x06); + + outb(0x3c4, 0x09); + save->dacregs[2] = inb(0x3c5); + outb(0x3c4, 0x0a); + save->dacregs[3] = inb(0x3c5); + outb(0x3c4, 0x0b); + save->dacregs[4] = inb(0x3c5); + outb(0x3c4, 0x0d); + save->dacregs[5] = inb(0x3c5); + outb(0x3c4, 0x15); + save->dacregs[6] = inb(0x3c5) & 0xfe; + + outb(0x3c4, 0x18); + save->dacregs[7] = inb(0x3c5); + outb(0x3c4, 0x10); + save->dacregs[8] = inb(0x3c5); + outb(0x3c4, 0x11); + save->dacregs[9] = inb(0x3c5); + outb(0x3c4, 0x12); + save->dacregs[10] = inb(0x3c5); + outb(0x3c4, 0x13); + save->dacregs[11] = inb(0x3c5); + outb(0x3c4, 0x1a); + save->dacregs[12] = inb(0x3c5); + outb(0x3c4, 0x1b); + save->dacregs[13] = inb(0x3c5); + + outb(0x3c4, 0x08); + outb(0x3c5, 0x00); +} + + +void S3Trio64DAC_Restore(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + S3RegPtr restore = &pS3->SavedRegs; + unsigned char tmp; + + outb(0x3c2, restore->dacregs[0]); + outb(0x3c4, 0x08); + outb(0x3c5, 0x06); + + outb(0x3c4, 0x09); + outb(0x3c5, restore->dacregs[2]); + outb(0x3c4, 0x0a); + outb(0x3c5, restore->dacregs[3]); + outb(0x3c4, 0x0b); + outb(0x3c5, restore->dacregs[4]); + outb(0x3c4, 0x0d); + outb(0x3c5, restore->dacregs[5]); + + outb(0x3c4, 0x10); + outb(0x3c5, restore->dacregs[8]); + outb(0x3c4, 0x11); + outb(0x3c5, restore->dacregs[9]); + outb(0x3c4, 0x12); + outb(0x3c5, restore->dacregs[10]); + outb(0x3c4, 0x13); + outb(0x3c5, restore->dacregs[11]); + outb(0x3c4, 0x1a); + outb(0x3c5, restore->dacregs[12]); + outb(0x3c4, 0x01b); + outb(0x3c5, restore->dacregs[13]); + outb(0x3c4, 0x15); + tmp = inb(0x3c5); + outb(0x3c4, tmp & ~0x20); + outb(0x3c4, tmp | 0x20); + outb(0x3c4, tmp & ~0x20); + + outb(0x3c4, 0x15); + outb(0x3c5, restore->dacregs[6]); + outb(0x3c4, 0x18); + outb(0x3c5, restore->dacregs[7]); + + outb(0x3c4, 0x08); + outb(0x3c5, restore->dacregs[1]); +} + + +int S3TrioCalcClock(long freq, int min_m, int min_n1, int max_n1, int min_n2, + int max_n2, long freq_min, long freq_max, + unsigned char *mdiv, unsigned char *ndiv) +{ + double ffreq, ffreq_min, ffreq_max; + double div, diff, best_diff; + unsigned int m; + unsigned char n1, n2, best_n1=18, best_n2=2, best_m=127; + +#define BASE_FREQ 14.31818 + ffreq = freq / 1000.0 / BASE_FREQ; + ffreq_min = freq_min / 1000.0 / BASE_FREQ; + ffreq_max = freq_max / 1000.0 / BASE_FREQ; + + if (ffreq < ffreq_min / (1<<max_n2)) { + ErrorF("invalid frequency %1.3f Mhz [freq >= %1.3f Mhz]\n", + ffreq*BASE_FREQ, ffreq_min*BASE_FREQ/(1<<max_n2)); + ffreq = ffreq_min / (1<<max_n2); + } + if (ffreq > ffreq_max / (1<<min_n2)) { + ErrorF("invalid frequency %1.3F Mhz [freq <= %1.3f Mhz]\n", + ffreq*BASE_FREQ, ffreq_max*BASE_FREQ/(1<<min_n2)); + ffreq = ffreq_max / (1<<min_n2); + } + + best_diff = ffreq; + + for(n2=min_n2; n2<=max_n2; n2++) { + for(n1=min_n1+2; n1<=max_n1+2; n1++) { + m = (int)(ffreq*n1*(1<<n2)+0.5); + if (m<min_m+2 || m > 127+2) + continue; + div = (double)(m)/(double)(n1); + if ((div >= ffreq_min) && + (div <= ffreq_max)) { + diff = ffreq - div / (1<<n2); + if (diff < 0.0) + diff = -diff; + if (diff < best_diff) { + best_diff = diff; + best_m = m; + best_n1 = n1; + best_n2 = n2; + } + } + } + } + + if (max_n1 == 63) + *ndiv = (best_n1 - 2) | (best_n2 << 6); + else + *ndiv = (best_n1 - 2) | (best_n2 << 5); + *mdiv = best_m - 2; +} + + +void S3TrioSetPLL(ScrnInfoPtr pScrn, int clk, unsigned char m, + unsigned char n) +{ + unsigned char tmp; + int index2; + +ErrorF("clk = %d, m = 0x%x, n = 0x%x\n", clk, m, n); + + if (clk < 2) { + tmp = inb(0x3cc); + outb(0x3c2, (tmp & 0xf3) | (clk << 2)); + } else { + tmp = inb(0x3cc); + outb(0x3c2, tmp | 0x0c); + + outb(0x3c4, 0x08); + outb(0x3c5, 0x06); /* unlock extended CR9-18 */ + + if (clk != 10) { + outb(0x3c4, 0x12); + outb(0x3c5, n); + outb(0x3c4, 0x13); + outb(0x3c5, m); + + outb(0x3c4, 0x15); + tmp = inb(0x3c5) & ~0x21; + outb(0x3c5, tmp | 0x02); + outb(0x3c5, tmp | 0x22); + outb(0x3c5, tmp | 0x02); + } else { + index2 = 0x10; + outb(0x3c4, 0x10); + outb(0x3c5, n); + outb(0x3c4, 0x11); + outb(0x3c5, m); + outb(0x3c4, 0x1a); + outb(0x3c5, n); + + outb(0x3c4, 0x15); + tmp = inb(0x3c5) & ~0x21; + outb(0x3c5, tmp | 0x01); + outb(0x3c5, tmp | 0x21); + outb(0x3c5, tmp | 0x01); + outb(0x3c5, tmp); + } + + outb(0x3c4, 0x08); + outb(0x3c5, 0x00); /* lock em */ + } +} + + +void S3TrioSetClock(ScrnInfoPtr pScrn, long freq, int clk, int min_m, + int min_n1, int max_n1, int min_n2, int max_n2, + int pll_type, long freq_min, long freq_max) +{ + S3Ptr pS3 = S3PTR(pScrn); + unsigned char m, n; + + S3TrioCalcClock(freq, min_m, min_n1, max_n1, min_n2, max_n2, + freq_min, freq_max, &m, &n); + + /* XXX for pll_type == TRIO */ + S3TrioSetPLL(pScrn, clk, m, n); +} + +void S3Trio64DAC_PreInit(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + unsigned char SR8, SR27, SR28; + int m, n, n1, n2, mclk; + + outb(0x3c4, 0x08); + SR8 = inb(0x3c5); + outb(0x3c5, 0x06); + + outb(0x3c4, 0x11); + m = inb(0x3c5); + outb(0x3c4, 0x10); + n = inb(0x3c5); + + m &= 0x7f; + n1 = n & 0x1f; + n2 = (n >> 5) & 0x03; + mclk = ((1431818 * (m+2)) / (n1+2) / (1<<n2)+50)/100; + pS3->mclk = mclk; + + outb(0x3c4, 0x08); + outb(0x3c5, SR8); + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MCLK %1.3f Mhz\n", + mclk / 1000.0); +} + + +void S3Trio64DAC_Init(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + S3Ptr pS3 = S3PTR(pScrn); + S3RegPtr new = &pS3->ModeRegs; + int pixmux=0, invert_vclk=0, sr8, sr15, sr18, cr33; + unsigned char blank, tmp; + + S3TrioSetClock(pScrn, mode->Clock, 2, 1, 1, 31, 0, 3, 2, + 135000, 270000); + + outb(0x3c4, 1); + blank = inb(0x3c5); + outb(0x3c5, blank | 0x20); /* blank the screen */ + + outb(0x3c4, 0x08); + sr8 = inb(0x3c5); + outb(0x3c5, 0x06); + + outb(0x3c4, 0x0d0); + tmp = inb(0x3c5) & ~1; + outb(0x3c5, tmp); + + outb(0x3c4, 0x15); + sr15 = inb(0x3c5) & ~0x10; + + outb(0x3c4, 0x18); + sr18 = inb(0x3c5) & ~0x80; + outb(pS3->vgaCRIndex, 0x33); + cr33 = inb(pS3->vgaCRReg) & ~0x28; + + /* ! pixmux */ + switch (pScrn->depth) { + case 8: + break; + case 15: + cr33 |= 0x08; + pixmux = 0x30; + break; + case 16: + cr33 |= 0x08; + pixmux = 0x50; + break; + case 32: + pixmux = 0xd0; + break; + } + + outb(pS3->vgaCRReg, cr33); + + outb(pS3->vgaCRIndex, 0x67); + outb(pS3->vgaCRReg, pixmux | invert_vclk); + + outb(0x3c4, 0x15); + outb(0x3c5, sr15); + outb(0x3c4, 0x18); + outb(0x3c5, sr18); + + outb(0x3c4, 0x08); + outb(0x3c5, sr8); + + outb(0x3c4, 1); + outb(0x3c5, blank); /* unblank the screen */ +} diff --git a/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_accel.c b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_accel.c new file mode 100644 index 000000000..5b6d6208e --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_accel.c @@ -0,0 +1,605 @@ +/* + * Copyright 2001 Ani Joshi <ajoshi@unixbox.com> + * + * XFree86 4.x driver for S3 chipsets + * + * + * 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 Ani Joshi not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Ani Joshi makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ANI JOSHI 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. + * + * + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3/s3_accel.c,v 1.1 2001/07/02 10:46:04 alanh Exp $ */ + + +#include "xf86.h" + +#include "miline.h" + +#include "s3.h" +#include "s3_reg.h" + + +static Bool NicePattern; +static int DashPatternSize; +#define MAX_LINE_PATTERN_LENGTH 512 +#define LINE_PATTERN_START ((MAX_LINE_PATTERN_LENGTH >> 5) - 1) +static CARD32 DashPattern[MAX_LINE_PATTERN_LENGTH >> 5]; + + +static void S3Sync(ScrnInfoPtr pScrn) +{ + WaitIdle(); +} + +static void S3SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask) +{ + S3Ptr pS3 = S3PTR(pScrn); + + WaitQueue16_32(4,6); + SET_PIX_CNTL(0); + SET_FRGD_COLOR(color); + SET_FRGD_MIX(FSS_FRGDCOL | s3alu[rop]); + SET_WRT_MASK(planemask); +} + +static void S3SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, + int w, int h) +{ + S3Ptr pS3 = S3PTR(pScrn); + + WaitQueue(5); + SET_CURPT((short)x, (short)y); + SET_AXIS_PCNT(w - 1, h - 1); + SET_CMD(CMD_RECT | DRAW | INC_X | INC_Y | WRTDATA); +} + + +static void S3SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, + int ydir, int rop, + unsigned int planemask, + int trans_color) +{ + S3Ptr pS3 = S3PTR(pScrn); + + pS3->BltDir = CMD_BITBLT | DRAW | WRTDATA; + + if (xdir == 1) + pS3->BltDir |= INC_X; + if (ydir == 1) + pS3->BltDir |= INC_Y; + + pS3->trans_color = trans_color; + + WaitQueue16_32(3,4); + SET_PIX_CNTL(0); + SET_FRGD_MIX(FSS_BITBLT | s3alu[rop]); + SET_WRT_MASK(planemask); +} + + +static void S3SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, + int srcx, int srcy, + int dstx, int dsty, + int w, int h) +{ + S3Ptr pS3 = S3PTR(pScrn); + + w--; + h--; + + if (!(pS3->BltDir & INC_Y)) { + srcy += h; + dsty += h; + } + + if (!(pS3->BltDir & INC_X)) { + srcx += w; + dstx += w; + } + + if (pS3->trans_color == -1) { + WaitQueue(7); + SET_CURPT((short)srcx, (short)srcy); + SET_DESTSTP((short)dstx, (short)dsty); + SET_AXIS_PCNT((short)w, (short)h); + SET_CMD(pS3->BltDir); + } else { + WaitQueue16_32(2,3); + SET_MULT_MISC(CMD_REG_WIDTH | 0x0100); + SET_COLOR_CMP(pS3->trans_color); + + WaitQueue(8); + SET_CURPT((short)srcx, (short)srcy); + SET_DESTSTP((short)dstx, (short)dsty); + SET_AXIS_PCNT((short)w, (short)h); + SET_CMD(pS3->BltDir); + SET_MULT_MISC(CMD_REG_WIDTH); + } +} + + +static void S3SetupForColor8x8PatternFill(ScrnInfoPtr pScrn, + int patx, int paty, + int rop, unsigned int planemask, + int trans_color) +{ + S3Ptr pS3 = S3PTR(pScrn); + + pS3->trans_color = trans_color; + + WaitQueue16_32(3,4); + SET_PIX_CNTL(0); + SET_FRGD_MIX(FSS_BITBLT | s3alu[rop]); + SET_WRT_MASK(planemask); +} + +static void S3SubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn, + int patx, int paty, + int x, int y, + int w, int h) +{ + S3Ptr pS3 = S3PTR(pScrn); + + if (pS3->trans_color == -1) { + WaitQueue(7); + SET_CURPT((short)patx, (short)paty); + SET_DESTSTP((short)x, (short)y); + SET_AXIS_PCNT(w - 1, h - 1); + SET_CMD(CMD_PFILL | DRAW | INC_Y | INC_X | WRTDATA); + } else { + WaitQueue16_32(2,3); + SET_MULT_MISC(CMD_REG_WIDTH | 0x0100); + SET_COLOR_CMP(pS3->trans_color); + + WaitQueue(8); + SET_CURPT((short)patx, (short)paty); + SET_DESTSTP((short)x, (short)y); + SET_AXIS_PCNT(w - 1, h - 1); + SET_CMD(CMD_PFILL | DRAW | INC_Y | INC_X | WRTDATA); + SET_MULT_MISC(CMD_REG_WIDTH); + } +} + +#ifdef S3_NEWMMIO +static void S3SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int planemask) +{ + S3Ptr pS3 = S3PTR(pScrn); + + WaitQueue16_32(3,4); + if (bg == -1) { + if (pS3->ColorExpandBug) { + SET_MIX(FSS_FRGDCOL | s3alu[rop], BSS_BKGDCOL | MIX_XOR); + SET_BKGD_COLOR(0); + } else + SET_MIX(FSS_FRGDCOL | s3alu[rop], BSS_BKGDCOL | MIX_DST); + } else { + SET_MIX(FSS_FRGDCOL | s3alu[rop], BSS_BKGDCOL | s3alu[rop]); + SET_BKGD_COLOR(bg); + } + + WaitQueue16_32(3,5); + SET_FRGD_COLOR(fg); + SET_WRT_MASK(planemask); + SET_PIX_CNTL(MIXSEL_EXPPC); +} + + +static void S3SubsequentCPUToScreenColorExpandFill32(ScrnInfoPtr pScrn, + int x, int y, + int w, int h, + int skipleft) +{ + S3Ptr pS3 = S3PTR(pScrn); + + WaitQueue(4); + SET_CURPT((short)x, (short)y); + SET_AXIS_PCNT((short)w-1, (short)h-1); + + WaitIdle(); + SET_CMD(CMD_RECT | BYTSEQ | _32BIT | PCDATA | DRAW | + PLANAR | INC_Y | INC_X | WRTDATA); +} +#endif + +#ifndef S3_NEWMMIO + +static void S3SetupForScanlineImageWriteNoMMIO(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, + int trans_color, + int bpp, int depth) +{ + S3Ptr pS3 = S3PTR(pScrn); + + WaitQueue16_32(3,4) + SET_FRGD_MIX(FSS_PCDATA | s3alu[rop]); + SET_WRT_MASK(planemask); + SET_PIX_CNTL(0); +} + +static void S3SubsequentScanlineImageWriteRectNoMMIO(ScrnInfoPtr pScrn, + int x, int y, + int w, int h, + int skipleft) +{ + S3Ptr pS3 = S3PTR(pScrn); + + pS3->imageWidth = w; + pS3->imageHeight = h; + + WaitQueue(5); + SET_CURPT((short)x, (short)y); + SET_AXIS_PCNT((short)w-1, (short)h-1); + WaitIdle(); + SET_CMD(CMD_RECT | BYTSEQ | _16BIT | INC_Y | INC_X | DRAW | + PCDATA | WRTDATA); +} + + +static void S3SubsequentImageWriteScanlineNoMMIO(ScrnInfoPtr pScrn, + int bufno) +{ + S3Ptr pS3 = S3PTR(pScrn); + int i, j; + int w, h; + CARD16 *src = (CARD16 *)&pS3->imageBuffer; + + w = pS3->imageWidth * pS3->s3Bpp; + h = pS3->imageHeight; + + for(j=0; j<h; j++) { + for(i=0; i<(w & ~1); ) { + /* XXX not for 32bpp */ + SET_PIX_TRANS_W(ldw_u(src)); + src++; + i += 2; + } + } +} + +#endif + + +static void S3SetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask) +{ + S3Ptr pS3 = S3PTR(pScrn); + + WaitQueue16_32(4,6); + SET_PIX_CNTL(0); + SET_FRGD_COLOR(color); + SET_FRGD_MIX(FSS_FRGDCOL | s3alu[rop]); + SET_WRT_MASK(planemask); +} + + +static void S3SubsequentSolidBresenhamLine(ScrnInfoPtr pScrn, + int x, int y, + int major, int minor, + int err, int len, int octant) +{ + S3Ptr pS3 = S3PTR(pScrn); + unsigned short cmd; + int error, e1, e2; + + error = minor + err; + e1 = major; + e2 = minor - major; + + if (major) { + cmd = CMD_LINE | DRAW | WRTDATA | LASTPIX; + + if (octant & YMAJOR) + cmd |= YMAJAXIS; + if (!(octant & XDECREASING)) + cmd |= INC_X; + if (!(octant & YDECREASING)) + cmd |= INC_Y; + + WaitQueue(7); + SET_CURPT((short)x, (short)y); + SET_ERR_TERM((short)error); + SET_DESTSTP((short)e2, (short)e1); + SET_MAJ_AXIS_PCNT((short)len); + SET_CMD(cmd); + } else { + WaitQueue(4); + SET_CURPT((short)x, (short)y); + SET_MAJ_AXIS_PCNT((short)len-1); + SET_CMD(CMD_LINE | DRAW | LINETYPE | WRTDATA | VECDIR_270); + } +} + + + +static void S3SubsequentSolidHorVertLine(ScrnInfoPtr pScrn, + int x, int y, int len, int dir) +{ + S3Ptr pS3 = S3PTR(pScrn); + + if (dir == DEGREES_0) + S3SubsequentSolidFillRect(pScrn, x, y, len, 1); + else + S3SubsequentSolidFillRect(pScrn, x, y, 1, len); +} + + + +static void S3SetupForDashedLine(ScrnInfoPtr pScrn, + int fg, int bg, + int rop, unsigned int planemask, + int len, unsigned char *pattern) +{ + S3Ptr pS3 = S3PTR(pScrn); + +#ifdef S3_NEWMMIO + S3SetupForCPUToScreenColorExpandFill(pScrn, bg, fg, rop, planemask); +#endif + + WaitQueue(4); + + NicePattern = FALSE; + + if (len <= 32) { + register CARD32 scratch = DashPattern[LINE_PATTERN_START]; + + if (len & (len - 1)) { + while (len < 16) { + scratch |= (scratch >> len); + len <<= 1; + } + scratch |= (scratch >> len); + DashPattern[LINE_PATTERN_START] = scratch; + } else { + switch (len) { + case 2: + scratch |= scratch >> 2; + case 4: + scratch |= scratch >> 4; + case 8: + scratch |= scratch >> 8; + case 16: + scratch |= scratch >> 16; + DashPattern[LINE_PATTERN_START] = scratch; + case 32: + NicePattern = TRUE; + default: + break; + } + } + } + + DashPatternSize = len; +} + + + +static void S3SubsequentDashedBresenhamLine32(ScrnInfoPtr pScrn, + int x, int y, + int absmaj, int absmin, + int err, int len, + int octant, int phase) +{ + S3Ptr pS3 = S3PTR(pScrn); + register int count = (len + 31) >> 5; + register CARD32 pattern; + int error, e1, e2; + + error = absmin + err; + e1 = absmaj; + e2 = absmin - absmaj; + + if (err) { + unsigned short cmd = _32BIT | PLANAR | WRTDATA | DRAW | + PCDATA | LASTPIX | CMD_LINE; + + if (octant & YMAJOR) + cmd |= YMAJAXIS; + if (!(octant & XDECREASING)) + cmd |= INC_X; + if (!(octant & YDECREASING)) + cmd |= INC_Y; + + WaitQueue(7); + SET_CURPT((short)x, (short)y); + SET_ERR_TERM((short)error); + SET_DESTSTP((short)e2, (short)e1); + SET_MAJ_AXIS_PCNT((short)len); + SET_CMD(cmd); + } else { + if (octant & YMAJOR) { + WaitQueue(4); + SET_CURPT((short)x, (short)y); + SET_MAJ_AXIS_PCNT((short)len - 1); + + if (octant & YDECREASING) { + SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW | + CMD_LINE | LINETYPE | VECDIR_090); + } else { + SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW | + CMD_LINE | LINETYPE | VECDIR_270); + } + } else { + if (octant & XDECREASING) { + WaitQueue(4); + SET_CURPT((short)x, (short)y); + SET_MAJ_AXIS_PCNT((short)len - 1); + SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW | + PCDATA | CMD_LINE | LINETYPE | VECDIR_180); + } else { + WaitQueue(4); + SET_CURPT((short)x, (short)y); + SET_MAJ_AXIS_PCNT((short)len - 1); + SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW | + PCDATA | CMD_RECT | INC_Y | INC_X); + } + } + } + + if (NicePattern) { +#ifdef S3_NEWMMIO + register CARD32 *dest = (CARD32*)&IMG_TRANS; +#endif + + pattern = (phase) ? (DashPattern[LINE_PATTERN_START] << phase) | + (DashPattern[LINE_PATTERN_START] >> (32 - phase)) : + DashPattern[LINE_PATTERN_START]; + +#ifdef S3_NEWMMIO + while (count & ~0x03) { + dest[0] = dest[1] = dest[2] = dest[3] = pattern; + dest += 4; + count -= 4; + } + switch (count) { + case 1: + dest[0] = pattern; + break; + case 2: + dest[0] = dest[1] = pattern; + break; + case 3: + dest[0] = dest[1] = dest[2] = pattern; + break; + } +#else + + while (count--) + SET_PIX_TRANS_L(pattern); +#endif + } else if (DashPatternSize < 32) { + register int offset = phase; + + while (count--) { + SET_PIX_TRANS_L((DashPattern[LINE_PATTERN_START] << offset) | + (DashPattern[LINE_PATTERN_START] >> + (DashPatternSize - offset))); + offset += 32; + while (offset > DashPatternSize) + offset -= DashPatternSize; + } + } else { + int offset = phase; + register unsigned char *srcp = (unsigned char *)(DashPattern) + + (MAX_LINE_PATTERN_LENGTH >> 3) - 1; + register CARD32 *scratch; + int scratch2, shift; + + while (count--) { + shift = DashPatternSize - offset; + scratch = (CARD32*)(srcp - (offset >> 3) - 3); + scratch2 = offset & 0x07; + + if (shift & ~31) { + if (scratch2) { + pattern = (*scratch << scratch2) | + (*(scratch - 1) >> (32 - scratch2)); + } else + pattern = *scratch; + } else { + pattern = (*((CARD32*)(srcp - 3)) >> shift) | + (*scratch << scratch2); + } + SET_PIX_TRANS_L(pattern); + offset += 32; + while (offset >= DashPatternSize) + offset -= DashPatternSize; + } + } +} + +#ifdef S3_NEWMMIO +Bool S3AccelInitNewMMIO(ScreenPtr pScreen) +#else +Bool S3AccelInitPIO(ScreenPtr pScreen) +#endif +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + S3Ptr pS3 = S3PTR(pScrn); + XAAInfoRecPtr pXAA; + + if (pS3->Chipset == PCI_CHIP_968) + pS3->ColorExpandBug = TRUE; + else + pS3->ColorExpandBug = FALSE; + + if (!(pXAA = XAACreateInfoRec())) + return FALSE; + + pS3->pXAA = pXAA; + + pXAA->Flags = (PIXMAP_CACHE | OFFSCREEN_PIXMAPS | + LINEAR_FRAMEBUFFER); + + pXAA->Sync = S3Sync; + + pXAA->SetupForSolidFill = S3SetupForSolidFill; + pXAA->SubsequentSolidFillRect = S3SubsequentSolidFillRect; + + pXAA->SetupForScreenToScreenCopy = S3SetupForScreenToScreenCopy; + pXAA->SubsequentScreenToScreenCopy = S3SubsequentScreenToScreenCopy; + + pXAA->SetupForColor8x8PatternFill = S3SetupForColor8x8PatternFill; + pXAA->SubsequentColor8x8PatternFillRect = S3SubsequentColor8x8PatternFillRect; + +#ifdef S3_NEWMMIO + pXAA->SetupForCPUToScreenColorExpandFill = + S3SetupForCPUToScreenColorExpandFill; + pXAA->SubsequentCPUToScreenColorExpandFill = + S3SubsequentCPUToScreenColorExpandFill32; + pXAA->ColorExpandBase = (void *) &IMG_TRANS; + pXAA->ColorExpandRange = 0x8000; + pXAA->CPUToScreenColorExpandFillFlags = CPU_TRANSFER_PAD_DWORD | + BIT_ORDER_IN_BYTE_MSBFIRST | + SCANLINE_PAD_DWORD; +#endif + +#if 0 +#ifndef S3_NEWMMIO + pXAA->ScanlineImageWriteFlags = NO_TRANSPARENCY; + pXAA->SetupForScanlineImageWrite = + S3SetupForScanlineImageWriteNoMMIO; + pXAA->SubsequentScanlineImageWriteRect = + S3SubsequentScanlineImageWriteRectNoMMIO; + pXAA->SubsequentImageWriteScanline = + S3SubsequentImageWriteScanlineNoMMIO; + pXAA->NumScanlineImageWriteBuffers = 1; + pXAA->ScanlineImageWriteBuffers = &pS3->imageBuffer; +#endif +#endif + + pXAA->SetupForSolidLine = S3SetupForSolidLine; + pXAA->SubsequentSolidBresenhamLine = S3SubsequentSolidBresenhamLine; + pXAA->SubsequentSolidHorVertLine = S3SubsequentSolidHorVertLine; + pXAA->SolidBresenhamLineErrorTermBits = 12; +#if 0 + /* kinda buggy... and its faster without it */ + pXAA->SetupForDashedLine = S3SetupForDashedLine; + pXAA->SubsequentDashedBresenhamLine = S3SubsequentDashedBresenhamLine32; + pXAA->DashPatternMaxLength = MAX_LINE_PATTERN_LENGTH; +#endif + + return XAAInit(pScreen, pXAA); +} + + + diff --git a/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_bios.c b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_bios.c new file mode 100644 index 000000000..aa598bd29 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_bios.c @@ -0,0 +1,83 @@ +/* + * Copyright 2001 Ani Joshi <ajoshi@unixbox.com> + * + * XFree86 4.x driver for S3 chipsets + * + * + * 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 Ani Joshi not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Ani Joshi makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ANI JOSHI 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. + * + * + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3/s3_bios.c,v 1.2 2001/07/11 07:45:35 alanh Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "compiler.h" + +#include "s3.h" + + +static unsigned char *find_bios_string(int BIOSbase, char *match1, char *match2) +{ + static unsigned char bios[BIOS_BSIZE]; + static int init=0; + int i, j, l1, l2; + + if (!init) { + init = 1; + if (xf86ReadBIOS(BIOSbase, 0, bios, BIOS_BSIZE) != BIOS_BSIZE) + return NULL; + if ((bios[0] != 0x55) || (bios[1] != 0xaa)) + return NULL; + } + if (match1 == NULL) + return NULL; + + l1 = strlen(match1); + if (match2 != NULL) + l2 = strlen(match2); + else + l2 = 0; + + for (i=0; i<BIOS_BSIZE; i++) + if (bios[i] == match1[0] && !memcmp(&bios[i], match1, l1)) { + if (match2 == NULL) + return &bios[i+l1]; + else + for(j=i+l1; (j<BIOS_BSIZE-l2) && bios[j]; j++) + if (bios[j] == match2[0] && + !memcmp(&bios[j], match2, l2)) + return &bios[j+l2]; + } + + return NULL; +} + + +int S3GetRefClock(ScrnInfoPtr pScrn) +{ + int RefClock = 16000; /* default */ + + if (find_bios_string(BIOS_BASE, "Number Nine Visual Technology", + "Motion 771") != NULL) + RefClock = 16000; + + return RefClock; +} diff --git a/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_cursor.c b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_cursor.c new file mode 100644 index 000000000..6400874ac --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_cursor.c @@ -0,0 +1,226 @@ +/* + * Copyright 2001 Ani Joshi <ajoshi@unixbox.com> + * + * XFree86 4.x driver for S3 chipsets + * + * + * 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 Ani Joshi not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Ani Joshi makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ANI JOSHI 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. + * + * + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3/s3_cursor.c,v 1.1 2001/07/02 10:46:04 alanh Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +#include "compiler.h" + +#include "s3.h" +#include "s3_reg.h" + + +static void S3SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + unsigned short packfg, packbg; + + switch (pS3->s3Bpp) { + case 1: + /* XXX Trio series only */ + outb(vgaCRIndex, 0x45); + inb(vgaCRReg); + outb(vgaCRIndex, 0x4a); + outb(vgaCRReg, fg); + outb(vgaCRReg, fg); + + outb(vgaCRIndex, 0x45); + inb(vgaCRReg); + outb(vgaCRIndex, 0x4b); + outb(vgaCRReg, bg); + outb(vgaCRReg, bg); + + break; + case 2: + /* XXX depth 16 */ + packfg = ((fg & 0x00f80000) >> 19) | ((fg & 0x0000fc00) >> 5) | + ((fg & 0x000000f8) << 8); + packbg = ((bg & 0x00f80000) >> 19) | ((bg & 0x0000fc00) >> 5) | + ((bg & 0x000000f8) << 8); + + outb(vgaCRIndex, 0x45); + inb(vgaCRReg); + outb(vgaCRIndex, 0x4a); + outb(vgaCRReg, packfg); + outb(vgaCRReg, packfg >> 8); + + outb(vgaCRIndex, 0x45); + inb(vgaCRReg); + outb(vgaCRIndex, 0x4b); + outb(vgaCRReg, packbg); + outb(vgaCRReg, packbg >> 8); + + break; + default: + outb(vgaCRIndex, 0x45); + inb(vgaCRReg); + outb(vgaCRIndex, 0x4a); + outb(vgaCRReg, (fg & 0x00ff0000) >> 16); + outb(vgaCRReg, (fg & 0x0000ff00) >> 8); + outb(vgaCRReg, (fg & 0x000000ff)); + + outb(vgaCRIndex, 0x45); + inb(vgaCRReg); + outb(vgaCRIndex, 0x4b); + outb(vgaCRReg, (bg & 0x00ff0000) >> 16); + outb(vgaCRReg, (bg & 0x0000ff00) >> 8); + outb(vgaCRReg, (bg & 0x000000ff)); + + break; + } +} + + +static void S3SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + + outb(vgaCRIndex, 0x39); + outb(vgaCRReg, 0xa5); + + outb(vgaCRIndex, 0x46); + outb(vgaCRReg, x >> 8); + outb(vgaCRIndex, 0x47); + outb(vgaCRReg, x); + + outb(vgaCRIndex, 0x49); + outb(vgaCRReg, y); + outb(vgaCRIndex, 0x48); + outb(vgaCRReg, y >> 8); +} + + +static void S3HideCursor(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + unsigned char tmp; + + outb(vgaCRIndex, 0x45); + tmp = inb(vgaCRReg); + outb(vgaCRReg, tmp & ~0x01); +} + + +static void S3ShowCursor(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + unsigned char tmp; + + outb(vgaCRIndex, 0x39); + outb(vgaCRReg, 0xa5); + + outb(vgaCRIndex, 0x55); + tmp = inb(vgaCRReg); + outb(vgaCRReg, tmp | 0x10); + + outb(vgaCRIndex, 0x4c); + outb(vgaCRReg, pS3->FBCursorOffset >> 8); + outb(vgaCRIndex, 0x4d); + outb(vgaCRReg, pS3->FBCursorOffset); + + outb(vgaCRIndex, 0x45); + tmp = inb(vgaCRReg); + outb(vgaCRReg, tmp | 0x01); +} + + +static void S3LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) +{ + S3Ptr pS3 = S3PTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + unsigned char cr45; + + outb(vgaCRIndex, 0x39); + outb(vgaCRReg, 0xa5); + + WaitIdle(); + + VerticalRetraceWait(); + + outb(vgaCRIndex, 0x45); + cr45 = inb(vgaCRReg); + outb(vgaCRReg, cr45 & 0xfe); + + outb(vgaCRIndex, 0x46); + outb(vgaCRReg, 0xff); + outb(vgaCRIndex, 0x47); + outb(vgaCRReg, 0x7f); + outb(vgaCRIndex, 0x49); + outb(vgaCRReg, 0xff); + outb(vgaCRIndex, 0x4e); + outb(vgaCRReg, 0x3f); + outb(vgaCRIndex, 0x4f); + outb(vgaCRReg, 0x3f); + outb(vgaCRIndex, 0x48); + outb(vgaCRReg, 0x7f); + + memcpy(pS3->FBBase + (pS3->FBCursorOffset * 1024), image, 1024); + + VerticalRetraceWait(); + + outb(vgaCRIndex, 0x45); + outb(vgaCRReg, cr45); +} + + +static Bool S3UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) +{ + return TRUE; +} + + +Bool S3_CursorInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + S3Ptr pS3 = S3PTR(pScrn); + xf86CursorInfoPtr pCurs; + + if (!(pCurs = pS3->pCurs = xf86CreateCursorInfoRec())) + return FALSE; + + pCurs->MaxWidth = 64; + pCurs->MaxHeight = 64; + pCurs->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | + HARDWARE_CURSOR_BIT_ORDER_MSBFIRST; + + pCurs->SetCursorColors = S3SetCursorColors; + pCurs->SetCursorPosition = S3SetCursorPosition; + pCurs->LoadCursorImage = S3LoadCursorImage; + pCurs->HideCursor = S3HideCursor; + pCurs->ShowCursor = S3ShowCursor; + pCurs->UseHWCursor = S3UseHWCursor; + + return xf86InitCursor(pScreen, pCurs); +} + diff --git a/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_dga.c b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_dga.c new file mode 100644 index 000000000..a8e6560a6 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_dga.c @@ -0,0 +1,318 @@ +/* + * Copyright 2001 Ani Joshi <ajoshi@unixbox.com> + * + * XFree86 4.x driver for S3 chipsets + * + * + * 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 Ani Joshi not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Ani Joshi makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ANI JOSHI 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. + * + * + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3/s3_dga.c,v 1.1 2001/07/02 10:46:04 alanh Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +#include "dgaproc.h" + +#include "s3.h" +#include "s3_reg.h" + + +static Bool S3_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode); +static int S3_GetViewport(ScrnInfoPtr pScrn); +static void S3_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags); +static void S3_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned long color); +static void S3_BltRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h, + int dstx, int dsty); +static Bool S3_OpenFramebuffer(ScrnInfoPtr pScrn, char **name, + unsigned char **mem, int *size, int *offset, + int *flags); +static void S3_Sync(ScrnInfoPtr pScrn); + + +static DGAFunctionRec S3_DGAFuncs = { + S3_OpenFramebuffer, + NULL, + S3_SetMode, + S3_SetViewport, + S3_GetViewport, + S3_Sync, + S3_FillRect, + S3_BltRect, + NULL +}; + + +static DGAModePtr S3SetupDGAMode(ScrnInfoPtr pScrn, DGAModePtr modes, + int *num, int bitsPerPixel, int depth, + Bool pixmap, int secondPitch, + unsigned long red, unsigned long green, + unsigned long blue, short visualClass) +{ + S3Ptr pS3 = S3PTR(pScrn); + DGAModePtr newmodes = NULL, currentMode; + DisplayModePtr pMode, firstMode; + int otherPitch, Bpp = bitsPerPixel >> 3; + Bool oneMore; + + pMode = firstMode = pScrn->modes; + + while (pMode) { + otherPitch = secondPitch ? secondPitch : pMode->HDisplay; + + if (pMode->HDisplay != otherPitch) { + newmodes = xrealloc(modes, (*num + 2) * sizeof(DGAModeRec)); + oneMore = TRUE; + } else { + newmodes = xrealloc(modes, (*num + 1) * sizeof(DGAModeRec)); + oneMore = FALSE; + } + + if (!newmodes) { + xfree(modes); + return NULL; + } + + modes = newmodes; + +SECOND_PASS: + + currentMode = modes + *num; + (*num)++; + + currentMode->mode = pMode; + currentMode->flags = DGA_CONCURRENT_ACCESS; + if (pixmap) + currentMode->flags |= DGA_PIXMAP_AVAILABLE; + if (pS3->pXAA) + currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT; + if (pMode->Flags & V_DBLSCAN) + currentMode->flags |= DGA_DOUBLESCAN; + if (pMode->Flags & V_INTERLACE) + currentMode->flags |= DGA_INTERLACED; + currentMode->byteOrder = pScrn->imageByteOrder; + currentMode->depth = depth; + currentMode->bitsPerPixel = bitsPerPixel; + currentMode->red_mask = red; + currentMode->green_mask = green; + currentMode->blue_mask = blue; + currentMode->visualClass = visualClass; + currentMode->viewportWidth = pMode->HDisplay; + currentMode->viewportHeight = pMode->VDisplay; + currentMode->xViewportStep = 8; + currentMode->yViewportStep = 1; + currentMode->viewportFlags = DGA_FLIP_RETRACE; + currentMode->offset = 0; + currentMode->address = (unsigned char*)pS3->FBAddress; + + if (oneMore) { + currentMode->bytesPerScanline = (((pMode->HDisplay * Bpp) + 3) & ~3L); + + currentMode->imageWidth = pMode->HDisplay; + currentMode->imageHeight = pMode->VDisplay; + currentMode->pixmapWidth = currentMode->imageWidth; + currentMode->pixmapHeight = currentMode->imageHeight; + currentMode->maxViewportX = currentMode->imageWidth - + currentMode->viewportWidth; + currentMode->maxViewportY = currentMode->imageHeight - + currentMode->viewportHeight; + + oneMore = FALSE; + goto SECOND_PASS; + } else { + currentMode->bytesPerScanline = (((otherPitch * Bpp) + 3) & ~3L); + + currentMode->imageWidth = otherPitch; + currentMode->imageHeight = pMode->VDisplay; + currentMode->pixmapWidth = currentMode->imageWidth; + currentMode->pixmapHeight = currentMode->imageHeight; + currentMode->maxViewportX = currentMode->imageWidth - + currentMode->viewportWidth; + currentMode->maxViewportY = currentMode->imageHeight - + currentMode->viewportHeight; + + } + + pMode = pMode->next; + + if (pMode == firstMode) + break; + + } + + return modes; +} + + + +Bool S3DGAInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + S3Ptr pS3 = S3PTR(pScrn); + DGAModePtr modes = NULL; + int num = 0; + + modes = S3SetupDGAMode(pScrn, modes, &num, 8, 8, + (pScrn->bitsPerPixel == 8), + ((pScrn->bitsPerPixel != 8) ? 0 : pScrn->displayWidth), + 0, 0, 0, PseudoColor); + + modes = S3SetupDGAMode(pScrn, modes, &num, 16, 15, + (pScrn->bitsPerPixel == 16), + ((pScrn->depth != 15) + ? 0 : pScrn->displayWidth), + 0x7c00, 0x03e0, 0x001f, TrueColor); + + modes = S3SetupDGAMode(pScrn, modes, &num, 16, 15, + (pScrn->bitsPerPixel == 16), + ((pScrn->depth != 15) + ? 0 : pScrn->displayWidth), + 0x7c00, 0x03e0, 0x001f, DirectColor); + + modes = S3SetupDGAMode(pScrn, modes, &num, 16, 16, + (pScrn->bitsPerPixel == 16), + ((pScrn->depth != 16) + ? 0 : pScrn->displayWidth), + 0xf800, 0x07e0, 0x001f, TrueColor); + + modes = S3SetupDGAMode(pScrn, modes, &num, 16, 16, + (pScrn->bitsPerPixel == 16), + ((pScrn->depth != 16) + ? 0 : pScrn->displayWidth), + 0xf800, 0x07e0, 0x001f, DirectColor); + + modes = S3SetupDGAMode(pScrn, modes, &num, 32, 24, + (pScrn->bitsPerPixel == 32), + ((pScrn->bitsPerPixel != 32) + ? 0 : pScrn->displayWidth), + 0xff0000, 0x00ff00, 0x0000ff, TrueColor); + + modes = S3SetupDGAMode(pScrn, modes, &num, 32, 24, + (pScrn->bitsPerPixel == 32), + ((pScrn->bitsPerPixel != 32) + ? 0 : pScrn->displayWidth), + 0xff0000, 0x00ff00, 0x0000ff, DirectColor); + + pS3->numDGAModes = num; + pS3->DGAModes = modes; + + return DGAInit(pScreen, &S3_DGAFuncs, modes, num); +} + + +static Bool S3_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode) +{ + S3Ptr pS3 = S3PTR(pScrn); + static S3FBLayout SavedLayouts[MAXSCREENS]; + int indx = pScrn->pScreen->myNum; + + if (!pMode) { + if (pS3->DGAactive) { + memcpy(&pS3->CurrentLayout, &SavedLayouts[indx], + sizeof(S3FBLayout)); + pS3->DGAactive = TRUE; + } + + pS3->CurrentLayout.bitsPerPixel = pMode->bitsPerPixel; + pS3->CurrentLayout.depth = pMode->depth; + pS3->CurrentLayout.displayWidth = (pMode->bytesPerScanline / + (pMode->bitsPerPixel >> 3)); + pS3->CurrentLayout.pixel_bytes = pMode->bitsPerPixel / 8; + pS3->CurrentLayout.pixel_code = (pMode->bitsPerPixel != 16 ? + pMode->bitsPerPixel : + pMode->depth); + + S3SwitchMode(indx, pMode->mode, 0); + } + + return TRUE; +} + + +static int S3_GetViewport(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + + return pS3->DGAViewportStatus; +} + + +static void S3_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags) +{ + S3Ptr pS3 = S3PTR(pScrn); + + pScrn->AdjustFrame(pScrn->pScreen->myNum, x, y, flags); + pS3->DGAViewportStatus = 0; +} + + +static void S3_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned long color) +{ + S3Ptr pS3 = S3PTR(pScrn); + + if (pS3->pXAA) { + (*pS3->pXAA->SetupForSolidFill)(pScrn, color, GXcopy, (CARD32)(~0)); + (*pS3->pXAA->SubsequentSolidFillRect)(pScrn, x, y, w, h); + SET_SYNC_FLAG(pS3->pXAA); + } +} + + +static void S3_BltRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h, + int dstx, int dsty) +{ + S3Ptr pS3 = S3PTR(pScrn); + + if (pS3->pXAA) { + int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; + int ydir = (srcy < dsty) ? -1 : 1; + + (*pS3->pXAA->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, + GXcopy, (CARD32)(~0), -1); + (*pS3->pXAA->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy, + dstx, dsty, w, h); + SET_SYNC_FLAG(pS3->pXAA); + } +} + + +static Bool S3_OpenFramebuffer(ScrnInfoPtr pScrn, char **name, + unsigned char **mem, int *size, int *offset, + int *flags) +{ + S3Ptr pS3 = S3PTR(pScrn); + + *name = NULL; + *mem = (unsigned char*)pS3->FBAddress; + *size = (pScrn->videoRam * 1024); + *offset = 0; + *flags = 0; + + return TRUE; +} + + +static void S3_Sync(ScrnInfoPtr pScrn) +{ + WaitIdle(); +} diff --git a/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_driver.c b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_driver.c new file mode 100644 index 000000000..3cc05c11b --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_driver.c @@ -0,0 +1,1759 @@ +/* + * Copyright 2001 Ani Joshi <ajoshi@unixbox.com> + * + * XFree86 4.x driver for S3 chipsets + * + * + * 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 Ani Joshi not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Ani Joshi makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ANI JOSHI 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. + * + * + * Credits: + * Thomas Roell <roell@informatik.tu-muenchen.de> + * Mark Vojkovich <markv@valinux.com> + * Kevin E. Martin <martin@valinux.com> + * - and others for their work on the 3.x S3 driver + * + * Dominik Behr + * - for various hardware donations + * + * + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3/s3_driver.c,v 1.3 2001/08/15 11:54:27 tsi Exp $ */ + + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "xf86Pci.h" +#include "xf86PciInfo.h" +#include "xf86Version.h" +#include "xf86Resources.h" +#include "xf86fbman.h" +#include "xf86cmap.h" +#include "compiler.h" +#include "xaa.h" +#include "mipointer.h" +#include "micmap.h" +#include "mibstore.h" +#include "fb.h" + +#include "IBM.h" +#include "TI.h" + +#include "s3.h" +#include "s3_reg.h" + +#define TRIO64_RAMDAC 0x8811 + + +short s3alu[16] = +{ + MIX_0, + MIX_AND, + MIX_SRC_AND_NOT_DST, + MIX_SRC, + MIX_NOT_SRC_AND_DST, + MIX_DST, + MIX_XOR, + MIX_OR, + MIX_NOR, + MIX_XNOR, + MIX_NOT_DST, + MIX_SRC_OR_NOT_DST, + MIX_NOT_SRC, + MIX_NOT_SRC_OR_DST, + MIX_NAND, + MIX_1, +}; + + +/* + * Prototypes + */ +static const OptionInfoRec * S3AvailableOptions(int chipid, int busid); +static void S3Identify(int flags); +static Bool S3Probe(DriverPtr drv, int flags); +static Bool S3PreInit(ScrnInfoPtr pScrn, int flags); +static Bool S3EnterVT(int scrnIndex, int flags); +static void S3LeaveVT(int scrnIndex, int flags); +static void S3Save(ScrnInfoPtr pScrn); +static Bool S3ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, + char **argv); +static Bool S3MapMem(ScrnInfoPtr pScrn); +static void S3UnmapMem(ScrnInfoPtr pScrn); +static Bool S3ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); +static void S3AdjustFrame(int scrnIndex, int x, int y, int flags); +Bool S3CloseScreen(int scrnIndex, ScreenPtr pScreen); +Bool S3SaveScreen(ScreenPtr pScreen, int mode); +static void S3FreeScreen(int scrnIndex, int flags); +static void S3GenericLoadPalette(ScrnInfoPtr pScrn, int numColors, + int *indicies, LOCO *colors, + VisualPtr pVisual); +static void S3Restore(ScrnInfoPtr pScrn); +void S3BankZero(ScrnInfoPtr pScrn); +void S3Regdump(ScrnInfoPtr pScrn); +static void S3DisplayPowerManagementSet(ScrnInfoPtr pScrn, + int PowerManagementMode, int flags); + + + +DriverRec S3 = +{ + S3_VERSION, + DRIVER_NAME, + S3Identify, + S3Probe, + S3AvailableOptions, + NULL, + 0 +}; + +/* supported chipsets */ +static SymTabRec S3Chipsets[] = { + { PCI_CHIP_964_0, "964-0"}, + { PCI_CHIP_964_1, "964-1"}, + { PCI_CHIP_968, "968" }, + { PCI_CHIP_TRIO, "Trio32/64" }, + { -1, NULL } +}; + + +static PciChipsets S3PciChipsets[] = { + { PCI_CHIP_964_0, PCI_CHIP_964_0, RES_SHARED_VGA }, + { PCI_CHIP_964_1, PCI_CHIP_964_1, RES_SHARED_VGA }, + { PCI_CHIP_968, PCI_CHIP_968, RES_SHARED_VGA }, + { PCI_CHIP_TRIO, PCI_CHIP_TRIO, RES_SHARED_VGA }, + { -1, -1, RES_UNDEFINED } +}; + +typedef enum { + OPTION_NOACCEL, + OPTION_SWCURS +} S3Opts; + +static OptionInfoRec S3Options[] = { + { OPTION_NOACCEL, "noaccel", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SWCURS, "swcursor", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +RamDacSupportedInfoRec IBMRamdacs[] = { + { IBM524_RAMDAC }, + { IBM524A_RAMDAC }, + { -1 } +}; + +#define S3_USEFB + +#ifdef S3_USEFB +static const char *fbSymbols[] = { + "fbScreenInit", + NULL +}; +#else +static const char *cfbSymbols[] = { + "cfbScreenInit", + "cfb16ScreenInit", + "cfb24ScreenInit", + "cfb32ScreenInit", + NULL +}; +#endif + +static const char *vgaHWSymbols[] = { + "vgaHWGetHWRec", + "vgaHWFreeHWRec", + "vgaHWGetIOBase", + "vgaHWSave", + "vgaHWProtect", + "vgaHWRestore", + "vgaHWMapMem", + "vgaHWUnmapMem", + "vgaHWSaveScreen", + "vgaHWLock", + "vgaHWInit", + "vgaHWDPMSSet", + NULL +}; + +static const char *vbeSymbols[] = { + "VBEInit", + "vbeDoEDID", + "vbeFree", + NULL +}; + +static const char *int10Symbols[] = { + "xf86ExecX86int10", + "xf86FreeInt10", + "xf86InitInt10", + "xf86Int10AllocPages", + "xf86Int10FreePages", + NULL +}; + +static const char *ramdacSymbols[] = { + "xf86InitCursor", + "xf86CreateCursorInfoRec", + "RamDacInit", + "RamDacCreateInfoRec", + "RamDacDestroyInfoRec", + "RamDacHelperCreateInfoRec", + "RamDacGetHWIndex", + "IBMramdacProbe", + "IBMramdac526CalculateMNPCForClock", + "IBMramdac526SetBpp", + NULL +}; + +static const char *xaaSymbols[] = { + "XAADestroyInfoRec", + "XAACreateInfoRec", + "XAAInit", + NULL +}; + + +#ifdef XFree86LOADER + +MODULESETUPPROTO(S3Setup); + +static XF86ModuleVersionInfo S3VersRec = { + "s3", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_VIDEODRV, + {0, 0, 0, 0} +}; + + +XF86ModuleData s3ModuleData = { &S3VersRec, S3Setup, NULL }; + +pointer S3Setup (pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + + if (!setupDone) { + setupDone = TRUE; + xf86AddDriver(&S3, module, 0); + LoaderRefSymLists(vgaHWSymbols, + vbeSymbols, int10Symbols, ramdacSymbols, +#ifdef S3_USEFB + fbSymbols, +#else + cfbSymbols, +#endif + xaaSymbols, + NULL); + return (pointer) 1; + } else { + if (errmaj) + *errmaj = LDR_ONCEONLY; + return NULL; + } +} + +#endif /* XFree86LOADER */ + + +static Bool S3GetRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate) + return TRUE; + + pScrn->driverPrivate = xnfcalloc(sizeof(S3Rec), 1); + + return TRUE; +} + +static void S3FreeRec(ScrnInfoPtr pScrn) +{ + if (!pScrn->driverPrivate) + return; + + xfree(pScrn->driverPrivate); + pScrn->driverPrivate = NULL; +} + +static const OptionInfoRec * S3AvailableOptions(int chipid, int busid) +{ + return S3Options; +} + +static void S3Identify(int flags) +{ + xf86PrintChipsets("s3", "driver (version " DRIVER_VERSION " for S3 chipset", + S3Chipsets); +} + +static Bool S3Probe(DriverPtr drv, int flags) +{ + GDevPtr *devSections; + int i, *usedChips, numDevSections, numUsed; + Bool foundScreen = FALSE; + + /* sanity check */ + if ((numDevSections = xf86MatchDevice("s3", &devSections)) <= 0) + return FALSE; + + /* XXX do ISA later... some day in the distant future... */ + numUsed = xf86MatchPciInstances("s3", PCI_VENDOR_S3, + S3Chipsets, S3PciChipsets, + devSections, numDevSections, + drv, &usedChips); + + xfree(devSections); + + if (numUsed <= 0) + return FALSE; + + if (flags & PROBE_DETECT) + foundScreen = TRUE; + else for (i=0; i<numUsed; i++) { + ScrnInfoPtr pScrn = xf86AllocateScreen(drv, 0); + + pScrn->driverVersion = VERSION_MAJOR; + pScrn->driverName = DRIVER_NAME; + pScrn->name = "s3"; + pScrn->Probe = S3Probe; + pScrn->PreInit = S3PreInit; + pScrn->ScreenInit = S3ScreenInit; + pScrn->SwitchMode = S3SwitchMode; + pScrn->AdjustFrame = S3AdjustFrame; + pScrn->EnterVT = S3EnterVT; + pScrn->LeaveVT = S3LeaveVT; + pScrn->FreeScreen = S3FreeScreen; + + foundScreen = TRUE; + + xf86ConfigActivePciEntity(pScrn, usedChips[i], S3PciChipsets, + NULL, NULL, NULL, NULL, NULL); + } + + xfree(usedChips); + + return foundScreen; +} + +static Bool S3PreInit(ScrnInfoPtr pScrn, int flags) +{ + EntityInfoPtr pEnt; + S3Ptr pS3; + vgaHWPtr hwp; + ClockRangePtr clockRanges; + rgb zeros = {0, 0, 0}; + Gamma gzeros = {0.0, 0.0, 0.0}; + int i, vgaCRIndex, vgaCRReg; + unsigned char tmp; + + if (flags & PROBE_DETECT) + return FALSE; + + if (!xf86LoadSubModule(pScrn, "vgahw")) + return FALSE; + + xf86LoaderReqSymLists(vgaHWSymbols, NULL); + + if (!vgaHWGetHWRec(pScrn)) + return FALSE; + + hwp = VGAHWPTR(pScrn); + vgaHWGetIOBase(hwp); + + pScrn->monitor = pScrn->confScreen->monitor; + + if (!xf86SetDepthBpp(pScrn, 8, 8, 8, Support24bppFb | Support32bppFb)) + return FALSE; + + switch (pScrn->depth) { + case 8: + case 15: + case 16: + case 24: + case 32: + /* OK */ + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given depth (%d) is not supported by this driver\n", + pScrn->depth); + return FALSE; + } + + xf86PrintDepthBpp(pScrn); + + if (pScrn->depth > 8) { + if (!xf86SetWeight(pScrn, zeros, zeros)) + return FALSE; + } + + if (!xf86SetDefaultVisual(pScrn, -1)) + return FALSE; + + pScrn->progClock = TRUE; + + if (!S3GetRec(pScrn)) + return FALSE; + + pS3 = S3PTR(pScrn); + + pS3->s3Bpp = (pScrn->bitsPerPixel >> 3); + +#if 0 + xf86CollectOptions(pScrn, NULL); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, S3Options); + + if (xf86ReturnOptValBool(S3Options, OPTION_NOACCEL, FALSE)) { + pS3->NoAccel = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: NoAccel - acceleration disabled\n"); + } else + pS3->NoAccel = FALSE; +#endif + + if (pScrn->numEntities > 1) { + S3FreeRec(pScrn); + return FALSE; + } + + pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + if (pEnt->resources) { + xfree(pEnt); + S3FreeRec(pScrn); + return FALSE; + } + + if (xf86LoadSubModule(pScrn, "int10")) { + xf86LoaderReqSymLists(int10Symbols, NULL); + pS3->pInt10 = xf86InitInt10(pEnt->index); + } + + if (xf86LoadSubModule(pScrn, "vbe")) { + xf86LoaderReqSymLists(vbeSymbols, NULL); + pS3->pVBE = VBEInit(pS3->pInt10, pEnt->index); + } + + if (!xf86SetGamma(pScrn, gzeros)) + return FALSE; + + pS3->PciInfo = xf86GetPciInfoForEntity(pEnt->index); + xf86RegisterResources(pEnt->index, NULL, ResNone); + xf86SetOperatingState(RES_SHARED_VGA, pEnt->index, ResUnusedOpr); + xf86SetOperatingState(resVgaMemShared, pEnt->index, ResDisableOpr); + + if (pEnt->device->chipset && *pEnt->device->chipset) { + pScrn->chipset = pEnt->device->chipset; + pS3->Chipset = xf86StringToToken(S3Chipsets, pScrn->chipset); + } else if (pEnt->device->chipID >= 0) { + pS3->Chipset = pEnt->device->chipID; + pScrn->chipset = (char *)xf86TokenToString(S3Chipsets, + pS3->Chipset); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", + pS3->Chipset); + } else { + pS3->Chipset = pS3->PciInfo->chipType; + pScrn->chipset = (char *)xf86TokenToString(S3Chipsets, + pS3->Chipset); + } + if (pEnt->device->chipRev >= 0) { + pS3->ChipRev = pEnt->device->chipRev; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", + pS3->ChipRev); + } else + pS3->ChipRev = pS3->PciInfo->chipRev; + + xfree(pEnt); + + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Chipset: \"%s\"\n", pScrn->chipset); + + pS3->PciTag = pciTag(pS3->PciInfo->bus, pS3->PciInfo->device, + pS3->PciInfo->func); + + switch (pS3->Chipset) { + case PCI_CHIP_964_0: + case PCI_CHIP_964_1: + case PCI_CHIP_TRIO: + pS3->S3NewMMIO = FALSE; + break; + case PCI_CHIP_968: + pS3->S3NewMMIO = TRUE; + break; + } + + pS3->FBAddress = pS3->PciInfo->memBase[0]; + if (pS3->S3NewMMIO) + pS3->IOAddress = pS3->FBAddress + S3_NEWMMIO_REGBASE; + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Framebuffer @ 0x%x\n", + pS3->FBAddress); + if (pS3->S3NewMMIO) + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MMIO @ 0x%x\n", + pS3->IOAddress); + + pS3->PCIRetry = FALSE; /* not supported yet */ + + pS3->vgaCRIndex = vgaCRIndex = hwp->IOBase + 4; + pS3->vgaCRReg = vgaCRReg = hwp->IOBase + 5; + + /* unlock sys regs */ + outb(vgaCRIndex, 0x38); + outb(vgaCRReg, 0x48); + outb(vgaCRIndex, 0x39); + outb(vgaCRReg, 0xa5); + + outb(vgaCRIndex, 0x40); + tmp = inb(vgaCRReg) | 0x01; + outb(vgaCRReg, tmp); + outb(vgaCRIndex, 0x35); + tmp = inb(vgaCRReg) & ~0x30; + outb(vgaCRReg, tmp); + + outb(0x3c4, 0x08); + outb(0x3c5, 0x06); + outb(vgaCRIndex, 0x33); + tmp = (inb(vgaCRReg) & ~(0x2 | 0x10 | 0x40)) | 0x20; + outb(vgaCRReg, tmp); + + /* unprotect CRTC[0-7] */ + outb(vgaCRIndex, 0x11); + tmp = inb(vgaCRReg) & 0x7f; + outb(vgaCRReg, tmp); + + /* wake up */ + outb(0x46e8, 0x10); + outb(0x102, 0x01); + outb(0x46e8, 0x08); + + if (!pScrn->videoRam) { + /* probe videoram */ + outb(vgaCRIndex, 0x36); + tmp = inb(vgaCRReg); + + switch ((tmp & 0xe0) >> 5) { + case 0: + pScrn->videoRam = 4096; + break; + case 2: + pScrn->videoRam = 3072; + break; + case 3: + pScrn->videoRam = 8192; + break; + case 4: + pScrn->videoRam = 2048; + break; + case 5: + pScrn->videoRam = 6144; + break; + case 6: + pScrn->videoRam = 1024; + break; + } + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "videoRam = %d Kb\n", pScrn->videoRam); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "videoRam = %d Kb\n", pScrn->videoRam); + } + + if (!xf86LoadSubModule(pScrn, "ramdac")) + return FALSE; + xf86LoaderReqSymLists(ramdacSymbols, NULL); + + pScrn->rgbBits = 8; /* set default */ + + /* probe for dac */ + if ((pS3->Chipset == PCI_CHIP_964_0) || + (pS3->Chipset == PCI_CHIP_964_1)) { + if (S3TiDACProbe(pScrn)) { + pS3->DacPreInit = S3TiDAC_PreInit; + pS3->DacInit = S3TiDAC_Init; + pS3->DacSave = S3TiDAC_Save; + pS3->DacRestore = S3TiDAC_Restore; + pS3->CursorInit = S3Ti_CursorInit; + pS3->MaxClock = 135000; + pScrn->rgbBits = 8; + if (pScrn->bitsPerPixel > 8) + pS3->LoadPalette = S3TiLoadPalette; + else + pS3->LoadPalette = S3GenericLoadPalette; + + pS3->LoadPalette = S3GenericLoadPalette; + } + } + if (pS3->Chipset == PCI_CHIP_968) { + if (S3ProbeIBMramdac(pScrn)) { + pS3->DacPreInit = S3IBMRGB_PreInit; + pS3->DacInit = S3IBMRGB_Init; + pS3->DacSave = S3IBMRGB_Save; + pS3->DacRestore = S3IBMRGB_Restore; + pS3->CursorInit = S3IBMRGB_CursorInit; + pS3->RamDac->SetBpp = IBMramdac526SetBpp; + pS3->MaxClock = 170000; + pScrn->rgbBits = 8; + pS3->LoadPalette = S3GenericLoadPalette; + } + } + if (S3Trio64DACProbe(pScrn)) { + pS3->DacPreInit = S3Trio64DAC_PreInit; + pS3->DacInit = S3Trio64DAC_Init; + pS3->DacSave = S3Trio64DAC_Save; + pS3->DacRestore = S3Trio64DAC_Restore; +#if 0 + pS3->CursorInit = S3_CursorInit; /* FIXME broken */ +#endif + switch(pScrn->bitsPerPixel) { + case 8: + pS3->MaxClock = 135000; + break; + case 16: + pS3->MaxClock = 80000; + break; + case 24: + case 32: + pS3->MaxClock = 50000; + break; + } + pScrn->rgbBits = 6; + pS3->LoadPalette = S3GenericLoadPalette; + } + + if (pS3->RamDac == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Ramdac probe failed\n"); + return FALSE; + } + + pS3->RefClock = S3GetRefClock(pScrn); + + if (pS3->DacPreInit) + pS3->DacPreInit(pScrn); + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "RefClock: %d\n", + pS3->RefClock); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Max pixel clock at this depth is %d Mhz\n", + pS3->MaxClock / 1000); + + clockRanges = xnfcalloc(sizeof(ClockRange), 1); + clockRanges->next = NULL; + clockRanges->minClock = 16000; /* guess */ + clockRanges->maxClock = pS3->MaxClock; + clockRanges->clockIndex = -1; + clockRanges->interlaceAllowed = FALSE; /* not yet */ + clockRanges->doubleScanAllowed = FALSE; /* not yet */ + + i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, + pScrn->display->modes, clockRanges, + NULL, 256, 2048, pScrn->bitsPerPixel, + 128, 2048, pScrn->virtualX, + pScrn->display->virtualY, pScrn->videoRam * 1024, + LOOKUP_BEST_REFRESH); + + if (i == -1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "no valid modes left\n"); + S3FreeRec(pScrn); + return FALSE; + } + + xf86PruneDriverModes(pScrn); + + if (i == 0 || pScrn->modes == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "no valid modes found\n"); + S3FreeRec(pScrn); + return FALSE; + } + + xf86SetCrtcForModes(pScrn, 0); + pScrn->currentMode = pScrn->modes; + xf86PrintModes(pScrn); + xf86SetDpi(pScrn, 0, 0); + +#ifdef S3_USEFB + xf86LoadSubModule(pScrn, "fb"); + xf86LoaderReqSymbols("fbScreenInit", NULL); +#else + { + switch (pScrn->bitsPerPixel) { + case 8: + xf86LoadSubModule(pScrn, "cfb"); + xf86LoaderReqSymbols("cfbScreenInit", NULL); + break; + case 16: + xf86LoadSubModule(pScrn, "cfb16"); + xf86LoaderReqSymbols("cfb16ScreenInit", NULL); + break; + case 24: + xf86LoadSubModule(pScrn, "cfb24"); + xf86LoaderReqSymbols("cfb24ScreenInit", NULL); + break; + case 32: + xf86LoadSubModule(pScrn, "cfb32"); + xf86LoaderReqSymbols("cfb32ScreenInit", NULL); + break; + } + } +#endif + + if (!xf86LoadSubModule(pScrn, "xaa")) + return FALSE; + xf86LoaderReqSymLists(xaaSymbols, NULL); + + return TRUE; +} + + +static Bool S3ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, + char **argv) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + S3Ptr pS3 = S3PTR(pScrn); + + pScrn->fbOffset = 0; + + if (!S3MapMem(pScrn)) { + S3FreeRec(pScrn); + return FALSE; + } + + S3Save(pScrn); + + vgaHWBlankScreen(pScrn, TRUE); + + if (!S3ModeInit(pScrn, pScrn->currentMode)) + return FALSE; +#if 0 + S3Regdump(pScrn); +#endif + + S3SaveScreen(pScreen, SCREEN_SAVER_ON); + + miClearVisualTypes(); + 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; + } + + miSetPixmapDepths (); + +#ifdef S3_USEFB + if (!fbScreenInit(pScreen, pS3->FBBase, pScrn->virtualX, + pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth, pScrn->bitsPerPixel)) + return FALSE; +#else + { + int ret; + + switch(pScrn->bitsPerPixel) { + case 8: + ret = cfbScreenInit(pScreen, pS3->FBBase, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth); + break; + case 16: + ret = cfb16ScreenInit(pScreen, pS3->FBBase, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth); + break; + case 24: + ret = cfb24ScreenInit(pScreen, pS3->FBBase, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth); + break; + case 32: + ret = cfb32ScreenInit(pScreen, pS3->FBBase, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth); + break; + } + if (!ret) + return FALSE; + } +#endif + + xf86SetBlackWhitePixels(pScreen); + + if (pScrn->bitsPerPixel > 8) { + VisualPtr pVis; + + pVis = pScreen->visuals + pScreen->numVisuals; + while (--pVis >= pScreen->visuals) { + if ((pVis->class | DynamicClass) == DirectColor) { + pVis->offsetRed = pScrn->offset.red; + pVis->offsetGreen = pScrn->offset.green; + pVis->offsetBlue = pScrn->offset.blue; + pVis->redMask = pScrn->mask.red; + pVis->greenMask = pScrn->mask.green; + pVis->blueMask = pScrn->mask.blue; + } + } + } + + S3DGAInit(pScreen); + + miInitializeBackingStore(pScreen); + xf86SetBackingStore(pScreen); + + if (pS3->S3NewMMIO) { + if (S3AccelInitNewMMIO(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Acceleration enabled\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using NewMMIO\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Acceleration initialization failed\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Acceleration disabled\n"); + } + } else { + if (S3AccelInitPIO(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Acceleration enabled\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using PIO\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Acceleration initialization failed\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Acceleration disabled\n"); + } + } + + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + + /* hw cursor setup */ + if (pS3->CursorInit) { + if (pS3->CursorInit(pScreen)) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using HW cursor\n"); + else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "HW cursor initialization failed\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using SW cursor\n"); + } + } else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using SW cursor\n"); + + + + + if (!miCreateDefColormap(pScreen)) + return FALSE; + + if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, pS3->LoadPalette, NULL, + CMAP_RELOAD_ON_MODE_SWITCH)) + return FALSE; + + vgaHWBlankScreen(pScrn, FALSE); + + pScreen->SaveScreen = S3SaveScreen; + pS3->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = S3CloseScreen; + + xf86DPMSInit(pScreen, S3DisplayPowerManagementSet, 0); + +#if 0 + S3InitVideo(pScreen); +#endif + return TRUE; +} + + + + +static void S3Save(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + S3RegPtr save = &pS3->SavedRegs; + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr pVga = &hwp->SavedReg; + RamDacHWRecPtr pRAMDAC; + RamDacRegRecPtr RAMDACreg; + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + int i; + unsigned char cr5c; + + pRAMDAC = RAMDACHWPTR(pScrn); + RAMDACreg = &pRAMDAC->SavedReg; + + S3BankZero(pScrn); + + save->clock = inb(0x3cc); + + vgaHWSave(pScrn, pVga, VGA_SR_ALL); + + if (pS3->RamDac->RamDacType == TI3025_RAMDAC) { + outb(vgaCRIndex, 0x5c); + cr5c = inb(vgaCRReg); + } + + pS3->DacSave(pScrn); + + for(i=0; i<5; i++) { + outb(vgaCRIndex, 0x30 + i); + save->s3save[i] = inb(vgaCRReg); + outb(vgaCRIndex, 0x38 + i); + save->s3save[5 + i] = inb(vgaCRReg); + } + + for (i=0; i<16; i++) { + outb(vgaCRIndex, 0x40 + i); + save->s3syssave[i] = inb(vgaCRReg); + } + + outb(vgaCRIndex, 0x45); + inb(vgaCRReg); + outb(vgaCRIndex, 0x4a); + for(i=0; i<4; i++) { + save->color_stack[i] = inb(vgaCRReg); + outb(vgaCRReg, save->color_stack[i]); + } + + outb(vgaCRIndex, 0x45); + inb(vgaCRReg); + outb(vgaCRIndex, 0x4b); + for(i=4; i<8; i++) { + save->color_stack[i] = inb(vgaCRReg); + outb(vgaCRReg, save->color_stack[i]); + } + + for(i=0; i<16; i++) { + for (i=0; i<16; i++) { + if (!((1 << i) & 0x673b)) + continue; + outb(vgaCRIndex, 0x50 + i); + save->s3syssave[i + 16] = inb(vgaCRReg); + } + } + + if (pS3->RamDac->RamDacType == TI3025_RAMDAC) + save->s3syssave[0x0c + 16] = cr5c; + + for(i=32; i<46; i++) { + outb(vgaCRIndex, 0x40 + i); + save->s3syssave[i] = inb(vgaCRReg); + } +} + + +Bool S3SaveScreen(ScreenPtr pScreen, int mode) +{ + return vgaHWSaveScreen(pScreen, mode); +} + + +static void S3FreeScreen(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + vgaHWFreeHWRec(pScrn); + + S3FreeRec(pScrn); +} + + +Bool S3CloseScreen(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + S3Ptr pS3 = S3PTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + + if (pScrn->vtSema) { + vgaHWUnlock(hwp); + S3Restore(pScrn); + vgaHWLock(hwp); + S3UnmapMem(pScrn); + } + + if (pS3->DGAModes) + xfree(pS3->DGAModes); + pS3->DGAModes = NULL; + + pScrn->vtSema = FALSE; + pScreen->CloseScreen = pS3->CloseScreen; + + return (*pScreen->CloseScreen)(scrnIndex, pScreen); +} + + +Bool S3SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +{ + return S3ModeInit(xf86Screens[scrnIndex], mode); +} + + +static void S3GenericLoadPalette(ScrnInfoPtr pScrn, int numColors, + int *indicies, LOCO *colors, + VisualPtr pVisual) +{ + int i, index; + + for (i=0; i<numColors; i++) { + index = indicies[i]; + outb(0x3c8, index); + outb(0x3c9, colors[index].red); + outb(0x3c9, colors[index].green); + outb(0x3c9, colors[index].blue); + } +} + + +static Bool S3MapMem(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + + if (pS3->S3NewMMIO) { + pS3->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, + pS3->PciTag, pS3->IOAddress, + S3_NEWMMIO_REGSIZE); + if (!pS3->MMIOBase) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not map MMIO\n"); + return FALSE; + } + } + + pS3->FBBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, + pS3->PciTag, pS3->FBAddress, + pScrn->videoRam * 1024); + if (!pS3->FBBase) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not map framebuffer\n"); + return FALSE; + } + + pS3->FBCursorOffset = pScrn->videoRam - 1; + + return TRUE; +} + + +static void S3UnmapMem(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + + if (pS3->S3NewMMIO) + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pS3->MMIOBase, + S3_NEWMMIO_REGSIZE); + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pS3->FBBase, + pScrn->videoRam * 1024); + + return; +} + + +static int S3GetPixMuxShift(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + int shift = 0; + + if (pS3->Chipset == PCI_CHIP_968) + shift = 1; /* XXX IBMRGB */ + else if (pS3->Chipset == PCI_CHIP_TRIO) + shift = -(pS3->s3Bpp >> 1); + + return shift; +} + +static Bool S3ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + S3Ptr pS3 = S3PTR(pScrn); + S3RegPtr new = &pS3->ModeRegs; + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr pVga = &hwp->ModeReg; + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + int vgaIOBase = hwp->IOBase; + int r, n, m; + unsigned char tmp; + + pS3->pixMuxShift = S3GetPixMuxShift(pScrn); + + pS3->s3BppDisplayWidth = pScrn->displayWidth * pS3->s3Bpp; + pS3->HDisplay = mode->HDisplay; + + pS3->s3ScissB = ((pScrn->videoRam * 1024) / pS3->s3BppDisplayWidth) - 1; + pS3->s3ScissR = pScrn->displayWidth - 1; + + if (mode->HTotal == mode->CrtcHTotal) { + if (pS3->pixMuxShift > 0) { + /* XXX hack */ + mode->Flags |= V_PIXMUX; + + mode->CrtcHTotal >>= pS3->pixMuxShift; + mode->CrtcHDisplay >>= pS3->pixMuxShift; + mode->CrtcHSyncStart >>= pS3->pixMuxShift; + mode->CrtcHSyncEnd >>= pS3->pixMuxShift; + mode->CrtcHSkew >>= pS3->pixMuxShift; + } else if (pS3->pixMuxShift < 0) { + mode->Flags |= V_PIXMUX; + + mode->CrtcHTotal <<= -pS3->pixMuxShift; + mode->CrtcHDisplay <<= -pS3->pixMuxShift; + mode->CrtcHSyncStart <<= -pS3->pixMuxShift; + mode->CrtcHSyncEnd <<= -pS3->pixMuxShift; + mode->CrtcHSkew <<= -pS3->pixMuxShift; + } + } + + if (!vgaHWInit(pScrn, mode)) + return FALSE; + + pVga->MiscOutReg |= 0x0c; + pVga->Sequencer[0] = 0x03; + pVga->CRTC[19] = pS3->s3BppDisplayWidth >> 3; + pVga->CRTC[23] = 0xe3; + pVga->Attribute[0x11] = 0xff; + + if (vgaIOBase == 0x3b0) + pVga->MiscOutReg &= 0xfe; + else + pVga->MiscOutReg |= 0x01; + + /* ok i give up also, i'm writing in here */ + + vgaHWProtect(pScrn, TRUE); + + if (pS3->RamDac->RamDacType == TI3025_RAMDAC) { + outb(vgaCRIndex, 0x5c); + tmp = inb(vgaCRReg); + outb(vgaCRReg, tmp & 0xdf); + + S3OutTiIndReg(pScrn, TIDAC_ind_curs_ctrl, 0x7f, 0x00); + } + + pS3->DacInit(pScrn, mode); + + outb(0x3c2, pVga->MiscOutReg); + + for(r=1; r<5; r++) { + outw(0x3c4, (pVga->Sequencer[r] << 8) | r); + } + + for(r=0; r<25; r++) + outw(vgaCRIndex, (pVga->CRTC[r] << 8) | r); + + for(r=0; r<9; r++) { + outw(0x3ce, (pVga->Graphics[r] << 8) | r); + } + + inb(vgaIOBase + 0x0a); + + for(r=0; r<16; r++) { + outb(0x3c0, r); + outb(0x3c0, pVga->Attribute[r]); + } + for(r=16; r<21; r++) { + outb(0x3c0, r | 0x20); + outb(0x3c0, pVga->Attribute[r]); + } + + + new->cr31 = 0x8d; + outb(vgaCRIndex, 0x31); + outb(vgaCRReg, new->cr31); + + new->cr32 = 0x00; + outb(vgaCRIndex, 0x32); + outb(vgaCRReg, new->cr32); + + outb(vgaCRIndex, 0x33); + new->cr33 = inb(vgaCRReg) | 0x20; + if ((pS3->Chipset == PCI_CHIP_964_0) || + (pS3->Chipset == PCI_CHIP_964_1)) + new->cr33 = 0x20; + outb(vgaCRReg, new->cr33); + + new->cr34 = 0x10; + outb(vgaCRIndex, 0x34); + outb(vgaCRReg, new->cr34); + + new->cr3a = 0xb5; + outb(vgaCRIndex, 0x3a); + outb(vgaCRReg, new->cr3a); + + new->cr3b = (pVga->CRTC[0] + pVga->CRTC[4] + 1) / 2; + outb(vgaCRIndex, 0x3b); + outb(vgaCRIndex, 0x3b); + outb(vgaCRReg, new->cr3b); + + new->cr3c = pVga->CRTC[0] / 2; + outb(vgaCRIndex, 0x3c); + outb(vgaCRReg, new->cr3c); + + outb(vgaCRIndex, 0x40); + tmp = inb(vgaCRReg); + new->cr40 = (tmp & 0xf2) | 0x05; + outb(vgaCRReg, new->cr40); + + outb(vgaCRIndex, 0x43); + switch (pScrn->bitsPerPixel) { + case 24: + case 32: + new->cr43 = inb(vgaCRReg); + break; + case 15: + case 16: + if ((pS3->RamDac->RamDacType == IBM524_RAMDAC) || + (pS3->RamDac->RamDacType == IBM524A_RAMDAC) || + (pS3->RamDac->RamDacType == TI3025_RAMDAC)) + new->cr43 = 0x10; + else if (pS3->RamDac->RamDacType == TRIO64_RAMDAC) + new->cr43 = 0x09; + break; + case 8: + default: + new->cr43 = 0x00; + break; + } + outb(vgaCRReg, new->cr43); + + new->cr44 = 0x00; + outb(vgaCRIndex, 0x44); + outb(vgaCRReg, new->cr44); + + outb(vgaCRIndex, 0x45); + new->cr45 = inb(vgaCRReg) & 0xf2; + outb(vgaCRReg, new->cr45); + + outb(vgaCRIndex, 0x50); + tmp = inb(vgaCRReg) & ~0xf1; + switch (pScrn->bitsPerPixel) { + case 8: + break; + case 16: + tmp |= 0x10; + break; + case 24: + tmp |= 0x20; + break; + case 32: + tmp |= 0x30; + break; + } + + switch (pScrn->displayWidth) { + case 640: + tmp |= 0x40; + break; + case 800: + tmp |= 0x80; + break; + case 1152: + tmp |= 0x01; + break; + case 1280: + tmp |= 0xc0; + break; + case 1600: + tmp |= 0x81; + break; + } + new->cr50 = tmp; + outb(vgaCRReg, new->cr50); + + + outb(vgaCRIndex, 0x51); + new->cr51 = (inb(vgaCRReg) & 0xc0) | + ((pS3->s3BppDisplayWidth >> 7) & 0x30); + outb(vgaCRReg, new->cr51); + + outb(vgaCRIndex, 0x53); + new->cr53 = inb(vgaCRReg); + if (pS3->S3NewMMIO) + new->cr53 |= 0x18; + else + new->cr53 &= ~0x18; + outb(vgaCRReg, new->cr53); + + n = 255; + outb(vgaCRIndex, 0x54); + { + int clock2, mclk; + + clock2 = mode->Clock * pS3->s3Bpp; + if (pScrn->videoRam < 2048) + clock2 *= 2; + mclk = pS3->mclk; + m = (int)((mclk/1000.0*.72+16.867)*89.736/(clock2/1000.0+39)-21.1543); + if (pScrn->videoRam < 2048) + m /= 2; + if (m >31) + m = 31; + else if (m < 0) { + m = 0; + n = 16; + } + } + new->cr54 = m << 3; + outb(vgaCRReg, new->cr54); + + if (n < 0) + n = 0; + else if (n > 255) + n = 255; + outb(vgaCRIndex, 0x60); + new->cr60 = n; + outb(vgaCRReg, new->cr60); + + outb(vgaCRIndex, 0x55); + new->cr55 = (inb(vgaCRReg) & 0x08) | 0x40; + outb(vgaCRReg, new->cr55); + + outb(vgaCRIndex, 0x5e); + new->cr5e = (((mode->CrtcVTotal - 2) & 0x400) >> 10) | + (((mode->CrtcVDisplay - 1) & 0x400) >> 9) | + (((mode->CrtcVSyncStart) & 0x400) >> 8) | + (((mode->CrtcVSyncStart) & 0x400) >> 6) | 0x40; + outb(vgaCRReg, new->cr5e); + + { + int i; + unsigned int j; + + i = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) | + ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) | + ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) | + ((mode->CrtcHSyncStart & 0x800) >> 7); + if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 64) + i |= 0x08; + if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 32) + i |= 0x20; + + outb(vgaCRIndex, 0x3b); + j = ((pVga->CRTC[0] + ((i & 0x01) << 8) + + pVga->CRTC[4] + ((i & 0x10) << 4) + 1) / 2); + + if (j - (pVga->CRTC[4] + ((i & 0x10) << 4)) < 4) { + if (pVga->CRTC[4] + ((i & 0x10) << 4) + 4 <= pVga->CRTC[0] + ((i & 0x01) << 8)) + j = pVga->CRTC[4] + ((i & 0x10) << 4) + 4; + else + j = pVga->CRTC[0] + ((i & 0x01) << 8) + 1; + } + + new->cr3b = j & 0xff; + outb(vgaCRReg, new->cr3b); + i |= (j & 0x100) >> 2; + + outb(vgaCRIndex, 0x3c); + new->cr3c = (pVga->CRTC[0] + ((i & 0x01) << 8)) / 2; + outb(vgaCRReg, new->cr3c); + + outb(vgaCRIndex, 0x5d); + new->cr5d = (inb(vgaCRReg) & 0x80) | i; + outb(vgaCRReg, new->cr5d); + } + + { + int i; + + if (pScrn->videoRam > 1024) + i = mode->HDisplay * pS3->s3Bpp / 8 + 1; + else + i = mode->HDisplay * pS3->s3Bpp / 4 + 1; + + outb(vgaCRIndex, 0x61); + tmp = 0x80 | (inb(vgaCRReg) & 0x60) | (i >> 8); + new->cr61 = tmp; + outb(vgaCRReg, new->cr61); + outb(vgaCRIndex, 0x62); + new->cr62 = i & 0xff; + outb(vgaCRReg, new->cr62); + } + + outb(vgaCRIndex, 0x42); + new->cr42 = inb(vgaCRReg) & ~0x20; + outb(vgaCRReg, new->cr42); + + if (pS3->Chipset == PCI_CHIP_968) { + unsigned char a; + + outb(vgaCRIndex, 0x67); + a = inb(vgaCRReg) & 0xfe; +#if 0 + switch (pScrn->depth) { + case 8: + break; + case 15: + a |= (3 << 4); + break; + case 16: + a |= (5 << 4); + a |= (3 << 2); /* streams */ + break; + case 24: + a |= (13 << 4); + a |= (3 << 2); /* streams */ + break; + } +#endif + outb(vgaCRReg, a); + + outb(vgaCRIndex, 0x6d); + outb(vgaCRReg, 0x00); + } + + if ((pS3->Chipset == PCI_CHIP_964_0) || + (pS3->Chipset == PCI_CHIP_964_1)) { + unsigned char bdelay; + + outb(vgaCRIndex, 0x6d); + bdelay = inb(vgaCRReg); + + if (pS3->RamDac->RamDacType == TI3025_RAMDAC) { + if (pS3->s3Bpp == 1) { + if (mode->Clock > 80000) + bdelay = 0x02; + else + bdelay = 0x03; + } else if (pS3->s3Bpp == 2) { + if (mode->Clock > 80000) + bdelay = 0x00; + else + bdelay = 0x01; + } else + bdelay = 0x00; + } + + outb(vgaCRReg, bdelay); + } + + outb(vgaCRIndex, 0x66); + new->cr66 = inb(vgaCRReg) | 0x80; /* XXX no newmmio */ + outb(vgaCRReg, new->cr66); + + pScrn->AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + vgaHWProtect(pScrn, FALSE); + + if (pScrn->displayWidth == 1024) + outw(ADVFUNC_CNTL, 0x0007); + else + outw(ADVFUNC_CNTL, 0x0003); + + outb(0x3c6, 0x00); + + outw(SUBSYS_CNTL, 0x8000 | 0x1000); + outw(SUBSYS_CNTL, 0x4000 | 0x1000); + + inw(SUBSYS_STAT); + + outw(0xbee8, 0x5000 | 0x0004 | 0x000c); + + outb(0x3c6, 0xff); + + new->cr59 = pS3->FBAddress >> 24; + new->cr5a = pS3->FBAddress >> 16; + + if (pScrn->videoRam <= 1024) + new->cr58 = 0x15; + else if (pScrn->videoRam <= 2048) + new->cr58 = 0x16; + else + new->cr58 = 0x17; + + if (pS3->Chipset == PCI_CHIP_968) + new->cr58 = 0x52; + else if ((pS3->Chipset == PCI_CHIP_964_0) || + (pS3->Chipset == PCI_CHIP_964_1)) + new->cr58 |= 0x40; + + outb(vgaCRIndex, 0x59); + outb(vgaCRReg, new->cr59); + outb(vgaCRIndex, 0x5a); + outb(vgaCRReg, new->cr5a); + outb(vgaCRIndex, 0x58); + outb(vgaCRReg, new->cr58); + + WaitQueue(5); + SET_SCISSORS(0, 0, pS3->s3ScissR, pS3->s3ScissB); + + outb(vgaCRIndex, 0x6f); + +#if 0 + if (((pScrn->bitsPerPixel == 16) || + (pScrn->bitsPerPixel == 24)) && (pS3->S3NewMMIO)) + S3InitStreams(pScrn, mode); +#endif + + return TRUE; +} + + +static Bool S3EnterVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + if (!S3ModeInit(pScrn, pScrn->currentMode)) + return FALSE; + + return TRUE; +} + + +static void S3Restore(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + S3RegPtr restore = &pS3->SavedRegs; + vgaHWPtr hwp = VGAHWPTR(pScrn); + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + int i; + + vgaHWProtect(pScrn, TRUE); + + WaitQueue(8); + + S3BankZero(pScrn); + + outw(ADVFUNC_CNTL, 0x0000); + + if (pS3->S3NewMMIO) { + outb(vgaCRIndex, 0x53); + outb(vgaCRReg, 0x00); + } + + if (pS3->RamDac->RamDacType == TI3025_RAMDAC) { + outb(vgaCRIndex, 0x5c); + outb(vgaCRReg, restore->s3syssave[0x0c + 16]); + } + + pS3->DacRestore(pScrn); + + for(i=32; i<46; i++) { + outb(vgaCRIndex, 0x40 + i); + outb(vgaCRReg, restore->s3syssave[i]); + } + + for(i=0; i<16; i++) { + if (!((1 << i) & 0x673b)) + continue; + outb(vgaCRIndex, 0x50 + i); + outb(vgaCRReg, restore->s3syssave[i+16]); + } + + for(i=0; i<5; i++) { + outb(vgaCRIndex, 0x30 + i); + outb(vgaCRReg, restore->s3save[i]); + outb(vgaCRIndex, 0x38 + i); + outb(vgaCRReg, restore->s3save[i + 5]); + } + + for(i=0; i<16; i++) { + outb(vgaCRIndex, 0x40 + i); + outb(vgaCRReg, restore->s3syssave[i]); + } + + outb(vgaCRIndex, 0x45); + inb(vgaCRReg); + outb(vgaCRIndex, 0x4a); + for(i=0; i<4; i++) + outb(vgaCRReg, restore->color_stack[i]); + + outb(vgaCRIndex, 0x45); + inb(vgaCRReg); + outb(vgaCRIndex, 0x4b); + for(i=4; i<8; i++) + outb(vgaCRReg, restore->color_stack[i]); + + vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_ALL); + + outb(0x3c2, restore->clock); + + vgaHWProtect(pScrn, FALSE); + +} + + +static void S3LeaveVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + S3Restore(pScrn); + + return; +} + + +static void S3AdjustFrame(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + S3Ptr pS3 = S3PTR(pScrn); + S3RegPtr regs = &pS3->ModeRegs; + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + int base, orig_base; + unsigned char tmp; + + if (x > pScrn->displayWidth - pS3->HDisplay) + x = pScrn->displayWidth - pS3->HDisplay; + + orig_base = (y * pScrn->displayWidth + x) * pS3->s3Bpp; + base = (orig_base >> 2) & ~1; + + /* for IBMRGB and TI only */ + if (pS3->RamDac->RamDacType == IBM524A_RAMDAC) + { + int px, py, a; + + miPointerPosition(&px, &py); + + if (pS3->s3Bpp == 1) + a = 4 - 1; + else + a = 8 - 1; + if (px-x > pS3->HDisplay/2) + base = ((orig_base + a*4) >> 2) & ~1; + base &= ~a; + } + + outb(vgaCRIndex, 0x31); + outb(vgaCRReg, ((base & 0x030000) >> 12) | regs->cr31); + regs->cr51 &= ~0x03; + regs->cr51 |= ((base & 0x0c0000) >> 18); + outb(vgaCRIndex, 0x51); + tmp = (inb(vgaCRReg) & ~0x03) | (regs->cr51 & 0x03); + outb(vgaCRReg, tmp); + + outw(vgaCRIndex, (base & 0x00ff00) | 0x0c); + outw(vgaCRIndex, ((base & 0x00ff) << 8) | 0x0d); +} + + +void S3Regdump(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + S3RegPtr regs = &pS3->ModeRegs; + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + +#if 1 + outb(vgaCRIndex, 0x31); + ErrorF("cr31 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x32); + ErrorF("cr32 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x33); + ErrorF("cr33 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x34); + ErrorF("cr34 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x3a); + ErrorF("cr3a = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x3b); + ErrorF("cr3b = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x3c); + ErrorF("cr3c = 0x%x\n", inb(vgaCRReg)); + + outb(vgaCRIndex, 0x40); + ErrorF("cr40 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x42); + ErrorF("cr42 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x43); + ErrorF("cr43 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x44); + ErrorF("cr44 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x45); + ErrorF("cr45 = 0x%x\n", inb(vgaCRReg)); + + outb(vgaCRIndex, 0x50); + ErrorF("cr50 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x51); + ErrorF("cr51 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x53); + ErrorF("cr53 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x54); + ErrorF("cr54 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x55); + ErrorF("cr55 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x58); + ErrorF("cr58 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x59); + ErrorF("cr59 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x5a); + ErrorF("cr5a = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x5d); + ErrorF("cr5d = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x5e); + ErrorF("cr5e = 0x%x\n", inb(vgaCRReg)); + + outb(vgaCRIndex, 0x60); + ErrorF("cr60 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x61); + ErrorF("cr61 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x62); + ErrorF("cr62 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x65); + ErrorF("cr65 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x66); + ErrorF("cr66 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x67); + ErrorF("cr67 = 0x%x\n", inb(vgaCRReg)); + outb(vgaCRIndex, 0x6d); + ErrorF("cr6d = 0x%x\n", inb(vgaCRReg)); + +#else + { + int j; + + for(j=0; j<0x100; j++) { + outb(vgaCRIndex, j); + ErrorF("CRTC 0x%x = 0x%x\n", j, inb(vgaCRReg)); + } + } +#endif + +#if 0 + ErrorF("DAC regs\n"); + + { + int j; + + for(j=0; j<0x100; j++) + ErrorF("0x%x = 0x%x\n", j, S3InTiIndReg(pScrn, j)); +#if 0 + outb(vgaCRIndex, 0x22); + ErrorF("cr22 = 0x%x\n", inb(vgaCRReg)); +#endif + } +#endif +} + + +void S3BankZero(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + unsigned char tmp; + int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; + + outb(vgaCRIndex, 0x35); + tmp = inb(vgaCRReg) & 0xf0; + outb(vgaCRReg, tmp); + + outb(vgaCRIndex, 0x51); + tmp = inb(vgaCRReg) & 0xf3; + outb(vgaCRReg, tmp); +} + + + +static void S3DisplayPowerManagementSet(ScrnInfoPtr pScrn, + int PowerManagementMode, int flags) +{ + vgaHWDPMSSet(pScrn, PowerManagementMode, flags); +} + diff --git a/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_reg.h b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_reg.h new file mode 100644 index 000000000..63646d99b --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_reg.h @@ -0,0 +1,262 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3/s3_reg.h,v 1.1 2001/07/02 10:46:04 alanh Exp $ */ + +#ifndef _S3_REG_H +#define _S3_REG_H + +#include "compiler.h" + +extern short s3alu[16]; + +#define S3_NEWMMIO_REGBASE 0x1000000 /* 16MB */ +#define S3_NEWMMIO_REGSIZE 0x10000 /* 64KB */ + +#define ADVFUNC_CNTL 0x4ae8 +#define SUBSYS_STAT 0x42e8 +#define SUBSYS_CNTL 0x42e8 +#define CUR_Y 0x82e8 +#define CUR_X 0x86e8 +#define CUR_Y2 0x82ea +#define CUR_X2 0x86ea +#define DESTY_AXSTP 0x8ae8 +#define DESTX_DIASTP 0x8ee8 +#define DESTY_AXSTP2 0x8aea +#define DESTX_DIASTP2 0x8eea +#define ERR_TERM 0x92e8 +#define ERR_TERM2 0x92ea +#define MAJ_AXIS_PCNT 0x96e8 +#define MAJ_AXIS_PCNT2 0x96ea +#define GP_STAT 0x9ae8 +#define CMD 0x9ae8 +#define CMD2 0x9aea +#define BKGD_COLOR 0xa2e8 +#define FRGD_COLOR 0xa6e8 +#define WRT_MASK 0xaae8 +#define RD_MASK 0xaee8 +#define COLOR_CMP 0xb2e8 +#define BKGD_MIX 0xb6e8 +#define FRGD_MIX 0xbae8 +#define MULTIFUNC_CNTL 0xbee8 +#define PIX_TRANS 0xe2e8 +#define PIX_TRANS_EXT 0xe2ea + +/* Graphics Processor Status Register */ +#define GPBUSY 0x0200 + +/* Command Register */ +#define CMD_NOP 0x0000 +#define CMD_LINE 0x2000 +#define CMD_RECT 0x4000 +#define CMD_RECTV1 0x6000 +#define CMD_RECTV2 0x8000 +#define CMD_LINEAF 0xa000 +#define CMD_BITBLT 0xc000 +#define CMD_PFILL 0xe000 +#define CMD_OP_MSK 0xf000 +#define BYTSEQ 0x1000 +#define _16BIT 0x0200 +#define _32BIT 0x0400 +#define PCDATA 0x0100 +#define INC_Y 0x0080 +#define YMAJAXIS 0x0040 +#define INC_X 0x0020 +#define DRAW 0x0010 +#define LINETYPE 0x0008 +#define LASTPIX 0x0004 +#define PLANAR 0x0002 +#define WRTDATA 0x0001 + + +/* Background Mix Register */ +#define BSS_BKGDCOL 0x0000 +#define BSS_FRGDCOL 0x0020 +#define BSS_PCDATA 0x0040 +#define BSS_BITBLT 0x0060 + +/* Foreground Mix Register */ +#define FSS_BKGDCOL 0x0000 +#define FSS_FRGDCOL 0x0020 +#define FSS_PCDATA 0x0040 +#define FSS_BITBLT 0x0060 + +#define PIX_CNTL 0xa000 +#define MIN_AXIS_PCNT 0x0000 + +/* Pixel Control Register */ +#define MIXSEL_EXPPC 0x0080 + +#define SCISSORS_T 0x1000 +#define SCISSORS_L 0x2000 +#define SCISSORS_B 0x3000 +#define SCISSORS_R 0x4000 +#define MULT_MISC2 0xd000 +#define MULT_MISC 0xe000 + + +#define MIX_MASK 0x001f + +#define MIX_NOT_DST 0x0000 +#define MIX_0 0x0001 +#define MIX_1 0x0002 +#define MIX_DST 0x0003 +#define MIX_NOT_SRC 0x0004 +#define MIX_XOR 0x0005 +#define MIX_XNOR 0x0006 +#define MIX_SRC 0x0007 +#define MIX_NAND 0x0008 +#define MIX_NOT_SRC_OR_DST 0x0009 +#define MIX_SRC_OR_NOT_DST 0x000a +#define MIX_OR 0x000b +#define MIX_AND 0x000c +#define MIX_SRC_AND_NOT_DST 0x000d +#define MIX_NOT_SRC_AND_DST 0x000e +#define MIX_NOR 0x000f + +#define MIX_MIN 0x0010 +#define MIX_DST_MINUS_SRC 0x0011 +#define MIX_SRC_MINUS_DST 0x0012 +#define MIX_PLUS 0x0013 +#define MIX_MAX 0x0014 +#define MIX_HALF__DST_MINUS_SRC 0x0015 +#define MIX_HALF__SRC_MINUS_DST 0x0016 +#define MIX_AVERAGE 0x0017 +#define MIX_DST_MINUS_SRC_SAT 0x0018 +#define MIX_SRC_MINUS_DST_SAT 0x001a +#define MIX_HALF__DST_MINUS_SRC_SAT 0x001c +#define MIX_HALF__SRC_MINUS_DST_SAT 0x001e +#define MIX_AVERAGE_SAT 0x001f + +/* + * Short Stroke Vector Transfer Register (The angular Defs also apply to +the + * Command Register + */ +#define VECDIR_000 0x0000 +#define VECDIR_045 0x0020 +#define VECDIR_090 0x0040 +#define VECDIR_135 0x0060 +#define VECDIR_180 0x0080 +#define VECDIR_225 0x00a0 +#define VECDIR_270 0x00c0 +#define VECDIR_315 0x00e0 +#define SSVDRAW 0x0010 + + +#define S3_OUTW(p,n) outw(p, n) +#define S3_OUTL(p,n) outl(p, n) +#define S3_OUTW32(p,n) if (pS3->s3Bpp > 2) { \ + outw(p, n); \ + outw(p, (n) >> 16); \ + } else outw(p, n) + + +#define WaitIdle() do { \ + mem_barrier(); \ + while(inw(GP_STAT) & GPBUSY); \ + } while(0) + + +#ifdef S3_NEWMMIO +#include "newmmio.h" + +/* + * streams regs + */ +#define SET_BLEND_CNTL(val) ((mmtr)s3MmioMem)->streams_regs.regs.blend_cntl = (val) +#define SET_PSTREAM_CNTL(val) ((mmtr)s3MmioMem)->streams_regs.regs.prim_stream_cntl = (val) +#define SET_PSTREAM_FBADDR(val) ((mmtr)s3MmioMem)->streams_regs.regs.prim_fbaddr0 = (val) +#define SET_PSTREAM_STRIDE(val) ((mmtr)s3MmioMem)->streams_regs.regs.prim_stream_stride = (val) +#define SET_PSTREAM_START(val) ((mmtr)s3MmioMem)->streams_regs.regs.prim_start_coord = (val) +#define SET_PSTREAM_WIND(val) ((mmtr)s3MmioMem)->streams_regs.regs.prim_window_size = (val) +#define SET_SSTREAM_CNTL(val) ((mmtr)s3MmioMem)->streams_regs.regs.second_stream_cntl = (val) +#define SET_SSTRETCH(val) ((mmtr)s3MmioMem)->streams_regs.regs.second_stream_stretch = (val) +#define SET_SSTREAM_FBADDR(val) ((mmtr)s3MmioMem)->streams_regs.regs.second_fbaddr0 = (val) +#define SET_SSTREAM_STRIDE(val) ((mmtr)s3MmioMem)->streams_regs.regs.second_stream_stride = (val) +#define SET_SSTREAM_START(val) ((mmtr)s3MmioMem)->streams_regs.regs.second_start_coord = (val) +#define SET_SSTREAM_WIND(val) ((mmtr)s3MmioMem)->streams_regs.regs.second_window_size = (val) +#define SET_K1_VSCALE(val) ((mmtr)s3MmioMem)->streams_regs.regs.k1 = (val) +#define SET_K2_VSCALE(val) ((mmtr)s3MmioMem)->streams_regs.regs.k2 = (val) +#define SET_DDA_VERT(val) ((mmtr)s3MmioMem)->streams_regs.regs.dda_vert = (val) +#define SET_CHROMA_KEY(val) ((mmtr)s3MmioMem)->streams_regs.regs.col_chroma_key_cntl = (val) +#define SET_DOUBLE_BUFFER(val) ((mmtr)s3MmioMem)->streams_regs.regs.double_buffer = (val) +#define SET_OPAQUE_OVERLAY(val) ((mmtr)s3MmioMem)->streams_regs.regs.opaq_overlay_cntl = (val) + +#else + +#define CMD_REG_WIDTH 0x0000 + +#define WaitQueue(n) do { \ + mem_barrier(); \ + while(inb(GP_STAT) & (0x0100 >> (n))); \ + } while (0) + +#define WaitQueue16_32(n16,n32) \ + if (pS3->s3Bpp <= 2) { \ + WaitQueue(n16); \ + } else { \ + WaitQueue(n32); \ + } + +#define VerticalRetraceWait() \ + { \ + outb(vgaCRIndex, 0x17); \ + if (inb(vgaCRReg) & 0x80) { \ + while ((inb(vgaCRIndex-4+0x0a) & 0x08) == 0x00); \ + while ((inb(vgaCRIndex-4+0x0a) & 0x08) == 0x08); \ + } \ + } + +/* accel commands */ + +#define SET_PIX_CNTL(val) S3_OUTW(MULTIFUNC_CNTL, PIX_CNTL | (val)) + +#define SET_FRGD_COLOR(col) S3_OUTW32(FRGD_COLOR, col) +#define SET_BKGD_COLOR(col) S3_OUTW32(BKGD_COLOR, col) + +#define SET_FRGD_MIX(fmix) S3_OUTW(FRGD_MIX, (fmix)) +#define SET_WRT_MASK(mask) S3_OUTW32(WRT_MASK, mask) + +#define SET_CUR_X(cur_x) S3_OUTW(CUR_X, cur_x) +#define SET_CUR_Y(cur_y) S3_OUTW(CUR_Y, cur_y) +#define SET_CUR_X2(cur_x) S3_OUTW(CUR_X2, cur_x) +#define SET_CUR_Y2(cur_y) S3_OUTW(CUR_Y2, cur_y) + +#define SET_CURPT(cur_x, cur_y) { \ + SET_CUR_X(cur_x); \ + SET_CUR_Y(cur_y); \ + } + +#define SET_DESTSTP(x,y) { \ + S3_OUTW(DESTX_DIASTP, x); \ + S3_OUTW(DESTY_AXSTP, y); \ + } + +#define SET_AXIS_PCNT(maj, min) { \ + S3_OUTW(MAJ_AXIS_PCNT, maj); \ + S3_OUTW(MULTIFUNC_CNTL, MIN_AXIS_PCNT | (min)); \ + } + +#define SET_CMD(cmd) S3_OUTW(CMD, cmd) + +#define SET_SCISSORS(x1,y1,x2,y2) { \ + S3_OUTW(MULTIFUNC_CNTL, SCISSORS_T | (y1)); \ + S3_OUTW(MULTIFUNC_CNTL, SCISSORS_L | (x1)); \ + S3_OUTW(MULTIFUNC_CNTL, SCISSORS_R | (x2)); \ + S3_OUTW(MULTIFUNC_CNTL, SCISSORS_B | (y2)); \ + } + +#define SET_MULT_MISC(val) S3_OUTW(MULTIFUNC_CNTL, MULT_MISC | (val)) + +#define SET_COLOR_CMP(color) S3_OUTW32(COLOR_CMP, color) + +#define SET_PIX_TRANS_W(val) S3_OUTW(PIX_TRANS, val) + +#define SET_PIX_TRANS_L(val) outl(PIX_TRANS, val) + +#define SET_ERR_TERM(err) S3_OUTW(ERR_TERM, err) +#define SET_ERR_TERM2(err) S3_OUTW(ERR_TERM2, err) + +#define SET_MAJ_AXIS_PCNT(maj) S3_OUTW(MAJ_AXIS_PCNT, maj) +#endif + + +#endif /* _S3_REG_H */ diff --git a/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_video.c b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_video.c new file mode 100644 index 000000000..2a60366c6 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_video.c @@ -0,0 +1,669 @@ +/* + * Copyright 2001 Ani Joshi <ajoshi@unixbox.com> + * + * XFree86 4.x driver for S3 chipsets + * + * + * 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 Ani Joshi not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Ani Joshi makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ANI JOSHI 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. + * + * + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3/s3_video.c,v 1.2 2001/08/15 11:54:27 tsi Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +#include "compiler.h" + +#include "s3.h" +#include "s3_reg.h" + + +#define CLIENT_VIDEO_ON 0x04 +#define S3_MAX_PORTS 1 +#define NUM_FORMATS_OVERLAY 4 +#define NUM_FORMATS_TEXTURE 4 + + +static XF86VideoAdaptorPtr S3AllocAdaptor(ScrnInfoPtr pScrn); +static XF86VideoAdaptorPtr S3SetupImageVideoOverlay(ScreenPtr); +static int S3SetPortAttributeOverlay(ScrnInfoPtr, Atom, INT32, pointer); +static int S3GetPortAttributeOverlay(ScrnInfoPtr, Atom ,INT32 *, pointer); +static void S3StopVideo(ScrnInfoPtr, pointer, Bool); +static void S3QueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, + unsigned int *, unsigned int *, pointer); +static int S3PutImage(ScrnInfoPtr, short, short, short, short, short, + short, short, short, int, unsigned char*, short, + short, Bool, RegionPtr, pointer); +static int S3QueryImageAttributes(ScrnInfoPtr, int, unsigned short *, + unsigned short *, int *, int *); +static void S3ResetVideoOverlay(ScrnInfoPtr); + + + +void S3InitVideo(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + S3Ptr pS3 = S3PTR(pScrn); + XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; + XF86VideoAdaptorPtr newAdaptor = NULL; + int num_adaptors; + + if (((pScrn->bitsPerPixel == 16) || + (pScrn->bitsPerPixel == 24)) && (pS3->S3NewMMIO)) { + newAdaptor = S3SetupImageVideoOverlay(pScreen); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using overlay video\n"); + } else + return; + + num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); + + if(newAdaptor) { + if(!num_adaptors) { + num_adaptors = 1; + adaptors = &newAdaptor; + } else { + newAdaptors = /* need to free this someplace */ + xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); + if(newAdaptors) { + memcpy(newAdaptors, adaptors, num_adaptors * + sizeof(XF86VideoAdaptorPtr)); + newAdaptors[num_adaptors] = newAdaptor; + adaptors = newAdaptors; + num_adaptors++; + } + } + } + + if(num_adaptors) + xf86XVScreenInit(pScreen, adaptors, num_adaptors); + + if(newAdaptors) + xfree(newAdaptors); +} + + +/* client libraries expect an encoding */ +static XF86VideoEncodingRec DummyEncoding[2] = +{ + { /* overlay limit */ + 0, + "XV_IMAGE", + 1024, 1024, + {1, 1} + }, + { /* texture limit */ + 0, + "XV_IMAGE", + 2046, 2046, + {1, 1} + } +}; + + + + +static XF86VideoFormatRec Formats[NUM_FORMATS_TEXTURE] = +{ + /*{15, TrueColor},*/ {16, TrueColor}, {24, TrueColor} /* , + {15, DirectColor}*/, {16, DirectColor}, {24, DirectColor} +}; + + + +#define NUM_IMAGES 3 + +static XF86ImageRec Images[NUM_IMAGES] = +{ + XVIMAGE_YUY2, + /* As in mga, YV12 & I420 are converted to YUY2 on the fly by */ + /* copy over conversion. */ + XVIMAGE_YV12, + XVIMAGE_I420 + /* XVIMAGE_UYVY */ +}; + + + +static int S3SetPortAttributeOverlay(ScrnInfoPtr pScrn, Atom attribute, + INT32 value, pointer data) +{ + return BadMatch; +} + + +static int S3GetPortAttributeOverlay(ScrnInfoPtr pScrn, Atom attribute, + INT32 *value, pointer data) +{ + return BadMatch; +} + + + +static void S3QueryBestSize(ScrnInfoPtr pScrn, Bool motion, short vid_w, + short vid_h, short drw_w, short drw_h, + unsigned int *p_w, unsigned int *p_h, + pointer data) +{ + *p_w = drw_w; + *p_h = drw_h; +} + + + +static void S3CopyData(unsigned char *src, unsigned char *dst, + int srcPitch, int dstPitch, int h, int w) +{ + w <<= 1; + while (h--) { + memcpy(dst, src, w); + src += srcPitch; + dst += dstPitch; + } +} + + +static void S3CopyMungedData(unsigned char *src1, unsigned char *src2, + unsigned char *src3, unsigned char *dst1, + int srcPitch, int srcPitch2, int dstPitch, + int h, int w) +{ + CARD32 *dst = (CARD32*)dst1; + int i, j; + + dstPitch >>= 2; + w >>= 1; + + for(j = 0; j < h; j++) { + for(i = 0; i < w; i++) { + dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) | + (src3[i] << 8) | (src2[i] << 24); + } + dst += dstPitch; + src1 += srcPitch; + if(j & 1) { + src2 += srcPitch2; + src3 += srcPitch2; + } + } +} + + + +static void S3ResetVideoOverlay(ScrnInfoPtr pScrn) +{ +} + + +static XF86VideoAdaptorPtr S3AllocAdaptor(ScrnInfoPtr pScrn) +{ + S3Ptr pS3 = S3PTR(pScrn); + XF86VideoAdaptorPtr adapt; + S3PortPrivPtr pPriv; + int i; + + if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn))) + return NULL; + + if(!(pPriv = xcalloc(1, sizeof(S3PortPrivRec) + + (sizeof(DevUnion) * S3_MAX_PORTS)))) + { + xfree(adapt); + return NULL; + } + + adapt->pPortPrivates = (DevUnion*)(&pPriv[1]); + + for(i = 0; i < S3_MAX_PORTS; i++) + adapt->pPortPrivates[i].val = i; + + pPriv->colorKey = (1 << pScrn->offset.red) | (1 << pScrn->offset.green) | + (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue); + + pPriv->videoStatus = 0; + pPriv->lastPort = -1; + + pS3->adaptor = adapt; + pS3->portPrivate = pPriv; + + return adapt; +} + + +static XF86VideoAdaptorPtr S3SetupImageVideoOverlay(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + S3Ptr pS3 = S3PTR(pScrn); + XF86VideoAdaptorPtr adapt; + + adapt = S3AllocAdaptor(pScrn); + + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adapt->name = "S3 Backend Scaler"; + adapt->nEncodings = 1; + adapt->pEncodings = &DummyEncoding[0]; + adapt->nFormats = NUM_FORMATS_OVERLAY; + adapt->pFormats = Formats; + adapt->nPorts = 1; + adapt->pAttributes = NULL /*Attributes*/; + adapt->nImages = 3; + adapt->nAttributes = 0; + + adapt->pImages = Images; + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; + adapt->StopVideo = S3StopVideo; + /* Empty Attrib functions - required anyway */ + adapt->SetPortAttribute = S3SetPortAttributeOverlay; + adapt->GetPortAttribute = S3GetPortAttributeOverlay; + adapt->QueryBestSize = S3QueryBestSize; + adapt->PutImage = S3PutImage; + adapt->QueryImageAttributes = S3QueryImageAttributes; + + /* gotta uninit this someplace */ + REGION_INIT(pScreen, &(pS3->portPrivate->clip), NullBox, 0); + + S3ResetVideoOverlay(pScrn); + + return adapt; +} + + + +static Bool +RegionsEqual(RegionPtr A, RegionPtr B) +{ + int *dataA, *dataB; + int num; + + num = REGION_NUM_RECTS(A); + if(num != REGION_NUM_RECTS(B)) + return FALSE; + + if((A->extents.x1 != B->extents.x1) || + (A->extents.x2 != B->extents.x2) || + (A->extents.y1 != B->extents.y1) || + (A->extents.y2 != B->extents.y2)) + return FALSE; + + dataA = (int*)REGION_RECTS(A); + dataB = (int*)REGION_RECTS(B); + + while(num--) { + if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])) + return FALSE; + dataA += 2; + dataB += 2; + } + + return TRUE; +} + + + +static Bool S3ClipVideo(BoxPtr dst, INT32 *x1, INT32 *x2, INT32 *y1, INT32 *y2, + RegionPtr reg, INT32 width, INT32 height) +{ + INT32 vscale, hscale, delta; + BoxPtr extents = REGION_EXTENTS(DummyScreen, reg); + int diff; + + hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1); + vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1); + + *x1 <<= 16; *x2 <<= 16; + *y1 <<= 16; *y2 <<= 16; + + diff = extents->x1 - dst->x1; + if(diff > 0) { + dst->x1 = extents->x1; + *x1 += diff * hscale; + } + diff = dst->x2 - extents->x2; + if(diff > 0) { + dst->x2 = extents->x2; + *x2 -= diff * hscale; + } + diff = extents->y1 - dst->y1; + if(diff > 0) { + dst->y1 = extents->y1; + *y1 += diff * vscale; + } + diff = dst->y2 - extents->y2; + if(diff > 0) { + dst->y2 = extents->y2; + *y2 -= diff * vscale; + } + + if(*x1 < 0) { + diff = (- *x1 + hscale - 1)/ hscale; + dst->x1 += diff; + *x1 += diff * hscale; + } + delta = *x2 - (width << 16); + if(delta > 0) { + diff = (delta + hscale - 1)/ hscale; + dst->x2 -= diff; + *x2 -= diff * hscale; + } + if(*x1 >= *x2) return FALSE; + + if(*y1 < 0) { + diff = (- *y1 + vscale - 1)/ vscale; + dst->y1 += diff; + *y1 += diff * vscale; + } + delta = *y2 - (height << 16); + if(delta > 0) { + diff = (delta + vscale - 1)/ vscale; + dst->y2 -= diff; + *y2 -= diff * vscale; + } + if(*y1 >= *y2) return FALSE; + + if((dst->x1 != extents->x1) || (dst->x2 != extents->x2) || + (dst->y1 != extents->y1) || (dst->y2 != extents->y2)) + { + RegionRec clipReg; + REGION_INIT(DummyScreen, &clipReg, dst, 1); + REGION_INTERSECT(DummyScreen, reg, reg, &clipReg); + REGION_UNINIT(DummyScreen, &clipReg); + } + return TRUE; +} + + +static void S3StopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit) +{ + S3Ptr pS3 = S3PTR(pScrn); + S3PortPrivPtr pPriv = pS3->portPrivate; + + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + + if (exit) { + if (pPriv->videoStatus & CLIENT_VIDEO_ON) + SET_BLEND_CNTL(0x01000000); + + if (pPriv->area) { + xf86FreeOffscreenArea(pPriv->area); + pPriv->area = NULL; + } + + pPriv->videoStatus = 0; + } +} + + +static FBAreaPtr S3AllocateMemory(ScrnInfoPtr pScrn, FBAreaPtr area, + int numlines) +{ + ScreenPtr pScreen; + FBAreaPtr new_area; + + if(area) { + if((area->box.y2 - area->box.y1) >= numlines) + return area; + + if(xf86ResizeOffscreenArea(area, pScrn->displayWidth, numlines)) + return area; + + xf86FreeOffscreenArea(area); + } + + pScreen = screenInfo.screens[pScrn->scrnIndex]; + + new_area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, + numlines, 0, NULL, NULL, NULL); + + if(!new_area) { + int max_w, max_h; + + xf86QueryLargestOffscreenArea(pScreen, &max_w, &max_h, 0, + FAVOR_WIDTH_THEN_AREA, PRIORITY_EXTREME); + + if((max_w < pScrn->displayWidth) || (max_h < numlines)) + return NULL; + + xf86PurgeUnlockedOffscreenAreas(pScreen); + new_area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, + numlines, 0, NULL, NULL, NULL); + } + + return new_area; +} + + + +static void S3DisplayVideoOverlay(ScrnInfoPtr pScrn, int id, int offset, + short width, short height, int pitch, + int x1, int y1, int x2, int y2, + BoxPtr dstBox, short src_w, short src_h, + short drw_w, short drw_h) +{ + S3Ptr pS3 = S3PTR(pScrn); + S3PortPrivPtr pPriv = pS3->portPrivate; + int tmp; + + if (drw_w == src_w) + tmp = 0; + else + tmp = 2; + + SET_SSTREAM_CNTL(tmp << 28 | 0x01000000 | + ((((src_w-1)<<1)-(drw_w-1)) & 0xfff)); + SET_SSTRETCH(((src_w - 1) & 0x7ff) | (((src_w-drw_w) & 0x7ff) << 16)); + SET_BLEND_CNTL(0x05000000); + SET_SSTREAM_FBADDR(offset & 0x3fffff); + SET_SSTREAM_STRIDE(pitch & 0xfff); + + SET_K1_VSCALE(src_h - 1); + SET_K2_VSCALE((src_h - drw_h) & 0x7ff); + + SET_DDA_VERT((((~drw_h)-1)) & 0xfff); + + SET_SSTREAM_START(((dstBox->x1 +1) << 16) | (dstBox->y1 +1)); + SET_SSTREAM_WIND(( ((drw_w-1) << 16) | (drw_h ) ) & 0x7ff07ff); + + SET_CHROMA_KEY(0x10000000 | + ((pScrn->weight.red-1) << 24) | + ((pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red) << + (16 + 8-pScrn->weight.red) | + ((pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green) << + (8 + 8-pScrn->weight.green) | + ((pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue) << + (8-pScrn->weight.blue)); +} + + +static int S3PutImage(ScrnInfoPtr pScrn, short src_x, short src_y, + short drw_x, short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int id, unsigned char *buf, + short width, short height, Bool sync, RegionPtr clipBoxes, + pointer data) +{ + S3Ptr pS3 = S3PTR(pScrn); + S3PortPrivPtr pPriv = pS3->portPrivate; + INT32 x1, x2, y1, y2; + unsigned char *dst_start; + int pitch, new_h, offset, offset2=0, offset3=0; + int srcPitch, srcPitch2=0, dstPitch; + int top, left, npixels, nlines; + BoxRec dstBox; + CARD32 tmp; + static int once = 1; + static int once2 = 1; + + /* Clip */ + x1 = src_x; + x2 = src_x + src_w; + y1 = src_y; + y2 = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + + if(!S3ClipVideo(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height)) + return Success; + + /*if(!pMga->TexturedVideo) {*/ + dstBox.x1 -= pScrn->frameX0; + dstBox.x2 -= pScrn->frameX0; + dstBox.y1 -= pScrn->frameY0; + dstBox.y2 -= pScrn->frameY0; + /*}*/ + + pitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3; + dstPitch = ((width << 1) + 15) & ~15; + new_h = ((dstPitch * height) + pitch - 1) / pitch; + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + srcPitch = (width + 3) & ~3; + offset2 = srcPitch * height; + srcPitch2 = ((width >> 1) + 3) & ~3; + offset3 = (srcPitch2 * (height >> 1)) + offset2; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + srcPitch = (width << 1); + break; + } + + if(!(pPriv->area = S3AllocateMemory(pScrn, pPriv->area, new_h))) + return BadAlloc; + + /* copy data */ + top = y1 >> 16; + left = (x1 >> 16) & ~1; + npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; + left <<= 1; + + offset = pPriv->area->box.y1 * pitch; + dst_start = pS3->FBBase + offset + left + (top * dstPitch); + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + top &= ~1; + tmp = ((top >> 1) * srcPitch2) + (left >> 2); + offset2 += tmp; + offset3 += tmp; + if(id == FOURCC_I420) { + tmp = offset2; + offset2 = offset3; + offset3 = tmp; + } + nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; + S3CopyMungedData(buf + (top * srcPitch) + (left >> 1), + buf + offset2, buf + offset3, dst_start, + srcPitch, srcPitch2, dstPitch, nlines, npixels); + once2 = 0; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + buf += (top * srcPitch) + left; + nlines = ((y2 + 0xffff) >> 16) - top; + S3CopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels); + once = 0; + break; + } + + /* update cliplist */ + if(!RegionsEqual(&pPriv->clip, clipBoxes)) { + REGION_COPY(pScreen, &pPriv->clip, clipBoxes); + /* draw these */ + (*pS3->pXAA->FillSolidRects)(pScrn, pPriv->colorKey, GXcopy, ~0, + REGION_NUM_RECTS(clipBoxes), + REGION_RECTS(clipBoxes)); + } + + offset += left + (top * dstPitch); + S3DisplayVideoOverlay(pScrn, id, offset, width, height, dstPitch, + x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); + + pPriv->videoStatus = CLIENT_VIDEO_ON; + return Success; +} + + + +static int S3QueryImageAttributes(ScrnInfoPtr pScrn, int id, + unsigned short *w, unsigned short *h, + int *pitches, int *offsets) +{ + int size, tmp; + + *w = (*w + 1) & ~1; + if(offsets) offsets[0] = 0; + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + *h = (*h + 1) & ~1; + size = (*w + 3) & ~3; + if(pitches) pitches[0] = size; + size *= *h; + if(offsets) offsets[1] = size; + tmp = ((*w >> 1) + 3) & ~3; + if(pitches) pitches[1] = pitches[2] = tmp; + tmp *= (*h >> 1); + size += tmp; + if(offsets) offsets[2] = size; + size += tmp; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + size = *w << 1; + if(pitches) pitches[0] = size; + size *= *h; + break; + } + + return size; +} + + + +void S3InitStreams(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + S3Ptr pS3 = S3PTR(pScrn); + unsigned int pst_wind = (mode->HDisplay-1) << 16 | (mode->VDisplay); + + SET_PSTREAM_CNTL(0x05000000 & 0x77000000); + SET_CHROMA_KEY(0x00); + SET_SSTREAM_CNTL(0x03000000); + SET_BLEND_CNTL(0x01000000); + SET_PSTREAM_STRIDE((pScrn->displayWidth * 2) & 0x0fff); + SET_SSTREAM_STRIDE(0x01); + SET_OPAQUE_OVERLAY(0x40000000); + SET_PSTREAM_START(0x00010001); + SET_PSTREAM_WIND(pst_wind & 0x07ff07ff); + SET_SSTREAM_START(0x07ff07ff); + SET_SSTREAM_WIND(0x00010001); +} + diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/bin-excl b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/bin-excl new file mode 100644 index 000000000..c24fdf318 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/bin-excl @@ -0,0 +1,6 @@ +bin/Xnest.exe +bin/Xprt.exe +bin/Xvfb.exe +bin/X +bin/xfs.exe +bin/XWin.exe diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/bin-list b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/bin-list new file mode 100644 index 000000000..23aa7b747 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/bin-list @@ -0,0 +1,36 @@ +.XFree86_Version +bin +lib/libdps.a +lib/libdpstk.a +lib/libfntstubs.a +lib/libfreetype.a +lib/libFS.a +lib/libGL.a +lib/libGLU.a +lib/libGLw.a +lib/libICE.a +lib/liboldX.a +lib/libpsres.a +lib/libSM.a +lib/libX11.a +lib/libXau.a +lib/libXaw.a +lib/libXdmcp.a +lib/libXext.a +lib/libXfont.a +lib/libXfontcache.a +lib/libXft.a +lib/libXi.a +lib/libxkbfile.a +lib/libxkbui.a +lib/libXmu.a +lib/libXmuu.a +lib/libXp.a +lib/libXpm.a +lib/libXrandr.a +lib/libXrender.a +lib/libXt.a +lib/libXtst.a +lib/libXv.a +lib/libXxf86misc.a +lib/libXxf86vm.a diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/build-bindist b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/build-bindist new file mode 100755 index 000000000..edd8e3365 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/build-bindist @@ -0,0 +1,148 @@ +#!/bin/sh +# +# $XFree86: xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/build-bindist,v 1.1 2001/07/02 09:37:18 alanh Exp $ +# + +Usage() +{ + echo `basename $0` [-l] [-t type] [prefix] from-dir to-dir + exit 1 +} + +args= +createlist=NO +type=list + +while [ $# != 0 ]; do + case $1 in + -l) + createlist=YES + shift + ;; + -t) + shift + type=$1 + shift + ;; + *) + args="$args $1" + shift + ;; + esac +done + +if [ X"$args" != X ]; then + set - $args +fi + +case $# in +3) + PRE=$1 + shift + ;; +2) + PRE=X + ;; +*) + Usage + ;; +esac + +FROMDIR=$1 +TODIR=$2 + +if [ ! -d $FROMDIR ]; then + echo No such dir $FROMDIR + exit 2 +fi + +if [ ! -d $TODIR ]; then + echo No such dir $TODIR + exit 2 +fi + +cd $TODIR +SUBDIRS="`find . -type d ! -name bindist -print`" + +DIRFILE=dir +BINDIR=bindist +EXTRASFILE=extras +TAR="gnu-tar" +TAROPTS="-c -v -z" +TARLOPTS="-t -v -z -i" +CKSUM=md5 +SUMFILE=SUMS.md5 +LISTFILE=FILES + +GenList() +{ + (cd $TODIR/$BINDIR + rm -f $SUMFILE $LISTFILE + for i in *.tgz; do + echo $i + $CKSUM $i >> $SUMFILE + echo $i >> $LISTFILE + echo "------------" >> $LISTFILE + $TAR $TARLOPTS -f $i >> $LISTFILE + echo "" >> $LISTFILE + done + if [ -f $TODIR/$EXTRASFILE ]; then + for i in `cat $TODIR/$EXTRASFILE`; do + $CKSUM `basename $i` >> $SUMFILE + done + fi + ) +} + +if [ ! -d $TODIR/$BINDIR ]; then + mkdir $TODIR/$BINDIR +fi + +if [ $createlist = YES ]; then + GenList + exit 0; +fi + +for d in $SUBDIRS; do + if [ ! -d $TODIR/$d ]; then + echo No such dir $TODIR/$d + exit 2 + fi + (cd $TODIR/$d; + if [ ! -f $DIRFILE ]; then + echo No file $DIRFILE in $TODIR/$d +# exit 3 + else + DEFPREFIX=`cat $DIRFILE` + for i in *-$type; do + name=`basename $i -$type` + tarball=$PRE$name.tgz + echo creating $tarball + lfile="`cat $TODIR/$d/$i`" + if [ -f $name-excl ]; then + xfile="-X $TODIR/$d/$name-excl" + else + xfile="" + fi + if [ -f $name-dir ]; then + PREFIX=`cat $name-dir` + else + PREFIX=$DEFPREFIX + fi + (cd $FROMDIR/$PREFIX + $TAR $TAROPTS -f $TODIR/$BINDIR/$tarball $xfile $lfile + ) + done + fi + if [ -f $EXTRASFILE ]; then + for i in `cat $EXTRASFILE`; do + rm -f $TODIR/$BINDIR/`basename $i` + cp $FROMDIR/$PREFIX/$i $TODIR/$BINDIR + done + fi + ) +done + +# GenList + +exit 0 diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/dir b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/dir new file mode 100644 index 000000000..11c5b9da7 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/dir @@ -0,0 +1 @@ +usr/X11R6 diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/etc-dir b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/etc-dir new file mode 100644 index 000000000..412cec0c3 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/etc-dir @@ -0,0 +1 @@ +etc/X11 diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/etc-list b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/etc-list new file mode 100644 index 000000000..9c558e357 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/etc-list @@ -0,0 +1 @@ +. diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/fsrv-list b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/fsrv-list new file mode 100644 index 000000000..2f578c539 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/fsrv-list @@ -0,0 +1,2 @@ +bin/xfs.exe +man/man1/xfs.1 diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/host.def b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/host.def new file mode 100644 index 000000000..4650f8824 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/host.def @@ -0,0 +1,3 @@ +#define InstallEmptyHostDef +#define BuildBindist + diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/lib-excl b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/lib-excl new file mode 100644 index 000000000..d7fb5cb03 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/lib-excl @@ -0,0 +1,14 @@ +lib/X11/XF86Setup +lib/X11/app-defaults +lib/X11/config +lib/X11/doc +lib/X11/fonts +lib/X11/fs +lib/X11/lbxproxy +lib/X11/proxymngr +lib/X11/rstart +lib/X11/twm +lib/X11/xdm +lib/X11/xinit +lib/X11/xsm +lib/X11/xserver diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/lib-list b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/lib-list new file mode 100644 index 000000000..9673fea05 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/lib-list @@ -0,0 +1,2 @@ +lib/X11 +include/X11/bitmaps diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/man-excl b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/man-excl new file mode 100644 index 000000000..e5b2fd2e7 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/man-excl @@ -0,0 +1,2 @@ +man/man1/xfs.1 +man/cat1/xmseconfig.0 diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/man-list b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/man-list new file mode 100644 index 000000000..2a3700c15 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/man-list @@ -0,0 +1 @@ +man diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/nest-list b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/nest-list new file mode 100644 index 000000000..ca3ea83df --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/nest-list @@ -0,0 +1 @@ +bin/Xnest.exe diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/prog-excl b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/prog-excl new file mode 100644 index 000000000..3204ca88f --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/prog-excl @@ -0,0 +1,5 @@ +lib/Server +lib/X11 +lib/lib*.a +lib/modules +include/X11/bitmaps diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/prog-list b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/prog-list new file mode 100644 index 000000000..059b71061 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/prog-list @@ -0,0 +1,3 @@ +lib +include +lib/X11/config diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/prt-list b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/prt-list new file mode 100644 index 000000000..88e46fd6f --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/prt-list @@ -0,0 +1 @@ +bin/Xprt.exe diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/update-upd b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/update-upd new file mode 100644 index 000000000..050fcfe7a --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/update-upd @@ -0,0 +1,32 @@ +bin/XWin.exe +bin/gccmakedep.exe +bin/mkhtmlindex.exe +bin/rman.exe +bin/pswrap.exe +bin/twm.exe +bin/xedit.exe +bin/xfs.exe +bin/xman.exe +bin/xterm.exe +include/X11/Xos.h +include/X11/Xosdefs.h +include/X11/Xos_r.h +lib/X11/config/FreeBSD.cf +lib/X11/config/Imake.rules +lib/X11/config/Imake.tmpl +lib/X11/config/NetBSD.cf +lib/X11/config/OpenBSD.cf +lib/X11/config/X11.tmpl +lib/X11/config/cygwin.cf +lib/X11/config/gnu.cf +lib/X11/config/linux.cf +lib/X11/config/osf1.cf +lib/X11/config/xfree86.cf +lib/X11/xkb/rules/xfree86.lst +lib/X11/xkb/symbols/us +lib/libX11.a +lib/libXaw.a +lib/libXfont.a +lib/libXft.a +lib/libfreetype.a +man/man1/XWin.1x diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/vfb-list b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/vfb-list new file mode 100644 index 000000000..350e4775c --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/vfb-list @@ -0,0 +1 @@ +bin/Xvfb.exe diff --git a/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/xserv-list b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/xserv-list new file mode 100644 index 000000000..f09db6963 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/etc/bindist/Cygwin/xserv-list @@ -0,0 +1,2 @@ +bin/XWin.exe +bin/X diff --git a/xc/programs/Xserver/hw/xfree86/input/acecad/acecad.c b/xc/programs/Xserver/hw/xfree86/input/acecad/acecad.c new file mode 100644 index 000000000..0081ff8d7 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/input/acecad/acecad.c @@ -0,0 +1,916 @@ +/* + * Copyright (c) 2001 Edouard TISSERANT <tissered@esstin.u-nancy.fr> + * Parts inspired from Shane Watts <shane@bofh.asn.au> XFree86 3 Acecad Driver + * Thanks to Emily, from AceCad, For giving me documents. + * + * 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 X CONSORTIUM 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. + * + * + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/input/acecad/acecad.c,v 1.1 2001/08/13 19:35:00 dawes Exp $ */ + +#define _ACECAD_C_ +/***************************************************************************** + * Standard Headers + ****************************************************************************/ + +#ifdef LINUX_INPUT +#include <asm/types.h> +#include <linux/input.h> +#ifdef BUS_PCI +#undef BUS_PCI +#endif +#ifdef BUS_ISA +#undef BUS_ISA +#endif +#endif + +#include <misc.h> +#include <xf86.h> +#define NEED_XF86_TYPES +#include <xf86_ansic.h> +#include <xf86_OSproc.h> +#include <xisb.h> +#include <xf86Xinput.h> +#include <exevents.h> +#include <xf86Module.h> + +/***************************************************************************** + * Local Headers + ****************************************************************************/ +#include "acecad.h" + +/***************************************************************************** + * Variables without includable headers + ****************************************************************************/ + +/***************************************************************************** + * Local Variables + ****************************************************************************/ + +#define SYSCALL(call) while(((call) == -1) && (errno == EINTR)) +#undef read +#define read(a,b,c) xf86ReadSerial((a),(b),(c)) + +/* max number of input events to read in one read call */ +#define MAX_EVENTS 50 + + +static InputDriverRec ACECAD = +{ + 1, + "acecad", + NULL, + AceCadPreInit, + NULL, + NULL, + 0 +}; + + +static XF86ModuleVersionInfo VersionRec = +{ + "acecad", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_XINPUT, + ABI_XINPUT_VERSION, + MOD_CLASS_XINPUT, + {0, 0, 0, 0} +}; + + +static const char *default_options[] = +{ + "BaudRate", "9600", + "StopBits", "1", + "DataBits", "8", + "Parity", "Odd", + "Vmin", "1", + "Vtime", "10", + "FlowControl", "Xoff", + NULL +}; + +XF86ModuleData acecadModuleData = { &VersionRec, SetupProc, TearDownProc}; + +/***************************************************************************** + * Function Definitions + ****************************************************************************/ + +static pointer +SetupProc( pointer module, + pointer options, + int *errmaj, + int *errmin ) +{ + xf86AddInputDriver(&ACECAD, module, 0); + return module; +} + +static void +TearDownProc( pointer p ) +{ + LocalDevicePtr local = (LocalDevicePtr) p; + AceCadPrivatePtr priv = (AceCadPrivatePtr) local->private; + + DeviceOff (local->dev); + + xf86RemoveLocalDevice (local); + + xf86CloseSerial (local->fd); + XisbFree (priv->buffer); + xfree (priv); + xfree (local->name); + xfree (local); +} + +static int +IsUSBLine(int fd) +{ + int version; + int err; + + SYSCALL(err = ioctl(fd, EVIOCGVERSION, &version)); + + if (!err) { + xf86Msg(X_CONFIG,"Kernel Input driver version is %d.%d.%d\n", + version >> 16, (version >> 8) & 0xff, version & 0xff); + return 1; + } else { + return 0; + } +} + + +static InputInfoPtr +AceCadPreInit(InputDriverPtr drv, IDevPtr dev, int flags) +{ + LocalDevicePtr local = xf86AllocateInput(drv, 0); + AceCadPrivatePtr priv = xcalloc (1, sizeof (AceCadPrivateRec)); + int speed; + char *s; + + if ((!local) || (!priv)) + goto SetupProc_fail; + + memset(priv,0,sizeof (AceCadPrivateRec)); + + local->name = dev->identifier; + local->type_name = "AceCad Tablet"; + local->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS; + local->motion_history_proc = xf86GetMotionEvents; + local->control_proc = NULL; + local->close_proc = CloseProc; + local->switch_mode = NULL; + local->conversion_proc = ConvertProc; + local->reverse_conversion_proc = ReverseConvertProc; + local->dev = NULL; + local->private = priv; + local->private_flags = 0; + local->conf_idev = dev; + local->device_control = DeviceControl; + /*local->always_core_feedback = 0;*/ + + xf86CollectInputOptions(local, default_options, NULL); + + xf86OptionListReport(local->options); + + priv->acecadInc = xf86SetIntOption(local->options, "Increment", 0 ); + + local->fd = xf86OpenSerial (local->options); + if (local->fd == -1) + { + xf86Msg(X_ERROR,"AceCad driver unable to open device\n"); + goto SetupProc_fail; + } + xf86ErrorFVerb( 6, "tty port opened successfully\n" ); + + if(IsUSBLine(local->fd)){ + priv->acecadUSB=1; + + local->read_input = USBReadInput; + + if (USBQueryHardware(local) != Success) + { + ErrorF ("Unable to query/initialize AceCad hardware.\n"); + goto SetupProc_fail; + } + } + else{ + priv->acecadUSB=0; + + local->read_input = ReadInput; + + speed = xf86SetIntOption(local->options, "ReportSpeed", 85 ); + + switch (speed) + { + case 120: + priv->acecadReportSpeed = 'Q'; + break; + case 85: + priv->acecadReportSpeed = 'R'; + break; + case 10: + priv->acecadReportSpeed = 'S'; + break; + case 2: + priv->acecadReportSpeed = 'T'; + break; + default: + priv->acecadReportSpeed = 'R'; + speed = 85; + xf86Msg(X_CONFIG, "Acecad Tablet: ReportSpeed possible values:\n 120, 85, 10, 2 \n"); + } + + xf86Msg(X_CONFIG, "Acecad Tablet report %d points/s\n", speed); + + priv->buffer = XisbNew (local->fd, 200); + + /* + * Verify that hardware is attached and fuctional + */ + if (QueryHardware(priv) != Success) + { + xf86Msg(X_ERROR,"Unable to query/initialize AceCad hardware.\n"); + goto SetupProc_fail; + } + } + + s = xf86FindOptionValue(local->options, "Mode"); + if (s && (xf86NameCmp(s, "Relative") == 0)) + { + priv->flags = priv->flags & ~ABSOLUTE_FLAG; + } + else + { + priv->flags = priv->flags | ABSOLUTE_FLAG; + } + + xf86Msg(X_CONFIG, "Acecad Tablet is in %s mode\n",(priv->flags & ABSOLUTE_FLAG) ? "absolute" : "relative"); + DBG (9, XisbTrace (priv->buffer, 1)); + + local->history_size = xf86SetIntOption(local->options , "HistorySize", 0); + + xf86ProcessCommonOptions(local, local->options); + + local->flags |= XI86_CONFIGURED; + + if (local->fd != -1) + { + RemoveEnabledDevice (local->fd); + if (priv->buffer) + { + XisbFree(priv->buffer); + priv->buffer = NULL; + } + xf86CloseSerial(local->fd); + } + RemoveEnabledDevice (local->fd); + local->fd = -1; + return (local); + + /* + * If something went wrong, cleanup and return NULL + */ + SetupProc_fail: + if ((local) && (local->fd)) + xf86CloseSerial (local->fd); + if (local) + xfree (local); + + if ((priv) && (priv->buffer)) + XisbFree (priv->buffer); + if (priv) + xfree (priv); + return (NULL); +} + +static Bool +DeviceControl (DeviceIntPtr dev, int mode) +{ + Bool RetValue; + + switch (mode) + { + case DEVICE_INIT: + DeviceInit (dev); + RetValue = Success; + break; + case DEVICE_ON: + RetValue = DeviceOn( dev ); + break; + case DEVICE_OFF: + RetValue = DeviceOff( dev ); + break; + case DEVICE_CLOSE: + RetValue = DeviceClose( dev ); + break; + default: + RetValue = BadValue; + } + + return( RetValue ); +} + +static Bool +DeviceOn (DeviceIntPtr dev) +{ + char buffer[256]; + LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate; + AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private); + + xf86Msg(X_CONFIG, "Acecad Tablet Device On\n"); + + local->fd = xf86OpenSerial(local->options); + if (local->fd == -1) + { + xf86Msg(X_WARNING, "%s: cannot open input device\n", local->name); + return (!Success); + } + + + if (priv->acecadUSB==0){ + priv->buffer = XisbNew(local->fd, 200); + if (!priv->buffer) + { + xf86CloseSerial(local->fd); + local->fd = -1; + return (!Success); + } + + /*Rets qu'a l'envoyer a la tablette */ + sprintf(buffer, "%s%c%c%c%c", acecad_initstr, priv->acecadReportSpeed ,ACECAD_INCREMENT, 32 + priv->acecadInc, (priv->flags & ABSOLUTE_FLAG)? ACECAD_ABSOLUTE: ACECAD_RELATIVE); + XisbWrite (priv->buffer, (unsigned char *)buffer, strlen(buffer)); + } + + xf86FlushInput(local->fd); + xf86AddEnabledDevice (local); + dev->public.on = TRUE; + return (Success); +} + +static Bool +DeviceOff (DeviceIntPtr dev) +{ + LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate; + AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private); + + + if (local->fd != -1) + { + RemoveEnabledDevice (local->fd); + if (priv->buffer) + { + XisbFree(priv->buffer); + priv->buffer = NULL; + } + xf86CloseSerial(local->fd); + } + + + xf86RemoveEnabledDevice (local); + dev->public.on = FALSE; + return (Success); +} + +static Bool +DeviceClose (DeviceIntPtr dev) +{ + xf86Msg(X_CONFIG, "Acecad Tablet Device Close\n"); + return (Success); +} + +static void +ControlProc(DeviceIntPtr device, + PtrCtrl *ctrl) +{ + xf86Msg(X_CONFIG, "Acecad Tablet Control Proc\n"); +} + +static Bool +DeviceInit (DeviceIntPtr dev) +{ + int rx, ry; + LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate; + AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private); + unsigned char map[] = + {0, 1, 2, 3}; + + xf86Msg(X_CONFIG, "Acecad Tablet Device Init\n"); + + /* 3 boutons */ + if (InitButtonClassDeviceStruct (dev, 3, map) == FALSE) + { + ErrorF ("Unable to allocate AceCad ButtonClassDeviceStruct\n"); + return !Success; + } + + if (InitFocusClassDeviceStruct (dev) == FALSE) + { + ErrorF("Unable to allocate AceCad FocusClassDeviceStruct\n"); + return !Success; + } + + if (InitPtrFeedbackClassDeviceStruct(dev, + ControlProc) == FALSE) { + ErrorF("unable to init ptr feedback\n"); + return !Success; + } + + + /* 3 axes */ + if (InitValuatorClassDeviceStruct (dev, 3, xf86GetMotionEvents, + local->history_size, + ((priv->flags & ABSOLUTE_FLAG)? Absolute: Relative)|OutOfProximity) + == FALSE) + { + ErrorF ("Unable to allocate AceCad ValuatorClassDeviceStruct\n"); + return !Success; + } + else + { + + InitValuatorAxisStruct(dev, + 0, + 0, /* min val */ + priv->acecadMaxX, /* max val */ + 1000, /* resolution */ + 0, /* min_res */ + 1000); /* max_res */ + InitValuatorAxisStruct(dev, + 1, + 0, /* min val */ + priv->acecadMaxY, /* max val */ + 1000, /* resolution */ + 0, /* min_res */ + 1000); /* max_res */ + InitValuatorAxisStruct(dev, + 2, + 0, /* min val */ + priv->acecadMaxZ, /* max val */ + 1000, /* resolution */ + 0, /* min_res */ + 1000); /* max_res */ + + } + + if (InitProximityClassDeviceStruct (dev) == FALSE) + { + ErrorF ("Unable to allocate ProximityClassDeviceStruct\n"); + return !Success; + } + + xf86MotionHistoryAllocate (local); + + + /* On ne peut pas calculer l'increment avant, faute d'ecran pour + connaitre la taille... */ + + if (priv->acecadInc > 95) + priv->acecadInc = 95; + if (priv->acecadInc < 1) + { + /* guess the best increment value given video mode */ + rx=priv->acecadMaxX / screenInfo.screens[0]->width; + ry=priv->acecadMaxY / screenInfo.screens[0]->height; + if (rx < ry) + priv->acecadInc = rx; + else + priv->acecadInc = ry; + if (priv->acecadInc < 1) + priv->acecadInc = 1; + } + + xf86Msg(X_CONFIG, "Acecad Tablet Increment: %d\n",priv->acecadInc); + + return (Success); +} + +static void +ReadInput (LocalDevicePtr local) +{ + int x, y, z; + int prox, buttons; + int is_core_pointer, is_absolute; + AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private); + + /*xf86Msg(X_CONFIG, "Acecad Tablet Read Input\n");*/ + + is_absolute = (priv->flags & ABSOLUTE_FLAG); + is_core_pointer = xf86IsCorePointer(local->dev); + + /* + * set blocking to -1 on the first call because we know there is data to + * read. Xisb automatically clears it after one successful read so that + * succeeding reads are preceeded buy a select with a 0 timeout to prevent + * read from blocking indefinately. + */ + XisbBlockDuration (priv->buffer, -1); + + while (AceCadGetPacket (priv) == Success) + { + x = (int)priv->packet[1] | ((int)priv->packet[2] << 7); + y = (int)priv->packet[3] | ((int)priv->packet[4] << 7); + + if (!(priv->flags & ABSOLUTE_FLAG)) + { + x = priv->packet[0] & XSIGN_BIT? x:-x; + y = priv->packet[0] & YSIGN_BIT? y:-y; + } + else + { + y = priv->acecadMaxY - y ; + } + + + z = ((int)priv->packet[5] << 2) | + (((int)priv->packet[6] & 0x01) << 1) | + (((int)priv->packet[6] & 0x10) >> 4); + + buttons = ((int)priv->packet[0] & 0x07) | + ((int)priv->packet[6] & 0x02 << 2); + + prox = (priv->packet[0] & PROXIMITY_BIT)? 0: 1; + + if (prox) + { + if (!(priv->acecadOldProximity)) + if (!is_core_pointer) + { + /*xf86Msg(X_CONFIG, "Acecad Tablet ProxIN %d %d %d\n",x, y, z);*/ + xf86PostProximityEvent(local->dev, 1, 0, 3 , x, y, z); + } + + if ((is_absolute && ((priv->acecadOldX != x) || (priv->acecadOldY != y) || (priv->acecadOldZ != z))) + || (!is_absolute && (x || y))) + { + if (is_absolute || priv->acecadOldProximity) + { + /*xf86Msg(X_CONFIG, "Acecad Tablet Motion %d %d %d\n", x, y, z);*/ + xf86PostMotionEvent(local->dev, is_absolute, 0, 3, x, y, z); + } + } + + if (priv->acecadOldButtons != buttons) + { + int delta; + + delta = buttons ^ priv->acecadOldButtons; + while(delta) + { + int id; + + id=ffs(delta); + delta &= ~(1 << (id-1)); + + /*xf86Msg(X_CONFIG, "Acecad Tablet Button %d 0x%x\n",id,(buttons&(1<<(id-1))));*/ + xf86PostButtonEvent(local->dev, is_absolute, id, (buttons&(1<<(id-1))), 0, 3, x, y,z); + } + } + + priv->acecadOldButtons = buttons; + priv->acecadOldX = x; + priv->acecadOldY = y; + priv->acecadOldZ = z; + priv->acecadOldProximity = prox; + } + else + { + if (!is_core_pointer) + if (priv->acecadOldProximity) + { + /*xf86Msg(X_CONFIG, "Acecad Tablet ProxOUT %d %d %d\n",x, y, z);*/ + xf86PostProximityEvent(local->dev, 0, 0, 3, x,y,z); + } + priv->acecadOldProximity = 0; + } + } + /*xf86Msg(X_CONFIG, "Acecad Tablet Sortie Read Input\n");*/ +} + +#define set_bit(byte,nb,bit) (bit ? byte | (1<<nb) : byte & (~(1<<nb))) +static void +USBReadInput (LocalDevicePtr local) +{ + int len; + struct input_event * event; + char eventbuf[sizeof(struct input_event) * MAX_EVENTS]; + AceCadPrivatePtr priv = (AceCadPrivatePtr) (local->private); + int x = priv->acecadOldX; + int y = priv->acecadOldY; + int z = priv->acecadOldZ; + int prox = priv->acecadOldProximity; + int buttons = priv->acecadOldButtons; + int is_core_pointer; + + is_core_pointer = xf86IsCorePointer(local->dev); + + SYSCALL(len = read(local->fd, eventbuf, sizeof(eventbuf))); + + if (len <= 0) { + ErrorF("Error reading wacom device : %s\n", strerror(errno)); + return; + } + + for (event=(struct input_event *)eventbuf; + event<(struct input_event *)(eventbuf+len); event++) { + + switch (event->type) { + case EV_ABS: + switch (event->code) { + case ABS_X: + x = event->value; + break; + + case ABS_Y: + y = event->value; + break; + + case ABS_PRESSURE: + z = event->value; + break; + + case ABS_MISC: + break; + + } + break; /* EV_ABS */ + + case EV_KEY: + switch (event->code) { + case BTN_TOOL_PEN: + prox = event->value; + break; + + case BTN_TOUCH: + buttons=set_bit(buttons,0,event->value); + break; + + case BTN_STYLUS: + buttons=set_bit(buttons,1,event->value); + break; + + case BTN_STYLUS2: + buttons=set_bit(buttons,2,event->value); + break; + } + break; /* EV_KEY */ + default: + xf86Msg(X_ERROR, "UNKNOWN event->code=%d\n", event->code); + } /* switch event->type */ + + /* ABS_MISC is the event terminator */ + if (event->type != EV_ABS || event->code != ABS_MISC) { + continue; + } + + if (prox) + { + if (!(priv->acecadOldProximity)) + if (!is_core_pointer) + { + xf86PostProximityEvent(local->dev, 1, 0, 3 , x, y, z); + } + + + xf86PostMotionEvent(local->dev, 1, 0, 3, x, y, z); + + if (priv->acecadOldButtons != buttons) + { + int delta; + + delta = buttons ^ priv->acecadOldButtons; + while(delta) + { + int id; + + id=ffs(delta); + delta &= ~(1 << (id-1)); + + xf86PostButtonEvent(local->dev, 1, id, (buttons&(1<<(id-1))), 0, 3, x, y,z); + } + } + } + else + { + if (!is_core_pointer) + if (priv->acecadOldProximity) + { + xf86PostProximityEvent(local->dev, 0, 0, 3, x,y,z); + } + priv->acecadOldProximity = 0; + } + + priv->acecadOldButtons = buttons; + priv->acecadOldX = x; + priv->acecadOldY = y; + priv->acecadOldZ = z; + priv->acecadOldProximity = prox; + } + /*xf86Msg(X_CONFIG, "Acecad Tablet Sortie Read Input\n");*/ +} + +static void +CloseProc (LocalDevicePtr local) +{ +} + +/* + * The ConvertProc function may need to be tailored for your device. + * This function converts the device's valuator outputs to x and y coordinates + * to simulate mouse events. + */ +static Bool +ConvertProc (LocalDevicePtr local, + int first, + int num, + int v0, + int v1, + int v2, + int v3, + int v4, + int v5, + int *x, + int *y) +{ + AceCadPrivatePtr priv = (AceCadPrivatePtr)(local->private); + + *x = v0 * screenInfo.screens[0]->width / priv->acecadMaxX; + *y = v1 * screenInfo.screens[0]->height / priv->acecadMaxY; + return TRUE; +} + + +static Bool +ReverseConvertProc( LocalDevicePtr local, + int x, + int y, + int *valuators) +{ + AceCadPrivatePtr priv = (AceCadPrivatePtr)(local->private); + + valuators[0] = x * priv->acecadMaxX / screenInfo.screens[0]->width; + valuators[1] = y * priv->acecadMaxY / screenInfo.screens[0]->height; + + return TRUE; +} + + +#define WriteString(str)\ +XisbWrite (priv->buffer, (unsigned char *)(str), strlen(str)) + + +static Bool +QueryHardware (AceCadPrivatePtr priv) +{ + + /* Reset */ + WriteString("z0"); + + /* Wait */ + milisleep (250); + + /* Prompt Mode in order to not be disturbed */ + WriteString(ACECAD_PROMPT_MODE); + + /* Flush */ + while(XisbRead(priv->buffer)>=0); + + /* Ask for Config packet*/ + WriteString(ACECAD_CONFIG); + + /* Read the packet */ + XisbBlockDuration (priv->buffer, 1000000); + NewPacket (priv); + + /*xf86Msg(X_CONFIG, "Acecad Tablet init envoyé \n");*/ + + if ((AceCadGetPacket (priv) == Success)) + { + priv->acecadMaxX = (int)priv->packet[1] + ((int)priv->packet[2] << 7); + priv->acecadMaxY = (int)priv->packet[3] + ((int)priv->packet[4] << 7); + priv->acecadMaxZ = 512; + xf86Msg(X_CONFIG, "Acecad Tablet MaxX:%d MaxY:%d\n",priv->acecadMaxX,priv->acecadMaxY); + } + else + return (!Success); + + /*xf86Msg(X_CONFIG, "Acecad Tablet query hardware fini \n");*/ + return (Success); +} + +#define BITS_PER_LONG (sizeof(long) * 8) +#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) +#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1) +#define OFF(x) ((x)%BITS_PER_LONG) +#define LONG(x) ((x)/BITS_PER_LONG) + +static Bool +USBQueryHardware (LocalDevicePtr local) +{ + AceCadPrivatePtr priv = (AceCadPrivatePtr) local->private; + unsigned long bit[EV_MAX][NBITS(KEY_MAX)]; + int i, j; + int abs[5]; + char name[256] = "Unknown"; + + ioctl(local->fd, EVIOCGNAME(sizeof(name)), name); + xf86Msg(X_CONFIG, "Kernel Input device name: \"%s\"\n", name); + + memset(bit, 0, sizeof(bit)); + ioctl(local->fd, EVIOCGBIT(0, EV_MAX), bit[0]); + + for (i = 0; i < EV_MAX; i++) + if (test_bit(i, bit[0])) { + ioctl(local->fd, EVIOCGBIT(i, KEY_MAX), bit[i]); + for (j = 0; j < KEY_MAX; j++) + if (test_bit(j, bit[i])) { + if (i == EV_ABS) { + ioctl(local->fd, EVIOCGABS(j), abs); + switch (j) { + case ABS_X: + priv->acecadMaxX = abs[2]; + break; + + case ABS_Y: + priv->acecadMaxY = abs[2]; + break; + + case ABS_PRESSURE: + priv->acecadMaxZ = abs[2]; + break; + } + } + } + } + + xf86Msg(X_CONFIG, "Acecad Tablet MaxX:%d MaxY:%d MaxZ:%d\n",priv->acecadMaxX,priv->acecadMaxY,priv->acecadMaxZ); + return (Success); +} + +static void +NewPacket (AceCadPrivatePtr priv) +{ + priv->packeti = 0; +} + +static Bool +AceCadGetPacket (AceCadPrivatePtr priv) +{ + int count = 0; + int c = 0; + + while((c = XisbRead(priv->buffer))>=0 ) + { + + /* + * fail after 500 bytes so the server doesn't hang forever if a + * device sends bad data. + */ + if (count++ > 500) + { + NewPacket (priv); + return (!Success); + } + + if (c & PHASING_BIT) + { + NewPacket(priv); + + /*xf86Msg(X_CONFIG, "Push %2.2x\n",(char) c);*/ + XisbBlockDuration (priv->buffer, 10000); + priv->packet[priv->packeti++] = c; + count=ACECAD_PACKET_SIZE-1; + while(count-- && (c = XisbRead(priv->buffer))>=0) + { + /*xf86Msg(X_CONFIG, "Push %2.2x\n",(char) c);*/ + priv->packet[priv->packeti++] = c; + } + XisbBlockDuration (priv->buffer, 0); + if(c > 0) + return (Success); + } + } + return (!Success); +} diff --git a/xc/programs/Xserver/hw/xfree86/input/acecad/acecad.h b/xc/programs/Xserver/hw/xfree86/input/acecad/acecad.h new file mode 100644 index 000000000..d1ec95030 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/input/acecad/acecad.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001 Edouard TISSERANT <tissered@esstin.u-nancy.fr> + * Parts inspired from Shane Watts <shane@bofh.asn.au> Xfree 3 Acecad Driver + * Thanks to Emily, from AceCad, For giving me documents. + * + * 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 X CONSORTIUM 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. + * + * + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/input/acecad/acecad.h,v 1.1 2001/08/13 19:35:00 dawes Exp $ */ + +#ifndef _ACECAD_H_ +#define _ACECAD_H_ + +/****************************************************************************** + * Definitions + * structs, typedefs, #defines, enums + *****************************************************************************/ +#define ACECAD_PACKET_SIZE 7 + +#define ACECAD_CONFIG "a" /* Send configuration (max coords) */ + +#define ACECAD_ABSOLUTE 'F' /* Absolute mode */ +#define ACECAD_RELATIVE 'E' /* Relative mode */ + +#define ACECAD_UPPER_ORIGIN "b" /* Origin upper left */ + +#define ACECAD_PROMPT_MODE "B" /* Prompt mode */ +#define ACECAD_STREAM_MODE "@" /* Stream mode */ +#define ACECAD_INCREMENT 'I' /* Set increment */ +#define ACECAD_BINARY_FMT "zb" /* Binary reporting */ + +#define ACECAD_PROMPT "P" /* Prompt for current position */ + +#define PHASING_BIT 0x80 +#define PROXIMITY_BIT 0x40 +#define TABID_BIT 0x20 +#define XSIGN_BIT 0x10 +#define YSIGN_BIT 0x08 +#define BUTTON_BITS 0x07 +#define COORD_BITS 0x7f + +#define ABSOLUTE_FLAG 1 + +#define milisleep(ms) xf86usleep (ms * 1000) + +#define SYSCALL(call) while(((call) == -1) && (errno == EINTR)) + +static const char * acecad_initstr = ACECAD_BINARY_FMT ACECAD_STREAM_MODE; + +typedef struct +{ + XISBuffer *buffer; + int acecadInc; /* increment between transmits */ + int acecadOldX; /* previous X position */ + int acecadOldY; /* previous Y position */ + int acecadOldZ; /* previous Z position */ + int acecadOldProximity; /* previous proximity */ + int acecadOldButtons; /* previous buttons state */ + int acecadMaxX; /* max X value */ + int acecadMaxY; /* max Y value */ + int acecadMaxZ; /* max Y value */ + char acecadReportSpeed; /* report speed */ + int acecadUSB; /*USB flag*/ + int flags; /* various flags */ + int packeti; /* number of bytes read */ + int PacketSize; /* number of bytes read */ + unsigned char packet[ACECAD_PACKET_SIZE]; /* data read on the device */ +} AceCadPrivateRec, *AceCadPrivatePtr; + + +/****************************************************************************** + * Declarations + *****************************************************************************/ +static MODULESETUPPROTO( SetupProc ); +static void TearDownProc (void *); +static Bool DeviceControl (DeviceIntPtr, int); +static Bool DeviceOn (DeviceIntPtr); +static Bool DeviceOff (DeviceIntPtr); +static Bool DeviceClose (DeviceIntPtr); +static Bool DeviceInit (DeviceIntPtr); +static void ReadInput (LocalDevicePtr); +static void USBReadInput (LocalDevicePtr); +static void CloseProc (LocalDevicePtr); +static Bool ConvertProc (LocalDevicePtr, int, int, int, int, int, int, int, int, int *, int *); +static Bool ReverseConvertProc(LocalDevicePtr , int , int , int*); +static Bool QueryHardware (AceCadPrivatePtr); +static Bool USBQueryHardware (LocalDevicePtr); +static void NewPacket (AceCadPrivatePtr priv); +static Bool AceCadGetPacket (AceCadPrivatePtr); +static InputInfoPtr AceCadPreInit(InputDriverPtr, IDevPtr , int); +static int IsUSBLine(int); + + +#endif diff --git a/xc/programs/Xserver/hw/xfree86/input/acecad/acecad.man b/xc/programs/Xserver/hw/xfree86/input/acecad/acecad.man new file mode 100644 index 000000000..0f8996707 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/input/acecad/acecad.man @@ -0,0 +1,40 @@ +.\" $XFree86: xc/programs/Xserver/hw/xfree86/input/acecad/acecad.man,v 1.1 2001/08/13 19:35:00 dawes Exp $ +.\" shorthand for double quote that works everywhere. +.ds q \N'34' +.TH ACECAD __drivermansuffix__ __vendorversion__ +.SH NAME +acecad \- Acecad Flair input driver +.SH SYNOPSIS +.B "Section \*qInputDevice\*q" +.br +.BI " Identifier \*q" idevname \*q +.br +.B " Driver \*qacecad\*q" +.br +.BI " Option \*qDevice\*q \*q" devpath \*q +.br +\ \ ... +.br +.B EndSection +.SH DESCRIPTION +.B acecad +is an XFree86 input driver for Acecad Flair devices... +.PP +The +.B acecad +driver functions as a pointer input device, and may be used as the +X server's core pointer. +THIS MAN PAGE NEEDS TO BE FILLED IN. +.SH SUPPORTED HARDWARE +What is supported... +.SH CONFIGURATION DETAILS +Please refer to XF86Config(__filemansuffix__) for general configuration +details and for options that can be used with all input drivers. This +section only covers configuration details specific to this driver. +.PP +Config details... +.SH "SEE ALSO" +XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__). +.SH AUTHORS +Authors include... +Edouard TISSERANT diff --git a/xc/programs/Xserver/hw/xfree86/input/calcomp/Imakefile b/xc/programs/Xserver/hw/xfree86/input/calcomp/Imakefile new file mode 100644 index 000000000..f5eec8d8e --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/input/calcomp/Imakefile @@ -0,0 +1,26 @@ +XCOMM $XFree86: xc/programs/Xserver/hw/xfree86/input/calcomp/Imakefile,v 1.1 2001/08/12 22:48:43 alanh Exp $ + +#define IHaveModules +#include <Server.tmpl> + +SRCS = xf86Calcomp.c +OBJS = xf86Calcomp.o + +DRIVER = calcomp + +INCLUDES = -I. -I$(XF86COMSRC) -I../../loader -I$(XF86OSSRC) \ + -I$(SERVERSRC)/include -I$(XINCLUDESRC) -I$(EXTINCSRC) + +#if MakeHasPosixVariableSubstitutions +SubdirLibraryRule($(OBJS)) +#endif + +ModuleObjectRule() + +ObjectModuleTarget($(DRIVER),$(OBJS)) + +InstallObjectModule($(DRIVER),$(MODULEDIR),input) + +DependTarget() + +InstallDriverSDKObjectModule($(DRIVER),$(DRIVERSDKMODULEDIR),input) diff --git a/xc/programs/Xserver/hw/xfree86/input/calcomp/calcomp.man b/xc/programs/Xserver/hw/xfree86/input/calcomp/calcomp.man new file mode 100644 index 000000000..2b025c012 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/input/calcomp/calcomp.man @@ -0,0 +1,82 @@ +.\" $XFree86: xc/programs/Xserver/hw/xfree86/input/calcomp/calcomp.man,v 1.2 2001/08/12 22:51:29 alanh Exp $ +.\" shorthand for double quote that works everywhere. +.ds q \N'34' +.TH CALCOMP __drivermansuffix__ __vendorversion__ +.SH NAME +calcomp \- Calcomp input driver +.SH SYNOPSIS +.nf +.B "Section \*qInputDevice\*q" +.BI " Identifier \*q" idevname \*q +.B " Driver \*qcalcomp\*q" +.BI " Option \*qDevice\*q \*q" devpath \*q +\ \ ... +.B EndSection +.fi +.SH DESCRIPTION +.B calcomp +is an XFree86 input driver for Calcomp devices. +.PP +The +.B calcomp +driver functions as a pointer input device, and may be used as the +X server's core pointer. +.SH SUPPORTED HARDWARE +This driver supports the Calcomp binary format used by the Drawing Board II +and III series. +.SH CONFIGURATION DETAILS +Please refer to XF86Config(__filemansuffix__) for general configuration +details and for options that can be used with all input drivers. This +section only covers configuration details specific to this driver. +.PP +Both the 3 button stylus and the 4- or 16 button lens cursors can be used +without changing the configuration file. Support for pressure sensitivity +has not been tested, so the solid-tip stylus will probably not work. +.PP +This device supports the following entries: +.RS 8 +.TP 4 +.B Option \fI"Device"\fP \fI"path"\fP +sets the path to the special file which represents the serial line where +the tablet is plugged. This option is mandatory. +.TP 4 +.B Option \fI"Cursor"\fP \fI"Stylus"|"Puck"\fP +this option is supported for backward compatibility only, but it should +not be necessary. +.TP 4 +.B Option \fI"DeviceName"\fP \fI"name"\fP +sets the name of the X device. Some user-space programs may require a fixed +name, e.g. TABLET, to recognize the digitizer. +.TP 4 +.B Option \fI"Mode"\fP \fI"Relative"|"Absolute"\fP +sets the mode of the device. Currently only Absolute mode is supported. +.TP 4 +.B Option \fI"Pressure"\fP \fI"on"\fP +enables pressure reporting if your tablet supports it. This option is +untested and may not work. +.TP 4 +.B Option \fI"AlwaysCore"\fP \fI"on"\fP +enables the sharing of the core pointer. When this feature is enabled, the +device will take control of the core pointer (and thus will emit core events) +and at the same time will be able, when asked so, to report extended events. +.TP 4 +.B Option \fI"MinX"\fP \fI"number"\fP +X coordinate of the bottom left corner of the active zone. +.TP 4 +.B Option \fI"MinY"\fP \fI"number"\fP +Y coordinate of the bottom left corner of the active zone. +.TP 4 +.B Option \fI"MaxX"\fP \fI"Inumber"\fP +X coordinate of the top right corner of the active zone. +.TP 4 +.B Option \fI"MaxY"\fP \fI"number"\fP +Y coordinate of the top right corner of the active zone. +.TP 4 +.B Option \fI"DebugLevel"\fP \fInumber \fP +sets the level of debugging info reported. +.TP 4 +.RE +.SH "SEE ALSO" +XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__). +.SH AUTHORS +Martin Kroeker <mk@daveg.com> diff --git a/xc/programs/Xserver/hw/xfree86/input/calcomp/xf86Calcomp.c b/xc/programs/Xserver/hw/xfree86/input/calcomp/xf86Calcomp.c new file mode 100644 index 000000000..9d4f95bc2 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/input/calcomp/xf86Calcomp.c @@ -0,0 +1,834 @@ +/* + * Copyright (c) 2000,2001 Martin Kroeker (mk@daveg.com) + * sample driver used : + * Copyright (c) 1998 Metro Link Incorporated + * + * 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 X CONSORTIUM 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 Metro Link shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Metro Link. + * + * Except as contained in this notice, the names of Martin Kroeker and/or + * Daveg GmbH shall not be used in advertising or otherwise to promote the + * sale, use or other dealings in this Software without prior written + * authorization from Martin Kroeker or Daveg GmbH. + * + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/input/calcomp/xf86Calcomp.c,v 1.2 2001/08/15 11:54:27 tsi Exp $ */ + +#define _CALCOMP_C_ +/***************************************************************************** + * Standard Headers + ****************************************************************************/ + +#include <misc.h> +#include <xf86.h> +#define NEED_XF86_TYPES +#include <xf86_ansic.h> +#include <xf86_OSproc.h> +#include <xf86Xinput.h> +#include <xisb.h> +#include <exevents.h> /* Needed for InitValuator/Proximity stuff */ + +/***************************************************************************** + * Local Headers + ****************************************************************************/ +#include "xf86Calcomp.h" + +/***************************************************************************** + * Variables without includable headers + ****************************************************************************/ + #define DEBUG 1 +/***************************************************************************** + * Local Variables + ****************************************************************************/ + +InputDriverRec CALCOMP = { + 1, + "calcomp", + NULL, + CalcompPreInit, /*preinit ?*/ + NULL, + NULL, + 0 + }; + +/* + * Be sure to set vmin appropriately for your device's protocol. You want to + * read a full packet before returning + */ +static const char *default_options[] = +{ + "Device", "/dev/ttyS1", + "BaudRate", "9600", + "StopBits", "1", + "DataBits", "8", + "Parity", "None", + "Vmin", "1", + "Vtime", "1", + "FlowControl", "None" +}; + + +#ifdef XFree86LOADER + +static XF86ModuleVersionInfo VersionRec = +{ + "calcomp", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_XINPUT, + ABI_XINPUT_VERSION, + MOD_CLASS_XINPUT, + {0, 0, 0, 0} /* signature, to be patched into the file by + * a tool */ +}; + +static const char *reqSymbols[] = { + "AddEnabledDevice", + "ErrorF", + "InitButtonClassDeviceStruct", + "InitProximityClassDeviceStruct", + "InitValuatorAxisStruct", + "InitValuatorClassDeviceStruct", + "InitPtrFeedbackClassDeviceStruct", + "RemoveEnabledDevice", + "Xcalloc", + "Xfree", + "XisbBlockDuration", + "XisbFree", + "XisbNew", + "XisbRead", + "XisbTrace", + "screenInfo", + "xf86AddInputDriver", + "xf86AllocateInput", + "xf86CloseSerial", + "xf86CollectInputOptions", + "xf86ErrorFVerb", + "xf86FindOptionValue", + "xf86GetMotionEvents", + "xf86GetVerbosity", + "xf86MotionHistoryAllocate", + "xf86NameCmp", + "xf86OpenSerial", + "xf86CloseSerial", + "xf86OptionListCreate", + "xf86OptionListMerge", + "xf86OptionListReport", + "xf86PostButtonEvent", + "xf86PostMotionEvent", + "xf86PostProximityEvent", + "xf86ProcessCommonOptions", + "xf86ScaleAxis", + "xf86SetIntOption", + "xf86SetStrOption", + "xf86XInputSetScreen", + "xf86XInputSetSendCoreEvents", + NULL + }; + + +static pointer +CalcompSetupProc( pointer module, + pointer options, + int *errmaj, + int *errmin ) + { + xf86LoaderReqSymLists(reqSymbols, NULL); + xf86AddInputDriver(&CALCOMP, module, 0); + return (pointer) 1; + } + + + +XF86ModuleData calcompModuleData = { &VersionRec, CalcompSetupProc, NULL }; + + +#endif /* XFree86LOADER */ + + + + +/***************************************************************************** + * Function Definitions + ****************************************************************************/ + + +/* + * The TearDownProc may have to be tailored to your device + */ +/****************************************************** +static void +TearDownProc( pointer p ) +{ + LocalDevicePtr local = (LocalDevicePtr) p; + CALCOMPPrivatePtr priv = (CALCOMPPrivatePtr) local->private; + + ErrorF ("Calcomp TearDownProc Called\n"); + + DeviceOff (local->dev); + + + xf86CloseSerial (local->fd); + XisbFree (priv->buffer); + xfree (priv); + xfree (local->name); + xfree (local); +} +**********************************************************/ + + + +/* + * The DeviceControl function should not need to be changed + * except to remove ErrorFs + */ +static Bool +DeviceControl (DeviceIntPtr dev, int mode) +{ + Bool RetValue; + +/* ErrorF ("DeviceControl called mode = %d\n", mode);*/ + switch (mode) + { + case DEVICE_INIT: +/* ErrorF ("\tINIT\n");*/ + DeviceInit (dev); + RetValue = Success; + break; + case DEVICE_ON: +/* ErrorF ("\tON\n");*/ + RetValue = DeviceOn( dev ); + break; + case DEVICE_OFF: +/* ErrorF ("\tOFF\n");*/ + RetValue = DeviceOff( dev ); + break; + case DEVICE_CLOSE: +/* ErrorF ("\tCLOSE\n");*/ + RetValue = DeviceClose( dev ); + break; + default: + ErrorF ("\tBAD MODE\n"); + RetValue = BadValue; + } + + return( RetValue ); +} + +/* + * The DeviceOn function should not need to be changed + */ +static Bool +DeviceOn (DeviceIntPtr dev) +{ + LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate; + + AddEnabledDevice (local->fd); + dev->public.on = TRUE; + return (Success); +} + +/* + * The DeviceOff function should not need to be changed + */ +static Bool +DeviceOff (DeviceIntPtr dev) +{ + LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate; + + RemoveEnabledDevice (local->fd); + dev->public.on = FALSE; + return (Success); +} + +/* + * The DeviceClose function should not need to be changed + */ +static Bool +DeviceClose (DeviceIntPtr dev) +{ + return (Success); +} + +/* + * The DeviceInit function will need to be tailored to your device + */ +static Bool +DeviceInit (DeviceIntPtr dev) +{ + LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate; + CALCOMPPrivatePtr priv = (CALCOMPPrivatePtr) (local->private); + unsigned char map[] = + {0, 1}; + + /* + * Set up buttons, valuators etc for your device + */ + if (InitButtonClassDeviceStruct (dev, 1, map) == FALSE) + { + ErrorF ("Unable to allocate CALCOMP ButtonClassDeviceStruct\n"); + return !Success; + } + if (InitFocusClassDeviceStruct (dev) == FALSE) { /* is this necessary? */ + ErrorF ("Unable to allocate CALCOMP focus class device\n"); + return !Success; + } + + /* + * this example device reports motions on 2 axes in absolute coordinates. + * Device may reports touch pressure on the 3rd axis. + */ + if (InitValuatorClassDeviceStruct (dev, 3, xf86GetMotionEvents, + local->history_size, Absolute) == FALSE) + { + ErrorF ("Unable to allocate CALCOMP ValuatorClassDeviceStruct\n"); + return !Success; + } + else + { + InitValuatorAxisStruct (dev, 0, priv->min_x, priv->max_x, + 39400, + 0 /* min_res */ , + 12000 /* max_res */ ); + InitValuatorAxisStruct (dev, 1, priv->min_y, priv->max_y, + 39400, + 0 /* min_res */ , + 39400 /* max_res */ ); + + InitValuatorAxisStruct (dev, 2, priv->min_z, priv->max_z, + 32, + 0 /* min_res */ , + 32 /* max_res */ ); + } + + if (InitProximityClassDeviceStruct (dev) == FALSE) + { + ErrorF ("unable to allocate CALCOMP ProximityClassDeviceStruct\n"); + return !Success; + } + + + if (InitPtrFeedbackClassDeviceStruct(dev, + ControlProc) == FALSE) { + ErrorF("unable to init ptr feedback\n"); + return !Success; + } + + /* + * Allocate the motion events buffer. + */ + xf86MotionHistoryAllocate (local); + return (Success); +} + +/* + * The ReadInput function will have to be tailored to your device + */ +static void +ReadInput (LocalDevicePtr local) +{ + int x=0, y=0 , z=0; + /*int state;*/ + int prox,buttons; + Bool is_absolute = TRUE; /* FIXME */ + CALCOMPPrivatePtr priv = (CALCOMPPrivatePtr) (local->private); + + /* + * set blocking to -1 on the first call because we know there is data to + * read. Xisb automatically clears it after one successful read so that + * succeeding reads are preceeded by a select with a 0 timeout to prevent + * read from blocking indefinitely. + */ + XisbBlockDuration (priv->buffer, -1); + while (CALCOMPGetPacket (priv) == Success) + { + /* + * Examine priv->packet and call these functions as appropriate: + * + xf86PostProximityEvent + xf86PostMotionEvent + xf86PostButtonEvent + */ + /* Format of 6 bytes data packet in Calcomp Binary Encoding + + Byte 1 + bit 7 Phasing bit, always 1 + bit 6 Buttons on a 16bit cursor + bit 5 Button 3 + bit 4 Button 2 + bit 3 Button 1 + bit 2 Button 0 (Stylus tip) + bit 1 X15 + bit 0 X14 + Byte 2 + bit 7 Always 0 + bits 6-0 = X13 - X7 + Byte 3 + bit 7 Always 0 + bits 6-0 = X6 - X0 + Byte 4 + bit 7 Always 0 + bit 6 Proximity + bits 3-0 = Y17 - Y14 + Byte 5 + bit 7 Always 0 + bits 6-0 = Y13 - Y7 + Byte 6 + bit 7 Always 0 + bits 6-0 = Y6 - Y0 + */ + x = priv->packet[2] + priv->packet[1] * 128 + +(priv->packet[0] & 0x03) *128*128; + y = priv->packet[5] + priv->packet[4]*128 +priv->packet[3]*128*128; + y = priv->max_y -y; + prox = ((int)priv->packet[3] & PROXIMITY_BIT)? 0: 1; + + buttons = (((int)priv->packet[0] & BUTTON_BITS) >>2); + if (buttons && ! priv->pressure ) { + if (buttons >15) { + buttons = buttons -15; + }else{ + buttons = buttons /2; + if (buttons <4 ) buttons = buttons +1; + } + }else{ + z = buttons; /* button bits convey pressure data*/ + if (z >= priv->button_threshold) buttons = 1; +xf86Msg(X_INFO,"Tablett pressurebutton = %d >= %d\n",z,priv->button_threshold); + } +/*xf86Msg(X_INFO,"Tablett x y prox buttons = %d %d %d %d\n",x,y,prox,buttons);*/ + if (prox) { + if (!(priv->prox)) { + xf86PostProximityEvent(local->dev, 1, 0, 2, x, y); + } + + if ((is_absolute && ((priv->x != x) || (priv->y != y))) + || (!is_absolute && (x || y))) { + priv->x = x; + priv->y = y; + + if (is_absolute || priv->prox) { + xf86PostMotionEvent(local->dev, is_absolute, 0, 3, x, y, z); + + } + } + if (priv->buttons != buttons) { + int delta; + int button; + delta = buttons - priv->buttons; + button = (delta > 0)? delta: ((delta == 0)? priv->buttons : -delta); + if (priv->buttons != buttons) { + xf86PostButtonEvent(local->dev, is_absolute, button, + (delta > 0), 0, 2, x, y); + } + } + priv->buttons = buttons; + priv->x = x; + priv->y = y; + priv->prox = prox; + } else { /* !PROXIMITY */ + /* Any changes in buttons are ignored when !proximity */ + if (priv->prox) xf86PostProximityEvent(local->dev, 0, 0, 2, x, y); + priv->prox = 0; + } + + } /* while packets come in */ +} + +/* + * The ControlProc function may need to be tailored for your device + */ +static void +ControlProc (DeviceIntPtr device, PtrCtrl * control) +{ +} +static int +ChangeControlProc(LocalDevicePtr local, xDeviceCtl *control) +{ +return(Success); +} +/* + * the CloseProc should not need to be tailored to your device + */ +static void +CloseProc (LocalDevicePtr local) +{ +} + +/* + * The SwitchMode function may need to be tailored for your device + */ +static int +SwitchMode (ClientPtr client, DeviceIntPtr dev, int mode) +{ + return (Success); +} + +/* + * The ConvertProc function may need to be tailored for your device. + * This function converts the device's valuator outputs to x and y coordinates + * to simulate mouse events. + */ +static Bool +ConvertProc (LocalDevicePtr local, + int first, + int num, + int v0, + int v1, + int v2, + int v3, + int v4, + int v5, + int *x, + int *y) +{ +CALCOMPPrivatePtr priv=(CALCOMPPrivatePtr) local->private; +double factorX,factorY; + +xf86Msg(X_INFO,"Calcomp ConvertProc called\n"); +if (first !=0 || num == 1) return FALSE; + +factorX= ((double) priv->screen_width) + /(priv->max_x - priv->min_x); +factorY= ((double) priv->screen_height) + /(priv->max_y - priv->min_y); + + *x = v0*factorX; + *y = v1*factorY; + return (Success); +} + +/* + * the QueryHardware fuction should be tailored to your device to + * verify the device is attached and functional and perform any + * needed initialization. + */ +static Bool +QueryHardware (int fd, CALCOMPPrivatePtr priv) +{ +char buffer[255]; +int err; + + SYSCALL(err = write(fd, DB_COMM_SETUP, strlen(DB_COMM_SETUP))); + if (err<0) return !Success; + + xf86WaitForInput(-1,500); + + SYSCALL(err = write(fd, DB_UPPER_ORIGIN, strlen(DB_UPPER_ORIGIN))); + if (err<0) return !Success; + + xf86WaitForInput(-1,500); + + SYSCALL(err = write(fd, DB_BINARY_FMT, strlen(DB_BINARY_FMT))); + if (err<0) return !Success; + + xf86WaitForInput(-1,500); + + SYSCALL(err = write(fd, DB_XINCREMENT, strlen(DB_XINCREMENT))); + if (err<0) return !Success; + + xf86WaitForInput(-1,500); + + SYSCALL(err = write(fd, DB_YINCREMENT, strlen(DB_YINCREMENT))); + if (err<0) return !Success; + + xf86WaitForInput(-1,500); + + SYSCALL(err = write(fd, DB_1000LPI, strlen(DB_1000LPI))); + if (err<0) return !Success; + + xf86WaitForInput(-1,500); + + SYSCALL(err = write(fd, DB_STREAM_MODE, strlen(DB_STREAM_MODE))); + if (err<0) return !Success; + + xf86WaitForInput(-1,500); + if (priv->pressure) + SYSCALL(err = write(fd, DB_PRESSURE_ON, strlen(DB_PRESSURE_ON))); + else + SYSCALL(err = write(fd, DB_PRESSURE_OFF, strlen(DB_PRESSURE_OFF))); + if (err<0) return !Success; + + xf86WaitForInput(-1,500); + + if (!xf86CalWriteAndRead(fd, DB_FIRMID, buffer, 35, 1)) + return !Success; + + xf86Msg(X_INFO,"Calcomp firmware ID : %s\n", buffer); + memset(buffer,32,35); + + xf86WaitForInput(-1,500); + + if (!xf86CalWriteAndRead(fd, DB_PRODID, buffer, 20, 1)) + return !Success; + xf86Msg(X_INFO,"Product ID : %s\n", buffer); + + memset(buffer,32,20); + + xf86WaitForInput(-1,500); + + if (!xf86CalWriteAndRead(fd, DB_CONFIG, buffer, 6, 1)) + return !Success; + priv->max_x = (int)buffer[2] + ((int)buffer[1] << 7) + + (((int)buffer[0]&0x03)<<14); + priv->max_y = (int)buffer[5] + ((int)buffer[4] << 7); + + xf86Msg(X_INFO,"Tablet size : %d x %d \n", priv->max_x,priv->max_y); + + + xf86WaitForInput(-1,500); + + + SYSCALL(err = write(fd, DB_ABSOLUTE, strlen(DB_ABSOLUTE))); + if (err<0) return !Success; + + + +/* +*/ + return (Success); + +} + +static InputInfoPtr +CalcompPreInit( InputDriverPtr drv, + IDevPtr dev, int flags) + { + + InputInfoPtr local; + CALCOMPPrivatePtr priv = xcalloc (1, sizeof (CALCOMPPrivateRec)); + char *s; + + if (!(local = xf86AllocateInput(drv, 0))) + return NULL; + + xf86Msg (X_INFO,"Calcomp SetupProc called\n"); + if ((!local) || (!priv)) + goto SetupProc_fail; + + + xf86CollectInputOptions(local, default_options, NULL); + + xf86OptionListReport( local->options ); + local->fd = xf86OpenSerial (local->options); + + + + + + + + if (local->fd == -1) + { + xf86Msg (X_ERROR,"CALCOMP driver unable to open device\n"); + goto SetupProc_fail; + } else { + xf86Msg( X_INFO,"CALCOMP driver: Serial device opened\n"); + } + + priv->min_x = xf86SetIntOption( local->options, "MinX", 0 ); + priv->max_x = xf86SetIntOption( local->options, "MaxX", 1000 ); + priv->min_y = xf86SetIntOption( local->options, "MinY", 0 ); + priv->max_y = xf86SetIntOption( local->options, "MaxY", 1000 ); + priv->min_z = xf86SetIntOption( local->options, "MinZ", 0 ); + priv->max_z = xf86SetIntOption( local->options, "MaxZ", 32 ); + priv->button_threshold = xf86SetIntOption (local->options, "ButtonThreshold", 16 ); + priv->pressure = xf86SetIntOption (local->options, "Pressure", 0); + priv->untouch_delay = xf86SetIntOption( local->options, "UntouchDelay", 10 ); + priv->report_delay = xf86SetIntOption( local->options, "ReportDelay", 40 ); + priv->screen_num = xf86SetIntOption( local->options, "ScreenNumber", 0 ); + priv->button_number = xf86SetIntOption( local->options, "ButtonNumber", 1 ); + + xf86Msg(X_INFO,"options read MaxX=%d, MaxY=%d\n",priv->max_x,priv->max_y); + + s = xf86FindOptionValue (local->options, "ReportingMode"); + if ((s) && (xf86NameCmp (s, "raw") == 0)) + + priv->reporting_mode = TS_Raw; + else + priv->reporting_mode = TS_Scaled; + + priv->checksum = 0; + priv->buffer = XisbNew (local->fd, 200); + + DBG (9, XisbTrace (priv->buffer, 1)); + + /* + * Verify that your hardware is attached and fuctional if you can + */ + if (QueryHardware (local->fd, priv) != Success) + { + xf86Msg (X_ERROR,"Unable to query/initialize CALCOMP hardware.\n"); + goto SetupProc_fail; + }else + xf86Msg (X_INFO,"Calcomp tablet queried OK\n"); + + local->name = xf86SetStrOption( local->options, "DeviceName", "CALCOMP XInput Device"); + xf86Msg(X_CONFIG," Calcomp device name is %s\n",local->name); + /* Set the type that's appropriate for your device + * XI_KEYBOARD + * XI_MOUSE + * XI_TABLET + * XI_TOUCHSCREEN + * XI_TOUCHPAD + * XI_BARCODE + * XI_BUTTONBOX + * XI_KNOB_BOX + * XI_ONE_KNOB + * XI_NINE_KNOB + * XI_TRACKBALL + * XI_QUADRATURE + * XI_ID_MODULE + * XI_SPACEBALL + * XI_DATAGLOVE + * XI_EYETRACKER + * XI_CURSORKEYS + * XI_FOOTMOUSE + */ + local->type_name = XI_TABLET; + /* + * Standard setup for the local device record + */ + local->device_control = DeviceControl; + local->read_input = ReadInput; + local->control_proc = ChangeControlProc; + local->close_proc = CloseProc; + local->switch_mode = SwitchMode; + local->conversion_proc = ConvertProc; + local->dev = NULL; + local->private = priv; + local->private_flags = 0; + local->history_size = xf86SetIntOption( local->options, "HistorySize", 0 ); + local->flags |= XI86_CONFIGURED; + + xf86Msg(X_INFO,"Calcomp base setup finished\n"); + return (local); +SetupProc_fail: + xf86Msg (X_ERROR,"Calcomp setup failed, unloading tablet driver\n"); +/* taken from xf86Wacom*/ + xfree (priv); + xf86DeleteInput(local, 0); +/* * */ + return (NULL); + + + } + +/* + * This function should be renamed for your device and tailored to handle + * your device's protocol. + */ +static Bool +CALCOMPGetPacket (CALCOMPPrivatePtr priv) +{ + int count = 0; + int c; + + while ((c = XisbRead (priv->buffer)) >= 0) + { + /* + * fail after 500 bytes so the server doesn't hang forever if a + * device sends bad data. + */ + if (count++ > 500) + return (!Success); + + + if (c > 127) /* phasing bit set, start of packet */ + { + priv->packeti=0; + priv->packet[priv->packeti++] = (unsigned char) c; + } + else { + if (priv->packeti >0 && priv->packeti < CALCOMP_BODY_LEN) + priv->packet[priv->packeti++] = (unsigned char) c; + if (priv->packeti == CALCOMP_BODY_LEN) + { + priv->packeti=0; + return (Success); + } + } + } + return (!Success); +} + +/* +** xf86CalWriteAndRead +** Write data, and get the response. +*/ +static char * +xf86CalWriteAndRead(int fd, char *data, char *buffer, int len, int cr_term) +{ + int err, numread = 0; + int retries = 5; + + + + xf86FlushInput(fd); + + SYSCALL(err = write(fd, data, strlen(data))); + if (err == -1) { + xf86Msg(X_ERROR,"Calcomp write"); + return NULL; + } +do { + err=xf86WaitForInput(fd, 2000); + if (err < 0 ) { + xf86Msg(X_ERROR,"Calcomp select failed\n"); + return NULL; + } + retries--; + } + while (err<1 && retries >0); + +if (retries<=0) { + xf86Msg(X_WARNING,"Timeout while reading Calcomp tablet. No tablet connected ???\n"); + return NULL; + } + + while (numread < len) { + if (err == -1) { + xf86Msg(X_ERROR,"Calcomp select"); + return NULL; + } + + SYSCALL(err = read(fd, buffer + numread++, 1)); + if (err == -1) { + xf86Msg(X_ERROR,"Calcomp read"); + return NULL; + } + if (!err) { + --numread; + break; + } + if (cr_term && buffer[numread - 1] == '\r') { + buffer[numread - 1] = 0; + break; + } + } + buffer[numread] = 0; + return buffer; + } + diff --git a/xc/programs/Xserver/hw/xfree86/input/calcomp/xf86Calcomp.h b/xc/programs/Xserver/hw/xfree86/input/calcomp/xf86Calcomp.h new file mode 100644 index 000000000..6a1ed031d --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/input/calcomp/xf86Calcomp.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2000-2001 Martin Kroeker (mk@daveg.com) + * code derived from sample driver + * Copyright (c) 1998 Metro Link Incorporated + * + * 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 X CONSORTIUM 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 Metro Link shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Metro Link. + * + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/input/calcomp/xf86Calcomp.h,v 1.1 2001/08/12 22:48:43 alanh Exp $ */ + +#ifndef _CALCOMP_H_ +#define _CALCOMP_H_ + +/****************************************************************************** + * Definitions + * structs, typedefs, #defines, enums + *****************************************************************************/ +#define CALCOMP_PACKET_SIZE 5 +#define CALCOMP_INIT_CHECKSUM 0 +#define CALCOMP_BODY_LEN 6 + + + +/*************************************************************************/ +#define SYSCALL(call) while(((call) == -1) && (errno == EINTR)) + +#define DB_COMM_SETUP "\033%C1N81\r" /* Serial communication setup */ +#define DB_FIRMID "\033%__V\r" /* Request firmware ID string */ +#define DB_PRODID "\033%__p\r" /* Request product ID string */ +#define DB_CONFIG "\033%VS\r" /* Send configuration (max coords) */ + +#define DB_ABSOLUTE "\033%IR\r" /* Absolute mode */ +#define DB_RELATIVE "\033%IT\r" /* Relative mode */ + +#define DB_UPPER_ORIGIN "\033%L1\r" /* Origin upper left */ +#define DB_1000LPI "\033%JR1000,0\r" /* 1000 lines per inch */ + +#define DB_PROMPT_MODE "\033%Q?\r" /* Prompt mode (untested!) */ +#define DB_STREAM_MODE "\033%IR\r" /* Stream mode */ +#define DB_XINCREMENT "\033%X1\r" +#define DB_YINCREMENT "\033%Y1\r" /* Set increment to 1 */ +#define DB_BINARY_FMT "\033%^23\r" /* Calcomp binary mode */ +#define DB_PRESSURE_OFF "\033%VA0\r" /* Select button or pressure */ +#define DB_PRESSURE_ON "\033%VA1\r" /* reporting */ +#define DB_PROMPT "?" /* Prompt for current position */ + +#define PHASING_BIT 0x80 +#define PROXIMITY_BIT 0x20 +#define BUTTON_BITS 0x7c +#define COORD_BITS 0x7f +#define tcflush(fd, n) xf86FlushInput((fd)) +#undef read +#define read(a,b,c) xf86ReadSerial((a),(b),(c)) +#undef write +#define write(a,b,c) xf86WriteSerial((a),(char*)(b),(c)) +#undef close +#define close(a) xf86CloseSerial((a)) + +/*************************************************************************/ +typedef enum +{ + CALCOMP_normal, /*CALCOMP_type,*/ CALCOMP_body, CALCOMP_checksum +} +CALCOMPState; + +#define WORD_ASSEMBLY(byte1, byte2) (((byte2) << 8) | (byte1)) + +typedef struct _CALCOMPPrivateRec +{ + int min_x; /* Minimum x reported by calibration */ + int max_x; /* Maximum x */ + int min_y; /* Minimum y reported by calibration */ + int max_y; /* Maximum y */ + int min_z; + int max_z; + int button_threshold; /* Z > button threshold = button click */ + int pressure; /* 0 or 1, do we need pressure info */ + int axes; + int prox; /* Proximity */ + int x,y; /* x,y values */ + int buttons; /* button state */ + Bool button_down; /* is the "button" currently down */ + int button_number; /* which button to report */ + int reporting_mode; /* TS_Raw or TS_Scaled */ + + int untouch_delay; /* Delay before reporting an untouch (in ms) */ + int report_delay; /* Delay between touch report packets */ + + int screen_num; /* Screen associated with the device */ + int screen_width; /* Width of the associated X screen */ + int screen_height; /* Height of the screen */ + XISBuffer *buffer; + unsigned char packet[CALCOMP_PACKET_SIZE]; /* packet being/just read */ + int packeti; /* index into packet */ + unsigned char checksum; /* Current checksum of data in assembly * + * buffer */ + CALCOMPState lex_mode; +} +CALCOMPPrivateRec, *CALCOMPPrivatePtr; + +/****************************************************************************** + * Declarations + *****************************************************************************/ +static MODULESETUPPROTO( CalcompSetupProc ); +/*static void TearDownProc (pointer p);*/ +static Bool DeviceControl (DeviceIntPtr, int); +static Bool DeviceOn (DeviceIntPtr); +static Bool DeviceOff (DeviceIntPtr); +static Bool DeviceClose (DeviceIntPtr); +static Bool DeviceInit (DeviceIntPtr); +static void ReadInput (LocalDevicePtr); +static void ControlProc (DeviceIntPtr, PtrCtrl *); +static int ChangeControlProc (LocalDevicePtr, xDeviceCtl *); +static void CloseProc (LocalDevicePtr); +static int SwitchMode (ClientPtr, DeviceIntPtr, int); +static Bool ConvertProc (LocalDevicePtr, int, int, int, int, int, int, int, int, int *, int *); +static Bool QueryHardware (int , CALCOMPPrivatePtr); +static Bool CALCOMPGetPacket (CALCOMPPrivatePtr priv); +static char * xf86CalWriteAndRead(int, char *, char *, int , int ); +static InputInfoPtr CalcompPreInit(InputDriverPtr, IDevPtr, int) ; +/* + * DO NOT PUT ANYTHING AFTER THIS ENDIF + */ +#endif diff --git a/xc/programs/Xserver/hw/xfree86/input/dmc/Imakefile b/xc/programs/Xserver/hw/xfree86/input/dmc/Imakefile new file mode 100644 index 000000000..e61fe57a3 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/input/dmc/Imakefile @@ -0,0 +1,30 @@ +XCOMM $XFree86: xc/programs/Xserver/hw/xfree86/input/dmc/Imakefile,v 1.1 2001/08/17 13:27:55 dawes Exp $ + +#define IHaveModules +#include <Server.tmpl> + +SRCS = xf86DMC.c +OBJS = xf86DMC.o + +DRIVER = dmc + +INCLUDES = -I. -I$(XF86COMSRC) -I../../loader -I$(XF86OSSRC) \ + -I$(SERVERSRC)/include -I$(XINCLUDESRC) -I$(EXTINCSRC) + +#if MakeHasPosixVariableSubstitutions +SubdirLibraryRule($(OBJS)) +#endif + +ModuleObjectRule() + +ObjectModuleTarget($(DRIVER),$(OBJS)) + +InstallObjectModule($(DRIVER),$(MODULEDIR),input) + +#if !defined(XF86DriverSDK) +InstallModuleManPage($(DRIVER)) +#endif + +DependTarget() + +InstallDriverSDKObjectModule($(DRIVER),$(DRIVERSDKMODULEDIR),input) diff --git a/xc/programs/Xserver/hw/xfree86/input/dmc/dmc.man b/xc/programs/Xserver/hw/xfree86/input/dmc/dmc.man new file mode 100644 index 000000000..f1e3bf1f9 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/input/dmc/dmc.man @@ -0,0 +1,39 @@ +.\" $XFree86: xc/programs/Xserver/hw/xfree86/input/dmc/dmc.man,v 1.1 2001/08/17 13:27:55 dawes Exp $ +.\" shorthand for double quote that works everywhere. +.ds q \N'34' +.TH DMC __drivermansuffix__ __vendorversion__ +.SH NAME +dmc \- DMC input driver +.SH SYNOPSIS +.B "Section \*qInputDevice\*q" +.br +.BI " Identifier \*q" idevname \*q +.br +.B " Driver \*qdmc\*q" +.br +.BI " Option \*qDevice\*q \*q" devpath \*q +.br +\ \ ... +.br +.B EndSection +.SH DESCRIPTION +.B dmc +is an XFree86 input driver for DMC FIT10-controller... +.PP +The +.B dmc +driver functions as a pointer input device, and may be used as the +X server's core pointer. +THIS MAN PAGE NEEDS TO BE FILLED IN. +.SH SUPPORTED HARDWARE +What is supported... +.SH CONFIGURATION DETAILS +Please refer to XF86Config(__filemansuffix__) for general configuration +details and for options that can be used with all input drivers. This +section only covers configuration details specific to this driver. +.PP +Config details... +.SH "SEE ALSO" +XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__). +.SH AUTHORS +Authors include... diff --git a/xc/programs/Xserver/hw/xfree86/input/dmc/xf86DMC.c b/xc/programs/Xserver/hw/xfree86/input/dmc/xf86DMC.c new file mode 100644 index 000000000..b28941787 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/input/dmc/xf86DMC.c @@ -0,0 +1,692 @@ +/* + * Copyright (c) 1999 Machine Vision Holdings Incorporated + * Author: Mayk Langer <langer@vsys.de> + * + * Template driver used: Copyright (c) 1998 Metro Link Incorporated + * + * 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, cpy, 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 X CONSORTIUM 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 Metro Link shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Metro Link. + * + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/input/dmc/xf86DMC.c,v 1.1 2001/08/17 13:27:55 dawes Exp $ */ + +#define _DMC_C_ + +#include <misc.h> +#include <xf86.h> +#define NEED_XF86_TYPES +#include <xf86_ansic.h> +#include <xf86_OSproc.h> +#include <xf86Xinput.h> +#include <xisb.h> +#include <exevents.h> + +#include "xf86DMC.h" + +InputDriverRec DMC = { + 1, + "dmc", + NULL, + DMCPreInit, + /*DMCUnInit*/NULL, + NULL, + 0 +}; + + + +#ifdef XFree86LOADER + +static XF86ModuleVersionInfo VersionRec = +{ + "dmc", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_XINPUT, + ABI_XINPUT_VERSION, + MOD_CLASS_XINPUT, + {0, 0, 0, 0} /* signature, to be patched into the file by + * a tool */ +}; + + +static const char *reqSymbols[] = { + "AddEnabledDevice", + "ErrorF", + "InitButtonClassDeviceStruct", + "InitProximityClassDeviceStruct", + "InitValuatorAxisStruct", + "InitValuatorClassDeviceStruct", + "InitPtrFeedbackClassDeviceStruct", + "RemoveEnabledDevice", + "Xcalloc", + "Xfree", + "XisbBlockDuration", + "XisbFree", + "XisbNew", + "XisbRead", + "XisbTrace", + "screenInfo", + "xf86AddInputDriver", + "xf86AllocateInput", + "xf86CloseSerial", /* first one */ + "xf86CollectInputOptions", + "xf86ErrorFVerb", + "xf86FindOptionValue", + "xf86GetMotionEvents", + "xf86GetVerbosity", + "xf86MotionHistoryAllocate", + "xf86NameCmp", + "xf86OpenSerial", + "xf86CloseSerial", /* second one ? */ + "xf86OptionListCreate", + "xf86OptionListMerge", + "xf86OptionListReport", + "xf86PostButtonEvent", + "xf86PostMotionEvent", + "xf86PostProximityEvent", + "xf86ProcessCommonOptions", + "xf86RemoveLocalDevice", + "xf86ScaleAxis", + "xf86SetIntOption", + "xf86SetStrOption", + "xf86XInputSetScreen", + "xf86XInputSetSendCoreEvents", + NULL +}; + + +static pointer +DMCSetupProc( pointer module, + pointer options, + int *errmaj, + int *errmin ) +{ + xf86LoaderReqSymLists(reqSymbols, NULL); + xf86AddInputDriver(&DMC, module, 0); + return (pointer) 1; +} + +XF86ModuleData dmcModuleData = { &VersionRec, DMCSetupProc, NULL }; + + +#endif /* XFree86LOADER */ + + +/* + * Be sure to set vmin appropriately for your device's protocol. You want to + * read a full packet before returning + */ +static const char *default_options[] = +{ + /* "Device", "/dev/ttyS1",*/ + "BaudRate", "9600", + "StopBits", "1", + "DataBits", "8", + "Parity", "None", + "Vmin", "3", + "Vtime", "1", + "FlowControl", "None", + NULL, +}; + + +/***************************************************************************** + * Function Definitions + ****************************************************************************/ + + + +static InputInfoPtr +DMCPreInit(InputDriverPtr drv, IDevPtr dev, int flags) +{ + InputInfoPtr pInfo; + DMCPrivatePtr priv = xcalloc (1, sizeof (DMCPrivateRec)); + char *s; + + if (!priv) + return NULL; + + if (!(pInfo = xf86AllocateInput(drv, 0))) { + xfree(priv); + return NULL; + } + + priv->min_x = 0; + priv->max_x = 1024; + priv->min_y = 768; + priv->max_y = 0; + priv->screen_num = 0; + priv->screen_width = -1; + priv->screen_height = -1; + priv->lex_mode = DMC_byte0; + priv->swap_xy = 0; + priv->button_down = FALSE; + priv->button_number = 1; + priv->proximity = FALSE; + priv->pen_down = 0; + + pInfo->type_name = XI_TOUCHSCREEN; + pInfo->device_control = DeviceControl; + pInfo->read_input = ReadInput; + pInfo->control_proc = ControlProc; + pInfo->close_proc = CloseProc; + pInfo->switch_mode = SwitchMode; + pInfo->conversion_proc = ConvertProc; + pInfo->dev = NULL; + pInfo->private = priv; + pInfo->private_flags = 0; + pInfo->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS; + pInfo->conf_idev = dev; + + xf86CollectInputOptions(pInfo, default_options, NULL); + + xf86OptionListReport( pInfo->options ); + + pInfo->fd = xf86OpenSerial (pInfo->options); + if (pInfo->fd == -1) + { + ErrorF ("DMC driver unable to open device\n"); + goto SetupProc_fail; + } + xf86CloseSerial(pInfo->fd); + /* + * Process the options for your device like this + */ + priv->min_x = xf86SetIntOption( pInfo->options, "MinX", 0 ); + priv->max_x = xf86SetIntOption( pInfo->options, "MaxX", 1024 ); + priv->min_y = xf86SetIntOption( pInfo->options, "MinY", 768 ); + priv->max_y = xf86SetIntOption( pInfo->options, "MaxY", 0 ); + priv->screen_num = xf86SetIntOption( pInfo->options, "ScreenNumber", 0 ); + priv->button_number = xf86SetIntOption( pInfo->options, "ButtonNumber", 1 ); + priv->swap_xy = xf86SetIntOption( pInfo->options, "SwapXY", 0 ); + priv->buffer = NULL; + s = xf86FindOptionValue (pInfo->options, "ReportingMode"); + if ((s) && (xf86NameCmp (s, "raw") == 0)) + priv->reporting_mode = TS_Raw; + else + priv->reporting_mode = TS_Scaled; + + priv->proximity = FALSE; + priv->button_down = FALSE; + priv->lex_mode = DMC_byte0; + + if (QueryHardware (priv) != Success) + { + ErrorF ("Unable to query/initialize DMC hardware.\n"); + goto SetupProc_fail; + } + + /* this results in an xstrdup that must be freed later */ + pInfo->name = xf86SetStrOption( pInfo->options, "DeviceName", "DMC"); + xf86ProcessCommonOptions(pInfo, pInfo->options); + + pInfo->flags |= XI86_CONFIGURED; + return (pInfo); + + SetupProc_fail: + if ((pInfo) && (pInfo->fd)) + xf86CloseSerial (pInfo->fd); + if ((pInfo) && (pInfo->name)) + xfree (pInfo->name); + + if ((priv) && (priv->buffer)) + XisbFree (priv->buffer); + if (priv) + xfree (priv); + return (pInfo); +} + +static Bool +DeviceControl (DeviceIntPtr dev, int mode) +{ + InputInfoPtr pInfo = dev->public.devicePrivate; + DMCPrivatePtr priv = (DMCPrivatePtr) (pInfo->private); + unsigned char map[] = + {0, 1}; + + switch (mode) + { + case DEVICE_INIT: + /* + * these have to be here instead of in the SetupProc, because when the + * SetupProc is run at server startup, screenInfo is not setup yet + */ + priv->screen_width = screenInfo.screens[priv->screen_num]->width; + priv->screen_height = screenInfo.screens[priv->screen_num]->height; + + /* + * Device reports button press for 1 button. + */ + if (InitButtonClassDeviceStruct (dev, 1, map) == FALSE) + { + ErrorF ("Unable to allocate DMC ButtonClassDeviceStruct\n"); + return !Success; + } + + /* + * Device reports motions on 2 axes in absolute coordinates. + * Axes min and max values are reported in raw coordinates. + */ + if (InitValuatorClassDeviceStruct (dev, 2, xf86GetMotionEvents, + pInfo->history_size, Absolute) == FALSE) + { + ErrorF ("Unable to allocate DMC ValuatorClassDeviceStruct\n"); + return !Success; + } + else + { + InitValuatorAxisStruct (dev, 0, priv->min_x, priv->max_x, + 9500, + 0 /* min_res */ , + 9500 /* max_res */ ); + InitValuatorAxisStruct (dev, 1, priv->min_y, priv->max_y, + 10500, + 0 /* min_res */ , + 10500 /* max_res */ ); + } + + if (InitProximityClassDeviceStruct (dev) == FALSE) + { + ErrorF ("unable to allocate DMC ProximityClassDeviceStruct\n"); + return !Success; + } + + if (InitPtrFeedbackClassDeviceStruct(dev, DMCPtrCtrl) == FALSE) + { + ErrorF ("unable to allocate DMC PtrFeedbackClassDeviceStruct\n"); + return !Success; + } + + /* + * Allocate the motion events buffer. + */ + xf86MotionHistoryAllocate (pInfo); + return (Success); + + case DEVICE_ON: + pInfo->fd = xf86OpenSerial(pInfo->options); + if (pInfo->fd == -1) + { + xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name); + return (!Success); + } + else + { + priv->buffer = XisbNew(pInfo->fd, 64); + if (!priv->buffer) + { + xf86CloseSerial(pInfo->fd); + pInfo->fd = -1; + return (!Success); + } + else + { + unsigned char buf[2] = { 0x05, 0x40 }; + + sleep(1); /* touch need ca. 500ms delay !!! */ + XisbBlockDuration (priv->buffer, 500000); + if ( DMCSendPacket(priv, buf, 2) == Success ) + { + /* wait for right response */ + priv->lex_mode = DMC_Response0; + if (DMCGetPacket (priv) == Success ) + { + if ( priv->packet[0] == 0x06 ) + { + buf[0] = 0x31; + DMCSendPacket(priv,buf,1); + priv->lex_mode = DMC_Response0; + xf86Msg(X_ERROR, "DMC-Touch found\n"); + } + else + { + xf86Msg(X_ERROR, "DMC-Touch found\n"); + return (!Success); + } + } + else + { + xf86Msg(X_ERROR, "DMC-Touch found\n"); + return (!Success); + } + } + else + { + xf86Msg(X_ERROR, "DMC-Touch found\n"); + return (!Success); + } + } + } + + XisbBlockDuration (priv->buffer, -1); + priv->lex_mode = DMC_byte0; + + xf86FlushInput(pInfo->fd); + AddEnabledDevice (pInfo->fd); + dev->public.on = TRUE; + return (Success); + + case DEVICE_OFF: + case DEVICE_CLOSE: + if (pInfo->fd != -1) + { + RemoveEnabledDevice (pInfo->fd); + if (priv->buffer) + { + XisbFree(priv->buffer); + priv->buffer = NULL; + } + xf86CloseSerial(pInfo->fd); + } + dev->public.on = FALSE; + return (Success); + default: + return (BadValue); + } + +} + + +/* + * The ReadInput function will have to be tailored to your device + */ +static void +ReadInput (InputInfoPtr pInfo) +{ + DMCPrivatePtr priv = (DMCPrivatePtr) (pInfo->private); + int x,y; + unsigned char opck[ DMC_PACKET_SIZE ]; + + /* + * set blocking to -1 on the first call because we know there is data to + * read. Xisb automatically clears it after one successful read so that + * succeeding reads are preceeded buy a select with a 0 timeout to prevent + * read from blocking indefinately. + */ + XisbBlockDuration (priv->buffer, -1); + while (1) + { + memcpy(opck,priv->packet,5); + + if ( DMCGetPacket (priv) != Success) + break; + if ( priv->packet[0] == 0x11 ) + priv->pen_down=1; + else + priv->pen_down=0; + + if ( priv->swap_xy) + { + y = priv->packet[1]*256+priv->packet[2]; + x = priv->packet[3]*256+priv->packet[4]; + } + else + { + x = priv->packet[1]*256+priv->packet[2]; + y = priv->packet[3]*256+priv->packet[4]; + } + priv->packet[0] = priv->pen_down ? 0x01 : 0x00; + + if (priv->reporting_mode == TS_Scaled) + { + x = xf86ScaleAxis (x, 0, priv->screen_width, priv->min_x, + priv->max_x); + y = xf86ScaleAxis (y, 0, priv->screen_height, priv->min_y, + priv->max_y); + } + + xf86XInputSetScreen (pInfo, priv->screen_num, x, y); + + if ((priv->proximity == FALSE) && (priv->packet[0] & 0x01)) + { + priv->proximity = TRUE; + xf86PostProximityEvent (pInfo->dev, 1, 0, 2, x, y); + } + + /* + * Send events. + * + * We *must* generate a motion before a button change if pointer + * location has changed as DIX assumes this. This is why we always + * emit a motion, regardless of the kind of packet processed. + */ + + xf86PostMotionEvent (pInfo->dev, TRUE, 0, 2, x, y); + + /* + * Emit a button press or release. + */ + if ((priv->button_down == FALSE) && (priv->packet[0] & 0x01)) + + { + xf86PostButtonEvent (pInfo->dev, TRUE, + priv->button_number, 1, 0, 2, x, y); + priv->button_down = TRUE; + } + if ((priv->button_down == TRUE) && !(priv->packet[0] & 0x01)) + { + xf86PostButtonEvent (pInfo->dev, TRUE, + priv->button_number, 0, 0, 2, x, y); + priv->button_down = FALSE; + } + /* + * the untouch should always come after the button release + */ + if ((priv->proximity == TRUE) && !(priv->packet[0] & 0x01)) + { + priv->proximity = FALSE; + xf86PostProximityEvent (pInfo->dev, 0, 0, 2, x, y); + } + } +} + +/* + * The ControlProc function may need to be tailored for your device + */ +static int +ControlProc (InputInfoPtr pInfo, xDeviceCtl * control) +{ + xDeviceTSCalibrationCtl *c = (xDeviceTSCalibrationCtl *) control; + DMCPrivatePtr priv = (DMCPrivatePtr) (pInfo->private); + + priv->min_x = c->min_x; + priv->max_x = c->max_x; + priv->min_y = c->min_y; + priv->max_y = c->max_y; + + return (Success); +} + +/* + * the CloseProc should not need to be tailored to your device + */ +static void +CloseProc (InputInfoPtr pInfo) +{ + +} + +/* + * The SwitchMode function may need to be tailored for your device + */ +static int +SwitchMode (ClientPtr client, DeviceIntPtr dev, int mode) +{ + InputInfoPtr pInfo = dev->public.devicePrivate; + DMCPrivatePtr priv = (DMCPrivatePtr) (pInfo->private); + + + if ((mode == TS_Raw) || (mode == TS_Scaled)) + { + priv->reporting_mode = mode; + return (Success); + } + else if ((mode == SendCoreEvents) || (mode == DontSendCoreEvents)) + { + xf86XInputSetSendCoreEvents (pInfo, (mode == SendCoreEvents)); + return (Success); + } + else + return (!Success); +} + +/* + * The ConvertProc function may need to be tailored for your device. + * This function converts the device's valuator outputs to x and y coordinates + * to simulate mouse events. + */ +static Bool +ConvertProc (InputInfoPtr pInfo, + int first, + int num, + int v0, + int v1, + int v2, + int v3, + int v4, + int v5, + int *x, + int *y) +{ + DMCPrivatePtr priv = (DMCPrivatePtr) (pInfo->private); + + if (priv->reporting_mode == TS_Raw) + { + *x = xf86ScaleAxis (v0, 0, priv->screen_width, priv->min_x, + priv->max_x); + *y = xf86ScaleAxis (v1, 0, priv->screen_height, priv->min_y, + priv->max_y); + } + else + { + *x = v0; + *y = v1; + } + return (TRUE); +} + +/* + * the QueryHardware fuction should be tailored to your device to + * verify the device is attached and functional and perform any + * needed initialization. + */ +static Bool +QueryHardware (DMCPrivatePtr priv) +{ + /* Maybe once we get the hardware to actually respond correctly to its + configuration 'packets' */ + + return (Success); +} + +/* + * This function should be renamed for your device and tailored to handle + * your device's protocol. + */ +static Bool +DMCGetPacket (DMCPrivatePtr priv) +{ + int count = 0; + int c; + + while ((c = XisbRead (priv->buffer)) >= 0) + { + /* + * fail after 500 bytes so the server doesn't hang forever if a + * device sends bad data. + */ + if (count++ > 500) + return (!Success); + + switch (priv->lex_mode) + { + case DMC_byte0: + if ((( c & 0x3f ) != 0x11 ) && + (( c & 0x3f ) != 0x10 )) + return (!Success); + + priv->packet[0] = (unsigned char) c & 0x3f; + priv->lex_mode = DMC_byte1; + break; + + case DMC_byte1: + priv->packet[1] = (unsigned char) c; + priv->lex_mode = DMC_byte2; + break; + + case DMC_byte2: + priv->packet[2] = (unsigned char) c; + priv->lex_mode = DMC_byte3; + break; + + case DMC_byte3: + priv->packet[3] = (unsigned char) c; + priv->lex_mode = DMC_byte4; + break; + + case DMC_byte4: + priv->packet[4] = (unsigned char) c; + priv->lex_mode = DMC_byte0; + return (Success); + break; + + case DMC_Response0: + priv->packet[0] = (unsigned char) c; + return (Success); + break; + + } + } + return (!Success); +} + +static Bool +DMCSendPacket (DMCPrivatePtr priv, unsigned char *buf, int len) +{ + int count = 0; + + while ( len > 0 ) + { + if ( XisbWrite(priv->buffer, buf, 1) == 1 ) + { + buf++; + len--; + continue; + } + if ( count++ > 500 ) + break; + } + return (len ? !Success : Success); +} + +static void +DMCPtrCtrl(DeviceIntPtr device, PtrCtrl *ctrl) +{ + /* I have no clue what this does, except that registering it stops the + X server segfaulting in ProcGetPointerMapping() + Ho Hum. + */ +} diff --git a/xc/programs/Xserver/hw/xfree86/input/dmc/xf86DMC.h b/xc/programs/Xserver/hw/xfree86/input/dmc/xf86DMC.h new file mode 100644 index 000000000..588e970ad --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/input/dmc/xf86DMC.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1999 Machine Vision Holdings Incorporated + * Author: Mayk Langer <langer@vsys.de> + * + * Template driver used: Copyright (c) 1998 Metro Link Incorporated + * + * 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 X CONSORTIUM 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 Metro Link shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Metro Link. + * + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/input/dmc/xf86DMC.h,v 1.1 2001/08/17 13:27:55 dawes Exp $ */ + +#ifndef _DMC_H_ +#define _DMC_H_ + +/****************************************************************************** + * Definitions + * structs, typedefs, #defines, enums + *****************************************************************************/ + +#define DMC_PACKET_SIZE 5 + +typedef enum +{ + DMC_byte0, DMC_byte1, DMC_byte2, DMC_byte3, DMC_byte4, + DMC_Response0 +} +DMCState; + + +typedef struct _DMCPrivateRec +{ + int min_x; /* Minimum x reported by calibration */ + int max_x; /* Maximum x */ + int min_y; /* Minimum y reported by calibration */ + int max_y; /* Maximum y */ + Bool button_down; /* is the "button" currently down */ + int button_number; /* which button to report */ + int reporting_mode; /* TS_Raw or TS_Scaled */ + + int screen_num; /* Screen associated with the device */ + int screen_width; /* Width of the associated X screen */ + int screen_height; /* Height of the screen */ + int proximity; + int swap_xy; + XISBuffer *buffer; + unsigned char packet[DMC_PACKET_SIZE]; /* packet being/just read */ + DMCState lex_mode; + char pen_down; +} +DMCPrivateRec, *DMCPrivatePtr; + +/****************************************************************************** + * Declarations + *****************************************************************************/ + +static Bool DeviceControl (DeviceIntPtr, int); +static void ReadInput (InputInfoPtr); +static int ControlProc (InputInfoPtr, xDeviceCtl *); +static void CloseProc (InputInfoPtr); +static int SwitchMode (ClientPtr, DeviceIntPtr, int); +static Bool ConvertProc (InputInfoPtr, int, int, int, int, int, int, int, int, int *, int *); +static Bool QueryHardware (DMCPrivatePtr); +static Bool DMCGetPacket (DMCPrivatePtr priv); +static Bool DMCSendPacket (DMCPrivatePtr priv, unsigned char *buf, int len ); + +static InputInfoPtr +DMCPreInit(InputDriverPtr drv, IDevPtr dev, int flags); + +static void +DMCPtrCtrl(DeviceIntPtr device, PtrCtrl *ctrl); + + +#endif /* _DMC_H_ */ diff --git a/xc/programs/Xserver/hw/xfree86/input/magictouch/Imakefile b/xc/programs/Xserver/hw/xfree86/input/magictouch/Imakefile new file mode 100644 index 000000000..81d048c23 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/input/magictouch/Imakefile @@ -0,0 +1,30 @@ +XCOMM $XFree86: xc/programs/Xserver/hw/xfree86/input/magictouch/Imakefile,v 1.1 2001/07/03 15:13:57 paulo Exp $ + +#define IHaveModules +#include <Server.tmpl> + +SRCS = xf86MagicTouch.c +OBJS = xf86MagicTouch.o + +DRIVER = magictouch + +INCLUDES = -I. -I$(XF86COMSRC) -I$(XF86SRC)/loader -I$(XF86OSSRC) \ + -I$(SERVERSRC)/include -I$(SERVERSRC)/mi -I$(XINCLUDESRC) -I$(EXTINCSRC) + +#if MakeHasPosixVariableSubstitutions +SubdirLibraryRule($(OBJS)) +#endif + +ModuleObjectRule() + +ObjectModuleTarget($(DRIVER),$(OBJS)) + +InstallObjectModule($(DRIVER),$(MODULEDIR),input) + +#if !defined(XF86DriverSDK) +InstallModuleManPage($(DRIVER)) +#endif + +DependTarget() + +InstallDriverSDKObjectModule($(DRIVER),$(DRIVERSDKMODULEDIR),input) diff --git a/xc/programs/Xserver/hw/xfree86/input/magictouch/magictouch.man b/xc/programs/Xserver/hw/xfree86/input/magictouch/magictouch.man new file mode 100644 index 000000000..29a78a47f --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/input/magictouch/magictouch.man @@ -0,0 +1,25 @@ +.\" $XFree86: xc/programs/Xserver/hw/xfree86/input/magictouch/magictouch.man,v 1.1 2001/07/03 15:13:57 paulo Exp $ +.\" shorthand for double quote that works everywhere. +.ds q \N'34' +.TH VOID __drivermansuffix__ __vendorversion__ +.SH NAME +void \- null input driver +.SH SYNOPSIS +.nf +.B "Section \*qInputDevice\*q" +.BI " Identifier \*q" idevname \*q +.B " Driver \*qmagictouch\*q" +\ \ ... +.B EndSection +.fi +.SH DESCRIPTION +.B magictouch +is an XFree86 input driver. +.SH CONFIGURATION DETAILS +Please refer to XF86Config(__filemansuffix__) for general configuration +details and for options that can be used with all input drivers. This +driver doesn't have any configuration options in addition to those. +.SH "SEE ALSO" +XFree86(1), XF86Config(__filemansuffix__), xf86cfg(1), xf86config(1), Xserver(1), X(__miscmansuffix__). +.SH AUTHORS +Authors include... diff --git a/xc/programs/Xserver/hw/xfree86/input/magictouch/xf86MagicTouch.c b/xc/programs/Xserver/hw/xfree86/input/magictouch/xf86MagicTouch.c new file mode 100644 index 000000000..4154512c3 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/input/magictouch/xf86MagicTouch.c @@ -0,0 +1,1107 @@ +/* + * $XFree86: xc/programs/Xserver/hw/xfree86/input/magictouch/xf86MagicTouch.c,v 1.2 2001/07/04 13:38:09 tsi Exp $ + */ + +#include <xf86Version.h> +#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(3,9,0,0,0) +#define XFREE86_V4 +#endif + +#ifdef XFREE86_V4 + +#ifndef XFree86LOADER +#include <errno.h> +#include <string.h> +#include <unistd.h> +#endif + +#include <misc.h> +#include <xf86.h> +#if !defined(DGUX) +#include <xf86_ansic.h> +#endif +#include <xf86_OSproc.h> +#include <xf86Xinput.h> +#include <exevents.h> + +#ifdef XFree86LOADER +#include <xf86Module.h> +#endif + +#else /* XFREE86_V4 */ + +#include "Xos.h" +#include <signal.h> +#include <stdio.h> +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "inputstr.h" +#include "scrnintstr.h" + +#include "XI.h" +#include "XIproto.h" + +#if defined(sun) && !defined(i386) +#include <errno.h> +#include <termio.h> +#include <fcntl.h> +#include <ctype.h> + +#include "extio.h" +#else /* defined(sun) && !defined(i386) */ +#include "compiler.h" + +#include "xf86.h" +#include "xf86Procs.h" +#include "xf86_OSlib.h" +#include "xf86_Config.h" +#include "xf86Xinput.h" +#include "xf86Version.h" +#endif /* defined(sun) && !defined(i386) */ + +#if !defined(sun) || defined(i386) +#include "os.h" +#include "osdep.h" +#include "exevents.h" + +#include "extnsionst.h" +#include "extinit.h" +#endif /* !defined(sun) || defined(i386) */ + +#endif /* XFREE86_V4 */ + + +#ifndef XFREE86_V4 +#if !defined(sun) || defined(i386) +/* + *************************************************************************** + * + * Configuration descriptor. + * + *************************************************************************** + */ + +#define PORT 1 +#define MAGIC_DEVICE_NAME 2 +#define SCREEN_NO 3 +#define MAXX 4 +#define MAXY 5 +#define MINX 6 +#define MINY 7 +#define DEBUG_LEVEL 8 +#define HISTORY_SIZE 9 +#define LINK_SPEED 10 +#define ALWAYS_CORE 11 +#define SWAP_AXES 12 +#define N_SAMPLE_X 13 +#define N_SAMPLE_Y 14 + +static SymTabRec MagicTab[] = { + { ENDSUBSECTION, "endsubsection" }, + { PORT, "port" }, + { MAGIC_DEVICE_NAME, "devicename" }, + { SCREEN_NO, "screenno" }, + { MAXX, "maximumxposition" }, + { MAXY, "maximumyposition" }, + { MINX, "minimumxposition" }, + { MINY, "minimumyposition" }, + { DEBUG_LEVEL, "debuglevel" }, + { HISTORY_SIZE, "historysize" }, + { LINK_SPEED, "linkspeed" }, + { ALWAYS_CORE, "alwayscore" }, + { SWAP_AXES, "swapxy" }, + { N_SAMPLE_X, "numsamplex" }, + { N_SAMPLE_Y, "numsampley" }, + { -1, "" }, +}; + + +#define LS1200 1 +#define LS2400 2 +#define LS4800 3 +#define LS9600 4 + +static SymTabRec LinkSpeedTab[] = { + { LS1200, "b1200" }, + { LS2400, "b2400" }, + { LS4800, "b4800" }, + { LS9600, "b9600" } +}; +#endif /* !defined(sun) || defined(i386) */ + +/* + * This struct connects a line speed with + * a compatible motion packet delay. The + * driver will attempt to enforce a correct + * delay (according to this table) in order to + * avoid losing data in the touchscreen controller. + * LinkSpeedValues should be kept in sync with + * LinkSpeedTab. + */ +typedef struct { + int speed; + int delay; +} LinkParameterStruct; + +static LinkParameterStruct LinkSpeedValues[] = { + { B1200, 8 }, + { B2400, 4 }, + { B4800, 2 }, + { B9600, 1 } +}; +#endif /* XFREE86_V4 */ + + +/* + *************************************************************************** + * + * Default constants. + * + *************************************************************************** + */ +#define MAGIC_PACKET_SIZE 5 +#define MAGIC_PORT "/dev/magictouch" +#define MAGIC_LINK_SPEED B9600 + +/* First byte of the packet */ +#define MGCT_TOUCH 0x01 +#define MGCT_RKEY 0x02 +#define MGCT_LKEY 0x04 +#define MGCT_MKEY 0x08 +#define MGCT_CLICK_STATUS 0x10 + +#define MEDIE_X 20 +#define MEDIE_Y 20 + + +/* + *************************************************************************** + * + * Usefull macros. + * + *************************************************************************** + */ +#define WORD_ASSEMBLY(byte1, byte2) (((byte2) << 8) | (byte1)) +#define SYSCALL(call) while(((call) == -1) && (errno == EINTR)) + +/* This one is handy, thanx Fred ! */ +#ifdef DBG +#undef DBG +#endif +#ifdef DEBUG +#undef DEBUG +#endif + +static int debug_level = 0; +#define DEBUG 1 +#if DEBUG +#define DBG(lvl, f) {if ((lvl) == debug_level) { f; } } +#else +#define DBG(lvl, f) +#endif + + +#ifdef XFREE86_V4 +#undef SYSCALL +#undef read +#undef write +#undef close +#undef strdup +#define SYSCALL(call) call +#define read(fd, ptr, num) xf86ReadSerial(fd, ptr, num) +#define write(fd, ptr, num) xf86WriteSerial(fd, ptr, num) +#define close(fd) xf86CloseSerial(fd) +#define strdup(str) xf86strdup(str) +#endif + + + + + + +/* + *************************************************************************** + * + * Device private records. + * + *************************************************************************** + */ +typedef struct _MagicPrivateRec { + char *input_dev; /* The touchscreen input tty */ + int min_x; /* Minimum x reported by calibration */ + int max_x; /* Maximum x */ + int min_y; /* Minimum y reported by calibration */ + int max_y; /* Maximum y */ +#ifndef XFREE86_V4 + int link_speed; /* Speed of the RS232 link connecting the ts. */ +#endif + int screen_no; /* Screen associated with the device */ + int screen_width; /* Width of the associated X screen */ + int screen_height; /* Height of the screen */ + int swap_axes; /* Swap X an Y axes if != 0 */ + unsigned char packet_buf[MAGIC_PACKET_SIZE]; /* Assembly buffer */ + int packet_pos; + int buf_x[MEDIE_X], i_x, num_medie_x; + int buf_y[MEDIE_Y], i_y, num_medie_y; + Bool first_x, first_y; + Bool first_entry; + Bool e_presente; + Bool click_on; +} MagicPrivateRec, *MagicPrivatePtr; + + +#ifndef XFREE86_V4 +#if !defined(sun) || defined(i386) +/* + **************************************************************************** + * xf86MagicConfig -- + * Configure the device driver from configuration data + **************************************************************************** + */ +static Bool +xf86MagicConfig(LocalDevicePtr *array, + int inx, + int max, + LexPtr val) +{ + LocalDevicePtr local = array[inx]; + MagicPrivatePtr priv = (MagicPrivatePtr)(local->private); + int token; + + while ((token = xf86GetToken(MagicTab)) != ENDSUBSECTION) { + switch(token) { + + case PORT: + if (xf86GetToken(NULL) != STRING) { + xf86ConfigError("MagicTouch input port expected"); + } + priv->input_dev = strdup(val->str); + if (xf86Verbose) { + ErrorF("%s MagicTouch input port: %s\n", + XCONFIG_GIVEN, priv->input_dev); + } + break; + + case MAGIC_DEVICE_NAME: + if (xf86GetToken(NULL) != STRING) { + xf86ConfigError("Magictouch device name expected"); + } + local->name = strdup(val->str); + if (xf86Verbose) { + ErrorF("%s MagicTouch X device name: %s\n", + XCONFIG_GIVEN, local->name); + } + break; + + case SCREEN_NO: + if (xf86GetToken(NULL) != NUMBER) { + xf86ConfigError("MagicTouch screen number expected"); + } + priv->screen_no = val->num; + if (xf86Verbose) { + ErrorF("%s MagicTouch associated screen: %d\n", + XCONFIG_GIVEN, priv->screen_no); + } + break; + + case LINK_SPEED: + { + int ltoken = xf86GetToken(LinkSpeedTab); + if (ltoken == EOF || + ltoken == STRING || + ltoken == NUMBER) { + xf86ConfigError("MagicTouch link speed expected"); + } + priv->link_speed = LinkSpeedValues[ltoken-1].speed; + if (xf86Verbose) { + ErrorF("%s MagicTouch link speed: %s bps\n", + XCONFIG_GIVEN, (LinkSpeedTab[ltoken-1].name)+1); + } + } + break; + + case MAXX: + if (xf86GetToken(NULL) != NUMBER) { + xf86ConfigError("MagicTouch maximum x position expected"); + } + priv->max_x = val->num; + if (xf86Verbose) { + ErrorF("%s MagicTouch maximum x position: %d\n", + XCONFIG_GIVEN, priv->max_x); + } + break; + + case MAXY: + if (xf86GetToken(NULL) != NUMBER) { + xf86ConfigError("MagicTouch maximum y position expected"); + } + priv->max_y = val->num; + if (xf86Verbose) { + ErrorF("%s MagicTouch maximum y position: %d\n", + XCONFIG_GIVEN, priv->max_y); + } + break; + + case MINX: + if (xf86GetToken(NULL) != NUMBER) { + xf86ConfigError("MagicTouch minimum x position expected"); + } + priv->min_x = val->num; + if (xf86Verbose) { + ErrorF("%s MagicTouch minimum x position: %d\n", + XCONFIG_GIVEN, priv->min_x); + } + break; + + case MINY: + if (xf86GetToken(NULL) != NUMBER) { + xf86ConfigError("MagicTouch minimum y position expected"); + } + priv->min_y = val->num; + if (xf86Verbose) { + ErrorF("%s MagicTouch minimum y position: %d\n", + XCONFIG_GIVEN, priv->min_y); + } + break; + + case DEBUG_LEVEL: + if (xf86GetToken(NULL) != NUMBER) { + xf86ConfigError("MagicTouch driver debug level expected"); + } + debug_level = val->num; + if (xf86Verbose) { +#if DEBUG + ErrorF("%s MagicTouch debug level sets to %d\n", XCONFIG_GIVEN, + debug_level); +#else + ErrorF("%s MagicTouch debug not available\n", + XCONFIG_GIVEN, debug_level); +#endif + } + break; + + case HISTORY_SIZE: + if (xf86GetToken(NULL) != NUMBER) { + xf86ConfigError("MagicTouch motion history size expected"); + } + local->history_size = val->num; + if (xf86Verbose) { + ErrorF("%s MagicTouch motion history size is %d\n", XCONFIG_GIVEN, + local->history_size); + } + break; + + case ALWAYS_CORE: + xf86AlwaysCore(local, TRUE); + if (xf86Verbose) { + ErrorF("%s MagicTouch device will always stays core pointer\n", + XCONFIG_GIVEN); + } + break; + + case SWAP_AXES: + priv->swap_axes = 1; + if (xf86Verbose) { + ErrorF("%s MagicTouch device will work with X and Y axes swapped\n", + XCONFIG_GIVEN); + } + break; + + case N_SAMPLE_X: + if (xf86GetToken(NULL) != NUMBER) { + xf86ConfigError("MagicTouch driver NumSamplesX expected"); + } + priv->num_medie_x = val->num; + + + if (priv->num_medie_x>MEDIE_X) + priv->num_medie_x=MEDIE_X; + + DBG(4, + ErrorF("NumSampleX = %d\n", priv->num_medie_x) + ); + + break; + + case N_SAMPLE_Y: + if (xf86GetToken(NULL) != NUMBER) { + xf86ConfigError("MagicTouch driver NumSamplesY expected"); + } + priv->num_medie_y = val->num; + + if (priv->num_medie_y>MEDIE_Y) + priv->num_medie_y=MEDIE_Y; + + DBG(4, + ErrorF("NumSampleY = %d\n", priv->num_medie_y) + ); + break; + + case EOF: + FatalError("Unexpected EOF (missing EndSubSection)"); + break; + + default: + xf86ConfigError("MagicTouch subsection keyword expected"); + break; + } + } + + if (priv->max_x - priv->min_x <= 0) { + ErrorF("%s MagicTouch: reverse x mode (minimum x position >= maximum x position)\n", + XCONFIG_GIVEN); + } + if (priv->max_y - priv->min_y <= 0) { + ErrorF("%s MagicTouch: reverse y mode (minimum y position >= maximum y position)\n", + XCONFIG_GIVEN); + } + + DBG(2, ErrorF("xf86MagicConfig port name=%s\n", priv->input_dev)) + + return Success; +} + +#endif /* !defined(sun) || defined(i386) */ +#endif /* XFREE86_V4 */ + +/**************************************************************************** + * + * xf86MagicQueryOK -- + * Testa la presenza del touch controller. + * Si osserva che al primo accesso al touch dopo l'accensione e' + * presente nel buffer di ricezione il codice 0xF che identifica la + * vera presenza del touch controller. + * Dal secondo accesso in poi bisogna interrogare il touch controller + * per verificarne l'esistenza. + **************************************************************************** + */ +static Bool +xf86MagicQueryOK(int fd) +{ + Bool ok; + int result; + char buf; + + ok = Success; + + /* Provo a leggere un byte dal buffer di ricezione */ + SYSCALL( result = read(fd, &buf, 1) ); + + DBG(4, ErrorF("<<%s[%d]>> QueryOK: read --> %d\n", __FILE__, __LINE__, result) ); + + /* Se result e' -1 vuol dire che non c'e' nessun carattere nel + buffer. Allora X/Window e' stato avviato almeno una volta */ + if (result<0) { + DBG(4, + ErrorF("Avvio n-esimo di X/Windows\n"); + ErrorF("Controllo presenza Touch Controller\n") + ); + + /* Cerco il touch controller. Invio il carattere 0x00. */ + buf = 0; + SYSCALL( result = write(fd, &buf, 1) ); + + /* Attendo 20 ms per dare il tempo al touch controller di + capire il comando */ + usleep(20000); + + /* Leggo la risposta */ + SYSCALL( result = read(fd, &buf, 1) ); + + DBG(4, + ErrorF("QueryOK: buf==%X, result==%d\n", buf, result) + ); + } + + /* Se result<0 allora il touch controller non e' presente sul + disposito. Non posso proseguire */ + if (result<0) { + DBG(4, + ErrorF("<<%s[%d]>> result<0\n", __FILE__, __LINE__) + ); + ok = !Success; + } + /* Se il touch controller ha risposto allora controllo cosa ha + risposto */ + else { + ok = (buf==0xF ? Success : !Success); + DBG(4, + ErrorF("<<%s[%d]>> QueryOK buf==%x\n", __FILE__, __LINE__, buf) + ); + } + + return ok; +} + +/* + *********************************************************************** + * + * xf86MagicControl + * + *********************************************************************** + */ +static Bool +xf86MagicControl(DeviceIntPtr dev, + int mode) +{ + LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate; + MagicPrivatePtr priv = (MagicPrivatePtr)(local->private); + unsigned char map[] = { 0, 1 }; + unsigned char req[MAGIC_PACKET_SIZE], replay[MAGIC_PACKET_SIZE]; + int status_line; + + switch (mode) { + case DEVICE_INIT: + DBG(2, ErrorF("MagicTouch init...\n") ); + + /* Controlla il numero di schermo selezionato */ + if (priv->screen_no >= screenInfo.numScreens || priv->screen_no<0) + priv->screen_no = 0; + /* Legge le dimensioni dello schermo */ + priv->screen_width = screenInfo.screens[priv->screen_no]->width; + priv->screen_height = screenInfo.screens[priv->screen_no]->height; + + if (InitButtonClassDeviceStruct(dev, 1, map)==FALSE) { + ErrorF("Impossibile allocare ButtonClassDeviceStruct per MagicTouch\n"); + return !Success; + } + + if (InitFocusClassDeviceStruct(dev)==FALSE) { + ErrorF("Impossibile allocare FocusClassDeviceStruct per MagicTouch\n"); + return !Success; + } + + /* + * Il movimento viene eseguito su due assi in coordinate assolute. + */ + if (InitValuatorClassDeviceStruct(dev, 2, xf86GetMotionEvents, local->history_size, Absolute) == FALSE ) + { + ErrorF("MagicTouch ValuatorClassDeviceStruct: ERRORE\n"); + return !Success; + } + else { + InitValuatorAxisStruct(dev, 0, priv->min_x, priv->max_x, + 9500, + 0, /* min res */ + 9500 /* max res */); + + InitValuatorAxisStruct(dev, 1, priv->min_y, priv->max_y, + 10500, + 0, + 10500); + } + + if (InitFocusClassDeviceStruct(dev)==FALSE) { + ErrorF("Impossibile allocare FocusClassDeviceStruct per MagicTouch\n"); + } + + /* + * Alloca il buffer degli eventi spostamento + */ + xf86MotionHistoryAllocate(local); + + #ifndef XFREE86_V4 + AssignTypeAndName(dev, local->atom, local->name); + #endif /* XFREE86_V4 */ + + DBG(2, ErrorF("MagicTouch INIT OK\n") ); + + break; /* DEVICE_INIT*/ + + case DEVICE_ON: + DBG(2, ErrorF("MagicTouch ON\n") ); + if (local->fd<0) { + #ifndef XFREE86_V4 + struct termios termios_tty; + int i,result; + #endif + + DBG(2, ErrorF("Opening device...\n") ); + + #ifdef XFREE86_V4 + local->fd = xf86OpenSerial(local->options); + if (local->fd<0) { + ErrorF("Impossibile aprire MagicTouch\n"); + return !Success; + } + #else + SYSCALL( local->fd = open(priv->input_dev, O_RDWR | O_NDELAY, 0) ); + if (local->fd<0) { + Error("Impossibile aprire MagicTouch\n"); + return !Success; + } + + DBG(3, ErrorF("Provo a configurare il MagicTouch\n") ); + + + memset(&termios_tty, 0, sizeof(termios_tty) ); + termios_tty.c_iflag = 0; + termios_tty.c_cflag = priv->link_speed | CS8 | CREAD | CLOCAL; + termios_tty.c_oflag = 0; + termios_tty.c_lflag = 0; + termios_tty.c_cc[VTIME]=0; + termios_tty.c_cc[VMIN]=1; + + /* + * Attivo l'RTS per abilitare il touch controller + */ + #if 0 + SYSCALL( result = ioctl(local->fd, TIOCMGET, &status_line) ); + if (result<0) + { + Error("Impossibile leggere stato linee seriale\n"); + close(local->fd); + return !Success; + } + status_line |= TIOCM_RTS; + SYSCALL( result = ioctl(local->fd, TIOCMSET, &status_line) ); + if (result<0) + { + Error("Impossibile settare stato linee seriale\n"); + close(local->fd); + return !Success; + } + #endif + + SYSCALL( result = tcsetattr(local->fd, TCSANOW, &termios_tty) ); + if (result<0) + { + Error("Impossibile configurare MagicTouch\n"); + close(local->fd); + return !Success; + } + #endif + + + /* Controlla se e' presente il touch controller.*/ + req[0] = 0x00; + if (xf86MagicQueryOK(local->fd)!=Success) { + ErrorF("MagicTouch not present\n"); + close(local->fd); + return !Success; + } + + priv->e_presente = TRUE; + + AddEnabledDevice(local->fd); + dev->public.on = TRUE; + } /* if (local->fd<0) */ + break; /* DEVICE_ON */ + + case DEVICE_CLOSE: + case DEVICE_OFF: + DBG(2, ErrorF("MagicTouch OFF\n") ); + dev->public.on = FALSE; + if (local->fd>=0) + emoveEnabledDevice(local->fd); + + SYSCALL( close(local->fd) ); + local->fd = -1; + DBG(2, ErrorF("OK\n") ); + break; /* DEVICE_OFF*/ + + default: + ErrorF("unsupported mode %d\n", mode); + return !Success; + } /* switch (mode) */ + + return Success; +} + + + +/* + *************************************************************************** + * + * GetPacket -- + * + *************************************************************************** + */ +static Bool +GetPacket(LocalDevicePtr local, unsigned char *buffer, int *n_rx, int fd) +{ + int num_bytes; + int i; + Bool ok; + MagicPrivatePtr priv=(MagicPrivatePtr) local->private; + + DBG(6, ErrorF("Entering GetPacket with packet_pos == %d\n", *n_rx) ); + + SYSCALL( + num_bytes=read(fd, buffer+*n_rx, MAGIC_PACKET_SIZE-*n_rx) + ); + + /* Se e' il primo ingresso nella procedura e ho letto un solo byte, + allora e' arrivato lo 0x0F di risposta all-inizializzazione del + touch controlloer */ + /* Sto gia' leggendo un pacchetto normale */ + *n_rx += num_bytes; + + DBG(8, + for (i=0; i<*n_rx; i++) + ErrorF("%3X", buffer[i]); + ErrorF("\n") + ); + + ok = (*n_rx==MAGIC_PACKET_SIZE ? Success : !Success ); + + if (ok==Success) + *n_rx = 0; + + DBG(6, + if(ok==Success) + ErrorF("GetPacket OK\n"); + else + ErrorF("GetPacket FAIL\n") + ); + + return ok; +} + +/* + ************************************************************************ + * + * xf86MagicReadInput + * + ************************************************************************ + */ +static +int medie_x(LocalDevicePtr local, int x) +{ + int i,res; + float medie; + MagicPrivatePtr priv = (MagicPrivatePtr)(local->private); + + DBG(6, + ErrorF("Medie in X = %d\n", priv->num_medie_x) + ); + + if (priv->first_x) { + priv->first_x = FALSE; + for (i=0; i<priv->num_medie_x; i++) + priv->buf_x[i] = x; + + res = x; + } + else { + priv->buf_x[priv->i_x] = x; + priv->i_x++; + if (priv->i_x>=priv->num_medie_x) + priv->i_x = 0; + + medie = 0.0; + for (i=0; i<priv->num_medie_x; i++) + medie += priv->buf_x[i]; + + res = (int)(medie/priv->num_medie_x); + } + + return res; +} + +static +int medie_y(LocalDevicePtr local, int y) +{ + int i,res; + float medie; + MagicPrivatePtr priv = (MagicPrivatePtr)(local->private); + + DBG(6, + ErrorF("Medie in Y = %d\n", priv->num_medie_y) + ); + + if (priv->first_y) { + priv->first_y = FALSE; + for (i=0; i<priv->num_medie_y; i++) + priv->buf_y[i] = y; + + res = y; + } + else { + priv->buf_y[priv->i_y] = y; + priv->i_y++; + if (priv->i_y>=priv->num_medie_y) + priv->i_y = 0; + + medie = 0.0; + for (i=0; i<priv->num_medie_y; i++) + medie += priv->buf_y[i]; + + res = (int)(medie/priv->num_medie_y); + } + + return res; +} + +/* +static +int MAX(int x, int y) +{ + return (x>=y ? x : y); +} +*/ + +#define MAX(x,y) (x>=y ? x : y) + +static void +xf86MagicReadInput(LocalDevicePtr local) +{ + MagicPrivatePtr priv = (MagicPrivatePtr)(local->private); + int cur_x, cur_y; + Bool touch_now; + static int n_coms = 0; + + if (!priv->e_presente) { + DBG(4, + ErrorF("<<%s[%d]>> ReadInput: Touch Controller non inizializzato\n") + ); + return; + } + + DBG(4, ErrorF("Entering ReadInput\n")); + /* + * Try to get a packet. + */ + if (GetPacket(local, priv->packet_buf, &priv->packet_pos, local->fd)==Success) + { + /* Calculate the (x,y) coord of pointer */ + cur_x = priv->packet_buf[1]; + cur_x <<= 6; + cur_x |= priv->packet_buf[2]; + + cur_y = priv->packet_buf[3]; + cur_y <<= 6; + cur_y |= priv->packet_buf[4]; + + touch_now = priv->packet_buf[0] & MGCT_TOUCH == MGCT_TOUCH; + + /* Se c'e' pressione sul touch inizio a calcolare la posizione + e a spostare il cursore grafico */ + if (touch_now) { + DBG(6, + ErrorF("Touch premuto: medio i valori di posizione\n") + ); + cur_x = medie_x(local, cur_x); + cur_y = medie_y(local, cur_y); + } + else { + DBG(6, + ErrorF("Touch rilasciato:\n" + "\tazzeramento buffer memoria\n" + "\tposizionamento immediato\n") + ); + + /* Se non ho pressione allora comando lo spostamento + del cursore senza mediare. Svuoto il buffer delle medie */ + priv->first_x = TRUE; + priv->first_y = TRUE; + } + /* Comando lo spostamento */ + xf86PostMotionEvent(local->dev, TRUE, 0, 2, cur_x, cur_y); + /* comanda la pressione del tasto */ + + DBG(9, + ErrorF("touch_now==%s\n", (touch_now==TRUE ? "TRUE" : "FALSE") ) + ); + if (touch_now!=priv->click_on) { + DBG(9, + ErrorF("Bottone == %s\n", (touch_now==TRUE ? "PREMUTO" : "RILASCAITO") ) + ); + priv->click_on = touch_now; + xf86PostButtonEvent(local->dev, TRUE, 1, touch_now, 0, 2, cur_x, cur_y); + } + } /* GetPacket */ +} + + +/* + ************************************************************************ + * + * xf86MagicConvert + * + ************************************************************************ + */ +static Bool +xf86MagicConvert(LocalDevicePtr local, + int first, + int num, + int v0, + int v1, + int v2, + int v3, + int v4, + int v5, + int *x, + int *y) +{ + MagicPrivatePtr priv = (MagicPrivatePtr) local->private; + int width = priv->max_x - priv->min_x; + int height = priv->max_y - priv->min_y; + int input_x, input_y; + + if (first != 0 || num != 2) { + return FALSE; + } + + DBG(3, ErrorF("MagicConvert: v0(%d), v1(%d)\n", v0, v1)); + + if (priv->swap_axes) { + input_x = v1; + input_y = v0; + } + else { + input_x = v0; + input_y = v1; + } + *x = (priv->screen_width * (input_x - priv->min_x)) / width; + *y = (priv->screen_height - (priv->screen_height * (input_y - priv->min_y)) / height); + +#ifdef XFREE86_V4 + /* + * Need to check if still on the correct screen. + * This call is here so that this work can be done after + * calib and before posting the event. + */ + xf86XInputSetScreen(local, priv->screen_no, *x, *y); +#endif + + DBG(3, ErrorF("MagicConvert: x(%d), y(%d)\n", *x, *y)); + + return TRUE; +} + + + +/* + ************************************************************************ + * + * xf86MagicAllocate + * + ************************************************************************ + */ +static LocalDevicePtr +#ifndef XFREE86_V4 +xf86MagicAllocate(void) +#else +xf86MagicAllocate(InputDriverPtr drv) +#endif +{ + #ifndef XFREE86_V4 + LocalDevicePtr local = (LocalDevicePtr) xalloc( sizeof(LocalDeviceRec) ); + #else + LocalDevicePtr local = xf86AllocateInput(drv, 0); + #endif + + MagicPrivatePtr priv = (MagicPrivatePtr) xalloc( sizeof(MagicPrivateRec) ); + + /* Controlla la corretta allocazione di buffers. Se uno dei buffers non + e' stato allocato correttamente termina l'inizializzazione + */ + if (!local) { + if (priv) + xfree(priv); + return NULL; + } + + if (!priv) { + if (local) + xfree(local); + return NULL; + } + + /* I buffers sono allocati correttamente */ + #ifdef XFREE86_V4 + priv->input_dev = strdup(MAGIC_PORT); + #else + priv->input_dev = MAGIC_PORT; + priv->link_speed = MAGIC_LINK_SPEED; + #endif + + priv->min_x = 60; + priv->max_x = 960; + priv->min_y = 60; + priv->max_y = 960; + priv->screen_no = 0; + priv->screen_width = -1; + priv->screen_height = -1; + priv->swap_axes = 0; + priv->first_x = + priv->first_y = TRUE; + priv->first_entry = TRUE; + priv->e_presente = FALSE; + priv->click_on = FALSE; + priv->i_x = + priv->i_y = 0; + priv->packet_pos = 0; + bzero(priv->buf_x, MEDIE_X); + bzero(priv->buf_y, MEDIE_Y); + priv->num_medie_x = MEDIE_X; + priv->num_medie_y = MEDIE_Y; + + local->name = XI_TOUCHSCREEN; + local->flags = 0; + + #ifndef XFREE86_V4 + #if !defined(sun) || defined(i386) + local->device_config = xf86MagicConfig; + #endif /* !defined(sun) || defined(i386) */ + #endif /* XFREE86_V4*/ + + local->device_control = xf86MagicControl; + local->read_input = xf86MagicReadInput; + local->control_proc = NULL; + local->close_proc = NULL; + local->switch_mode = NULL; + local->conversion_proc = xf86MagicConvert; + local->reverse_conversion_proc = NULL; + local->fd = -1; + local->atom = 0; + local->dev = NULL; + local->private = priv; + local->type_name = "MagicTouch"; + local->history_size = 0; + + return local; + +} /* xf86MagicAllocae */ + + + +#ifndef XFREE86_V4 + +/* + * Sezione relativa a X < 4.0.0 + */ + +DeviceAssocRec magictouch_assoc = { + "magictouch", + xf86MagicAllocate +}; + +#ifdef DYNAMIC_MODULE + +#ifndef DLSYM_BUG +int init_module(unsigned long server_version) +#else +int init_xf86Magic(unsigned long server_version) +#endif +{ + /* Aggiunge l'assiocazione per il touchscreen */ + xf86AddDeviceAssoc(&magictouch_assoc); + + /* Controlla la versione */ + if (server_version != XF86_VERSION_CURRENT) { + ErrorF("Warining: MagicTouch module compiled for version %s\n", XF86_VERSION); + return 0; + } + return 1; +} +#endif /* DYNAMIC_MODULE */ + +#else +/* + * Sezione relativa a X >= 4.0.0 + */ + +#endif /* XFREE86_V4 */ diff --git a/xc/programs/Xserver/hw/xfree86/os-support/sunos/Imakefile b/xc/programs/Xserver/hw/xfree86/os-support/sunos/Imakefile new file mode 100644 index 000000000..eb79cf471 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/sunos/Imakefile @@ -0,0 +1,85 @@ +XCOMM $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sunos/Imakefile,v 1.2 2001/08/17 22:08:15 tsi Exp $ +XCOMM +XCOMM Copyright 2001 The XFree86 Project, Inc. All Rights Reserved. +XCOMM +XCOMM Permission is hereby granted, free of charge, to any person obtaining a +XCOMM copy of this software and associated documentation files (the +XCOMM "Software"), to deal in the Software without restriction, including +XCOMM without limitation the rights to use, copy, modify, merge, publish, +XCOMM distribute, sublicense, and/or sell copies of the Software, and to permit +XCOMM persons to whom the Software is furnished to do so, subject to the +XCOMM following conditions: +XCOMM +XCOMM The above copyright notice and this permission notice shall be included +XCOMM in all copies or substantial portions of the Software. +XCOMM +XCOMM THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +XCOMM OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +XCOMM MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +XCOMM IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR +XCOMM OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +XCOMM ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +XCOMM OTHER DEALINGS IN THE SOFTWARE. +XCOMM +XCOMM Except as contained in this notice, the name of the XFree86 Project shall +XCOMM not be used in advertising or otherwise to promote the sale, use or other +XCOMM dealings in this Software without prior written authorization from the +XCOMM XFree86 Project. +XCOMM + +/* This is a combined Imakefile intended for all SunOS variants */ + +#include <Server.tmpl> + +#if !HasGcc && defined(i386Architecture) +PROWORKS_INOUT_SRC = sun_inout.s +PROWORKS_INOUT_OBJ = sun_inout.s +#endif + +#if defined(i386Architecture) && (OSMinorVersion < 8) +IO_SRC = sysv_io.c +IO_OBJ = sysv_io.o +KBD_SRCS = sysv_kbd.c std_kbdEv.c +KBD_OBJS = sysv_kbd.o std_kbdEv.o +VTSW_SRC = VTsw_usl.c +VTSW_OBJ = VTsw_usl.o +#else +IO_SRC = sun_io.c +IO_OBJ = sun_io.o +KBD_SRCS = sun_kbd.c sun_kbdEv.c +KBD_OBJS = sun_kbd.o sun_kbdEv.o +VTSW_SRC = VTsw_noop.c +VTSW_OBJ = VTsw_noop.o +#endif + +SRCS = sun_bios.c sun_init.c $(IO_SRC) $(KBD_SRCS) $(PROWORKS_INOUT_SRC) \ + sun_mouse.c sun_vid.c agp_noop.c libc_wrapper.c kmod_noop.c pm_noop.c \ + posix_tty.c sigiostubs.c stdPci.c stdResource.c $(VTSW_SRC) +OBJS = sun_bios.o sun_init.o $(IO_OBJ) $(KBD_OBJS) $(PROWORKS_INOUT_OBJ) \ + sun_mouse.o sun_vid.o agp_noop.o libc_wrapper.o kmod_noop.o pm_noop.o \ + posix_tty.o sigiostubs.o stdPci.o stdResource.o $(VTSW_OBJ) + +INCLUDES = -I. -I$(XF86OSSRC) -I$(XF86COMSRC) \ + -I$(SERVERSRC)/mi -I$(SERVERSRC)/include -I$(SERVERSRC)/Xext \ + -I$(XINCLUDESRC) -I$(EXTINCSRC) + +DEFINES = -DUSESTDRES + +SubdirLibraryRule($(OBJS)) +NormalLibraryObjectRule() +NormalAsmObjectRule() + +LinkSourceFile($(VTSW_SRC),../shared) +LinkSourceFile(agp_noop.c,../shared) +LinkSourceFile(libc_wrapper.c,../shared) +LinkSourceFile(kmod_noop.c,../shared) +LinkSourceFile(pm_noop.c,../shared) +LinkSourceFile(posix_tty.c,../shared) +LinkSourceFile(sigiostubs.c,../shared) +LinkSourceFile(stdPci.c,../shared) +LinkSourceFile(stdResource.c,../shared) +LinkSourceFile(std_kbdEv.c,../shared) +LinkSourceFile(sysv_io.c,../sysv) +LinkSourceFile(sysv_kbd.c,../shared) + +DependTarget() diff --git a/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_bios.c b/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_bios.c new file mode 100644 index 000000000..c42c7b9c7 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_bios.c @@ -0,0 +1,104 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_bios.c,v 1.1 2001/05/28 02:42:31 tsi Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany + * Copyright 1993 by David Wexelblat <dwex@goblin.org> + * Copyright 1999 by David Holland <davidh@iquest.net> + * + * 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 names 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. + */ + +#ifdef i386 +#define _NEED_SYSI86 +#endif +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +extern char *apertureDevName; + +/* + * Read BIOS via mmap()ing physical memory. + */ +int +xf86ReadBIOS(unsigned long Base, unsigned long Offset, unsigned char *Buf, + int Len) +{ +#ifdef i386 + int fd; + unsigned char *ptr; + char solx86_vtname[20]; + int psize; + int mlen; + + /* + * Solaris 2.1 x86 SVR4 (10/27/93) + * The server must treat the virtual terminal device file + * as the standard SVR4 /dev/pmem. By default, then used VT + * is considered the "default" file to open. + * + * Solaris 2.8 x86 (7/26/99) - DWH + * + * Use /dev/xsvc for everything. + */ + psize = xf86getpagesize(); + Offset += Base & (psize - 1); + Base &= ~(psize - 1); + mlen = (Offset + Len + psize - 1) & ~(psize - 1); +#ifndef __SOL8__ + if (Base >= 0xA0000 && Base + mlen < 0xFFFFF && xf86Info.vtno >= 0) + sprintf(solx86_vtname,"/dev/vt%02d",xf86Info.vtno); + else +#endif + { + if (!apertureDevName) + if (!xf86LinearVidMem()) + FatalError("xf86ReadBIOS: Could not mmap " + "BIOS [a=%x]\n", Base); + sprintf(solx86_vtname, apertureDevName); + } + + if ((fd = open(solx86_vtname, O_RDONLY)) < 0) + { + xf86Msg(X_WARNING, "xf86ReadBIOS: Failed to open %s (%s)\n", + solx86_vtname, strerror(errno)); + return(-1); + } + ptr = (unsigned char *)mmap((caddr_t)0, mlen, PROT_READ, + MAP_SHARED, fd, (off_t)Base); + if (ptr == MAP_FAILED) + { + xf86Msg(X_WARNING, "xf86ReadBIOS: %s mmap failed " + "[0x%05x, 0x%04x]\n", + solx86_vtname, Base, mlen); + close(fd); + return(-1); + } + (void)memcpy(Buf, (void *)(ptr + Offset), Len); + (void)munmap((caddr_t)ptr, mlen); + (void)close(fd); + return(Len); +#else + FatalError("xf86ReadBIOS() called\n"); + + return -1; /* G'd'ole gcc */ +#endif +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_init.c b/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_init.c new file mode 100644 index 000000000..63de850b7 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_init.c @@ -0,0 +1,330 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_init.c,v 1.2 2001/08/17 22:08:15 tsi Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany + * Copyright 1993 by David Wexelblat <dwex@goblin.org> + * Copyright 1999 by David Holland <davidh@iquest.net> + * + * 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 names 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, AND 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. + */ + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +static Bool KeepTty = FALSE; +static Bool Protect0 = FALSE; +#ifdef HAS_USL_VTS +static int VTnum = -1; +static int xf86StartVT = -1; +#endif + +static char fb_dev[PATH_MAX] = "/dev/console"; + +void +xf86OpenConsole(void) +{ + int fd, i; +#ifdef HAS_USL_VTS + struct vt_mode VT; + struct vt_stat vtinfo; + int FreeVTslot; + MessageType from = X_PROBED; +#endif + + if (serverGeneration == 1) + { + /* Check if we're run with euid==0 */ + if (geteuid() != 0) + FatalError("xf86OpenConsole: Server must be suid root\n"); + + /* Protect page 0 to help find NULL dereferencing */ + /* mprotect() doesn't seem to work */ + if (Protect0) + { + int fd = -1; + + if ((fd = open("/dev/zero", O_RDONLY, 0)) < 0) + { + xf86Msg(X_WARNING, + "xf86OpenConsole: cannot open /dev/zero (%s)\n", + strerror(errno)); + } + else + { + if ((int)mmap(0, 0x1000, PROT_NONE, + MAP_FIXED | MAP_SHARED, fd, 0) == -1) + xf86Msg(X_WARNING, + "xf86OpenConsole: failed to protect page 0 (%s)\n", + strerror(errno)); + + close(fd); + } + } + +#ifdef HAS_USL_VTS + + /* + * Setup the virtual terminal manager + */ + if (VTnum != -1) + { + xf86Info.vtno = VTnum; + from = X_CMDLINE; + } + else + { + if ((fd = open("/dev/vt00",O_RDWR,0)) < 0) + FatalError("xf86OpenConsole: Cannot open /dev/vt00 (%s)\n", + strerror(errno)); + + if (ioctl(fd, VT_GETSTATE, &vtinfo) < 0) + FatalError("xf86OpenConsole: Cannot determine current VT\n"); + + xf86StartVT = vtinfo.v_active; + + /* + * There is a SEVERE problem with x86's VT's. The VT_OPENQRY + * ioctl() will panic the entire system if all 8 (7 VT's+Console) + * terminals are used. The only other way I've found to determine + * if there is a free VT is to try activating all the the available + * VT's and see if they all succeed - if they do, there there is no + * free VT, and the Xserver cannot continue without panic'ing the + * system. (It's ugly, but it seems to work.) Note there is a + * possible race condition here. + * + * David Holland 2/23/94 + */ + + FreeVTslot = 0; + for (i = 7; (i >= 0) && !FreeVTslot; i--) + if (ioctl(fd, VT_ACTIVATE, i) != 0) + FreeVTslot = 1; + + if (!FreeVTslot) || + (ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) || + (xf86Info.vtno == -1)) + FatalError("xf86OpenConsole: Cannot find a free VT\n"); + + close(fd); + } + + xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno); + + sprintf(fb_dev, "/dev/vt%02d", xf86Info.vtno); /* Solaris 2.1 x86 */ + +#endif /* HAS_USL_VTS */ + + if (!KeepTty) + setpgrp(); + + if (((xf86Info.consoleFd = open(fb_dev, O_RDWR | O_NDELAY, 0)) < 0)) + FatalError("xf86OpenConsole: Cannot open %s (%s)\n", + fb_dev, strerror(errno)); + +#ifdef HAS_USL_VTS + + /* Change ownership of the vt */ + chown(fb_dev, getuid(), getgid()); + + /* + * Now get the VT + */ + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) + xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n"); + + if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) != 0) + xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n"); + + if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0) + FatalError("xf86OpenConsole: VT_GETMODE failed\n"); + + signal(SIGUSR1, xf86VTRequest); + + VT.mode = VT_PROCESS; + VT.relsig = SIGUSR1; + VT.acqsig = SIGUSR1; + + if (ioctl(xf86Info.consoleFd, VT_SETMODE, &VT) < 0) + FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed\n"); + + if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS) < 0) + FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed\n"); + } + else /* serverGeneration != 1 */ + { + /* + * Now re-get the VT + */ + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) + xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n"); + + if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) != 0) + xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n"); + + /* + * If the server doesn't have the VT when the reset occurs, + * this is to make sure we don't continue until the activate + * signal is received. + */ + if (!xf86Screens[0]->vtSema) + sleep(5); + +#endif /* HAS_USL_VTS */ + + } +} + +void +xf86CloseConsole(void) +{ +#ifdef HAS_USL_VTS + struct vt_mode VT; +#endif +#if defined(__SOL8__) || !defined(i386) + int tmp; +#endif + +#ifdef HAS_USL_VTS + + /* + * Solaris 2.1 x86 doesn't seem to "switch" back to the console when the VT + * is relinquished and its mode is reset to auto. Also, Solaris 2.1 seems + * to associate vt00 with the console so I've opened the "console" back up + * and made it the active vt again in text mode and then closed it. There + * must be a better hack for this but I'm not aware of one at this time. + * + * Doug Anson 11/6/93 + * danson@lgc.com + * + * Fixed - 12/5/93 - David Holland - davidh@dorite.use.com + * Did the whole thing similarly to the way linux does it + */ + + /* Reset the display back to text mode */ + ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT); + if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1) + { + VT.mode = VT_AUTO; /* Set default vt handling */ + ioctl(xf86Info.consoleFd, VT_SETMODE, &VT); + } + + /* Activate the VT that X was started on */ + ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86StartVT); + +#endif /* HAS_USL_VTS */ + + close(xf86Info.consoleFd); + +#if defined(__SOL8__) || !defined(i386) + + /* + * This probably shouldn't be here. However, there is no corresponding + * xf86CloseKbd() routine - DWH + */ + + /* Set the keyboard into "indirect" mode and turn off even translation */ + tmp = 0; + (void) ioctl(xf86Info.kbdFd, KIOCSDIRECT, &tmp); + tmp = TR_ASCII; + (void) ioctl(xf86Info.kbdFd, KIOCTRANS, &tmp); + + close(xf86Info.kbdFd); + +#endif +} + +int +xf86ProcessArgument(int argc, char **argv, int i) +{ + /* + * Keep server from detaching from controlling tty. This is useful when + * debugging, so the server can receive keyboard signals. + */ + if (!strcmp(argv[i], "-keeptty")) + { + KeepTty = TRUE; + return 1; + } + + /* + * Undocumented flag to protect page 0 from read/write to help catch NULL + * pointer dereferences. This is purely a debugging flag. + */ + if (!strcmp(argv[i], "-protect0")) + { + Protect0 = TRUE; + return 1; + } + +#ifdef HAS_USL_VTS + + if ((argv[i][0] == 'v') && (argv[i][1] == 't')) + { + if (sscanf(argv[i], "vt%2d", &VTnum) == 0) + { + UseMsg(); + VTnum = -1; + return 0; + } + + return 1; + } + +#endif /* HAS_USL_VTS */ + +#if defined(__SOL8__) || !defined(i386) + + if ((i + 1) < argc) { + if (!strcmp(argv[i], "-dev")) { + strncpy(fb_dev, argv[i+1], PATH_MAX); + fb_dev[PATH_MAX - 1] = '\0'; + return 2; + } + + if (!strcmp(argv[i], "-ar1")) { + xf86Info.kbdDelay = atoi(argv[i + 1]) * 1000; + return 2; + } + + if (!strcmp(argv[i], "-ar2")) { + xf86Info.kbdRate = atoi(argv[i + 1]) * 1000; + return 2; + } + } + +#endif + + return 0; +} + +void xf86UseMsg() +{ +#ifdef HAS_USL_VTS + ErrorF("vtXX Use the specified VT number\n"); +#endif +#if defined(__SOL8__) || !defined(i386) + ErrorF("-dev <fb> Framebuffer device\n"); + ErrorF("-ar1 <float> Set autorepeat initiate time (sec)\n"); + ErrorF(" (if not using XKB)\n"); + ErrorF("-ar2 <float> Set autorepeat interval time (sec)\n"); + ErrorF(" (if not using XKB)\n"); +#endif + ErrorF("-keeptty Don't detach controlling tty\n"); + ErrorF(" (for debugging only)\n"); +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_inout.s b/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_inout.s new file mode 100644 index 000000000..e8f03d0e8 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_inout.s @@ -0,0 +1,124 @@ +/ $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_inout.s,v 1.1 2001/05/28 02:42:31 tsi Exp $ +/ +/ Copyright 1994-2001 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. +/ +/ +/ File: sun_inout.s +/ +/ Purpose: Provide inb(), inw(), inl(), outb(), outw(), outl() functions +/ for Solaris x86 using the ProWorks compiler by SunPro +/ +/ Author: Installed into XFree86 SuperProbe by Doug Anson (danson@lgc.com) +/ Portions donated to XFree86 by Steve Dever (Steve.Dever@Eng.Sun.Com) +/ +/ Synopsis: (c callable external declarations) +/ extern unsigned char inb(int port); +/ extern unsigned short inw(int port); +/ extern unsigned long inl(int port); +/ extern void outb(int port, unsigned char value); +/ extern void outw(int port, unsigned short value); +/ extern void outl(int port, unsigned long value); +/ + +.file "sunos_inout.s" +.text + +.globl inb +.globl inw +.globl inl +.globl outb +.globl outw +.globl outl + +/ +/ unsigned char inb(int port); +/ +.align 4 +inb: + movl 4(%esp),%edx + subl %eax,%eax + inb (%dx) + ret +.type inb,@function +.size inb,.-inb + +/ +/ unsigned short inw(int port); +/ +.align 4 +inw: + movl 4(%esp),%edx + subl %eax,%eax + inw (%dx) + ret +.type inw,@function +.size inw,.-inw + +/ +/ unsigned long inl(int port); +/ +.align 4 +inl: + movl 4(%esp),%edx + inl (%dx) + ret +.type inl,@function +.size inl,.-inl + +/ +/ void outb(int port, unsigned char value); +/ +.align 4 +outb: + movl 4(%esp),%edx + movl 8(%esp),%eax + outb (%dx) + ret +.type outb,@function +.size outb,.-outb + +/ +/ void outw(int port, unsigned short value); +/ +.align 4 +outw: + movl 4(%esp),%edx + movl 8(%esp),%eax + outw (%dx) + ret +.type outw,@function +.size outw,.-outw + +/ +/ void outl(int port, unsigned long value); +/ +.align 4 +outl: + movl 4(%esp),%edx + movl 8(%esp),%eax + outl (%dx) + ret +.type outl,@function +.size outl,.-outl diff --git a/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_io.c b/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_io.c new file mode 100644 index 000000000..e2140b2b8 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_io.c @@ -0,0 +1,56 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_io.c,v 1.1 2001/05/28 02:42:31 tsi Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany + * Copyright 1993 by David Dawes <dawes@xfree86.org> + * + * 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 names of Thomas Roell and David Dawes + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. Thomas Roell and + * David Dawes makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * THOMAS ROELL AND DAVID DAWES DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL THOMAS ROELL OR DAVID DAWES 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. + * + */ + +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +void +xf86SoundKbdBell(int loudness, int pitch, int duration) +{ + int kbdCmd; + + if (loudness && pitch) + { + kbdCmd = KBD_CMD_BELL; + if (ioctl (xf86Info.kbdFd, KIOCCMD, &kbdCmd) == -1) { + ErrorF("Failed to activate bell\n"); + return; + } + + usleep(xf86Info.bell_duration * loudness * 20); + + kbdCmd = KBD_CMD_NOBELL; + if (ioctl (xf86Info.kbdFd, KIOCCMD, &kbdCmd) == -1) + ErrorF ("Failed to deactivate bell\n"); + } +} + +void +xf86SetKbdLeds(int leds) +{ + if( ioctl(xf86Info.kbdFd, KIOCSLED, &leds) < 0 ) + ErrorF("Failed to set Keyboard LED's\n"); +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_kbd.c b/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_kbd.c new file mode 100644 index 000000000..7e4998817 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_kbd.c @@ -0,0 +1,112 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_kbd.c,v 1.1 2001/05/28 02:42:31 tsi Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany + * Copyright 1993 by David Dawes <dawes@XFree86.org> + * Copyright 1999 by David Holland <davidh@iquest.net) + * + * 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 names of Thomas Roell, David Dawes, and David Holland not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Thomas Roell, David Dawes, and + * David Holland make no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + * + * THOMAS ROELL, DAVID DAWES, AND DAVID HOLLAND DISCLAIM ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THOMAS ROELL, DAVID DAWES, OR DAVID HOLLAND + * 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. + */ + +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +static int sun_otranslation = -1; +static int sun_odirect = -1; + +int +xf86GetKbdLeds() +{ + int leds; + + ioctl(xf86Info.kbdFd, KIOCGLED, &leds); + return leds; +} + +void +xf86SetKbdRepeat(char rad) +{ + /* Nothing to do */ +} + +/* + * Save initial keyboard state. This is called at the start of each server + * generation. + */ + +void +xf86KbdInit() +{ + int ktype, klayout; + + if (xf86Info.kbdFd < 0) { + xf86Info.kbdFd = open("/dev/kbd", O_RDWR|O_NONBLOCK); + if(xf86Info.kbdFd < 0) + FatalError("Unable to open keyboard: /dev/kbd\n"); + } + + /* + * None of the followin should ever fail. If it does, something is + * broken (IMO) - DWH 8/21/99 + */ + + if (ioctl(xf86Info.kbdFd, KIOCTYPE, &ktype) < 0) + FatalError("Unable to determine keyboard type: %d\n", errno); + + if (ioctl(xf86Info.kbdFd, KIOCLAYOUT, &klayout) < 0) + FatalError("Unable to determine keyboard layout: %d\n", errno); + + if (ioctl(xf86Info.kbdFd, KIOCGTRANS, &sun_otranslation) < 0) + FatalError("Unable to determine keyboard translation mode\n"); + + if (ioctl(xf86Info.kbdFd, KIOCGDIRECT, &sun_odirect) < 0) + FatalError("Unable to determine keyboard direct setting\n"); +} + +int +xf86KbdOn(void) +{ + int tmp = 1; + + if (ioctl(xf86Info.kbdFd, KIOCSDIRECT, &tmp) == -1) + FatalError("Setting keyboard direct mode on\n"); + + /* Setup translation */ + + tmp = TR_UNTRANS_EVENT; + + if (ioctl(xf86Info.kbdFd, KIOCTRANS, &tmp) == -1) + FatalError("Setting keyboard translation\n"); + + return xf86Info.kbdFd; +} + +int +xf86KbdOff() +{ + if ((sun_otranslation != -1) && + (ioctl(xf86Info.kbdFd, KIOCTRANS, &sun_otranslation) < 0)) + FatalError("Unable to restore keyboard translation mode\n"); + + if ((sun_odirect != 0) && + (ioctl(xf86Info.kbdFd, KIOCSDIRECT, &sun_odirect) < 0 )) + FatalError("Unable to restore keyboard direct setting\n"); + + return xf86Info.kbdFd; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_kbdEv.c b/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_kbdEv.c new file mode 100644 index 000000000..1c95b5b77 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_kbdEv.c @@ -0,0 +1,497 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_kbdEv.c,v 1.2 2001/08/17 22:08:15 tsi Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * Copyright 1993 by David Dawes <dawes@xfree86.org> + * + * 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 names of Thomas Roell and David Dawes not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Thomas Roell and David Dawes make no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * THOMAS ROELL AND DAVID DAWES DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL THOMAS ROELL OR DAVID DAWES 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. + */ + +/* [JCH-96/01/21] Extended std reverse map to four buttons. */ + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +#ifdef XINPUT +#include "XI.h" +#include "XIproto.h" +#include "xf86Xinput.h" +#else +#include "inputstr.h" +#endif + +#ifdef XFreeXDGA +#include "dgaproc.h" +#endif + +#include <sys/vuid_event.h> +#include "atKeynames.h" + +#ifdef XKB +extern Bool noXkbExtension; +#endif + +#define XE_POINTER 1 +#define XE_KEYBOARD 2 + +#ifdef XTESTEXT1 + +#define XTestSERVER_SIDE +#include "xtestext1.h" +extern short xtest_mousex; +extern short xtest_mousey; +extern int on_steal_input; +extern Bool XTestStealKeyData(); +extern void XTestStealMotionData(); + +#ifdef XINPUT +#define ENQUEUE(ev, code, direction, dev_type) \ + (ev)->u.u.detail = (code); \ + (ev)->u.u.type = (direction); \ + if (!on_steal_input || \ + XTestStealKeyData((ev)->u.u.detail, (ev)->u.u.type, dev_type, \ + xtest_mousex, xtest_mousey)) \ + xf86eqEnqueue((ev)) +#else +#define ENQUEUE(ev, code, direction, dev_type) \ + (ev)->u.u.detail = (code); \ + (ev)->u.u.type = (direction); \ + if (!on_steal_input || \ + XTestStealKeyData((ev)->u.u.detail, (ev)->u.u.type, dev_type, \ + xtest_mousex, xtest_mousey)) \ + mieqEnqueue((ev)) +#endif + +#else /* ! XTESTEXT1 */ + +#ifdef XINPUT +#define ENQUEUE(ev, code, direction, dev_type) \ + (ev)->u.u.detail = (code); \ + (ev)->u.u.type = (direction); \ + xf86eqEnqueue((ev)) +#else +#define ENQUEUE(ev, code, direction, dev_type) \ + (ev)->u.u.detail = (code); \ + (ev)->u.u.type = (direction); \ + mieqEnqueue((ev)) +#endif + +#endif + +static void startautorepeat(long keycode); +static CARD32 processautorepeat(OsTimerPtr timer, CARD32 now, pointer arg); + +static OsTimerPtr sunTimer = NULL; + +/* Map the Solaris keycodes to the "XFree86" keycodes. */ +static unsigned char map[256] = { + KEY_NOTUSED, /* 0 */ + KEY_Tilde, /* 1 */ + KEY_1, /* 2 */ + KEY_2, /* 3 */ + KEY_3, /* 4 */ + KEY_4, /* 5 */ + KEY_5, /* 6 */ + KEY_6, /* 7 */ + KEY_7, /* 8 */ + KEY_8, /* 9 */ + KEY_9, /* 10 */ + KEY_0, /* 11 */ + KEY_Minus, /* 12 */ + KEY_Equal, /* 13 */ + 0x7D, /*KEY_P_YEN*/ /* 14 */ + KEY_BackSpace, /* 15 */ + KEY_Tab, /* 16 */ + KEY_Q, /* 17 */ + KEY_W, /* 18 */ + KEY_E, /* 19 */ + KEY_R, /* 20 */ + KEY_T, /* 21 */ + KEY_Y, /* 22 */ + KEY_U, /* 23 */ + KEY_I, /* 24 */ + KEY_O, /* 25 */ + KEY_P, /* 26 */ + KEY_LBrace, /* 27 */ + KEY_RBrace, /* 28 */ + KEY_BSlash, /* 29 */ + KEY_CapsLock, /* 30 */ + KEY_A, /* 31 */ + KEY_S, /* 32 */ + KEY_D, /* 33 */ + KEY_F, /* 34 */ + KEY_G, /* 35 */ + KEY_H, /* 36 */ + KEY_J, /* 37 */ + KEY_K, /* 38 */ + KEY_L, /* 39 */ + KEY_SemiColon, /* 40 */ + KEY_Quote, /* 41 */ + KEY_UNKNOWN, /* 42 */ + KEY_Enter, /* 43 */ + KEY_ShiftL, /* 44 */ + KEY_Less, /* 45 */ + KEY_Z, /* 46 */ + KEY_X, /* 47 */ + KEY_C, /* 48 */ + KEY_V, /* 49 */ + KEY_B, /* 50 */ + KEY_N, /* 51 */ + KEY_M, /* 52 */ + KEY_Comma, /* 53 */ + KEY_Period, /* 54 */ + KEY_Slash, /* 55 */ + KEY_BSlash2, /* 56 */ + KEY_ShiftR, /* 57 */ + KEY_LCtrl, /* 58 */ + KEY_LMeta, /* 59 */ + KEY_Alt, /* 60 */ + KEY_Space, /* 61 */ + KEY_AltLang, /* 62 */ + KEY_RMeta, /* 63 */ + KEY_RCtrl, /* 64 */ + KEY_Menu, /* 65 */ + KEY_UNKNOWN, /* 66 */ + KEY_UNKNOWN, /* 67 */ + KEY_UNKNOWN, /* 68 */ + KEY_UNKNOWN, /* 69 */ + KEY_UNKNOWN, /* 70 */ + KEY_UNKNOWN, /* 71 */ + KEY_UNKNOWN, /* 72 */ + KEY_UNKNOWN, /* 73 */ + KEY_UNKNOWN, /* 74 */ + KEY_Insert, /* 75 */ + KEY_Delete, /* 76 */ + KEY_UNKNOWN, /* 77 */ + KEY_UNKNOWN, /* 78 */ + KEY_Left, /* 79 */ + KEY_Home, /* 80 */ + KEY_End, /* 81 */ + KEY_UNKNOWN, /* 82 */ + KEY_Up, /* 83 */ + KEY_Down, /* 84 */ + KEY_PgUp, /* 85 */ + KEY_PgDown, /* 86 */ + KEY_UNKNOWN, /* 87 */ + KEY_UNKNOWN, /* 88 */ + KEY_Right, /* 89 */ + KEY_NumLock, /* 90 */ + KEY_KP_7, /* 91 */ + KEY_KP_4, /* 92 */ + KEY_KP_1, /* 93 */ + KEY_UNKNOWN, /* 94 */ + KEY_KP_Divide, /* 95 */ + KEY_KP_8, /* 96 */ + KEY_KP_5, /* 97 */ + KEY_KP_2, /* 98 */ + KEY_KP_0, /* 99 */ + KEY_KP_Multiply, /* 100 */ + KEY_KP_9, /* 101 */ + KEY_KP_6, /* 102 */ + KEY_KP_3, /* 103 */ + KEY_KP_Decimal, /* 104 */ + KEY_KP_Minus, /* 105 */ + KEY_KP_Plus, /* 106 */ + KEY_UNKNOWN, /* 107 */ + KEY_KP_Enter, /* 108 */ + KEY_UNKNOWN, /* 109 */ + KEY_Escape, /* 110 */ + KEY_UNKNOWN, /* 111 */ + KEY_F1, /* 112 */ + KEY_F2, /* 113 */ + KEY_F3, /* 114 */ + KEY_F4, /* 115 */ + KEY_F5, /* 116 */ + KEY_F6, /* 117 */ + KEY_F7, /* 118 */ + KEY_F8, /* 119 */ + KEY_F9, /* 120 */ + KEY_F10, /* 121 */ + KEY_F11, /* 122 */ + KEY_F12, /* 123 */ + KEY_Print, /* 124 */ + KEY_ScrollLock, /* 125 */ + KEY_Pause, /* 126 */ + KEY_UNKNOWN, /* 127 */ + KEY_UNKNOWN, /* 128 */ + KEY_UNKNOWN, /* 129 */ + KEY_UNKNOWN, /* 130 */ + KEY_NFER, /* 131 */ + KEY_XFER, /* 132 */ + KEY_HKTG, /* 133 */ + KEY_UNKNOWN, /* 134 */ + /* The rest default to KEY_UNKNOWN */ +}; + +/* + * sunPostKbdEvent -- + * Translate the raw hardware Firm_event into an XEvent, and tell DIX + * about it. KeyCode preprocessing and so on is done ... + * + * Most of the Solaris stuff has whacked Panix/PC98 support in the + * interests of simplicity - DWH 8/30/99 + */ + +static void +sunPostKbdEvent(Firm_event *event) +{ + int specialkey; + Bool down; + KeyClassRec *keyc = ((DeviceIntPtr)xf86Info.pKeyboard)->key; + Bool updateLeds = FALSE; + Bool UsePrefix = FALSE; + Bool Direction = FALSE; + xEvent kevent; + KeySym *keysym; + int keycode; + static int lockkeys = 0; + + /* Give down a value */ + if (event->value == VKEY_DOWN) + down = TRUE; + else + down = FALSE; + + /* + * and now get some special keysequences + */ + + specialkey = map[event->id]; + + if ((ModifierDown(ControlMask | AltMask)) || + (ModifierDown(ControlMask | AltLangMask))) + { + switch (specialkey) { + + case KEY_BackSpace: + if (!xf86Info.dontZap) { + DGAShutdown(); + GiveUp(0); + } + break; + + /* + * The idea here is to pass the scancode down to a list of registered + * routines. There should be some standard conventions for processing + * certain keys. + */ + case KEY_KP_Minus: /* Keypad - */ + if (!xf86Info.dontZoom) { + if (down) + xf86ZoomViewport(xf86Info.currentScreen, -1); + return; + } + break; + + case KEY_KP_Plus: /* Keypad + */ + if (!xf86Info.dontZoom) { + if (down) + xf86ZoomViewport(xf86Info.currentScreen, 1); + return; + } + break; + } + } + + /* + * Now map the scancodes to real X-keycodes ... + */ + keycode = map[event->id]; + if (keycode == KEY_NOTUSED) { + xf86MsgVerb(X_INFO, 0, + "raw code %d mapped to KEY_NOTUSED -- please report\n", event->id); + return; + } + if (keycode == KEY_UNKNOWN) { + xf86MsgVerb(X_INFO, 0, + "raw code %d mapped to KEY_UNKNOWN -- please report\n", event->id); + return; + } + keycode += MIN_KEYCODE; + keysym = keyc->curKeySyms.map + + (keyc->curKeySyms.mapWidth * + (keycode - keyc->curKeySyms.minKeyCode)); + +#ifdef XKB + if (noXkbExtension) +#endif + { + /* + * Toggle lock keys. + */ +#define CAPSFLAG 0x01 +#define NUMFLAG 0x02 +#define SCROLLFLAG 0x04 +#define MODEFLAG 0x08 + + if (down) { + /* + * Handle the KeyPresses of the lock keys. + */ + + switch (keysym[0]) { + + case XK_Caps_Lock: + if (lockkeys & CAPSFLAG) { + lockkeys &= ~CAPSFLAG; + return; + } + lockkeys |= CAPSFLAG; + updateLeds = TRUE; + xf86Info.capsLock = down; + break; + + case XK_Num_Lock: + if (lockkeys & NUMFLAG) { + lockkeys &= ~NUMFLAG; + return; + } + lockkeys |= NUMFLAG; + updateLeds = TRUE; + xf86Info.numLock = down; + break; + + case XK_Scroll_Lock: + if (lockkeys & SCROLLFLAG) { + lockkeys &= ~SCROLLFLAG; + return; + } + lockkeys |= SCROLLFLAG; + updateLeds = TRUE; + xf86Info.scrollLock = down; + break; + } + } else { + /* + * Handle the releases of the lock keys. + */ + + switch (keysym[0]) { + + case XK_Caps_Lock: + if (lockkeys & CAPSFLAG) + return; + updateLeds = TRUE; + xf86Info.capsLock = down; + break; + + case XK_Num_Lock: + if (lockkeys & NUMFLAG) + return; + updateLeds = TRUE; + xf86Info.numLock = down; + break; + + case XK_Scroll_Lock: + if (lockkeys & SCROLLFLAG) + return; + updateLeds = TRUE; + xf86Info.scrollLock = down; + break; + } + } + + if (updateLeds) + xf86KbdLeds(); + + /* + * If this keycode is not a modifier key, and its down initiate the + * autorepeate sequence. (Only necessary if not using XKB). + * + * If its not down, then reset the timer. + */ + if (!keyc->modifierMap[keycode]) { + if (down) { + startautorepeat(keycode); + } else { + TimerFree(sunTimer); + sunTimer = NULL; + } + } + } + + xf86Info.lastEventTime = + kevent.u.keyButtonPointer.time = + GetTimeInMillis(); + + /* + * And now send these prefixes ... + * NOTE: There cannot be multiple Mode_Switch keys !!!! + */ + + ENQUEUE(&kevent, keycode, (down ? KeyPress : KeyRelease), XE_KEYBOARD); +} + +/* + * Lets try reading more than one keyboard event at a time in the hopes that + * this will be slightly more efficient. Or we could just try the MicroSoft + * method, and forget about efficiency. :-) + */ +void +xf86KbdEvents() +{ + Firm_event event[64]; + int nBytes, i; + + /* I certainly hope its not possible to read partial events */ + + if ((nBytes = read(xf86Info.kbdFd, (char *)event, sizeof(event))) > 0) + { + for (i = 0; i < (nBytes / sizeof(Firm_event)); i++) + sunPostKbdEvent(&event[i]); + } +} + +/* + * Autorepeat stuff + */ + +void +startautorepeat(long keycode) +{ + sunTimer = TimerSet(sunTimer, /* Timer */ + 0, /* Flags */ + xf86Info.kbdDelay, /* millis */ + processautorepeat, /* callback */ + (pointer) keycode); /* arg for timer */ +} + +CARD32 +processautorepeat(OsTimerPtr timer, CARD32 now, pointer arg) +{ + xEvent kevent; + int keycode; + + keycode = (long)arg; + + xf86Info.lastEventTime = + kevent.u.keyButtonPointer.time = + GetTimeInMillis(); + + /* + * Repeat a key by faking a KeyRelease, and a KeyPress event in rapid + * succession + */ + + ENQUEUE(&kevent, keycode, KeyRelease, XE_KEYBOARD); + ENQUEUE(&kevent, keycode, KeyPress, XE_KEYBOARD); + + /* And return the appropriate value so we get rescheduled */ + return xf86Info.kbdRate; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_mouse.c b/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_mouse.c new file mode 100644 index 000000000..cc3b7ec6b --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_mouse.c @@ -0,0 +1,316 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_mouse.c,v 1.2 2001/08/17 22:08:15 tsi Exp $ */ +/* + * Copyright 1999-2001 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. + */ + +#include "xf86.h" +#include "xf86_OSlib.h" +#include "xf86OSmouse.h" + +#if defined(__SOL8__) || !defined(i386) + +#include "xisb.h" +#include "mipointer.h" +#include <sys/vuid_event.h> + +/* Names of protocols that are handled internally here. */ + +static const char *internalNames[] = { + "VUID", + NULL +}; + +typedef struct _VuidMseRec { + Firm_event event; + unsigned char *buffer; +} VuidMseRec, *VuidMsePtr; + + +static int vuidMouseProc(DeviceIntPtr pPointer, int what); +static void vuidReadInput(InputInfoPtr pInfo); + +/* This function is called when the protocol is "VUID". */ +static Bool +vuidPreInit(InputInfoPtr pInfo, const char *protocol, int flags) +{ + MouseDevPtr pMse = pInfo->private; + VuidMsePtr pVuidMse; + int i; + + pVuidMse = xalloc(sizeof(VuidMseRec)); + if (pVuidMse == NULL) { + xf86Msg(X_ERROR, "%s: cannot allocate VuidMouseRec\n", pInfo->name); + xfree(pMse); + return FALSE; + } + + pMse->protocol = protocol; + xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, protocol); + + /* Collect the options, and process the common options. */ + xf86CollectInputOptions(pInfo, NULL, NULL); + xf86ProcessCommonOptions(pInfo, pInfo->options); + + /* Check if the device can be opened. */ + pInfo->fd = xf86OpenSerial(pInfo->options); + if (pInfo->fd == -1) { + if (xf86GetAllowMouseOpenFail()) + xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name); + else { + xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name); + xfree(pVuidMse); + xfree(pMse); + return FALSE; + } + } + pVuidMse->buffer = (unsigned char *)&pVuidMse->event; + xf86CloseSerial(pInfo->fd); + pInfo->fd = -1; + + /* Private structure */ + pMse->mousePriv = pVuidMse; + + /* Process common mouse options (like Emulate3Buttons, etc). */ + pMse->CommonOptions(pInfo); + + /* Setup the local procs. */ + pInfo->device_control = vuidMouseProc; + pInfo->read_input = vuidReadInput; + + pInfo->flags |= XI86_CONFIGURED; + return TRUE; +} + +static void +vuidReadInput(InputInfoPtr pInfo) +{ + MouseDevPtr pMse; + VuidMsePtr pVuidMse; + int buttons; + int dx = 0, dy = 0, dz = 0, dw = 0; + unsigned int n; + int c; + unsigned char *pBuf; + + pMse = pInfo->private; + pVuidMse = pMse->mousePriv; + buttons = pMse->lastButtons; + XisbBlockDuration(pMse->buffer, -1); + pBuf = pVuidMse->buffer; + n = 0; + + do { + while (n < sizeof(Firm_event) && (c = XisbRead(pMse->buffer)) >= 0) { + pBuf[n++] = (unsigned char)c; + } + + if (n == 0) + return; + + if (n != sizeof(Firm_event)) { + xf86Msg(X_WARNING, "%s: incomplete packet, size %d\n", + pInfo->name, n); + } + + if (pVuidMse->event.id >= BUT_FIRST && pVuidMse->event.id <= BUT_LAST) { + /* button */ + int butnum = pVuidMse->event.id - BUT_FIRST; + if (butnum < 3) + butnum = 2 - butnum; + if (!pVuidMse->event.value) + buttons &= ~(1 << butnum); + else + buttons |= (1 << butnum); + } else if (pVuidMse->event.id >= VLOC_FIRST && + pVuidMse->event.id <= VLOC_LAST) { + /* axis */ + int delta = pVuidMse->event.value; + switch(pVuidMse->event.id) { + case LOC_X_DELTA: + dx += delta; + break; + case LOC_Y_DELTA: + dy -= delta; + break; + } + } + + n = 0; + if ((c = XisbRead(pMse->buffer)) >= 0) { + /* Another packet. Handle it right away. */ + pBuf[n++] = c; + } + } while (n != 0); + + pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw); + return; +} + +#define NUMEVENTS 64 + +static int +vuidMouseProc(DeviceIntPtr pPointer, int what) +{ + InputInfoPtr pInfo; + MouseDevPtr pMse; + VuidMsePtr pVuidMse; + unsigned char map[MSE_MAXBUTTONS + 1]; + int nbuttons; + + pInfo = pPointer->public.devicePrivate; + pMse = pInfo->private; + pMse->device = pPointer; + pVuidMse = pMse->mousePriv; + + switch (what) { + case DEVICE_INIT: + pPointer->public.on = FALSE; + + for (nbuttons = 0; nbuttons < MSE_MAXBUTTONS; ++nbuttons) + map[nbuttons + 1] = nbuttons + 1; + + InitPointerDeviceStruct((DevicePtr)pPointer, + map, + min(pMse->buttons, MSE_MAXBUTTONS), + miPointerGetMotionEvents, + pMse->Ctrl, + miPointerGetMotionBufferSize()); + + /* X valuator */ + xf86InitValuatorAxisStruct(pPointer, 0, 0, -1, 1, 0, 1); + xf86InitValuatorDefaults(pPointer, 0); + /* Y valuator */ + xf86InitValuatorAxisStruct(pPointer, 1, 0, -1, 1, 0, 1); + xf86InitValuatorDefaults(pPointer, 1); + xf86MotionHistoryAllocate(pInfo); + break; + + case DEVICE_ON: + pInfo->fd = xf86OpenSerial(pInfo->options); + if (pInfo->fd == -1) + xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name); + else { + pMse->buffer = XisbNew(pInfo->fd, + NUMEVENTS * sizeof(Firm_event)); + if (!pMse->buffer) { + xfree(pMse); + xf86CloseSerial(pInfo->fd); + pInfo->fd = -1; + } else { + int fmt = VUID_FIRM_EVENT; + ioctl(pInfo->fd, VUIDSFORMAT, &fmt); + xf86FlushInput(pInfo->fd); + AddEnabledDevice(pInfo->fd); + } + } + pMse->lastButtons = 0; + pMse->emulateState = 0; + pPointer->public.on = TRUE; + break; + + case DEVICE_OFF: + case DEVICE_CLOSE: + if (pInfo->fd != -1) { + RemoveEnabledDevice(pInfo->fd); + if (pMse->buffer) { + XisbFree(pMse->buffer); + pMse->buffer = NULL; + } + xf86CloseSerial(pInfo->fd); + pInfo->fd = -1; + } + pPointer->public.on = FALSE; + usleep(300000); + break; + } + return Success; +} + +static Bool +sunMousePreInit(InputInfoPtr pInfo, const char *protocol, int flags) +{ + /* The protocol is guaranteed to be one of the internalNames[] */ + if (xf86NameCmp(protocol, "VUID") == 0) { + return vuidPreInit(pInfo, protocol, flags); + } + return TRUE; +} + +static const char ** +BuiltinNames(void) +{ + return internalNames; +} + +static Bool +CheckProtocol(const char *protocol) +{ + int i; + + for (i = 0; internalNames[i]; i++) + if (xf86NameCmp(protocol, internalNames[i]) == 0) + return TRUE; + + return FALSE; +} + +static const char * +DefaultProtocol(void) +{ + return "VUID"; +} + +#else /* __SOL8__ || !i386 */ + +#undef MSE_MISC +#define MSE_MISC 0 + +#endif /* !__SOL8__ && i386 */ + +static int +SupportedInterfaces(void) +{ + /* XXX This needs to be checked. */ + return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_XPS2 | MSE_MISC; +} + +OSMouseInfoPtr +xf86OSMouseInit(int flags) +{ + OSMouseInfoPtr p; + + p = xcalloc(sizeof(OSMouseInfoRec), 1); + if (!p) + return NULL; + p->SupportedInterfaces = SupportedInterfaces; +#if defined(__SOL8__) || !defined(i386) + p->BuiltinNames = BuiltinNames; + p->DefaultProtocol = DefaultProtocol; + p->CheckProtocol = CheckProtocol; + p->PreInit = sunMousePreInit; +#endif + return p; +} + diff --git a/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_vid.c b/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_vid.c new file mode 100644 index 000000000..15bf69b11 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_vid.c @@ -0,0 +1,239 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_vid.c,v 1.1 2001/05/28 02:42:31 tsi Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany + * Copyright 1993 by David Wexelblat <dwex@goblin.org> + * + * 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 names 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. + * + */ + +#ifdef i386 +#define _NEED_SYSI86 +#endif +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +/***************************************************************************/ +/* Video Memory Mapping section */ +/***************************************************************************/ + +char *apertureDevName = NULL; + +Bool +xf86LinearVidMem() +{ +#ifdef i386 + int mmapFd; + + apertureDevName = "/dev/xsvc"; + if ((mmapFd = open(apertureDevName, O_RDWR)) < 0) + { +#ifndef __SOL8__ + apertureDevName = "/dev/fbs/aperture"; + if((mmapFd = open(apertureDevName, O_RDWR)) < 0) +#endif + { + xf86Msg(X_WARNING, + "xf86LinearVidMem: failed to open %s (%s)\n", + apertureDevName, strerror(errno)); + xf86Msg(X_WARNING, "xf86LinearVidMem:" +#ifndef __SOL8__ + " either /dev/fbs/aperture or" +#endif + " /dev/xsvc device driver" + " required\n"); + xf86Msg(X_WARNING, + "xf86LinearVidMem: linear memory access disabled\n"); + return FALSE; + } + } + close(mmapFd); + return TRUE; +#else /* i386 */ + FatalError("xf86LinearVidMem() called\n"); + + return FALSE; /* Gd'ole gcc */ +#endif /* i386 */ +} + +pointer +xf86MapVidMem(int ScreenNum, int Flags, unsigned long Base, unsigned long Size) +{ +#ifdef i386 + pointer base; + int fd; + char solx86_vtname[20]; + + /* + * Solaris 2.1 x86 SVR4 (10/27/93) + * The server must treat the virtual terminal device file as the + * standard SVR4 /dev/pmem. + * + * Using the /dev/vtXX device as /dev/pmem only works for the + * A0000-FFFFF region - If we wish you mmap the linear aperture + * it requires a device driver. + * + * So what we'll do is use /dev/vtXX for the A0000-FFFFF stuff, and + * try to use the /dev/fbs/aperture or /dev/xsvc driver if the server + * tries to mmap anything > FFFFF. Its very very unlikely that the + * server will try to mmap anything below FFFFF that can't be handled + * by /dev/vtXX. + * + * DWH - 2/23/94 + * DWH - 1/31/99 (Gee has it really been 5 years?) + * + * Solaris 2.8 7/26/99 + * Use /dev/xsvc for everything + * + * DWH - 7/26/99 - Solaris8/dev/xsvc changes + */ + +#ifndef __SOL8__ + if(Base < 0xFFFFF) + sprintf(solx86_vtname,"/dev/vt%02d",xf86Info.vtno); + else +#endif + { + if (!apertureDevName) + if (!xf86LinearVidMem()) + FatalError("xf86MapVidMem: Could not mmap " + "linear framebuffer [s=%x,a=%x]\n", + Size, Base); + + sprintf(solx86_vtname, apertureDevName); + } + + if ((fd = open(solx86_vtname, O_RDWR,0)) < 0) + { + FatalError("xf86MapVidMem: failed to open %s (%s)\n", + solx86_vtname, strerror(errno)); + } + base = mmap((caddr_t)0, Size, PROT_READ|PROT_WRITE, + MAP_SHARED, fd, (off_t)Base); + close(fd); + if (base == MAP_FAILED) + { + FatalError("%s: Could not mmap framebuffer [s=%x,a=%x] (%s)\n", + "xf86MapVidMem", Size, Base, strerror(errno)); + } + return(base); +#else /* i386 */ + FatalError("xf86MapVidMem() called\n"); + + return NULL; /* Gd'ole gcc */ +#endif +} + +/* ARGSUSED */ +void +xf86UnMapVidMem(int ScreenNum, pointer Base, unsigned long Size) +{ + munmap(Base, Size); +} + +/***************************************************************************/ +/* I/O Permissions section */ +/***************************************************************************/ + +static Bool ExtendedEnabled = FALSE; + +void +xf86EnableIO() +{ +#ifdef i386 + if (ExtendedEnabled) + return; + + if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) < 0) + FatalError("xf86EnableIOPorts: Failed to set IOPL for I/O\n"); +#endif /* i386 */ + + ExtendedEnabled = TRUE; +} + +void +xf86DisableIO() +{ +#ifdef i386 + if(!ExtendedEnabled) + return; + + sysi86(SI86V86, V86SC_IOPL, 0); +#endif /* i386 */ + + ExtendedEnabled = FALSE; +} + + +/***************************************************************************/ +/* Interrupt Handling section */ +/***************************************************************************/ + +Bool xf86DisableInterrupts() +{ +#ifdef i386 + if (!ExtendedEnabled && (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) < 0)) + return FALSE; + +#ifdef __GNUC__ + __asm__ __volatile__("cli"); +#else + asm("cli"); +#endif /* __GNUC__ */ + + if (!ExtendedEnabled) + sysi86(SI86V86, V86SC_IOPL, 0); +#endif /* i386 */ + + return TRUE; +} + +void xf86EnableInterrupts() +{ +#ifdef i386 + if (!ExtendedEnabled && (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) < 0)) + return; + +#ifdef __GNUC__ + __asm__ __volatile__("sti"); +#else + asm("sti"); +#endif /* __GNUC__ */ + + if (!ExtendedEnabled) + sysi86(SI86V86, V86SC_IOPL, 0); +#endif /* i386 */ +} + +void +xf86MapReadSideEffects(int ScreenNum, int Flags, pointer Base, + unsigned long Size) +{ +} + +Bool +xf86CheckMTRR(int ScreenNum) +{ + return FALSE; +} + diff --git a/xc/programs/Xserver/hw/xfree86/xf86cfg/TODO b/xc/programs/Xserver/hw/xfree86/xf86cfg/TODO new file mode 100644 index 000000000..75fe91b95 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/xf86cfg/TODO @@ -0,0 +1,33 @@ +$XFree86: xc/programs/Xserver/hw/xfree86/xf86cfg/TODO,v 1.1 2001/07/04 16:09:14 paulo Exp $ + +o Have code to fetch the SymTabRec chipset list from a video driver. + This is mostly useful for the testing tool/interface, so that the + Cards file "uptodate" state can also be verified. + Probably it is better to forgot about the Cards file, and + either parse the output of scanpci, or link libscanpci.a + (and whatever else be required) in xf86cfg. + +o Check if a module is "certified", there was some talk about a + certification process in the past. + +o Rewrite mouse driver to use the same code as video drivers, so that + it is possible to store all available options in a single place. + This would also require rewriting all existing input device modules. + (Probably most of this can be made with cpp macros). + +o Create a protocol to allow 3rd part xf86cfg modules. + +o Write an interface for testing extensions/accel, maybe a frontend to + xdpyinfo, x11perf, glxinfo, etc. + +o Write a "wizard" mode, as several users find the graphical interface + too complicated, but find the text one easier to user. + +o Write code to use a Monitors database, either update the old Monitors + file or use RedHat MonitorsDB. + Chris Morgan is writting code to use MonitorsDB. + If xf86cfg could be changed to ddcprobe (in all supported platforms), + it would be even be a better solution than using a database. + +o Add interface to allow changing comments without the need of editing + XF86Config with a text editor. diff --git a/xc/programs/Xserver/hw/xfree86/xf86cfg/loadmod.c b/xc/programs/Xserver/hw/xfree86/xf86cfg/loadmod.c new file mode 100644 index 000000000..d1f78a64c --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/xf86cfg/loadmod.c @@ -0,0 +1,595 @@ +/* + * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com) + * + * 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 + * CONECTIVA LINUX 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 Conectiva Linux shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from + * Conectiva Linux. + * + * Author: Paulo César Pereira de Andrade <pcpa@conectiva.com.br> + * + * $XFree86: xc/programs/Xserver/hw/xfree86/xf86cfg/loadmod.c,v 1.7 2001/08/01 00:44:57 tsi Exp $ + */ + +#ifdef USE_MODULES +#define LOADER_PRIVATE +#include "loader.h" + +#define True 1 +#define False 0 +#define XtPointer char* +#define XtMalloc malloc +#define XtCalloc calloc +#define XtRealloc realloc +#define XtFree free +#define XtNew(t) malloc(sizeof(t)) +#define XtNewString(s) ((s) ? strdup(s) : NULL) + +#define pointer void* + +/* XXX beware (or fix it) libc functions called here are the xf86 ones */ + +static void AddModuleOptions(char*, const OptionInfoRec*); +#if 0 +void xf86AddDriver(DriverPtr, void*, int); +Bool xf86ServerIsOnlyDetecting(void); +void xf86AddInputDriver(InputDriverPtr, pointer, int); +void xf86AddModuleInfo(ModuleInfoPtr, void*); +Bool xf86LoaderCheckSymbol(const char*); +void xf86LoaderReqSymLists(const char **, ...); +void xf86Msg(int, const char*, ...); +void xf86PrintChipsets(const char*, const char*, SymTabPtr); +void xf86ErrorFVerb(int verb, const char *format, ...); +pciVideoPtr *xf86GetPciVideoInfo(void); +int xf86MatchDevice(const char*, GDevPtr**); +int xf86MatchPciInstances(const char*, int, SymTabPtr, PciChipsets*, GDevPtr*, int, DriverPtr,int**); +int xf86MatchIsaInstances(const char*, SymTabPtr, pointer*, DriverPtr, pointer, GDevPtr*, int, int**); +void *xf86LoadDrvSubModule(DriverPtr drv, const char*); +void xf86DrvMsg(int, int, const char*, ...); +#endif +void *xf86GetPciConfigInfo(void); + +extern char *loaderPath, **loaderList, **ploaderList; +xf86cfgModuleOptions *module_options; +FontModule *font_module; +int numFontModules; + +extern int noverify, error_level; + +int xf86ShowUnresolved = 1; + +LOOKUP miLookupTab[] = {{0,0}}; +LOOKUP dixLookupTab[] = {{0,0}}; +LOOKUP fontLookupTab[] = {{0,0}}; +LOOKUP extLookupTab[] = {{0,0}}; +LOOKUP xfree86LookupTab[] = { + /* Loader functions */ + SYMFUNC(LoaderDefaultFunc) + SYMFUNC(LoadSubModule) + SYMFUNC(DuplicateModule) + SYMFUNC(LoaderErrorMsg) + SYMFUNC(LoaderCheckUnresolved) + SYMFUNC(LoadExtension) + SYMFUNC(LoadFont) + SYMFUNC(LoaderReqSymbols) + SYMFUNC(LoaderReqSymLists) + SYMFUNC(LoaderRefSymbols) + SYMFUNC(LoaderRefSymLists) + SYMFUNC(UnloadSubModule) + SYMFUNC(LoaderSymbol) + SYMFUNC(LoaderListDirs) + SYMFUNC(LoaderFreeDirList) + SYMFUNC(LoaderGetOS) + + /* + * these here are our own interfaces to libc functions + */ + SYMFUNC(xf86abort) + SYMFUNC(xf86abs) + SYMFUNC(xf86acos) + SYMFUNC(xf86asin) + SYMFUNC(xf86atan) + SYMFUNC(xf86atan2) + SYMFUNC(xf86atof) + SYMFUNC(xf86atoi) + SYMFUNC(xf86atol) + SYMFUNC(xf86bsearch) + SYMFUNC(xf86ceil) + SYMFUNC(xf86calloc) + SYMFUNC(xf86clearerr) + SYMFUNC(xf86close) + SYMFUNC(xf86cos) + SYMFUNC(xf86exit) + SYMFUNC(xf86exp) + SYMFUNC(xf86fabs) + SYMFUNC(xf86fclose) + SYMFUNC(xf86feof) + SYMFUNC(xf86ferror) + SYMFUNC(xf86fflush) + SYMFUNC(xf86fgetc) + SYMFUNC(xf86fgetpos) + SYMFUNC(xf86fgets) + SYMFUNC(xf86floor) + SYMFUNC(xf86fmod) + SYMFUNC(xf86fopen) + SYMFUNC(xf86fprintf) + SYMFUNC(xf86fputc) + SYMFUNC(xf86fputs) + SYMFUNC(xf86fread) + SYMFUNC(xf86free) + SYMFUNC(xf86freopen) + SYMFUNC(xf86frexp) + SYMFUNC(xf86fscanf) + SYMFUNC(xf86fseek) + SYMFUNC(xf86fsetpos) + SYMFUNC(xf86ftell) + SYMFUNC(xf86fwrite) + SYMFUNC(xf86getc) + SYMFUNC(xf86getenv) + SYMFUNC(xf86getpagesize) + SYMFUNC(xf86hypot) + SYMFUNC(xf86ioctl) + SYMFUNC(xf86isalnum) + SYMFUNC(xf86isalpha) + SYMFUNC(xf86iscntrl) + SYMFUNC(xf86isdigit) + SYMFUNC(xf86isgraph) + SYMFUNC(xf86islower) + SYMFUNC(xf86isprint) + SYMFUNC(xf86ispunct) + SYMFUNC(xf86isspace) + SYMFUNC(xf86isupper) + SYMFUNC(xf86isxdigit) + SYMFUNC(xf86labs) + SYMFUNC(xf86ldexp) + SYMFUNC(xf86log) + SYMFUNC(xf86log10) + SYMFUNC(xf86lseek) + SYMFUNC(xf86malloc) + SYMFUNC(xf86memchr) + SYMFUNC(xf86memcmp) + SYMFUNC(xf86memcpy) +#if (defined(__powerpc__) && (defined(Lynx) || defined(linux))) || defined(__sparc__) || defined(__ia64__) + /* + * Some PPC, SPARC, and IA64 compilers generate calls to memcpy to handle + * structure copies. This causes a problem both here and in shared + * libraries as there is no way to map the name of the call to the + * correct function. + */ + SYMFUNC(memcpy) + /* + * Some PPC, SPARC, and IA64 compilers generate calls to memset to handle + * aggregate initializations. + */ + SYMFUNC(memset) +#endif + SYMFUNC(xf86memmove) + SYMFUNC(xf86memset) + SYMFUNC(xf86mmap) + SYMFUNC(xf86modf) + SYMFUNC(xf86munmap) + SYMFUNC(xf86open) + SYMFUNC(xf86perror) + SYMFUNC(xf86pow) + SYMFUNC(xf86printf) + SYMFUNC(xf86qsort) + SYMFUNC(xf86read) + SYMFUNC(xf86realloc) + SYMFUNC(xf86remove) + SYMFUNC(xf86rename) + SYMFUNC(xf86rewind) + SYMFUNC(xf86setbuf) + SYMFUNC(xf86setvbuf) + SYMFUNC(xf86sin) + SYMFUNC(xf86snprintf) + SYMFUNC(xf86sprintf) + SYMFUNC(xf86sqrt) + SYMFUNC(xf86sscanf) + SYMFUNC(xf86strcat) + SYMFUNC(xf86strcmp) + SYMFUNC(xf86strcasecmp) + SYMFUNC(xf86strcpy) + SYMFUNC(xf86strcspn) + SYMFUNC(xf86strerror) + SYMFUNC(xf86strlen) + SYMFUNC(xf86strncmp) + SYMFUNC(xf86strncasecmp) + SYMFUNC(xf86strncpy) + SYMFUNC(xf86strpbrk) + SYMFUNC(xf86strchr) + SYMFUNC(xf86strrchr) + SYMFUNC(xf86strspn) + SYMFUNC(xf86strstr) + SYMFUNC(xf86strtod) + SYMFUNC(xf86strtok) + SYMFUNC(xf86strtol) + SYMFUNC(xf86strtoul) + SYMFUNC(xf86tan) + SYMFUNC(xf86tmpfile) + SYMFUNC(xf86tolower) + SYMFUNC(xf86toupper) + SYMFUNC(xf86ungetc) + SYMFUNC(xf86vfprintf) + SYMFUNC(xf86vsnprintf) + SYMFUNC(xf86vsprintf) + SYMFUNC(xf86write) + +/* non-ANSI C functions */ + SYMFUNC(xf86opendir) + SYMFUNC(xf86closedir) + SYMFUNC(xf86readdir) + SYMFUNC(xf86rewinddir) + SYMFUNC(xf86ffs) + SYMFUNC(xf86strdup) + SYMFUNC(xf86bzero) + SYMFUNC(xf86usleep) + SYMFUNC(xf86execl) + + SYMFUNC(xf86getsecs) + SYMFUNC(xf86fpossize) /* for returning sizeof(fpos_t) */ + + SYMFUNC(xf86stat) + SYMFUNC(xf86fstat) + SYMFUNC(xf86access) + SYMFUNC(xf86geteuid) + SYMFUNC(xf86getegid) + SYMFUNC(xf86getpid) + SYMFUNC(xf86mknod) + SYMFUNC(xf86chmod) + SYMFUNC(xf86chown) + SYMFUNC(xf86sleep) + SYMFUNC(xf86mkdir) + SYMFUNC(xf86shmget) + SYMFUNC(xf86shmat) + SYMFUNC(xf86shmdt) + SYMFUNC(xf86shmctl) + SYMFUNC(xf86setjmp) + SYMFUNC(xf86longjmp) + + SYMFUNC(xf86AddDriver) + SYMFUNC(xf86ServerIsOnlyDetecting) + SYMFUNC(xf86AddInputDriver) + SYMFUNC(xf86AddModuleInfo) + SYMFUNC(xf86LoaderCheckSymbol) + + SYMFUNC(xf86LoaderReqSymLists) + SYMFUNC(xf86Msg) + SYMFUNC(ErrorF) + SYMFUNC(xf86PrintChipsets) + SYMFUNC(xf86ErrorFVerb) + SYMFUNC(xf86GetPciVideoInfo) + SYMFUNC(xf86MatchDevice) + SYMFUNC(xf86MatchPciInstances) + SYMFUNC(xf86MatchIsaInstances) + SYMFUNC(Xfree) + SYMFUNC(xf86LoadDrvSubModule) + SYMFUNC(xf86DrvMsg) + SYMFUNC(xf86GetPciConfigInfo) + {0,0} +}; + +static DriverPtr driver; +static ModuleInfoPtr info; +static SymTabPtr chips; +static int vendor; +ModuleType module_type = GenericModule; + +static void +AddModuleOptions(char *name, const OptionInfoRec *option) +{ + xf86cfgModuleOptions *ptr; + const OptionInfoRec *tmp; + SymTabPtr ctmp; + int count; + + ptr = XtNew(xf86cfgModuleOptions); + ptr->name = XtNewString(name); + ptr->type = module_type; + if (option) { + for (count = 0, tmp = option; tmp->name != NULL; tmp++, count++) + ; + ++count; + ptr->option = XtCalloc(1, count * sizeof(OptionInfoRec)); + for (count = 0, tmp = option; tmp->name != NULL; count++, tmp++) { + memcpy(&ptr->option[count], tmp, sizeof(OptionInfoRec)); + ptr->option[count].name = XtNewString(tmp->name); + if (tmp->type == OPTV_STRING || tmp->type == OPTV_ANYSTR) + ptr->option[count].value.str = XtNewString(tmp->value.str); + } + } + else + ptr->option = NULL; + if (vendor != -1 && chips) { + ptr->vendor = vendor; + for (count = 0, ctmp = chips; ctmp->name; ctmp++, count++) + ; + ++count; + ptr->chipsets = XtCalloc(1, count * sizeof(SymTabRec)); + for (count = 0, ctmp = chips; ctmp->name != NULL; count++, ctmp++) { + memcpy(&ptr->chipsets[count], ctmp, sizeof(SymTabRec)); + ptr->chipsets[count].name = XtNewString(ctmp->name); + } + } + else + ptr->chipsets = NULL; + + ptr->next = module_options; + module_options = ptr; +} + +extern void xf86WrapperInit(void); + +void +xf86cfgLoaderInit(void) +{ + LoaderInit(); + xf86WrapperInit(); +} + +void +xf86cfgLoaderInitList(int type) +{ + static const char *generic[] = { + ".", + NULL + }; + static const char *video[] = { + "drivers", + NULL + }; + static const char *input[] = { + "input", + NULL + }; + static const char *font[] = { + "fonts", + NULL + }; + const char **subdirs; + + switch (type) { + case GenericModule: + subdirs = generic; + break; + case VideoModule: + subdirs = video; + break; + case InputModule: + subdirs = input; + break; + case FontRendererModule: + subdirs = font; + break; + default: + fprintf(stderr, "Invalid value passed to xf86cfgLoaderInitList.\n"); + subdirs = generic; + break; + } + LoaderSetPath(loaderPath); + loaderList = LoaderListDirs(subdirs, NULL); +} + +void +xf86cfgLoaderFreeList(void) +{ + LoaderFreeDirList(loaderList); +} + +int +xf86cfgCheckModule(void) +{ + int errmaj, errmin; + ModuleDescPtr module; + int nfonts; + FontModule *fonts, *pfont_module; + + driver = NULL; + chips = NULL; + info = NULL; + pfont_module = NULL; + vendor = -1; + module_type = GenericModule; + + if ((module = LoadModule(*ploaderList, NULL, NULL, NULL, NULL, + NULL, &errmaj, &errmin)) == NULL) { + LoaderErrorMsg(NULL, *ploaderList, errmaj, errmin); + return (0); + } + else if (driver && driver->AvailableOptions) { + /* at least fbdev does not call xf86MatchPciInstances in Probe */ + if (driver->Identify) + (*driver->Identify)(-1); + if (driver->Probe) + (*driver->Probe)(driver, PROBE_DETECT); + AddModuleOptions(*ploaderList, (*driver->AvailableOptions)(-1, -1)); + } + else if (info && info->AvailableOptions) + AddModuleOptions(*ploaderList, (*info->AvailableOptions)(NULL)); + + if (!noverify) { + XF86ModuleData *initdata = NULL; + char *p; + + p = XtMalloc(strlen(*ploaderList) + strlen("ModuleData") + 1); + strcpy(p, *ploaderList); + strcat(p, "ModuleData"); + initdata = LoaderSymbol(p); + if (initdata) { + XF86ModuleVersionInfo *vers; + + vers = initdata->vers; + if (vers && strcmp(*ploaderList, vers->modname)) { + /* This was a problem at some time for some video drivers */ + CheckMsg(CHECKER_FILE_MODULE_NAME_MISMATCH, + "WARNING file/module name mismatch: \"%s\" \"%s\"\n", + *ploaderList, vers->modname); + ++error_level; + } + } + XtFree(p); + } + + nfonts = numFontModules; + numFontModules = 0; + fonts = FontModuleList; + if (fonts) { + while (fonts->name) { + if (strcmp(fonts->name, *ploaderList) == 0) + pfont_module = fonts; + ++numFontModules; + ++fonts; + } + } + if (pfont_module) + module_type = FontRendererModule; + else if (nfonts + 1 <= numFontModules) { + /* loader.c will flag a warning if -noverify is not set */ + pfont_module = &FontModuleList[nfonts]; + module_type = FontRendererModule; + } + + if (font_module) { + XtFree((XtPointer)font_module->name); + XtFree((XtPointer)font_module); + font_module = NULL; + } + if (pfont_module) { + font_module = XtNew(FontModule); + memcpy(font_module, pfont_module, sizeof(FontModule)); + font_module->name = XtNewString(pfont_module->name); + } + + UnloadModule(module); + + return (1); +} + +void +xf86AddDriver(DriverPtr drv, void *module, int flags) +{ + driver = drv; + if (driver) + driver->module = module; + module_type = VideoModule; +} + +Bool +xf86ServerIsOnlyDetecting(void) +{ + return (True); +} + +void +xf86AddInputDriver(InputDriverPtr inp, void *module, int flags) +{ + module_type = InputModule; +} + +void +xf86AddModuleInfo(ModuleInfoPtr inf, void *module) +{ + info = inf; +} + +Bool +xf86LoaderCheckSymbol(const char *symbol) +{ + return LoaderSymbol(symbol) != NULL; +} + +void +xf86LoaderReqSymLists(const char **list0, ...) +{ +} + +#if 0 +void xf86Msg(int type, const char *format, ...) +{ +} +#endif + +/*ARGSUSED*/ +void +xf86PrintChipsets(const char *name, const char *msg, SymTabPtr chipsets) +{ + vendor = 0; + chips = chipsets; +} + +pciVideoPtr * +xf86GetPciVideoInfo(void) +{ + static pciVideoRec pci_video; + static pciVideoPtr pci_video_ptr[2] = { &pci_video }; + + memset(&pci_video, 0, sizeof(pciVideoRec)); + + return (pci_video_ptr); +} + +int +xf86MatchDevice(const char *name, GDevPtr **gdev) +{ + *gdev = NULL; + + return (1); +} + +int +xf86MatchPciInstances(const char *name, int VendorID, SymTabPtr chipsets, PciChipsets *PCIchipsets, + GDevPtr *devList, int numDevs, DriverPtr drvp, int **foundEntities) +{ + vendor = VendorID; + chips = chipsets; + *foundEntities = NULL; + + return (0); +} + +int +xf86MatchIsaInstances(const char *name, SymTabPtr chipsets, IsaChipsets *ISAchipsets, DriverPtr drvp, + FindIsaDevProc FindIsaDevice, GDevPtr *devList, int numDevs, int **foundEntities) +{ + *foundEntities = NULL; + + return (0); +} + +/*ARGSUSED*/ +void * +xf86LoadDrvSubModule(DriverPtr drv, const char *name) +{ + pointer ret; + int errmaj = 0, errmin = 0; + + ret = LoadSubModule(drv->module, name, NULL, NULL, NULL, NULL, + &errmaj, &errmin); + if (!ret) + LoaderErrorMsg(NULL, name, errmaj, errmin); + return (ret); +} + +void * +xf86GetPciConfigInfo(void) +{ + return (NULL); +} +#endif diff --git a/xc/programs/Xserver/hw/xwin/XWin.man b/xc/programs/Xserver/hw/xwin/XWin.man new file mode 100644 index 000000000..b48ae6ddc --- /dev/null +++ b/xc/programs/Xserver/hw/xwin/XWin.man @@ -0,0 +1,86 @@ +.\" $XFree86: xc/programs/Xserver/hw/xwin/XWin.man,v 1.2 2001/07/29 22:08:15 tsi Exp $ +.TH XWIN 1 __vendorversion__ +.SH NAME +XWin \- X Server for the Cygwin environment on Microsoft Windows +.SH SYNOPSIS +.B XWin +[ options ] ... +.SH DESCRIPTION +.I XWin +is an X Server for the X Window System on the Cygwin environment +running on Microsoft Windows. +.SH OPTIONS +.PP +In addition to the normal server options described in the \fIXserver(1)\fP +manual page, \fIXWin\fP accepts the following command line switches: +.TP 8 +.B "\-depth \fIdepth\fP" +Specify the color depth, in bits per pixel, to use when running in +fullscreen with a DirectDraw engine. This parameter is ignored if +\fB\-fullscreen\fP is not specified. +.TP 8 +.B "\-emulate3buttons \fItimeout\fP" +Emulate a three button mouse; pressing both buttons within +.I timeout +milliseconds causes an emulated middle button press. The default +.I timeout +is 50 milliseconds. +.TP 8 +.B "\-engine \fIengine_type_id\fP" +Override the server's automatically supported engine type. This +parameter will be ignored if the specified engine type is not +supported on the current system. The supported engine type ids are 1 +- Windows GDI, 2 - DirectDraw, and 4 - DirectDraw4. +.TP 8 +.B \-fullscreen +Run the server in fullscreen mode, as opposed to the default windowed +mode. +.TP 8 +.B "\-screen \fIscreen_number\fP \fIwidth\fP \fIheight\fP" +Sets the display resolution for the X server to use on screen +.I screen_number. +.SH "SEE ALSO" +.PP +X(__miscmansuffix__), Xserver(1), xdm(1), xinit(1) +.SH BUGS +.I XWin +and this man page still have many limitations. Some of the more obvious +ones are: +.br +- The display mode can not be changed once the X server has started. +.br +- Locking your Windows NT Workstation with Ctrl-Alt-Del while +.I XWin has the keyboard focus causes the keyboard to misbehave in +.I XWin until you press and release the Ctrl key and Alt key once. +.PP +.SH AUTHORS +XFree86 was originally ported to Cygwin by Dakshinamurthy Karra, +Dr. Peter Busch, John Fortin, and Suhaib Siddiqi. +.I XWin +is maintained by the Cygwin/XFree86 project, with hosting services +provided by RedHat. +.PP +The following members, in alphabetical order by last name, of the +Cygwin/XFree86 Team contributed to the XFree86 4.1.0 release: +.PP +Robert Collins - Lead website maintainer +.br +Christopher Faylor - Management of hosting services, general +programming guru +.br +Alexander Gottwald - AltGr handling for non-U.S. keyboards +.br +Alan Hourihane - Developer, patch reviewer, general programming guru +.br +Pierre A Humblet - Debugging of socket-related crashes, developer +.br +Harold L Hunt II - Lead developer, documentation, and minor website updates +.br +Suhaib Siddiqi - Project lead + + + + + + + diff --git a/xc/programs/Xserver/hw/xwin/wincutpaste.c b/xc/programs/Xserver/hw/xwin/wincutpaste.c new file mode 100644 index 000000000..3897dfa48 --- /dev/null +++ b/xc/programs/Xserver/hw/xwin/wincutpaste.c @@ -0,0 +1,53 @@ +/* $XFree86: xc/programs/Xserver/hw/xwin/wincutpaste.c,v 1.1 2001/06/25 08:12:33 alanh Exp $ */ +#include "win.h" +#define NEED_EVENTS +#include <X.h> +#include <Xproto.h> +#include "selection.h" +#include "input.h" +#include <Xatom.h> + +extern WindowPtr *WindowTable; /* Why isn't this in a header file? */ +extern Selection *CurrentSelections; +extern int NumCurrentSelections; + + +static Bool inSetXCutText = FALSE; + +void +winSetXCutText (char *str, int len) +{ + int i = 0; + + inSetXCutText = TRUE; + ChangeWindowProperty (WindowTable[0], XA_CUT_BUFFER0, XA_STRING, + 8, PropModeReplace, len, + (pointer)str, TRUE); + + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != XA_PRIMARY) + i++; + + if (i < NumCurrentSelections) { + xEvent event; + + if (CurrentSelections[i].client) { + event.u.u.type = SelectionClear; + event.u.selectionClear.time = GetTimeInMillis(); + event.u.selectionClear.window = CurrentSelections[i].window; + event.u.selectionClear.atom = CurrentSelections[i].selection; + (void) TryClientEvents (CurrentSelections[i].client, + &event, + 1, + NoEventMask, + NoEventMask, + NullGrab); + } + + CurrentSelections[i].window = None; + CurrentSelections[i].pWin = NULL; + CurrentSelections[i].client = NullClient; + } + + inSetXCutText = FALSE; +} diff --git a/xc/programs/Xserver/hw/xwin/winlayer.c b/xc/programs/Xserver/hw/xwin/winlayer.c new file mode 100644 index 000000000..ab15dcf6f --- /dev/null +++ b/xc/programs/Xserver/hw/xwin/winlayer.c @@ -0,0 +1,236 @@ +/* + *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: Harold L Hunt II + */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winlayer.c,v 1.6 2001/08/16 08:23:36 alanh Exp $ */ + +#include "win.h" + + +/* + * Create initial layer. Cygwin only needs one initial layer. + */ + +LayerPtr +winLayerCreate (ScreenPtr pScreen) +{ + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + PixmapPtr pPixmap = NULL; + DWORD dwLayerKind; + + ErrorF ("winLayerCreate () - dwDepth %d\n", + pScreenInfo->dwDepth); + + /* We only need a single layer kind: shadow */ + dwLayerKind = LAYER_SHADOW; + pPixmap = LAYER_SCREEN_PIXMAP; + + return LayerCreate (pScreen, + dwLayerKind, + pScreenInfo->dwDepth, + pPixmap, + pScreenPriv->pwinShadowUpdate, + NULL, /* No ShadowWindowProc */ + 0, /* Rotate */ + 0); +} + +#ifdef RANDR +/* + * Used as a function parameter to WalkTree. + */ + +int +winLayerAdd (WindowPtr pWindow, pointer value) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + LayerPtr pLayer = (LayerPtr) value; + + ErrorF ("winLayerAdd ()\n"); + + if (!LayerWindowAdd (pScreen, pLayer, pWindow)) + return WT_STOPWALKING; + + return WT_WALKCHILDREN; +} + + +/* + * Used as a function parameter to WalkTree. + */ + +int +winLayerRemove (WindowPtr pWindow, pointer value) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + LayerPtr pLayer = (LayerPtr) value; + + ErrorF ("winLayerRemove ()\n"); + + LayerWindowRemove (pScreen, pLayer, pWindow); + + return WT_WALKCHILDREN; +} + + +/* + * Answer queries about the RandR features supported. + */ + +Bool +winRandRGetInfo (ScreenPtr pScreen, Rotation *pRotations) +{ + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + int n; + RRVisualGroupPtr pVisualGroup; + RRGroupOfVisualGroupPtr pGroupOfVisualGroup = NULL; + Rotation rotateKind; + RRScreenSizePtr pSize; + + ErrorF ("winRandRGetInfo ()\n"); + + /* Don't support rotations, yet */ + *pRotations = RR_Rotate_0; /* | RR_Rotate_90 | RR_Rotate_180 | ... */ + + /* Check for something naughty. Don't know what exactly... */ + for (n = 0; n < pScreen->numDepths; n++) + if (pScreen->allowedDepths[n].numVids) + break; + if (n == pScreen->numDepths) + return FALSE; + + /* Create an RandR visual group */ + pVisualGroup = RRCreateVisualGroup (pScreen); + if (!pVisualGroup) + return FALSE; + + + /* Not sure what this does */ + if (!RRAddDepthToVisualGroup (pScreen, + pVisualGroup, + &pScreen->allowedDepths[n])) + { + RRDestroyVisualGroup (pScreen, pVisualGroup); + return FALSE; + } + + /* Register the RandR visual group */ + pVisualGroup = RRRegisterVisualGroup (pScreen, pVisualGroup); + if (!pVisualGroup) + return FALSE; + + pGroupOfVisualGroup = RRRegisterGroupOfVisualGroup (pScreen, + pGroupOfVisualGroup); + + /* You have to be kidding */ + if (!RRAddVisualGroupToGroupOfVisualGroup (pScreen, + pGroupOfVisualGroup, + pVisualGroup)) + { + RRDestroyGroupOfVisualGroup (pScreen, pGroupOfVisualGroup); + /* pVisualGroup left until screen closed */ + return FALSE; + } + + /* I can't afford a clue */ + pGroupOfVisualGroup = RRRegisterGroupOfVisualGroup (pScreen, + pGroupOfVisualGroup); + if (!pGroupOfVisualGroup) + return FALSE; + + /* + * Register supported sizes. This can be called many times, but + * we only support one size for now. + */ + pSize = RRRegisterSize (pScreen, + pScreenInfo->dwWidth, + pScreenInfo->dwHeight, + pScreenInfo->dwWidth_mm, + pScreenInfo->dwHeight_mm, + pGroupOfVisualGroup); + + /* Only one allowed rotation for now */ + rotateKind = RR_Rotate_0; + + /* Tell RandR what the current config is */ + RRSetCurrentConfig (pScreen, rotateKind, pSize, pVisualGroup); + + return TRUE; +} + + +/* + * Configure which RandR features are supported. + */ + +Bool +winRandRSetConfig (ScreenPtr pScreen, + Rotation rotateKind, + RRScreenSizePtr pSize, + RRVisualGroupPtr pVisualGroup) +{ + ErrorF ("winRandRSetConfig ()\n"); + + /* + * Apparently the only thing that can change is rotation. + * We don't support rotation, so that means nothing can change, right? + */ + + assert (rotateKind == RR_Rotate_0); + + return TRUE; +} + + +/* + * Initialize the RandR layer. + */ + +Bool +winRandRInit (ScreenPtr pScreen) +{ + rrScrPrivPtr pRRScrPriv; + + ErrorF ("winRandRInit ()\n"); + + if (!RRScreenInit (pScreen)) + { + ErrorF ("winRandRInit () - RRScreenInit () failed\n"); + return FALSE; + } + + /* Set some RandR function pointers */ + pRRScrPriv = rrGetScrPriv (pScreen); + pRRScrPriv->rrGetInfo = winRandRGetInfo; + pRRScrPriv->rrSetConfig = winRandRSetConfig; + + return TRUE; +} +#endif diff --git a/xc/programs/Xserver/hw/xwin/winnativegdi.c b/xc/programs/Xserver/hw/xwin/winnativegdi.c new file mode 100644 index 000000000..19ef4fbcf --- /dev/null +++ b/xc/programs/Xserver/hw/xwin/winnativegdi.c @@ -0,0 +1,387 @@ +/* + *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: Harold L Hunt II + */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winnativegdi.c,v 1.4 2001/07/31 18:45:25 tsi Exp $ */ + +#include "win.h" + +/* + * We wrap whatever CloseScreen procedure was specified by fb; + * a pointer to said procedure is stored in our privates. + */ +Bool +winCloseScreenNativeGDI (int nIndex, ScreenPtr pScreen) +{ + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; +#if 0 + Bool fReturn; +#endif + + ErrorF ("winCloseScreenNativeGDI () - Freeing screen resources\n"); + + /* Flag that the screen is closed */ + pScreenPriv->fClosed = TRUE; + pScreenPriv->fActive = FALSE; + +#if 0 + /* Call the wrapped CloseScreen procedure */ + pScreen->CloseScreen = pScreenPriv->CloseScreen; + + ErrorF ("winCloseScreenNativeGDI () - Calling miCloseScreen ()\n"); + + fReturn = (*pScreen->CloseScreen) (nIndex, pScreen); + + ErrorF ("winCloseScreenNativeGDI () - miCloseScreen () returned\n"); +#endif + + /* Delete the window property */ + RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP); + + /* Redisplay the Windows cursor */ + if (!pScreenPriv->fCursor) + ShowCursor (TRUE); + + /* Kill our window */ + if (pScreenPriv->hwndScreen) + { + DestroyWindow (pScreenPriv->hwndScreen); + pScreenPriv->hwndScreen = NULL; + } + + /* Delete our garbage bitmap */ + if (g_hbmpGarbage != NULL) + { + DeleteObject (g_hbmpGarbage); + g_hbmpGarbage = NULL; + } + + /* Invalidate our screeninfo's pointer to the screen */ + pScreenInfo->pScreen = NULL; + + /* Free the screen privates for this screen */ + xfree (pScreenPriv); + + ErrorF ("winCloseScreenNativeGDI () - Returning\n"); + + return TRUE; +} + +Bool +winInitVisualsNativeGDI (ScreenPtr pScreen) +{ + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + + /* Set the bitsPerRGB and bit masks */ + switch (pScreenInfo->dwDepth) + { + case 32: + case 24: + pScreenPriv->dwBitsPerRGB = 8; + pScreenPriv->dwRedMask = 0x00FF0000; + pScreenPriv->dwGreenMask = 0x0000FF00; + pScreenPriv->dwBlueMask = 0x000000FF; + break; + + case 16: + pScreenPriv->dwBitsPerRGB = 6; + pScreenPriv->dwRedMask = 0xF800; + pScreenPriv->dwGreenMask = 0x07E0; + pScreenPriv->dwBlueMask = 0x001F; + break; + + case 15: + pScreenPriv->dwBitsPerRGB = 5; + pScreenPriv->dwRedMask = 0x7C00; + pScreenPriv->dwGreenMask = 0x07E0; + pScreenPriv->dwBlueMask = 0x001F; + break; + + case 8: + pScreenPriv->dwBitsPerRGB = 8; + pScreenPriv->dwRedMask = 0; + pScreenPriv->dwGreenMask = 0; + pScreenPriv->dwBlueMask = 0; + break; + + default: + ErrorF ("winInitVisualsNativeGDI () - Unknown screen depth\n"); + return FALSE; + break; + } + + /* Tell the user how many bits per RGB we are using */ + ErrorF ("winInitVisualsNativeGDI () - Using dwBitsPerRGB: %d\n", + pScreenPriv->dwBitsPerRGB); + + /* Create a single visual according to the Windows screen depth */ + switch (pScreenInfo->dwDepth) + { + case 32: + case 24: + case 16: + case 15: + if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth, + TrueColorMask, + pScreenPriv->dwBitsPerRGB, + TrueColor, + pScreenPriv->dwRedMask, + pScreenPriv->dwGreenMask, + pScreenPriv->dwBlueMask)) + { + ErrorF ("winInitVisuals () - miSetVisualTypesAndMasks failed\n"); + return FALSE; + } + break; + + case 8: + ErrorF ("winInitVisuals () - Calling miSetVisualTypesAndMasks\n"); + if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth, + StaticColorMask, + pScreenPriv->dwBitsPerRGB, + StaticColor, + pScreenPriv->dwRedMask, + pScreenPriv->dwGreenMask, + pScreenPriv->dwBlueMask)) + { + ErrorF ("winInitVisuals () - miSetVisualTypesAndMasks failed\n"); + return FALSE; + } + break; + + default: + ErrorF ("winInitVisualsNativeGDI () - Unknown screen depth\n"); + return FALSE; + } + +#if 1 + ErrorF ("winInitVisualsNativeGDI () - Returning\n"); +#endif + + return TRUE; +} + +/* Adjust the video mode */ +Bool +winAdjustVideoModeNativeGDI (ScreenPtr pScreen) +{ + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + HDC hdc = NULL; + HDC hdcMem = NULL; + HBITMAP hbmp = NULL; + DWORD dwDepth; + + hdc = GetDC (NULL); + + /* We're in serious trouble if we can't get a DC */ + if (hdc == NULL) + { + ErrorF ("winAdjustVideoModeNativeGDI () - GetDC () failed\n"); + return FALSE; + } + + /* Set the garbage bitmap handle */ + if (g_hbmpGarbage == NULL) + { + g_hbmpGarbage = CreateCompatibleBitmap (hdc, 0, 0); + } + + /* Query GDI for current display depth */ + dwDepth = GetDeviceCaps (hdc, BITSPIXEL); + + /* GDI cannot change the screen depth */ + if (pScreenInfo->dwDepth == WIN_DEFAULT_DEPTH) + { + /* No -depth parameter passed, let the user know the depth being used */ + ErrorF ("winAdjustVideoModeNativeGDI () - Using Windows display " + "depth of %d bits per pixel\n", dwDepth); + + /* Use GDI's depth */ + pScreenInfo->dwDepth = dwDepth; + } + else if (dwDepth != pScreenInfo->dwDepth) + { + /* Warn user if GDI depth is different than -depth parameter */ + ErrorF ("winAdjustVideoModeNativeGDI () - Command line depth: %d, "\ + "using depth: %d\n", pScreenInfo->dwDepth, dwDepth); + + /* We'll use GDI's depth */ + pScreenInfo->dwDepth = dwDepth; + } + + /* Release our DC */ + ReleaseDC (NULL, hdc); + + return TRUE; +} + +Bool +winActivateAppNativeGDI (ScreenPtr pScreen) +{ + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + + /* + * Are we active? + * Are we fullscreen? + */ + if (pScreenPriv != NULL + && pScreenPriv->fActive + && pScreenInfo->fFullScreen) + { + /* + * Activating, attempt to bring our window + * to the top of the display + */ + ShowWindow (pScreenPriv->hwndScreen, SW_RESTORE); + } + + /* + * Are we inactive? + * Are we fullscreen? + */ + if (pScreenPriv != NULL + && !pScreenPriv->fActive + && pScreenInfo->fFullScreen) + { + /* + * Deactivating, stuff our window onto the + * task bar. + */ + ShowWindow (pScreenPriv->hwndScreen, SW_MINIMIZE); + } + + return TRUE; +} + +HBITMAP +winCreateDIBNativeGDI (int iWidth, int iHeight, int iDepth, + void **ppvBits) +{ + BITMAPINFOHEADER *pbmih = NULL; + HDC hdcMem = NULL; + HBITMAP hBitmap = NULL; + + /* Don't create an invalid bitmap */ + if (iWidth == 0 + || iHeight == 0 + || iDepth == 0) + { + ErrorF ("\nwinCreateDIBNativeGDI () - Invalid specs w %d h %d d %d\n\n", + iWidth, iHeight, iDepth); + return NULL; + } + + /* Create a scratch DC */ + hdcMem = CreateCompatibleDC (NULL); + if (hdcMem == NULL) + { + ErrorF ("winCreateDIBNativeGDI () - CreateCompatibleDC () failed\n"); + return NULL; + } + + /* Allocate bitmap info header */ + pbmih = (BITMAPINFOHEADER*) xalloc (sizeof (BITMAPINFOHEADER) + + 256 * sizeof (RGBQUAD)); + if (pbmih == NULL) + { + ErrorF ("winCreateDIBNativeGDI () - xalloc () failed\n"); + return FALSE; + } + ZeroMemory (pbmih, sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD)); + + /* Describe bitmap to be created */ + pbmih->biSize = sizeof (BITMAPINFOHEADER); + pbmih->biWidth = iWidth; + pbmih->biHeight = -iHeight; + pbmih->biPlanes = 1; + pbmih->biBitCount = iDepth; + pbmih->biCompression = BI_RGB; + pbmih->biSizeImage = 0; + pbmih->biXPelsPerMeter = 0; + pbmih->biYPelsPerMeter = 0; + pbmih->biClrUsed = 0; + pbmih->biClrImportant = 0; + + /* Create a DIB with a bit pointer */ + hBitmap = CreateDIBSection (hdcMem, + (BITMAPINFO *) pbmih, + DIB_RGB_COLORS, + ppvBits, + NULL, + 0); + if (hBitmap == NULL) + { + ErrorF ("winCreateDIBNativeGDI () - CreateDIBSection () failed\n"); + return NULL; + } + + /* Free the bitmap info header memory */ + xfree (pbmih); + pbmih = NULL; + +#if CYGDEBUG + ErrorF ("winCreateDIBNativeGDI () - CreateDIBSection () returned\n"); +#endif + + /* Free the scratch DC */ + DeleteDC (hdcMem); + hdcMem = NULL; + + return hBitmap; +} + +/* Set engine specific funtions */ +Bool +winSetEngineFunctionsNativeGDI (ScreenPtr pScreen) +{ + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + + /* Set our pointers */ + pScreenPriv->pwinAllocateFB + = (winAllocateFBProcPtr) (void (*)())NoopDDA; + pScreenPriv->pwinShadowUpdate + = (winShadowUpdateProcPtr) (void (*)())NoopDDA; + pScreenPriv->pwinCloseScreen = winCloseScreenNativeGDI; + pScreenPriv->pwinInitVisuals = winInitVisualsNativeGDI; + pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeNativeGDI; + if (pScreenInfo->fFullScreen) + pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen; + else + pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed; + pScreenPriv->pwinFinishScreenInit = winFinishScreenInitNativeGDI; + pScreenPriv->pwinBltExposedRegions + = (winBltExposedRegionsProcPtr) (void (*)())NoopDDA; + pScreenPriv->pwinActivateApp = winActivateAppNativeGDI; + + return TRUE; +} diff --git a/xc/programs/Xserver/miext/layer/Imakefile b/xc/programs/Xserver/miext/layer/Imakefile new file mode 100644 index 000000000..673f8fefc --- /dev/null +++ b/xc/programs/Xserver/miext/layer/Imakefile @@ -0,0 +1,44 @@ +XCOMM $XFree86: xc/programs/Xserver/miext/layer/Imakefile,v 1.1 2001/05/29 04:54:13 keithp Exp $ +XCOMM +XCOMM + +#define IHaveModules +#include <Server.tmpl> + +#ifdef XFree86Version +#if DoLoadableServer +XFMODSRC = shmodule.c +XFMODOBJ = shmodule.o +#endif +#endif + +SRCS = layergc.c \ + layerinit.c \ + layerpict.c \ + layerwin.c + +OBJS = layergc.o \ + layerinit.o \ + layerpict.o \ + layerwin.o + + INCLUDES = -I. -I../shadow -I../../mi -I../../fb -I../../include -I$(XINCLUDESRC) \ + -I$(FONTINCSRC) -I$(XF86SRC)/common $(EXTRAINCLUDES) \ + -I../../render -I$(EXTINCSRC) + LINTLIBS = ../../dix/llib-ldix.ln ../../os/llib-los.ln \ + ../../mi/llib-lmi.ln + +NormalLibraryObjectRule() +LibraryModuleTarget(layer,$(OBJS)) +LintLibraryTarget(layer,$(SRCS)) + +NormalLintTarget($(SRCS)) + +InstallLibraryModule(layer,$(MODULEDIR),.) + +#ifndef OS2Architecture +DependTarget() +#endif + +InstallDriverSDKLibraryModule(layer,$(DRIVERSDKMODULEDIR),.) +InstallDriverSDKNonExecFile(layer.h,$(DRIVERSDKINCLUDEDIR)) diff --git a/xc/programs/Xserver/miext/layer/layer.h b/xc/programs/Xserver/miext/layer/layer.h new file mode 100644 index 000000000..e8cfe442f --- /dev/null +++ b/xc/programs/Xserver/miext/layer/layer.h @@ -0,0 +1,145 @@ +/* + * $XFree86: xc/programs/Xserver/miext/layer/layer.h,v 1.4 2001/08/01 00:44:58 tsi Exp $ + * + * Copyright © 2001 Keith Packard, member of The XFree86 Project, 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 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. + */ + +#ifndef _LAYER_H_ +#define _LAYER_H_ + +#include <shadow.h> + +#define LAYER_FB 0 +#define LAYER_SHADOW 1 + +typedef struct _LayerKind *LayerKindPtr; +typedef struct _LayerWin *LayerWinPtr; +typedef struct _LayerList *LayerListPtr; +typedef struct _LayerGC *LayerGCPtr; +typedef struct _Layer *LayerPtr; +typedef struct _LayerScreen *LayerScreenPtr; + +/* + * We'll try to work without a list of windows in each layer + * for now, this will make computing bounding boxes for each + * layer rather expensive, so that may need to change at some point. + */ + +#define LAYER_SCREEN_PIXMAP ((PixmapPtr) 1) + +typedef struct _Layer { + LayerPtr pNext; /* a list of all layers for this screen */ + LayerKindPtr pKind; /* characteristics of this layer */ + int refcnt; /* reference count, layer is freed when zero */ + int windows; /* number of windows, free pixmap when zero */ + int depth; /* window depth in this layer */ + PixmapPtr pPixmap; /* pixmap for this layer (may be frame buffer) */ + Bool freePixmap; /* whether to free this pixmap when done */ + RegionRec region; /* valid set of pPixmap for drawing */ + ShadowUpdateProc update; /* for shadow layers, update/window/closure values */ + ShadowWindowProc window; + int rotate; + void *closure; +} LayerRec; + +/* + * Call this before wrapping stuff for acceleration, it + * gives layer pointers to the raw frame buffer functions + */ + +Bool +LayerStartInit (ScreenPtr pScreen); + +/* + * Initialize wrappers for each acceleration type and + * call this function, it will move the needed functions + * into a new LayerKind and replace them with the generic + * functions. + */ + +int +LayerNewKind (ScreenPtr pScreen); + +/* + * Finally, call this function and layer + * will wrap the screen functions and prepare for execution + */ + +Bool +LayerFinishInit (ScreenPtr pScreen); + +/* + * At any point after LayerStartInit, a new layer can be created. + */ +LayerPtr +LayerCreate (ScreenPtr pScreen, + int kind, + int depth, + PixmapPtr pPixmap, + ShadowUpdateProc update, + ShadowWindowProc window, + int rotate, + void *closure); + +/* + * Create a layer pixmap + */ +Bool +LayerCreatePixmap (ScreenPtr pScreen, LayerPtr pLayer); + +/* + * Change a layer pixmap + */ +void +LayerSetPixmap (ScreenPtr pScreen, LayerPtr pLayer, PixmapPtr pPixmap); + +/* + * Destroy a layer pixmap + */ +void +LayerDestroyPixmap (ScreenPtr pScreen, LayerPtr pLayer); + +/* + * Change a layer kind + */ +void +LayerSetKind (ScreenPtr pScreen, LayerPtr pLayer, int kind); + +/* + * Destroy a layer. The layer must not contain any windows. + */ +void +LayerDestroy (ScreenPtr pScreen, LayerPtr layer); + +/* + * Add a window to a layer + */ +Bool +LayerWindowAdd (ScreenPtr pScreen, LayerPtr pLayer, WindowPtr pWin); + +/* + * Remove a window from a layer + */ + +void +LayerWindowRemove (ScreenPtr pScreen, LayerPtr pLayer, WindowPtr pWin); + +#endif /* _LAYER_H_ */ diff --git a/xc/programs/Xserver/miext/layer/layergc.c b/xc/programs/Xserver/miext/layer/layergc.c new file mode 100644 index 000000000..64ceda1ad --- /dev/null +++ b/xc/programs/Xserver/miext/layer/layergc.c @@ -0,0 +1,192 @@ +/* + * $XFree86: xc/programs/Xserver/miext/layer/layergc.c,v 1.3 2001/06/05 01:11:07 keithp Exp $ + * + * Copyright © 2001 Keith Packard, member of The XFree86 Project, 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 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. + */ + +#include "layerstr.h" + +GCFuncs layerGCFuncs = { + layerValidateGC, layerChangeGC, layerCopyGC, layerDestroyGC, + layerChangeClip, layerDestroyClip, layerCopyClip +}; + +#if 0 +/* + * XXX dont need this until this supports + * separate clipping and multiple layers + */ +GCOps layerGCOps = { + layerFillSpans, layerSetSpans, + layerPutImage, layerCopyArea, + layerCopyPlane, layerPolyPoint, + layerPolylines, layerPolySegment, + layerPolyRectangle, layerPolyArc, + layerFillPolygon, layerPolyFillRect, + layerPolyFillArc, layerPolyText8, + layerPolyText16, layerImageText8, + layerImageText16, layerImageGlyphBlt, + layerPolyGlyphBlt, layerPushPixels, +#ifdef NEED_LINEHELPER + NULL, +#endif + {NULL} /* devPrivate */ +}; +#endif + +Bool +layerCreateGC (GCPtr pGC) +{ + Bool ret = TRUE; + int kind; + LayerKindPtr pLayKind; + LayerPtr pLayer; + ScreenPtr pScreen = pGC->pScreen; + layerScrPriv(pScreen); + layerGCPriv(pGC); + + /* + * XXX assume the first layer can handle all GCs + */ + pLayKind = &pLayScr->kinds[0]; + if (pLayScr->pLayers) + pLayKind = pLayScr->pLayers->pKind; + pLayGC->pKind = pLayKind; + LayerUnwrap (pScreen,pLayGC->pKind,CreateGC); + + if (!(*pScreen->CreateGC) (pGC)) + ret = FALSE; + LayerWrap (pScreen,pLayKind,CreateGC,layerCreateGC); + + LayerWrap (pGC,pLayGC,funcs,&layerGCFuncs); + + return ret; +} + +void +layerValidateGC(GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw) +{ + layerGCPriv(pGC); + LayerKindPtr pKind; + + if (pDraw->type == DRAWABLE_WINDOW) + { + layerWinPriv ((WindowPtr) pDraw); + pKind = layerWinLayer (pLayWin)->pKind; + } + else + { + /* XXX assume the first layer can handle all pixmaps */ + layerScrPriv (pDraw->pScreen); + pKind = &pLayScr->kinds[0]; + if (pLayScr->pLayers) + pKind = pLayScr->pLayers->pKind; + } + + LayerUnwrap (pGC,pLayGC,funcs); + if (pKind != pLayGC->pKind) + { + /* + * Clean up the previous user + */ + CreateGCProcPtr CreateGC; + (*pGC->funcs->DestroyGC) (pGC); + + pGC->serialNumber = GC_CHANGE_SERIAL_BIT; + + pLayGC->pKind = pKind; + + /* + * Temporarily unwrap Create GC and let + * the new code setup the GC + */ + CreateGC = pGC->pScreen->CreateGC; + LayerUnwrap (pGC->pScreen, pLayGC->pKind, CreateGC); + (*pGC->pScreen->CreateGC) (pGC); + LayerWrap (pGC->pScreen, pLayGC->pKind, CreateGC, CreateGC); + } + + (*pGC->funcs->ValidateGC) (pGC, changes, pDraw); + LayerWrap(pGC,pLayGC,funcs,&layerGCFuncs); +} + +void +layerDestroyGC(GCPtr pGC) +{ + layerGCPriv(pGC); + LayerUnwrap (pGC,pLayGC,funcs); + (*pGC->funcs->DestroyGC)(pGC); + LayerWrap(pGC,pLayGC,funcs,&layerGCFuncs); +} + +void +layerChangeGC (GCPtr pGC, + unsigned long mask) +{ + layerGCPriv(pGC); + LayerUnwrap (pGC,pLayGC,funcs); + (*pGC->funcs->ChangeGC) (pGC, mask); + LayerWrap(pGC,pLayGC,funcs,&layerGCFuncs); +} + +void +layerCopyGC (GCPtr pGCSrc, + unsigned long mask, + GCPtr pGCDst) +{ + layerGCPriv(pGCDst); + LayerUnwrap (pGCDst,pLayGC,funcs); + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + LayerWrap(pGCDst,pLayGC,funcs,&layerGCFuncs); +} + +void +layerChangeClip (GCPtr pGC, + int type, + pointer pvalue, + int nrects) +{ + layerGCPriv(pGC); + LayerUnwrap (pGC,pLayGC,funcs); + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + LayerWrap(pGC,pLayGC,funcs,&layerGCFuncs); +} + +void +layerCopyClip(GCPtr pGCDst, GCPtr pGCSrc) +{ + layerGCPriv(pGCDst); + LayerUnwrap (pGCDst,pLayGC,funcs); + (*pGCDst->funcs->CopyClip) (pGCSrc, pGCDst); + LayerWrap(pGCDst,pLayGC,funcs,&layerGCFuncs); +} + +void +layerDestroyClip(GCPtr pGC) +{ + layerGCPriv(pGC); + LayerUnwrap (pGC,pLayGC,funcs); + (*pGC->funcs->DestroyClip) (pGC); + LayerWrap(pGC,pLayGC,funcs,&layerGCFuncs); +} + diff --git a/xc/programs/Xserver/miext/layer/layerinit.c b/xc/programs/Xserver/miext/layer/layerinit.c new file mode 100644 index 000000000..a4e12a285 --- /dev/null +++ b/xc/programs/Xserver/miext/layer/layerinit.c @@ -0,0 +1,351 @@ +/* + * $XFree86: xc/programs/Xserver/miext/layer/layerinit.c,v 1.3 2001/07/20 19:25:01 keithp Exp $ + * + * Copyright © 2001 Keith Packard, member of The XFree86 Project, 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 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. + */ + +#include "layerstr.h" + +int layerScrPrivateIndex; +int layerGCPrivateIndex; +int layerWinPrivateIndex; +int layerGeneration; + +/* + * Call this before wrapping stuff for acceleration, it + * gives layer pointers to the raw frame buffer functions + */ + +extern const GCFuncs fbGCFuncs; +extern GCFuncs shadowGCFuncs; + +Bool +LayerStartInit (ScreenPtr pScreen) +{ + LayerScreenPtr pScrPriv; + + if (layerGeneration != serverGeneration) + { + layerScrPrivateIndex = AllocateScreenPrivateIndex (); + if (layerScrPrivateIndex == -1) + return FALSE; + layerGCPrivateIndex = AllocateGCPrivateIndex (); + if (layerGCPrivateIndex == -1) + return FALSE; + layerWinPrivateIndex = AllocateWindowPrivateIndex (); + if (layerWinPrivateIndex == -1) + return FALSE; + layerGeneration = serverGeneration; + } + if (!AllocateGCPrivate (pScreen, layerGCPrivateIndex, sizeof (LayerGCRec))) + return FALSE; + if (!AllocateWindowPrivate (pScreen, layerWinPrivateIndex, sizeof (LayerWinRec))) + return FALSE; + pScrPriv = (LayerScreenPtr) xalloc (sizeof (LayerScreenRec)); + if (!pScrPriv) + return FALSE; + pScrPriv->nkinds = 0; + pScrPriv->kinds = 0; + pScrPriv->pLayers = 0; + pScreen->devPrivates[layerScrPrivateIndex].ptr = (pointer) pScrPriv; + /* + * Add fb kind -- always 0 + */ + if (LayerNewKind (pScreen) < 0) + { + pScreen->devPrivates[layerScrPrivateIndex].ptr = 0; + xfree (pScrPriv); + return FALSE; + } + /* + * Add shadow kind -- always 1 + */ + if (!shadowSetup (pScreen)) + return FALSE; + if (LayerNewKind (pScreen) < 0) + { + pScreen->devPrivates[layerScrPrivateIndex].ptr = 0; + xfree (pScrPriv->kinds); + xfree (pScrPriv); + return FALSE; + } + return TRUE; +} + +/* + * Initialize wrappers for each acceleration type and + * call this function, it will move the needed functions + * into a new LayerKind and replace them with the generic + * functions. + */ + +int +LayerNewKind (ScreenPtr pScreen) +{ + layerScrPriv(pScreen); + LayerKindPtr pLayKind, pLayKinds; +#ifdef RENDER + PictureScreenPtr ps = GetPictureScreen (pScreen); +#endif + LayerPtr pLayer; + + /* + * Allocate a new kind structure + */ + if (pLayScr->kinds) + pLayKinds = (LayerKindPtr) xrealloc ((pointer) pLayScr->kinds, + (pLayScr->nkinds + 1) * sizeof (LayerKindRec)); + else + pLayKinds = (LayerKindPtr) xalloc (sizeof (LayerKindRec)); + if (!pLayKinds) + return -1; + + /* + * Fix up existing layers to point at the new kind + */ + for (pLayer = pLayScr->pLayers; pLayer; pLayer = pLayer->pNext) + { + int kind = pLayer->pKind - pLayScr->kinds; + + pLayer->pKind = &pLayKinds[kind]; + } + + pLayScr->kinds = pLayKinds; + pLayKind = &pLayScr->kinds[pLayScr->nkinds]; + pLayKind->kind = pLayScr->nkinds; + + /* + * Extract wrapped functions from screen and stick in kind + */ + pLayKind->CloseScreen = pScreen->CloseScreen; + + pLayKind->CreateWindow = pScreen->CreateWindow; + pLayKind->DestroyWindow = pScreen->DestroyWindow; + pLayKind->ChangeWindowAttributes = pScreen->ChangeWindowAttributes; + pLayKind->PaintWindowBackground = pScreen->PaintWindowBackground; + pLayKind->PaintWindowBorder = pScreen->PaintWindowBorder; + pLayKind->CopyWindow = pScreen->CopyWindow; + + pLayKind->CreateGC = pScreen->CreateGC; + +#ifdef RENDER + if (ps) + { + pLayKind->Composite = ps->Composite; + pLayKind->Glyphs = ps->Glyphs; + pLayKind->CompositeRects = ps->CompositeRects; + } +#endif + /* + * If not underlying frame buffer kind, + * replace screen functions with those + */ + if (pLayKind->kind != 0) + { + pScreen->CloseScreen = pLayKinds->CloseScreen; + + pScreen->CreateWindow = pLayKinds->CreateWindow; + pScreen->DestroyWindow = pLayKinds->DestroyWindow; + pScreen->ChangeWindowAttributes = pLayKinds->ChangeWindowAttributes; + pScreen->PaintWindowBackground = pLayKinds->PaintWindowBackground; + pScreen->PaintWindowBorder = pLayKinds->PaintWindowBorder; + pScreen->CopyWindow = pLayKinds->CopyWindow; + + pScreen->CreateGC = pLayKinds->CreateGC; + +#ifdef RENDER + if (ps) + { + ps->Composite = pLayKinds->Composite; + ps->Glyphs = pLayKinds->Glyphs; + ps->CompositeRects = pLayKinds->CompositeRects; + } +#endif + } + + pLayScr->nkinds++; + return pLayKind->kind; +} + +/* + * Finally, call this function and layer + * will wrap the screen functions and prepare for execution + */ + +Bool +LayerFinishInit (ScreenPtr pScreen) +{ + layerScrPriv(pScreen); +#ifdef RENDER + PictureScreenPtr ps = GetPictureScreen (pScreen); +#endif + + pScreen->CloseScreen = layerCloseScreen; + + pScreen->CreateWindow = layerCreateWindow; + pScreen->DestroyWindow = layerDestroyWindow; + pScreen->ChangeWindowAttributes = layerChangeWindowAttributes; + pScreen->PaintWindowBackground = layerPaintWindowBackground; + pScreen->PaintWindowBorder = layerPaintWindowBorder; + pScreen->CopyWindow = layerCopyWindow; + + pScreen->CreateGC = layerCreateGC; + +#ifdef RENDER + if (ps) + { + ps->Composite = layerComposite; + ps->Glyphs = layerGlyphs; + ps->CompositeRects = layerCompositeRects; + } +#endif + + return TRUE; +} + +/* + * At any point after LayerStartInit, a new layer can be created. + */ +LayerPtr +LayerCreate (ScreenPtr pScreen, + int kind, + int depth, + PixmapPtr pPixmap, + ShadowUpdateProc update, + ShadowWindowProc window, + int rotate, + void *closure) +{ + layerScrPriv(pScreen); + LayerPtr pLay, *pPrev; + LayerKindPtr pLayKind; + + if (kind < 0 || pLayScr->nkinds <= kind) + return 0; + pLayKind = &pLayScr->kinds[kind]; + pLay = (LayerPtr) xalloc (sizeof (LayerRec)); + if (!pLay) + return 0; + /* + * Initialize the layer + */ + pLay->pNext = 0; + pLay->pKind = pLayKind; + pLay->refcnt = 1; + pLay->windows = 0; + pLay->depth = depth; + pLay->pPixmap = pPixmap; + pLay->update = update; + pLay->window = window; + pLay->rotate = rotate; + pLay->closure = closure; + if (pPixmap == LAYER_SCREEN_PIXMAP) + pLay->freePixmap = FALSE; + else + { + pLay->freePixmap = TRUE; + if (pPixmap) + pPixmap->refcnt++; + } + REGION_INIT (pScreen, &pLay->region, NullBox, 0); + /* + * Hook the layer at the end of the list + */ + for (pPrev = &pLayScr->pLayers; *pPrev; pPrev = &(*pPrev)->pNext) + ; + *pPrev = pLay; + return pLay; +} + +/* + * Change a layer pixmap + */ +void +LayerSetPixmap (ScreenPtr pScreen, LayerPtr pLayer, PixmapPtr pPixmap) +{ + LayerDestroyPixmap (pScreen, pLayer); + pLayer->pPixmap = pPixmap; + if (pPixmap == LAYER_SCREEN_PIXMAP) + pLayer->freePixmap = FALSE; + else + { + if (pPixmap) + pPixmap->refcnt++; + pLayer->freePixmap = TRUE; + } +} + +/* + * Destroy a layer. The layer must not contain any windows. + */ +void +LayerDestroy (ScreenPtr pScreen, LayerPtr pLay) +{ + layerScrPriv(pScreen); + LayerPtr *pPrev; + + --pLay->refcnt; + if (pLay->refcnt > 0) + return; + /* + * Unhook the layer from the list + */ + for (pPrev = &pLayScr->pLayers; *pPrev; pPrev = &(*pPrev)->pNext) + if (*pPrev == pLay) + { + *pPrev = pLay->pNext; + break; + } + /* + * Free associated storage + */ + LayerDestroyPixmap (pScreen, pLay); + REGION_UNINIT (pScreen, &pLay->region); + xfree (pLay); +} + +/* + * CloseScreen wrapper + */ +Bool +layerCloseScreen (int index, ScreenPtr pScreen) +{ + layerScrPriv(pScreen); + int kind; + + /* XXX this is a mess -- fbCloseScreen can only be called once, + * and yet the intervening layers need to be called as well. + */ + kind = pLayScr->nkinds - 1; + pScreen->CloseScreen = pLayScr->kinds[kind].CloseScreen; + (*pScreen->CloseScreen) (index, pScreen); + + /* + * make sure the shadow layer is cleaned up as well + */ + if (kind != LAYER_SHADOW) + xfree (shadowGetScrPriv (pScreen)); + + xfree (pLayScr->kinds); + xfree (pLayScr); + pScreen->devPrivates[layerScrPrivateIndex].ptr = 0; + return TRUE; +} diff --git a/xc/programs/Xserver/miext/layer/layerpict.c b/xc/programs/Xserver/miext/layer/layerpict.c new file mode 100644 index 000000000..e233d0271 --- /dev/null +++ b/xc/programs/Xserver/miext/layer/layerpict.c @@ -0,0 +1,145 @@ +/* + * $XFree86: xc/programs/Xserver/miext/layer/layerpict.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2001 Keith Packard, member of The XFree86 Project, 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 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. + */ + +#include "layerstr.h" + +void +layerComposite (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + LayerPtr pLayer; + LayerWinLoopRec loop; + DrawablePtr pDstDrawable = pDst->pDrawable; + ScreenPtr pScreen = pDstDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen (pScreen); + + if (pDstDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWin = (WindowPtr) pDstDrawable; + for (pLayer = LayerWindowFirst (pWin, &loop); + pLayer; + pLayer = LayerWindowNext (pWin, &loop)) + { + LayerUnwrap (ps, pLayer->pKind, Composite); + (*ps->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc, + xMask, yMask, xDst, yDst, width, height); + LayerWrap (ps, pLayer->pKind, Composite, layerComposite); + } + LayerWindowDone (pWin, &loop); + } + else + { + layerScrPriv (pScreen); + LayerUnwrap (ps, &pLayScr->kinds[LAYER_FB], Composite); + (*ps->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc, + xMask, yMask, xDst, yDst, width, height); + LayerWrap (ps, &pLayScr->kinds[LAYER_FB], Composite, layerComposite); + } +} + +void +layerGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs) +{ + LayerPtr pLayer; + LayerWinLoopRec loop; + DrawablePtr pDstDrawable = pDst->pDrawable; + ScreenPtr pScreen = pDstDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen (pScreen); + + if (pDstDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWin = (WindowPtr) pDstDrawable; + for (pLayer = LayerWindowFirst (pWin, &loop); + pLayer; + pLayer = LayerWindowNext (pWin, &loop)) + { + LayerUnwrap (ps, pLayer->pKind, Glyphs); + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, + nlist, list, glyphs); + LayerWrap (ps, pLayer->pKind, Glyphs, layerGlyphs); + } + LayerWindowDone (pWin, &loop); + } + else + { + layerScrPriv (pScreen); + LayerUnwrap (ps, &pLayScr->kinds[LAYER_FB], Glyphs); + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, + nlist, list, glyphs); + LayerWrap (ps, &pLayScr->kinds[LAYER_FB], Glyphs, layerGlyphs); + } +} + +void +layerCompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects) +{ + LayerPtr pLayer; + LayerWinLoopRec loop; + DrawablePtr pDstDrawable = pDst->pDrawable; + ScreenPtr pScreen = pDstDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen (pScreen); + + if (pDstDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWin = (WindowPtr) pDstDrawable; + for (pLayer = LayerWindowFirst (pWin, &loop); + pLayer; + pLayer = LayerWindowNext (pWin, &loop)) + { + LayerUnwrap (ps, pLayer->pKind, CompositeRects); + (*ps->CompositeRects) (op, pDst, color, nRect, rects); + LayerWrap (ps, pLayer->pKind, CompositeRects, layerCompositeRects); + } + LayerWindowDone (pWin, &loop); + } + else + { + layerScrPriv (pScreen); + LayerUnwrap (ps, &pLayScr->kinds[LAYER_FB], CompositeRects); + (*ps->CompositeRects) (op, pDst, color, nRect, rects); + LayerWrap (ps, &pLayScr->kinds[LAYER_FB], CompositeRects, layerCompositeRects); + } +} diff --git a/xc/programs/Xserver/miext/layer/layerstr.h b/xc/programs/Xserver/miext/layer/layerstr.h new file mode 100644 index 000000000..81b8d9035 --- /dev/null +++ b/xc/programs/Xserver/miext/layer/layerstr.h @@ -0,0 +1,411 @@ +/* + * $XFree86: xc/programs/Xserver/miext/layer/layerstr.h,v 1.2 2001/06/04 09:45:41 keithp Exp $ + * + * Copyright © 2001 Keith Packard, member of The XFree86 Project, 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 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. + */ + +#ifndef _LAYERSTR_H_ +#define _LAYERSTR_H_ + +#include "X.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "font.h" +#include "dixfontstr.h" +#include "fontstruct.h" +#include "mi.h" +#include "regionstr.h" +#include "globals.h" +#include "gcstruct.h" +#include "layer.h" +#ifdef RENDER +#include "picturestr.h" +#endif + +extern int layerScrPrivateIndex; +extern int layerGCPrivateIndex; +extern int layerWinPrivateIndex; + +/* + * One of these for each possible set of underlying + * rendering code. The first kind always points at the + * underlying frame buffer code and is created in LayerStartInit + * so that LayerNewKind can unwrap the screen and prepare it + * for another wrapping sequence. + * + * The set of functions wrapped here must be at least the union + * of all functions wrapped by any rendering layer in use; they're + * easy to add, so don't be shy + */ + +typedef struct _LayerKind { + int kind; /* kind index */ + + CloseScreenProcPtr CloseScreen; + + CreateWindowProcPtr CreateWindow; + DestroyWindowProcPtr DestroyWindow; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + PaintWindowBackgroundProcPtr PaintWindowBackground; + PaintWindowBorderProcPtr PaintWindowBorder; + CopyWindowProcPtr CopyWindow; + + CreateGCProcPtr CreateGC; + + CompositeProcPtr Composite; + GlyphsProcPtr Glyphs; + CompositeRectsProcPtr CompositeRects; + +} LayerKindRec; + +#define LayerWrap(orig,lay,member,func) \ + (((lay)->member = (orig)->member),\ + ((orig)->member = (func))) +#define LayerUnwrap(orig,lay,member) \ + ((orig)->member = (lay)->member) + +/* + * This is the window private structure allocated for + * all windows. There are two possible alternatives here, + * either the window belongs to a single layer and uses its + * internal clip/borderClip lists or the window belongs to one + * or more layers and uses a separate clip/borderclip for each + * layer. When this is integrated into the core window struct, + * the LayerWinKind can become a single bit saving 8 bytes per + * window. + */ + +typedef struct _LayerWin { + Bool isList; + union { + LayerPtr pLayer; + LayerListPtr pLayList; + } u; +} LayerWinRec; + +typedef struct _LayerList { + LayerListPtr pNext; /* list of layers for this window */ + LayerPtr pLayer; /* the layer */ + Bool inheritClip; /* use the window clipList/borderClip */ + RegionRec clipList; /* per-layer clip/border clip lists */ + RegionRec borderClip; +} LayerListRec; + +#define layerGetWinPriv(pWin) ((LayerWinPtr) (pWin)->devPrivates[layerWinPrivateIndex].ptr) +#define layerWinPriv(pWin) LayerWinPtr pLayWin = layerGetWinPriv(pWin) + +#define layerWinLayer(pLayWin) ((pLayWin)->isList ? (pLayWin)->u.pLayList->pLayer : (pLayWin)->u.pLayer) + +typedef struct _LayerWinLoop { + LayerWinPtr pLayWin; + LayerListPtr pLayList; + PixmapPtr pPixmap; /* original window pixmap */ + RegionRec clipList; /* saved original clipList contents */ + RegionRec borderClip; /* saved original borderClip contents */ +} LayerWinLoopRec, *LayerWinLoopPtr; + +#define layerWinFirstLayer(pLayWin,pLayList) ((pLayWin)->isList ? ((pLayList) = (pLayWin)->u.pLayList)->pLayer : pLayWin->u.pLayer) +#define layerWinNextLayer(pLayWin,pLayList) ((pLayWin)->isList ? ((pLayList) = (pLayList)->pNext)->pLayer : 0) + +LayerPtr +LayerWindowFirst (WindowPtr pWin, LayerWinLoopPtr pLoop); + +LayerPtr +LayerWindowNext (WindowPtr pWin, LayerWinLoopPtr pLoop); + +void +LayerWindowDone (WindowPtr pWin, LayerWinLoopPtr pLoop); + + +/* + * This is the GC private structure allocated for all GCs. + * XXX this is really messed up; I'm not sure how to fix it yet + */ + +typedef struct _LayerGC { + GCFuncs *funcs; + LayerKindPtr pKind; +} LayerGCRec; + +#define layerGetGCPriv(pGC) ((LayerGCPtr) (pGC)->devPrivates[layerGCPrivateIndex].ptr) +#define layerGCPriv(pGC) LayerGCPtr pLayGC = layerGetGCPriv(pGC) + +/* + * This is the screen private, it contains + * the layer kinds and the layers themselves + */ +typedef struct _LayerScreen { + int nkinds; /* number of elements in kinds array */ + LayerKindPtr kinds; /* created kinds; reallocated when new ones added */ + LayerPtr pLayers; /* list of layers for this screen */ +} LayerScreenRec; + +#define layerGetScrPriv(pScreen) ((LayerScreenPtr) (pScreen)->devPrivates[layerScrPrivateIndex].ptr) +#define layerScrPriv(pScreen) LayerScreenPtr pLayScr = layerGetScrPriv(pScreen) + +Bool +layerCloseScreen (int index, ScreenPtr pScreen); + +Bool +layerCreateWindow (WindowPtr pWin); + +Bool +layerDestroyWindow (WindowPtr pWin); + +Bool +layerChangeWindowAttributes (WindowPtr pWin, unsigned long mask); + +void +layerPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what); + +void +layerPaintWindowBorder (WindowPtr pWin, RegionPtr pRegion, int what); + +void +layerCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc); + +Bool +layerCreateGC (GCPtr pGC); + +void +layerComposite (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); +void +layerGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs); + +void +layerCompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +void layerValidateGC(GCPtr, unsigned long, DrawablePtr); +void layerChangeGC(GCPtr, unsigned long); +void layerCopyGC(GCPtr, unsigned long, GCPtr); +void layerDestroyGC(GCPtr); +void layerChangeClip(GCPtr, int, pointer, int); +void layerDestroyClip(GCPtr); +void layerCopyClip(GCPtr, GCPtr); + +void +layerFillSpans(DrawablePtr pDraw, + GC *pGC, + int nInit, + DDXPointPtr pptInit, + int *pwidthInit, + int fSorted); + +void +layerSetSpans(DrawablePtr pDraw, + GCPtr pGC, + char *pcharsrc, + DDXPointPtr pptInit, + int *pwidthInit, + int nspans, + int fSorted); + +void +layerPutImage( + DrawablePtr pDraw, + GCPtr pGC, + int depth, + int x, int y, int w, int h, + int leftPad, + int format, + char *pImage +); + +RegionPtr +layerCopyArea( + DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty +); + +RegionPtr +layerCopyPlane( + DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty, + unsigned long bitPlane +); + +void +layerPolyPoint( + DrawablePtr pDraw, + GCPtr pGC, + int mode, + int npt, + xPoint *pptInit +); +void +layerPolylines( + DrawablePtr pDraw, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr pptInit +); + +void +layerPolySegment( + DrawablePtr pDraw, + GCPtr pGC, + int nseg, + xSegment *pSeg +); + +void +layerPolyRectangle( + DrawablePtr pDraw, + GCPtr pGC, + int nRects, + xRectangle *pRects +); + +void +layerPolyArc( + DrawablePtr pDraw, + GCPtr pGC, + int narcs, + xArc *parcs +); + +void +layerFillPolygon( + DrawablePtr pDraw, + GCPtr pGC, + int shape, + int mode, + int count, + DDXPointPtr pptInit +); + +void +layerPolyFillRect( + DrawablePtr pDraw, + GCPtr pGC, + int nRectsInit, + xRectangle *pRectsInit +); + +void +layerPolyFillArc( + DrawablePtr pDraw, + GCPtr pGC, + int narcs, + xArc *parcs +); + +int +layerPolyText8( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + char *chars +); + +int +layerPolyText16( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars +); + +void +layerImageText8( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + char *chars +); + +void +layerImageText16( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars +); + +void +layerImageGlyphBlt( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase +); + +void +layerPolyGlyphBlt( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase +); + +void +layerPushPixels( + GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDraw, + int dx, int dy, int xOrg, int yOrg +); + +#endif /* _LAYERSTR_H_ */ diff --git a/xc/programs/Xserver/miext/layer/layerwin.c b/xc/programs/Xserver/miext/layer/layerwin.c new file mode 100644 index 000000000..1b19ba99a --- /dev/null +++ b/xc/programs/Xserver/miext/layer/layerwin.c @@ -0,0 +1,443 @@ +/* + * $XFree86: xc/programs/Xserver/miext/layer/layerwin.c,v 1.4 2001/07/20 19:25:01 keithp Exp $ + * + * Copyright © 2001 Keith Packard, member of The XFree86 Project, 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 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. + */ + +#include "layerstr.h" + +static LayerListPtr +NewLayerList (ScreenPtr pScreen, LayerPtr pLayer) +{ + LayerListPtr pLayList; + + pLayList = (LayerListPtr) xalloc (sizeof (LayerListRec)); + if (!pLayList) + return 0; + pLayList->pNext = 0; + pLayList->pLayer = pLayer; + pLayList->inheritClip = TRUE; + REGION_INIT (pScreen, &pLayList->clipList, NullBox, 0); + REGION_INIT (pScreen, &pLayList->borderClip, NullBox, 0); + return pLayList; +} + +static void +FreeLayerList (ScreenPtr pScreen, LayerListPtr pLayList) +{ + REGION_UNINIT (&pScreen, &pLayList->clipList); + REGION_UNINIT (&pScreen, &pLayList->borderClip); + xfree (pLayList); +} + +/* + * Create pixmap for a layer + */ + +Bool +LayerCreatePixmap (ScreenPtr pScreen, LayerPtr pLayer) +{ + /* XXX create full-screen sized layers all around */ + pLayer->pPixmap = (*pScreen->CreatePixmap) (pScreen, pScreen->width, + pScreen->height, pLayer->depth); + if (!pLayer->pPixmap) + return FALSE; + if (pLayer->pKind->kind == LAYER_SHADOW) + { + if (!shadowAdd (pScreen, pLayer->pPixmap, pLayer->update, + pLayer->window, pLayer->rotate, pLayer->closure)) + return FALSE; + } + return TRUE; +} + +/* + * Destroy pixmap for a layer + */ + +void +LayerDestroyPixmap (ScreenPtr pScreen, LayerPtr pLayer) +{ + if (pLayer->pPixmap) + { + if (pLayer->pKind->kind == LAYER_SHADOW) + shadowRemove (pScreen, pLayer->pPixmap); + if (pLayer->freePixmap) + (*pScreen->DestroyPixmap) (pLayer->pPixmap); + } + pLayer->pPixmap = 0; +} + +/* + * Add a window to a layer + */ +Bool +LayerWindowAdd (ScreenPtr pScreen, LayerPtr pLayer, WindowPtr pWin) +{ + layerWinPriv(pWin); + + if (pLayer->pPixmap == LAYER_SCREEN_PIXMAP) + pLayer->pPixmap = (*pScreen->GetScreenPixmap) (pScreen); + else if (!pLayer->pPixmap && !LayerCreatePixmap (pScreen, pLayer)) + return FALSE; + /* + * Add a new layer list if needed + */ + if (pLayWin->isList || pLayWin->u.pLayer) + { + LayerListPtr pPrev; + LayerListPtr pLayList; + + if (!pLayWin->isList) + { + pPrev = NewLayerList (pScreen, pLayWin->u.pLayer); + if (!pPrev) + return FALSE; + } + else + { + for (pPrev = pLayWin->u.pLayList; pPrev->pNext; pPrev = pPrev->pNext) + ; + } + pLayList = NewLayerList (pScreen, pLayer); + if (!pLayList) + { + if (!pLayWin->isList) + FreeLayerList (pScreen, pPrev); + return FALSE; + } + pPrev->pNext = pLayList; + if (!pLayWin->isList) + { + pLayWin->isList = TRUE; + pLayWin->u.pLayList = pPrev; + } + } + else + pLayWin->u.pLayer = pLayer; + /* + * XXX only one layer supported for drawing, last one wins + */ + (*pScreen->SetWindowPixmap) (pWin, pLayer->pPixmap); + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pLayer->refcnt++; + pLayer->windows++; + return TRUE; +} + +/* + * Remove a window from a layer + */ + +void +LayerWindowRemove (ScreenPtr pScreen, LayerPtr pLayer, WindowPtr pWin) +{ + layerWinPriv(pWin); + + if (pLayWin->isList) + { + LayerListPtr *pPrev; + LayerListPtr pLayList; + + for (pPrev = &pLayWin->u.pLayList; pLayList = *pPrev; pPrev = &pLayList->pNext) + { + if (pLayList->pLayer == pLayer) + { + *pPrev = pLayList->pNext; + FreeLayerList (pScreen, pLayList); + --pLayer->windows; + if (pLayer->windows <= 0) + LayerDestroyPixmap (pScreen, pLayer); + LayerDestroy (pScreen, pLayer); + break; + } + } + pLayList = pLayWin->u.pLayList; + if (!pLayList) + { + /* + * List is empty, set isList back to false + */ + pLayWin->isList = FALSE; + pLayWin->u.pLayer = 0; + } + else if (!pLayList->pNext && pLayList->inheritClip) + { + /* + * List contains a single element using the + * window clip, free the list structure and + * host the layer back to the window private + */ + pLayer = pLayList->pLayer; + FreeLayerList (pScreen, pLayList); + pLayWin->isList = FALSE; + pLayWin->u.pLayer = pLayer; + } + } + else + { + if (pLayWin->u.pLayer == pLayer) + { + --pLayer->windows; + if (pLayer->windows <= 0) + LayerDestroyPixmap (pScreen, pLayer); + LayerDestroy (pScreen, pLayer); + pLayWin->u.pLayer = 0; + } + } + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; +} + +/* + * Looping primitives for window layering. Usage: + * + * for (pLayer = LayerWindowFirst (pWin, &loop); + * pLayer; + * pLayer = LayerWindowNext (&loop)) + * { + * ... + * } + * LayerWindowDone (pWin, &loop); + */ + +LayerPtr +LayerWindowFirst (WindowPtr pWin, LayerWinLoopPtr pLoop) +{ + layerWinPriv (pWin); + LayerListPtr pLayList; + LayerPtr pLayer; + + pLoop->pLayWin = pLayWin; + if (!pLayWin->isList) + return pLayWin->u.pLayer; + + /* + * Preserve original state + */ + pLoop->clipList = pWin->clipList; + pLoop->borderClip = pWin->borderClip; + pLoop->pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin); + + /* + * Set initial list element + */ + pLoop->pLayList = pLayWin->u.pLayList; + + /* + * Return first layer + */ + return LayerWindowNext (pWin, pLoop); +} + +LayerPtr +LayerWindowNext (WindowPtr pWin, LayerWinLoopPtr pLoop) +{ + LayerPtr pLayer; + LayerWinPtr pLayWin = pLoop->pLayWin; + LayerListPtr pLayList; + + if (!pLayWin->isList) + return 0; + + pLayList = pLoop->pLayList; + pLayer = pLayList->pLayer; + /* + * Configure window for this layer + */ + (*pWin->drawable.pScreen->SetWindowPixmap) (pWin, pLayer->pPixmap); + if (!pLayList->inheritClip) + { + pWin->clipList = pLayList->clipList; + pWin->borderClip = pLayList->borderClip; + } + /* + * Step to next layer list + */ + pLoop->pLayList = pLayList->pNext; + /* + * Return layer + */ + return pLayer; +} + +void +LayerWindowDone (WindowPtr pWin, LayerWinLoopPtr pLoop) +{ + LayerWinPtr pLayWin = pLoop->pLayWin; + + if (!pLayWin->isList) + return; + /* + * clean up after the loop + */ + pWin->clipList = pLoop->clipList; + pWin->borderClip = pLoop->clipList; + (*pWin->drawable.pScreen->SetWindowPixmap) (pWin, pLoop->pPixmap); +} + +Bool +layerCreateWindow (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + layerWinPriv(pWin); + layerScrPriv(pScreen); + LayerPtr pLayer; + Bool ret; + + pLayWin->isList = FALSE; + pLayWin->u.pLayer = 0; + + /* + * input only windows don't live in any layer + */ + if (pWin->drawable.type == UNDRAWABLE_WINDOW) + return TRUE; + /* + * Use a reasonable default layer -- the first + * layer matching the windows depth. Subsystems needing + * alternative layering semantics can override this by + * replacing this function. Perhaps a new screen function + * could be used to select the correct initial window + * layer instead. + */ + for (pLayer = pLayScr->pLayers; pLayer; pLayer = pLayer->pNext) + if (pLayer->depth == pWin->drawable.depth) + break; + ret = TRUE; + if (pLayer) + { + pScreen->CreateWindow = pLayer->pKind->CreateWindow; + ret = (*pScreen->CreateWindow) (pWin); + pLayer->pKind->CreateWindow = pScreen->CreateWindow; + pScreen->CreateWindow = layerCreateWindow; + LayerWindowAdd (pScreen, pLayer, pWin); + } + return ret; +} + +Bool +layerDestroyWindow (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + layerWinPriv(pWin); + LayerPtr pLayer; + Bool ret = TRUE; + + while (pLayer = layerWinLayer (pLayWin)) + { + LayerUnwrap (pScreen, pLayer->pKind, DestroyWindow); + ret = (*pScreen->DestroyWindow) (pWin); + LayerWrap (pScreen, pLayer->pKind, DestroyWindow, layerDestroyWindow); + LayerWindowRemove (pWin->drawable.pScreen, pLayer, pWin); + } + return ret; +} + +Bool +layerChangeWindowAttributes (WindowPtr pWin, unsigned long mask) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + layerWinPriv (pWin); + LayerPtr pLay; + LayerWinLoopRec loop; + Bool ret = TRUE; + + for (pLay = LayerWindowFirst (pWin, &loop); + pLay; + pLay = LayerWindowNext (pWin, &loop)) + { + LayerUnwrap(pScreen,pLay->pKind,ChangeWindowAttributes); + if (!(*pScreen->ChangeWindowAttributes) (pWin, mask)) + ret = FALSE; + LayerWrap(pScreen,pLay->pKind,ChangeWindowAttributes,layerChangeWindowAttributes); + } + LayerWindowDone (pWin, &loop); + return ret; +} + +void +layerPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what) +{ + layerWinPriv (pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + LayerPtr pLay; + LayerWinLoopRec loop; + + for (pLay = LayerWindowFirst (pWin, &loop); + pLay; + pLay = LayerWindowNext (pWin, &loop)) + { + LayerUnwrap(pScreen,pLay->pKind,PaintWindowBackground); + (*pScreen->PaintWindowBackground) (pWin, pRegion, what); + LayerWrap(pScreen,pLay->pKind,PaintWindowBackground,layerPaintWindowBackground); + } + LayerWindowDone (pWin, &loop); +} + +void +layerPaintWindowBorder (WindowPtr pWin, RegionPtr pRegion, int what) +{ + layerWinPriv (pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + LayerPtr pLay; + LayerWinLoopRec loop; + + for (pLay = LayerWindowFirst (pWin, &loop); + pLay; + pLay = LayerWindowNext (pWin, &loop)) + { + LayerUnwrap(pScreen,pLay->pKind,PaintWindowBorder); + (*pScreen->PaintWindowBorder) (pWin, pRegion, what); + LayerWrap(pScreen,pLay->pKind,PaintWindowBorder,layerPaintWindowBorder); + } + LayerWindowDone (pWin, &loop); +} + +void +layerCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + layerWinPriv (pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + LayerPtr pLay; + LayerWinLoopRec loop; + int dx = 0, dy = 0; + + for (pLay = LayerWindowFirst (pWin, &loop); + pLay; + pLay = LayerWindowNext (pWin, &loop)) + { + LayerUnwrap(pScreen,pLay->pKind,CopyWindow); + /* + * Undo the translation done within the last CopyWindow proc (sigh) + */ + if (dx || dy) + REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, dx, dy); + (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); + LayerWrap(pScreen,pLay->pKind,CopyWindow,layerCopyWindow); + /* + * Save offset to undo translation next time around + */ + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + } + LayerWindowDone (pWin, &loop); +} + diff --git a/xc/programs/Xserver/miext/shadow/shrot16pack_180.c b/xc/programs/Xserver/miext/shadow/shrot16pack_180.c new file mode 100644 index 000000000..7ba41833e --- /dev/null +++ b/xc/programs/Xserver/miext/shadow/shrot16pack_180.c @@ -0,0 +1,29 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot16pack_180.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2000 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. + */ + +#define FUNC shadowUpdateRotate16_180 +#define Data CARD16 +#define ROTATE 180 + +#include "shrotpack.h" diff --git a/xc/programs/Xserver/miext/shadow/shrot16pack_270.c b/xc/programs/Xserver/miext/shadow/shrot16pack_270.c new file mode 100644 index 000000000..0b3c4e0ac --- /dev/null +++ b/xc/programs/Xserver/miext/shadow/shrot16pack_270.c @@ -0,0 +1,29 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot16pack_270.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2000 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. + */ + +#define FUNC shadowUpdateRotate16_270 +#define Data CARD16 +#define ROTATE 270 + +#include "shrotpack.h" diff --git a/xc/programs/Xserver/miext/shadow/shrot16pack_90.c b/xc/programs/Xserver/miext/shadow/shrot16pack_90.c new file mode 100644 index 000000000..574b3a157 --- /dev/null +++ b/xc/programs/Xserver/miext/shadow/shrot16pack_90.c @@ -0,0 +1,29 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot16pack_90.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2000 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. + */ + +#define FUNC shadowUpdateRotate16_90 +#define Data CARD16 +#define ROTATE 90 + +#include "shrotpack.h" diff --git a/xc/programs/Xserver/miext/shadow/shrot32pack_180.c b/xc/programs/Xserver/miext/shadow/shrot32pack_180.c new file mode 100644 index 000000000..838622267 --- /dev/null +++ b/xc/programs/Xserver/miext/shadow/shrot32pack_180.c @@ -0,0 +1,29 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot32pack_180.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2000 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. + */ + +#define FUNC shadowUpdateRotate32_180 +#define Data CARD32 +#define ROTATE 180 + +#include "shrotpack.h" diff --git a/xc/programs/Xserver/miext/shadow/shrot32pack_270.c b/xc/programs/Xserver/miext/shadow/shrot32pack_270.c new file mode 100644 index 000000000..b0dd28316 --- /dev/null +++ b/xc/programs/Xserver/miext/shadow/shrot32pack_270.c @@ -0,0 +1,29 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot32pack_270.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2000 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. + */ + +#define FUNC shadowUpdateRotate32_270 +#define Data CARD32 +#define ROTATE 270 + +#include "shrotpack.h" diff --git a/xc/programs/Xserver/miext/shadow/shrot32pack_90.c b/xc/programs/Xserver/miext/shadow/shrot32pack_90.c new file mode 100644 index 000000000..9bdb18e25 --- /dev/null +++ b/xc/programs/Xserver/miext/shadow/shrot32pack_90.c @@ -0,0 +1,29 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot32pack_90.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2000 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. + */ + +#define FUNC shadowUpdateRotate32_90 +#define Data CARD32 +#define ROTATE 90 + +#include "shrotpack.h" diff --git a/xc/programs/Xserver/miext/shadow/shrot8pack_180.c b/xc/programs/Xserver/miext/shadow/shrot8pack_180.c new file mode 100644 index 000000000..316c0c690 --- /dev/null +++ b/xc/programs/Xserver/miext/shadow/shrot8pack_180.c @@ -0,0 +1,29 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot8pack_180.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2000 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. + */ + +#define FUNC shadowUpdateRotate8_180 +#define Data CARD8 +#define ROTATE 180 + +#include "shrotpack.h" diff --git a/xc/programs/Xserver/miext/shadow/shrot8pack_270.c b/xc/programs/Xserver/miext/shadow/shrot8pack_270.c new file mode 100644 index 000000000..bed542f6d --- /dev/null +++ b/xc/programs/Xserver/miext/shadow/shrot8pack_270.c @@ -0,0 +1,29 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot8pack_270.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2000 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. + */ + +#define FUNC shadowUpdateRotate8_270 +#define Data CARD8 +#define ROTATE 270 + +#include "shrotpack.h" diff --git a/xc/programs/Xserver/miext/shadow/shrot8pack_90.c b/xc/programs/Xserver/miext/shadow/shrot8pack_90.c new file mode 100644 index 000000000..f2618fc47 --- /dev/null +++ b/xc/programs/Xserver/miext/shadow/shrot8pack_90.c @@ -0,0 +1,29 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot8pack_90.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2000 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. + */ + +#define FUNC shadowUpdateRotate8_90 +#define Data CARD8 +#define ROTATE 90 + +#include "shrotpack.h" diff --git a/xc/programs/Xserver/miext/shadow/shrotate.c b/xc/programs/Xserver/miext/shadow/shrotate.c new file mode 100644 index 000000000..9f631bd1d --- /dev/null +++ b/xc/programs/Xserver/miext/shadow/shrotate.c @@ -0,0 +1,243 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrotate.c,v 1.3 2001/07/21 04:13:26 keithp Exp $ + * + * Copyright © 2001 Keith Packard, member of The XFree86 Project, 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 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. + */ + +#include "X.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "font.h" +#include "dixfontstr.h" +#include "fontstruct.h" +#include "mi.h" +#include "regionstr.h" +#include "globals.h" +#include "gcstruct.h" +#include "shadow.h" +#include "fb.h" + +void +shadowUpdateRotatePacked (ScreenPtr pScreen, + shadowBufPtr pBuf) +{ + RegionPtr damage = &pBuf->damage; + PixmapPtr pShadow = pBuf->pPixmap; + int nbox = REGION_NUM_RECTS (damage); + BoxPtr pbox = REGION_RECTS (damage); + FbBits *shaBits; + FbStride shaStride; + int shaBpp; + int shaXoff, shaYoff; + int box_x1, box_x2, box_y1, box_y2; + int sha_x1, sha_y1; + int scr_x1, scr_x2, scr_y1, scr_y2, scr_w, scr_h; + int scr_x, scr_y; + int w; + int pixelsPerBits; + int pixelsMask; + FbStride shaStepOverY, shaStepDownY, shaStepOverX, shaStepDownX; + FbBits *shaLine, *sha; + int shaHeight = pShadow->drawable.height; + int shaWidth = pShadow->drawable.width; + FbBits shaMask; + int shaFirstShift, shaShift; + + fbGetDrawable (&pShadow->drawable, shaBits, shaStride, shaBpp, shaXoff, shaYoff); + pixelsPerBits = (sizeof (FbBits) * 8) / shaBpp; + pixelsMask = ~(pixelsPerBits - 1); + shaMask = FbBitsMask (FB_UNIT-shaBpp, shaBpp); + /* + * Compute rotation related constants to walk the shadow + */ + switch (pBuf->rotate) { + case 0: + default: + shaStepOverX = shaBpp; + shaStepDownX = 0; + shaStepOverY = 0; + shaStepDownY = shaStride; + break; + case 90: + shaStepOverX = 0; + shaStepDownX = -shaBpp; + shaStepOverY = shaStride; + shaStepDownY = 0; + break; + case 180: + shaStepOverX = -shaBpp; + shaStepDownX = 0; + shaStepOverY = 0; + shaStepDownY = -shaStride; + break; + case 270: + shaStepOverX = 0; + shaStepDownX = shaBpp; + shaStepOverY = -shaStride; + shaStepDownY = 0; + break; + } + while (nbox--) + { + box_x1 = pbox->x1; + box_y1 = pbox->y1; + box_x2 = pbox->x2; + box_y2 = pbox->y2; + pbox++; + + /* + * Compute screen and shadow locations for this box + */ + switch (pBuf->rotate) { + case 0: + default: + scr_x1 = box_x1 & pixelsMask; + scr_x2 = (box_x2 + pixelsPerBits - 1) & pixelsMask; + scr_y1 = box_y1; + scr_y2 = box_y2; + + sha_x1 = box_x1; + sha_y1 = box_y1; + break; + case 90: + scr_x1 = box_y1 & pixelsMask; + scr_x2 = (box_y2 + pixelsPerBits - 1) & pixelsMask; + scr_y1 = (shaWidth - box_x2); + scr_y2 = (shaWidth - box_x1); + + sha_x1 = box_x2 - 1; + sha_y1 = scr_x1; + break; + case 180: + scr_x1 = (shaWidth - box_x2) & pixelsMask; + scr_x2 = (shaWidth - box_x1 + pixelsPerBits - 1) & pixelsMask; + scr_y1 = shaHeight - box_y2; + scr_y2 = shaHeight - box_y1; + + sha_x1 = (shaWidth - scr_x1 - 1); + sha_y1 = box_y2 - 1; + break; + case 270: + scr_x1 = (shaHeight - box_y2) & pixelsMask; + scr_x2 = (shaHeight - box_y1 + pixelsPerBits - 1) & pixelsMask; + scr_y1 = box_x1; + scr_y2 = box_x2; + + sha_x1 = box_x1; + sha_y1 = (shaHeight - scr_x1 - 1); + break; + } + scr_w = ((scr_x2 - scr_x1) * shaBpp) >> FB_SHIFT; + scr_h = scr_y2 - scr_y1; + scr_y = scr_y1; + + /* shift amount for first pixel on screen */ + shaFirstShift = FB_UNIT - ((sha_x1 * shaBpp) & FB_MASK) - shaBpp; + + /* pointer to shadow data first placed on screen */ + shaLine = (shaBits + + sha_y1 * shaStride + + ((sha_x1 * shaBpp) >> FB_SHIFT)); + + /* + * Copy the bits, always write across the physical frame buffer + * to take advantage of write combining. + */ + while (scr_h--) + { + int p; + FbBits bits; + FbBits *win; + int i; + CARD32 winSize; + + sha = shaLine; + shaShift = shaFirstShift; + w = scr_w; + scr_x = scr_x1 * shaBpp >> FB_SHIFT; + + while (w) + { + /* + * Map some of this line + */ + win = (FbBits *) (*pBuf->window) (pScreen, + scr_y, + scr_x << 2, + SHADOW_WINDOW_WRITE, + &winSize, + pBuf->closure); + i = (winSize >> 2); + if (i > w) + i = w; + w -= i; + scr_x += i; + /* + * Copy the portion of the line mapped + */ + while (i--) + { + bits = 0; + p = pixelsPerBits; + /* + * Build one word of output from multiple inputs + * + * Note that for 90/270 rotations, this will walk + * down the shadow hitting each scanline once. + * This is probably not very efficient. + */ + while (p--) + { + bits = FbScrLeft(bits, shaBpp); + bits |= FbScrRight (*sha, shaShift) & shaMask; + + shaShift -= shaStepOverX; + if (shaShift >= FB_UNIT) + { + shaShift -= FB_UNIT; + sha--; + } + else if (shaShift < 0) + { + shaShift += FB_UNIT; + sha++; + } + sha += shaStepOverY; + } + *win++ = bits; + } + } + scr_y++; + shaFirstShift -= shaStepDownX; + if (shaFirstShift >= FB_UNIT) + { + shaFirstShift -= FB_UNIT; + shaLine--; + } + else if (shaFirstShift < 0) + { + shaFirstShift += FB_UNIT; + shaLine++; + } + shaLine += shaStepDownY; + } + } +} diff --git a/xc/programs/Xserver/render/miindex.c b/xc/programs/Xserver/render/miindex.c new file mode 100644 index 000000000..eb52ac746 --- /dev/null +++ b/xc/programs/Xserver/render/miindex.c @@ -0,0 +1,252 @@ +/* + * $XFree86: xc/programs/Xserver/render/miindex.c,v 1.4 2001/07/31 21:06:56 alanh Exp $ + * + * Copyright © 2001 Keith Packard, member of The XFree86 Project, 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 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. + */ + +#ifndef _MIINDEX_H_ +#define _MIINDEX_H_ + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" +#include "colormapst.h" + +Bool +miBuildRenderColormap (ColormapPtr pColormap, + int num, + Pixel *first, + Pixel *last) +{ + int cube, ramp; + int r, g, b; + unsigned short red, green, blue; + Pixel pix; + + cube = 0; + if ((pColormap->pVisual->class | DynamicClass) == PseudoColor) + { + for (cube = 0; cube * cube * cube < num; cube++) + ; + cube--; + } + if (cube == 1) + cube = 0; + ramp = num - (cube * cube * cube); + *first = MI_MAX_INDEXED; + *last = 0; + for (r = 0; r < cube; r++) + for (g = 0; g < cube; g++) + for (b = 0; b < cube; b++) + { + red = r * 65535 / (cube - 1); + green = g * 65535 / (cube - 1); + blue = b * 65535 / (cube - 1); + if (AllocColor (pColormap, &red, &green, &blue, &pix, 0) != Success) + return FALSE; + if (pix < *first) + *first = pix; + if (pix > *last) + *last = pix; + } + for (g = 0; g < ramp; g++) + { + red = + green = + blue = g * 65535 / (ramp - 1); + if (AllocColor (pColormap, &red, &green, &blue, &pix, 0) != Success) + return FALSE; + if (pix < *first) + *first = pix; + if (pix > *last) + *last = pix; + } + + return TRUE; +} + +/* 0 <= red, green, blue < 32 */ +static Pixel +FindBestColor (miIndexedPtr pIndexed, int first, int num, + int red, int green, int blue) +{ + Pixel best = first; + int bestDist = 1 << 30; + int dist; + int dr, dg, db; + while (num--) + { + CARD32 v = pIndexed->rgba[first]; + + dr = ((v >> 19) & 0x1f); + dg = ((v >> 11) & 0x1f); + db = ((v >> 3) & 0x1f); + dr = dr - red; + dg = dg - green; + db = db - blue; + dist = dr * dr + dg * dg + db * db; + if (dist < bestDist) + { + bestDist = dist; + best = first; + } + first++; + } + return best; +} + +/* 0 <= gray < 32768 */ +static Pixel +FindBestGray (miIndexedPtr pIndexed, int first, int num, int gray) +{ + Pixel best = first; + int bestDist = 1 << 30; + int dist; + int dr; + int r; + + while (num--) + { + CARD32 v = pIndexed->rgba[first]; + + r = v & 0xff; + r = r | (r << 8); + dr = gray - (r >> 1); + dist = dr * dr; + if (dist < bestDist) + { + bestDist = dist; + best = first; + } + first++; + } + return best; +} + +Bool +miInitIndexed (ScreenPtr pScreen, + PictFormatPtr pFormat) +{ + miIndexedPtr pIndexed; + int num; + Pixel first, last; + Pixel pix[MI_MAX_INDEXED]; + xrgb rgb[MI_MAX_INDEXED]; + Pixel p, r, g, b; + + if (pFormat->pVisual->ColormapEntries > MI_MAX_INDEXED) + return FALSE; + pIndexed = xalloc (sizeof (miIndexedRec)); + if (!pIndexed) + return FALSE; + num = pFormat->pVisual->ColormapEntries; + first = 0; + last = num - 1; + if (pFormat->pVisual->class & DynamicClass) + { + if (pFormat->pVisual->vid == pScreen->rootVisual) + { + if (num > 100) + num = num - 10; + else + num = num / 2; + } + if (!miBuildRenderColormap (pFormat->pColormap, num, &first, &last)) + { + xfree (pIndexed); + return FALSE; + } + } + /* + * Build mapping from pixel value to ARGB + */ + for (p = 0; p < pFormat->pVisual->ColormapEntries; p++) + pix[p] = p; + QueryColors (pFormat->pColormap, pFormat->pVisual->ColormapEntries, + pix, rgb); + for (p = 0; p < pFormat->pVisual->ColormapEntries; p++) + pIndexed->rgba[p] = (0xff000000 | + ((rgb[p].red & 0xff00) << 8) | + ((rgb[p].green & 0xff00) ) | + ((rgb[p].blue & 0xff00) >> 8)); + /* + * Build mapping from RGB to pixel value. This could probably be + * done a bit quicker... + */ + switch (pFormat->pVisual->class | DynamicClass) { + case GrayScale: + pIndexed->color = FALSE; + for (r = 0; r < 32768; r++) + pIndexed->ent[r] = FindBestGray (pIndexed, first, last-first+1, r); + break; + case PseudoColor: + pIndexed->color = TRUE; + p = 0; + for (r = 0; r < 32; r++) + for (g = 0; g < 32; g++) + for (b = 0; b < 32; b++) + { + pIndexed->ent[p] = FindBestColor (pIndexed, first, last-first+1, r, g, b); + p++; + } + break; + } + pFormat->indexed = pIndexed; + return TRUE; +} + +void +miCloseIndexed (ScreenPtr pScreen, + PictFormatPtr pFormat) +{ + if (pFormat->indexed) + { + xfree (pFormat->indexed); + pFormat->indexed = 0; + } +} + +void +miUpdateIndexed (ScreenPtr pScreen, + PictFormatPtr pFormat, + int ndef, + xColorItem *pdef) +{ + miIndexedPtr pIndexed = pFormat->indexed; + + if (pIndexed) + { + while (ndef--) + { + pIndexed->rgba[pdef->pixel] = (0xff000000 | + ((pdef->red & 0xff00) << 8) | + ((pdef->green & 0xff00) ) | + ((pdef->blue & 0xff00) >> 8)); + pdef++; + } + } +} + +#endif /* _MIINDEX_H_ */ |