Support typed YUV allocations

Change-Id: I844051ee1be1462e497d238f5460f301be1aaa1d
diff --git a/cpu_ref/rsCpuIntrinsicYuvToRGB.cpp b/cpu_ref/rsCpuIntrinsicYuvToRGB.cpp
index 946d1ba..bb8cde1 100644
--- a/cpu_ref/rsCpuIntrinsicYuvToRGB.cpp
+++ b/cpu_ref/rsCpuIntrinsicYuvToRGB.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -108,12 +108,13 @@
         ALOGE("YuvToRGB executed without input, skipping");
         return;
     }
-    const uchar *pin = (const uchar *)cp->alloc->mHal.drvState.lod[0].mallocPtr;
-    const size_t stride = cp->alloc->mHal.drvState.lod[0].stride;
+    const uchar *pinY = (const uchar *)cp->alloc->mHal.drvState.lod[0].mallocPtr;
+    const uchar *pinUV = (const uchar *)cp->alloc->mHal.drvState.lod[1].mallocPtr;
+    const size_t strideY = cp->alloc->mHal.drvState.lod[0].stride;
+    const size_t strideUV = cp->alloc->mHal.drvState.lod[1].stride;
 
-    const uchar *Y = pin + (p->y * p->dimX);
-    const uchar *uv = pin + (p->dimX * p->dimY);
-    uv += (p->y>>1) * p->dimX;
+    const uchar *Y = pinY + (p->y * strideY);
+    const uchar *uv = pinUV + ((p->y >> 1) * strideUV);
 
     uchar4 *out = (uchar4 *)p->out;
     uint32_t x1 = xstart;
diff --git a/driver/rsdAllocation.cpp b/driver/rsdAllocation.cpp
index b618536..7828baf 100644
--- a/driver/rsdAllocation.cpp
+++ b/driver/rsdAllocation.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -272,7 +272,38 @@
             if (ty > 1) ty >>= 1;
             if (tz > 1) tz >>= 1;
         }
+    } else if (alloc->mHal.state.yuv) {
+        // YUV only supports basic 2d
+        // so we can stash the plane pointers in the mipmap levels.
+        switch(alloc->mHal.state.yuv) {
+        case HAL_PIXEL_FORMAT_YV12:
+            offsets[1] = o;
+            alloc->mHal.drvState.lod[1].dimX = alloc->mHal.drvState.lod[0].dimX / 2;
+            alloc->mHal.drvState.lod[1].dimY = alloc->mHal.drvState.lod[0].dimY / 2;
+            alloc->mHal.drvState.lod[1].stride = rsRound(alloc->mHal.drvState.lod[1].dimX *
+                                                  type->getElementSizeBytes(), 16);
+            o += alloc->mHal.drvState.lod[1].stride * alloc->mHal.drvState.lod[1].dimY;
+            offsets[2] = o;
+            alloc->mHal.drvState.lod[2].dimX = alloc->mHal.drvState.lod[1].dimX;
+            alloc->mHal.drvState.lod[2].dimY = alloc->mHal.drvState.lod[1].dimY;
+            alloc->mHal.drvState.lod[2].stride = alloc->mHal.drvState.lod[1].stride;
+            o += alloc->mHal.drvState.lod[2].stride * alloc->mHal.drvState.lod[2].dimY;
+            alloc->mHal.drvState.lodCount = 3;
+            break;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:  // NV21
+            offsets[1] = o;
+            alloc->mHal.drvState.lod[1].dimX = alloc->mHal.drvState.lod[0].dimX;
+            alloc->mHal.drvState.lod[1].dimY = alloc->mHal.drvState.lod[0].dimY / 2;
+            alloc->mHal.drvState.lod[1].stride = rsRound(alloc->mHal.drvState.lod[1].dimX *
+                                                  type->getElementSizeBytes(), 16);
+            o += alloc->mHal.drvState.lod[1].stride * alloc->mHal.drvState.lod[1].dimY;
+            alloc->mHal.drvState.lodCount = 2;
+            break;
+        default:
+            rsAssert(0);
+        }
     }
+
     alloc->mHal.drvState.faceOffset = o;
 
     alloc->mHal.drvState.lod[0].mallocPtr = ptr;
@@ -718,6 +749,21 @@
             src += stride;
             dst += alloc->mHal.drvState.lod[lod].stride;
         }
