mirror of https://gitee.com/openkylin/qemu.git
pxa2xx_lcd: add proper rotation support
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> Signed-off-by: Andrzej Zaborowski <andrew.zaborowski@intel.com>
This commit is contained in:
parent
462a8bc646
commit
9312805d33
|
@ -78,6 +78,9 @@ void framebuffer_update_display(
|
||||||
dest = ds_get_data(ds);
|
dest = ds_get_data(ds);
|
||||||
if (dest_col_pitch < 0)
|
if (dest_col_pitch < 0)
|
||||||
dest -= dest_col_pitch * (cols - 1);
|
dest -= dest_col_pitch * (cols - 1);
|
||||||
|
if (dest_row_pitch < 0) {
|
||||||
|
dest -= dest_row_pitch * (rows - 1);
|
||||||
|
}
|
||||||
first = -1;
|
first = -1;
|
||||||
addr = pd;
|
addr = pd;
|
||||||
|
|
||||||
|
|
109
hw/pxa2xx_lcd.c
109
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)
|
target_phys_addr_t addr, int *miny, int *maxy)
|
||||||
{
|
{
|
||||||
int src_width, dest_width;
|
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);
|
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)
|
target_phys_addr_t addr, int *miny, int *maxy)
|
||||||
{
|
{
|
||||||
int src_width, dest_width;
|
int src_width, dest_width;
|
||||||
|
@ -720,6 +720,67 @@ static void pxa2xx_lcdc_dma0_redraw_vert(PXA2xxLCDState *s,
|
||||||
miny, maxy);
|
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)
|
static void pxa2xx_lcdc_resize(PXA2xxLCDState *s)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
|
@ -730,10 +791,11 @@ static void pxa2xx_lcdc_resize(PXA2xxLCDState *s)
|
||||||
height = LCCR2_LPP(s->control[2]) + 1;
|
height = LCCR2_LPP(s->control[2]) + 1;
|
||||||
|
|
||||||
if (width != s->xres || height != s->yres) {
|
if (width != s->xres || height != s->yres) {
|
||||||
if (s->orientation)
|
if (s->orientation == 90 || s->orientation == 270) {
|
||||||
qemu_console_resize(s->ds, height, width);
|
qemu_console_resize(s->ds, height, width);
|
||||||
else
|
} else {
|
||||||
qemu_console_resize(s->ds, width, height);
|
qemu_console_resize(s->ds, width, height);
|
||||||
|
}
|
||||||
s->invalidated = 1;
|
s->invalidated = 1;
|
||||||
s->xres = width;
|
s->xres = width;
|
||||||
s->yres = height;
|
s->yres = height;
|
||||||
|
@ -797,10 +859,24 @@ static void pxa2xx_update_display(void *opaque)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (miny >= 0) {
|
if (miny >= 0) {
|
||||||
if (s->orientation)
|
switch (s->orientation) {
|
||||||
dpy_update(s->ds, miny, 0, maxy - miny, s->xres);
|
case 0:
|
||||||
else
|
dpy_update(s->ds, 0, miny, s->xres, maxy - miny + 1);
|
||||||
dpy_update(s->ds, 0, miny, s->xres, maxy - miny);
|
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);
|
pxa2xx_lcdc_int_update(s);
|
||||||
|
|
||||||
|
@ -822,10 +898,19 @@ static void pxa2xx_lcdc_orientation(void *opaque, int angle)
|
||||||
{
|
{
|
||||||
PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
|
PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
|
||||||
|
|
||||||
if (angle) {
|
switch (angle) {
|
||||||
s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_vert;
|
case 0:
|
||||||
} else {
|
s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot0;
|
||||||
s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_horiz;
|
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;
|
s->orientation = angle;
|
||||||
|
|
26
input.c
26
input.c
|
@ -148,7 +148,7 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
|
||||||
QEMUPutMouseEntry *entry;
|
QEMUPutMouseEntry *entry;
|
||||||
QEMUPutMouseEvent *mouse_event;
|
QEMUPutMouseEvent *mouse_event;
|
||||||
void *mouse_event_opaque;
|
void *mouse_event_opaque;
|
||||||
int width;
|
int width, height;
|
||||||
|
|
||||||
if (QTAILQ_EMPTY(&mouse_handlers)) {
|
if (QTAILQ_EMPTY(&mouse_handlers)) {
|
||||||
return;
|
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;
|
mouse_event_opaque = entry->qemu_put_mouse_event_opaque;
|
||||||
|
|
||||||
if (mouse_event) {
|
if (mouse_event) {
|
||||||
if (graphic_rotate) {
|
|
||||||
if (entry->qemu_put_mouse_event_absolute) {
|
if (entry->qemu_put_mouse_event_absolute) {
|
||||||
width = 0x7fff;
|
width = 0x7fff;
|
||||||
|
height = 0x7fff;
|
||||||
} else {
|
} else {
|
||||||
width = graphic_width - 1;
|
width = graphic_width - 1;
|
||||||
|
height = graphic_height - 1;
|
||||||
}
|
}
|
||||||
mouse_event(mouse_event_opaque, width - dy, dx, dz, buttons_state);
|
|
||||||
} else {
|
switch (graphic_rotate) {
|
||||||
mouse_event(mouse_event_opaque, dx, dy, dz, buttons_state);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -787,6 +787,15 @@ STEXI
|
||||||
Rotate graphical output 90 deg left (only PXA LCD).
|
Rotate graphical output 90 deg left (only PXA LCD).
|
||||||
ETEXI
|
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,
|
DEF("vga", HAS_ARG, QEMU_OPTION_vga,
|
||||||
"-vga [std|cirrus|vmware|qxl|xenfb|none]\n"
|
"-vga [std|cirrus|vmware|qxl|xenfb|none]\n"
|
||||||
" select video card type\n", QEMU_ARCH_ALL)
|
" select video card type\n", QEMU_ARCH_ALL)
|
||||||
|
|
11
vl.c
11
vl.c
|
@ -2300,7 +2300,16 @@ int main(int argc, char **argv, char **envp)
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_portrait:
|
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;
|
break;
|
||||||
case QEMU_OPTION_kernel:
|
case QEMU_OPTION_kernel:
|
||||||
kernel_filename = optarg;
|
kernel_filename = optarg;
|
||||||
|
|
Loading…
Reference in New Issue