xserver-kdrive-imageon X11R7.1-1.1.0 : XV Port changes, cleanups
authorManuel Teira <manuel.teira@telefonica.net>
Thu, 14 Jun 2007 19:57:28 +0000 (19:57 +0000)
committerManuel Teira <manuel.teira@telefonica.net>
Thu, 14 Jun 2007 19:57:28 +0000 (19:57 +0000)
* Avoid recalculation of surface boundaries when possible
* Cleanups and optimizations in support functions
* More rational APIs for blitting functions.
* Release bumped up to r2

packages/xorg-xserver/xserver-kdrive-imageon_X11R7.1-1.1.0.bb
packages/xorg-xserver/xserver-kdrive/kdrive-imageon.patch

index 106d540..9cdc72f 100644 (file)
@@ -11,7 +11,7 @@ DEPENDS = "tslib xproto libxdmcp xextproto xtrans libxau virtual/libx11 libxext
 PROVIDES = "virtual/xserver"
 RPROVIDES = "virtual/xserver"
 
-PR = "r1"
+PR = "r2"
 
 FILESPATH = "${FILE_DIRNAME}/xserver-kdrive"
 
index f4272f8..2f7f5ca 100644 (file)
 +#endif
 --- /dev/null
 +++ xorg-server-X11R7.1-1.1.0.work/hw/kdrive/imageon/imageon_cursor.c
-@@ -0,0 +1,566 @@
+@@ -0,0 +1,565 @@
 +/*
 + * Copyright © 2007 Manuel Teira
 + *
 +#include "imageon_regs.h"
 +
 +#define W100_CURSOR_HEIGHT (16)
-+#define W100_CURSOR_PITCH  (4)
 +#define W100_CURSOR_WIDTH  (16)
++#define W100_CURSOR_PITCH  (W100_CURSOR_WIDTH / 4)
++
 +#define W100_CURSOR_SIZE   W100_CURSOR_PITCH * W100_CURSOR_WIDTH
 +
 +static CARD16 expand2bpp[256];
 +    (((y) * W100_CURSOR_PITCH + ((x) / 4)) >> 2)
 +
 +#define PixelShift(x, y) \
-+    (2 * ((x) % W100_CURSOR_WIDTH))
++    (2 * ((x) % 16))
 +
 +#define PixelMask(x, y) \
 +    ((0xc0000000) >> PixelShift(x, y))
 +    cursor_v_pos_u vpos;
 +    graphic_h_disp_u graphic_hdisp;
 +    graphic_v_disp_u graphic_vdisp;
-+    int tx, ty, tw, th;
++    BoxRec cursorBox, deviceBox;
 +
 +
 +    if (!pCurPriv->has_cursor) {
 +    graphic_vdisp.val = w100c->regs.GRAPHIC_V_DISP;
 +    xoffs = 0;
 +    yoffs = 0;
-+    x -= pCurPriv->xhot;
-+    y -= pCurPriv->yhot;
-+    tx = W100MapToHWX(w100c, x, y, pCurPriv->width, pCurPriv->height);
-+    ty = W100MapToHWY(w100c, x, y, pCurPriv->width, pCurPriv->height);
-+    tw = W100MapToHWW(w100c, x, y, pCurPriv->width, pCurPriv->height);
-+    th = W100MapToHWH(w100c, x, y, pCurPriv->width, pCurPriv->height);
++    cursorBox.x1 = x - pCurPriv->xhot;
++    cursorBox.y1 = y - pCurPriv->yhot;
++    cursorBox.x2 = cursorBox.x1 + pCurPriv->width  - 1;
++    cursorBox.y2 = cursorBox.y1 + pCurPriv->height - 1;
++    W100MapToDevice(w100c, &cursorBox, &deviceBox);
 +
-+    if (tx < 0) {
-+        xoffs = -tx;
-+        tw -= xoffs;
-+        tx = 0;
++    if (deviceBox.x1 < 0) {
++        xoffs = -deviceBox.x1;
++        deviceBox.x1 = 0;
 +    }
 +
-+    if (ty < 0) {
-+        yoffs = -ty;
-+        th -= yoffs;
-+        ty = 0;
++    if (deviceBox.y1 < 0) {
++        yoffs = -deviceBox.y1;
++        deviceBox.y1 = 0;
 +    }
-+
-+    hpos.f.cur_h_start = graphic_hdisp.f.graphic_h_start + tx;
-+    hpos.f.cur_h_end   = hpos.f.cur_h_start + tw;
++    
++    hpos.f.cur_h_start = graphic_hdisp.f.graphic_h_start + deviceBox.x1;
++    hpos.f.cur_h_end   = graphic_hdisp.f.graphic_h_start + deviceBox.x2 + 1;
 +    hpos.f.cur_en = 1;
-+    vpos.f.cur_v_start = graphic_vdisp.f.graphic_v_start + ty;
-+    vpos.f.cur_v_end   = vpos.f.cur_v_start + th;
++    vpos.f.cur_v_start = graphic_vdisp.f.graphic_v_start + deviceBox.y1;
++    vpos.f.cur_v_end   = graphic_vdisp.f.graphic_v_start + deviceBox.y2 + 1;
++
 +    cursor_offset.f.cur_x_offset = xoffs;
 +    cursor_offset.f.cur_y_offset = yoffs;
 +    cursor_offset.f.cur_offset = (CARD32) 
 +                       + pCurPriv->area->offset);
 +    DBG_IMAGEON(("W100MoveCursor dst(x:%d,y:%d),"
 +                 "mapped(x:%d,y:%d,xoffs:%d,yoffs:%d)\n",
-+                 x, y, tx, ty, xoffs, yoffs));
++                 x, y, deviceBox.x1, deviceBox.y1, xoffs, yoffs));
 +
 +    W100DisableDisplayUpdate(w100c);
 +    MMIO_OUT32(mmCURSOR1_OFFSET, cursor_offset.val);
 +}
 --- /dev/null
 +++ xorg-server-X11R7.1-1.1.0.work/hw/kdrive/imageon/imageon_draw.c
-@@ -0,0 +1,237 @@
+@@ -0,0 +1,238 @@
 +/*
 + * Copyright © 2007 Manuel Teira
 + *
 +    KdScreenPriv(pPix->drawable.pScreen);
 +    W100ScreenInfo(pScreenPriv);
 +    W100CardInfo(pScreenPriv);
++    W100PortPrivPtr pPortPriv = w100s->pAdaptor->pPortPrivates[0].ptr;
 +    int fifoEntries = 4;
 +
 +    DBG_IMAGEON(("W100PrepareSolid(alu:%d, pm:0x%08x, fg:%d)\n",
 +}
 --- /dev/null
 +++ xorg-server-X11R7.1-1.1.0.work/hw/kdrive/imageon/imageon.h
-@@ -0,0 +1,261 @@
+@@ -0,0 +1,284 @@
 +/*
 + * Copyright © 2007 Manuel Teira
 + *
 +    Bool   supported;
 +} W100ModeSpec;
 +
++typedef struct _W100BoxRec {
++    CARD16 x;
++    CARD16 y;
++    CARD16 w;
++    CARD16 h;
++} W100BoxRec, *W100BoxPtr;
++
 +typedef struct _W100Mode {
 +    CARD16 width;
 +    CARD16 height;
 +    CARD32 videoStatus;
 +    CARD32 videoCtrl;
 +    RegionRec clip;
-+    KdOffscreenArea *offSurface;
-+    CARD32 offSize;
-+    KdOffscreenArea *ovlSurface;
-+    CARD32 ovlSize;
-+    CARD32 YPlaneOffset;
-+    CARD32 UPlaneOffset;
-+    CARD32 VPlaneOffset;
-+    CARD32 colorKey;
-+    CARD8 brightness;
-+    CARD32 maxOverlaySize;
-+    CARD16 ovlX;
-+    CARD16 ovlY;
-+    CARD16 ovlWidth;
-+    CARD16 ovlHeight;
-+    CARD8 videoHorExp;
-+    CARD8 videoVerExp;
-+    int id;
++    struct {
++        int width;                /* Source width  */
++        int height;               /* Source height */
++        unsigned char *buffer;    /* Source buffer */
++        int id;                   /* Source FOURCC */
++        int size;                 /* Size of source rect (bytes) */
++        KdOffscreenArea *surface; /* Source surface (on card memory) */
++        BoxRec box;               /* Source rect boundaries */
++    } src;
++    struct {
++        BoxRec box;               /* Screen rectangle */
++    } dst;
++    struct {
++        int size;                  /* Size of the overlay surface (bytes) */
++        KdOffscreenArea *surface;  /* Overlay surface (on card memory)    */
++        BoxRec box;                /* Overlay box (util size)             */
++        BoxRec frame;              /* Overlay box (plus corrections)      */
++        Bool changed;              /* To avoid recalculations             */
++        int horExp;                /* Horizontal expansion                */
++        int verExp;                /* Vertical expansion                  */
++        int maxSize;               /* Maximum allowed surface size (bytes) */
++        int colorKey;              /* Colour to replace with overlay */
++        int brightness;            /* Brigthness */
++    } ovl;
++    struct {
++        int size;                  /* Number of planes  */
++        int bpp;                   /* bpp of the planes */
++        int offset[3];             /* Planes offsets    */
++        CARD32 yplane;             /* Offset (card) of Y plane */
++        CARD32 uplane;             /* Offset (card) of U plane */
++        CARD32 vplane;             /* Offset (card) of V plane */
++    } planes;
++    Bool changed;              /* To track changes and avoid recalculations */
 +} W100PortPrivRec, *W100PortPrivPtr;
 +
 +extern KdCardFuncs W100Funcs;
 +}
 --- /dev/null
 +++ xorg-server-X11R7.1-1.1.0.work/hw/kdrive/imageon/imageon_support.c
