On Mon, 2017-07-17 at 13:35 -0400, Lyude Paul wrote: > Just one change for this patch below > > On Wed, 2017-07-12 at 17:57 +0300, Paul Kocialkowski wrote: > > This adds support for VGA frame comparison testing with the > > reference > > generated from cairo. The retrieved frame from the chamelium is > > first > > cropped, as it contains the blanking intervals, through a dedicated > > helper. Another helper function asserts that the analogue frame > > matches or dump it to png if not. > > > > Signed-off-by: Paul Kocialkowski <paul.kocialkowski@xxxxxxxxxxxxxxx> > > --- > > lib/igt_chamelium.c | 164 > > ++++++++++++++++++++++++++++++++++++++++++++++++++-- > > lib/igt_chamelium.h | 7 ++- > > lib/igt_frame.c | 6 +- > > tests/chamelium.c | 57 ++++++++++++++++++ > > 4 files changed, 225 insertions(+), 9 deletions(-) > > > > diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c > > index df49936b..8701192e 100644 > > --- a/lib/igt_chamelium.c > > +++ b/lib/igt_chamelium.c > > @@ -938,6 +938,8 @@ static cairo_surface_t > > *convert_frame_dump_argb32(const struct chamelium_frame_d > > int w = dump->width, h = dump->height; > > uint32_t *bits_bgr = (uint32_t *) dump->bgr; > > unsigned char *bits_argb; > > + unsigned char *bits_target; > > + int size; > > > > image_bgr = pixman_image_create_bits( > > PIXMAN_b8g8r8, w, h, bits_bgr, > > @@ -947,9 +949,13 @@ static cairo_surface_t > > *convert_frame_dump_argb32(const struct chamelium_frame_d > > > > bits_argb = (unsigned char *) > > pixman_image_get_data(image_argb); > > > > - dump_surface = cairo_image_surface_create_for_data( > > - bits_argb, CAIRO_FORMAT_ARGB32, w, h, > > - PIXMAN_FORMAT_BPP(PIXMAN_x8r8g8b8) / 8 * w); > > + dump_surface = cairo_image_surface_create( > > + CAIRO_FORMAT_ARGB32, w, h); > > + > > + bits_target = cairo_image_surface_get_data(dump_surface); > > + size = cairo_image_surface_get_stride(dump_surface) * h; > > + memcpy(bits_target, bits_argb, size); > > + cairo_surface_mark_dirty(dump_surface); > > > > pixman_image_unref(image_argb); > > > > @@ -1055,6 +1061,154 @@ void chamelium_assert_crc_eq_or_dump(struct > > chamelium *chamelium, > > } > > > > /** > > + * chamelium_assert_analogue_frame_match_or_dump: > > + * @chamelium: The chamelium instance the frame dump belongs to > > + * @frame: The chamelium frame dump to match > > + * @fb: pointer to an #igt_fb structure > > + * > > + * Asserts that the provided captured frame matches the reference > > frame from > > + * the framebuffer. If they do not, this saves the reference and > > captured frames > > + * to a png file. > > + */ > > +void chamelium_assert_analogue_frame_match_or_dump(struct chamelium > > *chamelium, > > + struct > > chamelium_port *port, > > + const struct > > chamelium_frame_dump *frame, > > + struct igt_fb > > *fb) > > +{ > > + cairo_surface_t *reference; > > + cairo_surface_t *capture; > > + igt_crc_t *reference_crc; > > + igt_crc_t *capture_crc; > > + char *reference_suffix; > > + char *capture_suffix; > > + bool match; > > + > > + /* Grab the reference frame from framebuffer */ > > + reference = igt_get_cairo_surface(chamelium->drm_fd, fb); > > + > > + /* Grab the captured frame from chamelium */ > > + capture = convert_frame_dump_argb32(frame); > > + > > + match = igt_check_analogue_frame_match(reference, capture); > > + if (!match && igt_frame_dump_is_enabled()) { > > + reference_crc = > > chamelium_calculate_fb_crc(chamelium- > > > drm_fd, > > > > + fb); > > + capture_crc = chamelium_get_crc_for_area(chamelium, > > port, 0, 0, > > + 0, 0); > > + > > + reference_suffix = > > igt_crc_to_string_extended(reference_crc, > > + '-', > > 2); > > + capture_suffix = > > igt_crc_to_string_extended(capture_crc, '-', > > + 2); > > + > > + /* Write reference and capture frames to png */ > > + igt_write_compared_frames_to_png(reference, capture, > > + reference_suffix, > > + capture_suffix); > > + > > + free(reference_suffix); > > + free(capture_suffix); > > + } > > + > > + cairo_surface_destroy(capture); > > + > > + igt_assert(match); > > +} > > + > > + > > +/** > > + * chamelium_analogue_frame_crop: > > + * @chamelium: The Chamelium instance to use > > + * @dump: The chamelium frame dump to crop > > + * @width: The cropped frame width > > + * @height: The cropped frame height > > + * > > + * Detects the corners of a chamelium frame and crops it to the > > requested > > + * width/height. This is useful for VGA frame dumps that also > > contain the > > + * pixels dumped during the blanking intervals. > > + * > > + * The detection is done on a brightness-threshold-basis, that is > > adapted > > + * to the reference frame used by i-g-t. It may not be as relevant > > for other > > + * frames. > > + */ > > +void chamelium_crop_analogue_frame(struct chamelium_frame_dump > > *dump, int width, > > + int height) > > +{ > > + unsigned char *bgr; > > + unsigned char *p; > > + unsigned char *q; > > + int top, left; > > + int x, y, xx, yy; > > + int score; > > + > > + if (dump->width == width && dump->height == height) > > + return; > > + > > + /* Start with the most bottom-right position. */ > > + top = dump->height - height; > > + left = dump->width - width; > > + > > + igt_assert(top >= 0 && left >= 0); > > + > > + igt_debug("Cropping analogue frame from %dx%d to %dx%d\n", > > dump->width, > > + dump->height, width, height); > > + > > + /* Detect the top-left corner of the frame. */ > > + for (x = 0; x < dump->width; x++) { > > + for (y = 0; y < dump->height; y++) { > > + p = &dump->bgr[(x + y * dump->width) * 3]; > > + > > + /* Detect significantly bright pixels. */ > > + if (p[0] < 50 && p[1] < 50 && p[2] < 50) > > + continue; > > + > > + /* > > + * Make sure close-by pixels are also > > significantly > > + * bright. > > + */ > > + score = 0; > > + for (xx = x; xx < x + 10; xx++) { > > + for (yy = y; yy < y + 10; yy++) { > > + p = &dump->bgr[(xx + yy * > > dump->width) * 3]; > > + > > + if (p[0] > 50 && p[1] > 50 > > && > > p[2] > 50) > > + score++; > > + } > > + } > > + > > + /* Not enough pixels are significantly > > bright. */ > > + if (score < 25) > > + continue; > > + > > + if (x < left) > > + left = x; > > + > > + if (y < top) > > + top = y; > > + > > + if (left == x || top == y) > > + continue; > > + } > > + } > > + > > + igt_debug("Detected analogue frame edges at %dx%d\n", left, > > top); > > + > > + /* Crop the frame given the detected top-left corner. */ > > + bgr = malloc(width * height * 3); > > + > > + for (y = 0; y < height; y++) { > > + p = &dump->bgr[(left + (top + y) * dump->width) * > > 3]; > > + q = &bgr[(y * width) * 3]; > > + memcpy(q, p, width * 3); > > + } > > + > > + free(dump->bgr); > > + dump->width = width; > > + dump->height = height; > > + dump->bgr = bgr; > > +} > > + > > +/** > > * chamelium_get_frame_limit: > > * @chamelium: The Chamelium instance to use > > * @port: The port to check the frame limit on > > @@ -1480,7 +1634,7 @@ igt_constructor { > > /* Frame dumps can be large, so we need to be able to handle > > very large > > * responses > > * > > - * Limit here is 10MB > > + * Limit here is 15MB > > */ > > - xmlrpc_limit_set(XMLRPC_XML_SIZE_LIMIT_ID, 10485760); > > + xmlrpc_limit_set(XMLRPC_XML_SIZE_LIMIT_ID, 15728640); > > } > > diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h > > index 80afcafa..101e64b6 100644 > > --- a/lib/igt_chamelium.h > > +++ b/lib/igt_chamelium.h > > @@ -101,7 +101,6 @@ int chamelium_get_captured_frame_count(struct > > chamelium *chamelium); > > int chamelium_get_frame_limit(struct chamelium *chamelium, > > struct chamelium_port *port, > > int w, int h); > > - > > void chamelium_assert_frame_eq(const struct chamelium *chamelium, > > const struct chamelium_frame_dump > > *dump, > > struct igt_fb *fb); > > @@ -109,6 +108,12 @@ void chamelium_assert_crc_eq_or_dump(struct > > chamelium *chamelium, > > igt_crc_t *reference_crc, > > igt_crc_t *capture_crc, struct > > igt_fb *fb, > > int index); > > +void chamelium_assert_analogue_frame_match_or_dump(struct chamelium > > *chamelium, > > + struct > > chamelium_port *port, > > + const struct > > chamelium_frame_dump *frame, > > + struct igt_fb > > *fb); > > +void chamelium_crop_analogue_frame(struct chamelium_frame_dump > > *dump, int width, > > + int height); > > void chamelium_destroy_frame_dump(struct chamelium_frame_dump > > *dump); > > > > #endif /* IGT_CHAMELIUM_H */ > > diff --git a/lib/igt_frame.c b/lib/igt_frame.c > > index dc84fe01..8ca110c9 100644 > > --- a/lib/igt_frame.c > > +++ b/lib/igt_frame.c > > @@ -204,13 +204,13 @@ bool > > igt_check_analogue_frame_match(cairo_surface_t *reference, > > p = &capture_pixels[(x + y * w) * 4]; > > q = &reference_pixels[(x + y * w) * 4]; > > > > - for (i = 1; i < 4; i++) { > > + for (i = 0; i < 3; 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]++; > > + error_count[i][q[i]][0] += diff; > > + error_count[i][q[i]][1]++; > > Am I missing something? This change seems like it should just be part > of patch #1 instead of being done afterwards in patch #2. Woops, looks like I messed this one up when crafting the new version. Thanks for catching it! > > } > > } > > } > > diff --git a/tests/chamelium.c b/tests/chamelium.c > > index 89a3bde0..baaa424b 100644 > > --- a/tests/chamelium.c > > +++ b/tests/chamelium.c > > @@ -358,6 +358,10 @@ enable_output(data_t *data, > > BROADCAST_RGB_FULL); > > > > igt_display_commit(display); > > + > > + if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA) > > + usleep(250000); > > + > > chamelium_port_wait_video_input_stable(data->chamelium, > > port, > > HOTPLUG_TIMEOUT); > > > > @@ -492,6 +496,56 @@ test_display_frame_dump(data_t *data, struct > > chamelium_port *port) > > } > > > > static void > > +test_analogue_frame_dump(data_t *data, struct chamelium_port *port) > > +{ > > + igt_display_t display; > > + igt_output_t *output; > > + igt_plane_t *primary; > > + struct igt_fb fb; > > + struct chamelium_frame_dump *frame; > > + drmModeModeInfo *mode; > > + drmModeConnector *connector; > > + int fb_id, i; > > + > > + output = prepare_output(data, &display, port); > > + connector = chamelium_port_get_connector(data->chamelium, > > port, false); > > + primary = igt_output_get_plane_type(output, > > DRM_PLANE_TYPE_PRIMARY); > > + igt_assert(primary); > > + > > + for (i = 0; i < connector->count_modes; i++) { > > + mode = &connector->modes[i]; > > + > > + fb_id = igt_create_color_pattern_fb(data->drm_fd, > > + mode->hdisplay, > > mode->vdisplay, > > + DRM_FORMAT_XRGB8 > > 8 > > 88, > > + LOCAL_DRM_FORMAT > > _ > > MOD_NONE, > > + 0, 0, 0, &fb); > > + igt_assert(fb_id > 0); > > + > > + enable_output(data, port, output, mode, &fb); > > + > > + igt_debug("Reading frame dumps from > > Chamelium...\n"); > > + > > + frame = chamelium_port_dump_pixels(data->chamelium, > > port, 0, 0, > > + 0, 0); > > + > > + chamelium_crop_analogue_frame(frame, mode->hdisplay, > > + mode->vdisplay); > > + > > + chamelium_assert_analogue_frame_match_or_dump(data- > > > chamelium, > > > > + port, > > frame, &fb); > > + > > + chamelium_destroy_frame_dump(frame); > > + > > + disable_output(data, port, output); > > + igt_remove_fb(data->drm_fd, &fb); > > + } > > + > > + drmModeFreeConnector(connector); > > + igt_display_fini(&display); > > +} > > + > > +static void > > test_hpd_without_ddc(data_t *data, struct chamelium_port *port) > > { > > struct udev_monitor *mon = igt_watch_hotplug(); > > @@ -734,6 +788,9 @@ igt_main > > > > connector_subtest("vga-hpd-without-ddc", VGA) > > test_hpd_without_ddc(&data, port); > > + > > + connector_subtest("vga-frame-dump", VGA) > > + test_analogue_frame_dump(&data, port); > > } > > > > igt_subtest_group { > > -- > > 2.13.2 > > -- Paul Kocialkowski <paul.kocialkowski@xxxxxxxxxxxxxxx> Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo, Finland _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx