1 /*
2  * Copyright (C) 2015 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 android.renderscript.cts.refocus;
18 
19 
20 import android.renderscript.Allocation;
21 import android.renderscript.Element;
22 import android.renderscript.RenderScript;
23 
24 /**
25  * A class that manages the blur kernel matrices of a blending layer that
26  * interface between Java and Render Script. This class will be specialized for
27  * float in f32 package and for byte in u8 package.
28  *
29  */
30 public class KernelDataForRenderScript {
31     /**
32      * A flag to turn on using optimized RenderScript.
33      * False means using original version; true means using the new version.
34      */
35     private static boolean UseNewRS = false;
36 
37     /**
38      * Number of sub-pixels that is used to generate anti-aliased blur kernel
39      * matrix. That is, we divide one pixel into
40      * {@code NUM_SUB_PIXELS * NUM_SUB_PIXELS} sub-pixels to test whether or not a
41      * pixel is in the blur disk.
42      */
43     protected static final int NUM_SUB_PIXELS = 5;
44 
45     /**
46      * The width of the pixels that are used to pad the image boundary to avoid
47      * boundary checking in filtering operation.
48      */
49     private static final int MAX_KERNEL_RADIUS =
50             computeKernelRadiusFromDiskRadius(BlurStack.getMaxDiskRadius());
51 
52     /**
53      * The length of an array that concatenates all (vectorized) kernel matrices.
54      */
55     protected int stackLength;
56 
57     /**
58      * A class automatically generated by Render Script compiler, which contains
59      * required auxiliary information to parse {@code kernelStack}, including the
60      * starting position of each kernel matrix in a memory buffer and the radius
61      * (radius_x,radius_y) of each kernel matrix. The names radius_x and radius_y
62      * follow C++ style because render script is C language.
63      */
64     protected ScriptField_KernelInfo kernelInfo;
65 
66     /**
67      * Java array version of the current kernel info. Used when UseNewRS is true.
68      * 4*m: offset; 4*m + 1: radius_x; 4*m + 2: radius_y
69      */
70     protected float[] infoArray;
71 
72     /**
73      * An allocation used to store global allocation of stack info. Used when UseNewRS is true.
74      */
75     public Allocation infoAllocation;
76 
getNumSubPixels()77     public static int getNumSubPixels() {
78         return NUM_SUB_PIXELS;
79     }
80 
getMaxKernelRadius()81     public static int getMaxKernelRadius() {
82         return MAX_KERNEL_RADIUS;
83     }
84 
setUseNewRS(boolean choice)85     public static void setUseNewRS(boolean choice) {
86         UseNewRS = choice;
87     }
88 
89     /**
90      * Computes the kernel matrix radius from the blur disk radius.
91      *
92      * @param diskRadius blur disk radius
93      * @return kernel matrix radius
94      */
computeKernelRadiusFromDiskRadius(float diskRadius)95     public static int computeKernelRadiusFromDiskRadius(float diskRadius) {
96         return (int) (diskRadius) + 1;
97     }
98 
getKernelInfo()99     public ScriptField_KernelInfo getKernelInfo() {
100         return kernelInfo;
101     }
102 
103     /**
104      * Initializes {@code kernelInfo}.
105      *
106      * @param targetLayer  the index of a target layer
107      * @param blurStack    an instance of {@code BlurStack}
108      * @param renderScript an instance of {@code RenderScript}
109      */
KernelDataForRenderScript(int targetLayer, BlurStack blurStack, RenderScript renderScript)110     protected KernelDataForRenderScript(int targetLayer, BlurStack blurStack,
111                                         RenderScript renderScript) {
112         if (UseNewRS) {
113             // Use the new version of renderscript files.
114             int numDepths = blurStack.getNumDepths(targetLayer);
115             infoAllocation = Allocation.createSized(
116                     renderScript, Element.F32_4(renderScript),
117                     numDepths);
118 
119             infoArray = new float[4 * numDepths];
120             // Generates information for each blur kernel matrix.
121             int offset = 0;
122             for (int m = 0; m < numDepths; ++m) {
123                 int depth = blurStack.getDepth(targetLayer, m);
124                 float diskRadius = blurStack.getDiskRadius(depth);
125                 int kernelRadius = computeKernelRadiusFromDiskRadius(diskRadius);
126 
127                 infoArray[m * 4] = offset;
128                 infoArray[m * 4 + 1] = kernelRadius;
129                 infoArray[m * 4 + 2] = kernelRadius;
130 
131                 // Updates offset variable.
132                 int kernelLength = (2 * kernelRadius + 1) * (2 * kernelRadius + 1);
133                 offset += kernelLength;
134             }
135             infoAllocation.copyFrom(infoArray);
136             stackLength = offset;
137         } else {
138             // Use original version of renderscript files.
139             int numDepths = blurStack.getNumDepths(targetLayer);
140             kernelInfo = new ScriptField_KernelInfo(renderScript, numDepths);
141 
142             // Generates information for each blur kernel matrix.
143             int offset = 0;
144             for (int m = 0; m < numDepths; ++m) {
145                 int depth = blurStack.getDepth(targetLayer, m);
146                 float diskRadius = blurStack.getDiskRadius(depth);
147                 int kernelRadius = computeKernelRadiusFromDiskRadius(diskRadius);
148                 // Sets information for the {@code m}'th kernel matrix.
149                 kernelInfo.set_offset(m, offset, true);
150                 kernelInfo.set_radius_x(m, kernelRadius, true);
151                 kernelInfo.set_radius_y(m, kernelRadius, true);
152                 // Updates offset variable.
153                 int kernelLength = (2 * kernelRadius + 1) * (2 * kernelRadius + 1);
154                 offset += kernelLength;
155             }
156             stackLength = offset;
157         }
158     }
159 }
160