Add support for non-malloc backed textures.

Change-Id: Iee8e987591caa17b4c8186f8173089925140a568
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index aab789a..78b570a 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -36,7 +36,7 @@
 
     mUsageFlags = usages;
 
-    mPtr = malloc(mType->getSizeBytes());
+    allocScriptMemory();
     if (mType->getElement()->getHasReferences()) {
         memset(mPtr, 0, mType->getSizeBytes());
     }
@@ -75,10 +75,9 @@
 Allocation::~Allocation() {
     if (mUserBitmapCallback != NULL) {
         mUserBitmapCallback(mUserBitmapCallbackData);
-    } else {
-        free(mPtr);
+        mPtr = NULL;
     }
-    mPtr = NULL;
+    freeScriptMemory();
 
     if (mBufferID) {
         // Causes a SW crash....
@@ -108,12 +107,9 @@
     return false;
 }
 
-void Allocation::deferedUploadToTexture(const Context *rsc, bool genMipmap, uint32_t lodOffset) {
-    rsAssert(lodOffset < mType->getLODCount());
+void Allocation::deferedUploadToTexture(const Context *rsc) {
     mUsageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE;
-    mTextureLOD = lodOffset;
     mUploadDefered = true;
-    mTextureGenMipmap = !mType->getDimLOD() && genMipmap;
 }
 
 uint32_t Allocation::getGLTarget() const {
@@ -130,6 +126,20 @@
     return 0;
 }
 
+void Allocation::allocScriptMemory() {
+    rsAssert(!mPtr);
+    mPtr = malloc(mType->getSizeBytes());
+}
+
+void Allocation::freeScriptMemory() {
+    rsAssert(!(mUsageFlags & RS_ALLOCATION_USAGE_SCRIPT));
+    if (mPtr) {
+        free(mPtr);
+        mPtr = NULL;
+    }
+}
+
+
 void Allocation::syncAll(Context *rsc, RsAllocationUsageType src) {
     rsAssert(src == RS_ALLOCATION_USAGE_SCRIPT);
 
@@ -153,6 +163,10 @@
         return;
     }
 
+    if (!mPtr) {
+        return;
+    }
+
     bool isFirstUpload = false;
 
     if (!mTextureID) {
@@ -171,41 +185,46 @@
     }
 
     GLenum target = (GLenum)getGLTarget();
-    glBindTexture(target, mTextureID);
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
     if (target == GL_TEXTURE_2D) {
-        upload2DTexture(isFirstUpload);
+        upload2DTexture(isFirstUpload, mPtr);
     } else if (target == GL_TEXTURE_CUBE_MAP) {
         uploadCubeTexture(isFirstUpload);
     }
 
-    if (mTextureGenMipmap) {
+    if (mMipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) {
 #ifndef ANDROID_RS_BUILD_FOR_HOST
         glGenerateMipmap(target);
 #endif //ANDROID_RS_BUILD_FOR_HOST
     }
 
+
+    if (!(mUsageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
+        freeScriptMemory();
+    }
+
     rsc->checkError("Allocation::uploadToTexture");
 }
 
-void Allocation::upload2DTexture(bool isFirstUpload) {
+void Allocation::upload2DTexture(bool isFirstUpload, const void *ptr) {
     GLenum type = mType->getElement()->getComponent().getGLType();
     GLenum format = mType->getElement()->getComponent().getGLFormat();
 
-    Adapter2D adapt(getContext(), this);
-    for (uint32_t lod = 0; (lod + mTextureLOD) < mType->getLODCount(); lod++) {
-        adapt.setLOD(lod+mTextureLOD);
+    GLenum target = (GLenum)getGLTarget();
+    glBindTexture(target, mTextureID);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 
-        uint16_t * ptr = static_cast<uint16_t *>(adapt.getElement(0,0));
+    for (uint32_t lod = 0; lod < mType->getLODCount(); lod++) {
+        const uint8_t *p = (const uint8_t *)ptr;
+        p += mType->getLODOffset(lod);
+
         if (isFirstUpload) {
             glTexImage2D(GL_TEXTURE_2D, lod, format,
-                         adapt.getDimX(), adapt.getDimY(),
-                         0, format, type, ptr);
+                         mType->getLODDimX(lod), mType->getLODDimY(lod),
+                         0, format, type, p);
         } else {
             glTexSubImage2D(GL_TEXTURE_2D, lod, 0, 0,
-                            adapt.getDimX(), adapt.getDimY(),
-                            format, type, ptr);
+                            mType->getLODDimX(lod), mType->getLODDimY(lod),
+                            format, type, p);
         }
     }
 }
@@ -214,6 +233,10 @@
     GLenum type = mType->getElement()->getComponent().getGLType();
     GLenum format = mType->getElement()->getComponent().getGLFormat();
 
+    GLenum target = (GLenum)getGLTarget();
+    glBindTexture(target, mTextureID);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
     GLenum faceOrder[] = {
         GL_TEXTURE_CUBE_MAP_POSITIVE_X,
         GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
@@ -227,8 +250,8 @@
     for (uint32_t face = 0; face < 6; face ++) {
         adapt.setFace(face);
 
-        for (uint32_t lod = 0; (lod + mTextureLOD) < mType->getLODCount(); lod++) {
-            adapt.setLOD(lod+mTextureLOD);
+        for (uint32_t lod = 0; lod < mType->getLODCount(); lod++) {
+            adapt.setLOD(lod);
 
             uint16_t * ptr = static_cast<uint16_t *>(adapt.getElement(0,0));
 
@@ -585,7 +608,7 @@
 
 void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, bool genmip, uint32_t baseMipLevel) {
     Allocation *alloc = static_cast<Allocation *>(va);
-    alloc->deferedUploadToTexture(rsc, genmip, baseMipLevel);
+    alloc->deferedUploadToTexture(rsc);
 }
 
 void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va) {
@@ -681,16 +704,21 @@
         return;
     }
 
-    memcpy(texAlloc->getPtr(), data, s);
-    if (genMips) {
-        Adapter2D adapt(rsc, texAlloc);
-        Adapter2D adapt2(rsc, texAlloc);
-        for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
-            adapt.setLOD(lod);
-            adapt2.setLOD(lod + 1);
-            mip(adapt2, adapt);
+    if (texAlloc->getIsScript()) {
+        memcpy(texAlloc->getPtr(), data, s);
+        if (genMips) {
+            Adapter2D adapt(rsc, texAlloc);
+            Adapter2D adapt2(rsc, texAlloc);
+            for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
+                adapt.setLOD(lod);
+                adapt2.setLOD(lod + 1);
+                mip(adapt2, adapt);
+            }
         }
+    } else {
+        texAlloc->upload2DTexture(false, data);
     }
+
 }
 
 void rsi_AllocationCopyToBitmap(Context *rsc, RsAllocation va, void *data, size_t dataLen) {
@@ -792,7 +820,7 @@
         }
     }
 
-    texAlloc->deferedUploadToTexture(rsc, false, 0);
+    texAlloc->deferedUploadToTexture(rsc);
     return texAlloc;
 }
 
@@ -836,6 +864,6 @@
         }
     }
 
