Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3770 Serge 1
/*
2
 * Copyright (C) 2011 Red Hat Inc.
3
 *
4
 * block compression parts are:
5
 * Copyright (C) 2004  Roland Scheidegger   All Rights Reserved.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * copy of this software and associated documentation files (the "Software"),
9
 * to deal in the Software without restriction, including without limitation
10
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
 * and/or sell copies of the Software, and to permit persons to whom the
12
 * Software is furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice (including the next
15
 * paragraph) shall be included in all copies or substantial portions of the
16
 * Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24
 * DEALINGS IN THE SOFTWARE.
25
 *
26
 * Author:
27
 *    Dave Airlie
28
 */
29
 
30
/* included by texcompress_rgtc to define byte/ubyte compressors */
31
 
32
static void TAG(fetch_texel_rgtc)(unsigned srcRowStride, const TYPE *pixdata,
33
				  unsigned i, unsigned j, TYPE *value, unsigned comps)
34
{
35
   TYPE decode;
36
   const TYPE *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8 * comps);
37
   const TYPE alpha0 = blksrc[0];
38
   const TYPE alpha1 = blksrc[1];
39
   const char bit_pos = ((j&3) * 4 + (i&3)) * 3;
40
   const TYPE acodelow = blksrc[2 + bit_pos / 8];
41
   const TYPE acodehigh = (3 + bit_pos / 8) < 8 ? blksrc[3 + bit_pos / 8] : 0;
42
   const TYPE code = (acodelow >> (bit_pos & 0x7) |
43
      (acodehigh  << (8 - (bit_pos & 0x7)))) & 0x7;
44
 
45
   if (code == 0)
46
      decode = alpha0;
47
   else if (code == 1)
48
      decode = alpha1;
49
   else if (alpha0 > alpha1)
50
      decode = ((alpha0 * (8 - code) + (alpha1 * (code - 1))) / 7);
51
   else if (code < 6)
52
      decode = ((alpha0 * (6 - code) + (alpha1 * (code - 1))) / 5);
53
   else if (code == 6)
54
      decode = T_MIN;
55
   else
56
      decode = T_MAX;
57
 
58
   *value = decode;
59
}
60
 
61
static void TAG(write_rgtc_encoded_channel)(TYPE *blkaddr,
62
					    TYPE alphabase1,
63
					    TYPE alphabase2,
64
					    TYPE alphaenc[16])
65
{
66
   *blkaddr++ = alphabase1;
67
   *blkaddr++ = alphabase2;
68
   *blkaddr++ = alphaenc[0] | (alphaenc[1] << 3) | ((alphaenc[2] & 3) << 6);
69
   *blkaddr++ = (alphaenc[2] >> 2) | (alphaenc[3] << 1) | (alphaenc[4] << 4) | ((alphaenc[5] & 1) << 7);
70
   *blkaddr++ = (alphaenc[5] >> 1) | (alphaenc[6] << 2) | (alphaenc[7] << 5);
71
   *blkaddr++ = alphaenc[8] | (alphaenc[9] << 3) | ((alphaenc[10] & 3) << 6);
72
   *blkaddr++ = (alphaenc[10] >> 2) | (alphaenc[11] << 1) | (alphaenc[12] << 4) | ((alphaenc[13] & 1) << 7);
73
   *blkaddr++ = (alphaenc[13] >> 1) | (alphaenc[14] << 2) | (alphaenc[15] << 5);
74
}
75
 
76
static void TAG(encode_rgtc_ubyte)(TYPE *blkaddr, TYPE srccolors[4][4],
77
			     int numxpixels, int numypixels)
