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