Adding anisotropic filtering and related samples.

Change-Id: Idb173274417feb5e25bfd64c5e9fa2492a23a17e
diff --git a/RenderScript.h b/RenderScript.h
index 7902b9a..13ae1fb 100644
--- a/RenderScript.h
+++ b/RenderScript.h
@@ -122,7 +122,8 @@
     RS_SAMPLER_MAG_FILTER,
     RS_SAMPLER_WRAP_S,
     RS_SAMPLER_WRAP_T,
-    RS_SAMPLER_WRAP_R
+    RS_SAMPLER_WRAP_R,
+    RS_SAMPLER_ANISO
 };
 
 enum RsSamplerValue {
diff --git a/java/Samples/res/drawable/checker.png b/java/Samples/res/drawable/checker.png
new file mode 100644
index 0000000..b631e1e
--- /dev/null
+++ b/java/Samples/res/drawable/checker.png
Binary files differ
diff --git a/java/Samples/src/com/android/samples/RsRenderStatesRS.java b/java/Samples/src/com/android/samples/RsRenderStatesRS.java
index d4e83d3..a15c4a1 100644
--- a/java/Samples/src/com/android/samples/RsRenderStatesRS.java
+++ b/java/Samples/src/com/android/samples/RsRenderStatesRS.java
@@ -19,11 +19,12 @@
 import java.io.Writer;
 
 import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.renderscript.*;
 import android.renderscript.ProgramStore.DepthFunc;
+import android.renderscript.Sampler.Value;
 import android.util.Log;
-import android.graphics.BitmapFactory;
-import android.graphics.Bitmap;
 
 
 public class RsRenderStatesRS {
@@ -42,7 +43,7 @@
         mOptionsARGB.inScaled = false;
         mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
         mMode = 0;
-        mMaxModes = 8;
+        mMaxModes = 9;
         initRS();
     }
 
@@ -53,6 +54,8 @@
     private Sampler mLinearWrap;
     private Sampler mMipLinearWrap;
     private Sampler mNearestClamp;
+    private Sampler mMipLinearAniso8;
+    private Sampler mMipLinearAniso15;
 
     private ProgramStore mProgStoreBlendNoneDepth;
     private ProgramStore mProgStoreBlendNone;
@@ -74,10 +77,12 @@
 
     private ProgramRaster mCullBack;
     private ProgramRaster mCullFront;
+    private ProgramRaster mCullNone;
 
     private Allocation mTexTorus;
     private Allocation mTexOpaque;
     private Allocation mTexTransparent;
+    private Allocation mTexChecker;
 
     private Allocation mAllocPV;
 
@@ -243,10 +248,12 @@
         mTexTorus = loadTextureRGB(R.drawable.torusmap);
         mTexOpaque = loadTextureRGB(R.drawable.data);
         mTexTransparent = loadTextureARGB(R.drawable.leaf);
+        mTexChecker = loadTextureRGB(R.drawable.checker);
 
         mScript.set_gTexTorus(mTexTorus);
         mScript.set_gTexOpaque(mTexOpaque);
         mScript.set_gTexTransparent(mTexTransparent);
+        mScript.set_gTexChecker(mTexChecker);
     }
 
     private void initFonts() {
@@ -295,18 +302,32 @@
         mNearestClamp = Sampler.CLAMP_NEAREST(mRS);
         mMipLinearWrap = Sampler.WRAP_LINEAR_MIP_LINEAR(mRS);
 
+        bs = new Sampler.Builder(mRS);
+        bs.setMin(Sampler.Value.LINEAR_MIP_LINEAR);
+        bs.setMag(Sampler.Value.LINEAR);
+        bs.setWrapS(Sampler.Value.WRAP);
+        bs.setWrapT(Sampler.Value.WRAP);
+        bs.setAnisotropy(8.0f);
+        mMipLinearAniso8 = bs.create();
+        bs.setAnisotropy(15.0f);
+        mMipLinearAniso15 = bs.create();
+
         mScript.set_gLinearClamp(mLinearClamp);
         mScript.set_gLinearWrap(mLinearWrap);
         mScript.set_gMipLinearWrap(mMipLinearWrap);
+        mScript.set_gMipLinearAniso8(mMipLinearAniso8);
+        mScript.set_gMipLinearAniso15(mMipLinearAniso15);
         mScript.set_gNearestClamp(mNearestClamp);
     }
 
     private void initProgramRaster() {
         mCullBack = ProgramRaster.CULL_BACK(mRS);
         mCullFront = ProgramRaster.CULL_FRONT(mRS);
+        mCullNone = ProgramRaster.CULL_NONE(mRS);
 
         mScript.set_gCullBack(mCullBack);
         mScript.set_gCullFront(mCullFront);
+        mScript.set_gCullNone(mCullNone);
     }
 
     private void initRS() {
diff --git a/java/Samples/src/com/android/samples/rsrenderstates.rs b/java/Samples/src/com/android/samples/rsrenderstates.rs
index 659e1e4..b471504 100644
--- a/java/Samples/src/com/android/samples/rsrenderstates.rs
+++ b/java/Samples/src/com/android/samples/rsrenderstates.rs
@@ -31,6 +31,7 @@
 rs_allocation gTexOpaque;
 rs_allocation gTexTorus;
 rs_allocation gTexTransparent;
+rs_allocation gTexChecker;
 
 rs_mesh gMbyNMesh;
 rs_mesh gTorusMesh;
@@ -47,10 +48,13 @@
 rs_sampler gLinearClamp;
 rs_sampler gLinearWrap;
 rs_sampler gMipLinearWrap;
+rs_sampler gMipLinearAniso8;
+rs_sampler gMipLinearAniso15;
 rs_sampler gNearestClamp;
 
 rs_program_raster gCullBack;
 rs_program_raster gCullFront;
+rs_program_raster gCullNone;
 
 // Custom vertex shader compunents
 VertexShaderConstants *gVSConstants;
@@ -64,11 +68,11 @@
 
 #pragma rs export_var(gProgVertex, gProgFragmentColor, gProgFragmentTexture)
 #pragma rs export_var(gProgStoreBlendNoneDepth, gProgStoreBlendNone, gProgStoreBlendAlpha, gProgStoreBlendAdd)
-#pragma rs export_var(gTexOpaque, gTexTorus, gTexTransparent)
+#pragma rs export_var(gTexOpaque, gTexTorus, gTexTransparent, gTexChecker)
 #pragma rs export_var(gMbyNMesh, gTorusMesh)
 #pragma rs export_var(gFontSans, gFontSerif, gFontSerifBold, gFontSerifItalic, gFontSerifBoldItalic, gFontMono)
-#pragma rs export_var(gLinearClamp, gLinearWrap, gMipLinearWrap, gNearestClamp)
-#pragma rs export_var(gCullBack, gCullFront)
+#pragma rs export_var(gLinearClamp, gLinearWrap, gMipLinearWrap, gMipLinearAniso8, gMipLinearAniso15, gNearestClamp)
+#pragma rs export_var(gCullBack, gCullFront, gCullNone)
 #pragma rs export_var(gVSConstants, gFSConstants, gVSInputs, gProgVertexCustom, gProgFragmentCustom, gProgFragmentMultitex)
 
 //What we are showing
@@ -110,7 +114,7 @@
     rsgBindProgramVertex(gProgVertex);
     // Setup the projectioni matrix
     rs_matrix4x4 proj;
-    rsMatrixLoadOrtho(&proj, 0, rsgGetWidth(), rsgGetHeight(), 0, -1,1);
+    rsMatrixLoadOrtho(&proj, 0, rsgGetWidth(), rsgGetHeight(), 0, -500, 500);
     rsgProgramVertexLoadProjectionMatrix(&proj);
 }
 
