Message ID | 1273063904-6028-2-git-send-email-kraxel@redhat.com |
---|---|
State | New |
Headers | show |
On 5/5/10, Gerd Hoffmann <kraxel@redhat.com> wrote: > Add a new cursor type to console.h and a bunch of functions to > deal with cursors the (new) cursor.c file. > > Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> > --- > Makefile.objs | 3 +- > console.h | 24 ++++++- > cursor.c | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 232 insertions(+), 3 deletions(-) > create mode 100644 cursor.c > > diff --git a/Makefile.objs b/Makefile.objs > index ecdd53e..1ee6e9d 100644 > --- a/Makefile.objs > +++ b/Makefile.objs > @@ -48,7 +48,8 @@ common-obj-y = $(block-obj-y) > common-obj-y += $(net-obj-y) > common-obj-y += $(qobject-obj-y) > common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX)) > -common-obj-y += readline.o console.o async.o qemu-error.o > +common-obj-y += readline.o console.o cursor.o async.o qemu-error.o > + > common-obj-y += tcg-runtime.o host-utils.o > common-obj-y += irq.o ioport.o input.o > common-obj-$(CONFIG_PTIMER) += ptimer.o > diff --git a/console.h b/console.h > index 6def115..88861cb 100644 > --- a/console.h > +++ b/console.h > @@ -126,6 +126,27 @@ struct DisplaySurface { > struct PixelFormat pf; > }; > > +/* cursor data format is 32bit RGBA */ > +typedef struct QEMUCursor { > + int width, height; > + int hot_x, hot_y; > + int refcount; > + uint32_t data[]; > +} QEMUCursor; > + > +QEMUCursor *cursor_alloc(int width, int height); > +void cursor_get(QEMUCursor *c); > +void cursor_put(QEMUCursor *c); > +QEMUCursor *cursor_builtin_hidden(void); > +QEMUCursor *cursor_builtin_left_ptr(void); > +void cursor_print_ascii_art(QEMUCursor *c, const char *prefix); > +int cursor_get_mono_bpl(QEMUCursor *c); > +void cursor_set_mono(QEMUCursor *c, > + uint32_t foreground, uint32_t background, uint8_t *image, > + int transparent, uint8_t *mask); > +void cursor_get_mono_image(QEMUCursor *c, int foreground, uint8_t *mask); > +void cursor_get_mono_mask(QEMUCursor *c, int transparent, uint8_t *mask); > + > struct DisplayChangeListener { > int idle; > uint64_t gui_timer_interval; > @@ -158,8 +179,7 @@ struct DisplayState { > struct DisplayChangeListener* listeners; > > void (*mouse_set)(int x, int y, int on); > - void (*cursor_define)(int width, int height, int bpp, int hot_x, int hot_y, > - uint8_t *image, uint8_t *mask); > + void (*cursor_define)(QEMUCursor *cursor); > > struct DisplayState *next; > }; > diff --git a/cursor.c b/cursor.c > new file mode 100644 > index 0000000..3995a31 > --- /dev/null > +++ b/cursor.c > @@ -0,0 +1,208 @@ > +#include "qemu-common.h" > +#include "console.h" > + > +static const char cursor_hidden_32[32*32]; > +static const char cursor_left_ptr_32[32*32] = { > + " " > + " X " > + " XX " > + " X.X " > + " X..X " > + " X...X " > + " X....X " > + " X.....X " > + " X......X " > + " X.......X " > + " X........X " > + " X.....XXXXX " > + " X..X..X " > + " X.X X..X " > + " XX X..X " > + " X X..X " > + " X..X " > + " X..X " > + " X..X " > + " XX " > + " " > +}; Is this format standard? How about using X bitmap format instead: $ cat /usr/include/X11/bitmaps/left_ptr #define left_ptr_width 16 #define left_ptr_height 16 #define left_ptr_x_hot 3 #define left_ptr_y_hot 1 static char left_ptr_bits[] = { 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01, 0xf8, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0xd8, 0x00, 0x88, 0x01, 0x80, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00}; Then there would be no need of parsing. > + > +/* for creating built-in cursors */ > +static void cursor_parse_ascii_art(QEMUCursor *c, const char *ptr) > +{ > + int i, pixels; > + > + pixels = c->width * c->height; > + for (i = 0; i < pixels; i++) { > + switch (ptr[i]) { > + case 'X': /* black */ > + c->data[i] = 0xff000000; > + break; > + case '.': /* white */ > + c->data[i] = 0xffffffff; > + break; > + case ' ': /* transparent */ > + default: > + c->data[i] = 0x00000000; > + break; > + } > + } > +} > + > +/* nice for debugging */ > +void cursor_print_ascii_art(QEMUCursor *c, const char *prefix) > +{ > + uint32_t *data = c->data; > + int x,y; > + > + for (y = 0; y < c->height; y++) { > + fprintf(stderr, "%s: %2d: |", prefix, y); > + for (x = 0; x < c->width; x++, data++) { > + if ((*data & 0xff000000) != 0xff000000) { > + fprintf(stderr, " "); /* transparent */ > + } else if ((*data & 0x00ffffff) == 0x00ffffff) { > + fprintf(stderr, "."); /* white */ > + } else if ((*data & 0x00ffffff) == 0x00000000) { > + fprintf(stderr, "X"); /* black */ > + } else { > + fprintf(stderr, "o"); /* other */ > + } > + } > + fprintf(stderr, "|\n"); > + } > +} > + > +QEMUCursor *cursor_builtin_hidden(void) > +{ > + QEMUCursor *c; > + > + c = cursor_alloc(32, 32); > + cursor_parse_ascii_art(c, cursor_hidden_32); > + return c; > +} > + > +QEMUCursor *cursor_builtin_left_ptr(void) > +{ > + QEMUCursor *c; > + > + c = cursor_alloc(32, 32); > + cursor_parse_ascii_art(c, cursor_left_ptr_32); > + c->hot_x = 1; > + c->hot_y = 1; > + return c; > +} > + > +QEMUCursor *cursor_alloc(int width, int height) > +{ > + QEMUCursor *c; > + int datasize = width * height * sizeof(uint32_t); > + > + c = qemu_mallocz(sizeof(QEMUCursor) + datasize); > + c->width = width; > + c->height = height; > + c->refcount = 1; > + return c; > +} > + > +void cursor_get(QEMUCursor *c) > +{ > + c->refcount++; > +} > + > +void cursor_put(QEMUCursor *c) > +{ > + if (c == NULL) > + return; > + c->refcount--; > + if (c->refcount) > + return; > + qemu_free(c); > +} > + > +int cursor_get_mono_bpl(QEMUCursor *c) > +{ > + return (c->width + 7) / 8; > +} > + > +void cursor_set_mono(QEMUCursor *c, > + uint32_t foreground, uint32_t background, uint8_t *image, > + int transparent, uint8_t *mask) > +{ > + uint32_t *data = c->data; > + uint8_t bit; > + int x,y,bpl; > + > + bpl = cursor_get_mono_bpl(c); > + for (y = 0; y < c->height; y++) { > + bit = 0x80; > + for (x = 0; x < c->width; x++, data++) { > + if (transparent && mask[x/8] & bit) { > + *data = 0x00000000; > + } else if (!transparent && !(mask[x/8] & bit)) { > + *data = 0x00000000; > + } else if (image[x/8] & bit) { > + *data = 0xff000000 | foreground; > + } else { > + *data = 0xff000000 | background; > + } > + bit >>= 1; > + if (bit == 0) { > + bit = 0x80; > + } > + } > + mask += bpl; > + image += bpl; > + } > +} > + > +void cursor_get_mono_image(QEMUCursor *c, int foreground, uint8_t *image) > +{ > + uint32_t *data = c->data; > + uint8_t bit; > + int x,y,bpl; > + > + bpl = cursor_get_mono_bpl(c); > + memset(image, 0, bpl * c->height); > + for (y = 0; y < c->height; y++) { > + bit = 0x80; > + for (x = 0; x < c->width; x++, data++) { > + if (((*data & 0xff000000) == 0xff000000) && > + ((*data & 0x00ffffff) == foreground)) { > + image[x/8] |= bit; > + } > + bit >>= 1; > + if (bit == 0) { > + bit = 0x80; > + } > + } > + image += bpl; > + } > +} > + > +void cursor_get_mono_mask(QEMUCursor *c, int transparent, uint8_t *mask) > +{ > + uint32_t *data = c->data; > + uint8_t bit; > + int x,y,bpl; > + > + bpl = cursor_get_mono_bpl(c); > + memset(mask, 0, bpl * c->height); > + for (y = 0; y < c->height; y++) { > + bit = 0x80; > + for (x = 0; x < c->width; x++, data++) { > + if ((*data & 0xff000000) != 0xff000000) { > + if (transparent != 0) { > + mask[x/8] |= bit; > + } > + } else { > + if (transparent == 0) { > + mask[x/8] |= bit; > + } > + } > + bit >>= 1; > + if (bit == 0) { > + bit = 0x80; > + } > + } > + mask += bpl; > + } > +} > > -- > 1.6.6.1 > > > >
>> +static const char cursor_left_ptr_32[32*32] = { >> + " " >> + " X " >> + " XX " >> + " X.X " >> + " X..X " >> + " X...X " >> + " X....X " >> + " X.....X " >> + " X......X " >> + " X.......X " >> + " X........X " >> + " X.....XXXXX " >> + " X..X..X " >> + " X.X X..X " >> + " XX X..X " >> + " X X..X " >> + " X..X " >> + " X..X " >> + " X..X " >> + " XX " >> + " " >> +}; > > Is this format standard? Inspiried by xpm but simplified a bit as full xpm support just for a built-in fallback cursor would have been overkill. The nice thing about xpm is that you can use any text editor for editing icons. > How about using X bitmap format instead: > $ cat /usr/include/X11/bitmaps/left_ptr > Then there would be no need of parsing. Well. You still would have to convert it as qemu internal cursor format is defined as 32bit depth, rgb with alpha channel. So it doesn't buy you that much. cheers, Gerd
On 5/6/10, Gerd Hoffmann <kraxel@redhat.com> wrote: > > > > > +static const char cursor_left_ptr_32[32*32] = { > > > + " " > > > + " X " > > > + " XX " > > > + " X.X " > > > + " X..X " > > > + " X...X " > > > + " X....X " > > > + " X.....X " > > > + " X......X " > > > + " X.......X " > > > + " X........X " > > > + " X.....XXXXX " > > > + " X..X..X " > > > + " X.X X..X " > > > + " XX X..X " > > > + " X X..X " > > > + " X..X " > > > + " X..X " > > > + " X..X " > > > + " XX " > > > + " " > > > +}; > > > > > > > Is this format standard? > > > > Inspiried by xpm but simplified a bit as full xpm support just for a > built-in fallback cursor would have been overkill. The nice thing about xpm > is that you can use any text editor for editing icons. But for X bitmaps, you can use any real drawing program. The same would also apply to full xpm. But read on. > > How about using X bitmap format instead: > > $ cat /usr/include/X11/bitmaps/left_ptr > > > > > > Then there would be no need of parsing. > > > > Well. You still would have to convert it as qemu internal cursor format is > defined as 32bit depth, rgb with alpha channel. So it doesn't buy you that > much. There's still more wasted memory compared to binary format. I think the best would be to store only the 32 bit image and perform any conversions offline. This was the approach with for example keyboard tables, we don't convert them at startup but the original tables are retained as comments.
On 05/06/2010 08:12 PM, Blue Swirl wrote: > On 5/5/10, Gerd Hoffmann<kraxel@redhat.com> wrote: >> Add a new cursor type to console.h and a bunch of functions to >> deal with cursors the (new) cursor.c file. >> >> Signed-off-by: Gerd Hoffmann<kraxel@redhat.com> >> --- >> Makefile.objs | 3 +- >> console.h | 24 ++++++- >> cursor.c | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 232 insertions(+), 3 deletions(-) >> create mode 100644 cursor.c >> >> diff --git a/Makefile.objs b/Makefile.objs >> index ecdd53e..1ee6e9d 100644 >> --- a/Makefile.objs >> +++ b/Makefile.objs >> @@ -48,7 +48,8 @@ common-obj-y = $(block-obj-y) >> common-obj-y += $(net-obj-y) >> common-obj-y += $(qobject-obj-y) >> common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX)) >> -common-obj-y += readline.o console.o async.o qemu-error.o >> +common-obj-y += readline.o console.o cursor.o async.o qemu-error.o >> + >> common-obj-y += tcg-runtime.o host-utils.o >> common-obj-y += irq.o ioport.o input.o >> common-obj-$(CONFIG_PTIMER) += ptimer.o >> diff --git a/console.h b/console.h >> index 6def115..88861cb 100644 >> --- a/console.h >> +++ b/console.h >> @@ -126,6 +126,27 @@ struct DisplaySurface { >> struct PixelFormat pf; >> }; >> >> +/* cursor data format is 32bit RGBA */ >> +typedef struct QEMUCursor { >> + int width, height; >> + int hot_x, hot_y; >> + int refcount; >> + uint32_t data[]; >> +} QEMUCursor; >> + >> +QEMUCursor *cursor_alloc(int width, int height); >> +void cursor_get(QEMUCursor *c); >> +void cursor_put(QEMUCursor *c); >> +QEMUCursor *cursor_builtin_hidden(void); >> +QEMUCursor *cursor_builtin_left_ptr(void); >> +void cursor_print_ascii_art(QEMUCursor *c, const char *prefix); >> +int cursor_get_mono_bpl(QEMUCursor *c); >> +void cursor_set_mono(QEMUCursor *c, >> + uint32_t foreground, uint32_t background, uint8_t *image, >> + int transparent, uint8_t *mask); >> +void cursor_get_mono_image(QEMUCursor *c, int foreground, uint8_t *mask); >> +void cursor_get_mono_mask(QEMUCursor *c, int transparent, uint8_t *mask); >> + >> struct DisplayChangeListener { >> int idle; >> uint64_t gui_timer_interval; >> @@ -158,8 +179,7 @@ struct DisplayState { >> struct DisplayChangeListener* listeners; >> >> void (*mouse_set)(int x, int y, int on); >> - void (*cursor_define)(int width, int height, int bpp, int hot_x, int hot_y, >> - uint8_t *image, uint8_t *mask); >> + void (*cursor_define)(QEMUCursor *cursor); >> >> struct DisplayState *next; >> }; >> diff --git a/cursor.c b/cursor.c >> new file mode 100644 >> index 0000000..3995a31 >> --- /dev/null >> +++ b/cursor.c >> @@ -0,0 +1,208 @@ >> +#include "qemu-common.h" >> +#include "console.h" >> + >> +static const char cursor_hidden_32[32*32]; >> +static const char cursor_left_ptr_32[32*32] = { >> + " " >> + " X " >> + " XX " >> + " X.X " >> + " X..X " >> + " X...X " >> + " X....X " >> + " X.....X " >> + " X......X " >> + " X.......X " >> + " X........X " >> + " X.....XXXXX " >> + " X..X..X " >> + " X.X X..X " >> + " XX X..X " >> + " X X..X " >> + " X..X " >> + " X..X " >> + " X..X " >> + " XX " >> + " " >> +}; > > Is this format standard? How about using X bitmap format instead: > $ cat /usr/include/X11/bitmaps/left_ptr > #define left_ptr_width 16 > #define left_ptr_height 16 > #define left_ptr_x_hot 3 > #define left_ptr_y_hot 1 > static char left_ptr_bits[] = { > 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, > 0xf8, 0x01, 0xf8, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0xd8, 0x00, 0x88, 0x01, > 0x80, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00}; > > Then there would be no need of parsing. You would need _two_ bitmaps (e.g. mask and cursor, so that mask=1 gives transparent, mask=0 cursor=0 gives black and mask=0 cursor=1 gives white). Paolo
On 5/7/10, Paolo Bonzini <pbonzini@redhat.com> wrote: > On 05/06/2010 08:12 PM, Blue Swirl wrote: > > > On 5/5/10, Gerd Hoffmann<kraxel@redhat.com> wrote: > > > > > Add a new cursor type to console.h and a bunch of functions to > > > deal with cursors the (new) cursor.c file. > > > > > > Signed-off-by: Gerd Hoffmann<kraxel@redhat.com> > > > --- > > > Makefile.objs | 3 +- > > > console.h | 24 ++++++- > > > cursor.c | 208 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > > > 3 files changed, 232 insertions(+), 3 deletions(-) > > > create mode 100644 cursor.c > > > > > > diff --git a/Makefile.objs b/Makefile.objs > > > index ecdd53e..1ee6e9d 100644 > > > --- a/Makefile.objs > > > +++ b/Makefile.objs > > > @@ -48,7 +48,8 @@ common-obj-y = $(block-obj-y) > > > common-obj-y += $(net-obj-y) > > > common-obj-y += $(qobject-obj-y) > > > common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX)) > > > -common-obj-y += readline.o console.o async.o qemu-error.o > > > +common-obj-y += readline.o console.o cursor.o async.o qemu-error.o > > > + > > > common-obj-y += tcg-runtime.o host-utils.o > > > common-obj-y += irq.o ioport.o input.o > > > common-obj-$(CONFIG_PTIMER) += ptimer.o > > > diff --git a/console.h b/console.h > > > index 6def115..88861cb 100644 > > > --- a/console.h > > > +++ b/console.h > > > @@ -126,6 +126,27 @@ struct DisplaySurface { > > > struct PixelFormat pf; > > > }; > > > > > > +/* cursor data format is 32bit RGBA */ > > > +typedef struct QEMUCursor { > > > + int width, height; > > > + int hot_x, hot_y; > > > + int refcount; > > > + uint32_t data[]; > > > +} QEMUCursor; > > > + > > > +QEMUCursor *cursor_alloc(int width, int height); > > > +void cursor_get(QEMUCursor *c); > > > +void cursor_put(QEMUCursor *c); > > > +QEMUCursor *cursor_builtin_hidden(void); > > > +QEMUCursor *cursor_builtin_left_ptr(void); > > > +void cursor_print_ascii_art(QEMUCursor *c, const char > *prefix); > > > +int cursor_get_mono_bpl(QEMUCursor *c); > > > +void cursor_set_mono(QEMUCursor *c, > > > + uint32_t foreground, uint32_t background, uint8_t > *image, > > > + int transparent, uint8_t *mask); > > > +void cursor_get_mono_image(QEMUCursor *c, int > foreground, uint8_t *mask); > > > +void cursor_get_mono_mask(QEMUCursor *c, int > transparent, uint8_t *mask); > > > + > > > struct DisplayChangeListener { > > > int idle; > > > uint64_t gui_timer_interval; > > > @@ -158,8 +179,7 @@ struct DisplayState { > > > struct DisplayChangeListener* listeners; > > > > > > void (*mouse_set)(int x, int y, int on); > > > - void (*cursor_define)(int width, int height, int bpp, int hot_x, > int hot_y, > > > - uint8_t *image, uint8_t *mask); > > > + void (*cursor_define)(QEMUCursor *cursor); > > > > > > struct DisplayState *next; > > > }; > > > diff --git a/cursor.c b/cursor.c > > > new file mode 100644 > > > index 0000000..3995a31 > > > --- /dev/null > > > +++ b/cursor.c > > > @@ -0,0 +1,208 @@ > > > +#include "qemu-common.h" > > > +#include "console.h" > > > + > > > +static const char cursor_hidden_32[32*32]; > > > +static const char cursor_left_ptr_32[32*32] = { > > > + " " > > > + " X " > > > + " XX " > > > + " X.X " > > > + " X..X " > > > + " X...X " > > > + " X....X " > > > + " X.....X " > > > + " X......X " > > > + " X.......X " > > > + " X........X " > > > + " X.....XXXXX " > > > + " X..X..X " > > > + " X.X X..X " > > > + " XX X..X " > > > + " X X..X " > > > + " X..X " > > > + " X..X " > > > + " X..X " > > > + " XX " > > > + " " > > > +}; > > > > > > > Is this format standard? How about using X bitmap format instead: > > $ cat /usr/include/X11/bitmaps/left_ptr > > #define left_ptr_width 16 > > #define left_ptr_height 16 > > #define left_ptr_x_hot 3 > > #define left_ptr_y_hot 1 > > static char left_ptr_bits[] = { > > 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, > > 0xf8, 0x01, 0xf8, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0xd8, 0x00, 0x88, 0x01, > > 0x80, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00}; > > > > Then there would be no need of parsing. > > > > You would need _two_ bitmaps (e.g. mask and cursor, so that mask=1 gives > transparent, mask=0 cursor=0 gives black and mask=0 cursor=1 gives white). Yes, but it's still packed more efficiently. There's yet another way: #define _ 0, #define X 0xff000000, #define o 0xffffffff, { _ _ _ X o X _ _ _ } #undef _ #undef X #undef o This would not allow any drawing tool use, but there are no conversions at startup.
>>> Then there would be no need of parsing. >> >> You would need _two_ bitmaps (e.g. mask and cursor, so that mask=1 gives >> transparent, mask=0 cursor=0 gives black and mask=0 cursor=1 gives white). > > Yes, but it's still packed more efficiently. Well. You can't have both. We can have a efficiently packed format (i.e. two bitmaps). Or we can do it in a way which doesn't need parsing, but that wouldn't be the most compact format ... > There's yet another way: > #define _ 0, > #define X 0xff000000, > #define o 0xffffffff, > { > _ _ _ X o X _ _ _ > } > #undef _ > #undef X > #undef o Neat idea ;) cheers, Gerd
On 5/19/10, Gerd Hoffmann <kraxel@redhat.com> wrote: > > > > > > > > > Then there would be no need of parsing. > > > > > > > > > > You would need _two_ bitmaps (e.g. mask and cursor, so that mask=1 > gives > > > transparent, mask=0 cursor=0 gives black and mask=0 cursor=1 gives > white). > > > > > > > Yes, but it's still packed more efficiently. > > > > Well. You can't have both. We can have a efficiently packed format (i.e. > two bitmaps). Or we can do it in a way which doesn't need parsing, but that > wouldn't be the most compact format ... You're right, so packing or introducing a small conversion function is not critical. I'd still prefer a standard format if possible. > > There's yet another way: > > #define _ 0, > > #define X 0xff000000, > > #define o 0xffffffff, > > { > > _ _ _ X o X _ _ _ > > } > > #undef _ > > #undef X > > #undef o > > > > Neat idea ;) > > cheers, > Gerd > >
On 05/19/2010 01:57 PM, Blue Swirl wrote: > On 5/19/10, Gerd Hoffmann<kraxel@redhat.com> wrote: > >>> >>>> >>>>> Then there would be no need of parsing. >>>>> >>>>> >>>> You would need _two_ bitmaps (e.g. mask and cursor, so that mask=1 >>>> >> gives >> >>>> transparent, mask=0 cursor=0 gives black and mask=0 cursor=1 gives >>>> >> white). >> >>>> >>> Yes, but it's still packed more efficiently. >>> >>> >> Well. You can't have both. We can have a efficiently packed format (i.e. >> two bitmaps). Or we can do it in a way which doesn't need parsing, but that >> wouldn't be the most compact format ... >> > You're right, so packing or introducing a small conversion function is > not critical. I'd still prefer a standard format if possible. > Personally, I'd rather see Gerd's original format but read from a file instead of hard coded in a .c file. IOW, a /usr/share/qemu/default-cursor.qpm that contained the appropriate strings. A couple extra lines that made it an xpm I think would be worth it too. Regards, Anthony Liguori >>> There's yet another way: >>> #define _ 0, >>> #define X 0xff000000, >>> #define o 0xffffffff, >>> { >>> _ _ _ X o X _ _ _ >>> } >>> #undef _ >>> #undef X >>> #undef o >>> >>> >> Neat idea ;) >> >> cheers, >> Gerd >> >> >> >
diff --git a/Makefile.objs b/Makefile.objs index ecdd53e..1ee6e9d 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -48,7 +48,8 @@ common-obj-y = $(block-obj-y) common-obj-y += $(net-obj-y) common-obj-y += $(qobject-obj-y) common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX)) -common-obj-y += readline.o console.o async.o qemu-error.o +common-obj-y += readline.o console.o cursor.o async.o qemu-error.o + common-obj-y += tcg-runtime.o host-utils.o common-obj-y += irq.o ioport.o input.o common-obj-$(CONFIG_PTIMER) += ptimer.o diff --git a/console.h b/console.h index 6def115..88861cb 100644 --- a/console.h +++ b/console.h @@ -126,6 +126,27 @@ struct DisplaySurface { struct PixelFormat pf; }; +/* cursor data format is 32bit RGBA */ +typedef struct QEMUCursor { + int width, height; + int hot_x, hot_y; + int refcount; + uint32_t data[]; +} QEMUCursor; + +QEMUCursor *cursor_alloc(int width, int height); +void cursor_get(QEMUCursor *c); +void cursor_put(QEMUCursor *c); +QEMUCursor *cursor_builtin_hidden(void); +QEMUCursor *cursor_builtin_left_ptr(void); +void cursor_print_ascii_art(QEMUCursor *c, const char *prefix); +int cursor_get_mono_bpl(QEMUCursor *c); +void cursor_set_mono(QEMUCursor *c, + uint32_t foreground, uint32_t background, uint8_t *image, + int transparent, uint8_t *mask); +void cursor_get_mono_image(QEMUCursor *c, int foreground, uint8_t *mask); +void cursor_get_mono_mask(QEMUCursor *c, int transparent, uint8_t *mask); + struct DisplayChangeListener { int idle; uint64_t gui_timer_interval; @@ -158,8 +179,7 @@ struct DisplayState { struct DisplayChangeListener* listeners; void (*mouse_set)(int x, int y, int on); - void (*cursor_define)(int width, int height, int bpp, int hot_x, int hot_y, - uint8_t *image, uint8_t *mask); + void (*cursor_define)(QEMUCursor *cursor); struct DisplayState *next; }; diff --git a/cursor.c b/cursor.c new file mode 100644 index 0000000..3995a31 --- /dev/null +++ b/cursor.c @@ -0,0 +1,208 @@ +#include "qemu-common.h" +#include "console.h" + +static const char cursor_hidden_32[32*32]; +static const char cursor_left_ptr_32[32*32] = { + " " + " X " + " XX " + " X.X " + " X..X " + " X...X " + " X....X " + " X.....X " + " X......X " + " X.......X " + " X........X " + " X.....XXXXX " + " X..X..X " + " X.X X..X " + " XX X..X " + " X X..X " + " X..X " + " X..X " + " X..X " + " XX " + " " +}; + +/* for creating built-in cursors */ +static void cursor_parse_ascii_art(QEMUCursor *c, const char *ptr) +{ + int i, pixels; + + pixels = c->width * c->height; + for (i = 0; i < pixels; i++) { + switch (ptr[i]) { + case 'X': /* black */ + c->data[i] = 0xff000000; + break; + case '.': /* white */ + c->data[i] = 0xffffffff; + break; + case ' ': /* transparent */ + default: + c->data[i] = 0x00000000; + break; + } + } +} + +/* nice for debugging */ +void cursor_print_ascii_art(QEMUCursor *c, const char *prefix) +{ + uint32_t *data = c->data; + int x,y; + + for (y = 0; y < c->height; y++) { + fprintf(stderr, "%s: %2d: |", prefix, y); + for (x = 0; x < c->width; x++, data++) { + if ((*data & 0xff000000) != 0xff000000) { + fprintf(stderr, " "); /* transparent */ + } else if ((*data & 0x00ffffff) == 0x00ffffff) { + fprintf(stderr, "."); /* white */ + } else if ((*data & 0x00ffffff) == 0x00000000) { + fprintf(stderr, "X"); /* black */ + } else { + fprintf(stderr, "o"); /* other */ + } + } + fprintf(stderr, "|\n"); + } +} + +QEMUCursor *cursor_builtin_hidden(void) +{ + QEMUCursor *c; + + c = cursor_alloc(32, 32); + cursor_parse_ascii_art(c, cursor_hidden_32); + return c; +} + +QEMUCursor *cursor_builtin_left_ptr(void) +{ + QEMUCursor *c; + + c = cursor_alloc(32, 32); + cursor_parse_ascii_art(c, cursor_left_ptr_32); + c->hot_x = 1; + c->hot_y = 1; + return c; +} + +QEMUCursor *cursor_alloc(int width, int height) +{ + QEMUCursor *c; + int datasize = width * height * sizeof(uint32_t); + + c = qemu_mallocz(sizeof(QEMUCursor) + datasize); + c->width = width; + c->height = height; + c->refcount = 1; + return c; +} + +void cursor_get(QEMUCursor *c) +{ + c->refcount++; +} + +void cursor_put(QEMUCursor *c) +{ + if (c == NULL) + return; + c->refcount--; + if (c->refcount) + return; + qemu_free(c); +} + +int cursor_get_mono_bpl(QEMUCursor *c) +{ + return (c->width + 7) / 8; +} + +void cursor_set_mono(QEMUCursor *c, + uint32_t foreground, uint32_t background, uint8_t *image, + int transparent, uint8_t *mask) +{ + uint32_t *data = c->data; + uint8_t bit; + int x,y,bpl; + + bpl = cursor_get_mono_bpl(c); + for (y = 0; y < c->height; y++) { + bit = 0x80; + for (x = 0; x < c->width; x++, data++) { + if (transparent && mask[x/8] & bit) { + *data = 0x00000000; + } else if (!transparent && !(mask[x/8] & bit)) { + *data = 0x00000000; + } else if (image[x/8] & bit) { + *data = 0xff000000 | foreground; + } else { + *data = 0xff000000 | background; + } + bit >>= 1; + if (bit == 0) { + bit = 0x80; + } + } + mask += bpl; + image += bpl; + } +} + +void cursor_get_mono_image(QEMUCursor *c, int foreground, uint8_t *image) +{ + uint32_t *data = c->data; + uint8_t bit; + int x,y,bpl; + + bpl = cursor_get_mono_bpl(c); + memset(image, 0, bpl * c->height); + for (y = 0; y < c->height; y++) { + bit = 0x80; + for (x = 0; x < c->width; x++, data++) { + if (((*data & 0xff000000) == 0xff000000) && + ((*data & 0x00ffffff) == foreground)) { + image[x/8] |= bit; + } + bit >>= 1; + if (bit == 0) { + bit = 0x80; + } + } + image += bpl; + } +} + +void cursor_get_mono_mask(QEMUCursor *c, int transparent, uint8_t *mask) +{ + uint32_t *data = c->data; + uint8_t bit; + int x,y,bpl; + + bpl = cursor_get_mono_bpl(c); + memset(mask, 0, bpl * c->height); + for (y = 0; y < c->height; y++) { + bit = 0x80; + for (x = 0; x < c->width; x++, data++) { + if ((*data & 0xff000000) != 0xff000000) { + if (transparent != 0) { + mask[x/8] |= bit; + } + } else { + if (transparent == 0) { + mask[x/8] |= bit; + } + } + bit >>= 1; + if (bit == 0) { + bit = 0x80; + } + } + mask += bpl; + } +}
Add a new cursor type to console.h and a bunch of functions to deal with cursors the (new) cursor.c file. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- Makefile.objs | 3 +- console.h | 24 ++++++- cursor.c | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 cursor.c