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.prism.sw; 27 28 import com.sun.javafx.geom.Path2D; 29 import com.sun.javafx.geom.Rectangle; 30 import com.sun.javafx.geom.Shape; 31 import com.sun.javafx.geom.transform.BaseTransform; 32 import com.sun.marlin.IntArrayCache; 33 import com.sun.marlin.MarlinAlphaConsumer; 34 import com.sun.marlin.MarlinConst; 35 import com.sun.marlin.MarlinRenderer; 36 import com.sun.marlin.MarlinRenderingEngine; 37 import com.sun.marlin.RendererContext; 38 import com.sun.openpisces.Renderer; 39 import com.sun.pisces.PiscesRenderer; 40 import com.sun.prism.BasicStroke; 41 import com.sun.prism.PixelFormat; 42 import com.sun.prism.ResourceFactory; 43 import com.sun.prism.Texture; 44 import com.sun.prism.impl.PrismSettings; 45 import com.sun.prism.impl.shape.MarlinPrismUtils; 46 import com.sun.prism.impl.shape.MaskData; 47 import com.sun.prism.impl.shape.OpenPiscesPrismUtils; 48 import com.sun.prism.impl.shape.ShapeUtil; 49 50 import java.lang.ref.SoftReference; 51 52 final class SWContext { 53 54 private final ResourceFactory factory; 55 private final ShapeRenderer shapeRenderer; 56 private SoftReference<SWRTTexture> readBackBufferRef; 57 private SoftReference<SWArgbPreTexture> imagePaintTextureRef; 58 59 interface ShapeRenderer { 60 void renderShape(PiscesRenderer pr, Shape shape, BasicStroke stroke, BaseTransform tr, Rectangle clip, boolean antialiasedShape); 61 void dispose(); 62 } 63 64 class NativeShapeRenderer implements ShapeRenderer { 160 final int outpix_ymin = renderer.getOutpixMinY(); 161 final int outpix_ymax = renderer.getOutpixMaxY(); 162 final int w = outpix_xmax - outpix_xmin; 163 final int h = outpix_ymax - outpix_ymin; 164 if ((w <= 0) || (h <= 0)) { 165 return; 166 } 167 alphaConsumer.initConsumer(outpix_xmin, outpix_ymin, w, h, pr); 168 renderer.produceAlphas(alphaConsumer); 169 } finally { 170 if (renderer != null) { 171 renderer.dispose(); 172 } 173 // recycle the RendererContext instance 174 MarlinRenderingEngine.returnRendererContext(rdrCtx); 175 } 176 } 177 178 @Override 179 public void dispose() { } 180 181 private static final class DirectRTMarlinAlphaConsumer implements MarlinAlphaConsumer { 182 private byte alpha_map[]; 183 private int x; 184 private int y; 185 private int w; 186 private int h; 187 private int rowNum; 188 189 private PiscesRenderer pr; 190 191 public void initConsumer(int x, int y, int w, int h, PiscesRenderer pr) { 192 this.x = x; 193 this.y = y; 194 this.w = w; 195 this.h = h; 196 rowNum = 0; 197 this.pr = pr; 198 } 199 200 @Override 201 public int getOriginX() { 202 return x; 203 } 204 205 @Override 206 public int getOriginY() { 207 return y; 208 } 209 210 @Override 211 public int getWidth() { 212 return w; 213 } 214 215 @Override 216 public int getHeight() { 217 return h; 218 } 219 220 @Override 221 public void setMaxAlpha(int maxalpha) { 222 if ((alpha_map == null) || (alpha_map.length != maxalpha+1)) { 223 alpha_map = new byte[maxalpha+1]; 224 for (int i = 0; i <= maxalpha; i++) { 225 alpha_map[i] = (byte) ((i*255 + maxalpha/2)/maxalpha); 226 } 227 } 228 } 229 230 @Override 231 public boolean supportBlockFlags() { 232 return false; 233 } 234 235 @Override 236 public void clearAlphas(final int pix_y) { 237 // noop 238 } 239 240 @Override 241 public void setAndClearRelativeAlphas(final int[] alphaDeltas, final int pix_y, 242 final int pix_from, final int pix_to) 243 { 244 // use x instead of pix_from as it cause artefacts: 245 // note: it would be more efficient to skip all those empty pixels [x to pix_from[ 246 // but the native implementation must be fixed too. 247 // pr.emitAndClearAlphaRow(alpha_map, alphaDeltas, pix_y, pix_from, pix_to, rowNum); 248 pr.emitAndClearAlphaRow(alpha_map, alphaDeltas, pix_y, x, pix_to, rowNum); 249 rowNum++; 250 251 // clear properly the end of the alphaDeltas: 252 final int to = pix_to - x; 253 if (to <= w) { 254 alphaDeltas[to] = 0; 255 } else { 256 alphaDeltas[w] = 0; 257 } 258 259 if (MarlinConst.DO_CHECKS) { 260 IntArrayCache.check(alphaDeltas, pix_from - x, to + 1, 0); 261 } 262 } 263 264 @Override 265 public void setAndClearRelativeAlphas(final int[] blkFlags, final int[] alphaDeltas, final int pix_y, 266 final int pix_from, final int pix_to) 267 { 268 throw new UnsupportedOperationException(); 269 } 270 } 271 } 272 273 SWContext(ResourceFactory factory) { 274 this.factory = factory; 275 if (PrismSettings.useMarlinRasterizer) { 276 this.shapeRenderer = new MarlinShapeRenderer(); 277 } else if (PrismSettings.doNativePisces) { 278 this.shapeRenderer = new NativeShapeRenderer(); 279 } else { 280 this.shapeRenderer = new JavaShapeRenderer(); 281 } 282 } 283 284 void renderShape(PiscesRenderer pr, Shape shape, BasicStroke stroke, BaseTransform tr, Rectangle clip, boolean antialiasedShape) { 285 this.shapeRenderer.renderShape(pr, shape, stroke, tr, clip, antialiasedShape); 286 } 287 288 private SWRTTexture initRBBuffer(int width, int height) { 289 final SWRTTexture tex = (SWRTTexture)factory.createRTTexture(width, height, Texture.WrapMode.CLAMP_NOT_NEEDED); 290 readBackBufferRef = new SoftReference<SWRTTexture>(tex); 291 return tex; 292 } 293 294 private void disposeRBBuffer() { 295 if (readBackBufferRef != null) { 296 readBackBufferRef.clear(); | 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.prism.sw; 27 28 import com.sun.javafx.geom.Path2D; 29 import com.sun.javafx.geom.Rectangle; 30 import com.sun.javafx.geom.Shape; 31 import com.sun.javafx.geom.transform.BaseTransform; 32 import com.sun.marlin.DMarlinRenderer; 33 import com.sun.marlin.DMarlinRenderingEngine; 34 import com.sun.marlin.DRendererContext; 35 import com.sun.marlin.IntArrayCache; 36 import com.sun.marlin.MarlinAlphaConsumer; 37 import com.sun.marlin.MarlinConst; 38 import com.sun.marlin.MarlinRenderer; 39 import com.sun.marlin.MarlinRenderingEngine; 40 import com.sun.marlin.RendererContext; 41 import com.sun.openpisces.Renderer; 42 import com.sun.pisces.PiscesRenderer; 43 import com.sun.prism.BasicStroke; 44 import com.sun.prism.PixelFormat; 45 import com.sun.prism.ResourceFactory; 46 import com.sun.prism.Texture; 47 import com.sun.prism.impl.PrismSettings; 48 import com.sun.prism.impl.shape.DMarlinPrismUtils; 49 import com.sun.prism.impl.shape.DMarlinRasterizer; 50 import com.sun.prism.impl.shape.MarlinPrismUtils; 51 import com.sun.prism.impl.shape.MaskData; 52 import com.sun.prism.impl.shape.OpenPiscesPrismUtils; 53 import com.sun.prism.impl.shape.ShapeUtil; 54 55 import java.lang.ref.SoftReference; 56 57 final class SWContext { 58 59 private final ResourceFactory factory; 60 private final ShapeRenderer shapeRenderer; 61 private SoftReference<SWRTTexture> readBackBufferRef; 62 private SoftReference<SWArgbPreTexture> imagePaintTextureRef; 63 64 interface ShapeRenderer { 65 void renderShape(PiscesRenderer pr, Shape shape, BasicStroke stroke, BaseTransform tr, Rectangle clip, boolean antialiasedShape); 66 void dispose(); 67 } 68 69 class NativeShapeRenderer implements ShapeRenderer { 165 final int outpix_ymin = renderer.getOutpixMinY(); 166 final int outpix_ymax = renderer.getOutpixMaxY(); 167 final int w = outpix_xmax - outpix_xmin; 168 final int h = outpix_ymax - outpix_ymin; 169 if ((w <= 0) || (h <= 0)) { 170 return; 171 } 172 alphaConsumer.initConsumer(outpix_xmin, outpix_ymin, w, h, pr); 173 renderer.produceAlphas(alphaConsumer); 174 } finally { 175 if (renderer != null) { 176 renderer.dispose(); 177 } 178 // recycle the RendererContext instance 179 MarlinRenderingEngine.returnRendererContext(rdrCtx); 180 } 181 } 182 183 @Override 184 public void dispose() { } 185 } 186 187 static final class DirectRTMarlinAlphaConsumer implements MarlinAlphaConsumer { 188 private byte alpha_map[]; 189 private int x; 190 private int y; 191 private int w; 192 private int h; 193 private int rowNum; 194 195 private PiscesRenderer pr; 196 197 public void initConsumer(int x, int y, int w, int h, PiscesRenderer pr) { 198 this.x = x; 199 this.y = y; 200 this.w = w; 201 this.h = h; 202 rowNum = 0; 203 this.pr = pr; 204 } 205 206 @Override 207 public int getOriginX() { 208 return x; 209 } 210 211 @Override 212 public int getOriginY() { 213 return y; 214 } 215 216 @Override 217 public int getWidth() { 218 return w; 219 } 220 221 @Override 222 public int getHeight() { 223 return h; 224 } 225 226 @Override 227 public void setMaxAlpha(int maxalpha) { 228 if ((alpha_map == null) || (alpha_map.length != maxalpha+1)) { 229 alpha_map = new byte[maxalpha+1]; 230 for (int i = 0; i <= maxalpha; i++) { 231 alpha_map[i] = (byte) ((i*255 + maxalpha/2)/maxalpha); 232 } 233 } 234 } 235 236 @Override 237 public boolean supportBlockFlags() { 238 return false; 239 } 240 241 @Override 242 public void clearAlphas(final int pix_y) { 243 // noop 244 } 245 246 @Override 247 public void setAndClearRelativeAlphas(final int[] alphaDeltas, final int pix_y, 248 final int pix_from, final int pix_to) 249 { 250 // use x instead of pix_from as it cause artefacts: 251 // note: it would be more efficient to skip all those empty pixels [x to pix_from[ 252 // but the native implementation must be fixed too. 253 // pr.emitAndClearAlphaRow(alpha_map, alphaDeltas, pix_y, pix_from, pix_to, rowNum); 254 pr.emitAndClearAlphaRow(alpha_map, alphaDeltas, pix_y, x, pix_to, rowNum); 255 rowNum++; 256 257 // clear properly the end of the alphaDeltas: 258 final int to = pix_to - x; 259 if (to <= w) { 260 alphaDeltas[to] = 0; 261 } else { 262 alphaDeltas[w] = 0; 263 } 264 265 if (MarlinConst.DO_CHECKS) { 266 IntArrayCache.check(alphaDeltas, pix_from - x, to + 1, 0); 267 } 268 } 269 270 @Override 271 public void setAndClearRelativeAlphas(final int[] blkFlags, final int[] alphaDeltas, final int pix_y, 272 final int pix_from, final int pix_to) 273 { 274 throw new UnsupportedOperationException(); 275 } 276 } 277 278 static final class DMarlinShapeRenderer implements ShapeRenderer { 279 private final DirectRTMarlinAlphaConsumer alphaConsumer = new DirectRTMarlinAlphaConsumer(); 280 281 @Override 282 public void renderShape(PiscesRenderer pr, Shape shape, BasicStroke stroke, BaseTransform tr, Rectangle clip, boolean antialiasedShape) { 283 if (stroke != null && stroke.getType() != BasicStroke.TYPE_CENTERED) { 284 // RT-27427 285 // TODO: Optimize the combinatorial strokes for simple 286 // shapes and/or teach the rasterizer to be able to 287 // do a "differential fill" between two shapes. 288 // Note that most simple shapes will use a more optimized path 289 // than this method for the INNER/OUTER strokes anyway. 290 shape = stroke.createStrokedShape(shape); 291 stroke = null; 292 } 293 final DRendererContext rdrCtx = DMarlinRenderingEngine.getRendererContext(); 294 DMarlinRenderer renderer = null; 295 try { 296 if (shape instanceof Path2D) { 297 renderer = DMarlinPrismUtils.setupRenderer(rdrCtx, (Path2D) shape, stroke, tr, clip, 298 antialiasedShape); 299 } 300 if (renderer == null) { 301 renderer = DMarlinPrismUtils.setupRenderer(rdrCtx, shape, stroke, tr, clip, 302 antialiasedShape); 303 } 304 final int outpix_xmin = renderer.getOutpixMinX(); 305 final int outpix_xmax = renderer.getOutpixMaxX(); 306 final int outpix_ymin = renderer.getOutpixMinY(); 307 final int outpix_ymax = renderer.getOutpixMaxY(); 308 final int w = outpix_xmax - outpix_xmin; 309 final int h = outpix_ymax - outpix_ymin; 310 if ((w <= 0) || (h <= 0)) { 311 return; 312 } 313 alphaConsumer.initConsumer(outpix_xmin, outpix_ymin, w, h, pr); 314 renderer.produceAlphas(alphaConsumer); 315 } finally { 316 if (renderer != null) { 317 renderer.dispose(); 318 } 319 // recycle the RendererContext instance 320 DMarlinRenderingEngine.returnRendererContext(rdrCtx); 321 } 322 } 323 324 @Override 325 public void dispose() { } 326 } 327 328 SWContext(ResourceFactory factory) { 329 this.factory = factory; 330 if (PrismSettings.useMarlinRasterizer) { 331 if (PrismSettings.useMarlinRasterizerDP) { 332 this.shapeRenderer = new DMarlinShapeRenderer(); 333 } else { 334 this.shapeRenderer = new MarlinShapeRenderer(); 335 } 336 } else if (PrismSettings.doNativePisces) { 337 this.shapeRenderer = new NativeShapeRenderer(); 338 } else { 339 this.shapeRenderer = new JavaShapeRenderer(); 340 } 341 } 342 343 void renderShape(PiscesRenderer pr, Shape shape, BasicStroke stroke, BaseTransform tr, Rectangle clip, boolean antialiasedShape) { 344 this.shapeRenderer.renderShape(pr, shape, stroke, tr, clip, antialiasedShape); 345 } 346 347 private SWRTTexture initRBBuffer(int width, int height) { 348 final SWRTTexture tex = (SWRTTexture)factory.createRTTexture(width, height, Texture.WrapMode.CLAMP_NOT_NEEDED); 349 readBackBufferRef = new SoftReference<SWRTTexture>(tex); 350 return tex; 351 } 352 353 private void disposeRBBuffer() { 354 if (readBackBufferRef != null) { 355 readBackBufferRef.clear(); |