I don’t even know what happened. I’ve created a veritable abomination. This devil code is completely beyond me. I’ve been digging through GDB and Valgrind for hours, but nothing is helping me figure out what I did wrong.
Anyways, on to the actual problem. I’ve only included the code that is run during initialization (which I’m pretty sure is the culprit) but I’ll post a copy of my whole codebase if it isn’t. What first caught my attention was that valgrind was reporting thousands of invalid write operations from OpenGL.
This is the first occurrence.
==22432== Invalid write of size 4
==22432== at 0xA1FD38C: brw_emit_pipe_control (brw_pipe_control.c:197)
==22432== by 0xA1FC060: brw_emit_select_pipeline (brw_misc_state.c:461)
==22432== by 0xA1FC25E: brw_upload_invariant_state (brw_misc_state.c:545)
==22432== by 0xA2034BB: brw_upload_initial_gpu_state (brw_state_upload.c:63)
==22432== by 0xA2034BB: brw_init_state (brw_state_upload.c:186)
==22432== by 0xA1F2923: brwCreateContext (brw_context.c:1017)
==22432== by 0xA1B570B: driCreateContextAttribs (dri_util.c:479)
==22432== by 0x7F1350B: ??? (in /usr/lib/x86_64-linux-gnu/libEGL_mesa.so.0.0.0)
==22432== by 0x7F0BC2A: eglCreateContext (in /usr/lib/x86_64-linux-gnu/libEGL_mesa.so.0.0.0)
==22432== by 0x113C50: glesSetupOpenGLES() (window.cpp:72)
==22432== by 0x112EA0: main (main.cpp:69)
==22432== Address 0x7fe384c99004 is not stack'd, malloc'd or (recently) free'd
==22390== Invalid write of size 4
==22390== at 0xA448010: GEN75_3DSTATE_SBE_pack (gen75_pack.h:4652)
==22390== by 0xA448010: blorp_emit_sf_config (blorp_genX_exec.h:665)
==22390== by 0xA448010: blorp_emit_pipeline (blorp_genX_exec.h:1200)
==22390== by 0xA448B7C: blorp_exec (blorp_genX_exec.h:1617)
==22390== by 0xA448B7C: gen75_blorp_exec (genX_blorp_exec.c:284)
==22390== by 0xA424FBC: blorp_fast_clear (blorp_clear.c:337)
==22390== by 0xA1EA1F9: do_single_blorp_clear (brw_blorp.c:1267)
==22390== by 0xA1EC1CF: brw_blorp_clear_color (brw_blorp.c:1333)
==22390== by 0xA1EEEFB: brw_clear (brw_clear.c:297)
==22390== by 0x113D97: glesSetupOpenGLES() (window.cpp:82)
==22390== by 0x112EA0: main (main.cpp:69)
==22390== Address 0x7f364a822300 is not stack'd, malloc'd or (recently) free'd
But wait, there’s more. If I run it without valgrind, the window pops up and then my entire desktop crashes on that screen. HDMI cord isn’t even outputting a signal anymore. It comes back if I logout or change the display settings, but it’s fairly catastrophic. But there are NO error codes or segfaults in the actual program. My best guess is that I somehow configured OpenGL to buffer overflow and corrupt active memory. But I can’t for the life of me figure out why. Oh, I should also mention that it only crashes the desktop sometimes, regardless of code changes. Please help me!
glesCheckOpenGL() is just a macro to throw an error if glGetError returns
glesAssert() is just checking the condition
GLES Initialization Routine
static EGLDisplay eglDisplay;
static EGLSurface eglSurface;
static EGLContext eglContext;
static EGLNativeWindowType eglNativeWindow;
static EGLNativeDisplayType eglNativeDisplay;
void glesSetupOpenGLES() {
EGLBoolean result;
EGLConfig config;
EGLint majorVersion;
EGLint minorVersion;
EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE,
EGL_NONE};
result = eglBindAPI(EGL_OPENGL_ES_API);
glesAssert(result != EGL_FALSE, "Cannot Bind API");
glesCreateWindow(eglNativeWindow, eglNativeDisplay);
eglDisplay = eglGetDisplay(eglNativeDisplay);
if (eglDisplay == EGL_NO_DISPLAY) throw gles_error("Cannot Get Display");
glesCheckOpenGL("");
// Initialize EGL
result = eglInitialize(eglDisplay, &majorVersion, &minorVersion);
if (EGL_FALSE == result) throw gles_error("Cannot Initialize EGL");
glesCheckOpenGL("");
{
EGLint numConfigs = 0;
EGLint attribList[] = {
EGL_RED_SIZE, 6,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 6,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 16, // You need this line for depth buffering to work
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE};
// Get configs
result = eglGetConfigs(eglDisplay, NULL, 0, &numConfigs);
glesAssert(result != EGL_FALSE, "Cannot Get Configs");
// Choose config
result =
eglChooseConfig(eglDisplay, attribList, &config, 1, &numConfigs);
if (EGL_FALSE == result) throw gles_error("Cannot Choose Config");
if (numConfigs < 1) throw gles_error("No Valid Configurations");
}
glesCheckOpenGL("");
// Create a surface
eglSurface =
eglCreateWindowSurface(eglDisplay, config, eglNativeWindow, NULL);
if (eglSurface == EGL_NO_SURFACE)
throw gles_error("Cannot Create Window Surface");
glesCheckOpenGL("");
// Create a GL context
eglContext =
eglCreateContext(eglDisplay, config, EGL_NO_CONTEXT, contextAttribs);
if (eglContext == EGL_NO_CONTEXT) throw gles_error("Cannot Create Context");
glesCheckOpenGL("");
// Make the context current
result = eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
if (EGL_FALSE == result) throw gles_error("Cannot Assign Content");
glesCheckOpenGL("");
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, 240, 320);
glesCheckOpenGL("");
}
The window routine is separate because I have another file which creates a window on a Raspberry PI without X11. The X11 version is really just so I can test and iterate on my desktop.
X11 Window Routine
// X11 related local variables
static Display *x_display = NULL;
static Atom s_wmDeleteMessage;
void glesCreateWindow(EGLNativeWindowType &eglNativeWindow, EGLNativeDisplayType &eglNativeDisplay)
{
Window root;
XSetWindowAttributes swa;
XSetWindowAttributes xattr;
Atom wm_state;
XEvent xev;
EGLConfig ecfg;
EGLint num_config;
Window win;
/*
* X11 native display initialization
*/
x_display = XOpenDisplay(NULL);
if (x_display == NULL)
throw gles_error("Cannot Open X Display");
root = DefaultRootWindow(x_display);
swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask;
win = XCreateWindow(
x_display, root,
0, 0, 240, 320, 0,
CopyFromParent, InputOutput,
CopyFromParent, CWEventMask,
&swa);
s_wmDeleteMessage = XInternAtom(x_display, "WM_DELETE_WINDOW", 0);
XSetWMProtocols(x_display, win, &s_wmDeleteMessage, 1);
xattr.override_redirect = 0;
XChangeWindowAttributes(x_display, win, CWOverrideRedirect, &xattr);
XWMHints hints;
hints.input = 1;
hints.flags = InputHint;
XSetWMHints(x_display, win, &hints);
XSizeHints shints;
shints.min_width = 240;
shints.min_height = 320;
shints.min_aspect.x = 3;
shints.min_aspect.y = 4;
shints.max_aspect.x = 3;
shints.max_aspect.y = 4;
shints.flags = PMinSize | PAspect;
XSetWMNormalHints(x_display, win, &shints);
// make the window visible on the screen
XMapWindow(x_display, win);
XStoreName(x_display, win, "PrintrbotUI");
// get identifiers for the provided atom name strings
wm_state = XInternAtom(x_display, "_NET_WM_STATE", 0);
memset(&xev, 0, sizeof(xev));
xev.type = ClientMessage;
xev.xclient.window = win;
xev.xclient.message_type = wm_state;
xev.xclient.format = 32;
xev.xclient.data.l[0] = 1;
xev.xclient.data.l[1] = 0;
XSendEvent(
x_display,
DefaultRootWindow(x_display),
0,
SubstructureNotifyMask,
&xev);
eglNativeWindow = (EGLNativeWindowType)win;
eglNativeDisplay = (EGLNativeDisplayType)x_display;
}