1 #define GL_GLEXT_PROTOTYPES
7 #include <X11/extensions/Xcomposite.h>
8 #include <X11/extensions/Xdamage.h>
9 #include <X11/extensions/shape.h>
10 #include <X11/extensions/Xrandr.h>
14 typedef struct CompositedWindow
29 typedef struct CompositedMonitor
36 unsigned vertex_buffer;
37 unsigned index_buffer;
38 unsigned vertex_array;
39 unsigned tessellation;
43 typedef struct CompositedScreen
53 GLXContext glx_context;
56 unsigned geometry_loc;
57 unsigned window_vertex_buffer;
58 unsigned window_vertex_array;
61 CompositedWindow *windows;
63 unsigned windows_capacity;
64 CompositedMonitor *monitors;
69 typedef struct Compositor
72 CompositedScreen *screens;
75 PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB;
76 PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT;
77 PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT;
81 static const char *vshader =
83 "uniform vec4 geometry;\n"
85 "in vec2 texture_coord;\n"
86 "out vec2 texcoord;\n"
89 " gl_Position = vec4((geometry.xy+vertex*geometry.zw)*2.0-1.0, 0.0, 1.0);\n"
90 " texcoord = texture_coord;\n"
93 static const char *fshader =
95 "uniform sampler2D image;\n"
97 "out vec4 frag_color;\n"
100 " frag_color = texture(image, texcoord);\n"
103 static const float window_vertices[] =
105 /* vertex texcoord */
106 0.0f, 1.0f, 0.0f, 0.0f,
107 0.0f, 0.0f, 0.0f, 1.0f,
108 1.0f, 1.0f, 1.0f, 0.0f,
109 1.0f, 0.0f, 1.0f, 1.0f
112 int terminate_requested = 0;
114 int x_error_handler(Display *display, XErrorEvent *event)
116 printf("Ignoring X error %d on resource %lx\n", event->error_code, event->resourceid);
121 int with_error(const char *message)
123 fprintf(stderr, "%s\n", message);
127 int initialize_gl(Compositor *compositor, CompositedScreen *screen)
131 GLXFBConfig *configs;
134 XSetWindowAttributes win_attr;
137 attribs[i++] = GLX_DRAWABLE_TYPE;
138 attribs[i++] = GLX_WINDOW_BIT;
139 attribs[i++] = GLX_RENDER_TYPE;
140 attribs[i++] = GLX_RGBA_BIT;
141 attribs[i++] = GLX_DOUBLEBUFFER;
143 attribs[i++] = GLX_BIND_TO_TEXTURE_RGBA_EXT;
147 configs = glXChooseFBConfig(compositor->display, screen->number, attribs, &nconfigs);
148 if(!configs || !nconfigs)
149 return with_error("Could not find a suitable FBConfig");
150 screen->fbconfig = configs[0];
153 vi = glXGetVisualFromFBConfig(compositor->display, screen->fbconfig);
154 win_attr.colormap = XCreateColormap(compositor->display, screen->root, vi->visual, AllocNone);
155 screen->render_window = XCreateWindow(compositor->display, screen->overlay, 0, 0, screen->width, screen->height, 0, vi->depth, InputOutput, vi->visual, CWColormap, &win_attr);
156 XMapWindow(compositor->display, screen->render_window);
158 screen->glx_window = glXCreateWindow(compositor->display, screen->fbconfig, screen->render_window, NULL);
161 attribs[i++] = GLX_CONTEXT_FLAGS_ARB;
162 attribs[i++] = GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
163 attribs[i++] = GLX_CONTEXT_MAJOR_VERSION_ARB;
165 attribs[i++] = GLX_CONTEXT_MINOR_VERSION_ARB;
169 screen->glx_context = compositor->glXCreateContextAttribsARB(compositor->display, screen->fbconfig, NULL, True, attribs);
176 void use_gl(Compositor *compositor, CompositedScreen *screen)
178 glXMakeContextCurrent(compositor->display, screen->glx_window, screen->glx_window, screen->glx_context);
181 unsigned compile_shader(GLenum type, const char *source)
188 shader = glCreateShader(type);
189 glShaderSource(shader, 1, &source, NULL);
190 glCompileShader(shader);
191 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
192 glGetShaderInfoLog(shader, sizeof(info_log), &length, info_log);
195 fprintf(stderr, "Shader compilation failed:\n%s\n", info_log);
196 glDeleteShader(shader);
200 printf("Shader info log:\n%s\n", info_log);
205 unsigned link_program(unsigned *shaders, unsigned nshaders)
213 program = glCreateProgram();
214 for(i=0; i<nshaders; ++i)
215 glAttachShader(program, shaders[i]);
216 glBindAttribLocation(program, 0, "vertex");
217 glBindAttribLocation(program, 1, "texture_coord");
218 glBindFragDataLocation(program, 0, "frag_color");
219 glLinkProgram(program);
221 glGetProgramiv(program, GL_LINK_STATUS, &status);
222 glGetProgramInfoLog(program, sizeof(info_log), &length, info_log);
225 fprintf(stderr, "Program link failed:\n%s\n", info_log);
226 glDeleteProgram(program);
230 printf("Program info log:\n%s\n", info_log);
235 int create_gl_resources(Compositor *compositor, CompositedScreen *screen)
239 use_gl(compositor, screen);
241 screen->shaders[0] = compile_shader(GL_VERTEX_SHADER, vshader);
242 screen->shaders[1] = compile_shader(GL_FRAGMENT_SHADER, fshader);
243 if(!screen->shaders[0] || !screen->shaders[1])
246 screen->program = link_program(screen->shaders, 2);
250 screen->geometry_loc = glGetUniformLocation(screen->program, "geometry");
252 glGenBuffers(1, &screen->window_vertex_buffer);
253 glBindBuffer(GL_ARRAY_BUFFER, screen->window_vertex_buffer);
254 glBufferData(GL_ARRAY_BUFFER, sizeof(window_vertices), window_vertices, GL_STATIC_DRAW);
256 stride = 4*sizeof(float);
257 glGenVertexArrays(1, &screen->window_vertex_array);
258 glBindVertexArray(screen->window_vertex_array);
259 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, stride, NULL);
260 glEnableVertexAttribArray(0);
261 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, (void *)(2*sizeof(float)));
262 glEnableVertexAttribArray(1);
263 glBindVertexArray(0);
265 glBindBuffer(GL_ARRAY_BUFFER, 0);
267 glGenTextures(1, &screen->fb_texture);
268 glBindTexture(GL_TEXTURE_2D, screen->fb_texture);
269 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, screen->width, screen->height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
270 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
271 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
272 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
273 glBindTexture(GL_TEXTURE_2D, 0);
275 glGenFramebuffers(1, &screen->framebuffer);
276 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, screen->framebuffer);
277 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, screen->fb_texture, 0);
278 glDepthMask(GL_FALSE);
279 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
284 CompositedWindow *find_window(CompositedScreen *screen, Window w)
288 for(i=0; i<screen->nwindows; ++i)
289 if(screen->windows[i].window==w)
290 return &screen->windows[i];
295 void create_window_pixmap(Compositor *compositor, CompositedScreen *screen, CompositedWindow *window)
302 glXDestroyPixmap(compositor->display, window->glx_pixmap);
303 XFreePixmap(compositor->display, window->pixmap);
307 attribs[i++] = GLX_TEXTURE_TARGET_EXT;
308 attribs[i++] = GLX_TEXTURE_2D_EXT;
309 attribs[i++] = GLX_TEXTURE_FORMAT_EXT;
310 attribs[i++] = GLX_TEXTURE_FORMAT_RGBA_EXT;
313 window->pixmap = XCompositeNameWindowPixmap(compositor->display, window->window);
314 window->glx_pixmap = glXCreatePixmap(compositor->display, screen->fbconfig, window->pixmap, attribs);
317 CompositedWindow *add_window(Compositor *compositor, CompositedScreen *screen, Window w)
319 CompositedWindow *window;
320 XWindowAttributes win_attr;
322 if(w==screen->root || w==screen->overlay)
325 if(!XGetWindowAttributes(compositor->display, w, &win_attr))
327 printf("XGetWindowAttributes failed; probably the window was already destroyed\n");
330 if(win_attr.class==InputOnly)
333 if(find_window(screen, w))
336 if(screen->nwindows==screen->windows_capacity)
338 screen->windows = (CompositedWindow *)realloc(screen->windows, (screen->windows_capacity+1)*sizeof(CompositedWindow));
339 ++screen->windows_capacity;
342 window = &screen->windows[screen->nwindows++];
345 window->x = win_attr.x;
346 window->y = win_attr.y;
347 window->width = win_attr.width;
348 window->height = win_attr.height;
349 window->border = win_attr.border_width;
350 window->map_state = win_attr.map_state;
352 window->damage = XDamageCreate(compositor->display, window->window, XDamageReportNonEmpty);
353 window->pixmap = None;
354 window->glx_pixmap = None;
356 XCompositeRedirectWindow(compositor->display, window->window, CompositeRedirectManual);
357 if(window->map_state==IsViewable)
358 create_window_pixmap(compositor, screen, window);
360 glGenTextures(1, &window->texture);
361 glBindTexture(GL_TEXTURE_2D, window->texture);
362 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
364 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
369 void remove_window(Compositor *compositor, CompositedScreen *screen, CompositedWindow *window, int destroyed)
373 glDeleteTextures(1, &window->texture);
376 XDamageDestroy(compositor->display, window->damage);
379 glXDestroyPixmap(compositor->display, window->glx_pixmap);
380 XFreePixmap(compositor->display, window->pixmap);
382 XCompositeUnredirectWindow(compositor->display, window->window, CompositeRedirectManual);
386 for(i=window-screen->windows; i<screen->nwindows; ++i)
387 screen->windows[i] = screen->windows[i+1];
390 CompositedWindow *reorder_window(CompositedScreen *screen, CompositedWindow *window, Window above)
393 CompositedWindow hold;
395 i = window-screen->windows;
398 for(j=0; j<screen->nwindows; ++j)
399 if(screen->windows[j].window==above)
402 if(j>=screen->nwindows || i==j+1)
415 screen->windows[i] = screen->windows[i+1];
420 screen->windows[i] = screen->windows[i-1];
422 screen->windows[j] = hold;
424 return &screen->windows[j];
427 CompositedScreen *find_screen_by_root(Compositor *compositor, Window root)
431 for(i=0; i<compositor->nscreens; ++i)
432 if(compositor->screens[i].root==root)
433 return &compositor->screens[i];
438 CompositedScreen *find_screen_by_window(Compositor *compositor, Window w)
442 for(i=0; i<compositor->nscreens; ++i)
443 for(j=0; j<compositor->screens[i].nwindows; ++j)
444 if(compositor->screens[i].windows[j].window==w)
445 return &compositor->screens[i];
450 void update_monitor_vertices(CompositedScreen *screen, CompositedMonitor *monitor)
455 unsigned short *index_data;
459 t = monitor->tessellation;
461 data_size = (t+1)*(t+1)*4*sizeof(float);
462 vertex_data = (float *)malloc(data_size);
471 v = vertex_data+(y*(t+1)+x)*4;
474 v[2] = (monitor->x+xf*monitor->width)/screen->width;
475 v[3] = (monitor->y+yf*monitor->height)/screen->height;
477 glBindBuffer(GL_ARRAY_BUFFER, monitor->vertex_buffer);
478 glBufferData(GL_ARRAY_BUFFER, data_size, vertex_data, GL_STATIC_DRAW);
479 glBindBuffer(GL_ARRAY_BUFFER, 0);
482 monitor->nelements = t*((t+1)*2+1)-1;
483 data_size = monitor->nelements*sizeof(unsigned short);
484 index_data = (unsigned short *)malloc(data_size);
489 index_data[i++] = 0xFFFF;
492 index_data[i++] = (y+1)*(t+1)+x;
493 index_data[i++] = y*(t+1)+x;
496 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, monitor->index_buffer);
497 glBufferData(GL_ELEMENT_ARRAY_BUFFER, data_size, index_data, GL_STATIC_DRAW);
498 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
502 int initialize_monitor(Compositor *compositor, CompositedScreen *screen, CompositedMonitor *monitor, XRRScreenResources *xrr_res, unsigned index)
504 XRROutputInfo *output;
509 output = XRRGetOutputInfo(compositor->display, xrr_res, xrr_res->outputs[index]);
510 monitor->enabled = !!output->crtc;
511 if(!monitor->enabled)
513 XRRFreeOutputInfo(output);
517 crtc = XRRGetCrtcInfo(compositor->display, xrr_res, output->crtc);
518 monitor->x = crtc->x;
519 monitor->y = crtc->y;
520 monitor->width = crtc->width;
521 monitor->height = crtc->height;
522 XRRFreeCrtcInfo(crtc);
523 XRRFreeOutputInfo(output);
525 glGenBuffers(2, buffers);
526 monitor->vertex_buffer = buffers[0];
527 monitor->index_buffer = buffers[1];
529 monitor->tessellation = 20;
530 update_monitor_vertices(screen, monitor);
531 stride = 4*sizeof(float);
533 glGenVertexArrays(1, &monitor->vertex_array);
534 glBindVertexArray(monitor->vertex_array);
535 glBindBuffer(GL_ARRAY_BUFFER, monitor->vertex_buffer);
536 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, stride, NULL);
537 glEnableVertexAttribArray(0);
538 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, (void *)(2*sizeof(float)));
539 glEnableVertexAttribArray(1);
540 glBindBuffer(GL_ARRAY_BUFFER, 0);
541 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, monitor->index_buffer);
542 glBindVertexArray(0);
547 int initialize_screen(Compositor *compositor, unsigned number)
549 CompositedScreen *screen;
550 const char *extensions;
555 XRRScreenResources *xrr_res;
561 screen = &compositor->screens[number];
562 screen->number = number;
564 extensions = glXQueryExtensionsString(compositor->display, screen->number);
565 if(!strstr(extensions, "GLX_ARB_create_context"))
566 return with_error("GLX_ARB_create_context is required");
567 if(!strstr(extensions, "GLX_EXT_texture_from_pixmap"))
568 return with_error("GLX_EXT_texture_from_pixmap is required");
570 screen->root = RootWindow(compositor->display, screen->number);
571 XSelectInput(compositor->display, screen->root, SubstructureNotifyMask);
572 screen->overlay = XCompositeGetOverlayWindow(compositor->display, screen->root);
573 XGetGeometry(compositor->display, screen->overlay, &dummy_root, &x, &y, &screen->width, &screen->height, &border, &depth);
574 XShapeCombineRectangles(compositor->display, screen->overlay, ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted);
576 if(!initialize_gl(compositor, screen))
579 if(!create_gl_resources(compositor, screen))
582 xrr_res = XRRGetScreenResources(compositor->display, screen->root);
583 screen->nmonitors = xrr_res->noutput;
584 screen->monitors = (CompositedMonitor *)malloc(screen->nmonitors*sizeof(CompositedMonitor));
585 for(i=0; i<screen->nmonitors; ++i)
586 if(!initialize_monitor(compositor, screen, &screen->monitors[i], xrr_res, i))
588 XRRFreeScreenResources(xrr_res);
590 XQueryTree(compositor->display, screen->root, &dummy_root, &dummy_parent, &children, &nchildren);
592 screen->windows = (CompositedWindow *)malloc(nchildren*sizeof(CompositedWindow));
593 screen->nwindows = 0;
594 screen->windows_capacity = nchildren;
596 for(i=0; i<nchildren; ++i)
597 add_window(compositor, screen, children[i]);
606 int initialize_compositor(Compositor *compositor)
614 compositor->display = XOpenDisplay(NULL);
615 if(!compositor->display)
616 return with_error("Could not open X display");
618 XSetErrorHandler(&x_error_handler);
620 if(!XCompositeQueryExtension(compositor->display, &event_base, &error_base))
621 return with_error("XComposite is required but was not found");
622 else if(!XCompositeQueryVersion(compositor->display, &major_ver, &minor_ver))
623 return with_error("Cannot determine XComposite version");
624 else if(major_ver==0 && minor_ver<3)
625 return with_error("XComposite 0.3 or later is required");
627 if(!glXQueryExtension(compositor->display, &event_base, &error_base))
628 return with_error("GLX is required but was not found");
629 else if(!glXQueryVersion(compositor->display, &major_ver, &minor_ver))
630 return with_error("Cannot determine GLX version");
631 else if(major_ver<1 || (major_ver==1 && minor_ver<4))
632 return with_error("GLX 1.4 or later is required");
634 if(!XDamageQueryExtension(compositor->display, &compositor->damage_event, &error_base))
635 return with_error("XDamage is required but was not found");
636 else if(!XDamageQueryVersion(compositor->display, &major_ver, &minor_ver))
637 return with_error("Cannot determine XDamage version");
639 return with_error("XDamage 1.0 or later is required");
641 if(!XShapeQueryExtension(compositor->display, &event_base, &error_base))
642 return with_error("XShape is required but was not found");
643 else if(!XShapeQueryVersion(compositor->display, &major_ver, &minor_ver))
644 return with_error("Cannot determine XShape version");
645 else if(major_ver<1 || (major_ver==1 && minor_ver<1))
646 return with_error("XShape 1.1 or later is required");
648 if(!XRRQueryExtension(compositor->display, &event_base, &error_base))
649 return with_error("XRandR is required but was not found");
650 else if(!XRRQueryVersion(compositor->display, &major_ver, &minor_ver))
651 return with_error("Cannot determine XRandR version");
652 else if(major_ver<1 || (major_ver==1 && minor_ver<2))
653 return with_error("XRandR 1.2 or later is required");
655 compositor->glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((unsigned char *)"glXCreateContextAttribsARB");
656 compositor->glXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)glXGetProcAddress((unsigned char *)"glXBindTexImageEXT");
657 compositor->glXReleaseTexImageEXT = (PFNGLXRELEASETEXIMAGEEXTPROC)glXGetProcAddress((unsigned char *)"glXReleaseTexImageEXT");
659 compositor->nscreens = ScreenCount(compositor->display);
660 compositor->screens = (CompositedScreen *)malloc(compositor->nscreens*sizeof(CompositedScreen));
661 for(i=0; i<compositor->nscreens; ++i)
662 if(!initialize_screen(compositor, i))
665 compositor->dirty = 1;
670 void shutdown_screen(Compositor *compositor, CompositedScreen *screen)
674 use_gl(compositor, screen);
676 for(i=0; i<screen->nwindows; ++i)
678 glDeleteTextures(1, &screen->windows[i].texture);
679 if(screen->windows[i].pixmap)
681 glXDestroyPixmap(compositor->display, screen->windows[i].glx_pixmap);
682 XFreePixmap(compositor->display, screen->windows[i].pixmap);
683 XDamageDestroy(compositor->display, screen->windows[i].damage);
687 glXMakeContextCurrent(compositor->display, 0, 0, NULL);
688 glXDestroyContext(compositor->display, screen->glx_context);
689 glXDestroyWindow(compositor->display, screen->glx_window);
690 XDestroyWindow(compositor->display, screen->render_window);
692 XCompositeReleaseOverlayWindow(compositor->display, screen->overlay);
694 free(screen->windows);
695 free(screen->monitors);
698 void shutdown_compositor(Compositor *compositor)
702 for(i=0; i<compositor->nscreens; ++i)
703 shutdown_screen(compositor, &compositor->screens[i]);
704 free(compositor->screens);
706 XCloseDisplay(compositor->display);
709 void mark_dirty(Compositor *compositor, CompositedScreen *screen)
711 compositor->dirty = 1;
715 void process_create_window_event(Compositor *compositor, XCreateWindowEvent *event)
717 CompositedScreen *screen;
719 if((screen = find_screen_by_root(compositor, event->parent)))
720 add_window(compositor, screen, event->window);
723 void process_destroy_window_event(Compositor *compositor, XDestroyWindowEvent *event)
725 CompositedScreen *screen;
726 CompositedWindow *window;
728 if((screen = find_screen_by_root(compositor, event->event)))
729 if((window = find_window(screen, event->window)))
730 remove_window(compositor, screen, window, 1);
733 void process_map_event(Compositor *compositor, XMapEvent *event)
735 CompositedScreen *screen;
736 CompositedWindow *window;
738 screen = find_screen_by_root(compositor, event->event);
742 window = find_window(screen, event->window);
746 window->map_state = IsViewable;
747 create_window_pixmap(compositor, screen, window);
749 mark_dirty(compositor, screen);
752 void process_unmap_event(Compositor *compositor, XUnmapEvent *event)
754 CompositedScreen *screen;
755 CompositedWindow *window;
757 screen = find_screen_by_root(compositor, event->event);
761 window = find_window(screen, event->window);
763 window->map_state = IsUnviewable;
765 mark_dirty(compositor, screen);
768 void process_reparent_event(Compositor *compositor, XReparentEvent *event)
770 CompositedScreen *screen;
771 CompositedWindow *window;
773 screen = find_screen_by_root(compositor, event->event);
777 if(event->parent==screen->root)
778 window = add_window(compositor, screen, event->window);
781 window = find_window(screen, event->window);
785 remove_window(compositor, screen, window, 0);
788 if(window && window->map_state==IsViewable)
789 mark_dirty(compositor, screen);
792 void process_configure_event(Compositor *compositor, XConfigureEvent *event)
794 CompositedScreen *screen;
795 CompositedWindow *window;
797 screen = find_screen_by_root(compositor, event->event);
801 window = find_window(screen, event->window);
805 window->x = event->x;
806 window->y = event->y;
807 if((unsigned)event->width!=window->width || (unsigned)event->height!=window->height || (unsigned)event->border_width!=window->border)
809 window->width = event->width;
810 window->height = event->height;
811 window->border = event->border_width;
812 create_window_pixmap(compositor, screen, window);
814 reorder_window(screen, window, event->above);
816 if(window->map_state==IsViewable)
817 mark_dirty(compositor, screen);
820 void process_damage_event(Compositor *compositor, XDamageNotifyEvent *event)
822 CompositedScreen *screen;
823 CompositedWindow *window;
825 screen = find_screen_by_window(compositor, event->drawable);
829 window = find_window(screen, event->drawable);
830 if(window->map_state==IsViewable)
831 mark_dirty(compositor, screen);
834 int process_event(Compositor *compositor)
837 if(compositor->dirty)
839 if(!XCheckMaskEvent(compositor->display, -1, &event))
843 XNextEvent(compositor->display, &event);
848 process_create_window_event(compositor, &event.xcreatewindow);
851 process_destroy_window_event(compositor, &event.xdestroywindow);
854 process_map_event(compositor, &event.xmap);
857 process_unmap_event(compositor, &event.xunmap);
860 process_reparent_event(compositor, &event.xreparent);
862 case ConfigureNotify:
863 process_configure_event(compositor, &event.xconfigure);
866 if(event.type==compositor->damage_event+XDamageNotify)
867 process_damage_event(compositor, (XDamageNotifyEvent *)&event);
869 printf("Event %d\n", event.type);
875 void refresh_screen(Compositor *compositor, CompositedScreen *screen)
879 use_gl(compositor, screen);
881 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, screen->framebuffer);
883 glClearColor(0.5f, 0.5f, 0.5f, 0.0f);
884 glClear(GL_COLOR_BUFFER_BIT);
886 glUseProgram(screen->program);
887 glBindVertexArray(screen->window_vertex_array);
888 for(i=0; i<screen->nwindows; ++i)
890 CompositedWindow *window = &screen->windows[i];
891 if(window->map_state!=IsViewable)
894 glBindTexture(GL_TEXTURE_2D, window->texture);
895 compositor->glXBindTexImageEXT(compositor->display, window->glx_pixmap, GLX_FRONT_LEFT_EXT, NULL);
896 glUniform4f(screen->geometry_loc,
897 (float)window->x/screen->width, (float)(screen->height-window->y-window->height)/screen->height,
898 (float)(window->width+2*window->border)/screen->width, (float)(window->height+2*window->border)/screen->height);
899 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
900 compositor->glXReleaseTexImageEXT(compositor->display, window->glx_pixmap, GLX_FRONT_LEFT_EXT);
901 XDamageSubtract(compositor->display, window->damage, None, None);
904 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
905 glClearColor(0.5f, 0.0f, 0.5f, 0.0f);
906 glClear(GL_COLOR_BUFFER_BIT);
907 glBindTexture(GL_TEXTURE_2D, screen->fb_texture);
908 glEnable(GL_PRIMITIVE_RESTART);
909 glPrimitiveRestartIndex(0xFFFF);
911 for(i=0; i<screen->nmonitors; ++i)
913 CompositedMonitor *monitor = &screen->monitors[i];
914 if(!monitor->enabled)
917 glUniform4f(screen->geometry_loc,
918 (float)monitor->x/screen->width, (float)monitor->y/screen->height,
919 (float)monitor->width/screen->width, (float)monitor->height/screen->height);
921 glBindVertexArray(monitor->vertex_array);
922 glDrawElements(GL_TRIANGLE_STRIP, monitor->nelements, GL_UNSIGNED_SHORT, NULL);
925 glXSwapBuffers(compositor->display, screen->glx_window);
930 void refresh_all_screens(Compositor *compositor)
934 for(i=0; i<compositor->nscreens; ++i)
936 CompositedScreen *screen = &compositor->screens[i];
938 refresh_screen(compositor, screen);
941 compositor->dirty = 0;
944 void sighandler(int sig)
946 terminate_requested = 1;
952 Compositor compositor;
954 signal(SIGINT, &sighandler);
955 signal(SIGTERM, &sighandler);
957 if(!initialize_compositor(&compositor))
960 while(!terminate_requested)
962 if(!process_event(&compositor))
963 refresh_all_screens(&compositor);
966 shutdown_compositor(&compositor);