From 3b18b654b0805b35dd397fda20390b745157da59 Mon Sep 17 00:00:00 2001 From: Wang Zichong Date: Mon, 19 Oct 2026 10:28:47 +0800 Subject: [PATCH] DDS: add DX10 BC4/BC5/BC7 support DX10 DDS files using the BC (block compression) formats were reported as unsupported: knownDXGIFormat() only mapped the floating point DXGI formats, so getFormat() returned FormatUnknown and ensureScanned() failed, e.g. for a BC7_UNORM_SRGB (dxgi 99) image. The following changes have been made: - Added a self-contained BC7 decoder following the "BC7 Format" specification, supporting all 8 modes, for both the UNORM and the UNORM_SRGB variants (loaded as ARGB32) - Added BC4 support (single channel, loaded as Grayscale8) - Added BC5 support, reusing the existing ATI2/3Dc normal map decoder - Added DX10 mappings for BC1/BC2/BC3, which were previously handled only as the legacy DXT1/DXT3/DXT5 fourCC formats - Added read tests for BC4, BC5, BC7 and BC7_UNORM_SRGB, plus DX10 variants of the existing BC1/BC2/BC3 test images BC6H (HDR) is not supported. The test data was generated from the existing rgba.png test image, encoded with bc7enc_rdo and decoded with bcdec. BUG: 524495 --- autotests/read/dds/bc4.dds | Bin 0 -> 4756 bytes autotests/read/dds/bc4.png | Bin 0 -> 2129 bytes autotests/read/dds/bc5.dds | Bin 0 -> 9364 bytes autotests/read/dds/bc5.png | Bin 0 -> 4478 bytes autotests/read/dds/bc7.dds | Bin 0 -> 9364 bytes autotests/read/dds/bc7.png | Bin 0 -> 5350 bytes autotests/read/dds/bc7srgb.dds | Bin 0 -> 9364 bytes autotests/read/dds/bc7srgb.png | Bin 0 -> 5350 bytes autotests/read/dds/rgba_bc1dx10.dds | Bin 0 -> 4756 bytes autotests/read/dds/rgba_bc1dx10.png | Bin 0 -> 4727 bytes autotests/read/dds/rgba_bc2dx10.dds | Bin 0 -> 9364 bytes autotests/read/dds/rgba_bc2dx10.png | Bin 0 -> 5319 bytes autotests/read/dds/rgba_bc3dx10.dds | Bin 0 -> 9364 bytes autotests/read/dds/rgba_bc3dx10.png | Bin 0 -> 5385 bytes src/imageformats/dds.cpp | 440 +++++++++++++++++++++++++++- 15 files changed, 438 insertions(+), 2 deletions(-) create mode 100644 autotests/read/dds/bc4.dds create mode 100644 autotests/read/dds/bc4.png create mode 100644 autotests/read/dds/bc5.dds create mode 100644 autotests/read/dds/bc5.png create mode 100644 autotests/read/dds/bc7.dds create mode 100644 autotests/read/dds/bc7.png create mode 100644 autotests/read/dds/bc7srgb.dds create mode 100644 autotests/read/dds/bc7srgb.png create mode 100644 autotests/read/dds/rgba_bc1dx10.dds create mode 100644 autotests/read/dds/rgba_bc1dx10.png create mode 100644 autotests/read/dds/rgba_bc2dx10.dds create mode 100644 autotests/read/dds/rgba_bc2dx10.png create mode 100644 autotests/read/dds/rgba_bc3dx10.dds create mode 100644 autotests/read/dds/rgba_bc3dx10.png diff --git a/autotests/read/dds/bc4.dds b/autotests/read/dds/bc4.dds new file mode 100644 index 0000000000000000000000000000000000000000..6937effd9ac88d65939713660dd58fcef6c8c73b GIT binary patch literal 4756 zcmcgve{56N6+V9c6*nZYq6o4U6fb*#GL0&oHnh?$ak{Yhl>i}KwQSW2Etv+=vO=e2 zT}$TsvZ@-I0_H8HS<4V&{IRzGkb+#HO`2g;9h<})q)MpP210As{j&vYknF|w*>~T2 z*P#Y4DPvgI?@NyFyXU*-eCOQvy1O5Z?IEIYw1&0;<(C@e<>P;1xFvvZ_rL?~x4b)g zv$YQOE)C?q68p^f5P6EEj@@>C5=58d`vSb(u+AC{#5+$vT{zu9 zrKF4}iHrbAxSmVOI6rLJB%?aHM#%6{O1DWy{pUbwKQOrX`G0-nP5spX4;p9mC!w!z zhf>fGbT4eK~M zVd3?YyA=Pj-x2A5R3G7}){cC!KoX45P4#`=?6m^MEA2hM^u;LHxycnd;8VHuP%cg=YJ5z;(NDoX`ZXEHhwwv2xbuNd9pQdw9_qtE zvMI~OOOOQ$5TAMdAoxl@;BS_q(;W8^2kS_#@0NoIu=&F)dN1ld0rJ>_ioeREO(5Sp zsymC{aEZ&Jz=+3Pqe2mP?d3QM_xFsK$I5!n7{tN_?P`w=ttTAL>rDeJS+26RX@F2?&QW?kkh~D zHpaVwYgYERt_ zACNye76>xP8-woz8RYw~TnsYEA82~$PT5`h*iUu+I6RAzJhtqd7m(1)az1o_!qcbX zukr=`X95^ZPCJOPd}zRM^oRTJpgkq?q5M|%A7%f&qvxa2zawU0`=>b&BgFsu5K^G{ zt9*e!9(dzq2O}EjCW5^0&uBMkn-WfcnWM&mZA z=2r)K(l0X`O4_4hVo6JlIH^<@_iuT6z^rVi@gUnxR6#P!u*Tam39 z%g*X+YbAcj+VZxSpJ{u`=m@)grlZ5{0hP!dAJr}RW0&YB^8A&0HjTqy*o!{t_Mh@O z_K#%5Di{;Ts_933V|G7dJl-Fzoyy)b+2500G8wI%Omt58*G>HR^A9~Ru>V@~{%iN^ z(T1x74cA(m`^MfK7`wKtu6b;#dFZHuQ%#A!iuy6=Pc@1 z)w{V#qaB)FN`B|3=`F9OEA_LLwUqt{^fut0H@w+HN{`9Du}(uW5UTqEA3k*H}*7FUewckbFq5tKPsIMw-#b2Ry(zj0dGo$BQ zk343z8U^9oMLnO@g>B?Jk*Wpxd`$jW*Ww3L{(``JlX3WkQ|7sEouBw-4)vQ4Y~Ecx z-imKEv^I^dlJD8ccfNP1ME3ooGy%>R)M z@~39Gl-&Eo-;8?Vlwoy0_+NBVjc*mZS?ZkLDhm+rMS%n@nG(-hzk}qR_w@CRzd>I^ ze~X7z->7_lS9ZZQf@;K1-1$@Cw}r8-U9Mw(1?S=N8rY+LNOaLUsls=``?vh6E++j1 y*WU*KuJPe{CNo7i1i+_Aflm-xWs!7gkNuH;=JcH+X^x$PL$H(leHq}k`Thq0IgbDU literal 0 HcmV?d00001 diff --git a/autotests/read/dds/bc4.png b/autotests/read/dds/bc4.png new file mode 100644 index 0000000000000000000000000000000000000000..ccd46bd24d092b9a5ff8160f03433f777b6793d0 GIT binary patch literal 2129 zcmZ{lc{tPy7sr3UpJl8GH)9!F#Drvt>`BBZjENg28C|kY#7vCk&d3%X3`vY_E|HQj zgvv6JS0m}oRmd_zVbWML*F*j)*iQrb>0$tUhQRBiMNm{Co-i zW`9KZ9|&NeXJC9nU+;vzshggGnZALUp`o^(o|&E=_P)RG{{i?gzo6@+e+IPrCMFI5 zZqmTWvNwj7l>D4D9E-j*kF~R6| z@#!92pNN|!#+m16r8CV>e~gVOTJ>`$xf9$?ZrpwQjfv>%8=LPf))x0k*Z*ZRSS>{T zVxu;Ag+?%}Ya=geKa6NfgR?0LA*V&Kgbx8b|8jWLY+u7R{{SRtKU zjx~&{J|gWspfAdF2xb=JxZSv!K7Z*(lUzp#jbm)e%?=H7!HdNORvO{+B;fDmrt2@D6|M3pIW-4O%(t`N?%ETNzk~) z$wXKXyp}(WRD95g0dT>UcH2nOia9g+@=?&hIz4kC6<*3;r3Mb1W7MDh$#mIxkys1W zW3v910rre^{CkKt89R%pYbFi)EXXfC@s*hbE(W1wo~8ivvSoqBSE31GtA+Jx8ou*i zjYnXVhS-ET8^AQl!3PhgL|;~^;|F#5vUkh9x4t;apPbjC_(1!CWq-=TS^-d(Awf~k zQ)-hzvf;?Gj7OIr4^3~aG>T63c(!)ieXfR+j(;5~##Dg)U5W6|L8>^-@bvVefo9J$ zUu*+hBd3#d zxP5#nMWb>|FGo_cfa?CjsG{{7N|G{(d<&elzex5l4L<7LJslwlkg|%sb{@3|^5K2J zJP8s&Wazv_L-i=fphrK2S;4O(F?~O*tQjL|a?~dP!M0OMHF-OtH`?_Me!4Ff`bvir z8|y@;P7A~xV&QR3XLb9)M45n76rQQvePf^IPtxdcK99?J7v^lnXn9BKDzKu1(r9l zaqFh*p%J4P!(pb$?=5BJMY#rslnz085BhWSG_RahjehzJ0KKmn0Kx$#r)ntkH>W*h zCU`PpodUnv63niK3p_^>4KF@G(PO)VIRFs4KwXWpq^JfDoX{703)C}jGZ?j1zOu5k ziXPgh_Zdltmn3J)>2NSS$A!Y9WN?>?w?iT&ceRaPuz{|tN#E_h@eA=15LA;%8mfyV zx&6?&Rbwk4ARh;Y3GOQ#TFMTSm3bTb^3z+Qaf1U}>O#?G^z$fxqEW-|TDAAKbVB}q z0j#ajcuEBIFxSz1D6m(s^E?I+VlAX5P~j`_Jxpz8FVo&S&EF##Bdnt{;$7h?@C<#` ztz1;;o1C+iHgtubZk|KLTD9P|K<&Q1AKK7krO16rnZce82Oa^jp2(YRN zGTd$w>2zS`+q6`EN}g=@3^oqLL?#Vc_$eUoIaUVuD8ZdXRX0Lt-y(C05AJ_CwQ@Q! zMcSyO+EV_m#=y;I?^xh!VO9T+3&|NNtnL+%EROm2qAxLCPB8aio&D5TmB=st8lm?@ zlCRwTwZTu$jQgnsCl^CYGls>jNf~KrU0`0DNdYeO3hn3v=M4vnYxXvAKjZe{iDwur; z%7_CBM(g+9=>RUaV7R$;NQ-hu94AX)YQ@oRIgpeZFD%2Qz0!B<^F3Ydep&6AfMxgG zGp5L;c)r!83-|rlwT1{j#V7KV$95Z_SpAo|b>0=SZu6 z1c0?7&uD#YXySOgum#&X>WsFRXq_UnykS0-_?L&LpLA5RVncg#R!54oF@3!?Ucn<; z?b2wTw-d`@H2`4OJguwjw$!9dzn*WtJ`@(q)B)l(w`;JUZ#_KuXacfcOeQJ`kM8dT z$uUg%Kb&s7vAesLI#d#xS5<(^m4l+w63ecJ%_j25+>em8!PcN9*LfdlirYNKVYg;4 zzp4S$XZG|}_t;7dj>RNG(czFxIb-Ipm+X@TTHWp|?I<9HRq925GmZ$In=)_v!*mxI z$j7!;4to~TU|XusJ11FOGu}E({Aca$0{mF>4}(1X7{;-CH|yT{iKa0q`zmpqk#cP! j=H=%3sI3!&(mTrA9N9W7wyfmfK?5i|XWOSXxZD2$JH^_I literal 0 HcmV?d00001 diff --git a/autotests/read/dds/bc5.dds b/autotests/read/dds/bc5.dds new file mode 100644 index 0000000000000000000000000000000000000000..b6ae4f046f96d14cceb0fdf6e281734c6b34f46e GIT binary patch literal 9364 zcmds+e{fXQ701uM-OUd}k~Kv@0kfu0kWSHPl_J=%v7ydqFyjn0)5rvH^(}RV+Qn>Y;o*t<*t1fiSdUUDrWIktfS)i0nAr&g8Gg7 zdPa#(L>>#YL-)$p)_lTSEc3;K(tNt~QArZY$;8)7|55X8f2-?tksr4zZbC5J z8ZY46Bx6~m=QHIQ&3x;Fr56nvg@ar(9W85_wV~7O7!Cz**}dN4_2?IkcPpxVf^oTd zMaDhq6F2_Bub=*Eo@&0xyQbA?@`ohbdB~_n$UUscSuyk~fF6q8c=y;xV@vFS^;ETH z{qKDd3Pk94?09$E-@Dtq`ZIUEU_VvN<(;o-{?YTy@t5IZ8|{$?AOE3+#zp+2x$zJ7 zv4&1_ZH1}HZ=+>YaDsAtFM))CIMs~3WzcHu^P176$Ui5|%}#v1=-I2kcRga?V&;+~ zrY1SOMD(wjAZ(@x70n|-3Jvtk95{=i@v>o$X%PF{wURg*X`-)5L zm&rQVh67$EdR{QWhK{-e&%GNv&0y9p?-0a)p$qpbl0gpft=2b32=SMnJRanl5P#?7g+Z?Q)$&)mxX+`o zb%{K3-ufrKwlQfo;=1YlzwZ3{WQ6#*#G3AX1yYda6QY0Qd(A^?-Le&Dc5pPW{@(S4 zxK9MoG&#BDL3o7XeizSI#6t&{IJtX%&99t)++Ba-4b3}Wrt%MKJ6Jk^=GEWp{}(qe z?>99$;ei5Pn#}PJ@<5n05&x&!umlkQYs8(DSAXyNg6?=Q8^QkGz|4kYrV}hSgt9^B z6gGZr{rs_ipuFh~Ic2_+|u{t^Ko9d+cm~ZbX|!eH2jsJXo9* zPoNCdf5xay&hALg_M!g-O~N|s@ry_VTdeL@aKpDn1ds5sxzg6``KGirH&o5BtLDJp zrFXvAf8DwV@!x4;33&C7WeLx_ikdYu$jd?>P5B&_0y)OkR?J!}>L1DR=ARYL#{IK5 zt|NXi#Bb>2|7sFv+hr~+6|*wv-9{1ayUh6|t{r{p`_jJVB5CiP7cW>H?>1-og{tMz zUtGxwRo>({MMcnc9wk+IW zJXcdF_fcPstmA5G#8oExyyP`1k7$lJ|HQ1l^S28<6=mIn_;l-_QO{F9?I^a>*6stE z1rqZEhXU^2B2D$y7(VxYPqQ#>w+{E-H>`>Hmg5_nV)z6u zqW;-6Ek|!X<+Yi}@;IO3aK|%GZCJg%m$$y1Jka=SQ|ft&t#L!zE z$!A^tJ59~gs$NPdo<1#fCrYIxCv1Np>x|T5ncq%-(0k8xwA5mmrzhOMXS_Vw);|S} z56ScFcu=gWw!1W6e6Tz_@8|o?gX_vZo!2Jo&l$xbA4mP^GM~QV{oa1Tw}AN*{NAPX zQKW2N=h3Qtci2_do9%bo*Wl53n)%jH{dI`{XeXba@H59sF2a)1oUlIsXZX_a5E-lYyR%uU-6|l_yQ)pJbqME%Eh@cy4*|sQq+Q zejl&i`TXsrowLO6+3kuQZ{EMB9`@$L-`IoSznBB@Cnvck;tAnXLWn2)Q%d8tKTM0~ zjQ`<_9kHJd@(yJ} zpKMgjr_UGseJs0Za0T{3P2|gXAWD-o``H8bpONA<-QUp{SG(6)*qayZ*rtG(0_1|Ck2D6&0F&<4G`vL9?XB3Ul3i**bah&8A ztmg$^Kezp%G%V($8C*OaChB3$xjsDTNbsO!Kgl{rGedz(386niQ}~B7B>6Y`ja%<% dX2?+fl04W3e{nuZ95)pv`jfoi^UZU;{tNj008an_ literal 0 HcmV?d00001 diff --git a/autotests/read/dds/bc5.png b/autotests/read/dds/bc5.png new file mode 100644 index 0000000000000000000000000000000000000000..31d89c9479f9d37f6d2a98df8e2984dc2a448005 GIT binary patch literal 4478 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 literal 0 HcmV?d00001 diff --git a/autotests/read/dds/bc7.dds b/autotests/read/dds/bc7.dds new file mode 100644 index 0000000000000000000000000000000000000000..58ac3bc6e603916b9158a1ea2d81cdd1d2db8739 GIT binary patch literal 9364 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 Jp8ull_kVYKXUzZr literal 0 HcmV?d00001 diff --git a/autotests/read/dds/bc7.png b/autotests/read/dds/bc7.png new file mode 100644 index 0000000000000000000000000000000000000000..ee44a5d20a6435d3fb2674ea1f986bc08f9ae496 GIT binary patch literal 5350 zcmZ{ocQl+&)W>J_5SwfMS$J3@QEt{a14Q5=5(2_-0b!{pa1o@i2vSs(4-QAd;U+287XL@!>|$ka zm^Ans2M7f7&mPd04H^Y-Q&8FS;HXn&Y3n zB~QlAMp{5c!bwIzWLPO0evG1F6IRHqPsEm11Wl{%G}K;du0~v(6_@RnBCB7F7QWK{ z^lIY?Jtv2UNb170VK7096ftOL0Gh;mfO-bcoFUl6>f<5k7jEyzKcQ&i~O?JhWA00WE&2G=e@s|0@_Gn|Y8rCyBak18oV1qP4!Lf=|&=QP|p}*lE zs3h|0DHz}zu*w(7!DnhRw79L9uCsgcC)&arlNb@6j?5t~%MP`0+dd!L2Ue*HE@ltlE5y}kVs z87b+HmwmSZw>!+y2b&-)X=%_f;*QhG#J_1O@FqP4h4!a*=wclAe_VV7TsqJVb^e zn#IDs6m5PE^9#tx%p@cwwbBtO_+1*U)kabF1pwgd>&q=5AfB*NYx?zPb~eZOwwH!# za()X_W_C8-RJF@BRK7@90D%}YHZtPT*VliO?ylkI=NBa+L-kNYL)d4}eA<0LX1v0d z(!tTub3Gy=A_bJVOESA77q5n>6!e|v(<$fEn9@_?AN+$RG_oYqgl*I?1hWkd#e!*1%;gMRii|CIeezv2}D~<#7>hBg- zV_OA`F9gASNQ}juo|*U`DKDr7m??-!$;jR%B!s4>G7PP_b&0L(1G2wUa`oQ!Lt)3t zVJ^Bup}5yqeshRQlOHc>MRtiYz5HZoRO6UKdRDSOh}tqKuV~|DIG&z}rj#}uqjMny z&OX!SU0n<&zZmdQH;)?AQrSqHI#OVULUVIr-L4##-59#eNS!qWJMye$%7SLfhBIv? zD&?U%hf!XyF*9$Ypd^N3TGliSGSE(WJuPuCPBzQTr731?)|kBO1wLR9Q-VM0Ak zC{S9@J_}0N`7<}56fH} zM-*k0!LOO_B=M&?2G}jq*1Z!y=S!>(cPpLe(t^=&VVn(E-TC;}oYx~T=_k<8L7qQb zFUb3A-*<-IeqLI2lNG6-mP9@;Oi+HCa67!XsK~8y_4;xTGj9-dl{4u9K~5Lb*c_St zI8iXI`)#h$NY|vIriGtJG7jkJ>Bno`S6`_m^|SVLCa0E#$iXxWM2m9FON6L}vB`1Q zUL`b`)XMSWkVD`1Wg5x+JSH`+7Lk|>yl$$A3`$V5qN+abb>e8MXzoAnKl|~+K6;Y1 zW@ZO#-IIKJTLbP0D1vX%)33Pq>jlWN@>?nY`=%>tHU=ySED2P`mNBHU5wBB&bMh$+ z(drlF#-)~z9`%X*@Uvet?^aIfA+(F64w99Cv2M-&86Djcmb^UXU6#R`n3?M84)KZ_ z4->f}KZ#bZ68AIjZXk~&oo4HL8Qu%YjU!Jg2-i7S{fi646;Q|ttOoI~=6~B$m;Qfk zPhShDN@7=x7KWnIFqV@NmP34c#@b?ZZDa_DUwH+ziGRCNpJ8jU*q|&U-?=c&rO~Lv zgEMf=mYt$keZ^{YOIZR6fAvTw$vMad&71UP1OykD{(&Rb}GO>1Vh z$`VV>sj|kRl0RIS_^6#o4Zu~Tr2J1@4N@>2IVB}A2?+@!?kPRuPt#sFfzd#ViV5>S z_NIy_HM@=H9xlyW6BWd~9e7r(={USniN$?Kwa45zB{HU>UP^D_Pdz<_wa3dbHwe)#agf``V!L1B>`F%3W}(sP4}@6I`<`{b?c89I(xDto}5?c!H2 z)I*%JK!BShV6HJhpt7=37Wf>`c)K`pE^lsZ)YZiqi2wfW@gg>ia4AY1g+dvm>=#A; z5hO7G2Ey{E#61K{01Jr{TVY$)v3k3ZMJaEO6e4!)!MTdVQ@5bM&~PL`n=@eHwje#4(~N_J#;Y?ZBW=kUVP9N1JS5=K29 z>Vfs1_2n8yVoB}H4px}z0DGUkpWElxZ9{L@qN`%I&A-8y`gCnYblbG&%(p}d2=+{V zM#e>f`HfE_qxemrz&Kv+{YGMt#E=(B>REo(B=ssYG+L}wpH3OOF{&Y>-kh?WXkHa{Kv?{}jAgtN znVlEdtWj@|&Wo+qW~XO01q(CHbnq4>=TwN_RypR3Xo=EZ-)d{7 z9&vtgI3R4^1d5p(t(B|@T_HO6I4YGTjRzs7?VW*S0GvnczMFKr?awAAO#LV(Cqk*F zmV{OEBf6zU$ww_b%HNJXj<1C9g<$q;B{Av_`oCc*N?# z3Q}W*jKhWyUNX6EmFik`;* zy!P%ot*Q1__8MgM*^fbM^fcM$wTRA!`Q-@iI`%h@=6~Lh^=bA^^wSz4c!yB9!zx(` z_7-Me9y2{;VZ4Zqizp_X@tSh}55o;P%7B}j`vjJI+KdP8AC2g7^YB2Z*-cI2+boHx ziB|=Jo6wReP)`&fz>|z>B2Y&DUEprpl&jXD4C&6Bm4i^ z=oiln)q0vop2F&^0>5&S-lq-|>rKwpKGs?OjiZQmbFO-#KCCu(*wa~J%BQm`%dFmO zABXF2Vip_;N(A@>8bYpcm4o|&?UJ-sJOV=yk$i?iO}Z~e=J8)Gl@g%j_ZkREQR*DJ zWNm;(?aV)3@1hqE6*(x#pj=poE=)hndz6M2ZhsHA_(d=SGq-WtBsaectS|i+5`*0A zcG>18Fi<+dQ2&?2%zFxZ9lwMUm35WGGDkyG^CXqawDHIMav&813WMUog$Cin>mGHc zU+>E^S^6I!-1jg+h8BMAqEqNUS1&8spO_5Bo1Ec;XMv~I;yZ1(o|~d_Md@n@2?^_N zlT-Y}P?Wz8sH@wNA>~w^E0C_9aH{BC>t)Jhl&_e1QBC#kJnj(sJgj3$BTbY(gP~Z+ ztyry-WbBGYGp~9ogZ2mb*wxX>m^Z)@tNn-NaRLk?2Bo7*BE3gZ-t1BD*{#s_IDbHb zCkNG+V*pt^Z=EkbK-Ed6^(8OAl{LqgWR8=HE#Iipu5n!!t8V|dv4Qk*)XZ>bsb!kU zQ-s~D7g?w3jz>*?pM&l`#6FCyE8z;XnGx{r#0AiM-kW}OSq0p=pUk?$>>|@$eIv)j zcq|_AQ#pA;`WhH)ExK~YYqT|&wg=RV2YXe2FPQ2Uy6Tq`GJc8N3A;x(H(0bBEnotc z@tbz8O+)Hg(&EB;#vt&|oc~+~BELSTrAl8%5{X>*NE1JwRPZiSLlU3@7*R2;x}BX` z&5>^@LyvwJRy70%dnFF)_xD}u4LPY5%Rm5y;Pa@dLoOAai(=ZYu(FQ*mRs{jKLnSi z^R*wSY4k)nnZJW6w3YV-t#9~wlVP`~ZULQF|FW65-Xy>MY$j%J#61>ey-+9P5;}>G zc)kySO3cZ^SI$rI@xdl84Np7#IsTqqZpvL675Ik#2C{djCB%mjdt5w;LT#h-k4?!z zW@94@r)r#4{I+TUN=P)vl102lgNw~@f<4MGW~~?v zo-3QDRPXrOD*qdD;jIGlsKpzgX;1h%xaAzNG_nHmS&4n0cT1u+Uu8vO?ZBhj-v3u! zjn`@)XgwM7$~ZsbWJq$QxJ)48%-RL%vVK%nhs zWzg=n*l0#*Lk8@8UVHf0+yVVN@nGJ$9h?)ZJlg+-gSyA4W<{LZ~% z6Up0NPal6c6c9!rZgn5<%iO@Fh^ksz6sCd(X)Dr8=l3ohnioq6sclLX>#N1MIA-+v z8Pdq?SJB1vDvnn5{$bLV+P-|jA^)8V-0Nr7^^2d1$Kej`%t(*U?=P2B#1O?Mm5DF4 zeeWvFj*1o4=kX?PGoYLgK8skBYJEZ~i`w)K##xDXU&FS%&P@r*x5K03jOlhRenpUp zM&c+rma1cH{06sMmRD9hqemIbFjsz>>5|kfQIs7xaA_KlRZTdliyY>}QOxKC&i?e} z1NRp+mU1I_|Nebv zSJ%F(tcGatY?g+qmlA%e*F%Xka$qCHOtI-$){sm*&j}=b50>e{YcB1KpFRi6>OKv# zve0P4!ootk7cW$Bi!3f7k)4$ViH(ij^SQ5|=}A%cr#ad^E(D+Wduyu_c5{pp7ibDf zO9??zN=gOJJKR0aa|6M*9XXv?@x*(NjGeJl3Q5+1upi#qSd!2>)>nanjpBFjeo?89 zchJ*I)V|?{s$vM8lbK@=c)Px~w77WjJ3lv9$ItJqNN_%c3HgAGlqkq$h8wu2rKPR% zQ40$T%TI;y6=OttT*7w9W1^!gp4DbotU85>No5<#?)LK7I1heGZkGY`JU?EXBBbTy zg2;nqK)*`-XIRq>unDAGg2b1VdUEK(%M659$f?J`K?Sif0Xz>|wZT$F zAIeO~gP_vJhG5jT2DL(^JIgk9-ni+Bn&Z}u*;uiNbX7I4E9`ZiCxH4u7{To*wyk^=t01{L7P!`XdVxJlE! zj%_pu&+6+2kYtaoWn}6UQE-#$Ll=~9gYdP%bp4{ia>$UM>_(2AN%mDCV$b?RJ<1%& z#_RvFMAlE@WS26j9}Z5)M3eCPLJQaLqTa#t$-v!XuRVTbqJRH>5S!L)Q-|6Qw9+S+-?wdhvah|Wl@2dsEEfKYUyoD%@G^(O zi02+hVld3^gC4)?*BFu2u-gKC5*`S^0~g_e^&1YXi`w}1`k@Od2-o+f;|A3{n`yUh z0)b$UFs20oSEDY{Ku&RA7qU)qDpM3~nyfuH_xN^&<5`qyk3M6ME%7Z$_L+7xVtjl{ z()iO*vOP+*$Hqzax$^2NDbb$QG=iptnUD z5icY{8W76|-8dh((0cHZAHJY2yYtkoDy9_2Zkw|E^ryQQM!s>pCii&F2>e;M-GcLz zIG>pL%vY6vQs(QZoqz!OXwO*+6Ou%F_P|L%M(C-0R`=m(v}1Wdj|b28tuox@)p# zjKn|g4+j6}_V^Z;G60BXk(EP|AxPo0PLA+9;aB22P{wH!uR z40~jE(v?Z}$eZt-oA34J%N<3(I8t;YU*uYQAc%j9jcxlMYU90bWMN2rH^-m59(mV$ zz3UBotJldOB8}$wnTW&})82vbQAA<93e%@Q4u5>W)U0~djitIIak_a9NG%+hU<05wBDHksqNO`Boyn|CRWk9DikxVgr00 zG54RM=L~>{1M=@PsQowgLz-hV*)%_seH5k#ZBG>Ar~Zi09X4 zzNhCupae>XWBB0s+YI--2Ctg&*Ql?U_U3qFQ5tS?te!Q*h!s^;49#HtzxD^qzu@x* zM&E*CwxhOuu(lyw%c-&Wo{E3U{-USJj3NEmTwgX9k6$DKz|GWgy+?26^T;lvnf=t4 z&ED7^kQ!ff{sE=7bU2a!dGW!Gt*=w6Rc5{9H=r&L-ZHkO<{TH=#jZBm|7 z%3JcI;P=|kPw{bU4{@xMlNZUIzidBG`d^ehcBy&xrp}Ce&yDv<)lU+=-n&-Hxb1L; zkCT^k$igjV`xpk{Kc4?2<8KYXGDGV6xti(6*{A&< zHiTiJMTGXeqV5DpH@=v(c81^pW)9)cRW@3{VEWabT7V$TQ`5gR@nO;tPd~N8(+MIei)zURt>Mj zt!!9&rfYBTpl0+(77t7I!iSeXqQTOOEA=KFJ?uThYp`0kUm4{a%iQ;8Xt4Owl1odX zD~BD3I?JQ8Jasmfzg;c-|48iz*I)i6z$>`?ctiTsboNF6M-7n>(-n=X1B$A# zI{r!Z=2-pPrn#mn;eOfS|DTKgE${gUKX4)Rgf!;!_IAI->dKM9sMva1o;YNtaxfr{Hwtr-^vwFYuT`B!cng;G! zMk3T2uRfmiZ<4#kq5*rK(JvKZ{4JWm?~2(UX6zDU$G>|^$@f`ZGG_>* zpYNpRn1AEFPOi_@ae0$mCO;(VKXL!p`Nw*X3YjW=UxT{oPu0xW%ko@{tAB_=TE)wh zCS9Ja6qy$oUqR2Dqhx`ug|t zA38aBGu@%A`Gs;%uJ-DWvS*EByhi=!z}R4S1bVR-j*dTBkfikxI`LW1tt_2KRfK~Q zlDg~rcjNloYkgS}QeWcB#xGC1i=5xdg=-waslT>8rzOsh>b(tlJGA)uQMy|F$&$RA zDl~|nPlxaQl?{(?)`zcp{1MMr3VC?G=J@>1^!qIn&G{nP!A9R?oA$Czt)gwxtwAI< zZs2@FE8m2T_7zl_o4#VaN9>2su7|i(?cdjNDEbM0-|)80C5X2_H0$)>+J}CP-ytrX zCsN-z(*do`(Ck-!UIPbDeK%k2DOWnmo4BWTbO{eO=3g~F*BJk)YJ;jYs7(!OT@HkD zihU}SDzK~xxVp(=+aEvmO`5ZR(xulYjjj02l$p2lNL={i`acb(eFzcPJ9jSeqJK8t zqm3uF?10ll!UCvsp-AV<--xb$;DC$bReNF1>ve=X(@;P9^XD!tow;Jx(RwH{2rOd`ge!Asas5bx_DA zY?^)g1w-AkDs^;i9U<%-_a^Nz{C=K0Ok@|2~|5HwZT%Gat;20Q?N| J{1=Vi{{fqhXU+fs literal 0 HcmV?d00001 diff --git a/autotests/read/dds/bc7srgb.png b/autotests/read/dds/bc7srgb.png new file mode 100644 index 0000000000000000000000000000000000000000..ee44a5d20a6435d3fb2674ea1f986bc08f9ae496 GIT binary patch literal 5350 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.A??T%m?_QOh>TPDlh)w8imzel=6ebP3;AC*YDuA^;4#YBvFi8KGD3)jT2O2S@<-gtUqX2BS-=(F0R?nlzbw)f=IIyFLoywSL?do zbV#!wGEMM;9fJ{O{pdgT2D`AL#n-lhb=l(|AYD`yao*vChnm+Q{8IC%`)v zx+_Dp(C|yXx(Mq;(|at@;3*nBg$}!Bn_tr2E#6JsiggOQH+c6>#H%_}__F)>xxvv6 zts^?O%`EPM4sOXLk_k}(Z-g`J0gq*dAW+egNy| zoWNv&?cuS>0PCl@5FTUy@R%55yBG@#_HPzpS%bU_wsXC(|1%}%3+ujGT9mPjZsL-m+(v`Z-JZB08^oKcPLbG?D z^u@E0H3$B($w;N3XP5scdqb!w9+Lk}i@#b|vsYzYU9HM+Ja?beY|H3Ld~@4#(0R4W z{ky-vx0m_#iJmmklZFYwEB-PL=qHa)3*p7aSf5!0#L08jndW`dUU9fqt3~qnd*aw- zu)_(U$qOTQ`vMDf@XJ@WF3^EozwH0n-+ZH%*X#W(?|ZrkKPMmNLjn2q3ARi9%V*Wc z5P!+X z`85lLLfHX^LLtUlmHR=k!$d!n7zhN2rrK+A{$K}5`&2tM>_?=1sy)}R=Nfjew9kq^ z1V`vUv-P9&OcW6*;pz?a^-KAB;E1cA&{58pvj6b35cPV!iTQ(mR|N?A3FZ&_H`ES3 z*ni`^qnB{MU_C#@=jKH|%md{DJrl*DpT7>Uzh#7usy^fLSNZBe{VvAf-*sUyy7wC) znlNsp9q9sk%gY8oPmL>a-B~r*2;xFrcR{W7it16loAI|0OIxn;? z)Yo^zB9xbnvzwJVsdU%R?6HBsr@xleeGi3y^|r!~9F94uZeO4$$&gLU2BaQse)eq7B77{)m&b+jH-n^V(eBSX1!oJ+-o94%@5qZAl zA`vkJy*$z^BreDM)D)f(f8ha+LnkEbajM;&?-J@Vx^wkYp+VGd+e+psiiOMG5BOfh zs(avtEgx&yEO_3@{Rj2Rb#00|ed7?)jy^ezmHGY3#m^}o1pOR8v7f>_Y9ff|!wrlo zyF&gQ=Eph3mP_+Bo^`b@x&3E=`7c?zSZAIymtWsh8tA7-#~oiNMiua1g8Py=BKaG` zIJa51!_My zINq2>PVBw&(TA=69VhnZKK#5kkKT1ZMhDz{d}|+(-}YNIdURj0SVr{^JFJ(hVV#bj zu`CO^JAS5EEMC=5{k~3bA4n$m!|$Uf`tav~MOar9t~=b<+z;yxFJ-6(oOkhc{eM6o zFphDb=lAsFyNpQtcU0eS?U&x)m7VWjIQL#8YK4DWxEb$v`Zm*?-cz9k{@1I#&JCn} z)qU~(oA<+g_)kW^#O=C15gvE%*L)5gM7?mIiQ=Ba=cShuCdQpZhJin&5N+3M@^@#x HLYV&tgRCjV literal 0 HcmV?d00001 diff --git a/autotests/read/dds/rgba_bc1dx10.png b/autotests/read/dds/rgba_bc1dx10.png new file mode 100644 index 0000000000000000000000000000000000000000..bd321557fc08b40c556bcbf90e30407923a126a8 GIT binary patch literal 4727 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 Ze*|^%va)QpI{N?s002ovPDHLkV1fo!6!-uD literal 0 HcmV?d00001 diff --git a/autotests/read/dds/rgba_bc3dx10.dds b/autotests/read/dds/rgba_bc3dx10.dds new file mode 100644 index 0000000000000000000000000000000000000000..c097d7dfc2b20b2a8aa63b1335798de84d4ef0f7 GIT binary patch literal 9364 zcmds7VQduF5uV%gnWGKyQh7NeL30VFHdhd)#S*klSzEReBLjE#oex*IxQd*np-7<= zwGobVA}6(k{5T3Gq@~0%iG)pQOrfo5WqPVgf*U}h;wUYW&!UlVqNY|r>ZRcGbY|CY z_wAb4vJ7d;3QRt~x!IZT&HLWGcd4mq47LNnEY%OK^e_K~QvLzpp}$YmtqU)!scGCa z+iU!8vL8VjETF$N8&_1^)lQxG+jaCS;hEoOK6O7Sr9Vhd4?O_)7oRiz7l`*E;|~E4 z7u;YL2;W>!fg#clT_-&7S&ox&I2Hpu@E$`0dpu-+Dr}_0*dFSX3*+{{ z_WV95qR+>U(3O+bD17^{-T;} zigj#56!WbnBPSXnGG3;U{rGtC8)|Y>EEW@({YB`JF_~NTw+^YvN|*h1$v#V;*S<>j z=fIe+=P!=zjK!iC5H=`}Q)RP%?+Ws7l_@Ga<%v{lq8h zgRmbgNZz`2tI5LnkF{&otRY!2{i(?u)gIXOKjvFN_Hi-($XG!s*>?yW=yUnco=wR1 zcYXb-@TW3>a7R;xvD1RmTW0d|i>*41&Qqi{N7OOsaJ;?Q7#3Sno zectF#9?<%qm~W_^mV?DlmiS+|nCcUBr2>=$+xxT*s$`)DX1_V1AKdH-k`b_;G-(}e zg8vnV-mH%{HA(vHJ`_&tqr z4dC_8BAhB2NKu_HxWPvT!8h~Q1})7tPDNuR@HTexZ`6a-pS&;vpwNWb_M~Rg{*ddZ zmq~cthyq9R`Mj_X_OJKok{2MX>Y|~4xkVy z9$1}H=5s$o&H;)=e1`vclNBE#@h`2fsr2U>^$)aMto6vw<^9u*{nez7(tcfD{q}0v z-i_6yzgo6;*P|PAza`td_kTC${YtjyQjp^@_;Kj1Q-4hTx9gw#zf4C5^-G`x;i1GC z;-AXlGJ;2iSz+Rt$d~rhm2}>T#_f7nlfCuM_2sO8cfNdDk?q}lyYc@U{}c0_Tz@S4 zv$Ppd@~hsW`XqwzfG5nC5>v0Q>FLkkuaN)Iu`zo+k=&%yX@PnD#fplGWSk!z9TgbS zUmcVBRRjBcK6`w)D$ns-`@6py9rnXj=(0cNuph4KaoP8{>=lRoUFu)b+o|+tqFx1| ziS_3c1i{Ds4p$^t=ZlH!Yr`?8{uG^*_ZPSQ*XTB9Y-~)@GXSE$R`8Xj_YwWp{Q=Jh z(f_HoCw`>)cb)I>6y0Cg{SV>+K5tIKr=dSlgo0L@92M={JYmzd=yIN9ktJ^U%m}$t<;}<={EQy z5*{1_y3F9m>`#7{hjN-M3nP|>BT~PFxJWN{U?o`Vz#dh$=YFhM>aTcx%KjPCVzl0O znAW2l53f(3aUml5cdAc^{!slp__<5{Lq~>aF6@MdgJ;N}p+7J?1+(|keI?(=f-3T7 zK3kewr1_Yh{=74stu)%baXz;UjW&~iYd)VncRC{DCy(x^lJOHiUa?xni=X+RT*ix@ z><-FUsc2IZoe9gor{po{?CiAo9IgVt+|LZu&H9Q#_jr6$VZ`C8$@OG%{mBxau^qM4 z|0I-^X>TddC-GCj{eP0Clw&dat8r>@0u-t33CVe@jos z`I$<8n(6%293ef2)?KA*uN(Xq(ge8A!${u_c~+o*{6c+qoE_|#h+HBRATmRkq zgSf98>40Z_9!Hy<=bO_J8NZhE0!sR6R=?f<{;MMBIKTA-gU~7I&C?~|z>DZGIV_D+ z{ewrsy#CR#KMq&P@o>Gnu|}0?=QFwfWU+(x-^#_LH;@Kpl~MnoRl50hV|zWQNnNM+ zg~)-T!eQKSq^%<(?Jvu@|B?1r-mmTZmgP+Ea3O>ehNMN_U8}s`pe(Qbics>Se!oN{(Qod;RKl{Zv^FM##Ji7l0?<%Wj zeWClGIUb@w>>sAyOob61P5J9m?;KF{30GhUt#+5fhejeM>A=O1s_e&M}4qg3w?uiV&Gn#JEx z{riaU>G3_4Jwl=C-M#luh+B^YHigr4|4okyf9)UGbGuEm^eK;9_UAp31~EVX#NReR zh`&%V_m}@s{LXRoHa3cQ^Z4EUYxGz~;2p=$?ODF{n{nd1AgFhhzBclUXYui6 z_nhyk=VMmNTX%rg*YLjhCLQSh+nA3mo_}%M3H$r6JZ^nClNprsvpXm23)k0l@EE@R zemowx{4vgCG8Ue$KezoDo)DJ|@+WRYyMUdg>-&j;ynNVH|(#6x5rPop8pGLSraP& literal 0 HcmV?d00001 diff --git a/autotests/read/dds/rgba_bc3dx10.png b/autotests/read/dds/rgba_bc3dx10.png new file mode 100644 index 0000000000000000000000000000000000000000..9b34f21f370cae44c22e01dc51ac233f4e936b14 GIT binary patch literal 5385 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 literal 0 HcmV?d00001 diff --git a/src/imageformats/dds.cpp b/src/imageformats/dds.cpp index c636c32..2a4c5b3 100644 --- a/src/imageformats/dds.cpp +++ b/src/imageformats/dds.cpp @@ -128,6 +128,10 @@ enum Format { FormatP4, FormatA4P4, + FormatBC4, + FormatBC5, + FormatBC7, + FormatLast = 0x7fffffff }; @@ -391,7 +395,27 @@ static const DXGIFormatToFormat knownDXGIFormat[] = { { DXGIFormatR16G16_FLOAT, FormatG16R16F }, { DXGIFormatR32G32_FLOAT, FormatG32R32F }, { DXGIFormatR16_FLOAT, FormatR16F }, - { DXGIFormatR32_FLOAT, FormatR32F } + { DXGIFormatR32_FLOAT, FormatR32F }, + + // BC1/BC2/BC3 are the DXGI counterparts of the DXTn formats. + { DXGIFormatBC1_TYPELESS, FormatDXT1 }, + { DXGIFormatBC1_UNORM, FormatDXT1 }, + { DXGIFormatBC1_UNORM_SRGB, FormatDXT1 }, + { DXGIFormatBC2_TYPELESS, FormatDXT3 }, + { DXGIFormatBC2_UNORM, FormatDXT3 }, + { DXGIFormatBC2_UNORM_SRGB, FormatDXT3 }, + { DXGIFormatBC3_TYPELESS, FormatDXT5 }, + { DXGIFormatBC3_UNORM, FormatDXT5 }, + { DXGIFormatBC3_UNORM_SRGB, FormatDXT5 }, + + { DXGIFormatBC4_TYPELESS, FormatBC4 }, + { DXGIFormatBC4_UNORM, FormatBC4 }, + { DXGIFormatBC5_TYPELESS, FormatBC5 }, + { DXGIFormatBC5_UNORM, FormatBC5 }, + + { DXGIFormatBC7_TYPELESS, FormatBC7 }, + { DXGIFormatBC7_UNORM, FormatBC7 }, + { DXGIFormatBC7_UNORM_SRGB, FormatBC7 } }; static const size_t knownDXGIFormatSize = sizeof(knownDXGIFormat)/sizeof(DXGIFormatToFormat); @@ -486,7 +510,11 @@ static const FormatName formatNames[] = { { FormatBinaryBuffer, "BinaryBuffer" }, { FormatP4, "P4" }, - { FormatA4P4, "A4P4" } + { FormatA4P4, "A4P4" }, + + { FormatBC4, "BC4" }, + { FormatBC5, "BC5" }, + { FormatBC7, "BC7" } }; static const size_t formatNamesSize = sizeof(formatNames)/sizeof(FormatName); @@ -972,6 +1000,403 @@ static QImage readATI2(QDataStream &s, quint32 width, quint32 height) return image; } +/* *** BC4 *** + * Stores a single (unsigned) channel. It uses the same encoding of the DXT5/BC5 alpha block. + */ +static QImage readBC4(QDataStream &s, quint32 width, quint32 height) +{ + QImage image = imageAlloc(width, height, QImage::Format_Grayscale8); + if (image.isNull()) { + return image; + } + + for (quint32 i = 0; i < height; i += 4) { + for (quint32 j = 0; j < width; j += 4) { + quint64 block; + s >> block; + if (s.status() != QDataStream::Ok) + return QImage(); + + QRgb arr[16]; + memset(arr, 0, sizeof(QRgb) * 16); + setAlphaDXT(arr, block); + + const quint32 kMax = qMin(4, height - i); + const quint32 lMax = qMin(4, width - j); + for (quint32 k = 0; k < kMax; k++) { + quint8 *line = reinterpret_cast(image.scanLine(i + k)); + for (quint32 l = 0; l < lMax; l++) { + line[j + l] = qAlpha(arr[k * 4 + l]); + } + } + } + } + + return image; +} + +/* *** BC7 *** + * The decoder is implemented following the "BC7 Format" specification + * (https://learn.microsoft.com/en-us/windows/win32/direct3d11/bc7-format). + * The partition tables are the same described in the OpenGL ARB_texture_compression_bptc + * extension (the ones on the Khronos registry data format page contain errors). + */ + +static inline quint64 bc7ReadU64(const quint8 *p) +{ + return quint64(p[0]) | (quint64(p[1]) << 8) | (quint64(p[2]) << 16) | (quint64(p[3]) << 24) + | (quint64(p[4]) << 32) | (quint64(p[5]) << 40) | (quint64(p[6]) << 48) | (quint64(p[7]) << 56); +} + +struct BC7BitStream { + quint64 low = 0; + quint64 high = 0; +}; + +static inline int bc7ReadBits(BC7BitStream *bstream, int numBits) +{ + const quint64 mask = (quint64(1) << numBits) - 1; + const quint32 bits = bstream->low & mask; + bstream->low >>= numBits; + bstream->low |= (bstream->high & mask) << (64 - numBits); + bstream->high >>= numBits; + return bits; +} + +static inline int bc7Interpolate(int a, int b, const int *weights, int index) +{ + return (a * (64 - weights[index]) + b * weights[index] + 32) >> 6; +} + +static QImage readBC7(QDataStream &s, quint32 width, quint32 height) +{ + // Number of bits used to encode each endpoint per mode (RGB, Alpha). + static const quint8 actualBitsCount[2][8] = { + { 4, 6, 5, 7, 5, 7, 7, 5 }, // RGBA + { 0, 0, 0, 0, 6, 8, 7, 5 } // Alpha + }; + + // Modes that explicitly store P-bits. + static const quint8 modesWithPBits = 0b11001011; + + // Interpolation weights for 2, 3 and 4 bit indices. + static const int weight2[] = { 0, 21, 43, 64 }; + static const int weight3[] = { 0, 9, 18, 27, 37, 46, 55, 64 }; + static const int weight4[] = { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 }; + + // Partition tables for the 2-subset and 3-subset modes. The MSB of each + // value marks the fix-up index of the subset (the subset is in the low bits). + static const quint8 partitionSets[2][64][4][4] = { + { // 2-subset + { {128, 0, 1, 1}, {0, 0, 1, 1}, { 0, 0, 1, 1}, {0, 0, 1, 129} }, + { {128, 0, 0, 1}, {0, 0, 0, 1}, { 0, 0, 0, 1}, {0, 0, 0, 129} }, + { {128, 1, 1, 1}, {0, 1, 1, 1}, { 0, 1, 1, 1}, {0, 1, 1, 129} }, + { {128, 0, 0, 1}, {0, 0, 1, 1}, { 0, 0, 1, 1}, {0, 1, 1, 129} }, + { {128, 0, 0, 0}, {0, 0, 0, 1}, { 0, 0, 0, 1}, {0, 0, 1, 129} }, + { {128, 0, 1, 1}, {0, 1, 1, 1}, { 0, 1, 1, 1}, {1, 1, 1, 129} }, + { {128, 0, 0, 1}, {0, 0, 1, 1}, { 0, 1, 1, 1}, {1, 1, 1, 129} }, + { {128, 0, 0, 0}, {0, 0, 0, 1}, { 0, 0, 1, 1}, {0, 1, 1, 129} }, + { {128, 0, 0, 0}, {0, 0, 0, 0}, { 0, 0, 0, 1}, {0, 0, 1, 129} }, + { {128, 0, 1, 1}, {0, 1, 1, 1}, { 1, 1, 1, 1}, {1, 1, 1, 129} }, + { {128, 0, 0, 0}, {0, 0, 0, 1}, { 0, 1, 1, 1}, {1, 1, 1, 129} }, + { {128, 0, 0, 0}, {0, 0, 0, 0}, { 0, 0, 0, 1}, {0, 1, 1, 129} }, + { {128, 0, 0, 1}, {0, 1, 1, 1}, { 1, 1, 1, 1}, {1, 1, 1, 129} }, + { {128, 0, 0, 0}, {0, 0, 0, 0}, { 1, 1, 1, 1}, {1, 1, 1, 129} }, + { {128, 0, 0, 0}, {1, 1, 1, 1}, { 1, 1, 1, 1}, {1, 1, 1, 129} }, + { {128, 0, 0, 0}, {0, 0, 0, 0}, { 0, 0, 0, 0}, {1, 1, 1, 129} }, + { {128, 0, 0, 0}, {1, 0, 0, 0}, { 1, 1, 1, 0}, {1, 1, 1, 129} }, + { {128, 1, 129, 1}, {0, 0, 0, 1}, { 0, 0, 0, 0}, {0, 0, 0, 0} }, + { {128, 0, 0, 0}, {0, 0, 0, 0}, {129, 0, 0, 0}, {1, 1, 1, 0} }, + { {128, 1, 129, 1}, {0, 0, 1, 1}, { 0, 0, 0, 1}, {0, 0, 0, 0} }, + { {128, 0, 129, 1}, {0, 0, 0, 1}, { 0, 0, 0, 0}, {0, 0, 0, 0} }, + { {128, 0, 0, 0}, {1, 0, 0, 0}, {129, 1, 0, 0}, {1, 1, 1, 0} }, + { {128, 0, 0, 0}, {0, 0, 0, 0}, {129, 0, 0, 0}, {1, 1, 0, 0} }, + { {128, 1, 1, 1}, {0, 0, 1, 1}, { 0, 0, 1, 1}, {0, 0, 0, 129} }, + { {128, 0, 129, 1}, {0, 0, 0, 1}, { 0, 0, 0, 1}, {0, 0, 0, 0} }, + { {128, 0, 0, 0}, {1, 0, 0, 0}, {129, 0, 0, 0}, {1, 1, 0, 0} }, + { {128, 1, 129, 0}, {0, 1, 1, 0}, { 0, 1, 1, 0}, {0, 1, 1, 0} }, + { {128, 0, 129, 1}, {0, 1, 1, 0}, { 0, 1, 1, 0}, {1, 1, 0, 0} }, + { {128, 0, 0, 1}, {0, 1, 1, 1}, {129, 1, 1, 0}, {1, 0, 0, 0} }, + { {128, 0, 0, 0}, {1, 1, 1, 1}, {129, 1, 1, 1}, {0, 0, 0, 0} }, + { {128, 1, 129, 1}, {0, 0, 0, 1}, { 1, 0, 0, 0}, {1, 1, 1, 0} }, + { {128, 0, 129, 1}, {1, 0, 0, 1}, { 1, 0, 0, 1}, {1, 1, 0, 0} }, + { {128, 1, 0, 1}, {0, 1, 0, 1}, { 0, 1, 0, 1}, {0, 1, 0, 129} }, + { {128, 0, 0, 0}, {1, 1, 1, 1}, { 0, 0, 0, 0}, {1, 1, 1, 129} }, + { {128, 1, 0, 1}, {1, 0, 129, 0}, { 0, 1, 0, 1}, {1, 0, 1, 0} }, + { {128, 0, 1, 1}, {0, 0, 1, 1}, {129, 1, 0, 0}, {1, 1, 0, 0} }, + { {128, 0, 129, 1}, {1, 1, 0, 0}, { 0, 0, 1, 1}, {1, 1, 0, 0} }, + { {128, 1, 0, 1}, {0, 1, 0, 1}, {129, 0, 1, 0}, {1, 0, 1, 0} }, + { {128, 1, 1, 0}, {1, 0, 0, 1}, { 0, 1, 1, 0}, {1, 0, 0, 129} }, + { {128, 1, 0, 1}, {1, 0, 1, 0}, { 1, 0, 1, 0}, {0, 1, 0, 129} }, + { {128, 1, 129, 1}, {0, 0, 1, 1}, { 1, 1, 0, 0}, {1, 1, 1, 0} }, + { {128, 0, 0, 1}, {0, 0, 1, 1}, {129, 1, 0, 0}, {1, 0, 0, 0} }, + { {128, 0, 129, 1}, {0, 0, 1, 0}, { 0, 1, 0, 0}, {1, 1, 0, 0} }, + { {128, 0, 129, 1}, {1, 0, 1, 1}, { 1, 1, 0, 1}, {1, 1, 0, 0} }, + { {128, 1, 129, 0}, {1, 0, 0, 1}, { 1, 0, 0, 1}, {0, 1, 1, 0} }, + { {128, 0, 1, 1}, {1, 1, 0, 0}, { 1, 1, 0, 0}, {0, 0, 1, 129} }, + { {128, 1, 1, 0}, {0, 1, 1, 0}, { 1, 0, 0, 1}, {1, 0, 0, 129} }, + { {128, 0, 0, 0}, {0, 1, 129, 0}, { 0, 1, 1, 0}, {0, 0, 0, 0} }, + { {128, 1, 0, 0}, {1, 1, 129, 0}, { 0, 1, 0, 0}, {0, 0, 0, 0} }, + { {128, 0, 129, 0}, {0, 1, 1, 1}, { 0, 0, 1, 0}, {0, 0, 0, 0} }, + { {128, 0, 0, 0}, {0, 0, 129, 0}, { 0, 1, 1, 1}, {0, 0, 1, 0} }, + { {128, 0, 0, 0}, {0, 1, 0, 0}, {129, 1, 1, 0}, {0, 1, 0, 0} }, + { {128, 1, 1, 0}, {1, 1, 0, 0}, { 1, 0, 0, 1}, {0, 0, 1, 129} }, + { {128, 0, 1, 1}, {0, 1, 1, 0}, { 1, 1, 0, 0}, {1, 0, 0, 129} }, + { {128, 1, 129, 0}, {0, 0, 1, 1}, { 1, 0, 0, 1}, {1, 1, 0, 0} }, + { {128, 0, 129, 1}, {1, 0, 0, 1}, { 1, 1, 0, 0}, {0, 1, 1, 0} }, + { {128, 1, 1, 0}, {1, 1, 0, 0}, { 1, 1, 0, 0}, {1, 0, 0, 129} }, + { {128, 1, 1, 0}, {0, 0, 1, 1}, { 0, 0, 1, 1}, {1, 0, 0, 129} }, + { {128, 1, 1, 1}, {1, 1, 1, 0}, { 1, 0, 0, 0}, {0, 0, 0, 129} }, + { {128, 0, 0, 1}, {1, 0, 0, 0}, { 1, 1, 1, 0}, {0, 1, 1, 129} }, + { {128, 0, 0, 0}, {1, 1, 1, 1}, { 0, 0, 1, 1}, {0, 0, 1, 129} }, + { {128, 0, 129, 1}, {0, 0, 1, 1}, { 1, 1, 1, 1}, {0, 0, 0, 0} }, + { {128, 0, 129, 0}, {0, 0, 1, 0}, { 1, 1, 1, 0}, {1, 1, 1, 0} }, + { {128, 1, 0, 0}, {0, 1, 0, 0}, { 0, 1, 1, 1}, {0, 1, 1, 129} } + }, + { // 3-subset + { {128, 0, 1, 129}, {0, 0, 1, 1}, { 0, 2, 2, 1}, { 2, 2, 2, 130} }, + { {128, 0, 0, 129}, {0, 0, 1, 1}, {130, 2, 1, 1}, { 2, 2, 2, 1} }, + { {128, 0, 0, 0}, {2, 0, 0, 1}, {130, 2, 1, 1}, { 2, 2, 1, 129} }, + { {128, 2, 2, 130}, {0, 0, 2, 2}, { 0, 0, 1, 1}, { 0, 1, 1, 129} }, + { {128, 0, 0, 0}, {0, 0, 0, 0}, {129, 1, 2, 2}, { 1, 1, 2, 130} }, + { {128, 0, 1, 129}, {0, 0, 1, 1}, { 0, 0, 2, 2}, { 0, 0, 2, 130} }, + { {128, 0, 2, 130}, {0, 0, 2, 2}, { 1, 1, 1, 1}, { 1, 1, 1, 129} }, + { {128, 0, 1, 1}, {0, 0, 1, 1}, {130, 2, 1, 1}, { 2, 2, 1, 129} }, + { {128, 0, 0, 0}, {0, 0, 0, 0}, {129, 1, 1, 1}, { 2, 2, 2, 130} }, + { {128, 0, 0, 0}, {1, 1, 1, 1}, {129, 1, 1, 1}, { 2, 2, 2, 130} }, + { {128, 0, 0, 0}, {1, 1, 129, 1}, { 2, 2, 2, 2}, { 2, 2, 2, 130} }, + { {128, 0, 1, 2}, {0, 0, 129, 2}, { 0, 0, 1, 2}, { 0, 0, 1, 130} }, + { {128, 1, 1, 2}, {0, 1, 129, 2}, { 0, 1, 1, 2}, { 0, 1, 1, 130} }, + { {128, 1, 2, 2}, {0, 129, 2, 2}, { 0, 1, 2, 2}, { 0, 1, 2, 130} }, + { {128, 0, 1, 129}, {0, 1, 1, 2}, { 1, 1, 2, 2}, { 1, 2, 2, 130} }, + { {128, 0, 1, 129}, {2, 0, 0, 1}, {130, 2, 0, 0}, { 2, 2, 2, 0} }, + { {128, 0, 0, 129}, {0, 0, 1, 1}, { 0, 1, 1, 2}, { 1, 1, 2, 130} }, + { {128, 1, 1, 129}, {0, 0, 1, 1}, {130, 0, 0, 1}, { 2, 2, 0, 0} }, + { {128, 0, 0, 0}, {1, 1, 2, 2}, {129, 1, 2, 2}, { 1, 1, 2, 130} }, + { {128, 0, 2, 130}, {0, 0, 2, 2}, { 0, 0, 2, 2}, { 1, 1, 1, 129} }, + { {128, 1, 1, 129}, {0, 1, 1, 1}, { 0, 2, 2, 2}, { 0, 2, 2, 130} }, + { {128, 0, 0, 129}, {0, 0, 0, 1}, {130, 2, 2, 1}, { 2, 2, 2, 1} }, + { {128, 0, 0, 0}, {0, 0, 129, 1}, { 0, 1, 2, 2}, { 0, 1, 2, 130} }, + { {128, 0, 0, 0}, {1, 1, 0, 0}, {130, 2, 129, 0}, { 2, 2, 1, 0} }, + { {128, 1, 2, 130}, {0, 129, 2, 2}, { 0, 0, 1, 1}, { 0, 0, 0, 0} }, + { {128, 0, 1, 2}, {0, 0, 1, 2}, {129, 1, 2, 2}, { 2, 2, 2, 130} }, + { {128, 1, 1, 0}, {1, 2, 130, 1}, {129, 2, 2, 1}, { 0, 1, 1, 0} }, + { {128, 0, 0, 0}, {0, 1, 129, 0}, { 1, 2, 130, 1}, { 1, 2, 2, 1} }, + { {128, 0, 2, 2}, {1, 1, 0, 2}, {129, 1, 0, 2}, { 0, 0, 2, 130} }, + { {128, 1, 1, 0}, {0, 129, 1, 0}, { 2, 0, 0, 2}, { 2, 2, 2, 130} }, + { {128, 0, 1, 1}, {0, 1, 2, 2}, { 0, 1, 130, 2}, { 0, 0, 1, 129} }, + { {128, 0, 0, 0}, {2, 0, 0, 0}, {130, 2, 1, 1}, { 2, 2, 2, 129} }, + { {128, 0, 0, 0}, {0, 0, 0, 2}, {129, 1, 2, 2}, { 1, 2, 2, 130} }, + { {128, 2, 2, 130}, {0, 0, 2, 2}, { 0, 0, 1, 2}, { 0, 0, 1, 129} }, + { {128, 0, 1, 129}, {0, 0, 1, 2}, { 0, 0, 2, 2}, { 0, 2, 2, 130} }, + { {128, 1, 2, 0}, {0, 129, 2, 0}, { 0, 1, 130, 0}, { 0, 1, 2, 0} }, + { {128, 0, 0, 0}, {1, 1, 129, 1}, { 2, 2, 130, 2}, { 0, 0, 0, 0} }, + { {128, 1, 2, 0}, {1, 2, 0, 1}, {130, 0, 129, 2}, { 0, 1, 2, 0} }, + { {128, 1, 2, 0}, {2, 0, 1, 2}, {129, 130, 0, 1}, { 0, 1, 2, 0} }, + { {128, 0, 1, 1}, {2, 2, 0, 0}, { 1, 1, 130, 2}, { 0, 0, 1, 129} }, + { {128, 0, 1, 1}, {1, 1, 130, 2}, { 2, 2, 0, 0}, { 0, 0, 1, 129} }, + { {128, 1, 0, 129}, {0, 1, 0, 1}, { 2, 2, 2, 2}, { 2, 2, 2, 130} }, + { {128, 0, 0, 0}, {0, 0, 0, 0}, {130, 1, 2, 1}, { 2, 1, 2, 129} }, + { {128, 0, 2, 2}, {1, 129, 2, 2}, { 0, 0, 2, 2}, { 1, 1, 2, 130} }, + { {128, 0, 2, 130}, {0, 0, 1, 1}, { 0, 0, 2, 2}, { 0, 0, 1, 129} }, + { {128, 2, 2, 0}, {1, 2, 130, 1}, { 0, 2, 2, 0}, { 1, 2, 2, 129} }, + { {128, 1, 0, 1}, {2, 2, 130, 2}, { 2, 2, 2, 2}, { 0, 1, 0, 129} }, + { {128, 0, 0, 0}, {2, 1, 2, 1}, {130, 1, 2, 1}, { 2, 1, 2, 129} }, + { {128, 1, 0, 129}, {0, 1, 0, 1}, { 0, 1, 0, 1}, { 2, 2, 2, 130} }, + { {128, 2, 2, 130}, {0, 1, 1, 1}, { 0, 2, 2, 2}, { 0, 1, 1, 129} }, + { {128, 0, 0, 2}, {1, 129, 1, 2}, { 0, 0, 0, 2}, { 1, 1, 1, 130} }, + { {128, 0, 0, 0}, {2, 129, 1, 2}, { 2, 1, 1, 2}, { 2, 1, 1, 130} }, + { {128, 2, 2, 2}, {0, 129, 1, 1}, { 0, 1, 1, 1}, { 0, 2, 2, 130} }, + { {128, 0, 0, 2}, {1, 1, 1, 2}, {129, 1, 1, 2}, { 0, 0, 0, 130} }, + { {128, 1, 1, 0}, {0, 129, 1, 0}, { 0, 1, 1, 0}, { 2, 2, 2, 130} }, + { {128, 0, 0, 0}, {0, 0, 0, 0}, { 2, 1, 129, 2}, { 2, 1, 1, 130} }, + { {128, 1, 1, 0}, {0, 129, 1, 0}, { 2, 2, 2, 2}, { 2, 2, 2, 130} }, + { {128, 0, 2, 2}, {0, 0, 1, 1}, { 0, 0, 129, 1}, { 0, 0, 2, 130} }, + { {128, 0, 2, 2}, {1, 1, 2, 2}, {129, 1, 2, 2}, { 0, 0, 2, 130} }, + { {128, 0, 0, 0}, {0, 0, 0, 0}, { 0, 0, 0, 0}, { 2, 129, 1, 130} }, + { {128, 0, 0, 130}, {0, 0, 0, 1}, { 0, 0, 0, 2}, { 0, 0, 0, 129} }, + { {128, 2, 2, 2}, {1, 2, 2, 2}, { 0, 2, 2, 2}, {129, 2, 2, 130} }, + { {128, 1, 0, 129}, {2, 2, 2, 2}, { 2, 2, 2, 2}, { 2, 2, 2, 130} }, + { {128, 1, 1, 129}, {2, 0, 1, 1}, {130, 2, 0, 1}, { 2, 2, 2, 0} } + } + }; + + QImage image = imageAlloc(width, height, QImage::Format_ARGB32); + if (image.isNull()) { + return image; + } + + quint8 block[16]; + quint8 texel[4][4][4]; + for (quint32 by = 0; by < height; by += 4) { + for (quint32 bx = 0; bx < width; bx += 4) { + if (s.readRawData(reinterpret_cast(block), sizeof(block)) != int(sizeof(block))) + return QImage(); + + memset(texel, 0, sizeof(texel)); + + BC7BitStream bstream; + bstream.low = bc7ReadU64(block); + bstream.high = bc7ReadU64(block + 8); + + // The mode is the number of leading zero bits. + int mode = 0; + while (mode < 8 && bc7ReadBits(&bstream, 1) == 0) + ++mode; + + // Reserved mode: the decompressed block is transparent black. + if (mode < 8) { + int partition = 0; + int numPartitions = 1; + int rotation = 0; + int indexSelectionBit = 0; + + if (mode == 0 || mode == 1 || mode == 2 || mode == 3 || mode == 7) { + numPartitions = (mode == 0 || mode == 2) ? 3 : 2; + partition = bc7ReadBits(&bstream, (mode == 0) ? 4 : 6); + } + + const int numEndpoints = numPartitions * 2; + + if (mode == 4 || mode == 5) { + rotation = bc7ReadBits(&bstream, 2); + + if (mode == 4) + indexSelectionBit = bc7ReadBits(&bstream, 1); + } + + int endpoints[6][4]; + memset(endpoints, 0, sizeof(endpoints)); + + for (int c = 0; c < 3; ++c) + for (int e = 0; e < numEndpoints; ++e) + endpoints[e][c] = bc7ReadBits(&bstream, actualBitsCount[0][mode]); + + if (actualBitsCount[1][mode] > 0) + for (int e = 0; e < numEndpoints; ++e) + endpoints[e][3] = bc7ReadBits(&bstream, actualBitsCount[1][mode]); + + if (mode == 0 || mode == 1 || mode == 3 || mode == 6 || mode == 7) { + for (int e = 0; e < numEndpoints; ++e) + for (int c = 0; c < 4; ++c) + endpoints[e][c] <<= 1; + + if (mode == 1) { + // The two subsets share one P-bit each. + const int p0 = bc7ReadBits(&bstream, 1); + const int p1 = bc7ReadBits(&bstream, 1); + for (int c = 0; c < 3; ++c) { + endpoints[0][c] |= p0; + endpoints[1][c] |= p0; + endpoints[2][c] |= p1; + endpoints[3][c] |= p1; + } + } else if (modesWithPBits & (1 << mode)) { + // One P-bit per endpoint. + for (int e = 0; e < numEndpoints; ++e) { + const int p = bc7ReadBits(&bstream, 1); + for (int c = 0; c < 4; ++c) + endpoints[e][c] |= p; + } + } + } + + for (int e = 0; e < numEndpoints; ++e) { + int bits = actualBitsCount[0][mode] + ((modesWithPBits >> mode) & 1); + for (int c = 0; c < 3; ++c) { + endpoints[e][c] <<= (8 - bits); + endpoints[e][c] |= (endpoints[e][c] >> bits); + } + + bits = actualBitsCount[1][mode] + ((modesWithPBits >> mode) & 1); + endpoints[e][3] <<= (8 - bits); + endpoints[e][3] |= (endpoints[e][3] >> bits); + } + + // If the mode does not store alpha, then alpha is opaque. + if (actualBitsCount[1][mode] == 0) + for (int e = 0; e < numEndpoints; ++e) + endpoints[e][3] = 0xff; + + const int indexBits = (mode == 0 || mode == 1) ? 3 : ((mode == 6) ? 4 : 2); + const int indexBits2 = (mode == 4) ? 3 : ((mode == 5) ? 2 : 0); + const int *weights = (indexBits == 2) ? weight2 : ((indexBits == 3) ? weight3 : weight4); + const int *weights2 = (indexBits2 == 2) ? weight2 : weight3; + + // The color indices are stored before the alpha indices. + int indices[4][4]; + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + const int partitionSet = (numPartitions == 1) ? ((i | j) ? 0 : 128) + : partitionSets[numPartitions - 2][partition][i][j]; + int bits = indexBits; + if (partitionSet & 0x80) // fix-up index + bits--; + indices[i][j] = bc7ReadBits(&bstream, bits); + } + } + + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + const int partitionSet = ((numPartitions == 1) ? ((i | j) ? 0 : 128) + : partitionSets[numPartitions - 2][partition][i][j]) & 0x03; + + const int index = indices[i][j]; + int r, g, b, a; + if (indexBits2 == 0) { + r = bc7Interpolate(endpoints[partitionSet * 2][0], endpoints[partitionSet * 2 + 1][0], weights, index); + g = bc7Interpolate(endpoints[partitionSet * 2][1], endpoints[partitionSet * 2 + 1][1], weights, index); + b = bc7Interpolate(endpoints[partitionSet * 2][2], endpoints[partitionSet * 2 + 1][2], weights, index); + a = bc7Interpolate(endpoints[partitionSet * 2][3], endpoints[partitionSet * 2 + 1][3], weights, index); + } else { + const int index2 = bc7ReadBits(&bstream, (i | j) ? indexBits2 : (indexBits2 - 1)); + if (indexSelectionBit == 0) { + r = bc7Interpolate(endpoints[partitionSet * 2][0], endpoints[partitionSet * 2 + 1][0], weights, index); + g = bc7Interpolate(endpoints[partitionSet * 2][1], endpoints[partitionSet * 2 + 1][1], weights, index); + b = bc7Interpolate(endpoints[partitionSet * 2][2], endpoints[partitionSet * 2 + 1][2], weights, index); + a = bc7Interpolate(endpoints[partitionSet * 2][3], endpoints[partitionSet * 2 + 1][3], weights2, index2); + } else { + r = bc7Interpolate(endpoints[partitionSet * 2][0], endpoints[partitionSet * 2 + 1][0], weights2, index2); + g = bc7Interpolate(endpoints[partitionSet * 2][1], endpoints[partitionSet * 2 + 1][1], weights2, index2); + b = bc7Interpolate(endpoints[partitionSet * 2][2], endpoints[partitionSet * 2 + 1][2], weights2, index2); + a = bc7Interpolate(endpoints[partitionSet * 2][3], endpoints[partitionSet * 2 + 1][3], weights, index); + } + } + + switch (rotation) { + case 1: // swap A and R + std::swap(a, r); + break; + case 2: // swap A and G + std::swap(a, g); + break; + case 3: // swap A and B + std::swap(a, b); + break; + } + + texel[i][j][0] = quint8(r); + texel[i][j][1] = quint8(g); + texel[i][j][2] = quint8(b); + texel[i][j][3] = quint8(a); + } + } + } + + const quint32 kMax = qMin(4, height - by); + const quint32 lMax = qMin(4, width - bx); + for (quint32 i = 0; i < kMax; i++) { + QRgb *line = reinterpret_cast(image.scanLine(by + i)); + for (quint32 j = 0; j < lMax; j++) { + line[bx + j] = qRgba(texel[i][j][0], texel[i][j][1], texel[i][j][2], texel[i][j][3]); + } + } + } + } + + return image; +} + static QImage readUnsignedImage(QDataStream &s, const DDSHeader &dds, quint32 width, quint32 height, bool hasAlpha) { quint32 flags = dds.pixelFormat.flags; @@ -1694,6 +2119,12 @@ static QImage readLayer(QDataStream &s, const DDSHeader &dds, const int format, return readRXGB(s, width, height); case FormatATI2: return readATI2(s, width, height); + case FormatBC4: + return readBC4(s, width, height); + case FormatBC5: + return readATI2(s, width, height); + case FormatBC7: + return readBC7(s, width, height); case FormatR16F: return readR16F(s, width, height); case FormatG16R16F: @@ -1797,6 +2228,11 @@ static qint64 mipmapSize(const DDSHeader &dds, const int format, const int level case FormatDXT4: case FormatDXT5: return ((w + 3)/4) * ((h + 3)/4) * 16; + case FormatBC4: + return ((w + 3)/4) * ((h + 3)/4) * 8; + case FormatBC5: + case FormatBC7: + return ((w + 3)/4) * ((h + 3)/4) * 16; case FormatD16Lockable: case FormatD32: case FormatD15S1: