From d868b3e8b3b5bae6a4db7bab640e340a9ec8f6c7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 24 Apr 2012 12:49:39 +0200 Subject: Add alpha blending support For formats that include an alpha channel, the -a/--alpha command line argument can be used to specify an alpha value for the test pattern. Signed-off-by: Laurent Pinchart --- fbdev.c | 119 ++++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 71 insertions(+), 48 deletions(-) diff --git a/fbdev.c b/fbdev.c index a94751b..412d0e7 100644 --- a/fbdev.c +++ b/fbdev.c @@ -48,6 +48,7 @@ struct device { struct fb_bitfield red; struct fb_bitfield green; struct fb_bitfield blue; + struct fb_bitfield alpha; unsigned int fourcc; }; @@ -577,10 +578,12 @@ static int fb_update_info(struct device *dev) memset(&dev->red, 0, sizeof dev->red); memset(&dev->green, 0, sizeof dev->green); memset(&dev->blue, 0, sizeof dev->blue); + memset(&dev->alpha, 0, sizeof dev->alpha); } else { dev->red = var_info.red; dev->green = var_info.green; dev->blue = var_info.blue; + dev->alpha = var_info.transp; } return 0; @@ -1132,37 +1135,44 @@ fb_fill_smpte_rgb24(struct device *dev, unsigned int xoffset, } } +#define FB_MAKE_RGBA(dev, r, g, b, a) \ + ((((r) >> (8 - (dev)->red.length)) << (dev)->red.offset) | \ + (((g) >> (8 - (dev)->green.length)) << (dev)->green.offset) | \ + (((b) >> (8 - (dev)->blue.length)) << (dev)->blue.offset) | \ + (((a) >> (8 - (dev)->alpha.length)) << (dev)->alpha.offset)) + static void fb_fill_smpte_rgb32(struct device *dev, unsigned int xoffset, - unsigned int yoffset, unsigned int xres, unsigned int yres) + unsigned int yoffset, unsigned int xres, unsigned int yres, + uint8_t alpha) { const uint32_t colors_top[] = { - FB_MAKE_RGB(dev, 192, 192, 192), /* grey */ - FB_MAKE_RGB(dev, 192, 192, 0), /* yellow */ - FB_MAKE_RGB(dev, 0, 192, 192), /* cyan */ - FB_MAKE_RGB(dev, 0, 192, 0), /* green */ - FB_MAKE_RGB(dev, 192, 0, 192), /* magenta */ - FB_MAKE_RGB(dev, 192, 0, 0), /* red */ - FB_MAKE_RGB(dev, 0, 0, 192), /* blue */ + FB_MAKE_RGBA(dev, 192, 192, 192, alpha), /* grey */ + FB_MAKE_RGBA(dev, 192, 192, 0, alpha), /* yellow */ + FB_MAKE_RGBA(dev, 0, 192, 192, alpha), /* cyan */ + FB_MAKE_RGBA(dev, 0, 192, 0, alpha), /* green */ + FB_MAKE_RGBA(dev, 192, 0, 192, alpha), /* magenta */ + FB_MAKE_RGBA(dev, 192, 0, 0, alpha), /* red */ + FB_MAKE_RGBA(dev, 0, 0, 192, alpha), /* blue */ }; const uint32_t colors_middle[] = { - FB_MAKE_RGB(dev, 0, 0, 192), /* blue */ - FB_MAKE_RGB(dev, 19, 19, 19), /* black */ - FB_MAKE_RGB(dev, 192, 0, 192), /* magenta */ - FB_MAKE_RGB(dev, 19, 19, 19), /* black */ - FB_MAKE_RGB(dev, 0, 192, 192), /* cyan */ - FB_MAKE_RGB(dev, 19, 19, 19), /* black */ - FB_MAKE_RGB(dev, 192, 192, 192), /* grey */ + FB_MAKE_RGBA(dev, 0, 0, 192, alpha), /* blue */ + FB_MAKE_RGBA(dev, 19, 19, 19, alpha), /* black */ + FB_MAKE_RGBA(dev, 192, 0, 192, alpha), /* magenta */ + FB_MAKE_RGBA(dev, 19, 19, 19, alpha), /* black */ + FB_MAKE_RGBA(dev, 0, 192, 192, alpha), /* cyan */ + FB_MAKE_RGBA(dev, 19, 19, 19, alpha), /* black */ + FB_MAKE_RGBA(dev, 192, 192, 192, alpha), /* grey */ }; const uint32_t colors_bottom[] = { - FB_MAKE_RGB(dev, 0, 33, 76), /* in-phase */ - FB_MAKE_RGB(dev, 255, 255, 255), /* super white */ - FB_MAKE_RGB(dev, 50, 0, 106), /* quadrature */ - FB_MAKE_RGB(dev, 19, 19, 19), /* black */ - FB_MAKE_RGB(dev, 9, 9, 9), /* 3.5% */ - FB_MAKE_RGB(dev, 19, 19, 19), /* 7.5% */ - FB_MAKE_RGB(dev, 29, 29, 29), /* 11.5% */ - FB_MAKE_RGB(dev, 19, 19, 19), /* black */ + FB_MAKE_RGBA(dev, 0, 33, 76, alpha), /* in-phase */ + FB_MAKE_RGBA(dev, 255, 255, 255, alpha), /* super white */ + FB_MAKE_RGBA(dev, 50, 0, 106, alpha), /* quadrature */ + FB_MAKE_RGBA(dev, 19, 19, 19, alpha), /* black */ + FB_MAKE_RGBA(dev, 9, 9, 9, alpha), /* 3.5% */ + FB_MAKE_RGBA(dev, 19, 19, 19, alpha), /* 7.5% */ + FB_MAKE_RGBA(dev, 29, 29, 29, alpha), /* 11.5% */ + FB_MAKE_RGBA(dev, 19, 19, 19, alpha), /* black */ }; void *mem = dev->mem + dev->fix_info.line_length * yoffset + xoffset * dev->var_info.bits_per_pixel / 8; @@ -1202,13 +1212,14 @@ fb_fill_smpte_rgb32(struct device *dev, unsigned int xoffset, * @yoffset: Vertical offset, in pixels * @xres: Horizontal size, in pixels * @yres: Vertical size, in pixels + * @alpha: Transparency value (only for formats that support alpha values) * * Fill the display (when mode is FB_FILL_DISPLAY) or virtual frame buffer area * (when mode is FB_FILL_VIRTUAL) with an SMPTE color bars pattern. */ static void fb_fill_smpte(struct device *dev, unsigned int xoffset, unsigned int yoffset, - unsigned int xres, unsigned int yres) + unsigned int xres, unsigned int yres, uint8_t alpha) { switch (dev->fourcc) { case V4L2_PIX_FMT_NV12: @@ -1236,7 +1247,7 @@ fb_fill_smpte(struct device *dev, unsigned int xoffset, unsigned int yoffset, return fb_fill_smpte_rgb24(dev, xoffset, yoffset, xres, yres); case V4L2_PIX_FMT_BGR32: case V4L2_PIX_FMT_RGB32: - return fb_fill_smpte_rgb32(dev, xoffset, yoffset, xres, yres); + return fb_fill_smpte_rgb32(dev, xoffset, yoffset, xres, yres, alpha); } } @@ -1358,17 +1369,18 @@ fb_fill_lines_rgb24(struct device *dev, unsigned int xoffset, static void fb_fill_lines_rgb32(struct device *dev, unsigned int xoffset, - unsigned int yoffset, unsigned int xres, unsigned int yres) + unsigned int yoffset, unsigned int xres, unsigned int yres, + uint8_t alpha) { const uint32_t colors[] = { - FB_MAKE_RGB(dev, 192, 192, 0), /* yellow */ - FB_MAKE_RGB(dev, 19, 19, 19), /* black */ - FB_MAKE_RGB(dev, 0, 192, 0), /* green */ - FB_MAKE_RGB(dev, 19, 19, 19), /* black */ - FB_MAKE_RGB(dev, 192, 0, 0), /* red */ - FB_MAKE_RGB(dev, 19, 19, 19), /* black */ - FB_MAKE_RGB(dev, 0, 0, 192), /* blue */ - FB_MAKE_RGB(dev, 19, 19, 19), /* black */ + FB_MAKE_RGBA(dev, 192, 192, 0, alpha), /* yellow */ + FB_MAKE_RGBA(dev, 19, 19, 19, alpha), /* black */ + FB_MAKE_RGBA(dev, 0, 192, 0, alpha), /* green */ + FB_MAKE_RGBA(dev, 19, 19, 19, alpha), /* black */ + FB_MAKE_RGBA(dev, 192, 0, 0, alpha), /* red */ + FB_MAKE_RGBA(dev, 19, 19, 19, alpha), /* black */ + FB_MAKE_RGBA(dev, 0, 0, 192, alpha), /* blue */ + FB_MAKE_RGBA(dev, 19, 19, 19, alpha), /* black */ }; void *mem = dev->mem + dev->fix_info.line_length * yoffset + xoffset * dev->var_info.bits_per_pixel / 8; @@ -1395,13 +1407,14 @@ fb_fill_lines_rgb32(struct device *dev, unsigned int xoffset, * @yoffset: Vertical offset, in pixels * @xres: Horizontal size, in pixels * @yres: Vertical size, in pixels + * @alpha: Transparency value (only for formats that support alpha values) * * Fill the display (when mode is FB_FILL_DISPLAY) or virtual frame buffer area * (when mode is FB_FILL_VIRTUAL) with a lines pattern. */ static void fb_fill_lines(struct device *dev, unsigned int xoffset, unsigned int yoffset, - unsigned int xres, unsigned int yres) + unsigned int xres, unsigned int yres, uint8_t alpha) { switch (dev->fourcc) { case V4L2_PIX_FMT_NV12: @@ -1429,7 +1442,7 @@ fb_fill_lines(struct device *dev, unsigned int xoffset, unsigned int yoffset, return fb_fill_lines_rgb24(dev, xoffset, yoffset, xres, yres); case V4L2_PIX_FMT_BGR32: case V4L2_PIX_FMT_RGB32: - return fb_fill_lines_rgb32(dev, xoffset, yoffset, xres, yres); + return fb_fill_lines_rgb32(dev, xoffset, yoffset, xres, yres, alpha); } } @@ -1548,7 +1561,8 @@ fb_fill_gradient_rgb24(struct device *dev, unsigned int xoffset, static void fb_fill_gradient_rgb32(struct device *dev, unsigned int xoffset, - unsigned int yoffset, unsigned int xres, unsigned int yres) + unsigned int yoffset, unsigned int xres, unsigned int yres, + uint8_t alpha) { void *mem = dev->mem + dev->fix_info.line_length * yoffset + xoffset * dev->var_info.bits_per_pixel / 8; @@ -1557,17 +1571,17 @@ fb_fill_gradient_rgb32(struct device *dev, unsigned int xoffset, for (y = 0; y < yres / 3; ++y) { for (x = 0; x < xres; ++x) - ((uint32_t *)mem)[x] = FB_MAKE_RGB(dev, 255 * x / xres, 0, 0); + ((uint32_t *)mem)[x] = FB_MAKE_RGBA(dev, 255 * x / xres, 0, 0, alpha); mem += dev->fix_info.line_length; } for (; y < yres * 2 / 3; ++y) { for (x = 0; x < xres; ++x) - ((uint32_t *)mem)[x] = FB_MAKE_RGB(dev, 0, 255 * x / xres, 0); + ((uint32_t *)mem)[x] = FB_MAKE_RGBA(dev, 0, 255 * x / xres, 0, alpha); mem += dev->fix_info.line_length; } for (; y < yres; ++y) { for (x = 0; x < xres; ++x) - ((uint32_t *)mem)[x] = FB_MAKE_RGB(dev, 0, 0, 255 * x / xres); + ((uint32_t *)mem)[x] = FB_MAKE_RGBA(dev, 0, 0, 255 * x / xres, alpha); mem += dev->fix_info.line_length; } } @@ -1579,13 +1593,14 @@ fb_fill_gradient_rgb32(struct device *dev, unsigned int xoffset, * @yoffset: Vertical offset, in pixels * @xres: Horizontal size, in pixels * @yres: Vertical size, in pixels + * @alpha: Transparency value (only for formats that support alpha values) * * Fill the display (when mode is FB_FILL_DISPLAY) or virtual frame buffer area * (when mode is FB_FILL_VIRTUAL) with a gradient pattern. */ static void fb_fill_gradient(struct device *dev, unsigned int xoffset, unsigned int yoffset, - unsigned int xres, unsigned int yres) + unsigned int xres, unsigned int yres, uint8_t alpha) { switch (dev->fourcc) { case V4L2_PIX_FMT_NV12: @@ -1613,7 +1628,7 @@ fb_fill_gradient(struct device *dev, unsigned int xoffset, unsigned int yoffset, return fb_fill_gradient_rgb24(dev, xoffset, yoffset, xres, yres); case V4L2_PIX_FMT_BGR32: case V4L2_PIX_FMT_RGB32: - return fb_fill_gradient_rgb32(dev, xoffset, yoffset, xres, yres); + return fb_fill_gradient_rgb32(dev, xoffset, yoffset, xres, yres, alpha); } } @@ -1622,13 +1637,15 @@ fb_fill_gradient(struct device *dev, unsigned int xoffset, unsigned int yoffset, * @dev: FB device * @mode: Fill mode * @pattern: Test pattern + * @alpha: Transparency value (only for formats that support alpha values) * * Fill the display (when mode is FB_FILL_DISPLAY) or virtual frame buffer area * (when mode is FB_FILL_VIRTUAL) with the test pattern specified by the pattern * parameter. Only RGB16, RGB24 and RGB32 on true color visuals are supported. */ static void -fb_fill(struct device *dev, enum fb_fill_mode mode, enum fb_fill_pattern pattern) +fb_fill(struct device *dev, enum fb_fill_mode mode, + enum fb_fill_pattern pattern, uint8_t alpha) { unsigned int xoffset, yoffset; unsigned int xres, yres; @@ -1674,15 +1691,15 @@ fb_fill(struct device *dev, enum fb_fill_mode mode, enum fb_fill_pattern pattern switch (pattern) { case FB_PATTERN_SMPTE: printf("Filling frame buffer with SMPTE test pattern\n"); - return fb_fill_smpte(dev, xoffset, yoffset, xres, yres); + return fb_fill_smpte(dev, xoffset, yoffset, xres, yres, alpha); case FB_PATTERN_LINES: printf("Filling frame buffer with lines test pattern\n"); - return fb_fill_lines(dev, xoffset, yoffset, xres, yres); + return fb_fill_lines(dev, xoffset, yoffset, xres, yres, alpha); case FB_PATTERN_GRADIENT: printf("Filling frame buffer with gradient test pattern\n"); - return fb_fill_gradient(dev, xoffset, yoffset, xres, yres); + return fb_fill_gradient(dev, xoffset, yoffset, xres, yres, alpha); default: printf("Error: unsupported test pattern %u.\n", pattern); @@ -1700,6 +1717,7 @@ static void usage(const char *argv0) printf("Usage: %s [options] device\n", argv0); printf("Supported options:\n"); + printf("-a, --alpha value Transparency value for test patterns\n"); printf("-b, --blank mode Set blanking mode\n"); printf("-f, --fill[=mode] Fill the frame buffer with a test pattern\n"); printf("-F, --format fourcc Set the frame buffer format\n"); @@ -1730,6 +1748,7 @@ static void usage(const char *argv0) } static struct option opts[] = { + {"alpha", 1, 0, 'a'}, {"blank", 1, 0, 'b'}, {"fill", 2, 0, 'f'}, {"format", 1, 0, 'F'}, @@ -1836,6 +1855,7 @@ int main(int argc, char *argv[]) enum fb_fill_mode fill_mode = FB_FILL_NONE; enum fb_fill_pattern fill_pattern = FB_PATTERN_SMPTE; + uint8_t alpha = 255; bool do_format = false; unsigned int fourcc = 0; @@ -1856,9 +1876,12 @@ int main(int argc, char *argv[]) int c; opterr = 0; - while ((c = getopt_long(argc, argv, "b:f::F:hp:P:r:v:w::", opts, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "a:b:f::F:hp:P:r:v:w::", opts, NULL)) != -1) { switch (c) { + case 'a': + alpha = atoi(optarg); + break; case 'b': do_blank = true; if (fb_blank_parse(optarg, &blank) < 0) { @@ -1959,7 +1982,7 @@ int main(int argc, char *argv[]) fb_set_resolution(&dev, xres, yres, xres_virtual, yres_virtual); if (fill_mode != FB_FILL_NONE) - fb_fill(&dev, fill_mode, fill_pattern); + fb_fill(&dev, fill_mode, fill_pattern, alpha); if (do_pan) fb_pan(&dev, pan_x, pan_y); -- cgit v1.2.3