summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-04-21 00:37:09 +0200
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-04-21 00:37:09 +0200
commit618b53d4b49febefa56e8161bececa88d3ebc630 (patch)
treece64b01413b60e2c3e0dec3586cc5d6545ff6b63
parentc30447f399e79a6a30d4bbfc08c72cdaba882bff (diff)
Add gradient test pattern
-rw-r--r--fbdev.c204
1 files changed, 201 insertions, 3 deletions
diff --git a/fbdev.c b/fbdev.c
index 10e7612..a94751b 100644
--- a/fbdev.c
+++ b/fbdev.c
@@ -61,6 +61,7 @@ enum fb_fill_mode {
enum fb_fill_pattern {
FB_PATTERN_SMPTE = 0,
FB_PATTERN_LINES = 1,
+ FB_PATTERN_GRADIENT = 2,
};
/* -----------------------------------------------------------------------------
@@ -872,10 +873,17 @@ enum fb_yuv_order {
FB_YUV_YCrCb,
};
+#define FB_MAKE_YUV_601_Y(r, g, b) \
+ ((( 66 * (r) + 129 * (g) + 25 * (b) + 128) >> 8) + 16)
+#define FB_MAKE_YUV_601_U(r, g, b) \
+ (((-38 * (r) - 74 * (g) + 112 * (b) + 128) >> 8) + 128)
+#define FB_MAKE_YUV_601_V(r, g, b) \
+ (((112 * (r) - 94 * (g) - 18 * (b) + 128) >> 8) + 128)
+
#define FB_MAKE_YUV_601(dev, r, g, b) \
- { .y = (( 66 * (r) + 129 * (g) + 25 * (b) + 128) >> 8) + 16, \
- .u = ((-38 * (r) - 74 * (g) + 112 * (b) + 128) >> 8) + 128, \
- .v = ((112 * (r) - 94 * (g) - 18 * (b) + 128) >> 8) + 128 }
+ { .y = FB_MAKE_YUV_601_Y(r, g, b), \
+ .u = FB_MAKE_YUV_601_U(r, g, b), \
+ .v = FB_MAKE_YUV_601_V(r, g, b) }
static void
fb_fill_smpte_nv(struct device *dev, unsigned int xoffset, unsigned int yoffset,
@@ -1425,6 +1433,190 @@ fb_fill_lines(struct device *dev, unsigned int xoffset, unsigned int yoffset,
}
}
+static void
+fb_fill_gradient_nv(struct device *dev, unsigned int xoffset, unsigned int yoffset,
+ unsigned int xres, unsigned int yres,
+ unsigned int xsub, unsigned int ysub,
+ enum fb_yuv_order order)
+{
+ uint8_t *y_mem = dev->mem + dev->fix_info.line_length * yoffset
+ + xoffset;
+ uint8_t *c_mem = dev->mem
+ + dev->fix_info.line_length * dev->var_info.yres_virtual
+ + dev->fix_info.line_length * yoffset / ysub
+ + xoffset * 2 / xsub;
+ unsigned int u = order != FB_YUV_YCbCr;
+ unsigned int v = order == FB_YUV_YCbCr;
+ unsigned int x;
+ unsigned int y;
+
+ /* Luma */
+ for (y = 0; y < yres / 3; ++y) {
+ for (x = 0; x < xres; ++x)
+ y_mem[x] = FB_MAKE_YUV_601_Y(255 * x / xres, 0, 0);
+ y_mem += dev->fix_info.line_length;
+ }
+ for (; y < yres * 2 / 3; ++y) {
+ for (x = 0; x < xres; ++x)
+ y_mem[x] = FB_MAKE_YUV_601_Y(0, 255 * x / xres, 0);
+ y_mem += dev->fix_info.line_length;
+ }
+ for (; y < yres; ++y) {
+ for (x = 0; x < xres; ++x)
+ y_mem[x] = FB_MAKE_YUV_601_Y(0, 0, 255 * x / xres);
+ y_mem += dev->fix_info.line_length;
+ }
+
+ /* Chroma */
+ for (y = 0; y < yres / 3; y += ysub) {
+ for (x = 0; x < xres; x += xsub) {
+ c_mem[2/xsub*x+u] = FB_MAKE_YUV_601_U(255 * x / xres, 0, 0);
+ c_mem[2/xsub*x+v] = FB_MAKE_YUV_601_V(255 * x / xres, 0, 0);
+ }
+ c_mem += dev->fix_info.line_length * 2 / xsub;
+ }
+ for (; y < yres * 2 / 3; y += ysub) {
+ for (x = 0; x < xres; x += xsub) {
+ c_mem[2/xsub*x+u] = FB_MAKE_YUV_601_U(0, 255 * x / xres, 0);
+ c_mem[2/xsub*x+v] = FB_MAKE_YUV_601_V(0, 255 * x / xres, 0);
+ }
+ c_mem += dev->fix_info.line_length * 2 / xsub;
+ }
+ for (; y < yres; y += ysub) {
+ for (x = 0; x < xres; x += xsub) {
+ c_mem[2/xsub*x+u] = FB_MAKE_YUV_601_U(0, 0, 255 * x / xres);
+ c_mem[2/xsub*x+v] = FB_MAKE_YUV_601_V(0, 0, 255 * x / xres);
+ }
+ c_mem += dev->fix_info.line_length * 2 / xsub;
+ }
+}
+
+static void
+fb_fill_gradient_rgb16(struct device *dev, unsigned int xoffset,
+ unsigned int yoffset, unsigned int xres, unsigned int yres)
+{
+ void *mem = dev->mem + dev->fix_info.line_length * yoffset
+ + xoffset * dev->var_info.bits_per_pixel / 8;
+ unsigned int x;
+ unsigned int y;
+
+ for (y = 0; y < yres / 3; ++y) {
+ for (x = 0; x < xres; ++x)
+ ((uint16_t *)mem)[x] = FB_MAKE_RGB(dev, 255 * x / xres, 0, 0);
+ mem += dev->fix_info.line_length;
+ }
+ for (; y < yres * 2 / 3; ++y) {
+ for (x = 0; x < xres; ++x)
+ ((uint16_t *)mem)[x] = FB_MAKE_RGB(dev, 0, 255 * x / xres, 0);
+ mem += dev->fix_info.line_length;
+ }
+ for (; y < yres; ++y) {
+ for (x = 0; x < xres; ++x)
+ ((uint16_t *)mem)[x] = FB_MAKE_RGB(dev, 0, 0, 255 * x / xres);
+ mem += dev->fix_info.line_length;
+ }
+}
+
+static void
+fb_fill_gradient_rgb24(struct device *dev, unsigned int xoffset,
+ unsigned int yoffset, unsigned int xres, unsigned int yres)
+{
+ void *mem = dev->mem + dev->fix_info.line_length * yoffset
+ + xoffset * dev->var_info.bits_per_pixel / 8;
+ unsigned int x;
+ unsigned int y;
+
+ for (y = 0; y < yres / 3; ++y) {
+ for (x = 0; x < xres; ++x)
+ ((struct fb_color24 *)mem)[x].value =
+ FB_MAKE_RGB(dev, 255 * x / xres, 0, 0);
+ mem += dev->fix_info.line_length;
+ }
+ for (; y < yres * 2 / 3; ++y) {
+ for (x = 0; x < xres; ++x)
+ ((struct fb_color24 *)mem)[x].value =
+ FB_MAKE_RGB(dev, 0, 255 * x / xres, 0);
+ mem += dev->fix_info.line_length;
+ }
+ for (; y < yres; ++y) {
+ for (x = 0; x < xres; ++x)
+ ((struct fb_color24 *)mem)[x].value =
+ FB_MAKE_RGB(dev, 0, 0, 255 * x / xres);
+ mem += dev->fix_info.line_length;
+ }
+}
+
+static void
+fb_fill_gradient_rgb32(struct device *dev, unsigned int xoffset,
+ unsigned int yoffset, unsigned int xres, unsigned int yres)
+{
+ void *mem = dev->mem + dev->fix_info.line_length * yoffset
+ + xoffset * dev->var_info.bits_per_pixel / 8;
+ unsigned int x;
+ unsigned int y;
+
+ 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);
+ 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);
+ 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);
+ mem += dev->fix_info.line_length;
+ }
+}
+
+/*
+ * fb_fill_gradient - Fill the frame buffer with a gradient test pattern
+ * @dev: FB device
+ * @xoffset: Horizontal offset, in pixels
+ * @yoffset: Vertical offset, in pixels
+ * @xres: Horizontal size, in pixels
+ * @yres: Vertical size, in pixels
+ *
+ * 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)
+{
+ switch (dev->fourcc) {
+ case V4L2_PIX_FMT_NV12:
+ return fb_fill_gradient_nv(dev, xoffset, yoffset, xres, yres,
+ 2, 2, FB_YUV_YCbCr);
+ case V4L2_PIX_FMT_NV21:
+ return fb_fill_gradient_nv(dev, xoffset, yoffset, xres, yres,
+ 2, 2, FB_YUV_YCrCb);
+ case V4L2_PIX_FMT_NV16:
+ return fb_fill_gradient_nv(dev, xoffset, yoffset, xres, yres,
+ 2, 1, FB_YUV_YCbCr);
+ case V4L2_PIX_FMT_NV61:
+ return fb_fill_gradient_nv(dev, xoffset, yoffset, xres, yres,
+ 2, 1, FB_YUV_YCrCb);
+ case V4L2_PIX_FMT_NV24:
+ return fb_fill_gradient_nv(dev, xoffset, yoffset, xres, yres,
+ 1, 1, FB_YUV_YCbCr);
+ case V4L2_PIX_FMT_NV42:
+ return fb_fill_gradient_nv(dev, xoffset, yoffset, xres, yres,
+ 1, 1, FB_YUV_YCrCb);
+ case V4L2_PIX_FMT_RGB565:
+ return fb_fill_gradient_rgb16(dev, xoffset, yoffset, xres, yres);
+ case V4L2_PIX_FMT_BGR24:
+ case V4L2_PIX_FMT_RGB24:
+ 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);
+ }
+}
+
/*
* fb_fill - Fill the frame buffer with a test pattern
* @dev: FB device
@@ -1488,6 +1680,10 @@ fb_fill(struct device *dev, enum fb_fill_mode mode, enum fb_fill_pattern pattern
printf("Filling frame buffer with lines test pattern\n");
return fb_fill_lines(dev, xoffset, yoffset, xres, yres);
+ case FB_PATTERN_GRADIENT:
+ printf("Filling frame buffer with gradient test pattern\n");
+ return fb_fill_gradient(dev, xoffset, yoffset, xres, yres);
+
default:
printf("Error: unsupported test pattern %u.\n", pattern);
break;
@@ -1708,6 +1904,8 @@ int main(int argc, char *argv[])
fill_pattern = FB_PATTERN_SMPTE;
else if (strcmp(optarg, "lines") == 0)
fill_pattern = FB_PATTERN_LINES;
+ else if (strcmp(optarg, "gradient") == 0)
+ fill_pattern = FB_PATTERN_GRADIENT;
else {
printf("Invalid test pattern `%s'\n", optarg);
printf("Run %s -h for help.\n", argv[0]);