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