/** ** rblit_14.c ---- ram to ram blit support functions for 1bpp and ** 4bpp RAM frame drivers ** ** Copyright (c) 1998 Hartmut Schirmer ** ** 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. ** **/ #include "libgrx.h" #include "grdriver.h" #include "allocate.h" #include "arith.h" #include "mempeek.h" #include "memcopy.h" #include "memfill.h" #include "fdrivers/rblit_14.h" /* frame offset address calculation */ #define FOFS(x,y,lo) umuladd32((y),(lo),((x)>>3)) #define maskoper(d,op,s,msk) do { \ unsigned char _c_ = peek_b(d); \ poke_b((d), (_c_ & ~(msk)) | ((_c_ op (s)) & (msk))); \ } while (0) #define maskset(d,c,msk) \ poke_b((d),(peek_b(d) & ~(msk)) | ((c) & (msk))) static char *LineBuff = NULL; static int do_alloc(int width) { size_t bytes; GRX_ENTER(); bytes = sizeof(char) * (((width+7) >> 3)+2); LineBuff = _GrTempBufferAlloc(bytes); GRX_RETURN(LineBuff != NULL); } static void get_scanline(char *dptr, char *sptr, int w) { GRX_ENTER(); fwdcopy_set(sptr,dptr,sptr,w); GRX_LEAVE(); } static void put_scanline(char *dptr,char *sptr,int w, GR_int8u lm, GR_int8u rm, int op ) { GRX_ENTER(); if (w==1) lm &= rm; if ( ((GR_int8u)(~lm)) ) { switch (op) { case C_XOR: maskoper(dptr,^,*sptr,lm); break; case C_OR : maskoper(dptr,|,*sptr,lm); break; case C_AND: maskoper(dptr,&,*sptr,lm); break; default : maskset(dptr,*sptr,lm); break; } if (--w == 0) goto done; ++dptr; ++sptr; } if ( ((GR_int8u)(~rm)) ) --w; if (w) switch (op) { case C_XOR: fwdcopy_xor(dptr,dptr,sptr,w); break; case C_OR : fwdcopy_or( dptr,dptr,sptr,w); break; case C_AND: fwdcopy_and(dptr,dptr,sptr,w); break; default : fwdcopy_set(dptr,dptr,sptr,w); break; } if ( ((GR_int8u)(~rm)) ) switch (op) { case C_XOR: maskoper(dptr,^,*sptr,rm); break; case C_OR : maskoper(dptr,|,*sptr,rm); break; case C_AND: maskoper(dptr,&,*sptr,rm); break; default : maskset(dptr,*sptr,rm); break; } done: GRX_LEAVE(); } extern void _GR_shift_scanline(GR_int8u **dst, GR_int8u **src, int ws, int shift, int planes ); #define shift_scanline(dst,src,w,sh) \ _GR_shift_scanline((GR_int8u **)&(dst),(GR_int8u **)&(src),(w),(sh),1) void _GR_rblit_14(GrFrame *dst,int dx,int dy, GrFrame *src,int x,int y,int w,int h, GrColor op, int planes, _GR_blitFunc bitblt) { int pl; GRX_ENTER(); if(GrColorMode(op) != GrIMAGE && do_alloc(w)) { GR_int32u doffs, soffs; int oper = C_OPER(op); int shift = ((int)(x&7)) - ((int)(dx&7)); GR_int8u lm = 0xff >> (dx & 7); GR_int8u rm = 0xff << ((-(w + dx)) & 7); int ws = ((x+w+7) >> 3) - (x >> 3); int wd = ((dx+w+7) >> 3) - (dx >> 3); int dskip = dst->gf_lineoffset; int sskip = src->gf_lineoffset; if ((dy>y) && (dst->gf_baseaddr[0]==src->gf_baseaddr[0])) { /* reverse */ dy += h-1; y += h-1; doffs = FOFS(dx,dy,dskip); soffs = FOFS( x, y,sskip); for (pl=0; pl < planes; ++pl) { char *dptr = &dst->gf_baseaddr[pl][doffs]; char *sptr = &src->gf_baseaddr[pl][soffs]; int hh = h; if (shift) { while (hh-- > 0) { shift_scanline(LineBuff,sptr,ws,shift); put_scanline(dptr,LineBuff,wd,lm,rm,oper); dptr -= dskip; sptr -= sskip; } } else { while (hh-- > 0) { get_scanline(LineBuff, sptr, ws); put_scanline(dptr,LineBuff,wd,lm,rm,oper); dptr -= dskip; sptr -= sskip; } } } } else { /* forward */ doffs = FOFS(dx,dy,dst->gf_lineoffset); soffs = FOFS( x, y,src->gf_lineoffset); for (pl=0; pl < planes; ++pl) { char *dptr = &dst->gf_baseaddr[pl][doffs]; char *sptr = &src->gf_baseaddr[pl][soffs]; int hh = h; if (shift) { while (hh-- > 0) { shift_scanline(LineBuff,sptr,ws,shift); put_scanline(dptr,LineBuff,wd,lm,rm,oper); dptr += dskip; sptr += sskip; } } else { while (hh-- > 0) { put_scanline(dptr,sptr,wd,lm,rm,oper); dptr += dskip; sptr += sskip; } } } } } else bitblt(dst,dx,dy,src,x,y,w,h,op); GRX_LEAVE(); }