Move memory layout to driver.

This change moves all allocation data copies to the
hal.  Also removes stride from the runtime.  Follow on
changes will remove the malloc pointer from the runtime.

Change-Id: I30967c739800cd4b97186e9fc8b69f26a3f2787d
diff --git a/driver/rsdAllocation.cpp b/driver/rsdAllocation.cpp
index 20c2165..7f2de1d 100644
--- a/driver/rsdAllocation.cpp
+++ b/driver/rsdAllocation.cpp
@@ -78,6 +78,17 @@
     return 0;
 }
 
+uint8_t *GetOffsetPtr(const android::renderscript::Allocation *alloc,
+                      uint32_t xoff, uint32_t yoff, uint32_t lod,
+                      RsAllocationCubemapFace face) {
+    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+    uint8_t *ptr = (uint8_t *)drv->lod[lod].mallocPtr;
+    ptr += face * drv->faceOffset;
+    ptr += yoff * drv->lod[lod].stride;
+    ptr += xoff * alloc->mHal.state.elementSizeBytes;
+    return ptr;
+}
+
 
 static void Update2DTexture(const Context *rsc, const Allocation *alloc, const void *ptr,
                             uint32_t xoff, uint32_t yoff, uint32_t lod,
@@ -109,8 +120,7 @@
     rsdGLCheckError(rsc, "Upload2DTexture 1 ");
     for (uint32_t face = 0; face < faceCount; face ++) {
         for (uint32_t lod = 0; lod < alloc->mHal.state.type->getLODCount(); lod++) {
-            const uint8_t *p = (const uint8_t *)alloc->mHal.drvState.mallocPtr;
-            p += alloc->mHal.state.type->getLODFaceOffset(lod, (RsAllocationCubemapFace)face, 0, 0);
+            const uint8_t *p = GetOffsetPtr(alloc, 0, 0, lod, (RsAllocationCubemapFace)face);
 
             GLenum t = GL_TEXTURE_2D;
             if (alloc->mHal.state.hasFaces) {
@@ -165,9 +175,10 @@
     Upload2DTexture(rsc, alloc, isFirstUpload);
 
     if (!(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
-        if (alloc->mHal.drvState.mallocPtr) {
-            free(alloc->mHal.drvState.mallocPtr);
-            alloc->mHal.drvState.mallocPtr = NULL;
+        if (alloc->mHal.drvState.mallocPtrLOD0) {
+            free(alloc->mHal.drvState.mallocPtrLOD0);
+            alloc->mHal.drvState.mallocPtrLOD0 = NULL;
+            drv->lod[0].mallocPtr = NULL;
         }
     }
     rsdGLCheckError(rsc, "UploadToTexture");
@@ -214,7 +225,7 @@
     }
     RSD_CALL_GL(glBindBuffer, drv->glTarget, drv->bufferID);
     RSD_CALL_GL(glBufferData, drv->glTarget, alloc->mHal.state.type->getSizeBytes(),
-                 alloc->mHal.drvState.mallocPtr, GL_DYNAMIC_DRAW);
+                 alloc->mHal.drvState.mallocPtrLOD0, GL_DYNAMIC_DRAW);
     RSD_CALL_GL(glBindBuffer, drv->glTarget, 0);
     rsdGLCheckError(rsc, "UploadToBufferObject");
 }
@@ -225,15 +236,53 @@
         return false;
     }
 
-    void * ptr = NULL;
+    drv->lod[0].dimX = alloc->getType()->getDimX();
+    drv->lod[0].dimY = alloc->getType()->getDimY();
+    drv->lod[0].mallocPtr = 0;
+    drv->lod[0].stride = alloc->mHal.state.dimensionX * alloc->mHal.state.elementSizeBytes;
+    drv->lodCount = alloc->getType()->getLODCount();
+    drv->faceCount = alloc->getType()->getDimFaces();
+
+    size_t offsets[Allocation::MAX_LOD];
+    memset(offsets, 0, sizeof(offsets));
+
+    size_t o = drv->lod[0].stride * rsMax(drv->lod[0].dimY, 1u) * rsMax(drv->lod[0].dimZ, 1u);
+    if(drv->lodCount > 1) {
+        uint32_t tx = drv->lod[0].dimX;
+        uint32_t ty = drv->lod[0].dimY;
+        uint32_t tz = drv->lod[0].dimZ;
+        for (uint32_t lod=1; lod < drv->lodCount; lod++) {
+            drv->lod[lod].dimX = tx;
+            drv->lod[lod].dimY = ty;
+            drv->lod[lod].dimZ = tz;
+            drv->lod[lod].stride = tx * alloc->mHal.state.elementSizeBytes;
+            offsets[lod] = o;
+            o += drv->lod[lod].stride * rsMax(ty, 1u) * rsMax(tz, 1u);
+            if (tx > 1) tx >>= 1;
+            if (ty > 1) ty >>= 1;
+            if (tz > 1) tz >>= 1;
+        }
+    }
+    drv->faceOffset = o;
+
+    uint8_t * ptr = NULL;
     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) {
     } else {
-        ptr = malloc(alloc->mHal.state.type->getSizeBytes());
+        size_t allocSize = drv->faceOffset;
+        if(drv->faceCount) {
+            allocSize *= 6;
+        }
+
+        ptr = (uint8_t *)malloc(allocSize);
         if (!ptr) {
             free(drv);
             return false;
         }
     }
+    drv->lod[0].mallocPtr = ptr;
+    for (uint32_t lod=1; lod < drv->lodCount; lod++) {
+        drv->lod[lod].mallocPtr = ptr + offsets[lod];
+    }
 
     drv->glTarget = GL_NONE;
     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
@@ -251,9 +300,8 @@
     drv->glType = rsdTypeToGLType(alloc->mHal.state.type->getElement()->getComponent().getType());
     drv->glFormat = rsdKindToGLFormat(alloc->mHal.state.type->getElement()->getComponent().getKind());
 
-
-    alloc->mHal.drvState.mallocPtr = ptr;
-    alloc->mHal.drvState.stride = alloc->mHal.state.dimensionX * alloc->mHal.state.elementSizeBytes;
+    alloc->mHal.drvState.strideLOD0 = drv->lod[0].stride;
+    alloc->mHal.drvState.mallocPtrLOD0 = ptr;
     alloc->mHal.drv = drv;
     if (forceZero && ptr) {
         memset(ptr, 0, alloc->mHal.state.type->getSizeBytes());
@@ -263,8 +311,6 @@
         drv->uploadDeferred = true;
     }
 
-    drv->width = alloc->getType()->getDimX();
-    drv->height = alloc->getType()->getDimY();
 
     drv->readBackFBO = NULL;
 
@@ -289,9 +335,9 @@
         drv->renderTargetID = 0;
     }
 
