Patchwork [v4,1/2] pxa2xx_lcd: add proper rotation support

login
register
mail settings
Submitter Vasily Khoruzhick
Date June 17, 2011, 10:04 a.m.
Message ID <1308305077-21503-1-git-send-email-anarsoul@gmail.com>
Download mbox | patch
Permalink /patch/100808/
State New
Headers show

Comments

Vasily Khoruzhick - June 17, 2011, 10:04 a.m.
Until now, pxa2xx_lcd only supported 90deg rotation, but
some machines (for example Zipit Z2) needs 270deg rotation.

Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
---
v2: codestyle fixes
v3: fix dpy_update calls for 180 and 360 deg. rotation.
v4: codestyle fixes; replace atoi with strtol
 hw/framebuffer.c |    3 +
 hw/pxa2xx_lcd.c  |  109 ++++++++++++++++++++++++++++++++++++++++++++++++------
 input.c          |   34 ++++++++++++----
 qemu-options.hx  |    9 ++++
 vl.c             |   11 +++++-
 5 files changed, 144 insertions(+), 22 deletions(-)
Vasily Khoruzhick - June 21, 2011, 9:47 a.m.
On Friday 17 June 2011 13:04:36 Vasily Khoruzhick wrote:
> Until now, pxa2xx_lcd only supported 90deg rotation, but
> some machines (for example Zipit Z2) needs 270deg rotation.

Ping

> Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
> ---
> v2: codestyle fixes
> v3: fix dpy_update calls for 180 and 360 deg. rotation.
> v4: codestyle fixes; replace atoi with strtol
>  hw/framebuffer.c |    3 +
>  hw/pxa2xx_lcd.c  |  109
> ++++++++++++++++++++++++++++++++++++++++++++++++------ input.c          | 
>  34 ++++++++++++----
>  qemu-options.hx  |    9 ++++
>  vl.c             |   11 +++++-
>  5 files changed, 144 insertions(+), 22 deletions(-)
> 
> diff --git a/hw/framebuffer.c b/hw/framebuffer.c
> index 24cdf25..56cf16e 100644
> --- a/hw/framebuffer.c
> +++ b/hw/framebuffer.c
> @@ -78,6 +78,9 @@ void framebuffer_update_display(
>      dest = ds_get_data(ds);
>      if (dest_col_pitch < 0)
>          dest -= dest_col_pitch * (cols - 1);
> +    if (dest_row_pitch < 0) {
> +        dest -= dest_row_pitch * (rows - 1);
> +    }
>      first = -1;
>      addr = pd;
> 
> diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
> index e524802..a5f8c51 100644
> --- a/hw/pxa2xx_lcd.c
> +++ b/hw/pxa2xx_lcd.c
> @@ -665,7 +665,7 @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int
> ch, int bpp) }
>  }
> 
> -static void pxa2xx_lcdc_dma0_redraw_horiz(PXA2xxLCDState *s,
> +static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
>                  target_phys_addr_t addr, int *miny, int *maxy)
>  {
>      int src_width, dest_width;
> @@ -692,7 +692,7 @@ static void
> pxa2xx_lcdc_dma0_redraw_horiz(PXA2xxLCDState *s, fn, s->dma_ch[0].palette,
> miny, maxy); }
> 
> -static void pxa2xx_lcdc_dma0_redraw_vert(PXA2xxLCDState *s,
> +static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
>                 target_phys_addr_t addr, int *miny, int *maxy)
>  {
>      int src_width, dest_width;
> @@ -720,6 +720,67 @@ static void
> pxa2xx_lcdc_dma0_redraw_vert(PXA2xxLCDState *s, miny, maxy);
>  }
> 
> +static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
> +                target_phys_addr_t addr, int *miny, int *maxy)
> +{
> +    int src_width, dest_width;
> +    drawfn fn = NULL;
> +    if (s->dest_width) {
> +        fn = s->line_fn[s->transp][s->bpp];
> +    }
> +    if (!fn) {
> +        return;
> +    }
> +
> +    src_width = (s->xres + 3) & ~3;     /* Pad to a 4 pixels multiple */
> +    if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) {
> +        src_width *= 3;
> +    } else if (s->bpp > pxa_lcdc_16bpp) {
> +        src_width *= 4;
> +    } else if (s->bpp > pxa_lcdc_8bpp) {
> +        src_width *= 2;
> +    }
> +
> +    dest_width = s->xres * s->dest_width;
> +    *miny = 0;
> +    framebuffer_update_display(s->ds,
> +                               addr, s->xres, s->yres,
> +                               src_width, -dest_width, -s->dest_width,
> +                               s->invalidated,
> +                               fn, s->dma_ch[0].palette, miny, maxy);
> +}
> +
> +static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s,
> +               target_phys_addr_t addr, int *miny, int *maxy)
> +{
> +    int src_width, dest_width;
> +    drawfn fn = NULL;
> +    if (s->dest_width) {
> +        fn = s->line_fn[s->transp][s->bpp];
> +    }
> +    if (!fn) {
> +        return;
> +    }
> +
> +    src_width = (s->xres + 3) & ~3;     /* Pad to a 4 pixels multiple */
> +    if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) {
> +        src_width *= 3;
> +    } else if (s->bpp > pxa_lcdc_16bpp) {
> +        src_width *= 4;
> +    } else if (s->bpp > pxa_lcdc_8bpp) {
> +        src_width *= 2;
> +    }
> +
> +    dest_width = s->yres * s->dest_width;
> +    *miny = 0;
> +    framebuffer_update_display(s->ds,
> +                               addr, s->xres, s->yres,
> +                               src_width, -s->dest_width, dest_width,
> +                               s->invalidated,
> +                               fn, s->dma_ch[0].palette,
> +                               miny, maxy);
> +}
> +
>  static void pxa2xx_lcdc_resize(PXA2xxLCDState *s)
>  {
>      int width, height;
> @@ -730,10 +791,11 @@ static void pxa2xx_lcdc_resize(PXA2xxLCDState *s)
>      height = LCCR2_LPP(s->control[2]) + 1;
> 
>      if (width != s->xres || height != s->yres) {
> -        if (s->orientation)
> +        if (s->orientation == 90 || s->orientation == 270) {
>              qemu_console_resize(s->ds, height, width);
> -        else
> +        } else {
>              qemu_console_resize(s->ds, width, height);
> +        }
>          s->invalidated = 1;
>          s->xres = width;
>          s->yres = height;
> @@ -797,10 +859,24 @@ static void pxa2xx_update_display(void *opaque)
>      }
> 
>      if (miny >= 0) {
> -        if (s->orientation)
> -            dpy_update(s->ds, miny, 0, maxy - miny, s->xres);
> -        else
> -            dpy_update(s->ds, 0, miny, s->xres, maxy - miny);
> +        switch (s->orientation) {
> +        case 0:
> +            dpy_update(s->ds, 0, miny, s->xres, maxy - miny + 1);
> +            break;
> +        case 90:
> +            dpy_update(s->ds, miny, 0, maxy - miny + 1, s->xres);
> +            break;
> +        case 180:
> +            maxy = s->yres - maxy - 1;
> +            miny = s->yres - miny - 1;
> +            dpy_update(s->ds, 0, maxy, s->xres, miny - maxy + 1);
> +            break;
> +        case 270:
> +            maxy = s->yres - maxy - 1;
> +            miny = s->yres - miny - 1;
> +            dpy_update(s->ds, maxy, 0, miny - maxy + 1, s->xres);
> +            break;
> +        }
>      }
>      pxa2xx_lcdc_int_update(s);
> 
> @@ -822,10 +898,19 @@ static void pxa2xx_lcdc_orientation(void *opaque, int
> angle) {
>      PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
> 
> -    if (angle) {
> -        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_vert;
> -    } else {
> -        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_horiz;
> +    switch (angle) {
> +    case 0:
> +        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot0;
> +        break;
> +    case 90:
> +        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot90;
> +        break;
> +    case 180:
> +        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot180;
> +        break;
> +    case 270:
> +        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot270;
> +        break;
>      }
> 
>      s->orientation = angle;
> diff --git a/input.c b/input.c
> index 5664d3a..f0a02e7 100644
> --- a/input.c
> +++ b/input.c
> @@ -148,7 +148,7 @@ void kbd_mouse_event(int dx, int dy, int dz, int
> buttons_state) QEMUPutMouseEntry *entry;
>      QEMUPutMouseEvent *mouse_event;
>      void *mouse_event_opaque;
> -    int width;
> +    int width, height;
> 
>      if (QTAILQ_EMPTY(&mouse_handlers)) {
>          return;
> @@ -160,15 +160,31 @@ void kbd_mouse_event(int dx, int dy, int dz, int
> buttons_state) mouse_event_opaque = entry->qemu_put_mouse_event_opaque;
> 
>      if (mouse_event) {
> -        if (graphic_rotate) {
> -            if (entry->qemu_put_mouse_event_absolute) {
> -                width = 0x7fff;
> -            } else {
> -                width = graphic_width - 1;
> -            }
> -            mouse_event(mouse_event_opaque, width - dy, dx, dz,
> buttons_state); +        if (entry->qemu_put_mouse_event_absolute) {
> +            width = 0x7fff;
> +            height = 0x7fff;
>          } else {
> -            mouse_event(mouse_event_opaque, dx, dy, dz, buttons_state);
> +            width = graphic_width - 1;
> +            height = graphic_height - 1;
> +        }
> +
> +        switch (graphic_rotate) {
> +        case 0:
> +            mouse_event(mouse_event_opaque,
> +                        dx, dy, dz, buttons_state);
> +            break;
> +        case 90:
> +            mouse_event(mouse_event_opaque,
> +                        width - dy, dx, dz, buttons_state);
> +            break;
> +        case 180:
> +            mouse_event(mouse_event_opaque,
> +                        width - dx, height - dy, dz, buttons_state);
> +            break;
> +        case 270:
> +            mouse_event(mouse_event_opaque,
> +                        dy, height - dx, dz, buttons_state);
> +            break;
>          }
>      }
>  }
> diff --git a/qemu-options.hx b/qemu-options.hx
> index 82e085a..46d8f25 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -771,6 +771,15 @@ STEXI
>  Rotate graphical output 90 deg left (only PXA LCD).
>  ETEXI
> 
> +DEF("rotate", HAS_ARG, QEMU_OPTION_rotate,
> +    "-rotate <deg>   rotate graphical output some deg left (only PXA
> LCD)\n", +    QEMU_ARCH_ALL)
> +STEXI
> +@item -rotate
> +@findex -rotate
> +Rotate graphical output some deg left (only PXA LCD).
> +ETEXI
> +
>  DEF("vga", HAS_ARG, QEMU_OPTION_vga,
>      "-vga [std|cirrus|vmware|qxl|xenfb|none]\n"
>      "                select video card type\n", QEMU_ARCH_ALL)
> diff --git a/vl.c b/vl.c
> index b362871..c11cc44 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -2289,7 +2289,16 @@ int main(int argc, char **argv, char **envp)
>  #endif
>                  break;
>              case QEMU_OPTION_portrait:
> -                graphic_rotate = 1;
> +                graphic_rotate = 90;
> +                break;
> +            case QEMU_OPTION_rotate:
> +                graphic_rotate = strtol(optarg, (char **)&optarg, 10);
> +                if (graphic_rotate != 0 && graphic_rotate != 90 &&
> +                    graphic_rotate != 180 && graphic_rotate != 270) {
> +                    fprintf(stderr,
> +                        "qemu: only 90, 180, 270 deg rotation is
> available\n"); +                    exit(1);
> +                }
>                  break;
>              case QEMU_OPTION_kernel:
>                  kernel_filename = optarg;
andrzej zaborowski - July 4, 2011, 8:11 p.m.
On 17 June 2011 12:04, Vasily Khoruzhick <anarsoul@gmail.com> wrote:
> Until now, pxa2xx_lcd only supported 90deg rotation, but
> some machines (for example Zipit Z2) needs 270deg rotation.
>
> Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
> ---
> v2: codestyle fixes
> v3: fix dpy_update calls for 180 and 360 deg. rotation.
> v4: codestyle fixes; replace atoi with strtol

Thanks, I pushed this version.

Cheers

Patch

diff --git a/hw/framebuffer.c b/hw/framebuffer.c
index 24cdf25..56cf16e 100644
--- a/hw/framebuffer.c
+++ b/hw/framebuffer.c
@@ -78,6 +78,9 @@  void framebuffer_update_display(
     dest = ds_get_data(ds);
     if (dest_col_pitch < 0)
         dest -= dest_col_pitch * (cols - 1);
+    if (dest_row_pitch < 0) {
+        dest -= dest_row_pitch * (rows - 1);
+    }
     first = -1;
     addr = pd;
 
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index e524802..a5f8c51 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -665,7 +665,7 @@  static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
     }
 }
 
-static void pxa2xx_lcdc_dma0_redraw_horiz(PXA2xxLCDState *s,
+static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
                 target_phys_addr_t addr, int *miny, int *maxy)
 {
     int src_width, dest_width;
@@ -692,7 +692,7 @@  static void pxa2xx_lcdc_dma0_redraw_horiz(PXA2xxLCDState *s,
                                fn, s->dma_ch[0].palette, miny, maxy);
 }
 
-static void pxa2xx_lcdc_dma0_redraw_vert(PXA2xxLCDState *s,
+static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
                target_phys_addr_t addr, int *miny, int *maxy)
 {
     int src_width, dest_width;
@@ -720,6 +720,67 @@  static void pxa2xx_lcdc_dma0_redraw_vert(PXA2xxLCDState *s,
                                miny, maxy);
 }
 
+static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
+                target_phys_addr_t addr, int *miny, int *maxy)
+{
+    int src_width, dest_width;
+    drawfn fn = NULL;
+    if (s->dest_width) {
+        fn = s->line_fn[s->transp][s->bpp];
+    }
+    if (!fn) {
+        return;
+    }
+
+    src_width = (s->xres + 3) & ~3;     /* Pad to a 4 pixels multiple */
+    if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) {
+        src_width *= 3;
+    } else if (s->bpp > pxa_lcdc_16bpp) {
+        src_width *= 4;
+    } else if (s->bpp > pxa_lcdc_8bpp) {
+        src_width *= 2;
+    }
+
+    dest_width = s->xres * s->dest_width;
+    *miny = 0;
+    framebuffer_update_display(s->ds,
+                               addr, s->xres, s->yres,
+                               src_width, -dest_width, -s->dest_width,
+                               s->invalidated,
+                               fn, s->dma_ch[0].palette, miny, maxy);
+}
+
+static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s,
+               target_phys_addr_t addr, int *miny, int *maxy)
+{
+    int src_width, dest_width;
+    drawfn fn = NULL;
+    if (s->dest_width) {
+        fn = s->line_fn[s->transp][s->bpp];
+    }
+    if (!fn) {
+        return;
+    }
+
+    src_width = (s->xres + 3) & ~3;     /* Pad to a 4 pixels multiple */
+    if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) {
+        src_width *= 3;
+    } else if (s->bpp > pxa_lcdc_16bpp) {
+        src_width *= 4;
+    } else if (s->bpp > pxa_lcdc_8bpp) {
+        src_width *= 2;
+    }
+
+    dest_width = s->yres * s->dest_width;
+    *miny = 0;
+    framebuffer_update_display(s->ds,
+                               addr, s->xres, s->yres,
+                               src_width, -s->dest_width, dest_width,
+                               s->invalidated,
+                               fn, s->dma_ch[0].palette,
+                               miny, maxy);
+}
+
 static void pxa2xx_lcdc_resize(PXA2xxLCDState *s)
 {
     int width, height;
@@ -730,10 +791,11 @@  static void pxa2xx_lcdc_resize(PXA2xxLCDState *s)
     height = LCCR2_LPP(s->control[2]) + 1;
 
     if (width != s->xres || height != s->yres) {
-        if (s->orientation)
+        if (s->orientation == 90 || s->orientation == 270) {
             qemu_console_resize(s->ds, height, width);
-        else
+        } else {
             qemu_console_resize(s->ds, width, height);
+        }
         s->invalidated = 1;
         s->xres = width;
         s->yres = height;
@@ -797,10 +859,24 @@  static void pxa2xx_update_display(void *opaque)
     }
 
     if (miny >= 0) {
-        if (s->orientation)
-            dpy_update(s->ds, miny, 0, maxy - miny, s->xres);
-        else
-            dpy_update(s->ds, 0, miny, s->xres, maxy - miny);
+        switch (s->orientation) {
+        case 0:
+            dpy_update(s->ds, 0, miny, s->xres, maxy - miny + 1);
+            break;
+        case 90:
+            dpy_update(s->ds, miny, 0, maxy - miny + 1, s->xres);
+            break;
+        case 180:
+            maxy = s->yres - maxy - 1;
+            miny = s->yres - miny - 1;
+            dpy_update(s->ds, 0, maxy, s->xres, miny - maxy + 1);
+            break;
+        case 270:
+            maxy = s->yres - maxy - 1;
+            miny = s->yres - miny - 1;
+            dpy_update(s->ds, maxy, 0, miny - maxy + 1, s->xres);
+            break;
+        }
     }
     pxa2xx_lcdc_int_update(s);
 
@@ -822,10 +898,19 @@  static void pxa2xx_lcdc_orientation(void *opaque, int angle)
 {
     PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
 
-    if (angle) {
-        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_vert;
-    } else {
-        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_horiz;
+    switch (angle) {
+    case 0:
+        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot0;
+        break;
+    case 90:
+        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot90;
+        break;
+    case 180:
+        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot180;
+        break;
+    case 270:
+        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot270;
+        break;
     }
 
     s->orientation = angle;
diff --git a/input.c b/input.c
index 5664d3a..f0a02e7 100644
--- a/input.c
+++ b/input.c
@@ -148,7 +148,7 @@  void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
     QEMUPutMouseEntry *entry;
     QEMUPutMouseEvent *mouse_event;
     void *mouse_event_opaque;
-    int width;
+    int width, height;
 
     if (QTAILQ_EMPTY(&mouse_handlers)) {
         return;
@@ -160,15 +160,31 @@  void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
     mouse_event_opaque = entry->qemu_put_mouse_event_opaque;
 
     if (mouse_event) {
-        if (graphic_rotate) {
-            if (entry->qemu_put_mouse_event_absolute) {
-                width = 0x7fff;
-            } else {
-                width = graphic_width - 1;
-            }
-            mouse_event(mouse_event_opaque, width - dy, dx, dz, buttons_state);
+        if (entry->qemu_put_mouse_event_absolute) {
+            width = 0x7fff;
+            height = 0x7fff;
         } else {
-            mouse_event(mouse_event_opaque, dx, dy, dz, buttons_state);
+            width = graphic_width - 1;
+            height = graphic_height - 1;
+        }
+
+        switch (graphic_rotate) {
+        case 0:
+            mouse_event(mouse_event_opaque,
+                        dx, dy, dz, buttons_state);
+            break;
+        case 90:
+            mouse_event(mouse_event_opaque,
+                        width - dy, dx, dz, buttons_state);
+            break;
+        case 180:
+            mouse_event(mouse_event_opaque,
+                        width - dx, height - dy, dz, buttons_state);
+            break;
+        case 270:
+            mouse_event(mouse_event_opaque,
+                        dy, height - dx, dz, buttons_state);
+            break;
         }
     }
 }
diff --git a/qemu-options.hx b/qemu-options.hx
index 82e085a..46d8f25 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -771,6 +771,15 @@  STEXI
 Rotate graphical output 90 deg left (only PXA LCD).
 ETEXI
 
+DEF("rotate", HAS_ARG, QEMU_OPTION_rotate,
+    "-rotate <deg>   rotate graphical output some deg left (only PXA LCD)\n",
+    QEMU_ARCH_ALL)
+STEXI
+@item -rotate
+@findex -rotate
+Rotate graphical output some deg left (only PXA LCD).
+ETEXI
+
 DEF("vga", HAS_ARG, QEMU_OPTION_vga,
     "-vga [std|cirrus|vmware|qxl|xenfb|none]\n"
     "                select video card type\n", QEMU_ARCH_ALL)
diff --git a/vl.c b/vl.c
index b362871..c11cc44 100644
--- a/vl.c
+++ b/vl.c
@@ -2289,7 +2289,16 @@  int main(int argc, char **argv, char **envp)
 #endif
                 break;
             case QEMU_OPTION_portrait:
-                graphic_rotate = 1;
+                graphic_rotate = 90;
+                break;
+            case QEMU_OPTION_rotate:
+                graphic_rotate = strtol(optarg, (char **)&optarg, 10);
+                if (graphic_rotate != 0 && graphic_rotate != 90 &&
+                    graphic_rotate != 180 && graphic_rotate != 270) {
+                    fprintf(stderr,
+                        "qemu: only 90, 180, 270 deg rotation is available\n");
+                    exit(1);
+                }
                 break;
             case QEMU_OPTION_kernel:
                 kernel_filename = optarg;