Merge "Support LinkRuntimeCallback() with RS compiler."
diff --git a/cpu_ref/rsCpuIntrinsicYuvToRGB.cpp b/cpu_ref/rsCpuIntrinsicYuvToRGB.cpp
index 946d1ba..bb8cde1 100644
--- a/cpu_ref/rsCpuIntrinsicYuvToRGB.cpp
+++ b/cpu_ref/rsCpuIntrinsicYuvToRGB.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013 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.
@@ -108,12 +108,13 @@
         ALOGE("YuvToRGB executed without input, skipping");
         return;
     }
-    const uchar *pin = (const uchar *)cp->alloc->mHal.drvState.lod[0].mallocPtr;
-    const size_t stride = cp->alloc->mHal.drvState.lod[0].stride;
+    const uchar *pinY = (const uchar *)cp->alloc->mHal.drvState.lod[0].mallocPtr;
+    const uchar *pinUV = (const uchar *)cp->alloc->mHal.drvState.lod[1].mallocPtr;
+    const size_t strideY = cp->alloc->mHal.drvState.lod[0].stride;
+    const size_t strideUV = cp->alloc->mHal.drvState.lod[1].stride;
 
-    const uchar *Y = pin + (p->y * p->dimX);
-    const uchar *uv = pin + (p->dimX * p->dimY);
-    uv += (p->y>>1) * p->dimX;
+    const uchar *Y = pinY + (p->y * strideY);
+    const uchar *uv = pinUV + ((p->y >> 1) * strideUV);
 
     uchar4 *out = (uchar4 *)p->out;
     uint32_t x1 = xstart;
diff --git a/cpu_ref/rsCpuRuntimeStubs.cpp b/cpu_ref/rsCpuRuntimeStubs.cpp
index b87a639..ceea9c4 100644
--- a/cpu_ref/rsCpuRuntimeStubs.cpp
+++ b/cpu_ref/rsCpuRuntimeStubs.cpp
@@ -64,22 +64,6 @@
 //////////////////////////////////////////////////////////////////////////////
 
 
-int SC_divsi3(int a, int b) {
-    return a / b;
-}
-
-int SC_modsi3(int a, int b) {
-    return a % b;
-}
-
-unsigned int SC_udivsi3(unsigned int a, unsigned int b) {
-    return a / b;
-}
-
-unsigned int SC_umodsi3(unsigned int a, unsigned int b) {
-    return a % b;
-}
-
 static void SC_debugF(const char *s, float f) {
     ALOGD("%s %f, 0x%08x", s, f, *((int *) (&f)));
 }
diff --git a/driver/rsdAllocation.cpp b/driver/rsdAllocation.cpp
index aacdac3..7828baf 100644
--- a/driver/rsdAllocation.cpp
+++ b/driver/rsdAllocation.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 The Android Open Source Project
+ * Copyright (C) 2013 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.
@@ -272,7 +272,38 @@
             if (ty > 1) ty >>= 1;
             if (tz > 1) tz >>= 1;
         }
+    } else if (alloc->mHal.state.yuv) {
+        // YUV only supports basic 2d
+        // so we can stash the plane pointers in the mipmap levels.
+        switch(alloc->mHal.state.yuv) {
+        case HAL_PIXEL_FORMAT_YV12:
+            offsets[1] = o;
+            alloc->mHal.drvState.lod[1].dimX = alloc->mHal.drvState.lod[0].dimX / 2;
+            alloc->mHal.drvState.lod[1].dimY = alloc->mHal.drvState.lod[0].dimY / 2;
+            alloc->mHal.drvState.lod[1].stride = rsRound(alloc->mHal.drvState.lod[1].dimX *
+                                                  type->getElementSizeBytes(), 16);
+            o += alloc->mHal.drvState.lod[1].stride * alloc->mHal.drvState.lod[1].dimY;
+            offsets[2] = o;
+            alloc->mHal.drvState.lod[2].dimX = alloc->mHal.drvState.lod[1].dimX;
+            alloc->mHal.drvState.lod[2].dimY = alloc->mHal.drvState.lod[1].dimY;
+            alloc->mHal.drvState.lod[2].stride = alloc->mHal.drvState.lod[1].stride;
+            o += alloc->mHal.drvState.lod[2].stride * alloc->mHal.drvState.lod[2].dimY;
+            alloc->mHal.drvState.lodCount = 3;
+            break;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:  // NV21
+            offsets[1] = o;
+            alloc->mHal.drvState.lod[1].dimX = alloc->mHal.drvState.lod[0].dimX;
+            alloc->mHal.drvState.lod[1].dimY = alloc->mHal.drvState.lod[0].dimY / 2;
+            alloc->mHal.drvState.lod[1].stride = rsRound(alloc->mHal.drvState.lod[1].dimX *
+                                                  type->getElementSizeBytes(), 16);
+            o += alloc->mHal.drvState.lod[1].stride * alloc->mHal.drvState.lod[1].dimY;
+            alloc->mHal.drvState.lodCount = 2;
+            break;
+        default:
+            rsAssert(0);
+        }
     }
