#include <csetjmp>
#include <unistd.h>

#if defined(__APPLE__)
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif

#include "Halide.h"
#include "HalideRuntimeOpenGL.h"

std::string error_message;

/*
** Don't rely on func.set_error_handler() mechanism, it doesn't seem to catch
** the user OpenGL state errors. That might be a separate bug.
*/
jmp_buf env;
void on_sigabrt (int signum)
{
  longjmp (env, 1);
}
void catching_stderr_abort(std::function<void ()> func)
{
    auto ferr = tmpfile();
    auto prev_stderr = dup(2);
    dup2(fileno(ferr), 2);
    if (setjmp (env) == 0) {
        auto prev_handler = signal(SIGABRT, &on_sigabrt);
        (func)();
        signal(SIGABRT, prev_handler);
    }
    fseek(ferr, 0, SEEK_END);
    error_message.resize(ftell(ferr));
    rewind(ferr);
    fread(&error_message[0], 1, error_message.size(), ferr);
    dup2(prev_stderr, 2);
    close(prev_stderr);
}

using namespace Halide;

int main()
{
    // This test must be run with an OpenGL target
    const Target &target = get_jit_target_from_environment();
    if (!target.has_feature(Target::OpenGL))  {
        fprintf(stderr,"ERROR: This test must be run with an OpenGL target, e.g. by setting HL_JIT_TARGET=host-opengl.\n");
        return 1;
    }

    Image<uint8_t> output(255, 10, 3);

    Var x, y, c;
    Func g;
    g(x, y, c) = Halide::cast<uint8_t>(255);
    g.bound(c, 0, 3);
    g.glsl(x, y, c);

    // Let Halide initialize OpenGL
    g.realize(output);

    // Bad OpenGL call leaves OpenGL in a bad state
    glEnableVertexAttribArray(-1);

    // Halide should report that the OpenGL context is in a bad state due to user code`
    catching_stderr_abort( [&] () { g.realize(output); } );

    if (error_message.empty()) {
        fprintf(stderr, "Failed to report error in user OpenGL state\n");
        return 1;
    }
    else if (error_message.find("user OpenGL state") == std::string::npos) {
        error_message.erase(error_message.size() - 1); // remove trailing newline
        fprintf(stderr, "Reported error '%s' rather than identifying error at 'user OpenGL state'\n", error_message.c_str());
        return 1;
    }

    printf("Success!\n");
    return 0;
}

Add (failing) test that halide reports user error when called with OpenGL in bad state
Add (failing) test that halide reports user error when called with OpenGL in bad state


Former-commit-id: 13abd3bb083e4133aecc5d6ad0fbadab8abfe085