Need some help getting iPad external display working with OF

Hi folks,

So, I’m looking into using the iPad’s external display feature, as described here:

http://developer.apple.com/iphone/libra-…-70-CH4-SW7

I tested some non-OF demo code from here: http://mattgemmell.com/2010/06/01/ipad-vga-output - and this works fine on the real device as well as the simulator. This example uses two UIWindow objects defined in a nib file.

But when I try doing a similar thing in OF, I never get the external display to appear at all. The attached monitor resolutions are recognised fine, but I either get a blank device screen or the device screen is distorted according to the external display resolution, but either way, never get anything showing on the external display.

My thinking is that it’s to do with the fact that OF’s main view is EAGL and not a simple UIWindow from a nib. In fact, that Apple guide above does say…

Configure the window (by adding views or setting up your OpenGL ES rendering context).

…but I’m not sure what it means there. Is there some context locking/unlocking I need to take care of (GL clueless, me :slight_smile: )…?

Thanks for any advice here!

Bump… anyone any ideas? Anyone run two separate EAGL views in separate windows simultaneously?

I tried to take the code in http://mattgemmell.com/2010/06/01/ipad-vga-output, and put them in ofxiPhoneAppDelegate.mm and ofxiPhoneAppDelegate.h, here is how I modified the (void)alertView.

  • (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
    {
    UIScreenMode *desiredMode = [screenModes objectAtIndex:buttonIndex];
    externalScreen.currentMode = desiredMode;

CGRect rect = CGRectZero;
rect.size = desiredMode.size;

externalWindow = [[UIWindow alloc] initWithFrame:rect];

externalWindow.screen = externalScreen;

[glView removeFromSuperview];

glView = [[EAGLView alloc] initWithFrame:rect pixelFormat:GL_RGB565_OES depthFormat:GL_DEPTH_COMPONENT16_OES preserveBackbuffer:NO];

glView.frame = rect;
glView.bounds = rect;

externalWindow.hidden = NO;

[externalWindow addSubview:glView];

[externalWindow makeKeyAndVisible];

[screenModes release];
[externalScreen release];
}

I used a composite cable, I can manage to get the glView up to my TV, but it is offset to the left and horizontally reduced to ~30%. If i added an UIView instead, it will display properly. I have no clue to this.

Hi pillandpillow,

Thanks for that… I’m trying to give that a go too…

  
[glView removeFromSuperview];  

…here, what’s your glView definition previously?

Did you get the reference by doing something like…

  
EAGLView *glView = ofxiPhoneGetGLView();  

…? Because if I try that then I get no success - blank screen on iPad and nothing sent to the external display at all… :?

Any further work on this? Would love to get VGA out working!

I have got this working with the iPhone and the older private APIs.
I found the trick is to make the device window visible after the external display.

So in the update loop I did this:

  
  
	if(ofGetFrameNum() == 10 ) {  
		[myUIWindow makeKeyAndVisible];					  
	}  

Not sure if this will help with the newer API, but it is worth a shot.

Hi Karl, by private APIs, do you mean the unpublished ones - i.e. Apple will reject usage…?

I got this working a few weeks back but by using someone’s TVOut class. The problem is it uses private api’s which Apple will reject which is totally useless to me. Also, it seemed to dramatically affect the performance and literally halted my app on the iPhone 4! I believe it’s running my app twice, once for each display which causes the performance hit (or it’s at least affecting the memory/vram hard enough…).

Sooo I’m still looking for an acceptable solution that Apple won’t reject and one that won’t affect performance too bad. I wouldn’t mind shutting off the local display while external is active to help with performance.

It works for me too.
But the external view is stretched.
Not sure how to fix it yet. But maybe its a matter of finding the right combination between ofxiPhoneSetOrientation and resolution.

All i did is modify applicationDidFinishLaunching inside ofxiPhoneAppDelegate.mm

  
 -(void) applicationDidFinishLaunching:(UIApplication *)application {      
	  
	//original iPhoneAppDelegte stuff  
	static ofEventArgs voidEventArgs;  
	ofLog(OF_LOG_VERBOSE, "applicationDidFinishLaunching() start");  
	  
	// create an NSLock for GL Context locking  
	glLock = [[NSLock alloc] init];  
	  
	  
	// get screen bounds  
	CGRect screenBounds = [[UIScreen mainScreen] bounds];  
	  
	// create fullscreen window  
	UIWindow *window = [[UIWindow alloc] initWithFrame:screenBounds];  
	  
	// create the OpenGL view and add it to the window  
	glView = [[EAGLView alloc] initWithFrame:screenBounds];// pixelFormat:GL_RGB565_OES depthFormat:GL_DEPTH_COMPONENT16_OES preserveBackbuffer:NO];  
	[window addSubview:glView];  
	//	[glView release];	// do not release, incase app wants to removeFromSuper and add later  
	  
	// make window active  
	[window makeKeyAndVisible];  
	  
	  
	//external window stuff  
	NSLog(@"setup external window");  
	  
	// Check for external screen.  
	if ([[UIScreen screens] count] > 1) {  
		//[self log:@"Found an external screen."];  
		 NSLog(@"Found an external screen.");  
		  
		// Internal display is 0, external is 1.  
		externalScreen = [[[UIScreen screens] objectAtIndex:1] retain];  
		//[self log:[NSString stringWithFormat:@"External screen: %@", externalScreen]];  
		NSLog(@"External screen: %@", externalScreen);  
		  
		screenModes = [externalScreen.availableModes retain];  
		//[self log:[NSString stringWithFormat:@"Available modes: %@", screenModes]];  
		NSLog(@"Available modes: %@", screenModes);  
		/*  
		// Allow user to choose from available screen-modes (pixel-sizes).  
		UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"External Display Size"   
														 message:@"Choose a size for the external display."   
														delegate:self   
											   cancelButtonTitle:nil   
											   otherButtonTitles:nil] autorelease];  
		for (UIScreenMode *mode in screenModes) {  
			CGSize modeScreenSize = mode.size;  
			[alert addButtonWithTitle:[NSString stringWithFormat:@"%.0f x %.0f pixels", modeScreenSize.width, modeScreenSize.height]];  
		}  
		[alert show];  
		*/  
		  
		for (UIScreenMode *mode in screenModes) {  
			  
			//CGSize modeScreenSize = mode.size;  
			  
			//UIScreenMode *desiredMode = mode; //[screenModes objectAtIndex:buttonIndex];  
			externalScreen.currentMode = mode;  
			  
			CGRect rect = CGRectZero;  
			rect.size = mode.size;  
			  
			externalWindow = [[UIWindow alloc] initWithFrame:rect];  
			  
			externalWindow.screen = externalScreen;  
			  
			[glView removeFromSuperview];  
			  
			//glView = [[EAGLView alloc] initWithFrame:rect pixelFormat:GL_RGB565_OES depthFormat:GL_DEPTH_COMPONENT16_OES preserveBackbuffer:NO];  
			glView = [[EAGLView alloc] initWithFrame:rect];  
			  
			glView.frame = rect;  
			glView.bounds = rect;  
			  
			externalWindow.hidden = NO;  
			  
			[externalWindow addSubview:glView];  
			  
			[externalWindow makeKeyAndVisible];  
			  
			[screenModes release];  
			[externalScreen release];  
		}  
		  
		  
		  
	} else {  
		//[self log:@"External screen not found."];  
		  
		 NSLog(@"External screen not found.");  
	}  
  
	  
		  
	  
	//----- DAMIAN  
	// set data path root for ofToDataPath()  
	// path on iPhone will be ~/Applications/{application GUID}/openFrameworks.app/data  
	// get the resource path for the bundle (ie '~/Applications/{application GUID}/openFrameworks.app')  
	NSString *bundle_path_ns = [[NSBundle mainBundle] resourcePath];  
	// convert to UTF8 STL string  
	string path = [bundle_path_ns UTF8String];  
	// append data  
	//path.append( "/data/" ); // ZACH  
	path.append( "/" ); // ZACH  
	ofLog(OF_LOG_VERBOSE, "setting data path root to " + path);  
	ofSetDataPathRoot( path );  
	//-----  
	  
  
	animating = FALSE;  
	displayLinkSupported = FALSE;  
	animationFrameInterval = 1;  
	displayLink = nil;  
	animationTimer = nil;  
	  
	// A system version of 3.1 or greater is required to use CADisplayLink. The NSTimer  
	// class is used as fallback when it isn't available.  
	NSString *reqSysVer = @"3.1";  
	NSString *currSysVer = [[UIDevice currentDevice] systemVersion];  
//	if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending) displayLinkSupported = TRUE;  
  
	  
	externalWindow.hidden = NO; //YES;  
	  
	  
	iPhoneSetOrientation(OFXIPHONE_ORIENTATION_PORTRAIT);  
	  
  
	// call testApp::setup()  
	ofGetAppPtr()->setup();  
  
	#ifdef OF_USING_POCO  
		ofNotifyEvent( ofEvents.setup, voidEventArgs );  
		ofNotifyEvent( ofEvents.update, voidEventArgs );  
	#endif  
	  
	  
	// show or hide status bar depending on OF_WINDOW or OF_FULLSCREEN  
	[[UIApplication sharedApplication] setStatusBarHidden:(iPhoneGetOFWindow()->windowMode == OF_FULLSCREEN) animated:YES];  
	  
	// clear background  
	glClearColor(ofBgColorPtr()[0], ofBgColorPtr()[1], ofBgColorPtr()[2], ofBgColorPtr()[3]);  
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
	  
    // Listen to did rotate event  
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];  
    [[NSNotificationCenter defaultCenter] addObserver: self   
                                             selector: @selector(receivedRotate:)   
                                                 name: UIDeviceOrientationDidChangeNotification   
                                               object: nil];    
	  
}  

