Demos (master): egl/openvg: Verify blend demo rendering with vgReadPixels.

Chia-I Wu olv at kemper.freedesktop.org
Sat Dec 4 16:01:06 UTC 2010


Module: Demos
Branch: master
Commit: a6caaff1085e5bb438e66bfc9ae6780b9daccee7
URL:    http://cgit.freedesktop.org/mesa/demos/commit/?id=a6caaff1085e5bb438e66bfc9ae6780b9daccee7

Author: Chia-I Wu <olvaffe at gmail.com>
Date:   Sat Dec  4 19:53:20 2010 +0800

egl/openvg: Verify blend demo rendering with vgReadPixels.

Calculate the final colors separately and use vgReadPixels to compare
the results when -v is given.

---

 src/egl/openvg/trivial/blend.c |  124 ++++++++++++++++++++++++++++++++++++++--
 1 files changed, 119 insertions(+), 5 deletions(-)

diff --git a/src/egl/openvg/trivial/blend.c b/src/egl/openvg/trivial/blend.c
index c69abb8..2724481 100644
--- a/src/egl/openvg/trivial/blend.c
+++ b/src/egl/openvg/trivial/blend.c
@@ -6,6 +6,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 
+VGboolean verbose;
 VGPath rect;
 
 static void
@@ -64,55 +65,160 @@ rectangle(VGint x, VGint y, VGint width, VGint height)
 }
 
 static void
-test_blend(VGint x, VGint y, VGint width, VGint height)
+check_pixel(VGint x, VGint y, VGfloat ref[4], const char *msg)
 {
-   /* src is red with alpha 0.8 */
-   /* dst is green with alpha 0.3 */
+   VGfloat rgba[4];
+   VGint pixel;
+   VGint i;
+
+   vgReadPixels(&pixel, 0, VG_sRGBA_8888, x, y, 1, 1);
+   rgba[0] = ((pixel >> 24) & 0xff) / 255.0f;
+   rgba[1] = ((pixel >> 16) & 0xff) / 255.0f;
+   rgba[2] = ((pixel >>  8) & 0xff) / 255.0f;
+   rgba[3] = ((pixel >>  0) & 0xff) / 255.0f;
+
+   for (i = 0; i < 4; i++) {
+      if (fabs(ref[i] - rgba[i]) > 0.1f) {
+         printf("Test %s at (%d, %d): expect (%f, %f, %f, %f), got (%f, %f, %f, %f)\n",
+               msg, x, y, ref[0], ref[1], ref[2], ref[3],
+               rgba[0], rgba[1], rgba[2], rgba[3]);
+         break;
+      }
+   }
+}
+
+static void
+test_blend(VGint x, VGint y, VGint width, VGint height, VGboolean check)
+{
+   VGfloat src[4] = { 1.0f, 0.0f, 0.0f, 0.8f};
+   VGfloat dst[4] = { 0.0f, 1.0f, 0.0f, 0.3f};
+   VGfloat out[4];
+   VGint i;
+
+   /* premultiply */
+   if (check) {
+      for (i = 0; i < 3; i++) {
+         src[i] *= src[3];
+         dst[i] *= dst[3];
+      }
+
+      /*
+       * OpenVG allows an implementation to perform interpolation and blending
+       * in linear or non-linear color space.  Other factors might also affect
+       * the rendering result.  The checks are for reference only.
+       */
+      printf("Render and check blending result (for reference only)\n");
+   }
+
+#define CHECK(msg)            \
+   do {                       \
+      /* non-premultiply */   \
+      for (i = 0; i < 3; i++) \
+         out[i] /= out[3];    \
+      check_pixel(x + width / 2, y + height / 2, out, msg); \
+   } while (0)
 
    /* 0.8 * red */
    vgSeti(VG_BLEND_MODE, VG_BLEND_SRC);
    rectangle(x, y, width, height);
+   if (check) {
+      for (i = 0; i < 4; i++)
+         out[i] = src[i];
+      CHECK("VG_BLEND_SRC");
+   }
    x += width + 5;
 
    /* 0.8 * red + 0.06 * green */
    vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);
    rectangle(x, y, width, height);
+   if (check) {
+      for (i = 0; i < 4; i++)
+         out[i] = src[i] + dst[i] * (1.0f - src[3]);
+      CHECK("VG_BLEND_SRC_OVER");
+   }
    x += width + 5;
 
    /* 0.56 * red + 0.3 * green */
    vgSeti(VG_BLEND_MODE, VG_BLEND_DST_OVER);
    rectangle(x, y, width, height);
