OpenGL on Retina


#1

I’m slowly coming to the conclusion that the only way to get fast Graphics on the Retina MBP is using the OpenGL renderer. The only problem is that right now, it’s resolution is never the Retina resolution, but half of it in all directions.

I’ve found some docs that explain how to adapt OpenGL apps to using Retina displays:
http://developer.apple.com/library/mac/#documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/CapturingScreenContents/CapturingScreenContents.html

In juce_OpenGL_osx.h, I added at end of ThreadSafeNSOpenGLViewClass::init()

which results in a 2x smaller JUCE image (and the other 3/4 quarter of the display area will be messed up).
I can’t seem to get any further but I’m sure that Jules could advise me where to head next.


#2

Well, that turned out to be a massive PITA to do, but it’s checked in now if you want to try it!


#3

This agrees with what they were saying in the #Macdev channel.


#4

It works! Very nice! Only the fonts look much less good than with the CoreGraphics renderer, the rest seems pretty much the same.


#5

I’ve tried the Juce Demo application from the latest tip on a third generation iPad, thus with retina display.

When using the software renderer, everything is fine: components are rendered at high resolution taking advantage of the retina display and their showing size on the screen is correct: all the window fits inside the screen.

When I enable the opengl renderer for the components, the whole window doubles its size (i.e. approximately only the lower left quarter is visible in the iPad screen). Maybe the same changes (or similar) that were needed for OSX on the MBP are needed on iOS for the opengl rendering to be correct?


#6

You probably meant “CoreGraphics renderer”, not software renderer. I suppose the same changes must also be done for OpenGL to work on Retina iPads, yes.


#7

Hmm, the menu listed only two alternatives that were “Software Renderer” and “OpenGL Renderer”, I’ve double checked it now, but honestly didn’t dig into the code to see if the software renderer in this case refers to the one that uses coregraphics, in opposition to the other that uses OpenGL


#8

(using latest tip)

It seems that this change has broken OpenGL components using OpenGLContext::setComponentPaintingEnabled(false).

OpenGLContext::CachedImage::updateViewportSize is being called by CachedImage::paintComponent which only gets invoked when component painting is enabled, so it never gets called if component painting is disabled…

Cheers, Yair


#9

[quote=“yairadix”](using latest tip)

It seems that this change has broken OpenGL components using OpenGLContext::setComponentPaintingEnabled(false).

OpenGLContext::CachedImage::updateViewportSize is being called by CachedImage::paintComponent which only gets invoked when component painting is enabled, so it never gets called if component painting is disabled…

Cheers, Yair[/quote]

What platform is that? I tried setting that flag in the juce demo, but it still ran perfectly well on both normal and high DPI displays… (?)


#10

Ok, it seems to take more conditions than what I described before to happen. I now tried doing that in the juce demo as well and it works fine there. (OS X btw, 10.8 & 10.6)

But it does reproduce when doing this:

In the juce demo plugin, add:

class AnOpenGLThingy : public Component, public OpenGLRenderer {
public:
    AnOpenGLThingy();
    void paint (Graphics&) {}
    void newOpenGLContextCreated() {}
    void openGLContextClosing() {}
    void renderOpenGL();

    OpenGLContext openGLContext;
};

...

    Slider delaySlider;
+    AnOpenGLThingy thing;
    ScopedPointer<ResizableCornerComponent> resizer;

...

AnOpenGLThingy::AnOpenGLThingy() {
    openGLContext.setRenderer (this);
    openGLContext.setComponentPaintingEnabled (true);
    openGLContext.attachTo(*this);
}

void AnOpenGLThingy::renderOpenGL() {
    glBegin(GL_TRIANGLES);
    glColor3ub(255, 0, 0);
    glVertex2d(-1, -1);
    glVertex2d(1, -1);
    glVertex2d(-1, 1);
    glColor3ub(0, 255, 0);
    glVertex2d(1, -1);
    glVertex2d(-1, 1);
    glVertex2d(1, 1);
    glEnd();
}

...

     resizeLimits.setSizeLimits (150, 150, 800, 300);
 
+    addAndMakeVisible(&thing);
+
     // set our component's initial size to be the last one that was stored in the filter's settings

...

     delaySlider.setBounds (200, 60, 150, 40);
+    thing.setBounds(50, 50, 50, 50);

When changing AnOpenGLThingy to use

openGLContext.setComponentPaintingEnabled (false);

It does not paint properly anymore.
Reproduced when running in JUCE’s demo host, AU Lab & Logic.

It seems that it doesn’t happen in JuceDemo because updateViewportSize is also called by when the component is being resized and it seems that this always happen when it’s inside a DocumentWindow, while it doesn’t necessarily happen inside a plugin window.


#11

Hmm, it might just be the order in which things are added. Does this help, in juce_OpenGLContext.cpp at line 479 ?

void attach() { Component& comp = *getComponent(); CachedImage* const newCachedImage = new CachedImage (context, comp, context.pixelFormat, context.contextToShareWith); comp.setCachedComponentImage (newCachedImage); newCachedImage->start(); // (must wait until this is attached before starting its thread) newCachedImage->updateViewportSize (true); }


#12

Yep, this seems to make it work!
Cheers, Yair