| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522 |
- /*
- Copyright (c) 2015 Harm Hanemaaijer <[email protected]>
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
- enum
- {
- BPTC_MODE_ALLOWED_ALL =0xFF,
- MODES_ALLOWED_OPAQUE_ONLY =0x100,
- MODES_ALLOWED_NON_OPAQUE_ONLY =0x200,
- MODES_ALLOWED_PUNCHTHROUGH_ONLY =0x400,
- BPTC_FLOAT_MODE_ALLOWED_ALL =0x3FFF,
- TWO_COLORS =0x20000,
- };
- static unsigned int pack_r(int r) {return (unsigned int)r;}
- static unsigned int pack_g(int g) {return (unsigned int)g << 8;}
- static unsigned int pack_b(int b) {return (unsigned int)b << 16;}
- static unsigned int pack_a(int a) {return (unsigned int)a << 24;}
- #ifndef TGP_SHARED_FUNCTIONS // needed for Android compilation
- #define TGP_SHARED_FUNCTIONS
- static unsigned int pack_rgba(int r, int g, int b, int a) {return (unsigned int)r | ((unsigned int)g << 8) | ((unsigned int)b << 16) | ((unsigned int)a << 24);}
- #endif
- static uint64_t pack_r16(unsigned int r16) {return r16;}
- static uint64_t pack_g16(unsigned int g16) {return g16 << 16;}
- static uint64_t pack_b16(unsigned int b16) {return (uint64_t)b16 << 32;}
- static uint64_t pack_a16(unsigned int a16) {return (uint64_t)a16 << 48;}
- static uint64_t pack_rgb16(uint16_t r16, uint16_t g16, uint16_t b16) {return (uint64_t)r16 | ((uint64_t)g16 << 16) | ((uint64_t)b16 << 32);}
- static uint64_t pack_rgba16(uint16_t r16, uint16_t g16, uint16_t b16, uint16_t a16) {return (uint64_t)r16 | ((uint64_t)g16 << 16) | ((uint64_t)b16 << 32) | ((uint64_t)a16 << 48);}
- static int pixel_get_r(unsigned int pixel) {return pixel & 0xFF;}
- static int pixel_get_g(unsigned int pixel) {return (pixel & 0xFF00) >> 8;}
- static int pixel_get_b(unsigned int pixel) {return (pixel & 0xFF0000) >> 16;}
- static int pixel_get_a(unsigned int pixel) {return (pixel & 0xFF000000) >> 24;}
- /*#include <stdlib.h>
- #include <stdio.h>
- #include <stdint.h>
- #include "texgenpack.h"
- #include "decode.h"
- #include "packing.h"*/
- // Functions for BPTC/BC7/BC6H decompression.
- static const unsigned char table_P2[64 * 16] = {
- 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,
- 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,
- 0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,
- 0,0,0,1,0,0,1,1,0,0,1,1,0,1,1,1,
- 0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,1,
- 0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,1,
- 0,0,0,1,0,0,1,1,0,1,1,1,1,1,1,1,
- 0,0,0,0,0,0,0,1,0,0,1,1,0,1,1,1,
- 0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,
- 0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,
- 0,0,0,0,0,0,0,1,0,1,1,1,1,1,1,1,
- 0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,
- 0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,
- 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,
- 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,
- 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,
- 0,0,0,0,1,0,0,0,1,1,1,0,1,1,1,1,
- 0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0,
- 0,1,1,1,0,0,1,1,0,0,0,1,0,0,0,0,
- 0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,
- 0,0,0,0,1,0,0,0,1,1,0,0,1,1,1,0,
- 0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,
- 0,1,1,1,0,0,1,1,0,0,1,1,0,0,0,1,
- 0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,0,
- 0,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,
- 0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,
- 0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,
- 0,0,0,1,0,1,1,1,1,1,1,0,1,0,0,0,
- 0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,
- 0,1,1,1,0,0,0,1,1,0,0,0,1,1,1,0,
- 0,0,1,1,1,0,0,1,1,0,0,1,1,1,0,0,
- 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,
- 0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,
- 0,1,0,1,1,0,1,0,0,1,0,1,1,0,1,0,
- 0,0,1,1,0,0,1,1,1,1,0,0,1,1,0,0,
- 0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,
- 0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,
- 0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,
- 0,1,0,1,1,0,1,0,1,0,1,0,0,1,0,1,
- 0,1,1,1,0,0,1,1,1,1,0,0,1,1,1,0,
- 0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0,
- 0,0,1,1,0,0,1,0,0,1,0,0,1,1,0,0,
- 0,0,1,1,1,0,1,1,1,1,0,1,1,1,0,0,
- 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
- 0,0,1,1,1,1,0,0,1,1,0,0,0,0,1,1,
- 0,1,1,0,0,1,1,0,1,0,0,1,1,0,0,1,
- 0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,
- 0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0,
- 0,0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,
- 0,0,0,0,0,0,1,0,0,1,1,1,0,0,1,0,
- 0,0,0,0,0,1,0,0,1,1,1,0,0,1,0,0,
- 0,1,1,0,1,1,0,0,1,0,0,1,0,0,1,1,
- 0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,1,
- 0,1,1,0,0,0,1,1,1,0,0,1,1,1,0,0,
- 0,0,1,1,1,0,0,1,1,1,0,0,0,1,1,0,
- 0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,1,
- 0,1,1,0,0,0,1,1,0,0,1,1,1,0,0,1,
- 0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,1,
- 0,0,0,1,1,0,0,0,1,1,1,0,0,1,1,1,
- 0,0,0,0,1,1,1,1,0,0,1,1,0,0,1,1,
- 0,0,1,1,0,0,1,1,1,1,1,1,0,0,0,0,
- 0,0,1,0,0,0,1,0,1,1,1,0,1,1,1,0,
- 0,1,0,0,0,1,0,0,0,1,1,1,0,1,1,1
- };
- static const unsigned char table_P3[64 * 16] = {
- 0,0,1,1,0,0,1,1,0,2,2,1,2,2,2,2,
- 0,0,0,1,0,0,1,1,2,2,1,1,2,2,2,1,
- 0,0,0,0,2,0,0,1,2,2,1,1,2,2,1,1,
- 0,2,2,2,0,0,2,2,0,0,1,1,0,1,1,1,
- 0,0,0,0,0,0,0,0,1,1,2,2,1,1,2,2,
- 0,0,1,1,0,0,1,1,0,0,2,2,0,0,2,2,
- 0,0,2,2,0,0,2,2,1,1,1,1,1,1,1,1,
- 0,0,1,1,0,0,1,1,2,2,1,1,2,2,1,1,
- 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,
- 0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,
- 0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,
- 0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,
- 0,1,1,2,0,1,1,2,0,1,1,2,0,1,1,2,
- 0,1,2,2,0,1,2,2,0,1,2,2,0,1,2,2,
- 0,0,1,1,0,1,1,2,1,1,2,2,1,2,2,2,
- 0,0,1,1,2,0,0,1,2,2,0,0,2,2,2,0,
- 0,0,0,1,0,0,1,1,0,1,1,2,1,1,2,2,
- 0,1,1,1,0,0,1,1,2,0,0,1,2,2,0,0,
- 0,0,0,0,1,1,2,2,1,1,2,2,1,1,2,2,
- 0,0,2,2,0,0,2,2,0,0,2,2,1,1,1,1,
- 0,1,1,1,0,1,1,1,0,2,2,2,0,2,2,2,
- 0,0,0,1,0,0,0,1,2,2,2,1,2,2,2,1,
- 0,0,0,0,0,0,1,1,0,1,2,2,0,1,2,2,
- 0,0,0,0,1,1,0,0,2,2,1,0,2,2,1,0,
- 0,1,2,2,0,1,2,2,0,0,1,1,0,0,0,0,
- 0,0,1,2,0,0,1,2,1,1,2,2,2,2,2,2,
- 0,1,1,0,1,2,2,1,1,2,2,1,0,1,1,0,
- 0,0,0,0,0,1,1,0,1,2,2,1,1,2,2,1,
- 0,0,2,2,1,1,0,2,1,1,0,2,0,0,2,2,
- 0,1,1,0,0,1,1,0,2,0,0,2,2,2,2,2,
- 0,0,1,1,0,1,2,2,0,1,2,2,0,0,1,1,
- 0,0,0,0,2,0,0,0,2,2,1,1,2,2,2,1,
- 0,0,0,0,0,0,0,2,1,1,2,2,1,2,2,2,
- 0,2,2,2,0,0,2,2,0,0,1,2,0,0,1,1,
- 0,0,1,1,0,0,1,2,0,0,2,2,0,2,2,2,
- 0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0,
- 0,0,0,0,1,1,1,1,2,2,2,2,0,0,0,0,
- 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,
- 0,1,2,0,2,0,1,2,1,2,0,1,0,1,2,0,
- 0,0,1,1,2,2,0,0,1,1,2,2,0,0,1,1,
- 0,0,1,1,1,1,2,2,2,2,0,0,0,0,1,1,
- 0,1,0,1,0,1,0,1,2,2,2,2,2,2,2,2,
- 0,0,0,0,0,0,0,0,2,1,2,1,2,1,2,1,
- 0,0,2,2,1,1,2,2,0,0,2,2,1,1,2,2,
- 0,0,2,2,0,0,1,1,0,0,2,2,0,0,1,1,
- 0,2,2,0,1,2,2,1,0,2,2,0,1,2,2,1,
- 0,1,0,1,2,2,2,2,2,2,2,2,0,1,0,1,
- 0,0,0,0,2,1,2,1,2,1,2,1,2,1,2,1,
- 0,1,0,1,0,1,0,1,0,1,0,1,2,2,2,2,
- 0,2,2,2,0,1,1,1,0,2,2,2,0,1,1,1,
- 0,0,0,2,1,1,1,2,0,0,0,2,1,1,1,2,
- 0,0,0,0,2,1,1,2,2,1,1,2,2,1,1,2,
- 0,2,2,2,0,1,1,1,0,1,1,1,0,2,2,2,
- 0,0,0,2,1,1,1,2,1,1,1,2,0,0,0,2,
- 0,1,1,0,0,1,1,0,0,1,1,0,2,2,2,2,
- 0,0,0,0,0,0,0,0,2,1,1,2,2,1,1,2,
- 0,1,1,0,0,1,1,0,2,2,2,2,2,2,2,2,
- 0,0,2,2,0,0,1,1,0,0,1,1,0,0,2,2,
- 0,0,2,2,1,1,2,2,1,1,2,2,0,0,2,2,
- 0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,2,
- 0,0,0,2,0,0,0,1,0,0,0,2,0,0,0,1,
- 0,2,2,2,1,2,2,2,0,2,2,2,1,2,2,2,
- 0,1,0,1,2,2,2,2,2,2,2,2,2,2,2,2,
- 0,1,1,1,2,0,1,1,2,2,0,1,2,2,2,0,
- };
- typedef struct {
- uint64_t data0;
- uint64_t data1;
- int index;
- } Block;
- static uint32_t block_extract_bits(Block *block, int nu_bits) {
- uint32_t value = 0;
- for (int i = 0; i < nu_bits; i++) {
- if (block->index < 64) {
- int shift = block->index - i;
- if (shift < 0)
- value |= (block->data0 & ((uint64_t)1 << block->index)) << (- shift);
- else
- value |= (block->data0 & ((uint64_t)1 << block->index)) >> shift;
- }
- else {
- int shift = ((block->index - 64) - i);
- if (shift < 0)
- value |= (block->data1 & ((uint64_t)1 << (block->index - 64))) << (- shift);
- else
- value |= (block->data1 & ((uint64_t)1 << (block->index - 64))) >> shift;
- }
- block->index++;
- }
- // if (block->index > 128)
- // printf("Block overflow (%d)\n", block->index);
- return value;
- }
- static inline uint32_t get_bits_uint64(uint64_t data, int bit0, int bit1) {return (data >> bit0) & ((1 << (bit1 - bit0 + 1)) - 1);} // ESENTHEL CHANGED
- static const unsigned char color_precision_table[8] = { 4, 6, 5, 7, 5, 7, 7, 5 };
- // Note: precision includes P-bits!
- static const unsigned char color_precision_plus_pbit_table[8] = { 5, 7, 5, 8, 5, 7, 8, 6 };
- static char color_component_precision(int mode) {
- return color_precision_table[mode];
- }
- static char color_component_precision_plus_pbit(int mode) {
- return color_precision_plus_pbit_table[mode];
- }
- static const unsigned char alpha_precision_table[8] = { 0, 0, 0, 0, 6, 8, 7, 5 };
- // Note: precision include P-bits!
- static const unsigned char alpha_precision_plus_pbit_table[8] = { 0, 0, 0, 0, 6, 8, 8, 6 };
- static char alpha_component_precision(int mode) {
- return alpha_precision_table[mode];
- }
- static char alpha_component_precision_plus_pbit(int mode) {
- return alpha_precision_plus_pbit_table[mode];
- }
- // #subsets = { 3, 2, 3, 2, 1, 1, 1, 2 };
- // partition bits = { 4, 6, 6, 6, 0, 0, 0, 6 };
- // rotation bits = { 0, 0, 0, 0, 2, 2, 0, 0 };
- // mode 4 has one index selection bit.
- //
- // #subsets color alpha part. index before color index after color index after alpha
- // Mode 0 3 4 0 1 + 4 = 5 5 + 6 * 3 * 4 = 77 77
- // Mode 1 Handled elsewhere.
- // Mode 2 3 5 0 3 + 6 = 9 9 + 6 * 3 * 5 = 99 99
- // Mode 3 2 7 0 4 + 6 = 10 10 + 4 * 3 * 7 = 94 94
- // Mode 4 1 5 6 5 + 2 + 1 = 8 8 + 2 * 3 * 5 = 38 37 + 2 * 6 = 50
- // Mode 5 1 7 8 6 + 2 = 8 8 + 2 * 3 * 7 = 50 50 + 2 * 8 = 66
- // Mode 6 1 7 7 7 7 + 2 * 3 * 7 = 49 49 + 2 * 7 = 63
- // Mode 7 2 5 5 8 + 6 = 14 14 + 4 * 3 * 5 = 74 74 + 4 * 5 = 94
- static const signed char components_in_qword0_table[8] = { 2, -1, 1, 1, 3, 3, 3, 2 };
- static void extract_endpoints(int mode, int nu_subsets, Block *block, uint8_t *endpoint_array) {
- #if 1
- // Optimized version avoiding the use of block_extract_bits()
- int components_in_qword0 = components_in_qword0_table[mode];
- uint64_t data = block->data0 >> block->index;
- uint8_t precision = color_component_precision(mode);
- uint8_t mask = (1 << precision) - 1;
- int total_bits_per_component = nu_subsets * 2 * precision;
- for (int i = 0; i < components_in_qword0; i++) // For each color component.
- for (int j = 0; j < nu_subsets; j++) // For each subset.
- for (int k = 0; k < 2; k++) { // For each endpoint.
- endpoint_array[j * 8 + k * 4 + i] = data & mask;
- data >>= precision;
- }
- block->index += components_in_qword0 * total_bits_per_component;
- if (components_in_qword0 < 3) {
- // Handle the color component that crosses the boundary between data0 and data1
- data = block->data0 >> block->index;
- data |= block->data1 << (64 - block->index);
- int i = components_in_qword0;
- for (int j = 0; j < nu_subsets; j++) // For each subset.
- for (int k = 0; k < 2; k++) { // For each endpoint.
- endpoint_array[j * 8 + k * 4 + i] = data & mask;
- data >>= precision;
- }
- block->index += total_bits_per_component;
- }
- if (components_in_qword0 < 2) {
- // Handle the color component that is wholly in data1.
- data = block->data1 >> (block->index - 64);
- int i = 2;
- for (int j = 0; j < nu_subsets; j++) // For each subset.
- for (int k = 0; k < 2; k++) { // For each endpoint.
- endpoint_array[j * 8 + k * 4 + i] = data & mask;
- data >>= precision;
- }
- block->index += total_bits_per_component;
- }
- // Alpha component.
- if (alpha_component_precision(mode) > 0) {
- // For mode 7, the alpha data is wholly in data1.
- // For modes 4 and 6, the alpha data is wholly in data0.
- // For mode 5, the alpha data is in data0 and data1.
- if (mode == 7)
- data = block->data1 >> (block->index - 64);
- else if (mode == 5)
- data = (block->data0 >> block->index) | ((block->data1 & 0x3) << 14);
- else
- data = block->data0 >> block->index;
- uint8_t alpha_precision = alpha_component_precision(mode);
- uint8_t mask = (1 << alpha_precision) - 1;
- for (int j = 0; j < nu_subsets; j++)
- for (int k = 0; k < 2; k++) { // For each endpoint.
- endpoint_array[j * 8 + k * 4 + 3] = data & mask;
- data >>= alpha_precision;
- }
- block->index += nu_subsets * 2 * alpha_precision;
- }
- #else
- // Color components.
- for (int i = 0; i < 3; i++) // For each color component.
- for (int j = 0; j < nu_subsets; j++) // For each subset.
- for (int k = 0; k < 2; k++) // For each endpoint.
- endpoint_array[j * 8 + k * 4 + i] =
- block_extract_bits(block, color_component_precision(mode));
- // Alpha component.
- if (alpha_component_precision(mode) > 0) {
- for (int j = 0; j < nu_subsets; j++)
- for (int k = 0; k < 2; k++) // For each endpoint.
- endpoint_array[j * 8 + k * 4 + 3] =
- block_extract_bits(block, alpha_component_precision(mode));
- }
- #endif
- }
- static const unsigned char mode_has_p_bits[8] = { 1, 1, 0, 1, 0, 0, 1, 1 };
- void fully_decode_endpoints(uint8_t *endpoint_array, int nu_subsets, int mode, Block *block) {
- if (mode_has_p_bits[mode]) {
- // Mode 1 handled elsewhere.
- // Extract end-point pbits.
- uint32_t bits;
- if (block->index < 64)
- {
- bits = block->data0 >> block->index;
- bits|= block->data1 << (64 - block->index); // ESENTHEL CHANGED
- }
- else
- bits = block->data1 >> (block->index - 64);
- for (int i = 0; i < nu_subsets * 2; i++) {
- endpoint_array[i * 4 + 0] <<= 1;
- endpoint_array[i * 4 + 1] <<= 1;
- endpoint_array[i * 4 + 2] <<= 1;
- endpoint_array[i * 4 + 3] <<= 1;
- endpoint_array[i * 4 + 0] |= (bits & 1);
- endpoint_array[i * 4 + 1] |= (bits & 1);
- endpoint_array[i * 4 + 2] |= (bits & 1);
- endpoint_array[i * 4 + 3] |= (bits & 1);
- bits >>= 1;
- }
- block->index += nu_subsets * 2;
- }
- int color_prec = color_component_precision_plus_pbit(mode);
- int alpha_prec = alpha_component_precision_plus_pbit(mode);
- for (int i = 0; i < nu_subsets * 2; i++) {
- // Color_component_precision & alpha_component_precision includes pbit
- // left shift endpoint components so that their MSB lies in bit 7
- endpoint_array[i * 4 + 0] <<= (8 - color_prec);
- endpoint_array[i * 4 + 1] <<= (8 - color_prec);
- endpoint_array[i * 4 + 2] <<= (8 - color_prec);
- endpoint_array[i * 4 + 3] <<= (8 - alpha_prec);
- // Replicate each component's MSB into the LSBs revealed by the left-shift operation above.
- endpoint_array[i * 4 + 0] |= (endpoint_array[i * 4 + 0] >> color_prec);
- endpoint_array[i * 4 + 1] |= (endpoint_array[i * 4 + 1] >> color_prec);
- endpoint_array[i * 4 + 2] |= (endpoint_array[i * 4 + 2] >> color_prec);
- endpoint_array[i * 4 + 3] |= (endpoint_array[i * 4 + 3] >> alpha_prec);
- }
-
- if (mode <= 3) {
- for (int i = 0; i < nu_subsets * 2; i++)
- endpoint_array[i * 4 + 3] = 0xFF;
- }
- }
- static const uint8_t aWeight2[4] = { 0, 21, 43, 64 };
- static const uint8_t aWeight3[8] = { 0, 9, 18, 27, 37, 46, 55, 64 };
- static const uint8_t aWeight4[16] = { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 };
- static uint8_t interpolate(uint8_t e0, uint8_t e1, uint8_t index, uint8_t indexprecision) {
- if (indexprecision == 2)
- return (uint8_t) (((64 - aWeight2[index]) * (uint16_t)e0 + aWeight2[index] * (uint16_t)e1 + 32) >> 6);
- else
- if (indexprecision == 3)
- return (uint8_t) (((64 - aWeight3[index]) * (uint16_t)e0 + aWeight3[index] * (uint16_t)e1 + 32) >> 6);
- else // indexprecision == 4
- return (uint8_t) (((64 - aWeight4[index]) * (uint16_t)e0 + aWeight4[index] * (uint16_t)e1 + 32) >> 6);
- }
- static const unsigned char bptc_color_index_bitcount[8] = { 3, 3, 2, 2, 2, 2, 4, 2 };
- static int get_color_index_bitcount(int mode, int index_selection_bit) {
- // If the index selection bit is set for mode 4, return 3, otherwise 2.
- return bptc_color_index_bitcount[mode] + index_selection_bit;
- }
- static const unsigned char bptc_alpha_index_bitcount[8] = { 3, 3, 2, 2, 3, 2, 4, 2};
- static int get_alpha_index_bitcount(int mode, int index_selection_bit) {
- // If the index selection bit is set for mode 4, return 2, otherwise 3.
- return bptc_alpha_index_bitcount[mode] - index_selection_bit;
- }
- static int extract_mode(Block *block) {
- for (int i = 0; i < 8; i++)
- if (block->data0 & ((uint64_t)1 << i)) {
- block->index = i + 1;
- return i;
- }
- // Illegal.
- return - 1;
- }
- static const unsigned char bptc_NS[8] = { 3, 2, 3, 2, 1, 1, 1, 2 };
- static int get_nu_subsets(int mode) {
- return bptc_NS[mode];
- }
- static const unsigned char PB[8] = { 4, 6, 6, 6, 0, 0, 0, 6 };
- static int extract_partition_set_id(Block *block, int mode) {
- return block_extract_bits(block, PB[mode]);
- }
- static int get_partition_index(int nu_subsets, int partition_set_id, int i) {
- if (nu_subsets == 1)
- return 0;
- if (nu_subsets == 2)
- return table_P2[partition_set_id * 16 + i];
- return table_P3[partition_set_id * 16 + i];
- }
- static const unsigned char RB[8] = { 0, 0, 0, 0, 2, 2, 0, 0 };
- static int extract_rot_bits(Block *block, int mode) {
- return block_extract_bits(block, RB[mode]);
- }
- static const unsigned char anchor_index_second_subset[64] = {
- 15,15,15,15,15,15,15,15,
- 15,15,15,15,15,15,15,15,
- 15, 2, 8, 2, 2, 8, 8,15,
- 2, 8, 2, 2, 8, 8, 2, 2,
- 15,15, 6, 8, 2, 8,15,15,
- 2, 8, 2, 2, 2,15,15, 6,
- 6, 2, 6, 8,15,15, 2, 2,
- 15,15,15,15,15, 2, 2,15
- };
- static const unsigned char anchor_index_second_subset_of_three[64] = {
- 3, 3,15,15, 8, 3,15,15,
- 8, 8, 6, 6, 6, 5, 3, 3,
- 3, 3, 8,15, 3, 3, 6,10,
- 5, 8, 8, 6, 8, 5,15,15,
- 8,15, 3, 5, 6,10, 8,15,
- 15, 3,15, 5,15,15,15,15,
- 3,15, 5, 5, 5, 8, 5,10,
- 5,10, 8,13,15,12, 3, 3
- };
- static const unsigned char anchor_index_third_subset[64] = {
- 15, 8, 8, 3,15,15, 3, 8,
- 15,15,15,15,15,15,15, 8,
- 15, 8,15, 3,15, 8,15, 8,
- 3,15, 6,10,15,15,10, 8,
- 15, 3,15,10,10, 8, 9,10,
- 6,15, 8,15, 3, 6, 6, 8,
- 15, 3,15,15,15,15,15,15,
- 15,15,15,15, 3,15,15, 8
- };
- static int get_anchor_index(int partition_set_id, int partition, int nu_subsets) {
- if (partition == 0)
- return 0;
- if (nu_subsets == 2)
- return anchor_index_second_subset[partition_set_id];
- if (partition == 1)
- return anchor_index_second_subset_of_three[partition_set_id];
- return anchor_index_third_subset[partition_set_id];
- }
- static const unsigned char IB[8] = { 3, 3, 2, 2, 2, 2, 4, 2 };
- static const unsigned char IB2[8] = { 0, 0, 0, 0, 3, 2, 0, 0 };
- static const unsigned char mode_has_partition_bits[8] = { 1, 1, 1, 1, 0, 0, 0, 1 };
- static int draw_bptc_mode_1(Block *block, unsigned int *image_buffer);
- int block4x4_bptc_get_mode(const unsigned char *bitstring) {
- Block block;
- block.data0 = *(uint64_t *)&bitstring[0];
- block.data1 = *(uint64_t *)&bitstring[8];
- block.index = 0;
- int mode = extract_mode(&block);
- return mode;
- }
- void block4x4_bptc_set_mode(unsigned char *bitstring, int flags) {
- // Mode 0 starts with 1
- // Mode 1 starts with 01
- // ...
- // Mode 7 starts with 00000001
- int mode_flags = flags & BPTC_MODE_ALLOWED_ALL;
- int bit = 0x1;
- for (int i = 0; i < 8; i++) {
- if (mode_flags == (1 << i)) {
- bitstring[0] &= ~(bit - 1);
- bitstring[0] |= bit;
- return;
- }
- bit <<= 1;
- }
- }
- static uint64_t clear_bits_uint64(uint64_t data, int bit0, int bit1) {
- uint64_t mask = ~(((uint64_t)1 << (bit1 + 1)) - 1);
- mask |= ((uint64_t)1 << bit0) - 1;
- return data & mask;
- }
- static uint64_t set_bits_uint64(uint64_t data, int bit0, int bit1, uint64_t val) {
- uint64_t d = clear_bits_uint64(data, bit0, bit1);
- d |= val << bit0;
- return d;
- }
- void bptc_set_block_colors(unsigned char *bitstring, int flags, unsigned int *colors) {
- if ((flags & TWO_COLORS) == 0)
- return;
- uint64_t data0 = *(uint64_t *)&bitstring[0];
- uint64_t data1 = *(uint64_t *)&bitstring[8];
- if ((flags & BPTC_MODE_ALLOWED_ALL) == (1 << 3)) {
- // Mode 3, 7 color bits.
- // Color bits at index: 10
- // Color bits end before index: 10 + 4 * 3 * 7 = 94
- int r0 = pixel_get_r(colors[0]);
- int g0 = pixel_get_g(colors[0]);
- int b0 = pixel_get_b(colors[0]);
- int r1 = pixel_get_r(colors[1]);
- int g1 = pixel_get_g(colors[1]);
- int b1 = pixel_get_b(colors[1]);
- data0 = set_bits_uint64(data0, 10, 16, r0 >> 1);
- data0 = set_bits_uint64(data0, 17, 23, r0 >> 1);
- data0 = set_bits_uint64(data0, 24, 30, r1 >> 1);
- data0 = set_bits_uint64(data0, 31, 37, r1 >> 1);
- data0 = set_bits_uint64(data0, 38, 44, g0 >> 1);
- data0 = set_bits_uint64(data0, 45, 51, g0 >> 1);
- data0 = set_bits_uint64(data0, 52, 58, g1 >> 1);
- data0 = set_bits_uint64(data0, 59, 63, (g1 >> 1) & 0x1F);
- data1 = set_bits_uint64(data1, 0, 1, ((g1 >> 1) & 0x60) >> 5);
- data1 = set_bits_uint64(data1, 2, 8, b0 >> 1);
- data1 = set_bits_uint64(data1, 9, 15, b0 >> 1);
- data1 = set_bits_uint64(data1, 16, 22, b1 >> 1);
- data1 = set_bits_uint64(data1, 23, 29, b1 >> 1);
- *(uint64_t *)&bitstring[0] = data0;
- *(uint64_t *)&bitstring[8] = data1;
- // printf("bptc_set_block_colors: Colors set for mode 3.\n");
- }
- else if ((flags & BPTC_MODE_ALLOWED_ALL) == (1 << 5)) {
- // Mode 5, 7 color bits, 8 alpha bits.
- // Color bits at index: 6 + 2 = 8
- // Alpha bits at index: 8 + 2 * 3 * 7 = 50
- // Alpha bits end before index: 50 + 2 * 8 = 66
- int r0 = pixel_get_r(colors[0]);
- int g0 = pixel_get_g(colors[0]);
- int b0 = pixel_get_b(colors[0]);
- int r1 = pixel_get_r(colors[1]);
- int g1 = pixel_get_g(colors[1]);
- int b1 = pixel_get_b(colors[1]);
- data0 = set_bits_uint64(data0, 8, 14, r0 >> 1);
- data0 = set_bits_uint64(data0, 15, 21, r1 >> 1);
- data0 = set_bits_uint64(data0, 22, 28, g0 >> 1);
- data0 = set_bits_uint64(data0, 29, 35, g0 >> 1);
- data0 = set_bits_uint64(data0, 36, 42, b0 >> 1);
- data0 = set_bits_uint64(data0, 43, 49, b1 >> 1);
- if (flags & (MODES_ALLOWED_PUNCHTHROUGH_ONLY)) {
- data0 = set_bits_uint64(data0, 50, 57, 0x00);
- data0 = set_bits_uint64(data0, 58, 63, 0x3F);
- data1 = set_bits_uint64(data1, 0, 1, 0x3);
- }
- *(uint64_t *)&bitstring[0] = data0;
- *(uint64_t *)&bitstring[8] = data1;
- // printf("bptc_set_block_colors: Colors set for mode 5.\n");
- }
- else if ((flags & BPTC_MODE_ALLOWED_ALL) == (1 << 6)) {
- // Mode 5, 7 color bits, 7 alpha bits.
- // Color bits at index 7.
- // Alpha bits at index: 7 + 2 * 3 * 7 = 49
- // Alpha bits end before index: 49 + 2 * 7 = 63
- int r0 = pixel_get_r(colors[0]);
- int g0 = pixel_get_g(colors[0]);
- int b0 = pixel_get_b(colors[0]);
- int r1 = pixel_get_r(colors[1]);
- int g1 = pixel_get_g(colors[1]);
- int b1 = pixel_get_b(colors[1]);
- data0 = set_bits_uint64(data0, 7, 13, r0 >> 1);
- data0 = set_bits_uint64(data0, 14, 20, r1 >> 1);
- data0 = set_bits_uint64(data0, 21, 27, g0 >> 1);
- data0 = set_bits_uint64(data0, 28, 34, g1 >> 1);
- data0 = set_bits_uint64(data0, 35, 41, b0 >> 1);
- data0 = set_bits_uint64(data0, 42, 48, b1 >> 1);
- if (flags & (MODES_ALLOWED_PUNCHTHROUGH_ONLY)) {
- data0 = set_bits_uint64(data0, 49, 55, 0x00);
- data0 = set_bits_uint64(data0, 56, 62, 0x7F);
- }
- *(uint64_t *)&bitstring[0] = data0;
- // printf("bptc_set_block_colors: Colors set for mode 6.\n");
- }
- }
- // Draw a 4x4 pixel block using the BPTC/BC7 texture compression data in bitstring.
- int draw_block4x4_bptc(const unsigned char *bitstring, unsigned int *image_buffer/*, int flags*/) {
- Block block;
- block.data0 = *(uint64_t *)&bitstring[0];
- block.data1 = *(uint64_t *)&bitstring[8];
- block.index = 0;
- int mode = extract_mode(&block);
- if (mode == - 1)
- return 0;
- // Allow compression tied to specific modes (according to flags).
- /*if (!(flags & ((int)1 << mode)))
- return 0;
- if (mode >= 4 && (flags & MODES_ALLOWED_OPAQUE_ONLY))
- return 0;
- if (mode < 4 && (flags & MODES_ALLOWED_NON_OPAQUE_ONLY))
- return 0;*/
- if (mode == 1)
- return draw_bptc_mode_1(&block, image_buffer);
- int nu_subsets = 1;
- int partition_set_id = 0;
- if (mode_has_partition_bits[mode]) {
- nu_subsets = get_nu_subsets(mode);
- partition_set_id = extract_partition_set_id(&block, mode);
- }
- int rotation = extract_rot_bits(&block, mode);
- int index_selection_bit = 0;
- if (mode == 4)
- index_selection_bit = block_extract_bits(&block, 1);
- int alpha_index_bitcount = get_alpha_index_bitcount(mode, index_selection_bit);
- int color_index_bitcount = get_color_index_bitcount(mode, index_selection_bit);
- uint8_t endpoint_array[3 * 2 * 4]; // Max. 3 subsets.
- extract_endpoints(mode, nu_subsets, &block, endpoint_array);
- fully_decode_endpoints(endpoint_array, nu_subsets, mode, &block);
- uint8_t subset_index[16];
- for (int i = 0; i < 16; i++)
- // subset_index[i] is a number from 0 to 2, or 0 to 1, or 0 depending on the number of subsets.
- subset_index[i] = get_partition_index(nu_subsets, partition_set_id, i);
- uint8_t anchor_index[4]; // Only need max. 3 elements.
- for (int i = 0; i < nu_subsets; i++)
- anchor_index[i] = get_anchor_index(partition_set_id, i, nu_subsets);
- uint8_t color_index[16];
- uint8_t alpha_index[16];
- // Extract primary index bits.
- uint64_t data1;
- if (block.index >= 64) {
- // Because the index bits are all in the second 64-bit word, there is no need to use
- // block_extract_bits().
- // This implies the mode is not 4.
- data1 = block.data1 >> (block.index - 64);
- uint8_t mask1 = (1 << IB[mode]) - 1;
- uint8_t mask2 = (1 << (IB[mode] - 1)) - 1;
- for (int i = 0; i < 16; i++)
- if (i == anchor_index[subset_index[i]]) {
- // Highest bit is zero.
- color_index[i] = data1 & mask2;
- data1 >>= IB[mode] - 1;
- alpha_index[i] = color_index[i];
- }
- else {
- color_index[i] = data1 & mask1;
- data1 >>= IB[mode];
- alpha_index[i] = color_index[i];
- }
- }
- else { // Implies mode 4.
- // Because the bits cross the 64-bit word boundary, we have to be careful.
- // Block index is 50 at this point.
- uint64_t data = block.data0 >> 50;
- data |= block.data1 << 14;
- for (int i = 0; i < 16; i++)
- if (i == anchor_index[subset_index[i]]) {
- // Highest bit is zero.
- if (index_selection_bit) { // Implies mode == 4.
- alpha_index[i] = data & 0x1;
- data >>= 1;
- }
- else {
- color_index[i] = data & 0x1;
- data >>= 1;
- }
- }
- else {
- if (index_selection_bit) { // Implies mode == 4.
- alpha_index[i] = data & 0x3;
- data >>= 2;
- }
- else {
- color_index[i] = data & 0x3;
- data >>= 2;
- }
- }
- // Block index is 81 at this point.
- data1 = block.data1 >> (81 - 64);
- }
- // Extract secondary index bits.
- if (IB2[mode] > 0) {
- uint8_t mask1 = (1 << IB2[mode]) - 1;
- uint8_t mask2 = (1 << (IB2[mode] - 1)) - 1;
- for (int i = 0; i < 16; i++)
- if (i == anchor_index[subset_index[i]]) {
- // Highest bit is zero.
- if (index_selection_bit) {
- color_index[i] = data1 & 0x3;
- data1 >>= 2;
- }
- else {
- // alpha_index[i] = block_extract_bits(&block, IB2[mode] - 1);
- alpha_index[i] = data1 & mask2;
- data1 >>= IB2[mode] - 1;
- }
- }
- else {
- if (index_selection_bit) {
- color_index[i] = data1 & 0x7;
- data1 >>= 3;
- }
- else {
- // alpha_index[i] = block_extract_bits(&block, IB2[mode]);
- alpha_index[i] = data1 & mask1;
- data1 >>= IB2[mode];
- }
- }
- }
- for (int i = 0; i < 16; i++) {
- uint8_t endpoint_start[4];
- uint8_t endpoint_end[4];
- for (int j = 0; j < 4; j++) {
- endpoint_start[j] = endpoint_array[2 * subset_index[i] * 4 + j];
- endpoint_end[j] = endpoint_array[(2 * subset_index[i] + 1) * 4 + j];
- }
- uint32_t output = 0;
- output = pack_r(interpolate(endpoint_start[0], endpoint_end[0], color_index[i], color_index_bitcount));
- output |= pack_g(interpolate(endpoint_start[1], endpoint_end[1], color_index[i], color_index_bitcount));
- output |= pack_b(interpolate(endpoint_start[2], endpoint_end[2], color_index[i], color_index_bitcount));
- output |= pack_a(interpolate(endpoint_start[3], endpoint_end[3], alpha_index[i], alpha_index_bitcount));
-
- if (rotation > 0) {
- if (rotation == 1)
- output = pack_rgba(pixel_get_a(output), pixel_get_g(output), pixel_get_b(output),
- pixel_get_r(output));
- else
- if (rotation == 2)
- output = pack_rgba(pixel_get_r(output), pixel_get_a(output), pixel_get_b(output),
- pixel_get_g(output));
- else // rotation == 3
- output = pack_rgba(pixel_get_r(output), pixel_get_g(output), pixel_get_a(output),
- pixel_get_b(output));
- }
- image_buffer[i] = output;
- }
- return 1;
- }
- static uint32_t get_reversed_bits_uint64(uint64_t data, int bit0, int bit1) {
- // Assumes bit0 > bit1.
- // Reverse the bits.
- uint32_t val = 0;
- for (int i = 0; i <= bit0 - bit1; i++) {
- int shift_right = bit0 - 2 * i;
- if (shift_right >= 0)
- val |= (data & ((uint64_t)1 << (bit0 - i))) >> shift_right;
- else
- val |= (data & ((uint64_t)1 << (bit0 - i))) << (- shift_right);
- }
- return val;
- }
- // Optimized version of BPTC decode for mode 1, the most common mode.
- static int draw_bptc_mode_1(Block *block, unsigned int *image_buffer) {
- uint64_t data0 = block->data0;
- uint64_t data1 = block->data1;
- int partition_set_id = get_bits_uint64(data0, 2, 7);
- uint8_t endpoint[2 * 2 * 3]; // 2 subsets.
- endpoint[0] = get_bits_uint64(data0, 8, 13); // red, subset 0, endpoint 0
- endpoint[3] = get_bits_uint64(data0, 14, 19); // red, subset 0, endpoint 1
- endpoint[6] = get_bits_uint64(data0, 20, 25); // red, subset 1, endpoint 0
- endpoint[9] = get_bits_uint64(data0, 26, 31); // red, subset 1, endpoint 1
- endpoint[1] = get_bits_uint64(data0, 32, 37); // green, subset 0, endpoint 0
- endpoint[4] = get_bits_uint64(data0, 38, 43); // green, subset 0, endpoint 1
- endpoint[7] = get_bits_uint64(data0, 44, 49); // green, subset 1, endpoint 0
- endpoint[10] = get_bits_uint64(data0, 50, 55); // green, subset 1, endpoint 1
- endpoint[2] = get_bits_uint64(data0, 56, 61); // blue, subset 0, endpoint 0
- endpoint[5] = get_bits_uint64(data0, 62, 63) // blue, subset 0, endpoint 1
- | (get_bits_uint64(data1, 0, 3) << 2);
- endpoint[8] = get_bits_uint64(data1, 4, 9); // blue, subset 1, endpoint 0
- endpoint[11] = get_bits_uint64(data1, 10, 15); // blue, subset 1, endpoint 1
- // Decode endpoints.
- for (int i = 0; i < 2 * 2; i++) {
- //component-wise left-shift
- endpoint[i * 3 + 0] <<= 2;
- endpoint[i * 3 + 1] <<= 2;
- endpoint[i * 3 + 2] <<= 2;
- }
- // P-bit is shared.
- uint8_t pbit_zero = get_bits_uint64(data1, 16, 16) << 1;
- uint8_t pbit_one = get_bits_uint64(data1, 17, 17) << 1;
- // RGB only pbits for mode 1, one for each subset.
- for (int j = 0; j < 3; j++) {
- endpoint[0 * 3 + j] |= pbit_zero;
- endpoint[1 * 3 + j] |= pbit_zero;
- endpoint[2 * 3 + j] |= pbit_one;
- endpoint[3 * 3 + j] |= pbit_one;
- }
- for (int i = 0; i < 2 * 2; i++) {
- // Replicate each component's MSB into the LSB.
- endpoint[i * 3 + 0] |= endpoint[i * 3 + 0] >> 7;
- endpoint[i * 3 + 1] |= endpoint[i * 3 + 1] >> 7;
- endpoint[i * 3 + 2] |= endpoint[i * 3 + 2] >> 7;
- }
-
- uint8_t subset_index[16];
- for (int i = 0; i < 16; i++)
- // subset_index[i] is a number from 0 to 1.
- subset_index[i] = table_P2[partition_set_id * 16 + i];
- uint8_t anchor_index[2];
- anchor_index[0] = 0;
- anchor_index[1] = anchor_index_second_subset[partition_set_id];
- uint8_t color_index[16];
- // Extract primary index bits.
- data1 >>= 18;
- for (int i = 0; i < 16; i++)
- if (i == anchor_index[subset_index[i]]) {
- // Highest bit is zero.
- color_index[i] = data1 & 3; // Get two bits.
- data1 >>= 2;
- }
- else {
- color_index[i] = data1 & 7; // Get three bits.
- data1 >>= 3;
- }
- for (int i = 0; i < 16; i++) {
- uint8_t endpoint_start[3];
- uint8_t endpoint_end[3];
- for (int j = 0; j < 3; j++) {
- endpoint_start[j] = endpoint[2 * subset_index[i] * 3 + j];
- endpoint_end[j] = endpoint[(2 * subset_index[i] + 1) * 3 + j];
- }
- uint32_t output;
- output = pack_r(interpolate(endpoint_start[0], endpoint_end[0], color_index[i], 3));
- output |= pack_g(interpolate(endpoint_start[1], endpoint_end[1], color_index[i], 3));
- output |= pack_b(interpolate(endpoint_start[2], endpoint_end[2], color_index[i], 3));
- output |= pack_a(0xFF);
- image_buffer[i] = output;
- }
- return 1;
- }
- // BPTC float (BC6H) decoding.
- static const signed char map_mode_table[32] = {
- 0, 1, 2, 10, -1, -1, 3, 11, -1, -1, 4, 12, -1, -1, 5, 13, -1, -1, 6, -1, -1, -1, 7, -1, -1, -1, 8,
- -1, -1, -1, 9, -1 };
- static int extract_bptc_float_mode(Block *block) {
- int mode = block_extract_bits(block, 2);
- if (mode < 2)
- return mode;
- return map_mode_table[mode | (block_extract_bits(block, 3) << 2)];
- }
- static int bptc_float_get_partition_index(int nu_subsets, int partition_set_id, int i) {
- if (nu_subsets == 1)
- return 0;
- // nu_subset == 2
- return table_P2[partition_set_id * 16 + i];
- }
- static const unsigned char bptc_float_EPB[14] = {
- 10, 7, 11, 11, 11, 9, 8, 8, 8, 6, 10, 11, 12, 16 };
- static uint32_t unquantize(uint16_t x, int mode) {
- int32_t unq;
- if (mode == 13)
- unq = x;
- else if (x == 0)
- unq = 0;
- else if (x == (((int32_t)1 << bptc_float_EPB[mode]) - 1))
- unq = 0xFFFF;
- else
- unq = (((int32_t)x << 15) + 0x4000) >> (bptc_float_EPB[mode] - 1);
- return unq;
- }
- static int32_t unquantize_signed(int16_t x, int mode) {
- int s = 0;
- int32_t unq;
- if (bptc_float_EPB[mode] >= 16)
- unq = x;
- else {
- if (x < 0) {
- s = 1;
- x = -x;
- }
- if (x == 0)
- unq = 0;
- else
- if (x >= (((int32_t)1 << (bptc_float_EPB[mode] - 1)) - 1))
- unq = 0x7FFF;
- else
- unq = (((int32_t)x << 15) + 0x4000) >> (bptc_float_EPB[mode] - 1);
- if (s)
- unq = -unq;
- }
- return unq;
- }
- static int sign_extend(int value, int source_nu_bits, int target_nu_bits) {
- uint32_t sign_bit = value & (1 << (source_nu_bits - 1));
- if (!sign_bit)
- return value;
- uint32_t sign_extend_bits = 0xFFFFFFFF ^ ((1 << source_nu_bits) - 1);
- sign_extend_bits &= ((uint64_t)1 << target_nu_bits) - 1;
- return value | sign_extend_bits;
- }
- static int32_t interpolate_float(int32_t e0, int32_t e1, int16_t index, uint8_t indexprecision) {
- if (indexprecision == 2)
- return (((64 - aWeight2[index]) * (int32_t)e0 + aWeight2[index] * (int32_t)e1 + 32) >> 6);
- else
- if (indexprecision == 3)
- return (((64 - aWeight3[index]) * (int32_t)e0 + aWeight3[index] * (int32_t)e1 + 32) >> 6);
- else // indexprecision == 4
- return (((64 - aWeight4[index]) * (int32_t)e0 + aWeight4[index] * (int32_t)e1 + 32) >> 6);
- }
- int block4x4_bptc_float_get_mode(const unsigned char *bitstring) {
- Block block;
- block.data0 = *(uint64_t *)&bitstring[0];
- block.data1 = *(uint64_t *)&bitstring[8];
- block.index = 0;
- uint32_t mode = extract_bptc_float_mode(&block);
- return mode;
- }
- static const uint8_t bptc_float_set_mode_table[14] = {
- 0, 1, 2, 6, 10, 14, 18, 22, 26, 30, 3, 7, 11, 15
- };
- void block4x4_bptc_float_set_mode(unsigned char *bitstring, int flags) {
- int mode_flags = flags & BPTC_FLOAT_MODE_ALLOWED_ALL;
- if (mode_flags & 0x3) {
- // Set mode 0 or 1.
- bitstring[0] = (bitstring[0] & 0xFC) | ((mode_flags & 0x2) >> 1);
- return;
- }
- uint8_t byte0 = bitstring[0];
- byte0 &= 0xE0;
- for (int i = 2; i < 14; i++)
- if (flags & (1 << i)) {
- byte0 |= bptc_float_set_mode_table[i];
- bitstring[0] = byte0;
- return;
- }
- }
- int draw_block4x4_bptc_float_shared(const unsigned char *bitstring, unsigned int *image_buffer, int signed_flag, int flags) {
- Block block;
- block.data0 = *(uint64_t *)&bitstring[0];
- block.data1 = *(uint64_t *)&bitstring[8];
- block.index = 0;
- uint32_t mode = extract_bptc_float_mode(&block);
- if (mode == - 1)
- return 0;
- // Allow compression tied to specific modes (according to flags).
- if (!(flags & ((int)1 << mode)))
- return 0;
- int32_t r[4], g[4], b[4];
- int partition_set_id = 0;
- int delta_bits_r, delta_bits_g, delta_bits_b;
- uint64_t data0 = block.data0;
- uint64_t data1 = block.data1;
- switch (mode) {
- case 0 :
- // m[1:0],g2[4],b2[4],b3[4],r0[9:0],g0[9:0],b0[9:0],r1[4:0],g3[4],g2[3:0],
- // g1[4:0],b3[0],g3[3:0],b1[4:0],b3[1],b2[3:0],r2[4:0],b3[2],r3[4:0],b3[3]
- g[2] = get_bits_uint64(data0, 2, 2) << 4;
- b[2] = get_bits_uint64(data0, 3, 3) << 4;
- b[3] = get_bits_uint64(data0, 4, 4) << 4;
- r[0] = get_bits_uint64(data0, 5, 14);
- g[0] = get_bits_uint64(data0, 15, 24);
- b[0] = get_bits_uint64(data0, 25, 34);
- r[1] = get_bits_uint64(data0, 35, 39);
- g[3] = get_bits_uint64(data0, 40, 40) << 4;
- g[2] |= get_bits_uint64(data0, 41, 44);
- g[1] = get_bits_uint64(data0, 45, 49);
- b[3] |= get_bits_uint64(data0, 50, 50);
- g[3] |= get_bits_uint64(data0, 51, 54);
- b[1] = get_bits_uint64(data0, 55, 59);
- b[3] |= get_bits_uint64(data0, 60, 60) << 1;
- b[2] |= get_bits_uint64(data0, 61, 63);
- b[2] |= get_bits_uint64(data1, 0, 0) << 3;
- r[2] = get_bits_uint64(data1, 1, 5);
- b[3] |= get_bits_uint64(data1, 6, 6) << 2;
- r[3] = get_bits_uint64(data1, 7, 11);
- b[3] |= get_bits_uint64(data1, 12, 12) << 3;
- partition_set_id = get_bits_uint64(data1, 13, 17);
- block.index = 64 + 18;
- delta_bits_r = delta_bits_g = delta_bits_b = 5;
- break;
- case 1 :
- // m[1:0],g2[5],g3[4],g3[5],r0[6:0],b3[0],b3[1],b2[4],g0[6:0],b2[5],b3[2],
- // g2[4],b0[6:0],b3[3],b3[5],b3[4],r1[5:0],g2[3:0],g1[5:0],g3[3:0],b1[5:0],
- // b2[3:0],r2[5:0],r3[5:0]
- g[2] = get_bits_uint64(data0, 2, 2) << 5;
- g[3] = get_bits_uint64(data0, 3, 3) << 4;
- g[3] |= get_bits_uint64(data0, 4, 4) << 5;
- r[0] = get_bits_uint64(data0, 5, 11);
- b[3] = get_bits_uint64(data0, 12, 12);
- b[3] |= get_bits_uint64(data0, 13, 13) << 1;
- b[2] = get_bits_uint64(data0, 14, 14) << 4;
- g[0] = get_bits_uint64(data0, 15, 21);
- b[2] |= get_bits_uint64(data0, 22, 22) << 5;
- b[3] |= get_bits_uint64(data0, 23, 23) << 2;
- g[2] |= get_bits_uint64(data0, 24, 24) << 4;
- b[0] = get_bits_uint64(data0, 25, 31);
- b[3] |= get_bits_uint64(data0, 32, 32) << 3;
- b[3] |= get_bits_uint64(data0, 33, 33) << 5;
- b[3] |= get_bits_uint64(data0, 34, 34) << 4;
- r[1] = get_bits_uint64(data0, 35, 40);
- g[2] |= get_bits_uint64(data0, 41, 44);
- g[1] = get_bits_uint64(data0, 45, 50);
- g[3] |= get_bits_uint64(data0, 51, 54);
- b[1] = get_bits_uint64(data0, 55, 60);
- b[2] |= get_bits_uint64(data0, 61, 63);
- b[2] |= get_bits_uint64(data1, 0, 0) << 3;
- r[2] = get_bits_uint64(data1, 1, 6);
- r[3] = get_bits_uint64(data1, 7, 12);
- partition_set_id = get_bits_uint64(data1, 13, 17);
- block.index = 64 + 18;
- delta_bits_r = delta_bits_g = delta_bits_b = 6;
- break;
- case 2 :
- // m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[4:0],r0[10],g2[3:0],g1[3:0],g0[10],
- // b3[0],g3[3:0],b1[3:0],b0[10],b3[1],b2[3:0],r2[4:0],b3[2],r3[4:0],b3[3]
- r[0] = get_bits_uint64(data0, 5, 14);
- g[0] = get_bits_uint64(data0, 15, 24);
- b[0] = get_bits_uint64(data0, 25, 34);
- r[1] = get_bits_uint64(data0, 35, 39);
- r[0] |= get_bits_uint64(data0, 40, 40) << 10;
- g[2] = get_bits_uint64(data0, 41, 44);
- g[1] = get_bits_uint64(data0, 45, 48);
- g[0] |= get_bits_uint64(data0, 49, 49) << 10;
- b[3] = get_bits_uint64(data0, 50, 50);
- g[3] = get_bits_uint64(data0, 51, 54);
- b[1] = get_bits_uint64(data0, 55, 58);
- b[0] |= get_bits_uint64(data0, 59, 59) << 10;
- b[3] |= get_bits_uint64(data0, 60, 60) << 1;
- b[2] = get_bits_uint64(data0, 61, 63);
- b[2] |= get_bits_uint64(data1, 0, 0) << 3;
- r[2] = get_bits_uint64(data1, 1, 5);
- b[3] |= get_bits_uint64(data1, 6, 6) << 2;
- r[3] = get_bits_uint64(data1, 7, 11);
- b[3] |= get_bits_uint64(data1, 12, 12) << 3;
- partition_set_id = get_bits_uint64(data1, 13, 17);
- block.index = 64 + 18;
- delta_bits_r = 5;
- delta_bits_g = delta_bits_b = 4;
- break;
- case 3 : // Original mode 6.
- // m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[3:0],r0[10],g3[4],g2[3:0],g1[4:0],
- // g0[10],g3[3:0],b1[3:0],b0[10],b3[1],b2[3:0],r2[3:0],b3[0],b3[2],r3[3:0],
- // g2[4],b3[3]
- r[0] = get_bits_uint64(data0, 5, 14);
- g[0] = get_bits_uint64(data0, 15, 24);
- b[0] = get_bits_uint64(data0, 25, 34);
- r[1] = get_bits_uint64(data0, 35, 38);
- r[0] |= get_bits_uint64(data0, 39, 39) << 10;
- g[3] = get_bits_uint64(data0, 40, 40) << 4;
- g[2] = get_bits_uint64(data0, 41, 44);
- g[1] = get_bits_uint64(data0, 45, 49);
- g[0] |= get_bits_uint64(data0, 50, 50) << 10;
- g[3] |= get_bits_uint64(data0, 51, 54);
- b[1] = get_bits_uint64(data0, 55, 58);
- b[0] |= get_bits_uint64(data0, 59, 59) << 10;
- b[3] = get_bits_uint64(data0, 60, 60) << 1;
- b[2] = get_bits_uint64(data0, 61, 63);
- b[2] |= get_bits_uint64(data1, 0, 0) << 3;
- r[2] = get_bits_uint64(data1, 1, 4);
- b[3] |= get_bits_uint64(data1, 5, 5);
- b[3] |= get_bits_uint64(data1, 6, 6) << 2;
- r[3] = get_bits_uint64(data1, 7, 10);
- g[2] |= get_bits_uint64(data1, 11, 11) << 4;
- b[3] |= get_bits_uint64(data1, 12, 12) << 3;
- partition_set_id = get_bits_uint64(data1, 13, 17);
- block.index = 64 + 18;
- delta_bits_r = delta_bits_b = 4;
- delta_bits_g = 5;
- break;
- case 4 : // Original mode 10.
- // m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[3:0],r0[10],b2[4],g2[3:0],g1[3:0],
- // g0[10],b3[0],g3[3:0],b1[4:0],b0[10],b2[3:0],r2[3:0],b3[1],b3[2],r3[3:0],
- // b3[4],b3[3]
- r[0] = get_bits_uint64(data0, 5, 14);
- g[0] = get_bits_uint64(data0, 15, 24);
- b[0] = get_bits_uint64(data0, 25, 34);
- r[1] = get_bits_uint64(data0, 35, 38);
- r[0] |= get_bits_uint64(data0, 39, 39) << 10;
- b[2] = get_bits_uint64(data0, 40, 40) << 4;
- g[2] = get_bits_uint64(data0, 41, 44);
- g[1] = get_bits_uint64(data0, 45, 48);
- g[0] |= get_bits_uint64(data0, 49, 49) << 10;
- b[3] = get_bits_uint64(data0, 50, 50);
- g[3] = get_bits_uint64(data0, 51, 54);
- b[1] = get_bits_uint64(data0, 55, 59);
- b[0] |= get_bits_uint64(data0, 60, 60) << 10;
- b[2] |= get_bits_uint64(data0, 61, 63);
- b[2] |= get_bits_uint64(data1, 0, 0) << 3;
- r[2] = get_bits_uint64(data1, 1, 4);
- b[3] |= get_bits_uint64(data1, 5, 5) << 1;
- b[3] |= get_bits_uint64(data1, 6, 6) << 2;
- r[3] = get_bits_uint64(data1, 7, 10);
- b[3] |= get_bits_uint64(data1, 11, 11) << 4;
- b[3] |= get_bits_uint64(data1, 12, 12) << 3;
- partition_set_id = get_bits_uint64(data1, 13, 17);
- block.index = 64 + 18;
- delta_bits_r = delta_bits_g = 4;
- delta_bits_b = 5;
- break;
- case 5 : // Original mode 14
- // m[4:0],r0[8:0],b2[4],g0[8:0],g2[4],b0[8:0],b3[4],r1[4:0],g3[4],g2[3:0],
- // g1[4:0],b3[0],g3[3:0],b1[4:0],b3[1],b2[3:0],r2[4:0],b3[2],r3[4:0],b3[3]
- r[0] = get_bits_uint64(data0, 5, 13);
- b[2] = get_bits_uint64(data0, 14, 14) << 4;
- g[0] = get_bits_uint64(data0, 15, 23);
- g[2] = get_bits_uint64(data0, 24, 24) << 4;
- b[0] = get_bits_uint64(data0, 25, 33);
- b[3] = get_bits_uint64(data0, 34, 34) << 4;
- r[1] = get_bits_uint64(data0, 35, 39);
- g[3] = get_bits_uint64(data0, 40, 40) << 4;
- g[2] |= get_bits_uint64(data0, 41, 44);
- g[1] = get_bits_uint64(data0, 45, 49);
- b[3] |= get_bits_uint64(data0, 50, 50);
- g[3] |= get_bits_uint64(data0, 51, 54);
- b[1] = get_bits_uint64(data0, 55, 59);
- b[3] |= get_bits_uint64(data0, 60, 60) << 1;
- b[2] |= get_bits_uint64(data0, 61, 63);
- b[2] |= get_bits_uint64(data1, 0, 0) << 3;
- r[2] = get_bits_uint64(data1, 1, 5);
- b[3] |= get_bits_uint64(data1, 6, 6) << 2;
- r[3] = get_bits_uint64(data1, 7, 11);
- b[3] |= get_bits_uint64(data1, 12, 12) << 3;
- partition_set_id = get_bits_uint64(data1, 13, 17);
- block.index = 64 + 18;
- delta_bits_r = delta_bits_g = delta_bits_b = 5;
- break;
- case 6 : // Original mode 18
- // m[4:0],r0[7:0],g3[4],b2[4],g0[7:0],b3[2],g2[4],b0[7:0],b3[3],b3[4],
- // r1[5:0],g2[3:0],g1[4:0],b3[0],g3[3:0],b1[4:0],b3[1],b2[3:0],r2[5:0],r3[5:0]
- r[0] = get_bits_uint64(data0, 5, 12);
- g[3] = get_bits_uint64(data0, 13, 13) << 4;
- b[2] = get_bits_uint64(data0, 14, 14) << 4;
- g[0] = get_bits_uint64(data0, 15, 22);
- b[3] = get_bits_uint64(data0, 23, 23) << 2;
- g[2] = get_bits_uint64(data0, 24, 24) << 4;
- b[0] = get_bits_uint64(data0, 25, 32);
- b[3] |= get_bits_uint64(data0, 33, 33) << 3;
- b[3] |= get_bits_uint64(data0, 34, 34) << 4;
- r[1] = get_bits_uint64(data0, 35, 40);
- g[2] |= get_bits_uint64(data0, 41, 44);
- g[1] = get_bits_uint64(data0, 45, 49);
- b[3] |= get_bits_uint64(data0, 50, 50);
- g[3] |= get_bits_uint64(data0, 51, 54);
- b[1] = get_bits_uint64(data0, 55, 59);
- b[3] |= get_bits_uint64(data0, 60, 60) << 1;
- b[2] |= get_bits_uint64(data0, 61, 63);
- b[2] |= get_bits_uint64(data1, 0, 0) << 3;
- r[2] = get_bits_uint64(data1, 1, 6);
- r[3] = get_bits_uint64(data1, 7, 12);
- partition_set_id = get_bits_uint64(data1, 13, 17);
- block.index = 64 + 18;
- delta_bits_r = 6;
- delta_bits_g = delta_bits_b = 5;
- break;
- case 7 : // Original mode 22
- // m[4:0],r0[7:0],b3[0],b2[4],g0[7:0],g2[5],g2[4],b0[7:0],g3[5],b3[4],
- // r1[4:0],g3[4],g2[3:0],g1[5:0],g3[3:0],b1[4:0],b3[1],b2[3:0],r2[4:0],
- // b3[2],r3[4:0],b3[3]
- r[0] = get_bits_uint64(data0, 5, 12);
- b[3] = get_bits_uint64(data0, 13, 13);
- b[2] = get_bits_uint64(data0, 14, 14) << 4;
- g[0] = get_bits_uint64(data0, 15, 22);
- g[2] = get_bits_uint64(data0, 23, 23) << 5;
- g[2] |= get_bits_uint64(data0, 24, 24) << 4;
- b[0] = get_bits_uint64(data0, 25, 32);
- g[3] = get_bits_uint64(data0, 33, 33) << 5;
- b[3] |= get_bits_uint64(data0, 34, 34) << 4;
- r[1] = get_bits_uint64(data0, 35, 39);
- g[3] |= get_bits_uint64(data0, 40, 40) << 4;
- g[2] |= get_bits_uint64(data0, 41, 44);
- g[1] = get_bits_uint64(data0, 45, 50);
- g[3] |= get_bits_uint64(data0, 51, 54);
- b[1] = get_bits_uint64(data0, 55, 59);
- b[3] |= get_bits_uint64(data0, 60, 60) << 1;
- b[2] |= get_bits_uint64(data0, 61, 63);
- b[2] |= get_bits_uint64(data1, 0, 0) << 3;
- r[2] = get_bits_uint64(data1, 1, 5);
- b[3] |= get_bits_uint64(data1, 6, 6) << 2;
- r[3] = get_bits_uint64(data1, 7, 11);
- b[3] |= get_bits_uint64(data1, 12, 12) << 3;
- partition_set_id = get_bits_uint64(data1, 13, 17);
- block.index = 64 + 18;
- delta_bits_r = delta_bits_b = 5;
- delta_bits_g = 6;
- break;
- case 8 : // Original mode 26
- // m[4:0],r0[7:0],b3[1],b2[4],g0[7:0],b2[5],g2[4],b0[7:0],b3[5],b3[4],
- // r1[4:0],g3[4],g2[3:0],g1[4:0],b3[0],g3[3:0],b1[5:0],b2[3:0],r2[4:0],
- // b3[2],r3[4:0],b3[3]
- r[0] = get_bits_uint64(data0, 5, 12);
- b[3] = get_bits_uint64(data0, 13, 13) << 1;
- b[2] = get_bits_uint64(data0, 14, 14) << 4;
- g[0] = get_bits_uint64(data0, 15, 22);
- b[2] |= get_bits_uint64(data0, 23, 23) << 5;
- g[2] = get_bits_uint64(data0, 24, 24) << 4;
- b[0] = get_bits_uint64(data0, 25, 32);
- b[3] |= get_bits_uint64(data0, 33, 33) << 5;
- b[3] |= get_bits_uint64(data0, 34, 34) << 4;
- r[1] = get_bits_uint64(data0, 35, 39);
- g[3] = get_bits_uint64(data0, 40, 40) << 4;
- g[2] |= get_bits_uint64(data0, 41, 44);
- g[1] = get_bits_uint64(data0, 45, 49);
- b[3] |= get_bits_uint64(data0, 50, 50);
- g[3] |= get_bits_uint64(data0, 51, 54);
- b[1] = get_bits_uint64(data0, 55, 60);
- b[2] |= get_bits_uint64(data0, 61, 63);
- b[2] |= get_bits_uint64(data1, 0, 0) << 3;
- r[2] = get_bits_uint64(data1, 1, 5);
- b[3] |= get_bits_uint64(data1, 6, 6) << 2;
- r[3] = get_bits_uint64(data1, 7, 11);
- b[3] |= get_bits_uint64(data1, 12, 12) << 3;
- partition_set_id = get_bits_uint64(data1, 13, 17);
- block.index = 64 + 18;
- delta_bits_r = delta_bits_g = 5;
- delta_bits_b = 6;
- break;
- case 9 : // Original mode 30
- // m[4:0],r0[5:0],g3[4],b3[0],b3[1],b2[4],g0[5:0],g2[5],b2[5],b3[2],
- // g2[4],b0[5:0],g3[5],b3[3],b3[5],b3[4],r1[5:0],g2[3:0],g1[5:0],g3[3:0],
- // b1[5:0],b2[3:0],r2[5:0],r3[5:0]
- r[0] = get_bits_uint64(data0, 5, 10);
- g[3] = get_bits_uint64(data0, 11, 11) << 4;
- b[3] = get_bits_uint64(data0, 12, 13);
- b[2] = get_bits_uint64(data0, 14, 14) << 4;
- g[0] = get_bits_uint64(data0, 15, 20);
- g[2] = get_bits_uint64(data0, 21, 21) << 5;
- b[2] |= get_bits_uint64(data0, 22, 22) << 5;
- b[3] |= get_bits_uint64(data0, 23, 23) << 2;
- g[2] |= get_bits_uint64(data0, 24, 24) << 4;
- b[0] = get_bits_uint64(data0, 25, 30);
- g[3] |= get_bits_uint64(data0, 31, 31) << 5;
- b[3] |= get_bits_uint64(data0, 32, 32) << 3;
- b[3] |= get_bits_uint64(data0, 33, 33) << 5;
- b[3] |= get_bits_uint64(data0, 34, 34) << 4;
- r[1] = get_bits_uint64(data0, 35, 40);
- g[2] |= get_bits_uint64(data0, 41, 44);
- g[1] = get_bits_uint64(data0, 45, 50);
- g[3] |= get_bits_uint64(data0, 51, 54);
- b[1] = get_bits_uint64(data0, 55, 60);
- b[2] |= get_bits_uint64(data0, 61, 63);
- b[2] |= get_bits_uint64(data1, 0, 0) << 3;
- r[2] = get_bits_uint64(data1, 1, 6);
- r[3] = get_bits_uint64(data1, 7, 12);
- partition_set_id = get_bits_uint64(data1, 13, 17);
- block.index = 64 + 18;
- // delta_bits_r = delta_bits_g = delta_bits_b = 6;
- break;
- case 10 : // Original mode 3
- // m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[9:0],g1[9:0],b1[9:0]
- r[0] = get_bits_uint64(data0, 5, 14);
- g[0] = get_bits_uint64(data0, 15, 24);
- b[0] = get_bits_uint64(data0, 25, 34);
- r[1] = get_bits_uint64(data0, 35, 44);
- g[1] = get_bits_uint64(data0, 45, 54);
- b[1] = get_bits_uint64(data0, 55, 63);
- b[1] |= get_bits_uint64(data1, 0, 0) << 9;
- partition_set_id = 0;
- block.index = 65;
- // delta_bits_r = delta_bits_g = delta_bits_b = 10;
- break;
- case 11 : // Original mode 7
- // m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[8:0],r0[10],g1[8:0],g0[10],b1[8:0],b0[10]
- r[0] = get_bits_uint64(data0, 5, 14);
- g[0] = get_bits_uint64(data0, 15, 24);
- b[0] = get_bits_uint64(data0, 25, 34);
- r[1] = get_bits_uint64(data0, 35, 43);
- r[0] |= get_bits_uint64(data0, 44, 44) << 10;
- g[1] = get_bits_uint64(data0, 45, 53);
- g[0] |= get_bits_uint64(data0, 54, 54) << 10;
- b[1] = get_bits_uint64(data0, 55, 63);
- b[0] |= get_bits_uint64(data1, 0, 0) << 10;
- partition_set_id = 0;
- block.index = 65;
- delta_bits_r = delta_bits_g = delta_bits_b = 9;
- break;
- case 12 : // Original mode 11
- // m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[7:0],r0[10:11],g1[7:0],g0[10:11],
- // b1[7:0],b0[10:11]
- r[0] = get_bits_uint64(data0, 5, 14);
- g[0] = get_bits_uint64(data0, 15, 24);
- b[0] = get_bits_uint64(data0, 25, 34);
- r[1] = get_bits_uint64(data0, 35, 42);
- r[0] |= get_reversed_bits_uint64(data0, 44, 43) << 10; // Reversed.
- g[1] = get_bits_uint64(data0, 45, 52);
- g[0] |= get_reversed_bits_uint64(data0, 54, 53) << 10; // Reversed.
- b[1] = get_bits_uint64(data0, 55, 62);
- b[0] |= get_bits_uint64(data0, 63, 63) << 11; // MSB
- b[0] |= get_bits_uint64(data1, 0, 0) << 10; // LSB
- partition_set_id = 0;
- block.index = 65;
- delta_bits_r = delta_bits_g = delta_bits_b = 8;
- break;
- case 13 : // Original mode 15
- // m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[3:0],r0[10:15],g1[3:0],g0[10:15],
- // b1[3:0],b0[10:15]
- r[0] = get_bits_uint64(data0, 5, 14);
- g[0] = get_bits_uint64(data0, 15, 24);
- b[0] = get_bits_uint64(data0, 25, 34);
- r[1] = get_bits_uint64(data0, 35, 38);
- r[0] |= get_reversed_bits_uint64(data0, 44, 39) << 10; // Reversed.
- g[1] = get_bits_uint64(data0, 45, 48);
- g[0] |= get_reversed_bits_uint64(data0, 54, 49) << 10; // Reversed.
- b[1] = get_bits_uint64(data0, 55, 58);
- b[0] |= get_reversed_bits_uint64(data0, 63, 59) << 11; // Reversed.
- b[0] |= get_bits_uint64(data1, 0, 0) << 10;
- partition_set_id = 0;
- block.index = 65;
- delta_bits_r = delta_bits_g = delta_bits_b = 4;
- break;
- }
- int nu_subsets;
- if (mode >= 10)
- nu_subsets = 1;
- else
- nu_subsets = 2;
- if (signed_flag) {
- r[0] = sign_extend(r[0], bptc_float_EPB[mode], 32);
- g[0] = sign_extend(g[0], bptc_float_EPB[mode], 32);
- b[0] = sign_extend(b[0], bptc_float_EPB[mode], 32);
- }
- if (mode != 9 && mode != 10) {
- // Transformed endpoints.
- for (int i = 1; i < nu_subsets * 2; i++) {
- r[i] = sign_extend(r[i], delta_bits_r, 32);
- r[i] = (r[0] + r[i]) & (((uint32_t)1 << bptc_float_EPB[mode]) - 1);
- g[i] = sign_extend(g[i], delta_bits_g, 32);
- g[i] = (g[0] + g[i]) & (((uint32_t)1 << bptc_float_EPB[mode]) - 1);
- b[i] = sign_extend(b[i], delta_bits_b, 32);
- b[i] = (b[0] + b[i]) & (((uint32_t)1 << bptc_float_EPB[mode]) - 1);
- if (signed_flag) {
- r[i] = sign_extend(r[i], bptc_float_EPB[mode], 32);
- g[i] = sign_extend(g[i], bptc_float_EPB[mode], 32);
- b[i] = sign_extend(b[i], bptc_float_EPB[mode], 32);
- }
- }
- }
- else // Mode 9 or 10, no transformed endpoints.
- if (signed_flag)
- for (int i = 1; i < nu_subsets * 2; i++) {
- r[i] = sign_extend(r[i], bptc_float_EPB[mode], 32);
- g[i] = sign_extend(g[i], bptc_float_EPB[mode], 32);
- b[i] = sign_extend(b[i], bptc_float_EPB[mode], 32);
- }
- // Unquantize endpoints.
- if (signed_flag)
- for (int i = 0; i < 2 * nu_subsets; i++) {
- r[i] = unquantize_signed(r[i], mode);
- g[i] = unquantize_signed(g[i], mode);
- b[i] = unquantize_signed(b[i], mode);
- }
- else
- for (int i = 0; i < 2 * nu_subsets; i++) {
- r[i] = unquantize(r[i], mode);
- g[i] = unquantize(g[i], mode);
- b[i] = unquantize(b[i], mode);
- }
- uint8_t subset_index[16];
- for (int i = 0; i < 16; i++) {
- // subset_index[i] is a number from 0 to 1, depending on the number of subsets.
- subset_index[i] = bptc_float_get_partition_index(nu_subsets, partition_set_id, i);
- }
- uint8_t anchor_index[4]; // Only need max. 2 elements
- for (int i = 0; i < nu_subsets; i++)
- anchor_index[i] = get_anchor_index(partition_set_id, i, nu_subsets);
- uint8_t color_index[16];
- // Extract index bits.
- int color_index_bit_count = 3;
- if ((bitstring[0] & 3) == 3) // This defines original modes 3, 7, 11, 15
- color_index_bit_count = 4;
- // Because the index bits are all in the second 64-bit word, there is no need to use
- // block_extract_bits().
- data1 >>= (block.index - 64);
- uint8_t mask1 = (1 << color_index_bit_count) - 1;
- uint8_t mask2 = (1 << (color_index_bit_count - 1)) - 1;
- for (int i = 0; i < 16; i++) {
- if (i == anchor_index[subset_index[i]]) {
- // Highest bit is zero.
- // color_index[i] = block_extract_bits(&block, color_index_bit_count - 1);
- color_index[i] = data1 & mask2;
- data1 >>= color_index_bit_count - 1;
- }
- else {
- // color_index[i] = block_extract_bits(&block, color_index_bit_count);
- color_index[i] = data1 & mask1;
- data1 >>= color_index_bit_count;
- }
- }
- for (int i = 0; i < 16; i++) {
- int32_t endpoint_start_r, endpoint_start_g, endpoint_start_b;
- int32_t endpoint_end_r, endpoint_end_g, endpoint_end_b;
- endpoint_start_r = r[2 * subset_index[i]];
- endpoint_end_r = r[2 * subset_index[i] + 1];
- endpoint_start_g = g[2 * subset_index[i]];
- endpoint_end_g = g[2 * subset_index[i] + 1];
- endpoint_start_b = b[2 * subset_index[i]];
- endpoint_end_b = b[2 * subset_index[i] + 1];
- uint64_t output;
- if (signed_flag) {
- int32_t r16 = interpolate_float(endpoint_start_r, endpoint_end_r, color_index[i],
- color_index_bit_count);
- if (r16 < 0)
- r16 = - (((- r16) * 31) >> 5);
- else
- r16 = (r16 * 31) >> 5;
- int s = 0;
- if (r16 < 0) {
- s = 0x8000;
- r16 = - r16;
- }
- r16 |= s;
- int32_t g16 = interpolate_float(endpoint_start_g, endpoint_end_g, color_index[i],
- color_index_bit_count);
- if (g16 < 0)
- g16 = - (((- g16) * 31) >> 5);
- else
- g16 = (g16 * 31) >> 5;
- s = 0;
- if (g16 < 0) {
- s = 0x8000;
- g16 = - g16;
- }
- g16 |= s;
- int32_t b16 = interpolate_float(endpoint_start_b, endpoint_end_b, color_index[i],
- color_index_bit_count);
- if (b16 < 0)
- b16 = - (((- b16) * 31) >> 5);
- else
- b16 = (b16 * 31) >> 5;
- s = 0;
- if (b16 < 0) {
- s = 0x8000;
- b16 = - b16;
- }
- b16 |= s;
- output = pack_rgb16(r16, g16, b16);
- }
- else {
- output = pack_r16(interpolate_float(endpoint_start_r, endpoint_end_r, color_index[i],
- color_index_bit_count) * 31 / 64);
- output |= pack_g16(interpolate_float(endpoint_start_g, endpoint_end_g, color_index[i],
- color_index_bit_count) * 31 / 64);
- output |= pack_b16(interpolate_float(endpoint_start_b, endpoint_end_b, color_index[i],
- color_index_bit_count) * 31 / 64);
- }
- *(uint64_t *)&image_buffer[i * 2] = output;
- }
- return 1;
- }
- int draw_block4x4_bptc_float(const unsigned char *bitstring, unsigned int *image_buffer, int flags) {
- return draw_block4x4_bptc_float_shared(bitstring, image_buffer, 0, flags);
- }
- int draw_block4x4_bptc_signed_float(const unsigned char *bitstring, unsigned int *image_buffer, int flags) {
- return draw_block4x4_bptc_float_shared(bitstring, image_buffer, 1, flags);
- }
|