Re: Let's just build it and see how it works!
Brian Paul <brian-CdwZJljFklH+2FeEXyspIVaTQe2KTcn/@public.gmane.org>
| Newsgroups | gmane.comp.freedesktop.xserver |
|---|---|
| Organization | Tungsten Graphics, Inc. |
| Message-ID | <[email protected]> |
Keith Packard wrote: > Around 7 o'clock on Nov 26, Brian Paul wrote: > > >>>In particular, I >>>need per-component alpha compositing to display text on my LCD monitor, >>>and OpenGL just doesn't do that (yet). >> >>Keith, can you point me to the code which does this now? I have a >>strong hunch that you actually can pull this off with OpenGL as-is. > > > Yeah, I was reading through some of the GL compositing options wondering > if they weren't able to do this, either with multiple passes or some other > suitable kludge in the solid color case. > > Looks like the current specification is a bit light on the details > surrounding 'component-alpha', about the only information I could find was: > > "When the mask contains separate alpha values for each channel, the > alpha value resulting from the combination of that value with the source > alpha channel is used in the final image composition." > > Here's how it works. The fundemental pixel primitive in Render is: > > dst = (src IN mask) OP dst > > (OP is one of the Porter-Duff compositing operators like OVER) > > Normally, 'mask' is just a regular alpha channel, but with component-alpha > enabled, 'mask' has four separate alpha channels, one for each component. > This combined operation is not expressable as a sequence of primitive > operations with intermediate buffers because the (src IN mask) actually > has eight separate values (four components, plus four alpha values). > > The code which implements this fine operation is split across a few > functions in the 'fbcompose.c' file: > > http://freedesktop.org/cgi-bin/viewcvs.cgi/xserver/fb/fbcompose.c?rev=HEAD&cvsroot=xserver&content-type=text/vnd.viewcvs-markup > > The fbCombineMaskC function computes (src IN mask) value as two separate > four-channel values and the fbCombineOverC procedure uses that to place > that value OVER dst. > > I think the total lack of optimization should make this code relatively > easy to read, even as it sucks the life from my CPU as I type this email. Hmmm, I think it would take me a week or so to fully grasp that code. Anyway, in OpenGL the general equation for blending is: C = Cs * S EQ Cd * D Where: C = resulting (R,G,B,A) color Cs = source (R,G,B,A) factor S = incoming (R,G,B,A) color Cd = destination (R,G,B,A) factor D = destination/framebuffer (R,G,B,A) color EQ = the blend "equation" (add, subtract, etc) If the glyph you're drawing is a constant color (always true?) you can store the glyph color as the constant blend color (i.e. glBlendColor) and treat the per-R/G/B alpha values as the incoming RGB image. glBlendEquation(GL_FUNC_ADD); // the default glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR); glBlendColor(glyphR, glyphG, glyphB, 1.0); glDrawPixels(width, height, GL_RGB, type, glyphData); Pretty simple. -Brian