]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/services/gfx/mw/v2_0/src/drivers/fblin8.c
Cleanup CVS ipmorted branch
[karo-tx-redboot.git] / packages / services / gfx / mw / v2_0 / src / drivers / fblin8.c
1 /*
2  * Copyright (c) 1999, 2000, 2001 Greg Haerr <greg@censoft.com>
3  *
4  * 8bpp Linear Video Driver for Microwindows
5  *      00/01/26 added alpha blending with lookup tables (64k total)
6  *
7  * Inspired from Ben Pfaff's BOGL <pfaffben@debian.org>
8  */
9 /*#define NDEBUG*/
10 #include <assert.h>
11
12 /* We want to do string copying fast, so inline assembly if possible */
13 #ifndef __OPTIMIZE__
14 #define __OPTIMIZE__
15 #endif
16 #include <string.h>
17
18 #include "device.h"
19 #include "fb.h"
20
21 #if ALPHABLEND
22 /*
23  * Alpha lookup tables for 256 color palette systems
24  * A 5 bit alpha value is used to keep tables smaller.
25  *
26  * Two tables are created.  The first, alpha_to_rgb contains 15 bit RGB 
27  * values for each alpha value for each color: 32*256 short words.
28  * RGB values can then be blended.  The second, rgb_to_palindex contains
29  * the closest color (palette index) for each of the 5-bit
30  * R, G, and B values: 32*32*32 bytes.
31  */
32 static unsigned short *alpha_to_rgb = NULL;
33 static unsigned char  *rgb_to_palindex = NULL;
34 void init_alpha_lookup(void);
35 #endif
36
37 /* Calc linelen and mmap size, return 0 on fail*/
38 static int
39 linear8_init(PSD psd)
40 {
41         if (!psd->size)
42                 psd->size = psd->yres * psd->linelen;
43         /* linelen in bytes for bpp 1, 2, 4, 8 so no change*/
44         return 1;
45 }
46
47 /* Set pixel at x, y, to pixelval c*/
48 static void
49 linear8_drawpixel(PSD psd, MWCOORD x, MWCOORD y, MWPIXELVAL c)
50 {
51         ADDR8   addr = psd->addr;
52
53         assert (addr != 0);
54         assert (x >= 0 && x < psd->xres);
55         assert (y >= 0 && y < psd->yres);
56         assert (c < psd->ncolors);
57
58         DRAWON;
59         if(gr_mode == MWMODE_COPY)
60                 addr[x + y * psd->linelen] = c;
61         else
62                 applyOp(gr_mode, c, &addr[ x + y * psd->linelen], ADDR8);
63         DRAWOFF;
64 }
65
66 /* Read pixel at x, y*/
67 static MWPIXELVAL
68 linear8_readpixel(PSD psd, MWCOORD x, MWCOORD y)
69 {
70         ADDR8   addr = psd->addr;
71
72         assert (addr != 0);
73         assert (x >= 0 && x < psd->xres);
74         assert (y >= 0 && y < psd->yres);
75
76         return addr[x + y * psd->linelen];
77 }
78
79 /* Draw horizontal line from x1,y to x2,y including final point*/
80 static void
81 linear8_drawhorzline(PSD psd, MWCOORD x1, MWCOORD x2, MWCOORD y, MWPIXELVAL c)
82 {
83         ADDR8   addr = psd->addr;
84
85         assert (addr != 0);
86         assert (x1 >= 0 && x1 < psd->xres);
87         assert (x2 >= 0 && x2 < psd->xres);
88         assert (x2 >= x1);
89         assert (y >= 0 && y < psd->yres);
90         assert (c < psd->ncolors);
91
92         DRAWON;
93         addr += x1 + y * psd->linelen;
94         if(gr_mode == MWMODE_COPY)
95                 memset(addr, c, x2 - x1 + 1);
96         else {
97                 while(x1++ <= x2) {
98                         applyOp(gr_mode, c, addr, ADDR8);
99                         ++addr;
100                 }
101         }
102         DRAWOFF;
103 }
104
105 /* Draw a vertical line from x,y1 to x,y2 including final point*/
106 static void
107 linear8_drawvertline(PSD psd, MWCOORD x, MWCOORD y1, MWCOORD y2, MWPIXELVAL c)
108 {
109         ADDR8   addr = psd->addr;
110         int     linelen = psd->linelen;
111
112         assert (addr != 0);
113         assert (x >= 0 && x < psd->xres);
114         assert (y1 >= 0 && y1 < psd->yres);
115         assert (y2 >= 0 && y2 < psd->yres);
116         assert (y2 >= y1);
117         assert (c < psd->ncolors);
118
119         DRAWON;
120         addr += x + y1 * linelen;
121         if(gr_mode == MWMODE_COPY) {
122                 while(y1++ <= y2) {
123                         *addr = c;
124                         addr += linelen;
125                 }
126         } else {
127                 while(y1++ <= y2) {
128                         applyOp(gr_mode, c, addr, ADDR8);
129                         addr += linelen;
130                 }
131         }
132         DRAWOFF;
133 }
134
135 /* srccopy bitblt*/
136 static void
137 linear8_blit(PSD dstpsd, MWCOORD dstx, MWCOORD dsty, MWCOORD w, MWCOORD h,
138         PSD srcpsd, MWCOORD srcx, MWCOORD srcy, long op)
139 {
140         ADDR8   dst;
141         ADDR8   src;
142         int     dlinelen = dstpsd->linelen;
143         int     slinelen = srcpsd->linelen;
144 #if ALPHABLEND
145         unsigned int srcalpha, dstalpha;
146 #endif
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 + dsty * dlinelen;
163         src = srcpsd->addr + srcx + srcy * slinelen;
164
165 #if ALPHABLEND
166         if((op & MWROP_EXTENSION) != MWROP_BLENDCONSTANT)
167                 goto stdblit;
168         srcalpha = op & 0xff;
169
170         /* FIXME create lookup table after palette is stabilized...*/
171         if(!rgb_to_palindex || !alpha_to_rgb) {
172                 init_alpha_lookup();
173                 if(!rgb_to_palindex || !alpha_to_rgb)
174                         goto stdblit;
175         }
176
177         /* Create 5 bit alpha value index for 256 color indexing*/
178
179         /* destination alpha is (1 - source) alpha*/
180         dstalpha = ((srcalpha>>3) ^ 31) << 8;
181         srcalpha = (srcalpha>>3) << 8;
182
183         while(--h >= 0) {
184             int i;
185             for(i=0; i<w; ++i) {
186                 /* Get source RGB555 value for source alpha value*/
187                 unsigned short s = alpha_to_rgb[srcalpha + *src++];
188
189                 /* Get destination RGB555 value for dest alpha value*/
190                 unsigned short d = alpha_to_rgb[dstalpha + *dst];
191
192                 /* Add RGB values together and get closest palette index to it*/
193                 *dst++ = rgb_to_palindex[s + d];
194             }
195             dst += dlinelen - w;
196             src += slinelen - w;
197         }
198         DRAWOFF;
199         return;
200 stdblit:
201 #endif
202         if (op == MWROP_COPY) {
203                 /* copy from bottom up if dst in src rectangle*/
204                 /* memmove is used to handle x case*/
205                 if (srcy < dsty) {
206                         src += (h-1) * slinelen;
207                         dst += (h-1) * dlinelen;
208                         slinelen *= -1;
209                         dlinelen *= -1;
210                 }
211
212                 while(--h >= 0) {
213                         /* a _fast_ memcpy is a _must_ in this routine*/
214                         memmove(dst, src, w);
215                         dst += dlinelen;
216                         src += slinelen;
217                 }
218         } else {
219                 while (--h >= 0) {
220                         int i;
221                         for (i=0; i<w; i++) {
222                                 applyOp(MWROP_TO_MODE(op), *src, dst, ADDR8);
223                                 ++src;
224                                 ++dst;
225                         }
226                         dst += dlinelen - w;
227                         src += slinelen - w;
228                 }
229         }
230         DRAWOFF;
231 }
232
233 /* srccopy stretchblt*/
234 static void
235 linear8_stretchblit(PSD dstpsd, MWCOORD dstx, MWCOORD dsty, MWCOORD dstw,
236         MWCOORD dsth, PSD srcpsd, MWCOORD srcx, MWCOORD srcy, MWCOORD srcw,
237         MWCOORD srch, long op)
238 {
239         ADDR8   dst;
240         ADDR8   src;
241         int     dlinelen = dstpsd->linelen;
242         int     slinelen = srcpsd->linelen;
243         int     i, ymax;
244         int     row_pos, row_inc;
245         int     col_pos, col_inc;
246         unsigned char pixel = 0;
247
248         assert (dstpsd->addr != 0);
249         assert (dstx >= 0 && dstx < dstpsd->xres);
250         assert (dsty >= 0 && dsty < dstpsd->yres);
251         assert (dstw > 0);
252         assert (dsth > 0);
253         assert (srcpsd->addr != 0);
254         assert (srcx >= 0 && srcx < srcpsd->xres);
255         assert (srcy >= 0 && srcy < srcpsd->yres);
256         assert (srcw > 0);
257         assert (srch > 0);
258         assert (dstx+dstw <= dstpsd->xres);
259         assert (dsty+dsth <= dstpsd->yres);
260         assert (srcx+srcw <= srcpsd->xres);
261         assert (srcy+srch <= srcpsd->yres);
262
263         DRAWON;
264         row_pos = 0x10000;
265         row_inc = (srch << 16) / dsth;
266
267         /* stretch blit using integer ratio between src/dst height/width*/
268         for (ymax = dsty+dsth; dsty<ymax; ++dsty) {
269
270                 /* find source y position*/
271                 while (row_pos >= 0x10000L) {
272                         ++srcy;
273                         row_pos -= 0x10000L;
274                 }
275
276                 dst = dstpsd->addr + dstx + dsty*dlinelen;
277                 src = srcpsd->addr + srcx + (srcy-1)*slinelen;
278
279                 /* copy a row of pixels*/
280                 col_pos = 0x10000;
281                 col_inc = (srcw << 16) / dstw;
282                 for (i=0; i<dstw; ++i) {
283                         /* get source x pixel*/
284                         while (col_pos >= 0x10000L) {
285                                 pixel = *src++;
286                                 col_pos -= 0x10000L;
287                         }
288                         *dst++ = pixel;
289                         col_pos += col_inc;
290                 }
291
292                 row_pos += row_inc;
293         }
294         DRAWOFF;
295 }
296
297 #if ALPHABLEND
298 void
299 init_alpha_lookup(void)
300 {
301         int     i, a;
302         int     r, g, b;
303         extern MWPALENTRY gr_palette[256];
304
305         if(!alpha_to_rgb)
306                 alpha_to_rgb = (unsigned short *)malloc(
307                         sizeof(unsigned short)*32*256);
308         if(!rgb_to_palindex)
309                 rgb_to_palindex = (unsigned char *)malloc(
310                         sizeof(unsigned char)*32*32*32);
311         if(!rgb_to_palindex || !alpha_to_rgb)
312                 return;
313
314         /*
315          * Precompute alpha to rgb lookup by premultiplying
316          * each palette rgb value by each possible alpha
317          * and storing it as RGB555.
318          */
319         for(i=0; i<256; ++i) {
320                 MWPALENTRY *p = &gr_palette[i];
321                 for(a=0; a<32; ++a) {
322                         alpha_to_rgb[(a<<8)+i] =
323                                 (((p->r * a / 31)>>3) << 10) |
324                                 (((p->g * a / 31)>>3) << 5) |
325                                  ((p->b * a / 31)>>3);
326                 }
327         }
328
329         /*
330          * Precompute RGB555 to palette index table by
331          * finding the nearest palette index for all RGB555 colors.
332          */
333         for(r=0; r<32; ++r) {
334                 for(g=0; g<32; ++g)
335                         for(b=0; b<32; ++b)
336                                 rgb_to_palindex[ (r<<10)|(g<<5)|b] =
337                                         GdFindNearestColor(gr_palette, 256,
338                                                 MWRGB(r<<3, g<<3, b<<3));
339         }
340 }
341 #endif
342
343 SUBDRIVER fblinear8 = {
344         linear8_init,
345         linear8_drawpixel,
346         linear8_readpixel,
347         linear8_drawhorzline,
348         linear8_drawvertline,
349         gen_fillrect,
350         linear8_blit,
351         NULL,
352         linear8_stretchblit
353 };