--- modules/skcms/src/Transform_inl.h.orig +++ modules/skcms/src/Transform_inl.h @@ -494,7 +494,9 @@ SI U32 gather_24(const uint8_t* p, I32 ix) { // First, back up a byte. Any place we're gathering from has a safe junk byte to read - // in front of it, either a previous table value, or some tag metadata. + // in front of it, either a previous table value, or some tag metadata. (There is no + // such guarantee *after* the table, so big-endian must read the same bytes and mask, + // rather than reading one byte further along.) p -= 1; // Load the i'th 24-bit value from p, and 1 extra byte. @@ -530,8 +532,14 @@ U32 v = (U32)_mm512_i32gather_epi32((__m512i)(3*ix), p4, 1); #endif - // Shift off the junk byte, leaving r,g,b in low 24 bits (and zero in the top 8). + // Drop the junk byte, leaving r,g,b in the low 24 bits (and zero in the top 8). + // Little-endian loaded [junk,r,g,b] as b<<24|g<<16|r<<8|junk, big-endian as + // junk<<24|r<<16|g<<8|b, so the junk byte is at the opposite end. +#if defined(SKCMS_BIG_ENDIAN) + return v & 0x00ffffff; +#else return v >> 8; +#endif } #if !defined(__arm__) @@ -589,7 +597,11 @@ store((char*)v + 64, hi); #endif +#if defined(SKCMS_BIG_ENDIAN) + *v &= 0x0000ffffffffffffULL; +#else *v >>= 16; +#endif } #endif @@ -600,9 +612,13 @@ SI F F_from_U16_BE(U16 v) { // All 16-bit ICC values are big-endian, so we byte swap before converting to float. // MSVC catches the "loss" of data here in the portable path, so we also make sure to mask. +#if !defined(SKCMS_BIG_ENDIAN) U16 lo = (v >> 8), hi = (v << 8) & 0xffff; return cast(lo|hi) * (1/65535.0f); +#else + return cast(v) * (1/65535.0f); +#endif } SI U16 U16_from_F(F v) { @@ -641,19 +657,32 @@ SI void sample_clut_8(const uint8_t* grid_8, I32 ix, F* r, F* g, F* b) { U32 rgb = gather_24(grid_8, ix); +#if defined(SKCMS_BIG_ENDIAN) + *r = cast((rgb >> 16) & 0xff) * (1/255.0f); + *g = cast((rgb >> 8) & 0xff) * (1/255.0f); + *b = cast((rgb >> 0) & 0xff) * (1/255.0f); +#else *r = cast((rgb >> 0) & 0xff) * (1/255.0f); *g = cast((rgb >> 8) & 0xff) * (1/255.0f); *b = cast((rgb >> 16) & 0xff) * (1/255.0f); +#endif } SI void sample_clut_8(const uint8_t* grid_8, I32 ix, F* r, F* g, F* b, F* a) { // TODO: don't forget to optimize gather_32(). U32 rgba = gather_32(grid_8, ix); +#if defined(SKCMS_BIG_ENDIAN) + *r = cast((rgba >> 24) & 0xff) * (1/255.0f); + *g = cast((rgba >> 16) & 0xff) * (1/255.0f); + *b = cast((rgba >> 8) & 0xff) * (1/255.0f); + *a = cast((rgba >> 0) & 0xff) * (1/255.0f); +#else *r = cast((rgba >> 0) & 0xff) * (1/255.0f); *g = cast((rgba >> 8) & 0xff) * (1/255.0f); *b = cast((rgba >> 16) & 0xff) * (1/255.0f); *a = cast((rgba >> 24) & 0xff) * (1/255.0f); +#endif } SI void sample_clut_16(const uint8_t* grid_16, I32 ix, F* r, F* g, F* b) { @@ -666,12 +695,18 @@ // This strategy is much faster for 64-bit builds, and fine for 32-bit x86 too. U64 rgb; gather_48(grid_16, ix, &rgb); +#if defined(SKCMS_BIG_ENDIAN) + *r = cast((rgb >> 32) & 0xffff) * (1/65535.0f); + *g = cast((rgb >> 16) & 0xffff) * (1/65535.0f); + *b = cast((rgb >> 0) & 0xffff) * (1/65535.0f); +#else rgb = swap_endian_16x4(rgb); *r = cast((rgb >> 0) & 0xffff) * (1/65535.0f); *g = cast((rgb >> 16) & 0xffff) * (1/65535.0f); *b = cast((rgb >> 32) & 0xffff) * (1/65535.0f); #endif +#endif } SI void sample_clut_16(const uint8_t* grid_16, I32 ix, F* r, F* g, F* b, F* a) { @@ -896,10 +931,17 @@ STAGE(load_8888, NoCtx) { U32 rgba = load(src + 4*i); +#if defined(SKCMS_BIG_ENDIAN) + r = cast((rgba >> 24) & 0xff) * (1/255.0f); + g = cast((rgba >> 16) & 0xff) * (1/255.0f); + b = cast((rgba >> 8) & 0xff) * (1/255.0f); + a = cast((rgba >> 0) & 0xff) * (1/255.0f); +#else r = cast((rgba >> 0) & 0xff) * (1/255.0f); g = cast((rgba >> 8) & 0xff) * (1/255.0f); b = cast((rgba >> 16) & 0xff) * (1/255.0f); a = cast((rgba >> 24) & 0xff) * (1/255.0f); +#endif } STAGE(load_1010102, NoCtx) { @@ -933,14 +975,30 @@ const uint16_t* rgb = (const uint16_t*)ptr; // cast to const uint16_t* to be safe. #if defined(USING_NEON) uint16x4x3_t v = vld3_u16(rgb); +#if defined(SKCMS_BIG_ENDIAN) + r = cast(swap_endian_16((U16)v.val[0])) * (1/65535.0f); + g = cast(swap_endian_16((U16)v.val[1])) * (1/65535.0f); + b = cast(swap_endian_16((U16)v.val[2])) * (1/65535.0f); +#else r = cast((U16)v.val[0]) * (1/65535.0f); g = cast((U16)v.val[1]) * (1/65535.0f); b = cast((U16)v.val[2]) * (1/65535.0f); +#endif +#else +#if defined(SKCMS_BIG_ENDIAN) + U32 R = load_3(rgb+0), + G = load_3(rgb+1), + B = load_3(rgb+2); + // R,G,B are little-endian 16-bit, so byte swap them before converting to float. + r = cast((R & 0x00ff)<<8 | (R & 0xff00)>>8) * (1/65535.0f); + g = cast((G & 0x00ff)<<8 | (G & 0xff00)>>8) * (1/65535.0f); + b = cast((B & 0x00ff)<<8 | (B & 0xff00)>>8) * (1/65535.0f); #else r = cast(load_3(rgb+0)) * (1/65535.0f); g = cast(load_3(rgb+1)) * (1/65535.0f); b = cast(load_3(rgb+2)) * (1/65535.0f); #endif +#endif } STAGE(load_16161616LE, NoCtx) { @@ -949,10 +1007,25 @@ const uint16_t* rgba = (const uint16_t*)ptr; // cast to const uint16_t* to be safe. #if defined(USING_NEON) uint16x4x4_t v = vld4_u16(rgba); +#if defined(SKCMS_BIG_ENDIAN) + r = cast(swap_endian_16((U16)v.val[0])) * (1/65535.0f); + g = cast(swap_endian_16((U16)v.val[1])) * (1/65535.0f); + b = cast(swap_endian_16((U16)v.val[2])) * (1/65535.0f); + a = cast(swap_endian_16((U16)v.val[3])) * (1/65535.0f); +#else r = cast((U16)v.val[0]) * (1/65535.0f); g = cast((U16)v.val[1]) * (1/65535.0f); b = cast((U16)v.val[2]) * (1/65535.0f); a = cast((U16)v.val[3]) * (1/65535.0f); +#endif +#else +#if defined(SKCMS_BIG_ENDIAN) + U64 px = swap_endian_16x4(load(rgba)); + + r = cast((px >> 48) & 0xffff) * (1/65535.0f); + g = cast((px >> 32) & 0xffff) * (1/65535.0f); + b = cast((px >> 16) & 0xffff) * (1/65535.0f); + a = cast((px >> 0) & 0xffff) * (1/65535.0f); #else U64 px = load(rgba); @@ -961,6 +1034,7 @@ b = cast((px >> 32) & 0xffff) * (1/65535.0f); a = cast((px >> 48) & 0xffff) * (1/65535.0f); #endif +#endif } STAGE(load_161616BE, NoCtx) { @@ -969,9 +1043,20 @@ const uint16_t* rgb = (const uint16_t*)ptr; // cast to const uint16_t* to be safe. #if defined(USING_NEON) uint16x4x3_t v = vld3_u16(rgb); +#if defined(SKCMS_BIG_ENDIAN) + r = cast((U16)v.val[0]) * (1/65535.0f); + g = cast((U16)v.val[1]) * (1/65535.0f); + b = cast((U16)v.val[2]) * (1/65535.0f); +#else r = cast(swap_endian_16((U16)v.val[0])) * (1/65535.0f); g = cast(swap_endian_16((U16)v.val[1])) * (1/65535.0f); b = cast(swap_endian_16((U16)v.val[2])) * (1/65535.0f); +#endif +#else +#if defined(SKCMS_BIG_ENDIAN) + r = cast(load_3(rgb+0)) * (1/65535.0f); + g = cast(load_3(rgb+1)) * (1/65535.0f); + b = cast(load_3(rgb+2)) * (1/65535.0f); #else U32 R = load_3(rgb+0), G = load_3(rgb+1), @@ -981,6 +1066,7 @@ g = cast((G & 0x00ff)<<8 | (G & 0xff00)>>8) * (1/65535.0f); b = cast((B & 0x00ff)<<8 | (B & 0xff00)>>8) * (1/65535.0f); #endif +#endif } STAGE(load_16161616BE, NoCtx) { @@ -989,10 +1075,25 @@ const uint16_t* rgba = (const uint16_t*)ptr; // cast to const uint16_t* to be safe. #if defined(USING_NEON) uint16x4x4_t v = vld4_u16(rgba); +#if defined(SKCMS_BIG_ENDIAN) + r = cast((U16)v.val[0]) * (1/65535.0f); + g = cast((U16)v.val[1]) * (1/65535.0f); + b = cast((U16)v.val[2]) * (1/65535.0f); + a = cast((U16)v.val[3]) * (1/65535.0f); +#else r = cast(swap_endian_16((U16)v.val[0])) * (1/65535.0f); g = cast(swap_endian_16((U16)v.val[1])) * (1/65535.0f); b = cast(swap_endian_16((U16)v.val[2])) * (1/65535.0f); a = cast(swap_endian_16((U16)v.val[3])) * (1/65535.0f); +#endif +#else +#if defined(SKCMS_BIG_ENDIAN) + U64 px = load(rgba); + + r = cast((px >> 48) & 0xffff) * (1/65535.0f); + g = cast((px >> 32) & 0xffff) * (1/65535.0f); + b = cast((px >> 16) & 0xffff) * (1/65535.0f); + a = cast((px >> 0) & 0xffff) * (1/65535.0f); #else U64 px = swap_endian_16x4(load(rgba)); @@ -1001,6 +1102,7 @@ b = cast((px >> 32) & 0xffff) * (1/65535.0f); a = cast((px >> 48) & 0xffff) * (1/65535.0f); #endif +#endif } STAGE(load_hhh, NoCtx) { @@ -1034,11 +1136,18 @@ A = (U16)v.val[3]; #else U64 px = load(rgba); +#if defined(SKCMS_BIG_ENDIAN) + U16 R = cast((px >> 48) & 0xffff), + G = cast((px >> 32) & 0xffff), + B = cast((px >> 16) & 0xffff), + A = cast((px >> 0) & 0xffff); +#else U16 R = cast((px >> 0) & 0xffff), G = cast((px >> 16) & 0xffff), B = cast((px >> 32) & 0xffff), A = cast((px >> 48) & 0xffff); #endif +#endif r = F_from_Half(R); g = F_from_Half(G); b = F_from_Half(B); @@ -1344,10 +1453,17 @@ } FINAL_STAGE(store_8888, NoCtx) { +#if defined(SKCMS_BIG_ENDIAN) + store(dst + 4*i, cast(to_fixed(r * 255)) << 24 + | cast(to_fixed(g * 255)) << 16 + | cast(to_fixed(b * 255)) << 8 + | cast(to_fixed(a * 255)) << 0); +#else store(dst + 4*i, cast(to_fixed(r * 255)) << 0 | cast(to_fixed(g * 255)) << 8 | cast(to_fixed(b * 255)) << 16 | cast(to_fixed(a * 255)) << 24); +#endif } FINAL_STAGE(store_101010x_XR, NoCtx) { @@ -1377,16 +1493,31 @@ uint16_t* rgb = (uint16_t*)ptr; // for this cast to uint16_t* to be safe. #if defined(USING_NEON) uint16x4x3_t v = {{ +#if defined(SKCMS_BIG_ENDIAN) + (uint16x4_t)swap_endian_16(cast(U16_from_F(r))), + (uint16x4_t)swap_endian_16(cast(U16_from_F(g))), + (uint16x4_t)swap_endian_16(cast(U16_from_F(b))), +#else (uint16x4_t)U16_from_F(r), (uint16x4_t)U16_from_F(g), (uint16x4_t)U16_from_F(b), +#endif }}; vst3_u16(rgb, v); #else +#if defined(SKCMS_BIG_ENDIAN) + U32 R = to_fixed(r * 65535), + G = to_fixed(g * 65535), + B = to_fixed(b * 65535); + store_3(rgb+0, cast((R & 0x00ff) << 8 | (R & 0xff00) >> 8) ); + store_3(rgb+1, cast((G & 0x00ff) << 8 | (G & 0xff00) >> 8) ); + store_3(rgb+2, cast((B & 0x00ff) << 8 | (B & 0xff00) >> 8) ); +#else store_3(rgb+0, U16_from_F(r)); store_3(rgb+1, U16_from_F(g)); store_3(rgb+2, U16_from_F(b)); #endif +#endif } @@ -1396,19 +1527,34 @@ uint16_t* rgba = (uint16_t*)ptr; // for this cast to uint16_t* to be safe. #if defined(USING_NEON) uint16x4x4_t v = {{ +#if defined(SKCMS_BIG_ENDIAN) + (uint16x4_t)swap_endian_16(cast(U16_from_F(r))), + (uint16x4_t)swap_endian_16(cast(U16_from_F(g))), + (uint16x4_t)swap_endian_16(cast(U16_from_F(b))), + (uint16x4_t)swap_endian_16(cast(U16_from_F(a))), +#else (uint16x4_t)U16_from_F(r), (uint16x4_t)U16_from_F(g), (uint16x4_t)U16_from_F(b), (uint16x4_t)U16_from_F(a), +#endif }}; vst4_u16(rgba, v); #else +#if defined(SKCMS_BIG_ENDIAN) + U64 px = cast(to_fixed(r * 65535)) << 48 + | cast(to_fixed(g * 65535)) << 32 + | cast(to_fixed(b * 65535)) << 16 + | cast(to_fixed(a * 65535)) << 0; + store(rgba, swap_endian_16x4(px)); +#else U64 px = cast(to_fixed(r * 65535)) << 0 | cast(to_fixed(g * 65535)) << 16 | cast(to_fixed(b * 65535)) << 32 | cast(to_fixed(a * 65535)) << 48; store(rgba, px); #endif +#endif } FINAL_STAGE(store_161616BE, NoCtx) { @@ -1417,12 +1563,23 @@ uint16_t* rgb = (uint16_t*)ptr; // for this cast to uint16_t* to be safe. #if defined(USING_NEON) uint16x4x3_t v = {{ +#if defined(SKCMS_BIG_ENDIAN) + (uint16x4_t)U16_from_F(r), + (uint16x4_t)U16_from_F(g), + (uint16x4_t)U16_from_F(b), +#else (uint16x4_t)swap_endian_16(cast(U16_from_F(r))), (uint16x4_t)swap_endian_16(cast(U16_from_F(g))), (uint16x4_t)swap_endian_16(cast(U16_from_F(b))), +#endif }}; vst3_u16(rgb, v); #else +#if defined(SKCMS_BIG_ENDIAN) + store_3(rgb+0, U16_from_F(r)); + store_3(rgb+1, U16_from_F(g)); + store_3(rgb+2, U16_from_F(b)); +#else U32 R = to_fixed(r * 65535), G = to_fixed(g * 65535), B = to_fixed(b * 65535); @@ -1430,6 +1587,7 @@ store_3(rgb+1, cast((G & 0x00ff) << 8 | (G & 0xff00) >> 8) ); store_3(rgb+2, cast((B & 0x00ff) << 8 | (B & 0xff00) >> 8) ); #endif +#endif } @@ -1439,19 +1597,34 @@ uint16_t* rgba = (uint16_t*)ptr; // for this cast to uint16_t* to be safe. #if defined(USING_NEON) uint16x4x4_t v = {{ +#if defined(SKCMS_BIG_ENDIAN) + (uint16x4_t)U16_from_F(r), + (uint16x4_t)U16_from_F(g), + (uint16x4_t)U16_from_F(b), + (uint16x4_t)U16_from_F(a), +#else (uint16x4_t)swap_endian_16(cast(U16_from_F(r))), (uint16x4_t)swap_endian_16(cast(U16_from_F(g))), (uint16x4_t)swap_endian_16(cast(U16_from_F(b))), (uint16x4_t)swap_endian_16(cast(U16_from_F(a))), +#endif }}; vst4_u16(rgba, v); #else +#if defined(SKCMS_BIG_ENDIAN) + U64 px = cast(to_fixed(r * 65535)) << 48 + | cast(to_fixed(g * 65535)) << 32 + | cast(to_fixed(b * 65535)) << 16 + | cast(to_fixed(a * 65535)) << 0; + store(rgba, px); +#else U64 px = cast(to_fixed(r * 65535)) << 0 | cast(to_fixed(g * 65535)) << 16 | cast(to_fixed(b * 65535)) << 32 | cast(to_fixed(a * 65535)) << 48; store(rgba, swap_endian_16x4(px)); #endif +#endif } FINAL_STAGE(store_hhh, NoCtx) { @@ -1494,11 +1667,18 @@ }}; vst4_u16(rgba, v); #else +#if defined(SKCMS_BIG_ENDIAN) + store(rgba, cast(R) << 48 + | cast(G) << 32 + | cast(B) << 16 + | cast(A) << 0); +#else store(rgba, cast(R) << 0 | cast(G) << 16 | cast(B) << 32 | cast(A) << 48); #endif +#endif } FINAL_STAGE(store_fff, NoCtx) {