1 /* 2 * Copyright (c) 2011, 2015, 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 sun.java2d.opengl; 27 28 import java.awt.Graphics; 29 import java.awt.GraphicsConfiguration; 30 import java.awt.GraphicsDevice; 31 import java.awt.GraphicsEnvironment; 32 import java.awt.Image; 33 import java.awt.Rectangle; 34 import java.awt.image.ColorModel; 35 36 import sun.java2d.SunGraphics2D; 37 import sun.java2d.SurfaceData; 38 39 import sun.lwawt.macosx.CPlatformView; 40 41 public abstract class CGLSurfaceData extends OGLSurfaceData { 42 43 protected final int scale; 44 protected final int width; 45 protected final int height; 46 protected CPlatformView pView; 47 private CGLGraphicsConfig graphicsConfig; 48 49 native void validate(int xoff, int yoff, int width, int height, boolean isOpaque); 50 51 private native void initOps(long pConfigInfo, long pPeerData, long layerPtr, 52 int xoff, int yoff, boolean isOpaque); 53 54 protected CGLSurfaceData(CGLGraphicsConfig gc, ColorModel cm, int type, 55 int width, int height) { 56 super(gc, cm, type); 57 // TEXTURE shouldn't be scaled, it is used for managed BufferedImages. 58 scale = type == TEXTURE ? 1 : gc.getDevice().getScaleFactor(); 59 this.width = width * scale; 60 this.height = height * scale; 61 } 62 63 protected CGLSurfaceData(CPlatformView pView, CGLGraphicsConfig gc, 64 ColorModel cm, int type,int width, int height) 65 { 66 this(gc, cm, type, width, height); 67 this.pView = pView; 68 this.graphicsConfig = gc; 69 70 long pConfigInfo = gc.getNativeConfigInfo(); 71 long pPeerData = 0L; 72 boolean isOpaque = true; 73 if (pView != null) { 74 pPeerData = pView.getAWTView(); 75 isOpaque = pView.isOpaque(); 76 } 77 initOps(pConfigInfo, pPeerData, 0, 0, 0, isOpaque); 78 } 79 80 protected CGLSurfaceData(CGLLayer layer, CGLGraphicsConfig gc, 81 ColorModel cm, int type,int width, int height) 82 { 83 this(gc, cm, type, width, height); 84 this.graphicsConfig = gc; 85 86 long pConfigInfo = gc.getNativeConfigInfo(); 87 long layerPtr = 0L; 88 boolean isOpaque = true; 89 if (layer != null) { 90 layerPtr = layer.getPointer(); 91 isOpaque = layer.isOpaque(); 92 } 93 initOps(pConfigInfo, 0, layerPtr, 0, 0, isOpaque); 94 } 95 96 @Override //SurfaceData 97 public GraphicsConfiguration getDeviceConfiguration() { 98 return graphicsConfig; 99 } 100 101 /** 102 * Creates a SurfaceData object representing the primary (front) buffer of 103 * an on-screen Window. 104 */ 105 public static CGLWindowSurfaceData createData(CPlatformView pView) { 106 CGLGraphicsConfig gc = getGC(pView); 107 return new CGLWindowSurfaceData(pView, gc); 108 } 109 110 /** 111 * Creates a SurfaceData object representing the intermediate buffer 112 * between the Java2D flusher thread and the AppKit thread. 113 */ 114 public static CGLLayerSurfaceData createData(CGLLayer layer) { 115 CGLGraphicsConfig gc = getGC(layer); 116 Rectangle r = layer.getBounds(); 117 return new CGLLayerSurfaceData(layer, gc, r.width, r.height); 118 } 119 120 /** 121 * Creates a SurfaceData object representing the back buffer of a 122 * double-buffered on-screen Window. 123 */ 124 public static CGLOffScreenSurfaceData createData(CPlatformView pView, 125 Image image, int type) { 126 CGLGraphicsConfig gc = getGC(pView); 127 Rectangle r = pView.getBounds(); 128 if (type == FLIP_BACKBUFFER) { 129 return new CGLOffScreenSurfaceData(pView, gc, r.width, r.height, 130 image, gc.getColorModel(), FLIP_BACKBUFFER); 131 } else { 132 return new CGLVSyncOffScreenSurfaceData(pView, gc, r.width, 133 r.height, image, gc.getColorModel(), type); 134 } 135 } 136 137 /** 138 * Creates a SurfaceData object representing an off-screen buffer (either a 139 * FBO or Texture). 140 */ 141 public static CGLOffScreenSurfaceData createData(CGLGraphicsConfig gc, 142 int width, int height, ColorModel cm, Image image, int type) { 143 return new CGLOffScreenSurfaceData(null, gc, width, height, image, cm, 144 type); 145 } 146 147 public static CGLGraphicsConfig getGC(CPlatformView pView) { 148 if (pView != null) { 149 return (CGLGraphicsConfig)pView.getGraphicsConfiguration(); 150 } else { 151 // REMIND: this should rarely (never?) happen, but what if 152 // default config is not CGL? 153 GraphicsEnvironment env = GraphicsEnvironment 154 .getLocalGraphicsEnvironment(); 155 GraphicsDevice gd = env.getDefaultScreenDevice(); 156 return (CGLGraphicsConfig) gd.getDefaultConfiguration(); 157 } 158 } 159 160 public static CGLGraphicsConfig getGC(CGLLayer layer) { 161 return (CGLGraphicsConfig)layer.getGraphicsConfiguration(); 162 } 163 164 public void validate() { 165 // Overridden in CGLWindowSurfaceData below 166 } 167 168 @Override 169 public int getDefaultScale() { 170 return scale; 171 } 172 173 @Override 174 public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, 175 int dx, int dy) { 176 final int state = sg2d.transformState; 177 if (state > SunGraphics2D.TRANSFORM_TRANSLATESCALE 178 || sg2d.compositeState >= SunGraphics2D.COMP_XOR) { 179 return false; 180 } 181 if (state <= SunGraphics2D.TRANSFORM_ANY_TRANSLATE) { 182 x += sg2d.transX; 183 y += sg2d.transY; 184 } else if (state == SunGraphics2D.TRANSFORM_TRANSLATESCALE) { 185 final double[] coords = {x, y, x + w, y + h, x + dx, y + dy}; 186 sg2d.transform.transform(coords, 0, coords, 0, 3); 187 x = (int) Math.ceil(coords[0] - 0.5); 188 y = (int) Math.ceil(coords[1] - 0.5); 189 w = ((int) Math.ceil(coords[2] - 0.5)) - x; 190 h = ((int) Math.ceil(coords[3] - 0.5)) - y; 191 dx = ((int) Math.ceil(coords[4] - 0.5)) - x; 192 dy = ((int) Math.ceil(coords[5] - 0.5)) - y; 193 } 194 oglRenderPipe.copyArea(sg2d, x, y, w, h, dx, dy); 195 return true; 196 } 197 198 protected native void clearWindow(); 199 200 public static class CGLWindowSurfaceData extends CGLSurfaceData { 201 202 public CGLWindowSurfaceData(CPlatformView pView, 203 CGLGraphicsConfig gc) { 204 super(pView, gc, gc.getColorModel(), WINDOW, 0, 0); 205 } 206 207 @Override 208 public SurfaceData getReplacement() { 209 return pView.getSurfaceData(); 210 } 211 212 @Override 213 public Rectangle getBounds() { 214 Rectangle r = pView.getBounds(); 215 return new Rectangle(0, 0, r.width, r.height); 216 } 217 218 /** 219 * Returns destination Component associated with this SurfaceData. 220 */ 221 @Override 222 public Object getDestination() { 223 return pView.getDestination(); 224 } 225 226 public void validate() { 227 OGLRenderQueue rq = OGLRenderQueue.getInstance(); 228 rq.lock(); 229 try { 230 rq.flushAndInvokeNow(new Runnable() { 231 public void run() { 232 Rectangle peerBounds = pView.getBounds(); 233 validate(0, 0, peerBounds.width, peerBounds.height, pView.isOpaque()); 234 } 235 }); 236 } finally { 237 rq.unlock(); 238 } 239 } 240 241 @Override 242 public void invalidate() { 243 super.invalidate(); 244 clearWindow(); 245 } 246 } 247 248 /** 249 * A surface which implements an intermediate buffer between 250 * the Java2D flusher thread and the AppKit thread. 251 * 252 * This surface serves as a buffer attached to a CGLLayer and 253 * the layer redirects all painting to the buffer's graphics. 254 */ 255 public static class CGLLayerSurfaceData extends CGLSurfaceData { 256 257 private CGLLayer layer; 258 259 public CGLLayerSurfaceData(CGLLayer layer, CGLGraphicsConfig gc, 260 int width, int height) { 261 super(layer, gc, gc.getColorModel(), FBOBJECT, width, height); 262 this.layer = layer; 263 initSurface(this.width, this.height); 264 } 265 266 @Override 267 public SurfaceData getReplacement() { 268 return layer.getSurfaceData(); 269 } 270 271 @Override 272 boolean isOnScreen() { 273 return true; 274 } 275 276 @Override 277 public Rectangle getBounds() { 278 return new Rectangle(width, height); 279 } 280 281 @Override 282 public Object getDestination() { 283 return layer.getDestination(); 284 } 285 286 @Override 287 public int getTransparency() { 288 return layer.getTransparency(); 289 } 290 291 @Override 292 public void invalidate() { 293 super.invalidate(); 294 clearWindow(); 295 } 296 } 297 298 /** 299 * A surface which implements a v-synced flip back-buffer with COPIED 300 * FlipContents. 301 * 302 * This surface serves as a back-buffer to the outside world, while it is 303 * actually an offscreen surface. When the BufferStrategy this surface 304 * belongs to is showed, it is first copied to the real private 305 * FLIP_BACKBUFFER, which is then flipped. 306 */ 307 public static class CGLVSyncOffScreenSurfaceData extends 308 CGLOffScreenSurfaceData { 309 private CGLOffScreenSurfaceData flipSurface; 310 311 public CGLVSyncOffScreenSurfaceData(CPlatformView pView, 312 CGLGraphicsConfig gc, int width, int height, Image image, 313 ColorModel cm, int type) { 314 super(pView, gc, width, height, image, cm, type); 315 flipSurface = CGLSurfaceData.createData(pView, image, 316 FLIP_BACKBUFFER); 317 } 318 319 public SurfaceData getFlipSurface() { 320 return flipSurface; 321 } 322 323 @Override 324 public void flush() { 325 flipSurface.flush(); 326 super.flush(); 327 } 328 } 329 330 public static class CGLOffScreenSurfaceData extends CGLSurfaceData { 331 private Image offscreenImage; 332 333 public CGLOffScreenSurfaceData(CPlatformView pView, 334 CGLGraphicsConfig gc, int width, int height, Image image, 335 ColorModel cm, int type) { 336 super(pView, gc, cm, type, width, height); 337 offscreenImage = image; 338 initSurface(this.width, this.height); 339 } 340 341 @Override 342 public SurfaceData getReplacement() { 343 return restoreContents(offscreenImage); 344 } 345 346 @Override 347 public Rectangle getBounds() { 348 if (type == FLIP_BACKBUFFER) { 349 Rectangle r = pView.getBounds(); 350 return new Rectangle(0, 0, r.width, r.height); 351 } else { 352 return new Rectangle(width, height); 353 } 354 } 355 356 /** 357 * Returns destination Image associated with this SurfaceData. 358 */ 359 @Override 360 public Object getDestination() { 361 return offscreenImage; 362 } 363 } 364 365 // Mac OS X specific APIs for JOGL/Java2D bridge... 366 367 // given a surface create and attach GL context, then return it 368 private native static long createCGLContextOnSurface(CGLSurfaceData sd, 369 long sharedContext); 370 371 public static long createOGLContextOnSurface(Graphics g, long sharedContext) { 372 SurfaceData sd = ((SunGraphics2D) g).surfaceData; 373 if ((sd instanceof CGLSurfaceData) == true) { 374 CGLSurfaceData cglsd = (CGLSurfaceData) sd; 375 return createCGLContextOnSurface(cglsd, sharedContext); 376 } else { 377 return 0L; 378 } 379 } 380 381 // returns whether or not the makeCurrent operation succeeded 382 native static boolean makeCGLContextCurrentOnSurface(CGLSurfaceData sd, 383 long ctx); 384 385 public static boolean makeOGLContextCurrentOnSurface(Graphics g, long ctx) { 386 SurfaceData sd = ((SunGraphics2D) g).surfaceData; 387 if ((ctx != 0L) && ((sd instanceof CGLSurfaceData) == true)) { 388 CGLSurfaceData cglsd = (CGLSurfaceData) sd; 389 return makeCGLContextCurrentOnSurface(cglsd, ctx); 390 } else { 391 return false; 392 } 393 } 394 395 // additional cleanup 396 private native static void destroyCGLContext(long ctx); 397 398 public static void destroyOGLContext(long ctx) { 399 if (ctx != 0L) { 400 destroyCGLContext(ctx); 401 } 402 } 403 } --- EOF ---