Refactor hal loading

This CL make the loading of RS drivers more robust by
looking up entry points in place of a structure of entry points.

It also adds framework for a version handshake.

Change-Id: Iae46bf0171785c0ca1048223816b6efc60c337ad
diff --git a/Android.mk b/Android.mk
index 723d1da..3212eb9 100644
--- a/Android.mk
+++ b/Android.mk
@@ -35,7 +35,6 @@
 	driver/rsdGL.cpp \
 	driver/rsdMesh.cpp \
 	driver/rsdMeshObj.cpp \
-	driver/rsdPath.cpp \
 	driver/rsdProgram.cpp \
 	driver/rsdProgramRaster.cpp \
 	driver/rsdProgramStore.cpp \
@@ -143,6 +142,7 @@
 	rsClosure.cpp \
 	rsCppUtils.cpp \
 	rsDevice.cpp \
+	rsDriverLoader.cpp \
 	rsElement.cpp \
 	rsFBOCache.cpp \
 	rsFifoSocket.cpp \
@@ -155,7 +155,6 @@
 	rsMatrix4x4.cpp \
 	rsMesh.cpp \
 	rsMutex.cpp \
-	rsPath.cpp \
 	rsProgram.cpp \
 	rsProgramFragment.cpp \
 	rsProgramStore.cpp \
@@ -248,6 +247,7 @@
 	rsContext.cpp \
 	rsClosure.cpp \
 	rsDevice.cpp \
+	rsDriverLoader.cpp \
 	rsElement.cpp \
 	rsFBOCache.cpp \
 	rsFifoSocket.cpp \
@@ -259,7 +259,6 @@
 	rsMatrix4x4.cpp \
 	rsMesh.cpp \
 	rsMutex.cpp \
-	rsPath.cpp \
 	rsProgram.cpp \
 	rsProgramFragment.cpp \
 	rsProgramStore.cpp \
diff --git a/driver/rsdCore.cpp b/driver/rsdCore.cpp
index 5390faf..d9b11d2 100644
--- a/driver/rsdCore.cpp
+++ b/driver/rsdCore.cpp
@@ -23,7 +23,6 @@
 #include "rsdType.h"
 #ifndef RS_COMPATIBILITY_LIB
     #include "rsdGL.h"
-    #include "rsdPath.h"
     #include "rsdProgramStore.h"
     #include "rsdProgramRaster.h"
     #include "rsdProgramVertex.h"
@@ -57,137 +56,209 @@
     #define NATIVE_FUNC(a) nullptr
 #endif
 
