Hello Guest

[Solved] I dont understand this error

  • 5 Replies
  • 7135 Views
*

Offline Cornix

  • *****
  • 488
[Solved] I dont understand this error
« on: June 26, 2015, 22:39:11 »
Hi guys,
I have spent hours on this, to me it seems like this program is fine, but OpenGL says there is an error.

The problem is with immediate mode glBegin / glEnd rendering. For some odd reason when there is a glBegin followed by a glEnd the program will generate an error.
But if I only use glBegin without glEnd then everything works fine and is rendered. Oo
Shouldnt it be the other way around? I dont understand...

The important things happen inside the "run" method. I commented the line that produces the problem.
The error I get is an illegal_operation error.

Code: [Select]
import static org.lwjgl.glfw.Callbacks.errorCallbackPrint;
import static org.lwjgl.glfw.GLFW.GLFW_RESIZABLE;
import static org.lwjgl.glfw.GLFW.GLFW_VISIBLE;
import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
import static org.lwjgl.glfw.GLFW.glfwDefaultWindowHints;
import static org.lwjgl.glfw.GLFW.glfwDestroyWindow;
import static org.lwjgl.glfw.GLFW.glfwInit;
import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent;
import static org.lwjgl.glfw.GLFW.glfwPollEvents;
import static org.lwjgl.glfw.GLFW.glfwSetErrorCallback;
import static org.lwjgl.glfw.GLFW.glfwShowWindow;
import static org.lwjgl.glfw.GLFW.glfwSwapBuffers;
import static org.lwjgl.glfw.GLFW.glfwSwapInterval;
import static org.lwjgl.glfw.GLFW.glfwTerminate;
import static org.lwjgl.glfw.GLFW.glfwWindowHint;
import static org.lwjgl.glfw.GLFW.glfwWindowShouldClose;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_FALSE;
import static org.lwjgl.opengl.GL11.GL_STENCIL_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_TRUE;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glClearColor;
import static org.lwjgl.system.MemoryUtil.NULL;

import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLContext;

public class ErrorMain {

public static void main(String[] args) {
new ErrorMain();
}

private static final String TITLE = "Main";
public static final int WIDTH = 1024;
public static final int HEIGHT = 768;

private GLFWErrorCallback errorCallback;
private long windowHandle;

private ErrorMain() {
try {
initialize();
run();
} catch (Exception e) {
e.printStackTrace();
} finally {
terminate();
}
}

private void initialize() {
errorCallback = errorCallbackPrint(System.err);
glfwSetErrorCallback(errorCallback);

if (glfwInit() != GL_TRUE) {
throw new IllegalStateException("glfwInit() != GL_TRUE");
}
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

windowHandle = glfwCreateWindow(WIDTH, HEIGHT, TITLE, NULL, NULL);
if ( windowHandle == NULL ) {
throw new IllegalStateException("windowHandle == NULL");
}

glfwMakeContextCurrent(windowHandle);
glfwSwapInterval(1);

glfwShowWindow(windowHandle);
GLContext.createFromCurrent();

GL11.glOrtho(0, WIDTH, HEIGHT, 0, 1, -1);
}

private void run() {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

int clearBits = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
while (glfwWindowShouldClose(windowHandle) == GL_FALSE) {
glClear(clearBits);

GL11.glBegin(GL11.GL_TRIANGLES);
glError("initialize", "glBegin");
GL11.glColor4f(1, 0, 0, 1);
GL11.glVertex2f(0, 0);
GL11.glVertex2f(0, 32);
GL11.glVertex2f(32, 32);

// === This line creates the error! ===
GL11.glEnd();
// === If I comment glEnd() the program runs fine Oo ===
glError("initialize", "glEnd");

glfwSwapBuffers(windowHandle);

glfwPollEvents();
}
}

private void terminate() {
try {
glfwDestroyWindow(windowHandle);
} catch (Exception e) {
e.printStackTrace();
}
try {
glfwTerminate();
errorCallback.release();
} catch (Exception e) {
e.printStackTrace();
}
}

// Just a utility method to throw an exception in case of a glError
public static void glError(Object cause, String command) {
int errorCode = GL11.glGetError();
if (errorCode == GL11.GL_NO_ERROR) {
return;
}
StringBuilder str = new StringBuilder();
str.append(cause);
str.append(" caused an error with method ");
str.append(command);
str.append(':');
str.append(' ');
String msg = str.toString();

switch (errorCode) {
case GL11.GL_INVALID_VALUE:
throw new RuntimeException(msg);
case GL11.GL_INVALID_ENUM:
throw new RuntimeException(msg);
case GL11.GL_INVALID_OPERATION:
throw new RuntimeException(msg);
case GL11.GL_STACK_OVERFLOW:
throw new RuntimeException(msg);
case GL11.GL_STACK_UNDERFLOW:
throw new RuntimeException(msg);
case GL11.GL_OUT_OF_MEMORY:
throw new RuntimeException(msg);
default:
throw new RuntimeException(msg + '\n' + "Unknown error.");
}
}

}
« Last Edit: June 27, 2015, 14:52:45 by Cornix »

*

Kai

Re: I dont understand this error
« Reply #1 on: June 26, 2015, 22:45:45 »
It is an error to call glGetError within glBegin()/glEnd().
Move the first call to glGetError before glBegin.
Googling this brought this nice thread on www.opengl.org

*

Offline Cornix

  • *****
  • 488
Re: I dont understand this error
« Reply #2 on: June 26, 2015, 22:48:47 »
What? Really?
This is incredible. I would have thought you can call glError any time.

Moving the glError before the glBegin does indeed fix the error that glEnd generates. But why does it still work without the glEnd without generating any errors? Is this just weird driver dependent hocus pocus?

*

Kai

Re: I dont understand this error
« Reply #3 on: June 26, 2015, 22:53:15 »
Quote
But why does it still work without the glEnd without generating any errors? Is this just weird driver dependent hocus pocus?
Hm, don't know about your driver, but with me it does not work if I don't call glEnd().
It creates a weird flickering and the GL matrix stacks also do not seem to get updated.
I tested this with your demo and some programs using immediate mode of mine. All the same there: Flickering with GL matrices not getting updated.

*

Offline Cornix

  • *****
  • 488
Re: I dont understand this error
« Reply #4 on: June 26, 2015, 22:56:26 »
Okay, so it is my driver then. Weird.

But thanks, I would have never guessed this.
I wonder why glError is not allowed to be called within a glBegin block. I mean, all those functions can generate an error, why are you not allowed to query it?

*

Offline quew8

  • *****
  • 569
  • Because Square Eyes Look More Real
Re: I dont understand this error
« Reply #5 on: June 27, 2015, 13:30:21 »
It is indeed one of the most perplexing bugs you can get in legacy OpenGL, where trying to find out what the error is generates it's own error. A truly Microsoft level of confusion there.

As for the no bug without glEnd() conundrum, I think put it down to undefined behaviour in a legacy api. If you look at the specifications, the error would actually be generated on the next call to glBegin() but inbetween that, all sorts of things are likely to be happening under the hood.

But obviously ... legacy api ... shouldn't really be using anyway ...