Question with regards to componentAlpha
Thomas Roell <[email protected]> Fri, 13 Sep 2002 15:51:29 -0600 (MDT)
| Newsgroups | gmane.comp.xfree86.render |
|---|---|
| Message-ID | <[email protected]> |
While implementing the render-extension for our X-Server (Accelerated-X), we ran across a very convoluted problem with the specifiction: Consider the PictOpOver operation, here with some excepts from the spec: (I) dest = (source IN mask) OP dest (II) C = Ca * Fa + Cb * Fb (III) PictOp Fa Fb Over 1 1-Aa If one expands this now to all color channels it reads like this (componentAlpha not set): (IV) dest.b = (source.b IN mask.a) OVER dest.b dest.g = (source.g IN mask.a) OVER dest.g dest.r = (source.r IN mask.a) OVER dest.r dest.a = (source.a IN mask.a) OVER dest.a Or, using arithmetical terms: dest.b = (source.b * mask.a) * 1 + dest.b * (1 - source.a * mask.a) dest.g = (source.g * mask.a) * 1 + dest.g * (1 - source.a * mask.a) dest.r = (source.r * mask.a) * 1 + dest.r * (1 - source.a * mask.a) dest.a = (source.a * mask.a) * 1 + dest.a * (1 - source.a * mask.a) Now if componentAlpha is turned on, the spec says this: Whether the mask has a single alpha value for all four channels or whether each mask channel should affect the associated source/dest channels. This could be read in two ways. First off, in the original formula above that states how dest, source & mask are to be used, there are brackets. Hence if mask has now components it should do this: (V) dest.b = (source.b IN mask.b) OVER dest.b dest.g = (source.g IN mask.g) OVER dest.g dest.r = (source.r IN mask.r) OVER dest.r dest.a = (source.a IN mask.a) OVER dest.a Or, using arithmetical terms: dest.b = (source.b * mask.b) * 1 + dest.b * (1 - source.a * mask.a) dest.g = (source.g * mask.g) * 1 + dest.g * (1 - source.a * mask.a) dest.r = (source.r * mask.r) * 1 + dest.r * (1 - source.a * mask.a) dest.a = (source.a * mask.a) * 1 + dest.a * (1 - source.a * mask.a) The term (1 - source.a * mask.a) is used, as the specification (II),(III) clearly says that one is supposed to use the alpha channel or (source IN mask). On the other hand, the definition for componentAlpha says: "whether each mask channel should affect the associated source/dest channels" Now this could mean that instead of the (1 - Aa) value we should use (1 - Ca): (VI) dest.b = (source.b * mask.b) * 1 + dest.b * (1 - source.b * mask.b) dest.g = (source.g * mask.g) * 1 + dest.g * (1 - source.g * mask.g) dest.r = (source.r * mask.r) * 1 + dest.r * (1 - source.r * mask.r) dest.a = (source.a * mask.a) * 1 + dest.a * (1 - source.a * mask.a) As things get very tricky already, the XFree4.2 code in fbpict.c offer us yet another variant: (VII) dest.b = (source.b * mask.b) * 1 + dest.b * (1 - source.a * mask.b) dest.g = (source.g * mask.g) * 1 + dest.g * (1 - source.a * mask.g) dest.r = (source.r * mask.r) * 1 + dest.r * (1 - source.a * mask.r) dest.a = (source.a * mask.a) * 1 + dest.a * (1 - source.a * mask.a) This however contradicts the specification in applying (I). Even worse, unless "source" or "mask" is a constant it is not implementable in hardware reasonable (unless 2 passes are used). The question is now which of the three formulas (V), (VI) or (VII) is according to the spec and what the rationale is for which variant. - Thomas -- Thomas Roell /\ Das Reh sprint hoch, Xi Graphics / \/\ _ das Reh springt weit, [email protected] / / \ \ was soll es tun, / Oelch! \ \ es hat ja Zeit.