• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //========================================================================
2 // Multi-threading test
3 // Copyright (c) Camilla Berglund <elmindreda@glfw.org>
4 //
5 // This software is provided 'as-is', without any express or implied
6 // warranty. In no event will the authors be held liable for any damages
7 // arising from the use of this software.
8 //
9 // Permission is granted to anyone to use this software for any purpose,
10 // including commercial applications, and to alter it and redistribute it
11 // freely, subject to the following restrictions:
12 //
13 // 1. The origin of this software must not be misrepresented; you must not
14 //    claim that you wrote the original software. If you use this software
15 //    in a product, an acknowledgment in the product documentation would
16 //    be appreciated but is not required.
17 //
18 // 2. Altered source versions must be plainly marked as such, and must not
19 //    be misrepresented as being the original software.
20 //
21 // 3. This notice may not be removed or altered from any source
22 //    distribution.
23 //
24 //========================================================================
25 //
26 // This test is intended to verify whether the OpenGL context part of
27 // the GLFW API is able to be used from multiple threads
28 //
29 //========================================================================
30 
31 #include "tinycthread.h"
32 
33 #include <glad/glad.h>
34 #include <GLFW/glfw3.h>
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <math.h>
39 
40 typedef struct
41 {
42     GLFWwindow* window;
43     const char* title;
44     float r, g, b;
45     thrd_t id;
46 } Thread;
47 
48 static volatile int running = GLFW_TRUE;
49 
error_callback(int error,const char * description)50 static void error_callback(int error, const char* description)
51 {
52     fprintf(stderr, "Error: %s\n", description);
53 }
54 
thread_main(void * data)55 static int thread_main(void* data)
56 {
57     const Thread* thread = data;
58 
59     glfwMakeContextCurrent(thread->window);
60     glfwSwapInterval(1);
61 
62     while (running)
63     {
64         const float v = (float) fabs(sin(glfwGetTime() * 2.f));
65         glClearColor(thread->r * v, thread->g * v, thread->b * v, 0.f);
66 
67         glClear(GL_COLOR_BUFFER_BIT);
68         glfwSwapBuffers(thread->window);
69     }
70 
71     glfwMakeContextCurrent(NULL);
72     return 0;
73 }
74 
main(void)75 int main(void)
76 {
77     int i, result;
78     Thread threads[] =
79     {
80         { NULL, "Red", 1.f, 0.f, 0.f, 0 },
81         { NULL, "Green", 0.f, 1.f, 0.f, 0 },
82         { NULL, "Blue", 0.f, 0.f, 1.f, 0 }
83     };
84     const int count = sizeof(threads) / sizeof(Thread);
85 
86     glfwSetErrorCallback(error_callback);
87 
88     if (!glfwInit())
89         exit(EXIT_FAILURE);
90 
91     glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
92 
93     for (i = 0;  i < count;  i++)
94     {
95         threads[i].window = glfwCreateWindow(200, 200,
96                                              threads[i].title,
97                                              NULL, NULL);
98         if (!threads[i].window)
99         {
100             glfwTerminate();
101             exit(EXIT_FAILURE);
102         }
103 
104         glfwSetWindowPos(threads[i].window, 200 + 250 * i, 200);
105         glfwShowWindow(threads[i].window);
106     }
107 
108     glfwMakeContextCurrent(threads[0].window);
109     gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
110     glfwMakeContextCurrent(NULL);
111 
112     for (i = 0;  i < count;  i++)
113     {
114         if (thrd_create(&threads[i].id, thread_main, threads + i) !=
115             thrd_success)
116         {
117             fprintf(stderr, "Failed to create secondary thread\n");
118 
119             glfwTerminate();
120             exit(EXIT_FAILURE);
121         }
122     }
123 
124     while (running)
125     {
126         glfwWaitEvents();
127 
128         for (i = 0;  i < count;  i++)
129         {
130             if (glfwWindowShouldClose(threads[i].window))
131                 running = GLFW_FALSE;
132         }
133     }
134 
135     for (i = 0;  i < count;  i++)
136         glfwHideWindow(threads[i].window);
137 
138     for (i = 0;  i < count;  i++)
139         thrd_join(threads[i].id, &result);
140 
141     exit(EXIT_SUCCESS);
142 }
143 
144