Beging IO stream out from allocation to surface texture.

Change-Id: I4d6b7f7740a896d39b811d6fe7532bb00db62373
diff --git a/driver/rsdAllocation.cpp b/driver/rsdAllocation.cpp
index ea92192..b673a0a 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, uint32_t sizeBytes) {