JOGL v2.6.0-rc-20250706
JOGL, High-Performance Graphics Binding for Java™ (public API).
Bug735Inv1AppletAWT.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 * Difference to orig. Bug735Inv0AppletAWT:
42 * <pre>
43 * - MANUAL_FRAME_HANDLING: impl using pass through GLContext instead of static
44 * </pre>
45 * OSX Results:
46 * <pre>
47 * - Visible content
48 * - Fluent animation
49 * </pre>
50 */
51@SuppressWarnings("serial")
52public class Bug735Inv1AppletAWT extends Applet implements Runnable {
53 static public final int AWT = 0;
54 static public final int NEWT = 1;
55
56 static public final int APPLET_WIDTH = 500;
57 static public final int APPLET_HEIGHT = 290;
58 static public final int TARGET_FPS = 120;
59 static public final int TOOLKIT = NEWT;
60 static public final boolean MANUAL_FRAME_HANDLING = true;
61
62 //////////////////////////////////////////////////////////////////////////////
63
64 static private Frame frame;
65 static private Bug735Inv1AppletAWT applet;
66 private GLCanvas awtCanvas;
67 private GLWindow newtWindow;
68 private NewtCanvasAWT newtCanvas;
69 private DrawRunnable drawRunnable;
70 // JAU private GLContext context;
71 private GLU glu;
72
73 private int width;
74 private int height;
75 private Thread thread;
76
77 private boolean doneInit = false;
78 private boolean doneSetup = false;
79
80 private final long frameRatePeriod = 1000000000L / TARGET_FPS;
81 private long millisOffset;
82 private int frameCount;
83 private float frameRate;
84
85 private ShaderCode vertShader;
86 private ShaderCode fragShader;
87 private ShaderProgram shaderProg;
88 private ShaderState shaderState;
89 private GLUniformData resolution;
90 private GLUniformData time;
91 private GLArrayDataServer vertices;
92
93 private int fcount = 0, lastm = 0;
94 private final int fint = 1;
95
96 @Override
97public void init() {
98 setSize(APPLET_WIDTH, APPLET_HEIGHT);
99 setPreferredSize(new Dimension(APPLET_WIDTH, APPLET_HEIGHT));
100 width = APPLET_WIDTH;
101 height = APPLET_HEIGHT;
102 }
103
104 @Override
105public void start() {
106 thread = new InterruptSource.Thread(null, this, "Animation Thread");
107 thread.start();
108 }
109
110 @Override
111public void run() {
112 int noDelays = 0;
113 // Number of frames with a delay of 0 ms before the
114 // animation thread yields to other running threads.
115 final int NO_DELAYS_PER_YIELD = 15;
116 final int TIMEOUT_SECONDS = 2;
117
118 long beforeTime = Clock.currentNanos();
119 long overSleepTime = 0L;
120
121 millisOffset = System.currentTimeMillis();
122 frameCount = 1;
123 while (Thread.currentThread() == thread) {
124 final CountDownLatch latch = new CountDownLatch(1);
125 requestDraw(latch);
126 try {
127 latch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS);
128 } catch (final InterruptedException e) {
129 e.printStackTrace();
130 }
131
132 if (frameCount == 1) {
133 EventQueue.invokeLater(new Runnable() {
134 @Override
135 public void run() {
136 requestFocusInWindow();
137 }
138 });
139 }
140
141 final long afterTime = Clock.currentNanos();
142 final long timeDiff = afterTime - beforeTime;
143 final long sleepTime = (frameRatePeriod - timeDiff) - overSleepTime;
144 if (sleepTime > 0) { // some time left in this cycle
145 try {
146 Thread.sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L));
147 noDelays = 0; // Got some sleep, not delaying anymore
148 } catch (final InterruptedException ex) { }
149 overSleepTime = (Clock.currentNanos() - afterTime) - sleepTime;
150 } else { // sleepTime <= 0; the frame took longer than the period
151 overSleepTime = 0L;
152 noDelays++;
153 if (noDelays > NO_DELAYS_PER_YIELD) {
154 Thread.yield(); // give another thread a chance to run
155 noDelays = 0;
156 }
157 }
158 beforeTime = Clock.currentNanos();
159 }
160 }
161
162 public void requestDraw(final CountDownLatch latch) {
163 if (!doneInit) {
164 initDraw();
165 }
166
167 if (TOOLKIT == AWT) {
168 awtCanvas.invoke(true, drawRunnable);
169 } else if (TOOLKIT == NEWT) {
170 newtWindow.invoke(true, drawRunnable);
171 }
172
173 if (latch != null) {
174 latch.countDown();
175 }
176 }
177
178 private class DrawRunnable implements GLRunnable {
179 private boolean notCurrent;
180
181 @Override
182 public boolean run(final GLAutoDrawable drawable) {
183 if (MANUAL_FRAME_HANDLING) {
184 makeContextCurrent(drawable.getContext());
185 }
186
187 if (!doneSetup) {
188 setup(drawable.getGL().getGL2ES2());
189 }
190 draw(drawable.getGL().getGL2ES2());
191 checkGLErrors(drawable.getGL());
192
193 if (MANUAL_FRAME_HANDLING) {
194 swapBuffers(drawable.getContext());
195 releaseCurrentContext(drawable.getContext());
196 }
197
198 return true;
199 }
200
201 private void makeContextCurrent(final GLContext context) {
202 final int MAX_CONTEXT_GRAB_ATTEMPTS = 10;
203
204 if (context.isCurrent()) {
205 notCurrent = false;
206 } else {
207 notCurrent = true;
208 int value = GLContext.CONTEXT_NOT_CURRENT;
209 int attempt = 0;
210 do {
211 try {
212 value = context.makeCurrent();
213 System.out.println("Made context current");
214 } catch (final GLException gle) {
215 gle.printStackTrace();
216 } finally {
217 attempt++;
218 if (attempt == MAX_CONTEXT_GRAB_ATTEMPTS) {
219 throw new RuntimeException("Failed to claim OpenGL context.");
220 }
221 }
222 try {
223 Thread.sleep(5);
224 } catch (final InterruptedException e) {
225 e.printStackTrace();
226 }
227
228 } while (value == GLContext.CONTEXT_NOT_CURRENT);
229 }
230 }
231
232 private void swapBuffers(final GLContext context) {
233 final GL gl = context.getGL();
234 gl.glFlush();
235 context.getGLDrawable().swapBuffers();
236 }
237
238 private void releaseCurrentContext(final GLContext context) {
239 if (notCurrent) {
240 try {
241 context.release();
242 System.out.println("Released context");
243 } catch (final GLException gle) {
244 gle.printStackTrace();
245 }
246 }
247 }
248 }
249
250 private void initGL() {
251 final GLProfile profile = GLProfile.getDefault();
252 final GLCapabilities caps = new GLCapabilities(profile);
253 caps.setBackgroundOpaque(true);
254 caps.setOnscreen(true);
255 caps.setSampleBuffers(false);
256
257 if (TOOLKIT == AWT) {
258 awtCanvas = new GLCanvas(caps);
259 awtCanvas.setBounds(0, 0, applet.width, applet.height);
260 awtCanvas.setBackground(new Color(0xFFCCCCCC, true));
261 awtCanvas.setFocusable(true);
262
263 applet.setLayout(new BorderLayout());
264 applet.add(awtCanvas, BorderLayout.CENTER);
265
266 if (MANUAL_FRAME_HANDLING) {
267 awtCanvas.setIgnoreRepaint(true);
268 awtCanvas.setAutoSwapBufferMode(false);
269 }
270 } else if (TOOLKIT == NEWT) {
271 newtWindow = GLWindow.create(caps);
272 newtCanvas = new NewtCanvasAWT(newtWindow);
273 newtCanvas.setBounds(0, 0, applet.width, applet.height);
274 newtCanvas.setBackground(new Color(0xFFCCCCCC, true));
275 newtCanvas.setFocusable(true);
276
277 applet.setLayout(new BorderLayout());
278 applet.add(newtCanvas, BorderLayout.CENTER);
279
280 if (MANUAL_FRAME_HANDLING) {
281 newtCanvas.setIgnoreRepaint(true);
282 newtWindow.setAutoSwapBufferMode(false);
283 }
284 }
285 }
286
287 private void initDraw() {
288 if (TOOLKIT == AWT) {
289 awtCanvas.setVisible(true);
290 // Force the realization
291 awtCanvas.display();
292 if (awtCanvas.getDelegatedDrawable().isRealized()) {
293 // Request the focus here as it cannot work when the window is not visible
294 awtCanvas.requestFocus();
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 }
304 }
305
306 drawRunnable = new DrawRunnable();
307
308 doneInit = true;
309 }
310
311 private void setup(final GL2ES2 gl) {
312 if (60 < TARGET_FPS) {
313 // Disables vsync
314 gl.setSwapInterval(0);
315 }
316 glu = new GLU();
317
318 vertShader = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, LandscapeES2.class, "shader", "shader/bin", "landscape", true);
319 fragShader = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, LandscapeES2.class, "shader", "shader/bin", "landscape", true);
320 vertShader.defaultShaderCustomization(gl, true, true);
321 fragShader.defaultShaderCustomization(gl, true, true);
322 shaderProg = new ShaderProgram();
323 shaderProg.add(gl, vertShader, System.err);
324 shaderProg.add(gl, fragShader, System.err);
325
326 shaderState = new ShaderState();
327 shaderState.attachShaderProgram(gl, shaderProg, true);
328
329 resolution = new GLUniformData("iResolution", 3, FloatBuffer.wrap(new float[] {width, height, 0}));
330 shaderState.ownUniform(resolution);
331 shaderState.uniform(gl, resolution);
332
333 time = new GLUniformData("iGlobalTime", 0.0f);
334 shaderState.ownUniform(time);
335
336 vertices = GLArrayDataServer.createGLSL("inVertex", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
337 vertices.putf(-1.0f); vertices.putf(-1.0f);
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.seal(gl, true);
342 shaderState.ownAttribute(vertices, true);
343 shaderState.useProgram(gl, false);
344
345 doneSetup = true;
346 }
347
348 private void draw(final GL2ES2 gl) {
349 // gl.glClearColor(0.5f, 0.1f, 0.1f, 1);
350 // gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT);
351
352 shaderState.useProgram(gl, true);
353
354 time.setData((System.currentTimeMillis() - millisOffset) / 1000.0f);
355 shaderState.uniform(gl, time);
356 vertices.enableBuffer(gl, true);
357 gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
358 vertices.enableBuffer(gl, false);
359
360 shaderState.useProgram(gl, false);
361
362 // Compute current framerate and printout.
363 frameCount++;
364 fcount += 1;
365 final int m = (int) (System.currentTimeMillis() - millisOffset);
366 if (m - lastm > 1000 * fint) {
367 frameRate = (float)(fcount) / fint;
368 fcount = 0;
369 lastm = m;
370 }
371 if (frameCount % TARGET_FPS == 0) {
372 System.out.println("FrameCount: " + frameCount + " - " +
373 "FrameRate: " + frameRate);
374 }
375 }
376
377 private void checkGLErrors(final GL gl) {
378 final int err = gl.glGetError();
379 if (err != 0) {
380 final String errString = glu.gluErrorString(err);
381 System.out.println(errString);
382 }
383 }
384
385 static public void main(final String[] args) {
386 final GraphicsEnvironment environment =
387 GraphicsEnvironment.getLocalGraphicsEnvironment();
388 final GraphicsDevice displayDevice = environment.getDefaultScreenDevice();
389
390 frame = new Frame(displayDevice.getDefaultConfiguration());
391 frame.setBackground(new Color(0xCC, 0xCC, 0xCC));
392 frame.setTitle("TestBug735Inv1AppletAWT");
393
394 try {
395 final Class<?> c = Thread.currentThread().getContextClassLoader().
396 loadClass(Bug735Inv1AppletAWT.class.getName());
397 applet = (Bug735Inv1AppletAWT) c.newInstance();
398 } catch (final Exception e) {
399 throw new RuntimeException(e);
400 }
401
402 frame.setLayout(null);
403 frame.add(applet);
404 frame.pack();
405 frame.setResizable(false);
406
407 applet.init();
408
409 final Insets insets = frame.getInsets();
410 final int windowW = applet.width + insets.left + insets.right;
411 final int windowH = applet.height + insets.top + insets.bottom;
412 frame.setSize(windowW, windowH);
413
414 final Rectangle screenRect = displayDevice.getDefaultConfiguration().getBounds();
415 frame.setLocation(screenRect.x + (screenRect.width - applet.width) / 2,
416 screenRect.y + (screenRect.height - applet.height) / 2);
417
418 final int usableWindowH = windowH - insets.top - insets.bottom;
419 applet.setBounds((windowW - applet.width)/2,
420 insets.top + (usableWindowH - applet.height)/2,
421 applet.width, applet.height);
422
423 // This allows to close the frame.
424 frame.addWindowListener(new WindowAdapter() {
425 @Override
426 public void windowClosing(final WindowEvent e) {
427 System.exit(0);
428 }
429 });
430
431 applet.initGL();
432 frame.setVisible(true);
433 applet.start();
434 }
435}
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
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
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.