#include "config.h" #include #include #include #include #include #include #include #include #include #include static const char vertex_source[] = "attribute vec2 position;\n" "void\n" "main()\n" "{\n" " gl_Position = vec4(position, 0.0, 1.0);\n" "}\n"; static const char fragment_source[] = "#version 130\n" "uniform highp uint value;\n" "void\n" "main()\n" "{\n" " gl_FragColor = vec4(value & 255u,\n" " (value >> 8u) & 255u,\n" " (value >> 16u) & 255u,\n" " (value >> 24u) & 255u);\n" "}\n"; static GLuint make_shader(GLenum type, const char *source) { GLuint shader; GLint length, compile_status; GLsizei actual_length; GLchar *info_log; const char *type_name; switch (type) { case GL_VERTEX_SHADER: type_name = "vertex shader"; break; case GL_FRAGMENT_SHADER: type_name = "fragment shader"; break; default: type_name = "unknown shader"; break; } length = strlen(source); shader = glCreateShader(type); glShaderSource(shader, 1, (const GLchar **) &source, &length); glCompileShader(shader); glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); if (length > 0) { info_log = malloc(length); glGetShaderInfoLog(shader, length, &actual_length, info_log); if (*info_log) { fprintf(stderr, "Info log for %s:\n%s\n", type_name, info_log); } free(info_log); } glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); if (!compile_status) { fprintf(stderr, "%s: compilation failed\n", type_name); glDeleteShader(shader); return 0; } return shader; } static GLuint make_program(GLenum shader_type, ...) { GLint length, link_status; GLsizei actual_length; GLchar *info_log; GLuint program; GLuint shader; va_list ap; va_start(ap, shader_type); program = glCreateProgram(); while (shader_type != GL_NONE) { shader = make_shader(shader_type, va_arg(ap, const char *)); if (shader == 0) { glDeleteProgram(program); va_end(ap); return 0; } glAttachShader(program, shader); glDeleteShader(shader); shader_type = va_arg(ap, GLenum); } va_end(ap); glLinkProgram(program); glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length); if (length > 0) { info_log = malloc(length); glGetProgramInfoLog(program, length, &actual_length, info_log); if (*info_log) { fprintf(stderr, "Link info log:\n%s\n", info_log); } free(info_log); } glGetProgramiv(program, GL_LINK_STATUS, &link_status); if (!link_status) { fprintf(stderr, "program link failed\n"); glDeleteProgram(program); return 0; } return program; } static void run_test(unsigned int value) { static const float verts[] = { -1, -1, 1, -1, -1, 1, 1, 1 }; GLuint fbo, rb; GLuint program; GLuint uniform; GLuint attrib; float pixel[4]; glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glGenRenderbuffers(1, &rb); glBindRenderbuffer(GL_RENDERBUFFER, rb); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32F, 1, 1); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb); program = make_program(GL_VERTEX_SHADER, vertex_source, GL_FRAGMENT_SHADER, fragment_source, GL_NONE); glUseProgram(program); attrib = glGetAttribLocation(program, "position"); uniform = glGetUniformLocation(program, "value"); glUniform1ui(uniform, value); glEnableVertexAttribArray(attrib); glVertexAttribPointer(attrib, 2, /* size */ GL_FLOAT, GL_FALSE, /* normalized */ sizeof (float) * 2, /* stride */ verts); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisableVertexAttribArray(attrib); glUseProgram(0); glDeleteProgram(program); glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, pixel); printf("Expecting: %02x %02x %02x %02x\n" "Got: %02x %02x %02x %02x\n", value >> 24, (value >> 16) & 0xff, (value >> 8) & 0xff, value & 0xff, (int) pixel[3], (int) pixel[2], (int) pixel[1], (int) pixel[0]); glDeleteRenderbuffers(1, &rb); glDeleteFramebuffers(1, &fbo); } int main(int argc, char **argv) { int ret = EXIT_SUCCESS; SDL_Window *window; SDL_GLContext gl_context; unsigned int value; int res; if (argc > 1) value = strtoul(argv[1], NULL, 0); else value = 2139193217U; res = SDL_Init(SDL_INIT_VIDEO); if (res < 0) { fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); ret = EXIT_FAILURE; goto out; } SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); window = SDL_CreateWindow("glthing", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 128, 128, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN); if (window == NULL) { fprintf(stderr, "Failed to create SDL window: %s\n", SDL_GetError()); ret = EXIT_FAILURE; goto out_sdl; } gl_context = SDL_GL_CreateContext(window); if (gl_context == NULL) { fprintf(stderr, "Failed to create GL context window: %s\n", SDL_GetError()); ret = EXIT_FAILURE; goto out_window; } SDL_GL_MakeCurrent(window, gl_context); run_test(value); SDL_GL_MakeCurrent(NULL, NULL); SDL_GL_DeleteContext(gl_context); out_window: SDL_DestroyWindow(window); out_sdl: SDL_Quit(); out: return ret; }