Did you ever get this to work? I'm in the same boat. I have a semi-transparent window over the whole screen, which I'm trying to draw at @ 30fps, but I can't seem to force the CALayer to update when I blit to the CVPixelBuffer. I will see the first couple frames, but then it stops updating.
Observations:
Strangely, the layer will update if I interact with another part of my app, like while dragging a slider in the preferences window.
I can also force the layer to update by setting layer.contents = nil; layer.contents = buffer or I can use 2 buffers and continually set layer.contents to every other buffer, but this doesn't display smoothly.
I just want something more efficient than setting an NSImageView 30x a second. Using [NSColor colorWithPatternImage:] works, but for the life of me I can't understand why this CVPixelBuffer isn't working, it's pretty simple stuff.
Here's how I'm defining my CVPixelBuffer:
NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys:
@{}, kCVPixelBufferIOSurfacePropertiesKey,
@YES, kCVPixelBufferCGBitmapContextCompatibilityKey,
@YES, kCVPixelBufferIOSurfaceCoreAnimationCompatibilityKey, nil];
CVPixelBufferRef _buffer;
CVPixelBufferCreate(kCFAllocatorDefault, width, height, kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef)d, &_buffer);
_overlay.contentView.layer.contents = (__bridge id _Nullable)(_buffer);
I've also tried _overlay.contentView.layer.contents = (__bridge id _Nullable)CVPixelBufferGetIOSurface(_buffer);, but I get the same behavior.
The code to update the CVPixelBuffer getting called at 30fps by an NSTimer (main thread):
CVPixelBufferLockBaseAddress(_buffer, 0);
void *rasterData = CVPixelBufferGetBaseAddress(_buffer);
memcpy(rasterData, bitmapData, bytes);
CVPixelBufferUnlockBaseAddress(_buffer, 0);
None of these worked:
[_overlay.contentView setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawOnSetNeedsDisplay];
[_overlay.contentView.layer setNeedsDisplay];
[_overlay.contentView.layer display];
[_overlay.contentView display];
[_overlay.contentView setNeedsDisplay:YES];