Merge "Revert "Removing changes not meant for MR1"" into graphics-dev
diff --git a/Android.mk b/Android.mk
index 58d3e5c..7f0cbeb 100644
--- a/Android.mk
+++ b/Android.mk
@@ -96,6 +96,7 @@
 	rsMatrix4x4.cpp \
 	rsMesh.cpp \
 	rsMutex.cpp \
+	rsPath.cpp \
 	rsProgram.cpp \
 	rsProgramFragment.cpp \
 	rsProgramStore.cpp \
@@ -118,6 +119,7 @@
 	driver/rsdGL.cpp \
 	driver/rsdMesh.cpp \
 	driver/rsdMeshObj.cpp \
+	driver/rsdPath.cpp \
 	driver/rsdProgram.cpp \
 	driver/rsdProgramRaster.cpp \
 	driver/rsdProgramStore.cpp \
@@ -203,6 +205,7 @@
 	rsMatrix4x4.cpp \
 	rsMesh.cpp \
 	rsMutex.cpp \
+	rsPath.cpp \
 	rsProgram.cpp \
 	rsProgramFragment.cpp \
 	rsProgramStore.cpp \
diff --git a/RenderScriptDefines.h b/RenderScriptDefines.h
index d092520..728b27a 100644
--- a/RenderScriptDefines.h
+++ b/RenderScriptDefines.h
@@ -41,6 +41,7 @@
 typedef void * RsSampler;
 typedef void * RsScript;
 typedef void * RsMesh;
+typedef void * RsPath;
 typedef void * RsType;
 typedef void * RsObjectBase;
 
@@ -258,6 +259,11 @@
     RS_PRIMITIVE_TRIANGLE_FAN
 };
 
+enum RsPathPrimitive {
+    RS_PATH_PRIMITIVE_QUADRATIC_BEZIER,
+    RS_PATH_PRIMITIVE_CUBIC_BEZIER
+};
+
 enum RsError {
     RS_ERROR_NONE = 0,
     RS_ERROR_BAD_SHADER = 1,
diff --git a/driver/rsdAllocation.cpp b/driver/rsdAllocation.cpp
index e79cd0f..e072dab 100644
--- a/driver/rsdAllocation.cpp
+++ b/driver/rsdAllocation.cpp
@@ -212,10 +212,13 @@
         return false;
     }
 
-    void * ptr = malloc(alloc->mHal.state.type->getSizeBytes());
+    void * ptr = alloc->mHal.state.usrPtr;
     if (!ptr) {
-        free(drv);
-        return false;
+        ptr = malloc(alloc->mHal.state.type->getSizeBytes());
+        if (!ptr) {
+            free(drv);
+            return false;
+        }
     }
 
     drv->glTarget = GL_NONE;
@@ -269,7 +272,7 @@
         drv->renderTargetID = 0;
     }
 
-    if (drv->mallocPtr) {
+    if (drv->mallocPtr && !alloc->mHal.state.usrPtr) {
         free(drv->mallocPtr);
         drv->mallocPtr = NULL;
     }
diff --git a/driver/rsdBcc.cpp b/driver/rsdBcc.cpp
index c16091c..917b419 100644
--- a/driver/rsdBcc.cpp
+++ b/driver/rsdBcc.cpp
@@ -72,7 +72,7 @@
     //LOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc);
 
     pthread_mutex_lock(&rsdgInitMutex);
-    char *cachePath = NULL;
+
     size_t exportFuncCount = 0;
     size_t exportVarCount = 0;
     size_t objectSlotCount = 0;
@@ -122,8 +122,6 @@
         goto error;
     }
 
-    free(cachePath);
-
     drv->mRoot = reinterpret_cast<int (*)()>(bccGetFuncAddr(drv->mBccScript, "root"));
     drv->mInit = reinterpret_cast<void (*)()>(bccGetFuncAddr(drv->mBccScript, "init"));
     drv->mFreeChildren = reinterpret_cast<void (*)()>(bccGetFuncAddr(drv->mBccScript, ".rs.dtor"));
diff --git a/driver/rsdCore.cpp b/driver/rsdCore.cpp
index 9292fa1..a65e23b 100644
--- a/driver/rsdCore.cpp
+++ b/driver/rsdCore.cpp
@@ -18,6 +18,7 @@
 #include "rsdAllocation.h"
 #include "rsdBcc.h"
 #include "rsdGL.h"
+#include "rsdPath.h"
 #include "rsdProgramStore.h"
 #include "rsdProgramRaster.h"
 #include "rsdProgramVertex.h"
@@ -115,6 +116,13 @@
     },
 
     {
+        rsdPathInitStatic,
+        rsdPathInitDynamic,
+        rsdPathDraw,
+        rsdPathDestroy
+    },
+
+    {
         rsdSamplerInit,
         rsdSamplerDestroy
     },
