Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | /* vim: set ts=8 sw=8 noexpandtab: */ |
michael@0 | 2 | #include "qcms.h" |
michael@0 | 3 | #include "qcmstypes.h" |
michael@0 | 4 | |
michael@0 | 5 | /* used as a lookup table for the output transformation. |
michael@0 | 6 | * we refcount them so we only need to have one around per output |
michael@0 | 7 | * profile, instead of duplicating them per transform */ |
michael@0 | 8 | struct precache_output |
michael@0 | 9 | { |
michael@0 | 10 | int ref_count; |
michael@0 | 11 | /* We previously used a count of 65536 here but that seems like more |
michael@0 | 12 | * precision than we actually need. By reducing the size we can |
michael@0 | 13 | * improve startup performance and reduce memory usage. ColorSync on |
michael@0 | 14 | * 10.5 uses 4097 which is perhaps because they use a fixed point |
michael@0 | 15 | * representation where 1. is represented by 0x1000. */ |
michael@0 | 16 | #define PRECACHE_OUTPUT_SIZE 8192 |
michael@0 | 17 | #define PRECACHE_OUTPUT_MAX (PRECACHE_OUTPUT_SIZE-1) |
michael@0 | 18 | uint8_t data[PRECACHE_OUTPUT_SIZE]; |
michael@0 | 19 | }; |
michael@0 | 20 | |
michael@0 | 21 | #ifdef _MSC_VER |
michael@0 | 22 | #define ALIGN __declspec(align(16)) |
michael@0 | 23 | #else |
michael@0 | 24 | #define ALIGN __attribute__(( aligned (16) )) |
michael@0 | 25 | #endif |
michael@0 | 26 | |
michael@0 | 27 | struct _qcms_transform { |
michael@0 | 28 | float ALIGN matrix[3][4]; |
michael@0 | 29 | float *input_gamma_table_r; |
michael@0 | 30 | float *input_gamma_table_g; |
michael@0 | 31 | float *input_gamma_table_b; |
michael@0 | 32 | |
michael@0 | 33 | float *input_clut_table_r; |
michael@0 | 34 | float *input_clut_table_g; |
michael@0 | 35 | float *input_clut_table_b; |
michael@0 | 36 | uint16_t input_clut_table_length; |
michael@0 | 37 | float *r_clut; |
michael@0 | 38 | float *g_clut; |
michael@0 | 39 | float *b_clut; |
michael@0 | 40 | uint16_t grid_size; |
michael@0 | 41 | float *output_clut_table_r; |
michael@0 | 42 | float *output_clut_table_g; |
michael@0 | 43 | float *output_clut_table_b; |
michael@0 | 44 | uint16_t output_clut_table_length; |
michael@0 | 45 | |
michael@0 | 46 | float *input_gamma_table_gray; |
michael@0 | 47 | |
michael@0 | 48 | float out_gamma_r; |
michael@0 | 49 | float out_gamma_g; |
michael@0 | 50 | float out_gamma_b; |
michael@0 | 51 | |
michael@0 | 52 | float out_gamma_gray; |
michael@0 | 53 | |
michael@0 | 54 | uint16_t *output_gamma_lut_r; |
michael@0 | 55 | uint16_t *output_gamma_lut_g; |
michael@0 | 56 | uint16_t *output_gamma_lut_b; |
michael@0 | 57 | |
michael@0 | 58 | uint16_t *output_gamma_lut_gray; |
michael@0 | 59 | |
michael@0 | 60 | size_t output_gamma_lut_r_length; |
michael@0 | 61 | size_t output_gamma_lut_g_length; |
michael@0 | 62 | size_t output_gamma_lut_b_length; |
michael@0 | 63 | |
michael@0 | 64 | size_t output_gamma_lut_gray_length; |
michael@0 | 65 | |
michael@0 | 66 | struct precache_output *output_table_r; |
michael@0 | 67 | struct precache_output *output_table_g; |
michael@0 | 68 | struct precache_output *output_table_b; |
michael@0 | 69 | |
michael@0 | 70 | void (*transform_fn)(struct _qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length); |
michael@0 | 71 | }; |
michael@0 | 72 | |
michael@0 | 73 | struct matrix { |
michael@0 | 74 | float m[3][3]; |
michael@0 | 75 | bool invalid; |
michael@0 | 76 | }; |
michael@0 | 77 | |
michael@0 | 78 | struct qcms_modular_transform; |
michael@0 | 79 | |
michael@0 | 80 | typedef void (*transform_module_fn_t)(struct qcms_modular_transform *transform, float *src, float *dest, size_t length); |
michael@0 | 81 | |
michael@0 | 82 | struct qcms_modular_transform { |
michael@0 | 83 | struct matrix matrix; |
michael@0 | 84 | float tx, ty, tz; |
michael@0 | 85 | |
michael@0 | 86 | float *input_clut_table_r; |
michael@0 | 87 | float *input_clut_table_g; |
michael@0 | 88 | float *input_clut_table_b; |
michael@0 | 89 | uint16_t input_clut_table_length; |
michael@0 | 90 | float *r_clut; |
michael@0 | 91 | float *g_clut; |
michael@0 | 92 | float *b_clut; |
michael@0 | 93 | uint16_t grid_size; |
michael@0 | 94 | float *output_clut_table_r; |
michael@0 | 95 | float *output_clut_table_g; |
michael@0 | 96 | float *output_clut_table_b; |
michael@0 | 97 | uint16_t output_clut_table_length; |
michael@0 | 98 | |
michael@0 | 99 | uint16_t *output_gamma_lut_r; |
michael@0 | 100 | uint16_t *output_gamma_lut_g; |
michael@0 | 101 | uint16_t *output_gamma_lut_b; |
michael@0 | 102 | |
michael@0 | 103 | size_t output_gamma_lut_r_length; |
michael@0 | 104 | size_t output_gamma_lut_g_length; |
michael@0 | 105 | size_t output_gamma_lut_b_length; |
michael@0 | 106 | |
michael@0 | 107 | transform_module_fn_t transform_module_fn; |
michael@0 | 108 | struct qcms_modular_transform *next_transform; |
michael@0 | 109 | }; |
michael@0 | 110 | |
michael@0 | 111 | typedef int32_t s15Fixed16Number; |
michael@0 | 112 | typedef uint16_t uInt16Number; |
michael@0 | 113 | typedef uint8_t uInt8Number; |
michael@0 | 114 | |
michael@0 | 115 | struct XYZNumber { |
michael@0 | 116 | s15Fixed16Number X; |
michael@0 | 117 | s15Fixed16Number Y; |
michael@0 | 118 | s15Fixed16Number Z; |
michael@0 | 119 | }; |
michael@0 | 120 | |
michael@0 | 121 | struct curveType { |
michael@0 | 122 | uint32_t type; |
michael@0 | 123 | uint32_t count; |
michael@0 | 124 | float parameter[7]; |
michael@0 | 125 | uInt16Number data[]; |
michael@0 | 126 | }; |
michael@0 | 127 | |
michael@0 | 128 | struct lutmABType { |
michael@0 | 129 | uint8_t num_in_channels; |
michael@0 | 130 | uint8_t num_out_channels; |
michael@0 | 131 | // 16 is the upperbound, actual is 0..num_in_channels. |
michael@0 | 132 | uint8_t num_grid_points[16]; |
michael@0 | 133 | |
michael@0 | 134 | s15Fixed16Number e00; |
michael@0 | 135 | s15Fixed16Number e01; |
michael@0 | 136 | s15Fixed16Number e02; |
michael@0 | 137 | s15Fixed16Number e03; |
michael@0 | 138 | s15Fixed16Number e10; |
michael@0 | 139 | s15Fixed16Number e11; |
michael@0 | 140 | s15Fixed16Number e12; |
michael@0 | 141 | s15Fixed16Number e13; |
michael@0 | 142 | s15Fixed16Number e20; |
michael@0 | 143 | s15Fixed16Number e21; |
michael@0 | 144 | s15Fixed16Number e22; |
michael@0 | 145 | s15Fixed16Number e23; |
michael@0 | 146 | |
michael@0 | 147 | // reversed elements (for mBA) |
michael@0 | 148 | bool reversed; |
michael@0 | 149 | |
michael@0 | 150 | float *clut_table; |
michael@0 | 151 | struct curveType *a_curves[10]; |
michael@0 | 152 | struct curveType *b_curves[10]; |
michael@0 | 153 | struct curveType *m_curves[10]; |
michael@0 | 154 | float clut_table_data[]; |
michael@0 | 155 | }; |
michael@0 | 156 | |
michael@0 | 157 | /* should lut8Type and lut16Type be different types? */ |
michael@0 | 158 | struct lutType { // used by lut8Type/lut16Type (mft2) only |
michael@0 | 159 | uint8_t num_input_channels; |
michael@0 | 160 | uint8_t num_output_channels; |
michael@0 | 161 | uint8_t num_clut_grid_points; |
michael@0 | 162 | |
michael@0 | 163 | s15Fixed16Number e00; |
michael@0 | 164 | s15Fixed16Number e01; |
michael@0 | 165 | s15Fixed16Number e02; |
michael@0 | 166 | s15Fixed16Number e10; |
michael@0 | 167 | s15Fixed16Number e11; |
michael@0 | 168 | s15Fixed16Number e12; |
michael@0 | 169 | s15Fixed16Number e20; |
michael@0 | 170 | s15Fixed16Number e21; |
michael@0 | 171 | s15Fixed16Number e22; |
michael@0 | 172 | |
michael@0 | 173 | uint16_t num_input_table_entries; |
michael@0 | 174 | uint16_t num_output_table_entries; |
michael@0 | 175 | |
michael@0 | 176 | float *input_table; |
michael@0 | 177 | float *clut_table; |
michael@0 | 178 | float *output_table; |
michael@0 | 179 | |
michael@0 | 180 | float table_data[]; |
michael@0 | 181 | }; |
michael@0 | 182 | #if 0 |
michael@0 | 183 | /* this is from an intial idea of having the struct correspond to the data in |
michael@0 | 184 | * the file. I decided that it wasn't a good idea. |
michael@0 | 185 | */ |
michael@0 | 186 | struct tag_value { |
michael@0 | 187 | uint32_t type; |
michael@0 | 188 | union { |
michael@0 | 189 | struct { |
michael@0 | 190 | uint32_t reserved; |
michael@0 | 191 | struct { |
michael@0 | 192 | s15Fixed16Number X; |
michael@0 | 193 | s15Fixed16Number Y; |
michael@0 | 194 | s15Fixed16Number Z; |
michael@0 | 195 | } XYZNumber; |
michael@0 | 196 | } XYZType; |
michael@0 | 197 | }; |
michael@0 | 198 | }; // I guess we need to pack this? |
michael@0 | 199 | #endif |
michael@0 | 200 | |
michael@0 | 201 | #define RGB_SIGNATURE 0x52474220 |
michael@0 | 202 | #define GRAY_SIGNATURE 0x47524159 |
michael@0 | 203 | #define XYZ_SIGNATURE 0x58595A20 |
michael@0 | 204 | #define LAB_SIGNATURE 0x4C616220 |
michael@0 | 205 | |
michael@0 | 206 | struct _qcms_profile { |
michael@0 | 207 | uint32_t class; |
michael@0 | 208 | uint32_t color_space; |
michael@0 | 209 | uint32_t pcs; |
michael@0 | 210 | qcms_intent rendering_intent; |
michael@0 | 211 | struct XYZNumber redColorant; |
michael@0 | 212 | struct XYZNumber blueColorant; |
michael@0 | 213 | struct XYZNumber greenColorant; |
michael@0 | 214 | struct curveType *redTRC; |
michael@0 | 215 | struct curveType *blueTRC; |
michael@0 | 216 | struct curveType *greenTRC; |
michael@0 | 217 | struct curveType *grayTRC; |
michael@0 | 218 | struct lutType *A2B0; |
michael@0 | 219 | struct lutType *B2A0; |
michael@0 | 220 | struct lutmABType *mAB; |
michael@0 | 221 | struct lutmABType *mBA; |
michael@0 | 222 | struct matrix chromaticAdaption; |
michael@0 | 223 | |
michael@0 | 224 | struct precache_output *output_table_r; |
michael@0 | 225 | struct precache_output *output_table_g; |
michael@0 | 226 | struct precache_output *output_table_b; |
michael@0 | 227 | }; |
michael@0 | 228 | |
michael@0 | 229 | #ifdef _MSC_VER |
michael@0 | 230 | #define inline _inline |
michael@0 | 231 | #endif |
michael@0 | 232 | |
michael@0 | 233 | /* produces the nearest float to 'a' with a maximum error |
michael@0 | 234 | * of 1/1024 which happens for large values like 0x40000040 */ |
michael@0 | 235 | static inline float s15Fixed16Number_to_float(s15Fixed16Number a) |
michael@0 | 236 | { |
michael@0 | 237 | return ((int32_t)a)/65536.f; |
michael@0 | 238 | } |
michael@0 | 239 | |
michael@0 | 240 | static inline s15Fixed16Number double_to_s15Fixed16Number(double v) |
michael@0 | 241 | { |
michael@0 | 242 | return (int32_t)(v*65536); |
michael@0 | 243 | } |
michael@0 | 244 | |
michael@0 | 245 | static inline float uInt8Number_to_float(uInt8Number a) |
michael@0 | 246 | { |
michael@0 | 247 | return ((int32_t)a)/255.f; |
michael@0 | 248 | } |
michael@0 | 249 | |
michael@0 | 250 | static inline float uInt16Number_to_float(uInt16Number a) |
michael@0 | 251 | { |
michael@0 | 252 | return ((int32_t)a)/65535.f; |
michael@0 | 253 | } |
michael@0 | 254 | |
michael@0 | 255 | |
michael@0 | 256 | void precache_release(struct precache_output *p); |
michael@0 | 257 | qcms_bool set_rgb_colorants(qcms_profile *profile, qcms_CIE_xyY white_point, qcms_CIE_xyYTRIPLE primaries); |
michael@0 | 258 | qcms_bool get_rgb_colorants(struct matrix *colorants, qcms_CIE_xyY white_point, qcms_CIE_xyYTRIPLE primaries); |
michael@0 | 259 | |
michael@0 | 260 | void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform, |
michael@0 | 261 | unsigned char *src, |
michael@0 | 262 | unsigned char *dest, |
michael@0 | 263 | size_t length); |
michael@0 | 264 | void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform, |
michael@0 | 265 | unsigned char *src, |
michael@0 | 266 | unsigned char *dest, |
michael@0 | 267 | size_t length); |
michael@0 | 268 | void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, |
michael@0 | 269 | unsigned char *src, |
michael@0 | 270 | unsigned char *dest, |
michael@0 | 271 | size_t length); |
michael@0 | 272 | void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform, |
michael@0 | 273 | unsigned char *src, |
michael@0 | 274 | unsigned char *dest, |
michael@0 | 275 | size_t length); |
michael@0 | 276 | |
michael@0 | 277 | void qcms_transform_data_rgb_out_lut_altivec(qcms_transform *transform, |
michael@0 | 278 | unsigned char *src, |
michael@0 | 279 | unsigned char *dest, |
michael@0 | 280 | size_t length); |
michael@0 | 281 | void qcms_transform_data_rgba_out_lut_altivec(qcms_transform *transform, |
michael@0 | 282 | unsigned char *src, |
michael@0 | 283 | unsigned char *dest, |
michael@0 | 284 | size_t length); |
michael@0 | 285 | |
michael@0 | 286 | extern qcms_bool qcms_supports_iccv4; |
michael@0 | 287 | |
michael@0 | 288 | #ifdef _MSC_VER |
michael@0 | 289 | |
michael@0 | 290 | long __cdecl _InterlockedIncrement(long volatile *); |
michael@0 | 291 | long __cdecl _InterlockedDecrement(long volatile *); |
michael@0 | 292 | #pragma intrinsic(_InterlockedIncrement) |
michael@0 | 293 | #pragma intrinsic(_InterlockedDecrement) |
michael@0 | 294 | |
michael@0 | 295 | #define qcms_atomic_increment(x) _InterlockedIncrement((long volatile *)&x) |
michael@0 | 296 | #define qcms_atomic_decrement(x) _InterlockedDecrement((long volatile*)&x) |
michael@0 | 297 | |
michael@0 | 298 | #else |
michael@0 | 299 | |
michael@0 | 300 | #define qcms_atomic_increment(x) __sync_add_and_fetch(&x, 1) |
michael@0 | 301 | #define qcms_atomic_decrement(x) __sync_sub_and_fetch(&x, 1) |
michael@0 | 302 | |
michael@0 | 303 | #endif |
michael@0 | 304 | |
michael@0 | 305 | |
michael@0 | 306 | #ifdef NATIVE_OUTPUT |
michael@0 | 307 | # define RGB_OUTPUT_COMPONENTS 4 |
michael@0 | 308 | # define RGBA_OUTPUT_COMPONENTS 4 |
michael@0 | 309 | # ifdef IS_LITTLE_ENDIAN |
michael@0 | 310 | # define OUTPUT_A_INDEX 3 |
michael@0 | 311 | # define OUTPUT_R_INDEX 2 |
michael@0 | 312 | # define OUTPUT_G_INDEX 1 |
michael@0 | 313 | # define OUTPUT_B_INDEX 0 |
michael@0 | 314 | # else |
michael@0 | 315 | # define OUTPUT_A_INDEX 0 |
michael@0 | 316 | # define OUTPUT_R_INDEX 1 |
michael@0 | 317 | # define OUTPUT_G_INDEX 2 |
michael@0 | 318 | # define OUTPUT_B_INDEX 3 |
michael@0 | 319 | # endif |
michael@0 | 320 | #else |
michael@0 | 321 | # define RGB_OUTPUT_COMPONENTS 3 |
michael@0 | 322 | # define RGBA_OUTPUT_COMPONENTS 4 |
michael@0 | 323 | # define OUTPUT_R_INDEX 0 |
michael@0 | 324 | # define OUTPUT_G_INDEX 1 |
michael@0 | 325 | # define OUTPUT_B_INDEX 2 |
michael@0 | 326 | # define OUTPUT_A_INDEX 3 |
michael@0 | 327 | #endif |