1 /*
   2  * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.scenario.effect;
  27 
  28 import com.sun.scenario.effect.impl.EffectPeer;
  29 import com.sun.scenario.effect.impl.Renderer;
  30 import com.sun.javafx.geom.Rectangle;
  31 import com.sun.javafx.geom.transform.BaseTransform;
  32 import com.sun.scenario.effect.impl.state.RenderState;
  33 
  34 /**
  35  * Package-private base class for built-in effects, i.e., those that are
  36  * backed by an EffectPeer implementation.
  37  */
  38 abstract class CoreEffect<T extends RenderState> extends FilterEffect<T> {
  39 
  40     private String peerKey;
  41     private int peerCount = -1;
  42 
  43     CoreEffect() {
  44         super();
  45     }
  46 
  47     CoreEffect(Effect input) {
  48         super(input);
  49     }
  50 
  51     CoreEffect(Effect input1, Effect input2) {
  52         super(input1, input2);
  53     }
  54 
  55     final void updatePeerKey(String key) {
  56         updatePeerKey(key, -1);
  57     }
  58 
  59     final void updatePeerKey(String key, int unrollCount) {
  60         this.peerKey = key;
  61         this.peerCount = unrollCount;
  62     }
  63 
  64     private EffectPeer getPeer(FilterContext fctx, int approxW, int approxH) {
  65         return Renderer.getRenderer(fctx, this, approxW, approxH).
  66             getPeerInstance(fctx, peerKey, peerCount);
  67     }
  68 
  69     /**
  70      * Returns an {@code EffectPeer} that is most optimal for the size
  71      * of the operation, which is inferred from the given inputs.
  72      * For example, smaller operations may run faster in software (by
  73      * avoiding high overhead of shader-based operations) so here we choose
  74      * an appropriate Renderer/EffectPeer combination based on the
  75      * dimensions of the first input.
  76      */
  77     final EffectPeer getPeer(FilterContext fctx, ImageData[] inputs) {
  78         // RT-27395
  79         // TODO: we would be much better off using getResultBounds() here
  80         // to infer the size of the operation since some effects (e.g. Flood)
  81         // do not have any inputs to consult...
  82         int approxW, approxH;
  83         if (inputs.length > 0) {
  84             Rectangle approxBounds = inputs[0].getUntransformedBounds();
  85             approxW = approxBounds.width;
  86             approxH = approxBounds.height;
  87         } else {
  88             // NOTE: temporary hack until we start using result bounds
  89             // (see comment above)...
  90             approxW = approxH = 500;
  91         }
  92         return getPeer(fctx, approxW, approxH);
  93     }
  94 
  95     /**
  96      * Convenience method that sends the given input data through the
  97      * current peer, and then attempts to release the input image data.
  98      */
  99     @Override
 100     public ImageData filterImageDatas(FilterContext fctx,
 101                                       BaseTransform transform,
 102                                       Rectangle outputClip,
 103                                       T rstate,
 104                                       ImageData... inputs)
 105     {
 106         return getPeer(fctx, inputs).filter(this, rstate, transform, outputClip, inputs);
 107     }
 108 
 109     @Override
 110     public AccelType getAccelType(FilterContext fctx) {
 111         // We choose relatively large (yet arbitrary) values for approxW/H
 112         // here so that we get the AccelType for the "ideal" case where
 113         // hardware acceleration is used.
 114         EffectPeer peer = getPeer(fctx, 1024, 1024);
 115         return peer.getAccelType();
 116     }
 117 }