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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. /*
  2. * Test sharing of display lists and texture objects between GLX contests.
  3. * Brian Paul
  4. * Summer 2000
  5. *
  6. *
  7. * Copyright (C) 2000 Brian Paul All Rights Reserved.
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a
  10. * copy of this software and associated documentation files (the "Software"),
  11. * to deal in the Software without restriction, including without limitation
  12. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13. * and/or sell copies of the Software, and to permit persons to whom the
  14. * Software is furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included
  17. * in all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22. * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23. * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25. *
  26. *
  27. * Modified 2009 for multithreading by Thomas Hellstrom.
  28. *
  29. * Port to windows by Michal Krol.
  30. */
  31. #include <windows.h>
  32. #include <GL/gl.h>
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #pragma comment(lib, "opengl32.lib")
  37. struct thread_init_arg {
  38. int id;
  39. };
  40. struct window {
  41. CRITICAL_SECTION drawMutex;
  42. HDC hDC;
  43. HWND Win;
  44. HGLRC Context;
  45. float Angle;
  46. int Id;
  47. HGLRC sharedContext;
  48. HANDLE hEventInitialised;
  49. };
  50. #define MAX_WINDOWS 20
  51. static struct window Windows[MAX_WINDOWS];
  52. static int NumWindows = 0;
  53. static HANDLE terminate = NULL;
  54. static HGLRC gCtx = NULL;
  55. static HDC gHDC = NULL;
  56. static GLuint Textures[3];
  57. static void
  58. Error(const char *msg)
  59. {
  60. fprintf(stderr, "Error - %s\n", msg);
  61. exit(1);
  62. }
  63. static void
  64. Resize(struct window *h, unsigned int width, unsigned int height);
  65. static LRESULT CALLBACK
  66. WndProc(HWND hWnd,
  67. UINT uMsg,
  68. WPARAM wParam,
  69. LPARAM lParam )
  70. {
  71. switch (uMsg) {
  72. case WM_KEYDOWN:
  73. SetEvent(terminate);
  74. break;
  75. case WM_SIZE:
  76. {
  77. LONG index = GetWindowLong(hWnd, GWL_USERDATA);
  78. if (index >= 0 && index < MAX_WINDOWS) {
  79. RECT r;
  80. GetClientRect(hWnd, &r);
  81. Resize(&Windows[index], r.right, r.bottom);
  82. }
  83. }
  84. break;
  85. case WM_CREATE:
  86. {
  87. CREATESTRUCT *pcs = (CREATESTRUCT *) lParam;
  88. SetWindowLong(hWnd, GWL_USERDATA, (LONG) pcs->lpCreateParams);
  89. }
  90. break;
  91. case WM_DESTROY:
  92. PostQuitMessage(0);
  93. break;
  94. default:
  95. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  96. }
  97. return 0;
  98. }
  99. static int
  100. initMainthread(void)
  101. {
  102. WNDCLASS wc = {0};
  103. HWND win;
  104. PIXELFORMATDESCRIPTOR pfd = {0};
  105. int visinfo;
  106. wc.lpfnWndProc = WndProc;
  107. wc.lpszClassName = "sharedtex_mt.hidden";
  108. wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  109. RegisterClass(&wc);
  110. win = CreateWindowEx(0,
  111. wc.lpszClassName,
  112. "sharedtex_mt.hidden",
  113. WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
  114. CW_USEDEFAULT,
  115. CW_USEDEFAULT,
  116. CW_USEDEFAULT,
  117. CW_USEDEFAULT,
  118. NULL,
  119. NULL,
  120. wc.hInstance,
  121. (LPVOID) -1);
  122. if (!win) {
  123. Error("Couldn't create window");
  124. }
  125. gHDC = GetDC(win);
  126. if (!gHDC) {
  127. Error("Couldn't obtain HDC");
  128. }
  129. pfd.cColorBits = 24;
  130. pfd.cDepthBits = 24;
  131. pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
  132. pfd.iLayerType = PFD_MAIN_PLANE;
  133. pfd.iPixelType = PFD_TYPE_RGBA;
  134. pfd.nSize = sizeof(pfd);
  135. pfd.nVersion = 1;
  136. visinfo = ChoosePixelFormat(gHDC, &pfd);
  137. if (!visinfo) {
  138. Error("Unable to find RGB, Z, double-buffered visual");
  139. }
  140. SetPixelFormat(gHDC, visinfo, &pfd);
  141. gCtx = wglCreateContext(gHDC);
  142. if (!gCtx) {
  143. Error("Couldn't create WGL context");
  144. }
  145. return 0;
  146. }
  147. static struct window *
  148. AddWindow(int xpos, int ypos, HGLRC sCtx)
  149. {
  150. struct window *win = &Windows[NumWindows];
  151. WNDCLASS wc = {0};
  152. int width = 300, height = 300;
  153. if (NumWindows >= MAX_WINDOWS)
  154. return NULL;
  155. memset(win, 0, sizeof(*win));
  156. InitializeCriticalSection(&win->drawMutex);
  157. win->Angle = 0.0;
  158. win->Id = NumWindows++;
  159. wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
  160. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  161. wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  162. wc.lpfnWndProc = WndProc;
  163. wc.lpszClassName = "sharedtex_mt";
  164. wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  165. RegisterClass(&wc);
  166. win->Win = CreateWindowEx(0,
  167. wc.lpszClassName,
  168. "sharedtex_mt",
  169. WS_SIZEBOX | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
  170. xpos,
  171. ypos,
  172. width,
  173. height,
  174. NULL,
  175. NULL,
  176. wc.hInstance,
  177. (LPVOID) win->Id);
  178. if (!win->Win) {
  179. Error("Couldn't create window");
  180. }
  181. win->sharedContext = sCtx;
  182. ShowWindow(win->Win, SW_SHOW);
  183. return win;
  184. }
  185. static void
  186. InitGLstuff(void)
  187. {
  188. glGenTextures(3, Textures);
  189. /* setup first texture object */
  190. {
  191. GLubyte image[16][16][4];
  192. GLint i, j;
  193. glBindTexture(GL_TEXTURE_2D, Textures[0]);
  194. /* red/white checkerboard */
  195. for (i = 0; i < 16; i++) {
  196. for (j = 0; j < 16; j++) {
  197. if ((i ^ j) & 1) {
  198. image[i][j][0] = 255;
  199. image[i][j][1] = 255;
  200. image[i][j][2] = 255;
  201. image[i][j][3] = 255;
  202. }
  203. else {
  204. image[i][j][0] = 255;
  205. image[i][j][1] = 0;
  206. image[i][j][2] = 0;
  207. image[i][j][3] = 255;
  208. }
  209. }
  210. }
  211. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  212. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
  213. GL_UNSIGNED_BYTE, image);
  214. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  215. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  216. }
  217. /* setup second texture object */
  218. {
  219. GLubyte image[8][8][3];
  220. GLint i, j;
  221. glBindTexture(GL_TEXTURE_2D, Textures[1]);
  222. /* green/yellow checkerboard */
  223. for (i = 0; i < 8; i++) {
  224. for (j = 0; j < 8; j++) {
  225. if ((i ^ j) & 1) {
  226. image[i][j][0] = 0;
  227. image[i][j][1] = 255;
  228. image[i][j][2] = 0;
  229. }
  230. else {
  231. image[i][j][0] = 255;
  232. image[i][j][1] = 255;
  233. image[i][j][2] = 0;
  234. }
  235. }
  236. }
  237. glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
  238. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB,
  239. GL_UNSIGNED_BYTE, image);
  240. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  241. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  242. }
  243. /* setup second texture object */
  244. {
  245. GLubyte image[4][4][3];
  246. GLint i, j;
  247. glBindTexture(GL_TEXTURE_2D, Textures[2]);
  248. /* blue/gray checkerboard */
  249. for (i = 0; i < 4; i++) {
  250. for (j = 0; j < 4; j++) {
  251. if ((i ^ j) & 1) {
  252. image[i][j][0] = 0;
  253. image[i][j][1] = 0;
  254. image[i][j][2] = 255;
  255. }
  256. else {
  257. image[i][j][0] = 200;
  258. image[i][j][1] = 200;
  259. image[i][j][2] = 200;
  260. }
  261. }
  262. }
  263. glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
  264. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 4, 4, 0, GL_RGB,
  265. GL_UNSIGNED_BYTE, image);
  266. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  267. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  268. }
  269. /* Now make the cube object display list */
  270. printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
  271. printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION));
  272. printf("GL_VENDOR: %s\n", (char *) glGetString(GL_VENDOR));
  273. }
  274. static void
  275. Redraw(struct window *h)
  276. {
  277. EnterCriticalSection(&h->drawMutex);
  278. if (!wglMakeCurrent(h->hDC, h->Context)) {
  279. LeaveCriticalSection(&h->drawMutex);
  280. Error("wglMakeCurrent failed in Redraw");
  281. return;
  282. }
  283. h->Angle += 1.0;
  284. glShadeModel(GL_FLAT);
  285. glClearColor(0.25, 0.25, 0.25, 1.0);
  286. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  287. glEnable(GL_TEXTURE_2D);
  288. glEnable(GL_DEPTH_TEST);
  289. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  290. glColor3f(1, 1, 1);
  291. glPushMatrix();
  292. if (h->Id == 0)
  293. glRotatef(h->Angle, 0, 1, -1);
  294. else if (h->Id == 1)
  295. glRotatef(-(h->Angle), 0, 1, -1);
  296. else if (h->Id == 2)
  297. glRotatef(h->Angle, 0, 1, 1);
  298. else if (h->Id == 3)
  299. glRotatef(-(h->Angle), 0, 1, 1);
  300. glBindTexture(GL_TEXTURE_2D, Textures[0]);
  301. glBegin(GL_POLYGON);
  302. glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
  303. glTexCoord2f(1, 0); glVertex3f(-1, 1, -1);
  304. glTexCoord2f(1, 1); glVertex3f(-1, 1, 1);
  305. glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
  306. glEnd();
  307. glBegin(GL_POLYGON);
  308. glTexCoord2f(0, 0); glVertex3f(1, -1, -1);
  309. glTexCoord2f(1, 0); glVertex3f(1, 1, -1);
  310. glTexCoord2f(1, 1); glVertex3f(1, 1, 1);
  311. glTexCoord2f(0, 1); glVertex3f(1, -1, 1);
  312. glEnd();
  313. glBindTexture(GL_TEXTURE_2D, Textures[1]);
  314. glBegin(GL_POLYGON);
  315. glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
  316. glTexCoord2f(1, 0); glVertex3f( 1, -1, -1);
  317. glTexCoord2f(1, 1); glVertex3f( 1, -1, 1);
  318. glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
  319. glEnd();
  320. glBegin(GL_POLYGON);
  321. glTexCoord2f(0, 0); glVertex3f(-1, 1, -1);
  322. glTexCoord2f(1, 0); glVertex3f( 1, 1, -1);
  323. glTexCoord2f(1, 1); glVertex3f( 1, 1, 1);
  324. glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
  325. glEnd();
  326. glBindTexture(GL_TEXTURE_2D, Textures[2]);
  327. glBegin(GL_POLYGON);
  328. glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
  329. glTexCoord2f(1, 0); glVertex3f( 1, -1, -1);
  330. glTexCoord2f(1, 1); glVertex3f( 1, 1, -1);
  331. glTexCoord2f(0, 1); glVertex3f(-1, 1, -1);
  332. glEnd();
  333. glBegin(GL_POLYGON);
  334. glTexCoord2f(0, 0); glVertex3f(-1, -1, 1);
  335. glTexCoord2f(1, 0); glVertex3f( 1, -1, 1);
  336. glTexCoord2f(1, 1); glVertex3f( 1, 1, 1);
  337. glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
  338. glEnd();
  339. glPopMatrix();
  340. SwapBuffers(h->hDC);
  341. if (!wglMakeCurrent(NULL, NULL)) {
  342. Error("wglMakeCurrent failed in Redraw");
  343. }
  344. LeaveCriticalSection(&h->drawMutex);
  345. }
  346. static DWORD WINAPI
  347. threadRunner (void *arg)
  348. {
  349. struct thread_init_arg *tia = (struct thread_init_arg *) arg;
  350. struct window *win;
  351. PIXELFORMATDESCRIPTOR pfd = {0};
  352. int visinfo;
  353. win = &Windows[tia->id];
  354. win->hDC = GetDC(win->Win);
  355. if (!win->hDC) {
  356. Error("Couldn't obtain HDC");
  357. }
  358. /* Wait for the previous thread */
  359. if(tia->id > 0)
  360. WaitForSingleObject(Windows[tia->id - 1].hEventInitialised, INFINITE);
  361. pfd.cColorBits = 24;
  362. pfd.cDepthBits = 24;
  363. pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
  364. pfd.iLayerType = PFD_MAIN_PLANE;
  365. pfd.iPixelType = PFD_TYPE_RGBA;
  366. pfd.nSize = sizeof(pfd);
  367. pfd.nVersion = 1;
  368. visinfo = ChoosePixelFormat(win->hDC, &pfd);
  369. if (!visinfo) {
  370. Error("Unable to find RGB, Z, double-buffered visual");
  371. }
  372. SetPixelFormat(win->hDC, visinfo, &pfd);
  373. win->Context = wglCreateContext(win->hDC);
  374. if (!win->Context) {
  375. Error("Couldn't create WGL context");
  376. }
  377. if (win->sharedContext) {
  378. if(!wglShareLists(win->sharedContext, win->Context))
  379. Error("Couldn't share WGL context lists");
  380. }
  381. SetEvent(win->hEventInitialised);
  382. /* Wait for all threads to initialize otherwise wglShareLists will fail */
  383. if(tia->id < NumWindows - 1)
  384. WaitForSingleObject(Windows[NumWindows - 1].hEventInitialised, INFINITE);
  385. SendMessage(win->Win, WM_SIZE, 0, 0);
  386. while (1) {
  387. MSG msg;
  388. /* wait 1 ms for signal either to exit or process messages */
  389. switch (MsgWaitForMultipleObjects(1, &terminate, FALSE, 1, QS_ALLINPUT)) {
  390. case WAIT_OBJECT_0:
  391. SendMessage(win->Win, WM_CLOSE, 0, 0);
  392. break;
  393. case WAIT_OBJECT_0 + 1:
  394. break;
  395. }
  396. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  397. if (msg.message == WM_QUIT) {
  398. return 0;
  399. }
  400. TranslateMessage(&msg);
  401. DispatchMessage(&msg);
  402. }
  403. Redraw(win);
  404. }
  405. return 0;
  406. }
  407. static void
  408. Resize(struct window *h, unsigned int width, unsigned int height)
  409. {
  410. if (!h->Context)
  411. return;
  412. EnterCriticalSection(&h->drawMutex);
  413. if (!wglMakeCurrent(h->hDC, h->Context)) {
  414. LeaveCriticalSection(&h->drawMutex);
  415. Error("wglMakeCurrent failed in Resize()");
  416. return;
  417. }
  418. glViewport(0, 0, width, height);
  419. glMatrixMode(GL_PROJECTION);
  420. glLoadIdentity();
  421. glFrustum(-1, 1, -1, 1, 2, 10);
  422. glMatrixMode(GL_MODELVIEW);
  423. glLoadIdentity();
  424. glTranslatef(0, 0, -4.5);
  425. if (!wglMakeCurrent(NULL, NULL)) {
  426. Error("wglMakeCurrent failed in Resize()");
  427. }
  428. LeaveCriticalSection(&h->drawMutex);
  429. }
  430. int
  431. main(int argc, char *argv[])
  432. {
  433. struct thread_init_arg tia[MAX_WINDOWS];
  434. struct window *h[MAX_WINDOWS];
  435. HANDLE threads[MAX_WINDOWS];
  436. int i;
  437. terminate = CreateEvent(NULL, TRUE, FALSE, NULL);
  438. if (initMainthread())
  439. return -1;
  440. /* four windows and contexts sharing display lists and texture objects */
  441. h[0] = AddWindow( 10, 10, gCtx);
  442. h[1] = AddWindow(330, 10, gCtx);
  443. h[2] = AddWindow( 10, 350, gCtx);
  444. h[3] = AddWindow(330, 350, gCtx);
  445. for (i = 0; i < NumWindows; i++) {
  446. Windows[i].hEventInitialised = CreateEvent(NULL, TRUE, FALSE, NULL);
  447. }
  448. for (i = 0; i < NumWindows; i++) {
  449. DWORD id;
  450. tia[i].id = i;
  451. threads[i] = CreateThread(NULL, 0, threadRunner, &tia[i], 0, &id);
  452. WaitForSingleObject(Windows[i].hEventInitialised, INFINITE);
  453. }
  454. if (!wglMakeCurrent(gHDC, gCtx)) {
  455. Error("wglMakeCurrent failed for init thread.");
  456. return -1;
  457. }
  458. InitGLstuff();
  459. while (1) {
  460. MSG msg;
  461. /* wait 1 ms for signal either to exit or process messages */
  462. switch (MsgWaitForMultipleObjects(NumWindows, threads, TRUE, 1, QS_ALLINPUT)) {
  463. case WAIT_OBJECT_0:
  464. return 0;
  465. }
  466. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  467. if (msg.message == WM_QUIT) {
  468. return 0;
  469. }
  470. TranslateMessage(&msg);
  471. DispatchMessage(&msg);
  472. }
  473. }
  474. return 0;
  475. }