Source code of Windows XP (NT5)
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.

6861 lines
223 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: so_prim.c
  3. *
  4. * Routines to draw primitives
  5. *
  6. * Created: 10-16-1995
  7. * Author: Hock San Lee [hockl]
  8. *
  9. * Copyright (c) 1995 Microsoft Corporation
  10. \**************************************************************************/
  11. /*
  12. ** Copyright 1991, Silicon Graphics, Inc.
  13. ** All Rights Reserved.
  14. **
  15. ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  16. ** the contents of this file may not be disclosed to third parties, copied or
  17. ** duplicated in any form, in whole or in part, without the prior written
  18. ** permission of Silicon Graphics, Inc.
  19. **
  20. ** RESTRICTED RIGHTS LEGEND:
  21. ** Use, duplication or disclosure by the Government is subject to restrictions
  22. ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  23. ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  24. ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  25. ** rights reserved under the Copyright Laws of the United States.
  26. **
  27. ** $Revision: 1.13 $
  28. ** $Date: 1993/08/31 16:23:41 $
  29. */
  30. #include "precomp.h"
  31. #pragma hdrstop
  32. #include "glmath.h"
  33. #include "devlock.h"
  34. typedef void (FASTCALL *PFN_XFORM)
  35. (__GLcoord *, const __GLfloat *, const __GLmatrix *);
  36. typedef void (FASTCALL *PFN_XFORMBATCH)
  37. (__GLcoord *, __GLcoord *, const __GLmatrix *);
  38. #ifndef NEW_PARTIAL_PRIM
  39. typedef void (FASTCALL *PFN_POLYARRAYDRAW)(__GLcontext *, POLYARRAY *);
  40. #endif // NEW_PARTIAL_PRIM
  41. typedef void (FASTCALL *PFN_POLYARRAYRENDER)(__GLcontext *, POLYARRAY *);
  42. // The PA* functions apply to one array entry only.
  43. // The PolyArray* functions apply to the whole array.
  44. void FASTCALL PARenderPoint(__GLcontext *gc, __GLvertex *v);
  45. void FASTCALL PARenderTriangle(__GLcontext *gc, __GLvertex *v0, __GLvertex *v1, __GLvertex *v2);
  46. void PARenderQuadFast(__GLcontext *gc, __GLvertex *v0, __GLvertex *v1, __GLvertex *v2, __GLvertex *v3);
  47. void PARenderQuadSlow(__GLcontext *gc, __GLvertex *v0, __GLvertex *v1, __GLvertex *v2, __GLvertex *v3);
  48. void FASTCALL PAApplyMaterial(__GLcontext *gc, __GLmatChange *mat, GLint face);
  49. void FASTCALL PASphereGen(POLYDATA *pd, __GLcoord *result);
  50. GLuint FASTCALL PAClipCheckFrustum(__GLcontext *gc, POLYARRAY *pa,
  51. POLYDATA *pdLast);
  52. GLuint FASTCALL PAClipCheckFrustumWOne(__GLcontext *gc, POLYARRAY *pa,
  53. POLYDATA *pdLast);
  54. GLuint FASTCALL PAClipCheckFrustum2D(__GLcontext *gc, POLYARRAY *pa,
  55. POLYDATA *pdLast);
  56. GLuint FASTCALL PAClipCheckAll(__GLcontext *gc, POLYARRAY *pa,
  57. POLYDATA *pdLast);
  58. void FASTCALL PolyArrayRenderPoints(__GLcontext *gc, POLYARRAY *pa);
  59. void FASTCALL PolyArrayRenderLines(__GLcontext *gc, POLYARRAY *pa);
  60. void FASTCALL PolyArrayRenderLStrip(__GLcontext *gc, POLYARRAY *pa);
  61. void FASTCALL PolyArrayRenderTriangles(__GLcontext *gc, POLYARRAY *pa);
  62. void FASTCALL PolyArrayRenderTStrip(__GLcontext *gc, POLYARRAY *pa);
  63. void FASTCALL PolyArrayRenderTFan(__GLcontext *gc, POLYARRAY *pa);
  64. void FASTCALL PolyArrayRenderQuads(__GLcontext *gc, POLYARRAY *pa);
  65. void FASTCALL PolyArrayRenderQStrip(__GLcontext *gc, POLYARRAY *pa);
  66. void FASTCALL PolyArrayRenderPolygon(__GLcontext *gc, POLYARRAY *pa);
  67. #ifndef NEW_PARTIAL_PRIM
  68. void FASTCALL PolyArrayDrawPoints(__GLcontext *gc, POLYARRAY *pa);
  69. void FASTCALL PolyArrayDrawLines(__GLcontext *gc, POLYARRAY *pa);
  70. void FASTCALL PolyArrayDrawLLoop(__GLcontext *gc, POLYARRAY *pa);
  71. void FASTCALL PolyArrayDrawLStrip(__GLcontext *gc, POLYARRAY *pa);
  72. void FASTCALL PolyArrayDrawTriangles(__GLcontext *gc, POLYARRAY *pa);
  73. void FASTCALL PolyArrayDrawTStrip(__GLcontext *gc, POLYARRAY *pa);
  74. void FASTCALL PolyArrayDrawTFan(__GLcontext *gc, POLYARRAY *pa);
  75. void FASTCALL PolyArrayDrawQuads(__GLcontext *gc, POLYARRAY *pa);
  76. void FASTCALL PolyArrayDrawQStrip(__GLcontext *gc, POLYARRAY *pa);
  77. void FASTCALL PolyArrayDrawPolygon(__GLcontext *gc, POLYARRAY *pa);
  78. #endif // NEW_PARTIAL_PRIM
  79. void FASTCALL PolyArrayPropagateIndex(__GLcontext *gc, POLYARRAY *pa);
  80. void FASTCALL PolyArrayPropagateSameIndex(__GLcontext *gc, POLYARRAY *pa);
  81. void FASTCALL PolyArrayPropagateSameColor(__GLcontext *gc, POLYARRAY *pa);
  82. void FASTCALL PolyArrayPropagateColor(__GLcontext *gc, POLYARRAY *pa);
  83. void FASTCALL PolyArrayProcessEye(__GLcontext *gc, POLYARRAY *pa);
  84. void FASTCALL PolyArrayProcessEdgeFlag(POLYARRAY *pa);
  85. void FASTCALL PolyArrayComputeFog(__GLcontext *gc, POLYARRAY *pa);
  86. void FASTCALL PolyArrayApplyMaterials(__GLcontext *gc, POLYARRAY *pa);
  87. void FASTCALL PolyArrayCalcLightCache(__GLcontext *gc);
  88. GLuint FASTCALL PolyArrayCheckClippedPrimitive(__GLcontext *gc, POLYARRAY *pa, GLuint andCodes);
  89. POLYARRAY * FASTCALL PolyArrayRemoveClippedPrimitives(POLYARRAY *pa0);
  90. void RestoreAfterMcd(__GLGENcontext *gengc,
  91. POLYARRAY *paBegin, POLYARRAY *paEnd);
  92. // Turn on clipcode optimization
  93. #define POLYARRAY_AND_CLIPCODES 1
  94. // Some assertions used in this code
  95. // ASSERT_PRIMITIVE
  96. #if !((GL_POINTS == 0x0000) \
  97. && (GL_LINES == 0x0001) \
  98. && (GL_LINE_LOOP == 0x0002) \
  99. && (GL_LINE_STRIP == 0x0003) \
  100. && (GL_TRIANGLES == 0x0004) \
  101. && (GL_TRIANGLE_STRIP == 0x0005) \
  102. && (GL_TRIANGLE_FAN == 0x0006) \
  103. && (GL_QUADS == 0x0007) \
  104. && (GL_QUAD_STRIP == 0x0008) \
  105. && (GL_POLYGON == 0x0009))
  106. #error "bad primitive ordering\n"
  107. #endif
  108. // ASSERT_FACE
  109. #if !((__GL_FRONTFACE == 0) && (__GL_BACKFACE == 1))
  110. #error "bad face ordering\n"
  111. #endif
  112. // ASSERT_MATERIAL
  113. #if !((POLYARRAY_MATERIAL_FRONT == POLYDATA_MATERIAL_FRONT) \
  114. && (POLYARRAY_MATERIAL_BACK == POLYDATA_MATERIAL_BACK))
  115. #error "bad material mask\n"
  116. #endif
  117. // ASSERT_VERTEX
  118. #if !((POLYARRAY_VERTEX2 == POLYDATA_VERTEX2) \
  119. && (POLYARRAY_VERTEX3 == POLYDATA_VERTEX3) \
  120. && (POLYARRAY_VERTEX4 == POLYDATA_VERTEX4))
  121. #error "bad vertex flags\n"
  122. #endif
  123. //!!! Set it to 0!
  124. #define ENABLE_PERF_CHECK 0
  125. #if ENABLE_PERF_CHECK
  126. // Performance check macro
  127. #define PERF_CHECK(expr,str) \
  128. { \
  129. static BOOL bPrinted = FALSE; \
  130. if (!(expr) && !bPrinted) \
  131. { \
  132. bPrinted = TRUE; \
  133. WARNING("PERF_CHECK: " str);\
  134. } \
  135. }
  136. #else
  137. #define PERF_CHECK(expr,str)
  138. #endif // ENABLE_PERF_CHECK
  139. // Copy processed vertex.
  140. #define PA_COPY_PROCESSED_VERTEX(pdDst,pdSrc) \
  141. { \
  142. *(pdDst) = *(pdSrc); \
  143. /* must update color pointer for polygon to work! */ \
  144. (pdDst)->color = &(pdDst)->colors[__GL_FRONTFACE]; \
  145. }
  146. #define PA_COPY_VERTEX(pdDst,pdSrc) PA_COPY_PROCESSED_VERTEX(pdDst,pdSrc)
  147. #define PD_ARRAY(ary, idx) \
  148. ((POLYDATA *)((GLubyte *)(ary)+(sizeof(POLYDATA) * idx)))
  149. #define PD_VERTEX(ary, idx) \
  150. ((__GLvertex *)((GLubyte *)(ary)+(sizeof(__GLvertex) *idx)))
  151. #ifndef NEW_PARTIAL_PRIM
  152. // Poly array draw routines.
  153. // ASSERT_PRIMITIVE
  154. PFN_POLYARRAYDRAW afnPolyArrayDraw[] =
  155. {
  156. (PFN_POLYARRAYDRAW) PolyArrayDrawPoints,
  157. (PFN_POLYARRAYDRAW) PolyArrayDrawLines,
  158. (PFN_POLYARRAYDRAW) PolyArrayDrawLLoop,
  159. (PFN_POLYARRAYDRAW) PolyArrayDrawLStrip,
  160. (PFN_POLYARRAYDRAW) PolyArrayDrawTriangles,
  161. (PFN_POLYARRAYDRAW) PolyArrayDrawTStrip,
  162. (PFN_POLYARRAYDRAW) PolyArrayDrawTFan,
  163. (PFN_POLYARRAYDRAW) PolyArrayDrawQuads,
  164. (PFN_POLYARRAYDRAW) PolyArrayDrawQStrip,
  165. (PFN_POLYARRAYDRAW) PolyArrayDrawPolygon,
  166. };
  167. #endif // NEW_PARTIAL_PRIM
  168. // READ THIS NOTE BEFORE YOU MAKE ANY CHANGES!
  169. //
  170. // NOTE: This function is also called by RasterPos to compute its associated
  171. // color and texture coordinates!
  172. // This code has to update current values and material even if there is
  173. // no vertex.
  174. //!!! special case provoking vertex?
  175. void APIPRIVATE __glim_DrawPolyArray(void *_pa0)
  176. {
  177. __GLtransform *trMV;
  178. __GLmatrix *m, *mEye;
  179. GLuint enables;
  180. GLuint paNeeds;
  181. GLuint orCodes, andCodes;
  182. GLuint paflagsAll;
  183. POLYDATA *pd;
  184. POLYARRAY *pa0 = (POLYARRAY *) _pa0;
  185. POLYARRAY *pa;
  186. PFN_XFORM pfnXformEye;
  187. PFN_XFORMBATCH pfnXform;
  188. GLuint (FASTCALL *clipCheck)(__GLcontext *gc, POLYARRAY *pa,
  189. POLYDATA *pdLast);
  190. __GLmatrix *mInv;
  191. GLboolean doEye;
  192. __GLcolor scaledUserColor;
  193. GLuint paFlags;
  194. __GLcolor *pScaledUserColor;
  195. __GLcoord *pCurrentNormal;
  196. __GLcoord *pCurrentTexture;
  197. GLboolean bXformLightToNorm = FALSE;
  198. GLuint primFlags;
  199. BOOL bMcdProcessDone;
  200. BOOL bIsRasterPos;
  201. POLYARRAY* paPrev = 0;
  202. __GL_SETUP();
  203. // Crank down the fpu precision to 24-bit mantissa to gain front-end speed.
  204. // This will only affect code which relies on double arithmetic. Also,
  205. // mask off FP exceptions:
  206. FPU_SAVE_MODE();
  207. FPU_PREC_LOW_MASK_EXCEPTIONS();
  208. // There are 3 possible begin modes. If we are in the begin/end bracket,
  209. // it is __GL_IN_BEGIN. If we are not in the begin/end bracket, it is either
  210. // __GL_NOT_IN_BEGIN or __GL_NEED_VALIDATE.
  211. // Validation should only be done inside the display lock!
  212. ASSERTOPENGL(gc->beginMode != __GL_IN_BEGIN, "bad beginMode!");
  213. if (gc->beginMode == __GL_NEED_VALIDATE)
  214. (*gc->procs.validate)(gc);
  215. gc->beginMode = __GL_IN_BEGIN;
  216. // Initialize variables.
  217. enables = gc->state.enables.general;
  218. paNeeds = gc->vertex.paNeeds;
  219. paflagsAll = 0;
  220. // Need to save this flag because pa0 can be modified later,
  221. // possibly dropping the flag.
  222. bIsRasterPos = pa0->flags & POLYARRAY_RASTERPOS;
  223. // ---------------------------------------------------------
  224. // Update final current values and initialize current values at index 0
  225. // if not given. Material changes are updated later.
  226. paFlags = 0;
  227. if (!gc->modes.colorIndexMode) {
  228. __GL_SCALE_AND_CHECK_CLAMP_RGBA(scaledUserColor.r,
  229. scaledUserColor.g,
  230. scaledUserColor.b,
  231. scaledUserColor.a,
  232. gc, paFlags,
  233. gc->state.current.userColor.r,
  234. gc->state.current.userColor.g,
  235. gc->state.current.userColor.b,
  236. gc->state.current.userColor.a);
  237. pScaledUserColor = &scaledUserColor;
  238. } else {
  239. __GL_CHECK_CLAMP_CI(scaledUserColor.r, gc, paFlags, gc->state.current.userColorIndex);
  240. }
  241. pCurrentNormal = &gc->state.current.normal;
  242. pCurrentTexture = &gc->state.current.texture;
  243. primFlags = 0;
  244. // Optimization Possibility:
  245. // Currently, for every Primitive, we check to see if any of the
  246. // Attributes have been set by the evaluator. This could be potentially
  247. // optimized by having two versions of this loop (perhaps in a macro or
  248. // a function call); one which makes the checks and the other which doesnt.
  249. // If no evaluator is enabled, we could call the faster version (with
  250. // no checks)
  251. for (pa = pa0; pa; pa = pa->paNext)
  252. {
  253. POLYDATA *pd0;
  254. pd0 = pa->pd0;
  255. if (gc->modes.colorIndexMode)
  256. {
  257. // CI mode.
  258. // Update final current RGBA color incase one is given.
  259. if (pa->flags & POLYARRAY_OTHER_COLOR)
  260. gc->state.current.userColor = pa->otherColor;
  261. // Update final current CI color.
  262. if (!(pd0->flags & POLYDATA_COLOR_VALID))
  263. {
  264. pd0->flags |= POLYDATA_COLOR_VALID;
  265. pd0->colors[0].r = gc->state.current.userColorIndex;
  266. pa->flags |= paFlags;
  267. }
  268. // Update current color. pdCurColor could be NULL is there
  269. // were no glColor calls.
  270. if (pa->pdCurColor)
  271. {
  272. gc->state.current.userColorIndex = pa->pdCurColor->colors[0].r;
  273. }
  274. paFlags = (pa->flags & POLYARRAY_CLAMP_COLOR);
  275. }
  276. else
  277. {
  278. // RGBA mode.
  279. // Update final current CI color in case one is given.
  280. if (pa->flags & POLYARRAY_OTHER_COLOR)
  281. gc->state.current.userColorIndex = pa->otherColor.r;
  282. // Update final current RGBA color.
  283. if (!(pd0->flags & POLYDATA_COLOR_VALID))
  284. {
  285. pd0->flags |= POLYDATA_COLOR_VALID;
  286. pd0->colors[0] = *pScaledUserColor;
  287. pa->flags |= paFlags;
  288. }
  289. // Update current color. pdCurColor could be NULL is there
  290. // were no glColor calls.
  291. if (pa->pdCurColor)
  292. {
  293. pScaledUserColor = &pa->pdCurColor->colors[0];
  294. }
  295. paFlags = (pa->flags & POLYARRAY_CLAMP_COLOR);
  296. }
  297. // Update final current normal.
  298. if (!(pd0->flags & POLYDATA_NORMAL_VALID))
  299. {
  300. if (paNeeds & PANEEDS_NORMAL) {
  301. pd0->flags |= POLYDATA_NORMAL_VALID;
  302. // can also be pd0->normal = gc->state.current.normal!
  303. pd0->normal.x = pCurrentNormal->x;
  304. pd0->normal.y = pCurrentNormal->y;
  305. pd0->normal.z = pCurrentNormal->z;
  306. }
  307. }
  308. // Update current normal. pdCurNormal could be NULL if there
  309. // were no glNormal calls.
  310. if (pa->pdCurNormal)
  311. {
  312. pCurrentNormal = &pa->pdCurNormal->normal;
  313. }
  314. // Update final current texture coordinates.
  315. if (!(pd0->flags & POLYDATA_TEXTURE_VALID))
  316. {
  317. if (paNeeds & PANEEDS_TEXCOORD) {
  318. pd0->flags |= POLYDATA_TEXTURE_VALID;
  319. pd0->texture = *pCurrentTexture;
  320. if (__GL_FLOAT_COMPARE_PONE(pd0->texture.w, !=))
  321. pa->flags |= POLYARRAY_TEXTURE4;
  322. else if (__GL_FLOAT_NEZ(pd0->texture.z))
  323. pa->flags |= POLYARRAY_TEXTURE3;
  324. else if (__GL_FLOAT_NEZ(pd0->texture.y))
  325. pa->flags |= POLYARRAY_TEXTURE2;
  326. else
  327. pa->flags |= POLYARRAY_TEXTURE1;
  328. }
  329. }
  330. // Update current texture. pdCurTexture could be NULL if there
  331. // were no glTexture calls.
  332. if (pa->pdCurTexture)
  333. {
  334. pCurrentTexture = &pa->pdCurTexture->texture;
  335. }
  336. /*
  337. * Update current pointers. They have to point to the latest valid data.
  338. */
  339. if (pa->pdCurColor < pa->pdLastEvalColor)
  340. {
  341. pa->pdCurColor = pa->pdLastEvalColor;
  342. }
  343. if (pa->pdCurNormal < pa->pdLastEvalNormal)
  344. {
  345. pa->pdCurNormal = pa->pdLastEvalNormal;
  346. }
  347. if (pa->pdCurTexture < pa->pdLastEvalTexture)
  348. {
  349. pa->pdCurTexture = pa->pdLastEvalTexture;
  350. }
  351. // Update the texture key for hardware accelaration:
  352. pa->textureKey = gc->textureKey;
  353. // Update final current edge flag.
  354. if (!(pd0->flags & POLYDATA_EDGEFLAG_VALID))
  355. {
  356. if (gc->state.current.edgeTag)
  357. pd0->flags |= POLYDATA_EDGEFLAG_VALID | POLYDATA_EDGEFLAG_BOUNDARY;
  358. else
  359. pd0->flags |= POLYDATA_EDGEFLAG_VALID;
  360. }
  361. if (pa->pdCurEdgeFlag)
  362. {
  363. gc->state.current.edgeTag = (GLboolean)
  364. (pa->pdCurEdgeFlag->flags & POLYDATA_EDGEFLAG_BOUNDARY);
  365. }
  366. // Accumulate pa flags.
  367. paflagsAll |= pa->flags;
  368. // Accumulate primitive type bits
  369. primFlags |= 1 << pa->primType;
  370. if (pa->pd0 == pa->pdNextVertex)
  371. {
  372. // The polyarray has no vertices.
  373. // We have to apply material changes if there were any between BEGIN/END
  374. // and remove the polyarray from the chain
  375. if (pa->flags & (POLYARRAY_MATERIAL_FRONT | POLYARRAY_MATERIAL_BACK))
  376. PolyArrayApplyMaterials(gc, pa);
  377. if (paPrev)
  378. paPrev->paNext = pa->paNext;
  379. else
  380. pa0 = pa->paNext;
  381. PolyArrayRestoreColorPointer(pa);
  382. }
  383. else
  384. {
  385. paPrev = pa;
  386. }
  387. }
  388. // Store the normalized user color:
  389. if (!gc->modes.colorIndexMode)
  390. {
  391. gc->state.current.userColor.r = pScaledUserColor->r * gc->oneOverRedVertexScale;
  392. gc->state.current.userColor.g = pScaledUserColor->g * gc->oneOverGreenVertexScale;
  393. gc->state.current.userColor.b = pScaledUserColor->b * gc->oneOverBlueVertexScale;
  394. gc->state.current.userColor.a = pScaledUserColor->a * gc->oneOverAlphaVertexScale;
  395. }
  396. gc->state.current.normal.x = pCurrentNormal->x;
  397. gc->state.current.normal.y = pCurrentNormal->y;
  398. gc->state.current.normal.z = pCurrentNormal->z;
  399. gc->state.current.texture = *pCurrentTexture;
  400. // All polyarrays could be removed if they had no vertices
  401. if (!pa0)
  402. {
  403. bXformLightToNorm = FALSE;
  404. goto drawpolyarray_exit;
  405. }
  406. //
  407. // Get the modeling matrix:
  408. //
  409. trMV = gc->transform.modelView;
  410. // ---------------------------------------------------------
  411. //
  412. // Allow MCD 2.0 to do transform and light if possible.
  413. // Don't try it for rasterpos calls.
  414. //
  415. bMcdProcessDone = FALSE;
  416. #if MCD_VER_MAJOR >= 2
  417. if (((__GLGENcontext *)gc)->pMcdState != NULL &&
  418. McdDriverInfo.mcdDriver.pMCDrvProcess != NULL &&
  419. gc->renderMode == GL_RENDER &&
  420. !bIsRasterPos)
  421. #else
  422. if (0)
  423. #endif
  424. {
  425. POLYMATERIAL *pm;
  426. PDMATERIAL *pdMat;
  427. POLYARRAY *paEnd;
  428. // If no material changes have ever been seen then there
  429. // won't be a polymaterial at all.
  430. pm = GLTEB_CLTPOLYMATERIAL();
  431. if (pm != NULL)
  432. {
  433. pdMat = pm->pdMaterial0;
  434. }
  435. else
  436. {
  437. pdMat = NULL;
  438. }
  439. paEnd = GenMcdProcessPrim((__GLGENcontext *)gc,
  440. pa0, paflagsAll, primFlags,
  441. (MCDTRANSFORM *)trMV,
  442. (MCDMATERIALCHANGES *)pdMat);
  443. RestoreAfterMcd((__GLGENcontext *)gc, pa0, paEnd);
  444. bMcdProcessDone = TRUE;
  445. if (paEnd == NULL)
  446. {
  447. goto drawpolyarray_exit;
  448. }
  449. else
  450. {
  451. // If MCDrvProcess kicks back we will not
  452. // call MCDrvDraw. We could check for non-generic
  453. // here and abandon the batch, saving the front-end processing.
  454. // I don't think it's worth it since kicking back on
  455. // a non-generic format is basically a driver bug.
  456. pa0 = paEnd;
  457. }
  458. }
  459. // ---------------------------------------------------------
  460. // Initialize the normal matrix:
  461. // Normals are not needed after color assignment and texture generation!
  462. // The above is not true anymore. You need Normals for true PHONG shading.
  463. // IN: normal matrix
  464. // OUT: normal matrix (processed)
  465. if (paNeeds & (PANEEDS_NORMAL | PANEEDS_NORMAL_FOR_TEXTURE))
  466. {
  467. if (trMV->flags & XFORM_UPDATE_INVERSE)
  468. __glComputeInverseTranspose(gc, trMV);
  469. gc->mInv = mInv = &trMV->inverseTranspose;
  470. }
  471. #if DBG
  472. else
  473. gc->mInv = mInv = (__GLmatrix *) -1;
  474. #endif
  475. // ---------------------------------------------------------
  476. // Find out is we have to transform normals for lighting
  477. // We can only do lighting in object space if:
  478. // we're using infinite lighting AND
  479. // we're not doing two-sided lighting AND
  480. // we're rendering AND
  481. // the transformation matrix has unity scaling
  482. //
  483. bXformLightToNorm =
  484. (gc->vertex.paNeeds & PANEEDS_NORMAL) &&
  485. (gc->renderMode == GL_RENDER) &&
  486. (mInv->nonScaling) &&
  487. ((paNeeds & (PANEEDS_FRONT_COLOR | PANEEDS_BACK_COLOR)) ==
  488. PANEEDS_FRONT_COLOR) &&
  489. ((gc->procs.paCalcColor == PolyArrayFastCalcRGBColor) ||
  490. (gc->procs.paCalcColor == PolyArrayZippyCalcRGBColor) ||
  491. (gc->procs.paCalcColor == PolyArrayFastCalcCIColor));
  492. // Transform normals for spherical map texture generation
  493. //
  494. if (paNeeds & PANEEDS_NORMAL_FOR_TEXTURE)
  495. {
  496. // If we transform normals for texture, we have to process lighting in camera space
  497. bXformLightToNorm = FALSE;
  498. // Now transform normals
  499. for (pa = pa0; pa; pa = pa->paNext)
  500. {
  501. if (!(enables & __GL_NORMALIZE_ENABLE))
  502. (*mInv->xfNormBatch)(pa, mInv);
  503. else
  504. (*mInv->xfNormBatchN)(pa, mInv);
  505. }
  506. paNeeds &= ~PANEEDS_NORMAL;
  507. }
  508. // ---------------------------------------------------------
  509. // Process texture coordinates. We need to do this while we still have
  510. // valid object coordinate data. If we need normals to perform the texture
  511. // generation, we also transform the normals.
  512. //
  513. // Texture coordinates are modified in place.
  514. //
  515. // IN: texture, obj, (eye), normal
  516. // OUT: texture, (eye)
  517. if (paNeeds & PANEEDS_TEXCOORD)
  518. {
  519. if ((gc->procs.paCalcTexture == PolyArrayCalcTexture) &&
  520. (gc->transform.texture->matrix.matrixType == __GL_MT_IDENTITY)) {
  521. for (pa = pa0; pa; pa = pa->paNext)
  522. {
  523. PERF_CHECK(!(pa->flags & (POLYARRAY_TEXTURE3 | POLYARRAY_TEXTURE4)),
  524. "Uses r, q texture coordinates!\n");
  525. // If all incoming vertices have valid texcoords, and texture
  526. // matrix is identity, and texgen is disabled, we are done.
  527. if ((pa->flags & POLYARRAY_SAME_POLYDATA_TYPE)
  528. && (pa->pdCurTexture != pa->pd0)
  529. // Need to test 2nd vertex because pdCurTexture may have been
  530. // advanced as a result of combining TexCoord command after End
  531. && ((pa->pd0 + 1)->flags & POLYDATA_TEXTURE_VALID))
  532. ;
  533. else
  534. PolyArrayCalcTexture(gc, pa);
  535. }
  536. } else {
  537. for (pa = pa0; pa; pa = pa->paNext)
  538. {
  539. PERF_CHECK(!(pa->flags & (POLYARRAY_TEXTURE3 | POLYARRAY_TEXTURE4)),
  540. "Uses r, q texture coordinates!\n");
  541. (*gc->procs.paCalcTexture)(gc, pa);
  542. }
  543. }
  544. }
  545. //
  546. // Process the eye coordinate if:
  547. // user clip planes are enabled
  548. // we're processing RASTERPOS
  549. // we have slow lighting which needs the eye coordinate
  550. //
  551. // We need to process the eye coordinate here because the
  552. // object coordinate gets trashed by the initial obj->clip
  553. // transform.
  554. //
  555. //
  556. //
  557. clipCheck = gc->procs.paClipCheck;
  558. // Compute eye coord first
  559. // We need eye coordinates to do user clip plane clipping
  560. if ((clipCheck == PAClipCheckAll) ||
  561. bIsRasterPos ||
  562. (gc->procs.paCalcColor == PolyArrayCalcCIColor) ||
  563. (gc->procs.paCalcColor == PolyArrayCalcRGBColor) ||
  564. #ifdef GL_WIN_phong_shading
  565. (gc->polygon.shader.phong.flags & __GL_PHONG_NEED_EYE_XPOLATE) ||
  566. #endif //GL_WIN_phong_shading
  567. (enables & __GL_FOG_ENABLE && gc->renderMode == GL_RENDER))
  568. {
  569. mEye = &trMV->matrix;
  570. if (paflagsAll & POLYARRAY_VERTEX4)
  571. pfnXformEye = mEye->xf4;
  572. else if (paflagsAll & POLYARRAY_VERTEX3)
  573. pfnXformEye = mEye->xf3;
  574. else
  575. pfnXformEye = mEye->xf2;
  576. doEye = TRUE;
  577. } else
  578. doEye = FALSE;
  579. // If any incoming coords contains w coord, use xf4.
  580. m = &trMV->mvp;
  581. if (paflagsAll & POLYARRAY_VERTEX4)
  582. pfnXform = (void*)m->xf4Batch;
  583. else if (paflagsAll & POLYARRAY_VERTEX3)
  584. pfnXform = (void*)m->xf3Batch;
  585. else
  586. pfnXform = (void*)m->xf2Batch;
  587. //---------------------------------------------------------------------------
  588. // If normalization is on, we will handle it here in one pass. We will
  589. // then transform the light into normal space
  590. // flag. Note that we need to save the original light values away so
  591. // we can restore them before we exit.
  592. //
  593. if (bXformLightToNorm)
  594. {
  595. __GLlightSourceMachine *lsm;
  596. LONG i;
  597. __GLmatrix matrix2;
  598. __glTranspose3x3(&matrix2, &trMV->matrix);
  599. for (i = 0, lsm = gc->light.sources; lsm; lsm = lsm->next, i++) {
  600. __GLcoord hv;
  601. __GLmatrix matrix;
  602. lsm->tmpHHat = lsm->hHat;
  603. lsm->tmpUnitVPpli = lsm->unitVPpli;
  604. __glMultMatrix(&matrix,
  605. &gc->state.light.source[i].lightMatrix, &matrix2);
  606. hv = gc->state.light.source[i].position;
  607. __glXForm3x3(&hv, &hv.x, &matrix);
  608. __glNormalize(&lsm->unitVPpli.x, &hv.x);
  609. hv = lsm->unitVPpli;
  610. hv.x += matrix.matrix[2][0];
  611. hv.y += matrix.matrix[2][1];
  612. hv.z += matrix.matrix[2][2];
  613. __glNormalize(&lsm->hHat.x, &hv.x);
  614. }
  615. }
  616. PolyArrayCalcLightCache(gc);
  617. // ---------------------------------------------------------
  618. // Do transform, color, and lighting calculations.
  619. //
  620. // This is the heart of the rendering pipeline, so we try
  621. // to do as many operations as possible while touching the
  622. // least amount of memory to reduce cache affects.
  623. //
  624. // If it is phong-shading, dont update materials and dont do
  625. // lighting.
  626. // ---------------------------------------------------------
  627. for (pa = pa0; pa; pa = pa->paNext)
  628. {
  629. POLYDATA *pdLast;
  630. #ifdef NEW_PARTIAL_PRIM
  631. pa->flags |= POLYARRAY_RENDER_PRIMITIVE; // Needed for MCD
  632. #endif
  633. pdLast = pa->pdNextVertex - 1;
  634. // ---------------------------------------------------------
  635. // Process the eye coordinate if we will need it in the
  636. // pipeline and haven't yet processed it in texture generation.
  637. // We have to do this before we trash the object coord in the
  638. // next phase.
  639. //
  640. // IN: obj
  641. // OUT: eye
  642. if (doEye && !(pa->flags & POLYARRAY_EYE_PROCESSED)) {
  643. pa->flags |= POLYARRAY_EYE_PROCESSED;
  644. if (mEye->matrixType == __GL_MT_IDENTITY) {
  645. for (pd = pa->pd0; pd <= pdLast; pd++)
  646. pd->eye = pd->obj;
  647. } else {
  648. for (pd = pa->pd0; pd <= pdLast; pd++)
  649. (*pfnXformEye)(&pd->eye, (__GLfloat *) &pd->obj, mEye);
  650. }
  651. }
  652. // ---------------------------------------------------------
  653. // Process the object coordinate. This generates the clip
  654. // and window coordinates, along with the clip codes.
  655. //
  656. // IN: obj (destroyed)
  657. // OUT: clip, window
  658. orCodes = 0; // accumulate all clip codes
  659. #ifdef POLYARRAY_AND_CLIPCODES
  660. andCodes = (GLuint) -1;
  661. #endif
  662. if (m->matrixType == __GL_MT_IDENTITY)
  663. {
  664. // pd->clip = pd->obj;
  665. ASSERTOPENGL(&pd->clip == &pd->obj, "bad clip offset\n");
  666. }
  667. else
  668. (*pfnXform)(&pa->pd0->clip, &pdLast->clip, m);
  669. pa->orClipCodes = 0;
  670. pa->andClipCodes = (GLuint)-1;
  671. if (clipCheck != PAClipCheckFrustum2D)
  672. {
  673. if (m->matrixType != __GL_MT_GENERAL &&
  674. !(pa->flags & POLYDATA_VERTEX4) &&
  675. clipCheck != PAClipCheckAll)
  676. andCodes = PAClipCheckFrustumWOne(gc, pa, pdLast);
  677. else
  678. andCodes = (*clipCheck)(gc, pa, pdLast);
  679. }
  680. else
  681. {
  682. if (pa->flags & (POLYDATA_VERTEX3 | POLYDATA_VERTEX4))
  683. andCodes = PAClipCheckFrustum(gc, pa, pdLast);
  684. else
  685. andCodes = PAClipCheckFrustum2D(gc, pa, pdLast);
  686. }
  687. #ifdef POLYARRAY_AND_CLIPCODES
  688. if (andCodes)
  689. {
  690. andCodes = PolyArrayCheckClippedPrimitive(gc, pa, andCodes);
  691. // add POLYARRAY_REMOVE_PRIMITIVE flag
  692. paflagsAll |= pa->flags;
  693. }
  694. pa->andClipCodes = andCodes;
  695. #endif
  696. // ---------------------------------------------------------
  697. // Process colors and materials if we're not in selection and
  698. // haven't been completely clipped out.
  699. //
  700. // IN: obj/eye, color (front), normal
  701. // OUT: (normal), color (front and back)
  702. if (!(pa->flags & POLYARRAY_REMOVE_PRIMITIVE) &&
  703. !(paNeeds & PANEEDS_CLIP_ONLY))
  704. {
  705. if (!(enables & __GL_LIGHTING_ENABLE))
  706. {
  707. // Lighting is disabled.
  708. // Clamp RGBA colors, mask color index values.
  709. // Only front colors are computed, back colors are not needed.
  710. if (paNeeds & PANEEDS_SKIP_LIGHTING)
  711. {
  712. // Note that when lighting calculation is skipped,
  713. // we still need to fill in the colors field.
  714. // Otherwise, the rasterization routines may get FP
  715. // exceptions on invalid colors.
  716. pa->flags |= POLYARRAY_SAME_COLOR_DATA;
  717. (*gc->procs.paCalcColorSkip)(gc, pa, __GL_FRONTFACE);
  718. }
  719. else if (pa->flags & POLYARRAY_SAME_COLOR_DATA)
  720. {
  721. if (gc->modes.colorIndexMode)
  722. PolyArrayPropagateSameIndex(gc, pa);
  723. else
  724. PolyArrayPropagateSameColor(gc, pa);
  725. }
  726. else if (gc->modes.colorIndexMode)
  727. {
  728. PolyArrayPropagateIndex(gc, pa);
  729. }
  730. else
  731. {
  732. PolyArrayPropagateColor(gc, pa);
  733. }
  734. }
  735. else
  736. {
  737. // It is time to transform and normalize normals if nesessary
  738. if (bXformLightToNorm)
  739. {
  740. if(enables & __GL_NORMALIZE_ENABLE)
  741. {
  742. __glNormalizeBatch(pa);
  743. }
  744. }
  745. else
  746. {
  747. if (paNeeds & PANEEDS_NORMAL)
  748. {
  749. if (!(enables & __GL_NORMALIZE_ENABLE))
  750. (*mInv->xfNormBatch)(pa, mInv);
  751. else
  752. (*mInv->xfNormBatchN)(pa, mInv);
  753. }
  754. }
  755. #ifdef GL_WIN_phong_shading
  756. // if phong-shading, then do this at rendering time
  757. // else do it here
  758. if (!(gc->state.light.shadingModel == GL_PHONG_WIN)
  759. || (pa->primType <= GL_POINTS))
  760. #endif //GL_WIN_phong_shading
  761. {
  762. // Lighting is enabled.
  763. POLYDATA *pd1, *pd2, *pdN;
  764. GLint face;
  765. GLuint matMask;
  766. GLboolean doFrontColor, doBackColor, doColor;
  767. // Clear POLYARRAY_SAME_COLOR_DATA flag if lighting is
  768. // enabled.
  769. pa->flags &= ~POLYARRAY_SAME_COLOR_DATA;
  770. pdN = pa->pdNextVertex;
  771. // Needs only front color for points and lines.
  772. // ASSERT_PRIMITIVE
  773. if ((unsigned int) pa->primType <= GL_LINE_STRIP)
  774. {
  775. doFrontColor = GL_TRUE;
  776. doBackColor = GL_FALSE;
  777. }
  778. else
  779. {
  780. doFrontColor = paNeeds & PANEEDS_FRONT_COLOR;
  781. doBackColor = paNeeds & PANEEDS_BACK_COLOR;
  782. }
  783. // Process front and back colors in two passes.
  784. // Do back colors first!
  785. //!!! We can potentially optimize 2-sided lighting in the
  786. // slow path by running through all vertices and look for
  787. // color needs for each vertex!
  788. // See RenderSmoothTriangle.
  789. PERF_CHECK
  790. (
  791. !(doFrontColor && doBackColor),
  792. "Two-sided lighting - need both colors!\n"
  793. );
  794. // ASSERT_FACE
  795. // ASSERT_MATERIAL
  796. for (face = 1,
  797. matMask = POLYARRAY_MATERIAL_BACK,
  798. doColor = doBackColor;
  799. face >= 0;
  800. face--,
  801. matMask = POLYARRAY_MATERIAL_FRONT,
  802. doColor = doFrontColor
  803. )
  804. {
  805. POLYMATERIAL *pm;
  806. if (!doColor)
  807. continue;
  808. // If color is not needed, fill in the colors field
  809. // with default.
  810. if (paNeeds & PANEEDS_SKIP_LIGHTING)
  811. {
  812. (*gc->procs.paCalcColorSkip)(gc, pa, face);
  813. continue;
  814. }
  815. // Process color ranges that include no material
  816. // changes (excluding color material) one at a time.
  817. // Color material changes are handled in the color
  818. // procs.
  819. if (!(pa->flags & matMask))
  820. {
  821. // process the whole color array
  822. (*gc->procs.paCalcColor)(gc, face, pa, pa->pd0,
  823. pdN - 1);
  824. continue;
  825. }
  826. // There are material changes, we need to recompute
  827. // material and light source machine values before
  828. // processing the next color range.
  829. // Each range below is given by [pd1, pd2-1].
  830. //!!! it is possible to fix polyarraycalcrgbcolor to
  831. // accept certain material!
  832. pm = GLTEB_CLTPOLYMATERIAL();
  833. // no need to do this material later
  834. pa->flags &= ~matMask;
  835. for (pd1 = pa->pd0; pd1 <= pdN; pd1 = pd2)
  836. {
  837. POLYDATA *pdColor, *pdNormal;
  838. // Apply material changes to the current vertex.
  839. // It also applies trailing material changes
  840. // following the last vertex.
  841. if (pd1->flags & matMask)
  842. PAApplyMaterial(gc,
  843. *(&pm->pdMaterial0[pd1 -
  844. pa->pdBuffer0].front + face), face);
  845. // If this is the trailing material change, we are
  846. // done.
  847. if (pd1 == pdN)
  848. break;
  849. // Find next vertex with material changes. We
  850. // need to track current color and normal so that
  851. // the next color range begins with valid color
  852. // and normal. We cannot track current values on
  853. // client side because we don't have initial
  854. // current values when batching this function.
  855. pdColor = pd1;
  856. pdNormal = pd1;
  857. for (pd2 = pd1 + 1; pd2 < pdN; pd2++)
  858. {
  859. // track current color
  860. if (pd2->flags & POLYDATA_COLOR_VALID)
  861. pdColor = pd2;
  862. // track current normal
  863. if (pd2->flags & POLYDATA_NORMAL_VALID)
  864. pdNormal = pd2;
  865. if (pd2->flags & matMask)
  866. break;
  867. }
  868. // Update next vertex's current color and normal
  869. // if not given. The paCalcColor proc assumes that
  870. // the first vertex contains a valid current color
  871. // and normal. We need to save the current values
  872. // before they are modified by the color procs.
  873. if (!(pd2->flags & POLYDATA_COLOR_VALID))
  874. {
  875. pd2->flags |= POLYDATA_COLOR_VALID;
  876. pd2->colors[0] = pdColor->colors[0];
  877. }
  878. if (!(pd2->flags & POLYDATA_NORMAL_VALID))
  879. {
  880. pd2->flags |= POLYDATA_NORMAL_VALID;
  881. pd2->normal.x = pdNormal->normal.x;
  882. pd2->normal.y = pdNormal->normal.y;
  883. pd2->normal.z = pdNormal->normal.z;
  884. }
  885. // Compute the colos range [pd1, pd2-1] that
  886. // contains no material changes.
  887. (*gc->procs.paCalcColor)(gc, face, pa, pd1, pd2-1);
  888. }
  889. } // for (faces)
  890. } // Not phong-shading
  891. #ifdef GL_WIN_phong_shading
  892. else
  893. {
  894. PolyArrayPhongPropagateColorNormal(gc, pa);
  895. }
  896. #endif //GL_WIN_phong_shading
  897. } // lighting enabled
  898. }
  899. // Update material.
  900. if ((pa->flags & (POLYARRAY_MATERIAL_FRONT |
  901. POLYARRAY_MATERIAL_BACK))
  902. #ifdef GL_WIN_phong_shading
  903. && ((gc->state.light.shadingModel != GL_PHONG_WIN)
  904. || (pa->primType <= GL_POINTS))
  905. #endif //GL_WIN_phong_shading
  906. )
  907. PolyArrayApplyMaterials(gc, pa);
  908. } // end of transform, color, and lighting calculations.
  909. // ---------------------------------------------------------
  910. // This is the end of the main pipeline loop. At this point,
  911. // we need to take care of selection, removal of rejected
  912. // primitives, cheap fog, and edge-flag processing.
  913. // ---------------------------------------------------------
  914. // In selection, we need only clip and window (and possibly eye values
  915. // computed above.) At this point, we have already applied materials as
  916. // well. But we still need to apply materials and colors.
  917. if (paNeeds & PANEEDS_CLIP_ONLY)
  918. goto drawpolyarray_render_primitives;
  919. // If any of the andClipCodes is nonzero, we may be able to throw away
  920. // some primitives.
  921. #ifdef POLYARRAY_AND_CLIPCODES
  922. if (paflagsAll & POLYARRAY_REMOVE_PRIMITIVE)
  923. {
  924. pa0 = PolyArrayRemoveClippedPrimitives(pa0);
  925. if (!pa0)
  926. goto drawpolyarray_apply_color;
  927. }
  928. #endif
  929. // ---------------------------------------------------------
  930. // Process cheap fog.
  931. //
  932. // IN: obj/eye, color
  933. // OUT: eye, fog, color
  934. // if this is changed, need to fix RasterPos's setup!
  935. if ((gc->renderMode == GL_RENDER)
  936. && (enables & __GL_FOG_ENABLE)
  937. && (gc->polygon.shader.modeFlags & (__GL_SHADE_INTERP_FOG |
  938. __GL_SHADE_CHEAP_FOG)))
  939. {
  940. for (pa = pa0; pa; pa = pa->paNext)
  941. {
  942. // Note: the eye coordinate has already been computed.
  943. // compute fog values
  944. PolyArrayComputeFog(gc, pa);
  945. if (gc->polygon.shader.modeFlags & __GL_SHADE_CHEAP_FOG)
  946. {
  947. #ifdef GL_WIN_specular_fog
  948. ASSERTOPENGL (!(gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG), "Cheap fog cannot be done if Specular fog is needed\n");
  949. #endif //GL_WIN_specular_fog
  950. // Apply fog if it is smooth shading and in render mode.
  951. // In flat/phong shading, cheap fogging is currently done at
  952. // render procs we can probably do cheap fog in flat shading
  953. // here but we will need to compute the provoking colors with
  954. // z info correctly so we can interpolate in the clipping
  955. // procs. It would require rewriting the clipping routines
  956. // in so_clip.c too!
  957. if (gc->polygon.shader.modeFlags & __GL_SHADE_SMOOTH_LIGHT)
  958. (*gc->procs.paApplyCheapFog)(gc, pa);
  959. }
  960. else
  961. {
  962. PERF_CHECK(FALSE, "Uses slow fog\n");
  963. }
  964. }
  965. }
  966. // ---------------------------------------------------------
  967. // Process edge flags.
  968. //
  969. // IN: edge
  970. // OUT: edge (all vertices)
  971. if (paNeeds & PANEEDS_EDGEFLAG)
  972. {
  973. for (pa = pa0; pa; pa = pa->paNext)
  974. {
  975. if (pa->primType == GL_TRIANGLES
  976. || pa->primType == GL_QUADS
  977. || pa->primType == GL_POLYGON)
  978. {
  979. // If all incoming vertices have valid edgeflags, we are done.
  980. // When all polydata's are of the same type, there are 2 cases
  981. // where edge flag processing can be skipped:
  982. // 1. All edge flags were given.
  983. // 2. No edge flag was given and the initial edge flag (i.e.
  984. // current gc edge flag) is non boundary. In this case,
  985. // all edge flags were set to non boundary in pd->flags
  986. // initialization.
  987. if ((pa->flags & POLYARRAY_SAME_POLYDATA_TYPE)
  988. && (((pa->pdCurEdgeFlag != pa->pd0) &&
  989. // Need to test 2nd vertex because pdCurEdgeFlag may
  990. // have been advanced as a result of combining EdgeFlag
  991. // command after End
  992. ((pa->pd0 + 1)->flags & POLYDATA_EDGEFLAG_VALID))
  993. || !(pa->pd0->flags & POLYDATA_EDGEFLAG_BOUNDARY)))
  994. ;
  995. else
  996. PolyArrayProcessEdgeFlag(pa);
  997. #ifdef NEW_PARTIAL_PRIM
  998. // For partial begin polygon we have to clear edge flag for first vertex.
  999. // For partial end polygon we have to clear edge flag for last vertex.
  1000. //
  1001. if (pa->primType == GL_POLYGON)
  1002. {
  1003. if (pa->flags & POLYARRAY_PARTIAL_END)
  1004. (pa->pdNextVertex-1)->flags &= ~POLYDATA_EDGEFLAG_BOUNDARY;
  1005. if (pa->flags & POLYARRAY_PARTIAL_BEGIN)
  1006. pa->pd0->flags &= ~POLYDATA_EDGEFLAG_BOUNDARY;
  1007. }
  1008. #endif // NEW_PARTIAL_PRIM
  1009. }
  1010. }
  1011. }
  1012. // ---------------------------------------------------------
  1013. // Process the primitives.
  1014. drawpolyarray_render_primitives:
  1015. // Skip the rest if this is a RasterPos
  1016. if (bIsRasterPos)
  1017. goto drawpolyarray_exit;
  1018. #ifndef NEW_PARTIAL_PRIM
  1019. for (pa = pa0; pa; pa = pa->paNext)
  1020. {
  1021. ASSERTOPENGL(pa->primType >= GL_POINTS && pa->primType <= GL_POLYGON,
  1022. "DrawPolyArray: bad primitive type\n");
  1023. (*afnPolyArrayDraw[pa->primType])(gc, pa);
  1024. }
  1025. #endif // NEW_PARTIAL_PRIM
  1026. // ---------------------------------------------------------
  1027. // Update final light source machine.
  1028. // The user color was initialized above.
  1029. #ifndef GL_WIN_phong_shading
  1030. drawpolyarray_apply_color:
  1031. (*gc->procs.applyColor)(gc);
  1032. #endif //GL_WIN_phong_shading
  1033. // ---------------------------------------------------------
  1034. // Flush the primitive chain.
  1035. // To draw primitives, we can let the FPU run in chop (truncation) mode
  1036. // since we have enough precision left to convert to pixel units.
  1037. FPU_CHOP_ON_PREC_LOW();
  1038. #if 1
  1039. if (pa0)
  1040. glsrvFlushDrawPolyArray(pa0, bMcdProcessDone);
  1041. #endif
  1042. drawpolyarray_exit:
  1043. // Out of begin mode.
  1044. #ifdef GL_WIN_phong_shading
  1045. drawpolyarray_apply_color:
  1046. (*gc->procs.applyColor)(gc);
  1047. #endif //GL_WIN_phong_shading
  1048. // Out of begin mode.
  1049. FPU_RESTORE_MODE_NO_EXCEPTIONS();
  1050. ASSERTOPENGL(gc->beginMode == __GL_IN_BEGIN, "bad beginMode!");
  1051. gc->beginMode = __GL_NOT_IN_BEGIN;
  1052. //
  1053. // If we were using object-space lighting, restore the original lighting values:
  1054. //
  1055. if (bXformLightToNorm) {
  1056. __GLlightSourceMachine *lsm;
  1057. for (lsm = gc->light.sources; lsm; lsm = lsm->next) {
  1058. lsm->hHat = lsm->tmpHHat;
  1059. lsm->unitVPpli = lsm->tmpUnitVPpli;
  1060. }
  1061. }
  1062. return;
  1063. }
  1064. #ifdef POLYARRAY_AND_CLIPCODES
  1065. // Determine if a clipped primitive can be removed early.
  1066. // If the logical AND of vertex clip codes of a primitive is non-zero,
  1067. // the primitive is completely clipped and can be removed early.
  1068. // However, if a primitive is partially built, we may not be able to
  1069. // remove it yet to maintain connectivity between the partial primitives.
  1070. // By eliminating a primitive early, we save on lighting and other calculations.
  1071. //
  1072. // Set POLYARRAY_REMOVE_PRIMITIVE flag if the primitve can be removed early.
  1073. // Return new andCodes.
  1074. GLuint FASTCALL PolyArrayCheckClippedPrimitive(__GLcontext *gc, POLYARRAY *pa, GLuint andCodes)
  1075. {
  1076. ASSERTOPENGL(andCodes, "bad andCodes\n");
  1077. // Don't eliminate RasterPos
  1078. if (pa->flags & POLYARRAY_RASTERPOS)
  1079. return andCodes;
  1080. #ifndef NEW_PARTIAL_PRIM
  1081. // If this is a partial begin, include previous clipcode.
  1082. if (pa->flags & POLYARRAY_PARTIAL_BEGIN)
  1083. {
  1084. switch (pa->primType)
  1085. {
  1086. case GL_LINE_LOOP:
  1087. // previous vertex
  1088. andCodes &= gc->vertex.pdSaved[0].clipCode;
  1089. // loop vertex
  1090. if (!(pa->flags & POLYARRAY_PARTIAL_END))
  1091. andCodes &= gc->vertex.pdSaved[1].clipCode;
  1092. break;
  1093. case GL_POLYGON:
  1094. andCodes &= gc->vertex.pdSaved[2].clipCode;
  1095. // fall through
  1096. case GL_TRIANGLE_FAN:
  1097. case GL_TRIANGLE_STRIP:
  1098. case GL_QUAD_STRIP:
  1099. andCodes &= gc->vertex.pdSaved[1].clipCode;
  1100. // fall through
  1101. case GL_LINE_STRIP:
  1102. andCodes &= gc->vertex.pdSaved[0].clipCode;
  1103. break;
  1104. case GL_POINTS:
  1105. case GL_LINES:
  1106. case GL_TRIANGLES:
  1107. case GL_QUADS:
  1108. default:
  1109. break;
  1110. }
  1111. }
  1112. if (andCodes
  1113. &&
  1114. (
  1115. !(pa->flags & POLYARRAY_PARTIAL_END) ||
  1116. pa->primType == GL_POINTS ||
  1117. pa->primType == GL_LINES ||
  1118. pa->primType == GL_TRIANGLES ||
  1119. pa->primType == GL_QUADS
  1120. )
  1121. )
  1122. pa->flags |= POLYARRAY_REMOVE_PRIMITIVE;
  1123. #else
  1124. //
  1125. // If we have partial end primitive we cannot remove line strip, line loop or
  1126. // polygon to preserve stipple pattern. Line loop was converted to line strip.
  1127. //
  1128. if (andCodes &&
  1129. !(pa->flags & POLYARRAY_PARTIAL_END &&
  1130. (pa->primType == GL_LINE_STRIP || pa->primType == GL_POLYGON)))
  1131. pa->flags |= POLYARRAY_REMOVE_PRIMITIVE;
  1132. #endif // NEW_PARTIAL_PRIM
  1133. // return new andCodes.
  1134. return andCodes;
  1135. }
  1136. // Remove completely clipped primitives from the polyarray chain.
  1137. POLYARRAY * FASTCALL PolyArrayRemoveClippedPrimitives(POLYARRAY *pa0)
  1138. {
  1139. POLYARRAY *pa, *paNext, *pa2First, *pa2Last;
  1140. // Eliminate the trivially clipped primitives and build a new pa chain.
  1141. pa2First = pa2Last = NULL;
  1142. for (pa = pa0; pa; pa = paNext)
  1143. {
  1144. // get next pa first
  1145. paNext = pa->paNext;
  1146. if (pa->flags & POLYARRAY_REMOVE_PRIMITIVE)
  1147. {
  1148. PolyArrayRestoreColorPointer(pa);
  1149. }
  1150. else
  1151. {
  1152. // add to the new pa chain
  1153. if (!pa2First)
  1154. pa2First = pa;
  1155. else
  1156. pa2Last->paNext = pa;
  1157. pa2Last = pa;
  1158. pa2Last->paNext = NULL;
  1159. }
  1160. }
  1161. // Return the new pa chain.
  1162. return pa2First;
  1163. }
  1164. #endif // POLYARRAY_AND_CLIPCODES
  1165. /******************************Public*Routine******************************\
  1166. *
  1167. * RestoreAfterMcd
  1168. *
  1169. * Handles final bookkeeping necessary after the MCD has processed
  1170. * some or all of a batch.
  1171. *
  1172. * History:
  1173. * Thu Mar 20 12:04:49 1997 -by- Drew Bliss [drewb]
  1174. * Split from glsrvFlushDrawPolyArray.
  1175. *
  1176. \**************************************************************************/
  1177. void RestoreAfterMcd(__GLGENcontext *gengc,
  1178. POLYARRAY *paBegin, POLYARRAY *paEnd)
  1179. {
  1180. POLYARRAY *pa, *paNext;
  1181. // Restore color pointer in the vertex buffer (for the POLYARRAYs
  1182. // that have been processed by MCD; leave the unprocessed ones
  1183. // alone).
  1184. //
  1185. // If the driver is using DMA, it must do the reset. If not DMA,
  1186. // we will do it for the driver.
  1187. if (!(McdDriverInfo.mcdDriverInfo.drvMemFlags & MCDRV_MEM_DMA))
  1188. {
  1189. for (pa = paBegin; pa != paEnd; pa = paNext)
  1190. {
  1191. paNext = pa->paNext;
  1192. PolyArrayRestoreColorPointer(pa);
  1193. }
  1194. }
  1195. else
  1196. {
  1197. // With DMA, the driver must either process the entire batch
  1198. // or reject the entire batch.
  1199. //
  1200. // Therefore, if the MCD call returns success (paEnd == NULL),
  1201. // the POLYARRAY is being sent via DMA to the driver and we
  1202. // need to switch to the other buffer. Otherwise, we need to
  1203. // drop down into the software implementation.
  1204. if (!paEnd)
  1205. {
  1206. GenMcdSwapBatch(gengc);
  1207. }
  1208. }
  1209. }
  1210. /******************************Public*Routine******************************\
  1211. *
  1212. * RescaleVertexColorsToBuffer
  1213. *
  1214. * Scales vertex colors from vertex (MCD) color range to buffer color
  1215. * range for software simulations.
  1216. *
  1217. * History:
  1218. * Thu Mar 20 16:21:16 1997 -by- Drew Bliss [drewb]
  1219. * Created
  1220. *
  1221. \**************************************************************************/
  1222. void RescaleVertexColorsToBuffer(__GLcontext *gc, POLYARRAY *pa)
  1223. {
  1224. int idx;
  1225. POLYDATA *pd, *pdLast;
  1226. idx = 0;
  1227. if (pa->primType <= GL_LINE_STRIP)
  1228. {
  1229. idx |= 1;
  1230. }
  1231. else
  1232. {
  1233. if (gc->vertex.paNeeds & PANEEDS_FRONT_COLOR)
  1234. {
  1235. idx |= 1;
  1236. }
  1237. if (gc->vertex.paNeeds & PANEEDS_BACK_COLOR)
  1238. {
  1239. idx |= 2;
  1240. }
  1241. }
  1242. pdLast = pa->pdNextVertex-1;
  1243. switch(idx)
  1244. {
  1245. case 1:
  1246. // Front color only.
  1247. if (gc->modes.colorIndexMode)
  1248. {
  1249. for (pd = pa->pd0; pd <= pdLast; pd++)
  1250. {
  1251. pd->colors[0].r *= gc->redVertexToBufferScale;
  1252. }
  1253. }
  1254. else
  1255. {
  1256. for (pd = pa->pd0; pd <= pdLast; pd++)
  1257. {
  1258. pd->colors[0].r *= gc->redVertexToBufferScale;
  1259. pd->colors[0].g *= gc->greenVertexToBufferScale;
  1260. pd->colors[0].b *= gc->blueVertexToBufferScale;
  1261. pd->colors[0].a *= gc->alphaVertexToBufferScale;
  1262. }
  1263. }
  1264. break;
  1265. case 2:
  1266. // Back color only.
  1267. if (gc->modes.colorIndexMode)
  1268. {
  1269. for (pd = pa->pd0; pd <= pdLast; pd++)
  1270. {
  1271. pd->colors[1].r *= gc->redVertexToBufferScale;
  1272. }
  1273. }
  1274. else
  1275. {
  1276. for (pd = pa->pd0; pd <= pdLast; pd++)
  1277. {
  1278. pd->colors[1].r *= gc->redVertexToBufferScale;
  1279. pd->colors[1].g *= gc->greenVertexToBufferScale;
  1280. pd->colors[1].b *= gc->blueVertexToBufferScale;
  1281. pd->colors[1].a *= gc->alphaVertexToBufferScale;
  1282. }
  1283. }
  1284. break;
  1285. case 3:
  1286. // Front and back colors.
  1287. if (gc->modes.colorIndexMode)
  1288. {
  1289. for (pd = pa->pd0; pd <= pdLast; pd++)
  1290. {
  1291. pd->colors[0].r *= gc->redVertexToBufferScale;
  1292. pd->colors[1].r *= gc->redVertexToBufferScale;
  1293. }
  1294. }
  1295. else
  1296. {
  1297. for (pd = pa->pd0; pd <= pdLast; pd++)
  1298. {
  1299. pd->colors[0].r *= gc->redVertexToBufferScale;
  1300. pd->colors[0].g *= gc->greenVertexToBufferScale;
  1301. pd->colors[0].b *= gc->blueVertexToBufferScale;
  1302. pd->colors[0].a *= gc->alphaVertexToBufferScale;
  1303. pd->colors[1].r *= gc->redVertexToBufferScale;
  1304. pd->colors[1].g *= gc->greenVertexToBufferScale;
  1305. pd->colors[1].b *= gc->blueVertexToBufferScale;
  1306. pd->colors[1].a *= gc->alphaVertexToBufferScale;
  1307. }
  1308. }
  1309. }
  1310. }
  1311. /******************************Public*Routine******************************\
  1312. * glsrvFlushDrawPolyArray
  1313. *
  1314. * The dispatch code in glsrvAttention links together the POLYARRAY data
  1315. * structures of consecutive glim_DrawPolyArray calls. The front end
  1316. * preprocessing of the vertices in each POLYARRAY is executed immediately
  1317. * in glim_DrawPolyArray (i.e., PolyArrayDrawXXX), but the actually back end
  1318. * rendering (PolyArrayRenderXXX) is delayed until the chain is broken (either
  1319. * by a non-DrawPolyArray call, the end of the batch, or a batch timeout).
  1320. *
  1321. * glsrvFlushDrawPolyArray is the function that is called to flush the
  1322. * chained POLYARRAYs by invoking the back end rendering code. The back end
  1323. * may be the generic software-only implementation or the MCD driver.
  1324. *
  1325. * History:
  1326. * 12-Feb-1996 -by- Gilman Wong [gilmanw]
  1327. * Wrote it.
  1328. \**************************************************************************/
  1329. // Poly array render routines.
  1330. // ASSERT_PRIMITIVE
  1331. PFN_POLYARRAYRENDER afnPolyArrayRender[] =
  1332. {
  1333. (PFN_POLYARRAYRENDER) PolyArrayRenderPoints,
  1334. (PFN_POLYARRAYRENDER) PolyArrayRenderLines,
  1335. (PFN_POLYARRAYRENDER) NULL, // line loop not required
  1336. (PFN_POLYARRAYRENDER) PolyArrayRenderLStrip,
  1337. (PFN_POLYARRAYRENDER) PolyArrayRenderTriangles,
  1338. (PFN_POLYARRAYRENDER) PolyArrayRenderTStrip,
  1339. (PFN_POLYARRAYRENDER) PolyArrayRenderTFan,
  1340. (PFN_POLYARRAYRENDER) PolyArrayRenderQuads,
  1341. (PFN_POLYARRAYRENDER) PolyArrayRenderQStrip,
  1342. (PFN_POLYARRAYRENDER) PolyArrayRenderPolygon,
  1343. };
  1344. void APIPRIVATE glsrvFlushDrawPolyArray(POLYARRAY *paBegin,
  1345. BOOL bMcdProcessDone)
  1346. {
  1347. POLYARRAY *pa, *paNext;
  1348. __GLGENcontext *gengc;
  1349. BOOL bResetViewportAdj = FALSE;
  1350. __GL_SETUP();
  1351. //#define FRONT_END_ONLY 1
  1352. #if FRONT_END_ONLY
  1353. if (paBegin)
  1354. {
  1355. for (pa = paNext = paBegin; pa = paNext; )
  1356. {
  1357. ASSERTOPENGL(pa->primType >= GL_POINTS &&
  1358. pa->primType <= GL_POLYGON,
  1359. "DrawPolyArray: bad primitive type\n");
  1360. // Get next pointer first!
  1361. paNext = pa->paNext;
  1362. // Restore color pointer in the vertex buffer!
  1363. PolyArrayRestoreColorPointer(pa);
  1364. }
  1365. }
  1366. return;
  1367. #endif
  1368. gengc = (__GLGENcontext *) gc;
  1369. #ifdef _MCD_
  1370. #if DBG
  1371. if (gengc->pMcdState && !(glDebugFlags & GLDEBUG_DISABLEPRIM) &&
  1372. (gc->renderMode == GL_RENDER))
  1373. #else
  1374. if ((gengc->pMcdState) && (gc->renderMode == GL_RENDER))
  1375. #endif
  1376. {
  1377. POLYARRAY *paEnd;
  1378. // If no commands were processed via MCD front-end support
  1379. // then try the rasterization support.
  1380. if (!bMcdProcessDone)
  1381. {
  1382. // Let the MCD driver have first crack. If the MCD processes
  1383. // the entire batch, then it will return NULL. Otherwise, it
  1384. // will return a pointer to a chain of unprocessed POLYARRAYs.
  1385. paEnd = GenMcdDrawPrim(gengc, paBegin);
  1386. RestoreAfterMcd(gengc, paBegin, paEnd);
  1387. }
  1388. else
  1389. {
  1390. // MCD has already kicked back so nothing is consumed.
  1391. paEnd = paBegin;
  1392. }
  1393. // Prepare to use generic to provide simulations for the
  1394. // unhandled POLYARRAYs, if any.
  1395. paBegin = paEnd;
  1396. if (paBegin)
  1397. {
  1398. // Check if generic simulations can be used. If not, we must
  1399. // abandon the rest of the batch.
  1400. if (!(gengc->flags & GENGC_GENERIC_COMPATIBLE_FORMAT) ||
  1401. (gengc->gc.texture.ddtex.levels > 0 &&
  1402. (gengc->gc.texture.ddtex.flags & DDTEX_GENERIC_FORMAT) == 0))
  1403. {
  1404. goto PA_abandonBatch;
  1405. }
  1406. // If we need to kickback to simulations, now is the time to
  1407. // grab the device lock. If the lock fails, abandon the rest
  1408. // of the batch.
  1409. {
  1410. __GLbeginMode beginMode = gengc->gc.beginMode;
  1411. // Why save/restore beginMode?
  1412. //
  1413. // The glim_DrawPolyArray function plays with the beginMode
  1414. // value. However, in delayed locking the MCD state is
  1415. // validated, but the generic state is not properly validated
  1416. // if the lock is not held. So we need to also play with
  1417. // the beginMode so that the validation code can be called.
  1418. gengc->gc.beginMode = __GL_NOT_IN_BEGIN;
  1419. if (!glsrvLazyGrabSurfaces(gengc, gengc->fsGenLocks))
  1420. {
  1421. gengc->gc.beginMode = beginMode;
  1422. goto PA_abandonBatch;
  1423. }
  1424. gengc->gc.beginMode = beginMode;
  1425. }
  1426. // We may need to temporarily reset the viewport adjust values
  1427. // before calling simulations. If GenMcdResetViewportAdj returns
  1428. // TRUE, the viewport is changed and we need restore later with
  1429. // VP_NOBIAS.
  1430. bResetViewportAdj = GenMcdResetViewportAdj(gc, VP_FIXBIAS);
  1431. }
  1432. }
  1433. if (paBegin)
  1434. #endif
  1435. {
  1436. for (pa = paNext = paBegin; pa = paNext; )
  1437. {
  1438. ASSERTOPENGL(/* pa->primType >= GL_POINTS && <always true since primType is unsigned> */
  1439. pa->primType <= GL_POLYGON,
  1440. "DrawPolyArray: bad primitive type\n");
  1441. #ifndef NEW_PARTIAL_PRIM
  1442. if (pa->flags & POLYARRAY_RENDER_PRIMITIVE)
  1443. #endif // NEW_PARTIAL_PRIM
  1444. {
  1445. // Rescale colors if necessary.
  1446. if (!gc->vertexToBufferIdentity)
  1447. {
  1448. RescaleVertexColorsToBuffer(gc, pa);
  1449. }
  1450. #ifdef GL_WIN_phong_shading
  1451. if (pa->flags & POLYARRAY_PHONG_DATA_VALID)
  1452. {
  1453. if (pa->phong->flags & __GL_PHONG_FRONT_FIRST_VALID)
  1454. PAApplyMaterial(gc,
  1455. &(pa->phong->matChange[__GL_PHONG_FRONT_FIRST]),
  1456. 0);
  1457. if (pa->phong->flags & __GL_PHONG_BACK_FIRST_VALID)
  1458. PAApplyMaterial(gc,
  1459. &(pa->phong->matChange[__GL_PHONG_BACK_FIRST]),
  1460. 1);
  1461. }
  1462. (*afnPolyArrayRender[pa->primType])(gc, pa);
  1463. if (pa->flags & POLYARRAY_PHONG_DATA_VALID)
  1464. {
  1465. if (pa->phong->flags & __GL_PHONG_FRONT_TRAIL_VALID)
  1466. PAApplyMaterial(gc,
  1467. &(pa->phong->matChange[__GL_PHONG_FRONT_TRAIL]),
  1468. 0);
  1469. if (pa->phong->flags & __GL_PHONG_BACK_TRAIL_VALID)
  1470. PAApplyMaterial(gc,
  1471. &(pa->phong->matChange[__GL_PHONG_BACK_TRAIL]),
  1472. 1);
  1473. //Free the pa->phong data-structure
  1474. GCFREE(gc, pa->phong);
  1475. }
  1476. #else
  1477. (*afnPolyArrayRender[pa->primType])(gc, pa);
  1478. #endif //GL_WIN_phong_shading
  1479. }
  1480. // Get next pointer first!
  1481. paNext = pa->paNext;
  1482. // Restore color pointer in the vertex buffer!
  1483. PolyArrayRestoreColorPointer(pa);
  1484. }
  1485. // Restore viewport values if needed.
  1486. if (bResetViewportAdj)
  1487. {
  1488. GenMcdResetViewportAdj(gc, VP_NOBIAS);
  1489. }
  1490. }
  1491. return;
  1492. PA_abandonBatch:
  1493. if (paBegin)
  1494. {
  1495. // Abandoning the remainder of the batch. Must reset the color
  1496. // pointers in the remainder of the batch.
  1497. //
  1498. // Note that paBegin must point to the beginning of the chain of
  1499. // unprocessed POLYARRAYs.
  1500. for (pa = paBegin; pa; pa = paNext)
  1501. {
  1502. paNext = pa->paNext;
  1503. PolyArrayRestoreColorPointer(pa);
  1504. }
  1505. __glSetError(GL_OUT_OF_MEMORY);
  1506. }
  1507. }
  1508. /****************************************************************************/
  1509. // Restore color pointer in the vertex buffer!
  1510. // However, don't restore the color pointer if it is a RasterPos call.
  1511. GLvoid FASTCALL PolyArrayRestoreColorPointer(POLYARRAY *pa)
  1512. {
  1513. POLYDATA *pd, *pdLast;
  1514. ASSERTOPENGL(!(pa->flags & POLYARRAY_RASTERPOS),
  1515. "RasterPos unexpected\n");
  1516. // See also glsbResetBuffers.
  1517. // Reset color pointer in output index array
  1518. if (pa->aIndices)
  1519. {
  1520. ASSERTOPENGL((POLYDATA *) pa->aIndices >= pa->pdBuffer0 &&
  1521. (POLYDATA *) pa->aIndices <= pa->pdBufferMax,
  1522. "bad index map pointer\n");
  1523. pdLast = (POLYDATA *) (pa->aIndices + pa->nIndices);
  1524. for (pd = (POLYDATA *) pa->aIndices; pd < pdLast; pd++)
  1525. pd->color = &pd->colors[__GL_FRONTFACE];
  1526. ASSERTOPENGL(pd >= pa->pdBuffer0 &&
  1527. pd <= pa->pdBufferMax + 1,
  1528. "bad polyarray pointer\n");
  1529. }
  1530. // Reset color pointer in the POLYARRAY structure last!
  1531. ASSERTOPENGL((POLYDATA *) pa >= pa->pdBuffer0 &&
  1532. (POLYDATA *) pa <= pa->pdBufferMax,
  1533. "bad polyarray pointer\n");
  1534. ((POLYDATA *) pa)->color = &((POLYDATA *) pa)->colors[__GL_FRONTFACE];
  1535. }
  1536. /****************************************************************************/
  1537. // Compute generic fog value for the poly array.
  1538. //
  1539. // IN: eye
  1540. // OUT: fog
  1541. #ifdef GL_WIN_specular_fog
  1542. void FASTCALL PolyArrayComputeFog(__GLcontext *gc, POLYARRAY *pa)
  1543. {
  1544. __GLfloat density, density2neg, end, oneOverEMinusS;
  1545. POLYDATA *pd, *pdLast;
  1546. __GLfloat fog;
  1547. BOOL bNeedModulate = (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG);
  1548. ASSERTOPENGL(pa->flags & POLYARRAY_EYE_PROCESSED, "need eye\n");
  1549. pdLast = pa->pdNextVertex-1;
  1550. switch (gc->state.fog.mode)
  1551. {
  1552. case GL_EXP:
  1553. PERF_CHECK(FALSE, "Uses GL_EXP fog\n");
  1554. density = gc->state.fog.density;
  1555. for (pd = pa->pd0; pd <= pdLast; pd++)
  1556. {
  1557. __GLfloat eyeZ;
  1558. pd->flags |= POLYDATA_FOG_VALID; // used by clipping code!
  1559. eyeZ = pd->eye.z;
  1560. if (__GL_FLOAT_LTZ(eyeZ))
  1561. fog = __GL_POWF(__glE, density * eyeZ);
  1562. else
  1563. fog = __GL_POWF(__glE, -density * eyeZ);
  1564. // clamp the fog value to [0.0,1.0]
  1565. if (fog > __glOne)
  1566. fog = __glOne;
  1567. if (bNeedModulate)
  1568. pd->fog *= fog;
  1569. else
  1570. pd->fog = fog;
  1571. }
  1572. break;
  1573. case GL_EXP2:
  1574. PERF_CHECK(FALSE, "Uses GL_EXP2 fog\n");
  1575. density2neg = gc->state.fog.density2neg;
  1576. for (pd = pa->pd0; pd <= pdLast; pd++)
  1577. {
  1578. __GLfloat eyeZ;
  1579. pd->flags |= POLYDATA_FOG_VALID;
  1580. eyeZ = pd->eye.z;
  1581. fog = __GL_POWF(__glE, density2neg * eyeZ * eyeZ);
  1582. // clamp the fog value to [0.0,1.0]
  1583. if (fog > __glOne)
  1584. fog = __glOne;
  1585. if (bNeedModulate)
  1586. pd->fog *= fog;
  1587. else
  1588. pd->fog = fog;
  1589. }
  1590. break;
  1591. case GL_LINEAR:
  1592. end = gc->state.fog.end;
  1593. oneOverEMinusS = gc->state.fog.oneOverEMinusS;
  1594. for (pd = pa->pd0; pd <= pdLast; pd++)
  1595. {
  1596. __GLfloat eyeZ;
  1597. pd->flags |= POLYDATA_FOG_VALID;
  1598. eyeZ = pd->eye.z;
  1599. if (__GL_FLOAT_LTZ(eyeZ))
  1600. fog = (end + eyeZ) * oneOverEMinusS;
  1601. else
  1602. fog = (end - eyeZ) * oneOverEMinusS;
  1603. // clamp the fog value here
  1604. if (__GL_FLOAT_LTZ(pd->fog))
  1605. fog = __glZero;
  1606. else if (__GL_FLOAT_COMPARE_PONE(pd->fog, >))
  1607. fog = __glOne;
  1608. if (bNeedModulate)
  1609. pd->fog *= fog;
  1610. else
  1611. pd->fog = fog;
  1612. }
  1613. break;
  1614. }
  1615. }
  1616. #else //GL_WIN_specular_fog
  1617. void FASTCALL PolyArrayComputeFog(__GLcontext *gc, POLYARRAY *pa)
  1618. {
  1619. __GLfloat density, density2neg, end, oneOverEMinusS;
  1620. POLYDATA *pd, *pdLast;
  1621. ASSERTOPENGL(pa->flags & POLYARRAY_EYE_PROCESSED, "need eye\n");
  1622. pdLast = pa->pdNextVertex-1;
  1623. switch (gc->state.fog.mode)
  1624. {
  1625. case GL_EXP:
  1626. PERF_CHECK(FALSE, "Uses GL_EXP fog\n");
  1627. density = gc->state.fog.density;
  1628. for (pd = pa->pd0; pd <= pdLast; pd++)
  1629. {
  1630. __GLfloat eyeZ;
  1631. pd->flags |= POLYDATA_FOG_VALID; // used by clipping code!
  1632. eyeZ = pd->eye.z;
  1633. if (__GL_FLOAT_LTZ(eyeZ))
  1634. pd->fog = __GL_POWF(__glE, density * eyeZ);
  1635. else
  1636. pd->fog = __GL_POWF(__glE, -density * eyeZ);
  1637. // clamp the fog value to [0.0,1.0]
  1638. if (pd->fog > __glOne)
  1639. pd->fog = __glOne;
  1640. }
  1641. break;
  1642. case GL_EXP2:
  1643. PERF_CHECK(FALSE, "Uses GL_EXP2 fog\n");
  1644. density2neg = gc->state.fog.density2neg;
  1645. for (pd = pa->pd0; pd <= pdLast; pd++)
  1646. {
  1647. __GLfloat eyeZ;
  1648. pd->flags |= POLYDATA_FOG_VALID;
  1649. eyeZ = pd->eye.z;
  1650. pd->fog = __GL_POWF(__glE, density2neg * eyeZ * eyeZ);
  1651. // clamp the fog value to [0.0,1.0]
  1652. if (pd->fog > __glOne)
  1653. pd->fog = __glOne;
  1654. }
  1655. break;
  1656. case GL_LINEAR:
  1657. end = gc->state.fog.end;
  1658. oneOverEMinusS = gc->state.fog.oneOverEMinusS;
  1659. for (pd = pa->pd0; pd <= pdLast; pd++)
  1660. {
  1661. __GLfloat eyeZ;
  1662. pd->flags |= POLYDATA_FOG_VALID;
  1663. eyeZ = pd->eye.z;
  1664. if (__GL_FLOAT_LTZ(eyeZ))
  1665. pd->fog = (end + eyeZ) * oneOverEMinusS;
  1666. else
  1667. pd->fog = (end - eyeZ) * oneOverEMinusS;
  1668. // clamp the fog value here
  1669. if (__GL_FLOAT_LTZ(pd->fog))
  1670. pd->fog = __glZero;
  1671. else if (__GL_FLOAT_COMPARE_PONE(pd->fog, >))
  1672. pd->fog = __glOne;
  1673. }
  1674. break;
  1675. }
  1676. }
  1677. #endif //GL_WIN_specular_fog
  1678. // Apply cheap fog to RGB colors.
  1679. //
  1680. // IN: fog, color (front/back)
  1681. // OUT: color (front/back)
  1682. void FASTCALL PolyArrayCheapFogRGBColor(__GLcontext *gc, POLYARRAY *pa)
  1683. {
  1684. __GLfloat fogColorR, fogColorG, fogColorB;
  1685. POLYDATA *pd, *pdLast;
  1686. GLboolean bGrayFog;
  1687. GLboolean doFrontColor, doBackColor;
  1688. if (!(gc->state.enables.general & __GL_LIGHTING_ENABLE))
  1689. {
  1690. ASSERTOPENGL(!(gc->vertex.paNeeds & PANEEDS_BACK_COLOR),
  1691. "no back color needed when lighting is disabled\n");
  1692. }
  1693. // ASSERT_PRIMITIVE
  1694. if ((unsigned int) pa->primType <= GL_LINE_STRIP)
  1695. {
  1696. doFrontColor = GL_TRUE;
  1697. doBackColor = GL_FALSE;
  1698. }
  1699. else
  1700. {
  1701. doFrontColor = gc->vertex.paNeeds & PANEEDS_FRONT_COLOR;
  1702. doBackColor = gc->vertex.paNeeds & PANEEDS_BACK_COLOR;
  1703. }
  1704. pdLast = pa->pdNextVertex-1;
  1705. fogColorR = gc->state.fog.color.r;
  1706. fogColorG = gc->state.fog.color.g;
  1707. fogColorB = gc->state.fog.color.b;
  1708. bGrayFog = (gc->state.fog.flags & __GL_FOG_GRAY_RGB) ? GL_TRUE : GL_FALSE;
  1709. PERF_CHECK(bGrayFog, "Uses non gray fog color\n");
  1710. if (bGrayFog)
  1711. {
  1712. for (pd = pa->pd0; pd <= pdLast; pd++)
  1713. {
  1714. __GLfloat fog, oneMinusFog, delta;
  1715. /* Get the vertex fog value */
  1716. fog = pd->fog;
  1717. oneMinusFog = __glOne - fog;
  1718. delta = oneMinusFog * fogColorR;
  1719. /* Now whack the color */
  1720. if (doFrontColor)
  1721. {
  1722. pd->colors[0].r = fog * pd->colors[0].r + delta;
  1723. pd->colors[0].g = fog * pd->colors[0].g + delta;
  1724. pd->colors[0].b = fog * pd->colors[0].b + delta;
  1725. }
  1726. if (doBackColor)
  1727. {
  1728. pd->colors[1].r = fog * pd->colors[1].r + delta;
  1729. pd->colors[1].g = fog * pd->colors[1].g + delta;
  1730. pd->colors[1].b = fog * pd->colors[1].b + delta;
  1731. }
  1732. }
  1733. }
  1734. else
  1735. {
  1736. for (pd = pa->pd0; pd <= pdLast; pd++)
  1737. {
  1738. __GLfloat fog, oneMinusFog;
  1739. /* Get the vertex fog value */
  1740. fog = pd->fog;
  1741. oneMinusFog = __glOne - fog;
  1742. /* Now whack the color */
  1743. if (doFrontColor)
  1744. {
  1745. pd->colors[0].r = fog * pd->colors[0].r + oneMinusFog * fogColorR;
  1746. pd->colors[0].g = fog * pd->colors[0].g + oneMinusFog * fogColorG;
  1747. pd->colors[0].b = fog * pd->colors[0].b + oneMinusFog * fogColorB;
  1748. }
  1749. if (doBackColor)
  1750. {
  1751. pd->colors[1].r = fog * pd->colors[1].r + oneMinusFog * fogColorR;
  1752. pd->colors[1].g = fog * pd->colors[1].g + oneMinusFog * fogColorG;
  1753. pd->colors[1].b = fog * pd->colors[1].b + oneMinusFog * fogColorB;
  1754. }
  1755. }
  1756. }
  1757. }
  1758. // Apply cheap fog to color index values.
  1759. //
  1760. // IN: fog, color.r (front/back)
  1761. // OUT: color.r (front/back)
  1762. void FASTCALL PolyArrayCheapFogCIColor(__GLcontext *gc, POLYARRAY *pa)
  1763. {
  1764. __GLfloat maxR, fogIndex;
  1765. POLYDATA *pd, *pdLast;
  1766. GLboolean doFrontColor, doBackColor;
  1767. if (!(gc->state.enables.general & __GL_LIGHTING_ENABLE))
  1768. {
  1769. ASSERTOPENGL(!(gc->vertex.paNeeds & PANEEDS_BACK_COLOR),
  1770. "no back color needed when lighting is disabled\n");
  1771. }
  1772. // ASSERT_PRIMITIVE
  1773. if ((unsigned int) pa->primType <= GL_LINE_STRIP)
  1774. {
  1775. doFrontColor = GL_TRUE;
  1776. doBackColor = GL_FALSE;
  1777. }
  1778. else
  1779. {
  1780. doFrontColor = gc->vertex.paNeeds & PANEEDS_FRONT_COLOR;
  1781. doBackColor = gc->vertex.paNeeds & PANEEDS_BACK_COLOR;
  1782. }
  1783. fogIndex = gc->state.fog.index;
  1784. maxR = (1 << gc->modes.indexBits) - 1;
  1785. pdLast = pa->pdNextVertex-1;
  1786. for (pd = pa->pd0; pd <= pdLast; pd++)
  1787. {
  1788. __GLfloat fogDelta;
  1789. fogDelta = (__glOne - pd->fog) * fogIndex;
  1790. /* Now whack the color */
  1791. if (doFrontColor)
  1792. {
  1793. pd->colors[0].r = pd->colors[0].r + fogDelta;
  1794. if (pd->colors[0].r > maxR)
  1795. pd->colors[0].r = maxR;
  1796. }
  1797. if (doBackColor)
  1798. {
  1799. pd->colors[1].r = pd->colors[1].r + fogDelta;
  1800. if (pd->colors[1].r > maxR)
  1801. pd->colors[1].r = maxR;
  1802. }
  1803. }
  1804. }
  1805. /****************************************************************************/
  1806. /****************************************************************************/
  1807. // Compute eye coordinates
  1808. //
  1809. // IN: obj
  1810. // OUT: eye
  1811. void FASTCALL PolyArrayProcessEye(__GLcontext *gc, POLYARRAY *pa)
  1812. {
  1813. __GLtransform *trMV;
  1814. __GLmatrix *m;
  1815. POLYDATA *pd, *pdLast;
  1816. if (pa->flags & POLYARRAY_EYE_PROCESSED)
  1817. return;
  1818. pa->flags |= POLYARRAY_EYE_PROCESSED;
  1819. trMV = gc->transform.modelView;
  1820. m = &trMV->matrix;
  1821. pdLast = pa->pdNextVertex-1;
  1822. // The primitive may contain a mix of vertex types (2,3,4)!
  1823. if (m->matrixType == __GL_MT_IDENTITY)
  1824. {
  1825. for (pd = pa->pd0; pd <= pdLast; pd++)
  1826. pd->eye = pd->obj;
  1827. }
  1828. else
  1829. {
  1830. PFN_XFORM pfnXform;
  1831. // If any incoming coords contains w coord, use xf4.
  1832. if (pa->flags & POLYARRAY_VERTEX4)
  1833. pfnXform = m->xf4;
  1834. else if (pa->flags & POLYARRAY_VERTEX3)
  1835. pfnXform = m->xf3;
  1836. else
  1837. pfnXform = m->xf2;
  1838. for (pd = pa->pd0; pd <= pdLast; pd++)
  1839. (*pfnXform)(&pd->eye, (__GLfloat *) &pd->obj, m);
  1840. }
  1841. }
  1842. /****************************************************************************/
  1843. // Process edge flags.
  1844. //
  1845. // IN: edge
  1846. // OUT: edge (all vertices)
  1847. void FASTCALL PolyArrayProcessEdgeFlag(POLYARRAY *pa)
  1848. {
  1849. POLYDATA *pd, *pdLast;
  1850. GLuint prevEdgeFlag;
  1851. PERF_CHECK(FALSE, "Uses edge flags!\n");
  1852. ASSERTOPENGL(pa->pd0->flags & POLYDATA_EDGEFLAG_VALID,
  1853. "need initial edgeflag value\n");
  1854. pdLast = pa->pdNextVertex-1;
  1855. for (pd = pa->pd0; pd <= pdLast; pd++)
  1856. {
  1857. if (pd->flags & POLYDATA_EDGEFLAG_VALID)
  1858. prevEdgeFlag = pd->flags & (POLYDATA_EDGEFLAG_VALID | POLYDATA_EDGEFLAG_BOUNDARY);
  1859. else
  1860. pd->flags |= prevEdgeFlag;
  1861. }
  1862. }
  1863. /****************************************************************************/
  1864. // transform texture coordinates
  1865. // there is no generated texture coords.
  1866. // texture coordinates are modified in place
  1867. //
  1868. // IN: texture
  1869. // OUT: texture (all vertices are updated)
  1870. void FASTCALL PolyArrayCalcTexture(__GLcontext *gc, POLYARRAY *pa)
  1871. {
  1872. __GLmatrix *m;
  1873. POLYDATA *pd, *pdLast;
  1874. PFN_XFORM xf;
  1875. ASSERTOPENGL(pa->pd0->flags & POLYDATA_TEXTURE_VALID,
  1876. "need initial texcoord value\n");
  1877. ASSERTOPENGL(pa->flags & (POLYARRAY_TEXTURE1|POLYARRAY_TEXTURE2|
  1878. POLYARRAY_TEXTURE3|POLYARRAY_TEXTURE4),
  1879. "bad paflags\n");
  1880. m = &gc->transform.texture->matrix;
  1881. pdLast = pa->pdNextVertex-1;
  1882. if (m->matrixType == __GL_MT_IDENTITY)
  1883. {
  1884. // Identity texture xform.
  1885. //Incoming texcoord already has all s,t,q,r values.
  1886. for (pd = pa->pd0; pd <= pdLast; pd++)
  1887. if (!(pd->flags & POLYDATA_TEXTURE_VALID))
  1888. pd->texture = (pd-1)->texture;
  1889. }
  1890. else
  1891. {
  1892. // If any incoming texture coords contains q coord, use xf4.
  1893. if (pa->flags & POLYARRAY_TEXTURE4)
  1894. xf = m->xf4;
  1895. else if (pa->flags & POLYARRAY_TEXTURE3)
  1896. xf = m->xf3;
  1897. else if (pa->flags & POLYARRAY_TEXTURE2)
  1898. xf = m->xf2;
  1899. else
  1900. xf = m->xf1;
  1901. for (pd = pa->pd0; pd <= pdLast; pd++)
  1902. {
  1903. // Apply texture matrix
  1904. if (pd->flags & POLYDATA_TEXTURE_VALID)
  1905. (*xf)(&pd->texture, (__GLfloat *) &pd->texture, m);
  1906. else
  1907. pd->texture = (pd-1)->texture;
  1908. }
  1909. }
  1910. }
  1911. // Generate texture coordinates from object coordinates
  1912. // object linear texture generation
  1913. // s and t are enabled but r and q are disabled
  1914. // both s and t use the object linear mode
  1915. // both s and t have the SAME plane equation
  1916. // texture coordinates are modified in place
  1917. //
  1918. // IN: texture, obj
  1919. // OUT: texture (all vertices are updated)
  1920. void FASTCALL PolyArrayCalcObjectLinearSameST(__GLcontext *gc, POLYARRAY *pa)
  1921. {
  1922. __GLmatrix *m;
  1923. __GLcoord *cs, gen;
  1924. POLYDATA *pd, *pdLast;
  1925. PFN_XFORM xf;
  1926. ASSERTOPENGL(pa->pd0->flags & POLYDATA_TEXTURE_VALID,
  1927. "need initial texcoord value\n");
  1928. ASSERTOPENGL(pa->flags & (POLYARRAY_TEXTURE1|POLYARRAY_TEXTURE2|
  1929. POLYARRAY_TEXTURE3|POLYARRAY_TEXTURE4),
  1930. "bad paflags\n");
  1931. cs = &gc->state.texture.s.objectPlaneEquation;
  1932. pdLast = pa->pdNextVertex-1;
  1933. m = &gc->transform.texture->matrix;
  1934. if (m->matrixType == __GL_MT_IDENTITY)
  1935. {
  1936. for (pd = pa->pd0; pd <= pdLast; pd++)
  1937. {
  1938. if (!(pd->flags & POLYDATA_TEXTURE_VALID))
  1939. {
  1940. pd->texture.z = (pd-1)->texture.z;
  1941. pd->texture.w = (pd-1)->texture.w;
  1942. }
  1943. // both s and t have the SAME plane equation
  1944. pd->texture.x = cs->x * pd->obj.x + cs->y * pd->obj.y +
  1945. cs->z * pd->obj.z + cs->w * pd->obj.w;
  1946. pd->texture.y = pd->texture.x;
  1947. }
  1948. }
  1949. else
  1950. {
  1951. // If any incoming texture coords contains q coord, use xf4.
  1952. if (pa->flags & POLYARRAY_TEXTURE4)
  1953. xf = m->xf4;
  1954. else if (pa->flags & POLYARRAY_TEXTURE3)
  1955. xf = m->xf3;
  1956. else
  1957. xf = m->xf2; // at least 2 generated values
  1958. for (pd = pa->pd0; pd <= pdLast; pd++)
  1959. {
  1960. if (pd->flags & POLYDATA_TEXTURE_VALID)
  1961. {
  1962. gen.z = pd->texture.z;
  1963. gen.w = pd->texture.w;
  1964. }
  1965. // both s and t have the SAME plane equation
  1966. gen.x = cs->x * pd->obj.x + cs->y * pd->obj.y +
  1967. cs->z * pd->obj.z + cs->w * pd->obj.w;
  1968. gen.y = gen.x;
  1969. // Finally, apply texture matrix
  1970. (*xf)(&pd->texture, (__GLfloat *) &gen, m);
  1971. }
  1972. }
  1973. }
  1974. // Generate texture coordinates from object coordinates
  1975. // object linear texture generation
  1976. // s and t are enabled but r and q are disabled
  1977. // both s and t use the object linear mode
  1978. // both s and t have DIFFERENT plane equations
  1979. // texture coordinates are modified in place
  1980. //
  1981. // IN: texture, obj
  1982. // OUT: texture (all vertices are updated)
  1983. void FASTCALL PolyArrayCalcObjectLinear(__GLcontext *gc, POLYARRAY *pa)
  1984. {
  1985. __GLmatrix *m;
  1986. __GLcoord *cs, *ct, gen;
  1987. POLYDATA *pd, *pdLast;
  1988. PFN_XFORM xf;
  1989. ASSERTOPENGL(pa->pd0->flags & POLYDATA_TEXTURE_VALID,
  1990. "need initial texcoord value\n");
  1991. ASSERTOPENGL(pa->flags & (POLYARRAY_TEXTURE1|POLYARRAY_TEXTURE2|
  1992. POLYARRAY_TEXTURE3|POLYARRAY_TEXTURE4),
  1993. "bad paflags\n");
  1994. cs = &gc->state.texture.s.objectPlaneEquation;
  1995. ct = &gc->state.texture.t.objectPlaneEquation;
  1996. pdLast = pa->pdNextVertex-1;
  1997. m = &gc->transform.texture->matrix;
  1998. if (m->matrixType == __GL_MT_IDENTITY)
  1999. {
  2000. for (pd = pa->pd0; pd <= pdLast; pd++)
  2001. {
  2002. if (!(pd->flags & POLYDATA_TEXTURE_VALID))
  2003. {
  2004. pd->texture.z = (pd-1)->texture.z;
  2005. pd->texture.w = (pd-1)->texture.w;
  2006. }
  2007. pd->texture.x = cs->x * pd->obj.x + cs->y * pd->obj.y +
  2008. cs->z * pd->obj.z + cs->w * pd->obj.w;
  2009. pd->texture.y = ct->x * pd->obj.x + ct->y * pd->obj.y +
  2010. ct->z * pd->obj.z + ct->w * pd->obj.w;
  2011. }
  2012. }
  2013. else
  2014. {
  2015. // If any incoming texture coords contains q coord, use xf4.
  2016. if (pa->flags & POLYARRAY_TEXTURE4)
  2017. xf = m->xf4;
  2018. else if (pa->flags & POLYARRAY_TEXTURE3)
  2019. xf = m->xf3;
  2020. else
  2021. xf = m->xf2; // at least 2 generated values
  2022. for (pd = pa->pd0; pd <= pdLast; pd++)
  2023. {
  2024. if (pd->flags & POLYDATA_TEXTURE_VALID)
  2025. {
  2026. gen.z = pd->texture.z;
  2027. gen.w = pd->texture.w;
  2028. }
  2029. gen.x = cs->x * pd->obj.x + cs->y * pd->obj.y +
  2030. cs->z * pd->obj.z + cs->w * pd->obj.w;
  2031. gen.y = ct->x * pd->obj.x + ct->y * pd->obj.y +
  2032. ct->z * pd->obj.z + ct->w * pd->obj.w;
  2033. // Finally, apply texture matrix
  2034. (*xf)(&pd->texture, (__GLfloat *) &gen, m);
  2035. }
  2036. }
  2037. }
  2038. // Generate texture coordinates from eye coordinates
  2039. // eye linear texture generation
  2040. // s and t are enabled but r and q are disabled
  2041. // both s and t use the eye linear mode
  2042. // both s and t have SAME plane equations
  2043. // texture coordinates are modified in place
  2044. // we may be able to get away without computing eye coord!
  2045. //
  2046. // IN: texture; obj or eye
  2047. // OUT: texture and eye (all vertices are updated)
  2048. void FASTCALL PolyArrayCalcEyeLinearSameST(__GLcontext *gc, POLYARRAY *pa)
  2049. {
  2050. __GLmatrix *m;
  2051. __GLcoord *cs, gen;
  2052. POLYDATA *pd, *pdLast;
  2053. PFN_XFORM xf;
  2054. ASSERTOPENGL(pa->pd0->flags & POLYDATA_TEXTURE_VALID,
  2055. "need initial texcoord value\n");
  2056. ASSERTOPENGL(pa->flags & (POLYARRAY_TEXTURE1|POLYARRAY_TEXTURE2|
  2057. POLYARRAY_TEXTURE3|POLYARRAY_TEXTURE4),
  2058. "bad paflags\n");
  2059. // Compute eye coord first
  2060. if (!(pa->flags & POLYARRAY_EYE_PROCESSED))
  2061. PolyArrayProcessEye(gc, pa);
  2062. cs = &gc->state.texture.s.eyePlaneEquation;
  2063. pdLast = pa->pdNextVertex-1;
  2064. m = &gc->transform.texture->matrix;
  2065. if (m->matrixType == __GL_MT_IDENTITY)
  2066. {
  2067. for (pd = pa->pd0; pd <= pdLast; pd++)
  2068. {
  2069. if (!(pd->flags & POLYDATA_TEXTURE_VALID))
  2070. {
  2071. pd->texture.z = (pd-1)->texture.z;
  2072. pd->texture.w = (pd-1)->texture.w;
  2073. }
  2074. // both s and t have the SAME plane equation
  2075. pd->texture.x = cs->x * pd->eye.x + cs->y * pd->eye.y +
  2076. cs->z * pd->eye.z + cs->w * pd->eye.w;
  2077. pd->texture.y = pd->texture.x;
  2078. }
  2079. }
  2080. else
  2081. {
  2082. // If any incoming texture coords contains q coord, use xf4.
  2083. if (pa->flags & POLYARRAY_TEXTURE4)
  2084. xf = m->xf4;
  2085. else if (pa->flags & POLYARRAY_TEXTURE3)
  2086. xf = m->xf3;
  2087. else
  2088. xf = m->xf2; // at least 2 generated values
  2089. for (pd = pa->pd0; pd <= pdLast; pd++)
  2090. {
  2091. if (pd->flags & POLYDATA_TEXTURE_VALID)
  2092. {
  2093. gen.z = pd->texture.z;
  2094. gen.w = pd->texture.w;
  2095. }
  2096. // both s and t have the SAME plane equation
  2097. gen.x = cs->x * pd->eye.x + cs->y * pd->eye.y +
  2098. cs->z * pd->eye.z + cs->w * pd->eye.w;
  2099. gen.y = gen.x;
  2100. // Finally, apply texture matrix
  2101. (*xf)(&pd->texture, (__GLfloat *) &gen, m);
  2102. }
  2103. }
  2104. }
  2105. // Generate texture coordinates from eye coordinates
  2106. // eye linear texture generation
  2107. // s and t are enabled but r and q are disabled
  2108. // both s and t use the eye linear mode
  2109. // both s and t have SAME plane equations
  2110. // texture coordinates are modified in place
  2111. // we may be able to get away without computing eye coord!
  2112. //
  2113. // IN: texture; obj or eye
  2114. // OUT: texture and eye (all vertices are updated)
  2115. void FASTCALL PolyArrayCalcEyeLinear(__GLcontext *gc, POLYARRAY *pa)
  2116. {
  2117. __GLmatrix *m;
  2118. __GLcoord *cs, *ct, gen;
  2119. POLYDATA *pd, *pdLast;
  2120. PFN_XFORM xf;
  2121. ASSERTOPENGL(pa->pd0->flags & POLYDATA_TEXTURE_VALID,
  2122. "need initial texcoord value\n");
  2123. ASSERTOPENGL(pa->flags & (POLYARRAY_TEXTURE1|POLYARRAY_TEXTURE2|
  2124. POLYARRAY_TEXTURE3|POLYARRAY_TEXTURE4),
  2125. "bad paflags\n");
  2126. // Compute eye coord first
  2127. if (!(pa->flags & POLYARRAY_EYE_PROCESSED))
  2128. PolyArrayProcessEye(gc, pa);
  2129. cs = &gc->state.texture.s.eyePlaneEquation;
  2130. ct = &gc->state.texture.t.eyePlaneEquation;
  2131. pdLast = pa->pdNextVertex-1;
  2132. m = &gc->transform.texture->matrix;
  2133. if (m->matrixType == __GL_MT_IDENTITY)
  2134. {
  2135. for (pd = pa->pd0; pd <= pdLast; pd++)
  2136. {
  2137. if (!(pd->flags & POLYDATA_TEXTURE_VALID))
  2138. {
  2139. pd->texture.z = (pd-1)->texture.z;
  2140. pd->texture.w = (pd-1)->texture.w;
  2141. }
  2142. pd->texture.x = cs->x * pd->eye.x + cs->y * pd->eye.y +
  2143. cs->z * pd->eye.z + cs->w * pd->eye.w;
  2144. pd->texture.y = ct->x * pd->eye.x + ct->y * pd->eye.y +
  2145. ct->z * pd->eye.z + ct->w * pd->eye.w;
  2146. }
  2147. }
  2148. else
  2149. {
  2150. // If any incoming texture coords contains q coord, use xf4.
  2151. if (pa->flags & POLYARRAY_TEXTURE4)
  2152. xf = m->xf4;
  2153. else if (pa->flags & POLYARRAY_TEXTURE3)
  2154. xf = m->xf3;
  2155. else
  2156. xf = m->xf2; // at least 2 generated values
  2157. for (pd = pa->pd0; pd <= pdLast; pd++)
  2158. {
  2159. if (pd->flags & POLYDATA_TEXTURE_VALID)
  2160. {
  2161. gen.z = pd->texture.z;
  2162. gen.w = pd->texture.w;
  2163. }
  2164. gen.x = cs->x * pd->eye.x + cs->y * pd->eye.y +
  2165. cs->z * pd->eye.z + cs->w * pd->eye.w;
  2166. gen.y = ct->x * pd->eye.x + ct->y * pd->eye.y +
  2167. ct->z * pd->eye.z + ct->w * pd->eye.w;
  2168. // Finally, apply texture matrix
  2169. (*xf)(&pd->texture, (__GLfloat *) &gen, m);
  2170. }
  2171. }
  2172. }
  2173. // Compute the s & t coordinates for a sphere map. The s & t values
  2174. // are stored in "result" even if both coordinates are not being
  2175. // generated. The caller picks the right values out.
  2176. //
  2177. // IN: eye, normal
  2178. void FASTCALL PASphereGen(POLYDATA *pd, __GLcoord *result)
  2179. {
  2180. __GLcoord u, r;
  2181. __GLfloat m, ndotu;
  2182. // Get unit vector from origin to the vertex in eye coordinates into u
  2183. __glNormalize(&u.x, &pd->eye.x);
  2184. // Dot the normal with the unit position u
  2185. ndotu = pd->normal.x * u.x + pd->normal.y * u.y + pd->normal.z * u.z;
  2186. // Compute r
  2187. r.x = u.x - 2 * pd->normal.x * ndotu;
  2188. r.y = u.y - 2 * pd->normal.y * ndotu;
  2189. r.z = u.z - 2 * pd->normal.z * ndotu;
  2190. // Compute m
  2191. m = 2 * __GL_SQRTF(r.x*r.x + r.y*r.y + (r.z + 1) * (r.z + 1));
  2192. if (m)
  2193. {
  2194. result->x = r.x / m + __glHalf;
  2195. result->y = r.y / m + __glHalf;
  2196. }
  2197. else
  2198. {
  2199. result->x = __glHalf;
  2200. result->y = __glHalf;
  2201. }
  2202. }
  2203. // Generate texture coordinates for sphere map
  2204. // sphere map texture generation
  2205. // s and t are enabled but r and q are disabled
  2206. // both s and t use the sphere map mode
  2207. // texture coordinates are modified in place
  2208. // we may be able to get away without computing eye coord!
  2209. //
  2210. // IN: texture; obj or eye; normal
  2211. // OUT: texture and eye (all vertices are updated)
  2212. void FASTCALL PolyArrayCalcSphereMap(__GLcontext *gc, POLYARRAY *pa)
  2213. {
  2214. __GLmatrix *m;
  2215. __GLcoord gen;
  2216. POLYDATA *pd, *pdLast, *pdNormal;
  2217. PFN_XFORM xf;
  2218. GLboolean bIdentity;
  2219. // this is really okay
  2220. PERF_CHECK(FALSE, "Uses sphere map texture generation!\n");
  2221. ASSERTOPENGL(pa->pd0->flags & POLYDATA_TEXTURE_VALID,
  2222. "need initial texcoord value\n");
  2223. ASSERTOPENGL(pa->pd0->flags & POLYDATA_NORMAL_VALID,
  2224. "need initial normal\n");
  2225. ASSERTOPENGL(pa->flags & (POLYARRAY_TEXTURE1|POLYARRAY_TEXTURE2|
  2226. POLYARRAY_TEXTURE3|POLYARRAY_TEXTURE4),
  2227. "bad paflags\n");
  2228. // Compute eye coord first
  2229. if (!(pa->flags & POLYARRAY_EYE_PROCESSED))
  2230. PolyArrayProcessEye(gc, pa);
  2231. m = &gc->transform.texture->matrix;
  2232. bIdentity = (m->matrixType == __GL_MT_IDENTITY);
  2233. // If any incoming texture coords contains q coord, use xf4.
  2234. if (pa->flags & POLYARRAY_TEXTURE4)
  2235. xf = m->xf4;
  2236. else if (pa->flags & POLYARRAY_TEXTURE3)
  2237. xf = m->xf3;
  2238. else
  2239. xf = m->xf2; // at least 2 generated values
  2240. pdLast = pa->pdNextVertex-1;
  2241. for (pd = pa->pd0; pd <= pdLast; pd++)
  2242. {
  2243. if (pd->flags & POLYDATA_TEXTURE_VALID)
  2244. {
  2245. gen.z = pd->texture.z;
  2246. gen.w = pd->texture.w;
  2247. }
  2248. if (pd->flags & POLYDATA_NORMAL_VALID)
  2249. {
  2250. // track current normal
  2251. pdNormal = pd;
  2252. }
  2253. else
  2254. {
  2255. // pd->flags |= POLYDATA_NORMAL_VALID;
  2256. pd->normal.x = pdNormal->normal.x;
  2257. pd->normal.y = pdNormal->normal.y;
  2258. pd->normal.z = pdNormal->normal.z;
  2259. }
  2260. PASphereGen(pd, &gen); // compute s, t values
  2261. // Finally, apply texture matrix
  2262. if (!bIdentity)
  2263. (*xf)(&pd->texture, (__GLfloat *) &gen, m);
  2264. else
  2265. pd->texture = gen;
  2266. }
  2267. }
  2268. // Transform or compute the texture coordinates for the polyarray
  2269. // It handles all texture generation modes. Texture coordinates are
  2270. // generated (if necessary) and transformed.
  2271. // Note that texture coordinates are modified in place.
  2272. //
  2273. // IN: texture (always)
  2274. // obj in GL_OBJECT_LINEAR mode
  2275. // obj or eye in GL_EYE_LINEAR mode
  2276. // obj or eye; normal in GL_SPHERE_MAP mode
  2277. // OUT: texture (all vertices are updated)
  2278. // eye in GL_EYE_LINEAR and GL_SPHERE_MAP modes (all vertices
  2279. // are updated)
  2280. void FASTCALL PolyArrayCalcMixedTexture(__GLcontext *gc, POLYARRAY *pa)
  2281. {
  2282. __GLmatrix *m;
  2283. GLuint enables;
  2284. POLYDATA *pd, *pdLast, *pdNormal;
  2285. PFN_XFORM xf;
  2286. BOOL needNormal, didSphereGen;
  2287. __GLcoord savedTexture, sphereCoord, *c;
  2288. GLboolean bIdentity;
  2289. enables = gc->state.enables.general;
  2290. PERF_CHECK
  2291. (
  2292. !(enables & (__GL_TEXTURE_GEN_R_ENABLE | __GL_TEXTURE_GEN_Q_ENABLE)),
  2293. "Uses r, q texture generation!\n"
  2294. );
  2295. if ((enables & __GL_TEXTURE_GEN_S_ENABLE)
  2296. && (enables & __GL_TEXTURE_GEN_T_ENABLE)
  2297. && (gc->state.texture.s.mode != gc->state.texture.t.mode))
  2298. {
  2299. PERF_CHECK(FALSE, "Uses different s and t tex gen modes!\n");
  2300. }
  2301. ASSERTOPENGL(pa->pd0->flags & POLYDATA_TEXTURE_VALID,
  2302. "need initial texcoord value\n");
  2303. ASSERTOPENGL(pa->flags & (POLYARRAY_TEXTURE1|POLYARRAY_TEXTURE2|
  2304. POLYARRAY_TEXTURE3|POLYARRAY_TEXTURE4),
  2305. "bad paflags\n");
  2306. if ((enables & __GL_TEXTURE_GEN_S_ENABLE) && (gc->state.texture.s.mode == GL_SPHERE_MAP)
  2307. || (enables & __GL_TEXTURE_GEN_T_ENABLE) && (gc->state.texture.t.mode == GL_SPHERE_MAP))
  2308. {
  2309. ASSERTOPENGL(pa->pd0->flags & POLYDATA_NORMAL_VALID,
  2310. "need initial normal\n");
  2311. needNormal = TRUE;
  2312. }
  2313. else
  2314. {
  2315. needNormal = FALSE;
  2316. }
  2317. // Compute eye coord first
  2318. if (!(pa->flags & POLYARRAY_EYE_PROCESSED))
  2319. {
  2320. if ((enables & __GL_TEXTURE_GEN_S_ENABLE)
  2321. && (gc->state.texture.s.mode != GL_OBJECT_LINEAR)
  2322. || (enables & __GL_TEXTURE_GEN_T_ENABLE)
  2323. && (gc->state.texture.t.mode != GL_OBJECT_LINEAR)
  2324. || (enables & __GL_TEXTURE_GEN_R_ENABLE)
  2325. && (gc->state.texture.r.mode != GL_OBJECT_LINEAR)
  2326. || (enables & __GL_TEXTURE_GEN_Q_ENABLE)
  2327. && (gc->state.texture.q.mode != GL_OBJECT_LINEAR))
  2328. PolyArrayProcessEye(gc, pa);
  2329. }
  2330. m = &gc->transform.texture->matrix;
  2331. bIdentity = (m->matrixType == __GL_MT_IDENTITY);
  2332. // If any incoming texture coords contains q coord, use xf4.
  2333. if (pa->flags & POLYARRAY_TEXTURE4 || enables & __GL_TEXTURE_GEN_Q_ENABLE)
  2334. xf = m->xf4;
  2335. else if (pa->flags & POLYARRAY_TEXTURE3 || enables & __GL_TEXTURE_GEN_R_ENABLE)
  2336. xf = m->xf3;
  2337. else if (pa->flags & POLYARRAY_TEXTURE2 || enables & __GL_TEXTURE_GEN_T_ENABLE)
  2338. xf = m->xf2;
  2339. else
  2340. xf = m->xf1;
  2341. pdLast = pa->pdNextVertex-1;
  2342. for (pd = pa->pd0; pd <= pdLast; pd++)
  2343. {
  2344. // texture coordinates are modified in place.
  2345. // save the valid values to use for the invalid entries.
  2346. if (pd->flags & POLYDATA_TEXTURE_VALID)
  2347. savedTexture = pd->texture;
  2348. else
  2349. pd->texture = savedTexture;
  2350. if (needNormal)
  2351. {
  2352. if (pd->flags & POLYDATA_NORMAL_VALID)
  2353. {
  2354. // track current normal
  2355. pdNormal = pd;
  2356. }
  2357. else
  2358. {
  2359. // pd->flags |= POLYDATA_NORMAL_VALID;
  2360. pd->normal.x = pdNormal->normal.x;
  2361. pd->normal.y = pdNormal->normal.y;
  2362. pd->normal.z = pdNormal->normal.z;
  2363. }
  2364. }
  2365. didSphereGen = GL_FALSE;
  2366. /* Generate s coordinate */
  2367. if (enables & __GL_TEXTURE_GEN_S_ENABLE)
  2368. {
  2369. if (gc->state.texture.s.mode == GL_EYE_LINEAR)
  2370. {
  2371. c = &gc->state.texture.s.eyePlaneEquation;
  2372. pd->texture.x = c->x * pd->eye.x + c->y * pd->eye.y
  2373. + c->z * pd->eye.z + c->w * pd->eye.w;
  2374. }
  2375. else if (gc->state.texture.s.mode == GL_OBJECT_LINEAR)
  2376. {
  2377. // the primitive may contain a mix of vertex types (2,3,4)!
  2378. c = &gc->state.texture.s.objectPlaneEquation;
  2379. pd->texture.x = c->x * pd->obj.x + c->y * pd->obj.y +
  2380. c->z * pd->obj.z + c->w * pd->obj.w;
  2381. }
  2382. else
  2383. {
  2384. ASSERTOPENGL(gc->state.texture.s.mode == GL_SPHERE_MAP,
  2385. "invalide texture s mode");
  2386. PASphereGen(pd, &sphereCoord); // compute s, t values
  2387. pd->texture.x = sphereCoord.x;
  2388. didSphereGen = GL_TRUE;
  2389. }
  2390. }
  2391. /* Generate t coordinate */
  2392. if (enables & __GL_TEXTURE_GEN_T_ENABLE)
  2393. {
  2394. if (gc->state.texture.t.mode == GL_EYE_LINEAR)
  2395. {
  2396. c = &gc->state.texture.t.eyePlaneEquation;
  2397. pd->texture.y = c->x * pd->eye.x + c->y * pd->eye.y
  2398. + c->z * pd->eye.z + c->w * pd->eye.w;
  2399. }
  2400. else if (gc->state.texture.t.mode == GL_OBJECT_LINEAR)
  2401. {
  2402. // the primitive may contain a mix of vertex types (2,3,4)!
  2403. c = &gc->state.texture.t.objectPlaneEquation;
  2404. pd->texture.y = c->x * pd->obj.x + c->y * pd->obj.y +
  2405. c->z * pd->obj.z + c->w * pd->obj.w;
  2406. }
  2407. else
  2408. {
  2409. ASSERTOPENGL(gc->state.texture.t.mode == GL_SPHERE_MAP,
  2410. "invalide texture t mode");
  2411. if (!didSphereGen)
  2412. PASphereGen(pd, &sphereCoord); // compute s, t values
  2413. pd->texture.y = sphereCoord.y;
  2414. }
  2415. }
  2416. /* Generate r coordinate */
  2417. if (enables & __GL_TEXTURE_GEN_R_ENABLE)
  2418. {
  2419. if (gc->state.texture.r.mode == GL_EYE_LINEAR)
  2420. {
  2421. c = &gc->state.texture.r.eyePlaneEquation;
  2422. pd->texture.z = c->x * pd->eye.x + c->y * pd->eye.y
  2423. + c->z * pd->eye.z + c->w * pd->eye.w;
  2424. }
  2425. else
  2426. {
  2427. ASSERTOPENGL(gc->state.texture.r.mode == GL_OBJECT_LINEAR,
  2428. "invalide texture r mode");
  2429. // the primitive may contain a mix of vertex types (2,3,4)!
  2430. c = &gc->state.texture.r.objectPlaneEquation;
  2431. pd->texture.z = c->x * pd->obj.x + c->y * pd->obj.y +
  2432. c->z * pd->obj.z + c->w * pd->obj.w;
  2433. }
  2434. }
  2435. /* Generate q coordinate */
  2436. if (enables & __GL_TEXTURE_GEN_Q_ENABLE)
  2437. {
  2438. if (gc->state.texture.q.mode == GL_EYE_LINEAR)
  2439. {
  2440. c = &gc->state.texture.q.eyePlaneEquation;
  2441. pd->texture.w = c->x * pd->eye.x + c->y * pd->eye.y
  2442. + c->z * pd->eye.z + c->w * pd->eye.w;
  2443. }
  2444. else
  2445. {
  2446. ASSERTOPENGL(gc->state.texture.q.mode == GL_OBJECT_LINEAR,
  2447. "invalide texture q mode");
  2448. // the primitive may contain a mix of vertex types (2,3,4)!
  2449. c = &gc->state.texture.q.objectPlaneEquation;
  2450. pd->texture.w = c->x * pd->obj.x + c->y * pd->obj.y +
  2451. c->z * pd->obj.z + c->w * pd->obj.w;
  2452. }
  2453. }
  2454. /* Finally, apply texture matrix */
  2455. if (!bIdentity)
  2456. (*xf)(&pd->texture, (__GLfloat *) &pd->texture, m);
  2457. }
  2458. }
  2459. /****************************************************************************/
  2460. // Cache whatever values are possible for the current material and lights.
  2461. // This will let us avoid doing these computations for each primitive.
  2462. void FASTCALL PolyArrayCalcLightCache(__GLcontext *gc)
  2463. {
  2464. __GLcolor baseEmissiveAmbient;
  2465. __GLmaterialMachine *msm;
  2466. __GLlightSourceMachine *lsm;
  2467. __GLlightSourcePerMaterialMachine *lspmm;
  2468. GLuint face;
  2469. for (face = __GL_FRONTFACE; face <= __GL_BACKFACE; face++) {
  2470. if (face == __GL_FRONTFACE) {
  2471. if (!(gc->vertex.paNeeds & PANEEDS_FRONT_COLOR))
  2472. continue;
  2473. msm = &gc->light.front;
  2474. }
  2475. else {
  2476. if (!(gc->vertex.paNeeds & PANEEDS_BACK_COLOR))
  2477. return;
  2478. msm = &gc->light.back;
  2479. }
  2480. msm->cachedEmissiveAmbient.r = msm->paSceneColor.r;
  2481. msm->cachedEmissiveAmbient.g = msm->paSceneColor.g;
  2482. msm->cachedEmissiveAmbient.b = msm->paSceneColor.b;
  2483. // add invarient per-light per-material cached ambient
  2484. for (lsm = gc->light.sources; lsm; lsm = lsm->next)
  2485. {
  2486. lspmm = &lsm->front + face;
  2487. msm->cachedEmissiveAmbient.r += lspmm->ambient.r;
  2488. msm->cachedEmissiveAmbient.g += lspmm->ambient.g;
  2489. msm->cachedEmissiveAmbient.b += lspmm->ambient.b;
  2490. }
  2491. __GL_CLAMP_RGB(msm->cachedNonLit.r,
  2492. msm->cachedNonLit.g,
  2493. msm->cachedNonLit.b,
  2494. gc,
  2495. msm->cachedEmissiveAmbient.r,
  2496. msm->cachedEmissiveAmbient.g,
  2497. msm->cachedEmissiveAmbient.b);
  2498. }
  2499. }
  2500. /****************************************************************************/
  2501. // Apply the accumulated material changes to a vertex
  2502. void FASTCALL PAApplyMaterial(__GLcontext *gc, __GLmatChange *mat, GLint face)
  2503. {
  2504. __GLmaterialState *ms;
  2505. GLuint changeBits;
  2506. PERF_CHECK(FALSE, "Primitives contain glMaterial calls!\n");
  2507. // Don't modify color materials if they are in effect!
  2508. if (face == __GL_FRONTFACE)
  2509. {
  2510. ms = &gc->state.light.front;
  2511. changeBits = mat->dirtyBits & ~gc->light.front.colorMaterialChange;
  2512. }
  2513. else
  2514. {
  2515. ms = &gc->state.light.back;
  2516. changeBits = mat->dirtyBits & ~gc->light.back.colorMaterialChange;
  2517. }
  2518. if (changeBits & __GL_MATERIAL_AMBIENT)
  2519. ms->ambient = mat->ambient;
  2520. if (changeBits & __GL_MATERIAL_DIFFUSE)
  2521. ms->diffuse = mat->diffuse;
  2522. if (changeBits & __GL_MATERIAL_SPECULAR)
  2523. ms->specular = mat->specular;
  2524. if (changeBits & __GL_MATERIAL_EMISSIVE)
  2525. {
  2526. ms->emissive.r = mat->emissive.r * gc->redVertexScale;
  2527. ms->emissive.g = mat->emissive.g * gc->greenVertexScale;
  2528. ms->emissive.b = mat->emissive.b * gc->blueVertexScale;
  2529. ms->emissive.a = mat->emissive.a * gc->alphaVertexScale;
  2530. }
  2531. if (changeBits & __GL_MATERIAL_SHININESS)
  2532. ms->specularExponent = mat->shininess;
  2533. if (changeBits & __GL_MATERIAL_COLORINDEXES)
  2534. {
  2535. ms->cmapa = mat->cmapa;
  2536. ms->cmapd = mat->cmapd;
  2537. ms->cmaps = mat->cmaps;
  2538. }
  2539. // Re-calculate the precomputed values. This works for RGBA and CI modes.
  2540. if (face == __GL_FRONTFACE)
  2541. __glValidateMaterial(gc, (GLint) changeBits, 0);
  2542. else
  2543. __glValidateMaterial(gc, 0, (GLint) changeBits);
  2544. // Recompute cached RGB material values:
  2545. PolyArrayCalcLightCache(gc);
  2546. }
  2547. void FASTCALL PolyArrayApplyMaterials(__GLcontext *gc, POLYARRAY *pa)
  2548. {
  2549. __GLmatChange matChange, *pdMat;
  2550. GLuint matMask;
  2551. POLYDATA *pd, *pdN;
  2552. GLint face;
  2553. POLYMATERIAL *pm;
  2554. pm = GLTEB_CLTPOLYMATERIAL();
  2555. // Need to apply material changes defined after the last vertex!
  2556. pdN = pa->pdNextVertex;
  2557. // ASSERT_FACE
  2558. for (face = __GL_BACKFACE, matMask = POLYARRAY_MATERIAL_BACK;
  2559. face >= 0;
  2560. face--, matMask = POLYARRAY_MATERIAL_FRONT
  2561. )
  2562. {
  2563. if (!(pa->flags & matMask))
  2564. continue;
  2565. // Accumulate all changes into one material change record
  2566. // We need to process (n + 1) vertices for material changes!
  2567. matChange.dirtyBits = 0;
  2568. for (pd = pa->pd0; pd <= pdN; pd++)
  2569. {
  2570. // ASSERT_MATERIAL
  2571. if (pd->flags & matMask)
  2572. {
  2573. GLuint dirtyBits;
  2574. pdMat = *(&pm->pdMaterial0[pd - pa->pdBuffer0].front + face);
  2575. dirtyBits = pdMat->dirtyBits;
  2576. matChange.dirtyBits |= dirtyBits;
  2577. if (dirtyBits & __GL_MATERIAL_AMBIENT)
  2578. matChange.ambient = pdMat->ambient;
  2579. if (dirtyBits & __GL_MATERIAL_DIFFUSE)
  2580. matChange.diffuse = pdMat->diffuse;
  2581. if (dirtyBits & __GL_MATERIAL_SPECULAR)
  2582. matChange.specular = pdMat->specular;
  2583. if (dirtyBits & __GL_MATERIAL_EMISSIVE)
  2584. matChange.emissive = pdMat->emissive;
  2585. if (dirtyBits & __GL_MATERIAL_SHININESS)
  2586. matChange.shininess = pdMat->shininess;
  2587. if (dirtyBits & __GL_MATERIAL_COLORINDEXES)
  2588. {
  2589. matChange.cmapa = pdMat->cmapa;
  2590. matChange.cmapd = pdMat->cmapd;
  2591. matChange.cmaps = pdMat->cmaps;
  2592. }
  2593. }
  2594. }
  2595. // apply material changes for this face
  2596. PAApplyMaterial(gc, &matChange, face);
  2597. }
  2598. }
  2599. /****************************************************************************/
  2600. #ifndef __GL_ASM_POLYARRAYFILLINDEX0
  2601. // Fill the index values with 0
  2602. //
  2603. // IN: none
  2604. // OUT: colors[face].r (all vertices are updated)
  2605. void FASTCALL PolyArrayFillIndex0(__GLcontext *gc, POLYARRAY *pa, GLint face)
  2606. {
  2607. POLYDATA *pd, *pdLast;
  2608. ASSERTOPENGL((GLuint) face <= 1, "bad face value\n");
  2609. pdLast = pa->pdNextVertex-1;
  2610. for (pd = pa->pd0; pd <= pdLast; pd++)
  2611. {
  2612. pd->colors[face].r = __glZero;
  2613. }
  2614. }
  2615. #endif // __GL_ASM_POLYARRAYFILLINDEX0
  2616. #ifndef __GL_ASM_POLYARRAYFILLCOLOR0
  2617. // Fill the color values with 0,0,0,0
  2618. //
  2619. // IN: none
  2620. // OUT: colors[face] (all vertices are updated)
  2621. void FASTCALL PolyArrayFillColor0(__GLcontext *gc, POLYARRAY *pa, GLint face)
  2622. {
  2623. POLYDATA *pd, *pdLast;
  2624. ASSERTOPENGL((GLuint) face <= 1, "bad face value\n");
  2625. pdLast = pa->pdNextVertex-1;
  2626. for (pd = pa->pd0; pd <= pdLast; pd++)
  2627. {
  2628. pd->colors[face].r = __glZero;
  2629. pd->colors[face].g = __glZero;
  2630. pd->colors[face].b = __glZero;
  2631. pd->colors[face].a = __glZero;
  2632. }
  2633. }
  2634. #endif // __GL_ASM_POLYARRAYFILLCOLOR0
  2635. #ifndef __GL_ASM_POLYARRAYPROPAGATESAMECOLOR
  2636. // All vertices have the same color values.
  2637. // Clamp and scale the current color using the color buffer scales.
  2638. // From here on out the colors in the vertex are in their final form.
  2639. //
  2640. // Note: The first vertex must have a valid color!
  2641. // Back color is not needed when lighting is disabled.
  2642. //
  2643. // IN: color (front)
  2644. // OUT: color (front) (all vertices are updated)
  2645. void FASTCALL PolyArrayPropagateSameColor(__GLcontext *gc, POLYARRAY *pa)
  2646. {
  2647. POLYDATA *pd, *pdLast;
  2648. __GLfloat r, g, b, a;
  2649. pdLast = pa->pdNextVertex-1;
  2650. pd = pa->pd0;
  2651. if (pd > pdLast)
  2652. return;
  2653. ASSERTOPENGL(pd->flags & POLYDATA_COLOR_VALID, "no initial color\n");
  2654. if (pa->flags & POLYARRAY_CLAMP_COLOR) {
  2655. __GL_CLAMP_RGBA(pd->colors[0].r,
  2656. pd->colors[0].g,
  2657. pd->colors[0].b,
  2658. pd->colors[0].a,
  2659. gc,
  2660. pd->colors[0].r,
  2661. pd->colors[0].g,
  2662. pd->colors[0].b,
  2663. pd->colors[0].a);
  2664. }
  2665. r = pd->colors[0].r;
  2666. g = pd->colors[0].g;
  2667. b = pd->colors[0].b;
  2668. a = pd->colors[0].a;
  2669. for (pd = pd + 1 ; pd <= pdLast; pd++)
  2670. {
  2671. pd->colors[0].r = r;
  2672. pd->colors[0].g = g;
  2673. pd->colors[0].b = b;
  2674. pd->colors[0].a = a;
  2675. }
  2676. }
  2677. #endif // __GL_ASM_POLYARRAYPROPAGATESAMECOLOR
  2678. #ifndef __GL_ASM_POLYARRAYPROPAGATESAMEINDEX
  2679. // All vertices have the same index values.
  2680. // Mask the index values befor color clipping
  2681. // SGIBUG: The sample implementation fails to do this!
  2682. //
  2683. // Note: The first vertex must have a valid color index!
  2684. // Back color is not needed when lighting is disabled.
  2685. //
  2686. // IN: color.r (front)
  2687. // OUT: color.r (front) (all vertices are updated)
  2688. void FASTCALL PolyArrayPropagateSameIndex(__GLcontext *gc, POLYARRAY *pa)
  2689. {
  2690. POLYDATA *pd, *pdLast;
  2691. __GLfloat index;
  2692. pdLast = pa->pdNextVertex-1;
  2693. pd = pa->pd0;
  2694. if (pd > pdLast)
  2695. return;
  2696. ASSERTOPENGL(pd->flags & POLYDATA_COLOR_VALID, "no initial color index\n");
  2697. if (pa->flags & POLYARRAY_CLAMP_COLOR) {
  2698. __GL_CLAMP_CI(pd->colors[0].r, gc, pd->colors[0].r);
  2699. }
  2700. index = pd->colors[0].r;
  2701. for (pd = pd + 1; pd <= pdLast; pd++)
  2702. {
  2703. pd->colors[0].r = index;
  2704. }
  2705. }
  2706. #endif // __GL_ASM_POLYARRAYPROPAGATESAMEINDEX
  2707. #ifndef __GL_ASM_POLYARRAYPROPAGATEINDEX
  2708. // Propagate the valid CI colors through the vertex buffer.
  2709. //
  2710. // IN: color.r (front)
  2711. // OUT: color.r (front) (all vertices are updated)
  2712. void FASTCALL PolyArrayPropagateIndex(__GLcontext *gc, POLYARRAY *pa)
  2713. {
  2714. POLYDATA *pd, *pdLast;
  2715. if (pa->flags & POLYARRAY_CLAMP_COLOR) {
  2716. pdLast = pa->pdNextVertex-1;
  2717. for (pd = pa->pd0; pd <= pdLast; pd++)
  2718. {
  2719. if (!(pd->flags & POLYDATA_COLOR_VALID))
  2720. {
  2721. // If color has not changed for this vertex,
  2722. // use the previously computed color.
  2723. ASSERTOPENGL(pd != pa->pd0, "no initial color index\n");
  2724. pd->colors[0].r = (pd-1)->colors[0].r;
  2725. continue;
  2726. }
  2727. __GL_CLAMP_CI(pd->colors[0].r, gc, pd->colors[0].r);
  2728. }
  2729. } else {
  2730. // If all incoming vertices have valid colors, we are done.
  2731. if ((pa->flags & POLYARRAY_SAME_POLYDATA_TYPE)
  2732. && (pa->pdCurColor != pa->pd0)
  2733. // Need to test 2nd vertex because pdCurColor may have been
  2734. // advanced as a result of combining Color command after End
  2735. && ((pa->pd0 + 1)->flags & POLYDATA_COLOR_VALID))
  2736. ;
  2737. else
  2738. {
  2739. pdLast = pa->pdNextVertex-1;
  2740. for (pd = pa->pd0; pd <= pdLast; pd++)
  2741. {
  2742. if (!(pd->flags & POLYDATA_COLOR_VALID))
  2743. {
  2744. // If color has not changed for this vertex,
  2745. // use the previously computed color.
  2746. ASSERTOPENGL(pd != pa->pd0, "no initial color index\n");
  2747. pd->colors[0].r = (pd-1)->colors[0].r;
  2748. }
  2749. }
  2750. }
  2751. }
  2752. }
  2753. #endif // __GL_ASM_POLYARRAYPROPAGATEINDEX
  2754. #ifndef __GL_ASM_POLYARRAYPROPAGATECOLOR
  2755. // Propagate the valid RGBA colors through the vertex buffer.
  2756. //
  2757. // IN: color (front)
  2758. // OUT: color (front) (all vertices are updated)
  2759. void FASTCALL PolyArrayPropagateColor(__GLcontext *gc, POLYARRAY *pa)
  2760. {
  2761. POLYDATA *pd, *pdLast;
  2762. if (pa->flags & POLYARRAY_CLAMP_COLOR) {
  2763. pdLast = pa->pdNextVertex-1;
  2764. for (pd = pa->pd0; pd <= pdLast; pd++)
  2765. {
  2766. if (!(pd->flags & POLYDATA_COLOR_VALID))
  2767. {
  2768. // If color has not changed for this vertex,
  2769. // use the previously computed color.
  2770. ASSERTOPENGL(pd != pa->pd0, "no initial color\n");
  2771. pd->colors[0] = (pd-1)->colors[0];
  2772. continue;
  2773. }
  2774. __GL_CLAMP_RGBA(pd->colors[0].r,
  2775. pd->colors[0].g,
  2776. pd->colors[0].b,
  2777. pd->colors[0].a,
  2778. gc,
  2779. pd->colors[0].r,
  2780. pd->colors[0].g,
  2781. pd->colors[0].b,
  2782. pd->colors[0].a);
  2783. }
  2784. } else {
  2785. // If all incoming vertices have valid colors, we are done.
  2786. if ((pa->flags & POLYARRAY_SAME_POLYDATA_TYPE)
  2787. && (pa->pdCurColor != pa->pd0)
  2788. // Need to test 2nd vertex because pdCurColor may have been
  2789. // advanced as a result of combining Color command after End
  2790. && ((pa->pd0 + 1)->flags & POLYDATA_COLOR_VALID))
  2791. ;
  2792. else
  2793. {
  2794. pdLast = pa->pdNextVertex-1;
  2795. for (pd = pa->pd0; pd <= pdLast; pd++)
  2796. {
  2797. if (!(pd->flags & POLYDATA_COLOR_VALID))
  2798. {
  2799. // If color has not changed for this vertex,
  2800. // use the previously computed color.
  2801. ASSERTOPENGL(pd != pa->pd0, "no initial color\n");
  2802. pd->colors[0] = (pd-1)->colors[0];
  2803. }
  2804. }
  2805. }
  2806. }
  2807. }
  2808. #endif // __GL_ASM_POLYARRAYPROPAGATECOLOR
  2809. /****************************************************************************/
  2810. #if 0
  2811. //!!! remove this
  2812. // do we need clip?
  2813. // need __GL_HAS_FOG bit for line and polygon clipping!
  2814. // The boundaryEdge field is initialized in the calling routine.
  2815. #define PA_STORE_PROCESSED_POLYGON_VERTEX(v,pd,bits) \
  2816. { \
  2817. (v)->clip = (pd)->clip; \
  2818. (v)->window = (pd)->window; \
  2819. (v)->eye.z = (pd)->eye.z; /* needed by slow fog */ \
  2820. (v)->fog = (pd)->fog; /* needed by cheap fog in flat shading */ \
  2821. (v)->texture.x = (pd)->texture.x; \
  2822. (v)->texture.y = (pd)->texture.y; \
  2823. (v)->texture.z = (pd)->texture.z; /* z is needed by feedback! */\
  2824. (v)->texture.w = (pd)->texture.w; \
  2825. (v)->color = &(pd)->color; \
  2826. (v)->clipCode = (pd)->clipCode; \
  2827. (v)->has = bits; \
  2828. }
  2829. // need eye if there is eyeClipPlanes
  2830. // need texture if there is texture
  2831. // need __GL_HAS_FOG bit for line and polygon clipping!
  2832. #define PA_STORE_PROCESSED_LINE_VERTEX(v,pd,bits) \
  2833. { \
  2834. (v)->clip = (pd)->clip; \
  2835. (v)->window = (pd)->window; \
  2836. (v)->eye.z = (pd)->eye.z; /* needed by slow fog */ \
  2837. (v)->fog = (pd)->fog; /* needed by cheap fog in flat shading */ \
  2838. (v)->texture.x = (pd)->texture.x; \
  2839. (v)->texture.y = (pd)->texture.y; \
  2840. (v)->texture.z = (pd)->texture.z; /* z is needed by feedback! */\
  2841. (v)->texture.w = (pd)->texture.w; \
  2842. (v)->colors[__GL_FRONTFACE] = (pd)->color; \
  2843. (v)->clipCode = (pd)->clipCode; \
  2844. (v)->has = bits; \
  2845. }
  2846. // need eye if antialised is on
  2847. // need texture if there is texture
  2848. #define PA_STORE_PROCESSED_POINT_VERTEX(v,pd,bits) \
  2849. { \
  2850. (v)->window = (pd)->window; \
  2851. (v)->eye.z = (pd)->eye.z; /* needed by slow fog */ \
  2852. (v)->fog = (pd)->fog; /* needed by cheap fog in flat shading */ \
  2853. (v)->clip.w = (pd)->clip.w; /* needed by feedback! */ \
  2854. (v)->texture.x = (pd)->texture.x; \
  2855. (v)->texture.y = (pd)->texture.y; \
  2856. (v)->texture.z = (pd)->texture.z; /* z is needed by feedback! */\
  2857. (v)->texture.w = (pd)->texture.w; \
  2858. (v)->color = &(pd)->color; \
  2859. (v)->has = bits; \
  2860. }
  2861. #endif // 0
  2862. // ---------------------------------------------------------
  2863. // The primitive is clipped.
  2864. void FASTCALL PARenderPoint(__GLcontext *gc, __GLvertex *v)
  2865. {
  2866. if (v->clipCode == 0)
  2867. (*gc->procs.renderPoint)(gc, v);
  2868. }
  2869. // ---------------------------------------------------------
  2870. // The primitive is clipped.
  2871. void FASTCALL PARenderLine(__GLcontext *gc, __GLvertex *v0,
  2872. __GLvertex *v1, GLuint flags)
  2873. {
  2874. if (v0->clipCode | v1->clipCode)
  2875. {
  2876. /*
  2877. * The line must be clipped more carefully. Cannot
  2878. * trivially accept the lines.
  2879. *
  2880. * If anding the codes is non-zero then every vertex
  2881. * in the line is outside of the same set of clipping
  2882. * planes (at least one). Trivially reject the line.
  2883. */
  2884. if ((v0->clipCode & v1->clipCode) == 0)
  2885. __glClipLine(gc, v0, v1, flags);
  2886. }
  2887. else
  2888. {
  2889. // Line is trivially accepted so render it
  2890. (*gc->procs.renderLine)(gc, v0, v1, flags);
  2891. }
  2892. }
  2893. // ---------------------------------------------------------
  2894. // The primitive is clipped.
  2895. void FASTCALL PARenderTriangle(__GLcontext *gc, __GLvertex *v0, __GLvertex *v1, __GLvertex *v2)
  2896. {
  2897. GLuint orCodes;
  2898. /* Clip check */
  2899. orCodes = v0->clipCode | v1->clipCode | v2->clipCode;
  2900. if (orCodes)
  2901. {
  2902. /* Some kind of clipping is needed.
  2903. *
  2904. * If anding the codes is non-zero then every vertex
  2905. * in the triangle is outside of the same set of
  2906. * clipping planes (at least one). Trivially reject
  2907. * the triangle.
  2908. */
  2909. if (!(v0->clipCode & v1->clipCode & v2->clipCode))
  2910. (*gc->procs.clipTriangle)(gc, v0, v1, v2, orCodes);
  2911. }
  2912. else
  2913. {
  2914. (*gc->procs.renderTriangle)(gc, v0, v1, v2);
  2915. }
  2916. }
  2917. // ---------------------------------------------------------
  2918. // The primitive is not clipped.
  2919. void PARenderQuadFast(__GLcontext *gc, __GLvertex *v0, __GLvertex *v1, __GLvertex *v2, __GLvertex *v3)
  2920. {
  2921. // Vertex ordering is important. Line stippling uses it.
  2922. // SGIBUG: The sample implementation does it wrong.
  2923. GLuint savedTag;
  2924. /* Render the quad as two triangles */
  2925. savedTag = v2->has & __GL_HAS_EDGEFLAG_BOUNDARY;
  2926. v2->has &= ~__GL_HAS_EDGEFLAG_BOUNDARY;
  2927. (*gc->procs.renderTriangle)(gc, v0, v1, v2);
  2928. v2->has |= savedTag;
  2929. savedTag = v0->has & __GL_HAS_EDGEFLAG_BOUNDARY;
  2930. v0->has &= ~__GL_HAS_EDGEFLAG_BOUNDARY;
  2931. (*gc->procs.renderTriangle)(gc, v2, v3, v0);
  2932. v0->has |= savedTag;
  2933. }
  2934. // ---------------------------------------------------------
  2935. // The primitive is clipped.
  2936. void PARenderQuadSlow(__GLcontext *gc, __GLvertex *v0, __GLvertex *v1, __GLvertex *v2, __GLvertex *v3)
  2937. {
  2938. GLuint orCodes;
  2939. orCodes = v0->clipCode | v1->clipCode | v2->clipCode | v3->clipCode;
  2940. if (orCodes)
  2941. {
  2942. /* Some kind of clipping is needed.
  2943. *
  2944. * If anding the codes is non-zero then every vertex
  2945. * in the quad is outside of the same set of
  2946. * clipping planes (at least one). Trivially reject
  2947. * the quad.
  2948. */
  2949. if (!(v0->clipCode & v1->clipCode & v2->clipCode & v3->clipCode))
  2950. {
  2951. /* Clip the quad as a polygon */
  2952. __GLvertex *iv[4];
  2953. iv[0] = v0;
  2954. iv[1] = v1;
  2955. iv[2] = v2;
  2956. iv[3] = v3;
  2957. __glDoPolygonClip(gc, &iv[0], 4, orCodes);
  2958. }
  2959. }
  2960. else
  2961. {
  2962. PARenderQuadFast(gc, v0, v1, v2, v3);
  2963. }
  2964. }
  2965. // ---------------------------------------------------------
  2966. #ifndef NEW_PARTIAL_PRIM
  2967. void FASTCALL PolyArrayDrawPoints(__GLcontext *gc, POLYARRAY *pa)
  2968. {
  2969. // Index mapping is always identity in Points.
  2970. ASSERTOPENGL(!pa->aIndices, "Index mapping must be identity\n");
  2971. // Assert that pa->nIndices is correct
  2972. ASSERTOPENGL(pa->nIndices == pa->pdNextVertex - pa->pd0,
  2973. "bad nIndices\n");
  2974. // Call PolyArrayRenderPoints later
  2975. pa->flags |= POLYARRAY_RENDER_PRIMITIVE;
  2976. }
  2977. #endif // NEW_PARTIAL_PRIM
  2978. void FASTCALL PolyArrayRenderPoints(__GLcontext *gc, POLYARRAY *pa)
  2979. {
  2980. GLint i, nIndices;
  2981. POLYDATA *pd0;
  2982. void (FASTCALL *rp)(__GLcontext *gc, __GLvertex *v);
  2983. // Index mapping is always identity in Points.
  2984. ASSERTOPENGL(!pa->aIndices, "Index mapping must be identity\n");
  2985. nIndices = pa->nIndices;
  2986. pd0 = pa->pd0;
  2987. rp = pa->orClipCodes ? PARenderPoint : gc->procs.renderPoint;
  2988. // Identity mapping
  2989. for (i = 0; i < nIndices; i++)
  2990. /* Render the point */
  2991. (*rp)(gc, (__GLvertex *) &pd0[i]);
  2992. }
  2993. // ---------------------------------------------------------
  2994. #ifndef NEW_PARTIAL_PRIM
  2995. void FASTCALL PolyArrayDrawLines(__GLcontext *gc, POLYARRAY *pa)
  2996. {
  2997. // Assert that pa->nIndices is correct if aIndices is identity
  2998. ASSERTOPENGL(pa->aIndices || pa->nIndices == pa->pdNextVertex - pa->pd0,
  2999. "bad nIndices\n");
  3000. // Call PolyArrayRenderLines later
  3001. pa->flags |= POLYARRAY_RENDER_PRIMITIVE;
  3002. }
  3003. #endif //NEW_PARTIAL_PRIM
  3004. void FASTCALL PolyArrayRenderLines(__GLcontext *gc, POLYARRAY *pa)
  3005. {
  3006. GLint i, iLast2;
  3007. GLubyte *aIndices;
  3008. POLYDATA *pd0;
  3009. PFN_RENDER_LINE rl;
  3010. GLuint modeFlags;
  3011. iLast2 = pa->nIndices - 2;
  3012. pd0 = pa->pd0;
  3013. rl = pa->orClipCodes ? PARenderLine : gc->procs.renderLine;
  3014. if (pa->flags & POLYARRAY_SAME_COLOR_DATA) {
  3015. modeFlags = gc->polygon.shader.modeFlags;
  3016. gc->polygon.shader.modeFlags &= ~__GL_SHADE_SMOOTH;
  3017. }
  3018. (*gc->procs.lineBegin)(gc);
  3019. if (!(aIndices = pa->aIndices))
  3020. {
  3021. // Identity mapping
  3022. for (i = 0; i <= iLast2; i += 2)
  3023. {
  3024. /* setup for rendering this line */
  3025. gc->line.notResetStipple = GL_FALSE;
  3026. (*rl)(gc, (__GLvertex *) &pd0[i ],
  3027. (__GLvertex *) &pd0[i+1], __GL_LVERT_FIRST);
  3028. }
  3029. }
  3030. else
  3031. {
  3032. for (i = 0; i <= iLast2; i += 2)
  3033. {
  3034. /* setup for rendering this line */
  3035. gc->line.notResetStipple = GL_FALSE;
  3036. (*rl)(gc, (__GLvertex *) &pd0[aIndices[i ]],
  3037. (__GLvertex *) &pd0[aIndices[i+1]], __GL_LVERT_FIRST);
  3038. }
  3039. }
  3040. (*gc->procs.lineEnd)(gc);
  3041. if (pa->flags & POLYARRAY_SAME_COLOR_DATA) {
  3042. gc->polygon.shader.modeFlags = modeFlags;
  3043. }
  3044. }
  3045. // ---------------------------------------------------------
  3046. #ifndef NEW_PARTIAL_PRIM
  3047. void FASTCALL PolyArrayDrawLLoop(__GLcontext *gc, POLYARRAY *pa)
  3048. {
  3049. GLint nIndices;
  3050. POLYDATA *pd, *pd0;
  3051. // Index mapping is always identity in Line Loop.
  3052. ASSERTOPENGL(!pa->aIndices, "Index mapping must be identity\n");
  3053. // A line loop is the same as a line strip except that a final segment is
  3054. // added from the final specified vertex to the first vertex. We will
  3055. // convert the line loop into a strip here.
  3056. nIndices = pa->nIndices;
  3057. // If we are continuing with a previously decomposed line loop, we need to
  3058. // connect the last vertex of the previous primitive and the first vertex
  3059. // of the current primitive with a line segment.
  3060. if (pa->flags & POLYARRAY_PARTIAL_BEGIN)
  3061. {
  3062. ASSERTOPENGL(!(pa->flags & POLYARRAY_RESET_STIPPLE),
  3063. "bad stipple reset flag!\n");
  3064. // Insert previous end vertex at the beginning and update clip code
  3065. pd = --pa->pd0;
  3066. ASSERTOPENGL(pd > (POLYDATA *) pa, "vertex underflows\n");
  3067. PA_COPY_PROCESSED_VERTEX(pd, &gc->vertex.pdSaved[0]);
  3068. pa->orClipCodes |= pd->clipCode;
  3069. #ifdef POLYARRAY_AND_CLIPCODES
  3070. pa->andClipCodes &= pd->clipCode;
  3071. #endif
  3072. }
  3073. else
  3074. {
  3075. // New line loop.
  3076. ASSERTOPENGL(pa->flags & POLYARRAY_RESET_STIPPLE,
  3077. "bad stipple reset flag!\n");
  3078. // At least two vertices must be given for anything to occur.
  3079. // An extra vertex was added to close the loop.
  3080. if (nIndices < 3)
  3081. {
  3082. ASSERTOPENGL(!(pa->flags & POLYARRAY_PARTIAL_END),
  3083. "Partial end with insufficient vertices\n");
  3084. pa->nIndices--;
  3085. goto DrawLLoop_end;
  3086. }
  3087. }
  3088. pd0 = pa->pd0;
  3089. // If the primitive is only partially complete, save the last vertex for
  3090. // next batch.
  3091. if (pa->flags & POLYARRAY_PARTIAL_END)
  3092. {
  3093. pd = &pd0[nIndices-1];
  3094. PA_COPY_PROCESSED_VERTEX(&gc->vertex.pdSaved[0], pd);
  3095. // Save the the original first vertex for closing the loop later.
  3096. if (!(pa->flags & POLYARRAY_PARTIAL_BEGIN))
  3097. PA_COPY_PROCESSED_VERTEX(&gc->vertex.pdSaved[1], pd0);
  3098. // Need not render this partial primitive if it is completely clipped.
  3099. #ifdef POLYARRAY_AND_CLIPCODES
  3100. if (pa->andClipCodes != 0)
  3101. goto DrawLLoop_end;
  3102. #endif
  3103. }
  3104. else
  3105. {
  3106. POLYDATA *pdOrigin;
  3107. // Insert the original first vertex to close the loop and update clip code.
  3108. if (pa->flags & POLYARRAY_PARTIAL_BEGIN)
  3109. pdOrigin = &gc->vertex.pdSaved[1];
  3110. else
  3111. pdOrigin = pd0;
  3112. pd = pa->pdNextVertex++;
  3113. ASSERTOPENGL(pd <= pa->pdBufferMax, "vertex overflows\n");
  3114. PA_COPY_PROCESSED_VERTEX(pd, pdOrigin);
  3115. pa->orClipCodes |= pd->clipCode;
  3116. #ifdef POLYARRAY_AND_CLIPCODES
  3117. pa->andClipCodes &= pd->clipCode;
  3118. #endif
  3119. }
  3120. // Assert that pa->nIndices is correct
  3121. ASSERTOPENGL(pa->nIndices == pa->pdNextVertex - pa->pd0,
  3122. "bad nIndices\n");
  3123. // Render the line strip.
  3124. // Call PolyArrayRenderLStrip later
  3125. pa->flags |= POLYARRAY_RENDER_PRIMITIVE;
  3126. DrawLLoop_end:
  3127. // Change primitive type to line strip!
  3128. pa->primType = GL_LINE_STRIP;
  3129. }
  3130. #endif // NEW_PARTIAL_PRIM
  3131. void FASTCALL PolyArrayRenderLStrip(__GLcontext *gc, POLYARRAY *pa)
  3132. {
  3133. GLint i, iLast;
  3134. GLubyte *aIndices;
  3135. POLYDATA *pd0;
  3136. PFN_RENDER_LINE rl;
  3137. GLuint modeFlags;
  3138. // Render the line strip.
  3139. iLast = pa->nIndices - 1;
  3140. pd0 = pa->pd0;
  3141. rl = pa->orClipCodes ? PARenderLine : gc->procs.renderLine;
  3142. if (iLast <= 0)
  3143. return;
  3144. // Reset the line stipple if this is a new strip.
  3145. if (pa->flags & POLYARRAY_RESET_STIPPLE)
  3146. gc->line.notResetStipple = GL_FALSE;
  3147. if (pa->flags & POLYARRAY_SAME_COLOR_DATA) {
  3148. modeFlags = gc->polygon.shader.modeFlags;
  3149. gc->polygon.shader.modeFlags &= ~__GL_SHADE_SMOOTH;
  3150. }
  3151. (*gc->procs.lineBegin)(gc);
  3152. if (!(aIndices = pa->aIndices))
  3153. {
  3154. // Identity mapping
  3155. // Add first line segment (NOTE: 0, 1)
  3156. (*rl)(gc, (__GLvertex *) &pd0[0],
  3157. (__GLvertex *) &pd0[1], __GL_LVERT_FIRST);
  3158. // Add subsequent line segments (NOTE: i, i+1)
  3159. for (i = 1; i < iLast; i++)
  3160. (*rl)(gc, (__GLvertex *) &pd0[i ],
  3161. (__GLvertex *) &pd0[i+1], 0);
  3162. }
  3163. else
  3164. {
  3165. // Add first line segment (NOTE: 0, 1)
  3166. (*rl)(gc, (__GLvertex *) &pd0[aIndices[0]],
  3167. (__GLvertex *) &pd0[aIndices[1]], __GL_LVERT_FIRST);
  3168. // Add subsequent line segments (NOTE: i, i+1)
  3169. for (i = 1; i < iLast; i++)
  3170. (*rl)(gc, (__GLvertex *) &pd0[aIndices[i ]],
  3171. (__GLvertex *) &pd0[aIndices[i+1]], 0);
  3172. }
  3173. if (pa->flags & POLYARRAY_SAME_COLOR_DATA) {
  3174. gc->polygon.shader.modeFlags = modeFlags;
  3175. }
  3176. (*gc->procs.lineEnd)(gc);
  3177. }
  3178. // ---------------------------------------------------------
  3179. #ifndef NEW_PARTIAL_PRIM
  3180. void FASTCALL PolyArrayDrawLStrip(__GLcontext *gc, POLYARRAY *pa)
  3181. {
  3182. GLint nIndices;
  3183. GLubyte *aIndices;
  3184. POLYDATA *pd, *pd0;
  3185. nIndices = pa->nIndices;
  3186. aIndices = pa->aIndices;
  3187. // If we are continuing with a previously decomposed line strip, we need to
  3188. // connect the last vertex of the previous primitive and the first vertex
  3189. // of the current primitive with a line segment.
  3190. if (pa->flags & POLYARRAY_PARTIAL_BEGIN)
  3191. {
  3192. ASSERTOPENGL(!(pa->flags & POLYARRAY_RESET_STIPPLE),
  3193. "bad stipple reset flag!\n");
  3194. // Insert previous end vertex at the beginning and update clip code
  3195. pd = --pa->pd0;
  3196. ASSERTOPENGL(pd > (POLYDATA *) pa, "vertex underflows\n");
  3197. PA_COPY_PROCESSED_VERTEX(pd, &gc->vertex.pdSaved[0]);
  3198. pa->orClipCodes |= pd->clipCode;
  3199. #ifdef POLYARRAY_AND_CLIPCODES
  3200. pa->andClipCodes &= pd->clipCode;
  3201. #endif
  3202. // Assert that aIndices[0] was initialized in Begin
  3203. ASSERTOPENGL(!pa->aIndices || pa->aIndices[0] == 0, "bad index mapping\n");
  3204. }
  3205. else
  3206. {
  3207. // New line strip.
  3208. ASSERTOPENGL(pa->flags & POLYARRAY_RESET_STIPPLE,
  3209. "bad stipple reset flag!\n");
  3210. }
  3211. // At least two vertices must be given for anything to occur.
  3212. if (nIndices < 2)
  3213. {
  3214. ASSERTOPENGL(!(pa->flags & POLYARRAY_PARTIAL_END),
  3215. "Partial end with insufficient vertices\n");
  3216. return;
  3217. }
  3218. // If the primitive is only partially complete, save the last vertex for
  3219. // next batch.
  3220. if (pa->flags & POLYARRAY_PARTIAL_END)
  3221. {
  3222. pd0 = pa->pd0;
  3223. pd = aIndices ? &pd0[aIndices[nIndices-1]] : &pd0[nIndices-1];
  3224. PA_COPY_PROCESSED_VERTEX(&gc->vertex.pdSaved[0], pd);
  3225. // Need not render this partial primitive if it is completely clipped.
  3226. #ifdef POLYARRAY_AND_CLIPCODES
  3227. if (pa->andClipCodes != 0)
  3228. return;
  3229. #endif
  3230. }
  3231. // Assert that pa->nIndices is correct if aIndices is identity
  3232. ASSERTOPENGL(pa->aIndices || pa->nIndices == pa->pdNextVertex - pa->pd0,
  3233. "bad nIndices\n");
  3234. // Render the line strip.
  3235. // Call PolyArrayRenderLStrip later
  3236. pa->flags |= POLYARRAY_RENDER_PRIMITIVE;
  3237. }
  3238. // ---------------------------------------------------------
  3239. void FASTCALL PolyArrayDrawTriangles(__GLcontext *gc, POLYARRAY *pa)
  3240. {
  3241. // Assert that pa->nIndices is correct if aIndices is identity
  3242. ASSERTOPENGL(pa->aIndices || pa->nIndices == pa->pdNextVertex - pa->pd0,
  3243. "bad nIndices\n");
  3244. // Call PolyArrayRenderTriangles later
  3245. pa->flags |= POLYARRAY_RENDER_PRIMITIVE;
  3246. }
  3247. #endif // NEW_PARTIAL_PRIM
  3248. void FASTCALL PolyArrayRenderTriangles(__GLcontext *gc, POLYARRAY *pa)
  3249. {
  3250. GLint i, iLast3;
  3251. GLubyte *aIndices, *aIndicesEnd;
  3252. POLYDATA *pd0;
  3253. __GLvertex *provoking;
  3254. PFN_RENDER_TRIANGLE rt;
  3255. // Vertex ordering is important. Line stippling uses it.
  3256. // SGIBUG: The sample implementation does it wrong.
  3257. iLast3 = pa->nIndices - 3;
  3258. pd0 = pa->pd0;
  3259. rt = pa->orClipCodes ? PARenderTriangle : gc->procs.renderTriangle;
  3260. if (!(aIndices = pa->aIndices))
  3261. {
  3262. // Identity mapping
  3263. for (i = 0; i <= iLast3; i += 3)
  3264. {
  3265. /* setup for rendering this triangle */
  3266. gc->line.notResetStipple = GL_FALSE;
  3267. gc->vertex.provoking = (__GLvertex *) &pd0[i+2];
  3268. /* Render the triangle (NOTE: i, i+1, i+2) */
  3269. (*rt)(gc, (__GLvertex *) &pd0[i ],
  3270. (__GLvertex *) &pd0[i+1],
  3271. (__GLvertex *) &pd0[i+2]);
  3272. }
  3273. }
  3274. else
  3275. {
  3276. #if 0
  3277. for (i = 0; i <= iLast3; i += 3)
  3278. {
  3279. /* setup for rendering this triangle */
  3280. gc->line.notResetStipple = GL_FALSE;
  3281. gc->vertex.provoking = (__GLvertex *) &pd0[aIndices[i+2]];
  3282. /* Render the triangle (NOTE: i, i+1, i+2) */
  3283. (*rt)(gc, (__GLvertex *) &pd0[aIndices[i ]],
  3284. (__GLvertex *) &pd0[aIndices[i+1]],
  3285. (__GLvertex *) &pd0[aIndices[i+2]]);
  3286. }
  3287. #else
  3288. aIndicesEnd = aIndices+iLast3;
  3289. while (aIndices <= aIndicesEnd)
  3290. {
  3291. /* setup for rendering this triangle */
  3292. gc->line.notResetStipple = GL_FALSE;
  3293. provoking = PD_VERTEX(pd0, aIndices[2]);
  3294. gc->vertex.provoking = provoking;
  3295. /* Render the triangle (NOTE: i, i+1, i+2) */
  3296. (*rt)(gc, PD_VERTEX(pd0, aIndices[0]),
  3297. PD_VERTEX(pd0, aIndices[1]),
  3298. provoking);
  3299. aIndices += 3;
  3300. }
  3301. #endif
  3302. }
  3303. }
  3304. // ---------------------------------------------------------
  3305. #ifndef NEW_PARTIAL_PRIM
  3306. void FASTCALL PolyArrayDrawTStrip(__GLcontext *gc, POLYARRAY *pa)
  3307. {
  3308. GLint nIndices;
  3309. GLubyte *aIndices;
  3310. POLYDATA *pd, *pd0;
  3311. nIndices = pa->nIndices;
  3312. aIndices = pa->aIndices;
  3313. // If we are continuing with a previously decomposed triangle strip,
  3314. // we need to start from the last two vertices of the previous primitive.
  3315. //
  3316. // Note that the flush vertex ensures that the continuing triangle strip
  3317. // is in the default orientation so that it can fall through the normal
  3318. // code.
  3319. if (pa->flags & POLYARRAY_PARTIAL_BEGIN)
  3320. {
  3321. // Insert previous end vertices at the beginning and update clip code
  3322. pd = --pa->pd0;
  3323. ASSERTOPENGL(pd > (POLYDATA *) pa, "vertex underflows\n");
  3324. PA_COPY_PROCESSED_VERTEX(pd, &gc->vertex.pdSaved[1]);
  3325. pa->orClipCodes |= pd->clipCode;
  3326. #ifdef POLYARRAY_AND_CLIPCODES
  3327. pa->andClipCodes &= pd->clipCode;
  3328. #endif
  3329. // Assert that aIndices[1] was initialized in Begin
  3330. ASSERTOPENGL(!pa->aIndices || pa->aIndices[1] == 1, "bad index mapping\n");
  3331. pd = --pa->pd0;
  3332. ASSERTOPENGL(pd > (POLYDATA *) pa, "vertex underflows\n");
  3333. PA_COPY_PROCESSED_VERTEX(pd, &gc->vertex.pdSaved[0]);
  3334. pa->orClipCodes |= pd->clipCode;
  3335. #ifdef POLYARRAY_AND_CLIPCODES
  3336. pa->andClipCodes &= pd->clipCode;
  3337. #endif
  3338. // Assert that aIndices[0] was initialized in Begin
  3339. ASSERTOPENGL(!pa->aIndices || pa->aIndices[0] == 0, "bad index mapping\n");
  3340. }
  3341. // Need at least 3 vertices.
  3342. if (nIndices < 3)
  3343. {
  3344. ASSERTOPENGL(!(pa->flags & POLYARRAY_PARTIAL_END),
  3345. "Partial end with insufficient vertices\n");
  3346. return;
  3347. }
  3348. // If the primitive is only partially complete,
  3349. // save the last two vertices for next batch.
  3350. #ifdef GL_WIN_phong_shading
  3351. // !!If phong shaded, also save the current material parameters.
  3352. // No need, since in Phong shading, I am throwing away all glMaterial
  3353. // calls between glBegin/glEnd. If it is a PARTIAL_PRIMITIVE, then
  3354. // there were no material changes (except ColorMaterial) immediately
  3355. // before.
  3356. #endif //GL_WIN_phong_shading
  3357. if (pa->flags & POLYARRAY_PARTIAL_END)
  3358. {
  3359. pd0 = pa->pd0;
  3360. pd = aIndices ? &pd0[aIndices[nIndices-2]] : &pd0[nIndices-2];
  3361. PA_COPY_PROCESSED_VERTEX(&gc->vertex.pdSaved[0], pd);
  3362. pd = aIndices ? &pd0[aIndices[nIndices-1]] : &pd0[nIndices-1];
  3363. PA_COPY_PROCESSED_VERTEX(&gc->vertex.pdSaved[1], pd);
  3364. // Need not render this partial primitive if it is completely clipped.
  3365. #ifdef POLYARRAY_AND_CLIPCODES
  3366. if (pa->andClipCodes != 0)
  3367. return;
  3368. #endif
  3369. }
  3370. // Assert that pa->nIndices is correct if aIndices is identity
  3371. ASSERTOPENGL(pa->aIndices || pa->nIndices == pa->pdNextVertex - pa->pd0,
  3372. "bad nIndices\n");
  3373. // Render the triangle strip.
  3374. // Call PolyArrayRenderTStrip later
  3375. pa->flags |= POLYARRAY_RENDER_PRIMITIVE;
  3376. }
  3377. #endif //NEW_PARTIAL_PRIM
  3378. void FASTCALL PolyArrayRenderTStrip(__GLcontext *gc, POLYARRAY *pa)
  3379. {
  3380. GLint i, iLast3;
  3381. GLubyte *aIndices;
  3382. POLYDATA *pd0;
  3383. PFN_RENDER_TRIANGLE rt;
  3384. iLast3 = pa->nIndices - 3;
  3385. pd0 = pa->pd0;
  3386. rt = pa->orClipCodes ? PARenderTriangle : gc->procs.renderTriangle;
  3387. if (iLast3 < 0)
  3388. return;
  3389. // Vertex ordering is important. Line stippling uses it.
  3390. if (!(aIndices = pa->aIndices))
  3391. {
  3392. // Identity mapping
  3393. // Initialize first 2 vertices so we can start rendering the strip
  3394. // below. The edge flags are not modified by our lower level
  3395. // routines.
  3396. pd0[0].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3397. pd0[1].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3398. for (i = 0; i <= iLast3; )
  3399. {
  3400. /* setup for rendering this triangle */
  3401. gc->line.notResetStipple = GL_FALSE;
  3402. gc->vertex.provoking = (__GLvertex *) &pd0[i+2];
  3403. pd0[i+2].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3404. /* Render the triangle (NOTE: i, i+1, i+2) */
  3405. (*rt)(gc, (__GLvertex *) &pd0[i ],
  3406. (__GLvertex *) &pd0[i+1],
  3407. (__GLvertex *) &pd0[i+2]);
  3408. i++;
  3409. if (i > iLast3)
  3410. break;
  3411. /* setup for rendering this triangle */
  3412. gc->line.notResetStipple = GL_FALSE;
  3413. gc->vertex.provoking = (__GLvertex *) &pd0[i+2];
  3414. pd0[i+2].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3415. /* Render the triangle (NOTE: i+1, i, i+2) */
  3416. (*rt)(gc, (__GLvertex *) &pd0[i+1],
  3417. (__GLvertex *) &pd0[i ],
  3418. (__GLvertex *) &pd0[i+2]);
  3419. i++;
  3420. }
  3421. }
  3422. else
  3423. {
  3424. // Initialize first 2 vertices so we can start rendering the strip
  3425. // below. The edge flags are not modified by our lower level routines.
  3426. pd0[aIndices[0]].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3427. pd0[aIndices[1]].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3428. for (i = 0; i <= iLast3; )
  3429. {
  3430. /* setup for rendering this triangle */
  3431. gc->line.notResetStipple = GL_FALSE;
  3432. gc->vertex.provoking = (__GLvertex *) &pd0[aIndices[i+2]];
  3433. pd0[aIndices[i+2]].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3434. /* Render the triangle (NOTE: i, i+1, i+2) */
  3435. (*rt)(gc, (__GLvertex *) &pd0[aIndices[i ]],
  3436. (__GLvertex *) &pd0[aIndices[i+1]],
  3437. (__GLvertex *) &pd0[aIndices[i+2]]);
  3438. i++;
  3439. if (i > iLast3)
  3440. break;
  3441. /* setup for rendering this triangle */
  3442. gc->line.notResetStipple = GL_FALSE;
  3443. gc->vertex.provoking = (__GLvertex *) &pd0[aIndices[i+2]];
  3444. pd0[aIndices[i+2]].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3445. /* Render the triangle (NOTE: i+1, i, i+2) */
  3446. (*rt)(gc, (__GLvertex *) &pd0[aIndices[i+1]],
  3447. (__GLvertex *) &pd0[aIndices[i ]],
  3448. (__GLvertex *) &pd0[aIndices[i+2]]);
  3449. i++;
  3450. }
  3451. }
  3452. }
  3453. // ---------------------------------------------------------
  3454. #ifndef NEW_PARTIAL_PRIM
  3455. void FASTCALL PolyArrayDrawTFan(__GLcontext *gc, POLYARRAY *pa)
  3456. {
  3457. GLint nIndices;
  3458. GLubyte *aIndices;
  3459. POLYDATA *pd, *pd0;
  3460. nIndices = pa->nIndices;
  3461. aIndices = pa->aIndices;
  3462. // If we are continuing with a previously decomposed triangle fan,
  3463. // we need to connect the last vertex of the previous primitive and the
  3464. // first vertex of the current primitive with a triangle.
  3465. if (pa->flags & POLYARRAY_PARTIAL_BEGIN)
  3466. {
  3467. // Insert previous end vertex at the beginning and update clip code
  3468. pd = --pa->pd0;
  3469. ASSERTOPENGL(pd > (POLYDATA *) pa, "vertex underflows\n");
  3470. PA_COPY_PROCESSED_VERTEX(pd, &gc->vertex.pdSaved[1]);
  3471. pa->orClipCodes |= pd->clipCode;
  3472. #ifdef POLYARRAY_AND_CLIPCODES
  3473. pa->andClipCodes &= pd->clipCode;
  3474. #endif
  3475. // Assert that aIndices[1] was initialized in Begin
  3476. ASSERTOPENGL(!pa->aIndices || pa->aIndices[1] == 1, "bad index mapping\n");
  3477. // Insert the origin first vertex at the beginning and update
  3478. // clip code
  3479. pd = --pa->pd0;
  3480. ASSERTOPENGL(pd > (POLYDATA *) pa, "vertex underflows\n");
  3481. PA_COPY_PROCESSED_VERTEX(pd, &gc->vertex.pdSaved[0]);
  3482. pa->orClipCodes |= pd->clipCode;
  3483. #ifdef POLYARRAY_AND_CLIPCODES
  3484. pa->andClipCodes &= pd->clipCode;
  3485. #endif
  3486. // Assert that aIndices[0] was initialized in Begin
  3487. ASSERTOPENGL(!pa->aIndices || pa->aIndices[0] == 0, "bad index mapping\n");
  3488. }
  3489. // Need at least 3 vertices.
  3490. if (nIndices < 3)
  3491. {
  3492. ASSERTOPENGL(!(pa->flags & POLYARRAY_PARTIAL_END),
  3493. "Partial end with insufficient vertices\n");
  3494. return;
  3495. }
  3496. // If the primitive is only partially complete, save the last vertex
  3497. // for next batch. Also save the original first vertex of the triangle
  3498. // fan.
  3499. if (pa->flags & POLYARRAY_PARTIAL_END)
  3500. {
  3501. pd0 = pa->pd0;
  3502. pd = aIndices ? &pd0[aIndices[nIndices-1]] : &pd0[nIndices-1];
  3503. PA_COPY_PROCESSED_VERTEX(&gc->vertex.pdSaved[1], pd);
  3504. if (!(pa->flags & POLYARRAY_PARTIAL_BEGIN))
  3505. {
  3506. pd = aIndices ? &pd0[aIndices[0]] : &pd0[0];
  3507. PA_COPY_PROCESSED_VERTEX(&gc->vertex.pdSaved[0], pd);
  3508. }
  3509. // Need not render this partial primitive if it is completely clipped.
  3510. #ifdef POLYARRAY_AND_CLIPCODES
  3511. if (pa->andClipCodes != 0)
  3512. return;
  3513. #endif
  3514. }
  3515. // Assert that pa->nIndices is correct if aIndices is identity
  3516. ASSERTOPENGL(pa->aIndices || pa->nIndices == pa->pdNextVertex - pa->pd0,
  3517. "bad nIndices\n");
  3518. // Render the triangle fan.
  3519. // Call PolyArrayRenderTFan later
  3520. pa->flags |= POLYARRAY_RENDER_PRIMITIVE;
  3521. }
  3522. #endif // NEW_PARTIAL_PRIM
  3523. void FASTCALL PolyArrayRenderTFan(__GLcontext *gc, POLYARRAY *pa)
  3524. {
  3525. GLint i, iLast2;
  3526. GLubyte *aIndices;
  3527. POLYDATA *pd0;
  3528. PFN_RENDER_TRIANGLE rt;
  3529. iLast2 = pa->nIndices - 2;
  3530. pd0 = pa->pd0;
  3531. rt = pa->orClipCodes ? PARenderTriangle : gc->procs.renderTriangle;
  3532. if (iLast2 <= 0)
  3533. return;
  3534. // Vertex ordering is important. Line stippling uses it.
  3535. // SGIBUG: The sample implementation does it wrong.
  3536. if (!(aIndices = pa->aIndices))
  3537. {
  3538. // Identity mapping
  3539. // Initialize first 2 vertices so we can start rendering the tfan
  3540. // below. The edge flags are not modified by our lower level routines.
  3541. pd0[0].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3542. pd0[1].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3543. for (i = 1; i <= iLast2; i++)
  3544. {
  3545. /* setup for rendering this triangle */
  3546. gc->line.notResetStipple = GL_FALSE;
  3547. gc->vertex.provoking = (__GLvertex *) &pd0[i+1];
  3548. pd0[i+1].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3549. /* Render the triangle (NOTE: 0, i, i+1) */
  3550. (*rt)(gc, (__GLvertex *) &pd0[0 ],
  3551. (__GLvertex *) &pd0[i ],
  3552. (__GLvertex *) &pd0[i+1]);
  3553. }
  3554. }
  3555. else
  3556. {
  3557. POLYDATA *pdOrigin;
  3558. // Initialize first 2 vertices so we can start rendering the tfan
  3559. // below. The edge flags are not modified by our lower level
  3560. // routines.
  3561. pd0[aIndices[0]].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3562. pd0[aIndices[1]].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3563. pdOrigin = &pd0[aIndices[0]];
  3564. for (i = 1; i <= iLast2; i++)
  3565. {
  3566. /* setup for rendering this triangle */
  3567. gc->line.notResetStipple = GL_FALSE;
  3568. gc->vertex.provoking = (__GLvertex *) &pd0[aIndices[i+1]];
  3569. pd0[aIndices[i+1]].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3570. /* Render the triangle (NOTE: 0, i, i+1) */
  3571. (*rt)(gc, (__GLvertex *) pdOrigin,
  3572. (__GLvertex *) &pd0[aIndices[i ]],
  3573. (__GLvertex *) &pd0[aIndices[i+1]]);
  3574. }
  3575. }
  3576. }
  3577. // ---------------------------------------------------------
  3578. #ifndef NEW_PARTIAL_PRIM
  3579. void FASTCALL PolyArrayDrawQuads(__GLcontext *gc, POLYARRAY *pa)
  3580. {
  3581. // Assert that pa->nIndices is correct if aIndices is identity
  3582. ASSERTOPENGL(pa->aIndices || pa->nIndices == pa->pdNextVertex - pa->pd0,
  3583. "bad nIndices\n");
  3584. // Call PolyArrayRenderQuad later
  3585. pa->flags |= POLYARRAY_RENDER_PRIMITIVE;
  3586. }
  3587. #endif // NEW_PARTIAL_PRIM
  3588. void FASTCALL PolyArrayRenderQuads(__GLcontext *gc, POLYARRAY *pa)
  3589. {
  3590. GLint i, iLast4;
  3591. GLubyte *aIndices;
  3592. POLYDATA *pd0;
  3593. void (*rq)(__GLcontext *gc, __GLvertex *v0, __GLvertex *v1, __GLvertex *v2,
  3594. __GLvertex *v3);
  3595. // Vertex ordering is important. Line stippling uses it.
  3596. iLast4 = pa->nIndices - 4;
  3597. pd0 = pa->pd0;
  3598. rq = pa->orClipCodes ? PARenderQuadSlow : PARenderQuadFast;
  3599. if (!(aIndices = pa->aIndices))
  3600. {
  3601. // Identity mapping
  3602. for (i = 0; i <= iLast4; i += 4)
  3603. {
  3604. /* setup for rendering this quad */
  3605. gc->line.notResetStipple = GL_FALSE;
  3606. gc->vertex.provoking = (__GLvertex *) &pd0[i+3];
  3607. /* Render the quad (NOTE: i, i+1, i+2, i+3) */
  3608. (*rq)(gc, (__GLvertex *) &pd0[i ],
  3609. (__GLvertex *) &pd0[i+1],
  3610. (__GLvertex *) &pd0[i+2],
  3611. (__GLvertex *) &pd0[i+3]);
  3612. }
  3613. }
  3614. else
  3615. {
  3616. for (i = 0; i <= iLast4; i += 4)
  3617. {
  3618. /* setup for rendering this quad */
  3619. gc->line.notResetStipple = GL_FALSE;
  3620. gc->vertex.provoking = (__GLvertex *) &pd0[aIndices[i+3]];
  3621. /* Render the quad (NOTE: i, i+1, i+2, i+3) */
  3622. (*rq)(gc, (__GLvertex *) &pd0[aIndices[i ]],
  3623. (__GLvertex *) &pd0[aIndices[i+1]],
  3624. (__GLvertex *) &pd0[aIndices[i+2]],
  3625. (__GLvertex *) &pd0[aIndices[i+3]]);
  3626. }
  3627. }
  3628. }
  3629. // ---------------------------------------------------------
  3630. #ifndef NEW_PARTIAL_PRIM
  3631. void FASTCALL PolyArrayDrawQStrip(__GLcontext *gc, POLYARRAY *pa)
  3632. {
  3633. GLint nIndices;
  3634. GLubyte *aIndices;
  3635. POLYDATA *pd, *pd0;
  3636. nIndices = pa->nIndices;
  3637. aIndices = pa->aIndices;
  3638. // If we are continuing with a previously decomposed quad strip, we need
  3639. // to start from the last two vertices of the previous primitive.
  3640. //
  3641. // Note that the flush vertex ensures that the continuing quad strip
  3642. // starts at an odd vertex so that it can fall through the normal code.
  3643. if (pa->flags & POLYARRAY_PARTIAL_BEGIN)
  3644. {
  3645. // Insert previous end vertices at the beginning and update clip code
  3646. pd = --pa->pd0;
  3647. ASSERTOPENGL(pd > (POLYDATA *) pa, "vertex underflows\n");
  3648. PA_COPY_PROCESSED_VERTEX(pd, &gc->vertex.pdSaved[1]);
  3649. pa->orClipCodes |= pd->clipCode;
  3650. #ifdef POLYARRAY_AND_CLIPCODES
  3651. pa->andClipCodes &= pd->clipCode;
  3652. #endif
  3653. // Assert that aIndices[1] was initialized in Begin
  3654. ASSERTOPENGL(!pa->aIndices || pa->aIndices[1] == 1,
  3655. "bad index mapping\n");
  3656. pd = --pa->pd0;
  3657. ASSERTOPENGL(pd > (POLYDATA *) pa, "vertex underflows\n");
  3658. PA_COPY_PROCESSED_VERTEX(pd, &gc->vertex.pdSaved[0]);
  3659. pa->orClipCodes |= pd->clipCode;
  3660. #ifdef POLYARRAY_AND_CLIPCODES
  3661. pa->andClipCodes &= pd->clipCode;
  3662. #endif
  3663. // Assert that aIndices[0] was initialized in Begin
  3664. ASSERTOPENGL(!pa->aIndices || pa->aIndices[0] == 0,
  3665. "bad index mapping\n");
  3666. }
  3667. // Need at least 4 vertices.
  3668. if (nIndices < 4)
  3669. {
  3670. ASSERTOPENGL(!(pa->flags & POLYARRAY_PARTIAL_END),
  3671. "Partial end with insufficient vertices\n");
  3672. return;
  3673. }
  3674. // If the primitive is only partially complete, save the last two
  3675. // vertices for next batch.
  3676. if (pa->flags & POLYARRAY_PARTIAL_END)
  3677. {
  3678. pd0 = pa->pd0;
  3679. pd = aIndices ? &pd0[aIndices[nIndices-2]] : &pd0[nIndices-2];
  3680. PA_COPY_PROCESSED_VERTEX(&gc->vertex.pdSaved[0], pd);
  3681. pd = aIndices ? &pd0[aIndices[nIndices-1]] : &pd0[nIndices-1];
  3682. PA_COPY_PROCESSED_VERTEX(&gc->vertex.pdSaved[1], pd);
  3683. // Need not render this partial primitive if it is completely clipped.
  3684. #ifdef POLYARRAY_AND_CLIPCODES
  3685. if (pa->andClipCodes != 0)
  3686. return;
  3687. #endif
  3688. }
  3689. // Assert that pa->nIndices is correct if aIndices is identity
  3690. ASSERTOPENGL(pa->aIndices || pa->nIndices == pa->pdNextVertex - pa->pd0,
  3691. "bad nIndices\n");
  3692. // Render the quad strip.
  3693. // Call PolyArrayRenderQStrip later
  3694. pa->flags |= POLYARRAY_RENDER_PRIMITIVE;
  3695. }
  3696. #endif // NEW_PARTIAL_PRIM
  3697. void FASTCALL PolyArrayRenderQStrip(__GLcontext *gc, POLYARRAY *pa)
  3698. {
  3699. GLint i, iLast4;
  3700. GLubyte *aIndices;
  3701. POLYDATA *pd0;
  3702. void (*rq)(__GLcontext *gc, __GLvertex *v0, __GLvertex *v1, __GLvertex *v2,
  3703. __GLvertex *v3);
  3704. iLast4 = pa->nIndices - 4;
  3705. pd0 = pa->pd0;
  3706. rq = pa->orClipCodes ? PARenderQuadSlow : PARenderQuadFast;
  3707. if (iLast4 < 0)
  3708. return;
  3709. // Vertex ordering is important. Line stippling uses it.
  3710. if (!(aIndices = pa->aIndices))
  3711. {
  3712. // Identity mapping
  3713. // Initialize first 2 vertices so we can start rendering the quad
  3714. // below. The edge flags are not modified by our lower level routines.
  3715. pd0[0].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3716. pd0[1].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3717. for (i = 0; i <= iLast4; i += 2)
  3718. {
  3719. /* setup for rendering this quad */
  3720. gc->line.notResetStipple = GL_FALSE;
  3721. gc->vertex.provoking = (__GLvertex *) &pd0[i+3];
  3722. pd0[i+2].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3723. pd0[i+3].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3724. /* Render the quad (NOTE: i, i+1, i+3, i+2) */
  3725. (*rq)(gc, (__GLvertex *) &pd0[i ],
  3726. (__GLvertex *) &pd0[i+1],
  3727. (__GLvertex *) &pd0[i+3],
  3728. (__GLvertex *) &pd0[i+2]);
  3729. }
  3730. }
  3731. else
  3732. {
  3733. // Initialize first 2 vertices so we can start rendering the quad
  3734. // below. The edge flags are not modified by our lower level routines.
  3735. pd0[aIndices[0]].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3736. pd0[aIndices[1]].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3737. for (i = 0; i <= iLast4; i += 2)
  3738. {
  3739. /* setup for rendering this quad */
  3740. gc->line.notResetStipple = GL_FALSE;
  3741. gc->vertex.provoking = (__GLvertex *) &pd0[aIndices[i+3]];
  3742. pd0[aIndices[i+2]].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3743. pd0[aIndices[i+3]].flags |= POLYDATA_EDGEFLAG_BOUNDARY;
  3744. /* Render the quad (NOTE: i, i+1, i+3, i+2) */
  3745. (*rq)(gc, (__GLvertex *) &pd0[aIndices[i ]],
  3746. (__GLvertex *) &pd0[aIndices[i+1]],
  3747. (__GLvertex *) &pd0[aIndices[i+3]],
  3748. (__GLvertex *) &pd0[aIndices[i+2]]);
  3749. }
  3750. }
  3751. }
  3752. // ---------------------------------------------------------
  3753. #ifndef NEW_PARTIAL_PRIM
  3754. void FASTCALL PolyArrayDrawPolygon(__GLcontext *gc, POLYARRAY *pa)
  3755. {
  3756. GLint nIndices;
  3757. POLYDATA *pd, *pd0;
  3758. // Index mapping is always identity in Polygon.
  3759. ASSERTOPENGL(!pa->aIndices, "Index mapping must be identity\n");
  3760. nIndices = pa->nIndices;
  3761. // If we are continuing with a previously decomposed polygon, we need to
  3762. // insert the original first vertex and the last two vertices of the
  3763. // previous polygon at the beginning of the current batch(see note below).
  3764. // The decomposer expects the polygon vertices to be in sequential memory
  3765. // order.
  3766. if (pa->flags & POLYARRAY_PARTIAL_BEGIN)
  3767. {
  3768. ASSERTOPENGL(!(pa->flags & POLYARRAY_RESET_STIPPLE),
  3769. "bad stipple reset flag!\n");
  3770. // Insert previous end vertices at the beginning and update clip code
  3771. pd = --pa->pd0;
  3772. ASSERTOPENGL(pd > (POLYDATA *) pa, "vertex underflows\n");
  3773. PA_COPY_PROCESSED_VERTEX(pd, &gc->vertex.pdSaved[2]);
  3774. pa->orClipCodes |= pd->clipCode;
  3775. #ifdef POLYARRAY_AND_CLIPCODES
  3776. pa->andClipCodes &= pd->clipCode;
  3777. #endif
  3778. pd = --pa->pd0;
  3779. ASSERTOPENGL(pd > (POLYDATA *) pa, "vertex underflows\n");
  3780. PA_COPY_PROCESSED_VERTEX(pd, &gc->vertex.pdSaved[1]);
  3781. pa->orClipCodes |= pd->clipCode;
  3782. #ifdef POLYARRAY_AND_CLIPCODES
  3783. pa->andClipCodes &= pd->clipCode;
  3784. #endif
  3785. // Insert the origin first vertex at the beginning and update clip
  3786. // code
  3787. pd = --pa->pd0;
  3788. ASSERTOPENGL(pd > (POLYDATA *) pa, "vertex underflows\n");
  3789. PA_COPY_PROCESSED_VERTEX(pd, &gc->vertex.pdSaved[0]);
  3790. pa->orClipCodes |= pd->clipCode;
  3791. #ifdef POLYARRAY_AND_CLIPCODES
  3792. pa->andClipCodes &= pd->clipCode;
  3793. #endif
  3794. }
  3795. else
  3796. {
  3797. // New polygon.
  3798. ASSERTOPENGL(pa->flags & POLYARRAY_RESET_STIPPLE,
  3799. "bad stipple reset flag!\n");
  3800. }
  3801. // Need at least 3 vertices.
  3802. if (nIndices < 3)
  3803. {
  3804. ASSERTOPENGL(!(pa->flags & POLYARRAY_PARTIAL_END),
  3805. "Partial end with insufficient vertices\n");
  3806. ASSERTOPENGL(!(pa->flags & POLYARRAY_PARTIAL_BEGIN),
  3807. "Partial begin with insufficient vertices\n");
  3808. return;
  3809. }
  3810. // If the primitive is only partially complete, save the last 2 vertices
  3811. // for next batch. Also save the original first vertex of the polygon.
  3812. if (pa->flags & POLYARRAY_PARTIAL_END)
  3813. {
  3814. // Since there may be no vertex following this partial primitive, we
  3815. // cannot determine the edge flag of the last vertex in this batch.
  3816. // So we save the last vertex for next batch instead.
  3817. pd0 = pa->pd0;
  3818. pd = &pd0[nIndices-1];
  3819. PA_COPY_PROCESSED_VERTEX(&gc->vertex.pdSaved[2], pd);
  3820. // Remove the last vertex from this partial primitive
  3821. nIndices = --pa->nIndices;
  3822. pa->pdNextVertex--;
  3823. // Mark the closing edge of this decomposed polygon as non-boundary
  3824. // because we are synthetically generating it.
  3825. pd--;
  3826. PA_COPY_PROCESSED_VERTEX(&gc->vertex.pdSaved[1], pd);
  3827. pd->flags &= ~POLYDATA_EDGEFLAG_BOUNDARY;
  3828. if (!(pa->flags & POLYARRAY_PARTIAL_BEGIN))
  3829. {
  3830. PA_COPY_PROCESSED_VERTEX(&gc->vertex.pdSaved[0], pd0);
  3831. // Mark the first polygon vertex's edge tag as non-boundary
  3832. // because when it gets rendered again it will no longer be
  3833. // a boundary edge.
  3834. gc->vertex.pdSaved[0].flags &= ~POLYDATA_EDGEFLAG_BOUNDARY;
  3835. }
  3836. // Need not render this partial primitive if it is completely clipped.
  3837. #ifdef POLYARRAY_AND_CLIPCODES
  3838. if (pa->andClipCodes != 0)
  3839. return;
  3840. #endif
  3841. }
  3842. // The polygon clipper can only handle this many vertices.
  3843. ASSERTOPENGL(nIndices <= __GL_MAX_POLYGON_CLIP_SIZE,
  3844. "too many points for the polygon clipper!\n");
  3845. // Assert that pa->nIndices is correct
  3846. ASSERTOPENGL(pa->nIndices == pa->pdNextVertex - pa->pd0,
  3847. "bad nIndices\n");
  3848. // Render the polygon.
  3849. // Call PolyArrayRenderPolygon later
  3850. pa->flags |= POLYARRAY_RENDER_PRIMITIVE;
  3851. }
  3852. #endif // NEW_PARTIAL_PRIM
  3853. void FASTCALL PolyArrayRenderPolygon(__GLcontext *gc, POLYARRAY *pa)
  3854. {
  3855. // Index mapping is always identity in Polygon.
  3856. ASSERTOPENGL(!pa->aIndices, "Index mapping must be identity\n");
  3857. // Reset the line stipple if this is a new polygon.
  3858. if (pa->flags & POLYARRAY_RESET_STIPPLE)
  3859. gc->line.notResetStipple = GL_FALSE;
  3860. // Note that the provoking vertex is set to pd0 in clipPolygon
  3861. (*gc->procs.clipPolygon)(gc, (__GLvertex *) pa->pd0, pa->nIndices);
  3862. }
  3863. /****************************************************************************/
  3864. // Note: The first vertex must have a valid normal!
  3865. //
  3866. // IN: obj/eye, normal
  3867. // OUT: eye, color.r (front or back depending on face) (all vertices are
  3868. // updated)
  3869. void FASTCALL PolyArrayCalcCIColor(__GLcontext *gc, GLint face, POLYARRAY *pa, POLYDATA *pdFirst, POLYDATA *pdLast)
  3870. {
  3871. __GLfloat nxi, nyi, nzi;
  3872. __GLfloat zero;
  3873. __GLlightSourceMachine *lsm;
  3874. __GLmaterialState *ms;
  3875. __GLmaterialMachine *msm;
  3876. __GLfloat msm_threshold, msm_scale, *msm_specTable;
  3877. __GLfloat ms_cmapa, ms_cmapd, ms_cmaps;
  3878. __GLfloat si, di;
  3879. POLYDATA *pd;
  3880. GLfloat redMaxF;
  3881. GLint redMaxI;
  3882. GLboolean eyeWIsZero, localViewer;
  3883. static __GLcoord Pe = { 0, 0, 0, 1 };
  3884. #ifdef GL_WIN_specular_fog
  3885. __GLfloat fog;
  3886. #endif //GL_WIN_specular_fog
  3887. PERF_CHECK(FALSE, "Uses slow lights\n");
  3888. zero = __glZero;
  3889. if (face == __GL_FRONTFACE)
  3890. {
  3891. ms = &gc->state.light.front;
  3892. msm = &gc->light.front;
  3893. }
  3894. else
  3895. {
  3896. ms = &gc->state.light.back;
  3897. msm = &gc->light.back;
  3898. }
  3899. msm_scale = msm->scale;
  3900. msm_threshold = msm->threshold;
  3901. msm_specTable = msm->specTable;
  3902. ms_cmapa = ms->cmapa;
  3903. ms_cmapd = ms->cmapd;
  3904. ms_cmaps = ms->cmaps;
  3905. localViewer = gc->state.light.model.localViewer;
  3906. redMaxF = (GLfloat) gc->frontBuffer.redMax;
  3907. redMaxI = (GLint) gc->frontBuffer.redMax;
  3908. // Eye coord should have been processed
  3909. ASSERTOPENGL(pa->flags & POLYARRAY_EYE_PROCESSED, "need eye\n");
  3910. // NOTE: the following values may be re-used in the next iteration:
  3911. // nxi, nyi, nzi
  3912. for (pd = pdFirst; pd <= pdLast; pd++)
  3913. {
  3914. __GLfloat ci;
  3915. if (pd->flags & POLYDATA_NORMAL_VALID)
  3916. {
  3917. if (face == __GL_FRONTFACE)
  3918. {
  3919. nxi = pd->normal.x;
  3920. nyi = pd->normal.y;
  3921. nzi = pd->normal.z;
  3922. }
  3923. else
  3924. {
  3925. nxi = -pd->normal.x;
  3926. nyi = -pd->normal.y;
  3927. nzi = -pd->normal.z;
  3928. }
  3929. }
  3930. else
  3931. {
  3932. // use previous normal (nxi, nyi, nzi)!
  3933. #ifdef GL_WIN_specular_fog
  3934. // use previous fog (fog)!
  3935. #endif //GL_WIN_specular_fog
  3936. ASSERTOPENGL(pd != pdFirst, "no initial normal\n");
  3937. }
  3938. si = zero;
  3939. di = zero;
  3940. eyeWIsZero = __GL_FLOAT_EQZ(pd->eye.w);
  3941. #ifdef GL_WIN_specular_fog
  3942. // Initialize Fog value to 0 here;
  3943. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  3944. {
  3945. ASSERTOPENGL (face == __GL_FRONTFACE,
  3946. "Specular fog works for only GL_FRONT\n");
  3947. fog = __glZero;
  3948. }
  3949. #endif //GL_WIN_specular_fog
  3950. for (lsm = gc->light.sources; lsm; lsm = lsm->next)
  3951. {
  3952. if (lsm->slowPath || eyeWIsZero)
  3953. {
  3954. __GLfloat n1, n2, att, attSpot;
  3955. __GLcoord vPliHat, vPli, hHat, vPeHat;
  3956. __GLfloat hv[3];
  3957. /* Compute vPli, hi (normalized) */
  3958. __glVecSub4(&vPli, &pd->eye, &lsm->position);
  3959. __glNormalize(&vPliHat.x, &vPli.x);
  3960. if (localViewer)
  3961. {
  3962. __glVecSub4(&vPeHat, &pd->eye, &Pe);
  3963. __glNormalize(&vPeHat.x, &vPeHat.x);
  3964. hv[0] = vPliHat.x + vPeHat.x;
  3965. hv[1] = vPliHat.y + vPeHat.y;
  3966. hv[2] = vPliHat.z + vPeHat.z;
  3967. }
  3968. else
  3969. {
  3970. hv[0] = vPliHat.x;
  3971. hv[1] = vPliHat.y;
  3972. hv[2] = vPliHat.z + __glOne;
  3973. }
  3974. __glNormalize(&hHat.x, hv);
  3975. /* Compute attenuation */
  3976. if (__GL_FLOAT_NEZ(lsm->position.w))
  3977. {
  3978. __GLfloat k0, k1, k2, dist;
  3979. k0 = lsm->constantAttenuation;
  3980. k1 = lsm->linearAttenuation;
  3981. k2 = lsm->quadraticAttenuation;
  3982. if (__GL_FLOAT_EQZ(k1) && __GL_FLOAT_EQZ(k2))
  3983. {
  3984. /* Use pre-computed 1/k0 */
  3985. att = lsm->attenuation;
  3986. }
  3987. else
  3988. {
  3989. dist = __GL_SQRTF(vPli.x*vPli.x + vPli.y*vPli.y
  3990. + vPli.z*vPli.z);
  3991. att = __glOne / (k0 + k1 * dist + k2 * dist * dist);
  3992. }
  3993. }
  3994. else
  3995. {
  3996. att = __glOne;
  3997. }
  3998. /* Compute spot effect if light is a spot light */
  3999. attSpot = att;
  4000. if (lsm->isSpot)
  4001. {
  4002. __GLfloat dot, px, py, pz;
  4003. px = -vPliHat.x;
  4004. py = -vPliHat.y;
  4005. pz = -vPliHat.z;
  4006. dot = px * lsm->direction.x + py * lsm->direction.y
  4007. + pz * lsm->direction.z;
  4008. if ((dot >= lsm->threshold) && (dot >= lsm->cosCutOffAngle))
  4009. {
  4010. GLint ix = (GLint)((dot - lsm->threshold) * lsm->scale
  4011. + __glHalf);
  4012. if (ix < __GL_SPOT_LOOKUP_TABLE_SIZE)
  4013. attSpot = att * lsm->spotTable[ix];
  4014. }
  4015. else
  4016. {
  4017. attSpot = zero;
  4018. }
  4019. }
  4020. /* Add in remaining effect of light, if any */
  4021. if (attSpot)
  4022. {
  4023. n1 = nxi * vPliHat.x + nyi * vPliHat.y + nzi * vPliHat.z;
  4024. if (__GL_FLOAT_GTZ(n1)) {
  4025. n2 = nxi * hHat.x + nyi * hHat.y + nzi * hHat.z;
  4026. n2 -= msm_threshold;
  4027. if (__GL_FLOAT_GEZ(n2))
  4028. {
  4029. #ifdef NT
  4030. __GLfloat fx = n2 * msm_scale + __glHalf;
  4031. if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE )
  4032. n2 = msm_specTable[(GLint)fx];
  4033. else
  4034. n2 = __glOne;
  4035. #ifdef GL_WIN_specular_fog
  4036. if (gc->polygon.shader.modeFlags &
  4037. __GL_SHADE_SPEC_FOG)
  4038. {
  4039. fog += attSpot * n2;
  4040. }
  4041. #endif //GL_WIN_specular_fog
  4042. #else
  4043. GLint ix = (GLint)(n2 * msm_scale + __glHalf);
  4044. if (ix < __GL_SPEC_LOOKUP_TABLE_SIZE)
  4045. n2 = msm_specTable[ix];
  4046. else
  4047. n2 = __glOne;
  4048. #endif
  4049. si += attSpot * n2 * lsm->sli;
  4050. }
  4051. di += attSpot * n1 * lsm->dli;
  4052. }
  4053. }
  4054. }
  4055. else
  4056. {
  4057. __GLfloat n1, n2;
  4058. /* Compute specular contribution */
  4059. n1 = nxi * lsm->unitVPpli.x + nyi * lsm->unitVPpli.y +
  4060. nzi * lsm->unitVPpli.z;
  4061. if (__GL_FLOAT_GTZ(n1))
  4062. {
  4063. n2 = nxi * lsm->hHat.x + nyi * lsm->hHat.y + nzi * lsm->hHat.z;
  4064. n2 -= msm_threshold;
  4065. if (__GL_FLOAT_GEZ(n2))
  4066. {
  4067. #ifdef NT
  4068. __GLfloat fx = n2 * msm_scale + __glHalf;
  4069. if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE )
  4070. n2 = msm_specTable[(GLint)fx];
  4071. else
  4072. n2 = __glOne;
  4073. #ifdef GL_WIN_specular_fog
  4074. if (gc->polygon.shader.modeFlags &
  4075. __GL_SHADE_SPEC_FOG)
  4076. {
  4077. fog += n2;
  4078. }
  4079. #endif //GL_WIN_specular_fog
  4080. #else
  4081. GLint ix = (GLint)(n2 * msm_scale + __glHalf);
  4082. if (ix < __GL_SPEC_LOOKUP_TABLE_SIZE)
  4083. n2 = msm_specTable[ix];
  4084. else
  4085. n2 = __glOne;
  4086. #endif
  4087. si += n2 * lsm->sli;
  4088. }
  4089. di += n1 * lsm->dli;
  4090. }
  4091. }
  4092. }
  4093. /* Compute final color */
  4094. if (si > __glOne)
  4095. si = __glOne;
  4096. ci = ms_cmapa + (__glOne - si) * di * (ms_cmapd - ms_cmapa)
  4097. + si * (ms_cmaps - ms_cmapa);
  4098. if (ci > ms_cmaps)
  4099. ci = ms_cmaps;
  4100. // need to mask color index before color clipping
  4101. if (ci > redMaxF) {
  4102. GLfloat fraction;
  4103. GLint integer;
  4104. integer = (GLint) ci;
  4105. fraction = ci - (GLfloat) integer;
  4106. integer = integer & redMaxI;
  4107. ci = (GLfloat) integer + fraction;
  4108. } else if (ci < 0) {
  4109. GLfloat fraction;
  4110. GLint integer;
  4111. integer = (GLint) __GL_FLOORF(ci);
  4112. fraction = ci - (GLfloat) integer;
  4113. integer = integer & redMaxI;
  4114. ci = (GLfloat) integer + fraction;
  4115. }
  4116. pd->colors[face].r = ci;
  4117. #ifdef GL_WIN_specular_fog
  4118. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  4119. {
  4120. pd->fog = 1.0 - fog;
  4121. if (__GL_FLOAT_LTZ (pd->fog)) pd->fog = __glZero;
  4122. }
  4123. #endif //GL_WIN_specular_fog
  4124. }
  4125. }
  4126. // No slow lights version
  4127. // Note: The first vertex must have a valid normal!
  4128. //
  4129. // IN: normal
  4130. // OUT: color.r (front or back depending on face) (all vertices are updated)
  4131. void FASTCALL PolyArrayFastCalcCIColor(__GLcontext *gc, GLint face, POLYARRAY *pa, POLYDATA *pdFirst, POLYDATA *pdLast)
  4132. {
  4133. __GLfloat nxi, nyi, nzi;
  4134. __GLfloat zero;
  4135. __GLlightSourceMachine *lsm;
  4136. __GLmaterialState *ms;
  4137. __GLmaterialMachine *msm;
  4138. __GLfloat msm_threshold, msm_scale, *msm_specTable;
  4139. __GLfloat ms_cmapa, ms_cmapd, ms_cmaps;
  4140. __GLfloat si, di;
  4141. POLYDATA *pd;
  4142. GLfloat redMaxF;
  4143. GLint redMaxI;
  4144. #ifdef GL_WIN_specular_fog
  4145. __GLfloat fog;
  4146. #endif //GL_WIN_specular_fog
  4147. #if LATER
  4148. // if eye.w is zero, it should really take the slow path!
  4149. // Since the RGB version ignores it, we will also ignore it here.
  4150. // Even the original generic implementation may not have computed eye values.
  4151. #endif
  4152. zero = __glZero;
  4153. if (face == __GL_FRONTFACE)
  4154. {
  4155. ms = &gc->state.light.front;
  4156. msm = &gc->light.front;
  4157. }
  4158. else
  4159. {
  4160. ms = &gc->state.light.back;
  4161. msm = &gc->light.back;
  4162. }
  4163. msm_scale = msm->scale;
  4164. msm_threshold = msm->threshold;
  4165. msm_specTable = msm->specTable;
  4166. ms_cmapa = ms->cmapa;
  4167. ms_cmapd = ms->cmapd;
  4168. ms_cmaps = ms->cmaps;
  4169. redMaxF = (GLfloat) gc->frontBuffer.redMax;
  4170. redMaxI = (GLint) gc->frontBuffer.redMax;
  4171. // NOTE: the following values may be re-used in the next iteration:
  4172. // nxi, nyi, nzi
  4173. for (pd = pdFirst; pd <= pdLast; pd++)
  4174. {
  4175. __GLfloat ci;
  4176. // If normal has not changed for this vertex, use the previously
  4177. // computed color index.
  4178. if (!(pd->flags & POLYDATA_NORMAL_VALID))
  4179. {
  4180. ASSERTOPENGL(pd != pdFirst, "no initial normal\n");
  4181. pd->colors[face].r = (pd-1)->colors[face].r;
  4182. #ifdef GL_WIN_specular_fog
  4183. // Initialize Fog value to 0 here;
  4184. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  4185. {
  4186. ASSERTOPENGL (face == __GL_FRONTFACE,
  4187. "Specular fog works for only GL_FRONT\n");
  4188. pd->fog = (pd-1)->fog;
  4189. }
  4190. #endif //GL_WIN_specular_fog
  4191. continue;
  4192. }
  4193. if (face == __GL_FRONTFACE)
  4194. {
  4195. nxi = pd->normal.x;
  4196. nyi = pd->normal.y;
  4197. nzi = pd->normal.z;
  4198. }
  4199. else
  4200. {
  4201. nxi = -pd->normal.x;
  4202. nyi = -pd->normal.y;
  4203. nzi = -pd->normal.z;
  4204. }
  4205. si = zero;
  4206. di = zero;
  4207. #ifdef GL_WIN_specular_fog
  4208. // Initialize Fog value to 0 here;
  4209. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  4210. {
  4211. fog = __glZero;
  4212. }
  4213. #endif //GL_WIN_specular_fog
  4214. for (lsm = gc->light.sources; lsm; lsm = lsm->next)
  4215. {
  4216. __GLfloat n1, n2;
  4217. /* Compute specular contribution */
  4218. n1 = nxi * lsm->unitVPpli.x + nyi * lsm->unitVPpli.y +
  4219. nzi * lsm->unitVPpli.z;
  4220. if (__GL_FLOAT_GTZ(n1))
  4221. {
  4222. n2 = nxi * lsm->hHat.x + nyi * lsm->hHat.y + nzi * lsm->hHat.z;
  4223. n2 -= msm_threshold;
  4224. if (__GL_FLOAT_GEZ(n2))
  4225. {
  4226. #ifdef NT
  4227. __GLfloat fx = n2 * msm_scale + __glHalf;
  4228. if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE )
  4229. n2 = msm_specTable[(GLint)fx];
  4230. else
  4231. n2 = __glOne;
  4232. #else
  4233. GLint ix = (GLint)(n2 * msm_scale + __glHalf);
  4234. if (ix < __GL_SPEC_LOOKUP_TABLE_SIZE)
  4235. n2 = msm_specTable[ix];
  4236. else
  4237. n2 = __glOne;
  4238. #endif
  4239. si += n2 * lsm->sli;
  4240. #ifdef GL_WIN_specular_fog
  4241. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  4242. {
  4243. fog += n2;
  4244. }
  4245. #endif //GL_WIN_specular_fog
  4246. }
  4247. di += n1 * lsm->dli;
  4248. }
  4249. }
  4250. /* Compute final color */
  4251. if (si > __glOne)
  4252. si = __glOne;
  4253. ci = ms_cmapa + (__glOne - si) * di * (ms_cmapd - ms_cmapa)
  4254. + si * (ms_cmaps - ms_cmapa);
  4255. if (ci > ms_cmaps)
  4256. ci = ms_cmaps;
  4257. // need to mask color index before color clipping
  4258. // SGIBUG: The sample implementation fails to do this!
  4259. if (ci > redMaxF) {
  4260. GLfloat fraction;
  4261. GLint integer;
  4262. integer = (GLint) ci;
  4263. fraction = ci - (GLfloat) integer;
  4264. integer = integer & redMaxI;
  4265. ci = (GLfloat) integer + fraction;
  4266. } else if (ci < 0) {
  4267. GLfloat fraction;
  4268. GLint integer;
  4269. integer = (GLint) __GL_FLOORF(ci);
  4270. fraction = ci - (GLfloat) integer;
  4271. integer = integer & redMaxI;
  4272. ci = (GLfloat) integer + fraction;
  4273. }
  4274. pd->colors[face].r = ci;
  4275. #ifdef GL_WIN_specular_fog
  4276. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  4277. {
  4278. pd->fog = 1.0 - fog;
  4279. if (__GL_FLOAT_LTZ (pd->fog)) pd->fog = __glZero;
  4280. }
  4281. #endif //GL_WIN_specular_fog
  4282. }
  4283. }
  4284. // If both front and back colors are needed, the back colors must be computed
  4285. // first! Otherwise, the front colors can be overwritten prematurely.
  4286. // Note: The first vertex must have valid normal and color!
  4287. //
  4288. // IN: obj/eye, color (front), normal
  4289. // OUT: eye, color (front or back depending on face) (all vertices are updated)
  4290. void FASTCALL PolyArrayCalcRGBColor(__GLcontext *gc, GLint face, POLYARRAY *pa, POLYDATA *pdFirst, POLYDATA *pdLast)
  4291. {
  4292. __GLfloat nxi, nyi, nzi;
  4293. __GLfloat zero;
  4294. __GLlightSourcePerMaterialMachine *lspmm;
  4295. __GLlightSourceMachine *lsm;
  4296. __GLlightSourceState *lss;
  4297. __GLfloat ri, gi, bi;
  4298. __GLfloat alpha;
  4299. __GLfloat rsi, gsi, bsi;
  4300. __GLcolor sceneColorI;
  4301. __GLmaterialMachine *msm;
  4302. __GLcolor lm_ambient;
  4303. __GLfloat msm_alpha, msm_threshold, msm_scale, *msm_specTable;
  4304. __GLcolor msm_paSceneColor;
  4305. GLuint msm_colorMaterialChange;
  4306. POLYDATA *pd;
  4307. GLboolean eyeWIsZero, localViewer;
  4308. static __GLcoord Pe = { 0, 0, 0, 1 };
  4309. #ifdef GL_WIN_specular_fog
  4310. __GLfloat fog;
  4311. #endif //GL_WIN_specular_fog
  4312. PERF_CHECK(FALSE, "Uses slow lights\n");
  4313. zero = __glZero;
  4314. // Eye coord should have been processed
  4315. ASSERTOPENGL(pa->flags & POLYARRAY_EYE_PROCESSED, "need eye\n");
  4316. if (face == __GL_FRONTFACE)
  4317. msm = &gc->light.front;
  4318. else
  4319. msm = &gc->light.back;
  4320. lm_ambient.r = gc->state.light.model.ambient.r;
  4321. lm_ambient.g = gc->state.light.model.ambient.g;
  4322. lm_ambient.b = gc->state.light.model.ambient.b;
  4323. msm_scale = msm->scale;
  4324. msm_threshold = msm->threshold;
  4325. msm_specTable = msm->specTable;
  4326. msm_alpha = msm->alpha;
  4327. msm_colorMaterialChange = msm->colorMaterialChange;
  4328. msm_paSceneColor = msm->paSceneColor;
  4329. localViewer = gc->state.light.model.localViewer;
  4330. // Get invarient scene color if there is no ambient or emissive color
  4331. // material.
  4332. sceneColorI.r = msm_paSceneColor.r;
  4333. sceneColorI.g = msm_paSceneColor.g;
  4334. sceneColorI.b = msm_paSceneColor.b;
  4335. // NOTE: the following values may be re-used in the next iteration:
  4336. // ri, gi, bi, alpha, nxi, nyi, nzi, sceneColorI
  4337. for (pd = pdFirst; pd <= pdLast; pd++)
  4338. {
  4339. if (pd->flags & POLYDATA_COLOR_VALID)
  4340. {
  4341. // Save latest colors normalized to 0..1
  4342. ri = pd->colors[0].r * gc->oneOverRedVertexScale;
  4343. gi = pd->colors[0].g * gc->oneOverGreenVertexScale;
  4344. bi = pd->colors[0].b * gc->oneOverBlueVertexScale;
  4345. alpha = pd->colors[0].a;
  4346. // Compute scene color.
  4347. // If color has not changed, the previous sceneColorI values are
  4348. // used!
  4349. if (msm_colorMaterialChange & (__GL_MATERIAL_AMBIENT |
  4350. __GL_MATERIAL_EMISSIVE))
  4351. {
  4352. if (msm_colorMaterialChange & __GL_MATERIAL_AMBIENT)
  4353. {
  4354. sceneColorI.r = msm_paSceneColor.r + ri * lm_ambient.r;
  4355. sceneColorI.g = msm_paSceneColor.g + gi * lm_ambient.g;
  4356. sceneColorI.b = msm_paSceneColor.b + bi * lm_ambient.b;
  4357. }
  4358. else
  4359. {
  4360. sceneColorI.r = msm_paSceneColor.r + pd->colors[0].r;
  4361. sceneColorI.g = msm_paSceneColor.g + pd->colors[0].g;
  4362. sceneColorI.b = msm_paSceneColor.b + pd->colors[0].b;
  4363. }
  4364. }
  4365. }
  4366. else
  4367. {
  4368. // use previous ri, gi, bi, alpha, and sceneColorI!
  4369. ASSERTOPENGL(pd != pdFirst, "no initial color\n");
  4370. }
  4371. // Compute the diffuse and specular components for this vertex.
  4372. if (pd->flags & POLYDATA_NORMAL_VALID)
  4373. {
  4374. if (face == __GL_FRONTFACE)
  4375. {
  4376. nxi = pd->normal.x;
  4377. nyi = pd->normal.y;
  4378. nzi = pd->normal.z;
  4379. }
  4380. else
  4381. {
  4382. nxi = -pd->normal.x;
  4383. nyi = -pd->normal.y;
  4384. nzi = -pd->normal.z;
  4385. }
  4386. #ifdef GL_WIN_specular_fog
  4387. // Initialize Fog value to 0 here;
  4388. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  4389. {
  4390. ASSERTOPENGL (face == __GL_FRONTFACE,
  4391. "Specular fog works for only GL_FRONT\n");
  4392. fog = __glZero;
  4393. }
  4394. #endif //GL_WIN_specular_fog
  4395. }
  4396. else
  4397. {
  4398. // use previous normal (nxi, nyi, nzi)!
  4399. ASSERTOPENGL(pd != pdFirst, "no initial normal\n");
  4400. #ifdef GL_WIN_specular_fog
  4401. // use previous fog (fog)!
  4402. #endif //GL_WIN_specular_fog
  4403. }
  4404. rsi = sceneColorI.r;
  4405. gsi = sceneColorI.g;
  4406. bsi = sceneColorI.b;
  4407. eyeWIsZero = __GL_FLOAT_EQZ(pd->eye.w);
  4408. for (lsm = gc->light.sources; lsm; lsm = lsm->next)
  4409. {
  4410. __GLfloat n1, n2;
  4411. lss = lsm->state;
  4412. lspmm = &lsm->front + face;
  4413. if (lsm->slowPath || eyeWIsZero)
  4414. {
  4415. __GLcoord hHat, vPli, vPliHat, vPeHat;
  4416. __GLfloat att, attSpot;
  4417. __GLfloat hv[3];
  4418. /* Compute unit h[i] */
  4419. __glVecSub4(&vPli, &pd->eye, &lsm->position);
  4420. __glNormalize(&vPliHat.x, &vPli.x);
  4421. if (localViewer)
  4422. {
  4423. __glVecSub4(&vPeHat, &pd->eye, &Pe);
  4424. __glNormalize(&vPeHat.x, &vPeHat.x);
  4425. hv[0] = vPliHat.x + vPeHat.x;
  4426. hv[1] = vPliHat.y + vPeHat.y;
  4427. hv[2] = vPliHat.z + vPeHat.z;
  4428. }
  4429. else
  4430. {
  4431. hv[0] = vPliHat.x;
  4432. hv[1] = vPliHat.y;
  4433. hv[2] = vPliHat.z + __glOne;
  4434. }
  4435. __glNormalize(&hHat.x, hv);
  4436. /* Compute attenuation */
  4437. if (__GL_FLOAT_NEZ(lsm->position.w))
  4438. {
  4439. __GLfloat k0, k1, k2, dist;
  4440. k0 = lsm->constantAttenuation;
  4441. k1 = lsm->linearAttenuation;
  4442. k2 = lsm->quadraticAttenuation;
  4443. if (__GL_FLOAT_EQZ(k1) && __GL_FLOAT_EQZ(k2))
  4444. {
  4445. /* Use pre-computed 1/k0 */
  4446. att = lsm->attenuation;
  4447. }
  4448. else
  4449. {
  4450. dist = __GL_SQRTF(vPli.x*vPli.x + vPli.y*vPli.y
  4451. + vPli.z*vPli.z);
  4452. att = __glOne / (k0 + k1 * dist + k2 * dist * dist);
  4453. }
  4454. }
  4455. else
  4456. {
  4457. att = __glOne;
  4458. }
  4459. /* Compute spot effect if light is a spot light */
  4460. attSpot = att;
  4461. if (lsm->isSpot)
  4462. {
  4463. __GLfloat dot, px, py, pz;
  4464. px = -vPliHat.x;
  4465. py = -vPliHat.y;
  4466. pz = -vPliHat.z;
  4467. dot = px * lsm->direction.x + py * lsm->direction.y
  4468. + pz * lsm->direction.z;
  4469. if ((dot >= lsm->threshold) && (dot >= lsm->cosCutOffAngle))
  4470. {
  4471. GLint ix = (GLint)((dot - lsm->threshold) * lsm->scale
  4472. + __glHalf);
  4473. if (ix < __GL_SPOT_LOOKUP_TABLE_SIZE)
  4474. attSpot = att * lsm->spotTable[ix];
  4475. }
  4476. else
  4477. {
  4478. attSpot = zero;
  4479. }
  4480. }
  4481. /* Add in remaining effect of light, if any */
  4482. if (attSpot)
  4483. {
  4484. __GLfloat n1, n2;
  4485. __GLcolor sum;
  4486. if (msm_colorMaterialChange & __GL_MATERIAL_AMBIENT)
  4487. {
  4488. sum.r = ri * lss->ambient.r;
  4489. sum.g = gi * lss->ambient.g;
  4490. sum.b = bi * lss->ambient.b;
  4491. }
  4492. else
  4493. {
  4494. sum.r = lspmm->ambient.r;
  4495. sum.g = lspmm->ambient.g;
  4496. sum.b = lspmm->ambient.b;
  4497. }
  4498. n1 = nxi * vPliHat.x + nyi * vPliHat.y + nzi * vPliHat.z;
  4499. if (__GL_FLOAT_GTZ(n1))
  4500. {
  4501. n2 = nxi * hHat.x + nyi * hHat.y + nzi * hHat.z;
  4502. n2 -= msm_threshold;
  4503. if (__GL_FLOAT_GEZ(n2))
  4504. {
  4505. #ifdef NT
  4506. __GLfloat fx = n2 * msm_scale + __glHalf;
  4507. if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE )
  4508. n2 = msm_specTable[(GLint)fx];
  4509. else
  4510. n2 = __glOne;
  4511. #ifdef GL_WIN_specular_fog
  4512. if (gc->polygon.shader.modeFlags &
  4513. __GL_SHADE_SPEC_FOG)
  4514. {
  4515. fog += attSpot * n2;
  4516. }
  4517. #endif //GL_WIN_specular_fog
  4518. #else
  4519. GLint ix = (GLint)(n2 * msm_scale + __glHalf);
  4520. if (ix < __GL_SPEC_LOOKUP_TABLE_SIZE)
  4521. n2 = msm_specTable[ix];
  4522. else
  4523. n2 = __glOne;
  4524. #endif
  4525. if (msm_colorMaterialChange & __GL_MATERIAL_SPECULAR)
  4526. {
  4527. /* Recompute per-light per-material cached specular */
  4528. sum.r += n2 * ri * lss->specular.r;
  4529. sum.g += n2 * gi * lss->specular.g;
  4530. sum.b += n2 * bi * lss->specular.b;
  4531. }
  4532. else
  4533. {
  4534. sum.r += n2 * lspmm->specular.r;
  4535. sum.g += n2 * lspmm->specular.g;
  4536. sum.b += n2 * lspmm->specular.b;
  4537. }
  4538. }
  4539. if (msm_colorMaterialChange & __GL_MATERIAL_DIFFUSE)
  4540. {
  4541. /* Recompute per-light per-material cached diffuse */
  4542. sum.r += n1 * ri * lss->diffuse.r;
  4543. sum.g += n1 * gi * lss->diffuse.g;
  4544. sum.b += n1 * bi * lss->diffuse.b;
  4545. }
  4546. else
  4547. {
  4548. sum.r += n1 * lspmm->diffuse.r;
  4549. sum.g += n1 * lspmm->diffuse.g;
  4550. sum.b += n1 * lspmm->diffuse.b;
  4551. }
  4552. }
  4553. rsi += attSpot * sum.r;
  4554. gsi += attSpot * sum.g;
  4555. bsi += attSpot * sum.b;
  4556. }
  4557. }
  4558. else
  4559. {
  4560. __GLfloat n1, n2;
  4561. if (msm_colorMaterialChange & __GL_MATERIAL_AMBIENT)
  4562. {
  4563. rsi += ri * lss->ambient.r;
  4564. gsi += gi * lss->ambient.g;
  4565. bsi += bi * lss->ambient.b;
  4566. }
  4567. else
  4568. {
  4569. rsi += lspmm->ambient.r;
  4570. gsi += lspmm->ambient.g;
  4571. bsi += lspmm->ambient.b;
  4572. }
  4573. /* Add in specular and diffuse effect of light, if any */
  4574. n1 = nxi * lsm->unitVPpli.x + nyi * lsm->unitVPpli.y +
  4575. nzi * lsm->unitVPpli.z;
  4576. if (__GL_FLOAT_GTZ(n1))
  4577. {
  4578. n2 = nxi * lsm->hHat.x + nyi * lsm->hHat.y + nzi * lsm->hHat.z;
  4579. n2 -= msm_threshold;
  4580. if (__GL_FLOAT_GEZ(n2)) {
  4581. #ifdef NT
  4582. __GLfloat fx = n2 * msm_scale + __glHalf;
  4583. if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE )
  4584. n2 = msm_specTable[(GLint)fx];
  4585. else
  4586. n2 = __glOne;
  4587. #ifdef GL_WIN_specular_fog
  4588. if (gc->polygon.shader.modeFlags &
  4589. __GL_SHADE_SPEC_FOG)
  4590. {
  4591. fog += n2;
  4592. }
  4593. #endif //GL_WIN_specular_fog
  4594. #else
  4595. GLint ix = (GLint)(n2 * msm_scale + __glHalf);
  4596. if (ix < __GL_SPEC_LOOKUP_TABLE_SIZE)
  4597. n2 = msm_specTable[ix];
  4598. else
  4599. n2 = __glOne;
  4600. #endif
  4601. if (msm_colorMaterialChange & __GL_MATERIAL_SPECULAR)
  4602. {
  4603. /* Recompute per-light per-material cached
  4604. specular */
  4605. rsi += n2 * ri * lss->specular.r;
  4606. gsi += n2 * gi * lss->specular.g;
  4607. bsi += n2 * bi * lss->specular.b;
  4608. }
  4609. else
  4610. {
  4611. rsi += n2 * lspmm->specular.r;
  4612. gsi += n2 * lspmm->specular.g;
  4613. bsi += n2 * lspmm->specular.b;
  4614. }
  4615. }
  4616. if (msm_colorMaterialChange & __GL_MATERIAL_DIFFUSE)
  4617. {
  4618. /* Recompute per-light per-material cached diffuse */
  4619. rsi += n1 * ri * lss->diffuse.r;
  4620. gsi += n1 * gi * lss->diffuse.g;
  4621. bsi += n1 * bi * lss->diffuse.b;
  4622. }
  4623. else
  4624. {
  4625. rsi += n1 * lspmm->diffuse.r;
  4626. gsi += n1 * lspmm->diffuse.g;
  4627. bsi += n1 * lspmm->diffuse.b;
  4628. }
  4629. }
  4630. }
  4631. }
  4632. {
  4633. __GLcolor *pd_color_dst;
  4634. pd_color_dst = &pd->colors[face];
  4635. __GL_CLAMP_RGB(pd_color_dst->r,
  4636. pd_color_dst->g,
  4637. pd_color_dst->b,
  4638. gc, rsi, gsi, bsi);
  4639. if (msm_colorMaterialChange & __GL_MATERIAL_DIFFUSE)
  4640. {
  4641. if (pa->flags & POLYARRAY_CLAMP_COLOR)
  4642. {
  4643. __GL_CLAMP_A(pd_color_dst->a, gc, alpha);
  4644. }
  4645. else
  4646. pd_color_dst->a = alpha;
  4647. }
  4648. else
  4649. {
  4650. pd_color_dst->a = msm_alpha;
  4651. }
  4652. #ifdef GL_WIN_specular_fog
  4653. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  4654. {
  4655. pd->fog = 1.0 - fog;
  4656. if (__GL_FLOAT_LTZ (pd->fog)) pd->fog = __glZero;
  4657. }
  4658. #endif //GL_WIN_specular_fog
  4659. }
  4660. }
  4661. }
  4662. // If both front and back colors are needed, the back color must be computed
  4663. // first! Otherwise, the front color can be overwritten prematurely.
  4664. // Note: The first vertex must have valid normal and color!
  4665. //
  4666. // IN: color (front), normal
  4667. // OUT: color (front or back depending on face) (all vertices are updated)
  4668. #ifndef __GL_ASM_POLYARRAYFASTCALCRGBCOLOR
  4669. void FASTCALL PolyArrayFastCalcRGBColor(__GLcontext *gc, GLint face, POLYARRAY *pa, POLYDATA *pdFirst, POLYDATA *pdLast)
  4670. {
  4671. __GLfloat nxi, nyi, nzi;
  4672. __GLlightSourcePerMaterialMachine *lspmm;
  4673. __GLlightSourceMachine *lsm;
  4674. __GLlightSourceState *lss;
  4675. __GLfloat ri, gi, bi;
  4676. __GLfloat alpha;
  4677. // Don't use a structure. Compiler wants to store it on the stack,
  4678. // even though that's not necessary.
  4679. __GLfloat baseEmissiveAmbient_r, emissiveAmbientI_r, diffuseSpecularI_r;
  4680. __GLfloat baseEmissiveAmbient_g, emissiveAmbientI_g, diffuseSpecularI_g;
  4681. __GLfloat baseEmissiveAmbient_b, emissiveAmbientI_b, diffuseSpecularI_b;
  4682. __GLfloat lm_ambient_r;
  4683. __GLfloat lm_ambient_g;
  4684. __GLfloat lm_ambient_b;
  4685. __GLmaterialMachine *msm, *msm_front, *msm_back;
  4686. __GLfloat msm_alpha, msm_threshold, msm_scale, *msm_specTable;
  4687. GLuint msm_colorMaterialChange;
  4688. POLYDATA *pd;
  4689. __GLfloat diff_r, diff_g, diff_b;
  4690. __GLfloat spec_r, spec_g, spec_b;
  4691. __GLcolor *lss_diff_color, *lss_spec_color;
  4692. __GLcolor *lspmm_diff_color, *lspmm_spec_color;
  4693. __GLcolor *diff_color, *spec_color;
  4694. GLuint use_material_diffuse, use_material_specular;
  4695. GLuint use_material_ambient, use_material_emissive;
  4696. __GLfloat spec_r_sum, spec_g_sum, spec_b_sum;
  4697. __GLfloat diff_r_sum, diff_g_sum, diff_b_sum;
  4698. __GLfloat ambient_r_sum, ambient_g_sum, ambient_b_sum;
  4699. GLuint pd_flags, normal_valid, color_valid;
  4700. #ifdef GL_WIN_specular_fog
  4701. __GLfloat fog;
  4702. #endif //GL_WIN_specular_fog
  4703. #if LATER
  4704. // if eye.w is zero, it should really take the slow path!
  4705. // Since the sample implementation ignores it, we will also ignore it here.
  4706. #endif
  4707. PERF_CHECK(FALSE, "Primitives contain glColorMaterial calls\n");
  4708. msm_front = &gc->light.front;
  4709. msm_back = &gc->light.back;
  4710. msm = msm_back;
  4711. if (face == __GL_FRONTFACE)
  4712. msm = msm_front;
  4713. // If there is no color material change for this face, we can call the
  4714. // zippy function!
  4715. msm_colorMaterialChange = msm->colorMaterialChange;
  4716. if (!msm_colorMaterialChange)
  4717. {
  4718. PolyArrayZippyCalcRGBColor(gc, face, pa, pdFirst, pdLast);
  4719. return;
  4720. }
  4721. // Compute invarient emissive and ambient components for this vertex.
  4722. lm_ambient_r = gc->state.light.model.ambient.r;
  4723. lm_ambient_g = gc->state.light.model.ambient.g;
  4724. lm_ambient_b = gc->state.light.model.ambient.b;
  4725. msm_scale = msm->scale;
  4726. msm_threshold = msm->threshold;
  4727. msm_specTable = msm->specTable;
  4728. msm_alpha = msm->alpha;
  4729. use_material_ambient = msm_colorMaterialChange & __GL_MATERIAL_AMBIENT;
  4730. use_material_emissive = msm_colorMaterialChange & __GL_MATERIAL_EMISSIVE;
  4731. if (!use_material_ambient) {
  4732. baseEmissiveAmbient_r = msm->cachedEmissiveAmbient.r;
  4733. baseEmissiveAmbient_g = msm->cachedEmissiveAmbient.g;
  4734. baseEmissiveAmbient_b = msm->cachedEmissiveAmbient.b;
  4735. } else {
  4736. baseEmissiveAmbient_r = msm->paSceneColor.r;
  4737. baseEmissiveAmbient_g = msm->paSceneColor.g;
  4738. baseEmissiveAmbient_b = msm->paSceneColor.b;
  4739. }
  4740. // If there is no emissive or ambient color material change, this
  4741. // will be the emissive and ambient components.
  4742. emissiveAmbientI_r = baseEmissiveAmbient_r;
  4743. emissiveAmbientI_g = baseEmissiveAmbient_g;
  4744. emissiveAmbientI_b = baseEmissiveAmbient_b;
  4745. use_material_diffuse = msm_colorMaterialChange & __GL_MATERIAL_DIFFUSE;
  4746. use_material_specular = msm_colorMaterialChange & __GL_MATERIAL_SPECULAR;
  4747. // NOTE: the following values may be re-used in the next iteration:
  4748. // ri, gi, bi, alpha, nxi, nyi, nzi, emissiveAmbientI, diffuseSpecularI
  4749. for (pd = pdFirst; pd <= pdLast; pd++)
  4750. {
  4751. // If color and normal have not changed for this vertex, use the previously
  4752. // computed color.
  4753. pd_flags = pd->flags;
  4754. normal_valid = pd_flags & POLYDATA_NORMAL_VALID;
  4755. color_valid = pd_flags & POLYDATA_COLOR_VALID;
  4756. if (!(normal_valid || color_valid))
  4757. {
  4758. ASSERTOPENGL(pd != pdFirst, "no initial normal and color\n");
  4759. pd->colors[face] = (pd-1)->colors[face];
  4760. #ifdef GL_WIN_specular_fog
  4761. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  4762. {
  4763. pd->fog = (pd-1)->fog;
  4764. }
  4765. #endif //GL_WIN_specular_fog
  4766. continue;
  4767. }
  4768. if (color_valid)
  4769. {
  4770. __GLfloat pd_r, pd_g, pd_b;
  4771. // Save latest colors normalized to 0..1
  4772. pd_r = pd->colors[0].r;
  4773. pd_g = pd->colors[0].g;
  4774. pd_b = pd->colors[0].b;
  4775. ri = pd_r * gc->oneOverRedVertexScale;
  4776. gi = pd_g * gc->oneOverGreenVertexScale;
  4777. bi = pd_b * gc->oneOverBlueVertexScale;
  4778. alpha = pd->colors[0].a;
  4779. // Compute the emissive and ambient components for this vertex if necessary.
  4780. // If color has not changed, the previous emissveAmbientI values are used!
  4781. if (use_material_ambient || use_material_emissive)
  4782. {
  4783. if (use_material_ambient)
  4784. {
  4785. ambient_r_sum = lm_ambient_r;
  4786. ambient_g_sum = lm_ambient_g;
  4787. ambient_b_sum = lm_ambient_b;
  4788. // Add per-light per-material ambient
  4789. for (lsm = gc->light.sources; lsm; lsm = lsm->next)
  4790. {
  4791. lss = lsm->state;
  4792. ambient_r_sum += lss->ambient.r;
  4793. ambient_g_sum += lss->ambient.g;
  4794. ambient_b_sum += lss->ambient.b;
  4795. }
  4796. ambient_r_sum *= ri;
  4797. ambient_g_sum *= gi;
  4798. ambient_b_sum *= bi;
  4799. emissiveAmbientI_r = baseEmissiveAmbient_r + ambient_r_sum;
  4800. emissiveAmbientI_g = baseEmissiveAmbient_g + ambient_g_sum;
  4801. emissiveAmbientI_b = baseEmissiveAmbient_b + ambient_b_sum;
  4802. }
  4803. else
  4804. {
  4805. emissiveAmbientI_r = baseEmissiveAmbient_r + pd_r;
  4806. emissiveAmbientI_g = baseEmissiveAmbient_g + pd_g;
  4807. emissiveAmbientI_b = baseEmissiveAmbient_b + pd_b;
  4808. }
  4809. }
  4810. }
  4811. else
  4812. {
  4813. // use previous ri, gi, bi, alpha, and emissiveAmbientI!
  4814. ASSERTOPENGL(pd != pdFirst, "no initial color\n");
  4815. }
  4816. // Compute the diffuse and specular components for this vertex.
  4817. if (normal_valid)
  4818. {
  4819. nxi = pd->normal.x;
  4820. nyi = pd->normal.y;
  4821. nzi = pd->normal.z;
  4822. if (face != __GL_FRONTFACE)
  4823. {
  4824. nxi = -nxi;
  4825. nyi = -nyi;
  4826. nzi = -nzi;
  4827. }
  4828. #ifdef GL_WIN_specular_fog
  4829. // Initialize Fog value to 0 here;
  4830. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  4831. {
  4832. ASSERTOPENGL (face == __GL_FRONTFACE,
  4833. "Specular fog works for only GL_FRONT\n");
  4834. fog = __glZero;
  4835. }
  4836. #endif //GL_WIN_specular_fog
  4837. }
  4838. else
  4839. {
  4840. ASSERTOPENGL(pd != pdFirst, "no initial normal\n");
  4841. // If normal and diffuse and specular components have not changed,
  4842. // use the previously computed diffuse and specular values.
  4843. // otherwise, use previous normal (nxi, nyi, nzi) and
  4844. // diffuseSpecularI!
  4845. if (!(use_material_diffuse || use_material_specular))
  4846. goto store_color;
  4847. }
  4848. spec_r_sum = (__GLfloat)0.0;
  4849. spec_g_sum = (__GLfloat)0.0;
  4850. spec_b_sum = (__GLfloat)0.0;
  4851. diff_r_sum = (__GLfloat)0.0;
  4852. diff_g_sum = (__GLfloat)0.0;
  4853. diff_b_sum = (__GLfloat)0.0;
  4854. for (lsm = gc->light.sources; lsm; lsm = lsm->next)
  4855. {
  4856. __GLfloat n1, n2;
  4857. lss = lsm->state;
  4858. lspmm = &lsm->front + face;
  4859. lss_diff_color = &lss->diffuse;
  4860. lss_spec_color = &lss->specular;
  4861. lspmm_diff_color = &lspmm->diffuse;
  4862. lspmm_spec_color = &lspmm->specular;
  4863. diff_color = lspmm_diff_color;
  4864. spec_color = lspmm_spec_color;
  4865. if (use_material_diffuse)
  4866. diff_color = lss_diff_color;
  4867. if (use_material_specular)
  4868. spec_color = lss_spec_color;
  4869. /* Add in specular and diffuse effect of light, if any */
  4870. n1 = nxi * lsm->unitVPpli.x + nyi * lsm->unitVPpli.y +
  4871. nzi * lsm->unitVPpli.z;
  4872. if (n1 > 0.0)
  4873. {
  4874. diff_r = diff_color->r;
  4875. diff_g = diff_color->g;
  4876. diff_b = diff_color->b;
  4877. n2 = nxi * lsm->hHat.x + nyi * lsm->hHat.y + nzi * lsm->hHat.z;
  4878. n2 -= msm_threshold;
  4879. if (n2 >= 0.0)
  4880. {
  4881. __GLfloat fx = n2 * msm_scale + __glHalf;
  4882. spec_r = spec_color->r;
  4883. spec_g = spec_color->g;
  4884. spec_b = spec_color->b;
  4885. if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE ){
  4886. n2 = msm_specTable[(GLint)fx];
  4887. spec_r *= n2;
  4888. spec_g *= n2;
  4889. spec_b *= n2;
  4890. }
  4891. /* else n2 = 1.0.
  4892. Before, we multiplied (spec_r *= n2) in all cases.
  4893. But since n2 == 1.0, there's no need to do it in this case.
  4894. Thus there is no need to load n2 = 1.0. */
  4895. #ifdef GL_WIN_specular_fog
  4896. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  4897. {
  4898. pd->fog += n2;
  4899. }
  4900. #endif //GL_WIN_specular_fog
  4901. spec_r_sum += spec_r;
  4902. spec_g_sum += spec_g;
  4903. spec_b_sum += spec_b;
  4904. }
  4905. diff_r *= n1;
  4906. diff_g *= n1;
  4907. diff_b *= n1;
  4908. diff_r_sum += diff_r;
  4909. diff_g_sum += diff_g;
  4910. diff_b_sum += diff_b;
  4911. }
  4912. }
  4913. if (use_material_specular){
  4914. /* Recompute per-light per-material cached specular */
  4915. spec_r_sum *= ri;
  4916. spec_g_sum *= gi;
  4917. spec_b_sum *= bi;
  4918. }
  4919. if (use_material_diffuse){
  4920. /* Recompute per-light per-material cached diffuse */
  4921. diff_r_sum *= ri;
  4922. diff_g_sum *= gi;
  4923. diff_b_sum *= bi;
  4924. }
  4925. diffuseSpecularI_r = diff_r_sum + spec_r_sum;
  4926. diffuseSpecularI_g = diff_g_sum + spec_g_sum;
  4927. diffuseSpecularI_b = diff_b_sum + spec_b_sum;
  4928. store_color:
  4929. {
  4930. __GLcolor *pd_color_dst;
  4931. pd_color_dst = &pd->colors[face];
  4932. __GL_CLAMP_RGB( pd_color_dst->r,
  4933. pd_color_dst->g,
  4934. pd_color_dst->b,
  4935. gc,
  4936. emissiveAmbientI_r + diffuseSpecularI_r,
  4937. emissiveAmbientI_g + diffuseSpecularI_g,
  4938. emissiveAmbientI_b + diffuseSpecularI_b);
  4939. if (msm_colorMaterialChange & __GL_MATERIAL_DIFFUSE)
  4940. {
  4941. if (pa->flags & POLYARRAY_CLAMP_COLOR)
  4942. {
  4943. __GL_CLAMP_A(pd_color_dst->a, gc, alpha);
  4944. }
  4945. else
  4946. pd_color_dst->a = alpha;
  4947. }
  4948. else
  4949. {
  4950. pd_color_dst->a = msm_alpha;
  4951. }
  4952. #ifdef GL_WIN_specular_fog
  4953. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  4954. {
  4955. pd->fog = 1.0 - fog;
  4956. if (__GL_FLOAT_LTZ (pd->fog)) pd->fog = __glZero;
  4957. }
  4958. #endif //GL_WIN_specular_fog
  4959. }
  4960. }
  4961. }
  4962. #endif // __GL_ASM_POLYARRAYFASTCALCRGBCOLOR
  4963. // This function is called when color material is disabled and there are no
  4964. // slow lights.
  4965. //
  4966. // Note: The first vertex must have a valid normal!
  4967. //
  4968. // IN: normal
  4969. // OUT: color (front or back depending on face) (all vertices are updated)
  4970. #ifndef __GL_ASM_POLYARRAYZIPPYCALCRGBCOLOR
  4971. void FASTCALL PolyArrayZippyCalcRGBColor(__GLcontext *gc, GLint face, POLYARRAY *pa, POLYDATA *pdFirst, POLYDATA *pdLast)
  4972. {
  4973. register __GLfloat nxi, nyi, nzi;
  4974. __GLlightSourcePerMaterialMachine *lspmm;
  4975. __GLlightSourceMachine *lsm;
  4976. __GLlightSourceState *lss;
  4977. __GLfloat baseEmissiveAmbient_r, baseEmissiveAmbient_g, baseEmissiveAmbient_b;
  4978. __GLmaterialMachine *msm;
  4979. __GLfloat msm_alpha, msm_threshold, msm_scale, *msm_specTable;
  4980. __GLcolor *pd_color_dst;
  4981. GLboolean notBackface = FALSE;
  4982. POLYDATA *pd;
  4983. ULONG normal_valid, paneeds_valid;
  4984. register GLfloat diff_r, diff_g, diff_b;
  4985. register GLfloat spec_r, spec_g, spec_b;
  4986. GLfloat lsmx, lsmy, lsmz;
  4987. ULONG fast_path = 0;
  4988. #ifdef GL_WIN_specular_fog
  4989. __GLfloat fog;
  4990. #endif //GL_WIN_specular_fog
  4991. #if LATER
  4992. // if eye.w is zero, it should really take the slow path!
  4993. // Since the sample implementation ignores it, we will also ignore it here.
  4994. #endif
  4995. if (face == __GL_FRONTFACE)
  4996. msm = &gc->light.front;
  4997. else
  4998. msm = &gc->light.back;
  4999. lsm = gc->light.sources;
  5000. if (lsm && !lsm->next)
  5001. fast_path = 1;
  5002. msm_scale = msm->scale;
  5003. msm_threshold = msm->threshold;
  5004. msm_specTable = msm->specTable;
  5005. msm_alpha = msm->alpha;
  5006. // Compute invarient emissive and ambient components for this vertex.
  5007. baseEmissiveAmbient_r = msm->cachedEmissiveAmbient.r;
  5008. baseEmissiveAmbient_g = msm->cachedEmissiveAmbient.g;
  5009. baseEmissiveAmbient_b = msm->cachedEmissiveAmbient.b;
  5010. // NOTE: the following values may be re-used in the next iteration:
  5011. // nxi, nyi, nzi
  5012. #ifdef GL_WIN_specular_fog
  5013. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  5014. {
  5015. ASSERTOPENGL (face == __GL_FRONTFACE,
  5016. "Specular fog works only with GL_FRONT\n");
  5017. }
  5018. #endif //GL_WIN_specular_fog
  5019. if (fast_path)
  5020. {
  5021. __GLfloat n1, n2;
  5022. lspmm = &lsm->front + face;
  5023. lss = lsm->state;
  5024. lsmx = lsm->unitVPpli.x;
  5025. lsmy = lsm->unitVPpli.y;
  5026. lsmz = lsm->unitVPpli.z;
  5027. diff_r = lspmm->diffuse.r;
  5028. diff_g = lspmm->diffuse.g;
  5029. diff_b = lspmm->diffuse.b;
  5030. spec_r = lspmm->specular.r;
  5031. spec_g = lspmm->specular.g;
  5032. spec_b = lspmm->specular.b;
  5033. for (pd = pdFirst; pd <= pdLast; pd++)
  5034. {
  5035. __GLfloat rsi, gsi, bsi;
  5036. // If normal has not changed for this vertex, use the previously computed color.
  5037. normal_valid = pd->flags & POLYDATA_NORMAL_VALID;
  5038. paneeds_valid = gc->vertex.paNeeds & PANEEDS_NORMAL;
  5039. if (!(normal_valid))
  5040. {
  5041. ASSERTOPENGL(pd != pdFirst, "no initial normal\n");
  5042. pd->colors[face] = (pd-1)->colors[face];
  5043. #ifdef GL_WIN_specular_fog
  5044. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  5045. {
  5046. pd->fog = (pd-1)->fog;
  5047. }
  5048. #endif //GL_WIN_specular_fog
  5049. continue;
  5050. }
  5051. if (face == __GL_FRONTFACE)
  5052. {
  5053. nxi = pd->normal.x;
  5054. nyi = pd->normal.y;
  5055. nzi = pd->normal.z;
  5056. }
  5057. else
  5058. {
  5059. nxi = -pd->normal.x;
  5060. nyi = -pd->normal.y;
  5061. nzi = -pd->normal.z;
  5062. }
  5063. #ifdef GL_WIN_specular_fog
  5064. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  5065. {
  5066. fog = __glZero;
  5067. }
  5068. #endif //GL_WIN_specular_fog
  5069. rsi = baseEmissiveAmbient_r;
  5070. gsi = baseEmissiveAmbient_g;
  5071. bsi = baseEmissiveAmbient_b;
  5072. // Compute the diffuse and specular components for this vertex.
  5073. /* Add in specular and diffuse effect of light, if any */
  5074. n1 = nxi * lsmx + nyi * lsmy + nzi * lsmz;
  5075. pd_color_dst = &pd->colors[face];
  5076. if (n1 > 0.0)
  5077. {
  5078. n2 = (nxi * lsm->hHat.x + nyi * lsm->hHat.y + nzi * lsm->hHat.z)
  5079. - msm_threshold;
  5080. rsi += n1 * diff_r;
  5081. gsi += n1 * diff_g;
  5082. bsi += n1 * diff_b;
  5083. if (n2 >= 0.0)
  5084. {
  5085. GLint ix = (GLint)(n2 * msm_scale + __glHalf);
  5086. if (ix < __GL_SPEC_LOOKUP_TABLE_SIZE)
  5087. n2 = msm_specTable[ix];
  5088. else
  5089. n2 = __glOne;
  5090. #ifdef GL_WIN_specular_fog
  5091. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  5092. {
  5093. fog += n2;
  5094. }
  5095. #endif //GL_WIN_specular_fog
  5096. rsi += n2 * spec_r;
  5097. gsi += n2 * spec_g;
  5098. bsi += n2 * spec_b;
  5099. }
  5100. pd_color_dst->r = rsi;
  5101. pd_color_dst->g = gsi;
  5102. pd_color_dst->b = bsi;
  5103. if (__GL_COLOR_CHECK_CLAMP_RGB(gc, rsi, gsi, bsi)) {
  5104. __GL_CLAMP_RGB(pd_color_dst->r,
  5105. pd_color_dst->g,
  5106. pd_color_dst->b,
  5107. gc, rsi, gsi, bsi);
  5108. }
  5109. pd_color_dst->a = msm_alpha;
  5110. }
  5111. else
  5112. {
  5113. pd_color_dst->r = msm->cachedNonLit.r;
  5114. pd_color_dst->g = msm->cachedNonLit.g;
  5115. pd_color_dst->b = msm->cachedNonLit.b;
  5116. pd_color_dst->a = msm_alpha;
  5117. }
  5118. }
  5119. }
  5120. else
  5121. {
  5122. for (pd = pdFirst; pd <= pdLast; pd++)
  5123. {
  5124. __GLfloat rsi, gsi, bsi;
  5125. // If normal has not changed for this vertex, use the previously computed color.
  5126. normal_valid = pd->flags & POLYDATA_NORMAL_VALID;
  5127. paneeds_valid = gc->vertex.paNeeds & PANEEDS_NORMAL;
  5128. if (!(normal_valid))
  5129. {
  5130. ASSERTOPENGL(pd != pdFirst, "no initial normal\n");
  5131. pd->colors[face] = (pd-1)->colors[face];
  5132. #ifdef GL_WIN_specular_fog
  5133. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  5134. {
  5135. pd->fog = (pd-1)->fog;
  5136. }
  5137. #endif //GL_WIN_specular_fog
  5138. continue;
  5139. }
  5140. if (face == __GL_FRONTFACE)
  5141. {
  5142. nxi = pd->normal.x;
  5143. nyi = pd->normal.y;
  5144. nzi = pd->normal.z;
  5145. }
  5146. else
  5147. {
  5148. nxi = -pd->normal.x;
  5149. nyi = -pd->normal.y;
  5150. nzi = -pd->normal.z;
  5151. }
  5152. #ifdef GL_WIN_specular_fog
  5153. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  5154. {
  5155. fog = __glZero;
  5156. }
  5157. #endif //GL_WIN_specular_fog
  5158. rsi = baseEmissiveAmbient_r;
  5159. gsi = baseEmissiveAmbient_g;
  5160. bsi = baseEmissiveAmbient_b;
  5161. // Compute the diffuse and specular components for this vertex.
  5162. for (lsm = gc->light.sources; lsm; lsm = lsm->next)
  5163. {
  5164. __GLfloat n1, n2;
  5165. lspmm = &lsm->front + face;
  5166. lss = lsm->state;
  5167. lsmx = lsm->unitVPpli.x;
  5168. lsmy = lsm->unitVPpli.y;
  5169. lsmz = lsm->unitVPpli.z;
  5170. diff_r = lspmm->diffuse.r;
  5171. diff_g = lspmm->diffuse.g;
  5172. diff_b = lspmm->diffuse.b;
  5173. /* Add in specular and diffuse effect of light, if any */
  5174. n1 = nxi * lsmx + nyi * lsmy + nzi * lsmz;
  5175. if (n1 > 0.0)
  5176. {
  5177. notBackface = TRUE;
  5178. n2 = (nxi * lsm->hHat.x + nyi * lsm->hHat.y + nzi * lsm->hHat.z)
  5179. - msm_threshold;
  5180. if (n2 >= 0.0)
  5181. {
  5182. GLint ix = (GLint)(n2 * msm_scale + __glHalf);
  5183. spec_r = lspmm->specular.r;
  5184. spec_g = lspmm->specular.g;
  5185. spec_b = lspmm->specular.b;
  5186. if (ix < __GL_SPEC_LOOKUP_TABLE_SIZE)
  5187. n2 = msm_specTable[ix];
  5188. else
  5189. n2 = __glOne;
  5190. #ifdef GL_WIN_specular_fog
  5191. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  5192. {
  5193. fog += n2;
  5194. }
  5195. #endif //GL_WIN_specular_fog
  5196. rsi += n2 * spec_r;
  5197. gsi += n2 * spec_g;
  5198. bsi += n2 * spec_b;
  5199. }
  5200. rsi += n1 * diff_r;
  5201. gsi += n1 * diff_g;
  5202. bsi += n1 * diff_b;
  5203. }
  5204. }
  5205. pd_color_dst = &pd->colors[face];
  5206. #ifdef GL_WIN_specular_fog
  5207. if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
  5208. {
  5209. pd->fog = 1.0 - fog;
  5210. if (__GL_FLOAT_LTZ (pd->fog)) pd->fog = __glZero;
  5211. }
  5212. #endif //GL_WIN_specular_fog
  5213. if (notBackface)
  5214. {
  5215. pd_color_dst->r = rsi;
  5216. pd_color_dst->g = gsi;
  5217. pd_color_dst->b = bsi;
  5218. if (__GL_COLOR_CHECK_CLAMP_RGB(gc, rsi, gsi, bsi)) {
  5219. __GL_CLAMP_RGB(pd_color_dst->r,
  5220. pd_color_dst->g,
  5221. pd_color_dst->b,
  5222. gc, rsi, gsi, bsi);
  5223. }
  5224. pd_color_dst->a = msm_alpha;
  5225. }
  5226. else
  5227. {
  5228. pd_color_dst->r = msm->cachedNonLit.r;
  5229. pd_color_dst->g = msm->cachedNonLit.g;
  5230. pd_color_dst->b = msm->cachedNonLit.b;
  5231. pd_color_dst->a = msm_alpha;
  5232. }
  5233. }
  5234. }
  5235. }
  5236. #endif // __GL_ASM_POLYARRAYZIPPYCALCRGBCOLOR
  5237. #ifdef _X86_
  5238. // See comments in xform.asm (NORMALIZE macro) about format of this table
  5239. //
  5240. #define K 9 // Number of used mantissa bits
  5241. #define MAX_ENTRY (1 << (K+1))
  5242. #define EXPONENT_BIT (1 << K)
  5243. #define MANTISSA_MASK (EXPONENT_BIT - 1)
  5244. #define FRACTION_VALUE ((float)EXPONENT_BIT)
  5245. float invSqrtTable[MAX_ENTRY]; // used by glNormalizeBatch
  5246. void initInvSqrtTable()
  5247. {
  5248. int i;
  5249. for (i=0; i < MAX_ENTRY; i++)
  5250. {
  5251. if (i & EXPONENT_BIT)
  5252. invSqrtTable[i] = (float)(1.0/sqrt(((i & MANTISSA_MASK)/FRACTION_VALUE+1.0)));
  5253. else
  5254. invSqrtTable[i] = (float)(1.0/sqrt(((i & MANTISSA_MASK)/FRACTION_VALUE+1.0)/2));
  5255. }
  5256. }
  5257. /*
  5258. __glClipCodes table has precomputed clip codes.
  5259. Index to this table:
  5260. bit 6 - 1 if clipW < 0
  5261. bit 5 - 1 if clipX < 0
  5262. bit 4 - 1 if abs(clipX) < abs(clipW)
  5263. bit 3 - 1 if clipY < 0
  5264. bit 2 - 1 if abs(clipY) < abs(clipW)
  5265. bit 1 - 1 if clipZ < 0
  5266. bit 0 - 1 if abs(clipZ) < abs(clipW)
  5267. */
  5268. ULONG __glClipCodes[128];
  5269. void initClipCodesTable()
  5270. {
  5271. int i, v, w;
  5272. for (i=0; i < 128; i++)
  5273. {
  5274. int code = 0;
  5275. if (i & 0x10)
  5276. { // x < w
  5277. v = 1; w = 2;
  5278. }
  5279. else
  5280. {
  5281. v = 2; w = 1;
  5282. }
  5283. if (i & 0x20) v = -v;
  5284. if (i & 0x40) w = -w;
  5285. if (v > w) code|= __GL_CLIP_RIGHT;
  5286. if (v < -w) code|= __GL_CLIP_LEFT;
  5287. if (i & 0x04)
  5288. { // y < w
  5289. v = 1; w = 2;
  5290. }
  5291. else
  5292. {
  5293. v = 2; w = 1;
  5294. }
  5295. if (i & 0x08) v = -v;
  5296. if (i & 0x40) w = -w;
  5297. if (v > w) code|= __GL_CLIP_TOP;
  5298. if (v < -w) code|= __GL_CLIP_BOTTOM;
  5299. if (i & 0x01)
  5300. { // v < w
  5301. v = 1; w = 2;
  5302. }
  5303. else
  5304. {
  5305. v = 2; w = 1;
  5306. }
  5307. if (i & 0x02) v = -v;
  5308. if (i & 0x40) w = -w;
  5309. if (v > w) code|= __GL_CLIP_FAR;
  5310. if (v < -w) code|= __GL_CLIP_NEAR;
  5311. __glClipCodes[i] = code;
  5312. }
  5313. }
  5314. #endif // _X86_
  5315. #ifndef __GL_ASM_PACLIPCHECKFRUSTUM
  5316. /****************************************************************************/
  5317. // Clip check the clip coordinates against the frustum planes.
  5318. // Compute the window coordinates if not clipped!
  5319. //
  5320. // IN: clip
  5321. // OUT: window (if not clipped)
  5322. GLuint FASTCALL PAClipCheckFrustum(__GLcontext *gc, POLYARRAY *pa,
  5323. POLYDATA *pdLast)
  5324. {
  5325. __GLfloat x, y, z, w, invW, negW;
  5326. GLuint code;
  5327. POLYDATA *pd;
  5328. for (pd = pa->pd0; pd <= pdLast; pd++)
  5329. {
  5330. w = pd->clip.w;
  5331. /* Set clip codes */
  5332. /* XXX (mf) prevent divide-by-zero */
  5333. if (__GL_FLOAT_NEZ(w))
  5334. {
  5335. __GL_FLOAT_SIMPLE_BEGIN_DIVIDE(__glOne, w, invW);
  5336. }
  5337. else
  5338. {
  5339. invW = __glZero;
  5340. }
  5341. x = pd->clip.x;
  5342. y = pd->clip.y;
  5343. z = pd->clip.z;
  5344. code = 0;
  5345. negW = -w;
  5346. __GL_FLOAT_SIMPLE_END_DIVIDE(invW);
  5347. pd->window.w = invW;
  5348. /*
  5349. ** NOTE: it is possible for x to be less than negW and greater
  5350. ** than w (if w is negative). Otherwise there would be "else"
  5351. ** clauses here.
  5352. */
  5353. if (x < negW) code |= __GL_CLIP_LEFT;
  5354. if (x > w) code |= __GL_CLIP_RIGHT;
  5355. if (y < negW) code |= __GL_CLIP_BOTTOM;
  5356. if (y > w) code |= __GL_CLIP_TOP;
  5357. if (z < negW) code |= __GL_CLIP_NEAR;
  5358. if (z > w) code |= __GL_CLIP_FAR;
  5359. /* Compute window coordinates if not clipped */
  5360. if (!code)
  5361. {
  5362. __GLfloat wx, wy, wz;
  5363. wx = x * gc->state.viewport.xScale * invW +
  5364. gc->state.viewport.xCenter;
  5365. wy = y * gc->state.viewport.yScale * invW +
  5366. gc->state.viewport.yCenter;
  5367. wz = z * gc->state.viewport.zScale * invW +
  5368. gc->state.viewport.zCenter;
  5369. pd->window.x = wx;
  5370. pd->window.y = wy;
  5371. pd->window.z = wz;
  5372. }
  5373. pd->clipCode = code;
  5374. pa->orClipCodes |= code;
  5375. #ifdef POLYARRAY_AND_CLIPCODES
  5376. pa->andClipCodes &= code;
  5377. #endif
  5378. }
  5379. return pa->andClipCodes;
  5380. }
  5381. GLuint FASTCALL PAClipCheckFrustumWOne(__GLcontext *gc, POLYARRAY *pa,
  5382. POLYDATA *pdLast)
  5383. {
  5384. __GLfloat x, y, z, w, invW, negW;
  5385. GLuint code;
  5386. POLYDATA *pd;
  5387. for (pd = pa->pd0; pd <= pdLast; pd++)
  5388. {
  5389. w = pd->clip.w;
  5390. pd->window.w = __glOne;
  5391. /* Set clip codes */
  5392. x = pd->clip.x;
  5393. y = pd->clip.y;
  5394. z = pd->clip.z;
  5395. code = 0;
  5396. negW = __glMinusOne;
  5397. if (x < negW) code |= __GL_CLIP_LEFT;
  5398. else if (x > w) code |= __GL_CLIP_RIGHT;
  5399. if (y < negW) code |= __GL_CLIP_BOTTOM;
  5400. else if (y > w) code |= __GL_CLIP_TOP;
  5401. if (z < negW) code |= __GL_CLIP_NEAR;
  5402. else if (z > w) code |= __GL_CLIP_FAR;
  5403. /* Compute window coordinates if not clipped */
  5404. if (!code)
  5405. {
  5406. __GLfloat wx, wy, wz;
  5407. wx = x * gc->state.viewport.xScale + gc->state.viewport.xCenter;
  5408. wy = y * gc->state.viewport.yScale + gc->state.viewport.yCenter;
  5409. wz = z * gc->state.viewport.zScale + gc->state.viewport.zCenter;
  5410. pd->window.x = wx;
  5411. pd->window.y = wy;
  5412. pd->window.z = wz;
  5413. }
  5414. pd->clipCode = code;
  5415. pa->orClipCodes |= code;
  5416. #ifdef POLYARRAY_AND_CLIPCODES
  5417. pa->andClipCodes &= code;
  5418. #endif
  5419. }
  5420. return pa->andClipCodes;
  5421. }
  5422. #endif // __GL_ASM_PACLIPCHECKFRUSTUM
  5423. // Clip check the clip coordinates against the frustum planes.
  5424. // Compute the window coordinates if not clipped!
  5425. //
  5426. // IN: clip
  5427. // OUT: window (if not clipped)
  5428. #ifndef __GL_ASM_PACLIPCHECKFRUSTUM2D
  5429. GLuint FASTCALL PAClipCheckFrustum2D(__GLcontext *gc, POLYARRAY *pa,
  5430. POLYDATA *pdLast)
  5431. {
  5432. __GLfloat x, y, z, w, negW, invW;
  5433. GLuint code;
  5434. POLYDATA *pd;
  5435. for (pd = pa->pd0; pd <= pdLast; pd++) {
  5436. /* W is 1.0 */
  5437. pd->window.w = __glOne;
  5438. x = pd->clip.x;
  5439. y = pd->clip.y;
  5440. z = pd->clip.z;
  5441. w = pd->clip.w;
  5442. negW = __glMinusOne;
  5443. /* Set clip codes */
  5444. code = 0;
  5445. if (x < negW) code |= __GL_CLIP_LEFT;
  5446. else if (x > w) code |= __GL_CLIP_RIGHT;
  5447. if (y < negW) code |= __GL_CLIP_BOTTOM;
  5448. else if (y > w) code |= __GL_CLIP_TOP;
  5449. /* Compute window coordinates if not clipped */
  5450. if (!code)
  5451. {
  5452. __GLfloat wx, wy, wz;
  5453. wx = x * gc->state.viewport.xScale + gc->state.viewport.xCenter;
  5454. wy = y * gc->state.viewport.yScale + gc->state.viewport.yCenter;
  5455. wz = z * gc->state.viewport.zScale + gc->state.viewport.zCenter;
  5456. pd->window.x = wx;
  5457. pd->window.y = wy;
  5458. pd->window.z = wz;
  5459. }
  5460. pd->clipCode = code;
  5461. pa->orClipCodes |= code;
  5462. #ifdef POLYARRAY_AND_CLIPCODES
  5463. pa->andClipCodes &= code;
  5464. #endif
  5465. }
  5466. return pa->andClipCodes;
  5467. }
  5468. #endif // __GL_ASM_PACLIPCHECKFRUSTUM2D
  5469. // Clip check against the frustum and user clipping planes.
  5470. // Compute the window coordinates if not clipped!
  5471. //
  5472. // IN: clip, eye
  5473. // OUT: window (if not clipped)
  5474. #ifndef __GL_ASM_PACLIPCHECKALL
  5475. GLuint FASTCALL PAClipCheckAll(__GLcontext *gc, POLYARRAY *pa,
  5476. POLYDATA *pdLast)
  5477. {
  5478. __GLfloat x, y, z, w, negW, invW;
  5479. GLuint code, bit, clipPlanesMask;
  5480. __GLcoord *plane;
  5481. POLYDATA *pd;
  5482. // We need double precision to do this correctly. If precision is
  5483. // lowered (as it was in a previous version of this routine), triangles
  5484. // may be clipped incorrectly with user planes (very visible in tlogo)!
  5485. FPU_SAVE_MODE();
  5486. FPU_ROUND_ON_PREC_HI();
  5487. for (pd = pa->pd0; pd <= pdLast; pd++) {
  5488. PERF_CHECK(FALSE, "Performs user plane clipping!\n");
  5489. /*
  5490. ** Do frustum checks.
  5491. **
  5492. ** NOTE: it is possible for x to be less than negW and greater than w
  5493. ** (if w is negative). Otherwise there would be "else" clauses here.
  5494. */
  5495. x = pd->clip.x;
  5496. y = pd->clip.y;
  5497. z = pd->clip.z;
  5498. w = pd->clip.w;
  5499. /* Set clip codes */
  5500. /* XXX (mf) prevent divide-by-zero */
  5501. if (__GL_FLOAT_NEZ(w))
  5502. {
  5503. __GL_FLOAT_SIMPLE_BEGIN_DIVIDE(__glOne, w, invW);
  5504. __GL_FLOAT_SIMPLE_END_DIVIDE(invW);
  5505. }
  5506. else
  5507. {
  5508. invW = __glZero;
  5509. }
  5510. pd->window.w = invW;
  5511. negW = -w;
  5512. code = 0;
  5513. if (x < negW) code |= __GL_CLIP_LEFT;
  5514. if (x > w) code |= __GL_CLIP_RIGHT;
  5515. if (y < negW) code |= __GL_CLIP_BOTTOM;
  5516. if (y > w) code |= __GL_CLIP_TOP;
  5517. if (z < negW) code |= __GL_CLIP_NEAR;
  5518. if (z > w) code |= __GL_CLIP_FAR;
  5519. /*
  5520. ** Now do user clip plane checks
  5521. */
  5522. x = pd->eye.x;
  5523. y = pd->eye.y;
  5524. z = pd->eye.z;
  5525. w = pd->eye.w;
  5526. clipPlanesMask = gc->state.enables.clipPlanes;
  5527. plane = &gc->state.transform.eyeClipPlanes[0];
  5528. bit = __GL_CLIP_USER0;
  5529. while (clipPlanesMask)
  5530. {
  5531. if (clipPlanesMask & 1)
  5532. {
  5533. /*
  5534. ** Dot the vertex clip coordinate against the clip plane and
  5535. ** see if the sign is negative. If so, then the point is out.
  5536. */
  5537. if (x * plane->x + y * plane->y + z * plane->z + w * plane->w <
  5538. __glZero)
  5539. {
  5540. code |= bit;
  5541. }
  5542. }
  5543. clipPlanesMask >>= 1;
  5544. bit <<= 1;
  5545. plane++;
  5546. }
  5547. /* Compute window coordinates if not clipped */
  5548. if (!code)
  5549. {
  5550. __GLfloat wx, wy, wz;
  5551. x = pd->clip.x;
  5552. y = pd->clip.y;
  5553. z = pd->clip.z;
  5554. wx = x * gc->state.viewport.xScale * invW +
  5555. gc->state.viewport.xCenter;
  5556. wy = y * gc->state.viewport.yScale * invW +
  5557. gc->state.viewport.yCenter;
  5558. wz = z * gc->state.viewport.zScale * invW +
  5559. gc->state.viewport.zCenter;
  5560. pd->window.x = wx;
  5561. pd->window.y = wy;
  5562. pd->window.z = wz;
  5563. }
  5564. pd->clipCode = code;
  5565. pa->orClipCodes |= code;
  5566. #ifdef POLYARRAY_AND_CLIPCODES
  5567. pa->andClipCodes &= code;
  5568. #endif
  5569. }
  5570. FPU_RESTORE_MODE();
  5571. return pa->andClipCodes;
  5572. }
  5573. #endif // __GL_ASM_PACLIPCHECKALL
  5574. /****************************************************************************/
  5575. void APIPRIVATE __glim_EdgeFlag(GLboolean tag)
  5576. {
  5577. __GL_SETUP();
  5578. gc->state.current.edgeTag = tag;
  5579. }
  5580. void APIPRIVATE __glim_TexCoord4fv(const GLfloat x[4])
  5581. {
  5582. __GL_SETUP();
  5583. gc->state.current.texture.x = x[0];
  5584. gc->state.current.texture.y = x[1];
  5585. gc->state.current.texture.z = x[2];
  5586. gc->state.current.texture.w = x[3];
  5587. }
  5588. void APIPRIVATE __glim_Normal3fv(const GLfloat v[3])
  5589. {
  5590. __GL_SETUP();
  5591. GLfloat x, y, z;
  5592. x = v[0];
  5593. y = v[1];
  5594. z = v[2];
  5595. gc->state.current.normal.x = x;
  5596. gc->state.current.normal.y = y;
  5597. gc->state.current.normal.z = z;
  5598. }
  5599. void APIPRIVATE __glim_Color4fv(const GLfloat v[4])
  5600. {
  5601. __GL_SETUP();
  5602. gc->state.current.userColor.r = v[0];
  5603. gc->state.current.userColor.g = v[1];
  5604. gc->state.current.userColor.b = v[2];
  5605. gc->state.current.userColor.a = v[3];
  5606. (*gc->procs.applyColor)(gc);
  5607. }
  5608. void APIPRIVATE __glim_Indexf(GLfloat c)
  5609. {
  5610. __GL_SETUP();
  5611. gc->state.current.userColorIndex = c;
  5612. }
  5613. #if DBG
  5614. #define DEBUG_RASTERPOS 1
  5615. #endif
  5616. // This is not very efficient but it should work fine.
  5617. void APIPRIVATE __glim_RasterPos4fv(const GLfloat v[4])
  5618. {
  5619. POLYDATA pd3[3]; // one pa, one pd, followed by one spare.
  5620. POLYARRAY *pa = (POLYARRAY *) &pd3[0];
  5621. POLYDATA *pd = &pd3[1];
  5622. __GLvertex *rp;
  5623. GLuint oldPaNeeds, oldEnables;
  5624. #ifdef DEBUG_RASTERPOS
  5625. void (FASTCALL *oldRenderPoint)(__GLcontext *gc, __GLvertex *v);
  5626. #endif
  5627. GLuint pdflags;
  5628. __GL_SETUP_NOT_IN_BEGIN_VALIDATE();
  5629. // ASSERT_VERTEX
  5630. if (v[3] == (GLfloat) 1.0)
  5631. {
  5632. if (v[2] == (GLfloat) 0.0)
  5633. pdflags = POLYDATA_VERTEX2;
  5634. else
  5635. pdflags = POLYDATA_VERTEX3;
  5636. }
  5637. else
  5638. {
  5639. pdflags = POLYDATA_VERTEX4;
  5640. }
  5641. rp = &gc->state.current.rasterPos;
  5642. // Initialize POLYARRAY structure with one vertex
  5643. pa->flags = pdflags | POLYARRAY_RASTERPOS;
  5644. pa->pdNextVertex = pd+1;
  5645. pa->pdCurColor =
  5646. pa->pdCurNormal =
  5647. pa->pdCurTexture =
  5648. pa->pdCurEdgeFlag = NULL;
  5649. pa->pd0 = pd;
  5650. pa->primType = GL_POINTS;
  5651. pa->nIndices = 1;
  5652. pa->aIndices = NULL; // identity mapping
  5653. pa->paNext = NULL;
  5654. pd->flags = pdflags;
  5655. pd->obj = *(__GLcoord *) &v[0];
  5656. pd->color = &pd->colors[__GL_FRONTFACE];
  5657. pd->clipCode = 1; // set for debugging
  5658. (pd+1)->flags = 0;
  5659. pa->pdLastEvalColor =
  5660. pa->pdLastEvalNormal =
  5661. pa->pdLastEvalTexture = NULL;
  5662. // Set up states.
  5663. // need transformed texcoord in all cases
  5664. oldPaNeeds = gc->vertex.paNeeds;
  5665. gc->vertex.paNeeds |= PANEEDS_TEXCOORD;
  5666. // no front-end optimization
  5667. gc->vertex.paNeeds &= ~(PANEEDS_CLIP_ONLY | PANEEDS_SKIP_LIGHTING | PANEEDS_NORMAL);
  5668. // set normal need
  5669. if (gc->vertex.paNeeds & PANEEDS_RASTERPOS_NORMAL)
  5670. gc->vertex.paNeeds |= PANEEDS_NORMAL;
  5671. if (gc->vertex.paNeeds & PANEEDS_RASTERPOS_NORMAL_FOR_TEXTURE)
  5672. gc->vertex.paNeeds |= PANEEDS_NORMAL_FOR_TEXTURE;
  5673. // don't apply cheap fog!
  5674. oldEnables = gc->state.enables.general;
  5675. gc->state.enables.general &= ~__GL_FOG_ENABLE;
  5676. #ifdef DEBUG_RASTERPOS
  5677. // Debug only!
  5678. // allow DrawPolyArray to perform selection but not feedback and rendering
  5679. oldRenderPoint = gc->procs.renderPoint;
  5680. if (gc->renderMode != GL_SELECT)
  5681. gc->procs.renderPoint = NULL; // was __glRenderPointNop but set to 0
  5682. // for debugging
  5683. #endif
  5684. // Call DrawPolyArray to 'draw' the point.
  5685. // Begin validation has already been done.
  5686. __glim_DrawPolyArray(pa);
  5687. // 'Render' the point in selection but not in feedback and render modes.
  5688. if (gc->renderMode == GL_SELECT)
  5689. {
  5690. PARenderPoint(gc, (__GLvertex *)pa->pd0);
  5691. }
  5692. // Eye coord should have been processed
  5693. ASSERTOPENGL(pa->flags & POLYARRAY_EYE_PROCESSED, "need eye\n");
  5694. // Restore states.
  5695. gc->vertex.paNeeds = oldPaNeeds;
  5696. gc->state.enables.general = oldEnables;
  5697. #ifdef DEBUG_RASTERPOS
  5698. gc->procs.renderPoint = oldRenderPoint;
  5699. #endif
  5700. // If the point is clipped, the raster position is invalid.
  5701. if (pd->clipCode)
  5702. {
  5703. gc->state.current.validRasterPos = GL_FALSE;
  5704. return;
  5705. }
  5706. gc->state.current.validRasterPos = GL_TRUE;
  5707. // Update raster pos data structure!
  5708. // Only the following fields are needed.
  5709. rp->window.x = pd->window.x;
  5710. rp->window.y = pd->window.y;
  5711. rp->window.z = pd->window.z;
  5712. rp->clip.w = pd->clip.w;
  5713. rp->eyeZ = pd->eye.z;
  5714. rp->colors[__GL_FRONTFACE] = pd->colors[__GL_FRONTFACE];
  5715. rp->texture = pd->texture;
  5716. ASSERTOPENGL(rp->color == &rp->colors[__GL_FRONTFACE],
  5717. "Color pointer not restored\n");
  5718. #ifdef _MCD_
  5719. MCD_STATE_DIRTY(gc, PIXELSTATE);
  5720. #endif
  5721. }
  5722. /************************************************************************/
  5723. void FASTCALL __glNop(void) {}
  5724. void FASTCALL __glNopGC(__GLcontext* gc) {}
  5725. GLboolean FASTCALL __glNopGCBOOL(__GLcontext* gc) { return FALSE; }
  5726. void FASTCALL __glNopGCFRAG(__GLcontext* gc, __GLfragment *frag, __GLtexel *texel) {}
  5727. void FASTCALL __glNopGCCOLOR(__GLcontext* gc, __GLcolor *color, __GLtexel *texel) {}
  5728. void FASTCALL __glNopLight(__GLcontext*gc, GLint i, __GLvertex*v) {}
  5729. void FASTCALL __glNopExtract(__GLmipMapLevel *level, __GLtexture *tex,
  5730. GLint row, GLint col, __GLtexel *result) {}
  5731. void FASTCALL ComputeColorMaterialChange(__GLcontext *gc)
  5732. {
  5733. gc->light.front.colorMaterialChange = 0;
  5734. gc->light.back.colorMaterialChange = 0;
  5735. if (gc->modes.rgbMode
  5736. && gc->state.enables.general & __GL_COLOR_MATERIAL_ENABLE)
  5737. {
  5738. GLuint colorMaterialChange;
  5739. switch (gc->state.light.colorMaterialParam)
  5740. {
  5741. case GL_EMISSION:
  5742. colorMaterialChange = __GL_MATERIAL_EMISSIVE;
  5743. break;
  5744. case GL_SPECULAR:
  5745. colorMaterialChange = __GL_MATERIAL_SPECULAR;
  5746. break;
  5747. case GL_AMBIENT:
  5748. colorMaterialChange = __GL_MATERIAL_AMBIENT;
  5749. break;
  5750. case GL_DIFFUSE:
  5751. colorMaterialChange = __GL_MATERIAL_DIFFUSE;
  5752. break;
  5753. case GL_AMBIENT_AND_DIFFUSE:
  5754. colorMaterialChange = __GL_MATERIAL_AMBIENT | __GL_MATERIAL_DIFFUSE;
  5755. break;
  5756. }
  5757. if (gc->state.light.colorMaterialFace == GL_FRONT_AND_BACK
  5758. || gc->state.light.colorMaterialFace == GL_FRONT)
  5759. gc->light.front.colorMaterialChange = colorMaterialChange;
  5760. if (gc->state.light.colorMaterialFace == GL_FRONT_AND_BACK
  5761. || gc->state.light.colorMaterialFace == GL_BACK)
  5762. gc->light.back.colorMaterialChange = colorMaterialChange;
  5763. }
  5764. }
  5765. void FASTCALL __glGenericPickVertexProcs(__GLcontext *gc)
  5766. {
  5767. GLuint enables = gc->state.enables.general;
  5768. GLenum mvpMatrixType;
  5769. __GLmatrix *m;
  5770. m = &(gc->transform.modelView->mvp);
  5771. mvpMatrixType = m->matrixType;
  5772. /* Pick paClipCheck proc */
  5773. //!!! are there better clip procs?
  5774. if (gc->state.enables.clipPlanes)
  5775. {
  5776. gc->procs.paClipCheck = PAClipCheckAll;
  5777. }
  5778. else
  5779. {
  5780. if (mvpMatrixType >= __GL_MT_IS2D &&
  5781. m->matrix[3][2] >= -1.0f && m->matrix[3][2] <= 1.0f)
  5782. gc->procs.paClipCheck = PAClipCheckFrustum2D;
  5783. else
  5784. gc->procs.paClipCheck = PAClipCheckFrustum;
  5785. }
  5786. }
  5787. // Allocate the POLYDATA vertex buffer.
  5788. // Align the buffer on a cache line boundary
  5789. GLboolean FASTCALL PolyArrayAllocBuffer(__GLcontext *gc, GLuint nVertices)
  5790. {
  5791. GLuint cjSize;
  5792. // Make sure that the vertex buffer holds a minimum number of vertices.
  5793. if (nVertices < MINIMUM_POLYDATA_BUFFER_SIZE)
  5794. {
  5795. ASSERTOPENGL(FALSE, "vertex buffer too small\n");
  5796. return GL_FALSE;
  5797. }
  5798. // Allocate the vertex buffer.
  5799. cjSize = (nVertices * sizeof(POLYDATA));
  5800. if (!(gc->vertex.pdBuf = (POLYDATA *)GCALLOCALIGN32(gc, cjSize)))
  5801. return GL_FALSE;
  5802. gc->vertex.pdBufSizeBytes = cjSize;
  5803. // Only (n-1) vertices are available for use. The last one is reserved
  5804. // by polyarray code.
  5805. gc->vertex.pdBufSize = nVertices - 1;
  5806. // Initialize the vertex buffer.
  5807. PolyArrayResetBuffer(gc);
  5808. return GL_TRUE;
  5809. }
  5810. // Reset the color pointers in vertex buffer.
  5811. GLvoid FASTCALL PolyArrayResetBuffer(__GLcontext *gc)
  5812. {
  5813. GLuint i;
  5814. for (i = 0; i <= gc->vertex.pdBufSize; i++)
  5815. gc->vertex.pdBuf[i].color = &gc->vertex.pdBuf[i].colors[__GL_FRONTFACE];
  5816. }
  5817. // Free the POLYDATA vertex buffer.
  5818. GLvoid FASTCALL PolyArrayFreeBuffer(__GLcontext *gc)
  5819. {
  5820. #ifdef _MCD_
  5821. // If MCD, the POLYDATA vertex buffer is freed when the MCD context is
  5822. // destroyed (see GenMcdDestroy).
  5823. if (((__GLGENcontext *) gc)->_pMcdState)
  5824. return;
  5825. #endif
  5826. if (gc->vertex.pdBuf)
  5827. GCFREEALIGN32(gc, gc->vertex.pdBuf);
  5828. gc->vertex.pdBufSizeBytes = 0;
  5829. gc->vertex.pdBufSize = 0;
  5830. }