2 * Copyright (C) 2011 LunarG, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
25 * Included by texcompress_etc1 and gallium to define ETC1 decoding routines.
28 struct TAG(etc1_block
) {
29 uint32_t pixel_indices
;
31 const int *modifier_tables
[2];
32 UINT8_TYPE base_colors
[2][3];
36 TAG(etc1_base_color_diff_hi
)(UINT8_TYPE in
)
38 return (in
& 0xf8) | (in
>> 5);
42 TAG(etc1_base_color_diff_lo
)(UINT8_TYPE in
)
44 static const int lookup
[8] = { 0, 1, 2, 3, -4, -3, -2, -1 };
46 in
= (in
>> 3) + lookup
[in
& 0x7];
48 return (in
<< 3) | (in
>> 2);
52 TAG(etc1_base_color_ind_hi
)(UINT8_TYPE in
)
54 return (in
& 0xf0) | ((in
& 0xf0) >> 4);
58 TAG(etc1_base_color_ind_lo
)(UINT8_TYPE in
)
60 return ((in
& 0xf) << 4) | (in
& 0xf);
64 TAG(etc1_clamp
)(UINT8_TYPE base
, int modifier
)
66 int tmp
= (int) base
+ modifier
;
68 /* CLAMP(tmp, 0, 255) */
69 return (UINT8_TYPE
) ((tmp
< 0) ? 0 : ((tmp
> 255) ? 255 : tmp
));
72 static const int TAG(etc1_modifier_tables
)[8][4] = {
79 { 33, 106, -33, -106},
84 TAG(etc1_parse_block
)(struct TAG(etc1_block
) *block
, const UINT8_TYPE
*src
)
87 /* differential mode */
88 block
->base_colors
[0][0] = (int) TAG(etc1_base_color_diff_hi
)(src
[0]);
89 block
->base_colors
[1][0] = (int) TAG(etc1_base_color_diff_lo
)(src
[0]);
90 block
->base_colors
[0][1] = (int) TAG(etc1_base_color_diff_hi
)(src
[1]);
91 block
->base_colors
[1][1] = (int) TAG(etc1_base_color_diff_lo
)(src
[1]);
92 block
->base_colors
[0][2] = (int) TAG(etc1_base_color_diff_hi
)(src
[2]);
93 block
->base_colors
[1][2] = (int) TAG(etc1_base_color_diff_lo
)(src
[2]);
97 block
->base_colors
[0][0] = (int) TAG(etc1_base_color_ind_hi
)(src
[0]);
98 block
->base_colors
[1][0] = (int) TAG(etc1_base_color_ind_lo
)(src
[0]);
99 block
->base_colors
[0][1] = (int) TAG(etc1_base_color_ind_hi
)(src
[1]);
100 block
->base_colors
[1][1] = (int) TAG(etc1_base_color_ind_lo
)(src
[1]);
101 block
->base_colors
[0][2] = (int) TAG(etc1_base_color_ind_hi
)(src
[2]);
102 block
->base_colors
[1][2] = (int) TAG(etc1_base_color_ind_lo
)(src
[2]);
105 /* pick modifier tables */
106 block
->modifier_tables
[0] = TAG(etc1_modifier_tables
)[(src
[3] >> 5) & 0x7];
107 block
->modifier_tables
[1] = TAG(etc1_modifier_tables
)[(src
[3] >> 2) & 0x7];
109 block
->flipped
= (src
[3] & 0x1);
111 block
->pixel_indices
=
112 (src
[4] << 24) | (src
[5] << 16) | (src
[6] << 8) | src
[7];
116 TAG(etc1_fetch_texel
)(const struct TAG(etc1_block
) *block
,
117 int x
, int y
, UINT8_TYPE
*dst
)
119 const UINT8_TYPE
*base_color
;
120 int modifier
, bit
, idx
, blk
;
122 /* get pixel index */
124 idx
= ((block
->pixel_indices
>> (15 + bit
)) & 0x2) |
125 ((block
->pixel_indices
>> (bit
)) & 0x1);
128 blk
= (block
->flipped
) ? (y
>= 2) : (x
>= 2);
130 base_color
= block
->base_colors
[blk
];
131 modifier
= block
->modifier_tables
[blk
][idx
];
133 dst
[0] = TAG(etc1_clamp
)(base_color
[0], modifier
);
134 dst
[1] = TAG(etc1_clamp
)(base_color
[1], modifier
);
135 dst
[2] = TAG(etc1_clamp
)(base_color
[2], modifier
);
139 etc1_unpack_rgba8888(uint8_t *dst_row
,
141 const uint8_t *src_row
,
146 const unsigned bw
= 4, bh
= 4, bs
= 8, comps
= 4;
147 struct etc1_block block
;
150 for (y
= 0; y
< height
; y
+= bh
) {
151 const uint8_t *src
= src_row
;
153 for (x
= 0; x
< width
; x
+= bw
) {
154 etc1_parse_block(&block
, src
);
156 for (j
= 0; j
< MIN2(bh
, height
- y
); j
++) {
157 uint8_t *dst
= dst_row
+ (y
+ j
) * dst_stride
+ x
* comps
;
158 for (i
= 0; i
< MIN2(bw
, width
- x
); i
++) {
159 etc1_fetch_texel(&block
, i
, j
, dst
);
168 src_row
+= src_stride
;