Ternary Raster Ops

From WineHQ Wiki
Revision as of 15:49, 25 January 2016 by RosanneDiMesio (Talk | contribs) (Initial import; some markup fixes)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Ternary raster operation codes define how the graphics device interface (GDI) combines the bits in a source bitmap with the bits in the destination bitmap.

Microsoft has some documentation on ternary raster operations ([1]), but it is incomplete. They list 256 valid ternary raster operations, each of which is composed of a 16 bit number in the high word, and an apparently random number in the low word.

While these are sufficient to specify any of the outcomes available to the raster operations, the bits in the low word are meaningful (although it seems Windows may no longer use them).

The high word is documented at the page shown above, so this page will deal with the low word.

This page assumes you have read and understand the Microsoft documentation linked above.

The bitwise format

Bits Purpose
0-4 Specify the order of arguments to the raster operation
5 Used to apply the NOT operator to the results of the other operations
6-7 The first boolean operator
8-9 The second boolean operator
a-b The third boolean operator
c-d The fourth boolean operator
e-f The fifth boolean operator

The order of arguments

Each raster operation uses values for S, D and P, but because there are 5 boolean operators available, there may be 6 arguments such that any of S, D or P may be repeated to make up the 6 arguments.

In the following table, where a "dot" appears, the first boolean operator will appear in the postfix raster operation description

Order bits value Order
0x00 SSSSSS
0x01 PPPPPP
0x02 DDDDDD
0x03
0x04 SPDSPD
0x05 PDSPDS
0x06 DSPDSP
0x07
0x08 SDPSDP
0x09 DPSDPS
0x0a PSDPSD
0x0b
0x0c
0x0d
0x0e
0x0f
0x10
0x11
0x12
0x13
0x14 SSP.DS
0x15 SP.DS
0x16
0x17
0x18 SSP.PD
0x19 SP.PD
0x1a
0x1b
0x1c SSD.PD
0x1d SD.PD
0x1e
0x1f

The boolean operators

The boolean operators are read from the value starting from the

Boolean operator bits Operator
0x0 Not (n)
0x1 Xor (x)
0x2 OR (o)
0x3 AND (a)

The final "Not" bit

The "Not" bit is actually an indicator of the number of boolean operations. If the number of boolean operations is even, this bit is set to 1. If the number of boolean operations is odd, this bit is set to zero.

When you read the boolean operations, you start at the first (in bits 6-7). As soon as you encounter one that is zero and is followed only by others that are zero, you stop. That gives you your provisional number of operations. So if all operations are zero, you have zero operations. If operations 2-5 are zero, you have one. If operations 3-5 are zero, you have two.

If the number of provisional operations does not correspond with the value of the "Not" bit, there must be another operation - that operation is the one with all zero bits, a "Not" operation.

Some examples

From the Microsoft page listed above we know that operation Dn has a low word value of 0x0009, made up as follows:

Bits 0-4 01001 0x9 Sequence DPSDPS
Bit 5 0 0 Odd number of operations
Bits 6-7 00 0x0 (no operator)
Bits 8-9 00 0x0 (no operator)
Bits a-b 00 0x0 (no operator)
Bits c-d 00 0x0 (no operator)
Bits e-f 00 0x0 (no operator)

Since there must be an odd number of operations, but the number of operations in specified is zero, there must be an even number. Therefore we must have a "NOT" operation. We then take the arguments from the sequence as needed (in this case we only need 1), giving "Dn".

There is another way to create the "Dn" operation - 0x0006:

Bits 0-4 00110 0x6 Sequence DSPDSP
Bit 5 0 0 Odd number of operations
Bits 6-7 00 0x0 (no operator)
Bits 8-9 00 0x0 (no operator)
Bits a-b 00 0x0 (no operator)
Bits c-d 00 0x0 (no operator)
Bits e-f 00 0x0 (no operator)

From the MSDN page, operation PDSPDaoxxn has the low word value 0x16c5, which decodes as follows:

Bits 0-4 00101 0x5 Sequence PDSPDS
Bit 5 0 0 Odd number of operations
Bits 6-7 11 0x3 And
Bits 8-9 10 0x2 Or
Bits a-b 01 0x1 Xor
Bits c-d 01 0x1 Xor
Bits e-f 00 0x0 (no operator)

Four operators are specified, so we need a fifth (which must be Not) since the Not bit shows an odd number of operations. Our operations are therefore aoxxn. This requires 5 input values taken from the sequence, hence PDSPDaoxxn

From the MSDN page, operation SSPxDSxoxn has a low word value of 0x1954, which decodes as follows:

Bits 0-4 10100 0x14 Sequence SSP.DS
Bit 5 0 0 Odd number of operations
Bits 6-7 01 0x1 Xor
Bits 8-9 01 0x1 Xor
Bits a-b 10 0x2 Or
Bits c-d 01 0x1 Xor
Bits e-f 00 0x0 (no operator)

Four operators are specified, so we need a fifth (which must be Not) since the Not bit shows an odd number of operations. Our operations are therefore xxoxn. This requires 5 values from the sequence. Note that the first operation goes where the "dot" is, giving us: SSPxDSxoxn.

From the MSDN page, operation PDSxnan has a low word value of 0x0c65, which decodes as follows:

Bits 0-4 00101 0x05 Sequence PDSPDS
Bit 5 1 1 Even number of operations
Bits 6-7 01 0x1 Xor
Bits 8-9 00 0x0 Not
Bits a-b 11 0x3 And
Bits c-d 00 0x0 (no operator)
Bits e-f 00 0x0 (no operator)

Three operators are specified, so we need a fourth (which must be Not) since the Not bit shows an even number of operations. Our operations are therefore xnan. This requires 3 values from the sequence, giving PDSxnan.

Summary

As you can see the low word of the raster operations does have meaning and is not just a set of random numbers. Many raster operations can be represented in more than one way, although MSDN only documents one way.

If you are implementing the raster operations, then decoding the low 16 bit value may be better than having a huge switch statement that picks a set of operations based on one of the 256 valid high word values.