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