linux-fbdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Antonino Daplas <adaplas@pol.net>
To: James Simmons <jsimmons@infradead.org>
Cc: Linux console project <linuxconsole-dev@lists.sourceforge.net>,
	Linux Fbdev development list
	<linux-fbdev-devel@lists.sourceforge.net>
Subject: Re: status
Date: 23 Nov 2002 03:57:16 +0500	[thread overview]
Message-ID: <1038005868.13181.34.camel@localhost.localdomain> (raw)
In-Reply-To: <Pine.LNX.4.44.0211221902540.5899-100000@phoenix.infradead.org>

[-- Attachment #1: Type: text/plain, Size: 780 bytes --]

On Sat, 2002-11-23 at 00:04, James Simmons wrote:
> 

> > 1. optimized putcs to speed up scrolling by 2-3x.  (it's a small patch
> > but it already outperforms fb-2.4 especially at high color depths).
> > Compared with the previous patch I submitted, this change is
> > non-intrusive, so no other changes are required.
> >
> > 2. vga16fb imageblit that supports drawing of the penguin (vga-4-planes
> > only)
> > 
> > 3. logo drawing for directcolor visuals.
> 
> Please send me those patches ASAP!!! I will linclude them right away.
>  
Okay.  Instead of patches, I'll just attach a file with the targeted
functions which you can choose to cut and paste or modify as you see
fit.  

vga16fb_imageblit in vga16fb.c
fbcon_show_logo in fbcon.c
fbcon_accel_putcs in fbcon-accel.c




[-- Attachment #2: changes.txt --]
[-- Type: text/plain, Size: 13428 bytes --]

/*
 * James, 
 *
 * fbcon_pixmap is where we construct the individual characters
 * into a single combined bitmap before submitting in one burst
 * to imageblit.
 * 
 * Since you removed fbcon_accel_setup already, fbcon_pixmap
 * can be statically allocated (max xres * max fontheight/8) which
 * should be 4096 for a 2048 xres and a fontheight of 16.  8192 may
 * be safer number.
 *
 * Also dynamic allocation segfaults when we do a kfree and hardware 
 * is still processing contents. This is where fb_sync() will be useful.
 */


static u8 *fbcon_pixmap = NULL;

void fbcon_accel_setup(struct display *p)
{
	if (fbcon_pixmap != NULL) {
		if (p->fb_info->fbops->fb_sync)
			p->fb_info->fbops->fb_sync(p->fb_info);
		kfree(fbcon_pixmap);
		fbcon_pixmap = NULL;
	}
	fbcon_pixmap = kmalloc(fontheight(p) * 
			     (p->fb_info->var.xres_virtual + 7)/8, 
			     GFP_KERNEL); 

	p->next_line = p->fb_info->fix.line_length;
	p->next_plane = 0;
}


void fbcon_accel_putcs(struct vc_data *vc, struct display *p,
		       const unsigned short *s, int count, int yy, int xx)
{
	struct fb_info *info = p->fb_info;
	unsigned short charmask = p->charmask;
	unsigned int width = ((fontwidth(p) + 7) >> 3);
	struct fb_image image;
	unsigned int cellsize = fontheight(p) * width;
	u16 c = scr_readw(s);

	image.fg_color = attr_fgcol(p, c);
	image.bg_color = attr_bgcol(p, c);
	image.dx = xx * fontwidth(p);
	image.dy = yy * fontheight(p);
	image.height = fontheight(p);
	image.depth = 1;

	if (!(fontwidth(p) & 7) && fbcon_pixmap != NULL) {
		unsigned int pitch = width * count, i, j;
		char *src, *dst, *dst0;

		dst0 = fbcon_pixmap;
		image.width = fontwidth(p) * count;
		image.data = fbcon_pixmap;
		while (count--) {
			src = p->fontdata + (scr_readw(s++) & charmask) * cellsize;
			dst = dst0;
			for (i = image.height; i--; ) {
				for (j = 0; j < width; j++) 
					dst[j] = *src++;
				dst += pitch;
			}
			dst0 += width;
		}
		info->fbops->fb_imageblit(info, &image);
	}
	else {
		image.width = fontwidth(p);
		while (count--) {
			image.data = p->fontdata +
				(scr_readw(s++) & charmask) * cellsize;
			info->fbops->fb_imageblit(info, &image);
			image.dx += fontwidth(p);
		}
	}
}


/*
 * fbcon_show_logo that supports drawing using fb_imageblit.  All packed
 * pixel formats (truecolor, directcolor, pseudocolor) should now be
 * supported.  It also supports logo drawing with vga-4-planes as pseudocolor
 * at 4 bpp.
 */
static int __init fbcon_show_logo( void )
{
    struct display *p = &fb_display[fg_console]; /* draw to vt in foreground */
    struct fb_info *info = p->fb_info;
#ifdef CONFIG_FBCON_ACCEL    
    struct fb_image image;
    u32 *palette = NULL, *saved_palette = NULL;
    char *logo_new = NULL;
#else 
    int line = p->next_line, x1, y1;
    unsigned char *dst, *src;
#endif
    int depth = info->var.bits_per_pixel;
    unsigned char *fb = info->screen_base;
    unsigned char *logo;
    int i, j, n, x;
    int logo_depth, done = 0;

    /* Return if the frame buffer is not mapped */
    if (!fb)
	return 0;
	
    /*
     * Set colors if visual is PSEUDOCOLOR and we have enough colors, or for
     * DIRECTCOLOR
     * We don't have to set the colors for the 16-color logo, since that logo
     * uses the standard VGA text console palette
     */
    if ((info->fix.visual == FB_VISUAL_PSEUDOCOLOR && depth >= 8) ||
	(info->fix.visual == FB_VISUAL_DIRECTCOLOR && depth >= 24))
	for (i = 0; i < LINUX_LOGO_COLORS; i += n) {
	    n = LINUX_LOGO_COLORS - i;
	    if (n > 16)
		/* palette_cmap provides space for only 16 colors at once */
		n = 16;
	    palette_cmap.start = 32 + i;
	    palette_cmap.len   = n;
	    for( j = 0; j < n; ++j ) {
		palette_cmap.red[j]   = (linux_logo_red[i+j] << 8) |
					linux_logo_red[i+j];
		palette_cmap.green[j] = (linux_logo_green[i+j] << 8) |
					linux_logo_green[i+j];
		palette_cmap.blue[j]  = (linux_logo_blue[i+j] << 8) |
					linux_logo_blue[i+j];
	    }
	    fb_set_cmap(&palette_cmap, 1, info);
	}
	
    if (depth >= 8) {
	logo = linux_logo;
	logo_depth = 8;
    }
    else if (depth >= 4) {
	logo = linux_logo16;
	logo_depth = 4;
    }
    else {
	logo = linux_logo_bw;
	logo_depth = 1;
    }
   
#if defined(CONFIG_FBCON_ACCEL)
	if (info->fix.visual == FB_VISUAL_TRUECOLOR || 
	    (info->fix.visual == FB_VISUAL_DIRECTCOLOR && depth >= 24)) {
		unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
		unsigned char redmask, greenmask, bluemask;
		int redshift, greenshift, blueshift;

		/*
	 	 * We have to create a temporary palette since console palette is only
		 * 16 colors long.
	 	 */
		palette = kmalloc(256 * 4, GFP_KERNEL);
		if (palette == NULL)
			return (LOGO_H + fontheight(p) - 1) / fontheight(p);

		if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
			/* Bug: Doesn't obey msb_right ... (who needs that?) */
			redmask   = mask[info->var.red.length   < 8 ? info->var.red.length   : 8];
			greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8];
			bluemask  = mask[info->var.blue.length  < 8 ? info->var.blue.length  : 8];
			redshift   = info->var.red.offset   - (8 - info->var.red.length);
			greenshift = info->var.green.offset - (8 - info->var.green.length);
			blueshift  = info->var.blue.offset  - (8 - info->var.blue.length);


			for ( i = 0; i < LINUX_LOGO_COLORS; i++) {
				palette[i+32] = (safe_shift((linux_logo_red[i]   & redmask), redshift) |
						 safe_shift((linux_logo_green[i] & greenmask), greenshift) |
						 safe_shift((linux_logo_blue[i]  & bluemask), blueshift));
			}
		}
		else {
			redshift = info->var.red.offset;
			greenshift = info->var.green.offset;
			blueshift = info->var.blue.offset;

			for (i = 32; i < LINUX_LOGO_COLORS; i++) 
				palette[i] = i << redshift | i << greenshift | i << blueshift;
		}
		saved_palette = info->pseudo_palette;
		info->pseudo_palette = palette;
	}
	else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && depth >= 12 && depth < 24) {
		logo_new = kmalloc(LOGO_W * LOGO_H, GFP_KERNEL);
		if (logo_new == NULL)
			return (LOGO_H + fontheight(p) - 1) / fontheight(p);

		logo = logo_new;
		for (i = 0; i < (LOGO_W * LOGO_H)/2; i++) {
			logo_new[i*2] = linux_logo16[i] >> 4;
			logo_new[(i*2)+1] = linux_logo16[i] & 0xf;
		}
	} 
	image.width = LOGO_W;
	image.height = LOGO_H;
	image.depth = depth;
	image.data = logo;
	image.dy = 0;
