簡體   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