DXTEncoder.cpp 132 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. /*
  21. ================================================================================================
  22. Contains the DxtEncoder implementation.
  23. ================================================================================================
  24. */
  25. #pragma hdrstop
  26. #include "DXTCodec_local.h"
  27. #include "DXTCodec.h"
  28. #define INSET_COLOR_SHIFT 4 // inset the bounding box with ( range >> shift )
  29. #define INSET_ALPHA_SHIFT 5 // inset alpha channel
  30. #define C565_5_MASK 0xF8 // 0xFF minus last three bits
  31. #define C565_6_MASK 0xFC // 0xFF minus last two bits
  32. #define NVIDIA_7X_HARDWARE_BUG_FIX // keep the DXT5 colors sorted as: max, min
  33. typedef uint16 word;
  34. typedef uint32 dword;
  35. /*
  36. ========================
  37. idDxtEncoder::NV4XHardwareBugFix
  38. ========================
  39. */
  40. void idDxtEncoder::NV4XHardwareBugFix( byte *minColor, byte *maxColor ) const {
  41. #ifdef ID_WIN_X86_ASM
  42. int minq = ( ( minColor[0] << 16 ) | ( minColor[1] << 8 ) | minColor[2] ) & 0x00F8FCF8;
  43. int maxq = ( ( maxColor[0] << 16 ) | ( maxColor[1] << 8 ) | maxColor[2] ) & 0x00F8FCF8;
  44. int mask = -( minq > maxq ) & 0x00FFFFFF;
  45. int min = *(int *)minColor;
  46. int max = *(int *)maxColor;
  47. min ^= max;
  48. max ^= ( min & mask );
  49. min ^= max;
  50. *(int *)minColor = min;
  51. *(int *)maxColor = max;
  52. #else
  53. if ( ColorTo565( minColor ) > ColorTo565( maxColor ) ) {
  54. SwapValues( minColor[0], maxColor[0] );
  55. SwapValues( minColor[1], maxColor[1] );
  56. SwapValues( minColor[2], maxColor[2] );
  57. }
  58. #endif
  59. }
  60. /*
  61. ========================
  62. idDxtEncoder::HasConstantValuePer4x4Block
  63. ========================
  64. */
  65. bool idDxtEncoder::HasConstantValuePer4x4Block( const byte *inBuf, int width, int height, int channel ) const {
  66. if ( width < 4 || height < 4 ) {
  67. byte value = inBuf[channel];
  68. for ( int k = 0; k < height; k++ ) {
  69. for ( int l = 0; l < width; l++ ) {
  70. if ( inBuf[(k*width+l)*4+channel] != value ) {
  71. return false;
  72. }
  73. }
  74. }
  75. return true;
  76. }
  77. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  78. for ( int i = 0; i < width; i += 4 ) {
  79. const byte *inPtr = inBuf + i * 4;
  80. byte value = inPtr[channel];
  81. for ( int k = 0; k < 4; k++ ) {
  82. for ( int l = 0; l < 4; l++ ) {
  83. if ( inPtr[(k*width+l)*4+channel] != value ) {
  84. return false;
  85. }
  86. }
  87. }
  88. }
  89. inBuf += srcPadding;
  90. }
  91. return true;
  92. }
  93. /*
  94. ========================
  95. idDxtEncoder::WriteTinyColorDXT1
  96. ========================
  97. */
  98. void idDxtEncoder::WriteTinyColorDXT1( const byte *inBuf, int width, int height ) {
  99. int numBlocks = ( ( width + 3 ) / 4 ) * ( ( height + 3 ) / 4 );
  100. int stride = ( ( width * height ) / numBlocks ) * 4; // number of bytes from one block to the next
  101. // example: 2x8 pixels
  102. // numBlocks = 2
  103. // stride = 32 bytes (8 pixels)
  104. for ( int i = 0; i < numBlocks; i++ ) {
  105. // FIXME: This just emits a fake block based on the color at position 0,0
  106. EmitUShort( ColorTo565( inBuf ) );
  107. EmitUShort( 0 ); // dummy, never used
  108. EmitUInt( 0 ); // 4 color index bytes all use the first color
  109. inBuf += stride;
  110. }
  111. }
  112. /*
  113. ========================
  114. idDxtEncoder::WriteTinyColorDXT5
  115. ========================
  116. */
  117. void idDxtEncoder::WriteTinyColorDXT5( const byte *inBuf, int width, int height ) {
  118. int numBlocks = ( ( width + 3 ) / 4 ) * ( ( height + 3 ) / 4 );
  119. int stride = ( ( width * height ) / numBlocks ) * 4; // number of bytes from one block to the next
  120. // example: 2x8 pixels
  121. // numBlocks = 2
  122. // stride = 32 bytes (8 pixels)
  123. for ( int i = 0; i < numBlocks; i++ ) {
  124. // FIXME: This just emits a fake block based on the color at position 0,0
  125. EmitByte( inBuf[3] );
  126. EmitByte( 0 ); // dummy, never used
  127. EmitByte( 0 ); // 6 alpha index bytes all use the first alpha
  128. EmitByte( 0 );
  129. EmitByte( 0 );
  130. EmitByte( 0 );
  131. EmitByte( 0 );
  132. EmitByte( 0 );
  133. EmitUShort( ColorTo565( inBuf ) );
  134. EmitUShort( 0 ); // dummy, never used
  135. EmitUInt( 0 ); // 4 color index bytes all use the first color
  136. inBuf += stride;
  137. }
  138. }
  139. /*
  140. ========================
  141. idDxtEncoder::WriteTinyColorCTX1DXT5A
  142. ========================
  143. */
  144. void idDxtEncoder::WriteTinyColorCTX1DXT5A( const byte *inBuf, int width, int height ) {
  145. int numBlocks = ( ( width + 3 ) / 4 ) * ( ( height + 3 ) / 4 );
  146. int stride = ( ( width * height ) / numBlocks ) * 4; // number of bytes from one block to the next
  147. // example: 2x8 pixels
  148. // numBlocks = 2
  149. // stride = 32 bytes (8 pixels)
  150. for ( int i = 0; i < numBlocks; i++ ) {
  151. // FIXME: This just emits a fake block based on the color at position 0,0
  152. EmitByte( inBuf[0] );
  153. EmitByte( inBuf[1] );
  154. EmitByte( inBuf[0] );
  155. EmitByte( inBuf[1] );
  156. EmitUInt( 0 ); // 4 color index bytes all use the first color
  157. EmitByte( inBuf[3] );
  158. EmitByte( 0 ); // dummy, never used
  159. EmitByte( 0 ); // 6 alpha index bytes all use the first alpha
  160. EmitByte( 0 );
  161. EmitByte( 0 );
  162. EmitByte( 0 );
  163. EmitByte( 0 );
  164. EmitByte( 0 );
  165. inBuf += stride;
  166. }
  167. }
  168. /*
  169. ========================
  170. idDxtEncoder::WriteTinyNormalMapDXT5
  171. ========================
  172. */
  173. void idDxtEncoder::WriteTinyNormalMapDXT5( const byte *inBuf, int width, int height ) {
  174. int numBlocks = ( ( width + 3 ) / 4 ) * ( ( height + 3 ) / 4 );
  175. int stride = ( ( width * height ) / numBlocks ) * 4; // number of bytes from one block to the next
  176. // example: 2x8 pixels
  177. // numBlocks = 2
  178. // stride = 32 bytes (8 pixels)
  179. for ( int i = 0; i < numBlocks; i++ ) {
  180. // FIXME: This just emits a fake block based on the normal at position 0,0
  181. EmitByte( inBuf[3] );
  182. EmitByte( 0 ); // dummy, never used
  183. EmitByte( 0 ); // 6 alpha index bytes all use the first alpha
  184. EmitByte( 0 );
  185. EmitByte( 0 );
  186. EmitByte( 0 );
  187. EmitByte( 0 );
  188. EmitByte( 0 );
  189. EmitUShort( ColorTo565( inBuf[0], inBuf[1], inBuf[2] ) );
  190. EmitUShort( 0 ); // dummy, never used
  191. EmitUInt( 0 ); // 4 color index bytes all use the first color
  192. inBuf += stride;
  193. }
  194. }
  195. /*
  196. ========================
  197. idDxtEncoder::WriteTinyNormalMapDXN
  198. ========================
  199. */
  200. void idDxtEncoder::WriteTinyNormalMapDXN( const byte *inBuf, int width, int height ) {
  201. int numBlocks = ( ( width + 3 ) / 4 ) * ( ( height + 3 ) / 4 );
  202. int stride = ( ( width * height ) / numBlocks ) * 4; // number of bytes from one block to the next
  203. // example: 2x8 pixels
  204. // numBlocks = 2
  205. // stride = 32 bytes (8 pixels)
  206. for ( int i = 0; i < numBlocks; i++ ) {
  207. // FIXME: This just emits a fake block based on the normal at position 0,0
  208. EmitByte( inBuf[0] );
  209. EmitByte( 0 ); // dummy, never used
  210. EmitByte( 0 ); // 6 alpha index bytes all use the first alpha
  211. EmitByte( 0 );
  212. EmitByte( 0 );
  213. EmitByte( 0 );
  214. EmitByte( 0 );
  215. EmitByte( 0 );
  216. EmitByte( inBuf[1] );
  217. EmitByte( 0 ); // dummy, never used
  218. EmitByte( 0 ); // 6 alpha index bytes all use the first alpha
  219. EmitByte( 0 );
  220. EmitByte( 0 );
  221. EmitByte( 0 );
  222. EmitByte( 0 );
  223. EmitByte( 0 );
  224. inBuf += stride;
  225. }
  226. }
  227. /*
  228. ========================
  229. idDxtEncoder::WriteTinyDXT5A
  230. ========================
  231. */
  232. void idDxtEncoder::WriteTinyDXT5A( const byte *inBuf, int width, int height ) {
  233. int numBlocks = ( ( width + 3 ) / 4 ) * ( ( height + 3 ) / 4 );
  234. int stride = ( ( width * height ) / numBlocks ) * 4; // number of bytes from one block to the next
  235. // example: 2x8 pixels
  236. // numBlocks = 2
  237. // stride = 32 bytes (8 pixels)
  238. for ( int i = 0; i < numBlocks; i++ ) {
  239. // FIXME: This just emits a fake block based on the normal at position 0,0
  240. EmitByte( inBuf[0] );
  241. EmitByte( 0 ); // dummy, never used
  242. EmitByte( 0 ); // 6 alpha index bytes all use the first alpha
  243. EmitByte( 0 );
  244. EmitByte( 0 );
  245. EmitByte( 0 );
  246. EmitByte( 0 );
  247. EmitByte( 0 );
  248. inBuf += stride;
  249. }
  250. }
  251. /*
  252. ========================
  253. idDxtEncoder::ExtractBlock
  254. params: inPtr - input image, 4 bytes per pixel
  255. paramO: colorBlock - 4*4 output tile, 4 bytes per pixel
  256. ========================
  257. */
  258. ID_INLINE void idDxtEncoder::ExtractBlock( const byte *inPtr, int width, byte *colorBlock ) const {
  259. for ( int j = 0; j < 4; j++ ) {
  260. memcpy( &colorBlock[j*4*4], inPtr, 4*4 );
  261. inPtr += width * 4;
  262. }
  263. }
  264. /*
  265. ========================
  266. SwapColors
  267. ========================
  268. */
  269. void SwapColors( byte *c1, byte *c2 ) {
  270. byte tm[3];
  271. memcpy( tm, c1, 3 );
  272. memcpy( c1, c2, 3 );
  273. memcpy( c2, tm, 3 );
  274. }
  275. /*
  276. ========================
  277. idDxtEncoder::GetMinMaxColorsMaxDist
  278. Finds the two RGB colors in a 4x4 block furthest apart. Also finds the two alpha values
  279. furthest apart.
  280. params: colorBlock - 4*4 input tile, 4 bytes per pixel
  281. paramO: minColor - 4 byte min color
  282. paramO: maxColor - 4 byte max color
  283. ========================
  284. */
  285. void idDxtEncoder::GetMinMaxColorsMaxDist( const byte *colorBlock, byte *minColor, byte *maxColor ) const {
  286. int maxDistC = -1;
  287. int maxDistA = -1;
  288. for ( int i = 0; i < 64 - 4; i += 4 ) {
  289. for ( int j = i + 4; j < 64; j += 4 ) {
  290. int dc = ColorDistance( &colorBlock[i], &colorBlock[j] );
  291. if ( dc > maxDistC ) {
  292. maxDistC = dc;
  293. memcpy( minColor, colorBlock+i, 3 );
  294. memcpy( maxColor, colorBlock+j, 3 );
  295. }
  296. int da = AlphaDistance( colorBlock[i+3], colorBlock[j+3] );
  297. if ( da > maxDistA ) {
  298. maxDistA = da;
  299. minColor[3] = colorBlock[i+3];
  300. maxColor[3] = colorBlock[j+3];
  301. }
  302. }
  303. }
  304. if ( maxColor[0] < minColor[0] ) {
  305. SwapColors( minColor, maxColor );
  306. }
  307. }
  308. /*
  309. ========================
  310. idDxtEncoder::GetMinMaxColorsLuminance
  311. Finds the two RGB colors in a 4x4 block furthest apart based on luminance. Also finds the two
  312. alpha values furthest apart.
  313. params: colorBlock - 4*4 input tile, 4 bytes per pixel
  314. paramO: minColor - 4 byte min color
  315. paramO: maxColor - 4 byte max color
  316. ========================
  317. */
  318. void idDxtEncoder::GetMinMaxColorsLuminance( const byte *colorBlock, byte *minColor, byte *maxColor ) const {
  319. int maxLumC = 0, minLumC = 256 * 4;
  320. int maxAlpha = 0, minAlpha = 256 * 4;
  321. for ( int i = 0; i < 16; i++ ) {
  322. int luminance = colorBlock[i*4+0] + colorBlock[i*4+1] * 2 + colorBlock[i*4+2];
  323. if ( luminance > maxLumC ) {
  324. maxLumC = luminance;
  325. memcpy( maxColor, colorBlock+i*4, 3 );
  326. }
  327. if ( luminance < minLumC ) {
  328. minLumC = luminance;
  329. memcpy( minColor, colorBlock+i*4, 3 );
  330. }
  331. int alpha = colorBlock[i*4+3];
  332. if ( alpha > maxAlpha ) {
  333. maxAlpha = alpha;
  334. maxColor[3] = (byte)alpha;
  335. }
  336. if ( alpha < minAlpha ) {
  337. minAlpha = alpha;
  338. minColor[3] = (byte)alpha;
  339. }
  340. }
  341. if ( maxColor[0] < minColor[0] ) {
  342. SwapColors( minColor, maxColor );
  343. }
  344. }
  345. /*
  346. ========================
  347. idDxtEncoder::GetSquareAlphaError
  348. params: colorBlock - 16 pixel block for which to find color indexes
  349. paramO: minAlpha - Min alpha found
  350. paramO: maxAlpha - Max alpha found
  351. return: 4 byte color index block
  352. ========================
  353. */
  354. int idDxtEncoder::GetSquareAlphaError( const byte *colorBlock, const int alphaOffset, const byte minAlpha, const byte maxAlpha, int lastError ) const {
  355. int i, j;
  356. byte alphas[8];
  357. alphas[0] = maxAlpha;
  358. alphas[1] = minAlpha;
  359. if ( maxAlpha > minAlpha ) {
  360. alphas[2] = ( 6 * alphas[0] + 1 * alphas[1] ) / 7;
  361. alphas[3] = ( 5 * alphas[0] + 2 * alphas[1] ) / 7;
  362. alphas[4] = ( 4 * alphas[0] + 3 * alphas[1] ) / 7;
  363. alphas[5] = ( 3 * alphas[0] + 4 * alphas[1] ) / 7;
  364. alphas[6] = ( 2 * alphas[0] + 5 * alphas[1] ) / 7;
  365. alphas[7] = ( 1 * alphas[0] + 6 * alphas[1] ) / 7;
  366. } else {
  367. alphas[2] = ( 4 * alphas[0] + 1 * alphas[1] ) / 5;
  368. alphas[3] = ( 3 * alphas[0] + 2 * alphas[1] ) / 5;
  369. alphas[4] = ( 2 * alphas[0] + 3 * alphas[1] ) / 5;
  370. alphas[5] = ( 1 * alphas[0] + 4 * alphas[1] ) / 5;
  371. alphas[6] = 0;
  372. alphas[7] = 255;
  373. }
  374. int error = 0;
  375. for ( i = 0; i < 16; i++ ) {
  376. unsigned int minDist = MAX_UNSIGNED_TYPE( int );
  377. byte a = colorBlock[i*4+alphaOffset];
  378. for ( j = 0; j < 8; j++ ) {
  379. unsigned int dist = AlphaDistance( a, alphas[j] );
  380. if ( dist < minDist ) {
  381. minDist = dist;
  382. }
  383. }
  384. error += minDist;
  385. if ( error >= lastError ) {
  386. return error;
  387. }
  388. }
  389. return error;
  390. }
  391. /*
  392. ========================
  393. idDxtEncoder::GetMinMaxAlphaHQ
  394. params: colorBlock - 4*4 input tile, 4 bytes per pixel
  395. paramO: minColor - 4 byte min color found
  396. paramO: maxColor - 4 byte max color found
  397. ========================
  398. */
  399. int idDxtEncoder::GetMinMaxAlphaHQ( const byte *colorBlock, const int alphaOffset, byte *minColor, byte *maxColor ) const {
  400. int i, j;
  401. byte alphaMin, alphaMax;
  402. int error, bestError = MAX_TYPE( int );
  403. alphaMin = 255;
  404. alphaMax = 0;
  405. // get alpha min / max
  406. for ( i = 0; i < 16; i++ ) {
  407. if ( colorBlock[i*4+alphaOffset] < alphaMin ) {
  408. alphaMin = colorBlock[i*4+alphaOffset];
  409. }
  410. if ( colorBlock[i*4+alphaOffset] > alphaMax ) {
  411. alphaMax = colorBlock[i*4+alphaOffset];
  412. }
  413. }
  414. const int ALPHA_EXPAND = 32;
  415. alphaMin = ( alphaMin <= ALPHA_EXPAND ) ? 0 : alphaMin - ALPHA_EXPAND;
  416. alphaMax = ( alphaMax >= 255 - ALPHA_EXPAND ) ? 255 : alphaMax + ALPHA_EXPAND;
  417. for ( i = alphaMin; i <= alphaMax; i++ ) {
  418. for ( j = alphaMax; j >= i; j-- ) {
  419. error = GetSquareAlphaError( colorBlock, alphaOffset, (byte)i, (byte)j, bestError );
  420. if ( error < bestError ) {
  421. bestError = error;
  422. minColor[alphaOffset] = (byte)i;
  423. maxColor[alphaOffset] = (byte)j;
  424. }
  425. error = GetSquareAlphaError( colorBlock, alphaOffset, (byte)j, (byte)i, bestError );
  426. if ( error < bestError ) {
  427. bestError = error;
  428. minColor[alphaOffset] = (byte)i;
  429. maxColor[alphaOffset] = (byte)j;
  430. }
  431. }
  432. }
  433. return bestError;
  434. }
  435. /*
  436. ========================
  437. idDxtEncoder::GetSquareColorsError
  438. params: colorBlock - 16 pixel block for which to find color indexes
  439. paramO: color0 - 4 byte min color found
  440. paramO: color1 - 4 byte max color found
  441. return: 4 byte color index block
  442. ========================
  443. */
  444. int idDxtEncoder::GetSquareColorsError( const byte *colorBlock, const unsigned short color0, const unsigned short color1, int lastError ) const {
  445. int i, j;
  446. byte colors[4][4];
  447. ColorFrom565( color0, colors[0] );
  448. ColorFrom565( color1, colors[1] );
  449. if ( color0 > color1 ) {
  450. colors[2][0] = ( 2 * colors[0][0] + 1 * colors[1][0] ) / 3;
  451. colors[2][1] = ( 2 * colors[0][1] + 1 * colors[1][1] ) / 3;
  452. colors[2][2] = ( 2 * colors[0][2] + 1 * colors[1][2] ) / 3;
  453. colors[3][0] = ( 1 * colors[0][0] + 2 * colors[1][0] ) / 3;
  454. colors[3][1] = ( 1 * colors[0][1] + 2 * colors[1][1] ) / 3;
  455. colors[3][2] = ( 1 * colors[0][2] + 2 * colors[1][2] ) / 3;
  456. } else {
  457. colors[2][0] = ( 1 * colors[0][0] + 1 * colors[1][0] ) / 2;
  458. colors[2][1] = ( 1 * colors[0][1] + 1 * colors[1][1] ) / 2;
  459. colors[2][2] = ( 1 * colors[0][2] + 1 * colors[1][2] ) / 2;
  460. colors[3][0] = 0;
  461. colors[3][1] = 0;
  462. colors[3][2] = 0;
  463. }
  464. int error = 0;
  465. for ( i = 0; i < 16; i++ ) {
  466. unsigned int minDist = MAX_UNSIGNED_TYPE( int );
  467. for ( j = 0; j < 4; j++ ) {
  468. unsigned int dist = ColorDistance( &colorBlock[i*4], &colors[j][0] );
  469. if ( dist < minDist ) {
  470. minDist = dist;
  471. }
  472. }
  473. // accumulated error
  474. error += minDist;
  475. if ( error > lastError ) {
  476. return error;
  477. }
  478. }
  479. return error;
  480. }
  481. /*
  482. ========================
  483. idDxtEncoder::GetSquareNormalYError
  484. params: colorBlock - 16 pixel block for which to find color indexes
  485. paramO: color0 - 4 byte min color found
  486. paramO: color1 - 4 byte max color found
  487. return: 4 byte color index block
  488. ========================
  489. */
  490. int idDxtEncoder::GetSquareNormalYError( const byte *colorBlock, const unsigned short color0, const unsigned short color1, int lastError, int scale ) const {
  491. int i, j;
  492. byte colors[4][4];
  493. ColorFrom565( color0, colors[0] );
  494. ColorFrom565( color1, colors[1] );
  495. if ( color0 > color1 ) {
  496. colors[2][0] = ( 2 * colors[0][0] + 1 * colors[1][0] ) / 3;
  497. colors[2][1] = ( 2 * colors[0][1] + 1 * colors[1][1] ) / 3;
  498. colors[2][2] = ( 2 * colors[0][2] + 1 * colors[1][2] ) / 3;
  499. colors[3][0] = ( 1 * colors[0][0] + 2 * colors[1][0] ) / 3;
  500. colors[3][1] = ( 1 * colors[0][1] + 2 * colors[1][1] ) / 3;
  501. colors[3][2] = ( 1 * colors[0][2] + 2 * colors[1][2] ) / 3;
  502. } else {
  503. colors[2][0] = ( 1 * colors[0][0] + 1 * colors[1][0] ) / 2;
  504. colors[2][1] = ( 1 * colors[0][1] + 1 * colors[1][1] ) / 2;
  505. colors[2][2] = ( 1 * colors[0][2] + 1 * colors[1][2] ) / 2;
  506. colors[3][0] = 0;
  507. colors[3][1] = 0;
  508. colors[3][2] = 0;
  509. }
  510. int error = 0;
  511. for ( i = 0; i < 16; i++ ) {
  512. unsigned int minDist = MAX_UNSIGNED_TYPE( int );
  513. for ( j = 0; j < 4; j++ ) {
  514. float r = (float) colorBlock[i*4+1] / scale;
  515. float s = (float) colors[j][1] / scale;
  516. unsigned int dist = idMath::Ftoi( ( r - s ) * ( r - s ) );
  517. if ( dist < minDist ) {
  518. minDist = dist;
  519. }
  520. }
  521. // accumulated error
  522. error += minDist;
  523. if ( error > lastError ) {
  524. return error;
  525. }
  526. }
  527. return error;
  528. }
  529. /*
  530. ========================
  531. idDxtEncoder::GetMinMaxColorsHQ
  532. Uses an exhaustive search to find the two RGB colors that produce the least error when used to
  533. compress the 4x4 block. Also finds the minimum and maximum alpha values.
  534. params: colorBlock - 4*4 input tile, 4 bytes per pixel
  535. paramO: minColor - 4 byte min color found
  536. paramO: maxColor - 4 byte max color found
  537. ========================
  538. */
  539. int idDxtEncoder::GetMinMaxColorsHQ( const byte *colorBlock, byte *minColor, byte *maxColor, bool noBlack ) const {
  540. int i;
  541. int i0, i1, i2, j0, j1, j2;
  542. unsigned short minColor565, maxColor565, bestMinColor565, bestMaxColor565;
  543. byte bboxMin[3], bboxMax[3], minAxisDist[3];
  544. int error, bestError = MAX_TYPE( int );
  545. bboxMin[0] = bboxMin[1] = bboxMin[2] = 255;
  546. bboxMax[0] = bboxMax[1] = bboxMax[2] = 0;
  547. // get color bbox
  548. for ( i = 0; i < 16; i++ ) {
  549. if ( colorBlock[i*4+0] < bboxMin[0] ) {
  550. bboxMin[0] = colorBlock[i*4+0];
  551. }
  552. if ( colorBlock[i*4+1] < bboxMin[1] ) {
  553. bboxMin[1] = colorBlock[i*4+1];
  554. }
  555. if ( colorBlock[i*4+2] < bboxMin[2] ) {
  556. bboxMin[2] = colorBlock[i*4+2];
  557. }
  558. if ( colorBlock[i*4+0] > bboxMax[0] ) {
  559. bboxMax[0] = colorBlock[i*4+0];
  560. }
  561. if ( colorBlock[i*4+1] > bboxMax[1] ) {
  562. bboxMax[1] = colorBlock[i*4+1];
  563. }
  564. if ( colorBlock[i*4+2] > bboxMax[2] ) {
  565. bboxMax[2] = colorBlock[i*4+2];
  566. }
  567. }
  568. // decrease range for 565 encoding
  569. bboxMin[0] >>= 3;
  570. bboxMin[1] >>= 2;
  571. bboxMin[2] >>= 3;
  572. bboxMax[0] >>= 3;
  573. bboxMax[1] >>= 2;
  574. bboxMax[2] >>= 3;
  575. // get the minimum distance the end points of the line must be apart along each axis
  576. for ( i = 0; i < 3; i++ ) {
  577. minAxisDist[i] = ( bboxMax[i] - bboxMin[i] );
  578. if ( minAxisDist[i] >= 16 ) {
  579. minAxisDist[i] = minAxisDist[i] * 3 / 4;
  580. } else if ( minAxisDist[i] >= 8 ) {
  581. minAxisDist[i] = minAxisDist[i] * 2 / 4;
  582. } else if ( minAxisDist[i] >= 4 ) {
  583. minAxisDist[i] = minAxisDist[i] * 1 / 4;
  584. } else {
  585. minAxisDist[i] = 0;
  586. }
  587. }
  588. // expand the bounding box
  589. const int C565_BBOX_EXPAND = 1;
  590. bboxMin[0] = ( bboxMin[0] <= C565_BBOX_EXPAND ) ? 0 : bboxMin[0] - C565_BBOX_EXPAND;
  591. bboxMin[1] = ( bboxMin[1] <= C565_BBOX_EXPAND ) ? 0 : bboxMin[1] - C565_BBOX_EXPAND;
  592. bboxMin[2] = ( bboxMin[2] <= C565_BBOX_EXPAND ) ? 0 : bboxMin[2] - C565_BBOX_EXPAND;
  593. bboxMax[0] = ( bboxMax[0] >= (255>>3)-C565_BBOX_EXPAND ) ? (255>>3) : bboxMax[0] + C565_BBOX_EXPAND;
  594. bboxMax[1] = ( bboxMax[1] >= (255>>2)-C565_BBOX_EXPAND ) ? (255>>2) : bboxMax[1] + C565_BBOX_EXPAND;
  595. bboxMax[2] = ( bboxMax[2] >= (255>>3)-C565_BBOX_EXPAND ) ? (255>>3) : bboxMax[2] + C565_BBOX_EXPAND;
  596. bestMinColor565 = 0;
  597. bestMaxColor565 = 0;
  598. for ( i0 = bboxMin[0]; i0 <= bboxMax[0]; i0++ ) {
  599. for ( j0 = bboxMax[0]; j0 >= bboxMin[0]; j0-- ) {
  600. if ( abs( i0 - j0 ) < minAxisDist[0] ) {
  601. continue;
  602. }
  603. for ( i1 = bboxMin[1]; i1 <= bboxMax[1]; i1++ ) {
  604. for ( j1 = bboxMax[1]; j1 >= bboxMin[1]; j1-- ) {
  605. if ( abs( i1 - j1 ) < minAxisDist[1] ) {
  606. continue;
  607. }
  608. for ( i2 = bboxMin[2]; i2 <= bboxMax[2]; i2++ ) {
  609. for ( j2 = bboxMax[2]; j2 >= bboxMin[2]; j2-- ) {
  610. if ( abs( i2 - j2 ) < minAxisDist[2] ) {
  611. continue;
  612. }
  613. minColor565 = (unsigned short)( ( i0 << 11 ) | ( i1 << 5 ) | ( i2 << 0 ) );
  614. maxColor565 = (unsigned short)( ( j0 << 11 ) | ( j1 << 5 ) | ( j2 << 0 ) );
  615. if ( !noBlack ) {
  616. error = GetSquareColorsError( colorBlock, maxColor565, minColor565, bestError );
  617. if ( error < bestError ) {
  618. bestError = error;
  619. bestMinColor565 = minColor565;
  620. bestMaxColor565 = maxColor565;
  621. }
  622. } else {
  623. if ( minColor565 <= maxColor565 ) {
  624. SwapValues( minColor565, maxColor565 );
  625. }
  626. }
  627. error = GetSquareColorsError( colorBlock, minColor565, maxColor565, bestError );
  628. if ( error < bestError ) {
  629. bestError = error;
  630. bestMinColor565 = minColor565;
  631. bestMaxColor565 = maxColor565;
  632. }
  633. }
  634. }
  635. }
  636. }
  637. }
  638. }
  639. ColorFrom565( bestMinColor565, minColor );
  640. ColorFrom565( bestMaxColor565, maxColor );
  641. return bestError;
  642. }
  643. /*
  644. ========================
  645. idDxtEncoder::GetSquareCTX1Error
  646. params: colorBlock - 16 pixel block for which to find color indexes
  647. paramO: color0 - Min color found
  648. paramO: color1 - Max color found
  649. return: 4 byte color index block
  650. ========================
  651. */
  652. int idDxtEncoder::GetSquareCTX1Error( const byte *colorBlock, const byte *color0, const byte *color1, int lastError ) const {
  653. int i, j;
  654. byte colors[4][4];
  655. colors[0][0] = color0[0];
  656. colors[0][1] = color0[1];
  657. colors[1][0] = color1[0];
  658. colors[1][1] = color1[1];
  659. colors[2][0] = ( 2 * colors[0][0] + 1 * colors[1][0] ) / 3;
  660. colors[2][1] = ( 2 * colors[0][1] + 1 * colors[1][1] ) / 3;
  661. colors[3][0] = ( 1 * colors[0][0] + 2 * colors[1][0] ) / 3;
  662. colors[3][1] = ( 1 * colors[0][1] + 2 * colors[1][1] ) / 3;
  663. int error = 0;
  664. for ( i = 0; i < 16; i++ ) {
  665. unsigned int minDist = MAX_UNSIGNED_TYPE( int );
  666. for ( j = 0; j < 4; j++ ) {
  667. unsigned int dist = CTX1Distance( &colorBlock[i*4], &colors[j][0] );
  668. if ( dist < minDist ) {
  669. minDist = dist;
  670. }
  671. }
  672. // accumulated error
  673. error += minDist;
  674. if ( error > lastError ) {
  675. return error;
  676. }
  677. }
  678. return error;
  679. }
  680. /*
  681. ========================
  682. idDxtEncoder::GetMinMaxCTX1HQ
  683. Uses an exhaustive search to find the two RGB colors that produce the least error when used to
  684. compress the 4x4 block. Also finds the minimum and maximum alpha values.
  685. params: colorBlock - 4*4 input tile, 4 bytes per pixel
  686. paramO: minColor - 4 byte Min color found
  687. paramO: maxColor - 4 byte Max color found
  688. ========================
  689. */
  690. int idDxtEncoder::GetMinMaxCTX1HQ( const byte *colorBlock, byte *minColor, byte *maxColor ) const {
  691. int i;
  692. int i0, i1, j0, j1;
  693. byte curMinColor[2], curMaxColor[2];
  694. byte bboxMin[2], bboxMax[2], minAxisDist[2];
  695. int error, bestError = MAX_TYPE( int );
  696. bboxMin[0] = bboxMin[1] = 255;
  697. bboxMax[0] = bboxMax[1] = 0;
  698. // get color bbox
  699. for ( i = 0; i < 16; i++ ) {
  700. if ( colorBlock[i*4+0] < bboxMin[0] ) {
  701. bboxMin[0] = colorBlock[i*4+0];
  702. }
  703. if ( colorBlock[i*4+1] < bboxMin[1] ) {
  704. bboxMin[1] = colorBlock[i*4+1];
  705. }
  706. if ( colorBlock[i*4+0] > bboxMax[0] ) {
  707. bboxMax[0] = colorBlock[i*4+0];
  708. }
  709. if ( colorBlock[i*4+1] > bboxMax[1] ) {
  710. bboxMax[1] = colorBlock[i*4+1];
  711. }
  712. }
  713. // get the minimum distance the end points of the line must be apart along each axis
  714. for ( i = 0; i < 2; i++ ) {
  715. minAxisDist[i] = ( bboxMax[i] - bboxMin[i] );
  716. if ( minAxisDist[i] >= 64 ) {
  717. minAxisDist[i] = minAxisDist[i] * 3 / 4;
  718. } else if ( minAxisDist[i] >= 32 ) {
  719. minAxisDist[i] = minAxisDist[i] * 2 / 4;
  720. } else if ( minAxisDist[i] >= 16 ) {
  721. minAxisDist[i] = minAxisDist[i] * 1 / 4;
  722. } else {
  723. minAxisDist[i] = 0;
  724. }
  725. }
  726. // expand the bounding box
  727. const int CXT1_BBOX_EXPAND = 6;
  728. bboxMin[0] = ( bboxMin[0] <= CXT1_BBOX_EXPAND ) ? 0 : bboxMin[0] - CXT1_BBOX_EXPAND;
  729. bboxMin[1] = ( bboxMin[1] <= CXT1_BBOX_EXPAND ) ? 0 : bboxMin[1] - CXT1_BBOX_EXPAND;
  730. bboxMax[0] = ( bboxMax[0] >= 255 - CXT1_BBOX_EXPAND ) ? 255 : bboxMax[0] + CXT1_BBOX_EXPAND;
  731. bboxMax[1] = ( bboxMax[1] >= 255 - CXT1_BBOX_EXPAND ) ? 255 : bboxMax[1] + CXT1_BBOX_EXPAND;
  732. for ( i0 = bboxMin[0]; i0 <= bboxMax[0]; i0++ ) {
  733. for ( j0 = bboxMax[0]; j0 >= bboxMin[0]; j0-- ) {
  734. if ( abs( i0 - j0 ) < minAxisDist[0] ) {
  735. continue;
  736. }
  737. for ( i1 = bboxMin[1]; i1 <= bboxMax[1]; i1++ ) {
  738. for ( j1 = bboxMax[1]; j1 >= bboxMin[1]; j1-- ) {
  739. if ( abs( i1 - j1 ) < minAxisDist[1] ) {
  740. continue;
  741. }
  742. curMinColor[0] = (byte)i0;
  743. curMinColor[1] = (byte)i1;
  744. curMaxColor[0] = (byte)j0;
  745. curMaxColor[1] = (byte)j1;
  746. error = GetSquareCTX1Error( colorBlock, curMinColor, curMaxColor, bestError );
  747. if ( error < bestError ) {
  748. bestError = error;
  749. memcpy( minColor, curMinColor, 2 );
  750. memcpy( maxColor, curMaxColor, 2 );
  751. }
  752. }
  753. }
  754. }
  755. }
  756. return bestError;
  757. }
  758. /*
  759. ========================
  760. idDxtEncoder::GetMinMaxNormalYHQ
  761. Uses an exhaustive search to find the two RGB colors that produce the least error when used to
  762. compress the 4x4 block. Also finds the minimum and maximum alpha values.
  763. params: colorBlock - 4*4 input tile, 4 bytes per pixel
  764. paramO: minColor - 4 byte Min color found
  765. paramO: maxColor - 4 byte Max color found
  766. ========================
  767. */
  768. int idDxtEncoder::GetMinMaxNormalYHQ( const byte *colorBlock, byte *minColor, byte *maxColor, bool noBlack, int scale ) const {
  769. unsigned short bestMinColor565, bestMaxColor565;
  770. byte bboxMin[3], bboxMax[3];
  771. int error, bestError = MAX_TYPE( int );
  772. bboxMin[1] = 255;
  773. bboxMax[1] = 0;
  774. // get color bbox
  775. for ( int i = 0; i < 16; i++ ) {
  776. if ( colorBlock[i*4+1] < bboxMin[1] ) {
  777. bboxMin[1] = colorBlock[i*4+1];
  778. }
  779. if ( colorBlock[i*4+1] > bboxMax[1] ) {
  780. bboxMax[1] = colorBlock[i*4+1];
  781. }
  782. }
  783. // decrease range for 565 encoding
  784. bboxMin[1] >>= 2;
  785. bboxMax[1] >>= 2;
  786. // expand the bounding box
  787. const int C565_BBOX_EXPAND = 1;
  788. bboxMin[1] = ( bboxMin[1] <= C565_BBOX_EXPAND ) ? 0 : bboxMin[1] - C565_BBOX_EXPAND;
  789. bboxMax[1] = ( bboxMax[1] >= (255>>2)-C565_BBOX_EXPAND ) ? (255>>2) : bboxMax[1] + C565_BBOX_EXPAND;
  790. bestMinColor565 = 0;
  791. bestMaxColor565 = 0;
  792. for ( int i1 = bboxMin[1]; i1 <= bboxMax[1]; i1++ ) {
  793. for ( int j1 = bboxMax[1]; j1 >= bboxMin[1]; j1-- ) {
  794. if ( abs( i1 - j1 ) < 0 ) {
  795. continue;
  796. }
  797. unsigned short minColor565 = (unsigned short)i1 << 5;
  798. unsigned short maxColor565 = (unsigned short)j1 << 5;
  799. if ( !noBlack ) {
  800. error = GetSquareNormalYError( colorBlock, maxColor565, minColor565, bestError, scale );
  801. if ( error < bestError ) {
  802. bestError = error;
  803. bestMinColor565 = minColor565;
  804. bestMaxColor565 = maxColor565;
  805. }
  806. } else {
  807. if ( minColor565 <= maxColor565 ) {
  808. SwapValues( minColor565, maxColor565 );
  809. }
  810. }
  811. error = GetSquareNormalYError( colorBlock, minColor565, maxColor565, bestError, scale );
  812. if ( error < bestError ) {
  813. bestError = error;
  814. bestMinColor565 = minColor565;
  815. bestMaxColor565 = maxColor565;
  816. }
  817. }
  818. }
  819. ColorFrom565( bestMinColor565, minColor );
  820. ColorFrom565( bestMaxColor565, maxColor );
  821. int bias = colorBlock[0*4+0];
  822. int size = colorBlock[0*4+2];
  823. minColor[0] = maxColor[0] = (byte)bias;
  824. minColor[2] = maxColor[2] = (byte)size;
  825. return bestError;
  826. }
  827. #if defined( ID_WIN_X86_ASM )
  828. ALIGN16( static float SIMD_SSE2_float_scale[4] ) = { 2.0f / 255.0f, 2.0f / 255.0f, 2.0f / 255.0f, 2.0f / 255.0f };
  829. ALIGN16( static float SIMD_SSE2_float_descale[4] ) = { 255.0f / 2.0f, 255.0f / 2.0f, 255.0f / 2.0f, 255.0f / 2.0f };
  830. ALIGN16( static float SIMD_SSE2_float_zero[4] ) = { 0.0f, 0.0f, 0.0f, 0.0f };
  831. ALIGN16( static float SIMD_SSE2_float_one[4] ) = { 1.0f, 1.0f, 1.0f, 1.0f };
  832. ALIGN16( static float SIMD_SSE2_float_half[4] ) = { 0.5f, 0.5f, 0.5f, 0.5f };
  833. ALIGN16( static float SIMD_SSE2_float_255[4] ) = { 255.0f, 255.0f, 255.0f, 255.0f };
  834. ALIGN16( static float SIMD_SP_rsqrt_c0[4] ) = { 3.0f, 3.0f, 3.0f, 3.0f };
  835. ALIGN16( static float SIMD_SP_rsqrt_c1[4] ) = { -0.5f, -0.5f, -0.5f, -0.5f };
  836. ALIGN16( static dword SIMD_SSE2_dword_maskFirstThree[4] ) = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 };
  837. ALIGN16( static dword SIMD_SSE2_dword_maskWords[4] ) = { 0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x00000000 };
  838. #define R_SHUFFLE_PS( x, y, z, w ) (( (w) & 3 ) << 6 | ( (z) & 3 ) << 4 | ( (y) & 3 ) << 2 | ( (x) & 3 ))
  839. #endif
  840. /*
  841. ========================
  842. NormalDistanceDXT1
  843. ========================
  844. */
  845. int NormalDistanceDXT1( const int *vector, const int *normalized ) {
  846. #if defined( ID_WIN_X86_ASM )
  847. int result;
  848. __asm {
  849. mov esi, vector
  850. mov edi, normalized
  851. cvtdq2ps xmm0, [esi]
  852. mulps xmm0, SIMD_SSE2_float_scale
  853. subps xmm0, SIMD_SSE2_float_one
  854. pand xmm0, SIMD_SSE2_dword_maskFirstThree
  855. movaps xmm1, xmm0
  856. mulps xmm1, xmm1
  857. pshufd xmm2, xmm1, R_SHUFFLE_PS( 2, 3, 0, 1 )
  858. addps xmm2, xmm1
  859. pshufd xmm1, xmm2, R_SHUFFLE_PS( 1, 0, 1, 0 )
  860. addps xmm2, xmm1
  861. rsqrtps xmm1, xmm2
  862. mulps xmm2, xmm1
  863. mulps xmm2, xmm1
  864. subps xmm2, SIMD_SP_rsqrt_c0
  865. mulps xmm1, SIMD_SP_rsqrt_c1
  866. mulps xmm2, xmm1
  867. mulps xmm0, xmm2
  868. addps xmm0, SIMD_SSE2_float_one
  869. mulps xmm0, SIMD_SSE2_float_descale
  870. addps xmm0, SIMD_SSE2_float_half
  871. maxps xmm0, SIMD_SSE2_float_zero
  872. minps xmm0, SIMD_SSE2_float_255
  873. cvttps2dq xmm0, xmm0
  874. psubd xmm0, [edi]
  875. pand xmm0, SIMD_SSE2_dword_maskWords
  876. pmullw xmm0, xmm0
  877. pshufd xmm1, xmm0, R_SHUFFLE_PS( 2, 3, 0, 1 )
  878. paddd xmm0, xmm1
  879. pshufd xmm1, xmm0, R_SHUFFLE_PS( 1, 0, 1, 0 )
  880. paddd xmm0, xmm1
  881. movd result, xmm0
  882. }
  883. return result;
  884. #else
  885. float floatNormal[3];
  886. byte intNormal[4];
  887. floatNormal[0] = vector[0] * ( 2.0f / 255.0f ) - 1.0f;
  888. floatNormal[1] = vector[1] * ( 2.0f / 255.0f ) - 1.0f;
  889. floatNormal[2] = vector[2] * ( 2.0f / 255.0f ) - 1.0f;
  890. float rcplen = idMath::InvSqrt( floatNormal[0] * floatNormal[0] + floatNormal[1] * floatNormal[1] + floatNormal[2] * floatNormal[2] );
  891. floatNormal[0] *= rcplen;
  892. floatNormal[1] *= rcplen;
  893. floatNormal[2] *= rcplen;
  894. intNormal[0] = idMath::Ftob( ( floatNormal[0] + 1.0f ) * ( 255.0f / 2.0f ) + 0.5f );
  895. intNormal[1] = idMath::Ftob( ( floatNormal[1] + 1.0f ) * ( 255.0f / 2.0f ) + 0.5f );
  896. intNormal[2] = idMath::Ftob( ( floatNormal[2] + 1.0f ) * ( 255.0f / 2.0f ) + 0.5f );
  897. int result = ( ( intNormal[ 0 ] - normalized[ 0 ] ) * ( intNormal[ 0 ] - normalized[ 0 ] ) ) +
  898. ( ( intNormal[ 1 ] - normalized[ 1 ] ) * ( intNormal[ 1 ] - normalized[ 1 ] ) ) +
  899. ( ( intNormal[ 2 ] - normalized[ 2 ] ) * ( intNormal[ 2 ] - normalized[ 2 ] ) );
  900. return result;
  901. #endif
  902. }
  903. /*
  904. ========================
  905. NormalDistanceDXT5
  906. ========================
  907. */
  908. int NormalDistanceDXT5( const int *vector, const int *normalized ) {
  909. #if defined( ID_WIN_X86_ASM )
  910. int result;
  911. __asm {
  912. mov esi, vector
  913. mov edi, normalized
  914. #if 0 // object-space
  915. pshufd xmm0, [esi], R_SHUFFLE_PS( 0, 1, 3, 2 )
  916. #else
  917. pshufd xmm0, [esi], R_SHUFFLE_PS( 1, 2, 3, 0 )
  918. #endif
  919. cvtdq2ps xmm0, xmm0
  920. mulps xmm0, SIMD_SSE2_float_scale
  921. subps xmm0, SIMD_SSE2_float_one
  922. pand xmm0, SIMD_SSE2_dword_maskFirstThree
  923. movaps xmm1, xmm0
  924. mulps xmm1, xmm1
  925. pshufd xmm2, xmm1, R_SHUFFLE_PS( 2, 3, 0, 1 )
  926. addps xmm2, xmm1
  927. pshufd xmm1, xmm2, R_SHUFFLE_PS( 1, 0, 1, 0 )
  928. addps xmm2, xmm1
  929. rsqrtps xmm1, xmm2
  930. mulps xmm2, xmm1
  931. mulps xmm2, xmm1
  932. subps xmm2, SIMD_SP_rsqrt_c0
  933. mulps xmm1, SIMD_SP_rsqrt_c1
  934. mulps xmm2, xmm1
  935. mulps xmm0, xmm2
  936. addps xmm0, SIMD_SSE2_float_one
  937. mulps xmm0, SIMD_SSE2_float_descale
  938. addps xmm0, SIMD_SSE2_float_half
  939. maxps xmm0, SIMD_SSE2_float_zero
  940. minps xmm0, SIMD_SSE2_float_255
  941. cvttps2dq xmm0, xmm0
  942. #if 0 // object-space
  943. pshufd xmm3, [edi], R_SHUFFLE_PS( 0, 1, 3, 2 )
  944. #else
  945. pshufd xmm3, [edi], R_SHUFFLE_PS( 1, 2, 3, 0 )
  946. #endif
  947. psubd xmm0, xmm3
  948. pand xmm0, SIMD_SSE2_dword_maskWords
  949. pmullw xmm0, xmm0
  950. pshufd xmm1, xmm0, R_SHUFFLE_PS( 2, 3, 0, 1 )
  951. paddd xmm0, xmm1
  952. pshufd xmm1, xmm0, R_SHUFFLE_PS( 1, 0, 1, 0 )
  953. paddd xmm0, xmm1
  954. movd result, xmm0
  955. }
  956. return result;
  957. #else
  958. #if 0 // object-space
  959. const int c0 = 0;
  960. const int c1 = 1;
  961. const int c2 = 3;
  962. #else
  963. const int c0 = 1;
  964. const int c1 = 2;
  965. const int c2 = 3;
  966. #endif
  967. float floatNormal[3];
  968. byte intNormal[4];
  969. floatNormal[0] = vector[c0] / 255.0f * 2.0f - 1.0f;
  970. floatNormal[1] = vector[c1] / 255.0f * 2.0f - 1.0f;
  971. floatNormal[2] = vector[c2] / 255.0f * 2.0f - 1.0f;
  972. float rcplen = idMath::InvSqrt( floatNormal[0] * floatNormal[0] + floatNormal[1] * floatNormal[1] + floatNormal[2] * floatNormal[2] );
  973. floatNormal[0] *= rcplen;
  974. floatNormal[1] *= rcplen;
  975. floatNormal[2] *= rcplen;
  976. intNormal[c0] = idMath::Ftob( ( floatNormal[0] + 1.0f ) / 2.0f * 255.0f + 0.5f );
  977. intNormal[c1] = idMath::Ftob( ( floatNormal[1] + 1.0f ) / 2.0f * 255.0f + 0.5f );
  978. intNormal[c2] = idMath::Ftob( ( floatNormal[2] + 1.0f ) / 2.0f * 255.0f + 0.5f );
  979. int result = ( ( intNormal[ c0 ] - normalized[ c0 ] ) * ( intNormal[ c0 ] - normalized[ c0 ] ) ) +
  980. ( ( intNormal[ c1 ] - normalized[ c1 ] ) * ( intNormal[ c1 ] - normalized[ c1 ] ) ) +
  981. ( ( intNormal[ c2 ] - normalized[ c2 ] ) * ( intNormal[ c2 ] - normalized[ c2 ] ) );
  982. return result;
  983. #endif
  984. }
  985. /*
  986. ========================
  987. idDxtEncoder::GetSquareNormalsDXT1Error
  988. params: colorBlock - 4*4 input tile, 4 bytes per pixel
  989. paramO: color0 - 4 byte Min color found
  990. paramO: color1 - 4 byte Max color found
  991. return: 4 byte color index block
  992. ========================
  993. */
  994. int idDxtEncoder::GetSquareNormalsDXT1Error( const int *colorBlock, const unsigned short color0, const unsigned short color1, int lastError, unsigned int &colorIndices ) const {
  995. byte byteColors[2][4];
  996. ALIGN16( int colors[4][4] );
  997. ColorFrom565( color0, byteColors[0] );
  998. ColorFrom565( color1, byteColors[1] );
  999. for ( int i = 0; i < 4; i++ ) {
  1000. colors[0][i] = byteColors[0][i];
  1001. colors[1][i] = byteColors[1][i];
  1002. }
  1003. if ( color0 > color1 ) {
  1004. colors[2][0] = ( 2 * colors[0][0] + 1 * colors[1][0] ) / 3;
  1005. colors[2][1] = ( 2 * colors[0][1] + 1 * colors[1][1] ) / 3;
  1006. colors[2][2] = ( 2 * colors[0][2] + 1 * colors[1][2] ) / 3;
  1007. colors[3][0] = ( 1 * colors[0][0] + 2 * colors[1][0] ) / 3;
  1008. colors[3][1] = ( 1 * colors[0][1] + 2 * colors[1][1] ) / 3;
  1009. colors[3][2] = ( 1 * colors[0][2] + 2 * colors[1][2] ) / 3;
  1010. } else {
  1011. assert( color0 == color1 );
  1012. colors[2][0] = ( 1 * colors[0][0] + 1 * colors[1][0] ) / 2;
  1013. colors[2][1] = ( 1 * colors[0][1] + 1 * colors[1][1] ) / 2;
  1014. colors[2][2] = ( 1 * colors[0][2] + 1 * colors[1][2] ) / 2;
  1015. colors[3][0] = 0;
  1016. colors[3][1] = 0;
  1017. colors[3][2] = 0;
  1018. }
  1019. int error = 0;
  1020. int tempColorIndices[16];
  1021. for ( int i = 0; i < 16; i++ ) {
  1022. unsigned int minDist = MAX_UNSIGNED_TYPE( int );
  1023. for ( int j = 0; j < 4; j++ ) {
  1024. unsigned int dist = NormalDistanceDXT1( &colors[j][0], &colorBlock[i*4] );
  1025. if ( dist < minDist ) {
  1026. minDist = dist;
  1027. tempColorIndices[i] = j;
  1028. }
  1029. }
  1030. // accumulated error
  1031. error += minDist;
  1032. if ( error > lastError ) {
  1033. return error;
  1034. }
  1035. }
  1036. colorIndices = 0;
  1037. for ( int i = 0; i < 16; i++ ) {
  1038. colorIndices |= ( tempColorIndices[i] << (unsigned int)( i << 1 ) );
  1039. }
  1040. return error;
  1041. }
  1042. /*
  1043. ========================
  1044. idDxtEncoder::GetMinMaxNormalsDXT1HQ
  1045. Uses an exhaustive search to find the two RGB colors that produce the least error when used to
  1046. compress the 4x4 block. Also finds the minimum and maximum alpha values.
  1047. params: colorBlock - 4*4 input tile, 4 bytes per pixel
  1048. paramO: minColor - 4 byte Min color found
  1049. paramO: maxColor - 4 byte Max color found
  1050. ========================
  1051. */
  1052. int idDxtEncoder::GetMinMaxNormalsDXT1HQ( const byte *colorBlock, byte *minColor, byte *maxColor, unsigned int &colorIndices, bool noBlack ) const {
  1053. int i;
  1054. int i0, i1, i2, j0, j1, j2;
  1055. unsigned short bestMinColor565 = 0;
  1056. unsigned short bestMaxColor565 = 0;
  1057. byte bboxMin[3], bboxMax[3], minAxisDist[3];
  1058. int error, bestError = MAX_TYPE( int );
  1059. unsigned int tempColorIndices;
  1060. ALIGN16( int intColorBlock[16*4] );
  1061. bboxMin[0] = bboxMin[1] = bboxMin[2] = 128;
  1062. bboxMax[0] = bboxMax[1] = bboxMax[2] = 128;
  1063. // get color bbox
  1064. for ( i = 0; i < 16; i++ ) {
  1065. if ( colorBlock[i*4+0] < bboxMin[0] ) {
  1066. bboxMin[0] = colorBlock[i*4+0];
  1067. }
  1068. if ( colorBlock[i*4+1] < bboxMin[1] ) {
  1069. bboxMin[1] = colorBlock[i*4+1];
  1070. }
  1071. if ( colorBlock[i*4+2] < bboxMin[2] ) {
  1072. bboxMin[2] = colorBlock[i*4+2];
  1073. }
  1074. if ( colorBlock[i*4+0] > bboxMax[0] ) {
  1075. bboxMax[0] = colorBlock[i*4+0];
  1076. }
  1077. if ( colorBlock[i*4+1] > bboxMax[1] ) {
  1078. bboxMax[1] = colorBlock[i*4+1];
  1079. }
  1080. if ( colorBlock[i*4+2] > bboxMax[2] ) {
  1081. bboxMax[2] = colorBlock[i*4+2];
  1082. }
  1083. }
  1084. for ( int i = 0; i < 64; i++ ) {
  1085. intColorBlock[i] = colorBlock[i];
  1086. }
  1087. // decrease range for 565 encoding
  1088. bboxMin[0] >>= 3;
  1089. bboxMin[1] >>= 2;
  1090. bboxMin[2] >>= 3;
  1091. bboxMax[0] >>= 3;
  1092. bboxMax[1] >>= 2;
  1093. bboxMax[2] >>= 3;
  1094. // get the minimum distance the end points of the line must be apart along each axis
  1095. for ( i = 0; i < 3; i++ ) {
  1096. minAxisDist[i] = 0;
  1097. }
  1098. // expand the bounding box
  1099. const int C565_BBOX_EXPAND = 2;
  1100. bboxMin[0] = ( bboxMin[0] <= C565_BBOX_EXPAND ) ? 0 : bboxMin[0] - C565_BBOX_EXPAND;
  1101. bboxMin[1] = ( bboxMin[1] <= C565_BBOX_EXPAND ) ? 0 : bboxMin[1] - C565_BBOX_EXPAND;
  1102. bboxMin[2] = ( bboxMin[2] <= C565_BBOX_EXPAND ) ? 0 : bboxMin[2] - C565_BBOX_EXPAND;
  1103. bboxMax[0] = ( bboxMax[0] >= (255>>3)-C565_BBOX_EXPAND ) ? (255>>3) : bboxMax[0] + C565_BBOX_EXPAND;
  1104. bboxMax[1] = ( bboxMax[1] >= (255>>2)-C565_BBOX_EXPAND ) ? (255>>2) : bboxMax[1] + C565_BBOX_EXPAND;
  1105. bboxMax[2] = ( bboxMax[2] >= (255>>3)-C565_BBOX_EXPAND ) ? (255>>3) : bboxMax[2] + C565_BBOX_EXPAND;
  1106. for ( i0 = bboxMin[0]; i0 <= bboxMax[0]; i0++ ) {
  1107. for ( j0 = bboxMax[0]; j0 >= bboxMin[0]; j0-- ) {
  1108. if ( abs( i0 - j0 ) < minAxisDist[0] ) {
  1109. continue;
  1110. }
  1111. for ( i1 = bboxMin[1]; i1 <= bboxMax[1]; i1++ ) {
  1112. for ( j1 = bboxMax[1]; j1 >= bboxMin[1]; j1-- ) {
  1113. if ( abs( i1 - j1 ) < minAxisDist[1] ) {
  1114. continue;
  1115. }
  1116. for ( i2 = bboxMin[2]; i2 <= bboxMax[2]; i2++ ) {
  1117. for ( j2 = bboxMax[2]; j2 >= bboxMin[2]; j2-- ) {
  1118. if ( abs( i2 - j2 ) < minAxisDist[2] ) {
  1119. continue;
  1120. }
  1121. unsigned short minColor565 = (unsigned short)( ( i0 << 11 ) | ( i1 << 5 ) | ( i2 << 0 ) );
  1122. unsigned short maxColor565 = (unsigned short)( ( j0 << 11 ) | ( j1 << 5 ) | ( j2 << 0 ) );
  1123. if ( !noBlack ) {
  1124. error = GetSquareNormalsDXT1Error( intColorBlock, maxColor565, minColor565, bestError, tempColorIndices );
  1125. if ( error < bestError ) {
  1126. bestError = error;
  1127. bestMinColor565 = minColor565;
  1128. bestMaxColor565 = maxColor565;
  1129. colorIndices = tempColorIndices;
  1130. }
  1131. } else {
  1132. if ( minColor565 <= maxColor565 ) {
  1133. SwapValues( minColor565, maxColor565 );
  1134. }
  1135. }
  1136. error = GetSquareNormalsDXT1Error( intColorBlock, minColor565, maxColor565, bestError, tempColorIndices );
  1137. if ( error < bestError ) {
  1138. bestError = error;
  1139. bestMinColor565 = minColor565;
  1140. bestMaxColor565 = maxColor565;
  1141. colorIndices = tempColorIndices;
  1142. }
  1143. }
  1144. }
  1145. }
  1146. }
  1147. }
  1148. }
  1149. ColorFrom565( bestMinColor565, minColor );
  1150. ColorFrom565( bestMaxColor565, maxColor );
  1151. return bestError;
  1152. }
  1153. /*
  1154. ========================
  1155. idDxtEncoder::GetSquareNormalsDXT5Error
  1156. params: normalBlock - 16 pixel block for which to find normal indexes
  1157. paramO: minNormal - Min normal found
  1158. paramO: maxNormal - Max normal found
  1159. ========================
  1160. */
  1161. int idDxtEncoder::GetSquareNormalsDXT5Error( const int *normalBlock, const byte *minNormal, const byte *maxNormal, int lastError, unsigned int &colorIndices, byte *alphaIndices ) const {
  1162. byte alphas[8];
  1163. byte colors[4][4];
  1164. unsigned short smin = ColorTo565( minNormal );
  1165. unsigned short smax = ColorTo565( maxNormal );
  1166. ColorFrom565( smax, colors[0] );
  1167. ColorFrom565( smin, colors[1] );
  1168. if ( smax > smin ) {
  1169. colors[2][0] = ( 2 * colors[0][0] + 1 * colors[1][0] ) / 3;
  1170. colors[2][1] = ( 2 * colors[0][1] + 1 * colors[1][1] ) / 3;
  1171. colors[2][2] = ( 2 * colors[0][2] + 1 * colors[1][2] ) / 3;
  1172. colors[3][0] = ( 1 * colors[0][0] + 2 * colors[1][0] ) / 3;
  1173. colors[3][1] = ( 1 * colors[0][1] + 2 * colors[1][1] ) / 3;
  1174. colors[3][2] = ( 1 * colors[0][2] + 2 * colors[1][2] ) / 3;
  1175. } else {
  1176. assert( smax == smin );
  1177. colors[2][0] = ( 1 * colors[0][0] + 1 * colors[1][0] ) / 2;
  1178. colors[2][1] = ( 1 * colors[0][1] + 1 * colors[1][1] ) / 2;
  1179. colors[2][2] = ( 1 * colors[0][2] + 1 * colors[1][2] ) / 2;
  1180. colors[3][0] = 0;
  1181. colors[3][1] = 0;
  1182. colors[3][2] = 0;
  1183. }
  1184. alphas[0] = maxNormal[3];
  1185. alphas[1] = minNormal[3];
  1186. if ( maxNormal[3] > minNormal[3] ) {
  1187. alphas[2] = ( 6 * alphas[0] + 1 * alphas[1] ) / 7;
  1188. alphas[3] = ( 5 * alphas[0] + 2 * alphas[1] ) / 7;
  1189. alphas[4] = ( 4 * alphas[0] + 3 * alphas[1] ) / 7;
  1190. alphas[5] = ( 3 * alphas[0] + 4 * alphas[1] ) / 7;
  1191. alphas[6] = ( 2 * alphas[0] + 5 * alphas[1] ) / 7;
  1192. alphas[7] = ( 1 * alphas[0] + 6 * alphas[1] ) / 7;
  1193. } else {
  1194. alphas[2] = ( 4 * alphas[0] + 1 * alphas[1] ) / 5;
  1195. alphas[3] = ( 3 * alphas[0] + 2 * alphas[1] ) / 5;
  1196. alphas[4] = ( 2 * alphas[0] + 3 * alphas[1] ) / 5;
  1197. alphas[5] = ( 1 * alphas[0] + 4 * alphas[1] ) / 5;
  1198. alphas[6] = 0;
  1199. alphas[7] = 255;
  1200. }
  1201. int error = 0;
  1202. int tempColorIndices[16];
  1203. int tempAlphaIndices[16];
  1204. for ( int i = 0; i < 16; i++ ) {
  1205. ALIGN16( int normal[4] );
  1206. unsigned int minDist = MAX_UNSIGNED_TYPE( int );
  1207. for ( int j = 0; j < 4; j++ ) {
  1208. normal[0] = colors[j][0];
  1209. normal[1] = colors[j][1];
  1210. normal[2] = colors[j][2];
  1211. for ( int k = 0; k < 8; k++ ) {
  1212. normal[3] = alphas[k];
  1213. unsigned int dist = NormalDistanceDXT5( normal, &normalBlock[i*4] );
  1214. if ( dist < minDist ) {
  1215. minDist = dist;
  1216. tempColorIndices[i] = j;
  1217. tempAlphaIndices[i] = k;
  1218. }
  1219. }
  1220. }
  1221. error += minDist;
  1222. if ( error >= lastError ) {
  1223. return error;
  1224. }
  1225. }
  1226. alphaIndices[0] = byte( (tempAlphaIndices[ 0] >> 0) | (tempAlphaIndices[ 1] << 3) | (tempAlphaIndices[ 2] << 6) );
  1227. alphaIndices[1] = byte( (tempAlphaIndices[ 2] >> 2) | (tempAlphaIndices[ 3] << 1) | (tempAlphaIndices[ 4] << 4) | (tempAlphaIndices[ 5] << 7) );
  1228. alphaIndices[2] = byte( (tempAlphaIndices[ 5] >> 1) | (tempAlphaIndices[ 6] << 2) | (tempAlphaIndices[ 7] << 5) );
  1229. alphaIndices[3] = byte( (tempAlphaIndices[ 8] >> 0) | (tempAlphaIndices[ 9] << 3) | (tempAlphaIndices[10] << 6) );
  1230. alphaIndices[4] = byte( (tempAlphaIndices[10] >> 2) | (tempAlphaIndices[11] << 1) | (tempAlphaIndices[12] << 4) | (tempAlphaIndices[13] << 7) );
  1231. alphaIndices[5] = byte( (tempAlphaIndices[13] >> 1) | (tempAlphaIndices[14] << 2) | (tempAlphaIndices[15] << 5) );
  1232. colorIndices = 0;
  1233. for ( int i = 0; i < 16; i++ ) {
  1234. colorIndices |= ( tempColorIndices[i] << (unsigned int)( i << 1 ) );
  1235. }
  1236. return error;
  1237. }
  1238. /*
  1239. ========================
  1240. idDxtEncoder::GetMinMaxNormalsDXT5HQ
  1241. Uses an exhaustive search to find the two RGB colors that produce the least error when used to
  1242. compress the 4x4 block. Also finds the minimum and maximum alpha values.
  1243. params: colorBlock - 4*4 input tile, 4 bytes per pixel
  1244. paramO: minColor - 4 byte Min color found
  1245. paramO: maxColor - 4 byte Max color found
  1246. ========================
  1247. */
  1248. int idDxtEncoder::GetMinMaxNormalsDXT5HQ( const byte *colorBlock, byte *minColor, byte *maxColor, unsigned int &colorIndices, byte *alphaIndices ) const {
  1249. int i;
  1250. int i0, i1, i3, j0, j1, j3;
  1251. byte bboxMin[4], bboxMax[4], minAxisDist[4];
  1252. byte tmin[4], tmax[4];
  1253. int error, bestError = MAX_TYPE( int );
  1254. unsigned int tempColorIndices;
  1255. byte tempAlphaIndices[6];
  1256. ALIGN16( int intColorBlock[16*4] );
  1257. bboxMin[0] = bboxMin[1] = bboxMin[2] = bboxMin[3] = 255;
  1258. bboxMax[0] = bboxMax[1] = bboxMax[2] = bboxMax[3] = 0;
  1259. // get color bbox
  1260. for ( i = 0; i < 16; i++ ) {
  1261. if ( colorBlock[i*4+0] < bboxMin[0] ) {
  1262. bboxMin[0] = colorBlock[i*4+0];
  1263. }
  1264. if ( colorBlock[i*4+1] < bboxMin[1] ) {
  1265. bboxMin[1] = colorBlock[i*4+1];
  1266. }
  1267. if ( colorBlock[i*4+2] < bboxMin[2] ) {
  1268. bboxMin[2] = colorBlock[i*4+2];
  1269. }
  1270. if ( colorBlock[i*4+3] < bboxMin[3] ) {
  1271. bboxMin[3] = colorBlock[i*4+3];
  1272. }
  1273. if ( colorBlock[i*4+0] > bboxMax[0] ) {
  1274. bboxMax[0] = colorBlock[i*4+0];
  1275. }
  1276. if ( colorBlock[i*4+1] > bboxMax[1] ) {
  1277. bboxMax[1] = colorBlock[i*4+1];
  1278. }
  1279. if ( colorBlock[i*4+2] > bboxMax[2] ) {
  1280. bboxMax[2] = colorBlock[i*4+2];
  1281. }
  1282. if ( colorBlock[i*4+3] > bboxMax[3] ) {
  1283. bboxMax[3] = colorBlock[i*4+3];
  1284. }
  1285. }
  1286. for ( int i = 0; i < 64; i++ ) {
  1287. intColorBlock[i] = colorBlock[i];
  1288. }
  1289. // decrease range for 565 encoding
  1290. bboxMin[0] >>= 3;
  1291. bboxMin[1] >>= 2;
  1292. bboxMax[0] >>= 3;
  1293. bboxMax[1] >>= 2;
  1294. // get the minimum distance the end points of the line must be apart along each axis
  1295. for ( i = 0; i < 4; i++ ) {
  1296. minAxisDist[i] = 0;
  1297. }
  1298. // expand the bounding box
  1299. const int C565_BBOX_EXPAND = 2;
  1300. const int ALPHA_BBOX_EXPAND = 32;
  1301. bboxMin[0] = ( bboxMin[0] <= C565_BBOX_EXPAND ) ? 0 : bboxMin[0] - C565_BBOX_EXPAND;
  1302. bboxMin[1] = ( bboxMin[1] <= C565_BBOX_EXPAND ) ? 0 : bboxMin[1] - C565_BBOX_EXPAND;
  1303. bboxMin[3] = ( bboxMin[3] <= ALPHA_BBOX_EXPAND ) ? 0 : bboxMin[3] - ALPHA_BBOX_EXPAND;
  1304. bboxMax[0] = ( bboxMax[0] >= (255>>3)-C565_BBOX_EXPAND ) ? (255>>3) : bboxMax[0] + C565_BBOX_EXPAND;
  1305. bboxMax[1] = ( bboxMax[1] >= (255>>2)-C565_BBOX_EXPAND ) ? (255>>2) : bboxMax[1] + C565_BBOX_EXPAND;
  1306. bboxMax[3] = ( bboxMax[3] >= (255)-ALPHA_BBOX_EXPAND ) ? (255) : bboxMax[3] + ALPHA_BBOX_EXPAND;
  1307. for ( i0 = bboxMin[0]; i0 <= bboxMax[0]; i0++ ) {
  1308. for ( j0 = bboxMax[0]; j0 >= bboxMin[0]; j0-- ) {
  1309. if ( abs( i0 - j0 ) < minAxisDist[0] ) {
  1310. continue;
  1311. }
  1312. for ( i1 = bboxMin[1]; i1 <= bboxMax[1]; i1++ ) {
  1313. for ( j1 = bboxMax[1]; j1 >= bboxMin[1]; j1-- ) {
  1314. if ( abs( i1 - j1 ) < minAxisDist[1] ) {
  1315. continue;
  1316. }
  1317. tmin[0] = (byte)j0 << 3;
  1318. tmin[1] = (byte)j1 << 2;
  1319. tmin[2] = 0;
  1320. tmax[0] = (byte)i0 << 3;
  1321. tmax[1] = (byte)i1 << 2;
  1322. tmax[2] = 0;
  1323. for ( i3 = bboxMin[3]; i3 <= bboxMax[3]; i3++ ) {
  1324. for ( j3 = bboxMax[3]; j3 >= bboxMin[3]; j3-- ) {
  1325. if ( abs( i3 - j3 ) < minAxisDist[3] ) {
  1326. continue;
  1327. }
  1328. tmin[3] = (byte)j3;
  1329. tmax[3] = (byte)i3;
  1330. error = GetSquareNormalsDXT5Error( intColorBlock, tmin, tmax, bestError, tempColorIndices, tempAlphaIndices );
  1331. if ( error < bestError ) {
  1332. bestError = error;
  1333. memcpy( minColor, tmin, 4 );
  1334. memcpy( maxColor, tmax, 4 );
  1335. colorIndices = tempColorIndices;
  1336. memcpy( alphaIndices, tempAlphaIndices, 6 );
  1337. }
  1338. tmin[3] = (byte)i3;
  1339. tmax[3] = (byte)j3;
  1340. error = GetSquareNormalsDXT5Error( intColorBlock, tmin, tmax, bestError, tempColorIndices, tempAlphaIndices );
  1341. if ( error < bestError ) {
  1342. bestError = error;
  1343. memcpy( minColor, tmin, 4 );
  1344. memcpy( maxColor, tmax, 4 );
  1345. colorIndices = tempColorIndices;
  1346. memcpy( alphaIndices, tempAlphaIndices, 6 );
  1347. }
  1348. }
  1349. }
  1350. }
  1351. }
  1352. }
  1353. }
  1354. return bestError;
  1355. }
  1356. /*
  1357. ========================
  1358. idDxtEncoder::GetMinMaxNormalsDXT5HQFast
  1359. Uses an exhaustive search to find the two RGB colors that produce the least error when used to
  1360. compress the 4x4 block. Also finds the minimum and maximum alpha values.
  1361. params: colorBlock - 4*4 input tile, 4 bytes per pixel
  1362. paramO: minColor - 4 byte Min color found
  1363. paramO: maxColor - 4 byte Max color found
  1364. ========================
  1365. */
  1366. int idDxtEncoder::GetMinMaxNormalsDXT5HQFast( const byte *colorBlock, byte *minColor, byte *maxColor, unsigned int &colorIndices, byte *alphaIndices ) const {
  1367. int i0, i1, i2, i3, j0, j1, j2, j3;
  1368. byte bboxMin[4], bboxMax[4], minAxisDist[4];
  1369. byte tmin[4], tmax[4];
  1370. int error, bestError = MAX_TYPE( int );
  1371. unsigned int tempColorIndices;
  1372. byte tempAlphaIndices[6];
  1373. ALIGN16( int intColorBlock[16*4] );
  1374. bboxMin[0] = bboxMin[1] = bboxMin[2] = bboxMin[3] = 255;
  1375. bboxMax[0] = bboxMax[1] = bboxMax[2] = bboxMax[3] = 0;
  1376. // get color bbox
  1377. for ( int i = 0; i < 16; i++ ) {
  1378. if ( colorBlock[i*4+0] < bboxMin[0] ) {
  1379. bboxMin[0] = colorBlock[i*4+0];
  1380. }
  1381. if ( colorBlock[i*4+1] < bboxMin[1] ) {
  1382. bboxMin[1] = colorBlock[i*4+1];
  1383. }
  1384. if ( colorBlock[i*4+2] < bboxMin[2] ) {
  1385. bboxMin[2] = colorBlock[i*4+2];
  1386. }
  1387. if ( colorBlock[i*4+3] < bboxMin[3] ) {
  1388. bboxMin[3] = colorBlock[i*4+3];
  1389. }
  1390. if ( colorBlock[i*4+0] > bboxMax[0] ) {
  1391. bboxMax[0] = colorBlock[i*4+0];
  1392. }
  1393. if ( colorBlock[i*4+1] > bboxMax[1] ) {
  1394. bboxMax[1] = colorBlock[i*4+1];
  1395. }
  1396. if ( colorBlock[i*4+2] > bboxMax[2] ) {
  1397. bboxMax[2] = colorBlock[i*4+2];
  1398. }
  1399. if ( colorBlock[i*4+3] > bboxMax[3] ) {
  1400. bboxMax[3] = colorBlock[i*4+3];
  1401. }
  1402. }
  1403. for ( int i = 0; i < 64; i++ ) {
  1404. intColorBlock[i] = colorBlock[i];
  1405. }
  1406. // decrease range for 565 encoding
  1407. bboxMin[0] >>= 3;
  1408. bboxMin[1] >>= 2;
  1409. bboxMin[2] >>= 3;
  1410. bboxMax[0] >>= 3;
  1411. bboxMax[1] >>= 2;
  1412. bboxMax[2] >>= 3;
  1413. bboxMin[3] = 0;
  1414. bboxMax[3] = 255;
  1415. // get the minimum distance the end points of the line must be apart along each axis
  1416. for ( int i = 0; i < 4; i++ ) {
  1417. minAxisDist[i] = 0;
  1418. }
  1419. // expand the bounding box
  1420. const int C565_BBOX_EXPAND = 1;
  1421. const int ALPHA_BBOX_EXPAND = 128;
  1422. #if 0 // object-space
  1423. bboxMin[0] = ( bboxMin[0] <= C565_BBOX_EXPAND ) ? 0 : bboxMin[0] - C565_BBOX_EXPAND;
  1424. bboxMax[0] = ( bboxMax[0] >= (255>>3)-C565_BBOX_EXPAND ) ? (255>>3) : bboxMax[0] + C565_BBOX_EXPAND;
  1425. bboxMin[2] = 0;
  1426. bboxMax[2] = 0;
  1427. #else
  1428. bboxMin[0] = 0;
  1429. bboxMax[0] = 0;
  1430. bboxMin[2] = ( bboxMin[2] <= C565_BBOX_EXPAND ) ? 0 : bboxMin[2] - C565_BBOX_EXPAND;
  1431. bboxMax[2] = ( bboxMax[2] >= (255>>2)-C565_BBOX_EXPAND ) ? (255>>2) : bboxMax[2] + C565_BBOX_EXPAND;
  1432. #endif
  1433. bboxMin[1] = ( bboxMin[1] <= C565_BBOX_EXPAND ) ? 0 : bboxMin[1] - C565_BBOX_EXPAND;
  1434. bboxMax[1] = ( bboxMax[1] >= (255>>2)-C565_BBOX_EXPAND ) ? (255>>2) : bboxMax[1] + C565_BBOX_EXPAND;
  1435. bboxMin[3] = ( bboxMin[3] <= ALPHA_BBOX_EXPAND ) ? 0 : bboxMin[3] - ALPHA_BBOX_EXPAND;
  1436. bboxMax[3] = ( bboxMax[3] >= (255)-ALPHA_BBOX_EXPAND ) ? (255) : bboxMax[3] + ALPHA_BBOX_EXPAND;
  1437. for ( i0 = bboxMin[0]; i0 <= bboxMax[0]; i0++ ) {
  1438. for ( j0 = bboxMax[0]; j0 >= bboxMin[0]; j0-- ) {
  1439. if ( abs( i0 - j0 ) < minAxisDist[0] ) {
  1440. continue;
  1441. }
  1442. for ( i1 = bboxMin[1]; i1 <= bboxMax[1]; i1++ ) {
  1443. for ( j1 = bboxMax[1]; j1 >= bboxMin[1]; j1-- ) {
  1444. if ( abs( i1 - j1 ) < minAxisDist[1] ) {
  1445. continue;
  1446. }
  1447. for ( i2 = bboxMin[2]; i2 <= bboxMax[2]; i2++ ) {
  1448. for ( j2 = bboxMax[2]; j2 >= bboxMin[2]; j2-- ) {
  1449. if ( abs( i2 - j2 ) < minAxisDist[2] ) {
  1450. continue;
  1451. }
  1452. unsigned short minColor565 = (unsigned short)( ( i0 << 11 ) | ( i1 << 5 ) | i2 );
  1453. unsigned short maxColor565 = (unsigned short)( ( j0 << 11 ) | ( j1 << 5 ) | j2 );
  1454. if ( minColor565 > maxColor565 ) {
  1455. SwapValues( minColor565, maxColor565 );
  1456. }
  1457. error = GetSquareNormalsDXT1Error( intColorBlock, maxColor565, minColor565, bestError, tempColorIndices );
  1458. if ( error < bestError ) {
  1459. bestError = error;
  1460. ColorFrom565( minColor565, minColor );
  1461. ColorFrom565( maxColor565, maxColor );
  1462. colorIndices = tempColorIndices;
  1463. }
  1464. }
  1465. }
  1466. }
  1467. }
  1468. }
  1469. }
  1470. bestError = MAX_TYPE( int );
  1471. memcpy( tmin, minColor, 4 );
  1472. memcpy( tmax, maxColor, 4 );
  1473. for ( i3 = bboxMin[3]; i3 <= bboxMax[3]; i3++ ) {
  1474. for ( j3 = bboxMax[3]; j3 >= bboxMin[3]; j3-- ) {
  1475. if ( abs( i3 - j3 ) < minAxisDist[3] ) {
  1476. continue;
  1477. }
  1478. tmin[3] = (byte)j3;
  1479. tmax[3] = (byte)i3;
  1480. error = GetSquareNormalsDXT5Error( intColorBlock, tmin, tmax, bestError, tempColorIndices, tempAlphaIndices );
  1481. if ( error < bestError ) {
  1482. bestError = error;
  1483. memcpy( minColor, tmin, 4 );
  1484. memcpy( maxColor, tmax, 4 );
  1485. colorIndices = tempColorIndices;
  1486. memcpy( alphaIndices, tempAlphaIndices, 6 );
  1487. }
  1488. tmin[3] = (byte)i3;
  1489. tmax[3] = (byte)j3;
  1490. error = GetSquareNormalsDXT5Error( intColorBlock, tmin, tmax, bestError, tempColorIndices, tempAlphaIndices );
  1491. if ( error < bestError ) {
  1492. bestError = error;
  1493. memcpy( minColor, tmin, 4 );
  1494. memcpy( maxColor, tmax, 4 );
  1495. colorIndices = tempColorIndices;
  1496. memcpy( alphaIndices, tempAlphaIndices, 6 );
  1497. }
  1498. }
  1499. }
  1500. return bestError;
  1501. }
  1502. /*
  1503. ========================
  1504. idDxtEncoder::FindColorIndices
  1505. params: colorBlock - 16 pixel block for which find color indexes
  1506. paramO: color0 - Min color found
  1507. paramO: color1 - Max color found
  1508. return: 4 byte color index block
  1509. ========================
  1510. */
  1511. int idDxtEncoder::FindColorIndices( const byte *colorBlock, const unsigned short color0, const unsigned short color1, unsigned int &result ) const {
  1512. int i, j;
  1513. unsigned int indexes[16];
  1514. byte colors[4][4];
  1515. ColorFrom565( color0, colors[0] );
  1516. ColorFrom565( color1, colors[1] );
  1517. if ( color0 > color1 ) {
  1518. colors[2][0] = ( 2 * colors[0][0] + 1 * colors[1][0] ) / 3;
  1519. colors[2][1] = ( 2 * colors[0][1] + 1 * colors[1][1] ) / 3;
  1520. colors[2][2] = ( 2 * colors[0][2] + 1 * colors[1][2] ) / 3;
  1521. colors[3][0] = ( 1 * colors[0][0] + 2 * colors[1][0] ) / 3;
  1522. colors[3][1] = ( 1 * colors[0][1] + 2 * colors[1][1] ) / 3;
  1523. colors[3][2] = ( 1 * colors[0][2] + 2 * colors[1][2] ) / 3;
  1524. } else {
  1525. colors[2][0] = ( 1 * colors[0][0] + 1 * colors[1][0] ) / 2;
  1526. colors[2][1] = ( 1 * colors[0][1] + 1 * colors[1][1] ) / 2;
  1527. colors[2][2] = ( 1 * colors[0][2] + 1 * colors[1][2] ) / 2;
  1528. colors[3][0] = 0;
  1529. colors[3][1] = 0;
  1530. colors[3][2] = 0;
  1531. }
  1532. int error = 0;
  1533. for ( i = 0; i < 16; i++ ) {
  1534. unsigned int minDist = MAX_UNSIGNED_TYPE( int );
  1535. for ( j = 0; j < 4; j++ ) {
  1536. unsigned int dist = ColorDistance( &colorBlock[i*4], &colors[j][0] );
  1537. if ( dist < minDist ) {
  1538. minDist = dist;
  1539. indexes[i] = j;
  1540. }
  1541. }
  1542. // accumulated error
  1543. error += minDist;
  1544. }
  1545. result = 0;
  1546. for ( i = 0; i < 16; i++ ) {
  1547. result |= ( indexes[i] << (unsigned int)( i << 1 ) );
  1548. }
  1549. return error;
  1550. }
  1551. /*
  1552. ========================
  1553. idDxtEncoder::FindAlphaIndices
  1554. params: colorBlock - 16 pixel block for which find alpha indexes
  1555. paramO: alpha0 - Min alpha found
  1556. paramO: alpha1 - Max alpha found
  1557. params: rindexes - 6 byte alpha index block
  1558. return: error metric for this compression
  1559. ========================
  1560. */
  1561. int idDxtEncoder::FindAlphaIndices( const byte *colorBlock, const int alphaOffset, const byte alpha0, const byte alpha1, byte *rindexes ) const {
  1562. int i, j;
  1563. unsigned int indexes[16];
  1564. byte alphas[8];
  1565. alphas[0] = alpha0;
  1566. alphas[1] = alpha1;
  1567. if ( alpha0 > alpha1 ) {
  1568. alphas[2] = ( 6 * alpha0 + 1 * alpha1 ) / 7;
  1569. alphas[3] = ( 5 * alpha0 + 2 * alpha1 ) / 7;
  1570. alphas[4] = ( 4 * alpha0 + 3 * alpha1 ) / 7;
  1571. alphas[5] = ( 3 * alpha0 + 4 * alpha1 ) / 7;
  1572. alphas[6] = ( 2 * alpha0 + 5 * alpha1 ) / 7;
  1573. alphas[7] = ( 1 * alpha0 + 6 * alpha1 ) / 7;
  1574. } else {
  1575. alphas[2] = ( 4 * alpha0 + 1 * alpha1 ) / 5;
  1576. alphas[3] = ( 3 * alpha0 + 2 * alpha1 ) / 5;
  1577. alphas[4] = ( 2 * alpha0 + 3 * alpha1 ) / 5;
  1578. alphas[5] = ( 1 * alpha0 + 4 * alpha1 ) / 5;
  1579. alphas[6] = 0;
  1580. alphas[7] = 255;
  1581. }
  1582. int error = 0;
  1583. for ( i = 0; i < 16; i++ ) {
  1584. unsigned int minDist = MAX_UNSIGNED_TYPE( int );
  1585. byte a = colorBlock[i*4+alphaOffset];
  1586. for ( j = 0; j < 8; j++ ) {
  1587. unsigned int dist = AlphaDistance( a, alphas[j] );
  1588. if ( dist < minDist ) {
  1589. minDist = dist;
  1590. indexes[i] = j;
  1591. }
  1592. }
  1593. error += minDist;
  1594. }
  1595. rindexes[0] = byte( (indexes[ 0] >> 0) | (indexes[ 1] << 3) | (indexes[ 2] << 6) );
  1596. rindexes[1] = byte( (indexes[ 2] >> 2) | (indexes[ 3] << 1) | (indexes[ 4] << 4) | (indexes[ 5] << 7) );
  1597. rindexes[2] = byte( (indexes[ 5] >> 1) | (indexes[ 6] << 2) | (indexes[ 7] << 5) );
  1598. rindexes[3] = byte( (indexes[ 8] >> 0) | (indexes[ 9] << 3) | (indexes[10] << 6) );
  1599. rindexes[4] = byte( (indexes[10] >> 2) | (indexes[11] << 1) | (indexes[12] << 4) | (indexes[13] << 7) );
  1600. rindexes[5] = byte( (indexes[13] >> 1) | (indexes[14] << 2) | (indexes[15] << 5) );
  1601. return error;
  1602. }
  1603. /*
  1604. ========================
  1605. idDxtEncoder::FindCTX1Indices
  1606. params: colorBlock - 16 pixel block for which find color indexes
  1607. paramO: color0 - Min color found
  1608. paramO: color1 - Max color found
  1609. return: 4 byte color index block
  1610. ========================
  1611. */
  1612. int idDxtEncoder::FindCTX1Indices( const byte *colorBlock, const byte *color0, const byte *color1, unsigned int &result ) const {
  1613. int i, j;
  1614. unsigned int indexes[16];
  1615. byte colors[4][4];
  1616. colors[0][0] = color1[0];
  1617. colors[0][1] = color1[1];
  1618. colors[1][0] = color0[0];
  1619. colors[1][1] = color0[1];
  1620. colors[2][0] = ( 2 * colors[0][0] + 1 * colors[1][0] ) / 3;
  1621. colors[2][1] = ( 2 * colors[0][1] + 1 * colors[1][1] ) / 3;
  1622. colors[3][0] = ( 1 * colors[0][0] + 2 * colors[1][0] ) / 3;
  1623. colors[3][1] = ( 1 * colors[0][1] + 2 * colors[1][1] ) / 3;
  1624. int error = 0;
  1625. for ( i = 0; i < 16; i++ ) {
  1626. unsigned int minDist = MAX_UNSIGNED_TYPE( int );
  1627. for ( j = 0; j < 4; j++ ) {
  1628. unsigned int dist = CTX1Distance( &colorBlock[i*4], &colors[j][0] );
  1629. if ( dist < minDist ) {
  1630. minDist = dist;
  1631. indexes[i] = j;
  1632. }
  1633. }
  1634. // accumulated error
  1635. error += minDist;
  1636. }
  1637. result = 0;
  1638. for ( i = 0; i < 16; i++ ) {
  1639. result |= ( indexes[i] << (unsigned int)( i << 1 ) );
  1640. }
  1641. return error;
  1642. }
  1643. /*
  1644. ========================
  1645. idDxtEncoder::CompressImageDXT1HQ
  1646. params: inBuf - image to compress
  1647. paramO: outBuf - result of compression
  1648. params: width - width of image
  1649. params: height - height of image
  1650. ========================
  1651. */
  1652. void idDxtEncoder::CompressImageDXT1HQ( const byte *inBuf, byte *outBuf, int width, int height ) {
  1653. ALIGN16( byte block[64] );
  1654. unsigned int colorIndices1;
  1655. unsigned int colorIndices2;
  1656. byte col1[4];
  1657. byte col2[4];
  1658. int error1;
  1659. int error2;
  1660. this->width = width;
  1661. this->height = height;
  1662. this->outData = outBuf;
  1663. if ( width > 4 && ( width & 3 ) != 0 ) {
  1664. return;
  1665. }
  1666. if ( height > 4 && ( height & 3 ) != 0 ) {
  1667. return;
  1668. }
  1669. if ( width < 4 || height < 4 ) {
  1670. WriteTinyColorDXT1( inBuf, width, height );
  1671. return;
  1672. }
  1673. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  1674. for ( int i = 0; i < width; i += 4 ) {
  1675. ExtractBlock( inBuf + i * 4, width, block );
  1676. GetMinMaxColorsHQ( block, col1, col2, false );
  1677. // Write out color data. Try and find minimum error for the two encoding methods.
  1678. unsigned short scol1 = ColorTo565( col1 );
  1679. unsigned short scol2 = ColorTo565( col2 );
  1680. error1 = FindColorIndices( block, scol1, scol2, colorIndices1 );
  1681. error2 = FindColorIndices( block, scol2, scol1, colorIndices2 );
  1682. if ( error1 < error2 ) {
  1683. EmitUShort( scol1 );
  1684. EmitUShort( scol2 );
  1685. EmitUInt( colorIndices1 );
  1686. } else {
  1687. EmitUShort( scol2 );
  1688. EmitUShort( scol1 );
  1689. EmitUInt( colorIndices2 );
  1690. }
  1691. //idLib::Printf( "\r%3d%%", ( j * width + i ) * 100 / ( width * height ) );
  1692. }
  1693. outData += dstPadding;
  1694. inBuf += srcPadding;
  1695. }
  1696. //idLib::Printf( "\r100%%\n" );
  1697. }
  1698. /*
  1699. ========================
  1700. idDxtEncoder::CompressImageDXT5HQ
  1701. params: inBuf - image to compress
  1702. paramO: outBuf - result of compression
  1703. params: width - width of image
  1704. params: height - height of image
  1705. ========================
  1706. */
  1707. void idDxtEncoder::CompressImageDXT5HQ( const byte *inBuf, byte *outBuf, int width, int height ) {
  1708. ALIGN16( byte block[64] );
  1709. byte alphaIndices1[6];
  1710. byte alphaIndices2[6];
  1711. unsigned int colorIndices;
  1712. byte col1[4];
  1713. byte col2[4];
  1714. int error1;
  1715. int error2;
  1716. this->width = width;
  1717. this->height = height;
  1718. this->outData = outBuf;
  1719. if ( width > 4 && ( width & 3 ) != 0 ) {
  1720. return;
  1721. }
  1722. if ( height > 4 && ( height & 3 ) != 0 ) {
  1723. return;
  1724. }
  1725. if ( width < 4 || height < 4 ) {
  1726. WriteTinyColorDXT5( inBuf, width, height );
  1727. return;
  1728. }
  1729. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  1730. for ( int i = 0; i < width; i += 4 ) {
  1731. ExtractBlock( inBuf + i * 4, width, block );
  1732. GetMinMaxColorsHQ( block, col1, col2, true );
  1733. GetMinMaxAlphaHQ( block, 3, col1, col2 );
  1734. // Write out alpha data. Try and find minimum error for the two encoding methods.
  1735. error1 = FindAlphaIndices( block, 3, col1[3], col2[3], alphaIndices1 );
  1736. error2 = FindAlphaIndices( block, 3, col2[3], col1[3], alphaIndices2 );
  1737. if ( error1 < error2 ) {
  1738. EmitByte( col1[3] );
  1739. EmitByte( col2[3] );
  1740. EmitByte( alphaIndices1[0] );
  1741. EmitByte( alphaIndices1[1] );
  1742. EmitByte( alphaIndices1[2] );
  1743. EmitByte( alphaIndices1[3] );
  1744. EmitByte( alphaIndices1[4] );
  1745. EmitByte( alphaIndices1[5] );
  1746. } else {
  1747. EmitByte( col2[3] );
  1748. EmitByte( col1[3] );
  1749. EmitByte( alphaIndices2[0] );
  1750. EmitByte( alphaIndices2[1] );
  1751. EmitByte( alphaIndices2[2] );
  1752. EmitByte( alphaIndices2[3] );
  1753. EmitByte( alphaIndices2[4] );
  1754. EmitByte( alphaIndices2[5] );
  1755. }
  1756. #ifdef NVIDIA_7X_HARDWARE_BUG_FIX
  1757. NV4XHardwareBugFix( col2, col1 );
  1758. #endif
  1759. // Write out color data. Always take the path with 4 interpolated values.
  1760. unsigned short scol1 = ColorTo565( col1 );
  1761. unsigned short scol2 = ColorTo565( col2 );
  1762. EmitUShort( scol1 );
  1763. EmitUShort( scol2 );
  1764. FindColorIndices( block, scol1, scol2, colorIndices );
  1765. EmitUInt( colorIndices );
  1766. //idLib::Printf( "\r%3d%%", ( j * width + i ) * 100 / ( width * height ) );
  1767. }
  1768. outData += dstPadding;
  1769. inBuf += srcPadding;
  1770. }
  1771. //idLib::Printf( "\r100%%\n" );
  1772. }
  1773. /*
  1774. ========================
  1775. idDxtEncoder::CompressImageCTX1HQ
  1776. params: inBuf - image to compress
  1777. paramO: outBuf - result of compression
  1778. params: width - width of image
  1779. params: height - height of image
  1780. ========================
  1781. */
  1782. void idDxtEncoder::CompressImageCTX1HQ( const byte *inBuf, byte *outBuf, int width, int height ) {
  1783. ALIGN16( byte block[64] );
  1784. unsigned int colorIndices;
  1785. byte col1[4];
  1786. byte col2[4];
  1787. this->width = width;
  1788. this->height = height;
  1789. this->outData = outBuf;
  1790. if ( width > 4 && ( width & 3 ) != 0 ) {
  1791. return;
  1792. }
  1793. if ( height > 4 && ( height & 3 ) != 0 ) {
  1794. return;
  1795. }
  1796. if ( width < 4 || height < 4 ) {
  1797. WriteTinyColorCTX1DXT5A( inBuf, width, height );
  1798. return;
  1799. }
  1800. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  1801. for ( int i = 0; i < width; i += 4 ) {
  1802. ExtractBlock( inBuf + i * 4, width, block );
  1803. GetMinMaxCTX1HQ( block, col1, col2 );
  1804. EmitByte( col2[0] );
  1805. EmitByte( col2[1] );
  1806. EmitByte( col1[0] );
  1807. EmitByte( col1[1] );
  1808. FindCTX1Indices( block, col1, col2, colorIndices );
  1809. EmitUInt( colorIndices );
  1810. //idLib::Printf( "\r%3d%%", ( j * width + i ) * 100 / ( width * height ) );
  1811. }
  1812. outData += dstPadding;
  1813. inBuf += srcPadding;
  1814. }
  1815. //idLib::Printf( "\r100%%\n" );
  1816. }
  1817. /*
  1818. ========================
  1819. idDxtEncoder::ScaleYCoCg
  1820. params: colorBlock - 16 pixel block for which find color indexes
  1821. ========================
  1822. */
  1823. void idDxtEncoder::ScaleYCoCg( byte *colorBlock ) const {
  1824. ALIGN16( byte minColor[4] );
  1825. ALIGN16( byte maxColor[4] );
  1826. minColor[0] = minColor[1] = minColor[2] = minColor[3] = 255;
  1827. maxColor[0] = maxColor[1] = maxColor[2] = maxColor[3] = 0;
  1828. for ( int i = 0; i < 16; i++ ) {
  1829. if ( colorBlock[i*4+0] < minColor[0] ) {
  1830. minColor[0] = colorBlock[i*4+0];
  1831. }
  1832. if ( colorBlock[i*4+1] < minColor[1] ) {
  1833. minColor[1] = colorBlock[i*4+1];
  1834. }
  1835. if ( colorBlock[i*4+0] > maxColor[0] ) {
  1836. maxColor[0] = colorBlock[i*4+0];
  1837. }
  1838. if ( colorBlock[i*4+1] > maxColor[1] ) {
  1839. maxColor[1] = colorBlock[i*4+1];
  1840. }
  1841. }
  1842. int m0 = abs( minColor[0] - 128 );
  1843. int m1 = abs( minColor[1] - 128 );
  1844. int m2 = abs( maxColor[0] - 128 );
  1845. int m3 = abs( maxColor[1] - 128 );
  1846. if ( m1 > m0 ) m0 = m1;
  1847. if ( m3 > m2 ) m2 = m3;
  1848. if ( m2 > m0 ) m0 = m2;
  1849. const int s0 = 128 / 2 - 1;
  1850. const int s1 = 128 / 4 - 1;
  1851. int scale = 1 + ( m0 <= s0 ) + 2 * ( m0 <= s1 );
  1852. for ( int i = 0; i < 16; i++ ) {
  1853. colorBlock[i*4+0] = byte( ( colorBlock[i*4+0] - 128 ) * scale + 128 );
  1854. colorBlock[i*4+1] = byte( ( colorBlock[i*4+1] - 128 ) * scale + 128 );
  1855. colorBlock[i*4+2] = byte( ( scale - 1 ) << 3 );
  1856. }
  1857. }
  1858. /*
  1859. ========================
  1860. idDxtEncoder::CompressYCoCgDXT5HQ
  1861. params: inBuf - image to compress
  1862. paramO: outBuf - result of compression
  1863. params: width - width of image
  1864. params: height - height of image
  1865. ========================
  1866. */
  1867. void idDxtEncoder::CompressYCoCgDXT5HQ( const byte *inBuf, byte *outBuf, int width, int height ) {
  1868. ALIGN16( byte block[64] );
  1869. byte alphaIndices1[6];
  1870. byte alphaIndices2[6];
  1871. unsigned int colorIndices;
  1872. byte col1[4];
  1873. byte col2[4];
  1874. int error1;
  1875. int error2;
  1876. assert( HasConstantValuePer4x4Block( inBuf, width, height, 2 ) );
  1877. this->width = width;
  1878. this->height = height;
  1879. this->outData = outBuf;
  1880. if ( width > 4 && ( width & 3 ) != 0 ) {
  1881. return;
  1882. }
  1883. if ( height > 4 && ( height & 3 ) != 0 ) {
  1884. return;
  1885. }
  1886. if ( width < 4 || height < 4 ) {
  1887. WriteTinyColorDXT5( inBuf, width, height );
  1888. return;
  1889. }
  1890. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  1891. for ( int i = 0; i < width; i += 4 ) {
  1892. ExtractBlock( inBuf + i * 4, width, block );
  1893. ScaleYCoCg( block );
  1894. GetMinMaxColorsHQ( block, col1, col2, true );
  1895. GetMinMaxAlphaHQ( block, 3, col1, col2 );
  1896. // Write out alpha data. Try and find minimum error for the two encoding methods.
  1897. error1 = FindAlphaIndices( block, 3, col1[3], col2[3], alphaIndices1 );
  1898. error2 = FindAlphaIndices( block, 3, col2[3], col1[3], alphaIndices2 );
  1899. if ( error1 < error2 ) {
  1900. EmitByte( col1[3] );
  1901. EmitByte( col2[3] );
  1902. EmitByte( alphaIndices1[0] );
  1903. EmitByte( alphaIndices1[1] );
  1904. EmitByte( alphaIndices1[2] );
  1905. EmitByte( alphaIndices1[3] );
  1906. EmitByte( alphaIndices1[4] );
  1907. EmitByte( alphaIndices1[5] );
  1908. } else {
  1909. EmitByte( col2[3] );
  1910. EmitByte( col1[3] );
  1911. EmitByte( alphaIndices2[0] );
  1912. EmitByte( alphaIndices2[1] );
  1913. EmitByte( alphaIndices2[2] );
  1914. EmitByte( alphaIndices2[3] );
  1915. EmitByte( alphaIndices2[4] );
  1916. EmitByte( alphaIndices2[5] );
  1917. }
  1918. #ifdef NVIDIA_7X_HARDWARE_BUG_FIX
  1919. NV4XHardwareBugFix( col2, col1 );
  1920. #endif
  1921. // Write out color data. Always take the path with 4 interpolated values.
  1922. unsigned short scol1 = ColorTo565( col1 );
  1923. unsigned short scol2 = ColorTo565( col2 );
  1924. EmitUShort( scol1 );
  1925. EmitUShort( scol2 );
  1926. FindColorIndices( block, scol1, scol2, colorIndices );
  1927. EmitUInt( colorIndices );
  1928. //idLib::Printf( "\r%3d%%", ( j * width + i ) * 100 / ( width * height ) );
  1929. }
  1930. outData += dstPadding;
  1931. inBuf += srcPadding;
  1932. }
  1933. //idLib::Printf( "\r100%%\n" );
  1934. }
  1935. /*
  1936. ========================
  1937. idDxtEncoder::CompressYCoCgCTX1DXT5AHQ
  1938. params: inBuf - image to compress
  1939. paramO: outBuf - result of compression
  1940. params: width - width of image
  1941. params: height - height of image
  1942. ========================
  1943. */
  1944. void idDxtEncoder::CompressYCoCgCTX1DXT5AHQ( const byte *inBuf, byte *outBuf, int width, int height ) {
  1945. ALIGN16( byte block[64] );
  1946. byte alphaIndices1[6];
  1947. byte alphaIndices2[6];
  1948. unsigned int colorIndices;
  1949. byte col1[4];
  1950. byte col2[4];
  1951. int error1;
  1952. int error2;
  1953. assert( HasConstantValuePer4x4Block( inBuf, width, height, 2 ) );
  1954. this->width = width;
  1955. this->height = height;
  1956. this->outData = outBuf;
  1957. if ( width > 4 && ( width & 3 ) != 0 ) {
  1958. return;
  1959. }
  1960. if ( height > 4 && ( height & 3 ) != 0 ) {
  1961. return;
  1962. }
  1963. if ( width < 4 || height < 4 ) {
  1964. WriteTinyColorCTX1DXT5A( inBuf, width, height );
  1965. return;
  1966. }
  1967. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  1968. for ( int i = 0; i < width; i += 4 ) {
  1969. ExtractBlock( inBuf + i * 4, width, block );
  1970. GetMinMaxAlphaHQ( block, 3, col1, col2 );
  1971. // Write out alpha data. Try and find minimum error for the two encoding methods.
  1972. error1 = FindAlphaIndices( block, 3, col1[3], col2[3], alphaIndices1 );
  1973. error2 = FindAlphaIndices( block, 3, col2[3], col1[3], alphaIndices2 );
  1974. if ( error1 < error2 ) {
  1975. EmitByte( col1[3] );
  1976. EmitByte( col2[3] );
  1977. EmitByte( alphaIndices1[0] );
  1978. EmitByte( alphaIndices1[1] );
  1979. EmitByte( alphaIndices1[2] );
  1980. EmitByte( alphaIndices1[3] );
  1981. EmitByte( alphaIndices1[4] );
  1982. EmitByte( alphaIndices1[5] );
  1983. } else {
  1984. EmitByte( col2[3] );
  1985. EmitByte( col1[3] );
  1986. EmitByte( alphaIndices2[0] );
  1987. EmitByte( alphaIndices2[1] );
  1988. EmitByte( alphaIndices2[2] );
  1989. EmitByte( alphaIndices2[3] );
  1990. EmitByte( alphaIndices2[4] );
  1991. EmitByte( alphaIndices2[5] );
  1992. }
  1993. GetMinMaxCTX1HQ( block, col1, col2 );
  1994. EmitByte( col2[0] );
  1995. EmitByte( col2[1] );
  1996. EmitByte( col1[0] );
  1997. EmitByte( col1[1] );
  1998. FindCTX1Indices( block, col1, col2, colorIndices );
  1999. EmitUInt( colorIndices );
  2000. //idLib::Printf( "\r%3d%%", ( j * width + i ) * 100 / ( width * height ) );
  2001. }
  2002. outData += dstPadding;
  2003. inBuf += srcPadding;
  2004. }
  2005. //idLib::Printf( "\r100%%\n" );
  2006. }
  2007. /*
  2008. ========================
  2009. idDxtEncoder::RotateNormalsDXT1
  2010. ========================
  2011. */
  2012. void idDxtEncoder::RotateNormalsDXT1( byte *block ) const {
  2013. byte rotatedBlock[64];
  2014. byte col1[4];
  2015. byte col2[4];
  2016. int bestError = MAX_TYPE( int );
  2017. int bestRotation = 0;
  2018. for ( int i = 0; i < 32; i += 1 ) {
  2019. int r = ( i << 3 ) | ( i >> 2 );
  2020. float angle = ( r / 255.0f ) * idMath::PI;
  2021. float s = sin( angle );
  2022. float c = cos( angle );
  2023. for ( int j = 0; j < 16; j++ ) {
  2024. float x = block[j*4+0] / 255.0f * 2.0f - 1.0f;
  2025. float y = block[j*4+1] / 255.0f * 2.0f - 1.0f;
  2026. float rx = c * x - s * y;
  2027. float ry = s * x + c * y;
  2028. rotatedBlock[j*4+0] = idMath::Ftob( ( rx + 1.0f ) / 2.0f * 255.0f );
  2029. rotatedBlock[j*4+1] = idMath::Ftob( ( ry + 1.0f ) / 2.0f * 255.0f );
  2030. }
  2031. int error = GetMinMaxColorsHQ( rotatedBlock, col1, col2, true );
  2032. if ( error < bestError ) {
  2033. bestError = error;
  2034. bestRotation = r;
  2035. }
  2036. }
  2037. float angle = ( bestRotation / 255.0f ) * idMath::PI;
  2038. float s = sin( angle );
  2039. float c = cos( angle );
  2040. for ( int j = 0; j < 16; j++ ) {
  2041. float x = block[j*4+0] / 255.0f * 2.0f - 1.0f;
  2042. float y = block[j*4+1] / 255.0f * 2.0f - 1.0f;
  2043. float rx = c * x - s * y;
  2044. float ry = s * x + c * y;
  2045. block[j*4+0] = idMath::Ftob( ( rx + 1.0f ) / 2.0f * 255.0f );
  2046. block[j*4+1] = idMath::Ftob( ( ry + 1.0f ) / 2.0f * 255.0f );
  2047. block[j*4+2] = (byte)bestRotation;
  2048. }
  2049. }
  2050. /*
  2051. ========================
  2052. idDxtEncoder::CompressNormalMapDXT1HQ
  2053. params: inBuf - image to compress
  2054. paramO: outBuf - result of compression
  2055. params: width - width of image
  2056. params: height - height of image
  2057. ========================
  2058. */
  2059. void idDxtEncoder::CompressNormalMapDXT1HQ( const byte *inBuf, byte *outBuf, int width, int height ) {
  2060. ALIGN16( byte block[64] );
  2061. unsigned int colorIndices;
  2062. byte col1[4];
  2063. byte col2[4];
  2064. this->width = width;
  2065. this->height = height;
  2066. this->outData = outBuf;
  2067. if ( width > 4 && ( width & 3 ) != 0 ) {
  2068. return;
  2069. }
  2070. if ( height > 4 && ( height & 3 ) != 0 ) {
  2071. return;
  2072. }
  2073. if ( width < 4 || height < 4 ) {
  2074. WriteTinyColorDXT1( inBuf, width, height );
  2075. return;
  2076. }
  2077. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  2078. for ( int i = 0; i < width; i += 4 ) {
  2079. ExtractBlock( inBuf + i * 4, width, block );
  2080. for ( int k = 0; k < 16; k++ ) {
  2081. block[k*4+2] = 0;
  2082. }
  2083. GetMinMaxColorsHQ( block, col1, col2, true );
  2084. // Write out color data. Always take the path with 4 interpolated values.
  2085. unsigned short scol1 = ColorTo565( col1 );
  2086. unsigned short scol2 = ColorTo565( col2 );
  2087. EmitUShort( scol1 );
  2088. EmitUShort( scol2 );
  2089. FindColorIndices( block, scol1, scol2, colorIndices );
  2090. EmitUInt( colorIndices );
  2091. //idLib::Printf( "\r%3d%%", ( j * width + i * 4 ) * 100 / ( width * height ) );
  2092. }
  2093. outData += dstPadding;
  2094. inBuf += srcPadding;
  2095. }
  2096. //idLib::Printf( "\r100%%\n" );
  2097. }
  2098. /*
  2099. ========================
  2100. idDxtEncoder::CompressNormalMapDXT1RenormalizeHQ
  2101. params: inBuf - image to compress
  2102. paramO: outBuf - result of compression
  2103. params: width - width of image
  2104. params: height - height of image
  2105. ========================
  2106. */
  2107. void idDxtEncoder::CompressNormalMapDXT1RenormalizeHQ( const byte *inBuf, byte *outBuf, int width, int height ) {
  2108. ALIGN16( byte block[64] );
  2109. unsigned int colorIndices;
  2110. byte col1[4];
  2111. byte col2[4];
  2112. this->width = width;
  2113. this->height = height;
  2114. this->outData = outBuf;
  2115. if ( width > 4 && ( width & 3 ) != 0 ) {
  2116. return;
  2117. }
  2118. if ( height > 4 && ( height & 3 ) != 0 ) {
  2119. return;
  2120. }
  2121. if ( width < 4 || height < 4 ) {
  2122. WriteTinyColorDXT1( inBuf, width, height );
  2123. return;
  2124. }
  2125. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  2126. for ( int i = 0; i < width; i += 4 ) {
  2127. ExtractBlock( inBuf + i * 4, width, block );
  2128. // clear alpha channel
  2129. for ( int k = 0; k < 16; k++ ) {
  2130. block[k*4+3] = 0;
  2131. }
  2132. GetMinMaxNormalsDXT1HQ( block, col1, col2, colorIndices, true );
  2133. // Write out color data. Always take the path with 4 interpolated values.
  2134. unsigned short scol1 = ColorTo565( col1 );
  2135. unsigned short scol2 = ColorTo565( col2 );
  2136. EmitUShort( scol1 );
  2137. EmitUShort( scol2 );
  2138. EmitUInt( colorIndices );
  2139. ////idLib::Printf( "\r%3d%%", ( j * width + i * 4 ) * 100 / ( width * height ) );
  2140. }
  2141. outData += dstPadding;
  2142. inBuf += srcPadding;
  2143. }
  2144. ////idLib::Printf( "\r100%%\n" );
  2145. }
  2146. #define USE_SCALE 1
  2147. #define USE_BIAS 1
  2148. static int c_blocks;
  2149. static int c_scaled;
  2150. static int c_scaled2x;
  2151. static int c_scaled4x;
  2152. static int c_differentBias;
  2153. static int c_biasHelped;
  2154. /*
  2155. ========================
  2156. idDxtEncoder::BiasScaleNormalY
  2157. * scale2x = 33%
  2158. * scale4x = 23%
  2159. * bias + scale2x = 30%
  2160. * bias + scale4x = 55%
  2161. ========================
  2162. */
  2163. void idDxtEncoder::BiasScaleNormalY( byte *colorBlock ) const {
  2164. byte minColor = 255;
  2165. byte maxColor = 0;
  2166. for ( int i = 0; i < 16; i++ ) {
  2167. if ( colorBlock[i*4+1] < minColor ) {
  2168. minColor = colorBlock[i*4+1];
  2169. }
  2170. if ( colorBlock[i*4+1] > maxColor ) {
  2171. maxColor = colorBlock[i*4+1];
  2172. }
  2173. }
  2174. int bestBias = 128;
  2175. int bestRange = Max( abs( minColor - bestBias ), abs( maxColor - bestBias ) );
  2176. #if USE_BIAS
  2177. for ( int i = 0; i < 32; i++ ) {
  2178. int bias = ( ( i << 3 ) | ( i >> 2 ) ) - 4;
  2179. int range = Max( abs( minColor - bias ), abs( maxColor - bias ) );
  2180. if ( range < bestRange ) {
  2181. bestRange = range;
  2182. bestBias = bias;
  2183. }
  2184. }
  2185. #endif
  2186. const int s0 = 128 / 2 - 1;
  2187. const int s1 = 128 / 4 - 1;
  2188. #if USE_SCALE
  2189. int scale = 1 + ( bestRange <= s0 ) + 2 * ( bestRange <= s1 );
  2190. #else
  2191. int scale = 1;
  2192. #endif
  2193. if ( scale == 1 ) {
  2194. bestBias = 128;
  2195. } else {
  2196. c_scaled++;
  2197. if ( scale == 2 ) c_scaled2x++;
  2198. if ( scale == 4 ) c_scaled4x++;
  2199. if ( bestBias != 128 ) {
  2200. c_differentBias++;
  2201. int r = Max( abs( minColor - 128 ), abs( maxColor - 128 ) );
  2202. int s = 1 + ( r <= s0 ) + 2 * ( r <= s1 );
  2203. if ( scale > s ) {
  2204. c_biasHelped++;
  2205. }
  2206. }
  2207. }
  2208. c_blocks++;
  2209. for ( int i = 0; i < 16; i++ ) {
  2210. colorBlock[i*4+0] = byte( bestBias + 4 );
  2211. colorBlock[i*4+1] = byte( ( colorBlock[i*4+1] - bestBias ) * scale + 128 );
  2212. colorBlock[i*4+2] = byte( ( scale - 1 ) << 3 );
  2213. }
  2214. }
  2215. /*
  2216. ========================
  2217. idDxtEncoder::RotateNormalsDXT5
  2218. ========================
  2219. */
  2220. void idDxtEncoder::RotateNormalsDXT5( byte *block ) const {
  2221. byte rotatedBlock[64];
  2222. byte col1[4];
  2223. byte col2[4];
  2224. int bestError = MAX_TYPE( int );
  2225. int bestRotation = 0;
  2226. int bestScale = 1;
  2227. for ( int i = 0; i < 32; i += 1 ) {
  2228. int r = ( i << 3 ) | ( i >> 2 );
  2229. float angle = ( r / 255.0f ) * idMath::PI;
  2230. float s = sin( angle );
  2231. float c = cos( angle );
  2232. for ( int j = 0; j < 16; j++ ) {
  2233. float x = block[j*4+3] / 255.0f * 2.0f - 1.0f;
  2234. float y = block[j*4+1] / 255.0f * 2.0f - 1.0f;
  2235. float rx = c * x - s * y;
  2236. float ry = s * x + c * y;
  2237. rotatedBlock[j*4+3] = idMath::Ftob( ( rx + 1.0f ) / 2.0f * 255.0f );
  2238. rotatedBlock[j*4+1] = idMath::Ftob( ( ry + 1.0f ) / 2.0f * 255.0f );
  2239. }
  2240. #if USE_SCALE
  2241. byte minColor = 255;
  2242. byte maxColor = 0;
  2243. for ( int j = 0; j < 16; j++ ) {
  2244. if ( rotatedBlock[j*4+1] < minColor ) {
  2245. minColor = rotatedBlock[j*4+1];
  2246. }
  2247. if ( rotatedBlock[j*4+1] > maxColor ) {
  2248. maxColor = rotatedBlock[j*4+1];
  2249. }
  2250. }
  2251. const int s0 = 128 / 2 - 1;
  2252. const int s1 = 128 / 4 - 1;
  2253. int range = Max( abs( minColor - 128 ), abs( maxColor - 128 ) );
  2254. int scale = 1 + ( range <= s0 ) + 2 * ( range <= s1 );
  2255. for ( int j = 0; j < 16; j++ ) {
  2256. rotatedBlock[j*4+1] = byte( ( rotatedBlock[j*4+1] - 128 ) * scale + 128 );
  2257. }
  2258. #endif
  2259. int errorY = GetMinMaxNormalYHQ( rotatedBlock, col1, col2, true, scale );
  2260. int errorX = GetMinMaxAlphaHQ( rotatedBlock, 3, col1, col2 );
  2261. int error = errorX + errorY;
  2262. if ( error < bestError ) {
  2263. bestError = error;
  2264. bestRotation = r;
  2265. bestScale = scale;
  2266. }
  2267. }
  2268. float angle = ( bestRotation / 255.0f ) * idMath::PI;
  2269. float s = sin( angle );
  2270. float c = cos( angle );
  2271. for ( int j = 0; j < 16; j++ ) {
  2272. float x = block[j*4+3] / 255.0f * 2.0f - 1.0f;
  2273. float y = block[j*4+1] / 255.0f * 2.0f - 1.0f;
  2274. float rx = c * x - s * y;
  2275. float ry = s * x + c * y;
  2276. block[j*4+0] = (byte)bestRotation;
  2277. block[j*4+1] = idMath::Ftob( ( ry + 1.0f ) / 2.0f * 255.0f );
  2278. block[j*4+3] = idMath::Ftob( ( rx + 1.0f ) / 2.0f * 255.0f );
  2279. #if USE_SCALE
  2280. block[j*4+1] = byte( ( block[j*4+1] - 128 ) * bestScale + 128 );
  2281. block[j*4+2] = byte( ( bestScale - 1 ) << 3 );
  2282. #endif
  2283. }
  2284. }
  2285. /*
  2286. ========================
  2287. idDxtEncoder::CompressNormalMapDXT5HQ
  2288. params: inBuf - image to compress
  2289. paramO: outBuf - result of compression
  2290. params: width - width of image
  2291. params: height - height of image
  2292. ========================
  2293. */
  2294. void idDxtEncoder::CompressNormalMapDXT5HQ( const byte *inBuf, byte *outBuf, int width, int height ) {
  2295. ALIGN16( byte block[64] );
  2296. byte alphaIndices1[6];
  2297. byte alphaIndices2[6];
  2298. unsigned int colorIndices;
  2299. byte col1[4];
  2300. byte col2[4];
  2301. int error1;
  2302. int error2;
  2303. this->width = width;
  2304. this->height = height;
  2305. this->outData = outBuf;
  2306. if ( width > 4 && ( width & 3 ) != 0 ) {
  2307. return;
  2308. }
  2309. if ( height > 4 && ( height & 3 ) != 0 ) {
  2310. return;
  2311. }
  2312. if ( width < 4 || height < 4 ) {
  2313. WriteTinyColorDXT5( inBuf, width, height );
  2314. return;
  2315. }
  2316. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  2317. for ( int i = 0; i < width; i += 4 ) {
  2318. ExtractBlock( inBuf + i * 4, width, block );
  2319. // swizzle components
  2320. for ( int k = 0; k < 16; k++ ) {
  2321. block[k*4+3] = block[k*4+0];
  2322. block[k*4+0] = 0;
  2323. block[k*4+2] = 0;
  2324. }
  2325. //BiasScaleNormalY( block );
  2326. //RotateNormalsDXT5( block );
  2327. GetMinMaxNormalYHQ( block, col1, col2, true, 1 );
  2328. GetMinMaxAlphaHQ( block, 3, col1, col2 );
  2329. // Write out alpha data. Try and find minimum error for the two encoding methods.
  2330. error1 = FindAlphaIndices( block, 3, col1[3], col2[3], alphaIndices1 );
  2331. error2 = FindAlphaIndices( block, 3, col2[3], col1[3], alphaIndices2 );
  2332. if ( error1 < error2 ) {
  2333. EmitByte( col1[3] );
  2334. EmitByte( col2[3] );
  2335. EmitByte( alphaIndices1[0] );
  2336. EmitByte( alphaIndices1[1] );
  2337. EmitByte( alphaIndices1[2] );
  2338. EmitByte( alphaIndices1[3] );
  2339. EmitByte( alphaIndices1[4] );
  2340. EmitByte( alphaIndices1[5] );
  2341. } else {
  2342. EmitByte( col2[3] );
  2343. EmitByte( col1[3] );
  2344. EmitByte( alphaIndices2[0] );
  2345. EmitByte( alphaIndices2[1] );
  2346. EmitByte( alphaIndices2[2] );
  2347. EmitByte( alphaIndices2[3] );
  2348. EmitByte( alphaIndices2[4] );
  2349. EmitByte( alphaIndices2[5] );
  2350. }
  2351. #ifdef NVIDIA_7X_HARDWARE_BUG_FIX
  2352. NV4XHardwareBugFix( col2, col1 );
  2353. #endif
  2354. // Write out color data. Always take the path with 4 interpolated values.
  2355. unsigned short scol1 = ColorTo565( col1 );
  2356. unsigned short scol2 = ColorTo565( col2 );
  2357. EmitUShort( scol1 );
  2358. EmitUShort( scol2 );
  2359. FindColorIndices( block, scol1, scol2, colorIndices );
  2360. EmitUInt( colorIndices );
  2361. //idLib::Printf( "\r%3d%%", ( j * width + i ) * 100 / ( width * height ) );
  2362. }
  2363. outData += dstPadding;
  2364. inBuf += srcPadding;
  2365. }
  2366. //idLib::Printf( "\r100%%\n" );
  2367. }
  2368. /*
  2369. ========================
  2370. idDxtEncoder::CompressNormalMapDXT5RenormalizeHQ
  2371. params: inBuf - image to compress
  2372. paramO: outBuf - result of compression
  2373. params: width - width of image
  2374. params: height - height of image
  2375. ========================
  2376. */
  2377. void idDxtEncoder::CompressNormalMapDXT5RenormalizeHQ( const byte *inBuf, byte *outBuf, int width, int height ) {
  2378. ALIGN16( byte block[64] );
  2379. unsigned int colorIndices;
  2380. byte alphaIndices[6];
  2381. byte col1[4];
  2382. byte col2[4];
  2383. this->width = width;
  2384. this->height = height;
  2385. this->outData = outBuf;
  2386. if ( width > 4 && ( width & 3 ) != 0 ) {
  2387. return;
  2388. }
  2389. if ( height > 4 && ( height & 3 ) != 0 ) {
  2390. return;
  2391. }
  2392. if ( width < 4 || height < 4 ) {
  2393. WriteTinyColorDXT5( inBuf, width, height );
  2394. return;
  2395. }
  2396. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  2397. for ( int i = 0; i < width; i += 4 ) {
  2398. ExtractBlock( inBuf + i * 4, width, block );
  2399. // swizzle components
  2400. for ( int k = 0; k < 16; k++ ) {
  2401. #if 0 // object-space
  2402. block[k*4+3] = block[k*4+2];
  2403. block[k*4+2] = 0;
  2404. #else
  2405. block[k*4+3] = block[k*4+0];
  2406. block[k*4+0] = 0;
  2407. #endif
  2408. }
  2409. GetMinMaxNormalsDXT5HQFast( block, col1, col2, colorIndices, alphaIndices );
  2410. EmitByte( col2[3] );
  2411. EmitByte( col1[3] );
  2412. EmitByte( alphaIndices[0] );
  2413. EmitByte( alphaIndices[1] );
  2414. EmitByte( alphaIndices[2] );
  2415. EmitByte( alphaIndices[3] );
  2416. EmitByte( alphaIndices[4] );
  2417. EmitByte( alphaIndices[5] );
  2418. unsigned short scol1 = ColorTo565( col1 );
  2419. unsigned short scol2 = ColorTo565( col2 );
  2420. EmitUShort( scol2 );
  2421. EmitUShort( scol1 );
  2422. EmitUInt( colorIndices );
  2423. ////idLib::Printf( "\r%3d%%", ( j * width + i ) * 100 / ( width * height ) );
  2424. }
  2425. outData += dstPadding;
  2426. inBuf += srcPadding;
  2427. }
  2428. ////idLib::Printf( "\r100%%\n" );
  2429. }
  2430. /*
  2431. ========================
  2432. idDxtEncoder::CompressNormalMapDXN2HQ
  2433. params: inBuf - image to compress
  2434. paramO: outBuf - result of compression
  2435. params: width - width of image
  2436. params: height - height of image
  2437. ========================
  2438. */
  2439. void idDxtEncoder::CompressNormalMapDXN2HQ( const byte *inBuf, byte *outBuf, int width, int height ) {
  2440. ALIGN16( byte block[64] );
  2441. byte alphaIndices1[6];
  2442. byte alphaIndices2[6];
  2443. byte col1[4];
  2444. byte col2[4];
  2445. int error1;
  2446. int error2;
  2447. this->width = width;
  2448. this->height = height;
  2449. this->outData = outBuf;
  2450. if ( width > 4 && ( width & 3 ) != 0 ) {
  2451. return;
  2452. }
  2453. if ( height > 4 && ( height & 3 ) != 0 ) {
  2454. return;
  2455. }
  2456. if ( width < 4 || height < 4 ) {
  2457. WriteTinyColorDXT5( inBuf, width, height );
  2458. return;
  2459. }
  2460. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  2461. for ( int i = 0; i < width; i += 4 ) {
  2462. ExtractBlock( inBuf + i * 4, width, block );
  2463. for ( int k = 0; k < 2; k++ ) {
  2464. GetMinMaxAlphaHQ( block, k, col1, col2 );
  2465. // Write out alpha data. Try and find minimum error for the two encoding methods.
  2466. error1 = FindAlphaIndices( block, k, col1[k], col2[k], alphaIndices1 );
  2467. error2 = FindAlphaIndices( block, k, col2[k], col1[k], alphaIndices2 );
  2468. if ( error1 < error2 ) {
  2469. EmitByte( col1[k] );
  2470. EmitByte( col2[k] );
  2471. EmitByte( alphaIndices1[0] );
  2472. EmitByte( alphaIndices1[1] );
  2473. EmitByte( alphaIndices1[2] );
  2474. EmitByte( alphaIndices1[3] );
  2475. EmitByte( alphaIndices1[4] );
  2476. EmitByte( alphaIndices1[5] );
  2477. } else {
  2478. EmitByte( col2[k] );
  2479. EmitByte( col1[k] );
  2480. EmitByte( alphaIndices2[0] );
  2481. EmitByte( alphaIndices2[1] );
  2482. EmitByte( alphaIndices2[2] );
  2483. EmitByte( alphaIndices2[3] );
  2484. EmitByte( alphaIndices2[4] );
  2485. EmitByte( alphaIndices2[5] );
  2486. }
  2487. }
  2488. //idLib::Printf( "\r%3d%%", ( j * width + i ) * 100 / ( width * height ) );
  2489. }
  2490. outData += dstPadding;
  2491. inBuf += srcPadding;
  2492. }
  2493. //idLib::Printf( "\r100%%\n" );
  2494. }
  2495. /*
  2496. ========================
  2497. idDxtEncoder::GetMinMaxBBox
  2498. Takes the extents of the bounding box of the colors in the 4x4 block in RGB space.
  2499. Also finds the minimum and maximum alpha values.
  2500. params: colorBlock - 4*4 input tile, 4 bytes per pixel
  2501. paramO: minColor - 4 byte Min color found
  2502. paramO: maxColor - 4 byte Max color found
  2503. ========================
  2504. */
  2505. ID_INLINE void idDxtEncoder::GetMinMaxBBox( const byte *colorBlock, byte *minColor, byte *maxColor ) const {
  2506. minColor[0] = minColor[1] = minColor[2] = minColor[3] = 255;
  2507. maxColor[0] = maxColor[1] = maxColor[2] = maxColor[3] = 0;
  2508. for ( int i = 0; i < 16; i++ ) {
  2509. if ( colorBlock[i*4+0] < minColor[0] ) {
  2510. minColor[0] = colorBlock[i*4+0];
  2511. }
  2512. if ( colorBlock[i*4+1] < minColor[1] ) {
  2513. minColor[1] = colorBlock[i*4+1];
  2514. }
  2515. if ( colorBlock[i*4+2] < minColor[2] ) {
  2516. minColor[2] = colorBlock[i*4+2];
  2517. }
  2518. if ( colorBlock[i*4+3] < minColor[3] ) {
  2519. minColor[3] = colorBlock[i*4+3];
  2520. }
  2521. if ( colorBlock[i*4+0] > maxColor[0] ) {
  2522. maxColor[0] = colorBlock[i*4+0];
  2523. }
  2524. if ( colorBlock[i*4+1] > maxColor[1] ) {
  2525. maxColor[1] = colorBlock[i*4+1];
  2526. }
  2527. if ( colorBlock[i*4+2] > maxColor[2] ) {
  2528. maxColor[2] = colorBlock[i*4+2];
  2529. }
  2530. if ( colorBlock[i*4+3] > maxColor[3] ) {
  2531. maxColor[3] = colorBlock[i*4+3];
  2532. }
  2533. }
  2534. }
  2535. /*
  2536. ========================
  2537. idDxtEncoder::InsetColorsBBox
  2538. ========================
  2539. */
  2540. ID_INLINE void idDxtEncoder::InsetColorsBBox( byte *minColor, byte *maxColor ) const {
  2541. byte inset[4];
  2542. inset[0] = ( maxColor[0] - minColor[0] ) >> INSET_COLOR_SHIFT;
  2543. inset[1] = ( maxColor[1] - minColor[1] ) >> INSET_COLOR_SHIFT;
  2544. inset[2] = ( maxColor[2] - minColor[2] ) >> INSET_COLOR_SHIFT;
  2545. inset[3] = ( maxColor[3] - minColor[3] ) >> INSET_ALPHA_SHIFT;
  2546. minColor[0] = ( minColor[0] + inset[0] <= 255 ) ? minColor[0] + inset[0] : 255;
  2547. minColor[1] = ( minColor[1] + inset[1] <= 255 ) ? minColor[1] + inset[1] : 255;
  2548. minColor[2] = ( minColor[2] + inset[2] <= 255 ) ? minColor[2] + inset[2] : 255;
  2549. minColor[3] = ( minColor[3] + inset[3] <= 255 ) ? minColor[3] + inset[3] : 255;
  2550. maxColor[0] = ( maxColor[0] >= inset[0] ) ? maxColor[0] - inset[0] : 0;
  2551. maxColor[1] = ( maxColor[1] >= inset[1] ) ? maxColor[1] - inset[1] : 0;
  2552. maxColor[2] = ( maxColor[2] >= inset[2] ) ? maxColor[2] - inset[2] : 0;
  2553. maxColor[3] = ( maxColor[3] >= inset[3] ) ? maxColor[3] - inset[3] : 0;
  2554. }
  2555. /*
  2556. ========================
  2557. idDxtEncoder::SelectColorsDiagonal
  2558. ========================
  2559. */
  2560. void idDxtEncoder::SelectColorsDiagonal( const byte *colorBlock, byte *minColor, byte *maxColor ) const {
  2561. byte mid0 = byte( ( (int) minColor[0] + maxColor[0] + 1 ) >> 1 );
  2562. byte mid1 = byte( ( (int) minColor[1] + maxColor[1] + 1 ) >> 1 );
  2563. byte mid2 = byte( ( (int) minColor[2] + maxColor[2] + 1 ) >> 1 );
  2564. #if 0
  2565. // using the covariance is the best way to select the diagonal
  2566. int side0 = 0;
  2567. int side1 = 0;
  2568. for ( int i = 0; i < 16; i++ ) {
  2569. int b0 = colorBlock[i*4+0] - mid0;
  2570. int b1 = colorBlock[i*4+1] - mid1;
  2571. int b2 = colorBlock[i*4+2] - mid2;
  2572. side0 += ( b0 * b1 );
  2573. side1 += ( b1 * b2 );
  2574. }
  2575. byte mask0 = -( side0 < 0 );
  2576. byte mask1 = -( side1 < 0 );
  2577. #else
  2578. // calculating the covariance of just the sign bits is much faster and gives almost the same result
  2579. int side0 = 0;
  2580. int side1 = 0;
  2581. for ( int i = 0; i < 16; i++ ) {
  2582. byte b0 = colorBlock[i*4+0] >= mid0;
  2583. byte b1 = colorBlock[i*4+1] >= mid1;
  2584. byte b2 = colorBlock[i*4+2] >= mid2;
  2585. side0 += ( b0 ^ b1 );
  2586. side1 += ( b1 ^ b2 );
  2587. }
  2588. byte mask0 = -( side0 > 8 );
  2589. byte mask1 = -( side1 > 8 );
  2590. #endif
  2591. byte c0 = minColor[0];
  2592. byte c1 = maxColor[0];
  2593. byte c2 = minColor[2];
  2594. byte c3 = maxColor[2];
  2595. c0 ^= c1;
  2596. mask0 &= c0;
  2597. c1 ^= mask0;
  2598. c0 ^= c1;
  2599. c2 ^= c3;
  2600. mask1 &= c2;
  2601. c3 ^= mask1;
  2602. c2 ^= c3;
  2603. minColor[0] = c0;
  2604. maxColor[0] = c1;
  2605. minColor[2] = c2;
  2606. maxColor[2] = c3;
  2607. if ( ColorTo565( minColor ) > ColorTo565( maxColor ) ) {
  2608. SwapValues( minColor[0], maxColor[0] );
  2609. SwapValues( minColor[1], maxColor[1] );
  2610. SwapValues( minColor[2], maxColor[2] );
  2611. }
  2612. }
  2613. /*
  2614. ========================
  2615. idDxtEncoder::EmitColorIndices
  2616. params: colorBlock - 16 pixel block for which find color indexes
  2617. paramO: minColor - Min color found
  2618. paramO: maxColor - Max color found
  2619. return: 4 byte color index block
  2620. ========================
  2621. */
  2622. void idDxtEncoder::EmitColorIndices( const byte *colorBlock, const byte *minColor, const byte *maxColor ) {
  2623. #if 1
  2624. ALIGN16( uint16 colors[4][4] );
  2625. unsigned int result = 0;
  2626. colors[0][0] = ( maxColor[0] & C565_5_MASK ) | ( maxColor[0] >> 5 );
  2627. colors[0][1] = ( maxColor[1] & C565_6_MASK ) | ( maxColor[1] >> 6 );
  2628. colors[0][2] = ( maxColor[2] & C565_5_MASK ) | ( maxColor[2] >> 5 );
  2629. colors[0][3] = 0;
  2630. colors[1][0] = ( minColor[0] & C565_5_MASK ) | ( minColor[0] >> 5 );
  2631. colors[1][1] = ( minColor[1] & C565_6_MASK ) | ( minColor[1] >> 6 );
  2632. colors[1][2] = ( minColor[2] & C565_5_MASK ) | ( minColor[2] >> 5 );
  2633. colors[1][3] = 0;
  2634. colors[2][0] = ( 2 * colors[0][0] + 1 * colors[1][0] ) / 3;
  2635. colors[2][1] = ( 2 * colors[0][1] + 1 * colors[1][1] ) / 3;
  2636. colors[2][2] = ( 2 * colors[0][2] + 1 * colors[1][2] ) / 3;
  2637. colors[2][3] = 0;
  2638. colors[3][0] = ( 1 * colors[0][0] + 2 * colors[1][0] ) / 3;
  2639. colors[3][1] = ( 1 * colors[0][1] + 2 * colors[1][1] ) / 3;
  2640. colors[3][2] = ( 1 * colors[0][2] + 2 * colors[1][2] ) / 3;
  2641. colors[3][3] = 0;
  2642. // uses sum of absolute differences instead of squared distance to find the best match
  2643. for ( int i = 15; i >= 0; i-- ) {
  2644. int c0, c1, c2, c3, m, d0, d1, d2, d3;
  2645. c0 = colorBlock[i*4+0];
  2646. c1 = colorBlock[i*4+1];
  2647. c2 = colorBlock[i*4+2];
  2648. c3 = colorBlock[i*4+3];
  2649. m = colors[0][0] - c0;
  2650. d0 = abs( m );
  2651. m = colors[1][0] - c0;
  2652. d1 = abs( m );
  2653. m = colors[2][0] - c0;
  2654. d2 = abs( m );
  2655. m = colors[3][0] - c0;
  2656. d3 = abs( m );
  2657. m = colors[0][1] - c1;
  2658. d0 += abs( m );
  2659. m = colors[1][1] - c1;
  2660. d1 += abs( m );
  2661. m = colors[2][1] - c1;
  2662. d2 += abs( m );
  2663. m = colors[3][1] - c1;
  2664. d3 += abs( m );
  2665. m = colors[0][2] - c2;
  2666. d0 += abs( m );
  2667. m = colors[1][2] - c2;
  2668. d1 += abs( m );
  2669. m = colors[2][2] - c2;
  2670. d2 += abs( m );
  2671. m = colors[3][2] - c2;
  2672. d3 += abs( m );
  2673. #if 0
  2674. int b0 = d0 > d2;
  2675. int b1 = d1 > d3;
  2676. int b2 = d0 > d3;
  2677. int b3 = d1 > d2;
  2678. int b4 = d0 > d1;
  2679. int b5 = d2 > d3;
  2680. result |= ( ( !b3 & b4 ) | ( b2 & b5 ) | ( ( ( b0 & b3 ) | ( b1 & b2 ) ) << 1 ) ) << ( i << 1 );
  2681. #else
  2682. bool b0 = d0 > d3;
  2683. bool b1 = d1 > d2;
  2684. bool b2 = d0 > d2;
  2685. bool b3 = d1 > d3;
  2686. bool b4 = d2 > d3;
  2687. int x0 = b1 & b2;
  2688. int x1 = b0 & b3;
  2689. int x2 = b0 & b4;
  2690. result |= ( x2 | ( ( x0 | x1 ) << 1 ) ) << ( i << 1 );
  2691. #endif
  2692. }
  2693. EmitUInt( result );
  2694. #elif 1
  2695. byte colors[4][4];
  2696. unsigned int indexes[16];
  2697. colors[0][0] = ( maxColor[0] & C565_5_MASK ) | ( maxColor[0] >> 6 );
  2698. colors[0][1] = ( maxColor[1] & C565_6_MASK ) | ( maxColor[1] >> 5 );
  2699. colors[0][2] = ( maxColor[2] & C565_5_MASK ) | ( maxColor[2] >> 6 );
  2700. colors[0][3] = 0;
  2701. colors[1][0] = ( minColor[0] & C565_5_MASK ) | ( minColor[0] >> 6 );
  2702. colors[1][1] = ( minColor[1] & C565_6_MASK ) | ( minColor[1] >> 5 );
  2703. colors[1][2] = ( minColor[2] & C565_5_MASK ) | ( minColor[2] >> 6 );
  2704. colors[1][3] = 0;
  2705. colors[2][0] = ( 2 * colors[0][0] + 1 * colors[1][0] ) / 3;
  2706. colors[2][1] = ( 2 * colors[0][1] + 1 * colors[1][1] ) / 3;
  2707. colors[2][2] = ( 2 * colors[0][2] + 1 * colors[1][2] ) / 3;
  2708. colors[2][3] = 0;
  2709. colors[3][0] = ( 1 * colors[0][0] + 2 * colors[1][0] ) / 3;
  2710. colors[3][1] = ( 1 * colors[0][1] + 2 * colors[1][1] ) / 3;
  2711. colors[3][2] = ( 1 * colors[0][2] + 2 * colors[1][2] ) / 3;
  2712. colors[3][3] = 0;
  2713. for ( int i = 0; i < 16; i++ ) {
  2714. int c0, c1, c2, m, d, minDist;
  2715. c0 = colorBlock[i*4+0];
  2716. c1 = colorBlock[i*4+1];
  2717. c2 = colorBlock[i*4+2];
  2718. m = colors[0][0] - c0;
  2719. d = m * m;
  2720. m = colors[0][1] - c1;
  2721. d += m * m;
  2722. m = colors[0][2] - c2;
  2723. d += m * m;
  2724. minDist = d;
  2725. indexes[i] = 0;
  2726. m = colors[1][0] - c0;
  2727. d = m * m;
  2728. m = colors[1][1] - c1;
  2729. d += m * m;
  2730. m = colors[1][2] - c2;
  2731. d += m * m;
  2732. if ( d < minDist ) {
  2733. minDist = d;
  2734. indexes[i] = 1;
  2735. }
  2736. m = colors[2][0] - c0;
  2737. d = m * m;
  2738. m = colors[2][1] - c1;
  2739. d += m * m;
  2740. m = colors[2][2] - c2;
  2741. d += m * m;
  2742. if ( d < minDist ) {
  2743. minDist = d;
  2744. indexes[i] = 2;
  2745. }
  2746. m = colors[3][0] - c0;
  2747. d = m * m;
  2748. m = colors[3][1] - c1;
  2749. d += m * m;
  2750. m = colors[3][2] - c2;
  2751. d += m * m;
  2752. if ( d < minDist ) {
  2753. minDist = d;
  2754. indexes[i] = 3;
  2755. }
  2756. }
  2757. unsigned int result = 0;
  2758. for ( int i = 0; i < 16; i++ ) {
  2759. result |= ( indexes[i] << (unsigned int)( i << 1 ) );
  2760. }
  2761. EmitUInt( result );
  2762. #else
  2763. byte colors[4][4];
  2764. unsigned int indexes[16];
  2765. colors[0][0] = ( maxColor[0] & C565_5_MASK ) | ( maxColor[0] >> 6 );
  2766. colors[0][1] = ( maxColor[1] & C565_6_MASK ) | ( maxColor[1] >> 5 );
  2767. colors[0][2] = ( maxColor[2] & C565_5_MASK ) | ( maxColor[2] >> 6 );
  2768. colors[0][3] = 0;
  2769. colors[1][0] = ( minColor[0] & C565_5_MASK ) | ( minColor[0] >> 6 );
  2770. colors[1][1] = ( minColor[1] & C565_6_MASK ) | ( minColor[1] >> 5 );
  2771. colors[1][2] = ( minColor[2] & C565_5_MASK ) | ( minColor[2] >> 6 );
  2772. colors[1][3] = 0;
  2773. colors[2][0] = ( 2 * colors[0][0] + 1 * colors[1][0] ) / 3;
  2774. colors[2][1] = ( 2 * colors[0][1] + 1 * colors[1][1] ) / 3;
  2775. colors[2][2] = ( 2 * colors[0][2] + 1 * colors[1][2] ) / 3;
  2776. colors[2][3] = 0;
  2777. colors[3][0] = ( 1 * colors[0][0] + 2 * colors[1][0] ) / 3;
  2778. colors[3][1] = ( 1 * colors[0][1] + 2 * colors[1][1] ) / 3;
  2779. colors[3][2] = ( 1 * colors[0][2] + 2 * colors[1][2] ) / 3;
  2780. colors[3][3] = 0;
  2781. for ( int i = 0; i < 16; i++ ) {
  2782. unsigned int minDist = (255*255)*4;
  2783. for ( int j = 0; j < 4; j++ ) {
  2784. unsigned int dist = ColorDistance( &colorBlock[i*4], &colors[j][0] );
  2785. if ( dist < minDist ) {
  2786. minDist = dist;
  2787. indexes[i] = j;
  2788. }
  2789. }
  2790. }
  2791. unsigned int result = 0;
  2792. for ( int i = 0; i < 16; i++ ) {
  2793. result |= ( indexes[i] << (unsigned int)( i << 1 ) );
  2794. }
  2795. EmitUInt( result );
  2796. #endif
  2797. }
  2798. /*
  2799. ========================
  2800. idDxtEncoder::EmitColorAlphaIndices
  2801. params: colorBlock - 16 pixel block for which find color indexes
  2802. paramO: minColor - Min color found
  2803. paramO: maxColor - Max color found
  2804. return: 4 byte color index block
  2805. ========================
  2806. */
  2807. void idDxtEncoder::EmitColorAlphaIndices( const byte *colorBlock, const byte *minColor, const byte *maxColor ) {
  2808. ALIGN16( uint16 colors[4][4] );
  2809. unsigned int result = 0;
  2810. colors[0][0] = ( minColor[0] & C565_5_MASK ) | ( minColor[0] >> 5 );
  2811. colors[0][1] = ( minColor[1] & C565_6_MASK ) | ( minColor[1] >> 6 );
  2812. colors[0][2] = ( minColor[2] & C565_5_MASK ) | ( minColor[2] >> 5 );
  2813. colors[0][3] = 255;
  2814. colors[1][0] = ( maxColor[0] & C565_5_MASK ) | ( maxColor[0] >> 5 );
  2815. colors[1][1] = ( maxColor[1] & C565_6_MASK ) | ( maxColor[1] >> 6 );
  2816. colors[1][2] = ( maxColor[2] & C565_5_MASK ) | ( maxColor[2] >> 5 );
  2817. colors[1][3] = 255;
  2818. colors[2][0] = ( colors[0][0] + colors[1][0] ) / 2;
  2819. colors[2][1] = ( colors[0][1] + colors[1][1] ) / 2;
  2820. colors[2][2] = ( colors[0][2] + colors[1][2] ) / 2;
  2821. colors[2][3] = 255;
  2822. colors[3][0] = 0;
  2823. colors[3][1] = 0;
  2824. colors[3][2] = 0;
  2825. colors[3][3] = 0;
  2826. // uses sum of absolute differences instead of squared distance to find the best match
  2827. for ( int i = 15; i >= 0; i-- ) {
  2828. int c0, c1, c2, c3, m, d0, d1, d2;
  2829. c0 = colorBlock[i*4+0];
  2830. c1 = colorBlock[i*4+1];
  2831. c2 = colorBlock[i*4+2];
  2832. c3 = colorBlock[i*4+3];
  2833. m = colors[0][0] - c0;
  2834. d0 = abs( m );
  2835. m = colors[1][0] - c0;
  2836. d1 = abs( m );
  2837. m = colors[2][0] - c0;
  2838. d2 = abs( m );
  2839. m = colors[0][1] - c1;
  2840. d0 += abs( m );
  2841. m = colors[1][1] - c1;
  2842. d1 += abs( m );
  2843. m = colors[2][1] - c1;
  2844. d2 += abs( m );
  2845. m = colors[0][2] - c2;
  2846. d0 += abs( m );
  2847. m = colors[1][2] - c2;
  2848. d1 += abs( m );
  2849. m = colors[2][2] - c2;
  2850. d2 += abs( m );
  2851. unsigned int b0 = d2 > d0;
  2852. unsigned int b1 = d2 > d1;
  2853. unsigned int b2 = d1 > d0;
  2854. unsigned int b3 = c3 < 128;
  2855. result |= ( ( ( b0 & b1 | b3 ) << 1 ) | ( b2 ^ b1 | b3 ) ) << ( i << 1 );
  2856. }
  2857. EmitUInt( result );
  2858. }
  2859. /*
  2860. ========================
  2861. idDxtEncoder::EmitCTX1Indices
  2862. params: colorBlock - 16 pixel block for which find color indexes
  2863. paramO: minColor - Min color found
  2864. paramO: maxColor - Max color found
  2865. return: 4 byte color index block
  2866. ========================
  2867. */
  2868. void idDxtEncoder::EmitCTX1Indices( const byte *colorBlock, const byte *minColor, const byte *maxColor ) {
  2869. ALIGN16( uint16 colors[4][2] );
  2870. unsigned int result = 0;
  2871. colors[0][0] = maxColor[0];
  2872. colors[0][1] = maxColor[1];
  2873. colors[1][0] = minColor[0];
  2874. colors[1][1] = minColor[1];
  2875. colors[2][0] = ( 2 * colors[0][0] + 1 * colors[1][0] ) / 3;
  2876. colors[2][1] = ( 2 * colors[0][1] + 1 * colors[1][1] ) / 3;
  2877. colors[3][0] = ( 1 * colors[0][0] + 2 * colors[1][0] ) / 3;
  2878. colors[3][1] = ( 1 * colors[0][1] + 2 * colors[1][1] ) / 3;
  2879. for ( int i = 15; i >= 0; i-- ) {
  2880. int c0, c1, m, d0, d1, d2, d3;
  2881. c0 = colorBlock[i*4+0];
  2882. c1 = colorBlock[i*4+1];
  2883. m = colors[0][0] - c0;
  2884. d0 = abs( m );
  2885. m = colors[1][0] - c0;
  2886. d1 = abs( m );
  2887. m = colors[2][0] - c0;
  2888. d2 = abs( m );
  2889. m = colors[3][0] - c0;
  2890. d3 = abs( m );
  2891. m = colors[0][1] - c1;
  2892. d0 += abs( m );
  2893. m = colors[1][1] - c1;
  2894. d1 += abs( m );
  2895. m = colors[2][1] - c1;
  2896. d2 += abs( m );
  2897. m = colors[3][1] - c1;
  2898. d3 += abs( m );
  2899. bool b0 = d0 > d3;
  2900. bool b1 = d1 > d2;
  2901. bool b2 = d0 > d2;
  2902. bool b3 = d1 > d3;
  2903. bool b4 = d2 > d3;
  2904. int x0 = b1 & b2;
  2905. int x1 = b0 & b3;
  2906. int x2 = b0 & b4;
  2907. result |= ( x2 | ( ( x0 | x1 ) << 1 ) ) << ( i << 1 );
  2908. }
  2909. EmitUInt( result );
  2910. }
  2911. /*
  2912. ========================
  2913. idDxtEncoder::EmitAlphaIndices
  2914. params: colorBlock - 16 pixel block for which find alpha indexes
  2915. paramO: minAlpha - Min alpha found
  2916. paramO: maxAlpha - Max alpha found
  2917. ========================
  2918. */
  2919. void idDxtEncoder::EmitAlphaIndices( const byte *colorBlock, const int offset, const byte minAlpha, const byte maxAlpha ) {
  2920. assert( maxAlpha >= minAlpha );
  2921. const int ALPHA_RANGE = 7;
  2922. #if 1
  2923. byte ab1, ab2, ab3, ab4, ab5, ab6, ab7;
  2924. ALIGN16( byte indexes[16] );
  2925. ab1 = ( 13 * maxAlpha + 1 * minAlpha + ALPHA_RANGE ) / (ALPHA_RANGE*2);
  2926. ab2 = ( 11 * maxAlpha + 3 * minAlpha + ALPHA_RANGE ) / (ALPHA_RANGE*2);
  2927. ab3 = ( 9 * maxAlpha + 5 * minAlpha + ALPHA_RANGE ) / (ALPHA_RANGE*2);
  2928. ab4 = ( 7 * maxAlpha + 7 * minAlpha + ALPHA_RANGE ) / (ALPHA_RANGE*2);
  2929. ab5 = ( 5 * maxAlpha + 9 * minAlpha + ALPHA_RANGE ) / (ALPHA_RANGE*2);
  2930. ab6 = ( 3 * maxAlpha + 11 * minAlpha + ALPHA_RANGE ) / (ALPHA_RANGE*2);
  2931. ab7 = ( 1 * maxAlpha + 13 * minAlpha + ALPHA_RANGE ) / (ALPHA_RANGE*2);
  2932. colorBlock += offset;
  2933. for ( int i = 0; i < 16; i++ ) {
  2934. byte a = colorBlock[i*4];
  2935. int b1 = ( a >= ab1 );
  2936. int b2 = ( a >= ab2 );
  2937. int b3 = ( a >= ab3 );
  2938. int b4 = ( a >= ab4 );
  2939. int b5 = ( a >= ab5 );
  2940. int b6 = ( a >= ab6 );
  2941. int b7 = ( a >= ab7 );
  2942. int index = ( 8 - b1 - b2 - b3 - b4 - b5 - b6 - b7 ) & 7;
  2943. indexes[i] = byte( index ^ ( 2 > index ) );
  2944. }
  2945. EmitByte( (indexes[ 0] >> 0) | (indexes[ 1] << 3) | (indexes[ 2] << 6) );
  2946. EmitByte( (indexes[ 2] >> 2) | (indexes[ 3] << 1) | (indexes[ 4] << 4) | (indexes[ 5] << 7) );
  2947. EmitByte( (indexes[ 5] >> 1) | (indexes[ 6] << 2) | (indexes[ 7] << 5) );
  2948. EmitByte( (indexes[ 8] >> 0) | (indexes[ 9] << 3) | (indexes[10] << 6) );
  2949. EmitByte( (indexes[10] >> 2) | (indexes[11] << 1) | (indexes[12] << 4) | (indexes[13] << 7) );
  2950. EmitByte( (indexes[13] >> 1) | (indexes[14] << 2) | (indexes[15] << 5) );
  2951. #elif 0
  2952. ALIGN16( byte indexes[16] );
  2953. byte delta = maxAlpha - minAlpha;
  2954. byte half = delta >> 1;
  2955. byte bias = delta / ( 2 * ALPHA_RANGE );
  2956. byte bottom = minAlpha + bias;
  2957. byte top = maxAlpha - bias;
  2958. colorBlock += offset;
  2959. for ( int i = 0; i < 16; i++ ) {
  2960. byte a = colorBlock[i*4];
  2961. if ( a <= bottom ) {
  2962. indexes[i] = 1;
  2963. } else if ( a >= top ) {
  2964. indexes[i] = 0;
  2965. } else {
  2966. indexes[i] = (ALPHA_RANGE+1) + ( ( minAlpha - a ) * ALPHA_RANGE - half ) / delta;
  2967. }
  2968. }
  2969. EmitByte( (indexes[ 0] >> 0) | (indexes[ 1] << 3) | (indexes[ 2] << 6) );
  2970. EmitByte( (indexes[ 2] >> 2) | (indexes[ 3] << 1) | (indexes[ 4] << 4) | (indexes[ 5] << 7) );
  2971. EmitByte( (indexes[ 5] >> 1) | (indexes[ 6] << 2) | (indexes[ 7] << 5) );
  2972. EmitByte( (indexes[ 8] >> 0) | (indexes[ 9] << 3) | (indexes[10] << 6) );
  2973. EmitByte( (indexes[10] >> 2) | (indexes[11] << 1) | (indexes[12] << 4) | (indexes[13] << 7) );
  2974. EmitByte( (indexes[13] >> 1) | (indexes[14] << 2) | (indexes[15] << 5) );
  2975. #elif 0
  2976. ALIGN16( byte indexes[16] );
  2977. byte delta = maxAlpha - minAlpha;
  2978. byte half = delta >> 1;
  2979. byte bias = delta / ( 2 * ALPHA_RANGE );
  2980. byte bottom = minAlpha + bias;
  2981. byte top = maxAlpha - bias;
  2982. colorBlock += offset;
  2983. for ( int i = 0; i < 16; i++ ) {
  2984. byte a = colorBlock[i*4];
  2985. int index = (ALPHA_RANGE+1) + ( ( minAlpha - a ) * ALPHA_RANGE - half ) / delta;
  2986. int c0 = a > bottom;
  2987. int c1 = a < top;
  2988. indexes[i] = ( index & -( c0 & c1 ) ) | ( c0 ^ 1 );
  2989. }
  2990. EmitByte( (indexes[ 0] >> 0) | (indexes[ 1] << 3) | (indexes[ 2] << 6) );
  2991. EmitByte( (indexes[ 2] >> 2) | (indexes[ 3] << 1) | (indexes[ 4] << 4) | (indexes[ 5] << 7) );
  2992. EmitByte( (indexes[ 5] >> 1) | (indexes[ 6] << 2) | (indexes[ 7] << 5) );
  2993. EmitByte( (indexes[ 8] >> 0) | (indexes[ 9] << 3) | (indexes[10] << 6) );
  2994. EmitByte( (indexes[10] >> 2) | (indexes[11] << 1) | (indexes[12] << 4) | (indexes[13] << 7) );
  2995. EmitByte( (indexes[13] >> 1) | (indexes[14] << 2) | (indexes[15] << 5) );
  2996. #else
  2997. ALIGN16( byte indexes[16] );
  2998. ALIGN16( byte alphas[8] );
  2999. alphas[0] = maxAlpha;
  3000. alphas[1] = minAlpha;
  3001. alphas[2] = ( 6 * maxAlpha + 1 * minAlpha ) / ALPHA_RANGE;
  3002. alphas[3] = ( 5 * maxAlpha + 2 * minAlpha ) / ALPHA_RANGE;
  3003. alphas[4] = ( 4 * maxAlpha + 3 * minAlpha ) / ALPHA_RANGE;
  3004. alphas[5] = ( 3 * maxAlpha + 4 * minAlpha ) / ALPHA_RANGE;
  3005. alphas[6] = ( 2 * maxAlpha + 5 * minAlpha ) / ALPHA_RANGE;
  3006. alphas[7] = ( 1 * maxAlpha + 6 * minAlpha ) / ALPHA_RANGE;
  3007. colorBlock += offset;
  3008. for ( int i = 0; i < 16; i++ ) {
  3009. int minDist = INT_MAX;
  3010. byte a = colorBlock[i*4];
  3011. for ( int j = 0; j < 8; j++ ) {
  3012. int dist = abs( a - alphas[j] );
  3013. if ( dist < minDist ) {
  3014. minDist = dist;
  3015. indexes[i] = j;
  3016. }
  3017. }
  3018. }
  3019. EmitByte( (indexes[ 0] >> 0) | (indexes[ 1] << 3) | (indexes[ 2] << 6) );
  3020. EmitByte( (indexes[ 2] >> 2) | (indexes[ 3] << 1) | (indexes[ 4] << 4) | (indexes[ 5] << 7) );
  3021. EmitByte( (indexes[ 5] >> 1) | (indexes[ 6] << 2) | (indexes[ 7] << 5) );
  3022. EmitByte( (indexes[ 8] >> 0) | (indexes[ 9] << 3) | (indexes[10] << 6) );
  3023. EmitByte( (indexes[10] >> 2) | (indexes[11] << 1) | (indexes[12] << 4) | (indexes[13] << 7) );
  3024. EmitByte( (indexes[13] >> 1) | (indexes[14] << 2) | (indexes[15] << 5) );
  3025. #endif
  3026. }
  3027. /*
  3028. ========================
  3029. idDxtEncoder::CompressImageDXT1Fast_Generic
  3030. params: inBuf - image to compress
  3031. paramO: outBuf - result of compression
  3032. params: width - width of image
  3033. params: height - height of image
  3034. ========================
  3035. */
  3036. void idDxtEncoder::CompressImageDXT1Fast_Generic( const byte *inBuf, byte *outBuf, int width, int height ) {
  3037. ALIGN16( byte block[64] );
  3038. ALIGN16( byte minColor[4] );
  3039. ALIGN16( byte maxColor[4] );
  3040. assert( width >= 4 && ( width & 3 ) == 0 );
  3041. assert( height >= 4 && ( height & 3 ) == 0 );
  3042. this->width = width;
  3043. this->height = height;
  3044. this->outData = outBuf;
  3045. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  3046. for ( int i = 0; i < width; i += 4 ) {
  3047. ExtractBlock( inBuf + i * 4, width, block );
  3048. GetMinMaxBBox( block, minColor, maxColor );
  3049. //SelectColorsDiagonal( block, minColor, maxColor );
  3050. InsetColorsBBox( minColor, maxColor );
  3051. EmitUShort( ColorTo565( maxColor ) );
  3052. EmitUShort( ColorTo565( minColor ) );
  3053. EmitColorIndices( block, minColor, maxColor );
  3054. }
  3055. outData += dstPadding;
  3056. inBuf += srcPadding;
  3057. }
  3058. }
  3059. /*
  3060. ========================
  3061. idDxtEncoder::CompressImageDXT1AlphaFast_Generic
  3062. params: inBuf - image to compress
  3063. paramO: outBuf - result of compression
  3064. params: width - width of image
  3065. params: height - height of image
  3066. ========================
  3067. */
  3068. void idDxtEncoder::CompressImageDXT1AlphaFast_Generic( const byte *inBuf, byte *outBuf, int width, int height ) {
  3069. ALIGN16( byte block[64] );
  3070. ALIGN16( byte minColor[4] );
  3071. ALIGN16( byte maxColor[4] );
  3072. assert( width >= 4 && ( width & 3 ) == 0 );
  3073. assert( height >= 4 && ( height & 3 ) == 0 );
  3074. this->width = width;
  3075. this->height = height;
  3076. this->outData = outBuf;
  3077. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  3078. for ( int i = 0; i < width; i += 4 ) {
  3079. ExtractBlock( inBuf + i * 4, width, block );
  3080. GetMinMaxBBox( block, minColor, maxColor );
  3081. byte minAlpha = minColor[3];
  3082. //SelectColorsDiagonal( block, minColor, maxColor );
  3083. InsetColorsBBox( minColor, maxColor );
  3084. if ( minAlpha >= 128 ) {
  3085. EmitUShort( ColorTo565( maxColor ) );
  3086. EmitUShort( ColorTo565( minColor ) );
  3087. EmitColorIndices( block, minColor, maxColor );
  3088. } else {
  3089. EmitUShort( ColorTo565( minColor ) );
  3090. EmitUShort( ColorTo565( maxColor ) );
  3091. EmitColorAlphaIndices( block, minColor, maxColor );
  3092. }
  3093. }
  3094. outData += dstPadding;
  3095. inBuf += srcPadding;
  3096. }
  3097. }
  3098. /*
  3099. ========================
  3100. idDxtEncoder::CompressImageDXT5Fast_Generic
  3101. params: inBuf - image to compress
  3102. paramO: outBuf - result of compression
  3103. params: width - width of image
  3104. params: height - height of image
  3105. ========================
  3106. */
  3107. void idDxtEncoder::CompressImageDXT5Fast_Generic( const byte *inBuf, byte *outBuf, int width, int height ) {
  3108. ALIGN16( byte block[64] );
  3109. ALIGN16( byte minColor[4] );
  3110. ALIGN16( byte maxColor[4] );
  3111. assert( width >= 4 && ( width & 3 ) == 0 );
  3112. assert( height >= 4 && ( height & 3 ) == 0 );
  3113. this->width = width;
  3114. this->height = height;
  3115. this->outData = outBuf;
  3116. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  3117. for ( int i = 0; i < width; i += 4 ) {
  3118. ExtractBlock( inBuf + i * 4, width, block );
  3119. GetMinMaxBBox( block, minColor, maxColor );
  3120. //SelectColorsDiagonal( block, minColor, maxColor );
  3121. InsetColorsBBox( minColor, maxColor );
  3122. EmitByte( maxColor[3] );
  3123. EmitByte( minColor[3] );
  3124. EmitAlphaIndices( block, 3, minColor[3], maxColor[3] );
  3125. #ifdef NVIDIA_7X_HARDWARE_BUG_FIX
  3126. // the colors are already always guaranteed to be sorted properly
  3127. #endif
  3128. EmitUShort( ColorTo565( maxColor ) );
  3129. EmitUShort( ColorTo565( minColor ) );
  3130. EmitColorIndices( block, minColor, maxColor );
  3131. }
  3132. outData += dstPadding;
  3133. inBuf += srcPadding;
  3134. }
  3135. }
  3136. /*
  3137. ========================
  3138. idDxtEncoder::ScaleYCoCg
  3139. ========================
  3140. */
  3141. void idDxtEncoder::ScaleYCoCg( byte *colorBlock, byte *minColor, byte *maxColor ) const {
  3142. int m0 = abs( minColor[0] - 128 );
  3143. int m1 = abs( minColor[1] - 128 );
  3144. int m2 = abs( maxColor[0] - 128 );
  3145. int m3 = abs( maxColor[1] - 128 );
  3146. if ( m1 > m0 ) m0 = m1;
  3147. if ( m3 > m2 ) m2 = m3;
  3148. if ( m2 > m0 ) m0 = m2;
  3149. const int s0 = 128 / 2 - 1;
  3150. const int s1 = 128 / 4 - 1;
  3151. int mask0 = -( m0 <= s0 );
  3152. int mask1 = -( m0 <= s1 );
  3153. int scale = 1 + ( 1 & mask0 ) + ( 2 & mask1 );
  3154. minColor[0] = byte( ( minColor[0] - 128 ) * scale + 128 );
  3155. minColor[1] = byte( ( minColor[1] - 128 ) * scale + 128 );
  3156. minColor[2] = byte( ( scale - 1 ) << 3 );
  3157. maxColor[0] = byte( ( maxColor[0] - 128 ) * scale + 128 );
  3158. maxColor[1] = byte( ( maxColor[1] - 128 ) * scale + 128 );
  3159. maxColor[2] = byte( ( scale - 1 ) << 3 );
  3160. for ( int i = 0; i < 16; i++ ) {
  3161. colorBlock[i*4+0] = byte( ( colorBlock[i*4+0] - 128 ) * scale + 128 );
  3162. colorBlock[i*4+1] = byte( ( colorBlock[i*4+1] - 128 ) * scale + 128 );
  3163. }
  3164. }
  3165. /*
  3166. ========================
  3167. idDxtEncoder::InsetYCoCgBBox
  3168. ========================
  3169. */
  3170. ID_INLINE void idDxtEncoder::InsetYCoCgBBox( byte *minColor, byte *maxColor ) const {
  3171. #if 0
  3172. byte inset[4];
  3173. inset[0] = ( maxColor[0] - minColor[0] ) >> INSET_COLOR_SHIFT;
  3174. inset[1] = ( maxColor[1] - minColor[1] ) >> INSET_COLOR_SHIFT;
  3175. inset[3] = ( maxColor[3] - minColor[3] ) >> INSET_ALPHA_SHIFT;
  3176. minColor[0] = ( minColor[0] + inset[0] <= 255 ) ? minColor[0] + inset[0] : 255;
  3177. minColor[1] = ( minColor[1] + inset[1] <= 255 ) ? minColor[1] + inset[1] : 255;
  3178. minColor[3] = ( minColor[3] + inset[3] <= 255 ) ? minColor[3] + inset[3] : 255;
  3179. maxColor[0] = ( maxColor[0] >= inset[0] ) ? maxColor[0] - inset[0] : 0;
  3180. maxColor[1] = ( maxColor[1] >= inset[1] ) ? maxColor[1] - inset[1] : 0;
  3181. maxColor[3] = ( maxColor[3] >= inset[3] ) ? maxColor[3] - inset[3] : 0;
  3182. minColor[0] = ( minColor[0] & C565_5_MASK ) | ( minColor[0] >> 5 );
  3183. minColor[1] = ( minColor[1] & C565_6_MASK ) | ( minColor[1] >> 6 );
  3184. maxColor[0] = ( maxColor[0] & C565_5_MASK ) | ( maxColor[0] >> 5 );
  3185. maxColor[1] = ( maxColor[1] & C565_6_MASK ) | ( maxColor[1] >> 6 );
  3186. #elif 0
  3187. float inset[4];
  3188. float minf[4];
  3189. float maxf[4];
  3190. for ( int i = 0; i < 4; i++ ) {
  3191. minf[i] = minColor[i] / 255.0f;
  3192. maxf[i] = maxColor[i] / 255.0f;
  3193. }
  3194. inset[0] = ( maxf[0] - minf[0] ) / 16.0f;
  3195. inset[1] = ( maxf[1] - minf[1] ) / 16.0f;
  3196. inset[2] = ( maxf[2] - minf[2] ) / 16.0f;
  3197. inset[3] = ( maxf[3] - minf[3] ) / 32.0f;
  3198. for ( int i = 0; i < 4; i++ ) {
  3199. minf[i] = ( minf[i] + inset[i] <= 1.0f ) ? minf[i] + inset[i] : 1.0f;
  3200. maxf[i] = ( maxf[i] >= inset[i] ) ? maxf[i] - inset[i] : 0;
  3201. }
  3202. minColor[0] = ((int)floor( minf[0] * 31 )) & ( ( 1 << 5 ) - 1 );
  3203. minColor[1] = ((int)floor( minf[1] * 63 )) & ( ( 1 << 6 ) - 1 );
  3204. maxColor[0] = ((int)ceil( maxf[0] * 31 )) & ( ( 1 << 5 ) - 1 );
  3205. maxColor[1] = ((int)ceil( maxf[1] * 63 )) & ( ( 1 << 6 ) - 1 );
  3206. minColor[0] = ( minColor[0] << 3 ) | ( minColor[0] >> 2 );
  3207. minColor[1] = ( minColor[1] << 2 ) | ( minColor[1] >> 4 );
  3208. maxColor[0] = ( maxColor[0] << 3 ) | ( maxColor[0] >> 2 );
  3209. maxColor[1] = ( maxColor[1] << 2 ) | ( maxColor[1] >> 4 );
  3210. minColor[3] = (int)floor( minf[3] * 255.0f );
  3211. maxColor[3] = (int)ceil( maxf[3] * 255.0f );
  3212. #elif 0
  3213. int inset[4];
  3214. int mini[4];
  3215. int maxi[4];
  3216. inset[0] = ( maxColor[0] - minColor[0] );
  3217. inset[1] = ( maxColor[1] - minColor[1] );
  3218. inset[3] = ( maxColor[3] - minColor[3] );
  3219. mini[0] = ( minColor[0] << INSET_COLOR_SHIFT ) + inset[0];
  3220. mini[1] = ( minColor[1] << INSET_COLOR_SHIFT ) + inset[1];
  3221. mini[3] = ( minColor[3] << INSET_ALPHA_SHIFT ) + inset[3];
  3222. maxi[0] = ( maxColor[0] << INSET_COLOR_SHIFT ) - inset[0];
  3223. maxi[1] = ( maxColor[1] << INSET_COLOR_SHIFT ) - inset[1];
  3224. maxi[3] = ( maxColor[3] << INSET_ALPHA_SHIFT ) - inset[3];
  3225. mini[0] = ( mini[0] - ((1<<(3))-1) ) >> (INSET_COLOR_SHIFT+3);
  3226. mini[1] = ( mini[1] - ((1<<(3))-1) ) >> (INSET_COLOR_SHIFT+2);
  3227. mini[3] = ( mini[3] - ((1<<(2))-1) ) >> (INSET_ALPHA_SHIFT+0);
  3228. maxi[0] = ( maxi[0] + ((1<<(3))-1) ) >> (INSET_COLOR_SHIFT+3);
  3229. maxi[1] = ( maxi[1] + ((1<<(3))-1) ) >> (INSET_COLOR_SHIFT+2);
  3230. maxi[3] = ( maxi[3] + ((1<<(2))-1) ) >> (INSET_ALPHA_SHIFT+0);
  3231. if ( mini[0] < 0 ) mini[0] = 0;
  3232. if ( mini[1] < 0 ) mini[1] = 0;
  3233. if ( mini[3] < 0 ) mini[3] = 0;
  3234. if ( maxi[0] > 31 ) maxi[0] = 31;
  3235. if ( maxi[1] > 63 ) maxi[1] = 63;
  3236. if ( maxi[3] > 255 ) maxi[3] = 255;
  3237. minColor[0] = ( mini[0] << 3 ) | ( mini[0] >> 2 );
  3238. minColor[1] = ( mini[1] << 2 ) | ( mini[1] >> 4 );
  3239. minColor[3] = mini[3];
  3240. maxColor[0] = ( maxi[0] << 3 ) | ( maxi[0] >> 2 );
  3241. maxColor[1] = ( maxi[1] << 2 ) | ( maxi[1] >> 4 );
  3242. maxColor[3] = maxi[3];
  3243. #elif 1
  3244. int inset[4];
  3245. int mini[4];
  3246. int maxi[4];
  3247. inset[0] = ( maxColor[0] - minColor[0] ) - ((1<<(INSET_COLOR_SHIFT-1))-1);
  3248. inset[1] = ( maxColor[1] - minColor[1] ) - ((1<<(INSET_COLOR_SHIFT-1))-1);
  3249. inset[3] = ( maxColor[3] - minColor[3] ) - ((1<<(INSET_ALPHA_SHIFT-1))-1);
  3250. mini[0] = ( ( minColor[0] << INSET_COLOR_SHIFT ) + inset[0] ) >> INSET_COLOR_SHIFT;
  3251. mini[1] = ( ( minColor[1] << INSET_COLOR_SHIFT ) + inset[1] ) >> INSET_COLOR_SHIFT;
  3252. mini[3] = ( ( minColor[3] << INSET_ALPHA_SHIFT ) + inset[3] ) >> INSET_ALPHA_SHIFT;
  3253. maxi[0] = ( ( maxColor[0] << INSET_COLOR_SHIFT ) - inset[0] ) >> INSET_COLOR_SHIFT;
  3254. maxi[1] = ( ( maxColor[1] << INSET_COLOR_SHIFT ) - inset[1] ) >> INSET_COLOR_SHIFT;
  3255. maxi[3] = ( ( maxColor[3] << INSET_ALPHA_SHIFT ) - inset[3] ) >> INSET_ALPHA_SHIFT;
  3256. mini[0] = ( mini[0] >= 0 ) ? mini[0] : 0;
  3257. mini[1] = ( mini[1] >= 0 ) ? mini[1] : 0;
  3258. mini[3] = ( mini[3] >= 0 ) ? mini[3] : 0;
  3259. maxi[0] = ( maxi[0] <= 255 ) ? maxi[0] : 255;
  3260. maxi[1] = ( maxi[1] <= 255 ) ? maxi[1] : 255;
  3261. maxi[3] = ( maxi[3] <= 255 ) ? maxi[3] : 255;
  3262. minColor[0] = byte( ( mini[0] & C565_5_MASK ) | ( mini[0] >> 5 ) );
  3263. minColor[1] = byte( ( mini[1] & C565_6_MASK ) | ( mini[1] >> 6 ) );
  3264. minColor[3] = byte( mini[3] );
  3265. maxColor[0] = byte( ( maxi[0] & C565_5_MASK ) | ( maxi[0] >> 5 ) );
  3266. maxColor[1] = byte( ( maxi[1] & C565_6_MASK ) | ( maxi[1] >> 6 ) );
  3267. maxColor[3] = byte( maxi[3] );
  3268. #endif
  3269. }
  3270. /*
  3271. ========================
  3272. idDxtEncoder::InsetYCoCgAlpaBBox
  3273. ========================
  3274. */
  3275. ID_INLINE void idDxtEncoder::InsetYCoCgAlpaBBox( byte *minColor, byte *maxColor ) const {
  3276. int inset[4];
  3277. int mini[4];
  3278. int maxi[4];
  3279. inset[0] = ( maxColor[0] - minColor[0] ) - ((1<<(INSET_COLOR_SHIFT-1))-1);
  3280. inset[1] = ( maxColor[1] - minColor[1] ) - ((1<<(INSET_COLOR_SHIFT-1))-1);
  3281. inset[2] = ( maxColor[2] - minColor[2] ) - ((1<<(INSET_COLOR_SHIFT-1))-1);
  3282. inset[3] = ( maxColor[3] - minColor[3] ) - ((1<<(INSET_ALPHA_SHIFT-1))-1);
  3283. mini[0] = ( ( minColor[0] << INSET_COLOR_SHIFT ) + inset[0] ) >> INSET_COLOR_SHIFT;
  3284. mini[1] = ( ( minColor[1] << INSET_COLOR_SHIFT ) + inset[1] ) >> INSET_COLOR_SHIFT;
  3285. mini[2] = ( ( minColor[2] << INSET_COLOR_SHIFT ) + inset[2] ) >> INSET_COLOR_SHIFT;
  3286. mini[3] = ( ( minColor[3] << INSET_ALPHA_SHIFT ) + inset[3] ) >> INSET_ALPHA_SHIFT;
  3287. maxi[0] = ( ( maxColor[0] << INSET_COLOR_SHIFT ) - inset[0] ) >> INSET_COLOR_SHIFT;
  3288. maxi[1] = ( ( maxColor[1] << INSET_COLOR_SHIFT ) - inset[1] ) >> INSET_COLOR_SHIFT;
  3289. maxi[2] = ( ( maxColor[2] << INSET_COLOR_SHIFT ) - inset[2] ) >> INSET_COLOR_SHIFT;
  3290. maxi[3] = ( ( maxColor[3] << INSET_ALPHA_SHIFT ) - inset[3] ) >> INSET_ALPHA_SHIFT;
  3291. mini[0] = ( mini[0] >= 0 ) ? mini[0] : 0;
  3292. mini[1] = ( mini[1] >= 0 ) ? mini[1] : 0;
  3293. mini[2] = ( mini[2] >= 0 ) ? mini[2] : 0;
  3294. mini[3] = ( mini[3] >= 0 ) ? mini[3] : 0;
  3295. maxi[0] = ( maxi[0] <= 255 ) ? maxi[0] : 255;
  3296. maxi[1] = ( maxi[1] <= 255 ) ? maxi[1] : 255;
  3297. maxi[2] = ( maxi[2] <= 255 ) ? maxi[2] : 255;
  3298. maxi[3] = ( maxi[3] <= 255 ) ? maxi[3] : 255;
  3299. minColor[0] = byte( ( mini[0] & C565_5_MASK ) | ( mini[0] >> 5 ) );
  3300. minColor[1] = byte( ( mini[1] & C565_6_MASK ) | ( mini[1] >> 6 ) );
  3301. minColor[2] = byte( ( mini[2] & C565_5_MASK ) | ( mini[2] >> 5 ) );
  3302. minColor[3] = byte( mini[3] );
  3303. maxColor[0] = byte( ( maxi[0] & C565_5_MASK ) | ( maxi[0] >> 5 ) );
  3304. maxColor[1] = byte( ( maxi[1] & C565_6_MASK ) | ( maxi[1] >> 6 ) );
  3305. maxColor[2] = byte( ( maxi[2] & C565_5_MASK ) | ( maxi[2] >> 5 ) );
  3306. maxColor[3] = byte( maxi[3] );
  3307. }
  3308. /*
  3309. ========================
  3310. idDxtEncoder::SelectYCoCgDiagonal
  3311. ========================
  3312. */
  3313. void idDxtEncoder::SelectYCoCgDiagonal( const byte *colorBlock, byte *minColor, byte *maxColor ) const {
  3314. byte side = 0;
  3315. byte mid0 = byte( ( (int) minColor[0] + maxColor[0] + 1 ) >> 1 );
  3316. byte mid1 = byte( ( (int) minColor[1] + maxColor[1] + 1 ) >> 1 );
  3317. for ( int i = 0; i < 16; i++ ) {
  3318. byte b0 = colorBlock[i*4+0] >= mid0;
  3319. byte b1 = colorBlock[i*4+1] >= mid1;
  3320. side += ( b0 ^ b1 );
  3321. }
  3322. byte mask = -( side > 8 );
  3323. #if defined NVIDIA_7X_HARDWARE_BUG_FIX
  3324. mask &= -( minColor[0] != maxColor[0] );
  3325. #endif
  3326. byte c0 = minColor[1];
  3327. byte c1 = maxColor[1];
  3328. c0 ^= c1;
  3329. mask &= c0;
  3330. c1 ^= mask;
  3331. c0 ^= c1;
  3332. minColor[1] = c0;
  3333. maxColor[1] = c1;
  3334. }
  3335. /*
  3336. ========================
  3337. idDxtEncoder::CompressYCoCgDXT5Fast_Generic
  3338. params: inBuf - image to compress
  3339. paramO: outBuf - result of compression
  3340. params: width - width of image
  3341. params: height - height of image
  3342. ========================
  3343. */
  3344. void idDxtEncoder::CompressYCoCgDXT5Fast_Generic( const byte *inBuf, byte *outBuf, int width, int height ) {
  3345. ALIGN16( byte block[64] );
  3346. ALIGN16( byte minColor[4] );
  3347. ALIGN16( byte maxColor[4] );
  3348. //assert( HasConstantValuePer4x4Block( inBuf, width, height, 2 ) );
  3349. assert( width >= 4 && ( width & 3 ) == 0 );
  3350. assert( height >= 4 && ( height & 3 ) == 0 );
  3351. this->width = width;
  3352. this->height = height;
  3353. this->outData = outBuf;
  3354. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  3355. for ( int i = 0; i < width; i += 4 ) {
  3356. ExtractBlock( inBuf + i * 4, width, block );
  3357. GetMinMaxBBox( block, minColor, maxColor );
  3358. ScaleYCoCg( block, minColor, maxColor );
  3359. InsetYCoCgBBox( minColor, maxColor );
  3360. SelectYCoCgDiagonal( block, minColor, maxColor );
  3361. EmitByte( maxColor[3] );
  3362. EmitByte( minColor[3] );
  3363. EmitAlphaIndices( block, 3, minColor[3], maxColor[3] );
  3364. #ifdef NVIDIA_7X_HARDWARE_BUG_FIX
  3365. // the colors are already sorted when selecting the diagonal
  3366. #endif
  3367. EmitUShort( ColorTo565( maxColor ) );
  3368. EmitUShort( ColorTo565( minColor ) );
  3369. EmitColorIndices( block, minColor, maxColor );
  3370. }
  3371. outData += dstPadding;
  3372. inBuf += srcPadding;
  3373. }
  3374. }
  3375. /*
  3376. ========================
  3377. idDxtEncoder::CompressYCoCgAlphaDXT5Fast
  3378. params: inBuf - image to compress
  3379. paramO: outBuf - result of compression
  3380. params: width - width of image
  3381. params: height - height of image
  3382. ========================
  3383. */
  3384. void idDxtEncoder::CompressYCoCgAlphaDXT5Fast( const byte *inBuf, byte *outBuf, int width, int height ) {
  3385. ALIGN16( byte block[64] );
  3386. ALIGN16( byte minColor[4] );
  3387. ALIGN16( byte maxColor[4] );
  3388. assert( width >= 4 && ( width & 3 ) == 0 );
  3389. assert( height >= 4 && ( height & 3 ) == 0 );
  3390. this->width = width;
  3391. this->height = height;
  3392. this->outData = outBuf;
  3393. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  3394. for ( int i = 0; i < width; i += 4 ) {
  3395. ExtractBlock( inBuf + i * 4, width, block );
  3396. // scale down the chroma of texels that are close to gray with low luminance
  3397. for ( int k = 0; k < 16; k++ ) {
  3398. if ( abs( block[k*4+0] - 132 ) <= 8 &&
  3399. abs( block[k*4+2] - 132 ) <= 8 &&
  3400. block[k*4+3] < 96 ) {
  3401. block[k*4+0] = ( block[k*4+0] - 132 ) / 2 + 132;
  3402. block[k*4+2] = ( block[k*4+2] - 132 ) / 2 + 132;
  3403. }
  3404. }
  3405. GetMinMaxBBox( block, minColor, maxColor );
  3406. InsetYCoCgAlpaBBox( minColor, maxColor );
  3407. SelectColorsDiagonal( block, minColor, maxColor );
  3408. EmitByte( maxColor[3] );
  3409. EmitByte( minColor[3] );
  3410. EmitAlphaIndices( block, 3, minColor[3], maxColor[3] );
  3411. #ifdef NVIDIA_7X_HARDWARE_BUG_FIX
  3412. // the colors are already sorted when selecting the diagonal
  3413. #endif
  3414. EmitUShort( ColorTo565( maxColor ) );
  3415. EmitUShort( ColorTo565( minColor ) );
  3416. EmitColorIndices( block, minColor, maxColor );
  3417. }
  3418. outData += dstPadding;
  3419. inBuf += srcPadding;
  3420. }
  3421. }
  3422. /*
  3423. ========================
  3424. idDxtEncoder::CompressYCoCgCTX1DXT5AFast_Generic
  3425. params: inBuf - image to compress
  3426. paramO: outBuf - result of compression
  3427. params: width - width of image
  3428. params: height - height of image
  3429. ========================
  3430. */
  3431. void idDxtEncoder::CompressYCoCgCTX1DXT5AFast_Generic( const byte *inBuf, byte *outBuf, int width, int height ) {
  3432. ALIGN16( byte block[64] );
  3433. ALIGN16( byte minColor[4] );
  3434. ALIGN16( byte maxColor[4] );
  3435. assert( HasConstantValuePer4x4Block( inBuf, width, height, 2 ) );
  3436. assert( width >= 4 && ( width & 3 ) == 0 );
  3437. assert( height >= 4 && ( height & 3 ) == 0 );
  3438. this->width = width;
  3439. this->height = height;
  3440. this->outData = outBuf;
  3441. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  3442. for ( int i = 0; i < width; i += 4 ) {
  3443. ExtractBlock( inBuf + i * 4, width, block );
  3444. GetMinMaxBBox( block, minColor, maxColor );
  3445. SelectYCoCgDiagonal( block, minColor, maxColor );
  3446. InsetColorsBBox( minColor, maxColor );
  3447. EmitByte( maxColor[3] );
  3448. EmitByte( minColor[3] );
  3449. EmitAlphaIndices( block, 3, minColor[3], maxColor[3] );
  3450. EmitByte( maxColor[0] );
  3451. EmitByte( maxColor[1] );
  3452. EmitByte( minColor[0] );
  3453. EmitByte( minColor[1] );
  3454. EmitCTX1Indices( block, minColor, maxColor );
  3455. }
  3456. outData += dstPadding;
  3457. inBuf += srcPadding;
  3458. }
  3459. }
  3460. /*
  3461. ========================
  3462. idDxtEncoder::EmitGreenIndices
  3463. params: block - block for which to find green indices
  3464. paramO: minGreen - Min green found
  3465. paramO: maxGreen - Max green found
  3466. ========================
  3467. */
  3468. void idDxtEncoder::EmitGreenIndices( const byte *block, const int offset, const byte minGreen, const byte maxGreen ) {
  3469. assert( maxGreen >= minGreen );
  3470. const int COLOR_RANGE = 3;
  3471. #if 1
  3472. byte yb1 = ( 5 * maxGreen + 1 * minGreen + COLOR_RANGE ) / ( 2 * COLOR_RANGE );
  3473. byte yb2 = ( 3 * maxGreen + 3 * minGreen + COLOR_RANGE ) / ( 2 * COLOR_RANGE );
  3474. byte yb3 = ( 1 * maxGreen + 5 * minGreen + COLOR_RANGE ) / ( 2 * COLOR_RANGE );
  3475. unsigned int result = 0;
  3476. block += offset;
  3477. for ( int i = 15; i >= 0; i-- ) {
  3478. result <<= 2;
  3479. byte y = block[i*4];
  3480. int b1 = ( y >= yb1 );
  3481. int b2 = ( y >= yb2 );
  3482. int b3 = ( y >= yb3 );
  3483. int index = ( 4 - b1 - b2 - b3 ) & 3;
  3484. index ^= ( 2 > index );
  3485. result |= index;
  3486. }
  3487. EmitUInt( result );
  3488. #else
  3489. byte green[4];
  3490. green[0] = maxGreen;
  3491. green[1] = minGreen;
  3492. green[2] = ( 2 * green[0] + 1 * green[1] ) / 3;
  3493. green[3] = ( 1 * green[0] + 2 * green[1] ) / 3;
  3494. unsigned int result = 0;
  3495. block += offset;
  3496. for ( int i = 15; i >= 0; i-- ) {
  3497. result <<= 2;
  3498. byte y = block[i*4];
  3499. int minDist = INT_MAX;
  3500. int index;
  3501. for ( int j = 0; j < 4; j++ ) {
  3502. int dist = abs( y - green[j] );
  3503. if ( dist < minDist ) {
  3504. minDist = dist;
  3505. index = j;
  3506. }
  3507. }
  3508. result |= index;
  3509. }
  3510. EmitUInt( result );
  3511. #endif
  3512. }
  3513. /*
  3514. ========================
  3515. idDxtEncoder::InsetNormalsBBoxDXT5
  3516. ========================
  3517. */
  3518. void idDxtEncoder::InsetNormalsBBoxDXT5( byte *minNormal, byte *maxNormal ) const {
  3519. int inset[4];
  3520. int mini[4];
  3521. int maxi[4];
  3522. inset[3] = ( maxNormal[3] - minNormal[3] ) - ((1<<(INSET_ALPHA_SHIFT-1))-1);
  3523. inset[1] = ( maxNormal[1] - minNormal[1] ) - ((1<<(INSET_COLOR_SHIFT-1))-1);
  3524. mini[3] = ( ( minNormal[3] << INSET_ALPHA_SHIFT ) + inset[3] ) >> INSET_ALPHA_SHIFT;
  3525. mini[1] = ( ( minNormal[1] << INSET_COLOR_SHIFT ) + inset[1] ) >> INSET_COLOR_SHIFT;
  3526. maxi[3] = ( ( maxNormal[3] << INSET_ALPHA_SHIFT ) - inset[3] ) >> INSET_ALPHA_SHIFT;
  3527. maxi[1] = ( ( maxNormal[1] << INSET_COLOR_SHIFT ) - inset[1] ) >> INSET_COLOR_SHIFT;
  3528. mini[3] = ( mini[3] >= 0 ) ? mini[3] : 0;
  3529. mini[1] = ( mini[1] >= 0 ) ? mini[1] : 0;
  3530. maxi[3] = ( maxi[3] <= 255 ) ? maxi[3] : 255;
  3531. maxi[1] = ( maxi[1] <= 255 ) ? maxi[1] : 255;
  3532. minNormal[3] = byte( mini[3] );
  3533. minNormal[1] = byte( ( mini[1] & C565_6_MASK ) | ( mini[1] >> 6 ) );
  3534. maxNormal[3] = byte( maxi[3] );
  3535. maxNormal[1] = byte( ( maxi[1] & C565_6_MASK ) | ( maxi[1] >> 6 ) );
  3536. }
  3537. /*
  3538. ========================
  3539. idDxtEncoder::InsetNormalsBBox3Dc
  3540. ========================
  3541. */
  3542. void idDxtEncoder::InsetNormalsBBox3Dc( byte *minNormal, byte *maxNormal ) const {
  3543. int inset[4];
  3544. int mini[4];
  3545. int maxi[4];
  3546. inset[0] = ( maxNormal[0] - minNormal[0] ) - ((1<<(INSET_ALPHA_SHIFT-1))-1);
  3547. inset[1] = ( maxNormal[1] - minNormal[1] ) - ((1<<(INSET_ALPHA_SHIFT-1))-1);
  3548. mini[0] = ( ( minNormal[0] << INSET_ALPHA_SHIFT ) + inset[0] ) >> INSET_ALPHA_SHIFT;
  3549. mini[1] = ( ( minNormal[1] << INSET_ALPHA_SHIFT ) + inset[1] ) >> INSET_ALPHA_SHIFT;
  3550. maxi[0] = ( ( maxNormal[0] << INSET_ALPHA_SHIFT ) - inset[0] ) >> INSET_ALPHA_SHIFT;
  3551. maxi[1] = ( ( maxNormal[1] << INSET_ALPHA_SHIFT ) - inset[1] ) >> INSET_ALPHA_SHIFT;
  3552. mini[0] = ( mini[0] >= 0 ) ? mini[0] : 0;
  3553. mini[1] = ( mini[1] >= 0 ) ? mini[1] : 0;
  3554. maxi[0] = ( maxi[0] <= 255 ) ? maxi[0] : 255;
  3555. maxi[1] = ( maxi[1] <= 255 ) ? maxi[1] : 255;
  3556. minNormal[0] = (byte)mini[0];
  3557. minNormal[1] = (byte)mini[1];
  3558. maxNormal[0] = (byte)maxi[0];
  3559. maxNormal[1] = (byte)maxi[1];
  3560. }
  3561. /*
  3562. ========================
  3563. idDxtEncoder::CompressNormalMapDXT5Fast_Generic
  3564. params: inBuf - image to compress
  3565. paramO: outBuf - result of compression
  3566. params: width - width of image
  3567. params: height - height of image
  3568. ========================
  3569. */
  3570. void idDxtEncoder::CompressNormalMapDXT5Fast_Generic( const byte *inBuf, byte *outBuf, int width, int height ) {
  3571. ALIGN16( byte block[64] );
  3572. ALIGN16( byte normal1[4] );
  3573. ALIGN16( byte normal2[4] );
  3574. assert( width >= 4 && ( width & 3 ) == 0 );
  3575. assert( height >= 4 && ( height & 3 ) == 0 );
  3576. this->width = width;
  3577. this->height = height;
  3578. this->outData = outBuf;
  3579. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  3580. for ( int i = 0; i < width; i += 4 ) {
  3581. ExtractBlock( inBuf + i * 4, width, block );
  3582. GetMinMaxBBox( block, normal1, normal2 );
  3583. InsetNormalsBBoxDXT5( normal1, normal2 );
  3584. // Write out Nx into alpha channel.
  3585. EmitByte( normal2[3] );
  3586. EmitByte( normal1[3] );
  3587. EmitAlphaIndices( block, 3, normal1[3], normal2[3] );
  3588. // Write out Ny into green channel.
  3589. EmitUShort( ColorTo565( block[0], normal2[1], block[2] ) );
  3590. EmitUShort( ColorTo565( block[0], normal1[1], block[2] ) );
  3591. EmitGreenIndices( block, 1, normal1[1], normal2[1] );
  3592. }
  3593. outData += dstPadding;
  3594. inBuf += srcPadding;
  3595. }
  3596. }
  3597. /*
  3598. ========================
  3599. idDxtEncoder::CompressImageDXN1Fast_Generic
  3600. params: inBuf - image to compress
  3601. paramO: outBuf - result of compression
  3602. params: width - width of image
  3603. params: height - height of image
  3604. ========================
  3605. */
  3606. void idDxtEncoder::CompressImageDXN1Fast_Generic( const byte *inBuf, byte *outBuf, int width, int height ) {
  3607. ALIGN16( byte block[64] );
  3608. ALIGN16( byte min[4] );
  3609. ALIGN16( byte max[4] );
  3610. assert( width >= 4 && ( width & 3 ) == 0 );
  3611. assert( height >= 4 && ( height & 3 ) == 0 );
  3612. this->width = width;
  3613. this->height = height;
  3614. this->outData = outBuf;
  3615. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  3616. for ( int i = 0; i < width; i += 4 ) {
  3617. ExtractBlock( inBuf + i * 4, width, block );
  3618. GetMinMaxBBox( block, min, max );
  3619. InsetNormalsBBox3Dc( min, max );
  3620. // Write out an alpha channel.
  3621. EmitByte( max[0] );
  3622. EmitByte( min[0] );
  3623. EmitAlphaIndices( block, 0, min[0], max[0] );
  3624. }
  3625. outData += dstPadding;
  3626. inBuf += srcPadding;
  3627. }
  3628. }
  3629. /*
  3630. ========================
  3631. idDxtEncoder::CompressNormalMapDXN2Fast_Generic
  3632. params: inBuf - image to compress
  3633. paramO: outBuf - result of compression
  3634. params: width - width of image
  3635. params: height - height of image
  3636. ========================
  3637. */
  3638. void idDxtEncoder::CompressNormalMapDXN2Fast_Generic( const byte *inBuf, byte *outBuf, int width, int height ) {
  3639. ALIGN16( byte block[64] );
  3640. ALIGN16( byte normal1[4] );
  3641. ALIGN16( byte normal2[4] );
  3642. assert( width >= 4 && ( width & 3 ) == 0 );
  3643. assert( height >= 4 && ( height & 3 ) == 0 );
  3644. this->width = width;
  3645. this->height = height;
  3646. this->outData = outBuf;
  3647. for ( int j = 0; j < height; j += 4, inBuf += width * 4*4 ) {
  3648. for ( int i = 0; i < width; i += 4 ) {
  3649. ExtractBlock( inBuf + i * 4, width, block );
  3650. GetMinMaxBBox( block, normal1, normal2 );
  3651. InsetNormalsBBox3Dc( normal1, normal2 );
  3652. // Write out Nx as an alpha channel.
  3653. EmitByte( normal2[0] );
  3654. EmitByte( normal1[0] );
  3655. EmitAlphaIndices( block, 0, normal1[0], normal2[0] );
  3656. // Write out Ny as an alpha channel.
  3657. EmitByte( normal2[1] );
  3658. EmitByte( normal1[1] );
  3659. EmitAlphaIndices( block, 1, normal1[1], normal2[1] );
  3660. }
  3661. outData += dstPadding;
  3662. inBuf += srcPadding;
  3663. }
  3664. }
  3665. /*
  3666. ========================
  3667. idDxtEncoder::DecodeDXNAlphaValues
  3668. ========================
  3669. */
  3670. void idDxtEncoder::DecodeDXNAlphaValues( const byte *inBuf, byte *values ) {
  3671. int i;
  3672. unsigned int indices;
  3673. byte alphas[8];
  3674. if ( inBuf[0] <= inBuf[1] ) {
  3675. alphas[0] = inBuf[0];
  3676. alphas[1] = inBuf[1];
  3677. alphas[2] = ( 4 * alphas[0] + 1 * alphas[1] ) / 5;
  3678. alphas[3] = ( 3 * alphas[0] + 2 * alphas[1] ) / 5;
  3679. alphas[4] = ( 2 * alphas[0] + 3 * alphas[1] ) / 5;
  3680. alphas[5] = ( 1 * alphas[0] + 4 * alphas[1] ) / 5;
  3681. alphas[6] = 0;
  3682. alphas[7] = 255;
  3683. } else {
  3684. alphas[0] = inBuf[0];
  3685. alphas[1] = inBuf[1];
  3686. alphas[2] = ( 6 * alphas[0] + 1 * alphas[1] ) / 7;
  3687. alphas[3] = ( 5 * alphas[0] + 2 * alphas[1] ) / 7;
  3688. alphas[4] = ( 4 * alphas[0] + 3 * alphas[1] ) / 7;
  3689. alphas[5] = ( 3 * alphas[0] + 4 * alphas[1] ) / 7;
  3690. alphas[6] = ( 2 * alphas[0] + 5 * alphas[1] ) / 7;
  3691. alphas[7] = ( 1 * alphas[0] + 6 * alphas[1] ) / 7;
  3692. }
  3693. indices = (int)inBuf[2] | ( (int)inBuf[3] << 8 ) | ( (int)inBuf[4] << 16 );
  3694. for ( i = 0; i < 8; i++ ) {
  3695. values[i] = alphas[indices & 7];
  3696. indices >>= 3;
  3697. }
  3698. indices = (int)inBuf[5] | ( (int)inBuf[6] << 8 ) | ( (int)inBuf[7] << 16 );
  3699. for ( i = 8; i < 16; i++ ) {
  3700. values[i] = alphas[indices & 7];
  3701. indices >>= 3;
  3702. }
  3703. }
  3704. /*
  3705. ========================
  3706. idDxtEncoder::EncodeNormalRGBIndices
  3707. params: values - 16 normal block for which to find normal Y indices
  3708. paramO: min - Min grayscale value
  3709. paramO: max - Max grayscale value
  3710. ========================
  3711. */
  3712. void idDxtEncoder::EncodeNormalRGBIndices( byte *outBuf, const byte min, const byte max, const byte *values ) {
  3713. const int COLOR_RANGE = 3;
  3714. byte maskedMin, maskedMax, mid, yb1, yb2, yb3;
  3715. maskedMax = max & C565_6_MASK;
  3716. maskedMin = min & C565_6_MASK;
  3717. mid = ( maskedMax - maskedMin ) / ( 2 * COLOR_RANGE );
  3718. yb1 = maskedMax - mid;
  3719. yb2 = ( 2 * maskedMax + 1 * maskedMin ) / COLOR_RANGE - mid;
  3720. yb3 = ( 1 * maskedMax + 2 * maskedMin ) / COLOR_RANGE - mid;
  3721. unsigned int result = 0;
  3722. for ( int i = 15; i >= 0; i-- ) {
  3723. result <<= 2;
  3724. byte y = values[i];
  3725. int b1 = ( y >= yb1 );
  3726. int b2 = ( y >= yb2 );
  3727. int b3 = ( y >= yb3 );
  3728. int index = ( 4 - b1 - b2 - b3 ) & 3;
  3729. index ^= ( 2 > index );
  3730. result |= index;
  3731. }
  3732. unsigned short maskedMax5 = (max & C565_5_MASK) >> 3;
  3733. unsigned short maskedMin5 = (min & C565_5_MASK) >> 3;
  3734. unsigned short smax = (maskedMax5 << 11) | (maskedMax << 3) | maskedMax5;
  3735. unsigned short smin = (maskedMin5 << 11) | (maskedMin << 3) | maskedMin5;
  3736. outBuf[0] = byte( ( smax >> 0 ) & 0xFF );
  3737. outBuf[1] = byte( ( smax >> 8 ) & 0xFF );
  3738. outBuf[2] = byte( ( smin >> 0 ) & 0xFF );
  3739. outBuf[3] = byte( ( smin >> 8 ) & 0xFF );
  3740. outBuf[4] = byte( ( result >> 0 ) & 0xFF );
  3741. outBuf[5] = byte( ( result >> 8 ) & 0xFF );
  3742. outBuf[6] = byte( ( result >> 16 ) & 0xFF );
  3743. outBuf[7] = byte( ( result >> 24 ) & 0xFF );
  3744. }
  3745. /*
  3746. ========================
  3747. idDxtEncoder::ConvertNormalMapDXN2_DXT5
  3748. params: inBuf - normal map compressed in DXN2 format
  3749. paramO: outBuf - result of compression in DXT5 format
  3750. params: width - width of image
  3751. params: height - height of image
  3752. ========================
  3753. */
  3754. void idDxtEncoder::ConvertNormalMapDXN2_DXT5( const byte *inBuf, byte *outBuf, int width, int height ) {
  3755. ALIGN16( byte values[16] );
  3756. this->width = width;
  3757. this->height = height;
  3758. this->outData = outBuf;
  3759. if ( width > 4 && ( width & 3 ) != 0 ) {
  3760. return;
  3761. }
  3762. if ( height > 4 && ( height & 3 ) != 0 ) {
  3763. return;
  3764. }
  3765. if ( width < 4 || height < 4 ) {
  3766. assert( 0 );
  3767. return;
  3768. }
  3769. for ( int j = 0; j < height; j += 4 ) {
  3770. for ( int i = 0; i < width; i += 4, inBuf += 16, outBuf += 16 ) {
  3771. // decode normal Y stored as a DXT5 alpha channel
  3772. DecodeDXNAlphaValues( inBuf + 0, values );
  3773. // copy normal X
  3774. memcpy( outBuf + 0, inBuf + 8, 8 );
  3775. // get the min/max Y
  3776. byte minNormalY = 255;
  3777. byte maxNormalY = 0;
  3778. for ( int i = 0; i < 16; i++ ) {
  3779. if ( values[i] < minNormalY ) {
  3780. minNormalY = values[i];
  3781. }
  3782. if ( values[i] > maxNormalY ) {
  3783. maxNormalY = values[i];
  3784. }
  3785. }
  3786. // encode normal Y into DXT5 color channels
  3787. EncodeNormalRGBIndices( outBuf + 8, minNormalY, maxNormalY, values );
  3788. }
  3789. outData += dstPadding;
  3790. inBuf += srcPadding;
  3791. }
  3792. }
  3793. /*
  3794. ========================
  3795. idDxtEncoder::DecodeNormalYValues
  3796. ========================
  3797. */
  3798. void idDxtEncoder::DecodeNormalYValues( const byte *inBuf, byte &min, byte &max, byte *values ) {
  3799. int i;
  3800. unsigned int indexes;
  3801. unsigned short normal0, normal1;
  3802. byte normalsY[4];
  3803. normal0 = inBuf[0] | (inBuf[1] << 8);
  3804. normal1 = inBuf[2] | (inBuf[3] << 8);
  3805. assert( normal0 >= normal1 );
  3806. normalsY[0] = GreenFrom565( normal0 );
  3807. normalsY[1] = GreenFrom565( normal1 );
  3808. normalsY[2] = ( 2 * normalsY[0] + 1 * normalsY[1] ) / 3;
  3809. normalsY[3] = ( 1 * normalsY[0] + 2 * normalsY[1] ) / 3;
  3810. indexes = (unsigned int)inBuf[4] | ((unsigned int)inBuf[5]<<8) | ((unsigned int)inBuf[6]<<16) | ((unsigned int)inBuf[7]<<24);
  3811. for ( i = 0; i < 16; i++ ) {
  3812. values[i] = normalsY[indexes & 3];
  3813. indexes >>= 2;
  3814. }
  3815. max = normalsY[0];
  3816. min = normalsY[1];
  3817. }
  3818. /*
  3819. ========================
  3820. idDxtEncoder::EncodeDXNAlphaValues
  3821. ========================
  3822. */
  3823. void idDxtEncoder::EncodeDXNAlphaValues( byte *outBuf, const byte min, const byte max, const byte *values ) {
  3824. int i;
  3825. byte alphas[8];
  3826. int j;
  3827. unsigned int indexes[16];
  3828. alphas[0] = max;
  3829. alphas[1] = min;
  3830. alphas[2] = ( 6 * alphas[0] + 1 * alphas[1] ) / 7;
  3831. alphas[3] = ( 5 * alphas[0] + 2 * alphas[1] ) / 7;
  3832. alphas[4] = ( 4 * alphas[0] + 3 * alphas[1] ) / 7;
  3833. alphas[5] = ( 3 * alphas[0] + 4 * alphas[1] ) / 7;
  3834. alphas[6] = ( 2 * alphas[0] + 5 * alphas[1] ) / 7;
  3835. alphas[7] = ( 1 * alphas[0] + 6 * alphas[1] ) / 7;
  3836. int error = 0;
  3837. for ( i = 0; i < 16; i++ ) {
  3838. int minDist = MAX_TYPE( int );
  3839. byte a = values[i];
  3840. for ( j = 0; j < 8; j++ ) {
  3841. int dist = AlphaDistance( a, alphas[j] );
  3842. if ( dist < minDist ) {
  3843. minDist = dist;
  3844. indexes[i] = j;
  3845. }
  3846. }
  3847. error += minDist;
  3848. }
  3849. outBuf[0] = max;
  3850. outBuf[1] = min;
  3851. outBuf[2] = byte( (indexes[ 0] >> 0) | (indexes[ 1] << 3) | (indexes[ 2] << 6) );
  3852. outBuf[3] = byte( (indexes[ 2] >> 2) | (indexes[ 3] << 1) | (indexes[ 4] << 4) | (indexes[ 5] << 7) );
  3853. outBuf[4] = byte( (indexes[ 5] >> 1) | (indexes[ 6] << 2) | (indexes[ 7] << 5) );
  3854. outBuf[5] = byte( (indexes[ 8] >> 0) | (indexes[ 9] << 3) | (indexes[10] << 6) );
  3855. outBuf[6] = byte( (indexes[10] >> 2) | (indexes[11] << 1) | (indexes[12] << 4) | (indexes[13] << 7) );
  3856. outBuf[7] = byte( (indexes[13] >> 1) | (indexes[14] << 2) | (indexes[15] << 5) );
  3857. }
  3858. /*
  3859. ========================
  3860. idDxtEncoder::ConvertNormalMapDXT5_DXN2
  3861. params: inBuf - image to compress
  3862. paramO: outBuf - result of compression
  3863. params: width - width of image
  3864. params: height - height of image
  3865. ========================
  3866. */
  3867. void idDxtEncoder::ConvertNormalMapDXT5_DXN2( const byte *inBuf, byte *outBuf, int width, int height ) {
  3868. ALIGN16( byte values[16] );
  3869. byte minNormalY, maxNormalY;
  3870. this->width = width;
  3871. this->height = height;
  3872. this->outData = outBuf;
  3873. if ( width > 4 && ( width & 3 ) != 0 ) {
  3874. return;
  3875. }
  3876. if ( height > 4 && ( height & 3 ) != 0 ) {
  3877. return;
  3878. }
  3879. if ( width < 4 || height < 4 ) {
  3880. assert( 0 );
  3881. return;
  3882. }
  3883. for ( int j = 0; j < height; j += 4 ) {
  3884. for ( int i = 0; i < width; i += 4, inBuf += 16, outBuf += 16 ) {
  3885. // decode normal Y stored as a DXT5 alpha channel
  3886. DecodeNormalYValues( inBuf + 8, minNormalY, maxNormalY, values );
  3887. memcpy( outBuf + 8, inBuf + 0, 8 );
  3888. // encode normal Y into DXT5 green channel
  3889. EncodeDXNAlphaValues( outBuf + 0, minNormalY, maxNormalY, values );
  3890. }
  3891. outData += dstPadding;
  3892. inBuf += srcPadding;
  3893. }
  3894. }
  3895. /*
  3896. ========================
  3897. idDxtEncoder::ConvertImageDXN1_DXT1
  3898. params: inBuf - normal map compressed in DXN1 format
  3899. paramO: outBuf - result of compression in DXT1 format
  3900. params: width - width of image
  3901. params: height - height of image
  3902. ========================
  3903. */
  3904. void idDxtEncoder::ConvertImageDXN1_DXT1( const byte *inBuf, byte *outBuf, int width, int height ) {
  3905. ALIGN16( byte values[16] );
  3906. this->width = width;
  3907. this->height = height;
  3908. this->outData = outBuf;
  3909. if ( width > 4 && ( width & 3 ) != 0 ) {
  3910. return;
  3911. }
  3912. if ( height > 4 && ( height & 3 ) != 0 ) {
  3913. return;
  3914. }
  3915. if ( width < 4 || height < 4 ) {
  3916. assert( 0 );
  3917. return;
  3918. }
  3919. for ( int j = 0; j < height; j += 4 ) {
  3920. for ( int i = 0; i < width; i += 4, inBuf += 8, outBuf += 8 ) {
  3921. // decode single channel stored as a DXT5 alpha channel
  3922. DecodeDXNAlphaValues( inBuf + 0, values );
  3923. // get the min/max
  3924. byte min = 255;
  3925. byte max = 0;
  3926. for ( int i = 0; i < 16; i++ ) {
  3927. if ( values[i] < min ) {
  3928. min = values[i];
  3929. }
  3930. if ( values[i] > max ) {
  3931. max = values[i];
  3932. }
  3933. }
  3934. // encode single channel into DXT1
  3935. EncodeNormalRGBIndices( outBuf + 0, min, max, values );
  3936. }
  3937. outData += dstPadding;
  3938. inBuf += srcPadding;
  3939. }
  3940. }