and added modified ofxiPhoneAppDelegate.h to this

  
@interface ofxiPhoneAppDelegate : NSObject <UIApplicationDelegate> {  
	NSTimer				*animationTimer;  
    BOOL				animating;  
    BOOL				displayLinkSupported;  
    NSInteger			animationFrameInterval;  
    id					displayLink;  
	  
	EAGLView			*glView;  
  
	NSLock				*glLock;  
	  
	  
	UIWindow *deviceWindow;  
	UITextView *consoleTextView;  
	UIWindow *externalWindow;  
	NSArray *screenModes;  
	UIScreen *externalScreen;  
	  
}  
  
  
  
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url;  
-(void) receivedRotate:(NSNotification*)notification;  
-(void) setFrameRate:(float)frameRate;  
-(EAGLView*) getGLView;  
  
-(void)lockGL;  
-(void)unlockGL;  
  
@end  

i am using of_preRelease_v0062_iphone_FAT.

now this works. (had to set my ipod to not use the widescreen mode)

but now i am trying to use memo’s MSAShape3D , of FBO.
Using MSAShape3D compiles and runs but the 3d cylinder always shows the close and the far side of the cylinder.

so i thought i would render everything in an FBO and draw the FBO, but that does not work either. again it compiles and runs but nothing gets drawn.

does anyone know why?

thanks,
stephan.