-@@ -0,0 +1,1438 @@
+@@ -0,0 +1,1474 @@
 +/*
 + * Copyright © 2007 Manuel Teira
 + *
 +    } else {
 +        w100c->ctx.mask.enable = FALSE;
 +    }
-+
 +}
 +
 +Bool W100SetSource(KdScreenInfo *screen, 
 +                              pPix->drawable.bitsPerPixel);
 +}
 +
-+int W100MapToHWX(W100CardInfo *w100c,
-+                 int x, int y, int w, int h)
++void W100MapToDevice(W100CardInfo *w100c, BoxPtr src, BoxPtr dst)
 +{
-+    int tx;
 +    switch (w100c->hw_window.randr & RR_Rotate_All) {
 +    case RR_Rotate_0:
-+        tx = x;
++        dst->x1 = src->x1;
++        dst->y1 = src->y1;
++        dst->x2 = src->x2;
++        dst->y2 = src->y2;
 +        break;
 +    case RR_Rotate_90:
-+        tx = w100c->hw_window.height - (y + h);
++        dst->x1 = w100c->hw_window.height - src->y2 - 1;
++        dst->y1 = src->x1;
++        dst->x2 = w100c->hw_window.height - src->y1 - 1;
++        dst->y2 = src->x2;
 +        break;
 +    case RR_Rotate_180:
-+        tx = w100c->hw_window.width - (x + w);
++        dst->x1 = w100c->hw_window.width - src->x2 - 1;
++        dst->y1 = w100c->hw_window.height - src->y2 - 1;
++        dst->x2 = w100c->hw_window.width - src->x1 - 1;
++        dst->y2 = w100c->hw_window.height - src->y1 - 1;
 +        break;
 +    case RR_Rotate_270:
-+        tx = y;
++        dst->x1 = src->y1;
++        dst->y1 = w100c->hw_window.width - src->x2 - 1;
++        dst->x2 = src->y2;
++        dst->y2 = w100c->hw_window.height - src->x1 - 1;
 +        break;
-+    default:
-+        tx = x;
 +    }
-+    return tx;
++    DBG_IMAGEON(("MapToDevice (x1:%d,y1:%d,x2:%d,y2:%d)->(x1:%d,y1:%d,x2:%d,y2:%d)\n",
++                 src->x1, src->y1, src->x2, src->y2,
++                 dst->x1, dst->y1, dst->x2, dst->y2));
 +}
 +
-+int W100MapToHWY(W100CardInfo *w100c,
-+                 int x, int y, int w, int h)
++void W100MapFromDevice(W100CardInfo *w100c, BoxPtr src, BoxPtr dst)
 +{
-+    int ty;
 +    switch (w100c->hw_window.randr & RR_Rotate_All) {
 +    case RR_Rotate_0:
-+        ty = y;
++        dst->x1 = src->x1;
++        dst->y1 = src->y1;
++        dst->x2 = src->x2;
++        dst->y2 = src->y2;
 +        break;
 +    case RR_Rotate_90:
-+        ty = x;
++        dst->x1 = src->y1;
++        dst->y1 = w100c->hw_window.height - src->x2 - 1;
++        dst->x2 = src->y2;
++        dst->y2 = w100c->hw_window.height - src->x1 - 1;
 +        break;
 +    case RR_Rotate_180:
-+        ty = w100c->hw_window.height - (y + h);
++        dst->x1 = w100c->hw_window.width - src->x2 - 1;
++        dst->y1 = w100c->hw_window.height - src->y2 - 1;
++        dst->x2 = w100c->hw_window.width - src->x1 - 1;
++        dst->y2 = w100c->hw_window.height - src->y1 - 1;
 +        break;
 +    case RR_Rotate_270:
-+        ty = w100c->hw_window.width - (x + w);
++        dst->x1 = w100c->hw_window.height - src->y2 - 1;
++        dst->y1 = src->x1;
++        dst->x2 = w100c->hw_window.width - src->y1 - 1;
++        dst->y2 = src->x2;
 +        break;
-+    default:
-+        ty = y;
 +    }
-+    return ty;
++    DBG_IMAGEON(("MapFromDevice (x1:%d,y1:%d,x2:%d,y2:%d)->(x1:%d,y1:%d,x2:%d,y2:%d)\n",
++                 src->x1, src->y1, src->x2, src->y2,
++                 dst->x1, dst->y1, dst->x2, dst->y2));
 +}
 +
-+int W100MapToHWW(W100CardInfo *w100c,
-+                 int x, int y, int w, int h)
++void W100MoveTo(BoxPtr src, int x, int y)
 +{
-+    int tw;
-+    switch (w100c->hw_window.randr & RR_Rotate_All) {
-+    case RR_Rotate_0:
-+    case RR_Rotate_180:
-+        tw = w;
-+        break;
-+    case RR_Rotate_90:
-+    case RR_Rotate_270:
-+        tw = h;
-+        break;
-+    }
-+    return tw;
++    src->x1 += x;
++    src->y1 += y;
++    src->x2 += x;
++    src->y2 += y;
 +}
 +
-+int W100MapToHWH(W100CardInfo *w100c,
-+                 int x, int y, int w, int h)
++void W100ChangeOrigin(BoxPtr src, int x, int y)
 +{
-+    int th;
-+    switch (w100c->hw_window.randr & RR_Rotate_All) {
-+    case RR_Rotate_0:
-+    case RR_Rotate_180:
-+        th = h;
-+        break;
-+    case RR_Rotate_90:
-+    case RR_Rotate_270:
-+        th = w;
-+        break;
++    src->x1 -= x;
++    src->y1 -= y;
++    src->x2 -= x;
++    src->y2 -= y;
++}
++
++void W100ScaleBox(BoxPtr src, BoxPtr dst, int scale)
++{
++    if (scale >= 0) {
++        dst->x1 = src->x1 << scale;
++        dst->x2 = src->x2 << scale;
++        dst->y1 = src->y1 << scale;
++        dst->y2 = src->y2 << scale;
++    } else {
++        dst->x1 = src->x1 >> -scale;
++        dst->x2 = src->x2 >> -scale;
++        dst->y1 = src->y1 >> -scale;
++        dst->y2 = src->y2 >> -scale;
 +    }
-+    return th;
 +}
 +
-+CARD16 W100XformX(W100CardInfo *w100c,
-+                  CARD16 x, CARD16 y, CARD16 w, CARD16 h)
++void W100TrajectoryOrigin(W100CardInfo *w100c, BoxPtr box, short *x, short *y)
 +{
-+    CARD16 tx;
 +    switch (w100c->ctx.xform.randr & RR_Rotate_All) {
 +    case RR_Rotate_0:
 +        if (w100c->ctx.xform.mirror) {
-+            tx = x + w - 1;
++            *x = box->x2;
 +        } else {
-+            tx = x;
++            *x = box->x1;
 +        }
++        *y = box->y1;
 +        break;
 +    case RR_Rotate_90:
-+        tx = x + h - 1;
-+        break;
-+    case RR_Rotate_180:
++        *x = box->x2;
 +        if (w100c->ctx.xform.mirror) {
-+            tx = x;
++            *y = box->y2;
 +        } else {
-+            tx = x + w - 1;
++            *y = box->y1;
 +        }
 +        break;
-+    case RR_Rotate_270:
-+    default:
-+        tx = x;
-+        break;
-+    }
-+    return tx;
-+}
-+
-+CARD16 W100XformY(W100CardInfo *w100c,
-+                  CARD16 x, CARD16 y, CARD16 w, CARD16 h)
-+{
-+    CARD16 ty;
-+    switch (w100c->ctx.xform.randr & RR_Rotate_All) {
-+    case RR_Rotate_0:
-+        ty = y;
-+        break;
-+    case RR_Rotate_90:
++    case RR_Rotate_180:
 +        if (w100c->ctx.xform.mirror) {
-+            ty = y + w - 1;
++            *x = box->x1;
 +        } else {
-+            ty = y;
++            *x = box->x2;
 +        }
-+        break;
-+    case RR_Rotate_180:
-+        ty = y + h - 1;
++        *y = box->y2;
 +        break;
 +    case RR_Rotate_270:
-+    default:
++        *x = box->x1;
 +        if (w100c->ctx.xform.mirror) {
-+            ty = y;
++            *y = box->y1;
 +        } else {
-+            ty = y + w - 1;
++            *y = box->y2;
 +        }
-+        break;
 +    }
-+    return ty;
 +}
-+
-+CARD16 W100XformW(W100CardInfo *w100c,
-+                  CARD16 x, CARD16 y, CARD16 w, CARD16 h)
-+{
-+    CARD16 tw;
-+
-+    switch (w100c->ctx.xform.randr & RR_Rotate_All) {
-+    case RR_Rotate_0:
-+    case RR_Rotate_180:
-+    default:
-+        tw = w;
-+        break;
-+    case RR_Rotate_90:
-+    case RR_Rotate_270:
-+        tw = h;
-+        break;
-+    }
-+    return tw;
-+}
-+
-+CARD16 W100XformH(W100CardInfo *w100c,
-+                  CARD16 x, CARD16 y, CARD16 w, CARD16 h)
-+{
-+    CARD16 th;
-+
-+    switch (w100c->ctx.xform.randr & RR_Rotate_All) {
-+    case RR_Rotate_0:
-+    case RR_Rotate_180:
-+    default:
-+        th = h;
-+        break;
-+    case RR_Rotate_90:
-+    case RR_Rotate_270:
-+        th = w;
-+        break;
-+    }
-+    return th;
-+}
-+
++    
 +CARD8 W100GetScaler(CARD16 dstsize, CARD16 srcsize)
 +{
 +    return W100_MAX(1, W100_MIN(31, ((16 * srcsize) + dstsize - 1) / dstsize));
 +}
 +
 +
-+static void W100Blt(KdScreenInfo *screen, 
-+                    int randr,
-+                    int bpp,
++static void W100Blt(KdScreenInfo *screen,
++                    int randr, int bpp,
 +                    CARD32 srcOffset,
-+                    CARD16 srcW,
-+                    CARD16 srcH,
 +                    CARD16 srcPitch,
++                    BoxPtr srcBox,
 +                    CARD32 dstOffset,
 +                    CARD16 dstPitch,
-+                    CARD16 dstX,
-+                    CARD16 dstY)
++                    BoxPtr dstBox)
 +{
 +    ScreenPtr pScreen = screen->pScreen;
 +    KdScreenPriv(pScreen);
 +    W100CardInfo(pScreenPriv);
-+    CARD16 x, y, w, h;
 +    int fifoEntries = 9;
 +    Bool hasXForm = FALSE;
 +    eng_cntl_u eng_cntl;
 +    src_width_u src_width;
 +    src_height_u src_height;
 +    dst_width_height_u dst_width_height;
-+
-+    DBG_IMAGEON(("W100Blt(randr:%d,bpp:%d,srcOffset:0x%08x,"
-+                 "srcW:%d,srcH:%d,srcPitch:%d,dstOffset:0x%08x,"
-+                 "dstPitch:%d,dstX:%d,dstY:%d)\n",
-+                 randr, bpp, srcOffset, srcW, srcH, 
-+                 srcPitch, dstOffset, dstPitch, dstX, dstY));
++    CARD16 dstX;
++    CARD16 dstY;
 +
 +    if (randr & (RR_Rotate_90|RR_Rotate_270)) {
 +        hasXForm = TRUE;
 +    W100SetRotation(w100c, randr, FALSE);
 +    W100SetSource(screen, srcPitch, srcOffset, bpp);
 +    W100SetDestination(screen, dstPitch, dstOffset, bpp);
-+
-+    x = W100XformX(w100c, dstX, dstY, srcW, srcH);
-+    y = W100XformY(w100c, dstX, dstY, srcW, srcH);
-+    w = W100XformW(w100c, dstX, dstY, srcW, srcH);
-+    h = W100XformH(w100c, dstX, dstY, srcW, srcH);
-+
-+    src_x_y.f.src_y = 0;
-+    src_x_y.f.src_x = 0;
-+    dst_x_y.f.dst_x = x;
-+    dst_x_y.f.dst_y = y;
-+    src_width.f.src_width = srcW;
-+    src_height.f.src_height = srcH;
-+    dst_width_height.f.dst_height = h;
-+    dst_width_height.f.dst_width_b0 = w & 0xff;
-+    dst_width_height.f.dst_width_b1 = (w >> 8) & 0x3f;
++    W100TrajectoryOrigin(w100c, dstBox, &dstX, &dstY);
++
++    src_x_y.f.src_x = srcBox->x1;
++    src_x_y.f.src_y = srcBox->y1;
++    dst_x_y.f.dst_x = dstX;
++    dst_x_y.f.dst_y = dstY;
++    src_width.f.src_width = srcBox->x2 - srcBox->x1 + 1;
++    src_height.f.src_height = srcBox->y2 - srcBox->y1 + 1;
++    dst_width_height.f.dst_height = dstBox->y2 - dstBox->y1 + 1;
++    dst_width_height.f.dst_width_b0 = (dstBox->x2 - dstBox->x1 + 1) & 0xff;
++    dst_width_height.f.dst_width_b1 = ((dstBox->x2 - dstBox->x1 + 1) >> 8) & 0x3f;
++
++    DBG_IMAGEON(("W100Blt src(x:%d,y:%d,w:%d,h:%d) dst(x:%d,y:%d,w:%d,h:%d)\n",
++                 src_x_y.f.src_x,
++                 src_x_y.f.src_y,
++                 src_width.f.src_width,
++                 src_height.f.src_height,
++                 dst_x_y.f.dst_x,
++                 dst_x_y.f.dst_y,
++                 dst_width_height.f.dst_width_b0 |
++                 dst_width_height.f.dst_width_b1 << 8,
++                 dst_width_height.f.dst_height));
 +    
 +    if (W100WaitCmdFifoEntries(w100c, fifoEntries)) {
 +        MMIO_OUT32(mmDST_PITCH,   w100c->ctx.dst.pitch);
 +                           int randr,
 +                           int bpp,
 +                           CARD32 srcOffset,
-+                           CARD16 srcW,
-+                           CARD16 srcH,
 +                           CARD16 srcPitch,
++                           BoxPtr srcBox,
 +                           CARD32 dstOffset,
 +                           CARD16 dstPitch,
-+                           CARD16 dstX,
-+                           CARD16 dstY,
++                           BoxPtr dstBox,
 +                           CARD8 xscaler,
 +                           CARD8 yscaler)
 +{
 +    ScreenPtr pScreen = screen->pScreen;
 +    KdScreenPriv(pScreen);
 +    W100CardInfo(pScreenPriv);
-+    CARD16 x, y, w, h, sw, sh;
 +    Bool hasXForm = FALSE;
 +    dp_datatype_u dp_datatype;
 +    dp_mix_u dp_mix;
 +    dst_width_height_u dst_width_height;
 +    int firstStage = 10;
 +    int secondStage = 10;
-+
-+    DBG_IMAGEON(("W100StretchBlt(randr:%d,bpp:%d,srcOffset:0x%08x,"
-+                 "srcW:%d,srcH:%d,srcPitch:%d,dstOffset:0x%08x,"
-+                 "dstPitch:%d,dstX:%d,dstY:%d,xscaler:%d,yscaler:%d)\n",
-+                 randr, bpp, srcOffset, srcW, srcH, 
-+                 srcPitch, dstOffset, dstPitch, 
-+                 dstX, dstY, xscaler, yscaler));
++    CARD16 dx, dy, sw, sh, dw, dh;
++    BoxRec dst;
++
++    DBG_IMAGEON(("W100StretchBlt(randr:%d,bpp:%d,"
++                 "src(x1:%d,y1:%d,x2:%d,y2:%d,pitch:%d,offset:%d),"
++                 "dst(x1:%d,y1:%d,x2:%d,y2:%d,pitch:%d,offset:%d),"
++                 "xscaler:%d,yscaler:%d)\n",
++                 randr, bpp,
++                 srcBox->x1, srcBox->y1, srcBox->x2, srcBox->y2, 
++                 srcPitch, srcOffset,
++                 dstBox->x1, dstBox->y1, dstBox->x2, dstBox->y2, 
++                 dstPitch, dstOffset,
++                 xscaler, yscaler));
++
++    sw = W100ApplyScaler(srcBox->x2 - srcBox->x1 + 1, xscaler);
++    sh = W100ApplyScaler(srcBox->y2 - srcBox->y1 + 1, yscaler);
 +
 +    if (randr & (RR_Rotate_90|RR_Rotate_270)) {
 +        hasXForm = TRUE;
 +        eng_cntl.f.dis_src_uses_dst_dirmaj = 1;
 +        ++firstStage;
 +        ++secondStage;
++        dh = sw;
++        dw = sh;
++    } else {
++        dh = sh;
++        dw = sw;
 +    }
 +
++    dst.x1 = dstBox->x1;
++    dst.y1 = dstBox->y1;
++    dst.x2 = dst.x1 + dw - 1;
++    dst.y2 = dst.y1 + dh - 1;
++
 +    W100ResetContext(w100c);
 +    W100SetRotation(w100c, randr, FALSE);
 +    W100SetSource(screen, srcPitch, srcOffset, bpp);
 +    W100SetDestination(screen, dstPitch, dstOffset, bpp);
++    W100TrajectoryOrigin(w100c, &dst, &dx, &dy);
 +
 +    src_inc.val = 0;
 +    src_inc.f.src_xinc = xscaler;
 +    e2.f.srcblend = E2_SRCBLEND_ZERO;
 +    e2.f.dstblend = E2_DSTBLEND_ZERO;
 +
-+    sw = W100ApplyScaler(srcW, xscaler);
-+    sh = W100ApplyScaler(srcH, yscaler);
-+
-+    x = W100XformX(w100c, dstX, dstY, sw, sh);
-+    y = W100XformY(w100c, dstX, dstY, sw, sh);
-+    w = W100XformW(w100c, dstX, dstY, sw, sh);
-+    h = W100XformH(w100c, dstX, dstY, sw, sh);
-+
-+    src_x_y.f.src_y = 0;
-+    src_x_y.f.src_x = 0;
-+    dst_x_y.f.dst_x = x;
-+    dst_x_y.f.dst_y = y;
++    src_x_y.f.src_x = srcBox->x1;
++    src_x_y.f.src_y = srcBox->y1;
++    dst_x_y.f.dst_x = dx;
++    dst_x_y.f.dst_y = dy;
 +    src_width.f.src_width = sw + 1;
 +    src_height.f.src_height = sh;
-+    dst_width_height.f.dst_height = h;
-+    dst_width_height.f.dst_width_b0 = w & 0xff;
-+    dst_width_height.f.dst_width_b1 = (w >> 8) & 0x3f;
++    dst_width_height.f.dst_height = dh;
++    dst_width_height.f.dst_width_b0 = dw & 0xff;
++    dst_width_height.f.dst_width_b1 = (dw >> 8) & 0x3f;
 +
 +
 +    if (W100WaitCmdFifoEntries(w100c, firstStage)) {
 +                          int randr,
 +                          int bpp,
 +                          CARD32 srcOffset,
-+                          CARD16 srcW,
-+                          CARD16 srcH,
 +                          CARD16 srcPitch,
++                          BoxPtr srcBox,
 +                          CARD32 dstOffset,
 +                          CARD16 dstPitch,
-+                          CARD16 dstX,
-+                          CARD16 dstY,
++                          BoxPtr dstBox,
 +                          CARD8 xscaler,
 +                          CARD8 yscaler)
 +{
 +    ScreenPtr pScreen = screen->pScreen;
 +    KdScreenPriv(pScreen);
 +    W100CardInfo(pScreenPriv);
-+    CARD16 x, y, w, h, sw, sh;
 +    Bool hasXForm = FALSE;
 +    dp_datatype_u dp_datatype;
 +    dp_mix_u dp_mix;
 +    dst_width_height_u dst_width_height;
 +    int firstStage = 11;
 +    int secondStage = 11;
-+
-+    DBG_IMAGEON(("W100ScaledBlt(randr:%d,bpp:%d,srcOffset:0x%08x,"
-+                 "srcW:%d,srcH:%d,srcPitch:%d,dstOffset:0x%08x,"
-+                 "dstPitch:%d,dstX:%d,dstY:%d,xscaler:%d,yscaler:%d)\n",
-+                 randr, bpp, srcOffset, srcW, srcH, 
-+                 srcPitch, dstOffset, dstPitch, 
-+                 dstX, dstY, xscaler, yscaler));
-+
++    CARD16 dx, dy, sw, sh, dw, dh;
++    BoxRec dst;
++
++    DBG_IMAGEON(("W100ScaledBlt(randr:%d,bpp:%d,"
++                 "src(x1:%d,y1:%d,x2:%d,y2:%d,pitch:%d,offset:%d),"
++                 "dst(x1:%d,y1:%d,x2:%d,y2:%d,pitch:%d,offset:%d),"
++                 "xscaler:%d,yscaler:%d)\n",
++                 randr, bpp,
++                 srcBox->x1, srcBox->y1, srcBox->x2, srcBox->y2, 
++                 srcPitch, srcOffset,
++                 dstBox->x1, dstBox->y1, dstBox->x2, dstBox->y2, 
++                 dstPitch, dstOffset,
++                 xscaler, yscaler));
++
++    sw = W100ApplyScaler(srcBox->x2 - srcBox->x1 + 1, xscaler);
++    sh = W100ApplyScaler(srcBox->y2 - srcBox->y1 + 1, yscaler);
++    
 +    if (randr & (RR_Rotate_90|RR_Rotate_270)) {
 +        hasXForm = TRUE;
 +        eng_cntl.val = w100c->regs.ENG_CNTL;
 +        eng_cntl.f.dis_src_uses_dst_dirmaj = 1;
 +        ++firstStage;
 +        ++secondStage;
++        dh = sw;
++        dw = sh;
++    } else {
++        dh = sh;
++        dw = sw;
 +    }
 +
++    dst.x1 = dstBox->x1;
++    dst.y1 = dstBox->y1;
++    dst.x2 = dst.x1 + dw - 1;
++    dst.y2 = dst.y1 + dh - 1;
++
 +    W100ResetContext(w100c);
 +    W100SetRotation(w100c, randr, FALSE);
 +    W100SetSource(screen, srcPitch, srcOffset, bpp);
 +    W100SetDestination(screen, dstPitch, dstOffset, bpp);
++    W100TrajectoryOrigin(w100c, &dst, &dx, &dy);
++
++    DBG_IMAGEON(("Corrected dst(x1:%d,y1:%d,x2:%d,y2:%d). Origin(%d,%d)\n",
++                 dst.x1, dst.y1, dst.x2, dst.y2,
++                 dx, dy));
 +
 +    src_inc.val = 0;
 +    src_inc.f.src_xinc = xscaler;
 +    e2.f.srcblend = E2_SRCBLEND_ZERO;
 +    e2.f.dstblend = E2_DSTBLEND_ZERO;
 +
-+    sw = W100ApplyScaler(srcW, xscaler);
-+    sh = W100ApplyScaler(srcH, yscaler);
-+
-+    x = W100XformX(w100c, dstX, dstY, sw, sh);
-+    y = W100XformY(w100c, dstX, dstY, sw, sh);
-+    w = W100XformW(w100c, dstX, dstY, sw, sh);
-+    h = W100XformH(w100c, dstX, dstY, sw, sh);
 +
-+    src_x_y.f.src_y = 0;
-+    src_x_y.f.src_x = 0;
-+    src2_x_y.f.src_y = 0 + 4;
-+    src2_x_y.f.src_x = 0;
-+    dst_x_y.f.dst_x = x;
-+    dst_x_y.f.dst_y = y;
++    src_x_y.f.src_x = srcBox->x1;
++    src_x_y.f.src_y = srcBox->y1;
++    src2_x_y.f.src_x = srcBox->x1;
++    src2_x_y.f.src_y = srcBox->y1 + 4;
++    dst_x_y.f.dst_x = dx;
++    dst_x_y.f.dst_y = dy;
 +    src_width.f.src_width = sw + 1;
 +    src_height.f.src_height = sh;
-+    dst_width_height.f.dst_height = h;
-+    dst_width_height.f.dst_width_b0 = w & 0xff;
-+    dst_width_height.f.dst_width_b1 = (w >> 8) & 0x3f;
++    dst_width_height.f.dst_height = dh;
++    dst_width_height.f.dst_width_b0 = dw & 0xff;
++    dst_width_height.f.dst_width_b1 = (dw >> 8) & 0x3f;
 +
 +    if (W100WaitCmdFifoEntries(w100c, firstStage)) {
 +        /* Set Source */
 +}
 +
 +void W100PlanarBlt(KdScreenInfo *screen,
-+                   int planes,
-+                   int bpp,
-+                   int randr,
++                   int planes, int planeOffsets[],
++                   int bpp, int randr,
 +                   KdOffscreenArea *src,
 +                   int srcW,
-+                   int srcPitch,
 +                   int srcH,
++                   BoxPtr srcBox,
 +                   KdOffscreenArea *dst,
-+                   int planeOffsets[],
 +                   int dstW,
-+                   int dstPitch,
 +                   int dstH,
-+                   int dstX,
-+                   int dstY)
++                   BoxPtr dstBox)
 +{
 +    ScreenPtr pScreen = screen->pScreen;
 +    KdScreenPriv(pScreen);
 +    W100CardInfo(pScreenPriv);
 +    W100ScreenInfo(pScreenPriv);
++
++    CARD16 dstBoxW, dstBoxH, srcBoxW, srcBoxH;
 +    CARD8 *srcOffset, *dstBase, *dstOffset;
-+    int xoffs, yoffs;
++    int xerror, yerror;
 +    unsigned int subsampling[] = {0, 1, 1};
 +    int plane;
-+    int stretch = ((srcW != dstW) || (srcH != dstH));
++    srcBoxW = srcBox->x2 - srcBox->x1 + 1;
++    srcBoxH = srcBox->y2 - srcBox->y1 + 1;
++    if (randr & (RR_Rotate_90 | RR_Rotate_270)) {
++        dstBoxW = dstBox->y2 - dstBox->y1 + 1;
++        dstBoxH = dstBox->x2 - dstBox->x1 + 1;
++    } else {
++        dstBoxW = dstBox->x2 - dstBox->x1 + 1;
++        dstBoxH = dstBox->y2 - dstBox->y1 + 1;
++    }
++
++    Bool stretch = ((srcBoxW != dstBoxW) || (srcBoxH != dstBoxH));
 +    CARD8 xscaler, yscaler;
++    BoxRec dstb = *dstBox;
 +
 +    DBG_IMAGEON(("W100PlanarBlt(planes:%d,bpp:%d,randr:%d,"
-+                 "src(w:%d,pitch:%d,h:%d),"
-+                 "dst(w:%d,pitch:%d,h:%d,x:%d,y:%d)\n",
++                 "src(x1:%d,y1:%d,x2:%d,y2:%d,w:%d,h:%d),"
++                 "dst(x1:%d,y1:%d,x2:%d,y2:%d,w:%d,h:%d)\n",
 +                 planes, bpp, randr,
-+                 srcW, srcPitch, srcH,
-+                 dstW, dstPitch, dstH, dstX, dstY));
++                 srcBox->x1, srcBox->y1, srcBox->x2, srcBox->y2, srcW, srcH,
++                 dstBox->x1, dstBox->y1, dstBox->x2, dstBox->y2, dstW, dstH));
 +