-static RsdHalFunctions FunctionTable = {
-    NATIVE_FUNC(rsdGLInit),
-    NATIVE_FUNC(rsdGLShutdown),
-    NATIVE_FUNC(rsdGLSetSurface),
-    NATIVE_FUNC(rsdGLSwap),
+extern "C" bool rsdHalQueryHal(RsHalInitEnums entry, void **fnPtr) {
+    switch(entry) {
+    case RS_HAL_CORE_SHUTDOWN:
+        fnPtr[0] = (void *)Shutdown; break;
+    case RS_HAL_CORE_SET_PRIORITY:
+        fnPtr[0] = (void *)SetPriority; break;
+    case RS_HAL_CORE_ALLOC_RUNTIME_MEM:
+        fnPtr[0] = (void *)rsdAllocRuntimeMem; break;
+    case RS_HAL_CORE_FREE_RUNTIME_MEM:
+        fnPtr[0] = (void *)rsdFreeRuntimeMem; break;
+    case RS_HAL_CORE_FINISH:
+        fnPtr[0] = (void *)nullptr; break;
 
-    Shutdown,
-    nullptr,
-    SetPriority,
-    rsdAllocRuntimeMem,
-    rsdFreeRuntimeMem,
-    {
-        rsdScriptInit,
-        rsdInitIntrinsic,
-        rsdScriptInvokeFunction,
-        rsdScriptInvokeRoot,
-        rsdScriptInvokeForEach,
-        rsdScriptInvokeInit,
-        rsdScriptInvokeFreeChildren,
-        rsdScriptSetGlobalVar,
-        rsdScriptGetGlobalVar,
-        rsdScriptSetGlobalVarWithElemDims,
-        rsdScriptSetGlobalBind,
-        rsdScriptSetGlobalObj,
-        rsdScriptDestroy,
-        rsdScriptInvokeForEachMulti,
-        rsdScriptUpdateCachedObject
-    },
+    case RS_HAL_SCRIPT_INIT:
+        fnPtr[0] = (void *)rsdScriptInit; break;
+    case RS_HAL_SCRIPT_INIT_INTRINSIC:
+        fnPtr[0] = (void *)rsdInitIntrinsic; break;
+    case RS_HAL_SCRIPT_INVOKE_FUNCTION:
+        fnPtr[0] = (void *)rsdScriptInvokeFunction; break;
+    case RS_HAL_SCRIPT_INVOKE_ROOT:
+        fnPtr[0] = (void *)rsdScriptInvokeRoot; break;
+    case RS_HAL_SCRIPT_INVOKE_FOR_EACH:
+        fnPtr[0] = (void *)rsdScriptInvokeForEach; break;
+    case RS_HAL_SCRIPT_INVOKE_INIT:
+        fnPtr[0] = (void *)rsdScriptInvokeInit; break;
+    case RS_HAL_SCRIPT_INVOKE_FREE_CHILDREN:
+        fnPtr[0] = (void *)rsdScriptInvokeFreeChildren; break;
+    case RS_HAL_SCRIPT_SET_GLOBAL_VAR:
+        fnPtr[0] = (void *)rsdScriptSetGlobalVar; break;
+    case RS_HAL_SCRIPT_GET_GLOBAL_VAR:
+        fnPtr[0] = (void *)rsdScriptGetGlobalVar; break;
+    case RS_HAL_SCRIPT_SET_GLOBAL_VAR_WITH_ELEMENT_DIM:
+        fnPtr[0] = (void *)rsdScriptSetGlobalVarWithElemDims; break;
+    case RS_HAL_SCRIPT_SET_GLOBAL_BIND:
+        fnPtr[0] = (void *)rsdScriptSetGlobalBind; break;
+    case RS_HAL_SCRIPT_SET_GLOBAL_OBJECT:
+        fnPtr[0] = (void *)rsdScriptSetGlobalObj; break;
+    case RS_HAL_SCRIPT_DESTROY:
+        fnPtr[0] = (void *)rsdScriptDestroy; break;
+    case RS_HAL_SCRIPT_INVOKE_FOR_EACH_MULTI:
+        fnPtr[0] = (void *)rsdScriptInvokeForEachMulti; break;
+    case RS_HAL_SCRIPT_UPDATE_CACHED_OBJECT:
+        fnPtr[0] = (void *)rsdScriptUpdateCachedObject; break;
 
-    {
-        rsdAllocationInit,
-        rsdAllocationAdapterInit,
-        rsdAllocationDestroy,
-        rsdAllocationGrallocBits,
-        rsdAllocationResize,
-        rsdAllocationSyncAll,
-        rsdAllocationMarkDirty,
-        NATIVE_FUNC(rsdAllocationSetSurface),
-        NATIVE_FUNC(rsdAllocationIoSend),
-        NATIVE_FUNC(rsdAllocationIoReceive),
-        rsdAllocationData1D,
-        rsdAllocationData2D,
-        rsdAllocationData3D,
-        rsdAllocationRead1D,
-        rsdAllocationRead2D,
-        rsdAllocationRead3D,
-        rsdAllocationLock1D,
-        rsdAllocationUnlock1D,
-        rsdAllocationData1D_alloc,
-        rsdAllocationData2D_alloc,
-        rsdAllocationData3D_alloc,
-        rsdAllocationElementData,
-        rsdAllocationElementRead,
-        rsdAllocationGenerateMipmaps,
-        rsdAllocationUpdateCachedObject,
-        rsdAllocationAdapterOffset
-    },
+    case RS_HAL_ALLOCATION_INIT:
+        fnPtr[0] = (void *)rsdAllocationInit; break;
+    case RS_HAL_ALLOCATION_INIT_ADAPTER:
+        fnPtr[0] = (void *)rsdAllocationAdapterInit; break;
+    case RS_HAL_ALLOCATION_DESTROY:
+        fnPtr[0] = (void *)rsdAllocationDestroy; break;
+    case RS_HAL_ALLOCATION_GET_GRALLOC_BITS:
+        fnPtr[0] = (void *)rsdAllocationGrallocBits; break;
+    case RS_HAL_ALLOCATION_RESIZE:
+        fnPtr[0] = (void *)rsdAllocationResize; break;
+    case RS_HAL_ALLOCATION_SYNC_ALL:
+        fnPtr[0] = (void *)rsdAllocationSyncAll; break;
+    case RS_HAL_ALLOCATION_MARK_DIRTY:
+        fnPtr[0] = (void *)rsdAllocationMarkDirty; break;
+    case RS_HAL_ALLOCATION_SET_SURFACE:
+        fnPtr[0] = (void *)NATIVE_FUNC(rsdAllocationSetSurface); break;
+    case RS_HAL_ALLOCATION_IO_SEND:
+        fnPtr[0] = (void *)NATIVE_FUNC(rsdAllocationIoSend); break;
+    case RS_HAL_ALLOCATION_IO_RECEIVE:
+        fnPtr[0] = (void *)NATIVE_FUNC(rsdAllocationIoReceive); break;
+    case RS_HAL_ALLOCATION_DATA_1D:
+        fnPtr[0] = (void *)rsdAllocationData1D; break;
+    case RS_HAL_ALLOCATION_DATA_2D:
+        fnPtr[0] = (void *)rsdAllocationData2D; break;
+    case RS_HAL_ALLOCATION_DATA_3D:
+        fnPtr[0] = (void *)rsdAllocationData3D; break;
+    case RS_HAL_ALLOCATION_READ_1D:
+        fnPtr[0] = (void *)rsdAllocationRead1D; break;
+    case RS_HAL_ALLOCATION_READ_2D:
+        fnPtr[0] = (void *)rsdAllocationRead2D; break;
+    case RS_HAL_ALLOCATION_READ_3D:
+        fnPtr[0] = (void *)rsdAllocationRead3D; break;
+    case RS_HAL_ALLOCATION_LOCK_1D:
+        fnPtr[0] = (void *)rsdAllocationLock1D; break;
+    case RS_HAL_ALLOCATION_UNLOCK_1D:
+        fnPtr[0] = (void *)rsdAllocationUnlock1D; break;
+    case RS_HAL_ALLOCATION_COPY_1D:
+        fnPtr[0] = (void *)rsdAllocationData1D_alloc; break;
+    case RS_HAL_ALLOCATION_COPY_2D:
+        fnPtr[0] = (void *)rsdAllocationData2D_alloc; break;
+    case RS_HAL_ALLOCATION_COPY_3D:
+        fnPtr[0] = (void *)rsdAllocationData3D_alloc; break;
+    case RS_HAL_ALLOCATION_ELEMENT_DATA:
+        fnPtr[0] = (void *)rsdAllocationElementData; break;
+    case RS_HAL_ALLOCATION_ELEMENT_READ:
+        fnPtr[0] = (void *)rsdAllocationElementRead; break;
+    case RS_HAL_ALLOCATION_GENERATE_MIPMAPS:
+        fnPtr[0] = (void *)rsdAllocationGenerateMipmaps; break;
+    case RS_HAL_ALLOCATION_UPDATE_CACHED_OBJECT:
+        fnPtr[0] = (void *)rsdAllocationUpdateCachedObject; break;
+    case RS_HAL_ALLOCATION_ADAPTER_OFFSET:
+        fnPtr[0] = (void *)rsdAllocationAdapterOffset; break;
+
+    case RS_HAL_SAMPLER_INIT:
+        fnPtr[0] = (void *)rsdSamplerInit; break;
+    case RS_HAL_SAMPLER_DESTROY:
+        fnPtr[0] = (void *)rsdSamplerDestroy; break;
+    case RS_HAL_SAMPLER_UPDATE_CACHED_OBJECT:
+        fnPtr[0] = (void *)rsdSamplerUpdateCachedObject; break;
+
+    case RS_HAL_TYPE_INIT:
+        fnPtr[0] = (void *)rsdTypeInit; break;
+    case RS_HAL_TYPE_DESTROY:
+        fnPtr[0] = (void *)rsdTypeDestroy; break;
+    case RS_HAL_TYPE_UPDATE_CACHED_OBJECT:
+        fnPtr[0] = (void *)rsdTypeUpdateCachedObject; break;
+
+    case RS_HAL_ELEMENT_INIT:
+        fnPtr[0] = (void *)rsdElementInit; break;
+    case RS_HAL_ELEMENT_DESTROY:
+        fnPtr[0] = (void *)rsdElementDestroy; break;
+    case RS_HAL_ELEMENT_UPDATE_CACHED_OBJECT:
+        fnPtr[0] = (void *)rsdElementUpdateCachedObject; break;
+
+    case RS_HAL_SCRIPT_GROUP_INIT:
+        fnPtr[0] = (void *)rsdScriptGroupInit; break;
+    case RS_HAL_SCRIPT_GROUP_DESTROY:
+        fnPtr[0] = (void *)rsdScriptGroupDestroy; break;
+    case RS_HAL_SCRIPT_GROUP_UPDATE_CACHED_OBJECT:
+        fnPtr[0] = (void *)nullptr; break;
+    case RS_HAL_SCRIPT_GROUP_SET_INPUT:
+        fnPtr[0] = (void *)rsdScriptGroupSetInput; break;
+    case RS_HAL_SCRIPT_GROUP_SET_OUTPUT:
+        fnPtr[0] = (void *)rsdScriptGroupSetOutput; break;
+    case RS_HAL_SCRIPT_GROUP_EXECUTE:
+        fnPtr[0] = (void *)rsdScriptGroupExecute; break;
 
 
-    {
-        NATIVE_FUNC(rsdProgramStoreInit),
-        NATIVE_FUNC(rsdProgramStoreSetActive),
-        NATIVE_FUNC(rsdProgramStoreDestroy)
-    },
 
-    {
-        NATIVE_FUNC(rsdProgramRasterInit),
-        NATIVE_FUNC(rsdProgramRasterSetActive),
-        NATIVE_FUNC(rsdProgramRasterDestroy)
-    },
+    // Functions below this point are for the legacy graphics api,
+    // vendor drivers are NOT expected to implement these.  They will never be called
+    // for an external driver.
+#ifndef RS_COMPATIBILITY_LIB
+    case RS_HAL_GRAPHICS_INIT:
+        fnPtr[0] = (void *)rsdGLInit; break;
+    case RS_HAL_GRAPHICS_SHUTDOWN:
+        fnPtr[0] = (void *)rsdGLShutdown; break;
+    case RS_HAL_GRAPHICS_SWAP:
+        fnPtr[0] = (void *)rsdGLSwap; break;
+    case RS_HAL_GRAPHICS_SET_SURFACE:
+        fnPtr[0] = (void *)rsdGLSetSurface; break;
+    case RS_HAL_GRAPHICS_RASTER_INIT:
+        fnPtr[0] = (void *)rsdProgramRasterInit; break;
+    case RS_HAL_GRAPHICS_RASTER_SET_ACTIVE:
+        fnPtr[0] = (void *)rsdProgramRasterSetActive; break;
+    case RS_HAL_GRAPHICS_RASTER_DESTROY:
+        fnPtr[0] = (void *)rsdProgramRasterDestroy; break;
+    case RS_HAL_GRAPHICS_VERTEX_INIT:
+        fnPtr[0] = (void *)rsdProgramVertexInit; break;
+    case RS_HAL_GRAPHICS_VERTEX_SET_ACTIVE:
+        fnPtr[0] = (void *)rsdProgramVertexSetActive; break;
+    case RS_HAL_GRAPHICS_VERTEX_DESTROY:
+        fnPtr[0] = (void *)rsdProgramVertexDestroy; break;
+    case RS_HAL_GRAPHICS_FRAGMENT_INIT:
+        fnPtr[0] = (void *)rsdProgramFragmentInit; break;
+    case RS_HAL_GRAPHICS_FRAGMENT_SET_ACTIVE:
+        fnPtr[0] = (void *)rsdProgramFragmentSetActive; break;
+    case RS_HAL_GRAPHICS_FRAGMENT_DESTROY:
+        fnPtr[0] = (void *)rsdProgramFragmentDestroy; break;
+    case RS_HAL_GRAPHICS_MESH_INIT:
+        fnPtr[0] = (void *)rsdMeshInit; break;
+    case RS_HAL_GRAPHICS_MESH_DRAW:
+        fnPtr[0] = (void *)rsdMeshDraw; break;
+    case RS_HAL_GRAPHICS_MESH_DESTROY:
+        fnPtr[0] = (void *)rsdMeshDestroy; break;
+    case RS_HAL_GRAPHICS_FB_INIT:
+        fnPtr[0] = (void *)rsdFrameBufferInit; break;
+    case RS_HAL_GRAPHICS_FB_SET_ACTIVE:
+        fnPtr[0] = (void *)rsdFrameBufferSetActive; break;
+    case RS_HAL_GRAPHICS_FB_DESTROY:
+        fnPtr[0] = (void *)rsdFrameBufferDestroy; break;
+    case RS_HAL_GRAPHICS_STORE_INIT:
+        fnPtr[0] = (void *)rsdProgramStoreInit; break;
+    case RS_HAL_GRAPHICS_STORE_SET_ACTIVE:
+        fnPtr[0] = (void *)rsdProgramStoreSetActive; break;
+    case RS_HAL_GRAPHICS_STORE_DESTROY:
+        fnPtr[0] = (void *)rsdProgramStoreDestroy; break;
+#endif
 
-    {
-        NATIVE_FUNC(rsdProgramVertexInit),
-        NATIVE_FUNC(rsdProgramVertexSetActive),
-        NATIVE_FUNC(rsdProgramVertexDestroy)
-    },
+    default:
+        ALOGE("ERROR: unknown RenderScript HAL API query, %i", entry);
+        return false;
+    }
 
-    {
-        NATIVE_FUNC(rsdProgramFragmentInit),
-        NATIVE_FUNC(rsdProgramFragmentSetActive),
-        NATIVE_FUNC(rsdProgramFragmentDestroy)
-    },
+    return true;
+}
 
-    {
-        NATIVE_FUNC(rsdMeshInit),
-        NATIVE_FUNC(rsdMeshDraw),
-        NATIVE_FUNC(rsdMeshDestroy)
-    },
+extern "C" void rsdHalAbort(RsContext) {
 
-    {
-        NATIVE_FUNC(rsdPathInitStatic),
-        NATIVE_FUNC(rsdPathInitDynamic),
-        NATIVE_FUNC(rsdPathDraw),
-        NATIVE_FUNC(rsdPathDestroy)
-    },
+}
 
-    {
-        rsdSamplerInit,
-        rsdSamplerDestroy,
-        rsdSamplerUpdateCachedObject
-    },
 
-    {
-        NATIVE_FUNC(rsdFrameBufferInit),
-        NATIVE_FUNC(rsdFrameBufferSetActive),
-        NATIVE_FUNC(rsdFrameBufferDestroy)
-    },
+extern "C" bool rsdHalQueryVersion(uint32_t *major, uint32_t *minor) {
+    *major = 23;
+    *minor = 0;
+    return true;
+}
 
-    {
-        rsdScriptGroupInit,
-        rsdScriptGroupSetInput,
-        rsdScriptGroupSetOutput,
-        rsdScriptGroupExecute,
-        rsdScriptGroupDestroy,
-        nullptr
-    },
 
-    {
-        rsdTypeInit,
-        rsdTypeDestroy,
-        rsdTypeUpdateCachedObject
-    },
-
-    {
-        rsdElementInit,
-        rsdElementDestroy,
-        rsdElementUpdateCachedObject
-    },
-
-    nullptr // finish
-};
 
 extern const RsdCpuReference::CpuSymbol * rsdLookupRuntimeStub(Context * pContext, char const* name);
 
