Leaked source code of windows server 2003
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.

1386 lines
40 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: dl_opt.c
  3. *
  4. * Display list compilation error routines.
  5. *
  6. * Created: 12-24-1995
  7. * Author: Hock San Lee [hockl]
  8. *
  9. * Copyright (c) 1995-96 Microsoft Corporation
  10. \**************************************************************************/
  11. /*
  12. ** Copyright 1991, 1922, 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. */
  28. #include "precomp.h"
  29. #pragma hdrstop
  30. #include "glclt.h"
  31. void FASTCALL VA_ArrayElementCompile(__GLcontext *gc, GLint i);
  32. /************************************************************************/
  33. /*
  34. ** Optimized errors. Strange but true. These are called to save an error
  35. ** in the display list.
  36. */
  37. void __gllc_InvalidValue()
  38. {
  39. void *data;
  40. __GL_SETUP();
  41. data = __glDlistAddOpUnaligned(gc, DLIST_SIZE(0), DLIST_GENERIC_OP(InvalidValue));
  42. if (data == NULL) return;
  43. __glDlistAppendOp(gc, data, __glle_InvalidValue);
  44. }
  45. void __gllc_InvalidEnum()
  46. {
  47. void *data;
  48. __GL_SETUP();
  49. data = __glDlistAddOpUnaligned(gc, DLIST_SIZE(0), DLIST_GENERIC_OP(InvalidEnum));
  50. if (data == NULL) return;
  51. __glDlistAppendOp(gc, data, __glle_InvalidEnum);
  52. }
  53. void __gllc_InvalidOperation()
  54. {
  55. void *data;
  56. __GL_SETUP();
  57. data = __glDlistAddOpUnaligned(gc, DLIST_SIZE(0), DLIST_GENERIC_OP(InvalidOperation));
  58. if (data == NULL) return;
  59. __glDlistAppendOp(gc, data, __glle_InvalidOperation);
  60. }
  61. /*
  62. ** These routines execute an error stored in a display list.
  63. */
  64. const GLubyte * FASTCALL __glle_InvalidValue(__GLcontext *gc, const GLubyte *PC)
  65. {
  66. GLSETERROR(GL_INVALID_VALUE);
  67. return PC;
  68. }
  69. const GLubyte * FASTCALL __glle_InvalidEnum(__GLcontext *gc, const GLubyte *PC)
  70. {
  71. GLSETERROR(GL_INVALID_ENUM);
  72. return PC;
  73. }
  74. const GLubyte * FASTCALL __glle_InvalidOperation(__GLcontext *gc, const GLubyte *PC)
  75. {
  76. GLSETERROR(GL_INVALID_OPERATION);
  77. return PC;
  78. }
  79. /***************************************************************************/
  80. // This function compiles a poly material structure. It does not
  81. // execute the record in COMPILE_AND_EXECUTE mode. The execution is done
  82. // when the poly array buffer is flushed.
  83. void APIENTRY __gllc_PolyMaterial(GLuint faceName, __GLmatChange *pdMat)
  84. {
  85. GLubyte *data, *data0;
  86. GLuint dirtyBits;
  87. GLuint size, newSize;
  88. __GL_SETUP();
  89. ASSERTOPENGL(faceName == POLYDATA_MATERIAL_FRONT ||
  90. faceName == POLYDATA_MATERIAL_BACK, "bad faceName\n");
  91. // Allocate big enough record and resize it later
  92. size = sizeof(__GLmatChange) + sizeof(GLuint) + sizeof(GLuint);
  93. data = (GLubyte *) __glDlistAddOpUnaligned(gc, DLIST_SIZE(size),
  94. DLIST_GENERIC_OP(PolyMaterial));
  95. if (data == NULL) return;
  96. data0 = data;
  97. dirtyBits = pdMat->dirtyBits;
  98. // Skip size field to be filled in last
  99. ((GLuint *)data)++;
  100. // Record face name
  101. *((GLuint *) data)++ = faceName;
  102. *((GLuint *) data)++ = dirtyBits;
  103. if (dirtyBits & __GL_MATERIAL_AMBIENT)
  104. *((__GLcolor *) data)++ = pdMat->ambient;
  105. if (dirtyBits & __GL_MATERIAL_DIFFUSE)
  106. *((__GLcolor *) data)++ = pdMat->diffuse;
  107. if (dirtyBits & __GL_MATERIAL_SPECULAR)
  108. *((__GLcolor *) data)++ = pdMat->specular;
  109. if (dirtyBits & __GL_MATERIAL_EMISSIVE)
  110. *((__GLcolor *) data)++ = pdMat->emissive;
  111. if (dirtyBits & __GL_MATERIAL_SHININESS)
  112. *((__GLfloat *) data)++ = pdMat->shininess;
  113. if (dirtyBits & __GL_MATERIAL_COLORINDEXES)
  114. {
  115. *((__GLfloat *) data)++ = pdMat->cmapa;
  116. *((__GLfloat *) data)++ = pdMat->cmapd;
  117. *((__GLfloat *) data)++ = pdMat->cmaps;
  118. }
  119. // Now fill in the size field
  120. newSize = (GLuint) (data - data0);
  121. *((GLuint *) data0) = newSize;
  122. // Resize the record
  123. __glDlistResizeCurrentOp(gc, DLIST_SIZE(size), DLIST_SIZE(newSize));
  124. }
  125. // Playback a PolyMaterial record in Begin.
  126. const GLubyte * FASTCALL __glle_PolyMaterial(__GLcontext *gc, const GLubyte *PC)
  127. {
  128. GLubyte *data;
  129. POLYARRAY *pa;
  130. POLYDATA *pd;
  131. GLuint size, faceName, dirtyBits;
  132. __GLmatChange *pdMat;
  133. POLYMATERIAL *pm;
  134. data = (GLubyte *) PC;
  135. size = *((GLuint *) data)++;
  136. faceName = *((GLuint *) data)++;
  137. dirtyBits = *((GLuint *) data)++;
  138. ASSERTOPENGL(faceName == POLYDATA_MATERIAL_FRONT ||
  139. faceName == POLYDATA_MATERIAL_BACK, "bad faceName\n");
  140. pa = gc->paTeb;
  141. if (pa->flags & POLYARRAY_IN_BEGIN)
  142. {
  143. // Update pa flags POLYARRAY_MATERIAL_FRONT and POLYARRAY_MATERIAL_BACK.
  144. pa->flags |= faceName;
  145. // Do front or back material for this vertex.
  146. // Overwrite the previous material changes for this vertex if they exist since
  147. // only the last material changes matter.
  148. pd = pa->pdNextVertex;
  149. // allocate __GLmatChange structure if this vertex hasn't got one
  150. if (!(pd->flags & faceName))
  151. {
  152. if (!(pdMat = PAMatAlloc()))
  153. return PC + size;
  154. // Get POLYMATERIAL pointer after PAMatAlloc!
  155. pm = GLTEB_CLTPOLYMATERIAL();
  156. if (faceName == POLYDATA_MATERIAL_FRONT)
  157. pm->pdMaterial0[pd - pa->pdBuffer0].front = pdMat;
  158. else
  159. pm->pdMaterial0[pd - pa->pdBuffer0].back = pdMat;
  160. pdMat->dirtyBits = dirtyBits;
  161. }
  162. else
  163. {
  164. pm = GLTEB_CLTPOLYMATERIAL();
  165. if (faceName == POLYDATA_MATERIAL_FRONT)
  166. pdMat = pm->pdMaterial0[pd - pa->pdBuffer0].front;
  167. else
  168. pdMat = pm->pdMaterial0[pd - pa->pdBuffer0].back;
  169. pdMat->dirtyBits |= dirtyBits;
  170. }
  171. if (dirtyBits & __GL_MATERIAL_AMBIENT)
  172. pdMat->ambient = *((__GLcolor *) data)++;
  173. if (dirtyBits & __GL_MATERIAL_DIFFUSE)
  174. pdMat->diffuse = *((__GLcolor *) data)++;
  175. if (dirtyBits & __GL_MATERIAL_SPECULAR)
  176. pdMat->specular = *((__GLcolor *) data)++;
  177. if (dirtyBits & __GL_MATERIAL_EMISSIVE)
  178. pdMat->emissive = *((__GLcolor *) data)++;
  179. if (dirtyBits & __GL_MATERIAL_SHININESS)
  180. pdMat->shininess = *((__GLfloat *) data)++;
  181. if (dirtyBits & __GL_MATERIAL_COLORINDEXES)
  182. {
  183. pdMat->cmapa = *((__GLfloat *) data)++;
  184. pdMat->cmapd = *((__GLfloat *) data)++;
  185. pdMat->cmaps = *((__GLfloat *) data)++;
  186. }
  187. // Finally, update pd flags
  188. pd->flags |= faceName;
  189. }
  190. else
  191. {
  192. // Something went wrong at playback time! We can either try to playback
  193. // this record using the regular API or punt it altogether. I cannot think
  194. // of a situation when this can happen, so we will punt it for now.
  195. WARNING("Display list: playing back POLYMATERIAL outside BEGIN!\n");
  196. }
  197. return PC + size;
  198. }
  199. // Compile a PolyData structure in Begin. If the poly data contains
  200. // material changes, it will call __gllc_PolyMaterial to compile the material
  201. // changes. This function does not execute the record in COMPILE_AND_EXECUTE
  202. // mode. The execution is done when the poly array buffer is flushed.
  203. void APIENTRY __glDlistCompilePolyData(__GLcontext *gc, GLboolean bPartial)
  204. {
  205. POLYARRAY *pa;
  206. POLYDATA *pd;
  207. GLubyte *data, *data0;
  208. GLuint pdflags;
  209. GLuint size, newSize;
  210. __GLlistExecFunc *fp;
  211. ASSERTOPENGL(gc->dlist.beginRec, "not in being!\n");
  212. // If we have already recorded it in PolyArrayFlushPartialPrimitive, skip it.
  213. if (gc->dlist.skipPolyData)
  214. {
  215. gc->dlist.skipPolyData = GL_FALSE;
  216. return;
  217. }
  218. pa = gc->paTeb;
  219. if (bPartial)
  220. {
  221. // Record only current attribute changes
  222. pd = pa->pdNextVertex;
  223. if (!pd->flags)
  224. return;
  225. }
  226. else
  227. {
  228. pd = pa->pdNextVertex - 1;
  229. }
  230. // Record material changes first.
  231. if (pd->flags & (POLYDATA_MATERIAL_FRONT | POLYDATA_MATERIAL_BACK))
  232. {
  233. POLYMATERIAL *pm;
  234. pm = GLTEB_CLTPOLYMATERIAL();
  235. if (pd->flags & POLYDATA_MATERIAL_FRONT)
  236. __gllc_PolyMaterial(POLYDATA_MATERIAL_FRONT,
  237. pm->pdMaterial0[pd - pa->pdBuffer0].front);
  238. if (pd->flags & POLYDATA_MATERIAL_BACK)
  239. __gllc_PolyMaterial(POLYDATA_MATERIAL_BACK,
  240. pm->pdMaterial0[pd - pa->pdBuffer0].back);
  241. if (bPartial)
  242. {
  243. if (!(pd->flags & ~(POLYDATA_MATERIAL_FRONT | POLYDATA_MATERIAL_BACK)))
  244. return;
  245. }
  246. }
  247. // Record POLYARRAY_CLAMP_COLOR flag in the begin record.
  248. if (pa->flags & POLYARRAY_CLAMP_COLOR)
  249. gc->dlist.beginRec->flags |= DLIST_BEGIN_HAS_CLAMP_COLOR;
  250. // Make sure that we handle all the flags!
  251. ASSERTOPENGL(
  252. !(pd->flags &
  253. ~(POLYDATA_EDGEFLAG_BOUNDARY |
  254. POLYDATA_EDGEFLAG_VALID |
  255. POLYDATA_COLOR_VALID |
  256. POLYDATA_NORMAL_VALID |
  257. POLYDATA_TEXTURE_VALID |
  258. POLYDATA_VERTEX2 |
  259. POLYDATA_VERTEX3 |
  260. POLYDATA_VERTEX4 |
  261. POLYDATA_DLIST_COLOR_4 |
  262. POLYDATA_FOG_VALID |
  263. POLYDATA_DLIST_TEXTURE1 |
  264. POLYDATA_DLIST_TEXTURE2 |
  265. POLYDATA_DLIST_TEXTURE3 |
  266. POLYDATA_DLIST_TEXTURE4 |
  267. POLYDATA_MATERIAL_FRONT |
  268. POLYDATA_MATERIAL_BACK)),
  269. "Unknown POLYDATA flags!\n");
  270. // Get the flags that we are interested.
  271. pdflags = pd->flags &
  272. (POLYDATA_EDGEFLAG_BOUNDARY |
  273. POLYDATA_EDGEFLAG_VALID |
  274. POLYDATA_COLOR_VALID |
  275. POLYDATA_NORMAL_VALID |
  276. POLYDATA_TEXTURE_VALID |
  277. POLYDATA_VERTEX2 |
  278. POLYDATA_VERTEX3 |
  279. POLYDATA_VERTEX4 |
  280. POLYDATA_DLIST_COLOR_4 |
  281. POLYDATA_DLIST_TEXTURE1 |
  282. POLYDATA_DLIST_TEXTURE2 |
  283. POLYDATA_DLIST_TEXTURE3 |
  284. POLYDATA_DLIST_TEXTURE4);
  285. // Find out if it matches one of the following packed data structure for
  286. // fast playback.
  287. // C3F_V3F
  288. // N3F_V3F
  289. // C3F_N3F_V3F (non 1.1 format)
  290. // C4F_N3F_V3F
  291. // T2F_V3F
  292. // T2F_C3F_V3F
  293. // T2F_N3F_V3F
  294. // T2F_C3F_N3F_V3F (non 1.1 format)
  295. // T2F_C4F_N3F_V3F
  296. #define VTYPE_V2F (POLYDATA_VERTEX2)
  297. #define VTYPE_V3F (POLYDATA_VERTEX3)
  298. #define VTYPE_V4F (POLYDATA_VERTEX4)
  299. #define VTYPE_C3F (POLYDATA_COLOR_VALID)
  300. #define VTYPE_C4F (POLYDATA_COLOR_VALID | POLYDATA_DLIST_COLOR_4)
  301. #define VTYPE_N3F (POLYDATA_NORMAL_VALID)
  302. #define VTYPE_T2F (POLYDATA_TEXTURE_VALID | POLYDATA_DLIST_TEXTURE2)
  303. #define VTYPE_C3F_V3F (VTYPE_C3F | VTYPE_V3F)
  304. #define VTYPE_N3F_V3F (VTYPE_N3F | VTYPE_V3F)
  305. #define VTYPE_C3F_N3F_V3F (VTYPE_C3F | VTYPE_N3F | VTYPE_V3F)
  306. #define VTYPE_C4F_N3F_V3F (VTYPE_C4F | VTYPE_N3F | VTYPE_V3F)
  307. #define VTYPE_T2F_V3F (VTYPE_T2F | VTYPE_V3F)
  308. #define VTYPE_T2F_C3F_V3F (VTYPE_T2F | VTYPE_C3F | VTYPE_V3F)
  309. #define VTYPE_T2F_N3F_V3F (VTYPE_T2F | VTYPE_N3F | VTYPE_V3F)
  310. #define VTYPE_T2F_C3F_N3F_V3F (VTYPE_T2F | VTYPE_C3F | VTYPE_N3F | VTYPE_V3F)
  311. #define VTYPE_T2F_C4F_N3F_V3F (VTYPE_T2F | VTYPE_C4F | VTYPE_N3F | VTYPE_V3F)
  312. // Default playback routine
  313. fp = __glle_PolyData;
  314. if (!gc->modes.colorIndexMode &&
  315. !(pdflags & (POLYDATA_EDGEFLAG_BOUNDARY |
  316. POLYDATA_EDGEFLAG_VALID)))
  317. {
  318. switch (pdflags)
  319. {
  320. case VTYPE_V2F:
  321. case VTYPE_V3F:
  322. case VTYPE_V4F:
  323. ASSERTOPENGL(gc->dlist.mode != GL_COMPILE,
  324. "should have been recorded as a Vertex call\n");
  325. break;
  326. case VTYPE_C3F_V3F:
  327. fp = __glle_PolyData_C3F_V3F;
  328. break;
  329. case VTYPE_N3F_V3F:
  330. fp = __glle_PolyData_N3F_V3F;
  331. break;
  332. case VTYPE_C3F_N3F_V3F:
  333. fp = __glle_PolyData_C3F_N3F_V3F;
  334. break;
  335. case VTYPE_C4F_N3F_V3F:
  336. fp = __glle_PolyData_C4F_N3F_V3F;
  337. break;
  338. case VTYPE_T2F_V3F:
  339. fp = __glle_PolyData_T2F_V3F;
  340. break;
  341. case VTYPE_T2F_C3F_V3F:
  342. fp = __glle_PolyData_T2F_C3F_V3F;
  343. break;
  344. case VTYPE_T2F_N3F_V3F:
  345. fp = __glle_PolyData_T2F_N3F_V3F;
  346. break;
  347. case VTYPE_T2F_C3F_N3F_V3F:
  348. fp = __glle_PolyData_T2F_C3F_N3F_V3F;
  349. break;
  350. case VTYPE_T2F_C4F_N3F_V3F:
  351. fp = __glle_PolyData_T2F_C4F_N3F_V3F;
  352. break;
  353. }
  354. }
  355. // Allocate the dlist record. Allocate big enough record and resize it later.
  356. size = sizeof(POLYDATA) + sizeof(GLuint);
  357. data = (GLubyte *) __glDlistAddOpUnaligned(gc, DLIST_SIZE(size), fp);
  358. if (data == NULL) return;
  359. data0 = data;
  360. // Increment vertex count.
  361. if (!bPartial)
  362. gc->dlist.beginRec->nVertices++;
  363. // Compile the poly data record.
  364. // The fast poly data records do not include size and flags fields.
  365. if (fp == __glle_PolyData)
  366. {
  367. // Skip size field to be filled in last
  368. ((GLuint *) data)++;
  369. // flags and edge flag
  370. *((GLuint *) data)++ = pdflags;
  371. }
  372. // Texture coord
  373. if (pdflags & (POLYDATA_DLIST_TEXTURE4 | POLYDATA_DLIST_TEXTURE3
  374. | POLYDATA_DLIST_TEXTURE2 | POLYDATA_DLIST_TEXTURE1))
  375. {
  376. *((__GLfloat *) data)++ = pd->texture.x;
  377. if (pdflags & (POLYDATA_DLIST_TEXTURE4 | POLYDATA_DLIST_TEXTURE3
  378. | POLYDATA_DLIST_TEXTURE2))
  379. {
  380. *((__GLfloat *) data)++ = pd->texture.y;
  381. if (pdflags & (POLYDATA_DLIST_TEXTURE4 | POLYDATA_DLIST_TEXTURE3))
  382. {
  383. *((__GLfloat *) data)++ = pd->texture.z;
  384. if (pdflags & (POLYDATA_DLIST_TEXTURE4))
  385. *((__GLfloat *) data)++ = pd->texture.w;
  386. }
  387. }
  388. }
  389. // Color
  390. if (pdflags & POLYDATA_COLOR_VALID)
  391. {
  392. *((__GLfloat *) data)++ = pd->colors[0].r;
  393. if (!gc->modes.colorIndexMode)
  394. {
  395. *((__GLfloat *) data)++ = pd->colors[0].g;
  396. *((__GLfloat *) data)++ = pd->colors[0].b;
  397. if (pdflags & POLYDATA_DLIST_COLOR_4)
  398. *((__GLfloat *) data)++ = pd->colors[0].a;
  399. }
  400. }
  401. // Normal
  402. if (pdflags & POLYDATA_NORMAL_VALID)
  403. {
  404. *((__GLfloat *) data)++ = pd->normal.x;
  405. *((__GLfloat *) data)++ = pd->normal.y;
  406. *((__GLfloat *) data)++ = pd->normal.z;
  407. }
  408. // Vertex, evalcoord1, evalcoord2, evapoint1, or evalpoint2
  409. if (pdflags & (POLYDATA_VERTEX2 | POLYDATA_VERTEX3 | POLYDATA_VERTEX4))
  410. {
  411. ASSERTOPENGL(!bPartial, "vertex unexpected\n");
  412. *((__GLfloat *) data)++ = pd->obj.x;
  413. if (pdflags & (POLYDATA_VERTEX2 | POLYDATA_VERTEX3 | POLYDATA_VERTEX4))
  414. {
  415. *((__GLfloat *) data)++ = pd->obj.y;
  416. if (pdflags & (POLYDATA_VERTEX3 | POLYDATA_VERTEX4))
  417. {
  418. *((__GLfloat *) data)++ = pd->obj.z;
  419. if (pdflags & (POLYDATA_VERTEX4))
  420. *((__GLfloat *) data)++ = pd->obj.w;
  421. }
  422. }
  423. }
  424. else
  425. {
  426. ASSERTOPENGL(bPartial, "vertex expected\n");
  427. }
  428. // Now fill in the size field
  429. newSize = (GLuint) (data - data0);
  430. if (fp == __glle_PolyData)
  431. *((GLuint *) data0) = newSize;
  432. // Resize the record
  433. __glDlistResizeCurrentOp(gc, DLIST_SIZE(size), DLIST_SIZE(newSize));
  434. }
  435. #ifndef __GL_ASM_FAST_DLIST_PLAYBACK
  436. // Define fast playback routines for PolyData records.
  437. #define __GLLE_POLYDATA_C3F_V3F 1
  438. #include "dl_pdata.h"
  439. #undef __GLLE_POLYDATA_C3F_V3F
  440. #define __GLLE_POLYDATA_N3F_V3F 1
  441. #include "dl_pdata.h"
  442. #undef __GLLE_POLYDATA_N3F_V3F
  443. #define __GLLE_POLYDATA_C3F_N3F_V3F 1
  444. #include "dl_pdata.h"
  445. #undef __GLLE_POLYDATA_C3F_N3F_V3F
  446. #define __GLLE_POLYDATA_C4F_N3F_V3F 1
  447. #include "dl_pdata.h"
  448. #undef __GLLE_POLYDATA_C4F_N3F_V3F
  449. #define __GLLE_POLYDATA_T2F_V3F 1
  450. #include "dl_pdata.h"
  451. #undef __GLLE_POLYDATA_T2F_V3F
  452. #define __GLLE_POLYDATA_T2F_C3F_V3F 1
  453. #include "dl_pdata.h"
  454. #undef __GLLE_POLYDATA_T2F_C3F_V3F
  455. #define __GLLE_POLYDATA_T2F_N3F_V3F 1
  456. #include "dl_pdata.h"
  457. #undef __GLLE_POLYDATA_T2F_N3F_V3F
  458. #define __GLLE_POLYDATA_T2F_C3F_N3F_V3F 1
  459. #include "dl_pdata.h"
  460. #undef __GLLE_POLYDATA_T2F_C3F_N3F_V3F
  461. #define __GLLE_POLYDATA_T2F_C4F_N3F_V3F 1
  462. #include "dl_pdata.h"
  463. #undef __GLLE_POLYDATA_T2F_C4F_N3F_V3F
  464. #endif // __GL_ASM_FAST_DLIST_PLAYBACK
  465. // Playback a PolyData record in Begin.
  466. const GLubyte * FASTCALL __glle_PolyData(__GLcontext *gc, const GLubyte *PC)
  467. {
  468. GLubyte *data;
  469. POLYARRAY *pa;
  470. POLYDATA *pd;
  471. GLuint size, pdflags;
  472. data = (GLubyte *) PC;
  473. size = *((GLuint *) data)++;
  474. pa = gc->paTeb;
  475. if (pa->flags & POLYARRAY_IN_BEGIN)
  476. {
  477. pdflags = *((GLuint *) data)++;
  478. // Make sure that we handle all the flags!
  479. ASSERTOPENGL(
  480. !(pdflags &
  481. ~(POLYDATA_EDGEFLAG_BOUNDARY |
  482. POLYDATA_EDGEFLAG_VALID |
  483. POLYDATA_COLOR_VALID |
  484. POLYDATA_NORMAL_VALID |
  485. POLYDATA_TEXTURE_VALID |
  486. POLYDATA_VERTEX2 |
  487. POLYDATA_VERTEX3 |
  488. POLYDATA_VERTEX4 |
  489. POLYDATA_DLIST_COLOR_4 |
  490. POLYDATA_DLIST_TEXTURE1 |
  491. POLYDATA_DLIST_TEXTURE2 |
  492. POLYDATA_DLIST_TEXTURE3 |
  493. POLYDATA_DLIST_TEXTURE4)),
  494. "Unknown POLYDATA flags!\n");
  495. // Update pa flags.
  496. pa->flags |= pdflags &
  497. (POLYARRAY_VERTEX2 | POLYARRAY_VERTEX3 | POLYARRAY_VERTEX4 |
  498. POLYARRAY_TEXTURE1 | POLYARRAY_TEXTURE2 |
  499. POLYARRAY_TEXTURE3 | POLYARRAY_TEXTURE4);
  500. // Update pd attributes.
  501. pd = pa->pdNextVertex;
  502. pd->flags |= (pdflags & ~POLYDATA_EDGEFLAG_BOUNDARY);
  503. // Edge flag
  504. if (pdflags & POLYDATA_EDGEFLAG_VALID)
  505. {
  506. // Clear the edge flag here since they may be a previous edge flag
  507. pd->flags &= ~POLYDATA_EDGEFLAG_BOUNDARY;
  508. pd->flags |= pdflags;
  509. pa->pdCurEdgeFlag = pd;
  510. }
  511. // Texture coord
  512. // We need to be careful here if it has 2 TexCoord calls with
  513. // different sizes.
  514. if (pdflags & (POLYDATA_DLIST_TEXTURE4 | POLYDATA_DLIST_TEXTURE3
  515. | POLYDATA_DLIST_TEXTURE2 | POLYDATA_DLIST_TEXTURE1))
  516. {
  517. pd->texture.x = *((__GLfloat *) data)++;
  518. pa->pdCurTexture = pd;
  519. if (pdflags & (POLYDATA_DLIST_TEXTURE4 | POLYDATA_DLIST_TEXTURE3
  520. | POLYDATA_DLIST_TEXTURE2))
  521. pd->texture.y = *((__GLfloat *) data)++;
  522. else
  523. pd->texture.y = __glZero;
  524. if (pdflags & (POLYDATA_DLIST_TEXTURE4 | POLYDATA_DLIST_TEXTURE3))
  525. pd->texture.z = *((__GLfloat *) data)++;
  526. else
  527. pd->texture.z = __glZero;
  528. if (pdflags & (POLYDATA_DLIST_TEXTURE4))
  529. pd->texture.w = *((__GLfloat *) data)++;
  530. else
  531. pd->texture.w = __glOne;
  532. }
  533. // Color
  534. if (pdflags & POLYDATA_COLOR_VALID)
  535. {
  536. pd->color[0].r = *((__GLfloat *) data)++;
  537. if (!gc->modes.colorIndexMode)
  538. {
  539. pd->color[0].g = *((__GLfloat *) data)++;
  540. pd->color[0].b = *((__GLfloat *) data)++;
  541. if (pdflags & POLYDATA_DLIST_COLOR_4)
  542. pd->color[0].a = *((__GLfloat *) data)++;
  543. else
  544. pd->color[0].a = gc->alphaVertexScale;
  545. }
  546. pa->pdCurColor = pd;
  547. }
  548. // Normal
  549. if (pdflags & POLYDATA_NORMAL_VALID)
  550. {
  551. pd->normal.x = *((__GLfloat *) data)++;
  552. pd->normal.y = *((__GLfloat *) data)++;
  553. pd->normal.z = *((__GLfloat *) data)++;
  554. pa->pdCurNormal = pd;
  555. }
  556. // Vertex, evalcoord1, evalcoord2, evapoint1, or evalpoint2
  557. if (pdflags &
  558. (POLYARRAY_VERTEX2 | POLYARRAY_VERTEX3 | POLYARRAY_VERTEX4))
  559. {
  560. pd->obj.x = *((__GLfloat *) data)++;
  561. if (pdflags & (POLYDATA_VERTEX2 | POLYDATA_VERTEX3 | POLYDATA_VERTEX4))
  562. pd->obj.y = *((__GLfloat *) data)++;
  563. if (pdflags & (POLYDATA_VERTEX3 | POLYDATA_VERTEX4))
  564. pd->obj.z = *((__GLfloat *) data)++;
  565. else
  566. pd->obj.z = __glZero;
  567. if (pdflags & (POLYDATA_VERTEX4))
  568. pd->obj.w = *((__GLfloat *) data)++;
  569. else
  570. pd->obj.w = __glOne;
  571. // Advance vertex pointer
  572. pa->pdNextVertex++;
  573. pd[1].flags = 0;
  574. if (pd >= pa->pdFlush)
  575. PolyArrayFlushPartialPrimitive();
  576. }
  577. }
  578. else
  579. {
  580. // Something went wrong at playback time! We can either try to playback
  581. // this record using the regular API or punt it altogether. I cannot think
  582. // of a situation when this can happen, so we will punt it for now.
  583. WARNING("Display list: playing back POLYDATA outside BEGIN!\n");
  584. }
  585. return PC + size;
  586. }
  587. void APIENTRY __gllc_ArrayElement(GLint i)
  588. {
  589. __GL_SETUP();
  590. if (gc->vertexArray.flags & __GL_VERTEX_ARRAY_DIRTY)
  591. VA_ValidateArrayPointers(gc);
  592. VA_ArrayElementCompile(gc, i);
  593. }
  594. #define COMPILEARRAYPOINTER(ap, i) \
  595. ((*(ap).pfnCompile)((ap).pointer + (i) * (ap).ibytes))
  596. void FASTCALL VA_ArrayElementCompile(__GLcontext *gc, GLint i)
  597. {
  598. GLuint vaMask = gc->vertexArray.mask;
  599. // Call the individual compilation routines. They handle Begin mode,
  600. // color mode, and COMPILE_AND_EXECUTE mode correctly.
  601. if (vaMask & VAMASK_EDGEFLAG_ENABLE_MASK)
  602. COMPILEARRAYPOINTER(gc->vertexArray.edgeFlag, i);
  603. if (vaMask & VAMASK_TEXCOORD_ENABLE_MASK)
  604. COMPILEARRAYPOINTER(gc->vertexArray.texCoord, i);
  605. if (vaMask & VAMASK_COLOR_ENABLE_MASK)
  606. COMPILEARRAYPOINTER(gc->vertexArray.color, i);
  607. if (vaMask & VAMASK_INDEX_ENABLE_MASK)
  608. COMPILEARRAYPOINTER(gc->vertexArray.index, i);
  609. if (vaMask & VAMASK_NORMAL_ENABLE_MASK)
  610. COMPILEARRAYPOINTER(gc->vertexArray.normal, i);
  611. if (vaMask & VAMASK_VERTEX_ENABLE_MASK)
  612. COMPILEARRAYPOINTER(gc->vertexArray.vertex, i);
  613. }
  614. // Compile DrawArrays into Begin/End records. Since Begin/End records
  615. // contain optimized POLYDATA records, execution speed of these records
  616. // is optimal. However, it takes longer to compile this function using
  617. // this approach. But with this method, we don't have to deal with color
  618. // mode and COMPILE_AND_EXECUTE mode here.
  619. void APIENTRY __gllc_DrawArrays(GLenum mode, GLint first, GLsizei count)
  620. {
  621. int i;
  622. POLYARRAY *pa;
  623. __GL_SETUP();
  624. pa = gc->paTeb;
  625. // Not allowed in begin/end.
  626. if (pa->flags & POLYARRAY_IN_BEGIN)
  627. {
  628. __gllc_InvalidOperation();
  629. return;
  630. }
  631. if ((GLuint) mode > GL_POLYGON)
  632. {
  633. __gllc_InvalidEnum();
  634. return;
  635. }
  636. if (count < 0)
  637. {
  638. __gllc_InvalidValue();
  639. return;
  640. } else if (!count)
  641. return;
  642. // Find array element function to use.
  643. if (gc->vertexArray.flags & __GL_VERTEX_ARRAY_DIRTY)
  644. VA_ValidateArrayPointers(gc);
  645. // Draw the array elements.
  646. __gllc_Begin(mode);
  647. gc->dlist.beginRec->flags |= DLIST_BEGIN_DRAWARRAYS;
  648. for (i = 0; i < count; i++)
  649. VA_ArrayElementCompile(gc, first + i);
  650. __gllc_End();
  651. }
  652. #define __GL_PAD8(x) (((x) + 7) & ~7)
  653. GLuint FASTCALL __glDrawElements_size(__GLcontext *gc, GLsizei nVertices,
  654. GLsizei nElements, struct __gllc_DrawElements_Rec *rec)
  655. {
  656. GLuint size;
  657. GLuint vaMask;
  658. // Compute the size of each of the six arrays. Always keep size and address
  659. // QWORD aligned since some arrays may use GLdouble.
  660. size = __GL_PAD8(sizeof(struct __gllc_DrawElements_Rec));
  661. vaMask = gc->vertexArray.mask;
  662. if (vaMask & VAMASK_EDGEFLAG_ENABLE_MASK)
  663. {
  664. rec->edgeFlagOff = size;
  665. size += __GL_PAD8(nVertices * sizeof(GLboolean));
  666. }
  667. else
  668. rec->edgeFlagOff = 0;
  669. if (vaMask & VAMASK_TEXCOORD_ENABLE_MASK)
  670. {
  671. rec->texCoordOff = size;
  672. size += __GL_PAD8(nVertices * gc->vertexArray.texCoord.size *
  673. __GLTYPESIZE(gc->vertexArray.texCoord.type));
  674. }
  675. else
  676. rec->texCoordOff = 0;
  677. if (vaMask & VAMASK_COLOR_ENABLE_MASK)
  678. {
  679. rec->colorOff = size;
  680. size += __GL_PAD8(nVertices * gc->vertexArray.color.size *
  681. __GLTYPESIZE(gc->vertexArray.color.type));
  682. }
  683. else
  684. rec->colorOff = 0;
  685. if (vaMask & VAMASK_INDEX_ENABLE_MASK)
  686. {
  687. rec->indexOff = size;
  688. size += __GL_PAD8(nVertices * __GLTYPESIZE(gc->vertexArray.index.type));
  689. }
  690. else
  691. rec->indexOff = 0;
  692. if (vaMask & VAMASK_NORMAL_ENABLE_MASK)
  693. {
  694. rec->normalOff = size;
  695. size += __GL_PAD8(nVertices * 3 *
  696. __GLTYPESIZE(gc->vertexArray.normal.type));
  697. }
  698. else
  699. rec->normalOff = 0;
  700. if (vaMask & VAMASK_VERTEX_ENABLE_MASK)
  701. {
  702. rec->vertexOff = size;
  703. size += __GL_PAD8(nVertices * gc->vertexArray.vertex.size *
  704. __GLTYPESIZE(gc->vertexArray.vertex.type));
  705. }
  706. else
  707. rec->vertexOff = 0;
  708. rec->mapOff = size;
  709. size += __GL_PAD8(nElements * sizeof(GLubyte));
  710. return(size);
  711. }
  712. void FASTCALL __gllc_ReducedElementsHandler(__GLcontext *gc,
  713. GLenum mode,
  714. GLsizei iVertexCount,
  715. GLsizei iVertexBase,
  716. VAMAP *pvmVertices,
  717. GLsizei iElementCount,
  718. GLubyte *pbElements,
  719. GLboolean fPartial)
  720. {
  721. GLuint vaMask;
  722. GLuint size;
  723. GLubyte *pv1, *pv2;
  724. GLsizei stride;
  725. GLsizei i;
  726. struct __gllc_DrawElements_Rec *data, drawElementsRec;
  727. ASSERTOPENGL(pvmVertices != NULL,
  728. "__gllc_ReducedElementsHandler requires mapped vertices\n");
  729. // Allocate the record.
  730. size = __glDrawElements_size(gc, iVertexCount, iElementCount,
  731. &drawElementsRec);
  732. data = (struct __gllc_DrawElements_Rec *)
  733. __glDlistAddOpAligned(gc, DLIST_SIZE(size),
  734. DLIST_GENERIC_OP(DrawElements));
  735. if (data == NULL)
  736. {
  737. return;
  738. }
  739. #ifndef _IA64_
  740. ASSERTOPENGL((UINT_PTR) data == __GL_PAD8((UINT_PTR) data),
  741. "data not qword aligned\n");
  742. #endif
  743. vaMask = gc->vertexArray.mask;
  744. data->mode = mode;
  745. data->iElementCount = iElementCount;
  746. data->iVertexCount = iVertexCount;
  747. data->vaMask = vaMask;
  748. data->partial = fPartial;
  749. data->recSize = size;
  750. data->edgeFlagOff = drawElementsRec.edgeFlagOff;
  751. data->texCoordOff = drawElementsRec.texCoordOff;
  752. data->indexOff = drawElementsRec.indexOff;
  753. data->colorOff = drawElementsRec.colorOff;
  754. data->normalOff = drawElementsRec.normalOff;
  755. data->vertexOff = drawElementsRec.vertexOff;
  756. data->mapOff = drawElementsRec.mapOff;
  757. // Record the vertex arrays.
  758. // Note that iVertexBase parameter is not used, since all accesses here are
  759. // 0-based. It is there for function ptr compatibility with glcltReducedElementHandler
  760. if (vaMask & VAMASK_EDGEFLAG_ENABLE_MASK)
  761. {
  762. pv2 = &((GLubyte *) data)[data->edgeFlagOff];
  763. pv1 = (GLubyte *) gc->vertexArray.edgeFlag.pointer;
  764. stride = gc->vertexArray.edgeFlag.ibytes;
  765. for (i = 0; i < iVertexCount; i++)
  766. {
  767. *((GLboolean *) pv2) = *((GLboolean *)
  768. (pv1 + pvmVertices[i].iIn * stride));
  769. pv2 += sizeof(GLboolean);
  770. }
  771. }
  772. if (vaMask & VAMASK_TEXCOORD_ENABLE_MASK)
  773. {
  774. pv2 = &((GLubyte *) data)[data->texCoordOff];
  775. size = gc->vertexArray.texCoord.size *
  776. __GLTYPESIZE(gc->vertexArray.texCoord.type);
  777. pv1 = (GLubyte *) gc->vertexArray.texCoord.pointer;
  778. stride = gc->vertexArray.texCoord.ibytes;
  779. data->texCoordSize = gc->vertexArray.texCoord.size;
  780. data->texCoordType = gc->vertexArray.texCoord.type;
  781. for (i = 0; i < iVertexCount; i++)
  782. {
  783. memcpy(pv2, pv1 + pvmVertices[i].iIn * stride, size);
  784. pv2 += size;
  785. }
  786. }
  787. if (vaMask & VAMASK_COLOR_ENABLE_MASK)
  788. {
  789. pv2 = &((GLubyte *) data)[data->colorOff];
  790. size = gc->vertexArray.color.size *
  791. __GLTYPESIZE(gc->vertexArray.color.type);
  792. pv1 = (GLubyte *) gc->vertexArray.color.pointer;
  793. stride = gc->vertexArray.color.ibytes;
  794. data->colorSize = gc->vertexArray.color.size;
  795. data->colorType = gc->vertexArray.color.type;
  796. for (i = 0; i < iVertexCount; i++)
  797. {
  798. memcpy(pv2, pv1 + pvmVertices[i].iIn * stride, size);
  799. pv2 += size;
  800. }
  801. }
  802. if (vaMask & VAMASK_INDEX_ENABLE_MASK)
  803. {
  804. pv2 = &((GLubyte *) data)[data->indexOff];
  805. size = __GLTYPESIZE(gc->vertexArray.index.type);
  806. pv1 = (GLubyte *) gc->vertexArray.index.pointer;
  807. stride = gc->vertexArray.index.ibytes;
  808. data->indexType = gc->vertexArray.index.type;
  809. for (i = 0; i < iVertexCount; i++)
  810. {
  811. memcpy(pv2, pv1 + pvmVertices[i].iIn * stride, size);
  812. pv2 += size;
  813. }
  814. }
  815. if (vaMask & VAMASK_NORMAL_ENABLE_MASK)
  816. {
  817. pv2 = &((GLubyte *) data)[data->normalOff];
  818. size = 3 * __GLTYPESIZE(gc->vertexArray.normal.type);
  819. pv1 = (GLubyte *) gc->vertexArray.normal.pointer;
  820. stride = gc->vertexArray.normal.ibytes;
  821. data->normalType = gc->vertexArray.normal.type;
  822. for (i = 0; i < iVertexCount; i++)
  823. {
  824. memcpy(pv2, pv1 + pvmVertices[i].iIn * stride, size);
  825. pv2 += size;
  826. }
  827. }
  828. if (vaMask & VAMASK_VERTEX_ENABLE_MASK)
  829. {
  830. pv2 = &((GLubyte *) data)[data->vertexOff];
  831. size = gc->vertexArray.vertex.size *
  832. __GLTYPESIZE(gc->vertexArray.vertex.type);
  833. pv1 = (GLubyte *) gc->vertexArray.vertex.pointer;
  834. stride = gc->vertexArray.vertex.ibytes;
  835. data->vertexSize = gc->vertexArray.vertex.size;
  836. data->vertexType = gc->vertexArray.vertex.type;
  837. for (i = 0; i < iVertexCount; i++)
  838. {
  839. memcpy(pv2, pv1 + pvmVertices[i].iIn * stride, size);
  840. pv2 += size;
  841. }
  842. }
  843. // Record new index mapping array.
  844. pv2 = &((GLubyte *) data)[data->mapOff];
  845. memcpy(pv2, pbElements, iElementCount*sizeof(GLubyte));
  846. __glDlistAppendOp(gc, data, __glle_DrawElements);
  847. }
  848. void APIENTRY __gllc_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *pIn)
  849. {
  850. POLYARRAY *pa;
  851. GLuint iIn;
  852. GLsizei iCount;
  853. struct __gllc_DrawElementsBegin_Rec *dataBegin;
  854. __GL_SETUP();
  855. // Flush the cached memory pointers if we are in COMPILE_AND_EXECUTE mode.
  856. // See __glShrinkDlist for details.
  857. if (gc->dlist.mode == GL_COMPILE_AND_EXECUTE)
  858. glsbAttention();
  859. pa = gc->paTeb;
  860. // If we are already in the begin/end bracket, return an error.
  861. if (pa->flags & POLYARRAY_IN_BEGIN)
  862. {
  863. __gllc_InvalidOperation();
  864. return;
  865. }
  866. if ((GLuint) mode > GL_POLYGON)
  867. {
  868. __gllc_InvalidEnum();
  869. return;
  870. }
  871. if (count < 0)
  872. {
  873. __gllc_InvalidValue();
  874. return;
  875. } else if (!count)
  876. return;
  877. switch (type)
  878. {
  879. case GL_UNSIGNED_BYTE:
  880. case GL_UNSIGNED_SHORT:
  881. case GL_UNSIGNED_INT:
  882. break;
  883. default:
  884. __gllc_InvalidEnum();
  885. return;
  886. }
  887. // Find array element function to use.
  888. if (gc->vertexArray.flags & __GL_VERTEX_ARRAY_DIRTY)
  889. VA_ValidateArrayPointers(gc);
  890. // Convert Points, Line Loop and Polygon to DrawArrays call. Points and Polygon
  891. // don't benefit from optimization in this function. Further, Polygon and
  892. // Line Loop are too tricky to deal with in this function.
  893. if (mode == GL_POINTS || mode == GL_LINE_LOOP || mode == GL_POLYGON)
  894. {
  895. __gllc_Begin(mode);
  896. gc->dlist.beginRec->flags |= DLIST_BEGIN_DRAWARRAYS;
  897. for (iCount = 0; iCount < count; iCount++)
  898. {
  899. // Get next input index.
  900. if (type == GL_UNSIGNED_BYTE)
  901. iIn = (GLuint) ((GLubyte *) pIn)[iCount];
  902. else if (type == GL_UNSIGNED_SHORT)
  903. iIn = (GLuint) ((GLushort *) pIn)[iCount];
  904. else
  905. iIn = (GLuint) ((GLuint *) pIn)[iCount];
  906. VA_ArrayElementCompile(gc, iIn);
  907. }
  908. __gllc_End();
  909. return;
  910. }
  911. // Allocate begin record
  912. dataBegin = (struct __gllc_DrawElementsBegin_Rec *)
  913. __glDlistAddOpUnaligned(gc, DLIST_SIZE(sizeof(struct __gllc_DrawElementsBegin_Rec)),
  914. DLIST_GENERIC_OP(DrawElementsBegin));
  915. if (dataBegin == NULL)
  916. {
  917. return;
  918. }
  919. dataBegin->mode = mode;
  920. dataBegin->count = min(count, VA_DRAWELEM_MAP_SIZE);
  921. dataBegin->vaMask = gc->vertexArray.mask;
  922. __glDlistAppendOp(gc, dataBegin, __glle_DrawElementsBegin);
  923. // Reduce input data into easily processed chunks
  924. ReduceDrawElements(gc, mode, count, type, pIn,
  925. __gllc_ReducedElementsHandler);
  926. }
  927. const GLubyte * FASTCALL __glle_DrawElementsBegin(__GLcontext *gc, const GLubyte *PC)
  928. {
  929. struct __gllc_DrawElementsBegin_Rec *data;
  930. // Not allowed in begin/end.
  931. // Must use the client side begin state
  932. if (gc->paTeb->flags & POLYARRAY_IN_BEGIN)
  933. {
  934. GLSETERROR(GL_INVALID_OPERATION);
  935. // Mark saved state as invalid
  936. gc->savedVertexArray.flags = 0xffffffff;
  937. goto __glle_DrawElementsBegin_exit;
  938. }
  939. data = (struct __gllc_DrawElementsBegin_Rec *) PC;
  940. // Save vertex array states.
  941. gc->savedVertexArray = gc->vertexArray;
  942. // Set up temporary vertex arrays.
  943. // By setting up the mask value in gc, we don't need to call EnableClientState
  944. // and DisableClientState. We still need to set up pointers for the enabled
  945. // arrays.
  946. gc->vertexArray.mask = data->vaMask;
  947. // Force validation since we just completely changed the vertex array
  948. // enable state
  949. VA_ValidateArrayPointers(gc);
  950. // Begin primitive
  951. VA_DrawElementsBegin(gc->paTeb, data->mode, data->count);
  952. __glle_DrawElementsBegin_exit:
  953. return PC + sizeof(struct __gllc_DrawElementsBegin_Rec);
  954. }
  955. void APIENTRY __gllc_DrawRangeElementsWIN(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *pIn)
  956. {
  957. // !!! Currently we call the DrawElements function here when in lc mode.
  958. // If compile time performance for DrawRangeElements becomes an issue, then
  959. // we can flesh out this function.
  960. __gllc_DrawElements( mode, count, type, pIn );
  961. }
  962. const GLubyte * FASTCALL __glle_DrawElements(__GLcontext *gc, const GLubyte *PC)
  963. {
  964. GLuint vaMask;
  965. POLYARRAY *pa;
  966. struct __gllc_DrawElements_Rec *data;
  967. data = (struct __gllc_DrawElements_Rec *) PC;
  968. pa = gc->paTeb;
  969. // Must be in begin since DrawElementsBegin has started the primitive
  970. // Must use the client side begin state
  971. if ((pa->flags & POLYARRAY_IN_BEGIN) == 0 ||
  972. gc->savedVertexArray.flags == 0xffffffff)
  973. {
  974. GLSETERROR(GL_INVALID_OPERATION);
  975. goto __glle_DrawElements_exit;
  976. }
  977. vaMask = data->vaMask;
  978. // Set up temporary vertex arrays.
  979. // We need to temporarily mask off the begin flag so that these
  980. // calls can succeed. We probably want to do something smarter
  981. // that avoids parameter validation but this is good enough for now
  982. // Note that in immediate mode, the array function pointers are set up
  983. // once in __glle_DrawElementsBegin and remain unchanged until all
  984. // sub-batches are processed. In COMPILE_AND_EXECUTE mode, the array
  985. // function pointers are also set up once in __glle_DrawElementsBegin.
  986. // Since these function pointers are the same for compilation and
  987. // execution, we don't need to re-validate them for each sub-batch here.
  988. pa->flags ^= POLYARRAY_IN_BEGIN;
  989. if (vaMask & VAMASK_EDGEFLAG_ENABLE_MASK)
  990. glcltEdgeFlagPointer(0, &((GLubyte *) data)[data->edgeFlagOff]);
  991. if (vaMask & VAMASK_TEXCOORD_ENABLE_MASK)
  992. glcltTexCoordPointer(data->texCoordSize, data->texCoordType,
  993. 0, &((GLubyte *) data)[data->texCoordOff]);
  994. if (vaMask & VAMASK_COLOR_ENABLE_MASK)
  995. glcltColorPointer(data->colorSize, data->colorType,
  996. 0, &((GLubyte *) data)[data->colorOff]);
  997. if (vaMask & VAMASK_INDEX_ENABLE_MASK)
  998. glcltIndexPointer(data->indexType,
  999. 0, &((GLubyte *) data)[data->indexOff]);
  1000. if (vaMask & VAMASK_NORMAL_ENABLE_MASK)
  1001. glcltNormalPointer(data->normalType,
  1002. 0, &((GLubyte *) data)[data->normalOff]);
  1003. if (vaMask & VAMASK_VERTEX_ENABLE_MASK)
  1004. glcltVertexPointer(data->vertexSize, data->vertexType,
  1005. 0, &((GLubyte *) data)[data->vertexOff]);
  1006. pa->flags ^= POLYARRAY_IN_BEGIN;
  1007. // Call immediate mode chunk handler
  1008. glcltReducedElementsHandler(gc, data->mode,
  1009. data->iVertexCount, 0, NULL,
  1010. data->iElementCount,
  1011. (GLubyte *)data+data->mapOff,
  1012. data->partial);
  1013. // Restore vertex array states in the following conditions:
  1014. // 1. The DrawElements record is completed
  1015. // 2. It is in COMPILE_AND_EXECUTE mode and it is not called as a result
  1016. // of executing a CallList record. That is, the record is being
  1017. // compile *and* executed at the same time.
  1018. if ((!data->partial) ||
  1019. ((gc->dlist.mode == GL_COMPILE_AND_EXECUTE) && !gc->dlist.nesting))
  1020. {
  1021. gc->vertexArray = gc->savedVertexArray;
  1022. }
  1023. __glle_DrawElements_exit:
  1024. return PC + data->recSize;
  1025. }
  1026. void APIENTRY
  1027. __gllc_Begin ( IN GLenum mode )
  1028. {
  1029. POLYARRAY *pa;
  1030. struct __gllc_Begin_Rec *data;
  1031. __GL_SETUP();
  1032. // Flush the cached memory pointers if we are in COMPILE_AND_EXECUTE mode.
  1033. // See __glShrinkDlist for details.
  1034. if (gc->dlist.mode == GL_COMPILE_AND_EXECUTE)
  1035. glsbAttention();
  1036. // If we are already in the begin/end bracket, return an error.
  1037. pa = gc->paTeb;
  1038. if (pa->flags & POLYARRAY_IN_BEGIN)
  1039. {
  1040. __gllc_InvalidOperation();
  1041. return;
  1042. }
  1043. if ((GLuint) mode > GL_POLYGON)
  1044. {
  1045. __gllc_InvalidEnum();
  1046. return;
  1047. }
  1048. // Add the Begin record.
  1049. data = (struct __gllc_Begin_Rec *)
  1050. __glDlistAddOpUnaligned(gc,
  1051. DLIST_SIZE(sizeof(struct __gllc_Begin_Rec)),
  1052. DLIST_GENERIC_OP(Begin));
  1053. if (data == NULL) return;
  1054. data->mode = mode;
  1055. data->flags = 0;
  1056. data->nVertices = 0;
  1057. gc->dlist.skipPolyData = GL_FALSE;
  1058. // Use poly array code to compile the data structure for this primitive.
  1059. (*gc->savedCltProcTable.glDispatchTable.glBegin)(mode);
  1060. // Save the Begin record pointer. We are now compiling the poly array
  1061. // primitive. It is set to NULL in End.
  1062. gc->dlist.beginRec = data;
  1063. }
  1064. const GLubyte * FASTCALL __glle_Begin(__GLcontext *gc, const GLubyte *PC)
  1065. {
  1066. POLYARRAY *pa;
  1067. struct __gllc_Begin_Rec *data;
  1068. data = (struct __gllc_Begin_Rec *) PC;
  1069. pa = gc->paTeb;
  1070. // try not to break the poly data records into batches! The number 8
  1071. // is loosely chosen to allow for the poly array entry, the reserved
  1072. // polygon entries, and the flush limit. At worst, it causes an
  1073. // unnecessary attention!
  1074. if (data->nVertices <= (GLint) gc->vertex.pdBufSize - 8
  1075. && data->nVertices >= (GLint) (pa->pdBufferMax - pa->pdBufferNext + 1 - 8))
  1076. glsbAttention();
  1077. // call glcltBegin first
  1078. (*gc->savedCltProcTable.glDispatchTable.glBegin)(data->mode);
  1079. if (data->flags & DLIST_BEGIN_DRAWARRAYS)
  1080. pa->flags |= POLYARRAY_SAME_POLYDATA_TYPE;
  1081. // Set POLYARRAY_CLAMP_COLOR flag.
  1082. if (data->flags & DLIST_BEGIN_HAS_CLAMP_COLOR)
  1083. pa->flags |= POLYARRAY_CLAMP_COLOR;
  1084. // handle "otherColor"
  1085. if (data->flags & DLIST_BEGIN_HAS_OTHER_COLOR)
  1086. {
  1087. if (gc->modes.colorIndexMode)
  1088. (*gc->savedCltProcTable.glDispatchTable.glColor4fv)((GLfloat *) &data->otherColor);
  1089. else
  1090. (*gc->savedCltProcTable.glDispatchTable.glIndexf)(data->otherColor.r);
  1091. }
  1092. return PC + sizeof(struct __gllc_Begin_Rec);
  1093. }
  1094. void APIENTRY
  1095. __gllc_End ( void )
  1096. {
  1097. GLuint size;
  1098. POLYARRAY *pa;
  1099. void *data;
  1100. __GL_SETUP();
  1101. pa = gc->paTeb;
  1102. // If we are compiling poly array, finish the poly array processing.
  1103. // Note that we may have aborted poly array compilation in CallList(s).
  1104. // In that case, we need to compile an End record.
  1105. if (gc->dlist.beginRec)
  1106. {
  1107. ASSERTOPENGL(pa->flags & POLYARRAY_IN_BEGIN, "not in begin!\n");
  1108. // Record the last POLYDATA since it may contain attribute changes.
  1109. __glDlistCompilePolyData(gc, GL_TRUE);
  1110. // Call glcltEnd to finish the primitive.
  1111. (*gc->savedCltProcTable.glDispatchTable.glEnd)();
  1112. // Record the End call.
  1113. __glDlistAddOpUnaligned(gc, DLIST_SIZE(0), DLIST_GENERIC_OP(End));
  1114. // If we are in COMPILE mode, we need to reset the command buffer,
  1115. // the poly array buffer, and the poly material buffer.
  1116. if (gc->dlist.mode == GL_COMPILE)
  1117. {
  1118. glsbResetBuffers(TRUE);
  1119. // Clear begin flag too
  1120. pa->flags &= ~POLYARRAY_IN_BEGIN;
  1121. }
  1122. // Terminate poly array compilation
  1123. gc->dlist.beginRec = NULL;
  1124. }
  1125. else
  1126. {
  1127. // Record the call.
  1128. data = __glDlistAddOpUnaligned(gc, DLIST_SIZE(0), DLIST_GENERIC_OP(End));
  1129. if (data == NULL) return;
  1130. __glDlistAppendOp(gc, data, __glle_End);
  1131. }
  1132. }
  1133. const GLubyte * FASTCALL __glle_End(__GLcontext *gc, const GLubyte *PC)
  1134. {
  1135. (*gc->savedCltProcTable.glDispatchTable.glEnd)();
  1136. return PC;
  1137. }