NetBSD/sys/arch/newsmips/dev/fb_start.c

3517 lines
72 KiB
C

/* $NetBSD: fb_start.c,v 1.3 1999/02/15 04:36:34 hubertf Exp $ */
/*
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: $Hdr: fb_start.c,v 4.300 91/06/27 20:42:40 root Rel41 $ SONY
*
* @(#)fb_start.c 8.1 (Berkeley) 6/11/93
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <machine/framebuf.h>
#include <newsmips/dev/fbreg.h>
#include <newsmips/dev/fbdefs.h>
#define spl7 splhigh
#ifdef CPU_SINGLE
#include <machine/cpu.h>
extern struct tty cons;
extern int cnstart();
#define PRE_EMPT need_resched()
#endif
extern void mem_to_mem();
extern void mem_clear();
#ifdef IPC_MRX
static void iopmemfbmap __P((caddr_t, int, struct fb_map *));
#endif
static void checkArea __P((struct fbdev *, int *, int *));
static int cursorIn __P((struct fbdev *, lRectangle *));
static void fbcopy1 __P((lPoint, lPoint, char *));
static void fbcopy2 __P((lPoint, lPoint));
static void fbcopy3 __P((lPoint, lPoint));
static void cursorOn __P((struct fbdev *));
static void cursorOff __P((struct fbdev *));
static void softCursorCheck
__P((struct fbdev *, char, lRectangle *, char, lRectangle *));
static void cursorCheck
__P((struct fbdev *, char, lRectangle *, char, lRectangle *));
static int redrawCursor __P((struct fbdev *));
static int setCursor __P((struct fbdev *, lCursor2 *));
static int showCursor __P((struct fbdev *));
static int hideCursor __P((struct fbdev *));
static int moveCursor __P((struct fbdev *, lPoint *));
#ifdef notdef
#ifdef CPU_SINGLE
static int rop_xint __P((void));
#endif
#endif
static int cliprect2 __P((lRectangle *, lRectangle *, lRectangle *, lRectangle *));
static int cliprect __P((lRectangle *, lRectangle *, lRectangle *));
static int getclip __P((struct fbdev *, lBitmap *, lRectangle *));
static int clipsrc __P((struct fbdev *, lBitmap *));
static int setrop
__P((struct fbdev *, u_int, int, int, int, int, lBitmap *, lBitmap *));
static int bitblt_fb
__P((struct fbdev *, lBitmap *, lRectangle *, lBitmap *, lPoint *, lRectangle *));
static int bitblt_tofb
__P((struct fbdev *, lBitmap *, lRectangle *, lBitmap *, lPoint *, lRectangle *));
static int bitblt_tomem
__P((struct fbdev *, lBitmap *, lRectangle *, lBitmap *, lPoint *, lRectangle *));
static int bitblt_mem
__P((struct fbdev *, lBitmap *, lRectangle *, lBitmap *, lPoint *, lRectangle *));
static int bitblt_nop __P((void));
static int bitblt_0tofb
__P((struct fbdev *, lBitmap *, lRectangle *, lBitmap *, lPoint *, lRectangle *));
static int bitblt_1tofb
__P((struct fbdev *, lBitmap *, lRectangle *, lBitmap *, lPoint *, lRectangle *));
static int bitblt_0tomem
__P((struct fbdev *, lBitmap *, lRectangle *, lBitmap *, lPoint *, lRectangle *));
static int bitblt_1tomem
__P((struct fbdev *, lBitmap *, lRectangle *, lBitmap *, lPoint *, lRectangle *));
static int (*sel_ropfunc __P((int, int)))();
static int bitbltcmd __P((struct fbdev *, lBitblt *));
static int batch_bitblt_01tofb
__P((struct fbdev *, lBitmap *, lRectangle *, lSrcDest *, int, int));
static int batch_bitblt_fb
__P((struct fbdev *, lBitmap *, lRectangle *, lSrcDest *, int));
static int batch_bitblt_tofb
__P((struct fbdev *, lBitmap *, lBitmap *, lRectangle *, lSrcDest *, int));
static int batchbitbltcmd __P((struct fbdev *, lBatchBitblt *));
static int tilebitbltcmd __P((struct fbdev *, lTileBitblt *));
static int bitblt3cmd __P((struct fbdev *, lBitblt3 *));
static int draw_rectangle __P((struct fbdev *, lPrimRect *));
static int draw_polymarker __P((struct fbdev *, lPrimMarker *));
static void fill_line __P((struct fbdev *, int, lPoint *, int, int));
static int fill_scan __P((struct fbdev *, lPrimFill *));
static int put_string __P((struct fbdev *, lPrimText *));
static void mem_vector
__P((struct fbdev *, lPoint *, lPoint *, int, lBitmap *, int));
static int draw_polyline __P((struct fbdev *, lPrimLine *));
static int draw_dj_polyline __P((struct fbdev *, lPrimLine *));
static int emulate_polydot __P((struct fbdev *, lPrimDot *));
#ifndef CPU_DOUBLE
static void mem_dot __P((struct fbdev *, lPoint *, int, lBitmap *));
#endif
static int draw_polydot __P((struct fbdev *, lPrimDot *));
static int get_scrtype __P((struct fbdev *, lScrType *));
static struct fbdev *cfb = 0;
static lPoint mp;
#ifdef CPU_SINGLE
static int curs_pending = 0;
#endif
extern struct fbdevsw fbdevsw[];
extern int nfbdev;
#ifdef CPU_SINGLE
extern char *ext_fnt_addr[];
extern char *ext_fnt24_addr[];
#else
extern char **ext_fnt_addr;
extern char **ext_fnt24_addr;
#endif
static char copyfuncv[MAXPLANE] = {
BF_S, BF_S, BF_S, BF_S, BF_S, BF_S, BF_S, BF_S, /* SRC */
BF_S, BF_S, BF_S, BF_S, BF_S, BF_S, BF_S, BF_S, /* SRC */
BF_S, BF_S, BF_S, BF_S, BF_S, BF_S, BF_S, BF_S /* SRC */
};
unsigned short fb_color_pallet_def[48] = { /* define initial color */
/* R, G, B */
0, 0, 0,
0, 0, 0x44,
0, 0x44, 0,
0, 0x44, 0x44,
0x44, 0, 0,
0x44, 0, 0x44,
0x44, 0x44, 0,
0x44, 0x44, 0x44,
0x88, 0x88, 0x88,
0, 0, 0xff,
0, 0xff, 0,
0, 0xff, 0xff,
0xff, 0, 0,
0xff, 0, 0xff,
0xff, 0xff, 0,
0xff, 0xff, 0xff
};
unsigned short fb_gray_pallet_def[48] = { /* define initial color */
/* R, G, B */
0xff, 0xff, 0xff,
0xff, 0xff, 0,
0xff, 0, 0xff,
0xff, 0, 0,
0, 0xff, 0xff,
0, 0xff, 0,
0, 0, 0xff,
0x88, 0x88, 0x88,
0x44, 0x44, 0x44,
0x44, 0x44, 0,
0x44, 0, 0x44,
0x44, 0, 0,
0, 0x44, 0x44,
0, 0x44, 0,
0, 0, 0x44,
0, 0, 0
};
static int bitmap_use; /* shared variable for bitmap exclusion ctrl */
#ifdef IPC_MRX
struct fb_map rommap;
#endif
#ifdef CPU_SINGLE
void
lock_bitmap()
{
int s;
/* wait(bitmap_use) */
s = splbitmap();
while (bitmap_use & FB_BUSY) {
bitmap_use |= FB_WANTED;
sleep((caddr_t)&bitmap_use, FBPRI);
}
bitmap_use |= FB_BUSY;
splx(s);
}
void
unlock_bitmap()
{
int s;
/* signal(bitmap_use) */
s = splbitmap();
if (bitmap_use & FB_WANTED)
wakeup((caddr_t)&bitmap_use);
bitmap_use &= ~(FB_BUSY|FB_WANTED);
splx(s);
}
int
lock_bitmap_poll()
{
int s;
/* wait(bitmap_use) */
s = splbitmap();
if (bitmap_use & (FB_BUSY|FB_WANTED)) {
splx(s);
return (1);
}
bitmap_use |= FB_BUSY;
splx(s);
return (0);
}
void
unlock_bitmap_poll()
{
int s;
/* signal(bitmap_use) */
s = splbitmap();
if (bitmap_use & FB_WANTED)
wakeup((caddr_t)&bitmap_use);
bitmap_use &= ~(FB_BUSY|FB_WANTED);
splx(s);
}
int
bmlockedp()
{
return (bitmap_use & (FB_WANTED|FB_BUSY));
}
#ifdef NOTDEF /* KU:XXX not necessary for news3200 */
void
rop_wait(fb)
struct fbdev *fb;
{
register int s;
int i;
s = splbitmap();
/* KU:XXX trick! */
#define in_interrupt() ((caddr_t)&fb < (caddr_t)MACH_CODE_START)
if (in_interrupt() || (fb->run_flag & FB_WAITING)) {
splx(s);
fbbm_rop_wait(fb);
} else {
if (fbbm_ioctl(fb, FB_STATUSCHECK, 0) &
(FB_STATUS_ROPWAIT|FB_STATUS_ROPEXEC)) {
i = FB_INT_ROPDONE;
fbbm_ioctl(fb, FB_INTENABLE, &i);
if (!(fbbm_ioctl(fb, FB_STATUSCHECK, 0) &
(FB_STATUS_ROPWAIT|FB_STATUS_ROPEXEC))) {
i = FB_INT_ROPDONE;
fbbm_ioctl(fb, FB_INTCLEAR, &i);
} else {
fb->run_flag |= FB_WAITING;
sleep((caddr_t)&fb->run_flag, FBPRI);
}
}
splx(s);
}
}
#endif /* NOTDEF */
#else /* CPU_SINGLE */
#ifdef IPC_MRX
struct page {
char bytes[NBPG];
};
extern struct page *page_base;
extern struct page *page_max;
extern struct map pagemap[];
extern struct pte_iop page_pt[];
extern int mapped_page;
caddr_t
fb_map_page(map, n, prot)
register int *map;
register int n;
register int prot;
{
register int x;
register struct pte_iop *p;
register struct page *addr;
register int s = splhigh();
static int last_x, last_n;
if (last_n >= n) {
x = last_x;
} else {
rmfree(pagemap, last_n, last_x);
mapped_page -= last_n;
last_x = 0;
last_n = 0;
if ((x = rmalloc(pagemap, n)) <= 0) {
splx(s);
return (NULL);
}
mapped_page += n;
last_x = x;
last_n = n;
}
addr = page_base + x;
prot |= PG_PAGE;
for (p = page_pt + x; n > 0; p++, n--) {
*(int *)p = prot | *map++;
tbis((caddr_t)addr);
addr++;
}
splx(s);
return ((caddr_t)(page_base + x));
}
caddr_t
fb_map_page2(map, n, prot)
register int *map;
register int n;
register int prot;
{
register int x;
register struct pte_iop *p;
register struct page *addr;
register int s;
if (n == 0)
return (NULL);
s = spl7();
if ((x = rmalloc(pagemap, n)) <= 0) {
splx(s);
return (NULL);
}
mapped_page += n;
addr = page_base + x;
prot |= PG_PAGE;
for (p = page_pt + x; n > 0; p++, n--) {
*(int *)p = prot | (*map++);
tbis((caddr_t)addr);
addr++;
}
splx(s);
return ((caddr_t)(page_base + x));
}
#endif /* IPC_MRX */
#endif /* CPU_SINGLE */
#ifdef IPC_MRX
void
iopmemfbmap(addr, len, map)
register caddr_t addr;
register int len;
register struct fb_map *map;
{
register caddr_t *p;
register int i;
map->fm_vaddr = addr;
map->fm_offset = (unsigned)addr & CLOFSET;
map->fm_count = len;
len += map->fm_offset;
p = map->fm_addr;
addr -= map->fm_offset;
for (i = 0; i < NFBMAP && len > 0; i++) {
*p++ = addr;
addr += CLBYTES;
len -= CLBYTES;
}
}
#endif /* IPC_MRX */
int
nofunc()
{
return 0;
}
int
fb_error()
{
return FB_RERROR;
}
void
checkArea(fb, x, y)
register struct fbdev *fb;
register int *x, *y;
{
if (*x < fb->moveArea.origin.x)
*x = fb->moveArea.origin.x;
if (*y < fb->moveArea.origin.y)
*y = fb->moveArea.origin.y;
if (*x >= (fb->moveArea.origin.x + fb->moveArea.extent.x))
*x = (fb->moveArea.origin.x + fb->moveArea.extent.x) - 1;
if (*y >= (fb->moveArea.origin.y + fb->moveArea.extent.y))
*y = (fb->moveArea.origin.y + fb->moveArea.extent.y) - 1;
}
int
cursorIn(fb, clip)
register struct fbdev *fb;
register lRectangle *clip;
{
if (clip == 0)
return (1);
if (cfb != fb)
return (0);
return (clip->origin.x < fb->cursorP.x + fb->size.x &&
clip->origin.x + clip->extent.x > fb->cursorP.x &&
clip->origin.y < fb->cursorP.y + fb->size.y &&
clip->origin.y + clip->extent.y > fb->cursorP.y);
}
void
fbcopy1(src, dst, fv)
lPoint src;
lPoint dst;
char *fv;
{
lRectangle sr, dr;
sr.origin = src;
sr.extent = cfb->size;
dr.origin = dst;
if (cliprect2(&sr, &cfb->FrameRect, &dr, &cfb->VisRect)) {
fbbm_rop_init(cfb, fv);
fbbm_rop_copy(cfb, &sr, &dr.origin, 1, FB_PLANEALL);
}
}
void
fbcopy2(src, dst)
lPoint src;
lPoint dst;
{
lRectangle sr, dr;
sr.origin = src;
sr.extent = cfb->size;
dr.origin = dst;
if (cliprect2(&sr, &cfb->FrameRect, &dr, &cfb->FrameRect)) {
fbbm_rop_init(cfb, copyfuncv);
fbbm_rop_copy(cfb, &sr, &dr.origin, 0, FB_PLANEALL);
}
}
void
fbcopy3(src, dst)
lPoint src;
lPoint dst;
{
lRectangle sr, dr;
sr.origin = src;
sr.extent = cfb->size;
dr.origin = dst;
if (cliprect2(&sr, &cfb->FrameRect, &dr, &cfb->VisRect)) {
fbbm_rop_init(cfb, copyfuncv);
fbbm_rop_copy(cfb, &sr, &dr.origin, 0, FB_PLANEALL);
}
}
void
cursorOn(fb)
register struct fbdev *fb;
{
#ifdef CPU_SINGLE
int s = splbitmap();
#endif
if (cfb == fb && fb->cursorShow && !fb->cursorVis) {
if (fb->hard_cursor) {
fbbm_cursor_on(fb);
} else {
fbcopy2(fb->cursorP, fb->SaveRect.origin);
fbcopy1(fb->MaskRect.origin, fb->cursorP,
fb->maskfuncv);
fbcopy1(fb->CursorRect.origin, fb->cursorP,
fb->curfuncv);
}
fb->cursorVis = 1;
}
#ifdef CPU_SINGLE
splx(s);
#endif
}
void
cursorOff(fb)
register struct fbdev *fb;
{
#ifdef CPU_SINGLE
int s = splbitmap();
#endif
if (cfb == fb && fb->cursorShow && fb->cursorVis) {
if (fb->hard_cursor)
fbbm_cursor_off(fb);
else
fbcopy3(fb->SaveRect.origin, fb->cursorP);
fb->cursorVis = 0;
}
#ifdef CPU_SINGLE
splx(s);
#endif
}
void
softCursorCheck(fb, stype, srect, dtype, drect)
struct fbdev *fb;
char stype, dtype;
lRectangle *srect, *drect;
{
if (cfb == fb && cfb->cursorVis &&
((stype == BM_FB && cursorIn(fb, srect)) ||
(dtype == BM_FB && cursorIn(fb, drect))))
cursorOff(cfb);
}
void
cursorCheck(fb, stype, srect, dtype, drect)
struct fbdev *fb;
char stype, dtype;
lRectangle *srect, *drect;
{
if (!fb->hard_cursor)
softCursorCheck(fb, stype, srect, dtype, drect);
}
int
redrawCursor(fb)
register struct fbdev *fb;
{
int s;
lPoint tmp;
if (cfb == fb && fb->cursorSet) {
s = spl7();
tmp = mp;
splx(s);
#ifdef CPU_SINGLE
s = splbitmap();
#endif
if (fb->cursorP.x != tmp.x || fb->cursorP.y != tmp.y) {
if (fb->cursorVis) {
if (! fb->hard_cursor) {
fbcopy3(fb->SaveRect.origin,
fb->cursorP);
}
}
fb->cursorP = tmp;
if (fb->hard_cursor) {
fbbm_cursor_off(fb);
fbbm_cursor_move(fb);
}
if (fb->cursorVis) {
if (fb->hard_cursor) {
fbbm_cursor_on(fb);
} else {
fbcopy2(fb->cursorP,
fb->SaveRect.origin);
fbcopy1(fb->MaskRect.origin,
fb->cursorP, fb->maskfuncv);
fbcopy1(fb->CursorRect.origin,
fb->cursorP, fb->curfuncv);
}
}
}
#ifdef CPU_SINGLE
splx(s);
#endif
}
return (0);
}
void
updateCursor(x, y, flag)
int *x, *y;
int flag;
{
int s;
if (cfb && cfb->cursorSet) {
checkArea(cfb, x, y);
s = spl7();
mp.x = *x - cfb->hot.x;
mp.y = *y - cfb->hot.y;
splx(s);
#ifdef CPU_SINGLE
if (flag || cfb->hard_cursor) {
curs_pending = 0;
redrawCursor(cfb);
} else if (cfb->type == FB_LCDM) {
if (!lock_bitmap_poll()) {
curs_pending = 0;
redrawCursor(cfb);
unlock_bitmap_poll();
} else {
curs_pending = 1;
}
}
#else
redrawCursor(cfb);
#endif
}
}
int
setCursor(fb, cursor)
register struct fbdev *fb;
register lCursor2 *cursor;
{
register char *fv;
register int f0, f1, i, color;
#ifdef CPU_SINGLE
register int s = splbitmap();
#endif
int data;
if (cfb == fb) {
cursorOff(cfb);
fb->cursorShow = 0;
fb->cursorP.x += cfb->hot.x;
fb->cursorP.y += cfb->hot.y;
#ifdef CPU_SINGLE
data = FB_INT_VSYNC;
fbbm_ioctl(fb, FB_INTCLEAR, &data);
#endif
cfb = NULL;
}
if (cursor) {
fb->CursorRect = cursor->cursorRect;
fb->MaskRect = cursor->maskRect;
fb->SaveRect = cursor->saveRect;
fb->moveArea = cursor->moveArea;
fb->hot = cursor->hot;
fb->size = cursor->size;
f0 = 0x4 | ((cursor->func >> 2) & 0x3);
f1 = 0x4 | (cursor->func & 0x3);
i = fb->fbNplane;
fv = fb->curfuncv;
color = cursor->cursor_color;
while (i-- > 0) {
*fv++ = (color & 1) ? f1 : f0;
color >>= 1;
}
i = fb->fbNplane;
fv = fb->maskfuncv;
color = cursor->mask_color;
while (i-- > 0) {
*fv++ = (color & 1) ? f1 : f0;
color >>= 1;
}
checkArea(fb, &fb->cursorP.x, &fb->cursorP.y);
fb->cursorP.x -= fb->hot.x;
fb->cursorP.y -= fb->hot.y;
fb->cursorSet = 1;
fb->cursorShow = 0;
fb->cursorVis = 0;
if (fb->hard_cursor) {
fbbm_cursor_off(fb);
fbbm_cursor_set(fb, cursor->cursor_color, cursor->mask_color);
fbbm_cursor_move(fb);
}
} else {
fb->cursorP.x = fb->VisRect.extent.x / 2;
fb->cursorP.y = fb->VisRect.extent.y / 2;
fb->cursorSet = 0;
fb->cursorShow = 0;
fb->cursorVis = 0;
if (fb->hard_cursor)
fbbm_cursor_off(fb);
}
#ifdef CPU_SINGLE
splx(s);
#endif
return (FB_ROK);
}
int
showCursor(fb)
register struct fbdev *fb;
{
int data;
#ifdef CPU_SINGLE
register int s = splbitmap();
#endif
if (fb->cursorSet && !fb->cursorShow) {
if (cfb && cfb != fb) {
cursorOff(cfb);
cfb->cursorShow = 0;
}
cfb = fb;
fb->cursorShow = 1;
mp = fb->cursorP;
cursorOn(fb);
#ifdef CPU_SINGLE
data = FB_INT_VSYNC;
fbbm_ioctl(fb, FB_INTENABLE, &data);
splx(s);
#endif
return (FB_ROK);
}
#ifdef CPU_SINGLE
splx(s);
#endif
return (FB_RERROR);
}
int
hideCursor(fb)
register struct fbdev *fb;
{
int data;
#ifdef CPU_SINGLE
int s = splbitmap();
#endif
if (cfb == fb) {
cursorOff(fb);
fb->cursorShow = 0;
#ifdef CPU_SINGLE
data = FB_INT_VSYNC;
fbbm_ioctl(fb, FB_INTCLEAR, &data);
splx(s);
#endif
return (FB_ROK);
}
#ifdef CPU_SINGLE
splx(s);
#endif
return (FB_RERROR);
}
int
moveCursor(fb, point)
struct fbdev *fb;
lPoint *point;
{
if (cfb == fb) {
updateCursor(&point->x, &point->y, 1);
return (FB_ROK);
}
return (FB_RERROR);
}
#ifdef notyet
#ifdef CPU_SINGLE
int
rop_xint()
{
register struct fbdev *fb;
register int i;
register int done = 0;
int event, data;
int s = splbitmap();
for (i = 0, fb = fbdev; i < nfbdev; i++, fb++) {
if (fb->type && (event = fbbm_ioctl(fb, FB_INTCHECK, 0))) {
#ifdef notyet /* KU:XXX */
intrcnt[INTR_BITMAP]++;
#endif
done = 1;
if (event & FB_INT_VSYNC) {
data = FB_INT_VSYNC;
fbbm_ioctl(fb, FB_INTCLEAR, &data);
if (!lock_bitmap_poll()) {
curs_pending = 0;
redrawCursor(fb);
unlock_bitmap_poll();
} else {
curs_pending = 1;
}
data = FB_INT_VSYNC;
fbbm_ioctl(fb, FB_INTENABLE, &data);
}
if (event & FB_INT_ROPDONE) {
if(fb->run_flag & FB_WAITING) {
data = FB_INT_ROPDONE;
fbbm_ioctl(fb, FB_INTCLEAR, &data);
if (!(fbbm_ioctl(fb, FB_STATUSCHECK, 0)
& (FB_STATUS_ROPWAIT|FB_STATUS_ROPEXEC))) {
fb->run_flag &= ~FB_WAITING;
wakeup(&(fb->run_flag));
} else {
data = FB_INT_ROPDONE|0x100;
fbbm_ioctl(fb, FB_INTENABLE, &data);
}
}
}
}
}
splx(s);
return (done);
}
#endif /* CPU_SINGLE */
#endif
int
cliprect2(sr, sc, dr, dc)
register lRectangle *sr;
register lRectangle *sc;
register lRectangle *dr;
register lRectangle *dc;
{
register int d;
/* src left/right edge */
if ((d = sr->origin.x - sc->origin.x) < 0) {
sr->extent.x += d;
sr->origin.x -= d;
dr->origin.x -= d;
d = sr->extent.x - sc->extent.x;
} else
d += sr->extent.x - sc->extent.x;
if (d > 0)
sr->extent.x -= d;
/* src top/bottom edge */
if ((d = sr->origin.y - sc->origin.y) < 0) {
sr->extent.y += d;
sr->origin.y -= d;
dr->origin.y -= d;
d = sr->extent.y - sc->extent.y;
} else
d += sr->extent.y - sc->extent.y;
if (d > 0)
sr->extent.y -= d;
if (sr->extent.x <= 0 || sr->extent.y <= 0)
return (0);
/* dst left/right edge */
if ((d = dr->origin.x - dc->origin.x) < 0) {
dr->origin.x -= d;
sr->extent.x += d;
sr->origin.x -= d;
d = sr->extent.x - dc->extent.x;
} else
d += sr->extent.x - dc->extent.x;
if (d > 0)
sr->extent.x -= d;
/* dst top/bottom edge */
if ((d = dr->origin.y - dc->origin.y) < 0) {
dr->origin.y -= d;
sr->extent.y += d;
sr->origin.y -= d;
d = sr->extent.y - dc->extent.y;
} else
d += sr->extent.y - dc->extent.y;
if (d > 0)
sr->extent.y -= d;
if (sr->extent.x <= 0 || sr->extent.y <= 0)
return (0);
dr->extent = sr->extent;
return (1);
}
int
cliprect(r, crp, p)
register lRectangle *r;
register lRectangle *crp;
register lRectangle *p;
{
register int d;
/* left edge */
if ((d = r->origin.x - crp->origin.x) < 0) {
r->extent.x += d;
r->origin.x -= d;
if (p) {
p->extent.x += d;
p->origin.x -= d;
}
d = r->extent.x - crp->extent.x;
} else
d += r->extent.x - crp->extent.x;
/* right edge */
if (d > 0) {
r->extent.x -= d;
if (p)
p->extent.x -= d;
}
/* top edge */
if ((d = r->origin.y - crp->origin.y) < 0) {
r->extent.y += d;
r->origin.y -= d;
if (p) {
p->extent.y += d;
p->origin.y -= d;
}
d = r->extent.y - crp->extent.y;
} else
d += r->extent.y - crp->extent.y;
/* bottom edge */
if (d > 0) {
r->extent.y -= d;
if (p)
p->extent.y -= d;
}
return (r->extent.x > 0 && r->extent.y > 0);
}
int
getclip(fb, bmp, crp)
struct fbdev *fb;
lBitmap *bmp;
lRectangle *crp;
{
/* limit clip rectangle to bitmap rectangle */
if (!cliprect(crp, &bmp->rect, (lRectangle*)0))
return (0);
/* limit clip rectangle to frame buffer */
if ((bmp->type == BM_FB) &&
!cliprect(crp, &fb->FrameRect, (lRectangle*)0))
return (0);
return (1);
}
int
clipsrc(fb, bmp)
struct fbdev *fb;
lBitmap *bmp;
{
/* limit clip rectangle to frame buffer */
if (bmp->type == BM_FB &&
!cliprect(&bmp->rect, &fb->FrameRect, (lRectangle*)0))
return (0);
return (1);
}
int
setrop(fb, func, pmask, fore, aux, trans, sbp, dbp)
register struct fbdev *fb;
register unsigned int func;
int pmask;
register int fore, aux;
int trans;
lBitmap *sbp, *dbp;
{
register char *funcp;
register int i;
char tmp[4];
/* set plane register */
fb->Mode = 0;
fb->Pmask = pmask;
fb->func = func;
fb->fore = fore;
fb->aux = aux;
fb->trans = trans;
if (sbp->depth > 1)
fb->Mode |= 2;
if (dbp->depth > 1)
fb->Mode |= 1;
/* set rop function register */
func &= 0xf;
tmp[0] = TRANS(trans, (func & 0x0c) | (func>>2));
tmp[1] = TRANS(trans, (func>>2) | ((func<<2) & 0x0c));
tmp[2] = TRANS(trans, func);
tmp[3] = TRANS(trans, ((func<<2) & 0x0c) | (func & 3));
funcp = fb->funcvec;
for (i = fb->fbNplane; --i >= 0;) {
*funcp++ = tmp[((fore & 1) << 1) | (aux & 1)];
fore >>= 1; aux >>= 1;
}
return (0);
}
/*
* bitblt within frame buffer
*/
int
bitblt_fb(fb, sbp, srp, dbp, dpp, crp)
register struct fbdev *fb;
register lBitmap *sbp; /* source bitmap (FB) */
lRectangle *srp; /* source rectangle */
lBitmap *dbp; /* destination bitmap (FB) */
lPoint *dpp; /* destination point */
lRectangle *crp; /* clip region in destination */
{
lRectangle sr;
lRectangle dr;
register int wplane, i, j;
sr = *srp;
dr.origin = *dpp;
if (crp && !cliprect2(&sr, &sbp->rect, &dr, crp))
return (0);
fbbm_rop_init(fb, fb->funcvec);
switch (fb->Mode) {
case MODE_1to1:
fb->Pmask &= 1;
case MODE_NtoN:
fbbm_rop_copy(fb, &sr, &dr.origin, 0, fb->Pmask);
break;
case MODE_1toN:
fbbm_rop_copy(fb, &sr, &dr.origin, 1, fb->Pmask);
break;
case MODE_Nto1:
wplane = 1;
for (i = 0, j = sbp->depth; i < j; i++) {
if (fb->Pmask & wplane) {
fbbm_rop_copy(fb, &sr, &dr.origin, i + 1,
fb->Pmask >> 16);
break;
}
wplane <<= 1;
}
break;
default:
return (-1);
}
return (0);
}
/*
* bitblt from main memory to frame buffer
*/
int
bitblt_tofb(fb, sbp, srp, dbp, dpp, crp)
register struct fbdev *fb;
register lBitmap *sbp; /* source bitmap (MEM) */
lRectangle *srp; /* source rectangle */
lBitmap *dbp; /* destination bitmap (FB) */
lPoint *dpp; /* destination point */
lRectangle *crp; /* clip region in destination */
{
register unsigned p;
register struct fb_map *smap;
register int i, n, m;
lRectangle sr;
lRectangle dr;
register int wplane;
#ifdef IPC_MRX
extern struct fb_map rommap;
register int pages;
#endif
smap = (struct fb_map*)sbp->base;
sr = *srp;
dr.origin = *dpp;
if (crp && !cliprect2(&sr, &sbp->rect, &dr, crp))
return (0);
dr.extent = sr.extent;
/* transform source rectangle */
sr.origin.x -= sbp->rect.origin.x;
sr.origin.y -= sbp->rect.origin.y;
/*
* check memory map specification
*/
p = smap->fm_offset;
#ifdef IPC_MRX
pages = btoc(smap->fm_offset + smap->fm_count);
rommap.fm_vaddr = fb_map_page(smap->fm_addr, pages,
fb->cache_off ? PG_S|PG_WP|PG_CI : PG_S|PG_WP);
rommap.fm_offset = 0;
smap = &rommap;
#endif
wplane = 1;
fbbm_rop_winit(fb);
switch (fb->Mode) {
case MODE_1to1:
fbbm_rop_write(fb, smap, p, sbp->width,
&sr, &dr, fb->Pmask & 0x01);
break;
case MODE_1toN:
fbbm_rop_write(fb, smap, p, sbp->width,
&sr, &dr, fb->Pmask);
break;
case MODE_Nto1:
m = sbp->width * sbp->rect.extent.y;
for (i = 0; i < sbp->depth; i++, wplane <<= 1) {
if (fb->Pmask & wplane) {
p += (m * i) << 1;
fbbm_rop_write(fb, smap, p, sbp->width,
&sr, &dr, wplane);
break;
}
wplane <<= 1;
}
break;
case MODE_NtoN:
n = imin(sbp->depth, fb->fbNplane);
m = sbp->width * sbp->rect.extent.y;
p += (m << 1) * n;
wplane = 1 << (n - 1);
for (i = n; i > 0; i--) {
/* get next plane */
p -= m << 1;
if (fb->Pmask & wplane)
fbbm_rop_write(fb, smap, p, sbp->width,
&sr, &dr, wplane);
/* next plane mask */
wplane >>= 1;
}
break;
default:
return (-1);
}
return (0);
}
/*
* bitblt from frame buffer to main memroy
*/
int
bitblt_tomem(fb, sbp, srp, dbp, dpp, crp)
struct fbdev *fb;
lBitmap *sbp; /* source bitmap (FB) */
lRectangle *srp; /* source rectangle */
lBitmap *dbp; /* destination bitmap (MEM) */
lPoint *dpp; /* destination point */
lRectangle *crp; /* clip region in destination */
{
register struct fb_map *dmap;
register unsigned p;
register int i, n, m;
lRectangle sr;
lRectangle dr;
int plane;
#ifdef IPC_MRX
extern struct fb_map rommap;
register int pages;
#endif
dmap = (struct fb_map*)dbp->base;
sr = *srp;
dr.origin = *dpp;
if (crp && !cliprect2(&sr, &sbp->rect, &dr, crp))
return (0);
dr.extent = sr.extent;
dr.origin.x -= dbp->rect.origin.x;
dr.origin.y -= dbp->rect.origin.y;
p = dmap->fm_offset;
#ifdef IPC_MRX
pages = btoc(dmap->fm_offset + dmap->fm_count);
rommap.fm_vaddr = fb_map_page(dmap->fm_addr, pages, PG_S);
rommap.fm_offset = 0;
dmap = &rommap;
#endif
plane = 1;
/* Wait for rop busy */
switch (fb->Mode) {
case MODE_1to1:
if (fb->Pmask & plane)
fbbm_rop_read(fb, dmap, p, dbp->width,
&sr, &dr, 0, 0);
break;
case MODE_1toN:
m = (dbp->width * dbp->rect.extent.y) << 1;
for (i = 0; i < dbp->depth; i++) {
if (fb->Pmask & plane)
fbbm_rop_read(fb, dmap, p, dbp->width,
&sr, &dr, 0, i);
/* next plane */
p += m;
plane <<= 1;
}
break;
case MODE_Nto1:
for (i = 0; i < sbp->depth; i++, plane <<= 1) {
if (fb->Pmask & plane) {
fbbm_rop_read(fb, dmap, p, dbp->width,
&sr, &dr, i, 0);
break;
}
}
break;
case MODE_NtoN:
n = imin(dbp->depth, fb->fbNplane);
m = (dbp->width * dbp->rect.extent.y) << 1;
for (i = 0; i < n; i++) {
if (fb->Pmask & plane)
fbbm_rop_read(fb, dmap, p, dbp->width,
&sr, &dr, i, i);
/* next plane */
p += m;
plane <<= 1;
}
break;
default:
return (-1);
}
return (0);
}
int
bitblt_mem(fb, sbp, srp, dbp, dpp, crp)
struct fbdev *fb;
register lBitmap *sbp;
lRectangle *srp;
register lBitmap *dbp;
lPoint *dpp;
lRectangle *crp;
{
register int i;
register int plane;
register struct fb_map *smap, *dmap;
register unsigned int ps, pd;
lRectangle sr;
lRectangle dr;
#ifdef IPC_MRX
static struct fb_map drommap;
int spages, dpages;
#endif
smap = (struct fb_map*)sbp->base;
dmap = (struct fb_map*)dbp->base;
sr = *srp;
dr.origin = *dpp;
if (crp && !cliprect2(&sr, &sbp->rect, &dr, crp))
return (0);
/* normalize source/destination coordinates */
sr.origin.x -= sbp->rect.origin.x;
sr.origin.y -= sbp->rect.origin.y;
dr.origin.x -= dbp->rect.origin.x;
dr.origin.y -= dbp->rect.origin.y;
ps = smap->fm_offset;
pd = dmap->fm_offset;
#ifdef IPC_MRX
spages = btoc(smap->fm_offset + smap->fm_count);
dpages = btoc(dmap->fm_offset + dmap->fm_count);
rommap.fm_vaddr = fb_map_page2(smap->fm_addr, spages, PG_S|PG_WP);
rommap.fm_offset = 0;
drommap.fm_vaddr = fb_map_page2(dmap->fm_addr, dpages, PG_S);
drommap.fm_offset = 0;
smap = &rommap;
dmap = &drommap;
#endif
plane = 0x1; /* plane 0 */
switch (fb->Mode) {
case MODE_1to1:
if (fb->Pmask & plane) {
mem_to_mem(fb->funcvec[0],
smap, ps, sbp->width, dmap, pd, dbp->width,
&sr, &dr.origin);
}
break;
case MODE_1toN:
for (i = 0; i < dbp->depth; i++) {
if (fb->Pmask & plane) {
mem_to_mem(fb->funcvec[i],
smap, ps, sbp->width,
dmap, pd, dbp->width,
&sr, &dr.origin);
}
pd += (dbp->width * dbp->rect.extent.y) << 1;
plane <<= 1;
}
break;
case MODE_Nto1:
for (i = 0; i < sbp->depth; i++, plane <<= 1) {
if (fb->Pmask & plane)
break;
}
if (i < sbp->depth) {
ps += (sbp->width * sbp->rect.extent.y * i) << 1;
mem_to_mem(fb->funcvec[i],
smap, ps, sbp->width, dmap, pd, dbp->width,
&sr, &dr.origin);
}
break;
case MODE_NtoN:
for (i = 0; i < dbp->depth; i++) {
if (fb->Pmask & plane) {
mem_to_mem(fb->funcvec[i],
smap, ps, sbp->width,
dmap, pd, dbp->width,
&sr, &dr.origin);
}
ps += (sbp->width * sbp->rect.extent.y) << 1;
pd += (dbp->width * dbp->rect.extent.y) << 1;
plane <<= 1;
}
break;
default:
return (-1);
}
#ifdef IPC_MRX
page_unmap(rommap.fm_vaddr, spages);
page_unmap(drommap.fm_vaddr, dpages);
#endif
return (0);
}
int
bitblt_nop()
{
return (0);
}
/*
* bitblt from '0' bitmap to frame buffer
*/
int
bitblt_0tofb(fb, sbp, srp, dbp, dpp, crp)
register struct fbdev *fb;
lBitmap *sbp; /* source bitmap (0) */
lRectangle *srp; /* source rectangle */
lBitmap *dbp; /* destination bitmap (FB) */
lPoint *dpp; /* destination point */
lRectangle *crp; /* clip region in destination */
{
lRectangle sr;
lRectangle dr;
sr = *srp;
dr.origin = *dpp;
if (crp && !cliprect2(&sr, &sbp->rect, &dr, crp))
return (0);
dr.extent = sr.extent;
switch (fb->Mode) {
case MODE_1to1:
case MODE_Nto1:
fb->Pmask &= 1;
break;
case MODE_1toN:
case MODE_NtoN:
break;
default:
return (-1);
}
/*
* write data into ROP data register
*/
fbbm_rop_cinit(fb, fb->Pmask, 0);
fbbm_rop_clear(fb, &dr);
return (0);
}
/*
* bitblt from '1' bitmap to frame buffer
*/
int
bitblt_1tofb(fb, sbp, srp, dbp, dpp, crp)
register struct fbdev *fb;
lBitmap *sbp; /* source bitmap (1) */
lRectangle *srp; /* source rectangle */
lBitmap *dbp; /* destination bitmap (FB) */
lPoint *dpp; /* destination point */
lRectangle *crp; /* clip region in destination */
{
lRectangle sr;
lRectangle dr;
sr = *srp;
dr.origin = *dpp;
if (crp && !cliprect2(&sr, &sbp->rect, &dr, crp))
return (0);
dr.extent = sr.extent;
switch (fb->Mode) {
case MODE_1to1:
case MODE_Nto1:
/* plane mask set */
fb->Pmask &= 0x1;
break;
case MODE_1toN:
case MODE_NtoN:
break;
default:
return (-1);
}
/*
* write data into ROP data register
*/
fbbm_rop_cinit(fb, fb->Pmask, 1);
fbbm_rop_clear(fb, &dr);
return (0);
}
#ifndef CPU_DOUBLE
/*
* bitblt from '0' bitmap to main memory
*/
int
bitblt_0tomem(fb, sbp, srp, dbp, dpp, crp)
register struct fbdev *fb;
lBitmap *sbp; /* source bitmap (0) */
lRectangle *srp; /* source rectangle */
register lBitmap *dbp; /* destination bitmap (MEM) */
lPoint *dpp; /* destination point */
lRectangle *crp; /* clip region in destination */
{
register struct fb_map *dmap;
register unsigned int p;
register int i, j;
register int plane;
lRectangle sr;
lRectangle dr;
int skip;
dmap = (struct fb_map*)dbp->base;
sr = *srp;
dr.origin = *dpp;
if (crp && !cliprect2(&sr, &sbp->rect, &dr, crp))
return (0);
dr.extent = sr.extent;
dr.origin.x -= dbp->rect.origin.x;
dr.origin.y -= dbp->rect.origin.y;
p = dmap->fm_offset;
plane = 0x1;
switch (fb->Mode) {
case MODE_1to1:
if (fb->Pmask & plane)
mem_clear(fb->funcvec[0], dmap, p, dbp->width, &dr, 0);
break;
case MODE_1toN:
case MODE_NtoN:
skip = (dbp->width * dbp->rect.extent.y) << 1;
for (i = 0, j = dbp->depth; i < j; i++) {
if (fb->Pmask & plane)
mem_clear(fb->funcvec[i], dmap, p, dbp->width,
&dr, 0);
/* next plane */
p += skip;
plane <<= 1;
}
break;
case MODE_Nto1:
for (i = 0, j = sbp->depth; i < j; i++) {
if (fb->Pmask & plane) {
mem_clear(fb->funcvec[i], dmap, p, dbp->width,
&dr, 0);
break;
}
plane <<= 1;
}
break;
default:
return (1);
}
return (0);
}
/*
* bitblt from '1' bitmap to main memory
*/
int
bitblt_1tomem(fb, sbp, srp, dbp, dpp, crp)
register struct fbdev *fb;
lBitmap *sbp; /* source bitmap (1) */
lRectangle *srp; /* source rectangle */
register lBitmap *dbp; /* destination bitmap (MEM) */
lPoint *dpp; /* destination point */
lRectangle *crp; /* clip region in destination */
{
register struct fb_map *dmap;
register unsigned p;
register int i, j;
register int plane;
lRectangle sr;
lRectangle dr;
int skip;
dmap = (struct fb_map*)dbp->base;
sr = *srp;
dr.origin = *dpp;
if (crp && !cliprect2(&sr, &sbp->rect, &dr, crp))
return (0);
dr.extent = sr.extent;
dr.origin.x -= dbp->rect.origin.x;
dr.origin.y -= dbp->rect.origin.y;
p = dmap->fm_offset;
plane = 0x1;
switch (fb->Mode) {
case MODE_1to1:
if (fb->Pmask & plane)
mem_clear(fb->funcvec[0], dmap, p, dbp->width, &dr, 1);
break;
case MODE_1toN:
case MODE_NtoN:
skip = (dbp->width * dbp->rect.extent.y) << 1;
for (i = 0, j = dbp->depth; i < j; i++) {
if (fb->Pmask & plane)
mem_clear(fb->funcvec[i], dmap, p, dbp->width,
&dr, 1);
/* next plane */
p += skip;
plane <<= 1;
}
break;
case MODE_Nto1:
for (i = 0, j = sbp->depth; i < j; i++) {
if (fb->Pmask & plane) {
mem_clear(fb->funcvec[i], dmap, p, dbp->width,
&dr, 1);
break;
}
plane <<= 1;
}
break;
default:
return (1);
}
return (0);
}
#endif /* !CPU_DOUBLE */
int
(*sel_ropfunc(stype, dtype))()
int stype; /* source bitmap type */
int dtype; /* dest bitmap type */
{
if (dtype == BM_0)
return (bitblt_nop);
if (dtype == BM_1)
return (bitblt_nop);
#ifdef CPU_DOUBLE
switch (stype) {
case BM_FB:
return (dtype == BM_FB) ? bitblt_fb : bitblt_tomem;
break;
case BM_MEM:
return (dtype == BM_FB) ? bitblt_tofb : bitblt_mem;
break;
case BM_0:
return (dtype == BM_FB) ? bitblt_0tofb : bitblt_nop;
break;
case BM_1:
return (dtype == BM_FB) ? bitblt_1tofb : bitblt_nop;
break;
}
#else /* CPU_DOUBLE */
switch (stype) {
case BM_FB:
return (dtype == BM_FB) ? bitblt_fb : bitblt_tomem;
break;
case BM_MEM:
return (dtype == BM_FB) ? bitblt_tofb : bitblt_mem;
break;
case BM_0:
return (dtype == BM_FB) ? bitblt_0tofb : bitblt_0tomem;
break;
case BM_1:
return (dtype == BM_FB) ? bitblt_1tofb : bitblt_1tomem;
break;
}
#endif /* CPU_DOUBLE */
return (bitblt_nop);
}
int
bitbltcmd(fb, cmd)
register struct fbdev *fb;
register lBitblt *cmd;
{
lRectangle cr;
int ret;
cr = cmd->destClip;
if (!getclip(fb, &cmd->destBitmap, &cr))
return (0);
if (!clipsrc(fb, &cmd->srcBitmap))
return (0);
if (setrop(fb, cmd->func, cmd->planemask, cmd->fore_color, cmd->aux_color,
cmd->transp, &cmd->srcBitmap, &cmd->destBitmap) < 0)
return (FB_RERROR);
cursorCheck(fb, cmd->srcBitmap.type, &cmd->srcRect,
cmd->destBitmap.type, &cr);
ret = (*sel_ropfunc(cmd->srcBitmap.type, cmd->destBitmap.type))
(fb, &cmd->srcBitmap, &cmd->srcRect, &cmd->destBitmap, &cmd->destPoint, &cr);
cursorOn(fb);
return (FB_ROK);
}
static int
batch_bitblt_01tofb(fb, sbp, clip, sdp, n, sw)
register struct fbdev *fb;
lBitmap *sbp; /* source bitmap (MEM) */
register lRectangle *clip;
register lSrcDest *sdp;
register int n;
int sw;
{
register void (*rop_clear)();
lRectangle *srect = &sbp->rect;
switch (fb->Mode) {
case MODE_1to1:
case MODE_Nto1:
fb->Pmask &= 1;
break;
case MODE_1toN:
case MODE_NtoN:
break;
default:
return (FB_RERROR);
}
fbbm_rop_cinit(fb, fb->Pmask, sw);
rop_clear = fb->fbbm_op->fb_rop_clear;
while (--n >= 0) {
lRectangle sr;
lRectangle dr;
sr = sdp->srcRect;
dr.origin = sdp->destPoint;
if (cliprect2(&sr, srect, &dr, clip))
(*rop_clear)(fb, &dr);
sdp++;
}
return (FB_ROK);
}
static int
batch_bitblt_fb(fb, sbp, clip, sdp, n)
register struct fbdev *fb;
register lBitmap *sbp;
register lRectangle *clip;
register lSrcDest *sdp;
register int n;
{
register int wplane, i, j;
lRectangle sr;
lRectangle dr;
fbbm_rop_init(fb, fb->funcvec);
switch (fb->Mode) {
case MODE_1to1:
fb->Pmask &= 1;
while (--n >= 0) {
sr = sdp->srcRect;
dr.origin = sdp->destPoint;
if (cliprect2(&sr, &sbp->rect, &dr, clip))
fbbm_rop_copy(fb, &sr, &dr.origin, 0, fb->Pmask);
sdp++;
}
break;
case MODE_NtoN:
while (--n >= 0) {
sr = sdp->srcRect;
dr.origin = sdp->destPoint;
if (cliprect2(&sr, &sbp->rect, &dr, clip))
fbbm_rop_copy(fb, &sr, &dr.origin, 0, fb->Pmask);
sdp++;
}
break;
case MODE_1toN:
while (--n >= 0) {
sr = sdp->srcRect;
dr.origin = sdp->destPoint;
if (cliprect2(&sr, &sbp->rect, &dr, clip))
fbbm_rop_copy(fb, &sr, &dr.origin, 1, fb->Pmask);
sdp++;
}
break;
case MODE_Nto1:
for (; --n >= 0; sdp++) {
sr = sdp->srcRect;
dr.origin = sdp->destPoint;
if (!cliprect2(&sr, &sbp->rect, &dr, clip))
continue;
wplane = 1;
for (i = 0, j = sbp->depth; i < j; i++) {
if (fb->Pmask & wplane) {
fbbm_rop_copy(fb, &sr, &dr.origin,
i + 1, fb->Pmask >> 16);
break;
}
wplane <<= 1;
}
}
break;
default:
return (FB_RERROR);
}
return 0;
}
static int
batch_bitblt_tofb(fb, sbp, dbp, crp, sdp, n)
register struct fbdev *fb;
register lBitmap *sbp; /* source bitmap (MEM) */
lBitmap *dbp; /* destination bitmap (FB) */
lRectangle *crp; /* clip region in destination */
register lSrcDest *sdp;
register int n;
{
register unsigned p;
register struct fb_map *smap;
register int i, j, m;
lRectangle sr;
lRectangle dr;
register int wplane;
#ifdef IPC_MRX
extern struct fb_map rommap;
register int pages;
#endif
fbbm_rop_winit(fb);
while (--n >= 0) {
sr = sdp->srcRect;
dr.origin = sdp->destPoint;
if (crp && !cliprect2(&sr, &sbp->rect, &dr, crp)) {
sdp++;
continue;
}
dr.extent = sr.extent;
/* transform source rectangle */
sr.origin.x -= sbp->rect.origin.x;
sr.origin.y -= sbp->rect.origin.y;
/*
* check memory map specification
*/
smap = (struct fb_map*)sbp->base;
p = smap->fm_offset;
#ifdef IPC_MRX
pages = btoc(smap->fm_offset + smap->fm_count);
rommap.fm_vaddr = fb_map_page(smap->fm_addr, pages,
fb->cache_off ? PG_S|PG_WP|PG_CI : PG_S|PG_WP);
rommap.fm_offset = 0;
smap = &rommap;
#endif
wplane = 1;
switch (fb->Mode) {
case MODE_1to1:
fbbm_rop_write(fb, smap, p, sbp->width,
&sr, &dr, fb->Pmask & 0x01);
break;
case MODE_1toN:
fbbm_rop_write(fb, smap, p, sbp->width,
&sr, &dr, fb->Pmask);
break;
case MODE_Nto1:
m = sbp->width * sbp->rect.extent.y;
for (i = 0; i < sbp->depth; i++, wplane <<= 1) {
if (fb->Pmask & wplane) {
p += (m * i) << 1;
fbbm_rop_write(fb, smap, p, sbp->width,
&sr, &dr, wplane);
break;
}
wplane <<= 1;
}
break;
case MODE_NtoN:
j = imin(sbp->depth, fb->fbNplane);
m = sbp->width * sbp->rect.extent.y;
p += (m << 1) * j;
wplane = 1 << (j - 1);
for (i = j; i > 0; i--) {
/* get next plane */
p -= m << 1;
if (fb->Pmask & wplane)
fbbm_rop_write(fb, smap, p, sbp->width,
&sr, &dr, wplane);
/* next plane mask */
wplane >>= 1;
}
break;
default:
return (-1);
}
sdp++;
}
return (0);
}
int
batchbitbltcmd(fb, cmd)
register struct fbdev *fb;
register lBatchBitblt *cmd;
{
register int n;
register lSrcDest *sdp;
register int (*blt)();
lRectangle cr;
#ifdef CPU_SINGLE
struct fb_map *map;
unsigned int p;
#endif
int error;
if (setrop(fb, cmd->func, cmd->planemask,
cmd->fore_color, cmd->aux_color,
cmd->transp, &cmd->srcBitmap, &cmd->destBitmap) < 0)
return (FB_RERROR);
cr = cmd->destClip;
if (!getclip(fb, &cmd->destBitmap, &cr))
return (FB_ROK);
if (!clipsrc(fb, &cmd->srcBitmap))
return (0);
#ifdef CPU_SINGLE
map = (struct fb_map *)(cmd->srcDestList);
p = map->fm_offset;
sdp = (lSrcDest *)TypeAt(map, p);
#else
sdp = cmd->srcDestList;
#endif
n = cmd->nSrcDest;
cursorCheck(fb, cmd->srcBitmap.type, &cmd->srcBitmap.rect,
cmd->destBitmap.type, &cr);
blt = sel_ropfunc(cmd->srcBitmap.type, cmd->destBitmap.type);
if (blt == bitblt_0tofb || blt == bitblt_1tofb) {
if (error =
batch_bitblt_01tofb(fb, &cmd->srcBitmap, &cr, sdp, n,
blt == bitblt_1tofb)) {
cursorOn(fb);
return (error);
}
} else if (blt == bitblt_fb) {
if (error =
batch_bitblt_fb(fb, &cmd->srcBitmap, &cr, sdp, n)) {
cursorOn(fb);
return (error);
}
} else if (blt == bitblt_tofb) {
if (error =
batch_bitblt_tofb(fb, &cmd->srcBitmap, &cmd->destBitmap,
&cr, sdp, n)) {
cursorOn(fb);
return (error);
}
} else
while (--n >= 0) {
if ((*blt)(fb, &cmd->srcBitmap, &sdp->srcRect,
&cmd->destBitmap, &sdp->destPoint, &cr) < 0) {
cursorOn(fb);
return (FB_RERROR);
}
PRE_EMPT;
sdp++;
}
cursorOn(fb);
return (FB_ROK);
}
int
tilebitbltcmd(fb, cmd)
struct fbdev *fb;
register lTileBitblt *cmd;
{
lRectangle trect, rect, prect;
lPoint dp;
register int dx;
int dy;
register int offx, offy;
register int xlen, ylen;
int first;
register int (*blt)();
int t;
rect = cmd->destRect;
prect = cmd->ptnRect;
if (prect.extent.x <= 0 || prect.extent.y <= 0)
return 0;
if (cmd->ptnBitmap.type == BM_FB &&
!cliprect(&cmd->ptnBitmap.rect, &fb->FrameRect, (lRectangle*)0))
return 0;
/* clip pattern rectangle */
if (!cliprect(&prect, &cmd->ptnBitmap.rect, (lRectangle *)0))
return 0;
if (!getclip(fb, &cmd->destBitmap, &cmd->destClip)) return 0;
if (!cliprect(&rect, &cmd->destClip, (lRectangle *)0))
return 0;
if (setrop(fb, cmd->func, cmd->planemask, cmd->fore_color, cmd->aux_color,
cmd->transp, &cmd->ptnBitmap, &cmd->destBitmap) < 0)
return (FB_RERROR);
blt = sel_ropfunc(cmd->ptnBitmap.type, cmd->destBitmap.type);
offx = MOD(rect.origin.x - cmd->refPoint.x, prect.extent.x, t);
offy = MOD(rect.origin.y - cmd->refPoint.y, prect.extent.y, t);
dp = rect.origin;
trect.origin.x = prect.origin.x + offx;
trect.origin.y = prect.origin.y + offy;
dy = rect.extent.y;
cursorCheck(fb, cmd->ptnBitmap.type, &prect, cmd->destBitmap.type, &rect);
first = 1;
while (dy > 0) {
if (first) { /* for the first time */
ylen = prect.extent.y - offy;
ylen = imin(ylen, dy);
trect.extent.y = ylen;
trect.origin.y = prect.origin.y + offy;
first = 0;
} else {
ylen = imin(prect.extent.y, dy);
trect.extent.y = ylen;
trect.origin.y = prect.origin.y;
}
dp.x = rect.origin.x;
dx = rect.extent.x;
xlen = prect.extent.x - offx;
trect.origin.x = prect.origin.x + offx;
if (dx < xlen) {
trect.extent.x = dx;
(*blt)(fb, &cmd->ptnBitmap, &trect, &cmd->destBitmap, &dp, (lRectangle *)0);
} else {
trect.extent.x = xlen;
(*blt)(fb, &cmd->ptnBitmap, &trect, &cmd->destBitmap, &dp, (lRectangle *)0);
dp.x += xlen;
dx -= xlen;
trect.origin.x = prect.origin.x;
while (dx > 0) {
xlen = imin(dx, prect.extent.x);
trect.extent.x = xlen;
(*blt)(fb, &cmd->ptnBitmap, &trect, &cmd->destBitmap, &dp, (lRectangle *)0);
dp.x += xlen;
dx -= xlen;
}
}
dp.y += ylen;
dy -= ylen;
}
cursorOn(fb);
return 0;
}
int
bitblt3cmd(fb, cmd)
struct fbdev *fb;
lBitblt3 *cmd;
{
return (FB_ROK);
}
int
draw_rectangle(fb, dp)
struct fbdev *fb;
lPrimRect *dp;
{
lRectangle trect, rect, prect;
lPoint p;
register int dx;
int dy;
register int offx, offy;
register int xlen, ylen;
int first;
register int (*blt)();
int t;
rect = dp->rect;
prect = dp->ptnRect;
if (prect.extent.x <= 0 || prect.extent.y <= 0)
return 0;
if (dp->ptnBM.type == BM_FB &&
!cliprect(&dp->ptnBM.rect, &fb->FrameRect, (lRectangle*)0))
return 0;
/* clip pattern rectangle */
if (!cliprect(&prect, &dp->ptnBM.rect, (lRectangle *)0))
return 0;
if (!getclip(fb, &dp->drawBM, &dp->clip)) return 0;
if (!cliprect(&rect, &dp->clip, (lRectangle *)0))
return 0;
if (setrop(fb, dp->func, dp->planemask, dp->fore_color, dp->aux_color,
dp->transp, &dp->ptnBM, &dp->drawBM) < 0)
return (FB_RERROR);
blt = sel_ropfunc(dp->ptnBM.type, dp->drawBM.type);
offx = MOD(rect.origin.x - dp->refPoint.x, prect.extent.x, t);
offy = MOD(rect.origin.y - dp->refPoint.y, prect.extent.y, t);
p = rect.origin;
trect.origin.x = prect.origin.x + offx;
trect.origin.y = prect.origin.y + offy;
dy = rect.extent.y;
cursorCheck(fb, dp->ptnBM.type, &prect, dp->drawBM.type, &rect);
first = 1;
while (dy > 0) {
if (first) { /* for the first time */
ylen = prect.extent.y - offy;
ylen = imin(ylen, dy);
trect.extent.y = ylen;
trect.origin.y = prect.origin.y + offy;
first = 0;
} else {
ylen = imin(prect.extent.y, dy);
trect.extent.y = ylen;
trect.origin.y = prect.origin.y;
}
p.x = rect.origin.x;
dx = rect.extent.x;
xlen = prect.extent.x - offx;
trect.origin.x = prect.origin.x + offx;
if (dx < xlen) {
trect.extent.x = dx;
(*blt)(fb, &dp->ptnBM, &trect, &dp->drawBM, &p, (lRectangle *)0);
} else {
trect.extent.x = xlen;
(*blt)(fb, &dp->ptnBM, &trect, &dp->drawBM, &p, (lRectangle *)0);
p.x += xlen;
dx -= xlen;
trect.origin.x = prect.origin.x;
while (dx > 0) {
xlen = imin(dx, prect.extent.x);
trect.extent.x = xlen;
(*blt)(fb, &dp->ptnBM, &trect, &dp->drawBM, &p, (lRectangle *)0);
p.x += xlen;
dx -= xlen;
}
}
p.y += ylen;
dy -= ylen;
}
cursorOn(fb);
return 0;
}
int
draw_polymarker(fb, dp)
struct fbdev *fb;
register lPrimMarker *dp;
{
register lPoint *ps;
register int np;
lRectangle cr;
register int (*blt)();
#ifdef CPU_SINGLE
struct fb_map *map;
unsigned int p;
#endif
cr = dp->clip;
if ((dp->drawBM.type == BM_FB) &&
!getclip(fb, &dp->drawBM, &cr))
return (FB_ROK);
if (dp->ptnBM.type == BM_FB &&
!cliprect(&dp->ptnBM.rect, &fb->FrameRect, (lRectangle*)0))
return (FB_ROK);
if (setrop(fb, dp->func, dp->planemask, dp->fore_color, dp->aux_color,
dp->transp, &dp->ptnBM, &dp->drawBM) < 0)
return (FB_RERROR);
blt = sel_ropfunc(dp->ptnBM.type, dp->drawBM.type);
cursorCheck(fb, dp->ptnBM.type, &(dp->ptnRect), dp->drawBM.type, &cr);
#ifdef CPU_SINGLE
map = (struct fb_map *)(dp->plist);
p = map->fm_offset;
ps = (lPoint *)TypeAt(map, p);
#else
ps = dp->plist;
#endif
np = dp->np;
while (--np >= 0) {
(*blt)(fb, &dp->ptnBM, &dp->ptnRect, &dp->drawBM, ps++, &cr);
PRE_EMPT;
}
cursorOn(fb);
return (FB_ROK);
}
static int patternx;
static int patterny;
static int patternwidth;
static lBitmap *pbm; /* pattern bitmap */
static lBitmap *drawbm; /* drawing bitmap */
static int (*blt)();
static void
fill_line(fb, len, dp, offx, offy)
register struct fbdev *fb;
register int len;
register lPoint *dp;
int offx, offy;
{
register int plen;
static lRectangle srec = { {0, 0}, {0, 1} };
srec.origin.x = patternx + offx;
srec.origin.y = patterny + offy;
if ((plen = patternwidth - offx) > len) {
srec.extent.x = len;
(*blt)(fb, pbm, &srec, drawbm, dp, (lRectangle *)0);
return;
}
srec.extent.x = plen;
(*blt)(fb, pbm, &srec, drawbm, dp, (lRectangle *)0);
dp->x += plen;
len -= plen;
srec.origin.x = patternx;
plen = patternwidth;
while (len > 0) {
srec.extent.x = imin(plen, len);
(*blt)(fb, pbm, &srec, drawbm, dp, (lRectangle *)0);
dp->x += plen;
len -= plen;
}
}
int
fill_scan(fb, fdata)
register struct fbdev *fb;
register lPrimFill *fdata;
{
register lScanl *ls;
int nscan;
lRectangle clip;
lRectangle prect;
register int minx, maxx, miny, maxy;
#ifdef CPU_SINGLE
struct fb_map *map;
#endif
register void (*rop_clear)();
int (*sel_ropfunc())();
if ((nscan = fdata->nscan) <= 0)
return (FB_RERROR);
/* clip pattern rectangle */
prect = fdata->ptnRect;
if (!getclip(fb, &fdata->ptnBM, &prect))
return (0);
if (prect.extent.x <= 0 || prect.extent.y <= 0)
return (FB_RERROR);
/* clip clip rectangle */
clip = fdata->clip;
if (!getclip(fb, &fdata->drawBM, &clip))
return (0);
if (setrop(fb, fdata->func, fdata->planemask,
fdata->fore_color, fdata->aux_color, fdata->transp,
&fdata->ptnBM, &fdata->drawBM) < 0)
return (FB_RERROR);
#ifdef CPU_SINGLE
map = (struct fb_map *)(fdata->scan);
ls = (lScanl *)TypeAt(map, map->fm_offset);
#else
ls = fdata->scan;
#endif
minx = clip.origin.x;
maxx = minx + clip.extent.x - 1;
miny = clip.origin.y;
maxy = miny + clip.extent.y - 1;
cursorCheck(fb, fdata->ptnBM.type, &prect, fdata->drawBM.type, &clip);
blt = sel_ropfunc(fdata->ptnBM.type, fdata->drawBM.type);
if (blt == bitblt_1tofb || blt == bitblt_0tofb) {
lRectangle dr;
if (fb->fbbm_op->fb_rop_fillscan != (void (*)())nofunc) {
fbbm_rop_fillscan(fb, ls, nscan, &clip,
blt == bitblt_1tofb);
goto out;
}
dr.extent.y = 1;
fbbm_rop_cinit(fb, fb->Pmask, blt == bitblt_1tofb);
rop_clear = fb->fbbm_op->fb_rop_clear;
while (--nscan >= 0) {
if ((dr.origin.y = ls->y) >= miny &&
dr.origin.y <= maxy) {
dr.origin.x = imax(ls->x0, minx);
if ((dr.extent.x =
imin(ls->x1, maxx) - dr.origin.x + 1) > 0)
(*rop_clear)(fb, &dr);
}
ls++;
}
} else {
int len;
int refx, refy;
lPoint dp;
int sizex, sizey;
int t;
sizex = prect.extent.x;
sizey = prect.extent.y;
refx = fdata->refPoint.x;
refy = fdata->refPoint.y;
patternx = prect.origin.x;
patterny = prect.origin.y;
patternwidth = sizex;
pbm = &fdata->ptnBM;
drawbm = &fdata->drawBM;
while (--nscan >= 0) {
if ((dp.y = ls->y) >= miny && dp.y <= maxy) {
dp.x = imax(ls->x0, minx);
if ((len = imin(ls->x1, maxx) - dp.x + 1) > 0)
fill_line(fb, len, &dp,
MOD((dp.x - refx), sizex, t),
MOD((dp.y - refy), sizey, t));
}
ls++;
}
}
out:
cursorOn(fb);
return (FB_ROK);
}
int
put_string(fb, sdata)
struct fbdev *fb;
lPrimText *sdata;
{
register int x, y;
register int ex_factor = sdata->ex_factor;
register unsigned c;
register unsigned char *str;
int len = sdata->len;
int flen;
int i, j, k = 0, l = 0;
unsigned fchar = sdata->first_chr;
unsigned lchar = sdata->last_chr;
lRectangle cr, save;
register int (*bltfunc)();
register char *f_addr; /* font address */
register char **fnt_addr = NULL;
static struct fb_map rommap;
#ifdef CPU_SINGLE
struct fb_map *map;
unsigned int p;
#endif
lBitmap *fontBM;
lRectangle srec;
lPoint dp;
#if 0
extern int tmode; /* in ../dev/vt100if.c */
#endif
x = sdata->p.x << 16;
y = sdata->p.y << 16;
srec.extent.x = sdata->width;
srec.extent.y = sdata->height;
switch (sdata->type) {
case ASCII:
fontBM = &sdata->fontBM;
break;
case ROM_ASCII:
case ROM_CONS:
if (sdata->width >= 12 && sdata->height >= 24) {
if (fb->Krom_BM1.type == (char)0xff) {
fontBM = &fb->Krom_BM0;
srec.extent.x = fb->Krom_font_extent0.x>>1;
srec.extent.y = fb->Krom_font_extent0.y;
fnt_addr = ext_fnt_addr;
} else {
fontBM = &fb->Krom_BM1;
srec.extent.x = fb->Krom_font_extent1.x>>1;
srec.extent.y = fb->Krom_font_extent1.y;
fnt_addr = ext_fnt24_addr;
}
} else {
if (fb->Krom_BM0.type == (char)0xff) {
fontBM = &fb->Krom_BM1;
srec.extent.x = fb->Krom_font_extent1.x>>1;
srec.extent.y = fb->Krom_font_extent1.y;
fnt_addr = ext_fnt24_addr;
} else {
fontBM = &fb->Krom_BM0;
srec.extent.x = fb->Krom_font_extent0.x>>1;
srec.extent.y = fb->Krom_font_extent0.y;
fnt_addr = ext_fnt_addr;
}
}
if (srec.extent.x > sdata->width)
srec.extent.x = sdata->width;
if (srec.extent.y > sdata->height)
srec.extent.y = sdata->height;
flen = (fontBM->width<<1) * fontBM->rect.extent.y;
fontBM->base = (Word *)&rommap;
break;
case ROM_KANJI:
if (sdata->width >= 24 && sdata->height >= 24) {
if (fb->Krom_BM1.type == (char)0xff) {
fontBM = &fb->Krom_BM0;
srec.extent = fb->Krom_font_extent0;
fnt_addr = ext_fnt_addr;
} else {
fontBM = &fb->Krom_BM1;
srec.extent = fb->Krom_font_extent1;
fnt_addr = ext_fnt24_addr;
}
} else {
if (fb->Krom_BM0.type == (char)0xff) {
fontBM = &fb->Krom_BM1;
srec.extent = fb->Krom_font_extent1;
fnt_addr = ext_fnt24_addr;
} else {
fontBM = &fb->Krom_BM0;
srec.extent = fb->Krom_font_extent0;
fnt_addr = ext_fnt_addr;
}
}
if (srec.extent.x > sdata->width)
srec.extent.x = sdata->width;
if (srec.extent.y > sdata->height)
srec.extent.y = sdata->height;
save.extent.x = srec.extent.x;
flen = (fontBM->width<<1) * fontBM->rect.extent.y;
fontBM->base = (Word *)&rommap;
break;
default:
return (FB_RERROR);
}
/* get clipping rectangle */
cr = sdata->clip;
if (!getclip(fb, &sdata->drawBM, &cr))
return (FB_ROK);
/* set rop code */
if (setrop(fb, sdata->func, sdata->planemask,
sdata->fore_color, sdata->aux_color,
sdata->transp, fontBM, &sdata->drawBM) < 0)
return (FB_RERROR);
/* select rop function */
bltfunc = sel_ropfunc(fontBM->type, sdata->drawBM.type);
#ifdef CPU_SINGLE
map = (struct fb_map *)(sdata->str);
p = map->fm_offset;
str = (unsigned char *)TypeAt(map, p);
#else
str = sdata->str;
#endif
cursorCheck(fb, fontBM->type, &fontBM->rect, sdata->drawBM.type, &cr);
switch (sdata->type) {
case ASCII:
if (sdata->column == 0)
return (FB_RERROR);
while (len-- > 0) {
c = *str++;
if (c < fchar || c > lchar)
continue;
c -= fchar;
srec.origin.x = sdata->fp.x
+ sdata->width * (c % sdata->column);
srec.origin.y = sdata->fp.y
+ sdata->height * (c / sdata->column);
dp.x = x >> 16;
dp.y = y >> 16;
if (ex_factor == 1) {
(*bltfunc)(fb, fontBM, &srec, &sdata->drawBM,
&dp, &cr);
} else {
srec.extent.x = 1;
for (i = 0; i < sdata->width; i++) {
for (j = 0; j < ex_factor; j++) {
(*bltfunc)(fb, fontBM, &srec,
&sdata->drawBM,
&dp, &cr);
dp.x++;
PRE_EMPT;
}
srec.origin.x++;
}
}
x += sdata->dx;
y += sdata->dy;
}
break;
case ROM_ASCII:
case ROM_CONS:
#ifdef IPC_MRX
if (fb->type == FB_NWB251)
fb->cache_off = 1;
#endif
while (len-- > 0) {
c = *str++;
dp.x = x >> 16;
dp.y = y >> 16;
k = 0;
srec.origin.x = srec.origin.y = 0;
f_addr = 0;
if ((c >= 0x20) && (c <= 0x7e)) {
/*
* ASCII char
*/
f_addr = fnt_addr[c];
goto disp;
}
if (sdata->type == ROM_ASCII) {
if ((c >= 0xa1) && (c <= 0xdf)) {
/*
* KANA char
*/
f_addr = fnt_addr[c + 64];
goto disp;
}
}
if (sdata->type == ROM_CONS) {
#ifdef KM_ASCII
if (tmode == KM_ASCII) {
#endif
if ((c >= 0xa0) && (c <= 0xff)) {
/*
* ISO char
*/
f_addr = fnt_addr[c - 32];
goto disp;
}
#ifdef KM_ASCII
} else {
if ((c >= 0xa1) && (c <= 0xdf)) {
/*
* KANA char
*/
f_addr = fnt_addr[c + 64];
goto disp;
}
}
#endif
}
disp:
if (f_addr) {
/*
* not ROM font
* (font is in kernel data area)
*/
bltfunc = sel_ropfunc(BM_MEM,
sdata->drawBM.type);
rommap.fm_vaddr = f_addr;
rommap.fm_offset = 0;
#ifdef IPC_MRX
iopmemfbmap(f_addr, flen, &rommap);
#endif
k = 1;
l = fontBM->width;
fontBM->width = 1;
save = fontBM->rect;
fontBM->rect.origin = srec.origin;
fontBM->rect.extent.x = 12;
} else if (fontBM->type == BM_MEM) {
/*
* KANJI ROM except pop[cm]fb
*/
f_addr = fbbm_Krom_addr(fb, c, &srec);
rommap.fm_vaddr = f_addr;
rommap.fm_offset = 0;
#ifdef IPC_MRX
iopmemfbmap(f_addr, flen, &rommap);
#endif
} else {
/*
* XXX
* fontBM->type == BM_FB -> fbbm_pop[cm]
*
* see fbpop[cm]_setup() routine
* in fbbm_pop[cm].c
*/
bltfunc = sel_ropfunc(fontBM->type,
sdata->drawBM.type);
bzero((caddr_t)fontBM->base,
sizeof (struct fb_map));
fbbm_Krom_addr(fb, c, &srec);
fontBM->rect.origin = srec.origin;
}
if (ex_factor == 1) {
(*bltfunc)(fb, fontBM, &srec, &sdata->drawBM,
&dp, &cr);
} else {
srec.extent.x = 1;
for (i = 0; i < sdata->width; i++) {
for (j = 0; j < ex_factor; j++) {
(*bltfunc)(fb, fontBM, &srec,
&sdata->drawBM,
&dp, &cr);
dp.x++;
}
srec.origin.x++;
}
}
PRE_EMPT;
if (k != 0) {
fontBM->rect = save;
fontBM->width = l;
}
x += sdata->dx;
y += sdata->dy;
}
#ifdef IPC_MRX
fb->cache_off = 0;
#endif
break;
case ROM_KANJI:
#ifdef IPC_MRX
if (fb->type == FB_NWB251)
fb->cache_off = 1;
#endif
while (len > 1) {
c = *str++;
c <<= 8;
c |= *str++;
dp.x = x >> 16;
dp.y = y >> 16;
srec.origin.x = srec.origin.y = 0;
if (fontBM->type == BM_MEM) {
/*
* KANJI ROM except pop[cm]fb
*/
f_addr = fbbm_Krom_addr(fb, c, &srec);
rommap.fm_vaddr = f_addr;
rommap.fm_offset = 0;
#ifdef IPC_MRX
iopmemfbmap(f_addr, flen, &rommap);
#endif
} else {
/*
* XXX
* fontBM->type == BM_FB ---> fbbm_pop[cm]
*
* see fbpop[cm]_setup() in fbbm_pop[cm].c
*/
bzero((caddr_t)fontBM->base,
sizeof (struct fb_map));
fbbm_Krom_addr(fb, c, &srec);
fontBM->rect.origin = srec.origin;
}
if (ex_factor == 1) {
(*bltfunc)(fb, fontBM, &srec, &sdata->drawBM,
&dp, &cr);
} else {
srec.extent.x = 1;
for (i = 0; i < sdata->width; i++) {
for (j = 0; j < ex_factor; j++) {
(*bltfunc)(fb, fontBM, &srec,
&sdata->drawBM,
&dp, &cr);
dp.x++;
}
srec.origin.x++;
}
srec.extent.x = save.extent.x;
}
PRE_EMPT;
x += sdata->dx;
y += sdata->dy;
len -= 2;
}
#ifdef IPC_MRX
fb->cache_off = 0;
#endif
break;
default:
cursorOn(fb);
return (FB_RERROR);
}
cursorOn(fb);
return (FB_ROK);
}
void
linerop(fb, func, fore, aux, trans)
struct fbdev *fb;
register unsigned func;
register int fore;
register int aux;
int trans;
{
register char *funcv;
register int i;
char tmp[4];
/* set rop function register */
func &= 0xf;
tmp[0] = TRANS(trans, (func & 0x0c) | (func >> 2));
tmp[1] = TRANS(trans, (func >> 2) | ((func << 2) & 0x0c));
tmp[2] = TRANS(trans, func);
tmp[3] = TRANS(trans, ((func << 2) & 0x0c) | (func & 3));
funcv = fb->funcvec;
for (i = fb->fbNplane; --i >= 0;) {
*funcv++ = tmp[((fore & 1) << 1) | (aux & 1)];
fore >>= 1; aux >>= 1;
}
}
/*
* line clipping routine
*
* DRAW visual
* NODRAW not visual
*/
int
lineclip(p0, p1, r)
register lPoint *p0;
register lPoint *p1;
register lRectangle *r; /* clipping rectangle */
{
register lPoint *ptmp;
register int d0, d1, d2, limit;
/* sort 2 points by x-coordinate */
if (p0->x > p1->x) {
ptmp = p1;
p1 = p0;
p0 = ptmp;
}
limit = r->origin.x;
d0 = p1->y - p0->y;
d1 = p1->x - p0->x;
if ((d2 = limit - p0->x) > 0) {
if (p1->x < limit)
return (NODRAW);
p0->y += d2 * d0 / d1;
p0->x = limit;
}
limit += r->extent.x - 1;
if ((d2 = limit - p1->x) < 0) {
if (p0->x > limit)
return (NODRAW);
p1->y += d2 * d0 / d1;
p1->x = limit;
}
/* sort 2 points by y-coordinate */
if (p0->y > p1->y) {
ptmp = p1;
p1 = p0;
p0 = ptmp;
}
limit = r->origin.y;
d0 = p1->x - p0->x;
d1 = p1->y - p0->y;
if ((d2 = limit - p0->y) > 0) {
if (p1->y < limit)
return (NODRAW);
p0->x += d2 * d0 / d1;
p0->y = limit;
}
limit += r->extent.y - 1;
if ((d2 = limit - p1->y) < 0) {
if (p0->y > limit)
return (NODRAW);
p1->x += d2 * d0 / d1;
p1->y = limit;
}
return (DRAW);
}
#ifndef CPU_DOUBLE
/*
void
point(p, x, s, fp)
register char *p;
register int x;
register int s;
register char *fp;
{
x = 7 - (x & 7);
if ((1 << (3 - (((s & 1) << 1) | ((*p >> x) & 1)))) & *fp)
*p |= (1 << x);
else
*p &= ~(1 << x);
}
*/
#define point(p, x, s, fp) { \
int xx = 7 - ((x) & 7); \
if ((1 << (3 - ((((s) & 1) << 1) | ((*(p) >> xx) & 1)))) & *(fp)) \
*(p) |= (1 << xx); \
else \
*(p) &= ~(1 << xx); \
}
void
mem_vector(fb, p0, p1, mask, dbmp, lpf)
struct fbdev *fb;
lPoint *p0, *p1;
int mask; /* plane mask */
lBitmap *dbmp; /* drawing bitmap */
int lpf; /* if 0, don't draw last point */
{
register struct fb_map *map = (struct fb_map *)dbmp->base;
register char *funcv = fb->funcvec; /* rop function */
int p = (int)map->fm_offset;
register int pmask;
register unsigned int pat;
register int x = p0->x;
register int y = p0->y;
register char *fp;
int width = dbmp->width << 1;
int lim;
int size = width * dbmp->rect.extent.y;
int ddx, ddy;
int s, d, c;
int dx = p1->x - x;
int dy = p1->y - y;
int i, j;
int depth = dbmp->depth;
/* transformation */
x -= dbmp->rect.origin.x;
y -= dbmp->rect.origin.y;
pat = fb->pat;
ddx = 1;
ddy = dbmp->width << 1;
y = (int)p + y * ddy;
if (dx == 0)
ddx = 0;
else if (dx < 0) {
dx = -dx;
ddx = -ddx;
}
if (dy == 0)
ddy = 0;
else if (dy < 0) {
dy = -dy;
ddy = -ddy;
}
if (dx > dy) { /* case x */
lim = dx;
if (lpf)
lim++;
s = -dx;
d = dx << 1;
c = dy << 1;
for (i = lim; i > 0; i--) {
(int)p = y + (x >> 3);
pat = (pat << 1) | ((pat & 0x80000000) ? 1: 0);
fp = funcv;
pmask = mask;
for (j = depth; j > 0; j--) {
if (pmask & 1) {
point(_TypeAt(map, p), x, pat, fp);
}
p += size;
pmask >>= 1;
fp++;
}
if ((s += c) >= 0) {
s -= d;
y += ddy;
}
x += ddx;
}
} else { /* case y */
lim = dy;
if (lpf)
lim++;
s = -dy;
d = dy << 1;
c = dx << 1;
for (i = lim; i > 0; i--) {
(int)p = y + (x >> 3);
pat = (pat << 1) | ((pat & 0x80000000) ? 1: 0);
fp = funcv;
pmask = mask;
for (j = depth; j > 0; j--) {
if (pmask & 1) {
point(_TypeAt(map, p), x, pat, fp);
}
p += size;
pmask >>= 1;
fp++;
}
if ((s += c) >= 0) {
s -= d;
x += ddx;
}
y += ddy;
}
}
/* rotate pattern */
pat = fb->pat;
{
register int tmp;
tmp = lim & 31;
pat = (pat << tmp) | (pat >> (32 - tmp));
}
fb->pat = pat;
}
#endif /* !CPU_DOUBLE */
/* polyline drawing */
int
draw_polyline(fb, dp)
struct fbdev *fb;
register lPrimLine *dp;
{
register lPoint *ps;
lPoint p0, p1;
register int np;
lRectangle clip, *clipp;
#ifdef CPU_SINGLE
struct fb_map *map;
unsigned int p;
#endif
/* clip rectangle */
clip = dp->clip;
if (clip.origin.x == -1)
clipp = 0;
else {
clipp = &clip;
if (!getclip(fb, &dp->drawBM, clipp)) return 0;
}
#ifdef CPU_SINGLE
map = (struct fb_map *)(dp->plist);
p = map->fm_offset;
ps = (lPoint *)TypeAt(map, p);
#else
ps = dp->plist;
#endif
if (dp->drawBM.type == BM_FB) {
cursorCheck(fb, ~BM_FB, 0, dp->drawBM.type, clipp);
fbbm_rop_vect(fb, clipp, dp->func, dp->fore_color,
dp->aux_color, dp->transp, dp->planemask,
dp->np, ps, dp->lptn, (dp->dlpf)?1:0, 1);
cursorOn(fb);
return(FB_ROK);
}
#ifndef CPU_DOUBLE
linerop(fb, dp->func, dp->fore_color, dp->aux_color, dp->transp);
p0 = *ps++;
np = dp->np - 1;
fb->pat = dp->lptn;
if (clipp) {
while (--np > 0) {
p1 = *ps;
if (lineclip(&p0, &p1, clipp)) {
mem_vector(fb, &p0, &p1,
dp->planemask, &dp->drawBM,
ps->x != p1.x || ps->y != p1.y);
PRE_EMPT;
}
p0 = *ps++;
}
p1 = *ps;
if (lineclip(&p0, &p1, clipp)) {
mem_vector(fb, &p0, &p1, dp->planemask, &dp->drawBM,
ps->x != p1.x || ps->y != p1.y || dp->dlpf);
}
} else {
while (--np > 0) {
p1 = *ps;
mem_vector(fb, &p0, &p1, dp->planemask, &dp->drawBM, 0);
PRE_EMPT;
p0 = *ps++;
}
p1 = *ps;
mem_vector(fb, &p0, &p1, dp->planemask, &dp->drawBM, dp->dlpf);
}
#endif /* !CPU_DOUBLE */
return (FB_ROK);
}
/* disjoint polyline drawing */
int
draw_dj_polyline(fb, dp)
struct fbdev *fb;
register lPrimLine *dp;
{
register lPoint *ps;
lPoint p0, p1;
register int np;
lRectangle clip, *clipp;
#ifdef CPU_SINGLE
struct fb_map *map;
unsigned int p;
#endif
int lpf = (dp->dlpf)?1:0;
/* clip rectangle */
clip = dp->clip;
if (clip.origin.x == -1)
clipp = 0;
else {
clipp = &clip;
if(!getclip(fb, &dp->drawBM, clipp)) return (0);
}
#ifdef CPU_SINGLE
map = (struct fb_map *)(dp->plist);
p = map->fm_offset;
ps = (lPoint *)TypeAt(map, p);
#else
ps = dp->plist;
#endif
if (dp->drawBM.type == BM_FB) {
cursorCheck(fb, ~BM_FB, 0, dp->drawBM.type, clipp);
fbbm_rop_vect(fb, clipp, dp->func, dp->fore_color,
dp->aux_color, dp->transp, dp->planemask,
dp->np, ps, dp->lptn, lpf, 0);
cursorOn(fb);
PRE_EMPT;
return (FB_ROK);
}
#ifndef CPU_DOUBLE
linerop(fb, dp->func, dp->fore_color, dp->aux_color, dp->transp);
np = dp->np >> 1;
if (lpf) {
if (clipp) {
while (--np >= 0) {
p0 = *ps++;
p1 = *ps++;
fb->pat = dp->lptn;
if (lineclip(&p0, &p1, clipp)) {
mem_vector(fb, &p0, &p1,
dp->planemask, &dp->drawBM, 1);
PRE_EMPT;
}
}
} else {
while (--np >= 0) {
p0 = *ps++;
p1 = *ps++;
fb->pat = dp->lptn;
mem_vector(fb, &p0, &p1,
dp->planemask, &dp->drawBM, 1);
PRE_EMPT;
}
}
} else {
if (clipp) {
while (--np >= 0) {
p0 = *ps++;
p1 = *ps;
fb->pat = dp->lptn;
if (lineclip(&p0, &p1, clipp)) {
mem_vector(fb, &p0, &p1,
dp->planemask, &dp->drawBM,
ps->x != p1.x || ps->y != p1.y);
PRE_EMPT;
}
ps++;
}
} else {
while (--np >= 0) {
p0 = *ps++;
p1 = *ps++;
fb->pat = dp->lptn;
mem_vector(fb, &p0, &p1,
dp->planemask, &dp->drawBM, 0);
PRE_EMPT;
}
}
}
#endif /* !CPU_DOUBLE */
return (FB_ROK);
}
static lRectangle dotRect = {{ 0, 0 }, { 1, 1 }};
int
emulate_polydot(fb, dp)
struct fbdev *fb;
register lPrimDot *dp;
{
lPrimMarker marker;
lPrimMarker *cmdp;
cmdp = &marker;
cmdp->func = dp->func;
cmdp->transp = dp->transp;
cmdp->fore_color = dp->fore_color;
cmdp->aux_color = dp->aux_color;
cmdp->planemask = dp->planemask;
cmdp->ptnRect = dotRect;
cmdp->ptnBM.type = BM_1;
cmdp->ptnBM.depth = 1;
cmdp->ptnBM.rect = dotRect;
cmdp->drawBM = dp->drawBM;
cmdp->clip = dp->clip;
cmdp->np = dp->np;
cmdp->plist = dp->plist;
return (draw_polymarker(fb, cmdp));
}
#ifndef CPU_DOUBLE
void
mem_dot(fb, p0, mask, dbmp)
struct fbdev *fb;
lPoint *p0;
register int mask; /* plane mask */
lBitmap *dbmp; /* drawing bitmap */
{
register struct fb_map *map = (struct fb_map *)dbmp->base;
register char *funcv; /* rop function */
register int p = (int)map->fm_offset;
register int depth;
int size;
int x, y;
x = p0->x - dbmp->rect.origin.x;
y = p0->y - dbmp->rect.origin.y;
size = (dbmp->width * dbmp->rect.extent.y) << 1;
p += y * (dbmp->width << 1) + (x >> 3);
funcv = fb->funcvec;
for (depth = dbmp->depth; --depth >= 0;) {
if (mask & 1) {
point(_TypeAt(map, p), x, ~0, funcv);
}
p += size;
mask >>= 1;
funcv++;
}
}
#endif /* !CPU_DOUBLE */
int
draw_polydot(fb, dp)
struct fbdev *fb;
register lPrimDot *dp;
{
register lPoint *ps;
lRectangle clip, *clipp;
register int np;
#ifdef CPU_SINGLE
struct fb_map *map;
unsigned int p;
#endif
if (fb->fbbm_op->fb_rop_dot == (void (*)())nofunc)
return (emulate_polydot(fb, dp));
/* clip rectangle */
clip = dp->clip;
if (clip.origin.x == -1)
clipp = 0;
else {
clipp = &clip;
if (!getclip(fb, &dp->drawBM, clipp)) return 0;
}
#ifdef CPU_SINGLE
map = (struct fb_map *)(dp->plist);
p = map->fm_offset;
ps = (lPoint *)TypeAt(map, p);
#else
ps = dp->plist;
#endif
if (dp->drawBM.type == BM_FB) {
cursorCheck(fb, ~BM_FB, 0, dp->drawBM.type, clipp);
fbbm_rop_dot(fb, clipp, dp->func, dp->fore_color,
dp->aux_color, dp->transp, dp->planemask,
dp->np, ps);
cursorOn(fb);
return(FB_ROK);
}
#ifndef CPU_DOUBLE
linerop(fb, dp->func, dp->fore_color, dp->aux_color, dp->transp);
np = dp->np;
if (clipp) {
register int x0, y0, x1, y1;
x0 = clipp->origin.x;
y0 = clipp->origin.y;
x1 = x0 + clipp->extent.x - 1;
y1 = y0 + clipp->extent.y - 1;
if (x1 <= 0 || y1 <= 0) return 0;
while (--np >= 0) {
if ((ps->x >= x0) && (ps->y >= y0) &&
(ps->x <= x1) && (ps->y <= y1)) {
mem_dot(fb, ps, dp->planemask, &dp->drawBM);
PRE_EMPT;
}
ps++;
}
} else {
while (--np >= 0) {
mem_dot(fb, ps, dp->planemask, &dp->drawBM);
PRE_EMPT;
ps++;
}
}
#endif /* !CPU_DOUBLE */
return (FB_ROK);
}
int
get_scrtype(fb, cmd)
register struct fbdev *fb;
register lScrType *cmd;
{
cmd->colorwidth = fb->Colorwidth;
cmd->plane = fb->fbNplane;
cmd->bufferrect = fb->FrameRect;
cmd->visiblerect = fb->VisRect;
cmd->type = fb->type;
cmd->unit = fb->unit;
return FB_ROK;
}
int
fbstart(fbaddr, dummy)
register struct fbreg *fbaddr;
int dummy;
{
register struct fbdev *fb = &fbdev[fbaddr->fb_device];
FB_LOCK;
if (!fb) {
return (FB_RERROR);
}
/* reset dimmer count */
rst_dimmer_cnt();
switch(fbaddr->fb_command) {
case FB_CPROBE:
fbaddr->fb_data = search_fbdev(fbaddr->fb_device,
fbaddr->fb_unit);
fbaddr->fb_result = FB_ROK;
break;
case FB_CATTACH:
fbaddr->fb_result = get_scrtype(fb, &fbaddr->fb_scrtype);
break;
case FB_COPEN:
fbaddr->fb_result = fbbm_open(fb);
break;
case FB_CCLOSE:
fbaddr->fb_result = fbbm_close(fb);
break;
case FB_CSETDIM:
fbaddr->fb_result = fbbm_set_dimmer(fb, fbaddr->fb_data);
break;
case FB_CGETDIM:
if ((fbaddr->fb_data = fbbm_get_dimmer(fb)) == FB_RERROR)
fbaddr->fb_result = FB_RERROR;
else
fbaddr->fb_result = FB_ROK;
break;
case FB_CBITBLT:
fbaddr->fb_result = bitbltcmd(fb, &fbaddr->fb_bitblt);
break;
case FB_CBATCHBITBLT:
fbaddr->fb_result = batchbitbltcmd(fb, &fbaddr->fb_batchbitblt);
break;
case FB_CTILEBITBLT:
fbaddr->fb_result = tilebitbltcmd(fb, &fbaddr->fb_tilebitblt);
break;
case FB_CBITBLT3:
fbaddr->fb_result = bitblt3cmd(fb, &fbaddr->fb_bitblt3);
break;
case FB_CPOLYLINE:
fbaddr->fb_result = draw_polyline(fb, &fbaddr->fb_polyline);
break;
case FB_CDJPOLYLINE:
fbaddr->fb_result = draw_dj_polyline(fb, &fbaddr->fb_polyline);
break;
case FB_CRECTANGLE:
fbaddr->fb_result = draw_rectangle(fb, &fbaddr->fb_rectangle);
break;
case FB_CFILLSCAN:
fbaddr->fb_result = fill_scan(fb, &fbaddr->fb_fillscan);
break;
case FB_CPOLYMARKER:
fbaddr->fb_result = draw_polymarker(fb, &fbaddr->fb_polymarker);
break;
case FB_CTEXT:
fbaddr->fb_result = put_string(fb, &fbaddr->fb_text);
break;
case FB_CPOLYDOT:
fbaddr->fb_result = draw_polydot(fb, &fbaddr->fb_polydot);
break;
case FB_CGETSCRTYPE:
fbaddr->fb_result = get_scrtype(fb, &fbaddr->fb_scrtype);
break;
case FB_CSETPALETTE:
fbaddr->fb_result = fbbm_set_palette(fb, &fbaddr->fb_palette);
break;
case FB_CGETPALETTE:
fbaddr->fb_result = fbbm_get_palette(fb, &fbaddr->fb_palette);
break;
case FB_CSETCURSOR:
fbaddr->fb_result = setCursor(fb, &fbaddr->fb_cursor);
break;
case FB_CUNSETCURSOR:
fbaddr->fb_result = setCursor(fb, NULL);
break;
case FB_CSHOWCURSOR:
fbaddr->fb_result = showCursor(fb);
break;
case FB_CHIDECURSOR:
fbaddr->fb_result = hideCursor(fb);
break;
case FB_CSETXY:
fbaddr->fb_result = moveCursor(fb, &fbaddr->fb_point);
break;
case FB_CAUTODIM:
if (fbaddr->fb_data)
auto_dimmer_on();
else
auto_dimmer_off();
fbaddr->fb_result = FB_ROK;
break;
case FB_CSETVIDEO:
fbaddr->fb_result =
fbbm_ioctl(fb, FB_SETVIDEOCTL, &fbaddr->fb_videoctl);
break;
case FB_CGETVIDEO:
fbaddr->fb_result =
fbbm_ioctl(fb, FB_GETVIDEOSTATUS, &fbaddr->fb_videostatus);
break;
case FB_CSETPMODE:
fbaddr->fb_result =
fbbm_ioctl(fb, FB_SETPALETTEMODE, &fbaddr->fb_data);
break;
case FB_CGETPMODE:
fbaddr->fb_result =
fbbm_ioctl(fb, FB_GETPALETTEMODE, &fbaddr->fb_data);
break;
#ifdef CPU_SINGLE
case FB_CGETPAGE:
fbaddr->fb_data = fbbm_get_page(fb, fbaddr->fb_data);
if (fbaddr->fb_data == -1)
fbaddr->fb_result = FB_RERROR;
else
fbaddr->fb_result = FB_ROK;
break;
#endif
case FB_CIOCTL:
fbaddr->fb_fbioctl.request = fbbm_ioctl(fb,
fbaddr->fb_fbioctl.request, fbaddr->fb_fbioctl.param);
if (fbaddr->fb_fbioctl.request == -1)
fbaddr->fb_result = FB_RERROR;
else
fbaddr->fb_result = FB_ROK;
break;
default:
fbaddr->fb_result = FB_RERROR;
break;
}
#ifdef CPU_SINGLE
if (cfb && curs_pending) {
curs_pending = 0;
redrawCursor(cfb);
}
#endif
FB_UNLOCK;
return 0;
}