如何在 Cocoa / Objective-C 中从位图数据中执行无伪影的快速绘制?

How to perform artifact-free fast drawing from bitmap data in Cocoa / Objective-C?

提问人:Will B 提问时间:9/8/2023 更新时间:9/8/2023 访问量:40

问:

免责声明:我主要在 Linux 和 Windows 上使用 Gtk 和 FLTK。我差不多要开始我的 macOS / Cocoa / Objective-C 开发之旅了。虽然我做了很多研究,但我没有找到足够的文档或代码示例来解决这个问题。另外,我患有发育障碍,所以请放轻松。

我正在尝试以大约每秒 20 到 30 帧的速度将 VNC 库 (libvncserver / libvncclient) 帧缓冲区的内容绘制到程序中的 NSView 上。虽然我成功地以所需的速度将图像绘制到 NSView 上,但它看起来很糟糕,到处都是白色伪影:

Image showing drawing artifacts

在 NSView 的方法中,我首先必须遍历帧缓冲区并将 alpha 设置为 255,否则图像将(大部分)透明:drawRect

  if ([vnc bytesPerPixel] == 2 || [vnc bytesPerPixel] == 4)
  {
    for (int i = ([vnc bytesPerPixel] - 1); i < [vnc buffSize]; i+= [vnc bytesPerPixel])
      vnc.vncClient->frameBuffer[i] = 255;
  }

然后,我制作了 NSBitmapImageRep:

  NSBitmapImageRep * rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&vnc.vncClient->frameBuffer
         pixelsWide:vnc.vncClient->width
         pixelsHigh:vnc.vncClient->height
      bitsPerSample:8
    samplesPerPixel:4
           hasAlpha:YES
           isPlanar:NO
     colorSpaceName:NSDeviceRGBColorSpace
        bytesPerRow:vnc.vncClient->width * [vnc bytesPerPixel]
       bitsPerPixel:vnc.vncClient->format.bitsPerPixel
       ];

然后我实际上做了抽奖:

  [rep drawInRect:[self bounds] 
          fromRect:NSZeroRect
         operation:NSCompositingOperationCopy 
          fraction:1.0
    respectFlipped:YES
             hints:nil
  ];

由于显然还有其他 Mac 应用程序可以在没有所有伪影的情况下实现更高的帧速率,有没有更好的方法可以做到这一点?

Objective-C macOS Cocoa 图形

评论

1赞 Itai Ferber 9/8/2023
这远非答案,因为我没有直接的经验,但是是否可以将帧缓冲直接馈送到 Metal 进行显示?(这将是我探索的第一个途径:避免手动处理获取帧缓冲区,将其复制到位图表示中,然后将其重新绘制到屏幕上;如果我不得不猜测的话,任何可以让你直接将其传输到 GPU 的东西都会快一个数量级。
0赞 Will B 9/8/2023
@ItaiFerber谢谢!我会检查一下,看看它是否是一种选择。Apple 的 API 文档通常存在重大漏洞,使其难以学习,但 Metal 的建议听起来很有趣。👍

答: 暂无答案