- 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 "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,8 +312,12 @@ NSOpenGLPixelFormat* CreatePixelFormat()
attributes[i++] = NSOpenGLPixelFormatAttribute(24);
attributes[i++] = NSOpenGLPFAStencilSize;
attributes[i++] = NSOpenGLPixelFormatAttribute(8);
if (profile == OpenGLProfile::Core)
{
attributes[i++] = NSOpenGLPFAOpenGLProfile;
attributes[i++] = NSOpenGLProfileVersion3_2Core;
}
if (!vid_autoswitch)
{
@ -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)
@ -602,10 +621,18 @@ void SystemBaseFrameBuffer::SetWindowedMode()
}
void SystemBaseFrameBuffer::SetMode(const bool fullscreen, const bool hiDPI)
{
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<uint8_t> 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);
}