Merge "Fixing uint32 size_t mismatches."
diff --git a/driver/rsdAllocation.cpp b/driver/rsdAllocation.cpp
index 53e0e48..fb93d82 100644
--- a/driver/rsdAllocation.cpp
+++ b/driver/rsdAllocation.cpp
@@ -23,6 +23,11 @@
 
 #include "rsAllocation.h"
 
+#include "system/window.h"
+#include "hardware/gralloc.h"
+#include "ui/Rect.h"
+#include "ui/GraphicBufferMapper.h"
+
 #include <GLES/gl.h>
 #include <GLES2/gl2.h>
 #include <GLES/glext.h>
@@ -220,7 +225,8 @@
     }
 
     void * ptr = alloc->mHal.state.usrPtr;
-    if (!ptr) {
+    if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) {
+    } else {
         ptr = malloc(alloc->mHal.state.type->getSizeBytes());
         if (!ptr) {
             free(drv);
@@ -248,7 +254,7 @@
     alloc->mHal.drvState.mallocPtr = ptr;
     drv->mallocPtr = (uint8_t *)ptr;
     alloc->mHal.drv = drv;
-    if (forceZero) {
+    if (forceZero && ptr) {
         memset(ptr, 0, alloc->mHal.state.type->getSizeBytes());
     }
 
@@ -386,6 +392,93 @@
     return drv->textureID;
 }
 
+static bool IoGetBuffer(const Context *rsc, Allocation *alloc, ANativeWindow *nw) {
+    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+
+    int32_t r = nw->dequeueBuffer(nw, &drv->wndBuffer);
+    if (r) {
+        rsc->setError(RS_ERROR_DRIVER, "Error getting next IO output buffer.");
+        return false;
+    }
+
+    // This lock is implicitly released by the queue buffer in IoSend
+    r = nw->lockBuffer(nw, drv->wndBuffer);
+    if (r) {
+        rsc->setError(RS_ERROR_DRIVER, "Error locking next IO output buffer.");
+        return false;
+    }
+
+    // Must lock the whole surface
+    GraphicBufferMapper &mapper = GraphicBufferMapper::get();
+    Rect bounds(drv->wndBuffer->width, drv->wndBuffer->height);
+
+    void *dst = NULL;
+    mapper.lock(drv->wndBuffer->handle,
+            GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN,
+            bounds, &dst);
+    alloc->mHal.drvState.mallocPtr = dst;
+    return true;
+}
+
+void rsdAllocationSetSurfaceTexture(const Context *rsc, Allocation *alloc, ANativeWindow *nw) {
+    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+
+    //ALOGE("rsdAllocationSetSurfaceTexture %p  %p", alloc, nw);
+
+    // Cleanup old surface if there is one.
+    if (alloc->mHal.state.wndSurface) {
+        ANativeWindow *old = alloc->mHal.state.wndSurface;
+        GraphicBufferMapper &mapper = GraphicBufferMapper::get();
+        mapper.unlock(drv->wndBuffer->handle);
+        old->queueBuffer(old, drv->wndBuffer);
+    }
+
+    if (nw != NULL) {
+        int32_t r;
+        r = native_window_set_usage(nw, GRALLOC_USAGE_SW_READ_RARELY |
+                                        GRALLOC_USAGE_SW_WRITE_OFTEN);
+        if (r) {
+            rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer usage.");
+            return;
+        }
+
+        r = native_window_set_buffers_dimensions(nw, alloc->mHal.state.dimensionX,
+                                                 alloc->mHal.state.dimensionY);
+        if (r) {
+            rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer dimensions.");
+            return;
+        }
+
+        r = native_window_set_buffer_count(nw, 3);
+        if (r) {
+            rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer count.");
+            return;
+        }
+
+        IoGetBuffer(rsc, alloc, nw);
+    }
+}
+
+void rsdAllocationIoSend(const Context *rsc, Allocation *alloc) {
+    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+    ANativeWindow *nw = alloc->mHal.state.wndSurface;
+
+    GraphicBufferMapper &mapper = GraphicBufferMapper::get();
+    mapper.unlock(drv->wndBuffer->handle);
+    int32_t r = nw->queueBuffer(nw, drv->wndBuffer);
+    if (r) {
+        rsc->setError(RS_ERROR_DRIVER, "Error sending IO output buffer.");
+        return;
+    }
+
+    IoGetBuffer(rsc, alloc, nw);
+}
+
+void rsdAllocationIoReceive(const Context *rsc, Allocation *alloc) {
+    ALOGE("not implemented");
+}
+
+
 void rsdAllocationData1D(const Context *rsc, const Allocation *alloc,
                          uint32_t xoff, uint32_t lod, uint32_t count,
                          const void *data, size_t sizeBytes) {
diff --git a/driver/rsdAllocation.h b/driver/rsdAllocation.h
index 230804b..e3a5126 100644
--- a/driver/rsdAllocation.h
+++ b/driver/rsdAllocation.h
@@ -24,6 +24,7 @@
 #include <GLES2/gl2.h>
 
 class RsdFrameBufferObj;
+struct ANativeWindowBuffer;
 
 struct DrvAllocation {
     // Is this a legal structure to be used as a texture source.
@@ -47,6 +48,7 @@
     bool uploadDeferred;
 
     RsdFrameBufferObj * readBackFBO;
+    ANativeWindowBuffer *wndBuffer;
 };
 
 GLenum rsdTypeToGLType(RsDataType t);
@@ -69,6 +71,12 @@
                             const android::renderscript::Allocation *alloc);
 int32_t rsdAllocationInitSurfaceTexture(const android::renderscript::Context *rsc,
                                         const android::renderscript::Allocation *alloc);
+void rsdAllocationSetSurfaceTexture(const android::renderscript::Context *rsc,
+                                    android::renderscript::Allocation *alloc, ANativeWindow *nw);
+void rsdAllocationIoSend(const android::renderscript::Context *rsc,
+                         android::renderscript::Allocation *alloc);
+void rsdAllocationIoReceive(const android::renderscript::Context *rsc,
+                            android::renderscript::Allocation *alloc);
 
 void rsdAllocationData1D(const android::renderscript::Context *rsc,
                          const android::renderscript::Allocation *alloc,
diff --git a/driver/rsdCore.cpp b/driver/rsdCore.cpp
index e011955..bf2b62a 100644
--- a/driver/rsdCore.cpp
+++ b/driver/rsdCore.cpp
@@ -74,6 +74,9 @@
         rsdAllocationSyncAll,
         rsdAllocationMarkDirty,
         rsdAllocationInitSurfaceTexture,
+        rsdAllocationSetSurfaceTexture,
+        rsdAllocationIoSend,
+        rsdAllocationIoReceive,
         rsdAllocationData1D,
         rsdAllocationData2D,
         rsdAllocationData3D,
diff --git a/rs.spec b/rs.spec
index 6759bc7..491474e 100644
--- a/rs.spec
+++ b/rs.spec
@@ -69,6 +69,21 @@
     ret int32_t
 }
 
+AllocationSetSurface {
+    param RsAllocation alloc
+    param RsNativeWindow sur
+    sync
+    }
+
+AllocationIoSend {
+    param RsAllocation alloc
+    }
+
+AllocationIoReceive {
+    param RsAllocation alloc
+    }
+
+
 ContextFinish {
 	sync
 	}
diff --git a/rsAllocation.cpp b/rsAllocation.cpp
index 02c6809..83c88fd 100644
--- a/rsAllocation.cpp
+++ b/rsAllocation.cpp
@@ -17,6 +17,7 @@
 #include "rsContext.h"
 #include "rs_hal.h"
 
+#include "system/window.h"
 
 using namespace android;
 using namespace android::renderscript;
@@ -44,6 +45,7 @@
         delete a;
         return NULL;
     }
+
     return a;
 }
 