#endif
 
    for (x = 0; x < num_online_cpus() * (LOGO_W + 8) &&
    	 x < info->var.xres - (LOGO_W + 8); x += (LOGO_W + 8)) {
#if defined (CONFIG_FBCON_ACCEL)
	image.dx = x;
	info->fbops->fb_imageblit(info, &image);
	done = 1;
#endif
#if defined(CONFIG_FBCON_AFB) || defined(CONFIG_FBCON_ILBM) || \
    defined(CONFIG_FBCON_IPLAN2P2) || defined(CONFIG_FBCON_IPLAN2P4) || \
    defined(CONFIG_FBCON_IPLAN2P8)
	if (depth >= 2 && (info->fix.type == FB_TYPE_PLANES ||
			   info->fix.type == FB_TYPE_INTERLEAVED_PLANES)) {
	    /* planes (normal or interleaved), with color registers */
	    int bit;
	    unsigned char val, mask;
	    int plane = p->next_plane;

#if defined(CONFIG_FBCON_IPLAN2P2) || defined(CONFIG_FBCON_IPLAN2P4) || \
    defined(CONFIG_FBCON_IPLAN2P8)
	    int line_length = info->fix.line_length;

	    /* for support of Atari interleaved planes */
#define MAP_X(x)	(line_length ? (x) : ((x) & ~1)*depth + ((x) & 1))
#else
#define MAP_X(x)	(x)
#endif
	    /* extract a bit from the source image */
#define	BIT(p,pix,bit)	(p[pix*logo_depth/8] & \
			 (1 << ((8-((pix*logo_depth)&7)-logo_depth) + bit)))
		
	    src = logo;
	    for( y1 = 0; y1 < LOGO_H; y1++ ) {
		for( x1 = 0; x1 < LOGO_LINE; x1++, src += logo_depth ) {
		    dst = fb + y1*line + MAP_X(x/8+x1);
		    for( bit = 0; bit < logo_depth; bit++ ) {
			val = 0;
			for( mask = 0x80, i = 0; i < 8; mask >>= 1, i++ ) {
			    if (BIT( src, i, bit ))
				val |= mask;
			}
			*dst = val;
			dst += plane;
		    }
		}
	    }
	
	    /* fill remaining planes */
	    if (depth > logo_depth) {
		for( y1 = 0; y1 < LOGO_H; y1++ ) {
		    for( x1 = 0; x1 < LOGO_LINE; x1++ ) {
			dst = fb + y1*line + MAP_X(x/8+x1) + logo_depth*plane;
			for( i = logo_depth; i < depth; i++, dst += plane )
			    *dst = 0x00;
		    }
		}
	    }
	    done = 1;
	    break;
	}
