diff options
Diffstat (limited to 'hw/display')
32 files changed, 3122 insertions, 77 deletions
diff --git a/hw/display/blizzard.c b/hw/display/blizzard.c index bdb0b15ddb..175c5cdd00 100644 --- a/hw/display/blizzard.c +++ b/hw/display/blizzard.c @@ -21,7 +21,7 @@ #include "qemu-common.h" #include "ui/console.h" #include "hw/arm/devices.h" -#include "hw/vga_int.h" +#include "vga_int.h" #include "ui/pixel_ops.h" typedef void (*blizzard_fn_t)(uint8_t *, const uint8_t *, unsigned int); @@ -946,15 +946,15 @@ static void blizzard_screen_dump(void *opaque, const char *filename, } #define DEPTH 8 -#include "hw/blizzard_template.h" +#include "blizzard_template.h" #define DEPTH 15 -#include "hw/blizzard_template.h" +#include "blizzard_template.h" #define DEPTH 16 -#include "hw/blizzard_template.h" +#include "blizzard_template.h" #define DEPTH 24 -#include "hw/blizzard_template.h" +#include "blizzard_template.h" #define DEPTH 32 -#include "hw/blizzard_template.h" +#include "blizzard_template.h" void *s1d13745_init(qemu_irq gpio_int) { diff --git a/hw/display/blizzard_template.h b/hw/display/blizzard_template.h new file mode 100644 index 0000000000..a8a8899478 --- /dev/null +++ b/hw/display/blizzard_template.h @@ -0,0 +1,136 @@ +/* + * QEMU Epson S1D13744/S1D13745 templates + * + * Copyright (C) 2008 Nokia Corporation + * Written by Andrzej Zaborowski <andrew@openedhand.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#define SKIP_PIXEL(to) to += deststep +#if DEPTH == 8 +# define PIXEL_TYPE uint8_t +# define COPY_PIXEL(to, from) *to = from; SKIP_PIXEL(to) +# define COPY_PIXEL1(to, from) *to ++ = from +#elif DEPTH == 15 || DEPTH == 16 +# define PIXEL_TYPE uint16_t +# define COPY_PIXEL(to, from) *to = from; SKIP_PIXEL(to) +# define COPY_PIXEL1(to, from) *to ++ = from +#elif DEPTH == 24 +# define PIXEL_TYPE uint8_t +# define COPY_PIXEL(to, from) \ + to[0] = from; to[1] = (from) >> 8; to[2] = (from) >> 16; SKIP_PIXEL(to) +# define COPY_PIXEL1(to, from) \ + *to ++ = from; *to ++ = (from) >> 8; *to ++ = (from) >> 16 +#elif DEPTH == 32 +# define PIXEL_TYPE uint32_t +# define COPY_PIXEL(to, from) *to = from; SKIP_PIXEL(to) +# define COPY_PIXEL1(to, from) *to ++ = from +#else +# error unknown bit depth +#endif + +#ifdef HOST_WORDS_BIGENDIAN +# define SWAP_WORDS 1 +#endif + +static void glue(blizzard_draw_line16_, DEPTH)(PIXEL_TYPE *dest, + const uint16_t *src, unsigned int width) +{ +#if !defined(SWAP_WORDS) && DEPTH == 16 + memcpy(dest, src, width); +#else + uint16_t data; + unsigned int r, g, b; + const uint16_t *end = (const void *) src + width; + while (src < end) { + data = *src ++; + b = (data & 0x1f) << 3; + data >>= 5; + g = (data & 0x3f) << 2; + data >>= 6; + r = (data & 0x1f) << 3; + data >>= 5; + COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b)); + } +#endif +} + +static void glue(blizzard_draw_line24mode1_, DEPTH)(PIXEL_TYPE *dest, + const uint8_t *src, unsigned int width) +{ + /* TODO: check if SDL 24-bit planes are not in the same format and + * if so, use memcpy */ + unsigned int r[2], g[2], b[2]; + const uint8_t *end = src + width; + while (src < end) { + g[0] = *src ++; + r[0] = *src ++; + r[1] = *src ++; + b[0] = *src ++; + COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r[0], g[0], b[0])); + b[1] = *src ++; + g[1] = *src ++; + COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r[1], g[1], b[1])); + } +} + +static void glue(blizzard_draw_line24mode2_, DEPTH)(PIXEL_TYPE *dest, + const uint8_t *src, unsigned int width) +{ + unsigned int r, g, b; + const uint8_t *end = src + width; + while (src < end) { + r = *src ++; + src ++; + b = *src ++; + g = *src ++; + COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b)); + } +} + +/* No rotation */ +static blizzard_fn_t glue(blizzard_draw_fn_, DEPTH)[0x10] = { + NULL, + /* RGB 5:6:5*/ + (blizzard_fn_t) glue(blizzard_draw_line16_, DEPTH), + /* RGB 6:6:6 mode 1 */ + (blizzard_fn_t) glue(blizzard_draw_line24mode1_, DEPTH), + /* RGB 8:8:8 mode 1 */ + (blizzard_fn_t) glue(blizzard_draw_line24mode1_, DEPTH), + NULL, NULL, + /* RGB 6:6:6 mode 2 */ + (blizzard_fn_t) glue(blizzard_draw_line24mode2_, DEPTH), + /* RGB 8:8:8 mode 2 */ + (blizzard_fn_t) glue(blizzard_draw_line24mode2_, DEPTH), + /* YUV 4:2:2 */ + NULL, + /* YUV 4:2:0 */ + NULL, + NULL, NULL, NULL, NULL, NULL, NULL, +}; + +/* 90deg, 180deg and 270deg rotation */ +static blizzard_fn_t glue(blizzard_draw_fn_r_, DEPTH)[0x10] = { + /* TODO */ + [0 ... 0xf] = NULL, +}; + +#undef DEPTH +#undef SKIP_PIXEL +#undef COPY_PIXEL +#undef COPY_PIXEL1 +#undef PIXEL_TYPE + +#undef SWAP_WORDS diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index 7a4d63436e..bf2181afd8 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -29,7 +29,7 @@ #include "hw/hw.h" #include "hw/pci/pci.h" #include "ui/console.h" -#include "hw/vga_int.h" +#include "vga_int.h" #include "hw/loader.h" /* @@ -288,63 +288,63 @@ static void cirrus_bitblt_fill_nop(CirrusVGAState *s, #define ROP_NAME 0 #define ROP_FN(d, s) 0 -#include "hw/cirrus_vga_rop.h" +#include "cirrus_vga_rop.h" #define ROP_NAME src_and_dst #define ROP_FN(d, s) (s) & (d) -#include "hw/cirrus_vga_rop.h" +#include "cirrus_vga_rop.h" #define ROP_NAME src_and_notdst #define ROP_FN(d, s) (s) & (~(d)) -#include "hw/cirrus_vga_rop.h" +#include "cirrus_vga_rop.h" #define ROP_NAME notdst #define ROP_FN(d, s) ~(d) -#include "hw/cirrus_vga_rop.h" +#include "cirrus_vga_rop.h" #define ROP_NAME src #define ROP_FN(d, s) s -#include "hw/cirrus_vga_rop.h" +#include "cirrus_vga_rop.h" #define ROP_NAME 1 #define ROP_FN(d, s) ~0 -#include "hw/cirrus_vga_rop.h" +#include "cirrus_vga_rop.h" #define ROP_NAME notsrc_and_dst #define ROP_FN(d, s) (~(s)) & (d) -#include "hw/cirrus_vga_rop.h" +#include "cirrus_vga_rop.h" #define ROP_NAME src_xor_dst #define ROP_FN(d, s) (s) ^ (d) -#include "hw/cirrus_vga_rop.h" +#include "cirrus_vga_rop.h" #define ROP_NAME src_or_dst #define ROP_FN(d, s) (s) | (d) -#include "hw/cirrus_vga_rop.h" +#include "cirrus_vga_rop.h" #define ROP_NAME notsrc_or_notdst #define ROP_FN(d, s) (~(s)) | (~(d)) -#include "hw/cirrus_vga_rop.h" +#include "cirrus_vga_rop.h" #define ROP_NAME src_notxor_dst #define ROP_FN(d, s) ~((s) ^ (d)) -#include "hw/cirrus_vga_rop.h" +#include "cirrus_vga_rop.h" #define ROP_NAME src_or_notdst #define ROP_FN(d, s) (s) | (~(d)) -#include "hw/cirrus_vga_rop.h" +#include "cirrus_vga_rop.h" #define ROP_NAME notsrc #define ROP_FN(d, s) (~(s)) -#include "hw/cirrus_vga_rop.h" +#include "cirrus_vga_rop.h" #define ROP_NAME notsrc_or_dst #define ROP_FN(d, s) (~(s)) | (d) -#include "hw/cirrus_vga_rop.h" +#include "cirrus_vga_rop.h" #define ROP_NAME notsrc_and_notdst #define ROP_FN(d, s) (~(s)) & (~(d)) -#include "hw/cirrus_vga_rop.h" +#include "cirrus_vga_rop.h" static const cirrus_bitblt_rop_t cirrus_fwd_rop[16] = { cirrus_bitblt_rop_fwd_0, @@ -2166,13 +2166,13 @@ static void cirrus_cursor_invalidate(VGACommonState *s1) } #define DEPTH 8 -#include "hw/cirrus_vga_template.h" +#include "cirrus_vga_template.h" #define DEPTH 16 -#include "hw/cirrus_vga_template.h" +#include "cirrus_vga_template.h" #define DEPTH 32 -#include "hw/cirrus_vga_template.h" +#include "cirrus_vga_template.h" static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y) { diff --git a/hw/display/cirrus_vga_rop.h b/hw/display/cirrus_vga_rop.h new file mode 100644 index 0000000000..9c7bb09286 --- /dev/null +++ b/hw/display/cirrus_vga_rop.h @@ -0,0 +1,208 @@ +/* + * QEMU Cirrus CLGD 54xx VGA Emulator. + * + * Copyright (c) 2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +static inline void glue(rop_8_,ROP_NAME)(uint8_t *dst, uint8_t src) +{ + *dst = ROP_FN(*dst, src); +} + +static inline void glue(rop_16_,ROP_NAME)(uint16_t *dst, uint16_t src) +{ + *dst = ROP_FN(*dst, src); +} + +static inline void glue(rop_32_,ROP_NAME)(uint32_t *dst, uint32_t src) +{ + *dst = ROP_FN(*dst, src); +} + +#define ROP_OP(d, s) glue(rop_8_,ROP_NAME)(d, s) +#define ROP_OP_16(d, s) glue(rop_16_,ROP_NAME)(d, s) +#define ROP_OP_32(d, s) glue(rop_32_,ROP_NAME)(d, s) +#undef ROP_FN + +static void +glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + dstpitch -= bltwidth; + srcpitch -= bltwidth; + + if (dstpitch < 0 || srcpitch < 0) { + /* is 0 valid? srcpitch == 0 could be useful */ + return; + } + + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { + ROP_OP(dst, *src); + dst++; + src++; + } + dst += dstpitch; + src += srcpitch; + } +} + +static void +glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + dstpitch += bltwidth; + srcpitch += bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { + ROP_OP(dst, *src); + dst--; + src--; + } + dst += dstpitch; + src += srcpitch; + } +} + +static void +glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + uint8_t p; + dstpitch -= bltwidth; + srcpitch -= bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { + p = *dst; + ROP_OP(&p, *src); + if (p != s->vga.gr[0x34]) *dst = p; + dst++; + src++; + } + dst += dstpitch; + src += srcpitch; + } +} + +static void +glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + uint8_t p; + dstpitch += bltwidth; + srcpitch += bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { + p = *dst; + ROP_OP(&p, *src); + if (p != s->vga.gr[0x34]) *dst = p; + dst--; + src--; + } + dst += dstpitch; + src += srcpitch; + } +} + +static void +glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + uint8_t p1, p2; + dstpitch -= bltwidth; + srcpitch -= bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x+=2) { + p1 = *dst; + p2 = *(dst+1); + ROP_OP(&p1, *src); + ROP_OP(&p2, *(src + 1)); + if ((p1 != s->vga.gr[0x34]) || (p2 != s->vga.gr[0x35])) { + *dst = p1; + *(dst+1) = p2; + } + dst+=2; + src+=2; + } + dst += dstpitch; + src += srcpitch; + } +} + +static void +glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + uint8_t p1, p2; + dstpitch += bltwidth; + srcpitch += bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x+=2) { + p1 = *(dst-1); + p2 = *dst; + ROP_OP(&p1, *(src - 1)); + ROP_OP(&p2, *src); + if ((p1 != s->vga.gr[0x34]) || (p2 != s->vga.gr[0x35])) { + *(dst-1) = p1; + *dst = p2; + } + dst-=2; + src-=2; + } + dst += dstpitch; + src += srcpitch; + } +} + +#define DEPTH 8 +#include "cirrus_vga_rop2.h" + +#define DEPTH 16 +#include "cirrus_vga_rop2.h" + +#define DEPTH 24 +#include "cirrus_vga_rop2.h" + +#define DEPTH 32 +#include "cirrus_vga_rop2.h" + +#undef ROP_NAME +#undef ROP_OP +#undef ROP_OP_16 +#undef ROP_OP_32 diff --git a/hw/display/cirrus_vga_rop2.h b/hw/display/cirrus_vga_rop2.h new file mode 100644 index 0000000000..d28bcc6f25 --- /dev/null +++ b/hw/display/cirrus_vga_rop2.h @@ -0,0 +1,281 @@ +/* + * QEMU Cirrus CLGD 54xx VGA Emulator. + * + * Copyright (c) 2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if DEPTH == 8 +#define PUTPIXEL() ROP_OP(&d[0], col) +#elif DEPTH == 16 +#define PUTPIXEL() ROP_OP_16((uint16_t *)&d[0], col) +#elif DEPTH == 24 +#define PUTPIXEL() ROP_OP(&d[0], col); \ + ROP_OP(&d[1], (col >> 8)); \ + ROP_OP(&d[2], (col >> 16)) +#elif DEPTH == 32 +#define PUTPIXEL() ROP_OP_32(((uint32_t *)&d[0]), col) +#else +#error unsupported DEPTH +#endif + +static void +glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) + (CirrusVGAState * s, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint8_t *d; + int x, y, pattern_y, pattern_pitch, pattern_x; + unsigned int col; + const uint8_t *src1; +#if DEPTH == 24 + int skipleft = s->vga.gr[0x2f] & 0x1f; +#else + int skipleft = (s->vga.gr[0x2f] & 0x07) * (DEPTH / 8); +#endif + +#if DEPTH == 8 + pattern_pitch = 8; +#elif DEPTH == 16 + pattern_pitch = 16; +#else + pattern_pitch = 32; +#endif + pattern_y = s->cirrus_blt_srcaddr & 7; + for(y = 0; y < bltheight; y++) { + pattern_x = skipleft; + d = dst + skipleft; + src1 = src + pattern_y * pattern_pitch; + for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) { +#if DEPTH == 8 + col = src1[pattern_x]; + pattern_x = (pattern_x + 1) & 7; +#elif DEPTH == 16 + col = ((uint16_t *)(src1 + pattern_x))[0]; + pattern_x = (pattern_x + 2) & 15; +#elif DEPTH == 24 + { + const uint8_t *src2 = src1 + pattern_x * 3; + col = src2[0] | (src2[1] << 8) | (src2[2] << 16); + pattern_x = (pattern_x + 1) & 7; + } +#else + col = ((uint32_t *)(src1 + pattern_x))[0]; + pattern_x = (pattern_x + 4) & 31; +#endif + PUTPIXEL(); + d += (DEPTH / 8); + } + pattern_y = (pattern_y + 1) & 7; + dst += dstpitch; + } +} + +/* NOTE: srcpitch is ignored */ +static void +glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) + (CirrusVGAState * s, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint8_t *d; + int x, y; + unsigned bits, bits_xor; + unsigned int col; + unsigned bitmask; + unsigned index; +#if DEPTH == 24 + int dstskipleft = s->vga.gr[0x2f] & 0x1f; + int srcskipleft = dstskipleft / 3; +#else + int srcskipleft = s->vga.gr[0x2f] & 0x07; + int dstskipleft = srcskipleft * (DEPTH / 8); +#endif + + if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { + bits_xor = 0xff; + col = s->cirrus_blt_bgcol; + } else { + bits_xor = 0x00; + col = s->cirrus_blt_fgcol; + } + + for(y = 0; y < bltheight; y++) { + bitmask = 0x80 >> srcskipleft; + bits = *src++ ^ bits_xor; + d = dst + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + if ((bitmask & 0xff) == 0) { + bitmask = 0x80; + bits = *src++ ^ bits_xor; + } + index = (bits & bitmask); + if (index) { + PUTPIXEL(); + } + d += (DEPTH / 8); + bitmask >>= 1; + } + dst += dstpitch; + } +} + +static void +glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) + (CirrusVGAState * s, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint32_t colors[2]; + uint8_t *d; + int x, y; + unsigned bits; + unsigned int col; + unsigned bitmask; + int srcskipleft = s->vga.gr[0x2f] & 0x07; + int dstskipleft = srcskipleft * (DEPTH / 8); + + colors[0] = s->cirrus_blt_bgcol; + colors[1] = s->cirrus_blt_fgcol; + for(y = 0; y < bltheight; y++) { + bitmask = 0x80 >> srcskipleft; + bits = *src++; + d = dst + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + if ((bitmask & 0xff) == 0) { + bitmask = 0x80; + bits = *src++; + } + col = colors[!!(bits & bitmask)]; + PUTPIXEL(); + d += (DEPTH / 8); + bitmask >>= 1; + } + dst += dstpitch; + } +} + +static void +glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) + (CirrusVGAState * s, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint8_t *d; + int x, y, bitpos, pattern_y; + unsigned int bits, bits_xor; + unsigned int col; +#if DEPTH == 24 + int dstskipleft = s->vga.gr[0x2f] & 0x1f; + int srcskipleft = dstskipleft / 3; +#else + int srcskipleft = s->vga.gr[0x2f] & 0x07; + int dstskipleft = srcskipleft * (DEPTH / 8); +#endif + + if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { + bits_xor = 0xff; + col = s->cirrus_blt_bgcol; + } else { + bits_xor = 0x00; + col = s->cirrus_blt_fgcol; + } + pattern_y = s->cirrus_blt_srcaddr & 7; + + for(y = 0; y < bltheight; y++) { + bits = src[pattern_y] ^ bits_xor; + bitpos = 7 - srcskipleft; + d = dst + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + if ((bits >> bitpos) & 1) { + PUTPIXEL(); + } + d += (DEPTH / 8); + bitpos = (bitpos - 1) & 7; + } + pattern_y = (pattern_y + 1) & 7; + dst += dstpitch; + } +} + +static void +glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH) + (CirrusVGAState * s, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint32_t colors[2]; + uint8_t *d; + int x, y, bitpos, pattern_y; + unsigned int bits; + unsigned int col; + int srcskipleft = s->vga.gr[0x2f] & 0x07; + int dstskipleft = srcskipleft * (DEPTH / 8); + + colors[0] = s->cirrus_blt_bgcol; + colors[1] = s->cirrus_blt_fgcol; + pattern_y = s->cirrus_blt_srcaddr & 7; + + for(y = 0; y < bltheight; y++) { + bits = src[pattern_y]; + bitpos = 7 - srcskipleft; + d = dst + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + col = colors[(bits >> bitpos) & 1]; + PUTPIXEL(); + d += (DEPTH / 8); + bitpos = (bitpos - 1) & 7; + } + pattern_y = (pattern_y + 1) & 7; + dst += dstpitch; + } +} + +static void +glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH) + (CirrusVGAState *s, + uint8_t *dst, int dst_pitch, + int width, int height) +{ + uint8_t *d, *d1; + uint32_t col; + int x, y; + + col = s->cirrus_blt_fgcol; + + d1 = dst; + for(y = 0; y < height; y++) { + d = d1; + for(x = 0; x < width; x += (DEPTH / 8)) { + PUTPIXEL(); + d += (DEPTH / 8); + } + d1 += dst_pitch; + } +} + +#undef DEPTH +#undef PUTPIXEL diff --git a/hw/display/cirrus_vga_template.h b/hw/display/cirrus_vga_template.h new file mode 100644 index 0000000000..3b28280588 --- /dev/null +++ b/hw/display/cirrus_vga_template.h @@ -0,0 +1,102 @@ +/* + * QEMU Cirrus VGA Emulator templates + * + * Copyright (c) 2003 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if DEPTH == 8 +#define BPP 1 +#elif DEPTH == 15 || DEPTH == 16 +#define BPP 2 +#elif DEPTH == 32 +#define BPP 4 +#else +#error unsupported depth +#endif + +static void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1, + const uint8_t *src1, + int poffset, int w, + unsigned int color0, + unsigned int color1, + unsigned int color_xor) +{ + const uint8_t *plane0, *plane1; + int x, b0, b1; + uint8_t *d; + + d = d1; + plane0 = src1; + plane1 = src1 + poffset; + for (x = 0; x < w; x++) { + b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1; + b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1; +#if DEPTH == 8 + switch (b0 | (b1 << 1)) { + case 0: + break; + case 1: + d[0] ^= color_xor; + break; + case 2: + d[0] = color0; + break; + case 3: + d[0] = color1; + break; + } +#elif DEPTH == 16 + switch (b0 | (b1 << 1)) { + case 0: + break; + case 1: + ((uint16_t *)d)[0] ^= color_xor; + break; + case 2: + ((uint16_t *)d)[0] = color0; + break; + case 3: + ((uint16_t *)d)[0] = color1; + break; + } +#elif DEPTH == 32 + switch (b0 | (b1 << 1)) { + case 0: + break; + case 1: + ((uint32_t *)d)[0] ^= color_xor; + break; + case 2: + ((uint32_t *)d)[0] = color0; + break; + case 3: + ((uint32_t *)d)[0] = color1; + break; + } +#else +#error unsupported depth +#endif + d += BPP; + } +} + +#undef DEPTH +#undef BPP diff --git a/hw/display/framebuffer.c b/hw/display/framebuffer.c index 7326a98a41..6be31db2b5 100644 --- a/hw/display/framebuffer.c +++ b/hw/display/framebuffer.c @@ -19,7 +19,7 @@ #include "hw/hw.h" #include "ui/console.h" -#include "hw/framebuffer.h" +#include "framebuffer.h" /* Render an image from a shared memory framebuffer. */ diff --git a/hw/display/framebuffer.h b/hw/display/framebuffer.h new file mode 100644 index 0000000000..6eae035b7d --- /dev/null +++ b/hw/display/framebuffer.h @@ -0,0 +1,25 @@ +#ifndef QEMU_FRAMEBUFFER_H +#define QEMU_FRAMEBUFFER_H + +#include "exec/memory.h" + +/* Framebuffer device helper routines. */ + +typedef void (*drawfn)(void *, uint8_t *, const uint8_t *, int, int); + +void framebuffer_update_display( + DisplaySurface *ds, + MemoryRegion *address_space, + hwaddr base, + int cols, + int rows, + int src_width, + int dest_row_pitch, + int dest_col_pitch, + int invalidate, + drawfn fn, + void *opaque, + int *first_row, + int *last_row); + +#endif diff --git a/hw/display/milkymist-vgafb.c b/hw/display/milkymist-vgafb.c index 98762ecd21..3219041c81 100644 --- a/hw/display/milkymist-vgafb.c +++ b/hw/display/milkymist-vgafb.c @@ -26,20 +26,20 @@ #include "hw/sysbus.h" #include "trace.h" #include "ui/console.h" -#include "hw/framebuffer.h" +#include "framebuffer.h" #include "ui/pixel_ops.h" #include "qemu/error-report.h" #define BITS 8 -#include "hw/milkymist-vgafb_template.h" +#include "milkymist-vgafb_template.h" #define BITS 15 -#include "hw/milkymist-vgafb_template.h" +#include "milkymist-vgafb_template.h" #define BITS 16 -#include "hw/milkymist-vgafb_template.h" +#include "milkymist-vgafb_template.h" #define BITS 24 -#include "hw/milkymist-vgafb_template.h" +#include "milkymist-vgafb_template.h" #define BITS 32 -#include "hw/milkymist-vgafb_template.h" +#include "milkymist-vgafb_template.h" enum { R_CTRL = 0, diff --git a/hw/display/milkymist-vgafb_template.h b/hw/display/milkymist-vgafb_template.h new file mode 100644 index 0000000000..e0036e16cf --- /dev/null +++ b/hw/display/milkymist-vgafb_template.h @@ -0,0 +1,74 @@ +/* + * QEMU model of the Milkymist VGA framebuffer. + * + * Copyright (c) 2010 Michael Walle <michael@walle.cc> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + * + */ + +#if BITS == 8 +#define COPY_PIXEL(to, r, g, b) \ + do { \ + *to = rgb_to_pixel8(r, g, b); \ + to += 1; \ + } while (0) +#elif BITS == 15 +#define COPY_PIXEL(to, r, g, b) \ + do { \ + *(uint16_t *)to = rgb_to_pixel15(r, g, b); \ + to += 2; \ + } while (0) +#elif BITS == 16 +#define COPY_PIXEL(to, r, g, b) \ + do { \ + *(uint16_t *)to = rgb_to_pixel16(r, g, b); \ + to += 2; \ + } while (0) +#elif BITS == 24 +#define COPY_PIXEL(to, r, g, b) \ + do { \ + uint32_t tmp = rgb_to_pixel24(r, g, b); \ + *(to++) = tmp & 0xff; \ + *(to++) = (tmp >> 8) & 0xff; \ + *(to++) = (tmp >> 16) & 0xff; \ + } while (0) +#elif BITS == 32 +#define COPY_PIXEL(to, r, g, b) \ + do { \ + *(uint32_t *)to = rgb_to_pixel32(r, g, b); \ + to += 4; \ + } while (0) +#else +#error unknown bit depth +#endif + +static void glue(draw_line_, BITS)(void *opaque, uint8_t *d, const uint8_t *s, + int width, int deststep) +{ + uint16_t rgb565; + uint8_t r, g, b; + + while (width--) { + memcpy(&rgb565, s, sizeof(rgb565)); + r = ((rgb565 >> 11) & 0x1f) << 3; + g = ((rgb565 >> 5) & 0x3f) << 2; + b = ((rgb565 >> 0) & 0x1f) << 3; + COPY_PIXEL(d, r, g, b); + s += 2; + } +} + +#undef BITS +#undef COPY_PIXEL diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h new file mode 100644 index 0000000000..2fb96f83ae --- /dev/null +++ b/hw/display/omap_lcd_template.h @@ -0,0 +1,175 @@ +/* + * QEMU OMAP LCD Emulator templates + * + * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if DEPTH == 8 +# define BPP 1 +# define PIXEL_TYPE uint8_t +#elif DEPTH == 15 || DEPTH == 16 +# define BPP 2 +# define PIXEL_TYPE uint16_t +#elif DEPTH == 32 +# define BPP 4 +# define PIXEL_TYPE uint32_t +#else +# error unsupport depth +#endif + +/* + * 2-bit colour + */ +static void glue(draw_line2_, DEPTH)(void *opaque, + uint8_t *d, const uint8_t *s, int width, int deststep) +{ + uint16_t *pal = opaque; + uint8_t v, r, g, b; + + do { + v = ldub_raw((void *) s); + r = (pal[v & 3] >> 4) & 0xf0; + g = pal[v & 3] & 0xf0; + b = (pal[v & 3] << 4) & 0xf0; + ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); + d += BPP; + v >>= 2; + r = (pal[v & 3] >> 4) & 0xf0; + g = pal[v & 3] & 0xf0; + b = (pal[v & 3] << 4) & 0xf0; + ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); + d += BPP; + v >>= 2; + r = (pal[v & 3] >> 4) & 0xf0; + g = pal[v & 3] & 0xf0; + b = (pal[v & 3] << 4) & 0xf0; + ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); + d += BPP; + v >>= 2; + r = (pal[v & 3] >> 4) & 0xf0; + g = pal[v & 3] & 0xf0; + b = (pal[v & 3] << 4) & 0xf0; + ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); + d += BPP; + s ++; + width -= 4; + } while (width > 0); +} + +/* + * 4-bit colour + */ +static void glue(draw_line4_, DEPTH)(void *opaque, + uint8_t *d, const uint8_t *s, int width, int deststep) +{ + uint16_t *pal = opaque; + uint8_t v, r, g, b; + + do { + v = ldub_raw((void *) s); + r = (pal[v & 0xf] >> 4) & 0xf0; + g = pal[v & 0xf] & 0xf0; + b = (pal[v & 0xf] << 4) & 0xf0; + ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); + d += BPP; + v >>= 4; + r = (pal[v & 0xf] >> 4) & 0xf0; + g = pal[v & 0xf] & 0xf0; + b = (pal[v & 0xf] << 4) & 0xf0; + ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); + d += BPP; + s ++; + width -= 2; + } while (width > 0); +} + +/* + * 8-bit colour + */ +static void glue(draw_line8_, DEPTH)(void *opaque, + uint8_t *d, const uint8_t *s, int width, int deststep) +{ + uint16_t *pal = opaque; + uint8_t v, r, g, b; + + do { + v = ldub_raw((void *) s); + r = (pal[v] >> 4) & 0xf0; + g = pal[v] & 0xf0; + b = (pal[v] << 4) & 0xf0; + ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); + s ++; + d += BPP; + } while (-- width != 0); +} + +/* + * 12-bit colour + */ +static void glue(draw_line12_, DEPTH)(void *opaque, + uint8_t *d, const uint8_t *s, int width, int deststep) +{ + uint16_t v; + uint8_t r, g, b; + + do { + v = lduw_raw((void *) s); + r = (v >> 4) & 0xf0; + g = v & 0xf0; + b = (v << 4) & 0xf0; + ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); + s += 2; + d += BPP; + } while (-- width != 0); +} + +/* + * 16-bit colour + */ +static void glue(draw_line16_, DEPTH)(void *opaque, + uint8_t *d, const uint8_t *s, int width, int deststep) +{ +#if DEPTH == 16 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) + memcpy(d, s, width * 2); +#else + uint16_t v; + uint8_t r, g, b; + + 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 (-- width != 0); +#endif +} + +#undef DEPTH +#undef BPP +#undef PIXEL_TYPE diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c index 4048cc102d..be7e9c0d74 100644 --- a/hw/display/omap_lcdc.c +++ b/hw/display/omap_lcdc.c @@ -19,7 +19,7 @@ #include "hw/hw.h" #include "ui/console.h" #include "hw/arm/omap.h" -#include "hw/framebuffer.h" +#include "framebuffer.h" #include "ui/pixel_ops.h" struct omap_lcd_panel_s { @@ -70,13 +70,13 @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s) #define draw_line_func drawfn #define DEPTH 8 -#include "hw/omap_lcd_template.h" +#include "omap_lcd_template.h" #define DEPTH 15 -#include "hw/omap_lcd_template.h" +#include "omap_lcd_template.h" #define DEPTH 16 -#include "hw/omap_lcd_template.h" +#include "omap_lcd_template.h" #define DEPTH 32 -#include "hw/omap_lcd_template.h" +#include "omap_lcd_template.h" static draw_line_func draw_line_table2[33] = { [0 ... 32] = NULL, diff --git a/hw/display/pl110.c b/hw/display/pl110.c index fbef675f9c..295434eded 100644 --- a/hw/display/pl110.c +++ b/hw/display/pl110.c @@ -9,7 +9,7 @@ #include "hw/sysbus.h" #include "ui/console.h" -#include "hw/framebuffer.h" +#include "framebuffer.h" #include "ui/pixel_ops.h" #define PL110_CR_EN 0x001 @@ -111,15 +111,15 @@ static const unsigned char *idregs[] = { }; #define BITS 8 -#include "hw/pl110_template.h" +#include "pl110_template.h" #define BITS 15 -#include "hw/pl110_template.h" +#include "pl110_template.h" #define BITS 16 -#include "hw/pl110_template.h" +#include "pl110_template.h" #define BITS 24 -#include "hw/pl110_template.h" +#include "pl110_template.h" #define BITS 32 -#include "hw/pl110_template.h" +#include "pl110_template.h" static int pl110_enabled(pl110_state *s) { diff --git a/hw/display/pl110_template.h b/hw/display/pl110_template.h new file mode 100644 index 0000000000..e738e4a241 --- /dev/null +++ b/hw/display/pl110_template.h @@ -0,0 +1,395 @@ +/* + * Arm PrimeCell PL110 Color LCD Controller + * + * Copyright (c) 2005 CodeSourcery, LLC. + * Written by Paul Brook + * + * This code is licensed under the GNU LGPL + * + * Framebuffer format conversion routines. + */ + +#ifndef ORDER + +#if BITS == 8 +#define COPY_PIXEL(to, from) *(to++) = from +#elif BITS == 15 || BITS == 16 +#define COPY_PIXEL(to, from) *(uint16_t *)to = from; to += 2; +#elif BITS == 24 +#define COPY_PIXEL(to, from) \ + *(to++) = from; *(to++) = (from) >> 8; *(to++) = (from) >> 16 +#elif BITS == 32 +#define COPY_PIXEL(to, from) *(uint32_t *)to = from; to += 4; +#else +#error unknown bit depth +#endif + +#undef RGB +#define BORDER bgr +#define ORDER 0 +#include "pl110_template.h" +#define ORDER 1 +#include "pl110_template.h" +#define ORDER 2 +#include "pl110_template.h" +#undef BORDER +#define RGB +#define BORDER rgb +#define ORDER 0 +#include "pl110_template.h" +#define ORDER 1 +#include "pl110_template.h" +#define ORDER 2 +#include "pl110_template.h" +#undef BORDER + +static drawfn glue(pl110_draw_fn_,BITS)[48] = +{ + glue(pl110_draw_line1_lblp_bgr,BITS), + glue(pl110_draw_line2_lblp_bgr,BITS), + glue(pl110_draw_line4_lblp_bgr,BITS), + glue(pl110_draw_line8_lblp_bgr,BITS), + glue(pl110_draw_line16_555_lblp_bgr,BITS), + glue(pl110_draw_line32_lblp_bgr,BITS), + glue(pl110_draw_line16_lblp_bgr,BITS), + glue(pl110_draw_line12_lblp_bgr,BITS), + + glue(pl110_draw_line1_bbbp_bgr,BITS), + glue(pl110_draw_line2_bbbp_bgr,BITS), + glue(pl110_draw_line4_bbbp_bgr,BITS), + glue(pl110_draw_line8_bbbp_bgr,BITS), + glue(pl110_draw_line16_555_bbbp_bgr,BITS), + glue(pl110_draw_line32_bbbp_bgr,BITS), + glue(pl110_draw_line16_bbbp_bgr,BITS), + glue(pl110_draw_line12_bbbp_bgr,BITS), + + glue(pl110_draw_line1_lbbp_bgr,BITS), + glue(pl110_draw_line2_lbbp_bgr,BITS), + glue(pl110_draw_line4_lbbp_bgr,BITS), + glue(pl110_draw_line8_lbbp_bgr,BITS), + glue(pl110_draw_line16_555_lbbp_bgr,BITS), + glue(pl110_draw_line32_lbbp_bgr,BITS), + glue(pl110_draw_line16_lbbp_bgr,BITS), + glue(pl110_draw_line12_lbbp_bgr,BITS), + + glue(pl110_draw_line1_lblp_rgb,BITS), + glue(pl110_draw_line2_lblp_rgb,BITS), + glue(pl110_draw_line4_lblp_rgb,BITS), + glue(pl110_draw_line8_lblp_rgb,BITS), + glue(pl110_draw_line16_555_lblp_rgb,BITS), + glue(pl110_draw_line32_lblp_rgb,BITS), + glue(pl110_draw_line16_lblp_rgb,BITS), + glue(pl110_draw_line12_lblp_rgb,BITS), + + glue(pl110_draw_line1_bbbp_rgb,BITS), + glue(pl110_draw_line2_bbbp_rgb,BITS), + glue(pl110_draw_line4_bbbp_rgb,BITS), + glue(pl110_draw_line8_bbbp_rgb,BITS), + glue(pl110_draw_line16_555_bbbp_rgb,BITS), + glue(pl110_draw_line32_bbbp_rgb,BITS), + glue(pl110_draw_line16_bbbp_rgb,BITS), + glue(pl110_draw_line12_bbbp_rgb,BITS), + + glue(pl110_draw_line1_lbbp_rgb,BITS), + glue(pl110_draw_line2_lbbp_rgb,BITS), + glue(pl110_draw_line4_lbbp_rgb,BITS), + glue(pl110_draw_line8_lbbp_rgb,BITS), + glue(pl110_draw_line16_555_lbbp_rgb,BITS), + glue(pl110_draw_line32_lbbp_rgb,BITS), + glue(pl110_draw_line16_lbbp_rgb,BITS), + glue(pl110_draw_line12_lbbp_rgb,BITS), +}; + +#undef BITS +#undef COPY_PIXEL + +#else + +#if ORDER == 0 +#define NAME glue(glue(lblp_, BORDER), BITS) +#ifdef HOST_WORDS_BIGENDIAN +#define SWAP_WORDS 1 +#endif +#elif ORDER == 1 +#define NAME glue(glue(bbbp_, BORDER), BITS) +#ifndef HOST_WORDS_BIGENDIAN +#define SWAP_WORDS 1 +#endif +#else +#define SWAP_PIXELS 1 +#define NAME glue(glue(lbbp_, BORDER), BITS) +#ifdef HOST_WORDS_BIGENDIAN +#define SWAP_WORDS 1 +#endif +#endif + +#define FN_2(x, y) FN(x, y) FN(x+1, y) +#define FN_4(x, y) FN_2(x, y) FN_2(x+2, y) +#define FN_8(y) FN_4(0, y) FN_4(4, y) + +static void glue(pl110_draw_line1_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) +{ + uint32_t *palette = opaque; + uint32_t data; + while (width > 0) { + data = *(uint32_t *)src; +#ifdef SWAP_PIXELS +#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 7 - (x))) & 1]); +#else +#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x) + y)) & 1]); +#endif +#ifdef SWAP_WORDS + FN_8(24) + FN_8(16) + FN_8(8) + FN_8(0) +#else + FN_8(0) + FN_8(8) + FN_8(16) + FN_8(24) +#endif +#undef FN + width -= 32; + src += 4; + } +} + +static void glue(pl110_draw_line2_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) +{ + uint32_t *palette = opaque; + uint32_t data; + while (width > 0) { + data = *(uint32_t *)src; +#ifdef SWAP_PIXELS +#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 6 - (x)*2)) & 3]); +#else +#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x)*2 + y)) & 3]); +#endif +#ifdef SWAP_WORDS + FN_4(0, 24) + FN_4(0, 16) + FN_4(0, 8) + FN_4(0, 0) +#else + FN_4(0, 0) + FN_4(0, 8) + FN_4(0, 16) + FN_4(0, 24) +#endif +#undef FN + width -= 16; + src += 4; + } +} + +static void glue(pl110_draw_line4_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) +{ + uint32_t *palette = opaque; + uint32_t data; + while (width > 0) { + data = *(uint32_t *)src; +#ifdef SWAP_PIXELS +#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 4 - (x)*4)) & 0xf]); +#else +#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x)*4 + y)) & 0xf]); +#endif +#ifdef SWAP_WORDS + FN_2(0, 24) + FN_2(0, 16) + FN_2(0, 8) + FN_2(0, 0) +#else + FN_2(0, 0) + FN_2(0, 8) + FN_2(0, 16) + FN_2(0, 24) +#endif +#undef FN + width -= 8; + src += 4; + } +} + +static void glue(pl110_draw_line8_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) +{ + uint32_t *palette = opaque; + uint32_t data; + while (width > 0) { + data = *(uint32_t *)src; +#define FN(x) COPY_PIXEL(d, palette[(data >> (x)) & 0xff]); +#ifdef SWAP_WORDS + FN(24) + FN(16) + FN(8) + FN(0) +#else + FN(0) + FN(8) + FN(16) + FN(24) +#endif +#undef FN + width -= 4; + src += 4; + } +} + +static void glue(pl110_draw_line16_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) +{ + uint32_t data; + unsigned int r, g, b; + while (width > 0) { + data = *(uint32_t *)src; +#ifdef SWAP_WORDS + data = bswap32(data); +#endif +#ifdef RGB +#define LSB r +#define MSB b +#else +#define LSB b +#define MSB r +#endif +#if 0 + LSB = data & 0x1f; + data >>= 5; + g = data & 0x3f; + data >>= 6; + MSB = data & 0x1f; + data >>= 5; +#else + LSB = (data & 0x1f) << 3; + data >>= 5; + g = (data & 0x3f) << 2; + data >>= 6; + MSB = (data & 0x1f) << 3; + data >>= 5; +#endif + COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b)); + LSB = (data & 0x1f) << 3; + data >>= 5; + g = (data & 0x3f) << 2; + data >>= 6; + MSB = (data & 0x1f) << 3; + data >>= 5; + COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b)); +#undef MSB +#undef LSB + width -= 2; + src += 4; + } +} + +static void glue(pl110_draw_line32_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) +{ + uint32_t data; + unsigned int r, g, b; + while (width > 0) { + data = *(uint32_t *)src; +#ifdef RGB +#define LSB r +#define MSB b +#else +#define LSB b +#define MSB r +#endif +#ifndef SWAP_WORDS + LSB = data & 0xff; + g = (data >> 8) & 0xff; + MSB = (data >> 16) & 0xff; +#else + LSB = (data >> 24) & 0xff; + g = (data >> 16) & 0xff; + MSB = (data >> 8) & 0xff; +#endif + COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b)); +#undef MSB +#undef LSB + width--; + src += 4; + } +} + +static void glue(pl110_draw_line16_555_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) +{ + /* RGB 555 plus an intensity bit (which we ignore) */ + uint32_t data; + unsigned int r, g, b; + while (width > 0) { + data = *(uint32_t *)src; +#ifdef SWAP_WORDS + data = bswap32(data); +#endif +#ifdef RGB +#define LSB r +#define MSB b +#else +#define LSB b +#define MSB r +#endif + LSB = (data & 0x1f) << 3; + data >>= 5; + g = (data & 0x1f) << 3; + data >>= 5; + MSB = (data & 0x1f) << 3; + data >>= 5; + COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b)); + LSB = (data & 0x1f) << 3; + data >>= 5; + g = (data & 0x1f) << 3; + data >>= 5; + MSB = (data & 0x1f) << 3; + data >>= 6; + COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b)); +#undef MSB +#undef LSB + width -= 2; + src += 4; + } +} + +static void glue(pl110_draw_line12_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) +{ + /* RGB 444 with 4 bits of zeroes at the top of each halfword */ + uint32_t data; + unsigned int r, g, b; + while (width > 0) { + data = *(uint32_t *)src; +#ifdef SWAP_WORDS + data = bswap32(data); +#endif +#ifdef RGB +#define LSB r +#define MSB b +#else +#define LSB b +#define MSB r +#endif + LSB = (data & 0xf) << 4; + data >>= 4; + g = (data & 0xf) << 4; + data >>= 4; + MSB = (data & 0xf) << 4; + data >>= 8; + COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b)); + LSB = (data & 0xf) << 4; + data >>= 4; + g = (data & 0xf) << 4; + data >>= 4; + MSB = (data & 0xf) << 4; + data >>= 8; + COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b)); +#undef MSB +#undef LSB + width -= 2; + src += 4; + } +} + +#undef SWAP_PIXELS +#undef NAME +#undef SWAP_WORDS +#undef ORDER + +#endif diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c index ee59bc2de3..c9bd42e023 100644 --- a/hw/display/pxa2xx_lcd.c +++ b/hw/display/pxa2xx_lcd.c @@ -16,7 +16,7 @@ #include "ui/pixel_ops.h" /* FIXME: For graphic_rotate. Should probably be done in common code. */ #include "sysemu/sysemu.h" -#include "hw/framebuffer.h" +#include "framebuffer.h" struct DMAChannel { uint32_t branch; @@ -981,15 +981,15 @@ static const VMStateDescription vmstate_pxa2xx_lcdc = { }; #define BITS 8 -#include "hw/pxa2xx_template.h" +#include "pxa2xx_template.h" #define BITS 15 -#include "hw/pxa2xx_template.h" +#include "pxa2xx_template.h" #define BITS 16 -#include "hw/pxa2xx_template.h" +#include "pxa2xx_template.h" #define BITS 24 -#include "hw/pxa2xx_template.h" +#include "pxa2xx_template.h" #define BITS 32 -#include "hw/pxa2xx_template.h" +#include "pxa2xx_template.h" PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem, hwaddr base, qemu_irq irq) diff --git a/hw/display/pxa2xx_template.h b/hw/display/pxa2xx_template.h new file mode 100644 index 0000000000..1cbe36cb80 --- /dev/null +++ b/hw/display/pxa2xx_template.h @@ -0,0 +1,435 @@ +/* + * Intel XScale PXA255/270 LCDC emulation. + * + * Copyright (c) 2006 Openedhand Ltd. + * Written by Andrzej Zaborowski <balrog@zabor.org> + * + * This code is licensed under the GPLv2. + * + * Framebuffer format conversion routines. + */ + +# define SKIP_PIXEL(to) to += deststep +#if BITS == 8 +# define COPY_PIXEL(to, from) *to = from; SKIP_PIXEL(to) +#elif BITS == 15 || BITS == 16 +# define COPY_PIXEL(to, from) *(uint16_t *) to = from; SKIP_PIXEL(to) +#elif BITS == 24 +# define COPY_PIXEL(to, from) \ + *(uint16_t *) to = from; *(to + 2) = (from) >> 16; SKIP_PIXEL(to) +#elif BITS == 32 +# define COPY_PIXEL(to, from) *(uint32_t *) to = from; SKIP_PIXEL(to) +#else +# error unknown bit depth +#endif + +#ifdef HOST_WORDS_BIGENDIAN +# define SWAP_WORDS 1 +#endif + +#define FN_2(x) FN(x + 1) FN(x) +#define FN_4(x) FN_2(x + 2) FN_2(x) + +static void glue(pxa2xx_draw_line2_, BITS)(void *opaque, + uint8_t *dest, const uint8_t *src, int width, int deststep) +{ + uint32_t *palette = opaque; + uint32_t data; + while (width > 0) { + data = *(uint32_t *) src; +#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]); +#ifdef SWAP_WORDS + FN_4(12) + FN_4(8) + FN_4(4) + FN_4(0) +#else + FN_4(0) + FN_4(4) + FN_4(8) + FN_4(12) +#endif +#undef FN + width -= 16; + src += 4; + } +} + +static void glue(pxa2xx_draw_line4_, BITS)(void *opaque, + uint8_t *dest, const uint8_t *src, int width, int deststep) +{ + uint32_t *palette = opaque; + uint32_t data; + while (width > 0) { + data = *(uint32_t *) src; +#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]); +#ifdef SWAP_WORDS + FN_2(6) + FN_2(4) + FN_2(2) + FN_2(0) +#else + FN_2(0) + FN_2(2) + FN_2(4) + FN_2(6) +#endif +#undef FN + width -= 8; + src += 4; + } +} + +static void glue(pxa2xx_draw_line8_, BITS)(void *opaque, + uint8_t *dest, const uint8_t *src, int width, int deststep) +{ + uint32_t *palette = opaque; + uint32_t data; + while (width > 0) { + data = *(uint32_t *) src; +#define FN(x) COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]); +#ifdef SWAP_WORDS + FN(24) + FN(16) + FN(8) + FN(0) +#else + FN(0) + FN(8) + FN(16) + FN(24) +#endif +#undef FN + width -= 4; + src += 4; + } +} + +static void glue(pxa2xx_draw_line16_, BITS)(void *opaque, + uint8_t *dest, const uint8_t *src, int width, int deststep) +{ + uint32_t data; + unsigned int r, g, b; + while (width > 0) { + data = *(uint32_t *) src; +#ifdef SWAP_WORDS + data = bswap32(data); +#endif + b = (data & 0x1f) << 3; + data >>= 5; + g = (data & 0x3f) << 2; + data >>= 6; + r = (data & 0x1f) << 3; + data >>= 5; + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); + b = (data & 0x1f) << 3; + data >>= 5; + g = (data & 0x3f) << 2; + data >>= 6; + r = (data & 0x1f) << 3; + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); + width -= 2; + src += 4; + } +} + +static void glue(pxa2xx_draw_line16t_, BITS)(void *opaque, + uint8_t *dest, const uint8_t *src, int width, int deststep) +{ + uint32_t data; + unsigned int r, g, b; + while (width > 0) { + data = *(uint32_t *) src; +#ifdef SWAP_WORDS + data = bswap32(data); +#endif + b = (data & 0x1f) << 3; + data >>= 5; + g = (data & 0x1f) << 3; + data >>= 5; + r = (data & 0x1f) << 3; + data >>= 5; + if (data & 1) + SKIP_PIXEL(dest); + else + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); + data >>= 1; + b = (data & 0x1f) << 3; + data >>= 5; + g = (data & 0x1f) << 3; + data >>= 5; + r = (data & 0x1f) << 3; + data >>= 5; + if (data & 1) + SKIP_PIXEL(dest); + else + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); + width -= 2; + src += 4; + } +} + +static void glue(pxa2xx_draw_line18_, BITS)(void *opaque, + uint8_t *dest, const uint8_t *src, int width, int deststep) +{ + uint32_t data; + unsigned int r, g, b; + while (width > 0) { + data = *(uint32_t *) src; +#ifdef SWAP_WORDS + data = bswap32(data); +#endif + b = (data & 0x3f) << 2; + data >>= 6; + g = (data & 0x3f) << 2; + data >>= 6; + r = (data & 0x3f) << 2; + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); + width -= 1; + src += 4; + } +} + +/* The wicked packed format */ +static void glue(pxa2xx_draw_line18p_, BITS)(void *opaque, + uint8_t *dest, const uint8_t *src, int width, int deststep) +{ + uint32_t data[3]; + unsigned int r, g, b; + while (width > 0) { + data[0] = *(uint32_t *) src; + src += 4; + data[1] = *(uint32_t *) src; + src += 4; + data[2] = *(uint32_t *) src; + src += 4; +#ifdef SWAP_WORDS + data[0] = bswap32(data[0]); + data[1] = bswap32(data[1]); + data[2] = bswap32(data[2]); +#endif + b = (data[0] & 0x3f) << 2; + data[0] >>= 6; + g = (data[0] & 0x3f) << 2; + data[0] >>= 6; + r = (data[0] & 0x3f) << 2; + data[0] >>= 12; + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); + b = (data[0] & 0x3f) << 2; + data[0] >>= 6; + g = ((data[1] & 0xf) << 4) | (data[0] << 2); + data[1] >>= 4; + r = (data[1] & 0x3f) << 2; + data[1] >>= 12; + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); + b = (data[1] & 0x3f) << 2; + data[1] >>= 6; + g = (data[1] & 0x3f) << 2; + data[1] >>= 6; + r = ((data[2] & 0x3) << 6) | (data[1] << 2); + data[2] >>= 8; + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); + b = (data[2] & 0x3f) << 2; + data[2] >>= 6; + g = (data[2] & 0x3f) << 2; + data[2] >>= 6; + r = data[2] << 2; + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); + width -= 4; + } +} + +static void glue(pxa2xx_draw_line19_, BITS)(void *opaque, + uint8_t *dest, const uint8_t *src, int width, int deststep) +{ + uint32_t data; + unsigned int r, g, b; + while (width > 0) { + data = *(uint32_t *) src; +#ifdef SWAP_WORDS + data = bswap32(data); +#endif + b = (data & 0x3f) << 2; + data >>= 6; + g = (data & 0x3f) << 2; + data >>= 6; + r = (data & 0x3f) << 2; + data >>= 6; + if (data & 1) + SKIP_PIXEL(dest); + else + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); + width -= 1; + src += 4; + } +} + +/* The wicked packed format */ +static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque, + uint8_t *dest, const uint8_t *src, int width, int deststep) +{ + uint32_t data[3]; + unsigned int r, g, b; + while (width > 0) { + data[0] = *(uint32_t *) src; + src += 4; + data[1] = *(uint32_t *) src; + src += 4; + data[2] = *(uint32_t *) src; + src += 4; +# ifdef SWAP_WORDS + data[0] = bswap32(data[0]); + data[1] = bswap32(data[1]); + data[2] = bswap32(data[2]); +# endif + b = (data[0] & 0x3f) << 2; + data[0] >>= 6; + g = (data[0] & 0x3f) << 2; + data[0] >>= 6; + r = (data[0] & 0x3f) << 2; + data[0] >>= 6; + if (data[0] & 1) + SKIP_PIXEL(dest); + else + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); + data[0] >>= 6; + b = (data[0] & 0x3f) << 2; + data[0] >>= 6; + g = ((data[1] & 0xf) << 4) | (data[0] << 2); + data[1] >>= 4; + r = (data[1] & 0x3f) << 2; + data[1] >>= 6; + if (data[1] & 1) + SKIP_PIXEL(dest); + else + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); + data[1] >>= 6; + b = (data[1] & 0x3f) << 2; + data[1] >>= 6; + g = (data[1] & 0x3f) << 2; + data[1] >>= 6; + r = ((data[2] & 0x3) << 6) | (data[1] << 2); + data[2] >>= 2; + if (data[2] & 1) + SKIP_PIXEL(dest); + else + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); + data[2] >>= 6; + b = (data[2] & 0x3f) << 2; + data[2] >>= 6; + g = (data[2] & 0x3f) << 2; + data[2] >>= 6; + r = data[2] << 2; + data[2] >>= 6; + if (data[2] & 1) + SKIP_PIXEL(dest); + else + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); + width -= 4; + } +} + +static void glue(pxa2xx_draw_line24_, BITS)(void *opaque, + uint8_t *dest, const uint8_t *src, int width, int deststep) +{ + uint32_t data; + unsigned int r, g, b; + while (width > 0) { + data = *(uint32_t *) src; +#ifdef SWAP_WORDS + data = bswap32(data); +#endif + b = data & 0xff; + data >>= 8; + g = data & 0xff; + data >>= 8; + r = data & 0xff; + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); + width -= 1; + src += 4; + } +} + +static void glue(pxa2xx_draw_line24t_, BITS)(void *opaque, + uint8_t *dest, const uint8_t *src, int width, int deststep) +{ + uint32_t data; + unsigned int r, g, b; + while (width > 0) { + data = *(uint32_t *) src; +#ifdef SWAP_WORDS + data = bswap32(data); +#endif + b = (data & 0x7f) << 1; + data >>= 7; + g = data & 0xff; + data >>= 8; + r = data & 0xff; + data >>= 8; + if (data & 1) + SKIP_PIXEL(dest); + else + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); + width -= 1; + src += 4; + } +} + +static void glue(pxa2xx_draw_line25_, BITS)(void *opaque, + uint8_t *dest, const uint8_t *src, int width, int deststep) +{ + uint32_t data; + unsigned int r, g, b; + while (width > 0) { + data = *(uint32_t *) src; +#ifdef SWAP_WORDS + data = bswap32(data); +#endif + b = data & 0xff; + data >>= 8; + g = data & 0xff; + data >>= 8; + r = data & 0xff; + data >>= 8; + if (data & 1) + SKIP_PIXEL(dest); + else + COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); + width -= 1; + src += 4; + } +} + +/* Overlay planes disabled, no transparency */ +static drawfn glue(pxa2xx_draw_fn_, BITS)[16] = +{ + [0 ... 0xf] = NULL, + [pxa_lcdc_2bpp] = glue(pxa2xx_draw_line2_, BITS), + [pxa_lcdc_4bpp] = glue(pxa2xx_draw_line4_, BITS), + [pxa_lcdc_8bpp] = glue(pxa2xx_draw_line8_, BITS), + [pxa_lcdc_16bpp] = glue(pxa2xx_draw_line16_, BITS), + [pxa_lcdc_18bpp] = glue(pxa2xx_draw_line18_, BITS), + [pxa_lcdc_18pbpp] = glue(pxa2xx_draw_line18p_, BITS), + [pxa_lcdc_24bpp] = glue(pxa2xx_draw_line24_, BITS), +}; + +/* Overlay planes enabled, transparency used */ +static drawfn glue(glue(pxa2xx_draw_fn_, BITS), t)[16] = +{ + [0 ... 0xf] = NULL, + [pxa_lcdc_4bpp] = glue(pxa2xx_draw_line4_, BITS), + [pxa_lcdc_8bpp] = glue(pxa2xx_draw_line8_, BITS), + [pxa_lcdc_16bpp] = glue(pxa2xx_draw_line16t_, BITS), + [pxa_lcdc_19bpp] = glue(pxa2xx_draw_line19_, BITS), + [pxa_lcdc_19pbpp] = glue(pxa2xx_draw_line19p_, BITS), + [pxa_lcdc_24bpp] = glue(pxa2xx_draw_line24t_, BITS), + [pxa_lcdc_25bpp] = glue(pxa2xx_draw_line25_, BITS), +}; + +#undef BITS +#undef COPY_PIXEL +#undef SKIP_PIXEL + +#ifdef SWAP_WORDS +# undef SWAP_WORDS +#endif diff --git a/hw/display/qxl-logger.c b/hw/display/qxl-logger.c index 84f9aa1eda..3cd85d9b97 100644 --- a/hw/display/qxl-logger.c +++ b/hw/display/qxl-logger.c @@ -20,7 +20,7 @@ */ #include "qemu/timer.h" -#include "hw/qxl.h" +#include "qxl.h" static const char *qxl_type[] = { [ QXL_CMD_NOP ] = "nop", diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c index 8cd9be434d..f511a622c6 100644 --- a/hw/display/qxl-render.c +++ b/hw/display/qxl-render.c @@ -19,7 +19,7 @@ * along with this program; if not, see <http://www.gnu.org/licenses/>. */ -#include "hw/qxl.h" +#include "qxl.h" static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect) { diff --git a/hw/display/qxl.c b/hw/display/qxl.c index b66b41442a..930b7cf2ad 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -27,7 +27,7 @@ #include "sysemu/sysemu.h" #include "trace.h" -#include "hw/qxl.h" +#include "qxl.h" /* * NOTE: SPICE_RING_PROD_ITEM accesses memory on the pci bar and as diff --git a/hw/display/qxl.h b/hw/display/qxl.h new file mode 100644 index 0000000000..8e9b0c299e --- /dev/null +++ b/hw/display/qxl.h @@ -0,0 +1,165 @@ +#ifndef HW_QXL_H +#define HW_QXL_H 1 + +#include "qemu-common.h" + +#include "ui/console.h" +#include "hw/hw.h" +#include "hw/pci/pci.h" +#include "vga_int.h" +#include "qemu/thread.h" + +#include "ui/qemu-spice.h" +#include "ui/spice-display.h" + +enum qxl_mode { + QXL_MODE_UNDEFINED, + QXL_MODE_VGA, + QXL_MODE_COMPAT, /* spice 0.4.x */ + QXL_MODE_NATIVE, +}; + +#ifndef QXL_VRAM64_RANGE_INDEX +#define QXL_VRAM64_RANGE_INDEX 4 +#endif + +#define QXL_UNDEFINED_IO UINT32_MAX + +#define QXL_NUM_DIRTY_RECTS 64 + +typedef struct PCIQXLDevice { + PCIDevice pci; + SimpleSpiceDisplay ssd; + int id; + uint32_t debug; + uint32_t guestdebug; + uint32_t cmdlog; + + uint32_t guest_bug; + + enum qxl_mode mode; + uint32_t cmdflags; + int generation; + uint32_t revision; + + int32_t num_memslots; + + uint32_t current_async; + QemuMutex async_lock; + + struct guest_slots { + QXLMemSlot slot; + void *ptr; + uint64_t size; + uint64_t delta; + uint32_t active; + } guest_slots[NUM_MEMSLOTS]; + + struct guest_primary { + QXLSurfaceCreate surface; + uint32_t commands; + uint32_t resized; + int32_t qxl_stride; + uint32_t abs_stride; + uint32_t bits_pp; + uint32_t bytes_pp; + uint8_t *data; + } guest_primary; + + struct surfaces { + QXLPHYSICAL *cmds; + uint32_t count; + uint32_t max; + } guest_surfaces; + QXLPHYSICAL guest_cursor; + + QXLPHYSICAL guest_monitors_config; + + QemuMutex track_lock; + + /* thread signaling */ + QemuThread main; + int pipe[2]; + + /* ram pci bar */ + QXLRam *ram; + VGACommonState vga; + uint32_t num_free_res; + QXLReleaseInfo *last_release; + uint32_t last_release_offset; + uint32_t oom_running; + uint32_t vgamem_size; + + /* rom pci bar */ + QXLRom shadow_rom; + QXLRom *rom; + QXLModes *modes; + uint32_t rom_size; + MemoryRegion rom_bar; + + /* vram pci bar */ + uint32_t vram_size; + MemoryRegion vram_bar; + uint32_t vram32_size; + MemoryRegion vram32_bar; + + /* io bar */ + MemoryRegion io_bar; + + /* user-friendly properties (in megabytes) */ + uint32_t ram_size_mb; + uint32_t vram_size_mb; + uint32_t vram32_size_mb; + uint32_t vgamem_size_mb; + + /* qxl_render_update state */ + int render_update_cookie_num; + int num_dirty_rects; + QXLRect dirty[QXL_NUM_DIRTY_RECTS]; + QEMUBH *update_area_bh; +} PCIQXLDevice; + +#define PANIC_ON(x) if ((x)) { \ + printf("%s: PANIC %s failed\n", __FUNCTION__, #x); \ + abort(); \ +} + +#define dprint(_qxl, _level, _fmt, ...) \ + do { \ + if (_qxl->debug >= _level) { \ + fprintf(stderr, "qxl-%d: ", _qxl->id); \ + fprintf(stderr, _fmt, ## __VA_ARGS__); \ + } \ + } while (0) + +#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V12 + +/* qxl.c */ +void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id); +void qxl_set_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) + GCC_FMT_ATTR(2, 3); + +void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, + struct QXLRect *area, struct QXLRect *dirty_rects, + uint32_t num_dirty_rects, + uint32_t clear_dirty_region, + qxl_async_io async, QXLCookie *cookie); +void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext, + uint32_t count); +void qxl_spice_oom(PCIQXLDevice *qxl); +void qxl_spice_reset_memslots(PCIQXLDevice *qxl); +void qxl_spice_reset_image_cache(PCIQXLDevice *qxl); +void qxl_spice_reset_cursor(PCIQXLDevice *qxl); + +/* qxl-logger.c */ +int qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id); +int qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext); + +/* qxl-render.c */ +void qxl_render_resize(PCIQXLDevice *qxl); +void qxl_render_update(PCIQXLDevice *qxl); +int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext); +void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie); +void qxl_render_update_area_bh(void *opaque); + +#endif diff --git a/hw/display/sm501.c b/hw/display/sm501.c index d9fcead719..6b660ac1c0 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -1171,28 +1171,28 @@ typedef void draw_hwc_line_func(SM501State * s, int crt, uint8_t * palette, int c_y, uint8_t *d, int width); #define DEPTH 8 -#include "hw/sm501_template.h" +#include "sm501_template.h" #define DEPTH 15 -#include "hw/sm501_template.h" +#include "sm501_template.h" #define BGR_FORMAT #define DEPTH 15 -#include "hw/sm501_template.h" +#include "sm501_template.h" #define DEPTH 16 -#include "hw/sm501_template.h" +#include "sm501_template.h" #define BGR_FORMAT #define DEPTH 16 -#include "hw/sm501_template.h" +#include "sm501_template.h" #define DEPTH 32 -#include "hw/sm501_template.h" +#include "sm501_template.h" #define BGR_FORMAT #define DEPTH 32 -#include "hw/sm501_template.h" +#include "sm501_template.h" static draw_line_func * draw_line8_funcs[] = { draw_line8_8, diff --git a/hw/display/sm501_template.h b/hw/display/sm501_template.h new file mode 100644 index 0000000000..2d4a3d8b48 --- /dev/null +++ b/hw/display/sm501_template.h @@ -0,0 +1,145 @@ +/* + * Pixel drawing function templates for QEMU SM501 Device + * + * Copyright (c) 2008 Shin-ichiro KAWASAKI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if DEPTH == 8 +#define BPP 1 +#define PIXEL_TYPE uint8_t +#elif DEPTH == 15 || DEPTH == 16 +#define BPP 2 +#define PIXEL_TYPE uint16_t +#elif DEPTH == 32 +#define BPP 4 +#define PIXEL_TYPE uint32_t +#else +#error unsupport depth +#endif + +#ifdef BGR_FORMAT +#define PIXEL_NAME glue(DEPTH, bgr) +#else +#define PIXEL_NAME DEPTH +#endif /* BGR_FORMAT */ + + +static void glue(draw_line8_, PIXEL_NAME)( + uint8_t *d, const uint8_t *s, int width, const uint32_t *pal) +{ + uint8_t v, r, g, b; + do { + v = ldub_raw(s); + r = (pal[v] >> 16) & 0xff; + g = (pal[v] >> 8) & 0xff; + b = (pal[v] >> 0) & 0xff; + ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b); + s ++; + d += BPP; + } while (-- width != 0); +} + +static void glue(draw_line16_, PIXEL_NAME)( + uint8_t *d, const uint8_t *s, int width, const uint32_t *pal) +{ + uint16_t rgb565; + uint8_t r, g, b; + + do { + rgb565 = lduw_raw(s); + r = ((rgb565 >> 11) & 0x1f) << 3; + g = ((rgb565 >> 5) & 0x3f) << 2; + b = ((rgb565 >> 0) & 0x1f) << 3; + ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b); + s += 2; + d += BPP; + } while (-- width != 0); +} + +static void glue(draw_line32_, PIXEL_NAME)( + uint8_t *d, const uint8_t *s, int width, const uint32_t *pal) +{ + uint8_t r, g, b; + + do { + ldub_raw(s); +#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 (-- width != 0); +} + +/** + * Draw hardware cursor image on the given line. + */ +static void glue(draw_hwc_line_, PIXEL_NAME)(SM501State * s, int crt, + uint8_t * palette, int c_y, uint8_t *d, int width) +{ + int x, i; + uint8_t bitset = 0; + + /* get hardware cursor pattern */ + uint32_t cursor_addr = get_hwc_address(s, crt); + assert(0 <= c_y && c_y < SM501_HWC_HEIGHT); + cursor_addr += 64 * c_y / 4; /* 4 pixels per byte */ + cursor_addr += s->base; + + /* get cursor position */ + x = get_hwc_x(s, crt); + d += x * BPP; + + for (i = 0; i < SM501_HWC_WIDTH && x + i < width; i++) { + uint8_t v; + + /* get pixel value */ + if (i % 4 == 0) { + bitset = ldub_phys(cursor_addr); + cursor_addr++; + } + v = bitset & 3; + bitset >>= 2; + + /* write pixel */ + if (v) { + v--; + uint8_t r = palette[v * 3 + 0]; + uint8_t g = palette[v * 3 + 1]; + uint8_t b = palette[v * 3 + 2]; + ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b); + } + d += BPP; + } +} + +#undef DEPTH +#undef BPP +#undef PIXEL_TYPE +#undef PIXEL_NAME +#undef BGR_FORMAT diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c index 2d5fa89e9b..e252ce945f 100644 --- a/hw/display/tc6393xb.c +++ b/hw/display/tc6393xb.c @@ -421,15 +421,15 @@ static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value) } #define BITS 8 -#include "hw/tc6393xb_template.h" +#include "tc6393xb_template.h" #define BITS 15 -#include "hw/tc6393xb_template.h" +#include "tc6393xb_template.h" #define BITS 16 -#include "hw/tc6393xb_template.h" +#include "tc6393xb_template.h" #define BITS 24 -#include "hw/tc6393xb_template.h" +#include "tc6393xb_template.h" #define BITS 32 -#include "hw/tc6393xb_template.h" +#include "tc6393xb_template.h" static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update) { diff --git a/hw/display/tc6393xb_template.h b/hw/display/tc6393xb_template.h new file mode 100644 index 0000000000..154aafd400 --- /dev/null +++ b/hw/display/tc6393xb_template.h @@ -0,0 +1,68 @@ +/* + * Toshiba TC6393XB I/O Controller. + * Found in Sharp Zaurus SL-6000 (tosa) or some + * Toshiba e-Series PDAs. + * + * FB support code. Based on G364 fb emulator + * + * Copyright (c) 2007 Hervé Poussineau + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#if BITS == 8 +# define SET_PIXEL(addr, color) *(uint8_t*)addr = color; +#elif BITS == 15 || BITS == 16 +# define SET_PIXEL(addr, color) *(uint16_t*)addr = color; +#elif BITS == 24 +# define SET_PIXEL(addr, color) \ + addr[0] = color; addr[1] = (color) >> 8; addr[2] = (color) >> 16; +#elif BITS == 32 +# define SET_PIXEL(addr, color) *(uint32_t*)addr = color; +#else +# error unknown bit depth +#endif + + +static void glue(tc6393xb_draw_graphic, BITS)(TC6393xbState *s) +{ + DisplaySurface *surface = qemu_console_surface(s->con); + int i; + uint16_t *data_buffer; + uint8_t *data_display; + + data_buffer = s->vram_ptr; + data_display = surface_data(surface); + for(i = 0; i < s->scr_height; i++) { +#if (BITS == 16) + memcpy(data_display, data_buffer, s->scr_width * 2); + data_buffer += s->scr_width; + data_display += surface_stride(surface); +#else + int j; + for (j = 0; j < s->scr_width; j++, data_display += BITS / 8, data_buffer++) { + uint16_t color = *data_buffer; + uint32_t dest_color = glue(rgb_to_pixel, BITS)( + ((color & 0xf800) * 0x108) >> 11, + ((color & 0x7e0) * 0x41) >> 9, + ((color & 0x1f) * 0x21) >> 2 + ); + SET_PIXEL(data_display, dest_color); + } +#endif + } +} + +#undef BITS +#undef SET_PIXEL diff --git a/hw/display/vga-isa-mm.c b/hw/display/vga-isa-mm.c index 3b08720cf4..1c50070216 100644 --- a/hw/display/vga-isa-mm.c +++ b/hw/display/vga-isa-mm.c @@ -24,7 +24,7 @@ #include "hw/hw.h" #include "ui/console.h" #include "hw/i386/pc.h" -#include "hw/vga_int.h" +#include "vga_int.h" #include "ui/pixel_ops.h" #include "qemu/timer.h" diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c index 89d7fa6c3c..90959ebc2c 100644 --- a/hw/display/vga-isa.c +++ b/hw/display/vga-isa.c @@ -26,7 +26,7 @@ #include "hw/hw.h" #include "ui/console.h" #include "hw/i386/pc.h" -#include "hw/vga_int.h" +#include "vga_int.h" #include "ui/pixel_ops.h" #include "qemu/timer.h" #include "hw/loader.h" diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c index 05fa9bcb64..a9c69b6ac7 100644 --- a/hw/display/vga-pci.c +++ b/hw/display/vga-pci.c @@ -26,7 +26,7 @@ #include "hw/hw.h" #include "ui/console.h" #include "hw/pci/pci.h" -#include "hw/vga_int.h" +#include "vga_int.h" #include "ui/pixel_ops.h" #include "qemu/timer.h" #include "hw/loader.h" diff --git a/hw/display/vga.c b/hw/display/vga.c index dc31fd574c..c1b67bbbf8 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -22,11 +22,11 @@ * THE SOFTWARE. */ #include "hw/hw.h" -#include "hw/vga.h" +#include "vga.h" #include "ui/console.h" #include "hw/i386/pc.h" #include "hw/pci/pci.h" -#include "hw/vga_int.h" +#include "vga_int.h" #include "ui/pixel_ops.h" #include "qemu/timer.h" #include "hw/xen/xen.h" @@ -986,28 +986,28 @@ typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d, const uint8_t *s, int width); #define DEPTH 8 -#include "hw/vga_template.h" +#include "vga_template.h" #define DEPTH 15 -#include "hw/vga_template.h" +#include "vga_template.h" #define BGR_FORMAT #define DEPTH 15 -#include "hw/vga_template.h" +#include "vga_template.h" #define DEPTH 16 -#include "hw/vga_template.h" +#include "vga_template.h" #define BGR_FORMAT #define DEPTH 16 -#include "hw/vga_template.h" +#include "vga_template.h" #define DEPTH 32 -#include "hw/vga_template.h" +#include "vga_template.h" #define BGR_FORMAT #define DEPTH 32 -#include "hw/vga_template.h" +#include "vga_template.h" static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b) { diff --git a/hw/display/vga.h b/hw/display/vga.h new file mode 100644 index 0000000000..d917046da6 --- /dev/null +++ b/hw/display/vga.h @@ -0,0 +1,159 @@ +/* + * linux/include/video/vga.h -- standard VGA chipset interaction + * + * Copyright 1999 Jeff Garzik <jgarzik@pobox.com> + * + * Copyright history from vga16fb.c: + * Copyright 1999 Ben Pfaff and Petr Vandrovec + * Based on VGA info at http://www.osdever.net/FreeVGA/home.htm + * Based on VESA framebuffer (c) 1998 Gerd Knorr + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file COPYING in the main directory of this + * archive for more details. + * + */ + +#ifndef __linux_video_vga_h__ +#define __linux_video_vga_h__ + +/* Some of the code below is taken from SVGAlib. The original, + unmodified copyright notice for that code is below. */ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright 1993 Harm Hanemaayer */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + +/* VGA data register ports */ +#define VGA_CRT_DC 0x3D5 /* CRT Controller Data Register - color emulation */ +#define VGA_CRT_DM 0x3B5 /* CRT Controller Data Register - mono emulation */ +#define VGA_ATT_R 0x3C1 /* Attribute Controller Data Read Register */ +#define VGA_ATT_W 0x3C0 /* Attribute Controller Data Write Register */ +#define VGA_GFX_D 0x3CF /* Graphics Controller Data Register */ +#define VGA_SEQ_D 0x3C5 /* Sequencer Data Register */ +#define VGA_MIS_R 0x3CC /* Misc Output Read Register */ +#define VGA_MIS_W 0x3C2 /* Misc Output Write Register */ +#define VGA_FTC_R 0x3CA /* Feature Control Read Register */ +#define VGA_IS1_RC 0x3DA /* Input Status Register 1 - color emulation */ +#define VGA_IS1_RM 0x3BA /* Input Status Register 1 - mono emulation */ +#define VGA_PEL_D 0x3C9 /* PEL Data Register */ +#define VGA_PEL_MSK 0x3C6 /* PEL mask register */ + +/* EGA-specific registers */ +#define EGA_GFX_E0 0x3CC /* Graphics enable processor 0 */ +#define EGA_GFX_E1 0x3CA /* Graphics enable processor 1 */ + +/* VGA index register ports */ +#define VGA_CRT_IC 0x3D4 /* CRT Controller Index - color emulation */ +#define VGA_CRT_IM 0x3B4 /* CRT Controller Index - mono emulation */ +#define VGA_ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */ +#define VGA_GFX_I 0x3CE /* Graphics Controller Index */ +#define VGA_SEQ_I 0x3C4 /* Sequencer Index */ +#define VGA_PEL_IW 0x3C8 /* PEL Write Index */ +#define VGA_PEL_IR 0x3C7 /* PEL Read Index */ + +/* standard VGA indexes max counts */ +#define VGA_CRT_C 0x19 /* Number of CRT Controller Registers */ +#define VGA_ATT_C 0x15 /* Number of Attribute Controller Registers */ +#define VGA_GFX_C 0x09 /* Number of Graphics Controller Registers */ +#define VGA_SEQ_C 0x05 /* Number of Sequencer Registers */ +#define VGA_MIS_C 0x01 /* Number of Misc Output Register */ + +/* VGA misc register bit masks */ +#define VGA_MIS_COLOR 0x01 +#define VGA_MIS_ENB_MEM_ACCESS 0x02 +#define VGA_MIS_DCLK_28322_720 0x04 +#define VGA_MIS_ENB_PLL_LOAD (0x04 | 0x08) +#define VGA_MIS_SEL_HIGH_PAGE 0x20 + +/* VGA CRT controller register indices */ +#define VGA_CRTC_H_TOTAL 0 +#define VGA_CRTC_H_DISP 1 +#define VGA_CRTC_H_BLANK_START 2 +#define VGA_CRTC_H_BLANK_END 3 +#define VGA_CRTC_H_SYNC_START 4 +#define VGA_CRTC_H_SYNC_END 5 +#define VGA_CRTC_V_TOTAL 6 +#define VGA_CRTC_OVERFLOW 7 +#define VGA_CRTC_PRESET_ROW 8 +#define VGA_CRTC_MAX_SCAN 9 +#define VGA_CRTC_CURSOR_START 0x0A +#define VGA_CRTC_CURSOR_END 0x0B +#define VGA_CRTC_START_HI 0x0C +#define VGA_CRTC_START_LO 0x0D +#define VGA_CRTC_CURSOR_HI 0x0E +#define VGA_CRTC_CURSOR_LO 0x0F +#define VGA_CRTC_V_SYNC_START 0x10 +#define VGA_CRTC_V_SYNC_END 0x11 +#define VGA_CRTC_V_DISP_END 0x12 +#define VGA_CRTC_OFFSET 0x13 +#define VGA_CRTC_UNDERLINE 0x14 +#define VGA_CRTC_V_BLANK_START 0x15 +#define VGA_CRTC_V_BLANK_END 0x16 +#define VGA_CRTC_MODE 0x17 +#define VGA_CRTC_LINE_COMPARE 0x18 +#define VGA_CRTC_REGS VGA_CRT_C + +/* VGA CRT controller bit masks */ +#define VGA_CR11_LOCK_CR0_CR7 0x80 /* lock writes to CR0 - CR7 */ +#define VGA_CR17_H_V_SIGNALS_ENABLED 0x80 + +/* VGA attribute controller register indices */ +#define VGA_ATC_PALETTE0 0x00 +#define VGA_ATC_PALETTE1 0x01 +#define VGA_ATC_PALETTE2 0x02 +#define VGA_ATC_PALETTE3 0x03 +#define VGA_ATC_PALETTE4 0x04 +#define VGA_ATC_PALETTE5 0x05 +#define VGA_ATC_PALETTE6 0x06 +#define VGA_ATC_PALETTE7 0x07 +#define VGA_ATC_PALETTE8 0x08 +#define VGA_ATC_PALETTE9 0x09 +#define VGA_ATC_PALETTEA 0x0A +#define VGA_ATC_PALETTEB 0x0B +#define VGA_ATC_PALETTEC 0x0C +#define VGA_ATC_PALETTED 0x0D +#define VGA_ATC_PALETTEE 0x0E +#define VGA_ATC_PALETTEF 0x0F +#define VGA_ATC_MODE 0x10 +#define VGA_ATC_OVERSCAN 0x11 +#define VGA_ATC_PLANE_ENABLE 0x12 +#define VGA_ATC_PEL 0x13 +#define VGA_ATC_COLOR_PAGE 0x14 + +#define VGA_AR_ENABLE_DISPLAY 0x20 + +/* VGA sequencer register indices */ +#define VGA_SEQ_RESET 0x00 +#define VGA_SEQ_CLOCK_MODE 0x01 +#define VGA_SEQ_PLANE_WRITE 0x02 +#define VGA_SEQ_CHARACTER_MAP 0x03 +#define VGA_SEQ_MEMORY_MODE 0x04 + +/* VGA sequencer register bit masks */ +#define VGA_SR01_CHAR_CLK_8DOTS 0x01 /* bit 0: character clocks 8 dots wide are generated */ +#define VGA_SR01_SCREEN_OFF 0x20 /* bit 5: Screen is off */ +#define VGA_SR02_ALL_PLANES 0x0F /* bits 3-0: enable access to all planes */ +#define VGA_SR04_EXT_MEM 0x02 /* bit 1: allows complete mem access to 256K */ +#define VGA_SR04_SEQ_MODE 0x04 /* bit 2: directs system to use a sequential addressing mode */ +#define VGA_SR04_CHN_4M 0x08 /* bit 3: selects modulo 4 addressing for CPU access to display memory */ + +/* VGA graphics controller register indices */ +#define VGA_GFX_SR_VALUE 0x00 +#define VGA_GFX_SR_ENABLE 0x01 +#define VGA_GFX_COMPARE_VALUE 0x02 +#define VGA_GFX_DATA_ROTATE 0x03 +#define VGA_GFX_PLANE_READ 0x04 +#define VGA_GFX_MODE 0x05 +#define VGA_GFX_MISC 0x06 +#define VGA_GFX_COMPARE_MASK 0x07 +#define VGA_GFX_BIT_MASK 0x08 + +/* VGA graphics controller bit masks */ +#define VGA_GR06_GRAPHICS_MODE 0x01 + +#endif /* __linux_video_vga_h__ */ diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h new file mode 100644 index 0000000000..260f7d6948 --- /dev/null +++ b/hw/display/vga_int.h @@ -0,0 +1,218 @@ +/* + * QEMU internal VGA defines. + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef HW_VGA_INT_H +#define HW_VGA_INT_H 1 + +#include <hw/hw.h> +#include "qapi/error.h" +#include "exec/memory.h" + +#define ST01_V_RETRACE 0x08 +#define ST01_DISP_ENABLE 0x01 + +#define VBE_DISPI_MAX_XRES 16000 +#define VBE_DISPI_MAX_YRES 12000 +#define VBE_DISPI_MAX_BPP 32 + +#define VBE_DISPI_INDEX_ID 0x0 +#define VBE_DISPI_INDEX_XRES 0x1 +#define VBE_DISPI_INDEX_YRES 0x2 +#define VBE_DISPI_INDEX_BPP 0x3 +#define VBE_DISPI_INDEX_ENABLE 0x4 +#define VBE_DISPI_INDEX_BANK 0x5 +#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 +#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 +#define VBE_DISPI_INDEX_X_OFFSET 0x8 +#define VBE_DISPI_INDEX_Y_OFFSET 0x9 +#define VBE_DISPI_INDEX_NB 0xa /* size of vbe_regs[] */ +#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa /* read-only, not in vbe_regs */ + +#define VBE_DISPI_ID0 0xB0C0 +#define VBE_DISPI_ID1 0xB0C1 +#define VBE_DISPI_ID2 0xB0C2 +#define VBE_DISPI_ID3 0xB0C3 +#define VBE_DISPI_ID4 0xB0C4 +#define VBE_DISPI_ID5 0xB0C5 + +#define VBE_DISPI_DISABLED 0x00 +#define VBE_DISPI_ENABLED 0x01 +#define VBE_DISPI_GETCAPS 0x02 +#define VBE_DISPI_8BIT_DAC 0x20 +#define VBE_DISPI_LFB_ENABLED 0x40 +#define VBE_DISPI_NOCLEARMEM 0x80 + +#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 + +#define CH_ATTR_SIZE (160 * 100) +#define VGA_MAX_HEIGHT 2048 + +struct vga_precise_retrace { + int64_t ticks_per_char; + int64_t total_chars; + int htotal; + int hstart; + int hend; + int vstart; + int vend; + int freq; +}; + +union vga_retrace { + struct vga_precise_retrace precise; +}; + +struct VGACommonState; +typedef uint8_t (* vga_retrace_fn)(struct VGACommonState *s); +typedef void (* vga_update_retrace_info_fn)(struct VGACommonState *s); + +typedef struct VGACommonState { + MemoryRegion *legacy_address_space; + uint8_t *vram_ptr; + MemoryRegion vram; + MemoryRegion vram_vbe; + uint32_t vram_size; + uint32_t vram_size_mb; /* property */ + uint32_t latch; + MemoryRegion *chain4_alias; + uint8_t sr_index; + uint8_t sr[256]; + uint8_t gr_index; + uint8_t gr[256]; + uint8_t ar_index; + uint8_t ar[21]; + int ar_flip_flop; + uint8_t cr_index; + uint8_t cr[256]; /* CRT registers */ + uint8_t msr; /* Misc Output Register */ + uint8_t fcr; /* Feature Control Register */ + uint8_t st00; /* status 0 */ + uint8_t st01; /* status 1 */ + uint8_t dac_state; + uint8_t dac_sub_index; + uint8_t dac_read_index; + uint8_t dac_write_index; + uint8_t dac_cache[3]; /* used when writing */ + int dac_8bit; + uint8_t palette[768]; + int32_t bank_offset; + int (*get_bpp)(struct VGACommonState *s); + void (*get_offsets)(struct VGACommonState *s, + uint32_t *pline_offset, + uint32_t *pstart_addr, + uint32_t *pline_compare); + void (*get_resolution)(struct VGACommonState *s, + int *pwidth, + int *pheight); + /* bochs vbe state */ + uint16_t vbe_index; + uint16_t vbe_regs[VBE_DISPI_INDEX_NB]; + uint32_t vbe_start_addr; + uint32_t vbe_line_offset; + uint32_t vbe_bank_mask; + int vbe_mapped; + /* display refresh support */ + QemuConsole *con; + uint32_t font_offsets[2]; + int graphic_mode; + uint8_t shift_control; + uint8_t double_scan; + uint32_t line_offset; + uint32_t line_compare; + uint32_t start_addr; + uint32_t plane_updated; + uint32_t last_line_offset; + uint8_t last_cw, last_ch; + uint32_t last_width, last_height; /* in chars or pixels */ + uint32_t last_scr_width, last_scr_height; /* in pixels */ + uint32_t last_depth; /* in bits */ + uint8_t cursor_start, cursor_end; + bool cursor_visible_phase; + int64_t cursor_blink_time; + uint32_t cursor_offset; + unsigned int (*rgb_to_pixel)(unsigned int r, + unsigned int g, unsigned b); + vga_hw_update_ptr update; + vga_hw_invalidate_ptr invalidate; + vga_hw_screen_dump_ptr screen_dump; + vga_hw_text_update_ptr text_update; + bool full_update_text; + bool full_update_gfx; + /* hardware mouse cursor support */ + uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; + void (*cursor_invalidate)(struct VGACommonState *s); + void (*cursor_draw_line)(struct VGACommonState *s, uint8_t *d, int y); + /* tell for each page if it has been updated since the last time */ + uint32_t last_palette[256]; + uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */ + /* retrace */ + vga_retrace_fn retrace; + vga_update_retrace_info_fn update_retrace_info; + union vga_retrace retrace_info; + uint8_t is_vbe_vmstate; +} VGACommonState; + +static inline int c6_to_8(int v) +{ + int b; + v &= 0x3f; + b = v & 1; + return (v << 2) | (b << 1) | b; +} + +void vga_common_init(VGACommonState *s); +void vga_init(VGACommonState *s, MemoryRegion *address_space, + MemoryRegion *address_space_io, bool init_vga_ports); +MemoryRegion *vga_init_io(VGACommonState *s, + const MemoryRegionPortio **vga_ports, + const MemoryRegionPortio **vbe_ports); +void vga_common_reset(VGACommonState *s); + +void vga_sync_dirty_bitmap(VGACommonState *s); +void vga_dirty_log_start(VGACommonState *s); +void vga_dirty_log_stop(VGACommonState *s); + +extern const VMStateDescription vmstate_vga_common; +uint32_t vga_ioport_read(void *opaque, uint32_t addr); +void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val); +uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr); +void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val); +void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2); +void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp); + +int vga_ioport_invalid(VGACommonState *s, uint32_t addr); + +void vga_init_vbe(VGACommonState *s, MemoryRegion *address_space); +uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr); +void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val); +void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val); + +extern const uint8_t sr_mask[8]; +extern const uint8_t gr_mask[16]; + +#define VGABIOS_FILENAME "vgabios.bin" +#define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin" + +extern const MemoryRegionOps vga_mem_ops; + +#endif diff --git a/hw/display/vga_template.h b/hw/display/vga_template.h new file mode 100644 index 0000000000..f6f6a01d84 --- /dev/null +++ b/hw/display/vga_template.h @@ -0,0 +1,459 @@ +/* + * QEMU VGA Emulator templates + * + * Copyright (c) 2003 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if DEPTH == 8 +#define BPP 1 +#define PIXEL_TYPE uint8_t +#elif DEPTH == 15 || DEPTH == 16 +#define BPP 2 +#define PIXEL_TYPE uint16_t +#elif DEPTH == 32 +#define BPP 4 +#define PIXEL_TYPE uint32_t +#else +#error unsupport depth +#endif + +#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, + uint32_t xorcol, + uint32_t bgcol) +{ +#if BPP == 1 + ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol; + ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol; +#elif BPP == 2 + ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol; + ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol; + ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol; + ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol; +#else + ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol; + ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol; +#endif +} + +static void glue(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize, + const uint8_t *font_ptr, int h, + uint32_t fgcol, uint32_t bgcol) +{ + uint32_t font_data, xorcol; + + xorcol = bgcol ^ fgcol; + do { + font_data = font_ptr[0]; + glue(vga_draw_glyph_line_, DEPTH)(d, font_data, xorcol, bgcol); + font_ptr += 4; + d += linesize; + } while (--h); +} + +static void glue(vga_draw_glyph16_, DEPTH)(uint8_t *d, int linesize, + const uint8_t *font_ptr, int h, + uint32_t fgcol, uint32_t bgcol) +{ + uint32_t font_data, xorcol; + + xorcol = bgcol ^ fgcol; + do { + font_data = font_ptr[0]; + glue(vga_draw_glyph_line_, DEPTH)(d, + expand4to8[font_data >> 4], + xorcol, bgcol); + glue(vga_draw_glyph_line_, DEPTH)(d + 8 * BPP, + expand4to8[font_data & 0x0f], + xorcol, bgcol); + font_ptr += 4; + d += linesize; + } while (--h); +} + +static void glue(vga_draw_glyph9_, DEPTH)(uint8_t *d, int linesize, + const uint8_t *font_ptr, int h, + uint32_t fgcol, uint32_t bgcol, int dup9) +{ + uint32_t font_data, xorcol, v; + + xorcol = bgcol ^ fgcol; + do { + font_data = font_ptr[0]; +#if BPP == 1 + cpu_to_32wu((uint32_t *)d, (dmask16[(font_data >> 4)] & xorcol) ^ bgcol); + v = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol; + cpu_to_32wu(((uint32_t *)d)+1, v); + if (dup9) + ((uint8_t *)d)[8] = v >> (24 * (1 - BIG)); + else + ((uint8_t *)d)[8] = bgcol; + +#elif BPP == 2 + cpu_to_32wu(((uint32_t *)d)+0, (dmask4[(font_data >> 6)] & xorcol) ^ bgcol); + cpu_to_32wu(((uint32_t *)d)+1, (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol); + cpu_to_32wu(((uint32_t *)d)+2, (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol); + v = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol; + cpu_to_32wu(((uint32_t *)d)+3, v); + if (dup9) + ((uint16_t *)d)[8] = v >> (16 * (1 - BIG)); + else + ((uint16_t *)d)[8] = bgcol; +#else + ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol; + ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol; + v = (-((font_data >> 0) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[7] = v; + if (dup9) + ((uint32_t *)d)[8] = v; + else + ((uint32_t *)d)[8] = bgcol; +#endif + font_ptr += 4; + d += linesize; + } while (--h); +} + +/* + * 4 color mode + */ +static void glue(vga_draw_line2_, DEPTH)(VGACommonState *s1, uint8_t *d, + const uint8_t *s, int width) +{ + uint32_t plane_mask, *palette, data, v; + int x; + + palette = s1->last_palette; + plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; + width >>= 3; + for(x = 0; x < width; x++) { + data = ((uint32_t *)s)[0]; + data &= plane_mask; + v = expand2[GET_PLANE(data, 0)]; + v |= expand2[GET_PLANE(data, 2)] << 2; + ((PIXEL_TYPE *)d)[0] = palette[v >> 12]; + ((PIXEL_TYPE *)d)[1] = palette[(v >> 8) & 0xf]; + ((PIXEL_TYPE *)d)[2] = palette[(v >> 4) & 0xf]; + ((PIXEL_TYPE *)d)[3] = palette[(v >> 0) & 0xf]; + + v = expand2[GET_PLANE(data, 1)]; + v |= expand2[GET_PLANE(data, 3)] << 2; + ((PIXEL_TYPE *)d)[4] = palette[v >> 12]; + ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf]; + ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf]; + ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf]; + d += BPP * 8; + s += 4; + } +} + +#if BPP == 1 +#define PUT_PIXEL2(d, n, v) ((uint16_t *)d)[(n)] = (v) +#elif BPP == 2 +#define PUT_PIXEL2(d, n, v) ((uint32_t *)d)[(n)] = (v) +#else +#define PUT_PIXEL2(d, n, v) \ +((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v) +#endif + +/* + * 4 color mode, dup2 horizontal + */ +static void glue(vga_draw_line2d2_, DEPTH)(VGACommonState *s1, uint8_t *d, + const uint8_t *s, int width) +{ + uint32_t plane_mask, *palette, data, v; + int x; + + palette = s1->last_palette; + plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; + width >>= 3; + for(x = 0; x < width; x++) { + data = ((uint32_t *)s)[0]; + data &= plane_mask; + v = expand2[GET_PLANE(data, 0)]; + v |= expand2[GET_PLANE(data, 2)] << 2; + PUT_PIXEL2(d, 0, palette[v >> 12]); + PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]); + PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]); + PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]); + + v = expand2[GET_PLANE(data, 1)]; + v |= expand2[GET_PLANE(data, 3)] << 2; + PUT_PIXEL2(d, 4, palette[v >> 12]); + PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); + PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); + PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); + d += BPP * 16; + s += 4; + } +} + +/* + * 16 color mode + */ +static void glue(vga_draw_line4_, DEPTH)(VGACommonState *s1, uint8_t *d, + const uint8_t *s, int width) +{ + uint32_t plane_mask, data, v, *palette; + int x; + + palette = s1->last_palette; + plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; + width >>= 3; + for(x = 0; x < width; x++) { + data = ((uint32_t *)s)[0]; + data &= plane_mask; + v = expand4[GET_PLANE(data, 0)]; + v |= expand4[GET_PLANE(data, 1)] << 1; + v |= expand4[GET_PLANE(data, 2)] << 2; + v |= expand4[GET_PLANE(data, 3)] << 3; + ((PIXEL_TYPE *)d)[0] = palette[v >> 28]; + ((PIXEL_TYPE *)d)[1] = palette[(v >> 24) & 0xf]; + ((PIXEL_TYPE *)d)[2] = palette[(v >> 20) & 0xf]; + ((PIXEL_TYPE *)d)[3] = palette[(v >> 16) & 0xf]; + ((PIXEL_TYPE *)d)[4] = palette[(v >> 12) & 0xf]; + ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf]; + ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf]; + ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf]; + d += BPP * 8; + s += 4; + } +} + +/* + * 16 color mode, dup2 horizontal + */ +static void glue(vga_draw_line4d2_, DEPTH)(VGACommonState *s1, uint8_t *d, + const uint8_t *s, int width) +{ + uint32_t plane_mask, data, v, *palette; + int x; + + palette = s1->last_palette; + plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; + width >>= 3; + for(x = 0; x < width; x++) { + data = ((uint32_t *)s)[0]; + data &= plane_mask; + v = expand4[GET_PLANE(data, 0)]; + v |= expand4[GET_PLANE(data, 1)] << 1; + v |= expand4[GET_PLANE(data, 2)] << 2; + v |= expand4[GET_PLANE(data, 3)] << 3; + PUT_PIXEL2(d, 0, palette[v >> 28]); + PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]); + PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]); + PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]); + PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]); + PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); + PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); + PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); + d += BPP * 16; + s += 4; + } +} + +/* + * 256 color mode, double pixels + * + * XXX: add plane_mask support (never used in standard VGA modes) + */ +static void glue(vga_draw_line8d2_, DEPTH)(VGACommonState *s1, uint8_t *d, + const uint8_t *s, int width) +{ + uint32_t *palette; + int x; + + palette = s1->last_palette; + width >>= 3; + for(x = 0; x < width; x++) { + PUT_PIXEL2(d, 0, palette[s[0]]); + PUT_PIXEL2(d, 1, palette[s[1]]); + PUT_PIXEL2(d, 2, palette[s[2]]); + PUT_PIXEL2(d, 3, palette[s[3]]); + d += BPP * 8; + s += 4; + } +} + +/* + * standard 256 color mode + * + * XXX: add plane_mask support (never used in standard VGA modes) + */ +static void glue(vga_draw_line8_, DEPTH)(VGACommonState *s1, uint8_t *d, + const uint8_t *s, int width) +{ + uint32_t *palette; + int x; + + palette = s1->last_palette; + width >>= 3; + for(x = 0; x < width; x++) { + ((PIXEL_TYPE *)d)[0] = palette[s[0]]; + ((PIXEL_TYPE *)d)[1] = palette[s[1]]; + ((PIXEL_TYPE *)d)[2] = palette[s[2]]; + ((PIXEL_TYPE *)d)[3] = palette[s[3]]; + ((PIXEL_TYPE *)d)[4] = palette[s[4]]; + ((PIXEL_TYPE *)d)[5] = palette[s[5]]; + ((PIXEL_TYPE *)d)[6] = palette[s[6]]; + ((PIXEL_TYPE *)d)[7] = palette[s[7]]; + d += BPP * 8; + s += 8; + } +} + +#endif /* DEPTH != 15 */ + + +/* XXX: optimize */ + +/* + * 15 bit color + */ +static void glue(vga_draw_line15_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d, + const uint8_t *s, int width) +{ +#if DEPTH == 15 && defined(HOST_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)(VGACommonState *s1, uint8_t *d, + const uint8_t *s, int width) +{ +#if DEPTH == 16 && defined(HOST_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)(VGACommonState *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)(VGACommonState *s1, uint8_t *d, + const uint8_t *s, int width) +{ +#if DEPTH == 32 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) && !defined(BGR_FORMAT) + 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/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index 5b9ce8f96b..bcad47a68d 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -31,7 +31,7 @@ #define HW_FILL_ACCEL #define HW_MOUSE_ACCEL -#include "hw/vga_int.h" +#include "vga_int.h" /* See http://vmware-svga.sf.net/ for some documentation on VMWare SVGA */ |