Index: third_party/qcms/src/tests/qcms_test_tetra_clut_rgba.c |
diff --git a/third_party/qcms/src/tests/qcms_test_tetra_clut_rgba.c b/third_party/qcms/src/tests/qcms_test_tetra_clut_rgba.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..81b6ee3287615cce3cd1683a963a1eb9c313f5e4 |
--- /dev/null |
+++ b/third_party/qcms/src/tests/qcms_test_tetra_clut_rgba.c |
@@ -0,0 +1,180 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the Chromium LICENSE file. |
+ |
+#include "qcms.h" |
+#include "qcms_test_util.h" |
+#include "timing.h" |
+ |
+#include <math.h> |
+#include <stdio.h> |
+#include <stdlib.h> |
+#include <string.h> |
+ |
+// External qcms tetra clut interpolators. |
+ |
+extern void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, |
+ unsigned char *src, |
+ unsigned char *dest, |
+ size_t length, |
+ qcms_format_type output_format); |
+ |
+#ifdef SSE2_ENABLE |
+extern void qcms_transform_data_tetra_clut_rgba_sse2(qcms_transform *transform, |
+ unsigned char *src, |
+ unsigned char *dest, |
+ size_t length, |
+ qcms_format_type output_format); |
+#else |
+void qcms_transform_data_tetra_clut_rgba_dummy(qcms_transform *transform, |
+ unsigned char *src, |
+ unsigned char *dest, |
+ size_t length, |
+ qcms_format_type output_format) |
+{ |
+ (void)(transform); |
+ (void)(src); |
+ (void)(dest); |
+ (void)(length); |
+ (void)(output_format); |
+} |
+#endif |
+ |
+static float *create_lut(size_t lutSize) |
+{ |
+ float *lut = malloc(lutSize * sizeof(float)); |
+ size_t i; |
+ |
+ for (i = 0; i < lutSize; ++i) { |
+ lut[i] = (rand() & 255) * (1.0f / 255.0f); |
+ } |
+ |
+ return lut; |
+} |
+ |
+static int diffs; |
+ |
+static int validate(unsigned char *dst0, unsigned char *dst1, size_t length, int limit, const size_t pixel_size) |
+{ |
+ size_t bytes = length * pixel_size; |
+ size_t i; |
+ |
+ // Compare dst0/dst0 byte-by-byte, allowing for minor differences due |
+ // to SSE rounding modes (controlled by the limit argument). |
+ |
+ if (limit < 0) |
+ limit = 255; // Ignore all differences. |
+ |
+ for (diffs = 0, i = 0; i < bytes; ++i) { |
+ if (abs((int)dst0[i] - (int)dst1[i]) > limit) { |
+ ++diffs; |
+ } |
+ } |
+ |
+ return !diffs; |
+} |
+ |
+static int qcms_test_tetra_clut_rgba(size_t width, |
+ size_t height, |
+ int iterations, |
+ const char *in_profile, |
+ const char *out_profile, |
+ const int force_software) |
+{ |
+ qcms_transform transform0, transform1; |
+ qcms_format_type format = {2, 0}; |
+ uint16_t samples = 33; |
+ size_t lutSize; |
+ float *lut0, *lut1; |
+ |
+ const size_t length = width * height; |
+ const size_t pixel_size = 4; |
+ |
+ double time0, time1; |
+ int i; |
+ |
+ printf("Test qcms clut transforms for %d iterations\n", iterations); |
+ printf("Test image size %u x %u pixels\n", (unsigned) width, (unsigned) height); |
+ fflush(stdout); |
+ |
+ srand(0); |
+ seconds(); |
+ |
+ memset(&transform0, 0, sizeof(transform0)); |
+ memset(&transform1, 0, sizeof(transform1)); |
+ |
+ transform0.grid_size = samples; |
+ transform1.grid_size = samples; |
+ |
+ transform0.transform_flags = 0; |
+ transform1.transform_flags = 0; |
+ |
+ lutSize = 3 * samples * samples * samples; |
+ lut0 = create_lut(lutSize); |
+ lut1 = (float *)malloc(lutSize * sizeof(float)); |
+ memcpy(lut1, lut0, lutSize * sizeof(float)); |
+ |
+ transform0.r_clut = &lut0[0]; |
+ transform0.g_clut = &lut0[1]; |
+ transform0.b_clut = &lut0[2]; |
+ |
+ transform1.r_clut = &lut1[0]; |
+ transform1.g_clut = &lut1[1]; |
+ transform1.b_clut = &lut1[2]; |
+ |
+ // Re-generate and use different data sources during the iteration loop |
+ // to avoid compiler / cache optimizations that may affect performance. |
+ |
+ time0 = 0.0; |
+ time1 = 0.0; |
+ |
+ for (i = 0; i < iterations; ++i) { |
+ unsigned char *src0 = (unsigned char *)calloc(length, pixel_size); |
+ unsigned char *src1 = (unsigned char *)calloc(length, pixel_size); |
+ unsigned char *dst0 = (unsigned char *)calloc(length, pixel_size); |
+ unsigned char *dst1 = (unsigned char *)calloc(length, pixel_size); |
+ |
+ generate_source_uint8_t(src0, length, pixel_size); |
+ memcpy(src1, src0, length * pixel_size); |
+ |
+#define TRANSFORM_TEST0 qcms_transform_data_tetra_clut_rgba |
+#ifdef SSE2_ENABLE |
+#define TRANSFORM_TEST1 qcms_transform_data_tetra_clut_rgba_sse2 |
+#else |
+#define TRANSFORM_TEST1 qcms_transform_data_tetra_clut_rgba_dummy |
+#endif |
+ |
+ TIME(TRANSFORM_TEST0(&transform0, src0, dst0, length, format), &time0); |
+ TIME(TRANSFORM_TEST1(&transform1, src1, dst1, length, format), &time1); |
+ |
+ if (!validate(dst0, dst1, length, 0, pixel_size)) { |
+ fprintf(stderr, "Invalid transform output: %d diffs\n", diffs); |
+ } |
+ |
+ free(src0); |
+ free(src1); |
+ free(dst0); |
+ free(dst1); |
+ } |
+ |
+#define STRINGIZE(s) #s |
+#define STRING(s) STRINGIZE(s) |
+ |
+ printf("%.6lf (avg %.6lf) seconds " STRING(TRANSFORM_TEST0) "\n", |
+ time0, time0 / iterations); |
+ printf("%.6lf (avg %.6lf) seconds " STRING(TRANSFORM_TEST1) "\n", |
+ time1, time1 / iterations); |
+ printf("%.6lf speedup after %d iterations\n\n", |
+ time0 / time1, iterations); |
+ |
+ free(lut0); |
+ free(lut1); |
+ |
+ return diffs; |
+} |
+ |
+struct qcms_test_case qcms_test_tetra_clut_rgba_info = { |
+ "qcms_test_tetra_clut_rgba", |
+ qcms_test_tetra_clut_rgba, |
+ QCMS_TEST_DISABLED |
+}; |