From patchwork Wed Jul 12 14:57:11 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Kocialkowki X-Patchwork-Id: 9836923 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 464F560363 for ; Wed, 12 Jul 2017 14:57:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3796F285F7 for ; Wed, 12 Jul 2017 14:57:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2C24A28607; Wed, 12 Jul 2017 14:57:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 54C76285F7 for ; Wed, 12 Jul 2017 14:57:32 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D36576E41D; Wed, 12 Jul 2017 14:57:31 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by gabe.freedesktop.org (Postfix) with ESMTPS id C04E46E41D for ; Wed, 12 Jul 2017 14:57:29 +0000 (UTC) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 12 Jul 2017 07:57:29 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.40,350,1496127600"; d="scan'208";a="110490376" Received: from linux.intel.com ([10.54.29.200]) by orsmga002.jf.intel.com with ESMTP; 12 Jul 2017 07:57:29 -0700 Received: from workstation.fi.intel.com (workstation.fi.intel.com [10.237.68.144]) by linux.intel.com (Postfix) with ESMTP id 7B42C5807D9; Wed, 12 Jul 2017 07:57:27 -0700 (PDT) From: Paul Kocialkowski To: intel-gfx@lists.freedesktop.org Date: Wed, 12 Jul 2017 17:57:11 +0300 Message-Id: <20170712145712.3871-2-paul.kocialkowski@linux.intel.com> X-Mailer: git-send-email 2.13.2 In-Reply-To: <20170712145712.3871-1-paul.kocialkowski@linux.intel.com> References: <20170706132614.4163-1-paul.kocialkowski@linux.intel.com> <20170712145712.3871-1-paul.kocialkowski@linux.intel.com> Cc: Lyude Subject: [Intel-gfx] [PATCH i-g-t v2 1/2] lib/igt_frame: Add support for analogue frame comparison testing X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP This adds support for analogue frame comparison check, as used in VGA. Since VGA uses a DAC-ADC chain, its data cannot be expected to be pixel perfect. Thus, it is impossible to uses a CRC check and full frames have to be analyzed instead. Such an analysis is implemented, based on both an absolute error threshold and a correlation with the expected error trend for a DAC-ADC chain. It was tested with a couple encoders and provides reliable error detection with few false positives. Signed-off-by: Paul Kocialkowski --- configure.ac | 1 + lib/Makefile.am | 2 + lib/igt_frame.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/igt_frame.h | 2 + 4 files changed, 136 insertions(+) diff --git a/configure.ac b/configure.ac index bf09927c..63ed4d27 100644 --- a/configure.ac +++ b/configure.ac @@ -178,6 +178,7 @@ if test x"$udev" = xyes; then AC_DEFINE(HAVE_UDEV,1,[Enable udev-based monitor hotplug detection]) fi PKG_CHECK_MODULES(GLIB, glib-2.0) +PKG_CHECK_MODULES(GSL, gsl) # for chamelium PKG_CHECK_MODULES(XMLRPC, xmlrpc_client, [xmlrpc=yes], [xmlrpc=no]) diff --git a/lib/Makefile.am b/lib/Makefile.am index d4f41128..fb922ced 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -35,6 +35,7 @@ AM_CFLAGS = \ $(DRM_CFLAGS) \ $(PCIACCESS_CFLAGS) \ $(LIBUNWIND_CFLAGS) \ + $(GSL_CFLAGS) \ $(KMOD_CFLAGS) \ $(PROCPS_CFLAGS) \ $(DEBUG_CFLAGS) \ @@ -54,6 +55,7 @@ libintel_tools_la_LIBADD = \ $(DRM_LIBS) \ $(PCIACCESS_LIBS) \ $(PROCPS_LIBS) \ + $(GSL_LIBS) \ $(KMOD_LIBS) \ $(CAIRO_LIBS) \ $(LIBUDEV_LIBS) \ diff --git a/lib/igt_frame.c b/lib/igt_frame.c index dfafe53d..dc84fe01 100644 --- a/lib/igt_frame.c +++ b/lib/igt_frame.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include "igt.h" @@ -135,3 +137,132 @@ void igt_write_compared_frames_to_png(cairo_surface_t *reference, close(fd); } + +/** + * igt_check_analogue_frame_match: + * @reference: The reference cairo surface + * @capture: The captured cairo surface + * + * Checks that the analogue image contained in the chamelium frame dump matches + * the given framebuffer. + * + * In order to determine whether the frame matches the reference, the following + * reasoning is implemented: + * 1. The absolute error for each color value of the reference is collected. + * 2. The average absolute error is calculated for each color value of the + * reference and must not go above 60 (23.5 % of the total range). + * 3. A linear fit for the average absolute error from the pixel value is + * calculated, as a DAC-ADC chain is expected to have a linear error curve. + * 4. The linear fit is correlated with the actual average absolute error for + * the frame and the correlation coefficient is checked to be > 0.985, + * indicating a match with the expected error trend. + * + * Most errors (e.g. due to scaling, rotation, color space, etc) can be + * reliably detected this way, with a minimized number of false-positives. + * However, the brightest values (250 and up) are ignored as the error trend + * is often not linear there in practice due to clamping. + * + * Returns: a boolean indicating whether the frames match + */ + +bool igt_check_analogue_frame_match(cairo_surface_t *reference, + cairo_surface_t *capture) +{ + pixman_image_t *reference_src, *capture_src; + int w, h; + int error_count[3][256][2] = { 0 }; + double error_average[4][250]; + double error_trend[250]; + double c0, c1, cov00, cov01, cov11, sumsq; + double correlation; + unsigned char *reference_pixels, *capture_pixels; + unsigned char *p; + unsigned char *q; + bool match = true; + int diff; + int x, y; + int i, j; + + w = cairo_image_surface_get_width(reference); + h = cairo_image_surface_get_height(reference); + + reference_src = pixman_image_create_bits( + PIXMAN_x8r8g8b8, w, h, + (void*)cairo_image_surface_get_data(reference), + cairo_image_surface_get_stride(reference)); + reference_pixels = (unsigned char *) pixman_image_get_data(reference_src); + + capture_src = pixman_image_create_bits( + PIXMAN_x8r8g8b8, w, h, + (void*)cairo_image_surface_get_data(capture), + cairo_image_surface_get_stride(capture)); + capture_pixels = (unsigned char *) pixman_image_get_data(capture_src); + + /* Collect the absolute error for each color value */ + for (x = 0; x < w; x++) { + for (y = 0; y < h; y++) { + p = &capture_pixels[(x + y * w) * 4]; + q = &reference_pixels[(x + y * w) * 4]; + + for (i = 1; i < 4; i++) { + diff = (int) p[i] - q[i]; + if (diff < 0) + diff = -diff; + + error_count[i-1][q[i-1]][0] += diff; + error_count[i-1][q[i-1]][1]++; + } + } + } + + /* Calculate the average absolute error for each color value */ + for (i = 0; i < 250; i++) { + error_average[0][i] = i; + + for (j = 1; j < 4; j++) { + error_average[j][i] = (double) error_count[j-1][i][0] / + error_count[j-1][i][1]; + + if (error_average[j][i] > 60) { + igt_warn("Error average too high (%f)\n", + error_average[j][i]); + + match = false; + goto complete; + } + } + } + + /* + * Calculate error trend from linear fit. + * A DAC-ADC chain is expected to have a linear absolute error on + * most of its range + */ + for (i = 1; i < 4; i++) { + gsl_fit_linear((const double *) &error_average[0], 1, + (const double *) &error_average[i], 1, 250, + &c0, &c1, &cov00, &cov01, &cov11, &sumsq); + + for (j = 0; j < 250; j++) + error_trend[j] = c0 + j * c1; + + correlation = gsl_stats_correlation((const double *) &error_trend, + 1, + (const double *) &error_average[i], + 1, 250); + + if (correlation < 0.985) { + igt_warn("Error with reference not correlated (%f)\n", + correlation); + + match = false; + goto complete; + } + } + +complete: + pixman_image_unref(reference_src); + pixman_image_unref(capture_src); + + return match; +} diff --git a/lib/igt_frame.h b/lib/igt_frame.h index ec6a1643..2427b33b 100644 --- a/lib/igt_frame.h +++ b/lib/igt_frame.h @@ -39,5 +39,7 @@ void igt_write_compared_frames_to_png(cairo_surface_t *reference, cairo_surface_t *capture, const char *reference_suffix, const char *capture_suffix); +bool igt_check_analogue_frame_match(cairo_surface_t *reference, + cairo_surface_t *capture); #endif