@@ -276,14 +280,12 @@
                          startX + width, startY + height, 0, 1.5, 1.5,
                          startX + width, startY, 0, 1.5, 0);
 
-
     rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
     rsgBindFont(gFontMono);
     rsgDrawText("Filtering: linear clamp", 10, 290);
     rsgDrawText("Filtering: linear wrap", 10, 590);
     rsgDrawText("Filtering: nearest clamp", 310, 290);
     rsgDrawText("Filtering: miplinear wrap", 310, 590);
-
 }
 
 float gTorusRotation = 0;
@@ -430,7 +432,7 @@
     rsgBindSampler(gProgFragmentMultitex, 0, gLinearClamp);
     rsgBindSampler(gProgFragmentMultitex, 1, gLinearWrap);
     rsgBindSampler(gProgFragmentMultitex, 2, gLinearClamp);
-    rsgBindTexture(gProgFragmentMultitex, 0, gTexOpaque);
+    rsgBindTexture(gProgFragmentMultitex, 0, gTexChecker);
     rsgBindTexture(gProgFragmentMultitex, 1, gTexTorus);
     rsgBindTexture(gProgFragmentMultitex, 2, gTexTransparent);
 
@@ -446,6 +448,69 @@
     rsgDrawText("Custom shader with multitexturing", 10, 280);
 }
 
