diff --git a/hw/vga.c b/hw/vga.c index a712790c7c..b4eacc35b5 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -808,6 +808,11 @@ static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsign return (r << 16) | (g << 8) | b; } +static inline unsigned int rgb_to_pixel32bgr(unsigned int r, unsigned int g, unsigned b) +{ + return (b << 16) | (g << 8) | r; +} + #define DEPTH 8 #include "vga_template.h" @@ -820,6 +825,10 @@ static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsign #define DEPTH 32 #include "vga_template.h" +#define BGR_FORMAT +#define DEPTH 32 +#include "vga_template.h" + static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b) { unsigned int col; @@ -852,6 +861,13 @@ static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned return col; } +static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b) +{ + unsigned int col; + col = rgb_to_pixel32bgr(r, g, b); + return col; +} + /* return true if the palette was modified */ static int update_palette16(VGAState *s) { @@ -948,9 +964,11 @@ static int update_basic_params(VGAState *s) return full_update; } -static inline int get_depth_index(int depth) +#define NB_DEPTHS 5 + +static inline int get_depth_index(DisplayState *s) { - switch(depth) { + switch(s->depth) { default: case 8: return 0; @@ -959,29 +977,35 @@ static inline int get_depth_index(int depth) case 16: return 2; case 32: - return 3; + if (s->bgr) + return 4; + else + return 3; } } -static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = { +static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = { vga_draw_glyph8_8, vga_draw_glyph8_16, vga_draw_glyph8_16, vga_draw_glyph8_32, + vga_draw_glyph8_32, }; -static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = { +static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = { vga_draw_glyph16_8, vga_draw_glyph16_16, vga_draw_glyph16_16, vga_draw_glyph16_32, + vga_draw_glyph16_32, }; -static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = { +static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = { vga_draw_glyph9_8, vga_draw_glyph9_16, vga_draw_glyph9_16, vga_draw_glyph9_32, + vga_draw_glyph9_32, }; static const uint8_t cursor_glyph[32 * 4] = { @@ -1103,7 +1127,7 @@ static void vga_draw_text(VGAState *s, int full_update) } cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4; - depth_index = get_depth_index(s->ds->depth); + depth_index = get_depth_index(s->ds); if (cw == 16) vga_draw_glyph8 = vga_draw_glyph16_table[depth_index]; else @@ -1196,56 +1220,76 @@ enum { VGA_DRAW_LINE_NB, }; -static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = { +static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = { vga_draw_line2_8, vga_draw_line2_16, vga_draw_line2_16, vga_draw_line2_32, + vga_draw_line2_32, vga_draw_line2d2_8, vga_draw_line2d2_16, vga_draw_line2d2_16, vga_draw_line2d2_32, + vga_draw_line2d2_32, vga_draw_line4_8, vga_draw_line4_16, vga_draw_line4_16, vga_draw_line4_32, + vga_draw_line4_32, vga_draw_line4d2_8, vga_draw_line4d2_16, vga_draw_line4d2_16, vga_draw_line4d2_32, + vga_draw_line4d2_32, vga_draw_line8d2_8, vga_draw_line8d2_16, vga_draw_line8d2_16, vga_draw_line8d2_32, + vga_draw_line8d2_32, vga_draw_line8_8, vga_draw_line8_16, vga_draw_line8_16, vga_draw_line8_32, + vga_draw_line8_32, vga_draw_line15_8, vga_draw_line15_15, vga_draw_line15_16, vga_draw_line15_32, + vga_draw_line15_32bgr, vga_draw_line16_8, vga_draw_line16_15, vga_draw_line16_16, vga_draw_line16_32, + vga_draw_line16_32bgr, vga_draw_line24_8, vga_draw_line24_15, vga_draw_line24_16, vga_draw_line24_32, + vga_draw_line24_32bgr, vga_draw_line32_8, vga_draw_line32_15, vga_draw_line32_16, vga_draw_line32_32, + vga_draw_line32_32bgr, +}; + +typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b); + +static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = { + rgb_to_pixel8_dup, + rgb_to_pixel15_dup, + rgb_to_pixel16_dup, + rgb_to_pixel32_dup, + rgb_to_pixel32bgr_dup, }; static int vga_get_bpp(VGAState *s) @@ -1362,7 +1406,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) break; } } - vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)]; + vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)]; if (disp_width != s->last_width || height != s->last_height) { @@ -1492,21 +1536,8 @@ static void vga_update_display(void *opaque) if (s->ds->depth == 0) { /* nothing to do */ } else { - switch(s->ds->depth) { - case 8: - s->rgb_to_pixel = rgb_to_pixel8_dup; - break; - case 15: - s->rgb_to_pixel = rgb_to_pixel15_dup; - break; - default: - case 16: - s->rgb_to_pixel = rgb_to_pixel16_dup; - break; - case 32: - s->rgb_to_pixel = rgb_to_pixel32_dup; - break; - } + s->rgb_to_pixel = + rgb_to_pixel_dup_table[get_depth_index(s->ds)]; full_update = 0; if (!(s->ar_index & 0x20)) { diff --git a/hw/vga_template.h b/hw/vga_template.h index 909571ebb3..4ea938e01c 100644 --- a/hw/vga_template.h +++ b/hw/vga_template.h @@ -35,7 +35,13 @@ #error unsupport depth #endif -#if DEPTH != 15 +#ifdef BGR_FORMAT +#define PIXEL_NAME glue(DEPTH, bgr) +#else +#define PIXEL_NAME DEPTH +#endif /* BGR_FORMAT */ + +#if DEPTH != 15 && !defined(BGR_FORMAT) static inline void glue(vga_draw_glyph_line_, DEPTH)(uint8_t *d, uint32_t font_data, @@ -334,118 +340,6 @@ static void glue(vga_draw_line8_, DEPTH)(VGAState *s1, uint8_t *d, } } -#endif /* DEPTH != 15 */ - - -/* XXX: optimize */ - -/* - * 15 bit color - */ -static void glue(vga_draw_line15_, DEPTH)(VGAState *s1, uint8_t *d, - const uint8_t *s, int width) -{ -#if DEPTH == 15 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) - memcpy(d, s, width * 2); -#else - int w; - uint32_t v, r, g, b; - - w = width; - do { - v = lduw_raw((void *)s); - r = (v >> 7) & 0xf8; - g = (v >> 2) & 0xf8; - b = (v << 3) & 0xf8; - ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); - s += 2; - d += BPP; - } while (--w != 0); -#endif -} - -/* - * 16 bit color - */ -static void glue(vga_draw_line16_, DEPTH)(VGAState *s1, uint8_t *d, - const uint8_t *s, int width) -{ -#if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) - memcpy(d, s, width * 2); -#else - int w; - uint32_t v, r, g, b; - - w = width; - do { - v = lduw_raw((void *)s); - r = (v >> 8) & 0xf8; - g = (v >> 3) & 0xfc; - b = (v << 3) & 0xf8; - ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); - s += 2; - d += BPP; - } while (--w != 0); -#endif -} - -/* - * 24 bit color - */ -static void glue(vga_draw_line24_, DEPTH)(VGAState *s1, uint8_t *d, - const uint8_t *s, int width) -{ - int w; - uint32_t r, g, b; - - w = width; - do { -#if defined(TARGET_WORDS_BIGENDIAN) - r = s[0]; - g = s[1]; - b = s[2]; -#else - b = s[0]; - g = s[1]; - r = s[2]; -#endif - ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); - s += 3; - d += BPP; - } while (--w != 0); -} - -/* - * 32 bit color - */ -static void glue(vga_draw_line32_, DEPTH)(VGAState *s1, uint8_t *d, - const uint8_t *s, int width) -{ -#if DEPTH == 32 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) - memcpy(d, s, width * 4); -#else - int w; - uint32_t r, g, b; - - w = width; - do { -#if defined(TARGET_WORDS_BIGENDIAN) - r = s[1]; - g = s[2]; - b = s[3]; -#else - b = s[0]; - g = s[1]; - r = s[2]; -#endif - ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); - s += 4; - d += BPP; - } while (--w != 0); -#endif -} - -#if DEPTH != 15 void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1, const uint8_t *src1, int poffset, int w, @@ -511,9 +405,121 @@ void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1, d += BPP; } } + +#endif /* DEPTH != 15 */ + + +/* XXX: optimize */ + +/* + * 15 bit color + */ +static void glue(vga_draw_line15_, PIXEL_NAME)(VGAState *s1, uint8_t *d, + const uint8_t *s, int width) +{ +#if DEPTH == 15 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) + memcpy(d, s, width * 2); +#else + int w; + uint32_t v, r, g, b; + + w = width; + do { + v = lduw_raw((void *)s); + r = (v >> 7) & 0xf8; + g = (v >> 2) & 0xf8; + b = (v << 3) & 0xf8; + ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b); + s += 2; + d += BPP; + } while (--w != 0); +#endif +} + +/* + * 16 bit color + */ +static void glue(vga_draw_line16_, PIXEL_NAME)(VGAState *s1, uint8_t *d, + const uint8_t *s, int width) +{ +#if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) + memcpy(d, s, width * 2); +#else + int w; + uint32_t v, r, g, b; + + w = width; + do { + v = lduw_raw((void *)s); + r = (v >> 8) & 0xf8; + g = (v >> 3) & 0xfc; + b = (v << 3) & 0xf8; + ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b); + s += 2; + d += BPP; + } while (--w != 0); +#endif +} + +/* + * 24 bit color + */ +static void glue(vga_draw_line24_, PIXEL_NAME)(VGAState *s1, uint8_t *d, + const uint8_t *s, int width) +{ + int w; + uint32_t r, g, b; + + w = width; + do { +#if defined(TARGET_WORDS_BIGENDIAN) + r = s[0]; + g = s[1]; + b = s[2]; +#else + b = s[0]; + g = s[1]; + r = s[2]; #endif + ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b); + s += 3; + d += BPP; + } while (--w != 0); +} + +/* + * 32 bit color + */ +static void glue(vga_draw_line32_, PIXEL_NAME)(VGAState *s1, uint8_t *d, + const uint8_t *s, int width) +{ +#if DEPTH == 32 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) + memcpy(d, s, width * 4); +#else + int w; + uint32_t r, g, b; + + w = width; + do { +#if defined(TARGET_WORDS_BIGENDIAN) + r = s[1]; + g = s[2]; + b = s[3]; +#else + b = s[0]; + g = s[1]; + r = s[2]; +#endif + ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b); + s += 4; + d += BPP; + } while (--w != 0); +#endif +} #undef PUT_PIXEL2 #undef DEPTH #undef BPP #undef PIXEL_TYPE +#undef PIXEL_NAME +#undef BGR_FORMAT diff --git a/sdl.c b/sdl.c index 72a70808db..ec4f93c5ef 100644 --- a/sdl.c +++ b/sdl.c @@ -81,6 +81,11 @@ static void sdl_resize(DisplayState *ds, int w, int h) ds->data = screen->pixels; ds->linesize = screen->pitch; ds->depth = screen->format->BitsPerPixel; + if (ds->depth == 32 && screen->format->Rshift == 0) { + ds->bgr = 1; + } else { + ds->bgr = 0; + } ds->width = w; ds->height = h; } diff --git a/vl.h b/vl.h index 58a7877d10..7d51ff5764 100644 --- a/vl.h +++ b/vl.h @@ -677,6 +677,7 @@ struct DisplayState { uint8_t *data; int linesize; int depth; + int bgr; /* BGR color order instead of RGB. Only valid for depth == 32 */ int width; int height; void *opaque;