]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/services/gfx/mw/v2_0/src/drivers/fblin4.c
Initial revision
[karo-tx-redboot.git] / packages / services / gfx / mw / v2_0 / src / drivers / fblin4.c
1 /*
2  * Copyright (c) 1999, 2000 Greg Haerr <greg@censoft.com>
3  *
4  * 4bpp Packed Linear Video Driver for Microwindows
5  *      This driver is written for the Vr41xx Palm PC machines
6  *      Hopefully, we can get the 4bpp mode running 320x240x16
7  *
8  * If INVERT4BPP is defined, then the values are inverted before drawing.
9  *      This is used for the VTech Helio
10  *
11  *      In this driver, psd->linelen is line byte length, not line pixel length
12  */
13 /*#define NDEBUG*/
14 #include <assert.h>
15 #include <string.h>
16 #include "device.h"
17 #include "fb.h"
18
19 #if INVERT4BPP
20 #define INVERT(c)       ((c) = (~c & 0x0f))
21 #else
22 #define INVERT(c)
23 #endif
24
25 static unsigned char notmask[2] = { 0x0f, 0xf0};
26
27 /* Calc linelen and mmap size, return 0 on fail*/
28 static int
29 linear4_init(PSD psd)
30 {
31         if (!psd->size)
32                 psd->size = psd->yres * psd->linelen;
33         /* linelen in bytes for bpp 1, 2, 4, 8 so no change*/
34         return 1;
35 }
36
37 /* Set pixel at x, y, to pixelval c*/
38 static void
39 linear4_drawpixel(PSD psd, MWCOORD x, MWCOORD y, MWPIXELVAL c)
40 {
41         ADDR8   addr = psd->addr;
42
43         assert (addr != 0);
44         assert (x >= 0 && x < psd->xres);
45         assert (y >= 0 && y < psd->yres);
46         assert (c < psd->ncolors);
47
48         INVERT(c);
49         DRAWON;
50         addr += (x>>1) + y * psd->linelen;
51         if(gr_mode == MWMODE_XOR)
52                 *addr ^= c << ((1-(x&1))<<2);
53         else
54                 *addr = (*addr & notmask[x&1]) | (c << ((1-(x&1))<<2));
55         DRAWOFF;
56 }
57
58 /* Read pixel at x, y*/
59 static MWPIXELVAL
60 linear4_readpixel(PSD psd, MWCOORD x, MWCOORD y)
61 {
62         ADDR8           addr = psd->addr;
63         MWPIXELVAL      c;
64
65         assert (addr != 0);
66         assert (x >= 0 && x < psd->xres);
67         assert (y >= 0 && y < psd->yres);
68
69         c = (addr[(x>>1) + y * psd->linelen] >> ((1-(x&1))<<2) ) & 0x0f;
70         INVERT(c);
71         return c;
72         
73 }
74
75 /* Draw horizontal line from x1,y to x2,y including final point*/
76 static void
77 linear4_drawhorzline(PSD psd, MWCOORD x1, MWCOORD x2, MWCOORD y, MWPIXELVAL c)
78 {
79         ADDR8   addr = psd->addr;
80
81         assert (addr != 0);
82         assert (x1 >= 0 && x1 < psd->xres);
83         assert (x2 >= 0 && x2 < psd->xres);
84         assert (x2 >= x1);
85         assert (y >= 0 && y < psd->yres);
86         assert (c < psd->ncolors);
87
88         INVERT(c);
89         DRAWON;
90         addr += (x1>>1) + y * psd->linelen;
91         if(gr_mode == MWMODE_XOR) {
92                 while(x1 <= x2) {
93                         *addr ^= c << ((1-(x1&1))<<2);
94                         if((++x1 & 1) == 0)
95                                 ++addr;
96                 }
97         } else {
98                 while(x1 <= x2) {
99                         *addr = (*addr & notmask[x1&1]) | (c << ((1-(x1&1))<<2));
100                         if((++x1 & 1) == 0)
101                                 ++addr;
102                 }
103         }
104         DRAWOFF;
105 }
106
107 /* Draw a vertical line from x,y1 to x,y2 including final point*/
108 static void
109 linear4_drawvertline(PSD psd, MWCOORD x, MWCOORD y1, MWCOORD y2, MWPIXELVAL c)
110 {
111         ADDR8   addr = psd->addr;
112         int     linelen = psd->linelen;
113
114         assert (addr != 0);
115         assert (x >= 0 && x < psd->xres);
116         assert (y1 >= 0 && y1 < psd->yres);
117         assert (y2 >= 0 && y2 < psd->yres);
118         assert (y2 >= y1);
119         assert (c < psd->ncolors);
120
121         INVERT(c);
122         DRAWON;
123         addr += (x>>1) + y1 * linelen;
124         if(gr_mode == MWMODE_XOR)
125                 while(y1++ <= y2) {
126                         *addr ^= c << ((1-(x&1))<<2);
127                         addr += linelen;
128                 }
129         else
130                 while(y1++ <= y2) {
131                         *addr = (*addr & notmask[x&1]) | (c << ((1-(x&1))<<2));
132                         addr += linelen;
133                 }
134         DRAWOFF;
135 }
136
137 /* srccopy bitblt, opcode is currently ignored*/
138 static void
139 linear4_blit(PSD dstpsd, MWCOORD dstx, MWCOORD dsty, MWCOORD w, MWCOORD h,
140         PSD srcpsd, MWCOORD srcx, MWCOORD srcy, long op)
141 {
142         ADDR8   dst;
143         ADDR8   src;
144         int     i;
145         int     dlinelen = dstpsd->linelen;
146         int     slinelen = srcpsd->linelen;
147
148         assert (dstpsd->addr != 0);
149         assert (dstx >= 0 && dstx < dstpsd->xres);
150         assert (dsty >= 0 && dsty < dstpsd->yres);
151         assert (w > 0);
152         assert (h > 0);
153         assert (srcpsd->addr != 0);
154         assert (srcx >= 0 && srcx < srcpsd->xres);
155         assert (srcy >= 0 && srcy < srcpsd->yres);
156         assert (dstx+w <= dstpsd->xres);
157         assert (dsty+h <= dstpsd->yres);
158         assert (srcx+w <= srcpsd->xres);
159         assert (srcy+h <= srcpsd->yres);
160
161         DRAWON;
162         dst = dstpsd->addr + (dstx>>1) + dsty * dlinelen;
163         src = srcpsd->addr + (srcx>>1) + srcy * slinelen;
164         while(--h >= 0) {
165                 ADDR8   d = dst;
166                 ADDR8   s = src;
167                 MWCOORD dx = dstx;
168                 MWCOORD sx = srcx;
169                 for(i=0; i<w; ++i) {
170 #if INVERT4BPP
171                         unsigned char c = *s;
172                         INVERT(c);
173                         *d = (*d & notmask[dx&1]) |
174                            ((c >> ((1-(sx&1))<<2) & 0x0f) << ((1-(dx&1))<<2));
175 #else
176                         *d = (*d & notmask[dx&1]) |
177                            ((*s >> ((1-(sx&1))<<2) & 0x0f) << ((1-(dx&1))<<2));
178 #endif
179                         if((++dx & 1) == 0)
180                                 ++d;
181                         if((++sx & 1) == 0)
182                                 ++s;
183                 }
184                 dst += dlinelen;
185                 src += slinelen;
186         }
187         DRAWOFF;
188 }
189
190 SUBDRIVER fblinear4 = {
191         linear4_init,
192         linear4_drawpixel,
193         linear4_readpixel,
194         linear4_drawhorzline,
195         linear4_drawvertline,
196         gen_fillrect,
197         linear4_blit
198 };