summaryrefslogtreecommitdiff
path: root/exa/exa.c
diff options
context:
space:
mode:
authorZack Rusin <zack@kde.org>2005-07-01 08:56:12 +0000
committerZack Rusin <zack@kde.org>2005-07-01 08:56:12 +0000
commit30c019e847adef6f7f3963df8ef1f3f994669a54 (patch)
tree5fa869c68f199f83f6fa750e74f47bf4b8fd53b6 /exa/exa.c
parent276821605ee50e71f30dd52f2c12237fc61f288f (diff)
Adding the new acceleration architecture: Exa. It's meant to replace XAA in
the coming months.
Diffstat (limited to 'exa/exa.c')
-rw-r--r--exa/exa.c1252
1 files changed, 1252 insertions, 0 deletions
diff --git a/exa/exa.c b/exa/exa.c
new file mode 100644
index 000000000..c2d0db063
--- /dev/null
+++ b/exa/exa.c
@@ -0,0 +1,1252 @@
+/*
+ * Copyright © 2001 Keith Packard
+ *
+ * Partly based on code that is Copyright © The XFree86 Project Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "exaPriv.h"
+#include "fontstruct.h"
+#include "dixfontstr.h"
+#include "xf86str.h"
+#include "xf86.h"
+#include "exa.h"
+
+#define DEBUG_MIGRATE 0
+#define DEBUG_PIXMAP 0
+#if DEBUG_MIGRATE
+#define DBG_MIGRATE(a) ErrorF a
+#else
+#define DBG_MIGRATE(a)
+#endif
+#if DEBUG_PIXMAP
+#define DBG_PIXMAP(a) ErrorF a
+#else
+#define DBG_PIXMAP(a)
+#endif
+#define STRACE
+#define TRACE
+
+int exaGeneration;
+int exaScreenPrivateIndex;
+int exaPixmapPrivateIndex;
+
+#define EXA_PIXMAP_SCORE_MOVE_IN 10
+#define EXA_PIXMAP_SCORE_MAX 20
+#define EXA_PIXMAP_SCORE_MOVE_OUT -10
+#define EXA_PIXMAP_SCORE_MIN -20
+#define EXA_PIXMAP_SCORE_PINNED 1000
+#define EXA_PIXMAP_SCORE_INIT 1001
+
+void
+exaDrawableDirty (DrawablePtr pDrawable)
+{
+ PixmapPtr pPixmap;
+ ExaPixmapPrivPtr pExaPixmap;
+
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ pPixmap = (*pDrawable->pScreen->GetWindowPixmap)((WindowPtr) pDrawable);
+ else
+ pPixmap = (PixmapPtr)pDrawable;
+
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+ if (pExaPixmap != NULL)
+ pExaPixmap->dirty = TRUE;
+}
+
+static void
+exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area)
+{
+ PixmapPtr pPixmap = area->privData;
+ ExaScreenPriv (pScreen);
+ ExaPixmapPriv(pPixmap);
+ int dst_pitch, src_pitch, bytes;
+ char *dst, *src;
+ int i;
+
+ DBG_MIGRATE (("Save 0x%08p (0x%p) (%dx%d)\n",
+ (void*)pPixmap->drawable.id,
+ (void*)(ExaGetPixmapPriv(pPixmap)->area ?
+ ExaGetPixmapPriv(pPixmap)->area->offset : 0),
+ pPixmap->drawable.width,
+ pPixmap->drawable.height));
+
+ src_pitch = pPixmap->devKind;
+ dst_pitch = pExaPixmap->devKind;
+
+ src = pPixmap->devPrivate.ptr;
+ dst = pExaPixmap->devPrivate.ptr;
+
+ if (pExaScr->info->accel.DownloadFromScreen)
+ {
+ if (pExaScr->info->accel.DownloadFromScreen(pPixmap,
+ pPixmap->drawable.x,
+ pPixmap->drawable.y,
+ pPixmap->drawable.width,
+ pPixmap->drawable.height,
+ dst,
+ dst_pitch)) {
+
+ pPixmap->devKind = dst_pitch;
+ pPixmap->devPrivate.ptr = dst;
+ pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ pExaPixmap->area = NULL;
+ return;
+ }
+ }
+
+ pPixmap->devKind = dst_pitch;
+ pPixmap->devPrivate.ptr = dst;
+ pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ pExaPixmap->area = NULL;
+
+#if 0
+ if (!pExaPixmap->dirty)
+ return;
+#endif
+
+ exaWaitSync (pPixmap->drawable.pScreen);
+
+ bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch;
+
+ i = pPixmap->drawable.height;
+ while (i--) {
+ memcpy (dst, src, bytes);
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+}
+
+static int
+exaLog2(int val)
+{
+ int bits;
+
+ if (!val)
+ return 0;
+ for (bits = 0; val != 0; bits++)
+ val >>= 1;
+ return bits - 1;
+}
+
+static Bool
+exaPixmapAllocArea (PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv (pScreen);
+ ExaPixmapPriv (pPixmap);
+ int bpp = pPixmap->drawable.bitsPerPixel;
+ CARD16 h = pPixmap->drawable.height;
+ CARD16 w = pPixmap->drawable.width;
+ int pitch;
+
+ if (pExaScr->info->card.flags & EXA_OFFSCREEN_ALIGN_POT && w != 1)
+ w = 1 << (exaLog2(w - 1) + 1);
+ pitch = (w * bpp / 8 + pExaScr->info->card.offscreenPitch - 1) &
+ ~(pExaScr->info->card.offscreenPitch - 1);
+
+ pExaPixmap->devKind = pPixmap->devKind;
+ pExaPixmap->devPrivate = pPixmap->devPrivate;
+ pExaPixmap->area = exaOffscreenAlloc (pScreen, pitch * h,
+ pExaScr->info->card.offscreenByteAlign,
+ FALSE,
+ exaPixmapSave, (pointer) pPixmap);
+ if (!pExaPixmap->area)
+ return FALSE;
+
+ DBG_PIXMAP(("++ 0x%p (0x%p) (%dx%d)\n",
+ (void*)pPixmap->drawable.id,
+ (void*)(ExaGetPixmapPriv(pPixmap)->area ?
+ ExaGetPixmapPriv(pPixmap)->area->offset : 0),
+ pPixmap->drawable.width,
+ pPixmap->drawable.height));
+ pPixmap->devKind = pitch;
+
+ pPixmap->devPrivate.ptr = (pointer) ((CARD8 *) pExaScr->info->card.memoryBase + pExaPixmap->area->offset);
+ pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ return TRUE;
+}
+
+void
+exaMoveInPixmap (PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv (pScreen);
+ ExaPixmapPriv (pPixmap);
+ int dst_pitch, src_pitch, bytes;
+ char *dst, *src;
+ int i;
+
+ DBG_MIGRATE (("-> 0x%p (0x%p) (%dx%d)\n",
+ (void*)pPixmap->drawable.id,
+ (void*)(ExaGetPixmapPriv(pPixmap)->area ?
+ ExaGetPixmapPriv(pPixmap)->area->offset : 0),
+ pPixmap->drawable.width,
+ pPixmap->drawable.height));
+
+ src = pPixmap->devPrivate.ptr;
+ src_pitch = pPixmap->devKind;
+
+ if (!exaPixmapAllocArea (pPixmap))
+ return;
+
+ pExaPixmap->dirty = FALSE;
+
+ if (pExaScr->info->accel.UploadToScreen)
+ {
+ if (pExaScr->info->accel.UploadToScreen(pPixmap, src, src_pitch))
+ return;
+ }
+
+ dst = pPixmap->devPrivate.ptr;
+ dst_pitch = pPixmap->devKind;
+
+ bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch;
+
+ exaWaitSync (pPixmap->drawable.pScreen);
+
+ i = pPixmap->drawable.height;
+ ErrorF("dst = %p, src = %p,(%d, %d) height = %d, mem_base = %p, offset = %d\n",
+ dst, src, dst_pitch, src_pitch,
+ i, pExaScr->info->card.memoryBase, ExaGetPixmapPriv(pPixmap)->area->offset);
+
+ while (i--) {
+ memcpy (dst, src, bytes);
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+ ErrorF("done\n");
+}
+
+static void
+exaMoveOutPixmap (PixmapPtr pPixmap)
+{
+ ExaPixmapPriv (pPixmap);
+ ExaOffscreenArea *area = pExaPixmap->area;
+
+ DBG_MIGRATE (("<- 0x%p (0x%p) (%dx%d)\n",
+ (void*)pPixmap->drawable.id,
+ (void*)(ExaGetPixmapPriv(pPixmap)->area ?
+ ExaGetPixmapPriv(pPixmap)->area->offset : 0),
+ pPixmap->drawable.width,
+ pPixmap->drawable.height));
+ STRACE;
+ if (area)
+ {
+ exaPixmapSave (pPixmap->drawable.pScreen, area);
+ exaOffscreenFree (pPixmap->drawable.pScreen, area);
+ }
+}
+
+void
+exaPixmapUseScreen (PixmapPtr pPixmap)
+{
+ ExaPixmapPriv (pPixmap);
+
+ STRACE;
+ if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
+ return;
+
+ if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT) {
+ exaMoveInPixmap(pPixmap);
+ pExaPixmap->score = 0;
+ }
+
+ if (pExaPixmap->score < EXA_PIXMAP_SCORE_MAX)
+ {
+ pExaPixmap->score++;
+ if (!exaPixmapIsOffscreen(pPixmap) &&
+ pExaPixmap->score >= EXA_PIXMAP_SCORE_MOVE_IN)
+ exaMoveInPixmap (pPixmap);
+ }
+ ExaOffscreenMarkUsed (pPixmap);
+}
+
+void
+exaPixmapUseMemory (PixmapPtr pPixmap)
+{
+ ExaPixmapPriv (pPixmap);
+
+ if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
+ return;
+
+ if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT)
+ pExaPixmap->score = 0;
+
+ if (pExaPixmap->score > EXA_PIXMAP_SCORE_MIN)
+ {
+ pExaPixmap->score--;
+ if (pExaPixmap->area &&
+ pExaPixmap->score <= EXA_PIXMAP_SCORE_MOVE_OUT)
+ exaMoveOutPixmap (pPixmap);
+ }
+}
+
+static Bool
+exaDestroyPixmap (PixmapPtr pPixmap)
+{
+ if (pPixmap->refcnt == 1)
+ {
+ ExaPixmapPriv (pPixmap);
+ if (pExaPixmap->area)
+ {
+ DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n",
+ (void*)pPixmap->drawable.id,
+ ExaGetPixmapPriv(pPixmap)->area->offset,
+ pPixmap->drawable.width,
+ pPixmap->drawable.height));
+ /* Free the offscreen area */
+ exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area);
+ pPixmap->devPrivate = pExaPixmap->devPrivate;
+ pPixmap->devKind = pExaPixmap->devKind;
+ }
+ }
+ return fbDestroyPixmap (pPixmap);
+}
+
+static PixmapPtr
+exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth)
+{
+ PixmapPtr pPixmap;
+ ExaPixmapPrivPtr pExaPixmap;
+ int bpp;
+
+ bpp = BitsPerPixel (depth);
+ if (bpp == 32 && depth == 24)
+ {
+ int format;
+ ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen);
+ for (format = 0; format < MAXFORMATS && pScrn->formats[format].depth; ++format)
+ if (pScrn->formats[format].depth == 24)
+ {
+ bpp = pScrn->formats[format].bitsPerPixel;
+ break;
+ }
+ }
+
+ pPixmap = fbCreatePixmapBpp (pScreen, w, h, depth, bpp);
+ if (!pPixmap)
+ return NULL;
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+ if (!w || !h)
+ pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+ else
+ pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
+
+ pExaPixmap->area = NULL;
+ pExaPixmap->dirty = FALSE;
+
+ return pPixmap;
+}
+
+Bool
+exaPixmapIsOffscreen(PixmapPtr p)
+{
+ ScreenPtr pScreen = p->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+
+ STRACE;
+ return ((unsigned long) ((CARD8 *) p->devPrivate.ptr -
+ (CARD8 *) pExaScr->info->card.memoryBase) <
+ pExaScr->info->card.memorySize);
+}
+
+PixmapPtr
+exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp)
+{
+ PixmapPtr pPixmap;
+ int x, y;
+
+ STRACE;
+ if (pDrawable->type == DRAWABLE_WINDOW) {
+ pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable);
+#ifdef COMPOSITE
+ x = -pPixmap->screen_x;
+ y = -pPixmap->screen_y;
+#else
+ x = 0;
+ y = 0;
+#endif
+ }
+ else
+ {
+ pPixmap = (PixmapPtr) pDrawable;
+ x = 0;
+ y = 0;
+ }
+ *xp = x;
+ *yp = y;
+ if (exaPixmapIsOffscreen (pPixmap))
+ return pPixmap;
+ else
+ return NULL;
+}
+
+Bool
+exaDrawableIsOffscreen (DrawablePtr pDrawable)
+{
+ PixmapPtr pPixmap;
+ STRACE;
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable);
+ else
+ pPixmap = (PixmapPtr) pDrawable;
+ return exaPixmapIsOffscreen (pPixmap);
+}
+
+#if 0
+static void
+exaFillTiled(int dst_x,
+ int dst_y,
+ int width,
+ int height,
+ int src_x,
+ int src_y,
+ int src_width,
+ int src_height,
+ void (*Copy) (int srcX,
+ int srcY,
+ int dstX,
+ int dstY,
+ int width,
+ int height))
+{
+ modulus (src_x, src_width, src_x);
+ modulus (src_y, src_height, src_y);
+
+ while (height)
+ {
+ int dst_x_tmp = dst_x;
+ int src_x_tmp = src_x;
+ int width_tmp = width;
+ int height_left = src_height - src_y;
+ int height_this = min (height, height_left);
+
+ while (width_tmp)
+ {
+ int width_left = src_width - src_x_tmp;
+ int width_this = min (width_tmp, width_left);
+
+ (*Copy) (src_x_tmp, src_y,
+ dst_x_tmp, dst_y,
+ width_this, height_this);
+
+ width_tmp -= width_this;
+ dst_x_tmp += width_this;
+ }
+ height -= height_this;
+ dst_y += height_this;
+ src_y = 0;
+ }
+}
+#endif
+
+static void
+exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
+ DDXPointPtr ppt, int *pwidth, int fSorted)
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ ExaScreenPriv (pScreen);
+ RegionPtr pClip = fbGetCompositeClip(pGC);
+ PixmapPtr pPixmap;
+ BoxPtr pextent, pbox;
+ int nbox;
+ int extentX1, extentX2, extentY1, extentY2;
+ int fullX1, fullX2, fullY1;
+ int partX1, partX2;
+ int off_x, off_y;
+
+ STRACE;
+ if (pGC->fillStyle != FillSolid ||
+ !(pPixmap = exaGetOffscreenPixmap (pDrawable, &off_x, &off_y)) ||
+ !(*pExaScr->info->accel.PrepareSolid) (pPixmap,
+ pGC->alu,
+ pGC->planemask,
+ pGC->fgPixel))
+ {
+ ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
+ return;
+ }
+
+ pextent = REGION_EXTENTS(pGC->pScreen, pClip);
+ extentX1 = pextent->x1;
+ extentY1 = pextent->y1;
+ extentX2 = pextent->x2;
+ extentY2 = pextent->y2;
+ while (n--)
+ {
+ fullX1 = ppt->x;
+ fullY1 = ppt->y;
+ fullX2 = fullX1 + (int) *pwidth;
+ ppt++;
+ pwidth++;
+
+ if (fullY1 < extentY1 || extentY2 <= fullY1)
+ continue;
+
+ if (fullX1 < extentX1)
+ fullX1 = extentX1;
+
+ if (fullX2 > extentX2)
+ fullX2 = extentX2;
+
+ if (fullX1 >= fullX2)
+ continue;
+
+ nbox = REGION_NUM_RECTS (pClip);
+ if (nbox == 1)
+ {
+ (*pExaScr->info->accel.Solid) (pPixmap,
+ fullX1 + off_x, fullY1 + off_y,
+ fullX2 + off_x, fullY1 + 1 + off_y);
+ }
+ else
+ {
+ pbox = REGION_RECTS(pClip);
+ while(nbox--)
+ {
+ if (pbox->y1 <= fullY1 && fullY1 < pbox->y2)
+ {
+ partX1 = pbox->x1;
+ if (partX1 < fullX1)
+ partX1 = fullX1;
+ partX2 = pbox->x2;
+ if (partX2 > fullX2)
+ partX2 = fullX2;
+ if (partX2 > partX1)
+ (*pExaScr->info->accel.Solid) (pPixmap,
+ partX1 + off_x, fullY1 + off_y,
+ partX2 + off_x, fullY1 + 1 + off_y);
+ }
+ pbox++;
+ }
+ }
+ }
+ (*pExaScr->info->accel.DoneSolid) (pPixmap);
+ exaDrawableDirty (pDrawable);
+ exaMarkSync(pScreen);
+}
+
+void
+exaCopyNtoN (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown,
+ Pixel bitplane,
+ void *closure)
+{
+ ExaScreenPriv (pDstDrawable->pScreen);
+ PixmapPtr pSrcPixmap, pDstPixmap;
+ int src_off_x, src_off_y;
+ int dst_off_x, dst_off_y;
+ STRACE;
+
+ /* Migrate pixmaps to same place as destination */
+ if (pSrcDrawable->type == DRAWABLE_PIXMAP) {
+ if (exaDrawableIsOffscreen (pDstDrawable))
+ exaPixmapUseScreen ((PixmapPtr) pSrcDrawable);
+ else
+ exaPixmapUseMemory ((PixmapPtr) pSrcDrawable);
+ }
+
+ if ((pSrcPixmap = exaGetOffscreenPixmap (pSrcDrawable, &src_off_x, &src_off_y)) &&
+ (pDstPixmap = exaGetOffscreenPixmap (pDstDrawable, &dst_off_x, &dst_off_y)) &&
+ (*pExaScr->info->accel.PrepareCopy) (pSrcPixmap,
+ pDstPixmap,
+ dx,
+ dy,
+ pGC ? pGC->alu : GXcopy,
+ pGC ? pGC->planemask : FB_ALLONES))
+ {
+ while (nbox--)
+ {
+ (*pExaScr->info->accel.Copy) (pDstPixmap,
+ pbox->x1 + dx + src_off_x,
+ pbox->y1 + dy + src_off_y,
+ pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+ pbox++;
+ }
+ (*pExaScr->info->accel.DoneCopy) (pDstPixmap);
+ exaMarkSync(pDstDrawable->pScreen);
+ }
+ else
+ {
+ exaWaitSync (pDstDrawable->pScreen);
+ fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC,
+ pbox, nbox, dx, dy, reverse, upsidedown,
+ bitplane, closure);
+ }
+ exaDrawableDirty (pDstDrawable);
+}
+
+static RegionPtr
+exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height, int dstx, int dsty)
+{
+ return fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height,
+ dstx, dsty, exaCopyNtoN, 0, 0);
+}
+
+static void
+exaPolyFillRect(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int nrect,
+ xRectangle *prect)
+{
+ ExaScreenPriv (pDrawable->pScreen);
+ RegionPtr pClip = fbGetCompositeClip(pGC);
+ PixmapPtr pPixmap;
+ register BoxPtr pbox;
+ BoxPtr pextent;
+ int extentX1, extentX2, extentY1, extentY2;
+ int fullX1, fullX2, fullY1, fullY2;
+ int partX1, partX2, partY1, partY2;
+ int xoff, yoff;
+ int xorg, yorg;
+ int n;
+
+ STRACE;
+ if (pGC->fillStyle != FillSolid ||
+ !(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) ||
+ !(*pExaScr->info->accel.PrepareSolid) (pPixmap,
+ pGC->alu,
+ pGC->planemask,
+ pGC->fgPixel))
+ {
+ ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect);
+ return;
+ }
+
+ xorg = pDrawable->x;
+ yorg = pDrawable->y;
+
+ pextent = REGION_EXTENTS(pGC->pScreen, pClip);
+ extentX1 = pextent->x1;
+ extentY1 = pextent->y1;
+ extentX2 = pextent->x2;
+ extentY2 = pextent->y2;
+ while (nrect--)
+ {
+ fullX1 = prect->x + xorg;
+ fullY1 = prect->y + yorg;
+ fullX2 = fullX1 + (int) prect->width;
+ fullY2 = fullY1 + (int) prect->height;
+ prect++;
+
+ if (fullX1 < extentX1)
+ fullX1 = extentX1;
+
+ if (fullY1 < extentY1)
+ fullY1 = extentY1;
+
+ if (fullX2 > extentX2)
+ fullX2 = extentX2;
+
+ if (fullY2 > extentY2)
+ fullY2 = extentY2;
+
+ if ((fullX1 >= fullX2) || (fullY1 >= fullY2))
+ continue;
+ n = REGION_NUM_RECTS (pClip);
+ if (n == 1)
+ {
+ (*pExaScr->info->accel.Solid) (pPixmap,
+ fullX1 + xoff, fullY1 + yoff,
+ fullX2 + xoff, fullY2 + yoff);
+ }
+ else
+ {
+ pbox = REGION_RECTS(pClip);
+ /*
+ * clip the rectangle to each box in the clip region
+ * this is logically equivalent to calling Intersect()
+ */
+ while(n--)
+ {
+ partX1 = pbox->x1;
+ if (partX1 < fullX1)
+ partX1 = fullX1;
+ partY1 = pbox->y1;
+ if (partY1 < fullY1)
+ partY1 = fullY1;
+ partX2 = pbox->x2;
+ if (partX2 > fullX2)
+ partX2 = fullX2;
+ partY2 = pbox->y2;
+ if (partY2 > fullY2)
+ partY2 = fullY2;
+
+ pbox++;
+
+ if (partX1 < partX2 && partY1 < partY2)
+ (*pExaScr->info->accel.Solid) (pPixmap,
+ partX1 + xoff, partY1 + yoff,
+ partX2 + xoff, partY2 + yoff);
+ }
+ }
+ }
+ (*pExaScr->info->accel.DoneSolid) (pPixmap);
+ exaDrawableDirty (pDrawable);
+ exaMarkSync(pDrawable->pScreen);
+}
+
+static void
+exaSolidBoxClipped (DrawablePtr pDrawable,
+ RegionPtr pClip,
+ FbBits pm,
+ FbBits fg,
+ int x1,
+ int y1,
+ int x2,
+ int y2)
+{
+ ExaScreenPriv (pDrawable->pScreen);
+ PixmapPtr pPixmap;
+ BoxPtr pbox;
+ int nbox;
+ int xoff, yoff;
+ int partX1, partX2, partY1, partY2;
+
+ STRACE;
+ if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) ||
+ !(*pExaScr->info->accel.PrepareSolid) (pPixmap, GXcopy, pm, fg))
+ {
+ exaWaitSync (pDrawable->pScreen);
+ fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel);
+ fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2,
+ fbAnd (GXcopy, fg, pm),
+ fbXor (GXcopy, fg, pm));
+ exaDrawableDirty (pDrawable);
+ return;
+ }
+ for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip);
+ nbox--;
+ pbox++)
+ {
+ partX1 = pbox->x1;
+ if (partX1 < x1)
+ partX1 = x1;
+
+ partX2 = pbox->x2;
+ if (partX2 > x2)
+ partX2 = x2;
+
+ if (partX2 <= partX1)
+ continue;
+
+ partY1 = pbox->y1;
+ if (partY1 < y1)
+ partY1 = y1;
+
+ partY2 = pbox->y2;
+ if (partY2 > y2)
+ partY2 = y2;
+
+ if (partY2 <= partY1)
+ continue;
+
+ (*pExaScr->info->accel.Solid) (pPixmap,
+ partX1 + xoff, partY1 + yoff,
+ partX2 + xoff, partY2 + yoff);
+ }
+ (*pExaScr->info->accel.DoneSolid) (pPixmap);
+ exaDrawableDirty (pDrawable);
+ exaMarkSync(pDrawable->pScreen);
+}
+
+static void
+exaImageGlyphBlt (DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x,
+ int y,
+ unsigned int nglyph,
+ CharInfoPtr *ppciInit,
+ pointer pglyphBase)
+{
+ FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
+ CharInfoPtr *ppci;
+ CharInfoPtr pci;
+ unsigned char *pglyph; /* pointer bits in glyph */
+ int gWidth, gHeight; /* width and height of glyph */
+ FbStride gStride; /* stride of glyph */
+ Bool opaque;
+ int n;
+ int gx, gy;
+ void (*glyph) (FbBits *,
+ FbStride,
+ int,
+ FbStip *,
+ FbBits,
+ int,
+ int);
+ FbBits *dst;
+ FbStride dstStride;
+ int dstBpp;
+ int dstXoff, dstYoff;
+ FbBits depthMask;
+
+ STRACE;
+ depthMask = FbFullMask(pDrawable->depth);
+ if ((pGC->planemask & depthMask) != depthMask)
+ {
+ ExaCheckImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase);
+ return;
+ }
+ glyph = 0;
+ fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
+ switch (dstBpp) {
+ case 8: glyph = fbGlyph8; break;
+ case 16: glyph = fbGlyph16; break;
+ case 24: glyph = fbGlyph24; break;
+ case 32: glyph = fbGlyph32; break;
+ }
+
+ x += pDrawable->x;
+ y += pDrawable->y;
+
+ if (TERMINALFONT (pGC->font) && !glyph)
+ {
+ opaque = TRUE;
+ }
+ else
+ {
+ int xBack, widthBack;
+ int yBack, heightBack;
+
+ ppci = ppciInit;
+ n = nglyph;
+ widthBack = 0;
+ while (n--)
+ widthBack += (*ppci++)->metrics.characterWidth;
+
+ xBack = x;
+ if (widthBack < 0)
+ {
+ xBack += widthBack;
+ widthBack = -widthBack;
+ }
+ yBack = y - FONTASCENT(pGC->font);
+ heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
+ exaSolidBoxClipped (pDrawable,
+ fbGetCompositeClip(pGC),
+ pGC->planemask,
+ pGC->bgPixel,
+ xBack,
+ yBack,
+ xBack + widthBack,
+ yBack + heightBack);
+ opaque = FALSE;
+ }
+
+ exaWaitSync (pDrawable->pScreen);
+ exaDrawableDirty (pDrawable);
+
+ ppci = ppciInit;
+ while (nglyph--)
+ {
+ pci = *ppci++;
+ pglyph = FONTGLYPHBITS(pglyphBase, pci);
+ gWidth = GLYPHWIDTHPIXELS(pci);
+ gHeight = GLYPHHEIGHTPIXELS(pci);
+ if (gWidth && gHeight)
+ {
+ gx = x + pci->metrics.leftSideBearing;
+ gy = y - pci->metrics.ascent;
+ if (glyph && gWidth <= sizeof (FbStip) * 8 &&
+ fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight))
+ {
+ (*glyph) (dst + (gy + dstYoff) * dstStride,
+ dstStride,
+ dstBpp,
+ (FbStip *) pglyph,
+ pPriv->fg,
+ gx + dstXoff,
+ gHeight);
+ }
+ else
+ {
+ gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip);
+ fbPutXYImage (pDrawable,
+ fbGetCompositeClip(pGC),
+ pPriv->fg,
+ pPriv->bg,
+ pPriv->pm,
+ GXcopy,
+ opaque,
+
+ gx,
+ gy,
+ gWidth, gHeight,
+
+ (FbStip *) pglyph,
+ gStride,
+ 0);
+ }
+ }
+ x += pci->metrics.characterWidth;
+ }
+}
+
+static const GCOps exaOps = {
+ exaFillSpans,
+ ExaCheckSetSpans,
+ ExaCheckPutImage,
+ exaCopyArea,
+ ExaCheckCopyPlane,
+ ExaCheckPolyPoint,
+ ExaCheckPolylines,
+ ExaCheckPolySegment,
+ miPolyRectangle,
+ ExaCheckPolyArc,
+ miFillPolygon,
+ exaPolyFillRect,
+ miPolyFillArc,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ exaImageGlyphBlt,
+ ExaCheckPolyGlyphBlt,
+ ExaCheckPushPixels,
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+static void
+exaValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable)
+{
+ fbValidateGC (pGC, changes, pDrawable);
+
+ if (exaDrawableIsOffscreen (pDrawable))
+ pGC->ops = (GCOps *) &exaOps;
+ else
+ pGC->ops = (GCOps *) &exaAsyncPixmapGCOps;
+}
+
+GCFuncs exaGCFuncs = {
+ exaValidateGC,
+ miChangeGC,
+ miCopyGC,
+ miDestroyGC,
+ miChangeClip,
+ miDestroyClip,
+ miCopyClip
+};
+
+static int
+exaCreateGC (GCPtr pGC)
+{
+ STRACE;
+ if (!fbCreateGC (pGC))
+ return FALSE;
+
+ pGC->funcs = &exaGCFuncs;
+
+ return TRUE;
+}
+
+
+static void
+exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ RegionRec rgnDst;
+ int dx, dy;
+ PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
+
+ STRACE;
+ dx = ptOldOrg.x - pWin->drawable.x;
+ dy = ptOldOrg.y - pWin->drawable.y;
+ REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
+
+ REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0);
+
+ REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
+#ifdef COMPOSITE
+ if (pPixmap->screen_x || pPixmap->screen_y)
+ REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst,
+ -pPixmap->screen_x, -pPixmap->screen_y);
+#endif
+
+ fbCopyRegion (&pPixmap->drawable, &pPixmap->drawable,
+ 0,
+ &rgnDst, dx, dy, exaCopyNtoN, 0, 0);
+
+ REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
+}
+
+static void
+exaFillRegionSolid (DrawablePtr pDrawable,
+ RegionPtr pRegion,
+ Pixel pixel)
+{
+ ExaScreenPriv(pDrawable->pScreen);
+ PixmapPtr pPixmap;
+ int xoff, yoff;
+
+ STRACE;
+ if ((pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) &&
+ (*pExaScr->info->accel.PrepareSolid) (pPixmap, GXcopy, FB_ALLONES, pixel))
+ {
+ int nbox = REGION_NUM_RECTS (pRegion);
+ BoxPtr pBox = REGION_RECTS (pRegion);
+
+ while (nbox--)
+ {
+ (*pExaScr->info->accel.Solid) (pPixmap,
+ pBox->x1 + xoff, pBox->y1 + yoff,
+ pBox->x2 + xoff, pBox->y2 + yoff);
+ pBox++;
+ }
+ (*pExaScr->info->accel.DoneSolid) (pPixmap);
+ exaMarkSync(pDrawable->pScreen);
+ }
+ else
+ {
+ exaWaitSync (pDrawable->pScreen);
+ fbFillRegionSolid (pDrawable, pRegion, 0,
+ fbReplicatePixel (pixel, pDrawable->bitsPerPixel));
+ }
+ exaDrawableDirty (pDrawable);
+}
+
+static void
+exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ STRACE;
+ if (!REGION_NUM_RECTS(pRegion))
+ return;
+ switch (what) {
+ case PW_BACKGROUND:
+ switch (pWin->backgroundState) {
+ case None:
+ return;
+ case ParentRelative:
+ do {
+ pWin = pWin->parent;
+ } while (pWin->backgroundState == ParentRelative);
+ (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
+ what);
+ return;
+ case BackgroundPixel:
+ exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel);
+ return;
+#if 0
+ case BackgroundPixmap:
+ exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap);
+ return;
+#endif
+ }
+ break;
+ case PW_BORDER:
+ if (pWin->borderIsPixel)
+ {
+ exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel);
+ return;
+ }
+#if 0
+ else
+ {
+ exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap);
+ return;
+ }
+#endif
+ break;
+ }
+ ExaCheckPaintWindow (pWin, pRegion, what);
+}
+
+Bool
+exaDriverInit (ScreenPtr pScreen,
+ ExaDriverPtr pScreenInfo)
+{
+ ExaScreenPrivPtr pExaScr;
+
+#ifdef RENDER
+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+#endif
+ STRACE;
+ if (exaGeneration != serverGeneration)
+ {
+ exaScreenPrivateIndex = AllocateScreenPrivateIndex();
+ exaPixmapPrivateIndex = AllocatePixmapPrivateIndex();
+ exaGeneration = serverGeneration;
+ }
+
+ pExaScr = xalloc (sizeof (ExaScreenPrivRec));
+
+ if (!pExaScr)
+ return FALSE;
+
+ pExaScr->info = pScreenInfo;
+
+ pScreen->devPrivates[exaScreenPrivateIndex].ptr = (pointer) pExaScr;
+
+ /*
+ * Hook up asynchronous drawing
+ */
+ ExaScreenInitAsync (pScreen);
+ /*
+ * Replace various fb screen functions
+ */
+ pScreen->CreateGC = exaCreateGC;
+ pScreen->CopyWindow = exaCopyWindow;
+ pScreen->PaintWindowBackground = exaPaintWindow;
+ pScreen->PaintWindowBorder = exaPaintWindow;
+#ifdef RENDER
+ if (ps) {
+ ps->Composite = exaComposite;
+ }
+#endif
+
+ /*
+ * Hookup offscreen pixmaps
+ */
+ if ((pExaScr->info->card.flags & EXA_OFFSCREEN_PIXMAPS) &&
+ pExaScr->info->card.offScreenBase < pExaScr->info->card.memorySize)
+ {
+ if (!AllocatePixmapPrivate(pScreen, exaPixmapPrivateIndex,
+ sizeof (ExaPixmapPrivRec)))
+ return FALSE;
+ pScreen->CreatePixmap = exaCreatePixmap;
+ pScreen->DestroyPixmap = exaDestroyPixmap;
+ }
+ else
+ {
+ if (!AllocatePixmapPrivate(pScreen, exaPixmapPrivateIndex, 0))
+ return FALSE;
+ }
+
+ ErrorF("============== %ld < %ld\n", pExaScr->info->card.offScreenBase,
+ pExaScr->info->card.memorySize);
+ if (pExaScr->info->card.offScreenBase < pExaScr->info->card.memorySize) {
+ if (!exaOffscreenInit (pScreen))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+exaDriverFini (ScreenPtr pScreen)
+{
+ ExaScreenPriv(pScreen);
+
+ STRACE;
+ xfree (pExaScr);
+}
+
+
+void exaMarkSync(ScreenPtr pScreen)
+{
+ ExaScreenPriv(pScreen);
+ ExaCardInfoPtr card = &(pExaScr->info->card);
+
+ card->needsSync = TRUE;
+ if (pExaScr->info->accel.MarkSync != NULL) {
+ card->lastMarker = (*pExaScr->info->accel.MarkSync)(pScreen);
+ }
+}
+
+void exaWaitSync(ScreenPtr pScreen)
+{
+ ExaScreenPriv(pScreen);
+ ExaCardInfoPtr card = &(pExaScr->info->card);
+
+ if (card->needsSync) {
+ (*pExaScr->info->accel.WaitMarker)(pScreen, card->lastMarker);
+ card->needsSync = FALSE;
+ }
+}
+
+unsigned int exaGetVersion(void)
+{
+ return EXA_VERSION;
+}
+
+#ifdef XFree86LOADER
+static MODULESETUPPROTO(exaSetup);
+
+
+static const OptionInfoRec EXAOptions[] = {
+ { -1, NULL,
+ OPTV_NONE, {0}, FALSE }
+};
+
+/*ARGSUSED*/
+static const OptionInfoRec *
+EXAAvailableOptions(void *unused)
+{
+ return (EXAOptions);
+}
+
+static XF86ModuleVersionInfo exaVersRec =
+{
+ "exa",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ 1, 2, 0,
+ ABI_CLASS_VIDEODRV, /* requires the video driver ABI */
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_NONE,
+ {0,0,0,0}
+};
+
+XF86ModuleData exaModuleData = { &exaVersRec, exaSetup, NULL };
+
+ModuleInfoRec EXA = {
+ 1,
+ "EXA",
+ NULL,
+ 0,
+ EXAAvailableOptions,
+};
+
+/*ARGSUSED*/
+static pointer
+exaSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
+{
+ static Bool Initialised = FALSE;
+
+ ErrorF("exa setup\n");
+ if (!Initialised) {
+ Initialised = TRUE;
+#ifndef REMOVE_LOADER_CHECK_MODULE_INFO
+ if (xf86LoaderCheckSymbol("xf86AddModuleInfo"))
+#endif
+ xf86AddModuleInfo(&EXA, Module);
+ }
+
+ return (pointer)TRUE;
+}
+#endif