36 import com.sun.javafx.geom.Point2D;
37 import com.sun.javafx.geom.RectBounds;
38 import com.sun.javafx.geom.Rectangle;
39 import com.sun.javafx.geom.transform.Affine3D;
40 import com.sun.javafx.geom.transform.BaseTransform;
41 import com.sun.javafx.geom.transform.GeneralTransform3D;
42 import com.sun.javafx.geom.transform.NoninvertibleTransformException;
43 import com.sun.prism.CompositeMode;
44 import com.sun.prism.Graphics;
45 import com.sun.prism.GraphicsPipeline;
46 import com.sun.prism.RTTexture;
47 import com.sun.prism.ReadbackGraphics;
48 import com.sun.prism.impl.PrismSettings;
49 import com.sun.scenario.effect.Blend;
50 import com.sun.scenario.effect.Effect;
51 import com.sun.scenario.effect.FilterContext;
52 import com.sun.scenario.effect.ImageData;
53 import com.sun.scenario.effect.impl.prism.PrDrawable;
54 import com.sun.scenario.effect.impl.prism.PrEffectHelper;
55 import com.sun.scenario.effect.impl.prism.PrFilterContext;
56 import static com.sun.javafx.logging.PulseLogger.PULSE_LOGGER;
57 import static com.sun.javafx.logging.PulseLogger.PULSE_LOGGING_ENABLED;
58
59 /**
60 * NGNode is the abstract base class peer of Node, forming
61 * the basis for Prism and Scenario render graphs.
62 * <p>
63 * During synchronization, the FX scene graph will pass down to us
64 * the transform which takes us from local space to parent space, the
65 * content bounds (ie: geom bounds), and the transformed bounds
66 * (ie: boundsInParent), and the clippedBounds. The effect bounds have
67 * already been passed to the Effect peer (if there is one).
68 * <p>
69 * Whenever the transformedBounds of the NGNode are changed, we update
70 * the dirtyBounds, so that the next time we need to accumulate dirty
71 * regions, we will have the information we need to make sure we create
72 * an appropriate dirty region.
73 * <p>
74 * NGNode maintains a single "dirty" flag, which indicates that this
75 * node itself is dirty and must contribute to the dirty region. More
76 * specifically, it indicates that this node is now dirty with respect
1928 return false;
1929 }
1930
1931 /***************************************************************************
1932 * *
1933 * Rendering *
1934 * *
1935 **************************************************************************/
1936
1937 /**
1938 * Render the tree of nodes to the specified G (graphics) object
1939 * descending from this node as the root. This method is designed to avoid
1940 * generated trash as much as possible while descending through the
1941 * render graph while rendering. This is the appropriate method both to
1942 * initiate painting of an entire scene, and for a branch. The NGGroup
1943 * implementation must call this method on each child, not doRender directly.
1944 *
1945 * @param g The graphics object we're rendering to. This must never be null.
1946 */
1947 public final void render(Graphics g) {
1948 if (PULSE_LOGGING_ENABLED) PULSE_LOGGER.renderIncrementCounter("Nodes visited during render");
1949 // Clear the visuals changed flag
1950 clearDirty();
1951 // If it isn't visible, then punt
1952 if (!visible || opacity == 0f) return;
1953
1954 // We know that we are going to render this node, so we call the
1955 // doRender method, which subclasses implement to do the actual
1956 // rendering work.
1957 doRender(g);
1958 }
1959
1960 // This node requires 2D graphics state for rendering
1961 boolean isShape3D() {
1962 return false;
1963 }
1964
1965 /**
1966 * Invoked only by the final render method. Implementations
1967 * of this method should make sure to save & restore the transform state.
1968 */
2047 p = true;
2048 } else {
2049 renderContent(g);
2050 if (PrismSettings.showOverdraw) {
2051 p = this instanceof NGRegion || !(this instanceof NGGroup);
2052 }
2053 }
2054
2055 if (preCullingTurnedOff) {
2056 g.setHasPreCullingBits(true);
2057 }
2058
2059 // restore previous transform state
2060 g.setTransform3D(mxx, mxy, mxz, mxt,
2061 myx, myy, myz, myt,
2062 mzx, mzy, mzz, mzt);
2063
2064 // restore previous depth test state
2065 g.setDepthTest(prevDepthTest);
2066
2067 if (PULSE_LOGGING_ENABLED) PULSE_LOGGER.renderIncrementCounter("Nodes rendered");
2068
2069 // Used for debug purposes. This is not entirely accurate, as it doesn't measure the
2070 // number of times this node drew to the pixels, and in some cases reports a node as
2071 // having been drawn even when it didn't lay down any pixels. We'd need to integrate
2072 // with our shaders or do something much more invasive to get better data here.
2073 if (PrismSettings.showOverdraw) {
2074 if (p) {
2075 painted |= 3 << (g.getClipRectIndex() * 2);
2076 } else {
2077 painted |= 1 << (g.getClipRectIndex() * 2);
2078 }
2079 }
2080 }
2081
2082 /**
2083 * Return true if this node has a blend mode that requires special
2084 * processing.
2085 * Regular nodes can handle null or SRC_OVER just by rendering into
2086 * the existing buffer.
2087 * Groups override this since they must collect their children into
|
36 import com.sun.javafx.geom.Point2D;
37 import com.sun.javafx.geom.RectBounds;
38 import com.sun.javafx.geom.Rectangle;
39 import com.sun.javafx.geom.transform.Affine3D;
40 import com.sun.javafx.geom.transform.BaseTransform;
41 import com.sun.javafx.geom.transform.GeneralTransform3D;
42 import com.sun.javafx.geom.transform.NoninvertibleTransformException;
43 import com.sun.prism.CompositeMode;
44 import com.sun.prism.Graphics;
45 import com.sun.prism.GraphicsPipeline;
46 import com.sun.prism.RTTexture;
47 import com.sun.prism.ReadbackGraphics;
48 import com.sun.prism.impl.PrismSettings;
49 import com.sun.scenario.effect.Blend;
50 import com.sun.scenario.effect.Effect;
51 import com.sun.scenario.effect.FilterContext;
52 import com.sun.scenario.effect.ImageData;
53 import com.sun.scenario.effect.impl.prism.PrDrawable;
54 import com.sun.scenario.effect.impl.prism.PrEffectHelper;
55 import com.sun.scenario.effect.impl.prism.PrFilterContext;
56 import com.sun.javafx.logging.PulseLogger;
57 import static com.sun.javafx.logging.PulseLogger.PULSE_LOGGING_ENABLED;
58
59 /**
60 * NGNode is the abstract base class peer of Node, forming
61 * the basis for Prism and Scenario render graphs.
62 * <p>
63 * During synchronization, the FX scene graph will pass down to us
64 * the transform which takes us from local space to parent space, the
65 * content bounds (ie: geom bounds), and the transformed bounds
66 * (ie: boundsInParent), and the clippedBounds. The effect bounds have
67 * already been passed to the Effect peer (if there is one).
68 * <p>
69 * Whenever the transformedBounds of the NGNode are changed, we update
70 * the dirtyBounds, so that the next time we need to accumulate dirty
71 * regions, we will have the information we need to make sure we create
72 * an appropriate dirty region.
73 * <p>
74 * NGNode maintains a single "dirty" flag, which indicates that this
75 * node itself is dirty and must contribute to the dirty region. More
76 * specifically, it indicates that this node is now dirty with respect
1928 return false;
1929 }
1930
1931 /***************************************************************************
1932 * *
1933 * Rendering *
1934 * *
1935 **************************************************************************/
1936
1937 /**
1938 * Render the tree of nodes to the specified G (graphics) object
1939 * descending from this node as the root. This method is designed to avoid
1940 * generated trash as much as possible while descending through the
1941 * render graph while rendering. This is the appropriate method both to
1942 * initiate painting of an entire scene, and for a branch. The NGGroup
1943 * implementation must call this method on each child, not doRender directly.
1944 *
1945 * @param g The graphics object we're rendering to. This must never be null.
1946 */
1947 public final void render(Graphics g) {
1948 if (PULSE_LOGGING_ENABLED) PulseLogger.incrementCounter("Nodes visited during render");
1949 // Clear the visuals changed flag
1950 clearDirty();
1951 // If it isn't visible, then punt
1952 if (!visible || opacity == 0f) return;
1953
1954 // We know that we are going to render this node, so we call the
1955 // doRender method, which subclasses implement to do the actual
1956 // rendering work.
1957 doRender(g);
1958 }
1959
1960 // This node requires 2D graphics state for rendering
1961 boolean isShape3D() {
1962 return false;
1963 }
1964
1965 /**
1966 * Invoked only by the final render method. Implementations
1967 * of this method should make sure to save & restore the transform state.
1968 */
2047 p = true;
2048 } else {
2049 renderContent(g);
2050 if (PrismSettings.showOverdraw) {
2051 p = this instanceof NGRegion || !(this instanceof NGGroup);
2052 }
2053 }
2054
2055 if (preCullingTurnedOff) {
2056 g.setHasPreCullingBits(true);
2057 }
2058
2059 // restore previous transform state
2060 g.setTransform3D(mxx, mxy, mxz, mxt,
2061 myx, myy, myz, myt,
2062 mzx, mzy, mzz, mzt);
2063
2064 // restore previous depth test state
2065 g.setDepthTest(prevDepthTest);
2066
2067 if (PULSE_LOGGING_ENABLED) PulseLogger.incrementCounter("Nodes rendered");
2068
2069 // Used for debug purposes. This is not entirely accurate, as it doesn't measure the
2070 // number of times this node drew to the pixels, and in some cases reports a node as
2071 // having been drawn even when it didn't lay down any pixels. We'd need to integrate
2072 // with our shaders or do something much more invasive to get better data here.
2073 if (PrismSettings.showOverdraw) {
2074 if (p) {
2075 painted |= 3 << (g.getClipRectIndex() * 2);
2076 } else {
2077 painted |= 1 << (g.getClipRectIndex() * 2);
2078 }
2079 }
2080 }
2081
2082 /**
2083 * Return true if this node has a blend mode that requires special
2084 * processing.
2085 * Regular nodes can handle null or SRC_OVER just by rendering into
2086 * the existing buffer.
2087 * Groups override this since they must collect their children into
|