OpenGL and Mouse Lag

opengl

#1

I’m having a tough time resolving some mouse lag when using the OpenGLRenderer to display a simple rectangle on the screen. I’m following the example in the juce demo for doing 2D drawing into the OGL context, and had these results:

Here’s basically what I’m doing:

struct ScrollingRect { int x; int y; int height; };

struct ScrollingComponent : public Component, public OpenGLRenderer, public Timer
{
	OpenGLContext openGLContext;
	ScrollingComponent();
	void timerCallback() override;	//this is the Timer callback
	void renderOpenGL() override;  //this is the OpenGL render callback
 	//a few MouseListener functions and mouseRect updaters go here.
	ScopedPointer<ScrollingRect> mouseRect; 
	std::vector<ScrollingRect> rectsToRender;
};

ScrollingComponent::ScrollingComponent()
{
    openGLContext.setRenderer(this);  
    openGLContext.attachTo(*this);  
    openGLContext.setSwapInterval(0); //as fast as possible
    startTimerHz(100);
}

void ScrollingComponent::timerCallback()
{
	openGLContext.triggerRepaint(); //tell the OS to render an openGL frame. 
}
void ScrollingComponent::mouseEnter(const juce::MouseEvent &event)
{
    mouseRect = new ScrollingRect();
    updateMouseRect(event.getPosition());
}
void ScrollingComponent::mouseExit(const juce::MouseEvent &event)
{
    mouseRect = nullptr;
}
void ScrollingComponent::mouseMove(const juce::MouseEvent &event)
{
    updateMouseRect(event.getPosition()); //capture mouse position and update the rect to be drawn where the cursor is
}
void ScrollingComponent::updateMouseRect(const Point<int> &p)
{
    lastMousePos = p;
    if( mouseRect != nullptr )
    {
        mouseRect->x = p.getX();
        mouseRect->y = p.getY();
        mouseRect->height = getW( mouseRect->y );
    }
}

void ScrollingComponent::mouseDown(const juce::MouseEvent &event)
{
    addMouseRect(event);
}
void ScrollingComponent::addMouseRect(const juce::MouseEvent &e)
{
    ScopedLock sl(updateLock);
    auto y = e.getMouseDownY();
    int w = getW( y );
    w = jmax(w, 5); //at least 10 pix wide

    for( auto& rect : rectsToRender )
    {
        rect.x -= w; //make room for the new one
    }
    rectsToRender.push_back( *mouseRect );
}

//this is the callback that draws the openGL
void ScrollingComponent::renderOpenGL()
{
    // Create an OpenGLGraphicsContext that will draw into this GL window..
    const float desktopScale = openGLContext.getRenderingScale();
    ScopedPointer<LowLevelGraphicsContext> glRenderer (createOpenGLGraphicsContext (openGLContext,
                                                                                    roundToInt (desktopScale * getWidth()),
                                                                                    roundToInt (desktopScale * getHeight())));
    if (glRenderer != nullptr)  //got the LowLevelGraphicsContext
    {
        ScopedLock sl(updateLock);
        Graphics g(*glRenderer); //create a graphics context wrapper we can use to draw into the LowLevelGraphicsContext
        render(g, desktopScale); //draw into the context
    }
}

void ScrollingComponent::render(juce::Graphics &g, float desktopScale)
{
    g.fillAll(Colours::white);
    g.addTransform(AffineTransform::identity.scaled(desktopScale));
    //now you can do whatever you need to do the usual paint(g) way.
    
	//draw some horizontal lines
	g.setColour(Colours::black);
    for( int i = 0; i < 20; ++i )
    {
        if( (i > 3 && i < 7) || (i > 10 && i < 14) )
        {
            g.drawHorizontalLine( getHeight() * i / 20.f, 0, getWidth());
        }
    }
    for( auto it = rectsToRender.begin(); it != rectsToRender.end(); )
    {
        if( it->x + it->height < 0 ) //it's off screen, so remove it 
        {
            it = rectsToRender.erase(it);
        }
        else
        {
            ++it;
        }
    }
    g.setColour(Colours::blue);
    for( auto& rect : rectsToRender )
    {
        rect.x -= 1;	//shift one pixel to the left
        if( rect.x + rect.height > 0 )
        {
            g.drawRect(rect.x, rect.y, rect.height, rect.height); //draw it.
        }
    }
    if( mouseRect != nullptr ) //draw a rect at the mouse cursor
    {
        g.drawRect( mouseRect->x, mouseRect->y, mouseRect->height, mouseRect->height ); 
    }
}

any ideas to get that rectangle that’s following the mouse cursor to not lag?