@@ -420,6 +422,28 @@
     return id;
 }
 
+void Allocation::setSurface(const Context *rsc, RsNativeWindow sur) {
+    ANativeWindow *nw = (ANativeWindow *)sur;
+    ANativeWindow *old = mHal.state.wndSurface;
+    if (nw) {
+        nw->incStrong(NULL);
+    }
+    rsc->mHal.funcs.allocation.setSurfaceTexture(rsc, this, nw);
+    mHal.state.wndSurface = nw;
+    if (old) {
+        old->decStrong(NULL);
+    }
+}
+
+void Allocation::ioSend(const Context *rsc) {
+    rsc->mHal.funcs.allocation.ioSend(rsc, this);
+}
+
+void Allocation::ioReceive(const Context *rsc) {
+    rsc->mHal.funcs.allocation.ioReceive(rsc, this);
+}
+
+
 /////////////////
 //
 
@@ -670,6 +694,21 @@
     return alloc->getSurfaceTextureID(rsc);
 }
 
+void rsi_AllocationSetSurface(Context *rsc, RsAllocation valloc, RsNativeWindow sur) {
+    Allocation *alloc = static_cast<Allocation *>(valloc);
+    alloc->setSurface(rsc, sur);
+}
+
+void rsi_AllocationIoSend(Context *rsc, RsAllocation valloc) {
+    Allocation *alloc = static_cast<Allocation *>(valloc);
+    alloc->ioSend(rsc);
+}
+
+void rsi_AllocationIoReceive(Context *rsc, RsAllocation valloc) {
+    Allocation *alloc = static_cast<Allocation *>(valloc);
+    alloc->ioReceive(rsc);
+}
+
 }
 }
 
diff --git a/rsAllocation.h b/rsAllocation.h
index 58a582b..58a6fca 100644
--- a/rsAllocation.h
+++ b/rsAllocation.h
@@ -19,6 +19,8 @@
 
 #include "rsType.h"
 
+struct ANativeWindow;
+
 // ---------------------------------------------------------------------------
 namespace android {
 namespace renderscript {
@@ -57,6 +59,7 @@
             bool hasReferences;
             void * usrPtr;
             int32_t surfaceTextureID;
+            ANativeWindow *wndSurface;
         };
         State state;
 
@@ -127,6 +130,9 @@
     }
 
     int32_t getSurfaceTextureID(const Context *rsc);
+    void setSurface(const Context *rsc, RsNativeWindow sur);
+    void ioSend(const Context *rsc);
+    void ioReceive(const Context *rsc);
 
 protected:
     Vector<const Program *> mToDirtyList;
diff --git a/rs_hal.h b/rs_hal.h
index 7c9618a..12ace43 100644
--- a/rs_hal.h
+++ b/rs_hal.h
@@ -19,6 +19,8 @@
 
 #include <RenderScriptDefines.h>
 
+struct ANativeWindow;
+
 namespace android {
 namespace renderscript {
 
@@ -115,7 +117,11 @@
                        bool zeroNew);
         void (*syncAll)(const Context *rsc, const Allocation *alloc, RsAllocationUsageType src);
         void (*markDirty)(const Context *rsc, const Allocation *alloc);
+
         int32_t (*initSurfaceTexture)(const Context *rsc, const Allocation *alloc);
+        void (*setSurfaceTexture)(const Context *rsc, Allocation *alloc, ANativeWindow *sur);
+        void (*ioSend)(const Context *rsc, Allocation *alloc);
+        void (*ioReceive)(const Context *rsc, Allocation *alloc);
 
         void (*data1D)(const Context *rsc, const Allocation *alloc,
                        uint32_t xoff, uint32_t lod, uint32_t count,