| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1 | /* libs/opengles/dxt.cpp | 
 | 2 | ** | 
 | 3 | ** Copyright 2007, The Android Open Source Project | 
 | 4 | ** | 
 | 5 | ** Licensed under the Apache License, Version 2.0 (the "License");  | 
 | 6 | ** you may not use this file except in compliance with the License.  | 
 | 7 | ** You may obtain a copy of the License at  | 
 | 8 | ** | 
 | 9 | **     http://www.apache.org/licenses/LICENSE-2.0  | 
 | 10 | ** | 
 | 11 | ** Unless required by applicable law or agreed to in writing, software  | 
 | 12 | ** distributed under the License is distributed on an "AS IS" BASIS,  | 
 | 13 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  | 
 | 14 | ** See the License for the specific language governing permissions and  | 
 | 15 | ** limitations under the License. | 
 | 16 | */ | 
 | 17 |  | 
 | 18 | #define TIMING 0 | 
 | 19 |  | 
 | 20 | #if TIMING | 
 | 21 | #include <sys/time.h> // for optimization timing | 
 | 22 | #include <stdio.h> | 
 | 23 | #include <stdlib.h> | 
 | 24 | #endif | 
 | 25 |  | 
 | 26 | #include <GLES/gl.h> | 
 | 27 | #include <utils/Endian.h> | 
 | 28 |  | 
 | 29 | #include "context.h" | 
 | 30 |  | 
 | 31 | #define TIMING 0 | 
 | 32 |  | 
 | 33 | namespace android { | 
 | 34 |  | 
 | 35 | static uint8_t avg23tab[64*64]; | 
 | 36 | static volatile int tables_initialized = 0; | 
 | 37 |  | 
 | 38 | // Definitions below are equivalent to these over the valid range of arguments | 
 | 39 | //  #define div5(x) ((x)/5) | 
 | 40 | //  #define div7(x) ((x)/7) | 
 | 41 |  | 
 | 42 | // Use fixed-point to divide by 5 and 7 | 
 | 43 | // 3277 = 2^14/5 + 1 | 
 | 44 | // 2341 = 2^14/7 + 1 | 
 | 45 | #define div5(x) (((x)*3277) >> 14) | 
 | 46 | #define div7(x) (((x)*2341) >> 14) | 
 | 47 |  | 
 | 48 | // Table with entry [a << 6 | b] = (2*a + b)/3 for 0 <= a,b < 64 | 
 | 49 | #define avg23(x0,x1) avg23tab[((x0) << 6) | (x1)] | 
 | 50 |  | 
 | 51 | // Extract 5/6/5 RGB | 
 | 52 | #define red(x)   (((x) >> 11) & 0x1f) | 
 | 53 | #define green(x) (((x) >>  5) & 0x3f) | 
 | 54 | #define blue(x)  ( (x)        & 0x1f) | 
 | 55 |  | 
 | 56 | /* | 
 | 57 |  * Convert 5/6/5 RGB (as 3 ints) to 8/8/8 | 
 | 58 |  * | 
 | 59 |  * Operation count: 8 <<, 0 &, 5 | | 
 | 60 |  */ | 
 | 61 | inline static int rgb565SepTo888(int r, int g, int b) | 
 | 62 |  | 
 | 63 | { | 
 | 64 |     return ((((r << 3) | (r >> 2)) << 16) | | 
 | 65 |             (((g << 2) | (g >> 4)) <<  8) | | 
 | 66 |              ((b << 3) | (b >> 2))); | 
 | 67 | } | 
 | 68 |  | 
 | 69 | /* | 
 | 70 |  * Convert 5/6/5 RGB (as a single 16-bit word) to 8/8/8 | 
 | 71 |  * | 
 | 72 |  *                   r4r3r2r1 r0g5g4g3 g2g1g0b4 b3b2b1b0   rgb | 
 | 73 |  *            r4r3r2 r1r0g5g4 g3g2g1g0 b4b3b2b1 b0 0 0 0   rgb << 3 | 
 | 74 |  * r4r3r2r1 r0r4r3r2 g5g4g3g2 g1g0g5g4 b4b3b2b1 b0b4b3b2   desired result | 
 | 75 |  * | 
 | 76 |  * Construct the 24-bit RGB word as: | 
 | 77 |  * | 
 | 78 |  * r4r3r2r1 r0------ -------- -------- -------- --------  (rgb << 8) & 0xf80000 | 
 | 79 |  *            r4r3r2 -------- -------- -------- --------  (rgb << 3) & 0x070000 | 
 | 80 |  *                   g5g4g3g2 g1g0---- -------- --------  (rgb << 5) & 0x00fc00 | 
 | 81 |  *                                g5g4 -------- --------  (rgb >> 1) & 0x000300 | 
 | 82 |  *                                     b4b3b2b1 b0------  (rgb << 3) & 0x0000f8 | 
 | 83 |  *                                                b4b3b2  (rgb >> 2) & 0x000007 | 
 | 84 |  * | 
 | 85 |  * Operation count: 5 <<, 6 &, 5 | (n.b. rgb >> 3 is used twice) | 
 | 86 |  */ | 
 | 87 | inline static int rgb565To888(int rgb) | 
 | 88 |  | 
 | 89 | { | 
 | 90 |     int rgb3 = rgb >> 3; | 
 | 91 |     return (((rgb << 8) & 0xf80000) | | 
 | 92 |             ( rgb3      & 0x070000) | | 
 | 93 |             ((rgb << 5) & 0x00fc00) | | 
 | 94 |             ((rgb >> 1) & 0x000300) | | 
 | 95 |             ( rgb3      & 0x0000f8) | | 
 | 96 |             ((rgb >> 2) & 0x000007)); | 
 | 97 | } | 
 | 98 |  | 
 | 99 | #if __BYTE_ORDER == __BIG_ENDIAN | 
 | 100 | static uint32_t swap(uint32_t x) { | 
 | 101 |     int b0 = (x >> 24) & 0xff; | 
 | 102 |     int b1 = (x >> 16) & 0xff; | 
 | 103 |     int b2 = (x >>  8) & 0xff; | 
 | 104 |     int b3 = (x      ) & 0xff; | 
 | 105 |      | 
 | 106 |     return (uint32_t)((b3 << 24) | (b2 << 16) | (b1 << 8) | b0); | 
 | 107 | } | 
 | 108 | #endif | 
 | 109 |  | 
 | 110 | static void | 
 | 111 | init_tables() | 
 | 112 | { | 
 | 113 |     if (tables_initialized) { | 
 | 114 |         return; | 
 | 115 |     } | 
 | 116 |  | 
 | 117 |     for (int i = 0; i < 64; i++) { | 
 | 118 |         for (int j = 0; j < 64; j++) { | 
 | 119 |             int avg = (2*i + j)/3; | 
 | 120 |             avg23tab[(i << 6) | j] = avg; | 
 | 121 |         } | 
 | 122 |     } | 
 | 123 |  | 
 | 124 |     asm volatile ("" : : : "memory"); | 
 | 125 |     tables_initialized = 1; | 
 | 126 | } | 
 | 127 |  | 
 | 128 | /* | 
 | 129 |  * Utility to scan a DXT1 compressed texture to determine whether it | 
 | 130 |  * contains a transparent pixel (color0 < color1, code == 3).  This | 
 | 131 |  * may be useful if the application lacks information as to whether | 
 | 132 |  * the true format is GL_COMPRESSED_RGB_S3TC_DXT1_EXT or | 
 | 133 |  * GL_COMPRESSED_RGBA_S3TC_DXT1_EXT. | 
 | 134 |  */ | 
 | 135 | bool | 
 | 136 | DXT1HasAlpha(const GLvoid *data, int width, int height) {     | 
 | 137 | #if TIMING | 
 | 138 |     struct timeval start_t, end_t; | 
 | 139 |     struct timezone tz; | 
 | 140 |      | 
 | 141 |     gettimeofday(&start_t, &tz); | 
 | 142 | #endif | 
 | 143 |  | 
 | 144 |     bool hasAlpha = false; | 
 | 145 |  | 
 | 146 |     int xblocks = (width + 3)/4; | 
 | 147 |     int yblocks = (height + 3)/4; | 
 | 148 |     int numblocks = xblocks*yblocks; | 
 | 149 |  | 
 | 150 |     uint32_t const *d32 = (uint32_t *)data; | 
 | 151 |     for (int b = 0; b < numblocks; b++) { | 
 | 152 |         uint32_t colors = *d32++; | 
 | 153 |          | 
 | 154 | #if __BYTE_ORDER == __BIG_ENDIAN | 
 | 155 |         colors = swap(colors); | 
 | 156 | #endif | 
 | 157 |          | 
 | 158 |         uint16_t color0 = colors & 0xffff; | 
 | 159 |         uint16_t color1 = colors >> 16; | 
 | 160 |          | 
 | 161 |         if (color0 < color1) { | 
 | 162 |             // There's no need to endian-swap within 'bits' | 
 | 163 |             // since we don't care which pixel is the transparent one | 
 | 164 |             uint32_t bits = *d32++; | 
 | 165 |              | 
 | 166 |             // Detect if any (odd, even) pair of bits are '11' | 
 | 167 |             //      bits: b31 b30 b29 ... b3 b2 b1 b0 | 
 | 168 |             // bits >> 1: b31 b31 b30 ... b4 b3 b2 b1 | 
 | 169 |             //         &: b31 (b31 & b30) (b29 & b28) ... (b2 & b1) (b1 & b0) | 
 | 170 |             //  & 0x55..:   0 (b31 & b30)       0     ...     0     (b1 & b0) | 
 | 171 |             if (((bits & (bits >> 1)) & 0x55555555) != 0) { | 
 | 172 |                 hasAlpha = true; | 
 | 173 |                 goto done; | 
 | 174 |             } | 
 | 175 |         } else { | 
 | 176 |             // Skip 4 bytes | 
 | 177 |             ++d32; | 
 | 178 |         } | 
 | 179 |     } | 
 | 180 |      | 
 | 181 |  done: | 
 | 182 | #if TIMING | 
 | 183 |     gettimeofday(&end_t, &tz); | 
 | 184 |     long usec = (end_t.tv_sec - start_t.tv_sec)*1000000 + | 
 | 185 |         (end_t.tv_usec - start_t.tv_usec); | 
 | 186 |      | 
 | 187 |     printf("Scanned w=%d h=%d in %ld usec\n", width, height, usec); | 
 | 188 | #endif | 
 | 189 |      | 
 | 190 |     return hasAlpha; | 
 | 191 | } | 
 | 192 |  | 
 | 193 | static void | 
 | 194 | decodeDXT1(const GLvoid *data, int width, int height, | 
 | 195 |            void *surface, int stride, | 
 | 196 |            bool hasAlpha) | 
 | 197 |      | 
 | 198 | { | 
 | 199 |     init_tables(); | 
 | 200 |      | 
 | 201 |     uint32_t const *d32 = (uint32_t *)data; | 
 | 202 |      | 
 | 203 |     // Color table for the current block | 
 | 204 |     uint16_t c[4]; | 
 | 205 |     c[0] = c[1] = c[2] = c[3] = 0; | 
 | 206 |      | 
 | 207 |     // Specified colors from the previous block | 
 | 208 |     uint16_t prev_color0 = 0x0000; | 
 | 209 |     uint16_t prev_color1 = 0x0000; | 
 | 210 |      | 
 | 211 |     uint16_t* rowPtr = (uint16_t*)surface; | 
 | 212 |     for (int base_y = 0; base_y < height; base_y += 4, rowPtr += 4*stride) { | 
 | 213 |         uint16_t *blockPtr = rowPtr; | 
 | 214 |         for (int base_x = 0; base_x < width; base_x += 4, blockPtr += 4) { | 
 | 215 |             uint32_t colors = *d32++; | 
 | 216 |             uint32_t bits = *d32++; | 
 | 217 |              | 
 | 218 | #if __BYTE_ORDER == __BIG_ENDIAN | 
 | 219 |             colors = swap(colors); | 
 | 220 |             bits = swap(bits); | 
 | 221 | #endif | 
 | 222 |              | 
 | 223 |             // Raw colors | 
 | 224 |             uint16_t color0 = colors & 0xffff; | 
 | 225 |             uint16_t color1 = colors >> 16; | 
 | 226 |              | 
 | 227 |             // If the new block has the same base colors as the | 
 | 228 |             // previous one, we don't need to recompute the color | 
 | 229 |             // table c[] | 
 | 230 |             if (color0 != prev_color0 || color1 != prev_color1) { | 
 | 231 |                 // Store raw colors for comparison with next block | 
 | 232 |                 prev_color0 = color0; | 
 | 233 |                 prev_color1 = color1; | 
 | 234 |                  | 
 | 235 |                 int r0 =   red(color0); | 
 | 236 |                 int g0 = green(color0); | 
 | 237 |                 int b0 =  blue(color0); | 
 | 238 |  | 
 | 239 |                 int r1 =   red(color1); | 
 | 240 |                 int g1 = green(color1); | 
 | 241 |                 int b1 =  blue(color1);                 | 
 | 242 |                  | 
 | 243 |                 if (hasAlpha) { | 
 | 244 |                     c[0] = (r0 << 11) | ((g0 >> 1) << 6) | (b0 << 1) | 0x1; | 
 | 245 |                     c[1] = (r1 << 11) | ((g1 >> 1) << 6) | (b1 << 1) | 0x1; | 
 | 246 |                 } else { | 
 | 247 |                     c[0] = color0; | 
 | 248 |                     c[1] = color1; | 
 | 249 |                 } | 
 | 250 |                  | 
 | 251 |                 int r2, g2, b2, r3, g3, b3, a3; | 
 | 252 |                  | 
 | 253 |                 int bbits = bits >> 1; | 
 | 254 |                 bool has2 = ((bbits & ~bits) & 0x55555555) != 0; | 
 | 255 |                 bool has3 = ((bbits &  bits) & 0x55555555) != 0; | 
 | 256 |                  | 
 | 257 |                 if (has2 || has3) { | 
 | 258 |                     if (color0 > color1) { | 
 | 259 |                         r2 = avg23(r0, r1); | 
 | 260 |                         g2 = avg23(g0, g1); | 
 | 261 |                         b2 = avg23(b0, b1); | 
 | 262 |                          | 
 | 263 |                         r3 = avg23(r1, r0); | 
 | 264 |                         g3 = avg23(g1, g0); | 
 | 265 |                         b3 = avg23(b1, b0); | 
 | 266 |                         a3 = 1; | 
 | 267 |                     } else { | 
 | 268 |                         r2 = (r0 + r1) >> 1; | 
 | 269 |                         g2 = (g0 + g1) >> 1; | 
 | 270 |                         b2 = (b0 + b1) >> 1; | 
 | 271 |                          | 
 | 272 |                         r3 = g3 = b3 = a3 = 0; | 
 | 273 |                     } | 
 | 274 |                     if (hasAlpha) { | 
 | 275 |                         c[2] = (r2 << 11) | ((g2 >> 1) << 6) | | 
 | 276 |                             (b2 << 1) | 0x1; | 
 | 277 |                         c[3] = (r3 << 11) | ((g3 >> 1) << 6) | | 
 | 278 |                             (b3 << 1) | a3; | 
 | 279 |                     } else { | 
 | 280 |                         c[2] = (r2 << 11) | (g2 << 5) | b2; | 
 | 281 |                         c[3] = (r3 << 11) | (g3 << 5) | b3; | 
 | 282 |                     } | 
 | 283 |                 } | 
 | 284 |             } | 
 | 285 |              | 
 | 286 |             uint16_t* blockRowPtr = blockPtr; | 
 | 287 |             for (int y = 0; y < 4; y++, blockRowPtr += stride) { | 
 | 288 |                 // Don't process rows past the botom | 
 | 289 |                 if (base_y + y >= height) { | 
 | 290 |                     break; | 
 | 291 |                 } | 
 | 292 |                  | 
 | 293 |                 int w = min(width - base_x, 4); | 
 | 294 |                 for (int x = 0; x < w; x++) { | 
 | 295 |                     int code = bits & 0x3; | 
 | 296 |                     bits >>= 2; | 
 | 297 |                      | 
 | 298 |                     blockRowPtr[x] = c[code]; | 
 | 299 |                 } | 
 | 300 |             } | 
 | 301 |         } | 
 | 302 |     } | 
 | 303 | } | 
 | 304 |      | 
 | 305 | // Output data as internalformat=GL_RGBA, type=GL_UNSIGNED_BYTE | 
 | 306 | static void | 
 | 307 | decodeDXT3(const GLvoid *data, int width, int height, | 
 | 308 |            void *surface, int stride) | 
 | 309 |  | 
 | 310 | { | 
 | 311 |     init_tables(); | 
 | 312 |      | 
 | 313 |     uint32_t const *d32 = (uint32_t *)data; | 
 | 314 |      | 
 | 315 |     // Specified colors from the previous block | 
 | 316 |     uint16_t prev_color0 = 0x0000; | 
 | 317 |     uint16_t prev_color1 = 0x0000; | 
 | 318 |  | 
 | 319 |     // Color table for the current block | 
 | 320 |     uint32_t c[4]; | 
 | 321 |     c[0] = c[1] = c[2] = c[3] = 0; | 
 | 322 |  | 
 | 323 |     uint32_t* rowPtr = (uint32_t*)surface; | 
 | 324 |     for (int base_y = 0; base_y < height; base_y += 4, rowPtr += 4*stride) { | 
 | 325 |         uint32_t *blockPtr = rowPtr; | 
 | 326 |         for (int base_x = 0; base_x < width; base_x += 4, blockPtr += 4) { | 
 | 327 |              | 
 | 328 | #if __BYTE_ORDER == __BIG_ENDIAN | 
 | 329 |             uint32_t alphahi = *d32++; | 
 | 330 |             uint32_t alphalo = *d32++; | 
 | 331 |             alphahi = swap(alphahi); | 
 | 332 |             alphalo = swap(alphalo); | 
 | 333 | #else | 
 | 334 |             uint32_t alphalo = *d32++; | 
 | 335 |             uint32_t alphahi = *d32++; | 
 | 336 | #endif | 
 | 337 |  | 
 | 338 |             uint32_t colors = *d32++; | 
 | 339 |             uint32_t bits = *d32++; | 
 | 340 |              | 
 | 341 | #if __BYTE_ORDER == __BIG_ENDIAN | 
 | 342 |             colors = swap(colors); | 
 | 343 |             bits = swap(bits); | 
 | 344 | #endif | 
 | 345 |              | 
 | 346 |             uint64_t alpha = ((uint64_t)alphahi << 32) | alphalo; | 
 | 347 |  | 
 | 348 |             // Raw colors | 
 | 349 |             uint16_t color0 = colors & 0xffff; | 
 | 350 |             uint16_t color1 = colors >> 16; | 
 | 351 |  | 
 | 352 |             // If the new block has the same base colors as the | 
 | 353 |             // previous one, we don't need to recompute the color | 
 | 354 |             // table c[] | 
 | 355 |             if (color0 != prev_color0 || color1 != prev_color1) { | 
 | 356 |                 // Store raw colors for comparison with next block | 
 | 357 |                 prev_color0 = color0; | 
 | 358 |                 prev_color1 = color1; | 
 | 359 |                  | 
 | 360 |                 int bbits = bits >> 1; | 
 | 361 |                 bool has2 = ((bbits & ~bits) & 0x55555555) != 0; | 
 | 362 |                 bool has3 = ((bbits &  bits) & 0x55555555) != 0; | 
 | 363 |                  | 
 | 364 |                 if (has2 || has3) { | 
 | 365 |                     int r0 =   red(color0); | 
 | 366 |                     int g0 = green(color0); | 
 | 367 |                     int b0 =  blue(color0); | 
 | 368 |                      | 
 | 369 |                     int r1 =   red(color1); | 
 | 370 |                     int g1 = green(color1); | 
 | 371 |                     int b1 =  blue(color1); | 
 | 372 |                      | 
 | 373 |                     int r2 = avg23(r0, r1); | 
 | 374 |                     int g2 = avg23(g0, g1); | 
 | 375 |                     int b2 = avg23(b0, b1); | 
 | 376 |                      | 
 | 377 |                     int r3 = avg23(r1, r0); | 
 | 378 |                     int g3 = avg23(g1, g0); | 
 | 379 |                     int b3 = avg23(b1, b0); | 
 | 380 |  | 
 | 381 |                     c[0] = rgb565SepTo888(r0, g0, b0); | 
 | 382 |                     c[1] = rgb565SepTo888(r1, g1, b1); | 
 | 383 |                     c[2] = rgb565SepTo888(r2, g2, b2); | 
 | 384 |                     c[3] = rgb565SepTo888(r3, g3, b3); | 
 | 385 |                 } else { | 
 | 386 |                     // Convert to 8 bits | 
 | 387 |                     c[0] = rgb565To888(color0); | 
 | 388 |                     c[1] = rgb565To888(color1); | 
 | 389 |                 } | 
 | 390 |             } | 
 | 391 |  | 
 | 392 |             uint32_t* blockRowPtr = blockPtr; | 
 | 393 |             for (int y = 0; y < 4; y++, blockRowPtr += stride) { | 
 | 394 |                 // Don't process rows past the botom | 
 | 395 |                 if (base_y + y >= height) { | 
 | 396 |                     break; | 
 | 397 |                 } | 
 | 398 |                  | 
 | 399 |                 int w = min(width - base_x, 4); | 
 | 400 |                 for (int x = 0; x < w; x++) { | 
 | 401 |                     int a = alpha & 0xf; | 
 | 402 |                     alpha >>= 4; | 
 | 403 |  | 
 | 404 |                     int code = bits & 0x3; | 
 | 405 |                     bits >>= 2; | 
 | 406 |  | 
 | 407 |                     blockRowPtr[x] = c[code] | (a << 28) | (a << 24); | 
 | 408 |                 } | 
 | 409 |             } | 
 | 410 |         } | 
 | 411 |     } | 
 | 412 | } | 
 | 413 |  | 
 | 414 | // Output data as internalformat=GL_RGBA, type=GL_UNSIGNED_BYTE | 
 | 415 | static void | 
 | 416 | decodeDXT5(const GLvoid *data, int width, int height, | 
 | 417 |            void *surface, int stride) | 
 | 418 |  | 
 | 419 | { | 
 | 420 |     init_tables(); | 
 | 421 |      | 
 | 422 |     uint32_t const *d32 = (uint32_t *)data; | 
 | 423 |      | 
 | 424 |     // Specified alphas from the previous block | 
 | 425 |     uint8_t prev_alpha0 = 0x00; | 
 | 426 |     uint8_t prev_alpha1 = 0x00; | 
 | 427 |  | 
 | 428 |     // Specified colors from the previous block | 
 | 429 |     uint16_t prev_color0 = 0x0000; | 
 | 430 |      uint16_t prev_color1 = 0x0000; | 
 | 431 |  | 
 | 432 |     // Alpha table for the current block | 
 | 433 |     uint8_t a[8]; | 
 | 434 |     a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = a[6] = a[7] = 0; | 
 | 435 |  | 
 | 436 |     // Color table for the current block | 
 | 437 |     uint32_t c[4]; | 
 | 438 |     c[0] = c[1] = c[2] = c[3] = 0; | 
 | 439 |  | 
 | 440 |     int good_a5 = 0; | 
 | 441 |     int bad_a5 = 0; | 
 | 442 |     int good_a6 = 0; | 
 | 443 |     int bad_a6 = 0; | 
 | 444 |     int good_a7 = 0; | 
 | 445 |     int bad_a7 = 0; | 
 | 446 |  | 
 | 447 |     uint32_t* rowPtr = (uint32_t*)surface; | 
 | 448 |     for (int base_y = 0; base_y < height; base_y += 4, rowPtr += 4*stride) { | 
 | 449 |         uint32_t *blockPtr = rowPtr; | 
 | 450 |         for (int base_x = 0; base_x < width; base_x += 4, blockPtr += 4) { | 
 | 451 |              | 
 | 452 | #if __BYTE_ORDER == __BIG_ENDIAN | 
 | 453 |             uint32_t alphahi = *d32++; | 
 | 454 |             uint32_t alphalo = *d32++; | 
 | 455 |             alphahi = swap(alphahi); | 
 | 456 |             alphalo = swap(alphalo); | 
 | 457 | #else | 
 | 458 |              uint32_t alphalo = *d32++; | 
 | 459 |              uint32_t alphahi = *d32++; | 
 | 460 | #endif | 
 | 461 |  | 
 | 462 |             uint32_t colors = *d32++; | 
 | 463 |             uint32_t bits = *d32++; | 
 | 464 |              | 
 | 465 | #if __BYTE_ORDER == __BIG_ENDIANx | 
 | 466 |             colors = swap(colors); | 
 | 467 |             bits = swap(bits); | 
 | 468 | #endif | 
 | 469 |              | 
 | 470 |             uint64_t alpha = ((uint64_t)alphahi << 32) | alphalo; | 
 | 471 |             uint64_t alpha0 = alpha & 0xff; | 
 | 472 |             alpha >>= 8; | 
 | 473 |             uint64_t alpha1 = alpha & 0xff; | 
 | 474 |             alpha >>= 8; | 
 | 475 |  | 
 | 476 |             if (alpha0 != prev_alpha0 || alpha1 != prev_alpha1) { | 
 | 477 |                 prev_alpha0 = alpha0; | 
 | 478 |                 prev_alpha1 = alpha1; | 
 | 479 |                  | 
 | 480 |                 a[0] = alpha0; | 
 | 481 |                 a[1] = alpha1; | 
 | 482 |                 int a01 = alpha0 + alpha1 - 1; | 
 | 483 |                 if (alpha0 > alpha1) { | 
 | 484 |                     a[2] = div7(6*alpha0 +   alpha1); | 
 | 485 |                     a[4] = div7(4*alpha0 + 3*alpha1); | 
 | 486 |                     a[6] = div7(2*alpha0 + 5*alpha1); | 
 | 487 |  | 
 | 488 |                     // Use symmetry to derive half of the values | 
 | 489 |                     // A few values will be off by 1 (~.5%) | 
 | 490 |                     // Alternate which values are computed directly | 
 | 491 |                     // and which are derived to try to reduce bias | 
 | 492 |                     a[3] = a01 - a[6]; | 
 | 493 |                     a[5] = a01 - a[4]; | 
 | 494 |                     a[7] = a01 - a[2]; | 
 | 495 |                 } else { | 
 | 496 |                     a[2] = div5(4*alpha0 +   alpha1); | 
 | 497 |                     a[4] = div5(2*alpha0 + 3*alpha1); | 
 | 498 |                     a[3] = a01 - a[4]; | 
 | 499 |                     a[5] = a01 - a[2]; | 
 | 500 |                     a[6] = 0x00; | 
 | 501 |                     a[7] = 0xff; | 
 | 502 |                 } | 
 | 503 |             } | 
 | 504 |  | 
 | 505 |             // Raw colors | 
 | 506 |             uint16_t color0 = colors & 0xffff; | 
 | 507 |             uint16_t color1 = colors >> 16; | 
 | 508 |  | 
 | 509 |             // If the new block has the same base colors as the | 
 | 510 |             // previous one, we don't need to recompute the color | 
 | 511 |             // table c[] | 
 | 512 |             if (color0 != prev_color0 || color1 != prev_color1) { | 
 | 513 |                 // Store raw colors for comparison with next block | 
 | 514 |                 prev_color0 = color0; | 
 | 515 |                 prev_color1 = color1; | 
 | 516 |                  | 
 | 517 |                 int bbits = bits >> 1; | 
 | 518 |                 bool has2 = ((bbits & ~bits) & 0x55555555) != 0; | 
 | 519 |                 bool has3 = ((bbits &  bits) & 0x55555555) != 0; | 
 | 520 |                  | 
 | 521 |                 if (has2 || has3) { | 
 | 522 |                     int r0 =   red(color0); | 
 | 523 |                     int g0 = green(color0); | 
 | 524 |                     int b0 =  blue(color0); | 
 | 525 |                      | 
 | 526 |                     int r1 =   red(color1); | 
 | 527 |                     int g1 = green(color1); | 
 | 528 |                     int b1 =  blue(color1); | 
 | 529 |                  | 
 | 530 |                     int r2 = avg23(r0, r1); | 
 | 531 |                     int g2 = avg23(g0, g1); | 
 | 532 |                     int b2 = avg23(b0, b1); | 
 | 533 |                      | 
 | 534 |                     int r3 = avg23(r1, r0); | 
 | 535 |                     int g3 = avg23(g1, g0); | 
 | 536 |                     int b3 = avg23(b1, b0); | 
 | 537 |  | 
 | 538 |                     c[0] = rgb565SepTo888(r0, g0, b0); | 
 | 539 |                     c[1] = rgb565SepTo888(r1, g1, b1); | 
 | 540 |                     c[2] = rgb565SepTo888(r2, g2, b2); | 
 | 541 |                     c[3] = rgb565SepTo888(r3, g3, b3); | 
 | 542 |                 } else { | 
 | 543 |                     // Convert to 8 bits | 
 | 544 |                     c[0] = rgb565To888(color0); | 
 | 545 |                     c[1] = rgb565To888(color1); | 
 | 546 |                 }                 | 
 | 547 |             } | 
 | 548 |  | 
 | 549 |             uint32_t* blockRowPtr = blockPtr; | 
 | 550 |             for (int y = 0; y < 4; y++, blockRowPtr += stride) { | 
 | 551 |                 // Don't process rows past the botom | 
 | 552 |                 if (base_y + y >= height) { | 
 | 553 |                     break; | 
 | 554 |                 } | 
 | 555 |                  | 
 | 556 |                 int w = min(width - base_x, 4); | 
 | 557 |                 for (int x = 0; x < w; x++) { | 
 | 558 |                     int acode = alpha & 0x7; | 
 | 559 |                     alpha >>= 3; | 
 | 560 |  | 
 | 561 |                     int code = bits & 0x3; | 
 | 562 |                     bits >>= 2; | 
 | 563 |  | 
 | 564 |                     blockRowPtr[x] = c[code] | (a[acode] << 24); | 
 | 565 |                 } | 
 | 566 |             } | 
 | 567 |         } | 
 | 568 |     } | 
 | 569 | } | 
 | 570 |     | 
 | 571 | /* | 
 | 572 |  * Decode a DXT-compressed texture into memory.  DXT textures consist of | 
 | 573 |  * a series of 4x4 pixel blocks in left-to-right, top-down order. | 
 | 574 |  * The number of blocks is given by ceil(width/4)*ceil(height/4). | 
 | 575 |  * | 
 | 576 |  * 'data' points to the texture data. 'width' and 'height' indicate the | 
 | 577 |  * dimensions of the texture.  We assume width and height are >= 0 but | 
 | 578 |  * do not require them to be powers of 2 or divisible by any factor. | 
 | 579 |  * | 
 | 580 |  * The output is written to 'surface' with each scanline separated by | 
 | 581 |  * 'stride' 2- or 4-byte words. | 
 | 582 |  * | 
 | 583 |  * 'format' indicates the type of compression and must be one of the following: | 
 | 584 |  * | 
 | 585 |  *   GL_COMPRESSED_RGB_S3TC_DXT1_EXT: | 
 | 586 |  *      The output is written as 5/6/5 opaque RGB (16 bit words). | 
 | 587 |  *      8 bytes are read from 'data' for each block. | 
 | 588 |  * | 
 | 589 |  *   GL_COMPRESSED_RGBA_S3TC_DXT1_EXT | 
 | 590 |  *      The output is written as 5/5/5/1 RGBA (16 bit words) | 
 | 591 |  *      8 bytes are read from 'data' for each block. | 
 | 592 |  * | 
 | 593 |  *   GL_COMPRESSED_RGBA_S3TC_DXT3_EXT | 
 | 594 |  *   GL_COMPRESSED_RGBA_S3TC_DXT5_EXT | 
 | 595 |  *      The output is written as 8/8/8/8 ARGB (32 bit words) | 
 | 596 |  *      16 bytes are read from 'data' for each block. | 
 | 597 |  */ | 
 | 598 | void | 
 | 599 | decodeDXT(const GLvoid *data, int width, int height, | 
 | 600 |           void *surface, int stride, int format) | 
 | 601 | { | 
 | 602 | #if TIMING | 
 | 603 |     struct timeval start_t, end_t; | 
 | 604 |     struct timezone tz; | 
 | 605 |      | 
 | 606 |     gettimeofday(&start_t, &tz); | 
 | 607 | #endif | 
 | 608 |  | 
 | 609 |     switch (format) { | 
 | 610 |     case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: | 
 | 611 |         decodeDXT1(data, width, height, surface, stride, false); | 
 | 612 |         break; | 
 | 613 |          | 
 | 614 |     case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: | 
 | 615 |         decodeDXT1(data, width, height, surface, stride, true); | 
 | 616 |         break; | 
 | 617 |          | 
 | 618 |     case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: | 
 | 619 |         decodeDXT3(data, width, height, surface, stride); | 
 | 620 |         break; | 
 | 621 |          | 
 | 622 |     case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: | 
 | 623 |         decodeDXT5(data, width, height, surface, stride); | 
 | 624 |         break; | 
 | 625 |     } | 
 | 626 |      | 
 | 627 | #if TIMING | 
 | 628 |     gettimeofday(&end_t, &tz); | 
 | 629 |     long usec = (end_t.tv_sec - start_t.tv_sec)*1000000 + | 
 | 630 |         (end_t.tv_usec - start_t.tv_usec); | 
 | 631 |      | 
 | 632 |     printf("Loaded w=%d h=%d in %ld usec\n", width, height, usec); | 
 | 633 | #endif | 
 | 634 | } | 
 | 635 |  | 
 | 636 | } // namespace android |