Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

correctly resizing view w/ QCRenderer



Hello everyone,

I have a project that is using a relatively simple Quartz Composer composition. I am using a custom view with QCRenderer API's to present the composition. (QCView is not an option for me because I need to feed data into the composition in a thread-safe way.)

My view is working well, with one issue. When I resize my window (and thus my view), I either see excessive flicker or rendering artifacts. This suggests to me that I'm not handling resize events properly. Unfortunately, there's not a lot of sample code out there that uses QCRenderer... Apple's samples that do either don't handle resizing at all or have the same resize issues that I have. Yet, in Quartz Composer, my composition resizes perfectly. So if anyone has any suggestions or sample code that would show best practices for resizing a view using QCRenderer, that would be a big help to me.

For what it's worth, I'm attaching a stripped down version of my code.

thanks,
Chris

------(header)----------
#import <Quartz/Quartz.h>

@interface VideoView : NSView
{
	QCRenderer *				_renderer;
	NSRecursiveLock *			_rendererLock;
	NSOpenGLContext *			_glContext;
	NSOpenGLPixelFormat *		_glPixelFormat;
	CVDisplayLinkRef			_displayLink;
	NSTimeInterval				_startTime;
}

@end

------(source)----------
#import <OpenGL/OpenGL.h>
#import <OpenGL/CGLMacro.h>
#import <OpenGL/gl.h>
#import "VideoView.h"

@interface VideoView (privateMethods)
- (void)renderAtTime:(const CVTimeStamp *)time;
@end

static CVReturn _displayLinkCallBack(CVDisplayLinkRef displayLink, const CVTimeStamp* inNow
, const CVTimeStamp* inOutputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut
, void* displayLinkContext)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[(VideoView *)displayLinkContext renderAtTime: inOutputTime];
[pool release];

return kCVReturnSuccess;
}



@implementation VideoView

- (void)awakeFromNib
{
// Create the OpenGL context used to render the composition and attach it to the rendering view
NSOpenGLPixelFormatAttribute pixelFormatAttributes[] = {
NSOpenGLPFAAccelerated,
NSOpenGLPFANoRecovery,
NSOpenGLPFADoubleBuffer,
(NSOpenGLPixelFormatAttribute)0 };
_glPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes: pixelFormatAttributes];


long swapInterval = 1;
_glContext = [[NSOpenGLContext alloc] initWithFormat:_glPixelFormat shareContext:nil];
[_glContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
[_glContext setView: self];

// We need to know when the rendering view frame changes so that we can update the OpenGL context
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(frameDidChange:) name:NSViewFrameDidChangeNotification object:self];

// Get the path to the composition
NSString *path = [[NSBundle mainBundle] pathForResource:@"Video" ofType:@"qtz"];

// Create the QCRenderer to render the composition in the OpenGL context
if(_glContext && path)
_renderer = [[QCRenderer alloc] initWithOpenGLContext:_glContext pixelFormat:_glPixelFormat file:path];


	_rendererLock = [[NSRecursiveLock alloc] init];

// Create the CoreVideo display link (for the main display only)
if (_renderer) {
if (CVDisplayLinkCreateWithCGDisplay(kCGDirectMainDisplay, &_displayLink) == kCVReturnSuccess)
CVDisplayLinkSetOutputCallback(_displayLink, _displayLinkCallBack, self);
else
_displayLink = NULL;
}

// Start rendering
_startTime = -1.0;
CVDisplayLinkStart(_displayLink);
}



- (void)frameDidChange:(NSNotification *)notification { [_rendererLock lock];

	[_glContext update];

	NSRect frame = [self frame];
	CGLContextObj cgl_ctx = (CGLContextObj)[_glContext CGLContextObj];
	glViewport(0, 0, frame.size.width, frame.size.height);

	[_rendererLock unlock];
	
	[self display];
}


- (void)renderAtTime:(const CVTimeStamp *)time
{
NSTimeInterval videoTime,
localTime;
id image;

// Compute the video time
if (time->flags & kCVTimeStampVideoTimeValid)
videoTime = (NSTimeInterval)time->videoTime / (NSTimeInterval)time- >videoTimeScale;
else
videoTime = 0;

// Compute the local time as the difference between the current video time and the video
// time at which the first frame was rendered
if (_startTime < 0)
{
_startTime = videoTime;
localTime = 0;
}
else
localTime = videoTime - _startTime;

// Now ask the QCRenderer to do it's rendering
[_rendererLock lock];


	[_renderer renderAtTime:localTime arguments:nil];
	
	[_glContext flushBuffer];

	[_rendererLock unlock];
}


- (BOOL)isOpaque { return YES; }


- (void)drawRect:(NSRect)aRect { [_rendererLock lock];

// With this line enabled, I see flicker when resizing. When disabled, I see
// distortion when resizing.
//[_renderer renderAtTime:nil arguments:nil];


	CGLContextObj cgl_ctx = (CGLContextObj)[_glContext CGLContextObj];
	glFlush();

	[_rendererLock unlock];
}


- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver: self];

	if (_displayLink)
	{
		CVDisplayLinkStop(_displayLink);
		CVDisplayLinkRelease(_displayLink);
	}

	[_renderer release];
	[_glContext release];
	[_glPixelFormat release];
	[_rendererLock release];

	[super dealloc];
}


@end

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Quartzcomposer-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/quartzcomposer-dev/email@hidden

This email sent to email@hidden


Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.