-    if (alloc->mHal.drvState.mallocPtr) {
-        free(alloc->mHal.drvState.mallocPtr);
-        alloc->mHal.drvState.mallocPtr = NULL;
+    if (alloc->mHal.drvState.mallocPtrLOD0) {
+        free(alloc->mHal.drvState.mallocPtrLOD0);
+        alloc->mHal.drvState.mallocPtrLOD0 = NULL;
     }
     if (drv->readBackFBO != NULL) {
         delete drv->readBackFBO;
@@ -305,8 +351,8 @@
                          const Type *newType, bool zeroNew) {
     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
 
-    alloc->mHal.drvState.mallocPtr = (uint8_t *)realloc(
-            alloc->mHal.drvState.mallocPtr, newType->getSizeBytes());
+    alloc->mHal.drvState.mallocPtrLOD0 = (uint8_t *)realloc(
+            alloc->mHal.drvState.mallocPtrLOD0, newType->getSizeBytes());
 
     const uint32_t oldDimX = alloc->mHal.state.dimensionX;
     const uint32_t dimX = newType->getDimX();
@@ -314,7 +360,7 @@
     if (dimX > oldDimX) {
         const Element *e = alloc->mHal.state.type->getElement();
         uint32_t stride = e->getSizeBytes();
-        memset(((uint8_t *)alloc->mHal.drvState.mallocPtr) + stride * oldDimX,
+        memset(((uint8_t *)alloc->mHal.drvState.mallocPtrLOD0) + stride * oldDimX,
                  0, stride * (dimX - oldDimX));
     }
 }
@@ -413,8 +459,9 @@
     mapper.lock(drv->wndBuffer->handle,
             GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN,
             bounds, &dst);
-    alloc->mHal.drvState.mallocPtr = dst;
-    alloc->mHal.drvState.stride = drv->wndBuffer->stride * alloc->mHal.state.elementSizeBytes;
+    drv->lod[0].mallocPtr = dst;
+    alloc->mHal.drvState.mallocPtrLOD0 = dst;
+    drv->lod[0].stride = drv->wndBuffer->stride * alloc->mHal.state.elementSizeBytes;
 
     return true;
 }
@@ -507,8 +554,7 @@
     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
 
     const uint32_t eSize = alloc->mHal.state.type->getElementSizeBytes();
-    uint8_t * ptr = (uint8_t *)alloc->mHal.drvState.mallocPtr;
-    ptr += eSize * xoff;
+    uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
     uint32_t size = count * eSize;
 
     if (alloc->mHal.state.hasReferences) {
@@ -528,10 +574,9 @@
     uint32_t eSize = alloc->mHal.state.elementSizeBytes;
     uint32_t lineSize = eSize * w;
 
-    if (alloc->mHal.drvState.mallocPtr) {
+    if (drv->lod[0].mallocPtr) {
         const uint8_t *src = static_cast<const uint8_t *>(data);
-        uint8_t *dst = (uint8_t *)alloc->mHal.drvState.mallocPtr;
-        dst += alloc->mHal.state.type->getLODFaceOffset(lod, face, xoff, yoff);
+        uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, lod, face);
 
         for (uint32_t line=yoff; line < (yoff+h); line++) {
             if (alloc->mHal.state.hasReferences) {
@@ -540,7 +585,7 @@
             }
             memcpy(dst, src, lineSize);
             src += lineSize;
-            dst += alloc->mHal.drvState.stride;
+            dst += drv->lod[lod].stride;
         }
         drv->uploadDeferred = true;
     } else {
@@ -555,6 +600,56 @@
 
 }
 
+void rsdAllocationRead1D(const Context *rsc, const Allocation *alloc,
+                         uint32_t xoff, uint32_t lod, uint32_t count,
+                         void *data, size_t sizeBytes) {
+    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+
+    const uint32_t eSize = alloc->mHal.state.type->getElementSizeBytes();
+    const uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
+    memcpy(data, ptr, count * eSize);
+}
+
+void rsdAllocationRead2D(const Context *rsc, const Allocation *alloc,
+                         uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
+                         uint32_t w, uint32_t h, void *data, size_t sizeBytes) {
+    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+
+    uint32_t eSize = alloc->mHal.state.elementSizeBytes;
+    uint32_t lineSize = eSize * w;
+
+    if (drv->lod[0].mallocPtr) {
+        uint8_t *dst = static_cast<uint8_t *>(data);
+        const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, lod, face);
+
+        for (uint32_t line=yoff; line < (yoff+h); line++) {
+            memcpy(dst, src, lineSize);
+            dst += lineSize;
+            src += drv->lod[lod].stride;
+        }
+    } else {
+        ALOGE("Add code to readback from non-script memory");
+    }
+}
+
+void rsdAllocationRead3D(const Context *rsc, const Allocation *alloc,
+                         uint32_t xoff, uint32_t yoff, uint32_t zoff,
+                         uint32_t lod, RsAllocationCubemapFace face,
+                         uint32_t w, uint32_t h, uint32_t d, void *data, uint32_t sizeBytes) {
+
+}
+
+void * rsdAllocationLock1D(const android::renderscript::Context *rsc,
+                          const android::renderscript::Allocation *alloc) {
+    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+    return drv->lod[0].mallocPtr;
+}
+
+void rsdAllocationUnlock1D(const android::renderscript::Context *rsc,
+                          const android::renderscript::Allocation *alloc) {
+
+}
+
 void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc,
                                const android::renderscript::Allocation *dstAlloc,
                                uint32_t dstXoff, uint32_t dstLod, uint32_t count,
@@ -562,20 +657,6 @@
                                uint32_t srcXoff, uint32_t srcLod) {
 }
 
