I modified the Multisample demo to create a test case in order to get the results.
Here is the differences from the capabilites I choose in the GLCapabilitiesChooser, the one actually used by JOGL and the values requested from OpenGL.
Requested capabilites
GLCapabilities [DoubleBuffered: true, Stereo: false, HardwareAccelerated: true, DepthBits: 24, StencilBits: 8, Red: 8, Green: 8, Blue: 8, Alpha: 8, Red Accum: 16, Green Accum: 16, Blue Accum: 16, Alpha Accum: 16, Multisample: true, Num samples: 4 ]
JOGL capabilities
GLCapabilities [DoubleBuffered: true, Stereo: false, HardwareAccelerated: true, DepthBits: 24, StencilBits: 8, Red: 8, Green: 8, Blue: 8, Alpha: 8, Red Accum: 16, Green Accum: 16, Blue Accum: 16, Alpha Accum: 16, Multisample: true, Num samples: 4 ]
Real capabilites
[DoubleBuffered: 1, Stereo : 0, DepthBits : 24, StencilBits : 8, Red : 8, Green : 8, Blue : 8, Alpha : 8, Red Accum : 16, Green Accum : 16, Blue Accum : 16, Alpha Accum : 16, Multisample : 1, Num samples : 2]
The only difference is the number of sample between the capabilities and the values queried from OpenGL.
I’ve also looked at the WindowsGLDrawable.java file and the code seems OK for me.
It’s probably a driver bug then. I hope it’s just happening on Win XP 64.
I will try my test case on other computers to see if there are any differences.
Here is the test case:
import java.awt.*;
import java.awt.event.*;
import javax.media.opengl.*;
public class Multisample {
private GLCanvas canvas;
// Simple class to warn if results are not going to be as expected
static class MultisampleChooser extends DefaultGLCapabilitiesChooser {
public int chooseCapabilities(GLCapabilities desired,
GLCapabilities[] available,
int windowSystemRecommendedChoice) {
boolean anyHaveSampleBuffers = false;
System.err.println("Quering");
for (int i = 0; i < available.length; i++) {
GLCapabilities caps = available[i];
if (caps == null) {
continue;
}
if (caps.getNumSamples() == 4
&& caps.getDepthBits() == 24
&& caps.getRedBits() == 8
&& caps.getAlphaBits() == 8
&& caps.getStencilBits() == 8
&& !caps.getStereo()
&& caps.getDoubleBuffered()
&& caps.getAccumAlphaBits() == 16
&& caps.getSampleBuffers()
&& caps.getHardwareAccelerated())
{
System.err.println("Requested capabilites\n" + caps);
return i;
}
}
return windowSystemRecommendedChoice;
}
}
public static void main(String[] args) {
new Multisample().run(args);
}
public void run(String[] args) {
GLCapabilities caps = new GLCapabilities();
GLCapabilitiesChooser chooser = new MultisampleChooser();
caps.setSampleBuffers(true);
canvas = new GLCanvas(caps, chooser, null, null);
canvas.addGLEventListener(new Listener());
Frame frame = new Frame("Full-scene antialiasing");
frame.setLayout(new BorderLayout());
canvas.setSize(512, 512);
frame.add(canvas, BorderLayout.CENTER);
frame.pack();
frame.show();
canvas.requestFocus();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
runExit();
}
});
}
class Listener implements GLEventListener {
public void init(GLAutoDrawable drawable) {
GL gl = drawable.getGL();
gl.glClearColor(0, 0, 0, 0);
gl.glEnable(GL.GL_MULTISAMPLE);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrtho(-1, 1, -1, 1, -1, 1);
/* Getting info from JOGL */
System.err.println("JOGL capabilities \n" + drawable.getChosenGLCapabilities() );
/* Getting info from OpenGL */
int[] buf = new int[1];
byte[] bbuf = new byte[1];
gl.glGetBooleanv(GL.GL_DOUBLEBUFFER, bbuf,0);
String realCaps = "[DoubleBuffered: " + bbuf[0];
gl.glGetBooleanv(GL.GL_STEREO, bbuf,0);
realCaps += ", Stereo : " + bbuf[0];
gl.glGetIntegerv(GL.GL_DEPTH_BITS, buf, 0);
realCaps += ", DepthBits : " + buf[0];
gl.glGetIntegerv(GL.GL_STENCIL_BITS, buf, 0);
realCaps += ", StencilBits : " + buf[0];
gl.glGetIntegerv(GL.GL_RED_BITS, buf, 0);
realCaps += ", Red : " + buf[0];
gl.glGetIntegerv(GL.GL_GREEN_BITS, buf, 0);
realCaps += ", Green : " + buf[0];
gl.glGetIntegerv(GL.GL_BLUE_BITS, buf, 0);
realCaps += ", Blue : " + buf[0];
gl.glGetIntegerv(GL.GL_ALPHA_BITS, buf, 0);
realCaps += ", Alpha : " + buf[0];
gl.glGetIntegerv(GL.GL_ACCUM_RED_BITS, buf, 0);
realCaps += ", Red Accum : " + buf[0];
gl.glGetIntegerv(GL.GL_ACCUM_GREEN_BITS, buf, 0);
realCaps += ", Green Accum : " + buf[0];
gl.glGetIntegerv(GL.GL_ACCUM_BLUE_BITS, buf, 0);
realCaps += ", Blue Accum : " + buf[0];
gl.glGetIntegerv(GL.GL_ACCUM_ALPHA_BITS, buf, 0);
realCaps += ", Alpha Accum : " + buf[0];
gl.glGetIntegerv(GL.GL_SAMPLE_BUFFERS, buf, 0);
realCaps += ", Multisample : " + buf[0];
gl.glGetIntegerv(GL.GL_SAMPLES, buf, 0);
realCaps += ", Num samples : " + buf[0];
realCaps += "]";
System.err.println("Real capabilites \n" + realCaps);
}
public void display(GLAutoDrawable drawable) {
GL gl = drawable.getGL();
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
int numSteps = 20;
double increment = Math.PI / numSteps;
double radius = 1;
gl.glBegin(GL.GL_LINES);
for (int i = numSteps - 1; i >= 0; i--) {
gl.glVertex3d(radius * Math.cos(i * increment),
radius * Math.sin(i * increment),
0);
gl.glVertex3d(-1.0 * radius * Math.cos(i * increment),
-1.0 * radius * Math.sin(i * increment),
0);
}
gl.glEnd();
}
// Unused routines
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {}
public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {}
}
private void runExit() {
// Note: calling System.exit() synchronously inside the draw,
// reshape or init callbacks can lead to deadlocks on certain
// platforms (in particular, X11) because the JAWT's locking
// routines cause a global AWT lock to be grabbed. Instead run
// the exit routine in another thread.
new Thread(new Runnable() {
public void run() {
System.exit(0);
}
}).start();
}
}