@@ -234,12 +305,12 @@
     Context *rsc = (Context*) c;
 #ifdef RS_COMPATIBILITY_LIB
     if (loadIOSuppLibSyms()) {
-        FunctionTable.allocation.destroy = sAllocationDestroy;
-        FunctionTable.allocation.ioSend = sAllocationIoSend;
-        FunctionTable.allocation.setSurface = sAllocationSetSurface;
+        rsc->mHal.funcs.allocation.destroy = sAllocationDestroy;
+        rsc->mHal.funcs.allocation.ioSend = sAllocationIoSend;
+        rsc->mHal.funcs.allocation.setSurface = sAllocationSetSurface;
     }
 #endif
-    rsc->mHal.funcs = FunctionTable;
+
     RsdHal *dc = (RsdHal *)calloc(1, sizeof(RsdHal));
     if (!dc) {
         ALOGE("Calloc for driver hal failed.");
diff --git a/driver/rsdPath.cpp b/driver/rsdPath.cpp
deleted file mode 100644
index 1a9fa21..0000000
--- a/driver/rsdPath.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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 = nullptr;
-    cleanup(rsc, m);
-
-    DrvPathStatic *dps = new DrvPathStatic(vtx, loops);
-    //LOGE("init path m %p,  %p", m, dps);
-    m->mHal.drv = dps;
-    return dps != nullptr;
-}
-
-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 = nullptr;
-}
-
-
-
-
-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, (size_t)vtx, "ATTRIB_position");
-    attribs[1].set(GL_FLOAT, 4, 16, false, (size_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
deleted file mode 100644
index fa00972..0000000
--- a/driver/rsdPath.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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 1bfbf9f..d14e687 100644
--- a/driver/rsdRuntimeStubs.cpp
+++ b/driver/rsdRuntimeStubs.cpp
@@ -24,7 +24,6 @@
 #include "rsdCore.h"
 #include "rsdBcc.h"
 
-#include "rsdPath.h"
 #include "rsdAllocation.h"
 #include "rsdShaderCache.h"
 #include "rsdVertexArray.h"
@@ -465,11 +464,6 @@
     SC_DrawQuad(x1, y2, z, x2, y2, z, x2, y1, z, x1, y1, z);
 }
 
-static void SC_DrawPath(Path *p) {
-    Context *rsc = RsdCpuReference::getTlsContext();
-    rsdPathDraw(rsc, p);
-}
-
 static void SC_DrawMesh(Mesh *m) {
     Context *rsc = RsdCpuReference::getTlsContext();
     rsrDrawMesh(rsc, m);
@@ -1492,8 +1486,6 @@
     { "_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 },
 
@@ -1694,10 +1686,6 @@
                                 maxX, maxY, maxZ);
 }
 
-void rsgDrawPath(::rs_path p) {
-    return SC_DrawPath((Path *) p.p);
-}
-
 void rsgClearColor(float r, float g, float b, float a) {
     return SC_ClearColor(r, g, b, a);
 }
diff --git a/rsContext.cpp b/rsContext.cpp
index 5818b66..75f927e 100644
--- a/rsContext.cpp
+++ b/rsContext.cpp
@@ -244,49 +244,6 @@
 #endif
 }
 
