|
26 | 26 | package sun.java2d.opengl; |
27 | 27 |
|
28 | 28 | import java.awt.AWTException; |
| 29 | +import java.awt.AWTError; |
29 | 30 | import java.awt.BufferCapabilities; |
30 | 31 | import java.awt.Component; |
31 | 32 | import java.awt.Graphics; |
|
60 | 61 |
|
61 | 62 | import sun.lwawt.LWComponentPeer; |
62 | 63 | import sun.lwawt.macosx.CPlatformView; |
| 64 | +import sun.lwawt.macosx.CThreading; |
| 65 | +import java.security.PrivilegedAction; |
| 66 | +import java.util.concurrent.Callable; |
63 | 67 |
|
64 | 68 | public final class CGLGraphicsConfig extends CGraphicsConfig |
65 | 69 | implements OGLGraphicsConfig |
@@ -134,40 +138,57 @@ public static CGLGraphicsConfig getConfig(CGraphicsDevice device, |
134 | 138 | return null; |
135 | 139 | } |
136 | 140 |
|
137 | | - long cfginfo = 0; |
138 | | - int textureSize = 0; |
139 | | - final String ids[] = new String[1]; |
140 | | - OGLRenderQueue rq = OGLRenderQueue.getInstance(); |
141 | | - rq.lock(); |
142 | | - try { |
143 | | - // getCGLConfigInfo() creates and destroys temporary |
144 | | - // surfaces/contexts, so we should first invalidate the current |
145 | | - // Java-level context and flush the queue... |
146 | | - OGLContext.invalidateCurrentContext(); |
147 | | - |
148 | | - cfginfo = getCGLConfigInfo(device.getCGDisplayID(), pixfmt, |
149 | | - kOpenGLSwapInterval); |
150 | | - if (cfginfo != 0L) { |
151 | | - textureSize = nativeGetMaxTextureSize(); |
152 | | - // 7160609: GL still fails to create a square texture of this |
153 | | - // size. Half should be safe enough. |
154 | | - // Explicitly not support a texture more than 2^14, see 8010999. |
155 | | - textureSize = textureSize <= 16384 ? textureSize / 2 : 8192; |
156 | | - OGLContext.setScratchSurface(cfginfo); |
157 | | - rq.flushAndInvokeNow(() -> { |
158 | | - ids[0] = OGLContext.getOGLIdString(); |
159 | | - }); |
| 141 | + // Move CGLGraphicsConfig creation code to AppKit thread in order to avoid the |
| 142 | + // following deadlock: |
| 143 | + // 1) CGLGraphicsConfig.getCGLConfigInfo (called from EDT) takes RenderQueue.lock |
| 144 | + // 2) CGLLayer.drawInCGLContext is invoked on AppKit thread and |
| 145 | + // blocked on RenderQueue.lock |
| 146 | + // 1) invokes native block on AppKit and wait |
| 147 | + |
| 148 | + Callable<CGLGraphicsConfig> command = () -> { |
| 149 | + long cfginfo; |
| 150 | + int textureSize = 0; |
| 151 | + final String ids[] = new String[1]; |
| 152 | + OGLRenderQueue rq = OGLRenderQueue.getInstance(); |
| 153 | + rq.lock(); |
| 154 | + try { |
| 155 | + // getCGLConfigInfo() creates and destroys temporary |
| 156 | + // surfaces/contexts, so we should first invalidate the current |
| 157 | + // Java-level context and flush the queue... |
| 158 | + OGLContext.invalidateCurrentContext(); |
| 159 | + |
| 160 | + cfginfo = getCGLConfigInfo(device.getCGDisplayID(), pixfmt, |
| 161 | + kOpenGLSwapInterval); |
| 162 | + if (cfginfo != 0L) { |
| 163 | + textureSize = nativeGetMaxTextureSize(); |
| 164 | + // 7160609: GL still fails to create a square texture of this |
| 165 | + // size. Half should be safe enough. |
| 166 | + // Explicitly not support a texture more than 2^14, see 8010999. |
| 167 | + textureSize = textureSize <= 16384 ? textureSize / 2 : 8192; |
| 168 | + OGLContext.setScratchSurface(cfginfo); |
| 169 | + rq.flushAndInvokeNow(() -> ids[0] = OGLContext.getOGLIdString()); |
| 170 | + } |
| 171 | + } finally { |
| 172 | + rq.unlock(); |
| 173 | + } |
| 174 | + if (cfginfo == 0) { |
| 175 | + return null; |
160 | 176 | } |
161 | | - } finally { |
162 | | - rq.unlock(); |
163 | | - } |
164 | | - if (cfginfo == 0) { |
165 | | - return null; |
166 | | - } |
167 | 177 |
|
168 | | - int oglCaps = getOGLCapabilities(cfginfo); |
169 | | - ContextCapabilities caps = new OGLContextCaps(oglCaps, ids[0]); |
170 | | - return new CGLGraphicsConfig(device, pixfmt, cfginfo, textureSize, caps); |
| 178 | + int oglCaps = getOGLCapabilities(cfginfo); |
| 179 | + ContextCapabilities caps = new OGLContextCaps(oglCaps, ids[0]); |
| 180 | + return new CGLGraphicsConfig( |
| 181 | + device, pixfmt, cfginfo, textureSize, caps); |
| 182 | + }; |
| 183 | + |
| 184 | + return java.security.AccessController.doPrivileged( |
| 185 | + (PrivilegedAction<CGLGraphicsConfig>) () -> { |
| 186 | + try { |
| 187 | + return CThreading.executeOnAppKit(command); |
| 188 | + } catch (Throwable throwable) { |
| 189 | + throw new AWTError(throwable.getMessage()); |
| 190 | + } |
| 191 | + }); |
171 | 192 | } |
172 | 193 |
|
173 | 194 | static void refPConfigInfo(long pConfigInfo) { |
|
0 commit comments