Merge branch 'mesa_7_7_branch' of http://anongit.freedesktop.org/git/mesa/mesa into...
[mesa.git] / src / mesa / main / texfetch.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.7
4 *
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Copyright (c) 2009 VMware, Inc.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27 /**
28 * \file texfetch.c
29 *
30 * Texel fetch/store functions
31 *
32 * \author Gareth Hughes
33 */
34
35
36 #include "colormac.h"
37 #include "context.h"
38 #include "texcompress.h"
39 #include "texcompress_fxt1.h"
40 #include "texcompress_s3tc.h"
41 #include "texfetch.h"
42
43
44 /**
45 * Convert an 8-bit sRGB value from non-linear space to a
46 * linear RGB value in [0, 1].
47 * Implemented with a 256-entry lookup table.
48 */
49 static INLINE GLfloat
50 nonlinear_to_linear(GLubyte cs8)
51 {
52 static GLfloat table[256];
53 static GLboolean tableReady = GL_FALSE;
54 if (!tableReady) {
55 /* compute lookup table now */
56 GLuint i;
57 for (i = 0; i < 256; i++) {
58 const GLfloat cs = UBYTE_TO_FLOAT(i);
59 if (cs <= 0.04045) {
60 table[i] = cs / 12.92f;
61 }
62 else {
63 table[i] = (GLfloat) _mesa_pow((cs + 0.055) / 1.055, 2.4);
64 }
65 }
66 tableReady = GL_TRUE;
67 }
68 return table[cs8];
69 }
70
71
72
73 /* Texel fetch routines for all supported formats
74 */
75 #define DIM 1
76 #include "texfetch_tmp.h"
77
78 #define DIM 2
79 #include "texfetch_tmp.h"
80
81 #define DIM 3
82 #include "texfetch_tmp.h"
83
84 /**
85 * Null texel fetch function.
86 *
87 * Have to have this so the FetchTexel function pointer is never NULL.
88 */
89 static void fetch_null_texelf( const struct gl_texture_image *texImage,
90 GLint i, GLint j, GLint k, GLfloat *texel )
91 {
92 (void) texImage; (void) i; (void) j; (void) k;
93 texel[RCOMP] = 0.0;
94 texel[GCOMP] = 0.0;
95 texel[BCOMP] = 0.0;
96 texel[ACOMP] = 0.0;
97 _mesa_warning(NULL, "fetch_null_texelf() called!");
98 }
99
100 static void store_null_texel(struct gl_texture_image *texImage,
101 GLint i, GLint j, GLint k, const void *texel)
102 {
103 (void) texImage;
104 (void) i;
105 (void) j;
106 (void) k;
107 (void) texel;
108 /* no-op */
109 }
110
111
112
113 /**
114 * Table to map MESA_FORMAT_ to texel fetch/store funcs.
115 * XXX this is somewhat temporary.
116 */
117 static struct {
118 GLuint Name;
119 FetchTexelFuncF Fetch1D;
120 FetchTexelFuncF Fetch2D;
121 FetchTexelFuncF Fetch3D;
122 StoreTexelFunc StoreTexel;
123 }
124 texfetch_funcs[MESA_FORMAT_COUNT] =
125 {
126 {
127 MESA_FORMAT_SRGB8,
128 fetch_texel_1d_srgb8,
129 fetch_texel_2d_srgb8,
130 fetch_texel_3d_srgb8,
131 store_texel_srgb8
132 },
133 {
134 MESA_FORMAT_SRGBA8,
135 fetch_texel_1d_srgba8,
136 fetch_texel_2d_srgba8,
137 fetch_texel_3d_srgba8,
138 store_texel_srgba8
139 },
140 {
141 MESA_FORMAT_SARGB8,
142 fetch_texel_1d_sargb8,
143 fetch_texel_2d_sargb8,
144 fetch_texel_3d_sargb8,
145 store_texel_sargb8
146 },
147 {
148 MESA_FORMAT_SL8,
149 fetch_texel_1d_sl8,
150 fetch_texel_2d_sl8,
151 fetch_texel_3d_sl8,
152 store_texel_sl8
153 },
154 {
155 MESA_FORMAT_SLA8,
156 fetch_texel_1d_sla8,
157 fetch_texel_2d_sla8,
158 fetch_texel_3d_sla8,
159 store_texel_sla8
160 },
161 {
162 MESA_FORMAT_RGB_FXT1,
163 NULL,
164 _mesa_fetch_texel_2d_f_rgb_fxt1,
165 NULL,
166 NULL
167 },
168 {
169 MESA_FORMAT_RGBA_FXT1,
170 NULL,
171 _mesa_fetch_texel_2d_f_rgba_fxt1,
172 NULL,
173 NULL
174 },
175 {
176 MESA_FORMAT_RGB_DXT1,
177 NULL,
178 _mesa_fetch_texel_2d_f_rgb_dxt1,
179 NULL,
180 NULL
181 },
182 {
183 MESA_FORMAT_RGBA_DXT1,
184 NULL,
185 _mesa_fetch_texel_2d_f_rgba_dxt1,
186 NULL,
187 NULL
188 },
189 {
190 MESA_FORMAT_RGBA_DXT3,
191 NULL,
192 _mesa_fetch_texel_2d_f_rgba_dxt3,
193 NULL,
194 NULL
195 },
196 {
197 MESA_FORMAT_RGBA_DXT5,
198 NULL,
199 _mesa_fetch_texel_2d_f_rgba_dxt5,
200 NULL,
201 NULL
202 },
203 {
204 MESA_FORMAT_SRGB_DXT1,
205 NULL,
206 _mesa_fetch_texel_2d_f_srgb_dxt1,
207 NULL,
208 NULL
209 },
210 {
211 MESA_FORMAT_SRGBA_DXT1,
212 NULL,
213 _mesa_fetch_texel_2d_f_srgba_dxt1,
214 NULL,
215 NULL
216 },
217 {
218 MESA_FORMAT_SRGBA_DXT3,
219 NULL,
220 _mesa_fetch_texel_2d_f_srgba_dxt3,
221 NULL,
222 NULL
223 },
224 {
225 MESA_FORMAT_SRGBA_DXT5,
226 NULL,
227 _mesa_fetch_texel_2d_f_srgba_dxt5,
228 NULL,
229 NULL
230 },
231 {
232 MESA_FORMAT_RGBA_FLOAT32,
233 fetch_texel_1d_f_rgba_f32,
234 fetch_texel_2d_f_rgba_f32,
235 fetch_texel_3d_f_rgba_f32,
236 store_texel_rgba_f32
237 },
238 {
239 MESA_FORMAT_RGBA_FLOAT16,
240 fetch_texel_1d_f_rgba_f16,
241 fetch_texel_2d_f_rgba_f16,
242 fetch_texel_3d_f_rgba_f16,
243 store_texel_rgba_f16
244 },
245 {
246 MESA_FORMAT_RGB_FLOAT32,
247 fetch_texel_1d_f_rgb_f32,
248 fetch_texel_2d_f_rgb_f32,
249 fetch_texel_3d_f_rgb_f32,
250 store_texel_rgb_f32
251 },
252 {
253 MESA_FORMAT_RGB_FLOAT16,
254 fetch_texel_1d_f_rgb_f16,
255 fetch_texel_2d_f_rgb_f16,
256 fetch_texel_3d_f_rgb_f16,
257 store_texel_rgb_f16
258 },
259 {
260 MESA_FORMAT_ALPHA_FLOAT32,
261 fetch_texel_1d_f_alpha_f32,
262 fetch_texel_2d_f_alpha_f32,
263 fetch_texel_3d_f_alpha_f32,
264 store_texel_alpha_f32
265 },
266 {
267 MESA_FORMAT_ALPHA_FLOAT16,
268 fetch_texel_1d_f_alpha_f16,
269 fetch_texel_2d_f_alpha_f16,
270 fetch_texel_3d_f_alpha_f16,
271 store_texel_alpha_f16
272 },
273 {
274 MESA_FORMAT_LUMINANCE_FLOAT32,
275 fetch_texel_1d_f_luminance_f32,
276 fetch_texel_2d_f_luminance_f32,
277 fetch_texel_3d_f_luminance_f32,
278 store_texel_luminance_f32
279 },
280 {
281 MESA_FORMAT_LUMINANCE_FLOAT16,
282 fetch_texel_1d_f_luminance_f16,
283 fetch_texel_2d_f_luminance_f16,
284 fetch_texel_3d_f_luminance_f16,
285 store_texel_luminance_f16
286 },
287 {
288 MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32,
289 fetch_texel_1d_f_luminance_alpha_f32,
290 fetch_texel_2d_f_luminance_alpha_f32,
291 fetch_texel_3d_f_luminance_alpha_f32,
292 store_texel_luminance_alpha_f32
293 },
294 {
295 MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16,
296 fetch_texel_1d_f_luminance_alpha_f16,
297 fetch_texel_2d_f_luminance_alpha_f16,
298 fetch_texel_3d_f_luminance_alpha_f16,
299 store_texel_luminance_alpha_f16
300 },
301 {
302 MESA_FORMAT_INTENSITY_FLOAT32,
303 fetch_texel_1d_f_intensity_f32,
304 fetch_texel_2d_f_intensity_f32,
305 fetch_texel_3d_f_intensity_f32,
306 store_texel_intensity_f32
307 },
308 {
309 MESA_FORMAT_INTENSITY_FLOAT16,
310 fetch_texel_1d_f_intensity_f16,
311 fetch_texel_2d_f_intensity_f16,
312 fetch_texel_3d_f_intensity_f16,
313 store_texel_intensity_f16
314 },
315 {
316 MESA_FORMAT_DUDV8,
317 fetch_texel_1d_dudv8,
318 fetch_texel_2d_dudv8,
319 fetch_texel_3d_dudv8,
320 NULL
321 },
322 {
323 MESA_FORMAT_SIGNED_RGBA8888,
324 fetch_texel_1d_signed_rgba8888,
325 fetch_texel_2d_signed_rgba8888,
326 fetch_texel_3d_signed_rgba8888,
327 store_texel_signed_rgba8888
328 },
329 {
330 MESA_FORMAT_SIGNED_RGBA8888_REV,
331 fetch_texel_1d_signed_rgba8888_rev,
332 fetch_texel_2d_signed_rgba8888_rev,
333 fetch_texel_3d_signed_rgba8888_rev,
334 store_texel_signed_rgba8888_rev
335 },
336 {
337 MESA_FORMAT_SIGNED_RGBA_16,
338 NULL, /* XXX to do */
339 NULL,
340 NULL,
341 NULL
342 },
343 {
344 MESA_FORMAT_RGBA8888,
345 fetch_texel_1d_f_rgba8888,
346 fetch_texel_2d_f_rgba8888,
347 fetch_texel_3d_f_rgba8888,
348 store_texel_rgba8888
349 },
350 {
351 MESA_FORMAT_RGBA8888_REV,
352 fetch_texel_1d_f_rgba8888_rev,
353 fetch_texel_2d_f_rgba8888_rev,
354 fetch_texel_3d_f_rgba8888_rev,
355 store_texel_rgba8888_rev
356 },
357 {
358 MESA_FORMAT_ARGB8888,
359 fetch_texel_1d_f_argb8888,
360 fetch_texel_2d_f_argb8888,
361 fetch_texel_3d_f_argb8888,
362 store_texel_argb8888
363 },
364 {
365 MESA_FORMAT_ARGB8888_REV,
366 fetch_texel_1d_f_argb8888_rev,
367 fetch_texel_2d_f_argb8888_rev,
368 fetch_texel_3d_f_argb8888_rev,
369 store_texel_argb8888_rev
370 },
371 {
372 MESA_FORMAT_XRGB8888,
373 fetch_texel_1d_f_xrgb8888,
374 fetch_texel_2d_f_xrgb8888,
375 fetch_texel_3d_f_xrgb8888,
376 store_texel_xrgb8888
377 },
378 {
379 MESA_FORMAT_XRGB8888_REV,
380 fetch_texel_1d_f_xrgb8888_rev,
381 fetch_texel_2d_f_xrgb8888_rev,
382 fetch_texel_3d_f_xrgb8888_rev,
383 store_texel_xrgb8888_rev,
384 },
385 {
386 MESA_FORMAT_RGB888,
387 fetch_texel_1d_f_rgb888,
388 fetch_texel_2d_f_rgb888,
389 fetch_texel_3d_f_rgb888,
390 store_texel_rgb888
391 },
392 {
393 MESA_FORMAT_BGR888,
394 fetch_texel_1d_f_bgr888,
395 fetch_texel_2d_f_bgr888,
396 fetch_texel_3d_f_bgr888,
397 store_texel_bgr888
398 },
399 {
400 MESA_FORMAT_RGB565,
401 fetch_texel_1d_f_rgb565,
402 fetch_texel_2d_f_rgb565,
403 fetch_texel_3d_f_rgb565,
404 store_texel_rgb565
405 },
406 {
407 MESA_FORMAT_RGB565_REV,
408 fetch_texel_1d_f_rgb565_rev,
409 fetch_texel_2d_f_rgb565_rev,
410 fetch_texel_3d_f_rgb565_rev,
411 store_texel_rgb565_rev
412 },
413 {
414 MESA_FORMAT_ARGB4444,
415 fetch_texel_1d_f_argb4444,
416 fetch_texel_2d_f_argb4444,
417 fetch_texel_3d_f_argb4444,
418 store_texel_argb4444
419 },
420 {
421 MESA_FORMAT_ARGB4444_REV,
422 fetch_texel_1d_f_argb4444_rev,
423 fetch_texel_2d_f_argb4444_rev,
424 fetch_texel_3d_f_argb4444_rev,
425 store_texel_argb4444_rev
426 },
427 {
428 MESA_FORMAT_RGBA5551,
429 fetch_texel_1d_f_rgba5551,
430 fetch_texel_2d_f_rgba5551,
431 fetch_texel_3d_f_rgba5551,
432 store_texel_rgba5551
433 },
434 {
435 MESA_FORMAT_ARGB1555,
436 fetch_texel_1d_f_argb1555,
437 fetch_texel_2d_f_argb1555,
438 fetch_texel_3d_f_argb1555,
439 store_texel_argb1555
440 },
441 {
442 MESA_FORMAT_ARGB1555_REV,
443 fetch_texel_1d_f_argb1555_rev,
444 fetch_texel_2d_f_argb1555_rev,
445 fetch_texel_3d_f_argb1555_rev,
446 store_texel_argb1555_rev
447 },
448 {
449 MESA_FORMAT_AL88,
450 fetch_texel_1d_f_al88,
451 fetch_texel_2d_f_al88,
452 fetch_texel_3d_f_al88,
453 store_texel_al88
454 },
455 {
456 MESA_FORMAT_AL88_REV,
457 fetch_texel_1d_f_al88_rev,
458 fetch_texel_2d_f_al88_rev,
459 fetch_texel_3d_f_al88_rev,
460 store_texel_al88_rev
461 },
462 {
463 MESA_FORMAT_AL1616,
464 fetch_texel_1d_f_al1616,
465 fetch_texel_2d_f_al1616,
466 fetch_texel_3d_f_al1616,
467 store_texel_al1616
468 },
469 {
470 MESA_FORMAT_AL1616_REV,
471 fetch_texel_1d_f_al1616_rev,
472 fetch_texel_2d_f_al1616_rev,
473 fetch_texel_3d_f_al1616_rev,
474 store_texel_al1616_rev
475 },
476 {
477 MESA_FORMAT_RGB332,
478 fetch_texel_1d_f_rgb332,
479 fetch_texel_2d_f_rgb332,
480 fetch_texel_3d_f_rgb332,
481 store_texel_rgb332
482 },
483 {
484 MESA_FORMAT_A8,
485 fetch_texel_1d_f_a8,
486 fetch_texel_2d_f_a8,
487 fetch_texel_3d_f_a8,
488 store_texel_a8
489 },
490 {
491 MESA_FORMAT_L8,
492 fetch_texel_1d_f_l8,
493 fetch_texel_2d_f_l8,
494 fetch_texel_3d_f_l8,
495 store_texel_l8
496 },
497 {
498 MESA_FORMAT_I8,
499 fetch_texel_1d_f_i8,
500 fetch_texel_2d_f_i8,
501 fetch_texel_3d_f_i8,
502 store_texel_i8
503 },
504 {
505 MESA_FORMAT_CI8,
506 fetch_texel_1d_f_ci8,
507 fetch_texel_2d_f_ci8,
508 fetch_texel_3d_f_ci8,
509 store_texel_ci8
510 },
511 {
512 MESA_FORMAT_YCBCR,
513 fetch_texel_1d_f_ycbcr,
514 fetch_texel_2d_f_ycbcr,
515 fetch_texel_3d_f_ycbcr,
516 store_texel_ycbcr
517 },
518 {
519 MESA_FORMAT_YCBCR_REV,
520 fetch_texel_1d_f_ycbcr_rev,
521 fetch_texel_2d_f_ycbcr_rev,
522 fetch_texel_3d_f_ycbcr_rev,
523 store_texel_ycbcr_rev
524 },
525 {
526 MESA_FORMAT_Z24_S8,
527 fetch_texel_1d_f_z24_s8,
528 fetch_texel_2d_f_z24_s8,
529 fetch_texel_3d_f_z24_s8,
530 store_texel_z24_s8
531 },
532 {
533 MESA_FORMAT_S8_Z24,
534 fetch_texel_1d_f_s8_z24,
535 fetch_texel_2d_f_s8_z24,
536 fetch_texel_3d_f_s8_z24,
537 store_texel_s8_z24
538 },
539 {
540 MESA_FORMAT_Z16,
541 fetch_texel_1d_f_z16,
542 fetch_texel_2d_f_z16,
543 fetch_texel_3d_f_z16,
544 store_texel_z16
545 },
546 {
547 MESA_FORMAT_X8_Z24,
548 fetch_texel_1d_f_s8_z24,
549 fetch_texel_2d_f_s8_z24,
550 fetch_texel_3d_f_s8_z24,
551 store_texel_s8_z24
552 },
553 {
554 MESA_FORMAT_Z24_X8,
555 fetch_texel_1d_f_z24_s8,
556 fetch_texel_2d_f_z24_s8,
557 fetch_texel_3d_f_z24_s8,
558 store_texel_z24_s8
559 },
560 {
561 MESA_FORMAT_Z32,
562 fetch_texel_1d_f_z32,
563 fetch_texel_2d_f_z32,
564 fetch_texel_3d_f_z32,
565 store_texel_z32
566 }
567 };
568
569
570 static FetchTexelFuncF
571 _mesa_get_texel_fetch_func(gl_format format, GLuint dims)
572 {
573 FetchTexelFuncF f = NULL;
574 GLuint i;
575 /* XXX replace loop with direct table lookup */
576 for (i = 0; i < MESA_FORMAT_COUNT; i++) {
577 if (texfetch_funcs[i].Name == format) {
578 switch (dims) {
579 case 1:
580 f = texfetch_funcs[i].Fetch1D;
581 break;
582 case 2:
583 f = texfetch_funcs[i].Fetch2D;
584 break;
585 case 3:
586 f = texfetch_funcs[i].Fetch3D;
587 break;
588 }
589 if (!f)
590 f = fetch_null_texelf;
591 return f;
592 }
593 }
594 return NULL;
595 }
596
597
598 StoreTexelFunc
599 _mesa_get_texel_store_func(gl_format format)
600 {
601 GLuint i;
602 /* XXX replace loop with direct table lookup */
603 for (i = 0; i < MESA_FORMAT_COUNT; i++) {
604 if (texfetch_funcs[i].Name == format) {
605 if (texfetch_funcs[i].StoreTexel)
606 return texfetch_funcs[i].StoreTexel;
607 else
608 return store_null_texel;
609 }
610 }
611 return NULL;
612 }
613
614
615
616 /**
617 * Adaptor for fetching a GLchan texel from a float-valued texture.
618 */
619 static void
620 fetch_texel_float_to_chan(const struct gl_texture_image *texImage,
621 GLint i, GLint j, GLint k, GLchan *texelOut)
622 {
623 GLfloat temp[4];
624 GLenum baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
625
626 ASSERT(texImage->FetchTexelf);
627 texImage->FetchTexelf(texImage, i, j, k, temp);
628 if (baseFormat == GL_DEPTH_COMPONENT ||
629 baseFormat == GL_DEPTH_STENCIL_EXT) {
630 /* just one channel */
631 UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
632 }
633 else {
634 /* four channels */
635 UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
636 UNCLAMPED_FLOAT_TO_CHAN(texelOut[1], temp[1]);
637 UNCLAMPED_FLOAT_TO_CHAN(texelOut[2], temp[2]);
638 UNCLAMPED_FLOAT_TO_CHAN(texelOut[3], temp[3]);
639 }
640 }
641
642
643 #if 0
644 /**
645 * Adaptor for fetching a float texel from a GLchan-valued texture.
646 */
647 static void
648 fetch_texel_chan_to_float(const struct gl_texture_image *texImage,
649 GLint i, GLint j, GLint k, GLfloat *texelOut)
650 {
651 GLchan temp[4];
652 GLenum baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
653
654 ASSERT(texImage->FetchTexelc);
655 texImage->FetchTexelc(texImage, i, j, k, temp);
656 if (baseFormat == GL_DEPTH_COMPONENT ||
657 baseFormat == GL_DEPTH_STENCIL_EXT) {
658 /* just one channel */
659 texelOut[0] = CHAN_TO_FLOAT(temp[0]);
660 }
661 else {
662 /* four channels */
663 texelOut[0] = CHAN_TO_FLOAT(temp[0]);
664 texelOut[1] = CHAN_TO_FLOAT(temp[1]);
665 texelOut[2] = CHAN_TO_FLOAT(temp[2]);
666 texelOut[3] = CHAN_TO_FLOAT(temp[3]);
667 }
668 }
669 #endif
670
671
672 /**
673 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
674 */
675 void
676 _mesa_set_fetch_functions(struct gl_texture_image *texImage, GLuint dims)
677 {
678 ASSERT(dims == 1 || dims == 2 || dims == 3);
679 ASSERT(texImage->TexFormat);
680
681 if (!texImage->FetchTexelf) {
682 texImage->FetchTexelf =
683 _mesa_get_texel_fetch_func(texImage->TexFormat, dims);
684 }
685
686 /* now check if we need to use a float/chan adaptor */
687 if (!texImage->FetchTexelc) {
688 texImage->FetchTexelc = fetch_texel_float_to_chan;
689 }
690
691 ASSERT(texImage->FetchTexelc);
692 ASSERT(texImage->FetchTexelf);
693 }