-bool Context::loadRuntime(const char* filename, Context* rsc) {
-
-    // TODO: store the driverSO somewhere so we can dlclose later
-    void *driverSO = nullptr;
-
-    driverSO = dlopen(filename, RTLD_LAZY);
-    if (driverSO == nullptr) {
-        ALOGE("Failed loading RS driver: %s", dlerror());
-        return false;
-    }
-
-    // Need to call dlerror() to clear buffer before using it for dlsym().
-    (void) dlerror();
-    typedef bool (*HalSig)(Context*, uint32_t, uint32_t);
-    HalSig halInit = (HalSig) dlsym(driverSO, "rsdHalInit");
-
-    // If we can't find the C variant, we go looking for the C++ version.
-    if (halInit == nullptr) {
-        ALOGW("Falling back to find C++ rsdHalInit: %s", dlerror());
-        halInit = (HalSig) dlsym(driverSO,
-                "_Z10rsdHalInitPN7android12renderscript7ContextEjj");
-    }
-
-    if (halInit == nullptr) {
-        dlclose(driverSO);
-        ALOGE("Failed to find rsdHalInit: %s", dlerror());
-        return false;
-    }
-
-    if (!(*halInit)(rsc, 0, 0)) {
-        dlclose(driverSO);
-        ALOGE("Hal init failed");
-        return false;
-    }
-
-    //validate HAL struct
-
-
-    return true;
-}
-
-extern "C" bool rsdHalInit(RsContext c, uint32_t version_major, uint32_t version_minor);
-
 void * Context::threadProc(void *vrsc) {
     Context *rsc = static_cast<Context *>(vrsc);
 
@@ -306,52 +263,17 @@
     if (getProp("debug.rs.debug") != 0) {
         ALOGD("Forcing debug context due to debug.rs.debug.");
         rsc->mContextType = RS_CONTEXT_TYPE_DEBUG;
+        rsc->mForceCpu = true;
     }
 
-    bool loadDefault = true;
-
-    // Provide a mechanism for dropping in a different RS driver.
-#ifndef RS_COMPATIBILITY_LIB
-#ifdef OVERRIDE_RS_DRIVER
-#define XSTR(S) #S
-#define STR(S) XSTR(S)
-#define OVERRIDE_RS_DRIVER_STRING STR(OVERRIDE_RS_DRIVER)
-
-    if (getProp("debug.rs.default-CPU-driver") != 0) {
-        ALOGD("Skipping override driver and loading default CPU driver");
-    } else if (rsc->mForceCpu || rsc->mIsGraphicsContext) {
-        ALOGV("Application requested CPU execution");
-    } else if (rsc->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
-        ALOGV("Application requested debug context");
-    } else {
-#if defined(__LP64__) && defined(DISABLE_RS_64_BIT_DRIVER)
-        // skip load
-#else
-        if (loadRuntime(OVERRIDE_RS_DRIVER_STRING, rsc)) {
-            ALOGV("Successfully loaded runtime: %s", OVERRIDE_RS_DRIVER_STRING);
-            loadDefault = false;
-        } else {
-            ALOGE("Failed to load runtime %s, loading default", OVERRIDE_RS_DRIVER_STRING);
-        }
-#endif
+    bool forceCpu = getProp("debug.rs.default-CPU-driver") != 0;
+    if (forceCpu) {
+        ALOGD("Skipping hardware driver and loading default CPU driver");
+        rsc->mForceCpu = true;
     }
 
-#undef XSTR
-#undef STR
-#endif  // OVERRIDE_RS_DRIVER
-
-    if (loadDefault) {
-        if (!loadRuntime("libRSDriver.so", rsc)) {
-            ALOGE("Failed to load default runtime!");
-            rsc->setError(RS_ERROR_FATAL_DRIVER, "Failed loading RS driver");
-            return nullptr;
-        }
-    }
-#else // RS_COMPATIBILITY_LIB
-    if (rsdHalInit(rsc, 0, 0) != true) {
-        return nullptr;
-    }
-#endif
+    rsc->mForceCpu |= rsc->mIsGraphicsContext;
+    rsc->loadDriver(rsc->mForceCpu);
 
     if (!rsc->isSynchronous()) {
         // Due to legacy we default to normal_graphics
diff --git a/rsContext.h b/rsContext.h
index 3084a9a..459550c 100644
--- a/rsContext.h
+++ b/rsContext.h
@@ -37,7 +37,6 @@
 
 #ifndef RS_COMPATIBILITY_LIB
 #include "rsFont.h"
-#include "rsPath.h"
 #include "rsProgramFragment.h"
 #include "rsProgramStore.h"
 #include "rsProgramRaster.h"
@@ -300,7 +299,8 @@
 
     uint32_t runRootScript();
 
-    static bool loadRuntime(const char* filename, Context* rsc);
+    bool loadRuntime(const char* filename);
+    bool loadDriver(bool forceDefault);
     static void * threadProc(void *);
     static void * helperThreadProc(void *);
 
diff --git a/rsDriverLoader.cpp b/rsDriverLoader.cpp
new file mode 100644
index 0000000..8145582
--- /dev/null
+++ b/rsDriverLoader.cpp
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2015 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 "rs.h"
+#include "rsDevice.h"
+#include "rsContext.h"
+#include "rsThreadIO.h"
+
+#include "rsgApiStructs.h"
+
+#ifndef RS_COMPATIBILITY_LIB
+#include "rsMesh.h"
+#include <gui/DisplayEventReceiver.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sched.h>
+
+#include <sys/syscall.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <inttypes.h>
+#include <unistd.h>
+
+#if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB) && \
+        defined(HAVE_ANDROID_OS)
+#include <cutils/properties.h>
+#endif
+
+#ifdef RS_COMPATIBILITY_LIB
+#include "rsCompatibilityLib.h"
+#endif
+
+using namespace android;
+using namespace android::renderscript;
+
+
+
+typedef bool (*HalQueryVersion)(uint32_t *version_major, uint32_t *version_minor);
+typedef bool (*HalQueryHal)(android::renderscript::RsHalInitEnums entry, void **fnPtr);
+typedef bool (*HalInit)(RsContext, uint32_t version_major, uint32_t version_minor);
+typedef void (*HalAbort)(RsContext);
+
+
+static bool LoadHalTable(Context *rsc, HalQueryHal fn, bool loadGraphics) {
+    bool ret = true;
+
+    ret &= fn(RS_HAL_CORE_SHUTDOWN, (void **)&rsc->mHal.funcs.shutdownDriver);
+    ret &= fn(RS_HAL_CORE_SET_PRIORITY, (void **)&rsc->mHal.funcs.setPriority);
+    ret &= fn(RS_HAL_CORE_ALLOC_RUNTIME_MEM, (void **)&rsc->mHal.funcs.allocRuntimeMem);
+    ret &= fn(RS_HAL_CORE_FREE_RUNTIME_MEM, (void **)&rsc->mHal.funcs.freeRuntimeMem);
+    ret &= fn(RS_HAL_CORE_FINISH, (void **)&rsc->mHal.funcs.finish);
+
+    ret &= fn(RS_HAL_SCRIPT_INIT, (void **)&rsc->mHal.funcs.script.init);
+    ret &= fn(RS_HAL_SCRIPT_INIT_INTRINSIC, (void **)&rsc->mHal.funcs.script.initIntrinsic);
+    ret &= fn(RS_HAL_SCRIPT_INVOKE_FUNCTION, (void **)&rsc->mHal.funcs.script.invokeFunction);
+    ret &= fn(RS_HAL_SCRIPT_INVOKE_ROOT, (void **)&rsc->mHal.funcs.script.invokeRoot);
+    ret &= fn(RS_HAL_SCRIPT_INVOKE_FOR_EACH, (void **)&rsc->mHal.funcs.script.invokeForEach);
+    ret &= fn(RS_HAL_SCRIPT_INVOKE_INIT, (void **)&rsc->mHal.funcs.script.invokeInit);
+    ret &= fn(RS_HAL_SCRIPT_INVOKE_FREE_CHILDREN, (void **)&rsc->mHal.funcs.script.invokeFreeChildren);
+    ret &= fn(RS_HAL_SCRIPT_SET_GLOBAL_VAR, (void **)&rsc->mHal.funcs.script.setGlobalVar);
+    ret &= fn(RS_HAL_SCRIPT_GET_GLOBAL_VAR, (void **)&rsc->mHal.funcs.script.getGlobalVar);
+    ret &= fn(RS_HAL_SCRIPT_SET_GLOBAL_VAR_WITH_ELEMENT_DIM, (void **)&rsc->mHal.funcs.script.setGlobalVarWithElemDims);
+    ret &= fn(RS_HAL_SCRIPT_SET_GLOBAL_BIND, (void **)&rsc->mHal.funcs.script.setGlobalBind);
+    ret &= fn(RS_HAL_SCRIPT_SET_GLOBAL_OBJECT, (void **)&rsc->mHal.funcs.script.setGlobalObj);
+    ret &= fn(RS_HAL_SCRIPT_DESTROY, (void **)&rsc->mHal.funcs.script.destroy);
+    ret &= fn(RS_HAL_SCRIPT_INVOKE_FOR_EACH_MULTI, (void **)&rsc->mHal.funcs.script.invokeForEachMulti);
+    ret &= fn(RS_HAL_SCRIPT_UPDATE_CACHED_OBJECT, (void **)&rsc->mHal.funcs.script.updateCachedObject);
+
+    ret &= fn(RS_HAL_ALLOCATION_INIT, (void **)&rsc->mHal.funcs.allocation.init);
+    ret &= fn(RS_HAL_ALLOCATION_INIT_ADAPTER, (void **)&rsc->mHal.funcs.allocation.initAdapter);
+    ret &= fn(RS_HAL_ALLOCATION_DESTROY, (void **)&rsc->mHal.funcs.allocation.destroy);
+    ret &= fn(RS_HAL_ALLOCATION_GET_GRALLOC_BITS, (void **)&rsc->mHal.funcs.allocation.grallocBits);
+    ret &= fn(RS_HAL_ALLOCATION_RESIZE, (void **)&rsc->mHal.funcs.allocation.resize);
+    ret &= fn(RS_HAL_ALLOCATION_SYNC_ALL, (void **)&rsc->mHal.funcs.allocation.syncAll);
+    ret &= fn(RS_HAL_ALLOCATION_MARK_DIRTY, (void **)&rsc->mHal.funcs.allocation.markDirty);
+    ret &= fn(RS_HAL_ALLOCATION_SET_SURFACE, (void **)&rsc->mHal.funcs.allocation.setSurface);
+    ret &= fn(RS_HAL_ALLOCATION_IO_SEND, (void **)&rsc->mHal.funcs.allocation.ioSend);
+    ret &= fn(RS_HAL_ALLOCATION_IO_RECEIVE, (void **)&rsc->mHal.funcs.allocation.ioReceive);
+    ret &= fn(RS_HAL_ALLOCATION_DATA_1D, (void **)&rsc->mHal.funcs.allocation.data1D);
+    ret &= fn(RS_HAL_ALLOCATION_DATA_2D, (void **)&rsc->mHal.funcs.allocation.data2D);
+    ret &= fn(RS_HAL_ALLOCATION_DATA_3D, (void **)&rsc->mHal.funcs.allocation.data3D);
+    ret &= fn(RS_HAL_ALLOCATION_READ_1D, (void **)&rsc->mHal.funcs.allocation.read1D);
+    ret &= fn(RS_HAL_ALLOCATION_READ_2D, (void **)&rsc->mHal.funcs.allocation.read2D);
+    ret &= fn(RS_HAL_ALLOCATION_READ_3D, (void **)&rsc->mHal.funcs.allocation.read3D);
+    ret &= fn(RS_HAL_ALLOCATION_LOCK_1D, (void **)&rsc->mHal.funcs.allocation.lock1D);
+    ret &= fn(RS_HAL_ALLOCATION_UNLOCK_1D, (void **)&rsc->mHal.funcs.allocation.unlock1D);
+    ret &= fn(RS_HAL_ALLOCATION_COPY_1D, (void **)&rsc->mHal.funcs.allocation.allocData1D);
+    ret &= fn(RS_HAL_ALLOCATION_COPY_2D, (void **)&rsc->mHal.funcs.allocation.allocData2D);
+    ret &= fn(RS_HAL_ALLOCATION_COPY_3D, (void **)&rsc->mHal.funcs.allocation.allocData3D);
+    ret &= fn(RS_HAL_ALLOCATION_ELEMENT_DATA, (void **)&rsc->mHal.funcs.allocation.elementData);
+    ret &= fn(RS_HAL_ALLOCATION_ELEMENT_READ, (void **)&rsc->mHal.funcs.allocation.elementRead);
+    ret &= fn(RS_HAL_ALLOCATION_GENERATE_MIPMAPS, (void **)&rsc->mHal.funcs.allocation.generateMipmaps);
+    ret &= fn(RS_HAL_ALLOCATION_UPDATE_CACHED_OBJECT, (void **)&rsc->mHal.funcs.allocation.updateCachedObject);
+    ret &= fn(RS_HAL_ALLOCATION_ADAPTER_OFFSET, (void **)&rsc->mHal.funcs.allocation.adapterOffset);
+
+    ret &= fn(RS_HAL_SAMPLER_INIT, (void **)&rsc->mHal.funcs.sampler.init);
+    ret &= fn(RS_HAL_SAMPLER_DESTROY, (void **)&rsc->mHal.funcs.sampler.destroy);
+    ret &= fn(RS_HAL_SAMPLER_UPDATE_CACHED_OBJECT, (void **)&rsc->mHal.funcs.sampler.updateCachedObject);
+
+    ret &= fn(RS_HAL_TYPE_INIT, (void **)&rsc->mHal.funcs.type.init);
+    ret &= fn(RS_HAL_TYPE_DESTROY, (void **)&rsc->mHal.funcs.type.destroy);
+    ret &= fn(RS_HAL_TYPE_UPDATE_CACHED_OBJECT, (void **)&rsc->mHal.funcs.type.updateCachedObject);
+
+    ret &= fn(RS_HAL_ELEMENT_INIT, (void **)&rsc->mHal.funcs.element.init);
+    ret &= fn(RS_HAL_ELEMENT_DESTROY, (void **)&rsc->mHal.funcs.element.destroy);
+    ret &= fn(RS_HAL_ELEMENT_UPDATE_CACHED_OBJECT, (void **)&rsc->mHal.funcs.element.updateCachedObject);
+
+    ret &= fn(RS_HAL_SCRIPT_GROUP_INIT, (void **)&rsc->mHal.funcs.scriptgroup.init);
+    ret &= fn(RS_HAL_SCRIPT_GROUP_DESTROY, (void **)&rsc->mHal.funcs.scriptgroup.destroy);
+    ret &= fn(RS_HAL_SCRIPT_GROUP_UPDATE_CACHED_OBJECT, (void **)&rsc->mHal.funcs.scriptgroup.updateCachedObject);
+    ret &= fn(RS_HAL_SCRIPT_GROUP_SET_INPUT, (void **)&rsc->mHal.funcs.scriptgroup.setInput);
+    ret &= fn(RS_HAL_SCRIPT_GROUP_SET_OUTPUT, (void **)&rsc->mHal.funcs.scriptgroup.setOutput);
+    ret &= fn(RS_HAL_SCRIPT_GROUP_EXECUTE, (void **)&rsc->mHal.funcs.scriptgroup.execute);
+
+
+    if (loadGraphics) {
+        ret &= fn(RS_HAL_GRAPHICS_INIT, (void **)&rsc->mHal.funcs.initGraphics);
+        ret &= fn(RS_HAL_GRAPHICS_SHUTDOWN, (void **)&rsc->mHal.funcs.shutdownGraphics);
+        ret &= fn(RS_HAL_GRAPHICS_SWAP, (void **)&rsc->mHal.funcs.swap);
+        ret &= fn(RS_HAL_GRAPHICS_SET_SURFACE, (void **)&rsc->mHal.funcs.setSurface);
+        ret &= fn(RS_HAL_GRAPHICS_RASTER_INIT, (void **)&rsc->mHal.funcs.raster.init);
+        ret &= fn(RS_HAL_GRAPHICS_RASTER_SET_ACTIVE, (void **)&rsc->mHal.funcs.raster.setActive);
+        ret &= fn(RS_HAL_GRAPHICS_RASTER_DESTROY, (void **)&rsc->mHal.funcs.raster.destroy);
+        ret &= fn(RS_HAL_GRAPHICS_VERTEX_INIT, (void **)&rsc->mHal.funcs.vertex.init);
+        ret &= fn(RS_HAL_GRAPHICS_VERTEX_SET_ACTIVE, (void **)&rsc->mHal.funcs.vertex.setActive);
+        ret &= fn(RS_HAL_GRAPHICS_VERTEX_DESTROY, (void **)&rsc->mHal.funcs.vertex.destroy);
+        ret &= fn(RS_HAL_GRAPHICS_FRAGMENT_INIT, (void **)&rsc->mHal.funcs.fragment.init);
+        ret &= fn(RS_HAL_GRAPHICS_FRAGMENT_SET_ACTIVE, (void **)&rsc->mHal.funcs.fragment.setActive);
+        ret &= fn(RS_HAL_GRAPHICS_FRAGMENT_DESTROY, (void **)&rsc->mHal.funcs.fragment.destroy);
+        ret &= fn(RS_HAL_GRAPHICS_MESH_INIT, (void **)&rsc->mHal.funcs.mesh.init);
+        ret &= fn(RS_HAL_GRAPHICS_MESH_DRAW, (void **)&rsc->mHal.funcs.mesh.draw);
+        ret &= fn(RS_HAL_GRAPHICS_MESH_DESTROY, (void **)&rsc->mHal.funcs);
+        ret &= fn(RS_HAL_GRAPHICS_FB_INIT, (void **)&rsc->mHal.funcs.framebuffer.init);
+        ret &= fn(RS_HAL_GRAPHICS_FB_SET_ACTIVE, (void **)&rsc->mHal.funcs.framebuffer.setActive);
+        ret &= fn(RS_HAL_GRAPHICS_FB_DESTROY, (void **)&rsc->mHal.funcs.framebuffer.destroy);
+        ret &= fn(RS_HAL_GRAPHICS_STORE_INIT, (void **)&rsc->mHal.funcs.store.init);
+        ret &= fn(RS_HAL_GRAPHICS_STORE_SET_ACTIVE, (void **)&rsc->mHal.funcs.store.setActive);
+        ret &= fn(RS_HAL_GRAPHICS_STORE_DESTROY, (void **)&rsc->mHal.funcs.store.destroy);
+    }
+
+    return ret;
+}
+
+bool Context::loadRuntime(const char* filename) {
+    HalQueryVersion fnQueryVersion = nullptr;
+    HalQueryHal fnQueryHal = nullptr;
+    HalInit fnInit = nullptr;
+    HalAbort fnAbort = nullptr;
+
+
+    // TODO: store the driverSO somewhere so we can dlclose later
+    void *driverSO = nullptr;
+
+    driverSO = dlopen(filename, RTLD_LAZY);
+    if (driverSO == nullptr) {
+        ALOGE("Failed loading RS driver: %s", dlerror());
+        return false;
+    }
+
+    // Need to call dlerror() to clear buffer before using it for dlsym().
+    (void) dlerror();
+
+    fnQueryVersion = (HalQueryVersion) dlsym(driverSO, "rsdHalQueryVersion");
+    fnQueryHal = (HalQueryHal) dlsym(driverSO, "rsdHalQueryHal");
+    fnInit = (HalInit) dlsym(driverSO, "rsdHalInit");
+    fnAbort = (HalAbort) dlsym(driverSO, "rsdHalAbort");
+    uint32_t version_major = 0;
+    uint32_t version_minor = 0;
+
+    if ((fnQueryVersion == nullptr) || (fnQueryHal == nullptr) ||
+        (fnInit == nullptr) || (fnAbort == nullptr)) {
+
+        ALOGE("Failed to find hal setup entry points: %s", dlerror());
+        goto error;
+    }
+
+    if (!fnQueryVersion(&version_major, &version_minor)) {
+        ALOGE("Error checking RS driver version, %s", filename);
+        goto error;
+    }
+
+    if (!LoadHalTable(this, fnQueryHal, mIsGraphicsContext)) {
+        ALOGE("Error loading RS HAL table, %s", filename);
+        goto error;
+    }
+
+    if (!(*fnInit)(this, 0, 0)) {
+        ALOGE("Hal init failed,  %s", filename);
+        goto error;
+    }
+
+    return true;
+
+
+error:
+    if (fnAbort != nullptr) {
+        fnAbort(this);
+    }
+    dlclose(driverSO);
+    return false;
+}
+
+
+
+bool Context::loadDriver(bool forceDefault) {
+    bool loadDefault = true;
+
+    // Provide a mechanism for dropping in a different RS driver.
+#ifndef RS_COMPATIBILITY_LIB
+#ifdef OVERRIDE_RS_DRIVER
+#define XSTR(S) #S
+#define STR(S) XSTR(S)
+#define OVERRIDE_RS_DRIVER_STRING STR(OVERRIDE_RS_DRIVER)
+
+    if (!forceDefault) {
+        if (loadRuntime(OVERRIDE_RS_DRIVER_STRING)) {
+            ALOGV("Successfully loaded runtime: %s", OVERRIDE_RS_DRIVER_STRING);
+            loadDefault = false;
+        } else {
+            ALOGE("Failed to load runtime %s, loading default", OVERRIDE_RS_DRIVER_STRING);
+        }
+    }
+#undef XSTR
+#undef STR
+#endif  // OVERRIDE_RS_DRIVER
+
+    if (loadDefault) {
+        if (!loadRuntime("libRSDriver.so")) {
+            ALOGE("Failed to load default runtime!");
+            return false;
+        }
+    }
+#else // RS_COMPATIBILITY_LIB
+    if (rsdHalInit(this, 0, 0) != true) {
+        return false;
+    }
+#endif
+
+    return true;
+}
+
+
+
diff --git a/rsPath.cpp b/rsPath.cpp
deleted file mode 100644
index bcf4b8e..0000000
--- a/rsPath.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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"
-#include "rs.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(Context *rsc, 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
deleted file mode 100644
index ea14335..0000000
--- a/rsPath.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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 "rsObjectBase.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(Context *rsc, 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/rsScriptC_LibGL.cpp b/rsScriptC_LibGL.cpp
index 5c55c6b..9304797 100644
--- a/rsScriptC_LibGL.cpp
+++ b/rsScriptC_LibGL.cpp
@@ -149,11 +149,7 @@
 
 
 void rsrDrawPath(Context *rsc, Path *sm) {
-    CHECK_OBJ(sm);
-    if (!rsc->setupCheck()) {
-        return;
-    }
-    sm->render(rsc);
+    // Never shipped in a working state
 }
 
 void rsrDrawMesh(Context *rsc, Mesh *sm) {
diff --git a/rs_hal.h b/rs_hal.h
index 5e8fee8..f8e9e4b 100644
--- a/rs_hal.h
+++ b/rs_hal.h
@@ -19,6 +19,30 @@
 
 #include <rsInternalDefines.h>
 
+/**
+ * The interface for loading RenderScript drivers
+ *
+ * The startup sequence is
+ *
+ * 1: dlopen driver
+ * 2: Query driver version with rsdHalQueryVersion()
+ * 3: Fill in HAL pointer table with calls to rsdHalQueryHAL()
+ * 4: Initialize the context with rsdHalInit()
+ *
+ * If any of these functions return false, the loading of the
+ * driver will abort and the reference driver will be used.
+ * rsdHalAbort() will be called to clean up any partially
+ * allocated state.
+ *
+ * If these are successful, the driver will be loaded and used
+ * normally.  Teardown will use the normal
+ * context->mHal.funcs.shutdown() path.  There will be no call
+ * to rsdHalAbort().
+ *
+ *
+ */
+
+
 struct ANativeWindow;
 
 namespace android {
@@ -94,7 +118,6 @@
     void (*swap)(const Context *);
 
     void (*shutdownDriver)(Context *);
-    void (*getVersion)(unsigned int *major, unsigned int *minor);
     void (*setPriority)(const Context *, int32_t priority);
 
     void* (*allocRuntimeMem)(size_t size, uint32_t flags);
@@ -287,13 +310,6 @@
     } 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);
         void (*updateCachedObject)(const Context *rsc, const Sampler *s, rs_sampler *obj);
@@ -332,6 +348,101 @@
 } RsdHalFunctions;
 
 
+enum RsHalInitEnums {
+    RS_HAL_CORE_SHUTDOWN                                    = 1,
+    RS_HAL_CORE_SET_PRIORITY                                = 2,
+    RS_HAL_CORE_ALLOC_RUNTIME_MEM                           = 3,
+    RS_HAL_CORE_FREE_RUNTIME_MEM                            = 4,
+    RS_HAL_CORE_FINISH                                      = 5,
+
+    RS_HAL_SCRIPT_INIT                                      = 1000,
+    RS_HAL_SCRIPT_INIT_INTRINSIC                            = 1001,
+    RS_HAL_SCRIPT_INVOKE_FUNCTION                           = 1002,
+    RS_HAL_SCRIPT_INVOKE_ROOT                               = 1003,
+    RS_HAL_SCRIPT_INVOKE_FOR_EACH                           = 1004,
+    RS_HAL_SCRIPT_INVOKE_INIT                               = 1005,
+    RS_HAL_SCRIPT_INVOKE_FREE_CHILDREN                      = 1006,
+    RS_HAL_SCRIPT_SET_GLOBAL_VAR                            = 1007,
+    RS_HAL_SCRIPT_GET_GLOBAL_VAR                            = 1008,
+    RS_HAL_SCRIPT_SET_GLOBAL_VAR_WITH_ELEMENT_DIM           = 1009,
+    RS_HAL_SCRIPT_SET_GLOBAL_BIND                           = 1010,
+    RS_HAL_SCRIPT_SET_GLOBAL_OBJECT                         = 1011,
+    RS_HAL_SCRIPT_DESTROY                                   = 1012,
+    RS_HAL_SCRIPT_INVOKE_FOR_EACH_MULTI                     = 1013,
+    RS_HAL_SCRIPT_UPDATE_CACHED_OBJECT                      = 1014,
+
+    RS_HAL_ALLOCATION_INIT                                  = 2000,
+    RS_HAL_ALLOCATION_INIT_ADAPTER                          = 2001,
+    RS_HAL_ALLOCATION_DESTROY                               = 2002,
+    RS_HAL_ALLOCATION_GET_GRALLOC_BITS                      = 2003,
+    RS_HAL_ALLOCATION_RESIZE                                = 2004,
+    RS_HAL_ALLOCATION_SYNC_ALL                              = 2005,
+    RS_HAL_ALLOCATION_MARK_DIRTY                            = 2006,
+    RS_HAL_ALLOCATION_SET_SURFACE                           = 2007,
+    RS_HAL_ALLOCATION_IO_SEND                               = 2008,
+    RS_HAL_ALLOCATION_IO_RECEIVE                            = 2009,
+    RS_HAL_ALLOCATION_DATA_1D                               = 2010,
+    RS_HAL_ALLOCATION_DATA_2D                               = 2011,
+    RS_HAL_ALLOCATION_DATA_3D                               = 2012,
+    RS_HAL_ALLOCATION_READ_1D                               = 2013,
+    RS_HAL_ALLOCATION_READ_2D                               = 2014,
+    RS_HAL_ALLOCATION_READ_3D                               = 2015,
+    RS_HAL_ALLOCATION_LOCK_1D                               = 2016,
+    RS_HAL_ALLOCATION_UNLOCK_1D                             = 2017,
+    RS_HAL_ALLOCATION_COPY_1D                               = 2018,
+    RS_HAL_ALLOCATION_COPY_2D                               = 2019,
+    RS_HAL_ALLOCATION_COPY_3D                               = 2020,
+    RS_HAL_ALLOCATION_ELEMENT_DATA                          = 2021,
+    RS_HAL_ALLOCATION_ELEMENT_READ                          = 2022,
+    RS_HAL_ALLOCATION_GENERATE_MIPMAPS                      = 2023,
+    RS_HAL_ALLOCATION_UPDATE_CACHED_OBJECT                  = 2024,
+    RS_HAL_ALLOCATION_ADAPTER_OFFSET                        = 2025,
+
+    RS_HAL_SAMPLER_INIT                                     = 3000,
+    RS_HAL_SAMPLER_DESTROY                                  = 3001,
+    RS_HAL_SAMPLER_UPDATE_CACHED_OBJECT                     = 3002,
+
+    RS_HAL_TYPE_INIT                                        = 4000,
+    RS_HAL_TYPE_DESTROY                                     = 4001,
+    RS_HAL_TYPE_UPDATE_CACHED_OBJECT                        = 4002,
+
+    RS_HAL_ELEMENT_INIT                                     = 5000,
+    RS_HAL_ELEMENT_DESTROY                                  = 5001,
+    RS_HAL_ELEMENT_UPDATE_CACHED_OBJECT                     = 5002,
+
+    RS_HAL_SCRIPT_GROUP_INIT                                = 6000,
+    RS_HAL_SCRIPT_GROUP_DESTROY                             = 6001,
+    RS_HAL_SCRIPT_GROUP_UPDATE_CACHED_OBJECT                = 6002,
+    RS_HAL_SCRIPT_GROUP_SET_INPUT                           = 6003,
+    RS_HAL_SCRIPT_GROUP_SET_OUTPUT                          = 6004,
+    RS_HAL_SCRIPT_GROUP_EXECUTE                             = 6005,
+
+
+
+    RS_HAL_GRAPHICS_INIT                                    = 100001,
+    RS_HAL_GRAPHICS_SHUTDOWN                                = 100002,
+    RS_HAL_GRAPHICS_SWAP                                    = 100003,
+    RS_HAL_GRAPHICS_SET_SURFACE                             = 100004,
+    RS_HAL_GRAPHICS_RASTER_INIT                             = 101000,
+    RS_HAL_GRAPHICS_RASTER_SET_ACTIVE                       = 101001,
+    RS_HAL_GRAPHICS_RASTER_DESTROY                          = 101002,
+    RS_HAL_GRAPHICS_VERTEX_INIT                             = 102000,
+    RS_HAL_GRAPHICS_VERTEX_SET_ACTIVE                       = 102001,
+    RS_HAL_GRAPHICS_VERTEX_DESTROY                          = 102002,
+    RS_HAL_GRAPHICS_FRAGMENT_INIT                           = 103000,
+    RS_HAL_GRAPHICS_FRAGMENT_SET_ACTIVE                     = 103001,
+    RS_HAL_GRAPHICS_FRAGMENT_DESTROY                        = 103002,
+    RS_HAL_GRAPHICS_MESH_INIT                               = 104000,
+    RS_HAL_GRAPHICS_MESH_DRAW                               = 104001,
+    RS_HAL_GRAPHICS_MESH_DESTROY                            = 104002,
+    RS_HAL_GRAPHICS_FB_INIT                                 = 105000,
+    RS_HAL_GRAPHICS_FB_SET_ACTIVE                           = 105001,
+    RS_HAL_GRAPHICS_FB_DESTROY                              = 105002,
+    RS_HAL_GRAPHICS_STORE_INIT                              = 106000,
+    RS_HAL_GRAPHICS_STORE_SET_ACTIVE                        = 106001,
+    RS_HAL_GRAPHICS_STORE_DESTROY                           = 106002,
+};
+
 }
 }
 
