diff options
author | robert.bradford <robert.bradford@intel.com> | 2015-05-12 10:27:12 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-05-12 17:27:26 +0000 |
commit | e0469a68bcc7a037f52642dae821ad05d9cf67d2 (patch) | |
tree | 26516e2f14a21b75707dedb5eddb5d80553a9ff0 /third_party | |
parent | 7109355da4f837784b1db260385280c928b2dcbb (diff) | |
download | chromium_src-e0469a68bcc7a037f52642dae821ad05d9cf67d2.zip chromium_src-e0469a68bcc7a037f52642dae821ad05d9cf67d2.tar.gz chromium_src-e0469a68bcc7a037f52642dae821ad05d9cf67d2.tar.bz2 |
qcms: Drop the google.patch file
Rather than having a file that must be kept current with all changes to
third_party/qcms/src highlight in the README.Chromium how the changes
since the import can be readily seen.
R=noel@chromium.org
BUG=None
TEST=None
Review URL: https://codereview.chromium.org/1136283002
Cr-Commit-Position: refs/heads/master@{#329431}
Diffstat (limited to 'third_party')
-rw-r--r-- | third_party/qcms/README.chromium | 8 | ||||
-rw-r--r-- | third_party/qcms/google.patch | 1699 |
2 files changed, 4 insertions, 1703 deletions
diff --git a/third_party/qcms/README.chromium b/third_party/qcms/README.chromium index 0e3ec7b..3548a0f 100644 --- a/third_party/qcms/README.chromium +++ b/third_party/qcms/README.chromium @@ -16,8 +16,7 @@ Local Modifications: Some files only have license headers in the master branch. - Added the same license headers to the versions brought down from the 'v4' branch src URL qcms/tree/v4 -google.patch contains the following modifications. Apply with - patch -p1 < google.patch. +The following changes have been made since qcms was imported: - Add bgra output support. - Use HAVE_POSIX_MEMALIGN instead of HAS_POSIX_MEMALIG (https://bugzilla.mozilla.org/show_bug.cgi?id=692922) @@ -67,5 +66,6 @@ google.patch contains the following modifications. Apply with - https://code.google.com/p/chromium/issues/detail?id=471749 - Limit vcgt table to a maximum of 1024 entries - https://code.google.com/p/chromium/issues/detail?id=471749 -To regenerate google.patch: - git diff b8456f38 src > google.patch + +For the Chromium changes, since the import, in a patch format run: + git diff b8456f38 src diff --git a/third_party/qcms/google.patch b/third_party/qcms/google.patch deleted file mode 100644 index 0b0b8b9..0000000 --- a/third_party/qcms/google.patch +++ /dev/null @@ -1,1699 +0,0 @@ -diff --git a/third_party/qcms/src/iccread.c b/third_party/qcms/src/iccread.c -index 36b7011..0deab10 100644 ---- a/third_party/qcms/src/iccread.c -+++ b/third_party/qcms/src/iccread.c -@@ -266,7 +266,7 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile) - if (profile->color_space != RGB_SIGNATURE) - return false; - -- if (profile->A2B0 || profile->B2A0) -+ if (qcms_supports_iccv4 && (profile->A2B0 || profile->B2A0)) - return false; - - rX = s15Fixed16Number_to_float(profile->redColorant.X); -@@ -297,6 +297,11 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile) - sum[1] = rY + gY + bY; - sum[2] = rZ + gZ + bZ; - -+#if defined (_MSC_VER) -+#pragma warning(push) -+/* Disable double to float truncation warning 4305 */ -+#pragma warning(disable:4305) -+#endif - // Build our target vector (see mozilla bug 460629) - target[0] = 0.96420; - target[1] = 1.00000; -@@ -310,6 +315,10 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile) - tolerance[1] = 0.02; - tolerance[2] = 0.04; - -+#if defined (_MSC_VER) -+/* Restore warnings */ -+#pragma warning(pop) -+#endif - // Compare with our tolerance - for (i = 0; i < 3; ++i) { - if (!(((sum[i] - tolerance[i]) <= target[i]) && -@@ -331,6 +340,8 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile) - #define TAG_A2B0 0x41324230 - #define TAG_B2A0 0x42324130 - #define TAG_CHAD 0x63686164 -+#define TAG_desc 0x64657363 -+#define TAG_vcgt 0x76636774 - - static struct tag *find_tag(struct tag_index index, uint32_t tag_id) - { -@@ -344,6 +355,215 @@ static struct tag *find_tag(struct tag_index index, uint32_t tag_id) - return tag; - } - -+#define DESC_TYPE 0x64657363 // 'desc' -+#define MLUC_TYPE 0x6d6c7563 // 'mluc' -+#define MMOD_TYPE 0x6D6D6F64 // 'mmod' -+#define VCGT_TYPE 0x76636774 // 'vcgt' -+ -+// Check unsigned short is uint16_t. -+typedef char assert_short_not_16b[(sizeof(unsigned short) == sizeof(uint16_t)) ? 1 : -1]; -+ -+qcms_bool read_tag_vcgtType(qcms_profile *profile, struct mem_source *src, struct tag_index index) { -+ size_t tag_offset = find_tag(index, TAG_vcgt)->offset; -+ uint32_t tag_type = read_u32(src, tag_offset); -+ uint32_t vcgt_type = read_u32(src, tag_offset + 8); -+ uint16_t channels = read_u16(src, tag_offset + 12); -+ uint16_t elements = read_u16(src, tag_offset + 14); -+ uint16_t byte_depth = read_u16(src, tag_offset + 16); -+ size_t table_offset = tag_offset + 18; -+ uint32_t i; -+ uint16_t *dest; -+ -+ if (!src->valid || tag_type != VCGT_TYPE) -+ goto invalid_vcgt_tag; -+ -+ // Only support 3 channels. -+ if (channels != 3) -+ return true; -+ // Only support single or double byte values. -+ if (byte_depth != 1 && byte_depth != 2) -+ return true; -+ // Only support table data, not equation. -+ if (vcgt_type != 0) -+ return true; -+ // Limit the table to a sensible size; 10-bit gamma is a reasonable -+ // maximum for hardware correction. -+ if (elements > 1024) -+ return true; -+ -+ // Empty table is invalid. -+ if (!elements) -+ goto invalid_vcgt_tag; -+ -+ profile->vcgt.length = elements; -+ profile->vcgt.data = malloc(3 * elements * sizeof(uint16_t)); -+ if (!profile->vcgt.data) -+ return false; -+ -+ dest = profile->vcgt.data; -+ -+ for (i = 0; i < 3 * elements; ++i) { -+ if (byte_depth == 1) { -+ *dest++ = read_u8(src, table_offset) * 256; -+ } else { -+ *dest++ = read_u16(src, table_offset); -+ } -+ -+ table_offset += byte_depth; -+ -+ if (!src->valid) -+ goto invalid_vcgt_tag; -+ } -+ -+ return true; -+ -+invalid_vcgt_tag: -+ invalid_source(src, "invalid vcgt tag"); -+ return false; -+} -+ -+static bool read_tag_descType(qcms_profile *profile, struct mem_source *src, struct tag_index index, uint32_t tag_id) -+{ -+ struct tag *tag = find_tag(index, tag_id); -+ if (tag) { -+ const uint32_t limit = sizeof profile->description; -+ uint32_t offset = tag->offset; -+ uint32_t type = read_u32(src, offset); -+ uint32_t length = read_u32(src, offset+8); -+ uint32_t i, description_offset; -+ bool mluc = false; -+ if (length && type == MLUC_TYPE) { -+ length = read_u32(src, offset+20); -+ if (!length || (length & 1) || (read_u32(src, offset+12) != 12)) -+ goto invalid_desc_tag; -+ description_offset = offset + read_u32(src, offset+24); -+ if (!src->valid) -+ goto invalid_desc_tag; -+ mluc = true; -+ } else if (length && type == DESC_TYPE) { -+ description_offset = offset + 12; -+ } else { -+ goto invalid_desc_tag; -+ } -+ if (length >= limit) -+ length = limit - 1; -+ for (i = 0; i < length; ++i) { -+ uint8_t value = read_u8(src, description_offset + i); -+ if (!src->valid) -+ goto invalid_desc_tag; -+ if (mluc && !value) -+ value = '.'; -+ profile->description[i] = value; -+ } -+ profile->description[length] = 0; -+ } else { -+ goto invalid_desc_tag; -+ } -+ -+ if (src->valid) -+ return true; -+ -+invalid_desc_tag: -+ invalid_source(src, "invalid description"); -+ return false; -+} -+ -+#if defined(__APPLE__) -+ -+// Use the dscm tag to change profile description "Display" to its more specific en-localized monitor name, if any. -+ -+#define TAG_dscm 0x6473636D // 'dscm' -+ -+static bool read_tag_dscmType(qcms_profile *profile, struct mem_source *src, struct tag_index index, uint32_t tag_id) -+{ -+ if (strcmp(profile->description, "Display") != 0) -+ return true; -+ -+ struct tag *tag = find_tag(index, tag_id); -+ if (tag) { -+ uint32_t offset = tag->offset; -+ uint32_t type = read_u32(src, offset); -+ uint32_t records = read_u32(src, offset+8); -+ -+ if (!src->valid || !records || type != MLUC_TYPE) -+ goto invalid_dscm_tag; -+ if (read_u32(src, offset+12) != 12) // MLUC record size: bytes -+ goto invalid_dscm_tag; -+ -+ for (uint32_t i = 0; i < records; ++i) { -+ const uint32_t limit = sizeof profile->description; -+ const uint16_t isoen = 0x656E; // ISO-3166-1 language 'en' -+ -+ uint16_t language = read_u16(src, offset + 16 + (i * 12) + 0); -+ uint32_t length = read_u32(src, offset + 16 + (i * 12) + 4); -+ uint32_t description_offset = read_u32(src, offset + 16 + (i * 12) + 8); -+ -+ if (!src->valid || !length || (length & 1)) -+ goto invalid_dscm_tag; -+ if (language != isoen) -+ continue; -+ -+ // Use a prefix to identify the display description source -+ strcpy(profile->description, "dscm:"); -+ length += 5; -+ -+ if (length >= limit) -+ length = limit - 1; -+ for (uint32_t j = 5; j < length; ++j) { -+ uint8_t value = read_u8(src, offset + description_offset + j - 5); -+ if (!src->valid) -+ goto invalid_dscm_tag; -+ profile->description[j] = value ? value : '.'; -+ } -+ profile->description[length] = 0; -+ break; -+ } -+ } -+ -+ if (src->valid) -+ return true; -+ -+invalid_dscm_tag: -+ invalid_source(src, "invalid dscm tag"); -+ return false; -+} -+ -+// Use the mmod tag to change profile description "Display" to its specific mmod maker model data, if any. -+ -+#define TAG_mmod 0x6D6D6F64 // 'mmod' -+ -+static bool read_tag_mmodType(qcms_profile *profile, struct mem_source *src, struct tag_index index, uint32_t tag_id) -+{ -+ if (strcmp(profile->description, "Display") != 0) -+ return true; -+ -+ struct tag *tag = find_tag(index, tag_id); -+ if (tag) { -+ const uint8_t length = 4 * 4; // Four 4-byte fields: 'mmod', 0, maker, model. -+ -+ uint32_t offset = tag->offset; -+ if (tag->size < 40 || read_u32(src, offset) != MMOD_TYPE) -+ goto invalid_mmod_tag; -+ -+ for (uint8_t i = 0; i < length; ++i) { -+ uint8_t value = read_u8(src, offset + i); -+ if (!src->valid) -+ goto invalid_mmod_tag; -+ profile->description[i] = value ? value : '.'; -+ } -+ profile->description[length] = 0; -+ } -+ -+ if (src->valid) -+ return true; -+ -+invalid_mmod_tag: -+ invalid_source(src, "invalid mmod tag"); -+ return false; -+} -+ -+#endif // __APPLE__ -+ - #define XYZ_TYPE 0x58595a20 // 'XYZ ' - #define CURVE_TYPE 0x63757276 // 'curv' - #define PARAMETRIC_CURVE_TYPE 0x70617261 // 'para' -@@ -402,7 +622,7 @@ static struct XYZNumber read_tag_XYZType(struct mem_source *src, struct tag_inde - // present that are not part of the tag_index. - static struct curveType *read_curveType(struct mem_source *src, uint32_t offset, uint32_t *len) - { -- static const size_t COUNT_TO_LENGTH[5] = {1, 3, 4, 5, 7}; -+ static const uint32_t COUNT_TO_LENGTH[5] = {1, 3, 4, 5, 7}; - struct curveType *curve = NULL; - uint32_t type = read_u32(src, offset); - uint32_t count; -@@ -484,19 +704,23 @@ static void read_nested_curveType(struct mem_source *src, struct curveType *(*cu - uint32_t channel_offset = 0; - int i; - for (i = 0; i < num_channels; i++) { -- uint32_t tag_len; -+ uint32_t tag_len = ~0; - - (*curveArray)[i] = read_curveType(src, curve_offset + channel_offset, &tag_len); - if (!(*curveArray)[i]) { - invalid_source(src, "invalid nested curveType curve"); - } - -+ if (tag_len == ~0) { -+ invalid_source(src, "invalid nested curveType tag length"); -+ return; -+ } -+ - channel_offset += tag_len; - // 4 byte aligned - if ((tag_len % 4) != 0) - channel_offset += 4 - (tag_len % 4); - } -- - } - - static void mAB_release(struct lutmABType *lut) -@@ -540,7 +764,7 @@ static struct lutmABType *read_tag_lutmABType(struct mem_source *src, struct tag - // We require 3in/out channels since we only support RGB->XYZ (or RGB->LAB) - // XXX: If we remove this restriction make sure that the number of channels - // is less or equal to the maximum number of mAB curves in qcmsint.h -- // also check for clut_size overflow. -+ // also check for clut_size overflow. Also make sure it's != 0 - if (num_in_channels != 3 || num_out_channels != 3) - return NULL; - -@@ -570,6 +794,9 @@ static struct lutmABType *read_tag_lutmABType(struct mem_source *src, struct tag - // clut_size can not overflow since lg(256^num_in_channels) = 24 bits. - for (i = 0; i < num_in_channels; i++) { - clut_size *= read_u8(src, clut_offset + i); -+ if (clut_size == 0) { -+ invalid_source(src, "bad clut_size"); -+ } - } - } else { - clut_size = 0; -@@ -590,6 +817,9 @@ static struct lutmABType *read_tag_lutmABType(struct mem_source *src, struct tag - - for (i = 0; i < num_in_channels; i++) { - lut->num_grid_points[i] = read_u8(src, clut_offset + i); -+ if (lut->num_grid_points[i] == 0) { -+ invalid_source(src, "bad grid_points"); -+ } - } - - // Reverse the processing of transformation elements for mBA type. -@@ -657,7 +887,7 @@ static struct lutType *read_tag_lutType(struct mem_source *src, struct tag_index - uint16_t num_input_table_entries; - uint16_t num_output_table_entries; - uint8_t in_chan, grid_points, out_chan; -- uint32_t clut_offset, output_offset; -+ size_t clut_offset, output_offset; - uint32_t clut_size; - size_t entry_size; - struct lutType *lut; -@@ -672,6 +902,10 @@ static struct lutType *read_tag_lutType(struct mem_source *src, struct tag_index - } else if (type == LUT16_TYPE) { - num_input_table_entries = read_u16(src, offset + 48); - num_output_table_entries = read_u16(src, offset + 50); -+ if (num_input_table_entries == 0 || num_output_table_entries == 0) { -+ invalid_source(src, "Bad channel count"); -+ return NULL; -+ } - entry_size = 2; - } else { - assert(0); // the caller checks that this doesn't happen -@@ -685,15 +919,18 @@ static struct lutType *read_tag_lutType(struct mem_source *src, struct tag_index - - clut_size = pow(grid_points, in_chan); - if (clut_size > MAX_CLUT_SIZE) { -+ invalid_source(src, "CLUT too large"); - return NULL; - } - - if (in_chan != 3 || out_chan != 3) { -+ invalid_source(src, "CLUT only supports RGB"); - return NULL; - } - - lut = malloc(sizeof(struct lutType) + (num_input_table_entries * in_chan + clut_size*out_chan + num_output_table_entries * out_chan)*sizeof(float)); - if (!lut) { -+ invalid_source(src, "CLUT too large"); - return NULL; - } - -@@ -704,9 +941,9 @@ static struct lutType *read_tag_lutType(struct mem_source *src, struct tag_index - - lut->num_input_table_entries = num_input_table_entries; - lut->num_output_table_entries = num_output_table_entries; -- lut->num_input_channels = read_u8(src, offset + 8); -- lut->num_output_channels = read_u8(src, offset + 9); -- lut->num_clut_grid_points = read_u8(src, offset + 10); -+ lut->num_input_channels = in_chan; -+ lut->num_output_channels = out_chan; -+ lut->num_clut_grid_points = grid_points; - lut->e00 = read_s15Fixed16Number(src, offset+12); - lut->e01 = read_s15Fixed16Number(src, offset+16); - lut->e02 = read_s15Fixed16Number(src, offset+20); -@@ -979,11 +1216,13 @@ qcms_profile* qcms_profile_sRGB(void) - return NO_MEM_PROFILE; - - profile = qcms_profile_create_rgb_with_table(D65, Rec709Primaries, table, 1024); -+ if (profile) -+ strcpy(profile->description, "sRGB IEC61966-2.1"); -+ - free(table); - return profile; - } - -- - /* qcms_profile_from_memory does not hold a reference to the memory passed in */ - qcms_profile* qcms_profile_from_memory(const void *mem, size_t size) - { -@@ -997,6 +1236,9 @@ qcms_profile* qcms_profile_from_memory(const void *mem, size_t size) - source.size = size; - source.valid = true; - -+ if (size < 4) -+ return INVALID_PROFILE; -+ - length = read_u32(src, 0); - if (length <= size) { - // shrink the area that we can read if appropriate -@@ -1028,12 +1270,26 @@ qcms_profile* qcms_profile_from_memory(const void *mem, size_t size) - if (!src->valid || !index.tags) - goto invalid_tag_table; - -+ if (!read_tag_descType(profile, src, index, TAG_desc)) -+ goto invalid_tag_table; -+#if defined(__APPLE__) -+ if (!read_tag_dscmType(profile, src, index, TAG_dscm)) -+ goto invalid_tag_table; -+ if (!read_tag_mmodType(profile, src, index, TAG_mmod)) -+ goto invalid_tag_table; -+#endif // __APPLE__ -+ - if (find_tag(index, TAG_CHAD)) { - profile->chromaticAdaption = read_tag_s15Fixed16ArrayType(src, index, TAG_CHAD); - } else { - profile->chromaticAdaption.invalid = true; //Signal the data is not present - } - -+ if (find_tag(index, TAG_vcgt)) { -+ if (!read_tag_vcgtType(profile, src, index)) -+ goto invalid_tag_table; -+ } -+ - if (profile->class == DISPLAY_DEVICE_PROFILE || profile->class == INPUT_DEVICE_PROFILE || - profile->class == OUTPUT_DEVICE_PROFILE || profile->class == COLOR_SPACE_PROFILE) { - if (profile->color_space == RGB_SIGNATURE) { -@@ -1098,6 +1354,16 @@ invalid_profile: - return INVALID_PROFILE; - } - -+qcms_bool qcms_profile_match(qcms_profile *p1, qcms_profile *p2) -+{ -+ return memcmp(p1->description, p2->description, sizeof p1->description) == 0; -+} -+ -+const char* qcms_profile_get_description(qcms_profile *profile) -+{ -+ return profile->description; -+} -+ - qcms_intent qcms_profile_get_rendering_intent(qcms_profile *profile) - { - return profile->rendering_intent; -@@ -1114,6 +1380,18 @@ static void lut_release(struct lutType *lut) - free(lut); - } - -+size_t qcms_profile_get_vcgt_channel_length(qcms_profile *profile) { -+ return profile->vcgt.length; -+} -+ -+qcms_bool qcms_profile_get_vcgt_rgb_channels(qcms_profile *profile, unsigned short *data) { -+ size_t vcgt_channel_bytes = qcms_profile_get_vcgt_channel_length(profile) * sizeof(uint16_t); -+ if (!vcgt_channel_bytes || !data) -+ return false; -+ memcpy(data, profile->vcgt.data, 3 * vcgt_channel_bytes); -+ return true; -+} -+ - void qcms_profile_release(qcms_profile *profile) - { - if (profile->output_table_r) -@@ -1133,6 +1411,9 @@ void qcms_profile_release(qcms_profile *profile) - if (profile->mBA) - mAB_release(profile->mBA); - -+ if (profile->vcgt.data) -+ free(profile->vcgt.data); -+ - free(profile->redTRC); - free(profile->blueTRC); - free(profile->greenTRC); -diff --git a/third_party/qcms/src/qcms.h b/third_party/qcms/src/qcms.h -index 7d83623..be74717 100644 ---- a/third_party/qcms/src/qcms.h -+++ b/third_party/qcms/src/qcms.h -@@ -40,6 +40,12 @@ sale, use or other dealings in this Software without written - authorization from SunSoft Inc. - ******************************************************************/ - -+/* -+ * QCMS, in general, is not threadsafe. However, it should be safe to create -+ * profile and transformation objects on different threads, so long as you -+ * don't use the same objects on different threads at the same time. -+ */ -+ - /* - * Color Space Signatures - * Note that only icSigXYZData and icSigLabData are valid -@@ -102,6 +108,12 @@ typedef enum { - QCMS_DATA_GRAYA_8 - } qcms_data_type; - -+/* Format of the output data for qcms_transform_data_type() */ -+typedef enum { -+ QCMS_OUTPUT_RGBX, -+ QCMS_OUTPUT_BGRX -+} qcms_output_type; -+ - /* the names for the following two types are sort of ugly */ - typedef struct - { -@@ -136,16 +148,27 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile); - qcms_intent qcms_profile_get_rendering_intent(qcms_profile *profile); - icColorSpaceSignature qcms_profile_get_color_space(qcms_profile *profile); - -+qcms_bool qcms_profile_match(qcms_profile *p1, qcms_profile *p2); -+const char* qcms_profile_get_description(qcms_profile *profile); -+ - void qcms_profile_precache_output_transform(qcms_profile *profile); - -+size_t qcms_profile_get_vcgt_channel_length(qcms_profile *profile); -+qcms_bool qcms_profile_get_vcgt_rgb_channels(qcms_profile *profile, unsigned short *data); -+ - qcms_transform* qcms_transform_create( - qcms_profile *in, qcms_data_type in_type, - qcms_profile* out, qcms_data_type out_type, - qcms_intent intent); - --void qcms_transform_release(qcms_transform *); -+qcms_bool qcms_transform_create_LUT_zyx_bgra( -+ qcms_profile *in, qcms_profile* out, qcms_intent intent, -+ int samples, unsigned char* lut); - - void qcms_transform_data(qcms_transform *transform, void *src, void *dest, size_t length); -+void qcms_transform_data_type(qcms_transform *transform, void *src, void *dest, size_t length, qcms_output_type type); -+ -+void qcms_transform_release(qcms_transform *); - - void qcms_enable_iccv4(); - -diff --git a/third_party/qcms/src/qcmsint.h b/third_party/qcms/src/qcmsint.h -index 53a3420..6b22c5a 100644 ---- a/third_party/qcms/src/qcmsint.h -+++ b/third_party/qcms/src/qcmsint.h -@@ -45,6 +45,11 @@ struct precache_output - #define ALIGN __attribute__(( aligned (16) )) - #endif - -+typedef struct _qcms_format_type { -+ int r; -+ int b; -+} qcms_format_type; -+ - struct _qcms_transform { - float ALIGN matrix[3][4]; - float *input_gamma_table_r; -@@ -88,7 +93,7 @@ struct _qcms_transform { - struct precache_output *output_table_g; - struct precache_output *output_table_b; - -- void (*transform_fn)(struct _qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length); -+ void (*transform_fn)(struct _qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, struct _qcms_format_type output_format); - }; - - struct matrix { -@@ -200,6 +205,14 @@ struct lutType { // used by lut8Type/lut16Type (mft2) only - - float table_data[]; - }; -+ -+struct vcgtType { -+ /* data contains three gamma channels: R[length], then G[length], then -+ * B[length]. */ -+ uint16_t *data; -+ size_t length; -+}; -+ - #if 0 - /* this is from an intial idea of having the struct correspond to the data in - * the file. I decided that it wasn't a good idea. -@@ -225,6 +238,7 @@ struct tag_value { - #define LAB_SIGNATURE 0x4C616220 - - struct _qcms_profile { -+ char description[64]; - uint32_t class; - uint32_t color_space; - uint32_t pcs; -@@ -241,6 +255,7 @@ struct _qcms_profile { - struct lutmABType *mAB; - struct lutmABType *mBA; - struct matrix chromaticAdaption; -+ struct vcgtType vcgt; - - struct precache_output *output_table_r; - struct precache_output *output_table_g; -@@ -280,18 +295,40 @@ qcms_bool set_rgb_colorants(qcms_profile *profile, qcms_CIE_xyY white_point, qcm - void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform, - unsigned char *src, - unsigned char *dest, -- size_t length); -+ size_t length, -+ qcms_format_type output_format); - void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform, - unsigned char *src, - unsigned char *dest, -- size_t length); -+ size_t length, -+ qcms_format_type output_format); - void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, - unsigned char *src, - unsigned char *dest, -- size_t length); -+ size_t length, -+ qcms_format_type output_format); - void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform, - unsigned char *src, - unsigned char *dest, -- size_t length); -+ size_t length, -+ qcms_format_type output_format); - - extern qcms_bool qcms_supports_iccv4; -+ -+ -+#ifdef _MSC_VER -+ -+long __cdecl _InterlockedIncrement(long volatile *); -+long __cdecl _InterlockedDecrement(long volatile *); -+#pragma intrinsic(_InterlockedIncrement) -+#pragma intrinsic(_InterlockedDecrement) -+ -+#define qcms_atomic_increment(x) _InterlockedIncrement((long volatile *)&x) -+#define qcms_atomic_decrement(x) _InterlockedDecrement((long volatile*)&x) -+ -+#else -+ -+#define qcms_atomic_increment(x) __sync_add_and_fetch(&x, 1) -+#define qcms_atomic_decrement(x) __sync_sub_and_fetch(&x, 1) -+ -+#endif -diff --git a/third_party/qcms/src/qcmstypes.h b/third_party/qcms/src/qcmstypes.h -index 56d8de3..d58f691 100644 ---- a/third_party/qcms/src/qcmstypes.h -+++ b/third_party/qcms/src/qcmstypes.h -@@ -22,37 +22,6 @@ - #ifndef QCMS_TYPES_H - #define QCMS_TYPES_H - --#ifdef MOZ_QCMS -- --#include "prtypes.h" -- --/* prtypes.h defines IS_LITTLE_ENDIAN and IS_BIG ENDIAN */ -- --#if defined (__SVR4) && defined (__sun) --/* int_types.h gets included somehow, so avoid redefining the types differently */ --#include <sys/int_types.h> --#elif defined (_AIX) --#include <sys/types.h> --#elif !defined(ANDROID) && !defined(__OpenBSD__) --typedef PRInt8 int8_t; --typedef PRUint8 uint8_t; --typedef PRInt16 int16_t; --typedef PRUint16 uint16_t; --typedef PRInt32 int32_t; --typedef PRUint32 uint32_t; --typedef PRInt64 int64_t; --typedef PRUint64 uint64_t; -- --#ifdef __OS2__ --/* OS/2's stdlib typdefs uintptr_t. So we'll just include that so we don't collide */ --#include <stdlib.h> --#elif !defined(__intptr_t_defined) && !defined(_UINTPTR_T_DEFINED) --typedef PRUptrdiff uintptr_t; --#endif --#endif -- --#else // MOZ_QCMS -- - #if BYTE_ORDER == LITTLE_ENDIAN - #define IS_LITTLE_ENDIAN - #elif BYTE_ORDER == BIG_ENDIAN -@@ -75,7 +44,7 @@ typedef PRUptrdiff uintptr_t; - - #if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || defined (_sgi) || defined (__sun) || defined (sun) || defined (__digital__) - # include <inttypes.h> --#elif defined (_MSC_VER) -+#elif defined (_MSC_VER) && _MSC_VER < 1600 - typedef __int8 int8_t; - typedef unsigned __int8 uint8_t; - typedef __int16 int16_t; -@@ -87,7 +56,12 @@ typedef unsigned __int64 uint64_t; - #ifdef _WIN64 - typedef unsigned __int64 uintptr_t; - #else -+#pragma warning(push) -+/* Disable benign redefinition of type warning 4142 */ -+#pragma warning(disable:4142) - typedef unsigned long uintptr_t; -+/* Restore warnings */ -+#pragma warning(pop) - #endif - - #elif defined (_AIX) -@@ -96,8 +70,6 @@ typedef unsigned long uintptr_t; - # include <stdint.h> - #endif - --#endif -- - typedef qcms_bool bool; - #define true 1 - #define false 0 -diff --git a/third_party/qcms/src/transform-sse1.c b/third_party/qcms/src/transform-sse1.c -index 2f34db5..aaee1bf 100644 ---- a/third_party/qcms/src/transform-sse1.c -+++ b/third_party/qcms/src/transform-sse1.c -@@ -34,7 +34,8 @@ static const ALIGN float clampMaxValueX4[4] = - void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, - unsigned char *src, - unsigned char *dest, -- size_t length) -+ size_t length, -+ qcms_format_type output_format) - { - unsigned int i; - float (*mat)[4] = transform->matrix; -@@ -70,6 +71,8 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, - - /* working variables */ - __m128 vec_r, vec_g, vec_b, result; -+ const int r_out = output_format.r; -+ const int b_out = output_format.b; - - /* CYA */ - if (!length) -@@ -116,9 +119,9 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, - src += 3; - - /* use calc'd indices to output RGB values */ -- dest[0] = otdata_r[output[0]]; -- dest[1] = otdata_g[output[1]]; -- dest[2] = otdata_b[output[2]]; -+ dest[r_out] = otdata_r[output[0]]; -+ dest[1] = otdata_g[output[1]]; -+ dest[b_out] = otdata_b[output[2]]; - dest += 3; - } - -@@ -141,9 +144,9 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, - result = _mm_movehl_ps(result, result); - *((__m64 *)&output[2]) = _mm_cvtps_pi32(result); - -- dest[0] = otdata_r[output[0]]; -- dest[1] = otdata_g[output[1]]; -- dest[2] = otdata_b[output[2]]; -+ dest[r_out] = otdata_r[output[0]]; -+ dest[1] = otdata_g[output[1]]; -+ dest[b_out] = otdata_b[output[2]]; - - _mm_empty(); - } -@@ -151,7 +154,8 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, - void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform, - unsigned char *src, - unsigned char *dest, -- size_t length) -+ size_t length, -+ qcms_format_type output_format) - { - unsigned int i; - float (*mat)[4] = transform->matrix; -@@ -187,6 +191,8 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform, - - /* working variables */ - __m128 vec_r, vec_g, vec_b, result; -+ const int r_out = output_format.r; -+ const int b_out = output_format.b; - unsigned char alpha; - - /* CYA */ -@@ -239,9 +245,9 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform, - src += 4; - - /* use calc'd indices to output RGB values */ -- dest[0] = otdata_r[output[0]]; -- dest[1] = otdata_g[output[1]]; -- dest[2] = otdata_b[output[2]]; -+ dest[r_out] = otdata_r[output[0]]; -+ dest[1] = otdata_g[output[1]]; -+ dest[b_out] = otdata_b[output[2]]; - dest += 4; - } - -@@ -266,9 +272,9 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform, - result = _mm_movehl_ps(result, result); - *((__m64 *)&output[2]) = _mm_cvtps_pi32(result); - -- dest[0] = otdata_r[output[0]]; -- dest[1] = otdata_g[output[1]]; -- dest[2] = otdata_b[output[2]]; -+ dest[r_out] = otdata_r[output[0]]; -+ dest[1] = otdata_g[output[1]]; -+ dest[b_out] = otdata_b[output[2]]; - - _mm_empty(); - } -diff --git a/third_party/qcms/src/transform-sse2.c b/third_party/qcms/src/transform-sse2.c -index 6a5faf9..fa7f2d1 100644 ---- a/third_party/qcms/src/transform-sse2.c -+++ b/third_party/qcms/src/transform-sse2.c -@@ -34,7 +34,8 @@ static const ALIGN float clampMaxValueX4[4] = - void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform, - unsigned char *src, - unsigned char *dest, -- size_t length) -+ size_t length, -+ qcms_format_type output_format) - { - unsigned int i; - float (*mat)[4] = transform->matrix; -@@ -70,6 +71,8 @@ void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform, - - /* working variables */ - __m128 vec_r, vec_g, vec_b, result; -+ const int r_out = output_format.r; -+ const int b_out = output_format.b; - - /* CYA */ - if (!length) -@@ -114,9 +117,9 @@ void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform, - src += 3; - - /* use calc'd indices to output RGB values */ -- dest[0] = otdata_r[output[0]]; -- dest[1] = otdata_g[output[1]]; -- dest[2] = otdata_b[output[2]]; -+ dest[r_out] = otdata_r[output[0]]; -+ dest[1] = otdata_g[output[1]]; -+ dest[b_out] = otdata_b[output[2]]; - dest += 3; - } - -@@ -137,15 +140,16 @@ void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform, - - _mm_store_si128((__m128i*)output, _mm_cvtps_epi32(result)); - -- dest[0] = otdata_r[output[0]]; -- dest[1] = otdata_g[output[1]]; -- dest[2] = otdata_b[output[2]]; -+ dest[r_out] = otdata_r[output[0]]; -+ dest[1] = otdata_g[output[1]]; -+ dest[b_out] = otdata_b[output[2]]; - } - - void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform, - unsigned char *src, - unsigned char *dest, -- size_t length) -+ size_t length, -+ qcms_format_type output_format) - { - unsigned int i; - float (*mat)[4] = transform->matrix; -@@ -181,6 +185,8 @@ void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform, - - /* working variables */ - __m128 vec_r, vec_g, vec_b, result; -+ const int r_out = output_format.r; -+ const int b_out = output_format.b; - unsigned char alpha; - - /* CYA */ -@@ -231,9 +237,9 @@ void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform, - src += 4; - - /* use calc'd indices to output RGB values */ -- dest[0] = otdata_r[output[0]]; -- dest[1] = otdata_g[output[1]]; -- dest[2] = otdata_b[output[2]]; -+ dest[r_out] = otdata_r[output[0]]; -+ dest[1] = otdata_g[output[1]]; -+ dest[b_out] = otdata_b[output[2]]; - dest += 4; - } - -@@ -256,7 +262,7 @@ void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform, - - _mm_store_si128((__m128i*)output, _mm_cvtps_epi32(result)); - -- dest[0] = otdata_r[output[0]]; -- dest[1] = otdata_g[output[1]]; -- dest[2] = otdata_b[output[2]]; -+ dest[r_out] = otdata_r[output[0]]; -+ dest[1] = otdata_g[output[1]]; -+ dest[b_out] = otdata_b[output[2]]; - } -diff --git a/third_party/qcms/src/transform.c b/third_party/qcms/src/transform.c -index 9a6562b..f669a6b 100644 ---- a/third_party/qcms/src/transform.c -+++ b/third_party/qcms/src/transform.c -@@ -181,11 +181,20 @@ compute_chromatic_adaption(struct CIE_XYZ source_white_point, - static struct matrix - adaption_matrix(struct CIE_XYZ source_illumination, struct CIE_XYZ target_illumination) - { -+#if defined (_MSC_VER) -+#pragma warning(push) -+/* Disable double to float truncation warning 4305 */ -+#pragma warning(disable:4305) -+#endif - struct matrix lam_rigg = {{ // Bradford matrix - { 0.8951, 0.2664, -0.1614 }, - { -0.7502, 1.7135, 0.0367 }, - { 0.0389, -0.0685, 1.0296 } - }}; -+#if defined (_MSC_VER) -+/* Restore warnings */ -+#pragma warning(pop) -+#endif - return compute_chromatic_adaption(source_illumination, target_illumination, lam_rigg); - } - -@@ -230,8 +239,11 @@ qcms_bool set_rgb_colorants(qcms_profile *profile, qcms_CIE_xyY white_point, qcm - } - - #if 0 --static void qcms_transform_data_rgb_out_pow(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) -+static void qcms_transform_data_rgb_out_pow(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format) - { -+ const int r_out = output_format.r; -+ const int b_out = output_format.b; -+ - int i; - float (*mat)[4] = transform->matrix; - for (i=0; i<length; i++) { -@@ -251,15 +263,19 @@ static void qcms_transform_data_rgb_out_pow(qcms_transform *transform, unsigned - float out_device_g = pow(out_linear_g, transform->out_gamma_g); - float out_device_b = pow(out_linear_b, transform->out_gamma_b); - -- *dest++ = clamp_u8(255*out_device_r); -- *dest++ = clamp_u8(255*out_device_g); -- *dest++ = clamp_u8(255*out_device_b); -+ dest[r_out] = clamp_u8(out_device_r*255); -+ dest[1] = clamp_u8(out_device_g*255); -+ dest[b_out] = clamp_u8(out_device_b*255); -+ dest += 3; - } - } - #endif - --static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) -+static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format) - { -+ const int r_out = output_format.r; -+ const int b_out = output_format.b; -+ - unsigned int i; - for (i = 0; i < length; i++) { - float out_device_r, out_device_g, out_device_b; -@@ -267,13 +283,14 @@ static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned - - float linear = transform->input_gamma_table_gray[device]; - -- out_device_r = lut_interp_linear(linear, transform->output_gamma_lut_r, transform->output_gamma_lut_r_length); -+ out_device_r = lut_interp_linear(linear, transform->output_gamma_lut_r, transform->output_gamma_lut_r_length); - out_device_g = lut_interp_linear(linear, transform->output_gamma_lut_g, transform->output_gamma_lut_g_length); - out_device_b = lut_interp_linear(linear, transform->output_gamma_lut_b, transform->output_gamma_lut_b_length); - -- *dest++ = clamp_u8(out_device_r*255); -- *dest++ = clamp_u8(out_device_g*255); -- *dest++ = clamp_u8(out_device_b*255); -+ dest[r_out] = clamp_u8(out_device_r*255); -+ dest[1] = clamp_u8(out_device_g*255); -+ dest[b_out] = clamp_u8(out_device_b*255); -+ dest += 3; - } - } - -@@ -283,8 +300,11 @@ static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned - See: ftp://ftp.alvyray.com/Acrobat/17_Nonln.pdf - */ - --static void qcms_transform_data_graya_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) -+static void qcms_transform_data_graya_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format) - { -+ const int r_out = output_format.r; -+ const int b_out = output_format.b; -+ - unsigned int i; - for (i = 0; i < length; i++) { - float out_device_r, out_device_g, out_device_b; -@@ -293,20 +313,24 @@ static void qcms_transform_data_graya_out_lut(qcms_transform *transform, unsigne - - float linear = transform->input_gamma_table_gray[device]; - -- out_device_r = lut_interp_linear(linear, transform->output_gamma_lut_r, transform->output_gamma_lut_r_length); -+ out_device_r = lut_interp_linear(linear, transform->output_gamma_lut_r, transform->output_gamma_lut_r_length); - out_device_g = lut_interp_linear(linear, transform->output_gamma_lut_g, transform->output_gamma_lut_g_length); - out_device_b = lut_interp_linear(linear, transform->output_gamma_lut_b, transform->output_gamma_lut_b_length); - -- *dest++ = clamp_u8(out_device_r*255); -- *dest++ = clamp_u8(out_device_g*255); -- *dest++ = clamp_u8(out_device_b*255); -- *dest++ = alpha; -+ dest[r_out] = clamp_u8(out_device_r*255); -+ dest[1] = clamp_u8(out_device_g*255); -+ dest[b_out] = clamp_u8(out_device_b*255); -+ dest[3] = alpha; -+ dest += 4; - } - } - - --static void qcms_transform_data_gray_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) -+static void qcms_transform_data_gray_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format) - { -+ const int r_out = output_format.r; -+ const int b_out = output_format.b; -+ - unsigned int i; - for (i = 0; i < length; i++) { - unsigned char device = *src++; -@@ -317,14 +341,19 @@ static void qcms_transform_data_gray_out_precache(qcms_transform *transform, uns - /* we could round here... */ - gray = linear * PRECACHE_OUTPUT_MAX; - -- *dest++ = transform->output_table_r->data[gray]; -- *dest++ = transform->output_table_g->data[gray]; -- *dest++ = transform->output_table_b->data[gray]; -+ dest[r_out] = transform->output_table_r->data[gray]; -+ dest[1] = transform->output_table_g->data[gray]; -+ dest[b_out] = transform->output_table_b->data[gray]; -+ dest += 3; - } - } - --static void qcms_transform_data_graya_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) -+ -+static void qcms_transform_data_graya_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format) - { -+ const int r_out = output_format.r; -+ const int b_out = output_format.b; -+ - unsigned int i; - for (i = 0; i < length; i++) { - unsigned char device = *src++; -@@ -336,15 +365,19 @@ static void qcms_transform_data_graya_out_precache(qcms_transform *transform, un - /* we could round here... */ - gray = linear * PRECACHE_OUTPUT_MAX; - -- *dest++ = transform->output_table_r->data[gray]; -- *dest++ = transform->output_table_g->data[gray]; -- *dest++ = transform->output_table_b->data[gray]; -- *dest++ = alpha; -+ dest[r_out] = transform->output_table_r->data[gray]; -+ dest[1] = transform->output_table_g->data[gray]; -+ dest[b_out] = transform->output_table_b->data[gray]; -+ dest[3] = alpha; -+ dest += 4; - } - } - --static void qcms_transform_data_rgb_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) -+static void qcms_transform_data_rgb_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format) - { -+ const int r_out = output_format.r; -+ const int b_out = output_format.b; -+ - unsigned int i; - float (*mat)[4] = transform->matrix; - for (i = 0; i < length; i++) { -@@ -370,14 +403,18 @@ static void qcms_transform_data_rgb_out_lut_precache(qcms_transform *transform, - g = out_linear_g * PRECACHE_OUTPUT_MAX; - b = out_linear_b * PRECACHE_OUTPUT_MAX; - -- *dest++ = transform->output_table_r->data[r]; -- *dest++ = transform->output_table_g->data[g]; -- *dest++ = transform->output_table_b->data[b]; -+ dest[r_out] = transform->output_table_r->data[r]; -+ dest[1] = transform->output_table_g->data[g]; -+ dest[b_out] = transform->output_table_b->data[b]; -+ dest += 3; - } - } - --static void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) -+static void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format) - { -+ const int r_out = output_format.r; -+ const int b_out = output_format.b; -+ - unsigned int i; - float (*mat)[4] = transform->matrix; - for (i = 0; i < length; i++) { -@@ -404,16 +441,21 @@ static void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform, - g = out_linear_g * PRECACHE_OUTPUT_MAX; - b = out_linear_b * PRECACHE_OUTPUT_MAX; - -- *dest++ = transform->output_table_r->data[r]; -- *dest++ = transform->output_table_g->data[g]; -- *dest++ = transform->output_table_b->data[b]; -- *dest++ = alpha; -+ dest[r_out] = transform->output_table_r->data[r]; -+ dest[1] = transform->output_table_g->data[g]; -+ dest[b_out] = transform->output_table_b->data[b]; -+ dest[3] = alpha; -+ dest += 4; - } - } - - // Not used - /* --static void qcms_transform_data_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) { -+static void qcms_transform_data_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format) -+{ -+ const int r_out = output_format.r; -+ const int b_out = output_format.b; -+ - unsigned int i; - int xy_len = 1; - int x_len = transform->grid_size; -@@ -462,15 +504,20 @@ static void qcms_transform_data_clut(qcms_transform *transform, unsigned char *s - float b_y2 = lerp(b_x3, b_x4, y_d); - float clut_b = lerp(b_y1, b_y2, z_d); - -- *dest++ = clamp_u8(clut_r*255.0f); -- *dest++ = clamp_u8(clut_g*255.0f); -- *dest++ = clamp_u8(clut_b*255.0f); -- } -+ dest[r_out] = clamp_u8(clut_r*255.0f); -+ dest[1] = clamp_u8(clut_g*255.0f); -+ dest[b_out] = clamp_u8(clut_b*255.0f); -+ dest += 3; -+ } - } - */ - - // Using lcms' tetra interpolation algorithm. --static void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) { -+static void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format) -+{ -+ const int r_out = output_format.r; -+ const int b_out = output_format.b; -+ - unsigned int i; - int xy_len = 1; - int x_len = transform->grid_size; -@@ -577,15 +624,20 @@ static void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, unsig - clut_g = c0_g + c1_g*rx + c2_g*ry + c3_g*rz; - clut_b = c0_b + c1_b*rx + c2_b*ry + c3_b*rz; - -- *dest++ = clamp_u8(clut_r*255.0f); -- *dest++ = clamp_u8(clut_g*255.0f); -- *dest++ = clamp_u8(clut_b*255.0f); -- *dest++ = in_a; -- } -+ dest[r_out] = clamp_u8(clut_r*255.0f); -+ dest[1] = clamp_u8(clut_g*255.0f); -+ dest[b_out] = clamp_u8(clut_b*255.0f); -+ dest[3] = in_a; -+ dest += 4; -+ } - } - - // Using lcms' tetra interpolation code. --static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) { -+static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format) -+{ -+ const int r_out = output_format.r; -+ const int b_out = output_format.b; -+ - unsigned int i; - int xy_len = 1; - int x_len = transform->grid_size; -@@ -691,14 +743,18 @@ static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned c - clut_g = c0_g + c1_g*rx + c2_g*ry + c3_g*rz; - clut_b = c0_b + c1_b*rx + c2_b*ry + c3_b*rz; - -- *dest++ = clamp_u8(clut_r*255.0f); -- *dest++ = clamp_u8(clut_g*255.0f); -- *dest++ = clamp_u8(clut_b*255.0f); -- } -+ dest[r_out] = clamp_u8(clut_r*255.0f); -+ dest[1] = clamp_u8(clut_g*255.0f); -+ dest[b_out] = clamp_u8(clut_b*255.0f); -+ dest += 3; -+ } - } - --static void qcms_transform_data_rgb_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) -+static void qcms_transform_data_rgb_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format) - { -+ const int r_out = output_format.r; -+ const int b_out = output_format.b; -+ - unsigned int i; - float (*mat)[4] = transform->matrix; - for (i = 0; i < length; i++) { -@@ -726,14 +782,18 @@ static void qcms_transform_data_rgb_out_lut(qcms_transform *transform, unsigned - out_device_b = lut_interp_linear(out_linear_b, - transform->output_gamma_lut_b, transform->output_gamma_lut_b_length); - -- *dest++ = clamp_u8(out_device_r*255); -- *dest++ = clamp_u8(out_device_g*255); -- *dest++ = clamp_u8(out_device_b*255); -+ dest[r_out] = clamp_u8(out_device_r*255); -+ dest[1] = clamp_u8(out_device_g*255); -+ dest[b_out] = clamp_u8(out_device_b*255); -+ dest += 3; - } - } - --static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) -+static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format) - { -+ const int r_out = output_format.r; -+ const int b_out = output_format.b; -+ - unsigned int i; - float (*mat)[4] = transform->matrix; - for (i = 0; i < length; i++) { -@@ -762,16 +822,20 @@ static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigned - out_device_b = lut_interp_linear(out_linear_b, - transform->output_gamma_lut_b, transform->output_gamma_lut_b_length); - -- *dest++ = clamp_u8(out_device_r*255); -- *dest++ = clamp_u8(out_device_g*255); -- *dest++ = clamp_u8(out_device_b*255); -- *dest++ = alpha; -+ dest[r_out] = clamp_u8(out_device_r*255); -+ dest[1] = clamp_u8(out_device_g*255); -+ dest[b_out] = clamp_u8(out_device_b*255); -+ dest[3] = alpha; -+ dest += 4; - } - } - - #if 0 --static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) -+static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format) - { -+ const int r_out = output_format.r; -+ const int b_out = output_format.b; -+ - int i; - float (*mat)[4] = transform->matrix; - for (i = 0; i < length; i++) { -@@ -787,16 +851,25 @@ static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsign - float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + mat[2][1]*linear_b; - float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + mat[2][2]*linear_b; - -- *dest++ = clamp_u8(out_linear_r*255); -- *dest++ = clamp_u8(out_linear_g*255); -- *dest++ = clamp_u8(out_linear_b*255); -+ dest[r_out] = clamp_u8(out_linear_r*255); -+ dest[1] = clamp_u8(out_linear_g*255); -+ dest[b_out] = clamp_u8(out_linear_b*255); -+ dest += 3; - } - } - #endif - -+/* -+ * If users create and destroy objects on different threads, even if the same -+ * objects aren't used on different threads at the same time, we can still run -+ * in to trouble with refcounts if they aren't atomic. -+ * -+ * This can lead to us prematurely deleting the precache if threads get unlucky -+ * and write the wrong value to the ref count. -+ */ - static struct precache_output *precache_reference(struct precache_output *p) - { -- p->ref_count++; -+ qcms_atomic_increment(p->ref_count); - return p; - } - -@@ -810,12 +883,12 @@ static struct precache_output *precache_create() - - void precache_release(struct precache_output *p) - { -- if (--p->ref_count == 0) { -+ if (qcms_atomic_decrement(p->ref_count) == 0) { - free(p); - } - } - --#ifdef HAS_POSIX_MEMALIGN -+#ifdef HAVE_POSIX_MEMALIGN - static qcms_transform *transform_alloc(void) - { - qcms_transform *t; -@@ -994,13 +1067,15 @@ void qcms_profile_precache_output_transform(qcms_profile *profile) - if (profile->color_space != RGB_SIGNATURE) - return; - -- /* don't precache since we will use the B2A LUT */ -- if (profile->B2A0) -- return; -+ if (qcms_supports_iccv4) { -+ /* don't precache since we will use the B2A LUT */ -+ if (profile->B2A0) -+ return; - -- /* don't precache since we will use the mBA LUT */ -- if (profile->mBA) -- return; -+ /* don't precache since we will use the mBA LUT */ -+ if (profile->mBA) -+ return; -+ } - - /* don't precache if we do not have the TRC curves */ - if (!profile->redTRC || !profile->greenTRC || !profile->blueTRC) -@@ -1043,28 +1118,31 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_transform *transform, qcms - float* src = NULL; - float* dest = NULL; - float* lut = NULL; -+ float inverse; - - src = malloc(lutSize*sizeof(float)); - dest = malloc(lutSize*sizeof(float)); - - if (src && dest) { -- /* Prepare a list of points we want to sample */ -+ /* Prepare a list of points we want to sample: x, y, z order */ - l = 0; -+ inverse = 1 / (float)(samples-1); - for (x = 0; x < samples; x++) { - for (y = 0; y < samples; y++) { - for (z = 0; z < samples; z++) { -- src[l++] = x / (float)(samples-1); -- src[l++] = y / (float)(samples-1); -- src[l++] = z / (float)(samples-1); -+ src[l++] = x * inverse; // r -+ src[l++] = y * inverse; // g -+ src[l++] = z * inverse; // b - } - } - } - - lut = qcms_chain_transform(in, out, src, dest, lutSize); -+ - if (lut) { -- transform->r_clut = &lut[0]; -- transform->g_clut = &lut[1]; -- transform->b_clut = &lut[2]; -+ transform->r_clut = &lut[0]; // r -+ transform->g_clut = &lut[1]; // g -+ transform->b_clut = &lut[2]; // b - transform->grid_size = samples; - if (in_type == QCMS_DATA_RGBA_8) { - transform->transform_fn = qcms_transform_data_tetra_clut_rgba; -@@ -1074,11 +1152,12 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_transform *transform, qcms - } - } - -- -- //XXX: qcms_modular_transform_data may return either the src or dest buffer. If so it must not be free-ed -+ // XXX: qcms_modular_transform_data may return the lut in either the src or the -+ // dest buffer. If so, it must not be free-ed. - if (src && lut != src) { - free(src); -- } else if (dest && lut != src) { -+ } -+ if (dest && lut != dest) { - free(dest); - } - -@@ -1088,6 +1167,71 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_transform *transform, qcms - return transform; - } - -+/* Create a transform LUT using the given number of sample points. The transform LUT data is stored -+ in the output (cube) in bgra format in zyx sample order. */ -+qcms_bool qcms_transform_create_LUT_zyx_bgra(qcms_profile *in, qcms_profile *out, qcms_intent intent, -+ int samples, unsigned char* cube) -+{ -+ uint16_t z,y,x; -+ uint32_t l,index; -+ uint32_t lutSize = 3 * samples * samples * samples; -+ -+ float* src = NULL; -+ float* dest = NULL; -+ float* lut = NULL; -+ float inverse; -+ -+ src = malloc(lutSize*sizeof(float)); -+ dest = malloc(lutSize*sizeof(float)); -+ -+ if (src && dest) { -+ /* Prepare a list of points we want to sample: z, y, x order */ -+ l = 0; -+ inverse = 1 / (float)(samples-1); -+ for (z = 0; z < samples; z++) { -+ for (y = 0; y < samples; y++) { -+ for (x = 0; x < samples; x++) { -+ src[l++] = x * inverse; // r -+ src[l++] = y * inverse; // g -+ src[l++] = z * inverse; // b -+ } -+ } -+ } -+ -+ lut = qcms_chain_transform(in, out, src, dest, lutSize); -+ -+ if (lut) { -+ index = l = 0; -+ for (z = 0; z < samples; z++) { -+ for (y = 0; y < samples; y++) { -+ for (x = 0; x < samples; x++) { -+ cube[index++] = (int)floorf(lut[l + 2] * 255.0f + 0.5f); // b -+ cube[index++] = (int)floorf(lut[l + 1] * 255.0f + 0.5f); // g -+ cube[index++] = (int)floorf(lut[l + 0] * 255.0f + 0.5f); // r -+ cube[index++] = 255; // a -+ l += 3; -+ } -+ } -+ } -+ } -+ } -+ -+ // XXX: qcms_modular_transform_data may return the lut data in either the src or -+ // dest buffer so free src, dest, and lut with care. -+ -+ if (src && lut != src) -+ free(src); -+ if (dest && lut != dest) -+ free(dest); -+ -+ if (lut) { -+ free(lut); -+ return true; -+ } -+ -+ return false; -+} -+ - #define NO_MEM_TRANSFORM NULL - - qcms_transform* qcms_transform_create( -@@ -1157,14 +1301,14 @@ qcms_transform* qcms_transform_create( - return NULL; - } - if (precache) { --#ifdef X86 -+#if defined(SSE2_ENABLE) && defined(X86) - if (sse_version_available() >= 2) { - if (in_type == QCMS_DATA_RGB_8) - transform->transform_fn = qcms_transform_data_rgb_out_lut_sse2; - else - transform->transform_fn = qcms_transform_data_rgba_out_lut_sse2; - --#if !(defined(_MSC_VER) && defined(_M_AMD64)) -+#if defined(SSE2_ENABLE) && !(defined(_MSC_VER) && defined(_M_AMD64)) - /* Microsoft Compiler for x64 doesn't support MMX. - * SSE code uses MMX so that we disable on x64 */ - } else -@@ -1256,13 +1400,34 @@ qcms_transform* qcms_transform_create( - return transform; - } - --#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) -+/* __force_align_arg_pointer__ is an x86-only attribute, and gcc/clang warns on unused -+ * attributes. Don't use this on ARM or AMD64. __has_attribute can detect the presence -+ * of the attribute but is currently only supported by clang */ -+#if defined(__has_attribute) -+#define HAS_FORCE_ALIGN_ARG_POINTER __has_attribute(__force_align_arg_pointer__) -+#elif defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) && !defined(__arm__) && !defined(__mips__) -+#define HAS_FORCE_ALIGN_ARG_POINTER 1 -+#else -+#define HAS_FORCE_ALIGN_ARG_POINTER 0 -+#endif -+ -+#if HAS_FORCE_ALIGN_ARG_POINTER - /* we need this to avoid crashes when gcc assumes the stack is 128bit aligned */ - __attribute__((__force_align_arg_pointer__)) - #endif - void qcms_transform_data(qcms_transform *transform, void *src, void *dest, size_t length) - { -- transform->transform_fn(transform, src, dest, length); -+ static const struct _qcms_format_type output_rgbx = { 0, 2 }; -+ -+ transform->transform_fn(transform, src, dest, length, output_rgbx); -+} -+ -+void qcms_transform_data_type(qcms_transform *transform, void *src, void *dest, size_t length, qcms_output_type type) -+{ -+ static const struct _qcms_format_type output_rgbx = { 0, 2 }; -+ static const struct _qcms_format_type output_bgrx = { 2, 0 }; -+ -+ transform->transform_fn(transform, src, dest, length, type == QCMS_OUTPUT_BGRX ? output_bgrx : output_rgbx); - } - - qcms_bool qcms_supports_iccv4; -diff --git a/third_party/qcms/src/transform_util.c b/third_party/qcms/src/transform_util.c -index e8447e5..5eeafa2 100644 ---- a/third_party/qcms/src/transform_util.c -+++ b/third_party/qcms/src/transform_util.c -@@ -36,7 +36,7 @@ - - /* value must be a value between 0 and 1 */ - //XXX: is the above a good restriction to have? --float lut_interp_linear(double value, uint16_t *table, int length) -+float lut_interp_linear(double value, uint16_t *table, size_t length) - { - int upper, lower; - value = value * (length - 1); // scale to length of the array -@@ -49,11 +49,11 @@ float lut_interp_linear(double value, uint16_t *table, int length) - } - - /* same as above but takes and returns a uint16_t value representing a range from 0..1 */ --uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, int length) -+uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, size_t length) - { - /* Start scaling input_value to the length of the array: 65535*(length-1). - * We'll divide out the 65535 next */ -- uint32_t value = (input_value * (length - 1)); -+ uintptr_t value = (input_value * (length - 1)); - uint32_t upper = (value + 65534) / 65535; /* equivalent to ceil(value/65535) */ - uint32_t lower = value / 65535; /* equivalent to floor(value/65535) */ - /* interp is the distance from upper to value scaled to 0..65535 */ -@@ -67,11 +67,11 @@ uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, int length) - /* same as above but takes an input_value from 0..PRECACHE_OUTPUT_MAX - * and returns a uint8_t value representing a range from 0..1 */ - static --uint8_t lut_interp_linear_precache_output(uint32_t input_value, uint16_t *table, int length) -+uint8_t lut_interp_linear_precache_output(uint32_t input_value, uint16_t *table, size_t length) - { - /* Start scaling input_value to the length of the array: PRECACHE_OUTPUT_MAX*(length-1). - * We'll divide out the PRECACHE_OUTPUT_MAX next */ -- uint32_t value = (input_value * (length - 1)); -+ uintptr_t value = (input_value * (length - 1)); - - /* equivalent to ceil(value/PRECACHE_OUTPUT_MAX) */ - uint32_t upper = (value + PRECACHE_OUTPUT_MAX-1) / PRECACHE_OUTPUT_MAX; -@@ -91,7 +91,7 @@ uint8_t lut_interp_linear_precache_output(uint32_t input_value, uint16_t *table, - - /* value must be a value between 0 and 1 */ - //XXX: is the above a good restriction to have? --float lut_interp_linear_float(float value, float *table, int length) -+float lut_interp_linear_float(float value, float *table, size_t length) - { - int upper, lower; - value = value * (length - 1); -@@ -235,6 +235,21 @@ float u8Fixed8Number_to_float(uint16_t x) - return x/256.; - } - -+/* The SSE2 code uses min & max which let NaNs pass through. -+ We want to try to prevent that here by ensuring that -+ gamma table is within expected values. */ -+void validate_gamma_table(float gamma_table[256]) -+{ -+ int i; -+ for (i = 0; i < 256; i++) { -+ // Note: we check that the gamma is not in range -+ // instead of out of range so that we catch NaNs -+ if (!(gamma_table[i] >= 0.f && gamma_table[i] <= 1.f)) { -+ gamma_table[i] = 0.f; -+ } -+ } -+} -+ - float *build_input_gamma_table(struct curveType *TRC) - { - float *gamma_table; -@@ -254,7 +269,10 @@ float *build_input_gamma_table(struct curveType *TRC) - } - } - } -- return gamma_table; -+ -+ validate_gamma_table(gamma_table); -+ -+ return gamma_table; - } - - struct matrix build_colorant_matrix(qcms_profile *p) -@@ -295,7 +313,7 @@ uint16_fract_t lut_inverse_interp16(uint16_t Value, uint16_t LutTable[], int len - - NumZeroes = 0; - while (LutTable[NumZeroes] == 0 && NumZeroes < length-1) -- NumZeroes++; -+ NumZeroes++; - - // There are no zeros at the beginning and we are trying to find a zero, so - // return anything. It seems zero would be the less destructive choice -@@ -305,26 +323,37 @@ uint16_fract_t lut_inverse_interp16(uint16_t Value, uint16_t LutTable[], int len - - NumPoles = 0; - while (LutTable[length-1- NumPoles] == 0xFFFF && NumPoles < length-1) -- NumPoles++; -+ NumPoles++; - - // Does the curve belong to this case? - if (NumZeroes > 1 || NumPoles > 1) -- { -- int a, b; -+ { -+ int a, b, sample; - -- // Identify if value fall downto 0 or FFFF zone -+ // Identify if value fall downto 0 or FFFF zone - if (Value == 0) return 0; -- // if (Value == 0xFFFF) return 0xFFFF; -+ // if (Value == 0xFFFF) return 0xFFFF; -+ sample = (length-1) * ((double) Value * (1./65535.)); -+ if (LutTable[sample] == 0) -+ return 0; -+ if (LutTable[sample] == 0xffff) -+ return 0xffff; - - // else restrict to valid zone - -- a = ((NumZeroes-1) * 0xFFFF) / (length-1); -+ a = ((NumZeroes-1) * 0xFFFF) / (length-1); - b = ((length-1 - NumPoles) * 0xFFFF) / (length-1); -- -+ - l = a - 1; - r = b + 1; -- } - -+ // Ensure a valid binary search range -+ -+ if (l < 1) -+ l = 1; -+ if (r > 0x10000) -+ r = 0x10000; -+ } - - // Seems not a degenerated case... apply binary search - -@@ -332,12 +361,12 @@ uint16_fract_t lut_inverse_interp16(uint16_t Value, uint16_t LutTable[], int len - - x = (l + r) / 2; - -- res = (int) lut_interp_linear16((uint16_fract_t) (x-1), LutTable, length); -+ res = (int) lut_interp_linear16((uint16_fract_t) (x-1), LutTable, length); - - if (res == Value) { - -- // Found exact match. -- -+ // Found exact match. -+ - return (uint16_fract_t) (x - 1); - } - -@@ -347,14 +376,14 @@ uint16_fract_t lut_inverse_interp16(uint16_t Value, uint16_t LutTable[], int len - - // Not found, should we interpolate? - -- -+ - // Get surrounding nodes -- -+ - val2 = (length-1) * ((double) (x - 1) / 65535.0); - - cell0 = (int) floor(val2); - cell1 = (int) ceil(val2); -- -+ - if (cell0 == cell1) return (uint16_fract_t) x; - - y0 = LutTable[cell0] ; -@@ -373,8 +402,7 @@ uint16_fract_t lut_inverse_interp16(uint16_t Value, uint16_t LutTable[], int len - if (f < 0.0) return (uint16_fract_t) 0; - if (f >= 65535.0) return (uint16_fract_t) 0xFFFF; - -- return (uint16_fract_t) floor(f + 0.5); -- -+ return (uint16_fract_t) floor(f + 0.5); - } - - /* -@@ -390,7 +418,7 @@ uint16_fract_t lut_inverse_interp16(uint16_t Value, uint16_t LutTable[], int len - which has an maximum error of about 9855 (pixel difference of ~38.346) - - For now, we punt the decision of output size to the caller. */ --static uint16_t *invert_lut(uint16_t *table, int length, int out_length) -+static uint16_t *invert_lut(uint16_t *table, int length, size_t out_length) - { - int i; - /* for now we invert the lut by creating a lut of size out_length -diff --git a/third_party/qcms/src/transform_util.h b/third_party/qcms/src/transform_util.h -index 8f358a8..de465f4 100644 ---- a/third_party/qcms/src/transform_util.h -+++ b/third_party/qcms/src/transform_util.h -@@ -31,9 +31,9 @@ - //XXX: could use a bettername - typedef uint16_t uint16_fract_t; - --float lut_interp_linear(double value, uint16_t *table, int length); --float lut_interp_linear_float(float value, float *table, int length); --uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, int length); -+float lut_interp_linear(double value, uint16_t *table, size_t length); -+float lut_interp_linear_float(float value, float *table, size_t length); -+uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, size_t length); - - - static inline float lerp(float a, float b, float t) |