- added support for softpoly backend on macOS

Grabbed most of code from old Cocoa backend with separate code path for software rendering
This commit is contained in:
alexey.lysiuk 2019-12-07 13:25:12 +02:00
parent 75248cffd0
commit e4587138bb

View file

@ -57,6 +57,7 @@
#include "gl/system/gl_framebuffer.h" #include "gl/system/gl_framebuffer.h"
#include "vulkan/system/vk_framebuffer.h" #include "vulkan/system/vk_framebuffer.h"
#include "rendering/polyrenderer/backend/poly_framebuffer.h"
@implementation NSWindow(ExitAppOnClose) @implementation NSWindow(ExitAppOnClose)
@ -293,7 +294,13 @@ CocoaWindow* CreateWindow(const NSUInteger styleMask)
return window; return window;
} }
NSOpenGLPixelFormat* CreatePixelFormat() enum class OpenGLProfile
{
Core,
Legacy
};
NSOpenGLPixelFormat* CreatePixelFormat(const OpenGLProfile profile)
{ {
NSOpenGLPixelFormatAttribute attributes[16]; NSOpenGLPixelFormatAttribute attributes[16];
size_t i = 0; size_t i = 0;
@ -305,8 +312,12 @@ NSOpenGLPixelFormat* CreatePixelFormat()
attributes[i++] = NSOpenGLPixelFormatAttribute(24); attributes[i++] = NSOpenGLPixelFormatAttribute(24);
attributes[i++] = NSOpenGLPFAStencilSize; attributes[i++] = NSOpenGLPFAStencilSize;
attributes[i++] = NSOpenGLPixelFormatAttribute(8); 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) if (!vid_autoswitch)
{ {
@ -315,12 +326,14 @@ NSOpenGLPixelFormat* CreatePixelFormat()
attributes[i] = NSOpenGLPixelFormatAttribute(0); attributes[i] = NSOpenGLPixelFormatAttribute(0);
assert(i < sizeof attributes / sizeof attributes[0]);
return [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; 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) if (nil == pixelFormat)
{ {
@ -364,13 +377,12 @@ public:
assert(ms_window == nil); assert(ms_window == nil);
ms_window = CreateWindow(STYLE_MASK_WINDOWED); ms_window = CreateWindow(STYLE_MASK_WINDOWED);
const NSRect contentRect = [ms_window contentRectForFrameRect:[ms_window frame]];
SystemBaseFrameBuffer *fb = nullptr; SystemBaseFrameBuffer *fb = nullptr;
#ifdef HAVE_VULKAN #ifdef HAVE_VULKAN
if (ms_isVulkanEnabled) if (ms_isVulkanEnabled)
{ {
const NSRect contentRect = [ms_window contentRectForFrameRect:[ms_window frame]];
NSView* vulkanView = [[VulkanCocoaView alloc] initWithFrame:contentRect]; NSView* vulkanView = [[VulkanCocoaView alloc] initWithFrame:contentRect];
vulkanView.wantsLayer = YES; vulkanView.wantsLayer = YES;
vulkanView.layer.backgroundColor = NSColor.blackColor.CGColor; vulkanView.layer.backgroundColor = NSColor.blackColor.CGColor;
@ -417,13 +429,20 @@ public:
{ {
ms_isVulkanEnabled = false; ms_isVulkanEnabled = false;
SetupOpenGLView(ms_window); SetupOpenGLView(ms_window, OpenGLProfile::Core);
} }
} }
else else
#endif #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) if (fb == nullptr)
@ -603,9 +622,17 @@ void SystemBaseFrameBuffer::SetWindowedMode()
void SystemBaseFrameBuffer::SetMode(const bool fullscreen, const bool hiDPI) void SystemBaseFrameBuffer::SetMode(const bool fullscreen, const bool hiDPI)
{ {
assert(m_window.screen != nil); if ([m_window.contentView isKindOfClass:[OpenGLCocoaView class]])
assert(m_window.contentView.layer != nil); {
[m_window.contentView layer].contentsScale = hiDPI ? m_window.screen.backingScaleFactor : 1.0; 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) if (fullscreen)
{ {
@ -956,19 +983,90 @@ bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface)
} }
#endif #endif
namespace
{
TArray<uint8_t> polyPixelBuffer;
GLuint polyTexture;
int polyWidth = -1;
int polyHeight = -1;
int polyVSync = -1;
}
void I_PolyPresentInit() 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) 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) 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() void I_PolyPresentDeinit()
{ {
glBindTexture(GL_TEXTURE_2D, 0);
glDeleteTextures(1, &polyTexture);
} }