diff --git a/driver/rsdPath.cpp b/driver/rsdPath.cpp
new file mode 100644
index 0000000..d475beb
--- /dev/null
+++ b/driver/rsdPath.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <GLES/gl.h>
+#include <GLES2/gl2.h>
+#include <GLES/glext.h>
+
+#include <rs_hal.h>
+#include <rsContext.h>
+#include <rsPath.h>
+
+#include "rsdCore.h"
+#include "rsdPath.h"
+#include "rsdAllocation.h"
+#include "rsdGL.h"
+#include "rsdVertexArray.h"
+#include "rsdShaderCache.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+class DrvPath {
+protected:
+    DrvPath();
+public:
+    virtual ~DrvPath();
+    virtual void draw(Context *) = 0;
+};
+
+class DrvPathStatic : public DrvPath {
+public:
+    typedef struct {
+        float x1, xc, x2;
+        float y1, yc, y2;
+    } segment_t;
+
+    segment_t *mSegments;
+    uint32_t mSegmentCount;
+
+    DrvPathStatic(const Allocation *vtx, const Allocation *loops);
+    virtual ~DrvPathStatic();
+
+    virtual void draw(Context *);
+};
+
+class DrvPathDynamic : public DrvPath {
+public:
+    DrvPathDynamic();
+    virtual ~DrvPathDynamic();
+};
+
+static void cleanup(const Context *rsc, const Path *m) {
+    DrvPath *dp = (DrvPath *)m->mHal.drv;
+    if (dp) {
+        delete dp;
+    }
+}
+
+bool rsdPathInitStatic(const Context *rsc, const Path *m,
+                       const Allocation *vtx, const Allocation *loops) {
+    DrvPathStatic *drv = NULL;
+    cleanup(rsc, m);
+
+    DrvPathStatic *dps = new DrvPathStatic(vtx, loops);
+    LOGE("init path m %p,  %p", m, dps);
+    m->mHal.drv = dps;
+    return dps != NULL;
+}
+
+bool rsdPathInitDynamic(const Context *rsc, const Path *m) {
+    return false;
+}
+
+
+void rsdPathDraw(const Context *rsc, const Path *m) {
+    LOGE("render m=%p", m);
+
+    DrvPath *drv = (DrvPath *)m->mHal.drv;
+    if(drv) {
+        LOGE("render 2 drv=%p", drv);
+        drv->draw((Context *)rsc);
+    }
+}
+
+void rsdPathDestroy(const Context *rsc, const Path *m) {
+    cleanup(rsc, m);
+    m->mHal.drv = NULL;
+}
+
+
+
+
+DrvPath::DrvPath() {
+}
+
+DrvPath::~DrvPath() {
+}
+
+DrvPathStatic::DrvPathStatic(const Allocation *vtx, const Allocation *loops) {
+    mSegmentCount = vtx->getType()->getDimX() / 3;
+    mSegments = new segment_t[mSegmentCount];
+
+    const float *fin = (const float *)vtx->getPtr();
+    for (uint32_t ct=0; ct < mSegmentCount; ct++) {
+        segment_t *s = &mSegments[ct];
+        s->x1 = fin[0];
+        s->y1 = fin[1];
+
+        s->xc = fin[2];
+        s->yc = fin[3];
+
+        s->x2 = fin[4];
+        s->y2 = fin[5];
+        fin += 6;
+    }
+}
+
+DrvPathStatic::~DrvPathStatic() {
+}
+
+void DrvPathStatic::draw(Context *rsc) {
+    const static float color[24] = {
+        1.f, 0.f, 0.f, 1.f,  0.5f, 0.f, 0.f, 1.f,
+        1.f, 0.f, 0.f, 1.f,  0.5f, 0.f, 0.f, 1.f,
+        1.f, 1.f, 1.f, 1.f,  1.f, 1.f, 1.f, 1.f};
+    float vtx[12];
+
+    LOGE("draw");
+    if (!rsc->setupCheck()) {
+        return;
+    }
+
+    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+    if (!dc->gl.shaderCache->setup(rsc)) {
+        return;
+    }
+
+    RsdVertexArray::Attrib attribs[2];
+    attribs[0].set(GL_FLOAT, 2, 8, false, (uint32_t)vtx, "ATTRIB_position");
+    attribs[1].set(GL_FLOAT, 4, 16, false, (uint32_t)color, "ATTRIB_color");
+    RsdVertexArray va(attribs, 2);
+    va.setup(rsc);
+
+    LOGE("mSegmentCount %i", mSegmentCount);
+    for (uint32_t ct=0; ct < mSegmentCount; ct++) {
+        segment_t *s = &mSegments[ct];
+
+        vtx[0] = s->x1;
+        vtx[1] = s->y1;
+        vtx[2] = s->xc;
+        vtx[3] = s->yc;
+
+        vtx[4] = s->x2;
+        vtx[5] = s->y2;
+        vtx[6] = s->xc;
+        vtx[7] = s->yc;
+
+        vtx[8] = s->x1;
+        vtx[9] = s->y1;
+        vtx[10] = s->x2;
+        vtx[11] = s->y2;
+
+        RSD_CALL_GL(glDrawArrays, GL_LINES, 0, 6);
+    }
+
+}
+
+DrvPathDynamic::DrvPathDynamic() {
+}
+
+DrvPathDynamic::~DrvPathDynamic() {
+}
diff --git a/driver/rsdPath.h b/driver/rsdPath.h
new file mode 100644
index 0000000..fa00972
--- /dev/null
+++ b/driver/rsdPath.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSD_PATH_H
+#define RSD_PATH_H
+
+#include <rs_hal.h>
+
+
+bool rsdPathInitStatic(const android::renderscript::Context *rsc,
+                       const android::renderscript::Path *m,
+                       const android::renderscript::Allocation *vertex,
+                       const android::renderscript::Allocation *loops);
+bool rsdPathInitDynamic(const android::renderscript::Context *rsc,
+                        const android::renderscript::Path *m);
+void rsdPathDraw(const android::renderscript::Context *rsc,
+                 const android::renderscript::Path *m);
+void rsdPathDestroy(const android::renderscript::Context *rsc,
+                    const android::renderscript::Path *m);
+
+
+#endif
diff --git a/driver/rsdRuntimeStubs.cpp b/driver/rsdRuntimeStubs.cpp
index 90c8928..c2201be 100644
--- a/driver/rsdRuntimeStubs.cpp
+++ b/driver/rsdRuntimeStubs.cpp
@@ -25,6 +25,7 @@
 #include "rsdCore.h"
 
 #include "rsdRuntime.h"
+#include "rsdPath.h"
 
 #include <time.h>
 
@@ -204,6 +205,12 @@
     rsrDrawRect(rsc, sc, x1, y1, x2, y2, z);
 }
 
+static void SC_DrawPath(Path *p) {
+    GET_TLS();
+    //rsrDrawPath(rsc, sc, p);
+    rsdPathDraw(rsc, p);
+}
+
 static void SC_DrawMesh(Mesh *m) {
     GET_TLS();
     rsrDrawMesh(rsc, sc, m);
@@ -533,6 +540,10 @@
     { "_Z13rsClearObjectP9rs_script", (void *)&SC_ClearObject, true },
     { "_Z10rsIsObject9rs_script", (void *)&SC_IsObject, true },
 
+    { "_Z11rsSetObjectP7rs_pathS_", (void *)&SC_SetObject, true },
+    { "_Z13rsClearObjectP7rs_path", (void *)&SC_ClearObject, true },
+    { "_Z10rsIsObject7rs_path", (void *)&SC_IsObject, true },
+
     { "_Z11rsSetObjectP7rs_meshS_", (void *)&SC_SetObject, true },
     { "_Z13rsClearObjectP7rs_mesh", (void *)&SC_ClearObject, true },
     { "_Z10rsIsObject7rs_mesh", (void *)&SC_IsObject, true },
@@ -603,6 +614,8 @@
     { "_Z11rsgDrawMesh7rs_meshjjj", (void *)&SC_DrawMeshPrimitiveRange, false },
     { "_Z25rsgMeshComputeBoundingBox7rs_meshPfS0_S0_S0_S0_S0_", (void *)&SC_MeshComputeBoundingBox, false },
 
+    { "_Z11rsgDrawPath7rs_path", (void *)&SC_DrawPath, false },
+
     { "_Z13rsgClearColorffff", (void *)&SC_ClearColor, false },
     { "_Z13rsgClearDepthf", (void *)&SC_ClearDepth, false },
 
diff --git a/rs.spec b/rs.spec
index 20b1f52..d60db7e 100644
--- a/rs.spec
+++ b/rs.spec
@@ -42,6 +42,7 @@
     param RsType vtype
     param RsAllocationMipmapControl mips
     param uint32_t usages
+    param uint32_t ptr
     ret RsAllocation
 }
 
