modules/graphics/src/main/java/com/sun/scenario/effect/impl/state/LinearConvolveKernel.java

Print this page

        

@@ -23,89 +23,20 @@
  * questions.
  */
 
 package com.sun.scenario.effect.impl.state;
 
-import java.nio.FloatBuffer;
 import com.sun.javafx.geom.Rectangle;
 import com.sun.javafx.geom.transform.BaseTransform;
-import com.sun.scenario.effect.Color4f;
-import com.sun.scenario.effect.Effect;
-import com.sun.scenario.effect.FilterContext;
-import com.sun.scenario.effect.ImageData;
-import com.sun.scenario.effect.impl.EffectPeer;
-import com.sun.scenario.effect.impl.Renderer;
 
 /**
  * The helper class for defining a 1 dimensional linear convolution kernel
  * for either the LinearConvolve or LinearConvolveShadow shaders.
  * This class is abstract and must be subclassed for specific linear
  * convolutions.
  */
 public abstract class LinearConvolveKernel {
-    public static final int MAX_KERNEL_SIZE = 128;
-
-    public enum PassType {
-        /**
-         * The kernel on this pass will be applied horizontally with
-         * the kernel centered symmetrically around each pixel.
-         * The specific conditions indicated by this type are:
-         * <ul>
-         * <li>The kernel is an odd size {@code (2*k+1)}
-         * <li>The data for destination pixel {@code (x,y)} is taken from
-         *     pixels {@code x-k,y} through {@code (x+k,y)} with the weights
-         *     applied in that same order.
-         * <li>If the bounds of the source image are {@code (x,y,w,h)} then
-         *     the bounds of the destination will be {@code (x-k,y,w+2*k,h)}.
-         * </ul>
-         */
-        HORIZONTAL_CENTERED,
-
-        /**
-         * The kernel on this pass will be applied vertically with
-         * the kernel centered symmetrically around each pixel.
-         * The specific conditions indicated by this type are:
-         * <ul>
-         * <li>The kernel is an odd size {@code (2*k+1)}
-         * <li>The data for destination pixel {@code (x,y)} is taken from
-         *     pixels {@code x,y-k} through {@code (x,y+k)} with the weights
-         *     applied in that same order.
-         * <li>If the bounds of the source image are {@code (x,y,w,h)} then
-         *     the bounds of the destination will be {@code (x,y-k,w,h+2*k)}.
-         * </ul>
-         */
-        VERTICAL_CENTERED,
-
-        /**
-         * The kernel on this pass can be applied in any direction or with
-         * any kind of offset.
-         * No assumptions are made about the offset and delta of the kernel
-         * vector.
-         */
-        GENERAL_VECTOR,
-    };
-
-    /**
-     * Returns the peer sample count for a given kernel size.  There are
-     * only a few peers defined to operate on specific sizes of convolution
-     * kernel.  If there are peers defined only for kernel sizes of 8 and 16
-     * and a given effect has a linear convolution kernel with 5 weights,
-     * then the peer for size 8 will be used and the buffer of weights must
-     * be padded out to the appropriate size with 0s so that the shader
-     * constant pool will be fully initialized and the extra unneeded
-     * convolution samples will be ignored by the 0 weights.
-     * 
-     * @param ksize the number of computed convolution kernel weights
-     * @return the number of convolution weights which will be applied by
-     *         the associated peer.
-     */
-    public static int getPeerSize(int ksize) {
-        if (ksize < 32) return ((ksize + 3) & (~3));
-        if (ksize <= MAX_KERNEL_SIZE) return ((ksize + 31) & (~31));
-        throw new RuntimeException("No peer available for kernel size: "+ksize);
-    }
-
     /**
      * Returns true if this is a LinearConvolveShadow operation, or false
      * if the operation is a regular LinearConvolve.
      *
      * @return true if this is a Shadow operation

@@ -113,316 +44,34 @@
     public boolean isShadow() {
         return false;
     }
 
     /**
-     * Returns the number of linear convolution passes the algorithm must make
-     * to complete its work.  Most subclasses will use only 1 or 2 passes
-     * (typically broken down into a horizontal pass and a vertical pass as
-     * necessary).
-     *
-     * @return the number of passes to be made
-     */
-    public abstract int getNumberOfPasses();
-
-    /**
      * Returns true if the entire operation of this linear convolution
      * would have no effect on the source data.
      * 
      * @return true if the operation is a NOP
      */
     public boolean isNop() {
         return false;
     }
 
     /**
-     * Returns true if the operation of a particular pass of this linear
-     * convolution would have no effect on the source data.
-     *
-     * @param pass the algorithm pass being performed
-     * @return true if the given pass is a NOP
-     */
-    public boolean isNop(int pass) {
-        return false;
-    }
-
-    /**
-     * Returns the {@link PassType} that indicates the assumptions that
-     * can be made in optimizing the application of the kernel on this
-     * pass.
-     * 
-     * @param pass the algorithm pass being performed
-     * @return the {@link PassType} that describes the kernel vector for
-     *         this pass
-     */
-    public PassType getPassType(int pass) {
-        return PassType.GENERAL_VECTOR;
-    }
-
-    /**
      * Returns the size of the output image needed for a given input
      * image dimensions and a given pass of the algorithm.
      * 
      * @param srcdimension the bounds of the input image
      * @param pass the algorithm pass being performed
      * @return the bounds of the result image
      */
     public abstract Rectangle getResultBounds(Rectangle srcdimension, int pass);
 
     /**
-     * Returns the size of the scaled result image needed to hold the output
-     * for a given input image dimensions and a given pass of the algorithm.
-     * The image may be further scaled after the shader operation is through
-     * to obtain the final result bounds.
-     * This value is only of use to the actual shader to understand exactly
-     * how much room to allocate for the shader result.
-     *
-     * @param srcdimension the bounds of the input image
-     * @param pass the algorithm pass being performed
-     * @return the bounds of the result image
-     */
-    public Rectangle getScaledResultBounds(Rectangle srcdimension, int pass) {
-        return getResultBounds(srcdimension, pass);
-    }
-
-    /**
-     * Returns an array of 4 floats used to initialize a float4 Shader
-     * constant with the relative starting location of the first weight
-     * in the convolution kernel and the incremental offset between each
-     * sample to be weighted and convolved.  The values are stored in
-     * the array in the following order:
-     * <pre>
-     *     shadervec.x = vector[0] = incdx // X offset between subsequent samples
-     *     shadervec.y = vector[1] = incdy // Y offset between subsequent samples
-     *     shadervec.z = vector[2] = startdx // X offset to first convolution sample
-     *     shadervec.w = vector[3] = startdy // Y offset to first convolution sample
-     * </pre>
-     * These values are used in the shader loop as follows:
-     * <pre>
-     *     samplelocation = outputpixellocation.xy + shadervec.zw;
-     *     for (each weight) {
-     *         sum += weight * sample(samplelocation.xy);
-     *         samplelocation.xy += shadervec.xy;
-     *     }
-     *
-     * @param srcnativedimensions the native dimensions (including unused
-     *                            padding) of the input source
-     * @param pass the pass of the algorithm being performed
-     * @return an array of 4 floats representing
-     *         {@code [ incdx, incdy, startdx, startdy ]}
-     */
-    public abstract float[] getVector(Rectangle srcnativedimensions,
-                                      BaseTransform transform, int pass);
-
-    /**
      * Returns the size of the kernel for a given pass.
      *
      * @param pass the pass of the algorithm being performed
      * @return the size of the kernel for the given pass
      */
     public abstract int getKernelSize(int pass);
 
-    /**
-     * Returns the size of the kernel used in the shader for a given pass,
-     * taking into account the scaling specified by the getPow2ScaleXY methods.
-     *
-     * @param pass the pass of the algorithm being performed
-     * @return the size of the kernel for the scaled operation
-     */
-    public int getScaledKernelSize(int pass) {
-        return getKernelSize(pass);
-    }
-
-    /**
-     * Returns the number of power of 2 scales along the X axis.
-     * Positive numbers mean to scale the image larger by the indicated
-     * factors of 2.0.
-     * Negative numbers mean to scale the image smaller by the indicated
-     * factors of 0.5.
-     * Overall the image will be scaled by {@code pow(2.0, getPow2ScaleX())}.
-     * <p>
-     * The kernel specified by the {@link #getWeights()} method will be
-     * relative to the scale factor recommended by this method.
-     * This scaling allows larger kernels to be reduced in size to save
-     * computation if the resolution reduction will not alter the quality
-     * of the convolution (eg. for blur convolutions).
-     *
-     * @return the power of 2.0 by which to scale the source image along the
-     *         X axis.
-     */
-    public int getPow2ScaleX() {
-        return 0;
-    }
-
-    /**
-     * Returns the number of power of 2 scales along the Y axis.
-     * Positive numbers mean to scale the image larger by the indicated
-     * factors of 2.0.
-     * Negative numbers mean to scale the image smaller by the indicated
-     * factors of 0.5.
-     * Overall the image will be scaled by {@code pow(2.0, getPow2ScaleY())}.
-     * <p>
-     * The kernel specified by the {@link #getWeights()} method will be
-     * relative to the scale factor recommended by this method.
-     * This scaling allows larger kernels to be reduced in size to save
-     * computation if the resolution reduction will not alter the quality
-     * of the convolution (eg. for blur convolutions).
-     *
-     * @return the power of 2.0 by which to scale the source image along the
-     *         Y axis.
-     */
-    public int getPow2ScaleY() {
-        return 0;
-    }
-
-    /**
-     * A {@link FloatBuffer} padded out to the required size as specified by
-     * the {@link #getPeerSize()} method.
-     *
-     * @param pass the pass of the algorithm being performed
-     * @return a {@code FloatBuffer} containing the kernel convolution weights
-     */
-    public abstract FloatBuffer getWeights(int pass);
-
-    /**
-     * Returns the maximum number of valid float4 elements that should be
-     * referenced from the buffer returned by getWeights() for the given pass.
-     *
-     * @param pass the pass of the algorithm being performed
-     * @return the maximum number of valid float4 elements in the weights buffer
-     */
-    public int getWeightsArrayLength(int pass) {
-        int ksize = getScaledKernelSize(pass);
-        int psize = getPeerSize(ksize);
-        return psize / 4;
-    }
-
-    final static float[] BLACK_COMPONENTS =
-        Color4f.BLACK.getPremultipliedRGBComponents();
-
-    /**
-     * Returns the color components to be used for a linearly convolved shadow.
-     * Only the LinearConvolveShadow shader uses this method.  State
-     * subclasses that are only intended to be used with the LinearConvolve
-     * shader do not need to override this method.
-     *
-     * @param pass the pass of the algorithm being performed
-     * @return the color components for the shadow color for the given pass
-     */
-    public float[] getShadowColorComponents(int pass) {
-        return BLACK_COMPONENTS;
-    }
-
-    public EffectPeer getPeer(Renderer r, FilterContext fctx, int pass) {
-        if (isNop(pass)) {
-            return null;
-        }
-        int ksize = getScaledKernelSize(pass);
-        int psize = getPeerSize(ksize);
-        String opname = isShadow() ? "LinearConvolveShadow" : "LinearConvolve";
-        return r.getPeerInstance(fctx, opname, psize);
-    }
-
-    public Rectangle transform(Rectangle clip,
-                               int xpow2scales, int ypow2scales)
-    {
-        // Modeled after Renderer.transform(fctx, img, hscale, vscale)
-        if (clip == null || (xpow2scales | ypow2scales) == 0) {
-            return clip;
-        }
-        clip = new Rectangle(clip);
-        if (xpow2scales < 0) {
-            xpow2scales = -xpow2scales;
-            clip.width = (clip.width + (1 << xpow2scales) - 1) >> xpow2scales;
-            clip.x >>= xpow2scales;
-        } else if (xpow2scales > 0) {
-            clip.width = clip.width << xpow2scales;
-            clip.x <<= xpow2scales;
-        }
-        if (ypow2scales < 0) {
-            ypow2scales = -ypow2scales;
-            clip.height = (clip.height + (1 << ypow2scales) - 1) >> ypow2scales;
-            clip.y >>= ypow2scales;
-        } else if (ypow2scales > 0) {
-            clip.height = clip.height << ypow2scales;
-            clip.y <<= ypow2scales;
-        }
-        return clip;
-    }
-
-    public ImageData filterImageDatas(Effect effect,
-                                      FilterContext fctx,
-                                      BaseTransform transform,
-                                      Rectangle outputClip,
-                                      ImageData... inputs)
-    {
-        ImageData src = inputs[0];
-        src.addref();
-        if (isNop()) {
-            return src;
-        }
-        Rectangle approxBounds = inputs[0].getUntransformedBounds();
-        int approxW = approxBounds.width;
-        int approxH = approxBounds.height;
-        Renderer r = Renderer.getRenderer(fctx, effect, approxW, approxH);
-        EffectPeer peer0 = getPeer(r, fctx, 0);
-        EffectPeer peer1 = getPeer(r, fctx, 1);
-        int hscale = 0;
-        int vscale = 0;
-        if (peer0 instanceof LinearConvolvePeer) {
-            hscale = ((LinearConvolvePeer) peer0).getPow2ScaleX(this);
-        }
-        if (peer1 instanceof LinearConvolvePeer) {
-            vscale = ((LinearConvolvePeer) peer1).getPow2ScaleY(this);
-        }
-        Rectangle filterClip = outputClip;
-        if ((hscale | vscale) != 0) {
-            src = r.transform(fctx, src, hscale, vscale);
-            if (!src.validate(fctx)) {
-                src.unref();
-                return src;
-            }
-            filterClip = transform(outputClip, hscale, vscale);
-        }
-        if (filterClip != null) {
-            // The inputClip was already grown by the padding when the
-            // inputs were filtered, but now we need to make sure that
-            // the peers pass out padded results from the already padded
-            // input data, so we grow the clip here by the size of the
-            // scaled kernel padding.
-            int hgrow = getScaledKernelSize(0) / 2;
-            int vgrow = getScaledKernelSize(1) / 2;
-            if ((hgrow | vgrow) != 0) {
-                if (filterClip == outputClip) {
-                    filterClip = new Rectangle(outputClip);
-                }
-                filterClip.grow(hgrow, vgrow);
-            }
-        }
-        if (peer0 != null) {
-            peer0.setPass(0);
-            ImageData res = peer0.filter(effect, transform, filterClip, src);
-            src.unref();
-            src = res;
-            if (!src.validate(fctx)) {
-                src.unref();
-                return src;
-            }
-        }
-
-        if (peer1 != null) {
-            peer1.setPass(1);
-            ImageData res = peer1.filter(effect, transform, filterClip, src);
-            src.unref();
-            src = res;
-            if (!src.validate(fctx)) {
-                src.unref();
-                return src;
-            }
-        }
-
-        if ((hscale | vscale) != 0) {
-            src = r.transform(fctx, src, -hscale, -vscale);
-        }
-        return src;
-    }
+    public abstract LinearConvolveRenderState getRenderState(BaseTransform filtertx);
 }