package com.android.rs.refocus; import android.support.v8.renderscript.RenderScript; import android.support.v8.renderscript.Allocation; import android.support.v8.renderscript.Element; import com.android.rs.refocus.renderscript.ScriptField_KernelInfo; /** * A class that manages the blur kernel matrices of a blending layer that * interface between Java and Render Script. This class will be specialized for * float in f32 package and for byte in u8 package. * * @author zhl@google.com (Li Zhang) */ public class KernelDataForRenderScript { /** * A flag to turn on using optimized RenderScript. * False means using original version; true means using the new version. */ private static boolean UseNewRS = false; /** * Number of sub-pixels that is used to generate anti-aliased blur kernel * matrix. That is, we divide one pixel into * {@code NUM_SUB_PIXELS * NUM_SUB_PIXELS} sub-pixels to test whether or not a * pixel is in the blur disk. */ protected static final int NUM_SUB_PIXELS = 5; /** * The width of the pixels that are used to pad the image boundary to avoid * boundary checking in filtering operation. */ private static final int MAX_KERNEL_RADIUS = computeKernelRadiusFromDiskRadius(BlurStack.getMaxDiskRadius()); /** * The length of an array that concatenates all (vectorized) kernel matrices. */ protected int stackLength; /** * A class automatically generated by Render Script compiler, which contains * required auxiliary information to parse {@code kernelStack}, including the * starting position of each kernel matrix in a memory buffer and the radius * (radius_x,radius_y) of each kernel matrix. The names radius_x and radius_y * follow C++ style because render script is C language. */ protected ScriptField_KernelInfo kernelInfo; /** Java array version of the current kernel info. Used when UseNewRS is true. * 4*m: offset; 4*m + 1: radius_x; 4*m + 2: radius_y */ protected float[] infoArray; /** An allocation used to store global allocation of stack info. Used when UseNewRS is true. * */ public Allocation infoAllocation; public static int getNumSubPixels() { return NUM_SUB_PIXELS; } public static int getMaxKernelRadius() { return MAX_KERNEL_RADIUS; } public static void setUseNewRS(boolean choice) {UseNewRS = choice;} /** * Computes the kernel matrix radius from the blur disk radius. * * @param diskRadius blur disk radius * @return kernel matrix radius */ public static int computeKernelRadiusFromDiskRadius(float diskRadius) { return (int) (diskRadius) + 1; } public ScriptField_KernelInfo getKernelInfo() { return kernelInfo; } /** * Initializes {@code kernelInfo}. * * @param targetLayer the index of a target layer * @param blurStack an instance of {@code BlurStack} * @param renderScript an instance of {@code RenderScript} */ protected KernelDataForRenderScript(int targetLayer, BlurStack blurStack, RenderScript renderScript) { if (UseNewRS) { // Use the new version of renderscript files. int numDepths = blurStack.getNumDepths(targetLayer); infoAllocation = Allocation.createSized( renderScript, Element.F32_4(renderScript), numDepths); infoArray = new float[4*numDepths]; // Generates information for each blur kernel matrix. int offset = 0; for (int m = 0; m < numDepths; ++m) { int depth = blurStack.getDepth(targetLayer, m); float diskRadius = blurStack.getDiskRadius(depth); int kernelRadius = computeKernelRadiusFromDiskRadius(diskRadius); infoArray[m*4] = offset; infoArray[m*4 + 1] = kernelRadius; infoArray[m*4 + 2] = kernelRadius; // Updates offset variable. int kernelLength = (2 * kernelRadius + 1) * (2 * kernelRadius + 1); offset += kernelLength; } infoAllocation.copyFrom(infoArray); stackLength = offset; } else { // Use original version of renderscript files. int numDepths = blurStack.getNumDepths(targetLayer); kernelInfo = new ScriptField_KernelInfo(renderScript, numDepths); // Generates information for each blur kernel matrix. int offset = 0; for (int m = 0; m < numDepths; ++m) { int depth = blurStack.getDepth(targetLayer, m); float diskRadius = blurStack.getDiskRadius(depth); int kernelRadius = computeKernelRadiusFromDiskRadius(diskRadius); // Sets information for the {@code m}'th kernel matrix. kernelInfo.set_offset(m, offset, true); kernelInfo.set_radius_x(m, kernelRadius, true); kernelInfo.set_radius_y(m, kernelRadius, true); // Updates offset variable. int kernelLength = (2 * kernelRadius + 1) * (2 * kernelRadius + 1); offset += kernelLength; } stackLength = offset; } } }