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.javafx.tk.quantum; 27 28 import java.nio.IntBuffer; 29 import com.sun.glass.ui.Pixels; 30 import com.sun.prism.Graphics; 31 import com.sun.prism.GraphicsPipeline; 32 import com.sun.prism.RTTexture; 33 import com.sun.prism.Texture.WrapMode; 34 import com.sun.prism.impl.Disposer; 35 import com.sun.prism.impl.QueuedPixelSource; 36 37 /** 38 * UploadingPainter is used when we need to render into an offscreen buffer. 39 * The PresentingPainter is used when we are rendering to the main screen. 40 */ 41 final class UploadingPainter extends ViewPainter implements Runnable { 42 43 private RTTexture rttexture; 44 // resolveRTT is a temporary render target to "resolve" a msaa render buffer 45 // into a normal color render target. 46 private RTTexture resolveRTT = null; 47 48 private QueuedPixelSource pixelSource = new QueuedPixelSource(true); 49 private float penScale; 50 private volatile float pixScaleFactor = 1.0f; 51 52 UploadingPainter(GlassScene view) { 53 super(view); 54 } 55 56 void disposeRTTexture() { 57 if (rttexture != null) { 58 rttexture.dispose(); 59 rttexture = null; 60 } 61 if (resolveRTT != null) { 62 resolveRTT.dispose(); 63 resolveRTT = null; 64 } 65 } 66 67 public void setPixelScaleFactor(float scale) { 68 pixScaleFactor = scale; 69 } 70 71 @Override 72 public float getPixelScaleFactor() { 73 return pixScaleFactor; 74 } 75 76 @Override public void run() { 77 renderLock.lock(); 78 79 boolean errored = false; 80 try { 81 if (!validateStageGraphics()) { 82 if (QuantumToolkit.verbose) { 83 System.err.println("UploadingPainter: validateStageGraphics failed"); 84 } 85 paintImpl(null); 86 return; 87 } 88 89 if (factory == null) { 90 factory = GraphicsPipeline.getDefaultResourceFactory(); 91 } 92 if (factory == null || !factory.isDeviceReady()) { 93 return; 94 } 95 96 float scale = pixScaleFactor; 97 int bufWidth = Math.round(viewWidth * scale); 98 int bufHeight = Math.round(viewHeight * scale); 99 100 boolean needsReset = (penScale != scale || 101 penWidth != viewWidth || 102 penHeight != viewHeight || 103 rttexture == null); 104 105 if (!needsReset) { 106 rttexture.lock(); 107 if (rttexture.isSurfaceLost()) { 108 rttexture.unlock(); 109 sceneState.getScene().entireSceneNeedsRepaint(); 110 needsReset = true; 111 } 112 } 113 114 if (needsReset) { 115 disposeRTTexture(); 116 rttexture = factory.createRTTexture(bufWidth, bufHeight, WrapMode.CLAMP_NOT_NEEDED, 117 sceneState.isAntiAliasing()); 118 if (rttexture == null) { 119 return; 120 } 121 penScale = scale; 122 penWidth = viewWidth; 123 penHeight = viewHeight; 124 freshBackBuffer = true; 125 } 126 Graphics g = rttexture.createGraphics(); 127 if (g == null) { 128 disposeRTTexture(); 129 sceneState.getScene().entireSceneNeedsRepaint(); 130 return; 131 } 132 g.scale(scale, scale); 133 paintImpl(g); 134 freshBackBuffer = false; 135 136 Pixels pix = pixelSource.getUnusedPixels(bufWidth, bufHeight, scale); 137 IntBuffer bits = (IntBuffer) pix.getPixels(); 138 139 int rawbits[] = rttexture.getPixels(); 140 141 if (rawbits != null) { 142 bits.put(rawbits, 0, bufWidth * bufHeight); 143 } else { 144 RTTexture rtt = rttexture.isAntiAliasing() ? 145 resolveRenderTarget(g) : rttexture; 146 147 if (!rtt.readPixels(bits)) { 148 /* device lost */ 149 sceneState.getScene().entireSceneNeedsRepaint(); 150 disposeRTTexture(); 151 pix = null; 152 } 153 } 154 155 if (rttexture != null) { 156 rttexture.unlock(); 157 } 158 159 if (pix != null) { 160 /* transparent pixels created and ready for upload */ 161 // Copy references, which are volatile, used by upload. Thus 162 // ensure they still exist once event queue is consumed. 163 pixelSource.enqueuePixels(pix); 164 sceneState.uploadPixels(pixelSource); 165 } 166 167 } catch (Throwable th) { 168 errored = true; 169 th.printStackTrace(System.err); 170 } finally { 171 if (rttexture != null && rttexture.isLocked()) { 172 rttexture.unlock(); 173 } 174 if (resolveRTT != null && resolveRTT.isLocked()) { 175 resolveRTT.unlock(); 176 } 177 178 Disposer.cleanUp(); 179 180 sceneState.getScene().setPainting(false); 181 182 if (factory != null) { 183 factory.getTextureResourcePool().freeDisposalRequestedAndCheckResources(errored); 184 } 185 186 renderLock.unlock(); 187 } 188 } 189 190 private RTTexture resolveRenderTarget(Graphics g) { 191 int width = rttexture.getContentWidth(); 192 int height = rttexture.getContentHeight(); 193 if (resolveRTT != null && 194 (resolveRTT.getContentWidth() != width || 195 (resolveRTT.getContentHeight() != height))) 196 { 197 // If msaa rtt is not the same size than resolve buffer, then dispose 198 resolveRTT.dispose(); 199 resolveRTT = null; 200 } 201 if (resolveRTT == null || resolveRTT.isSurfaceLost()) { 202 resolveRTT = g.getResourceFactory().createRTTexture( 203 width, height, 204 WrapMode.CLAMP_NOT_NEEDED, false); 205 } else { 206 resolveRTT.lock(); 207 } 208 g.blit(rttexture, resolveRTT, 0, 0, width, height, 0, 0, width, height); 209 return resolveRTT; 210 } 211 }