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