1 /* 2 * Copyright (c) 2011, 2014, 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.prism.sw; 27 28 import com.sun.javafx.geom.Rectangle; 29 import com.sun.javafx.geom.Shape; 30 import com.sun.javafx.geom.transform.BaseTransform; 31 import com.sun.openpisces.Renderer; 32 import com.sun.pisces.PiscesRenderer; 33 import com.sun.prism.BasicStroke; 34 import com.sun.prism.PixelFormat; 35 import com.sun.prism.ResourceFactory; 36 import com.sun.prism.Texture; 37 import com.sun.prism.impl.PrismSettings; 38 import com.sun.prism.impl.shape.MaskData; 39 import com.sun.prism.impl.shape.OpenPiscesPrismUtils; 40 import com.sun.prism.impl.shape.ShapeUtil; 41 42 import java.lang.ref.SoftReference; 43 44 final class SWContext { 45 46 private final ResourceFactory factory; 47 private final ShapeRenderer shapeRenderer; 48 private SoftReference<SWRTTexture> readBackBufferRef; 49 private SoftReference<SWArgbPreTexture> imagePaintTextureRef; 50 51 interface ShapeRenderer { 52 void renderShape(PiscesRenderer pr, Shape shape, BasicStroke stroke, BaseTransform tr, Rectangle clip); 53 void dispose(); 54 } 55 56 class NativeShapeRenderer implements ShapeRenderer { 57 private SoftReference<SWMaskTexture> maskTextureRef; 58 59 public void renderShape(PiscesRenderer pr, Shape shape, BasicStroke stroke, BaseTransform tr, Rectangle clip) { 60 final MaskData mask = ShapeUtil.rasterizeShape(shape, stroke, clip.toRectBounds(), tr, true); 61 final SWMaskTexture tex = this.validateMaskTexture(mask.getWidth(), mask.getHeight()); 62 mask.uploadToTexture(tex, 0, 0, false); 63 pr.fillAlphaMask(tex.getDataNoClone(), mask.getOriginX(), mask.getOriginY(), 64 mask.getWidth(), mask.getHeight(), 0, tex.getPhysicalWidth()); 65 } 66 67 private SWMaskTexture initMaskTexture(int width, int height) { 68 final SWMaskTexture tex = (SWMaskTexture)factory.createMaskTexture(width, height, Texture.WrapMode.CLAMP_NOT_NEEDED); 69 maskTextureRef = new SoftReference<SWMaskTexture>(tex); 70 return tex; 71 } 72 73 private void disposeMaskTexture() { 74 if (maskTextureRef != null){ 75 maskTextureRef.clear(); 76 maskTextureRef = null; 77 } 78 } 79 80 private SWMaskTexture validateMaskTexture(int width, int height) { 81 SWMaskTexture tex; 82 if (maskTextureRef == null) { 83 tex = this.initMaskTexture(width, height); 84 } else { 85 tex = maskTextureRef.get(); 86 if (tex == null || 87 tex.getPhysicalWidth() < width || 88 tex.getPhysicalHeight() < height) 89 { 90 this.disposeMaskTexture(); 91 tex = this.initMaskTexture(width, height); 92 } 93 } 94 return tex; 95 } 96 97 public void dispose() { 98 this.disposeMaskTexture(); 99 } 100 } 101 102 class JavaShapeRenderer implements ShapeRenderer { 103 private final DirectRTPiscesAlphaConsumer alphaConsumer = new DirectRTPiscesAlphaConsumer(); 104 105 public void renderShape(PiscesRenderer pr, Shape shape, BasicStroke stroke, BaseTransform tr, Rectangle clip) { 106 if (stroke != null && stroke.getType() != BasicStroke.TYPE_CENTERED) { 107 // RT-27427 108 // TODO: Optimize the combinatorial strokes for simple 109 // shapes and/or teach the rasterizer to be able to 110 // do a "differential fill" between two shapes. 111 // Note that most simple shapes will use a more optimized path 112 // than this method for the INNER/OUTER strokes anyway. 113 shape = stroke.createStrokedShape(shape); 114 stroke = null; 115 } 116 final Renderer r = OpenPiscesPrismUtils.setupRenderer(shape, stroke, tr, clip); 117 alphaConsumer.initConsumer(r, pr); 118 r.produceAlphas(alphaConsumer); 119 } 120 121 public void dispose() { } 122 } 123 124 SWContext(ResourceFactory factory) { 125 this.factory = factory; 126 this.shapeRenderer = (PrismSettings.doNativePisces) ? new NativeShapeRenderer() : new JavaShapeRenderer(); 127 } 128 129 void renderShape(PiscesRenderer pr, Shape shape, BasicStroke stroke, BaseTransform tr, Rectangle clip) { 130 this.shapeRenderer.renderShape(pr, shape, stroke, tr, clip); 131 } 132 133 private SWRTTexture initRBBuffer(int width, int height) { 134 final SWRTTexture tex = (SWRTTexture)factory.createRTTexture(width, height, Texture.WrapMode.CLAMP_NOT_NEEDED); 135 readBackBufferRef = new SoftReference<SWRTTexture>(tex); 136 return tex; 137 } 138 139 private void disposeRBBuffer() { 140 if (readBackBufferRef != null) { 141 readBackBufferRef.clear(); 142 readBackBufferRef = null; 143 } 144 } 145 146 SWRTTexture validateRBBuffer(int width, int height) { 147 SWRTTexture tex; 148 if (readBackBufferRef == null) { 149 tex = this.initRBBuffer(width, height); 150 } else { 151 tex = readBackBufferRef.get(); 152 if (tex == null || 153 tex.getPhysicalWidth() < width || 154 tex.getPhysicalHeight() < height) 155 { 156 this.disposeRBBuffer(); 157 tex = this.initRBBuffer(width, height); 158 } 159 tex.setContentWidth(width); 160 tex.setContentHeight(height); 161 } 162 return tex; 163 } 164 165 private SWArgbPreTexture initImagePaintTexture(int width, int height) { 166 final SWArgbPreTexture tex = (SWArgbPreTexture)factory.createTexture(PixelFormat.INT_ARGB_PRE, 167 Texture.Usage.DEFAULT, Texture.WrapMode.REPEAT, width, height); 168 imagePaintTextureRef = new SoftReference<SWArgbPreTexture>(tex); 169 return tex; 170 } 171 172 private void disposeImagePaintTexture() { 173 if (imagePaintTextureRef != null) { 174 imagePaintTextureRef.clear(); 175 imagePaintTextureRef = null; 176 } 177 } 178 179 SWArgbPreTexture validateImagePaintTexture(int width, int height) { 180 SWArgbPreTexture tex; 181 if (imagePaintTextureRef == null) { 182 tex = this.initImagePaintTexture(width, height); 183 } else { 184 tex = imagePaintTextureRef.get(); 185 if (tex == null || 186 tex.getPhysicalWidth() < width || 187 tex.getPhysicalHeight() < height) 188 { 189 this.disposeImagePaintTexture(); 190 tex = this.initImagePaintTexture(width, height); 191 } 192 tex.setContentWidth(width); 193 tex.setContentHeight(height); 194 } 195 return tex; 196 } 197 198 199 void dispose() { 200 this.disposeRBBuffer(); 201 this.disposeImagePaintTexture(); 202 this.shapeRenderer.dispose(); 203 } 204 }