2 * Copyright (c) 1999, 2000, 2001 Greg Haerr <greg@censoft.com>
4 * 8bpp Linear Video Driver for Microwindows
5 * 00/01/26 added alpha blending with lookup tables (64k total)
7 * Inspired from Ben Pfaff's BOGL <pfaffben@debian.org>
12 /* We want to do string copying fast, so inline assembly if possible */
23 * Alpha lookup tables for 256 color palette systems
24 * A 5 bit alpha value is used to keep tables smaller.
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.
32 static unsigned short *alpha_to_rgb = NULL;
33 static unsigned char *rgb_to_palindex = NULL;
34 void init_alpha_lookup(void);
37 /* Calc linelen and mmap size, return 0 on fail*/
42 psd->size = psd->yres * psd->linelen;
43 /* linelen in bytes for bpp 1, 2, 4, 8 so no change*/
47 /* Set pixel at x, y, to pixelval c*/
49 linear8_drawpixel(PSD psd, MWCOORD x, MWCOORD y, MWPIXELVAL c)
51 ADDR8 addr = psd->addr;
54 assert (x >= 0 && x < psd->xres);
55 assert (y >= 0 && y < psd->yres);
56 assert (c < psd->ncolors);
59 if(gr_mode == MWMODE_COPY)
60 addr[x + y * psd->linelen] = c;
62 applyOp(gr_mode, c, &addr[ x + y * psd->linelen], ADDR8);
66 /* Read pixel at x, y*/
68 linear8_readpixel(PSD psd, MWCOORD x, MWCOORD y)
70 ADDR8 addr = psd->addr;
73 assert (x >= 0 && x < psd->xres);
74 assert (y >= 0 && y < psd->yres);
76 return addr[x + y * psd->linelen];
79 /* Draw horizontal line from x1,y to x2,y including final point*/
81 linear8_drawhorzline(PSD psd, MWCOORD x1, MWCOORD x2, MWCOORD y, MWPIXELVAL c)
83 ADDR8 addr = psd->addr;
86 assert (x1 >= 0 && x1 < psd->xres);
87 assert (x2 >= 0 && x2 < psd->xres);
89 assert (y >= 0 && y < psd->yres);
90 assert (c < psd->ncolors);
93 addr += x1 + y * psd->linelen;
94 if(gr_mode == MWMODE_COPY)
95 memset(addr, c, x2 - x1 + 1);
98 applyOp(gr_mode, c, addr, ADDR8);
105 /* Draw a vertical line from x,y1 to x,y2 including final point*/
107 linear8_drawvertline(PSD psd, MWCOORD x, MWCOORD y1, MWCOORD y2, MWPIXELVAL c)
109 ADDR8 addr = psd->addr;
110 int linelen = psd->linelen;
113 assert (x >= 0 && x < psd->xres);
114 assert (y1 >= 0 && y1 < psd->yres);
115 assert (y2 >= 0 && y2 < psd->yres);
117 assert (c < psd->ncolors);
120 addr += x + y1 * linelen;
121 if(gr_mode == MWMODE_COPY) {
128 applyOp(gr_mode, c, addr, ADDR8);
137 linear8_blit(PSD dstpsd, MWCOORD dstx, MWCOORD dsty, MWCOORD w, MWCOORD h,
138 PSD srcpsd, MWCOORD srcx, MWCOORD srcy, long op)
142 int dlinelen = dstpsd->linelen;
143 int slinelen = srcpsd->linelen;
145 unsigned int srcalpha, dstalpha;
148 assert (dstpsd->addr != 0);
149 assert (dstx >= 0 && dstx < dstpsd->xres);
150 assert (dsty >= 0 && dsty < dstpsd->yres);
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);
162 dst = dstpsd->addr + dstx + dsty * dlinelen;
163 src = srcpsd->addr + srcx + srcy * slinelen;
166 if((op & MWROP_EXTENSION) != MWROP_BLENDCONSTANT)
168 srcalpha = op & 0xff;
170 /* FIXME create lookup table after palette is stabilized...*/
171 if(!rgb_to_palindex || !alpha_to_rgb) {
173 if(!rgb_to_palindex || !alpha_to_rgb)
177 /* Create 5 bit alpha value index for 256 color indexing*/
179 /* destination alpha is (1 - source) alpha*/
180 dstalpha = ((srcalpha>>3) ^ 31) << 8;
181 srcalpha = (srcalpha>>3) << 8;
186 /* Get source RGB555 value for source alpha value*/
187 unsigned short s = alpha_to_rgb[srcalpha + *src++];
189 /* Get destination RGB555 value for dest alpha value*/
190 unsigned short d = alpha_to_rgb[dstalpha + *dst];
192 /* Add RGB values together and get closest palette index to it*/
193 *dst++ = rgb_to_palindex[s + d];
202 if (op == MWROP_COPY) {
203 /* copy from bottom up if dst in src rectangle*/
204 /* memmove is used to handle x case*/
206 src += (h-1) * slinelen;
207 dst += (h-1) * dlinelen;
213 /* a _fast_ memcpy is a _must_ in this routine*/
214 memmove(dst, src, w);
221 for (i=0; i<w; i++) {
222 applyOp(MWROP_TO_MODE(op), *src, dst, ADDR8);
233 /* srccopy stretchblt*/
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)
241 int dlinelen = dstpsd->linelen;
242 int slinelen = srcpsd->linelen;
244 int row_pos, row_inc;
245 int col_pos, col_inc;
246 unsigned char pixel = 0;
248 assert (dstpsd->addr != 0);
249 assert (dstx >= 0 && dstx < dstpsd->xres);
250 assert (dsty >= 0 && dsty < dstpsd->yres);
253 assert (srcpsd->addr != 0);
254 assert (srcx >= 0 && srcx < srcpsd->xres);
255 assert (srcy >= 0 && srcy < srcpsd->yres);
258 assert (dstx+dstw <= dstpsd->xres);
259 assert (dsty+dsth <= dstpsd->yres);
260 assert (srcx+srcw <= srcpsd->xres);
261 assert (srcy+srch <= srcpsd->yres);
265 row_inc = (srch << 16) / dsth;
267 /* stretch blit using integer ratio between src/dst height/width*/
268 for (ymax = dsty+dsth; dsty<ymax; ++dsty) {
270 /* find source y position*/
271 while (row_pos >= 0x10000L) {
276 dst = dstpsd->addr + dstx + dsty*dlinelen;
277 src = srcpsd->addr + srcx + (srcy-1)*slinelen;
279 /* copy a row of pixels*/
281 col_inc = (srcw << 16) / dstw;
282 for (i=0; i<dstw; ++i) {
283 /* get source x pixel*/
284 while (col_pos >= 0x10000L) {
299 init_alpha_lookup(void)
303 extern MWPALENTRY gr_palette[256];
306 alpha_to_rgb = (unsigned short *)malloc(
307 sizeof(unsigned short)*32*256);
309 rgb_to_palindex = (unsigned char *)malloc(
310 sizeof(unsigned char)*32*32*32);
311 if(!rgb_to_palindex || !alpha_to_rgb)
315 * Precompute alpha to rgb lookup by premultiplying
316 * each palette rgb value by each possible alpha
317 * and storing it as RGB555.
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);
330 * Precompute RGB555 to palette index table by
331 * finding the nearest palette index for all RGB555 colors.
333 for(r=0; r<32; ++r) {
336 rgb_to_palindex[ (r<<10)|(g<<5)|b] =
337 GdFindNearestColor(gr_palette, 256,
338 MWRGB(r<<3, g<<3, b<<3));
343 SUBDRIVER fblinear8 = {
347 linear8_drawhorzline,
348 linear8_drawvertline,