[PATCH v2 3/4] GUI: Add fbtest command

Andrey Smirnov andrew.smirnov at gmail.com
Mon Jun 27 20:53:39 PDT 2016


On Sun, Jun 26, 2016 at 10:57 PM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> On Thu, Jun 23, 2016 at 10:35:34PM -0700, Andrey Smirnov wrote:
>> Add 'fbtest' - a command to produce test patterns on a screen
>>
>> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
>> Signed-off-by: Andrey Gusakov <andrey.gusakov at cogentembedded.com>
>> ---
>>  commands/Kconfig  |   9 +++
>>  commands/Makefile |   1 +
>>  commands/fbtest.c | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 211 insertions(+)
>>  create mode 100644 commands/fbtest.c
>>
>> diff --git a/commands/Kconfig b/commands/Kconfig
>> index 880cd45..cf71289 100644
>> --- a/commands/Kconfig
>> +++ b/commands/Kconfig
>> @@ -1417,6 +1417,15 @@ config CMD_SPLASH
>>                 -b COLOR      background color in 0xttrrggbb
>>                 -o            render offscreen
>>
>> +config CMD_FBTEST
>> +     bool
>> +     depends on VIDEO
>> +     select 2D_PRIMITIVES
>> +     prompt "FB test"
>> +     help
>> +       Framebuffer test command that allows to produce a number of
>> +       test patterns on a screen.
>> +
>>  config CMD_READLINE
>>       tristate
>>       prompt "readline"
>> diff --git a/commands/Makefile b/commands/Makefile
>> index b8c07f3..5a899ab 100644
>> --- a/commands/Makefile
>> +++ b/commands/Makefile
>> @@ -57,6 +57,7 @@ obj-$(CONFIG_CMD_HELP)              += help.o
>>  obj-$(CONFIG_CMD_LSMOD)              += lsmod.o
>>  obj-$(CONFIG_CMD_INSMOD)     += insmod.o
>>  obj-$(CONFIG_CMD_SPLASH)     += splash.o
>> +obj-$(CONFIG_CMD_FBTEST)     += fbtest.o
>>  obj-$(CONFIG_USB_GADGET_DFU) += dfu.o
>>  obj-$(CONFIG_USB_GADGET_SERIAL)      += usbserial.o
>>  obj-$(CONFIG_CMD_GPIO)               += gpio.o
>> diff --git a/commands/fbtest.c b/commands/fbtest.c
>> new file mode 100644
>> index 0000000..f1569e9
>> --- /dev/null
>> +++ b/commands/fbtest.c
>> @@ -0,0 +1,201 @@
>> +#include <common.h>
>> +#include <command.h>
>> +#include <errno.h>
>> +#include <malloc.h>
>> +#include <getopt.h>
>> +#include <fb.h>
>> +#include <gui/graphic_utils.h>
>> +#include <gui/2d-primitives.h>
>> +#include <linux/gcd.h>
>> +#include <int_sqrt.h>
>> +
>> +static void fbtest_pattern_bars(struct screen *sc, u32 unused)
>> +{
>> +     int i;
>> +
>> +     const u32 xres = sc->info->xres;
>> +     const u32 yres = sc->info->yres;
>> +
>> +     const u32 colors[] =  {
>> +             0xFFFFFF,       /* white */
>> +             0xFFFF00,       /* yellow */
>> +             0x00FFFF,       /* cyan */
>> +             0x00FF00,       /* green */
>> +             0xFF00FF,       /* magenta */
>> +             0xFF0000,       /* red */
>> +             0x0000FF,       /* blue */
>> +             0x000000,       /* black */
>> +     };
>> +
>> +     for (i = 0; i < ARRAY_SIZE(colors); i++) {
>> +             const u8 r = (colors[i] >> 16) & 0xff;
>> +             const u8 g = (colors[i] >>  8) & 0xff;
>> +             const u8 b = (colors[i] >>  0) & 0xff;
>> +             const int dx = xres / ARRAY_SIZE(colors);
>> +
>> +             gu_fill_rectangle(sc,
>> +                               i * dx, 0, (i + 1) * dx - 1, yres - 1,
>> +                               r, g, b, 0xff);
>> +     }
>> +}
>> +
>> +static void fbtest_pattern_geometry(struct screen *sc, u32 color)
>> +{
>> +     int i;
>> +
>> +     const u8 r = (color >> 16) & 0xff;
>> +     const u8 g = (color >>  8) & 0xff;
>> +     const u8 b = (color >>  0) & 0xff;
>> +
>> +     const u32 xres = sc->info->xres;
>> +     const u32 yres = sc->info->yres;
>> +
>> +     const u8 xcount = xres / gcd(xres, yres);
>> +     const u8 ycount = yres / gcd(xres, yres);
>> +
>> +     const struct {
>> +             int x1, y1, x2, y2;
>> +     } borders[] = {
>> +             { 0,        0,        xres - 1, 0        },
>> +             { xres - 1, 0,        xres - 1, yres - 1 },
>> +             { 0,        yres - 1, xres - 1, yres - 1 },
>> +             { 0,        0,        0,        yres - 1 },
>> +     };
>> +
>> +     const int R1 = min(xres, yres) / 2;
>> +     const int h  = xres * xres + yres * yres;
>> +     const int R2 = (int_sqrt(h) / 2 - R1) * 5 / 12;
>> +
>> +     const  struct {
>> +             int x0, y0, radius;
>> +     } circles[] = {
>> +             { xres / 2,  yres / 2,  R1 - 1 },
>> +             { R2,        R2,        R2 - 1 },
>> +             { xres - R2, R2,        R2 - 1 },
>> +             { xres - R2, yres - R2, R2 - 1 },
>> +             { R2,        yres - R2, R2 - 1 }
>> +     };
>> +
>> +     void *buf = gui_screen_render_buffer(sc);
>> +
>> +     gu_memset_pixel(sc->info, buf, ~color,
>> +                     sc->s.width * sc->s.height);
>> +
>> +     for (i = 0; i < ARRAY_SIZE(borders); i++)
>> +             gu_draw_line(sc,
>> +                          borders[i].x1, borders[i].y1,
>> +                          borders[i].x2, borders[i].y2,
>> +                          r, g, b, 0xff, 10);
>> +
>> +     for (i = 0; i < ARRAY_SIZE(circles); i++)
>> +             gu_draw_circle(sc,
>> +                            circles[i].x0, circles[i].y0,
>> +                            circles[i].radius,
>> +                            r, g, b, 0xff);
>> +
>> +     for (i = 1; i < ycount; i++) {
>> +             const int y = (yres - 1) * i / ycount;
>> +             gu_draw_line(sc,
>> +                          0, y, xres - 1, y,
>> +                          r, g, b, 0xff, 0);
>> +     }
>> +
>> +
>> +     for (i = 1; i < xcount; i++) {
>> +             const int x = (xres - 1) * i / xcount;
>> +             gu_draw_line(sc,
>> +                          x, 0, x, yres - 1,
>> +                          r, g, b, 0xff, 0);
>> +     }
>> +}
>> +
>> +static int do_fbtest(int argc, char *argv[])
>> +{
>> +     struct screen *sc;
>> +     int opt;
>> +     unsigned int i;
>> +     const char *pattern_name = NULL;
>> +     char *fbdev = "/dev/fb0";
>> +     void (*pattern) (struct screen *sc, u32 color) = NULL;
>> +     u32 color = 0xffffff;
>> +
>> +     struct {
>> +             const char *name;
>> +             void (*func) (struct screen *sc, u32 color);
>> +     } patterns[] = {
>> +             { "geometry", fbtest_pattern_geometry },
>> +             { "bars",     fbtest_pattern_bars     }
>> +     };
>> +
>> +     while((opt = getopt(argc, argv, "d:p:c:")) > 0) {
>> +             switch(opt) {
>> +             case 'd':
>> +                     fbdev = optarg;
>> +                     break;
>> +             case 'p':
>> +                     pattern_name = optarg;
>> +                     break;
>> +             case 'c':
>> +                     color = simple_strtoul(optarg, NULL, 16);
>> +                     break;
>> +             }
>> +     }
>> +
>> +     if (pattern_name) {
>> +             for (i = 0; i < ARRAY_SIZE(patterns); i++)
>> +                     if (!strcmp(pattern_name, patterns[i].name))
>> +                             pattern = patterns[i].func;
>> +
>> +             if (!pattern) {
>> +                     printf("Unknonw pattern: %s\n", pattern_name);
>
> s/Unknonw/Unknown/

Will fix in v3. Thanks for noticing!

>
>> +                     return -EINVAL;
>> +             }
>> +     }
>> +
>> +     sc = fb_open(fbdev);
>> +     if (IS_ERR(sc)) {
>> +             perror("fd_open");
>> +             return PTR_ERR(sc);
>> +     }
>> +
>> +     if (!pattern_name) {
>> +             printf("No pattern selected. Cycling through all of them.\n");
>> +             printf("Press Ctrl-C to stop\n");
>> +
>> +             i = 0;
>> +             for (;;) {
>> +                     pattern = patterns[i++ % ARRAY_SIZE(patterns)].func;
>> +                     pattern(sc, color);
>> +                     gu_screen_blit(sc);
>> +
>> +                     if (ctrlc())
>> +                             break;
>> +
>> +                     mdelay(2000);
>> +             }
>
> The user will likely hit ctrl-c during the delay. Then when pressed there
> will always be the next pattern printed before actually stopping, which
> is probably not expected. How about this instead?
>
>         start = get_time_ns();
>         while (!is_timeout(start, 2 * SECOND))
>                 if (ctrlc())
>                         break;

Good suggestion, will use in v3.

Andrey



More information about the barebox mailing list