blob: d0d0e408533e75c7c5e2c16338f260db05d5f3cf [file] [log] [blame]
/*
* Copyright (C) 2012 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.rs.sgtest;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.Sampler;
import android.renderscript.Script;
import android.renderscript.Type;
import android.renderscript.Matrix3f;
import android.renderscript.Matrix4f;
import android.renderscript.ScriptGroup;
import android.util.Log;
import java.lang.reflect.Constructor;
import java.lang.Math;
import java.util.HashMap;
public class Filters extends TestBase {
interface FilterInterface {
public void init();
public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b);
public Script.KernelID getKernelID();
public ScriptGroup.Closure asyncLaunch(ScriptGroup.Builder2 builder,
Object in, Type outputType);
public void forEach(Allocation in, Allocation out);
}
abstract class FilterBase implements FilterInterface {
public ScriptGroup.Closure asyncLaunch(ScriptGroup.Builder2 builder,
Object in, Type outputType) {
return builder.addKernel(getKernelID(), outputType, in);
}
}
/*
Template for a subclass that implements Filter.
class Filter implements Filter {
Filter(RenderScript RS) { s = new ScriptC_(RS); }
void init() {}
Script.KernelID getKernelID() { return s.getKernelID_(); }
void forEach(Allocation in, Allocation out) { s.forEach_(in, out); }
private ScriptC_ s;
}
*/
class ColorMatrixFilter extends FilterBase {
public ColorMatrixFilter(RenderScript RS) { s_mat = new ScriptC_colormatrix_f(RS); }
public void init() { }
public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) { /* TODO */ return null; }
public Script.KernelID getKernelID() { return s_mat.getKernelID_colormatrix(); }
public void forEach(Allocation in, Allocation out) { s_mat.forEach_colormatrix(in, out); }
private ScriptC_colormatrix_f s_mat;
}
class ContrastFilter extends FilterBase {
public ContrastFilter(RenderScript RS) { s = new ScriptC_contrast_f(RS); }
public void init() {}
public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) { return null; }
public Script.KernelID getKernelID() { return s.getKernelID_contrast(); }
public void forEach(Allocation in, Allocation out) { s.forEach_contrast(in, out); }
private ScriptC_contrast_f s;
}
class ExposureFilter extends FilterBase {
public ExposureFilter(RenderScript RS) { s = new ScriptC_exposure_f(RS); }
public void init() {}
public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) { return null; }
public Script.KernelID getKernelID() { return s.getKernelID_exposure(); }
public void forEach(Allocation in, Allocation out) { s.forEach_exposure(in, out); }
private ScriptC_exposure_f s;
}
class FisheyeFilter extends FilterBase {
public FisheyeFilter(RenderScript RS) {
mRS = RS;
s = new ScriptC_fisheye_approx_relaxed_f(RS);
}
public void init() {
}
public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) {
return b.addInvoke(s.getInvokeID_init_filter(),
dimX, dimY, 0.5f, 0.5f, 0.5f, Sampler.CLAMP_LINEAR(mRS));
}
public Script.KernelID getKernelID() { return s.getKernelID_fisheye(); }
public ScriptGroup.Closure asyncLaunch(ScriptGroup.Builder2 builder,
Object in, Type outputType) {
return builder.addKernel(getKernelID(), outputType,
new ScriptGroup.Binding(s.getFieldID_in_alloc(), in));
}
public void forEach(Allocation in, Allocation out) {
s.set_in_alloc(in);
s.forEach_fisheye(out);
}
private RenderScript mRS;
private ScriptC_fisheye_approx_relaxed_f s;
private final int dimX=1067, dimY=1600;
}
class GreyFilter extends FilterBase {
public GreyFilter(RenderScript RS) { s = new ScriptC_greyscale_f(RS); }
public void init() {}
public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) { return null; }
public Script.KernelID getKernelID() { return s.getKernelID_greyscale(); }
public void forEach(Allocation in, Allocation out) { s.forEach_greyscale(in, out); }
private ScriptC_greyscale_f s;
}
class LevelsFilter extends FilterBase {
public LevelsFilter(RenderScript RS) { s = new ScriptC_levels_relaxed_f(RS); }
private final float mSaturation = 1.0f;
private final float mInBlack = 0.0f; // 0-255
private final float mOutBlack = 0.0f; // 0-255
private final float mInWhite = 255.0f; // 0-255
private final float mOutWhite = 255.0f; // 0-255
private final float mInWMinInB = mInWhite - mInBlack;
private final float mOutWMinOutB = mOutWhite - mOutBlack;
private final float mOverInWMinInB = 1.f / mInWMinInB;
private Matrix3f mSatMatrix;
private void setLevels() {
s.set_inBlack(mInBlack);
s.set_outBlack(mOutBlack);
s.set_inWMinInB(mInWMinInB);
s.set_outWMinOutB(mOutWMinOutB);
s.set_overInWMinInB(mOverInWMinInB);
}
private void setSaturation() {
Matrix3f satMatrix = new Matrix3f();
float rWeight = 0.299f;
float gWeight = 0.587f;
float bWeight = 0.114f;
float oneMinusS = 1.0f - mSaturation;
satMatrix.set(0, 0, oneMinusS * rWeight + mSaturation);
satMatrix.set(0, 1, oneMinusS * rWeight);
satMatrix.set(0, 2, oneMinusS * rWeight);
satMatrix.set(1, 0, oneMinusS * gWeight);
satMatrix.set(1, 1, oneMinusS * gWeight + mSaturation);
satMatrix.set(1, 2, oneMinusS * gWeight);
satMatrix.set(2, 0, oneMinusS * bWeight);
satMatrix.set(2, 1, oneMinusS * bWeight);
satMatrix.set(2, 2, oneMinusS * bWeight + mSaturation);
s.set_colorMat(satMatrix);
mSatMatrix = satMatrix;
}
public void init() {
setSaturation();
setLevels();
}
public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) {
return b.addInvoke(s.getInvokeID_initialize(),
mInBlack, mOutBlack, mInWMinInB, mOutWMinOutB,
mOverInWMinInB, mSatMatrix);
}
public Script.KernelID getKernelID() { return s.getKernelID_levels_v4(); }
public void forEach(Allocation in, Allocation out) { s.forEach_levels_v4(in, out); }
private ScriptC_levels_relaxed_f s;
}
class ShadowsFilter extends FilterBase {
public ShadowsFilter(RenderScript RS) { s = new ScriptC_shadows_f(RS); }
public void init() { s.invoke_prepareShadows(50.f); }
public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) {
cInit = b.addInvoke(s.getInvokeID_prepareShadows(), 50.f);
return cInit;
}
public Script.KernelID getKernelID() { return s.getKernelID_shadowsKernel(); }
public void forEach(Allocation in, Allocation out) { s.forEach_shadowsKernel(in, out); }
private ScriptC_shadows_f s;
private ScriptGroup.Closure cInit;
}
class VibranceFilter extends FilterBase {
public VibranceFilter(RenderScript RS) { s = new ScriptC_vibrance_f(RS); }
public void init() {}
public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) { return null; }
public Script.KernelID getKernelID() { return s.getKernelID_vibranceKernel(); }
public void forEach(Allocation in, Allocation out) { s.forEach_vibranceKernel(in, out); }
private ScriptC_vibrance_f s;
}
class VignetteFilter extends FilterBase {
public VignetteFilter(RenderScript RS) { s = new ScriptC_vignette_approx_relaxed_f(RS); }
private final float center_x = 0.5f;
private final float center_y = 0.5f;
private final float scale = 0.5f;
private final float shade = 0.5f;
private final float slope = 20.0f;
private ScriptGroup.Closure cInit;
public void init() {
s.invoke_init_vignette(
mInPixelsAllocation.getType().getX(),
mInPixelsAllocation.getType().getY(), center_x,
center_y, scale, shade, slope);
}
public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) {
cInit = b.addInvoke(s.getInvokeID_init_vignette(),
mInPixelsAllocation.getType().getX(),
mInPixelsAllocation.getType().getY(),
center_x,
center_y,
scale, shade, slope);
return cInit;
}
public Script.KernelID getKernelID() { return s.getKernelID_vignette(); }
public void forEach(Allocation in, Allocation out) { s.forEach_vignette(in, out); }
private ScriptC_vignette_approx_relaxed_f s;
}
public final static Class[] mFilterClasses = {
ColorMatrixFilter.class,
ContrastFilter.class,
ExposureFilter.class,
/* The fisheye filter uses rsSample, which does not work for float4 element
type.
FisheyeFilter.class,
*/
GreyFilter.class,
LevelsFilter.class,
ShadowsFilter.class,
VibranceFilter.class,
VignetteFilter.class
};
private FilterInterface[] mFilters;
private int[] mIndices;
ScriptC_uc4tof4 s_uc2f;
ScriptC_f4touc4 s_f2uc;
private Allocation[] mScratchPixelsAllocation = new Allocation[2];
private ScriptGroup mGroup;
private ScriptGroup mGroup2;
private int mWidth;
private int mHeight;
private int mMode;
public static final int EMULATED = 0;
public static final int NATIVE2 = 1;
public static final int NATIVE1 = 2;
public static final int MANUAL = 3;
public Filters(int mode, int[] filter) {
mMode = mode;
mIndices = new int[filter.length];
System.arraycopy(filter, 0, mIndices, 0, filter.length);
mFilters = new FilterInterface[filter.length+2];
}
public void createTest(android.content.res.Resources res) {
s_uc2f = new ScriptC_uc4tof4(mRS);
s_f2uc = new ScriptC_f4touc4(mRS);
for (int i = 0; i < mIndices.length; i++) {
try {
/*
Constructor[] constructors = mFilterClasses[mIndices[i]].getConstructors();
for (Constructor ctr : constructors) {
Log.i("Filters", "constructor " + ctr);
}
*/
Constructor constructor =
// mFilterClasses[i].getConstructor(new Class[]{ RenderScript.class });
//mFilterClasses[i].getConstructor(RenderScript.class);
mFilterClasses[mIndices[i]].getConstructors()[0];
try {
mFilters[i] = (FilterInterface)constructor.newInstance(this, mRS);
} catch (Exception e) {
Log.e("Filters", "newInstance caught " + e);
System.exit(-2);
}
mFilters[i].init();
} catch (Exception e) {
Log.e("Filters", "getConstructor caught " + e + " for " +
mFilterClasses[mIndices[i]].getName());
System.exit(-1);
}
}
mWidth = mInPixelsAllocation.getType().getX();
mHeight = mInPixelsAllocation.getType().getY();
Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
tb.setX(mWidth);
tb.setY(mHeight);
Type connect = tb.create();
switch (mMode) {
case NATIVE1:
ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
b.addKernel(s_uc2f.getKernelID_uc4tof4());
b.addKernel(mFilters[0].getKernelID());
b.addConnection(connect, s_uc2f.getKernelID_uc4tof4(),
mFilters[0].getKernelID());
for (int i = 0; i < mIndices.length; i++) {
b.addKernel(mFilters[i].getKernelID());
b.addConnection(connect, mFilters[i-1].getKernelID(),
mFilters[i].getKernelID());
}
b.addKernel(s_f2uc.getKernelID_f4touc4());
b.addConnection(mOutPixelsAllocation.getType(),
mFilters[0].getKernelID(), s_f2uc.getKernelID_f4touc4());
mGroup = b.create();
break;
case NATIVE2: {
ScriptGroup.Builder2 b2 = new ScriptGroup.Builder2(mRS);
for (int i = 0; i < mIndices.length; i++) {
mFilters[i].prepInit(b2);
}
ScriptGroup.Input in = b2.addInput();
ScriptGroup.Closure c = b2.addKernel(s_uc2f.getKernelID_uc4tof4(),
connect, in);
for (int i = 0; i < mIndices.length; i++) {
c = mFilters[i].asyncLaunch(b2, c.getReturn(), connect);
}
c = b2.addKernel(s_f2uc.getKernelID_f4touc4(),
mOutPixelsAllocation.getType(),
c.getReturn());
final String name = mFilters[0].getClass().getSimpleName() + "-" +
mFilters[1].getClass().getSimpleName();
mGroup2 = b2.create(name, c.getReturn());
}
break;
case EMULATED:
mScratchPixelsAllocation[0] = Allocation.createTyped(mRS, connect);
mScratchPixelsAllocation[1] = Allocation.createTyped(mRS, connect);
break;
}
}
public void runTest() {
switch (mMode) {
case NATIVE1:
// mGroup.setInput(mFilters[0].getKernelID(), mInPixelsAllocation);
mGroup.setInput(s_uc2f.getKernelID_uc4tof4(), mInPixelsAllocation);
// mGroup.setOutput(mFilters[mIndices.length - 1].getKernelID(), mOutPixelsAllocation);
mGroup.setOutput(s_f2uc.getKernelID_f4touc4(), mOutPixelsAllocation);
mGroup.execute();
break;
case NATIVE2:
mOutPixelsAllocation = (Allocation)mGroup2.execute(mInPixelsAllocation)[0];
break;
case EMULATED:
s_uc2f.forEach_uc4tof4(mInPixelsAllocation, mScratchPixelsAllocation[0]);
for (int i = 0; i < mIndices.length; i++) {
mFilters[i].forEach(mScratchPixelsAllocation[i % 2],
mScratchPixelsAllocation[(i+1) % 2]);
}
s_f2uc.forEach_f4touc4(mScratchPixelsAllocation[mIndices.length % 2],
mOutPixelsAllocation);
break;
}
}
}