Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
MainOpenGLView.m
#import "MainOpenGLView.h" |
#include <sys/time.h> |
#include <unistd.h> |
#define VERTEX_COUNT 256 |
#define ITERATIONS 10 |
#define APP_OPT_MAX 20000 |
#define NO_DATA 0 |
#define HAS_DATA 1 |
@interface MainOpenGLView (Helper) |
- (void)DrawThread; |
@end |
@implementation MainOpenGLView (Helper) |
- (void)DrawThread |
{ |
struct timeval t1, t2; |
GLuint count = 0; |
GLdouble ut; |
GLint qitem; |
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
[NSThread setThreadPriority:1.0]; |
[[self openGLContext] makeCurrentContext]; |
gettimeofday(&t1, NULL); |
do |
{ |
[buffer_lock[COMPUTATION_QUEUE] lockWhenCondition:HAS_DATA]; |
qitem = work_queue[COMPUTATION_QUEUE][0]; |
//[buffer_lock[DISPLAY_QUEUE] lock]; |
//glFinishFenceAPPLE(qitem + 1); |
//[buffer_lock[DISPLAY_QUEUE] unlock]; |
[wave WaveMotion:qitem]; |
work_queue[COMPUTATION_QUEUE][0] = work_queue[COMPUTATION_QUEUE][1]; |
work_queue[COMPUTATION_QUEUE][1] = -1; |
[buffer_lock[COMPUTATION_QUEUE] unlockWithCondition:(work_queue[COMPUTATION_QUEUE][0] < 0 ? NO_DATA : HAS_DATA)]; |
[buffer_lock[DISPLAY_QUEUE] lock]; |
if(work_queue[DISPLAY_QUEUE][0] < 0) |
work_queue[DISPLAY_QUEUE][0] = qitem; |
else |
work_queue[DISPLAY_QUEUE][1] = qitem; |
[buffer_lock[DISPLAY_QUEUE] unlockWithCondition:HAS_DATA]; |
gettimeofday(&t2, NULL); |
count++; |
ut = (GLdouble) (t2.tv_sec - t1.tv_sec) + (GLdouble) (t2.tv_usec - t1.tv_usec) * 0.000001; |
if(ut > 0.5) |
{ |
comptime = ut / (GLdouble) count; |
gettimeofday(&t1, NULL); |
count = 0; |
} |
} while(multi_threaded); |
[pool release]; |
[NSThread exit]; |
} |
@end |
@implementation MainOpenGLView |
- (IBAction)setAppOptLevelAction:(id)sender |
{ |
int app_time = -([sender intValue] - APP_OPT_MAX); |
appOptLevel = app_time; |
[self setNeedsDisplay:true]; |
} |
- (void) UpdateLabels |
{ |
NSTextField *textField = NULL; |
char labelString[64]; |
char *labels[] = { "Quads", |
"Quad Strips", |
"Vertex Arrays", |
"Vertex Array Range", |
"Vertex Array Range + Altivec", |
"Vertex Program"}; |
int i; |
for(i=0; i<6; i++) |
{ |
if (i == 0) textField = optLevelLabel_0; |
if (i == 1) textField = optLevelLabel_1; |
if (i == 2) textField = optLevelLabel_2; |
if (i == 3) textField = optLevelLabel_3; |
if (i == 4) textField = optLevelLabel_4; |
if (i == 5) textField = optLevelLabel_5; |
if (i == openglOptLevel) |
{ |
sprintf(labelString, labels[i]); |
[textField setBezeled: YES]; |
[textField setStringValue: [NSString stringWithCString: labelString]]; |
[textField setTextColor: [NSColor redColor]]; |
} |
else |
{ |
labelString[0] = 0; |
[textField setBezeled: NO]; |
[textField setStringValue: [NSString stringWithCString: labelString]]; |
} |
} |
[self setNeedsDisplay:true]; |
} |
- (IBAction)setOptLevelAction: (id)sender |
{ |
openglOptLevel = [sender intValue]; |
[[self openGLContext] makeCurrentContext]; |
if (5 == openglOptLevel && multi_threaded) |
{ |
[self setMPAction: 0]; |
} |
[wave WaveSetDisplay: openglOptLevel]; |
[self UpdateLabels]; |
[self setNeedsDisplay:true]; |
} |
- (IBAction)setMPAction:(id)sender |
{ |
int mp = [sender intValue]; |
if(mp) |
{ |
if (openglOptLevel != 5) |
{ |
if(!multi_threaded) |
{ |
multi_threaded = true; |
[NSThread detachNewThreadSelector:@selector(DrawThread) toTarget:self withObject:nil]; |
} |
} |
else |
{ |
[selectMP setState: 0]; |
} |
} |
else |
{ |
multi_threaded = false; |
[selectMP setState: 0]; |
} |
[self setNeedsDisplay:true]; |
} |
- (IBAction)setBarScaleFactor:(id)sender |
{ |
float factor; |
int setting = [sender intValue]; |
if(setting) factor = 0.1f; |
else factor = 1.0f; |
[perfBarGLView setBarScaleFactor:factor]; |
} |
- (void) awakeFromNib |
{ |
[self UpdateLabels]; |
} |
- (id)initWithFrame:(NSRect)frameRect |
{ |
GLint qitem; |
NSBundle *mainBndl; |
NSString *bndlPath; |
NSOpenGLPixelFormatAttribute attrs[] = |
{ |
NSOpenGLPFANoRecovery, |
NSOpenGLPFAAccelerated, |
NSOpenGLPFADoubleBuffer, |
NSOpenGLPFADepthSize, 16, |
0 |
}; |
NSOpenGLPixelFormat* pixFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; |
if(!pixFmt) |
{ |
NSLog(@"No pixel format -- exiting"); |
exit(1); |
} |
mainBndl = [NSBundle mainBundle]; |
bndlPath = [mainBndl resourcePath]; |
chdir([bndlPath cString]); |
buffer_lock[COMPUTATION_QUEUE] = [[NSConditionLock alloc] initWithCondition:HAS_DATA]; |
buffer_lock[DISPLAY_QUEUE] = [[NSConditionLock alloc] initWithCondition:NO_DATA]; |
work_queue[COMPUTATION_QUEUE][0] = 0; |
work_queue[COMPUTATION_QUEUE][1] = 1; |
work_queue[DISPLAY_QUEUE][0] = -1; |
work_queue[DISPLAY_QUEUE][1] = -1; |
appOptLevel = APP_OPT_MAX; |
openglOptLevel = 0; |
multi_threaded = false; |
fillmode = 1; |
tottime = 0; |
comptime = 0; |
ogltime = 0; |
passes = 0; |
prev_tottime = 0; |
gettimeofday(&cycle_time, NULL); |
gettimeofday(&display_time, NULL); |
self = [super initWithFrame:frameRect pixelFormat: pixFmt]; |
[[self openGLContext] makeCurrentContext]; |
wave = [[WaveOject alloc] init]; |
// Compute the initial buffer |
qitem = work_queue[COMPUTATION_QUEUE][0]; |
[wave WaveMotion: qitem]; |
work_queue[COMPUTATION_QUEUE][0] = work_queue[COMPUTATION_QUEUE][1]; |
work_queue[COMPUTATION_QUEUE][1] = -1; |
if(work_queue[DISPLAY_QUEUE][0] < 0) |
work_queue[DISPLAY_QUEUE][0] = qitem; |
else |
work_queue[DISPLAY_QUEUE][1] = qitem; |
[self UpdateLabels]; |
[self setNeedsDisplay:true]; |
return self; |
} |
- (void)drawRect:(NSRect)aRect |
{ |
struct timeval t1, t2, ct; |
GLuint r, tris = 0; |
GLint qitem; |
[[self openGLContext] makeCurrentContext]; |
// Display the current buffer |
if(multi_threaded) |
{ |
gettimeofday(&t1, NULL); |
for(r = 0; r < ((openglOptLevel + 1) * 2); r++, passes++) |
{ |
[buffer_lock[DISPLAY_QUEUE] lockWhenCondition:HAS_DATA]; |
qitem = work_queue[DISPLAY_QUEUE][0]; |
if(qitem >= 0) |
{ |
tris = [wave WaveDisplay: qitem]; |
glSetFenceAPPLE(qitem + 1); |
work_queue[DISPLAY_QUEUE][0] = work_queue[DISPLAY_QUEUE][1]; |
work_queue[DISPLAY_QUEUE][1] = -1; |
} |
[buffer_lock[DISPLAY_QUEUE] unlockWithCondition:(work_queue[DISPLAY_QUEUE][0] < 0 ? NO_DATA : HAS_DATA)]; |
[buffer_lock[COMPUTATION_QUEUE] lock]; |
if(work_queue[COMPUTATION_QUEUE][0] < 0) |
work_queue[COMPUTATION_QUEUE][0] = qitem; |
else |
work_queue[COMPUTATION_QUEUE][1] = qitem; |
[buffer_lock[COMPUTATION_QUEUE] unlockWithCondition:HAS_DATA]; |
[[self openGLContext] flushBuffer]; |
} |
gettimeofday(&t2, NULL); |
ogltime += (GLdouble) (t2.tv_sec - t1.tv_sec) + (GLdouble) (t2.tv_usec - t1.tv_usec) * 0.000001; |
} |
else |
{ |
for(r = 0; r < ((openglOptLevel + 1) * 2); r++, passes++) |
{ |
gettimeofday(&t1, NULL); |
// Compute the next buffer in queue |
qitem = work_queue[COMPUTATION_QUEUE][0]; |
if(qitem >= 0) |
{ |
[wave WaveMotion: qitem]; |
work_queue[COMPUTATION_QUEUE][0] = work_queue[COMPUTATION_QUEUE][1]; |
work_queue[COMPUTATION_QUEUE][1] = -1; |
if(work_queue[DISPLAY_QUEUE][0] < 0) |
work_queue[DISPLAY_QUEUE][0] = qitem; |
else |
work_queue[DISPLAY_QUEUE][1] = qitem; |
} |
gettimeofday(&ct, NULL); |
comptime += (GLdouble) (ct.tv_sec - t1.tv_sec) + (GLdouble) (ct.tv_usec - t1.tv_usec) * 0.000001; |
[[self openGLContext] makeCurrentContext]; |
qitem = work_queue[DISPLAY_QUEUE][0]; |
if(qitem >= 0) |
{ |
tris = [wave WaveDisplay: qitem]; |
work_queue[DISPLAY_QUEUE][0] = work_queue[DISPLAY_QUEUE][1]; |
work_queue[DISPLAY_QUEUE][1] = -1; |
if(work_queue[COMPUTATION_QUEUE][0] < 0) |
work_queue[COMPUTATION_QUEUE][0] = qitem; |
else |
work_queue[COMPUTATION_QUEUE][1] = qitem; |
} |
[[self openGLContext] flushBuffer]; |
gettimeofday(&t2, NULL); |
ogltime += (GLdouble) (t2.tv_sec - ct.tv_sec) + (GLdouble) (t2.tv_usec - ct.tv_usec) * 0.000001; |
} |
} |
gettimeofday(&cycle_time, NULL); |
tottime = (GLdouble) (cycle_time.tv_sec - display_time.tv_sec) + (GLdouble) (cycle_time.tv_usec - display_time.tv_usec) * 0.000001; |
if(tottime > 0.5) |
{ |
GLdouble lag_time; |
gettimeofday(&display_time, NULL); |
tottime /= (GLdouble) passes; |
if(!multi_threaded) |
comptime /= (GLdouble) passes; |
ogltime /= (GLdouble) passes; |
lag_time = prev_tottime * 0.1 + tottime * 0.9; |
prev_tottime = tottime; |
[setFPS setFloatValue:1.0 / lag_time]; |
[setTriRate setFloatValue:(GLdouble) tris / lag_time]; |
[perfBarGLView setPerfTimes:tottime:comptime:ogltime:multi_threaded:0.1]; |
tottime = 0.0; |
if(!multi_threaded) |
comptime = 0.0; |
ogltime = 0.0; |
passes = 0; |
} |
} |
- (void)update // moved or resized |
{ |
NSRect rect; |
[super update]; |
[buffer_lock[DISPLAY_QUEUE] lock]; |
[[self openGLContext] makeCurrentContext]; |
[[self openGLContext] update]; |
rect = [self bounds]; |
[wave WaveReshape:(int) rect.size.width:(int) rect.size.height]; |
[buffer_lock[DISPLAY_QUEUE] unlock]; |
[self setNeedsDisplay:true]; |
} |
- (void)reshape // scrolled, moved or resized |
{ |
NSRect rect; |
[super reshape]; |
[buffer_lock[DISPLAY_QUEUE] lock]; |
[[self openGLContext] makeCurrentContext]; |
[[self openGLContext] update]; |
rect = [self bounds]; |
[wave WaveReshape:(int) rect.size.width:(int) rect.size.height]; |
[buffer_lock[DISPLAY_QUEUE] unlock]; |
[self setNeedsDisplay:true]; |
} |
- (void)mouseDragged:(NSEvent *)theEvent |
{ |
NSPoint pt; |
[buffer_lock[DISPLAY_QUEUE] lock]; |
[[self openGLContext] makeCurrentContext]; |
pt = [theEvent locationInWindow]; |
[wave WaveMouseMotion:(int) pt.x:(int) pt.y]; |
[buffer_lock[DISPLAY_QUEUE] unlock]; |
[self setNeedsDisplay:true]; |
} |
- (void)mouseDown:(NSEvent *)theEvent |
{ |
NSPoint pt; |
[buffer_lock[DISPLAY_QUEUE] lock]; |
[[self openGLContext] makeCurrentContext]; |
pt = [theEvent locationInWindow]; |
[wave WaveMouseDown:(int) pt.x:(int) pt.y]; |
[buffer_lock[DISPLAY_QUEUE] unlock]; |
[self setNeedsDisplay:true]; |
} |
- (BOOL)acceptsFirstResponder |
{ |
return YES; |
} |
- (BOOL)becomeFirstResponder |
{ |
return YES; |
} |
- (BOOL)resignFirstResponder |
{ |
return YES; |
} |
- (void)keyDown:(NSEvent *)theEvent |
{ |
unichar c = [theEvent keyCode]; |
if ([theEvent isARepeat]) |
{ |
return; |
} |
switch (c) |
{ |
case 0x31: |
fillmode = fillmode ? 0 : 1; |
[wave WaveSetFillMode: fillmode]; |
break; |
default: |
[super keyDown: theEvent]; |
} |
} |
@end |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-07-07