-uint8_t *getOffsetPtr(const android::renderscript::Allocation *alloc,
-                      uint32_t xoff, uint32_t yoff, uint32_t lod,
-                      RsAllocationCubemapFace face) {
-    uint8_t *ptr = static_cast<uint8_t *>(alloc->getPtr());
-    ptr += alloc->getType()->getLODOffset(lod, xoff, yoff);
-
-    if (face != 0) {
-        uint32_t totalSizeBytes = alloc->getType()->getSizeBytes();
-        uint32_t faceOffset = totalSizeBytes / 6;
-        ptr += faceOffset * (uint32_t)face;
-    }
-    return ptr;
-}
-
 
 void rsdAllocationData2D_alloc_script(const android::renderscript::Context *rsc,
                                       const android::renderscript::Allocation *dstAlloc,
@@ -586,8 +667,8 @@
                                       RsAllocationCubemapFace srcFace) {
     uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes();
     for (uint32_t i = 0; i < h; i ++) {
-        uint8_t *dstPtr = getOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstLod, dstFace);
-        uint8_t *srcPtr = getOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcLod, srcFace);
+        uint8_t *dstPtr = GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstLod, dstFace);
+        uint8_t *srcPtr = GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcLod, srcFace);
         memcpy(dstPtr, srcPtr, w * elementSize);
 
         //ALOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)",
@@ -628,8 +709,7 @@
     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
 
     uint32_t eSize = alloc->mHal.state.elementSizeBytes;
-    uint8_t * ptr = (uint8_t *)alloc->mHal.drvState.mallocPtr;
-    ptr += eSize * x;
+    uint8_t * ptr = GetOffsetPtr(alloc, x, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
 
     const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
     ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
@@ -649,8 +729,7 @@
     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
 
     uint32_t eSize = alloc->mHal.state.elementSizeBytes;
-    uint8_t * ptr = (uint8_t *)alloc->mHal.drvState.mallocPtr;
-    ptr += (eSize * x) + (y * alloc->mHal.drvState.stride);
+    uint8_t * ptr = GetOffsetPtr(alloc, x, y, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
 
     const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
     ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
diff --git a/driver/rsdAllocation.h b/driver/rsdAllocation.h
index 0b196a1..98b1d65 100644
--- a/driver/rsdAllocation.h
+++ b/driver/rsdAllocation.h
@@ -19,6 +19,7 @@
 
 #include <rs_hal.h>
 #include <rsRuntime.h>
+#include <rsAllocation.h>
 
 #include <GLES/gl.h>
 #include <GLES2/gl2.h>
@@ -39,9 +40,6 @@
     // Is this a legal structure to be used as an FBO render target
     uint32_t renderTargetID;
 
-    uint32_t width;
-    uint32_t height;
-
     GLenum glTarget;
     GLenum glType;
     GLenum glFormat;
@@ -51,6 +49,19 @@
     RsdFrameBufferObj * readBackFBO;
     ANativeWindow *wnd;
     ANativeWindowBuffer *wndBuffer;
+
+    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;
+
+
 };
 
 GLenum rsdTypeToGLType(RsDataType t);
@@ -95,6 +106,27 @@
                          uint32_t lod, RsAllocationCubemapFace face,
                          uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes);
 
+void rsdAllocationRead1D(const android::renderscript::Context *rsc,
+                         const android::renderscript::Allocation *alloc,
+                         uint32_t xoff, uint32_t lod, uint32_t count,
+                         void *data, uint32_t sizeBytes);
+void rsdAllocationRead2D(const android::renderscript::Context *rsc,
+                         const android::renderscript::Allocation *alloc,
+                         uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
+                         uint32_t w, uint32_t h,
+                         void *data, uint32_t sizeBytes);
+void rsdAllocationRead3D(const android::renderscript::Context *rsc,
+                         const android::renderscript::Allocation *alloc,
+                         uint32_t xoff, uint32_t yoff, uint32_t zoff,
+                         uint32_t lod, RsAllocationCubemapFace face,
+                         uint32_t w, uint32_t h, uint32_t d, void *data, uint32_t sizeBytes);
+
+void * rsdAllocationLock1D(const android::renderscript::Context *rsc,
+                          const android::renderscript::Allocation *alloc);
+void rsdAllocationUnlock1D(const android::renderscript::Context *rsc,
+                          const android::renderscript::Allocation *alloc);
+
+
 void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc,
                                const android::renderscript::Allocation *dstAlloc,
                                uint32_t dstXoff, uint32_t dstLod, uint32_t count,
diff --git a/driver/rsdBcc.cpp b/driver/rsdBcc.cpp
index 5a15899..00d9cb1 100644
--- a/driver/rsdBcc.cpp
+++ b/driver/rsdBcc.cpp
@@ -17,6 +17,7 @@
 #include "rsdCore.h"
 #include "rsdBcc.h"
 #include "rsdRuntime.h"
+#include "rsdAllocation.h"
 
 #include <bcc/BCCContext.h>
 #include <bcc/RenderScript/RSCompilerDriver.h>
@@ -43,6 +44,8 @@
     bcc::BCCContext *mCompilerContext;
     bcc::RSCompilerDriver *mCompilerDriver;
     bcc::RSExecutable *mExecutable;
+
+    Allocation **mBoundAllocs;
 };
 
 typedef void (*outer_foreach_t)(
@@ -141,6 +144,11 @@
         script->mHal.info.root = drv->mRoot;
     }
 