+   if (check) {
+      for (i = 0; i < 4; i++)
+         out[i] = dst[i] + src[i] * (1.0f - dst[3]);
+      CHECK("VG_BLEND_DST_OVER");
+   }
    x += width + 5;
 
    /* 0.24 * red */
    vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_IN);
    rectangle(x, y, width, height);
+   if (check) {
+      for (i = 0; i < 4; i++)
+         out[i] = src[i] * dst[3];
+      CHECK("VG_BLEND_SRC_IN");
+   }
    x += width + 5;
 
    /* 0.24 * green */
    vgSeti(VG_BLEND_MODE, VG_BLEND_DST_IN);
+   if (check) {
+      for (i = 0; i < 4; i++)
+         out[i] = dst[i] * src[3];
+      CHECK("VG_BLEND_DST_IN");
+   }
    rectangle(x, y, width, height);
    x += width + 5;
 
    /* (...) * 0.8 * red + 0.06 * green */
    vgSeti(VG_BLEND_MODE, VG_BLEND_MULTIPLY);
    rectangle(x, y, width, height);
+   if (check) {
+      for (i = 0; i < 3; i++) {
+         out[i] = (1.0f - dst[3]) * src[i] +
+            (1.0f - src[3]) * dst[i] + src[i] * dst[i];
+      }
+      out[3] = src[3] + dst[3] * (1.0f - src[3]);
+      CHECK("VG_BLEND_MULTIPLY");
+   }
    x += width + 5;
 
    /* 0.8 * red + (white - 0.8 * red) * 0.3 * green */
    vgSeti(VG_BLEND_MODE, VG_BLEND_SCREEN);
    rectangle(x, y, width, height);
+   if (check) {
+      for (i = 0; i < 4; i++)
+         out[i] = src[i] + (1.0f - src[i]) * dst[i];
+      CHECK("VG_BLEND_SCREEN");
+   }
    x += width + 5;
 
    /* min(SRC_OVER, DST_OVER) */
    vgSeti(VG_BLEND_MODE, VG_BLEND_DARKEN);
    rectangle(x, y, width, height);
+   if (check) {
+      for (i = 0; i < 4; i++) {
+         VGfloat src_over = src[i] + dst[i] * (1.0f - src[3]);
+         VGfloat dst_over = dst[i] + src[i] * (1.0f - dst[3]);
+         out[i] = (src_over < dst_over) ? src_over : dst_over;
+      }
+      CHECK("VG_BLEND_DARKEN");
+   }
    x += width + 5;
 
    /* max(SRC_OVER, DST_OVER) */
    vgSeti(VG_BLEND_MODE, VG_BLEND_LIGHTEN);
    rectangle(x, y, width, height);
+   if (check) {
+      for (i = 0; i < 4; i++) {
+         VGfloat src_over = src[i] + dst[i] * (1.0f - src[3]);
+         VGfloat dst_over = dst[i] + src[i] * (1.0f - dst[3]);
+         out[i] = (src_over > dst_over) ? src_over : dst_over;
+      }
+      CHECK("VG_BLEND_LIGHTEN");
+   }
    x += width + 5;
+
+   if (check)
+      printf("done\n");
 }
 
 static void
@@ -129,7 +235,7 @@ draw(void)
 
    x = y = 5;
    vgClear(x, y, window_width(), 20);
-   test_blend(x, y, 20, 20);
+   test_blend(x, y, 20, 20, verbose);
 
    y += window_height() / 2;
    vgClear(x, y, window_width(), 20);
@@ -137,13 +243,21 @@ draw(void)
     * This will have more green because
     *
     *   result = blended * coverage + dst * (1 - coverage)
+    *
+    * Note that impplementations may choose a different formula.
     */
-   test_blend(x, y, 20, 20);
+   test_blend(x, y, 20, 20, VG_FALSE);
 }
 
 
 int main(int argc, char **argv)
 {
+   if (argc > 1) {
+      const char *arg = argv[1];
+      if (!strcmp("-v", arg))
+         verbose = VG_TRUE;
+   }
+
    set_window_size(300, 300);
    set_window_alpha_size(1);
    return run(argc, argv, init, reshape,




More information about the mesa-commit mailing list