+
     alloc->mHal.drvState.faceOffset = o;
 
     alloc->mHal.drvState.lod[0].mallocPtr = ptr;
@@ -288,6 +319,18 @@
     return allocSize;
 }
 
+static uint8_t* allocAlignedMemory(size_t allocSize, bool forceZero) {
+    // We align all allocations to a 16-byte boundary.
+    uint8_t* ptr = (uint8_t *)memalign(16, allocSize);
+    if (!ptr) {
+        return NULL;
+    }
+    if (forceZero) {
+        memset(ptr, 0, allocSize);
+    }
+    return ptr;
+}
+
 bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) {
     DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
     if (!drv) {
@@ -311,18 +354,31 @@
             ALOGE("User-allocated buffers must not have multiple faces or LODs");
             return false;
         }
-        ptr = (uint8_t*)alloc->mHal.state.userProvidedPtr;
+
+        // rows must be 16-byte aligned
+        // validate that here, otherwise fall back to not use the user-backed allocation
+        if (((alloc->getType()->getDimX() * alloc->getType()->getElement()->getSizeBytes()) % 16) != 0) {
+            ALOGV("User-backed allocation failed stride requirement, falling back to separate allocation");
+            drv->useUserProvidedPtr = false;
+
+            ptr = allocAlignedMemory(allocSize, forceZero);
+            if (!ptr) {
+                alloc->mHal.drv = NULL;
+                free(drv);
+                return false;
+            }
+
+        } else {
+            drv->useUserProvidedPtr = true;
+            ptr = (uint8_t*)alloc->mHal.state.userProvidedPtr;
+        }
     } else {
-        // We align all allocations to a 16-byte boundary.
-        ptr = (uint8_t *)memalign(16, allocSize);
+        ptr = allocAlignedMemory(allocSize, forceZero);
         if (!ptr) {
             alloc->mHal.drv = NULL;
             free(drv);
             return false;
         }
-        if (forceZero) {
-            memset(ptr, 0, allocSize);
-        }
     }
     // Build the pointer tables
     size_t verifySize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), ptr);
@@ -358,6 +414,11 @@
 
     drv->readBackFBO = NULL;
 
+    // fill out the initial state of the buffer if we couldn't use the user-provided ptr and USAGE_SHARED was accepted
+    if ((alloc->mHal.state.userProvidedPtr != 0) && (drv->useUserProvidedPtr == false)) {
+        rsdAllocationData2D(rsc, alloc, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, alloc->getType()->getDimX(), alloc->getType()->getDimY(), alloc->mHal.state.userProvidedPtr, allocSize, 0);
+    }
+
     return true;
 }
 
@@ -383,7 +444,7 @@
 
     if (alloc->mHal.drvState.lod[0].mallocPtr) {
         // don't free user-allocated ptrs
-        if (!(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SHARED)) {
+        if (!(drv->useUserProvidedPtr)) {
             free(alloc->mHal.drvState.lod[0].mallocPtr);
         }
         alloc->mHal.drvState.lod[0].mallocPtr = NULL;
@@ -688,6 +749,21 @@
             src += stride;
             dst += alloc->mHal.drvState.lod[lod].stride;
         }
+        if (alloc->mHal.state.yuv) {
+            int lod = 1;
+            while (alloc->mHal.drvState.lod[lod].mallocPtr) {
+                uint32_t lineSize = alloc->mHal.drvState.lod[lod].dimX;
+                uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, lod, face);
+
+                for (uint32_t line=(yoff >> 1); line < ((yoff+h)>>1); line++) {
+                    memcpy(dst, src, lineSize);
+                    src += lineSize;
+                    dst += alloc->mHal.drvState.lod[lod].stride;
+                }
+                lod++;
+            }
+
+        }
         drv->uploadDeferred = true;
     } else {
         Update2DTexture(rsc, alloc, data, xoff, yoff, lod, face, w, h);
diff --git a/driver/rsdAllocation.h b/driver/rsdAllocation.h
index d506dc4..306c1b9 100644
--- a/driver/rsdAllocation.h
+++ b/driver/rsdAllocation.h
@@ -52,6 +52,7 @@
     int glFormat;
 #endif
 
+    bool useUserProvidedPtr;
     bool uploadDeferred;
 
     RsdFrameBufferObj * readBackFBO;
diff --git a/driver/rsdGL.cpp b/driver/rsdGL.cpp
index 2b4b925..58c52e2 100644
--- a/driver/rsdGL.cpp
+++ b/driver/rsdGL.cpp
@@ -42,7 +42,7 @@
 #include "rsdVertexArray.h"
 #include "rsdFrameBufferObj.h"
 
-#include <gui/SurfaceTextureClient.h>
+#include <gui/Surface.h>
 #include <gui/DummyConsumer.h>
 
 using namespace android;
@@ -331,7 +331,7 @@
     // Create a BufferQueue with a fake consumer
     sp<BufferQueue> bq = new BufferQueue();
     bq->consumerConnect(new DummyConsumer());
-    sp<SurfaceTextureClient> stc(new SurfaceTextureClient(static_cast<sp<IGraphicBufferProducer> >(bq)));
+    sp<Surface> stc(new Surface(static_cast<sp<IGraphicBufferProducer> >(bq)));
 
     dc->gl.egl.surfaceDefault = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config,
                                                        static_cast<ANativeWindow*>(stc.get()),
diff --git a/rsAllocation.cpp b/rsAllocation.cpp
index b215dba..1f36040 100644
--- a/rsAllocation.cpp
+++ b/rsAllocation.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2012 The Android Open Source Project
+ * Copyright (C) 2013 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.
diff --git a/rsAllocation.h b/rsAllocation.h
index 09ce104..0948011 100644
--- a/rsAllocation.h
+++ b/rsAllocation.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2012 The Android Open Source Project
+ * Copyright (C) 2013 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.
diff --git a/rsComponent.cpp b/rsComponent.cpp
index d240952..e48af4e 100644
--- a/rsComponent.cpp
+++ b/rsComponent.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2012 The Android Open Source Project
+ * Copyright (C) 2013 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.
@@ -61,6 +61,12 @@
         rsAssert(mVectorSize == 4);
         rsAssert(mNormalized == true);
         break;
+    case RS_KIND_PIXEL_YUV:
+        mIsPixel = true;
+        rsAssert(mVectorSize == 1);
+        rsAssert(mNormalized == true);
+        break;
+
     default:
         rsAssert(mKind != RS_KIND_INVALID);
         break;
diff --git a/rsDefines.h b/rsDefines.h
index dfa0f9d..413f1ba 100644
--- a/rsDefines.h
+++ b/rsDefines.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2012 The Android Open Source Project
+ * Copyright (C) 2013 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.
@@ -174,6 +174,7 @@
     RS_KIND_PIXEL_RGB,
     RS_KIND_PIXEL_RGBA,
     RS_KIND_PIXEL_DEPTH,
+    RS_KIND_PIXEL_YUV,
 
     RS_KIND_INVALID = 100,
 };