++    xerror = yerror = 0;
 +    if (stretch) {
-+        xscaler = W100GetScaler(dstW, srcW);
-+        yscaler = W100GetScaler(dstH, srcH);
-+        xoffs = yoffs = 0;
++        xscaler = W100GetScaler(dstBoxW, srcBoxW);
++        yscaler = W100GetScaler(dstBoxH, srcBoxH);
 +        if (xscaler != 16 || yscaler != 16) {
-+            xoffs = (dstW - W100ApplyScaler(srcW, xscaler)) / 2;
-+            yoffs = (dstH - W100ApplyScaler(srcH, yscaler)) / 2;
++            xerror = (dstBoxW - W100ApplyScaler(srcBoxW, xscaler)) / 2;
++            yerror = (dstBoxH - W100ApplyScaler(srcBoxH, yscaler)) / 2;
 +            DBG_IMAGEON(("Stretching with xscaler:%d,yscaler:%d,"
-+                         "xoffs:%d,yoffs:%d\n", 
-+                         xscaler, yscaler, xoffs, yoffs));
++                         "xerror:%d,yerror:%d\n", 
++                         xscaler, yscaler, xerror, yerror));
 +        } else {
-+            xoffs = yoffs = 0;
++            xerror = yerror = 0;
 +            stretch = FALSE;
 +        }
 +    }
 +
++    W100MoveTo(&dstb, xerror, yerror);
++
 +    srcOffset = src->vidmem->base + src->offset;
 +    dstBase = dst->vidmem->base + dst->offset;
 +    for (plane = 0; plane < planes; plane++) {
++        BoxRec srcCBox;
++        BoxRec dstCBox;
 +        dstOffset = dstBase + planeOffsets[plane];
++        W100ScaleBox(srcBox, &srcCBox, -subsampling[plane]);
++        W100ScaleBox(&dstb, &dstCBox, -subsampling[plane]);
 +        if (stretch) {
 +            W100ScaledBlt(screen, randr, bpp,
 +                          (CARD32) srcOffset,
 +                          srcW           >> subsampling[plane],
-+                          srcH           >> subsampling[plane],
-+                          srcPitch       >> subsampling[plane],
++                          &srcCBox,
 +                          (CARD32) dstOffset,
-+                          dstPitch       >> subsampling[plane],
-+                          (dstX + xoffs) >> subsampling[plane], 
-+                          (dstY + yoffs) >> subsampling[plane],
++                          dstW           >> subsampling[plane],
++                          &dstCBox,
 +                          xscaler, yscaler);
 +        } else {
 +            W100Blt(screen, randr, bpp,
 +                    (CARD32) srcOffset,
 +                    srcW     >> subsampling[plane],
-+                    srcH     >> subsampling[plane],
-+                    srcPitch >> subsampling[plane],
++                    &srcCBox,
 +                    (CARD32) dstOffset,
-+                    dstPitch >> subsampling[plane],
-+                    dstX     >> subsampling[plane], 
-+                    dstY     >> subsampling[plane]);
++                    dstW     >> subsampling[plane],
++                    &dstCBox);
 +        }