+        if (alloc->mHal.state.yuv) {
+            int lod = 1;
+            while (alloc->mHal.drvState.lod[lod].mallocPtr) {
+                uint32_t lineSize = alloc->mHal.drvState.lod[lod].dimX;
+                uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, lod, face);
+
+                for (uint32_t line=(yoff >> 1); line < ((yoff+h)>>1); line++) {
+                    memcpy(dst, src, lineSize);
+                    src += lineSize;
+                    dst += alloc->mHal.drvState.lod[lod].stride;
+                }
+                lod++;
+            }
+
+        }
         drv->uploadDeferred = true;
     } else {
         Update2DTexture(rsc, alloc, data, xoff, yoff, lod, face, w, h);
diff --git a/rsAllocation.cpp b/rsAllocation.cpp
index b215dba..1f36040 100644
--- a/rsAllocation.cpp
+++ b/rsAllocation.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2012 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/rsAllocation.h b/rsAllocation.h
index 09ce104..0948011 100644
--- a/rsAllocation.h
+++ b/rsAllocation.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2012 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/rsComponent.cpp b/rsComponent.cpp
index d240952..e48af4e 100644
--- a/rsComponent.cpp
+++ b/rsComponent.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2012 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -61,6 +61,12 @@
         rsAssert(mVectorSize == 4);
         rsAssert(mNormalized == true);
         break;
+    case RS_KIND_PIXEL_YUV:
+        mIsPixel = true;
+        rsAssert(mVectorSize == 1);
+        rsAssert(mNormalized == true);
+        break;
+
     default:
         rsAssert(mKind != RS_KIND_INVALID);
         break;
diff --git a/rsDefines.h b/rsDefines.h
index dfa0f9d..c878450 100644
--- a/rsDefines.h
+++ b/rsDefines.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2012 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -174,6 +174,7 @@
     RS_KIND_PIXEL_RGB,
     RS_KIND_PIXEL_RGBA,
     RS_KIND_PIXEL_DEPTH,
+    RS_KIND_PIXEL_YUV,
 
     RS_KIND_INVALID = 100,
 };
diff --git a/rsType.cpp b/rsType.cpp
index 1fba2f9..74a1a54 100644
--- a/rsType.cpp
+++ b/rsType.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
 
 #include "rsContext.h"
 
+#include "system/graphics.h"
+
 using namespace android;
 using namespace android::renderscript;
 
@@ -106,6 +108,32 @@
     if (mHal.state.faces) {
         offset *= 6;
     }
+
+    // YUV only supports basic 2d
+    // so we can stash the plane pointers in the mipmap levels.
+    if (mHal.state.dimYuv) {
+        switch(mHal.state.dimYuv) {
+        case HAL_PIXEL_FORMAT_YV12:
+            mHal.state.lodOffset[1] = offset;
+            mHal.state.lodDimX[1] = mHal.state.lodDimX[0] / 2;
+            mHal.state.lodDimY[1] = mHal.state.lodDimY[0] / 2;
+            offset += offset / 4;
+            mHal.state.lodOffset[2] = offset;
+            mHal.state.lodDimX[2] = mHal.state.lodDimX[0] / 2;
+            mHal.state.lodDimY[2] = mHal.state.lodDimY[0] / 2;
+            offset += offset / 4;
+            break;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:  // NV21
+            mHal.state.lodOffset[1] = offset;
+            mHal.state.lodDimX[1] = mHal.state.lodDimX[0];
+            mHal.state.lodDimY[1] = mHal.state.lodDimY[0] / 2;
+            offset += offset / 2;
+            break;
+        default:
+            rsAssert(0);
+        }
+    }
+
     mTotalSizeBytes = offset;
     mHal.state.element = mElement.get();
 }
diff --git a/rsType.h b/rsType.h
index 8ccf757..d2bc96b 100644
--- a/rsType.h
+++ b/rsType.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/scriptc/rs_types.rsh b/scriptc/rs_types.rsh
index 5c99313..3a5be6f 100644
--- a/scriptc/rs_types.rsh
+++ b/scriptc/rs_types.rsh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -530,6 +530,7 @@
     RS_KIND_PIXEL_RGB    = 10,
     RS_KIND_PIXEL_RGBA   = 11,
     RS_KIND_PIXEL_DEPTH  = 12,
+    RS_KIND_PIXEL_YUV    = 13,
 
     RS_KIND_INVALID      = 100,
 } rs_data_kind;