Merge remote-tracking branch 'goog/master' into jb-mr1-dev
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,