Clone of mesa.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

debugger.c 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  1. /*
  2. * Test the GL_MESA_program_debug extension
  3. */
  4. #include <assert.h>
  5. #include <ctype.h>
  6. #include <string.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <math.h>
  10. #define GL_GLEXT_PROTOTYPES
  11. #include <GL/glut.h>
  12. /*
  13. * Print the string with line numbers
  14. */
  15. static void list_program(const GLubyte *string, GLsizei len)
  16. {
  17. const char *c = (const char *) string;
  18. int i, line = 1, printNumber = 1;
  19. for (i = 0; i < len; i++) {
  20. if (printNumber) {
  21. printf("%3d ", line);
  22. printNumber = 0;
  23. }
  24. if (*c == '\n') {
  25. line++;
  26. printNumber = 1;
  27. }
  28. putchar(*c);
  29. c++;
  30. }
  31. putchar('\n');
  32. }
  33. /*
  34. * Return the line number and column number that corresponds to the
  35. * given program position. Also return a null-terminated copy of that
  36. * line of the program string.
  37. */
  38. static const GLubyte *
  39. find_line_column(const GLubyte *string, const GLubyte *pos,
  40. GLint *line, GLint *col)
  41. {
  42. const GLubyte *lineStart = string;
  43. const GLubyte *p = string;
  44. GLubyte *s;
  45. int len;
  46. *line = 1;
  47. while (p != pos) {
  48. if (*p == (GLubyte) '\n') {
  49. (*line)++;
  50. lineStart = p + 1;
  51. }
  52. p++;
  53. }
  54. *col = (pos - lineStart) + 1;
  55. /* return copy of this line */
  56. while (*p != 0 && *p != '\n')
  57. p++;
  58. len = p - lineStart;
  59. s = (GLubyte *) malloc(len + 1);
  60. memcpy(s, lineStart, len);
  61. s[len] = 0;
  62. return s;
  63. }
  64. #define ARB_VERTEX_PROGRAM 1
  65. #define ARB_FRAGMENT_PROGRAM 2
  66. #define NV_VERTEX_PROGRAM 3
  67. #define NV_FRAGMENT_PROGRAM 4
  68. struct breakpoint {
  69. enum {PIXEL, LINE} type;
  70. int x, y;
  71. int line;
  72. GLboolean enabled;
  73. };
  74. #define MAX_BREAKPOINTS 100
  75. static struct breakpoint Breakpoints[MAX_BREAKPOINTS];
  76. static int NumBreakpoints = 0;
  77. /*
  78. * Interactive debugger
  79. */
  80. static void Debugger2(GLenum target, GLvoid *data)
  81. {
  82. static GLuint skipCount = 0;
  83. const GLubyte *ln;
  84. GLint pos, line, column;
  85. GLint id;
  86. int progType;
  87. GLint len;
  88. GLubyte *program;
  89. GLboolean stop;
  90. int i;
  91. /* Sigh, GL_VERTEX_PROGRAM_ARB == GL_VERTEX_PROGRAM_NV so it's a bit
  92. * hard to distinguish between them.
  93. */
  94. if (target == GL_FRAGMENT_PROGRAM_ARB)
  95. progType = ARB_FRAGMENT_PROGRAM;
  96. else if (target == GL_FRAGMENT_PROGRAM_NV)
  97. progType = NV_FRAGMENT_PROGRAM;
  98. else
  99. progType = NV_VERTEX_PROGRAM;
  100. /* Until we hit zero, continue rendering */
  101. if (skipCount > 0) {
  102. skipCount--;
  103. return;
  104. }
  105. /* Get id of the program and current position */
  106. switch (progType) {
  107. case ARB_FRAGMENT_PROGRAM:
  108. glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_BINDING_ARB, &id);
  109. glGetIntegerv(GL_FRAGMENT_PROGRAM_POSITION_MESA, &pos);
  110. break;
  111. case NV_FRAGMENT_PROGRAM:
  112. glGetIntegerv(GL_FRAGMENT_PROGRAM_BINDING_NV, &id);
  113. glGetIntegerv(GL_FRAGMENT_PROGRAM_POSITION_MESA, &pos);
  114. break;
  115. case ARB_VERTEX_PROGRAM:
  116. glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_BINDING_ARB, &id);
  117. glGetIntegerv(GL_VERTEX_PROGRAM_POSITION_MESA, &pos);
  118. break;
  119. case NV_VERTEX_PROGRAM:
  120. glGetIntegerv(GL_VERTEX_PROGRAM_BINDING_NV, &id);
  121. glGetIntegerv(GL_VERTEX_PROGRAM_POSITION_MESA, &pos);
  122. break;
  123. default:
  124. abort();
  125. }
  126. /* get program string */
  127. if (progType == ARB_VERTEX_PROGRAM ||
  128. progType == ARB_FRAGMENT_PROGRAM)
  129. glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &len);
  130. else
  131. glGetProgramivNV(id, GL_PROGRAM_LENGTH_NV, &len);
  132. program = malloc(len + 1);
  133. if (progType == ARB_VERTEX_PROGRAM ||
  134. progType == ARB_FRAGMENT_PROGRAM)
  135. glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, program);
  136. else
  137. glGetProgramStringNV(id, GL_PROGRAM_STRING_NV, program);
  138. /* Get current line number, column, line string */
  139. ln = find_line_column(program, program + pos, &line, &column);
  140. /* test breakpoints */
  141. if (NumBreakpoints > 0)
  142. stop = GL_FALSE;
  143. else
  144. stop = GL_TRUE;
  145. for (i = 0; i < NumBreakpoints; i++) {
  146. if (Breakpoints[i].enabled) {
  147. switch (Breakpoints[i].type) {
  148. case PIXEL:
  149. if (progType == ARB_FRAGMENT_PROGRAM) {
  150. }
  151. else if (progType == NV_FRAGMENT_PROGRAM) {
  152. GLfloat pos[4];
  153. int px, py;
  154. glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
  155. 6, (GLubyte *) "f[WPOS]", pos);
  156. px = (int) pos[0];
  157. py = (int) pos[1];
  158. printf("%d, %d\n", px, py);
  159. if (px == Breakpoints[i].x &&
  160. py == Breakpoints[i].y) {
  161. printf("Break at pixel (%d, %d)\n", px, py);
  162. stop = GL_TRUE;
  163. }
  164. }
  165. break;
  166. case LINE:
  167. if (line == Breakpoints[i].line) {
  168. /* hit a breakpoint! */
  169. printf("Break at line %d\n", line);
  170. stop = GL_TRUE;
  171. }
  172. break;
  173. }
  174. }
  175. }
  176. if (!stop) {
  177. free(program);
  178. return;
  179. }
  180. printf("%d: %s\n", line, ln);
  181. /* get commands from stdin */
  182. while (1) {
  183. char command[1000], *cmd;
  184. /* print prompt and get command */
  185. printf("(%s %d) ", (target == GL_VERTEX_PROGRAM_ARB ? "vert" : "frag"),
  186. line);
  187. fgets(command, 999, stdin);
  188. /* skip leading whitespace */
  189. for (cmd = command; cmd[0] == ' '; cmd++)
  190. ;
  191. if (!cmd[0])
  192. /* nothing (repeat the previous cmd?) */
  193. continue;
  194. switch (cmd[0]) {
  195. case 's':
  196. /* skip N instructions */
  197. i = atoi(cmd + 2);
  198. skipCount = i;
  199. printf("Skipping %d instructions\n", i);
  200. return;
  201. case 'n':
  202. /* next */
  203. return;
  204. case 'c':
  205. return;
  206. case 'd':
  207. /* dump machine state */
  208. if (progType == NV_FRAGMENT_PROGRAM) {
  209. static const char *inRegs[] = {
  210. "f[WPOS]", "f[COL0]", "f[COL1]", "f[FOGC]",
  211. "f[TEX0]", "f[TEX1]", "f[TEX2]", "f[TEX3]",
  212. NULL
  213. };
  214. static const char *outRegs[] = {
  215. "o[COLR]", "o[COLH]", "o[DEPR]", NULL
  216. };
  217. GLfloat v[4];
  218. int i;
  219. printf("Fragment input attributes:\n");
  220. for (i = 0; inRegs[i]; i++) {
  221. glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
  222. strlen(inRegs[i]),
  223. (const GLubyte *) inRegs[i], v);
  224. printf(" %s: %g, %g, %g, %g\n", inRegs[i],
  225. v[0], v[1], v[2], v[3]);
  226. }
  227. printf("Fragment output attributes:\n");
  228. for (i = 0; outRegs[i]; i++) {
  229. glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
  230. strlen(outRegs[i]),
  231. (const GLubyte *) outRegs[i], v);
  232. printf(" %s: %g, %g, %g, %g\n", outRegs[i],
  233. v[0], v[1], v[2], v[3]);
  234. }
  235. printf("Temporaries:\n");
  236. for (i = 0; i < 4; i++) {
  237. char temp[100];
  238. GLfloat v[4];
  239. sprintf(temp, "R%d", i);
  240. glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
  241. strlen(temp),
  242. (const GLubyte *) temp, v);
  243. printf(" %s: %g, %g, %g, %g\n", temp, v[0],v[1],v[2],v[3]);
  244. }
  245. }
  246. else if (progType == NV_VERTEX_PROGRAM) {
  247. GLfloat v[4];
  248. int i;
  249. static const char *inRegs[] = {
  250. "v[OPOS]", "v[WGHT]", "v[NRML]", "v[COL0]",
  251. "v[COL1]", "v[FOGC]", "v[6]", "v[7]",
  252. "v[TEX0]", "v[TEX1]", "v[TEX2]", "v[TEX3]",
  253. "v[TEX4]", "v[TEX5]", "v[TEX6]", "v[TEX7]",
  254. NULL
  255. };
  256. static const char *outRegs[] = {
  257. "o[HPOS]", "o[COL0]", "o[COL1]", "o[BFC0]",
  258. "o[BFC1]", "o[FOGC]", "o[PSIZ]",
  259. "o[TEX0]", "o[TEX1]", "o[TEX2]", "o[TEX3]",
  260. "o[TEX4]", "o[TEX5]", "o[TEX6]", "o[TEX7]",
  261. NULL
  262. };
  263. printf("Vertex input attributes:\n");
  264. for (i = 0; inRegs[i]; i++) {
  265. glGetProgramRegisterfvMESA(GL_VERTEX_PROGRAM_NV,
  266. strlen(inRegs[i]),
  267. (const GLubyte *) inRegs[i], v);
  268. printf(" %s: %g, %g, %g, %g\n", inRegs[i],
  269. v[0], v[1], v[2], v[3]);
  270. }
  271. printf("Vertex output attributes:\n");
  272. for (i = 0; outRegs[i]; i++) {
  273. glGetProgramRegisterfvMESA(GL_VERTEX_PROGRAM_NV,
  274. strlen(outRegs[i]),
  275. (const GLubyte *) outRegs[i], v);
  276. printf(" %s: %g, %g, %g, %g\n", outRegs[i],
  277. v[0], v[1], v[2], v[3]);
  278. }
  279. printf("Temporaries:\n");
  280. for (i = 0; i < 4; i++) {
  281. char temp[100];
  282. GLfloat v[4];
  283. sprintf(temp, "R%d", i);
  284. glGetProgramRegisterfvMESA(GL_VERTEX_PROGRAM_NV,
  285. strlen(temp),
  286. (const GLubyte *) temp, v);
  287. printf(" %s: %g, %g, %g, %g\n", temp, v[0],v[1],v[2],v[3]);
  288. }
  289. }
  290. break;
  291. case 'l':
  292. /* list */
  293. list_program(program, len);
  294. break;
  295. case 'p':
  296. /* print */
  297. {
  298. GLfloat v[4];
  299. char *c;
  300. cmd++;
  301. while (*cmd == ' ')
  302. cmd++;
  303. c = cmd;
  304. while (*c) {
  305. if (*c == '\n' || *c == '\r')
  306. *c = 0;
  307. else
  308. c++;
  309. }
  310. glGetProgramRegisterfvMESA(target, strlen(cmd),
  311. (const GLubyte *) cmd, v);
  312. if (glGetError() == GL_NO_ERROR)
  313. printf("%s = %g, %g, %g, %g\n", cmd, v[0], v[1], v[2], v[3]);
  314. else
  315. printf("Invalid expression\n");
  316. }
  317. break;
  318. case 'b':
  319. if (cmd[1] == ' ' && isdigit(cmd[2])) {
  320. char *comma = strchr(cmd, ',');
  321. if (comma) {
  322. /* break at pixel */
  323. int x = atoi(cmd + 2);
  324. int y = atoi(comma + 1);
  325. if (NumBreakpoints < MAX_BREAKPOINTS) {
  326. Breakpoints[NumBreakpoints].type = PIXEL;
  327. Breakpoints[NumBreakpoints].x = x;
  328. Breakpoints[NumBreakpoints].y = y;
  329. Breakpoints[NumBreakpoints].enabled = GL_TRUE;
  330. NumBreakpoints++;
  331. printf("Breakpoint %d: break at pixel (%d, %d)\n",
  332. NumBreakpoints, x, y);
  333. }
  334. }
  335. else {
  336. /* break at line */
  337. int l = atoi(cmd + 2);
  338. if (l && NumBreakpoints < MAX_BREAKPOINTS) {
  339. Breakpoints[NumBreakpoints].type = LINE;
  340. Breakpoints[NumBreakpoints].line = l;
  341. Breakpoints[NumBreakpoints].enabled = GL_TRUE;
  342. NumBreakpoints++;
  343. printf("Breakpoint %d: break at line %d\n",
  344. NumBreakpoints, l);
  345. }
  346. }
  347. }
  348. else {
  349. /* list breakpoints */
  350. printf("Breakpoints:\n");
  351. for (i = 0; i < NumBreakpoints; i++) {
  352. switch (Breakpoints[i].type) {
  353. case LINE:
  354. printf(" %d: break at line %d\n",
  355. i + 1, Breakpoints[i].line);
  356. break;
  357. case PIXEL:
  358. printf(" %d: break at pixel (%d, %d)\n",
  359. i + 1, Breakpoints[i].x, Breakpoints[i].y);
  360. break;
  361. }
  362. }
  363. }
  364. break;
  365. case 'h':
  366. /* help */
  367. printf("Debugger commands:\n");
  368. printf(" b list breakpoints\n");
  369. printf(" b N break at line N\n");
  370. printf(" b x,y break at pixel x,y\n");
  371. printf(" c continue execution\n");
  372. printf(" d display register values\n");
  373. printf(" h help\n");
  374. printf(" l list program\n");
  375. printf(" n next instruction\n");
  376. printf(" p V print value V\n");
  377. printf(" s N skip N instructions\n");
  378. break;
  379. default:
  380. printf("Unknown command: %c\n", cmd[0]);
  381. }
  382. }
  383. }
  384. /*
  385. * Print current line, some registers, and continue.
  386. */
  387. static void Debugger(GLenum target, GLvoid *data)
  388. {
  389. GLint pos;
  390. const GLubyte *ln;
  391. GLint line, column;
  392. GLfloat v[4];
  393. assert(target == GL_FRAGMENT_PROGRAM_NV);
  394. glGetIntegerv(GL_FRAGMENT_PROGRAM_POSITION_MESA, &pos);
  395. ln = find_line_column((const GLubyte *) data, (const GLubyte *) data + pos,
  396. &line, &column);
  397. printf("%d:%d: %s\n", line, column, (char *) ln);
  398. glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
  399. 2, (const GLubyte *) "R0", v);
  400. printf(" R0 = %g, %g, %g, %g\n", v[0], v[1], v[2], v[3]);
  401. glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
  402. 7, (const GLubyte *) "f[WPOS]", v);
  403. printf(" o[WPOS] = %g, %g, %g, %g\n", v[0], v[1], v[2], v[3]);
  404. glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
  405. 7, (const GLubyte *) "o[COLR]", v);
  406. printf(" o[COLR] = %g, %g, %g, %g\n", v[0], v[1], v[2], v[3]);
  407. free((void *) ln);
  408. }
  409. /**********************************************************************/
  410. static GLfloat Diffuse[4] = { 0.5, 0.5, 1.0, 1.0 };
  411. static GLfloat Specular[4] = { 0.8, 0.8, 0.8, 1.0 };
  412. static GLfloat LightPos[4] = { 0.0, 10.0, 20.0, 1.0 };
  413. static GLfloat Delta = 1.0;
  414. static GLuint FragProg;
  415. static GLuint VertProg;
  416. static GLboolean Anim = GL_TRUE;
  417. static GLboolean Wire = GL_FALSE;
  418. static GLboolean PixelLight = GL_TRUE;
  419. static GLfloat Xrot = 0, Yrot = 0;
  420. #define NAMED_PARAMETER4FV(prog, name, v) \
  421. glProgramNamedParameter4fvNV(prog, strlen(name), (const GLubyte *) name, v)
  422. static void Display( void )
  423. {
  424. glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  425. if (PixelLight) {
  426. NAMED_PARAMETER4FV(FragProg, "LightPos", LightPos);
  427. glEnable(GL_FRAGMENT_PROGRAM_NV);
  428. glEnable(GL_VERTEX_PROGRAM_NV);
  429. glDisable(GL_LIGHTING);
  430. }
  431. else {
  432. glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
  433. glDisable(GL_FRAGMENT_PROGRAM_NV);
  434. glDisable(GL_VERTEX_PROGRAM_NV);
  435. glEnable(GL_LIGHTING);
  436. }
  437. glPushMatrix();
  438. glRotatef(Xrot, 1, 0, 0);
  439. glRotatef(Yrot, 0, 1, 0);
  440. #if 1
  441. glutSolidSphere(2.0, 10, 5);
  442. #else
  443. {
  444. GLUquadricObj *q = gluNewQuadric();
  445. gluQuadricNormals(q, GL_SMOOTH);
  446. gluQuadricTexture(q, GL_TRUE);
  447. glRotatef(90, 1, 0, 0);
  448. glTranslatef(0, 0, -1);
  449. gluCylinder(q, 1.0, 1.0, 2.0, 24, 1);
  450. gluDeleteQuadric(q);
  451. }
  452. #endif
  453. glPopMatrix();
  454. glutSwapBuffers();
  455. }
  456. static void Idle(void)
  457. {
  458. LightPos[0] += Delta;
  459. if (LightPos[0] > 25.0)
  460. Delta = -1.0;
  461. else if (LightPos[0] <- 25.0)
  462. Delta = 1.0;
  463. glutPostRedisplay();
  464. }
  465. static void Reshape( int width, int height )
  466. {
  467. glViewport( 0, 0, width, height );
  468. glMatrixMode( GL_PROJECTION );
  469. glLoadIdentity();
  470. glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 );
  471. /*glOrtho( -2.0, 2.0, -2.0, 2.0, 5.0, 25.0 );*/
  472. glMatrixMode( GL_MODELVIEW );
  473. glLoadIdentity();
  474. glTranslatef( 0.0, 0.0, -15.0 );
  475. }
  476. static void Key( unsigned char key, int x, int y )
  477. {
  478. (void) x;
  479. (void) y;
  480. switch (key) {
  481. case ' ':
  482. Anim = !Anim;
  483. if (Anim)
  484. glutIdleFunc(Idle);
  485. else
  486. glutIdleFunc(NULL);
  487. break;
  488. case 'x':
  489. LightPos[0] -= 1.0;
  490. break;
  491. case 'X':
  492. LightPos[0] += 1.0;
  493. break;
  494. case 'w':
  495. Wire = !Wire;
  496. if (Wire)
  497. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  498. else
  499. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  500. break;
  501. case 'p':
  502. PixelLight = !PixelLight;
  503. if (PixelLight) {
  504. printf("Per-pixel lighting\n");
  505. }
  506. else {
  507. printf("Conventional lighting\n");
  508. }
  509. break;
  510. case 27:
  511. exit(0);
  512. break;
  513. }
  514. glutPostRedisplay();
  515. }
  516. static void SpecialKey( int key, int x, int y )
  517. {
  518. const GLfloat step = 3.0;
  519. (void) x;
  520. (void) y;
  521. switch (key) {
  522. case GLUT_KEY_UP:
  523. Xrot -= step;
  524. break;
  525. case GLUT_KEY_DOWN:
  526. Xrot += step;
  527. break;
  528. case GLUT_KEY_LEFT:
  529. Yrot -= step;
  530. break;
  531. case GLUT_KEY_RIGHT:
  532. Yrot += step;
  533. break;
  534. }
  535. glutPostRedisplay();
  536. }
  537. static void Init( int argc, char *argv[] )
  538. {
  539. static const char *fragProgramText =
  540. "!!FP1.0\n"
  541. "DECLARE Diffuse; \n"
  542. "DECLARE Specular; \n"
  543. "DECLARE LightPos; \n"
  544. "# Compute normalized LightPos, put it in R0\n"
  545. "DP3 R0.x, LightPos, LightPos;\n"
  546. "RSQ R0.y, R0.x;\n"
  547. "MUL R0, LightPos, R0.y;\n"
  548. "# Compute normalized normal, put it in R1\n"
  549. "DP3 R1, f[TEX0], f[TEX0]; \n"
  550. "RSQ R1.y, R1.x;\n"
  551. "MUL R1, f[TEX0], R1.y;\n"
  552. "# Compute dot product of light direction and normal vector\n"
  553. "DP3 R2, R0, R1;\n"
  554. "MUL R3, Diffuse, R2; # diffuse attenuation\n"
  555. "POW R4, R2.x, {20.0}.x; # specular exponent\n"
  556. "MUL R5, Specular, R4; # specular attenuation\n"
  557. "ADD o[COLR], R3, R5; # add diffuse and specular colors\n"
  558. "END \n"
  559. ;
  560. static const char *vertProgramText =
  561. "!!VP1.0\n"
  562. "# typical modelview/projection transform\n"
  563. "DP4 o[HPOS].x, c[0], v[OPOS] ;\n"
  564. "DP4 o[HPOS].y, c[1], v[OPOS] ;\n"
  565. "DP4 o[HPOS].z, c[2], v[OPOS] ;\n"
  566. "DP4 o[HPOS].w, c[3], v[OPOS] ;\n"
  567. "# transform normal by inv transpose of modelview, put in tex0\n"
  568. "DP4 o[TEX0].x, c[4], v[NRML] ;\n"
  569. "DP4 o[TEX0].y, c[5], v[NRML] ;\n"
  570. "DP4 o[TEX0].z, c[6], v[NRML] ;\n"
  571. "DP4 o[TEX0].w, c[7], v[NRML] ;\n"
  572. "END\n";
  573. ;
  574. if (!glutExtensionSupported("GL_NV_vertex_program")) {
  575. printf("Sorry, this demo requires GL_NV_vertex_program\n");
  576. exit(1);
  577. }
  578. if (!glutExtensionSupported("GL_NV_fragment_program")) {
  579. printf("Sorry, this demo requires GL_NV_fragment_program\n");
  580. exit(1);
  581. }
  582. glGenProgramsNV(1, &FragProg);
  583. assert(FragProg > 0);
  584. glGenProgramsNV(1, &VertProg);
  585. assert(VertProg > 0);
  586. /*
  587. * Fragment program
  588. */
  589. glLoadProgramNV(GL_FRAGMENT_PROGRAM_NV, FragProg,
  590. strlen(fragProgramText),
  591. (const GLubyte *) fragProgramText);
  592. assert(glIsProgramNV(FragProg));
  593. glBindProgramNV(GL_FRAGMENT_PROGRAM_NV, FragProg);
  594. NAMED_PARAMETER4FV(FragProg, "Diffuse", Diffuse);
  595. NAMED_PARAMETER4FV(FragProg, "Specular", Specular);
  596. /*
  597. * Vertex program
  598. */
  599. glLoadProgramNV(GL_VERTEX_PROGRAM_NV, VertProg,
  600. strlen(vertProgramText),
  601. (const GLubyte *) vertProgramText);
  602. assert(glIsProgramNV(VertProg));
  603. glBindProgramNV(GL_VERTEX_PROGRAM_NV, VertProg);
  604. glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 0, GL_MODELVIEW_PROJECTION_NV, GL_IDENTITY_NV);
  605. glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 4, GL_MODELVIEW, GL_INVERSE_TRANSPOSE_NV);
  606. /*
  607. * Misc init
  608. */
  609. glClearColor(0.3, 0.3, 0.3, 0.0);
  610. glEnable(GL_DEPTH_TEST);
  611. glEnable(GL_LIGHT0);
  612. glEnable(GL_LIGHTING);
  613. glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Diffuse);
  614. glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Specular);
  615. glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.0);
  616. printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
  617. printf("Press p to toggle between per-pixel and per-vertex lighting\n");
  618. #ifdef GL_MESA_program_debug
  619. if (argc > 1 && strcmp(argv[1], "fragment") == 0) {
  620. printf(">> Debugging fragment program\n");
  621. glProgramCallbackMESA(GL_FRAGMENT_PROGRAM_ARB, Debugger2,
  622. (GLvoid *) fragProgramText);
  623. glEnable(GL_FRAGMENT_PROGRAM_CALLBACK_MESA);
  624. }
  625. else {
  626. printf(">> Debugging vertex program\n");
  627. glProgramCallbackMESA(GL_VERTEX_PROGRAM_ARB, Debugger2,
  628. (GLvoid *) fragProgramText);
  629. glEnable(GL_VERTEX_PROGRAM_CALLBACK_MESA);
  630. }
  631. #endif
  632. }
  633. int main( int argc, char *argv[] )
  634. {
  635. glutInit( &argc, argv );
  636. glutInitWindowPosition( 0, 0 );
  637. glutInitWindowSize( 200, 200 );
  638. glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
  639. glutCreateWindow(argv[0]);
  640. glutReshapeFunc( Reshape );
  641. glutKeyboardFunc( Key );
  642. glutSpecialFunc( SpecialKey );
  643. glutDisplayFunc( Display );
  644. if (Anim)
  645. glutIdleFunc(Idle);
  646. Init(argc, argv);
  647. glutMainLoop();
  648. return 0;
  649. }