@@ -388,3 +389,13 @@
 	param uint32_t *primType
 	ret RsMesh
 	}
+
+PathCreate {
+    param RsPathPrimitive pp
+    param bool isStatic
+    param RsAllocation vertex
+    param RsAllocation loops
+    param float quality
+    ret RsPath
+    }
+
diff --git a/rsAllocation.cpp b/rsAllocation.cpp
index 35d812d..2c360fb 100644
--- a/rsAllocation.cpp
+++ b/rsAllocation.cpp
@@ -22,21 +22,22 @@
 using namespace android::renderscript;
 
 Allocation::Allocation(Context *rsc, const Type *type, uint32_t usages,
-                       RsAllocationMipmapControl mc)
+                       RsAllocationMipmapControl mc, void * ptr)
     : ObjectBase(rsc) {
 
     memset(&mHal, 0, sizeof(mHal));
     mHal.state.mipmapControl = RS_ALLOCATION_MIPMAP_NONE;
     mHal.state.usageFlags = usages;
     mHal.state.mipmapControl = mc;
+    mHal.state.usrPtr = ptr;
 
     setType(type);
     updateCache();
 }
 
 Allocation * Allocation::createAllocation(Context *rsc, const Type *type, uint32_t usages,
-                              RsAllocationMipmapControl mc) {
-    Allocation *a = new Allocation(rsc, type, usages, mc);
+                              RsAllocationMipmapControl mc, void * ptr) {
+    Allocation *a = new Allocation(rsc, type, usages, mc, ptr);
 
     if (!rsc->mHal.funcs.allocation.init(rsc, a, type->getElement()->getHasReferences())) {
         rsc->setError(RS_ERROR_FATAL_DRIVER, "Allocation::Allocation, alloc failure");
@@ -195,6 +196,81 @@
          prefix, getPtr(), mHal.state.usageFlags, mHal.state.mipmapControl);
 }
 
+uint32_t Allocation::getPackedSize() const {
+    uint32_t numItems = mHal.state.type->getSizeBytes() / mHal.state.type->getElementSizeBytes();
+    return numItems * mHal.state.type->getElement()->getSizeBytesUnpadded();
+}
+
+void Allocation::writePackedData(const Type *type,
+                                 uint8_t *dst, const uint8_t *src, bool dstPadded) {
+    const Element *elem = type->getElement();
+    uint32_t unpaddedBytes = elem->getSizeBytesUnpadded();
+    uint32_t paddedBytes = elem->getSizeBytes();
+    uint32_t numItems = type->getSizeBytes() / paddedBytes;
+
+    uint32_t srcInc = !dstPadded ? paddedBytes : unpaddedBytes;
+    uint32_t dstInc =  dstPadded ? paddedBytes : unpaddedBytes;
+
+    // no sub-elements
+    uint32_t fieldCount = elem->getFieldCount();
+    if (fieldCount == 0) {
+        for (uint32_t i = 0; i < numItems; i ++) {
+            memcpy(dst, src, unpaddedBytes);
+            src += srcInc;
+            dst += dstInc;
+        }
+        return;
+    }
+
+    // Cache offsets
+    uint32_t *offsetsPadded = new uint32_t[fieldCount];
+    uint32_t *offsetsUnpadded = new uint32_t[fieldCount];
+    uint32_t *sizeUnpadded = new uint32_t[fieldCount];
+
+    for (uint32_t i = 0; i < fieldCount; i++) {
+        offsetsPadded[i] = elem->getFieldOffsetBytes(i);
+        offsetsUnpadded[i] = elem->getFieldOffsetBytesUnpadded(i);
+        sizeUnpadded[i] = elem->getField(i)->getSizeBytesUnpadded();
+    }
+
+    uint32_t *srcOffsets = !dstPadded ? offsetsPadded : offsetsUnpadded;
+    uint32_t *dstOffsets =  dstPadded ? offsetsPadded : offsetsUnpadded;
+
+    // complex elements, need to copy subelem after subelem
+    for (uint32_t i = 0; i < numItems; i ++) {
+        for (uint32_t fI = 0; fI < fieldCount; fI++) {
+            memcpy(dst + dstOffsets[fI], src + srcOffsets[fI], sizeUnpadded[fI]);
+        }
+        src += srcInc;
+        dst += dstInc;
+    }
+
+    delete[] offsetsPadded;
+    delete[] offsetsUnpadded;
+    delete[] sizeUnpadded;
+}
+
+void Allocation::unpackVec3Allocation(const void *data, uint32_t dataSize) {
+    const uint8_t *src = (const uint8_t*)data;
+    uint8_t *dst = (uint8_t*)getPtr();
+
+    writePackedData(getType(), dst, src, true);
+}
+
+void Allocation::packVec3Allocation(OStream *stream) const {
+    uint32_t paddedBytes = getType()->getElement()->getSizeBytes();
+    uint32_t unpaddedBytes = getType()->getElement()->getSizeBytesUnpadded();
+    uint32_t numItems = mHal.state.type->getSizeBytes() / paddedBytes;
+
+    const uint8_t *src = (const uint8_t*)getPtr();
+    uint8_t *dst = new uint8_t[numItems * unpaddedBytes];
+
+    writePackedData(getType(), dst, src, false);
+    stream->addByteArray(dst, getPackedSize());
+
+    delete[] dst;
+}
+
 void Allocation::serialize(OStream *stream) const {
     // Need to identify ourselves
     stream->addU32((uint32_t)getClassId());
@@ -207,10 +283,17 @@
     mHal.state.type->serialize(stream);
 
     uint32_t dataSize = mHal.state.type->getSizeBytes();
+    // 3 element vectors are padded to 4 in memory, but padding isn't serialized
+    uint32_t packedSize = getPackedSize();
     // Write how much data we are storing
-    stream->addU32(dataSize);
-    // Now write the data
-    stream->addByteArray(getPtr(), dataSize);
+    stream->addU32(packedSize);
+    if (dataSize == packedSize) {
+        // Now write the data
+        stream->addByteArray(getPtr(), dataSize);
+    } else {
+        // Now write the data
+        packVec3Allocation(stream);
+    }
 }
 
 Allocation *Allocation::createFromStream(Context *rsc, IStream *stream) {
@@ -230,22 +313,30 @@
     }
     type->compute();
 
