summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2006-09-13 13:37:00 -0700
committerH. Peter Anvin <hpa@zytor.com>2006-09-13 13:37:00 -0700
commitea13d36710bcb5a4502fe2281528665ee5ac61cd (patch)
treecc9dc6b388910cf03d8e47173cd5f561c4ed46b0
parent229a3a08016d601585a79856d8bae6d59852bfa4 (diff)
downloadsyslinux-ea13d36710bcb5a4502fe2281528665ee5ac61cd.tar.gz
Beginnings of supporting multiple pixel formats
-rw-r--r--com32/lib/sys/vesa/drawtxt.c65
-rw-r--r--com32/lib/sys/vesa/initvesa.c49
-rw-r--r--com32/lib/sys/vesa/video.h4
3 files changed, 91 insertions, 27 deletions
diff --git a/com32/lib/sys/vesa/drawtxt.c b/com32/lib/sys/vesa/drawtxt.c
index ddb1720d..08b0e914 100644
--- a/com32/lib/sys/vesa/drawtxt.c
+++ b/com32/lib/sys/vesa/drawtxt.c
@@ -29,6 +29,7 @@
#include <colortbl.h>
#include "vesa.h"
#include "video.h"
+#include "fmtpixel.h"
/*
* Visible cursor information
@@ -72,15 +73,37 @@ static void vesacon_update_characters(int row, int col, int nrows, int ncols)
{
const int height = __vesacon_font_height;
const int width = FONT_WIDTH;
- uint32_t *bgrowptr, *bgptr, *fbrowptr, *fbptr, bgval, fgval;
+ uint32_t *bgrowptr, *bgptr, bgval, fgval;
uint32_t fgcolor = 0, bgcolor = 0, color;
uint8_t chbits = 0, chxbits = 0, chsbits = 0;
int i, j, pixrow, pixsrow;
struct vesa_char *rowptr, *rowsptr, *cptr, *csptr;
-
+ unsigned long pixel_offset, bytes_per_pixel, bytes_per_row;
+ uint8_t row_buffer[VIDEO_X_SIZE*4], *rowbufptr;
+ uint8_t *fbrowptr;
+
bgrowptr = &__vesacon_background[row*height+VIDEO_BORDER][col*width+VIDEO_BORDER];
- fbrowptr = ((uint32_t *)__vesa_info.mi.lfb_ptr)+
- ((row*height+VIDEO_BORDER)*VIDEO_X_SIZE)+(col*width+VIDEO_BORDER);
+
+ pixel_offset = ((row*height+VIDEO_BORDER)*VIDEO_X_SIZE)+
+ (col*width+VIDEO_BORDER);
+
+ switch (__vesacon_pixel_format) {
+ case PXF_BGR24:
+ bytes_per_pixel = 3;
+ break;
+ case PXF_BGRA32:
+ bytes_per_pixel = 4;
+ break;
+ case PXF_LE_RGB16_565:
+ bytes_per_pixel = 2;
+ break;
+ default:
+ bytes_per_pixel = 0;
+ break;
+ }
+
+ bytes_per_row = bytes_per_pixel*VIDEO_X_SIZE;
+ fbrowptr = ((uint8_t *)__vesa_info.mi.lfb_ptr)+pixel_offset*bytes_per_pixel;
/* Note that we keep a 1-character guard area around the real text area... */
rowptr = &__vesacon_text_display[(row+1)*(TEXT_PIXEL_COLS/FONT_WIDTH+2)+(col+1)];
@@ -90,7 +113,7 @@ static void vesacon_update_characters(int row, int col, int nrows, int ncols)
for (i = height*nrows; i >= 0; i--) {
bgptr = bgrowptr;
- fbptr = fbrowptr;
+ rowbufptr = row_buffer;
cptr = rowptr;
csptr = rowsptr;
@@ -100,16 +123,21 @@ static void vesacon_update_characters(int row, int col, int nrows, int ncols)
chsbits |= cursor_pattern[pixsrow];
chsbits &= (csptr->sha & 0x02) ? 0xff : 0x00;
chsbits ^= (csptr->sha & 0x01) ? 0xff : 0x00;
- chsbits <<= 6;
+ chsbits <<= (width-2);
csptr++;
- for (j = width*ncols; j >= 0; j--) {
+ /* Draw two pixels beyond the end of the line. One for the shadow,
+ and one to make sure we have a whole dword of data for the copy
+ operation at the end. Note that this code depends on the fact that
+ all characters begin on dword boundaries in the frame buffer. */
+
+ for (j = width*ncols+1; j >= 0; j--) {
chbits <<= 1;
chsbits <<= 1;
chxbits <<= 1;
- switch (j % FONT_WIDTH) {
- case 0:
+ switch (j % width) {
+ case 1:
chbits = __vesacon_graphics_font[cptr->ch][pixrow];
if (__unlikely(cptr == cursor_pointer))
chbits |= cursor_pattern[pixrow];
@@ -120,7 +148,7 @@ static void vesacon_update_characters(int row, int col, int nrows, int ncols)
bgcolor = console_color_table[cptr->attr].argb_bg;
cptr++;
break;
- case FONT_WIDTH-1:
+ case 0:
chsbits = __vesacon_graphics_font[csptr->ch][pixsrow];
if (__unlikely(csptr == cursor_pointer))
chsbits |= cursor_pattern[pixsrow];
@@ -148,11 +176,24 @@ static void vesacon_update_characters(int row, int col, int nrows, int ncols)
color &= 0x3f3f3f;
}
- *fbptr++ = color;
+ rowbufptr = format_pixel(rowbufptr, color, __vesacon_pixel_format);
+ }
+
+ /* Copy to frame buffer */
+ {
+ void *fb_ptr = fbrowptr;
+ void *rb_ptr = row_buffer;
+ unsigned int dword_count = (rowbufptr-row_buffer) >> 2;
+
+ /* Note that the dword_count is rounded down, not up. That's because
+ the row_buffer includes a spillover pixel. */
+
+ asm volatile("cld; rep; movsl"
+ : "+D" (fb_ptr), "+S" (rb_ptr), "+c" (dword_count));
}
bgrowptr += VIDEO_X_SIZE;
- fbrowptr += VIDEO_X_SIZE;
+ fbrowptr += bytes_per_row;
if (++pixrow == height) {
rowptr += TEXT_PIXEL_COLS/FONT_WIDTH+2;
diff --git a/com32/lib/sys/vesa/initvesa.c b/com32/lib/sys/vesa/initvesa.c
index c42a7b34..ebef3044 100644
--- a/com32/lib/sys/vesa/initvesa.c
+++ b/com32/lib/sys/vesa/initvesa.c
@@ -47,6 +47,7 @@ struct vesa_info __vesa_info;
struct vesa_char *__vesacon_text_display;
int __vesacon_font_height, __vesacon_text_rows;
+enum vesa_pixel_format __vesacon_pixel_format;
uint8_t __vesacon_graphics_font[FONT_MAX_CHARS][FONT_MAX_HEIGHT];
uint32_t __vesacon_background[VIDEO_Y_SIZE][VIDEO_X_SIZE];
@@ -90,9 +91,10 @@ static int vesacon_set_mode(void)
{
com32sys_t rm;
uint8_t *rom_font;
- uint16_t mode, *mode_ptr;
+ uint16_t mode, bestmode, *mode_ptr;
struct vesa_general_info *gi;
struct vesa_mode_info *mi;
+ enum vesa_pixel_format pxf, bestpxf;
/* Allocate space in the bounce buffer for these structures */
gi = &((struct vesa_info *)__com32.cs_bounce)->gi;
@@ -118,11 +120,10 @@ static int vesacon_set_mode(void)
/* Search for a 640x480 32-bit linear frame buffer mode */
mode_ptr = GET_PTR(gi->video_mode_ptr);
+ bestmode = 0;
+ bestpxf = PXF_NONE;
- for(;;) {
- if ((mode = *mode_ptr++) == 0xFFFF)
- return 4; /* No mode found */
-
+ while ((mode = *mode_ptr++) != 0xFFFF) {
debug("Found mode: 0x%04x\r\n", mode);
rm.eax.w[0] = 0x4F01; /* Get SVGA mode information */
@@ -142,21 +143,41 @@ static int vesacon_set_mode(void)
/* Must be an LFB color graphics mode supported by the hardware */
if ( (mi->mode_attr & 0x0099) != 0x0099 )
continue;
+
/* Must be 640x480, 32 bpp */
- if ( mi->h_res != VIDEO_X_SIZE || mi->v_res != VIDEO_Y_SIZE ||
- mi->bpp != 32 )
+ if ( mi->h_res != VIDEO_X_SIZE || mi->v_res != VIDEO_Y_SIZE )
continue;
+
/* Must either be a packed-pixel mode or a direct color mode
(depending on VESA version ) */
- if ( mi->memory_layout != 4 && /* Packed pixel */
- (mi->memory_layout != 6 || mi->rpos != 16 ||
- mi->gpos != 8 || mi->bpos != 0) )
- continue;
-
- /* Hey, looks like we found something we can live with */
- break;
+ if (mi->bpp == 32 &&
+ (mi->memory_layout == 4 ||
+ (mi->memory_layout == 6 && mi->rpos == 16 && mi->gpos == 8 &&
+ mi->bpos == 0)))
+ pxf = PXF_BGRA32;
+ else if (mi->bpp == 24 &&
+ (mi->memory_layout == 4 ||
+ (mi->memory_layout == 6 && mi->rpos == 16 && mi->gpos == 8 &&
+ mi->bpos == 0)))
+ pxf = PXF_BGR24;
+ else if (mi->bpp == 16 &&
+ (mi->memory_layout == 4 ||
+ (mi->memory_layout == 6 && mi->rpos == 11 && mi->gpos == 5 &&
+ mi->bpos == 0)))
+ pxf = PXF_LE_RGB16_565;
+ else
+ pxf = PXF_NONE; /* Not a usable mode for us */
+
+ if (pxf < bestpxf) {
+ /* Best mode so far... */
+ bestmode = mode;
+ bestpxf = pxf;
+ }
}
+ if (bestpxf == PXF_NONE)
+ return 4; /* No mode found */
+
/* Download the SYSLINUX- or BIOS-provided font */
rm.eax.w[0] = 0x0018; /* Query custom font */
__intcall(0x22, &rm, &rm);
diff --git a/com32/lib/sys/vesa/video.h b/com32/lib/sys/vesa/video.h
index 3bf93e39..ab3c765a 100644
--- a/com32/lib/sys/vesa/video.h
+++ b/com32/lib/sys/vesa/video.h
@@ -52,9 +52,10 @@ struct vesa_char {
};
/* Pixel formats in order of decreasing preference; PXF_NONE should be last */
+/* BGR24 is preferred over BGRA32 since the I/O overhead is smaller. */
enum vesa_pixel_format {
- PXF_BGRA32, /* 32-bit BGRA */
PXF_BGR24, /* 24-bit BGR */
+ PXF_BGRA32, /* 32-bit BGRA */
PXF_LE_RGB16_565, /* 16-bit littleendian 5:6:5 RGB */
PXF_NONE
};
@@ -62,6 +63,7 @@ enum vesa_pixel_format {
extern struct vesa_char *__vesacon_text_display;
extern int __vesacon_font_height, __vesacon_text_rows;
+extern enum vesa_pixel_format __vesacon_pixel_format;
extern uint8_t __vesacon_graphics_font[FONT_MAX_CHARS][FONT_MAX_HEIGHT];
extern uint32_t __vesacon_background[VIDEO_Y_SIZE][VIDEO_X_SIZE];
extern uint32_t __vesacon_shadowfb[VIDEO_Y_SIZE][VIDEO_X_SIZE];