11 #include <xcb/render.h>
16 void (*screen_paint)(d_screen_t *sc);
17 void (*screen_root_pixmap_changed)(d_screen_t *sc);
18 void (*window_show)(d_window_t *w);
19 void (*window_hide)(d_window_t *w);
20 void (*window_resize)(d_window_t *w);
22 xcb_render_pictformat_t root_format;
23 xcb_render_pictformat_t argb32_format;
24 xcb_render_query_pict_formats_reply_t *pict_formats;
25 xcb_render_picture_t overlay_picture;
26 xcb_render_picture_t overlay_buffer;
27 xcb_render_picture_t root_picture;
28 xcb_render_picture_t solid_bg;
30 xcb_xfixes_region_t all_region;
31 xcb_xfixes_region_t paint_region;
32 xcb_xfixes_region_t shadow_region;
40 xcb_render_picture_t picture;
41 xcb_render_picture_t shadow_picture;
42 xcb_xfixes_region_t paint_clip;
45 static void render_paint(d_screen_t *sc);
46 static void render_root_pixmap_changed(d_screen_t *sc);
47 static void paint_root(d_screen_t *sc, data_t *d);
48 static void paint_window(d_window_t *window, data_t *d, window_data_t *wd,
50 static void paint_shadow(d_window_t *w, data_t *d, window_data_t *wd);
51 static void render_update_picture(d_window_t *w, data_t *d, window_data_t *wd);
52 static void render_update_root_picture(d_screen_t *sc, data_t *d);
53 static void render_free_picture(d_window_t *w, window_data_t *wd);
54 static xcb_render_pictformat_t find_visual_format(data_t *d,
55 xcb_visualid_t visual);
56 static xcb_render_pictformat_t find_argb32_format(data_t *d);
57 static xcb_render_picture_t solid_picture(data_t *d, d_screen_t *sc,
61 static void render_window_show(d_window_t *window);
62 static void render_window_hide(d_window_t *window);
63 static void render_window_resize(d_window_t *window);
66 render_init(d_screen_t *sc, int id)
68 xcb_render_query_pict_formats_cookie_t ck;
74 data_t *d = malloc(sizeof(data_t));
75 d->screen_paint = sc->screen_paint;
76 d->screen_root_pixmap_changed = sc->screen_root_pixmap_changed;
77 d->window_show = sc->window_show;
78 d->window_hide = sc->window_hide;
79 d->window_resize = sc->window_resize;
80 screen_add_plugin_data(sc, plugin_id, d);
82 sc->screen_paint = render_paint;
83 sc->screen_root_pixmap_changed = render_root_pixmap_changed;
84 sc->window_show = render_window_show;
85 sc->window_hide = render_window_hide;
86 sc->window_resize = render_window_resize;
88 ck = xcb_render_query_pict_formats_unchecked(sc->dpy->conn);
89 d->pict_formats = xcb_render_query_pict_formats_reply(sc->dpy->conn, ck,
92 d->root_format = find_visual_format(d, sc->super.root_visual);
93 d->argb32_format = find_argb32_format(d);
94 d->root_picture = XCB_NONE;
96 d->overlay_picture = xcb_generate_id(sc->dpy->conn);
97 xcb_render_create_picture(sc->dpy->conn,
98 d->overlay_picture, sc->overlay, d->root_format,
101 /* make the double buffer */
102 px = xcb_generate_id(sc->dpy->conn);
103 xcb_create_pixmap(sc->dpy->conn, sc->super.root_depth, px,
104 sc->super.root, sc->super.width_in_pixels,
105 sc->super.height_in_pixels);
106 d->overlay_buffer = xcb_generate_id(sc->dpy->conn);
107 xcb_render_create_picture(sc->dpy->conn, d->overlay_buffer, px,
108 d->root_format, 0, 0);
109 xcb_free_pixmap(sc->dpy->conn, px);
111 d->solid_bg = solid_picture(d, sc, 1.0, 0.0, 0.0, 0.0);
113 d->all_region = xcb_generate_id(sc->dpy->conn);
114 d->paint_region = xcb_generate_id(sc->dpy->conn);
115 d->shadow_region = xcb_generate_id(sc->dpy->conn);
117 rect.width = sc->super.width_in_pixels;
118 rect.height = sc->super.height_in_pixels;
119 xcb_xfixes_create_region(sc->dpy->conn, d->all_region, 1, &rect);
120 xcb_xfixes_create_region(sc->dpy->conn, d->paint_region, 1, &rect);
121 xcb_xfixes_create_region(sc->dpy->conn, d->shadow_region, 1, &rect);
123 d->shadowalpha = 0.2;
129 render_free(d_screen_t *sc)
131 data_t *d = screen_find_plugin_data(sc, plugin_id);
132 free(d->pict_formats);
133 xcb_render_free_picture(sc->dpy->conn, d->solid_bg);
135 xcb_render_free_picture(sc->dpy->conn, d->root_picture);
136 xcb_render_free_picture(sc->dpy->conn, d->overlay_picture);
137 xcb_render_free_picture(sc->dpy->conn, d->overlay_buffer);
138 xcb_xfixes_destroy_region(sc->dpy->conn, d->all_region);
139 xcb_xfixes_destroy_region(sc->dpy->conn, d->paint_region);
140 xcb_xfixes_destroy_region(sc->dpy->conn, d->shadow_region);
142 screen_remove_plugin_data(sc, plugin_id);
146 render_window_free(d_window_t *w, window_data_t *wd)
148 render_free_picture(w, wd);
149 if (wd->shadow_picture) {
150 xcb_render_free_picture(w->sc->dpy->conn, wd->shadow_picture);
151 wd->shadow_picture = XCB_NONE;
157 render_window_show(d_window_t *w)
161 xcb_rectangle_t rect;
163 d = screen_find_plugin_data(w->sc, plugin_id);
168 wd = window_find_plugin_data(w, plugin_id);
170 render_window_free(w, wd);
172 wd = malloc(sizeof(window_data_t));
173 wd->picture = XCB_NONE;
174 wd->shadow_picture = solid_picture(d, w->sc, d->shadowalpha,
177 wd->paint_clip = xcb_generate_id(w->sc->dpy->conn);
179 rect.width = rect.height = 1;
180 xcb_xfixes_create_region(w->sc->dpy->conn, wd->paint_clip, 1, &rect);
182 window_add_plugin_data(w, plugin_id, wd);
188 render_window_hide(d_window_t *w)
193 d = screen_find_plugin_data(w->sc, plugin_id);
194 wd = window_find_plugin_data(w, plugin_id);
196 render_window_free(w, wd);
197 xcb_xfixes_destroy_region(w->sc->dpy->conn, wd->paint_clip);
198 window_remove_plugin_data(w, plugin_id);
205 static xcb_render_picture_t
206 solid_picture(data_t *d, d_screen_t *sc,
207 double a, double r, double g, double b)
210 xcb_render_picture_t picture;
211 xcb_render_color_t c;
212 const uint32_t vals = XCB_RENDER_REPEAT_NORMAL;
213 const xcb_rectangle_t rect = { 0, 0, 1, 1 };
215 pixmap = xcb_generate_id(sc->dpy->conn);
216 picture = xcb_generate_id(sc->dpy->conn);
218 xcb_create_pixmap(sc->dpy->conn, 32, pixmap, sc->super.root, 1, 1);
219 xcb_render_create_picture(sc->dpy->conn, picture, pixmap, d->argb32_format,
220 XCB_RENDER_CP_REPEAT, &vals);
222 c.alpha = a * 0xffff;
224 c.green = g * 0xffff;
227 xcb_render_fill_rectangles(sc->dpy->conn, XCB_RENDER_PICT_OP_SRC,
228 picture, c, 1, &rect);
229 xcb_free_pixmap(sc->dpy->conn, pixmap);
234 static xcb_render_pictformat_t
235 find_argb32_format(data_t *d)
237 xcb_render_pictforminfo_iterator_t it;
239 for (it = xcb_render_query_pict_formats_formats_iterator(d->pict_formats);
240 it.rem; xcb_render_pictforminfo_next(&it))
242 xcb_render_pictforminfo_t *format = it.data;
243 if (format->type == XCB_RENDER_PICT_TYPE_DIRECT) {
244 if (format->depth == 32 &&
245 format->direct.alpha_mask == 0xff &&
246 format->direct.red_mask == 0xff &&
247 format->direct.green_mask == 0xff &&
248 format->direct.blue_mask == 0xff &&
249 format->direct.alpha_shift == 24 &&
250 format->direct.red_shift == 16 &&
251 format->direct.green_shift == 8 &&
252 format->direct.blue_shift == 0)
259 static xcb_render_pictformat_t
260 find_visual_format(data_t *d, xcb_visualid_t visual)
262 xcb_render_pictscreen_iterator_t si;
263 xcb_render_pictdepth_iterator_t di;
264 xcb_render_pictvisual_iterator_t vi;
266 if (!visual) return XCB_NONE;
268 /* go through all the screens */
269 si = xcb_render_query_pict_formats_screens_iterator(d->pict_formats);
270 for (; si.rem; xcb_render_pictscreen_next(&si)) {
271 di = xcb_render_pictscreen_depths_iterator(si.data);
272 for (; di.rem; xcb_render_pictdepth_next(&di)) {
273 vi = xcb_render_pictdepth_visuals_iterator(di.data);
274 for (; vi.rem; xcb_render_pictvisual_next(&vi)) {
275 if (vi.data->visual == visual)
276 return vi.data->format;
284 render_free_picture(d_window_t *w, window_data_t *wd)
286 /* this might cause an error, oh well */
288 xcb_render_free_picture(w->sc->dpy->conn, wd->picture);
289 wd->picture = XCB_NONE;
294 render_update_root_picture(d_screen_t *sc, data_t *d)
298 px = screen_get_root_pixmap(sc);
300 d->root_picture = xcb_generate_id(sc->dpy->conn);
301 xcb_render_create_picture_checked(sc->dpy->conn,
303 d->root_format, 0, NULL);
308 render_update_picture(d_window_t *w, data_t *d, window_data_t *wd)
312 px = window_get_pixmap(w);
313 //printf("got pixmap 0x%x\n", px);
315 xcb_render_pictformat_t format;
316 const uint32_t vals = XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS;
318 render_free_picture(w, wd);
320 wd->picture = xcb_generate_id(w->sc->dpy->conn);
321 format = find_visual_format(d, window_get_visual(w));
322 /* we don't need to check this. if it fails, we'll just be drawing
323 an invalid picture and creating some X errors but that's no big
325 xcb_render_create_picture(w->sc->dpy->conn,
326 wd->picture, px, format,
327 XCB_RENDER_CP_SUBWINDOW_MODE,
333 render_window_resize(d_window_t *w)
338 d = screen_find_plugin_data(w->sc, plugin_id);
339 wd = window_find_plugin_data(w, plugin_id);
345 render_free_picture(w, wd);
349 render_root_pixmap_changed(d_screen_t *sc)
353 d = screen_find_plugin_data(sc, plugin_id);
354 if (d->root_picture) {
355 xcb_render_free_picture(sc->dpy->conn, d->root_picture);
356 d->root_picture = XCB_NONE;
360 d->screen_root_pixmap_changed(sc);
364 render_paint(d_screen_t *sc)
366 data_t *d = screen_find_plugin_data(sc, plugin_id);
369 xcb_xfixes_copy_region(sc->dpy->conn, d->all_region, d->paint_region);
371 //printf("-- painting --\n");
372 for (it = list_top(sc->stacking); it; it = it->next) {
373 d_window_t *w = it->data;
375 if (!window_is_input_only(w) && window_is_mapped(w)) {
376 gboolean opaque = !window_is_argb(w);
379 wd = window_find_plugin_data(w, plugin_id);
383 paint_window(w, d, wd, opaque);
385 /* remove this window from the paint region, as nothing is
386 above it, so nothing should draw to this space again */
387 xcb_xfixes_subtract_region(sc->dpy->conn, d->paint_region,
388 window_get_region(w),
390 xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
396 /* save the clip region, when drawing windows (and shadows)
397 below this window, they should use this clip region */
398 xcb_xfixes_copy_region(sc->dpy->conn, d->paint_region,
405 xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
410 for (it = list_bottom(sc->stacking); it; it = it->prev) {
411 d_window_t *w = it->data;
413 if (!window_is_input_only(w) && window_is_mapped(w)) {
415 gboolean opaque = !window_is_argb(w);
417 wd = window_find_plugin_data(w, plugin_id);
419 /* shape the shadow to the window */
420 xcb_xfixes_copy_region(sc->dpy->conn, window_get_region(w),
422 xcb_xfixes_translate_region(sc->dpy->conn, d->shadow_region,
423 d->xshadowoff, d->yshadowoff);
424 xcb_xfixes_intersect_region(sc->dpy->conn,
425 wd->paint_clip, d->shadow_region,
427 xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
431 paint_shadow(w, d, wd);
434 /* use the clip region of the highest opaque window seen so
435 far, as nothing should be able to draw on top of that region
437 xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
441 paint_window(w, d, wd, opaque);
446 xcb_xfixes_set_picture_clip_region(sc->dpy->conn,
451 /* copy the double buffer to the overlay window */
452 xcb_render_composite(sc->dpy->conn,
453 XCB_RENDER_PICT_OP_SRC,
459 sc->super.width_in_pixels,
460 sc->super.height_in_pixels);
462 /* call the function we replaced in the chain */
467 paint_root(d_screen_t *sc, data_t *d)
469 xcb_render_picture_t src;
472 if (!d->root_picture)
473 render_update_root_picture(sc, d);
475 if (d->root_picture) {
476 src = d->root_picture;
477 op = XCB_RENDER_PICT_OP_SRC;
481 op = XCB_RENDER_PICT_OP_CLEAR;
483 xcb_render_composite(sc->dpy->conn,
490 sc->super.width_in_pixels,
491 sc->super.height_in_pixels);
495 paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque)
498 render_update_picture(w, d, wd);
500 //printf("-- paint window 0x%x picture 0x%x --\n", w->id, wd->picture);
502 int x, y, width, height, bwidth;
505 window_get_area(w, &x, &y, &width, &height, &bwidth);
507 XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_SRC;
509 xcb_render_composite(w->sc->dpy->conn,
515 x, y, width + bwidth*2, height + bwidth *2);
520 paint_shadow(d_window_t *w, data_t *d, window_data_t *wd)
522 int x, y, width, height, bwidth;
524 window_get_area(w, &x, &y, &width, &height, &bwidth);
525 xcb_render_composite(w->sc->dpy->conn,
526 XCB_RENDER_PICT_OP_OVER,
531 x+d->xshadowoff, y+d->yshadowoff,
532 width + bwidth*2, height + bwidth *2);