+    Allocation *alloc = Allocation::createAllocation(rsc, type, RS_ALLOCATION_USAGE_SCRIPT);
+    type->decUserRef();
+
     // Number of bytes we wrote out for this allocation
     uint32_t dataSize = stream->loadU32();
-    if (dataSize != type->getSizeBytes()) {
+    // 3 element vectors are padded to 4 in memory, but padding isn't serialized
+    uint32_t packedSize = alloc->getPackedSize();
+    if (dataSize != type->getSizeBytes() &&
+        dataSize != packedSize) {
         LOGE("failed to read allocation because numbytes written is not the same loaded type wants\n");
+        ObjectBase::checkDelete(alloc);
         ObjectBase::checkDelete(type);
         return NULL;
     }
 
-    Allocation *alloc = Allocation::createAllocation(rsc, type, RS_ALLOCATION_USAGE_SCRIPT);
     alloc->setName(name.string(), name.size());
-    type->decUserRef();
 
-    uint32_t count = dataSize / type->getElementSizeBytes();
-
-    // Read in all of our allocation data
-    alloc->data(rsc, 0, 0, count, stream->getPtr() + stream->getPos(), dataSize);
+    if (dataSize == type->getSizeBytes()) {
+        uint32_t count = dataSize / type->getElementSizeBytes();
+        // Read in all of our allocation data
+        alloc->data(rsc, 0, 0, count, stream->getPtr() + stream->getPos(), dataSize);
+    } else {
+        alloc->unpackVec3Allocation(stream->getPtr() + stream->getPos(), dataSize);
+    }
     stream->reset(stream->getPos() + dataSize);
 
     return alloc;
@@ -480,8 +571,8 @@
 
 RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype,
                                        RsAllocationMipmapControl mips,
-                                       uint32_t usages) {
-    Allocation * alloc = Allocation::createAllocation(rsc, static_cast<Type *>(vtype), usages, mips);
+                                       uint32_t usages, uint32_t ptr) {
+    Allocation * alloc = Allocation::createAllocation(rsc, static_cast<Type *>(vtype), usages, mips, (void *)ptr);
     if (!alloc) {
         return NULL;
     }
@@ -494,7 +585,7 @@
                                             const void *data, size_t data_length, uint32_t usages) {
     Type *t = static_cast<Type *>(vtype);
 
-    RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mips, usages);
+    RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mips, usages, 0);
     Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
     if (texAlloc == NULL) {
         LOGE("Memory allocation failure");
@@ -518,7 +609,7 @@
     // Cubemap allocation's faces should be Width by Width each.
     // Source data should have 6 * Width by Width pixels
     // Error checking is done in the java layer
-    RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mips, usages);
+    RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mips, usages, 0);
     Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
     if (texAlloc == NULL) {
         LOGE("Memory allocation failure");
diff --git a/rsAllocation.h b/rsAllocation.h
index 714798a..0f7ed42 100644
--- a/rsAllocation.h
+++ b/rsAllocation.h
@@ -55,6 +55,8 @@
             bool hasMipmaps;
             bool hasFaces;
             bool hasReferences;
+
+            void * usrPtr;
         };
         State state;
 
@@ -66,7 +68,8 @@
     Hal mHal;
 
     static Allocation * createAllocation(Context *rsc, const Type *, uint32_t usages,
-                                  RsAllocationMipmapControl mc = RS_ALLOCATION_MIPMAP_NONE);
+                                         RsAllocationMipmapControl mc = RS_ALLOCATION_MIPMAP_NONE,
+                                         void *ptr = 0);
     virtual ~Allocation();
     void updateCache();
 
@@ -134,7 +137,12 @@
 
 private:
     void freeChildrenUnlocked();
-    Allocation(Context *rsc, const Type *, uint32_t usages, RsAllocationMipmapControl mc);
+    Allocation(Context *rsc, const Type *, uint32_t usages, RsAllocationMipmapControl mc, void *ptr);
+
+    uint32_t getPackedSize() const;
+    static void writePackedData(const Type *type, uint8_t *dst, const uint8_t *src, bool dstPadded);
+    void unpackVec3Allocation(const void *data, uint32_t dataSize);
+    void packVec3Allocation(OStream *stream) const;
 };
 
 }
diff --git a/rsComponent.cpp b/rsComponent.cpp
index 7d9cf0b..21b98f6 100644
--- a/rsComponent.cpp
+++ b/rsComponent.cpp
@@ -169,7 +169,8 @@
         break;
     }
 
-    mBits = mTypeBits * mVectorSize;
+    mBitsUnpadded = mTypeBits * mVectorSize;
+    mBits = mTypeBits * rsHigherPow2(mVectorSize);
 }
 
 bool Component::isReference() const {
diff --git a/rsComponent.h b/rsComponent.h
index 6ddc990..8629d0d 100644
--- a/rsComponent.h
+++ b/rsComponent.h
@@ -41,6 +41,7 @@
     bool getIsFloat() const {return mIsFloat;}
     bool getIsSigned() const {return mIsSigned;}
     uint32_t getBits() const {return mBits;}
+    uint32_t getBitsUnpadded() const {return mBitsUnpadded;}
 
     // Helpers for reading / writing this class out
     void serialize(OStream *stream) const;
@@ -56,6 +57,7 @@
 
     // derived
     uint32_t mBits;
+    uint32_t mBitsUnpadded;
     uint32_t mTypeBits;
     bool mIsFloat;
     bool mIsSigned;
diff --git a/rsContext.cpp b/rsContext.cpp
index f8213a1..293fc3a 100644
--- a/rsContext.cpp
+++ b/rsContext.cpp
@@ -472,6 +472,30 @@
     }
 }
 
