/** ** driver8.h ---- the 256 color padded SVGA linear frame buffer driver ** ** Copyright (c) 1995 Csaba Biegl, 820 Stirrup Dr, Nashville, TN 37221 ** [e-mail: csaba@vuse.vanderbilt.edu]. ** ** This file is part of the GRX graphics library. ** ** The GRX graphics library is free software; you can redistribute it ** and/or modify it under some conditions; see the "copying.grx" file ** for details. ** ** This library is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ** ** Contributions by: (See "doc/credits.doc" for details) ** Hartmut Schirmer (hsc@techfak.uni-kiel.de) ** Andrzej Lawa [FidoNet: Andrzej Lawa 2:480/19.77] ** **/ #include "libgrx.h" #include "grdriver.h" #include "allocate.h" #include "arith.h" #include "docolor.h" #include "mempeek.h" #include "memfill.h" /* frame offset address calculation */ #define FOFS(x,y,lo) umuladd32((y),(lo),(x)) /* #define FAR_ACCESS for video access routines */ #ifdef FAR_ACCESS # define peek8 peek_b_f # define poke8_xor poke_b_f_xor # define poke8_or poke_b_f_or # define poke8_and poke_b_f_and # define poke8 poke_b_f # define colfill8_xor colfill_b_f_xor # define colfill8_or colfill_b_f_or # define colfill8_and colfill_b_f_and # define colfill8 colfill_b_f # define repfill8_xor repfill_b_f_xor # define repfill8_or repfill_b_f_or # define repfill8_and repfill_b_f_and # define repfill8 repfill_b_f # define SETFARSEL(sel) setup_far_selector(sel) # if defined(__GNUC__) && defined(__i386__) # define ASM_386_SEL I386_GCC_FAR_SELECTOR # endif /* GCC i386 */ #else /* defined FAR_ACCESS */ # define peek8 peek_b # define poke8_xor poke_b_xor # define poke8_or poke_b_or # define poke8_and poke_b_and # define poke8 poke_b # define colfill8_xor colfill_b_xor # define colfill8_or colfill_b_or # define colfill8_and colfill_b_and # define colfill8 colfill_b # define repfill8_xor repfill_b_xor # define repfill8_or repfill_b_or # define repfill8_and repfill_b_and # define repfill8 repfill_b # define SETFARSEL(sel) #endif #ifndef ASM_386_SEL # define ASM_386_SEL #endif static INLINE GrColor readpixel(GrFrame *c,int x,int y) { GR_int8u *pp; GRX_ENTER(); #ifdef FAR_ACCESS pp = (GR_int8u *)&SCRN->gc_baseaddr[0][FOFS(x,y,SCRN->gc_lineoffset)]; SETFARSEL(SCRN->gc_selector); GRX_RETURN((GR_int8u)peek8(pp)); #else /* problem with LFB_BY_NEAR_POINTER here? Does c always point to screen? */ pp = (GR_int8u *)&c->gf_baseaddr[0][FOFS(x,y,c->gf_lineoffset)]; GRX_RETURN(*pp); #endif } /* -------------------------------------------------------------------- */ static INLINE void drawpixel(int x,int y,GrColor color) { char *pp; GRX_ENTER(); pp = &CURC->gc_baseaddr[0][FOFS(x,y,CURC->gc_lineoffset)]; SETFARSEL(CURC->gc_selector); switch(C_OPER(color)) { case C_XOR: poke8_xor(pp,(GR_int8u)color); break; case C_OR: poke8_or( pp,(GR_int8u)color); break; case C_AND: poke8_and(pp,(GR_int8u)color); break; default: poke8( pp,(GR_int8u)color); break; } GRX_LEAVE(); } /* -------------------------------------------------------------------- */ static void drawvline(int x,int y,int h,GrColor color) { int copr; GRX_ENTER(); copr = C_OPER(color); if(DOCOLOR8(color,copr)) { unsigned lwdt = CURC->gc_lineoffset; char *pp = &CURC->gc_baseaddr[0][FOFS(x,y,lwdt)]; SETFARSEL(CURC->gc_selector); switch(copr) { case C_XOR: colfill8_xor(pp,lwdt,(GR_int8u)color,h); break; case C_OR: colfill8_or( pp,lwdt,(GR_int8u)color,h); break; case C_AND: colfill8_and(pp,lwdt,(GR_int8u)color,h); break; default: colfill8( pp,lwdt,(GR_int8u)color,h); break; } } GRX_LEAVE(); } /* -------------------------------------------------------------------- */ static void drawhline(int x,int y,int w,GrColor color) { int copr; GRX_ENTER(); copr = C_OPER(color); if(DOCOLOR8(color,copr)) { GR_repl cval = freplicate_b(color); char *pp = &CURC->gc_baseaddr[0][FOFS(x,y,CURC->gc_lineoffset)]; SETFARSEL(CURC->gc_selector); switch(copr) { case C_XOR: repfill8_xor(pp,cval,w); break; case C_OR: repfill8_or( pp,cval,w); break; case C_AND: repfill8_and(pp,cval,w); break; default: repfill8( pp,cval,w); break; } } GRX_LEAVE(); } /* -------------------------------------------------------------------- */ static void drawblock(int x,int y,int w,int h,GrColor color) { int copr; GRX_ENTER(); copr = C_OPER(color); if(DOCOLOR8(color,copr)) { GR_repl cval = freplicate_b(color); unsigned int skip = CURC->gc_lineoffset; char *pp = &CURC->gc_baseaddr[0][FOFS(x,y,skip)]; skip -= w; SETFARSEL(CURC->gc_selector); switch(copr) { case C_XOR: do { int ww = w; repfill8_xor(pp,cval,ww); pp += skip; } while(--h != 0); break; case C_OR: do { int ww = w; repfill8_or(pp,cval,ww); pp += skip; } while(--h != 0); break; case C_AND: do { int ww = w; repfill8_and(pp,cval,ww); pp += skip; } while(--h != 0); break; default: do { int ww = w; repfill8(pp,cval,ww); pp += skip; } while(--h != 0); break; } } GRX_LEAVE(); } /* -------------------------------------------------------------------- */ #if defined(__GNUC__) && defined(__i386__) static void drawline(int x,int y,int dx,int dy,GrColor color) { struct { int errsub; int erradd; int offset1; int offset2; } lndata; int copr,xstep,npts,error; char *ptr; GRX_ENTER(); copr = C_OPER(color); if(!DOCOLOR8(color,copr)) goto done; # ifdef __GNUC__ # ifdef __i386__ # define ASM_LINE1(OPC) asm volatile("" \ " .align 2,0x90 \n" \ "0: "#OPC"b %6,"ASM_386_SEL"(%0) \n" \ " subl %7,%2 \n" \ " jb 1f \n" \ " decl %3 \n" \ " decl %1 \n" \ " jne 0b \n" \ " jmp 2f \n" \ " .align 2,0x90 \n" \ "1: addl 4 + %7,%2 \n" \ " addl 12 + %7,%3 \n" \ " decl %1 \n" \ " jne 0b \n" \ "2: " \ : "=r" (ptr), "=r" (npts), "=r" (error) \ : "0" ((long)(ptr)), "1" (npts), "2" (error), \ "q" ((char)(color)), "o" (lndata) \ ) # define ASM_LINE2(OPC) asm volatile("" \ " .align 2,0x90 \n" \ "0: "#OPC"b %6,"ASM_386_SEL"(%0) \n" \ " subl %7,%2 \n" \ " jb 1f \n" \ " addl 8 + %7,%3 \n" \ " decl %1 \n" \ " jne 0b \n" \ " jmp 2f \n" \ " .align 2,0x90 \n" \ "1: addl 4 + %7,%2 \n" \ " addl 12 + %7,%3 \n" \ " decl %1 \n" \ " jne 0b \n" \ "2: " \ : "=r" (ptr), "=r" (npts), "=r" (error) \ : "0" ((long)(ptr)), "1" (npts), "2" (error), \ "q" ((char)(color)), "o" (lndata) \ ) # endif # endif if(dy < 0) { y -= (dy = (-dy)); x -= (dx = (-dx)); } if(dx < 0) { xstep = (-1); dx = (-dx); } else xstep = 1; ptr = &CURC->gc_baseaddr[0][FOFS(x,y,CURC->gc_lineoffset)]; SETFARSEL(CURC->gc_selector); if(dx > dy) { npts = dx + 1; error = dx >> 1; lndata.errsub = dy; lndata.erradd = dx; lndata.offset1 = xstep; lndata.offset2 = CURC->gc_lineoffset + xstep; if(xstep < 0) { again_nonlinear: lndata.offset1 = 1; switch(copr) { case C_XOR: ASM_LINE1(xor); break; case C_OR: ASM_LINE1(or); break; case C_AND: ASM_LINE1(and); break; default: ASM_LINE1(mov); break; } if(npts == 0) goto done; goto again_nonlinear; } } else { npts = dy + 1; error = dy >> 1; lndata.errsub = dx; lndata.erradd = dy; lndata.offset1 = CURC->gc_lineoffset; lndata.offset2 = CURC->gc_lineoffset + xstep; } again_linear: switch(copr) { case C_XOR: ASM_LINE2(xor); break; case C_OR: ASM_LINE2(or); break; case C_AND: ASM_LINE2(and); break; default: ASM_LINE2(mov); break; } if(npts == 0) goto done; goto again_linear; done: GRX_LEAVE(); } #else static #include "fdrivers/generic/line.c" #endif /* -------------------------------------------------------------------- */ static void drawbitmap(int x,int y,int w,int h, char *bmp,int pitch,int start,GrColor fg,GrColor bg) { int fgop, bgop; int dofg, dobg; GRX_ENTER(); fgop = C_OPER(fg); bgop = C_OPER(bg); dofg = DOCOLOR8(fg,fgop); dobg = DOCOLOR8(bg,bgop); if(dofg | dobg) { long offs = FOFS(x,y,CURC->gc_lineoffset); int once = dofg && dobg && (fgop == bgop); int skip = CURC->gc_lineoffset; bmp += start >> 3; start &= 7; SETFARSEL(CURC->gc_selector); do { GR_int8u *bp = (GR_int8u *)bmp; GR_int8u bits = *bp; GR_int8u mask = 0x80 >> start; GR_int32u w1 = w; char *pp = &CURC->gc_baseaddr[0][offs]; # define DOBOTH(POKEOP) do { \ POKEOP(pp,((bits&mask)?(GR_int8u)fg:(GR_int8u)bg)); \ if((mask >>= 1) == 0) bits = *++bp,mask = 0x80; \ pp++; \ } while(--w1 != 0) # define DOFGC(POKEOP) do { \ if((mask & bits) != 0) POKEOP(pp,(GR_int8u)fg); \ if((mask >>= 1) == 0) bits = *++bp,mask = 0x80; \ pp++; \ } while(--w1 != 0) # define DOBGC(POKEOP) do { \ if((mask & bits) == 0) POKEOP(pp,(GR_int8u)bg); \ if((mask >>= 1) == 0) bits = *++bp,mask = 0x80; \ pp++; \ } while(--w1 != 0) if(once) switch(fgop) { case C_XOR: DOBOTH(poke8_xor); break; case C_OR: DOBOTH(poke8_or); break; case C_AND: DOBOTH(poke8_and); break; default: DOBOTH(poke8); break; } else { char *ppsave = pp; GR_int32u w1save = w1; if(dofg) switch(fgop) { case C_XOR: DOFGC(poke8_xor); break; case C_OR: DOFGC(poke8_or); break; case C_AND: DOFGC(poke8_and); break; default: DOFGC(poke8); break; } if(dobg) { pp = ppsave; w1 = w1save; bp = (GR_int8u *)bmp; bits = *bp; mask = 0x80 >> start; switch(bgop) { case C_XOR: DOBGC(poke8_xor); break; case C_OR: DOBGC(poke8_or); break; case C_AND: DOBGC(poke8_and); break; default: DOBGC(poke8); break; } } } offs += skip; bmp += pitch; } while(--h != 0); } GRX_LEAVE(); } /* -------------------------------------------------------------------- */ static #include "fdrivers/generic/pattern.c" /* -------------------------------------------------------------------- */ #ifdef FAR_ACCESS #define bitblit _GrFrDrvPackedBitBltV2V_LFB #define bltr2v _GrFrDrvPackedBitBltR2V_LFB #define bltv2r _GrFrDrvPackedBitBltV2R_LFB #else #define bitblit _GrFrDrvPackedBitBltR2R #endif /* -------------------------------------------------------------------- */ static #include "fdrivers/generic/getiscl.c" /* -------------------------------------------------------------------- */ static #include "fdrivers/generic/putscl.c" /* -------------------------------------------------------------------- */