Add AllocationCreateStrided to support lib CPU driver

 - Able to create Allocations with arbitrary alignment requirement,
   making Incremental Intrinsic Support able to run with different
   native GPU RS runtime.
 - Make compat mode CPU driver using an additional rs_compat.spec.
 - Add a compat mode only USAGE_INCREMENTAL_SUPPORT.
 - Add AllocationCreateStrided() to take an Alignment requirement (power
   of 2). Only enbled when detect USAGE_INCREMENTAL_SUPPORT.

Change-Id: I66f913c3a2474f93af5a244c0c84460a7a395e71
diff --git a/driver/rsdAllocation.cpp b/driver/rsdAllocation.cpp
index 790005d..a3203a7 100644
--- a/driver/rsdAllocation.cpp
+++ b/driver/rsdAllocation.cpp
@@ -302,16 +302,15 @@
     return uvSize;
 }
 
-
 static size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc,
-        const Type *type, uint8_t *ptr) {
+                                          const Type *type, uint8_t *ptr, size_t requiredAlignment) {
     alloc->mHal.drvState.lod[0].dimX = type->getDimX();
     alloc->mHal.drvState.lod[0].dimY = type->getDimY();
     alloc->mHal.drvState.lod[0].dimZ = type->getDimZ();
     alloc->mHal.drvState.lod[0].mallocPtr = 0;
-    // Stride needs to be 16-byte aligned too!
+    // Stride needs to be aligned to a boundary defined by requiredAlignment!
     size_t stride = alloc->mHal.drvState.lod[0].dimX * type->getElementSizeBytes();
-    alloc->mHal.drvState.lod[0].stride = rsRound(stride, 16);
+    alloc->mHal.drvState.lod[0].stride = rsRound(stride, requiredAlignment);
     alloc->mHal.drvState.lodCount = type->getLODCount();
     alloc->mHal.drvState.faceCount = type->getDimFaces();
 
@@ -335,7 +334,7 @@
             alloc->mHal.drvState.lod[lod].dimY = ty;
             alloc->mHal.drvState.lod[lod].dimZ = tz;
             alloc->mHal.drvState.lod[lod].stride =
-                    rsRound(tx * type->getElementSizeBytes(), 16);
+                    rsRound(tx * type->getElementSizeBytes(), requiredAlignment);
             offsets[lod] = o;
             o += alloc->mHal.drvState.lod[lod].stride * rsMax(ty, 1u) * rsMax(tz, 1u);
             if (tx > 1) tx >>= 1;
@@ -359,9 +358,14 @@
     return allocSize;
 }
 
-static uint8_t* allocAlignedMemory(size_t allocSize, bool forceZero) {
-    // We align all allocations to a 16-byte boundary.
-    uint8_t* ptr = (uint8_t *)memalign(16, allocSize);
+static size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc,
+                                          const Type *type, uint8_t *ptr) {
+    return AllocationBuildPointerTable(rsc, alloc, type, ptr, Allocation::kMinimumRSAlignment);
+}
+
+static uint8_t* allocAlignedMemory(size_t allocSize, bool forceZero, size_t requiredAlignment) {
+    // We align all allocations to a boundary defined by requiredAlignment.
+    uint8_t* ptr = (uint8_t *)memalign(requiredAlignment, allocSize);
     if (!ptr) {
         return nullptr;
     }
@@ -371,15 +375,20 @@
     return ptr;
 }
 
-bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) {
+bool rsdAllocationInitStrided(const Context *rsc, Allocation *alloc, bool forceZero, size_t requiredAlignment) {
     DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
     if (!drv) {
         return false;
     }
     alloc->mHal.drv = drv;
 
+    // Check if requiredAlignment is power of 2, also requiredAlignment should be larger or equal than kMinimumRSAlignment.
+    if ((requiredAlignment & (requiredAlignment-1)) != 0 || requiredAlignment < Allocation::kMinimumRSAlignment) {
+        ALOGE("requiredAlignment must be power of 2");
+        return false;
+    }
     // Calculate the object size.
-    size_t allocSize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), nullptr);
+    size_t allocSize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), nullptr, requiredAlignment);
 
     uint8_t * ptr = nullptr;
     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) {
@@ -387,6 +396,20 @@
     } else if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) {
         // Allocation is allocated when the surface is created
         // in getSurface
+#ifdef RS_COMPATIBILITY_LIB
+    } else if (alloc->mHal.state.usageFlags == (RS_ALLOCATION_USAGE_INCREMENTAL_SUPPORT | RS_ALLOCATION_USAGE_SHARED)) {
+        if (alloc->mHal.state.userProvidedPtr == nullptr) {
+            ALOGE("User-backed buffer pointer cannot be null");
+            return false;
+        }
+        if (alloc->getType()->getDimLOD() || alloc->getType()->getDimFaces()) {
+            ALOGE("User-allocated buffers must not have multiple faces or LODs");
+            return false;
+        }
+
+        drv->useUserProvidedPtr = true;
+        ptr = (uint8_t*)alloc->mHal.state.userProvidedPtr;
+#endif
     } else if (alloc->mHal.state.userProvidedPtr != nullptr) {
         // user-provided allocation
         // limitations: no faces, no LOD, USAGE_SCRIPT or SCRIPT+TEXTURE only
@@ -400,13 +423,13 @@
             return false;
         }
 
-        // rows must be 16-byte aligned
+        // rows must be aligned based on requiredAlignment.
         // validate that here, otherwise fall back to not use the user-backed allocation
-        if (((alloc->getType()->getDimX() * alloc->getType()->getElement()->getSizeBytes()) % 16) != 0) {
+        if (((alloc->getType()->getDimX() * alloc->getType()->getElement()->getSizeBytes()) % requiredAlignment) != 0) {
             ALOGV("User-backed allocation failed stride requirement, falling back to separate allocation");
             drv->useUserProvidedPtr = false;
 
-            ptr = allocAlignedMemory(allocSize, forceZero);
+            ptr = allocAlignedMemory(allocSize, forceZero, requiredAlignment);
             if (!ptr) {
                 alloc->mHal.drv = nullptr;
                 free(drv);
@@ -418,7 +441,7 @@
             ptr = (uint8_t*)alloc->mHal.state.userProvidedPtr;
         }
     } else {
-        ptr = allocAlignedMemory(allocSize, forceZero);
+        ptr = allocAlignedMemory(allocSize, forceZero, requiredAlignment);
         if (!ptr) {
             alloc->mHal.drv = nullptr;
             free(drv);
@@ -426,7 +449,7 @@
         }
     }
     // Build the pointer tables
-    size_t verifySize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), ptr);
+    size_t verifySize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), ptr, requiredAlignment);
     if(allocSize != verifySize) {
         rsAssert(!"Size mismatch");
     }
@@ -476,6 +499,10 @@
     return true;
 }
 
+bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) {
+    return rsdAllocationInitStrided(rsc, alloc, forceZero, Allocation::kMinimumRSAlignment);
+}
+
 void rsdAllocationAdapterOffset(const Context *rsc, const Allocation *alloc) {
     //ALOGE("rsdAllocationAdapterOffset");