繁体   English   中英

为NSView初始化/同步OpenGL的正确方法

[英]Correct way to initialize / sync OpenGL for NSView

我遵循苹果的文档创建了一个自定义OpenGLView而不是使用NSOpenGLView 绘图似乎很好,但似乎我这里有线程同步问题。 由于NSView应该在主线程中,然后在如何同步线程中,我的意思是CADisplayLink似乎在不同的线程上工作,因此在旋转或缩放到3D场景后,某些节点会保持其旧的转换(缓慢转换),直到旋转/缩放完成为止。 但是如果我在显示链接绘图中使用dispatch_sync/dispatch_async似乎是正确的。 但是我不确定它如何影响性能。

Q1:在displaylink cb中使用dispatch_sync是否正确? 还是更好的选择?

Q2:另外我没有绘制全屏视图,会有可可控件或多个openglviews。 由于主线程不是专用于opengl的,所以我不知道它如何影响FPS或可可粉控件。 那么可以在单独的线程中运行opengl绘图操作吗?

对于缩放/旋转情况,我有一个解决方案,我向场景或节点添加了一个标志(更改缩放/旋转时),然后在渲染功能时,我检查了该标志然后应用了变换。 渲染/绘图似乎也是正确的。 但这是一种情况。 将来还会有其他问题。 所以我需要同步我认为的线程

CVReturn
displaylink_cb(CVDisplayLinkRef    CV_NONNULL  displayLink,
               const CVTimeStamp * CV_NONNULL  inNow,
               const CVTimeStamp * CV_NONNULL  inOutputTime,
               CVOptionFlags                   flagsIn,
               CVOptionFlags     * CV_NONNULL  flagsOut,
               void              * CV_NULLABLE displayLinkContext) {
  dispatch_sync(dispatch_get_main_queue(), ^{
    [(__bridge GLView *)displayLinkContext renderOnce];
  });

  return kCVReturnSuccess;
}

- (void)syncWithCurrentDisplay {
  NSOpenGLContext  *openGLContext;
  CGLContextObj     cglContext;
  CGLPixelFormatObj cglPixelFormat;
  GLint             swapInt;

  openGLContext = [self openGLContext];
  swapInt       = 1;

  /* Synchronize buffer swaps with vertical refresh rate */
  [openGLContext setValues: &swapInt
              forParameter: NSOpenGLCPSwapInterval];

  /* Create a display link capable of being used with all active displays */
  CVDisplayLinkCreateWithActiveCGDisplays(&m_displayLink);

  /* Set the renderer output callback function */
  CVDisplayLinkSetOutputCallback(m_displayLink,
                                 display_link_cb,
                                 (__bridge void *)self);

  /* Set the display link for the current renderer */
  cglContext     = [openGLContext CGLContextObj];
  cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj];
  CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(m_displayLink,
                                                    cglContext,
                                                    cglPixelFormat);
}

- (void) renderOnce {
  NSOpenGLContext *context;
  context = [self openGLContext];

  [context makeCurrentContext];

  /* because display link is threaded */
  CGLLockContext([context CGLContextObj]);
  [[self delegate] render];
  [context flushBuffer];
  CGLUnlockContext([context CGLContextObj]);
}

OpenGL渲染可以在任何线程上进行,只要一次只在一个线程上进行即可。 仅仅因为您拥有NSView并不意味着您的上下文必须在主线程上呈现。

请参见下面的示例。 呈现是在显示链接的线程上完成的,除了在主线程上发生视图框架更改通知期间外,因此代码使用锁在主线程上呈现该一帧(这实际上不是必需的,但是如果您这样做,该锁将显示操作方法)。

https://developer.apple.com/library/content/samplecode/GLFullScreen/Introduction/Intro.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM