Subject: kern/6741: add 2bpp support to rcons
To: None <gnats-bugs@gnats.netbsd.org>
From: None <deberg@MIT.EDU>
List: netbsd-bugs
Date: 01/06/1999 03:11:43
>Number:         6741
>Category:       kern
>Synopsis:       additional code to support 2bpp in sys/dev/rcons
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Wed Jan  6 00:20:01 1999
>Last-Modified:
>Originator:     matt debergalis
>Organization:
matt debergalis <deberg@mit.edu> KB1CTH
finger deberg@ai.mit.edu for PGP key
>Release:        19990106
>Environment:
System: NetBSD sunrise.ne.mediaone.net 1.3I NetBSD 1.3I (SUNRISE) #2: Tue Dec 29 14:21:21 EST 1998 deberg@sunrise.ne.mediaone.net:/src/netbsd/src/sys/arch/i386/compile/SUNRISE i386

>Description:
        rcons only supports 1bpp and 8bpp displays.  the NeXT mono
        display uses 2bpp (4 shades of gray), and the nextdisplay driver
        uses rcons.

        below are patches to support 2bpp.  there's still more to be
        done, including support for BCOPY_FAST, COLORFONT_CACHE, and
        2bpp -> 8bpp bitblts, but this is good enough to render text on
        the mono display.

        incidentally, the rcons code is a complete mess.  i'll send more
        patches to clean it up if i can find the time.

>How-To-Repeat:
>Fix:
cvs rdiff: Diffing netbsd/src/sys/dev/rcons
Index: netbsd/src/sys/dev/rcons/raster.h
diff -c netbsd/src/sys/dev/rcons/raster.h:1.1.1.1 netbsd/src/sys/dev/rcons/raster.h:1.2
*** netbsd/src/sys/dev/rcons/raster.h:1.1.1.1	Sat Sep 19 20:17:36 1998
--- netbsd/src/sys/dev/rcons/raster.h	Wed Jan  6 03:06:21 1999
***************
*** 66,72 ****
  
  /* CONFIGURE: The text routines can optionally keep a cache of 8-bit
  ** characters.  This uses about 30K, but makes text on a color screen
! ** go 3.2 times faster.
  */
  #undef COLORFONT_CACHE
  
--- 66,72 ----
  
  /* CONFIGURE: The text routines can optionally keep a cache of 8-bit
  ** characters.  This uses about 30K, but makes text on a color screen
! ** go 3.2 times faster.  XXX: it will also break 2bpp displays.
  */
  #undef COLORFONT_CACHE
  
