├── .gitignore ├── README.md ├── img └── preview.png ├── makefile ├── shaders ├── blur.frag ├── simple.frag ├── simple.vert └── vis.frag └── src ├── main.c └── util ├── audio.c ├── audio.h ├── file_io.c ├── file_io.h ├── frame_buffer.c ├── frame_buffer.h ├── gl_util.c ├── gl_util.h ├── shaders.c ├── shaders.h ├── window.c └── window.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.o 3 | barvis 4 | wget* 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## barvis 2 | 3 | Barvis provides a minimal music visualizer in OpenGL, intended to be used as a background application for Linux status bars. 4 | 5 | ![alt tag](https://raw.githubusercontent.com/imalerich/barvis/master/img/preview.png) 6 | 7 | ## Dependencies 8 | 9 | - [gstreamer](https://gstreamer.freedesktop.org/) 10 | - Will need pulse audio support. 11 | - On Arch Linux, this is provided by the gst-good package. 12 | - [Xlib](https://www.x.org/docs/X11/xlib.pdf) 13 | - [OpenGL](https://www.opengl.org/) 14 | - [Glew](http://glew.sourceforge.net/) 15 | -------------------------------------------------------------------------------- /img/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imalerich/barvis/4ce1b5eb1a0296554a7afe9c033edd0df994afb0/img/preview.png -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | EXE = barvis 2 | OBJ = main.o gl_util.o file_io.o window.o audio.o shaders.o frame_buffer.o 3 | LIB = -lGLEW -lX11 -lGL -lGLU -lglut 4 | GST = `pkg-config --cflags --libs gstreamer-1.0` 5 | 6 | all: $(OBJ) 7 | gcc -g -o $(EXE) $(OBJ) $(LIB) $(GST) 8 | 9 | main.o: src/main.c gl_util.o window.o audio.o 10 | gcc -g -c src/main.c $(GST) 11 | 12 | gl_util.o: src/util/gl_util.c src/util/gl_util.h shaders.o frame_buffer.o 13 | gcc -g -c src/util/gl_util.c 14 | 15 | shaders.o: src/util/shaders.c src/util/shaders.h file_io.o 16 | gcc -g -c src/util/shaders.c $(GST) 17 | 18 | frame_buffer.o: src/util/frame_buffer.c src/util/frame_buffer.h 19 | gcc -g -c src/util/frame_buffer.c $(GST) 20 | 21 | window.o: src/util/window.c src/util/window.h 22 | gcc -g -c src/util/window.c 23 | 24 | file_io.o: src/util/file_io.c src/util/file_io.h 25 | gcc -g -c src/util/file_io.c 26 | 27 | audio.o: src/util/audio.c src/util/audio.h 28 | gcc -g -c src/util/audio.c $(GST) 29 | 30 | clean: 31 | rm -rf barvis 32 | rm -rf *.o 33 | -------------------------------------------------------------------------------- /shaders/blur.frag: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | in vec2 TexCoord; 4 | layout(location=0) out vec4 OutColor; 5 | 6 | uniform sampler2D tex; 7 | uniform vec2 dir; 8 | uniform vec2 size; 9 | 10 | #define M_PI 3.1415926535897932384626433832795 11 | #define M_E 2.71828 12 | 13 | // Eventually, this should be a static kernel. 14 | // As all coefficients are constant, this should 15 | // greatly improve performance. 16 | float gaussian(float mean, float sigma, float x) { 17 | float sigma2 = pow(sigma, 2); 18 | float den = sqrt(2.0 * sigma2 * M_PI); 19 | float num = pow(M_E, -(pow(x - mean, 2.0)) / (2.0 * sigma2)); 20 | return num / den; 21 | } 22 | 23 | #define H_KERNEL_WIDTH 44 24 | #define SCALE 3.0 25 | #define SIGMA 30 26 | #define MEAN 0.0 27 | 28 | void blur() { 29 | OutColor = vec4(0.0, 0.0, 0.0, 0.0); 30 | for (int i=-H_KERNEL_WIDTH; i= (size.y-BORDER_WIDTH)/(size.y)) { 21 | OutColor = BORDER; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /shaders/simple.vert: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | in vec2 position; 4 | in vec2 texcoord; 5 | 6 | out vec2 TexCoord; 7 | 8 | void main() { 9 | // passes the input coordinate on to the vertex shader 10 | TexCoord = texcoord; 11 | gl_Position = vec4(position, 0.0, 1.0); 12 | } 13 | -------------------------------------------------------------------------------- /shaders/vis.frag: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | in vec2 TexCoord; 4 | layout(location=0) out vec4 OutColor; 5 | 6 | // TODO: These should be input uniforms. 7 | #define BANDS 50 8 | #define THRESHOLD -80.0 9 | #define SCALE 60.0 10 | 11 | #define M_PI 3.1415926535897932384626433832795 12 | #define M_E 2.71828 13 | 14 | // TODO: These should be input uniforms. 15 | #define C1 rgb(21, 69, 93) 16 | #define C2 rgb(21, 69, 91) 17 | #define BG rgb(0, 0, 0) 18 | 19 | uniform float pulse[BANDS]; 20 | 21 | vec4 rgb(float R, float G, float B) { 22 | return vec4(R/255.0, G/255.0, B/255.0, 1.0); 23 | } 24 | 25 | float gaussian(float mean, float sigma, float x) { 26 | float sigma2 = pow(sigma, 2); 27 | float den = sqrt(2.0 * sigma2 * M_PI); 28 | float num = pow(M_E, -(pow(x - mean, 2.0)) / (2.0 * sigma2)); 29 | return num / den; 30 | } 31 | 32 | void norm() { 33 | float h = 1.0 / float(BANDS); 34 | float sigma = h; 35 | 36 | float sum = 0.0; 37 | float MAX = 0.0; 38 | for (int i=0; i= y) { 50 | float c = max(min(y + 0.5, 1), 0); 51 | // OutColor = 0.9 * sum * C1 + 1.1 * y * C2; 52 | OutColor = (C1 * sum) + BG * (1-sum); 53 | 54 | } else { 55 | OutColor = BG; 56 | } 57 | } 58 | 59 | void square() { 60 | int i = max(min(int(TexCoord.x * BANDS), BANDS-1), 0); 61 | float perc = (pulse[i] - THRESHOLD) / SCALE; 62 | float y = 1.0 - perc; 63 | 64 | if (TexCoord.y >= y) { 65 | OutColor = C2; 66 | } else { 67 | OutColor = BG; 68 | } 69 | } 70 | 71 | void main() { 72 | norm(); 73 | } 74 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "util/audio.h" 8 | #include "util/window.h" 9 | 10 | void print_help(); 11 | 12 | int main(int argc, char ** argv) { 13 | int coords[] = { 0, 0, 0, 0 }; 14 | 15 | static struct option long_options[] = { 16 | // Empty for now 17 | }; 18 | 19 | char c = 0; 20 | int option_index = 0; 21 | while ((c = getopt_long(argc, argv, "g:h", long_options, &option_index)) != -1) { 22 | char * end; 23 | // Keep it easy for now. 24 | switch (c) { 25 | case 'g': 26 | for (int idx=0, i=0; itype == GST_MESSAGE_ELEMENT) { 12 | const GstStructure * s = gst_message_get_structure(message); 13 | const char * name = gst_structure_get_name(s); 14 | GstClockTime endtime; 15 | 16 | if (strcmp(name, "spectrum") == 0) { 17 | const GValue * magnitudes; 18 | const GValue * mag, * phase; 19 | gdouble freq; 20 | guint i; 21 | 22 | if (!gst_structure_get_clock_time(s, "endtime", &endtime)) { 23 | endtime = GST_CLOCK_TIME_NONE; 24 | } 25 | 26 | magnitudes = gst_structure_get_value(s, "magnitude"); 27 | 28 | GLfloat gl_pulse[BANDS]; 29 | 30 | for (i=0; i 5 | #include 6 | #include 7 | #include 8 | 9 | #define BANDS 160 10 | #define THRESHOLD -80 11 | #define AUDIOFREQ 6000 12 | 13 | /** 14 | * Initialize gstreamer. 15 | */ 16 | void init_audio(); 17 | 18 | /** 19 | * Cleanup gstreamer. 20 | */ 21 | void clean_audio(); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/util/file_io.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "file_io.h" 5 | 6 | char * read_file(const char * filename) { 7 | FILE * f = fopen(filename, "rb"); 8 | char * buffer; 9 | size_t file_length; 10 | 11 | if (!f) { 12 | printf("failed to open file: %s\n", filename); 13 | exit(EXIT_FAILURE); 14 | } 15 | 16 | // this will tell us how big of a buffer we need 17 | fseek(f, 0, SEEK_END); 18 | file_length = ftell(f); 19 | fseek(f, 0, SEEK_SET); 20 | 21 | // allocate our buffer and read the data 22 | buffer = (char *)malloc(file_length + 1); // +1 for NULL terminator 23 | fread(buffer, file_length, 1, f); 24 | buffer[file_length] = '\0'; 25 | fclose(f); 26 | 27 | return buffer; 28 | } 29 | 30 | size_t file_length(const char * filename) { 31 | FILE * f = fopen(filename, "rb"); 32 | size_t file_length; 33 | 34 | if (!f) { 35 | printf("failed to open file: %s\n", filename); 36 | exit(EXIT_FAILURE); 37 | } 38 | 39 | fseek(f, 0, SEEK_END); 40 | file_length = ftell(f); 41 | fclose(f); 42 | 43 | return file_length; 44 | } 45 | -------------------------------------------------------------------------------- /src/util/file_io.h: -------------------------------------------------------------------------------- 1 | #ifndef FILE_IO_H 2 | #define FILE_IO_H 3 | 4 | /** 5 | * Utility method to read the given file name into a single 6 | * character buffer. The caller will be responsible for 7 | * freeing the returned memeory. 8 | * 9 | * \param filename Name of the file to read in as a buffer. 10 | * \return Buffer representation of the input file. 11 | */ 12 | char * read_file(const char * filename); 13 | 14 | /** 15 | * Determines the length (in bytes) of the input file. 16 | * \param filename Name of the file to read. 17 | * \return The length (in bytes) of the file. 18 | */ 19 | size_t file_length(const char * filename); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/util/frame_buffer.c: -------------------------------------------------------------------------------- 1 | #include "frame_buffer.h" 2 | 3 | struct frame_buffer create_frame_buffer(const unsigned width, const unsigned height) { 4 | GLuint tex, buff; 5 | 6 | glGenFramebuffers(1, &buff); 7 | glBindFramebuffer(GL_FRAMEBUFFER, buff); 8 | 9 | glGenTextures(1, &tex); 10 | glBindTexture(GL_TEXTURE_2D, tex); 11 | 12 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 13 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 14 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 15 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 16 | 17 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGB, GL_FLOAT, NULL); 18 | 19 | glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0); 20 | GLenum draw_buff[1] = { GL_COLOR_ATTACHMENT0 }; 21 | glDrawBuffers(1, draw_buff); 22 | 23 | return (struct frame_buffer){buff, tex, width, height}; 24 | } 25 | 26 | void bind_frame_buffer(struct frame_buffer buff) { 27 | glBindFramebuffer(GL_FRAMEBUFFER, buff.buffer); 28 | glViewport(0, 0, buff.width, buff.height); 29 | 30 | glActiveTexture(GL_TEXTURE0); 31 | glBindTexture(GL_TEXTURE_2D, buff.tex); 32 | } 33 | 34 | void bind_screen_buffer(unsigned screenw, unsigned screenh) { 35 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 36 | glViewport(0, 0, screenw, screenh); 37 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 38 | } 39 | -------------------------------------------------------------------------------- /src/util/frame_buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef FRAME_BUFFER_H 2 | #define FRAME_BUFFER_H 3 | 4 | #include "gl_util.h" 5 | 6 | /** 7 | * Encapsulates the frame buffer to render to 8 | * as well as the texture associated with that frame buffer. 9 | */ 10 | struct frame_buffer { 11 | GLuint buffer; 12 | GLuint tex; 13 | unsigned width; 14 | unsigned height; 15 | }; 16 | 17 | /** 18 | * Constructs a new frame buffer and corresponding texture 19 | * for the given texture size. 20 | */ 21 | struct frame_buffer create_frame_buffer(const unsigned width, const unsigned height); 22 | 23 | /** 24 | * Binds the input frame buffer, and sets the buffers 25 | * corresponding texture as the render target. 26 | */ 27 | void bind_frame_buffer(struct frame_buffer buff); 28 | 29 | /** 30 | * Reset the current frame buffer and 31 | * render to the screen. 32 | * This call will clear the screen buffer. 33 | */ 34 | void bind_screen_buffer(unsigned screenw, unsigned screenh); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/util/gl_util.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "window.h" 7 | #include "gl_util.h" 8 | #include "shaders.h" 9 | #include "frame_buffer.h" 10 | 11 | struct frame_buffer vis_frame; 12 | struct frame_buffer blur_h_frame; 13 | struct frame_buffer blur_v_frame; 14 | 15 | GLuint vao; 16 | GLuint vbo; 17 | GLuint ebo; 18 | 19 | GLuint vis_prog; 20 | GLuint blur_prog; 21 | GLuint simple_prog; 22 | 23 | // array of vertices describing the entire screen 24 | const float vertices[] = { 25 | -1.0f, 1.0f, 0.0f, 0.0f, // Top-Left 26 | 1.0f, 1.0f, 1.0f, 0.0f, // Top-Right 27 | 1.0f, -1.0f, 1.0f, 1.0f, // Bottom-Right 28 | -1.0f, -1.0f, 0.0f, 1.0f // Bottom-Left 29 | }; 30 | 31 | const GLuint elements[] = { 32 | 0, 1, 2, 33 | 2, 3, 0 34 | }; 35 | 36 | // private function prototypes 37 | void init_screen_rect(); 38 | void check_shader_compile(const char * filename, GLuint shader); 39 | void init_frame_buffers(); 40 | 41 | void init_vis_shader(); 42 | void init_blur_shader(); 43 | void init_simple_shader(); 44 | 45 | ////////////////////////// 46 | // Update // 47 | ////////////////////////// 48 | 49 | void update_screen() { 50 | // Get the window size. 51 | XWindowAttributes gwa; 52 | XGetWindowAttributes(dpy, win, &gwa); 53 | float SIZE[] = { gwa.width, gwa.height }; 54 | glClearColor(0.0, 0.0, 0.0, 1.0); 55 | 56 | ////////////////////////////// 57 | // Render The Visualizer // 58 | ////////////////////////////// 59 | 60 | bind_frame_buffer(vis_frame); 61 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 62 | glUseProgram(vis_prog); 63 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 64 | 65 | ////////////////////////////////////// 66 | // Gaussian Blur Horizontal Pass // 67 | ////////////////////////////////////// 68 | 69 | float RIGHT[] = { 1.0, 0.0 }; 70 | 71 | bind_frame_buffer(blur_h_frame); 72 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 73 | glUseProgram(blur_prog); 74 | glBindTexture(GL_TEXTURE_2D, vis_frame.tex); 75 | 76 | glUniform1i(glGetUniformLocation(blur_prog, "tex"), 0); 77 | glUniform2fv(glGetUniformLocation(blur_prog, "dir"), 1, RIGHT); 78 | glUniform2fv(glGetUniformLocation(blur_prog, "size"), 1, SIZE); 79 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 80 | 81 | ////////////////////////////////////// 82 | // Gaussian Blur Vertical Pass // 83 | ////////////////////////////////////// 84 | 85 | float UP[] = { 0.0, 1.0 }; 86 | 87 | bind_frame_buffer(blur_v_frame); 88 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 89 | glUseProgram(blur_prog); 90 | glBindTexture(GL_TEXTURE_2D, blur_h_frame.tex); 91 | 92 | glUniform1i(glGetUniformLocation(blur_prog, "tex"), 0); 93 | glUniform2fv(glGetUniformLocation(blur_prog, "dir"), 1, UP); 94 | glUniform2fv(glGetUniformLocation(blur_prog, "size"), 1, SIZE); 95 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 96 | 97 | ////////////////////////////////////// 98 | // Render to the Back Buffer // 99 | ////////////////////////////////////// 100 | 101 | bind_screen_buffer(gwa.width, gwa.height); 102 | glUseProgram(simple_prog); 103 | glBindTexture(GL_TEXTURE_2D, blur_v_frame.tex); 104 | glUniform1i(glGetUniformLocation(simple_prog, "tex"), 0); 105 | glUniform2fv(glGetUniformLocation(simple_prog, "size"), 1, SIZE); 106 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 107 | 108 | // Rendering is done, swap buffers. 109 | glXSwapBuffers(dpy, win); 110 | gl_check_errors("update_screen(...)"); 111 | } 112 | 113 | ////////////////////////// 114 | // Init // 115 | ////////////////////////// 116 | 117 | void init_gl() { 118 | // intialize glew 119 | glewExperimental = GL_TRUE; 120 | int glew_err = GLEW_OK; 121 | 122 | if ((glew_err = glewInit()) != GLEW_OK) { 123 | printf("error - glewInit():\nt\t%s\n", glewGetErrorString(glew_err)); 124 | exit(EXIT_FAILURE); 125 | } 126 | 127 | // clear the error buffer, just trust me on this 128 | glGetError(); 129 | 130 | // generate our vertex array object 131 | glGenVertexArrays(1, &vao); 132 | glBindVertexArray(vao); 133 | 134 | // initialize the rendering objects that will be used for ray tracing 135 | init_screen_rect(); 136 | init_vis_shader(); 137 | init_blur_shader(); 138 | init_simple_shader(); 139 | init_frame_buffers(); 140 | gl_check_errors("init_gl(...)"); 141 | } 142 | 143 | void init_frame_buffers() { 144 | // Get the window size. 145 | XWindowAttributes gwa; 146 | XGetWindowAttributes(dpy, win, &gwa); 147 | 148 | vis_frame = create_frame_buffer(gwa.width, gwa.height); 149 | blur_h_frame = create_frame_buffer(gwa.width, gwa.height); 150 | blur_v_frame = create_frame_buffer(gwa.width, gwa.height); 151 | } 152 | 153 | void init_screen_rect() { 154 | glGenBuffers(1, &vbo); 155 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 156 | glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW); 157 | 158 | glGenBuffers(1, &ebo); 159 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); 160 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), &elements, GL_STATIC_DRAW); 161 | } 162 | 163 | ////////////////////////// 164 | // Shaders // 165 | ////////////////////////// 166 | 167 | void init_vis_shader() { 168 | vis_prog = compile_shader("shaders/simple.vert", "shaders/vis.frag"); 169 | glBindFragDataLocation(vis_prog, 0, "OutColor"); 170 | 171 | // tell the shader where each input is located on the vertex buffer 172 | GLint pos_att = glGetAttribLocation(vis_prog, "position"); 173 | GLint tex_att = glGetAttribLocation(vis_prog, "texcoord"); 174 | 175 | glVertexAttribPointer(pos_att, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0); 176 | glVertexAttribPointer(tex_att, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 177 | (void *)(2 * sizeof(float))); 178 | 179 | glEnableVertexAttribArray(pos_att); 180 | glEnableVertexAttribArray(tex_att); 181 | } 182 | 183 | void init_blur_shader() { 184 | blur_prog = compile_shader("shaders/simple.vert", "shaders/blur.frag"); 185 | glBindFragDataLocation(blur_prog, 0, "OutColor"); 186 | 187 | // tell the shader where each input is located on the vertex buffer 188 | GLint pos_att = glGetAttribLocation(blur_prog, "position"); 189 | GLint tex_att = glGetAttribLocation(blur_prog, "texcoord"); 190 | 191 | glVertexAttribPointer(pos_att, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0); 192 | glVertexAttribPointer(tex_att, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 193 | (void *)(2 * sizeof(float))); 194 | 195 | glEnableVertexAttribArray(pos_att); 196 | glEnableVertexAttribArray(tex_att); 197 | } 198 | 199 | void init_simple_shader() { 200 | simple_prog = compile_shader("shaders/simple.vert", "shaders/simple.frag"); 201 | glBindFragDataLocation(simple_prog, 0, "OutColor"); 202 | 203 | // tell the shader where each input is located on the vertex buffer 204 | GLint pos_att = glGetAttribLocation(simple_prog, "position"); 205 | GLint tex_att = glGetAttribLocation(simple_prog, "texcoord"); 206 | 207 | glVertexAttribPointer(pos_att, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0); 208 | glVertexAttribPointer(tex_att, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 209 | (void *)(2 * sizeof(float))); 210 | 211 | glEnableVertexAttribArray(pos_att); 212 | glEnableVertexAttribArray(tex_att); 213 | } 214 | 215 | ////////////////////////// 216 | // Errors // 217 | ////////////////////////// 218 | 219 | void gl_check_errors(const char * info) { 220 | GLenum gl_err; 221 | bool found_err = false; 222 | 223 | while ((gl_err = glGetError()) != 0) { 224 | found_err = true; 225 | fprintf(stderr, "%s - err: %d\n", info, gl_err); 226 | } 227 | 228 | if (found_err) { 229 | exit(EXIT_FAILURE); 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /src/util/gl_util.h: -------------------------------------------------------------------------------- 1 | #ifndef GL_UTIL_H 2 | #define GL_UTIL_H 3 | 4 | #define GLEW_STATIC 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | extern GLuint vis_prog; 12 | 13 | /** 14 | * Initializes an OpenGL context using screen 15 | * dimmensions of screen_w and screen_h. 16 | * \param title Title to use for the window. 17 | * \param v_sync The swap interval, use 0 to disable vertical sync. 18 | */ 19 | void init_gl(); 20 | 21 | /** 22 | * Draws a rectangle over the entire screen using the 23 | * texture to be filled by OpenCL. 24 | */ 25 | void update_screen(); 26 | 27 | /** 28 | * Checks if an operation has produced an error since last 29 | * checking for an error. If so, this method will print out 30 | * the information detailed in 'info' as well as the error code 31 | * to stderr, and then exit with a failure. 32 | */ 33 | void gl_check_errors(const char * info); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/util/shaders.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "shaders.h" 6 | #include "file_io.h" 7 | 8 | GLuint compile_shader(const char * vert_name, const char * frag_name) { 9 | char * vs_source = read_file(vert_name); 10 | char * fs_source = read_file(frag_name); 11 | 12 | // compile and check the vertex shader 13 | GLuint vshader = glCreateShader(GL_VERTEX_SHADER); 14 | glShaderSource(vshader, 1, (const GLchar **)&vs_source, NULL); 15 | glCompileShader(vshader); 16 | check_shader_compile(vert_name, vshader); 17 | 18 | // compile and check the fragment shader 19 | GLuint fshader = glCreateShader(GL_FRAGMENT_SHADER); 20 | glShaderSource(fshader, 1, (const GLchar **)&fs_source, NULL); 21 | glCompileShader(fshader); 22 | check_shader_compile(frag_name, fshader); 23 | 24 | free(vs_source); 25 | free(fs_source); 26 | 27 | // finally create and compile the shader program 28 | GLuint prog = glCreateProgram(); 29 | glAttachShader(prog, vshader); 30 | glAttachShader(prog, fshader); 31 | 32 | glLinkProgram(prog); 33 | glUseProgram(prog); 34 | 35 | return prog; 36 | } 37 | 38 | void check_shader_compile(const char * filename, GLuint shader) { 39 | GLint status; 40 | char buffer[512]; 41 | 42 | glGetShaderiv(shader, GL_COMPILE_STATUS, &status); 43 | glGetShaderInfoLog(shader, 512, NULL, buffer); 44 | 45 | // check for any log info 46 | if (strlen(buffer) > 0) { 47 | fprintf(stderr, "%s\n%s\n", filename, buffer); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/util/shaders.h: -------------------------------------------------------------------------------- 1 | #ifndef SHADERS_H 2 | #define SHADERS_H 3 | 4 | #include "gl_util.h" 5 | 6 | /** 7 | * Compiles a new shader program using the input vertex and fragment 8 | * shader files. 9 | * \param vert_name File name and path for the vertex shader. 10 | * \param frag_name File name and path for the fragment shader. 11 | * \return Identifier for the compiled shader program. 12 | */ 13 | GLuint compile_shader(const char * vert_name, const char * frag_name); 14 | 15 | /** 16 | * Checks whether or not the input shader was successfuly compiled. 17 | * If not an error message will be printed to the stderr stream 18 | * with the compile error. 19 | * Note that this method will NOT terminate the application. 20 | */ 21 | void check_shader_compile(const char * filename, GLuint shader); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/util/window.c: -------------------------------------------------------------------------------- 1 | #include "window.h" 2 | 3 | Display * dpy; 4 | Window win; 5 | GLXContext glc; 6 | 7 | void init_window(int width, int height, int x, int y) { 8 | Window root; 9 | GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None }; 10 | XVisualInfo * vi; 11 | Colormap cmap; 12 | XSetWindowAttributes swa; 13 | 14 | dpy = XOpenDisplay(NULL); 15 | root = DefaultRootWindow(dpy); 16 | vi = glXChooseVisual(dpy, 0, att); 17 | cmap = XCreateColormap(dpy, root, vi->visual, AllocNone); 18 | swa.colormap = cmap; 19 | swa.event_mask = ExposureMask | KeyPressMask; 20 | swa.override_redirect = true; 21 | 22 | // Create the window. 23 | win = XCreateWindow(dpy, root, x, y, width, height, 0, 24 | vi->depth, InputOutput, vi->visual, 25 | CWColormap | CWEventMask | CWOverrideRedirect, 26 | &swa); 27 | 28 | XClassHint * hint = XAllocClassHint(); 29 | hint->res_name = "barvis"; 30 | hint->res_class = "dektop"; 31 | XSetClassHint(dpy, win, hint); 32 | 33 | XMapWindow(dpy, win); 34 | XStoreName(dpy, win, "barvis"); 35 | 36 | glc = glXCreateContext(dpy, vi, NULL, GL_TRUE); 37 | glXMakeCurrent(dpy, win, glc); 38 | 39 | init_gl(); 40 | } 41 | -------------------------------------------------------------------------------- /src/util/window.h: -------------------------------------------------------------------------------- 1 | #ifndef XLIB_UTIL_H 2 | #define XLIB_UTIL_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "gl_util.h" 10 | 11 | extern Display * dpy; 12 | extern Window win; 13 | extern GLXContext glc; 14 | 15 | /** 16 | * Initializes a desktop window, 17 | * creates an OpenGL context for that window. 18 | * Then performs some basic setup on that context. 19 | * This method will call the init_gl(..) method of 20 | * gl_util.h, so there is no need to call it after this 21 | * method completes. 22 | * \param width Width for the new window. 23 | * \param height Height for the new window. 24 | * \param x X coordinate for the new window. 25 | * \param y Y coordinate for the new window. 26 | */ 27 | void init_window(int width, int height, int x, int y); 28 | 29 | #endif 30 | --------------------------------------------------------------------------------