From b923d897a51707c25b2dc62395d9765ba1a47bfe Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Jul 2003 17:53:46 +0000 Subject: [PATCH] Initial revision --- hw/kdrive/smi/Imakefile | 20 + hw/kdrive/smi/smi.c | 367 ++++++++++++++ hw/kdrive/smi/smi.h | 196 ++++++++ hw/kdrive/smi/smidraw.c | 336 +++++++++++++ hw/kdrive/smi/smidraw.h | 72 +++ hw/kdrive/smi/smistub.c | 58 +++ hw/kdrive/smi/smivideo.c | 1013 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 2062 insertions(+) create mode 100644 hw/kdrive/smi/Imakefile create mode 100644 hw/kdrive/smi/smi.c create mode 100644 hw/kdrive/smi/smi.h create mode 100644 hw/kdrive/smi/smidraw.c create mode 100644 hw/kdrive/smi/smidraw.h create mode 100644 hw/kdrive/smi/smistub.c create mode 100644 hw/kdrive/smi/smivideo.c diff --git a/hw/kdrive/smi/Imakefile b/hw/kdrive/smi/Imakefile new file mode 100644 index 000000000..930425447 --- /dev/null +++ b/hw/kdrive/smi/Imakefile @@ -0,0 +1,20 @@ +XCOMM $XFree86: xc/programs/Xserver/hw/kdrive/smi/Imakefile,v 1.2 2001/06/16 05:48:48 keithp Exp $ +KDRIVE=.. +#include "../Kdrive.tmpl" + +#if BuildXvExt +XVSRCS=smivideo.c +XVOBJS=smivideo.o +#endif + +SRCS = smi.c smidraw.c smistub.c $(XVSRCS) + +OBJS = smi.o smidraw.o smistub.o $(XVOBJS) + +DEFINES = XvExtensionDefines -DVESA /* -DUSE_PCI*/ + +INCLUDES = -I. $(KDINCS) -I$(KDRIVE)/vesa + +NormalLibraryObjectRule() +NormalLibraryTarget(smi,$(OBJS)) +DependTarget() diff --git a/hw/kdrive/smi/smi.c b/hw/kdrive/smi/smi.c new file mode 100644 index 000000000..1445b7f59 --- /dev/null +++ b/hw/kdrive/smi/smi.c @@ -0,0 +1,367 @@ +/* + * 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/smi/smi.c,v 1.11 2002/10/18 06:31:17 keithp Exp $ */ + +#include "smi.h" +#include + +#define DEBUG +#ifdef DEBUG +#define DBGOUT(fmt,a...) fprintf (stderr, fmt, ##a) +#else +#define DBGOUT(fmt,a...) +#endif + +#define ENTER() DBGOUT("Enter %s\n", __FUNCTION__) +#define LEAVE() DBGOUT("Leave %s\n", __FUNCTION__) + + + +Bool +smiCardInit (KdCardInfo *card) +{ + SmiCardInfo *smic; + + ENTER (); + smic = (SmiCardInfo *) xalloc (sizeof (SmiCardInfo)); + if (!smic) + return FALSE; + + (void) smiMapReg (card, smic); + + if (!vesaInitialize (card, &smic->vesa)) + { + xfree (smic); + return FALSE; + } + + card->driver = smic; + LEAVE(); + return TRUE; +} + +Bool +smiScreenInit (KdScreenInfo *screen) +{ + SmiCardInfo *smic = screen->card->driver; + SmiScreenInfo *smis; + int screen_size, memory; + + ENTER(); + smis = (SmiScreenInfo *) xalloc (sizeof (SmiScreenInfo)); + if (!smis) + return FALSE; + memset (smis, '\0', sizeof (SmiScreenInfo)); + if (!vesaScreenInitialize (screen, &smis->vesa)) + { + xfree (smis); + return FALSE; + } + if (!smic->reg_base) + screen->dumb = TRUE; + if (smis->vesa.mapping != VESA_LINEAR) + screen->dumb = TRUE; + smis->screen = smis->vesa.fb; + memory = smis->vesa.fb_size; + screen_size = screen->fb[0].byteStride * screen->height; + screen->softCursor = TRUE; + memory -= screen_size; + if (memory > screen->fb[0].byteStride) + { + smis->off_screen = smis->screen + screen_size; + smis->off_screen_size = memory; + } + else + { + smis->off_screen = 0; + smis->off_screen_size = 0; + } + screen->driver = smis; + LEAVE(); + return TRUE; +} + +Bool +smiInitScreen (ScreenPtr pScreen) +{ + Bool ret; + ENTER (); +#if 0 +#ifdef XV + KdScreenPriv(pScreen); + SmiCardInfo *smic = pScreenPriv->screen->card->driver; + if (smic->media_reg && smic->reg) + smiInitVideo(pScreen); +#endif +#endif + ret = vesaInitScreen (pScreen); + LEAVE(); +} + +#ifdef RANDR +smiRandRSetConfig (ScreenPtr pScreen, + Rotation randr, + int rate, + RRScreenSizePtr pSize) +{ + Bool ret; + KdScreenPriv(pScreen); + + ENTER (); + KdCheckSync (pScreen); + + ret = vesaRandRSetConfig (pScreen, randr, rate, pSize); + LEAVE(); + return ret; +} + +Bool +smiRandRInit (ScreenPtr pScreen) +{ + rrScrPriv(pScreen); + + ENTER (); + pScrPriv->rrSetConfig = smiRandRSetConfig; + LEAVE (); + return TRUE; +} +#endif + +Bool +smiFinishInitScreen (ScreenPtr pScreen) +{ + ENTER (); + if (!vesaFinishInitScreen (pScreen)) + return FALSE; +#ifdef RANDR + if (!smiRandRInit (pScreen)) + return FALSE; +#endif + LEAVE (); + return TRUE; +} + +void +smiPreserve (KdCardInfo *card) +{ + SmiCardInfo *smic = card->driver; + + ENTER (); + vesaPreserve(card); + LEAVE(); +} + +Bool +smiMapReg (KdCardInfo *card, SmiCardInfo *smic) +{ + ENTER (); + smic->io_base = 0; /* only handles one SMI card at standard VGA address */ + smic->reg_base = (CARD8 *) KdMapDevice (SMI_REG_BASE(card), + SMI_REG_SIZE(card)); + + if (!smic->reg_base) + { + smic->dpr = 0; + return FALSE; + } + + KdSetMappedMode (SMI_REG_BASE(card), + SMI_REG_SIZE(card), + KD_MAPPED_MODE_REGISTERS); + smic->dpr = (DPR *) (smic->reg_base + SMI_DPR_OFF(card)); + LEAVE (); + return TRUE; +} + +void +smiUnmapReg (KdCardInfo *card, SmiCardInfo *smic) +{ + ENTER (); + if (smic->reg_base) + { + KdResetMappedMode (SMI_REG_BASE(card), + SMI_REG_SIZE(card), + KD_MAPPED_MODE_REGISTERS); + KdUnmapDevice ((void *) smic->reg_base, SMI_REG_SIZE(card)); + smic->reg_base = 0; + smic->dpr = 0; + } + LEAVE (); +} + +void +smiOutb (CARD16 port, CARD8 val) +{ + asm volatile ("outb %b0,%w1" : : "a" (val), "d" (port)); +} + +CARD8 +smiInb (CARD16 port) +{ + CARD8 v; + asm volatile ("inb %w1,%b0" : "=a" (v) : "d" (port)); + return v; +} + +CARD8 +smiGetIndex (SmiCardInfo *smic, CARD16 addr, CARD16 data, CARD8 id) +{ + smiOutb (smic->io_base + addr, id); + return smiInb (smic->io_base + data); +} + +void +smiSetIndex (SmiCardInfo *smic, CARD16 addr, CARD16 data, CARD8 id, CARD8 val) +{ + smiOutb (smic->io_base + addr, id); + smiOutb (smic->io_base + data, val); +} + +void +smiSetMMIO (KdCardInfo *card, SmiCardInfo *smic) +{ + ENTER (); + if (!smic->reg_base) + smiMapReg (card, smic); + LEAVE(); +} + +void +smiResetMMIO (KdCardInfo *card, SmiCardInfo *smic) +{ + smiUnmapReg (card, smic); +} + +Bool +smiEnable (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + SmiCardInfo *smic = pScreenPriv->card->driver; + + ENTER (); + if (!vesaEnable (pScreen)) + return FALSE; + + smiSetMMIO (pScreenPriv->card, smic); + smiDPMS (pScreen, KD_DPMS_NORMAL); +#if 0 +#ifdef XV + KdXVEnable (pScreen); +#endif +#endif + LEAVE (); + return TRUE; +} + +void +smiDisable (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + SmiCardInfo *smic = pScreenPriv->card->driver; + + ENTER (); +#ifdef XV + KdXVDisable (pScreen); +#endif + smiResetMMIO (pScreenPriv->card, smic); + vesaDisable (pScreen); + LEAVE (); +} + +Bool +smiDPMS (ScreenPtr pScreen, int mode) +{ + Bool ret; + ENTER (); + ret = vesaDPMS (pScreen, mode); + LEAVE (); + return ret; +} + +void +smiRestore (KdCardInfo *card) +{ + SmiCardInfo *smic = card->driver; + + ENTER (); + vesaRestore (card); + LEAVE(); +} + +void +smiScreenFini (KdScreenInfo *screen) +{ + SmiScreenInfo *smis = (SmiScreenInfo *) screen->driver; + + ENTER (); + vesaScreenFini (screen); + xfree (smis); + screen->driver = 0; + LEAVE (); +} + +void +smiCardFini (KdCardInfo *card) +{ + SmiCardInfo *smic = card->driver; + + ENTER (); + smiUnmapReg (card, smic); + vesaCardFini (card); + LEAVE (); +} + +#define smiCursorInit 0 /* initCursor */ +#define smiCursorEnable 0 /* enableCursor */ +#define smiCursorDisable 0 /* disableCursor */ +#define smiCursorFini 0 /* finiCursor */ +#define smiRecolorCursor 0 /* recolorCursor */ + +KdCardFuncs smiFuncs = { + smiCardInit, /* cardinit */ + smiScreenInit, /* scrinit */ + smiInitScreen, /* initScreen */ + smiPreserve, /* preserve */ + smiEnable, /* enable */ + smiDPMS, /* dpms */ + smiDisable, /* disable */ + smiRestore, /* restore */ + smiScreenFini, /* scrfini */ + smiCardFini, /* cardfini */ + + smiCursorInit, /* initCursor */ + smiCursorEnable, /* enableCursor */ + smiCursorDisable, /* disableCursor */ + smiCursorFini, /* finiCursor */ + smiRecolorCursor, /* recolorCursor */ + + smiDrawInit, /* initAccel */ + smiDrawEnable, /* enableAccel */ + smiDrawSync, /* syncAccel */ + smiDrawDisable, /* disableAccel */ + smiDrawFini, /* finiAccel */ + + vesaGetColors, /* getColors */ + vesaPutColors, /* putColors */ + + smiFinishInitScreen, /* finishInitScreen */ +}; diff --git a/hw/kdrive/smi/smi.h b/hw/kdrive/smi/smi.h new file mode 100644 index 000000000..5092988d7 --- /dev/null +++ b/hw/kdrive/smi/smi.h @@ -0,0 +1,196 @@ +/* + * Id: smi.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/smi/smi.h,v 1.6 2001/07/24 19:06:03 keithp Exp $ */ + +#ifndef _SMI_H_ +#define _SMI_H_ +#include +#include "kxv.h" + +/* + * offset from ioport beginning + */ + +#define SMI_IO_BASE(c) ((c)->attr.io) +#define SMI_REG_BASE(c) ((c)->attr.address[0]) +#define SMI_REG_SIZE(c) (4096) + +#define SMI_DPR_OFF(c) (0x00000) + +typedef volatile CARD8 VOL8; +typedef volatile CARD16 VOL16; +typedef volatile CARD32 VOL32; + +/* DPR reg */ +typedef struct _DPR { + VOL32 src_xy; /* 0x00 */ + VOL32 dst_xy; /* 0x04 */ + VOL32 dst_wh; /* 0x08 */ + VOL32 accel_cmd; /* 0x0c */ + VOL32 src_stride; /* 0x10 */ + VOL32 fg; /* 0x14 */ + VOL32 bg; /* 0x18 */ + VOL32 data_format; /* 0x1c */ + VOL32 transparent; /* 0x20 */ + VOL32 mask1; /* 0x24 ? */ + VOL32 mask2; /* 0x28 ? */ + VOL32 scissors_ul; /* 0x2c */ + VOL32 scissors_lr; /* 0x30 */ + VOL32 mask3; /* 0x34 */ + VOL32 mask4; /* 0x38 */ + VOL32 dst_stride; /* 0x3c */ + VOL32 unknown_40; /* 0x40 */ + VOL32 unknown_44; /* 0x44 */ +} DPR; + +#define SMI_XY(x,y) (((y) & 0x7fff) | (((x) & 0x7fff) << 16)) + +/* 2D Engine commands */ +#define SMI_TRANSPARENT_SRC 0x00000100 +#define SMI_TRANSPARENT_DEST 0x00000300 + +#define SMI_OPAQUE_PXL 0x00000000 +#define SMI_TRANSPARENT_PXL 0x00000400 + +#define SMI_MONO_PACK_8 0x00001000 +#define SMI_MONO_PACK_16 0x00002000 +#define SMI_MONO_PACK_32 0x00003000 + +#define SMI_ROP2_SRC 0x00008000 +#define SMI_ROP2_PAT 0x0000C000 +#define SMI_ROP3 0x00000000 + +#define SMI_BITBLT 0x00000000 +#define SMI_RECT_FILL 0x00010000 +#define SMI_TRAPEZOID_FILL 0x00030000 +#define SMI_SHORT_STROKE 0x00060000 +#define SMI_BRESENHAM_LINE 0x00070000 +#define SMI_HOSTBLT_WRITE 0x00080000 +#define SMI_HOSTBLT_READ 0x00090000 +#define SMI_ROTATE_BLT 0x000B0000 + +#define SMI_SRC_COLOR 0x00000000 +#define SMI_SRC_MONOCHROME 0x00400000 + +#define SMI_GRAPHICS_STRETCH 0x00800000 + +#define SMI_ROTATE_CW 0x01000000 +#define SMI_ROTATE_CCW 0x02000000 + +#define SMI_MAJOR_X 0x00000000 +#define SMI_MAJOR_Y 0x04000000 + +#define SMI_LEFT_TO_RIGHT 0x00000000 +#define SMI_RIGHT_TO_LEFT 0x08000000 + +#define SMI_COLOR_PATTERN 0x40000000 +#define SMI_MONO_PATTERN 0x00000000 + +#define SMI_QUICK_START 0x10000000 +#define SMI_START_ENGINE 0x80000000 + +#define VGA_SEQ_INDEX 0x3C4 +#define VGA_SEQ_DATA 0x3C5 + +typedef struct _smiCardInfo { + VesaCardPrivRec vesa; + CARD16 io_base; + CARD8 *reg_base; + DPR *dpr; + int avail; +} SmiCardInfo; + +#define getSmiCardInfo(kd) ((SmiCardInfo *) ((kd)->card->driver)) +#define smiCardInfo(kd) SmiCardInfo *smic = getSmiCardInfo(kd) + +typedef struct _smiScreenInfo { + VesaScreenPrivRec vesa; + CARD8 *screen; + CARD8 *off_screen; + int off_screen_size; + CARD32 stride; + CARD32 data_format; + CARD8 dpr_vpr_enable; +} SmiScreenInfo; + +#define getSmiScreenInfo(kd) ((SmiScreenInfo *) ((kd)->screen->driver)) +#define smiScreenInfo(kd) SmiScreenInfo *smis = getSmiScreenInfo(kd) + +void +smiPreserve (KdCardInfo *card); + +Bool +smiMapReg (KdCardInfo *card, SmiCardInfo *smic); + +void +smiUnmapReg (KdCardInfo *card, SmiCardInfo *smic); + +void +smiSetMMIO (KdCardInfo *card, SmiCardInfo *smic); + +void +smiResetMMIO (KdCardInfo *card, SmiCardInfo *smic); + +Bool +smiEnable (ScreenPtr pScreen); + +void +smiDisable (ScreenPtr pScreen); + +void +smiWaitAvail(SmiCardInfo *smic, int n); + +void +smiWaitIdle (SmiCardInfo *smic); + +Bool +smiDrawSetup (ScreenPtr pScreen); + +Bool +smiDrawInit (ScreenPtr pScreen); + +void +smiDrawReinit (ScreenPtr pScreen); + +void +smiDrawEnable (ScreenPtr pScreen); + +void +smiDrawSync (ScreenPtr pScreen); + +void +smiDrawDisable (ScreenPtr pScreen); + +void +smiDrawFini (ScreenPtr pScreen); + +CARD8 +smiReadIndex (SmiCardInfo *smic, CARD16 port, CARD8 index); + +void +smiWriteIndex (SmiCardInfo *smic, CARD16 port, CARD8 index, CARD8 value); + +extern KdCardFuncs smiFuncs; + +#endif /* _SMI_H_ */ diff --git a/hw/kdrive/smi/smidraw.c b/hw/kdrive/smi/smidraw.c new file mode 100644 index 000000000..445d356b5 --- /dev/null +++ b/hw/kdrive/smi/smidraw.c @@ -0,0 +1,336 @@ +/* + * Id: smidraw.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/smi/smidraw.c,v 1.7 2001/07/24 19:06:03 keithp Exp $ */ + +#include "smi.h" +#include "smidraw.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 smiBltRop[16] = { + /* GXclear */ 0x00, /* 0 */ + /* GXand */ 0x88, /* src AND dst */ + /* GXandReverse */ 0x44, /* src AND NOT dst */ + /* GXcopy */ 0xcc, /* src */ + /* GXandInverted*/ 0x22, /* NOT src AND dst */ + /* GXnoop */ 0xaa, /* dst */ + /* GXxor */ 0x66, /* src XOR dst */ + /* GXor */ 0xee, /* src OR dst */ + /* GXnor */ 0x11, /* NOT src AND NOT dst */ + /* GXequiv */ 0x99, /* NOT src XOR dst */ + /* GXinvert */ 0x55, /* NOT dst */ + /* GXorReverse */ 0xdd, /* src OR NOT dst */ + /* GXcopyInverted*/ 0x33, /* NOT src */ + /* GXorInverted */ 0xbb, /* NOT src OR dst */ + /* GXnand */ 0x77, /* NOT src OR NOT dst */ + /* GXset */ 0xff, /* 1 */ +}; + +CARD8 smiSolidRop[16] = { + /* GXclear */ 0x00, /* 0 */ + /* GXand */ 0xa0, /* src AND dst */ + /* GXandReverse */ 0x50, /* src AND NOT dst */ + /* GXcopy */ 0xf0, /* src */ + /* GXandInverted*/ 0x0a, /* NOT src AND dst */ + /* GXnoop */ 0xaa, /* dst */ + /* GXxor */ 0x5a, /* src XOR dst */ + /* GXor */ 0xfa, /* src OR dst */ + /* GXnor */ 0x05, /* NOT src AND NOT dst */ + /* GXequiv */ 0xa5, /* NOT src XOR dst */ + /* GXinvert */ 0x55, /* NOT dst */ + /* GXorReverse */ 0xf5, /* src OR NOT dst */ + /* GXcopyInverted*/ 0x0f, /* NOT src */ + /* GXorInverted */ 0xaf, /* NOT src OR dst */ + /* GXnand */ 0x5f, /* NOT src OR NOT dst */ + /* GXset */ 0xff, /* 1 */ +}; + + +#define GET_STATUS(smic) smiGetIndex (smic, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x16) + +#define ENGINE_IDLE_EMPTY(smic) ((GET_STATUS(smic) & 0x18) == 0x10) +#define FIFO_EMPTY(smic) ((GET_STATUS(smic) & 0x10) == 0x10) + +static void +smiSleep (int ms) +{ + struct timespec req; + + req.tv_sec = ms / 1000; + req.tv_nsec = (ms % 1000) * 1000000; + while (req.tv_sec || req.tv_nsec) + if (nanosleep (&req, &req) == 0) + break; +} + +#define MAX_FIFO 16 + +void +smiWaitAvail(SmiCardInfo *smic, int n) +{ + if (smic->avail < n) + { + while (!FIFO_EMPTY (smic)) + ; + smic->avail = MAX_FIFO; + } + smic->avail -= n; +} + +void +smiWaitIdle (SmiCardInfo *smic) +{ + while (!ENGINE_IDLE_EMPTY (smic)) + ; + smic->avail = MAX_FIFO; +} + +static SmiCardInfo *smic; +static SmiScreenInfo *smis; +static DPR *dpr; +static CARD32 accel_cmd; + +static Bool +smiSetup (ScreenPtr pScreen, int wait) +{ + KdScreenPriv(pScreen); + + smis = getSmiScreenInfo (pScreenPriv); + smic = getSmiCardInfo(pScreenPriv); + dpr = smic->dpr; + + if (!dpr) + return FALSE; + + /* enable DPR/VPR registers */ + smiSetIndex (smic, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, + smis->dpr_vpr_enable); + + smiWaitAvail (smic, wait + 9); + dpr->src_stride = (smis->stride << 16) | smis->stride; + dpr->data_format = smis->data_format; + dpr->mask1 = 0xffffffff; + dpr->mask2 = 0xffffffff; + dpr->dst_stride = (smis->stride << 16) | smis->stride; + dpr->unknown_40 = 0x0; + dpr->unknown_44 = 0x0; + dpr->scissors_ul = 0x0; + dpr->scissors_lr = SMI_XY(4095,4095); + + return TRUE; +} + +Bool +smiPrepareSolid (DrawablePtr pDrawable, + int alu, + Pixel pm, + Pixel fg) +{ + KdScreenPriv(pDrawable->pScreen); + + if (~pm & FbFullMask(pDrawable->depth)) + return FALSE; + + if (!smiSetup (pDrawable->pScreen, 3)) + return FALSE; + + accel_cmd = smiSolidRop[alu] | SMI_BITBLT | SMI_START_ENGINE; + dpr->fg = fg; + dpr->mask3 = 0xffffffff; + dpr->mask4 = 0xffffffff; + return TRUE; +} + +void +smiSolid (int x1, int y1, int x2, int y2) +{ + smiWaitAvail(smic,3); + dpr->dst_xy = SMI_XY(x1,y1); + dpr->dst_wh = SMI_XY(x2-x1,y2-y1); + dpr->accel_cmd = accel_cmd; +} + +void +smiDoneSolid (void) +{ +} + +static int copyDx; +static int copyDy; + +Bool +smiPrepareCopy (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + int dx, + int dy, + int alu, + Pixel pm) +{ + KdScreenPriv(pSrcDrawable->pScreen); + + if (~pm & FbFullMask(pSrcDrawable->depth)) + return FALSE; + + if (!smiSetup (pSrcDrawable->pScreen, 0)) + return FALSE; + + accel_cmd = smiBltRop[alu] | SMI_BITBLT | SMI_START_ENGINE; + + copyDx = dx; + copyDy = dy; + if (dy < 0 || (dy == 0 && dx < 0)) + accel_cmd |= SMI_RIGHT_TO_LEFT; + return TRUE; +} + +void +smiCopy (int srcX, + int srcY, + int dstX, + int dstY, + int w, + int h) +{ + if (accel_cmd & SMI_RIGHT_TO_LEFT) + { + srcX += w - 1; + dstX += w - 1; + srcY += h - 1; + dstY += h - 1; + } + smiWaitAvail (smic, 4); + dpr->src_xy = SMI_XY (srcX, srcY); + dpr->dst_xy = SMI_XY (dstX, dstY); + dpr->dst_wh = SMI_XY (w, h); + dpr->accel_cmd = accel_cmd; +} + +void +smiDoneCopy (void) +{ +} + +KaaScreenPrivRec smiKaa = { + smiPrepareSolid, + smiSolid, + smiDoneSolid, + + smiPrepareCopy, + smiCopy, + smiDoneCopy, +}; + +Bool +smiDrawInit (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + + if (pScreenPriv->screen->fb[0].depth == 4) + return FALSE; + + if (!kaaDrawInit (pScreen, &smiKaa)) + return FALSE; + + return TRUE; +} + +void +smiDrawEnable (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + int i; + static const int xyAddress[] = { 320, 400, 512, 640, 800, 1024, 1280, 1600, 2048 }; + + smis = getSmiScreenInfo (pScreenPriv); + smic = getSmiCardInfo(pScreenPriv); + dpr = smic->dpr; + + smis->stride = pScreenPriv->screen->fb[0].byteStride; + smis->dpr_vpr_enable = smiGetIndex (smic, VGA_SEQ_INDEX, + VGA_SEQ_DATA, 0x21) & ~0x03; + + switch (pScreenPriv->screen->fb[0].depth) { + case 8: + smis->data_format = 0x00000000; + break; + case 15: + case 16: + smis->data_format = 0x00100000; + smis->stride >>= 1; + break; + case 24: + smis->data_format = 0x00300000; + break; + case 32: + smis->data_format = 0x00200000; + smis->stride >>= 2; + break; + } + for (i = 0; i < sizeof(xyAddress) / sizeof(xyAddress[0]); i++) + { + if (xyAddress[i] == pScreenPriv->screen->fb[0].pixelStride) + { + smis->data_format |= i << 16; + break; + } + } + + smiSetup (pScreen, 0); + + KdMarkSync (pScreen); +} + +void +smiDrawDisable (ScreenPtr pScreen) +{ + smic = 0; + smis = 0; + dpr = 0; + accel_cmd = 0; +} + +void +smiDrawFini (ScreenPtr pScreen) +{ +} + +void +smiDrawSync (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + smic = getSmiCardInfo(pScreenPriv); + + smiWaitIdle (smic); +} diff --git a/hw/kdrive/smi/smidraw.h b/hw/kdrive/smi/smidraw.h new file mode 100644 index 000000000..3ec0831fc --- /dev/null +++ b/hw/kdrive/smi/smidraw.h @@ -0,0 +1,72 @@ +/* + * Id: smidraw.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 _SMIDRAW_H_ +#define _SMIDRAW_H_ + +#define SetupSmi(s) KdScreenPriv(s); \ + smiCardInfo(pScreenPriv); \ + Cop *cop = smic->cop + +#define SmiAlpha (COP_MULTI_ALPHA|COP_ALPHA_WRITE_ENABLE) + +#define _smiInit(cop,smic) { \ + if ((cop)->status == 0xffffffff) smiSetMMIO(smic); \ + (cop)->multi = (smic)->cop_depth; \ + (cop)->multi = (smic)->cop_stride; \ + (cop)->multi = SmiAlpha; \ +} \ + +#define _smiSetSolidRect(cop,pix,alu,cmd) {\ + cop->multi = COP_MULTI_PATTERN; \ + cop->multi = COP_MULTI_ROP | smiRop[alu]; \ + cop->fg = (pix); \ + cmd = COP_OP_BLT | COP_SCL_OPAQUE | COP_OP_ROP | COP_OP_FG; \ +} + +#define _smiRect(cop,x1,y1,x2,y2,cmd) { \ + (cop)->dst_start_xy = TRI_XY (x1,y1); \ + (cop)->dst_end_xy = TRI_XY(x2,y2); \ + _smiWaitDone(cop); \ + (cop)->command = (cmd); \ +} + +#define COP_STATUS_BUSY (COP_STATUS_BE_BUSY | \ + COP_STATUS_DPE_BUSY | \ + COP_STATUS_MI_BUSY) + +#define _smiWaitDone(cop) { \ + int __q__ = 500000; \ + while (__q__-- && (cop)->status & COP_STATUS_BUSY) \ + ; \ + if (!__q__) \ + (cop)->status = 0; \ +} + +#define _smiWaitIdleEmpty(cop) _smiWaitDone(cop) + +#define sourceInvarient(alu) (((alu) & 3) == (((alu) >> 2) & 3)) + +#endif diff --git a/hw/kdrive/smi/smistub.c b/hw/kdrive/smi/smistub.c new file mode 100644 index 000000000..d43908439 --- /dev/null +++ b/hw/kdrive/smi/smistub.c @@ -0,0 +1,58 @@ +/* + * Id: smistub.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/smi/smistub.c,v 1.4 2002/10/08 21:25:35 keithp Exp $ */ + +#include "smi.h" + +void +InitCard (char *name) +{ + KdCardAttr attr; + + if (LinuxFindPci (0x126f, 0x0720, 0, &attr)) + KdCardInfoAdd (&smiFuncs, &attr, 0); +} + +void +InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv) +{ + KdInitOutput (pScreenInfo, argc, argv); +} + +void +InitInput (int argc, char **argv) +{ + KdInitInput (&LinuxMouseFuncs, &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/hw/kdrive/smi/smivideo.c b/hw/kdrive/smi/smivideo.c new file mode 100644 index 000000000..8ff29e67f --- /dev/null +++ b/hw/kdrive/smi/smivideo.c @@ -0,0 +1,1013 @@ +/* + * 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.10 2003/04/23 21:51:18 tsi 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 randr, + 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 (randr & RR_Rotate_All) { + case RR_Rotate_0: + src = buf; + srcDown = srcPitch; + srcRight = 2; + break; + case RR_Rotate_90: + src = buf + (srcH - 1) * 2; + srcDown = -2; + srcRight = srcPitch; + break; + case RR_Rotate_180: + src = buf + srcPitch * (srcH - 1) + (srcW - 1) * 2; + srcDown = -srcPitch; + srcRight = -2; + break; + case RR_Rotate_270: + src = buf + 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 randr, + 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 (randr & RR_Rotate_All) { + case RR_Rotate_0: + srcDown = srcPitch; + srcDown2 = srcPitch2; + srcRight = 2; + srcRight2 = 1; + srcNext = 1; + break; + case RR_Rotate_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 RR_Rotate_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 RR_Rotate_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; + } + } +} + +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 randr = mach64s->vesa.randr; + 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 randr = mach64s->vesa.randr; + 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; + + if (randr & (RR_Rotate_0|RR_Rotate_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; + } + else + { + 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; + } + + switch (randr & RR_Rotate_All) { + case RR_Rotate_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 RR_Rotate_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 RR_Rotate_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 RR_Rotate_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, randr, + 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, randr, + 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 (!REGION_EQUAL (screen->pScreen, &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 (!REGION_EQUAL (screen->pScreen, &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; +}