+    if (script->mHal.info.exportedVariableCount) {
+        drv->mBoundAllocs = new Allocation *[script->mHal.info.exportedVariableCount];
+        memset(drv->mBoundAllocs, 0, sizeof(void *) * script->mHal.info.exportedVariableCount);
+    }
+
     pthread_mutex_unlock(&rsdgInitMutex);
     return true;
 
@@ -151,6 +159,7 @@
         delete drv->mCompilerContext;
         delete drv->mCompilerDriver;
         delete drv->mExecutable;
+        delete[] drv->mBoundAllocs;
         free(drv);
     }
     script->mHal.drv = NULL;
@@ -334,17 +343,19 @@
     mtls.ptrIn = NULL;
     mtls.eStrideIn = 0;
     if (ain) {
+        DrvAllocation *aindrv = (DrvAllocation *)ain->mHal.drv;
         mtls.ptrIn = (const uint8_t *)ain->getPtr();
         mtls.eStrideIn = ain->getType()->getElementSizeBytes();
-        mtls.yStrideIn = ain->mHal.drvState.stride;
+        mtls.yStrideIn = aindrv->lod[0].stride;
     }
 
     mtls.ptrOut = NULL;
     mtls.eStrideOut = 0;
     if (aout) {
+        DrvAllocation *aoutdrv = (DrvAllocation *)aout->mHal.drv;
         mtls.ptrOut = (uint8_t *)aout->getPtr();
         mtls.eStrideOut = aout->getType()->getElementSizeBytes();
-        mtls.yStrideOut = aout->mHal.drvState.stride;
+        mtls.yStrideOut = aoutdrv->lod[0].stride;
     }
 
     if ((dc->mWorkers.mCount > 1) && s->mHal.info.isThreadable && !dc->mInForEach) {
@@ -491,8 +502,9 @@
     memcpy(destPtr, data, dataLength);
 }
 
-void rsdScriptSetGlobalBind(const Context *dc, const Script *script, uint32_t slot, void *data) {
+void rsdScriptSetGlobalBind(const Context *dc, const Script *script, uint32_t slot, Allocation *data) {
     DrvScript *drv = (DrvScript *)script->mHal.drv;
+
     //rsAssert(!script->mFieldIsObject[slot]);
     //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data);
 
@@ -503,7 +515,13 @@
         return;
     }
 
-    memcpy(destPtr, &data, sizeof(void *));
+    void *ptr = NULL;
+    drv->mBoundAllocs[slot] = data;
+    if(data) {
+        DrvAllocation *allocDrv = (DrvAllocation *)data->mHal.drv;
+        ptr = allocDrv->lod[0].mallocPtr;
+    }
+    memcpy(destPtr, &ptr, sizeof(void *));
 }
 
 void rsdScriptSetGlobalObj(const Context *dc, const Script *script, uint32_t slot, ObjectBase *data) {
@@ -558,7 +576,28 @@
     delete drv->mCompilerContext;
     delete drv->mCompilerDriver;
     delete drv->mExecutable;
-
+    delete[] drv->mBoundAllocs;
     free(drv);
     script->mHal.drv = NULL;
 }
+
+Allocation * rsdScriptGetAllocationForPointer(const android::renderscript::Context *dc,
+                                              const android::renderscript::Script *sc,
+                                              const void *ptr) {
+    DrvScript *drv = (DrvScript *)sc->mHal.drv;
+    if (!ptr) {
+        return NULL;
+    }
+
+    for (uint32_t ct=0; ct < sc->mHal.info.exportedVariableCount; ct++) {
+        Allocation *a = drv->mBoundAllocs[ct];
+        if (!a) continue;
+        DrvAllocation *adrv = (DrvAllocation *)a->mHal.drv;
+        if (adrv->lod[0].mallocPtr == ptr) {
+            return a;
+        }
+    }
+    ALOGE("rsGetAllocation, failed to find %p", ptr);
+    return NULL;
+}
+
diff --git a/driver/rsdBcc.h b/driver/rsdBcc.h
index 7a4b138..ead6701 100644
--- a/driver/rsdBcc.h
+++ b/driver/rsdBcc.h
@@ -58,7 +58,7 @@
                                        size_t dimLength);
 void rsdScriptSetGlobalBind(const android::renderscript::Context *,
                             const android::renderscript::Script *,
-                            uint32_t slot, void *data);
+                            uint32_t slot, android::renderscript::Allocation *data);
 void rsdScriptSetGlobalObj(const android::renderscript::Context *,
                            const android::renderscript::Script *,
                            uint32_t slot, android::renderscript::ObjectBase *data);
@@ -76,5 +76,9 @@
 void rsdScriptDestroy(const android::renderscript::Context *dc,
                       android::renderscript::Script *script);
 
+android::renderscript::Allocation * rsdScriptGetAllocationForPointer(
+                        const android::renderscript::Context *dc,
+                        const android::renderscript::Script *script,
+                        const void *);
 
 #endif
diff --git a/driver/rsdCore.cpp b/driver/rsdCore.cpp
index 7b27a62..1a71d54 100644
--- a/driver/rsdCore.cpp
+++ b/driver/rsdCore.cpp
@@ -79,6 +79,11 @@
         rsdAllocationData1D,
         rsdAllocationData2D,
         rsdAllocationData3D,
+        rsdAllocationRead1D,
+        rsdAllocationRead2D,
+        rsdAllocationRead3D,
+        rsdAllocationLock1D,
+        rsdAllocationUnlock1D,
         rsdAllocationData1D_alloc,
         rsdAllocationData2D_alloc,
         rsdAllocationData3D_alloc,
diff --git a/driver/rsdMeshObj.cpp b/driver/rsdMeshObj.cpp
index 5dab84b..92e02be 100644
--- a/driver/rsdMeshObj.cpp
+++ b/driver/rsdMeshObj.cpp
@@ -151,7 +151,7 @@
             mAttribs[ct].ptr = NULL;
         } else {
             mAttribs[ct].buffer = 0;
-            mAttribs[ct].ptr = (const uint8_t*)alloc->mHal.drvState.mallocPtr;
+            mAttribs[ct].ptr = (const uint8_t*)alloc->mHal.drvState.mallocPtrLOD0;
         }
     }
 
