2 * Copyright (c) 1999, 2000, 2001 Greg Haerr <greg@censoft.com>
4 * 16bpp Linear Video Driver for Microwindows
6 * Inspired from Ben Pfaff's BOGL <pfaffben@debian.org>
12 /* We want to do string copying fast, so inline assembly if possible */
21 #define USE_DRAWAREA 0 /* =1 to implement temp removed DrawArea code*/
22 #define USE_16BIT_ACCESS 0 /* =1 to force 16 bit display access*/
25 #define memcpy(d,s,nbytes) memcpy16(d,s,(nbytes)>>1)
26 #define memmove(d,s,nbytes) memcpy16(d,s,(nbytes)>>1)
28 memcpy16(unsigned short *dst, unsigned short *src, int nwords)
35 /* Calc linelen and mmap size, return 0 on fail*/
37 linear16_init(PSD psd)
40 psd->size = psd->yres * psd->linelen;
41 /* convert linelen from byte to pixel len for bpp 16, 24, 32*/
47 /* Set pixel at x, y, to pixelval c*/
49 linear16_drawpixel(PSD psd, MWCOORD x, MWCOORD y, MWPIXELVAL c)
51 ADDR16 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], ADDR16);
66 /* Read pixel at x, y*/
68 linear16_readpixel(PSD psd, MWCOORD x, MWCOORD y)
70 ADDR16 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 linear16_drawhorzline(PSD psd, MWCOORD x1, MWCOORD x2, MWCOORD y, MWPIXELVAL c)
83 ADDR16 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 /* FIXME: memsetw(dst, c, x2-x1+1)*/
100 applyOp(gr_mode, c, addr, ADDR16);
107 /* Draw a vertical line from x,y1 to x,y2 including final point*/
109 linear16_drawvertline(PSD psd, MWCOORD x, MWCOORD y1, MWCOORD y2, MWPIXELVAL c)
111 ADDR16 addr = psd->addr;
112 int linelen = psd->linelen;
115 assert (x >= 0 && x < psd->xres);
116 assert (y1 >= 0 && y1 < psd->yres);
117 assert (y2 >= 0 && y2 < psd->yres);
119 assert (c < psd->ncolors);
122 addr += x + y1 * linelen;
123 if(gr_mode == MWMODE_COPY) {
130 applyOp(gr_mode, c, addr, ADDR16);
139 linear16_blit(PSD dstpsd, MWCOORD dstx, MWCOORD dsty, MWCOORD w, MWCOORD h,
140 PSD srcpsd, MWCOORD srcx, MWCOORD srcy, long op)
142 ADDR16 dst = dstpsd->addr;
143 ADDR16 src = srcpsd->addr;
145 int dlinelen = dstpsd->linelen;
146 int slinelen = srcpsd->linelen;
152 assert (dstx >= 0 && dstx < dstpsd->xres);
153 assert (dsty >= 0 && dsty < dstpsd->yres);
157 assert (srcx >= 0 && srcx < srcpsd->xres);
158 assert (srcy >= 0 && srcy < srcpsd->yres);
159 assert (dstx+w <= dstpsd->xres);
160 assert (dsty+h <= dstpsd->yres);
161 assert (srcx+w <= srcpsd->xres);
162 assert (srcy+h <= srcpsd->yres);
165 dst += dstx + dsty * dlinelen;
166 src += srcx + srcy * slinelen;
169 if((op & MWROP_EXTENSION) != MWROP_BLENDCONSTANT)
173 if (dstpsd->pixtype == MWPF_TRUECOLOR565) {
176 unsigned int s = *src++;
177 unsigned int d = *dst;
178 unsigned int t = d & 0xf800;
179 unsigned int m1, m2, m3;
180 m1 = (((((s & 0xf800) - t)*alpha)>>8) & 0xf800) + t;
182 m2 = (((((s & 0x07e0) - t)*alpha)>>8) & 0x07e0) + t;
184 m3 = (((((s & 0x001f) - t)*alpha)>>8) & 0x001f) + t;
185 *dst++ = m1 | m2 | m3;
194 unsigned int s = *src++;
195 unsigned int d = *dst;
196 unsigned int t = d & 0x7c00;
197 unsigned int m1, m2, m3;
198 m1 = (((((s & 0x7c00) - t)*alpha)>>8) & 0x7c00) + t;
200 m2 = (((((s & 0x03e0) - t)*alpha)>>8) & 0x03e0) + t;
202 m3 = (((((s & 0x001f) - t)*alpha)>>8) & 0x001f) + t;
203 *dst++ = m1 | m2 | m3;
214 if (op == MWROP_COPY) {
215 /* copy from bottom up if dst in src rectangle*/
216 /* memmove is used to handle x case*/
218 src += (h-1) * slinelen;
219 dst += (h-1) * dlinelen;
224 /* a _fast_ memcpy is a _must_ in this routine*/
225 memmove(dst, src, w<<1);
231 for (i=0; i<w; i++) {
232 applyOp(MWROP_TO_MODE(op), *src, dst, ADDR16);
243 /* VERY experimental globals for debugging stretchblit off-by-some bug*/
244 extern int g_row_inc, g_col_inc;
246 /* srccopy stretchblt*/
248 linear16_stretchblit(PSD dstpsd, MWCOORD dstx, MWCOORD dsty, MWCOORD dstw,
249 MWCOORD dsth, PSD srcpsd, MWCOORD srcx, MWCOORD srcy, MWCOORD srcw,
250 MWCOORD srch, long op)
254 int dlinelen = dstpsd->linelen;
255 int slinelen = srcpsd->linelen;
257 int row_pos, row_inc;
258 int col_pos, col_inc;
259 unsigned short pixel = 0;
261 assert (dstpsd->addr != 0);
262 assert (dstx >= 0 && dstx < dstpsd->xres);
263 assert (dsty >= 0 && dsty < dstpsd->yres);
266 assert (srcpsd->addr != 0);
267 assert (srcx >= 0 && srcx < srcpsd->xres);
268 assert (srcy >= 0 && srcy < srcpsd->yres);
271 assert (dstx+dstw <= dstpsd->xres);
272 assert (dsty+dsth <= dstpsd->yres);
273 assert (srcx+srcw <= srcpsd->xres);
274 assert (srcy+srch <= srcpsd->yres);
278 if (g_row_inc) row_inc = g_row_inc; else
279 row_inc = (srch << 16) / dsth;
281 /* stretch blit using integer ratio between src/dst height/width*/
282 for (ymax = dsty+dsth; dsty<ymax; ++dsty) {
284 /* find source y position*/
285 while (row_pos >= 0x10000L) {
290 dst = (ADDR16)dstpsd->addr + dstx + dsty*dlinelen;
291 src = (ADDR16)srcpsd->addr + srcx + (srcy-1)*slinelen;
293 /* copy a row of pixels*/
295 if (g_col_inc) col_inc = g_col_inc; else
296 col_inc = (srcw << 16) / dstw;
297 for (i=0; i<dstw; ++i) {
298 /* get source x pixel*/
299 while (col_pos >= 0x10000L) {
313 /* temporarily removed DrawArea entry point code*/
314 static void init_alpha_lookup(unsigned short **low, unsigned short **high)
316 unsigned short a, x, *lo, *hi;
317 unsigned short r, g, b;
320 lo = *low = malloc(32*256*2);
321 hi = *high = malloc(32*256*2);
323 if ( hi == 0 || lo == 0 )
326 for ( a=0; a < 32; a++ )
327 for ( x=0; x < 256; x++ ) {
330 r = (x >> 3) * a / 31;
331 g = ((x << 3) & 0x38) * a / 31;
332 hi[idx] = (r << 11) | (g << 5);
334 b = (x & 0x1f) * a / 31;
335 g = ((x >> 5) & 0x7) * a / 31;
336 lo[idx] = (g << 5) | b;
340 static void init_wordmask_lookup(unsigned short **byte2wordmask)
342 unsigned short *maskp, *b2wm;
345 b2wm = *byte2wordmask = malloc(256*8*2);
348 for ( t=0; t < 256; t++ ) {
349 maskp = b2wm + 8 * t;
351 for ( u=1; u < 256; u <<= 1 )
359 /* psd->DrawArea operation PSDOP_PIXMAP_COPYALL which takes a
360 * pixmap, each line is byte aligned, and copies it to the
361 * screen using fg_color and bg_color to replace a 1 and 0 in
362 * the pixmap. This pixmap is ordered the wrong way around;
363 * it has the leftmost pixel (on the screen) in LSB (Bit 0)
366 * The reason why this non-intuitive bit ordering is used is
367 * to match the bit ordering used in the T1lib font rendering
370 * Variables used in the gc:
371 * dstx, dsty, dsth, dstw Destination rectangle
372 * srcx, srcy Source rectangle
373 * src_linelen Linesize in bytes of source
375 * fg_color Color of a '1' bit
376 * bg_color Color of a '0' bit
379 static void pixmap_copyall(PSD psd, driver_gc_t *gc)
381 int first_byte, last_byte;
382 int hard_prefix, hard_postfix;
383 unsigned short prefixbits, postfixbits, *maskp;
384 unsigned short xor_color, m;
385 unsigned short prefix_mask = 0, prefix_last = 0;
386 unsigned short postfix_mask = 0, postfix_last = 0;
388 unsigned int advance_src, advance_dst;
392 static unsigned short *byte2wordmask = 0;
394 prefixbits = gc->srcx & 7;
395 postfixbits = (gc->srcx + gc->dstw - 1) & 7;
396 first_byte = gc->srcx >> 3;
397 last_byte = (gc->srcx + gc->dstw - 1) >> 3;
399 src = ((ADDR8)gc->pixels) + gc->src_linelen * gc->srcy + first_byte;
400 dst = ((ADDR16)psd->addr) + psd->linelen * gc->dsty + gc->dstx;
401 xor_color = gc->fg_color ^ gc->bg_color;
403 if ( first_byte != last_byte ) {
404 if ( prefixbits == 0 ) {
405 /* All bits of first byte used */
407 size_main = last_byte - first_byte;
409 /* Needs to do a few odd bits first */
411 size_main = last_byte - first_byte - 1;
412 prefix_mask = 1 << prefixbits;
415 if ( postfixbits != 7 ) {
416 /* Last byte in source contains a few odd bits */
419 postfix_last = 2 << postfixbits;
421 /* Last byte in source is used completely */
426 /* Very narrow pixmap, fits in single first byte */
430 prefix_mask = 1 << prefixbits;
431 prefix_last = 1 << (prefixbits + gc->dstw);
434 advance_src = gc->src_linelen - last_byte + first_byte - 1;
435 advance_dst = psd->linelen - gc->dstw;
437 if ( byte2wordmask == 0 )
438 init_wordmask_lookup(&byte2wordmask);
441 for ( y=0; y < gc->dsth; y++ ) {
443 /* Do pixels of partial first byte */
445 for ( m=prefix_mask; m < prefix_last; m <<= 1 ) {
447 *dst++ = gc->fg_color;
449 *dst++ = gc->bg_color;
454 /* Do all pixles of main part one byte at a time */
455 for ( t=0; t < size_main; t++ ) {
456 maskp = byte2wordmask + 8 * (*src++);
458 *dst++ = gc->bg_color ^ (*maskp++ & xor_color);
459 *dst++ = gc->bg_color ^ (*maskp++ & xor_color);
460 *dst++ = gc->bg_color ^ (*maskp++ & xor_color);
461 *dst++ = gc->bg_color ^ (*maskp++ & xor_color);
462 *dst++ = gc->bg_color ^ (*maskp++ & xor_color);
463 *dst++ = gc->bg_color ^ (*maskp++ & xor_color);
464 *dst++ = gc->bg_color ^ (*maskp++ & xor_color);
465 *dst++ = gc->bg_color ^ (*maskp++ & xor_color);
468 /* Do last few bits of line */
469 if ( hard_postfix ) {
470 for ( m=postfix_mask; m < postfix_last; m <<= 1 ) {
472 *dst++ = gc->fg_color;
474 *dst++ = gc->bg_color;
486 static unsigned short *low2scale = 0, *high2scale = 0;
488 static void drawarea_alphamap(PSD psd, driver_gc_t *gc)
490 ADDR8 src, dst, alpha;
491 unsigned short psl, psh, pd;
492 unsigned char as, ad;
495 if ( low2scale == 0 )
496 init_alpha_lookup(&low2scale,&high2scale);
498 src = (ADDR8)(((ADDR16)gc->pixels) + gc->srcx +
499 gc->src_linelen * gc->srcy);
500 dst = (ADDR8)(((ADDR16)psd->addr) +
501 psd->linelen * gc->dsty + gc->dstx);
502 alpha = ((ADDR8)gc->misc) + gc->src_linelen * gc->srcy + gc->srcx;
505 for ( y=0; y < gc->dsth; y++ ) {
506 for ( x=0; x < gc->dstw; x++ ) {
507 as = (*alpha++) >> 3;
509 psl = low2scale[(as<<8)|*src++];
510 psh = high2scale[(as<<8)|*src++];
511 pd = low2scale[(ad<<8)|dst[0]] +
512 high2scale[(ad<<8)|dst[1]];
513 *((unsigned short *)dst)++ = psl + psh + pd;
519 static void drawarea_alphacol(PSD psd, driver_gc_t *gc)
522 unsigned short col_low, col_high, psl, psh, pd;
523 unsigned char as, ad;
526 if ( low2scale == 0 )
527 init_alpha_lookup(&low2scale,&high2scale);
529 dst = (ADDR8)(((ADDR16)psd->addr) +
530 psd->linelen * gc->dsty + gc->dstx);
531 alpha = ((ADDR8)gc->misc) + gc->src_linelen * gc->srcy + gc->srcx;
532 col_low = gc->bg_color & 0xff;
533 col_high = ( gc->bg_color >> 8 ) & 0xff;
536 for ( y=0; y < gc->dsth; y++ ) {
537 for ( x=0; x < gc->dstw; x++ ) {
538 as = (*alpha++) >> 3;
540 if ( (ad = 31 - as) ) {
541 psl = low2scale[(as<<8)|col_low];
542 psh = high2scale[(as<<8)|col_high];
543 pd = low2scale[(ad<<8)|dst[0]] +
544 high2scale[(ad<<8)|dst[1]];
545 *((unsigned short *)dst)++ = psl + psh + pd;
547 *((unsigned short *)dst)++ = gc->bg_color;
555 static void linear16_drawarea(PSD psd, driver_gc_t *gc, int op)
557 ADDR16 src16, dst, rsrc, rdst;
561 assert(psd->addr != 0);
562 /*assert(gc->dstw <= gc->srcw);*/
563 assert(gc->dstx >= 0 && gc->dstx+gc->dstw <= psd->xres);
564 /*assert(gc->dsty >= 0 && gc->dsty+gc->dsth <= psd->yres);*/
565 /*assert(gc->srcx >= 0 && gc->srcx+gc->dstw <= gc->srcw);*/
566 assert(gc->srcy >= 0);
570 printf("DrawArea op=%d x=%d y=%d\n",op,gc->x,gc->y);
573 if ( op == PSDOP_COPY )
574 op = gc->gr_usebg ? PSDOP_COPYALL : PSDOP_COPYTRANS;
578 linesize = 2 * gc->dstw;
579 src16 = ((ADDR16)gc->pixels) + gc->srcx +
580 gc->src_linelen * gc->srcy;
581 dst = ((ADDR16)psd->addr) + gc->dstx +
582 psd->linelen * gc->dsty;
585 for ( y=1; y < gc->dsth; y++ ) {
586 memcpy(dst,src16,linesize);
587 src16 += gc->src_linelen;
590 memcpy(dst,src16,linesize); /* To be seriously ANSI */
594 case PSDOP_COPYTRANS:
595 src16 = ((ADDR16)gc->pixels) + gc->srcx +
596 gc->src_linelen * gc->srcy;
597 dst = ((ADDR16)psd->addr) + gc->dstx +
598 psd->linelen * gc->dsty;
601 for ( y=0; y < gc->dsth; y++ ) {
604 for ( x=0; x < gc->dstw; x++ ) {
606 if ( pcol == gc->bg_color )
612 src16 += gc->src_linelen;
618 drawarea_alphamap(psd,gc);
622 drawarea_alphacol(psd,gc);
625 case PSDOP_PIXMAP_COPYALL:
626 pixmap_copyall(psd,gc);
631 #endif /* USE_DRAWAREA*/
633 SUBDRIVER fblinear16 = {
637 linear16_drawhorzline,
638 linear16_drawvertline,