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