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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.