@@ -172,7 +172,7 @@
         } else {
             RSD_CALL_GL(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER, 0);
             RSD_CALL_GL(glDrawElements, mGLPrimitives[primIndex], len, GL_UNSIGNED_SHORT,
-                        idxAlloc->mHal.drvState.mallocPtr);
+                        idxAlloc->mHal.drvState.mallocPtrLOD0);
         }
     } else {
         RSD_CALL_GL(glDrawArrays, mGLPrimitives[primIndex], start, len);
diff --git a/driver/rsdRuntimeStubs.cpp b/driver/rsdRuntimeStubs.cpp
index 5eb80c5..da92839 100644
--- a/driver/rsdRuntimeStubs.cpp
+++ b/driver/rsdRuntimeStubs.cpp
@@ -23,6 +23,7 @@
 
 #include "utils/Timers.h"
 #include "rsdCore.h"
+#include "rsdBcc.h"
 
 #include "rsdRuntime.h"
 #include "rsdPath.h"
@@ -380,7 +381,7 @@
 
 static const Allocation * SC_GetAllocation(const void *ptr) {
     GET_TLS();
-    return rsrGetAllocation(rsc, sc, ptr);
+    return rsdScriptGetAllocationForPointer(rsc, sc, ptr);
 }
 
 static void SC_ForEach_SAA(Script *target,
diff --git a/rsAllocation.cpp b/rsAllocation.cpp
index 95cc33e..ae1bd91 100644
--- a/rsAllocation.cpp
+++ b/rsAllocation.cpp
@@ -72,10 +72,6 @@
     rsc->mHal.funcs.allocation.syncAll(rsc, this, src);
 }
 
-void Allocation::read(void *data) {
-    memcpy(data, getPtr(), mHal.state.type->getSizeBytes());
-}
-
 void Allocation::data(Context *rsc, uint32_t xoff, uint32_t lod,
                          uint32_t count, const void *data, size_t sizeBytes) {
     const size_t eSize = mHal.state.type->getElementSizeBytes();
@@ -113,6 +109,39 @@
                       uint32_t w, uint32_t h, uint32_t d, const void *data, size_t sizeBytes) {
 }
 
+void Allocation::read(Context *rsc, uint32_t xoff, uint32_t lod,
+                         uint32_t count, void *data, size_t sizeBytes) {
+    const size_t eSize = mHal.state.type->getElementSizeBytes();
+
+    if ((count * eSize) != sizeBytes) {
+        ALOGE("Allocation::read called with mismatched size expected %zu, got %zu",
+             (count * eSize), sizeBytes);
+        mHal.state.type->dumpLOGV("type info");
+        return;
+    }
+
+    rsc->mHal.funcs.allocation.read1D(rsc, this, xoff, lod, count, data, sizeBytes);
+}
+
+void Allocation::read(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
+             uint32_t w, uint32_t h, void *data, size_t sizeBytes) {
+    const size_t eSize = mHal.state.elementSizeBytes;
+    const size_t lineSize = eSize * w;
+
+    if ((lineSize * h) != sizeBytes) {
+        ALOGE("Allocation size mismatch, expected %zu, got %zu", (lineSize * h), sizeBytes);
+        rsAssert(!"Allocation::read called with mismatched size");
+        return;
+    }
+
+    rsc->mHal.funcs.allocation.read2D(rsc, this, xoff, yoff, lod, face, w, h, data, sizeBytes);
+}
+
+void Allocation::read(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff,
+                      uint32_t lod, RsAllocationCubemapFace face,
+                      uint32_t w, uint32_t h, uint32_t d, void *data, size_t sizeBytes) {
+}
+
 void Allocation::elementData(Context *rsc, uint32_t x, const void *data,
                                 uint32_t cIdx, size_t sizeBytes) {
     size_t eSize = mHal.state.elementSizeBytes;
@@ -528,17 +557,11 @@
     AllocationGenerateScriptMips(rsc, texAlloc);
 }
 
-void rsi_AllocationCopyToBitmap(Context *rsc, RsAllocation va, void *data, size_t dataLen) {
-    Allocation *texAlloc = static_cast<Allocation *>(va);
-    const Type * t = texAlloc->getType();
-
-    size_t s = t->getDimX() * t->getDimY() * t->getElementSizeBytes();
-    if (s != dataLen) {
-        rsc->setError(RS_ERROR_BAD_VALUE, "Bitmap size didn't match allocation size");
-        return;
-    }
-
-    memcpy(data, texAlloc->getPtr(), s);
+void rsi_AllocationCopyToBitmap(Context *rsc, RsAllocation va, void *data, size_t sizeBytes) {
+    Allocation *a = static_cast<Allocation *>(va);
+    const Type * t = a->getType();
+    a->read(rsc, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X,
+            t->getDimX(), t->getDimY(), data, sizeBytes);
 }
 
 void rsi_Allocation1DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t lod,
@@ -565,9 +588,16 @@
     a->data(rsc, xoff, yoff, lod, face, w, h, data, sizeBytes);
 }
 
-void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data, size_t data_length) {
+void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data, size_t sizeBytes) {
     Allocation *a = static_cast<Allocation *>(va);
-    a->read(data);
+    const Type * t = a->getType();
+    if(t->getDimY()) {
+        a->read(rsc, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X,
+                t->getDimX(), t->getDimY(), data, sizeBytes);
+    } else {
+        a->read(rsc, 0, 0, t->getDimX(), data, sizeBytes);
+    }
+
 }
 
 void rsi_AllocationResize1D(Context *rsc, RsAllocation va, uint32_t dimX) {
@@ -610,7 +640,7 @@
 
 RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, RsType vtype,
                                             RsAllocationMipmapControl mips,
-                                            const void *data, size_t data_length, uint32_t usages) {
+                                            const void *data, size_t sizeBytes, uint32_t usages) {
     Type *t = static_cast<Type *>(vtype);
 
     RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mips, usages, 0);
