Re: Problem in cairo + xcb where alpha blending is cumulative (becoming more opaque with each render)
Ryan Flannery <[email protected]> Thu, 27 Sep 2018 00:28:08 -0400
| Newsgroups | gmane.comp.lib.cairo |
|---|---|
| Message-ID | <CAMgLCAhCvgPVmi9qTu1Vwr-UKs-bCZw8RiK9zzWBsFGQg0JOkw@mail.gmail.com> |
From what I can see, my issue boils down to CAIRO_OPERATOR_SOURCE not behaving as I would expect, with the use of an xcb backed surface. Namely, after doing a cairo_pop_group_to_source(), if I cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE), based on the docs I would expect the alpha channel to be copied from the intermediate pattern/surface as-is to the destination, with no blending. I actually observe this when the destination is *not* an xcb derived surface (I'm playing with a png one now, using the sample program I included). With an xcb backed surface like in my original program, setting the operator to CAIRO_OPERATOR_SOURCE results in a solid black background. Specifically, my case is this: // BEGIN render loop cairo_push_group(cairo); cairo_set_source_rgba(cairo, 0.8, 0, 0, 0.1); // draw (lots of) stuff // END render loop cairo_pop_group_to_source(cairo); cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); cairo_paint(cairo); // reset operator to CAIRO_OPERATOR_OVER xcb_flush(xcon); sleep(1); I've been looking into cairo-xcb / xcb specifics regarding this, but any cluesticks that could be provided would be appreciated. Cheers, -Ryan Hello, > I've recently been using cairo + xcb to build a new application. I've hit > a problem supporting transparency / alpha-blending, where I want to allow > users to set the background window with an alpha value and have the root > x11 window show through that. The raw transparency piece works fine and is > easy in cairo + xcb, but I'm struggling with my main render loop -- it > seems to add / accumulate the alpha values with each render, and doesn't > remove previously drawn content with alpha values. I have more details > below including a fully functioning prototype with my layout setup (also > below and in a gist), but here's what I've been trying after much > google'ing and searching the archives: > My main render loop looks roughly like this (and I understand why this > would accumulate opaqueness over time): > // BEGIN render loop > cairo_push_group(cairo); > clear_background(); > // draw (lots of) stuff > // END render loop > cairo_pop_group_to_source(cairo); > cairo_paint(cairo); > xcb_flush(xcon); > sleep(1); > where clear_background() is: > cairo_set_source_rgba(cairo, 0.8, 0, 0, 0.1); > cairo_paint(cairo); > With that loop, as-is, I can see why the alpha values are accumulating > with each render. > To compensate, I've tried the following based on the cairo site's > documentation, and browsing the archives, but with no success: > 1. cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); (and subsequent > resets to *_OVER) > I've tried this before the cairo_paint() at the END of the loop, as > well as in the BEGIN loop (both before and after the cairo_push_group()). > My understanding is that this copies the alpha from SOURCE as-is, > with no blending, but I'm not observing that in the results, regardless of > where I place it (and tweak the timing to confirm each step). > Use of it *always* results in a black background, which makes me > think I have something larger out-of-whack. > 2. I've looked at other operators, but none seem applicable (and I've > tested most in various setups like the above). > 3. Using cairo_mask() / cairo_mask_surface() when using > cairo_pop_group() (the raw one, returning a cairo_pattern_t) to render > after the pop, but that also fails. > My ultimate goals are basically these: > 1. Have the window always reset to a consistent background of rgba = > 0.8/0/0/0.1 > 2. Don't 'accumulate' alpha artifacts from the widgets drawn in the > loop each time > My sample code below illustrates what I'm trying and my setup. > It draws a 200 x 200 pixel window (at x,y = 200,200). > It has an initial background of rgba = 0.8/0/0/0.1, > and a 50x50 pixel green square in the top left (rgba=0/1/0/0.5). > Every second it redraws, and moves the square towards the bottom right. > IDEALLY: > 1. The background is *always* rgba = 0.8/0/0/0.1 > 2. Only one square (the most recent) is shown with rgba = 0/1/0/0.5 > BUT what I observe (trying lots of variants): > 1. The background gets more opaque with each render, eventually > becoming solid > 2. The previous renders of the green square persist and aren't cleared > The code is below, along with build instructions, and available at: > https://gist.github.com/ryanflannery/1649ce3dd45cb6e16088931262283386 > Note the example includes a great deal of XCB setup, including logic to > handle tiling window managers (my use case). I doubt that's of interest > here, but I'm including it for completeness (but below the main cairo > logic). > Any feedback appreciated (on this or other conventions I have!) > Cheers, > -Ryan -- cairo mailing list [email protected] https://lists.cairographics.org/mailman/listinfo/cairo