diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:55 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:55 +0000 |
commit | 68c56916d79bf06e26e01c3e84206edc928d9b51 (patch) | |
tree | d39c13092dc680721e163e448a57df847a6fad62 /src/ffb_glyph.c |
Initial revision
Diffstat (limited to 'src/ffb_glyph.c')
-rw-r--r-- | src/ffb_glyph.c | 380 |
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); +} |