summaryrefslogtreecommitdiff
path: root/src/static_libs/rg_etc
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2014-05-30 15:26:07 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2014-06-10 14:58:28 +0900
commit173b6bebf9dc079f96d1e434e5506a7d98ec6011 (patch)
tree1e51bc25b1b7c1b2fce1a33894697cf26103f06b /src/static_libs/rg_etc
parent22c5632256bc15b0cc216849d436c6e5770e88e5 (diff)
Evas ETC2: Implement H mode encoding
And we gain some more decibels of PSNR :) @feature
Diffstat (limited to 'src/static_libs/rg_etc')
-rw-r--r--src/static_libs/rg_etc/etc2_encoder.c208
1 files changed, 161 insertions, 47 deletions
diff --git a/src/static_libs/rg_etc/etc2_encoder.c b/src/static_libs/rg_etc/etc2_encoder.c
index 8f3072484c..042667f187 100644
--- a/src/static_libs/rg_etc/etc2_encoder.c
+++ b/src/static_libs/rg_etc/etc2_encoder.c
@@ -87,12 +87,6 @@ static const int kBlockWalk[16] = {
87#define BIT(byteval, bit) \ 87#define BIT(byteval, bit) \
88 (((byteval) >> (bit)) & 0x1) 88 (((byteval) >> (bit)) & 0x1)
89 89
90// Clamps only if value is > 255
91#define CLAMPDOWN(a) ({ int _z = (a); ((_z <= 255) ? _z : 255); })
92
93// Clamps only if value is < 0
94#define CLAMPUP(a) ({ int _z = (a); ((_z >= 0) ? _z : 0); })
95
96// Real clamp 90// Real clamp
97#define CLAMP(a) ({ int _b = (a); (((_b) >= 0) ? (((_b) < 256) ? (_b) : 255) : 0); }) 91#define CLAMP(a) ({ int _b = (a); (((_b) >= 0) ? (((_b) < 256) ? (_b) : 255) : 0); })
98 92
@@ -336,6 +330,93 @@ _etc2_t_mode_header_pack(uint8_t *etc2,
336 return EINA_TRUE; 330 return EINA_TRUE;
337} 331}
338 332
333static Eina_Bool
334_etc2_h_mode_header_pack(uint8_t *etc2, Eina_Bool *swap_colors,
335 uint32_t color1, uint32_t color2, int distance)
336{
337 int distanceIdx, R, dR, G, dG, distanceSpecialBit, da, db;
338 int r1_4, g1_4, b1_4, r2_4, g2_4, b2_4;
339 uint32_t c1, c2;
340
341 for (distanceIdx = 0; distanceIdx < 8; distanceIdx++)
342 if (kDistances[distanceIdx] == distance) break;
343
344 if (distanceIdx >= 8)
345 return EINA_FALSE;
346
347 // The distance is coded in 3 bits. But in H mode, one bit is not coded
348 // in the header, as we use the comparison result between the two colors
349 // to select it.
350 distanceSpecialBit = BIT(distanceIdx, 0);
351 db = BIT(distanceIdx, 1);
352 da = BIT(distanceIdx, 2);
353
354 // Note: if c1 == c2, no big deal because H is not the best choice of mode
355 if (distanceSpecialBit)
356 {
357 c1 = MAX(color1, color2);
358 c2 = MIN(color1, color2);
359 }
360 else
361 {
362 c1 = MIN(color1, color2);
363 c2 = MAX(color1, color2);
364 }
365
366 // Return flag so we use the proper colors when packing the block
367 *swap_colors = (c1 != color1);
368
369 // 4 bit colors
370 r1_4 = R_VAL(&c1) >> 4;
371 g1_4 = G_VAL(&c1) >> 4;
372 b1_4 = B_VAL(&c1) >> 4;
373 r2_4 = R_VAL(&c2) >> 4;
374 g2_4 = G_VAL(&c2) >> 4;
375 b2_4 = B_VAL(&c2) >> 4;
376
377 // R1 + G1a. R + [dR] must be inside [0..31]. Scanning all values. Not smart.
378 R = r1_4;
379 dR = g1_4 >> 1;
380 if ((R + kSigned3bit[dR]) < 0 || (R + kSigned3bit[dR] > 31))
381 R |= (1 << 4);
382
383 if ((R + kSigned3bit[dR]) < 0 || (R + kSigned3bit[dR] > 31))
384 return EINA_FALSE; // wtf?
385
386 etc2[0] = ((R & 0x1F) << 3) | (dR & 0x7);
387
388 // G1b + B1a + B1b[2 msb]. G + dG must be outside the range.
389 G = (g1_4 & 0x1) << 1;
390 G |= BIT(b1_4, 3);
391 dG = BITS(b1_4, 1, 2);
392 for (int Gx = 0; Gx < 8; Gx++)
393 for (int dGx = 0; dGx < 2; dGx++)
394 {
395 int Gtry = G | (Gx << 2);
396 int dGtry = dG | (dGx << 2);
397 if ((Gtry + kSigned3bit[dGtry]) < 0 || (Gtry + kSigned3bit[dGtry] > 31))
398 {
399 G = Gtry;
400 dG = dGtry;
401 break;
402 }
403 }
404
405 if ((G + kSigned3bit[dG]) >= 0 && (G + kSigned3bit[dG] <= 31))
406 return EINA_FALSE; // wtf?
407
408 etc2[1] = ((G & 0x1F) << 3) | (dG & 0x7);
409
410 // B1[lsb] + R2 + G2 [3 msb]
411 etc2[2] = ((b1_4 & 0x1) << 7) | (r2_4 << 3) | (g2_4 >> 1);
412
413 // G2[lsb] + B2 + distance
414 etc2[3] = ((g2_4 & 0x1) << 7) | (b2_4 << 3)
415 | (da << 2) | 0x2 | db;
416
417 return EINA_TRUE;
418}
419
339static inline int 420static inline int
340_rgb_distance_percept(uint32_t color1, uint32_t color2) 421_rgb_distance_percept(uint32_t color1, uint32_t color2)
341{ 422{
@@ -355,24 +436,53 @@ _rgb_distance_euclid(uint32_t color1, uint32_t color2)
355} 436}
356 437
357static unsigned int 438static unsigned int
358_etc2_t_mode_block_pack(uint8_t *etc2, 439_etc2_th_mode_block_pack(uint8_t *etc2, Eina_Bool h_mode,
359 uint32_t color1, uint32_t color2, int distance, 440 uint32_t color1, uint32_t color2, int distance,
360 const uint32_t *bgra, Eina_Bool write) 441 const uint32_t *bgra, Eina_Bool write,
442 Eina_Bool *swap_colors)
361{ 443{
362 uint8_t paint_colors[4][4]; 444 uint8_t paint_colors[4][4];
363 int errAcc = 0; 445 int errAcc = 0;
364 446
365 for (int k = 0; k < 4; k++) 447 if (write)
366 { 448 {
367 // Note: We don't really care about alpha... 449 memset(etc2 + 4, 0, 4);
368 paint_colors[0][k] = ((uint8_t *) &color1)[k]; 450 if (!h_mode)
369 paint_colors[1][k] = CLAMPDOWN(((uint8_t *) &color2)[k] + distance); 451 {
370 paint_colors[2][k] = ((uint8_t *) &color2)[k]; 452 if (!_etc2_t_mode_header_pack(etc2, color1, color2, distance))
371 paint_colors[3][k] = CLAMPUP(((uint8_t *) &color2)[k] - distance); 453 return INT_MAX; // assert
454 }
455 else
456 {
457 if (!_etc2_h_mode_header_pack(etc2, swap_colors,
458 color1, color2, distance))
459 return INT_MAX; // assert
460 if (*swap_colors)
461 {
462 uint32_t tmp = color1;
463 color1 = color2;
464 color2 = tmp;
465 }
466 }
372 } 467 }
373 468
374 if (write) 469 for (int k = 0; k < 4; k++)
375 memset(etc2 + 4, 0, 4); 470 {
471 if (!h_mode)
472 {
473 paint_colors[0][k] = ((uint8_t *) &color1)[k];
474 paint_colors[1][k] = CLAMP(((uint8_t *) &color2)[k] + distance);
475 paint_colors[2][k] = ((uint8_t *) &color2)[k];
476 paint_colors[3][k] = CLAMP(((uint8_t *) &color2)[k] - distance);
477 }
478 else
479 {
480 paint_colors[0][k] = CLAMP(((uint8_t *) &color1)[k] + distance);
481 paint_colors[1][k] = CLAMP(((uint8_t *) &color1)[k] - distance);
482 paint_colors[2][k] = CLAMP(((uint8_t *) &color2)[k] + distance);
483 paint_colors[3][k] = CLAMP(((uint8_t *) &color2)[k] - distance);
484 }
485 }
376 486
377 for (int k = 0; k < 16; k++) 487 for (int k = 0; k < 16; k++)
378 { 488 {
@@ -400,12 +510,6 @@ _etc2_t_mode_block_pack(uint8_t *etc2,
400 } 510 }
401 } 511 }
402 512
403 if (write)
404 {
405 if (!_etc2_t_mode_header_pack(etc2, color1, color2, distance))
406 return INT_MAX; // assert
407 }
408
409 return errAcc; 513 return errAcc;
410} 514}
411 515
@@ -547,12 +651,13 @@ found:
547} 651}
548 652
549static unsigned int 653static unsigned int
550_etc2_t_mode_block_encode(uint8_t *etc2, const uint32_t *bgra, 654_etc2_th_mode_block_encode(uint8_t *etc2, const uint32_t *bgra,
551 const rg_etc1_pack_params *params) 655 const rg_etc1_pack_params *params)
552{ 656{
553 int err, bestDist = kDistances[0]; 657 int err, bestDist = kDistances[0];
554 int minErr = INT_MAX; 658 int minErr = INT_MAX, bestMode = 0;
555 uint32_t c1, c2, bestC1 = bgra[0], bestC2 = bgra[1]; 659 uint32_t c1, c2, bestC1 = bgra[0], bestC2 = bgra[1];
660 Eina_Bool swap_colors = EINA_FALSE;
556 661
557 Eina_Inlist *tried_pairs = NULL; 662 Eina_Inlist *tried_pairs = NULL;
558 struct ColorPair { 663 struct ColorPair {
@@ -609,23 +714,31 @@ _etc2_t_mode_block_encode(uint8_t *etc2, const uint32_t *bgra,
609 714
610 for (int distIdx = 0; distIdx < 8; distIdx++) 715 for (int distIdx = 0; distIdx < 8; distIdx++)
611 { 716 {
612 for (int swap = 0; swap < 2; swap++) 717 for (int mode = 0; mode < 2; mode++)
613 { 718 {
614 if (swap) 719
615 { 720 for (int swap = 0; swap < 2; swap++)
616 uint32_t tmp = c2;
617 c2 = c1;
618 c1 = tmp;
619 }
620 err = _etc2_t_mode_block_pack(etc2, c1, c2, kDistances[distIdx], bgra, EINA_FALSE);
621 if (err < minErr)
622 { 721 {
623 bestDist = kDistances[distIdx]; 722 if (mode == 0 && swap)
624 minErr = err; 723 {
625 bestC1 = c1; 724 uint32_t tmp = c2;
626 bestC2 = c2; 725 c2 = c1;
627 if (err <= kTargetError[params->m_quality]) 726 c1 = tmp;
628 goto found; 727 }
728 err = _etc2_th_mode_block_pack(etc2, mode, c1, c2,
729 kDistances[distIdx],
730 bgra, EINA_FALSE,
731 &swap_colors);
732 if (err < minErr)
733 {
734 bestDist = kDistances[distIdx];
735 minErr = err;
736 bestC1 = (!swap_colors) ? c1 : c2;
737 bestC2 = (!swap_colors) ? c2 : c1;
738 bestMode = mode;
739 if (err <= kTargetError[params->m_quality])
740 goto found;
741 }
629 } 742 }
630 } 743 }
631 } 744 }
@@ -638,7 +751,8 @@ found:
638 free(pair); 751 free(pair);
639 } 752 }
640 753
641 err = _etc2_t_mode_block_pack(etc2, bestC1, bestC2, bestDist, bgra, EINA_TRUE); 754 err = _etc2_th_mode_block_pack(etc2, bestMode, bestC1, bestC2, bestDist,
755 bgra, EINA_TRUE, &swap_colors);
642 756
643 return err; 757 return err;
644} 758}
@@ -673,8 +787,8 @@ etc2_rgba8_block_pack(unsigned char *etc2, const unsigned int *bgra,
673 787
674 // TODO: H mode, Planar mode 788 // TODO: H mode, Planar mode
675 789
676 errors[0] = rg_etc1_pack_block(etc2_try[0], bgra, &safe_params); // 36.63dB 790 errors[0] = rg_etc1_pack_block(etc2_try[0], bgra, &safe_params);
677 errors[1] = _etc2_t_mode_block_encode(etc2_try[1], bgra, &safe_params); // 36.69dB (+0.6dB) 791 errors[1] = _etc2_th_mode_block_encode(etc2_try[1], bgra, &safe_params);
678 792
679#ifdef DEBUG 793#ifdef DEBUG
680 if (errors[1] < INT_MAX) 794 if (errors[1] < INT_MAX)
@@ -688,8 +802,8 @@ etc2_rgba8_block_pack(unsigned char *etc2, const unsigned int *bgra,
688 802
689 if (real_errors[0] != errors[1]) 803 if (real_errors[0] != errors[1])
690 { 804 {
691 DBG("Invalid error calc in T mode"); 805 DBG("Invalid error calc in T or H mode");
692 errors[1] = real_errors[0]; 806 //errors[1] = real_errors[0];
693 } 807 }
694 } 808 }
695#endif 809#endif
@@ -723,7 +837,7 @@ etc2_rgb8_block_pack(unsigned char *etc2, const unsigned int *bgra,
723 // TODO: Planar mode 837 // TODO: Planar mode
724 838
725 errors[0] = rg_etc1_pack_block(etc2_try[0], bgra, &safe_params); 839 errors[0] = rg_etc1_pack_block(etc2_try[0], bgra, &safe_params);
726 errors[1] = _etc2_t_mode_block_encode(etc2_try[1], bgra, &safe_params); 840 errors[1] = _etc2_th_mode_block_encode(etc2_try[1], bgra, &safe_params);
727 841
728 for (unsigned k = 0; k < sizeof(errors) / sizeof(*errors); k++) 842 for (unsigned k = 0; k < sizeof(errors) / sizeof(*errors); k++)
729 if (errors[k] < minErr) 843 if (errors[k] < minErr)