Home | History | Annotate | Download | only in sgtest
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.rs.sgtest;
     18 
     19 import android.renderscript.Allocation;
     20 import android.renderscript.Element;
     21 import android.renderscript.RenderScript;
     22 import android.renderscript.Sampler;
     23 import android.renderscript.Script;
     24 import android.renderscript.Type;
     25 import android.renderscript.Matrix3f;
     26 import android.renderscript.Matrix4f;
     27 import android.renderscript.ScriptGroup;
     28 import android.util.Log;
     29 
     30 import java.lang.reflect.Constructor;
     31 import java.lang.Math;
     32 import java.util.HashMap;
     33 
     34 public class Filters extends TestBase {
     35 
     36   interface FilterInterface {
     37     public void init();
     38     public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b);
     39     public Script.KernelID getKernelID();
     40       public ScriptGroup.Closure asyncLaunch(ScriptGroup.Builder2 builder,
     41                                               Object in, Type outputType);
     42     public void forEach(Allocation in, Allocation out);
     43   }
     44 
     45     abstract class FilterBase implements FilterInterface {
     46         public ScriptGroup.Closure asyncLaunch(ScriptGroup.Builder2 builder,
     47                                                 Object in, Type outputType) {
     48             return builder.addKernel(getKernelID(), outputType, in);
     49         }
     50     }
     51 
     52   /*
     53 
     54     Template for a subclass that implements Filter.
     55 
     56   class Filter implements Filter {
     57     Filter(RenderScript RS) { s = new ScriptC_(RS); }
     58 
     59     void init() {}
     60 
     61     Script.KernelID getKernelID() { return s.getKernelID_(); }
     62 
     63     void forEach(Allocation in, Allocation out) { s.forEach_(in, out); }
     64 
     65     private ScriptC_ s;
     66   }
     67   */
     68 
     69   class ColorMatrixFilter extends FilterBase {
     70     public ColorMatrixFilter(RenderScript RS) { s_mat = new ScriptC_colormatrix_f(RS); }
     71 
     72     public void init() { }
     73 
     74     public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) { /* TODO */ return null; }
     75 
     76     public Script.KernelID getKernelID() { return s_mat.getKernelID_colormatrix(); }
     77 
     78     public void forEach(Allocation in, Allocation out) { s_mat.forEach_colormatrix(in, out); }
     79 
     80     private ScriptC_colormatrix_f s_mat;
     81   }
     82 
     83   class ContrastFilter extends FilterBase {
     84     public ContrastFilter(RenderScript RS) { s = new ScriptC_contrast_f(RS); }
     85 
     86     public void init() {}
     87 
     88     public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) { return null; }
     89 
     90     public Script.KernelID getKernelID() { return s.getKernelID_contrast(); }
     91 
     92     public void forEach(Allocation in, Allocation out) { s.forEach_contrast(in, out); }
     93 
     94     private ScriptC_contrast_f s;
     95   }
     96 
     97   class ExposureFilter extends FilterBase {
     98     public ExposureFilter(RenderScript RS) { s = new ScriptC_exposure_f(RS); }
     99 
    100     public void init() {}
    101 
    102     public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) { return null; }
    103 
    104     public Script.KernelID getKernelID() { return s.getKernelID_exposure(); }
    105 
    106     public void forEach(Allocation in, Allocation out) { s.forEach_exposure(in, out); }
    107 
    108     private ScriptC_exposure_f s;
    109   }
    110 
    111   class FisheyeFilter extends FilterBase {
    112     public FisheyeFilter(RenderScript RS) {
    113         mRS = RS;
    114         s = new ScriptC_fisheye_approx_relaxed_f(RS);
    115     }
    116 
    117     public void init() {
    118     }
    119 
    120     public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) {
    121         return b.addInvoke(s.getInvokeID_init_filter(),
    122                            dimX, dimY, 0.5f, 0.5f, 0.5f, Sampler.CLAMP_LINEAR(mRS));
    123     }
    124 
    125     public Script.KernelID getKernelID() { return s.getKernelID_fisheye(); }
    126 
    127     public ScriptGroup.Closure asyncLaunch(ScriptGroup.Builder2 builder,
    128                                             Object in, Type outputType) {
    129         return builder.addKernel(getKernelID(), outputType,
    130                                  new ScriptGroup.Binding(s.getFieldID_in_alloc(), in));
    131     }
    132 
    133     public void forEach(Allocation in, Allocation out) {
    134         s.set_in_alloc(in);
    135         s.forEach_fisheye(out);
    136     }
    137 
    138       private RenderScript mRS;
    139       private ScriptC_fisheye_approx_relaxed_f s;
    140       private final int dimX=1067, dimY=1600;
    141   }
    142 
    143   class GreyFilter extends FilterBase {
    144     public GreyFilter(RenderScript RS) { s = new ScriptC_greyscale_f(RS); }
    145 
    146     public void init() {}
    147 
    148     public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) { return null; }
    149 
    150     public Script.KernelID getKernelID() { return s.getKernelID_greyscale(); }
    151 
    152     public void forEach(Allocation in, Allocation out) { s.forEach_greyscale(in, out); }
    153 
    154     private ScriptC_greyscale_f s;
    155   }
    156 
    157   class LevelsFilter extends FilterBase {
    158     public LevelsFilter(RenderScript RS) { s = new ScriptC_levels_relaxed_f(RS); }
    159     private final float mSaturation = 1.0f;
    160     private final float mInBlack = 0.0f; // 0-255
    161     private final float mOutBlack = 0.0f; // 0-255
    162     private final float mInWhite = 255.0f; // 0-255
    163     private final float mOutWhite = 255.0f; // 0-255
    164     private final float mInWMinInB = mInWhite - mInBlack;
    165     private final float mOutWMinOutB = mOutWhite - mOutBlack;
    166     private final float mOverInWMinInB = 1.f / mInWMinInB;
    167     private Matrix3f mSatMatrix;
    168 
    169     private void setLevels() {
    170       s.set_inBlack(mInBlack);
    171       s.set_outBlack(mOutBlack);
    172       s.set_inWMinInB(mInWMinInB);
    173       s.set_outWMinOutB(mOutWMinOutB);
    174       s.set_overInWMinInB(mOverInWMinInB);
    175     }
    176 
    177     private void setSaturation() {
    178       Matrix3f satMatrix = new Matrix3f();
    179       float rWeight = 0.299f;
    180       float gWeight = 0.587f;
    181       float bWeight = 0.114f;
    182       float oneMinusS = 1.0f - mSaturation;
    183 
    184       satMatrix.set(0, 0, oneMinusS * rWeight + mSaturation);
    185       satMatrix.set(0, 1, oneMinusS * rWeight);
    186       satMatrix.set(0, 2, oneMinusS * rWeight);
    187       satMatrix.set(1, 0, oneMinusS * gWeight);
    188       satMatrix.set(1, 1, oneMinusS * gWeight + mSaturation);
    189       satMatrix.set(1, 2, oneMinusS * gWeight);
    190       satMatrix.set(2, 0, oneMinusS * bWeight);
    191       satMatrix.set(2, 1, oneMinusS * bWeight);
    192       satMatrix.set(2, 2, oneMinusS * bWeight + mSaturation);
    193       s.set_colorMat(satMatrix);
    194 
    195       mSatMatrix = satMatrix;
    196     }
    197 
    198     public void init() {
    199       setSaturation();
    200       setLevels();
    201     }
    202 
    203     public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) {
    204         return b.addInvoke(s.getInvokeID_initialize(),
    205                            mInBlack, mOutBlack, mInWMinInB, mOutWMinOutB,
    206                            mOverInWMinInB, mSatMatrix);
    207     }
    208 
    209     public Script.KernelID getKernelID() { return s.getKernelID_levels_v4(); }
    210 
    211     public void forEach(Allocation in, Allocation out) { s.forEach_levels_v4(in, out); }
    212 
    213     private ScriptC_levels_relaxed_f s;
    214   }
    215 
    216   class ShadowsFilter extends FilterBase {
    217     public ShadowsFilter(RenderScript RS) { s = new ScriptC_shadows_f(RS); }
    218 
    219     public void init() { s.invoke_prepareShadows(50.f); }
    220 
    221     public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) {
    222       cInit = b.addInvoke(s.getInvokeID_prepareShadows(), 50.f);
    223       return cInit;
    224     }
    225 
    226     public Script.KernelID getKernelID() { return s.getKernelID_shadowsKernel(); }
    227 
    228     public void forEach(Allocation in, Allocation out) { s.forEach_shadowsKernel(in, out); }
    229 
    230     private ScriptC_shadows_f s;
    231     private ScriptGroup.Closure cInit;
    232   }
    233 
    234   class VibranceFilter extends FilterBase {
    235     public VibranceFilter(RenderScript RS) { s = new ScriptC_vibrance_f(RS); }
    236 
    237     public void init() {}
    238 
    239     public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) { return null; }
    240 
    241     public Script.KernelID getKernelID() { return s.getKernelID_vibranceKernel(); }
    242 
    243     public void forEach(Allocation in, Allocation out) { s.forEach_vibranceKernel(in, out); }
    244 
    245     private ScriptC_vibrance_f s;
    246   }
    247 
    248   class VignetteFilter extends FilterBase {
    249     public VignetteFilter(RenderScript RS) { s = new ScriptC_vignette_approx_relaxed_f(RS); }
    250     private final float center_x = 0.5f;
    251     private final float center_y = 0.5f;
    252     private final float scale = 0.5f;
    253     private final float shade = 0.5f;
    254     private final float slope = 20.0f;
    255     private ScriptGroup.Closure cInit;
    256 
    257     public void init() {
    258       s.invoke_init_vignette(
    259           mInPixelsAllocation.getType().getX(),
    260           mInPixelsAllocation.getType().getY(), center_x,
    261           center_y, scale, shade, slope);
    262     }
    263 
    264     public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) {
    265       cInit = b.addInvoke(s.getInvokeID_init_vignette(),
    266             mInPixelsAllocation.getType().getX(),
    267             mInPixelsAllocation.getType().getY(),
    268             center_x,
    269             center_y,
    270             scale, shade, slope);
    271       return cInit;
    272     }
    273 
    274     public Script.KernelID getKernelID() { return s.getKernelID_vignette(); }
    275 
    276     public void forEach(Allocation in, Allocation out) { s.forEach_vignette(in, out); }
    277 
    278     private ScriptC_vignette_approx_relaxed_f s;
    279   }
    280 
    281   public final static Class[] mFilterClasses = {
    282     ColorMatrixFilter.class,
    283     ContrastFilter.class,
    284     ExposureFilter.class,
    285     /* The fisheye filter uses rsSample, which does not work for float4 element
    286        type.
    287     FisheyeFilter.class,
    288     */
    289     GreyFilter.class,
    290     LevelsFilter.class,
    291     ShadowsFilter.class,
    292     VibranceFilter.class,
    293     VignetteFilter.class
    294   };
    295   private FilterInterface[] mFilters;
    296   private int[] mIndices;
    297 
    298   ScriptC_uc4tof4 s_uc2f;
    299   ScriptC_f4touc4 s_f2uc;
    300 
    301   private Allocation[] mScratchPixelsAllocation = new Allocation[2];
    302   private ScriptGroup mGroup;
    303   private ScriptGroup mGroup2;
    304 
    305   private int mWidth;
    306   private int mHeight;
    307   private int mMode;
    308 
    309   public static final int EMULATED = 0;
    310   public static final int NATIVE2 = 1;
    311   public static final int NATIVE1 = 2;
    312   public static final int MANUAL = 3;
    313 
    314   public Filters(int mode, int[] filter) {
    315     mMode = mode;
    316     mIndices = new int[filter.length];
    317     System.arraycopy(filter, 0, mIndices, 0, filter.length);
    318     mFilters = new FilterInterface[filter.length+2];
    319   }
    320 
    321   public void createTest(android.content.res.Resources res) {
    322     s_uc2f = new ScriptC_uc4tof4(mRS);
    323     s_f2uc = new ScriptC_f4touc4(mRS);
    324     for (int i = 0; i < mIndices.length; i++) {
    325       try {
    326         /*
    327         Constructor[] constructors = mFilterClasses[mIndices[i]].getConstructors();
    328         for (Constructor ctr : constructors) {
    329           Log.i("Filters", "constructor " + ctr);
    330         }
    331         */
    332         Constructor constructor =
    333             // mFilterClasses[i].getConstructor(new Class[]{ RenderScript.class });
    334             //mFilterClasses[i].getConstructor(RenderScript.class);
    335             mFilterClasses[mIndices[i]].getConstructors()[0];
    336         try {
    337           mFilters[i] = (FilterInterface)constructor.newInstance(this, mRS);
    338         } catch (Exception e) {
    339           Log.e("Filters", "newInstance caught " + e);
    340           System.exit(-2);
    341         }
    342         mFilters[i].init();
    343       } catch (Exception e) {
    344         Log.e("Filters", "getConstructor caught " + e + " for " +
    345               mFilterClasses[mIndices[i]].getName());
    346         System.exit(-1);
    347       }
    348 
    349     }
    350 
    351     mWidth = mInPixelsAllocation.getType().getX();
    352     mHeight = mInPixelsAllocation.getType().getY();
    353 
    354     Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
    355     tb.setX(mWidth);
    356     tb.setY(mHeight);
    357     Type connect = tb.create();
    358 
    359     switch (mMode) {
    360       case NATIVE1:
    361           ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
    362           b.addKernel(s_uc2f.getKernelID_uc4tof4());
    363           b.addKernel(mFilters[0].getKernelID());
    364           b.addConnection(connect, s_uc2f.getKernelID_uc4tof4(),
    365               mFilters[0].getKernelID());
    366 
    367           for (int i = 0; i < mIndices.length; i++) {
    368             b.addKernel(mFilters[i].getKernelID());
    369             b.addConnection(connect, mFilters[i-1].getKernelID(),
    370                 mFilters[i].getKernelID());
    371           }
    372 
    373           b.addKernel(s_f2uc.getKernelID_f4touc4());
    374           b.addConnection(mOutPixelsAllocation.getType(),
    375               mFilters[0].getKernelID(), s_f2uc.getKernelID_f4touc4());
    376 
    377           mGroup = b.create();
    378           break;
    379       case NATIVE2: {
    380         ScriptGroup.Builder2 b2 = new ScriptGroup.Builder2(mRS);
    381 
    382         for (int i = 0; i < mIndices.length; i++) {
    383           mFilters[i].prepInit(b2);
    384         }
    385 
    386         ScriptGroup.Input in = b2.addInput();
    387 
    388         ScriptGroup.Closure c = b2.addKernel(s_uc2f.getKernelID_uc4tof4(),
    389             connect, in);
    390 
    391         for (int i = 0; i < mIndices.length; i++) {
    392             c = mFilters[i].asyncLaunch(b2, c.getReturn(), connect);
    393         }
    394 
    395         c = b2.addKernel(s_f2uc.getKernelID_f4touc4(),
    396             mOutPixelsAllocation.getType(),
    397             c.getReturn());
    398 
    399         final String name = mFilters[0].getClass().getSimpleName() + "-" +
    400                 mFilters[1].getClass().getSimpleName();
    401         mGroup2 = b2.create(name, c.getReturn());
    402       }
    403         break;
    404       case EMULATED:
    405         mScratchPixelsAllocation[0] = Allocation.createTyped(mRS, connect);
    406         mScratchPixelsAllocation[1] = Allocation.createTyped(mRS, connect);
    407         break;
    408     }
    409   }
    410 
    411     public void runTest() {
    412         switch (mMode) {
    413           case NATIVE1:
    414             // mGroup.setInput(mFilters[0].getKernelID(), mInPixelsAllocation);
    415             mGroup.setInput(s_uc2f.getKernelID_uc4tof4(), mInPixelsAllocation);
    416             // mGroup.setOutput(mFilters[mIndices.length - 1].getKernelID(), mOutPixelsAllocation);
    417             mGroup.setOutput(s_f2uc.getKernelID_f4touc4(), mOutPixelsAllocation);
    418             mGroup.execute();
    419             break;
    420           case NATIVE2:
    421             mOutPixelsAllocation = (Allocation)mGroup2.execute(mInPixelsAllocation)[0];
    422             break;
    423           case EMULATED:
    424             s_uc2f.forEach_uc4tof4(mInPixelsAllocation, mScratchPixelsAllocation[0]);
    425             for (int i = 0; i < mIndices.length; i++) {
    426               mFilters[i].forEach(mScratchPixelsAllocation[i % 2],
    427                   mScratchPixelsAllocation[(i+1) % 2]);
    428             }
    429             s_f2uc.forEach_f4touc4(mScratchPixelsAllocation[mIndices.length % 2],
    430                 mOutPixelsAllocation);
    431             break;
    432         }
    433     }
    434 
    435 }
    436