Implement arrays and allocation adapters

WIP: now passing basic tests

Change-Id: I3d8c1ab12975428def225f88a04e24a4158ca69c
diff --git a/driver/rsdAllocation.cpp b/driver/rsdAllocation.cpp
index 33649c3..f56ab56 100644
--- a/driver/rsdAllocation.cpp
+++ b/driver/rsdAllocation.cpp
@@ -472,58 +472,99 @@
     return true;
 }
 
+void rsdAllocationAdapterOffset(const Context *rsc, const Allocation *alloc) {
+    //ALOGE("rsdAllocationAdapterOffset");
+
+    // Get a base pointer to the new LOD
+    const Allocation *base = alloc->mHal.state.baseAlloc;
+    const Type *type = alloc->mHal.state.type;
+    if (base == nullptr) {
+        return;
+    }
+
+    uint8_t * ptrA = (uint8_t *)base->getPointerUnchecked(alloc->mHal.state.originX, alloc->mHal.state.originY);
+    uint8_t * ptrB = (uint8_t *)base->getPointerUnchecked(0, 0);
+
+    //ALOGE("rsdAllocationAdapterOffset  %p  %p", ptrA, ptrB);
+    //ALOGE("rsdAllocationAdapterOffset  lodCount %i", alloc->mHal.drvState.lodCount);
+
+    const int lodBias = alloc->mHal.state.originLOD;
+    uint32_t lodCount = rsMax(alloc->mHal.drvState.lodCount, (uint32_t)1);
+    for (uint32_t lod=0; lod < lodCount; lod++) {
+        alloc->mHal.drvState.lod[lod] = base->mHal.drvState.lod[lod + lodBias];
+        alloc->mHal.drvState.lod[lod].mallocPtr =
+                ((uint8_t *)alloc->mHal.drvState.lod[lod].mallocPtr + (ptrA - ptrB));
+        //ALOGE("rsdAllocationAdapterOffset  lod  %p  %i %i", alloc->mHal.drvState.lod[lod].mallocPtr, alloc->mHal.drvState.lod[lod].dimX, alloc->mHal.drvState.lod[lod].dimY);
+    }
+}
+
+bool rsdAllocationAdapterInit(const Context *rsc, Allocation *alloc) {
+    DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
+    if (!drv) {
+        return false;
+    }
+    alloc->mHal.drv = drv;
+
+    // We need to build an allocation that looks like a subset of the parent allocation
+    rsdAllocationAdapterOffset(rsc, alloc);
+
+    return true;
+}
+
 void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) {
     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
 
+    if (alloc->mHal.state.baseAlloc == nullptr) {
 #ifndef RS_COMPATIBILITY_LIB
-    if (drv->bufferID) {
-        // Causes a SW crash....
-        //ALOGV(" mBufferID %i", mBufferID);
-        //glDeleteBuffers(1, &mBufferID);
-        //mBufferID = 0;
-    }
-    if (drv->textureID) {
-        RSD_CALL_GL(glDeleteTextures, 1, &drv->textureID);
-        drv->textureID = 0;
-    }
-    if (drv->renderTargetID) {
-        RSD_CALL_GL(glDeleteRenderbuffers, 1, &drv->renderTargetID);
-        drv->renderTargetID = 0;
-    }
+        if (drv->bufferID) {
+            // Causes a SW crash....
+            //ALOGV(" mBufferID %i", mBufferID);
+            //glDeleteBuffers(1, &mBufferID);
+            //mBufferID = 0;
+        }
+        if (drv->textureID) {
+            RSD_CALL_GL(glDeleteTextures, 1, &drv->textureID);
+            drv->textureID = 0;
+        }
+        if (drv->renderTargetID) {
+            RSD_CALL_GL(glDeleteRenderbuffers, 1, &drv->renderTargetID);
+            drv->renderTargetID = 0;
+        }
 #endif
 
-    if (alloc->mHal.drvState.lod[0].mallocPtr) {
-        // don't free user-allocated ptrs or IO_OUTPUT buffers
-        if (!(drv->useUserProvidedPtr) &&
-            !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) &&
-            !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT)) {
-                free(alloc->mHal.drvState.lod[0].mallocPtr);
+        if (alloc->mHal.drvState.lod[0].mallocPtr) {
+            // don't free user-allocated ptrs or IO_OUTPUT buffers
+            if (!(drv->useUserProvidedPtr) &&
+                !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) &&
+                !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT)) {
+                    free(alloc->mHal.drvState.lod[0].mallocPtr);
+            }
+            alloc->mHal.drvState.lod[0].mallocPtr = nullptr;
         }
-        alloc->mHal.drvState.lod[0].mallocPtr = nullptr;
-    }
 
 #ifndef RS_COMPATIBILITY_LIB
