Clone of mesa.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

corender.c 9.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. /**
  2. * Example of cooperative rendering into one window by two processes.
  3. * The first instance of the program creates the GLX window.
  4. * The second instance of the program gets the window ID from the first
  5. * and draws into it.
  6. * Socket IPC is used for synchronization.
  7. *
  8. * Usage:
  9. * 1. run 'corender &'
  10. * 2. run 'corender 2' (any arg will do)
  11. *
  12. * Brian Paul
  13. * 11 Oct 2007
  14. */
  15. #include <GL/gl.h>
  16. #include <GL/glx.h>
  17. #include <assert.h>
  18. #include <math.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <X11/keysym.h>
  23. #include <unistd.h>
  24. #include "ipc.h"
  25. #ifndef M_PI
  26. #define M_PI 3.14159265358979323846
  27. #endif
  28. static int MyID = 0; /* 0 or 1 */
  29. static int WindowID = 0;
  30. static GLXContext Context = 0;
  31. static int Width = 700, Height = 350;
  32. static int Rot = 0;
  33. static int Sock = 0;
  34. static GLfloat Red[4] = {1.0, 0.2, 0.2, 1.0};
  35. static GLfloat Blue[4] = {0.2, 0.2, 1.0, 1.0};
  36. static int Sync = 1; /** synchronized rendering? */
  37. static void
  38. setup_ipc(void)
  39. {
  40. int k, port = 10001;
  41. if (MyID == 0) {
  42. /* I'm the first one, wait for connection from second */
  43. k = CreatePort(&port);
  44. assert(k != -1);
  45. printf("Waiting for connection from another 'corender'\n");
  46. Sock = AcceptConnection(k);
  47. printf("Got connection, sending windowID\n");
  48. /* send windowID */
  49. SendData(Sock, &WindowID, sizeof(WindowID));
  50. }
  51. else {
  52. /* I'm the second one, connect to first */
  53. char hostname[1000];
  54. MyHostName(hostname, 1000);
  55. Sock = Connect(hostname, port);
  56. assert(Sock != -1);
  57. /* get windowID */
  58. ReceiveData(Sock, &WindowID, sizeof(WindowID));
  59. printf("Contacted first 'corender', getting WindowID\n");
  60. }
  61. }
  62. /** from GLUT */
  63. static void
  64. doughnut(GLfloat r, GLfloat R, GLint nsides, GLint rings)
  65. {
  66. int i, j;
  67. GLfloat theta, phi, theta1;
  68. GLfloat cosTheta, sinTheta;
  69. GLfloat cosTheta1, sinTheta1;
  70. GLfloat ringDelta, sideDelta;
  71. ringDelta = 2.0 * M_PI / rings;
  72. sideDelta = 2.0 * M_PI / nsides;
  73. theta = 0.0;
  74. cosTheta = 1.0;
  75. sinTheta = 0.0;
  76. for (i = rings - 1; i >= 0; i--) {
  77. theta1 = theta + ringDelta;
  78. cosTheta1 = cos(theta1);
  79. sinTheta1 = sin(theta1);
  80. glBegin(GL_QUAD_STRIP);
  81. phi = 0.0;
  82. for (j = nsides; j >= 0; j--) {
  83. GLfloat cosPhi, sinPhi, dist;
  84. phi += sideDelta;
  85. cosPhi = cos(phi);
  86. sinPhi = sin(phi);
  87. dist = R + r * cosPhi;
  88. glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
  89. glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
  90. glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
  91. glVertex3f(cosTheta * dist, -sinTheta * dist, r * sinPhi);
  92. }
  93. glEnd();
  94. theta = theta1;
  95. cosTheta = cosTheta1;
  96. sinTheta = sinTheta1;
  97. }
  98. }
  99. static void
  100. redraw(Display *dpy)
  101. {
  102. int dbg = 0;
  103. glXMakeCurrent(dpy, WindowID, Context);
  104. glEnable(GL_LIGHTING);
  105. glEnable(GL_LIGHT0);
  106. glEnable(GL_DEPTH_TEST);
  107. glClearColor(0.5, 0.5, 0.5, 0.0);
  108. if (MyID == 0) {
  109. /* First process */
  110. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  111. glPushMatrix();
  112. glTranslatef(-1, 0, 0);
  113. glRotatef(Rot, 1, 0, 0);
  114. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Red);
  115. doughnut(0.5, 2.0, 20, 30);
  116. glPopMatrix();
  117. glFinish();
  118. if (!Sync) {
  119. usleep(1000*10);
  120. }
  121. /* signal second process to render */
  122. if (Sync) {
  123. int code = 1;
  124. if (dbg) printf("0: send signal\n");
  125. SendData(Sock, &code, sizeof(code));
  126. SendData(Sock, &Rot, sizeof(Rot));
  127. }
  128. /* wait for second process to finish rendering */
  129. if (Sync) {
  130. int code = 0;
  131. if (dbg) printf("0: wait signal\n");
  132. ReceiveData(Sock, &code, sizeof(code));
  133. if (dbg) printf("0: got signal\n");
  134. assert(code == 2);
  135. }
  136. }
  137. else {
  138. /* Second process */
  139. /* wait for first process's signal for me to render */
  140. if (Sync) {
  141. int code = 0;
  142. if (dbg) printf("1: wait signal\n");
  143. ReceiveData(Sock, &code, sizeof(code));
  144. ReceiveData(Sock, &Rot, sizeof(Rot));
  145. if (dbg) printf("1: got signal\n");
  146. assert(code == 1);
  147. }
  148. /* XXX this clear should not be here, but for some reason, it
  149. * makes things _mostly_ work correctly w/ NVIDIA's driver.
  150. * There's only occasional glitches.
  151. * Without this glClear(), depth buffer for the second process
  152. * is pretty much broken.
  153. */
  154. //glClear(GL_DEPTH_BUFFER_BIT);
  155. glPushMatrix();
  156. glTranslatef(1, 0, 0);
  157. glRotatef(Rot + 90 , 1, 0, 0);
  158. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Blue);
  159. doughnut(0.5, 2.0, 20, 30);
  160. glPopMatrix();
  161. glFinish();
  162. glXSwapBuffers(dpy, WindowID);
  163. usleep(1000*10);
  164. /* signal first process that I'm done rendering */
  165. if (Sync) {
  166. int code = 2;
  167. if (dbg) printf("1: send signal\n");
  168. SendData(Sock, &code, sizeof(code));
  169. }
  170. }
  171. }
  172. static void
  173. resize(Display *dpy, int width, int height)
  174. {
  175. float ar = (float) width / height;
  176. glXMakeCurrent(dpy, WindowID, Context);
  177. glViewport(0, 0, width, height);
  178. glMatrixMode(GL_PROJECTION);
  179. glLoadIdentity();
  180. glFrustum(-ar, ar, 1.0, -1.0, 5.0, 200.0);
  181. glMatrixMode(GL_MODELVIEW);
  182. glLoadIdentity();
  183. glTranslatef(0, 0, -15);
  184. Width = width;
  185. Height = height;
  186. }
  187. static void
  188. set_window_title(Display *dpy, Window win, const char *title)
  189. {
  190. XSizeHints sizehints;
  191. sizehints.flags = 0;
  192. XSetStandardProperties(dpy, win, title, title,
  193. None, (char **)NULL, 0, &sizehints);
  194. }
  195. static Window
  196. make_gl_window(Display *dpy, XVisualInfo *visinfo, int width, int height)
  197. {
  198. int scrnum;
  199. XSetWindowAttributes attr;
  200. unsigned long mask;
  201. Window root;
  202. Window win;
  203. int x = 0, y = 0;
  204. char *name = NULL;
  205. scrnum = DefaultScreen( dpy );
  206. root = RootWindow( dpy, scrnum );
  207. /* window attributes */
  208. attr.background_pixel = 0;
  209. attr.border_pixel = 0;
  210. attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
  211. attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
  212. mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
  213. win = XCreateWindow( dpy, root, x, y, width, height,
  214. 0, visinfo->depth, InputOutput,
  215. visinfo->visual, mask, &attr );
  216. /* set hints and properties */
  217. {
  218. XSizeHints sizehints;
  219. sizehints.x = x;
  220. sizehints.y = y;
  221. sizehints.width = width;
  222. sizehints.height = height;
  223. sizehints.flags = USSize | USPosition;
  224. XSetNormalHints(dpy, win, &sizehints);
  225. XSetStandardProperties(dpy, win, name, name,
  226. None, (char **)NULL, 0, &sizehints);
  227. }
  228. return win;
  229. }
  230. static void
  231. set_event_mask(Display *dpy, Window win)
  232. {
  233. XSetWindowAttributes attr;
  234. attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
  235. XChangeWindowAttributes(dpy, win, CWEventMask, &attr);
  236. }
  237. static void
  238. event_loop(Display *dpy)
  239. {
  240. while (1) {
  241. while (XPending(dpy) > 0) {
  242. XEvent event;
  243. XNextEvent(dpy, &event);
  244. switch (event.type) {
  245. case Expose:
  246. redraw(dpy);
  247. break;
  248. case ConfigureNotify:
  249. resize(dpy, event.xconfigure.width, event.xconfigure.height);
  250. break;
  251. case KeyPress:
  252. {
  253. char buffer[10];
  254. int r, code;
  255. code = XLookupKeysym(&event.xkey, 0);
  256. if (code == XK_Left) {
  257. }
  258. else {
  259. r = XLookupString(&event.xkey, buffer, sizeof(buffer),
  260. NULL, NULL);
  261. if (buffer[0] == 27) {
  262. exit(0);
  263. }
  264. }
  265. }
  266. default:
  267. /* nothing */
  268. ;
  269. }
  270. }
  271. if (MyID == 0 || !Sync)
  272. Rot += 1;
  273. redraw(dpy);
  274. }
  275. }
  276. static XVisualInfo *
  277. choose_visual(Display *dpy)
  278. {
  279. int attribs[] = { GLX_RGBA,
  280. GLX_RED_SIZE, 1,
  281. GLX_GREEN_SIZE, 1,
  282. GLX_BLUE_SIZE, 1,
  283. GLX_DOUBLEBUFFER,
  284. GLX_DEPTH_SIZE, 1,
  285. None };
  286. int scrnum = DefaultScreen( dpy );
  287. return glXChooseVisual(dpy, scrnum, attribs);
  288. }
  289. static void
  290. parse_opts(int argc, char *argv[])
  291. {
  292. if (argc > 1) {
  293. MyID = 1;
  294. }
  295. }
  296. int
  297. main( int argc, char *argv[] )
  298. {
  299. Display *dpy;
  300. XVisualInfo *visinfo;
  301. parse_opts(argc, argv);
  302. dpy = XOpenDisplay(NULL);
  303. visinfo = choose_visual(dpy);
  304. Context = glXCreateContext( dpy, visinfo, NULL, True );
  305. if (!Context) {
  306. printf("Error: glXCreateContext failed\n");
  307. exit(1);
  308. }
  309. if (MyID == 0) {
  310. WindowID = make_gl_window(dpy, visinfo, Width, Height);
  311. set_window_title(dpy, WindowID, "corender");
  312. XMapWindow(dpy, WindowID);
  313. /*printf("WindowID 0x%x\n", (int) WindowID);*/
  314. }
  315. /* do ipc hand-shake here */
  316. setup_ipc();
  317. assert(Sock);
  318. assert(WindowID);
  319. if (MyID == 1) {
  320. set_event_mask(dpy, WindowID);
  321. }
  322. resize(dpy, Width, Height);
  323. event_loop(dpy);
  324. return 0;
  325. }