Retina support & size in main.mm ??

Hi there,
I’m looking for the best way to handle retina support

The only way I tested is:

  
ofAppiPhoneWindow * iOSWindow = new ofAppiPhoneWindow();  
	ofSetupOpenGL(iOSWindow, 1024, 768, OF_FULLSCREEN);			// <-------- setup the GL context    
        iOSWindow->enableRetinaSupport();  
  

but is it the best practice ?

Considering the nice answer I had here:
http://forum.openframeworks.cc/t/how-to-find-which-device-runs-the-app-/9184/7
it seems I’d be able to test the device & thus the resolution.

So, should I feed ofSetupOpenGL(iOSWindow, 1024, 768, OF_FULLSCREEN); with the resolution of the device’s screen in main.mm ?

Is it the best thing to do?

And about iOSWindow->enableRetinaSupport() ?

I did that, but no hardware to test today.
Does it make sense ?

  
#include "ofMain.h"  
#include "testApp.h"  
  
int main(){  
      
    BOOL isRetina, isiPad;  
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];    
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {    
        if ([[UIScreen mainScreen] scale] > 1)    
            isRetina = true;    
    }    
      
    if ([[UIDevice currentDevice] respondsToSelector:@selector(userInterfaceIdiom)])    
        if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)    
            isiPad = true;    
      
    [pool release];  
      
    int width;  
    int height;  
      
      
    if (isRetina && isiPad){  
        width = 1536;  
        height = 2048;  
    }  
    else if (!isRetina && !isiPad){  
        width = 320;  
        height = 480;  
    }  
    else if (isRetina && !isiPad){  
        width = 640;  
        height = 960;  
    }      
    else if (!isRetina && isiPad){  
        width = 768;  
        height = 1024;  
    }  
      
      
    ofAppiPhoneWindow * iOSWindow = new ofAppiPhoneWindow();  
      
	ofSetupOpenGL(iOSWindow, width, height, OF_FULLSCREEN);  
    iOSWindow->enableRetinaSupport();  
      
	ofRunApp(new testApp);  
}  

anyone?

this seems to detect correctly on my iPad3, but setting the width and height in this way doesn’t seem to affect the app properly. ofGetWidth() and ofGetHeight() still report 768x1024.

Hi and thanks for your answer & test :slight_smile:

I found that, which combines also objC.
I’ll do it in setup of ALL my app, I guess to make them universal.
I can conditionally setup some assets in the setup().

  
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)  
    {  
        if ([UIScreen instancesRespondToSelector:@selector(scale)])   
        {  
            CGFloat scale = [[UIScreen mainScreen] scale];  
              
            if (scale > 1.0)   
            {  
                // isPad Retina  
            }  
              
            else  
            {  
                // isIpad 1 or 2  
            }  
        }  
    }  
    else {  
    if ([UIScreen instancesRespondToSelector:@selector(scale)])   
        {  
            CGFloat scale = [[UIScreen mainScreen] scale];  
              
            if (scale > 1.0)   
            {  
                // iPhone Retina  
            }  
              
            else  
            {  
                // iPhone  
            }  
}  

But I’d have a question…
In main.mm, doing that:

  
	iOSWindow->enableRetinaSupport();  
	ofSetupOpenGL(iOSWindow,768,1024, OF_FULLSCREEN);  

How the width & height are used by the openGL window ?
I mean, should I test stuff in main.mm too to put correct values to ofSetupOpenGL ? or ?

Some progress…looking at the ofSetupOpenGL method, we find :

  
/******** Initialization methods ************/  
  
void ofAppiPhoneWindow::setupOpenGL(int w, int h, int screenMode) {  
	ofLog(OF_LOG_VERBOSE, "ofAppiPhoneWindow::setupOpenGL()");  
	  
	windowMode = screenMode;	// use this as flag for displaying status bar or not  
  
	ofDisableTextureEdgeHack();  
	  
	  
	// w & h are ignored, currently Apple don't allow windows which aren't fullscreen  
	// DO NOTHING ELSE, opengl will be setup by the app which creates an opengl view  
}  
  

So, passing w & h doesn’t make a difference here.

the getWindowSize() method (which is called by getWidth and getHeight) does have some logic to test whether Retina support is enabled, and double the returned output if it is, but it makes a call to multiply the screen size by [[UIScreen mainscreen] scale], which is set to 1 even after calling enableRetinaSupport. So perhaps we need to find out how to make sure this ‘scale’ property is set to 2?

  
  
// return cached size, read if nessecary  
ofPoint	ofAppiPhoneWindow::getWindowSize() {  
	if(windowSize.x == NOT_INITIALIZED) {  
		CGSize s = [[[UIApplication sharedApplication] keyWindow] bounds].size;  
		windowSize.set(s.width, s.height, 0);  
  
		if(retinaEnabled)  
			if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)])  
				windowSize*=[[UIScreen mainScreen] scale];  
	}  
  
	return windowSize;  
}  
  