@@ -620,7 +650,8 @@
         return NULL;
     }
 
-    memcpy(texAlloc->getPtr(), data, t->getDimX() * t->getDimY() * t->getElementSizeBytes());
+    texAlloc->data(rsc, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X,
+                   t->getDimX(), t->getDimY(), data, sizeBytes);
     if (mips == RS_ALLOCATION_MIPMAP_FULL) {
         AllocationGenerateScriptMips(rsc, texAlloc);
     }
@@ -631,7 +662,7 @@
 
 RsAllocation rsi_AllocationCubeCreateFromBitmap(Context *rsc, RsType vtype,
                                                 RsAllocationMipmapControl mips,
-                                                const void *data, size_t data_length, uint32_t usages) {
+                                                const void *data, size_t sizeBytes, uint32_t usages) {
     Type *t = static_cast<Type *>(vtype);
 
     // Cubemap allocation's faces should be Width by Width each.
@@ -650,11 +681,9 @@
 
     uint8_t *sourcePtr = (uint8_t*)data;
     for (uint32_t face = 0; face < 6; face ++) {
-        Adapter2D faceAdapter(rsc, texAlloc);
-        faceAdapter.setFace(face);
-
         for (uint32_t dI = 0; dI < faceSize; dI ++) {
-            memcpy(faceAdapter.getElement(0, dI), sourcePtr + strideBytes * dI, copySize);
+            texAlloc->data(rsc, 0, dI, 0, (RsAllocationCubemapFace)face,
+                           t->getDimX(), 1, sourcePtr + strideBytes * dI, copySize);
         }
 
         // Move the data pointer to the next cube face
diff --git a/rsAllocation.h b/rsAllocation.h
index 2da2dbf..9296654 100644
--- a/rsAllocation.h
+++ b/rsAllocation.h
@@ -41,6 +41,8 @@
     // The graphics equivalent of malloc.  The allocation contains a structure of elements.
 
 public:
+    const static int MAX_LOD = 16;
+
     struct Hal {
         void * drv;
 
@@ -67,8 +69,8 @@
         State state;
 
         struct DrvState {
-            mutable void * mallocPtr;
-            mutable uint32_t stride;
+            mutable void * mallocPtrLOD0;
+            mutable uint32_t strideLOD0;
         } drvState;
 
     };
@@ -80,7 +82,7 @@
     virtual ~Allocation();
     void updateCache();
 
-    void * getPtr() const {return mHal.drvState.mallocPtr;}
+    void * getPtr() const {return mHal.drvState.mallocPtrLOD0;}
     const Type * getType() const {return mHal.state.type;}
 
     void syncAll(Context *rsc, RsAllocationUsageType src);
@@ -96,13 +98,17 @@
     void data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t lod, RsAllocationCubemapFace face,
                  uint32_t w, uint32_t h, uint32_t d, const void *data, size_t sizeBytes);
 
+    void read(Context *rsc, uint32_t xoff, uint32_t lod, uint32_t count, void *data, size_t sizeBytes);
+    void read(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
+                 uint32_t w, uint32_t h, void *data, size_t sizeBytes);
+    void read(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t lod, RsAllocationCubemapFace face,
+                 uint32_t w, uint32_t h, uint32_t d, void *data, size_t sizeBytes);
+
     void elementData(Context *rsc, uint32_t x,
                      const void *data, uint32_t elementOff, size_t sizeBytes);
     void elementData(Context *rsc, uint32_t x, uint32_t y,
                      const void *data, uint32_t elementOff, size_t sizeBytes);
 
-    void read(void *data);
-
     void addProgramToDirty(const Program *);
     void removeProgramToDirty(const Program *);
 
@@ -152,7 +158,8 @@
     Allocation(Context *rsc, const Type *, uint32_t usages, RsAllocationMipmapControl mc, void *ptr);
 
     uint32_t getPackedSize() const;
-    static void writePackedData(Context *rsc, const Type *type, uint8_t *dst, const uint8_t *src, bool dstPadded);
+    static void writePackedData(Context *rsc, const Type *type, uint8_t *dst,
+                                const uint8_t *src, bool dstPadded);
     void unpackVec3Allocation(Context *rsc, const void *data, size_t dataSize);
     void packVec3Allocation(Context *rsc, OStream *stream) const;
 };
diff --git a/rsElement.cpp b/rsElement.cpp
index 4424938..3126c28 100644
--- a/rsElement.cpp
+++ b/rsElement.cpp
@@ -130,7 +130,7 @@
                                           component.getType(),
                                           component.getKind(),
                                           component.getIsNormalized(),
-                                          component.getVectorSize());;
+                                          component.getVectorSize());
     }
 
     const Element **subElems = new const Element *[fieldCount];
diff --git a/rsMesh.cpp b/rsMesh.cpp
index 89361e5..651a8f3 100644
--- a/rsMesh.cpp
+++ b/rsMesh.cpp
@@ -220,6 +220,7 @@
     uint32_t vectorSize = 0;
     uint32_t stride = 0;
     uint32_t numVerts = 0;
+    Allocation *posAlloc = NULL;
     // First we need to find the position ptr and stride
     for (uint32_t ct=0; ct < mHal.state.vertexBuffersCount; ct++) {
         const Type *bufferType = mHal.state.vertexBuffers[ct]->getType();
@@ -230,7 +231,10 @@
                 vectorSize = bufferElem->getField(ct)->getComponent().getVectorSize();
                 stride = bufferElem->getSizeBytes() / sizeof(float);
                 uint32_t offset = bufferElem->getFieldOffsetBytes(ct);
-                posPtr = (float*)((uint8_t*)mHal.state.vertexBuffers[ct]->getPtr() + offset);
+                posAlloc = mHal.state.vertexBuffers[ct];
+                const uint8_t *bp = (const uint8_t *)rsc->mHal.funcs.allocation.lock1D(
+                        rsc, posAlloc);
+                posPtr = (float*)(bp + offset);
                 numVerts = bufferType->getDimX();
                 break;
             }