#endif
#if defined(CONFIG_FBCON_MFB) || defined(CONFIG_FBCON_AFB) || \
    defined(CONFIG_FBCON_ILBM) || defined(CONFIG_FBCON_HGA)

	if (depth == 1 && (info->fix.type == FB_TYPE_PACKED_PIXELS ||
			   info->fix.type == FB_TYPE_PLANES ||
			   info->fix.type == FB_TYPE_INTERLEAVED_PLANES)) {

	    /* monochrome */
	    unsigned char inverse = p->inverse || info->fix.visual == FB_VISUAL_MONO01
		? 0x00 : 0xff;

	    int is_hga = !strncmp(info->modename, "HGA", 3);
	    /* can't use simply memcpy because need to apply inverse */
	    for( y1 = 0; y1 < LOGO_H; y1++ ) {
		src = logo + y1*LOGO_LINE;
		if (is_hga)
		    dst = fb + (y1%4)*8192 + (y1>>2)*line + x/8;
		else
		    dst = fb + y1*line + x/8;
		for( x1 = 0; x1 < LOGO_LINE; ++x1 )
		    fb_writeb(*src++ ^ inverse, dst++);
	    }
	    done = 1;
	}
#endif
#if defined(CONFIG_FBCON_VGA_PLANES)
	if (depth == 4 && info->fix.type == FB_TYPE_VGA_PLANES) {
		outb_p(1,0x3ce); outb_p(0xf,0x3cf);
		outb_p(3,0x3ce); outb_p(0,0x3cf);
		outb_p(5,0x3ce); outb_p(0,0x3cf);

		src = logo;
		for (y1 = 0; y1 < LOGO_H; y1++) {
			for (x1 = 0; x1 < LOGO_W / 2; x1++) {
				dst = fb + y1*line + x1/4 + x/8;

				outb_p(0,0x3ce);
				outb_p(*src >> 4,0x3cf);
				outb_p(8,0x3ce);
				outb_p(1 << (7 - x1 % 4 * 2),0x3cf);
				fb_readb (dst);
				fb_writeb (0, dst);

				outb_p(0,0x3ce);
				outb_p(*src & 0xf,0x3cf);
				outb_p(8,0x3ce);
				outb_p(1 << (7 - (1 + x1 % 4 * 2)),0x3cf);
				fb_readb (dst);
				fb_writeb (0, dst);

				src++;
			}
		}
		done = 1;
	}