+uint32_t Context::getCurrentSurfaceWidth() const {
+    for (uint32_t i = 0; i < mFBOCache.mHal.state.colorTargetsCount; i ++) {
+        if (mFBOCache.mHal.state.colorTargets[i] != NULL) {
+            return mFBOCache.mHal.state.colorTargets[i]->getType()->getDimX();
+        }
+    }
+    if (mFBOCache.mHal.state.depthTarget != NULL) {
+        return mFBOCache.mHal.state.depthTarget->getType()->getDimX();
+    }
+    return mWidth;
+}
+
+uint32_t Context::getCurrentSurfaceHeight() const {
+    for (uint32_t i = 0; i < mFBOCache.mHal.state.colorTargetsCount; i ++) {
+        if (mFBOCache.mHal.state.colorTargets[i] != NULL) {
+            return mFBOCache.mHal.state.colorTargets[i]->getType()->getDimY();
+        }
+    }
+    if (mFBOCache.mHal.state.depthTarget != NULL) {
+        return mFBOCache.mHal.state.depthTarget->getType()->getDimY();
+    }
+    return mHeight;
+}
+
 void Context::pause() {
     rsAssert(mIsGraphicsContext);
     mPaused = true;
diff --git a/rsContext.h b/rsContext.h
index 199cc5a..9f8cc4a 100644
--- a/rsContext.h
+++ b/rsContext.h
@@ -32,6 +32,7 @@
 #include "rsAdapter.h"
 #include "rsSampler.h"
 #include "rsFont.h"
+#include "rsPath.h"
 #include "rsProgramFragment.h"
 #include "rsProgramStore.h"
 #include "rsProgramRaster.h"
@@ -164,6 +165,9 @@
     uint32_t getWidth() const {return mWidth;}
     uint32_t getHeight() const {return mHeight;}
 
+    uint32_t getCurrentSurfaceWidth() const;
+    uint32_t getCurrentSurfaceHeight() const;
+
     mutable ThreadIO mIO;
 
     // Timers
diff --git a/rsElement.cpp b/rsElement.cpp
index df90ce4..56c31b6 100644
--- a/rsElement.cpp
+++ b/rsElement.cpp
@@ -23,6 +23,7 @@
 
 Element::Element(Context *rsc) : ObjectBase(rsc) {
     mBits = 0;
+    mBitsUnpadded = 0;
     mFields = NULL;
     mFieldCount = 0;
     mHasReference = false;
@@ -60,6 +61,18 @@
     return total;
 }
 
+size_t Element::getSizeBitsUnpadded() const {
+    if (!mFieldCount) {
+        return mBitsUnpadded;
+    }
+
+    size_t total = 0;
+    for (size_t ct=0; ct < mFieldCount; ct++) {
+        total += mFields[ct].e->mBitsUnpadded * mFields[ct].arraySize;
+    }
+    return total;
+}
+
 void Element::dumpLOGV(const char *prefix) const {
     ObjectBase::dumpLOGV(prefix);
     ALOGV("%s Element: fieldCount: %zu,  size bytes: %zu", prefix, mFieldCount, getSizeBytes());
@@ -146,14 +159,18 @@
 void Element::compute() {
     if (mFieldCount == 0) {
         mBits = mComponent.getBits();
+        mBitsUnpadded = mComponent.getBitsUnpadded();
         mHasReference = mComponent.isReference();
         return;
     }
 
     size_t bits = 0;
+    size_t bitsUnpadded = 0;
     for (size_t ct=0; ct < mFieldCount; ct++) {
         mFields[ct].offsetBits = bits;
+        mFields[ct].offsetBitsUnpadded = bitsUnpadded;
         bits += mFields[ct].e->getSizeBits() * mFields[ct].arraySize;
+        bitsUnpadded += mFields[ct].e->getSizeBitsUnpadded() * mFields[ct].arraySize;
 
         if (mFields[ct].e->mHasReference) {
             mHasReference = true;
diff --git a/rsElement.h b/rsElement.h
index bfdec53..04010fa 100644
--- a/rsElement.h
+++ b/rsElement.h
@@ -43,6 +43,11 @@
     uint32_t getGLType() const;
     uint32_t getGLFormat() const;
 
+    size_t getSizeBitsUnpadded() const;
+    size_t getSizeBytesUnpadded() const {
+        return (getSizeBitsUnpadded() + 7) >> 3;
+    }
+
     size_t getSizeBits() const;
     size_t getSizeBytes() const {
         return (getSizeBits() + 7) >> 3;
@@ -55,6 +60,10 @@
         return mFields[componentNumber].offsetBits >> 3;
     }
 
+    size_t getFieldOffsetBytesUnpadded(uint32_t componentNumber) const {
+        return mFields[componentNumber].offsetBitsUnpadded >> 3;
+    }
+
     uint32_t getFieldCount() const {return mFieldCount;}
     const Element * getField(uint32_t idx) const {return mFields[idx].e.get();}
     const char * getFieldName(uint32_t idx) const {return mFields[idx].name.string();}
@@ -64,6 +73,7 @@
     RsDataType getType() const {return mComponent.getType();}
     RsDataKind getKind() const {return mComponent.getKind();}
     uint32_t getBits() const {return mBits;}
+    uint32_t getBitsUnpadded() const {return mBitsUnpadded;}
 
     void dumpLOGV(const char *prefix) const;
     virtual void serialize(OStream *stream) const;
@@ -112,6 +122,7 @@
         String8 name;
         ObjectBaseRef<const Element> e;
         uint32_t offsetBits;
+        uint32_t offsetBitsUnpadded;
         uint32_t arraySize;
     } ElementField_t;
     ElementField_t *mFields;
@@ -123,6 +134,7 @@
     Element(Context *);
 
     Component mComponent;
+    uint32_t mBitsUnpadded;
     uint32_t mBits;
 
     void compute();
diff --git a/rsFont.cpp b/rsFont.cpp
index 7efed9d..7b3aa70 100644
--- a/rsFont.cpp
+++ b/rsFont.cpp
@@ -651,14 +651,10 @@
                                float x4, float y4, float z4,
                                float u4, float v4) {
     const uint32_t vertsPerQuad = 4;
-    const uint32_t floatsPerVert = 5;
+    const uint32_t floatsPerVert = 6;
     float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert;
 
-    // Cull things that are off the screen
-    float width = (float)mRSC->getWidth();
-    float height = (float)mRSC->getHeight();
-
-    if (x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) {
+    if (x1 > mSurfaceWidth || y1 < 0.0f || x2 < 0 || y4 > mSurfaceHeight) {
         return;
     }
 
@@ -670,24 +666,28 @@
     (*currentPos++) = x1;
     (*currentPos++) = y1;
     (*currentPos++) = z1;
+    (*currentPos++) = 0;
     (*currentPos++) = u1;
     (*currentPos++) = v1;
 
     (*currentPos++) = x2;
     (*currentPos++) = y2;
     (*currentPos++) = z2;
+    (*currentPos++) = 0;
     (*currentPos++) = u2;
     (*currentPos++) = v2;
 
     (*currentPos++) = x3;
     (*currentPos++) = y3;
     (*currentPos++) = z3;
+    (*currentPos++) = 0;
     (*currentPos++) = u3;
     (*currentPos++) = v3;
 
     (*currentPos++) = x4;
     (*currentPos++) = y4;
     (*currentPos++) = z4;
+    (*currentPos++) = 0;
     (*currentPos++) = u4;
     (*currentPos++) = v4;
 
@@ -746,6 +746,10 @@
         return;
     }
 
+    // Cull things that are off the screen
+    mSurfaceWidth = (float)mRSC->getCurrentSurfaceWidth();
+    mSurfaceHeight = (float)mRSC->getCurrentSurfaceHeight();
+
     currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs,
                            mode, bounds, bitmap, bitmapW, bitmapH);
 
diff --git a/rsFont.h b/rsFont.h
index 679591c..4ca794d 100644
--- a/rsFont.h
+++ b/rsFont.h
@@ -160,6 +160,9 @@
 
 protected:
 
+    float mSurfaceWidth;
+    float mSurfaceHeight;
+
     friend class Font;
 
     struct CacheTextureLine {
diff --git a/rsPath.cpp b/rsPath.cpp
new file mode 100644
index 0000000..89a0770
--- /dev/null
+++ b/rsPath.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+
+Path::Path(Context *rsc) : ObjectBase(rsc) {
+}
+
+Path::Path(Context *rsc, RsPathPrimitive pp, bool isStatic,
+                      Allocation *vtx, Allocation *loops, float quality)
+: ObjectBase(rsc) {
+
+    memset(&mHal, 0, sizeof(mHal));
+    mHal.state.quality = quality;
+    mHal.state.primitive = pp;
+
+    LOGE("i1");
+    rsc->mHal.funcs.path.initStatic(rsc, this, vtx, loops);
+
+    LOGE("i2");
+}
+
+Path::Path(Context *rsc, uint32_t vertexBuffersCount, uint32_t primitivesCount)
+: ObjectBase(rsc) {
+
+}
+
+Path::~Path() {
+
+}
+
+
+void Path::rasterize(const BezierSegment_t *s, uint32_t num, Allocation *alloc) {
+
+    for (uint32_t i=0; i < num; i++) {
+
+    }
+
+}
+
+void Path::render(Context *rsc) {
+}
+
+void Path::serialize(OStream *stream) const {
+
+}
+
+RsA3DClassID Path::getClassId() const {
+    return RS_A3D_CLASS_ID_UNKNOWN;
+}
+
+namespace android {
+namespace renderscript {
+
+RsPath rsi_PathCreate(Context *rsc, RsPathPrimitive pp, bool isStatic,
+                      RsAllocation vtx, RsAllocation loops, float quality) {
+    return new Path(rsc, pp, isStatic, (Allocation *)vtx, (Allocation *)loops, quality);
+}
+
+}
+}
diff --git a/rsPath.h b/rsPath.h
new file mode 100644
index 0000000..dac795e
--- /dev/null
+++ b/rsPath.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_PATH_H
+#define ANDROID_RS_PATH_H
+
+
+#include "RenderScript.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+class Path : public ObjectBase {
+public:
+    struct {
+        mutable void * drv;
+
+        struct State {
+            RsPathPrimitive primitive;
+            float quality;
+        };
+        State state;
+    } mHal;
+
+    Path(Context *);
+    Path(Context *, uint32_t vertexBuffersCount, uint32_t primitivesCount);
+    Path(Context *, RsPathPrimitive pp, bool isStatic, Allocation *vtx, Allocation *loop, float q);
+
+    ~Path();
+
+    void render(Context *);
+    virtual void serialize(OStream *stream) const;
+    virtual RsA3DClassID getClassId() const;
+
+private:
+
+
+    typedef struct {
+        float x[4];
+        float y[4];
+    } BezierSegment_t;
+
+    bool subdivideCheck(const BezierSegment_t *s, float u1, float u2);
+
+    void rasterize(const BezierSegment_t *s, uint32_t num, Allocation *alloc);
+
+
+};
+
+}
+}
+#endif //ANDROID_RS_PATH_H
+
+
+
diff --git a/rsProgramVertex.cpp b/rsProgramVertex.cpp
index 4a13622..871caac 100644
--- a/rsProgramVertex.cpp
+++ b/rsProgramVertex.cpp
@@ -206,8 +206,11 @@
 void ProgramVertexState::updateSize(Context *rsc) {
     float *f = static_cast<float *>(mDefaultAlloc->getPtr());
 
+    float surfaceWidth = (float)rsc->getCurrentSurfaceWidth();
+    float surfaceHeight = (float)rsc->getCurrentSurfaceHeight();
+
     Matrix4x4 m;
-    m.loadOrtho(0,rsc->getWidth(), rsc->getHeight(),0, -1,1);
+    m.loadOrtho(0, surfaceWidth, surfaceHeight, 0, -1, 1);
     memcpy(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], m.m, sizeof(m));
     memcpy(&f[RS_PROGRAM_VERTEX_MVP_OFFSET], m.m, sizeof(m));
 
diff --git a/rsRuntime.h b/rsRuntime.h
index cb962a8..b0869f6 100644
--- a/rsRuntime.h
+++ b/rsRuntime.h
@@ -68,6 +68,7 @@
 void rsrDrawSpriteScreenspace(Context *, Script *,
                               float x, float y, float z, float w, float h);
 void rsrDrawRect(Context *, Script *, float x1, float y1, float x2, float y2, float z);
+void rsrDrawPath(Context *, Script *, Path *);
 void rsrDrawMesh(Context *, Script *, Mesh *);
 void rsrDrawMeshPrimitive(Context *, Script *, Mesh *, uint32_t primIndex);
 void rsrDrawMeshPrimitiveRange(Context *, Script *, Mesh *,
diff --git a/rsScript.cpp b/rsScript.cpp
index 93513fe..7fc128e 100644
--- a/rsScript.cpp
+++ b/rsScript.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "rsContext.h"
+#include <time.h>
 
 using namespace android;
 using namespace android::renderscript;
@@ -25,6 +26,7 @@
 
     mSlots = NULL;
     mTypes = NULL;
+    mInitialized = false;
 }
 
 Script::~Script() {
@@ -89,8 +91,22 @@
 }
 
 void rsi_ScriptSetTimeZone(Context * rsc, RsScript vs, const char * timeZone, size_t length) {
-    Script *s = static_cast<Script *>(vs);
-    s->mEnviroment.mTimeZone = timeZone;
+    // We unfortunately need to make a new copy of the string, since it is
+    // not NULL-terminated. We then use setenv(), which properly handles
+    // freeing/duplicating the actual string for the environment.
+    char *tz = (char *) malloc(length + 1);
+    if (!tz) {
+        LOGE("Couldn't allocate memory for timezone buffer");
+        return;
+    }
+    strncpy(tz, timeZone, length);
+    tz[length] = '\0';
+    if (setenv("TZ", tz, 1) == 0) {
+        tzset();
+    } else {
+        LOGE("Error setting timezone");
+    }
+    free(tz);
 }
 
 void rsi_ScriptForEach(Context *rsc, RsScript vs, uint32_t slot,
diff --git a/rsScript.h b/rsScript.h
index d645421..99dceaf 100644
--- a/rsScript.h
+++ b/rsScript.h
@@ -59,7 +59,6 @@
     struct Enviroment_t {
         int64_t mStartTimeMillis;
         int64_t mLastDtTime;
-        const char* mTimeZone;
 
         ObjectBaseRef<ProgramVertex> mVertex;
         ObjectBaseRef<ProgramFragment> mFragment;
@@ -68,7 +67,6 @@
     };
     Enviroment_t mEnviroment;
 
-    void initSlots();
     void setSlot(uint32_t slot, Allocation *a);
     void setVar(uint32_t slot, const void *val, size_t len);
     void setVarObj(uint32_t slot, ObjectBase *val);
@@ -86,6 +84,7 @@
     virtual void setupScript(Context *rsc) = 0;
     virtual uint32_t run(Context *) = 0;
 protected:
+    bool mInitialized;
     ObjectBaseRef<Allocation> *mSlots;
     ObjectBaseRef<const Type> *mTypes;
 
diff --git a/rsScriptC.cpp b/rsScriptC.cpp
index b45366b..ce3c643 100644
--- a/rsScriptC.cpp
+++ b/rsScriptC.cpp
@@ -21,6 +21,7 @@
 
 #ifndef ANDROID_RS_SERIALIZE
 #include <bcinfo/BitcodeTranslator.h>
+#include <bcinfo/BitcodeWrapper.h>
 #endif
 
 using namespace android;
@@ -44,8 +45,10 @@
         BT = NULL;
     }
 #endif
-    mRSC->mHal.funcs.script.invokeFreeChildren(mRSC, this);
-    mRSC->mHal.funcs.script.destroy(mRSC, this);
+    if (mInitialized) {
+        mRSC->mHal.funcs.script.invokeFreeChildren(mRSC, this);
+        mRSC->mHal.funcs.script.destroy(mRSC, this);
+    }
 }
 
 void ScriptC::setupScript(Context *rsc) {
@@ -196,7 +199,24 @@
 
     //LOGE("runCompiler %p %p %p %p %p %i", rsc, this, resName, cacheDir, bitcode, bitcodeLen);
 #ifndef ANDROID_RS_SERIALIZE
-    uint32_t sdkVersion = rsc->getTargetSdkVersion();
+    uint32_t sdkVersion = 0;
+    bcinfo::BitcodeWrapper bcWrapper((const char *)bitcode, bitcodeLen);
+    if (!bcWrapper.unwrap()) {
+        LOGE("Bitcode is not in proper container format (raw or wrapper)");
+        return false;
+    }
+
+    rsAssert(bcWrapper.getHeaderVersion() == 0);
+    if (bcWrapper.getBCFileType() == bcinfo::BC_WRAPPER) {
+        sdkVersion = bcWrapper.getTargetAPI();
+    }
+
+    if (sdkVersion == 0) {
+        // This signals that we didn't have a wrapper containing information
+        // about the bitcode.
+        sdkVersion = rsc->getTargetSdkVersion();
+    }
+
     if (BT) {
         delete BT;
     }
@@ -212,8 +232,11 @@
     bitcodeLen = BT->getTranslatedBitcodeSize();
 #endif
 
-    rsc->mHal.funcs.script.init(rsc, this, resName, cacheDir, bitcode, bitcodeLen, 0);
+    if (!rsc->mHal.funcs.script.init(rsc, this, resName, cacheDir, bitcode, bitcodeLen, 0)) {
+        return false;
+    }
 
+    mInitialized = true;
     mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
     mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
     mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore());
