Understanding ternary raster operations


It’s perfectly logical, which doesn’t mean that it’s easy to understand.

A ternary raster operation describes how three boolean values should combine to form an output boolean. I was going to write up a description but found that the existing documentation pretty much covers it, so I refer you to that. In particular, look at the table that explains where PSo and DPSoo come from.

Now, one question that has come up is “What is the algorithm for deriving the RPN raster operation description string from the operation index?” The answer is, “You stare at it and use your brain’s power of pattern-matching.” There is no single “correct” expression of an operation index as RPN. For example, “DPSoo” could have been written as “DSPoo” or “DSoPo” or as the equivalent but pointlessly esoteric “DPoDnPnSaao”. All of these expressions have the same boolean truth table.

Comments (9)
  1. josh says:

    IMO the RPN string is completely useless. Just make a truth table for what you want and forget about the operation required.

    I #define a long list of ROP3_33, ROP3_8C, etc. so I can just use the number straight out of the truth table as well. (I also write the table sideways so it’s easier to read that way…)

    Same deal for binary raster ops.

  2. Mike says:

    I agree. The whole discussion about RPN really just obfuscates the whole thing. The first time I tried to find some non-standard rop I wasted a huge amount of time coming up with RPN forms and alternatives and trying to match them to the table. Just going by the truth table is much simpler.

  3. Sergey Vlasov says:

    I have found an old book "Writing Windows device drivers" by Daniel Norton, and was surprised to see that even the raster operation codes are not unique. E.g., the "DPSoo" you give as an example is encoded as 0x02a9 (this gives the 0x00FE02A9 value in the MSDN table), but if represented as "DSPoo", the same operation can be encoded as 0x02a6, or as 0x2a0 ("SPDoo"), or even as 0x02a5 ("PDSoo")…

    Probably there was some ordering between the alternative representations which gave the rule to choose one from them.

  4. E. Massey says:

    The ROP codes have always been a bit "mysterious" since there’s little detailed documentation about them. However, there used to be a MS knowledge base article titled "The Lower Order Word of 32-Bit ROP Codes" (Q74508) that explained the ROP codes in detail.

    I can’t find it online, but it’s part of the MSDN that came with VC++ 6.0.

    Some key points from this article:

    …only the higher-order word or most-significant word (MSW) of the 32-bit ROP code is explained. This word is an index in the ROP table. The use of the lower-order word or least-significant word (LSW) of the ROP code is not addressed in the Windows Device Development Kit (DDK).

    The LSW of the ROP code may be used by display drivers to assist in parsing the ROP. A complete explanation of the LSW of the ROP code can be found in the file COMMENT.BLT, which is included with the DDK display driver sample source code.

    The low-order word in and of itself does not contain enough information to generate the ROP code. What it contains is:

    1. An index specifying which predefined parse sting to use.

    2. Amount to rotate the parse string.

    3. Five logic operations.

    4. A parity bit used to imply a sixth logic operation of NOT. Pairs of trailing NOTs are discarded since they cancel.

    <pre>

    Example 1: 85, 0085 1E05, PDSPnoaxn,

    D = not ((((not P) or S) and D) xor P)

    1E08 = 00 01 11 10 00 0 001 01

    | | | | | | | |

    | | | | | | | |___ bias start by 1

    | | | | | | |______ use string 1

    | | | | | |_________ parity – no trailing NOT

    | | | | |____________ Logic operation #1 is a NOT

    | | | |_______________ Logic operation #2 is a OR

    | | |__________________ Logic operation #3 is a AND

    | |_____________________ Logic operation #4 is a XOR

    |________________________ Logic operation #5 is a NOT

    String #1 is defined as: SPDSPDSP

    After the bias, it will be: PDSPDSPS

    </pre>

  5. asdf says:

    Feng Yuan does a very detailed job describing the ROP code format in his Windows Graphics Programming book (among other things). I made an interactive ROP code truth table (javascript required) a while ago http://www.kkow.net/etep/docs/rop.html because looking up a ROP code in that MSDN table is really annoying and impossible to do in under a minute.

  6. I know how to use ternary raster operations, but I don’t think I know a situation where to use them. Could you give me some PRACTICAL examples or situations that use ternary raster operations?

  7. NickFitz says:

    @Tommy Carlier:

    An example from my days as a games programmer:

    Suppose a 32 bit word in display memory has value 0x12345678 where a pixel is 4 bits in size (16 colours was a lot in those days…) and you want to place part of a space invader on it without disturbing the parts of the background outside the invader. Assume that the invader word has value 0x00009876. Further asssume that you have a mask word corresponding to the visible pixels of the invader: 0x0000ffff.

    You can now get your piece of invader on the screen using

    screen AND (NOT mask) OR invader:

    0x12345678 (screen) AND

    0xffff0000 (NOT mask) OR

    0x00009876 (beastie)

    gives

    0x12349876

    Do that for a matrix of words on the screen and you have a menacing monster over a pretty background the graphics boys drew for you. If you want, you can extend the mask by one pixel around the sides of the monster, which gives it a black outline, helping it to stand out against the background. (The mask can also be used for collision detection, but that’s another story.)

    Just one example from the halcyon days of the ’80s :-)

  8. @NickFitz:

    That was a very practical example, thanks!

  9. Ben Hutchings says:

    I seem to remember reading (possibly even in this blog) that the GDI would dynamically generate machine code for specific blitter operations rather than using slow generic code to handle them all. At a guess, the low word of the ROP would be used to drive that code generator. For operations that can be performed by a hardware blitter (which is probably all of them with current hardware) it’s presumably useless.

Comments are closed.