11 #include <xcb/render.h>
16 void (*screen_paint)(d_screen_t *sc);
17 void (*screen_root_pixmap_change)(d_screen_t *sc);
18 void (*window_show)(d_window_t *w);
19 void (*window_zombie_dead)(d_window_t *w);
20 void (*window_resize)(d_window_t *w);
21 void (*window_opacity_change)(d_window_t *w);
23 xcb_render_pictformat_t root_format;
24 xcb_render_pictformat_t argb32_format;
25 xcb_render_query_pict_formats_reply_t *pict_formats;
26 xcb_render_picture_t overlay_picture;
27 xcb_render_picture_t overlay_buffer;
28 xcb_render_picture_t root_picture;
29 xcb_render_picture_t solid_bg;
31 xcb_xfixes_region_t all_region;
32 xcb_xfixes_region_t paint_region;
33 xcb_xfixes_region_t shadow_region;
41 xcb_render_picture_t picture;
42 xcb_render_picture_t shadow_picture;
43 xcb_xfixes_region_t paint_clip;
46 static void render_paint(d_screen_t *sc);
47 static void render_root_pixmap_change(d_screen_t *sc);
48 static void paint_root(d_screen_t *sc, data_t *d);
49 static void paint_window(d_window_t *window, data_t *d, window_data_t *wd,
50 gboolean opaque, int x, int y, int width,
51 int height, int bwidth);
52 static void paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
53 int x, int y, int width, int height, int bwidth);
54 static void render_update_shadow_picture(d_window_t *w, data_t *d,
56 static void render_update_picture(d_window_t *w, data_t *d, window_data_t *wd);
57 static void render_update_root_picture(d_screen_t *sc, data_t *d);
58 static void render_free_picture(d_window_t *w, window_data_t *wd);
59 static xcb_render_pictformat_t find_visual_format(data_t *d,
60 xcb_visualid_t visual);
61 static xcb_render_pictformat_t find_argb32_format(data_t *d);
62 static xcb_render_picture_t solid_picture(data_t *d, d_screen_t *sc,
63 uint16_t a, uint16_t r,
64 uint16_t g, uint16_t b);
66 static void render_window_show(d_window_t *window);
67 static void render_window_zombie_dead(d_window_t *window);
68 static void render_window_resize(d_window_t *window);
69 static void render_window_opacity_change(d_window_t *w);
72 render_init(d_screen_t *sc, int id)
74 xcb_render_query_pict_formats_cookie_t ck;
80 data_t *d = malloc(sizeof(data_t));
81 d->screen_paint = sc->screen_paint;
82 d->screen_root_pixmap_change = sc->screen_root_pixmap_change;
83 d->window_show = sc->window_show;
84 d->window_zombie_dead = sc->window_zombie_dead;
85 d->window_resize = sc->window_resize;
86 d->window_opacity_change = sc->window_opacity_change;
87 screen_add_plugin_data(sc, plugin_id, d);
89 sc->screen_paint = render_paint;
90 sc->screen_root_pixmap_change = render_root_pixmap_change;
91 sc->window_show = render_window_show;
92 sc->window_zombie_dead = render_window_zombie_dead;
93 sc->window_resize = render_window_resize;
94 sc->window_opacity_change = render_window_opacity_change;
96 ck = xcb_render_query_pict_formats_unchecked(sc->dpy->conn);
97 d->pict_formats = xcb_render_query_pict_formats_reply(sc->dpy->conn, ck,
100 d->root_format = find_visual_format(d, sc->super.root_visual);
101 d->argb32_format = find_argb32_format(d);
102 d->root_picture = XCB_NONE;
104 d->overlay_picture = xcb_generate_id(sc->dpy->conn);
105 xcb_render_create_picture(sc->dpy->conn,
106 d->overlay_picture, sc->overlay, d->root_format,
109 /* make the double buffer */
110 px = xcb_generate_id(sc->dpy->conn);
111 xcb_create_pixmap(sc->dpy->conn, sc->super.root_depth, px,
112 sc->super.root, sc->super.width_in_pixels,
113 sc->super.height_in_pixels);
114 d->overlay_buffer = xcb_generate_id(sc->dpy->conn);
115 xcb_render_create_picture(sc->dpy->conn, d->overlay_buffer, px,
116 d->root_format, 0, 0);
117 xcb_free_pixmap(sc->dpy->conn, px);
119 d->solid_bg = solid_picture(d, sc, 0xffff, 0x6060, 02020, 0x3030);
121 d->all_region = xcb_generate_id(sc->dpy->conn);
122 d->paint_region = xcb_generate_id(sc->dpy->conn);
123 d->shadow_region = xcb_generate_id(sc->dpy->conn);
125 rect.width = sc->super.width_in_pixels;
126 rect.height = sc->super.height_in_pixels;
127 xcb_xfixes_create_region(sc->dpy->conn, d->all_region, 1, &rect);
128 xcb_xfixes_create_region(sc->dpy->conn, d->paint_region, 1, &rect);
129 xcb_xfixes_create_region(sc->dpy->conn, d->shadow_region, 1, &rect);
131 d->shadowalpha = 0x3333; /* 20% */
137 render_free(d_screen_t *sc)
139 data_t *d = screen_find_plugin_data(sc, plugin_id);
140 free(d->pict_formats);
141 xcb_render_free_picture(sc->dpy->conn, d->solid_bg);
143 xcb_render_free_picture(sc->dpy->conn, d->root_picture);
144 xcb_render_free_picture(sc->dpy->conn, d->overlay_picture);
145 xcb_render_free_picture(sc->dpy->conn, d->overlay_buffer);
146 xcb_xfixes_destroy_region(sc->dpy->conn, d->all_region);
147 xcb_xfixes_destroy_region(sc->dpy->conn, d->paint_region);
148 xcb_xfixes_destroy_region(sc->dpy->conn, d->shadow_region);
150 screen_remove_plugin_data(sc, plugin_id);
154 render_next_timeout(struct d_screen *sc, struct timeval *tv)
162 render_timeout(struct d_screen *sc, const struct timeval *now)
168 render_window_free(d_window_t *w, window_data_t *wd)
170 render_free_picture(w, wd);
171 if (wd->shadow_picture) {
172 xcb_render_free_picture(w->sc->dpy->conn, wd->shadow_picture);
173 wd->shadow_picture = XCB_NONE;
179 render_window_show(d_window_t *w)
183 xcb_rectangle_t rect;
185 d = screen_find_plugin_data(w->sc, plugin_id);
190 wd = window_find_plugin_data(w, plugin_id);
192 render_window_free(w, wd);
194 wd = malloc(sizeof(window_data_t));
195 wd->picture = XCB_NONE;
197 wd->paint_clip = xcb_generate_id(w->sc->dpy->conn);
199 rect.width = rect.height = 1;
200 xcb_xfixes_create_region(w->sc->dpy->conn, wd->paint_clip, 1, &rect);
202 render_update_shadow_picture(w, d, wd);
204 window_add_plugin_data(w, plugin_id, wd);
208 render_window_zombie_dead(d_window_t *w)
213 d = screen_find_plugin_data(w->sc, plugin_id);
214 wd = window_find_plugin_data(w, plugin_id);
216 render_window_free(w, wd);
217 xcb_xfixes_destroy_region(w->sc->dpy->conn, wd->paint_clip);
218 window_remove_plugin_data(w, plugin_id);
222 d->window_zombie_dead(w);
225 static xcb_render_picture_t
226 solid_picture(data_t *d, d_screen_t *sc, uint16_t a, uint16_t r,
227 uint16_t g, uint16_t b)
230 xcb_render_picture_t picture;
231 xcb_render_color_t c;
232 const uint32_t vals = XCB_RENDER_REPEAT_NORMAL;
233 const xcb_rectangle_t rect = { 0, 0, 1, 1 };
235 pixmap = xcb_generate_id(sc->dpy->conn);
236 picture = xcb_generate_id(sc->dpy->conn);
238 xcb_create_pixmap(sc->dpy->conn, 32, pixmap, sc->super.root, 1, 1);
239 xcb_render_create_picture(sc->dpy->conn, picture, pixmap, d->argb32_format,
240 XCB_RENDER_CP_REPEAT, &vals);
247 xcb_render_fill_rectangles(sc->dpy->conn, XCB_RENDER_PICT_OP_SRC,
248 picture, c, 1, &rect);
249 xcb_free_pixmap(sc->dpy->conn, pixmap);
254 static xcb_render_pictformat_t
255 find_argb32_format(data_t *d)
257 xcb_render_pictforminfo_iterator_t it;
259 for (it = xcb_render_query_pict_formats_formats_iterator(d->pict_formats);
260 it.rem; xcb_render_pictforminfo_next(&it))
262 xcb_render_pictforminfo_t *format = it.data;
263 if (format->type == XCB_RENDER_PICT_TYPE_DIRECT) {
264 if (format->depth == 32 &&
265 format->direct.alpha_mask == 0xff &&
266 format->direct.red_mask == 0xff &&
267 format->direct.green_mask == 0xff &&
268 format->direct.blue_mask == 0xff &&
269 format->direct.alpha_shift == 24 &&
270 format->direct.red_shift == 16 &&
271 format->direct.green_shift == 8 &&
272 format->direct.blue_shift == 0)
279 static xcb_render_pictformat_t
280 find_visual_format(data_t *d, xcb_visualid_t visual)
282 xcb_render_pictscreen_iterator_t si;
283 xcb_render_pictdepth_iterator_t di;
284 xcb_render_pictvisual_iterator_t vi;
286 if (!visual) return XCB_NONE;
288 /* go through all the screens */
289 si = xcb_render_query_pict_formats_screens_iterator(d->pict_formats);
290 for (; si.rem; xcb_render_pictscreen_next(&si)) {
291 di = xcb_render_pictscreen_depths_iterator(si.data);
292 for (; di.rem; xcb_render_pictdepth_next(&di)) {
293 vi = xcb_render_pictdepth_visuals_iterator(di.data);
294 for (; vi.rem; xcb_render_pictvisual_next(&vi)) {
295 if (vi.data->visual == visual)
296 return vi.data->format;
304 render_free_picture(d_window_t *w, window_data_t *wd)
306 /* this might cause an error, oh well */
308 xcb_render_free_picture(w->sc->dpy->conn, wd->picture);
309 wd->picture = XCB_NONE;
314 render_update_shadow_picture(d_window_t *w, data_t *d, window_data_t *wd)
316 if (wd->shadow_picture)
317 xcb_render_free_picture(w->sc->dpy->conn, wd->shadow_picture);
318 wd->shadow_picture = solid_picture(d, w->sc,
320 window_get_opacity(w) / 0xffff,
325 render_update_root_picture(d_screen_t *sc, data_t *d)
329 px = screen_get_root_pixmap(sc);
331 d->root_picture = xcb_generate_id(sc->dpy->conn);
332 xcb_render_create_picture(sc->dpy->conn,
334 d->root_format, 0, NULL);
339 render_update_picture(d_window_t *w, data_t *d, window_data_t *wd)
343 px = window_get_pixmap(w);
344 //printf("got pixmap 0x%x\n", px);
346 xcb_render_pictformat_t format;
347 const uint32_t vals = XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS;
349 render_free_picture(w, wd);
351 wd->picture = xcb_generate_id(w->sc->dpy->conn);
352 format = find_visual_format(d, window_get_visual(w));
353 /* we don't need to check this. if it fails, we'll just be drawing
354 an invalid picture and creating some X errors but that's no big
356 xcb_render_create_picture(w->sc->dpy->conn,
357 wd->picture, px, format,
358 XCB_RENDER_CP_SUBWINDOW_MODE,
364 render_window_resize(d_window_t *w)
369 d = screen_find_plugin_data(w->sc, plugin_id);
370 wd = window_find_plugin_data(w, plugin_id);
376 render_free_picture(w, wd);
380 render_window_opacity_change(d_window_t *w)
385 d = screen_find_plugin_data(w->sc, plugin_id);
386 wd = window_find_plugin_data(w, plugin_id);
389 d->window_opacity_change(w);
392 render_update_shadow_picture(w, d, wd);
396 render_root_pixmap_change(d_screen_t *sc)
400 d = screen_find_plugin_data(sc, plugin_id);
401 if (d->root_picture) {
402 xcb_render_free_picture(sc->dpy->conn, d->root_picture);
403 d->root_picture = XCB_NONE;
407 d->screen_root_pixmap_change(sc);
411 render_paint(d_screen_t *sc)
413 data_t *d = screen_find_plugin_data(sc, plugin_id);
416 xcb_xfixes_copy_region(sc->dpy->conn, d->all_region, d->paint_region);
418 //printf("-- painting --\n");
419 for (it = list_top(sc->stacking); it; it = it->next) {
420 d_window_t *w = it->data;
421 int x, y, width, height, bwidth;
423 window_get_area(w, &x, &y, &width, &height, &bwidth);
425 if (!window_is_input_only(w) &&
426 (window_is_mapped(w) || window_is_zombie(w)) &&
427 x < sc->super.width_in_pixels &&
428 y < sc->super.height_in_pixels &&
429 x + width > 0 && y + height > 0)
431 gboolean opaque = !(window_is_argb(w) ||
432 window_get_opacity(w) < 0xffff);
435 wd = window_find_plugin_data(w, plugin_id);
438 paint_window(w, d, wd, opaque, x, y, width, height, bwidth);
440 /* remove this window from the paint region, as nothing is
441 above it, so nothing should draw to this space again */
442 xcb_xfixes_subtract_region(sc->dpy->conn, d->paint_region,
443 window_get_region(w),
445 xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
451 /* save the clip region, when drawing windows (and shadows)
452 below this window, they should use this clip region */
453 xcb_xfixes_copy_region(sc->dpy->conn, d->paint_region,
460 xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
465 for (it = list_bottom(sc->stacking); it; it = it->prev) {
466 d_window_t *w = it->data;
467 int x, y, width, height, bwidth;
469 window_get_area(w, &x, &y, &width, &height, &bwidth);
471 if (!window_is_input_only(w) &&
472 (window_is_mapped(w) || window_is_zombie(w)) &&
473 x < sc->super.width_in_pixels &&
474 y < sc->super.height_in_pixels &&
475 (x + width > 0 || x + width + d->xshadowoff > 0) &&
476 (y + height > 0 || y + height + d->yshadowoff > 0))
479 gboolean opaque = !(window_is_argb(w) ||
480 window_get_opacity(w) < 0xffff);
482 wd = window_find_plugin_data(w, plugin_id);
484 /* shape the shadow to the window */
485 xcb_xfixes_copy_region(sc->dpy->conn, window_get_region(w),
487 xcb_xfixes_translate_region(sc->dpy->conn, d->shadow_region,
488 d->xshadowoff, d->yshadowoff);
489 xcb_xfixes_intersect_region(sc->dpy->conn,
490 wd->paint_clip, d->shadow_region,
492 xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
496 paint_shadow(w, d, wd, x, y, width, height, bwidth);
499 /* use the clip region of the highest opaque window seen so
500 far, as nothing should be able to draw on top of that region
502 xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
506 paint_window(w, d, wd, opaque, x, y, width, height, bwidth);
511 xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
516 /* copy the double buffer to the overlay window */
517 xcb_render_composite(sc->dpy->conn,
518 XCB_RENDER_PICT_OP_SRC,
524 sc->super.width_in_pixels,
525 sc->super.height_in_pixels);
527 /* call the function we replaced in the chain */
532 paint_root(d_screen_t *sc, data_t *d)
534 xcb_render_picture_t src;
537 if (!d->root_picture)
538 render_update_root_picture(sc, d);
540 if (d->root_picture) {
541 src = d->root_picture;
542 op = XCB_RENDER_PICT_OP_SRC;
546 op = XCB_RENDER_PICT_OP_CLEAR;
549 xcb_render_composite(sc->dpy->conn,
556 sc->super.width_in_pixels,
557 sc->super.height_in_pixels);
561 paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque,
562 int x, int y, int width, int height, int bwidth)
564 xcb_render_picture_t alphamap;
567 render_update_picture(w, d, wd);
569 //printf("-- paint window 0x%x picture 0x%x --\n", w->id, wd->picture);
574 XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_SRC;
579 alphamap = solid_picture(d, w->sc, window_get_opacity(w), 0, 0, 0);
581 xcb_render_composite(w->sc->dpy->conn,
587 x, y, width + bwidth*2, height + bwidth *2);
592 paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
593 int x, int y, int width, int height, int bwidth)
595 xcb_render_composite(w->sc->dpy->conn,
596 XCB_RENDER_PICT_OP_OVER,
601 x+d->xshadowoff, y+d->yshadowoff,
602 width + bwidth*2, height + bwidth *2);