***************
*** 85,91 ****
  /* Raster struct. */
  struct raster {
      int width, height;	/* size in pixels */
!     int depth;		/* bits per pixel - 1 or 8 */
      int linelongs;	/* longs from one line to the next - for padding */
      u_int32_t *pixels;	/* pointer to the actual bits */
      caddr_t data;	/* special pointer for frame buffers and subregions */
--- 85,91 ----
  /* Raster struct. */
  struct raster {
      int width, height;	/* size in pixels */
!     int depth;		/* bits per pixel - 1, 2, or 8 */
      int linelongs;	/* longs from one line to the next - for padding */
      u_int32_t *pixels;	/* pointer to the actual bits */
      caddr_t data;	/* special pointer for frame buffers and subregions */
Index: netbsd/src/sys/dev/rcons/raster_op.c
diff -c netbsd/src/sys/dev/rcons/raster_op.c:1.1.1.2 netbsd/src/sys/dev/rcons/raster_op.c:1.2
*** netbsd/src/sys/dev/rcons/raster_op.c:1.1.1.2	Sat Dec 26 23:43:44 1998
--- netbsd/src/sys/dev/rcons/raster_op.c	Wed Jan  6 03:06:24 1999
***************
*** 49,58 ****
--- 49,62 ----
   *
   *   src required
   *       1-bit to 1-bit
+  *       1-bit to 2-bits
   *       1-bit to 8-bits
+  *       2-bits to 2-bits
+  *       2-bits to 8-bits
   *       8-bits to 8-bits
   *   no src required
   *       1-bit no-src
+  *       2-bits no-src
   *       8-bits no-src
   */
  
***************
*** 492,499 ****
--- 496,513 ----
  
  #ifdef MSBYTE_FIRST
  static u_int32_t bytemask[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
+ static u_int32_t twobitmask[16] = {
+   0xc0000000, 0x30000000, 0x0c000000, 0x03000000,
+   0x00c00000, 0x00300000, 0x000c0000, 0x00030000,
+   0x0000c000, 0x00003000, 0x00000c00, 0x00000300,
+   0x000000c0, 0x00000030, 0x0000000c, 0x00000003 };
  #else /*MSBYTE_FIRST*/
  static u_int32_t bytemask[4] = { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };
+ static u_int32_t twobitmask[16] = {
+   0x00000003, 0x0000000c, 0x00000030, 0x000000c0 };
+   0x00000300, 0x00000c00, 0x00003000, 0x0000c000,
+   0x00030000, 0x000c0000, 0x00300000, 0x00c00000,
+   0x03000000, 0x0c000000, 0x30000000, 0xc0000000,
  #endif /*MSBYTE_FIRST*/
  
  
***************
*** 640,645 ****
--- 654,731 ----
  		dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
  	    }
  
+ 	else if ( dst->depth == 2 )
+           {
+             /* One to two, using the color in the rop.  */
+ 	    u_int32_t* srclin1;
+ 	    u_int32_t* dstlin1;
+ 	    u_int32_t* srclin2;
+ 	    u_int32_t* srclin;
+ 	    u_int32_t* dstlin;
+ 	    register u_int32_t* srclong;
+ 	    register u_int32_t* dstlong;
+ 	    register u_int32_t color, dl;
+ 	    register int srcbit, dstbyte, i;
+ 
+ 	    color = RAS_GETCOLOR( rop );
+ 	    if ( color == 0 )
+               color = 3;
+ 
+ 	    /* Make 32 bits of color so we can do the ROP without shifting. */
+ 	    color |= (( color << 30 ) | ( color << 28 ) | ( color << 26 )
+                       | ( color << 24 ) | ( color << 22 ) | ( color << 20 )
+                       | ( color << 18 ) | ( color << 16 ) | ( color << 14 )
+                       | ( color << 12 ) | ( color << 10 ) | ( color << 8 )
+                       | ( color << 6 ) | ( color << 4 ) | ( color << 2 ));
+ 
+ 	    /* Don't have to worry about overlapping blits here. */
+ 	    srclin1 = RAS_ADDR( src, sx, sy );
+ 	    srclin2 = srclin1 + h * src->linelongs;
+ 	    dstlin1 = RAS_ADDR( dst, dx, dy );
+ 	    srclin = srclin1;
+ 	    dstlin = dstlin1;
+             
+ 	    while ( srclin != srclin2 )
+ 		{
+ 		srclong = srclin;
+ 		srcbit = sx & 31;
+ 		dstlong = dstlin;
+ 		dstbyte = dx & 15;
+ 		i = w;
+ 
+ 		/* WARNING: this code is KNOWN TO FAIL on Sun 3's / CG2's. */
+ 		ROP_SRCDSTCOLOR(
+ 		/*op*/  op,
+ 		/*pre*/ while ( i > 0 )
+ 			    {
+ 			    dl = *dstlong;,
+ 		/*s*/       *srclong & raster_bitmask[srcbit],
+ 		/*d*/       dl,
+ 		/*c*/       color,
+ 		/*pst*/     *dstlong = ( *dstlong & ~twobitmask[dstbyte] ) |
+ 				       ( dl & twobitmask[dstbyte] );
+ 			    if ( srcbit == 31 )
+ 				{
+ 				srcbit = 0;
+ 				++srclong;
+ 				}
+ 			    else
+ 				++srcbit;
+ 			    if ( dstbyte == 15 )
+ 				{
+ 				dstbyte = 0;
+ 				++dstlong;
+ 				}
+ 			    else
+ 				++dstbyte;
+ 			    --i;
+ 			    } )
+ 
+ 		srclin += src->linelongs;
+ 		dstlin += dst->linelongs;
+ 		}
+           }
+ 
  	else
  	    {
  	    /* One to eight, using the color in the rop.  This could
***************
*** 712,717 ****
--- 798,827 ----
  	    }
  	}
  
+     else if ( src->depth == 2 ) 
+       {
+         /* Two to two blit. */
+ 	    u_int32_t* srclin1;
+ 	    u_int32_t* dstlin1;
+ 	    int srcleftignore, srcrightignore, srclongs;
+ 	    int dstleftignore, dstrightignore, dstlongs;
+ 
+ 	    srclin1 = RAS_ADDR( src, sx, sy );
+ 	    dstlin1 = RAS_ADDR( dst, dx, dy );
+ 
+ 	    srcleftignore = ( sx & 15 ) * 2;
+ 	    srclongs = ( srcleftignore + w * 2 + 31 ) >> 5;
+ 	    srcrightignore = ( srclongs * 32 - w * 2 - srcleftignore ) & 31;
+ 	    dstleftignore = ( dx & 15 ) * 2;
+ 	    dstlongs = ( dstleftignore + w * 2 + 31 ) >> 5;
+ 	    dstrightignore = ( dstlongs * 32 - w * 2 - dstleftignore ) & 31;
+ 
+ 	    return raster_blit(
+ 		src, srclin1, srcleftignore, srcrightignore, srclongs,
+ 		dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
+ 	    }
+         
+ 
      else
  	{
  	/* Eight to eight blit. */
***************
*** 789,794 ****
--- 899,1010 ----
  	dstleftignore = ( dx & 31 );
  	dstlongs = ( dstleftignore + w + 31 ) >> 5;
  	dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31;
+ 
+ 	dstlin2 = dstlin1 + h * dst->linelongs;
+ 	dstlin = dstlin1;
+ 
+ 	if ( dstlongs == 1 )
+ 	    {
+ 	    /* It fits into a single longword. */
+ 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
+ 	    nlm = ~lm;
+ 	    while ( dstlin != dstlin2 )
+ 		{
+ 		ROP_DST(
+ 		/*op*/  op,
+ 		/*pre*/ dl = *dstlin;,
+ 		/*d*/   dl,
+ 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
+ 
+ 		dstlin += dst->linelongs;
+ 		}
+ 	    }
+ 	else
+ 	    {
+ 	    lm = leftmask[dstleftignore];
+ 	    rm = rightmask[dstrightignore];
+ 	    nrm = ~rm;
+ 	    nlm = ~lm;
+ 
+ 	    while ( dstlin != dstlin2 )
+ 		{
+ 		dstlong = dstlin;
+ 		dstlong2 = dstlong + dstlongs;
+ 		if ( dstrightignore != 0 )
+ 		    --dstlong2;
+ 
+ 		/* Leading edge. */
+ 		if ( dstleftignore != 0 )
+ 		    {
+ 		    ROP_DST(
+ 		    /*op*/  op,
+ 		    /*pre*/ dl = *dstlong;,
+ 		    /*d*/   dl,
+ 		    /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
+ 		    ++dstlong;
+ 		    }
+ 
+ 		/* Main rop. */
+ 		ROP_DST(
+ 		/*op*/  op,
+ 		/*pre*/ while ( dstlong != dstlong2 )
+ 			    {,
+ 		/*d*/       *dstlong,
+ 		/*pst*/     ++dstlong;
+ 			    } )
+ 
+ 		/* Trailing edge. */
+ 		if ( dstrightignore != 0 )
+ 		    {
+ 		    ROP_DST(
+ 		    /*op*/  op,
+ 		    /*pre*/ dl = *dstlong;,
+ 		    /*d*/   dl,
+ 		    /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
+ 		    }
+ 
+ 		dstlin += dst->linelongs;
+ 		}
+ 	    }
+ 	}
+ 
+     else if ( dst->depth == 2 ) 
+ 	{
+ 	/* Two-bit no-src blit. */
+ 	register u_int32_t color;
+ 	u_int32_t* dstlin1;
+ 	u_int32_t* dstlin2;
+ 	u_int32_t* dstlin;
+ 	int dstleftignore, dstrightignore, dstlongs;
+ 	u_int32_t dl, lm, nlm, rm, nrm;
+ 	register u_int32_t* dstlong2;
+ 	register u_int32_t* dstlong;
+ 
+ 	dstlin1 = RAS_ADDR( dst, dx, dy );
+ 
+ #ifdef BCOPY_FASTER
+ 	/* Special-case full-width clears. */
+ 	if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 5 )
+ 	    {
+ 	    bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_int32_t) );
+ 	    return 0;
+ 	    }
+ #endif /*BCOPY_FASTER*/
+ 
+ 	color = RAS_GETCOLOR( rop );
+ 	if ( color == 0 )
+ 	    color = 3;
+ 
+         /* Make 32 bits of color so we can do the ROP without shifting. */
+         color |= (( color << 30 ) | ( color << 28 ) | ( color << 26 )
+                   | ( color << 24 ) | ( color << 22 ) | ( color << 20 )
+                   | ( color << 18 ) | ( color << 16 ) | ( color << 14 )
+                   | ( color << 12 ) | ( color << 10 ) | ( color << 8 )
+                   | ( color << 6 ) | ( color << 4 ) | ( color << 2 ));
+         
+ 	dstleftignore = ( dx & 15 ) * 2;
+ 	dstlongs = ( dstleftignore + w * 2 + 31 ) >> 5;
+ 	dstrightignore = ( dstlongs * 32 - w * 2 - dstleftignore ) & 31;
  
  	dstlin2 = dstlin1 + h * dst->linelongs;
  	dstlin = dstlin1;
>Audit-Trail:
>Unformatted: