Fix element handling. Add YUV support.

bug 10427951

Change-Id: I2c9cd4faca881e3fa05eb65ab5edaab9f1c6c140
diff --git a/cpp/Element.cpp b/cpp/Element.cpp
index d685595..8223f99 100644
--- a/cpp/Element.cpp
+++ b/cpp/Element.cpp
@@ -73,7 +73,7 @@
 
 #define CREATE_USER(N, T) android::RSC::sp<const Element> Element::N(android::RSC::sp<RS> rs) { \
     if (rs->mElements.N == NULL) {                                  \
-        rs->mElements.N = (createUser(rs, RS_TYPE_##T)).get();      \
+        rs->mElements.N = (createUser(rs, RS_TYPE_##T));            \
     }                                                               \
     return rs->mElements.N;                                         \
     }
@@ -104,22 +104,36 @@
 CREATE_USER(MATRIX_2X2, MATRIX_2X2);
 
 #define CREATE_PIXEL(N, T, K) android::RSC::sp<const Element> Element::N(android::RSC::sp<RS> rs) { \
-    return createPixel(rs, RS_TYPE_##T, RS_KIND_##K); \
+    if (rs->mElements.N == NULL) {                                  \
+        rs->mElements.N = createPixel(rs, RS_TYPE_##T, RS_KIND_##K);    \
+    }                                                                   \
+    return rs->mElements.N;                                             \
 }
+
 CREATE_PIXEL(A_8, UNSIGNED_8, PIXEL_A);
 CREATE_PIXEL(RGB_565, UNSIGNED_5_6_5, PIXEL_RGB);
 CREATE_PIXEL(RGB_888, UNSIGNED_8, PIXEL_RGB);
 CREATE_PIXEL(RGBA_4444, UNSIGNED_4_4_4_4, PIXEL_RGBA);
 CREATE_PIXEL(RGBA_8888, UNSIGNED_8, PIXEL_RGBA);
+CREATE_PIXEL(YUV, UNSIGNED_8, PIXEL_YUV);
 
 #define CREATE_VECTOR(N, T) android::RSC::sp<const Element> Element::N##_2(android::RSC::sp<RS> rs) { \
-    return createVector(rs, RS_TYPE_##T, 2); \
-} \
+    if (rs->mElements.N##_2 == NULL) {                                  \
+        rs->mElements.N##_2 = createVector(rs, RS_TYPE_##T, 2);         \
+    }                                                                   \
+    return rs->mElements.N##_2;                                         \
+}                                                                       \
 android::RSC::sp<const Element> Element::N##_3(android::RSC::sp<RS> rs) { \
-    return createVector(rs, RS_TYPE_##T, 3); \
+    if (rs->mElements.N##_3 == NULL) {                                  \
+        rs->mElements.N##_3 = createVector(rs, RS_TYPE_##T, 3);         \
+    }                                                                   \
+    return rs->mElements.N##_3;                                         \
 } \
 android::RSC::sp<const Element> Element::N##_4(android::RSC::sp<RS> rs) { \
-    return createVector(rs, RS_TYPE_##T, 4); \
+    if (rs->mElements.N##_4 == NULL) {                                  \
+        rs->mElements.N##_4 = createVector(rs, RS_TYPE_##T, 4);         \
+    }                                                                   \
+    return rs->mElements.N##_4;                                         \
 }
 CREATE_VECTOR(U8, UNSIGNED_8);
 CREATE_VECTOR(I8, SIGNED_8);
diff --git a/cpp/ScriptIntrinsics.cpp b/cpp/ScriptIntrinsics.cpp
index e4bf907..2f52896 100644
--- a/cpp/ScriptIntrinsics.cpp
+++ b/cpp/ScriptIntrinsics.cpp
@@ -573,7 +573,7 @@
 }
 
 void ScriptIntrinsicYuvToRGB::setInput(sp<Allocation> in) {
-    if (!(in->getType()->getElement()->isCompatible(mElement))) {
+    if (!(in->getType()->getElement()->isCompatible(Element::YUV(mRS)))) {
         mRS->throwError(RS_ERROR_INVALID_ELEMENT, "Invalid element for input in YuvToRGB");
         return;
     }
diff --git a/cpp/Type.cpp b/cpp/Type.cpp
index fe80797..bc86a94 100644
--- a/cpp/Type.cpp
+++ b/cpp/Type.cpp
@@ -19,6 +19,12 @@
 
 #include "RenderScript.h"
 
+// from system/graphics.h
+enum {
+    HAL_PIXEL_FORMAT_YV12   = 0x32315659, // YCrCb 4:2:0 Planar
+    HAL_PIXEL_FORMAT_YCrCb_420_SP       = 0x11, // NV21
+};
+
 using namespace android;
 using namespace RSC;
 
@@ -66,6 +72,7 @@
     mDimMipmaps = false;
     mDimFaces = false;
     mElement = NULL;
+    mYuvFormat = RS_YUV_NONE;
 }
 
 void Type::updateFromNative() {
@@ -131,6 +138,27 @@
     mDimY = value;
 }
 
+void Type::Builder::setZ(uint32_t value) {
+    if(value < 1) {
+        ALOGE("Values of less than 1 for Dimension Z are not valid.");
+    }
+    mDimZ = value;
+}
+
+void Type::Builder::setYuvFormat(RSYuvFormat format) {
+    if (format != RS_YUV_NONE && !(mElement->isCompatible(Element::YUV(mRS)))) {
+        ALOGE("Invalid element for use with YUV.");
+        return;
+    }
+
+    if (format >= RS_YUV_MAX) {
+        ALOGE("Invalid YUV format.");
+        return;
+    }
+    mYuvFormat = format;
+}
+
+
 void Type::Builder::setMipmaps(bool value) {
     mDimMipmaps = value;
 }
@@ -159,6 +187,18 @@
         }
     }
 
+    uint32_t nativeYuv;
+    switch(mYuvFormat) {
+    case(RS_YUV_YV12):
+        nativeYuv = HAL_PIXEL_FORMAT_YV12;
+        break;
+    case (RS_YUV_NV21):
+        nativeYuv = HAL_PIXEL_FORMAT_YCrCb_420_SP;
+        break;
+    default:
+        nativeYuv = 0;
+    }
+
     void * id = RS::dispatch->TypeCreate(mRS->getContext(), mElement->getID(), mDimX, mDimY, mDimZ,
                                          mDimMipmaps, mDimFaces, 0);
     Type *t = new Type(id, mRS);
diff --git a/cpp/rsCppStructs.h b/cpp/rsCppStructs.h
index 1d0f9de..a2a6fcf 100644
--- a/cpp/rsCppStructs.h
+++ b/cpp/rsCppStructs.h
@@ -53,6 +53,13 @@
 
  };
 
+ enum RSYuvFormat {
+     RS_YUV_NONE = 0,
+     RS_YUV_YV12 = 1,
+     RS_YUV_NV21 = 2,
+     RS_YUV_MAX = 3
+ };
+
  class RS : public android::RSC::LightRefBase<RS> {
 
  public:
@@ -100,15 +107,45 @@
 
     struct {
         sp<const Element> U8;
+        sp<const Element> U8_2;
+        sp<const Element> U8_3;
+        sp<const Element> U8_4;
         sp<const Element> I8;
+        sp<const Element> I8_2;
+        sp<const Element> I8_3;
+        sp<const Element> I8_4;
         sp<const Element> U16;
+        sp<const Element> U16_2;
+        sp<const Element> U16_3;
+        sp<const Element> U16_4;
         sp<const Element> I16;
+        sp<const Element> I16_2;
+        sp<const Element> I16_3;
+        sp<const Element> I16_4;
         sp<const Element> U32;
+        sp<const Element> U32_2;
+        sp<const Element> U32_3;
+        sp<const Element> U32_4;
         sp<const Element> I32;
+        sp<const Element> I32_2;
+        sp<const Element> I32_3;
+        sp<const Element> I32_4;
         sp<const Element> U64;
+        sp<const Element> U64_2;
+        sp<const Element> U64_3;
+        sp<const Element> U64_4;
         sp<const Element> I64;
+        sp<const Element> I64_2;
+        sp<const Element> I64_3;
+        sp<const Element> I64_4;
         sp<const Element> F32;
+        sp<const Element> F32_2;
+        sp<const Element> F32_3;
+        sp<const Element> F32_4;
         sp<const Element> F64;
+        sp<const Element> F64_2;
+        sp<const Element> F64_3;
+        sp<const Element> F64_4;
         sp<const Element> BOOLEAN;
 
         sp<const Element> ELEMENT;
@@ -129,45 +166,7 @@
         sp<const Element> RGBA_4444;
         sp<const Element> RGBA_8888;
 
-        sp<const Element> FLOAT_2;
-        sp<const Element> FLOAT_3;
-        sp<const Element> FLOAT_4;
-
-        sp<const Element> DOUBLE_2;
-        sp<const Element> DOUBLE_3;
-        sp<const Element> DOUBLE_4;
-
-        sp<const Element> UCHAR_2;
-        sp<const Element> UCHAR_3;
-        sp<const Element> UCHAR_4;
-
-        sp<const Element> CHAR_2;
-        sp<const Element> CHAR_3;
-        sp<const Element> CHAR_4;
-
-        sp<const Element> USHORT_2;
-        sp<const Element> USHORT_3;
-        sp<const Element> USHORT_4;
-
-        sp<const Element> SHORT_2;
-        sp<const Element> SHORT_3;
-        sp<const Element> SHORT_4;
-
-        sp<const Element> UINT_2;
-        sp<const Element> UINT_3;
-        sp<const Element> UINT_4;
-
-        sp<const Element> INT_2;
-        sp<const Element> INT_3;
-        sp<const Element> INT_4;
-
-        sp<const Element> ULONG_2;
-        sp<const Element> ULONG_3;
-        sp<const Element> ULONG_4;
-
-        sp<const Element> LONG_2;
-        sp<const Element> LONG_3;
-        sp<const Element> LONG_4;
+        sp<const Element> YUV;
 
         sp<const Element> MATRIX_4X4;
         sp<const Element> MATRIX_3X3;
@@ -387,6 +386,7 @@
     static sp<const Element> I64_2(sp<RS> rs);
     static sp<const Element> I64_3(sp<RS> rs);
     static sp<const Element> I64_4(sp<RS> rs);
+    static sp<const Element> YUV(sp<RS> rs);
     static sp<const Element> MATRIX_4X4(sp<RS> rs);
     static sp<const Element> MATRIX_3X3(sp<RS> rs);
     static sp<const Element> MATRIX_2X2(sp<RS> rs);
@@ -539,6 +539,7 @@
     uint32_t mDimX;
     uint32_t mDimY;
     uint32_t mDimZ;
+    RSYuvFormat mYuvFormat;
     bool mDimMipmaps;
     bool mDimFaces;
     size_t mElementCount;
@@ -551,6 +552,10 @@
 
 public:
 
+    RSYuvFormat getYuvFormat() const {
+        return mYuvFormat;
+    }
+
     sp<const Element> getElement() const {
         return mElement;
     }
@@ -591,6 +596,7 @@
         uint32_t mDimX;
         uint32_t mDimY;
         uint32_t mDimZ;
+        RSYuvFormat mYuvFormat;
         bool mDimMipmaps;
         bool mDimFaces;
         sp<const Element> mElement;
@@ -600,6 +606,8 @@
 
         void setX(uint32_t value);
         void setY(uint32_t value);
+        void setZ(uint32_t value);
+        void setYuvFormat(RSYuvFormat format);
         void setMipmaps(bool value);
         void setFaces(bool value);
         sp<const Type> create();