/java-1.7.0-openjdk/openjdk/jdk/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java

# · Java · 481 lines · 327 code · 55 blank · 99 comment · 40 complexity · e215de6d513e84558e0648ffe3c51e1b MD5 · raw file

  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. package sun.java2d.opengl;
  26. import java.awt.AWTException;
  27. import java.awt.BufferCapabilities;
  28. import java.awt.Color;
  29. import java.awt.Component;
  30. import java.awt.Graphics;
  31. import java.awt.Graphics2D;
  32. import java.awt.Image;
  33. import java.awt.ImageCapabilities;
  34. import java.awt.Transparency;
  35. import java.awt.color.ColorSpace;
  36. import java.awt.image.BufferedImage;
  37. import java.awt.image.ColorModel;
  38. import java.awt.image.DataBuffer;
  39. import java.awt.image.DirectColorModel;
  40. import java.awt.image.VolatileImage;
  41. import java.awt.image.WritableRaster;
  42. import sun.awt.CGraphicsConfig;
  43. import sun.awt.CGraphicsDevice;
  44. import sun.awt.image.OffScreenImage;
  45. import sun.awt.image.SunVolatileImage;
  46. import sun.awt.image.SurfaceManager;
  47. import sun.java2d.Disposer;
  48. import sun.java2d.DisposerRecord;
  49. import sun.java2d.SunGraphics2D;
  50. import sun.java2d.Surface;
  51. import sun.java2d.SurfaceData;
  52. import sun.java2d.opengl.OGLContext.OGLContextCaps;
  53. import sun.java2d.pipe.hw.AccelSurface;
  54. import sun.java2d.pipe.hw.AccelTypedVolatileImage;
  55. import sun.java2d.pipe.hw.ContextCapabilities;
  56. import static sun.java2d.opengl.OGLSurfaceData.*;
  57. import static sun.java2d.opengl.OGLContext.OGLContextCaps.*;
  58. import sun.java2d.opengl.CGLSurfaceData.CGLVSyncOffScreenSurfaceData;
  59. import sun.java2d.pipe.hw.AccelDeviceEventListener;
  60. import sun.java2d.pipe.hw.AccelDeviceEventNotifier;
  61. import sun.lwawt.macosx.CPlatformView;
  62. public class CGLGraphicsConfig extends CGraphicsConfig
  63. implements OGLGraphicsConfig
  64. {
  65. //private static final int kOpenGLSwapInterval = RuntimeOptions.getCurrentOptions().OpenGLSwapInterval;
  66. private static final int kOpenGLSwapInterval = 0; // TODO
  67. protected static boolean cglAvailable;
  68. private static ImageCapabilities imageCaps = new CGLImageCaps();
  69. private int pixfmt;
  70. private BufferCapabilities bufferCaps;
  71. private long pConfigInfo;
  72. private ContextCapabilities oglCaps;
  73. private OGLContext context;
  74. private Object disposerReferent = new Object();
  75. public static native int getDefaultPixFmt(int screennum);
  76. private static native boolean initCGL();
  77. private static native long getCGLConfigInfo(int screennum, int visualnum,
  78. int swapInterval);
  79. private static native int getOGLCapabilities(long configInfo);
  80. static {
  81. cglAvailable = initCGL();
  82. }
  83. protected CGLGraphicsConfig(CGraphicsDevice device, int pixfmt,
  84. long configInfo, ContextCapabilities oglCaps)
  85. {
  86. super(device);
  87. this.pixfmt = pixfmt;
  88. this.pConfigInfo = configInfo;
  89. this.oglCaps = oglCaps;
  90. context = new OGLContext(OGLRenderQueue.getInstance(), this);
  91. // add a record to the Disposer so that we destroy the native
  92. // CGLGraphicsConfigInfo data when this object goes away
  93. Disposer.addRecord(disposerReferent,
  94. new CGLGCDisposerRecord(pConfigInfo));
  95. }
  96. @Override
  97. public Object getProxyKey() {
  98. return this;
  99. }
  100. @Override
  101. public SurfaceData createManagedSurface(int w, int h, int transparency) {
  102. return CGLSurfaceData.createData(this, w, h,
  103. getColorModel(transparency),
  104. null,
  105. OGLSurfaceData.TEXTURE);
  106. }
  107. public static CGLGraphicsConfig getConfig(CGraphicsDevice device,
  108. int pixfmt)
  109. {
  110. if (!cglAvailable) {
  111. return null;
  112. }
  113. long cfginfo = 0;
  114. final String ids[] = new String[1];
  115. OGLRenderQueue rq = OGLRenderQueue.getInstance();
  116. rq.lock();
  117. try {
  118. // getCGLConfigInfo() creates and destroys temporary
  119. // surfaces/contexts, so we should first invalidate the current
  120. // Java-level context and flush the queue...
  121. OGLContext.invalidateCurrentContext();
  122. cfginfo = getCGLConfigInfo(device.getCoreGraphicsScreen(), pixfmt,
  123. kOpenGLSwapInterval);
  124. OGLContext.setScratchSurface(cfginfo);
  125. rq.flushAndInvokeNow(new Runnable() {
  126. public void run() {
  127. ids[0] = OGLContext.getOGLIdString();
  128. }
  129. });
  130. } finally {
  131. rq.unlock();
  132. }
  133. if (cfginfo == 0) {
  134. return null;
  135. }
  136. int oglCaps = getOGLCapabilities(cfginfo);
  137. ContextCapabilities caps = new OGLContextCaps(oglCaps, ids[0]);
  138. return new CGLGraphicsConfig(device, pixfmt, cfginfo, caps);
  139. }
  140. public static boolean isCGLAvailable() {
  141. return cglAvailable;
  142. }
  143. /**
  144. * Returns true if the provided capability bit is present for this config.
  145. * See OGLContext.java for a list of supported capabilities.
  146. */
  147. public final boolean isCapPresent(int cap) {
  148. return ((oglCaps.getCaps() & cap) != 0);
  149. }
  150. public final long getNativeConfigInfo() {
  151. return pConfigInfo;
  152. }
  153. /**
  154. * {@inheritDoc}
  155. *
  156. * @see sun.java2d.pipe.hw.BufferedContextProvider#getContext
  157. */
  158. public final OGLContext getContext() {
  159. return context;
  160. }
  161. @Override
  162. public BufferedImage createCompatibleImage(int width, int height) {
  163. ColorModel model = new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
  164. WritableRaster
  165. raster = model.createCompatibleWritableRaster(width, height);
  166. return new BufferedImage(model, raster, model.isAlphaPremultiplied(),
  167. null);
  168. }
  169. @Override
  170. public ColorModel getColorModel(int transparency) {
  171. switch (transparency) {
  172. case Transparency.OPAQUE:
  173. // REMIND: once the ColorModel spec is changed, this should be
  174. // an opaque premultiplied DCM...
  175. return new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
  176. case Transparency.BITMASK:
  177. return new DirectColorModel(25, 0xff0000, 0xff00, 0xff, 0x1000000);
  178. case Transparency.TRANSLUCENT:
  179. ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
  180. return new DirectColorModel(cs, 32,
  181. 0xff0000, 0xff00, 0xff, 0xff000000,
  182. true, DataBuffer.TYPE_INT);
  183. default:
  184. return null;
  185. }
  186. }
  187. public boolean isDoubleBuffered() {
  188. return isCapPresent(CAPS_DOUBLEBUFFERED);
  189. }
  190. private static class CGLGCDisposerRecord implements DisposerRecord {
  191. private long pCfgInfo;
  192. public CGLGCDisposerRecord(long pCfgInfo) {
  193. this.pCfgInfo = pCfgInfo;
  194. }
  195. public void dispose() {
  196. if (pCfgInfo != 0) {
  197. OGLRenderQueue.disposeGraphicsConfig(pCfgInfo);
  198. pCfgInfo = 0;
  199. }
  200. }
  201. }
  202. // TODO: CGraphicsConfig doesn't implement displayChanged() yet
  203. //@Override
  204. public synchronized void displayChanged() {
  205. //super.displayChanged();
  206. // the context could hold a reference to a CGLSurfaceData, which in
  207. // turn has a reference back to this CGLGraphicsConfig, so in order
  208. // for this instance to be disposed we need to break the connection
  209. OGLRenderQueue rq = OGLRenderQueue.getInstance();
  210. rq.lock();
  211. try {
  212. OGLContext.invalidateCurrentContext();
  213. } finally {
  214. rq.unlock();
  215. }
  216. }
  217. @Override
  218. public String toString() {
  219. int screen = getDevice().getCoreGraphicsScreen();
  220. return ("CGLGraphicsConfig[dev="+screen+",pixfmt="+pixfmt+"]");
  221. }
  222. /**
  223. * The following methods are invoked from ComponentModel.java rather
  224. * than having the Mac OS X-dependent implementations hardcoded in that
  225. * class. This way the appropriate actions are taken based on the peer's
  226. * GraphicsConfig, whether it is a CGraphicsConfig or a
  227. * CGLGraphicsConfig.
  228. */
  229. /**
  230. * Creates a new SurfaceData that will be associated with the given
  231. * LWWindowPeer.
  232. */
  233. @Override
  234. public SurfaceData createSurfaceData(CPlatformView pView) {
  235. return CGLSurfaceData.createData(pView);
  236. }
  237. /**
  238. * Creates a new SurfaceData that will be associated with the given
  239. * CGLLayer.
  240. */
  241. @Override
  242. public SurfaceData createSurfaceData(CGLLayer layer) {
  243. return CGLSurfaceData.createData(layer);
  244. }
  245. /**
  246. * Creates a new hidden-acceleration image of the given width and height
  247. * that is associated with the target Component.
  248. */
  249. @Override
  250. public Image createAcceleratedImage(Component target,
  251. int width, int height)
  252. {
  253. ColorModel model = getColorModel(Transparency.OPAQUE);
  254. WritableRaster wr =
  255. model.createCompatibleWritableRaster(width, height);
  256. return new OffScreenImage(target, model, wr,
  257. model.isAlphaPremultiplied());
  258. }
  259. /**
  260. * The following methods correspond to the multibuffering methods in
  261. * CWindowPeer.java...
  262. */
  263. /**
  264. * Attempts to create a OGL-based backbuffer for the given peer. If
  265. * the requested configuration is not natively supported, an AWTException
  266. * is thrown. Otherwise, if the backbuffer creation is successful, a
  267. * value of 1 is returned.
  268. */
  269. @Override
  270. public long createBackBuffer(CPlatformView pView,
  271. int numBuffers, BufferCapabilities caps)
  272. throws AWTException
  273. {
  274. if (numBuffers > 2) {
  275. throw new AWTException(
  276. "Only double or single buffering is supported");
  277. }
  278. BufferCapabilities configCaps = getBufferCapabilities();
  279. if (!configCaps.isPageFlipping()) {
  280. throw new AWTException("Page flipping is not supported");
  281. }
  282. if (caps.getFlipContents() == BufferCapabilities.FlipContents.PRIOR) {
  283. throw new AWTException("FlipContents.PRIOR is not supported");
  284. }
  285. // non-zero return value means backbuffer creation was successful
  286. // (checked in CPlatformWindow.flip(), etc.)
  287. return 1;
  288. }
  289. /**
  290. * Destroys the backbuffer object represented by the given handle value.
  291. */
  292. @Override
  293. public void destroyBackBuffer(long backBuffer) {
  294. }
  295. /**
  296. * Creates a VolatileImage that essentially wraps the target Component's
  297. * backbuffer (the provided backbuffer handle is essentially ignored).
  298. */
  299. @Override
  300. public VolatileImage createBackBufferImage(Component target,
  301. long backBuffer)
  302. {
  303. return new SunVolatileImage(target,
  304. target.getWidth(), target.getHeight(),
  305. Boolean.TRUE);
  306. }
  307. /**
  308. * Performs the native OGL flip operation for the given target Component.
  309. */
  310. @Override
  311. public void flip(CPlatformView pView,
  312. Component target, VolatileImage xBackBuffer,
  313. int x1, int y1, int x2, int y2,
  314. BufferCapabilities.FlipContents flipAction)
  315. {
  316. if (flipAction == BufferCapabilities.FlipContents.COPIED) {
  317. SurfaceManager vsm = SurfaceManager.getManager(xBackBuffer);
  318. SurfaceData sd = vsm.getPrimarySurfaceData();
  319. if (sd instanceof CGLVSyncOffScreenSurfaceData) {
  320. CGLVSyncOffScreenSurfaceData vsd =
  321. (CGLVSyncOffScreenSurfaceData)sd;
  322. SurfaceData bbsd = vsd.getFlipSurface();
  323. Graphics2D bbg =
  324. new SunGraphics2D(bbsd, Color.black, Color.white, null);
  325. try {
  326. bbg.drawImage(xBackBuffer, 0, 0, null);
  327. } finally {
  328. bbg.dispose();
  329. }
  330. } else {
  331. pView.drawImageOnPeer(xBackBuffer, x1, y1, x2, y2);
  332. return;
  333. }
  334. } else if (flipAction == BufferCapabilities.FlipContents.PRIOR) {
  335. // not supported by CGL...
  336. return;
  337. }
  338. OGLSurfaceData.swapBuffers(pView.getAWTView());
  339. if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) {
  340. Graphics g = xBackBuffer.getGraphics();
  341. try {
  342. g.setColor(target.getBackground());
  343. g.fillRect(0, 0,
  344. xBackBuffer.getWidth(),
  345. xBackBuffer.getHeight());
  346. } finally {
  347. g.dispose();
  348. }
  349. }
  350. }
  351. private static class CGLBufferCaps extends BufferCapabilities {
  352. public CGLBufferCaps(boolean dblBuf) {
  353. super(imageCaps, imageCaps,
  354. dblBuf ? FlipContents.UNDEFINED : null);
  355. }
  356. }
  357. @Override
  358. public BufferCapabilities getBufferCapabilities() {
  359. if (bufferCaps == null) {
  360. bufferCaps = new CGLBufferCaps(isDoubleBuffered());
  361. }
  362. return bufferCaps;
  363. }
  364. private static class CGLImageCaps extends ImageCapabilities {
  365. private CGLImageCaps() {
  366. super(true);
  367. }
  368. public boolean isTrueVolatile() {
  369. return true;
  370. }
  371. }
  372. @Override
  373. public ImageCapabilities getImageCapabilities() {
  374. return imageCaps;
  375. }
  376. /**
  377. * {@inheritDoc}
  378. *
  379. * @see sun.java2d.pipe.hw.AccelGraphicsConfig#createCompatibleVolatileImage
  380. */
  381. public VolatileImage
  382. createCompatibleVolatileImage(int width, int height,
  383. int transparency, int type)
  384. {
  385. if (type == FLIP_BACKBUFFER || type == WINDOW || type == UNDEFINED ||
  386. transparency == Transparency.BITMASK)
  387. {
  388. return null;
  389. }
  390. if (type == FBOBJECT) {
  391. if (!isCapPresent(CAPS_EXT_FBOBJECT)) {
  392. return null;
  393. }
  394. } else if (type == PBUFFER) {
  395. boolean isOpaque = transparency == Transparency.OPAQUE;
  396. if (!isOpaque && !isCapPresent(CAPS_STORED_ALPHA)) {
  397. return null;
  398. }
  399. }
  400. SunVolatileImage vi = new AccelTypedVolatileImage(this, width, height,
  401. transparency, type);
  402. Surface sd = vi.getDestSurface();
  403. if (!(sd instanceof AccelSurface) ||
  404. ((AccelSurface)sd).getType() != type)
  405. {
  406. vi.flush();
  407. vi = null;
  408. }
  409. return vi;
  410. }
  411. /**
  412. * {@inheritDoc}
  413. *
  414. * @see sun.java2d.pipe.hw.AccelGraphicsConfig#getContextCapabilities
  415. */
  416. public ContextCapabilities getContextCapabilities() {
  417. return oglCaps;
  418. }
  419. public void addDeviceEventListener(AccelDeviceEventListener l) {
  420. int screen = getDevice().getCoreGraphicsScreen();
  421. AccelDeviceEventNotifier.addListener(l, screen);
  422. }
  423. public void removeDeviceEventListener(AccelDeviceEventListener l) {
  424. AccelDeviceEventNotifier.removeListener(l);
  425. }
  426. }