From e4587138bbf3c4c3b8177a07180081d1e287fead Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 7 Dec 2019 13:25:12 +0200 Subject: [PATCH] - added support for softpoly backend on macOS Grabbed most of code from old Cocoa backend with separate code path for software rendering --- src/posix/cocoa/i_video.mm | 126 ++++++++++++++++++++++++++++++++----- 1 file changed, 112 insertions(+), 14 deletions(-) diff --git a/src/posix/cocoa/i_video.mm b/src/posix/cocoa/i_video.mm index 399e7eda8d..b06fb0bb80 100644 --- a/src/posix/cocoa/i_video.mm +++ b/src/posix/cocoa/i_video.mm @@ -57,6 +57,7 @@ #include "gl/system/gl_framebuffer.h" #include "vulkan/system/vk_framebuffer.h" +#include "rendering/polyrenderer/backend/poly_framebuffer.h" @implementation NSWindow(ExitAppOnClose) @@ -293,7 +294,13 @@ CocoaWindow* CreateWindow(const NSUInteger styleMask) return window; } -NSOpenGLPixelFormat* CreatePixelFormat() +enum class OpenGLProfile +{ + Core, + Legacy +}; + +NSOpenGLPixelFormat* CreatePixelFormat(const OpenGLProfile profile) { NSOpenGLPixelFormatAttribute attributes[16]; size_t i = 0; @@ -305,9 +312,13 @@ NSOpenGLPixelFormat* CreatePixelFormat() attributes[i++] = NSOpenGLPixelFormatAttribute(24); attributes[i++] = NSOpenGLPFAStencilSize; attributes[i++] = NSOpenGLPixelFormatAttribute(8); - attributes[i++] = NSOpenGLPFAOpenGLProfile; - attributes[i++] = NSOpenGLProfileVersion3_2Core; - + + if (profile == OpenGLProfile::Core) + { + attributes[i++] = NSOpenGLPFAOpenGLProfile; + attributes[i++] = NSOpenGLProfileVersion3_2Core; + } + if (!vid_autoswitch) { attributes[i++] = NSOpenGLPFAAllowOfflineRenderers; @@ -315,12 +326,14 @@ NSOpenGLPixelFormat* CreatePixelFormat() attributes[i] = NSOpenGLPixelFormatAttribute(0); + assert(i < sizeof attributes / sizeof attributes[0]); + return [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; } -void SetupOpenGLView(CocoaWindow* window) +void SetupOpenGLView(CocoaWindow* const window, const OpenGLProfile profile) { - NSOpenGLPixelFormat* pixelFormat = CreatePixelFormat(); + NSOpenGLPixelFormat* pixelFormat = CreatePixelFormat(profile); if (nil == pixelFormat) { @@ -364,13 +377,12 @@ public: assert(ms_window == nil); ms_window = CreateWindow(STYLE_MASK_WINDOWED); + const NSRect contentRect = [ms_window contentRectForFrameRect:[ms_window frame]]; SystemBaseFrameBuffer *fb = nullptr; #ifdef HAVE_VULKAN if (ms_isVulkanEnabled) { - const NSRect contentRect = [ms_window contentRectForFrameRect:[ms_window frame]]; - NSView* vulkanView = [[VulkanCocoaView alloc] initWithFrame:contentRect]; vulkanView.wantsLayer = YES; vulkanView.layer.backgroundColor = NSColor.blackColor.CGColor; @@ -417,13 +429,20 @@ public: { ms_isVulkanEnabled = false; - SetupOpenGLView(ms_window); + SetupOpenGLView(ms_window, OpenGLProfile::Core); } } else #endif + if (vid_preferbackend == 2) { - SetupOpenGLView(ms_window); + SetupOpenGLView(ms_window, OpenGLProfile::Legacy); + + fb = new PolyFrameBuffer(nullptr, fullscreen); + } + else + { + SetupOpenGLView(ms_window, OpenGLProfile::Core); } if (fb == nullptr) @@ -603,9 +622,17 @@ void SystemBaseFrameBuffer::SetWindowedMode() void SystemBaseFrameBuffer::SetMode(const bool fullscreen, const bool hiDPI) { - assert(m_window.screen != nil); - assert(m_window.contentView.layer != nil); - [m_window.contentView layer].contentsScale = hiDPI ? m_window.screen.backingScaleFactor : 1.0; + if ([m_window.contentView isKindOfClass:[OpenGLCocoaView class]]) + { + NSOpenGLView* const glView = [m_window contentView]; + [glView setWantsBestResolutionOpenGLSurface:hiDPI]; + } + else + { + assert(m_window.screen != nil); + assert(m_window.contentView.layer != nil); + [m_window.contentView layer].contentsScale = hiDPI ? m_window.screen.backingScaleFactor : 1.0; + } if (fullscreen) { @@ -956,19 +983,90 @@ bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface) } #endif + +namespace +{ + TArray polyPixelBuffer; + GLuint polyTexture; + + int polyWidth = -1; + int polyHeight = -1; + int polyVSync = -1; +} + void I_PolyPresentInit() { + ogl_LoadFunctions(); + + glGenTextures(1, &polyTexture); + assert(polyTexture != 0); + + glEnable(GL_TEXTURE_RECTANGLE_ARB); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, polyTexture); + + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch) { - return nullptr; + static const int PIXEL_BYTES = 4; + + if (polyPixelBuffer.Size() == 0 || w != polyWidth || h != polyHeight) + { + polyPixelBuffer.Resize(w * h * PIXEL_BYTES); + + polyWidth = w; + polyHeight = h; + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0.0, w, h, 0.0, -1.0, 1.0); + + glViewport(0, 0, w, h); + } + + if (vsync != polyVSync) + { + const GLint value = vsync ? 1 : 0; + + [[NSOpenGLContext currentContext] setValues:&value + forParameter:NSOpenGLCPSwapInterval]; + } + + pitch = w * PIXEL_BYTES; + + return &polyPixelBuffer[0]; } void I_PolyPresentUnlock(int x, int y, int w, int h) { + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, &polyPixelBuffer[0]); + + glBegin(GL_QUADS); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glTexCoord2f(0.0f, 0.0f); + glVertex2f(0.0f, 0.0f); + glTexCoord2f(w, 0.0f); + glVertex2f(w, 0.0f); + glTexCoord2f(w, h); + glVertex2f(w, h); + glTexCoord2f(0.0f, h); + glVertex2f(0.0f, h); + glEnd(); + + glFlush(); + + [[NSOpenGLContext currentContext] flushBuffer]; } void I_PolyPresentDeinit() { + glBindTexture(GL_TEXTURE_2D, 0); + glDeleteTextures(1, &polyTexture); }