OpenGL M1 - GL_INVALID_OPERATION - using glGenVertexArrays

Hi,

I’m just moving some code from another mac with Juce6 to m1 mac with Juce 7.

Are there breaking changes with glGenVertexArrays in Juce 7.0.2?

I’ve isolated the problem down to glGenVertexArrays, this is the line that triggers the GL_INVALID_OPERATION.

The debug messages seem a bit useless to find the issue.

using either way openGLContext.extensions.glGenVertexArrays(1, &VAO);

or with ::juce::gl, the same things happens: “GL_Invalid_Operation.”

glGenVertexArrays(1, &VAO);

It’s not an invalid op, it’s worked before, and it’s in the gl namespace.

I’m using just Juce v7.0.2.

The entire code is:
cpp:

#include "ViewGL.h"

ViewGL::ViewGL()
    {
    using namespace ::juce::gl;
    setOpaque (true);

    if (auto* peer = getPeer())
        peer->setCurrentRenderingEngine (0);

    openGLContext.setRenderer(this);
    openGLContext.attachTo(*this);
    //openGLContext.setContinuousRepainting(true);
    setSize(400, 300);
}


ViewGL::~ViewGL()
{
    openGLContext.detach();
}


void ViewGL::newOpenGLContextCreated()
{
    using namespace ::juce::gl;
    compileOpenGLShaderProgram();
    vertices = ShapeVertices::generateTriangle();
    // Generate opengl vertex objects 
    openGLContext.extensions.glGenVertexArrays(1, &VAO); // Vertex Array Object
    // How/why does it screw up on this line above?
    
//       openGLContext.extensions.glGenBuffers (1, &VBO);     // Vertex Buffer Object
}

void ViewGL::renderOpenGL()
{
//        using namespace ::juce::gl;
//        jassert (OpenGLHelpers::isContextActive());
//        // Scale viewport
//        const float renderingScale = (float) openGLContext.getRenderingScale();
//        juce::gl::glViewport (0, 0, roundToInt (renderingScale * getWidth()), roundToInt(renderingScale * getHeight()));
//
//        shaderProgram->use();
//
//        openGLContext.extensions.glBindVertexArray(VAO);
//        juce::gl::glDrawArrays (juce::gl::GL_TRIANGLES, 0, (int) vertices.size());
//        openGLContext.extensions.glBindVertexArray (0);
}

void ViewGL::openGLContextClosing()
{
    
}

void ViewGL::paint (juce::Graphics& g)
{
}

void ViewGL::resized ()
{
    draggableOrientation.setViewport (getLocalBounds());
}

void ViewGL::handleAsyncUpdate()
{
}
// OpenGL Related Member Functions =============================================
void ViewGL::compileOpenGLShaderProgram()
{
    using namespace ::juce::gl;
    
    std::unique_ptr<OpenGLShaderProgram> shaderProgramAttempt
        = std::make_unique<OpenGLShaderProgram> (openGLContext);
    
    if (shaderProgramAttempt->addVertexShader ({ BinaryData::BasicVertex_glsl })
        && shaderProgramAttempt->addFragmentShader ({ BinaryData::mainShader1_glsl })
        && shaderProgramAttempt->link())
    {
        shaderProgram.reset (shaderProgramAttempt.release());
    }

    triggerAsyncUpdate(); // Update status text
}

.h:

#pragma once
#include <JuceHeader.h>
#include "OpenGLUtil/OpenGLUtil.h"
#include "ShapeVertices.hpp"


class ViewGL : public Component,
               public OpenGLRenderer,
               private AsyncUpdater
{
public:
    ViewGL ();
    ~ViewGL();

void newOpenGLContextCreated() override;
void renderOpenGL() override;
void openGLContextClosing() override;

void paint (Graphics& g) override;
void resized () override;
void handleAsyncUpdate() override;
private:

void compileOpenGLShaderProgram();

// Create an OpenGLContext for this Component.
juce::OpenGLContext openGLContext;
std::unique_ptr<OpenGLShaderProgram> shaderProgram;

GLuint VAO;
GLuint VBO;
std::vector<Vector3D<GLfloat>> vertices;
// GUI Mouse Drag Interaction
Draggable3DOrientation draggableOrientation;
};

Shader code:

void main()
{
    vec3 col = vec3(1.0,0.0,0.0);
    gl_FragColor = vec4(col,1.0);
}

pluginEditor.h:

#pragma once

#include <JuceHeader.h>

#include "PluginProcessor.h"

#include "ViewGL.h"

class OpenGL2DAudioProcessorEditor : public juce::AudioProcessorEditor

{

public:

OpenGL2DAudioProcessorEditor (OpenGL2DAudioProcessor&);

~OpenGL2DAudioProcessorEditor() override;

void paint (juce::Graphics&) override;

void resized() override ;

private :

// This reference is provided as a quick way for your editor to

// access the processor object that created it.

OpenGL2DAudioProcessor& audioProcessor;

ViewGL viewGL;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR 
(OpenGL2DAudioProcessorEditor)

};

and editor.cpp:

#include "PluginProcessor.h"
#include "PluginEditor.h"

OpenGL2DAudioProcessorEditor::OpenGL2DAudioProcessorEditor 
(OpenGL2DAudioProcessor& p)
    : AudioProcessorEditor (&p), audioProcessor (p)
{
// Make sure that before the constructor has finished, you've set the
// editor's size to whatever you need it to be.
addAndMakeVisible(viewGL);

setSize (400, 300);
}

OpenGL2DAudioProcessorEditor::~OpenGL2DAudioProcessorEditor()
{
}

void OpenGL2DAudioProcessorEditor::paint (juce::Graphics& g)
{

}

void OpenGL2DAudioProcessorEditor::resized()
{
viewGL.setBounds(0, 0, 400, 300);
// This is generally where you'll want to lay out the positions of any
// subcomponents in your editor..
}

There’s also errors just above the checkGLError:

Any heads up would be great on this.

glGenVertexArrays is only supported from OpenGL 3.0 onwards. My guess is that the new mac is defaulting to a Compatibility profile (with a version of 2.1), rather than a core profile (with a version of 3.2 or higher).

If you need a specific kind of GL context, you should request it explicitly with OpenGLContext::setOpenGLVersionRequired.

2 Likes

I think that might have worked, it’s not crashing, thank you so much for answering on a SUNDAY!! Jebus, thank you so much honestly.

Any one else who has an issue with M1 ARM mac’s with OpenGL and Juce (Writing for search engine pick up) the solution is to use openGLContext.setOpenGLVersionRequired(juce::OpenGLContext::openGL3_2);

In the constructor for your openGL component class.

That was actually frightening me! Absolute saviour <3

2 Likes