summaryrefslogtreecommitdiff
path: root/src/ffb_glyph.c
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:55 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:55 +0000
commit68c56916d79bf06e26e01c3e84206edc928d9b51 (patch)
treed39c13092dc680721e163e448a57df847a6fad62 /src/ffb_glyph.c
Initial revision
Diffstat (limited to 'src/ffb_glyph.c')
-rw-r--r--src/ffb_glyph.c380
1 files changed, 380 insertions, 0 deletions
diff --git a/src/ffb_glyph.c b/src/ffb_glyph.c
new file mode 100644
index 0000000..76668e3
--- /dev/null
+++ b/src/ffb_glyph.c
@@ -0,0 +1,380 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Glyph rops.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1998 Michal Rehacek (majkl@iname.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK, MICHAL REHACEK, OR DAVID MILLER BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_glyph.c,v 1.2 2000/05/23 04:47:45 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+#include "ffb_loops.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+#include "fontstruct.h"
+#include "dixfontstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+void
+CreatorPolyGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ unsigned int nglyph, CharInfoPtr *ppci, pointer pGlyphBase)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pGC->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ FontPtr pfont = pGC->font;
+ RegionPtr clip = cfbGetCompositeClip(pGC);
+ BoxPtr pbox = REGION_RECTS(clip);
+ int nbox = REGION_NUM_RECTS(clip);
+ int skippix, skipglyph, width, n, i;
+ int Left, Right, Top, Bottom, LeftEdge, RightEdge;
+
+ FFBLOG(("CreatorPolyGlyphBlt: xy[%08x:%08x] nglyph(%d)\n", x, y, nglyph));
+ x += pDrawable->x;
+ y += pDrawable->y;
+
+ width = 0;
+ for(i = 0; i < (nglyph - 1); i++)
+ width += (ppci[i])->metrics.characterWidth;
+
+ Left = x + (ppci[0])->metrics.leftSideBearing;
+ Right = x + (width + (ppci[nglyph - 1])->metrics.rightSideBearing);
+ Top = y - FONTMAXBOUNDS(pfont, ascent);
+ Bottom = y + FONTMAXBOUNDS(pfont, descent);
+
+ while(nbox && (Top >= pbox->y2)) {
+ pbox++;
+ nbox--;
+ }
+
+ if(!nbox || Bottom < pbox->y1)
+ return;
+
+ /* Ok, setup the chip. */
+ {
+ unsigned int ppc = (FFB_PPC_APE_DISABLE | FFB_PPC_TBE_TRANSPARENT |
+ FFB_PPC_CS_CONST);
+ unsigned int ppc_mask = (FFB_PPC_APE_MASK | FFB_PPC_TBE_MASK |
+ FFB_PPC_CS_MASK);
+ unsigned int pmask = pGC->planemask;
+ unsigned int rop = (FFB_ROP_EDIT_BIT | pGC->alu) | (FFB_ROP_NEW << 8);
+ unsigned int fg = pGC->fgPixel;
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ unsigned int fbc = FFB_FBC_WIN(pWin);
+
+ fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
+
+ if((pFfb->ppc_cache & ppc_mask) != ppc ||
+ pFfb->fg_cache != fg ||
+ pFfb->fbc_cache != fbc ||
+ pFfb->rop_cache != rop ||
+ pFfb->pmask_cache != pmask ||
+ pFfb->fontinc_cache != ((1<<16) | 0)) {
+ pFfb->ppc_cache &= ~ppc_mask;
+ pFfb->ppc_cache |= ppc;
+ pFfb->fg_cache = fg;
+ pFfb->fbc_cache = fbc;
+ pFfb->rop_cache = rop;
+ pFfb->pmask_cache = pmask;
+ pFfb->fontinc_cache = ((1<<16) | 0);
+ pFfb->rp_active = 1;
+ FFBFifo(pFfb, 6);
+ ffb->ppc = ppc;
+ ffb->fg = fg;
+ ffb->fbc = fbc;
+ ffb->rop = rop;
+ ffb->pmask = pmask;
+ ffb->fontinc = ((1 << 16) | 0);
+ }
+ }
+
+ while(nbox && (Bottom >= pbox->y1)) {
+ LeftEdge = max(Left, pbox->x1);
+ RightEdge = min(Right, pbox->x2);
+ if(RightEdge > LeftEdge) {
+ int walk, x_start;
+
+ skippix = LeftEdge - x;
+ skipglyph = walk = 0;
+ while(skippix >= (walk + (ppci[skipglyph])->metrics.rightSideBearing)) {
+ walk += (ppci[skipglyph])->metrics.characterWidth;
+ skipglyph++;
+ }
+ x_start = x + walk;
+ skippix = RightEdge - x;
+ n = 0;
+ i = skipglyph;
+ while((i < nglyph) &&
+ (skippix > (walk + (ppci[i])->metrics.leftSideBearing))) {
+ walk += (ppci[i])->metrics.characterWidth;
+ i++;
+ n++;
+ }
+ if(n) {
+ CharInfoPtr *ppci_iter = ppci + skipglyph;
+ CharInfoPtr pci;
+ unsigned int *bits;
+ int w, h, x0, y0, xskip, yskip;
+
+ while(n--) {
+ pci = *ppci_iter++;
+ w = GLYPHWIDTHPIXELS(pci);
+ h = GLYPHHEIGHTPIXELS(pci);
+ if(!w || !h)
+ goto next_glyph;
+
+ x0 = x_start + pci->metrics.leftSideBearing;
+ y0 = y - pci->metrics.ascent;
+ bits = (unsigned int *) pci->bits;
+
+ /* Now clip it to the bits we should actually
+ * render.
+ */
+ xskip = yskip = 0;
+ if(pbox->x1 > x0) {
+ xskip = pbox->x1 - x0;
+ w -= xskip;
+ x0 = pbox->x1;
+ if(w <= 0)
+ goto next_glyph;
+ }
+ if(pbox->y1 > y0) {
+ yskip = pbox->y1 - y0;
+ h -= yskip;
+ y0 = pbox->y1;
+ if(h <= 0)
+ goto next_glyph;
+ }
+ if(pbox->x2 < (x0 + w)) {
+ w = pbox->x2 - x0;
+ if(w <= 0)
+ goto next_glyph;
+ }
+ if(pbox->y2 < (y0 + h)) {
+ h = pbox->y2 - y0;
+ if(h <= 0)
+ goto next_glyph;
+ }
+
+ FFB_WRITE_FONTW(pFfb, ffb, w);
+ FFBFifo(pFfb, 1 + h);
+ ffb->fontxy = ((y0 << 16) | x0);
+ for(i = 0; i < h; i++)
+ ffb->font = bits[yskip + i] << xskip;
+
+ next_glyph:
+ x_start += pci->metrics.characterWidth;
+ }
+ }
+ }
+ nbox--;
+ pbox++;
+ }
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, ffb);
+}
+
+void
+CreatorTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ unsigned int nglyph, CharInfoPtr *ppci, pointer pGlyphBase)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pGC->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ RegionPtr clip = cfbGetCompositeClip(pGC);
+ int nbox = REGION_NUM_RECTS(clip);
+ BoxPtr pbox = REGION_RECTS(clip);
+ FontPtr pfont = pGC->font;
+ int glyphWidth = FONTMAXBOUNDS(pfont, characterWidth);
+ int skippix, skipglyphs, Left, Right, Top, Bottom;
+ int LeftEdge, RightEdge, ytop, ybot, h, w;
+
+ FFBLOG(("CreatorTEGlyphBlt: xy[%08x:%08x] nglyph(%d) pgbase(%p)\n",
+ x, y, nglyph, pGlyphBase));
+
+ Left = x + pDrawable->x;
+ Right = Left + (glyphWidth * nglyph);
+ y += pDrawable->y;
+ Top = y - FONTASCENT(pfont);
+ Bottom = y + FONTDESCENT(pfont);
+
+ while(nbox && (Top >= pbox->y2)) {
+ pbox++;
+ nbox--;
+ }
+
+ if(!nbox || Bottom <= pbox->y1)
+ return;
+
+ /* Ok, setup the chip. */
+ {
+ unsigned int ppc = FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST;
+ unsigned int ppc_mask = FFB_PPC_APE_MASK|FFB_PPC_TBE_MASK|FFB_PPC_CS_MASK;
+ unsigned int pmask = pGC->planemask;
+ unsigned int rop;
+ unsigned int fg = pGC->fgPixel;
+ unsigned int bg = pGC->bgPixel;
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ unsigned int fbc = FFB_FBC_WIN(pWin);
+
+ fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
+
+ if(pGlyphBase) {
+ ppc |= FFB_PPC_TBE_TRANSPARENT;
+ rop = FFB_ROP_EDIT_BIT | pGC->alu;
+ } else {
+ ppc |= FFB_PPC_TBE_OPAQUE;
+ rop = FFB_ROP_EDIT_BIT | GXcopy;
+ }
+ rop |= (FFB_ROP_NEW << 8);
+ if((pFfb->ppc_cache & ppc_mask) != ppc ||
+ pFfb->fg_cache != fg ||
+ pFfb->fbc_cache != fbc ||
+ pFfb->rop_cache != rop ||
+ pFfb->pmask_cache != pmask ||
+ pFfb->fontinc_cache != ((1<<16) | 0) ||
+ (!pGlyphBase && pFfb->bg_cache != bg)) {
+ pFfb->ppc_cache &= ~ppc_mask;
+ pFfb->ppc_cache |= ppc;
+ pFfb->fg_cache = fg;
+ pFfb->fbc_cache = fbc;
+ pFfb->rop_cache = rop;
+ pFfb->pmask_cache = pmask;
+ pFfb->fontinc_cache = ((1<<16) | 0);
+ if(!pGlyphBase)
+ pFfb->bg_cache = bg;
+ FFBFifo(pFfb, (!pGlyphBase ? 7 : 6));
+ ffb->ppc = ppc;
+ ffb->fg = fg;
+ ffb->fbc = fbc;
+ ffb->rop = rop;
+ ffb->pmask = pmask;
+ ffb->fontinc = ((1 << 16) | 0);
+ if(!pGlyphBase)
+ ffb->bg = bg;
+ }
+ }
+
+ while(nbox && (Bottom > pbox->y1)) {
+ LeftEdge = max(Left, pbox->x1);
+ RightEdge = min(Right, pbox->x2);
+
+ if(RightEdge > LeftEdge) {
+ ytop = max(Top, pbox->y1);
+ ybot = min(Bottom, pbox->y2);
+
+ if((skippix = LeftEdge - Left)) {
+ skipglyphs = skippix / glyphWidth;
+ skippix %= glyphWidth;
+ } else
+ skipglyphs = 0;
+ w = RightEdge - LeftEdge;
+
+ /* Get aligned onto a character. */
+ if(skippix) {
+ unsigned int *gbits = (unsigned int *) ppci[skipglyphs++]->bits;
+ int chunk_size = (glyphWidth - skippix);
+
+ if (chunk_size > w)
+ chunk_size = w;
+
+ FFB_WRITE_FONTW(pFfb, ffb, chunk_size);
+ FFBFifo(pFfb, 1 + (ybot - ytop));
+ ffb->fontxy = ((ytop << 16) | LeftEdge);
+ for(h = (ytop - Top); h < (ybot - Top); h++)
+ ffb->font = gbits[h] << skippix;
+ LeftEdge += chunk_size;
+ w -= chunk_size;
+ }
+ /* And now blit the rest with unrolled loops. */
+#define LoopIt(chunkW, loadup, fetch) \
+ FFB_WRITE_FONTW(pFfb, ffb, chunkW); \
+ while (w >= chunkW) { \
+ loadup \
+ FFBFifo(pFfb, 1 + (ybot - ytop)); \
+ ffb->fontxy = ((ytop << 16) | LeftEdge); \
+ for(h = (ytop - Top); h < (ybot - Top); h++) \
+ ffb->font = fetch; \
+ LeftEdge += chunkW; \
+ w -= chunkW; \
+ }
+ if(glyphWidth <= 8) {
+ int chunk_size = glyphWidth << 2;
+ LoopIt(chunk_size,
+ unsigned int *char1 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);
+ unsigned int *char2 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);
+ unsigned int *char3 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);
+ unsigned int *char4 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);,
+ (*char1++ | ((*char2++ | ((*char3++ | (*char4++ >> glyphWidth))
+ >> glyphWidth))
+ >> glyphWidth)))
+ } else if(glyphWidth <= 10) {
+ int chunk_size = (glyphWidth << 1) + glyphWidth;
+ LoopIt(chunk_size,
+ unsigned int *char1 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);
+ unsigned int *char2 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);
+ unsigned int *char3 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);,
+ (*char1++ | ((*char2++ | (*char3++ >> glyphWidth)) >> glyphWidth)));
+ } else if(glyphWidth <= 16) {
+ int chunk_size = glyphWidth << 1;
+ LoopIt(chunk_size,
+ unsigned int *char1 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);
+ unsigned int *char2 = ((unsigned int *)ppci[skipglyphs++]->bits)+(ytop-Top);,
+ (*char1++ | (*char2++ >> glyphWidth)));
+ }
+#undef LoopIt
+ /* Take care of any final glyphs. */
+ while(w > 0) {
+ unsigned int *gbits = (unsigned int *) ppci[skipglyphs++]->bits;
+ int pix = glyphWidth;
+
+ if(w < pix)
+ pix = w;
+ FFB_WRITE_FONTW(pFfb, ffb, pix);
+ FFBFifo(pFfb, 1 + (ybot - ytop));
+ ffb->fontxy = ((ytop << 16) | LeftEdge);
+ for(h = (ytop - Top); h < (ybot - Top); h++)
+ ffb->font = gbits[h];
+ LeftEdge += pix;
+ w -= pix;
+ }
+ }
+ nbox--;
+ pbox++;
+ }
+
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, ffb);
+}
+
+void
+CreatorPolyTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ unsigned int nglyph, CharInfoPtr *ppci, pointer pGlyphBase)
+{
+ CreatorTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, (char *) 1);
+}