Use SDL helpers to create Metal view

This commit is contained in:
Cameron Gutman 2024-02-07 03:26:09 -06:00
parent db06239018
commit b972a22459

View file

@ -97,19 +97,6 @@ struct Vertex
vector_float2 texCoord; vector_float2 texCoord;
}; };
@interface VTView : NSView
- (NSView *)hitTest:(NSPoint)point;
@end
@implementation VTView
- (NSView *)hitTest:(NSPoint)point {
Q_UNUSED(point);
return nil;
}
@end
class VTRenderer : public IFFmpegRenderer class VTRenderer : public IFFmpegRenderer
{ {
public: public:
@ -123,7 +110,7 @@ public:
m_PipelineState(nullptr), m_PipelineState(nullptr),
m_ShaderLibrary(nullptr), m_ShaderLibrary(nullptr),
m_CommandQueue(nullptr), m_CommandQueue(nullptr),
m_StreamView(nullptr), m_MetalView(nullptr),
m_DisplayLink(nullptr), m_DisplayLink(nullptr),
m_LastColorSpace(-1), m_LastColorSpace(-1),
m_LastFullRange(false), m_LastFullRange(false),
@ -171,11 +158,6 @@ public:
} }
} }
if (m_StreamView != nullptr) {
[m_StreamView removeFromSuperview];
[m_StreamView release];
}
if (m_CscParamsBuffer != nullptr) { if (m_CscParamsBuffer != nullptr) {
[m_CscParamsBuffer release]; [m_CscParamsBuffer release];
} }
@ -200,6 +182,10 @@ public:
CFRelease(m_TextureCache); CFRelease(m_TextureCache);
} }
if (m_MetalView != nullptr) {
SDL_Metal_DestroyView(m_MetalView);
}
// It appears to be necessary to run the event loop after destroying // It appears to be necessary to run the event loop after destroying
// the AVSampleBufferDisplayLayer to avoid issue #973. // the AVSampleBufferDisplayLayer to avoid issue #973.
SDL_PumpEvents(); SDL_PumpEvents();
@ -226,9 +212,20 @@ public:
return kCVReturnSuccess; return kCVReturnSuccess;
} }
bool initializeVsyncCallback(SDL_SysWMinfo* info) bool initializeVsyncCallback()
{ {
NSScreen* screen = [info->info.cocoa.window screen]; SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (!SDL_GetWindowWMInfo(m_Window, &info)) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetWindowWMInfo() failed: %s",
SDL_GetError());
return false;
}
SDL_assert(info.subsystem == SDL_SYSWM_COCOA);
NSScreen* screen = [info.info.cocoa.window screen];
CVReturn status; CVReturn status;
if (screen == nullptr) { if (screen == nullptr) {
// Window not visible on any display, so use a // Window not visible on any display, so use a
@ -606,27 +603,15 @@ public:
return false; return false;
} }
SDL_SysWMinfo info; m_MetalView = SDL_Metal_CreateView(m_Window);
if (!m_MetalView) {
SDL_VERSION(&info.version); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_Metal_CreateView() failed: %s",
if (!SDL_GetWindowWMInfo(params->window, &info)) { SDL_GetError());
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetWindowWMInfo() failed: %s",
SDL_GetError());
return false; return false;
} }
SDL_assert(info.subsystem == SDL_SYSWM_COCOA); m_MetalLayer = (CAMetalLayer*)SDL_Metal_GetLayer(m_MetalView);
// SDL adds its own content view to listen for events.
// We need to add a subview for our display layer.
NSView* contentView = info.info.cocoa.window.contentView;
m_StreamView = [[VTView alloc] initWithFrame:contentView.bounds];
// Associate a CAMetalLayer to our view
m_StreamView.layer = m_MetalLayer = [CAMetalLayer layer];
m_StreamView.wantsLayer = YES;
// Choose a device // Choose a device
m_MetalLayer.device = m_MetalLayer.preferredDevice; m_MetalLayer.device = m_MetalLayer.preferredDevice;
@ -644,8 +629,6 @@ public:
m_MetalLayer.displaySyncEnabled = params->enableVsync; m_MetalLayer.displaySyncEnabled = params->enableVsync;
m_MetalLayer.maximumDrawableCount = 2; // Double buffering m_MetalLayer.maximumDrawableCount = 2; // Double buffering
[contentView addSubview: m_StreamView];
// Create the Metal texture cache for our CVPixelBuffers // Create the Metal texture cache for our CVPixelBuffers
CFStringRef keys[1] = { kCVMetalTextureUsage }; CFStringRef keys[1] = { kCVMetalTextureUsage };
NSUInteger values[1] = { MTLTextureUsageShaderRead }; NSUInteger values[1] = { MTLTextureUsageShaderRead };
@ -673,7 +656,7 @@ public:
m_CommandQueue = [m_MetalLayer.device newCommandQueue]; m_CommandQueue = [m_MetalLayer.device newCommandQueue];
if (params->enableFramePacing) { if (params->enableFramePacing) {
if (!initializeVsyncCallback(&info)) { if (!initializeVsyncCallback()) {
return false; return false;
} }
} }
@ -685,7 +668,7 @@ public:
{ @autoreleasepool { { @autoreleasepool {
// Lazy initialization for the overlay // Lazy initialization for the overlay
if (m_OverlayTextFields[type] == nullptr) { if (m_OverlayTextFields[type] == nullptr) {
m_OverlayTextFields[type] = [[NSTextField alloc] initWithFrame:m_StreamView.bounds]; m_OverlayTextFields[type] = [[NSTextField alloc] initWithFrame:((NSView*)m_MetalView).bounds];
[m_OverlayTextFields[type] setBezeled:NO]; [m_OverlayTextFields[type] setBezeled:NO];
[m_OverlayTextFields[type] setDrawsBackground:NO]; [m_OverlayTextFields[type] setDrawsBackground:NO];
[m_OverlayTextFields[type] setEditable:NO]; [m_OverlayTextFields[type] setEditable:NO];
@ -706,7 +689,7 @@ public:
[m_OverlayTextFields[type] setTextColor:[NSColor colorWithSRGBRed:color.r / 255.0 green:color.g / 255.0 blue:color.b / 255.0 alpha:color.a / 255.0]]; [m_OverlayTextFields[type] setTextColor:[NSColor colorWithSRGBRed:color.r / 255.0 green:color.g / 255.0 blue:color.b / 255.0 alpha:color.a / 255.0]];
[m_OverlayTextFields[type] setFont:[NSFont messageFontOfSize:Session::get()->getOverlayManager().getOverlayFontSize(type)]]; [m_OverlayTextFields[type] setFont:[NSFont messageFontOfSize:Session::get()->getOverlayManager().getOverlayFontSize(type)]];
[m_StreamView addSubview: m_OverlayTextFields[type]]; [(NSView*)m_MetalView addSubview: m_OverlayTextFields[type]];
} }
// Update text contents // Update text contents
@ -770,7 +753,7 @@ private:
id<MTLRenderPipelineState> m_PipelineState; id<MTLRenderPipelineState> m_PipelineState;
id<MTLLibrary> m_ShaderLibrary; id<MTLLibrary> m_ShaderLibrary;
id<MTLCommandQueue> m_CommandQueue; id<MTLCommandQueue> m_CommandQueue;
VTView* m_StreamView; SDL_MetalView m_MetalView;
dispatch_block_t m_OverlayUpdateBlocks[Overlay::OverlayMax]; dispatch_block_t m_OverlayUpdateBlocks[Overlay::OverlayMax];
NSTextField* m_OverlayTextFields[Overlay::OverlayMax]; NSTextField* m_OverlayTextFields[Overlay::OverlayMax];
CVDisplayLinkRef m_DisplayLink; CVDisplayLinkRef m_DisplayLink;