• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //========================================================================
2 // Vsync enabling 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 renders a high contrast, horizontally moving bar, allowing for
27 // visual verification of whether the set swap interval is indeed obeyed
28 //
29 //========================================================================
30 
31 #include <glad/glad.h>
32 #include <GLFW/glfw3.h>
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <math.h>
37 
38 #include "getopt.h"
39 
40 static int swap_tear;
41 static int swap_interval;
42 static double frame_rate;
43 
usage(void)44 static void usage(void)
45 {
46     printf("Usage: tearing [-h] [-f]\n");
47     printf("Options:\n");
48     printf("  -f create full screen window\n");
49     printf("  -h show this help\n");
50 }
51 
update_window_title(GLFWwindow * window)52 static void update_window_title(GLFWwindow* window)
53 {
54     char title[256];
55 
56     sprintf(title, "Tearing detector (interval %i%s, %0.1f Hz)",
57             swap_interval,
58             (swap_tear && swap_interval < 0) ? " (swap tear)" : "",
59             frame_rate);
60 
61     glfwSetWindowTitle(window, title);
62 }
63 
set_swap_interval(GLFWwindow * window,int interval)64 static void set_swap_interval(GLFWwindow* window, int interval)
65 {
66     swap_interval = interval;
67     glfwSwapInterval(swap_interval);
68     update_window_title(window);
69 }
70 
error_callback(int error,const char * description)71 static void error_callback(int error, const char* description)
72 {
73     fprintf(stderr, "Error: %s\n", description);
74 }
75 
framebuffer_size_callback(GLFWwindow * window,int width,int height)76 static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
77 {
78     glViewport(0, 0, width, height);
79 }
80 
key_callback(GLFWwindow * window,int key,int scancode,int action,int mods)81 static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
82 {
83     if (action != GLFW_PRESS)
84         return;
85 
86     switch (key)
87     {
88         case GLFW_KEY_UP:
89         {
90             if (swap_interval + 1 > swap_interval)
91                 set_swap_interval(window, swap_interval + 1);
92             break;
93         }
94 
95         case GLFW_KEY_DOWN:
96         {
97             if (swap_tear)
98             {
99                 if (swap_interval - 1 < swap_interval)
100                     set_swap_interval(window, swap_interval - 1);
101             }
102             else
103             {
104                 if (swap_interval - 1 >= 0)
105                     set_swap_interval(window, swap_interval - 1);
106             }
107             break;
108         }
109 
110         case GLFW_KEY_ESCAPE:
111             glfwSetWindowShouldClose(window, 1);
112             break;
113     }
114 }
115 
main(int argc,char ** argv)116 int main(int argc, char** argv)
117 {
118     int ch, width, height;
119     float position;
120     unsigned long frame_count = 0;
121     double last_time, current_time;
122     int fullscreen = GLFW_FALSE;
123     GLFWmonitor* monitor = NULL;
124     GLFWwindow* window;
125 
126     while ((ch = getopt(argc, argv, "fh")) != -1)
127     {
128         switch (ch)
129         {
130             case 'h':
131                 usage();
132                 exit(EXIT_SUCCESS);
133 
134             case 'f':
135                 fullscreen = GLFW_TRUE;
136                 break;
137         }
138     }
139 
140     glfwSetErrorCallback(error_callback);
141 
142     if (!glfwInit())
143         exit(EXIT_FAILURE);
144 
145     if (fullscreen)
146     {
147         const GLFWvidmode* mode;
148 
149         monitor = glfwGetPrimaryMonitor();
150         mode = glfwGetVideoMode(monitor);
151 
152         glfwWindowHint(GLFW_RED_BITS, mode->redBits);
153         glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits);
154         glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits);
155         glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
156 
157         width = mode->width;
158         height = mode->height;
159     }
160     else
161     {
162         width = 640;
163         height = 480;
164     }
165 
166     window = glfwCreateWindow(width, height, "", monitor, NULL);
167     if (!window)
168     {
169         glfwTerminate();
170         exit(EXIT_FAILURE);
171     }
172 
173     glfwMakeContextCurrent(window);
174     gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
175     set_swap_interval(window, 0);
176 
177     last_time = glfwGetTime();
178     frame_rate = 0.0;
179     swap_tear = (glfwExtensionSupported("WGL_EXT_swap_control_tear") ||
180                  glfwExtensionSupported("GLX_EXT_swap_control_tear"));
181 
182     glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
183     glfwSetKeyCallback(window, key_callback);
184 
185     glMatrixMode(GL_PROJECTION);
186     glOrtho(-1.f, 1.f, -1.f, 1.f, 1.f, -1.f);
187     glMatrixMode(GL_MODELVIEW);
188 
189     while (!glfwWindowShouldClose(window))
190     {
191         glClear(GL_COLOR_BUFFER_BIT);
192 
193         position = cosf((float) glfwGetTime() * 4.f) * 0.75f;
194         glRectf(position - 0.25f, -1.f, position + 0.25f, 1.f);
195 
196         glfwSwapBuffers(window);
197         glfwPollEvents();
198 
199         frame_count++;
200 
201         current_time = glfwGetTime();
202         if (current_time - last_time > 1.0)
203         {
204             frame_rate = frame_count / (current_time - last_time);
205             frame_count = 0;
206             last_time = current_time;
207             update_window_title(window);
208         }
209     }
210 
211     glfwTerminate();
212     exit(EXIT_SUCCESS);
213 }
214 
215