JOGL v2.6.0-rc-20250706
JOGL, High-Performance Graphics Binding for Java™ (public API).
TestGLContextDrawableSwitch01NEWT.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.glels;
30
31import java.io.IOException;
32
33import com.jogamp.newt.NewtFactory;
34import com.jogamp.newt.Window;
35import com.jogamp.newt.event.WindowAdapter;
36import com.jogamp.newt.event.WindowEvent;
37import com.jogamp.newt.event.WindowListener;
38import com.jogamp.newt.event.WindowUpdateEvent;
39import com.jogamp.newt.opengl.GLWindow;
40
41import com.jogamp.opengl.GLAutoDrawable;
42import com.jogamp.opengl.GLCapabilities;
43import com.jogamp.opengl.GLContext;
44import com.jogamp.opengl.GLDrawable;
45import com.jogamp.opengl.GLDrawableFactory;
46import com.jogamp.opengl.GLProfile;
47
48import com.jogamp.opengl.GLAutoDrawableDelegate;
49import com.jogamp.opengl.util.Animator;
50import com.jogamp.opengl.util.GLDrawableUtil;
51
52import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
53import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
54import com.jogamp.opengl.test.junit.util.NewtTestUtil;
55import com.jogamp.opengl.test.junit.util.QuitAdapter;
56import com.jogamp.opengl.test.junit.util.UITestCase;
57
58import org.junit.Assert;
59import org.junit.BeforeClass;
60import org.junit.Test;
61import org.junit.FixMethodOrder;
62import org.junit.runners.MethodSorters;
63
64/**
65 * Test re-association (switching) of GLContext/GLDrawables,
66 * i.e. ctx1/draw1, ctx2/draw2 -> ctx1/draw2, ctx2/draw1.
67 */
68@FixMethodOrder(MethodSorters.NAME_ASCENDING)
70 static int width, height;
71
72 static GLCapabilities getCaps(final String profile) {
73 if( !GLProfile.isAvailable(profile) ) {
74 System.err.println("Profile "+profile+" n/a");
75 return null;
76 }
77 return new GLCapabilities(GLProfile.get(profile));
78 }
79
80 @BeforeClass
81 public static void initClass() {
82 width = 256;
83 height = 256;
84 }
85
86 private GLAutoDrawable createGLAutoDrawable(final GLCapabilities caps, final int x, final int y, final int width, final int height, final WindowListener wl) throws InterruptedException {
87 final Window window = NewtFactory.createWindow(caps);
88 Assert.assertNotNull(window);
89 window.setPosition(x, y);
90 window.setSize(width, height);
91 window.setVisible(true);
92 Assert.assertTrue(NewtTestUtil.waitForVisible(window, true, null));
93 Assert.assertTrue(NewtTestUtil.waitForRealized(window, true, null));
94
95 final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
96 final GLDrawable drawable = factory.createGLDrawable(window);
97 Assert.assertNotNull(drawable);
98
99 drawable.setRealized(true);
100 Assert.assertTrue(drawable.isRealized());
101
102 final GLContext context = drawable.createContext(null);
103 Assert.assertNotNull(context);
104
105 final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false, null) {
106 @Override
107 protected void destroyImplInLock() {
108 super.destroyImplInLock();
109 window.destroy(); // destroys the actual window
110 }
111 };
112
113 window.setWindowDestroyNotifyAction( new Runnable() {
114 @Override
115 public void run() {
117 } } );
118
119 // add basic window interaction
120 window.addWindowListener(new WindowAdapter() {
121 @Override
122 public void windowRepaint(final WindowUpdateEvent e) {
123 glad.windowRepaintOp();
124 }
125 @Override
126 public void windowResized(final WindowEvent e) {
127 glad.windowResizedOp(window.getSurfaceWidth(), window.getSurfaceHeight());
128 }
129 });
130 window.addWindowListener(wl);
131
132 return glad;
133 }
134
135 @Test(timeout=30000)
136 public void testSwitch2WindowSingleContextGL2ES2() throws InterruptedException {
137 final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
138 if(null == reqGLCaps) return;
139 testSwitch2WindowSingleContextImpl(reqGLCaps);
140 }
141
142 @Test(timeout=30000)
143 public void testSwitch2WindowSingleContextGLES2() throws InterruptedException {
144 final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
145 if(null == reqGLCaps) return;
146 testSwitch2WindowSingleContextImpl(reqGLCaps);
147 }
148
149 private void testSwitch2WindowSingleContextImpl(final GLCapabilities caps) throws InterruptedException {
150 final QuitAdapter quitAdapter = new QuitAdapter();
151
152 final GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter);
153 final GLAutoDrawable glad2 = createGLAutoDrawable(caps, 2*64+width, 64, width+100, height+100, quitAdapter);
154
155 // create single context using glad1 and assign it to glad1,
156 // destroy the prev. context afterwards.
157 {
158 final GLContext newCtx = glad1.createContext(null);
159 Assert.assertNotNull(newCtx);
160 final GLContext oldCtx = glad1.setContext(newCtx, true);
161 Assert.assertNotNull(oldCtx);
162 Assert.assertFalse(oldCtx.isCreated());
163 final int res = newCtx.makeCurrent();
164 Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res);
165 newCtx.release();
166 }
167
168 final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
169 final GearsES2 gears = new GearsES2(1);
170 glad1.addGLEventListener(gears);
171 glad1.addGLEventListener(snapshotGLEventListener);
172 snapshotGLEventListener.setMakeSnapshot();
173
174 final Animator animator = new Animator(0 /* w/o AWT */);
175 animator.add(glad1);
176 animator.add(glad2);
177 animator.start();
178
179 int s = 0;
180 final long t0 = System.currentTimeMillis();
181 long t1 = t0;
182
183 while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
184 if( ( t1 - t0 ) / period > s) {
185 s++;
186 System.err.println(s+" - switch - START "+ ( t1 - t0 ));
187
188 // switch context _and_ the demo synchronously
190
191 System.err.println(s+" - switch - END "+ ( t1 - t0 ));
192 }
193 Thread.sleep(100);
194 t1 = System.currentTimeMillis();
195 }
196
197 animator.stop();
198 glad1.destroy();
199 glad2.destroy();
200 }
201
202 @Test(timeout=30000)
203 public void testSwitch2GLWindowOneDemoGL2ES2() throws InterruptedException {
204 final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
205 if(null == reqGLCaps) return;
206 testSwitch2GLWindowOneDemoImpl(reqGLCaps);
207 }
208
209 @Test(timeout=30000)
210 public void testSwitch2GLWindowOneDemoGLES2() throws InterruptedException {
211 final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
212 if(null == reqGLCaps) return;
213 testSwitch2GLWindowOneDemoImpl(reqGLCaps);
214 }
215
216 private void testSwitch2GLWindowOneDemoImpl(final GLCapabilities caps) throws InterruptedException {
217 final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
218 final GearsES2 gears = new GearsES2(1);
219 final QuitAdapter quitAdapter = new QuitAdapter();
220
221 final GLWindow glWindow1 = GLWindow.create(caps);
222 glWindow1.setTitle("win1");
223 glWindow1.setSize(width, height);
224 glWindow1.setPosition(64, 64);
225 glWindow1.addGLEventListener(0, gears);
226 glWindow1.addGLEventListener(snapshotGLEventListener);
227 glWindow1.addWindowListener(quitAdapter);
228
229 final GLWindow glWindow2 = GLWindow.create(caps);
230 glWindow2.setTitle("win2");
231 glWindow2.setSize(width+100, height+100);
232 glWindow2.setPosition(2*64+width, 64);
233 glWindow2.addWindowListener(quitAdapter);
234
235 final Animator animator = new Animator(0 /* w/o AWT */);
236 animator.add(glWindow1);
237 animator.add(glWindow2);
238 animator.start();
239
240 glWindow1.setVisible(true);
241 glWindow2.setVisible(true);
242
243 snapshotGLEventListener.setMakeSnapshot();
244
245 int s = 0;
246 final long t0 = System.currentTimeMillis();
247 long t1 = t0;
248
249 while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
250 if( ( t1 - t0 ) / period > s) {
251 s++;
252 System.err.println(s+" - switch - START "+ ( t1 - t0 ));
253 System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
254 System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
255
256 // switch context _and_ the demo synchronously
258
259 System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
260 System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
261 System.err.println(s+" - switch - END "+ ( t1 - t0 ));
262
263 snapshotGLEventListener.setMakeSnapshot();
264 }
265 Thread.sleep(100);
266 t1 = System.currentTimeMillis();
267 }
268
269 animator.stop();
270 glWindow1.destroy();
271 glWindow2.destroy();
272
273 }
274
275 @Test(timeout=30000)
276 public void testSwitch2GLWindowEachWithOwnDemoGL2ES2() throws InterruptedException {
277 final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
278 if(null == reqGLCaps) return;
279 testSwitch2GLWindowEachWithOwnDemoImpl(reqGLCaps);
280 }
281
282 @Test(timeout=30000)
283 public void testSwitch2GLWindowEachWithOwnDemoGLES2() throws InterruptedException {
284 final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
285 if(null == reqGLCaps) return;
286 testSwitch2GLWindowEachWithOwnDemoImpl(reqGLCaps);
287 }
288
289 public void testSwitch2GLWindowEachWithOwnDemoImpl(final GLCapabilities caps) throws InterruptedException {
290 final GearsES2 gears = new GearsES2(1);
291 final RedSquareES2 rsquare = new RedSquareES2(1);
292 final QuitAdapter quitAdapter = new QuitAdapter();
293 final SnapshotGLEventListener snapshotGLEventListener1 = new SnapshotGLEventListener();
294 final SnapshotGLEventListener snapshotGLEventListener2 = new SnapshotGLEventListener();
295
296 final GLWindow glWindow1 = GLWindow.create(caps);
297 glWindow1.setTitle("win1");
298 glWindow1.setSize(width, height);
299 glWindow1.setPosition(64, 64);
300 glWindow1.addGLEventListener(0, gears);
301 glWindow1.addGLEventListener(snapshotGLEventListener1);
302 glWindow1.addWindowListener(quitAdapter);
303
304 final GLWindow glWindow2 = GLWindow.create(caps);
305 glWindow2.setTitle("win2");
306 glWindow2.setSize(width+100, height+100);
307 glWindow2.setPosition(2*64+width, 64);
308 glWindow2.addGLEventListener(0, rsquare);
309 glWindow2.addGLEventListener(snapshotGLEventListener2);
310 glWindow2.addWindowListener(quitAdapter);
311
312 final Animator animator = new Animator(0 /* w/o AWT */);
313 animator.add(glWindow1);
314 animator.add(glWindow2);
315 animator.start();
316
317 glWindow1.setVisible(true);
318 glWindow2.setVisible(true);
319
320 snapshotGLEventListener1.setMakeSnapshot();
321 snapshotGLEventListener2.setMakeSnapshot();
322
323 int s = 0;
324 final long t0 = System.currentTimeMillis();
325 long t1 = t0;
326
327 while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
328 if( ( t1 - t0 ) / period > s) {
329 s++;
330 System.err.println(s+" - switch - START "+ ( t1 - t0 ));
331 System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
332 System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
334 System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
335 System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
336 System.err.println(s+" - switch - END "+ ( t1 - t0 ));
337 snapshotGLEventListener1.setMakeSnapshot();
338 snapshotGLEventListener2.setMakeSnapshot();
339 }
340 Thread.sleep(100);
341 t1 = System.currentTimeMillis();
342 }
343
344 animator.stop();
345 // System.err.println("pre -del-w1: w1: "+glWindow1);
346 // System.err.println("pre -del-w1: w2: "+glWindow2);
347 glWindow1.destroy();
348 // System.err.println("post-del-w1: w1: "+glWindow1);
349 // System.err.println("post-del-w1: w2: "+glWindow2);
350 glWindow2.destroy();
351
352 }
353
354 // default timing for 2 switches
355 static long duration = 2200; // ms
356 static long period = 1000; // ms
357
358 public static void main(final String args[]) throws IOException {
359 for(int i=0; i<args.length; i++) {
360 if(args[i].equals("-time")) {
361 i++;
362 try {
363 duration = Integer.parseInt(args[i]);
364 } catch (final Exception ex) { ex.printStackTrace(); }
365 } else if(args[i].equals("-period")) {
366 i++;
367 try {
368 period = Integer.parseInt(args[i]);
369 } catch (final Exception ex) { ex.printStackTrace(); }
370 }
371 }
372 /**
373 BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
374 System.err.println("Press enter to continue");
375 System.err.println(stdin.readLine()); */
376 org.junit.runner.JUnitCore.main(TestGLContextDrawableSwitch01NEWT.class.getName());
377 }
378}
static Window createWindow(final CapabilitiesImmutable caps)
Create a top level Window entity on the default Display and default Screen.
An implementation of GLAutoDrawable and Window interface, using a delegated Window instance,...
Definition: GLWindow.java:121
final void setPosition(final int x, final int y)
Sets the location of the window's client area excluding insets (window decorations) in window units.
Definition: GLWindow.java:525
final void setTitle(final String title)
Definition: GLWindow.java:297
final void setSize(final int width, final int height)
Sets the size of the window's client area in window units, excluding decorations.
Definition: GLWindow.java:625
final void setVisible(final boolean visible)
Calls setVisible(true, visible), i.e.
Definition: GLWindow.java:615
final void addWindowListener(final WindowListener l)
Appends the given com.jogamp.newt.event.WindowListener to the end of the list.
Definition: GLWindow.java:882
final void destroy()
Destroys all resources associated with this GLAutoDrawable, inclusive the GLContext.
Definition: GLWindow.java:605
static GLWindow create(final GLCapabilitiesImmutable caps)
Creates a new GLWindow attaching a new Window referencing a new default Screen and default Display wi...
Definition: GLWindow.java:169
Fully functional GLAutoDrawable implementation utilizing already created GLDrawable and GLContext ins...
final void windowResizedOp(final int newWidth, final int newHeight)
Handling resize events from the windowing system.
final void windowDestroyNotifyOp()
Implementation to handle destroy notifications from the windowing system.
final void windowRepaintOp()
Default implementation to handle repaint events from the windowing system.
Specifies a set of OpenGL capabilities.
Abstraction for an OpenGL rendering context.
Definition: GLContext.java:74
abstract int makeCurrent()
Makes this GLContext current on the calling thread.
final boolean isCreated()
Indicates whether the underlying native OpenGL context has been created.
Definition: GLContext.java:604
static final int CONTEXT_CURRENT
Indicates that the context was made current during the last call to makeCurrent, value {@value}.
Definition: GLContext.java:114
abstract void release()
Releases control of this GLContext from the current thread.
static final int CONTEXT_CURRENT_NEW
Indicates that a newly-created context was made current during the last call to makeCurrent,...
Definition: GLContext.java:116
final long getHandle()
Returns the underlying native OpenGL context handle.
Definition: GLContext.java:599
abstract GLDrawable createGLDrawable(NativeSurface target)
Returns an unrealized GLDrawable according to it's chosen GLCapabilitiesImmutable,...
static GLDrawableFactory getFactory(final GLProfile glProfile)
Returns the sole GLDrawableFactory instance.
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 final String GLES2
The embedded OpenGL profile ES 2.x, with x >= 0.
Definition: GLProfile.java:585
static GLProfile get(final AbstractGraphicsDevice device, String profile)
Returns a GLProfile object.
static boolean waitForRealized(final Screen screen, final boolean realized, final Runnable waitAction)
static boolean waitForVisible(final Window win, final boolean visible, final Runnable waitAction)
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
Providing utility functions dealing w/ GLDrawables, GLAutoDrawable and their GLEventListener.
static final void swapGLContextAndAllGLEventListener(final GLAutoDrawable a, final GLAutoDrawable b)
Swaps the GLContext and all GLEventListener between GLAutoDrawable a and b, while preserving it's ini...
int getSurfaceWidth()
Returns the width of the client area excluding insets (window decorations) in pixel units.
int getSurfaceHeight()
Returns the height of the client area excluding insets (window decorations) in pixel units.
Specifying NEWT's Window functionality:
Definition: Window.java:115
void addWindowListener(WindowListener l)
Appends the given com.jogamp.newt.event.WindowListener to the end of the list.
void setWindowDestroyNotifyAction(Runnable r)
Set a custom action handling destruction issued by a toolkit triggered window destroy replacing the d...
void setSize(int width, int height)
Sets the size of the window's client area in window units, excluding decorations.
void setVisible(boolean visible)
Calls setVisible(true, visible), i.e.
void setPosition(int x, int y)
Sets the location of the window's client area excluding insets (window decorations) in window units.
void destroy()
Destroys this window incl.releasing all related resources.
A higher-level abstraction than GLDrawable which supplies an event based mechanism (GLEventListener) ...
GLContext setContext(GLContext newCtx, boolean destroyPrevCtx)
Associate the new context, newtCtx, to this auto-drawable.
GLContext createContext(GLContext shareWith)
Creates a new context for drawing to this drawable that will optionally share buffer objects,...
void addGLEventListener(GLEventListener listener)
Adds the given listener to the end of this drawable queue.
void destroy()
Destroys all resources associated with this GLAutoDrawable, inclusive the GLContext.
GLContext getContext()
Returns the context associated with this drawable.
An abstraction for an OpenGL rendering target.
Definition: GLDrawable.java:51
long getHandle()
Returns the GL drawable handle, guaranteed to be valid after realization and while it's surface is be...
boolean isRealized()
Returns true if this drawable is realized, otherwise false.
void setRealized(boolean realized)
Indicates to GLDrawable implementations whether the underlying surface has been created and can be dr...
GLContext createContext(GLContext shareWith)
Creates a new context for drawing to this drawable that will optionally share buffer objects,...