Add support for user-allocated buffers from the C++ API.

Bug: 7256604
Change-Id: Ia5d458ebadfd893e41130f90a1650258280a41cd
diff --git a/driver/rsdAllocation.cpp b/driver/rsdAllocation.cpp
index 82d87c2..ef3a707 100644
--- a/driver/rsdAllocation.cpp
+++ b/driver/rsdAllocation.cpp
@@ -283,9 +283,24 @@
 
     uint8_t * ptr = NULL;
     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) {
+    } else if (alloc->mHal.state.userProvidedPtr != NULL) {
+        // user-provided allocation
+        // limitations: no faces, no LOD, USAGE_SCRIPT only
+        if (alloc->mHal.state.usageFlags != RS_ALLOCATION_USAGE_SCRIPT) {
+            ALOGE("Can't use user-allocated buffers if usage is not USAGE_SCRIPT");
+            return false;
+        }
+        if (alloc->getType()->getDimLOD() || alloc->getType()->getDimFaces()) {
+            ALOGE("User-allocated buffers must not have multiple faces or LODs");
+            return false;
+        }
+        ptr = (uint8_t*)alloc->mHal.state.userProvidedPtr;
     } else {
-
-        ptr = (uint8_t *)malloc(allocSize);
+        if (forceZero) {
+            ptr = (uint8_t *)calloc(1, allocSize);
+        } else {
+            ptr = (uint8_t *)malloc(allocSize);
+        }
         if (!ptr) {
             free(drv);
             return false;
@@ -313,10 +328,6 @@
     drv->glType = rsdTypeToGLType(alloc->mHal.state.type->getElement()->getComponent().getType());
     drv->glFormat = rsdKindToGLFormat(alloc->mHal.state.type->getElement()->getComponent().getKind());
 
-    if (forceZero && ptr) {
-        memset(ptr, 0, alloc->mHal.state.type->getSizeBytes());
-    }
-
     if (alloc->mHal.state.usageFlags & ~RS_ALLOCATION_USAGE_SCRIPT) {
         drv->uploadDeferred = true;
     }
@@ -346,7 +357,10 @@
     }
 
     if (alloc->mHal.drvState.lod[0].mallocPtr) {
-        free(alloc->mHal.drvState.lod[0].mallocPtr);
+        // don't free user-allocated ptrs
+        if (!alloc->mHal.state.userProvidedPtr) {
+            free(alloc->mHal.drvState.lod[0].mallocPtr);
+        }
         alloc->mHal.drvState.lod[0].mallocPtr = NULL;
     }
     if (drv->readBackFBO != NULL) {
diff --git a/rsAllocation.cpp b/rsAllocation.cpp
index df0a79e..f4f6d95 100644
--- a/rsAllocation.cpp
+++ b/rsAllocation.cpp
@@ -33,6 +33,7 @@
     mHal.state.mipmapControl = RS_ALLOCATION_MIPMAP_NONE;
     mHal.state.usageFlags = usages;
     mHal.state.mipmapControl = mc;
+    mHal.state.userProvidedPtr = ptr;
 
     setType(type);
     updateCache();
diff --git a/rsAllocation.h b/rsAllocation.h
index b552ca3..5ee9afb 100644
--- a/rsAllocation.h
+++ b/rsAllocation.h
@@ -61,7 +61,7 @@
             bool hasMipmaps;
             bool hasFaces;
             bool hasReferences;
-            void * unused_01;
+            void * userProvidedPtr;
             int32_t surfaceTextureID;
             ANativeWindow *wndSurface;
             SurfaceTexture *surfaceTexture;