+float gAnisoTime = 0.0f;
+uint anisoMode = 0;
+void displayAnisoSample() {
+
+    gAnisoTime += gDt;
+
+    rsgBindProgramVertex(gProgVertex);
+    float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+    rs_matrix4x4 proj;
+    rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f);
+    rsgProgramVertexLoadProjectionMatrix(&proj);
+
+    rs_matrix4x4 matrix;
+    // Fragment shader with texture
+    rsgBindProgramStore(gProgStoreBlendNone);
+    rsgBindProgramFragment(gProgFragmentTexture);
+    rsMatrixLoadTranslate(&matrix, 0.0f, 0.0f, -10.0f);
+    rsMatrixRotate(&matrix, -80, 1.0f, 0.0f, 0.0f);
+    rsgProgramVertexLoadModelMatrix(&matrix);
+
+    rsgBindProgramRaster(gCullNone);
+
+    rsgBindTexture(gProgFragmentTexture, 0, gTexChecker);
+
+    if(gAnisoTime >= 5.0f) {
+        gAnisoTime = 0.0f;
+        anisoMode ++;
+        anisoMode = anisoMode % 3;
+    }
+
+    if(anisoMode == 0) {
+        rsgBindSampler(gProgFragmentTexture, 0, gMipLinearAniso8);
+    }
+    else if(anisoMode == 1) {
+        rsgBindSampler(gProgFragmentTexture, 0, gMipLinearAniso15);
+    }
+    else {
+        rsgBindSampler(gProgFragmentTexture, 0, gMipLinearWrap);
+    }
+
+    float startX = -15;
+    float startY = -15;
+    float width = 30;
+    float height = 30;
+    rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
+                         startX, startY + height, 0, 0, 10,
+                         startX + width, startY + height, 0, 10, 10,
+                         startX + width, startY, 0, 10, 0);
+
+    rsgBindProgramRaster(gCullBack);
+
+    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+    rsgBindFont(gFontMono);
+    if(anisoMode == 0) {
+        rsgDrawText("Anisotropic filtering 8", 10, 40);
+    }
+    else if(anisoMode == 1) {
+        rsgDrawText("Anisotropic filtering 15", 10, 40);
+    }
+    else {
+        rsgDrawText("Miplinear filtering", 10, 40);
+    }
+}
 
 int root(int launchID) {
 
@@ -479,6 +544,9 @@
     case 7:
         displayMultitextureSample();
         break;
+    case 8:
+        displayAnisoSample();
+        break;
     }
 
     return 10;
diff --git a/rs.spec b/rs.spec
index 2b7928f..a4752f4 100644
--- a/rs.spec
+++ b/rs.spec
@@ -288,6 +288,11 @@
 	param RsSamplerValue value
 	}
 
+SamplerSet2 {
+	param RsSamplerParam p
+	param float value
+	}
+
 SamplerCreate {
 	ret RsSampler
 	}
diff --git a/rsAdapter.cpp b/rsAdapter.cpp
index b4ec250..ef69b75 100644
--- a/rsAdapter.cpp
+++ b/rsAdapter.cpp
@@ -183,7 +183,6 @@
 
     uint32_t eSize = mAllocation.get()->getType()->getElementSizeBytes();
     uint32_t lineSize = eSize * w;
-    uint32_t destW = getDimX();
 
     const uint8_t *src = static_cast<const uint8_t *>(data);
     for (uint32_t line=yoff; line < (yoff+h); line++) {
diff --git a/rsAllocation.cpp b/rsAllocation.cpp
index 87c4f2b..0356e4d 100644
--- a/rsAllocation.cpp
+++ b/rsAllocation.cpp
@@ -293,7 +293,6 @@
     }
 
     for (uint32_t line=yoff; line < (yoff+h); line++) {
-        uint8_t * ptr = static_cast<uint8_t *>(mPtr);
         if (mType->getElement()->getHasReferences()) {
             incRefs(src, w);
             decRefs(dst, w);
diff --git a/rsContextHostStub.h b/rsContextHostStub.h
index f30915e..06298e8 100644
--- a/rsContextHostStub.h
+++ b/rsContextHostStub.h
@@ -111,6 +111,9 @@
         bool mLogScripts;
         bool mLogObjects;
         bool mLogShaders;
+        bool mLogShadersAttr;
+        bool mLogShadersUniforms;
+        bool mLogVisual;
     } props;
 
     void dumpDebug() const {    }
@@ -120,6 +123,7 @@
     mutable const ObjectBase * mObjHead;
 
     bool ext_OES_texture_npot() const {return mGL.OES_texture_npot;}
+    float ext_texture_max_aniso() const {return 1.0f;}
     uint32_t getMaxFragmentTextures() const {return mGL.mMaxFragmentTextureImageUnits;}
     uint32_t getMaxFragmentUniformVectors() const {return mGL.mMaxFragmentUniformVectors;}
     uint32_t getMaxVertexUniformVectors() const {return mGL.mMaxVertexUniformVectors;}
diff --git a/rsSampler.cpp b/rsSampler.cpp
index c6a848c..180d78e 100644
--- a/rsSampler.cpp
+++ b/rsSampler.cpp
@@ -44,7 +44,8 @@
                  RsSamplerValue minFilter,
                  RsSamplerValue wrapS,
                  RsSamplerValue wrapT,
-                 RsSamplerValue wrapR) : ObjectBase(rsc)
+                 RsSamplerValue wrapR,
+                 float aniso) : ObjectBase(rsc)
 {
     mAllocFile = __FILE__;
     mAllocLine = __LINE__;
@@ -53,6 +54,7 @@
     mWrapS = wrapS;
     mWrapT = wrapT;
     mWrapR = wrapR;
+    mAniso = aniso;
 }
 
 Sampler::~Sampler()
