If these are individual glyphs I think you are going to have a problem if any glyphs extend outside the box defined by their escapement. Either these pixels will get clipped off, or portions of neighboring glyphs will get erased.

So I think you have to composite glyphs at some point as though they have transparent areas outside the ink.

However your idea could be used to then copy a temporary buffer containing all the glyphs to the final output as a 2-color image. The main advantage would be that the temporary buffer would be 1-channel rather than 3 or 4.

A plausable cairo api would be to be able to set the source to an image plus two colors which are the colors that 0 and 1 in that source image turn into. I think it has been proposed (or already exists?) that a "fade" color be able to be specified, this is used to render a colorized and partially transparent version of a source without another intermediate image. This would be the same as the 1 color, the 0 color would be a new addition.

The problem I see is that this probably adds a huge number of new compositing back-end functions. There would have to be variations depending on whether the source image is 1 or 3 or 4 channels, whether the colors are transparent, and for each compositing operation.

David Herrmann wrote:
Hi

While working on kmscon the main rendering task I am faced with is
blending a glyph into the main framebuffer with a constant foreground
and background color. The code I have been using is a per-pixel
blending operation on each color value:

For each pixel "i" I do:
  r = alpha[i] * foreground.r + (255 - alpha[i]) * background.r
  g = alpha[i] * foreground.g + (255 - alpha[i]) * background.g
  b = alpha[i] * foreground.b + (255 - alpha[i]) * background.b
  r /= 255;
  g /= 255;
  b /= 255;
  dst[i] = (r << 16) | (g << 8) | b;

So I have an 8bit alpha channel from the glyph as input and an xrgb32
output framebuffer. The 24bit foreground/background values are
constant during a single blending operation.

I already optimized this by special-casing alpha[i] == 0 or 255 and I
changed the division to 256 instead of 255. However, I was wondering
whether pixman can provide a better alternative. Unfortunately, the
fastest code I could come up with was (using shadow-buffer):

pixman_fill(shadow, background);
pixman_composite(OVER, foreground, alpha, shadow);
pixman_blt(shadow, dst);

I use a shadow buffer as I _really_ want to avoid to composite
directly into the hardware buffer (which is in most cases way slower
than the extra pixman_blt). However, this scenario requires writing
the data three times and even reading it during the composite
operation. But still, thanks to pixman-optimizations, this turns out
to be almost exactly as fast as my own trivial implementation. So I
was wondering whether anyone has ideas how to speed this up?

Is there a way to perform this operation with a single pixman call? If
not, are there any other optimizations I should consider?

The best renderer I could come up with creates an array with all
characters that need to be updated for the next frame and then does:

foreach(character as c) {
  foreach(line(c) as l) {
    foreach(alpha(l) as a) {
      dst[l, p] = composite(a, fg, bg);
    }
  }
}

And composite() does what I described above. This loop can also be found here:
https://github.com/dvdhrm/kmscon/blob/master/src/uterm_video_dumb.c#L371

I would be thankful for any hints how to optimize this.
Regards
David
_______________________________________________
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman
_______________________________________________
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman

Reply via email to