@@ -194,6 +195,7 @@
     RS_SAMPLER_WRAP,
     RS_SAMPLER_CLAMP,
     RS_SAMPLER_LINEAR_MIP_NEAREST,
+    RS_SAMPLER_MIRRORED_REPEAT,
 
     RS_SAMPLER_INVALID = 100,
 };
diff --git a/rsType.cpp b/rsType.cpp
index 1fba2f9..74a1a54 100644
--- a/rsType.cpp
+++ b/rsType.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2013 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.
@@ -16,6 +16,8 @@
 
 #include "rsContext.h"
 
+#include "system/graphics.h"
+
 using namespace android;
 using namespace android::renderscript;
 
@@ -106,6 +108,32 @@
     if (mHal.state.faces) {
         offset *= 6;
     }
+
+    // YUV only supports basic 2d
+    // so we can stash the plane pointers in the mipmap levels.
+    if (mHal.state.dimYuv) {
+        switch(mHal.state.dimYuv) {
+        case HAL_PIXEL_FORMAT_YV12:
+            mHal.state.lodOffset[1] = offset;
+            mHal.state.lodDimX[1] = mHal.state.lodDimX[0] / 2;
+            mHal.state.lodDimY[1] = mHal.state.lodDimY[0] / 2;
+            offset += offset / 4;
+            mHal.state.lodOffset[2] = offset;
+            mHal.state.lodDimX[2] = mHal.state.lodDimX[0] / 2;
+            mHal.state.lodDimY[2] = mHal.state.lodDimY[0] / 2;
+            offset += offset / 4;
+            break;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:  // NV21
+            mHal.state.lodOffset[1] = offset;
+            mHal.state.lodDimX[1] = mHal.state.lodDimX[0];
+            mHal.state.lodDimY[1] = mHal.state.lodDimY[0] / 2;
+            offset += offset / 2;
+            break;
+        default:
+            rsAssert(0);
+        }
+    }
+
     mTotalSizeBytes = offset;
     mHal.state.element = mElement.get();
 }
diff --git a/rsType.h b/rsType.h
index 8ccf757..d2bc96b 100644
--- a/rsType.h
+++ b/rsType.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2013 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.
diff --git a/scriptc/rs_types.rsh b/scriptc/rs_types.rsh
index 5c99313..57dba37 100644
--- a/scriptc/rs_types.rsh
+++ b/scriptc/rs_types.rsh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2013 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.
@@ -530,6 +530,7 @@
     RS_KIND_PIXEL_RGB    = 10,
     RS_KIND_PIXEL_RGBA   = 11,
     RS_KIND_PIXEL_DEPTH  = 12,
+    RS_KIND_PIXEL_YUV    = 13,
 
     RS_KIND_INVALID      = 100,
 } rs_data_kind;
@@ -617,6 +618,7 @@
     RS_SAMPLER_WRAP                 = 3,
     RS_SAMPLER_CLAMP                = 4,
     RS_SAMPLER_LINEAR_MIP_NEAREST   = 5,
+    RS_SAMPLER_MIRRORED_REPEAT      = 6,
 
     RS_SAMPLER_INVALID              = 100,
 } rs_sampler_value;