Hi All,
I am developing an application that needs to render portions of a single
composition across multiple displays attached to a single machine. My approach
is to create one renderer for each display and drive them "in parallel" with
displayLinks. My QCRenderer subclass works fine when rendering to system with
only one display, however when two displays are attached to the system, it
appears as though all rendering is done on the main screen (where the menubar
is located). Has anyone had this experience before? What are the possible
causes for this situation?
My code is based on the old source code from Quartz Composer Visualizer and is
the relevant portions are attached below. Basically, I create a QCRenderer
with info specific to my app, then I drive the rendering process using a
displayLink. Also included is a listing of the relevant log messages when my
renderers are being created.
I have checked the archives to see if any light could be shed on what I was
doing, but the suggestions I found (e.g., use multiple QCRenderers for multiple
displays, check pixel format, sharing opengl context) are things I believe I
have handled properly... but then again, my code isn't working, so take my
surety with a grain of salt.
Any help, hints, suggestions would be greatly appreciated.
Thanks,
douglas
---
*** Here's the relevant code from the QCRenderer subclass:
- (id) initWithComposition: (QCComposition *)composition screen: (NSDictionary
*)screen renderFrame: (CGRect)renderFrame usingSharedContext: (NSOpenGLContext
*)sharedContext
{
NSOpenGLPixelFormatAttribute attributes[] = {
NSOpenGLPFAScreenMask, 0,
NSOpenGLPFANoRecovery,
NSOpenGLPFAAccelerated,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAColorSize, 24,
NSOpenGLPFADepthSize, 16,
NSOpenGLPFAFullScreen, 0
};
NSOpenGLPixelFormat* pixelFormat;
CGFloat
longestSide = 0.0;
CGColorSpaceRef colorSpace;
GLint
swapInterval = 1;
BOOL
bezelEnabled;
CGFloat
bezel;
CVReturn
returnCode;
self.displayID = [[screen objectForKey: @"displayId"] intValue];
self.glSharedContext = sharedContext;
bezel = [[screen valueForKey: @"bezel"] floatValue];
bezelEnabled = [[screen valueForKey: @"bezelEnabled"] boolValue];
colorSpace = (CGColorSpaceRef)CGDisplayCopyColorSpace( self.displayID
);
longestSide = fmaxf( renderFrame.size.width, renderFrame.size.height );
CGRectMakeWithDictionaryRepresentation( (CFDictionaryRef)[screen
objectForKey: @"onCanvasFrame"], &screenFrame );
attributes[1] = CGDisplayIDToOpenGLDisplayMask( [[screen objectForKey:
@"displayID"] intValue] );
//+
// Make allowance for displaying with a bezelWidth adjustment
//-
if ( bezelEnabled && bezel != 0 )
screenFrame = CGRectMake( screenFrame.origin.x + bezel,
screenFrame.origin.y + bezel, screenFrame.size.width - 2 * bezel,
screenFrame.size.height - 2 * bezel );
//+
// Determine the region of the composition that is being drawn for
this screen
//-
subRegion = screenFrame;
subRegion.origin.x = ( subRegion.origin.x + longestSide / 2.0 -
renderFrame.size.width / 2.0 + subRegion.size.width / 2.0 ) / longestSide;
subRegion.origin.y = ( subRegion.origin.y + longestSide / 2.0 -
renderFrame.size.height / 2.0 + subRegion.size.height / 2.0 ) / longestSide;
subRegion.size.width = subRegion.size.width / longestSide;
subRegion.size.height = subRegion.size.height / longestSide;
NSLog( @"\n--- display id: %@\n--- canvasFrame: %@\n---OpenGL Display
Mask: %d\n---Sub Region: %@",
[screen objectForKey: @"displayId"],
NSStringFromRect( NSRectFromCGRect( screenFrame )),
attributes[1],
NSStringFromRect( NSRectFromCGRect( subRegion )));
//+
// Configure the pixelFormat to be used for the OpenGL context
pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:
attributes] autorelease];
[pixelFormat getValues: &rendererID forAttribute: NSOpenGLPFARendererID
forVirtualScreen: 0];
self.glContext = [[NSOpenGLContext alloc] initWithFormat: pixelFormat
shareContext: sharedContext];
[self.glContext setValues: &swapInterval forParameter:
NSOpenGLCPSwapInterval];
[self.glContext setFullScreen];
NSLog( @"\n--- Virtual Screen: %d\n--- Renderer ID: %d\n--- pixel
format: %@\n--- Context: %@\n--- shared Context: %@",
[self.glContext currentVirtualScreen],
[ArenaRenderer rendererIDForDisplayID: self.displayID],
pixelFormat,
self.glContext,
sharedContext );
//+
// Call the superclass
//-
self = [super initWithCGLContext: [self.glContext CGLContextObj]
pixelFormat:[pixelFormat CGLPixelFormatObj] colorSpace: colorSpace composition:
composition];
if ( self != nil )
{
CGColorSpaceRelease( colorSpace );
self.startTime = -1;
returnCode = CVDisplayLinkCreateWithOpenGLDisplayMask(
CGDisplayIDToOpenGLDisplayMask( self.displayID ), &displayLink );
if ( returnCode == kCVReturnSuccess )
{
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(
displayLink, [self.glContext CGLContextObj], [pixelFormat CGLPixelFormatObj]);
CVDisplayLinkSetOutputCallback( displayLink,
displayLinkCallBack, self);
}
}
CGDisplayCapture( self.displayID );
CGDisplayHideCursor( self.displayID );
CVDisplayLinkStart( displayLink );
return self;
}
- (void) renderScene
{
float scale;
NSTimeInterval renderTime;
//+
// Normalize the startTime, if necessary, then determine the current
render time
//-
if ( self.startTime < 0 )
self.startTime = [NSDate timeIntervalSinceReferenceDate];
renderTime = [NSDate timeIntervalSinceReferenceDate] - self.startTime;
//+
// Set up the OpenGL enviroment and get ready to render a frame
//-
[self.glContext makeCurrentContext];
glClearColor( 0.0f, 0.0, 0.0, 1.0 );
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glPushMatrix();
//+
// Translate and scale the projection matrix so that correct subregion
is rendered on display
//-
glTranslatef(( 0.5 - subRegion.origin.x ) / subRegion.size.width * 2.0,
( 0.5 - subRegion.origin.y ) / subRegion.size.height * 2.0, 0.0 );
scale = MIN( 1.0 / subRegion.size.width, 1.0 / subRegion.size.height );
glScalef( scale, scale, 1.0 );
//+
// Render composition
//-
[super renderAtTime: renderTime arguments: nil];
[self.glContext flushBuffer];
//+
// Restore projection matrix
//-
glMatrixMode( GL_PROJECTION );
glPopMatrix();
}
*** Here are the log messages I get on the console when the init method
executes on a system with two displays:
6/28/11 1:01:32 PM Arena Client[1641]
--- display id: 69676800
--- canvasFrame: {{1391.79, 933.214}, {1920, 1080}}
---OpenGL Display Mask: 1
---Sub Region: {{0.653274, 0.409226}, {0.533333, 0.3}}
6/28/11 1:01:32 PM Arena Client[1641]
--- Virtual Screen: 0
--- Renderer ID: 16918030
--- pixel format: <NSOpenGLPixelFormat: 0x1027c6160>
--- Context: <NSOpenGLContext: 0x1027d0bf0>
--- shared Context: (null)
6/28/11 1:01:32 PM Arena Client[1641] --- comparing rendererIDs:
16918030 to 16918030
6/28/11 1:01:32 PM Arena Client[1641] --- sharing a renderer's context
6/28/11 1:01:32 PM Arena Client[1641]
--- display id: 418793473
--- canvasFrame: {{692.143, 2046.43}, {1680, 1050}}
---OpenGL Display Mask: 1
---Sub Region: {{0.425595, 0.714286}, {0.466667, 0.291667}}
6/28/11 1:01:32 PM Arena Client[1641]
--- Virtual Screen: 0
--- Renderer ID: 16918030
--- pixel format: <NSOpenGLPixelFormat: 0x1027c9ba0>
--- Context: <NSOpenGLContext: 0x1027c8fa0>
--- shared Context: <NSOpenGLContext: 0x1027d0bf0>
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Quartzcomposer-dev mailing list ([email protected])
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/quartzcomposer-dev/archive%40mail-archive.com
This email sent to [email protected]