/* $XFree86: xc/programs/Xserver/hw/xfree86/xaa/xf86expblt.c,v 3.8.2.6 1998/09/05 03:32:05 dawes Exp $ */ /* * Copyright 1996 The XFree86 Project * * 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 * HARM HANEMAAYER 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. * * Written by Harm Hanemaayer (H.Hanemaayer@inter.nl.net). */ #include "compiler.h" #include "misc.h" #include "windowstr.h" #include "gcstruct.h" #include "regionstr.h" #include "xf86.h" #include "xf86xaa.h" #include "xf86local.h" #include "xf86expblt.h" /* * When compiled with MSBFIRST defined, * this file produces MSB-first versions of most of the functions. * When compiled with FIXEDBASE, fixed-base versions are produced. */ /* These are macros for 64-bit integer handling. */ #define UINT64_DECLARE(uint64) \ unsigned int uint64##low32; \ unsigned int uint64##high32 #define UINT64_ASSIGN(uint64, int32, int32_2) \ uint64##low32 = int32; uint64##high32 = int32_2 #define UINT64_LOW32(uint64) uint64##low32 #define UINT64_SHIFTRIGHT32(uint64) uint64##low32 = uint64##high32; uint64##high32 = 0 /* * Something fishy is going on with ">> 32". This seems to be equivalent to * ">> 0" on my system. I'm not sure whether this is a CPU or compiler bug. * We check for this case (shift == 0). */ /* shift <= 32 */ #define UINT64_ORLEFTSHIFTEDINT(uint64, int32, shift) \ uint64##low32 |= int32 << shift; \ if (shift > 0) \ uint64##high32 |= int32 >> (32 - shift) extern unsigned char byte_reversed[256]; /* Macros to write a word, converting the per-byte bit order if required. */ #ifndef MSBFIRST #ifdef FIXEDBASE #define WRITE_IN_BITORDER(dest, offset, data) *(dest) = data; #else /* Increasing base address. */ #define WRITE_IN_BITORDER(dest, offset, data) *(dest + offset) = data; #endif #else /* "Nasty" bit order within bytes. */ #if defined(__GNUC__) && defined(__i386__) static __inline__ unsigned int reverse_bitorder(data) { #if defined(Lynx) || (defined(SYSV) || defined(SVR4)) && !defined(ACK_ASSEMBLER) || defined(__ELF__) __asm__( "movl $0,%%ecx\n" "movb %%al,%%cl\n" "movb byte_reversed(%%ecx),%%al\n" "movb %%ah,%%cl\n" "movb byte_reversed(%%ecx),%%ah\n" "roll $16,%%eax\n" "movb %%al,%%cl\n" "movb byte_reversed(%%ecx),%%al\n" "movb %%ah,%%cl\n" "movb byte_reversed(%%ecx),%%ah\n" "roll $16,%%eax\n" : "=a" (data) : "0" (data) : "cx" ); #else __asm__( "movl $0,%%ecx\n" "movb %%al,%%cl\n" "movb _byte_reversed(%%ecx),%%al\n" "movb %%ah,%%cl\n" "movb _byte_reversed(%%ecx),%%ah\n" "roll $16,%%eax\n" "movb %%al,%%cl\n" "movb _byte_reversed(%%ecx),%%al\n" "movb %%ah,%%cl\n" "movb _byte_reversed(%%ecx),%%ah\n" "roll $16,%%eax\n" : "=a" (data) : "0" (data) : "cx" ); #endif return data; } #ifdef FIXEDBASE #define WRITE_IN_BITORDER(dest, offset, data) *(dest) = reverse_bitorder(data); #else #define WRITE_IN_BITORDER(dest, offset, data) \ *(dest + offset) = reverse_bitorder(data); #endif #else /* If no (gcc on i386), don't use asm. */ #ifdef FIXEDBASE #define WRITE_IN_BITORDER(dest, offset, data) \ { unsigned data2; \ data2 = byte_reversed[data & 0xFF]; \ data2 |= byte_reversed[(data & 0xFF00) >> 8] << 8; \ data2 |= byte_reversed[(data & 0xFF0000) >> 16] << 16; \ data2 |= byte_reversed[(data & 0xFF000000) >> 24] << 24; \ *(dest) = data2; \ } #else #define WRITE_IN_BITORDER(dest, offset, data) \ { unsigned data2; \ data2 = byte_reversed[data & 0xFF]; \ data2 |= byte_reversed[(data & 0xFF00) >> 8] << 8; \ data2 |= byte_reversed[(data & 0xFF0000) >> 16] << 16; \ data2 |= byte_reversed[(data & 0xFF000000) >> 24] << 24; \ *(dest + offset) = data2; \ } #endif #endif #endif /* * Macros for 24bpp color expansion in 8bpp pixel mode (each bit is * expanded to three bits). */ #define WRITE_IN_BITORDER3_FIRSTWORD_MACRO(dest, data, mapping) \ { unsigned data2; \ data2 = mapping[data & 0xFF]; \ data2 |= mapping[(data & 0xFF00) >> 8] << 24; \ *(dest) = data2; \ } #define WRITE_IN_BITORDER3_SECONDWORD_MACRO(dest, data, mapping) \ { unsigned data2; \ data2 = mapping[(data & 0xFF00) >> 8] >> 8; \ data2 |= mapping[(data & 0xFF0000) >> 16] << 16; \ *(dest) = data2; \ } #define WRITE_IN_BITORDER3_THIRDWORD_MACRO(dest, data, mapping) \ { unsigned data2; \ data2 = mapping[(data & 0xFF0000) >> 16] >> 16; \ data2 |= mapping[(data & 0xFF000000) >> 24] << 8; \ *(dest) = data2; \ } #define WRITE_IN_BITORDER3_MACRO(dest, data, mapping) \ WRITE_IN_BITORDER3_FIRSTWORD_MACRO(dest, data, mapping) \ WRITE_IN_BITORDER3_SECONDWORD_MACRO(dest + 1, data, mapping) \ WRITE_IN_BITORDER3_THIRDWORD_MACRO(dest + 2, data, mapping) #ifdef MSBFIRST #define BYTE_EXPAND byte_reversed_expand3 #else #define BYTE_EXPAND byte_expand3 #endif #ifndef FIXEDBASE #define WRITE_IN_BITORDER3(dest, offset, data) \ WRITE_IN_BITORDER3_MACRO(dest + offset, data, BYTE_EXPAND) #define WRITE_IN_BITORDER3_FIRSTWORD(dest, offset, data) \ WRITE_IN_BITORDER3_FIRSTWORD_MACRO(dest + offset, data, BYTE_EXPAND) #define WRITE_IN_BITORDER3_SECONDWORD(dest, offset, data) \ WRITE_IN_BITORDER3_SECONDWORD_MACRO(dest + offset, data, BYTE_EXPAND) #define WRITE_IN_BITORDER3_THIRDWORD(dest, offset, data) \ WRITE_IN_BITORDER3_THIRDWORD_MACRO(dest + offset, data, BYTE_EXPAND) #else #define WRITE_IN_BITORDER3(dest, offset, data) \ WRITE_IN_BITORDER3_MACRO(dest, data, BYTE_EXPAND) #define WRITE_IN_BITORDER3_FIRSTWORD(dest, offset, data) \ WRITE_IN_BITORDER3_FIRSTWORD_MACRO(dest, data, BYTE_EXPAND) #define WRITE_IN_BITORDER3_SECONDWORD(dest, offset, data) \ WRITE_IN_BITORDER3_SECONDWORD_MACRO(dest, data, BYTE_EXPAND) #define WRITE_IN_BITORDER3_THIRDWORD(dest, offset, data) \ WRITE_IN_BITORDER3_THIRDWORD_MACRO(dest, data, BYTE_EXPAND) #endif #ifdef MSBFIRST #ifdef FIXEDBASE #define MAPPEDNAME(x) x##MSBFirstFixedBase #else #define MAPPEDNAME(x) x##MSBFirst #endif #else #ifdef FIXEDBASE #define MAPPEDNAME(x) x##FixedBase #else #define MAPPEDNAME(x) x #endif #endif /* * Overview of supported low-level color expansion bitmap transfer functions: * * Bit order: LSB MSB LSB MSB(-first) * FIXEDBASE? No No Yes Yes * * TE Text, SCANLINE_PAD_DWORD X/O X/O u/o u/o * TE Text, SCANLINE_PAD_BYTE u/w u/w u/w u/w * TE Text, SCANLINE_NO_PAD u/w u/w u/w u/w * TE Text3, SCANLINE_PAD_DWORD u u u u * TE Text3, SCANLINE_PAD_BYTE - - - - * TE Text3, SCANLINE_NO_PAD - - - - * Non-TE Text, SCANLINE_PAD_DWORD d d d d * Non-TE Text, other padding - - - - * Non-TE Text3, any padding - - - - * Bitmap, SCANLINE_PAD_DWORD X X u u * Bitmap, SCANLINE_PAD_BYTE d d d d * Bitmap, SCANLINE_NO_PAD d d d d * Stipple, any padding d d d d * * X = Supported, tested * u = Supported, untested * d = Disabled/unfinished * - = Not supported * w = Only supports transfer of the whole bitmap, not scanline-by-scanline. * o = Optimized * O = Really optimized * * Text3 = Bitmap transfer function for 24bpp with 8bpp color expansion. */ #define xf86DrawBitmapScanline \ MAPPEDNAME(xf86DrawBitmapScanline) #define xf86DrawBitmapScanline3 \ MAPPEDNAME(xf86DrawBitmapScanline3) #define xf86DrawTextScanline \ MAPPEDNAME(xf86DrawTextScanline) #define xf86DrawTextNoPad \ MAPPEDNAME(xf86DrawTextNoPad) #define xf86DrawTextBytePad \ MAPPEDNAME(xf86DrawTextBytePad) #define xf86DrawTextScanline3 \ MAPPEDNAME(xf86DrawTextScanline3) #define xf86DrawNonTETextScanline \ MAPPEDNAME(xf86DrawNonTETextScanline) #define xf86DrawStippleScanline \ MAPPEDNAME(xf86DrawStippleScanline) /* Functions for plain bitmap scanlines. */ unsigned int *xf86DrawBitmapScanline(base, src, nbytes) unsigned int *base; unsigned int *src; int nbytes; { int i, nwords; nwords = nbytes / 4; while (nwords >= 4) { /* Reshuffled a bit for performance. */ WRITE_IN_BITORDER(base, 0, ldl_u((unsigned int *)src)); WRITE_IN_BITORDER(base, 1, ldl_u((unsigned int *)src + 1)); nwords -= 4; WRITE_IN_BITORDER(base, 2, ldl_u((unsigned int *)src + 2)); #ifndef FIXEDBASE base += 4; #endif WRITE_IN_BITORDER(base, -1, ldl_u((unsigned int *)src + 3)); src += 4; } for (i = 0; i < nwords; i++) { WRITE_IN_BITORDER(base, i, ldl_u((unsigned int *)src + i)); } src += i; #ifndef FIXEDBASE base += i; #endif switch (nbytes % 4) { case 1 : WRITE_IN_BITORDER(base, 0, *(unsigned char *)src); return base + 1; case 2 : WRITE_IN_BITORDER(base, 0, ldw_u((unsigned short *)src)); return base + 1; case 3 : WRITE_IN_BITORDER(base, 0, ldw_u((unsigned short *)src) | (*((unsigned char *)src + 2) << 16)); return base + 1; default : break; } return base; } unsigned int *xf86DrawBitmapScanline3(base, src, w) unsigned int *base; unsigned int *src; int w; { int i, nwords; unsigned int bits; /* Number of full words in the source. */ nwords = w / 32; while (nwords >= 4) { /* Reshuffled a bit for performance. */ WRITE_IN_BITORDER3(base, 0, ldl_u((unsigned int *)src)); WRITE_IN_BITORDER3(base, 3, ldl_u((unsigned int *)src + 1)); nwords -= 4; WRITE_IN_BITORDER3(base, 6, ldl_u((unsigned int *)src + 2)); #ifndef FIXEDBASE base += 12; #endif WRITE_IN_BITORDER3(base, -3, ldl_u((unsigned int *)src + 3)); src += 4; } while (nwords >= 1) { WRITE_IN_BITORDER3(base, 0, ldl_u((unsigned int *)src)); src++; #ifndef FIXEDBASE base += 3; #endif nwords --; } w &= 31; if (w == 0) return base; /* Get the last source bits. */ switch ((w + 7) / 8) { case 1 : bits = *(unsigned char *)src; break; case 2 : bits = ldw_u((unsigned short *)src); break; case 3 : bits = ldw_u((unsigned short *)src) | (*((unsigned char *)src + 2) << 16); break; default : /* 4 */ bits = ldl_u((unsigned int *)src); } WRITE_IN_BITORDER3_FIRSTWORD(base, 0, bits); #ifndef FIXEDBASE base++; #endif if (w >= 11) { WRITE_IN_BITORDER3_SECONDWORD(base, 0, bits); #ifndef FIXEDBASE base++; #endif if (w >= 22) { WRITE_IN_BITORDER3_THIRDWORD(base, 0, bits); #ifndef FIXEDBASE base++; #endif } } return base; } /* * nbytes > 0, src access can be unaligned. * This isn't used yet. It doesn't work. */ #if defined(MSBFIRST) && !defined(FIXEDBASE) ScanlineReturn xf86DrawBitmapScanlineMSBFirstBytePadded(base, src, bits, nbytes) unsigned int *base; unsigned int *src; unsigned int bits; int nbytes; { int i, leftedgebytes, nwords; ScanlineReturn ret; if (nbytes <= 2) { if (nbytes == 1) { if (((unsigned long)base & 3L) == 3L) *(unsigned int *)((unsigned long)base & ~3L) = bits | ((unsigned int)*(unsigned char *)src << 24); else ret.bits |= *(unsigned char *)src << (((unsigned long)base & 3L) * 8); } else { /* nbytes == 2 */ if (((unsigned long)base & 3L) == 3L) { *(unsigned int *)((unsigned long)base & ~3L) = bits | ((unsigned int)*(unsigned char *)src << 24); ret.bits = *((unsigned char *)src + 1); } else if (((unsigned long)base & 3L) == 2L) *(unsigned int *)((unsigned long)base & ~3L) = bits | ((unsigned int)*(unsigned short *)src << 16); else ret.bits |= (unsigned int)*(unsigned short *)src << (((unsigned long)base & 3L) * 8); } ret.base = (unsigned int *)((unsigned long)base + nbytes); return ret; } /* First combine the left over bytes with new ones to form a word. */ switch ((unsigned long)base & 3L) { case 0 : leftedgebytes = 0; break; case 1 : bits |= *(unsigned char *)src << 8; bits |= *(unsigned short *)((unsigned char *)src + 1) << 16; leftedgebytes = 3; break; case 2 : bits |= *(unsigned short *)src << 16; leftedgebytes = 2; break; case 3 : bits |= *(unsigned char *)src << 24; leftedgebytes = 1; break; } if (leftedgebytes > 0) { base = (unsigned int *)((unsigned long)base & ~3L); WRITE_IN_BITORDER(base, 0, bits); nbytes -= leftedgebytes; #ifdef FIXEDBASE base++; #endif } nwords = nbytes / 4; while (nwords >= 4) { /* Reshuffled a bit for performance. */ WRITE_IN_BITORDER(base, 0, *src); WRITE_IN_BITORDER(base, 1, *(src + 1)); nwords -= 4; WRITE_IN_BITORDER(base, 2, *(src + 2)); base += 4; WRITE_IN_BITORDER(base, -1, *(src + 3)); src += 4; } for (i = 0; i < nwords; i++) { WRITE_IN_BITORDER(base, i, *(src + i)); } switch (nbytes) { case 0 : ret.base = base + i; break; case 1 : ret.base = (unsigned int *)((unsigned char *)(base + i) + 1); ret.bits = *(unsigned char *)src; break; case 2 : ret.base = (unsigned int *)((unsigned char *)(base + i) + 2); ret.bits = *(unsigned short *)src; break; case 3 : ret.base = (unsigned int *)((unsigned char *)(base + i) + 3); ret.bits = *(unsigned short *)src; ret.bits |= *((unsigned char *)src + 2) << 16; break; } return ret; } #endif /* Functions that generate text bitmap scanlines. */ static unsigned int *DrawTextScanlineWidth6(); unsigned int *DrawTextScanlineWidth6P(); /* Pentium-opt ASM version */ unsigned int *DrawTextScanlineWidth6PMSBFirst(); static unsigned int *DrawTextScanlineWidth8(); unsigned int *DrawTextScanlineWidth8P(); unsigned int *DrawTextScanlineWidth8PMSBFirst(); static unsigned int *DrawTextScanlineWidth9(); static unsigned int *DrawTextScanlineWidth10(); static unsigned int *DrawTextScanlineWidth12(); static unsigned int *DrawTextScanlineWidth14(); static unsigned int *DrawTextScanlineWidth16(); static unsigned int *DrawTextScanlineWidth18(); static unsigned int *DrawTextScanlineWidth24(); #if defined(MSBFIRST) || defined(FIXEDBASE) /* Export just the non-MSBFirst version. */ static #endif unsigned int *(*glyphwidth_function[32])( #if NeedNestedPrototypes unsigned int *base, unsigned int **glyphp, int line, int nglyph #endif ) = { NULL, NULL, NULL, NULL, NULL, #if defined(__i386__) && !defined(FIXEDBASE) /* && defined(NEVER) */ #ifdef MSBFIRST DrawTextScanlineWidth6PMSBFirst, /* Pentium-optimized ASM version. */ #else DrawTextScanlineWidth6P, /* Pentium-optimized ASM version. */ #endif #else DrawTextScanlineWidth6, #endif NULL, #if defined(__i386__) && !defined(FIXEDBASE) /* && defined(NEVER) */ #ifdef MSBFIRST DrawTextScanlineWidth8PMSBFirst, /* Pentium-optimized ASM version. */ #else DrawTextScanlineWidth8P, /* Pentium-optimized ASM version. */ #endif #else DrawTextScanlineWidth8, #endif DrawTextScanlineWidth9, DrawTextScanlineWidth10, NULL, DrawTextScanlineWidth12, NULL, DrawTextScanlineWidth14, NULL, DrawTextScanlineWidth16, NULL, DrawTextScanlineWidth18, NULL, NULL, NULL, NULL, NULL, DrawTextScanlineWidth24, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; #if defined(MSBFIRST) && !defined(FIXEDBASE) /* This one needs to be defined only once. */ int glyphwidth_stretchsize[32] = { 0, 0, 0, 0, 0, 16, 0, 8, 32, 16, 0, 8, 0, 16, 0, 8, 0, 16, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0 }; #else extern int glyphwidth_stretchsize[32]; #endif #if defined(__GNUC__) && defined(__i386__) #ifdef FIXEDBASE #ifdef MSBFIRST #define WRITE_BITS() *base = reverse_bitorder(bits) #else #define WRITE_BITS() *base = bits #endif #else #ifdef MSBFIRST #define WRITE_BITS() *(base++) = reverse_bitorder(bits) #else #define WRITE_BITS() *(base++) = bits #endif #endif #else /* If no (gcc on i386), don't use reverse_bitorder */ #ifdef FIXEDBASE #ifdef MSBFIRST #define WRITE_BITS() \ { unsigned data2; \ data2 = byte_reversed[bits & 0xFF]; \ data2 |= byte_reversed[(bits & 0xFF00) >> 8] << 8; \ data2 |= byte_reversed[(bits & 0xFF0000) >> 16] << 16; \ data2 |= byte_reversed[(bits & 0xFF000000) >> 24] << 24; \ *(base) = data2; \ } #else #define WRITE_BITS() *base = bits #endif #else #ifdef MSBFIRST #define WRITE_BITS() \ { unsigned data2; \ data2 = byte_reversed[bits & 0xFF]; \ data2 |= byte_reversed[(bits & 0xFF00) >> 8] << 8; \ data2 |= byte_reversed[(bits & 0xFF0000) >> 16] << 16; \ data2 |= byte_reversed[(bits & 0xFF000000) >> 24] << 24; \ *(base++) = data2; \ } #else #define WRITE_BITS() *(base++) = bits #endif #endif #endif /* (gcc on i386) */ unsigned int *xf86DrawTextScanline(base, glyphp, line, nglyph, glyphwidth) unsigned int *base; unsigned int **glyphp; int line; int nglyph; int glyphwidth; { register CARD32 bits; register int shift; int count = 0; if (glyphwidth_stretchsize[glyphwidth - 1] && glyphwidth_stretchsize[glyphwidth - 1] <= nglyph) { base = (*glyphwidth_function[glyphwidth - 1])(base, glyphp, line, nglyph); count = nglyph - (nglyph & (glyphwidth_stretchsize[glyphwidth - 1] - 1)); } for(bits = 0, shift = 0;count < nglyph; count++) { bits |= glyphp[count][line] << shift; shift += glyphwidth; if(shift & ~31) { WRITE_BITS(); shift &= 31; bits = glyphp[count][line] >> (glyphwidth - shift); } } if(shift) WRITE_BITS(); return base; } #if 0 /* this is the old code, new code is above (MArk) */ unsigned int *xf86DrawTextScanline(base, glyphp, line, nglyph, glyphwidth) unsigned int *base; unsigned int **glyphp; int line; int nglyph; int glyphwidth; { UINT64_DECLARE(bits); int shift, i; if (glyphwidth_stretchsize[glyphwidth - 1] > 0 && glyphwidth_stretchsize[glyphwidth - 1] <= nglyph) { int glyphsleft; /* * Draw the first stretches of characters using a function * customized for the glyph width. */ base = (*glyphwidth_function[glyphwidth - 1])(base, glyphp, line, nglyph); glyphsleft = nglyph & (glyphwidth_stretchsize[glyphwidth - 1] - 1); /* Now do the rest. */ glyphp += nglyph - glyphsleft; nglyph = glyphsleft; } UINT64_ASSIGN(bits, 0, 0); shift = 0; i = 0; while (i < nglyph) { UINT64_ORLEFTSHIFTEDINT(bits, glyphp[i][line], shift); shift += glyphwidth; if (shift >= 32) { /* Write a 32-bit word. */ WRITE_IN_BITORDER(base, 0, UINT64_LOW32(bits)); #ifndef FIXEDBASE base++; #endif shift -= 32; UINT64_SHIFTRIGHT32(bits); } i++; } if (shift > 0) { WRITE_IN_BITORDER(base, 0, UINT64_LOW32(bits)); #ifndef FIXEDBASE base++; #endif } return base; } #endif /* * This function does not transfer one scanline worth of bits like all the * other ones, but instead transfers the whole bitmap (padded to a DWORD * boundary), without any end-of-scanline padding (SCANLINE_NO_PAD). * This function violates the non-XAA dependency of the functions defined * in this file (it references the xf86AccelInfoRec). */ unsigned int *xf86DrawTextNoPad(base, glyphp, height, nglyph, glyphwidth) unsigned int *base; unsigned int **glyphp; int height; int nglyph; int glyphwidth; { UINT64_DECLARE(bits); int shift, i, line; UINT64_ASSIGN(bits, 0, 0); shift = 0; for (line = 0; line < height; line++) { i = 0; while (i < nglyph) { UINT64_ORLEFTSHIFTEDINT(bits, glyphp[i][line], shift); shift += glyphwidth; if (shift >= 32) { /* Write a 32-bit word. */ WRITE_IN_BITORDER(base, 0, UINT64_LOW32(bits)); #ifndef FIXEDBASE base++; #endif shift -= 32; UINT64_SHIFTRIGHT32(bits); } i++; } #ifndef FIXEDBASE if ((unsigned char *)base >= (unsigned char *) xf86AccelInfoRec.CPUToScreenColorExpandEndMarker) base = (unsigned int *) xf86AccelInfoRec.CPUToScreenColorExpandBase; #endif } if (shift > 0) { WRITE_IN_BITORDER(base, 0, UINT64_LOW32(bits)); #ifndef FIXEDBASE base++; #endif } return base; } /* * Similarly, this is for BYTE-padded scanlines. */ unsigned int *xf86DrawTextBytePad(base, glyphp, height, nglyph, glyphwidth) unsigned int *base; unsigned int **glyphp; int height; int nglyph; int glyphwidth; { UINT64_DECLARE(bits); int shift, i, line; UINT64_ASSIGN(bits, 0, 0); shift = 0; for (line = 0; line < height; line++) { i = 0; while (i < nglyph) { UINT64_ORLEFTSHIFTEDINT(bits, glyphp[i][line], shift); shift += glyphwidth; if (shift >= 32) { /* Write a 32-bit word. */ WRITE_IN_BITORDER(base, 0, UINT64_LOW32(bits)); #ifndef FIXEDBASE base++; #endif shift -= 32; UINT64_SHIFTRIGHT32(bits); } i++; } /* Pad to nearest BYTE boundary. */ shift = (shift + 7) & (~7); if (shift >= 32) { /* Write a 32-bit word. */ WRITE_IN_BITORDER(base, 0, UINT64_LOW32(bits)); #ifndef FIXEDBASE base++; #endif shift -= 32; UINT64_SHIFTRIGHT32(bits); } #ifndef FIXEDBASE if ((unsigned char *)base >= (unsigned char *) xf86AccelInfoRec.CPUToScreenColorExpandEndMarker) base = (unsigned int *) xf86AccelInfoRec.CPUToScreenColorExpandBase; #endif } if (shift > 0) { WRITE_IN_BITORDER(base, 0, UINT64_LOW32(bits)); #ifndef FIXEDBASE base++; #endif } return base; } unsigned int *xf86DrawNonTETextScanline(base, glyphinfop, line, nglyph) unsigned int *base; NonTEGlyphInfo *glyphinfop; int line; int nglyph; { UINT64_DECLARE(bits); int shift, i; UINT64_ASSIGN(bits, 0, 0); shift = 0; i = 0; while (i < nglyph) { /* Check whether the current glyph has bits for this scanline. */ if (line >= glyphinfop[i].firstline && line <= glyphinfop[i].lastline) { UINT64_ORLEFTSHIFTEDINT(bits, glyphinfop[i].bitsp[line], shift); } shift += glyphinfop[i].width; if (shift >= 32) { /* Write a 32-bit word. */ WRITE_IN_BITORDER(base, 0, UINT64_LOW32(bits)); #ifndef FIXEDBASE base++; #endif shift -= 32; UINT64_SHIFTRIGHT32(bits); } i++; } if (shift > 0) { WRITE_IN_BITORDER(base, 0, UINT64_LOW32(bits)); #ifndef FIXEDBASE base++; #endif } return base; } unsigned int *xf86DrawTextScanline3(base, glyphp, line, nglyph, glyphwidth) unsigned int *base; unsigned int **glyphp; int line; int nglyph; int glyphwidth; { UINT64_DECLARE(bits); int shift, i; UINT64_ASSIGN(bits, 0, 0); shift = 0; i = 0; while (i < nglyph) { UINT64_ORLEFTSHIFTEDINT(bits, glyphp[i][line], shift); shift += glyphwidth; if (shift >= 32) { /* Write a 32-bit word. */ WRITE_IN_BITORDER3(base, 0, UINT64_LOW32(bits)); #ifndef FIXEDBASE base += 3; #endif shift -= 32; UINT64_SHIFTRIGHT32(bits); } i++; } if (shift > 0) { WRITE_IN_BITORDER3_FIRSTWORD(base, 0, UINT64_LOW32(bits)); #ifndef FIXEDBASE base++; #endif if (shift >= 11) { WRITE_IN_BITORDER3_SECONDWORD(base, 0, UINT64_LOW32(bits)); #ifndef FIXEDBASE base++; #endif if (shift >= 22) { WRITE_IN_BITORDER3_THIRDWORD(base, 0, UINT64_LOW32(bits)); #ifndef FIXEDBASE base++; #endif } } } return base; } /* * The functions below write stretches of glyphs for special font widths. * Actually, these functions could also be used for 24bpp color expansion * in 8bpp mode. */ static unsigned int *DrawTextScanlineWidth6(base, glyphp, line, nglyph) unsigned int *base; unsigned int **glyphp; int line; int nglyph; { while (nglyph >= 16) { unsigned int bits; bits = glyphp[0][line]; bits |= glyphp[1][line] << 6; bits |= glyphp[2][line] << 12; bits |= glyphp[3][line] << 18; bits |= glyphp[4][line] << 24; bits |= glyphp[5][line] << 30; WRITE_IN_BITORDER(base, 0, bits); bits = glyphp[5][line] >> 2; bits |= glyphp[6][line] << 4; bits |= glyphp[7][line] << 10; bits |= glyphp[8][line] << 16; bits |= glyphp[9][line] << 22; bits |= glyphp[10][line] << 28; WRITE_IN_BITORDER(base, 1, bits); bits = glyphp[10][line] >> 4; bits |= glyphp[11][line] << 2; bits |= glyphp[12][line] << 8; bits |= glyphp[13][line] << 14; bits |= glyphp[14][line] << 20; bits |= glyphp[15][line] << 26; WRITE_IN_BITORDER(base, 2, bits); #ifndef FIXEDBASE base += 3; #endif nglyph -= 16; glyphp += 16; } return base; } static unsigned int *DrawTextScanlineWidth8(base, glyphp, line, nglyph) unsigned int *base; unsigned int **glyphp; int line; int nglyph; { #ifdef MSBFIRST /* * For this font width (and only this one), there's a seperate * MSB-first version. */ while (nglyph >= 8) { unsigned int bits; bits = byte_reversed[glyphp[0][line]]; bits |= byte_reversed[glyphp[1][line]] << 8; bits |= byte_reversed[glyphp[2][line]] << 16; bits |= byte_reversed[glyphp[3][line]] << 24; *base = bits; bits = byte_reversed[glyphp[4][line]]; bits |= byte_reversed[glyphp[5][line]] << 8; bits |= byte_reversed[glyphp[6][line]] << 16; bits |= byte_reversed[glyphp[7][line]] << 24; #ifndef FIXEDBASE *(base + 1) = bits; base += 2; #else *base = bits; #endif nglyph -= 8; glyphp += 8; } #else while (nglyph >= 8) { unsigned int bits; bits = glyphp[0][line]; bits |= glyphp[1][line] << 8; bits |= glyphp[2][line] << 16; bits |= glyphp[3][line] << 24; WRITE_IN_BITORDER(base, 0, bits); bits = glyphp[4][line]; bits |= glyphp[5][line] << 8; bits |= glyphp[6][line] << 16; bits |= glyphp[7][line] << 24; WRITE_IN_BITORDER(base, 1, bits); #ifndef FIXEDBASE base += 2; #endif nglyph -= 8; glyphp += 8; } #endif #ifdef WHOLE_SCANLINE if (nglyph == 0) return base; do { bits = glyphp[8][line]; if (nglyph == 1) break; bits |= glyphp[9][line] << 16; if (nglyph == 2) break; bits |= glyphp[10][line] << 16; if (nglyph == 3) break; bits |= glyphp[11][line] << 24; } while (0); WRITE_IN_BITORDER(base, 0, bits); if (nglyph <= 4) return base + 1; do { bits = glyphp[8][line]; if (nglyph == 5) break; bits |= glyphp[9][line] << 16; if (nglyph == 6) break; bits |= glyphp[10][line] << 16; if (nglyph == 7) break; bits |= glyphp[11][line] << 24; } while (0); WRITE_IN_BITORDER(base, 1, bits); return base + 2; #endif return base; } static unsigned int *DrawTextScanlineWidth9(base, glyphp, line, nglyph) unsigned int *base; unsigned int **glyphp; int line; int nglyph; { while (nglyph >= 32) { unsigned int bits; bits = glyphp[0][line]; bits |= glyphp[1][line] << 9; bits |= glyphp[2][line] << 18; bits |= glyphp[3][line] << 27; WRITE_IN_BITORDER(base, 0, bits); bits = glyphp[3][line] >> 5; bits |= glyphp[4][line] << 4; bits |= glyphp[5][line] << 13; bits |= glyphp[6][line] << 22; bits |= glyphp[7][line] << 31; WRITE_IN_BITORDER(base, 1, bits); bits = glyphp[7][line] >> 1; bits |= glyphp[8][line] << 8; bits |= glyphp[9][line] << 17; bits |= glyphp[10][line] << 26; WRITE_IN_BITORDER(base, 2, bits); bits = glyphp[10][line] >> 6; bits |= glyphp[11][line] << 3; bits |= glyphp[12][line] << 12; bits |= glyphp[13][line] << 21; bits |= glyphp[14][line] << 30; WRITE_IN_BITORDER(base, 3, bits); bits = glyphp[14][line] >> 2; bits |= glyphp[15][line] << 7; bits |= glyphp[16][line] << 16; bits |= glyphp[17][line] << 25; WRITE_IN_BITORDER(base, 4, bits); bits = glyphp[17][line] >> 7; bits |= glyphp[18][line] << 2; bits |= glyphp[19][line] << 11; bits |= glyphp[20][line] << 20; bits |= glyphp[21][line] << 29; WRITE_IN_BITORDER(base, 5, bits); bits = glyphp[21][line] >> 3; bits |= glyphp[22][line] << 6; bits |= glyphp[23][line] << 15; bits |= glyphp[24][line] << 24; WRITE_IN_BITORDER(base, 6, bits); bits = glyphp[24][line] >> 8; bits |= glyphp[25][line] << 1; bits |= glyphp[26][line] << 10; bits |= glyphp[27][line] << 19; bits |= glyphp[28][line] << 28; WRITE_IN_BITORDER(base, 7, bits); bits = glyphp[28][line] >> 4; bits |= glyphp[29][line] << 5; bits |= glyphp[30][line] << 14; bits |= glyphp[31][line] << 23; WRITE_IN_BITORDER(base, 8, bits); #ifndef FIXEDBASE base += 9; #endif nglyph -= 32; glyphp += 32; } return base; } static unsigned int *DrawTextScanlineWidth10(base, glyphp, line, nglyph) unsigned int *base; unsigned int **glyphp; int line; int nglyph; { while (nglyph >= 16) { unsigned int bits; bits = glyphp[0][line]; bits |= glyphp[1][line] << 10; bits |= glyphp[2][line] << 20; bits |= glyphp[3][line] << 30; WRITE_IN_BITORDER(base, 0, bits); bits = glyphp[3][line] >> 2; bits |= glyphp[4][line] << 8; bits |= glyphp[5][line] << 18; bits |= glyphp[6][line] << 28; WRITE_IN_BITORDER(base, 1, bits); bits = glyphp[6][line] >> 4; bits |= glyphp[7][line] << 6; bits |= glyphp[8][line] << 16; bits |= glyphp[9][line] << 26; WRITE_IN_BITORDER(base, 2, bits); bits = glyphp[9][line] >> 6; bits |= glyphp[10][line] << 4; bits |= glyphp[11][line] << 14; bits |= glyphp[12][line] << 24; WRITE_IN_BITORDER(base, 3, bits); bits = glyphp[12][line] >> 8; bits |= glyphp[13][line] << 2; bits |= glyphp[14][line] << 12; bits |= glyphp[15][line] << 22; WRITE_IN_BITORDER(base, 4, bits); #ifndef FIXEDBASE base += 5; #endif nglyph -= 16; glyphp += 16; } return base; } static unsigned int *DrawTextScanlineWidth12(base, glyphp, line, nglyph) unsigned int *base; unsigned int **glyphp; int line; int nglyph; { while (nglyph >= 8) { unsigned int bits; bits = glyphp[0][line]; bits |= glyphp[1][line] << 12; bits |= glyphp[2][line] << 24; WRITE_IN_BITORDER(base, 0, bits); bits = glyphp[2][line] >> 8; bits |= glyphp[3][line] << 4; bits |= glyphp[4][line] << 16; bits |= glyphp[5][line] << 28; WRITE_IN_BITORDER(base, 1, bits); bits = glyphp[5][line] >> 4; bits |= glyphp[6][line] << 8; bits |= glyphp[7][line] << 20; WRITE_IN_BITORDER(base, 2, bits); #ifndef FIXEDBASE base += 3; #endif nglyph -= 8; glyphp += 8; } return base; } static unsigned int *DrawTextScanlineWidth14(base, glyphp, line, nglyph) unsigned int *base; unsigned int **glyphp; int line; int nglyph; { while (nglyph >= 16) { unsigned int bits; bits = glyphp[0][line]; bits |= glyphp[1][line] << 14; bits |= glyphp[2][line] << 28; WRITE_IN_BITORDER(base, 0, bits); bits = glyphp[2][line] >> 4; bits |= glyphp[3][line] << 10; bits |= glyphp[4][line] << 24; WRITE_IN_BITORDER(base, 1, bits); bits = glyphp[4][line] >> 8; bits |= glyphp[5][line] << 6; bits |= glyphp[6][line] << 20; WRITE_IN_BITORDER(base, 2, bits); bits = glyphp[6][line] >> 12; bits |= glyphp[7][line] << 2; bits |= glyphp[8][line] << 16; bits |= glyphp[9][line] << 30; WRITE_IN_BITORDER(base, 3, bits); bits = glyphp[9][line] >> 2; bits |= glyphp[10][line] << 12; bits |= glyphp[11][line] << 26; WRITE_IN_BITORDER(base, 4, bits); bits = glyphp[11][line] >> 6; bits |= glyphp[12][line] << 8; bits |= glyphp[13][line] << 22; WRITE_IN_BITORDER(base, 5, bits); bits = glyphp[13][line] >> 10; bits |= glyphp[14][line] << 4; bits |= glyphp[15][line] << 18; WRITE_IN_BITORDER(base, 6, bits); #ifndef FIXEDBASE base += 7; #endif nglyph -= 16; glyphp += 16; } return base; } static unsigned int *DrawTextScanlineWidth16(base, glyphp, line, nglyph) unsigned int *base; unsigned int **glyphp; int line; int nglyph; { while (nglyph >= 8) { unsigned int bits; bits = glyphp[0][line]; bits |= glyphp[1][line] << 16; WRITE_IN_BITORDER(base, 0, bits); bits = glyphp[2][line]; bits |= glyphp[3][line] << 16; WRITE_IN_BITORDER(base, 1, bits); bits = glyphp[4][line]; bits |= glyphp[5][line] << 16; WRITE_IN_BITORDER(base, 2, bits); bits = glyphp[6][line]; bits |= glyphp[7][line] << 16; WRITE_IN_BITORDER(base, 3, bits); #ifndef FIXEDBASE base += 4; #endif nglyph -= 8; glyphp += 8; } return base; } static unsigned int *DrawTextScanlineWidth18(base, glyphp, line, nglyph) unsigned int *base; unsigned int **glyphp; int line; int nglyph; { while (nglyph >= 16) { unsigned int bits; bits = glyphp[0][line]; bits |= glyphp[1][line] << 18; WRITE_IN_BITORDER(base, 0, bits); bits = glyphp[1][line] >> 14; bits |= glyphp[2][line] << 4; bits |= glyphp[3][line] << 22; WRITE_IN_BITORDER(base, 1, bits); bits = glyphp[3][line] >> 10; bits |= glyphp[4][line] << 8; bits |= glyphp[5][line] << 26; WRITE_IN_BITORDER(base, 2, bits); bits = glyphp[5][line] >> 6; bits |= glyphp[6][line] << 12; bits |= glyphp[7][line] << 30; WRITE_IN_BITORDER(base, 3, bits); bits = glyphp[7][line] >> 2; bits |= glyphp[8][line] << 16; WRITE_IN_BITORDER(base, 4, bits); bits = glyphp[8][line] >> 16; bits |= glyphp[9][line] << 2; bits |= glyphp[10][line] << 20; WRITE_IN_BITORDER(base, 5, bits); bits = glyphp[10][line] >> 12; bits |= glyphp[11][line] << 6; bits |= glyphp[12][line] << 24; WRITE_IN_BITORDER(base, 6, bits); bits = glyphp[12][line] >> 8; bits |= glyphp[13][line] << 10; bits |= glyphp[14][line] << 28; WRITE_IN_BITORDER(base, 7, bits); bits = glyphp[14][line] >> 4; bits |= glyphp[15][line] << 14; WRITE_IN_BITORDER(base, 8, bits); #ifndef FIXEDBASE base += 9; #endif nglyph -= 16; glyphp += 16; } return base; } static unsigned int *DrawTextScanlineWidth24(base, glyphp, line, nglyph) unsigned int *base; unsigned int **glyphp; int line; int nglyph; { while (nglyph >= 4) { unsigned int bits; bits = glyphp[0][line]; bits |= glyphp[1][line] << 24; WRITE_IN_BITORDER(base, 0, bits); bits = glyphp[1][line] >> 8; bits |= glyphp[2][line] << 16; WRITE_IN_BITORDER(base, 1, bits); bits = glyphp[2][line] >> 16; bits |= glyphp[3][line] << 8; WRITE_IN_BITORDER(base, 2, bits); #ifndef FIXEDBASE base += 3; #endif nglyph -= 4; glyphp += 4; } return base; } /* * Stipple bitmap data transfer. This requires the scanline to start * with a horizontal stipple offset that is at a byte (multiple of 8 pixel) * boundary in the stipple bitmap scanline. * Source data access can be unaligned. */ static unsigned int stipplemask[33] = { 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF }; unsigned int *xf86DrawStippleScanline(base, src, srcwidth, stipplewidth, srcoffset, w) unsigned int *base; unsigned char *src; /* Pointer to stipple bitmap. */ int srcwidth; /* Width of stipple bitmap in bytes. */ int stipplewidth; /* Width of stipple in pixels. */ int srcoffset; /* The offset in bytes into the stipple */ /* of the first pixel. */ int w; /* Width of scanline in pixels. */ { UINT64_DECLARE(bits); int shift, sw; unsigned char *srcp; UINT64_ASSIGN(bits, 0, 0); shift = 0; sw = stipplewidth - srcoffset * 8; srcp = src + srcoffset; for (;;) { int dw; dw = min(w, sw); if (dw >= 32) { UINT64_ORLEFTSHIFTEDINT(bits, ldl_u((unsigned int *)srcp), shift); shift += 32; sw -= 32; w -= 32; srcp += 4; } else { UINT64_ORLEFTSHIFTEDINT(bits, ((ldl_u((unsigned int *)srcp)) & stipplemask[dw]), shift); shift += dw; sw = 0; w -= dw; } if (shift >= 32) { /* Write a 32-bit word. */ WRITE_IN_BITORDER(base, 0, UINT64_LOW32(bits)); #ifndef FIXEDBASE base++; #endif shift -= 32; UINT64_SHIFTRIGHT32(bits); } if (w == 0) break; if (sw == 0) { srcp = src; sw = stipplewidth; } } if (shift > 0) { WRITE_IN_BITORDER(base, 0, UINT64_LOW32(bits)); #ifndef FIXEDBASE base++; #endif } return base; }