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

sharedtex_mt.c 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. /* $Id: sharedtex.c,v 1.2 2002/01/16 14:32:46 joukj Exp $ */
  2. /*
  3. * Test sharing of display lists and texture objects between GLX contests.
  4. * Brian Paul
  5. * Summer 2000
  6. *
  7. *
  8. * Copyright (C) 2000 Brian Paul All Rights Reserved.
  9. *
  10. * Permission is hereby granted, free of charge, to any person obtaining a
  11. * copy of this software and associated documentation files (the "Software"),
  12. * to deal in the Software without restriction, including without limitation
  13. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  14. * and/or sell copies of the Software, and to permit persons to whom the
  15. * Software is furnished to do so, subject to the following conditions:
  16. *
  17. * The above copyright notice and this permission notice shall be included
  18. * in all copies or substantial portions of the Software.
  19. *
  20. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  21. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  23. * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  24. * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  25. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26. *
  27. *
  28. * Modified 2009 for multithreading by Thomas Hellstrom.
  29. */
  30. #include <GL/gl.h>
  31. #include <GL/glx.h>
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <unistd.h>
  35. #include <string.h>
  36. #include <pthread.h>
  37. #include <X11/X.h>
  38. struct thread_init_arg {
  39. int id;
  40. };
  41. struct window {
  42. pthread_mutex_t drawMutex;
  43. char DisplayName[1000];
  44. Display *Dpy;
  45. Window Win;
  46. GLXContext Context;
  47. float Angle;
  48. int Id;
  49. XVisualInfo *visInfo;
  50. };
  51. #define MAX_WINDOWS 20
  52. static struct window Windows[MAX_WINDOWS];
  53. static int NumWindows = 0;
  54. static int terminate = 0;
  55. static GLXContext gCtx;
  56. static Display *gDpy;
  57. static GLuint Textures[3];
  58. static void
  59. Error(const char *display, const char *msg)
  60. {
  61. fprintf(stderr, "Error on display %s - %s\n", display, msg);
  62. exit(1);
  63. }
  64. static int
  65. initMainthread(Display *dpy, const char *displayName)
  66. {
  67. int scrnum;
  68. XVisualInfo *visinfo;
  69. int attrib[] = { GLX_RGBA,
  70. GLX_RED_SIZE, 1,
  71. GLX_GREEN_SIZE, 1,
  72. GLX_BLUE_SIZE, 1,
  73. GLX_DOUBLEBUFFER,
  74. GLX_DEPTH_SIZE, 1,
  75. None };
  76. scrnum = DefaultScreen(dpy);
  77. visinfo = glXChooseVisual(dpy, scrnum, attrib);
  78. if (!visinfo) {
  79. Error(displayName, "Unable to find RGB, double-buffered visual");
  80. return -1;
  81. }
  82. gCtx = glXCreateContext(dpy, visinfo, NULL, True);
  83. if (!gCtx) {
  84. Error(displayName, "Couldn't create GLX context");
  85. return -1;
  86. }
  87. return 0;
  88. }
  89. static struct window *
  90. AddWindow(Display *dpy, const char *displayName, int xpos, int ypos,
  91. GLXContext sCtx)
  92. {
  93. Window win;
  94. GLXContext ctx;
  95. int attrib[] = { GLX_RGBA,
  96. GLX_RED_SIZE, 1,
  97. GLX_GREEN_SIZE, 1,
  98. GLX_BLUE_SIZE, 1,
  99. GLX_DOUBLEBUFFER,
  100. GLX_DEPTH_SIZE, 1,
  101. None };
  102. int scrnum;
  103. XSetWindowAttributes attr;
  104. unsigned long mask;
  105. Window root;
  106. XVisualInfo *visinfo;
  107. int width = 300, height = 300;
  108. if (NumWindows >= MAX_WINDOWS)
  109. return NULL;
  110. scrnum = DefaultScreen(dpy);
  111. root = RootWindow(dpy, scrnum);
  112. visinfo = glXChooseVisual(dpy, scrnum, attrib);
  113. if (!visinfo) {
  114. Error(displayName, "Unable to find RGB, double-buffered visual");
  115. return NULL;
  116. }
  117. /* window attributes */
  118. attr.background_pixel = 0;
  119. attr.border_pixel = 0;
  120. attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
  121. attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
  122. mask = CWBorderPixel | CWColormap | CWEventMask;
  123. win = XCreateWindow(dpy, root, xpos, ypos, width, height,
  124. 0, visinfo->depth, InputOutput,
  125. visinfo->visual, mask, &attr);
  126. if (!win) {
  127. Error(displayName, "Couldn't create window");
  128. return NULL;
  129. }
  130. {
  131. XSizeHints sizehints;
  132. sizehints.x = xpos;
  133. sizehints.y = ypos;
  134. sizehints.width = width;
  135. sizehints.height = height;
  136. sizehints.flags = USSize | USPosition;
  137. XSetNormalHints(dpy, win, &sizehints);
  138. XSetStandardProperties(dpy, win, displayName, displayName,
  139. None, (char **)NULL, 0, &sizehints);
  140. }
  141. ctx = glXCreateContext(dpy, visinfo,
  142. sCtx ? sCtx : NULL, True);
  143. if (!ctx) {
  144. Error(displayName, "Couldn't create GLX context");
  145. return NULL;
  146. }
  147. XMapWindow(dpy, win);
  148. /* save the info for this window */
  149. {
  150. static int id = 0;
  151. struct window *h = &Windows[NumWindows];
  152. if (strlen(displayName) + 1 > sizeof(h->DisplayName)) {
  153. Error(displayName, "string overflow");
  154. return NULL;
  155. }
  156. strcpy(h->DisplayName, displayName);
  157. h->Dpy = dpy;
  158. h->Win = win;
  159. h->Context = ctx;
  160. h->Angle = 0.0;
  161. h->Id = id++;
  162. h->visInfo = visinfo;
  163. pthread_mutex_init(&h->drawMutex, NULL);
  164. NumWindows++;
  165. return &Windows[NumWindows-1];
  166. }
  167. }
  168. static void
  169. InitGLstuff(void)
  170. {
  171. glGenTextures(3, Textures);
  172. /* setup first texture object */
  173. {
  174. GLubyte image[16][16][4];
  175. GLint i, j;
  176. glBindTexture(GL_TEXTURE_2D, Textures[0]);
  177. /* red/white checkerboard */
  178. for (i = 0; i < 16; i++) {
  179. for (j = 0; j < 16; j++) {
  180. if ((i ^ j) & 1) {
  181. image[i][j][0] = 255;
  182. image[i][j][1] = 255;
  183. image[i][j][2] = 255;
  184. image[i][j][3] = 255;
  185. }
  186. else {
  187. image[i][j][0] = 255;
  188. image[i][j][1] = 0;
  189. image[i][j][2] = 0;
  190. image[i][j][3] = 255;
  191. }
  192. }
  193. }
  194. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  195. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
  196. GL_UNSIGNED_BYTE, image);
  197. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  198. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  199. }
  200. /* setup second texture object */
  201. {
  202. GLubyte image[8][8][3];
  203. GLint i, j;
  204. glBindTexture(GL_TEXTURE_2D, Textures[1]);
  205. /* green/yellow checkerboard */
  206. for (i = 0; i < 8; i++) {
  207. for (j = 0; j < 8; j++) {
  208. if ((i ^ j) & 1) {
  209. image[i][j][0] = 0;
  210. image[i][j][1] = 255;
  211. image[i][j][2] = 0;
  212. }
  213. else {
  214. image[i][j][0] = 255;
  215. image[i][j][1] = 255;
  216. image[i][j][2] = 0;
  217. }
  218. }
  219. }
  220. glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
  221. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB,
  222. GL_UNSIGNED_BYTE, image);
  223. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  224. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  225. }
  226. /* setup second texture object */
  227. {
  228. GLubyte image[4][4][3];
  229. GLint i, j;
  230. glBindTexture(GL_TEXTURE_2D, Textures[2]);
  231. /* blue/gray checkerboard */
  232. for (i = 0; i < 4; i++) {
  233. for (j = 0; j < 4; j++) {
  234. if ((i ^ j) & 1) {
  235. image[i][j][0] = 0;
  236. image[i][j][1] = 0;
  237. image[i][j][2] = 255;
  238. }
  239. else {
  240. image[i][j][0] = 200;
  241. image[i][j][1] = 200;
  242. image[i][j][2] = 200;
  243. }
  244. }
  245. }
  246. glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
  247. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 4, 4, 0, GL_RGB,
  248. GL_UNSIGNED_BYTE, image);
  249. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  250. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  251. }
  252. /* Now make the cube object display list */
  253. printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
  254. printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION));
  255. printf("GL_VENDOR: %s\n", (char *) glGetString(GL_VENDOR));
  256. }
  257. static void
  258. Redraw(struct window *h)
  259. {
  260. pthread_mutex_lock(&h->drawMutex);
  261. if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
  262. Error(h->DisplayName, "glXMakeCurrent failed in Redraw");
  263. pthread_mutex_unlock(&h->drawMutex);
  264. return;
  265. }
  266. h->Angle += 1.0;
  267. glShadeModel(GL_FLAT);
  268. glClearColor(0.25, 0.25, 0.25, 1.0);
  269. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  270. glEnable(GL_TEXTURE_2D);
  271. glEnable(GL_DEPTH_TEST);
  272. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  273. glColor3f(1, 1, 1);
  274. glPushMatrix();
  275. if (h->Id == 0)
  276. glRotatef(h->Angle, 0, 1, -1);
  277. else if (h->Id == 1)
  278. glRotatef(-(h->Angle), 0, 1, -1);
  279. else if (h->Id == 2)
  280. glRotatef(h->Angle, 0, 1, 1);
  281. else if (h->Id == 3)
  282. glRotatef(-(h->Angle), 0, 1, 1);
  283. glBindTexture(GL_TEXTURE_2D, Textures[0]);
  284. glBegin(GL_POLYGON);
  285. glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
  286. glTexCoord2f(1, 0); glVertex3f(-1, 1, -1);
  287. glTexCoord2f(1, 1); glVertex3f(-1, 1, 1);
  288. glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
  289. glEnd();
  290. glBegin(GL_POLYGON);
  291. glTexCoord2f(0, 0); glVertex3f(1, -1, -1);
  292. glTexCoord2f(1, 0); glVertex3f(1, 1, -1);
  293. glTexCoord2f(1, 1); glVertex3f(1, 1, 1);
  294. glTexCoord2f(0, 1); glVertex3f(1, -1, 1);
  295. glEnd();
  296. glBindTexture(GL_TEXTURE_2D, Textures[1]);
  297. glBegin(GL_POLYGON);
  298. glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
  299. glTexCoord2f(1, 0); glVertex3f( 1, -1, -1);
  300. glTexCoord2f(1, 1); glVertex3f( 1, -1, 1);
  301. glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
  302. glEnd();
  303. glBegin(GL_POLYGON);
  304. glTexCoord2f(0, 0); glVertex3f(-1, 1, -1);
  305. glTexCoord2f(1, 0); glVertex3f( 1, 1, -1);
  306. glTexCoord2f(1, 1); glVertex3f( 1, 1, 1);
  307. glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
  308. glEnd();
  309. glBindTexture(GL_TEXTURE_2D, Textures[2]);
  310. glBegin(GL_POLYGON);
  311. glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
  312. glTexCoord2f(1, 0); glVertex3f( 1, -1, -1);
  313. glTexCoord2f(1, 1); glVertex3f( 1, 1, -1);
  314. glTexCoord2f(0, 1); glVertex3f(-1, 1, -1);
  315. glEnd();
  316. glBegin(GL_POLYGON);
  317. glTexCoord2f(0, 0); glVertex3f(-1, -1, 1);
  318. glTexCoord2f(1, 0); glVertex3f( 1, -1, 1);
  319. glTexCoord2f(1, 1); glVertex3f( 1, 1, 1);
  320. glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
  321. glEnd();
  322. glPopMatrix();
  323. glXSwapBuffers(h->Dpy, h->Win);
  324. if (!glXMakeCurrent(h->Dpy, None, NULL)) {
  325. Error(h->DisplayName, "glXMakeCurrent failed in Redraw");
  326. }
  327. pthread_mutex_unlock(&h->drawMutex);
  328. }
  329. static void *threadRunner (void *arg)
  330. {
  331. struct thread_init_arg *tia = (struct thread_init_arg *) arg;
  332. struct window *win;
  333. win = &Windows[tia->id];
  334. while(!terminate) {
  335. usleep(1000);
  336. Redraw(win);
  337. }
  338. return NULL;
  339. }
  340. static void
  341. Resize(struct window *h, unsigned int width, unsigned int height)
  342. {
  343. pthread_mutex_lock(&h->drawMutex);
  344. if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
  345. Error(h->DisplayName, "glXMakeCurrent failed in Resize()");
  346. pthread_mutex_unlock(&h->drawMutex);
  347. return;
  348. }
  349. glViewport(0, 0, width, height);
  350. glMatrixMode(GL_PROJECTION);
  351. glLoadIdentity();
  352. glFrustum(-1, 1, -1, 1, 2, 10);
  353. glMatrixMode(GL_MODELVIEW);
  354. glLoadIdentity();
  355. glTranslatef(0, 0, -4.5);
  356. if (!glXMakeCurrent(h->Dpy, None, NULL)) {
  357. Error(h->DisplayName, "glXMakeCurrent failed in Resize()");
  358. }
  359. pthread_mutex_unlock(&h->drawMutex);
  360. }
  361. static void
  362. EventLoop(void)
  363. {
  364. while (1) {
  365. int i;
  366. XEvent event;
  367. XNextEvent(gDpy, &event);
  368. for (i = 0; i < NumWindows; i++) {
  369. struct window *h = &Windows[i];
  370. if (event.xany.window == h->Win) {
  371. switch (event.type) {
  372. case Expose:
  373. Redraw(h);
  374. break;
  375. case ConfigureNotify:
  376. Resize(h, event.xconfigure.width, event.xconfigure.height);
  377. break;
  378. case KeyPress:
  379. terminate = 1;
  380. return;
  381. default:
  382. /*no-op*/ ;
  383. }
  384. }
  385. }
  386. }
  387. }
  388. int
  389. main(int argc, char *argv[])
  390. {
  391. const char *dpyName = XDisplayName(NULL);
  392. pthread_t t0, t1, t2, t3;
  393. struct thread_init_arg tia0, tia1, tia2, tia3;
  394. struct window *h0;
  395. XInitThreads();
  396. gDpy = XOpenDisplay(dpyName);
  397. if (!gDpy) {
  398. Error(dpyName, "Unable to open display");
  399. return -1;
  400. }
  401. if (initMainthread(gDpy, dpyName))
  402. return -1;
  403. /* four windows and contexts sharing display lists and texture objects */
  404. h0 = AddWindow(gDpy, dpyName, 10, 10, gCtx);
  405. (void) AddWindow(gDpy, dpyName, 330, 10, gCtx);
  406. (void) AddWindow(gDpy, dpyName, 10, 350, gCtx);
  407. (void) AddWindow(gDpy, dpyName, 330, 350, gCtx);
  408. if (!glXMakeCurrent(gDpy, h0->Win, gCtx)) {
  409. Error(dpyName, "glXMakeCurrent failed for init thread.");
  410. return -1;
  411. }
  412. InitGLstuff();
  413. tia0.id = 0;
  414. pthread_create(&t0, NULL, threadRunner, &tia0);
  415. tia1.id = 1;
  416. pthread_create(&t1, NULL, threadRunner, &tia1);
  417. tia2.id = 2;
  418. pthread_create(&t2, NULL, threadRunner, &tia2);
  419. tia3.id = 3;
  420. pthread_create(&t3, NULL, threadRunner, &tia3);
  421. EventLoop();
  422. return 0;
  423. }