@@ -256,6 +260,10 @@
         }
         posPtr += stride;
     }
+
+    if (posAlloc) {
+        rsc->mHal.funcs.allocation.unlock1D(rsc, posAlloc);
+    }
 }
 
 namespace android {
diff --git a/rsProgramFragment.cpp b/rsProgramFragment.cpp
index af2d396..438b620 100644
--- a/rsProgramFragment.cpp
+++ b/rsProgramFragment.cpp
@@ -53,8 +53,10 @@
     mConstantColor[1] = g;
     mConstantColor[2] = b;
     mConstantColor[3] = a;
-    memcpy(mHal.state.constants[0]->getPtr(), mConstantColor, 4*sizeof(float));
+    void *p = rsc->mHal.funcs.allocation.lock1D(rsc, mHal.state.constants[0]);
+    memcpy(p, mConstantColor, 4*sizeof(float));
     mDirty = true;
+    rsc->mHal.funcs.allocation.unlock1D(rsc, mHal.state.constants[0]);
 }
 
 void ProgramFragment::setup(Context *rsc, ProgramFragmentState *state) {
diff --git a/rsProgramVertex.cpp b/rsProgramVertex.cpp
index 4374e51..c2ce7ee 100644
--- a/rsProgramVertex.cpp
+++ b/rsProgramVertex.cpp
@@ -46,7 +46,8 @@
                           "Unable to set fixed function emulation matrices because allocation is missing");
             return;
         }
-        float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
+        float *f = static_cast<float *>(rsc->mHal.funcs.allocation.lock1D(
+                rsc, mHal.state.constants[0]));
         Matrix4x4 mvp;
         mvp.load(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
         Matrix4x4 t;
@@ -55,6 +56,7 @@
         for (uint32_t i = 0; i < 16; i ++) {
             f[RS_PROGRAM_VERTEX_MVP_OFFSET + i] = mvp.m[i];
         }
+        rsc->mHal.funcs.allocation.unlock1D(rsc, mHal.state.constants[0]);
     }
 
     state->mLast.set(this);
@@ -73,9 +75,11 @@
                       "Unable to set fixed function emulation matrix projection because allocation is missing");
         return;
     }
-    float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
+    float *f = static_cast<float *>(rsc->mHal.funcs.allocation.lock1D(
+                rsc, mHal.state.constants[0]));
     memcpy(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], m, sizeof(rsc_Matrix));
     mDirty = true;
+    rsc->mHal.funcs.allocation.unlock1D(rsc, mHal.state.constants[0]);
 }
 
 void ProgramVertex::setModelviewMatrix(Context *rsc, const rsc_Matrix *m) const {
@@ -89,9 +93,11 @@
                       "Unable to set fixed function emulation matrix modelview because allocation is missing");
         return;
     }
-    float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
+    float *f = static_cast<float *>(rsc->mHal.funcs.allocation.lock1D(
+                rsc, mHal.state.constants[0]));
     memcpy(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], m, sizeof(rsc_Matrix));
     mDirty = true;
+    rsc->mHal.funcs.allocation.unlock1D(rsc, mHal.state.constants[0]);
 }
 
 void ProgramVertex::setTextureMatrix(Context *rsc, const rsc_Matrix *m) const {
@@ -105,9 +111,11 @@
                       "Unable to set fixed function emulation matrix texture because allocation is missing");
         return;
     }
-    float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
+    float *f = static_cast<float *>(rsc->mHal.funcs.allocation.lock1D(
+            rsc, mHal.state.constants[0]));
     memcpy(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET], m, sizeof(rsc_Matrix));
     mDirty = true;
+    rsc->mHal.funcs.allocation.unlock1D(rsc, mHal.state.constants[0]);
 }
 
 void ProgramVertex::getProjectionMatrix(Context *rsc, rsc_Matrix *m) const {
@@ -121,19 +129,23 @@
                       "Unable to get fixed function emulation matrix projection because allocation is missing");
         return;
     }
-    float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
+    float *f = static_cast<float *>(
+            rsc->mHal.funcs.allocation.lock1D(rsc, mHal.state.constants[0]));
     memcpy(m, &f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], sizeof(rsc_Matrix));
+    rsc->mHal.funcs.allocation.unlock1D(rsc, mHal.state.constants[0]);
 }
 
 void ProgramVertex::transformToScreen(Context *rsc, float *v4out, const float *v3in) const {
     if (isUserProgram()) {
         return;
     }
-    float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
+    float *f = static_cast<float *>(
+            rsc->mHal.funcs.allocation.lock1D(rsc, mHal.state.constants[0]));
     Matrix4x4 mvp;
     mvp.loadMultiply((Matrix4x4 *)&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET],
                      (Matrix4x4 *)&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
     mvp.vectorMultiply(v4out, v3in);
+    rsc->mHal.funcs.allocation.unlock1D(rsc, mHal.state.constants[0]);
 }
 
 void ProgramVertex::serialize(Context *rsc, OStream *stream) const {
@@ -207,7 +219,7 @@
 }
 
 void ProgramVertexState::updateSize(Context *rsc) {
-    float *f = static_cast<float *>(mDefaultAlloc->getPtr());
+    float *f = static_cast<float *>(rsc->mHal.funcs.allocation.lock1D(rsc, mDefaultAlloc.get()));
 
     float surfaceWidth = (float)rsc->getCurrentSurfaceWidth();
     float surfaceHeight = (float)rsc->getCurrentSurfaceHeight();
@@ -220,6 +232,7 @@
     m.loadIdentity();
     memcpy(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], m.m, sizeof(m));
     memcpy(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET], m.m, sizeof(m));