-+        srcOffset += (srcPitch * srcH) >> (subsampling[plane] * 2);
++        srcOffset += (srcW * srcH) >> (subsampling[plane] * 2);
 +    }
 +}
 +
 +        *y >>= 1;
 +    }
 +}
-+        
++  
++void W100VSync(W100CardInfo *w100c)
++{
++    int timeout = 30000;  /* VSync timeout = 30[ms] > 16.8[ms] */
++    active_v_disp_u active_v_disp;
++    disp_int_cntl_u disp_int_cntl;
++    gen_int_cntl_u gen_int_cntl;
++    gen_int_status_wr_u gen_int_status;
++
++    active_v_disp.val = MMIO_IN32(mmACTIVE_V_DISP);
++
++    /*set vline pos */
++    disp_int_cntl.val = 0;
++    disp_int_cntl.f.vline_int_pos = active_v_disp.f.active_v_end;
++    MMIO_OUT32(mmDISP_INT_CNTL, disp_int_cntl.val);
++
++    /* disable vline irq */
++    gen_int_cntl.val = MMIO_IN32(mmGEN_INT_CNTL);
++    gen_int_cntl.f.crtc_vline_mask = 0;
++    MMIO_OUT32(mmGEN_INT_CNTL, gen_int_cntl.val);
++
++    /* clear vline irq status */
++    gen_int_status.val = 0;
++    gen_int_status.f.crtc_vline_stat_ak = 1;
++    MMIO_OUT32(mmGEN_INT_STATUS, gen_int_status.val);
++
++    /* enable vline irq */
++    gen_int_cntl.f.crtc_vline_mask = 1;
++    MMIO_OUT32(gen_int_cntl.val, mmGEN_INT_CNTL);
++
++    /* clear vline irq status */
++    MMIO_OUT32(mmGEN_INT_STATUS, gen_int_status.val);
++
++    while (timeout > 0) {
++        if (MMIO_IN32(mmGEN_INT_STATUS) & 0x00000002) {
++            break;
++        }
++        usleep(1);
++        timeout--;
++    }
++
++    /* disable vline irq */
++    gen_int_cntl.f.crtc_vline_mask = 0;
++    MMIO_OUT32(mmGEN_INT_CNTL, gen_int_cntl.val);
++
++    /* clear vline irq status */
++    MMIO_OUT32(mmGEN_INT_STATUS, gen_int_status.val);
++}
++      
 +        
 --- /dev/null
 +++ xorg-server-X11R7.1-1.1.0.work/hw/kdrive/imageon/imageon_video.c
-@@ -0,0 +1,1051 @@
+@@ -0,0 +1,1170 @@
 +/*
 + * Copyright © 2007 Manuel Teira
 + *
 +static struct {
 +    CARD8 xfactor;
 +    CARD8 yfactor;
-+} ovlResizers[10] = {
-+    { 0, 0 },
-+    { 1, 0 },
-+    { 0, 1 },
-+    { 1, 1 },
-+    { 2, 1 },
-+    { 1, 2 },
-+    { 2, 2 },
-+    { 3, 2 },
-+    { 2, 3 },
-+    { 3, 3 }
++} ovlResizers[NUM_OVL_RESIZERS] = {
++    { 0, 0 }, 
++    { 0, 1 }, { 1, 0 }, { 1, 1 }, 
++    { 1, 2 }, { 2, 1 }, { 2, 2 }, 
++    { 2, 3 }, { 3, 2 }, { 3, 3 }
 +};
 +
++static int W100SurfaceSize(W100PortPrivPtr port, short w, short h)
++{
++    int size = 0;
++    DBG_IMAGEON(("W100SurfaceSize for id=%08x, w=%d, h=%d\n", 
++                 port->src.id, w, h));
++
++    switch (port->src.id) {
++    case FOURCC_YV12:
++    case FOURCC_I420:
++        size = (3 * w * h) / 2;
++        break;
++    case FOURCC_UYVY:
++    case FOURCC_YUY2:
++        size = w * h * 2;
++        break;
++    }
++    return size;
++}
++
 +static void W100ClearSurface(KdScreenInfo *screen, 
 +                             KdOffscreenArea *area,
 +                             CARD16 x,
 +{
 +    W100ScreenInfo *w100s = screen->driver;
 +    W100CardInfo(screen);
-+    W100PortPrivPtr pPortPriv = w100s->pAdaptor->pPortPrivates[0].ptr;
-+
++    W100PortPrivPtr port = w100s->pAdaptor->pPortPrivates[0].ptr;
++    CARD16 w, h, pitch;
 +    video_ctrl_u     video_ctrl;
 +    video_y_offset_u video_y_offset;
 +    video_y_pitch_u  video_y_pitch;
 +    graphic_h_disp_u graphic_h_disp;
 +    graphic_v_disp_u graphic_v_disp;
 +
-+    CARD16 w, h;
++    w = pitch = port->ovl.frame.x2 - port->ovl.frame.x1 + 1;
++    h = port->ovl.frame.y2 - port->ovl.frame.y1 + 1;
 +
-+    DBG_IMAGEON(("W100OverlaySetup(ovlX:%d,ovlY:%d,ovlWidth:%d,ovlHeight:%d,"
-+                 "videoHorExp:%d,videoVerExp:%d,YPlane:0x%08x,UPlane:0x%08x,"
-+                 "VPlane:0x%08x)\n",
-+                 pPortPriv->ovlX, pPortPriv->ovlY,
-+                 pPortPriv->ovlWidth, pPortPriv->ovlHeight,
-+                 pPortPriv->videoHorExp, pPortPriv->videoVerExp,
-+                 pPortPriv->YPlaneOffset, pPortPriv->UPlaneOffset, 
-+                 pPortPriv->VPlaneOffset));
++    ErrorF("W100OverlaySetup(ovlX:%d,ovlY:%d,ovlWidth:%d,ovlHeight:%d,"
++           "videoHorExp:%d,videoVerExp:%d,YPlane:0x%08x,UPlane:0x%08x,"
++           "VPlane:0x%08x)\n",
++           port->ovl.frame.x1, port->ovl.frame.y1, w, h,
++           port->ovl.horExp, 
++           port->ovl.verExp,
++           port->planes.yplane, 
++           port->planes.uplane,
++           port->planes.vplane);
 +
-+    if (pPortPriv->videoStatus & W100_OVERLAY_CONFIGURED) {
++    if (port->videoStatus & W100_OVERLAY_CONFIGURED) {
 +        return;
 +    }
 +
-+    w = pPortPriv->ovlWidth  << pPortPriv->videoHorExp;
-+    h = pPortPriv->ovlHeight << pPortPriv->videoVerExp;
++    w <<= port->ovl.horExp;
++    h <<= port->ovl.verExp;
 +
 +    video_ctrl.val = w100c->regs.VIDEO_CTRL;
 +
 +    video_ctrl.f.video_inv_hor = 0;
 +    video_ctrl.f.video_inv_ver = 0;
 +    video_ctrl.f.yuv2rgb_option = 0;
-+    video_ctrl.f.video_hor_exp = pPortPriv->videoHorExp;
-+    video_ctrl.f.video_ver_exp = pPortPriv->videoVerExp;
++    video_ctrl.f.video_hor_exp = port->ovl.horExp;
++    video_ctrl.f.video_ver_exp = port->ovl.verExp;
 +    video_ctrl.f.video_ch_sel = 0;
 +
 +    video_ctrl.f.yuv2rgb_en = 1;
 +    //Only support this, by the moment
 +    video_ctrl.f.video_mode = OVLFORMAT_YUV420;
 +
-+    video_y_pitch.f.y_pitch = pPortPriv->ovlWidth;
-+    video_u_pitch.f.u_pitch = pPortPriv->ovlWidth >> 1;
-+    video_v_pitch.f.v_pitch = pPortPriv->ovlWidth >> 1;
 +
-+    /*
-+    video_y_offset.f.y_offset = pPortPriv->YPlaneOffset +
-+        video_y_pitch.f.y_pitch * pPortPriv->ovlY + pPortPriv->ovlX;
-+    video_u_offset.f.u_offset = pPortPriv->UPlaneOffset +
-+        video_u_pitch.f.u_pitch * pPortPriv->ovlY + (pPortPriv->ovlX / 2);
-+    video_v_offset.f.v_offset = pPortPriv->VPlaneOffset +
-+        video_v_pitch.f.v_pitch * pPortPriv->ovlY + (pPortPriv->ovlX / 2);
-+    */
++    video_y_pitch.val = 0;
++    video_u_pitch.val = 0;
++    video_v_pitch.val = 0;
++    video_y_pitch.f.y_pitch = pitch;
++    video_u_pitch.f.u_pitch = pitch >> 1;
++    video_v_pitch.f.v_pitch = pitch >> 1;
 +
-+    video_y_offset.f.y_offset = pPortPriv->YPlaneOffset;
-+    video_u_offset.f.u_offset = pPortPriv->UPlaneOffset;
-+    video_v_offset.f.v_offset = pPortPriv->VPlaneOffset;
++    video_y_offset.val = 0;
++    video_u_offset.val = 0;
++    video_v_offset.val = 0;
++    video_y_offset.f.y_offset = port->planes.yplane;
++    video_u_offset.f.u_offset = port->planes.uplane;
++    video_v_offset.f.v_offset = port->planes.vplane;
 +
 +    graphic_key.val = 0;
-+    graphic_key.f.keyer_color = pPortPriv->colorKey;
++    graphic_key.f.keyer_color = port->ovl.colorKey;
 +    graphic_key.f.keyer_mask  = 0xffffUL;
 +    video_ctrl.f.keyer_en = 1;
 +
 +    graphic_v_disp.val = w100c->regs.GRAPHIC_V_DISP;
 +
 +    video_hpos.f.video_h_start = graphic_h_disp.f.graphic_h_start 
-+        + pPortPriv->ovlX;
++        + port->ovl.frame.x1;
 +    video_hpos.f.video_h_end = video_hpos.f.video_h_start + w;
++
 +    video_vpos.f.video_v_start = graphic_v_disp.f.graphic_v_start 
-+        + pPortPriv->ovlY;
++        + port->ovl.frame.y1;
 +    video_vpos.f.video_v_end = video_vpos.f.video_v_start + h;
 +    if (video_hpos.f.video_h_end > graphic_h_disp.f.graphic_h_end) {
 +        w = graphic_h_disp.f.graphic_h_end - video_hpos.f.video_h_start;
 +
 +    W100DisableDisplayUpdate(w100c);
 +    //This need to be tuned deeply, to get an stable
-+    //overlay image
++    //overlay image:
++    //Best results seems to be present with 0x40xxxxxx
++    //But overlay surface must be located in a 8 dot multiple
 +    MMIO_OUT32(mmDISP_DEBUG2, 
-+               (w100c->regs.DISP_DEBUG2 & ~0xff000000) | 0x80000000 );
++               (w100c->regs.DISP_DEBUG2 & ~0xff000000) | 0x40000000 );
 +    MMIO_OUT32(mmGRAPHIC_KEY, graphic_key.val);
 +    MMIO_OUT32(mmVIDEO_Y_OFFSET, video_y_offset.val);
 +    MMIO_OUT32(mmVIDEO_Y_PITCH, video_y_pitch.val);
 +    MMIO_OUT32(mmVIDEO_V_POS, video_vpos.val);
 +    W100EnableDisplayUpdate(w100c);
 +
