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