+    rsc->mHal.funcs.allocation.unlock1D(rsc, mDefaultAlloc.get());
 }
 
 void ProgramVertexState::deinit(Context *rsc) {
diff --git a/rsRuntime.h b/rsRuntime.h
index 64f2de8..eff691b 100644
--- a/rsRuntime.h
+++ b/rsRuntime.h
@@ -149,7 +149,6 @@
 
 uint32_t rsrToClient(Context *, Script *, int cmdID, void *data, int len);
 uint32_t rsrToClientBlocking(Context *, Script *, int cmdID, void *data, int len);
-const Allocation * rsrGetAllocation(Context *, Script *, const void *ptr);
 
 void rsrAllocationMarkDirty(Context *, Script *, RsAllocation a);
 void rsrAllocationSyncAll(Context *, Script *, Allocation *a, RsAllocationUsageType source);
diff --git a/rsScript.cpp b/rsScript.cpp
index d39fb5e..b199496 100644
--- a/rsScript.cpp
+++ b/rsScript.cpp
@@ -48,11 +48,7 @@
     }
 
     mSlots[slot].set(a);
-    if (a != NULL) {
-        mRSC->mHal.funcs.script.setGlobalBind(mRSC, this, slot, a->getPtr());
-    } else {
-        mRSC->mHal.funcs.script.setGlobalBind(mRSC, this, slot, NULL);
-    }
+    mRSC->mHal.funcs.script.setGlobalBind(mRSC, this, slot, a);
 }
 
 void Script::setVar(uint32_t slot, const void *val, size_t len) {
diff --git a/rsScriptC.cpp b/rsScriptC.cpp
index 79725b9..466c18a 100644
--- a/rsScriptC.cpp
+++ b/rsScriptC.cpp
@@ -62,31 +62,10 @@
 
         if (!mTypes[ct].get())
             continue;
-        void *ptr = NULL;
-        if (mSlots[ct].get()) {
-            ptr = mSlots[ct]->getPtr();
-        }
-
-        rsc->mHal.funcs.script.setGlobalBind(rsc, this, ct, ptr);
+        rsc->mHal.funcs.script.setGlobalBind(rsc, this, ct, mSlots[ct].get());
     }
 }
 
-const Allocation *ScriptC::ptrToAllocation(const void *ptr) const {
-    //ALOGE("ptr to alloc %p", ptr);
-    if (!ptr) {
-        return NULL;
-    }
-    for (uint32_t ct=0; ct < mHal.info.exportedVariableCount; ct++) {
-        if (!mSlots[ct].get())
-            continue;
-        if (mSlots[ct]->getPtr() == ptr) {
-            return mSlots[ct].get();
-        }
-    }
-    ALOGE("ScriptC::ptrToAllocation, failed to find %p", ptr);
-    return NULL;
-}
-
 void ScriptC::setupGLState(Context *rsc) {
     if (mEnviroment.mFragmentStore.get()) {
         rsc->setProgramStore(mEnviroment.mFragmentStore.get());
diff --git a/rsScriptC.h b/rsScriptC.h
index 53a59f8..6bc41f2 100644
--- a/rsScriptC.h
+++ b/rsScriptC.h
@@ -38,10 +38,6 @@
     ScriptC(Context *);
     virtual ~ScriptC();
 
-
-    const Allocation *ptrToAllocation(const void *) const;
-
-
     virtual void Invoke(Context *rsc, uint32_t slot, const void *data, size_t len);
 
     virtual uint32_t run(Context *);
diff --git a/rsScriptC_Lib.cpp b/rsScriptC_Lib.cpp
index 749495d..ac3dd12 100644
--- a/rsScriptC_Lib.cpp
+++ b/rsScriptC_Lib.cpp
@@ -188,10 +188,6 @@
                               srcAlloc, srcXoff, srcYoff, srcMip, srcFace);
 }
 
-const Allocation * rsrGetAllocation(Context *rsc, Script *s, const void *ptr) {
-    ScriptC *sc = (ScriptC *)s;
-    return sc->ptrToAllocation(ptr);
-}
 
 }
 }
diff --git a/rs_hal.h b/rs_hal.h
index b4da744..5903805 100644
--- a/rs_hal.h
+++ b/rs_hal.h
@@ -108,7 +108,7 @@
                                          size_t dimLength);
         void (*setGlobalBind)(const Context *rsc, const Script *s,
                               uint32_t slot,
-                              void *data);
+                              Allocation *data);
         void (*setGlobalObj)(const Context *rsc, const Script *s,
                              uint32_t slot,
                              ObjectBase *data);
@@ -142,6 +142,24 @@
                        uint32_t lod, RsAllocationCubemapFace face,
                        uint32_t w, uint32_t h, uint32_t d, const void *data, size_t sizeBytes);
 
+        void (*read1D)(const Context *rsc, const Allocation *alloc,
+                       uint32_t xoff, uint32_t lod, uint32_t count,
+                       void *data, size_t sizeBytes);
+        void (*read2D)(const Context *rsc, const Allocation *alloc,
+                       uint32_t xoff, uint32_t yoff, uint32_t lod,
+                       RsAllocationCubemapFace face, uint32_t w, uint32_t h,
+                       void *data, size_t sizeBytes);
+        void (*read3D)(const Context *rsc, const Allocation *alloc,
+                       uint32_t xoff, uint32_t yoff, uint32_t zoff,
+                       uint32_t lod, RsAllocationCubemapFace face,
+                       uint32_t w, uint32_t h, uint32_t d, void *data, size_t sizeBytes);
+
+        // Lock and unlock make a 1D region of memory available to the CPU
+        // for direct access by pointer.  Once unlock is called control is
+        // returned to the SOC driver.
+        void * (*lock1D)(const Context *rsc, const Allocation *alloc);
+        void (*unlock1D)(const Context *rsc, const Allocation *alloc);
+
         // Allocation to allocation copies
         void (*allocData1D)(const Context *rsc,
                             const Allocation *dstAlloc,