JOGL v2.6.0-rc-20250706
JOGL, High-Performance Graphics Binding for Java™ (public API).
TestGLContextDrawableSwitch10NEWT.java
Go to the documentation of this file.
1/**
2 * Copyright 2013 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;
39
40import com.jogamp.opengl.GLAutoDrawable;
41import com.jogamp.opengl.GLCapabilities;
42import com.jogamp.opengl.GLContext;
43import com.jogamp.opengl.GLDrawable;
44import com.jogamp.opengl.GLDrawableFactory;
45import com.jogamp.opengl.GLProfile;
46
47
48import com.jogamp.opengl.GLAutoDrawableDelegate;
49import com.jogamp.opengl.GLEventListenerState;
50import com.jogamp.opengl.util.Animator;
51
52import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
53import com.jogamp.opengl.test.junit.util.GLEventListenerCounter;
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 of GLContext/GLDrawables,
66 * here GLContext's survival of GLDrawable destruction
67 * and reuse w/ new or recreated GLDrawable.
68 * <p>
69 * Test utilizes {@link GLEventListenerState} for preserving the
70 * GLAutoDrawable state, i.e. GLContext, all GLEventListener
71 * and the GLAnimatorControl association.
72 * </p>
73 * <p>
74 * This test is using NEWT's plain Window w/ GLAutoDrawableDelegate.
75 * </p>
76 * <p>
77 * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665.
78 * </p>
79 */
80@FixMethodOrder(MethodSorters.NAME_ASCENDING)
82 // default period for 1 GLAD cycle
83 static long duration = 1000; // ms
84
85 static int width, height;
86
87 static GLCapabilities getCaps(final String profile) {
88 if( !GLProfile.isAvailable(profile) ) {
89 System.err.println("Profile "+profile+" n/a");
90 return null;
91 }
92 return new GLCapabilities(GLProfile.get(profile));
93 }
94
95 @BeforeClass
96 public static void initClass() {
97 width = 256;
98 height = 256;
99 }
100
101 private GLAutoDrawable createGLAutoDrawableWithoutContext(final GLCapabilities caps, final int x, final int y, final int width, final int height, final WindowListener wl) throws InterruptedException {
102 final Window window = NewtFactory.createWindow(caps);
103 Assert.assertNotNull(window);
104 window.setPosition(x, y);
105 window.setSize(width, height);
106 window.setVisible(true);
107 Assert.assertTrue(NewtTestUtil.waitForVisible(window, true, null));
108 Assert.assertTrue(NewtTestUtil.waitForRealized(window, true, null));
109 Assert.assertTrue(NewtTestUtil.waitForSize(window, width, height, null));
110
111 final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
112 final GLDrawable drawable = factory.createGLDrawable(window);
113 Assert.assertNotNull(drawable);
114
115 drawable.setRealized(true);
116 Assert.assertTrue(drawable.isRealized());
117 Assert.assertEquals(drawable.getSurfaceWidth(), window.getSurfaceWidth());
118 Assert.assertEquals(drawable.getSurfaceHeight(), window.getSurfaceHeight());
119
120 final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window, false, null) {
121 @Override
122 protected void destroyImplInLock() {
123 super.destroyImplInLock();
124 window.destroy(); // destroys the actual window
125 }
126 };
127
128 window.setWindowDestroyNotifyAction( new Runnable() {
129 @Override
130 public void run() {
132 } } );
133
134 // add basic window interaction
135 window.addWindowListener(new WindowAdapter() {
136 @Override
137 public void windowRepaint(final WindowUpdateEvent e) {
138 glad.windowRepaintOp();
139 }
140 @Override
141 public void windowResized(final WindowEvent e) {
142 glad.windowResizedOp(window.getSurfaceWidth(), window.getSurfaceHeight());
143 }
144 });
145 window.addWindowListener(wl);
146
147 return glad;
148 }
149
150 @Test(timeout=30000)
151 public void test01GLADDelegateGL2ES2() throws InterruptedException {
152 final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
153 if(null == reqGLCaps) return;
154 testGLADDelegateImpl(reqGLCaps);
155 }
156
157 @Test(timeout=30000)
158 public void test02GLADDelegateGLES2() throws InterruptedException {
159 final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
160 if(null == reqGLCaps) return;
161 testGLADDelegateImpl(reqGLCaps);
162 }
163
164 private void testGLADDelegateImpl(final GLCapabilities caps) throws InterruptedException {
165 final GLEventListenerCounter glelCounter = new GLEventListenerCounter();
166 final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
167 final Animator animator = new Animator(0 /* w/o AWT */);
168 animator.start();
169
170 final GLEventListenerState glls1;
171
172 // - create glad1 w/o context
173 // - create context using glad1 and assign it to glad1
174 {
175 final QuitAdapter quitAdapter = new QuitAdapter();
176 final GLAutoDrawable glad1 = createGLAutoDrawableWithoutContext(caps, 64, 64, width, height, quitAdapter);
177 final GLContext context1 = glad1.createContext(null);
178 glad1.setContext(context1, true);
179 animator.add(glad1);
180
181 glad1.addGLEventListener(glelCounter);
182 glad1.addGLEventListener(new GearsES2(1));
183 glad1.addGLEventListener(snapshotGLEventListener);
184 snapshotGLEventListener.setMakeSnapshot();
185
186 final long t0 = System.currentTimeMillis();
187 long t1 = t0;
188
189 while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
190 Thread.sleep(100);
191 t1 = System.currentTimeMillis();
192 }
193
194 Assert.assertEquals(1, glelCounter.initCount);
195 Assert.assertTrue(1 <= glelCounter.reshapeCount);
196 Assert.assertTrue(1 <= glelCounter.displayCount);
197 Assert.assertEquals(0, glelCounter.disposeCount);
198 Assert.assertEquals(context1, glad1.getContext());
199 Assert.assertEquals(3, glad1.getGLEventListenerCount());
200 Assert.assertEquals(context1.getGLReadDrawable(), glad1.getDelegatedDrawable());
201 Assert.assertEquals(context1.getGLDrawable(), glad1.getDelegatedDrawable());
202
203 // - dis-associate context from glad1
204 // - destroy glad1
205 glls1 = GLEventListenerState.moveFrom(glad1);
206
207 Assert.assertEquals(1, glelCounter.initCount);
208 Assert.assertTrue(1 <= glelCounter.reshapeCount);
209 Assert.assertTrue(1 <= glelCounter.displayCount);
210 Assert.assertEquals(0, glelCounter.disposeCount);
211 Assert.assertEquals(context1, glls1.context);
212 Assert.assertNull(context1.getGLReadDrawable());
213 Assert.assertNull(context1.getGLDrawable());
214 Assert.assertEquals(3, glls1.listenerCount());
215 Assert.assertEquals(true, glls1.isOwner());
216 Assert.assertEquals(null, glad1.getContext());
217 Assert.assertEquals(0, glad1.getGLEventListenerCount());
218
219 glad1.destroy();
220 Assert.assertEquals(1, glelCounter.initCount);
221 Assert.assertTrue(1 <= glelCounter.reshapeCount);
222 Assert.assertTrue(1 <= glelCounter.displayCount);
223 Assert.assertEquals(0, glelCounter.disposeCount);
224 }
225
226 // - create glad2 w/ survived context
227 {
228 final QuitAdapter quitAdapter = new QuitAdapter();
229 final GLAutoDrawable glad2 = createGLAutoDrawableWithoutContext(caps, 2*64+width, 64, width+100, height+100, quitAdapter);
230 snapshotGLEventListener.setMakeSnapshot();
231
232 Assert.assertEquals(null, glad2.getContext());
233 Assert.assertEquals(0, glad2.getGLEventListenerCount());
234
235 glls1.moveTo(glad2);
236
237 Assert.assertTrue(glad2.isRealized());
238
239 Assert.assertEquals(1, glelCounter.initCount);
240 Assert.assertTrue(1 <= glelCounter.reshapeCount);
241 Assert.assertTrue(1 <= glelCounter.displayCount);
242 Assert.assertEquals(0, glelCounter.disposeCount);
243 Assert.assertEquals(glls1.context, glad2.getContext());
244 Assert.assertEquals(3, glad2.getGLEventListenerCount());
245 Assert.assertEquals(glls1.context.getGLReadDrawable(), glad2.getDelegatedDrawable());
246 Assert.assertEquals(glls1.context.getGLDrawable(), glad2.getDelegatedDrawable());
247 Assert.assertEquals(false, glls1.isOwner());
248
249 final long t0 = System.currentTimeMillis();
250 long t1 = t0;
251
252 while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
253 Thread.sleep(100);
254 t1 = System.currentTimeMillis();
255 }
256
257 glad2.destroy();
258 Assert.assertEquals(1, glelCounter.initCount);
259 Assert.assertTrue(1 <= glelCounter.reshapeCount);
260 Assert.assertTrue(1 <= glelCounter.displayCount);
261 Assert.assertEquals(1, glelCounter.disposeCount);
262 }
263 animator.stop();
264 }
265
266 public static void main(final String args[]) throws IOException {
267 for(int i=0; i<args.length; i++) {
268 if(args[i].equals("-time")) {
269 i++;
270 try {
271 duration = Integer.parseInt(args[i]);
272 } catch (final Exception ex) { ex.printStackTrace(); }
273 }
274 }
275 /**
276 BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
277 System.err.println("Press enter to continue");
278 System.err.println(stdin.readLine()); */
279 org.junit.runner.JUnitCore.main(TestGLContextDrawableSwitch10NEWT.class.getName());
280 }
281}
static Window createWindow(final CapabilitiesImmutable caps)
Create a top level Window entity on the default Display and default Screen.
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 GLDrawable getGLDrawable()
Returns the write-drawable this context uses for framebuffer operations.
abstract GLDrawable getGLReadDrawable()
Returns the read-Drawable this context uses for read framebuffer operations.
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.
GLEventListenerState is holding GLAutoDrawable components crucial to relocating all its GLEventListen...
final boolean isOwner()
Returns true, if this instance is the current owner of the components, otherwise false.
final void moveTo(final GLAutoDrawable dest)
Moves all GLEventListenerState components to the given GLAutoDrawable from this instance,...
static GLEventListenerState moveFrom(final GLAutoDrawable src)
Moves all GLEventListenerState components from the given GLAutoDrawable to a newly created 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.
Test re-association of GLContext/GLDrawables, here GLContext's survival of GLDrawable destruction and...
static boolean waitForSize(final Window window, final int width, final int height, final Runnable waitAction)
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
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.
int getGLEventListenerCount()
Returns the number of GLEventListener 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.
GLDrawable getDelegatedDrawable()
If the implementation uses delegation, return the delegated GLDrawable instance, otherwise return thi...
An abstraction for an OpenGL rendering target.
Definition: GLDrawable.java:51
int getSurfaceWidth()
Returns the width of this GLDrawable's surface client area in pixel units.
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...
int getSurfaceHeight()
Returns the height of this GLDrawable's surface client area in pixel units.