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 for(i=0; i<screen->nmonitors; ++i)
688 if(screen->monitors[i].enabled)
690 glDeleteBuffers(1, &screen->monitors[i].vertex_buffer);
691 glDeleteBuffers(1, &screen->monitors[i].index_buffer);
692 glDeleteVertexArrays(1, &screen->monitors[i].vertex_array);
695 glDeleteBuffers(1, &screen->window_vertex_buffer);
696 glDeleteVertexArrays(1, &screen->window_vertex_array);
697 glDeleteFramebuffers(1, &screen->framebuffer);
698 glDeleteTextures(1, &screen->fb_texture);
699 glDeleteProgram(screen->program);
700 glDeleteShader(screen->shaders[0]);
701 glDeleteShader(screen->shaders[1]);
703 glXMakeContextCurrent(compositor->display, 0, 0, NULL);
704 glXDestroyContext(compositor->display, screen->glx_context);
705 glXDestroyWindow(compositor->display, screen->glx_window);
706 XDestroyWindow(compositor->display, screen->render_window);
708 XCompositeReleaseOverlayWindow(compositor->display, screen->overlay);
710 free(screen->windows);
711 free(screen->monitors);
714 void shutdown_compositor(Compositor *compositor)
718 for(i=0; i<compositor->nscreens; ++i)
719 shutdown_screen(compositor, &compositor->screens[i]);
720 free(compositor->screens);
722 XCloseDisplay(compositor->display);
725 void mark_dirty(Compositor *compositor, CompositedScreen *screen)
727 compositor->dirty = 1;
731 void process_create_window_event(Compositor *compositor, XCreateWindowEvent *event)
733 CompositedScreen *screen;
735 if((screen = find_screen_by_root(compositor, event->parent)))
736 add_window(compositor, screen, event->window);
739 void process_destroy_window_event(Compositor *compositor, XDestroyWindowEvent *event)
741 CompositedScreen *screen;
742 CompositedWindow *window;
744 if((screen = find_screen_by_root(compositor, event->event)))
745 if((window = find_window(screen, event->window)))
746 remove_window(compositor, screen, window, 1);
749 void process_map_event(Compositor *compositor, XMapEvent *event)
751 CompositedScreen *screen;
752 CompositedWindow *window;
754 screen = find_screen_by_root(compositor, event->event);
758 window = find_window(screen, event->window);
762 window->map_state = IsViewable;
763 create_window_pixmap(compositor, screen, window);
765 mark_dirty(compositor, screen);
768 void process_unmap_event(Compositor *compositor, XUnmapEvent *event)
770 CompositedScreen *screen;
771 CompositedWindow *window;
773 screen = find_screen_by_root(compositor, event->event);
777 window = find_window(screen, event->window);
779 window->map_state = IsUnviewable;
781 mark_dirty(compositor, screen);
784 void process_reparent_event(Compositor *compositor, XReparentEvent *event)
786 CompositedScreen *screen;
787 CompositedWindow *window;
789 screen = find_screen_by_root(compositor, event->event);
793 if(event->parent==screen->root)
794 window = add_window(compositor, screen, event->window);
797 window = find_window(screen, event->window);
801 remove_window(compositor, screen, window, 0);
804 if(window && window->map_state==IsViewable)
805 mark_dirty(compositor, screen);
808 void process_configure_event(Compositor *compositor, XConfigureEvent *event)
810 CompositedScreen *screen;
811 CompositedWindow *window;
813 screen = find_screen_by_root(compositor, event->event);
817 window = find_window(screen, event->window);
821 window->x = event->x;
822 window->y = event->y;
823 if((unsigned)event->width!=window->width || (unsigned)event->height!=window->height || (unsigned)event->border_width!=window->border)
825 window->width = event->width;
826 window->height = event->height;
827 window->border = event->border_width;
828 create_window_pixmap(compositor, screen, window);
830 reorder_window(screen, window, event->above);
832 if(window->map_state==IsViewable)
833 mark_dirty(compositor, screen);
836 void process_damage_event(Compositor *compositor, XDamageNotifyEvent *event)
838 CompositedScreen *screen;
839 CompositedWindow *window;
841 screen = find_screen_by_window(compositor, event->drawable);
845 window = find_window(screen, event->drawable);
846 if(window->map_state==IsViewable)
847 mark_dirty(compositor, screen);
850 int process_event(Compositor *compositor)
853 if(compositor->dirty)
855 if(!XCheckMaskEvent(compositor->display, -1, &event))
859 XNextEvent(compositor->display, &event);
864 process_create_window_event(compositor, &event.xcreatewindow);
867 process_destroy_window_event(compositor, &event.xdestroywindow);
870 process_map_event(compositor, &event.xmap);
873 process_unmap_event(compositor, &event.xunmap);
876 process_reparent_event(compositor, &event.xreparent);
878 case ConfigureNotify:
879 process_configure_event(compositor, &event.xconfigure);
882 if(event.type==compositor->damage_event+XDamageNotify)
883 process_damage_event(compositor, (XDamageNotifyEvent *)&event);
885 printf("Event %d\n", event.type);
891 void refresh_screen(Compositor *compositor, CompositedScreen *screen)
895 use_gl(compositor, screen);
897 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, screen->framebuffer);
899 glClearColor(0.5f, 0.5f, 0.5f, 0.0f);
900 glClear(GL_COLOR_BUFFER_BIT);
902 glUseProgram(screen->program);
903 glBindVertexArray(screen->window_vertex_array);
904 for(i=0; i<screen->nwindows; ++i)
906 CompositedWindow *window = &screen->windows[i];
907 if(window->map_state!=IsViewable)
910 glBindTexture(GL_TEXTURE_2D, window->texture);
911 compositor->glXBindTexImageEXT(compositor->display, window->glx_pixmap, GLX_FRONT_LEFT_EXT, NULL);
912 glUniform4f(screen->geometry_loc,
913 (float)window->x/screen->width, ((float)screen->height-window->y-window->height)/screen->height,
914 (float)(window->width+2*window->border)/screen->width, (float)(window->height+2*window->border)/screen->height);
915 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
916 compositor->glXReleaseTexImageEXT(compositor->display, window->glx_pixmap, GLX_FRONT_LEFT_EXT);
917 XDamageSubtract(compositor->display, window->damage, None, None);
920 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
921 glClearColor(0.5f, 0.0f, 0.5f, 0.0f);
922 glClear(GL_COLOR_BUFFER_BIT);
923 glBindTexture(GL_TEXTURE_2D, screen->fb_texture);
924 glEnable(GL_PRIMITIVE_RESTART);
925 glPrimitiveRestartIndex(0xFFFF);
927 for(i=0; i<screen->nmonitors; ++i)
929 CompositedMonitor *monitor = &screen->monitors[i];
930 if(!monitor->enabled)
933 glUniform4f(screen->geometry_loc,
934 (float)monitor->x/screen->width, (float)monitor->y/screen->height,
935 (float)monitor->width/screen->width, (float)monitor->height/screen->height);
937 glBindVertexArray(monitor->vertex_array);
938 glDrawElements(GL_TRIANGLE_STRIP, monitor->nelements, GL_UNSIGNED_SHORT, NULL);
941 glXSwapBuffers(compositor->display, screen->glx_window);
946 void refresh_all_screens(Compositor *compositor)
950 for(i=0; i<compositor->nscreens; ++i)
952 CompositedScreen *screen = &compositor->screens[i];
954 refresh_screen(compositor, screen);
957 compositor->dirty = 0;
960 void sighandler(int sig)
962 terminate_requested = 1;
968 Compositor compositor;
970 signal(SIGINT, &sighandler);
971 signal(SIGTERM, &sighandler);
973 if(!initialize_compositor(&compositor))
976 while(!terminate_requested)
978 if(!process_event(&compositor))
979 refresh_all_screens(&compositor);
982 shutdown_compositor(&compositor);