glfw/tests/msaa.c
Emmanuel Gil Peyrot 8e51c4a577 Tests: Add damage tracking to MSAA
This lets compositors avoid re-rendering the entire buffer when only the
outside of the squares changed.

If glfwGetBufferAge() returns 0 for any reason (the buffer was just
created, there was an error, or the underlying API doesn’t track buffer
age), we swap the entire buffer again.
2019-12-08 18:40:19 +01:00

241 lines
6.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//========================================================================
// Multisample anti-aliasing test
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This test renders two high contrast, slowly rotating quads, one aliased
// and one (hopefully) anti-aliased, thus allowing for visual verification
// of whether MSAA is indeed enabled
//
//========================================================================
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#if defined(_MSC_VER)
// Make MS math.h define M_PI
#define _USE_MATH_DEFINES
#endif
#include "linmath.h"
#include <stdio.h>
#include <stdlib.h>
#include "getopt.h"
static const vec2 vertices[4] =
{
{ -0.6f, -0.6f },
{ 0.6f, -0.6f },
{ 0.6f, 0.6f },
{ -0.6f, 0.6f }
};
static const char* vertex_shader_text =
"#version 110\n"
"uniform mat4 MVP;\n"
"attribute vec2 vPos;\n"
"void main()\n"
"{\n"
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
"}\n";
static const char* fragment_shader_text =
"#version 110\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(1.0);\n"
"}\n";
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action != GLFW_PRESS)
return;
switch (key)
{
case GLFW_KEY_SPACE:
glfwSetTime(0.0);
break;
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
}
}
static void usage(void)
{
printf("Usage: msaa [-h] [-s SAMPLES]\n");
}
int main(int argc, char** argv)
{
int ch, samples = 4;
GLFWwindow* window;
GLuint vertex_buffer, vertex_shader, fragment_shader, program;
GLint mvp_location, vpos_location;
// Minimum static damage for both squares.
GLFWrect rects[8] =
{{ 25, 25, 350, 90},
{ 25, 285, 350, 90},
{ 25, 115, 90, 170},
{285, 115, 90, 170},
{425, 25, 350, 90},
{425, 285, 350, 90},
{425, 115, 90, 170},
{685, 115, 90, 170},
};
while ((ch = getopt(argc, argv, "hs:")) != -1)
{
switch (ch)
{
case 'h':
usage();
exit(EXIT_SUCCESS);
case 's':
samples = atoi(optarg);
break;
default:
usage();
exit(EXIT_FAILURE);
}
}
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
if (samples)
printf("Requesting MSAA with %i samples\n", samples);
else
printf("Requesting that MSAA not be available\n");
glfwWindowHint(GLFW_SAMPLES, samples);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
window = glfwCreateWindow(800, 400, "Aliasing Detector", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetKeyCallback(window, key_callback);
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSwapInterval(1);
glGetIntegerv(GL_SAMPLES, &samples);
if (samples)
printf("Context reports MSAA is available with %i samples\n", samples);
else
printf("Context reports MSAA is unavailable\n");
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
glCompileShader(vertex_shader);
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
glCompileShader(fragment_shader);
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
mvp_location = glGetUniformLocation(program, "MVP");
vpos_location = glGetAttribLocation(program, "vPos");
glEnableVertexAttribArray(vpos_location);
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
sizeof(vertices[0]), (void*) 0);
while (!glfwWindowShouldClose(window))
{
float ratio;
int buffer_age;
int width, height;
mat4x4 m, p, mvp;
const double angle = glfwGetTime() * M_PI / 180.0;
glfwGetFramebufferSize(window, &width, &height);
buffer_age = glfwGetBufferAge(window);
ratio = width / (float) height;
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
mat4x4_ortho(p, -ratio, ratio, -1.f, 1.f, 0.f, 1.f);
mat4x4_translate(m, -1.f, 0.f, 0.f);
mat4x4_rotate_Z(m, m, (float) angle);
mat4x4_mul(mvp, p, m);
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
glDisable(GL_MULTISAMPLE);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
mat4x4_translate(m, 1.f, 0.f, 0.f);
mat4x4_rotate_Z(m, m, (float) angle);
mat4x4_mul(mvp, p, m);
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
glEnable(GL_MULTISAMPLE);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
// If buffer_age is 0, we cant assume anything about the previous buffer
// so swap the entire buffer.
if (buffer_age > 0)
glfwSwapBuffersWithDamage(window, rects, 8);
else
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}