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