Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / swrast / s_atifragshader.c
1 /*
2  * Copyright (C) 2004  David Airlie   All Rights Reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * DAVID AIRLIE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20  */
21
22 #include "main/glheader.h"
23 #include "main/colormac.h"
24 #include "main/macros.h"
25 #include "main/atifragshader.h"
26 #include "swrast/s_atifragshader.h"
27 #include "swrast/s_context.h"
28
29
30 /**
31  * State for executing ATI fragment shader.
32  */
33 struct atifs_machine
34 {
35    GLfloat Registers[6][4];         /** six temporary registers */
36    GLfloat PrevPassRegisters[6][4];
37    GLfloat Inputs[2][4];   /** Primary, secondary input colors */
38 };
39
40
41
42 /**
43  * Fetch a texel.
44  */
45 static void
46 fetch_texel(struct gl_context * ctx, const GLfloat texcoord[4], GLfloat lambda,
47             GLuint unit, GLfloat color[4])
48 {
49    SWcontext *swrast = SWRAST_CONTEXT(ctx);
50
51    /* XXX use a float-valued TextureSample routine here!!! */
52    swrast->TextureSample[unit](ctx, ctx->Texture.Unit[unit]._Current,
53                                1, (const GLfloat(*)[4]) texcoord,
54                                &lambda, (GLfloat (*)[4]) color);
55 }
56
57 static void
58 apply_swizzle(GLfloat values[4], GLuint swizzle)
59 {
60    GLfloat s, t, r, q;
61
62    s = values[0];
63    t = values[1];
64    r = values[2];
65    q = values[3];
66
67    switch (swizzle) {
68    case GL_SWIZZLE_STR_ATI:
69       values[0] = s;
70       values[1] = t;
71       values[2] = r;
72       break;
73    case GL_SWIZZLE_STQ_ATI:
74       values[0] = s;
75       values[1] = t;
76       values[2] = q;
77       break;
78    case GL_SWIZZLE_STR_DR_ATI:
79       values[0] = s / r;
80       values[1] = t / r;
81       values[2] = 1 / r;
82       break;
83    case GL_SWIZZLE_STQ_DQ_ATI:
84 /* make sure q is not 0 to avoid problems later with infinite values (texture lookup)? */
85       if (q == 0.0F)
86          q = 0.000000001F;
87       values[0] = s / q;
88       values[1] = t / q;
89       values[2] = 1.0F / q;
90       break;
91    }
92    values[3] = 0.0;
93 }
94
95 static void
96 apply_src_rep(GLint optype, GLuint rep, GLfloat * val)
97 {
98    GLint i;
99    GLint start, end;
100    if (!rep)
101       return;
102
103    start = optype ? 3 : 0;
104    end = 4;
105
106    for (i = start; i < end; i++) {
107       switch (rep) {
108       case GL_RED:
109          val[i] = val[0];
110          break;
111       case GL_GREEN:
112          val[i] = val[1];
113          break;
114       case GL_BLUE:
115          val[i] = val[2];
116          break;
117       case GL_ALPHA:
118          val[i] = val[3];
119          break;
120       }
121    }
122 }
123
124 static void
125 apply_src_mod(GLint optype, GLuint mod, GLfloat * val)
126 {
127    GLint i;
128    GLint start, end;
129
130    if (!mod)
131       return;
132
133    start = optype ? 3 : 0;
134    end = 4;
135
136    for (i = start; i < end; i++) {
137       if (mod & GL_COMP_BIT_ATI)
138          val[i] = 1 - val[i];
139
140       if (mod & GL_BIAS_BIT_ATI)
141          val[i] = val[i] - 0.5F;
142
143       if (mod & GL_2X_BIT_ATI)
144          val[i] = 2 * val[i];
145
146       if (mod & GL_NEGATE_BIT_ATI)
147          val[i] = -val[i];
148    }
149 }
150
151 static void
152 apply_dst_mod(GLuint optype, GLuint mod, GLfloat * val)
153 {
154    GLint i;
155    GLint has_sat = mod & GL_SATURATE_BIT_ATI;
156    GLint start, end;
157
158    mod &= ~GL_SATURATE_BIT_ATI;
159
160    start = optype ? 3 : 0;
161    end = optype ? 4 : 3;
162
163    for (i = start; i < end; i++) {
164       switch (mod) {
165       case GL_2X_BIT_ATI:
166          val[i] = 2 * val[i];
167          break;
168       case GL_4X_BIT_ATI:
169          val[i] = 4 * val[i];
170          break;
171       case GL_8X_BIT_ATI:
172          val[i] = 8 * val[i];
173          break;
174       case GL_HALF_BIT_ATI:
175          val[i] = val[i] * 0.5F;
176          break;
177       case GL_QUARTER_BIT_ATI:
178          val[i] = val[i] * 0.25F;
179          break;
180       case GL_EIGHTH_BIT_ATI:
181          val[i] = val[i] * 0.125F;
182          break;
183       }
184
185       if (has_sat) {
186          if (val[i] < 0.0F)
187             val[i] = 0.0F;
188          else if (val[i] > 1.0F)
189             val[i] = 1.0F;
190       }
191       else {
192          if (val[i] < -8.0F)
193             val[i] = -8.0F;
194          else if (val[i] > 8.0F)
195             val[i] = 8.0F;
196       }
197    }
198 }
199
200
201 static void
202 write_dst_addr(GLuint optype, GLuint mod, GLuint mask, GLfloat * src,
203                GLfloat * dst)
204 {
205    GLint i;
206    apply_dst_mod(optype, mod, src);
207
208    if (optype == ATI_FRAGMENT_SHADER_COLOR_OP) {
209       if (mask) {
210          if (mask & GL_RED_BIT_ATI)
211             dst[0] = src[0];
212
213          if (mask & GL_GREEN_BIT_ATI)
214             dst[1] = src[1];
215
216          if (mask & GL_BLUE_BIT_ATI)
217             dst[2] = src[2];
218       }
219       else {
220          for (i = 0; i < 3; i++)
221             dst[i] = src[i];
222       }
223    }
224    else
225       dst[3] = src[3];
226 }
227
228 static void
229 finish_pass(struct atifs_machine *machine)
230 {
231    GLint i;
232
233    for (i = 0; i < 6; i++) {
234       COPY_4V(machine->PrevPassRegisters[i], machine->Registers[i]);
235    }
236 }
237
238 struct ati_fs_opcode_st ati_fs_opcodes[] = {
239    {GL_ADD_ATI, 2},
240    {GL_SUB_ATI, 2},
241    {GL_MUL_ATI, 2},
242    {GL_MAD_ATI, 3},
243    {GL_LERP_ATI, 3},
244    {GL_MOV_ATI, 1},
245    {GL_CND_ATI, 3},
246    {GL_CND0_ATI, 3},
247    {GL_DOT2_ADD_ATI, 3},
248    {GL_DOT3_ATI, 2},
249    {GL_DOT4_ATI, 2}
250 };
251
252
253
254 static void
255 handle_pass_op(struct atifs_machine *machine, struct atifs_setupinst *texinst,
256                const SWspan *span, GLuint column, GLuint idx)
257 {
258    GLuint swizzle = texinst->swizzle;
259    GLuint pass_tex = texinst->src;
260
261    if (pass_tex >= GL_TEXTURE0_ARB && pass_tex <= GL_TEXTURE7_ARB) {
262       pass_tex -= GL_TEXTURE0_ARB;
263       COPY_4V(machine->Registers[idx],
264               span->array->attribs[FRAG_ATTRIB_TEX0 + pass_tex][column]);
265    }
266    else if (pass_tex >= GL_REG_0_ATI && pass_tex <= GL_REG_5_ATI) {
267       pass_tex -= GL_REG_0_ATI;
268       COPY_4V(machine->Registers[idx], machine->PrevPassRegisters[pass_tex]);
269    }
270    apply_swizzle(machine->Registers[idx], swizzle);
271
272 }
273
274 static void
275 handle_sample_op(struct gl_context * ctx, struct atifs_machine *machine,
276                  struct atifs_setupinst *texinst, const SWspan *span,
277                  GLuint column, GLuint idx)
278 {
279 /* sample from unit idx using texinst->src as coords */
280    GLuint swizzle = texinst->swizzle;
281    GLuint coord_source = texinst->src;
282    GLfloat tex_coords[4] = { 0 };
283
284    if (coord_source >= GL_TEXTURE0_ARB && coord_source <= GL_TEXTURE7_ARB) {
285       coord_source -= GL_TEXTURE0_ARB;
286       COPY_4V(tex_coords,
287               span->array->attribs[FRAG_ATTRIB_TEX0 + coord_source][column]);
288    }
289    else if (coord_source >= GL_REG_0_ATI && coord_source <= GL_REG_5_ATI) {
290       coord_source -= GL_REG_0_ATI;
291       COPY_4V(tex_coords, machine->PrevPassRegisters[coord_source]);
292    }
293    apply_swizzle(tex_coords, swizzle);
294    fetch_texel(ctx, tex_coords, 0.0F, idx, machine->Registers[idx]);
295 }
296
297 #define SETUP_SRC_REG(optype, i, x)             \
298 do {                                            \
299    COPY_4V(src[optype][i], x);                  \
300 } while (0)
301
302
303
304 /**
305  * Execute the given fragment shader.
306  * NOTE: we do everything in single-precision floating point
307  * \param ctx - rendering context
308  * \param shader - the shader to execute
309  * \param machine - virtual machine state
310  * \param span - the SWspan we're operating on
311  * \param column - which pixel [i] we're operating on in the span
312  */
313 static void
314 execute_shader(struct gl_context *ctx, const struct ati_fragment_shader *shader,
315                struct atifs_machine *machine, const SWspan *span,
316                GLuint column)
317 {
318    GLuint pc;
319    struct atifs_instruction *inst;
320    struct atifs_setupinst *texinst;
321    GLint optype;
322    GLuint i;
323    GLint j, pass;
324    GLint dstreg;
325    GLfloat src[2][3][4];
326    GLfloat zeros[4] = { 0.0, 0.0, 0.0, 0.0 };
327    GLfloat ones[4] = { 1.0, 1.0, 1.0, 1.0 };
328    GLfloat dst[2][4], *dstp;
329
330    for (pass = 0; pass < shader->NumPasses; pass++) {
331       if (pass > 0)
332          finish_pass(machine);
333       for (j = 0; j < MAX_NUM_FRAGMENT_REGISTERS_ATI; j++) {
334          texinst = &shader->SetupInst[pass][j];
335          if (texinst->Opcode == ATI_FRAGMENT_SHADER_PASS_OP)
336             handle_pass_op(machine, texinst, span, column, j);
337          else if (texinst->Opcode == ATI_FRAGMENT_SHADER_SAMPLE_OP)
338             handle_sample_op(ctx, machine, texinst, span, column, j);
339       }
340
341       for (pc = 0; pc < shader->numArithInstr[pass]; pc++) {
342          inst = &shader->Instructions[pass][pc];
343
344          /* setup the source registers for color and alpha ops */
345          for (optype = 0; optype < 2; optype++) {
346             for (i = 0; i < inst->ArgCount[optype]; i++) {
347                GLint index = inst->SrcReg[optype][i].Index;
348
349                if (index >= GL_REG_0_ATI && index <= GL_REG_5_ATI)
350                   SETUP_SRC_REG(optype, i,
351                                 machine->Registers[index - GL_REG_0_ATI]);
352                else if (index >= GL_CON_0_ATI && index <= GL_CON_7_ATI) {
353                   if (shader->LocalConstDef & (1 << (index - GL_CON_0_ATI))) {
354                      SETUP_SRC_REG(optype, i,
355                                 shader->Constants[index - GL_CON_0_ATI]);
356                   } else {
357                      SETUP_SRC_REG(optype, i,
358                                 ctx->ATIFragmentShader.GlobalConstants[index - GL_CON_0_ATI]);
359                   }
360                }
361                else if (index == GL_ONE)
362                   SETUP_SRC_REG(optype, i, ones);
363                else if (index == GL_ZERO)
364                   SETUP_SRC_REG(optype, i, zeros);
365                else if (index == GL_PRIMARY_COLOR_EXT)
366                   SETUP_SRC_REG(optype, i,
367                                 machine->Inputs[ATI_FS_INPUT_PRIMARY]);
368                else if (index == GL_SECONDARY_INTERPOLATOR_ATI)
369                   SETUP_SRC_REG(optype, i,
370                                 machine->Inputs[ATI_FS_INPUT_SECONDARY]);
371
372                apply_src_rep(optype, inst->SrcReg[optype][i].argRep,
373                              src[optype][i]);
374                apply_src_mod(optype, inst->SrcReg[optype][i].argMod,
375                              src[optype][i]);
376             }
377          }
378
379          /* Execute the operations - color then alpha */
380          for (optype = 0; optype < 2; optype++) {
381             if (inst->Opcode[optype]) {
382                switch (inst->Opcode[optype]) {
383                case GL_ADD_ATI:
384                   if (!optype)
385                      for (i = 0; i < 3; i++) {
386                         dst[optype][i] =
387                            src[optype][0][i] + src[optype][1][i];
388                      }
389                   else
390                      dst[optype][3] = src[optype][0][3] + src[optype][1][3];
391                   break;
392                case GL_SUB_ATI:
393                   if (!optype)
394                      for (i = 0; i < 3; i++) {
395                         dst[optype][i] =
396                            src[optype][0][i] - src[optype][1][i];
397                      }
398                   else
399                      dst[optype][3] = src[optype][0][3] - src[optype][1][3];
400                   break;
401                case GL_MUL_ATI:
402                   if (!optype)
403                      for (i = 0; i < 3; i++) {
404                         dst[optype][i] =
405                            src[optype][0][i] * src[optype][1][i];
406                      }
407                   else
408                      dst[optype][3] = src[optype][0][3] * src[optype][1][3];
409                   break;
410                case GL_MAD_ATI:
411                   if (!optype)
412                      for (i = 0; i < 3; i++) {
413                         dst[optype][i] =
414                            src[optype][0][i] * src[optype][1][i] +
415                            src[optype][2][i];
416                      }
417                   else
418                      dst[optype][3] =
419                         src[optype][0][3] * src[optype][1][3] +
420                         src[optype][2][3];
421                   break;
422                case GL_LERP_ATI:
423                   if (!optype)
424                      for (i = 0; i < 3; i++) {
425                         dst[optype][i] =
426                            src[optype][0][i] * src[optype][1][i] + (1 -
427                                                                     src
428                                                                     [optype]
429                                                                     [0][i]) *
430                            src[optype][2][i];
431                      }
432                   else
433                      dst[optype][3] =
434                         src[optype][0][3] * src[optype][1][3] + (1 -
435                                                                  src[optype]
436                                                                  [0][3]) *
437                         src[optype][2][3];
438                   break;
439
440                case GL_MOV_ATI:
441                   if (!optype)
442                      for (i = 0; i < 3; i++) {
443                         dst[optype][i] = src[optype][0][i];
444                      }
445                   else
446                      dst[optype][3] = src[optype][0][3];
447                   break;
448                case GL_CND_ATI:
449                   if (!optype) {
450                      for (i = 0; i < 3; i++) {
451                         dst[optype][i] =
452                            (src[optype][2][i] >
453                             0.5) ? src[optype][0][i] : src[optype][1][i];
454                      }
455                   }
456                   else {
457                      dst[optype][3] =
458                         (src[optype][2][3] >
459                          0.5) ? src[optype][0][3] : src[optype][1][3];
460                   }
461                   break;
462
463                case GL_CND0_ATI:
464                   if (!optype)
465                      for (i = 0; i < 3; i++) {
466                         dst[optype][i] =
467                            (src[optype][2][i] >=
468                             0) ? src[optype][0][i] : src[optype][1][i];
469                      }
470                   else {
471                      dst[optype][3] =
472                         (src[optype][2][3] >=
473                          0) ? src[optype][0][3] : src[optype][1][3];
474                   }
475                   break;
476                case GL_DOT2_ADD_ATI:
477                   {
478                      GLfloat result;
479
480                      /* DOT 2 always uses the source from the color op */
481                      /* could save recalculation of dot products for alpha inst */
482                      result = src[0][0][0] * src[0][1][0] +
483                         src[0][0][1] * src[0][1][1] + src[0][2][2];
484                      if (!optype) {
485                         for (i = 0; i < 3; i++) {
486                            dst[optype][i] = result;
487                         }
488                      }
489                      else
490                         dst[optype][3] = result;
491                   }
492                   break;
493                case GL_DOT3_ATI:
494                   {
495                      GLfloat result;
496
497                      /* DOT 3 always uses the source from the color op */
498                      result = src[0][0][0] * src[0][1][0] +
499                         src[0][0][1] * src[0][1][1] +
500                         src[0][0][2] * src[0][1][2];
501
502                      if (!optype) {
503                         for (i = 0; i < 3; i++) {
504                            dst[optype][i] = result;
505                         }
506                      }
507                      else
508                         dst[optype][3] = result;
509                   }
510                   break;
511                case GL_DOT4_ATI:
512                   {
513                      GLfloat result;
514
515                      /* DOT 4 always uses the source from the color op */
516                      result = src[0][0][0] * src[0][1][0] +
517                         src[0][0][1] * src[0][1][1] +
518                         src[0][0][2] * src[0][1][2] +
519                         src[0][0][3] * src[0][1][3];
520                      if (!optype) {
521                         for (i = 0; i < 3; i++) {
522                            dst[optype][i] = result;
523                         }
524                      }
525                      else
526                         dst[optype][3] = result;
527                   }
528                   break;
529
530                }
531             }
532          }
533
534          /* write out the destination registers */
535          for (optype = 0; optype < 2; optype++) {
536             if (inst->Opcode[optype]) {
537                dstreg = inst->DstReg[optype].Index;
538                dstp = machine->Registers[dstreg - GL_REG_0_ATI];
539
540                if ((optype == 0) || ((inst->Opcode[1] != GL_DOT2_ADD_ATI) &&
541                   (inst->Opcode[1] != GL_DOT3_ATI) && (inst->Opcode[1] != GL_DOT4_ATI)))
542                   write_dst_addr(optype, inst->DstReg[optype].dstMod,
543                               inst->DstReg[optype].dstMask, dst[optype],
544                               dstp);
545                else
546                   write_dst_addr(1, inst->DstReg[0].dstMod, 0, dst[1], dstp);
547             }
548          }
549       }
550    }
551 }
552
553
554 /**
555  * Init fragment shader virtual machine state.
556  */
557 static void
558 init_machine(struct gl_context * ctx, struct atifs_machine *machine,
559              const struct ati_fragment_shader *shader,
560              const SWspan *span, GLuint col)
561 {
562    GLfloat (*inputs)[4] = machine->Inputs;
563    GLint i, j;
564
565    for (i = 0; i < 6; i++) {
566       for (j = 0; j < 4; j++)
567          machine->Registers[i][j] = 0.0;
568    }
569
570    COPY_4V(inputs[ATI_FS_INPUT_PRIMARY], span->array->attribs[FRAG_ATTRIB_COL0][col]);
571    COPY_4V(inputs[ATI_FS_INPUT_SECONDARY], span->array->attribs[FRAG_ATTRIB_COL1][col]);
572 }
573
574
575
576 /**
577  * Execute the current ATI shader program, operating on the given span.
578  */
579 void
580 _swrast_exec_fragment_shader(struct gl_context * ctx, SWspan *span)
581 {
582    const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current;
583    struct atifs_machine machine;
584    GLuint i;
585
586    /* incoming colors should be floats */
587    ASSERT(span->array->ChanType == GL_FLOAT);
588
589    for (i = 0; i < span->end; i++) {
590       if (span->array->mask[i]) {
591          init_machine(ctx, &machine, shader, span, i);
592
593          execute_shader(ctx, shader, &machine, span, i);
594
595          /* store result color */
596          {
597             const GLfloat *colOut = machine.Registers[0];
598             /*fprintf(stderr,"outputs %f %f %f %f\n",
599               colOut[0], colOut[1], colOut[2], colOut[3]); */
600             COPY_4V(span->array->attribs[FRAG_ATTRIB_COL0][i], colOut);
601          }
602       }
603    }
604 }