--- old/modules/javafx.graphics/src/main/java/com/sun/prism/sw/SWContext.java 2016-11-30 22:45:23.502404836 +0100 +++ new/modules/javafx.graphics/src/main/java/com/sun/prism/sw/SWContext.java 2016-11-30 22:45:23.274404819 +0100 @@ -29,6 +29,9 @@ import com.sun.javafx.geom.Rectangle; import com.sun.javafx.geom.Shape; import com.sun.javafx.geom.transform.BaseTransform; +import com.sun.marlin.DMarlinRenderer; +import com.sun.marlin.DMarlinRenderingEngine; +import com.sun.marlin.DRendererContext; import com.sun.marlin.IntArrayCache; import com.sun.marlin.MarlinAlphaConsumer; import com.sun.marlin.MarlinConst; @@ -42,6 +45,8 @@ import com.sun.prism.ResourceFactory; import com.sun.prism.Texture; import com.sun.prism.impl.PrismSettings; +import com.sun.prism.impl.shape.DMarlinPrismUtils; +import com.sun.prism.impl.shape.DMarlinRasterizer; import com.sun.prism.impl.shape.MarlinPrismUtils; import com.sun.prism.impl.shape.MaskData; import com.sun.prism.impl.shape.OpenPiscesPrismUtils; @@ -177,103 +182,157 @@ @Override public void dispose() { } + } - private static final class DirectRTMarlinAlphaConsumer implements MarlinAlphaConsumer { - private byte alpha_map[]; - private int x; - private int y; - private int w; - private int h; - private int rowNum; + static final class DirectRTMarlinAlphaConsumer implements MarlinAlphaConsumer { + private byte alpha_map[]; + private int x; + private int y; + private int w; + private int h; + private int rowNum; + + private PiscesRenderer pr; + + public void initConsumer(int x, int y, int w, int h, PiscesRenderer pr) { + this.x = x; + this.y = y; + this.w = w; + this.h = h; + rowNum = 0; + this.pr = pr; + } - private PiscesRenderer pr; + @Override + public int getOriginX() { + return x; + } - public void initConsumer(int x, int y, int w, int h, PiscesRenderer pr) { - this.x = x; - this.y = y; - this.w = w; - this.h = h; - rowNum = 0; - this.pr = pr; - } + @Override + public int getOriginY() { + return y; + } - @Override - public int getOriginX() { - return x; - } + @Override + public int getWidth() { + return w; + } - @Override - public int getOriginY() { - return y; - } + @Override + public int getHeight() { + return h; + } - @Override - public int getWidth() { - return w; + @Override + public void setMaxAlpha(int maxalpha) { + if ((alpha_map == null) || (alpha_map.length != maxalpha+1)) { + alpha_map = new byte[maxalpha+1]; + for (int i = 0; i <= maxalpha; i++) { + alpha_map[i] = (byte) ((i*255 + maxalpha/2)/maxalpha); + } } + } - @Override - public int getHeight() { - return h; - } + @Override + public boolean supportBlockFlags() { + return false; + } - @Override - public void setMaxAlpha(int maxalpha) { - if ((alpha_map == null) || (alpha_map.length != maxalpha+1)) { - alpha_map = new byte[maxalpha+1]; - for (int i = 0; i <= maxalpha; i++) { - alpha_map[i] = (byte) ((i*255 + maxalpha/2)/maxalpha); - } - } - } + @Override + public void clearAlphas(final int pix_y) { + // noop + } + + @Override + public void setAndClearRelativeAlphas(final int[] alphaDeltas, final int pix_y, + final int pix_from, final int pix_to) + { + // use x instead of pix_from as it cause artefacts: + // note: it would be more efficient to skip all those empty pixels [x to pix_from[ + // but the native implementation must be fixed too. +// pr.emitAndClearAlphaRow(alpha_map, alphaDeltas, pix_y, pix_from, pix_to, rowNum); + pr.emitAndClearAlphaRow(alpha_map, alphaDeltas, pix_y, x, pix_to, rowNum); + rowNum++; - @Override - public boolean supportBlockFlags() { - return false; + // clear properly the end of the alphaDeltas: + final int to = pix_to - x; + if (to <= w) { + alphaDeltas[to] = 0; + } else { + alphaDeltas[w] = 0; } - @Override - public void clearAlphas(final int pix_y) { - // noop + if (MarlinConst.DO_CHECKS) { + IntArrayCache.check(alphaDeltas, pix_from - x, to + 1, 0); } + } - @Override - public void setAndClearRelativeAlphas(final int[] alphaDeltas, final int pix_y, - final int pix_from, final int pix_to) - { - // use x instead of pix_from as it cause artefacts: - // note: it would be more efficient to skip all those empty pixels [x to pix_from[ - // but the native implementation must be fixed too. -// pr.emitAndClearAlphaRow(alpha_map, alphaDeltas, pix_y, pix_from, pix_to, rowNum); - pr.emitAndClearAlphaRow(alpha_map, alphaDeltas, pix_y, x, pix_to, rowNum); - rowNum++; + @Override + public void setAndClearRelativeAlphas(final int[] blkFlags, final int[] alphaDeltas, final int pix_y, + final int pix_from, final int pix_to) + { + throw new UnsupportedOperationException(); + } + } - // clear properly the end of the alphaDeltas: - final int to = pix_to - x; - if (to <= w) { - alphaDeltas[to] = 0; - } else { - alphaDeltas[w] = 0; - } + static final class DMarlinShapeRenderer implements ShapeRenderer { + private final DirectRTMarlinAlphaConsumer alphaConsumer = new DirectRTMarlinAlphaConsumer(); - if (MarlinConst.DO_CHECKS) { - IntArrayCache.check(alphaDeltas, pix_from - x, to + 1, 0); - } + @Override + public void renderShape(PiscesRenderer pr, Shape shape, BasicStroke stroke, BaseTransform tr, Rectangle clip, boolean antialiasedShape) { + if (stroke != null && stroke.getType() != BasicStroke.TYPE_CENTERED) { + // RT-27427 + // TODO: Optimize the combinatorial strokes for simple + // shapes and/or teach the rasterizer to be able to + // do a "differential fill" between two shapes. + // Note that most simple shapes will use a more optimized path + // than this method for the INNER/OUTER strokes anyway. + shape = stroke.createStrokedShape(shape); + stroke = null; } - - @Override - public void setAndClearRelativeAlphas(final int[] blkFlags, final int[] alphaDeltas, final int pix_y, - final int pix_from, final int pix_to) - { - throw new UnsupportedOperationException(); + final DRendererContext rdrCtx = DMarlinRenderingEngine.getRendererContext(); + DMarlinRenderer renderer = null; + try { + if (shape instanceof Path2D) { + renderer = DMarlinPrismUtils.setupRenderer(rdrCtx, (Path2D) shape, stroke, tr, clip, + antialiasedShape); + } + if (renderer == null) { + renderer = DMarlinPrismUtils.setupRenderer(rdrCtx, shape, stroke, tr, clip, + antialiasedShape); + } + final int outpix_xmin = renderer.getOutpixMinX(); + final int outpix_xmax = renderer.getOutpixMaxX(); + final int outpix_ymin = renderer.getOutpixMinY(); + final int outpix_ymax = renderer.getOutpixMaxY(); + final int w = outpix_xmax - outpix_xmin; + final int h = outpix_ymax - outpix_ymin; + if ((w <= 0) || (h <= 0)) { + return; + } + alphaConsumer.initConsumer(outpix_xmin, outpix_ymin, w, h, pr); + renderer.produceAlphas(alphaConsumer); + } finally { + if (renderer != null) { + renderer.dispose(); + } + // recycle the RendererContext instance + DMarlinRenderingEngine.returnRendererContext(rdrCtx); } } + + @Override + public void dispose() { } } SWContext(ResourceFactory factory) { this.factory = factory; if (PrismSettings.useMarlinRasterizer) { - this.shapeRenderer = new MarlinShapeRenderer(); + if (PrismSettings.useMarlinRasterizerDP) { + this.shapeRenderer = new DMarlinShapeRenderer(); + } else { + this.shapeRenderer = new MarlinShapeRenderer(); + } } else if (PrismSettings.doNativePisces) { this.shapeRenderer = new NativeShapeRenderer(); } else {