diff --git a/rsScriptC_LibGL.cpp b/rsScriptC_LibGL.cpp
index 7862f3c..a79c3cb 100644
--- a/rsScriptC_LibGL.cpp
+++ b/rsScriptC_LibGL.cpp
@@ -79,23 +79,28 @@
 void rsrBindFrameBufferObjectColorTarget(Context *rsc, Script *sc, Allocation *a, uint32_t slot) {
     CHECK_OBJ(va);
     rsc->mFBOCache.bindColorTarget(rsc, a, slot);
+    rsc->mStateVertex.updateSize(rsc);
 }
 
 void rsrBindFrameBufferObjectDepthTarget(Context *rsc, Script *sc, Allocation *a) {
     CHECK_OBJ(va);
     rsc->mFBOCache.bindDepthTarget(rsc, a);
+    rsc->mStateVertex.updateSize(rsc);
 }
 
 void rsrClearFrameBufferObjectColorTarget(Context *rsc, Script *sc, uint32_t slot) {
     rsc->mFBOCache.bindColorTarget(rsc, NULL, slot);
+    rsc->mStateVertex.updateSize(rsc);
 }
 
 void rsrClearFrameBufferObjectDepthTarget(Context *rsc, Script *sc) {
     rsc->mFBOCache.bindDepthTarget(rsc, NULL);
+    rsc->mStateVertex.updateSize(rsc);
 }
 
 void rsrClearFrameBufferObjectTargets(Context *rsc, Script *sc) {
     rsc->mFBOCache.resetAll(rsc);
+    rsc->mStateVertex.updateSize(rsc);
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -195,6 +200,14 @@
     rsrDrawQuad(rsc, sc, x1, y2, z, x2, y2, z, x2, y1, z, x1, y1, z);
 }
 
