xref: /aosp_15_r20/frameworks/rs/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/Filters.java (revision e1eccf28f96817838ad6867f7f39d2351ec11f56)
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 {
init()37     public void init();
prepInit(ScriptGroup.Builder2 b)38     public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b);
getKernelID()39     public Script.KernelID getKernelID();
asyncLaunch(ScriptGroup.Builder2 builder, Object in, Type outputType)40       public ScriptGroup.Closure asyncLaunch(ScriptGroup.Builder2 builder,
41                                               Object in, Type outputType);
forEach(Allocation in, Allocation out)42     public void forEach(Allocation in, Allocation out);
43   }
44 
45     abstract class FilterBase implements FilterInterface {
asyncLaunch(ScriptGroup.Builder2 builder, Object in, Type outputType)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 {
ColorMatrixFilter(RenderScript RS)70     public ColorMatrixFilter(RenderScript RS) { s_mat = new ScriptC_colormatrix_f(RS); }
71 
init()72     public void init() { }
73 
prepInit(ScriptGroup.Builder2 b)74     public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) { /* TODO */ return null; }
75 
getKernelID()76     public Script.KernelID getKernelID() { return s_mat.getKernelID_colormatrix(); }
77 
forEach(Allocation in, Allocation out)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 {
ContrastFilter(RenderScript RS)84     public ContrastFilter(RenderScript RS) { s = new ScriptC_contrast_f(RS); }
85 
init()86     public void init() {}
87 
prepInit(ScriptGroup.Builder2 b)88     public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) { return null; }
89 
getKernelID()90     public Script.KernelID getKernelID() { return s.getKernelID_contrast(); }
91 
forEach(Allocation in, Allocation out)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 {
ExposureFilter(RenderScript RS)98     public ExposureFilter(RenderScript RS) { s = new ScriptC_exposure_f(RS); }
99 
init()100     public void init() {}
101 
prepInit(ScriptGroup.Builder2 b)102     public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) { return null; }
103 
getKernelID()104     public Script.KernelID getKernelID() { return s.getKernelID_exposure(); }
105 
forEach(Allocation in, Allocation out)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 {
FisheyeFilter(RenderScript RS)112     public FisheyeFilter(RenderScript RS) {
113         mRS = RS;
114         s = new ScriptC_fisheye_approx_relaxed_f(RS);
115     }
116 
init()117     public void init() {
118     }
119 
prepInit(ScriptGroup.Builder2 b)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 
getKernelID()125     public Script.KernelID getKernelID() { return s.getKernelID_fisheye(); }
126 
asyncLaunch(ScriptGroup.Builder2 builder, Object in, Type outputType)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 
forEach(Allocation in, Allocation out)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 {
GreyFilter(RenderScript RS)144     public GreyFilter(RenderScript RS) { s = new ScriptC_greyscale_f(RS); }
145 
init()146     public void init() {}
147 
prepInit(ScriptGroup.Builder2 b)148     public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) { return null; }
149 
getKernelID()150     public Script.KernelID getKernelID() { return s.getKernelID_greyscale(); }
151 
forEach(Allocation in, Allocation out)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 {
LevelsFilter(RenderScript RS)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 
setLevels()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 
setSaturation()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 
init()198     public void init() {
199       setSaturation();
200       setLevels();
201     }
202 
prepInit(ScriptGroup.Builder2 b)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 
getKernelID()209     public Script.KernelID getKernelID() { return s.getKernelID_levels_v4(); }
210 
forEach(Allocation in, Allocation out)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 {
ShadowsFilter(RenderScript RS)217     public ShadowsFilter(RenderScript RS) { s = new ScriptC_shadows_f(RS); }
218 
init()219     public void init() { s.invoke_prepareShadows(50.f); }
220 
prepInit(ScriptGroup.Builder2 b)221     public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) {
222       cInit = b.addInvoke(s.getInvokeID_prepareShadows(), 50.f);
223       return cInit;
224     }
225 
getKernelID()226     public Script.KernelID getKernelID() { return s.getKernelID_shadowsKernel(); }
227 
forEach(Allocation in, Allocation out)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 {
VibranceFilter(RenderScript RS)235     public VibranceFilter(RenderScript RS) { s = new ScriptC_vibrance_f(RS); }
236 
init()237     public void init() {}
238 
prepInit(ScriptGroup.Builder2 b)239     public ScriptGroup.Closure prepInit(ScriptGroup.Builder2 b) { return null; }
240 
getKernelID()241     public Script.KernelID getKernelID() { return s.getKernelID_vibranceKernel(); }
242 
forEach(Allocation in, Allocation out)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 {
VignetteFilter(RenderScript RS)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 
init()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 
prepInit(ScriptGroup.Builder2 b)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 
getKernelID()274     public Script.KernelID getKernelID() { return s.getKernelID_vignette(); }
275 
forEach(Allocation in, Allocation out)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 
Filters(int mode, int[] filter)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 
createTest(android.content.res.Resources res)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 
runTest()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