0

I am working on a OSX/Cocoa graphics application which (for performance reasons) I would like to render at 640x480 when the user selects "full screen" mode. For what it's worth, the content is a custom NSView which draws using openGL.

I understand that rather than actually change the user's resolution, it's preferable to change the backbuffer (as explained on another SO question here: Programmatically change resolution OS X).

Following that advice, I end up with the following two methods (see below) to toggle between fullscreen and windowed. The trouble is that when I go fullscreen, the content does indeed render at 640x480 but is not scaled (IE it appears as if we stayed at the window's resolution and "zoomed" into a 640x480 corner of the render).

I'm probably missing something obvious here - I suppose I could translate the render according to the actual screen resolution to "center" it, but that seems overcomplicated?

- (void)goFullscreen{

  // Bounce if we're already fullscreen
  if(_isFullscreen){return;}

  // Save original size and position
  NSRect frame = [self.window.contentView frame];
  original_size = frame.size;
  original_position = frame.origin;

  NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                         [NSNumber numberWithBool:NO],NSFullScreenModeAllScreens,
                         nil];

  // In lieu of changing resolution, we set the backbuffer to 640x480
  GLint dim[2] = {640, 480};
  CGLSetParameter([[self openGLContext] CGLContextObj], kCGLCPSurfaceBackingSize, dim);
  CGLEnable ([[self openGLContext] CGLContextObj], kCGLCESurfaceBackingSize);

  // Go fullscreen!
  [self enterFullScreenMode:[NSScreen mainScreen] withOptions:options];
  _isFullscreen=true;

}


- (void)goWindowed{

  // Bounce if we're already windowed
  if(!_isFullscreen){return;}

  // Reset backbuffer
  GLint dim[2] = {original_size.width, original_size.height};
  CGLSetParameter([[self openGLContext] CGLContextObj], kCGLCPSurfaceBackingSize, dim);
  CGLEnable ([[self openGLContext] CGLContextObj], kCGLCESurfaceBackingSize);

  // Go windowed!
  [self exitFullScreenModeWithOptions:nil];
  [self.window makeFirstResponder:self];
  _isFullscreen=false;

}

Update

Here's now to do something similar to datenwolf's suggestion below, but not using openGL (useful for non-gl content).

// Render into a specific size
renderDimensions = NSMakeSize(640, 480);
NSImage *drawIntoImage = [[NSImage alloc] initWithSize:renderDimensions];
[drawIntoImage lockFocus];
[self drawViewOfSize:renderDimensions];
[drawIntoImage unlockFocus];
[self syphonSendImage:drawIntoImage];

// Resize to fit preview area and draw
NSSize newSize = NSMakeSize(self.frame.size.width, self.frame.size.height);
[drawIntoImage setSize: newSize];
[[NSColor blackColor] set];

[self lockFocus];
[NSBezierPath fillRect:self.frame];
[drawIntoImage drawAtPoint:NSZeroPoint fromRect:self.frame operation:NSCompositeCopy fraction:1];
[self unlockFocus];
4

1 回答 1

4

使用附加了所需目标分辨率纹理的 FBO,并以所述分辨率渲染到该 FBO/纹理。然后切换到主帧缓冲区并使用之前渲染的纹理绘制一个全屏四边形。使用您最喜欢的任何放大滤镜。如果你想拿出大炮,你可以在片段着色器中实现一个 Lancosz / sinc 插值器来放大中间纹理。

于 2013-08-27T16:33:54.103 回答