#endif
    }
   
#if defined (CONFIG_FBCON_ACCEL)
	if (palette != NULL)
		kfree(palette);
	if (saved_palette != NULL)
		info->pseudo_palette = saved_palette;
	if (logo_new != NULL)
		kfree(logo_new);
#endif
    /* Modes not yet supported: packed pixels with depth != 8 (does such a
     * thing exist in reality?) */

    return done ? (LOGO_H + fontheight(p) - 1) / fontheight(p) : 0 ;
}


/*
 * The following is a vga imageblit that supports bitmaps greater than
 * 8 pixels wide and logo drawing in vga-4-planes.
 *
 * I haven't made any changes to the other VGA formats.  No hardware.
 */

void vga_imageblit_expand(struct fb_info *info, struct fb_image *image)
{
	char *where = info->screen_base + (image->dx/8) + 
		image->dy * info->fix.line_length;
	struct vga16fb_par *par = (struct vga16fb_par *) info->par;
	u8 *cdat = image->data, *dst;
	int x, y;

	switch (info->fix.type) {
		case FB_TYPE_VGA_PLANES:
			if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {
				if (par->isVGA) {
					setmode(2);
					setop(0);
					setsr(0xf);
					setcolor(image->fg_color);
					selectmask();

					setmask(0xff);
					writeb(image->bg_color, where);
					rmb();
					readb(where); /* fill latches */
					setmode(3);
					wmb();
					for (y = 0; y < image->height; y++) {
						dst = where;
						for (x = image->width/8; x--;) 
							writeb(*cdat++, dst++);
						where += info->fix.line_length;
					}
					wmb();
				} else {
					setmode(0);
					setop(0);
					setsr(0xf);
					setcolor(image->bg_color);
					selectmask();

					setmask(0xff);
					for (y = 0; y < image->height; y++) {
						dst = where;
						for (x=image->width/8; x--;){
							rmw(dst);
							setcolor(image->fg_color);
							selectmask();
							if (*cdat) {
								setmask(*cdat++);
								rmw(dst++);
							}
						}
						where += info->fix.line_length;
					}
				}
			} else 
				vga_8planes_imageblit(info, image);
			break;
#ifdef FBCON_HAS_VGA
		case FB_TYPE_TEXT:
			break;
#endif
		case FB_TYPE_PACKED_PIXELS:
		default:
			cfb_imageblit(info, image);
			break;
	}
}

