JOGL v2.6.0-rc-20250706
JOGL, High-Performance Graphics Binding for Java™ (public API).
TestSharedContextVBOES2AWT3.java
Go to the documentation of this file.
1/**
2 * Copyright 2010 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28
29package com.jogamp.opengl.test.junit.jogl.acore;
30
31import java.awt.Frame;
32import java.lang.reflect.InvocationTargetException;
33import java.util.List;
34
35import com.jogamp.opengl.GLCapabilities;
36import com.jogamp.opengl.GLContext;
37import com.jogamp.opengl.GLProfile;
38import com.jogamp.opengl.awt.GLCanvas;
39
40import com.jogamp.opengl.util.Animator;
41import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
42import com.jogamp.opengl.test.junit.util.GLTestUtil;
43import com.jogamp.opengl.test.junit.util.MiscUtils;
44import com.jogamp.opengl.test.junit.util.NewtTestUtil;
45import com.jogamp.opengl.test.junit.util.UITestCase;
46import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
47
48import org.junit.Assert;
49import org.junit.BeforeClass;
50import org.junit.Test;
51import org.junit.FixMethodOrder;
52import org.junit.runners.MethodSorters;
53
54/**
55 * Sharing the VBO of 3 GearsES2 instances, each in their own AWT GLCanvas.
56 * <p>
57 * This is achieved by using the 1st GLCanvas as the <i>master</i>
58 * and using the build-in blocking mechanism to postpone creation
59 * of the 2nd and 3rd GLCanvas until the 1st GLCanvas's GLContext becomes created.
60 * </p>
61 * <p>
62 * Above method allows random creation of the 1st GLCanvas, which triggers
63 * creation of the <i>dependent</i> other GLCanvas sharing it's GLContext.
64 * </p>
65 */
66@FixMethodOrder(MethodSorters.NAME_ASCENDING)
68 static GLProfile glp;
69 static GLCapabilities caps;
70 static int width, height;
71
72 @BeforeClass
73 public static void initClass() {
76 Assert.assertNotNull(glp);
77 caps = new GLCapabilities(glp);
78 Assert.assertNotNull(caps);
79 width = 256;
80 height = 256;
81 } else {
82 setTestSupported(false);
83 }
84 }
85
86 protected GLCanvas createGLCanvas(final Frame frame, final int x, final int y, final GearsES2 gears) throws InterruptedException {
87 final GLCanvas glCanvas = new GLCanvas(caps);
88 Assert.assertNotNull(glCanvas);
89 glCanvas.addGLEventListener(gears);
90 frame.add(glCanvas);
91 frame.setLocation(x, y);
92 frame.setSize(width, height);
93 frame.setTitle("AWT GLCanvas Shared Gears Test: "+x+"/"+y+" shared true");
94 return glCanvas;
95 }
96
97 @Test
98 public void test01SyncedOneAnimatorCleanDtorOrder() throws InterruptedException, InvocationTargetException {
99 syncedOneAnimator(true);
100 }
101
102 @Test
103 public void test02SyncedOneAnimatorDirtyDtorOrder() throws InterruptedException, InvocationTargetException {
104 syncedOneAnimator(false);
105 }
106
107 public void syncedOneAnimator(final boolean destroyCleanOrder) throws InterruptedException, InvocationTargetException {
108 final Frame f1 = new Frame();
109 final Animator animator = new Animator();
110 final GearsES2 g1 = new GearsES2(0);
111 // g1.setUseMappedBuffers(useMappedBuffers);
112 g1.setValidateBuffers(true);
113 final GLCanvas c1 = createGLCanvas(f1, 0, 0, g1);
114 animator.add(c1);
115
116 final Frame f2 = new Frame();
117 final GearsES2 g2 = new GearsES2(0);
118 g2.setSharedGears(g1);
119 final GLCanvas c2 = createGLCanvas(f2, f1.getX()+width,
120 f1.getY()+0, g2);
122 animator.add(c2);
123
124 final Frame f3 = new Frame();
125 final GearsES2 g3 = new GearsES2(0);
126 g3.setSharedGears(g1);
127 final GLCanvas c3 = createGLCanvas(f3, f1.getX()+0,
128 f1.getY()+height, g3);
130 animator.add(c3);
131
132 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
133 public void run() {
134 f2.setVisible(true); // shall wait until f1 is ready
135 f1.setVisible(true); // master ..
136 f3.setVisible(true); // shall wait until f1 is ready
137 } } );
138 animator.start(); // kicks off GLContext .. and hence gears of f2 + f3 completion
139
140 Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid)
141
142 Assert.assertTrue(GLTestUtil.waitForRealized(c1, true, null));
143 Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true, null));
144 Assert.assertTrue(GLTestUtil.waitForContextCreated(c1, true, null));
145 Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true));
146
147 Assert.assertTrue(GLTestUtil.waitForRealized(c2, true, null));
148 Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true, null));
149 Assert.assertTrue(GLTestUtil.waitForContextCreated(c2, true, null));
150 Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true));
151
152 Assert.assertTrue(GLTestUtil.waitForRealized(c3, true, null));
153 Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true, null));
154 Assert.assertTrue(GLTestUtil.waitForContextCreated(c3, true, null));
155 Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true));
156
157 final GLContext ctx1 = c1.getContext();
158 final GLContext ctx2 = c2.getContext();
159 final GLContext ctx3 = c3.getContext();
160 {
161 final List<GLContext> ctx1Shares = ctx1.getCreatedShares();
162 final List<GLContext> ctx2Shares = ctx2.getCreatedShares();
163 final List<GLContext> ctx3Shares = ctx3.getCreatedShares();
164 MiscUtils.dumpSharedGLContext("XXX-C-3.1", ctx1);
165 MiscUtils.dumpSharedGLContext("XXX-C-3.2", ctx2);
166 MiscUtils.dumpSharedGLContext("XXX-C-3.3", ctx3);
167
168 Assert.assertTrue("Ctx1 is not shared", ctx1.isShared());
169 Assert.assertTrue("Ctx2 is not shared", ctx2.isShared());
170 Assert.assertTrue("Ctx3 is not shared", ctx3.isShared());
171 Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size());
172 Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size());
173 Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size());
174 }
175
176 Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears());
177 Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears());
178 Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears());
179
180 try {
181 Thread.sleep(duration);
182 } catch(final Exception e) {
183 e.printStackTrace();
184 }
185 // Stopped animator allows native windowing system 'repaint' event
186 // to trigger GLAD 'display'
187 animator.stop();
188 Assert.assertEquals(false, animator.isAnimating());
189
190 if( destroyCleanOrder ) {
191 System.err.println("XXX Destroy in clean order NOW");
192 } else {
193 System.err.println("XXX Destroy in creation order NOW - Driver Impl. Ma trigger driver Bug i.e. not postponing GL ctx destruction after releasing all refs.");
194 }
195 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
196 public void run() {
197 try {
198 if( destroyCleanOrder ) {
199 f3.dispose();
200 } else {
201 f1.dispose();
202 }
203 } catch (final Throwable t) {
204 throw new RuntimeException(t);
205 }
206 }});
207
208 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
209 public void run() {
210 try {
211 f2.dispose();
212 } catch (final Throwable t) {
213 throw new RuntimeException(t);
214 }
215 }});
216
217 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
218 public void run() {
219 try {
220 if( destroyCleanOrder ) {
221 f1.dispose();
222 } else {
223 f3.dispose();
224 }
225 } catch (final Throwable t) {
226 throw new RuntimeException(t);
227 }
228 }});
229
230 Assert.assertTrue(GLTestUtil.waitForRealized(c1, false, null));
231 Assert.assertTrue(GLTestUtil.waitForRealized(c2, false, null));
232 Assert.assertTrue(GLTestUtil.waitForRealized(c3, false, null));
233 }
234
235 @Test
236 public void test11AsyncEachAnimatorCleanDtorOrder() throws InterruptedException, InvocationTargetException {
237 syncedOneAnimator(true);
238 }
239
240 @Test
241 public void test12AsyncEachAnimatorDirtyDtorOrder() throws InterruptedException, InvocationTargetException {
242 asyncEachOneAnimator(false);
243 }
244
245 public void asyncEachOneAnimator(final boolean destroyCleanOrder) throws InterruptedException, InvocationTargetException {
246 final Frame f1 = new Frame();
247 final Animator a1 = new Animator();
248 final GearsES2 g1 = new GearsES2(0);
249 g1.setSyncObjects(g1); // this is master, since rendered we must use it as sync
250 // g1.setUseMappedBuffers(useMappedBuffers);
251 g1.setValidateBuffers(true);
252 final GLCanvas c1 = createGLCanvas(f1, 0, 0, g1);
253 a1.add(c1);
254 a1.start();
255 // f1.setVisible(true); // we do this post f2 .. to test pending creation!
256
257 final Frame f2 = new Frame();
258 final Animator a2 = new Animator();
259 final GearsES2 g2 = new GearsES2(0);
260 g2.setSharedGears(g1);
261 final GLCanvas c2 = createGLCanvas(f2, f1.getX()+width, f1.getY()+0, g2);
263 a2.add(c2);
264 a2.start();
265 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
266 public void run() {
267 f2.setVisible(true);
268 } } );
269
270 Thread.sleep(200); // wait a while ..
271
272 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
273 public void run() {
274 f1.setVisible(true); // test pending creation of f2
275 } } );
276
277 final Frame f3 = new Frame();
278 final Animator a3 = new Animator();
279 final GearsES2 g3 = new GearsES2(0);
280 g3.setSharedGears(g1);
281 final GLCanvas c3 = createGLCanvas(f3, f1.getX()+0, f1.getY()+height, g3);
283 a3.add(c3);
284 a3.start();
285 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
286 public void run() {
287 f3.setVisible(true);
288 } } );
289
290 Thread.sleep(1000/60*10); // wait ~10 frames giving a chance to create (blocking until master share is valid)
291
292 Assert.assertTrue(GLTestUtil.waitForRealized(c1, true, null));
293 Assert.assertTrue(AWTRobotUtil.waitForVisible(c1, true, null));
294 Assert.assertTrue(GLTestUtil.waitForContextCreated(c1, true, null));
295 Assert.assertTrue("Gears1 not initialized", g1.waitForInit(true));
296
297 Assert.assertTrue(GLTestUtil.waitForRealized(c2, true, null));
298 Assert.assertTrue(AWTRobotUtil.waitForVisible(c2, true, null));
299 Assert.assertTrue(GLTestUtil.waitForContextCreated(c2, true, null));
300 Assert.assertTrue("Gears2 not initialized", g2.waitForInit(true));
301
302 Assert.assertTrue(GLTestUtil.waitForRealized(c3, true, null));
303 Assert.assertTrue(AWTRobotUtil.waitForVisible(c3, true, null));
304 Assert.assertTrue(GLTestUtil.waitForContextCreated(c3, true, null));
305 Assert.assertTrue("Gears3 not initialized", g3.waitForInit(true));
306
307 final GLContext ctx1 = c1.getContext();
308 final GLContext ctx2 = c2.getContext();
309 final GLContext ctx3 = c3.getContext();
310 {
311 final List<GLContext> ctx1Shares = ctx1.getCreatedShares();
312 final List<GLContext> ctx2Shares = ctx2.getCreatedShares();
313 final List<GLContext> ctx3Shares = ctx3.getCreatedShares();
314 MiscUtils.dumpSharedGLContext("XXX-C-3.1", ctx1);
315 MiscUtils.dumpSharedGLContext("XXX-C-3.2", ctx2);
316 MiscUtils.dumpSharedGLContext("XXX-C-3.3", ctx3);
317
318 Assert.assertTrue("Ctx1 is not shared", ctx1.isShared());
319 Assert.assertTrue("Ctx2 is not shared", ctx2.isShared());
320 Assert.assertTrue("Ctx3 is not shared", ctx3.isShared());
321 Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size());
322 Assert.assertEquals("Ctx2 has unexpected number of created shares", 2, ctx2Shares.size());
323 Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size());
324 }
325
326 Assert.assertTrue("Gears1 is shared", !g1.usesSharedGears());
327 Assert.assertTrue("Gears2 is not shared", g2.usesSharedGears());
328 Assert.assertTrue("Gears3 is not shared", g3.usesSharedGears());
329
330 try {
331 Thread.sleep(duration);
332 } catch(final Exception e) {
333 e.printStackTrace();
334 }
335 // Stopped animator allows native windowing system 'repaint' event
336 // to trigger GLAD 'display'
337 a1.stop();
338 Assert.assertEquals(false, a1.isAnimating());
339 a2.stop();
340 Assert.assertEquals(false, a2.isAnimating());
341 a3.stop();
342 Assert.assertEquals(false, a3.isAnimating());
343
344 if( destroyCleanOrder ) {
345 System.err.println("XXX Destroy in clean order NOW");
346 } else {
347 System.err.println("XXX Destroy in creation order NOW - Driver Impl. Ma trigger driver Bug i.e. not postponing GL ctx destruction after releasing all refs.");
348 }
349 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
350 public void run() {
351 try {
352 if( destroyCleanOrder ) {
353 f3.dispose();
354 } else {
355 f1.dispose();
356 }
357 } catch (final Throwable t) {
358 throw new RuntimeException(t);
359 }
360 }});
361
362 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
363 public void run() {
364 try {
365 f2.dispose();
366 } catch (final Throwable t) {
367 throw new RuntimeException(t);
368 }
369 }});
370
371 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
372 public void run() {
373 try {
374 if( destroyCleanOrder ) {
375 f1.dispose();
376 } else {
377 f3.dispose();
378 }
379 } catch (final Throwable t) {
380 throw new RuntimeException(t);
381 }
382 }});
383
384 Assert.assertTrue(GLTestUtil.waitForRealized(c1, false, null));
385 Assert.assertTrue(GLTestUtil.waitForRealized(c2, false, null));
386 Assert.assertTrue(GLTestUtil.waitForRealized(c3, false, null));
387 }
388
389 static long duration = 1000; // ms
390
391 public static void main(final String args[]) {
392 for(int i=0; i<args.length; i++) {
393 if(args[i].equals("-time")) {
394 i++;
395 try {
396 duration = Integer.parseInt(args[i]);
397 } catch (final Exception ex) { ex.printStackTrace(); }
398 }
399 }
400 /**
401 BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
402 System.err.println("Press enter to continue");
403 System.err.println(stdin.readLine()); */
404 org.junit.runner.JUnitCore.main(TestSharedContextVBOES2AWT3.class.getName());
405 }
406}
Specifies a set of OpenGL capabilities.
Abstraction for an OpenGL rendering context.
Definition: GLContext.java:74
final boolean isShared()
Returns true if this GLContext is shared, otherwise false.
Definition: GLContext.java:261
final List< GLContext > getCreatedShares()
Returns a new list of created GLContext shared with this GLContext.
Definition: GLContext.java:277
Specifies the the OpenGL profile.
Definition: GLProfile.java:77
static boolean isAvailable(final AbstractGraphicsDevice device, final String profile)
Returns the availability of a profile on a device.
Definition: GLProfile.java:305
static final String GL2ES2
The intersection of the desktop GL3, GL2 and embedded ES2 profile.
Definition: GLProfile.java:594
static GLProfile get(final AbstractGraphicsDevice device, String profile)
Returns a GLProfile object.
A heavyweight AWT component which provides OpenGL rendering support.
Definition: GLCanvas.java:170
final void setSharedAutoDrawable(final GLAutoDrawable sharedAutoDrawable)
Specifies an GLAutoDrawable, which OpenGL context shall be shared by this GLAutoDrawable's GLContext.
Definition: GLCanvas.java:288
GLContext getContext()
Returns the context associated with this drawable.
Definition: GLCanvas.java:1166
void addGLEventListener(final GLEventListener listener)
Adds the given listener to the end of this drawable queue.
Definition: GLCanvas.java:1065
Sharing the VBO of 3 GearsES2 instances, each in their own AWT GLCanvas.
GLCanvas createGLCanvas(final Frame frame, final int x, final int y, final GearsES2 gears)
boolean waitForInit(final boolean initialized)
Definition: GearsES2.java:187
static boolean waitForVisible(final java.awt.Component comp, final boolean visible, final Runnable waitAction)
static boolean waitForRealized(final GLAutoDrawable glad, final boolean realized, final Runnable waitAction)
Definition: GLTestUtil.java:91
static boolean waitForContextCreated(final GLAutoDrawable autoDrawable, final boolean created, final Runnable waitAction)
Definition: GLTestUtil.java:42
static void dumpSharedGLContext(final String prefix, final GLContext self)
Definition: MiscUtils.java:271
final synchronized void add(final GLAutoDrawable drawable)
Adds a drawable to this animator's list of rendering drawables.
final synchronized boolean start()
Starts this animator, if not running.
Definition: Animator.java:344
final synchronized boolean stop()
Stops this animator.
Definition: Animator.java:368