JOGL v2.6.0-rc-20250712
JOGL, High-Performance Graphics Binding for Java™ (public API).
Bug735Inv0AppletAWT.java
Go to the documentation of this file.
1package com.jogamp.opengl.test.bugs;
2
3import java.applet.Applet;
4import java.awt.BorderLayout;
5import java.awt.Color;
6import java.awt.Dimension;
7import java.awt.EventQueue;
8import java.awt.Frame;
9import java.awt.GraphicsDevice;
10import java.awt.GraphicsEnvironment;
11import java.awt.Insets;
12import java.awt.Rectangle;
13import java.awt.event.WindowAdapter;
14import java.awt.event.WindowEvent;
15import java.nio.FloatBuffer;
16import java.util.concurrent.CountDownLatch;
17import java.util.concurrent.TimeUnit;
18
19import com.jogamp.opengl.GL;
20import com.jogamp.opengl.GL2ES2;
21import com.jogamp.opengl.GLAutoDrawable;
22import com.jogamp.opengl.GLCapabilities;
23import com.jogamp.opengl.GLContext;
24import com.jogamp.opengl.GLException;
25import com.jogamp.opengl.GLProfile;
26import com.jogamp.opengl.GLRunnable;
27import com.jogamp.opengl.GLUniformData;
28import com.jogamp.opengl.awt.GLCanvas;
29import com.jogamp.opengl.glu.GLU;
30import com.jogamp.common.os.Clock;
31import com.jogamp.common.util.InterruptSource;
32import com.jogamp.newt.awt.NewtCanvasAWT;
33import com.jogamp.newt.opengl.GLWindow;
34import com.jogamp.opengl.test.junit.jogl.demos.es2.LandscapeES2;
35import com.jogamp.opengl.util.GLArrayDataServer;
36import com.jogamp.opengl.util.glsl.ShaderCode;
37import com.jogamp.opengl.util.glsl.ShaderProgram;
38import com.jogamp.opengl.util.glsl.ShaderState;
39
40/**
41 * Original test case.
42 * <br/>
43 * OSX Results:
44 * <pre>
45 * - Visible content
46 * - Fluent animation
47 * </pre>
48 */
49@SuppressWarnings("serial")
50public class Bug735Inv0AppletAWT extends Applet implements Runnable {
51 static public final int AWT = 0;
52 static public final int NEWT = 1;
53
54 static public final int APPLET_WIDTH = 500;
55 static public final int APPLET_HEIGHT = 290;
56 static public final int TARGET_FPS = 120;
57 static public final int TOOLKIT = NEWT;
58 static public final boolean MANUAL_FRAME_HANDLING = true;
59
60 //////////////////////////////////////////////////////////////////////////////
61
62 static private Frame frame;
63 static private Bug735Inv0AppletAWT applet;
64 private GLCanvas awtCanvas;
65 private GLWindow newtWindow;
66 private NewtCanvasAWT newtCanvas;
67 private DrawRunnable drawRunnable;
68 private GLContext context;
69 private GLU glu;
70
71 private int width;
72 private int height;
73 private Thread thread;
74
75 private boolean doneInit = false;
76 private boolean doneSetup = false;
77
78 private final long frameRatePeriod = 1000000000L / TARGET_FPS;
79 private long millisOffset;
80 private int frameCount;
81 private float frameRate;
82
83 private ShaderCode vertShader;
84 private ShaderCode fragShader;
85 private ShaderProgram shaderProg;
86 private ShaderState shaderState;
87 private GLUniformData resolution;
88 private GLUniformData time;
89 private GLArrayDataServer vertices;
90
91 private int fcount = 0, lastm = 0;
92 private final int fint = 1;
93
94 @Override
95public void init() {
96 setSize(APPLET_WIDTH, APPLET_HEIGHT);
97 setPreferredSize(new Dimension(APPLET_WIDTH, APPLET_HEIGHT));
98 width = APPLET_WIDTH;
99 height = APPLET_HEIGHT;
100 }
101
102 @Override
103public void start() {
104 thread = new InterruptSource.Thread(null, this, "Animation Thread");
105 thread.start();
106 }
107
108 @Override
109public void run() {
110 int noDelays = 0;
111 // Number of frames with a delay of 0 ms before the
112 // animation thread yields to other running threads.
113 final int NO_DELAYS_PER_YIELD = 15;
114 final int TIMEOUT_SECONDS = 2;
115
116 long beforeTime = Clock.currentNanos();
117 long overSleepTime = 0L;
118
119 millisOffset = System.currentTimeMillis();
120 frameCount = 1;
121 while (Thread.currentThread() == thread) {
122 final CountDownLatch latch = new CountDownLatch(1);
123 requestDraw(latch);
124 try {
125 latch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS);
126 } catch (final InterruptedException e) {
127 e.printStackTrace();
128 }
129
130 if (frameCount == 1) {
131 EventQueue.invokeLater(new Runnable() {
132 @Override
133 public void run() {
134 requestFocusInWindow();
135 }
136 });
137 }
138
139 final long afterTime = Clock.currentNanos();
140 final long timeDiff = afterTime - beforeTime;
141 final long sleepTime = (frameRatePeriod - timeDiff) - overSleepTime;
142 if (sleepTime > 0) { // some time left in this cycle
143 try {
144 Thread.sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L));
145 noDelays = 0; // Got some sleep, not delaying anymore
146 } catch (final InterruptedException ex) { }
147 overSleepTime = (Clock.currentNanos() - afterTime) - sleepTime;
148 } else { // sleepTime <= 0; the frame took longer than the period
149 overSleepTime = 0L;
150 noDelays++;
151 if (noDelays > NO_DELAYS_PER_YIELD) {
152 Thread.yield(); // give another thread a chance to run
153 noDelays = 0;
154 }
155 }
156 beforeTime = Clock.currentNanos();
157 }
158 }
159
160 public void requestDraw(final CountDownLatch latch) {
161 if (!doneInit) {
162 initDraw();
163 }
164
165 if (TOOLKIT == AWT) {
166 awtCanvas.invoke(true, drawRunnable);
167 } else if (TOOLKIT == NEWT) {
168 newtWindow.invoke(true, drawRunnable);
169 }
170
171 if (latch != null) {
172 latch.countDown();
173 }
174 }
175
176 private class DrawRunnable implements GLRunnable {
177 private boolean notCurrent;
178
179 @Override
180 public boolean run(final GLAutoDrawable drawable) {
181 if (MANUAL_FRAME_HANDLING) {
182 makeContextCurrent();
183 }
184
185 if (doneSetup) {
186 draw(drawable.getGL().getGL2ES2());
187 } else {
188 setup(drawable.getGL().getGL2ES2());
189 }
190 checkGLErrors(drawable.getGL());
191
192 if (MANUAL_FRAME_HANDLING) {
193 swapBuffers();
194 releaseCurrentContext();
195 }
196
197 return true;
198 }
199
200 private void makeContextCurrent() {
201 final int MAX_CONTEXT_GRAB_ATTEMPTS = 10;
202
203 if (context.isCurrent()) {
204 notCurrent = false;
205 } else {
206 notCurrent = true;
207 int value = GLContext.CONTEXT_NOT_CURRENT;
208 int attempt = 0;
209 do {
210 try {
211 value = context.makeCurrent();
212 System.out.println("Made context current");
213 } catch (final GLException gle) {
214 gle.printStackTrace();
215 } finally {
216 attempt++;
217 if (attempt == MAX_CONTEXT_GRAB_ATTEMPTS) {
218 throw new RuntimeException("Failed to claim OpenGL context.");
219 }
220 }
221 try {
222 Thread.sleep(5);
223 } catch (final InterruptedException e) {
224 e.printStackTrace();
225 }
226
227 } while (value == GLContext.CONTEXT_NOT_CURRENT);
228 }
229 }
230
231 private void swapBuffers() {
232 final GL gl = GLContext.getCurrentGL();
233 gl.glFlush();
234 GLContext.getCurrent().getGLDrawable().swapBuffers();
235 }
236
237 private void releaseCurrentContext() {
238 if (notCurrent) {
239 try {
240 context.release();
241 System.out.println("Released context");
242 } catch (final GLException gle) {
243 gle.printStackTrace();
244 }
245 }
246 }
247 }
248
249 private void initGL() {
250 final GLProfile profile = GLProfile.getDefault();
251 final GLCapabilities caps = new GLCapabilities(profile);
252 caps.setBackgroundOpaque(true);
253 caps.setOnscreen(true);
254 caps.setSampleBuffers(false);
255
256 if (TOOLKIT == AWT) {
257 awtCanvas = new GLCanvas(caps);
258 awtCanvas.setBounds(0, 0, applet.width, applet.height);
259 awtCanvas.setBackground(new Color(0xFFCCCCCC, true));
260 awtCanvas.setFocusable(true);
261
262 applet.setLayout(new BorderLayout());
263 applet.add(awtCanvas, BorderLayout.CENTER);
264
265 if (MANUAL_FRAME_HANDLING) {
266 awtCanvas.setIgnoreRepaint(true);
267 awtCanvas.setAutoSwapBufferMode(false);
268 }
269 } else if (TOOLKIT == NEWT) {
270 newtWindow = GLWindow.create(caps);
271 newtCanvas = new NewtCanvasAWT(newtWindow);
272 newtCanvas.setBounds(0, 0, applet.width, applet.height);
273 newtCanvas.setBackground(new Color(0xFFCCCCCC, true));
274 newtCanvas.setFocusable(true);
275
276 applet.setLayout(new BorderLayout());
277 applet.add(newtCanvas, BorderLayout.CENTER);
278
279 if (MANUAL_FRAME_HANDLING) {
280 newtCanvas.setIgnoreRepaint(true);
281 newtWindow.setAutoSwapBufferMode(false);
282 }
283 }
284 }
285
286 private void initDraw() {
287 if (TOOLKIT == AWT) {
288 awtCanvas.setVisible(true);
289 // Force the realization
290 awtCanvas.display();
291 if (awtCanvas.getDelegatedDrawable().isRealized()) {
292 // Request the focus here as it cannot work when the window is not visible
293 awtCanvas.requestFocus();
294 context = awtCanvas.getContext();
295 }
296 } else if (TOOLKIT == NEWT) {
297 newtCanvas.setVisible(true);
298 // Force the realization
299 newtWindow.display();
300 if (newtWindow.isRealized()) {
301 // Request the focus here as it cannot work when the window is not visible
302 newtCanvas.requestFocus();
303 context = newtWindow.getContext();
304 }
305 }
306
307 drawRunnable = new DrawRunnable();
308
309 doneInit = true;
310 }
311
312 private void setup(final GL2ES2 gl) {
313 if (60 < TARGET_FPS) {
314 // Disables vsync
315 gl.setSwapInterval(0);
316 }
317 glu = new GLU();
318
319 vertShader = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, LandscapeES2.class, "shader", "shader/bin", "landscape", true);
320 fragShader = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, LandscapeES2.class, "shader", "shader/bin", "landscape", true);
321 vertShader.defaultShaderCustomization(gl, true, true);
322 fragShader.defaultShaderCustomization(gl, true, true);
323 shaderProg = new ShaderProgram();
324 shaderProg.add(gl, vertShader, System.err);
325 shaderProg.add(gl, fragShader, System.err);
326
327 shaderState = new ShaderState();
328 shaderState.attachShaderProgram(gl, shaderProg, true);
329
330 resolution = new GLUniformData("iResolution", 3, FloatBuffer.wrap(new float[] {width, height, 0}));
331 shaderState.ownUniform(resolution);
332 shaderState.uniform(gl, resolution);
333
334 time = new GLUniformData("iGlobalTime", 0.0f);
335 shaderState.ownUniform(time);
336
337 vertices = GLArrayDataServer.createGLSL("inVertex", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
338 vertices.putf(-1.0f); vertices.putf(-1.0f);
339 vertices.putf(+1.0f); vertices.putf(-1.0f);
340 vertices.putf(-1.0f); vertices.putf(+1.0f);
341 vertices.putf(+1.0f); vertices.putf(+1.0f);
342 vertices.seal(gl, true);
343 shaderState.ownAttribute(vertices, true);
344 shaderState.useProgram(gl, false);
345
346 doneSetup = true;
347 }
348
349 private void draw(final GL2ES2 gl) {
350 // gl.glClearColor(0.5f, 0.1f, 0.1f, 1);
351 // gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT);
352
353 shaderState.useProgram(gl, true);
354
355 time.setData((System.currentTimeMillis() - millisOffset) / 1000.0f);
356 shaderState.uniform(gl, time);
357 vertices.enableBuffer(gl, true);
358 gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
359 vertices.enableBuffer(gl, false);
360
361 shaderState.useProgram(gl, false);
362
363 // Compute current framerate and printout.
364 frameCount++;
365 fcount += 1;
366 final int m = (int) (System.currentTimeMillis() - millisOffset);
367 if (m - lastm > 1000 * fint) {
368 frameRate = (float)(fcount) / fint;
369 fcount = 0;
370 lastm = m;
371 }
372 if (frameCount % TARGET_FPS == 0) {
373 System.out.println("FrameCount: " + frameCount + " - " +
374 "FrameRate: " + frameRate);
375 }
376 }
377
378 private void checkGLErrors(final GL gl) {
379 final int err = gl.glGetError();
380 if (err != 0) {
381 final String errString = glu.gluErrorString(err);
382 System.out.println(errString);
383 }
384 }
385
386 static public void main(final String[] args) {
387 final GraphicsEnvironment environment =
388 GraphicsEnvironment.getLocalGraphicsEnvironment();
389 final GraphicsDevice displayDevice = environment.getDefaultScreenDevice();
390
391 frame = new Frame(displayDevice.getDefaultConfiguration());
392 frame.setBackground(new Color(0xCC, 0xCC, 0xCC));
393 frame.setTitle("TestBug735Inv0AppletAWT");
394
395 try {
396 final Class<?> c = Thread.currentThread().getContextClassLoader().
397 loadClass(Bug735Inv0AppletAWT.class.getName());
398 applet = (Bug735Inv0AppletAWT) c.newInstance();
399 } catch (final Exception e) {
400 throw new RuntimeException(e);
401 }
402
403 frame.setLayout(null);
404 frame.add(applet);
405 frame.pack();
406 frame.setResizable(false);
407
408 applet.init();
409
410 final Insets insets = frame.getInsets();
411 final int windowW = applet.width + insets.left + insets.right;
412 final int windowH = applet.height + insets.top + insets.bottom;
413 frame.setSize(windowW, windowH);
414
415 final Rectangle screenRect = displayDevice.getDefaultConfiguration().getBounds();
416 frame.setLocation(screenRect.x + (screenRect.width - applet.width) / 2,
417 screenRect.y + (screenRect.height - applet.height) / 2);
418
419 final int usableWindowH = windowH - insets.top - insets.bottom;
420 applet.setBounds((windowW - applet.width)/2,
421 insets.top + (usableWindowH - applet.height)/2,
422 applet.width, applet.height);
423
424 // This allows to close the frame.
425 frame.addWindowListener(new WindowAdapter() {
426 @Override
427 public void windowClosing(final WindowEvent e) {
428 System.exit(0);
429 }
430 });
431
432 applet.initGL();
433 frame.setVisible(true);
434 applet.start();
435 }
436}
AWT Canvas containing a NEWT Window using native parenting.
An implementation of GLAutoDrawable and Window interface, using a delegated Window instance,...
Definition: GLWindow.java:121
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
Abstraction for an OpenGL rendering context.
Definition: GLContext.java:74
abstract int makeCurrent()
Makes this GLContext current on the calling thread.
abstract void release()
Releases control of this GLContext from the current thread.
final boolean isCurrent()
Definition: GLContext.java:522
GLSL uniform data wrapper encapsulating data to be uploaded to the GPU as a uniform.
GLUniformData setData(final int data)
A heavyweight AWT component which provides OpenGL rendering support.
Definition: GLCanvas.java:170
GLContext getContext()
Returns the context associated with this drawable.
Definition: GLCanvas.java:1166
void setAutoSwapBufferMode(final boolean onOrOff)
Enables or disables automatic buffer swapping for this drawable.
Definition: GLCanvas.java:1191
final GLDrawable getDelegatedDrawable()
If the implementation uses delegation, return the delegated GLDrawable instance, otherwise return thi...
Definition: GLCanvas.java:1161
boolean invoke(final boolean wait, final GLRunnable glRunnable)
Enqueues a one-shot GLRunnable, which will be executed within the next display() call after all regis...
Definition: GLCanvas.java:1132
Provides access to the OpenGL Utility Library (GLU).
Definition: GLU.java:43
final String gluErrorString(int errorCode)
Definition: GLU.java:187
void seal(final GL gl, final boolean seal)
Convenience method calling seal(boolean) and enableBuffer(GL, boolean).
void enableBuffer(final GL gl, final boolean enable)
Enables the buffer if enable is true, and transfers the data if required.
static GLArrayDataServer createGLSL(final String name, final int compsPerElement, final int dataType, final boolean normalized, final int initialElementCount, final int vboUsage)
Create a VBO, using a custom GLSL array attribute name and starting with a new created Buffer object ...
Convenient shader code class to use and instantiate vertex or fragment programs.
Definition: ShaderCode.java:75
final int defaultShaderCustomization(final GL2ES2 gl, final boolean preludeVersion, final boolean addDefaultPrecision)
Default customization of this shader source code.
static ShaderCode create(final GL2ES2 gl, final int type, final int count, final Class<?> context, final String[] sourceFiles, final boolean mutableStringBuilder)
Creates a complete ShaderCode object while reading all shader source of sourceFiles,...
synchronized void add(final ShaderCode shaderCode)
Adds a new shader to this program.
ShaderState allows to sharing data between shader programs, while updating the attribute and uniform ...
void ownAttribute(final GLArrayData attribute, final boolean own)
Binds or unbinds the GLArrayData lifecycle to this ShaderState.
synchronized void useProgram(final GL2ES2 gl, final boolean on)
Turns the shader program on or off.
synchronized boolean attachShaderProgram(final GL2ES2 gl, final ShaderProgram prog, final boolean enable)
Attach or switch a shader program.
boolean uniform(final GL2ES2 gl, final GLUniformData data)
Set the uniform data, if it's location is valid, i.e.
void ownUniform(final GLUniformData uniform)
Bind the GLUniform lifecycle to this ShaderState.
A higher-level abstraction than GLDrawable which supplies an event based mechanism (GLEventListener) ...
boolean invoke(boolean wait, GLRunnable glRunnable)
Enqueues a one-shot GLRunnable, which will be executed within the next display() call after all regis...
GL getGL()
Returns the GL pipeline object this GLAutoDrawable uses.
GLContext getContext()
Returns the context associated with this drawable.
void setAutoSwapBufferMode(boolean enable)
Enables or disables automatic buffer swapping for this drawable.
GL2ES2 getGL2ES2()
Casts this object to the GL2ES2 interface.
boolean isRealized()
Returns true if this drawable is realized, otherwise false.