the code I posted worked fine (as far as I tested on my real devices…)
it was the big thing of this weekend and I have to thank Seth too here :slight_smile:

when you call getScreenSize() on your iOSWindow, it returns the multiplied sizes? Not getting that on my end.

I don’t call it.

I only use that :

  
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)  
    {  
        if ([UIScreen instancesRespondToSelector:@selector(scale)])   
        {  
            CGFloat scale = [[UIScreen mainScreen] scale];  
              
            if (scale > 1.0)   
            {  
                // isPad Retina  
            }  
              
            else  
            {  
                // isIpad 1 or 2  
            }  
        }  
    }  
    else {  
    if ([UIScreen instancesRespondToSelector:@selector(scale)])   
        {  
            CGFloat scale = [[UIScreen mainScreen] scale];  
              
            if (scale > 1.0)   
            {  
                // iPhone Retina  
            }  
              
            else  
            {  
                // iPhone  
            }  
}  

in setup() only
loading some assets conditionally and it makes my app universal
(btw, the app using it is: http://julienbayle.net/2012/03/17/my-first-app-on-app-store)

I found the issue in my setup. The OS Deployment target has to be 5.1 in order for the scale to read greater than 1.0 on the iPad. Once I set my project and target to deploy on iOS 5.1, the scale read properly as 2.

Does that means you’d have to release with a minimum requirement of 5.1 for iPad 3s to see the retina graphics? Or do you just set the sdk to use 5.1 but the target can be lower?

This method only works if the actual target is 5.1, which means anyone below that OS would not be able to use it. You could work around it for now by detecting the device type and doing your scaling manually…

Ok, that’s interesting to know. Setting a target of 5.1 wouldn’t be ideal for a AppStore release yet since there’s still a lot of people on iOS4.

yes interesting to know.

http://itunes.apple.com/us/app/mobile-particles/id509804829?mt=8 has been released … for 5.1 which was a little mistake.
I should maybe upload the 4.x version of the app which would be strange, but more compatible :stuck_out_tongue:

Good News, Everyone!

I’ve got retina display support working on iOS 4.2!

The bad news is that I have no idea what I changed that did it. I had an NSLog in my main.mm that reported the screen size that I never commented out. It had always displayed “1.000000”, and I just noticed while debugging today that it was properly detecting “2.000000” on my iPad 3 while targeting iOS 4.2. But I’ve done so much work in the last week that I couldn’t say for sure what fixed it. I did switch from LLVM GCC to pure LLVM compiling, but I thought I’d checked that before. I’ll post again if I figure out what changed.

Glad it’s working. If you figure out what did it, definitely let us know! :smiley:

I was having issues with this.

It seemed that sometimes I would randomly build a retina executable but most times it wouldn’t. This happen when I had to “rebuild the world”. I think it was happening when I was hitting build without the iPad plugged in, so it would build for “IOS Device”, which must have been defaulting to a 5.1 deployment target (or more likely defaulting to latest available).

After reading this thread, I changed both my project (Info->iOS Deployment Target) and build target (Summary->Deployment Target) to “5.1”. I’ve done two clean&build’s and its been at full iPad 3 resolution both times. So I guess thats fixed it.

The option “5.1” wasn’t actually in the drop down (topped out at 5.0), so I just added it manually. I’m pretty sure this is because I’m running Snow Leopard with the 5.1 SDK manually installed, so my Xcode internals haven’t been updated. The option should be there if you’re on Lion with the latest Xcode.

Not a whole lot of news, but maybe something helpful:

This project has two schemes named the same thing. When I launch the first one, it creates a non-retina version, and the second one creates a retina version. Always.

As with Soup, I’m working with Snow Leopard with a manually-injected 5.1 SDK as I’m not ready to update this machine to Lion yet. Maybe it has something to do with that. Does anyone else get two identical schemes for the same device?

This one is exclusively one of most efficient discussion to solve the problem. As I have found the extreme coding of way about Retina Support from this source. Thanks for sharing some most elegant information for me.

hi all…

can someone who owns an ipad3 please tell us if this code detects the device??

to do this please return the ofGetWidth() or ofGetHeight()

I made the 2 BOOL for retina and ipad external and global so that they can be used in the whole project if needed…

the way I am going to approach this is I will replace all ofGetWidth() & height with 320,480 and then scale the whole project up by doing something like :

in the testapp.mm:

#include “Globals.h”

float width,height;

if (isRetina && isiPad){
//load stuff imgs etc

width = 1536/320;
height = 2048/480;
}
else if (!isRetina && !isiPad){
width = 1;
height = 1;
}
else if (isRetina && !isiPad){
width = 640/320;
height = 960/480;
}
else if (!isRetina && isiPad){
width = 768/320;
height = 1024/480;
}

ofScale(width,height);

(in the draw)

I think this is the best way to transform an app from 320 to all scales

note that if you load an hd image 500X500 and draw it lets say img.draw(0,0,10,10)

and then scale it

ofScale(12,12);

it will draw it in hd without pixels…

so in most cases just replace the image you load using the bool and load an hd…

(I havent reallly checked it on a device but i think it works… because scale is just multiplying the pixels)

  
  
///Globals.h\\\  
  
#ifndef Butterfly_Globals_h  
#define Butterfly_Globals_h  
  
extern BOOL isRetina, isiPad;    
  
  
  
#endif  
  
  

  
  
  
//  
//  Globals.mm  
  
#include <iostream>  
  
BOOL isRetina, isiPad;    
  
  

  
  
#include "ofMain.h"  
#include "testApp.h"  
#include "Globals.h"  
  
  
int main(){  
  
      
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];      
     if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {      
     if ([[UIScreen mainScreen] scale] > 1)      
     isRetina = true;      
     }      
       
     if ([[UIDevice currentDevice] respondsToSelector:@selector(userInterfaceIdiom)])      
     if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)      
     isiPad = true;      
       
    if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad && [[UIScreen mainScreen] respondsToSelector:@selector(scale)] && [UIScreen mainScreen].scale > 1)  
    {  
        isRetina = true;  
        isiPad = true;      
          
    }  
      
     [pool release];    
       
     int width;    
     int height;    
       
       
     if (isRetina && isiPad){    
     width = 1536;    
     height = 2048;    
     }    
     else if (!isRetina && !isiPad){    
     width = 320;    
     height = 480;    
     }    
     else if (isRetina && !isiPad){    
     width = 640;    
     height = 960;    
     }        
     else if (!isRetina && isiPad){    
     width = 768;    
     height = 1024;    
     }    
       
       
     ofAppiPhoneWindow * iOSWindow = new ofAppiPhoneWindow();    
       
     ofSetupOpenGL(iOSWindow, width, height, OF_FULLSCREEN);    
     iOSWindow->enableRetinaSupport();    
       
     ofRunApp(new testApp);   
       
       
}  
  

I can test it on ipod retina on iphone and on normal ipad and it works… but I don’t have an ipad3…