void vga_imageblit_color(struct fb_info *info, struct fb_image *image) 
{
	/*
	 * Draw logo 
	 */
	struct vga16fb_par *par = (struct vga16fb_par *) info->par;
	char *where = info->screen_base + image->dy * info->fix.line_length + 
		image->dx/8;
	char *cdat = image->data, *dst;
	int x, y;

	switch (info->fix.type) {
	case FB_TYPE_VGA_PLANES:
		if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4 &&
		    par->isVGA) {
			setsr(0xf);
			setop(0);
			setmode(0);
			
			for (y = 0; y < image->height; y++) {
				for (x = 0; x < image->width/2; x++) {
					dst = where + x/4;

					setcolor(*cdat >> 4);
					selectmask();
					setmask(1 << (7 - x % 4 * 2));
					fb_readb(dst);
					fb_writeb(0, dst);

					setcolor(*cdat & 0xf);
					selectmask();
					setmask(1 << (7 - (1 + x % 4 * 2)));
					fb_readb(dst);
					fb_writeb(0, dst);

					cdat++;
				}
				where += info->fix.line_length;
			}
		}
		break;
	case FB_TYPE_PACKED_PIXELS:
		cfb_imageblit(info, image);
		break;
	default:
		break;
	}
}
				
void vga16fb_imageblit(struct fb_info *info, struct fb_image *image)
{
	if (image->depth == 1)
		vga_imageblit_expand(info, image);
	else if (image->depth == info->var.bits_per_pixel)
		vga_imageblit_color(info, image);
}


  parent reply	other threads:[~2002-11-22 22:57 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-11-22 17:52 status James Simmons
2002-11-22 21:45 ` status Antonino Daplas
2002-11-22 19:04   ` status James Simmons
2002-11-22 22:12     ` status Antonino Daplas
2002-11-22 22:57     ` Antonino Daplas [this message]
2002-11-23 21:07     ` status Geert Uytterhoeven
2002-11-25 18:47       ` James Simmons
2002-11-25 21:35         ` Johan Bolmsjo
2002-11-26  0:39           ` James Simmons
2002-11-27 23:02           ` Geert Uytterhoeven
2002-12-08 11:47             ` Geert Uytterhoeven

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1038005868.13181.34.camel@localhost.localdomain \
    --to=adaplas@pol.net \
    --cc=jsimmons@infradead.org \
    --cc=linux-fbdev-devel@lists.sourceforge.net \
    --cc=linuxconsole-dev@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).