@@ -93,6 +95,11 @@
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, trans[mWrapT]);
     }
 
+    float anisoValue = rsMin(rsc->ext_texture_max_aniso(), mAniso);
+    if(rsc->ext_texture_max_aniso() > 1.0f) {
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisoValue);
+    }
+
     rsc->checkError("Sampler::setupGL2 tex env");
 }
 
@@ -147,6 +154,7 @@
     ss->mWrapS = RS_SAMPLER_WRAP;
     ss->mWrapT = RS_SAMPLER_WRAP;
     ss->mWrapR = RS_SAMPLER_WRAP;
+    ss->mAniso = 1.0f;
 }
 
 void rsi_SamplerSet(Context *rsc, RsSamplerParam param, RsSamplerValue value)
@@ -169,21 +177,37 @@
     case RS_SAMPLER_WRAP_R:
         ss->mWrapR = value;
         break;
+    default:
+        LOGE("Attempting to set invalid value on sampler");
+        break;
     }
+}
 
+void rsi_SamplerSet2(Context *rsc, RsSamplerParam param, float value)
+{
+    SamplerState * ss = &rsc->mStateSampler;
+
+    switch(param) {
+    case RS_SAMPLER_ANISO:
+        ss->mAniso = value;
+        break;
+    default:
+        LOGE("Attempting to set invalid value on sampler");
+        break;
+    }
 }
 
 RsSampler rsi_SamplerCreate(Context *rsc)
 {
     SamplerState * ss = &rsc->mStateSampler;
 
-
     Sampler * s = new Sampler(rsc,
                               ss->mMagFilter,
                               ss->mMinFilter,
                               ss->mWrapS,
                               ss->mWrapT,
-                              ss->mWrapR);
+                              ss->mWrapR,
+                              ss->mAniso);
     s->incUserRef();
     return s;
 }
diff --git a/rsSampler.h b/rsSampler.h
index 32a8efd..4946355 100644
--- a/rsSampler.h
+++ b/rsSampler.h
@@ -36,7 +36,8 @@
             RsSamplerValue minFilter,
             RsSamplerValue wrapS,
             RsSamplerValue wrapT,
-            RsSamplerValue wrapR);
+            RsSamplerValue wrapR,
+            float aniso = 1.0f);
 
     virtual ~Sampler();
 
@@ -56,6 +57,7 @@
     RsSamplerValue mWrapS;
     RsSamplerValue mWrapT;
     RsSamplerValue mWrapR;
+    float mAniso;
 
     int32_t mBoundSlot;
 
@@ -74,6 +76,7 @@
     RsSamplerValue mWrapS;
     RsSamplerValue mWrapT;
     RsSamplerValue mWrapR;
+    float mAniso;
 
 
     ObjectBaseRef<Sampler> mSamplers[RS_MAX_SAMPLER_SLOT];
diff --git a/rsType.cpp b/rsType.cpp
index 1ee07cd..fc037a3 100644
--- a/rsType.cpp
+++ b/rsType.cpp
@@ -321,8 +321,6 @@
         break;
     }
 
-
-    int32_t arrayNum = dim - RS_DIMENSION_ARRAY_0;
     if ((dim < 0) || (dim > RS_DIMENSION_MAX)) {
         LOGE("rsTypeAdd: Bad dimension");
         //error