}
-static void
-gen_colormask(uint colormask,
- struct spe_function *f,
- int fragRGBA_reg, int fbRGBA_reg)
-{
- /* We've got four 32-bit RGBA packed pixels in each of
- * fragRGBA_reg and fbRGBA_reg, not sets of floating-point
- * reds, greens, blues, and alphas.
- * */
-
- /* The color mask operation can prevent any set of color
- * components in the incoming fragment from being written to the frame
- * buffer; we do this by replacing the masked components of the
- * fragment with the frame buffer values.
- *
- * There are only 16 possibilities, with a unique mask for
- * each of the possibilities. (Technically, there are only 15
- * possibilities, since we shouldn't be called for the one mask
- * that does nothing, but the complete implementation is here
- * anyway to avoid confusion.)
- *
- * We implement this via a constant static array which we'll index
- * into to get the correct mask.
- *
- * We're dependent on the mask values being low-order bits,
- * with particular values for each bit; so we start with a
- * few assertions, which will fail if any of the values were
- * to change.
- */
- ASSERT(PIPE_MASK_R == 0x1);
- ASSERT(PIPE_MASK_G == 0x2);
- ASSERT(PIPE_MASK_B == 0x4);
- ASSERT(PIPE_MASK_A == 0x8);
-
- /* Here's the list of all possible colormasks, indexed by the
- * value of the combined mask specifier.
- */
- static const unsigned int colormasks[16] = {
- 0x00000000, /* 0: all colors masked */
- 0xff000000, /* 1: PIPE_MASK_R */
- 0x00ff0000, /* 2: PIPE_MASK_G */
- 0xffff0000, /* 3: PIPE_MASK_R | PIPE_MASK_G */
- 0x0000ff00, /* 4: PIPE_MASK_B */
- 0xff00ff00, /* 5: PIPE_MASK_R | PIPE_MASK_B */
- 0x00ffff00, /* 6: PIPE_MASK_G | PIPE_MASK_B */
- 0xffffff00, /* 7: PIPE_MASK_R | PIPE_MASK_G | PIPE_MASK_B */
- 0x000000ff, /* 8: PIPE_MASK_A */
- 0xff0000ff, /* 9: PIPE_MASK_R | PIPE_MASK_A */
- 0x00ff00ff, /* 10: PIPE_MASK_G | PIPE_MASK_A */
- 0xffff00ff, /* 11: PIPE_MASK_R | PIPE_MASK_G | PIPE_MASK_A */
- 0x0000ffff, /* 12: PIPE_MASK_B | PIPE_MASK_A */
- 0xff00ffff, /* 13: PIPE_MASK_R | PIPE_MASK_B | PIPE_MASK_A */
- 0x00ffffff, /* 14: PIPE_MASK_G | PIPE_MASK_B | PIPE_MASK_A */
- 0xffffffff /* 15: PIPE_MASK_R | PIPE_MASK_G | PIPE_MASK_B | PIPE_MASK_A */
- };
-
- /* Get a temporary register to hold the mask */
- int colormask_reg = spe_allocate_available_register(f);
-
- /* Look up the desired mask directly and load it into the mask register.
- * This will load the same mask into each of the four words in the
- * mask register.
- */
- spe_load_uint(f, colormask_reg, colormasks[colormask]);
-
- /* Use the mask register to select between the fragment color
- * values and the frame buffer color values. Wherever the
- * mask has a 0 bit, the current frame buffer color should override
- * the fragment color. Wherever the mask has a 1 bit, the
- * fragment color should persevere. The Select Bits (selb rt, rA, rB, rM)
- * instruction will select bits from its first operand rA wherever the
- * the mask bits rM are 0, and from its second operand rB wherever the
- * mask bits rM are 1. That means that the frame buffer color is the
- * first operand, and the fragment color the second.
- */
- spe_selb(f, fragRGBA_reg, fbRGBA_reg, fragRGBA_reg, colormask_reg);
-
- /* Release the temporary register and we're done */
- spe_release_register(f, colormask_reg);
-}
-
/**
* Generate code to pack a quad of float colors into four 32-bit integers.
*
spe_release_register(f, ba_reg);
}
+static void
+gen_colormask(struct spe_function *f,
+ uint colormask,
+ enum pipe_format color_format,
+ int fragRGBA_reg, int fbRGBA_reg)
+{
+ /* We've got four 32-bit RGBA packed pixels in each of
+ * fragRGBA_reg and fbRGBA_reg, not sets of floating-point
+ * reds, greens, blues, and alphas. Further, the pixels
+ * are packed according to the given color format, not
+ * necessarily RGBA...
+ */
+ unsigned int r_mask;
+ unsigned int g_mask;
+ unsigned int b_mask;
+ unsigned int a_mask;
+
+ /* Calculate exactly where the bits for any particular color
+ * end up, so we can mask them correctly.
+ */
+ switch(color_format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ /* ARGB */
+ a_mask = 0xff000000;
+ r_mask = 0x00ff0000;
+ g_mask = 0x0000ff00;
+ b_mask = 0x000000ff;
+ break;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ /* BGRA */
+ b_mask = 0xff000000;
+ g_mask = 0x00ff0000;
+ r_mask = 0x0000ff00;
+ a_mask = 0x000000ff;
+ break;
+ default:
+ ASSERT(0);
+ }
+ /* For each R, G, B, and A component we're supposed to mask out,
+ * clear its bits. Then our mask operation later will work
+ * as expected.
+ */
+ if (!(colormask & PIPE_MASK_R)) {
+ r_mask = 0;
+ }
+ if (!(colormask & PIPE_MASK_G)) {
+ g_mask = 0;
+ }
+ if (!(colormask & PIPE_MASK_B)) {
+ b_mask = 0;
+ }
+ if (!(colormask & PIPE_MASK_A)) {
+ a_mask = 0;
+ }
+
+ /* Get a temporary register to hold the mask that will be applied to the fragment */
+ int colormask_reg = spe_allocate_available_register(f);
+ /* The actual mask we're going to use is an OR of the remaining R, G, B, and A
+ * masks. Load the result value into our temporary register.
+ */
+ spe_load_uint(f, colormask_reg, r_mask | g_mask | b_mask | a_mask);
+
+ /* Use the mask register to select between the fragment color
+ * values and the frame buffer color values. Wherever the
+ * mask has a 0 bit, the current frame buffer color should override
+ * the fragment color. Wherever the mask has a 1 bit, the
+ * fragment color should persevere. The Select Bits (selb rt, rA, rB, rM)
+ * instruction will select bits from its first operand rA wherever the
+ * the mask bits rM are 0, and from its second operand rB wherever the
+ * mask bits rM are 1. That means that the frame buffer color is the
+ * first operand, and the fragment color the second.
+ */
+ spe_selb(f, fragRGBA_reg, fbRGBA_reg, fragRGBA_reg, colormask_reg);
+
+ /* Release the temporary register and we're done */
+ spe_release_register(f, colormask_reg);
+}
/**
* Generate SPE code to implement the fragment operations (alpha test,
}
if (blend->colormask != PIPE_MASK_RGBA) {
- gen_colormask(blend->colormask, f, rgba_reg, fbRGBA_reg);
+ gen_colormask(f, blend->colormask, color_format, rgba_reg, fbRGBA_reg);
}
spe_bi(f, SPE_REG_RA, 0, 0); /* return from function call */
-
spe_release_register(f, fbRGBA_reg);
spe_release_register(f, fbZS_reg);
spe_release_register(f, quad_offset_reg);