| /* |
| * 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; |
| } |
| } |
| |
| } |