-+    pPortPriv->videoCtrl = video_ctrl.val;
-+    pPortPriv->videoStatus |= W100_OVERLAY_CONFIGURED;
++    port->videoCtrl = video_ctrl.val;
++    port->videoStatus |= W100_OVERLAY_CONFIGURED;
 +}
 +
 +static void W100OverlayEnable(KdScreenInfo *screen)
 +{
 +    W100ScreenInfo *w100s = screen->driver;
 +    W100CardInfo(screen);
-+    W100PortPrivPtr pPortPriv = w100s->pAdaptor->pPortPrivates[0].ptr;
++    W100PortPrivPtr port = w100s->pAdaptor->pPortPrivates[0].ptr;
 +    video_ctrl_u video_ctrl;
 +
-+    DBG_IMAGEON(("W100OverlayEnable()\n"));
-+
-+    if (!(pPortPriv->videoStatus & W100_OVERLAY_CONFIGURED)) {
++    if (!(port->videoStatus & W100_OVERLAY_CONFIGURED)) {
 +        W100OverlaySetup(screen);
 +    }
 +
-+    video_ctrl.val = pPortPriv->videoCtrl;
-+    video_ctrl.f.en_video_req = 1;
-+    video_ctrl.f.en_video_crtc = 1;
-+    video_ctrl.f.en_graphic_req_video = 1;
-+    W100DisableDisplayUpdate(w100c);
-+    MMIO_OUT32(mmVIDEO_CTRL, video_ctrl.val);
-+    W100EnableDisplayUpdate(w100c);
-+    pPortPriv->videoCtrl = video_ctrl.val;
-+    pPortPriv->videoStatus |= W100_OVERLAY_ON;
++    if (!(port->videoStatus & W100_OVERLAY_ON)) {
++        ErrorF("W100OverlayEnable()\n");
++        video_ctrl.val = port->videoCtrl;
++        video_ctrl.f.en_video_req = 1;
++        video_ctrl.f.en_video_crtc = 1;
++        video_ctrl.f.en_graphic_req_video = 1;
++        W100DisableDisplayUpdate(w100c);
++        MMIO_OUT32(mmVIDEO_CTRL, video_ctrl.val);
++        W100EnableDisplayUpdate(w100c);
++        port->videoCtrl = video_ctrl.val;
++        port->videoStatus |= W100_OVERLAY_ON;
++    }
 +}
 +
 +static void W100OverlayDisable(KdScreenInfo *screen)
 +{
-+    DBG_IMAGEON(("W100OverlayDisable()\n"));
++
 +    W100ScreenInfo *w100s = screen->driver;
 +    W100CardInfo(screen);
-+    W100PortPrivPtr pPortPriv = w100s->pAdaptor->pPortPrivates[0].ptr;
++    W100PortPrivPtr port = w100s->pAdaptor->pPortPrivates[0].ptr;
 +
 +    video_ctrl_u video_ctrl;
 +
-+    video_ctrl.val = pPortPriv->videoCtrl;
-+    video_ctrl.f.en_video_req = 0;
-+    video_ctrl.f.en_video_crtc = 0;
-+    video_ctrl.f.en_graphic_req_video = 0;
-+    W100DisableDisplayUpdate(w100c);
-+    MMIO_OUT32(mmVIDEO_CTRL, video_ctrl.val);
-+    W100EnableDisplayUpdate(w100c);
-+    pPortPriv->videoCtrl = video_ctrl.val;
-+    pPortPriv->videoStatus &= ~W100_OVERLAY_ON;
++    if ((port->videoStatus & W100_OVERLAY_ON)) {
++        ErrorF("W100OverlayDisable()\n");
++        video_ctrl.val = port->videoCtrl;
++        video_ctrl.f.en_video_req = 0;
++        video_ctrl.f.en_video_crtc = 0;
++        video_ctrl.f.en_graphic_req_video = 0;
++        W100DisableDisplayUpdate(w100c);
++        MMIO_OUT32(mmVIDEO_CTRL, video_ctrl.val);
++        W100EnableDisplayUpdate(w100c);
++        port->videoCtrl = video_ctrl.val;
++        port->videoStatus &= ~W100_OVERLAY_ON;
++    }
 +}
 +
 +static void W100VideoSave(ScreenPtr pScreen, KdOffscreenArea *area)
 +    KdScreenPriv(pScreen);
 +    W100CardInfo(pScreenPriv);
 +    W100ScreenInfo(pScreenPriv);
-+    W100PortPrivPtr pPortPriv = w100s->pAdaptor->pPortPrivates[0].ptr;
++    W100PortPrivPtr port = w100s->pAdaptor->pPortPrivates[0].ptr;
 +
-+    if (pPortPriv->offSurface == area) {
-+        pPortPriv->offSurface = NULL;
-+        pPortPriv->offSize = 0;
++    if (port->src.surface == area) {
++        port->src.surface = NULL;
 +    }
-+    if (pPortPriv->ovlSurface == area) {
-+        pPortPriv->ovlSurface = NULL;
-+        pPortPriv->ovlSize = 0;
++
++    if (port->ovl.surface == area) {
++        port->ovl.surface = NULL;
 +    }
 +}
 +
-+static void W100HostPlanarData(KdScreenInfo *screen,
-+                               int id,
-+                               CARD8 *src,
-+                               KdOffscreenArea *dst,
-+                               CARD32 srcPitch, CARD32 srcHeight,
-+                               CARD32 dstPitch, CARD32 dstHeight,
-+                               CARD16 srcX,     CARD16 srcY,
-+                               CARD16 dstX,     CARD16 dstY,
-+                               CARD16 w,        CARD16 h)
++static void W100SaveSurface(CARD8 *src, int size, const char *file)
 +{
++    int fd;
++    if (fd = open(file, O_WRONLY | O_CREAT | O_TRUNC,
++                  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) {
++        write(fd, (void*) src, size);
++        close(fd);
++    }
++}
++    
++static void W100HostPlanarData(KdScreenInfo *screen)
++{
++    W100ScreenInfo *w100s = screen->driver;
++    W100CardInfo(screen);
++    W100PortPrivPtr port = w100s->pAdaptor->pPortPrivates[0].ptr;
++    KdOffscreenArea *dst = port->src.surface;
++    CARD8 *src = port->src.buffer;
++    CARD16 srcPitch = port->src.width; //WARN: padding?
++    CARD16 srcHeight = port->src.height;
++    CARD16 dstPitch = port->src.box.x2 - port->src.box.x1 + 1; //WARN: padding?
++    CARD16 dstHeight = port->src.box.y2 - port->src.box.y1 + 1;
++    CARD16 srcX = port->src.box.x1;
++    CARD16 srcY = port->src.box.y1;
++    CARD16 dstX = 0;
++    CARD16 dstY = 0;
++    CARD16 w = dstPitch;
++    CARD16 h = dstHeight;
 +    CARD8 *dstBase = dst->vidmem->base + dst->offset;
 +    CARD8 *dstPtr;
 +    CARD8 *srcPtr;
 +    dstPtr = dstBase + (dstHeight * dstPitch) //Start of U Plane
 +        + (dstX >> 1)                         //X Offset
 +        + ((dstY * dstPitch) >> 2);           //Y Offset
-+    if (id == FOURCC_I420) {
++    if (port->src.id == FOURCC_I420) {
 +        srcPtr = src + (srcHeight * srcPitch) //Start of U Plane
 +            + (srcX >> 1)                     //X Offset
 +            + ((srcY * srcPitch) >> 2);       //Y Offset
 +    dstPtr = dstBase + ((5 * dstHeight * dstPitch) / 4) //Start of V Plane
 +        + (dstX >> 1)                         //X Offset
 +        + ((dstY * dstPitch) >> 2);           //Y Offset
-+    if (id == FOURCC_I420) {
++    if (port->src.id == FOURCC_I420) {
 +        srcPtr = src + ((5 * srcHeight * srcPitch) / 4) //Start of V Plane
 +            + (srcX >> 1)                               //X Offset
 +            + ((srcY * srcPitch) >> 2);                 //Y Offset
 +    }
 +}
 +
-+static void W100HostPackedData(KdScreenInfo *screen,
-+                               int id,
-+                               CARD8 *src,
-+                               KdOffscreenArea *dst,
-+                               CARD32 srcPitch,
-+                               CARD32 dstPitch,
-+                               CARD16 srcX, CARD16 srcY,
-+                               CARD16 dstX, CARD16 dstY,
-+                               CARD16 w,    CARD16 h)
++static void W100HostPackedData(KdScreenInfo *screen)
 +{
++    W100ScreenInfo *w100s = screen->driver;
++    W100CardInfo(screen);
++    W100PortPrivPtr port = w100s->pAdaptor->pPortPrivates[0].ptr;
++    KdOffscreenArea *dst = port->src.surface;
++    CARD8 *src = port->src.buffer;
++    CARD16 srcPitch = port->src.width << 1; //WARN: padding?
++    CARD16 dstPitch = (port->src.box.x2 - port->src.box.x1 + 1) << 1;
++    CARD16 srcX = port->src.box.x1;
++    CARD16 srcY = port->src.box.y1;
++    CARD16 dstX = 0;
++    CARD16 dstY = 0;
++    CARD16 w = port->src.box.x2 - port->src.box.x1 + 1;
++    CARD16 h = port->src.box.y2 - port->src.box.y1 + 1;
++ 
 +    CARD8 *dstBase = dst->vidmem->base + dst->offset;
 +    CARD8 *dstPtr = dstBase + (dstY * dstPitch) + (dstX << 1);
 +    CARD8 *srcPtr = src + (srcY + srcPitch) + (srcX << 1);
 +                 srcPitch, srcPtr, srcX, srcY,
 +                 dstPitch, dstPtr, dstX, dstY,
 +                 w, h));
-+    while(h--) {
++    while (h--) {
 +        memcpy(dstPtr, srcPtr, (w << 1)); /* 16bpp assumed */
 +        srcPtr += srcPitch;
 +        dstPtr += dstPitch;
 +static void W100StopVideo(KdScreenInfo *screen, pointer data, Bool exit)
 +{
 +    W100CardInfo(screen);
-+    W100PortPrivPtr pPriv = (W100PortPrivPtr)data;
++    W100PortPrivPtr port = (W100PortPrivPtr)data;
 +
 +    DBG_IMAGEON(("W100StopVideo(exit:%d)\n", exit));
 +
-+    REGION_EMPTY(screen->pScreen, &pPriv->clip);
++    REGION_EMPTY(screen->pScreen, &port->clip);
 +    
 +    if (exit) {
-+        if (pPriv->videoStatus & W100_OVERLAY_ON) {
++        if (port->videoStatus & W100_OVERLAY_ON) {
 +            W100OverlayDisable(screen);
 +        }
-+        if (pPriv->offSurface) {
-+            KdOffscreenFree(screen->pScreen, pPriv->offSurface);
-+            pPriv->offSurface = NULL;
-+            pPriv->offSize = 0;
++        if (port->src.surface) {
++            KdOffscreenFree(screen->pScreen, port->src.surface);
++            port->src.surface = NULL;
 +        }
-+        if (pPriv->ovlSurface) {
-+            KdOffscreenFree(screen->pScreen, pPriv->ovlSurface);
-+            pPriv->ovlSurface = NULL;
-+            pPriv->ovlSize = 0;
++
++        if (port->ovl.surface) {
++            KdOffscreenFree(screen->pScreen, port->ovl.surface);
++            port->ovl.surface = NULL;
 +        }
-+        pPriv->videoStatus &= ~W100_OVERLAY_ON;
++        port->src.id = -1; // Just to avoid cached values.
 +    } else {
-+        if (pPriv->videoStatus & W100_OVERLAY_ON) {
++        if (port->videoStatus & W100_OVERLAY_ON) {
 +            W100OverlayDisable(screen);
-+            pPriv->videoStatus &= ~W100_OVERLAY_ON;
 +        }
 +    }
 +}
 +                                pointer data)
 +{
 +    W100CardInfo(screen);
-+    W100PortPrivPtr pPriv = (W100PortPrivPtr)data;
++    W100PortPrivPtr port = (W100PortPrivPtr)data;
 +
 +    if (attribute == xvBrightness) {
 +        DBG_IMAGEON(("Setting Brightness attribute to %d\n", value));
 +        W100SetBrightness(w100c, value);
-+        pPriv->brightness = value;
++        port->ovl.brightness = value;
 +    } else if (attribute == xvMaxOverlaySize) {
 +        DBG_IMAGEON(("Setting MaxOverlaySize to %d\n", value));
-+        pPriv->maxOverlaySize = value;
++        port->ovl.maxSize = value;
 +    } else if (attribute == xvColorKey) {
 +        DBG_IMAGEON(("Setting ColorKey attribute to %d\n", value));
-+        pPriv->colorKey = value;
++        port->ovl.colorKey = value;
 +    }
 +    return Success;
 +}
 +                                pointer data)
 +{
 +    W100CardInfo(screen);
-+    W100PortPrivPtr pPriv = (W100PortPrivPtr)data;
++    W100PortPrivPtr port = (W100PortPrivPtr)data;
 +
 +    if (attribute == xvBrightness) {
 +        DBG_IMAGEON(("Getting Brightness attribute\n"));
-+        *value = pPriv->brightness;
++        *value = port->ovl.brightness;
 +    } else if (attribute == xvMaxOverlaySize) {
-+        *value = pPriv->maxOverlaySize;
++        *value = port->ovl.maxSize;
 +        DBG_IMAGEON(("Getting Contrast attribute\n"));
 +    } else if (attribute == xvColorKey) {
 +        DBG_IMAGEON(("Getting ColorKey attribute\n"));
-+        *value = pPriv->colorKey;
++        *value = port->ovl.colorKey;
 +    }
 +    return Success;
 +}
 +                              Bool motion,
 +                              short vid_w, short vid_h, /*Video dimensions */
 +                              short drw_w, short drw_h, /*Drawable dimensions */
-+                              unsigned int *p_w, unsigned int *p_h,
++                              unsigned int *p_w, 
++                              unsigned int *p_h,
 +                              pointer data)
 +{
 +    DBG_IMAGEON(("W100QueryBestSize(vid_w:%d,vid_h:%d,drw_w:%d,drw_h:%d)\n",
 +{
 +    int size, tmp;
 +
++    DBG_IMAGEON(("W100QueryImageAttributes(id:%d,w:%d,h:%d)\n", id, *w, *h));
++
 +    if (*w > IMAGE_MAX_WIDTH) {
 +        *w = IMAGE_MAX_WIDTH;
 +    }
 +      if (pitches) pitches[1] = pitches[2] = tmp;
 +      tmp *= (*h >> 1); 
 +      size += tmp; 
-+      if(offsets) offsets[2] = size;
++      if (offsets) offsets[2] = size;
 +      size += tmp;
 +      break;
 +        /* Packed Formats */
 +    return size;
 +}
 +
-+
-+static void W100ClipVideo(BoxPtr dst, 
-+                          INT32 *x1, 
-+                          INT32 *x2, 
-+                          INT32 *y1, 
-+                          INT32 *y2,
-+                          BoxPtr extents,
-+                          INT32 width, 
-+                          INT32 height)
++static void W100ClipVideo(BoxPtr src, BoxPtr dst, BoxPtr extents,
++                          short width, short height)
 +{
 +    INT32 vscale, hscale, delta;
-+    int diff;
++    INT32 diff, x1, x2, y1, y2;
 +
-+    hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1);
-+    vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1);
++    hscale = ((src->x2 - src->x1) << 16) / (dst->x2 - dst->x1);
++    vscale = ((src->y2 - src->y1) << 16) / (dst->y2 - dst->y1);
 +
-+    *x1 <<= 16; *x2 <<= 16;
-+    *y1 <<= 16; *y2 <<= 16;
++    x1 = src->x1 << 16;
++    x2 = src->x2 << 16;
++    y1 = src->y1 << 16;
++    y2 = src->y2 << 16;
 +
 +    diff = extents->x1 - dst->x1;
-+    if(diff > 0) {
-+      dst->x1 = extents->x1;
-+      *x1 += diff * hscale;     
++    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;     
++    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;     
++    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 (diff > 0) {
++        dst->y2 = extents->y2;
++        y2 -= diff * vscale;
 +    }
 +
-+    if(*x1 < 0) {
-+      diff =  (- *x1 + hscale - 1)/ hscale;
-+      dst->x1 += diff;
-+      *x1 += diff * hscale;
++    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;
++
++    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;
++
++    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;
++    delta = y2 - (height << 16);
++    if (delta > 0) {
++        diff = (delta + vscale - 1) / vscale;
++        dst->y2 -= diff;
++        y2 -= diff * vscale;
 +    }
-+} 
++  
++    src->x1 = x1 >> 16;
++    src->x2 = x2 >> 16;
++    src->y1 = y1 >> 16;
++    src->y2 = y2 >> 16;
++}
 +
-+static int W100PutImage(KdScreenInfo *screen, 
-+                        DrawablePtr pDraw,        /* Destination drawable */
-+                        short src_x, short src_y, /* Source coordinates   */
-+                        short drw_x, short drw_y, /* Destination coordinates */
-+                        short src_w, short src_h, /* Source rectangle to put */
-+                        short drw_w, short drw_h, /* Destination size */
-+                        int id,                   /* FOURCC id        */
-+                        unsigned char *buf,       /* Source data      */
-+                        short width,              /* Source width     */
-+                        short height,             /* Source height    */
-+                        Bool sync,                /* Sync before returning */
-+                        RegionPtr clipBoxes,
-+                        pointer data)
++static Bool W100SetOverlaySource(W100PortPrivPtr port,
++                                 unsigned char *buffer,
++                                 int id,
++                                 short src_x, short src_y,
++                                 short src_w, short src_h,
++                                 short width, short height,
++                                 short drw_x, short drw_y, 
++                                 short drw_w, short drw_h,
++                                 RegionPtr clipBoxes)
 +{
-+    ScreenPtr pScreen = screen->pScreen;
-+    KdScreenPriv(pScreen);
-+    W100CardInfo(pScreenPriv);
-+    W100ScreenInfo(pScreenPriv);
-+    W100PortPrivPtr pPortPriv = (W100PortPrivPtr)data;
-+    CARD32 baseAddr;
-+    int randr = w100c->hw_window.randr;
-+    int offWidth, offHeight;
-+    int ovlWidth, ovlHeight;
-+    int ovlX, ovlY;
-+    int dstX, dstY;
-+    int offSize;
-+    int ovlSize;
-+    int planes;
-+    int bpp;
-+    int i;
-+    INT32 x1, x2, y1, y2;
-+    BoxRec dstBox;
-+    int planeOffsets[3];
 +    
++    BoxRec srcBox, dstBox;
++    Bool changed = FALSE;
 +
-+    DBG_IMAGEON(("W100PutImage(src(x:%d,y:%d,w:%d,h:%d),"
-+                 "drw(x:%d,y:%d,w:%d,h:%d),"
-+                 "width:%d,height:%d)\n",
-+                 src_x,src_y,src_w,src_h,
-+                 drw_x,drw_y,drw_w,drw_h,
-+                 width, height));
-+
-+    /* Clip */
-+    x1 = src_x;
-+    x2 = src_x + src_w;
-+    y1 = src_y;
-+    y2 = src_y + src_h;
++    srcBox.x1 = src_x;
++    srcBox.x2 = src_x + src_w - 1;
++    srcBox.y1 = src_y;
++    srcBox.y2 = src_y + src_h - 1;
 +
 +    dstBox.x1 = drw_x;
-+    dstBox.x2 = drw_x + drw_w;
++    dstBox.x2 = drw_x + drw_w - 1;
 +    dstBox.y1 = drw_y;
-+    dstBox.y2 = drw_y + drw_h;
++    dstBox.y2 = drw_y + drw_h - 1;
 +
-+    W100ClipVideo(&dstBox, &x1, &x2, &y1, &y2, 
-+                REGION_EXTENTS(pScreen, clipBoxes), 
++    W100ClipVideo(&srcBox, &dstBox,
++                  REGION_EXTENTS(pScreen, clipBoxes),
 +                  width, height);
 +
-+    if ((x1 >= x2) || (y1 >= y2)) {
-+      return Success;
++    port->src.buffer = buffer;
++    port->ovl.changed = FALSE;
++
++    if (port->src.id != id) {
++        port->src.id = id;
++        changed = TRUE;
++        port->ovl.changed = TRUE;
++    }
++    if (port->src.box.x1 != srcBox.x1) {
++        port->src.box.x1 = srcBox.x1;
++        changed = TRUE;
++    }
++    if (port->src.box.x2 != srcBox.x2) {
++        port->src.box.x2 = srcBox.x2;
++        changed = TRUE;
++    }
++    if (port->src.box.y1 != srcBox.y1) {
++        port->src.box.y1 = srcBox.y1;
++        changed = TRUE;
++    }
++    if (port->src.box.y2 != srcBox.y2) {
++        port->src.box.y2 = srcBox.y2;
++        changed = TRUE;
++    }
++    if (port->src.width != width) {
++        port->src.width = width;
++        changed = TRUE;
++    }
++    if (port->src.height != height) {
++        port->src.height = height;
++        changed = TRUE;
 +    }
 +
-+    src_w = (x2 - x1) >> 16;
-+    src_h = (y2 - y1) >> 16;
-+    drw_w = dstBox.x2 - dstBox.x1;
-+    drw_h = dstBox.y2 - dstBox.y1;
-+    drw_x = dstBox.x1;
-+    drw_y = dstBox.y1;
-+    src_x = x1 >> 16;
-+    src_y = y1 >> 16;
-+    
-+    /* Calculate dimensions for offscren and overlay surfaces */
-+    offWidth  = src_w;
-+    offHeight = src_h;
++    if (port->dst.box.x1 != dstBox.x1) {
++        port->dst.box.x1 = dstBox.x1;
++        changed = TRUE;
++    }
++    if (port->dst.box.x2 != dstBox.x2) {
++        port->dst.box.x2 = dstBox.x2;
++        changed = TRUE;
++    }
++    if (port->dst.box.y1 != dstBox.y1) {
++        port->dst.box.y1 = dstBox.y1;
++        changed = TRUE;
++    }
++    if (port->dst.box.y2 != dstBox.y2) {
++        port->dst.box.y2 = dstBox.y2;
++        changed = TRUE;
++    }
 +
-+    ovlX = W100MapToHWX(w100c, drw_x, drw_y, drw_w, drw_h);
-+    ovlY = W100MapToHWY(w100c, drw_x, drw_y, drw_w, drw_h);
++    if (changed) {
++        port->src.size = W100SurfaceSize(port, 
++                                         srcBox.x2 - srcBox.x1 + 1,
++                                         srcBox.y2 - srcBox.y1 + 1);
++    }
++    port->changed = changed;
++    return changed;
++}
 +
-+    for (i = 0; i < NUM_OVL_RESIZERS; i++) {
-+        CARD16 candidate_w = drw_w >> ovlResizers[i].xfactor;
-+        CARD16 candidate_h = drw_h >> ovlResizers[i].yfactor;
-+        
-+        switch (randr & RR_Rotate_All) {
-+        case RR_Rotate_0:
-+            ovlWidth  = W100_ALIGN(candidate_w, OVL_W_ALIGN);
-+            ovlHeight = W100_ALIGN(candidate_h, OVL_H_ALIGN);
-+            dstX = 0;
-+            dstY = 0;
-+            pPortPriv->videoHorExp = ovlResizers[i].xfactor;
-+            pPortPriv->videoVerExp = ovlResizers[i].yfactor;
-+            break;
-+        case RR_Rotate_180:
-+            ovlWidth  = W100_ALIGN(candidate_w, OVL_W_ALIGN);
-+            ovlHeight = W100_ALIGN(candidate_h, OVL_H_ALIGN);
-+            dstX = ovlWidth  - candidate_w;
-+            dstY = ovlHeight - candidate_h;
-+            pPortPriv->videoHorExp = ovlResizers[i].xfactor;
-+            pPortPriv->videoVerExp = ovlResizers[i].yfactor;
-+            break;
-+        case RR_Rotate_90:
-+            ovlWidth  = W100_ALIGN(candidate_h, OVL_W_ALIGN);
-+            ovlHeight = W100_ALIGN(candidate_w, OVL_H_ALIGN);
-+            dstX = (ovlWidth  - candidate_h) / 2;
-+            dstY = (ovlHeight - candidate_w) / 2;
-+            pPortPriv->videoHorExp = ovlResizers[i].yfactor;
-+            pPortPriv->videoVerExp = ovlResizers[i].xfactor;
-+            break;
-+        case RR_Rotate_270:
-+            ovlWidth  = W100_ALIGN(candidate_h, OVL_W_ALIGN);
-+            ovlHeight = W100_ALIGN(candidate_w, OVL_H_ALIGN);
-+            dstX = 0;
-+            dstY = ovlHeight - candidate_w;
-+            pPortPriv->videoHorExp = ovlResizers[i].yfactor;
-+            pPortPriv->videoVerExp = ovlResizers[i].xfactor;
-+            break;
-+        }
 +
-+        /* Calculate sizes for the surfaces */
-+        switch (id) {
-+        case FOURCC_YV12:
-+        case FOURCC_I420:
-+            offSize = (3 * offWidth * offHeight) / 2;
-+            ovlSize = (3 * ovlWidth * ovlHeight) / 2;
-+            planes = 3;
-+            planeOffsets[0] = 0;
-+            planeOffsets[1] = ovlWidth * ovlHeight;
-+            planeOffsets[2] = (5 * (ovlWidth * ovlHeight)) / 4;
-+            bpp = 8;
-+            break;
-+        case FOURCC_UYVY:
-+        case FOURCC_YUY2:
-+            offSize = offWidth * offHeight * 2;
-+            ovlSize = ovlWidth * ovlHeight * 2;
-+            planes = 1;
-+            planeOffsets[0] = 0;
-+            bpp = 16;
-+            break;
-+        }
-+        if (ovlSize <= pPortPriv->maxOverlaySize) {
-+            DBG_IMAGEON(("Using %dx%d overlay surface (%d bytes). "
-+                         "Resizer(xfactor:%d,yfactor:%d)\n",
-+                         ovlWidth, ovlHeight, ovlSize,
-+                         ovlResizers[i].xfactor, ovlResizers[i].yfactor));
-+            drw_w = candidate_w;
-+            drw_h = candidate_h;
-+            break;
-+        }
++
++static int W100SetOverlaySurfaces(KdScreenInfo *screen,
++                                  short x, short y, short w, short h)
++{
++    W100ScreenInfo *w100s = screen->driver;
++    W100CardInfo(screen);
++    W100PortPrivPtr port = w100s->pAdaptor->pPortPrivates[0].ptr;
++
++    if (port->ovl.changed ||
++        (port->ovl.frame.x1 != x) ||
++        (port->ovl.frame.y1 != y) ||
++        (port->ovl.frame.x2 != (x + w - 1)) ||
++        (port->ovl.frame.y2 != (y + h - 1))) {
++
++        port->ovl.changed = TRUE;
++        port->ovl.frame.x1 = x;
++        port->ovl.frame.x2 = x + w - 1;
++        port->ovl.frame.y1 = y;
++        port->ovl.frame.y2 = y + h - 1;
++
++        W100MapToDevice(w100c, &port->dst.box, &port->ovl.box);
++        W100ChangeOrigin(&port->ovl.box,
++                         port->ovl.frame.x1, port->ovl.frame.y1);
++        port->ovl.box.x2 >>= port->ovl.horExp;
++        port->ovl.box.y2 >>= port->ovl.verExp;
++        DBG_IMAGEON(("Translated ovl.box(x1:%d,y1:%d,x2:%d,y2:%d)\n",
++                     port->ovl.box.x1, port->ovl.box.y1,
++                     port->ovl.box.x2, port->ovl.box.y2));
 +    }
 +    
-+    /* Reallocate the surfaces, if existing ones are not valid.
-+     * If overlay surface is not valid, dump both ones, to give
-+     * ovlSurface more chances to get internal memory
-+     */
-+    if (pPortPriv->ovlSurface && ovlSize != pPortPriv->ovlSize) {
-+        DBG_IMAGEON(("Freeing overlay and offscreen surfaces\n"));
-+        KdOffscreenFree(screen->pScreen, pPortPriv->ovlSurface);
-+        KdOffscreenFree(screen->pScreen, pPortPriv->offSurface);
-+        pPortPriv->ovlSurface = NULL;
-+        pPortPriv->offSurface = NULL;
-+    }
-+
-+    if (pPortPriv->offSurface && offSize != pPortPriv->offSize) {
-+        DBG_IMAGEON(("Freeing offscreen surface\n"));
-+        KdOffscreenFree(screen->pScreen, pPortPriv->offSurface);
-+        pPortPriv->offSurface = NULL;
-+    }
-+
-+    if (!pPortPriv->ovlSurface) {
-+        pPortPriv->ovlSurface = KdOffscreenAllocPrio(screen->pScreen,
-+                                                     ovlSize, 0, TRUE, 
-+                                                     W100VideoSave,
-+                                                     pPortPriv,
-+                                                     KD_VIDMEM_MAXPRIO,
-+                                                     KD_VIDMEM_MAXPRIO,
-+                                                     TRUE);
-+        if (!pPortPriv->ovlSurface) {
-+            ErrorF("Using non internal memory to overlay. "
-+                   "Expected bad performance\n");
-+            pPortPriv->ovlSurface = KdOffscreenAlloc(screen->pScreen,
-+                                                     ovlSize, 0, TRUE, 
-+                                                     W100VideoSave,
-+                                                     pPortPriv);
++    switch (port->src.id) {
++    case FOURCC_YV12:
++    case FOURCC_I420:
++        port->planes.size = 3;
++        port->planes.offset[0] = 0;
++        port->planes.offset[1] = w * h;
++        port->planes.offset[2] = (5 * (w * h)) / 4;
++        port->planes.bpp = 8;
++        break;
++    case FOURCC_UYVY:
++    case FOURCC_YUY2:
++        port->planes.size = 1;
++        port->planes.offset[0] = 0;
++        port->planes.bpp = 16;
++        break;
++    }
++
++    if (port->ovl.surface && port->ovl.size != port->ovl.surface->size) {
++        KdOffscreenFree(screen->pScreen, port->ovl.surface);
++        KdOffscreenFree(screen->pScreen, port->src.surface);
++        port->ovl.surface = NULL;
++        port->src.surface = NULL;
++    }
++    if (port->src.surface && port->src.size != port->src.surface->size) {
++        KdOffscreenFree(screen->pScreen, port->src.surface);
++        port->src.surface = NULL;
++    }
++
++    if (!port->ovl.surface) {
++        port->ovl.surface = KdOffscreenAllocPrio(screen->pScreen,
++                                                 port->ovl.size, 0, TRUE,
++                                                 W100VideoSave,
++                                                 port,
++                                                 KD_VIDMEM_MAXPRIO,
++                                                 KD_VIDMEM_MAXPRIO,
++                                                 TRUE);
++        if (!port->ovl.surface) {
++            ErrorF("Using external memory for overlay surface. "
++                   "Expect bad performance\n");
++            port->ovl.surface = KdOffscreenAlloc(screen->pScreen,
++                                                 port->ovl.size, 0, TRUE, 
++                                                 W100VideoSave,
++                                                 port);
 +        }
-+        if (!pPortPriv->ovlSurface) {
++        if (!port->ovl.surface) {
 +            ErrorF("Unable to allocate %d bytes for overlay surface\n",
-+                   ovlSize);
++                   port->ovl.size);
 +            return BadAlloc;
 +        }
-+        
-+        pPortPriv->ovlSize = ovlSize;
-+        W100ClearSurface(screen, pPortPriv->ovlSurface,
-+                         0, 0, (ovlWidth * bpp / 8),
-+                         ovlWidth, ovlHeight, id);
-+    }
-+    
-+    if (!pPortPriv->offSurface) {
-+        pPortPriv->offSurface = KdOffscreenAlloc(screen->pScreen,
-+                                                 offSize, 0, TRUE, 
-+                                                 W100VideoSave,
-+                                                 pPortPriv);
-+        if (!pPortPriv->offSurface) {
++
++        W100ClearSurface(screen, port->ovl.surface,
++                         0, 0, 
++                         (w * port->planes.bpp / 8),
++                         w, h, port->src.id);
++    }
++    if (!port->src.surface) {
++        port->src.surface = KdOffscreenAlloc(screen->pScreen,
++                                             port->src.size, 0, TRUE, 
++                                             W100VideoSave,
++                                             port);
++        if (!port->src.surface) {
 +            ErrorF("Unable to allocate %d bytes for offscreen surface\n",
-+                   offSize);
++                   port->src.size);
 +            return BadAlloc;
 +        }
-+        pPortPriv->offSize = offSize;
 +    }
 +
-+    /* Copy the data into the offscreen surface */
-+    W100WaitIdle(w100c);
++    CARD32 baseAddr = (CARD32) W100_HOST2CARD(port->ovl.surface->vidmem->base +
++                                              port->ovl.surface->offset);
 +
-+    switch (id) {
++
++    switch (port->src.id) {
 +    case FOURCC_YV12:
 +    case FOURCC_I420:
-+        W100HostPlanarData(screen,                //screen
-+                           id,                    //id
-+                           buf,                   //src
-+                           pPortPriv->offSurface, //dst
-+                           width,                 //srcPitch
-+                           height,                //srcHeight
-+                           offWidth,              //dstPitch
-+                           offHeight,             //dstHeight
-+                           src_x,                 //srcX
-+                           src_y,                 //srcY
-+                           0,                     //dstX 
-+                           0,                     //dstY
-+                           src_w,                 //w
-+                           src_h);                //h
++        port->planes.yplane = baseAddr + port->planes.offset[0];
++        port->planes.uplane = baseAddr + port->planes.offset[1];
++        port->planes.vplane = baseAddr + port->planes.offset[2];
 +        break;
 +    case FOURCC_UYVY:
 +    case FOURCC_YUY2:
-+        W100HostPackedData(screen,                //screen
-+                           id,                    //id
-+                           buf,                   //src
-+                           pPortPriv->offSurface, //dst
-+                           width << 1,            //srcPitch
-+                           offWidth << 1,         //dstPitch
-+                           src_x,                 //srcX
-+                           src_y,                 //srcY
-+                           0,                     //dstX
-+                           0,                     //dstY
-+                           src_w,                 //w
-+                           src_h);                //h
++        port->planes.yplane = baseAddr + port->planes.offset[0];
++        port->planes.uplane = 0;
++        port->planes.vplane = 0;
 +        break;
 +    }
 +
-+    /* Update cliplist */
-+    if(!REGION_EQUAL(screen->pScreen, &pPortPriv->clip, clipBoxes)) {
-+      REGION_COPY(screen->pScreen, &pPortPriv->clip, clipBoxes);
-+      KXVPaintRegion(pDraw, &pPortPriv->clip, pPortPriv->colorKey);
++    return Success;
++}
++                                   
++static int W100OvlSetup(KdScreenInfo *screen)
++{
++    W100ScreenInfo *w100s = screen->driver;
++    W100CardInfo(screen);
++    W100PortPrivPtr port = w100s->pAdaptor->pPortPrivates[0].ptr;
++    BoxRec ovlBox;
++    short x, y, w, h;
++    int i;
++
++    W100MapToDevice(w100c, &port->dst.box, &ovlBox);
++
++    x = ovlBox.x1 & ~7;
++    y = ovlBox.y1;
++
++    for (i = 0; i < NUM_OVL_RESIZERS; i++) {
++        w = (ovlBox.x2 - x + 1) >> ovlResizers[i].xfactor;
++        h = (ovlBox.y2 - y + 1) >> ovlResizers[i].yfactor;
++        DBG_IMAGEON(("Before aligning w=%d, h=%d\n", w, h));
++        w = W100_ALIGN(w, OVL_W_ALIGN);
++        h = W100_ALIGN(h, OVL_H_ALIGN);
++        DBG_IMAGEON(("Trying overlay surface (%d,%d,%d,%d)\n",
++                     x, y, w, h));
++        port->ovl.size = W100SurfaceSize(port, w, h);
++        if (port->ovl.size <= port->ovl.maxSize) {
++            ErrorF("Using (x=%d,y=%d,w=%d,h=%d) overlay surface (%d bytes). "
++                   "Resizer(xfactor:%d,yfactor:%d)\n",
++                   x, y, w, h, port->ovl.size,
++                   ovlResizers[i].xfactor, ovlResizers[i].yfactor);
++            port->ovl.horExp = ovlResizers[i].xfactor;
++            port->ovl.verExp = ovlResizers[i].yfactor;
++            return W100SetOverlaySurfaces(screen, x, y, w, h);
++        }
 +    }
++    return BadAlloc;
++}
++    
++static void W100OvlHostData(KdScreenInfo *screen)
++{
++    W100ScreenInfo *w100s = screen->driver;
++    W100CardInfo(screen);
++    W100PortPrivPtr port = w100s->pAdaptor->pPortPrivates[0].ptr;
 +
-+    /* Calculate the incard offsets for the different planes */
-+    baseAddr = (CARD32) W100_HOST2CARD(pPortPriv->ovlSurface->vidmem->base +
-+                                       pPortPriv->ovlSurface->offset);
-+    switch (id) {
++    W100WaitIdle(w100c);
++    switch (port->src.id) {
 +    case FOURCC_YV12:
 +    case FOURCC_I420:
-+        pPortPriv->YPlaneOffset = baseAddr + planeOffsets[0];
-+        pPortPriv->UPlaneOffset = baseAddr + planeOffsets[1];
-+        pPortPriv->VPlaneOffset = baseAddr + planeOffsets[2];
++        W100HostPlanarData(screen);
 +        break;
 +    case FOURCC_UYVY:
 +    case FOURCC_YUY2:
-+        pPortPriv->YPlaneOffset = baseAddr + planeOffsets[0];
-+        pPortPriv->UPlaneOffset = 0;
-+        pPortPriv->VPlaneOffset = 0;
++        W100HostPackedData(screen);
++        break;
 +    }
++}
 +
-+    DBG_IMAGEON(("Offsets(Y:0x%08x,U:0x%08x,V:0x%08x)\n",
-+                 pPortPriv->YPlaneOffset,
-+                 pPortPriv->UPlaneOffset,
-+                 pPortPriv->VPlaneOffset));
-+                
-+
-+    /* Blit from offSurface to ovlSurface taking into account
-+     * the randr needed transformation
-+     */
-+    W100DisableDisplayUpdate(w100c);
-+    W100PlanarBlt(screen, planes, bpp, randr,
-+                  pPortPriv->offSurface,
-+                  src_w, offWidth * bpp / 8, src_h,
-+                  pPortPriv->ovlSurface, planeOffsets,
-+                  drw_w, ovlWidth * bpp / 8, drw_h,
-+                  dstX, dstY);
-+    W100EnableDisplayUpdate(w100c);
++static void W100OvlBlt(KdScreenInfo *screen)
++{
++    W100ScreenInfo *w100s = screen->driver;
++    W100CardInfo(screen);
++    W100PortPrivPtr port = w100s->pAdaptor->pPortPrivates[0].ptr;
++    static int frame = 0;
++    int srcW = port->src.box.x2 - port->src.box.x1 + 1;
++    int srcH = port->src.box.y2 - port->src.box.y1 + 1;
++    int dstW = port->ovl.frame.x2 - port->ovl.frame.x1 + 1;
++    int dstH = port->ovl.frame.y2 - port->ovl.frame.y1 + 1;
++
++    DBG_IMAGEON(("ovl.box(x1:%d,y1:%d,x2:%d,y2:%d),"
++                 "src.box(x1:%d,y1:%d,x2:%d,y2:%d),"
++                 "dstW:%d, dstH:%d\n",
++                 port->ovl.box.x1, port->ovl.box.y1,
++                 port->ovl.box.x2, port->ovl.box.y2,
++                 port->src.box.x1, port->src.box.y1,
++                 port->src.box.x2, port->src.box.y2,
++                 dstW, dstH));
++
++    W100PlanarBlt(screen,                        //KdScreenInfo* screen
++                  port->planes.size,             //int planes
++                  port->planes.offset,           //int planeOffsets[]
++                  port->planes.bpp,              //int bpp
++                  w100c->hw_window.randr,        //int randr
++                  port->src.surface,             //KdOffscrenArea *src
++                  srcW,                          //int srcW
++                  srcH,                          //int srcH
++                  &port->src.box,                //BoxPtr srcBox
++                  port->ovl.surface,             //KdOffscreenArea *dst
++                  dstW,                          //int dstW
++                  dstH,                          //int dstH
++                  &port->ovl.box);               //BoxPtr dstBox
++
++#if 0
++    if (++frame == 10) {
++    W100SaveSurface(port->src.surface->vidmem->base +
++                    port->src.surface->offset, 
++                    port->src.surface->size, 
++                    "/media/card/kdrive/source.yuv");
++    W100SaveSurface(port->ovl.surface->vidmem->base +
++                    port->ovl.surface->offset, 
++                    port->ovl.surface->size, 
++                    "/media/card/kdrive/ovl.yuv");
++    exit(1);
++    }
++#endif
++}
 +
++static void W100OvlUpdate(KdScreenInfo *screen)
++{
++    W100ScreenInfo *w100s = screen->driver;
++    W100PortPrivPtr port = w100s->pAdaptor->pPortPrivates[0].ptr;
 +
-+    if ((pPortPriv->ovlWidth  != ovlWidth) ||
-+        (pPortPriv->ovlHeight != ovlHeight) ||
-+        (pPortPriv->ovlX      != ovlX) ||
-+        (pPortPriv->ovlY      != ovlY) ||
-+        (pPortPriv->id        != id)) {
-+        pPortPriv->videoStatus &= ~W100_OVERLAY_CONFIGURED;
++    if (port->videoStatus & W100_OVERLAY_ON) {
 +        W100OverlayDisable(screen);
 +    }
-+    /* Enable overlay */
-+    pPortPriv->ovlWidth = ovlWidth;
-+    pPortPriv->ovlHeight = ovlHeight;
-+    pPortPriv->ovlX = ovlX;
-+    pPortPriv->ovlY = ovlY;
-+    pPortPriv->id = id;
++    port->videoStatus &= ~W100_OVERLAY_CONFIGURED;
++
 +    W100OverlayEnable(screen);
++}
++
++static int W100PutImage(KdScreenInfo *screen, 
++                        DrawablePtr pDraw,        /* Destination drawable */
++                        short src_x, short src_y, /* Source coordinates   */
++                        short drw_x, short drw_y, /* Destination coordinates */
++                        short src_w, short src_h, /* Source rectangle to put */
++                        short drw_w, short drw_h, /* Destination size */
++                        int id,                   /* FOURCC id        */
++                        unsigned char *buffer,    /* Source data      */
++                        short width,              /* Source width     */
++                        short height,             /* Source height    */
++                        Bool sync,                /* Sync before returning */
++                        RegionPtr clipBoxes,
++                        pointer data)
++{
++    ScreenPtr pScreen = screen->pScreen;
++    KdScreenPriv(pScreen);
++    W100CardInfo(pScreenPriv);
++    W100ScreenInfo(pScreenPriv);
++    W100PortPrivPtr port = (W100PortPrivPtr) data;
++    int errCode;
++
++    DBG_IMAGEON(("W100PutImage(src(x:%d,y:%d,w:%d,h:%d),"
++                 "drw(x:%d,y:%d,w:%d,h:%d),"
++                 "width:%d,height:%d), buffer:%p)\n",
++                 src_x,src_y,src_w,src_h,
++                 drw_x,drw_y,drw_w,drw_h,
++                 width, height,
++                 buffer));
++
++    if (W100SetOverlaySource(port, buffer, id, 
++                             src_x, src_y, src_w, src_h, 
++                             width, height,
++                             drw_x, drw_y, drw_w, drw_h, 
++                             clipBoxes)) {
++        if ((errCode = W100OvlSetup(screen)) != Success) {
++            return errCode;
++        }
++    }
++    W100OvlHostData(screen);
++    /* Update cliplist */
++    if(!REGION_EQUAL(screen->pScreen, &port->clip, clipBoxes)) {
++      REGION_COPY(screen->pScreen, &port->clip, clipBoxes);
++      KXVPaintRegion(pDraw, &port->clip, port->ovl.colorKey);
++    }
 +    
++    W100OvlBlt(screen);
++
++    if (port->ovl.changed) {
++        W100OvlUpdate(screen);
++    }
 +    return Success;
 +}
-+
++    
 +static KdVideoAdaptorPtr 
 +W100SetupImageVideo(ScreenPtr pScreen)
 +{
 +    W100ScreenInfo(pScreenPriv);
 +    W100CardInfo(pScreenPriv);
 +    KdVideoAdaptorPtr adaptor;
-+    W100PortPrivPtr pPortPriv;
++    W100PortPrivPtr port;
 +
 +    adaptor = xcalloc(1, sizeof(KdVideoAdaptorRec) 
 +                      +  sizeof(W100PortPrivRec) 
 +    adaptor->nPorts = 1;
 +    adaptor->pPortPrivates = (DevUnion*)(&adaptor[1]);
 +
-+    pPortPriv = (W100PortPrivPtr)(&adaptor->pPortPrivates[1]);
++    port = (W100PortPrivPtr)(&adaptor->pPortPrivates[1]);
 +
-+    adaptor->pPortPrivates[0].ptr = (pointer)(pPortPriv);
++    adaptor->pPortPrivates[0].ptr = (pointer)(port);
 +
 +    adaptor->nAttributes = NUM_ATTRIBUTES;
 +    adaptor->pAttributes = Attributes;
 +    adaptor->ReputImage = NULL;
 +    adaptor->QueryImageAttributes = W100QueryImageAttributes;
 +
-+    REGION_INIT(pScreen, &pPortPriv->clip, NullBox, 0); 
++    REGION_INIT(pScreen, &port->clip, NullBox, 0);
 +
 +    w100s->pAdaptor = adaptor;
 +
 +    xvColorKey       = MAKE_ATOM("XV_COLORKEY");
 +    xvMaxOverlaySize = MAKE_ATOM("XV_MAXOVERLAYSIZE");
 +
-+    pPortPriv->maxOverlaySize = OVL_MAX_SIZE;
-+    pPortPriv->colorKey = 0xff00;
-+    pPortPriv->brightness = W100GetBrightness(w100c);
++    port->ovl.maxSize = OVL_MAX_SIZE;
++    port->ovl.colorKey = 0xff00;
++    port->ovl.brightness = W100GetBrightness(w100c);
 +    return adaptor;
 +}
 +
 +    KdScreenPriv(pScreen);
 +    W100ScreenInfo(pScreenPriv);
 +    KdVideoAdaptorPtr adaptor = w100s->pAdaptor;
-+    W100PortPrivPtr pPortPriv;
++    W100PortPrivPtr port;
 +    int i;
 +
 +    if (!adaptor)
 +        return;
 +
-+    pPortPriv = (W100PortPrivPtr)(&adaptor->pPortPrivates[0].ptr);
-+    REGION_UNINIT(pScreen, &pPortPriv->clip);
++    port = (W100PortPrivPtr)(&adaptor->pPortPrivates[0].ptr);
++    REGION_UNINIT(pScreen, &port->clip);
 +
 +    xfree(adaptor);
 +    w100s->pAdaptor = NULL;
 +
 --- /dev/null
 +++ xorg-server-X11R7.1-1.1.0.work/hw/kdrive/imageon/imageon_support.h
-@@ -0,0 +1,98 @@
+@@ -0,0 +1,108 @@
 +/*
 + * Copyright © 2007 Manuel Teira
 + *
 +extern CARD8 W100SolidRop[16];
 +extern CARD8 W100BltRop[16];
 +
++/* Card control */
 +void W100DisableDisplayUpdate(W100CardInfo *w100c);
 +void W100EnableDisplayUpdate(W100CardInfo *w100c);
 +void W100SetupGraphicEngine(W100CardInfo *w100c);
 +void W100SetupGraphicWindow(W100CardInfo *w100c);
 +void W100EnableGraphicWindow(W100CardInfo *w100c);
 +void W100DisableGraphicWindow(W100CardInfo *w100c);
-+inline Bool W100WaitCmdFifoEntries(W100CardInfo *w100c, int entries);
++void W100VSync(W100CardInfo *w100c);
++
++/* Wait for card slots */
++__inline__ Bool W100WaitCmdFifoEntries(W100CardInfo *w100c, int entries);
 +Bool W100WaitIdle(W100CardInfo *w100c);
++
++/* Set context of the current operation */
 +void W100ResetContext(W100CardInfo *w100c);
 +CARD32 W100ComputeSolidGmc(W100CardInfo *w100c, CARD8 alu);
 +CARD32 W100ComputeCopyGmc(W100CardInfo *w100c, CARD8 alu);
 +                        CARD32 dstOffset, CARD8 bpp);
 +Bool W100SetSourcePixmap(PixmapPtr pPix);
 +Bool W100SetDestinationPixmap(PixmapPtr pPix);
-+int W100MapToHWX(W100CardInfo *w100c, 
-+                 int x, int y, int w, int h);
-+int W100MapToHWY(W100CardInfo *w100c,
-+                 int x, int y, int w, int h);
-+int W100MapToHWW(W100CardInfo *w100c,
-+                 int x, int y, int w, int h);
-+int W100MapToHWH(W100CardInfo *w100c,
-+                 int x, int y, int w, int h);
-+CARD16 W100XformX(W100CardInfo *w100c, CARD16 x, CARD16 y, CARD16 w, CARD16 h);
-+CARD16 W100XformY(W100CardInfo *w100c, CARD16 x, CARD16 y, CARD16 w, CARD16 h);
-+CARD16 W100XformW(W100CardInfo *w100c, CARD16 x, CARD16 y, CARD16 w, CARD16 h);
-+CARD16 W100XformH(W100CardInfo *w100c, CARD16 x, CARD16 y, CARD16 w, CARD16 h);
++
++/* Scaler related functions */
 +CARD8 W100GetScaler(CARD16 dstsize, CARD16 srcsize);
 +CARD16 W100ApplyScaler(CARD16 srcsize, CARD8 scaler);
-+static void W100Blt(KdScreenInfo *screen, int randr, int bpp,
-+                    CARD32 srcOffset, CARD16 srcW, CARD16 srcH, CARD16 srcPitch,
-+                    CARD32 dstOffset, CARD16 dstPitch, 
-+                    CARD16 dstX, CARD16 dstY);
-+static void W100StretchBlt(KdScreenInfo *screen, int randr, int bpp,
-+                           CARD32 srcOffset, CARD16 srcW, CARD16 srcH,
-+                           CARD16 srcPitch,
-+                           CARD32 dstOffset, CARD16 dstPitch,
-+                           CARD16 dstX, CARD16 dstY,
-+                           CARD8 xscaler, CARD8 yscaler);
++
++/* Blitting functions */
++void W100PlanarBlt(KdScreenInfo *screen, int planes, int planeOffsets[],
++                   int bpp, int randr,
++                   KdOffscreenArea *src, int srcW, int srcH, BoxPtr srcBox,
++                   KdOffscreenArea *dst, int dstW, int dstH, BoxPtr dstBox);
 +static void W100ScaledBlt(KdScreenInfo *screen, int randr, int bpp,
-+                          CARD32 srcOffset, CARD16 srcW, CARD16 srcH,
-+                          CARD16 srcPitch,
-+                          CARD32 dstOffset, CARD16 dstPitch,
-+                          CARD16 dstX, CARD16 dstY,
++                          CARD32 srcOffset, CARD16 srcPitch, BoxPtr srcBox,
++                          CARD32 dstOffset, CARD16 dstPitch, BoxPtr dstBox,
++                          CARD8 xscaler, CARD8 yscaler);
++static void W100StretchBlt(KdScreenInfo *screen, int randr, int bpp,
++                          CARD32 srcOffset, CARD16 srcPitch, BoxPtr srcBox,
++                          CARD32 dstOffset, CARD16 dstPitch, BoxPtr dstBox,
 +                          CARD8 xscaler, CARD8 yscaler);
-+void W100PlanarBlt(KdScreenInfo *screen, int planes, int bpp, int randr,
-+                   KdOffscreenArea *src, int srcW, int srcPitch, int srcH,
-+                   KdOffscreenArea *dst, int planeOffsets[],
-+                   int dstW, int dstPitch, int dstH,
-+                   int dstX, int dstY);
++static void W100Blt(KdScreenInfo *screen, int randr, int bpp,
++                    CARD32 srcOffset, CARD16 srcPitch, BoxPtr srcBox,
++                    CARD32 dstOffset, CARD16 dstPitch, BoxPtr dstBox);
++
++/* Brightness functions */
 +CARD8 W100GetBrightness(W100CardInfo *w100c);
 +void W100SetBrightness(W100CardInfo *w100c, CARD8 value);
++
++
++/* Get and set mode and rotation info */
 +int W100GetRotation(W100CardInfo *w100c);
 +W100ModeSpec *W100GetModeSpec(W100CardInfo *w100c, W100Mode *mode);
 +Bool W100GetFbMode(W100CardInfo *w100c, W100Mode *mode);
 +Bool W100CheckFbMode(W100CardInfo *w100c, W100ModeSpec *modes);
 +W100ModeSpec *W100GetBestMode(W100CardInfo *w100c, int width, int height);
-+void W100TransformTsLibCoordinates(long *x, long *y, void *closure);
++
++/* SysFS helpers */
 +Bool W100SysFsGet(W100CardInfo *w100c, const char *path, char *value);
 +Bool W100SysFsSet(W100CardInfo *w100c, const char *path, const char *value);
++
++/* Coordinate transformations */
++void W100TransformTsLibCoordinates(long *x, long *y, void *closure);
++void W100MapToDevice(W100CardInfo *w100c, BoxPtr src, BoxPtr dst);
++void W100MapFromDevice(W100CardInfo *w100c, BoxPtr src, BoxPtr dst);
++void W100ChangeOrigin(BoxPtr src, int x, int y);
++void W100TrajectoryOrigin(W100CardInfo *w100c, BoxPtr box, short *x, short *y);
++void W100ScaleBox(BoxPtr src, BoxPtr dst, int scale);
++void W100MoveTo(BoxPtr src, int x, int y);
++
++
++
 +#endif
 --- xorg-server-X11R7.1-1.1.0.work/hw/kdrive/linux/tslib.c~kdrive-imageon
 +++ xorg-server-X11R7.1-1.1.0.work/hw/kdrive/linux/tslib.c