summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/igt_chamelium.c143
-rw-r--r--lib/igt_chamelium.h5
-rw-r--r--tests/chamelium.c77
3 files changed, 167 insertions, 58 deletions
diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c
index 93392af72..abcdc522c 100644
--- a/lib/igt_chamelium.c
+++ b/lib/igt_chamelium.c
@@ -94,6 +94,13 @@ struct chamelium_frame_dump {
struct chamelium_port *port;
};
+struct chamelium_fb_crc_async_data {
+ cairo_surface_t *fb_surface;
+
+ pthread_t thread_id;
+ igt_crc_t *ret;
+};
+
struct chamelium {
xmlrpc_env env;
xmlrpc_client *client;
@@ -998,6 +1005,142 @@ int chamelium_get_frame_limit(struct chamelium *chamelium,
return ret;
}
+static uint32_t chamelium_xrgb_hash16(const unsigned char *buffer, int width,
+ int height, int k, int m)
+{
+ unsigned char r, g, b;
+ uint64_t sum = 0;
+ uint64_t count = 0;
+ uint64_t value;
+ uint32_t hash;
+ int index;
+ int i;
+
+ for (i=0; i < width * height; i++) {
+ if ((i % m) != k)
+ continue;
+
+ index = i * 4;
+
+ r = buffer[index + 2];
+ g = buffer[index + 1];
+ b = buffer[index + 0];
+
+ value = r | (g << 8) | (b << 16);
+ sum += ++count * value;
+ }
+
+ hash = ((sum >> 0) ^ (sum >> 16) ^ (sum >> 32) ^ (sum >> 48)) & 0xffff;
+
+ return hash;
+}
+
+static void chamelium_do_calculate_fb_crc(cairo_surface_t *fb_surface,
+ igt_crc_t *out)
+{
+ unsigned char *buffer;
+ int n = 4;
+ int w, h;
+ int i, j;
+
+ buffer = cairo_image_surface_get_data(fb_surface);
+ w = cairo_image_surface_get_width(fb_surface);
+ h = cairo_image_surface_get_height(fb_surface);
+
+ for (i = 0; i < n; i++) {
+ j = n - i - 1;
+ out->crc[i] = chamelium_xrgb_hash16(buffer, w, h, j, n);
+ }
+
+ out->n_words = n;
+}
+
+/**
+ * chamelium_calculate_fb_crc:
+ * @fd: The drm file descriptor
+ * @fb: The framebuffer to calculate the CRC for
+ *
+ * Calculates the CRC for the provided framebuffer, using the Chamelium's CRC
+ * algorithm. This calculates the CRC in a synchronous fashion.
+ *
+ * Returns: The calculated CRC
+ */
+igt_crc_t *chamelium_calculate_fb_crc(int fd, struct igt_fb *fb)
+{
+ igt_crc_t *ret = calloc(1, sizeof(igt_crc_t));
+ cairo_surface_t *fb_surface;
+
+ /* Get the cairo surface for the framebuffer */
+ fb_surface = igt_get_cairo_surface(fd, fb);
+
+ chamelium_do_calculate_fb_crc(fb_surface, ret);
+
+ return ret;
+}
+
+static void *chamelium_calculate_fb_crc_async_work(void *data)
+{
+ struct chamelium_fb_crc_async_data *fb_crc;
+
+ fb_crc = (struct chamelium_fb_crc_async_data *) data;
+
+ chamelium_do_calculate_fb_crc(fb_crc->fb_surface, fb_crc->ret);
+
+ return NULL;
+}
+
+/**
+ * chamelium_calculate_fb_crc_launch:
+ * @fd: The drm file descriptor
+ * @fb: The framebuffer to calculate the CRC for
+ *
+ * Launches the CRC calculation for the provided framebuffer, using the
+ * Chamelium's CRC algorithm. This calculates the CRC in an asynchronous
+ * fashion.
+ *
+ * The returned structure should be passed to a subsequent call to
+ * chamelium_calculate_fb_crc_result. It should not be freed.
+ *
+ * Returns: An intermediate structure for the CRC calculation work.
+ */
+struct chamelium_fb_crc_async_data *chamelium_calculate_fb_crc_async_start(int fd,
+ struct igt_fb *fb)
+{
+ struct chamelium_fb_crc_async_data *fb_crc;
+
+ fb_crc = calloc(1, sizeof(struct chamelium_fb_crc_async_data));
+ fb_crc->ret = calloc(1, sizeof(igt_crc_t));
+
+ /* Get the cairo surface for the framebuffer */
+ fb_crc->fb_surface = igt_get_cairo_surface(fd, fb);
+
+ pthread_create(&fb_crc->thread_id, NULL,
+ chamelium_calculate_fb_crc_async_work, fb_crc);
+
+ return fb_crc;
+}
+
+/**
+ * chamelium_calculate_fb_crc_result:
+ * @fb_crc: An intermediate structure with thread-related information
+ *
+ * Blocks until the asynchronous CRC calculation is finished, and then returns
+ * its result.
+ *
+ * Returns: The calculated CRC
+ */
+igt_crc_t *chamelium_calculate_fb_crc_async_finish(struct chamelium_fb_crc_async_data *fb_crc)
+{
+ igt_crc_t *ret;
+
+ pthread_join(fb_crc->thread_id, NULL);
+
+ ret = fb_crc->ret;
+ free(fb_crc);
+
+ return ret;
+}
+
static unsigned int chamelium_get_port_type(struct chamelium *chamelium,
struct chamelium_port *port)
{
diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h
index 81322ad2e..2bfbfdc72 100644
--- a/lib/igt_chamelium.h
+++ b/lib/igt_chamelium.h
@@ -36,6 +36,7 @@
struct chamelium;
struct chamelium_port;
struct chamelium_frame_dump;
+struct chamelium_fb_crc_async_data;
struct chamelium *chamelium_init(int drm_fd);
void chamelium_deinit(struct chamelium *chamelium);
@@ -92,6 +93,10 @@ struct chamelium_frame_dump *chamelium_port_dump_pixels(struct chamelium *chamel
struct chamelium_port *port,
int x, int y,
int w, int h);
+igt_crc_t *chamelium_calculate_fb_crc(int fd, struct igt_fb *fb);
+struct chamelium_fb_crc_async_data *chamelium_calculate_fb_crc_async_start(int fd,
+ struct igt_fb *fb);
+igt_crc_t *chamelium_calculate_fb_crc_async_finish(struct chamelium_fb_crc_async_data *fb_crc);
int chamelium_get_captured_frame_count(struct chamelium *chamelium);
int chamelium_get_frame_limit(struct chamelium *chamelium,
struct chamelium_port *port,
diff --git a/tests/chamelium.c b/tests/chamelium.c
index 0528ffb37..ecd0434ce 100644
--- a/tests/chamelium.c
+++ b/tests/chamelium.c
@@ -49,43 +49,6 @@ typedef struct {
#define HPD_TOGGLE_COUNT_VGA 5
#define HPD_TOGGLE_COUNT_DP_HDMI 15
-/* Pre-calculated CRCs for the pattern fb, for all the modes in the default
- * chamelium edid
- */
-struct crc_entry {
- int width;
- int height;
- igt_crc_t crc;
-};
-
-#define CRC_ENTRY(w_, h_, ...) \
- { w_, h_, { .n_words = 4, .crc = { __VA_ARGS__ } } }
-
-static const struct crc_entry pattern_fb_crcs[] = {
- CRC_ENTRY(1920, 1080, 0xf859, 0xa751, 0x8c81, 0x45a1),
- CRC_ENTRY(1280, 720, 0xcec2, 0x4246, 0x6cfd, 0xeb43),
- CRC_ENTRY(1024, 768, 0x85e5, 0xf0cd, 0xafe3, 0x7f18),
- CRC_ENTRY( 800, 600, 0x6b39, 0x32b6, 0x831a, 0xb03e),
- CRC_ENTRY( 640, 480, 0xa121, 0x2473, 0xb150, 0x8c47),
-};
-#undef CRC_ENTRY
-
-static const igt_crc_t *
-get_precalculated_crc(struct chamelium_port *port, int w, int h)
-{
- int i;
- const struct crc_entry *entry;
-
- for (i = 0; i < ARRAY_SIZE(pattern_fb_crcs); i++) {
- entry = &pattern_fb_crcs[i];
-
- if (entry->width == w && entry->height == h)
- return &entry->crc;
- }
-
- return NULL;
-}
-
static void
get_connectors_link_status_failed(data_t *data, bool *link_status_failed)
{
@@ -463,7 +426,8 @@ test_display_crc_single(data_t *data, struct chamelium_port *port)
igt_output_t *output;
igt_plane_t *primary;
igt_crc_t *crc;
- const igt_crc_t *expected_crc;
+ igt_crc_t *expected_crc;
+ struct chamelium_fb_crc_async_data *fb_crc;
struct igt_fb fb;
drmModeModeInfo *mode;
drmModeConnector *connector;
@@ -486,24 +450,21 @@ test_display_crc_single(data_t *data, struct chamelium_port *port)
0, 0, 0, &fb);
igt_assert(fb_id > 0);
+ fb_crc = chamelium_calculate_fb_crc_async_start(data->drm_fd,
+ &fb);
enable_output(data, port, output, mode, &fb);
- expected_crc = get_precalculated_crc(port,
- mode->hdisplay,
- mode->vdisplay);
- if (!expected_crc) {
- igt_warn("No precalculated CRC found for %dx%d, skipping CRC check\n",
- mode->hdisplay, mode->vdisplay);
- goto next;
- }
-
igt_debug("Testing single CRC fetch\n");
+
crc = chamelium_get_crc_for_area(data->chamelium, port,
0, 0, 0, 0);
+
+ expected_crc = chamelium_calculate_fb_crc_async_finish(fb_crc);
+
igt_assert_crc_equal(crc, expected_crc);
+ free(expected_crc);
free(crc);
-next:
disable_output(data, port, output);
igt_remove_fb(data->drm_fd, &fb);
}
@@ -519,7 +480,8 @@ test_display_crc_multiple(data_t *data, struct chamelium_port *port)
igt_output_t *output;
igt_plane_t *primary;
igt_crc_t *crc;
- const igt_crc_t *expected_crc;
+ igt_crc_t *expected_crc;
+ struct chamelium_fb_crc_async_data *fb_crc;
struct igt_fb fb;
drmModeModeInfo *mode;
drmModeConnector *connector;
@@ -542,15 +504,10 @@ test_display_crc_multiple(data_t *data, struct chamelium_port *port)
0, 0, 0, &fb);
igt_assert(fb_id > 0);
- enable_output(data, port, output, mode, &fb);
+ fb_crc = chamelium_calculate_fb_crc_async_start(data->drm_fd,
+ &fb);
- expected_crc = get_precalculated_crc(port, mode->hdisplay,
- mode->vdisplay);
- if (!expected_crc) {
- igt_warn("No precalculated CRC found for %dx%d, skipping CRC check\n",
- mode->hdisplay, mode->vdisplay);
- goto next;
- }
+ enable_output(data, port, output, mode, &fb);
/* We want to keep the display running for a little bit, since
* there's always the potential the driver isn't able to keep
@@ -561,11 +518,15 @@ test_display_crc_multiple(data_t *data, struct chamelium_port *port)
&captured_frame_count);
igt_debug("Captured %d frames\n", captured_frame_count);
+
+ expected_crc = chamelium_calculate_fb_crc_async_finish(fb_crc);
+
for (j = 0; j < captured_frame_count; j++)
igt_assert_crc_equal(&crc[j], expected_crc);
+
+ free(expected_crc);
free(crc);
-next:
disable_output(data, port, output);
igt_remove_fb(data->drm_fd, &fb);
}