Take the 2-minute tour ×

I'm trying to get the avTouch sample code app to run on the retina display. Has anyone done this?

In the CALevelMeter class, I've tried the following:

- (id)initWithCoder:(NSCoder *)coder {
 if (self = [super initWithCoder:coder]) {
      CGFloat f = self.contentScaleFactor;
      if ([self respondsToSelector:@selector(contentScaleFactor)])
           self.contentScaleFactor = [[UIScreen mainScreen] scale];
      f = self.contentScaleFactor;

      _showsPeaks = YES;
      _channelNumbers = [[NSArray alloc] initWithObjects:[NSNumber numberWithInt:0], nil];
      _vertical = NO;
      _useGL = YES;
      _meterTable = new MeterTable(kMinDBvalue);
      [self layoutSubLevelMeters];
      [self registerForBackgroundNotifications];
 return self;


and it sets the contentScaleFactor to "2". Great, that was expected. But then in the layoutSubviews, CALevelMeter frame is still 1/2 of what it should be.

Any ideas?

share|improve this question
add comment

1 Answer

up vote 11 down vote accepted

Frames are in points, not pixels. When a scale factor is applied to the UIView hosting your CAEAGLLayer, it will be double the pixels, but its frame point size will remain the same.

If you look at the backing width and height for the color renderbuffer attached to the CAEAGLLayer using code like the following:

glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

you should see that the width and height of the renderbuffer on a Retina display are twice the values they are on a standard iPhone display.

The code you show above should cause nice, sharp rendering on a Retina display.

EDIT (12/22/2010): In response to your further question, looking at the avTouch sample code shows that the current version of that code makes a mistake in looking up the bounds of the OpenGL-hosting view, rather than using the backing width and height of the renderbuffer. With a non-1.0 scale factor, this will cause the OpenGL content to be drawn at half size.

To fix this, replace the appropriate section within _drawView in GLLevelMeter with the following code:

if (_vertical)
    glTranslatef(0., _backingWidth, 0.);
    glScalef(1., -1., 1.);
    bds = CGRectMake(0., 0., _backingWidth, _backingHeight);
} else {
    glTranslatef(0., _backingHeight, 0.);
    glRotatef(-90., 0., 0., 1.);
    bds = CGRectMake(0., 0., _backingHeight, _backingWidth);

This will cause everything to work in the appropriate pixel space, and lead to crisp rendering at the correct size in the equalizer. I've filed a bug report on this.

share|improve this answer
But doesn't the retina display double the frame size to account for the higher resolution? Even after adding the code I mentioned, I still only get a meter thats 1/2 the height. This is only the case for the openGL meter. The UIView meter works fine with retina. I'm stumped. –  Bryan Dec 22 '10 at 13:55
@Bryan - Looking at the avTouch sample code, it appears that Apple has made an error in the way they've implemented _drawView in GLLevelMeter. They are using the bounds of the view, which is in points, to determine sizes of things in OpenGL, when instead they should be using the _backingWidth and _backingHeight instance variables. Replace references to the bounds' size and height with _backingWidth and _backingHeight and this will draw properly on a Retina display. I'll file a bug report on the sample code. –  Brad Larson Dec 22 '10 at 15:17
@Bryan - I've localized the code that needs to be changed within the edit to my answer. –  Brad Larson Dec 22 '10 at 15:37
Awesome. Thanks so much. I'm new to openGL and was thinking the frame got adjusted based on the contentScaleFactor, but clearly not. Thanks again! –  Bryan Dec 22 '10 at 15:52
Brilliant - thanks. This fixes it :-) –  Ben Clayton Aug 9 '12 at 15:15
add comment

Your Answer


