Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

s_fragprog.c 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. * Mesa 3-D graphics library
  3. * Version: 7.0.3
  4. *
  5. * Copyright (C) 1999-2007 Brian Paul 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 shall be included
  15. * in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  21. * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. */
  24. #include "main/glheader.h"
  25. #include "main/colormac.h"
  26. #include "main/context.h"
  27. #include "main/texstate.h"
  28. #include "shader/prog_instruction.h"
  29. #include "s_fragprog.h"
  30. #include "s_span.h"
  31. /**
  32. * Apply texture object's swizzle (X/Y/Z/W/0/1) to incoming 'texel'
  33. * and return results in 'colorOut'.
  34. */
  35. static INLINE void
  36. swizzle_texel(const GLfloat texel[4], GLfloat colorOut[4], GLuint swizzle)
  37. {
  38. if (swizzle == SWIZZLE_NOOP) {
  39. COPY_4V(colorOut, texel);
  40. }
  41. else {
  42. GLfloat vector[6];
  43. vector[SWIZZLE_X] = texel[0];
  44. vector[SWIZZLE_Y] = texel[1];
  45. vector[SWIZZLE_Z] = texel[2];
  46. vector[SWIZZLE_W] = texel[3];
  47. vector[SWIZZLE_ZERO] = 0.0F;
  48. vector[SWIZZLE_ONE] = 1.0F;
  49. colorOut[0] = vector[GET_SWZ(swizzle, 0)];
  50. colorOut[1] = vector[GET_SWZ(swizzle, 1)];
  51. colorOut[2] = vector[GET_SWZ(swizzle, 2)];
  52. colorOut[3] = vector[GET_SWZ(swizzle, 3)];
  53. }
  54. }
  55. /**
  56. * Fetch a texel with given lod.
  57. * Called via machine->FetchTexelLod()
  58. */
  59. static void
  60. fetch_texel_lod( GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda,
  61. GLuint unit, GLfloat color[4] )
  62. {
  63. const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
  64. if (texObj) {
  65. SWcontext *swrast = SWRAST_CONTEXT(ctx);
  66. GLfloat rgba[4];
  67. lambda = CLAMP(lambda, texObj->MinLod, texObj->MaxLod);
  68. swrast->TextureSample[unit](ctx, texObj, 1,
  69. (const GLfloat (*)[4]) texcoord,
  70. &lambda, &rgba);
  71. swizzle_texel(rgba, color, texObj->_Swizzle);
  72. }
  73. else {
  74. ASSIGN_4V(color, 0.0F, 0.0F, 0.0F, 1.0F);
  75. }
  76. }
  77. /**
  78. * Fetch a texel with the given partial derivatives to compute a level
  79. * of detail in the mipmap.
  80. * Called via machine->FetchTexelDeriv()
  81. */
  82. static void
  83. fetch_texel_deriv( GLcontext *ctx, const GLfloat texcoord[4],
  84. const GLfloat texdx[4], const GLfloat texdy[4],
  85. GLfloat lodBias, GLuint unit, GLfloat color[4] )
  86. {
  87. SWcontext *swrast = SWRAST_CONTEXT(ctx);
  88. const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
  89. if (texObj) {
  90. const struct gl_texture_image *texImg =
  91. texObj->Image[0][texObj->BaseLevel];
  92. const GLfloat texW = (GLfloat) texImg->WidthScale;
  93. const GLfloat texH = (GLfloat) texImg->HeightScale;
  94. GLfloat lambda;
  95. GLfloat rgba[4];
  96. lambda = _swrast_compute_lambda(texdx[0], texdy[0], /* ds/dx, ds/dy */
  97. texdx[1], texdy[1], /* dt/dx, dt/dy */
  98. texdx[3], texdy[2], /* dq/dx, dq/dy */
  99. texW, texH,
  100. texcoord[0], texcoord[1], texcoord[3],
  101. 1.0F / texcoord[3]) + lodBias;
  102. lambda = CLAMP(lambda, texObj->MinLod, texObj->MaxLod);
  103. swrast->TextureSample[unit](ctx, texObj, 1,
  104. (const GLfloat (*)[4]) texcoord,
  105. &lambda, &rgba);
  106. swizzle_texel(rgba, color, texObj->_Swizzle);
  107. }
  108. else {
  109. ASSIGN_4V(color, 0.0F, 0.0F, 0.0F, 1.0F);
  110. }
  111. }
  112. /**
  113. * Initialize the virtual fragment program machine state prior to running
  114. * fragment program on a fragment. This involves initializing the input
  115. * registers, condition codes, etc.
  116. * \param machine the virtual machine state to init
  117. * \param program the fragment program we're about to run
  118. * \param span the span of pixels we'll operate on
  119. * \param col which element (column) of the span we'll operate on
  120. */
  121. static void
  122. init_machine(GLcontext *ctx, struct gl_program_machine *machine,
  123. const struct gl_fragment_program *program,
  124. const SWspan *span, GLuint col)
  125. {
  126. if (program->Base.Target == GL_FRAGMENT_PROGRAM_NV) {
  127. /* Clear temporary registers (undefined for ARB_f_p) */
  128. _mesa_bzero(machine->Temporaries,
  129. MAX_PROGRAM_TEMPS * 4 * sizeof(GLfloat));
  130. }
  131. /* Setup pointer to input attributes */
  132. machine->Attribs = span->array->attribs;
  133. machine->DerivX = (GLfloat (*)[4]) span->attrStepX;
  134. machine->DerivY = (GLfloat (*)[4]) span->attrStepY;
  135. machine->NumDeriv = FRAG_ATTRIB_MAX;
  136. machine->Samplers = program->Base.SamplerUnits;
  137. /* if running a GLSL program (not ARB_fragment_program) */
  138. if (ctx->Shader.CurrentProgram) {
  139. /* Store front/back facing value in register FOGC.Y */
  140. machine->Attribs[FRAG_ATTRIB_FOGC][col][1] = 1.0 - span->facing;
  141. /* Note FOGC.ZW is gl_PointCoord if drawing a sprite */
  142. }
  143. machine->CurElement = col;
  144. /* init condition codes */
  145. machine->CondCodes[0] = COND_EQ;
  146. machine->CondCodes[1] = COND_EQ;
  147. machine->CondCodes[2] = COND_EQ;
  148. machine->CondCodes[3] = COND_EQ;
  149. /* init call stack */
  150. machine->StackDepth = 0;
  151. machine->FetchTexelLod = fetch_texel_lod;
  152. machine->FetchTexelDeriv = fetch_texel_deriv;
  153. }
  154. /**
  155. * Run fragment program on the pixels in span from 'start' to 'end' - 1.
  156. */
  157. static void
  158. run_program(GLcontext *ctx, SWspan *span, GLuint start, GLuint end)
  159. {
  160. SWcontext *swrast = SWRAST_CONTEXT(ctx);
  161. const struct gl_fragment_program *program = ctx->FragmentProgram._Current;
  162. const GLbitfield outputsWritten = program->Base.OutputsWritten;
  163. struct gl_program_machine *machine = &swrast->FragProgMachine;
  164. GLuint i;
  165. for (i = start; i < end; i++) {
  166. if (span->array->mask[i]) {
  167. init_machine(ctx, machine, program, span, i);
  168. if (_mesa_execute_program(ctx, &program->Base, machine)) {
  169. /* Store result color */
  170. if (outputsWritten & (1 << FRAG_RESULT_COLOR)) {
  171. COPY_4V(span->array->attribs[FRAG_ATTRIB_COL0][i],
  172. machine->Outputs[FRAG_RESULT_COLOR]);
  173. }
  174. else {
  175. /* Multiple drawbuffers / render targets
  176. * Note that colors beyond 0 and 1 will overwrite other
  177. * attributes, such as FOGC, TEX0, TEX1, etc. That's OK.
  178. */
  179. GLuint buf;
  180. for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) {
  181. if (outputsWritten & (1 << (FRAG_RESULT_DATA0 + buf))) {
  182. COPY_4V(span->array->attribs[FRAG_ATTRIB_COL0 + buf][i],
  183. machine->Outputs[FRAG_RESULT_DATA0 + buf]);
  184. }
  185. }
  186. }
  187. /* Store result depth/z */
  188. if (outputsWritten & (1 << FRAG_RESULT_DEPTH)) {
  189. const GLfloat depth = machine->Outputs[FRAG_RESULT_DEPTH][2];
  190. if (depth <= 0.0)
  191. span->array->z[i] = 0;
  192. else if (depth >= 1.0)
  193. span->array->z[i] = ctx->DrawBuffer->_DepthMax;
  194. else
  195. span->array->z[i] = IROUND(depth * ctx->DrawBuffer->_DepthMaxF);
  196. }
  197. }
  198. else {
  199. /* killed fragment */
  200. span->array->mask[i] = GL_FALSE;
  201. span->writeAll = GL_FALSE;
  202. }
  203. }
  204. }
  205. }
  206. /**
  207. * Execute the current fragment program for all the fragments
  208. * in the given span.
  209. */
  210. void
  211. _swrast_exec_fragment_program( GLcontext *ctx, SWspan *span )
  212. {
  213. const struct gl_fragment_program *program = ctx->FragmentProgram._Current;
  214. /* incoming colors should be floats */
  215. if (program->Base.InputsRead & FRAG_BIT_COL0) {
  216. ASSERT(span->array->ChanType == GL_FLOAT);
  217. }
  218. run_program(ctx, span, 0, span->end);
  219. if (program->Base.OutputsWritten & (1 << FRAG_RESULT_COLOR)) {
  220. span->interpMask &= ~SPAN_RGBA;
  221. span->arrayMask |= SPAN_RGBA;
  222. }
  223. if (program->Base.OutputsWritten & (1 << FRAG_RESULT_DEPTH)) {
  224. span->interpMask &= ~SPAN_Z;
  225. span->arrayMask |= SPAN_Z;
  226. }
  227. }