-    if (drv->readBackFBO != nullptr) {
-        delete drv->readBackFBO;
-        drv->readBackFBO = nullptr;
-    }
-
-    if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) &&
-        (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
-
-        DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
-        ANativeWindow *nw = drv->wndSurface;
-        if (nw) {
-            GraphicBufferMapper &mapper = GraphicBufferMapper::get();
-            mapper.unlock(drv->wndBuffer->handle);
-            int32_t r = nw->queueBuffer(nw, drv->wndBuffer, -1);
-
-            drv->wndSurface = nullptr;
-            native_window_api_disconnect(nw, NATIVE_WINDOW_API_CPU);
-            nw->decStrong(nullptr);
+        if (drv->readBackFBO != nullptr) {
+            delete drv->readBackFBO;
+            drv->readBackFBO = nullptr;
         }
-    }
+
+        if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) &&
+            (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
+
+            DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+            ANativeWindow *nw = drv->wndSurface;
+            if (nw) {
+                GraphicBufferMapper &mapper = GraphicBufferMapper::get();
+                mapper.unlock(drv->wndBuffer->handle);
+                int32_t r = nw->queueBuffer(nw, drv->wndBuffer, -1);
+
+                drv->wndSurface = nullptr;
+                native_window_api_disconnect(nw, NATIVE_WINDOW_API_CPU);
+                nw->decStrong(nullptr);
+            }
+        }
 #endif
+    }
 
     free(drv);
     alloc->mHal.drv = nullptr;
diff --git a/driver/rsdAllocation.h b/driver/rsdAllocation.h
index 9f13c98..0b6d8bf 100644
--- a/driver/rsdAllocation.h
+++ b/driver/rsdAllocation.h
@@ -84,6 +84,8 @@
 bool rsdAllocationInit(const android::renderscript::Context *rsc,
                        android::renderscript::Allocation *alloc,
                        bool forceZero);
+bool rsdAllocationAdapterInit(const android::renderscript::Context *rsc,
+                              android::renderscript::Allocation *alloc);
 void rsdAllocationDestroy(const android::renderscript::Context *rsc,
                           android::renderscript::Allocation *alloc);
 
@@ -175,5 +177,8 @@
                                      const android::renderscript::Allocation *alloc,
                                      android::renderscript::rs_allocation *obj);
 
+void rsdAllocationAdapterOffset(const android::renderscript::Context *rsc,
+                                const android::renderscript::Allocation *alloc);
+
 
 #endif
diff --git a/driver/rsdCore.cpp b/driver/rsdCore.cpp
index 0181282..8812446 100644
--- a/driver/rsdCore.cpp
+++ b/driver/rsdCore.cpp
@@ -88,6 +88,7 @@
 
     {
         rsdAllocationInit,
+        rsdAllocationAdapterInit,
         rsdAllocationDestroy,
         rsdAllocationGrallocBits,
         rsdAllocationResize,
@@ -110,7 +111,8 @@
         rsdAllocationElementData1D,
         rsdAllocationElementData2D,
         rsdAllocationGenerateMipmaps,
-        rsdAllocationUpdateCachedObject
+        rsdAllocationUpdateCachedObject,
+        rsdAllocationAdapterOffset
     },
 
 
diff --git a/driver/runtime/rs_structs.h b/driver/runtime/rs_structs.h
index b57a2c8..76c2156 100644
--- a/driver/runtime/rs_structs.h
+++ b/driver/runtime/rs_structs.h
@@ -45,6 +45,15 @@
             int32_t surfaceTextureID;
             void * nativeBuffer;
             int64_t timestamp;
+
+            // Allocation adapter state
+            const void *baseAlloc;
+            uint32_t originX;
+            uint32_t originY;
+            uint32_t originZ;
+            uint32_t originLOD;
+            uint32_t originFace;
+            uint32_t originArray[4/*Type::mMaxArrays*/];
         } state;
 
         struct DrvState {
@@ -63,6 +72,9 @@
                 uint32_t shift;
                 uint32_t step;
             } yuv;
+
+            int grallocFlags;
+            uint32_t dimArray[4/*Type::mMaxArrays*/];
         } drvState;
     } mHal;
 } Allocation_t;
diff --git a/rs.spec b/rs.spec
index 183ae8b..2f3cfb5 100644
--- a/rs.spec
+++ b/rs.spec
@@ -88,6 +88,18 @@
     sync
     }
 
+AllocationAdapterCreate {
+    direct
+    param RsType vtype
+    param RsAllocation baseAlloc
+    ret RsAllocation
+}
+
+AllocationAdapterOffset {
+    param RsAllocation alloc
+    param const uint32_t *offsets
+}
+
 ContextFinish {
     sync
     }
diff --git a/rsAllocation.cpp b/rsAllocation.cpp
index 9b83ebb..5712a17 100644
--- a/rsAllocation.cpp
+++ b/rsAllocation.cpp
@@ -41,6 +41,53 @@
     updateCache();
 }
 
