b634a4d938ebc7bcb965ec5b3a7f411a94978d1a
[blender-staging.git] / source / blender / imbuf / intern / dds / BlockDXT.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * Contributors: Amorilia (amorilia@users.sourceforge.net)
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /** \file blender/imbuf/intern/dds/BlockDXT.cpp
26  *  \ingroup imbdds
27  */
28
29
30 /*
31  * This file is based on a similar file from the NVIDIA texture tools
32  * (http://nvidia-texture-tools.googlecode.com/)
33  *
34  * Original license from NVIDIA follows.
35  */
36
37 // Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
38 // 
39 // Permission is hereby granted, free of charge, to any person
40 // obtaining a copy of this software and associated documentation
41 // files (the "Software"), to deal in the Software without
42 // restriction, including without limitation the rights to use,
43 // copy, modify, merge, publish, distribute, sublicense, and/or sell
44 // copies of the Software, and to permit persons to whom the
45 // Software is furnished to do so, subject to the following
46 // conditions:
47 // 
48 // The above copyright notice and this permission notice shall be
49 // included in all copies or substantial portions of the Software.
50 // 
51 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
52 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
53 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
54 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
55 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
56 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
57 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
58 // OTHER DEALINGS IN THE SOFTWARE.
59
60 #include <Common.h>
61 #include <Stream.h>
62 #include <ColorBlock.h>
63 #include <BlockDXT.h>
64
65 /*----------------------------------------------------------------------------
66         BlockDXT1
67 ----------------------------------------------------------------------------*/
68
69 uint BlockDXT1::evaluatePalette(Color32 color_array[4]) const
70 {
71         // Does bit expansion before interpolation.
72         color_array[0].b = (col0.b << 3) | (col0.b >> 2);
73         color_array[0].g = (col0.g << 2) | (col0.g >> 4);
74         color_array[0].r = (col0.r << 3) | (col0.r >> 2);
75         color_array[0].a = 0xFF;
76         
77         // @@ Same as above, but faster?
78 //      Color32 c;
79 //      c.u = ((col0.u << 3) & 0xf8) | ((col0.u << 5) & 0xfc00) | ((col0.u << 8) & 0xf80000);
80 //      c.u |= (c.u >> 5) & 0x070007;
81 //      c.u |= (c.u >> 6) & 0x000300;
82 //      color_array[0].u = c.u;
83         
84         color_array[1].r = (col1.r << 3) | (col1.r >> 2);
85         color_array[1].g = (col1.g << 2) | (col1.g >> 4);
86         color_array[1].b = (col1.b << 3) | (col1.b >> 2);
87         color_array[1].a = 0xFF;
88         
89         // @@ Same as above, but faster?
90 //      c.u = ((col1.u << 3) & 0xf8) | ((col1.u << 5) & 0xfc00) | ((col1.u << 8) & 0xf80000);
91 //      c.u |= (c.u >> 5) & 0x070007;
92 //      c.u |= (c.u >> 6) & 0x000300;
93 //      color_array[1].u = c.u;
94         
95         if( col0.u > col1.u ) {
96                 // Four-color block: derive the other two colors.
97                 color_array[2].r = (2 * color_array[0].r + color_array[1].r) / 3;
98                 color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3;
99                 color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3;
100                 color_array[2].a = 0xFF;
101                 
102                 color_array[3].r = (2 * color_array[1].r + color_array[0].r) / 3;
103                 color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3;
104                 color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3;
105                 color_array[3].a = 0xFF;
106                 
107                 return 4;
108         }
109         else {
110                 // Three-color block: derive the other color.
111                 color_array[2].r = (color_array[0].r + color_array[1].r) / 2;
112                 color_array[2].g = (color_array[0].g + color_array[1].g) / 2;
113                 color_array[2].b = (color_array[0].b + color_array[1].b) / 2;
114                 color_array[2].a = 0xFF;
115                 
116                 // Set all components to 0 to match DXT specs.
117                 color_array[3].r = 0x00; // color_array[2].r;
118                 color_array[3].g = 0x00; // color_array[2].g;
119                 color_array[3].b = 0x00; // color_array[2].b;
120                 color_array[3].a = 0x00;
121                 
122                 return 3;
123         }
124 }
125
126 // Evaluate palette assuming 3 color block.
127 void BlockDXT1::evaluatePalette3(Color32 color_array[4]) const
128 {
129         color_array[0].b = (col0.b << 3) | (col0.b >> 2);
130         color_array[0].g = (col0.g << 2) | (col0.g >> 4);
131         color_array[0].r = (col0.r << 3) | (col0.r >> 2);
132         color_array[0].a = 0xFF;
133         
134         color_array[1].r = (col1.r << 3) | (col1.r >> 2);
135         color_array[1].g = (col1.g << 2) | (col1.g >> 4);
136         color_array[1].b = (col1.b << 3) | (col1.b >> 2);
137         color_array[1].a = 0xFF;
138         
139         // Three-color block: derive the other color.
140         color_array[2].r = (color_array[0].r + color_array[1].r) / 2;
141         color_array[2].g = (color_array[0].g + color_array[1].g) / 2;
142         color_array[2].b = (color_array[0].b + color_array[1].b) / 2;
143         color_array[2].a = 0xFF;
144                 
145         // Set all components to 0 to match DXT specs.
146         color_array[3].r = 0x00; // color_array[2].r;
147         color_array[3].g = 0x00; // color_array[2].g;
148         color_array[3].b = 0x00; // color_array[2].b;
149         color_array[3].a = 0x00;
150 }
151
152 // Evaluate palette assuming 4 color block.
153 void BlockDXT1::evaluatePalette4(Color32 color_array[4]) const
154 {
155         color_array[0].b = (col0.b << 3) | (col0.b >> 2);
156         color_array[0].g = (col0.g << 2) | (col0.g >> 4);
157         color_array[0].r = (col0.r << 3) | (col0.r >> 2);
158         color_array[0].a = 0xFF;
159         
160         color_array[1].r = (col1.r << 3) | (col1.r >> 2);
161         color_array[1].g = (col1.g << 2) | (col1.g >> 4);
162         color_array[1].b = (col1.b << 3) | (col1.b >> 2);
163         color_array[1].a = 0xFF;
164         
165         // Four-color block: derive the other two colors.
166         color_array[2].r = (2 * color_array[0].r + color_array[1].r) / 3;
167         color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3;
168         color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3;
169         color_array[2].a = 0xFF;
170                 
171         color_array[3].r = (2 * color_array[1].r + color_array[0].r) / 3;
172         color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3;
173         color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3;
174         color_array[3].a = 0xFF;
175 }
176
177 void BlockDXT1::decodeBlock(ColorBlock * block) const
178 {
179         // Decode color block.
180         Color32 color_array[4];
181         evaluatePalette(color_array);
182         
183         // Write color block.
184         for( uint j = 0; j < 4; j++ ) {
185                 for( uint i = 0; i < 4; i++ ) {
186                         uint idx = (row[j] >> (2 * i)) & 3;
187                         block->color(i, j) = color_array[idx];
188                 }
189         }       
190 }
191
192 void BlockDXT1::setIndices(int * idx)
193 {
194         indices = 0;
195         for(uint i = 0; i < 16; i++) {
196                 indices |= (idx[i] & 3) << (2 * i);
197         }
198 }
199
200
201 /// Flip DXT1 block vertically.
202 inline void BlockDXT1::flip4()
203 {
204         swap(row[0], row[3]);
205         swap(row[1], row[2]);
206 }
207
208 /// Flip half DXT1 block vertically.
209 inline void BlockDXT1::flip2()
210 {
211         swap(row[0], row[1]);
212 }
213
214
215 /*----------------------------------------------------------------------------
216         BlockDXT3
217 ----------------------------------------------------------------------------*/
218
219 void BlockDXT3::decodeBlock(ColorBlock * block) const
220 {
221         // Decode color.
222         color.decodeBlock(block);
223         
224         // Decode alpha.
225         alpha.decodeBlock(block);
226 }
227
228 void AlphaBlockDXT3::decodeBlock(ColorBlock * block) const
229 {
230         block->color(0x0).a = (alpha0 << 4) | alpha0;
231         block->color(0x1).a = (alpha1 << 4) | alpha1;
232         block->color(0x2).a = (alpha2 << 4) | alpha2;
233         block->color(0x3).a = (alpha3 << 4) | alpha3;
234         block->color(0x4).a = (alpha4 << 4) | alpha4;
235         block->color(0x5).a = (alpha5 << 4) | alpha5;
236         block->color(0x6).a = (alpha6 << 4) | alpha6;
237         block->color(0x7).a = (alpha7 << 4) | alpha7;
238         block->color(0x8).a = (alpha8 << 4) | alpha8;
239         block->color(0x9).a = (alpha9 << 4) | alpha9;
240         block->color(0xA).a = (alphaA << 4) | alphaA;
241         block->color(0xB).a = (alphaB << 4) | alphaB;
242         block->color(0xC).a = (alphaC << 4) | alphaC;
243         block->color(0xD).a = (alphaD << 4) | alphaD;
244         block->color(0xE).a = (alphaE << 4) | alphaE;
245         block->color(0xF).a = (alphaF << 4) | alphaF;
246 }
247
248 /// Flip DXT3 alpha block vertically.
249 void AlphaBlockDXT3::flip4()
250 {
251         swap(row[0], row[3]);
252         swap(row[1], row[2]);
253 }
254
255 /// Flip half DXT3 alpha block vertically.
256 void AlphaBlockDXT3::flip2()
257 {
258         swap(row[0], row[1]);
259 }
260
261 /// Flip DXT3 block vertically.
262 void BlockDXT3::flip4()
263 {
264         alpha.flip4();
265         color.flip4();
266 }
267
268 /// Flip half DXT3 block vertically.
269 void BlockDXT3::flip2()
270 {
271         alpha.flip2();
272         color.flip2();
273 }
274
275
276 /*----------------------------------------------------------------------------
277         BlockDXT5
278 ----------------------------------------------------------------------------*/
279
280 void AlphaBlockDXT5::evaluatePalette(uint8 alpha[8]) const
281 {
282         if (alpha0() > alpha1()) {
283                 evaluatePalette8(alpha);
284         }
285         else {
286                 evaluatePalette6(alpha);
287         }
288 }
289
290 void AlphaBlockDXT5::evaluatePalette8(uint8 alpha[8]) const
291 {
292         // 8-alpha block:  derive the other six alphas.
293         // Bit code 000 = alpha0, 001 = alpha1, others are interpolated.
294         alpha[0] = alpha0();
295         alpha[1] = alpha1();
296         alpha[2] = (6 * alpha[0] + 1 * alpha[1]) / 7;   // bit code 010
297         alpha[3] = (5 * alpha[0] + 2 * alpha[1]) / 7;   // bit code 011
298         alpha[4] = (4 * alpha[0] + 3 * alpha[1]) / 7;   // bit code 100
299         alpha[5] = (3 * alpha[0] + 4 * alpha[1]) / 7;   // bit code 101
300         alpha[6] = (2 * alpha[0] + 5 * alpha[1]) / 7;   // bit code 110
301         alpha[7] = (1 * alpha[0] + 6 * alpha[1]) / 7;   // bit code 111
302 }
303
304 void AlphaBlockDXT5::evaluatePalette6(uint8 alpha[8]) const
305 {
306         // 6-alpha block.
307         // Bit code 000 = alpha0, 001 = alpha1, others are interpolated.
308         alpha[0] = alpha0();
309         alpha[1] = alpha1();
310         alpha[2] = (4 * alpha[0] + 1 * alpha[1]) / 5;   // Bit code 010
311         alpha[3] = (3 * alpha[0] + 2 * alpha[1]) / 5;   // Bit code 011
312         alpha[4] = (2 * alpha[0] + 3 * alpha[1]) / 5;   // Bit code 100
313         alpha[5] = (1 * alpha[0] + 4 * alpha[1]) / 5;   // Bit code 101
314         alpha[6] = 0x00;                                                        // Bit code 110
315         alpha[7] = 0xFF;                                                        // Bit code 111
316 }
317
318 void AlphaBlockDXT5::indices(uint8 index_array[16]) const
319 {
320         index_array[0x0] = bits0();
321         index_array[0x1] = bits1();
322         index_array[0x2] = bits2();
323         index_array[0x3] = bits3();
324         index_array[0x4] = bits4();
325         index_array[0x5] = bits5();
326         index_array[0x6] = bits6();
327         index_array[0x7] = bits7();
328         index_array[0x8] = bits8();
329         index_array[0x9] = bits9();
330         index_array[0xA] = bitsA();
331         index_array[0xB] = bitsB();
332         index_array[0xC] = bitsC();
333         index_array[0xD] = bitsD();
334         index_array[0xE] = bitsE();
335         index_array[0xF] = bitsF();
336 }
337
338 uint AlphaBlockDXT5::index(uint index) const
339 {
340         int offset = (3 * index + 16);
341         return uint((this->u >> offset) & 0x7);
342 }
343
344 void AlphaBlockDXT5::setIndex(uint index, uint value)
345 {
346         int offset = (3 * index + 16);
347         uint64 mask = uint64(0x7) << offset;
348         this->u = (this->u & ~mask) | (uint64(value) << offset);
349 }
350
351 void AlphaBlockDXT5::decodeBlock(ColorBlock * block) const
352 {
353         uint8 alpha_array[8];
354         evaluatePalette(alpha_array);
355         
356         uint8 index_array[16];
357         indices(index_array);
358         
359         for(uint i = 0; i < 16; i++) {
360                 block->color(i).a = alpha_array[index_array[i]];
361         }
362 }
363
364 void AlphaBlockDXT5::flip4()
365 {
366         uint64 * b = (uint64 *)this;
367         
368         // @@ The masks might have to be byte swapped.
369         uint64 tmp = (*b & (uint64)(0x000000000000FFFFLL));
370         tmp |= (*b & (uint64)(0x000000000FFF0000LL)) << 36;
371         tmp |= (*b & (uint64)(0x000000FFF0000000LL)) << 12;
372         tmp |= (*b & (uint64)(0x000FFF0000000000LL)) >> 12;
373         tmp |= (*b & (uint64)(0xFFF0000000000000LL)) >> 36;
374         
375         *b = tmp;
376 }
377
378 void AlphaBlockDXT5::flip2()
379 {
380         uint * b = (uint *)this;
381         
382         // @@ The masks might have to be byte swapped.
383         uint tmp = (*b & 0xFF000000);
384         tmp |=  (*b & 0x00000FFF) << 12;
385         tmp |= (*b & 0x00FFF000) >> 12;
386         
387         *b = tmp;
388 }
389
390 void BlockDXT5::decodeBlock(ColorBlock * block) const
391 {
392         // Decode color.
393         color.decodeBlock(block);
394         
395         // Decode alpha.
396         alpha.decodeBlock(block);
397
398 }
399
400 /// Flip DXT5 block vertically.
401 void BlockDXT5::flip4()
402 {
403         alpha.flip4();
404         color.flip4();
405 }
406
407 /// Flip half DXT5 block vertically.
408 void BlockDXT5::flip2()
409 {
410         alpha.flip2();
411         color.flip2();
412 }
413
414
415 /// Decode ATI1 block.
416 void BlockATI1::decodeBlock(ColorBlock * block) const
417 {
418         uint8 alpha_array[8];
419         alpha.evaluatePalette(alpha_array);
420         
421         uint8 index_array[16];
422         alpha.indices(index_array);
423         
424         for(uint i = 0; i < 16; i++) {
425                 Color32 & c = block->color(i);
426                 c.b = c.g = c.r = alpha_array[index_array[i]];
427                 c.a = 255;
428         }
429 }
430
431 /// Flip ATI1 block vertically.
432 void BlockATI1::flip4()
433 {
434         alpha.flip4();
435 }
436
437 /// Flip half ATI1 block vertically.
438 void BlockATI1::flip2()
439 {
440         alpha.flip2();
441 }
442
443
444 /// Decode ATI2 block.
445 void BlockATI2::decodeBlock(ColorBlock * block) const
446 {
447         uint8 alpha_array[8];
448         uint8 index_array[16];
449         
450         x.evaluatePalette(alpha_array);
451         x.indices(index_array);
452         
453         for(uint i = 0; i < 16; i++) {
454                 Color32 & c = block->color(i);
455                 c.r = alpha_array[index_array[i]];
456         }
457
458         y.evaluatePalette(alpha_array);
459         y.indices(index_array);
460         
461         for(uint i = 0; i < 16; i++) {
462                 Color32 & c = block->color(i);
463                 c.g = alpha_array[index_array[i]];
464                 c.b = 0;
465                 c.a = 255;
466         }
467 }
468
469 /// Flip ATI2 block vertically.
470 void BlockATI2::flip4()
471 {
472         x.flip4();
473         y.flip4();
474 }
475
476 /// Flip half ATI2 block vertically.
477 void BlockATI2::flip2()
478 {
479         x.flip2();
480         y.flip2();
481 }
482
483
484 void BlockCTX1::evaluatePalette(Color32 color_array[4]) const
485 {
486         // Does bit expansion before interpolation.
487         color_array[0].b = 0x00;
488         color_array[0].g = col0[1];
489         color_array[0].r = col0[0];
490         color_array[0].a = 0xFF;
491         
492         color_array[1].r = 0x00;
493         color_array[1].g = col0[1];
494         color_array[1].b = col1[0];
495         color_array[1].a = 0xFF;
496         
497         color_array[2].r = 0x00;
498         color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3;
499         color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3;
500         color_array[2].a = 0xFF;
501                 
502         color_array[3].r = 0x00;
503         color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3;
504         color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3;
505         color_array[3].a = 0xFF;
506 }
507
508 void BlockCTX1::decodeBlock(ColorBlock * block) const
509 {
510         // Decode color block.
511         Color32 color_array[4];
512         evaluatePalette(color_array);
513         
514         // Write color block.
515         for( uint j = 0; j < 4; j++ ) {
516                 for( uint i = 0; i < 4; i++ ) {
517                         uint idx = (row[j] >> (2 * i)) & 3;
518                         block->color(i, j) = color_array[idx];
519                 }
520         }       
521 }
522
523 void BlockCTX1::setIndices(int * idx)
524 {
525         indices = 0;
526         for(uint i = 0; i < 16; i++) {
527                 indices |= (idx[i] & 3) << (2 * i);
528         }
529 }
530
531
532 /// Flip CTX1 block vertically.
533 inline void BlockCTX1::flip4()
534 {
535         swap(row[0], row[3]);
536         swap(row[1], row[2]);
537 }
538
539 /// Flip half CTX1 block vertically.
540 inline void BlockCTX1::flip2()
541 {
542         swap(row[0], row[1]);
543 }
544
545 void mem_read(Stream & mem, BlockDXT1 & block)
546 {
547         mem_read(mem, block.col0.u);
548         mem_read(mem, block.col1.u);
549         mem_read(mem, block.indices);
550 }
551
552 void mem_read(Stream & mem, AlphaBlockDXT3 & block)
553 {
554         for (unsigned int i = 0; i < 4; i++) mem_read(mem, block.row[i]);
555 }
556
557 void mem_read(Stream & mem, BlockDXT3 & block)
558 {
559         mem_read(mem, block.alpha);
560         mem_read(mem, block.color);
561 }
562
563 void mem_read(Stream & mem, AlphaBlockDXT5 & block)
564 {
565         mem_read(mem, block.u);
566 }
567
568 void mem_read(Stream & mem, BlockDXT5 & block)
569 {
570         mem_read(mem, block.alpha);
571         mem_read(mem, block.color);
572 }
573
574 void mem_read(Stream & mem, BlockATI1 & block)
575 {
576         mem_read(mem, block.alpha);
577 }
578
579 void mem_read(Stream & mem, BlockATI2 & block)
580 {
581         mem_read(mem, block.x);
582         mem_read(mem, block.y);
583 }
584
585 void mem_read(Stream & mem, BlockCTX1 & block)
586 {
587         mem_read(mem, block.col0[0]);
588         mem_read(mem, block.col0[1]);
589         mem_read(mem, block.col1[0]);
590         mem_read(mem, block.col1[1]);
591         mem_read(mem, block.indices);
592 }
593