From f5880769fe4009b11450abb39204db8a1756b9dc Mon Sep 17 00:00:00 2001 From: Eden Salomon Date: Thu, 22 Oct 2015 21:08:01 +0300 Subject: [PATCH] Add 'Graphics' options test --- tests/CMakeLists.txt | 5 +- tests/options.c | 289 +++++++++++++++++++++++++++++++++++++++++++ tests/options.txt | 10 ++ 3 files changed, 303 insertions(+), 1 deletion(-) create mode 100644 tests/options.c create mode 100644 tests/options.txt diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 31e5d19b3..031f339be 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -47,10 +47,13 @@ set_target_properties(title PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Title") add_executable(windows WIN32 MACOSX_BUNDLE windows.c ${GLAD}) set_target_properties(windows PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Windows") +add_executable(options MACOSX_BUNDLE options.c ${GETOPT} ${GLAD}) +set_target_properties(options PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Options") + target_link_libraries(empty "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}") target_link_libraries(threads "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}") -set(WINDOWS_BINARIES empty sharing tearing threads title windows) +set(WINDOWS_BINARIES empty sharing tearing threads title windows options) set(CONSOLE_BINARIES clipboard events msaa gamma glfwinfo iconify joysticks monitors reopen cursor) diff --git a/tests/options.c b/tests/options.c new file mode 100644 index 000000000..aabb03616 --- /dev/null +++ b/tests/options.c @@ -0,0 +1,289 @@ +//======================================================================== +// Simple 'Graphics' options test +// Copyright (C) 2015 Eden Salomon +// +// 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 creates a window with the ability to change during runtime +// the window options typically seen in the 'Graphics' section of games. +// This includes resolution, refresh rate, and fullscreen / windowed mode. +// +//======================================================================== + +#include +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#define GLFW_EXPOSE_NATIVE_WGL +#include + +#include +#include + +#include "getopt.h" + +typedef struct _WindowState +{ + SIZE* dimenstions; + int size; + int count; + int current; +} WindowState; + +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + +static void list_resolutions(GLFWwindow* window) +{ + GLFWmonitor* monitor; + int count; + const GLFWvidmode* modes; + + monitor = glfwGetWindowMonitor(window); + modes = glfwGetVideoModes(monitor ? monitor : glfwGetPrimaryMonitor(), &count); + + printf("List of supported resolutions:\n"); + printf(" +----+------------------------+----+\n"); + printf(" | | resolution | color | |\n"); + printf(" | id | width height | r g b | rf |\n"); + printf(" +----+------------------------+----+\n"); + for (int i = 0; i < count; ++i) { + printf(" | %2d | %5d %6d | %d %d %d | %2d |\n", + i + 1, + modes[i].width, modes[i].height, + modes[i].redBits, + modes[i].greenBits, + modes[i].blueBits, + modes[i].refreshRate); + } + printf(" +----+------------------------+----+\n\n"); +} + +static void setVideoMode(GLFWwindow* window, WindowState* state, int index) +{ + GLFWmonitor* monitor; + const GLFWvidmode* mode; + int width, height; + + state->current = (index + state->count) % state->count; + width = state->dimenstions[state->current].cx; + height = state->dimenstions[state->current].cy; + + glfwSetWindowSize(window, width, height); + + monitor = glfwGetWindowMonitor(window); + mode = glfwGetVideoMode(monitor); + + printf("Changed resolution to %dx%d [%d].\n", width, height, mode->refreshRate); +} + +static void controls() +{ + printf("When the window is in focus, use the following keys to control the various options:\n"); + printf(" Esc Exit the application\n"); + printf(" h display this help\n"); + printf(" f toggle fullscreen / window mode\n"); + printf(" r toggle between different refresh rates\n"); + printf(" l list all supported resolutions\n"); + printf(" d, -> next resolution\n"); + printf(" a, <- previous resolution\n"); +} + +static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) +{ + WindowState* state = (WindowState*) glfwGetWindowUserPointer(window); + + if (action != GLFW_PRESS) + return; + + switch (key) + { + case GLFW_KEY_H: + controls(); + break; + case GLFW_KEY_L: + list_resolutions(window); + break; + case GLFW_KEY_F: + glfwToggleWindowFullscreen(window); + break; + case GLFW_KEY_ESCAPE: + glfwSetWindowShouldClose(window, GLFW_TRUE); + break; + case GLFW_KEY_A: + setVideoMode(window, state, state->current - 1); + break; + case GLFW_KEY_D: + setVideoMode(window, state, state->current + 1); + break; + case GLFW_KEY_R: + // TODO: toggle refresh rate on current resolution + // as of now the highest value is used due to + // GLFW_REFRESH_RATE being set to GLFW_DONT_CARE + break; + } +} + +static void usage() +{ + printf("Usage: oprions [OPTION]...\n"); + printf("Options:\n"); + printf(" -h, --help show this help\n"); + printf(" -l, --list-resolutions list all resolutions supported by the primary monitor\n"); + printf(" --width=640 specify the width of the window in pixels\n"); + printf(" --height=480 specify the height of the window in pixels\n"); + printf(" -r, --refresh-rate=RATE specify the refresh rate of the window in Hz\n"); +} + +int main(int argc, char** argv) +{ + int ch; + int width = 640; + int height = 480; + int list = GLFW_FALSE; + int fullscreen = GLFW_FALSE; + int running = GLFW_TRUE; + GLFWwindow* window; + GLFWmonitor* monitor; + WindowState state = { NULL, 0, 0, 0 }; + int i, j, count; + const GLFWvidmode* modes; + + enum { HELP, RESOLUTIONS, WIDTH, HIEGHT, REFRESH, FULLSCREEN }; + + const struct option options[] = + { + { "help", 0, NULL, HELP }, + { "list-resolutions", 0, NULL, RESOLUTIONS }, + { "width", 1, NULL, WIDTH }, + { "height", 1, NULL, HIEGHT }, + { "refresh-rate", 1, NULL, REFRESH }, + { "fullscreen", 0, NULL, FULLSCREEN }, + { NULL, 0, NULL, 0 } + }; + + glfwSetErrorCallback(error_callback); + + if (!glfwInit()) + exit(EXIT_FAILURE); + + while ((ch = getopt_long(argc, argv, "hlr:f", options, NULL)) != -1) { + switch (ch) { + case 'h': + case HELP: + usage(); + exit(EXIT_SUCCESS); + case 'l': + case RESOLUTIONS: + list = GLFW_TRUE; + break; + case WIDTH: + width = atoi(optarg); + break; + case HIEGHT: + height = atoi(optarg); + break; + case 'r': + case REFRESH: + glfwWindowHint(GLFW_REFRESH_RATE, atoi(optarg)); + break; + case 'f': + case FULLSCREEN: + glfwWindowHint(GLFW_FULLSCREEN, GLFW_TRUE); + break; + default: + usage(); + exit(EXIT_FAILURE); + } + } + + monitor = glfwGetPrimaryMonitor(); + window = glfwCreateWindow(width, height, "Graphics Options", (fullscreen ? monitor : NULL), NULL); + + modes = glfwGetVideoModes(monitor ? monitor : glfwGetPrimaryMonitor(), &count); + + for (i = 0; i < count; ++i) { + SIZE size; + + size.cx = modes[i].width; + size.cy = modes[i].height; + + for (j = 0; j < state.count; ++j) { + if (state.dimenstions[j].cx == size.cx && + state.dimenstions[j].cy == size.cy) + break; + } + + if (j < state.count) + continue; + + if (state.count == state.size) + { + if (state.count) + state.size *= 2; + else + state.size = 128; + + state.dimenstions = (SIZE*) realloc(state.dimenstions, state.size * sizeof(SIZE)); + } + + state.count++; + state.dimenstions[state.count - 1] = size; + } + + glfwSetWindowUserPointer(window, &state); + + if (!window) { + glfwTerminate(); + exit(EXIT_FAILURE); + } + + glfwSetKeyCallback(window, key_callback); + + glfwMakeContextCurrent(window); + + gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); + + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + + if (list) + list_resolutions(window); + + controls(); + + while (running) + { + glClear(GL_COLOR_BUFFER_BIT); + glfwSwapBuffers(window); + + if (glfwWindowShouldClose(window)) + running = GLFW_FALSE; + + glfwPollEvents(); + } + + free(state.dimenstions); + glfwTerminate(); + exit(EXIT_SUCCESS); +} + diff --git a/tests/options.txt b/tests/options.txt new file mode 100644 index 000000000..352d8ad5e --- /dev/null +++ b/tests/options.txt @@ -0,0 +1,10 @@ +TODO: +- Change Resulution +- Refresh Rate +- Fullscreen / Window +all in runtime + +new state variables + + +Enter fullscreen mode: