[MESA]
[reactos.git] / reactos / dll / opengl / mesa / src / mesa / swrast / s_texcombine.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.5
4 *
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
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 #include "main/glheader.h"
28 #include "main/context.h"
29 #include "main/colormac.h"
30 #include "main/imports.h"
31 #include "main/pixeltransfer.h"
32 #include "program/prog_instruction.h"
33
34 #include "s_context.h"
35 #include "s_texcombine.h"
36
37
38 /**
39 * Pointer to array of float[4]
40 * This type makes the code below more concise and avoids a lot of casting.
41 */
42 typedef float (*float4_array)[4];
43
44
45 /**
46 * Return array of texels for given unit.
47 */
48 static inline float4_array
49 get_texel_array(SWcontext *swrast, GLuint unit)
50 {
51 #ifdef _OPENMP
52 return (float4_array) (swrast->TexelBuffer + unit * MAX_WIDTH * 4 * omp_get_num_threads() + (MAX_WIDTH * 4 * omp_get_thread_num()));
53 #else
54 return (float4_array) (swrast->TexelBuffer + unit * MAX_WIDTH * 4);
55 #endif
56 }
57
58
59
60 /**
61 * Do texture application for:
62 * GL_EXT_texture_env_combine
63 * GL_ARB_texture_env_combine
64 * GL_EXT_texture_env_dot3
65 * GL_ARB_texture_env_dot3
66 * GL_ATI_texture_env_combine3
67 * GL_NV_texture_env_combine4
68 * conventional GL texture env modes
69 *
70 * \param ctx rendering context
71 * \param unit the texture combiner unit
72 * \param primary_rgba incoming fragment color array
73 * \param texelBuffer pointer to texel colors for all texture units
74 *
75 * \param span two fields are used in this function:
76 * span->end: number of fragments to process
77 * span->array->rgba: incoming/result fragment colors
78 */
79 static void
80 texture_combine( struct gl_context *ctx, GLuint unit,
81 const float4_array primary_rgba,
82 const GLfloat *texelBuffer,
83 SWspan *span )
84 {
85 SWcontext *swrast = SWRAST_CONTEXT(ctx);
86 const struct gl_texture_unit *textureUnit = &(ctx->Texture.Unit[unit]);
87 const struct gl_tex_env_combine_state *combine = textureUnit->_CurrentCombine;
88 float4_array argRGB[MAX_COMBINER_TERMS];
89 float4_array argA[MAX_COMBINER_TERMS];
90 const GLfloat scaleRGB = (GLfloat) (1 << combine->ScaleShiftRGB);
91 const GLfloat scaleA = (GLfloat) (1 << combine->ScaleShiftA);
92 const GLuint numArgsRGB = combine->_NumArgsRGB;
93 const GLuint numArgsA = combine->_NumArgsA;
94 float4_array ccolor[4], rgba;
95 GLuint i, term;
96 GLuint n = span->end;
97 GLchan (*rgbaChan)[4] = span->array->rgba;
98
99 /* alloc temp pixel buffers */
100 rgba = (float4_array) malloc(4 * n * sizeof(GLfloat));
101 if (!rgba) {
102 _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
103 return;
104 }
105
106 for (i = 0; i < numArgsRGB || i < numArgsA; i++) {
107 ccolor[i] = (float4_array) malloc(4 * n * sizeof(GLfloat));
108 if (!ccolor[i]) {
109 while (i) {
110 free(ccolor[i]);
111 i--;
112 }
113 _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
114 free(rgba);
115 return;
116 }
117 }
118
119 for (i = 0; i < n; i++) {
120 rgba[i][RCOMP] = CHAN_TO_FLOAT(rgbaChan[i][RCOMP]);
121 rgba[i][GCOMP] = CHAN_TO_FLOAT(rgbaChan[i][GCOMP]);
122 rgba[i][BCOMP] = CHAN_TO_FLOAT(rgbaChan[i][BCOMP]);
123 rgba[i][ACOMP] = CHAN_TO_FLOAT(rgbaChan[i][ACOMP]);
124 }
125
126 /*
127 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
128 combine->ModeRGB,
129 combine->ModeA,
130 combine->SourceRGB[0],
131 combine->SourceA[0],
132 combine->SourceRGB[1],
133 combine->SourceA[1]);
134 */
135
136 /*
137 * Do operand setup for up to 4 operands. Loop over the terms.
138 */
139 for (term = 0; term < numArgsRGB; term++) {
140 const GLenum srcRGB = combine->SourceRGB[term];
141 const GLenum operandRGB = combine->OperandRGB[term];
142
143 switch (srcRGB) {
144 case GL_TEXTURE:
145 argRGB[term] = get_texel_array(swrast, unit);
146 break;
147 case GL_PRIMARY_COLOR:
148 argRGB[term] = primary_rgba;
149 break;
150 case GL_PREVIOUS:
151 argRGB[term] = rgba;
152 break;
153 case GL_CONSTANT:
154 {
155 float4_array c = ccolor[term];
156 GLfloat red = textureUnit->EnvColor[0];
157 GLfloat green = textureUnit->EnvColor[1];
158 GLfloat blue = textureUnit->EnvColor[2];
159 GLfloat alpha = textureUnit->EnvColor[3];
160 for (i = 0; i < n; i++) {
161 ASSIGN_4V(c[i], red, green, blue, alpha);
162 }
163 argRGB[term] = ccolor[term];
164 }
165 break;
166 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
167 */
168 case GL_ZERO:
169 {
170 float4_array c = ccolor[term];
171 for (i = 0; i < n; i++) {
172 ASSIGN_4V(c[i], 0.0F, 0.0F, 0.0F, 0.0F);
173 }
174 argRGB[term] = ccolor[term];
175 }
176 break;
177 case GL_ONE:
178 {
179 float4_array c = ccolor[term];
180 for (i = 0; i < n; i++) {
181 ASSIGN_4V(c[i], 1.0F, 1.0F, 1.0F, 1.0F);
182 }
183 argRGB[term] = ccolor[term];
184 }
185 break;
186 default:
187 /* ARB_texture_env_crossbar source */
188 {
189 const GLuint srcUnit = srcRGB - GL_TEXTURE0;
190 ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
191 if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
192 goto end;
193 argRGB[term] = get_texel_array(swrast, srcUnit);
194 }
195 }
196
197 if (operandRGB != GL_SRC_COLOR) {
198 float4_array src = argRGB[term];
199 float4_array dst = ccolor[term];
200
201 /* point to new arg[term] storage */
202 argRGB[term] = ccolor[term];
203
204 switch (operandRGB) {
205 case GL_ONE_MINUS_SRC_COLOR:
206 for (i = 0; i < n; i++) {
207 dst[i][RCOMP] = 1.0F - src[i][RCOMP];
208 dst[i][GCOMP] = 1.0F - src[i][GCOMP];
209 dst[i][BCOMP] = 1.0F - src[i][BCOMP];
210 }
211 break;
212 case GL_SRC_ALPHA:
213 for (i = 0; i < n; i++) {
214 dst[i][RCOMP] =
215 dst[i][GCOMP] =
216 dst[i][BCOMP] = src[i][ACOMP];
217 }
218 break;
219 case GL_ONE_MINUS_SRC_ALPHA:
220 for (i = 0; i < n; i++) {
221 dst[i][RCOMP] =
222 dst[i][GCOMP] =
223 dst[i][BCOMP] = 1.0F - src[i][ACOMP];
224 }
225 break;
226 default:
227 _mesa_problem(ctx, "Bad operandRGB");
228 }
229 }
230 }
231
232 /*
233 * Set up the argA[term] pointers
234 */
235 for (term = 0; term < numArgsA; term++) {
236 const GLenum srcA = combine->SourceA[term];
237 const GLenum operandA = combine->OperandA[term];
238
239 switch (srcA) {
240 case GL_TEXTURE:
241 argA[term] = get_texel_array(swrast, unit);
242 break;
243 case GL_PRIMARY_COLOR:
244 argA[term] = primary_rgba;
245 break;
246 case GL_PREVIOUS:
247 argA[term] = rgba;
248 break;
249 case GL_CONSTANT:
250 {
251 float4_array c = ccolor[term];
252 GLfloat alpha = textureUnit->EnvColor[3];
253 for (i = 0; i < n; i++)
254 c[i][ACOMP] = alpha;
255 argA[term] = ccolor[term];
256 }
257 break;
258 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
259 */
260 case GL_ZERO:
261 {
262 float4_array c = ccolor[term];
263 for (i = 0; i < n; i++)
264 c[i][ACOMP] = 0.0F;
265 argA[term] = ccolor[term];
266 }
267 break;
268 case GL_ONE:
269 {
270 float4_array c = ccolor[term];
271 for (i = 0; i < n; i++)
272 c[i][ACOMP] = 1.0F;
273 argA[term] = ccolor[term];
274 }
275 break;
276 default:
277 /* ARB_texture_env_crossbar source */
278 {
279 const GLuint srcUnit = srcA - GL_TEXTURE0;
280 ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
281 if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
282 goto end;
283 argA[term] = get_texel_array(swrast, srcUnit);
284 }
285 }
286
287 if (operandA == GL_ONE_MINUS_SRC_ALPHA) {
288 float4_array src = argA[term];
289 float4_array dst = ccolor[term];
290 argA[term] = ccolor[term];
291 for (i = 0; i < n; i++) {
292 dst[i][ACOMP] = 1.0F - src[i][ACOMP];
293 }
294 }
295 }
296
297 /* RGB channel combine */
298 {
299 float4_array arg0 = argRGB[0];
300 float4_array arg1 = argRGB[1];
301 float4_array arg2 = argRGB[2];
302 float4_array arg3 = argRGB[3];
303
304 switch (combine->ModeRGB) {
305 case GL_REPLACE:
306 for (i = 0; i < n; i++) {
307 rgba[i][RCOMP] = arg0[i][RCOMP] * scaleRGB;
308 rgba[i][GCOMP] = arg0[i][GCOMP] * scaleRGB;
309 rgba[i][BCOMP] = arg0[i][BCOMP] * scaleRGB;
310 }
311 break;
312 case GL_MODULATE:
313 for (i = 0; i < n; i++) {
314 rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * scaleRGB;
315 rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * scaleRGB;
316 rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * scaleRGB;
317 }
318 break;
319 case GL_ADD:
320 if (textureUnit->EnvMode == GL_COMBINE4_NV) {
321 /* (a * b) + (c * d) */
322 for (i = 0; i < n; i++) {
323 rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
324 arg2[i][RCOMP] * arg3[i][RCOMP]) * scaleRGB;
325 rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
326 arg2[i][GCOMP] * arg3[i][GCOMP]) * scaleRGB;
327 rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
328 arg2[i][BCOMP] * arg3[i][BCOMP]) * scaleRGB;
329 }
330 }
331 else {
332 /* 2-term addition */
333 for (i = 0; i < n; i++) {
334 rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * scaleRGB;
335 rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * scaleRGB;
336 rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * scaleRGB;
337 }
338 }
339 break;
340 case GL_ADD_SIGNED:
341 if (textureUnit->EnvMode == GL_COMBINE4_NV) {
342 /* (a * b) + (c * d) - 0.5 */
343 for (i = 0; i < n; i++) {
344 rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
345 arg2[i][RCOMP] * arg3[i][RCOMP] - 0.5F) * scaleRGB;
346 rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
347 arg2[i][GCOMP] * arg3[i][GCOMP] - 0.5F) * scaleRGB;
348 rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
349 arg2[i][BCOMP] * arg3[i][BCOMP] - 0.5F) * scaleRGB;
350 }
351 }
352 else {
353 for (i = 0; i < n; i++) {
354 rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5F) * scaleRGB;
355 rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5F) * scaleRGB;
356 rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5F) * scaleRGB;
357 }
358 }
359 break;
360 case GL_INTERPOLATE:
361 for (i = 0; i < n; i++) {
362 rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] +
363 arg1[i][RCOMP] * (1.0F - arg2[i][RCOMP])) * scaleRGB;
364 rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] +
365 arg1[i][GCOMP] * (1.0F - arg2[i][GCOMP])) * scaleRGB;
366 rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] +
367 arg1[i][BCOMP] * (1.0F - arg2[i][BCOMP])) * scaleRGB;
368 }
369 break;
370 case GL_SUBTRACT:
371 for (i = 0; i < n; i++) {
372 rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * scaleRGB;
373 rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * scaleRGB;
374 rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * scaleRGB;
375 }
376 break;
377 case GL_DOT3_RGB_EXT:
378 case GL_DOT3_RGBA_EXT:
379 /* Do not scale the result by 1 2 or 4 */
380 for (i = 0; i < n; i++) {
381 GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
382 (arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
383 (arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
384 * 4.0F;
385 dot = CLAMP(dot, 0.0F, 1.0F);
386 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
387 }
388 break;
389 case GL_DOT3_RGB:
390 case GL_DOT3_RGBA:
391 /* DO scale the result by 1 2 or 4 */
392 for (i = 0; i < n; i++) {
393 GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
394 (arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
395 (arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
396 * 4.0F * scaleRGB;
397 dot = CLAMP(dot, 0.0F, 1.0F);
398 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
399 }
400 break;
401 case GL_MODULATE_ADD_ATI:
402 for (i = 0; i < n; i++) {
403 rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
404 arg1[i][RCOMP]) * scaleRGB;
405 rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
406 arg1[i][GCOMP]) * scaleRGB;
407 rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
408 arg1[i][BCOMP]) * scaleRGB;
409 }
410 break;
411 case GL_MODULATE_SIGNED_ADD_ATI:
412 for (i = 0; i < n; i++) {
413 rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
414 arg1[i][RCOMP] - 0.5F) * scaleRGB;
415 rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
416 arg1[i][GCOMP] - 0.5F) * scaleRGB;
417 rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
418 arg1[i][BCOMP] - 0.5F) * scaleRGB;
419 }
420 break;
421 case GL_MODULATE_SUBTRACT_ATI:
422 for (i = 0; i < n; i++) {
423 rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) -
424 arg1[i][RCOMP]) * scaleRGB;
425 rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) -
426 arg1[i][GCOMP]) * scaleRGB;
427 rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) -
428 arg1[i][BCOMP]) * scaleRGB;
429 }
430 break;
431 case GL_BUMP_ENVMAP_ATI:
432 /* this produces a fixed rgba color, and the coord calc is done elsewhere */
433 for (i = 0; i < n; i++) {
434 /* rgba result is 0,0,0,1 */
435 rgba[i][RCOMP] = 0.0;
436 rgba[i][GCOMP] = 0.0;
437 rgba[i][BCOMP] = 0.0;
438 rgba[i][ACOMP] = 1.0;
439 }
440 goto end; /* no alpha processing */
441 default:
442 _mesa_problem(ctx, "invalid combine mode");
443 }
444 }
445
446 /* Alpha channel combine */
447 {
448 float4_array arg0 = argA[0];
449 float4_array arg1 = argA[1];
450 float4_array arg2 = argA[2];
451 float4_array arg3 = argA[3];
452
453 switch (combine->ModeA) {
454 case GL_REPLACE:
455 for (i = 0; i < n; i++) {
456 rgba[i][ACOMP] = arg0[i][ACOMP] * scaleA;
457 }
458 break;
459 case GL_MODULATE:
460 for (i = 0; i < n; i++) {
461 rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * scaleA;
462 }
463 break;
464 case GL_ADD:
465 if (textureUnit->EnvMode == GL_COMBINE4_NV) {
466 /* (a * b) + (c * d) */
467 for (i = 0; i < n; i++) {
468 rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
469 arg2[i][ACOMP] * arg3[i][ACOMP]) * scaleA;
470 }
471 }
472 else {
473 /* two-term add */
474 for (i = 0; i < n; i++) {
475 rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * scaleA;
476 }
477 }
478 break;
479 case GL_ADD_SIGNED:
480 if (textureUnit->EnvMode == GL_COMBINE4_NV) {
481 /* (a * b) + (c * d) - 0.5 */
482 for (i = 0; i < n; i++) {
483 rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
484 arg2[i][ACOMP] * arg3[i][ACOMP] -
485 0.5F) * scaleA;
486 }
487 }
488 else {
489 /* a + b - 0.5 */
490 for (i = 0; i < n; i++) {
491 rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * scaleA;
492 }
493 }
494 break;
495 case GL_INTERPOLATE:
496 for (i = 0; i < n; i++) {
497 rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] +
498 arg1[i][ACOMP] * (1.0F - arg2[i][ACOMP]))
499 * scaleA;
500 }
501 break;
502 case GL_SUBTRACT:
503 for (i = 0; i < n; i++) {
504 rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * scaleA;
505 }
506 break;
507 case GL_MODULATE_ADD_ATI:
508 for (i = 0; i < n; i++) {
509 rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
510 + arg1[i][ACOMP]) * scaleA;
511 }
512 break;
513 case GL_MODULATE_SIGNED_ADD_ATI:
514 for (i = 0; i < n; i++) {
515 rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) +
516 arg1[i][ACOMP] - 0.5F) * scaleA;
517 }
518 break;
519 case GL_MODULATE_SUBTRACT_ATI:
520 for (i = 0; i < n; i++) {
521 rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
522 - arg1[i][ACOMP]) * scaleA;
523 }
524 break;
525 default:
526 _mesa_problem(ctx, "invalid combine mode");
527 }
528 }
529
530 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
531 * This is kind of a kludge. It would have been better if the spec
532 * were written such that the GL_COMBINE_ALPHA value could be set to
533 * GL_DOT3.
534 */
535 if (combine->ModeRGB == GL_DOT3_RGBA_EXT ||
536 combine->ModeRGB == GL_DOT3_RGBA) {
537 for (i = 0; i < n; i++) {
538 rgba[i][ACOMP] = rgba[i][RCOMP];
539 }
540 }
541
542 for (i = 0; i < n; i++) {
543 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][RCOMP], rgba[i][RCOMP]);
544 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][GCOMP], rgba[i][GCOMP]);
545 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][BCOMP], rgba[i][BCOMP]);
546 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][ACOMP], rgba[i][ACOMP]);
547 }
548 /* The span->array->rgba values are of CHAN type so set
549 * span->array->ChanType field accordingly.
550 */
551 span->array->ChanType = CHAN_TYPE;
552
553 end:
554 for (i = 0; i < numArgsRGB || i < numArgsA; i++) {
555 free(ccolor[i]);
556 }
557 free(rgba);
558 }
559
560 /**
561 * Apply texture mapping to a span of fragments.
562 */
563 void
564 _swrast_texture_span( struct gl_context *ctx, SWspan *span )
565 {
566 SWcontext *swrast = SWRAST_CONTEXT(ctx);
567 float4_array primary_rgba;
568 GLuint unit;
569
570 if (!swrast->TexelBuffer) {
571 #ifdef _OPENMP
572 const GLint maxThreads = omp_get_max_threads();
573 #else
574 const GLint maxThreads = 1;
575 #endif
576
577 /* TexelBuffer is also global and normally shared by all SWspan
578 * instances; when running with multiple threads, create one per
579 * thread.
580 */
581 swrast->TexelBuffer =
582 (GLfloat *) MALLOC(ctx->Const.MaxTextureImageUnits * maxThreads *
583 MAX_WIDTH * 4 * sizeof(GLfloat));
584 if (!swrast->TexelBuffer) {
585 _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
586 return;
587 }
588 }
589
590 primary_rgba = (float4_array) malloc(span->end * 4 * sizeof(GLfloat));
591
592 if (!primary_rgba) {
593 _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_span");
594 return;
595 }
596
597 ASSERT(span->end <= MAX_WIDTH);
598
599 /*
600 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
601 */
602 if (swrast->_TextureCombinePrimary) {
603 GLuint i;
604 for (i = 0; i < span->end; i++) {
605 primary_rgba[i][RCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][RCOMP]);
606 primary_rgba[i][GCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][GCOMP]);
607 primary_rgba[i][BCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][BCOMP]);
608 primary_rgba[i][ACOMP] = CHAN_TO_FLOAT(span->array->rgba[i][ACOMP]);
609 }
610 }
611
612 /* First must sample all bump maps */
613 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
614 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
615
616 if (texUnit->_ReallyEnabled &&
617 texUnit->_CurrentCombine->ModeRGB == GL_BUMP_ENVMAP_ATI) {
618 const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
619 span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
620 float4_array targetcoords =
621 span->array->attribs[FRAG_ATTRIB_TEX0 +
622 ctx->Texture.Unit[unit].BumpTarget - GL_TEXTURE0];
623
624 const struct gl_texture_object *curObj = texUnit->_Current;
625 GLfloat *lambda = span->array->lambda[unit];
626 float4_array texels = get_texel_array(swrast, unit);
627 GLuint i;
628 GLfloat rotMatrix00 = ctx->Texture.Unit[unit].RotMatrix[0];
629 GLfloat rotMatrix01 = ctx->Texture.Unit[unit].RotMatrix[1];
630 GLfloat rotMatrix10 = ctx->Texture.Unit[unit].RotMatrix[2];
631 GLfloat rotMatrix11 = ctx->Texture.Unit[unit].RotMatrix[3];
632
633 /* adjust texture lod (lambda) */
634 if (span->arrayMask & SPAN_LAMBDA) {
635 if (texUnit->LodBias + curObj->Sampler.LodBias != 0.0F) {
636 /* apply LOD bias, but don't clamp yet */
637 const GLfloat bias = CLAMP(texUnit->LodBias + curObj->Sampler.LodBias,
638 -ctx->Const.MaxTextureLodBias,
639 ctx->Const.MaxTextureLodBias);
640 GLuint i;
641 for (i = 0; i < span->end; i++) {
642 lambda[i] += bias;
643 }
644 }
645
646 if (curObj->Sampler.MinLod != -1000.0 ||
647 curObj->Sampler.MaxLod != 1000.0) {
648 /* apply LOD clamping to lambda */
649 const GLfloat min = curObj->Sampler.MinLod;
650 const GLfloat max = curObj->Sampler.MaxLod;
651 GLuint i;
652 for (i = 0; i < span->end; i++) {
653 GLfloat l = lambda[i];
654 lambda[i] = CLAMP(l, min, max);
655 }
656 }
657 }
658
659 /* Sample the texture (span->end = number of fragments) */
660 swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
661 texcoords, lambda, texels );
662
663 /* manipulate the span values of the bump target
664 not sure this can work correctly even ignoring
665 the problem that channel is unsigned */
666 for (i = 0; i < span->end; i++) {
667 targetcoords[i][0] += (texels[i][0] * rotMatrix00 + texels[i][1] *
668 rotMatrix01) / targetcoords[i][3];
669 targetcoords[i][1] += (texels[i][0] * rotMatrix10 + texels[i][1] *
670 rotMatrix11) / targetcoords[i][3];
671 }
672 }
673 }
674
675 /*
676 * Must do all texture sampling before combining in order to
677 * accomodate GL_ARB_texture_env_crossbar.
678 */
679 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
680 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
681 if (texUnit->_ReallyEnabled &&
682 texUnit->_CurrentCombine->ModeRGB != GL_BUMP_ENVMAP_ATI) {
683 const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
684 span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
685 const struct gl_texture_object *curObj = texUnit->_Current;
686 GLfloat *lambda = span->array->lambda[unit];
687 float4_array texels = get_texel_array(swrast, unit);
688
689 /* adjust texture lod (lambda) */
690 if (span->arrayMask & SPAN_LAMBDA) {
691 if (texUnit->LodBias + curObj->Sampler.LodBias != 0.0F) {
692 /* apply LOD bias, but don't clamp yet */
693 const GLfloat bias = CLAMP(texUnit->LodBias + curObj->Sampler.LodBias,
694 -ctx->Const.MaxTextureLodBias,
695 ctx->Const.MaxTextureLodBias);
696 GLuint i;
697 for (i = 0; i < span->end; i++) {
698 lambda[i] += bias;
699 }
700 }
701
702 if (curObj->Sampler.MinLod != -1000.0 ||
703 curObj->Sampler.MaxLod != 1000.0) {
704 /* apply LOD clamping to lambda */
705 const GLfloat min = curObj->Sampler.MinLod;
706 const GLfloat max = curObj->Sampler.MaxLod;
707 GLuint i;
708 for (i = 0; i < span->end; i++) {
709 GLfloat l = lambda[i];
710 lambda[i] = CLAMP(l, min, max);
711 }
712 }
713 }
714 else if (curObj->Sampler.MaxAnisotropy > 1.0 &&
715 curObj->Sampler.MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
716 /* sample_lambda_2d_aniso is beeing used as texture_sample_func,
717 * it requires the current SWspan *span as an additional parameter.
718 * In order to keep the same function signature, the unused lambda
719 * parameter will be modified to actually contain the SWspan pointer.
720 * This is a Hack. To make it right, the texture_sample_func
721 * signature and all implementing functions need to be modified.
722 */
723 /* "hide" SWspan struct; cast to (GLfloat *) to suppress warning */
724 lambda = (GLfloat *)span;
725 }
726
727 /* Sample the texture (span->end = number of fragments) */
728 swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
729 texcoords, lambda, texels );
730 }
731 }
732
733 /*
734 * OK, now apply the texture (aka texture combine/blend).
735 * We modify the span->color.rgba values.
736 */
737 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
738 if (ctx->Texture.Unit[unit]._ReallyEnabled)
739 texture_combine(ctx, unit, primary_rgba, swrast->TexelBuffer, span);
740 }
741
742 free(primary_rgba);
743 }