78
{
79
   TYPE alphabase[2], alphause[2];
80
   short alphatest[2] = { 0 };
81
   unsigned int alphablockerror1, alphablockerror2, alphablockerror3;
82
   TYPE i, j, aindex, acutValues[7];
83
   TYPE alphaenc1[16], alphaenc2[16], alphaenc3[16];
84
   int alphaabsmin = 0, alphaabsmax = 0;
85
   short alphadist;
86
 
87
   /* find lowest and highest alpha value in block, alphabase[0] lowest, alphabase[1] highest */
88
   alphabase[0] = T_MAX; alphabase[1] = T_MIN;
89
   for (j = 0; j < numypixels; j++) {
90
      for (i = 0; i < numxpixels; i++) {
91
	 if (srccolors[j][i] == T_MIN)
92
            alphaabsmin = 1;
93
         else if (srccolors[j][i] == T_MAX)
94
            alphaabsmax = 1;
95
         else {
96
            if (srccolors[j][i] > alphabase[1])
97
               alphabase[1] = srccolors[j][i];
98
            if (srccolors[j][i] < alphabase[0])
99
               alphabase[0] = srccolors[j][i];
100
         }
101
      }
102
   }
103
 
104
 
105
   if (((alphabase[0] > alphabase[1]) && !(alphaabsmin && alphaabsmax))
106
       || (alphabase[0] == alphabase[1] && !alphaabsmin && !alphaabsmax)) { /* one color, either max or min */
107
      /* shortcut here since it is a very common case (and also avoids later problems) */
108
      /* could also thest for alpha0 == alpha1 (and not min/max), but probably not common, so don't bother */
109
 
110
      *blkaddr++ = srccolors[0][0];
111
      blkaddr++;
112
      *blkaddr++ = 0;
113
      *blkaddr++ = 0;
114
      *blkaddr++ = 0;
115
      *blkaddr++ = 0;
116
      *blkaddr++ = 0;
117
      *blkaddr++ = 0;
118
#if RGTC_DEBUG
119
      fprintf(stderr, "enc0 used\n");
120
#endif
121
      return;
122
   }
123
 
124
   /* find best encoding for alpha0 > alpha1 */
125
   /* it's possible this encoding is better even if both alphaabsmin and alphaabsmax are true */
126
   alphablockerror1 = 0x0;
127
   alphablockerror2 = 0xffffffff;
128
   alphablockerror3 = 0xffffffff;
129
   if (alphaabsmin) alphause[0] = T_MIN;
130
   else alphause[0] = alphabase[0];
131
   if (alphaabsmax) alphause[1] = T_MAX;
132
   else alphause[1] = alphabase[1];
133
   /* calculate the 7 cut values, just the middle between 2 of the computed alpha values */
134
   for (aindex = 0; aindex < 7; aindex++) {
135
      /* don't forget here is always rounded down */
136
      acutValues[aindex] = (alphause[0] * (2*aindex + 1) + alphause[1] * (14 - (2*aindex + 1))) / 14;
137
   }
138
 
139
   for (j = 0; j < numypixels; j++) {
140
      for (i = 0; i < numxpixels; i++) {
141
         /* maybe it's overkill to have the most complicated calculation just for the error
142
            calculation which we only need to figure out if encoding1 or encoding2 is better... */
143
         if (srccolors[j][i] > acutValues[0]) {
144
            alphaenc1[4*j + i] = 0;
145
            alphadist = srccolors[j][i] - alphause[1];
146
         }
147
         else if (srccolors[j][i] > acutValues[1]) {
148
            alphaenc1[4*j + i] = 2;
149
            alphadist = srccolors[j][i] - (alphause[1] * 6 + alphause[0] * 1) / 7;
150
         }
151
         else if (srccolors[j][i] > acutValues[2]) {
152
            alphaenc1[4*j + i] = 3;
153
            alphadist = srccolors[j][i] - (alphause[1] * 5 + alphause[0] * 2) / 7;
154
         }
155
         else if (srccolors[j][i] > acutValues[3]) {
156
            alphaenc1[4*j + i] = 4;
157
            alphadist = srccolors[j][i] - (alphause[1] * 4 + alphause[0] * 3) / 7;
158
         }
159
         else if (srccolors[j][i] > acutValues[4]) {
160
            alphaenc1[4*j + i] = 5;
161
            alphadist = srccolors[j][i] - (alphause[1] * 3 + alphause[0] * 4) / 7;
162
         }
163
         else if (srccolors[j][i] > acutValues[5]) {
164
            alphaenc1[4*j + i] = 6;
165
            alphadist = srccolors[j][i] - (alphause[1] * 2 + alphause[0] * 5) / 7;
166
         }
167
         else if (srccolors[j][i] > acutValues[6]) {
168
            alphaenc1[4*j + i] = 7;
169
            alphadist = srccolors[j][i] - (alphause[1] * 1 + alphause[0] * 6) / 7;
170
         }
171
         else {
172
            alphaenc1[4*j + i] = 1;
173
            alphadist = srccolors[j][i] - alphause[0];
174
         }
175
         alphablockerror1 += alphadist * alphadist;
176
      }
177
   }
178
 
179
#if RGTC_DEBUG
180
   for (i = 0; i < 16; i++) {
181
      fprintf(stderr, "%d ", alphaenc1[i]);
182
   }
183
   fprintf(stderr, "cutVals ");
184
   for (i = 0; i < 7; i++) {
185
      fprintf(stderr, "%d ", acutValues[i]);
186
   }
187
   fprintf(stderr, "srcVals ");
188
   for (j = 0; j < numypixels; j++) {
189
      for (i = 0; i < numxpixels; i++) {
190
	 fprintf(stderr, "%d ", srccolors[j][i]);
191
      }
192
   }
193
   fprintf(stderr, "\n");
194
#endif
195
 
196
   /* it's not very likely this encoding is better if both alphaabsmin and alphaabsmax
197
      are false but try it anyway */
198
   if (alphablockerror1 >= 32) {
199
 
200
      /* don't bother if encoding is already very good, this condition should also imply
201
      we have valid alphabase colors which we absolutely need (alphabase[0] <= alphabase[1]) */
202
      alphablockerror2 = 0;
203
      for (aindex = 0; aindex < 5; aindex++) {
204
         /* don't forget here is always rounded down */
205
         acutValues[aindex] = (alphabase[0] * (10 - (2*aindex + 1)) + alphabase[1] * (2*aindex + 1)) / 10;
206
      }
207
      for (j = 0; j < numypixels; j++) {
208
         for (i = 0; i < numxpixels; i++) {
209
             /* maybe it's overkill to have the most complicated calculation just for the error
210
               calculation which we only need to figure out if encoding1 or encoding2 is better... */
211
            if (srccolors[j][i] == T_MIN) {
212
               alphaenc2[4*j + i] = 6;
213
               alphadist = 0;
214
            }
215
            else if (srccolors[j][i] == T_MAX) {
216
               alphaenc2[4*j + i] = 7;
217
               alphadist = 0;
218
            }
219
            else if (srccolors[j][i] <= acutValues[0]) {
220
               alphaenc2[4*j + i] = 0;
221
               alphadist = srccolors[j][i] - alphabase[0];
222
            }
223
            else if (srccolors[j][i] <= acutValues[1]) {
224
               alphaenc2[4*j + i] = 2;
225
               alphadist = srccolors[j][i] - (alphabase[0] * 4 + alphabase[1] * 1) / 5;
226
            }
227
            else if (srccolors[j][i] <= acutValues[2]) {
228
               alphaenc2[4*j + i] = 3;
229
               alphadist = srccolors[j][i] - (alphabase[0] * 3 + alphabase[1] * 2) / 5;
230
            }
231
            else if (srccolors[j][i] <= acutValues[3]) {
232
               alphaenc2[4*j + i] = 4;
233
               alphadist = srccolors[j][i] - (alphabase[0] * 2 + alphabase[1] * 3) / 5;
234
            }
235
            else if (srccolors[j][i] <= acutValues[4]) {
236
               alphaenc2[4*j + i] = 5;
237
               alphadist = srccolors[j][i] - (alphabase[0] * 1 + alphabase[1] * 4) / 5;
238
            }
239
            else {
240
               alphaenc2[4*j + i] = 1;
241
               alphadist = srccolors[j][i] - alphabase[1];
242
            }
243
            alphablockerror2 += alphadist * alphadist;
244
         }
245
      }
246
 
247
 
248
      /* skip this if the error is already very small
249
         this encoding is MUCH better on average than #2 though, but expensive! */
250
      if ((alphablockerror2 > 96) && (alphablockerror1 > 96)) {
251
         short blockerrlin1 = 0;
252
         short blockerrlin2 = 0;
253
         TYPE nralphainrangelow = 0;
254
         TYPE nralphainrangehigh = 0;
255
         alphatest[0] = T_MAX;
256
         alphatest[1] = T_MIN;
257
         /* if we have large range it's likely there are values close to 0/255, try to map them to 0/255 */
258
         for (j = 0; j < numypixels; j++) {
259
            for (i = 0; i < numxpixels; i++) {
260
               if ((srccolors[j][i] > alphatest[1]) && (srccolors[j][i] < (T_MAX -(alphabase[1] - alphabase[0]) / 28)))
261
                  alphatest[1] = srccolors[j][i];
262
               if ((srccolors[j][i] < alphatest[0]) && (srccolors[j][i] > (alphabase[1] - alphabase[0]) / 28))
263
                  alphatest[0] = srccolors[j][i];
264
            }
265
         }
266
          /* shouldn't happen too often, don't really care about those degenerated cases */
267
          if (alphatest[1] <= alphatest[0]) {
268
             alphatest[0] = T_MIN+1;
269
             alphatest[1] = T_MAX-1;
270
         }
271
         for (aindex = 0; aindex < 5; aindex++) {
272
         /* don't forget here is always rounded down */
273
            acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
274
         }
275
 
276
         /* find the "average" difference between the alpha values and the next encoded value.
277
            This is then used to calculate new base values.
278
            Should there be some weighting, i.e. those values closer to alphatest[x] have more weight,
279
            since they will see more improvement, and also because the values in the middle are somewhat
280
            likely to get no improvement at all (because the base values might move in different directions)?
281
            OTOH it would mean the values in the middle are even less likely to get an improvement
282
         */
283
         for (j = 0; j < numypixels; j++) {
284
            for (i = 0; i < numxpixels; i++) {
285
               if (srccolors[j][i] <= alphatest[0] / 2) {
286
               }
287
               else if (srccolors[j][i] > ((T_MAX + alphatest[1]) / 2)) {
288
               }
289
               else if (srccolors[j][i] <= acutValues[0]) {
290
                  blockerrlin1 += (srccolors[j][i] - alphatest[0]);
291
                  nralphainrangelow += 1;
292
               }
293
               else if (srccolors[j][i] <= acutValues[1]) {
294
                  blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
295
                  blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
296
                  nralphainrangelow += 1;
297
                  nralphainrangehigh += 1;
298
               }
299
               else if (srccolors[j][i] <= acutValues[2]) {
300
                  blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
301
                  blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
302
                  nralphainrangelow += 1;
303
                  nralphainrangehigh += 1;
304
               }
305
               else if (srccolors[j][i] <= acutValues[3]) {
306
                  blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
307
                  blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
308
                  nralphainrangelow += 1;
309
                  nralphainrangehigh += 1;
310
               }
311
               else if (srccolors[j][i] <= acutValues[4]) {
312
                  blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
313
                  blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
314
                  nralphainrangelow += 1;
315
                  nralphainrangehigh += 1;
316
                  }
317
               else {
318
                  blockerrlin2 += (srccolors[j][i] - alphatest[1]);
319
                  nralphainrangehigh += 1;
320
               }
321
            }
322
         }
323
         /* shouldn't happen often, needed to avoid div by zero */
324
         if (nralphainrangelow == 0) nralphainrangelow = 1;
325
         if (nralphainrangehigh == 0) nralphainrangehigh = 1;
326
         alphatest[0] = alphatest[0] + (blockerrlin1 / nralphainrangelow);
327
#if RGTC_DEBUG
328
         fprintf(stderr, "block err lin low %d, nr %d\n", blockerrlin1, nralphainrangelow);
329
         fprintf(stderr, "block err lin high %d, nr %d\n", blockerrlin2, nralphainrangehigh);
330
#endif
331
         /* again shouldn't really happen often... */
332
         if (alphatest[0] < T_MIN) {
333
            alphatest[0] = T_MIN;
334
         }
335
         alphatest[1] = alphatest[1] + (blockerrlin2 / nralphainrangehigh);
336
         if (alphatest[1] > T_MAX) {
337
            alphatest[1] = T_MAX;
338
         }
339
 
340
         alphablockerror3 = 0;
341
         for (aindex = 0; aindex < 5; aindex++) {
342
         /* don't forget here is always rounded down */
343
            acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
344
         }
345
         for (j = 0; j < numypixels; j++) {
346
            for (i = 0; i < numxpixels; i++) {
347
                /* maybe it's overkill to have the most complicated calculation just for the error
348
                  calculation which we only need to figure out if encoding1 or encoding2 is better... */
349
               if (srccolors[j][i] <= alphatest[0] / 2) {
350
                  alphaenc3[4*j + i] = 6;
351
                  alphadist = srccolors[j][i];
352
               }
353
               else if (srccolors[j][i] > ((T_MAX + alphatest[1]) / 2)) {
354
                  alphaenc3[4*j + i] = 7;
355
                  alphadist = T_MAX - srccolors[j][i];
356
               }
357
               else if (srccolors[j][i] <= acutValues[0]) {
358
                  alphaenc3[4*j + i] = 0;
359
                  alphadist = srccolors[j][i] - alphatest[0];
360
               }
361
               else if (srccolors[j][i] <= acutValues[1]) {
362
                 alphaenc3[4*j + i] = 2;
363
                 alphadist = srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5;
364
               }
365
               else if (srccolors[j][i] <= acutValues[2]) {
366
                  alphaenc3[4*j + i] = 3;
367
                  alphadist = srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5;
368
               }
369
               else if (srccolors[j][i] <= acutValues[3]) {
370
                  alphaenc3[4*j + i] = 4;
371
                  alphadist = srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5;
372
               }
373
               else if (srccolors[j][i] <= acutValues[4]) {
374
                  alphaenc3[4*j + i] = 5;
375
                  alphadist = srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5;
376
               }
377
               else {
378
                  alphaenc3[4*j + i] = 1;
379
                  alphadist = srccolors[j][i] - alphatest[1];
380
               }
381
               alphablockerror3 += alphadist * alphadist;
382
            }
383
         }
384
      }
385
   }
386
 
387
  /* write the alpha values and encoding back. */
388
   if ((alphablockerror1 <= alphablockerror2) && (alphablockerror1 <= alphablockerror3)) {
389
#if RGTC_DEBUG
390
      if (alphablockerror1 > 96) fprintf(stderr, "enc1 used, error %d\n", alphablockerror1);
391
      fprintf(stderr,"w1: min %d max %d au0 %d au1 %d\n",
392
	      T_MIN, T_MAX,
393
	      alphause[1], alphause[0]);
394
#endif
395
 
396
      TAG(write_rgtc_encoded_channel)( blkaddr, alphause[1], alphause[0], alphaenc1 );
397
   }
398
   else if (alphablockerror2 <= alphablockerror3) {
399
#if RGTC_DEBUG
400
      if (alphablockerror2 > 96) fprintf(stderr, "enc2 used, error %d\n", alphablockerror2);
401
      fprintf(stderr,"w2: min %d max %d au0 %d au1 %d\n",
402
	      T_MIN, T_MAX,
403
	      alphabase[0], alphabase[1]);
404
#endif
405
 
406
      TAG(write_rgtc_encoded_channel)( blkaddr, alphabase[0], alphabase[1], alphaenc2 );
407
   }
408
   else {
409
#if RGTC_DEBUG
410
      fprintf(stderr, "enc3 used, error %d\n", alphablockerror3);
411
      fprintf(stderr,"w3: min %d max %d au0 %d au1 %d\n",
412
	      T_MIN, T_MAX,
413
	      alphatest[0], alphatest[1]);
414
#endif
415
 
416
      TAG(write_rgtc_encoded_channel)( blkaddr, (TYPE)alphatest[0], (TYPE)alphatest[1], alphaenc3 );
417
   }
418
}