1 /* 2 * Copyright (c) 2010, 2013, 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.j2d; 27 28 import com.sun.glass.ui.Application; 29 import com.sun.glass.ui.Pixels; 30 import com.sun.glass.ui.Screen; 31 import com.sun.javafx.geom.Rectangle; 32 import com.sun.prism.Graphics; 33 import com.sun.prism.Presentable; 34 import com.sun.prism.PresentableState; 35 import com.sun.prism.ResourceFactory; 36 import com.sun.prism.Texture.WrapMode; 37 import com.sun.prism.impl.PrismSettings; 38 39 import java.awt.Graphics2D; 40 import java.awt.image.BufferedImage; 41 import java.nio.ByteOrder; 42 import java.nio.IntBuffer; 43 import java.util.concurrent.atomic.AtomicInteger; 44 45 public abstract class J2DPresentable implements Presentable { 46 static J2DPresentable create(PresentableState pState, 47 J2DResourceFactory factory) 48 { 49 return new Glass(pState, factory); 50 } 51 52 static J2DPresentable create(BufferedImage buffer, J2DResourceFactory factory) 53 { 54 return new Bimg(buffer, factory); 55 } 56 57 58 private static class Glass extends J2DPresentable { 59 private final PresentableState pState; 60 private final int theFormat; 61 private Pixels pixels; 62 private IntBuffer pixBuf; 63 private final AtomicInteger uploadCount = new AtomicInteger(0); 64 private boolean opaque; 65 66 Glass(PresentableState pState, J2DResourceFactory factory) { 67 super(null, factory); 68 this.pState = pState; 69 this.theFormat = pState.getPixelFormat(); 70 needsResize = true; 71 } 72 73 @Override 74 public BufferedImage createBuffer(int w, int h) { 75 pixels = null; 76 pixBuf = null; 77 if (PrismSettings.verbose) { 78 System.out.println("Glass native format: "+theFormat); 79 } 80 ByteOrder byteorder = ByteOrder.nativeOrder(); 81 switch (theFormat) { 82 case Pixels.Format.BYTE_BGRA_PRE: 83 if (byteorder == ByteOrder.LITTLE_ENDIAN) { 84 return new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE); 85 } else { 86 throw new UnsupportedOperationException("BYTE_BGRA_PRE pixel format on BIG_ENDIAN"); 87 } 88 /* NOTREACHED */ 89 case Pixels.Format.BYTE_ARGB: 90 if (byteorder == ByteOrder.BIG_ENDIAN) { 91 return new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 92 } else { 93 throw new UnsupportedOperationException("BYTE_ARGB pixel format on LITTLE_ENDIAN"); 94 } 95 /* NOTREACHED */ 96 default: 97 throw new UnsupportedOperationException("unrecognized pixel format: "+theFormat); 98 } 99 } 100 101 private final Application app = Application.GetApplication(); 102 103 @Override 104 public boolean lockResources(PresentableState pState) { 105 if (this.pState != pState || this.theFormat != pState.getPixelFormat()) { 106 return true; 107 } 108 needsResize = (buffer == null || 109 buffer.getWidth() != pState.getWidth() || 110 buffer.getHeight() != pState.getHeight()); 111 return false; 112 } 113 114 public boolean prepare(Rectangle dirty) { 115 if (pState.isViewClosed() == false) { 116 /* 117 * RT-27385 118 * TODO: make sure the imgrep matches the Pixels.getNativeFormat() 119 * TODO: dirty region support 120 */ 121 int w = getPhysicalWidth(); 122 int h = getPhysicalHeight(); 123 if (pixels == null || uploadCount.get() > 0) { 124 pixBuf = IntBuffer.allocate(w*h); 125 pixels = Application.GetApplication().createPixels(w, h, pixBuf); 126 } 127 assert ib.hasArray(); 128 System.arraycopy(ib.array(), 0, pixBuf.array(), 0, w*h); 129 return true; 130 } else { 131 return (false); 132 } 133 } 134 135 public boolean present() { 136 uploadCount.incrementAndGet(); 137 pState.uploadPixels(pixels, uploadCount); 138 return true; 139 } 140 141 public int getContentWidth() { 142 return pState.getWidth(); 143 } 144 145 public int getContentHeight() { 146 return pState.getHeight(); 147 } 148 149 public void setOpaque(boolean opaque) { 150 this.opaque = opaque; 151 } 152 153 public boolean isOpaque() { 154 return opaque; 155 } 156 } 157 158 private static class Bimg extends J2DPresentable { 159 private boolean opaque; 160 public Bimg(java.awt.image.BufferedImage buffer, 161 J2DResourceFactory factory) { 162 super(buffer, factory); 163 } 164 165 @Override 166 public BufferedImage createBuffer(int w, int h) { 167 throw new UnsupportedOperationException("cannot create new buffers for image"); 168 } 169 170 @Override 171 public boolean lockResources(PresentableState pState) { 172 return false; 173 } 174 175 public boolean prepare(Rectangle dirtyregion) { 176 throw new UnsupportedOperationException("cannot prepare/present on image"); 177 } 178 179 public boolean present() { 180 throw new UnsupportedOperationException("cannot prepare/present on image"); 181 } 182 183 public int getContentWidth() { 184 return buffer.getWidth(); 185 } 186 187 public int getContentHeight() { 188 return buffer.getHeight(); 189 } 190 191 public void setOpaque(boolean opaque) { 192 this.opaque = opaque; 193 } 194 195 public boolean isOpaque() { 196 return opaque; 197 } 198 } 199 200 J2DResourceFactory factory; 201 boolean needsResize; 202 java.awt.image.BufferedImage buffer; 203 IntBuffer ib; 204 J2DRTTexture readbackBuffer; 205 206 J2DPresentable(java.awt.image.BufferedImage buffer, 207 J2DResourceFactory factory) 208 { 209 this.buffer = buffer; 210 this.factory = factory; 211 } 212 213 ResourceFactory getResourceFactory() { 214 return factory; 215 } 216 217 public abstract BufferedImage createBuffer(int w, int h); 218 219 public Graphics createGraphics() { 220 if (needsResize) { 221 int w = getContentWidth(); 222 int h = getContentHeight(); 223 // TODO: Have Glass Pixels class relax its constraints 224 // so we can use an oversized buffer if we want to... 225 buffer = null; 226 readbackBuffer = null; 227 buffer = createBuffer(w, h); 228 java.awt.image.Raster r = buffer.getRaster(); 229 java.awt.image.DataBuffer db = r.getDataBuffer(); 230 java.awt.image.SinglePixelPackedSampleModel sppsm = 231 (java.awt.image.SinglePixelPackedSampleModel) r.getSampleModel(); 232 int pixels[] = ((java.awt.image.DataBufferInt) db).getData(); 233 ib = IntBuffer.wrap(pixels, db.getOffset(), db.getSize()); 234 needsResize = false; 235 } 236 Graphics2D g2d = (Graphics2D) buffer.getGraphics(); 237 return new J2DPrismGraphics(this, g2d); 238 } 239 240 J2DRTTexture getReadbackBuffer() { 241 if (readbackBuffer == null) { 242 readbackBuffer = (J2DRTTexture) 243 factory.createRTTexture(getContentWidth(), getContentHeight(), 244 WrapMode.CLAMP_NOT_NEEDED); 245 readbackBuffer.makePermanent(); 246 } 247 return readbackBuffer; 248 } 249 250 BufferedImage getBackBuffer() { 251 return buffer; 252 } 253 254 public Screen getAssociatedScreen() { 255 return factory.getScreen(); 256 } 257 258 public int getContentX() { 259 return 0; 260 } 261 262 public int getContentY() { 263 return 0; 264 } 265 266 public float getPixelScaleFactor() { 267 return 1.0f; 268 } 269 270 public int getPhysicalWidth() { 271 // If the buffer has not yet been created (typically that means 272 // createGraphics() has not yet been called), we will plan to 273 // create it at the content size initially. 274 return (buffer == null) ? getContentWidth() : buffer.getWidth(); 275 } 276 277 public int getPhysicalHeight() { 278 // If the buffer has not yet been created (typically that means 279 // createGraphics() has not yet been called), we will plan to 280 // create it at the content size initially. 281 return (buffer == null) ? getContentHeight() : buffer.getHeight(); 282 } 283 284 @Override public boolean isAntiAliasing() { 285 return false; 286 } 287 }