From: Aurelien Jarno <aurelien@aurel32.net>
To: Shin-ichiro KAWASAKI <kawasaki@juno.dti.ne.jp>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH] sh: sm501: Add hardware cursor feature
Date: Thu, 14 Jan 2010 16:18:27 +0100 [thread overview]
Message-ID: <20100114151827.GD16630@volta.aurel32.net> (raw)
In-Reply-To: <4B3D9D5B.6080501@juno.dti.ne.jp>
On Fri, Jan 01, 2010 at 03:59:39PM +0900, Shin-ichiro KAWASAKI wrote:
> This patch adds hardware cursor feature to SM501 graphics chip emulation,
> to make the graphic console more useful for QEMU SH4 users.
>
>
> Signed-off-by: Shin-ichiro KAWASAKI <kawasaki@juno.dti.ne.jp>
Thanks, applied.
> hw/sm501.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++----
> hw/sm501_template.h | 42 ++++++++++++++
> 2 files changed, 185 insertions(+), 11 deletions(-)
>
> diff --git a/hw/sm501.c b/hw/sm501.c
> index 612a8e5..cd1f595 100644
> --- a/hw/sm501.c
> +++ b/hw/sm501.c
> @@ -434,6 +434,8 @@
>
> /* end of register definitions */
>
> +#define SM501_HWC_WIDTH (64)
> +#define SM501_HWC_HEIGHT (64)
>
> /* SM501 local memory size taken from "linux/drivers/mfd/sm501.c" */
> static const uint32_t sm501_mem_local_size[] = {
> @@ -526,6 +528,95 @@ static uint32_t get_local_mem_size_index(uint32_t size)
> return index;
> }
>
> +/**
> + * Check the availability of hardware cursor.
> + * @param crt 0 for PANEL, 1 for CRT.
> + */
> +static inline int is_hwc_enabled(SM501State *state, int crt)
> +{
> + uint32_t addr = crt ? state->dc_crt_hwc_addr : state->dc_panel_hwc_addr;
> + return addr & 0x80000000;
> +}
> +
> +/**
> + * Get the address which holds cursor pattern data.
> + * @param crt 0 for PANEL, 1 for CRT.
> + */
> +static inline uint32_t get_hwc_address(SM501State *state, int crt)
> +{
> + uint32_t addr = crt ? state->dc_crt_hwc_addr : state->dc_panel_hwc_addr;
> + return (addr & 0x03FFFFF0)/* >> 4*/;
> +}
> +
> +/**
> + * Get the cursor position in y coordinate.
> + * @param crt 0 for PANEL, 1 for CRT.
> + */
> +static inline uint32_t get_hwc_y(SM501State *state, int crt)
> +{
> + uint32_t location = crt ? state->dc_crt_hwc_location
> + : state->dc_panel_hwc_location;
> + return (location & 0x07FF0000) >> 16;
> +}
> +
> +/**
> + * Get the cursor position in x coordinate.
> + * @param crt 0 for PANEL, 1 for CRT.
> + */
> +static inline uint32_t get_hwc_x(SM501State *state, int crt)
> +{
> + uint32_t location = crt ? state->dc_crt_hwc_location
> + : state->dc_panel_hwc_location;
> + return location & 0x000007FF;
> +}
> +
> +/**
> + * Get the cursor position in x coordinate.
> + * @param crt 0 for PANEL, 1 for CRT.
> + * @param index 0, 1, 2 or 3 which specifies color of corsor dot.
> + */
> +static inline uint16_t get_hwc_color(SM501State *state, int crt, int index)
> +{
> + uint16_t color_reg = 0;
> + uint16_t color_565 = 0;
> +
> + if (index == 0) {
> + return 0;
> + }
> +
> + switch (index) {
> + case 1:
> + case 2:
> + color_reg = crt ? state->dc_crt_hwc_color_1_2
> + : state->dc_panel_hwc_color_1_2;
> + break;
> + case 3:
> + color_reg = crt ? state->dc_crt_hwc_color_3
> + : state->dc_panel_hwc_color_3;
> + break;
> + default:
> + printf("invalid hw cursor color.\n");
> + assert(0);
> + }
> +
> + switch (index) {
> + case 1:
> + case 3:
> + color_565 = (uint16_t)(color_reg & 0xFFFF);
> + break;
> + case 2:
> + color_565 = (uint16_t)((color_reg >> 16) & 0xFFFF);
> + break;
> + }
> + return color_565;
> +}
> +
> +static int within_hwc_y_range(SM501State *state, int y, int crt)
> +{
> + int hwc_y = get_hwc_y(state, crt);
> + return (hwc_y <= y && y < hwc_y + SM501_HWC_HEIGHT);
> +}
> +
> static uint32_t sm501_system_config_read(void *opaque, target_phys_addr_t addr)
> {
> SM501State * s = (SM501State *)opaque;
> @@ -736,13 +827,13 @@ static uint32_t sm501_disp_ctrl_read(void *opaque, target_phys_addr_t addr)
> ret = s->dc_crt_hwc_addr;
> break;
> case SM501_DC_CRT_HWC_LOC:
> - ret = s->dc_crt_hwc_addr;
> + ret = s->dc_crt_hwc_location;
> break;
> case SM501_DC_CRT_HWC_COLOR_1_2:
> - ret = s->dc_crt_hwc_addr;
> + ret = s->dc_crt_hwc_color_1_2;
> break;
> case SM501_DC_CRT_HWC_COLOR_3:
> - ret = s->dc_crt_hwc_addr;
> + ret = s->dc_crt_hwc_color_3;
> break;
>
> case SM501_DC_PANEL_PALETTE ... SM501_DC_PANEL_PALETTE + 0x400*3 - 4:
> @@ -809,13 +900,13 @@ static void sm501_disp_ctrl_write(void *opaque,
> s->dc_panel_hwc_addr = value & 0x8FFFFFF0;
> break;
> case SM501_DC_PANEL_HWC_LOC:
> - s->dc_panel_hwc_addr = value & 0x0FFF0FFF;
> + s->dc_panel_hwc_location = value & 0x0FFF0FFF;
> break;
> case SM501_DC_PANEL_HWC_COLOR_1_2:
> - s->dc_panel_hwc_addr = value;
> + s->dc_panel_hwc_color_1_2 = value;
> break;
> case SM501_DC_PANEL_HWC_COLOR_3:
> - s->dc_panel_hwc_addr = value & 0x0000FFFF;
> + s->dc_panel_hwc_color_3 = value & 0x0000FFFF;
> break;
>
> case SM501_DC_CRT_CONTROL:
> @@ -844,13 +935,13 @@ static void sm501_disp_ctrl_write(void *opaque,
> s->dc_crt_hwc_addr = value & 0x8FFFFFF0;
> break;
> case SM501_DC_CRT_HWC_LOC:
> - s->dc_crt_hwc_addr = value & 0x0FFF0FFF;
> + s->dc_crt_hwc_location = value & 0x0FFF0FFF;
> break;
> case SM501_DC_CRT_HWC_COLOR_1_2:
> - s->dc_crt_hwc_addr = value;
> + s->dc_crt_hwc_color_1_2 = value;
> break;
> case SM501_DC_CRT_HWC_COLOR_3:
> - s->dc_crt_hwc_addr = value & 0x0000FFFF;
> + s->dc_crt_hwc_color_3 = value & 0x0000FFFF;
> break;
>
> case SM501_DC_PANEL_PALETTE ... SM501_DC_PANEL_PALETTE + 0x400*3 - 4:
> @@ -883,6 +974,9 @@ static CPUWriteMemoryFunc * const sm501_disp_ctrl_writefn[] = {
> typedef void draw_line_func(uint8_t *d, const uint8_t *s,
> int width, const uint32_t *pal);
>
> +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 "sm501_template.h"
>
> @@ -937,6 +1031,16 @@ static draw_line_func * draw_line32_funcs[] = {
> draw_line32_16bgr,
> };
>
> +static draw_hwc_line_func * draw_hwc_line_funcs[] = {
> + draw_hwc_line_8,
> + draw_hwc_line_15,
> + draw_hwc_line_16,
> + draw_hwc_line_32,
> + draw_hwc_line_32bgr,
> + draw_hwc_line_15bgr,
> + draw_hwc_line_16bgr,
> +};
> +
> static inline int get_depth_index(DisplayState *s)
> {
> switch(ds_get_bits_per_pixel(s)) {
> @@ -966,8 +1070,10 @@ static void sm501_draw_crt(SM501State * s)
> int dst_bpp = ds_get_bytes_per_pixel(s->ds) + (ds_get_bits_per_pixel(s->ds) % 8 ? 1 : 0);
> uint32_t * palette = (uint32_t *)&s->dc_palette[SM501_DC_CRT_PALETTE
> - SM501_DC_PANEL_PALETTE];
> + uint8_t hwc_palette[3 * 3];
> int ds_depth_index = get_depth_index(s->ds);
> draw_line_func * draw_line = NULL;
> + draw_hwc_line_func * draw_hwc_line = NULL;
> int full_update = 0;
> int y_start = -1;
> int page_min = 0x7fffffff;
> @@ -995,6 +1101,22 @@ static void sm501_draw_crt(SM501State * s)
> break;
> }
>
> + /* set up to draw hardware cursor */
> + if (is_hwc_enabled(s, 1)) {
> + int i;
> +
> + /* get cursor palette */
> + for (i = 0; i < 3; i++) {
> + uint16_t rgb565 = get_hwc_color(s, 1, i + 1);
> + hwc_palette[i * 3 + 0] = (rgb565 & 0xf800) >> 8; /* red */
> + hwc_palette[i * 3 + 1] = (rgb565 & 0x07e0) >> 3; /* green */
> + hwc_palette[i * 3 + 2] = (rgb565 & 0x001f) << 3; /* blue */
> + }
> +
> + /* choose cursor draw line function */
> + draw_hwc_line = draw_hwc_line_funcs[ds_depth_index];
> + }
> +
> /* adjust console size */
> if (s->last_width != width || s->last_height != height) {
> qemu_console_resize(s->ds, width, height);
> @@ -1005,7 +1127,8 @@ static void sm501_draw_crt(SM501State * s)
>
> /* draw each line according to conditions */
> for (y = 0; y < height; y++) {
> - int update = full_update;
> + int update_hwc = draw_hwc_line ? within_hwc_y_range(s, y, 1) : 0;
> + int update = full_update || update_hwc;
> ram_addr_t page0 = offset & TARGET_PAGE_MASK;
> ram_addr_t page1 = (offset + width * src_bpp - 1) & TARGET_PAGE_MASK;
> ram_addr_t page;
> @@ -1017,7 +1140,16 @@ static void sm501_draw_crt(SM501State * s)
>
> /* draw line and change status */
> if (update) {
> - draw_line(&(ds_get_data(s->ds)[y * width * dst_bpp]), src, width, palette);
> + uint8_t * d = &(ds_get_data(s->ds)[y * width * dst_bpp]);
> +
> + /* draw graphics layer */
> + draw_line(d, src, width, palette);
> +
> + /* draw haredware cursor */
> + if (update_hwc) {
> + draw_hwc_line(s, 1, hwc_palette, y - get_hwc_y(s, 1), d, width);
> + }
> +
> if (y_start < 0)
> y_start = y;
> if (page0 < page_min)
> diff --git a/hw/sm501_template.h b/hw/sm501_template.h
> index 1679df7..d1ceef9 100644
> --- a/hw/sm501_template.h
> +++ b/hw/sm501_template.h
> @@ -96,6 +96,48 @@ static void glue(draw_line32_, PIXEL_NAME)(
> } 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) {
> + cpu_physical_memory_rw(cursor_addr, &bitset, 1, 0);
> + 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
>
>
>
>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
prev parent reply other threads:[~2010-01-14 15:18 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-01-01 6:59 [Qemu-devel] [PATCH] sh: sm501: Add hardware cursor feature Shin-ichiro KAWASAKI
2010-01-14 15:18 ` Aurelien Jarno [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100114151827.GD16630@volta.aurel32.net \
--to=aurelien@aurel32.net \
--cc=kawasaki@juno.dti.ne.jp \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.