summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian <[email protected]>2008-04-03 16:36:07 -0600
committerBrian <[email protected]>2008-04-03 16:36:07 -0600
commit766f3a545ebb317d2115b9053a8fc13b49ceec12 (patch)
treec3323e7d2a06296b95f3d13668d910569f139ad5
parent124e1345c9ba4abe17bb04b8781ec0fe803eda7b (diff)
gallium: implement ycbcr->rgba tile conversion
-rw-r--r--src/gallium/auxiliary/util/p_tile.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/util/p_tile.c b/src/gallium/auxiliary/util/p_tile.c
index 287d7839812..c9a9c8f4f71 100644
--- a/src/gallium/auxiliary/util/p_tile.c
+++ b/src/gallium/auxiliary/util/p_tile.c
@@ -560,6 +560,69 @@ z24s8_get_tile_rgba(unsigned *src,
}
+/*** PIPE_FORMAT_YCBCR / PIPE_FORMAT_YCBCR_REV ***/
+
+/**
+ * Convert YCbCr (or YCrCb) to RGBA.
+ */
+static void
+ycbcr_get_tile_rgba(ushort *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride,
+ boolean rev)
+{
+ const float scale = 1.0f / 255.0f;
+ unsigned i, j;
+
+ /* we're assuming we're being asked for an even number of texels */
+ assert((w & 1) == 0);
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ /* do two texels at a time */
+ for (j = 0; j < w; j += 2, src += 2) {
+ const ushort t0 = src[0];
+ const ushort t1 = src[1];
+ const ubyte y0 = (t0 >> 8) & 0xff; /* luminance */
+ const ubyte y1 = (t1 >> 8) & 0xff; /* luminance */
+ ubyte cb, cr;
+ if (rev) {
+ cb = t1 & 0xff; /* chroma U */
+ cr = t0 & 0xff; /* chroma V */
+ }
+ else {
+ cb = t0 & 0xff; /* chroma U */
+ cr = t1 & 0xff; /* chroma V */
+ }
+ float r, g, b;
+
+ /* even pixel: y0,cr,cb */
+ r = 1.164 * (y0-16) + 1.596 * (cr-128);
+ g = 1.164 * (y0-16) - 0.813 * (cr-128) - 0.391 * (cb-128);
+ b = 1.164 * (y0-16) + 2.018 * (cb-128);
+ pRow[0] = r * scale;
+ pRow[1] = g * scale;
+ pRow[2] = b * scale;
+ pRow[3] = 1.0f;
+ pRow += 4;
+
+ /* odd pixel: use y1,cr,cb */
+ r = 1.164 * (y1-16) + 1.596 * (cr-128);
+ g = 1.164 * (y1-16) - 0.813 * (cr-128) - 0.391 * (cb-128);
+ b = 1.164 * (y1-16) + 2.018 * (cb-128);
+ pRow[0] = r * scale;
+ pRow[1] = g * scale;
+ pRow[2] = b * scale;
+ pRow[3] = 1.0f;
+ pRow += 4;
+
+ }
+ p += dst_stride;
+ }
+}
+
+
void
pipe_get_tile_rgba(struct pipe_context *pipe,
struct pipe_surface *ps,
@@ -622,6 +685,14 @@ pipe_get_tile_rgba(struct pipe_context *pipe,
case PIPE_FORMAT_Z24S8_UNORM:
z24s8_get_tile_rgba((unsigned *) packed, w, h, p, dst_stride);
break;
+ case PIPE_FORMAT_YCBCR:
+ assert((x & 1) == 0);
+ ycbcr_get_tile_rgba((ushort *) packed, w, h, p, dst_stride, FALSE);
+ break;
+ case PIPE_FORMAT_YCBCR_REV:
+ assert((x & 1) == 0);
+ ycbcr_get_tile_rgba((ushort *) packed, w, h, p, dst_stride, TRUE);
+ break;
default:
assert(0);
}