+void rsrDrawPath(Context *rsc, Script *sc, Path *sm) {
+    CHECK_OBJ(sm);
+    if (!rsc->setupCheck()) {
+        return;
+    }
+    sm->render(rsc);
+}
+
 void rsrDrawMesh(Context *rsc, Script *sc, Mesh *sm) {
     CHECK_OBJ(sm);
     if (!rsc->setupCheck()) {
diff --git a/rs_hal.h b/rs_hal.h
index b8d7351..a5df600 100644
--- a/rs_hal.h
+++ b/rs_hal.h
@@ -29,6 +29,7 @@
 class Allocation;
 class Script;
 class ScriptC;
+class Path;
 class Program;
 class ProgramStore;
 class ProgramRaster;
@@ -189,6 +190,13 @@
     } mesh;
 
     struct {
+        bool (*initStatic)(const Context *rsc, const Path *m, const Allocation *vtx, const Allocation *loops);
+        bool (*initDynamic)(const Context *rsc, const Path *m);
+        void (*draw)(const Context *rsc, const Path *m);
+        void (*destroy)(const Context *rsc, const Path *m);
+    } path;
+
+    struct {
         bool (*init)(const Context *rsc, const Sampler *m);
         void (*destroy)(const Context *rsc, const Sampler *m);
     } sampler;
diff --git a/scriptc/rs_allocation.rsh b/scriptc/rs_allocation.rsh
index 154a099..1cb3a99 100644
--- a/scriptc/rs_allocation.rsh
+++ b/scriptc/rs_allocation.rsh
@@ -14,6 +14,31 @@
  * limitations under the License.
  */
 
+/*! \mainpage notitle
+ *
+ * Renderscript is a high-performance runtime that provides graphics rendering and
+ * compute operations at the native level. Renderscript code is compiled on devices
+ * at runtime to allow platform-independence as well.
+ * This reference documentation describes the Renderscript runtime APIs, which you
+ * can utilize to write Renderscript code in C99. The Renderscript header
+ * files are automatically included for you, except for the rs_graphics.rsh header. If
+ * you are doing graphics rendering, include the graphics header file like this:
+ *
+ * <code>#include "rs_graphics.rsh"</code>
+ *
+ * To use Renderscript, you need to utilize the Renderscript runtime APIs documented here
+ * as well as the Android framework APIs for Renderscript.
+ * For documentation on the Android framework APIs, see the <a href=
+ * "http://developer.android.com/reference/android/renderscript/package-summary.html">
+ * android.renderscript</a> package reference.
+ * For more information on how to develop with Renderscript and how the runtime and
+ * Android framework APIs interact, see the <a href=
+ * "http://developer.android.com/guide/topics/renderscript/index.html">Renderscript
+ * developer guide</a> and the <a href=
+ * "http://developer.android.com/resources/samples/RenderScript/index.html">
+ * Renderscript samples</a>.
+ */
+
 /** @file rs_allocation.rsh
  *  \brief Allocation routines
  *
diff --git a/scriptc/rs_graphics.rsh b/scriptc/rs_graphics.rsh
index 80267c7..a01bc3d 100644
--- a/scriptc/rs_graphics.rsh
+++ b/scriptc/rs_graphics.rsh
@@ -483,6 +483,9 @@
 extern void __attribute__((overloadable))
     rsgDrawSpriteScreenspace(float x, float y, float z, float w, float h);
 
+extern void __attribute__((overloadable))
+    rsgDrawPath(rs_path p);
+
 /**
  * Draw a mesh using the current context state.  The whole mesh is
  * rendered.
diff --git a/scriptc/rs_object.rsh b/scriptc/rs_object.rsh
index a431219..1fc3f83 100644
--- a/scriptc/rs_object.rsh
+++ b/scriptc/rs_object.rsh
@@ -56,6 +56,11 @@
  * \overload
  */
 extern void __attribute__((overloadable))
+    rsSetObject(rs_path *dst, rs_path src);
+/**
+ * \overload
+ */
+extern void __attribute__((overloadable))
     rsSetObject(rs_mesh *dst, rs_mesh src);
 /**
  * \overload
@@ -114,6 +119,11 @@
  * \overload
  */
 extern void __attribute__((overloadable))
+    rsClearObject(rs_path *dst);
+/**
+ * \overload
+ */
+extern void __attribute__((overloadable))
     rsClearObject(rs_mesh *dst);
 /**
  * \overload
@@ -175,6 +185,11 @@
  * \overload
  */
 extern bool __attribute__((overloadable))
+    rsIsObject(rs_path);
+/**
+ * \overload
+ */
+extern bool __attribute__((overloadable))
     rsIsObject(rs_mesh);
 /**
  * \overload
diff --git a/scriptc/rs_types.rsh b/scriptc/rs_types.rsh
index e9c3c5e..a01807e 100644
--- a/scriptc/rs_types.rsh
+++ b/scriptc/rs_types.rsh
@@ -138,6 +138,12 @@
  */
 typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_mesh;
 /**
+ * \brief Opaque handle to a Renderscript Path object.
+ *
+ * See: android.renderscript.Path
+ */
+typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_path;
+/**
  * \brief Opaque handle to a Renderscript ProgramFragment object.
  *
  * See: android.renderscript.ProgramFragment
@@ -364,7 +370,7 @@
 typedef float4 rs_quaternion;
 
 #define RS_PACKED __attribute__((packed, aligned(4)))
-#define NULL ((const void *)0)
+#define NULL ((void *)0)
 
 #if (defined(RS_VERSION) && (RS_VERSION >= 14))