-    texAlloc->deferedUploadToTexture(rsc, false, 0);
+    texAlloc->deferedUploadToTexture(rsc);
     return texAlloc;
 }
diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h
index d1dcb73..4a5f3da 100644
--- a/libs/rs/rsAllocation.h
+++ b/libs/rs/rsAllocation.h
@@ -45,7 +45,7 @@
 
     void syncAll(Context *rsc, RsAllocationUsageType src);
 
-    void deferedUploadToTexture(const Context *rsc, bool genMipmap, uint32_t lodOffset);
+    void deferedUploadToTexture(const Context *rsc);
     void uploadToTexture(const Context *rsc);
     uint32_t getTextureID() const {return mTextureID;}
 
@@ -87,6 +87,9 @@
 
     virtual void uploadCheck(Context *rsc);
 
+    bool getIsScript() const {
+        return (mUsageFlags & RS_ALLOCATION_USAGE_SCRIPT) != 0;
+    }
     bool getIsTexture() const {
         return (mUsageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) != 0;
     }
@@ -98,7 +101,11 @@
     void decRefs(const void *ptr, size_t ct, size_t startOff = 0) const;
 
     void sendDirty() const;
-    bool getHasGraphicsMipmaps() const {return mTextureGenMipmap;}
+    bool getHasGraphicsMipmaps() const {
+        return mMipmapControl != RS_ALLOCATION_MIPMAP_NONE;
+    }
+
+    void upload2DTexture(bool isFirstUpload, const void *ptr);
 
 protected:
     ObjectBaseRef<const Type> mType;
@@ -129,8 +136,6 @@
 
     // Is this a legal structure to be used as a texture source.
     // Initially this will require 1D or 2D and color data
-    bool mTextureGenMipmap;
-    uint32_t mTextureLOD;
     uint32_t mTextureID;
 
     // Is this a legal structure to be used as a vertex source.
@@ -142,8 +147,11 @@
 
 private:
     void init(Context *rsc, const Type *);
-    void upload2DTexture(bool isFirstUpload);
     void uploadCubeTexture(bool isFirstUpload);
+
+    void allocScriptMemory();
+    void freeScriptMemory();
+
 };
 
 }
diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp
index 3d17be2..3f9a9d6 100644
--- a/libs/rs/rsFont.cpp
+++ b/libs/rs/rsFont.cpp
@@ -463,7 +463,7 @@
 
     // This will dirty the texture and the shader so next time
     // we draw it will upload the data
-    mTextTexture->deferedUploadToTexture(mRSC, false, 0);
+    mTextTexture->deferedUploadToTexture(mRSC);
     mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get());
 
     // Some debug code
@@ -529,7 +529,7 @@
 
     Allocation *cacheAlloc = new Allocation(mRSC, texType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE);
     mTextTexture.set(cacheAlloc);
-    mTextTexture->deferedUploadToTexture(mRSC, false, 0);
+    mTextTexture->deferedUploadToTexture(mRSC);
 
     // Split up our cache texture into lines of certain widths
     int32_t nextLine = 0;