+Allocation::Allocation(Context *rsc, const Allocation *alloc, const Type *type)
+    : ObjectBase(rsc) {
+
+    memset(&mHal, 0, sizeof(mHal));
+
+
+    mHal.state.baseAlloc = alloc;
+    mHal.state.type = type;
+    mHal.state.usageFlags = alloc->mHal.state.usageFlags;
+    mHal.state.mipmapControl = RS_ALLOCATION_MIPMAP_NONE;
+
+    setType(type);
+    updateCache();
+
+
+
+
+    struct Hal {
+        void * drv;
+
+        struct DrvState {
+            struct LodState {
+                void * mallocPtr;
+                size_t stride;
+                uint32_t dimX;
+                uint32_t dimY;
+                uint32_t dimZ;
+            } lod[android::renderscript::Allocation::MAX_LOD];
+            size_t faceOffset;
+            uint32_t lodCount;
+            uint32_t faceCount;
+
+            struct YuvState {
+                uint32_t shift;
+                uint32_t step;
+            } yuv;
+
+            int grallocFlags;
+            uint32_t dimArray[Type::mMaxArrays];
+        };
+        mutable DrvState drvState;
+
+    };
+    Hal mHal;
+
+}
+
 void Allocation::operator delete(void* ptr) {
     if (ptr) {
         Allocation *a = (Allocation*) ptr;
@@ -69,6 +116,27 @@
     return a;
 }
 
+Allocation * Allocation::createAdapter(Context *rsc, const Allocation *alloc, const Type *type) {
+    // Allocation objects must use allocator specified by the driver
+    void* allocMem = rsc->mHal.funcs.allocRuntimeMem(sizeof(Allocation), 0);
+
+    if (!allocMem) {
+        rsc->setError(RS_ERROR_FATAL_DRIVER, "Couldn't allocate memory for Allocation");
+        return nullptr;
+    }
+
+    Allocation *a = new (allocMem) Allocation(rsc, alloc, type);
+
+    if (!rsc->mHal.funcs.allocation.initAdapter(rsc, a)) {
+        rsc->setError(RS_ERROR_FATAL_DRIVER, "Allocation::Allocation, alloc failure");
+        delete a;
+        return nullptr;
+    }
+
+    return a;
+}
+
+
 void Allocation::updateCache() {
     const Type *type = mHal.state.type;
     mHal.state.yuv = type->getDimYuv();
@@ -786,6 +854,22 @@
     a->read(rsc, xoff, yoff, lod, face, w, h, data, sizeBytes, stride);
 }
 
+RsAllocation rsi_AllocationAdapterCreate(Context *rsc, RsType vwindow, RsAllocation vbase) {
+
+
+    Allocation * alloc = Allocation::createAdapter(rsc,
+            static_cast<Allocation *>(vbase), static_cast<Type *>(vwindow));
+    if (!alloc) {
+        return nullptr;
+    }
+    alloc->incUserRef();
+    return alloc;
+}
+
+void rsi_AllocationAdapterOffset(Context *rsc, RsAllocation va, const uint32_t *offsets, size_t len) {
+}
+
+
 }
 }
 
diff --git a/rsAllocation.h b/rsAllocation.h
index cf33556..3714852 100644
--- a/rsAllocation.h
+++ b/rsAllocation.h
@@ -69,6 +69,15 @@
             int32_t surfaceTextureID;
             ANativeWindowBuffer *nativeBuffer;
             int64_t timestamp;
+
+            // Allocation adapter state
+            const Allocation *baseAlloc;
+            uint32_t originX;
+            uint32_t originY;
+            uint32_t originZ;
+            uint32_t originLOD;
+            uint32_t originFace;
+            uint32_t originArray[Type::mMaxArrays];
         };
         State state;
 
@@ -90,6 +99,7 @@
             } yuv;
 
             int grallocFlags;
+            uint32_t dimArray[Type::mMaxArrays];
         };
         mutable DrvState drvState;
 
@@ -101,6 +111,9 @@
     static Allocation * createAllocation(Context *rsc, const Type *, uint32_t usages,
                                          RsAllocationMipmapControl mc = RS_ALLOCATION_MIPMAP_NONE,
                                          void *ptr = 0);
+    static Allocation * createAdapter(Context *rsc, const Allocation *alloc, const Type *type);
+
+
     virtual ~Allocation();
     void updateCache();
 
@@ -211,6 +224,7 @@
 private:
     void freeChildrenUnlocked();
     Allocation(Context *rsc, const Type *, uint32_t usages, RsAllocationMipmapControl mc, void *ptr);
+    Allocation(Context *rsc, const Allocation *, const Type *);
 
     uint32_t getPackedSize() const;
     static void writePackedData(Context *rsc, const Type *type, uint8_t *dst,
diff --git a/rs_hal.h b/rs_hal.h
index b3c2e39..9a4e9a5 100644
--- a/rs_hal.h
+++ b/rs_hal.h
@@ -164,6 +164,7 @@
 
     struct {
         bool (*init)(const Context *rsc, Allocation *alloc, bool forceZero);
+        bool (*initAdapter)(const Context *rsc, Allocation *alloc);
         void (*destroy)(const Context *rsc, Allocation *alloc);
         uint32_t (*grallocBits)(const Context *rsc, Allocation *alloc);
 
@@ -243,6 +244,8 @@
         void (*generateMipmaps)(const Context *rsc, const Allocation *alloc);
 
         void (*updateCachedObject)(const Context *rsc, const Allocation *alloc, rs_allocation *obj);
+
+        void (*adapterOffset)(const Context *rsc, const Allocation *alloc);
     } allocation;
 
     struct {