@@ -339,8 +450,47 @@
 extern "C" {
 #endif
 
+/**
+ * Get the major version number of the driver.  The major
+ * version should be the API version number
+ *
+ * The Minor version number is vendor specific
+ *
+ * return: False will abort loading the driver, true indicates
+ * success
+ */
+bool rsdHalQueryVersion(uint32_t *version_major, uint32_t *version_minor);
+
+
+/**
+ * Get an entry point in the driver HAL
+ *
+ * The driver should set the function pointer to its
+ * implementation of the function.  If it does not have an entry
+ * for an enum, its should set the function pointer to NULL
+ *
+ * return: False will abort loading the driver, true indicates
+ * success
+ */
+bool rsdHalQueryHal(android::renderscript::RsHalInitEnums entry, void **fnPtr);
+
+
+/**
+ * Called to initialize the context for use with a driver.
+ *
+ * return: False will abort loading the driver, true indicates
+ * success
+ */
 bool rsdHalInit(RsContext, uint32_t version_major, uint32_t version_minor);
 
+/**
+ * Called if one of the loading functions above returns false.
+ * This is to clean up any resources allocated during an error
+ * condition. If this path is called it means the normal
+ * context->mHal.funcs.shutdown() will not be called.
+ */
+void rsdHalAbort(RsContext);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/rsg.spec b/rsg.spec
index a80a31c..dbe9db2 100644
--- a/rsg.spec
+++ b/rsg.spec
@@ -76,15 +76,6 @@
     ret RsMesh
     }
 
-PathCreate {
-    param RsPathPrimitive pp
-    param bool isStatic
-    param RsAllocation vertex
-    param RsAllocation loops
-    param float quality
-    ret RsPath
-    }
-
 ContextBindProgramStore {
     param RsProgramStore pgm
     }